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

export const AccountsDataView = defineDataView({
  meta: {
    key: 'crm.accounts',
    version: '1.0.0',
    title: 'Accounts',
    description: 'Customer account workspace',
    domain: 'crm',
    entity: 'account',
    owners: ['@crm'],
    tags: ['crm', 'accounts'],
    stability: 'stable',
  },
  source: {
    primary: { key: 'crm.accounts.list', version: '1.0.0' },
  },
  view: {
    kind: 'table',
    fields: [
      { key: 'name', label: 'Name', dataPath: 'name', sortable: true },
      { key: 'owner', label: 'Owner', dataPath: 'owner' },
      { key: 'arr', label: 'ARR', dataPath: 'arr', format: { type: 'currency', currency: 'EUR' } },
      {
        key: 'internalNotes',
        label: 'Internal notes',
        dataPath: 'internalNotes',
        visibility: { minDataDepth: 'detailed' },
      },
    ],
    columns: [
      { field: 'name' },
      { field: 'owner' },
      { field: 'arr' },
      { field: 'internalNotes' },
    ],
    collection: {
      viewModes: {
        defaultMode: 'table',
        allowedModes: ['list', 'grid', 'table'],
      },
      pagination: {
        pageSize: 25,
        pageSizeOptions: [10, 25, 50],
      },
      toolbar: {
        search: true,
        viewMode: true,
        filters: true,
        density: true,
        dataDepth: true,
      },
      density: 'comfortable',
      dataDepth: 'standard',
      personalization: {
        enabled: true,
        persist: {
          viewMode: true,
          density: true,
          dataDepth: true,
          pageSize: true,
        },
      },
    },
  },
});`,D=`import { DataViewRenderer } from '@contractspec/lib.design-system';
import { resolveDataViewPreferences } from '@contractspec/lib.personalization/data-view-preferences';

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

<DataViewRenderer
  spec={AccountsDataView}
  items={accounts}
  defaultViewMode={resolved.viewMode}
  defaultDensity={resolved.density}
  defaultDataDepth={resolved.dataDepth}
  pagination={{
    page,
    pageSize: resolved.pageSize ?? 25,
    total,
  }}
  onViewModeChange={(viewMode) => {
    tracker.trackDataViewInteraction({
      dataViewKey: AccountsDataView.meta.key,
      dataViewVersion: AccountsDataView.meta.version,
      action: 'view_mode_changed',
      viewMode,
    });
  }}
  onDensityChange={(density) => {
    tracker.trackDataViewInteraction({
      dataViewKey: AccountsDataView.meta.key,
      action: 'density_changed',
      density,
    });
  }}
  onDataDepthChange={(dataDepth) => {
    tracker.trackDataViewInteraction({
      dataViewKey: AccountsDataView.meta.key,
      action: 'data_depth_changed',
      dataDepth,
    });
  }}
/>;
`,N=`Implement a production DataView for <entity>.

Requirements:
- Define one canonical DataViewSpec with kind 'table', collection viewModes for list/grid/table, pagination defaults, toolbar search/filter/view mode/density/dataDepth controls, and personalization persist hints.
- Mark fields that should only appear in richer experiences with visibility.minDataDepth.
- Render it with DataViewRenderer using plain props from resolveDataViewPreferences.
- Track user interactions with trackDataViewInteraction for view mode, density, data depth, search, filters, sorting, and pagination.
- Keep @contractspec/lib.design-system independent from @contractspec/lib.personalization.
- Add focused tests for default resolution, invalid-mode fallback, data-depth projection, and behavior-derived preferred view mode.`;function l(){return w(Q,{className:"space-y-8",children:[w(Q,{className:"space-y-4",children:[f(u,{className:"font-bold text-4xl",children:"DataViews Runtime Library"}),w(Y,{className:"text-lg text-muted-foreground",children:["The ",f(q,{children:"@contractspec/lib.contracts-spec/data-views"})," and"," ",f(q,{children:"@contractspec/lib.design-system"})," libraries provide the runtime logic and UI components to render DataViews in your application."]})]}),w(Q,{className:"space-y-4",children:[f(U,{className:"font-bold text-2xl",children:"Installation"}),f(X,{package:["@contractspec/lib.contracts-spec","@contractspec/lib.design-system"]})]}),w(Q,{className:"space-y-4",children:[f(U,{className:"font-bold text-2xl",children:"DataViewRenderer"}),f(Y,{className:"text-muted-foreground",children:"The primary component for rendering any DataView. It automatically selects the correct layout (List, Table, Grid, Detail) based on the spec."}),f($,{language:"tsx",code:`import { DataViewRenderer } from '@contractspec/lib.design-system';
import { MyUserList } from './specs/users.data-view';

export function UserPage() {
  return (
    <DataViewRenderer
      spec={MyUserList}
      items={users}
      pagination={{ page: 1, pageSize: 20, total: 100 }}
      onPageChange={(page) => fetchPage(page)}
    />
  );
}`}),f(y,{className:"font-semibold text-xl",children:"Props"}),w(h,{className:"list-disc space-y-2 pl-6 text-muted-foreground",children:[f(J,{children:w(z,{children:[f(q,{children:"spec"}),": The DataViewSpec definition."]})}),f(J,{children:w(z,{children:[f(q,{children:"items"}),": Array of data items to render."]})}),f(J,{children:w(z,{children:[f(q,{children:"filters"}),": Current filter state object."]})}),f(J,{children:w(z,{children:[f(q,{children:"onFilterChange"}),": Callback when typed filters change. Renderers emit ",f(q,{children:"DataViewFilterValue"})," objects for numeric, percent, currency, temporal, duration, and boolean filters."]})}),f(J,{children:w(z,{children:[f(q,{children:"pagination"}),": Object with ",f(q,{children:"page"}),","," ",f(q,{children:"pageSize"}),", ",f(q,{children:"total"}),"."]})}),f(J,{children:w(z,{children:[f(q,{children:"onPageChange"}),": Callback when page changes."]})}),f(J,{children:w(z,{children:[f(q,{children:"viewMode"})," / ",f(q,{children:"defaultViewMode"}),": Controlled or initial collection mode for specs that allow ",f(q,{children:"list"}),","," ",f(q,{children:"grid"}),", or ",f(q,{children:"table"})," projections through"," ",f(q,{children:"view.collection.viewModes"}),"."]})}),f(J,{children:w(z,{children:[f(q,{children:"density"})," / ",f(q,{children:"defaultDensity"}),": Controlled or initial density for collection renderers. Host apps can seed this from ",f(q,{children:"@contractspec/lib.personalization"})," while specs can declare ",f(q,{children:"view.collection.density"})," and table"," ",f(q,{children:"view.density"})," defaults."]})}),f(J,{children:w(z,{children:[f(q,{children:"dataDepth"})," / ",f(q,{children:"defaultDataDepth"}),": Controlled or initial summary/standard/detailed/exhaustive projection. Fields can declare ",f(q,{children:"visibility.minDataDepth"}),", and collection specs can opt into ",f(q,{children:"view.collection.personalization"})," ","persistence hints."]})})]})]}),w(Q,{className:"space-y-4",children:[f(U,{className:"font-bold text-2xl",children:"Collection Defaults And Data Depth"}),w(Y,{className:"text-muted-foreground",children:["Use one authored ",f(q,{children:"DataViewSpec"})," for list, grid, and table experiences. ",f(q,{children:"view.collection"})," declares allowed modes, toolbar controls, pagination defaults, density, data depth, and persistence hints. ",f(q,{children:"visibility.minDataDepth"})," lets a field appear only when the renderer is in a detailed or exhaustive mode."]}),f($,{language:"typescript",code:p})]}),w(Q,{className:"space-y-4",children:[f(U,{className:"font-bold text-2xl",children:"Personalization Bridge"}),w(Y,{className:"text-muted-foreground",children:["Resolve user preferences in the host app, then pass ordinary renderer props into ",f(q,{children:"DataViewRenderer"}),". The bridge helper lives in"," ",f(q,{children:"@contractspec/lib.personalization"}),", so the design-system renderer stays portable for apps that do not use personalization. See the"," ",f(G,{href:"/docs/libraries/personalization",className:"text-[color:var(--rust)] underline underline-offset-4",children:f(z,{children:"personalization library guide"})})," ","for the behavior tracker, analyzer, and DataView preference resolver."]}),f($,{language:"tsx",code:D})]}),w(Q,{className:"space-y-4",children:[f(U,{className:"font-bold text-2xl",children:"Agent Prompt"}),f(Y,{className:"text-muted-foreground",children:"Use this prompt when asking an implementation agent to add a preference-aware collection DataView without breaking package boundaries."}),f($,{language:"markdown",code:N})]}),w(Q,{className:"space-y-4",children:[f(U,{className:"font-bold text-2xl",children:"Query Generation"}),w(Y,{className:"text-muted-foreground",children:["The ",f(q,{children:"DataViewQueryGenerator"})," utility helps translate DataView parameters (filters, sorting, pagination) into query arguments for your backend."]}),f($,{language:"typescript",code:`import { DataViewQueryGenerator } from '@contractspec/lib.contracts-spec/data-views/query-generator';

const generator = new DataViewQueryGenerator(MyUserList);
const params = {
  pagination: { page: 1, pageSize: 20 },
  filters: {
    role: { kind: 'single', value: 'admin' },
    revenue: { kind: 'range', from: 1000, to: 5000 },
    lastSeenAt: { kind: 'single', value: '2026-04-28T08:30:00Z' }
  }
};

const errors = generator.validateParams(params);
const query = generator.generate(params);

// query.input contains skip/take plus the typed filter payloads.`})]}),w(g,{className:"items-center gap-4 pt-4",children:[f(G,{href:"/docs/libraries",className:"btn-ghost",children:f(z,{children:"Back to Libraries"})}),w(G,{href:"/docs/libraries/data-backend",className:"btn-primary",children:[f(z,{children:"Next: Data & Backend"})," ",f(M,{size:16})]})]})]})}export{l as LibrariesDataViewsPage};
