Complete API reference for the useCheckIn composable and related types.
The main composable for creating and managing check-in desks.
const { createDesk, checkIn, standaloneDesk, generateId, memoizedId, isCheckedIn, getRegistry, clearIdCache } = useCheckIn<T, TContext>();
| Parameter | Description | Default |
|---|---|---|
T | Type of data stored in the desk | any |
TContext | Type of additional context provided by the desk | {} |
Creates a check-in desk and provides it to child components.
createDesk(
injectionKey: InjectionKey<DeskWithContext<T, TContext>>,
options?: DeskCoreOptions<T> & { context?: TContext }
): { desk: DeskWithContext<T, TContext>, injectionKey: InjectionKey }
Parameters:
| Name | Type | Description |
|---|---|---|
injectionKey | InjectionKey<DeskWithContext<T, TContext>> | Symbol-based injection key for dependency injection |
options | DeskCoreOptions<T> & { context?: TContext } | Desk configuration and context |
Options:
| Option | Type | Description | Default |
|---|---|---|---|
context | TContext | Additional context to share with child components | undefined |
onBeforeCheckIn | (id, data) => boolean | undefined | Hook called before check-in, return false to cancel | undefined |
onCheckIn | (id, data) => void | Hook called after successful check-in | undefined |
onBeforeCheckOut | (id) => boolean | undefined | Hook called before check-out, return false to cancel | undefined |
onCheckOut | (id) => void | Hook called after successful check-out | undefined |
debug | boolean | Enable debug logging | false |
devTools | boolean | Enable Vue DevTools integration | false |
plugins | CheckInPlugin<T>[] | Array of plugins to extend functionality | [] |
deskId | string | Identifier for DevTools display | Auto-generated |
Returns: An object containing:
desk: The desk instance with contextinjectionKey: The injection key usedExample:
const TABS_DESK_KEY = Symbol('tabsDesk');
const { createDesk } = useCheckIn<TabItemData, TabItemContext>();
const { desk } = createDesk(TABS_DESK_KEY, {
devTools: true,
context: {
activeTab: ref('tab-1'),
selectTab: (id) => { /* ... */ },
},
onCheckIn: (id, data) => {
console.log('Tab checked in:', id, data);
},
});
Registers a child component with a desk.
checkIn(
parentDeskOrKey: DeskCore<T> & TContext | InjectionKey<DeskCore<T> & TContext> | null | undefined,
checkInOptions?: CheckInOptions<T, TContext>
): CheckInResult<T, TContext>
Parameters:
| Name | Type | Description |
|---|---|---|
parentDeskOrKey | DeskCore<T> & TContext | InjectionKey | null | undefined | Desk instance or injection key |
checkInOptions | CheckInOptions<T, TContext> | Check-in configuration |
Check-in Options:
| Option | Type | Description | Default |
|---|---|---|---|
id | string | number | Unique identifier for this component | Auto-generated |
autoCheckIn | boolean | Automatically check in on component mount | false |
data | T | (() => T) | (() => Promise<T>) | ((desk) => T) | ((desk) => Promise<T>) | Data to register, or sync/async function that returns data. When using a function, it receives the desk instance as a parameter, allowing access to desk context without manual inject calls | undefined |
watchData | boolean | Watch data for changes and auto-update the desk registry. Works with both sync and async data | false |
shallow | boolean | Use shallow watching (deep: false) instead of deep watching when watchData is enabled. Set to true for performance optimization when only tracking object reference changes, or false to detect nested property changes | false |
watchCondition | (() => boolean) | Ref<boolean> | Conditional check-in/check-out based on reactive state. The component will automatically check in when the condition becomes true and check out when it becomes false. Works independently of autoCheckIn, which only controls the initial check-in behavior | undefined |
meta | Record<string, any> | Additional metadata visible in DevTools inspector | undefined |
debug | boolean | Enable debug logging for this check-in | false |
Returns: An object containing:
desk: Reference to the desk (with context if provided)checkOut(): Function to manually check outupdateSelf(newData?): Function to manually update dataExample:
const { checkIn } = useCheckIn<TabItemData, TabItemContext>();
// Example 1: Basic auto check-in with data watching
const { desk, checkOut, updateSelf } = checkIn(TABS_DESK_KEY, {
id: props.id,
autoCheckIn: true,
watchData: true,
data: (desk) => ({
label: desk.tabsData.value.find(t => t.id === props.id)?.label ?? '',
content: desk.tabsData.value.find(t => t.id === props.id)?.content ?? '',
}),
});
// Example 2: Conditional check-in based on visibility
const isVisible = ref(true);
checkIn(MY_DESK_KEY, {
id: 'item-1',
watchCondition: isVisible,
data: { name: 'My Item' },
});
// Example 3: Shallow watching for performance
const largeList = ref([{ id: 1 }, { id: 2 }, { id: 3 }]);
checkIn(LIST_DESK_KEY, {
id: 'list-1',
autoCheckIn: true,
watchData: true,
shallow: true,
data: () => largeList.value,
});
// Example 4: Async data with race condition protection
checkIn(USER_DESK_KEY, {
id: props.userId,
autoCheckIn: true,
watchData: true,
data: async (desk) => {
const response = await fetch(`/api/users/${props.userId}`);
return await response.json();
},
});
data function receives the desk instance, eliminating the need for manual inject callswatchCondition works independently of autoCheckIn. When autoCheckIn: true, it controls the initial check-in only if the condition is true. The watcher remains active regardlessshallow: true for large objects when you only need to track reference changesThe watchCondition option enables dynamic check-in/check-out based on reactive state:
// Scenario 1: autoCheckIn: false (default)
const isActive = ref(false);
checkIn(MY_DESK_KEY, {
watchCondition: isActive,
autoCheckIn: false,
});
// No initial check-in (even if isActive is true)
// Waits for isActive to become true for first check-in
// Automatically checks out when isActive becomes false
// Scenario 2: autoCheckIn: true
const isActive = ref(true);
checkIn(MY_DESK_KEY, {
watchCondition: isActive,
autoCheckIn: true,
});
// Immediate check-in if isActive is already true
// Watch remains active for future condition changes
// Automatically checks out when isActive becomes false
// Scenario 3: Complex conditions
checkIn(MY_DESK_KEY, {
watchCondition: () => isLoggedIn.value && hasPermission.value && !isDisabled.value,
autoCheckIn: true,
});
// Checks in/out based on combined conditions
Creates a standalone desk without dependency injection (useful for testing).
standaloneDesk(options?: DeskCoreOptions<T>): DeskCore<T>
Example:
const desk = standaloneDesk<TabItemData>({
debug: true,
});
desk.checkIn('tab-1', { label: 'Home' });
Generates a cryptographically secure unique ID.
generateId(prefix?: string): string
Parameters:
prefix: Optional prefix for the ID (default: 'item')Example:
const id = generateId('tab');
Generates a memoized ID for a component, ensuring stability across remounts.
memoizedId(
instanceOrId: object | string | number | null | undefined,
prefix?: string
): string
Parameters:
instanceOrId: Vue instance, custom ID, or nullprefix: Optional prefix for the IDExample:
import { getCurrentInstance } from 'vue';
const instance = getCurrentInstance();
const id = memoizedId(instance, 'tab');
Computed helper to check if a specific ID is checked in.
isCheckedIn<T, TContext>(
desk: DeskCore<T> & TContext,
id: string | number | Ref<string | number>
): ComputedRef<boolean>
Example:
const isTabActive = isCheckedIn(desk, 'tab-1');
Computed helper to get the registry as an array, with optional sorting.
getRegistry<T, TContext>(
desk: DeskCore<T> & TContext,
options?: { sortBy?: keyof T | 'timestamp'; order?: 'asc' | 'desc' }
): ComputedRef<CheckInItem<T>[]>
Example:
// Get all tabs sorted by timestamp
const allTabs = getRegistry(desk, {
sortBy: 'timestamp',
order: 'desc'
});
Clears the memoization cache for custom IDs.
clearIdCache(resetCounter?: boolean): void
Parameters:
resetCounter: Whether to reset the instance counter (default: false)The desk instance provides methods to interact with the registry.
Manually register an item.
desk.checkIn(id: string | number, data: T, meta?: Record<string, any>): boolean
Returns: true if successful, false if cancelled by plugin/hook
Manually unregister an item.
desk.checkOut(id: string | number): boolean
Returns: true if successful, false if not found or cancelled
Update an existing item's data.
desk.update(id: string | number, data: T): boolean
Returns: true if successful, false if not found
Retrieve a specific item by ID.
desk.get(id: string | number): CheckInItem<T> | undefined
Check if an ID exists in the registry.
desk.has(id: string | number): boolean
Get all items, optionally sorted.
desk.getAll(options?: {
sortBy?: keyof T | 'timestamp';
order?: 'asc' | 'desc';
}): CheckInItem<T>[]
Get the number of checked-in items.
desk.count(): number
Returns: Reactive computed ref with the count
Remove all items from the registry.
desk.clear(): void
Subscribe to desk events.
desk.on(event: DeskEventType, callback: DeskEventCallback<T>): () => void
Events:
'check-in': Fired when an item checks in'check-out': Fired when an item checks out'update': Fired when an item is updated'clear': Fired when the desk is clearedReturns: Unsubscribe function
Example:
const unsubscribe = desk.on('check-in', ({ id, data }) => {
console.log(`Item ${id} checked in:`, data);
});
// Later: unsubscribe()
Unsubscribe from desk events.
desk.off(event: DeskEventType, callback: DeskEventCallback<T>): void
Clean up the desk and remove all listeners.
desk.destroy(): void
desk automatically cleans up on component unmount. Use destroy() for manual cleanup in long-running applications.Represents an item in the desk registry.
interface CheckInItem<T = any> {
id: string | number;
data: T;
timestamp?: number;
meta?: Record<string, any>;
}
Type of events emitted by the desk.
type DeskEventType = 'check-in' | 'check-out' | 'update' | 'clear';
Callback signature for desk events.
type DeskEventCallback<T = any> = (payload: {
id?: string | number;
data?: T;
timestamp: number;
}) => void;
Plugin interface for extending desk functionality.
interface CheckInPlugin<T = any> {
name: string;
onBeforeCheckIn?: (id: string | number, data: T, desk: DeskCore<T>) => boolean | undefined;
onCheckIn?: (id: string | number, data: T, desk: DeskCore<T>) => void;
onBeforeCheckOut?: (id: string | number, desk: DeskCore<T>) => boolean | undefined;
onCheckOut?: (id: string | number, desk: DeskCore<T>) => void;
onUpdate?: (id: string | number, data: T, desk: DeskCore<T>) => void;
}
Always provide type parameters for useCheckIn<T, TContext>() to get full type safety and IntelliSense support:
interface MyData {
name: string;
value: number;
}
interface MyContext {
selectedId: Ref<string>;
selectItem: (id: string) => void;
}
const { createDesk, checkIn } = useCheckIn<MyData, MyContext>();
When using the desk parameter in the data function:
// Good: Lightweight computation
data: (desk) => ({
label: desk.items.value.find(i => i.id === props.id)?.label ?? 'Unknown'
})
// Caution: Heavy computation with watchData
data: (desk) => {
// This runs on every data change when watchData: true
return expensiveCalculation(desk.data.value);
}
Important: When watchData: true, the function is re-evaluated on each change. Keep the logic lightweight to avoid performance issues.
Choose the appropriate watching strategy based on your data structure:
// Use shallow: true for large arrays/objects when only tracking replacements
const items = ref([{ id: 1 }, { id: 2 }, ...largeList]);
checkIn(DESK_KEY, {
watchData: true,
shallow: true, // Only detects items.value = newArray
data: () => items.value,
});
// Use shallow: false (default) for nested property changes
const formData = ref({ user: { name: '', email: '' } });
checkIn(FORM_DESK_KEY, {
watchData: true,
shallow: false, // Detects formData.value.user.name = 'John'
data: () => formData.value,
});
Use watchCondition for dynamic component participation:
// Tab visibility
checkIn(TABS_DESK_KEY, {
id: props.tabId,
watchCondition: () => props.visible,
data: { label: props.label },
});
// User permissions
checkIn(ADMIN_DESK_KEY, {
id: props.userId,
watchCondition: () => hasAdminRole.value,
data: () => userData.value,
});
// Combined conditions
checkIn(DESK_KEY, {
id: props.id,
watchCondition: () => isEnabled.value && !isLoading.value && hasData.value,
autoCheckIn: true, // Initial check-in if all conditions are met
data: myData,
});
Choose the appropriate registration strategy:
// Auto check-in: Component should always be registered
checkIn(DESK_KEY, {
autoCheckIn: true,
data: myData,
});
// Manual check-in: Need control over timing
const { desk, checkOut } = checkIn(DESK_KEY, {
autoCheckIn: false,
data: myData,
});
// Later, when ready...
if (someCondition) {
// Manual check-in via updateSelf or direct desk.checkIn
}
// Conditional check-in: Dynamic participation
checkIn(DESK_KEY, {
watchCondition: isActive,
data: myData,
});
VueAirport includes built-in protection against race conditions for async data:
// Safe: Automatic race condition protection
checkIn(USER_DESK_KEY, {
id: props.userId,
autoCheckIn: true,
watchData: true,
data: async (desk) => {
// Slow API call
const response = await fetch(`/api/users/${props.userId}`);
const userData = await response.json();
// If props.userId changed during the fetch, this update is automatically discarded
return userData;
},
});
The async update guard ensures that only the most recent update is applied, preventing stale data from overwriting newer data.
The desk automatically cleans up on component unmount. For manual cleanup in long-running applications:
// Clear memoized ID cache
clearIdCache(true); // true = reset counter
// Destroy a desk manually
desk.destroy();
// Clear all items from a desk
desk.clear();
Add meaningful metadata for better debugging experience:
checkIn(DESK_KEY, {
id: props.id,
autoCheckIn: true,
data: myData,
meta: {
label: 'User Profile Form',
componentType: 'form',
priority: 'high',
createdBy: 'AuthModule',
},
});
Extend desk functionality with plugins:
const validationPlugin = {
name: 'validation',
onBeforeCheckIn: (id, data, desk) => {
if (!data.email) {
console.warn('Email is required');
return false; // Cancel check-in
}
return true;
},
};
createDesk(FORM_DESK_KEY, {
plugins: [validationPlugin],
devTools: true,
});