@fayz-ai/admin 0.11.0 → 0.12.0
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/{CommandPalette-2AL327XQ.js → CommandPalette-U7MMA2WH.js} +27 -4
- package/dist/CommandPalette-U7MMA2WH.js.map +1 -0
- package/dist/app/AdminShell.d.ts.map +1 -1
- package/dist/app/admin-app.d.ts.map +1 -1
- package/dist/app/config.d.ts +7 -0
- package/dist/app/config.d.ts.map +1 -1
- package/dist/components/chat/AssistantInvite.d.ts +10 -0
- package/dist/components/chat/AssistantInvite.d.ts.map +1 -1
- package/dist/components/chat/ChatFab.d.ts.map +1 -1
- package/dist/components/chat/ConfirmActionCard.d.ts.map +1 -1
- package/dist/components/chat/fab-anchor.d.ts +15 -0
- package/dist/components/chat/fab-anchor.d.ts.map +1 -0
- package/dist/components/connect/connector-map.generated.d.ts.map +1 -1
- package/dist/components/layout/CommandPalette.d.ts +5 -2
- package/dist/components/layout/CommandPalette.d.ts.map +1 -1
- package/dist/components/shared/PersonLink.d.ts +8 -1
- package/dist/components/shared/PersonLink.d.ts.map +1 -1
- package/dist/components/shared/RecordPickerModal.d.ts +7 -1
- package/dist/components/shared/RecordPickerModal.d.ts.map +1 -1
- package/dist/crud/CrudListView.d.ts +8 -3
- package/dist/crud/CrudListView.d.ts.map +1 -1
- package/dist/crud/CrudPage.d.ts.map +1 -1
- package/dist/crud/archetype-lookup.d.ts +4 -0
- package/dist/crud/archetype-lookup.d.ts.map +1 -1
- package/dist/hooks/useAuth.d.ts.map +1 -1
- package/dist/hooks/useGlobalSearch.d.ts +3 -1
- package/dist/hooks/useGlobalSearch.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +837 -558
- package/dist/index.js.map +1 -1
- package/dist/lib/assistant-invite.d.ts +18 -0
- package/dist/lib/assistant-invite.d.ts.map +1 -1
- package/dist/lib/cache.d.ts +2 -17
- package/dist/lib/cache.d.ts.map +1 -1
- package/dist/stores/createCrudStore.d.ts +8 -0
- package/dist/stores/createCrudStore.d.ts.map +1 -1
- package/dist/theme/utils.d.ts.map +1 -1
- package/package.json +6 -6
- package/dist/CommandPalette-2AL327XQ.js.map +0 -1
|
@@ -34,12 +34,30 @@ export interface AssistantInviteDef {
|
|
|
34
34
|
auto?: boolean;
|
|
35
35
|
}
|
|
36
36
|
type Stage = 'hero' | 'dock';
|
|
37
|
+
/** Where the docked composer is drawn: `left` is its CENTRE x, in viewport px. */
|
|
38
|
+
export interface DockBox {
|
|
39
|
+
left: number;
|
|
40
|
+
width: number;
|
|
41
|
+
}
|
|
37
42
|
interface AssistantInviteState {
|
|
38
43
|
invite: AssistantInviteDef | null;
|
|
39
44
|
stage: Stage;
|
|
45
|
+
/** Published by the mounted invite while its composer is actually on screen
|
|
46
|
+
* (null on phones, with the rail open, or during the hero). The FAB reads it
|
|
47
|
+
* to know what shape it grew into. */
|
|
48
|
+
dockBox: DockBox | null;
|
|
49
|
+
/** The composer whose page just unmounted, kept alive for the morph back into
|
|
50
|
+
* the FAB. The page is already gone — this is what still has to be drawn. */
|
|
51
|
+
leaving: {
|
|
52
|
+
invite: AssistantInviteDef;
|
|
53
|
+
box: DockBox;
|
|
54
|
+
} | null;
|
|
40
55
|
/** Mount/unmount. Passing null clears only if `id` still owns the slot. */
|
|
41
56
|
setInvite: (invite: AssistantInviteDef | null, id?: string) => void;
|
|
57
|
+
setDockBox: (box: DockBox | null) => void;
|
|
42
58
|
dismiss: () => void;
|
|
59
|
+
/** The morph back finished; the FAB owns the corner again. */
|
|
60
|
+
endLeave: () => void;
|
|
43
61
|
}
|
|
44
62
|
export declare const useAssistantInviteStore: import("zustand").UseBoundStore<import("zustand").StoreApi<AssistantInviteState>>;
|
|
45
63
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assistant-invite.d.ts","sourceRoot":"","sources":["../../src/lib/assistant-invite.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,MAAM,CAAA;IACb,uDAAuD;IACvD,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,mEAAmE;IACnE,EAAE,EAAE,MAAM,CAAA;IACV,gFAAgF;IAChF,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,CAAA;IAChB,+EAA+E;IAC/E,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,2EAA2E;IAC3E,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,yBAAyB,EAAE,CAAA;IACzC,wEAAwE;IACxE,IAAI,CAAC,EAAE,OAAO,CAAA;CACf;AAED,KAAK,KAAK,GAAG,MAAM,GAAG,MAAM,CAAA;AA4B5B,UAAU,oBAAoB;IAC5B,MAAM,EAAE,kBAAkB,GAAG,IAAI,CAAA;IACjC,KAAK,EAAE,KAAK,CAAA;IACZ,2EAA2E;IAC3E,SAAS,EAAE,CAAC,MAAM,EAAE,kBAAkB,GAAG,IAAI,EAAE,EAAE,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;IACnE,OAAO,EAAE,MAAM,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"assistant-invite.d.ts","sourceRoot":"","sources":["../../src/lib/assistant-invite.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,MAAM,CAAA;IACb,uDAAuD;IACvD,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,mEAAmE;IACnE,EAAE,EAAE,MAAM,CAAA;IACV,gFAAgF;IAChF,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,CAAA;IAChB,+EAA+E;IAC/E,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,2EAA2E;IAC3E,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,yBAAyB,EAAE,CAAA;IACzC,wEAAwE;IACxE,IAAI,CAAC,EAAE,OAAO,CAAA;CACf;AAED,KAAK,KAAK,GAAG,MAAM,GAAG,MAAM,CAAA;AA4B5B,kFAAkF;AAClF,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;CACd;AAED,UAAU,oBAAoB;IAC5B,MAAM,EAAE,kBAAkB,GAAG,IAAI,CAAA;IACjC,KAAK,EAAE,KAAK,CAAA;IACZ;;2CAEuC;IACvC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;IACvB;kFAC8E;IAC9E,OAAO,EAAE;QAAE,MAAM,EAAE,kBAAkB,CAAC;QAAC,GAAG,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAA;IAC5D,2EAA2E;IAC3E,SAAS,EAAE,CAAC,MAAM,EAAE,kBAAkB,GAAG,IAAI,EAAE,EAAE,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;IACnE,UAAU,EAAE,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,KAAK,IAAI,CAAA;IACzC,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,8DAA8D;IAC9D,QAAQ,EAAE,MAAM,IAAI,CAAA;CACrB;AAED,eAAO,MAAM,uBAAuB,mFAsCjC,CAAA"}
|
package/dist/lib/cache.d.ts
CHANGED
|
@@ -1,18 +1,3 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
set<T>(key: string, data: T, ttl?: number): void;
|
|
4
|
-
/** Clear all entries whose key starts with `prefix` */
|
|
5
|
-
invalidate(prefix: string): void;
|
|
6
|
-
clear(): void;
|
|
7
|
-
size(): number;
|
|
8
|
-
}
|
|
9
|
-
export interface CacheConfig {
|
|
10
|
-
/** Default time-to-live in ms (default: 60 000 — 1 minute) */
|
|
11
|
-
defaultTTL?: number;
|
|
12
|
-
/** Maximum cached entries before LRU eviction (default: 500) */
|
|
13
|
-
maxEntries?: number;
|
|
14
|
-
}
|
|
15
|
-
export declare function stableKey(...parts: unknown[]): string;
|
|
16
|
-
export declare function createCacheStore(config?: CacheConfig): CacheStore;
|
|
17
|
-
export declare const globalCache: CacheStore;
|
|
1
|
+
export { globalCache, createCacheStore, clearGlobalCache, stableKey, DEFAULT_CACHE_TTL } from '@fayz-ai/core';
|
|
2
|
+
export type { CacheStore, CacheConfig } from '@fayz-ai/core';
|
|
18
3
|
//# sourceMappingURL=cache.d.ts.map
|
package/dist/lib/cache.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/lib/cache.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/lib/cache.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAC7G,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA"}
|
|
@@ -15,6 +15,10 @@ export interface CrudState<T> {
|
|
|
15
15
|
*/
|
|
16
16
|
error: string | null;
|
|
17
17
|
errorAt: number;
|
|
18
|
+
/** True when the rows on screen were answered locally (read cache or offline
|
|
19
|
+
* snapshot) rather than by the network. Screens tint their refresh control
|
|
20
|
+
* with it; `refresh()` is the way out. */
|
|
21
|
+
fromCache: boolean;
|
|
18
22
|
}
|
|
19
23
|
export interface ImportBatchResult<T> {
|
|
20
24
|
item?: T;
|
|
@@ -22,6 +26,10 @@ export interface ImportBatchResult<T> {
|
|
|
22
26
|
}
|
|
23
27
|
export interface CrudActions<T> {
|
|
24
28
|
fetch: () => Promise<void>;
|
|
29
|
+
/** Hard refresh: drops the store's freshness window and refetches. Callers
|
|
30
|
+
* that also want to bypass the shared read cache clear it first (the CRUD
|
|
31
|
+
* page does, via emitDataChanged). */
|
|
32
|
+
refresh: () => Promise<void>;
|
|
25
33
|
create: (data: any) => Promise<T>;
|
|
26
34
|
/** Batch create without per-item list refetch. Calls onProgress after each batch. Single fetch at the end. */
|
|
27
35
|
createMany: (rows: any[], options?: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createCrudStore.d.ts","sourceRoot":"","sources":["../../src/stores/createCrudStore.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAI9E,MAAM,WAAW,SAAS,CAAC,CAAC;IAC1B,KAAK,EAAE,CAAC,EAAE,GAAG,IAAI,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE,SAAS,CAAA;IAChB;;;;;;;;OAQG;IACH,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,OAAO,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"createCrudStore.d.ts","sourceRoot":"","sources":["../../src/stores/createCrudStore.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAI9E,MAAM,WAAW,SAAS,CAAC,CAAC;IAC1B,KAAK,EAAE,CAAC,EAAE,GAAG,IAAI,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE,SAAS,CAAA;IAChB;;;;;;;;OAQG;IACH,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,OAAO,EAAE,MAAM,CAAA;IACf;;+CAE2C;IAC3C,SAAS,EAAE,OAAO,CAAA;CACnB;AAED,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC,IAAI,CAAC,EAAE,CAAC,CAAA;IACR,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1B;;2CAEuC;IACvC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5B,MAAM,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,CAAA;IACjC,8GAA8G;IAC9G,UAAU,EAAE,CACV,IAAI,EAAE,GAAG,EAAE,EACX,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,KACtF,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAA;KAAE,CAAC,CAAA;IAClE,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAA;IACpD,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC;iDAC6C;IAC7C,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAA;IACxD,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC,KAAK,IAAI,CAAA;IAC7C,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,CAAC,GAAG,SAAS,CAAA;CACvC;AAED,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAA;AAExD;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;CACd;AAED,wBAAgB,eAAe,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EACtD,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC,EAC7B,MAAM,CAAC,EAAE,eAAe,6EAkRzB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/theme/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,cAAc,EACd,kBAAkB,EAClB,SAAS,EAIV,MAAM,UAAU,CAAA;AAqCjB,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAA;IAChC,gFAAgF;IAChF,UAAU,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAA;IACpC,UAAU,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAA;IACxC,8EAA8E;IAC9E,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,GAAG,kBAAkB,GAAG,KAAK,IAAI,SAAS,CAGrF;AA+BD;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,GAAG,kBAAkB,CA8FjE;AAED,wBAAgB,WAAW,CAAC,SAAS,EAAE,kBAAkB,GAAG,WAAW,CA2BtE;
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/theme/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,cAAc,EACd,kBAAkB,EAClB,SAAS,EAIV,MAAM,UAAU,CAAA;AAqCjB,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAA;IAChC,gFAAgF;IAChF,UAAU,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAA;IACpC,UAAU,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAA;IACxC,8EAA8E;IAC9E,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,GAAG,kBAAkB,GAAG,KAAK,IAAI,SAAS,CAGrF;AA+BD;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,GAAG,kBAAkB,CA8FjE;AAED,wBAAgB,WAAW,CAAC,SAAS,EAAE,kBAAkB,GAAG,WAAW,CA2BtE;AAkGD,wBAAgB,UAAU,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,IAAI,CAoB1E;AAED,wBAAgB,mBAAmB,IAAI,OAAO,GAAG,MAAM,CAGtD"}
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"fayz": {
|
|
4
4
|
"status": "beta"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.12.0",
|
|
7
7
|
"description": "Fayz SDK admin layer — the admin shell, CRUD engine, multi-tenancy, billing, permissions and org management",
|
|
8
8
|
"type": "module",
|
|
9
9
|
"sideEffects": [
|
|
@@ -59,12 +59,12 @@
|
|
|
59
59
|
"@radix-ui/react-dialog": "^1.1.0",
|
|
60
60
|
"@tanstack/react-table": "^8.20.0",
|
|
61
61
|
"cmdk": "^1.0.0",
|
|
62
|
-
"@fayz-ai/auth": "^0.
|
|
63
|
-
"@fayz-ai/core": "^0.
|
|
62
|
+
"@fayz-ai/auth": "^0.12.0",
|
|
63
|
+
"@fayz-ai/core": "^0.12.0",
|
|
64
64
|
"@fayz-ai/db": "^0.11.0",
|
|
65
|
-
"@fayz-ai/plugin-auth": "^0.10.
|
|
66
|
-
"@fayz-ai/sdk": "^0.
|
|
67
|
-
"@fayz-ai/ui": "^0.
|
|
65
|
+
"@fayz-ai/plugin-auth": "^0.10.1",
|
|
66
|
+
"@fayz-ai/sdk": "^0.12.0",
|
|
67
|
+
"@fayz-ai/ui": "^0.12.0"
|
|
68
68
|
},
|
|
69
69
|
"devDependencies": {
|
|
70
70
|
"@supabase/supabase-js": "^2.45.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/layout/CommandPalette.tsx"],"names":["Fragment"],"mappings":"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","file":"CommandPalette-2AL327XQ.js","sourcesContent":["import * as React from 'react'\nimport { useEffect, useMemo, useRef, useState } from 'react'\nimport { Command } from 'cmdk'\nimport * as Dialog from '@radix-ui/react-dialog'\nimport {\n Home, Users, Settings, CreditCard, Bell, Calendar, CalendarCheck2,\n CalendarClock, CalendarX, Package, Activity, BarChart3, FileText, FileCheck2, Mail, Search,\n DollarSign, BadgeDollarSign, CircleDollarSign, Megaphone, ShoppingCart, ShoppingBag, Target,\n Wrench, ClipboardList, ListChecks, Briefcase, UserCog, BookOpen, BookOpenCheck, MessageCircle,\n Globe, Percent, Tag, Tags, Camera, UtensilsCrossed, MapPin, Map, Handshake,\n Contact, Building2, Filter, Plus, List, Shield, User, Box, Sparkles, Loader2,\n ListPlus, FolderOpen, Boxes, Landmark, Receipt, Ban, Clock, Clock3, Inbox,\n Star, TrendingUp, UserCheck, UserPlus, UserX, Zap,\n type LucideIcon,\n} from 'lucide-react'\nimport {\n MIN_QUERY_LENGTH, highlightRanges, normalizeQuery, scoreCandidate, foldText,\n type GlobalSearchResult, type SearchHit,\n} from '@fayz-ai/core'\nimport { useTranslation } from '../../hooks/useTranslation'\n\nexport interface CommandItem {\n id: string\n label: string\n icon?: string\n action: () => void\n group?: string\n keywords?: string\n subtitle?: string\n}\n\n/** Runs one global search. `onPartial` paints a cheap early answer, if there is one. */\nexport type EntitySearchFn = (\n query: string,\n onPartial?: (result: GlobalSearchResult) => void,\n) => Promise<GlobalSearchResult>\n\ninterface CommandPaletteProps {\n commands?: CommandItem[]\n open: boolean\n onOpenChange: (open: boolean) => void\n onEntitySearch?: EntitySearchFn\n onEntitySelect?: (hit: SearchHit) => void\n}\n\nconst ICON_MAP: Record<string, LucideIcon> = {\n Home, Users, Settings, CreditCard, Bell, Calendar, CalendarClock, Package, Activity, BarChart3,\n CalendarCheck2, CalendarX, FileText, FileCheck2, Mail, Search, DollarSign, BadgeDollarSign, CircleDollarSign, Megaphone, ShoppingCart, ShoppingBag, Target,\n Wrench, ClipboardList, ListChecks, Briefcase, UserCog, BookOpen, BookOpenCheck, MessageCircle,\n Globe, Percent, Tag, Tags, Camera, UtensilsCrossed, MapPin, Map, Handshake,\n Contact, Building2, Filter, Plus, List, Shield, ListPlus, FolderOpen, User, Box, Boxes, Sparkles, Landmark, Receipt, Ban, Clock, Clock3, Inbox,\n Star, TrendingUp, UserCheck, UserPlus, UserX, Zap,\n}\n\n/** Long enough that a fast typist issues one request per word, not per letter. */\nconst DEBOUNCE_MS = 140\n\n// Highlighting — the matched run, in the record's own spelling\n\nfunction Highlight({ text, query }: { text: string; query: string }) {\n const parts = useMemo(() => {\n const normalized = normalizeQuery(query)\n const ranges = highlightRanges(text, normalized)\n if (ranges.length === 0) return [{ text, hit: false }]\n const out: Array<{ text: string; hit: boolean }> = []\n let cursor = 0\n for (const [from, to] of ranges) {\n if (from > cursor) out.push({ text: text.slice(cursor, from), hit: false })\n out.push({ text: text.slice(from, to), hit: true })\n cursor = to\n }\n if (cursor < text.length) out.push({ text: text.slice(cursor), hit: false })\n return out\n }, [text, query])\n\n return (\n <>\n {parts.map((part, i) =>\n part.hit\n ? <mark key={i} className=\"bg-transparent font-semibold text-foreground\">{part.text}</mark>\n : <React.Fragment key={i}>{part.text}</React.Fragment>,\n )}\n </>\n )\n}\n\n// Records arrive from the server; commands are already in memory. Same scorer,\n// different clocks — commands re-rank per keystroke, records refine as they land.\n\nfunction useEntitySearch(searchFn: EntitySearchFn | undefined, query: string, open: boolean) {\n const [result, setResult] = useState<GlobalSearchResult | null>(null)\n const [loading, setLoading] = useState(false)\n const generation = useRef(0)\n\n useEffect(() => {\n const trimmed = query.trim()\n if (!open || !searchFn || foldText(trimmed).length < MIN_QUERY_LENGTH) {\n setResult(null)\n setLoading(false)\n return\n }\n\n const token = ++generation.current\n setLoading(true)\n\n const timer = setTimeout(() => {\n searchFn(trimmed, (partial) => {\n // A partial must never replace a final answer for this same query.\n if (token === generation.current) setResult((prev) => (prev?.partial === false && prev.query === trimmed ? prev : partial))\n })\n .then((final) => {\n if (token !== generation.current) return\n setResult(final)\n setLoading(false)\n })\n .catch(() => {\n // Keep what is on screen: a failed refresh is not an empty result.\n if (token !== generation.current) return\n setLoading(false)\n })\n }, DEBOUNCE_MS)\n\n return () => clearTimeout(timer)\n }, [query, searchFn, open])\n\n return { result, loading }\n}\n\n/**\n * Commands, ranked by the same ladder records use. cmdk's own filter is OFF:\n * it re-filtered the SERVER's results with its own substring rules, so a record\n * matched by phone, by a note or by an accent-folded name was fetched and then\n * dropped — the list said \"no results\" while the footer counted them.\n */\nfunction useRankedCommands(commands: CommandItem[], query: string): CommandItem[] {\n return useMemo(() => {\n const trimmed = query.trim()\n if (!trimmed) return commands\n const normalized = normalizeQuery(trimmed)\n if (normalized.tokens.length === 0) return commands\n return commands\n .map((cmd) => ({\n cmd,\n score: scoreCandidate(normalized, {\n title: foldText(cmd.label),\n haystack: foldText(`${cmd.label} ${cmd.group ?? ''} ${cmd.keywords ?? ''} ${cmd.subtitle ?? ''}`),\n }),\n }))\n .filter((c) => c.score > 0)\n .sort((a, b) => b.score - a.score)\n .map((c) => c.cmd)\n }, [commands, query])\n}\n\nconst GROUP_HEADING =\n '[&_[cmdk-group-heading]]:px-3 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-[11px] [&_[cmdk-group-heading]]:font-semibold [&_[cmdk-group-heading]]:uppercase [&_[cmdk-group-heading]]:tracking-wider [&_[cmdk-group-heading]]:text-muted-foreground'\n\nconst ITEM =\n 'flex cursor-pointer items-center gap-3 rounded-lg px-3 py-2.5 text-sm outline-none transition-colors aria-selected:bg-muted'\n\nexport function CommandPalette({ commands = [], open, onOpenChange, onEntitySearch, onEntitySelect }: CommandPaletteProps) {\n const { t } = useTranslation()\n const [search, setSearch] = useState('')\n const { result, loading } = useEntitySearch(onEntitySearch, search, open)\n const rankedCommands = useRankedCommands(commands, search)\n\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if ((e.metaKey || e.ctrlKey) && e.key === 'k') {\n e.preventDefault()\n onOpenChange(!open)\n }\n }\n document.addEventListener('keydown', handleKeyDown)\n return () => document.removeEventListener('keydown', handleKeyDown)\n }, [open, onOpenChange])\n\n // Reset search when closed\n useEffect(() => {\n if (!open) setSearch('')\n }, [open])\n\n const grouped = rankedCommands.reduce<Record<string, CommandItem[]>>((acc, cmd) => {\n const group = cmd.group ?? 'Actions'\n if (!acc[group]) acc[group] = []\n acc[group].push(cmd)\n return acc\n }, {})\n\n const hasQuery = foldText(search).length >= MIN_QUERY_LENGTH\n // A lookup wants the client, not the page that lists clients.\n const recordGroups = hasQuery ? (result?.groups ?? []) : []\n const recordCount = recordGroups.reduce((n, g) => n + g.hits.length, 0)\n const totalResults = rankedCommands.length + recordCount\n const nothingYet = totalResults === 0\n\n return (\n <Dialog.Root open={open} onOpenChange={onOpenChange}>\n <Dialog.Portal>\n <Dialog.Overlay className=\"saas-overlay fixed inset-0 z-50 bg-black/40 backdrop-blur-sm\" />\n <Dialog.Content className=\"fayz-glass-surface saas-cmd-palette fixed left-1/2 top-[15%] z-50 w-full max-w-xl -translate-x-1/2 overflow-hidden rounded-2xl border border-border/50 bg-popover shadow-2xl\">\n <Dialog.Title className=\"sr-only\">{t('layout.commandPalette.title')}</Dialog.Title>\n <Dialog.Description className=\"sr-only\">{t('layout.commandPalette.description')}</Dialog.Description>\n\n <Command className=\"flex flex-col\" label=\"Command palette\" shouldFilter={false}>\n <div className=\"flex items-center gap-3 border-b border-border/50 px-4\">\n <Search className=\"h-4 w-4 shrink-0 text-muted-foreground\" />\n <Command.Input\n placeholder={t('layout.commandPalette.placeholder')}\n className=\"flex h-12 w-full bg-transparent text-sm outline-none placeholder:text-muted-foreground\"\n autoFocus\n value={search}\n onValueChange={setSearch}\n />\n {loading && <Loader2 className=\"h-3.5 w-3.5 shrink-0 animate-spin text-muted-foreground\" />}\n <kbd className=\"hidden shrink-0 rounded-md border border-border bg-muted px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground sm:inline-block\">ESC</kbd>\n </div>\n\n <Command.List className=\"max-h-[360px] overflow-y-auto p-1.5\">\n {nothingYet && (\n <Command.Empty className=\"py-8 text-center text-sm text-muted-foreground\">\n {loading ? t('layout.commandPalette.searching') : t('layout.commandPalette.noResults')}\n </Command.Empty>\n )}\n\n {/* Records first */}\n {recordGroups.map((group) => {\n const GroupIcon = group.icon ? (ICON_MAP[group.icon] ?? User) : User\n return (\n <Command.Group key={`entity:${group.key}`} heading={group.label} className={GROUP_HEADING}>\n {group.hits.map((hit) => {\n const Icon = hit.icon ? (ICON_MAP[hit.icon] ?? GroupIcon) : GroupIcon\n return (\n <Command.Item\n key={hit.uid}\n value={hit.uid}\n onSelect={() => { onEntitySelect?.(hit); onOpenChange(false) }}\n className={ITEM}\n >\n <Icon className=\"h-4 w-4 shrink-0 text-muted-foreground\" />\n <div className=\"min-w-0 flex-1\">\n <span className=\"block truncate\"><Highlight text={hit.title} query={search} /></span>\n {hit.subtitle && (\n <span className=\"block truncate text-[11px] text-muted-foreground\">\n <Highlight text={hit.subtitle} query={search} />\n </span>\n )}\n </div>\n <span className=\"shrink-0 text-[11px] text-muted-foreground/40\">{group.label}</span>\n </Command.Item>\n )\n })}\n </Command.Group>\n )\n })}\n\n {/* Pages and actions */}\n {Object.entries(grouped).map(([group, items]) => (\n <Command.Group key={group} heading={group} className={GROUP_HEADING}>\n {items.map((cmd, i) => {\n const Icon = cmd.icon ? (ICON_MAP[cmd.icon] ?? null) : null\n // Command ids are not unique — \"Clientes\" and its \"Lista\"\n // child both mint `page:/clients`. Also the cmdk value.\n const uid = `${group}:${cmd.id}:${i}`\n return (\n <Command.Item\n key={uid}\n value={uid}\n onSelect={() => { cmd.action(); onOpenChange(false) }}\n className={ITEM}\n >\n {Icon && <Icon className=\"h-4 w-4 shrink-0 text-muted-foreground\" />}\n <span className=\"flex-1\"><Highlight text={cmd.label} query={search} /></span>\n <span className=\"text-[11px] text-muted-foreground/40\">{cmd.group}</span>\n </Command.Item>\n )\n })}\n </Command.Group>\n ))}\n </Command.List>\n\n <div className=\"flex items-center justify-between border-t border-border/50 px-4 py-2\">\n <span className=\"text-xs text-muted-foreground\">\n {loading\n ? t('layout.commandPalette.searching')\n : hasQuery\n ? t('layout.commandPalette.resultCount', { count: String(totalResults), plural: totalResults !== 1 ? 's' : '' })\n : t('layout.commandPalette.commandCount', { count: String(commands.length), plural: commands.length !== 1 ? 's' : '' })}\n </span>\n <div className=\"flex items-center gap-2 text-[10px] text-muted-foreground\">\n <kbd className=\"rounded border border-border bg-muted px-1 py-0.5 font-medium\">↑↓</kbd>\n <span>{t('layout.commandPalette.navigate')}</span>\n <kbd className=\"rounded border border-border bg-muted px-1 py-0.5 font-medium\">↵</kbd>\n <span>{t('layout.commandPalette.open')}</span>\n </div>\n </div>\n </Command>\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n )\n}\n"]}
|