← Files DataARCHIVED FILE

templates/data-app/base/examples/component-lab/main.jsx

33.8 KB · Oct 3, 2026 · 06:03 UTC

↓ Download file

import React, { useState } from "react";
import { createRoot } from "react-dom/client";

import { DataAppShell } from "../shell.jsx";
import {
  Chart,
  DataComponent,
  Dropdown,
  barChartSpec,
  ExecutiveSummary,
  Filters,
  MetricCardTabs,
  SectionHeader,
  SegmentedControl,
  Switch,
  SortableItem,
  SortableRegion,
  useDataApp,
  useDashboardTabs,
} from "../../src/data-app-public.jsx";
import { snapshot, planToneColors, categoryToneColors } from "./data.js";
import "./component-lab.css";
import { LibraryInventory } from "./Library.jsx";

const planColors = { Enterprise: "var(--chart-1)", Growth: "var(--chart-2)", Starter: "var(--chart-4)" };

const axisChartDefinitions = [
  { type: "horizontalBar", queryId: "category_performance", title: "Horizontal bar", x: "segment", y: "value",
    spec: { sortOrder: "descending", showValues: true, showXAxisLabel: false, showYAxisLabel: false,
      yAxisPosition: "left" } },
  { type: "stackedBar", queryId: "account_composition", title: "Stacked bar", x: "region", y: "accounts",
    series: "plan", spec: { showXAxisLabel: false, showYAxisLabel: false, colors: planToneColors } },
  { type: "stackedBar100", queryId: "account_composition", title: "100% stacked bar", x: "region", y: "accounts",
    series: "plan", spec: { showXAxisLabel: false, showYAxisLabel: false, colors: planToneColors } },
  { type: "horizontalStackedBar", queryId: "account_composition", title: "Horizontal stacked bar",
    x: "region", y: "accounts", series: "plan",
    spec: { showXAxisLabel: false, showYAxisLabel: false, yAxisPosition: "left", colors: planToneColors } },
  { type: "horizontalStackedBar100", queryId: "account_composition", title: "100% horizontal stack",
    x: "region", y: "accounts", series: "plan",
    spec: { showXAxisLabel: false, showYAxisLabel: false, yAxisPosition: "left", colors: planToneColors } },
  { type: "histogram", queryId: "response_distribution", title: "Histogram", x: "team", y: "responseMinutes",
    spec: { showYAxisLabel: false, showValues: true, colors: { responseMinutes: "var(--chart-5)" } } },
];

const axisCharts = axisChartDefinitions.map((definition) => ({
  ...definition,
  id: definition.type.replace(/([a-z])([A-Z])/gu, "$1-$2").toLowerCase(),
  description: `${definition.title} with its standard configuration.`,
  height: 250,
  spec: {
    type: definition.type,
    x: definition.x,
    y: definition.y,
    ...(definition.series ? { series: definition.series } : {}),
    ...definition.spec,
  },
}));

const axislessCharts = [
  { id: "leaderboard", queryId: "category_performance", title: "Leaderboard",
    description: "Compact ranked category comparison.",
    breakdown: ["segment"],
    additionalRows: [
      { segment: "Professional", value: 21 },
      { segment: "Nonprofit", value: 18 },
      { segment: "Agencies", value: 15 },
      { segment: "Developer", value: 12 },
      { segment: "Personal", value: 9 },
    ],
    experimentalBarSpec: { presentation: "rankedList", category: "segment", value: "value",
      sort: "descending", visibleRows: 10,
      style: { color: "color-mix(in srgb, var(--text) 9%, transparent)",
        thickness: 36, radius: 8, gap: 8, textColor: "var(--text)" } } },
  { id: "ranked-list", queryId: "category_performance", title: "Ranked list",
    description: "Expandable ranked category comparison.",
    breakdown: ["segment"],
    experimentalBarSpec: {
      presentation: "groupedList",
      category: "segment",
      value: "value",
      series: [
        { key: "value", label: "This week", color: "var(--chart-1)",
          colors: Object.values(categoryToneColors),
          textColors: ["white", "white", "white", "light-dark(#1a1c1f, #111)", "light-dark(#1a1c1f, #111)"],
        },
        { key: "target", label: "Last week", color: "color-mix(in srgb, var(--text) 10%, transparent)", textColor: "var(--text)" },
      ],
      style: { thickness: 36, radius: 7, gap: 15 },
    } },
  { id: "funnel", queryId: "activation_funnel", title: "Funnel", description: "Ordered activation progression.",
    spec: { type: "funnel", x: "stage", y: "accounts", colors: { accounts: "var(--chart-2)" } } },
].map((entry) => ({ ...entry, height: entry.height ?? 250 }));

const teamCharts = [
  {
    id: "team-delivery-benchmark",
    queryId: "team_delivery_weekly",
    title: "Delivery vs target",
    description: "Completed work by day, with the team target shown as a benchmark line.",
    breakdown: ["day"],
    height: 320,
    experimentalBarSpec: {
      category: "day",
      value: "completed",
      markers: [{ value: 20, label: "Target 20", color: "var(--secondary)" }],
      domain: [0, 30],
      style: { color: "var(--chart-2)", thickness: 22, radius: 5 },
      barCategoryGap: "18%",
    },
  },
  {
    id: "team-rituals-heatmap",
    queryId: "team_rituals",
    title: "Team rituals",
    description: "A weekly check-in map for the routines that keep the team aligned.",
    breakdown: ["day", "ritual"],
    height: 250,
    spec: {
      type: "heatmap",
      x: "day",
      y: "completed",
      series: "ritual",
      showXAxisLabel: false,
      showYAxisLabel: false,
      showLegend: false,
      categoryOrder: ["Mon", "Tue", "Wed", "Thu", "Fri"],
      seriesOrder: ["Standup", "Planning", "Review", "Retro"],
      rowHeight: 40,
      markRadius: 8,
      colorBands: [
        { max: 0.5, color: "color-mix(in srgb, var(--text) 6%, var(--surface))", label: "Missed" },
        { color: "var(--chart-3)", label: "Complete" },
      ],
      cellLabel: { showWhen: 1, text: "✓", color: "var(--surface)", fontSize: 13, fontWeight: 800 },
    },
  },
  {
    id: "team-focus-windows",
    queryId: "team_focus_windows",
    title: "Focus windows",
    description: "Protected focus time for each team across the shared workday.",
    breakdown: ["team"],
    height: 320,
    experimentalBarSpec: {
      orientation: "horizontal",
      category: "team",
      value: "focusHours",
      range: ["beforeFocus", "focusEnd"],
      track: true,
      grid: false,
      xLabel: "Hours into workday",
      domain: [0, 9],
      categoryWidth: 78,
      style: { color: "var(--chart-4)", thickness: 22, radius: 7 },
      rangeLabelField: "focusHoursLabel",
    },
  },
  {
    id: "team-capacity-mix",
    queryId: "team_capacity_mix",
    title: "Capacity mix",
    description: "How each team divides its available time across core work.",
    breakdown: ["team", "workType"],
    height: 250,
    spec: {
      type: "horizontalStackedBar100",
      x: "team",
      y: "share",
      series: "workType",
      colors: {
        "Product work": "var(--chart-1)",
        Reliability: "color-mix(in srgb, var(--chart-1) 76%, var(--surface))",
        Support: "color-mix(in srgb, var(--chart-1) 52%, var(--surface))",
        Planning: "color-mix(in srgb, var(--chart-1) 28%, var(--surface))",
      },
      showXAxisLabel: false,
      showYAxisLabel: false,
      showLegend: true,
      yAxisPosition: "left",
    },
  },
];

const standardBarCharts = [
  ...axisCharts,
  teamCharts.find(({ id }) => id === "team-capacity-mix"),
  axislessCharts.find(({ id }) => id === "funnel"),
].filter(Boolean);

const experimentalCatalogCharts = [
  ...teamCharts.filter(({ experimentalBarSpec }) => experimentalBarSpec),
  ...axislessCharts.filter(({ experimentalBarSpec }) => experimentalBarSpec),
];

const adoptionMetricDefinitions = [
  {
    id: "active-teams",
    title: "Active teams",
    queryId: "weekly_activity",
    field: "activeTeams",
    color: "var(--chart-1)",
    chart: { type: "line", x: "week", y: "activeTeams" },
    comparison: "+5.5%",
    format: (value) => new Intl.NumberFormat().format(value),
  },
  {
    id: "completed-tasks",
    title: "Completed tasks",
    queryId: "weekly_activity",
    field: "completedTasks",
    color: "var(--chart-5)",
    chart: { type: "area", x: "week", y: "completedTasks" },
    comparison: "+5.6%",
    format: (value) => new Intl.NumberFormat().format(value),
  },
  {
    id: "tasks-per-team",
    title: "Tasks per team",
    queryId: "weekly_activity",
    field: "tasksPerTeam",
    color: "var(--chart-2)",
    chart: { type: "bar", x: "week", y: "tasksPerTeam" },
    comparison: "Stable",
    tone: "neutral",
    format: (value) => new Intl.NumberFormat(undefined, {
      minimumFractionDigits: 2,
      maximumFractionDigits: 2,
    }).format(value),
  },
  {
    id: "team-mix",
    title: "Team mix",
    queryId: "weekly_composition",
    field: "activeTeams",
    color: "var(--chart-3)",
    chart: { type: "stackedArea", x: "week", y: "activeTeams", series: "plan", colors: planColors },
    comparison: "+6.1%",
    summarize: (rows) => {
      const lastWeek = rows.at(-1)?.week;
      return rows.filter(({ week }) => week === lastWeek)
        .reduce((total, { activeTeams }) => total + activeTeams, 0);
    },
    format: (value) => new Intl.NumberFormat().format(value),
  },
  {
    id: "segment-score",
    title: "Top segment score",
    queryId: "category_performance",
    field: "value",
    color: "var(--chart-4)",
    chart: { type: "horizontalBar", x: "segment", y: "value", sortOrder: "descending", showValues: true },
    comparison: "Above target",
    summarize: (rows) => Math.max(...rows.map(({ value }) => value)),
    format: (value) => new Intl.NumberFormat().format(value),
  },
];

const formatExperimentalCurrency = (value) => new Intl.NumberFormat("en-US", {
  style: "currency",
  currency: "USD",
  maximumFractionDigits: 0,
}).format(value);

const goalProgressRows = [
  { goal: "Sleep", value: 7.7, target: 8, unit: "hours", color: "var(--chart-2)" },
  { goal: "Steps", value: 10000, target: 10000, unit: "steps", color: "var(--chart-3)" },
  { goal: "Exercise", value: 30, target: 30, unit: "minutes", color: "var(--chart-7)" },
];

const fleetCashRows = [
  242000, 251400, 250800, 242600, 241900, 256300, 259800,
  254700, 252900, 260400, 269700, 293700, 285600,
].map((balance, index) => ({
  week: `W${index + 1}`,
  balance,
  reserveBase: Math.min(balance, 250000),
  reserveOverflow: Math.max(0, balance - 250000),
}));

const fleetCostRows = [
  { category: "Driver pay", amount: 54900, color: "color-mix(in srgb, var(--text) 10%, transparent)", textColor: "var(--secondary)" },
  { category: "Fuel", amount: 43700, color: "var(--negative)", textColor: "white" },
  { category: "Vehicle maintenance", amount: 22500, color: "color-mix(in srgb, var(--text) 10%, transparent)", textColor: "var(--secondary)" },
  { category: "Warehousing", amount: 17800, color: "color-mix(in srgb, var(--text) 10%, transparent)", textColor: "var(--secondary)" },
  { category: "Insurance", amount: 12900, color: "color-mix(in srgb, var(--text) 10%, transparent)", textColor: "var(--secondary)" },
  { category: "Software and systems", amount: 9700, color: "color-mix(in srgb, var(--text) 10%, transparent)", textColor: "var(--secondary)" },
];

const pipelineComparisonRows = [
  { period: "This quarter", discovery: 196000, proposal: 402000, commit: 358000, closedWon: 100000 },
  { period: "Last quarter", discovery: 238000, proposal: 352000, commit: 318000, closedWon: 86000 },
];

const pipelineComparisonSeries = [
  { key: "discovery", label: "Discovery", color: "#B5DAF6", comparisonColor: "#DCE1E6" },
  { key: "proposal", label: "Proposal", color: "#75AFE1", comparisonColor: "#C8CDD3" },
  { key: "commit", label: "Commit", color: "#3475BD", comparisonColor: "#AEB5BE" },
  { key: "closedWon", label: "Closed Won", color: "#91CFAB", comparisonColor: "#8E98A4" },
];

const dayComparisonRows = [
  { day: "Saturday", steps: 3830, color: "var(--chart-4)", textColor: "white" },
  { day: "Sunday", steps: 6654, color: "color-mix(in srgb, var(--text) 9%, transparent)", textColor: "var(--text)" },
];

const spendRows = [
  { category: "Rent and utilities", amount: 678, total: 1724, color: "#075F2B" },
  { category: "Groceries", amount: 342, total: 1724, color: "#079447" },
  { category: "Subscriptions", amount: 230, total: 1724, color: "#4BCB82" },
  { category: "Medical", amount: 176, total: 1724, color: "#8EDCB0" },
  { category: "Miscellaneous", amount: 144, total: 1724, color: "#91C5F4" },
  { category: "Transit", amount: 91, total: 1724, color: "#4CA4E8" },
  { category: "Saving", amount: 63, total: 1724, color: "#167DC1" },
];

const spendCompositionRow = {
  period: "January",
  rent: 678,
  groceries: 342,
  subscriptions: 230,
  medical: 176,
  miscellaneous: 144,
  transit: 91,
  saving: 63,
};

const spendSeries = [
  { key: "rent", label: "Rent and utilities", color: "#075F2B" },
  { key: "groceries", label: "Groceries", color: "#079447" },
  { key: "subscriptions", label: "Subscriptions", color: "#4BCB82" },
  { key: "medical", label: "Medical", color: "#8EDCB0" },
  { key: "miscellaneous", label: "Miscellaneous", color: "#91C5F4" },
  { key: "transit", label: "Transit", color: "#4CA4E8" },
  { key: "saving", label: "Saving", color: "#167DC1" },
];

const portfolioRows = [
  { category: "Stocks", amount: 45320, total: 100937, color: "#075F2B" },
  { category: "ETFs", amount: 24225, total: 100937, color: "#079447" },
  { category: "Bonds", amount: 18500, total: 100937, color: "#4BCB82" },
  { category: "Crypto", amount: 7893, total: 100937, color: "#8EDCB0" },
  { category: "Cash", amount: 4999, total: 100937, color: "#91C5F4" },
];

const portfolioPieSpec = {
  type: "pie",
  x: "category",
  y: "amount",
  currency: "USD",
  valueDecimals: 0,
  showLegend: false,
  colors: Object.fromEntries(portfolioRows.map(({ category, color }) => [category, color])),
};

function ExperimentalBarExamples({ catalog }) {
  const [pipelineLabelsRight, setPipelineLabelsRight] = useState(false);
  const progressSpec = {
    presentation: "progress",
    category: "goal",
    value: "value",
    track: { max: "target" },
    unitField: "unit",
    format: { maximumFractionDigits: 1 },
    style: { colorField: "color", thickness: 3, gap: 16, fontSize: 14 },
  };
  const comparisonSpec = {
    presentation: "comparison",
    category: "day",
    value: "steps",
    labels: { position: "above", suffix: " steps" },
    style: { colorField: "color", textColorField: "textColor", thickness: 32, radius: 6, gap: 18, fontSize: 14 },
    format: { maximumFractionDigits: 0 },
  };
  const categoryProgressSpec = {
    presentation: "progress",
    category: "category",
    value: "amount",
    track: { max: "total" },
    labels: { value: "formatted" },
    style: { colorField: "color", thickness: 5, gap: 15, fontSize: 14 },
    format: { style: "currency", currency: "USD", maximumFractionDigits: 0 },
  };

  return <section className="experimental-bar-examples" aria-labelledby="experimental-bar-examples-title">
    <SectionHeader id="experimental-bar-examples-title" as="h2"
      title="Bar examples in context" description="Compositions and styling variations built with the shared Chart API." />
    <div className="experimental-bar-examples-grid">
      <DataComponent id="experimental-daily-goals" queryId="experimental_bar_examples" kind="custom" title="Today’s goals"
        description="Compact goal completion tracks." displayRows={goalProgressRows} sourceRows={goalProgressRows}
        variant="card" padding="spacious">
        <Chart rows={goalProgressRows} spec={barChartSpec(progressSpec)} />
      </DataComponent>
      <DataComponent id="experimental-day-comparison" queryId="experimental_bar_examples" kind="custom" title="Steps"
        description="You took 2,824 more steps yesterday than the day before."
        displayRows={dayComparisonRows} sourceRows={dayComparisonRows} variant="card" padding="spacious">
        <Chart rows={dayComparisonRows} spec={barChartSpec(comparisonSpec)} />
      </DataComponent>
      <DataComponent id="experimental-spend-composition" queryId="experimental_bar_examples" kind="custom" title="Spend by category"
        description="January spending shown as a total composition and category-level progress."
        displayRows={spendRows} sourceRows={spendRows} variant="card" padding="spacious">
        <div className="experimental-bar-example-summary"><span>January</span><strong>{formatExperimentalCurrency(spendRows.reduce((sum, row) => sum + row.amount, 0))}</strong></div>
        <Chart rows={[spendCompositionRow]} spec={barChartSpec({
          presentation: "segmented",
          category: "period",
          series: spendSeries,
          style: { thickness: 44, radius: 10, segmentGap: 3 },
        })} />
        <Chart rows={spendRows} spec={barChartSpec(categoryProgressSpec)} />
      </DataComponent>
      <DataComponent id="experimental-portfolio-distribution" queryId="experimental_bar_examples" kind="custom" title="Portfolio distribution"
        description="Five holdings across three accounts." displayRows={portfolioRows} sourceRows={portfolioRows}
        variant="card" padding="spacious">
        <div className="experimental-bar-example-summary"><span>Current allocation</span><strong>{formatExperimentalCurrency(portfolioRows.reduce((sum, row) => sum + row.amount, 0))}</strong></div>
        <div className="experimental-portfolio-layout">
          <Chart spec={portfolioPieSpec} rows={portfolioRows} height={260} />
          <Chart rows={portfolioRows} spec={barChartSpec(categoryProgressSpec)} />
        </div>
      </DataComponent>
      <DataComponent id="experimental-fleet-cash" queryId="experimental_bar_examples" kind="custom"
        title="Fleet cash balance" description="Weekly cash balance compared with the operating reserve target."
        displayRows={fleetCashRows} sourceRows={fleetCashRows} variant="card" padding="spacious">
        <div className="experimental-bar-example-summary">
          <span>Target {formatExperimentalCurrency(250000)}</span>
          <strong>{formatExperimentalCurrency(fleetCashRows.at(-1).balance)}</strong>
        </div>
        <Chart rows={fleetCashRows} height={220} spec={barChartSpec({
          category: "week",
          value: "balance",
          series: [
            { key: "reserveBase", label: "Reserve", color: "color-mix(in srgb, var(--text) 13%, transparent)", stackId: "cash" },
            { key: "reserveOverflow", label: "Over target", color: "var(--negative)", stackId: "cash" },
          ],
          tooltipFields: [
            { key: "balance", label: "Value", color: "color-mix(in srgb, var(--text) 13%, transparent)" },
            { key: "reserveOverflow", label: "Over target", color: "var(--negative)" },
          ],
          markers: [{ value: 250000, label: "Target", color: "var(--secondary)" }],
          axes: { category: true, value: false },
          grid: false,
          domain: [0, 320000],
          style: { thickness: 24, radius: 3 },
          barCategoryGap: "12%",
          format: { style: "currency", currency: "USD", maximumFractionDigits: 0 },
        })} />
      </DataComponent>
      <DataComponent id="experimental-fleet-costs" queryId="experimental_bar_examples" kind="custom"
        title="Costs by category" description="Latest weekly fleet operating costs by category."
        displayRows={fleetCostRows} sourceRows={fleetCostRows} variant="card" padding="spacious">
        <p className="experimental-fleet-cost-insight">Fuel costs have risen <strong>2.5×</strong> this week</p>
        <Chart rows={fleetCostRows} spec={barChartSpec({
          presentation: "rankedList",
          category: "category",
          value: "amount",
          style: { colorField: "color", textColorField: "textColor", thickness: 28, radius: 5, gap: 12 },
          format: { style: "currency", currency: "USD", notation: "compact", minimumFractionDigits: 1, maximumFractionDigits: 1 },
        })} />
      </DataComponent>
      <DataComponent id="experimental-pipeline-comparison" queryId="experimental_bar_examples" kind="custom"
        title="Pipeline by stage" description="This quarter compared with last quarter across each pipeline stage."
        displayRows={pipelineComparisonRows} sourceRows={pipelineComparisonRows} variant="card" padding="spacious"
        className="experimental-bar-example--wide">
        <div className="experimental-pipeline-controls">
          <Switch label="Right-align labels" checked={pipelineLabelsRight} onChange={setPipelineLabelsRight} />
        </div>
        <Chart rows={pipelineComparisonRows} spec={barChartSpec({
          presentation: "segmented",
          category: "period",
          series: pipelineComparisonSeries,
          comparison: true,
          annotations: "auto",
          labels: { align: pipelineLabelsRight ? "right" : "left" },
          style: { thickness: 36, radius: 7, roundedSegments: true, segmentGap: 2, fontSize: 14 },
          format: { style: "currency", currency: "USD", notation: "compact", maximumFractionDigits: 0 },
        })} />
      </DataComponent>
    </div>
    <SectionHeader id="experimental-bar-catalog-title" as="h3"
      title="Additional bar variations" description="Reusable bar layouts built with Chart." />
    {catalog}
  </section>;
}

function DisclosurePlayground() {
  return <section className="component-lab-disclosure-playground"
    aria-label="Executive summary component">
    <ExecutiveSummary preview="307 active teams · 659 completed tasks · 2.15 tasks per team">
      <p><strong>Product adoption continued to grow.</strong> Active teams and completed tasks both increased during the selected period.</p>
      <p><strong>Task volume remains healthy.</strong> Teams completed an average of 2.15 tasks each.</p>
    </ExecutiveSummary>
  </section>;
}

const feedbackFlowColumns = [
  { field: "feedbackSource", label: "Feedback sources" },
  { field: "theme", label: "Themes" },
  { field: "feature", label: "Features" },
  { field: "roadmap", label: "Priority" },
];
const feedbackFlowStages = feedbackFlowColumns.map(({ field }) => field);
const feedbackFlowPriorityColors = {
  Prioritized: "var(--chart-1)",
  Backlog: "var(--secondary)",
  Unplanned: "var(--negative)",
};
const feedbackFlowPriorityValues = Object.keys(feedbackFlowPriorityColors);
const feedbackFlowChart = {
  type: "sankey",
  x: "feedbackSource",
  y: "mentions",
  stages: feedbackFlowStages,
  showLegend: false,
  showValues: true,
  labelMaxLength: 14,
  sankeyNodeWidth: 18,
  sankeyLabelFontSize: 13,
  sankeyValueFontSize: 11,
  colors: {
    feedbackSource: "var(--chart-2)",
    theme: "var(--chart-4)",
    feature: "var(--chart-3)",
    ...feedbackFlowPriorityColors,
  },
};

function PriorityFilter({ selected, onChange }) {
  return <div className="component-lab-priority-picker"><SegmentedControl size="default" className="component-lab-priority-filter"
    ariaLabel="Priority filters" selectionMode="multiple" value={selected.length ? selected : ["all"]}
    onChange={values => onChange(values.includes("all") && selected.length ? [] : values.filter(value => value !== "all"))}
    options={[{ value: "all", label: "All priorities" }, ...feedbackFlowPriorityValues.map((priority) => ({
      value: priority,
      ariaLabel: priority,
      label: <><span className="component-lab-priority-filter-dot" aria-hidden="true"
        style={{ "--priority-color": feedbackFlowPriorityColors[priority] }} /><span className="data-segmented-control-label">{priority}</span></>,
    }))]} /><div className="component-lab-priority-dropdown"><Dropdown label="Priority" showLabel multiple value={selected}
      choices={["all", ...feedbackFlowPriorityValues]} onChange={onChange} /></div></div>;
}

function LabExamples({ view: activeTabId }) {
  const [selectedAdoptionMetric, setSelectedAdoptionMetric] = useState("active-teams");
  const [metricTabSize, setMetricTabSize] = useState("medium");
  const [metricTabOrientation, setMetricTabOrientation] = useState("horizontal");
  const [feedbackFlowFilters, setFeedbackFlowFilters] = useState(() => Object.fromEntries(
    feedbackFlowColumns.map(({ field }) => [field,
    []]),
  ));
  const {
    snapshot: dashboard,
    queries,
    filters,
    setFilter,
    chartOverrides,
    chartProps,
    reviewedRows,
    visible,
  } = useDataApp();

  const weeklyActivity = reviewedRows("weekly_activity", ["week"]);
  const weeklyComposition = reviewedRows("weekly_composition", ["week", "plan"]);
  const categoryPerformance = reviewedRows("category_performance", ["segment"]);
  const feedbackFlowRows = reviewedRows("feedback_roadmap", feedbackFlowStages);
  const matchesFeedbackFlowFilters = (row, selections, skippedField) => feedbackFlowColumns.every(({ field }) => {
    if (field === skippedField) return true;
    const selected = selections[field] ?? [];
    return !selected.length || selected.includes(row[field]);
  });
  const feedbackFlowChoices = Object.fromEntries(feedbackFlowColumns.map(({ field }) => [
    field,
    [...new Set(feedbackFlowRows
      .filter((row) => matchesFeedbackFlowFilters(row, feedbackFlowFilters, field))
      .map((row) => row[field])
      .filter((value) => value != null && value !== ""))],
  ]));
  const filteredFeedbackFlowRows = feedbackFlowRows.filter((row) =>
    matchesFeedbackFlowFilters(row, feedbackFlowFilters));
  const feedbackFlowHasFeatures = !filteredFeedbackFlowRows.length
    || filteredFeedbackFlowRows.some((row) => row.feature != null && row.feature !== "");
  const changeFeedbackFlowFilter = (changedField, values) => {
    setFeedbackFlowFilters((current) => {
      const next = { ...current, [changedField]: values };
      if (changedField === "roadmap") return next;
      for (let pass = 0; pass < feedbackFlowColumns.length; pass += 1) {
        let changed = false;
        for (const { field } of feedbackFlowColumns) {
          if (field === changedField || field === "roadmap" || !next[field]?.length) continue;
          const available = new Set(feedbackFlowRows
            .filter((row) => matchesFeedbackFlowFilters(row, next, field))
            .map((row) => row[field])
            .filter((value) => value != null && value !== ""));
          const retained = next[field].filter((value) => available.has(value));
          if (retained.length !== next[field].length) {
            next[field] = retained;
            changed = true;
          }
        }
        if (!changed) break;
      }
      return next;
    });
  };
  const metricRows = {
    weekly_activity: weeklyActivity,
    weekly_composition: weeklyComposition,
    category_performance: categoryPerformance,
  };
  const adoptionMetrics = adoptionMetricDefinitions.map((definition) => {
    const rows = metricRows[definition.queryId] ?? [];
    const current = definition.summarize?.(rows) ?? rows.at(-1)?.[definition.field];
    return {
      ...definition,
      rows,
      trendValues: rows.slice(-6).map((row) => row[definition.field]).filter(Number.isFinite),
      value: Number.isFinite(current) ? definition.format(current) : "—",
    };
  });
  const catalogById = new Map((queries.chart_catalog?.rows ?? []).map((row) => [row.chartId, row]));
  const filterCharts = (entries) => entries.filter((entry) => {
    const catalogEntry = catalogById.get(entry.id);
    if (!catalogEntry) return true;
    return (dashboard.filters ?? []).every(({ id }) => {
      const selected = filters[id] ?? "all";
      return selected === "all" || catalogEntry[id] === selected;
    });
  });
  const filteredStandardBarCharts = filterCharts(standardBarCharts);
  const filteredExperimentalCharts = filterCharts(experimentalCatalogCharts);

  const renderChart = (entry) => {
    if (!visible(entry.id)) return null;
    const breakdown = entry.breakdown ?? [entry.spec?.x, entry.spec?.series, ...(entry.spec?.stages ?? [])].filter(Boolean);
    const rows = [...reviewedRows(entry.queryId, breakdown), ...(entry.additionalRows ?? [])];
    if (entry.experimentalBarSpec) {
      const chart = chartOverrides[entry.id] ?? barChartSpec(entry.experimentalBarSpec);
      return <SortableItem key={entry.id} id={entry.id} label={entry.title} kind="chart"
        className={entry.className}>
        <DataComponent id={entry.id} queryId={entry.queryId} kind="chart" chart={chart}
          title={entry.title} description={entry.description} displayRows={rows} sourceRows={rows}
          variant="card" padding="spacious">
          <Chart rows={rows} spec={chart} height={entry.height} {...chartProps(entry.id)} />
        </DataComponent>
      </SortableItem>;
    }
    const reviewedChart = chartOverrides[entry.id] ?? entry.spec;
    const chart = { ...reviewedChart, yAxisPosition: reviewedChart.yAxisPosition ?? "right" };
    return <SortableItem key={entry.id} id={entry.id} label={entry.title} kind="chart"
      className={entry.className}>
      <DataComponent id={entry.id} queryId={entry.queryId} kind="chart" chart={chart}
        title={entry.title} description={entry.description} displayRows={rows} sourceRows={rows}
        variant="card" padding="spacious">
        <Chart spec={chart} rows={rows} height={entry.height} {...chartProps(entry.id)} />
      </DataComponent>
    </SortableItem>;
  };

  return <div className="lab-composed-examples">
    {activeTabId === "overview" && <SectionHeader id="component-lab-compositions" as="h2" title="Composed examples" filters={<>
      <SegmentedControl ariaLabel="Metric tab density" value={metricTabSize}
        options={[
          { value: "small", label: "Compact" },
          { value: "medium", label: "Comfortable" },
          { value: "large", label: "Spacious" },
        ]} onChange={setMetricTabSize} />
      <SegmentedControl ariaLabel="Metric tab orientation" value={metricTabOrientation}
        options={[
          { value: "horizontal", label: "Horizontal" },
          { value: "vertical", label: "Vertical" },
        ]} onChange={setMetricTabOrientation} />
    </>} />}
    {activeTabId === "overview" && <>
      <DisclosurePlayground />
      <MetricCardTabs
        size={metricTabSize} orientation={metricTabOrientation}
        ariaLabel="Product adoption metric" items={adoptionMetrics}
        selectedId={selectedAdoptionMetric} onChange={setSelectedAdoptionMetric}>
        {({ item }) => {
          const chart = {
            ...item.chart,
            showLegend: false,
            showXAxisLabel: false,
            showYAxisLabel: false,
            colors: item.chart.colors ?? { [item.field]: item.color },
          };
          const componentId = `adoption-metric-${item.id}`;
          return <DataComponent id={componentId} queryId={item.queryId} kind="chart"
            chart={chart} title={item.title}
            description={`${item.title} across the reviewed data.`}
            displayRows={item.rows} sourceRows={item.rows} variant="plain">
            <Chart spec={chart} rows={item.rows} height={280}
              {...chartProps(componentId)} />
          </DataComponent>;
        }}
      </MetricCardTabs>
      <DataComponent id="feedback-roadmap-flow" queryId="feedback_roadmap" kind="chart"
      chart={feedbackFlowChart} title="From feedback to roadmap"
      description="Feedback sources flow into shared themes, then features, and finally priority. Unplanned feedback skips the feature column instead of inventing one."
      displayRows={filteredFeedbackFlowRows} sourceRows={filteredFeedbackFlowRows}
      className="component-lab-feedback-flow" variant="card" padding="spacious">
      <div className="component-lab-feedback-flow-filters" role="group" aria-label="Feedback flow filters"
        data-has-features={feedbackFlowHasFeatures}>
        {feedbackFlowColumns.slice(0, -1).map(({ field, label }) => <div
          className="component-lab-feedback-flow-filter" data-flow-column={field} key={field}>
          <Dropdown searchable multiple showLabel label={label} value={feedbackFlowFilters[field]}
            choices={["all", ...feedbackFlowChoices[field]]}
            onChange={(values) => changeFeedbackFlowFilter(field, values)} />
        </div>)}
        <PriorityFilter selected={feedbackFlowFilters.roadmap}
          onChange={(priorities) => changeFeedbackFlowFilter("roadmap", priorities)} />
      </div>
      <Chart spec={feedbackFlowChart} rows={filteredFeedbackFlowRows}
        height="clamp(560px, calc(100dvh - 220px), 900px)"
        {...chartProps("feedback-roadmap-flow")} />
      </DataComponent>
    </>}
    {activeTabId === "bar-experiments" && <>
      <Filters filters={dashboard.filters ?? []} queries={queries} values={filters}
        onChange={setFilter} ariaLabel="Bar chart filters" />
      <section className="component-lab-chart-section" aria-labelledby="standard-bar-charts-title">
        <SectionHeader id="standard-bar-charts-title" as="h2" title="Standard bar charts"
          description="Established ChartRenderer bar, histogram, stacked, ranked, and funnel layouts." />
        <SortableRegion id="component-lab:standard-bars" label="Standard bar charts" variant="freeform"
          className="component-lab-grid">
          {filteredStandardBarCharts.map(renderChart)}
        </SortableRegion>
        {!filteredStandardBarCharts.length && <p className="lab-catalog-empty">No standard charts match these filters. <button type="button"
          onClick={() => { setFilter("family", "all"); setFilter("chartType", "all"); }}>Clear catalog filters</button></p>}
      </section>
      <ExperimentalBarExamples catalog={filteredExperimentalCharts.length ?
        <SortableRegion id="component-lab:experimental-bars" label="Experimental bar charts" variant="freeform"
          className="component-lab-grid">
          {filteredExperimentalCharts.map(renderChart)}
        </SortableRegion> : <p className="lab-catalog-empty">No experimental charts match these filters. <button type="button"
          onClick={() => { setFilter("family", "all"); setFilter("chartType", "all"); }}>Clear catalog filters</button></p>
      } />
    </>}
  </div>;
}

export function ComponentLab() {
  useDashboardTabs([
    { id: "inventory", label: "Inventory", aliases: ["overview", "bar-experiments"], previousLabels: ["Overview", "Bar chart experiments"] },
  ]);
  return <article className="page component-lab-page" data-dashboard-layout="full-width">
    <LibraryInventory
      barExamples={<LabExamples view="bar-experiments" />}
      composedExamples={<LabExamples view="overview" />} />
  </article>;
}

createRoot(document.getElementById("root")).render(
  <React.StrictMode>
    <DataAppShell snapshot={snapshot} hosted={false}><ComponentLab /></DataAppShell>
  </React.StrictMode>,
);

SHA-256: 70320f93a05fce230c7df375d9b195d96d41c31e6e5a27ca2049669e77878c0b