require("./chunk-9hOWP6kD.cjs");
const require_FluidThemeProvider = require("./FluidThemeProvider-DMfCMPLp.cjs");
let react = require("react");
let _tanstack_react_query = require("@tanstack/react-query");
//#region src/hooks/query-keys.ts
/**
* Company-scoped query key factory for TanStack Query.
*
* In portal-tenant, each tenant is a single company, so query keys are
* returned unscoped. The `createCompanyQueryKey` utility is preserved for
* potential future multi-company support.
*/
/**
* Create a company-scoped query key by prepending ["company", companyId].
*
* @param companyId - The company ID
* @param baseKey - The base query key segments (e.g. ["fluid", "profile"])
* @returns A tuple like ["company", 42, "fluid", "profile"]
*/
function createCompanyQueryKey(companyId, ...baseKey) {
	return [
		"company",
		companyId,
		...baseKey
	];
}
/**
* Hook that returns a `scopeKey` function.
*
* In portal-tenant, each tenant is a single company, so keys are
* returned unscoped (no company prefix).
*/
function useCompanyScopedQueryKey() {
	return {
		companyId: void 0,
		scopeKey: (0, react.useCallback)((baseKey) => {
			return baseKey;
		}, [])
	};
}
//#endregion
//#region src/transforms/screen-transforms.ts
/**
* Normalize component_tree to always be an array.
* The API stores component_tree as a hash (object), but the frontend expects an array.
*/
function normalizeComponentTree(componentTree) {
	if (!componentTree) return [];
	if (Array.isArray(componentTree)) return componentTree;
	if (typeof componentTree === "object") return [componentTree];
	return [];
}
/**
* Convert a raw FluidOS screen to ScreenDefinition.
* Normalizes component_tree and converts string IDs to numbers.
*/
function toScreenDefinition(screen) {
	return {
		id: Number(screen.id),
		slug: screen.slug ?? "",
		name: screen.name ?? "",
		component_tree: normalizeComponentTree(screen.component_tree)
	};
}
//#endregion
//#region src/transforms/navigation-transforms.ts
/**
* Convert a raw FluidOS navigation item to NavigationItem.
* Recursively transforms children and sorts by position.
*/
function toNavigationItem(item) {
	const children = (item.children ?? []).map(toNavigationItem).sort((a, b) => (a.position ?? 0) - (b.position ?? 0));
	return {
		id: Number(item.id),
		label: item.label ?? "Untitled",
		...item.slug != null ? { slug: String(item.slug) } : {},
		...item.icon != null ? { icon: String(item.icon) } : {},
		...item.screen_id != null ? { screen_id: Number(item.screen_id) } : {},
		...item.parent_id != null ? { parent_id: Number(item.parent_id) } : {},
		...item.source != null ? { source: item.source } : {},
		position: item.position ?? 0,
		children
	};
}
//#endregion
//#region src/transforms/index.ts
/**
* Convert an `AppManifestResponse` into the `RawManifestResponse` shape
* expected by the transform pipeline. `AppManifestResponse` is structurally
* assignable to `RawManifestResponse`, so this is a runtime-only guard that
* rejects empty payloads.
*/
function toRawManifest(response) {
	if (!response.manifest) throw new Error("Portal BFF returned empty manifest");
	return response;
}
/**
* Transform a raw FluidOS manifest API response into RepAppData.
*
* Handles:
* - Theme transformation (legacy and new formats)
* - Screen normalization (component_tree array wrapping)
* - Navigation item transformation (recursive with position sorting)
*/
function transformManifestToRepAppData(response) {
	const manifest = response.manifest;
	const rawProfile = manifest.profile;
	const rawThemes = Array.isArray(rawProfile?.themes) ? rawProfile.themes : [];
	const screens = (manifest.screens ?? []).map((screen) => toScreenDefinition(screen));
	const navigationItems = (rawProfile?.navigation?.navigation_items ?? []).map(toNavigationItem);
	const nav = rawProfile?.navigation;
	const mobileNav = rawProfile?.mobile_navigation;
	const mobileNavigationItems = (mobileNav?.navigation_items ?? []).map(toNavigationItem);
	const activeThemeId = require_FluidThemeProvider.getActiveThemeId(rawThemes);
	const definitionId = manifest.definition_id ?? 0;
	return {
		definition_id: definitionId,
		published_version: manifest.published_version ?? 0,
		screens,
		profile: {
			name: rawProfile?.name ?? "Default",
			definition_id: rawProfile?.definition_id ?? definitionId,
			themes: require_FluidThemeProvider.transformThemes(rawThemes),
			...activeThemeId !== void 0 ? { activeThemeId } : {},
			navigation: {
				definition_id: nav?.definition_id ?? definitionId,
				id: nav?.id ?? 0,
				name: nav?.name ?? "Main Navigation",
				navigation_items: navigationItems,
				screens
			},
			...mobileNav ? { mobile_navigation: {
				definition_id: mobileNav.definition_id ?? definitionId,
				id: mobileNav.id ?? 0,
				name: mobileNav.name ?? "Mobile Navigation",
				navigation_items: mobileNavigationItems,
				screens
			} } : {}
		}
	};
}
//#endregion
//#region src/hooks/use-app-definition.ts
/**
* Base query key for the app definition endpoint.
* The runtime key includes a company prefix via {@link useCompanyScopedQueryKey}.
*/
const APP_DEFINITION_QUERY_KEY = ["fluid", "app-definition"];
/**
* Hook to fetch the active app manifest from the portal-tenant BFF.
*
* Returns the manifest metadata (id, name, version)
* sourced from `GET /api/app/manifest` via the {@link AppDefinitionApi} port.
*
* @example
* ```tsx
* function MyComponent() {
*   const { data } = useAppDefinition();
*   const definitionId = data?.definition.id ?? 0;
* }
* ```
*/
function useAppDefinition(options) {
	const api = require_FluidThemeProvider.useAppDefinitionApi();
	const { scopeKey } = useCompanyScopedQueryKey();
	return (0, _tanstack_react_query.useQuery)({
		queryKey: scopeKey(APP_DEFINITION_QUERY_KEY),
		queryFn: () => api.fetchDefinition(),
		...options?.enabled !== void 0 && { enabled: options.enabled }
	});
}
//#endregion
//#region src/hooks/use-fluid-theme.ts
/**
* Hook to access and control theme settings
*
* @example
* ```tsx
* function ThemeSwitcher({ themes }: { themes: ThemeDefinition[] }) {
*   const { currentTheme, setTheme, setThemeMode, mode } = useFluidTheme();
*
*   return (
*     <div>
*       <select
*         value={currentTheme?.name}
*         onChange={(e) => {
*           const theme = themes.find(t => t.name === e.target.value);
*           if (theme) setTheme(theme);
*         }}
*       >
*         {themes.map(theme => (
*           <option key={theme.name} value={theme.name}>
*             {theme.name}
*           </option>
*         ))}
*       </select>
*
*       <button onClick={() => setThemeMode(mode === "dark" ? "light" : "dark")}>
*         Toggle {mode === "dark" ? "Light" : "Dark"} Mode
*       </button>
*     </div>
*   );
* }
* ```
*/
function useFluidTheme() {
	const { currentTheme, setTheme, setThemeMode, mode } = require_FluidThemeProvider.useThemeContext();
	return {
		currentTheme,
		setTheme,
		setThemeMode,
		mode
	};
}
//#endregion
//#region src/hooks/hook-types.ts
/**
* Type predicate to check if a query result has successfully loaded data.
* Narrows the data type from T | null | undefined to T.
*
* @example
* const result = useContact(id);
* if (hasData(result)) {
*   // TypeScript knows result.data is Contact, not Contact | null
*   console.log(result.data.name);
* }
*/
function hasData(result) {
	return result.data != null && !result.isLoading && !result.isError;
}
/**
* Type predicate to check if a query result is in loading state.
* Useful for conditional rendering.
*
* @example
* if (isLoading(result)) {
*   return <Spinner />;
* }
*/
function isLoading(result) {
	return result.isLoading;
}
/**
* Type predicate to check if a query result has an error.
* Narrows to include the error property.
*
* @example
* if (isErrorResult(result)) {
*   console.error(result.error); // error is E, not undefined
* }
*/
function isErrorResult(result) {
	return result.isError && result.error !== void 0;
}
/**
* Type predicate to check if a query result is in idle state (not loading, no error, has data).
*
* @example
* if (isIdle(result)) {
*   // Safe to access and render data
* }
*/
function isIdle(result) {
	return !result.isLoading && !result.isError;
}
/**
* Type-safe property selector for hook results.
* Uses K extends keyof T constraint (generics-function-constraints rule).
*
* @typeParam T - The data object type
* @typeParam K - Key of T (constrained to actual keys)
*
* @example
* const users = [{ name: "Alice", age: 30 }];
* const names = selectProperty(users, "name"); // string[]
* const ages = selectProperty(users, "age");   // number[]
* selectProperty(users, "invalid"); // Error: "invalid" not in "name" | "age"
*/
function selectProperty(items, key) {
	return items.map((item) => item[key]);
}
/**
* Type-safe property getter for a single item.
* Returns undefined if item is null/undefined.
*
* @typeParam T - The data object type
* @typeParam K - Key of T (constrained to actual keys)
*/
function getProperty(item, key) {
	return item?.[key];
}
/**
* Activity slug constants as a const object.
* Derive the ActivitySlug type from this single source of truth.
*/
const ACTIVITY_SLUGS = {
	abandonedCart: "abandoned_cart",
	announcements: "announcements",
	cartItemsAdded: "cart_items_added",
	commentReply: "comment_reply",
	directMessage: "direct_message",
	fantasyPoint: "fantasy_point",
	newLead: "new_lead",
	orderPlaced: "order_placed",
	pageViews: "page_views",
	pageViewsContact: "page_views_contact",
	tasks: "tasks",
	upcomingEvent: "upcoming_event",
	video: "video",
	videoComplete: "video_complete",
	videoCompleteContact: "video_complete_contact",
	videoContact: "video_contact",
	messageReceived: "message_received",
	messageSent: "message_sent",
	newCartItemsAdded: "new_cart_items_added",
	smartLinkClicked: "smart_link_clicked",
	reviewLeft: "review_left"
};
/** Type predicate to check if a string is a valid ActivitySlug. */
function isActivitySlug(value) {
	return Object.values(ACTIVITY_SLUGS).includes(value);
}
//#endregion
Object.defineProperty(exports, "ACTIVITY_SLUGS", {
	enumerable: true,
	get: function() {
		return ACTIVITY_SLUGS;
	}
});
Object.defineProperty(exports, "APP_DEFINITION_QUERY_KEY", {
	enumerable: true,
	get: function() {
		return APP_DEFINITION_QUERY_KEY;
	}
});
Object.defineProperty(exports, "createCompanyQueryKey", {
	enumerable: true,
	get: function() {
		return createCompanyQueryKey;
	}
});
Object.defineProperty(exports, "getProperty", {
	enumerable: true,
	get: function() {
		return getProperty;
	}
});
Object.defineProperty(exports, "hasData", {
	enumerable: true,
	get: function() {
		return hasData;
	}
});
Object.defineProperty(exports, "isActivitySlug", {
	enumerable: true,
	get: function() {
		return isActivitySlug;
	}
});
Object.defineProperty(exports, "isErrorResult", {
	enumerable: true,
	get: function() {
		return isErrorResult;
	}
});
Object.defineProperty(exports, "isIdle", {
	enumerable: true,
	get: function() {
		return isIdle;
	}
});
Object.defineProperty(exports, "isLoading", {
	enumerable: true,
	get: function() {
		return isLoading;
	}
});
Object.defineProperty(exports, "normalizeComponentTree", {
	enumerable: true,
	get: function() {
		return normalizeComponentTree;
	}
});
Object.defineProperty(exports, "selectProperty", {
	enumerable: true,
	get: function() {
		return selectProperty;
	}
});
Object.defineProperty(exports, "toNavigationItem", {
	enumerable: true,
	get: function() {
		return toNavigationItem;
	}
});
Object.defineProperty(exports, "toRawManifest", {
	enumerable: true,
	get: function() {
		return toRawManifest;
	}
});
Object.defineProperty(exports, "toScreenDefinition", {
	enumerable: true,
	get: function() {
		return toScreenDefinition;
	}
});
Object.defineProperty(exports, "transformManifestToRepAppData", {
	enumerable: true,
	get: function() {
		return transformManifestToRepAppData;
	}
});
Object.defineProperty(exports, "useAppDefinition", {
	enumerable: true,
	get: function() {
		return useAppDefinition;
	}
});
Object.defineProperty(exports, "useCompanyScopedQueryKey", {
	enumerable: true,
	get: function() {
		return useCompanyScopedQueryKey;
	}
});
Object.defineProperty(exports, "useFluidTheme", {
	enumerable: true,
	get: function() {
		return useFluidTheme;
	}
});

//# sourceMappingURL=hook-types-B8cS7ta0.cjs.map