@contractspec/bundle.library 3.9.7 → 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 +186 -174
- package/CHANGELOG.md +96 -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 +117 -6
- package/dist/components/docs/getting-started/index.js +130 -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 +1195 -276
- package/dist/components/docs/libraries/LibrariesApplicationShellPage.content.d.ts +33 -0
- package/dist/components/docs/libraries/LibrariesApplicationShellPage.content.js +236 -0
- package/dist/components/docs/libraries/LibrariesApplicationShellPage.d.ts +1 -0
- package/dist/components/docs/libraries/LibrariesApplicationShellPage.js +236 -0
- package/dist/components/docs/libraries/LibrariesDataViewsPage.js +130 -6
- package/dist/components/docs/libraries/LibrariesDesignSystemPage.js +102 -3
- 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 +2 -0
- package/dist/components/docs/libraries/index.js +616 -64
- package/dist/components/docs/specs/SpecsDataViewsPage.js +85 -3
- package/dist/components/docs/specs/index.js +96 -14
- package/dist/index.js +1206 -287
- 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 +117 -6
- package/dist/node/components/docs/getting-started/index.js +130 -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 +1195 -276
- package/dist/node/components/docs/libraries/LibrariesApplicationShellPage.content.js +235 -0
- package/dist/node/components/docs/libraries/LibrariesApplicationShellPage.js +235 -0
- package/dist/node/components/docs/libraries/LibrariesDataViewsPage.js +130 -6
- package/dist/node/components/docs/libraries/LibrariesDesignSystemPage.js +102 -3
- 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 +616 -64
- package/dist/node/components/docs/specs/SpecsDataViewsPage.js +85 -3
- package/dist/node/components/docs/specs/index.js +96 -14
- package/dist/node/index.js +1206 -287
- package/package.json +98 -26
- package/src/components/docs/docsManifest.test.ts +87 -0
- package/src/components/docs/docsManifest.ts +98 -1
- package/src/components/docs/generated/docs-index.notifications.json +7 -7
- package/src/components/docs/getting-started/DataViewTutorialPage.tsx +217 -47
- 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 +283 -0
- package/src/components/docs/libraries/LibrariesApplicationShellPage.tsx +145 -0
- package/src/components/docs/libraries/LibrariesDataViewsPage.tsx +278 -54
- package/src/components/docs/libraries/LibrariesDesignSystemPage.tsx +244 -0
- package/src/components/docs/libraries/LibrariesOverviewPage.tsx +13 -1
- 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 +2 -0
- package/src/components/docs/specs/SpecsDataViewsPage.tsx +278 -116
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { CodeBlock, InstallCommand } from '@contractspec/lib.design-system';
|
|
2
|
+
import { HStack, VStack } from '@contractspec/lib.design-system/layout';
|
|
3
|
+
import { List, ListItem } from '@contractspec/lib.design-system/list';
|
|
4
|
+
import {
|
|
5
|
+
Code,
|
|
6
|
+
H1,
|
|
7
|
+
H2,
|
|
8
|
+
H3,
|
|
9
|
+
P,
|
|
10
|
+
Text,
|
|
11
|
+
} from '@contractspec/lib.design-system/typography';
|
|
12
|
+
import Link from '@contractspec/lib.ui-link';
|
|
13
|
+
import { ChevronRight } from 'lucide-react';
|
|
14
|
+
import {
|
|
15
|
+
i18nextAdapterExample,
|
|
16
|
+
ssrHydrationExample,
|
|
17
|
+
translationRuntimeChecks,
|
|
18
|
+
translationRuntimeExample,
|
|
19
|
+
translationRuntimeInstall,
|
|
20
|
+
translationRuntimeLayers,
|
|
21
|
+
translationRuntimePrompt,
|
|
22
|
+
} from './LibrariesTranslationRuntimePage.content';
|
|
23
|
+
|
|
24
|
+
export function LibrariesTranslationRuntimePage() {
|
|
25
|
+
return (
|
|
26
|
+
<VStack className="space-y-8">
|
|
27
|
+
<VStack className="space-y-4">
|
|
28
|
+
<Text className="editorial-kicker">Runtime and adapters</Text>
|
|
29
|
+
<H1 className="font-serif text-4xl tracking-[-0.04em] md:text-5xl">
|
|
30
|
+
Translation runtime and i18next adapter
|
|
31
|
+
</H1>
|
|
32
|
+
<P className="max-w-3xl text-lg text-muted-foreground leading-8">
|
|
33
|
+
Use ContractSpec as the canonical translation contract layer, then
|
|
34
|
+
resolve and format messages through a framework-independent runtime.
|
|
35
|
+
i18next is supported as an optional downstream adapter, not as the
|
|
36
|
+
source of truth.
|
|
37
|
+
</P>
|
|
38
|
+
</VStack>
|
|
39
|
+
|
|
40
|
+
<VStack className="space-y-4">
|
|
41
|
+
<H2 className="font-bold text-2xl">Install the runtime</H2>
|
|
42
|
+
<InstallCommand package={translationRuntimeInstall} />
|
|
43
|
+
<P className="text-muted-foreground">
|
|
44
|
+
<Text>Add </Text>
|
|
45
|
+
<Code>i18next</Code>
|
|
46
|
+
<Text>
|
|
47
|
+
{' '}
|
|
48
|
+
only when an app imports the adapter subpath. Core server, React,
|
|
49
|
+
React Native, CLI, and test code can use the runtime without loading
|
|
50
|
+
i18next.
|
|
51
|
+
</Text>
|
|
52
|
+
</P>
|
|
53
|
+
</VStack>
|
|
54
|
+
|
|
55
|
+
<HStack className="grid gap-4 md:grid-cols-3">
|
|
56
|
+
{translationRuntimeLayers.map((item) => (
|
|
57
|
+
<VStack className="card-subtle space-y-2 p-5" key={item.title}>
|
|
58
|
+
<H3 className="font-semibold text-lg">{item.title}</H3>
|
|
59
|
+
<P className="text-muted-foreground text-sm leading-7">
|
|
60
|
+
{item.body}
|
|
61
|
+
</P>
|
|
62
|
+
</VStack>
|
|
63
|
+
))}
|
|
64
|
+
</HStack>
|
|
65
|
+
|
|
66
|
+
<VStack className="space-y-4">
|
|
67
|
+
<H2 className="font-bold text-2xl">Use the ContractSpec runtime</H2>
|
|
68
|
+
<P className="text-muted-foreground">
|
|
69
|
+
<Text>The runtime consumes canonical </Text>
|
|
70
|
+
<Code>TranslationSpec[]</Code>
|
|
71
|
+
<Text>
|
|
72
|
+
{' '}
|
|
73
|
+
catalogs, supports BCP 47 tags such as en-US, ar-EG, and zh-Hans,
|
|
74
|
+
and delegates ICU parsing/formatting to a mature formatter engine
|
|
75
|
+
instead of a custom parser.
|
|
76
|
+
</Text>
|
|
77
|
+
</P>
|
|
78
|
+
<CodeBlock language="typescript" code={translationRuntimeExample} />
|
|
79
|
+
</VStack>
|
|
80
|
+
|
|
81
|
+
<VStack className="space-y-4">
|
|
82
|
+
<H2 className="font-bold text-2xl">Project to i18next when needed</H2>
|
|
83
|
+
<P className="text-muted-foreground">
|
|
84
|
+
<Text>Import from </Text>
|
|
85
|
+
<Code>@contractspec/lib.translation-runtime/i18next</Code>
|
|
86
|
+
<Text>
|
|
87
|
+
{' '}
|
|
88
|
+
to export resources by locale, namespace, and message key. The
|
|
89
|
+
namespace defaults to the stable bundle key, dotted message keys
|
|
90
|
+
stay flat with keySeparator false, and metadata remains in a sidecar
|
|
91
|
+
manifest.
|
|
92
|
+
</Text>
|
|
93
|
+
</P>
|
|
94
|
+
<CodeBlock language="typescript" code={i18nextAdapterExample} />
|
|
95
|
+
</VStack>
|
|
96
|
+
|
|
97
|
+
<VStack className="space-y-4">
|
|
98
|
+
<H2 className="font-bold text-2xl">SSR, streaming, and hydration</H2>
|
|
99
|
+
<P className="text-muted-foreground">
|
|
100
|
+
Negotiate locale on the server, preload catalogs needed for streamed
|
|
101
|
+
content, and hydrate the client from the same serialized state. Never
|
|
102
|
+
let client-only language detection choose a different locale after the
|
|
103
|
+
server has rendered.
|
|
104
|
+
</P>
|
|
105
|
+
<CodeBlock language="typescript" code={ssrHydrationExample} />
|
|
106
|
+
</VStack>
|
|
107
|
+
|
|
108
|
+
<VStack className="space-y-4">
|
|
109
|
+
<H2 className="font-bold text-2xl">Production checklist</H2>
|
|
110
|
+
<List className="list-disc space-y-2 pl-6 text-muted-foreground">
|
|
111
|
+
{translationRuntimeChecks.map((item) => (
|
|
112
|
+
<ListItem key={item}>{item}</ListItem>
|
|
113
|
+
))}
|
|
114
|
+
</List>
|
|
115
|
+
</VStack>
|
|
116
|
+
|
|
117
|
+
<VStack className="space-y-4 rounded-xl border border-border p-6">
|
|
118
|
+
<H2 className="font-bold text-2xl">Agent implementation prompt</H2>
|
|
119
|
+
<P className="text-muted-foreground">
|
|
120
|
+
Use this prompt when asking an agent to wire translations into a web,
|
|
121
|
+
server, or React Native surface without losing ContractSpec ownership.
|
|
122
|
+
</P>
|
|
123
|
+
<CodeBlock language="markdown" code={translationRuntimePrompt} />
|
|
124
|
+
</VStack>
|
|
125
|
+
|
|
126
|
+
<HStack className="flex flex-wrap items-center gap-4 pt-4">
|
|
127
|
+
<Link href="/docs/libraries/contracts" className="btn-ghost">
|
|
128
|
+
<Text>Translation contracts</Text>
|
|
129
|
+
</Link>
|
|
130
|
+
<Link href="/docs/libraries/design-system" className="btn-primary">
|
|
131
|
+
<Text>Design-system integration</Text>
|
|
132
|
+
<ChevronRight size={16} />
|
|
133
|
+
</Link>
|
|
134
|
+
</HStack>
|
|
135
|
+
</VStack>
|
|
136
|
+
);
|
|
137
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { LibrariesAccessibilityPage } from './LibrariesAccessibilityPage';
|
|
2
2
|
export { LibrariesAiAgentPage } from './LibrariesAiAgentPage';
|
|
3
3
|
export { LibrariesAnalyticsPage } from './LibrariesAnalyticsPage';
|
|
4
|
+
export { LibrariesApplicationShellPage } from './LibrariesApplicationShellPage';
|
|
4
5
|
export { LibrariesContentGenPage } from './LibrariesContentGenPage';
|
|
5
6
|
export { LibrariesContractsPage } from './LibrariesContractsPage';
|
|
6
7
|
export { LibrariesCostTrackingPage } from './LibrariesCostTrackingPage';
|
|
@@ -23,6 +24,7 @@ export { LibrariesSchemaPage } from './LibrariesSchemaPage';
|
|
|
23
24
|
export { LibrariesSLOPage } from './LibrariesSLOPage';
|
|
24
25
|
export { LibrariesSupportBotPage } from './LibrariesSupportBotPage';
|
|
25
26
|
export { LibrariesTestingPage } from './LibrariesTestingPage';
|
|
27
|
+
export { LibrariesTranslationRuntimePage } from './LibrariesTranslationRuntimePage';
|
|
26
28
|
export { LibrariesUIKitPage } from './LibrariesUIKitPage';
|
|
27
29
|
export { LibrariesUIKitWebPage } from './LibrariesUIKitWebPage';
|
|
28
30
|
export { LibrariesWorkflowComposerPage } from './LibrariesWorkflowComposerPage';
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
import { CodeBlock } from '@contractspec/lib.design-system';
|
|
2
|
+
import { HStack, VStack } from '@contractspec/lib.design-system/layout';
|
|
3
|
+
import { List, ListItem } from '@contractspec/lib.design-system/list';
|
|
4
|
+
import {
|
|
5
|
+
Code,
|
|
6
|
+
H1,
|
|
7
|
+
H2,
|
|
8
|
+
H3,
|
|
9
|
+
P,
|
|
10
|
+
Text,
|
|
11
|
+
} from '@contractspec/lib.design-system/typography';
|
|
1
12
|
import Link from '@contractspec/lib.ui-link';
|
|
2
13
|
import { ChevronRight } from 'lucide-react';
|
|
3
14
|
|
|
@@ -45,7 +56,76 @@ export const DataGridShowcaseDataView = defineDataView({
|
|
|
45
56
|
{ key: 'account', label: 'Account', dataPath: 'account', sortable: true },
|
|
46
57
|
{ key: 'owner', label: 'Owner', dataPath: 'owner', sortable: true },
|
|
47
58
|
{ key: 'status', label: 'Status', dataPath: 'status', sortable: true },
|
|
48
|
-
{
|
|
59
|
+
{
|
|
60
|
+
key: 'arr',
|
|
61
|
+
label: 'ARR',
|
|
62
|
+
dataPath: 'arr',
|
|
63
|
+
sortable: true,
|
|
64
|
+
format: { type: 'currency', currency: 'USD', rounded: true },
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
key: 'healthScore',
|
|
68
|
+
label: 'Health score',
|
|
69
|
+
dataPath: 'healthScore',
|
|
70
|
+
format: { type: 'percent', valueScale: 'fraction', maximumFractionDigits: 1 },
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
key: 'lastActivityAt',
|
|
74
|
+
label: 'Last activity',
|
|
75
|
+
dataPath: 'lastActivityAt',
|
|
76
|
+
format: { type: 'datetime', dateStyle: 'medium', timeStyle: 'short' },
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
key: 'notes',
|
|
80
|
+
label: 'Notes',
|
|
81
|
+
dataPath: 'notes',
|
|
82
|
+
visibility: { minDataDepth: 'detailed' },
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
collection: {
|
|
86
|
+
viewModes: {
|
|
87
|
+
defaultMode: 'table',
|
|
88
|
+
allowedModes: ['list', 'grid', 'table'],
|
|
89
|
+
},
|
|
90
|
+
pagination: {
|
|
91
|
+
pageSize: 25,
|
|
92
|
+
pageSizeOptions: [10, 25, 50],
|
|
93
|
+
},
|
|
94
|
+
toolbar: {
|
|
95
|
+
search: true,
|
|
96
|
+
viewMode: true,
|
|
97
|
+
filters: true,
|
|
98
|
+
density: true,
|
|
99
|
+
dataDepth: true,
|
|
100
|
+
},
|
|
101
|
+
density: 'comfortable',
|
|
102
|
+
dataDepth: 'standard',
|
|
103
|
+
personalization: {
|
|
104
|
+
enabled: true,
|
|
105
|
+
persist: {
|
|
106
|
+
viewMode: true,
|
|
107
|
+
density: true,
|
|
108
|
+
dataDepth: true,
|
|
109
|
+
pageSize: true,
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
filters: [
|
|
114
|
+
{ key: 'status', label: 'Status', field: 'status', type: 'enum' },
|
|
115
|
+
{
|
|
116
|
+
key: 'arr',
|
|
117
|
+
label: 'ARR',
|
|
118
|
+
field: 'arr',
|
|
119
|
+
type: 'currency',
|
|
120
|
+
valueMode: 'range',
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
key: 'lastActivityAt',
|
|
124
|
+
label: 'Last activity',
|
|
125
|
+
field: 'lastActivityAt',
|
|
126
|
+
type: 'datetime',
|
|
127
|
+
valueMode: 'range',
|
|
128
|
+
},
|
|
49
129
|
],
|
|
50
130
|
},
|
|
51
131
|
});`;
|
|
@@ -58,163 +138,245 @@ export const DataGridShowcaseDataView = defineDataView({
|
|
|
58
138
|
|
|
59
139
|
export function SpecsDataViewsPage() {
|
|
60
140
|
return (
|
|
61
|
-
<
|
|
62
|
-
<
|
|
63
|
-
<
|
|
64
|
-
<
|
|
65
|
-
A <
|
|
66
|
-
filtered, sorted, and presented to users.
|
|
67
|
-
optimized database queries and serve list
|
|
68
|
-
search interfaces while respecting policy
|
|
69
|
-
|
|
70
|
-
|
|
141
|
+
<VStack className="space-y-8">
|
|
142
|
+
<VStack className="space-y-4">
|
|
143
|
+
<H1 className="font-bold text-4xl">DataViews</H1>
|
|
144
|
+
<P className="text-muted-foreground">
|
|
145
|
+
A <Text className="font-semibold">DataViewSpec</Text> describes how
|
|
146
|
+
data should be queried, filtered, sorted, and presented to users.
|
|
147
|
+
Runtime adapters execute optimized database queries and serve list
|
|
148
|
+
views, detail views, and search interfaces while respecting policy
|
|
149
|
+
constraints.
|
|
150
|
+
</P>
|
|
151
|
+
</VStack>
|
|
71
152
|
|
|
72
|
-
<
|
|
73
|
-
<
|
|
74
|
-
<
|
|
75
|
-
<
|
|
76
|
-
<
|
|
77
|
-
<
|
|
153
|
+
<VStack className="space-y-4">
|
|
154
|
+
<H2 className="font-bold text-2xl">Core concepts</H2>
|
|
155
|
+
<VStack className="space-y-3">
|
|
156
|
+
<VStack>
|
|
157
|
+
<H3 className="font-semibold text-lg">Data sources</H3>
|
|
158
|
+
<P className="text-muted-foreground">
|
|
78
159
|
A DataView connects to one or more data sources—databases, APIs,
|
|
79
160
|
or other capabilities. You specify the source and the fields you
|
|
80
161
|
want to expose.
|
|
81
|
-
</
|
|
82
|
-
</
|
|
83
|
-
<
|
|
84
|
-
<
|
|
85
|
-
<
|
|
162
|
+
</P>
|
|
163
|
+
</VStack>
|
|
164
|
+
<VStack>
|
|
165
|
+
<H3 className="font-semibold text-lg">Filtering</H3>
|
|
166
|
+
<P className="text-muted-foreground">
|
|
86
167
|
Define filters that users can apply to narrow down results.
|
|
87
|
-
Filters
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
</
|
|
91
|
-
</
|
|
92
|
-
<
|
|
93
|
-
<
|
|
94
|
-
<
|
|
168
|
+
Filters are typed as search, enum, number, percent, currency,
|
|
169
|
+
date, time, datetime, duration, or boolean so renderers and query
|
|
170
|
+
helpers can validate values before execution.
|
|
171
|
+
</P>
|
|
172
|
+
</VStack>
|
|
173
|
+
<VStack>
|
|
174
|
+
<H3 className="font-semibold text-lg">Sorting</H3>
|
|
175
|
+
<P className="text-muted-foreground">
|
|
95
176
|
Specify which fields can be sorted and the default sort order.
|
|
96
177
|
ContractSpec generates efficient database queries with proper
|
|
97
178
|
indexes.
|
|
98
|
-
</
|
|
99
|
-
</
|
|
100
|
-
<
|
|
101
|
-
<
|
|
102
|
-
<
|
|
179
|
+
</P>
|
|
180
|
+
</VStack>
|
|
181
|
+
<VStack>
|
|
182
|
+
<H3 className="font-semibold text-lg">Pagination</H3>
|
|
183
|
+
<P className="text-muted-foreground">
|
|
103
184
|
DataViews automatically support pagination to handle large
|
|
104
185
|
datasets. You can configure page size limits and cursor-based or
|
|
105
186
|
offset-based pagination.
|
|
106
|
-
</
|
|
107
|
-
</
|
|
108
|
-
<
|
|
109
|
-
<
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
187
|
+
</P>
|
|
188
|
+
</VStack>
|
|
189
|
+
<VStack>
|
|
190
|
+
<H3 className="font-semibold text-lg">
|
|
191
|
+
Collection modes and data depth
|
|
192
|
+
</H3>
|
|
193
|
+
<P className="text-muted-foreground">
|
|
194
|
+
List, grid, and table views can share a single{' '}
|
|
195
|
+
<Code>view.collection</Code> contract. It declares allowed view
|
|
196
|
+
modes, toolbar controls, page-size defaults, density, data depth,
|
|
197
|
+
and persistence hints. Fields can use{' '}
|
|
198
|
+
<Code>visibility.minDataDepth</Code> so summary views stay light
|
|
199
|
+
while detailed views expose richer context.
|
|
200
|
+
</P>
|
|
201
|
+
</VStack>
|
|
202
|
+
<VStack>
|
|
203
|
+
<H3 className="font-semibold text-lg">Personalization hints</H3>
|
|
204
|
+
<P className="text-muted-foreground">
|
|
205
|
+
The contract layer stays neutral: it can opt into persistence with{' '}
|
|
206
|
+
<Code>view.collection.personalization</Code>, but it does not
|
|
207
|
+
import the personalization runtime. Host apps resolve preferences
|
|
208
|
+
and behavior insights into renderer props.
|
|
209
|
+
</P>
|
|
210
|
+
</VStack>
|
|
211
|
+
</VStack>
|
|
212
|
+
</VStack>
|
|
117
213
|
|
|
118
|
-
<
|
|
119
|
-
<
|
|
120
|
-
<
|
|
214
|
+
<VStack className="space-y-4">
|
|
215
|
+
<H2 className="font-bold text-2xl">Example DataViewSpec</H2>
|
|
216
|
+
<P className="text-muted-foreground">
|
|
121
217
|
Here is the canonical table contract used by the live{' '}
|
|
122
218
|
<Link
|
|
123
219
|
href="/docs/examples/data-grid-showcase"
|
|
124
220
|
className="text-[color:var(--rust)] underline underline-offset-4"
|
|
125
221
|
>
|
|
126
|
-
Data Grid Showcase
|
|
222
|
+
<Text>Data Grid Showcase</Text>
|
|
127
223
|
</Link>
|
|
128
224
|
:
|
|
129
|
-
</
|
|
130
|
-
<
|
|
131
|
-
|
|
132
|
-
</div>
|
|
133
|
-
<p className="text-muted-foreground text-sm">
|
|
225
|
+
</P>
|
|
226
|
+
<CodeBlock language="typescript" code={SPECS_DATAVIEWS_EXAMPLE} />
|
|
227
|
+
<P className="text-muted-foreground text-sm">
|
|
134
228
|
This one contract drives the DataView lane, while the same rows and
|
|
135
229
|
controller also feed the raw web primitive, native-first primitive,
|
|
136
230
|
and composed design-system demos.
|
|
137
|
-
</
|
|
138
|
-
</
|
|
231
|
+
</P>
|
|
232
|
+
</VStack>
|
|
139
233
|
|
|
140
|
-
<
|
|
141
|
-
<
|
|
142
|
-
<
|
|
234
|
+
<VStack className="space-y-4">
|
|
235
|
+
<H2 className="font-bold text-2xl">Policy integration</H2>
|
|
236
|
+
<P className="text-muted-foreground">
|
|
143
237
|
DataViews automatically enforce{' '}
|
|
144
238
|
<Link
|
|
145
239
|
href="/docs/specs/policy"
|
|
146
240
|
className="text-violet-400 hover:text-violet-300"
|
|
147
241
|
>
|
|
148
|
-
PolicySpecs
|
|
242
|
+
<Text>PolicySpecs</Text>
|
|
149
243
|
</Link>
|
|
150
244
|
. If a user doesn't have permission to see certain fields, those
|
|
151
245
|
fields are automatically filtered out or redacted. If a user can only
|
|
152
246
|
see their own data, the query is automatically scoped.
|
|
153
|
-
</
|
|
154
|
-
<
|
|
247
|
+
</P>
|
|
248
|
+
<P className="text-muted-foreground">
|
|
155
249
|
This means you define the data view once, and it works correctly for
|
|
156
250
|
all users based on their permissions—no need to write separate queries
|
|
157
251
|
for different roles.
|
|
158
|
-
</
|
|
159
|
-
</
|
|
252
|
+
</P>
|
|
253
|
+
</VStack>
|
|
254
|
+
|
|
255
|
+
<VStack className="space-y-4">
|
|
256
|
+
<H2 className="font-bold text-2xl">Personalized Rendering Pattern</H2>
|
|
257
|
+
<P className="text-muted-foreground">
|
|
258
|
+
To personalize a DataView, keep the spec declarative and resolve
|
|
259
|
+
user-specific defaults at the app boundary. Use{' '}
|
|
260
|
+
<Code>resolveDataViewPreferences</Code> from{' '}
|
|
261
|
+
<Code>@contractspec/lib.personalization/data-view-preferences</Code>
|
|
262
|
+
to compute <Code>viewMode</Code>, <Code>density</Code>,{' '}
|
|
263
|
+
<Code>dataDepth</Code>, and <Code>pageSize</Code>. Pass those values
|
|
264
|
+
to <Code>DataViewRenderer</Code> as controlled or default props, then
|
|
265
|
+
record UI changes with <Code>trackDataViewInteraction</Code>.
|
|
266
|
+
</P>
|
|
267
|
+
<CodeBlock
|
|
268
|
+
language="tsx"
|
|
269
|
+
code={`const resolved = resolveDataViewPreferences({
|
|
270
|
+
spec: DataGridShowcaseDataView,
|
|
271
|
+
preferences: profile.canonical,
|
|
272
|
+
insights,
|
|
273
|
+
record: savedPreference,
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
<DataViewRenderer
|
|
277
|
+
spec={DataGridShowcaseDataView}
|
|
278
|
+
items={rows}
|
|
279
|
+
defaultViewMode={resolved.viewMode}
|
|
280
|
+
defaultDensity={resolved.density}
|
|
281
|
+
defaultDataDepth={resolved.dataDepth}
|
|
282
|
+
/>;`}
|
|
283
|
+
/>
|
|
284
|
+
</VStack>
|
|
160
285
|
|
|
161
|
-
<
|
|
162
|
-
<
|
|
163
|
-
<
|
|
286
|
+
<VStack className="space-y-4">
|
|
287
|
+
<H2 className="font-bold text-2xl">Served outputs</H2>
|
|
288
|
+
<P className="text-muted-foreground">
|
|
164
289
|
From a DataViewSpec, ContractSpec serves:
|
|
165
|
-
</
|
|
166
|
-
<
|
|
167
|
-
<
|
|
168
|
-
<
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
</
|
|
179
|
-
<
|
|
180
|
-
<
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
290
|
+
</P>
|
|
291
|
+
<List className="list-inside list-disc space-y-2 text-muted-foreground">
|
|
292
|
+
<ListItem>
|
|
293
|
+
<Text>
|
|
294
|
+
<Text className="font-semibold">Database queries</Text> –
|
|
295
|
+
Optimized SQL or NoSQL queries executed at runtime
|
|
296
|
+
</Text>
|
|
297
|
+
</ListItem>
|
|
298
|
+
<ListItem>
|
|
299
|
+
<Text>
|
|
300
|
+
<Text className="font-semibold">API endpoints</Text> – RESTful or
|
|
301
|
+
GraphQL endpoints for fetching data
|
|
302
|
+
</Text>
|
|
303
|
+
</ListItem>
|
|
304
|
+
<ListItem>
|
|
305
|
+
<Text>
|
|
306
|
+
<Text className="font-semibold">UI components</Text> – List views,
|
|
307
|
+
tables, cards, and detail views
|
|
308
|
+
</Text>
|
|
309
|
+
</ListItem>
|
|
310
|
+
<ListItem>
|
|
311
|
+
<Text>
|
|
312
|
+
<Text className="font-semibold">Personalized defaults</Text> –
|
|
313
|
+
Plain renderer props for preferred mode, density, data depth, and
|
|
314
|
+
page size
|
|
315
|
+
</Text>
|
|
316
|
+
</ListItem>
|
|
317
|
+
<ListItem>
|
|
318
|
+
<Text>
|
|
319
|
+
<Text className="font-semibold">Search interfaces</Text> –
|
|
320
|
+
Full-text search with autocomplete
|
|
321
|
+
</Text>
|
|
322
|
+
</ListItem>
|
|
323
|
+
<ListItem>
|
|
324
|
+
<Text>
|
|
325
|
+
<Text className="font-semibold">Export functions</Text> – CSV,
|
|
326
|
+
JSON, or Excel exports
|
|
327
|
+
</Text>
|
|
328
|
+
</ListItem>
|
|
329
|
+
</List>
|
|
330
|
+
</VStack>
|
|
188
331
|
|
|
189
|
-
<
|
|
190
|
-
<
|
|
191
|
-
<
|
|
192
|
-
<
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
</
|
|
203
|
-
<
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
332
|
+
<VStack className="space-y-4">
|
|
333
|
+
<H2 className="font-bold text-2xl">Best practices</H2>
|
|
334
|
+
<List className="list-inside list-disc space-y-2 text-muted-foreground">
|
|
335
|
+
<ListItem>
|
|
336
|
+
<Text>
|
|
337
|
+
Only expose fields that users actually need—this improves
|
|
338
|
+
performance and security.
|
|
339
|
+
</Text>
|
|
340
|
+
</ListItem>
|
|
341
|
+
<ListItem>
|
|
342
|
+
<Text>
|
|
343
|
+
Use appropriate indexes for sortable and filterable fields.
|
|
344
|
+
</Text>
|
|
345
|
+
</ListItem>
|
|
346
|
+
<ListItem>
|
|
347
|
+
<Text>
|
|
348
|
+
Set reasonable pagination limits to prevent performance issues.
|
|
349
|
+
</Text>
|
|
350
|
+
</ListItem>
|
|
351
|
+
<ListItem>
|
|
352
|
+
<Text>
|
|
353
|
+
Use <Code>allowedModes</Code> to constrain mode switching to
|
|
354
|
+
layouts that the fields and row actions can support.
|
|
355
|
+
</Text>
|
|
356
|
+
</ListItem>
|
|
357
|
+
<ListItem>
|
|
358
|
+
<Text>
|
|
359
|
+
Store preferences only for dimensions enabled by{' '}
|
|
360
|
+
<Code>view.collection.personalization.persist</Code>.
|
|
361
|
+
</Text>
|
|
362
|
+
</ListItem>
|
|
363
|
+
<ListItem>
|
|
364
|
+
<Text>
|
|
365
|
+
Test DataViews with realistic data volumes to ensure they perform
|
|
366
|
+
well.
|
|
367
|
+
</Text>
|
|
368
|
+
</ListItem>
|
|
369
|
+
</List>
|
|
370
|
+
</VStack>
|
|
209
371
|
|
|
210
|
-
<
|
|
372
|
+
<HStack className="items-center gap-4 pt-4">
|
|
211
373
|
<Link href="/docs/specs/capabilities" className="btn-ghost">
|
|
212
|
-
Previous: Capabilities
|
|
374
|
+
<Text>Previous: Capabilities</Text>
|
|
213
375
|
</Link>
|
|
214
376
|
<Link href="/docs/specs/workflows" className="btn-primary">
|
|
215
|
-
Next: Workflows <ChevronRight size={16} />
|
|
377
|
+
<Text>Next: Workflows</Text> <ChevronRight size={16} />
|
|
216
378
|
</Link>
|
|
217
|
-
</
|
|
218
|
-
</
|
|
379
|
+
</HStack>
|
|
380
|
+
</VStack>
|
|
219
381
|
);
|
|
220
382
|
}
|