Varendo

Explorer

Filter plus collection plus selected detail using shared parameter/selection state.

FamilycompoundLicenseApache-2.0
StandaloneAvailable

Use the web element directly without the semantic runtime.

Semantic bindingNo built-in binding

Use this component directly or compose it in application code.

Automatic adaptationNo standard recipe

The standard recipe resolver does not select this component automatically.

Import and live example

A people explorer combining authorized filters, a single-select record collection, and selected detail.

Interactive preview requires JavaScript.

View the complete example source
import {registerAeliqoElements} from "@varendo/web";
import {
  AeliqoBreakdownElement,
  AeliqoComparisonElement,
  AeliqoExplorerElement,
  AeliqoFormFlowElement,
  AeliqoInvestigationElement,
  AeliqoQualityPanelElement,
  AeliqoRecordEditorElement,
  AeliqoSearchResultsElement,
  } from "@varendo/web/compound";

import {AeliqoDateRangeElement, AeliqoTextFieldElement} from "@varendo/web/inputs";
import type {ResultRef, Scalar} from "@varendo/core";
import type {VisualizationBindingContext, VisualizationSpec} from "@varendo/core/visualization";
import type {AeliqoDataColumn, AeliqoDataScope, AeliqoFieldOption} from "@varendo/web/data";
import type {VisualizationDataset} from "@varendo/web/visualization";

const catalogRef: ResultRef = {
  id: "aeliqo-catalog-example",
  revision: "1",
  outputId: "people",
  queryDigest: "catalog-query",
  scopeDigest: "catalog-scope",
};
const catalogRows: readonly Readonly<Record<string, Scalar>>[] = [
  {id: "ada", name: "Ada Lovelace", team: "Research", date: "2026-09-08", amount: 120},
  {id: "lin", name: "Lin Chen", team: "Product", date: "2026-09-09", amount: 96},
  {id: "grace", name: "Grace Hopper", team: "Research", date: "2026-09-10", amount: 144},
];
const catalogColumns: readonly AeliqoDataColumn[] = [
  {key: "id", label: "ID", type: "text", sortable: true},
  {key: "name", label: "Name", type: "text", sortable: true},
  {key: "team", label: "Team", type: "text"},
  {key: "date", label: "Date", type: "date", sortable: true},
  {key: "amount", label: "Amount", type: "integer", align: "end"},
];
const catalogFields: readonly AeliqoFieldOption[] = [
  {id: "name", label: "Name", type: "text"},
  {id: "team", label: "Team", type: "text"},
  {id: "amount", label: "Amount", type: "integer"},
];
const catalogScope: AeliqoDataScope = {loaded: catalogRows.length, filteredTotal: catalogRows.length, populationDigest: catalogRef.scopeDigest, kind: "filtered", label: "Authorized people"};
const catalogVisualizationContext: VisualizationBindingContext = {results: []};
const catalogVisualizationDataset: VisualizationDataset = {result: catalogRef, rows: catalogRows};
const catalogVisualizationSpecs: Readonly<Record<"trend", VisualizationSpec>> = {trend: {version: "1", view: "trend", plot: {version: "1", root: {kind: "unit", mark: "line", result: catalogRef, missing: "gap", encoding: {x: {field: "date", scale: "temporal"}, y: {field: "amount", scale: "linear"}}}}}};

registerAeliqoElements();

const host = document.querySelector<HTMLElement>("#aeliqo-example") ?? (() => {
  const created = document.createElement("div");
  created.id = "aeliqo-example";
  (document.body ?? document.documentElement).append(created);
  return created;
})();

function createCatalogRoot(container: HTMLElement): HTMLElement {
  const root = document.createElement("div");
  root.dataset.catalogSourceRoot = "true";
  root.style.display = "grid";
  root.style.gap = "12px";
  container.append(root);
  return root;
}

function createCatalogElement<T extends HTMLElement>(tagName: string, container: HTMLElement): T {
  const element = document.createElement(tagName) as T;
  element.setAttribute("data-aeliqo-theme", "light");
  container.append(element);
  return element;
}

function appendSlottedText(root: HTMLElement, slot: string, textContent: string): void {
  const content = document.createElement("span");
  content.slot = slot;
  content.textContent = textContent;
  root.append(content);
}

const root = createCatalogRoot(host);
(((root) => {
		const element = createCatalogElement<AeliqoExplorerElement>("aeliqo-explorer", root);
		element.fields = catalogFields;
		element.rows = catalogRows;
		element.columns = catalogColumns;
		element.identity = ["id"];
		element.entity = "person";
		element.selectedKey = "string:3:ada";
		element.detailRecord = catalogRows[0];
		element.detailFields = catalogColumns;
		element.result = catalogRef;
		element.scope = catalogScope;
		element.selection = "single";
	}))(root);

Purpose

Explorer combines a filter bar, record list, and detail pane into one view with shared scope. Use it when browsing and inspecting records belong on the same screen.

When to use it

When to use a different component

Properties and defaults

Filter and selection requests retain result lineage and scope; persistence, navigation, and query execution remain with the host.

Properties, ownership, and initial values
PropertyUse and ownershipDeclared typeInitial value
fieldsDefines the fields available to this control, including stable IDs, labels, and declared types.readonly AeliqoFieldOption[][]
predicateSupplies the validated filter predicate represented by the current control state.AeliqoFilterPredicate | undefinedundefined
rowsSupplies the bounded records to render. The component never fetches or widens this set.readonly AeliqoDataRecord[][]
columnsDefines ordered visible fields, labels, formatting, alignment, and supported column interactions.readonly AeliqoDataColumn[][]
identityLists stable identity fields used for selection, detail targeting, and state transfer.readonly string[][]
entityNames the catalog entity whose records and identities are displayed.string'record'
selectedKeyControls the current record selection by stable encoded identity.string''
detailRecordSupplies detail record to the component as application-owned input.AeliqoDataRecord | undefinedundefined
detailFieldsSupplies the bounded ordered detail fields collection used by this component.readonly AeliqoDataColumn[][]
resultSupplies the Result reference that binds displayed data to its query and scope evidence.ResultRef | undefinedundefined
scopeSupplies the visible authorization and population scope associated with the displayed value or rows.AeliqoDataScope | undefinedundefined
statusSupplies the explicit ready, loading, empty, partial, stale, or error state.AeliqoCompoundStatus'ready'
messageProvides the user-facing status, error, or recovery message.string''
titleProvides the visible title for the current data or compound surface.string'Explore'
filterLabelProvides the visible text for the filter control or section.string'Filter'
collectionLabelProvides the visible text for the collection control or section.string'Records'
detailLabelProvides the visible text for the detail control or section.string'Selected detail'
selectionChooses none, single, or multiple selection behavior.'none' | 'single' | 'multiple''single'

Events

Events, payloads, timing, and application responsibilities
EventPayloadEmittedApplication responsibility
aeliqo-explorer-filterThe proposed validated predicate.After the explorer filter is applied.Evaluate the predicate in the host and replace rows/result evidence.
aeliqo-explorer-selectionThe selected stable identity key.After explorer selection changes.Load authorized detail evidence and update controlled selection.

Events cross the component boundary as user proposals. Validate their detail and current authority before applying a business effect.

Listen for aeliqo-explorer-filter

TypeScript example
const element = document.querySelector('aeliqo-explorer');<p>element?.addEventListener('aeliqo-explorer-filter', (event) => {
  const proposal = (event as CustomEvent<unknown>).detail;
  // Validate the proposal, update host state, then assign controlled properties.
  applyProposal(proposal);
});

Listen for aeliqo-explorer-selection

TypeScript example
const element = document.querySelector('aeliqo-explorer');</p>
<p>element?.addEventListener('aeliqo-explorer-selection', (event) => {
  const proposal = (event as CustomEvent<unknown>).detail;
  // Validate the proposal, update host state, then assign controlled properties.
  applyProposal(proposal);
});

States and failure handling

Relevant states:

Expected result: The three panels share one scope and stable identity while emitting typed filter and selection requests.

Keyboard, focus, and accessibility

Keyboard behavior:

Exposed semantics:

Responsive behavior

Stack filters, records, and detail in reading order on narrow hosts. Preserve the shared scope and selected identity when panels move.

Style hooks

Generated TypeScript declaration

View generated declaration
export declare class AeliqoExplorerElement extends AeliqoCompoundElement {
    static readonly properties: {
        fields: {
            attribute: boolean;
        };
        predicate: {
            attribute: boolean;
        };
        rows: {
            attribute: boolean;
        };
        columns: {
            attribute: boolean;
        };
        identity: {
            attribute: boolean;
        };
        entity: {
            type: StringConstructor;
        };
        selectedKey: {
            attribute: string;
            type: StringConstructor;
        };
        detailRecord: {
            attribute: boolean;
        };
        detailFields: {
            attribute: boolean;
        };
        result: {
            attribute: boolean;
        };
        scope: {
            attribute: boolean;
        };
        status: {
            type: StringConstructor;
        };
        message: {
            type: StringConstructor;
        };
        title: {
            type: StringConstructor;
        };
        filterLabel: {
            attribute: string;
            type: StringConstructor;
        };
        collectionLabel: {
            attribute: string;
            type: StringConstructor;
        };
        detailLabel: {
            attribute: string;
            type: StringConstructor;
        };
        selection: {
            type: StringConstructor;
        };
    };
    static readonly styles: import("lit").CSSResult[];
    fields: readonly AeliqoFieldOption[];
    predicate: AeliqoFilterPredicate | undefined;
    rows: readonly AeliqoDataRecord[];
    columns: readonly AeliqoDataColumn[];
    identity: readonly string[];
    entity: string;
    selectedKey: string;
    detailRecord: AeliqoDataRecord | undefined;
    detailFields: readonly AeliqoDataColumn[];
    result: ResultRef | undefined;
    scope: AeliqoDataScope | undefined;
    status: AeliqoCompoundStatus;
    message: string;
    title: string;
    filterLabel: string;
    collectionLabel: string;
    detailLabel: string;
    selection: 'none' | 'single' | 'multiple';
    protected render(): import("lit").TemplateResult<1>;
    private rowKey;
    private readonly forwardFilter;
    private readonly forwardSelection;
}

Version

This page documents the Varendo 0.6 component contract.