learning_ai_common_plat/packages/quick-actions/src/client.ts
saravanakumardb1 be03efa111 feat(shared-packages): add 9 @bytelyst/* client packages with 100% API coverage
Packages added:
- @bytelyst/referral-client — referral API client + share helpers
- @bytelyst/subscription-client — subscription/plan API client + cache
- @bytelyst/celebrations — milestone triggers, confetti, positive messages
- @bytelyst/gentle-notifications — ND-friendly messaging, forbidden phrases
- @bytelyst/accessibility — VoiceOver/TalkBack label generators
- @bytelyst/quick-actions — progressive disclosure, smart defaults
- @bytelyst/time-references — familiar duration references
- @bytelyst/org-client — org/workspace/membership/license API client
- @bytelyst/marketplace-client — listing/review/install API client

All packages: pure TS, ESM, globalThis.fetch, no Node.js deps.
99 Vitest tests across 9 packages, 79/79 public methods covered.

Review fixes applied:
- time-references: fix module-level mutable state leak + add clearCustomReferences()
- accessibility: fix parameter reassignment in formatDurationForA11y/numberToWords
- subscription-client: fix flaky daysRemaining test (ms boundary race)
2026-03-19 13:10:09 -07:00

48 lines
1.3 KiB
TypeScript

/**
* Progressive disclosure system, smart defaults, quick action definitions.
*
* Reduces cognitive load by surfacing only relevant UI sections and actions.
* Pure client-side TS — no backend dependency.
*/
import type { ProgressiveSection, QuickAction, SmartDefault } from './types.js';
export const MAX_VISIBLE_ITEMS = 3;
export const MAX_VISIBLE_LIST = 5;
export function getVisibleSections(
sections: ProgressiveSection[],
expandedIds: Set<string>
): ProgressiveSection[] {
return sections.filter(
s => s.defaultExpanded || expandedIds.has(s.id) || s.priority === 'primary'
);
}
export function getAvailableActions(
actions: QuickAction[],
context: { isActive?: boolean; isAuthenticated?: boolean }
): QuickAction[] {
return actions.filter(a => {
if (a.requiresAuth && !context.isAuthenticated) return false;
return true;
});
}
export function pickSmartDefault(candidates: SmartDefault[]): SmartDefault | null {
if (candidates.length === 0) return null;
const priority: SmartDefault['source'][] = [
'last_used',
'most_common',
'recommendation',
'system',
];
for (const source of priority) {
const match = candidates.find(c => c.source === source);
if (match) return match;
}
return candidates[0];
}