// @bun
var $=Object.defineProperty;var v=(z)=>z;function D(z,G){this[z]=v.bind(null,G)}var R=(z,G)=>{for(var Y in G)$(z,Y,{get:G[Y],enumerable:!0,configurable:!0,set:D.bind(G,Y)})};var _=(z,G)=>()=>(z&&(G=z(z=0)),G);import{CodeBlock as N}from"@contractspec/lib.design-system";import{HStack as M,VStack as J}from"@contractspec/lib.design-system/layout";import{List as O,ListItem as F}from"@contractspec/lib.design-system/list";import{H1 as U,H2 as Q,H3 as W,P as K,Text as q}from"@contractspec/lib.design-system/typography";import Z from"@contractspec/lib.ui-link";import{ChevronRight as X}from"lucide-react";import{jsx as f,jsxs as w}from"react/jsx-runtime";var b=`import { defineDataView } from '@contractspec/lib.contracts-spec/data-views';
import { ListTransactions } from './list-transactions';

export const TransactionHistory = defineDataView({
  meta: {
    key: 'billing.transactionHistory',
    version: '1.0.0',
    entity: 'transaction',
    title: 'Transaction History',
    description: 'Customer payment history',
    domain: 'billing',
    owners: ['team-billing'],
    tags: ['payments'],
    stability: 'stable',
  },
  source: {
    primary: {
      key: ListTransactions.meta.key,
      version: ListTransactions.meta.version,
    },
  },
  view: {
    kind: 'table',
    executionMode: 'client',
    selection: 'multiple',
    columnVisibility: true,
    columnResizing: true,
    columnPinning: true,
    rowExpansion: {
      fields: ['notes', 'renewalDate', 'lastActivityAt'],
    },
    initialState: {
      pageSize: 4,
      hiddenColumns: ['notes'],
      pinnedColumns: {
        left: ['account'],
      },
      sorting: [{ field: 'arr', desc: true }],
    },
    fields: [
      { key: 'account', label: 'Account', dataPath: 'account', sortable: true },
      { key: 'owner', label: 'Owner', dataPath: 'owner', sortable: true },
      { key: 'status', label: 'Status', dataPath: 'status', sortable: true },
      {
        key: 'amount',
        label: 'Amount',
        dataPath: 'amount',
        sortable: true,
        format: { type: 'currency', currency: 'EUR', rounded: true },
      },
      {
        key: 'renewalDate',
        label: 'Renewal',
        dataPath: 'renewalDate',
        format: { type: 'date', dateStyle: 'medium' },
      },
      {
        key: 'processingTime',
        label: 'Processing time',
        dataPath: 'processingMinutes',
        format: { type: 'duration', unit: 'minute', display: 'digital' },
      },
      {
        key: 'notes',
        label: 'Notes',
        dataPath: 'notes',
        visibility: { minDataDepth: 'detailed' },
      },
    ],
    collection: {
      viewModes: {
        defaultMode: 'table',
        allowedModes: ['list', 'grid', 'table'],
      },
      toolbar: {
        search: true,
        viewMode: true,
        filters: true,
        density: true,
        dataDepth: true,
      },
      pagination: {
        pageSize: 25,
        pageSizeOptions: [10, 25, 50],
      },
      density: 'comfortable',
      dataDepth: 'standard',
      personalization: {
        enabled: true,
        persist: {
          viewMode: true,
          density: true,
          dataDepth: true,
          pageSize: true,
        },
      },
    },
    filters: [
      { key: 'status', label: 'Status', field: 'status', type: 'enum' },
      {
        key: 'amount',
        label: 'Amount',
        field: 'amount',
        type: 'currency',
        valueMode: 'range',
      },
      {
        key: 'renewalDate',
        label: 'Renewal',
        field: 'renewalDate',
        type: 'date',
        valueMode: 'range',
      },
    ],
  },
});`;function B(){return w(J,{className:"space-y-8",children:[w(J,{className:"space-y-4",children:[f(U,{className:"font-bold text-4xl",children:"Display Data with DataViews"}),f(K,{className:"text-lg text-muted-foreground",children:"Define a filterable, sortable transaction history view that works across web and mobile without duplicating UI code."})]}),w(J,{className:"space-y-4",children:[f(Q,{className:"font-bold text-2xl",children:"1. Define the underlying query"}),f(K,{className:"text-muted-foreground",children:"First, create a query operation to fetch the data:"}),f(N,{language:"typescript",filename:"lib/specs/billing/list-transactions.ts",code:`import { defineQuery } from '@contractspec/lib.contracts-spec';

export const ListTransactions = defineQuery({
  meta: {
    key: 'billing.listTransactions',
    version: '1.0.0',
    description: 'Fetch customer transaction history',
  },
  io: {
    input: /* pagination + filters */,
    output: /* array of transactions */,
  },
  policy: { auth: 'user' },
});`})]}),w(J,{className:"space-y-4",children:[f(Q,{className:"font-bold text-2xl",children:"2. Define the DataView spec"}),f(K,{className:"text-muted-foreground",children:"Wrap your query with presentation metadata:"}),f(N,{language:"typescript",filename:"lib/specs/billing/transaction-history.data-view.ts",code:b}),w(K,{className:"text-muted-foreground text-sm",children:["The live version of this pattern is available in the canonical"," ",f(Z,{href:"/docs/examples/data-grid-showcase",className:"text-[color:var(--rust)] underline underline-offset-4",children:f(q,{children:"Data Grid Showcase"})}),"."]})]}),w(J,{className:"space-y-4",children:[f(Q,{className:"font-bold text-2xl",children:"3. Render on the frontend"}),f(K,{className:"text-muted-foreground",children:"Use the runtime renderer in your React or React Native app:"}),f(N,{language:"tsx",filename:"app/dashboard/transactions/page.tsx",code:`'use client';

import { DataViewRenderer } from '@contractspec/lib.design-system';
import { TransactionHistory } from '@/lib/specs/billing/transaction-history.data-view';
import { useQuery } from '@tanstack/react-query';

export function TransactionsPage() {
  const { data, isLoading } = useQuery({
    queryKey: ['transactions'],
    queryFn: () => fetch('/api/ops/billing.listTransactions').then(r => r.json()),
  });

  return (
    <div className="container py-8">
      <h1 className="text-3xl font-bold mb-6">Payment History</h1>
      <DataViewRenderer
        spec={TransactionHistory}
        items={data?.items ?? []}
        loading={isLoading}
        defaultViewMode="table"
        defaultDensity="comfortable"
        defaultDataDepth="standard"
        onFilterChange={(filters) => {
          // refetch with new filters
        }}
      />
    </div>
  );
}`})]}),w(J,{className:"space-y-4",children:[f(Q,{className:"font-bold text-2xl",children:"4. Add personalization"}),f(K,{className:"text-muted-foreground",children:"When the app has a user profile or behavior insights, resolve DataView preferences before rendering. The renderer receives plain props; personalization stays in the app/runtime boundary."}),f(N,{language:"tsx",filename:"app/dashboard/transactions/PersonalizedTransactions.tsx",code:`'use client';

import { DataViewRenderer } from '@contractspec/lib.design-system';
import { resolveDataViewPreferences } from '@contractspec/lib.personalization/data-view-preferences';
import { createBehaviorTracker } from '@contractspec/lib.personalization';

const tracker = createBehaviorTracker({
  store,
  context: { tenantId: tenant.id, userId: user.id },
});

const resolved = resolveDataViewPreferences({
  spec: TransactionHistory,
  preferences: profile.canonical,
  insights,
  record: savedTransactionViewPreference,
});

<DataViewRenderer
  spec={TransactionHistory}
  items={transactions}
  defaultViewMode={resolved.viewMode}
  defaultDensity={resolved.density}
  defaultDataDepth={resolved.dataDepth}
  pagination={{ page, pageSize: resolved.pageSize ?? 25, total }}
  onViewModeChange={(viewMode) =>
    tracker.trackDataViewInteraction({
      dataViewKey: TransactionHistory.meta.key,
      action: 'view_mode_changed',
      viewMode,
    })
  }
  onDataDepthChange={(dataDepth) =>
    tracker.trackDataViewInteraction({
      dataViewKey: TransactionHistory.meta.key,
      action: 'data_depth_changed',
      dataDepth,
    })
  }
/>;`})]}),w(J,{className:"card-subtle space-y-4 p-6",children:[f(W,{className:"font-bold",children:"Why DataViews?"}),w(O,{className:"space-y-2 text-muted-foreground text-sm",children:[f(F,{children:f(q,{children:"Same spec renders on web (React) and mobile (React Native)"})}),f(F,{children:f(q,{children:"Filters, sorting, and pagination handled automatically"})}),f(F,{children:f(q,{children:"Column visibility, pinning, resizing, and row expansion stay contract-driven"})}),f(F,{children:f(q,{children:"List, grid, and table modes can share one collection config with toolbar and pagination defaults"})}),f(F,{children:f(q,{children:"Data depth lets summary screens hide detailed fields without forking the spec"})}),f(F,{children:f(q,{children:"Typed format rules for numbers, percent values, currency, dates, times, datetimes, and durations applied consistently"})}),f(F,{children:f(q,{children:"Personalization helpers can seed preferred view mode, density, data depth, and page size from user preferences or behavior insights"})}),f(F,{children:f(q,{children:"Export to CSV/PDF using the same spec"})}),f(F,{children:f(q,{children:"A/B test different layouts without touching the backend"})})]})]}),w(M,{className:"items-center gap-4 pt-4",children:[w(Z,{href:"/docs/libraries/data-views",className:"btn-primary",children:[f(q,{children:"DataView API Reference"})," ",f(X,{size:16})]}),f(Z,{href:"/docs/specs/workflows",className:"btn-ghost",children:f(q,{children:"Next: Workflows"})})]})]})}export{B as DataViewTutorialPage};
