-
+
{schema.title}
+ setFilterQuery(e.target.value)}
+ placeholder="Filter…"
+ aria-label="Filter attributes"
+ data-testid="attributes-filter"
+ style={{
+ flex: "1 1 100px",
+ minWidth: 80,
+ maxWidth: 160,
+ fontSize: 12,
+ padding: "4px 6px",
+ border: "1px solid #ccc",
+ borderRadius: 4,
+ }}
+ />
@@ -286,13 +344,22 @@ export function FormRenderer({
})
}
onCancel={() => onCancelAddField?.()}
- saveLabel="Add field"
- badge="New form field"
+ saveLabel="Add attribute"
+ badge="New attribute"
testidPrefix="field-add"
/>
)}
- {schema.fields.map((field) => (
+ {visibleFields.length === 0 && schema.fields.length > 0 && (
+
+ No matches.
+
+ )}
+
+ {visibleFields.map((field) => (
onCancelFieldEdit?.()}
/>
))}
-
+
);
-}
\ No newline at end of file
+}
diff --git a/src/index.ts b/src/index.ts
index a2e88f4..a0c7754 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -2,8 +2,9 @@ export * from "./repos";
export * from "./services";
export * from "./state";
export * from "./visual-guide";
-export { FormRenderer } from "./FormRenderer";
+export { FormRenderer, matchesTextFilter } from "./FormRenderer";
export type {
+ FieldDefinitionPatch,
FormFieldSchema,
FormRendererProps,
FormSchema,
diff --git a/src/visual-guide/Overlay.tsx b/src/visual-guide/Overlay.tsx
index aa257bf..e0fa2ad 100644
--- a/src/visual-guide/Overlay.tsx
+++ b/src/visual-guide/Overlay.tsx
@@ -11,10 +11,10 @@
* `useSyncExternalStore` subscription via `useRectRegistryVersion` picks
* up that single tick and React re-renders once per frame.
*
- * Active-only: only the currently active triple is drawn. If any leg's
- * rect is missing (e.g. the viewer hasn't reported a highlight rect for
- * the active annotation yet), that leg is omitted but the other one
- * still renders.
+ * Active-only: draws legs for the active evidence card. Attribute→card
+ * when a Capture attribute is focused; card→highlight whenever the
+ * highlight rect is available (Annotate or Capture). Missing legs are
+ * omitted independently.
*
* MVP-sufficient. Future polish: easing the curve direction by source
* type, animating the transition between active states, dimming
@@ -33,14 +33,6 @@ function rectCenter(rect: DOMRect): { x: number; y: number } {
return { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 };
}
-function rectBottomCenter(rect: DOMRect): { x: number; y: number } {
- return { x: rect.left + rect.width / 2, y: rect.bottom };
-}
-
-function rectTopCenter(rect: DOMRect): { x: number; y: number } {
- return { x: rect.left + rect.width / 2, y: rect.top };
-}
-
/**
* Build a quadratic bezier from `a` to `b` whose control point bulges
* horizontally between them. The horizontal-bulge style is right for a
@@ -72,18 +64,24 @@ export function Overlay({
const version = useRectRegistryVersion();
const paths = useMemo