@seed-ship/mcp-ui-solid 2.0.0 → 2.1.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.
Files changed (140) hide show
  1. package/README.md +50 -1
  2. package/dist/components/AutocompleteDropdown.cjs +201 -0
  3. package/dist/components/AutocompleteDropdown.cjs.map +1 -0
  4. package/dist/components/AutocompleteDropdown.d.ts +71 -0
  5. package/dist/components/AutocompleteDropdown.d.ts.map +1 -0
  6. package/dist/components/AutocompleteDropdown.js +201 -0
  7. package/dist/components/AutocompleteDropdown.js.map +1 -0
  8. package/dist/components/AutocompleteFormField.cjs +289 -0
  9. package/dist/components/AutocompleteFormField.cjs.map +1 -0
  10. package/dist/components/AutocompleteFormField.d.ts +52 -0
  11. package/dist/components/AutocompleteFormField.d.ts.map +1 -0
  12. package/dist/components/AutocompleteFormField.js +289 -0
  13. package/dist/components/AutocompleteFormField.js.map +1 -0
  14. package/dist/components/DraggableGridItem.cjs +133 -0
  15. package/dist/components/DraggableGridItem.cjs.map +1 -0
  16. package/dist/components/DraggableGridItem.d.ts +95 -0
  17. package/dist/components/DraggableGridItem.d.ts.map +1 -0
  18. package/dist/components/DraggableGridItem.js +133 -0
  19. package/dist/components/DraggableGridItem.js.map +1 -0
  20. package/dist/components/EditableUIResourceRenderer.cjs +203 -0
  21. package/dist/components/EditableUIResourceRenderer.cjs.map +1 -0
  22. package/dist/components/EditableUIResourceRenderer.d.ts +43 -0
  23. package/dist/components/EditableUIResourceRenderer.d.ts.map +1 -0
  24. package/dist/components/EditableUIResourceRenderer.js +203 -0
  25. package/dist/components/EditableUIResourceRenderer.js.map +1 -0
  26. package/dist/components/GhostText.cjs +105 -0
  27. package/dist/components/GhostText.cjs.map +1 -0
  28. package/dist/components/GhostText.d.ts +113 -0
  29. package/dist/components/GhostText.d.ts.map +1 -0
  30. package/dist/components/GhostText.js +105 -0
  31. package/dist/components/GhostText.js.map +1 -0
  32. package/dist/components/ResizeHandle.cjs +173 -0
  33. package/dist/components/ResizeHandle.cjs.map +1 -0
  34. package/dist/components/ResizeHandle.d.ts +50 -0
  35. package/dist/components/ResizeHandle.d.ts.map +1 -0
  36. package/dist/components/ResizeHandle.js +173 -0
  37. package/dist/components/ResizeHandle.js.map +1 -0
  38. package/dist/context/AutocompleteContext.cjs +158 -0
  39. package/dist/context/AutocompleteContext.cjs.map +1 -0
  40. package/dist/context/AutocompleteContext.d.ts +77 -0
  41. package/dist/context/AutocompleteContext.d.ts.map +1 -0
  42. package/dist/context/AutocompleteContext.js +158 -0
  43. package/dist/context/AutocompleteContext.js.map +1 -0
  44. package/dist/hooks/index.d.ts +6 -0
  45. package/dist/hooks/index.d.ts.map +1 -1
  46. package/dist/hooks/useAutocomplete.cjs +234 -0
  47. package/dist/hooks/useAutocomplete.cjs.map +1 -0
  48. package/dist/hooks/useAutocomplete.d.ts +119 -0
  49. package/dist/hooks/useAutocomplete.d.ts.map +1 -0
  50. package/dist/hooks/useAutocomplete.js +234 -0
  51. package/dist/hooks/useAutocomplete.js.map +1 -0
  52. package/dist/hooks/useDragDrop.cjs +170 -0
  53. package/dist/hooks/useDragDrop.cjs.map +1 -0
  54. package/dist/hooks/useDragDrop.d.ts +100 -0
  55. package/dist/hooks/useDragDrop.d.ts.map +1 -0
  56. package/dist/hooks/useDragDrop.js +170 -0
  57. package/dist/hooks/useDragDrop.js.map +1 -0
  58. package/dist/hooks/useResize.cjs +209 -0
  59. package/dist/hooks/useResize.cjs.map +1 -0
  60. package/dist/hooks/useResize.d.ts +87 -0
  61. package/dist/hooks/useResize.d.ts.map +1 -0
  62. package/dist/hooks/useResize.js +209 -0
  63. package/dist/hooks/useResize.js.map +1 -0
  64. package/dist/hooks.cjs +6 -0
  65. package/dist/hooks.cjs.map +1 -1
  66. package/dist/hooks.d.cts +6 -0
  67. package/dist/hooks.d.ts +6 -0
  68. package/dist/hooks.js +6 -0
  69. package/dist/hooks.js.map +1 -1
  70. package/dist/index.cjs +29 -0
  71. package/dist/index.cjs.map +1 -1
  72. package/dist/index.d.cts +18 -3
  73. package/dist/index.d.ts +18 -3
  74. package/dist/index.d.ts.map +1 -1
  75. package/dist/index.js +29 -0
  76. package/dist/index.js.map +1 -1
  77. package/dist/plugins/duckdb.cjs +192 -0
  78. package/dist/plugins/duckdb.cjs.map +1 -0
  79. package/dist/plugins/duckdb.d.ts +20 -0
  80. package/dist/plugins/duckdb.d.ts.map +1 -0
  81. package/dist/plugins/duckdb.js +170 -0
  82. package/dist/plugins/duckdb.js.map +1 -0
  83. package/dist/plugins/groq.cjs +97 -0
  84. package/dist/plugins/groq.cjs.map +1 -0
  85. package/dist/plugins/groq.d.ts +13 -0
  86. package/dist/plugins/groq.d.ts.map +1 -0
  87. package/dist/plugins/groq.js +97 -0
  88. package/dist/plugins/groq.js.map +1 -0
  89. package/dist/plugins/index.d.ts +10 -0
  90. package/dist/plugins/index.d.ts.map +1 -0
  91. package/dist/plugins/rest.cjs +92 -0
  92. package/dist/plugins/rest.cjs.map +1 -0
  93. package/dist/plugins/rest.d.ts +13 -0
  94. package/dist/plugins/rest.d.ts.map +1 -0
  95. package/dist/plugins/rest.js +92 -0
  96. package/dist/plugins/rest.js.map +1 -0
  97. package/dist/plugins/supabase.cjs +79 -0
  98. package/dist/plugins/supabase.cjs.map +1 -0
  99. package/dist/plugins/supabase.d.ts +13 -0
  100. package/dist/plugins/supabase.d.ts.map +1 -0
  101. package/dist/plugins/supabase.js +79 -0
  102. package/dist/plugins/supabase.js.map +1 -0
  103. package/dist/services/validation.cjs +40 -1
  104. package/dist/services/validation.cjs.map +1 -1
  105. package/dist/services/validation.d.ts.map +1 -1
  106. package/dist/services/validation.js +40 -1
  107. package/dist/services/validation.js.map +1 -1
  108. package/dist/types/index.d.ts +430 -0
  109. package/dist/types/index.d.ts.map +1 -1
  110. package/dist/types.d.cts +430 -0
  111. package/dist/types.d.ts +430 -0
  112. package/package.json +16 -1
  113. package/src/components/AutocompleteDropdown.tsx +329 -0
  114. package/src/components/AutocompleteFormField.tsx +288 -0
  115. package/src/components/DraggableGridItem.tsx +274 -0
  116. package/src/components/EditableUIResourceRenderer.tsx +273 -0
  117. package/src/components/GhostText.tsx +262 -0
  118. package/src/components/ResizeHandle.tsx +262 -0
  119. package/src/context/AutocompleteContext.tsx +317 -0
  120. package/src/hooks/index.ts +23 -0
  121. package/src/hooks/useAutocomplete.test.ts +334 -0
  122. package/src/hooks/useAutocomplete.ts +466 -0
  123. package/src/hooks/useDragDrop.test.ts +355 -0
  124. package/src/hooks/useDragDrop.ts +379 -0
  125. package/src/hooks/useResize.test.ts +313 -0
  126. package/src/hooks/useResize.ts +372 -0
  127. package/src/index.ts +71 -0
  128. package/src/plugins/duckdb.ts +269 -0
  129. package/src/plugins/groq.ts +137 -0
  130. package/src/plugins/index.ts +14 -0
  131. package/src/plugins/rest.ts +147 -0
  132. package/src/plugins/supabase.ts +120 -0
  133. package/src/services/validation.ts +46 -0
  134. package/src/styles/autocomplete.css +356 -0
  135. package/src/styles/drag-drop.css +297 -0
  136. package/src/styles/index.css +7 -0
  137. package/src/types/index.ts +529 -0
  138. package/src/vite-env.d.ts +18 -0
  139. package/tsconfig.tsbuildinfo +1 -1
  140. package/vite.config.ts +2 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AutocompleteContext.js","sources":["../../src/context/AutocompleteContext.tsx"],"sourcesContent":["/**\n * AutocompleteContext - Context provider for autocomplete functionality\n * Manages plugins and provides unified autocomplete API\n *\n * Sprint Autocomplete Feature\n */\n\nimport {\n createContext,\n useContext,\n ParentComponent,\n Accessor,\n createSignal,\n createMemo,\n onCleanup\n} from 'solid-js'\nimport type {\n AutocompletePlugin,\n AutocompleteResult,\n AutocompleteContext as AutocompleteContextData,\n AutocompleteProviderConfig\n} from '../types'\n\n/**\n * Cache entry for autocomplete results\n */\ninterface CacheEntry {\n result: AutocompleteResult\n timestamp: number\n}\n\n/**\n * Context value interface\n */\nexport interface AutocompleteContextValue {\n /**\n * Get suggestions from a plugin\n */\n getSuggestions: (\n input: string,\n pluginId?: string,\n context?: AutocompleteContextData\n ) => Promise<AutocompleteResult>\n\n /**\n * Get registered plugins\n */\n plugins: Accessor<AutocompletePlugin[]>\n\n /**\n * Get default plugin ID\n */\n defaultPluginId: Accessor<string | undefined>\n\n /**\n * Check if a plugin is ready\n */\n isPluginReady: (pluginId: string) => boolean\n\n /**\n * Get plugin by ID\n */\n getPlugin: (pluginId: string) => AutocompletePlugin | undefined\n\n /**\n * Register a new plugin\n */\n registerPlugin: (plugin: AutocompletePlugin) => void\n\n /**\n * Unregister a plugin\n */\n unregisterPlugin: (pluginId: string) => void\n\n /**\n * Clear cache\n */\n clearCache: () => void\n\n /**\n * Global config\n */\n config: {\n debounceMs: number\n minChars: number\n cacheTtl: number\n cacheEnabled: boolean\n }\n}\n\n// Create context with undefined default\nconst AutocompleteCtx = createContext<AutocompleteContextValue>()\n\n/**\n * Props for AutocompleteProvider\n */\nexport interface AutocompleteProviderProps extends AutocompleteProviderConfig {\n children: any\n}\n\n/**\n * Generate cache key\n */\nfunction getCacheKey(input: string, pluginId: string, context?: AutocompleteContextData): string {\n const contextKey = context ? JSON.stringify(context) : ''\n return `${pluginId}:${input}:${contextKey}`\n}\n\n/**\n * AutocompleteProvider Component\n * Provides autocomplete context to child components\n */\nexport const AutocompleteProvider: ParentComponent<AutocompleteProviderProps> = (props) => {\n // Plugin registry\n const [plugins, setPlugins] = createSignal<AutocompletePlugin[]>(props.plugins || [])\n\n // Result cache\n const [cache, setCache] = createSignal<Map<string, CacheEntry>>(new Map())\n\n // Config with defaults\n const config = createMemo(() => ({\n debounceMs: props.debounceMs ?? 150,\n minChars: props.minChars ?? 1,\n cacheTtl: props.cacheTtl ?? 60000,\n cacheEnabled: props.cacheEnabled ?? true\n }))\n\n // Default plugin ID\n const defaultPluginId = createMemo(() => {\n if (props.defaultPlugin) return props.defaultPlugin\n const firstPlugin = plugins()[0]\n return firstPlugin?.id\n })\n\n /**\n * Get plugin by ID\n */\n const getPlugin = (pluginId: string): AutocompletePlugin | undefined => {\n return plugins().find(p => p.id === pluginId)\n }\n\n /**\n * Check if plugin is ready\n */\n const isPluginReady = (pluginId: string): boolean => {\n const plugin = getPlugin(pluginId)\n if (!plugin) return false\n if (plugin.isReady) return plugin.isReady()\n return true\n }\n\n /**\n * Check cache for result\n */\n const getFromCache = (key: string): AutocompleteResult | null => {\n if (!config().cacheEnabled) return null\n\n const entry = cache().get(key)\n if (!entry) return null\n\n const age = Date.now() - entry.timestamp\n if (age > config().cacheTtl) {\n // Expired, remove from cache\n setCache(prev => {\n const next = new Map(prev)\n next.delete(key)\n return next\n })\n return null\n }\n\n return { ...entry.result, cached: true }\n }\n\n /**\n * Add result to cache\n */\n const addToCache = (key: string, result: AutocompleteResult): void => {\n if (!config().cacheEnabled) return\n\n setCache(prev => {\n const next = new Map(prev)\n next.set(key, { result, timestamp: Date.now() })\n return next\n })\n }\n\n /**\n * Get suggestions from plugin\n */\n const getSuggestions = async (\n input: string,\n pluginId?: string,\n context?: AutocompleteContextData\n ): Promise<AutocompleteResult> => {\n const targetPluginId = pluginId || defaultPluginId()\n\n if (!targetPluginId) {\n return { type: 'options', options: [], pluginId: undefined }\n }\n\n const plugin = getPlugin(targetPluginId)\n if (!plugin) {\n console.warn(`[Autocomplete] Plugin not found: ${targetPluginId}`)\n return { type: 'options', options: [], pluginId: targetPluginId }\n }\n\n // Check cache\n const cacheKey = getCacheKey(input, targetPluginId, context)\n const cached = getFromCache(cacheKey)\n if (cached) {\n return cached\n }\n\n try {\n const result = await plugin.getSuggestions(input, context)\n result.pluginId = targetPluginId\n\n // Cache result\n addToCache(cacheKey, result)\n\n return result\n } catch (error) {\n console.error(`[Autocomplete] Plugin error (${targetPluginId}):`, error)\n return {\n type: 'options',\n options: [],\n pluginId: targetPluginId\n }\n }\n }\n\n /**\n * Register a new plugin\n */\n const registerPlugin = (plugin: AutocompletePlugin): void => {\n setPlugins(prev => {\n // Remove existing plugin with same ID\n const filtered = prev.filter(p => p.id !== plugin.id)\n return [...filtered, plugin]\n })\n }\n\n /**\n * Unregister a plugin\n */\n const unregisterPlugin = (pluginId: string): void => {\n const plugin = getPlugin(pluginId)\n if (plugin?.dispose) {\n plugin.dispose()\n }\n setPlugins(prev => prev.filter(p => p.id !== pluginId))\n }\n\n /**\n * Clear cache\n */\n const clearCache = (): void => {\n setCache(new Map())\n }\n\n // Cleanup on unmount\n onCleanup(() => {\n // Dispose all plugins\n plugins().forEach(plugin => {\n if (plugin.dispose) {\n try {\n plugin.dispose()\n } catch (e) {\n console.error(`[Autocomplete] Error disposing plugin ${plugin.id}:`, e)\n }\n }\n })\n })\n\n // Context value\n const contextValue: AutocompleteContextValue = {\n getSuggestions,\n plugins,\n defaultPluginId,\n isPluginReady,\n getPlugin,\n registerPlugin,\n unregisterPlugin,\n clearCache,\n config: config()\n }\n\n return (\n <AutocompleteCtx.Provider value={contextValue}>\n {props.children}\n </AutocompleteCtx.Provider>\n )\n}\n\n/**\n * Hook to use autocomplete context\n * @throws Error if used outside provider\n */\nexport function useAutocompleteContext(): AutocompleteContextValue {\n const context = useContext(AutocompleteCtx)\n if (!context) {\n throw new Error(\n 'useAutocompleteContext must be used within an AutocompleteProvider'\n )\n }\n return context\n}\n\n/**\n * Safe hook that returns undefined if outside provider\n */\nexport function useAutocompleteContextSafe(): AutocompleteContextValue | undefined {\n return useContext(AutocompleteCtx)\n}\n\nexport { AutocompleteCtx }\n"],"names":["AutocompleteCtx","createContext","getCacheKey","input","pluginId","context","contextKey","JSON","stringify","AutocompleteProvider","props","plugins","setPlugins","createSignal","cache","setCache","Map","config","createMemo","debounceMs","minChars","cacheTtl","cacheEnabled","defaultPluginId","defaultPlugin","firstPlugin","id","getPlugin","find","p","isPluginReady","plugin","isReady","getFromCache","key","entry","get","age","Date","now","timestamp","prev","next","delete","result","cached","addToCache","set","getSuggestions","targetPluginId","type","options","undefined","console","warn","cacheKey","error","registerPlugin","filtered","filter","unregisterPlugin","dispose","clearCache","onCleanup","forEach","e","contextValue","_$createComponent","Provider","value","children","useAutocompleteContext","useContext","Error","useAutocompleteContextSafe"],"mappings":"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"}
@@ -13,4 +13,10 @@ export { useModal, useConfirmModal } from './useModal';
13
13
  export type { UseModalReturn, UseConfirmModalReturn } from './useModal';
14
14
  export { useFormPersistence } from './useFormPersistence';
15
15
  export type { UseFormPersistenceOptions, UseFormPersistenceReturn } from './useFormPersistence';
16
+ export { useDragDrop } from './useDragDrop';
17
+ export type { UseDragDropOptions, UseDragDropReturn, DragProps, } from './useDragDrop';
18
+ export { useResize } from './useResize';
19
+ export type { UseResizeOptions, UseResizeReturn, ResizeEdge, ResizeHandleProps, } from './useResize';
20
+ export { useAutocomplete } from './useAutocomplete';
21
+ export type { UseAutocompleteOptions, UseAutocompleteReturn, } from './useAutocomplete';
16
22
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AACjD,YAAY,EACV,qBAAqB,EACrB,gBAAgB,EAChB,cAAc,EACd,WAAW,EACX,gBAAgB,GACjB,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AACtD,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,aAAa,EACb,YAAY,GACb,MAAM,aAAa,CAAA;AAGpB,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AAC9E,YAAY,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAA;AAGvE,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AACtD,YAAY,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAGvE,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AACzD,YAAY,EAAE,yBAAyB,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AACjD,YAAY,EACV,qBAAqB,EACrB,gBAAgB,EAChB,cAAc,EACd,WAAW,EACX,gBAAgB,GACjB,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AACtD,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,aAAa,EACb,YAAY,GACb,MAAM,aAAa,CAAA;AAGpB,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AAC9E,YAAY,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAA;AAGvE,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AACtD,YAAY,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAGvE,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AACzD,YAAY,EAAE,yBAAyB,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAA;AAG/F,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,YAAY,EACV,kBAAkB,EAClB,iBAAiB,EACjB,SAAS,GACV,MAAM,eAAe,CAAA;AAEtB,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,YAAY,EACV,gBAAgB,EAChB,eAAe,EACf,UAAU,EACV,iBAAiB,GAClB,MAAM,aAAa,CAAA;AAGpB,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,YAAY,EACV,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,mBAAmB,CAAA"}
@@ -0,0 +1,234 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const solidJs = require("solid-js");
4
+ const web = require("solid-js/web");
5
+ const AutocompleteContext = require("../context/AutocompleteContext.cjs");
6
+ function debounce(fn, delay) {
7
+ let timeoutId = null;
8
+ return {
9
+ call: (...args) => {
10
+ if (timeoutId) clearTimeout(timeoutId);
11
+ timeoutId = setTimeout(() => {
12
+ fn(...args);
13
+ timeoutId = null;
14
+ }, delay);
15
+ },
16
+ cancel: () => {
17
+ if (timeoutId) {
18
+ clearTimeout(timeoutId);
19
+ timeoutId = null;
20
+ }
21
+ }
22
+ };
23
+ }
24
+ function useAutocomplete(options) {
25
+ const {
26
+ inputValue,
27
+ pluginId,
28
+ fieldConfig,
29
+ context,
30
+ enabled = true,
31
+ onInputChange,
32
+ minChars: minCharsOption,
33
+ debounceMs: debounceOption
34
+ } = options;
35
+ const autocompleteCtx = AutocompleteContext.useAutocompleteContextSafe();
36
+ const [completion, setCompletion] = solidJs.createSignal(null);
37
+ const [options_, setOptions] = solidJs.createSignal([]);
38
+ const [selectedIndex, setSelectedIndex] = solidJs.createSignal(-1);
39
+ const [isLoading, setIsLoading] = solidJs.createSignal(false);
40
+ const [error, setError] = solidJs.createSignal(null);
41
+ const [isOpen, setIsOpen] = solidJs.createSignal(false);
42
+ const [resultType, setResultType] = solidJs.createSignal(null);
43
+ const config = solidJs.createMemo(() => ({
44
+ minChars: minCharsOption ?? (fieldConfig == null ? void 0 : fieldConfig.minChars) ?? (autocompleteCtx == null ? void 0 : autocompleteCtx.config.minChars) ?? 1,
45
+ debounceMs: debounceOption ?? (fieldConfig == null ? void 0 : fieldConfig.debounceMs) ?? (autocompleteCtx == null ? void 0 : autocompleteCtx.config.debounceMs) ?? 150
46
+ }));
47
+ const ghostText = solidJs.createMemo(() => {
48
+ const comp = completion();
49
+ const input = inputValue();
50
+ if (!comp || !input) return "";
51
+ if (comp.toLowerCase().startsWith(input.toLowerCase())) {
52
+ return comp.slice(input.length);
53
+ }
54
+ return "";
55
+ });
56
+ const fetchSuggestions = async (input) => {
57
+ if (!autocompleteCtx) {
58
+ return;
59
+ }
60
+ if (input.length < config().minChars) {
61
+ solidJs.batch(() => {
62
+ setCompletion(null);
63
+ setOptions([]);
64
+ setIsOpen(false);
65
+ setResultType(null);
66
+ });
67
+ return;
68
+ }
69
+ setIsLoading(true);
70
+ setError(null);
71
+ try {
72
+ const targetPluginId = pluginId ?? (fieldConfig == null ? void 0 : fieldConfig.plugin);
73
+ const contextData = context == null ? void 0 : context();
74
+ const result = await autocompleteCtx.getSuggestions(
75
+ input,
76
+ targetPluginId,
77
+ contextData
78
+ );
79
+ solidJs.batch(() => {
80
+ var _a;
81
+ setResultType(result.type);
82
+ if (result.type === "completion") {
83
+ setCompletion(result.completion || null);
84
+ setOptions([]);
85
+ setIsOpen(!!result.completion);
86
+ } else {
87
+ setCompletion(null);
88
+ setOptions(result.options || []);
89
+ setSelectedIndex(-1);
90
+ setIsOpen((((_a = result.options) == null ? void 0 : _a.length) || 0) > 0);
91
+ }
92
+ setIsLoading(false);
93
+ });
94
+ } catch (e) {
95
+ solidJs.batch(() => {
96
+ setError(e instanceof Error ? e.message : "Unknown error");
97
+ setIsLoading(false);
98
+ setIsOpen(false);
99
+ });
100
+ }
101
+ };
102
+ const debouncedFetch = debounce(fetchSuggestions, config().debounceMs);
103
+ solidJs.createEffect(
104
+ solidJs.on(inputValue, (value) => {
105
+ if (!enabled || !autocompleteCtx || web.isServer) {
106
+ return;
107
+ }
108
+ debouncedFetch.call(value);
109
+ })
110
+ );
111
+ solidJs.onCleanup(() => {
112
+ debouncedFetch.cancel();
113
+ });
114
+ const acceptCompletion = () => {
115
+ const comp = completion();
116
+ if (comp && onInputChange) {
117
+ onInputChange(comp);
118
+ solidJs.batch(() => {
119
+ setCompletion(null);
120
+ setIsOpen(false);
121
+ });
122
+ }
123
+ };
124
+ const selectOption = (option) => {
125
+ if (onInputChange) {
126
+ onInputChange(option.value);
127
+ }
128
+ solidJs.batch(() => {
129
+ setOptions([]);
130
+ setSelectedIndex(-1);
131
+ setIsOpen(false);
132
+ });
133
+ };
134
+ const nextOption = () => {
135
+ const opts = options_();
136
+ if (opts.length === 0) return;
137
+ setSelectedIndex((prev) => {
138
+ const next = prev + 1;
139
+ return next >= opts.length ? 0 : next;
140
+ });
141
+ };
142
+ const prevOption = () => {
143
+ const opts = options_();
144
+ if (opts.length === 0) return;
145
+ setSelectedIndex((prev) => {
146
+ const next = prev - 1;
147
+ return next < 0 ? opts.length - 1 : next;
148
+ });
149
+ };
150
+ const selectCurrentOption = () => {
151
+ const idx = selectedIndex();
152
+ const opts = options_();
153
+ if (idx >= 0 && idx < opts.length) {
154
+ selectOption(opts[idx]);
155
+ }
156
+ };
157
+ const dismiss = () => {
158
+ debouncedFetch.cancel();
159
+ solidJs.batch(() => {
160
+ setCompletion(null);
161
+ setOptions([]);
162
+ setSelectedIndex(-1);
163
+ setIsOpen(false);
164
+ setError(null);
165
+ });
166
+ };
167
+ const open = () => {
168
+ const input = inputValue();
169
+ if (input.length >= config().minChars) {
170
+ fetchSuggestions(input);
171
+ }
172
+ };
173
+ const handleKeyDown = (e) => {
174
+ if (!isOpen()) return false;
175
+ const type = resultType();
176
+ if (e.key === "Tab" && type === "completion" && ghostText()) {
177
+ e.preventDefault();
178
+ acceptCompletion();
179
+ return true;
180
+ }
181
+ if (type === "options") {
182
+ switch (e.key) {
183
+ case "ArrowDown":
184
+ e.preventDefault();
185
+ nextOption();
186
+ return true;
187
+ case "ArrowUp":
188
+ e.preventDefault();
189
+ prevOption();
190
+ return true;
191
+ case "Enter":
192
+ if (selectedIndex() >= 0) {
193
+ e.preventDefault();
194
+ selectCurrentOption();
195
+ return true;
196
+ }
197
+ break;
198
+ case "Tab":
199
+ if (selectedIndex() >= 0) {
200
+ e.preventDefault();
201
+ selectCurrentOption();
202
+ return true;
203
+ }
204
+ break;
205
+ }
206
+ }
207
+ if (e.key === "Escape") {
208
+ e.preventDefault();
209
+ dismiss();
210
+ return true;
211
+ }
212
+ return false;
213
+ };
214
+ return {
215
+ completion,
216
+ ghostText,
217
+ acceptCompletion,
218
+ options: options_,
219
+ selectedIndex,
220
+ selectOption,
221
+ nextOption,
222
+ prevOption,
223
+ selectCurrentOption,
224
+ isLoading,
225
+ error,
226
+ dismiss,
227
+ isOpen,
228
+ resultType,
229
+ open,
230
+ handleKeyDown
231
+ };
232
+ }
233
+ exports.useAutocomplete = useAutocomplete;
234
+ //# sourceMappingURL=useAutocomplete.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAutocomplete.cjs","sources":["../../src/hooks/useAutocomplete.ts"],"sourcesContent":["/**\n * useAutocomplete Hook\n * Provides autocomplete functionality for form fields\n *\n * Sprint Autocomplete Feature\n */\n\nimport {\n createSignal,\n createEffect,\n on,\n Accessor,\n onCleanup,\n batch,\n createMemo\n} from 'solid-js'\nimport { isServer } from 'solid-js/web'\nimport { useAutocompleteContextSafe } from '../context/AutocompleteContext'\nimport type {\n AutocompleteOption,\n AutocompleteContext,\n FieldAutocompleteConfig\n} from '../types'\n\n/**\n * Options for the useAutocomplete hook\n */\nexport interface UseAutocompleteOptions {\n /**\n * Current input value accessor\n */\n inputValue: Accessor<string>\n\n /**\n * Plugin ID to use (overrides default)\n */\n pluginId?: string\n\n /**\n * Field configuration\n */\n fieldConfig?: FieldAutocompleteConfig\n\n /**\n * Context data for suggestions\n */\n context?: Accessor<AutocompleteContext>\n\n /**\n * Whether autocomplete is enabled\n */\n enabled?: boolean\n\n /**\n * Callback when input value should change (for accepting suggestions)\n */\n onInputChange?: (value: string) => void\n\n /**\n * Minimum characters before triggering\n */\n minChars?: number\n\n /**\n * Debounce delay in ms\n */\n debounceMs?: number\n}\n\n/**\n * Return type for the useAutocomplete hook\n */\nexport interface UseAutocompleteReturn {\n /**\n * Current completion text (for ghost text, LLM mode)\n */\n completion: Accessor<string | null>\n\n /**\n * Ghost text to show (remaining text after input)\n */\n ghostText: Accessor<string>\n\n /**\n * Accept the current completion\n */\n acceptCompletion: () => void\n\n /**\n * Current options (for dropdown, data mode)\n */\n options: Accessor<AutocompleteOption[]>\n\n /**\n * Currently selected option index\n */\n selectedIndex: Accessor<number>\n\n /**\n * Select an option by index\n */\n selectOption: (option: AutocompleteOption) => void\n\n /**\n * Navigate to next option\n */\n nextOption: () => void\n\n /**\n * Navigate to previous option\n */\n prevOption: () => void\n\n /**\n * Select current highlighted option\n */\n selectCurrentOption: () => void\n\n /**\n * Whether suggestions are loading\n */\n isLoading: Accessor<boolean>\n\n /**\n * Error message if any\n */\n error: Accessor<string | null>\n\n /**\n * Dismiss suggestions\n */\n dismiss: () => void\n\n /**\n * Whether suggestions are visible\n */\n isOpen: Accessor<boolean>\n\n /**\n * Result type ('completion' or 'options')\n */\n resultType: Accessor<'completion' | 'options' | null>\n\n /**\n * Open/show suggestions\n */\n open: () => void\n\n /**\n * Handle keyboard events\n */\n handleKeyDown: (e: KeyboardEvent) => boolean\n}\n\n/**\n * Debounce helper\n */\nfunction debounce<T extends (...args: any[]) => any>(\n fn: T,\n delay: number\n): { call: (...args: Parameters<T>) => void; cancel: () => void } {\n let timeoutId: ReturnType<typeof setTimeout> | null = null\n\n return {\n call: (...args: Parameters<T>) => {\n if (timeoutId) clearTimeout(timeoutId)\n timeoutId = setTimeout(() => {\n fn(...args)\n timeoutId = null\n }, delay)\n },\n cancel: () => {\n if (timeoutId) {\n clearTimeout(timeoutId)\n timeoutId = null\n }\n }\n }\n}\n\n/**\n * Hook for autocomplete functionality\n */\nexport function useAutocomplete(options: UseAutocompleteOptions): UseAutocompleteReturn {\n const {\n inputValue,\n pluginId,\n fieldConfig,\n context,\n enabled = true,\n onInputChange,\n minChars: minCharsOption,\n debounceMs: debounceOption\n } = options\n\n // Get context (may be undefined if no provider)\n const autocompleteCtx = useAutocompleteContextSafe()\n\n // State\n const [completion, setCompletion] = createSignal<string | null>(null)\n const [options_, setOptions] = createSignal<AutocompleteOption[]>([])\n const [selectedIndex, setSelectedIndex] = createSignal(-1)\n const [isLoading, setIsLoading] = createSignal(false)\n const [error, setError] = createSignal<string | null>(null)\n const [isOpen, setIsOpen] = createSignal(false)\n const [resultType, setResultType] = createSignal<'completion' | 'options' | null>(null)\n\n // Config with defaults from context/options\n const config = createMemo(() => ({\n minChars: minCharsOption ?? fieldConfig?.minChars ?? autocompleteCtx?.config.minChars ?? 1,\n debounceMs: debounceOption ?? fieldConfig?.debounceMs ?? autocompleteCtx?.config.debounceMs ?? 150\n }))\n\n // Ghost text (portion after current input)\n const ghostText = createMemo(() => {\n const comp = completion()\n const input = inputValue()\n\n if (!comp || !input) return ''\n\n // If completion starts with input, show the remaining part\n if (comp.toLowerCase().startsWith(input.toLowerCase())) {\n return comp.slice(input.length)\n }\n\n return ''\n })\n\n // Fetch suggestions\n const fetchSuggestions = async (input: string) => {\n if (!autocompleteCtx) {\n return\n }\n\n if (input.length < config().minChars) {\n batch(() => {\n setCompletion(null)\n setOptions([])\n setIsOpen(false)\n setResultType(null)\n })\n return\n }\n\n setIsLoading(true)\n setError(null)\n\n try {\n const targetPluginId = pluginId ?? fieldConfig?.plugin\n const contextData = context?.()\n\n const result = await autocompleteCtx.getSuggestions(\n input,\n targetPluginId,\n contextData\n )\n\n batch(() => {\n setResultType(result.type)\n\n if (result.type === 'completion') {\n setCompletion(result.completion || null)\n setOptions([])\n setIsOpen(!!result.completion)\n } else {\n setCompletion(null)\n setOptions(result.options || [])\n setSelectedIndex(-1)\n setIsOpen((result.options?.length || 0) > 0)\n }\n\n setIsLoading(false)\n })\n } catch (e) {\n batch(() => {\n setError(e instanceof Error ? e.message : 'Unknown error')\n setIsLoading(false)\n setIsOpen(false)\n })\n }\n }\n\n // Debounced fetch\n const debouncedFetch = debounce(fetchSuggestions, config().debounceMs)\n\n // Watch input value changes\n createEffect(\n on(inputValue, (value) => {\n if (!enabled || !autocompleteCtx || isServer) {\n return\n }\n\n debouncedFetch.call(value)\n })\n )\n\n // Cleanup\n onCleanup(() => {\n debouncedFetch.cancel()\n })\n\n /**\n * Accept the current completion\n */\n const acceptCompletion = () => {\n const comp = completion()\n if (comp && onInputChange) {\n onInputChange(comp)\n batch(() => {\n setCompletion(null)\n setIsOpen(false)\n })\n }\n }\n\n /**\n * Select an option\n */\n const selectOption = (option: AutocompleteOption) => {\n if (onInputChange) {\n onInputChange(option.value)\n }\n batch(() => {\n setOptions([])\n setSelectedIndex(-1)\n setIsOpen(false)\n })\n }\n\n /**\n * Navigate to next option\n */\n const nextOption = () => {\n const opts = options_()\n if (opts.length === 0) return\n\n setSelectedIndex((prev) => {\n const next = prev + 1\n return next >= opts.length ? 0 : next\n })\n }\n\n /**\n * Navigate to previous option\n */\n const prevOption = () => {\n const opts = options_()\n if (opts.length === 0) return\n\n setSelectedIndex((prev) => {\n const next = prev - 1\n return next < 0 ? opts.length - 1 : next\n })\n }\n\n /**\n * Select current highlighted option\n */\n const selectCurrentOption = () => {\n const idx = selectedIndex()\n const opts = options_()\n if (idx >= 0 && idx < opts.length) {\n selectOption(opts[idx])\n }\n }\n\n /**\n * Dismiss suggestions\n */\n const dismiss = () => {\n debouncedFetch.cancel()\n batch(() => {\n setCompletion(null)\n setOptions([])\n setSelectedIndex(-1)\n setIsOpen(false)\n setError(null)\n })\n }\n\n /**\n * Open suggestions\n */\n const open = () => {\n const input = inputValue()\n if (input.length >= config().minChars) {\n fetchSuggestions(input)\n }\n }\n\n /**\n * Handle keyboard events\n * Returns true if the event was handled\n */\n const handleKeyDown = (e: KeyboardEvent): boolean => {\n if (!isOpen()) return false\n\n const type = resultType()\n\n // Tab to accept completion\n if (e.key === 'Tab' && type === 'completion' && ghostText()) {\n e.preventDefault()\n acceptCompletion()\n return true\n }\n\n // Arrow keys for dropdown navigation\n if (type === 'options') {\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault()\n nextOption()\n return true\n\n case 'ArrowUp':\n e.preventDefault()\n prevOption()\n return true\n\n case 'Enter':\n if (selectedIndex() >= 0) {\n e.preventDefault()\n selectCurrentOption()\n return true\n }\n break\n\n case 'Tab':\n if (selectedIndex() >= 0) {\n e.preventDefault()\n selectCurrentOption()\n return true\n }\n break\n }\n }\n\n // Escape to dismiss\n if (e.key === 'Escape') {\n e.preventDefault()\n dismiss()\n return true\n }\n\n return false\n }\n\n return {\n completion,\n ghostText,\n acceptCompletion,\n options: options_,\n selectedIndex,\n selectOption,\n nextOption,\n prevOption,\n selectCurrentOption,\n isLoading,\n error,\n dismiss,\n isOpen,\n resultType,\n open,\n handleKeyDown\n }\n}\n"],"names":["useAutocompleteContextSafe","createSignal","createMemo","batch","createEffect","on","isServer","onCleanup"],"mappings":"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"}
@@ -0,0 +1,119 @@
1
+ /**
2
+ * useAutocomplete Hook
3
+ * Provides autocomplete functionality for form fields
4
+ *
5
+ * Sprint Autocomplete Feature
6
+ */
7
+ import { Accessor } from 'solid-js';
8
+ import type { AutocompleteOption, AutocompleteContext, FieldAutocompleteConfig } from '../types';
9
+ /**
10
+ * Options for the useAutocomplete hook
11
+ */
12
+ export interface UseAutocompleteOptions {
13
+ /**
14
+ * Current input value accessor
15
+ */
16
+ inputValue: Accessor<string>;
17
+ /**
18
+ * Plugin ID to use (overrides default)
19
+ */
20
+ pluginId?: string;
21
+ /**
22
+ * Field configuration
23
+ */
24
+ fieldConfig?: FieldAutocompleteConfig;
25
+ /**
26
+ * Context data for suggestions
27
+ */
28
+ context?: Accessor<AutocompleteContext>;
29
+ /**
30
+ * Whether autocomplete is enabled
31
+ */
32
+ enabled?: boolean;
33
+ /**
34
+ * Callback when input value should change (for accepting suggestions)
35
+ */
36
+ onInputChange?: (value: string) => void;
37
+ /**
38
+ * Minimum characters before triggering
39
+ */
40
+ minChars?: number;
41
+ /**
42
+ * Debounce delay in ms
43
+ */
44
+ debounceMs?: number;
45
+ }
46
+ /**
47
+ * Return type for the useAutocomplete hook
48
+ */
49
+ export interface UseAutocompleteReturn {
50
+ /**
51
+ * Current completion text (for ghost text, LLM mode)
52
+ */
53
+ completion: Accessor<string | null>;
54
+ /**
55
+ * Ghost text to show (remaining text after input)
56
+ */
57
+ ghostText: Accessor<string>;
58
+ /**
59
+ * Accept the current completion
60
+ */
61
+ acceptCompletion: () => void;
62
+ /**
63
+ * Current options (for dropdown, data mode)
64
+ */
65
+ options: Accessor<AutocompleteOption[]>;
66
+ /**
67
+ * Currently selected option index
68
+ */
69
+ selectedIndex: Accessor<number>;
70
+ /**
71
+ * Select an option by index
72
+ */
73
+ selectOption: (option: AutocompleteOption) => void;
74
+ /**
75
+ * Navigate to next option
76
+ */
77
+ nextOption: () => void;
78
+ /**
79
+ * Navigate to previous option
80
+ */
81
+ prevOption: () => void;
82
+ /**
83
+ * Select current highlighted option
84
+ */
85
+ selectCurrentOption: () => void;
86
+ /**
87
+ * Whether suggestions are loading
88
+ */
89
+ isLoading: Accessor<boolean>;
90
+ /**
91
+ * Error message if any
92
+ */
93
+ error: Accessor<string | null>;
94
+ /**
95
+ * Dismiss suggestions
96
+ */
97
+ dismiss: () => void;
98
+ /**
99
+ * Whether suggestions are visible
100
+ */
101
+ isOpen: Accessor<boolean>;
102
+ /**
103
+ * Result type ('completion' or 'options')
104
+ */
105
+ resultType: Accessor<'completion' | 'options' | null>;
106
+ /**
107
+ * Open/show suggestions
108
+ */
109
+ open: () => void;
110
+ /**
111
+ * Handle keyboard events
112
+ */
113
+ handleKeyDown: (e: KeyboardEvent) => boolean;
114
+ }
115
+ /**
116
+ * Hook for autocomplete functionality
117
+ */
118
+ export declare function useAutocomplete(options: UseAutocompleteOptions): UseAutocompleteReturn;
119
+ //# sourceMappingURL=useAutocomplete.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAutocomplete.d.ts","sourceRoot":"","sources":["../../src/hooks/useAutocomplete.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAIL,QAAQ,EAIT,MAAM,UAAU,CAAA;AAGjB,OAAO,KAAK,EACV,kBAAkB,EAClB,mBAAmB,EACnB,uBAAuB,EACxB,MAAM,UAAU,CAAA;AAEjB;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;OAEG;IACH,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAA;IAE5B;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IAEjB;;OAEG;IACH,WAAW,CAAC,EAAE,uBAAuB,CAAA;IAErC;;OAEG;IACH,OAAO,CAAC,EAAE,QAAQ,CAAC,mBAAmB,CAAC,CAAA;IAEvC;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IAEjB;;OAEG;IACH,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAEvC;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IAEjB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;OAEG;IACH,UAAU,EAAE,QAAQ,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IAEnC;;OAEG;IACH,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAA;IAE3B;;OAEG;IACH,gBAAgB,EAAE,MAAM,IAAI,CAAA;IAE5B;;OAEG;IACH,OAAO,EAAE,QAAQ,CAAC,kBAAkB,EAAE,CAAC,CAAA;IAEvC;;OAEG;IACH,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAA;IAE/B;;OAEG;IACH,YAAY,EAAE,CAAC,MAAM,EAAE,kBAAkB,KAAK,IAAI,CAAA;IAElD;;OAEG;IACH,UAAU,EAAE,MAAM,IAAI,CAAA;IAEtB;;OAEG;IACH,UAAU,EAAE,MAAM,IAAI,CAAA;IAEtB;;OAEG;IACH,mBAAmB,EAAE,MAAM,IAAI,CAAA;IAE/B;;OAEG;IACH,SAAS,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAA;IAE5B;;OAEG;IACH,KAAK,EAAE,QAAQ,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IAE9B;;OAEG;IACH,OAAO,EAAE,MAAM,IAAI,CAAA;IAEnB;;OAEG;IACH,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAA;IAEzB;;OAEG;IACH,UAAU,EAAE,QAAQ,CAAC,YAAY,GAAG,SAAS,GAAG,IAAI,CAAC,CAAA;IAErD;;OAEG;IACH,IAAI,EAAE,MAAM,IAAI,CAAA;IAEhB;;OAEG;IACH,aAAa,EAAE,CAAC,CAAC,EAAE,aAAa,KAAK,OAAO,CAAA;CAC7C;AA4BD;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG,qBAAqB,CA0RtF"}
@@ -0,0 +1,234 @@
1
+ import { createSignal, createMemo, createEffect, on, onCleanup, batch } from "solid-js";
2
+ import { isServer } from "solid-js/web";
3
+ import { useAutocompleteContextSafe } from "../context/AutocompleteContext.js";
4
+ function debounce(fn, delay) {
5
+ let timeoutId = null;
6
+ return {
7
+ call: (...args) => {
8
+ if (timeoutId) clearTimeout(timeoutId);
9
+ timeoutId = setTimeout(() => {
10
+ fn(...args);
11
+ timeoutId = null;
12
+ }, delay);
13
+ },
14
+ cancel: () => {
15
+ if (timeoutId) {
16
+ clearTimeout(timeoutId);
17
+ timeoutId = null;
18
+ }
19
+ }
20
+ };
21
+ }
22
+ function useAutocomplete(options) {
23
+ const {
24
+ inputValue,
25
+ pluginId,
26
+ fieldConfig,
27
+ context,
28
+ enabled = true,
29
+ onInputChange,
30
+ minChars: minCharsOption,
31
+ debounceMs: debounceOption
32
+ } = options;
33
+ const autocompleteCtx = useAutocompleteContextSafe();
34
+ const [completion, setCompletion] = createSignal(null);
35
+ const [options_, setOptions] = createSignal([]);
36
+ const [selectedIndex, setSelectedIndex] = createSignal(-1);
37
+ const [isLoading, setIsLoading] = createSignal(false);
38
+ const [error, setError] = createSignal(null);
39
+ const [isOpen, setIsOpen] = createSignal(false);
40
+ const [resultType, setResultType] = createSignal(null);
41
+ const config = createMemo(() => ({
42
+ minChars: minCharsOption ?? (fieldConfig == null ? void 0 : fieldConfig.minChars) ?? (autocompleteCtx == null ? void 0 : autocompleteCtx.config.minChars) ?? 1,
43
+ debounceMs: debounceOption ?? (fieldConfig == null ? void 0 : fieldConfig.debounceMs) ?? (autocompleteCtx == null ? void 0 : autocompleteCtx.config.debounceMs) ?? 150
44
+ }));
45
+ const ghostText = createMemo(() => {
46
+ const comp = completion();
47
+ const input = inputValue();
48
+ if (!comp || !input) return "";
49
+ if (comp.toLowerCase().startsWith(input.toLowerCase())) {
50
+ return comp.slice(input.length);
51
+ }
52
+ return "";
53
+ });
54
+ const fetchSuggestions = async (input) => {
55
+ if (!autocompleteCtx) {
56
+ return;
57
+ }
58
+ if (input.length < config().minChars) {
59
+ batch(() => {
60
+ setCompletion(null);
61
+ setOptions([]);
62
+ setIsOpen(false);
63
+ setResultType(null);
64
+ });
65
+ return;
66
+ }
67
+ setIsLoading(true);
68
+ setError(null);
69
+ try {
70
+ const targetPluginId = pluginId ?? (fieldConfig == null ? void 0 : fieldConfig.plugin);
71
+ const contextData = context == null ? void 0 : context();
72
+ const result = await autocompleteCtx.getSuggestions(
73
+ input,
74
+ targetPluginId,
75
+ contextData
76
+ );
77
+ batch(() => {
78
+ var _a;
79
+ setResultType(result.type);
80
+ if (result.type === "completion") {
81
+ setCompletion(result.completion || null);
82
+ setOptions([]);
83
+ setIsOpen(!!result.completion);
84
+ } else {
85
+ setCompletion(null);
86
+ setOptions(result.options || []);
87
+ setSelectedIndex(-1);
88
+ setIsOpen((((_a = result.options) == null ? void 0 : _a.length) || 0) > 0);
89
+ }
90
+ setIsLoading(false);
91
+ });
92
+ } catch (e) {
93
+ batch(() => {
94
+ setError(e instanceof Error ? e.message : "Unknown error");
95
+ setIsLoading(false);
96
+ setIsOpen(false);
97
+ });
98
+ }
99
+ };
100
+ const debouncedFetch = debounce(fetchSuggestions, config().debounceMs);
101
+ createEffect(
102
+ on(inputValue, (value) => {
103
+ if (!enabled || !autocompleteCtx || isServer) {
104
+ return;
105
+ }
106
+ debouncedFetch.call(value);
107
+ })
108
+ );
109
+ onCleanup(() => {
110
+ debouncedFetch.cancel();
111
+ });
112
+ const acceptCompletion = () => {
113
+ const comp = completion();
114
+ if (comp && onInputChange) {
115
+ onInputChange(comp);
116
+ batch(() => {
117
+ setCompletion(null);
118
+ setIsOpen(false);
119
+ });
120
+ }
121
+ };
122
+ const selectOption = (option) => {
123
+ if (onInputChange) {
124
+ onInputChange(option.value);
125
+ }
126
+ batch(() => {
127
+ setOptions([]);
128
+ setSelectedIndex(-1);
129
+ setIsOpen(false);
130
+ });
131
+ };
132
+ const nextOption = () => {
133
+ const opts = options_();
134
+ if (opts.length === 0) return;
135
+ setSelectedIndex((prev) => {
136
+ const next = prev + 1;
137
+ return next >= opts.length ? 0 : next;
138
+ });
139
+ };
140
+ const prevOption = () => {
141
+ const opts = options_();
142
+ if (opts.length === 0) return;
143
+ setSelectedIndex((prev) => {
144
+ const next = prev - 1;
145
+ return next < 0 ? opts.length - 1 : next;
146
+ });
147
+ };
148
+ const selectCurrentOption = () => {
149
+ const idx = selectedIndex();
150
+ const opts = options_();
151
+ if (idx >= 0 && idx < opts.length) {
152
+ selectOption(opts[idx]);
153
+ }
154
+ };
155
+ const dismiss = () => {
156
+ debouncedFetch.cancel();
157
+ batch(() => {
158
+ setCompletion(null);
159
+ setOptions([]);
160
+ setSelectedIndex(-1);
161
+ setIsOpen(false);
162
+ setError(null);
163
+ });
164
+ };
165
+ const open = () => {
166
+ const input = inputValue();
167
+ if (input.length >= config().minChars) {
168
+ fetchSuggestions(input);
169
+ }
170
+ };
171
+ const handleKeyDown = (e) => {
172
+ if (!isOpen()) return false;
173
+ const type = resultType();
174
+ if (e.key === "Tab" && type === "completion" && ghostText()) {
175
+ e.preventDefault();
176
+ acceptCompletion();
177
+ return true;
178
+ }
179
+ if (type === "options") {
180
+ switch (e.key) {
181
+ case "ArrowDown":
182
+ e.preventDefault();
183
+ nextOption();
184
+ return true;
185
+ case "ArrowUp":
186
+ e.preventDefault();
187
+ prevOption();
188
+ return true;
189
+ case "Enter":
190
+ if (selectedIndex() >= 0) {
191
+ e.preventDefault();
192
+ selectCurrentOption();
193
+ return true;
194
+ }
195
+ break;
196
+ case "Tab":
197
+ if (selectedIndex() >= 0) {
198
+ e.preventDefault();
199
+ selectCurrentOption();
200
+ return true;
201
+ }
202
+ break;
203
+ }
204
+ }
205
+ if (e.key === "Escape") {
206
+ e.preventDefault();
207
+ dismiss();
208
+ return true;
209
+ }
210
+ return false;
211
+ };
212
+ return {
213
+ completion,
214
+ ghostText,
215
+ acceptCompletion,
216
+ options: options_,
217
+ selectedIndex,
218
+ selectOption,
219
+ nextOption,
220
+ prevOption,
221
+ selectCurrentOption,
222
+ isLoading,
223
+ error,
224
+ dismiss,
225
+ isOpen,
226
+ resultType,
227
+ open,
228
+ handleKeyDown
229
+ };
230
+ }
231
+ export {
232
+ useAutocomplete
233
+ };
234
+ //# sourceMappingURL=useAutocomplete.js.map