@shuffleio/shuffle-mcps 0.0.3 → 0.0.4

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.js CHANGED
@@ -1,13 +1,14 @@
1
1
  // ShuffleMCP.tsx
2
2
  import React, { useState, useEffect, useRef, useCallback, useMemo, useImperativeHandle } from "react";
3
3
  import { algoliasearch } from "algoliasearch";
4
- import "./singul-GZKBHJNI.css";
4
+ import "./shuffle-mcp-XZEVQXW2.css";
5
5
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6
6
  var DEFAULT_ALGOLIA_APP_ID = "JNSS5CFDZZ";
7
7
  var DEFAULT_ALGOLIA_API_KEY = "33e4e3564f4f060e96e0531957bed552";
8
8
  var DEFAULT_ALGOLIA_INDEX = "appsearch";
9
9
  var ShuffleMCP = React.forwardRef(({
10
10
  authToken,
11
+ orgId,
11
12
  placeholder = "Search apps...",
12
13
  layout = "list",
13
14
  gridColumns = 3,
@@ -53,6 +54,7 @@ var ShuffleMCP = React.forwardRef(({
53
54
  const [selectedIndex, setSelectedIndex] = useState(-1);
54
55
  const [internalSelectedApps, setInternalSelectedApps] = useState(selectedApps);
55
56
  const [authenticatedApps, setAuthenticatedApps] = useState(externalAuthenticatedApps || []);
57
+ const [drawerApp, setDrawerApp] = useState(null);
56
58
  const hasInitialized = useRef(false);
57
59
  const containerRef = useRef(null);
58
60
  const inputRef = useRef(null);
@@ -64,7 +66,8 @@ var ShuffleMCP = React.forwardRef(({
64
66
  try {
65
67
  const response = await fetch(`${apiBaseUrl}${authPath}`, {
66
68
  headers: {
67
- "Authorization": `Bearer ${apiKey}`
69
+ "Authorization": `Bearer ${apiKey}`,
70
+ ...orgId ? { "Org-Id": orgId } : {}
68
71
  }
69
72
  });
70
73
  if (response.ok) {
@@ -81,7 +84,7 @@ var ShuffleMCP = React.forwardRef(({
81
84
  };
82
85
  fetchAuthenticatedApps();
83
86
  }
84
- }, [apiKey, apiBaseUrl]);
87
+ }, [apiKey, apiBaseUrl, orgId]);
85
88
  useEffect(() => {
86
89
  if (!apiKey || disablePrivateApps) {
87
90
  setPrivateApps([]);
@@ -90,7 +93,10 @@ var ShuffleMCP = React.forwardRef(({
90
93
  const fetchPrivateApps = async () => {
91
94
  try {
92
95
  const response = await fetch(`${apiBaseUrl}${privateAppsPath}`, {
93
- headers: { "Authorization": `Bearer ${apiKey}` },
96
+ headers: {
97
+ "Authorization": `Bearer ${apiKey}`,
98
+ ...orgId ? { "Org-Id": orgId } : {}
99
+ },
94
100
  credentials: "include"
95
101
  });
96
102
  if (!response.ok) return;
@@ -122,7 +128,7 @@ var ShuffleMCP = React.forwardRef(({
122
128
  }
123
129
  };
124
130
  fetchPrivateApps();
125
- }, [apiKey, apiBaseUrl, privateAppsPath, disablePrivateApps]);
131
+ }, [apiKey, apiBaseUrl, privateAppsPath, disablePrivateApps, orgId]);
126
132
  useEffect(() => {
127
133
  if (authenticatedApps.length > 0 && results.length > 0) {
128
134
  const validatedApps = authenticatedApps.filter((auth) => auth.validation?.valid);
@@ -241,22 +247,24 @@ var ShuffleMCP = React.forwardRef(({
241
247
  }, 300);
242
248
  }, [performSearch, onSearchChange]);
243
249
  const selectApp = useCallback((app) => {
244
- const authUrl = `${apiBaseUrl}${appAuthPath}?app_id=${app.objectID}&auth=${authToken}&source=shuffle`;
250
+ const authUrl = `${apiBaseUrl}${appAuthPath}?app_id=${app.objectID}&auth=${authToken}&source=shuffle${orgId ? `&org_id=${encodeURIComponent(orgId)}` : ""}`;
245
251
  if (multiSelect) {
246
252
  const isAlreadySelected = internalSelectedApps.some((a) => a.objectID === app.objectID);
247
253
  const newSelection = isAlreadySelected ? internalSelectedApps.filter((a) => a.objectID !== app.objectID) : [...internalSelectedApps, app];
248
254
  setInternalSelectedApps(newSelection);
249
255
  onSelectionChange?.(newSelection);
250
256
  } else {
251
- onAppSelected?.({ app, authUrl });
252
- if (!preventDefault) {
253
- window.open(authUrl, "_blank");
257
+ if (onAppSelected) {
258
+ onAppSelected({ app, authUrl });
259
+ if (!preventDefault) {
260
+ window.open(authUrl, "_blank");
261
+ }
262
+ } else if (!preventDefault) {
263
+ setDrawerApp(app);
254
264
  }
255
265
  setIsOpen(false);
256
- setQuery("");
257
- setResults([]);
258
266
  }
259
- }, [authToken, apiBaseUrl, appAuthPath, multiSelect, internalSelectedApps, onAppSelected, onSelectionChange, preventDefault]);
267
+ }, [authToken, apiBaseUrl, appAuthPath, orgId, multiSelect, internalSelectedApps, onAppSelected, onSelectionChange, preventDefault]);
260
268
  const handleKeyDown = useCallback((event) => {
261
269
  if (!isOpen) return;
262
270
  switch (event.key) {
@@ -377,100 +385,163 @@ var ShuffleMCP = React.forwardRef(({
377
385
  app.objectID
378
386
  );
379
387
  };
380
- return /* @__PURE__ */ jsx(
388
+ return /* @__PURE__ */ jsxs(
381
389
  "div",
382
390
  {
383
391
  ref: containerRef,
384
392
  className: `singul-container ${inline ? "singul-inline" : ""} ${className}`,
385
393
  style: customStyles.container,
386
- children: /* @__PURE__ */ jsxs("div", { className: "singul-search-bar-container", children: [
387
- /* @__PURE__ */ jsxs("div", { className: "singul-search-input-wrapper", style: customStyles.inputWrapper, children: [
388
- /* @__PURE__ */ jsx(
389
- "input",
394
+ children: [
395
+ /* @__PURE__ */ jsxs("div", { className: "singul-search-bar-container", children: [
396
+ /* @__PURE__ */ jsxs("div", { className: "singul-search-input-wrapper", style: customStyles.inputWrapper, children: [
397
+ /* @__PURE__ */ jsx(
398
+ "input",
399
+ {
400
+ ref: inputRef,
401
+ type: "text",
402
+ className: "singul-search-input",
403
+ style: customStyles.input,
404
+ placeholder,
405
+ value: query,
406
+ onChange: handleInputChange,
407
+ onFocus: () => {
408
+ if (!inline && query.trim() && results.length > 0) {
409
+ setIsOpen(true);
410
+ }
411
+ },
412
+ onKeyDown: handleKeyDown,
413
+ autoComplete: "off"
414
+ }
415
+ ),
416
+ /* @__PURE__ */ jsx("div", { className: "singul-search-icon", style: customStyles.searchIcon, children: /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
417
+ /* @__PURE__ */ jsx("circle", { cx: "11", cy: "11", r: "8" }),
418
+ /* @__PURE__ */ jsx("path", { d: "m21 21-4.35-4.35" })
419
+ ] }) }),
420
+ isLoading && /* @__PURE__ */ jsx("div", { className: "singul-loading-spinner", style: customStyles.loadingSpinner, children: renderLoadingState ? renderLoadingState() : /* @__PURE__ */ jsx("div", { className: "singul-spinner", style: customStyles.spinner }) })
421
+ ] }),
422
+ showSourceFilter && privateApps.length > 0 && /* @__PURE__ */ jsx("div", { className: "singul-source-filter", role: "tablist", "aria-label": "Filter by app source", children: [
423
+ { key: "all", label: "All", count: results.length + filteredPrivateApps.length },
424
+ { key: "public", label: "Public", count: results.length },
425
+ { key: "private", label: "Private", count: filteredPrivateApps.length }
426
+ ].map((opt) => /* @__PURE__ */ jsxs(
427
+ "button",
428
+ {
429
+ type: "button",
430
+ role: "tab",
431
+ "aria-selected": sourceFilter === opt.key,
432
+ className: `singul-source-pill ${sourceFilter === opt.key ? "singul-source-pill-active" : ""}`,
433
+ onClick: () => setSourceFilter(opt.key),
434
+ children: [
435
+ opt.label,
436
+ /* @__PURE__ */ jsx("span", { className: "singul-source-count", children: opt.count })
437
+ ]
438
+ },
439
+ opt.key
440
+ )) }),
441
+ inline && /* @__PURE__ */ jsx(
442
+ "div",
390
443
  {
391
- ref: inputRef,
392
- type: "text",
393
- className: "singul-search-input",
394
- style: customStyles.input,
395
- placeholder,
396
- value: query,
397
- onChange: handleInputChange,
398
- onFocus: () => {
399
- if (!inline && query.trim() && results.length > 0) {
400
- setIsOpen(true);
401
- }
444
+ className: `singul-results-container ${layout === "grid" ? "singul-results-grid" : ""}`,
445
+ style: {
446
+ ...customStyles.resultsContainer,
447
+ ...getGridColumnsStyle,
448
+ ...layout === "grid" ? { display: "grid" } : {}
402
449
  },
403
- onKeyDown: handleKeyDown,
404
- autoComplete: "off"
450
+ children: displayResults.length > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
451
+ displayResults.map((app, index) => renderAppItem(app, index)),
452
+ /* @__PURE__ */ jsx("div", { className: "singul-end-of-results", style: {
453
+ padding: "10px 16px",
454
+ color: "rgba(255, 255, 255, 0.3)",
455
+ textAlign: "center",
456
+ fontSize: "11px",
457
+ gridColumn: "1 / -1"
458
+ }, children: "Can't find what you're looking for? Try a different search term." })
459
+ ] }) : query.trim() ? /* @__PURE__ */ jsx("div", { className: "singul-empty-state", style: customStyles.emptyState, children: renderEmptyState ? renderEmptyState() : /* @__PURE__ */ jsxs(Fragment, { children: [
460
+ 'No integrations match "',
461
+ query,
462
+ '". Try searching for a different app or category.'
463
+ ] }) }) : /* @__PURE__ */ jsx("div", { className: "singul-empty-state", style: customStyles.emptyState, children: "Start typing to search integrations..." })
405
464
  }
406
465
  ),
407
- /* @__PURE__ */ jsx("div", { className: "singul-search-icon", style: customStyles.searchIcon, children: /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
408
- /* @__PURE__ */ jsx("circle", { cx: "11", cy: "11", r: "8" }),
409
- /* @__PURE__ */ jsx("path", { d: "m21 21-4.35-4.35" })
410
- ] }) }),
411
- isLoading && /* @__PURE__ */ jsx("div", { className: "singul-loading-spinner", style: customStyles.loadingSpinner, children: renderLoadingState ? renderLoadingState() : /* @__PURE__ */ jsx("div", { className: "singul-spinner", style: customStyles.spinner }) })
466
+ !inline && isOpen && /* @__PURE__ */ jsx(
467
+ "div",
468
+ {
469
+ className: `singul-dropdown ${layout === "grid" ? "singul-dropdown-grid" : ""}`,
470
+ style: {
471
+ ...customStyles.dropdown,
472
+ ...getGridColumnsStyle,
473
+ ...layout === "grid" ? { display: "grid" } : {}
474
+ },
475
+ children: displayResults.length > 0 ? displayResults.map((app, index) => renderAppItem(app, index)) : /* @__PURE__ */ jsx("div", { className: "singul-empty-state", style: customStyles.emptyState, children: renderEmptyState ? renderEmptyState() : /* @__PURE__ */ jsxs(Fragment, { children: [
476
+ 'No apps found for "',
477
+ query,
478
+ '"'
479
+ ] }) })
480
+ }
481
+ )
412
482
  ] }),
413
- showSourceFilter && privateApps.length > 0 && /* @__PURE__ */ jsx("div", { className: "singul-source-filter", role: "tablist", "aria-label": "Filter by app source", children: [
414
- { key: "all", label: "All", count: results.length + filteredPrivateApps.length },
415
- { key: "public", label: "Public", count: results.length },
416
- { key: "private", label: "Private", count: filteredPrivateApps.length }
417
- ].map((opt) => /* @__PURE__ */ jsxs(
418
- "button",
419
- {
420
- type: "button",
421
- role: "tab",
422
- "aria-selected": sourceFilter === opt.key,
423
- className: `singul-source-pill ${sourceFilter === opt.key ? "singul-source-pill-active" : ""}`,
424
- onClick: () => setSourceFilter(opt.key),
425
- children: [
426
- opt.label,
427
- /* @__PURE__ */ jsx("span", { className: "singul-source-count", children: opt.count })
428
- ]
429
- },
430
- opt.key
431
- )) }),
432
- inline && /* @__PURE__ */ jsx(
433
- "div",
434
- {
435
- className: `singul-results-container ${layout === "grid" ? "singul-results-grid" : ""}`,
436
- style: {
437
- ...customStyles.resultsContainer,
438
- ...getGridColumnsStyle,
439
- ...layout === "grid" ? { display: "grid" } : {}
440
- },
441
- children: displayResults.length > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
442
- displayResults.map((app, index) => renderAppItem(app, index)),
443
- /* @__PURE__ */ jsx("div", { className: "singul-end-of-results", style: {
444
- padding: "10px 16px",
445
- color: "rgba(255, 255, 255, 0.3)",
446
- textAlign: "center",
447
- fontSize: "11px",
448
- gridColumn: "1 / -1"
449
- }, children: "Can't find what you're looking for? Try a different search term." })
450
- ] }) : query.trim() ? /* @__PURE__ */ jsx("div", { className: "singul-empty-state", style: customStyles.emptyState, children: renderEmptyState ? renderEmptyState() : /* @__PURE__ */ jsxs(Fragment, { children: [
451
- 'No integrations match "',
452
- query,
453
- '". Try searching for a different app or category.'
454
- ] }) }) : /* @__PURE__ */ jsx("div", { className: "singul-empty-state", style: customStyles.emptyState, children: "Start typing to search integrations..." })
455
- }
456
- ),
457
- !inline && isOpen && /* @__PURE__ */ jsx(
458
- "div",
459
- {
460
- className: `singul-dropdown ${layout === "grid" ? "singul-dropdown-grid" : ""}`,
461
- style: {
462
- ...customStyles.dropdown,
463
- ...getGridColumnsStyle,
464
- ...layout === "grid" ? { display: "grid" } : {}
465
- },
466
- children: displayResults.length > 0 ? displayResults.map((app, index) => renderAppItem(app, index)) : /* @__PURE__ */ jsx("div", { className: "singul-empty-state", style: customStyles.emptyState, children: renderEmptyState ? renderEmptyState() : /* @__PURE__ */ jsxs(Fragment, { children: [
467
- 'No apps found for "',
468
- query,
469
- '"'
470
- ] }) })
471
- }
472
- )
473
- ] })
483
+ drawerApp && (() => {
484
+ const norm = (n) => (n || "").toLowerCase().replace(/[\s_\-]+/g, "_");
485
+ const matchingAuths = authenticatedApps.filter(
486
+ (a) => norm(a.app?.name || "") === norm(drawerApp.name)
487
+ );
488
+ const drawerAuthUrl = `${apiBaseUrl}${appAuthPath}?app_id=${drawerApp.objectID}&auth=${authToken}&source=shuffle${orgId ? `&org_id=${encodeURIComponent(orgId)}` : ""}`;
489
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
490
+ /* @__PURE__ */ jsx("div", { className: "singul-drawer-backdrop", onClick: () => setDrawerApp(null) }),
491
+ /* @__PURE__ */ jsxs("aside", { className: "singul-drawer", role: "dialog", "aria-label": `${drawerApp.name} configuration`, children: [
492
+ /* @__PURE__ */ jsxs("header", { className: "singul-drawer-header", children: [
493
+ /* @__PURE__ */ jsxs("div", { className: "singul-drawer-title-row", children: [
494
+ drawerApp.image_url && /* @__PURE__ */ jsx("img", { src: drawerApp.image_url, alt: drawerApp.name, className: "singul-drawer-icon" }),
495
+ /* @__PURE__ */ jsxs("div", { children: [
496
+ /* @__PURE__ */ jsx("div", { className: "singul-drawer-title", children: drawerApp.name.replace(/_/g, " ") }),
497
+ /* @__PURE__ */ jsx("div", { className: "singul-drawer-subtitle", children: "App configuration" })
498
+ ] })
499
+ ] }),
500
+ /* @__PURE__ */ jsx(
501
+ "button",
502
+ {
503
+ type: "button",
504
+ className: "singul-drawer-close",
505
+ onClick: () => setDrawerApp(null),
506
+ "aria-label": "Close",
507
+ children: "\xD7"
508
+ }
509
+ )
510
+ ] }),
511
+ /* @__PURE__ */ jsxs("div", { className: "singul-drawer-body", children: [
512
+ drawerApp.description && /* @__PURE__ */ jsx("p", { className: "singul-drawer-desc", children: drawerApp.description }),
513
+ /* @__PURE__ */ jsxs("div", { className: "singul-drawer-section-title", children: [
514
+ "Authentication",
515
+ /* @__PURE__ */ jsxs("span", { className: "singul-drawer-count", children: [
516
+ matchingAuths.length,
517
+ " configuration",
518
+ matchingAuths.length === 1 ? "" : "s",
519
+ " found"
520
+ ] })
521
+ ] }),
522
+ matchingAuths.length > 0 ? /* @__PURE__ */ jsx("ul", { className: "singul-drawer-auth-list", children: matchingAuths.map((a) => /* @__PURE__ */ jsxs("li", { className: "singul-drawer-auth-item", children: [
523
+ /* @__PURE__ */ jsx("div", { className: "singul-drawer-auth-label", children: a.label || "Untitled" }),
524
+ /* @__PURE__ */ jsxs("div", { className: "singul-drawer-auth-chips", children: [
525
+ a.active && /* @__PURE__ */ jsx("span", { className: "singul-chip singul-chip-configured", children: "Configured" }),
526
+ a.validation?.valid && /* @__PURE__ */ jsx("span", { className: "singul-chip singul-chip-tested", children: "Tested" }),
527
+ !a.active && /* @__PURE__ */ jsx("span", { className: "singul-chip singul-chip-inactive", children: "Inactive" })
528
+ ] })
529
+ ] }, a.id)) }) : /* @__PURE__ */ jsx("div", { className: "singul-drawer-empty", children: "No authentications yet for this app." }),
530
+ /* @__PURE__ */ jsx(
531
+ "a",
532
+ {
533
+ href: drawerAuthUrl,
534
+ target: "_blank",
535
+ rel: "noopener noreferrer",
536
+ className: "singul-drawer-cta",
537
+ children: matchingAuths.length > 0 ? "Manage authentication" : "Add authentication"
538
+ }
539
+ )
540
+ ] })
541
+ ] })
542
+ ] });
543
+ })()
544
+ ]
474
545
  }
475
546
  );
476
547
  });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../ShuffleMCP.tsx"],"sourcesContent":["/**\n * Local Singul Library - React Component\n * This is a local copy for development. Changes here should be merged back to:\n * https://github.com/Shuffle/singul.js\n */\n\nimport React, { useState, useEffect, useRef, useCallback, useMemo, useImperativeHandle } from 'react';\nimport { algoliasearch, SearchClient } from 'algoliasearch';\nimport type { AlgoliaSearchApp, AppSelectedEvent, ShuffleMCPProps, AppAuthentication } from './singul.helpers';\nimport './singul.css';\n\nconst DEFAULT_ALGOLIA_APP_ID = 'JNSS5CFDZZ';\nconst DEFAULT_ALGOLIA_API_KEY = '33e4e3564f4f060e96e0531957bed552';\nconst DEFAULT_ALGOLIA_INDEX = 'appsearch';\n\nexport interface ShuffleMCPHandle {\n search: (query: string) => void;\n clear: () => void;\n}\n\nexport const ShuffleMCP = React.forwardRef<ShuffleMCPHandle, ShuffleMCPProps>(({\n authToken,\n placeholder = 'Search apps...',\n layout = 'list',\n gridColumns = 3,\n showDescription = false,\n showCategories = false,\n showCheckbox = false,\n multiSelect = false,\n selectedApps = [],\n preventDefault = false,\n inline = false,\n initialQuery = '',\n initialFilterQuery,\n hitsPerPage = 15,\n apiKey,\n apiBaseUrl = 'https://shuffler.io',\n authPath = '/api/v1/apps/authentication',\n appAuthPath = '/appauth',\n privateAppsPath = '/api/v1/apps',\n disablePrivateApps = false,\n showSourceFilter = true,\n singulBaseUrl = 'https://singul.io',\n hideAuthStatus = false,\n authenticatedApps: externalAuthenticatedApps,\n pinnedApps,\n algoliaAppId = DEFAULT_ALGOLIA_APP_ID,\n algoliaApiKey = DEFAULT_ALGOLIA_API_KEY,\n algoliaIndexName = DEFAULT_ALGOLIA_INDEX,\n customStyles = {},\n className = '',\n renderItem,\n renderEmptyState,\n renderLoadingState,\n onAppSelected,\n onSelectionChange,\n onSearchChange,\n}, ref) => {\n const [query, setQuery] = useState(initialQuery);\n const [results, setResults] = useState<AlgoliaSearchApp[]>([]);\n const [privateApps, setPrivateApps] = useState<AlgoliaSearchApp[]>([]);\n const [sourceFilter, setSourceFilter] = useState<'all' | 'public' | 'private'>('all');\n const [isLoading, setIsLoading] = useState(false);\n const [isOpen, setIsOpen] = useState(false);\n const [selectedIndex, setSelectedIndex] = useState(-1);\n const [internalSelectedApps, setInternalSelectedApps] = useState<AlgoliaSearchApp[]>(selectedApps);\n const [authenticatedApps, setAuthenticatedApps] = useState<AppAuthentication[]>(externalAuthenticatedApps || []);\n const hasInitialized = useRef(false);\n\n const containerRef = useRef<HTMLDivElement>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n const debounceTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n const searchClient = useRef<SearchClient | null>(null);\n\n // Fetch authenticated apps when apiKey is provided\n useEffect(() => {\n if (apiKey) {\n const fetchAuthenticatedApps = async () => {\n try {\n const response = await fetch(`${apiBaseUrl}${authPath}`, {\n headers: {\n 'Authorization': `Bearer ${apiKey}`,\n },\n });\n if (response.ok) {\n const result = await response.json();\n // Handle both { success: true, data: [...] } and direct array response\n const authData = result.data || result;\n if (Array.isArray(authData)) {\n console.log('Loaded authenticated apps:', authData.length, authData.map(a => a.app?.name));\n setAuthenticatedApps(authData);\n }\n }\n } catch (error) {\n console.error('Failed to fetch authenticated apps:', error);\n }\n };\n fetchAuthenticatedApps();\n }\n }, [apiKey, apiBaseUrl]);\n\n // Fetch the user's private apps from /api/v1/apps when apiKey is provided.\n // These get merged into search results so users can find their own apps too.\n useEffect(() => {\n if (!apiKey || disablePrivateApps) {\n setPrivateApps([]);\n return;\n }\n const fetchPrivateApps = async () => {\n try {\n const response = await fetch(`${apiBaseUrl}${privateAppsPath}`, {\n headers: { 'Authorization': `Bearer ${apiKey}` },\n credentials: 'include',\n });\n if (!response.ok) return;\n const data = await response.json();\n const apps = Array.isArray(data) ? data : (data?.data || []);\n // Normalize to AlgoliaSearchApp shape, tagged as 'private' source.\n const normalized: AlgoliaSearchApp[] = apps.map((a: any) => ({\n name: a.name || '',\n description: a.description || '',\n objectID: a.id || a.objectID || `private-${a.name}`,\n creator: a.owner || a.creator || '',\n app_version: a.app_version || '1.0.0',\n image_url: a.large_image || a.image_url || '',\n time_edited: a.edited || 0,\n generated: !!a.generated,\n invalid: !!a.invalid,\n priority: a.priority || 0,\n actions: Array.isArray(a.actions) ? a.actions.length : (a.actions || 0),\n tags: a.tags || [],\n accessible_by: a.accessible_by || [],\n categories: a.categories || [],\n action_labels: a.action_labels || [],\n triggers: a.triggers || [],\n verified: !!a.verified,\n source: 'private',\n }));\n setPrivateApps(normalized);\n } catch (error) {\n console.error('Failed to fetch private apps:', error);\n }\n };\n fetchPrivateApps();\n }, [apiKey, apiBaseUrl, privateAppsPath, disablePrivateApps]);\n\n // Auto-select validated apps when they're loaded (validated = tests ran successfully)\n useEffect(() => {\n if (authenticatedApps.length > 0 && results.length > 0) {\n const validatedApps = authenticatedApps.filter(auth => auth.validation?.valid);\n const appsToAutoSelect = results.filter(app => \n validatedApps.some(auth => auth.app.name.toLowerCase() === app.name.toLowerCase())\n );\n \n if (appsToAutoSelect.length > 0) {\n const newSelection = [...internalSelectedApps];\n appsToAutoSelect.forEach(app => {\n if (!newSelection.some(a => a.objectID === app.objectID)) {\n newSelection.push(app);\n }\n });\n if (newSelection.length !== internalSelectedApps.length) {\n setInternalSelectedApps(newSelection);\n onSelectionChange?.(newSelection);\n }\n }\n }\n }, [authenticatedApps, results]);\n\n // Sync external authenticatedApps\n useEffect(() => {\n if (externalAuthenticatedApps) {\n setAuthenticatedApps(externalAuthenticatedApps);\n }\n }, [externalAuthenticatedApps]);\n\n // Initialize Algolia client and run initial search\n useEffect(() => {\n searchClient.current = algoliasearch(algoliaAppId, algoliaApiKey);\n \n // Run initial search after client is ready\n if (!hasInitialized.current) {\n hasInitialized.current = true;\n const searchTerm = initialQuery || initialFilterQuery || '';\n setTimeout(() => {\n if (searchClient.current) {\n performSearch(searchTerm);\n onSearchChange?.(initialQuery); // Only report the visible query\n }\n }, 100);\n }\n }, []);\n\n // Sync external selectedApps\n useEffect(() => {\n setInternalSelectedApps(selectedApps);\n }, [selectedApps]);\n\n // Handle click outside\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (containerRef.current && !containerRef.current.contains(event.target as Node)) {\n setIsOpen(false);\n setSelectedIndex(-1);\n }\n };\n\n document.addEventListener('click', handleClickOutside);\n return () => document.removeEventListener('click', handleClickOutside);\n }, []);\n\n // Check if an app is configured (found in authentication API with active: true)\n const isAppConfigured = useCallback((app: AlgoliaSearchApp) => {\n return authenticatedApps.some(\n auth => auth.app.name.toLowerCase() === app.name.toLowerCase() && auth.active === true\n );\n }, [authenticatedApps]);\n\n // Check if an app is validated/tested (validation.valid is true)\n const isAppValidated = useCallback((app: AlgoliaSearchApp) => {\n return authenticatedApps.some(\n auth => auth.app.name.toLowerCase() === app.name.toLowerCase() && auth.validation?.valid === true\n );\n }, [authenticatedApps]);\n\n // Get auth state for an app\n const getAppAuthState = useCallback((app: AlgoliaSearchApp) => {\n return {\n configured: isAppConfigured(app),\n validated: isAppValidated(app),\n };\n }, [isAppConfigured, isAppValidated]);\n\n // Perform search\n const performSearch = useCallback(async (searchQuery: string) => {\n if (!searchClient.current) {\n return;\n }\n\n setIsLoading(true);\n try {\n const searchResult = await searchClient.current.searchSingleIndex({\n indexName: algoliaIndexName,\n searchParams: {\n query: searchQuery || '', // Empty string gets top results\n hitsPerPage,\n },\n });\n\n const hits = (searchResult.hits as AlgoliaSearchApp[]).map(h => ({ ...h, source: 'public' as const }));\n setResults(hits);\n setIsOpen(hits.length > 0);\n setSelectedIndex(-1);\n } catch (error) {\n console.error('Search failed:', error);\n setResults([]);\n setIsOpen(false);\n } finally {\n setIsLoading(false);\n }\n }, [hitsPerPage]);\n\n // Expose imperative methods via ref\n useImperativeHandle(ref, () => ({\n search: (searchQuery: string) => {\n setQuery(searchQuery);\n onSearchChange?.(searchQuery);\n performSearch(searchQuery);\n },\n clear: () => {\n setQuery('');\n performSearch(''); // Show top results when cleared\n },\n getQuery: () => query,\n }), [performSearch, onSearchChange, query]);\n\n // Handle input change\n const handleInputChange = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {\n const value = event.target.value;\n setQuery(value);\n setSelectedIndex(-1);\n onSearchChange?.(value);\n\n if (debounceTimer.current) {\n clearTimeout(debounceTimer.current);\n }\n\n debounceTimer.current = setTimeout(() => {\n performSearch(value);\n }, 300);\n }, [performSearch, onSearchChange]);\n\n // Handle app selection\n const selectApp = useCallback((app: AlgoliaSearchApp) => {\n const authUrl = `${apiBaseUrl}${appAuthPath}?app_id=${app.objectID}&auth=${authToken}&source=shuffle`;\n \n if (multiSelect) {\n const isAlreadySelected = internalSelectedApps.some((a) => a.objectID === app.objectID);\n const newSelection = isAlreadySelected\n ? internalSelectedApps.filter((a) => a.objectID !== app.objectID)\n : [...internalSelectedApps, app];\n \n setInternalSelectedApps(newSelection);\n onSelectionChange?.(newSelection);\n } else {\n onAppSelected?.({ app, authUrl });\n \n if (!preventDefault) {\n window.open(authUrl, '_blank');\n }\n \n setIsOpen(false);\n setQuery('');\n setResults([]);\n }\n }, [authToken, apiBaseUrl, appAuthPath, multiSelect, internalSelectedApps, onAppSelected, onSelectionChange, preventDefault]);\n\n // Handle keyboard navigation\n const handleKeyDown = useCallback((event: React.KeyboardEvent) => {\n if (!isOpen) return;\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n setSelectedIndex((prev) => Math.min(prev + 1, displayResults.length - 1));\n break;\n case 'ArrowUp':\n event.preventDefault();\n setSelectedIndex((prev) => Math.max(prev - 1, -1));\n break;\n case 'Enter':\n event.preventDefault();\n if (selectedIndex >= 0 && displayResults[selectedIndex]) {\n selectApp(displayResults[selectedIndex]);\n }\n break;\n case 'Escape':\n event.preventDefault();\n setIsOpen(false);\n setSelectedIndex(-1);\n inputRef.current?.blur();\n break;\n }\n }, [isOpen, results, selectedIndex, selectApp]);\n\n // Check if app is selected\n const isAppSelected = useCallback((app: AlgoliaSearchApp) => {\n return internalSelectedApps.some((a) => a.objectID === app.objectID);\n }, [internalSelectedApps]);\n\n // Filter the user's private apps client-side by the current query.\n const filteredPrivateApps = useMemo(() => {\n if (privateApps.length === 0) return [];\n const q = query.trim().toLowerCase();\n if (!q) return privateApps;\n return privateApps.filter(a =>\n a.name.toLowerCase().includes(q) ||\n (a.description || '').toLowerCase().includes(q) ||\n (a.categories || []).some(c => c.toLowerCase().includes(q))\n );\n }, [privateApps, query]);\n\n // Merge private + public apps, apply source filter, prepend pinned, dedupe by name.\n const displayResults = useMemo(() => {\n const norm = (n: string) => (n || '').toLowerCase().replace(/[\\s_\\-]+/g, '');\n\n let merged: AlgoliaSearchApp[];\n if (sourceFilter === 'public') {\n merged = results;\n } else if (sourceFilter === 'private') {\n merged = filteredPrivateApps;\n } else {\n // 'all' — private apps first (your own tools win), then public, deduped by name\n const privateNames = new Set(filteredPrivateApps.map(a => norm(a.name)));\n const publicOnly = results.filter(a => !privateNames.has(norm(a.name)));\n merged = [...filteredPrivateApps, ...publicOnly];\n }\n\n if (!pinnedApps || pinnedApps.length === 0) return merged;\n const pinnedNames = new Set(pinnedApps.map(a => norm(a.name)));\n return [...pinnedApps, ...merged.filter(a => !pinnedNames.has(norm(a.name)))];\n }, [pinnedApps, results, filteredPrivateApps, sourceFilter]);\n\n // Get grid columns style\n const getGridColumnsStyle = useMemo(() => {\n if (layout !== 'grid') return {};\n \n const cols = typeof gridColumns === 'number' ? gridColumns : gridColumns.md || 3;\n return { '--singul-grid-columns': cols } as React.CSSProperties;\n }, [layout, gridColumns]);\n\n // Render individual app item\n const renderAppItem = (app: AlgoliaSearchApp, index: number) => {\n const selected = isAppSelected(app);\n const isHighlighted = index === selectedIndex;\n const authState = getAppAuthState(app);\n\n // Use custom render if provided\n if (renderItem) {\n return (\n <div\n key={app.objectID}\n onClick={() => selectApp(app)}\n onMouseEnter={() => setSelectedIndex(index)}\n >\n {renderItem(app, selected, () => selectApp(app), authState)}\n </div>\n );\n }\n\n // Show both chips (configured/not configured AND tested/not tested)\n return (\n <div\n key={app.objectID}\n className={`singul-dropdown-item ${selected ? 'singul-selected' : ''} ${authState.validated ? 'singul-validated' : ''} ${authState.configured ? 'singul-configured' : ''}`}\n style={{\n ...customStyles.dropdownItem,\n ...(selected ? customStyles.selectedItem : {}),\n }}\n onClick={() => selectApp(app)}\n >\n <div className=\"singul-app-info\" style={customStyles.appInfo}>\n {app.image_url && (\n <div style={{ position: 'relative', flexShrink: 0 }}>\n <img\n src={app.image_url}\n alt={app.name}\n className=\"singul-app-icon\"\n style={customStyles.appIcon}\n />\n {/* Color-coded status dot: green=tested, yellow=configured, blue=activated/selected, gray=inactive */}\n {!hideAuthStatus && (\n <span\n className={`singul-status-dot ${\n authState.validated ? 'singul-dot-validated' :\n authState.configured ? 'singul-dot-configured' :\n selected ? 'singul-dot-activated' :\n 'singul-dot-inactive'\n }`}\n />\n )}\n </div>\n )}\n <div className=\"singul-app-details\" style={customStyles.appDetails}>\n <span className=\"singul-app-name\" style={customStyles.appName}>\n {app.name.replace(/_/g, ' ')}\n {app.source === 'private' && (\n <span className=\"singul-private-badge\" title=\"From your private apps\">Private</span>\n )}\n </span>\n {showDescription && app.description && (\n <span className=\"singul-app-description\" style={customStyles.appDescription}>\n {app.description}\n </span>\n )}\n {showCategories && app.categories?.[0] && (\n <span className=\"singul-app-category\" style={customStyles.appCategory}>\n {app.categories[0]}\n </span>\n )}\n </div>\n {showCheckbox && (\n <div\n className={`singul-checkbox ${selected ? 'singul-checked' : ''}`}\n style={selected ? customStyles.checkboxChecked : customStyles.checkbox}\n >\n {selected && (\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"3\">\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n )}\n </div>\n )}\n </div>\n </div>\n );\n };\n\n return (\n <div\n ref={containerRef}\n className={`singul-container ${inline ? 'singul-inline' : ''} ${className}`}\n style={customStyles.container}\n >\n <div className=\"singul-search-bar-container\">\n <div className=\"singul-search-input-wrapper\" style={customStyles.inputWrapper}>\n <input\n ref={inputRef}\n type=\"text\"\n className=\"singul-search-input\"\n style={customStyles.input}\n placeholder={placeholder}\n value={query}\n onChange={handleInputChange}\n onFocus={() => {\n if (!inline && query.trim() && results.length > 0) {\n setIsOpen(true);\n }\n }}\n onKeyDown={handleKeyDown}\n autoComplete=\"off\"\n />\n <div className=\"singul-search-icon\" style={customStyles.searchIcon}>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <path d=\"m21 21-4.35-4.35\" />\n </svg>\n </div>\n {isLoading && (\n <div className=\"singul-loading-spinner\" style={customStyles.loadingSpinner}>\n {renderLoadingState ? (\n renderLoadingState()\n ) : (\n <div className=\"singul-spinner\" style={customStyles.spinner} />\n )}\n </div>\n )}\n </div>\n\n {/* Source filter — only shown when private apps are loaded */}\n {showSourceFilter && privateApps.length > 0 && (\n <div className=\"singul-source-filter\" role=\"tablist\" aria-label=\"Filter by app source\">\n {([\n { key: 'all', label: 'All', count: results.length + filteredPrivateApps.length },\n { key: 'public', label: 'Public', count: results.length },\n { key: 'private', label: 'Private', count: filteredPrivateApps.length },\n ] as const).map(opt => (\n <button\n key={opt.key}\n type=\"button\"\n role=\"tab\"\n aria-selected={sourceFilter === opt.key}\n className={`singul-source-pill ${sourceFilter === opt.key ? 'singul-source-pill-active' : ''}`}\n onClick={() => setSourceFilter(opt.key)}\n >\n {opt.label}\n <span className=\"singul-source-count\">{opt.count}</span>\n </button>\n ))}\n </div>\n )}\n\n {/* Inline Results Container */}\n {inline && (\n <div\n className={`singul-results-container ${layout === 'grid' ? 'singul-results-grid' : ''}`}\n style={{\n ...customStyles.resultsContainer,\n ...getGridColumnsStyle,\n ...(layout === 'grid' ? { display: 'grid' } : {}),\n }}\n >\n {displayResults.length > 0 ? (\n <>\n {displayResults.map((app, index) => renderAppItem(app, index))}\n <div className=\"singul-end-of-results\" style={{\n padding: '10px 16px',\n color: 'rgba(255, 255, 255, 0.3)',\n textAlign: 'center' as const,\n fontSize: '11px',\n gridColumn: '1 / -1',\n }}>\n Can't find what you're looking for? Try a different search term.\n </div>\n </>\n ) : query.trim() ? (\n <div className=\"singul-empty-state\" style={customStyles.emptyState}>\n {renderEmptyState ? (\n renderEmptyState()\n ) : (\n <>No integrations match \"{query}\". Try searching for a different app or category.</>\n )}\n </div>\n ) : (\n <div className=\"singul-empty-state\" style={customStyles.emptyState}>\n Start typing to search integrations...\n </div>\n )}\n </div>\n )}\n\n {/* Dropdown Results (non-inline mode) */}\n {!inline && isOpen && (\n <div\n className={`singul-dropdown ${layout === 'grid' ? 'singul-dropdown-grid' : ''}`}\n style={{\n ...customStyles.dropdown,\n ...getGridColumnsStyle,\n ...(layout === 'grid' ? { display: 'grid' } : {}),\n }}\n >\n {displayResults.length > 0 ? (\n displayResults.map((app, index) => renderAppItem(app, index))\n ) : (\n <div className=\"singul-empty-state\" style={customStyles.emptyState}>\n {renderEmptyState ? (\n renderEmptyState()\n ) : (\n <>No apps found for \"{query}\"</>\n )}\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n );\n});\n\nShuffleMCP.displayName = 'ShuffleMCP';\n\nexport default ShuffleMCP;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../ShuffleMCP.tsx"],"sourcesContent":["/**\n * Local Singul Library - React Component\n * This is a local copy for development. Changes here should be merged back to:\n * https://github.com/Shuffle/singul.js\n */\n\nimport React, { useState, useEffect, useRef, useCallback, useMemo, useImperativeHandle } from 'react';\nimport { algoliasearch, SearchClient } from 'algoliasearch';\nimport type { AlgoliaSearchApp, AppSelectedEvent, ShuffleMCPProps, AppAuthentication } from './shuffle-mcp.helpers';\nimport './shuffle-mcp.css';\n\nconst DEFAULT_ALGOLIA_APP_ID = 'JNSS5CFDZZ';\nconst DEFAULT_ALGOLIA_API_KEY = '33e4e3564f4f060e96e0531957bed552';\nconst DEFAULT_ALGOLIA_INDEX = 'appsearch';\n\nexport interface ShuffleMCPHandle {\n search: (query: string) => void;\n clear: () => void;\n}\n\nexport const ShuffleMCP = React.forwardRef<ShuffleMCPHandle, ShuffleMCPProps>(({\n authToken,\n orgId,\n placeholder = 'Search apps...',\n layout = 'list',\n gridColumns = 3,\n showDescription = false,\n showCategories = false,\n showCheckbox = false,\n multiSelect = false,\n selectedApps = [],\n preventDefault = false,\n inline = false,\n initialQuery = '',\n initialFilterQuery,\n hitsPerPage = 15,\n apiKey,\n apiBaseUrl = 'https://shuffler.io',\n authPath = '/api/v1/apps/authentication',\n appAuthPath = '/appauth',\n privateAppsPath = '/api/v1/apps',\n disablePrivateApps = false,\n showSourceFilter = true,\n singulBaseUrl = 'https://singul.io',\n hideAuthStatus = false,\n authenticatedApps: externalAuthenticatedApps,\n pinnedApps,\n algoliaAppId = DEFAULT_ALGOLIA_APP_ID,\n algoliaApiKey = DEFAULT_ALGOLIA_API_KEY,\n algoliaIndexName = DEFAULT_ALGOLIA_INDEX,\n customStyles = {},\n className = '',\n renderItem,\n renderEmptyState,\n renderLoadingState,\n onAppSelected,\n onSelectionChange,\n onSearchChange,\n}, ref) => {\n const [query, setQuery] = useState(initialQuery);\n const [results, setResults] = useState<AlgoliaSearchApp[]>([]);\n const [privateApps, setPrivateApps] = useState<AlgoliaSearchApp[]>([]);\n const [sourceFilter, setSourceFilter] = useState<'all' | 'public' | 'private'>('all');\n const [isLoading, setIsLoading] = useState(false);\n const [isOpen, setIsOpen] = useState(false);\n const [selectedIndex, setSelectedIndex] = useState(-1);\n const [internalSelectedApps, setInternalSelectedApps] = useState<AlgoliaSearchApp[]>(selectedApps);\n const [authenticatedApps, setAuthenticatedApps] = useState<AppAuthentication[]>(externalAuthenticatedApps || []);\n const [drawerApp, setDrawerApp] = useState<AlgoliaSearchApp | null>(null);\n const hasInitialized = useRef(false);\n\n const containerRef = useRef<HTMLDivElement>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n const debounceTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n const searchClient = useRef<SearchClient | null>(null);\n\n // Fetch authenticated apps when apiKey is provided\n useEffect(() => {\n if (apiKey) {\n const fetchAuthenticatedApps = async () => {\n try {\n const response = await fetch(`${apiBaseUrl}${authPath}`, {\n headers: {\n 'Authorization': `Bearer ${apiKey}`,\n ...(orgId ? { 'Org-Id': orgId } : {}),\n },\n });\n if (response.ok) {\n const result = await response.json();\n // Handle both { success: true, data: [...] } and direct array response\n const authData = result.data || result;\n if (Array.isArray(authData)) {\n console.log('Loaded authenticated apps:', authData.length, authData.map(a => a.app?.name));\n setAuthenticatedApps(authData);\n }\n }\n } catch (error) {\n console.error('Failed to fetch authenticated apps:', error);\n }\n };\n fetchAuthenticatedApps();\n }\n }, [apiKey, apiBaseUrl, orgId]);\n\n // Fetch the user's private apps from /api/v1/apps when apiKey is provided.\n // These get merged into search results so users can find their own apps too.\n useEffect(() => {\n if (!apiKey || disablePrivateApps) {\n setPrivateApps([]);\n return;\n }\n const fetchPrivateApps = async () => {\n try {\n const response = await fetch(`${apiBaseUrl}${privateAppsPath}`, {\n headers: {\n 'Authorization': `Bearer ${apiKey}`,\n ...(orgId ? { 'Org-Id': orgId } : {}),\n },\n credentials: 'include',\n });\n if (!response.ok) return;\n const data = await response.json();\n const apps = Array.isArray(data) ? data : (data?.data || []);\n // Normalize to AlgoliaSearchApp shape, tagged as 'private' source.\n const normalized: AlgoliaSearchApp[] = apps.map((a: any) => ({\n name: a.name || '',\n description: a.description || '',\n objectID: a.id || a.objectID || `private-${a.name}`,\n creator: a.owner || a.creator || '',\n app_version: a.app_version || '1.0.0',\n image_url: a.large_image || a.image_url || '',\n time_edited: a.edited || 0,\n generated: !!a.generated,\n invalid: !!a.invalid,\n priority: a.priority || 0,\n actions: Array.isArray(a.actions) ? a.actions.length : (a.actions || 0),\n tags: a.tags || [],\n accessible_by: a.accessible_by || [],\n categories: a.categories || [],\n action_labels: a.action_labels || [],\n triggers: a.triggers || [],\n verified: !!a.verified,\n source: 'private',\n }));\n setPrivateApps(normalized);\n } catch (error) {\n console.error('Failed to fetch private apps:', error);\n }\n };\n fetchPrivateApps();\n }, [apiKey, apiBaseUrl, privateAppsPath, disablePrivateApps, orgId]);\n\n // Auto-select validated apps when they're loaded (validated = tests ran successfully)\n useEffect(() => {\n if (authenticatedApps.length > 0 && results.length > 0) {\n const validatedApps = authenticatedApps.filter(auth => auth.validation?.valid);\n const appsToAutoSelect = results.filter(app => \n validatedApps.some(auth => auth.app.name.toLowerCase() === app.name.toLowerCase())\n );\n \n if (appsToAutoSelect.length > 0) {\n const newSelection = [...internalSelectedApps];\n appsToAutoSelect.forEach(app => {\n if (!newSelection.some(a => a.objectID === app.objectID)) {\n newSelection.push(app);\n }\n });\n if (newSelection.length !== internalSelectedApps.length) {\n setInternalSelectedApps(newSelection);\n onSelectionChange?.(newSelection);\n }\n }\n }\n }, [authenticatedApps, results]);\n\n // Sync external authenticatedApps\n useEffect(() => {\n if (externalAuthenticatedApps) {\n setAuthenticatedApps(externalAuthenticatedApps);\n }\n }, [externalAuthenticatedApps]);\n\n // Initialize Algolia client and run initial search\n useEffect(() => {\n searchClient.current = algoliasearch(algoliaAppId, algoliaApiKey);\n \n // Run initial search after client is ready\n if (!hasInitialized.current) {\n hasInitialized.current = true;\n const searchTerm = initialQuery || initialFilterQuery || '';\n setTimeout(() => {\n if (searchClient.current) {\n performSearch(searchTerm);\n onSearchChange?.(initialQuery); // Only report the visible query\n }\n }, 100);\n }\n }, []);\n\n // Sync external selectedApps\n useEffect(() => {\n setInternalSelectedApps(selectedApps);\n }, [selectedApps]);\n\n // Handle click outside\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (containerRef.current && !containerRef.current.contains(event.target as Node)) {\n setIsOpen(false);\n setSelectedIndex(-1);\n }\n };\n\n document.addEventListener('click', handleClickOutside);\n return () => document.removeEventListener('click', handleClickOutside);\n }, []);\n\n // Check if an app is configured (found in authentication API with active: true)\n const isAppConfigured = useCallback((app: AlgoliaSearchApp) => {\n return authenticatedApps.some(\n auth => auth.app.name.toLowerCase() === app.name.toLowerCase() && auth.active === true\n );\n }, [authenticatedApps]);\n\n // Check if an app is validated/tested (validation.valid is true)\n const isAppValidated = useCallback((app: AlgoliaSearchApp) => {\n return authenticatedApps.some(\n auth => auth.app.name.toLowerCase() === app.name.toLowerCase() && auth.validation?.valid === true\n );\n }, [authenticatedApps]);\n\n // Get auth state for an app\n const getAppAuthState = useCallback((app: AlgoliaSearchApp) => {\n return {\n configured: isAppConfigured(app),\n validated: isAppValidated(app),\n };\n }, [isAppConfigured, isAppValidated]);\n\n // Perform search\n const performSearch = useCallback(async (searchQuery: string) => {\n if (!searchClient.current) {\n return;\n }\n\n setIsLoading(true);\n try {\n const searchResult = await searchClient.current.searchSingleIndex({\n indexName: algoliaIndexName,\n searchParams: {\n query: searchQuery || '', // Empty string gets top results\n hitsPerPage,\n },\n });\n\n const hits = (searchResult.hits as AlgoliaSearchApp[]).map(h => ({ ...h, source: 'public' as const }));\n setResults(hits);\n setIsOpen(hits.length > 0);\n setSelectedIndex(-1);\n } catch (error) {\n console.error('Search failed:', error);\n setResults([]);\n setIsOpen(false);\n } finally {\n setIsLoading(false);\n }\n }, [hitsPerPage]);\n\n // Expose imperative methods via ref\n useImperativeHandle(ref, () => ({\n search: (searchQuery: string) => {\n setQuery(searchQuery);\n onSearchChange?.(searchQuery);\n performSearch(searchQuery);\n },\n clear: () => {\n setQuery('');\n performSearch(''); // Show top results when cleared\n },\n getQuery: () => query,\n }), [performSearch, onSearchChange, query]);\n\n // Handle input change\n const handleInputChange = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {\n const value = event.target.value;\n setQuery(value);\n setSelectedIndex(-1);\n onSearchChange?.(value);\n\n if (debounceTimer.current) {\n clearTimeout(debounceTimer.current);\n }\n\n debounceTimer.current = setTimeout(() => {\n performSearch(value);\n }, 300);\n }, [performSearch, onSearchChange]);\n\n // Handle app selection\n const selectApp = useCallback((app: AlgoliaSearchApp) => {\n const authUrl = `${apiBaseUrl}${appAuthPath}?app_id=${app.objectID}&auth=${authToken}&source=shuffle${orgId ? `&org_id=${encodeURIComponent(orgId)}` : ''}`;\n\n if (multiSelect) {\n const isAlreadySelected = internalSelectedApps.some((a) => a.objectID === app.objectID);\n const newSelection = isAlreadySelected\n ? internalSelectedApps.filter((a) => a.objectID !== app.objectID)\n : [...internalSelectedApps, app];\n\n setInternalSelectedApps(newSelection);\n onSelectionChange?.(newSelection);\n } else {\n // If consumer wired up onAppSelected, defer entirely to them.\n if (onAppSelected) {\n onAppSelected({ app, authUrl });\n if (!preventDefault) {\n window.open(authUrl, '_blank');\n }\n } else if (!preventDefault) {\n // New default: open built-in side drawer with the app + its existing\n // authentications, instead of popping a new tab to shuffler.io.\n setDrawerApp(app);\n }\n\n setIsOpen(false);\n }\n }, [authToken, apiBaseUrl, appAuthPath, orgId, multiSelect, internalSelectedApps, onAppSelected, onSelectionChange, preventDefault]);\n\n // Handle keyboard navigation\n const handleKeyDown = useCallback((event: React.KeyboardEvent) => {\n if (!isOpen) return;\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n setSelectedIndex((prev) => Math.min(prev + 1, displayResults.length - 1));\n break;\n case 'ArrowUp':\n event.preventDefault();\n setSelectedIndex((prev) => Math.max(prev - 1, -1));\n break;\n case 'Enter':\n event.preventDefault();\n if (selectedIndex >= 0 && displayResults[selectedIndex]) {\n selectApp(displayResults[selectedIndex]);\n }\n break;\n case 'Escape':\n event.preventDefault();\n setIsOpen(false);\n setSelectedIndex(-1);\n inputRef.current?.blur();\n break;\n }\n }, [isOpen, results, selectedIndex, selectApp]);\n\n // Check if app is selected\n const isAppSelected = useCallback((app: AlgoliaSearchApp) => {\n return internalSelectedApps.some((a) => a.objectID === app.objectID);\n }, [internalSelectedApps]);\n\n // Filter the user's private apps client-side by the current query.\n const filteredPrivateApps = useMemo(() => {\n if (privateApps.length === 0) return [];\n const q = query.trim().toLowerCase();\n if (!q) return privateApps;\n return privateApps.filter(a =>\n a.name.toLowerCase().includes(q) ||\n (a.description || '').toLowerCase().includes(q) ||\n (a.categories || []).some(c => c.toLowerCase().includes(q))\n );\n }, [privateApps, query]);\n\n // Merge private + public apps, apply source filter, prepend pinned, dedupe by name.\n const displayResults = useMemo(() => {\n const norm = (n: string) => (n || '').toLowerCase().replace(/[\\s_\\-]+/g, '');\n\n let merged: AlgoliaSearchApp[];\n if (sourceFilter === 'public') {\n merged = results;\n } else if (sourceFilter === 'private') {\n merged = filteredPrivateApps;\n } else {\n // 'all' — private apps first (your own tools win), then public, deduped by name\n const privateNames = new Set(filteredPrivateApps.map(a => norm(a.name)));\n const publicOnly = results.filter(a => !privateNames.has(norm(a.name)));\n merged = [...filteredPrivateApps, ...publicOnly];\n }\n\n if (!pinnedApps || pinnedApps.length === 0) return merged;\n const pinnedNames = new Set(pinnedApps.map(a => norm(a.name)));\n return [...pinnedApps, ...merged.filter(a => !pinnedNames.has(norm(a.name)))];\n }, [pinnedApps, results, filteredPrivateApps, sourceFilter]);\n\n // Get grid columns style\n const getGridColumnsStyle = useMemo(() => {\n if (layout !== 'grid') return {};\n \n const cols = typeof gridColumns === 'number' ? gridColumns : gridColumns.md || 3;\n return { '--singul-grid-columns': cols } as React.CSSProperties;\n }, [layout, gridColumns]);\n\n // Render individual app item\n const renderAppItem = (app: AlgoliaSearchApp, index: number) => {\n const selected = isAppSelected(app);\n const isHighlighted = index === selectedIndex;\n const authState = getAppAuthState(app);\n\n // Use custom render if provided\n if (renderItem) {\n return (\n <div\n key={app.objectID}\n onClick={() => selectApp(app)}\n onMouseEnter={() => setSelectedIndex(index)}\n >\n {renderItem(app, selected, () => selectApp(app), authState)}\n </div>\n );\n }\n\n // Show both chips (configured/not configured AND tested/not tested)\n return (\n <div\n key={app.objectID}\n className={`singul-dropdown-item ${selected ? 'singul-selected' : ''} ${authState.validated ? 'singul-validated' : ''} ${authState.configured ? 'singul-configured' : ''}`}\n style={{\n ...customStyles.dropdownItem,\n ...(selected ? customStyles.selectedItem : {}),\n }}\n onClick={() => selectApp(app)}\n >\n <div className=\"singul-app-info\" style={customStyles.appInfo}>\n {app.image_url && (\n <div style={{ position: 'relative', flexShrink: 0 }}>\n <img\n src={app.image_url}\n alt={app.name}\n className=\"singul-app-icon\"\n style={customStyles.appIcon}\n />\n {/* Color-coded status dot: green=tested, yellow=configured, blue=activated/selected, gray=inactive */}\n {!hideAuthStatus && (\n <span\n className={`singul-status-dot ${\n authState.validated ? 'singul-dot-validated' :\n authState.configured ? 'singul-dot-configured' :\n selected ? 'singul-dot-activated' :\n 'singul-dot-inactive'\n }`}\n />\n )}\n </div>\n )}\n <div className=\"singul-app-details\" style={customStyles.appDetails}>\n <span className=\"singul-app-name\" style={customStyles.appName}>\n {app.name.replace(/_/g, ' ')}\n {app.source === 'private' && (\n <span className=\"singul-private-badge\" title=\"From your private apps\">Private</span>\n )}\n </span>\n {showDescription && app.description && (\n <span className=\"singul-app-description\" style={customStyles.appDescription}>\n {app.description}\n </span>\n )}\n {showCategories && app.categories?.[0] && (\n <span className=\"singul-app-category\" style={customStyles.appCategory}>\n {app.categories[0]}\n </span>\n )}\n </div>\n {showCheckbox && (\n <div\n className={`singul-checkbox ${selected ? 'singul-checked' : ''}`}\n style={selected ? customStyles.checkboxChecked : customStyles.checkbox}\n >\n {selected && (\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"3\">\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n )}\n </div>\n )}\n </div>\n </div>\n );\n };\n\n return (\n <div\n ref={containerRef}\n className={`singul-container ${inline ? 'singul-inline' : ''} ${className}`}\n style={customStyles.container}\n >\n <div className=\"singul-search-bar-container\">\n <div className=\"singul-search-input-wrapper\" style={customStyles.inputWrapper}>\n <input\n ref={inputRef}\n type=\"text\"\n className=\"singul-search-input\"\n style={customStyles.input}\n placeholder={placeholder}\n value={query}\n onChange={handleInputChange}\n onFocus={() => {\n if (!inline && query.trim() && results.length > 0) {\n setIsOpen(true);\n }\n }}\n onKeyDown={handleKeyDown}\n autoComplete=\"off\"\n />\n <div className=\"singul-search-icon\" style={customStyles.searchIcon}>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <path d=\"m21 21-4.35-4.35\" />\n </svg>\n </div>\n {isLoading && (\n <div className=\"singul-loading-spinner\" style={customStyles.loadingSpinner}>\n {renderLoadingState ? (\n renderLoadingState()\n ) : (\n <div className=\"singul-spinner\" style={customStyles.spinner} />\n )}\n </div>\n )}\n </div>\n\n {/* Source filter — only shown when private apps are loaded */}\n {showSourceFilter && privateApps.length > 0 && (\n <div className=\"singul-source-filter\" role=\"tablist\" aria-label=\"Filter by app source\">\n {([\n { key: 'all', label: 'All', count: results.length + filteredPrivateApps.length },\n { key: 'public', label: 'Public', count: results.length },\n { key: 'private', label: 'Private', count: filteredPrivateApps.length },\n ] as const).map(opt => (\n <button\n key={opt.key}\n type=\"button\"\n role=\"tab\"\n aria-selected={sourceFilter === opt.key}\n className={`singul-source-pill ${sourceFilter === opt.key ? 'singul-source-pill-active' : ''}`}\n onClick={() => setSourceFilter(opt.key)}\n >\n {opt.label}\n <span className=\"singul-source-count\">{opt.count}</span>\n </button>\n ))}\n </div>\n )}\n\n {/* Inline Results Container */}\n {inline && (\n <div\n className={`singul-results-container ${layout === 'grid' ? 'singul-results-grid' : ''}`}\n style={{\n ...customStyles.resultsContainer,\n ...getGridColumnsStyle,\n ...(layout === 'grid' ? { display: 'grid' } : {}),\n }}\n >\n {displayResults.length > 0 ? (\n <>\n {displayResults.map((app, index) => renderAppItem(app, index))}\n <div className=\"singul-end-of-results\" style={{\n padding: '10px 16px',\n color: 'rgba(255, 255, 255, 0.3)',\n textAlign: 'center' as const,\n fontSize: '11px',\n gridColumn: '1 / -1',\n }}>\n Can't find what you're looking for? Try a different search term.\n </div>\n </>\n ) : query.trim() ? (\n <div className=\"singul-empty-state\" style={customStyles.emptyState}>\n {renderEmptyState ? (\n renderEmptyState()\n ) : (\n <>No integrations match \"{query}\". Try searching for a different app or category.</>\n )}\n </div>\n ) : (\n <div className=\"singul-empty-state\" style={customStyles.emptyState}>\n Start typing to search integrations...\n </div>\n )}\n </div>\n )}\n\n {/* Dropdown Results (non-inline mode) */}\n {!inline && isOpen && (\n <div\n className={`singul-dropdown ${layout === 'grid' ? 'singul-dropdown-grid' : ''}`}\n style={{\n ...customStyles.dropdown,\n ...getGridColumnsStyle,\n ...(layout === 'grid' ? { display: 'grid' } : {}),\n }}\n >\n {displayResults.length > 0 ? (\n displayResults.map((app, index) => renderAppItem(app, index))\n ) : (\n <div className=\"singul-empty-state\" style={customStyles.emptyState}>\n {renderEmptyState ? (\n renderEmptyState()\n ) : (\n <>No apps found for \"{query}\"</>\n )}\n </div>\n )}\n </div>\n )}\n </div>\n\n {/* Built-in app auth drawer — shown when no custom onAppSelected handler is provided */}\n {drawerApp && (() => {\n const norm = (n: string) => (n || '').toLowerCase().replace(/[\\s_\\-]+/g, '_');\n const matchingAuths = authenticatedApps.filter(\n a => norm(a.app?.name || '') === norm(drawerApp.name)\n );\n const drawerAuthUrl = `${apiBaseUrl}${appAuthPath}?app_id=${drawerApp.objectID}&auth=${authToken}&source=shuffle${orgId ? `&org_id=${encodeURIComponent(orgId)}` : ''}`;\n return (\n <>\n <div className=\"singul-drawer-backdrop\" onClick={() => setDrawerApp(null)} />\n <aside className=\"singul-drawer\" role=\"dialog\" aria-label={`${drawerApp.name} configuration`}>\n <header className=\"singul-drawer-header\">\n <div className=\"singul-drawer-title-row\">\n {drawerApp.image_url && (\n <img src={drawerApp.image_url} alt={drawerApp.name} className=\"singul-drawer-icon\" />\n )}\n <div>\n <div className=\"singul-drawer-title\">{drawerApp.name.replace(/_/g, ' ')}</div>\n <div className=\"singul-drawer-subtitle\">App configuration</div>\n </div>\n </div>\n <button\n type=\"button\"\n className=\"singul-drawer-close\"\n onClick={() => setDrawerApp(null)}\n aria-label=\"Close\"\n >×</button>\n </header>\n\n <div className=\"singul-drawer-body\">\n {drawerApp.description && (\n <p className=\"singul-drawer-desc\">{drawerApp.description}</p>\n )}\n\n <div className=\"singul-drawer-section-title\">\n Authentication\n <span className=\"singul-drawer-count\">\n {matchingAuths.length} configuration{matchingAuths.length === 1 ? '' : 's'} found\n </span>\n </div>\n\n {matchingAuths.length > 0 ? (\n <ul className=\"singul-drawer-auth-list\">\n {matchingAuths.map(a => (\n <li key={a.id} className=\"singul-drawer-auth-item\">\n <div className=\"singul-drawer-auth-label\">{a.label || 'Untitled'}</div>\n <div className=\"singul-drawer-auth-chips\">\n {a.active && <span className=\"singul-chip singul-chip-configured\">Configured</span>}\n {a.validation?.valid && <span className=\"singul-chip singul-chip-tested\">Tested</span>}\n {!a.active && <span className=\"singul-chip singul-chip-inactive\">Inactive</span>}\n </div>\n </li>\n ))}\n </ul>\n ) : (\n <div className=\"singul-drawer-empty\">No authentications yet for this app.</div>\n )}\n\n <a\n href={drawerAuthUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"singul-drawer-cta\"\n >\n {matchingAuths.length > 0 ? 'Manage authentication' : 'Add authentication'}\n </a>\n </div>\n </aside>\n </>\n );\n })()}\n </div>\n );\n});\n\nShuffleMCP.displayName = 'ShuffleMCP';\n\nexport default ShuffleMCP;\n"],"mappings":"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","names":[]}