@contractspec/bundle.library 3.9.8 → 3.9.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +222 -214
- package/CHANGELOG.md +52 -0
- package/dist/components/docs/DocsIndexPage.js +2 -2
- package/dist/components/docs/docsManifest.js +1 -1
- package/dist/components/docs/getting-started/DataViewTutorialPage.js +81 -6
- package/dist/components/docs/getting-started/index.js +94 -19
- package/dist/components/docs/guides/GuideDataExchangeImportTemplatesPage.content.d.ts +6 -0
- package/dist/components/docs/guides/GuideDataExchangeImportTemplatesPage.content.js +176 -0
- package/dist/components/docs/guides/GuideDataExchangeImportTemplatesPage.d.ts +1 -0
- package/dist/components/docs/guides/GuideDataExchangeImportTemplatesPage.js +176 -0
- package/dist/components/docs/guides/GuidesIndexPage.js +2 -2
- package/dist/components/docs/guides/index.d.ts +1 -0
- package/dist/components/docs/guides/index.js +220 -46
- package/dist/components/docs/index.js +1003 -309
- package/dist/components/docs/libraries/LibrariesApplicationShellPage.content.d.ts +22 -5
- package/dist/components/docs/libraries/LibrariesApplicationShellPage.content.js +125 -37
- package/dist/components/docs/libraries/LibrariesApplicationShellPage.js +125 -37
- package/dist/components/docs/libraries/LibrariesDataViewsPage.js +120 -3
- package/dist/components/docs/libraries/LibrariesDesignSystemPage.js +101 -2
- package/dist/components/docs/libraries/LibrariesOverviewPage.js +1 -1
- package/dist/components/docs/libraries/LibrariesPersonalizationPage.js +58 -4
- package/dist/components/docs/libraries/LibrariesTranslationRuntimePage.content.d.ts +10 -0
- package/dist/components/docs/libraries/LibrariesTranslationRuntimePage.content.js +43 -0
- package/dist/components/docs/libraries/LibrariesTranslationRuntimePage.d.ts +1 -0
- package/dist/components/docs/libraries/LibrariesTranslationRuntimePage.js +43 -0
- package/dist/components/docs/libraries/index.d.ts +1 -0
- package/dist/components/docs/libraries/index.js +496 -97
- package/dist/components/docs/specs/SpecsDataViewsPage.js +49 -3
- package/dist/components/docs/specs/index.js +60 -14
- package/dist/index.js +1014 -320
- package/dist/node/components/docs/DocsIndexPage.js +2 -2
- package/dist/node/components/docs/docsManifest.js +1 -1
- package/dist/node/components/docs/getting-started/DataViewTutorialPage.js +81 -6
- package/dist/node/components/docs/getting-started/index.js +94 -19
- package/dist/node/components/docs/guides/GuideDataExchangeImportTemplatesPage.content.js +175 -0
- package/dist/node/components/docs/guides/GuideDataExchangeImportTemplatesPage.js +175 -0
- package/dist/node/components/docs/guides/GuidesIndexPage.js +2 -2
- package/dist/node/components/docs/guides/index.js +220 -46
- package/dist/node/components/docs/index.js +1003 -309
- package/dist/node/components/docs/libraries/LibrariesApplicationShellPage.content.js +125 -37
- package/dist/node/components/docs/libraries/LibrariesApplicationShellPage.js +125 -37
- package/dist/node/components/docs/libraries/LibrariesDataViewsPage.js +120 -3
- package/dist/node/components/docs/libraries/LibrariesDesignSystemPage.js +101 -2
- package/dist/node/components/docs/libraries/LibrariesOverviewPage.js +1 -1
- package/dist/node/components/docs/libraries/LibrariesPersonalizationPage.js +58 -4
- package/dist/node/components/docs/libraries/LibrariesTranslationRuntimePage.content.js +42 -0
- package/dist/node/components/docs/libraries/LibrariesTranslationRuntimePage.js +42 -0
- package/dist/node/components/docs/libraries/index.js +496 -97
- package/dist/node/components/docs/specs/SpecsDataViewsPage.js +49 -3
- package/dist/node/components/docs/specs/index.js +60 -14
- package/dist/node/index.js +1014 -320
- package/package.json +74 -26
- package/src/components/docs/docsManifest.test.ts +87 -0
- package/src/components/docs/docsManifest.ts +90 -3
- package/src/components/docs/generated/docs-index.notifications.json +7 -7
- package/src/components/docs/getting-started/DataViewTutorialPage.tsx +181 -50
- package/src/components/docs/guides/GuideDataExchangeImportTemplatesPage.content.ts +185 -0
- package/src/components/docs/guides/GuideDataExchangeImportTemplatesPage.tsx +186 -0
- package/src/components/docs/guides/GuidesIndexPage.tsx +49 -42
- package/src/components/docs/guides/index.ts +1 -0
- package/src/components/docs/libraries/LibrariesApplicationShellPage.content.ts +148 -35
- package/src/components/docs/libraries/LibrariesApplicationShellPage.tsx +38 -5
- package/src/components/docs/libraries/LibrariesDataViewsPage.tsx +267 -64
- package/src/components/docs/libraries/LibrariesDesignSystemPage.tsx +235 -0
- package/src/components/docs/libraries/LibrariesOverviewPage.tsx +8 -2
- package/src/components/docs/libraries/LibrariesPersonalizationPage.tsx +141 -31
- package/src/components/docs/libraries/LibrariesTranslationRuntimePage.content.ts +78 -0
- package/src/components/docs/libraries/LibrariesTranslationRuntimePage.tsx +137 -0
- package/src/components/docs/libraries/index.ts +1 -0
- package/src/components/docs/specs/SpecsDataViewsPage.tsx +239 -113
|
@@ -1,4 +1,121 @@
|
|
|
1
|
-
var
|
|
1
|
+
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';
|
|
2
|
+
|
|
3
|
+
export const AccountsDataView = defineDataView({
|
|
4
|
+
meta: {
|
|
5
|
+
key: 'crm.accounts',
|
|
6
|
+
version: '1.0.0',
|
|
7
|
+
title: 'Accounts',
|
|
8
|
+
description: 'Customer account workspace',
|
|
9
|
+
domain: 'crm',
|
|
10
|
+
entity: 'account',
|
|
11
|
+
owners: ['@crm'],
|
|
12
|
+
tags: ['crm', 'accounts'],
|
|
13
|
+
stability: 'stable',
|
|
14
|
+
},
|
|
15
|
+
source: {
|
|
16
|
+
primary: { key: 'crm.accounts.list', version: '1.0.0' },
|
|
17
|
+
},
|
|
18
|
+
view: {
|
|
19
|
+
kind: 'table',
|
|
20
|
+
fields: [
|
|
21
|
+
{ key: 'name', label: 'Name', dataPath: 'name', sortable: true },
|
|
22
|
+
{ key: 'owner', label: 'Owner', dataPath: 'owner' },
|
|
23
|
+
{ key: 'arr', label: 'ARR', dataPath: 'arr', format: { type: 'currency', currency: 'EUR' } },
|
|
24
|
+
{
|
|
25
|
+
key: 'internalNotes',
|
|
26
|
+
label: 'Internal notes',
|
|
27
|
+
dataPath: 'internalNotes',
|
|
28
|
+
visibility: { minDataDepth: 'detailed' },
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
columns: [
|
|
32
|
+
{ field: 'name' },
|
|
33
|
+
{ field: 'owner' },
|
|
34
|
+
{ field: 'arr' },
|
|
35
|
+
{ field: 'internalNotes' },
|
|
36
|
+
],
|
|
37
|
+
collection: {
|
|
38
|
+
viewModes: {
|
|
39
|
+
defaultMode: 'table',
|
|
40
|
+
allowedModes: ['list', 'grid', 'table'],
|
|
41
|
+
},
|
|
42
|
+
pagination: {
|
|
43
|
+
pageSize: 25,
|
|
44
|
+
pageSizeOptions: [10, 25, 50],
|
|
45
|
+
},
|
|
46
|
+
toolbar: {
|
|
47
|
+
search: true,
|
|
48
|
+
viewMode: true,
|
|
49
|
+
filters: true,
|
|
50
|
+
density: true,
|
|
51
|
+
dataDepth: true,
|
|
52
|
+
},
|
|
53
|
+
density: 'comfortable',
|
|
54
|
+
dataDepth: 'standard',
|
|
55
|
+
personalization: {
|
|
56
|
+
enabled: true,
|
|
57
|
+
persist: {
|
|
58
|
+
viewMode: true,
|
|
59
|
+
density: true,
|
|
60
|
+
dataDepth: true,
|
|
61
|
+
pageSize: true,
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
});`,D=`import { DataViewRenderer } from '@contractspec/lib.design-system';
|
|
67
|
+
import { resolveDataViewPreferences } from '@contractspec/lib.personalization/data-view-preferences';
|
|
68
|
+
|
|
69
|
+
const resolved = resolveDataViewPreferences({
|
|
70
|
+
spec: AccountsDataView,
|
|
71
|
+
preferences: profile.canonical,
|
|
72
|
+
insights,
|
|
73
|
+
record: savedDataViewPreference,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
<DataViewRenderer
|
|
77
|
+
spec={AccountsDataView}
|
|
78
|
+
items={accounts}
|
|
79
|
+
defaultViewMode={resolved.viewMode}
|
|
80
|
+
defaultDensity={resolved.density}
|
|
81
|
+
defaultDataDepth={resolved.dataDepth}
|
|
82
|
+
pagination={{
|
|
83
|
+
page,
|
|
84
|
+
pageSize: resolved.pageSize ?? 25,
|
|
85
|
+
total,
|
|
86
|
+
}}
|
|
87
|
+
onViewModeChange={(viewMode) => {
|
|
88
|
+
tracker.trackDataViewInteraction({
|
|
89
|
+
dataViewKey: AccountsDataView.meta.key,
|
|
90
|
+
dataViewVersion: AccountsDataView.meta.version,
|
|
91
|
+
action: 'view_mode_changed',
|
|
92
|
+
viewMode,
|
|
93
|
+
});
|
|
94
|
+
}}
|
|
95
|
+
onDensityChange={(density) => {
|
|
96
|
+
tracker.trackDataViewInteraction({
|
|
97
|
+
dataViewKey: AccountsDataView.meta.key,
|
|
98
|
+
action: 'density_changed',
|
|
99
|
+
density,
|
|
100
|
+
});
|
|
101
|
+
}}
|
|
102
|
+
onDataDepthChange={(dataDepth) => {
|
|
103
|
+
tracker.trackDataViewInteraction({
|
|
104
|
+
dataViewKey: AccountsDataView.meta.key,
|
|
105
|
+
action: 'data_depth_changed',
|
|
106
|
+
dataDepth,
|
|
107
|
+
});
|
|
108
|
+
}}
|
|
109
|
+
/>;
|
|
110
|
+
`,N=`Implement a production DataView for <entity>.
|
|
111
|
+
|
|
112
|
+
Requirements:
|
|
113
|
+
- 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.
|
|
114
|
+
- Mark fields that should only appear in richer experiences with visibility.minDataDepth.
|
|
115
|
+
- Render it with DataViewRenderer using plain props from resolveDataViewPreferences.
|
|
116
|
+
- Track user interactions with trackDataViewInteraction for view mode, density, data depth, search, filters, sorting, and pagination.
|
|
117
|
+
- Keep @contractspec/lib.design-system independent from @contractspec/lib.personalization.
|
|
118
|
+
- 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';
|
|
2
119
|
import { MyUserList } from './specs/users.data-view';
|
|
3
120
|
|
|
4
121
|
export function UserPage() {
|
|
@@ -10,7 +127,7 @@ export function UserPage() {
|
|
|
10
127
|
onPageChange={(page) => fetchPage(page)}
|
|
11
128
|
/>
|
|
12
129
|
);
|
|
13
|
-
}`}),
|
|
130
|
+
}`}),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';
|
|
14
131
|
|
|
15
132
|
const generator = new DataViewQueryGenerator(MyUserList);
|
|
16
133
|
const params = {
|
|
@@ -25,4 +142,4 @@ const params = {
|
|
|
25
142
|
const errors = generator.validateParams(params);
|
|
26
143
|
const query = generator.generate(params);
|
|
27
144
|
|
|
28
|
-
// query.input contains skip/take plus the typed filter payloads.`})]}),
|
|
145
|
+
// 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};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var
|
|
1
|
+
var c=Object.defineProperty;var s=(o)=>o;function l(o,a){this[o]=s.bind(null,a)}var v=(o,a)=>{for(var n in a)c(o,n,{get:a[n],enumerable:!0,configurable:!0,set:l.bind(a,n)})};var y=(o,a)=>()=>(o&&(a=o(o=0)),a);import{CodeBlock as r,InstallCommand as d}from"@contractspec/lib.design-system";import i from"@contractspec/lib.ui-link";import{ChevronRight as m}from"lucide-react";import{jsx as e,jsxs as t}from"react/jsx-runtime";var p=`import { Button, DataTable } from '@contractspec/lib.design-system';
|
|
2
2
|
import { useContractTable } from '@contractspec/lib.presentation-runtime-react';
|
|
3
3
|
|
|
4
4
|
import { SHOWCASE_ROWS } from '@contractspec/example.data-grid-showcase/ui/data-grid-showcase.data';
|
|
@@ -80,6 +80,105 @@ export function TenantSurface({ children }: { children: React.ReactNode }) {
|
|
|
80
80
|
import { Select } from '@contractspec/lib.design-system/controls';
|
|
81
81
|
import { FormDialog } from '@contractspec/lib.design-system/forms';
|
|
82
82
|
import { HStack } from '@contractspec/lib.design-system/layout';
|
|
83
|
+
import { AdaptivePanel } from '@contractspec/lib.design-system/components/overlays';
|
|
84
|
+
import { ObjectReferenceHandler } from '@contractspec/lib.design-system/components/object-reference';
|
|
83
85
|
|
|
84
86
|
// Root imports remain supported:
|
|
85
|
-
import { Button, DataTable } from '@contractspec/lib.design-system'
|
|
87
|
+
import { Button, DataTable } from '@contractspec/lib.design-system';`,f=`import {
|
|
88
|
+
ObjectReferenceHandler,
|
|
89
|
+
createDefaultObjectReferenceActions,
|
|
90
|
+
createMapsReferenceActions,
|
|
91
|
+
type ObjectReferenceDescriptor,
|
|
92
|
+
type ObjectReferenceOpenHrefHandler,
|
|
93
|
+
} from '@contractspec/lib.design-system';
|
|
94
|
+
|
|
95
|
+
const customerContact: ObjectReferenceDescriptor = {
|
|
96
|
+
id: 'user.amina',
|
|
97
|
+
kind: 'user',
|
|
98
|
+
label: 'Amina Laurent',
|
|
99
|
+
description: 'Customer success owner',
|
|
100
|
+
href: '/customers/acme/users/amina',
|
|
101
|
+
properties: [
|
|
102
|
+
{
|
|
103
|
+
id: 'user.amina.email',
|
|
104
|
+
kind: 'email',
|
|
105
|
+
label: 'Email',
|
|
106
|
+
value: 'amina@example.com',
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
id: 'user.amina.phone',
|
|
110
|
+
kind: 'phone',
|
|
111
|
+
label: 'Phone',
|
|
112
|
+
value: '+33 1 23 45 67 89',
|
|
113
|
+
},
|
|
114
|
+
],
|
|
115
|
+
sections: [
|
|
116
|
+
{
|
|
117
|
+
id: 'customer-site',
|
|
118
|
+
title: 'Primary site',
|
|
119
|
+
properties: [
|
|
120
|
+
{
|
|
121
|
+
id: 'customer-site.address',
|
|
122
|
+
kind: 'address',
|
|
123
|
+
label: 'Paris office',
|
|
124
|
+
value: '10 rue de Rivoli, 75001 Paris',
|
|
125
|
+
actions: createMapsReferenceActions({
|
|
126
|
+
id: 'customer-site.address',
|
|
127
|
+
kind: 'address',
|
|
128
|
+
label: 'Paris office',
|
|
129
|
+
value: '10 rue de Rivoli, 75001 Paris',
|
|
130
|
+
}),
|
|
131
|
+
},
|
|
132
|
+
],
|
|
133
|
+
},
|
|
134
|
+
],
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const openHref: ObjectReferenceOpenHrefHandler = (href, _event, options) => {
|
|
138
|
+
if (options.target === 'new-page') {
|
|
139
|
+
window.open(href, '_blank', 'noopener,noreferrer');
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
window.location.assign(href);
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
<ObjectReferenceHandler
|
|
147
|
+
reference={customerContact}
|
|
148
|
+
actions={createDefaultObjectReferenceActions(customerContact)}
|
|
149
|
+
interactivityVisibility="icon"
|
|
150
|
+
openTarget="same-page"
|
|
151
|
+
panelMode="responsive"
|
|
152
|
+
mobilePanelMode="drawer"
|
|
153
|
+
desktopPanelMode="sheet"
|
|
154
|
+
responsiveBreakpoint="md"
|
|
155
|
+
openHref={openHref}
|
|
156
|
+
/>;`,g=`import { AdaptivePanel } from '@contractspec/lib.design-system/components/overlays';
|
|
157
|
+
|
|
158
|
+
<AdaptivePanel
|
|
159
|
+
open={open}
|
|
160
|
+
onOpenChange={setOpen}
|
|
161
|
+
trigger={<button type="button">Edit</button>}
|
|
162
|
+
title="Edit customer"
|
|
163
|
+
description="Update contact and site details."
|
|
164
|
+
mode="responsive"
|
|
165
|
+
mobileMode="drawer"
|
|
166
|
+
desktopMode="sheet"
|
|
167
|
+
breakpoint="md"
|
|
168
|
+
sheetSide="right"
|
|
169
|
+
drawerDirection="bottom"
|
|
170
|
+
>
|
|
171
|
+
{content}
|
|
172
|
+
</AdaptivePanel>;`,b=`Find every user-facing address, phone number, email, user, customer, file, URL, and tenant-specific object reference currently rendered as inert text.
|
|
173
|
+
|
|
174
|
+
Replace each one with ObjectReferenceHandler from @contractspec/lib.design-system. Keep descriptors data-only: id, kind, label, value, href, openTarget, properties, sections, metadata, iconKey, and ariaLabel are allowed; React callbacks belong in handler props only.
|
|
175
|
+
|
|
176
|
+
Use properties and sections for rich references. For example, a user reference can expose email, phone, address, files, and customer links in one panel instead of rendering separate disconnected strings.
|
|
177
|
+
|
|
178
|
+
Use panelMode="responsive" by default. Let desktop render a sheet and small screens render a bottom drawer through AdaptivePanel. Do not call Sheet or Drawer directly for this interaction unless a lower-level primitive is being implemented.
|
|
179
|
+
|
|
180
|
+
Use openTarget="same-page" unless product requirements explicitly require a new page. Put custom copy, navigation, analytics, permissions, or tenant-specific actions in copyHandler, openHref, actionHandlers, onAction, and onActionError.
|
|
181
|
+
|
|
182
|
+
For addresses, use createMapsReferenceActions so users can choose Google Maps, Apple Maps, or Waze. For email and phone references, prefer createDefaultObjectReferenceActions unless a product-specific action set is required.
|
|
183
|
+
|
|
184
|
+
After replacing references, verify keyboard access, visible affordance choice (none, underline, or icon), safe href behavior, mobile drawer layout, and desktop sheet layout.`;function k(){return t("div",{className:"space-y-8",children:[t("div",{className:"space-y-4",children:[e("h1",{className:"font-bold text-4xl",children:"@contractspec/lib.design-system"}),t("p",{className:"text-muted-foreground",children:["High-level design system components, patterns, and layouts for LSSM applications. Built on top of ",e("code",{children:"@contractspec/lib.ui-kit"}),"."]})]}),t("div",{className:"space-y-4",children:[e("h2",{className:"font-bold text-2xl",children:"Installation"}),e(d,{package:"@contractspec/lib.design-system"})]}),t("div",{className:"space-y-4",children:[e("h2",{className:"font-bold text-2xl",children:"What It Provides"}),t("ul",{className:"list-inside list-disc space-y-2 text-muted-foreground",children:[t("li",{children:[e("strong",{children:"Composite Components"}),": Molecules and Organisms that solve common UI problems"]}),t("li",{children:[e("strong",{children:"Layouts"}),": Ready-to-use page structures for dashboards, marketing sites, and lists"]}),t("li",{children:[e("strong",{children:"Data Views"}),": Standardized renderers for lists, tables, and detail views"]}),t("li",{children:[e("strong",{children:"Forms"}),": Zod-integrated form layouts and components"]}),t("li",{children:[e("strong",{children:"Code Display"}),": Syntax-highlighted code blocks with package manager tabs"]}),t("li",{children:[e("strong",{children:"Platform Utilities"}),": Hooks for responsive and adaptive design"]}),t("li",{children:[e("strong",{children:"Object References"}),": Clickable references for addresses, phone numbers, users, customers, files, URLs, and custom objects"]}),t("li",{children:[e("strong",{children:"Adaptive Panels"}),": One panel API that resolves to a desktop sheet or mobile drawer"]}),t("li",{children:[e("strong",{children:"Theme Bridge"}),": ThemeSpec to Tailwind variables, presets, CSS text, and runtime light/dark mode"]}),t("li",{children:[e("strong",{children:"Legal Templates"}),": Compliant templates for Terms, Privacy, and GDPR"]})]})]}),t("div",{className:"space-y-4",children:[e("h2",{className:"font-bold text-2xl",children:"ThemeSpec to Tailwind"}),t("p",{className:"text-muted-foreground",children:["The theme bridge keeps ",e("code",{children:"ThemeSpec"})," as the source of truth and exposes no-generation Tailwind helpers, optional CSS text serialization, runtime CSS variables, light/dark modes, and OKLCH color pass-through."]}),e(r,{language:"tsx",code:u})]}),t("div",{className:"space-y-4",children:[e("h2",{className:"font-bold text-2xl",children:"Focused import surfaces"}),e("p",{className:"text-muted-foreground",children:"New code can use focused subpaths for theme, controls, forms, and layout while existing root imports remain compatible."}),e(r,{language:"tsx",code:h})]}),t("div",{className:"space-y-4",children:[e("h2",{className:"font-bold text-2xl",children:"Actionable object references"}),t("p",{className:"text-muted-foreground",children:["Use ",e("code",{children:"ObjectReferenceHandler"})," whenever a product surface renders an object that may need quick interaction: addresses, phone numbers, emails, users, customers, files, URLs, and tenant-specific objects. The goal is to avoid inert references while keeping the descriptor contract declarative enough for OSS consumers and future contract-generated surfaces."]}),t("div",{className:"grid gap-4 md:grid-cols-2",children:[t("div",{className:"card-subtle p-4",children:[e("h3",{className:"mb-2 font-semibold",children:"Descriptor model"}),t("ul",{className:"list-inside list-disc space-y-1 text-muted-foreground text-sm",children:[t("li",{children:["References use data-only descriptors: ",e("code",{children:"id"}),","," ",e("code",{children:"kind"}),", ",e("code",{children:"label"}),", ",e("code",{children:"value"}),","," ",e("code",{children:"href"}),", ",e("code",{children:"openTarget"}),","," ",e("code",{children:"metadata"}),", ",e("code",{children:"iconKey"}),", and"," ",e("code",{children:"ariaLabel"}),"."]}),t("li",{children:["Rich references use nested ",e("code",{children:"properties"})," and"," ",e("code",{children:"sections"}),", so one user or customer can expose email, phone, address, files, and links inside the same panel."]}),t("li",{children:["Reference kinds are ",e("code",{children:"address"}),", ",e("code",{children:"email"}),","," ",e("code",{children:"phone"}),", ",e("code",{children:"user"}),", ",e("code",{children:"customer"}),","," ",e("code",{children:"file"}),", ",e("code",{children:"url"}),", and ",e("code",{children:"custom"}),"."]})]})]}),t("div",{className:"card-subtle p-4",children:[e("h3",{className:"mb-2 font-semibold",children:"Runtime behavior"}),t("ul",{className:"list-inside list-disc space-y-1 text-muted-foreground text-sm",children:[t("li",{children:["Choose visibility with ",e("code",{children:"interactivityVisibility"}),":",e("code",{children:"none"}),", ",e("code",{children:"underline"}),", or ",e("code",{children:"icon"}),"."]}),t("li",{children:["Detail navigation defaults to ",e("code",{children:"same-page"}),"; set"," ",e("code",{children:'openTarget="new-page"'})," on the handler, reference, or action when a new page is required."]}),t("li",{children:["Host apps provide behavior through ",e("code",{children:"copyHandler"}),","," ",e("code",{children:"openHref"}),", ",e("code",{children:"actionHandlers"}),","," ",e("code",{children:"onAction"}),", and ",e("code",{children:"onActionError"}),"."]})]})]}),t("div",{className:"card-subtle p-4",children:[e("h3",{className:"mb-2 font-semibold",children:"Default actions"}),t("ul",{className:"list-inside list-disc space-y-1 text-muted-foreground text-sm",children:[t("li",{children:[e("code",{children:"createDefaultObjectReferenceActions"})," adds copy, open, email, phone, and map actions when the descriptor supports them."]}),t("li",{children:[e("code",{children:"createMapsReferenceActions"})," creates Google Maps, Apple Maps, Waze, or geo actions for address references."]}),e("li",{children:"Safe href handling allows expected app, web, email, phone, and map URLs while rejecting unsafe schemes."})]})]}),t("div",{className:"card-subtle p-4",children:[e("h3",{className:"mb-2 font-semibold",children:"Extension points"}),t("ul",{className:"list-inside list-disc space-y-1 text-muted-foreground text-sm",children:[t("li",{children:["Use ",e("code",{children:"renderTrigger"}),", ",e("code",{children:"renderDetail"}),","," ",e("code",{children:"renderAction"}),", ",e("code",{children:"renderProperty"}),","," ",e("code",{children:"renderSection"}),", and ",e("code",{children:"iconRenderer"})," to wrap or overload presentation."]}),e("li",{children:"Keep tenant-specific permissions, analytics, and integration side effects at the host boundary through runtime handlers."})]})]})]}),e(r,{language:"tsx",code:f})]}),t("div",{className:"space-y-4",children:[e("h2",{className:"font-bold text-2xl",children:"Adaptive panels"}),t("p",{className:"text-muted-foreground",children:[e("code",{children:"AdaptivePanel"})," is the shared overlay decision for surfaces that should feel native on both desktop and small screens. Its default responsive mode renders a sheet at the configured desktop breakpoint and a drawer below it. ",e("code",{children:"ObjectReferenceHandler"})," uses this panel contract through ",e("code",{children:"panelMode"}),","," ",e("code",{children:"mobilePanelMode"}),", ",e("code",{children:"desktopPanelMode"}),", and"," ",e("code",{children:"responsiveBreakpoint"}),"."]}),e(r,{language:"tsx",code:g})]}),t("div",{className:"space-y-4",children:[e("h2",{className:"font-bold text-2xl",children:"Prompt for adoption work"}),e("p",{className:"text-muted-foreground",children:"Use this prompt when asking an agent or downstream OSS consumer to replace inert references across an application."}),e(r,{language:"text",code:b})]}),t("div",{className:"space-y-4",children:[e("h2",{className:"font-bold text-2xl",children:"Data table example"}),t("p",{className:"text-muted-foreground",children:["This is the composed lane from the canonical"," ",e(i,{href:"/docs/examples/data-grid-showcase",className:"text-[color:var(--rust)] underline underline-offset-4",children:"Data Grid Showcase"}),". The design-system wrapper owns title, description, header actions, and the opinionated card shell on top of the raw web primitive."]}),e(r,{language:"tsx",code:p})]}),t("div",{className:"space-y-4",children:[e("h2",{className:"font-bold text-2xl",children:"Key Exports"}),t("div",{className:"grid gap-4 md:grid-cols-2",children:[t("div",{className:"card-subtle p-4",children:[e("h3",{className:"mb-2 font-semibold",children:"Organisms"}),t("ul",{className:"space-y-1 text-muted-foreground text-sm",children:[e("li",{children:"AppShell, PageOutline"}),e("li",{children:"AppLayout, AppHeader, AppSidebar"}),e("li",{children:"MarketingLayout, HeroSection"}),e("li",{children:"ListCardPage, ListTablePage"})]})]}),t("div",{className:"card-subtle p-4",children:[e("h3",{className:"mb-2 font-semibold",children:"Data & Forms"}),t("ul",{className:"space-y-1 text-muted-foreground text-sm",children:[e("li",{children:"DataTable"}),e("li",{children:"DataViewTable"}),e("li",{children:"DataViewRenderer"}),e("li",{children:"ZodForm"}),e("li",{children:"FormLayout, FormDialog"})]})]}),t("div",{className:"card-subtle p-4",children:[e("h3",{className:"mb-2 font-semibold",children:"Code Display"}),t("ul",{className:"space-y-1 text-muted-foreground text-sm",children:[e("li",{children:"CodeBlock (syntax highlighting)"}),e("li",{children:"CommandTabs (package manager tabs)"}),e("li",{children:"InstallCommand (convenience wrapper)"}),e("li",{children:"CopyButton"})]})]}),t("div",{className:"card-subtle p-4",children:[e("h3",{className:"mb-2 font-semibold",children:"Providers"}),e("ul",{className:"space-y-1 text-muted-foreground text-sm",children:e("li",{children:"PackageManagerProvider"})})]}),t("div",{className:"card-subtle p-4",children:[e("h3",{className:"mb-2 font-semibold",children:"References & Overlays"}),t("ul",{className:"space-y-1 text-muted-foreground text-sm",children:[e("li",{children:"ObjectReferenceHandler"}),e("li",{children:"createDefaultObjectReferenceActions"}),e("li",{children:"createMapsReferenceActions"}),e("li",{children:"AdaptivePanel"})]})]})]})]}),t("div",{className:"card-subtle space-y-3 p-6",children:[e("h2",{className:"font-bold text-2xl",children:"Where this layer fits"}),t("p",{className:"text-muted-foreground",children:["Read"," ",e(i,{href:"/docs/libraries/application-shell",className:"text-[color:var(--rust)] underline underline-offset-4",children:"Application shell"})," ","for the shared sidebar, topbar, command search, mobile navigation, and"," ",e("code",{children:"PageOutline"})," pattern. Read"," ",e(i,{href:"/docs/libraries/cross-platform-ui",className:"text-[color:var(--rust)] underline underline-offset-4",children:"Cross-platform UI"})," ","for the package split between shared runtime controllers, leaf platform primitives, and this composed design-system layer."]})]}),t("div",{className:"flex items-center gap-4 pt-4",children:[e(i,{href:"/docs/libraries/ui-kit-web",className:"btn-ghost",children:"Previous: UI Kit Web"}),t(i,{href:"/docs/libraries/accessibility",className:"btn-primary",children:["Next: Accessibility ",e(m,{size:16})]})]})]})}export{k as LibrariesDesignSystemPage};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var s=Object.defineProperty;var o=(e)=>e;function
|
|
1
|
+
var s=Object.defineProperty;var o=(e)=>e;function n(e,t){this[e]=o.bind(null,t)}var p=(e,t)=>{for(var r in t)s(e,r,{get:t[r],enumerable:!0,configurable:!0,set:n.bind(t,r)})};var m=(e,t)=>()=>(e&&(t=e(e=0)),t);import c from"@contractspec/lib.ui-link";import{ChevronRight as l}from"lucide-react";import{jsx as i,jsxs as a}from"react/jsx-runtime";var d=[{title:"Contract and schema foundation",body:"Use these packages to define explicit contracts, schemas, and generated artifacts without inventing a new platform-specific language.",items:[{title:"@contractspec/lib.contracts-spec",description:"Define operations, events, policies, and generated surfaces in TypeScript.",href:"/docs/libraries/contracts"},{title:"@contractspec/lib.schema",description:"Share type-safe schema definitions across validation, clients, and runtime adapters.",href:"/docs/libraries/schema"}]},{title:"Runtime and surface libraries",body:"These packages execute the contract model across UI, data, observability, workflows, and generated runtime behavior.",items:[{title:"@contractspec/lib.runtime",description:"Run typed capability surfaces, execute policies, and connect runtime adapters.",href:"/docs/libraries/runtime"},{title:"@contractspec/lib.translation-runtime",description:"Resolve ContractSpec TranslationSpec catalogs with ICU formatting, SSR snapshots, BCP 47 locales, overrides, and optional i18next projection.",href:"/docs/libraries/translation-runtime"},{title:"@contractspec/lib.ui-kit",description:"Render shared surfaces across web and React Native without forking the contract layer.",href:"/docs/libraries/ui-kit"},{title:"@contractspec/lib.ui-kit-web",description:"Use the raw web primitive layer directly when you want the browser table, accessibility, and interaction model without the design-system shell.",href:"/docs/libraries/ui-kit-web"},{title:"@contractspec/lib.design-system",description:"Build higher-level product surfaces, actionable object references, adaptive panels, and documented marketing/docs primitives on top of the web and native UI packages.",href:"/docs/libraries/design-system"},{title:"Application shell",description:"Adopt the shared sidebar, topbar, command search, notifications, mobile navigation, and PageOutline patterns for product apps.",href:"/docs/libraries/application-shell"},{title:"Cross-platform UI",description:"See how the presentation runtimes, ui-kit-web, ui-kit, and design-system stay compatible across React and React Native.",href:"/docs/libraries/cross-platform-ui"},{title:"@contractspec/lib.data-views",description:"Generate and render list/detail style surfaces that stay aligned with data contracts.",href:"/docs/libraries/data-views"}]},{title:"Operator and system packages",body:"These packages matter once the system is live and you need governance, resilience, and observability.",items:[{title:"@contractspec/lib.observability",description:"Trace, log, and measure contract execution using the same system boundaries.",href:"/docs/libraries/observability"},{title:"@contractspec/lib.resilience",description:"Add circuit breakers, retries, and failure controls without hiding the integration model.",href:"/docs/libraries/resilience"},{title:"@contractspec/lib.multi-tenancy",description:"Keep tenant-specific config, policy, and surface resolution explicit.",href:"/docs/libraries/multi-tenancy"},{title:"@contractspec/lib.workflow-composer",description:"Compose and extend workflows without smearing orchestration concerns across apps.",href:"/docs/libraries/workflow-composer"}]}];function f(){return a("div",{className:"space-y-10",children:[a("div",{className:"space-y-3",children:[i("p",{className:"editorial-kicker",children:"Build"}),i("h1",{className:"font-serif text-4xl tracking-[-0.04em] md:text-5xl",children:"The OSS foundation is a library system, not a closed platform."}),i("p",{className:"max-w-3xl text-lg text-muted-foreground leading-8",children:"ContractSpec is assembled from libraries that remain useful on their own and stronger together. Start with the contract and schema foundation, then add runtime, UI, integration, and operator packages as your system grows."})]}),a("div",{className:"editorial-proof-strip",children:[a("div",{className:"editorial-stat",children:[i("span",{className:"editorial-label",children:"Layering rule"}),i("span",{className:"editorial-stat-value",children:"libs → bundles → apps"})]}),i("p",{className:"max-w-2xl text-muted-foreground text-sm leading-7",children:"Keep reusable behavior in libraries, compose it into bundle-level surfaces, and reserve app packages for concrete delivery shells."})]}),i("div",{className:"space-y-6",children:d.map((e)=>a("section",{className:"editorial-panel space-y-5",children:[a("div",{className:"space-y-2",children:[i("h2",{className:"font-serif text-3xl tracking-[-0.03em]",children:e.title}),i("p",{className:"text-muted-foreground text-sm leading-7",children:e.body})]}),i("div",{className:"grid gap-4 md:grid-cols-2",children:e.items.map((t)=>a(c,{href:t.href,className:"rounded-[24px] border border-border/75 bg-background/70 p-5 transition-colors hover:border-[color:rgb(162_79_42_/_0.45)]",children:[i("h3",{className:"font-semibold text-lg",children:t.title}),i("p",{className:"mt-2 text-muted-foreground text-sm leading-7",children:t.description}),a("div",{className:"mt-3 flex items-center gap-2 text-[color:var(--rust)] text-sm",children:["Learn more ",i(l,{size:14})]})]},t.title))})]},e.title))})]})}export{f as LibrariesOverviewPage};
|
|
@@ -1,4 +1,52 @@
|
|
|
1
|
-
var
|
|
1
|
+
var u=Object.defineProperty;var v=(e)=>e;function w(e,g){this[e]=v.bind(null,g)}var $=(e,g)=>{for(var o in g)u(e,o,{get:g[o],enumerable:!0,configurable:!0,set:w.bind(g,o)})};var F=(e,g)=>()=>(e&&(g=e(e=0)),g);import{CodeBlock as m,InstallCommand as y}from"@contractspec/lib.design-system";import{HStack as z,VStack as f}from"@contractspec/lib.design-system/layout";import{Code as r,H1 as B,H2 as h,P as l,Text as p}from"@contractspec/lib.design-system/typography";import q from"@contractspec/lib.ui-link";import{ChevronRight as J}from"lucide-react";import{jsx as b,jsxs as d}from"react/jsx-runtime";var Q=`import { DataViewRenderer } from '@contractspec/lib.design-system';
|
|
2
|
+
import { resolveDataViewPreferences } from '@contractspec/lib.personalization/data-view-preferences';
|
|
3
|
+
|
|
4
|
+
const resolved = resolveDataViewPreferences({
|
|
5
|
+
spec: AccountsDataView,
|
|
6
|
+
preferences: profile.canonical,
|
|
7
|
+
insights,
|
|
8
|
+
record: savedAccountViewPreference,
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
<DataViewRenderer
|
|
13
|
+
spec={AccountsDataView}
|
|
14
|
+
items={accounts}
|
|
15
|
+
defaultViewMode={resolved.viewMode}
|
|
16
|
+
defaultDensity={resolved.density}
|
|
17
|
+
defaultDataDepth={resolved.dataDepth}
|
|
18
|
+
pagination={{
|
|
19
|
+
page,
|
|
20
|
+
pageSize: resolved.pageSize ?? 25,
|
|
21
|
+
total,
|
|
22
|
+
}}
|
|
23
|
+
/>
|
|
24
|
+
);`,U=`tracker.trackDataViewInteraction({
|
|
25
|
+
dataViewKey: AccountsDataView.meta.key,
|
|
26
|
+
dataViewVersion: AccountsDataView.meta.version,
|
|
27
|
+
action: 'view_mode_changed',
|
|
28
|
+
viewMode: 'grid',
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
tracker.trackDataViewInteraction({
|
|
32
|
+
dataViewKey: AccountsDataView.meta.key,
|
|
33
|
+
action: 'data_depth_changed',
|
|
34
|
+
dataDepth: 'detailed',
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
tracker.trackDataViewInteraction({
|
|
38
|
+
dataViewKey: AccountsDataView.meta.key,
|
|
39
|
+
action: 'filter_changed',
|
|
40
|
+
filterKey: 'status',
|
|
41
|
+
});`,Y=`Add DataView personalization for <screen>.
|
|
42
|
+
|
|
43
|
+
Acceptance criteria:
|
|
44
|
+
- Resolve viewMode, density, dataDepth, and pageSize with resolveDataViewPreferences.
|
|
45
|
+
- Apply resolved values to DataViewRenderer as default or controlled props.
|
|
46
|
+
- Track opened, view_mode_changed, density_changed, data_depth_changed, search_changed, filter_changed, sort_changed, and page_changed actions with trackDataViewInteraction.
|
|
47
|
+
- Persist only the dimensions allowed by view.collection.personalization.persist.
|
|
48
|
+
- Ignore behavior-derived modes that are not allowed by view.collection.viewModes.allowedModes.
|
|
49
|
+
- Do not import React or design-system code into @contractspec/lib.personalization helpers.`;function i(){return d(f,{className:"space-y-8",children:[d(f,{className:"space-y-4",children:[b(B,{className:"font-bold text-4xl",children:"@contractspec/lib.personalization"}),b(l,{className:"text-lg text-muted-foreground",children:"Track field/feature/workflow usage, analyze drop-offs, and convert insights into OverlaySpecs or workflow tweaks."})]}),d(f,{className:"space-y-4",children:[b(h,{className:"font-bold text-2xl",children:"Installation"}),b(y,{package:"@contractspec/lib.personalization"})]}),d(f,{className:"space-y-4",children:[b(h,{className:"font-bold text-2xl",children:"Tracker"}),b(l,{className:"text-muted-foreground",children:"Buffer events per tenant/user and emit OpenTelemetry counters automatically."}),b(m,{language:"typescript",code:`import { createBehaviorTracker } from '@contractspec/lib.personalization';
|
|
2
50
|
|
|
3
51
|
const tracker = createBehaviorTracker({
|
|
4
52
|
store,
|
|
@@ -6,14 +54,20 @@ const tracker = createBehaviorTracker({
|
|
|
6
54
|
});
|
|
7
55
|
|
|
8
56
|
tracker.trackFieldAccess({ operation: 'billing.createOrder', field: 'items' });
|
|
9
|
-
tracker.trackWorkflowStep({ workflow: 'invoice', step: 'review', status: 'entered' });`})]}),r("
|
|
57
|
+
tracker.trackWorkflowStep({ workflow: 'invoice', step: 'review', status: 'entered' });`})]}),d(f,{className:"space-y-4",children:[b(h,{className:"font-bold text-2xl",children:"DataView Preferences"}),d(l,{className:"text-muted-foreground",children:["Use ",b(r,{children:"resolveDataViewPreferences"})," when a collection DataView should honor a user's preferred list/grid/table mode, compact or comfortable density, data depth, and page size. The helper returns plain values that can be passed into the renderer without coupling the design-system package to personalization. Start from the"," ",b(q,{href:"/docs/libraries/data-views",className:"text-[color:var(--rust)] underline underline-offset-4",children:b(p,{children:"DataViews runtime guide"})})," ","when you need the contract and renderer shape."]}),b(m,{language:"tsx",code:Q})]}),d(f,{className:"space-y-4",children:[b(h,{className:"font-bold text-2xl",children:"DataView Interaction Events"}),d(l,{className:"text-muted-foreground",children:["Track ",b(r,{children:"data_view_interaction"})," events for view mode, density, data depth, search, filters, sorting, and pagination. The in-memory store summarizes those events, and the analyzer can derive a scoped preferred collection mode from valid interaction counts."]}),b(m,{language:"typescript",code:U})]}),d(f,{className:"space-y-4",children:[b(h,{className:"font-bold text-2xl",children:"Analyzer"}),b(l,{className:"text-muted-foreground",children:"Summarize events and highlight unused UI, frequent fields, and workflow bottlenecks."}),b(m,{language:"typescript",code:`import { BehaviorAnalyzer } from '@contractspec/lib.personalization/analyzer';
|
|
10
58
|
|
|
11
59
|
const analyzer = new BehaviorAnalyzer(store);
|
|
12
60
|
const insights = await analyzer.analyze({ tenantId: 'acme', userId: 'ops-42' });
|
|
13
|
-
// {
|
|
61
|
+
// {
|
|
62
|
+
// unusedFields: ['internalNotes'],
|
|
63
|
+
// workflowBottlenecks: [...],
|
|
64
|
+
// dataViewPreferences: {
|
|
65
|
+
// 'crm.accounts': { preferredViewMode: 'grid' }
|
|
66
|
+
// }
|
|
67
|
+
// }`})]}),d(f,{className:"space-y-4",children:[b(h,{className:"font-bold text-2xl",children:"Adapter"}),b(l,{className:"text-muted-foreground",children:"Convert insights into overlays or workflow extension hints."}),b(m,{language:"typescript",code:`import { insightsToOverlaySuggestion } from '@contractspec/lib.personalization/adapter';
|
|
14
68
|
|
|
15
69
|
const overlay = insightsToOverlaySuggestion(insights, {
|
|
16
70
|
overlayId: 'acme-order-form',
|
|
17
71
|
tenantId: 'acme',
|
|
18
72
|
capability: 'billing.createOrder',
|
|
19
|
-
});`})]}),
|
|
73
|
+
});`})]}),d(f,{className:"space-y-4",children:[b(h,{className:"font-bold text-2xl",children:"Agent Prompt"}),b(l,{className:"text-muted-foreground",children:"Use this when asking an agent to wire DataView preferences while preserving the personalization/design-system boundary."}),b(m,{language:"markdown",code:Y})]}),d(z,{className:"items-center gap-4 pt-4",children:[b(q,{href:"/docs/libraries",className:"btn-ghost",children:b(p,{children:"Back to Libraries"})}),d(q,{href:"/docs/libraries/overlay-engine",className:"btn-primary",children:[b(p,{children:"Next: Overlay Engine"})," ",b(J,{size:16})]})]})]})}export{i as LibrariesPersonalizationPage};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
var n=Object.defineProperty;var s=(e)=>e;function o(e,t){this[e]=s.bind(null,t)}var r=(e,t)=>{for(var a in t)n(e,a,{get:t[a],enumerable:!0,configurable:!0,set:o.bind(t,a)})};var i=(e,t)=>()=>(e&&(t=e(e=0)),t);var l=["@contractspec/lib.contracts-spec","@contractspec/lib.translation-runtime"],p=`import { createTranslationRuntime } from '@contractspec/lib.translation-runtime';
|
|
2
|
+
import { checkoutMessages } from './translations/checkout.messages';
|
|
3
|
+
|
|
4
|
+
const runtime = createTranslationRuntime({
|
|
5
|
+
catalogs: [checkoutMessages],
|
|
6
|
+
locale: 'fr-FR',
|
|
7
|
+
fallbackLocales: ['fr', 'en-US'],
|
|
8
|
+
onDiagnostic: (diagnostic) => reportTranslationIssue(diagnostic),
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const label = runtime.t('checkout.pay', {
|
|
12
|
+
amount: 4200,
|
|
13
|
+
currency: 'EUR',
|
|
14
|
+
});`,d=`import { createInstance } from 'i18next';
|
|
15
|
+
import {
|
|
16
|
+
createI18nextInitOptions,
|
|
17
|
+
exportContractSpecToI18next,
|
|
18
|
+
} from '@contractspec/lib.translation-runtime/i18next';
|
|
19
|
+
|
|
20
|
+
const exported = exportContractSpecToI18next([checkoutMessages], {
|
|
21
|
+
locale: 'en-US',
|
|
22
|
+
assumeIcuFormatter: true,
|
|
23
|
+
});
|
|
24
|
+
const { options, diagnostics } = createI18nextInitOptions(exported, {
|
|
25
|
+
lng: 'en-US',
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const i18next = createInstance();
|
|
29
|
+
await i18next.init(options);
|
|
30
|
+
reportAdapterDiagnostics(diagnostics);`,m=`// Server: negotiate once, preload catalogs, and serialize the runtime snapshot.
|
|
31
|
+
const runtime = createTranslationRuntime({
|
|
32
|
+
catalogs,
|
|
33
|
+
locale: negotiatedLocale,
|
|
34
|
+
fallbackLocales,
|
|
35
|
+
});
|
|
36
|
+
const snapshot = runtime.createSnapshot();
|
|
37
|
+
|
|
38
|
+
// Client: hydrate from the same snapshot so locale, resources, and fallback state match.
|
|
39
|
+
const hydratedRuntime = createTranslationRuntime({ snapshot });`,u=["Keep TranslationSpec as the source of truth; do not flatten metadata into i18next JSON as the canonical model.","Keep stable bundle identity in TranslationSpec.meta.key and keep BCP 47 language tags in TranslationSpec.locale.","Use ICU messages for plural, select, selectordinal, number, date, currency, list, and relative-time formatting.","Create one runtime per SSR request when tenant, project, or user overrides are involved.","Serialize the same runtime snapshot or exported adapter resources used by the server for hydration.","Configure an ICU-capable i18next formatter plugin when rendering ContractSpec ICU messages through i18next.","Treat adapter diagnostics as release blockers in production pipelines instead of silently rendering raw keys."],h=`You are integrating ContractSpec translations into a production app.
|
|
40
|
+
Use @contractspec/lib.contracts-spec/translations as the canonical contract layer and @contractspec/lib.translation-runtime as the runtime layer.
|
|
41
|
+
Keep locale variants separate from stable bundle keys, support BCP 47 tags, preserve ICU plural/select/selectordinal messages, and use request-scoped runtime instances for SSR.
|
|
42
|
+
If the app already uses i18next, use @contractspec/lib.translation-runtime/i18next only as a downstream adapter. Do not make i18next the canonical translation model. Include diagnostics, fallback behavior, tenant/user override isolation, and hydration snapshot handling in the implementation and tests.`,g=[{title:"Spec layer",body:"TranslationSpec owns keys, locales, domains, versions, owners, fallback declarations, direction, and validation metadata."},{title:"Runtime layer",body:"Runtime instances negotiate locales, apply fallback chains, resolve overrides, cache compiled messages, report diagnostics, and serialize SSR snapshots."},{title:"Adapter layer",body:"The i18next adapter projects ContractSpec specs or snapshots to resources and manifests for caller-owned i18next instances."}];export{h as translationRuntimePrompt,g as translationRuntimeLayers,l as translationRuntimeInstall,p as translationRuntimeExample,u as translationRuntimeChecks,m as ssrHydrationExample,d as i18nextAdapterExample};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
var v=Object.defineProperty;var S=(a)=>a;function R(a,r){this[a]=S.bind(null,r)}var M=(a,r)=>{for(var l in r)v(a,l,{get:r[l],enumerable:!0,configurable:!0,set:R.bind(r,l)})};var O=(a,r)=>()=>(a&&(r=a(a=0)),r);var d=["@contractspec/lib.contracts-spec","@contractspec/lib.translation-runtime"],u=`import { createTranslationRuntime } from '@contractspec/lib.translation-runtime';
|
|
2
|
+
import { checkoutMessages } from './translations/checkout.messages';
|
|
3
|
+
|
|
4
|
+
const runtime = createTranslationRuntime({
|
|
5
|
+
catalogs: [checkoutMessages],
|
|
6
|
+
locale: 'fr-FR',
|
|
7
|
+
fallbackLocales: ['fr', 'en-US'],
|
|
8
|
+
onDiagnostic: (diagnostic) => reportTranslationIssue(diagnostic),
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const label = runtime.t('checkout.pay', {
|
|
12
|
+
amount: 4200,
|
|
13
|
+
currency: 'EUR',
|
|
14
|
+
});`,m=`import { createInstance } from 'i18next';
|
|
15
|
+
import {
|
|
16
|
+
createI18nextInitOptions,
|
|
17
|
+
exportContractSpecToI18next,
|
|
18
|
+
} from '@contractspec/lib.translation-runtime/i18next';
|
|
19
|
+
|
|
20
|
+
const exported = exportContractSpecToI18next([checkoutMessages], {
|
|
21
|
+
locale: 'en-US',
|
|
22
|
+
assumeIcuFormatter: true,
|
|
23
|
+
});
|
|
24
|
+
const { options, diagnostics } = createI18nextInitOptions(exported, {
|
|
25
|
+
lng: 'en-US',
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const i18next = createInstance();
|
|
29
|
+
await i18next.init(options);
|
|
30
|
+
reportAdapterDiagnostics(diagnostics);`,h=`// Server: negotiate once, preload catalogs, and serialize the runtime snapshot.
|
|
31
|
+
const runtime = createTranslationRuntime({
|
|
32
|
+
catalogs,
|
|
33
|
+
locale: negotiatedLocale,
|
|
34
|
+
fallbackLocales,
|
|
35
|
+
});
|
|
36
|
+
const snapshot = runtime.createSnapshot();
|
|
37
|
+
|
|
38
|
+
// Client: hydrate from the same snapshot so locale, resources, and fallback state match.
|
|
39
|
+
const hydratedRuntime = createTranslationRuntime({ snapshot });`,g=["Keep TranslationSpec as the source of truth; do not flatten metadata into i18next JSON as the canonical model.","Keep stable bundle identity in TranslationSpec.meta.key and keep BCP 47 language tags in TranslationSpec.locale.","Use ICU messages for plural, select, selectordinal, number, date, currency, list, and relative-time formatting.","Create one runtime per SSR request when tenant, project, or user overrides are involved.","Serialize the same runtime snapshot or exported adapter resources used by the server for hydration.","Configure an ICU-capable i18next formatter plugin when rendering ContractSpec ICU messages through i18next.","Treat adapter diagnostics as release blockers in production pipelines instead of silently rendering raw keys."],f=`You are integrating ContractSpec translations into a production app.
|
|
40
|
+
Use @contractspec/lib.contracts-spec/translations as the canonical contract layer and @contractspec/lib.translation-runtime as the runtime layer.
|
|
41
|
+
Keep locale variants separate from stable bundle keys, support BCP 47 tags, preserve ICU plural/select/selectordinal messages, and use request-scoped runtime instances for SSR.
|
|
42
|
+
If the app already uses i18next, use @contractspec/lib.translation-runtime/i18next only as a downstream adapter. Do not make i18next the canonical translation model. Include diagnostics, fallback behavior, tenant/user override isolation, and hydration snapshot handling in the implementation and tests.`,b=[{title:"Spec layer",body:"TranslationSpec owns keys, locales, domains, versions, owners, fallback declarations, direction, and validation metadata."},{title:"Runtime layer",body:"Runtime instances negotiate locales, apply fallback chains, resolve overrides, cache compiled messages, report diagnostics, and serialize SSR snapshots."},{title:"Adapter layer",body:"The i18next adapter projects ContractSpec specs or snapshots to resources and manifests for caller-owned i18next instances."}];import{CodeBlock as s,InstallCommand as U}from"@contractspec/lib.design-system";import{HStack as y,VStack as n}from"@contractspec/lib.design-system/layout";import{List as w,ListItem as C}from"@contractspec/lib.design-system/list";import{Code as p,H1 as z,H2 as c,H3 as D,P as i,Text as o}from"@contractspec/lib.design-system/typography";import I from"@contractspec/lib.ui-link";import{ChevronRight as K}from"lucide-react";import{jsx as e,jsxs as t}from"react/jsx-runtime";function G(){return t(n,{className:"space-y-8",children:[t(n,{className:"space-y-4",children:[e(o,{className:"editorial-kicker",children:"Runtime and adapters"}),e(z,{className:"font-serif text-4xl tracking-[-0.04em] md:text-5xl",children:"Translation runtime and i18next adapter"}),e(i,{className:"max-w-3xl text-lg text-muted-foreground leading-8",children:"Use ContractSpec as the canonical translation contract layer, then resolve and format messages through a framework-independent runtime. i18next is supported as an optional downstream adapter, not as the source of truth."})]}),t(n,{className:"space-y-4",children:[e(c,{className:"font-bold text-2xl",children:"Install the runtime"}),e(U,{package:d}),t(i,{className:"text-muted-foreground",children:[e(o,{children:"Add "}),e(p,{children:"i18next"}),t(o,{children:[" ","only when an app imports the adapter subpath. Core server, React, React Native, CLI, and test code can use the runtime without loading i18next."]})]})]}),e(y,{className:"grid gap-4 md:grid-cols-3",children:b.map((a)=>t(n,{className:"card-subtle space-y-2 p-5",children:[e(D,{className:"font-semibold text-lg",children:a.title}),e(i,{className:"text-muted-foreground text-sm leading-7",children:a.body})]},a.title))}),t(n,{className:"space-y-4",children:[e(c,{className:"font-bold text-2xl",children:"Use the ContractSpec runtime"}),t(i,{className:"text-muted-foreground",children:[e(o,{children:"The runtime consumes canonical "}),e(p,{children:"TranslationSpec[]"}),t(o,{children:[" ","catalogs, supports BCP 47 tags such as en-US, ar-EG, and zh-Hans, and delegates ICU parsing/formatting to a mature formatter engine instead of a custom parser."]})]}),e(s,{language:"typescript",code:u})]}),t(n,{className:"space-y-4",children:[e(c,{className:"font-bold text-2xl",children:"Project to i18next when needed"}),t(i,{className:"text-muted-foreground",children:[e(o,{children:"Import from "}),e(p,{children:"@contractspec/lib.translation-runtime/i18next"}),t(o,{children:[" ","to export resources by locale, namespace, and message key. The namespace defaults to the stable bundle key, dotted message keys stay flat with keySeparator false, and metadata remains in a sidecar manifest."]})]}),e(s,{language:"typescript",code:m})]}),t(n,{className:"space-y-4",children:[e(c,{className:"font-bold text-2xl",children:"SSR, streaming, and hydration"}),e(i,{className:"text-muted-foreground",children:"Negotiate locale on the server, preload catalogs needed for streamed content, and hydrate the client from the same serialized state. Never let client-only language detection choose a different locale after the server has rendered."}),e(s,{language:"typescript",code:h})]}),t(n,{className:"space-y-4",children:[e(c,{className:"font-bold text-2xl",children:"Production checklist"}),e(w,{className:"list-disc space-y-2 pl-6 text-muted-foreground",children:g.map((a)=>e(C,{children:a},a))})]}),t(n,{className:"space-y-4 rounded-xl border border-border p-6",children:[e(c,{className:"font-bold text-2xl",children:"Agent implementation prompt"}),e(i,{className:"text-muted-foreground",children:"Use this prompt when asking an agent to wire translations into a web, server, or React Native surface without losing ContractSpec ownership."}),e(s,{language:"markdown",code:f})]}),t(y,{className:"flex flex-wrap items-center gap-4 pt-4",children:[e(I,{href:"/docs/libraries/contracts",className:"btn-ghost",children:e(o,{children:"Translation contracts"})}),t(I,{href:"/docs/libraries/design-system",className:"btn-primary",children:[e(o,{children:"Design-system integration"}),e(K,{size:16})]})]})]})}export{G as LibrariesTranslationRuntimePage};
|