feat(storybook): add configurable LiveDataExplorer story for Autocomplete - #384
Conversation
…lete Mirrors the eSheet autocomplete field's controls (data source URL, results path, label/value keys, capture attributes) as Storybook args; documents verified public API presets (Wikipedia, RxNorm, Datamuse, OpenLibrary).
There was a problem hiding this comment.
Pull request overview
Adds a new Storybook “LiveDataExplorer” story for Autocomplete that lets developers try arbitrary CORS-enabled JSON endpoints via Controls, mirroring the configurable autocomplete field behavior referenced in the PR description.
Changes:
- Added story-local helpers to unwrap enveloped responses (dot-path) and normalize common result shapes (OpenSearch arrays, string arrays, object arrays).
- Implemented a debounced, abortable remote-search harness with stale-response guarding and surfaced errors via
emptyMessage. - Rendered the selected option plus captured attributes below the input and documented several verified API presets in the Docs tab.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Deploying ui with
|
| Latest commit: |
53cfa8d
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://4918ea70.ui-6d0.pages.dev |
| Branch Preview URL: | https://feat-autocomplete-live-explo.ui-6d0.pages.dev |
On-canvas table of verified data sources (Wikipedia REST/OpenSearch, RxNorm, Datamuse, OpenLibrary) with Load buttons wired to useArgs; docs table generated from the same preset array.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.
Suppressed comments (2)
src/components/Autocomplete/Autocomplete.stories.tsx:740
- The preset “Loaded” state only compares
dataSourceUrl, so it can show a preset as loaded even when resultsPath/keys/captureAttributes differ (e.g., after tweaking controls). This makes the UI misleading and can also cause the wrong button variant/label.
const isActive = (preset: ExplorerPreset) =>
preset.args.dataSourceUrl === args.dataSourceUrl;
// Remount the example when the source config changes so stale
// items/selection from the previous API never linger.
const configKey = `${args.dataSourceUrl}|${args.resultsPath}|${args.labelKey}|${args.valueKey}|${args.captureAttributes}`;
src/components/Autocomplete/Autocomplete.stories.tsx:628
dataSourceUrl.replace('{query}', …)only replaces the first{query}token. If a preset or user-provided URL contains{query}more than once, the request URL will be malformed and the story will silently fail to fetch expected results.
const res = await fetch(
dataSourceUrl.replace('{query}', encodeURIComponent(q)),
{ signal: ac.signal }
);
…veDataExplorer
A data source URL without the {query} token now shows an explicit
configuration error in the popover instead of a misleading 'No results.'
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.
Suppressed comments (2)
src/components/Autocomplete/Autocomplete.stories.tsx:493
captureAttributesFromcoerces captured values withString(value), so non-scalar JSON (e.g. arrays like OpenLibraryauthor_name) loses its structure. This makes the “incl. arrays” preset hint misleading and prevents the story from visibly demonstrating array/object capture.
function captureAttributesFrom(
raw: Record<string, unknown> | undefined,
captureAttributes: string
): Record<string, string> {
const captured: Record<string, string> = {};
if (!raw) return captured;
for (const key of captureAttributes
.split(',')
.map((k) => k.trim())
.filter(Boolean)) {
const value = raw[key];
if (value != null) captured[key] = String(value);
}
return captured;
src/components/Autocomplete/Autocomplete.stories.tsx:738
- The preset “Loaded” state only compares
dataSourceUrl, so the button can show “Loaded” even when the other preset knobs (results path/keys/capture attributes) have been edited. This makes the table state inaccurate for users tweaking controls.
const [, updateArgs] = useArgs<ExplorerArgs>();
const isActive = (preset: ExplorerPreset) =>
preset.args.dataSourceUrl === args.dataSourceUrl;
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.
Suppressed comments (2)
src/components/Autocomplete/Autocomplete.stories.tsx:493
captureAttributesFromcoerces captured values withString(value), which flattens arrays/objects into ambiguous strings (e.g.author_namebecomes "a,b"), despite the OpenLibrary preset hint calling out arrays. Preserve the raw JSON values so the rendered JSON shows accurate structure.
const value = raw[key];
if (value != null) captured[key] = String(value);
src/components/Autocomplete/Autocomplete.stories.tsx:738
isActiveonly comparesdataSourceUrl, so a preset button can show “Loaded” even when the user has changed other preset-controlled fields (resultsPath/keys/captureAttributes). This makes the table state misleading.
const [, updateArgs] = useArgs<ExplorerArgs>();
const isActive = (preset: ExplorerPreset) =>
preset.args.dataSourceUrl === args.dataSourceUrl;
Summary
Adds a
LiveDataExplorerstory to the Autocomplete component that mirrors the configurableautocompletefield type shipped in mieweb/eSheet#162. The Storybook Controls panel exposes the same knobs as the eSheet builder edit panel, so any CORS-enabled JSON API can be tried live without code changes:{query}token replaced with the typed textsuggestionGroup.suggestionList.suggestion)Implementation
AbortController, stale-response guard, error surfaced viaemptyMessage.Testing
pnpm exec prettier/pnpm exec eslint/pnpm typecheckall pass{ id, description }attributes