@fluid-app/portal-sdk 0.1.127 → 0.1.129

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.
package/dist/index.d.cts CHANGED
@@ -1951,1880 +1951,1882 @@ declare function AppShell({
1951
1951
  children
1952
1952
  }: AppShellProps): React.JSX.Element;
1953
1953
  //#endregion
1954
- //#region src/entry/create-portal.d.ts
1954
+ //#region ../core/src/registries/property-schema-types.d.ts
1955
1955
  /**
1956
- * Configuration for `createPortal()`.
1957
- *
1958
- * Provides a single-call entry point that sets up the full provider hierarchy
1959
- * (auth, SDK, shell) with sensible defaults. Every field is optional.
1960
- *
1961
- * For full control, skip `createPortal()` and compose providers manually:
1962
- * ```tsx
1963
- * import { FluidAuthProvider, FluidProvider, RequireAuth, AppShell } from "@fluid-app/portal-sdk";
1964
- * ```
1956
+ * Tab configuration for organizing properties
1965
1957
  */
1966
- interface PortalConfig {
1967
- /** Custom page components keyed by navigation slug */
1968
- customPages?: Record<string, ComponentType<{
1969
- slug?: string;
1970
- params?: string;
1971
- }>>;
1972
- /** API client config overrides (merged with defaults) */
1973
- fluid?: Partial<FluidSDKConfig>;
1974
- /** Auth config overrides (merged with defaults) */
1975
- auth?: Partial<FluidAuthConfig>;
1976
- /** Root element ID. @default "root" */
1977
- rootId?: string;
1978
- /** AppShell props passthrough (basePath, sidebarHeader, etc.) */
1979
- shell?: Omit<AppShellProps, "customPages">;
1980
- /** Wrap AppShell with additional providers (inserted inside RequireAuth, below FluidProvider) */
1981
- providers?: ComponentType<{
1982
- children: ReactNode;
1983
- }>;
1984
- /** Disable StrictMode. @default false */
1985
- disableStrictMode?: boolean;
1958
+ interface TabConfig {
1959
+ /** Unique identifier for the tab */
1960
+ id: string;
1961
+ /** Display label for the tab */
1962
+ label: string;
1986
1963
  }
1987
1964
  /**
1988
- * Bootstrap a Fluid portal with a single function call.
1989
- *
1990
- * Sets up the full provider hierarchy (FluidAuthProvider → FluidProvider → RequireAuth → AppShell)
1991
- * and renders into the DOM.
1992
- *
1993
- * @example Minimal usage
1994
- * ```ts
1995
- * import { createPortal } from "@fluid-app/portal-sdk";
1996
- * import "./index.css";
1997
- *
1998
- * createPortal();
1999
- * ```
2000
- *
2001
- * @example With custom pages
2002
- * ```ts
2003
- * import { createPortal } from "@fluid-app/portal-sdk";
2004
- * import { customPages } from "./portal.config";
2005
- * import "./index.css";
2006
- *
2007
- * createPortal({ customPages });
2008
- * ```
2009
- *
2010
- * @example With overrides
2011
- * ```ts
2012
- * createPortal({
2013
- * customPages,
2014
- * fluid: { baseUrl: "https://my-api.example.com" },
2015
- * auth: { onAuthFailure: () => console.log("auth failed") },
2016
- * shell: { basePath: "/portal" },
2017
- * });
2018
- * ```
1965
+ * Property field type constant - single source of truth for field types.
1966
+ * Use PROPERTY_FIELD_TYPES.text instead of "text" for type-safe comparisons.
2019
1967
  */
2020
- declare function createPortal(config?: PortalConfig): void;
2021
- //#endregion
2022
- //#region src/config/defaults.d.ts
1968
+ declare const PROPERTY_FIELD_TYPES: {
1969
+ readonly text: "text";
1970
+ readonly textarea: "textarea";
1971
+ readonly number: "number";
1972
+ readonly boolean: "boolean";
1973
+ readonly select: "select";
1974
+ readonly color: "color";
1975
+ readonly range: "range";
1976
+ readonly dataSource: "dataSource";
1977
+ readonly resource: "resource";
1978
+ readonly image: "image";
1979
+ readonly alignment: "alignment";
1980
+ readonly slider: "slider";
1981
+ readonly colorPicker: "colorPicker";
1982
+ readonly sectionHeader: "sectionHeader";
1983
+ readonly separator: "separator";
1984
+ readonly buttonGroup: "buttonGroup";
1985
+ readonly colorSelect: "colorSelect";
1986
+ readonly sectionLayoutSelect: "sectionLayoutSelect";
1987
+ readonly background: "background";
1988
+ readonly contentPosition: "contentPosition";
1989
+ readonly textSizeSelect: "textSizeSelect";
1990
+ readonly cssUnit: "cssUnit";
1991
+ readonly fontPicker: "fontPicker";
1992
+ readonly stringArray: "stringArray";
1993
+ readonly borderRadius: "borderRadius";
1994
+ readonly screenPicker: "screenPicker";
1995
+ };
2023
1996
  /**
2024
- * Creates a FluidSDKConfig with sensible defaults.
2025
- *
2026
- * Default behavior:
2027
- * - baseUrl: reads from `VITE_API_URL` env var, falls back to `""` (same-origin relative)
2028
- * - Auth: relies on session cookies sent via `credentials: 'include'`
2029
- *
2030
- * Pass overrides to customize any field:
2031
- * ```ts
2032
- * const config = createDefaultFluidConfig({ baseUrl: "https://my-api.example.com" });
2033
- * ```
1997
+ * Union type of all property field types, derived from PROPERTY_FIELD_TYPES constant.
1998
+ * @see deriving-typeof-for-object-keys pattern
2034
1999
  */
2035
- declare function createDefaultFluidConfig(overrides?: Partial<FluidSDKConfig>): FluidSDKConfig;
2000
+ type PropertyFieldType = (typeof PROPERTY_FIELD_TYPES)[keyof typeof PROPERTY_FIELD_TYPES];
2036
2001
  /**
2037
- * Creates a FluidAuthConfig with sensible defaults.
2038
- *
2039
- * The SDK's FluidAuthProvider already applies defaults for all fields,
2040
- * so an empty config works out of the box. Use overrides to customize:
2041
- * ```ts
2042
- * const config = createDefaultAuthConfig({ onAuthFailure: () => navigate("/login") });
2043
- * ```
2002
+ * Runtime validation for property field types.
2003
+ * @param value - The value to check
2004
+ * @returns true if value is a valid PropertyFieldType
2044
2005
  */
2045
- declare function createDefaultAuthConfig(overrides?: Partial<FluidAuthConfig>): FluidAuthConfig;
2046
- //#endregion
2047
- //#region src/hooks/use-fluid-api.d.ts
2006
+ declare function isPropertyFieldType(value: string): value is PropertyFieldType;
2048
2007
  /**
2049
- * Hook to access the Fluid API client
2050
- *
2051
- * @example
2052
- * ```tsx
2053
- * function UserInfo() {
2054
- * const api = useFluidApi();
2055
- *
2056
- * const { data: user } = useQuery({
2057
- * queryKey: ["me"],
2058
- * queryFn: () => api.users.me(),
2059
- * });
2060
- *
2061
- * return <p>Hello, {user?.name}</p>;
2062
- * }
2063
- * ```
2008
+ * Base schema for a property field
2064
2009
  */
2065
- declare function useFluidApi(): FluidClient;
2066
- //#endregion
2067
- //#region src/hooks/use-fluid-profile.d.ts
2010
+ interface PropertyFieldSchema {
2011
+ /** Property key in the widget props */
2012
+ key: string;
2013
+ /** Display label for the field */
2014
+ label: string;
2015
+ /** Field type determines the input control */
2016
+ type: PropertyFieldType;
2017
+ /** Optional description/help text */
2018
+ description?: string;
2019
+ /** Optional default value */
2020
+ defaultValue?: unknown;
2021
+ /** Optional tab ID (must match a TabConfig id if widget has tabsConfig) */
2022
+ tab?: string;
2023
+ /** Optional group for organizing fields within a tab */
2024
+ group?: string;
2025
+ /**
2026
+ * @deprecated Use requiresKeyValue instead
2027
+ */
2028
+ requiresKeyToBeTrue?: string;
2029
+ /** Optional requires a specific key to have a specific value. Supports single condition or array (AND logic). */
2030
+ requiresKeyValue?: {
2031
+ key: string;
2032
+ value: unknown;
2033
+ } | Array<{
2034
+ key: string;
2035
+ value: unknown;
2036
+ }>;
2037
+ }
2068
2038
  /**
2069
- * Base query key for profile data.
2070
- * Kept for backwards compatibility — the runtime key used by the hook
2071
- * includes a company prefix via {@link useCompanyScopedQueryKey}.
2072
- *
2073
- * @deprecated Use {@link APP_DATA_QUERY_KEY} with `useFluidApp` instead.
2039
+ * Text field schema
2074
2040
  */
2075
- declare const PROFILE_QUERY_KEY: readonly ["fluid", "profile"];
2041
+ interface TextFieldSchema extends PropertyFieldSchema {
2042
+ type: "text";
2043
+ placeholder?: string;
2044
+ maxLength?: number;
2045
+ }
2076
2046
  /**
2077
- * Hook to fetch the portal profile (themes, navigation, screens).
2078
- *
2079
- * Internally fetches from the fluidos API (same data source as
2080
- * {@link useFluidApp}) and selects the `profile` slice, so no
2081
- * legacy `/api/rep_app/manifest` call is made.
2082
- *
2083
- * @deprecated Use `useFluidApp()` instead — it returns the full
2084
- * `RepAppData` including `profile`, `screens`, and more.
2085
- *
2086
- * @example
2087
- * ```tsx
2088
- * function Navigation() {
2089
- * const { data: profile, isLoading } = useFluidProfile();
2090
- *
2091
- * if (isLoading) return <Spinner />;
2092
- *
2093
- * return (
2094
- * <nav>
2095
- * {profile?.navigation.navigation_items.map(item => (
2096
- * <NavItem key={item.id} item={item} />
2097
- * ))}
2098
- * </nav>
2099
- * );
2100
- * }
2101
- * ```
2047
+ * Textarea field schema
2102
2048
  */
2103
- declare function useFluidProfile(): UseQueryResult<Profile>;
2104
- //#endregion
2105
- //#region src/hooks/use-fluid-app.d.ts
2049
+ interface TextareaFieldSchema extends PropertyFieldSchema {
2050
+ type: "textarea";
2051
+ placeholder?: string;
2052
+ rows?: number;
2053
+ maxLength?: number;
2054
+ }
2106
2055
  /**
2107
- * Base query key for full app data (fluidos endpoint).
2108
- * Kept for backwards compatibility — the runtime key used by the hook
2109
- * includes a company prefix via {@link useCompanyScopedQueryKey}.
2056
+ * Number field schema
2110
2057
  */
2111
- declare const APP_DATA_QUERY_KEY: readonly ["fluid", "app"];
2058
+ interface NumberFieldSchema extends PropertyFieldSchema {
2059
+ type: "number";
2060
+ min?: number;
2061
+ max?: number;
2062
+ step?: number;
2063
+ }
2112
2064
  /**
2113
- * Hook to fetch the full portal app data from the fluidos API.
2114
- *
2115
- * Returns a `RepAppData` object containing:
2116
- * - `screens` — all screen definitions with normalized component trees
2117
- * - `profile.themes` — fully-transformed ThemeDefinition[] (handles legacy + new formats)
2118
- * - `profile.activeThemeId` — the currently active theme ID
2119
- * - `profile.navigation.navigation_items` — sorted, recursive navigation tree
2120
- *
2121
- * Uses IndexedDB persistence so subsequent page loads hydrate instantly
2122
- * from cache while revalidating in the background. The raw API response
2123
- * (plain JSON) is cached; Color objects are recreated from cache via
2124
- * `select` on every restore — this is fast (CPU only, no network).
2125
- *
2126
- * @example
2127
- * ```tsx
2128
- * function App() {
2129
- * const { data: appData, isLoading } = useFluidApp();
2130
- *
2131
- * if (isLoading) return <Spinner />;
2132
- *
2133
- * return (
2134
- * <AppShell
2135
- * appData={appData}
2136
- * navigation={appData.profile.navigation.navigation_items}
2137
- * />
2138
- * );
2139
- * }
2140
- * ```
2065
+ * Boolean field schema
2141
2066
  */
2142
- declare function useFluidApp(options?: {
2143
- enabled?: boolean;
2144
- }): UseQueryResult<RepAppData>;
2145
- //#endregion
2146
- //#region src/hooks/use-fluid-permissions.d.ts
2067
+ interface BooleanFieldSchema extends PropertyFieldSchema {
2068
+ type: "boolean";
2069
+ }
2147
2070
  /**
2148
- * Base query key for permissions data.
2149
- * Kept for backwards compatibility the runtime key used by the hook
2150
- * includes a company prefix via {@link useCompanyScopedQueryKey}.
2071
+ * Select field schema with type-safe option values.
2072
+ * Uses StrictOmit to ensure "defaultValue" key exists on PropertyFieldSchema.
2151
2073
  */
2152
- declare const PERMISSIONS_QUERY_KEY: readonly ["fluid", "permissions"];
2074
+ interface SelectFieldSchema<T extends string | number = string | number> extends StrictOmit<PropertyFieldSchema, "defaultValue"> {
2075
+ type: "select";
2076
+ options: Array<{
2077
+ label: string;
2078
+ value: T;
2079
+ }>;
2080
+ defaultValue?: T;
2081
+ }
2153
2082
  /**
2154
- * Result of useFluidPermissions hook
2083
+ * Color field schema
2155
2084
  */
2156
- interface UseFluidPermissionsResult {
2157
- /** Raw permissions query result */
2158
- query: UseQueryResult<UserPermissions>;
2159
- /** Permissions data (alias for query.data) */
2160
- permissions: UserPermissions | undefined;
2161
- /** Check if user has a specific permission */
2162
- can: (resource: string, action?: PermissionAction) => boolean;
2163
- /** Check if user is a super admin */
2164
- isSuperAdmin: boolean;
2085
+ interface ColorFieldSchema extends PropertyFieldSchema {
2086
+ type: "color";
2165
2087
  }
2166
2088
  /**
2167
- * Hook to fetch and check user permissions
2168
- *
2169
- * @example
2170
- * ```tsx
2171
- * function TeamSettings() {
2172
- * const { can, isSuperAdmin } = useFluidPermissions();
2173
- *
2174
- * if (!can("team", "manage")) {
2175
- * return <AccessDenied />;
2176
- * }
2177
- *
2178
- * return <TeamSettingsForm canDelete={can("team", "delete")} />;
2179
- * }
2180
- * ```
2089
+ * Range slider field schema
2181
2090
  */
2182
- declare function useFluidPermissions(): UseFluidPermissionsResult;
2183
- //#endregion
2184
- //#region src/hooks/use-fluid-theme.d.ts
2091
+ interface RangeFieldSchema extends PropertyFieldSchema {
2092
+ type: "range";
2093
+ min: number;
2094
+ max: number;
2095
+ step?: number;
2096
+ }
2185
2097
  /**
2186
- * Result of useFluidTheme hook
2098
+ * Data source field schema for configuring widget data sources
2187
2099
  */
2188
- interface UseFluidThemeResult {
2189
- /** Currently active theme */
2190
- currentTheme: ThemeDefinition | null;
2191
- /** Switch to a different theme */
2192
- setTheme: (theme: ThemeDefinition) => void;
2193
- /** Switch between light and dark mode */
2194
- setThemeMode: (mode: "light" | "dark") => void;
2195
- /** Current theme mode (convenience accessor) */
2196
- mode: "light" | "dark" | undefined;
2100
+ interface DataSourceFieldSchema extends PropertyFieldSchema {
2101
+ type: "dataSource";
2197
2102
  }
2198
2103
  /**
2199
- * Hook to access and control theme settings
2200
- *
2201
- * @example
2202
- * ```tsx
2203
- * function ThemeSwitcher({ themes }: { themes: ThemeDefinition[] }) {
2204
- * const { currentTheme, setTheme, setThemeMode, mode } = useFluidTheme();
2205
- *
2206
- * return (
2207
- * <div>
2208
- * <select
2209
- * value={currentTheme?.name}
2210
- * onChange={(e) => {
2211
- * const theme = themes.find(t => t.name === e.target.value);
2212
- * if (theme) setTheme(theme);
2213
- * }}
2214
- * >
2215
- * {themes.map(theme => (
2216
- * <option key={theme.name} value={theme.name}>
2217
- * {theme.name}
2218
- * </option>
2219
- * ))}
2220
- * </select>
2221
- *
2222
- * <button onClick={() => setThemeMode(mode === "dark" ? "light" : "dark")}>
2223
- * Toggle {mode === "dark" ? "Light" : "Dark"} Mode
2224
- * </button>
2225
- * </div>
2226
- * );
2227
- * }
2228
- * ```
2104
+ * Resource field schema for selecting a single resource from the selection modal
2229
2105
  */
2230
- declare function useFluidTheme(): UseFluidThemeResult;
2231
- //#endregion
2232
- //#region src/hooks/use-current-rep.d.ts
2106
+ interface ResourceFieldSchema extends PropertyFieldSchema {
2107
+ type: "resource";
2108
+ /** Optional filter to specific shareable types */
2109
+ allowedTypes?: string[];
2110
+ }
2233
2111
  /**
2234
- * Base query key for current rep data.
2235
- * Kept for backwards compatibility — the runtime key used by the hook
2236
- * includes a company prefix via {@link useCompanyScopedQueryKey}.
2112
+ * Image field schema for selecting a single image from the image picker
2237
2113
  */
2238
- declare const CURRENT_REP_QUERY_KEY: readonly ["fluid", "currentRep"];
2114
+ interface ImageFieldSchema extends PropertyFieldSchema {
2115
+ type: "image";
2116
+ }
2239
2117
  /**
2240
- * Hook to fetch the currently authenticated rep's profile
2241
- *
2242
- * @example
2243
- * ```tsx
2244
- * function RepHeader() {
2245
- * const { data: rep, isLoading } = useCurrentRep();
2246
- *
2247
- * if (isLoading) return <Skeleton />;
2248
- *
2249
- * return (
2250
- * <div>
2251
- * <Avatar src={rep?.avatar_url} />
2252
- * <span>{rep?.first_name} {rep?.last_name}</span>
2253
- * </div>
2254
- * );
2255
- * }
2256
- * ```
2118
+ * Alignment field schema
2257
2119
  */
2258
- declare function useCurrentRep(): UseQueryResult<Rep>;
2259
- //#endregion
2260
- //#region src/hooks/use-current-user.d.ts
2120
+ interface AlignmentFieldSchema extends PropertyFieldSchema {
2121
+ type: "alignment";
2122
+ options: {
2123
+ verticalEnabled: boolean;
2124
+ horizontalEnabled: boolean;
2125
+ };
2126
+ defaultValue?: AlignOptions;
2127
+ }
2261
2128
  /**
2262
- * Base query key for current user data.
2263
- * Kept for backwards compatibility — the runtime key used by the hook
2264
- * includes a company prefix via {@link useCompanyScopedQueryKey}.
2129
+ * Slider field schema with optional unit suffix (e.g., "rem", "px")
2265
2130
  */
2266
- declare const CURRENT_USER_QUERY_KEY: readonly ["fluid", "currentUser"];
2131
+ interface SliderFieldSchema extends PropertyFieldSchema {
2132
+ type: "slider";
2133
+ min: number;
2134
+ max: number;
2135
+ step?: number;
2136
+ unit?: string;
2137
+ }
2267
2138
  /**
2268
- * Hook to fetch the currently authenticated user's full profile.
2269
- * Returns company, country, and other fields from GET /api/me.
2270
- *
2271
- * @example
2272
- * ```tsx
2273
- * function ShopPage() {
2274
- * const { data: user, isLoading } = useCurrentUser();
2275
- * const subdomain = user?.company?.subdomain;
2276
- * const countryIso = user?.country?.iso ?? "US";
2277
- * // ...
2278
- * }
2279
- * ```
2139
+ * Color picker field schema with optional swatches
2280
2140
  */
2281
- declare function useCurrentUser(): UseQueryResult<UserMe>;
2282
- //#endregion
2283
- //#region src/hooks/use-fluid-auth.d.ts
2141
+ interface ColorPickerFieldSchema extends PropertyFieldSchema {
2142
+ type: "colorPicker";
2143
+ swatches?: string[];
2144
+ }
2284
2145
  /**
2285
- * Hook to access authentication state and utilities.
2286
- *
2287
- * Must be used within a `FluidAuthProvider`.
2288
- *
2289
- * @returns Authentication context with user info, loading state, and utilities
2290
- * @throws Error if used outside FluidAuthProvider
2291
- *
2292
- * @example
2293
- * ```tsx
2294
- * function UserProfile() {
2295
- * const { isAuthenticated, isLoading, user, clearAuth } = useFluidAuth();
2296
- *
2297
- * if (isLoading) {
2298
- * return <Spinner />;
2299
- * }
2300
- *
2301
- * if (!isAuthenticated) {
2302
- * return <p>Please log in</p>;
2303
- * }
2304
- *
2305
- * return (
2306
- * <div>
2307
- * <p>Welcome, {user.full_name}!</p>
2308
- * <button onClick={clearAuth}>Log out</button>
2309
- * </div>
2310
- * );
2311
- * }
2312
- * ```
2146
+ * Section header field schema for visual grouping
2313
2147
  */
2314
- declare function useFluidAuth(): FluidAuthContextValue;
2315
- //#endregion
2316
- //#region src/hooks/use-user-type.d.ts
2317
- interface UseUserTypeResult {
2318
- userType: UserType | null;
2319
- isCustomer: boolean;
2320
- isRep: boolean;
2321
- isAdmin: boolean;
2148
+ interface SectionHeaderFieldSchema extends PropertyFieldSchema {
2149
+ type: "sectionHeader";
2150
+ subtitle?: string;
2322
2151
  }
2323
2152
  /**
2324
- * Convenience hook for user-type checks in the portal SDK.
2153
+ * Separator field schema for visual separation
2325
2154
  */
2326
- declare function useUserType(): UseUserTypeResult;
2327
- //#endregion
2328
- //#region src/hooks/query-keys.d.ts
2155
+ interface SeparatorFieldSchema extends PropertyFieldSchema {
2156
+ type: "separator";
2157
+ }
2329
2158
  /**
2330
- * Create a company-scoped query key by prepending ["company", companyId].
2331
- *
2332
- * @param companyId - The company ID from the JWT payload
2333
- * @param baseKey - The base query key segments (e.g. ["fluid", "profile"])
2334
- * @returns A tuple like ["company", 42, "fluid", "profile"]
2335
- *
2336
- * @example
2337
- * ```ts
2338
- * const key = createCompanyQueryKey(42, "fluid", "profile");
2339
- * // => ["company", 42, "fluid", "profile"]
2340
- * ```
2159
+ * Button group field schema.
2160
+ * Uses StrictOmit to ensure "defaultValue" key exists on PropertyFieldSchema.
2341
2161
  */
2342
- declare function createCompanyQueryKey(companyId: number, ...baseKey: readonly string[]): readonly ["company", number, ...string[]];
2343
- /**
2344
- * Hook that returns a `scopeKey` function bound to the current company ID
2345
- * from the auth context. If the user is not authenticated or has no
2346
- * company_id, the base key is returned unscoped (graceful degradation).
2347
- *
2348
- * @example
2349
- * ```tsx
2350
- * function MyComponent() {
2351
- * const { scopeKey } = useCompanyScopedQueryKey();
2352
- * const queryKey = scopeKey(PROFILE_QUERY_KEY);
2353
- * // => ["company", 42, "fluid", "profile"] (when authenticated)
2354
- * // => ["fluid", "profile"] (fallback)
2355
- * }
2356
- * ```
2357
- */
2358
- declare function useCompanyScopedQueryKey(): {
2359
- readonly companyId: number | undefined;
2360
- readonly scopeKey: <T extends readonly string[]>(baseKey: T) => readonly (string | number)[];
2361
- };
2362
- //#endregion
2363
- //#region src/hooks/use-logout.d.ts
2364
- interface UseLogoutOptions {
2365
- /** URL to redirect to after logout. Triggers a full page navigation. */
2366
- redirectUrl?: string;
2367
- /** Callback invoked after all state is cleared. Ignored when `redirectUrl` is set. */
2368
- onLogout?: () => void;
2162
+ interface ButtonGroupFieldSchema<T extends string | number = string | number> extends StrictOmit<PropertyFieldSchema, "defaultValue"> {
2163
+ type: "buttonGroup";
2164
+ options: Array<{
2165
+ label?: string;
2166
+ icon?: LucideIcon;
2167
+ value: T;
2168
+ }>;
2169
+ defaultValue?: T;
2369
2170
  }
2370
2171
  /**
2371
- * Hook that returns a `logout` function which clears the server session
2372
- * via `DELETE /logout` and all cached/persisted client state.
2373
- *
2374
- * @example
2375
- * ```tsx
2376
- * const logout = useLogout({ redirectUrl: "/login" });
2377
- * <button onClick={logout}>Log out</button>
2378
- * ```
2379
- *
2380
- * @example
2381
- * ```tsx
2382
- * const logout = useLogout({
2383
- * onLogout: () => navigate("/signed-out"),
2384
- * });
2385
- * ```
2172
+ * Color select field schema
2386
2173
  */
2387
- declare function useLogout({
2388
- redirectUrl,
2389
- onLogout
2390
- }?: UseLogoutOptions): () => Promise<void>;
2391
- //#endregion
2392
- //#region src/hooks/use-company-switch.d.ts
2393
- interface UseCompanySwitchOptions {}
2174
+ interface ColorSelectFieldSchema extends PropertyFieldSchema {
2175
+ type: "colorSelect";
2176
+ defaultValue?: ColorOptions;
2177
+ excludeColors?: ColorOptions[];
2178
+ }
2394
2179
  /**
2395
- * Hook that handles company switching for the portal.
2396
- *
2397
- * Calls PUT /api/authentication/company/{id}/switch, clears the TanStack
2398
- * Query cache and IndexedDB persisted cache, then reloads the page so all
2399
- * queries re-fetch with the new company context.
2400
- *
2401
- * The server updates the session cookie automatically via the switch
2402
- * endpoint response; no client-side token storage is needed.
2180
+ * Section layout select field schema for visual masonry layout selector
2403
2181
  */
2404
- declare function useCompanySwitch(_options?: UseCompanySwitchOptions): {
2405
- switchCompany: (companyId: number) => void;
2406
- isPending: boolean;
2407
- isError: boolean;
2408
- error: Error | null;
2409
- };
2410
- //#endregion
2411
- //#region src/hooks/hook-types.d.ts
2182
+ interface SectionLayoutSelectFieldSchema extends PropertyFieldSchema {
2183
+ type: "sectionLayoutSelect";
2184
+ defaultValue?: SectionLayoutType;
2185
+ }
2412
2186
  /**
2413
- * Hook type utilities and type predicates.
2414
- *
2415
- * This module provides:
2416
- * - Generic hook result types with default type parameters
2417
- * - Type predicates for query state narrowing
2418
- * - Reusable patterns for type-safe property access in hooks
2419
- *
2420
- * Following generics best practices:
2421
- * - generics-default-type-parameters: Default E to Error for common case
2422
- * - generics-type-predicates: Type predicates for result state narrowing
2423
- * - generics-constrain-type-parameters: K extends keyof T for property access
2187
+ * Background field combines resource selection and color properties.
2188
+ * Uses StrictOmit to exclude conflicting "type" discriminant from parents.
2424
2189
  */
2190
+ interface BackgroundFieldSchema extends StrictOmit<ResourceFieldSchema, "type">, StrictOmit<ColorFieldSchema, "type"> {
2191
+ type: "background";
2192
+ }
2425
2193
  /**
2426
- * Base result type for query hooks with default error type.
2427
- * Uses default type parameter for E (generics-default-type-parameters rule).
2428
- *
2429
- * @typeParam T - The data type
2430
- * @typeParam E - The error type (defaults to Error)
2431
- *
2432
- * @example
2433
- * // Error type defaults to Error
2434
- * type UsersResult = QueryResult<User[]>;
2435
- *
2436
- * // Can override when needed
2437
- * type CustomResult = QueryResult<User[], ApiError>;
2194
+ * Content position field schema for 3x3 grid position picker
2438
2195
  */
2439
- interface QueryResult<T, E = Error> {
2440
- readonly data: T;
2441
- readonly isLoading: boolean;
2442
- readonly isError: boolean;
2443
- readonly error?: E | undefined;
2196
+ interface ContentPositionFieldSchema extends PropertyFieldSchema {
2197
+ type: "contentPosition";
2198
+ defaultValue?: string;
2444
2199
  }
2445
2200
  /**
2446
- * Result type for hooks that may not have data yet.
2447
- * Extends QueryResult with nullable data.
2448
- *
2449
- * @typeParam T - The data type
2450
- * @typeParam E - The error type (defaults to Error)
2201
+ * Text size select field schema for visual font size selector
2451
2202
  */
2452
- interface QueryResultNullable<T, E = Error> {
2453
- readonly data: T | null | undefined;
2454
- readonly isLoading: boolean;
2455
- readonly isError: boolean;
2456
- readonly error?: E | undefined;
2203
+ interface TextSizeSelectFieldSchema extends PropertyFieldSchema {
2204
+ type: "textSizeSelect";
2205
+ defaultValue?: FontSizeOptions;
2457
2206
  }
2458
2207
  /**
2459
- * Result type for list/collection hooks with aggregates.
2460
- *
2461
- * @typeParam T - The item type in the array
2462
- * @typeParam E - The error type (defaults to Error)
2208
+ * CSS unit type for height/width fields
2463
2209
  */
2464
- interface ListQueryResult<T, E = Error> extends QueryResult<T[], E> {
2465
- readonly totalCount: number;
2466
- }
2210
+ type CssUnit = "px" | "rem" | "vh" | "%";
2467
2211
  /**
2468
- * Result type for list hooks with value aggregation (e.g., deals with total value).
2469
- *
2470
- * @typeParam T - The item type in the array
2471
- * @typeParam E - The error type (defaults to Error)
2212
+ * CSS unit field schema for numeric values with selectable units (px, rem, vh, %)
2472
2213
  */
2473
- interface ValueListQueryResult<T, E = Error> extends ListQueryResult<T, E> {
2474
- readonly totalValue: number;
2214
+ interface CssUnitFieldSchema extends PropertyFieldSchema {
2215
+ type: "cssUnit";
2216
+ minByUnit?: Partial<Record<CssUnit, number>>;
2217
+ maxByUnit?: Partial<Record<CssUnit, number>>;
2218
+ stepByUnit?: Partial<Record<CssUnit, number>>;
2219
+ allowedUnits?: CssUnit[];
2220
+ defaultUnit?: CssUnit;
2475
2221
  }
2476
2222
  /**
2477
- * Type predicate to check if a query result has successfully loaded data.
2478
- * Narrows the data type from T | null | undefined to T.
2479
- *
2480
- * @example
2481
- * const result = useContact(id);
2482
- * if (hasData(result)) {
2483
- * // TypeScript knows result.data is Contact, not Contact | null
2484
- * console.log(result.data.name);
2485
- * }
2223
+ * Font picker field schema for Google Fonts selection
2486
2224
  */
2487
- declare function hasData<T, E = Error>(result: QueryResultNullable<T, E>): result is QueryResultNullable<T, E> & {
2488
- readonly data: T;
2489
- };
2225
+ interface FontPickerFieldSchema extends PropertyFieldSchema {
2226
+ type: "fontPicker";
2227
+ placeholder?: string;
2228
+ }
2490
2229
  /**
2491
- * Type predicate to check if a query result is in loading state.
2492
- * Useful for conditional rendering.
2493
- *
2494
- * @example
2495
- * if (isLoading(result)) {
2496
- * return <Spinner />;
2497
- * }
2230
+ * String array field schema for managing lists of text items
2498
2231
  */
2499
- declare function isLoading<T, E = Error>(result: QueryResult<T, E> | QueryResultNullable<T, E>): boolean;
2232
+ interface StringArrayFieldSchema extends PropertyFieldSchema {
2233
+ type: "stringArray";
2234
+ placeholder?: string;
2235
+ defaultValue?: string[];
2236
+ }
2500
2237
  /**
2501
- * Type predicate to check if a query result has an error.
2502
- * Narrows to include the error property.
2503
- *
2504
- * @example
2505
- * if (isErrorResult(result)) {
2506
- * console.error(result.error); // error is E, not undefined
2507
- * }
2238
+ * Border radius composite field schema for controlling 4 corners with a single field.
2239
+ * Maps to 4 individual widget prop keys (topLeft, topRight, bottomLeft, bottomRight).
2508
2240
  */
2509
- declare function isErrorResult<T, E = Error>(result: QueryResult<T, E> | QueryResultNullable<T, E>): result is (QueryResult<T, E> | QueryResultNullable<T, E>) & {
2510
- readonly isError: true;
2511
- readonly error: E;
2512
- };
2241
+ interface BorderRadiusFieldSchema extends PropertyFieldSchema {
2242
+ type: "borderRadius";
2243
+ keys: {
2244
+ topLeft: string;
2245
+ topRight: string;
2246
+ bottomLeft: string;
2247
+ bottomRight: string;
2248
+ };
2249
+ defaultValue?: BorderRadiusOptions;
2250
+ }
2513
2251
  /**
2514
- * Type predicate to check if a query result is in idle state (not loading, no error, has data).
2515
- *
2516
- * @example
2517
- * if (isIdle(result)) {
2518
- * // Safe to access and render data
2519
- * }
2252
+ * Screen picker field schema for selecting a portal screen (navigation, system, or available)
2520
2253
  */
2521
- declare function isIdle<T, E = Error>(result: QueryResult<T, E> | QueryResultNullable<T, E>): boolean;
2254
+ interface ScreenPickerFieldSchema extends PropertyFieldSchema {
2255
+ type: "screenPicker";
2256
+ /** Whether to include system navigation items in the picker */
2257
+ includeSystemItems?: boolean;
2258
+ }
2522
2259
  /**
2523
- * Type-safe property selector for hook results.
2524
- * Uses K extends keyof T constraint (generics-function-constraints rule).
2525
- *
2526
- * @typeParam T - The data object type
2527
- * @typeParam K - Key of T (constrained to actual keys)
2528
- *
2529
- * @example
2530
- * const users = [{ name: "Alice", age: 30 }];
2531
- * const names = selectProperty(users, "name"); // string[]
2532
- * const ages = selectProperty(users, "age"); // number[]
2533
- * selectProperty(users, "invalid"); // Error: "invalid" not in "name" | "age"
2260
+ * Union of all field schema types
2534
2261
  */
2535
- declare function selectProperty<T, K extends keyof T>(items: readonly T[], key: K): T[K][];
2262
+ type PropertyField = TextFieldSchema | TextareaFieldSchema | NumberFieldSchema | BooleanFieldSchema | SelectFieldSchema<string | number> | ColorFieldSchema | RangeFieldSchema | DataSourceFieldSchema | ResourceFieldSchema | ImageFieldSchema | AlignmentFieldSchema | SliderFieldSchema | ColorPickerFieldSchema | SectionHeaderFieldSchema | SeparatorFieldSchema | ButtonGroupFieldSchema<string | number> | ColorSelectFieldSchema | SectionLayoutSelectFieldSchema | BackgroundFieldSchema | ContentPositionFieldSchema | TextSizeSelectFieldSchema | CssUnitFieldSchema | FontPickerFieldSchema | StringArrayFieldSchema | BorderRadiusFieldSchema | ScreenPickerFieldSchema;
2536
2263
  /**
2537
- * Type-safe property getter for a single item.
2538
- * Returns undefined if item is null/undefined.
2539
- *
2540
- * @typeParam T - The data object type
2541
- * @typeParam K - Key of T (constrained to actual keys)
2264
+ * Schema for per-item configuration in custom data sources.
2265
+ * Widgets can define this to allow users to configure widget-specific
2266
+ * settings for each selected item (e.g., title, description, button).
2542
2267
  */
2543
- declare function getProperty<T, K extends keyof T>(item: T | null | undefined, key: K): T[K] | undefined;
2268
+ interface ItemConfigSchema {
2269
+ /** Fields available for per-item configuration */
2270
+ fields: PropertyField[];
2271
+ /** Optional description shown at top of item config panel */
2272
+ description?: string;
2273
+ }
2544
2274
  /**
2545
- * Generic type for hooks that fetch a single resource by ID.
2546
- * Useful for creating consistent API across different resource types.
2547
- *
2548
- * @typeParam T - The resource type
2549
- * @typeParam E - The error type (defaults to Error)
2275
+ * Schema for a widget's editable properties
2550
2276
  */
2551
- type UseSingleResourceHook<T, E = Error> = (id: string) => QueryResultNullable<T, E>;
2552
- /**
2553
- * Generic type for hooks that fetch a list of resources with optional params.
2554
- * Uses generics-default-type-parameters for the params type.
2555
- *
2556
- * @typeParam T - The item type
2557
- * @typeParam P - The params type (defaults to empty object)
2558
- * @typeParam E - The error type (defaults to Error)
2559
- */
2560
- type UseListResourceHook<T, P extends Record<string, unknown> = Record<string, never>, E = Error> = (params?: P) => ListQueryResult<T, E>;
2561
- /**
2562
- * Transforms a nullable result to a non-nullable one if data exists.
2563
- * Useful when you've already checked hasData().
2564
- */
2565
- type WithData<R extends QueryResultNullable<unknown>> = R extends QueryResultNullable<infer T, infer E> ? QueryResultNullable<T, E> & {
2566
- readonly data: T;
2567
- } : never;
2568
- /**
2569
- * Activity slug constants as a const object.
2570
- * Derive the ActivitySlug type from this single source of truth.
2571
- */
2572
- declare const ACTIVITY_SLUGS: {
2573
- readonly abandonedCart: "abandoned_cart";
2574
- readonly announcements: "announcements";
2575
- readonly cartItemsAdded: "cart_items_added";
2576
- readonly commentReply: "comment_reply";
2577
- readonly directMessage: "direct_message";
2578
- readonly fantasyPoint: "fantasy_point";
2579
- readonly newLead: "new_lead";
2580
- readonly orderPlaced: "order_placed";
2581
- readonly pageViews: "page_views";
2582
- readonly pageViewsContact: "page_views_contact";
2583
- readonly tasks: "tasks";
2584
- readonly upcomingEvent: "upcoming_event";
2585
- readonly video: "video";
2586
- readonly videoComplete: "video_complete";
2587
- readonly videoCompleteContact: "video_complete_contact";
2588
- readonly videoContact: "video_contact";
2589
- readonly messageReceived: "message_received";
2590
- readonly messageSent: "message_sent";
2591
- readonly newCartItemsAdded: "new_cart_items_added";
2592
- readonly smartLinkClicked: "smart_link_clicked";
2593
- readonly reviewLeft: "review_left";
2594
- };
2595
- /** Activity slug union type derived from ACTIVITY_SLUGS constant. */
2596
- type ActivitySlug = (typeof ACTIVITY_SLUGS)[keyof typeof ACTIVITY_SLUGS];
2597
- /** Type predicate to check if a string is a valid ActivitySlug. */
2598
- declare function isActivitySlug(value: string): value is ActivitySlug;
2599
- /** Transformed activity for display. */
2600
- interface Activity {
2601
- readonly id: number;
2602
- readonly userName: string;
2603
- readonly avatarUrl: string | null;
2604
- readonly activityType: string;
2605
- readonly targetName: string;
2606
- readonly timestamp: string;
2607
- readonly slug: ActivitySlug;
2608
- }
2609
- /** Description/rich text metadata for a calendar event. */
2610
- interface CalendarEventDescription {
2611
- readonly id?: number | null;
2612
- readonly name?: string | null;
2613
- readonly body?: string | null;
2614
- readonly record_type?: string | null;
2615
- readonly record_id?: number | null;
2616
- readonly created_at?: string | null;
2617
- readonly updated_at?: string | null;
2618
- readonly locale?: string | null;
2619
- }
2620
- /** Calendar event data from the API. */
2621
- interface CalendarEvent {
2622
- readonly id: number;
2623
- readonly title: string;
2624
- readonly description?: CalendarEventDescription | null;
2625
- readonly color?: string | null;
2626
- readonly url?: string | null;
2627
- readonly start: string;
2628
- readonly end: string;
2629
- readonly active?: boolean | null;
2630
- readonly time_zone?: string | null;
2631
- readonly status?: string | null;
2632
- readonly image_url?: string | null;
2633
- readonly images?: readonly unknown[] | null;
2634
- readonly venue?: string | null;
2635
- readonly countries?: readonly string[] | null;
2636
- readonly hasTomorrow?: boolean | null;
2637
- readonly hasYesterday?: boolean | null;
2638
- readonly isAllDay?: boolean;
2639
- }
2640
- /** Catch up suggestion data from the API. */
2641
- interface CatchUp {
2642
- readonly id: number;
2643
- readonly suggestion_title: string;
2644
- }
2645
- /** MySite data returned by the hook. */
2646
- interface MySiteData {
2647
- readonly url: string | null;
2648
- readonly views: number;
2649
- readonly leads: number;
2650
- readonly userName: string;
2651
- }
2652
- /** Transformed todo for display. */
2653
- interface Todo {
2654
- readonly id: number;
2655
- readonly body: string;
2656
- readonly dueAt: string | null;
2657
- readonly completedAt: string | null;
2658
- readonly createdAt: string;
2659
- readonly contactName: string | null;
2277
+ interface WidgetPropertySchema {
2278
+ /** Widget type this schema applies to */
2279
+ widgetType: WidgetType;
2280
+ /** Display name for the widget */
2281
+ displayName: string;
2282
+ /** Optional tab configuration - if present, tabs are enabled */
2283
+ tabsConfig?: TabConfig[];
2284
+ /** Editable property fields */
2285
+ fields: PropertyField[];
2286
+ /** Optional custom validator function */
2287
+ validate?: (props: Record<string, unknown>) => string | null;
2288
+ /** Props that can be populated from data sources */
2289
+ dataSourceTargetProps?: string[];
2290
+ /** Optional schema for per-item configurations in custom data sources */
2291
+ itemConfigSchema?: ItemConfigSchema;
2660
2292
  }
2661
2293
  //#endregion
2662
- //#region src/hooks/use-calendar-events.d.ts
2663
- /**
2664
- * Result type for useCalendarEvents hook.
2665
- * Uses QueryResult<CalendarEvent[]> with default Error type.
2666
- */
2667
- type UseCalendarEventsResult = QueryResult<CalendarEvent[]>;
2668
- /**
2669
- * Hook to fetch calendar events.
2670
- * This is a stub implementation - override with your own data fetching logic.
2671
- */
2672
- declare function useCalendarEvents(): UseCalendarEventsResult;
2673
- //#endregion
2674
- //#region src/hooks/use-todos.d.ts
2675
- /**
2676
- * Result type for useTodos hook.
2677
- * Uses QueryResult<Todo[]> with default Error type.
2678
- */
2679
- type UseTodosResult = QueryResult<Todo[]>;
2680
- /**
2681
- * Hook to fetch todo items.
2682
- * This is a stub implementation - override with your own data fetching logic.
2683
- */
2684
- declare function useTodos(): UseTodosResult;
2685
- //#endregion
2686
- //#region src/hooks/use-activities.d.ts
2687
- /**
2688
- * Result type for useActivities hook.
2689
- * Uses QueryResult generic with Activity[] and default Error type.
2690
- */
2691
- type UseActivitiesResult = QueryResult<Activity[]>;
2294
+ //#region ../core/src/registries/field-helpers.d.ts
2692
2295
  /**
2693
- * Hook to fetch recent activities.
2694
- * This is a stub implementation - override with your own data fetching logic.
2296
+ * Gap value mapping - use `as const satisfies` for compile-time validation
2297
+ * with literal type preservation.
2695
2298
  */
2696
- declare function useActivities(): UseActivitiesResult;
2299
+ declare const gapValues: {
2300
+ readonly none: 0;
2301
+ readonly xs: 1;
2302
+ readonly sm: 2;
2303
+ readonly md: 4;
2304
+ readonly lg: 6;
2305
+ readonly xl: 8;
2306
+ };
2697
2307
  //#endregion
2698
- //#region src/hooks/use-catchups.d.ts
2699
- /**
2700
- * Result type for useCatchUps hook.
2701
- * Uses QueryResult<CatchUp[]> with default Error type.
2702
- */
2703
- type UseCatchUpsResult = QueryResult<CatchUp[]>;
2308
+ //#region ../core/src/registries/container-types.d.ts
2704
2309
  /**
2705
- * Hook to fetch catch up items.
2706
- * This is a stub implementation - override with your own data fetching logic.
2310
+ * Interface for container widget behavior.
2311
+ * Container widgets can hold and manage child widgets.
2312
+ * Note: Children can be null for sparse arrays (e.g., grid layouts with empty cells)
2707
2313
  */
2708
- declare function useCatchUps(): UseCatchUpsResult;
2314
+ interface ContainerWidgetBehavior {
2315
+ /** Identifies this widget type as a container */
2316
+ isContainer: true;
2317
+ /** Gets children from the widget's props */
2318
+ getChildren: (props: Record<string, unknown>) => (WidgetSchema | null)[];
2319
+ /** Creates new props with updated children */
2320
+ setChildren: (props: Record<string, unknown>, children: (WidgetSchema | null)[]) => Record<string, unknown>;
2321
+ /** Optional: Check if this container accepts a specific widget type */
2322
+ canAcceptChild?: (childType: string) => boolean;
2323
+ }
2709
2324
  //#endregion
2710
- //#region src/hooks/use-mysite.d.ts
2711
- /**
2712
- * Result type for useMySite hook.
2713
- * Uses QueryResultNullable since MySite data may not be available.
2714
- */
2715
- type UseMySiteResult = QueryResultNullable<MySiteData>;
2325
+ //#region ../core/src/registries/widget-manifest.d.ts
2716
2326
  /**
2717
- * Hook to fetch MySite data.
2718
- * This is a stub implementation - override with your own data fetching logic.
2327
+ * The manifest a plugin author provides to register a custom widget.
2328
+ * Required fields ensure the widget works in both builder and SDK contexts.
2329
+ * Optional fields enable advanced behavior (containers, min SDK version).
2719
2330
  */
2720
- declare function useMySite(): UseMySiteResult;
2331
+ interface WidgetManifest {
2332
+ /** Schema version for forward compatibility. Currently must be 1. */
2333
+ manifestVersion: number;
2334
+ /** Unique widget type identifier (e.g., "StockTickerWidget"). */
2335
+ type: string;
2336
+ /** The React component that renders this widget. */
2337
+ component: AnyComponent;
2338
+ /** Human-readable name shown in the builder palette. */
2339
+ displayName: string;
2340
+ /** Brief description shown in the builder palette. */
2341
+ description: string;
2342
+ /** Icon identifier for the builder palette (e.g., "chart-line"). */
2343
+ icon: string;
2344
+ /** Category ID for palette grouping (e.g., "components", "blocks", "utility"). */
2345
+ category: string;
2346
+ /** Property schema defining editable fields in the builder's property panel. */
2347
+ propertySchema: WidgetPropertySchema;
2348
+ /** Default prop values when the widget is first created. */
2349
+ defaultProps: Record<string, unknown>;
2350
+ /** Container behavior — only if this widget can hold child widgets. */
2351
+ container?: ContainerWidgetBehavior;
2352
+ /** Minimum SDK version required (e.g., "1.0.0"). */
2353
+ minSdkVersion?: string;
2354
+ /** Resizable configuration. */
2355
+ resizable?: {
2356
+ horizontal?: boolean;
2357
+ vertical?: boolean;
2358
+ minWidth?: number;
2359
+ minHeight?: number;
2360
+ };
2361
+ }
2721
2362
  //#endregion
2722
- //#region src/hooks/use-conversations.d.ts
2723
- /**
2724
- * Result type for useConversations hook.
2725
- * Uses QueryResult<Conversation[]> with default Error type.
2726
- */
2727
- type UseConversationsResult = QueryResult<Conversation[]>;
2363
+ //#region src/entry/create-portal.d.ts
2728
2364
  /**
2729
- * Hook to fetch all conversations.
2730
- * This is a stub implementation - override with your own data fetching logic.
2365
+ * Configuration for `createPortal()`.
2731
2366
  *
2732
- * @returns UseConversationsResult with empty data array
2367
+ * Provides a single-call entry point that sets up the full provider hierarchy
2368
+ * (auth, SDK, shell) with sensible defaults. Every field is optional.
2733
2369
  *
2734
- * @example
2370
+ * For full control, skip `createPortal()` and compose providers manually:
2735
2371
  * ```tsx
2736
- * const { data: conversations, isLoading, isError } = useConversations();
2737
- *
2738
- * if (isLoading) return <Loading />;
2739
- * if (isError) return <Error />;
2740
- *
2741
- * return conversations.map(conv => <ConversationItem key={conv.id} {...conv} />);
2372
+ * import { FluidAuthProvider, FluidProvider, RequireAuth, AppShell } from "@fluid-app/portal-sdk";
2742
2373
  * ```
2743
2374
  */
2744
- declare function useConversations(): UseConversationsResult;
2745
- /**
2746
- * Result type for useConversationMessages hook.
2747
- * Uses QueryResult<Message[]> with default Error type.
2748
- */
2749
- type UseConversationMessagesResult = QueryResult<Message[]>;
2375
+ interface PortalConfig {
2376
+ /** Custom page components keyed by navigation slug */
2377
+ customPages?: Record<string, ComponentType<{
2378
+ slug?: string;
2379
+ params?: string;
2380
+ }>>;
2381
+ /** Custom widget manifests (type + component + propertySchema) */
2382
+ customWidgets?: WidgetManifest[];
2383
+ /** API client config overrides (merged with defaults) */
2384
+ fluid?: Partial<FluidSDKConfig>;
2385
+ /** Auth config overrides (merged with defaults) */
2386
+ auth?: Partial<FluidAuthConfig>;
2387
+ /** Root element ID. @default "root" */
2388
+ rootId?: string;
2389
+ /** AppShell props passthrough (basePath, sidebarHeader, etc.) */
2390
+ shell?: Omit<AppShellProps, "customPages">;
2391
+ /** Wrap AppShell with additional providers (inserted inside RequireAuth, below FluidProvider) */
2392
+ providers?: ComponentType<{
2393
+ children: ReactNode;
2394
+ }>;
2395
+ /** Disable StrictMode. @default false */
2396
+ disableStrictMode?: boolean;
2397
+ }
2750
2398
  /**
2751
- * Hook to fetch messages for a specific conversation.
2752
- * This is a stub implementation - override with your own data fetching logic.
2399
+ * Bootstrap a Fluid portal with a single function call.
2753
2400
  *
2754
- * @param conversationId - The ID of the conversation to fetch messages for
2755
- * @returns UseConversationMessagesResult with empty data array
2401
+ * Sets up the full provider hierarchy (FluidAuthProvider FluidProvider RequireAuth → AppShell)
2402
+ * and renders into the DOM.
2756
2403
  *
2757
- * @example
2758
- * ```tsx
2759
- * const { data: messages, isLoading, isError } = useConversationMessages(conversationId);
2404
+ * @example Minimal usage
2405
+ * ```ts
2406
+ * import { createPortal } from "@fluid-app/portal-sdk";
2407
+ * import "./index.css";
2760
2408
  *
2761
- * if (isLoading) return <Loading />;
2762
- * if (isError) return <Error />;
2409
+ * createPortal();
2410
+ * ```
2763
2411
  *
2764
- * return messages.map(msg => <MessageBubble key={msg.id} {...msg} />);
2412
+ * @example With custom pages
2413
+ * ```ts
2414
+ * import { createPortal } from "@fluid-app/portal-sdk";
2415
+ * import { customPages } from "./portal.config";
2416
+ * import "./index.css";
2417
+ *
2418
+ * createPortal({ customPages });
2419
+ * ```
2420
+ *
2421
+ * @example With overrides
2422
+ * ```ts
2423
+ * createPortal({
2424
+ * customPages,
2425
+ * fluid: { baseUrl: "https://my-api.example.com" },
2426
+ * auth: { onAuthFailure: () => console.log("auth failed") },
2427
+ * shell: { basePath: "/portal" },
2428
+ * });
2765
2429
  * ```
2766
2430
  */
2767
- declare function useConversationMessages(_conversationId: string): UseConversationMessagesResult;
2431
+ declare function createPortal(config?: PortalConfig): void;
2768
2432
  //#endregion
2769
- //#region src/hooks/use-contacts.d.ts
2770
- /**
2771
- * Type predicate to check if a status string is a valid ContactStatus.
2772
- * Enables runtime validation with type narrowing.
2773
- */
2774
- declare function isContactStatus(value: string): value is ContactStatus;
2775
- /**
2776
- * Parameters for filtering and paginating contacts.
2777
- * Uses readonly properties and proper ContactStatus type for status.
2778
- */
2779
- interface UseContactsParams {
2780
- /** Search query to filter contacts by name, email, or company */
2781
- readonly search?: string;
2782
- /** Filter contacts by status - uses ContactStatus union type for type safety */
2783
- readonly status?: ContactStatus;
2784
- /** Maximum number of contacts to return */
2785
- readonly limit?: number;
2786
- }
2787
- /**
2788
- * Result type for the useContacts hook.
2789
- * Uses ListQueryResult<Contact> with totalCount and default Error type.
2790
- */
2791
- type UseContactsResult = ListQueryResult<Contact>;
2792
- /**
2793
- * Result type for the useContact hook.
2794
- * Uses QueryResultNullable since a specific contact may not exist.
2795
- */
2796
- type UseContactResult = QueryResultNullable<Contact>;
2433
+ //#region src/config/defaults.d.ts
2797
2434
  /**
2798
- * Hook to fetch a list of contacts with optional filtering and pagination.
2799
- * This is a stub implementation - override with your own data fetching logic.
2435
+ * Creates a FluidSDKConfig with sensible defaults.
2800
2436
  *
2801
- * @param params - Optional parameters for filtering and pagination
2802
- * @returns Object containing contacts data, loading state, error state, and total count
2437
+ * Default behavior:
2438
+ * - baseUrl: reads from `VITE_API_URL` env var, falls back to `""` (same-origin relative)
2439
+ * - Auth: relies on session cookies sent via `credentials: 'include'`
2803
2440
  *
2804
- * @example
2805
- * ```tsx
2806
- * const { data: contacts, isLoading, totalCount } = useContacts({
2807
- * search: 'john',
2808
- * status: 'active',
2809
- * limit: 20
2810
- * });
2441
+ * Pass overrides to customize any field:
2442
+ * ```ts
2443
+ * const config = createDefaultFluidConfig({ baseUrl: "https://my-api.example.com" });
2811
2444
  * ```
2812
2445
  */
2813
- declare function useContacts(_params?: UseContactsParams): UseContactsResult;
2446
+ declare function createDefaultFluidConfig(overrides?: Partial<FluidSDKConfig>): FluidSDKConfig;
2814
2447
  /**
2815
- * Hook to fetch a single contact by ID.
2816
- * This is a stub implementation - override with your own data fetching logic.
2817
- *
2818
- * @param contactId - The unique identifier of the contact to fetch
2819
- * @returns Object containing contact data, loading state, and error state
2448
+ * Creates a FluidAuthConfig with sensible defaults.
2820
2449
  *
2821
- * @example
2822
- * ```tsx
2823
- * const { data: contact, isLoading, isError } = useContact('contact-123');
2450
+ * The SDK's FluidAuthProvider already applies defaults for all fields,
2451
+ * so an empty config works out of the box. Use overrides to customize:
2452
+ * ```ts
2453
+ * const config = createDefaultAuthConfig({ onAuthFailure: () => navigate("/login") });
2824
2454
  * ```
2825
2455
  */
2826
- declare function useContact(_contactId: string): UseContactResult;
2456
+ declare function createDefaultAuthConfig(overrides?: Partial<FluidAuthConfig>): FluidAuthConfig;
2827
2457
  //#endregion
2828
- //#region src/components/RequireAuth.d.ts
2829
- interface RequireAuthProps {
2830
- /** Content to render when authenticated */
2831
- children: ReactNode;
2832
- /** Component to show while checking authentication (default: AuthLoading) */
2833
- fallback?: ReactNode;
2834
- /** Component to show when not authenticated (default: AuthError) */
2835
- errorComponent?: ReactNode;
2836
- }
2458
+ //#region src/hooks/use-fluid-api.d.ts
2837
2459
  /**
2838
- * Component that protects content requiring authentication.
2839
- *
2840
- * **Important:** This provides UX-level protection only. It prevents
2841
- * unauthenticated users from seeing the UI, but the real security
2842
- * boundary is the server-side API. Client-side auth can always be
2843
- * bypassed by modifying browser state.
2844
- *
2845
- * For defense-in-depth, configure `jwksUrl` in `FluidAuthConfig`
2846
- * to enable client-side JWT signature verification.
2847
- *
2848
- * Shows different states based on auth status:
2849
- * - Loading: Shows fallback (spinner by default)
2850
- * - Not authenticated: Shows errorComponent (AuthError by default)
2851
- * - Authenticated: Shows children
2460
+ * Hook to access the Fluid API client
2852
2461
  *
2853
2462
  * @example
2854
2463
  * ```tsx
2855
- * // Basic usage - shows default loading/error states
2856
- * <RequireAuth>
2857
- * <ProtectedContent />
2858
- * </RequireAuth>
2859
- *
2860
- * // Custom loading state
2861
- * <RequireAuth fallback={<CustomSpinner />}>
2862
- * <ProtectedContent />
2863
- * </RequireAuth>
2464
+ * function UserInfo() {
2465
+ * const api = useFluidApi();
2864
2466
  *
2865
- * // Custom error component
2866
- * <RequireAuth errorComponent={<LoginPrompt />}>
2867
- * <ProtectedContent />
2868
- * </RequireAuth>
2467
+ * const { data: user } = useQuery({
2468
+ * queryKey: ["me"],
2469
+ * queryFn: () => api.users.me(),
2470
+ * });
2869
2471
  *
2870
- * // Both custom
2871
- * <RequireAuth
2872
- * fallback={<SkeletonLoader />}
2873
- * errorComponent={<RedirectToLogin />}
2874
- * >
2875
- * <Dashboard />
2876
- * </RequireAuth>
2472
+ * return <p>Hello, {user?.name}</p>;
2473
+ * }
2877
2474
  * ```
2878
2475
  */
2879
- declare function RequireAuth({
2880
- children,
2881
- fallback,
2882
- errorComponent
2883
- }: RequireAuthProps): React.JSX.Element;
2476
+ declare function useFluidApi(): FluidClient;
2884
2477
  //#endregion
2885
- //#region src/components/AuthError.d.ts
2886
- interface AuthErrorProps {
2887
- /** Error message to display */
2888
- message?: string;
2889
- /** Optional title */
2890
- title?: string;
2891
- /** Optional children for custom content */
2892
- children?: ReactNode;
2893
- }
2478
+ //#region src/hooks/use-fluid-profile.d.ts
2894
2479
  /**
2895
- * Default authentication error component.
2480
+ * Base query key for profile data.
2481
+ * Kept for backwards compatibility — the runtime key used by the hook
2482
+ * includes a company prefix via {@link useCompanyScopedQueryKey}.
2896
2483
  *
2897
- * Displays a simple error message when authentication fails.
2898
- * Can be customized via props or replaced entirely in RequireAuth.
2484
+ * @deprecated Use {@link APP_DATA_QUERY_KEY} with `useFluidApp` instead.
2485
+ */
2486
+ declare const PROFILE_QUERY_KEY: readonly ["fluid", "profile"];
2487
+ /**
2488
+ * Hook to fetch the portal profile (themes, navigation, screens).
2489
+ *
2490
+ * Internally fetches from the fluidos API (same data source as
2491
+ * {@link useFluidApp}) and selects the `profile` slice, so no
2492
+ * legacy `/api/rep_app/manifest` call is made.
2493
+ *
2494
+ * @deprecated Use `useFluidApp()` instead — it returns the full
2495
+ * `RepAppData` including `profile`, `screens`, and more.
2899
2496
  *
2900
2497
  * @example
2901
2498
  * ```tsx
2902
- * // Use with default message
2903
- * <AuthError />
2499
+ * function Navigation() {
2500
+ * const { data: profile, isLoading } = useFluidProfile();
2904
2501
  *
2905
- * // Use with custom message
2906
- * <AuthError message="Session expired. Please log in again." />
2502
+ * if (isLoading) return <Spinner />;
2907
2503
  *
2908
- * // Use with custom content
2909
- * <AuthError>
2910
- * <CustomLoginButton />
2911
- * </AuthError>
2504
+ * return (
2505
+ * <nav>
2506
+ * {profile?.navigation.navigation_items.map(item => (
2507
+ * <NavItem key={item.id} item={item} />
2508
+ * ))}
2509
+ * </nav>
2510
+ * );
2511
+ * }
2912
2512
  * ```
2913
2513
  */
2914
- declare function AuthError({
2915
- message,
2916
- title,
2917
- children
2918
- }: AuthErrorProps): React.JSX.Element;
2514
+ declare function useFluidProfile(): UseQueryResult<Profile>;
2515
+ //#endregion
2516
+ //#region src/hooks/use-fluid-app.d.ts
2919
2517
  /**
2920
- * Simple loading spinner component for auth loading state.
2518
+ * Base query key for full app data (fluidos endpoint).
2519
+ * Kept for backwards compatibility — the runtime key used by the hook
2520
+ * includes a company prefix via {@link useCompanyScopedQueryKey}.
2921
2521
  */
2922
- declare function AuthLoading(): React.JSX.Element;
2923
- //#endregion
2924
- //#region ../../messaging/core/src/types.d.ts
2522
+ declare const APP_DATA_QUERY_KEY: readonly ["fluid", "app"];
2925
2523
  /**
2926
- * Domain types for the messaging package.
2524
+ * Hook to fetch the full portal app data from the fluidos API.
2927
2525
  *
2928
- * These are owned by messaging-core and represent the contract that
2929
- * any API adapter (current client, future BFF) must satisfy.
2930
- * Consuming packages import from here never from the API client directly.
2931
- */
2932
- interface PaginationObject {
2933
- pagination: {
2934
- current: number;
2935
- previous: number | null;
2936
- next: number | null;
2937
- per_page: number;
2938
- pages: number;
2939
- count: number;
2940
- };
2941
- }
2942
- type Paginated<T> = [PaginationObject, {
2943
- items: T[];
2944
- }];
2945
- interface AttachmentMetadata {
2946
- width?: number;
2947
- height?: number;
2948
- }
2949
- interface Attachment {
2950
- id: number;
2951
- url: string;
2952
- filename: string;
2953
- kind: string;
2954
- image_url: string | null;
2955
- image_path: string | null;
2956
- content_type: string | null;
2957
- attachable_type: string | null;
2958
- attachable_id: number | null;
2959
- thumbnail_url: string | null;
2960
- metadata: AttachmentMetadata | null;
2961
- content_size: number | null;
2962
- }
2963
- interface MessageAttachmentInput {
2964
- url: string;
2965
- filename: string;
2966
- kind: string;
2967
- content_type?: string;
2968
- content_size?: number;
2969
- metadata?: AttachmentMetadata;
2970
- }
2971
- interface LinkPreview {
2972
- url: string;
2973
- title?: string | null;
2974
- description?: string | null;
2975
- images?: string[];
2976
- videos?: string[];
2977
- favicon?: string | null;
2978
- error?: string | null;
2979
- original_url?: string | null;
2980
- }
2981
- interface InfoMessageRecipient {
2982
- id: number;
2983
- first_name: string;
2984
- last_name: string;
2985
- }
2986
- interface DefaultMessageMetadata {
2987
- links: LinkPreview[];
2988
- client_message_id?: string | number | null;
2989
- }
2990
- interface SystemConversationUpdateMetadata {
2991
- name: string;
2992
- previous_name: string;
2993
- client_message_id?: string | number | null;
2994
- links?: LinkPreview[];
2995
- }
2996
- interface SystemConversationCreatedMetadata {
2997
- conversation_name: string;
2998
- description?: string;
2999
- member_count: number;
3000
- auto_add_recipients: boolean;
3001
- client_message_id?: string | number | null;
3002
- links?: LinkPreview[];
3003
- }
3004
- interface SystemRecipientActionMetadata {
3005
- recipient_ids_added?: number[];
3006
- recipient_ids_removed?: number[];
3007
- recipient_ids_left?: number[];
3008
- recipient_ids_joined?: number[];
3009
- recipient_added?: InfoMessageRecipient[];
3010
- recipient_removed?: InfoMessageRecipient[];
3011
- recipient_left?: InfoMessageRecipient[];
3012
- recipient_joined?: InfoMessageRecipient[];
3013
- client_message_id?: string | number | null;
3014
- links?: LinkPreview[];
3015
- }
3016
- interface InfoMessageMetadataShape {
3017
- recipient_added?: InfoMessageRecipient[];
3018
- recipient_ids_added?: number[];
3019
- recipient_removed?: InfoMessageRecipient[];
3020
- recipient_ids_removed?: number[];
3021
- links?: LinkPreview[];
3022
- client_message_id?: string | number | null;
3023
- }
3024
- type MessageMetadata = DefaultMessageMetadata | null | SystemConversationUpdateMetadata | SystemConversationCreatedMetadata | SystemRecipientActionMetadata | InfoMessageMetadataShape;
3025
- interface Recipient {
3026
- id: number;
3027
- first_name: string;
3028
- last_name: string;
3029
- avatar_url: string | null;
3030
- image_url: string | null;
3031
- receivable_id: number;
3032
- receivable_type: "Contact" | "UserCompany";
3033
- discarded_at: string | null;
3034
- left_conversation_at: string | null;
3035
- blocked: boolean | null;
3036
- country_name: string | null;
3037
- pro_user: boolean;
3038
- avatar_background: string | null;
3039
- email?: string | null;
3040
- phone?: string | null;
3041
- status?: "online" | "offline" | "away";
3042
- last_online?: string | null;
3043
- "conversation_messaging_enabled?"?: boolean;
3044
- }
3045
- interface ReducedRecipient {
3046
- id: number;
3047
- first_name: string;
3048
- last_name: string;
3049
- image_url: string | null;
3050
- discarded_at: string | null;
3051
- blocked: boolean | null;
3052
- blocker: boolean | null;
3053
- avatar_background: string | null;
3054
- seen_at?: string | null;
3055
- email?: string | null;
3056
- phone?: string | null;
3057
- pro_user?: boolean;
3058
- }
3059
- interface SlimmedRecipient {
3060
- id: number;
3061
- first_name: string;
3062
- last_name: string;
3063
- discarded_at: string | null;
3064
- blocked: boolean | null;
3065
- avatar_background: string | null;
3066
- email?: string | null;
3067
- phone?: string | null;
3068
- removed_at?: string | null;
2526
+ * Returns a `RepAppData` object containing:
2527
+ * - `screens` all screen definitions with normalized component trees
2528
+ * - `profile.themes` fully-transformed ThemeDefinition[] (handles legacy + new formats)
2529
+ * - `profile.activeThemeId` — the currently active theme ID
2530
+ * - `profile.navigation.navigation_items` — sorted, recursive navigation tree
2531
+ *
2532
+ * Uses IndexedDB persistence so subsequent page loads hydrate instantly
2533
+ * from cache while revalidating in the background. The raw API response
2534
+ * (plain JSON) is cached; Color objects are recreated from cache via
2535
+ * `select` on every restore — this is fast (CPU only, no network).
2536
+ *
2537
+ * @example
2538
+ * ```tsx
2539
+ * function App() {
2540
+ * const { data: appData, isLoading } = useFluidApp();
2541
+ *
2542
+ * if (isLoading) return <Spinner />;
2543
+ *
2544
+ * return (
2545
+ * <AppShell
2546
+ * appData={appData}
2547
+ * navigation={appData.profile.navigation.navigation_items}
2548
+ * />
2549
+ * );
2550
+ * }
2551
+ * ```
2552
+ */
2553
+ declare function useFluidApp(options?: {
2554
+ enabled?: boolean;
2555
+ }): UseQueryResult<RepAppData>;
2556
+ //#endregion
2557
+ //#region src/hooks/use-fluid-permissions.d.ts
2558
+ /**
2559
+ * Base query key for permissions data.
2560
+ * Kept for backwards compatibility — the runtime key used by the hook
2561
+ * includes a company prefix via {@link useCompanyScopedQueryKey}.
2562
+ */
2563
+ declare const PERMISSIONS_QUERY_KEY: readonly ["fluid", "permissions"];
2564
+ /**
2565
+ * Result of useFluidPermissions hook
2566
+ */
2567
+ interface UseFluidPermissionsResult {
2568
+ /** Raw permissions query result */
2569
+ query: UseQueryResult<UserPermissions>;
2570
+ /** Permissions data (alias for query.data) */
2571
+ permissions: UserPermissions | undefined;
2572
+ /** Check if user has a specific permission */
2573
+ can: (resource: string, action?: PermissionAction) => boolean;
2574
+ /** Check if user is a super admin */
2575
+ isSuperAdmin: boolean;
3069
2576
  }
3070
- interface WithContactRecipient {
3071
- id: number;
3072
- email?: string | null;
3073
- phone?: string | null;
3074
- first_name?: string | null;
3075
- last_name?: string | null;
3076
- image_url: string | null;
3077
- receivable_id: number;
3078
- receivable_type: "Contact";
2577
+ /**
2578
+ * Hook to fetch and check user permissions
2579
+ *
2580
+ * @example
2581
+ * ```tsx
2582
+ * function TeamSettings() {
2583
+ * const { can, isSuperAdmin } = useFluidPermissions();
2584
+ *
2585
+ * if (!can("team", "manage")) {
2586
+ * return <AccessDenied />;
2587
+ * }
2588
+ *
2589
+ * return <TeamSettingsForm canDelete={can("team", "delete")} />;
2590
+ * }
2591
+ * ```
2592
+ */
2593
+ declare function useFluidPermissions(): UseFluidPermissionsResult;
2594
+ //#endregion
2595
+ //#region src/hooks/use-fluid-theme.d.ts
2596
+ /**
2597
+ * Result of useFluidTheme hook
2598
+ */
2599
+ interface UseFluidThemeResult {
2600
+ /** Currently active theme */
2601
+ currentTheme: ThemeDefinition | null;
2602
+ /** Switch to a different theme */
2603
+ setTheme: (theme: ThemeDefinition) => void;
2604
+ /** Switch between light and dark mode */
2605
+ setThemeMode: (mode: "light" | "dark") => void;
2606
+ /** Current theme mode (convenience accessor) */
2607
+ mode: "light" | "dark" | undefined;
3079
2608
  }
3080
- interface RecipientSearchCount {
3081
- meta: {
3082
- count: number;
3083
- };
2609
+ /**
2610
+ * Hook to access and control theme settings
2611
+ *
2612
+ * @example
2613
+ * ```tsx
2614
+ * function ThemeSwitcher({ themes }: { themes: ThemeDefinition[] }) {
2615
+ * const { currentTheme, setTheme, setThemeMode, mode } = useFluidTheme();
2616
+ *
2617
+ * return (
2618
+ * <div>
2619
+ * <select
2620
+ * value={currentTheme?.name}
2621
+ * onChange={(e) => {
2622
+ * const theme = themes.find(t => t.name === e.target.value);
2623
+ * if (theme) setTheme(theme);
2624
+ * }}
2625
+ * >
2626
+ * {themes.map(theme => (
2627
+ * <option key={theme.name} value={theme.name}>
2628
+ * {theme.name}
2629
+ * </option>
2630
+ * ))}
2631
+ * </select>
2632
+ *
2633
+ * <button onClick={() => setThemeMode(mode === "dark" ? "light" : "dark")}>
2634
+ * Toggle {mode === "dark" ? "Light" : "Dark"} Mode
2635
+ * </button>
2636
+ * </div>
2637
+ * );
2638
+ * }
2639
+ * ```
2640
+ */
2641
+ declare function useFluidTheme(): UseFluidThemeResult;
2642
+ //#endregion
2643
+ //#region src/hooks/use-current-rep.d.ts
2644
+ /**
2645
+ * Base query key for current rep data.
2646
+ * Kept for backwards compatibility — the runtime key used by the hook
2647
+ * includes a company prefix via {@link useCompanyScopedQueryKey}.
2648
+ */
2649
+ declare const CURRENT_REP_QUERY_KEY: readonly ["fluid", "currentRep"];
2650
+ /**
2651
+ * Hook to fetch the currently authenticated rep's profile
2652
+ *
2653
+ * @example
2654
+ * ```tsx
2655
+ * function RepHeader() {
2656
+ * const { data: rep, isLoading } = useCurrentRep();
2657
+ *
2658
+ * if (isLoading) return <Skeleton />;
2659
+ *
2660
+ * return (
2661
+ * <div>
2662
+ * <Avatar src={rep?.avatar_url} />
2663
+ * <span>{rep?.first_name} {rep?.last_name}</span>
2664
+ * </div>
2665
+ * );
2666
+ * }
2667
+ * ```
2668
+ */
2669
+ declare function useCurrentRep(): UseQueryResult<Rep>;
2670
+ //#endregion
2671
+ //#region src/hooks/use-current-user.d.ts
2672
+ /**
2673
+ * Base query key for current user data.
2674
+ * Kept for backwards compatibility — the runtime key used by the hook
2675
+ * includes a company prefix via {@link useCompanyScopedQueryKey}.
2676
+ */
2677
+ declare const CURRENT_USER_QUERY_KEY: readonly ["fluid", "currentUser"];
2678
+ /**
2679
+ * Hook to fetch the currently authenticated user's full profile.
2680
+ * Returns company, country, and other fields from GET /api/me.
2681
+ *
2682
+ * @example
2683
+ * ```tsx
2684
+ * function ShopPage() {
2685
+ * const { data: user, isLoading } = useCurrentUser();
2686
+ * const subdomain = user?.company?.subdomain;
2687
+ * const countryIso = user?.country?.iso ?? "US";
2688
+ * // ...
2689
+ * }
2690
+ * ```
2691
+ */
2692
+ declare function useCurrentUser(): UseQueryResult<UserMe>;
2693
+ //#endregion
2694
+ //#region src/hooks/use-fluid-auth.d.ts
2695
+ /**
2696
+ * Hook to access authentication state and utilities.
2697
+ *
2698
+ * Must be used within a `FluidAuthProvider`.
2699
+ *
2700
+ * @returns Authentication context with user info, loading state, and utilities
2701
+ * @throws Error if used outside FluidAuthProvider
2702
+ *
2703
+ * @example
2704
+ * ```tsx
2705
+ * function UserProfile() {
2706
+ * const { isAuthenticated, isLoading, user, clearAuth } = useFluidAuth();
2707
+ *
2708
+ * if (isLoading) {
2709
+ * return <Spinner />;
2710
+ * }
2711
+ *
2712
+ * if (!isAuthenticated) {
2713
+ * return <p>Please log in</p>;
2714
+ * }
2715
+ *
2716
+ * return (
2717
+ * <div>
2718
+ * <p>Welcome, {user.full_name}!</p>
2719
+ * <button onClick={clearAuth}>Log out</button>
2720
+ * </div>
2721
+ * );
2722
+ * }
2723
+ * ```
2724
+ */
2725
+ declare function useFluidAuth(): FluidAuthContextValue;
2726
+ //#endregion
2727
+ //#region src/hooks/use-user-type.d.ts
2728
+ interface UseUserTypeResult {
2729
+ userType: UserType | null;
2730
+ isCustomer: boolean;
2731
+ isRep: boolean;
2732
+ isAdmin: boolean;
3084
2733
  }
3085
- type FluidMessage = {
3086
- id: number;
3087
- body: string;
3088
- type: string;
3089
- created_at: string;
3090
- updated_at?: string | null;
3091
- deleted_at?: string | null;
3092
- edited_at?: string | null;
3093
- conversation_id: number;
3094
- status: string;
3095
- attachments: Attachment[];
3096
- reaction_stats: Record<string, number> | null;
3097
- reaction?: string | null;
3098
- metadata?: MessageMetadata;
3099
- emoji_only_count?: number;
3100
- mentioned_recipients: SlimmedRecipient[];
3101
- sent_at?: string;
3102
- pinned?: boolean;
3103
- scheduled_at?: string;
3104
- replied_to_message?: ({
3105
- id: number;
3106
- } & Record<string, unknown>) | null;
3107
- sender_recipient: ReducedRecipient;
3108
- seen_by: unknown;
3109
- seen_by_count: unknown;
2734
+ /**
2735
+ * Convenience hook for user-type checks in the portal SDK.
2736
+ */
2737
+ declare function useUserType(): UseUserTypeResult;
2738
+ //#endregion
2739
+ //#region src/hooks/query-keys.d.ts
2740
+ /**
2741
+ * Create a company-scoped query key by prepending ["company", companyId].
2742
+ *
2743
+ * @param companyId - The company ID from the JWT payload
2744
+ * @param baseKey - The base query key segments (e.g. ["fluid", "profile"])
2745
+ * @returns A tuple like ["company", 42, "fluid", "profile"]
2746
+ *
2747
+ * @example
2748
+ * ```ts
2749
+ * const key = createCompanyQueryKey(42, "fluid", "profile");
2750
+ * // => ["company", 42, "fluid", "profile"]
2751
+ * ```
2752
+ */
2753
+ declare function createCompanyQueryKey(companyId: number, ...baseKey: readonly string[]): readonly ["company", number, ...string[]];
2754
+ /**
2755
+ * Hook that returns a `scopeKey` function bound to the current company ID
2756
+ * from the auth context. If the user is not authenticated or has no
2757
+ * company_id, the base key is returned unscoped (graceful degradation).
2758
+ *
2759
+ * @example
2760
+ * ```tsx
2761
+ * function MyComponent() {
2762
+ * const { scopeKey } = useCompanyScopedQueryKey();
2763
+ * const queryKey = scopeKey(PROFILE_QUERY_KEY);
2764
+ * // => ["company", 42, "fluid", "profile"] (when authenticated)
2765
+ * // => ["fluid", "profile"] (fallback)
2766
+ * }
2767
+ * ```
2768
+ */
2769
+ declare function useCompanyScopedQueryKey(): {
2770
+ readonly companyId: number | undefined;
2771
+ readonly scopeKey: <T extends readonly string[]>(baseKey: T) => readonly (string | number)[];
3110
2772
  };
3111
- interface MessagePinResponse {
3112
- message: string;
3113
- pinned: boolean;
3114
- }
3115
- interface BaseConversation {
3116
- id: number;
3117
- name: string;
3118
- description: string | null;
3119
- kind: string | null;
3120
- type: string;
3121
- status: string;
3122
- created_at: string;
3123
- pinned: boolean;
3124
- unread_messages_count?: number | null;
3125
- "sms_enabled?": boolean;
3126
- draft_message: DraftMessage | null;
3127
- "email_enabled?": boolean;
3128
- conversation_type: string;
3129
- "messaging_enabled?": boolean;
3130
- broadcasting: boolean | null;
3131
- total_recipients: number;
3132
- unread?: boolean | null;
3133
- image_url: string | null;
3134
- auto_add_recipients?: boolean | null;
3135
- muted?: boolean | null;
3136
- announcing?: boolean | null;
3137
- scheduled_messages_count?: number | null;
3138
- avatar_background_color: string | null;
3139
- avatar_emoji: string | null;
3140
- avatar_url: string | null;
3141
- pinned_messages_count?: number | null;
3142
- recipients: Recipient[];
3143
- creator: ReducedRecipient | null;
3144
- }
3145
- interface EmailConversation extends BaseConversation {
3146
- type: "EmailConversation";
3147
- kind: null;
3148
- "sms_enabled?": false;
3149
- "email_enabled?": true;
3150
- broadcasting: null;
3151
- }
3152
- interface ChannelConversation extends BaseConversation {
3153
- type: "ChannelConversation";
3154
- kind: "channel";
3155
- "sms_enabled?": false;
3156
- "email_enabled?": false;
3157
- }
3158
- interface GroupConversation extends BaseConversation {
3159
- type: "GroupConversation";
3160
- kind: "group";
3161
- "sms_enabled?": false;
3162
- "email_enabled?": false;
3163
- broadcasting: null;
2773
+ //#endregion
2774
+ //#region src/hooks/use-logout.d.ts
2775
+ interface UseLogoutOptions {
2776
+ /** URL to redirect to after logout. Triggers a full page navigation. */
2777
+ redirectUrl?: string;
2778
+ /** Callback invoked after all state is cleared. Ignored when `redirectUrl` is set. */
2779
+ onLogout?: () => void;
3164
2780
  }
3165
- interface SmsConversation extends BaseConversation {
3166
- type: "SmsConversation";
3167
- kind: null;
3168
- "sms_enabled?": true;
3169
- "email_enabled?": false;
3170
- broadcasting: null;
2781
+ /**
2782
+ * Hook that returns a `logout` function which clears the server session
2783
+ * via `DELETE /logout` and all cached/persisted client state.
2784
+ *
2785
+ * @example
2786
+ * ```tsx
2787
+ * const logout = useLogout({ redirectUrl: "/login" });
2788
+ * <button onClick={logout}>Log out</button>
2789
+ * ```
2790
+ *
2791
+ * @example
2792
+ * ```tsx
2793
+ * const logout = useLogout({
2794
+ * onLogout: () => navigate("/signed-out"),
2795
+ * });
2796
+ * ```
2797
+ */
2798
+ declare function useLogout({
2799
+ redirectUrl,
2800
+ onLogout
2801
+ }?: UseLogoutOptions): () => Promise<void>;
2802
+ //#endregion
2803
+ //#region src/hooks/use-company-switch.d.ts
2804
+ interface UseCompanySwitchOptions {}
2805
+ /**
2806
+ * Hook that handles company switching for the portal.
2807
+ *
2808
+ * Calls PUT /api/authentication/company/{id}/switch, clears the TanStack
2809
+ * Query cache and IndexedDB persisted cache, then reloads the page so all
2810
+ * queries re-fetch with the new company context.
2811
+ *
2812
+ * The server updates the session cookie automatically via the switch
2813
+ * endpoint response; no client-side token storage is needed.
2814
+ */
2815
+ declare function useCompanySwitch(_options?: UseCompanySwitchOptions): {
2816
+ switchCompany: (companyId: number) => void;
2817
+ isPending: boolean;
2818
+ isError: boolean;
2819
+ error: Error | null;
2820
+ };
2821
+ //#endregion
2822
+ //#region src/hooks/hook-types.d.ts
2823
+ /**
2824
+ * Hook type utilities and type predicates.
2825
+ *
2826
+ * This module provides:
2827
+ * - Generic hook result types with default type parameters
2828
+ * - Type predicates for query state narrowing
2829
+ * - Reusable patterns for type-safe property access in hooks
2830
+ *
2831
+ * Following generics best practices:
2832
+ * - generics-default-type-parameters: Default E to Error for common case
2833
+ * - generics-type-predicates: Type predicates for result state narrowing
2834
+ * - generics-constrain-type-parameters: K extends keyof T for property access
2835
+ */
2836
+ /**
2837
+ * Base result type for query hooks with default error type.
2838
+ * Uses default type parameter for E (generics-default-type-parameters rule).
2839
+ *
2840
+ * @typeParam T - The data type
2841
+ * @typeParam E - The error type (defaults to Error)
2842
+ *
2843
+ * @example
2844
+ * // Error type defaults to Error
2845
+ * type UsersResult = QueryResult<User[]>;
2846
+ *
2847
+ * // Can override when needed
2848
+ * type CustomResult = QueryResult<User[], ApiError>;
2849
+ */
2850
+ interface QueryResult<T, E = Error> {
2851
+ readonly data: T;
2852
+ readonly isLoading: boolean;
2853
+ readonly isError: boolean;
2854
+ readonly error?: E | undefined;
3171
2855
  }
3172
- interface DirectConversation extends BaseConversation {
3173
- type: "DirectConversation";
3174
- kind: "direct";
3175
- "sms_enabled?": false;
3176
- "email_enabled?": false;
3177
- broadcasting: null;
2856
+ /**
2857
+ * Result type for hooks that may not have data yet.
2858
+ * Extends QueryResult with nullable data.
2859
+ *
2860
+ * @typeParam T - The data type
2861
+ * @typeParam E - The error type (defaults to Error)
2862
+ */
2863
+ interface QueryResultNullable<T, E = Error> {
2864
+ readonly data: T | null | undefined;
2865
+ readonly isLoading: boolean;
2866
+ readonly isError: boolean;
2867
+ readonly error?: E | undefined;
3178
2868
  }
3179
- interface BotConversation extends BaseConversation {
3180
- type: "BotConversation";
3181
- kind: "direct";
3182
- "sms_enabled?": false;
3183
- "email_enabled?": false;
3184
- broadcasting: null;
2869
+ /**
2870
+ * Result type for list/collection hooks with aggregates.
2871
+ *
2872
+ * @typeParam T - The item type in the array
2873
+ * @typeParam E - The error type (defaults to Error)
2874
+ */
2875
+ interface ListQueryResult<T, E = Error> extends QueryResult<T[], E> {
2876
+ readonly totalCount: number;
3185
2877
  }
3186
- interface DownlineConversation extends BaseConversation {
3187
- type: "DownlineConversation";
3188
- kind: "downline";
3189
- "sms_enabled?": false;
3190
- "email_enabled?": false;
3191
- broadcasting: null;
2878
+ /**
2879
+ * Result type for list hooks with value aggregation (e.g., deals with total value).
2880
+ *
2881
+ * @typeParam T - The item type in the array
2882
+ * @typeParam E - The error type (defaults to Error)
2883
+ */
2884
+ interface ValueListQueryResult<T, E = Error> extends ListQueryResult<T, E> {
2885
+ readonly totalValue: number;
3192
2886
  }
3193
- type Conversation$1 = EmailConversation | ChannelConversation | GroupConversation | SmsConversation | DirectConversation | BotConversation | DownlineConversation;
3194
- type ListConversationsInput = {
3195
- status?: "open" | "closed";
3196
- kind?: "direct" | "group" | "channel";
3197
- pinned?: boolean;
3198
- per_page?: number;
3199
- page?: number;
3200
- template?: string;
3201
- search?: string;
3202
- filterrific?: Record<string, unknown>;
3203
- } | undefined;
3204
- type ConversationCreateInput = {
3205
- conversation: {
3206
- kind?: string;
3207
- type?: string;
3208
- name?: string;
3209
- description?: string | null;
3210
- broadcasting?: boolean;
3211
- filter?: Record<string, unknown>;
3212
- auto_add_recipients?: boolean;
3213
- };
3214
- recipients?: {
3215
- id?: number;
3216
- uid?: number;
3217
- email?: string;
3218
- phone?: string;
3219
- first_name?: string;
3220
- last_name?: string;
3221
- image_url?: string;
3222
- }[];
3223
- };
3224
- type FindConversationInput = {
3225
- contact_id: number;
3226
- conversation_type: "ChannelConversation" | "DirectConversation" | "GroupConversation" | "SmsConversation" | "EmailConversation" | "channel" | "direct" | "group";
3227
- };
3228
- type CreateMessageInput = {
3229
- message: {
3230
- body?: string;
3231
- theme?: string;
3232
- subject?: string;
3233
- type?: string;
3234
- attachments_attributes?: MessageAttachmentInput[];
3235
- };
3236
- client_message_id?: string | number;
2887
+ /**
2888
+ * Type predicate to check if a query result has successfully loaded data.
2889
+ * Narrows the data type from T | null | undefined to T.
2890
+ *
2891
+ * @example
2892
+ * const result = useContact(id);
2893
+ * if (hasData(result)) {
2894
+ * // TypeScript knows result.data is Contact, not Contact | null
2895
+ * console.log(result.data.name);
2896
+ * }
2897
+ */
2898
+ declare function hasData<T, E = Error>(result: QueryResultNullable<T, E>): result is QueryResultNullable<T, E> & {
2899
+ readonly data: T;
3237
2900
  };
3238
- type ScheduledMessageInput = {
3239
- scheduled_message: {
3240
- body?: string;
3241
- theme?: string;
3242
- scheduled_at: string;
3243
- attachments_attributes?: MessageAttachmentInput[];
3244
- type?: string;
3245
- };
2901
+ /**
2902
+ * Type predicate to check if a query result is in loading state.
2903
+ * Useful for conditional rendering.
2904
+ *
2905
+ * @example
2906
+ * if (isLoading(result)) {
2907
+ * return <Spinner />;
2908
+ * }
2909
+ */
2910
+ declare function isLoading<T, E = Error>(result: QueryResult<T, E> | QueryResultNullable<T, E>): boolean;
2911
+ /**
2912
+ * Type predicate to check if a query result has an error.
2913
+ * Narrows to include the error property.
2914
+ *
2915
+ * @example
2916
+ * if (isErrorResult(result)) {
2917
+ * console.error(result.error); // error is E, not undefined
2918
+ * }
2919
+ */
2920
+ declare function isErrorResult<T, E = Error>(result: QueryResult<T, E> | QueryResultNullable<T, E>): result is (QueryResult<T, E> | QueryResultNullable<T, E>) & {
2921
+ readonly isError: true;
2922
+ readonly error: E;
3246
2923
  };
3247
- type SaveDraftInput = {
3248
- draft_message: {
3249
- body?: string | null;
3250
- replied_to_id?: number | null;
3251
- attachments_attributes?: (MessageAttachmentInput & {
3252
- id?: number;
3253
- _destroy?: boolean;
3254
- })[];
3255
- };
2924
+ /**
2925
+ * Type predicate to check if a query result is in idle state (not loading, no error, has data).
2926
+ *
2927
+ * @example
2928
+ * if (isIdle(result)) {
2929
+ * // Safe to access and render data
2930
+ * }
2931
+ */
2932
+ declare function isIdle<T, E = Error>(result: QueryResult<T, E> | QueryResultNullable<T, E>): boolean;
2933
+ /**
2934
+ * Type-safe property selector for hook results.
2935
+ * Uses K extends keyof T constraint (generics-function-constraints rule).
2936
+ *
2937
+ * @typeParam T - The data object type
2938
+ * @typeParam K - Key of T (constrained to actual keys)
2939
+ *
2940
+ * @example
2941
+ * const users = [{ name: "Alice", age: 30 }];
2942
+ * const names = selectProperty(users, "name"); // string[]
2943
+ * const ages = selectProperty(users, "age"); // number[]
2944
+ * selectProperty(users, "invalid"); // Error: "invalid" not in "name" | "age"
2945
+ */
2946
+ declare function selectProperty<T, K extends keyof T>(items: readonly T[], key: K): T[K][];
2947
+ /**
2948
+ * Type-safe property getter for a single item.
2949
+ * Returns undefined if item is null/undefined.
2950
+ *
2951
+ * @typeParam T - The data object type
2952
+ * @typeParam K - Key of T (constrained to actual keys)
2953
+ */
2954
+ declare function getProperty<T, K extends keyof T>(item: T | null | undefined, key: K): T[K] | undefined;
2955
+ /**
2956
+ * Generic type for hooks that fetch a single resource by ID.
2957
+ * Useful for creating consistent API across different resource types.
2958
+ *
2959
+ * @typeParam T - The resource type
2960
+ * @typeParam E - The error type (defaults to Error)
2961
+ */
2962
+ type UseSingleResourceHook<T, E = Error> = (id: string) => QueryResultNullable<T, E>;
2963
+ /**
2964
+ * Generic type for hooks that fetch a list of resources with optional params.
2965
+ * Uses generics-default-type-parameters for the params type.
2966
+ *
2967
+ * @typeParam T - The item type
2968
+ * @typeParam P - The params type (defaults to empty object)
2969
+ * @typeParam E - The error type (defaults to Error)
2970
+ */
2971
+ type UseListResourceHook<T, P extends Record<string, unknown> = Record<string, never>, E = Error> = (params?: P) => ListQueryResult<T, E>;
2972
+ /**
2973
+ * Transforms a nullable result to a non-nullable one if data exists.
2974
+ * Useful when you've already checked hasData().
2975
+ */
2976
+ type WithData<R extends QueryResultNullable<unknown>> = R extends QueryResultNullable<infer T, infer E> ? QueryResultNullable<T, E> & {
2977
+ readonly data: T;
2978
+ } : never;
2979
+ /**
2980
+ * Activity slug constants as a const object.
2981
+ * Derive the ActivitySlug type from this single source of truth.
2982
+ */
2983
+ declare const ACTIVITY_SLUGS: {
2984
+ readonly abandonedCart: "abandoned_cart";
2985
+ readonly announcements: "announcements";
2986
+ readonly cartItemsAdded: "cart_items_added";
2987
+ readonly commentReply: "comment_reply";
2988
+ readonly directMessage: "direct_message";
2989
+ readonly fantasyPoint: "fantasy_point";
2990
+ readonly newLead: "new_lead";
2991
+ readonly orderPlaced: "order_placed";
2992
+ readonly pageViews: "page_views";
2993
+ readonly pageViewsContact: "page_views_contact";
2994
+ readonly tasks: "tasks";
2995
+ readonly upcomingEvent: "upcoming_event";
2996
+ readonly video: "video";
2997
+ readonly videoComplete: "video_complete";
2998
+ readonly videoCompleteContact: "video_complete_contact";
2999
+ readonly videoContact: "video_contact";
3000
+ readonly messageReceived: "message_received";
3001
+ readonly messageSent: "message_sent";
3002
+ readonly newCartItemsAdded: "new_cart_items_added";
3003
+ readonly smartLinkClicked: "smart_link_clicked";
3004
+ readonly reviewLeft: "review_left";
3256
3005
  };
3257
- interface DraftMessage {
3258
- id: number;
3259
- body: string | null;
3260
- created_at: string;
3261
- updated_at: string;
3262
- scheduled_at: string | null;
3263
- metadata?: unknown;
3264
- replied_to_message: ({
3265
- id: number;
3266
- } & Record<string, unknown>) | null;
3267
- mentioned_recipients: ({
3268
- id: number;
3269
- } & Record<string, unknown>)[];
3270
- attachments: Attachment[];
3271
- sender_recipient?: ReducedRecipient;
3272
- conversation?: {
3273
- id: number;
3274
- name: string | null;
3275
- } & Record<string, unknown>;
3006
+ /** Activity slug union type derived from ACTIVITY_SLUGS constant. */
3007
+ type ActivitySlug = (typeof ACTIVITY_SLUGS)[keyof typeof ACTIVITY_SLUGS];
3008
+ /** Type predicate to check if a string is a valid ActivitySlug. */
3009
+ declare function isActivitySlug(value: string): value is ActivitySlug;
3010
+ /** Transformed activity for display. */
3011
+ interface Activity {
3012
+ readonly id: number;
3013
+ readonly userName: string;
3014
+ readonly avatarUrl: string | null;
3015
+ readonly activityType: string;
3016
+ readonly targetName: string;
3017
+ readonly timestamp: string;
3018
+ readonly slug: ActivitySlug;
3276
3019
  }
3277
- type ListConnectedRecipientsInput = {
3278
- kind?: "external" | "sms" | "email" | "internal";
3279
- filterrific?: Record<string, unknown>;
3280
- per_page?: number;
3281
- page?: number;
3282
- };
3283
- //#endregion
3284
- //#region ../../messaging/core/src/auth-types.d.ts
3285
- interface MessagingAuthContext {
3286
- readonly recipientId: number | null;
3287
- readonly companyId: number | null;
3288
- readonly currentUser: MessagingCurrentUser | null;
3289
- readonly isLoading: boolean;
3020
+ /** Description/rich text metadata for a calendar event. */
3021
+ interface CalendarEventDescription {
3022
+ readonly id?: number | null;
3023
+ readonly name?: string | null;
3024
+ readonly body?: string | null;
3025
+ readonly record_type?: string | null;
3026
+ readonly record_id?: number | null;
3027
+ readonly created_at?: string | null;
3028
+ readonly updated_at?: string | null;
3029
+ readonly locale?: string | null;
3290
3030
  }
3291
- interface MessagingCurrentUser {
3031
+ /** Calendar event data from the API. */
3032
+ interface CalendarEvent {
3292
3033
  readonly id: number;
3293
- readonly recipientId: number;
3294
- readonly firstName: string;
3295
- readonly lastName: string;
3296
- readonly email: string;
3297
- readonly imageUrl?: string;
3298
- readonly affiliateId?: number;
3034
+ readonly title: string;
3035
+ readonly description?: CalendarEventDescription | null;
3036
+ readonly color?: string | null;
3037
+ readonly url?: string | null;
3038
+ readonly start: string;
3039
+ readonly end: string;
3040
+ readonly active?: boolean | null;
3041
+ readonly time_zone?: string | null;
3042
+ readonly status?: string | null;
3043
+ readonly image_url?: string | null;
3044
+ readonly images?: readonly unknown[] | null;
3045
+ readonly venue?: string | null;
3046
+ readonly countries?: readonly string[] | null;
3047
+ readonly hasTomorrow?: boolean | null;
3048
+ readonly hasYesterday?: boolean | null;
3049
+ readonly isAllDay?: boolean;
3050
+ }
3051
+ /** Catch up suggestion data from the API. */
3052
+ interface CatchUp {
3053
+ readonly id: number;
3054
+ readonly suggestion_title: string;
3055
+ }
3056
+ /** MySite data returned by the hook. */
3057
+ interface MySiteData {
3058
+ readonly url: string | null;
3059
+ readonly views: number;
3060
+ readonly leads: number;
3061
+ readonly userName: string;
3062
+ }
3063
+ /** Transformed todo for display. */
3064
+ interface Todo {
3065
+ readonly id: number;
3066
+ readonly body: string;
3067
+ readonly dueAt: string | null;
3068
+ readonly completedAt: string | null;
3069
+ readonly createdAt: string;
3070
+ readonly contactName: string | null;
3299
3071
  }
3300
3072
  //#endregion
3301
- //#region ../../messaging/core/src/file-upload-types.d.ts
3073
+ //#region src/hooks/use-calendar-events.d.ts
3302
3074
  /**
3303
- * Generic file upload abstraction.
3304
- *
3305
- * These types are re-exported from messaging-core so that both
3306
- * messaging-ui (which owns the concrete hook) and external consumers
3307
- * can reference the same contracts without depending on the UI layer.
3075
+ * Result type for useCalendarEvents hook.
3076
+ * Uses QueryResult<CalendarEvent[]> with default Error type.
3308
3077
  */
3309
- type UploadResult = {
3310
- readonly url: string;
3311
- readonly size: number;
3312
- readonly mimetype: string;
3313
- readonly kind: string;
3314
- readonly metadata?: {
3315
- width: number;
3316
- height: number;
3317
- } | null;
3318
- };
3319
- type UploadCallbacks = {
3320
- onProgress: (progress: number) => void;
3321
- onSuccess: (result: UploadResult) => void;
3322
- onError: (error: Error) => void;
3323
- };
3324
- type FileUploader = {
3325
- uploadFile: (file: File, callbacks: UploadCallbacks) => {
3326
- abort: () => void;
3327
- };
3328
- };
3078
+ type UseCalendarEventsResult = QueryResult<CalendarEvent[]>;
3079
+ /**
3080
+ * Hook to fetch calendar events.
3081
+ * This is a stub implementation - override with your own data fetching logic.
3082
+ */
3083
+ declare function useCalendarEvents(): UseCalendarEventsResult;
3329
3084
  //#endregion
3330
- //#region ../../messaging/core/src/messaging-api.d.ts
3085
+ //#region src/hooks/use-todos.d.ts
3331
3086
  /**
3332
- * Interface defining all messaging API operations that core hooks need.
3333
- * Each app provides an implementation via {@link MessagingApiProvider},
3334
- * decoupling shared packages from concrete API clients.
3087
+ * Result type for useTodos hook.
3088
+ * Uses QueryResult<Todo[]> with default Error type.
3335
3089
  */
3336
- interface MessagingApi {
3337
- listConversations(input?: ListConversationsInput): Promise<Paginated<Conversation$1>>;
3338
- getConversation(conversationId: number): Promise<Conversation$1>;
3339
- findConversation(input: FindConversationInput): Promise<Conversation$1>;
3340
- createConversation(input: ConversationCreateInput): Promise<Conversation$1>;
3341
- getAnnouncementChannel(): Promise<Conversation$1>;
3342
- listMessages(conversationId: number, input?: {
3343
- preview?: boolean;
3344
- message_id?: number;
3345
- after?: number;
3346
- before?: number;
3347
- sorted_by?: string;
3348
- per_page?: number;
3349
- page?: number;
3350
- }): Promise<Paginated<FluidMessage>>;
3351
- createMessage(conversationId: number, input: CreateMessageInput): Promise<FluidMessage>;
3352
- replyToMessage(conversationId: number, messageId: number, input: CreateMessageInput): Promise<FluidMessage>;
3353
- reactToMessage(conversationId: number, input: {
3354
- message_id: number;
3355
- reaction: string;
3356
- }): Promise<string>;
3357
- unreactToMessage(conversationId: number, input: {
3358
- message_id: number;
3359
- }): Promise<string>;
3360
- pinMessage(conversationId: number, messageId: number): Promise<MessagePinResponse>;
3361
- unpinMessage(conversationId: number, messageId: number): Promise<MessagePinResponse>;
3362
- listPinnedMessages(conversationId: number, input?: {
3363
- sorted_by?: string;
3364
- per_page?: number;
3365
- page?: number;
3366
- }): Promise<Paginated<FluidMessage>>;
3367
- listScheduledMessages(conversationId: number, input?: {
3368
- per_page?: number;
3369
- page?: number;
3370
- }): Promise<Paginated<FluidMessage>>;
3371
- createScheduledMessage(conversationId: number, input: ScheduledMessageInput): Promise<FluidMessage>;
3372
- updateScheduledMessage(conversationId: number, id: number, input: ScheduledMessageInput): Promise<FluidMessage>;
3373
- destroyScheduledMessage(conversationId: number, id: number): Promise<{
3374
- success: boolean;
3375
- message: string;
3376
- }>;
3377
- listMyScheduledMessages(input?: {
3378
- per_page?: number;
3379
- page?: number;
3380
- }): Promise<Paginated<DraftMessage>>;
3381
- saveDraft(conversationId: number, input: SaveDraftInput): Promise<DraftMessage | Record<string, never>>;
3382
- destroyDraft(conversationId: number): Promise<unknown>;
3383
- searchRecipientsCount(input: {
3384
- filter: Record<string, unknown>;
3385
- }): Promise<RecipientSearchCount>;
3386
- listConnectedRecipients(input: ListConnectedRecipientsInput): Promise<Paginated<Recipient | WithContactRecipient>>;
3387
- }
3090
+ type UseTodosResult = QueryResult<Todo[]>;
3091
+ /**
3092
+ * Hook to fetch todo items.
3093
+ * This is a stub implementation - override with your own data fetching logic.
3094
+ */
3095
+ declare function useTodos(): UseTodosResult;
3388
3096
  //#endregion
3389
- //#region src/messaging/use-messaging-auth.d.ts
3390
- declare function useMessagingAuth(): MessagingAuthContext;
3097
+ //#region src/hooks/use-activities.d.ts
3098
+ /**
3099
+ * Result type for useActivities hook.
3100
+ * Uses QueryResult generic with Activity[] and default Error type.
3101
+ */
3102
+ type UseActivitiesResult = QueryResult<Activity[]>;
3103
+ /**
3104
+ * Hook to fetch recent activities.
3105
+ * This is a stub implementation - override with your own data fetching logic.
3106
+ */
3107
+ declare function useActivities(): UseActivitiesResult;
3108
+ //#endregion
3109
+ //#region src/hooks/use-catchups.d.ts
3110
+ /**
3111
+ * Result type for useCatchUps hook.
3112
+ * Uses QueryResult<CatchUp[]> with default Error type.
3113
+ */
3114
+ type UseCatchUpsResult = QueryResult<CatchUp[]>;
3115
+ /**
3116
+ * Hook to fetch catch up items.
3117
+ * This is a stub implementation - override with your own data fetching logic.
3118
+ */
3119
+ declare function useCatchUps(): UseCatchUpsResult;
3391
3120
  //#endregion
3392
- //#region ../../messaging/api-client/src/client.d.ts
3121
+ //#region src/hooks/use-mysite.d.ts
3393
3122
  /**
3394
- * Configuration for the messaging API client.
3395
- * The consuming app provides auth headers and base URL.
3123
+ * Result type for useMySite hook.
3124
+ * Uses QueryResultNullable since MySite data may not be available.
3396
3125
  */
3397
- interface MessagingApiConfig {
3398
- baseUrl: string;
3399
- getHeaders: () => Record<string, string> | Promise<Record<string, string>>;
3400
- onAuthError?: () => void;
3401
- }
3402
- //#endregion
3403
- //#region src/messaging/use-messaging-config.d.ts
3404
- interface MessagingConfig {
3405
- readonly apiConfig: MessagingApiConfig;
3406
- readonly messagingApi: MessagingApi;
3407
- readonly websocketUrl: string;
3408
- }
3409
- declare function useMessagingConfig(): MessagingConfig;
3126
+ type UseMySiteResult = QueryResultNullable<MySiteData>;
3127
+ /**
3128
+ * Hook to fetch MySite data.
3129
+ * This is a stub implementation - override with your own data fetching logic.
3130
+ */
3131
+ declare function useMySite(): UseMySiteResult;
3410
3132
  //#endregion
3411
- //#region src/messaging/fluid-file-uploader.d.ts
3133
+ //#region src/hooks/use-conversations.d.ts
3412
3134
  /**
3413
- * Creates a FileUploader that uploads to Filestack using the REST API.
3135
+ * Result type for useConversations hook.
3136
+ * Uses QueryResult<Conversation[]> with default Error type.
3137
+ */
3138
+ type UseConversationsResult = QueryResult<Conversation[]>;
3139
+ /**
3140
+ * Hook to fetch all conversations.
3141
+ * This is a stub implementation - override with your own data fetching logic.
3414
3142
  *
3415
- * @param apiKey - Filestack API key. If falsy, returns a noop uploader
3416
- * that rejects uploads with a helpful error message.
3143
+ * @returns UseConversationsResult with empty data array
3144
+ *
3145
+ * @example
3146
+ * ```tsx
3147
+ * const { data: conversations, isLoading, isError } = useConversations();
3148
+ *
3149
+ * if (isLoading) return <Loading />;
3150
+ * if (isError) return <Error />;
3151
+ *
3152
+ * return conversations.map(conv => <ConversationItem key={conv.id} {...conv} />);
3153
+ * ```
3417
3154
  */
3418
- declare function createFluidFileUploader(apiKey: string | undefined): FileUploader;
3155
+ declare function useConversations(): UseConversationsResult;
3156
+ /**
3157
+ * Result type for useConversationMessages hook.
3158
+ * Uses QueryResult<Message[]> with default Error type.
3159
+ */
3160
+ type UseConversationMessagesResult = QueryResult<Message[]>;
3161
+ /**
3162
+ * Hook to fetch messages for a specific conversation.
3163
+ * This is a stub implementation - override with your own data fetching logic.
3164
+ *
3165
+ * @param conversationId - The ID of the conversation to fetch messages for
3166
+ * @returns UseConversationMessagesResult with empty data array
3167
+ *
3168
+ * @example
3169
+ * ```tsx
3170
+ * const { data: messages, isLoading, isError } = useConversationMessages(conversationId);
3171
+ *
3172
+ * if (isLoading) return <Loading />;
3173
+ * if (isError) return <Error />;
3174
+ *
3175
+ * return messages.map(msg => <MessageBubble key={msg.id} {...msg} />);
3176
+ * ```
3177
+ */
3178
+ declare function useConversationMessages(_conversationId: string): UseConversationMessagesResult;
3419
3179
  //#endregion
3420
- //#region ../core/src/registries/property-schema-types.d.ts
3180
+ //#region src/hooks/use-contacts.d.ts
3421
3181
  /**
3422
- * Tab configuration for organizing properties
3182
+ * Type predicate to check if a status string is a valid ContactStatus.
3183
+ * Enables runtime validation with type narrowing.
3423
3184
  */
3424
- interface TabConfig {
3425
- /** Unique identifier for the tab */
3426
- id: string;
3427
- /** Display label for the tab */
3428
- label: string;
3185
+ declare function isContactStatus(value: string): value is ContactStatus;
3186
+ /**
3187
+ * Parameters for filtering and paginating contacts.
3188
+ * Uses readonly properties and proper ContactStatus type for status.
3189
+ */
3190
+ interface UseContactsParams {
3191
+ /** Search query to filter contacts by name, email, or company */
3192
+ readonly search?: string;
3193
+ /** Filter contacts by status - uses ContactStatus union type for type safety */
3194
+ readonly status?: ContactStatus;
3195
+ /** Maximum number of contacts to return */
3196
+ readonly limit?: number;
3429
3197
  }
3430
3198
  /**
3431
- * Property field type constant - single source of truth for field types.
3432
- * Use PROPERTY_FIELD_TYPES.text instead of "text" for type-safe comparisons.
3199
+ * Result type for the useContacts hook.
3200
+ * Uses ListQueryResult<Contact> with totalCount and default Error type.
3433
3201
  */
3434
- declare const PROPERTY_FIELD_TYPES: {
3435
- readonly text: "text";
3436
- readonly textarea: "textarea";
3437
- readonly number: "number";
3438
- readonly boolean: "boolean";
3439
- readonly select: "select";
3440
- readonly color: "color";
3441
- readonly range: "range";
3442
- readonly dataSource: "dataSource";
3443
- readonly resource: "resource";
3444
- readonly image: "image";
3445
- readonly alignment: "alignment";
3446
- readonly slider: "slider";
3447
- readonly colorPicker: "colorPicker";
3448
- readonly sectionHeader: "sectionHeader";
3449
- readonly separator: "separator";
3450
- readonly buttonGroup: "buttonGroup";
3451
- readonly colorSelect: "colorSelect";
3452
- readonly sectionLayoutSelect: "sectionLayoutSelect";
3453
- readonly background: "background";
3454
- readonly contentPosition: "contentPosition";
3455
- readonly textSizeSelect: "textSizeSelect";
3456
- readonly cssUnit: "cssUnit";
3457
- readonly fontPicker: "fontPicker";
3458
- readonly stringArray: "stringArray";
3459
- readonly borderRadius: "borderRadius";
3460
- readonly screenPicker: "screenPicker";
3461
- };
3202
+ type UseContactsResult = ListQueryResult<Contact>;
3462
3203
  /**
3463
- * Union type of all property field types, derived from PROPERTY_FIELD_TYPES constant.
3464
- * @see deriving-typeof-for-object-keys pattern
3204
+ * Result type for the useContact hook.
3205
+ * Uses QueryResultNullable since a specific contact may not exist.
3465
3206
  */
3466
- type PropertyFieldType = (typeof PROPERTY_FIELD_TYPES)[keyof typeof PROPERTY_FIELD_TYPES];
3207
+ type UseContactResult = QueryResultNullable<Contact>;
3467
3208
  /**
3468
- * Runtime validation for property field types.
3469
- * @param value - The value to check
3470
- * @returns true if value is a valid PropertyFieldType
3209
+ * Hook to fetch a list of contacts with optional filtering and pagination.
3210
+ * This is a stub implementation - override with your own data fetching logic.
3211
+ *
3212
+ * @param params - Optional parameters for filtering and pagination
3213
+ * @returns Object containing contacts data, loading state, error state, and total count
3214
+ *
3215
+ * @example
3216
+ * ```tsx
3217
+ * const { data: contacts, isLoading, totalCount } = useContacts({
3218
+ * search: 'john',
3219
+ * status: 'active',
3220
+ * limit: 20
3221
+ * });
3222
+ * ```
3471
3223
  */
3472
- declare function isPropertyFieldType(value: string): value is PropertyFieldType;
3224
+ declare function useContacts(_params?: UseContactsParams): UseContactsResult;
3473
3225
  /**
3474
- * Base schema for a property field
3226
+ * Hook to fetch a single contact by ID.
3227
+ * This is a stub implementation - override with your own data fetching logic.
3228
+ *
3229
+ * @param contactId - The unique identifier of the contact to fetch
3230
+ * @returns Object containing contact data, loading state, and error state
3231
+ *
3232
+ * @example
3233
+ * ```tsx
3234
+ * const { data: contact, isLoading, isError } = useContact('contact-123');
3235
+ * ```
3475
3236
  */
3476
- interface PropertyFieldSchema {
3477
- /** Property key in the widget props */
3478
- key: string;
3479
- /** Display label for the field */
3480
- label: string;
3481
- /** Field type determines the input control */
3482
- type: PropertyFieldType;
3483
- /** Optional description/help text */
3484
- description?: string;
3485
- /** Optional default value */
3486
- defaultValue?: unknown;
3487
- /** Optional tab ID (must match a TabConfig id if widget has tabsConfig) */
3488
- tab?: string;
3489
- /** Optional group for organizing fields within a tab */
3490
- group?: string;
3491
- /**
3492
- * @deprecated Use requiresKeyValue instead
3493
- */
3494
- requiresKeyToBeTrue?: string;
3495
- /** Optional requires a specific key to have a specific value. Supports single condition or array (AND logic). */
3496
- requiresKeyValue?: {
3497
- key: string;
3498
- value: unknown;
3499
- } | Array<{
3500
- key: string;
3501
- value: unknown;
3502
- }>;
3237
+ declare function useContact(_contactId: string): UseContactResult;
3238
+ //#endregion
3239
+ //#region src/components/RequireAuth.d.ts
3240
+ interface RequireAuthProps {
3241
+ /** Content to render when authenticated */
3242
+ children: ReactNode;
3243
+ /** Component to show while checking authentication (default: AuthLoading) */
3244
+ fallback?: ReactNode;
3245
+ /** Component to show when not authenticated (default: AuthError) */
3246
+ errorComponent?: ReactNode;
3247
+ }
3248
+ /**
3249
+ * Component that protects content requiring authentication.
3250
+ *
3251
+ * **Important:** This provides UX-level protection only. It prevents
3252
+ * unauthenticated users from seeing the UI, but the real security
3253
+ * boundary is the server-side API. Client-side auth can always be
3254
+ * bypassed by modifying browser state.
3255
+ *
3256
+ * For defense-in-depth, configure `jwksUrl` in `FluidAuthConfig`
3257
+ * to enable client-side JWT signature verification.
3258
+ *
3259
+ * Shows different states based on auth status:
3260
+ * - Loading: Shows fallback (spinner by default)
3261
+ * - Not authenticated: Shows errorComponent (AuthError by default)
3262
+ * - Authenticated: Shows children
3263
+ *
3264
+ * @example
3265
+ * ```tsx
3266
+ * // Basic usage - shows default loading/error states
3267
+ * <RequireAuth>
3268
+ * <ProtectedContent />
3269
+ * </RequireAuth>
3270
+ *
3271
+ * // Custom loading state
3272
+ * <RequireAuth fallback={<CustomSpinner />}>
3273
+ * <ProtectedContent />
3274
+ * </RequireAuth>
3275
+ *
3276
+ * // Custom error component
3277
+ * <RequireAuth errorComponent={<LoginPrompt />}>
3278
+ * <ProtectedContent />
3279
+ * </RequireAuth>
3280
+ *
3281
+ * // Both custom
3282
+ * <RequireAuth
3283
+ * fallback={<SkeletonLoader />}
3284
+ * errorComponent={<RedirectToLogin />}
3285
+ * >
3286
+ * <Dashboard />
3287
+ * </RequireAuth>
3288
+ * ```
3289
+ */
3290
+ declare function RequireAuth({
3291
+ children,
3292
+ fallback,
3293
+ errorComponent
3294
+ }: RequireAuthProps): React.JSX.Element;
3295
+ //#endregion
3296
+ //#region src/components/AuthError.d.ts
3297
+ interface AuthErrorProps {
3298
+ /** Error message to display */
3299
+ message?: string;
3300
+ /** Optional title */
3301
+ title?: string;
3302
+ /** Optional children for custom content */
3303
+ children?: ReactNode;
3503
3304
  }
3504
3305
  /**
3505
- * Text field schema
3306
+ * Default authentication error component.
3307
+ *
3308
+ * Displays a simple error message when authentication fails.
3309
+ * Can be customized via props or replaced entirely in RequireAuth.
3310
+ *
3311
+ * @example
3312
+ * ```tsx
3313
+ * // Use with default message
3314
+ * <AuthError />
3315
+ *
3316
+ * // Use with custom message
3317
+ * <AuthError message="Session expired. Please log in again." />
3318
+ *
3319
+ * // Use with custom content
3320
+ * <AuthError>
3321
+ * <CustomLoginButton />
3322
+ * </AuthError>
3323
+ * ```
3506
3324
  */
3507
- interface TextFieldSchema extends PropertyFieldSchema {
3508
- type: "text";
3509
- placeholder?: string;
3510
- maxLength?: number;
3511
- }
3325
+ declare function AuthError({
3326
+ message,
3327
+ title,
3328
+ children
3329
+ }: AuthErrorProps): React.JSX.Element;
3512
3330
  /**
3513
- * Textarea field schema
3331
+ * Simple loading spinner component for auth loading state.
3514
3332
  */
3515
- interface TextareaFieldSchema extends PropertyFieldSchema {
3516
- type: "textarea";
3517
- placeholder?: string;
3518
- rows?: number;
3519
- maxLength?: number;
3520
- }
3333
+ declare function AuthLoading(): React.JSX.Element;
3334
+ //#endregion
3335
+ //#region ../../messaging/core/src/types.d.ts
3521
3336
  /**
3522
- * Number field schema
3337
+ * Domain types for the messaging package.
3338
+ *
3339
+ * These are owned by messaging-core and represent the contract that
3340
+ * any API adapter (current client, future BFF) must satisfy.
3341
+ * Consuming packages import from here — never from the API client directly.
3523
3342
  */
3524
- interface NumberFieldSchema extends PropertyFieldSchema {
3525
- type: "number";
3526
- min?: number;
3527
- max?: number;
3528
- step?: number;
3343
+ interface PaginationObject {
3344
+ pagination: {
3345
+ current: number;
3346
+ previous: number | null;
3347
+ next: number | null;
3348
+ per_page: number;
3349
+ pages: number;
3350
+ count: number;
3351
+ };
3529
3352
  }
3530
- /**
3531
- * Boolean field schema
3532
- */
3533
- interface BooleanFieldSchema extends PropertyFieldSchema {
3534
- type: "boolean";
3353
+ type Paginated<T> = [PaginationObject, {
3354
+ items: T[];
3355
+ }];
3356
+ interface AttachmentMetadata {
3357
+ width?: number;
3358
+ height?: number;
3535
3359
  }
3536
- /**
3537
- * Select field schema with type-safe option values.
3538
- * Uses StrictOmit to ensure "defaultValue" key exists on PropertyFieldSchema.
3539
- */
3540
- interface SelectFieldSchema<T extends string | number = string | number> extends StrictOmit<PropertyFieldSchema, "defaultValue"> {
3541
- type: "select";
3542
- options: Array<{
3543
- label: string;
3544
- value: T;
3545
- }>;
3546
- defaultValue?: T;
3360
+ interface Attachment {
3361
+ id: number;
3362
+ url: string;
3363
+ filename: string;
3364
+ kind: string;
3365
+ image_url: string | null;
3366
+ image_path: string | null;
3367
+ content_type: string | null;
3368
+ attachable_type: string | null;
3369
+ attachable_id: number | null;
3370
+ thumbnail_url: string | null;
3371
+ metadata: AttachmentMetadata | null;
3372
+ content_size: number | null;
3547
3373
  }
3548
- /**
3549
- * Color field schema
3550
- */
3551
- interface ColorFieldSchema extends PropertyFieldSchema {
3552
- type: "color";
3374
+ interface MessageAttachmentInput {
3375
+ url: string;
3376
+ filename: string;
3377
+ kind: string;
3378
+ content_type?: string;
3379
+ content_size?: number;
3380
+ metadata?: AttachmentMetadata;
3553
3381
  }
3554
- /**
3555
- * Range slider field schema
3556
- */
3557
- interface RangeFieldSchema extends PropertyFieldSchema {
3558
- type: "range";
3559
- min: number;
3560
- max: number;
3561
- step?: number;
3382
+ interface LinkPreview {
3383
+ url: string;
3384
+ title?: string | null;
3385
+ description?: string | null;
3386
+ images?: string[];
3387
+ videos?: string[];
3388
+ favicon?: string | null;
3389
+ error?: string | null;
3390
+ original_url?: string | null;
3562
3391
  }
3563
- /**
3564
- * Data source field schema for configuring widget data sources
3565
- */
3566
- interface DataSourceFieldSchema extends PropertyFieldSchema {
3567
- type: "dataSource";
3392
+ interface InfoMessageRecipient {
3393
+ id: number;
3394
+ first_name: string;
3395
+ last_name: string;
3568
3396
  }
3569
- /**
3570
- * Resource field schema for selecting a single resource from the selection modal
3571
- */
3572
- interface ResourceFieldSchema extends PropertyFieldSchema {
3573
- type: "resource";
3574
- /** Optional filter to specific shareable types */
3575
- allowedTypes?: string[];
3397
+ interface DefaultMessageMetadata {
3398
+ links: LinkPreview[];
3399
+ client_message_id?: string | number | null;
3576
3400
  }
3577
- /**
3578
- * Image field schema for selecting a single image from the image picker
3579
- */
3580
- interface ImageFieldSchema extends PropertyFieldSchema {
3581
- type: "image";
3401
+ interface SystemConversationUpdateMetadata {
3402
+ name: string;
3403
+ previous_name: string;
3404
+ client_message_id?: string | number | null;
3405
+ links?: LinkPreview[];
3582
3406
  }
3583
- /**
3584
- * Alignment field schema
3585
- */
3586
- interface AlignmentFieldSchema extends PropertyFieldSchema {
3587
- type: "alignment";
3588
- options: {
3589
- verticalEnabled: boolean;
3590
- horizontalEnabled: boolean;
3591
- };
3592
- defaultValue?: AlignOptions;
3407
+ interface SystemConversationCreatedMetadata {
3408
+ conversation_name: string;
3409
+ description?: string;
3410
+ member_count: number;
3411
+ auto_add_recipients: boolean;
3412
+ client_message_id?: string | number | null;
3413
+ links?: LinkPreview[];
3593
3414
  }
3594
- /**
3595
- * Slider field schema with optional unit suffix (e.g., "rem", "px")
3596
- */
3597
- interface SliderFieldSchema extends PropertyFieldSchema {
3598
- type: "slider";
3599
- min: number;
3600
- max: number;
3601
- step?: number;
3602
- unit?: string;
3415
+ interface SystemRecipientActionMetadata {
3416
+ recipient_ids_added?: number[];
3417
+ recipient_ids_removed?: number[];
3418
+ recipient_ids_left?: number[];
3419
+ recipient_ids_joined?: number[];
3420
+ recipient_added?: InfoMessageRecipient[];
3421
+ recipient_removed?: InfoMessageRecipient[];
3422
+ recipient_left?: InfoMessageRecipient[];
3423
+ recipient_joined?: InfoMessageRecipient[];
3424
+ client_message_id?: string | number | null;
3425
+ links?: LinkPreview[];
3426
+ }
3427
+ interface InfoMessageMetadataShape {
3428
+ recipient_added?: InfoMessageRecipient[];
3429
+ recipient_ids_added?: number[];
3430
+ recipient_removed?: InfoMessageRecipient[];
3431
+ recipient_ids_removed?: number[];
3432
+ links?: LinkPreview[];
3433
+ client_message_id?: string | number | null;
3434
+ }
3435
+ type MessageMetadata = DefaultMessageMetadata | null | SystemConversationUpdateMetadata | SystemConversationCreatedMetadata | SystemRecipientActionMetadata | InfoMessageMetadataShape;
3436
+ interface Recipient {
3437
+ id: number;
3438
+ first_name: string;
3439
+ last_name: string;
3440
+ avatar_url: string | null;
3441
+ image_url: string | null;
3442
+ receivable_id: number;
3443
+ receivable_type: "Contact" | "UserCompany";
3444
+ discarded_at: string | null;
3445
+ left_conversation_at: string | null;
3446
+ blocked: boolean | null;
3447
+ country_name: string | null;
3448
+ pro_user: boolean;
3449
+ avatar_background: string | null;
3450
+ email?: string | null;
3451
+ phone?: string | null;
3452
+ status?: "online" | "offline" | "away";
3453
+ last_online?: string | null;
3454
+ "conversation_messaging_enabled?"?: boolean;
3455
+ }
3456
+ interface ReducedRecipient {
3457
+ id: number;
3458
+ first_name: string;
3459
+ last_name: string;
3460
+ image_url: string | null;
3461
+ discarded_at: string | null;
3462
+ blocked: boolean | null;
3463
+ blocker: boolean | null;
3464
+ avatar_background: string | null;
3465
+ seen_at?: string | null;
3466
+ email?: string | null;
3467
+ phone?: string | null;
3468
+ pro_user?: boolean;
3469
+ }
3470
+ interface SlimmedRecipient {
3471
+ id: number;
3472
+ first_name: string;
3473
+ last_name: string;
3474
+ discarded_at: string | null;
3475
+ blocked: boolean | null;
3476
+ avatar_background: string | null;
3477
+ email?: string | null;
3478
+ phone?: string | null;
3479
+ removed_at?: string | null;
3480
+ }
3481
+ interface WithContactRecipient {
3482
+ id: number;
3483
+ email?: string | null;
3484
+ phone?: string | null;
3485
+ first_name?: string | null;
3486
+ last_name?: string | null;
3487
+ image_url: string | null;
3488
+ receivable_id: number;
3489
+ receivable_type: "Contact";
3603
3490
  }
3604
- /**
3605
- * Color picker field schema with optional swatches
3606
- */
3607
- interface ColorPickerFieldSchema extends PropertyFieldSchema {
3608
- type: "colorPicker";
3609
- swatches?: string[];
3491
+ interface RecipientSearchCount {
3492
+ meta: {
3493
+ count: number;
3494
+ };
3610
3495
  }
3611
- /**
3612
- * Section header field schema for visual grouping
3613
- */
3614
- interface SectionHeaderFieldSchema extends PropertyFieldSchema {
3615
- type: "sectionHeader";
3616
- subtitle?: string;
3496
+ type FluidMessage = {
3497
+ id: number;
3498
+ body: string;
3499
+ type: string;
3500
+ created_at: string;
3501
+ updated_at?: string | null;
3502
+ deleted_at?: string | null;
3503
+ edited_at?: string | null;
3504
+ conversation_id: number;
3505
+ status: string;
3506
+ attachments: Attachment[];
3507
+ reaction_stats: Record<string, number> | null;
3508
+ reaction?: string | null;
3509
+ metadata?: MessageMetadata;
3510
+ emoji_only_count?: number;
3511
+ mentioned_recipients: SlimmedRecipient[];
3512
+ sent_at?: string;
3513
+ pinned?: boolean;
3514
+ scheduled_at?: string;
3515
+ replied_to_message?: ({
3516
+ id: number;
3517
+ } & Record<string, unknown>) | null;
3518
+ sender_recipient: ReducedRecipient;
3519
+ seen_by: unknown;
3520
+ seen_by_count: unknown;
3521
+ };
3522
+ interface MessagePinResponse {
3523
+ message: string;
3524
+ pinned: boolean;
3617
3525
  }
3618
- /**
3619
- * Separator field schema for visual separation
3620
- */
3621
- interface SeparatorFieldSchema extends PropertyFieldSchema {
3622
- type: "separator";
3526
+ interface BaseConversation {
3527
+ id: number;
3528
+ name: string;
3529
+ description: string | null;
3530
+ kind: string | null;
3531
+ type: string;
3532
+ status: string;
3533
+ created_at: string;
3534
+ pinned: boolean;
3535
+ unread_messages_count?: number | null;
3536
+ "sms_enabled?": boolean;
3537
+ draft_message: DraftMessage | null;
3538
+ "email_enabled?": boolean;
3539
+ conversation_type: string;
3540
+ "messaging_enabled?": boolean;
3541
+ broadcasting: boolean | null;
3542
+ total_recipients: number;
3543
+ unread?: boolean | null;
3544
+ image_url: string | null;
3545
+ auto_add_recipients?: boolean | null;
3546
+ muted?: boolean | null;
3547
+ announcing?: boolean | null;
3548
+ scheduled_messages_count?: number | null;
3549
+ avatar_background_color: string | null;
3550
+ avatar_emoji: string | null;
3551
+ avatar_url: string | null;
3552
+ pinned_messages_count?: number | null;
3553
+ recipients: Recipient[];
3554
+ creator: ReducedRecipient | null;
3623
3555
  }
3624
- /**
3625
- * Button group field schema.
3626
- * Uses StrictOmit to ensure "defaultValue" key exists on PropertyFieldSchema.
3627
- */
3628
- interface ButtonGroupFieldSchema<T extends string | number = string | number> extends StrictOmit<PropertyFieldSchema, "defaultValue"> {
3629
- type: "buttonGroup";
3630
- options: Array<{
3631
- label?: string;
3632
- icon?: LucideIcon;
3633
- value: T;
3634
- }>;
3635
- defaultValue?: T;
3556
+ interface EmailConversation extends BaseConversation {
3557
+ type: "EmailConversation";
3558
+ kind: null;
3559
+ "sms_enabled?": false;
3560
+ "email_enabled?": true;
3561
+ broadcasting: null;
3636
3562
  }
3637
- /**
3638
- * Color select field schema
3639
- */
3640
- interface ColorSelectFieldSchema extends PropertyFieldSchema {
3641
- type: "colorSelect";
3642
- defaultValue?: ColorOptions;
3643
- excludeColors?: ColorOptions[];
3563
+ interface ChannelConversation extends BaseConversation {
3564
+ type: "ChannelConversation";
3565
+ kind: "channel";
3566
+ "sms_enabled?": false;
3567
+ "email_enabled?": false;
3644
3568
  }
3645
- /**
3646
- * Section layout select field schema for visual masonry layout selector
3647
- */
3648
- interface SectionLayoutSelectFieldSchema extends PropertyFieldSchema {
3649
- type: "sectionLayoutSelect";
3650
- defaultValue?: SectionLayoutType;
3569
+ interface GroupConversation extends BaseConversation {
3570
+ type: "GroupConversation";
3571
+ kind: "group";
3572
+ "sms_enabled?": false;
3573
+ "email_enabled?": false;
3574
+ broadcasting: null;
3651
3575
  }
3652
- /**
3653
- * Background field combines resource selection and color properties.
3654
- * Uses StrictOmit to exclude conflicting "type" discriminant from parents.
3655
- */
3656
- interface BackgroundFieldSchema extends StrictOmit<ResourceFieldSchema, "type">, StrictOmit<ColorFieldSchema, "type"> {
3657
- type: "background";
3576
+ interface SmsConversation extends BaseConversation {
3577
+ type: "SmsConversation";
3578
+ kind: null;
3579
+ "sms_enabled?": true;
3580
+ "email_enabled?": false;
3581
+ broadcasting: null;
3658
3582
  }
3659
- /**
3660
- * Content position field schema for 3x3 grid position picker
3661
- */
3662
- interface ContentPositionFieldSchema extends PropertyFieldSchema {
3663
- type: "contentPosition";
3664
- defaultValue?: string;
3583
+ interface DirectConversation extends BaseConversation {
3584
+ type: "DirectConversation";
3585
+ kind: "direct";
3586
+ "sms_enabled?": false;
3587
+ "email_enabled?": false;
3588
+ broadcasting: null;
3665
3589
  }
3666
- /**
3667
- * Text size select field schema for visual font size selector
3668
- */
3669
- interface TextSizeSelectFieldSchema extends PropertyFieldSchema {
3670
- type: "textSizeSelect";
3671
- defaultValue?: FontSizeOptions;
3590
+ interface BotConversation extends BaseConversation {
3591
+ type: "BotConversation";
3592
+ kind: "direct";
3593
+ "sms_enabled?": false;
3594
+ "email_enabled?": false;
3595
+ broadcasting: null;
3672
3596
  }
3673
- /**
3674
- * CSS unit type for height/width fields
3675
- */
3676
- type CssUnit = "px" | "rem" | "vh" | "%";
3677
- /**
3678
- * CSS unit field schema for numeric values with selectable units (px, rem, vh, %)
3679
- */
3680
- interface CssUnitFieldSchema extends PropertyFieldSchema {
3681
- type: "cssUnit";
3682
- minByUnit?: Partial<Record<CssUnit, number>>;
3683
- maxByUnit?: Partial<Record<CssUnit, number>>;
3684
- stepByUnit?: Partial<Record<CssUnit, number>>;
3685
- allowedUnits?: CssUnit[];
3686
- defaultUnit?: CssUnit;
3597
+ interface DownlineConversation extends BaseConversation {
3598
+ type: "DownlineConversation";
3599
+ kind: "downline";
3600
+ "sms_enabled?": false;
3601
+ "email_enabled?": false;
3602
+ broadcasting: null;
3603
+ }
3604
+ type Conversation$1 = EmailConversation | ChannelConversation | GroupConversation | SmsConversation | DirectConversation | BotConversation | DownlineConversation;
3605
+ type ListConversationsInput = {
3606
+ status?: "open" | "closed";
3607
+ kind?: "direct" | "group" | "channel";
3608
+ pinned?: boolean;
3609
+ per_page?: number;
3610
+ page?: number;
3611
+ template?: string;
3612
+ search?: string;
3613
+ filterrific?: Record<string, unknown>;
3614
+ } | undefined;
3615
+ type ConversationCreateInput = {
3616
+ conversation: {
3617
+ kind?: string;
3618
+ type?: string;
3619
+ name?: string;
3620
+ description?: string | null;
3621
+ broadcasting?: boolean;
3622
+ filter?: Record<string, unknown>;
3623
+ auto_add_recipients?: boolean;
3624
+ };
3625
+ recipients?: {
3626
+ id?: number;
3627
+ uid?: number;
3628
+ email?: string;
3629
+ phone?: string;
3630
+ first_name?: string;
3631
+ last_name?: string;
3632
+ image_url?: string;
3633
+ }[];
3634
+ };
3635
+ type FindConversationInput = {
3636
+ contact_id: number;
3637
+ conversation_type: "ChannelConversation" | "DirectConversation" | "GroupConversation" | "SmsConversation" | "EmailConversation" | "channel" | "direct" | "group";
3638
+ };
3639
+ type CreateMessageInput = {
3640
+ message: {
3641
+ body?: string;
3642
+ theme?: string;
3643
+ subject?: string;
3644
+ type?: string;
3645
+ attachments_attributes?: MessageAttachmentInput[];
3646
+ };
3647
+ client_message_id?: string | number;
3648
+ };
3649
+ type ScheduledMessageInput = {
3650
+ scheduled_message: {
3651
+ body?: string;
3652
+ theme?: string;
3653
+ scheduled_at: string;
3654
+ attachments_attributes?: MessageAttachmentInput[];
3655
+ type?: string;
3656
+ };
3657
+ };
3658
+ type SaveDraftInput = {
3659
+ draft_message: {
3660
+ body?: string | null;
3661
+ replied_to_id?: number | null;
3662
+ attachments_attributes?: (MessageAttachmentInput & {
3663
+ id?: number;
3664
+ _destroy?: boolean;
3665
+ })[];
3666
+ };
3667
+ };
3668
+ interface DraftMessage {
3669
+ id: number;
3670
+ body: string | null;
3671
+ created_at: string;
3672
+ updated_at: string;
3673
+ scheduled_at: string | null;
3674
+ metadata?: unknown;
3675
+ replied_to_message: ({
3676
+ id: number;
3677
+ } & Record<string, unknown>) | null;
3678
+ mentioned_recipients: ({
3679
+ id: number;
3680
+ } & Record<string, unknown>)[];
3681
+ attachments: Attachment[];
3682
+ sender_recipient?: ReducedRecipient;
3683
+ conversation?: {
3684
+ id: number;
3685
+ name: string | null;
3686
+ } & Record<string, unknown>;
3687
3687
  }
3688
- /**
3689
- * Font picker field schema for Google Fonts selection
3690
- */
3691
- interface FontPickerFieldSchema extends PropertyFieldSchema {
3692
- type: "fontPicker";
3693
- placeholder?: string;
3688
+ type ListConnectedRecipientsInput = {
3689
+ kind?: "external" | "sms" | "email" | "internal";
3690
+ filterrific?: Record<string, unknown>;
3691
+ per_page?: number;
3692
+ page?: number;
3693
+ };
3694
+ //#endregion
3695
+ //#region ../../messaging/core/src/auth-types.d.ts
3696
+ interface MessagingAuthContext {
3697
+ readonly recipientId: number | null;
3698
+ readonly companyId: number | null;
3699
+ readonly currentUser: MessagingCurrentUser | null;
3700
+ readonly isLoading: boolean;
3694
3701
  }
3695
- /**
3696
- * String array field schema for managing lists of text items
3697
- */
3698
- interface StringArrayFieldSchema extends PropertyFieldSchema {
3699
- type: "stringArray";
3700
- placeholder?: string;
3701
- defaultValue?: string[];
3702
+ interface MessagingCurrentUser {
3703
+ readonly id: number;
3704
+ readonly recipientId: number;
3705
+ readonly firstName: string;
3706
+ readonly lastName: string;
3707
+ readonly email: string;
3708
+ readonly imageUrl?: string;
3709
+ readonly affiliateId?: number;
3702
3710
  }
3711
+ //#endregion
3712
+ //#region ../../messaging/core/src/file-upload-types.d.ts
3703
3713
  /**
3704
- * Border radius composite field schema for controlling 4 corners with a single field.
3705
- * Maps to 4 individual widget prop keys (topLeft, topRight, bottomLeft, bottomRight).
3714
+ * Generic file upload abstraction.
3715
+ *
3716
+ * These types are re-exported from messaging-core so that both
3717
+ * messaging-ui (which owns the concrete hook) and external consumers
3718
+ * can reference the same contracts without depending on the UI layer.
3706
3719
  */
3707
- interface BorderRadiusFieldSchema extends PropertyFieldSchema {
3708
- type: "borderRadius";
3709
- keys: {
3710
- topLeft: string;
3711
- topRight: string;
3712
- bottomLeft: string;
3713
- bottomRight: string;
3720
+ type UploadResult = {
3721
+ readonly url: string;
3722
+ readonly size: number;
3723
+ readonly mimetype: string;
3724
+ readonly kind: string;
3725
+ readonly metadata?: {
3726
+ width: number;
3727
+ height: number;
3728
+ } | null;
3729
+ };
3730
+ type UploadCallbacks = {
3731
+ onProgress: (progress: number) => void;
3732
+ onSuccess: (result: UploadResult) => void;
3733
+ onError: (error: Error) => void;
3734
+ };
3735
+ type FileUploader = {
3736
+ uploadFile: (file: File, callbacks: UploadCallbacks) => {
3737
+ abort: () => void;
3714
3738
  };
3715
- defaultValue?: BorderRadiusOptions;
3716
- }
3717
- /**
3718
- * Screen picker field schema for selecting a portal screen (navigation, system, or available)
3719
- */
3720
- interface ScreenPickerFieldSchema extends PropertyFieldSchema {
3721
- type: "screenPicker";
3722
- /** Whether to include system navigation items in the picker */
3723
- includeSystemItems?: boolean;
3724
- }
3725
- /**
3726
- * Union of all field schema types
3727
- */
3728
- type PropertyField = TextFieldSchema | TextareaFieldSchema | NumberFieldSchema | BooleanFieldSchema | SelectFieldSchema<string | number> | ColorFieldSchema | RangeFieldSchema | DataSourceFieldSchema | ResourceFieldSchema | ImageFieldSchema | AlignmentFieldSchema | SliderFieldSchema | ColorPickerFieldSchema | SectionHeaderFieldSchema | SeparatorFieldSchema | ButtonGroupFieldSchema<string | number> | ColorSelectFieldSchema | SectionLayoutSelectFieldSchema | BackgroundFieldSchema | ContentPositionFieldSchema | TextSizeSelectFieldSchema | CssUnitFieldSchema | FontPickerFieldSchema | StringArrayFieldSchema | BorderRadiusFieldSchema | ScreenPickerFieldSchema;
3729
- /**
3730
- * Schema for per-item configuration in custom data sources.
3731
- * Widgets can define this to allow users to configure widget-specific
3732
- * settings for each selected item (e.g., title, description, button).
3733
- */
3734
- interface ItemConfigSchema {
3735
- /** Fields available for per-item configuration */
3736
- fields: PropertyField[];
3737
- /** Optional description shown at top of item config panel */
3738
- description?: string;
3739
- }
3739
+ };
3740
+ //#endregion
3741
+ //#region ../../messaging/core/src/messaging-api.d.ts
3740
3742
  /**
3741
- * Schema for a widget's editable properties
3743
+ * Interface defining all messaging API operations that core hooks need.
3744
+ * Each app provides an implementation via {@link MessagingApiProvider},
3745
+ * decoupling shared packages from concrete API clients.
3742
3746
  */
3743
- interface WidgetPropertySchema {
3744
- /** Widget type this schema applies to */
3745
- widgetType: WidgetType;
3746
- /** Display name for the widget */
3747
- displayName: string;
3748
- /** Optional tab configuration - if present, tabs are enabled */
3749
- tabsConfig?: TabConfig[];
3750
- /** Editable property fields */
3751
- fields: PropertyField[];
3752
- /** Optional custom validator function */
3753
- validate?: (props: Record<string, unknown>) => string | null;
3754
- /** Props that can be populated from data sources */
3755
- dataSourceTargetProps?: string[];
3756
- /** Optional schema for per-item configurations in custom data sources */
3757
- itemConfigSchema?: ItemConfigSchema;
3747
+ interface MessagingApi {
3748
+ listConversations(input?: ListConversationsInput): Promise<Paginated<Conversation$1>>;
3749
+ getConversation(conversationId: number): Promise<Conversation$1>;
3750
+ findConversation(input: FindConversationInput): Promise<Conversation$1>;
3751
+ createConversation(input: ConversationCreateInput): Promise<Conversation$1>;
3752
+ getAnnouncementChannel(): Promise<Conversation$1>;
3753
+ listMessages(conversationId: number, input?: {
3754
+ preview?: boolean;
3755
+ message_id?: number;
3756
+ after?: number;
3757
+ before?: number;
3758
+ sorted_by?: string;
3759
+ per_page?: number;
3760
+ page?: number;
3761
+ }): Promise<Paginated<FluidMessage>>;
3762
+ createMessage(conversationId: number, input: CreateMessageInput): Promise<FluidMessage>;
3763
+ replyToMessage(conversationId: number, messageId: number, input: CreateMessageInput): Promise<FluidMessage>;
3764
+ reactToMessage(conversationId: number, input: {
3765
+ message_id: number;
3766
+ reaction: string;
3767
+ }): Promise<string>;
3768
+ unreactToMessage(conversationId: number, input: {
3769
+ message_id: number;
3770
+ }): Promise<string>;
3771
+ pinMessage(conversationId: number, messageId: number): Promise<MessagePinResponse>;
3772
+ unpinMessage(conversationId: number, messageId: number): Promise<MessagePinResponse>;
3773
+ listPinnedMessages(conversationId: number, input?: {
3774
+ sorted_by?: string;
3775
+ per_page?: number;
3776
+ page?: number;
3777
+ }): Promise<Paginated<FluidMessage>>;
3778
+ listScheduledMessages(conversationId: number, input?: {
3779
+ per_page?: number;
3780
+ page?: number;
3781
+ }): Promise<Paginated<FluidMessage>>;
3782
+ createScheduledMessage(conversationId: number, input: ScheduledMessageInput): Promise<FluidMessage>;
3783
+ updateScheduledMessage(conversationId: number, id: number, input: ScheduledMessageInput): Promise<FluidMessage>;
3784
+ destroyScheduledMessage(conversationId: number, id: number): Promise<{
3785
+ success: boolean;
3786
+ message: string;
3787
+ }>;
3788
+ listMyScheduledMessages(input?: {
3789
+ per_page?: number;
3790
+ page?: number;
3791
+ }): Promise<Paginated<DraftMessage>>;
3792
+ saveDraft(conversationId: number, input: SaveDraftInput): Promise<DraftMessage | Record<string, never>>;
3793
+ destroyDraft(conversationId: number): Promise<unknown>;
3794
+ searchRecipientsCount(input: {
3795
+ filter: Record<string, unknown>;
3796
+ }): Promise<RecipientSearchCount>;
3797
+ listConnectedRecipients(input: ListConnectedRecipientsInput): Promise<Paginated<Recipient | WithContactRecipient>>;
3758
3798
  }
3759
3799
  //#endregion
3760
- //#region ../core/src/registries/field-helpers.d.ts
3761
- /**
3762
- * Gap value mapping - use `as const satisfies` for compile-time validation
3763
- * with literal type preservation.
3764
- */
3765
- declare const gapValues: {
3766
- readonly none: 0;
3767
- readonly xs: 1;
3768
- readonly sm: 2;
3769
- readonly md: 4;
3770
- readonly lg: 6;
3771
- readonly xl: 8;
3772
- };
3800
+ //#region src/messaging/use-messaging-auth.d.ts
3801
+ declare function useMessagingAuth(): MessagingAuthContext;
3773
3802
  //#endregion
3774
- //#region ../core/src/registries/container-types.d.ts
3803
+ //#region ../../messaging/api-client/src/client.d.ts
3775
3804
  /**
3776
- * Interface for container widget behavior.
3777
- * Container widgets can hold and manage child widgets.
3778
- * Note: Children can be null for sparse arrays (e.g., grid layouts with empty cells)
3805
+ * Configuration for the messaging API client.
3806
+ * The consuming app provides auth headers and base URL.
3779
3807
  */
3780
- interface ContainerWidgetBehavior {
3781
- /** Identifies this widget type as a container */
3782
- isContainer: true;
3783
- /** Gets children from the widget's props */
3784
- getChildren: (props: Record<string, unknown>) => (WidgetSchema | null)[];
3785
- /** Creates new props with updated children */
3786
- setChildren: (props: Record<string, unknown>, children: (WidgetSchema | null)[]) => Record<string, unknown>;
3787
- /** Optional: Check if this container accepts a specific widget type */
3788
- canAcceptChild?: (childType: string) => boolean;
3808
+ interface MessagingApiConfig {
3809
+ baseUrl: string;
3810
+ getHeaders: () => Record<string, string> | Promise<Record<string, string>>;
3811
+ onAuthError?: () => void;
3789
3812
  }
3790
3813
  //#endregion
3791
- //#region ../core/src/registries/widget-manifest.d.ts
3814
+ //#region src/messaging/use-messaging-config.d.ts
3815
+ interface MessagingConfig {
3816
+ readonly apiConfig: MessagingApiConfig;
3817
+ readonly messagingApi: MessagingApi;
3818
+ readonly websocketUrl: string;
3819
+ }
3820
+ declare function useMessagingConfig(): MessagingConfig;
3821
+ //#endregion
3822
+ //#region src/messaging/fluid-file-uploader.d.ts
3792
3823
  /**
3793
- * The manifest a plugin author provides to register a custom widget.
3794
- * Required fields ensure the widget works in both builder and SDK contexts.
3795
- * Optional fields enable advanced behavior (containers, min SDK version).
3824
+ * Creates a FileUploader that uploads to Filestack using the REST API.
3825
+ *
3826
+ * @param apiKey - Filestack API key. If falsy, returns a noop uploader
3827
+ * that rejects uploads with a helpful error message.
3796
3828
  */
3797
- interface WidgetManifest {
3798
- /** Schema version for forward compatibility. Currently must be 1. */
3799
- manifestVersion: number;
3800
- /** Unique widget type identifier (e.g., "StockTickerWidget"). */
3801
- type: string;
3802
- /** The React component that renders this widget. */
3803
- component: AnyComponent;
3804
- /** Human-readable name shown in the builder palette. */
3805
- displayName: string;
3806
- /** Brief description shown in the builder palette. */
3807
- description: string;
3808
- /** Icon identifier for the builder palette (e.g., "chart-line"). */
3809
- icon: string;
3810
- /** Category ID for palette grouping (e.g., "components", "blocks", "utility"). */
3811
- category: string;
3812
- /** Property schema defining editable fields in the builder's property panel. */
3813
- propertySchema: WidgetPropertySchema;
3814
- /** Default prop values when the widget is first created. */
3815
- defaultProps: Record<string, unknown>;
3816
- /** Container behavior — only if this widget can hold child widgets. */
3817
- container?: ContainerWidgetBehavior;
3818
- /** Minimum SDK version required (e.g., "1.0.0"). */
3819
- minSdkVersion?: string;
3820
- /** Resizable configuration. */
3821
- resizable?: {
3822
- horizontal?: boolean;
3823
- vertical?: boolean;
3824
- minWidth?: number;
3825
- minHeight?: number;
3826
- };
3827
- }
3829
+ declare function createFluidFileUploader(apiKey: string | undefined): FileUploader;
3828
3830
  //#endregion
3829
3831
  //#region ../widgets/src/widgets/TextWidget.d.ts
3830
3832
  type TextAlignment = "left" | "center" | "right";