@neuronection/assistant-ui 0.61.0 → 0.62.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/dist/{chunk-KCXU3SDM.js → chunk-7LT2HC54.js} +5 -3
- package/dist/chunk-7LT2HC54.js.map +1 -0
- package/dist/{chunk-3Y6QOTVA.js → chunk-PQGWPXEG.js} +3 -3
- package/dist/{chunk-3Y6QOTVA.js.map → chunk-PQGWPXEG.js.map} +1 -1
- package/dist/{chunk-O6BRNGXV.js → chunk-QSZND2FV.js} +4 -3
- package/dist/chunk-QSZND2FV.js.map +1 -0
- package/dist/connection-test-row.d.ts +3 -0
- package/dist/connection-test-row.js +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.js +3 -3
- package/dist/provider-card.d.ts +3 -0
- package/dist/provider-card.js +1 -1
- package/dist/web-search-providers.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-KCXU3SDM.js.map +0 -1
- package/dist/chunk-O6BRNGXV.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# @neuronection/assistant-ui
|
|
2
2
|
|
|
3
|
+
## 0.62.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#91](https://github.com/neuronection/assistant-ui/pull/91) [`e472b67`](https://github.com/neuronection/assistant-ui/commit/e472b679e60f5e8005489353e74280d6d7f50782) Thanks [@constLiakos](https://github.com/constLiakos)! - `ConnectionTestRow` / `ProviderCard`: new optional `idleLabel` ("Not
|
|
8
|
+
tested") — the never-tested state previously rendered no status text at
|
|
9
|
+
all, which forced apps to keep a static label just to hold the line.
|
|
10
|
+
No behavior change when the prop is unset.
|
|
11
|
+
|
|
3
12
|
## 0.61.0
|
|
4
13
|
|
|
5
14
|
### Minor Changes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ProviderLogo } from './chunk-7IP3JP3Z.js';
|
|
2
2
|
import { ActionMenu } from './chunk-3UCBKZ2O.js';
|
|
3
|
-
import { ConnectionTestRow } from './chunk-
|
|
3
|
+
import { ConnectionTestRow } from './chunk-QSZND2FV.js';
|
|
4
4
|
import { cn } from './chunk-RVVXVTH3.js';
|
|
5
5
|
import * as React from 'react';
|
|
6
6
|
import { EllipsisVertical } from 'lucide-react';
|
|
@@ -16,6 +16,7 @@ var ProviderCard = React.forwardRef(
|
|
|
16
16
|
connectionLabel,
|
|
17
17
|
okLabel,
|
|
18
18
|
failLabel,
|
|
19
|
+
idleLabel,
|
|
19
20
|
latencyLabel,
|
|
20
21
|
latencyMs,
|
|
21
22
|
errorMessage,
|
|
@@ -63,6 +64,7 @@ var ProviderCard = React.forwardRef(
|
|
|
63
64
|
status,
|
|
64
65
|
latencyMs,
|
|
65
66
|
latencyLabel,
|
|
67
|
+
idleLabel,
|
|
66
68
|
errorMessage,
|
|
67
69
|
meta,
|
|
68
70
|
okLabel,
|
|
@@ -86,5 +88,5 @@ var ProviderCard = React.forwardRef(
|
|
|
86
88
|
);
|
|
87
89
|
|
|
88
90
|
export { ProviderCard };
|
|
89
|
-
//# sourceMappingURL=chunk-
|
|
90
|
-
//# sourceMappingURL=chunk-
|
|
91
|
+
//# sourceMappingURL=chunk-7LT2HC54.js.map
|
|
92
|
+
//# sourceMappingURL=chunk-7LT2HC54.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/provider-card/ProviderCard.tsx"],"names":["ProviderCard"],"mappings":";;;;;;;;AA8DO,IAAM,YAAA,GAAqB,KAAA,CAAA,UAAA;AAAA,EAChC,SAASA,aAAAA,CACP;AAAA,IACE,IAAA;AAAA,IACA,UAAA;AAAA,IACA,SAAA;AAAA,IACA,MAAA;AAAA,IACA,MAAA,GAAS,MAAA;AAAA,IACT,eAAA;AAAA,IACA,OAAA;AAAA,IACA,SAAA;AAAA,IACA,SAAA;AAAA,IACA,YAAA;AAAA,IACA,SAAA;AAAA,IACA,YAAA;AAAA,IACA,IAAA;AAAA,IACA,OAAA;AAAA,IACA,YAAA;AAAA,IACA,SAAA;AAAA,IACA,GAAG;AAAA,KAEL,GAAA,EACA;AACA,IAAA,uBACE,IAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,SAAA,EAAQ,eAAA;AAAA,QACR,SAAA,EAAW,EAAA;AAAA,UACT,kIAAA;AAAA,UACA;AAAA,SACF;AAAA,QACC,GAAG,KAAA;AAAA,QAEJ,QAAA,EAAA;AAAA,0BAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,gBAAA,EACb,QAAA,EAAA;AAAA,4BAAA,IAAA,CAAC,GAAA,EAAA,EAAE,WAAU,yDAAA,EACX,QAAA,EAAA;AAAA,8BAAA,GAAA,CAAC,YAAA,EAAA,EAAa,MAAA,EAAQ,UAAA,IAAc,EAAA,EAAI,WAAU,UAAA,EAAW,CAAA;AAAA,kCAC5D,MAAA,EAAA,EAAK,SAAA,EAAU,UAAA,EAAW,KAAA,EAAO,WAC/B,QAAA,EAAA,IAAA,EACH,CAAA;AAAA,cAAA,CACE,MAAA,IAAU,EAAC,EAAG,GAAA,CAAI,CAAC,KAAA,qBACnB,GAAA;AAAA,gBAAC,MAAA;AAAA,gBAAA;AAAA,kBAEC,OAAO,KAAA,CAAM,KAAA;AAAA,kBACb,eAAa,KAAA,CAAM,MAAA;AAAA,kBACnB,SAAA,EAAW,EAAA;AAAA,oBACT,+FAAA;AAAA,oBACA,MAAM,MAAA,IAAU;AAAA,mBAClB;AAAA,kBAEC,QAAA,EAAA,KAAA,CAAM;AAAA,iBAAA;AAAA,gBARF,KAAA,CAAM;AAAA,eAUd;AAAA,aAAA,EACH,CAAA;AAAA,4BACA,GAAA;AAAA,cAAC,iBAAA;AAAA,cAAA;AAAA,gBACC,OAAA,EAAQ,QAAA;AAAA,gBACR,SAAA,EAAU,QAAA;AAAA,gBACV,KAAA,EAAO,eAAA;AAAA,gBACP,MAAA;AAAA,gBACA,SAAA;AAAA,gBACA,YAAA;AAAA,gBACA,SAAA;AAAA,gBACA,YAAA;AAAA,gBACA,IAAA;AAAA,gBACA,OAAA;AAAA,gBACA;AAAA;AAAA;AACF,WAAA,EACF,CAAA;AAAA,UACC,OAAA,IAAW,OAAA,CAAQ,MAAA,GAAS,CAAA,mBAC3B,GAAA;AAAA,YAAC,UAAA;AAAA,YAAA;AAAA,cACC,OAAO,YAAA,IAAgB,IAAA;AAAA,cACvB,KAAA,EAAM,KAAA;AAAA,cACN,yBAAS,GAAA,CAAC,gBAAA,EAAA,EAAiB,SAAA,EAAU,QAAA,EAAS,eAAW,IAAA,EAAC,CAAA;AAAA,cAC1D,KAAA,EAAO;AAAA;AAAA,WACT,GACE;AAAA;AAAA;AAAA,KACN;AAAA,EAEJ;AACF","file":"chunk-7LT2HC54.js","sourcesContent":["import * as React from 'react'\nimport { EllipsisVertical } from 'lucide-react'\nimport { cn } from '../../lib/utils'\nimport {\n ActionMenu,\n type ActionMenuItem,\n} from '../menu/Menu'\nimport {\n ConnectionTestRow,\n type ConnectionTestStatus,\n} from '../connection-test-row/ConnectionTestRow'\nimport { ProviderLogo } from '../provider-logo/ProviderLogo'\n\nexport interface ProviderCardBadge {\n /** Stable badge id (also the React key). */\n key: string\n label: string\n /** Tooltip on the badge (e.g. the country's name behind its flag). */\n title?: string\n /** Danger tone (the \"inactive\" marker). */\n danger?: boolean\n /** Apps target badges in tests (`data-testid`). */\n testId?: string\n}\n\n/** Same shape as the overflow menu's items — management actions\n * (\"Set up automatically\", \"Edit\", \"Delete\"), not the inline test. */\nexport type ProviderCardAction = ActionMenuItem\n\nexport interface ProviderCardProps\n extends Omit<React.ComponentProps<'div'>, 'children'> {\n name: string\n /** Preset key for the provider mark — unknown keys fall back to the\n * monogram. */\n logoPreset?: string\n /** Tooltip on the name — the connection string's only at-a-glance home\n * (config detail lives in Edit; the card stays status-forward). */\n nameTitle?: string\n badges?: ProviderCardBadge[]\n status?: ConnectionTestStatus\n /** Accessible label for the connection row. */\n connectionLabel?: string\n okLabel?: string\n failLabel?: string\n /** Text for the never-tested state (\"Not tested\") — shown when the\n * connection has never been tested. */\n idleLabel?: string\n latencyLabel?: string\n latencyMs?: number | null\n errorMessage?: string | null\n /** Context after the status — model count. */\n meta?: React.ReactNode\n actions?: ProviderCardAction[]\n /** Accessible label for the actions menu. */\n actionsLabel?: string\n}\n\n/** One provider summary card: mark + name + identity badges, the\n * connection result as the card's second line (status display only —\n * the test action lives in the `⋯` overflow menu alongside the other\n * management actions), and config detail (base URL) as a name tooltip.\n * Presentational and controlled: data in via props, events out. */\nexport const ProviderCard = React.forwardRef<HTMLDivElement, ProviderCardProps>(\n function ProviderCard(\n {\n name,\n logoPreset,\n nameTitle,\n badges,\n status = 'idle',\n connectionLabel,\n okLabel,\n failLabel,\n idleLabel,\n latencyLabel,\n latencyMs,\n errorMessage,\n meta,\n actions,\n actionsLabel,\n className,\n ...props\n },\n ref,\n ) {\n return (\n <div\n ref={ref}\n data-as=\"provider-card\"\n className={cn(\n 'flex items-start justify-between gap-2 rounded-[var(--as-radius-lg)] border border-[var(--as-border)] bg-[var(--as-surface)] p-4',\n className,\n )}\n {...props}\n >\n <div className=\"min-w-0 flex-1\">\n <p className=\"flex items-center gap-2 font-medium text-[var(--as-fg)]\">\n <ProviderLogo preset={logoPreset ?? ''} className=\"shrink-0\" />\n <span className=\"truncate\" title={nameTitle}>\n {name}\n </span>\n {(badges ?? []).map((badge) => (\n <span\n key={badge.key}\n title={badge.title}\n data-testid={badge.testId}\n className={cn(\n 'shrink-0 rounded bg-[var(--as-secondary)] px-1.5 py-0.5 text-xs text-[var(--as-secondary-fg)]',\n badge.danger && 'bg-transparent text-[var(--as-danger)]',\n )}\n >\n {badge.label}\n </span>\n ))}\n </p>\n <ConnectionTestRow\n variant=\"inline\"\n className=\"mt-1.5\"\n label={connectionLabel}\n status={status}\n latencyMs={latencyMs}\n latencyLabel={latencyLabel}\n idleLabel={idleLabel}\n errorMessage={errorMessage}\n meta={meta}\n okLabel={okLabel}\n failLabel={failLabel}\n />\n </div>\n {actions && actions.length > 0 ? (\n <ActionMenu\n label={actionsLabel ?? name}\n align=\"end\"\n trigger={<EllipsisVertical className=\"size-4\" aria-hidden />}\n items={actions}\n />\n ) : null}\n </div>\n )\n },\n)\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ConnectionTestRow } from './chunk-
|
|
1
|
+
import { ConnectionTestRow } from './chunk-QSZND2FV.js';
|
|
2
2
|
import { Button } from './chunk-4WBBF5LH.js';
|
|
3
3
|
import { cn } from './chunk-RVVXVTH3.js';
|
|
4
4
|
import * as React from 'react';
|
|
@@ -266,5 +266,5 @@ var WebSearchProvidersPanel = React.forwardRef(function WebSearchProvidersPanel2
|
|
|
266
266
|
});
|
|
267
267
|
|
|
268
268
|
export { WebSearchProvidersPanel };
|
|
269
|
-
//# sourceMappingURL=chunk-
|
|
270
|
-
//# sourceMappingURL=chunk-
|
|
269
|
+
//# sourceMappingURL=chunk-PQGWPXEG.js.map
|
|
270
|
+
//# sourceMappingURL=chunk-PQGWPXEG.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/web-search-providers/WebSearchProvidersPanel.tsx"],"names":["WebSearchProvidersPanel"],"mappings":"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","file":"chunk-3Y6QOTVA.js","sourcesContent":["import * as React from 'react'\nimport { ChevronDown, ChevronUp, Pencil, Plus, Trash2 } from 'lucide-react'\nimport { cn } from '../../lib/utils'\nimport { Button } from '../button/Button'\nimport { ConnectionTestRow, type ConnectionTestStatus } from '../connection-test-row/ConnectionTestRow'\n\nexport type WebSearchProbeStatus =\n | 'ok'\n | 'unreachable'\n | 'auth'\n | 'rate_limit'\n | 'json_disabled'\n | 'error'\n\nexport interface WebSearchProviderView {\n id: string\n name: string\n type: string\n enabled: boolean\n baseUrl?: string | null\n googleCx?: string | null\n keyHint?: string | null\n keySet: boolean\n}\n\nexport interface WebSearchProviderCatalogField {\n id: string\n label: string\n required: boolean\n placeholder?: string\n}\n\nexport interface WebSearchProviderCatalogEntry {\n label: string\n requiresKey: boolean\n keyUrl?: string | null\n baseUrl?: string | null\n baseUrlRequired: boolean\n baseUrlHint?: string | null\n notes?: string | null\n fields?: WebSearchProviderCatalogField[]\n}\n\nexport interface WebSearchProviderCatalog {\n /** Rendering + form order for provider types. */\n order: string[]\n entries: Record<string, WebSearchProviderCatalogEntry>\n}\n\nexport interface WebSearchProviderSaveInput {\n /** Absent = create. */\n id?: string\n type: string\n name?: string | null\n baseUrl?: string | null\n googleCx?: string | null\n /** `null` keeps the stored key, a value stores it. */\n apiKey?: string | null\n}\n\nexport interface WebSearchProviderProbeView {\n status: WebSearchProbeStatus\n latencyMs?: number | null\n error?: string | null\n}\n\nexport interface WebSearchProvidersPanelLabels {\n title?: string\n hint?: string\n addLabel?: string\n emptyLabel?: string\n nameLabel?: string\n typeLabel?: string\n baseUrlLabel?: string\n baseUrlRequiredLabel?: string\n keyLabel?: string\n keyOptionalLabel?: string\n keyStoredLabel?: string\n noKeyLabel?: string\n saveLabel?: string\n cancelLabel?: string\n editLabel?: string\n deleteLabel?: string\n moveUpLabel?: string\n moveDownLabel?: string\n enabledAriaLabel?: string\n disabledBadge?: string\n testLabel?: string\n probeLabels?: Partial<Record<WebSearchProbeStatus, string>>\n}\n\nexport interface WebSearchProvidersPanelProps {\n providers: WebSearchProviderView[]\n catalog: WebSearchProviderCatalog\n /** Connection probes keyed by provider id. */\n probes?: Record<string, WebSearchProviderProbeView>\n /** Id currently mid-test (shows the testing spinner). */\n testingId?: string | null\n busy?: boolean\n labels?: WebSearchProvidersPanelLabels\n onSave: (input: WebSearchProviderSaveInput) => void\n onDelete: (id: string) => void\n onMove: (id: string, direction: 'up' | 'down') => void\n onToggle: (id: string, enabled: boolean) => void\n onTest: (id: string) => void\n className?: string\n}\n\nconst inputClass =\n 'min-w-0 flex-1 rounded-[var(--as-radius-sm)] border border-[var(--as-border)] bg-[var(--as-surface)] px-2 py-1.5 text-sm text-[var(--as-fg)] placeholder:text-[var(--as-muted-fg)] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]'\n\n/**\n * Presentational ordered web-search provider list (ADR-0035 family shape):\n * enable/reorder/test/edit/delete rows plus a catalog-driven add/edit form.\n * Fully controlled — persistence, keys and probes are app-side; the panel\n * renders and emits. The first enabled provider that answers wins is the\n * family's fallback semantics, surfaced here by row order.\n */\nexport const WebSearchProvidersPanel = React.forwardRef<\n HTMLDivElement,\n WebSearchProvidersPanelProps\n>(function WebSearchProvidersPanel(\n {\n providers,\n catalog,\n probes = {},\n testingId = null,\n busy = false,\n labels,\n onSave,\n onDelete,\n onMove,\n onToggle,\n onTest,\n className,\n },\n ref,\n) {\n const t = React.useMemo(\n () => ({\n title: labels?.title ?? 'Web search providers',\n hint: labels?.hint,\n addLabel: labels?.addLabel ?? 'Add provider',\n emptyLabel: labels?.emptyLabel ?? 'No web search providers yet.',\n nameLabel: labels?.nameLabel ?? 'Name (optional)',\n typeLabel: labels?.typeLabel ?? 'Provider type',\n baseUrlLabel: labels?.baseUrlLabel ?? 'Base URL (optional)',\n baseUrlRequiredLabel: labels?.baseUrlRequiredLabel ?? 'Base URL (required)',\n keyLabel: labels?.keyLabel ?? 'API key',\n keyOptionalLabel: labels?.keyOptionalLabel ?? 'API key (optional)',\n keyStoredLabel: labels?.keyStoredLabel ?? 'API key saved',\n noKeyLabel: labels?.noKeyLabel ?? 'no key',\n saveLabel: labels?.saveLabel ?? 'Save provider',\n cancelLabel: labels?.cancelLabel ?? 'Cancel',\n editLabel: labels?.editLabel ?? 'Edit provider',\n deleteLabel: labels?.deleteLabel ?? 'Delete provider',\n moveUpLabel: labels?.moveUpLabel ?? 'Move up',\n moveDownLabel: labels?.moveDownLabel ?? 'Move down',\n enabledAriaLabel: labels?.enabledAriaLabel ?? 'Enable provider',\n disabledBadge: labels?.disabledBadge ?? 'disabled',\n testLabel: labels?.testLabel ?? 'Test',\n probeLabels: { ...labels?.probeLabels },\n }),\n [labels],\n )\n\n const [draft, setDraft] = React.useState<WebSearchProviderSaveInput | null>(null)\n\n const openAdd = () => {\n const first = catalog.order[0]\n if (first) setDraft({ type: first, name: '', baseUrl: '', googleCx: '', apiKey: null })\n }\n\n const openEdit = (provider: WebSearchProviderView) =>\n setDraft({\n id: provider.id,\n type: provider.type,\n name: provider.name,\n baseUrl: provider.baseUrl ?? '',\n googleCx: provider.googleCx ?? '',\n apiKey: null,\n })\n\n const draftEntry = draft ? catalog.entries[draft.type] : undefined\n const draftCxField = draftEntry?.fields?.some((field) => field.id === 'google_cx') ?? false\n const saveDisabled =\n busy ||\n (draftEntry?.baseUrlRequired && !(draft?.baseUrl ?? '').trim()) ||\n (draft?.id == null && (draftEntry?.requiresKey ?? false) && !(draft?.apiKey ?? '').trim())\n\n return (\n <div\n ref={ref}\n data-as=\"web-search-providers\"\n className={cn(\n 'rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface)] p-4',\n className,\n )}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"min-w-0\">\n <p className=\"text-base font-medium text-[var(--as-fg)]\">{t.title}</p>\n {t.hint ? (\n <p className=\"mt-0.5 text-xs text-[var(--as-muted-fg)]\">{t.hint}</p>\n ) : null}\n </div>\n {draft === null ? (\n <Button variant=\"outline\" size=\"sm\" onClick={openAdd}>\n <Plus className=\"size-4\" aria-hidden />\n {t.addLabel}\n </Button>\n ) : null}\n </div>\n\n <ul className=\"mt-3 space-y-2\" data-testid=\"wsp-rows\">\n {providers.map((provider, index) => {\n const probe = probes[provider.id]\n const isTesting = testingId === provider.id\n const showProbeRow = probe != null || isTesting\n const probeStatus: ConnectionTestStatus | null = !showProbeRow\n ? null\n : isTesting\n ? 'testing'\n : probe!.status === 'ok'\n ? 'ok'\n : 'fail'\n const probeText =\n probe && probe.status !== 'ok' && probe.error\n ? probe.error\n : probe\n ? (t.probeLabels[probe.status] ?? probe.status)\n : null\n return (\n <li\n key={provider.id}\n data-testid={`wsp-row-${provider.id}`}\n className=\"border-border border-[var(--as-border)] space-y-1 rounded-[var(--as-radius-sm)] border p-3\"\n >\n <div className=\"flex flex-wrap items-center gap-2\">\n <label className=\"flex cursor-pointer items-center gap-2 text-sm font-medium text-[var(--as-fg)]\">\n <input\n type=\"checkbox\"\n checked={provider.enabled}\n aria-label={`${t.enabledAriaLabel}: ${provider.name}`}\n onChange={(event) => onToggle(provider.id, event.target.checked)}\n />\n {provider.name}\n </label>\n <span className=\"rounded-full bg-[var(--as-secondary)] px-2 py-0.5 text-[11px] text-[var(--as-muted-fg)]\">\n {catalog.entries[provider.type]?.label ?? provider.type}\n </span>\n {provider.baseUrl ? (\n <span className=\"truncate font-mono text-xs text-[var(--as-muted-fg)]\">\n {provider.baseUrl}\n </span>\n ) : null}\n <span className=\"ml-auto text-xs text-[var(--as-muted-fg)]\">\n {provider.keySet\n ? (provider.keyHint ?? t.keyStoredLabel)\n : t.noKeyLabel}\n </span>\n </div>\n {showProbeRow ? (\n <ConnectionTestRow\n variant=\"inline\"\n status={probeStatus ?? 'idle'}\n latencyMs={probe?.latencyMs ?? null}\n label={catalog.entries[provider.type]?.label ?? provider.type}\n testLabel={t.testLabel}\n okLabel={t.probeLabels.ok ?? probe?.status ?? 'ok'}\n failLabel={probeText ?? t.probeLabels.error ?? probe?.status ?? 'failed'}\n errorMessage={probe && probe.status === 'ok' ? null : (probe?.error ?? null)}\n />\n ) : null}\n <div className=\"flex flex-wrap items-center gap-1.5\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={busy || testingId === provider.id}\n onClick={() => onTest(provider.id)}\n >\n {t.testLabel}\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={`${t.moveUpLabel}: ${provider.name}`}\n disabled={index === 0 || busy}\n onClick={() => onMove(provider.id, 'up')}\n >\n <ChevronUp className=\"size-4\" aria-hidden />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={`${t.moveDownLabel}: ${provider.name}`}\n disabled={index === providers.length - 1 || busy}\n onClick={() => onMove(provider.id, 'down')}\n >\n <ChevronDown className=\"size-4\" aria-hidden />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={`${t.editLabel}: ${provider.name}`}\n disabled={busy}\n onClick={() => openEdit(provider)}\n >\n <Pencil className=\"size-4\" aria-hidden />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={`${t.deleteLabel}: ${provider.name}`}\n disabled={busy}\n onClick={() => onDelete(provider.id)}\n >\n <Trash2 className=\"size-4\" aria-hidden />\n </Button>\n {!provider.enabled ? (\n <span className=\"text-xs text-[var(--as-muted-fg)]\">\n {t.disabledBadge}\n </span>\n ) : null}\n </div>\n </li>\n )\n })}\n </ul>\n\n {providers.length === 0 && draft === null ? (\n <p className=\"py-4 text-center text-sm text-[var(--as-muted-fg)]\" data-testid=\"wsp-empty\">\n {t.emptyLabel}\n </p>\n ) : null}\n\n {draft !== null ? (\n <form\n data-testid=\"wsp-form\"\n className=\"mt-3 space-y-2 rounded-[var(--as-radius-sm)] border border-[var(--as-border)] p-3\"\n onSubmit={(event) => {\n event.preventDefault()\n onSave(draft)\n }}\n >\n <div className=\"flex flex-wrap gap-2\">\n <select\n className={inputClass}\n value={draft.type}\n disabled={draft.id != null || busy}\n aria-label={t.typeLabel}\n onChange={(event) =>\n setDraft({ ...draft, type: event.target.value, googleCx: '' })\n }\n >\n {catalog.order.map((type) => (\n <option key={type} value={type}>\n {catalog.entries[type]?.label ?? type}\n </option>\n ))}\n </select>\n <input\n className={inputClass}\n placeholder={t.nameLabel}\n value={draft.name ?? ''}\n onChange={(event) => setDraft({ ...draft, name: event.target.value })}\n />\n </div>\n <div className=\"flex flex-wrap gap-2\">\n <input\n className={inputClass}\n placeholder={\n draftEntry?.baseUrlRequired\n ? t.baseUrlRequiredLabel\n : (draftEntry?.baseUrlHint ?? t.baseUrlLabel)\n }\n value={draft.baseUrl ?? ''}\n onChange={(event) => setDraft({ ...draft, baseUrl: event.target.value })}\n />\n {draftCxField ? (\n <input\n className={cn(inputClass, 'w-48 flex-none')}\n placeholder={draftEntry?.fields?.find((f) => f.id === 'google_cx')?.placeholder ?? ''}\n aria-label={draftEntry?.fields?.find((f) => f.id === 'google_cx')?.label ?? 'Engine id'}\n value={draft.googleCx ?? ''}\n onChange={(event) => setDraft({ ...draft, googleCx: event.target.value })}\n />\n ) : null}\n <input\n type=\"password\"\n className={cn(inputClass, 'w-48 flex-none')}\n placeholder={\n draft.id != null\n ? t.keyStoredLabel\n : draftEntry?.requiresKey\n ? t.keyLabel\n : t.keyOptionalLabel\n }\n aria-label={t.keyLabel}\n value={draft.apiKey ?? ''}\n onChange={(event) => setDraft({ ...draft, apiKey: event.target.value })}\n />\n </div>\n {draftEntry?.notes ? (\n <p className=\"text-[11px] text-[var(--as-muted-fg)]\">{draftEntry.notes}</p>\n ) : null}\n <div className=\"flex items-center gap-2\">\n <Button size=\"sm\" type=\"submit\" disabled={saveDisabled}>\n {t.saveLabel}\n </Button>\n <Button size=\"sm\" variant=\"ghost\" type=\"button\" onClick={() => setDraft(null)}>\n {t.cancelLabel}\n </Button>\n </div>\n </form>\n ) : null}\n </div>\n )\n})\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/web-search-providers/WebSearchProvidersPanel.tsx"],"names":["WebSearchProvidersPanel"],"mappings":"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","file":"chunk-PQGWPXEG.js","sourcesContent":["import * as React from 'react'\nimport { ChevronDown, ChevronUp, Pencil, Plus, Trash2 } from 'lucide-react'\nimport { cn } from '../../lib/utils'\nimport { Button } from '../button/Button'\nimport { ConnectionTestRow, type ConnectionTestStatus } from '../connection-test-row/ConnectionTestRow'\n\nexport type WebSearchProbeStatus =\n | 'ok'\n | 'unreachable'\n | 'auth'\n | 'rate_limit'\n | 'json_disabled'\n | 'error'\n\nexport interface WebSearchProviderView {\n id: string\n name: string\n type: string\n enabled: boolean\n baseUrl?: string | null\n googleCx?: string | null\n keyHint?: string | null\n keySet: boolean\n}\n\nexport interface WebSearchProviderCatalogField {\n id: string\n label: string\n required: boolean\n placeholder?: string\n}\n\nexport interface WebSearchProviderCatalogEntry {\n label: string\n requiresKey: boolean\n keyUrl?: string | null\n baseUrl?: string | null\n baseUrlRequired: boolean\n baseUrlHint?: string | null\n notes?: string | null\n fields?: WebSearchProviderCatalogField[]\n}\n\nexport interface WebSearchProviderCatalog {\n /** Rendering + form order for provider types. */\n order: string[]\n entries: Record<string, WebSearchProviderCatalogEntry>\n}\n\nexport interface WebSearchProviderSaveInput {\n /** Absent = create. */\n id?: string\n type: string\n name?: string | null\n baseUrl?: string | null\n googleCx?: string | null\n /** `null` keeps the stored key, a value stores it. */\n apiKey?: string | null\n}\n\nexport interface WebSearchProviderProbeView {\n status: WebSearchProbeStatus\n latencyMs?: number | null\n error?: string | null\n}\n\nexport interface WebSearchProvidersPanelLabels {\n title?: string\n hint?: string\n addLabel?: string\n emptyLabel?: string\n nameLabel?: string\n typeLabel?: string\n baseUrlLabel?: string\n baseUrlRequiredLabel?: string\n keyLabel?: string\n keyOptionalLabel?: string\n keyStoredLabel?: string\n noKeyLabel?: string\n saveLabel?: string\n cancelLabel?: string\n editLabel?: string\n deleteLabel?: string\n moveUpLabel?: string\n moveDownLabel?: string\n enabledAriaLabel?: string\n disabledBadge?: string\n testLabel?: string\n probeLabels?: Partial<Record<WebSearchProbeStatus, string>>\n}\n\nexport interface WebSearchProvidersPanelProps {\n providers: WebSearchProviderView[]\n catalog: WebSearchProviderCatalog\n /** Connection probes keyed by provider id. */\n probes?: Record<string, WebSearchProviderProbeView>\n /** Id currently mid-test (shows the testing spinner). */\n testingId?: string | null\n busy?: boolean\n labels?: WebSearchProvidersPanelLabels\n onSave: (input: WebSearchProviderSaveInput) => void\n onDelete: (id: string) => void\n onMove: (id: string, direction: 'up' | 'down') => void\n onToggle: (id: string, enabled: boolean) => void\n onTest: (id: string) => void\n className?: string\n}\n\nconst inputClass =\n 'min-w-0 flex-1 rounded-[var(--as-radius-sm)] border border-[var(--as-border)] bg-[var(--as-surface)] px-2 py-1.5 text-sm text-[var(--as-fg)] placeholder:text-[var(--as-muted-fg)] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]'\n\n/**\n * Presentational ordered web-search provider list (ADR-0035 family shape):\n * enable/reorder/test/edit/delete rows plus a catalog-driven add/edit form.\n * Fully controlled — persistence, keys and probes are app-side; the panel\n * renders and emits. The first enabled provider that answers wins is the\n * family's fallback semantics, surfaced here by row order.\n */\nexport const WebSearchProvidersPanel = React.forwardRef<\n HTMLDivElement,\n WebSearchProvidersPanelProps\n>(function WebSearchProvidersPanel(\n {\n providers,\n catalog,\n probes = {},\n testingId = null,\n busy = false,\n labels,\n onSave,\n onDelete,\n onMove,\n onToggle,\n onTest,\n className,\n },\n ref,\n) {\n const t = React.useMemo(\n () => ({\n title: labels?.title ?? 'Web search providers',\n hint: labels?.hint,\n addLabel: labels?.addLabel ?? 'Add provider',\n emptyLabel: labels?.emptyLabel ?? 'No web search providers yet.',\n nameLabel: labels?.nameLabel ?? 'Name (optional)',\n typeLabel: labels?.typeLabel ?? 'Provider type',\n baseUrlLabel: labels?.baseUrlLabel ?? 'Base URL (optional)',\n baseUrlRequiredLabel: labels?.baseUrlRequiredLabel ?? 'Base URL (required)',\n keyLabel: labels?.keyLabel ?? 'API key',\n keyOptionalLabel: labels?.keyOptionalLabel ?? 'API key (optional)',\n keyStoredLabel: labels?.keyStoredLabel ?? 'API key saved',\n noKeyLabel: labels?.noKeyLabel ?? 'no key',\n saveLabel: labels?.saveLabel ?? 'Save provider',\n cancelLabel: labels?.cancelLabel ?? 'Cancel',\n editLabel: labels?.editLabel ?? 'Edit provider',\n deleteLabel: labels?.deleteLabel ?? 'Delete provider',\n moveUpLabel: labels?.moveUpLabel ?? 'Move up',\n moveDownLabel: labels?.moveDownLabel ?? 'Move down',\n enabledAriaLabel: labels?.enabledAriaLabel ?? 'Enable provider',\n disabledBadge: labels?.disabledBadge ?? 'disabled',\n testLabel: labels?.testLabel ?? 'Test',\n probeLabels: { ...labels?.probeLabels },\n }),\n [labels],\n )\n\n const [draft, setDraft] = React.useState<WebSearchProviderSaveInput | null>(null)\n\n const openAdd = () => {\n const first = catalog.order[0]\n if (first) setDraft({ type: first, name: '', baseUrl: '', googleCx: '', apiKey: null })\n }\n\n const openEdit = (provider: WebSearchProviderView) =>\n setDraft({\n id: provider.id,\n type: provider.type,\n name: provider.name,\n baseUrl: provider.baseUrl ?? '',\n googleCx: provider.googleCx ?? '',\n apiKey: null,\n })\n\n const draftEntry = draft ? catalog.entries[draft.type] : undefined\n const draftCxField = draftEntry?.fields?.some((field) => field.id === 'google_cx') ?? false\n const saveDisabled =\n busy ||\n (draftEntry?.baseUrlRequired && !(draft?.baseUrl ?? '').trim()) ||\n (draft?.id == null && (draftEntry?.requiresKey ?? false) && !(draft?.apiKey ?? '').trim())\n\n return (\n <div\n ref={ref}\n data-as=\"web-search-providers\"\n className={cn(\n 'rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface)] p-4',\n className,\n )}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"min-w-0\">\n <p className=\"text-base font-medium text-[var(--as-fg)]\">{t.title}</p>\n {t.hint ? (\n <p className=\"mt-0.5 text-xs text-[var(--as-muted-fg)]\">{t.hint}</p>\n ) : null}\n </div>\n {draft === null ? (\n <Button variant=\"outline\" size=\"sm\" onClick={openAdd}>\n <Plus className=\"size-4\" aria-hidden />\n {t.addLabel}\n </Button>\n ) : null}\n </div>\n\n <ul className=\"mt-3 space-y-2\" data-testid=\"wsp-rows\">\n {providers.map((provider, index) => {\n const probe = probes[provider.id]\n const isTesting = testingId === provider.id\n const showProbeRow = probe != null || isTesting\n const probeStatus: ConnectionTestStatus | null = !showProbeRow\n ? null\n : isTesting\n ? 'testing'\n : probe!.status === 'ok'\n ? 'ok'\n : 'fail'\n const probeText =\n probe && probe.status !== 'ok' && probe.error\n ? probe.error\n : probe\n ? (t.probeLabels[probe.status] ?? probe.status)\n : null\n return (\n <li\n key={provider.id}\n data-testid={`wsp-row-${provider.id}`}\n className=\"border-border border-[var(--as-border)] space-y-1 rounded-[var(--as-radius-sm)] border p-3\"\n >\n <div className=\"flex flex-wrap items-center gap-2\">\n <label className=\"flex cursor-pointer items-center gap-2 text-sm font-medium text-[var(--as-fg)]\">\n <input\n type=\"checkbox\"\n checked={provider.enabled}\n aria-label={`${t.enabledAriaLabel}: ${provider.name}`}\n onChange={(event) => onToggle(provider.id, event.target.checked)}\n />\n {provider.name}\n </label>\n <span className=\"rounded-full bg-[var(--as-secondary)] px-2 py-0.5 text-[11px] text-[var(--as-muted-fg)]\">\n {catalog.entries[provider.type]?.label ?? provider.type}\n </span>\n {provider.baseUrl ? (\n <span className=\"truncate font-mono text-xs text-[var(--as-muted-fg)]\">\n {provider.baseUrl}\n </span>\n ) : null}\n <span className=\"ml-auto text-xs text-[var(--as-muted-fg)]\">\n {provider.keySet\n ? (provider.keyHint ?? t.keyStoredLabel)\n : t.noKeyLabel}\n </span>\n </div>\n {showProbeRow ? (\n <ConnectionTestRow\n variant=\"inline\"\n status={probeStatus ?? 'idle'}\n latencyMs={probe?.latencyMs ?? null}\n label={catalog.entries[provider.type]?.label ?? provider.type}\n testLabel={t.testLabel}\n okLabel={t.probeLabels.ok ?? probe?.status ?? 'ok'}\n failLabel={probeText ?? t.probeLabels.error ?? probe?.status ?? 'failed'}\n errorMessage={probe && probe.status === 'ok' ? null : (probe?.error ?? null)}\n />\n ) : null}\n <div className=\"flex flex-wrap items-center gap-1.5\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={busy || testingId === provider.id}\n onClick={() => onTest(provider.id)}\n >\n {t.testLabel}\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={`${t.moveUpLabel}: ${provider.name}`}\n disabled={index === 0 || busy}\n onClick={() => onMove(provider.id, 'up')}\n >\n <ChevronUp className=\"size-4\" aria-hidden />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={`${t.moveDownLabel}: ${provider.name}`}\n disabled={index === providers.length - 1 || busy}\n onClick={() => onMove(provider.id, 'down')}\n >\n <ChevronDown className=\"size-4\" aria-hidden />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={`${t.editLabel}: ${provider.name}`}\n disabled={busy}\n onClick={() => openEdit(provider)}\n >\n <Pencil className=\"size-4\" aria-hidden />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={`${t.deleteLabel}: ${provider.name}`}\n disabled={busy}\n onClick={() => onDelete(provider.id)}\n >\n <Trash2 className=\"size-4\" aria-hidden />\n </Button>\n {!provider.enabled ? (\n <span className=\"text-xs text-[var(--as-muted-fg)]\">\n {t.disabledBadge}\n </span>\n ) : null}\n </div>\n </li>\n )\n })}\n </ul>\n\n {providers.length === 0 && draft === null ? (\n <p className=\"py-4 text-center text-sm text-[var(--as-muted-fg)]\" data-testid=\"wsp-empty\">\n {t.emptyLabel}\n </p>\n ) : null}\n\n {draft !== null ? (\n <form\n data-testid=\"wsp-form\"\n className=\"mt-3 space-y-2 rounded-[var(--as-radius-sm)] border border-[var(--as-border)] p-3\"\n onSubmit={(event) => {\n event.preventDefault()\n onSave(draft)\n }}\n >\n <div className=\"flex flex-wrap gap-2\">\n <select\n className={inputClass}\n value={draft.type}\n disabled={draft.id != null || busy}\n aria-label={t.typeLabel}\n onChange={(event) =>\n setDraft({ ...draft, type: event.target.value, googleCx: '' })\n }\n >\n {catalog.order.map((type) => (\n <option key={type} value={type}>\n {catalog.entries[type]?.label ?? type}\n </option>\n ))}\n </select>\n <input\n className={inputClass}\n placeholder={t.nameLabel}\n value={draft.name ?? ''}\n onChange={(event) => setDraft({ ...draft, name: event.target.value })}\n />\n </div>\n <div className=\"flex flex-wrap gap-2\">\n <input\n className={inputClass}\n placeholder={\n draftEntry?.baseUrlRequired\n ? t.baseUrlRequiredLabel\n : (draftEntry?.baseUrlHint ?? t.baseUrlLabel)\n }\n value={draft.baseUrl ?? ''}\n onChange={(event) => setDraft({ ...draft, baseUrl: event.target.value })}\n />\n {draftCxField ? (\n <input\n className={cn(inputClass, 'w-48 flex-none')}\n placeholder={draftEntry?.fields?.find((f) => f.id === 'google_cx')?.placeholder ?? ''}\n aria-label={draftEntry?.fields?.find((f) => f.id === 'google_cx')?.label ?? 'Engine id'}\n value={draft.googleCx ?? ''}\n onChange={(event) => setDraft({ ...draft, googleCx: event.target.value })}\n />\n ) : null}\n <input\n type=\"password\"\n className={cn(inputClass, 'w-48 flex-none')}\n placeholder={\n draft.id != null\n ? t.keyStoredLabel\n : draftEntry?.requiresKey\n ? t.keyLabel\n : t.keyOptionalLabel\n }\n aria-label={t.keyLabel}\n value={draft.apiKey ?? ''}\n onChange={(event) => setDraft({ ...draft, apiKey: event.target.value })}\n />\n </div>\n {draftEntry?.notes ? (\n <p className=\"text-[11px] text-[var(--as-muted-fg)]\">{draftEntry.notes}</p>\n ) : null}\n <div className=\"flex items-center gap-2\">\n <Button size=\"sm\" type=\"submit\" disabled={saveDisabled}>\n {t.saveLabel}\n </Button>\n <Button size=\"sm\" variant=\"ghost\" type=\"button\" onClick={() => setDraft(null)}>\n {t.cancelLabel}\n </Button>\n </div>\n </form>\n ) : null}\n </div>\n )\n})\n"]}
|
|
@@ -11,6 +11,7 @@ var ConnectionTestRow = React.forwardRef(function ConnectionTestRow2({
|
|
|
11
11
|
testLabel = "Test",
|
|
12
12
|
okLabel = "Connected",
|
|
13
13
|
failLabel = "Failed",
|
|
14
|
+
idleLabel,
|
|
14
15
|
latencyLabel = "ms",
|
|
15
16
|
errorMessage,
|
|
16
17
|
onTest,
|
|
@@ -52,7 +53,7 @@ var ConnectionTestRow = React.forwardRef(function ConnectionTestRow2({
|
|
|
52
53
|
latencyMs,
|
|
53
54
|
latencyLabel
|
|
54
55
|
] }) : null
|
|
55
|
-
] }) : null,
|
|
56
|
+
] }) : status === "idle" && idleLabel ? /* @__PURE__ */ jsx("span", { className: "flex items-center gap-1 font-medium text-[var(--as-muted-fg)]", children: idleLabel }) : null,
|
|
56
57
|
status === "fail" && errorMessage ? /* @__PURE__ */ jsx("span", { className: "min-w-0 whitespace-pre-wrap break-words text-xs text-[var(--as-danger)]", children: errorMessage }) : null,
|
|
57
58
|
meta ? /* @__PURE__ */ jsx("span", { className: "text-xs text-[var(--as-muted-fg)]", children: meta }) : null
|
|
58
59
|
] }),
|
|
@@ -75,5 +76,5 @@ var ConnectionTestRow = React.forwardRef(function ConnectionTestRow2({
|
|
|
75
76
|
});
|
|
76
77
|
|
|
77
78
|
export { ConnectionTestRow };
|
|
78
|
-
//# sourceMappingURL=chunk-
|
|
79
|
-
//# sourceMappingURL=chunk-
|
|
79
|
+
//# sourceMappingURL=chunk-QSZND2FV.js.map
|
|
80
|
+
//# sourceMappingURL=chunk-QSZND2FV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/connection-test-row/ConnectionTestRow.tsx"],"names":["ConnectionTestRow"],"mappings":"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","file":"chunk-QSZND2FV.js","sourcesContent":["import * as React from 'react'\nimport { Check, TriangleAlert, X } from 'lucide-react'\nimport { cn } from '../../lib/utils'\nimport { Spinner } from '../spinner/Spinner'\n\nexport type ConnectionTestStatus = 'idle' | 'testing' | 'ok' | 'fail'\n\nexport interface ConnectionTestRowProps {\n status: ConnectionTestStatus\n latencyMs?: number | null\n label?: string\n testLabel?: string\n okLabel?: string\n failLabel?: string\n /** Text for the never-tested state (\"Not tested\") — the row shows no\n * status text when idle unless this is set. */\n idleLabel?: string\n latencyLabel?: string\n errorMessage?: string | null\n onTest?: () => void\n disabled?: boolean\n /** `row` = standalone bordered row; `inline` = bare, for embedding in app cards. */\n variant?: 'row' | 'inline'\n /** Extra app-side context rendered after the status (e.g. model count). */\n meta?: React.ReactNode\n className?: string\n}\n\n/**\n * Presentational connection-test row (idle/testing/ok/fail + latency).\n * The actual ping is app-side: flip `status` from the test handler.\n */\nexport const ConnectionTestRow = React.forwardRef<\n HTMLDivElement,\n ConnectionTestRowProps\n>(function ConnectionTestRow(\n {\n status,\n latencyMs,\n label = 'Connection',\n testLabel = 'Test',\n okLabel = 'Connected',\n failLabel = 'Failed',\n idleLabel,\n latencyLabel = 'ms',\n errorMessage,\n onTest,\n disabled = false,\n variant = 'row',\n meta,\n className,\n },\n ref,\n) {\n const state =\n status === 'ok'\n ? { text: okLabel, icon: <Check className=\"size-3.5\" aria-hidden />, tone: 'text-[var(--as-success)]' }\n : status === 'fail'\n ? {\n text: failLabel,\n icon: <TriangleAlert className=\"size-3.5\" aria-hidden />,\n tone: 'text-[var(--as-danger)]',\n }\n : null\n\n return (\n <div\n ref={ref}\n data-as=\"connection-test-row\"\n data-status={status}\n data-variant={variant}\n className={cn(\n 'flex items-center justify-between gap-3 rounded-[var(--as-radius)] px-3 py-2',\n variant === 'row' && 'border border-[var(--as-border)] bg-[var(--as-surface)]',\n variant === 'inline' && 'px-0 py-0',\n className,\n )}\n >\n <div className=\"flex min-w-0 items-center gap-2 text-sm\">\n <span className=\"font-medium text-[var(--as-fg)]\">{label}</span>\n {status === 'testing' ? (\n <span className=\"flex items-center gap-1.5 text-[var(--as-muted-fg)]\" role=\"status\">\n <Spinner size=\"sm\" />\n {testLabel}…\n </span>\n ) : state ? (\n <span className={cn('flex items-center gap-1 font-medium', state.tone)}>\n {state.icon}\n {state.text}\n {status === 'ok' && latencyMs != null ? (\n <span className=\"font-normal text-[var(--as-muted-fg)]\">\n · {latencyMs}\n {latencyLabel}\n </span>\n ) : null}\n </span>\n ) : status === 'idle' && idleLabel ? (\n <span className=\"flex items-center gap-1 font-medium text-[var(--as-muted-fg)]\">\n {idleLabel}\n </span>\n ) : null}\n {status === 'fail' && errorMessage ? (\n <span className=\"min-w-0 whitespace-pre-wrap break-words text-xs text-[var(--as-danger)]\">\n {errorMessage}\n </span>\n ) : null}\n {meta ? <span className=\"text-xs text-[var(--as-muted-fg)]\">{meta}</span> : null}\n </div>\n {onTest ? (\n <button\n type=\"button\"\n onClick={onTest}\n disabled={disabled || status === 'testing'}\n className=\"shrink-0 cursor-pointer rounded-[var(--as-radius-sm)] border border-[var(--as-border)] px-2.5 py-1 text-xs font-medium text-[var(--as-fg)] transition-colors hover:bg-[var(--as-secondary)] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)] disabled:pointer-events-none disabled:opacity-50\"\n >\n {status === 'fail' ? <X className=\"mr-1 inline size-3\" aria-hidden /> : null}\n {testLabel}\n </button>\n ) : null}\n </div>\n )\n})\n"]}
|
|
@@ -8,6 +8,9 @@ interface ConnectionTestRowProps {
|
|
|
8
8
|
testLabel?: string;
|
|
9
9
|
okLabel?: string;
|
|
10
10
|
failLabel?: string;
|
|
11
|
+
/** Text for the never-tested state ("Not tested") — the row shows no
|
|
12
|
+
* status text when idle unless this is set. */
|
|
13
|
+
idleLabel?: string;
|
|
11
14
|
latencyLabel?: string;
|
|
12
15
|
errorMessage?: string | null;
|
|
13
16
|
onTest?: () => void;
|
package/dist/index.d.ts
CHANGED
|
@@ -511,6 +511,9 @@ interface ConnectionTestRowProps {
|
|
|
511
511
|
testLabel?: string;
|
|
512
512
|
okLabel?: string;
|
|
513
513
|
failLabel?: string;
|
|
514
|
+
/** Text for the never-tested state ("Not tested") — the row shows no
|
|
515
|
+
* status text when idle unless this is set. */
|
|
516
|
+
idleLabel?: string;
|
|
514
517
|
latencyLabel?: string;
|
|
515
518
|
errorMessage?: string | null;
|
|
516
519
|
onTest?: () => void;
|
|
@@ -1025,6 +1028,9 @@ interface ProviderCardProps extends Omit<React.ComponentProps<'div'>, 'children'
|
|
|
1025
1028
|
connectionLabel?: string;
|
|
1026
1029
|
okLabel?: string;
|
|
1027
1030
|
failLabel?: string;
|
|
1031
|
+
/** Text for the never-tested state ("Not tested") — shown when the
|
|
1032
|
+
* connection has never been tested. */
|
|
1033
|
+
idleLabel?: string;
|
|
1028
1034
|
latencyLabel?: string;
|
|
1029
1035
|
latencyMs?: number | null;
|
|
1030
1036
|
errorMessage?: string | null;
|
package/dist/index.js
CHANGED
|
@@ -18,7 +18,7 @@ export { Skeleton, SkeletonText } from './chunk-4OJXAFGA.js';
|
|
|
18
18
|
export { HoverCard, HoverCardContent, HoverCardPortal, HoverCardTrigger } from './chunk-PNYJ5VX2.js';
|
|
19
19
|
export { SetupSteps } from './chunk-K54EWKQC.js';
|
|
20
20
|
export { SetupAssignments } from './chunk-MVJCUNCD.js';
|
|
21
|
-
export { ProviderCard } from './chunk-
|
|
21
|
+
export { ProviderCard } from './chunk-7LT2HC54.js';
|
|
22
22
|
export { RangeBar } from './chunk-3UDWLHLD.js';
|
|
23
23
|
export { ScaleSlider, scaleColorForValue } from './chunk-NLHODVBI.js';
|
|
24
24
|
export { ProfileSwitcher } from './chunk-6ANLDUGL.js';
|
|
@@ -55,8 +55,8 @@ export { ExpandableSearch } from './chunk-BAXBFV7Q.js';
|
|
|
55
55
|
export { ChatTraceMeta } from './chunk-5CIRID6W.js';
|
|
56
56
|
export { ChatTraceTimeline } from './chunk-HR3FYO7C.js';
|
|
57
57
|
export { ChatToolsCatalog } from './chunk-OMWI53FM.js';
|
|
58
|
-
export { WebSearchProvidersPanel } from './chunk-
|
|
59
|
-
export { ConnectionTestRow } from './chunk-
|
|
58
|
+
export { WebSearchProvidersPanel } from './chunk-PQGWPXEG.js';
|
|
59
|
+
export { ConnectionTestRow } from './chunk-QSZND2FV.js';
|
|
60
60
|
export { CheckIndicator } from './chunk-FVIIVWRC.js';
|
|
61
61
|
export { ChipInput } from './chunk-HQN55NOV.js';
|
|
62
62
|
export { ChatDrawer } from './chunk-UKR2WUO3.js';
|
package/dist/provider-card.d.ts
CHANGED
|
@@ -41,6 +41,9 @@ interface ProviderCardProps extends Omit<React.ComponentProps<'div'>, 'children'
|
|
|
41
41
|
connectionLabel?: string;
|
|
42
42
|
okLabel?: string;
|
|
43
43
|
failLabel?: string;
|
|
44
|
+
/** Text for the never-tested state ("Not tested") — shown when the
|
|
45
|
+
* connection has never been tested. */
|
|
46
|
+
idleLabel?: string;
|
|
44
47
|
latencyLabel?: string;
|
|
45
48
|
latencyMs?: number | null;
|
|
46
49
|
errorMessage?: string | null;
|
package/dist/provider-card.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neuronection/assistant-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.62.0",
|
|
4
4
|
"description": "Shared React component library for the Assistant family (career-, study-, health-, desktop-assistant). Family look by default, app-flavored via CSS-variable tokens.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/provider-card/ProviderCard.tsx"],"names":["ProviderCard"],"mappings":";;;;;;;;AA2DO,IAAM,YAAA,GAAqB,KAAA,CAAA,UAAA;AAAA,EAChC,SAASA,aAAAA,CACP;AAAA,IACE,IAAA;AAAA,IACA,UAAA;AAAA,IACA,SAAA;AAAA,IACA,MAAA;AAAA,IACA,MAAA,GAAS,MAAA;AAAA,IACT,eAAA;AAAA,IACA,OAAA;AAAA,IACA,SAAA;AAAA,IACA,YAAA;AAAA,IACA,SAAA;AAAA,IACA,YAAA;AAAA,IACA,IAAA;AAAA,IACA,OAAA;AAAA,IACA,YAAA;AAAA,IACA,SAAA;AAAA,IACA,GAAG;AAAA,KAEL,GAAA,EACA;AACA,IAAA,uBACE,IAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,SAAA,EAAQ,eAAA;AAAA,QACR,SAAA,EAAW,EAAA;AAAA,UACT,kIAAA;AAAA,UACA;AAAA,SACF;AAAA,QACC,GAAG,KAAA;AAAA,QAEJ,QAAA,EAAA;AAAA,0BAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,gBAAA,EACb,QAAA,EAAA;AAAA,4BAAA,IAAA,CAAC,GAAA,EAAA,EAAE,WAAU,yDAAA,EACX,QAAA,EAAA;AAAA,8BAAA,GAAA,CAAC,YAAA,EAAA,EAAa,MAAA,EAAQ,UAAA,IAAc,EAAA,EAAI,WAAU,UAAA,EAAW,CAAA;AAAA,kCAC5D,MAAA,EAAA,EAAK,SAAA,EAAU,UAAA,EAAW,KAAA,EAAO,WAC/B,QAAA,EAAA,IAAA,EACH,CAAA;AAAA,cAAA,CACE,MAAA,IAAU,EAAC,EAAG,GAAA,CAAI,CAAC,KAAA,qBACnB,GAAA;AAAA,gBAAC,MAAA;AAAA,gBAAA;AAAA,kBAEC,OAAO,KAAA,CAAM,KAAA;AAAA,kBACb,eAAa,KAAA,CAAM,MAAA;AAAA,kBACnB,SAAA,EAAW,EAAA;AAAA,oBACT,+FAAA;AAAA,oBACA,MAAM,MAAA,IAAU;AAAA,mBAClB;AAAA,kBAEC,QAAA,EAAA,KAAA,CAAM;AAAA,iBAAA;AAAA,gBARF,KAAA,CAAM;AAAA,eAUd;AAAA,aAAA,EACH,CAAA;AAAA,4BACA,GAAA;AAAA,cAAC,iBAAA;AAAA,cAAA;AAAA,gBACC,OAAA,EAAQ,QAAA;AAAA,gBACR,SAAA,EAAU,QAAA;AAAA,gBACV,KAAA,EAAO,eAAA;AAAA,gBACP,MAAA;AAAA,gBACA,SAAA;AAAA,gBACA,YAAA;AAAA,gBACA,YAAA;AAAA,gBACA,IAAA;AAAA,gBACA,OAAA;AAAA,gBACA;AAAA;AAAA;AACF,WAAA,EACF,CAAA;AAAA,UACC,OAAA,IAAW,OAAA,CAAQ,MAAA,GAAS,CAAA,mBAC3B,GAAA;AAAA,YAAC,UAAA;AAAA,YAAA;AAAA,cACC,OAAO,YAAA,IAAgB,IAAA;AAAA,cACvB,KAAA,EAAM,KAAA;AAAA,cACN,yBAAS,GAAA,CAAC,gBAAA,EAAA,EAAiB,SAAA,EAAU,QAAA,EAAS,eAAW,IAAA,EAAC,CAAA;AAAA,cAC1D,KAAA,EAAO;AAAA;AAAA,WACT,GACE;AAAA;AAAA;AAAA,KACN;AAAA,EAEJ;AACF","file":"chunk-KCXU3SDM.js","sourcesContent":["import * as React from 'react'\nimport { EllipsisVertical } from 'lucide-react'\nimport { cn } from '../../lib/utils'\nimport {\n ActionMenu,\n type ActionMenuItem,\n} from '../menu/Menu'\nimport {\n ConnectionTestRow,\n type ConnectionTestStatus,\n} from '../connection-test-row/ConnectionTestRow'\nimport { ProviderLogo } from '../provider-logo/ProviderLogo'\n\nexport interface ProviderCardBadge {\n /** Stable badge id (also the React key). */\n key: string\n label: string\n /** Tooltip on the badge (e.g. the country's name behind its flag). */\n title?: string\n /** Danger tone (the \"inactive\" marker). */\n danger?: boolean\n /** Apps target badges in tests (`data-testid`). */\n testId?: string\n}\n\n/** Same shape as the overflow menu's items — management actions\n * (\"Set up automatically\", \"Edit\", \"Delete\"), not the inline test. */\nexport type ProviderCardAction = ActionMenuItem\n\nexport interface ProviderCardProps\n extends Omit<React.ComponentProps<'div'>, 'children'> {\n name: string\n /** Preset key for the provider mark — unknown keys fall back to the\n * monogram. */\n logoPreset?: string\n /** Tooltip on the name — the connection string's only at-a-glance home\n * (config detail lives in Edit; the card stays status-forward). */\n nameTitle?: string\n badges?: ProviderCardBadge[]\n status?: ConnectionTestStatus\n /** Accessible label for the connection row. */\n connectionLabel?: string\n okLabel?: string\n failLabel?: string\n latencyLabel?: string\n latencyMs?: number | null\n errorMessage?: string | null\n /** Context after the status — model count. */\n meta?: React.ReactNode\n actions?: ProviderCardAction[]\n /** Accessible label for the actions menu. */\n actionsLabel?: string\n}\n\n/** One provider summary card: mark + name + identity badges, the\n * connection result as the card's second line (status display only —\n * the test action lives in the `⋯` overflow menu alongside the other\n * management actions), and config detail (base URL) as a name tooltip.\n * Presentational and controlled: data in via props, events out. */\nexport const ProviderCard = React.forwardRef<HTMLDivElement, ProviderCardProps>(\n function ProviderCard(\n {\n name,\n logoPreset,\n nameTitle,\n badges,\n status = 'idle',\n connectionLabel,\n okLabel,\n failLabel,\n latencyLabel,\n latencyMs,\n errorMessage,\n meta,\n actions,\n actionsLabel,\n className,\n ...props\n },\n ref,\n ) {\n return (\n <div\n ref={ref}\n data-as=\"provider-card\"\n className={cn(\n 'flex items-start justify-between gap-2 rounded-[var(--as-radius-lg)] border border-[var(--as-border)] bg-[var(--as-surface)] p-4',\n className,\n )}\n {...props}\n >\n <div className=\"min-w-0 flex-1\">\n <p className=\"flex items-center gap-2 font-medium text-[var(--as-fg)]\">\n <ProviderLogo preset={logoPreset ?? ''} className=\"shrink-0\" />\n <span className=\"truncate\" title={nameTitle}>\n {name}\n </span>\n {(badges ?? []).map((badge) => (\n <span\n key={badge.key}\n title={badge.title}\n data-testid={badge.testId}\n className={cn(\n 'shrink-0 rounded bg-[var(--as-secondary)] px-1.5 py-0.5 text-xs text-[var(--as-secondary-fg)]',\n badge.danger && 'bg-transparent text-[var(--as-danger)]',\n )}\n >\n {badge.label}\n </span>\n ))}\n </p>\n <ConnectionTestRow\n variant=\"inline\"\n className=\"mt-1.5\"\n label={connectionLabel}\n status={status}\n latencyMs={latencyMs}\n latencyLabel={latencyLabel}\n errorMessage={errorMessage}\n meta={meta}\n okLabel={okLabel}\n failLabel={failLabel}\n />\n </div>\n {actions && actions.length > 0 ? (\n <ActionMenu\n label={actionsLabel ?? name}\n align=\"end\"\n trigger={<EllipsisVertical className=\"size-4\" aria-hidden />}\n items={actions}\n />\n ) : null}\n </div>\n )\n },\n)\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/connection-test-row/ConnectionTestRow.tsx"],"names":["ConnectionTestRow"],"mappings":"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","file":"chunk-O6BRNGXV.js","sourcesContent":["import * as React from 'react'\nimport { Check, TriangleAlert, X } from 'lucide-react'\nimport { cn } from '../../lib/utils'\nimport { Spinner } from '../spinner/Spinner'\n\nexport type ConnectionTestStatus = 'idle' | 'testing' | 'ok' | 'fail'\n\nexport interface ConnectionTestRowProps {\n status: ConnectionTestStatus\n latencyMs?: number | null\n label?: string\n testLabel?: string\n okLabel?: string\n failLabel?: string\n latencyLabel?: string\n errorMessage?: string | null\n onTest?: () => void\n disabled?: boolean\n /** `row` = standalone bordered row; `inline` = bare, for embedding in app cards. */\n variant?: 'row' | 'inline'\n /** Extra app-side context rendered after the status (e.g. model count). */\n meta?: React.ReactNode\n className?: string\n}\n\n/**\n * Presentational connection-test row (idle/testing/ok/fail + latency).\n * The actual ping is app-side: flip `status` from the test handler.\n */\nexport const ConnectionTestRow = React.forwardRef<\n HTMLDivElement,\n ConnectionTestRowProps\n>(function ConnectionTestRow(\n {\n status,\n latencyMs,\n label = 'Connection',\n testLabel = 'Test',\n okLabel = 'Connected',\n failLabel = 'Failed',\n latencyLabel = 'ms',\n errorMessage,\n onTest,\n disabled = false,\n variant = 'row',\n meta,\n className,\n },\n ref,\n) {\n const state =\n status === 'ok'\n ? { text: okLabel, icon: <Check className=\"size-3.5\" aria-hidden />, tone: 'text-[var(--as-success)]' }\n : status === 'fail'\n ? {\n text: failLabel,\n icon: <TriangleAlert className=\"size-3.5\" aria-hidden />,\n tone: 'text-[var(--as-danger)]',\n }\n : null\n\n return (\n <div\n ref={ref}\n data-as=\"connection-test-row\"\n data-status={status}\n data-variant={variant}\n className={cn(\n 'flex items-center justify-between gap-3 rounded-[var(--as-radius)] px-3 py-2',\n variant === 'row' && 'border border-[var(--as-border)] bg-[var(--as-surface)]',\n variant === 'inline' && 'px-0 py-0',\n className,\n )}\n >\n <div className=\"flex min-w-0 items-center gap-2 text-sm\">\n <span className=\"font-medium text-[var(--as-fg)]\">{label}</span>\n {status === 'testing' ? (\n <span className=\"flex items-center gap-1.5 text-[var(--as-muted-fg)]\" role=\"status\">\n <Spinner size=\"sm\" />\n {testLabel}…\n </span>\n ) : state ? (\n <span className={cn('flex items-center gap-1 font-medium', state.tone)}>\n {state.icon}\n {state.text}\n {status === 'ok' && latencyMs != null ? (\n <span className=\"font-normal text-[var(--as-muted-fg)]\">\n · {latencyMs}\n {latencyLabel}\n </span>\n ) : null}\n </span>\n ) : null}\n {status === 'fail' && errorMessage ? (\n <span className=\"min-w-0 whitespace-pre-wrap break-words text-xs text-[var(--as-danger)]\">\n {errorMessage}\n </span>\n ) : null}\n {meta ? <span className=\"text-xs text-[var(--as-muted-fg)]\">{meta}</span> : null}\n </div>\n {onTest ? (\n <button\n type=\"button\"\n onClick={onTest}\n disabled={disabled || status === 'testing'}\n className=\"shrink-0 cursor-pointer rounded-[var(--as-radius-sm)] border border-[var(--as-border)] px-2.5 py-1 text-xs font-medium text-[var(--as-fg)] transition-colors hover:bg-[var(--as-secondary)] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)] disabled:pointer-events-none disabled:opacity-50\"\n >\n {status === 'fail' ? <X className=\"mr-1 inline size-3\" aria-hidden /> : null}\n {testLabel}\n </button>\n ) : null}\n </div>\n )\n})\n"]}
|