@malloy-publisher/sdk 0.0.140 → 0.0.141

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@malloy-publisher/sdk",
3
3
  "description": "Malloy Publisher SDK",
4
- "version": "0.0.140",
4
+ "version": "0.0.141",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs.js",
7
7
  "module": "dist/index.es.js",
@@ -138,13 +138,13 @@ export function DimensionFilter({
138
138
  const [retrievalInputValue, setRetrievalInputValue] = useState("");
139
139
  const [retrievalSearched, setRetrievalSearched] = useState(false);
140
140
  const [retrievalFocused, setRetrievalFocused] = useState(false);
141
- const pendingRequestRef = useRef<string | null>(null);
142
- const isRequestInFlightRef = useRef(false);
141
+ const retrievalTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
142
+ const latestRequestIdRef = useRef(0);
143
143
 
144
144
  // MinMax focus state for showing helper text
145
145
  const [showMinMaxHelper, setShowMinMaxHelper] = useState(false);
146
146
 
147
- // Effect to trigger retrieval
147
+ // Effect to trigger retrieval with debounce
148
148
  useEffect(() => {
149
149
  if (spec.filterType !== "Retrieval" || !retrievalFn) return;
150
150
 
@@ -155,41 +155,46 @@ export function DimensionFilter({
155
155
  return;
156
156
  }
157
157
 
158
- const performRetrieval = async (searchQuery: string) => {
159
- if (isRequestInFlightRef.current) {
160
- pendingRequestRef.current = searchQuery;
161
- return;
162
- }
158
+ // Cancel any existing timer
159
+ if (retrievalTimerRef.current) {
160
+ clearTimeout(retrievalTimerRef.current);
161
+ }
162
+
163
+ // Set a new 300ms timer
164
+ retrievalTimerRef.current = setTimeout(async () => {
165
+ // Increment and capture request ID to track this request
166
+ latestRequestIdRef.current += 1;
167
+ const thisRequestId = latestRequestIdRef.current;
163
168
 
164
- isRequestInFlightRef.current = true;
165
169
  setRetrievalLoading(true);
166
170
 
167
171
  try {
168
- const results = await retrievalFn(searchQuery, spec);
169
- setRetrievalOptions(results);
172
+ const results = await retrievalFn(query, spec);
173
+ // Only update state if this is still the latest request
174
+ if (thisRequestId === latestRequestIdRef.current) {
175
+ setRetrievalOptions(results);
176
+ }
170
177
  } catch (e) {
171
- console.error("Retrieval failed", e);
172
- setRetrievalOptions([]);
178
+ // Only update state if this is still the latest request
179
+ if (thisRequestId === latestRequestIdRef.current) {
180
+ console.error("Retrieval failed", e);
181
+ setRetrievalOptions([]);
182
+ }
173
183
  } finally {
174
- isRequestInFlightRef.current = false;
175
- setRetrievalLoading(false);
176
- setRetrievalSearched(true);
177
-
178
- // Check pending
179
- if (pendingRequestRef.current) {
180
- const nextQuery = pendingRequestRef.current;
181
- pendingRequestRef.current = null;
182
- setTimeout(() => performRetrieval(nextQuery), 0);
184
+ // Only update loading/searched state if this is still the latest request
185
+ if (thisRequestId === latestRequestIdRef.current) {
186
+ setRetrievalLoading(false);
187
+ setRetrievalSearched(true);
183
188
  }
184
189
  }
185
- };
186
-
187
- // Debounce
188
- const timeoutId = setTimeout(() => {
189
- performRetrieval(query);
190
190
  }, 300);
191
191
 
192
- return () => clearTimeout(timeoutId);
192
+ // Cleanup: cancel timer on unmount or when dependencies change
193
+ return () => {
194
+ if (retrievalTimerRef.current) {
195
+ clearTimeout(retrievalTimerRef.current);
196
+ }
197
+ };
193
198
  }, [retrievalInputValue, spec, retrievalFn]);
194
199
 
195
200
  // Sync internal state with selection prop changes (e.g., when filter is cleared externally)