@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,37 +1,170 @@
|
|
|
1
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';
|
|
2
12
|
import Link from '@contractspec/lib.ui-link';
|
|
3
13
|
import { ChevronRight } from 'lucide-react';
|
|
4
14
|
|
|
15
|
+
const COLLECTION_DATAVIEW_EXAMPLE = `import { defineDataView } from '@contractspec/lib.contracts-spec/data-views';
|
|
16
|
+
|
|
17
|
+
export const AccountsDataView = defineDataView({
|
|
18
|
+
meta: {
|
|
19
|
+
key: 'crm.accounts',
|
|
20
|
+
version: '1.0.0',
|
|
21
|
+
title: 'Accounts',
|
|
22
|
+
description: 'Customer account workspace',
|
|
23
|
+
domain: 'crm',
|
|
24
|
+
entity: 'account',
|
|
25
|
+
owners: ['@crm'],
|
|
26
|
+
tags: ['crm', 'accounts'],
|
|
27
|
+
stability: 'stable',
|
|
28
|
+
},
|
|
29
|
+
source: {
|
|
30
|
+
primary: { key: 'crm.accounts.list', version: '1.0.0' },
|
|
31
|
+
},
|
|
32
|
+
view: {
|
|
33
|
+
kind: 'table',
|
|
34
|
+
fields: [
|
|
35
|
+
{ key: 'name', label: 'Name', dataPath: 'name', sortable: true },
|
|
36
|
+
{ key: 'owner', label: 'Owner', dataPath: 'owner' },
|
|
37
|
+
{ key: 'arr', label: 'ARR', dataPath: 'arr', format: { type: 'currency', currency: 'EUR' } },
|
|
38
|
+
{
|
|
39
|
+
key: 'internalNotes',
|
|
40
|
+
label: 'Internal notes',
|
|
41
|
+
dataPath: 'internalNotes',
|
|
42
|
+
visibility: { minDataDepth: 'detailed' },
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
columns: [
|
|
46
|
+
{ field: 'name' },
|
|
47
|
+
{ field: 'owner' },
|
|
48
|
+
{ field: 'arr' },
|
|
49
|
+
{ field: 'internalNotes' },
|
|
50
|
+
],
|
|
51
|
+
collection: {
|
|
52
|
+
viewModes: {
|
|
53
|
+
defaultMode: 'table',
|
|
54
|
+
allowedModes: ['list', 'grid', 'table'],
|
|
55
|
+
},
|
|
56
|
+
pagination: {
|
|
57
|
+
pageSize: 25,
|
|
58
|
+
pageSizeOptions: [10, 25, 50],
|
|
59
|
+
},
|
|
60
|
+
toolbar: {
|
|
61
|
+
search: true,
|
|
62
|
+
viewMode: true,
|
|
63
|
+
filters: true,
|
|
64
|
+
density: true,
|
|
65
|
+
dataDepth: true,
|
|
66
|
+
},
|
|
67
|
+
density: 'comfortable',
|
|
68
|
+
dataDepth: 'standard',
|
|
69
|
+
personalization: {
|
|
70
|
+
enabled: true,
|
|
71
|
+
persist: {
|
|
72
|
+
viewMode: true,
|
|
73
|
+
density: true,
|
|
74
|
+
dataDepth: true,
|
|
75
|
+
pageSize: true,
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
});`;
|
|
81
|
+
|
|
82
|
+
const PERSONALIZED_RENDERER_EXAMPLE = `import { DataViewRenderer } from '@contractspec/lib.design-system';
|
|
83
|
+
import { resolveDataViewPreferences } from '@contractspec/lib.personalization/data-view-preferences';
|
|
84
|
+
|
|
85
|
+
const resolved = resolveDataViewPreferences({
|
|
86
|
+
spec: AccountsDataView,
|
|
87
|
+
preferences: profile.canonical,
|
|
88
|
+
insights,
|
|
89
|
+
record: savedDataViewPreference,
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
<DataViewRenderer
|
|
93
|
+
spec={AccountsDataView}
|
|
94
|
+
items={accounts}
|
|
95
|
+
defaultViewMode={resolved.viewMode}
|
|
96
|
+
defaultDensity={resolved.density}
|
|
97
|
+
defaultDataDepth={resolved.dataDepth}
|
|
98
|
+
pagination={{
|
|
99
|
+
page,
|
|
100
|
+
pageSize: resolved.pageSize ?? 25,
|
|
101
|
+
total,
|
|
102
|
+
}}
|
|
103
|
+
onViewModeChange={(viewMode) => {
|
|
104
|
+
tracker.trackDataViewInteraction({
|
|
105
|
+
dataViewKey: AccountsDataView.meta.key,
|
|
106
|
+
dataViewVersion: AccountsDataView.meta.version,
|
|
107
|
+
action: 'view_mode_changed',
|
|
108
|
+
viewMode,
|
|
109
|
+
});
|
|
110
|
+
}}
|
|
111
|
+
onDensityChange={(density) => {
|
|
112
|
+
tracker.trackDataViewInteraction({
|
|
113
|
+
dataViewKey: AccountsDataView.meta.key,
|
|
114
|
+
action: 'density_changed',
|
|
115
|
+
density,
|
|
116
|
+
});
|
|
117
|
+
}}
|
|
118
|
+
onDataDepthChange={(dataDepth) => {
|
|
119
|
+
tracker.trackDataViewInteraction({
|
|
120
|
+
dataViewKey: AccountsDataView.meta.key,
|
|
121
|
+
action: 'data_depth_changed',
|
|
122
|
+
dataDepth,
|
|
123
|
+
});
|
|
124
|
+
}}
|
|
125
|
+
/>;
|
|
126
|
+
`;
|
|
127
|
+
|
|
128
|
+
const DATAVIEW_AGENT_PROMPT = `Implement a production DataView for <entity>.
|
|
129
|
+
|
|
130
|
+
Requirements:
|
|
131
|
+
- 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.
|
|
132
|
+
- Mark fields that should only appear in richer experiences with visibility.minDataDepth.
|
|
133
|
+
- Render it with DataViewRenderer using plain props from resolveDataViewPreferences.
|
|
134
|
+
- Track user interactions with trackDataViewInteraction for view mode, density, data depth, search, filters, sorting, and pagination.
|
|
135
|
+
- Keep @contractspec/lib.design-system independent from @contractspec/lib.personalization.
|
|
136
|
+
- Add focused tests for default resolution, invalid-mode fallback, data-depth projection, and behavior-derived preferred view mode.`;
|
|
137
|
+
|
|
5
138
|
export function LibrariesDataViewsPage() {
|
|
6
139
|
return (
|
|
7
|
-
<
|
|
8
|
-
<
|
|
9
|
-
<
|
|
10
|
-
<
|
|
11
|
-
The <
|
|
12
|
-
<
|
|
140
|
+
<VStack className="space-y-8">
|
|
141
|
+
<VStack className="space-y-4">
|
|
142
|
+
<H1 className="font-bold text-4xl">DataViews Runtime Library</H1>
|
|
143
|
+
<P className="text-lg text-muted-foreground">
|
|
144
|
+
The <Code>@contractspec/lib.contracts-spec/data-views</Code> and{' '}
|
|
145
|
+
<Code>@contractspec/lib.design-system</Code> libraries provide the
|
|
13
146
|
runtime logic and UI components to render DataViews in your
|
|
14
147
|
application.
|
|
15
|
-
</
|
|
16
|
-
</
|
|
148
|
+
</P>
|
|
149
|
+
</VStack>
|
|
17
150
|
|
|
18
|
-
<
|
|
19
|
-
<
|
|
151
|
+
<VStack className="space-y-4">
|
|
152
|
+
<H2 className="font-bold text-2xl">Installation</H2>
|
|
20
153
|
<InstallCommand
|
|
21
154
|
package={[
|
|
22
155
|
'@contractspec/lib.contracts-spec',
|
|
23
156
|
'@contractspec/lib.design-system',
|
|
24
157
|
]}
|
|
25
158
|
/>
|
|
26
|
-
</
|
|
159
|
+
</VStack>
|
|
27
160
|
|
|
28
|
-
<
|
|
29
|
-
<
|
|
30
|
-
<
|
|
161
|
+
<VStack className="space-y-4">
|
|
162
|
+
<H2 className="font-bold text-2xl">DataViewRenderer</H2>
|
|
163
|
+
<P className="text-muted-foreground">
|
|
31
164
|
The primary component for rendering any DataView. It automatically
|
|
32
165
|
selects the correct layout (List, Table, Grid, Detail) based on the
|
|
33
166
|
spec.
|
|
34
|
-
</
|
|
167
|
+
</P>
|
|
35
168
|
|
|
36
169
|
<CodeBlock
|
|
37
170
|
language="tsx"
|
|
@@ -50,51 +183,121 @@ export function UserPage() {
|
|
|
50
183
|
}`}
|
|
51
184
|
/>
|
|
52
185
|
|
|
53
|
-
<
|
|
54
|
-
<
|
|
55
|
-
<
|
|
56
|
-
<
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
<
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
<
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
<
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
186
|
+
<H3 className="font-semibold text-xl">Props</H3>
|
|
187
|
+
<List className="list-disc space-y-2 pl-6 text-muted-foreground">
|
|
188
|
+
<ListItem>
|
|
189
|
+
<Text>
|
|
190
|
+
<Code>spec</Code>: The DataViewSpec definition.
|
|
191
|
+
</Text>
|
|
192
|
+
</ListItem>
|
|
193
|
+
<ListItem>
|
|
194
|
+
<Text>
|
|
195
|
+
<Code>items</Code>: Array of data items to render.
|
|
196
|
+
</Text>
|
|
197
|
+
</ListItem>
|
|
198
|
+
<ListItem>
|
|
199
|
+
<Text>
|
|
200
|
+
<Code>filters</Code>: Current filter state object.
|
|
201
|
+
</Text>
|
|
202
|
+
</ListItem>
|
|
203
|
+
<ListItem>
|
|
204
|
+
<Text>
|
|
205
|
+
<Code>onFilterChange</Code>: Callback when typed filters change.
|
|
206
|
+
Renderers emit <Code>DataViewFilterValue</Code> objects for
|
|
207
|
+
numeric, percent, currency, temporal, duration, and boolean
|
|
208
|
+
filters.
|
|
209
|
+
</Text>
|
|
210
|
+
</ListItem>
|
|
211
|
+
<ListItem>
|
|
212
|
+
<Text>
|
|
213
|
+
<Code>pagination</Code>: Object with <Code>page</Code>,{' '}
|
|
214
|
+
<Code>pageSize</Code>, <Code>total</Code>.
|
|
215
|
+
</Text>
|
|
216
|
+
</ListItem>
|
|
217
|
+
<ListItem>
|
|
218
|
+
<Text>
|
|
219
|
+
<Code>onPageChange</Code>: Callback when page changes.
|
|
220
|
+
</Text>
|
|
221
|
+
</ListItem>
|
|
222
|
+
<ListItem>
|
|
223
|
+
<Text>
|
|
224
|
+
<Code>viewMode</Code> / <Code>defaultViewMode</Code>: Controlled
|
|
225
|
+
or initial collection mode for specs that allow <Code>list</Code>,{' '}
|
|
226
|
+
<Code>grid</Code>, or <Code>table</Code> projections through{' '}
|
|
227
|
+
<Code>view.collection.viewModes</Code>.
|
|
228
|
+
</Text>
|
|
229
|
+
</ListItem>
|
|
230
|
+
<ListItem>
|
|
231
|
+
<Text>
|
|
232
|
+
<Code>density</Code> / <Code>defaultDensity</Code>: Controlled or
|
|
233
|
+
initial density for collection renderers. Host apps can seed this
|
|
234
|
+
from <Code>@contractspec/lib.personalization</Code> while specs
|
|
235
|
+
can declare <Code>view.collection.density</Code> and table{' '}
|
|
236
|
+
<Code>view.density</Code> defaults.
|
|
237
|
+
</Text>
|
|
238
|
+
</ListItem>
|
|
239
|
+
<ListItem>
|
|
240
|
+
<Text>
|
|
241
|
+
<Code>dataDepth</Code> / <Code>defaultDataDepth</Code>: Controlled
|
|
242
|
+
or initial summary/standard/detailed/exhaustive projection. Fields
|
|
243
|
+
can declare <Code>visibility.minDataDepth</Code>, and collection
|
|
244
|
+
specs can opt into <Code>view.collection.personalization</Code>{' '}
|
|
245
|
+
persistence hints.
|
|
246
|
+
</Text>
|
|
247
|
+
</ListItem>
|
|
248
|
+
</List>
|
|
249
|
+
</VStack>
|
|
250
|
+
|
|
251
|
+
<VStack className="space-y-4">
|
|
252
|
+
<H2 className="font-bold text-2xl">
|
|
253
|
+
Collection Defaults And Data Depth
|
|
254
|
+
</H2>
|
|
255
|
+
<P className="text-muted-foreground">
|
|
256
|
+
Use one authored <Code>DataViewSpec</Code> for list, grid, and table
|
|
257
|
+
experiences. <Code>view.collection</Code> declares allowed modes,
|
|
258
|
+
toolbar controls, pagination defaults, density, data depth, and
|
|
259
|
+
persistence hints. <Code>visibility.minDataDepth</Code> lets a field
|
|
260
|
+
appear only when the renderer is in a detailed or exhaustive mode.
|
|
261
|
+
</P>
|
|
262
|
+
<CodeBlock language="typescript" code={COLLECTION_DATAVIEW_EXAMPLE} />
|
|
263
|
+
</VStack>
|
|
264
|
+
|
|
265
|
+
<VStack className="space-y-4">
|
|
266
|
+
<H2 className="font-bold text-2xl">Personalization Bridge</H2>
|
|
267
|
+
<P className="text-muted-foreground">
|
|
268
|
+
Resolve user preferences in the host app, then pass ordinary renderer
|
|
269
|
+
props into <Code>DataViewRenderer</Code>. The bridge helper lives in{' '}
|
|
270
|
+
<Code>@contractspec/lib.personalization</Code>, so the design-system
|
|
271
|
+
renderer stays portable for apps that do not use personalization. See
|
|
272
|
+
the{' '}
|
|
273
|
+
<Link
|
|
274
|
+
href="/docs/libraries/personalization"
|
|
275
|
+
className="text-[color:var(--rust)] underline underline-offset-4"
|
|
276
|
+
>
|
|
277
|
+
<Text>personalization library guide</Text>
|
|
278
|
+
</Link>{' '}
|
|
279
|
+
for the behavior tracker, analyzer, and DataView preference resolver.
|
|
280
|
+
</P>
|
|
281
|
+
<CodeBlock language="tsx" code={PERSONALIZED_RENDERER_EXAMPLE} />
|
|
282
|
+
</VStack>
|
|
283
|
+
|
|
284
|
+
<VStack className="space-y-4">
|
|
285
|
+
<H2 className="font-bold text-2xl">Agent Prompt</H2>
|
|
286
|
+
<P className="text-muted-foreground">
|
|
287
|
+
Use this prompt when asking an implementation agent to add a
|
|
288
|
+
preference-aware collection DataView without breaking package
|
|
289
|
+
boundaries.
|
|
290
|
+
</P>
|
|
291
|
+
<CodeBlock language="markdown" code={DATAVIEW_AGENT_PROMPT} />
|
|
292
|
+
</VStack>
|
|
293
|
+
|
|
294
|
+
<VStack className="space-y-4">
|
|
295
|
+
<H2 className="font-bold text-2xl">Query Generation</H2>
|
|
296
|
+
<P className="text-muted-foreground">
|
|
297
|
+
The <Code>DataViewQueryGenerator</Code> utility helps translate
|
|
95
298
|
DataView parameters (filters, sorting, pagination) into query
|
|
96
299
|
arguments for your backend.
|
|
97
|
-
</
|
|
300
|
+
</P>
|
|
98
301
|
<CodeBlock
|
|
99
302
|
language="typescript"
|
|
100
303
|
code={`import { DataViewQueryGenerator } from '@contractspec/lib.contracts-spec/data-views/query-generator';
|
|
@@ -114,16 +317,16 @@ const query = generator.generate(params);
|
|
|
114
317
|
|
|
115
318
|
// query.input contains skip/take plus the typed filter payloads.`}
|
|
116
319
|
/>
|
|
117
|
-
</
|
|
320
|
+
</VStack>
|
|
118
321
|
|
|
119
|
-
<
|
|
322
|
+
<HStack className="items-center gap-4 pt-4">
|
|
120
323
|
<Link href="/docs/libraries" className="btn-ghost">
|
|
121
|
-
Back to Libraries
|
|
324
|
+
<Text>Back to Libraries</Text>
|
|
122
325
|
</Link>
|
|
123
326
|
<Link href="/docs/libraries/data-backend" className="btn-primary">
|
|
124
|
-
Next: Data & Backend <ChevronRight size={16} />
|
|
327
|
+
<Text>Next: Data & Backend</Text> <ChevronRight size={16} />
|
|
125
328
|
</Link>
|
|
126
|
-
</
|
|
127
|
-
</
|
|
329
|
+
</HStack>
|
|
330
|
+
</VStack>
|
|
128
331
|
);
|
|
129
332
|
}
|
|
@@ -88,10 +88,115 @@ const FOCUSED_SUBPATHS_EXAMPLE = `import { themeSpecToTailwindPreset } from '@co
|
|
|
88
88
|
import { Select } from '@contractspec/lib.design-system/controls';
|
|
89
89
|
import { FormDialog } from '@contractspec/lib.design-system/forms';
|
|
90
90
|
import { HStack } from '@contractspec/lib.design-system/layout';
|
|
91
|
+
import { AdaptivePanel } from '@contractspec/lib.design-system/components/overlays';
|
|
92
|
+
import { ObjectReferenceHandler } from '@contractspec/lib.design-system/components/object-reference';
|
|
91
93
|
|
|
92
94
|
// Root imports remain supported:
|
|
93
95
|
import { Button, DataTable } from '@contractspec/lib.design-system';`;
|
|
94
96
|
|
|
97
|
+
const OBJECT_REFERENCE_EXAMPLE = `import {
|
|
98
|
+
ObjectReferenceHandler,
|
|
99
|
+
createDefaultObjectReferenceActions,
|
|
100
|
+
createMapsReferenceActions,
|
|
101
|
+
type ObjectReferenceDescriptor,
|
|
102
|
+
type ObjectReferenceOpenHrefHandler,
|
|
103
|
+
} from '@contractspec/lib.design-system';
|
|
104
|
+
|
|
105
|
+
const customerContact: ObjectReferenceDescriptor = {
|
|
106
|
+
id: 'user.amina',
|
|
107
|
+
kind: 'user',
|
|
108
|
+
label: 'Amina Laurent',
|
|
109
|
+
description: 'Customer success owner',
|
|
110
|
+
href: '/customers/acme/users/amina',
|
|
111
|
+
properties: [
|
|
112
|
+
{
|
|
113
|
+
id: 'user.amina.email',
|
|
114
|
+
kind: 'email',
|
|
115
|
+
label: 'Email',
|
|
116
|
+
value: 'amina@example.com',
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
id: 'user.amina.phone',
|
|
120
|
+
kind: 'phone',
|
|
121
|
+
label: 'Phone',
|
|
122
|
+
value: '+33 1 23 45 67 89',
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
sections: [
|
|
126
|
+
{
|
|
127
|
+
id: 'customer-site',
|
|
128
|
+
title: 'Primary site',
|
|
129
|
+
properties: [
|
|
130
|
+
{
|
|
131
|
+
id: 'customer-site.address',
|
|
132
|
+
kind: 'address',
|
|
133
|
+
label: 'Paris office',
|
|
134
|
+
value: '10 rue de Rivoli, 75001 Paris',
|
|
135
|
+
actions: createMapsReferenceActions({
|
|
136
|
+
id: 'customer-site.address',
|
|
137
|
+
kind: 'address',
|
|
138
|
+
label: 'Paris office',
|
|
139
|
+
value: '10 rue de Rivoli, 75001 Paris',
|
|
140
|
+
}),
|
|
141
|
+
},
|
|
142
|
+
],
|
|
143
|
+
},
|
|
144
|
+
],
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const openHref: ObjectReferenceOpenHrefHandler = (href, _event, options) => {
|
|
148
|
+
if (options.target === 'new-page') {
|
|
149
|
+
window.open(href, '_blank', 'noopener,noreferrer');
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
window.location.assign(href);
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
<ObjectReferenceHandler
|
|
157
|
+
reference={customerContact}
|
|
158
|
+
actions={createDefaultObjectReferenceActions(customerContact)}
|
|
159
|
+
interactivityVisibility="icon"
|
|
160
|
+
openTarget="same-page"
|
|
161
|
+
panelMode="responsive"
|
|
162
|
+
mobilePanelMode="drawer"
|
|
163
|
+
desktopPanelMode="sheet"
|
|
164
|
+
responsiveBreakpoint="md"
|
|
165
|
+
openHref={openHref}
|
|
166
|
+
/>;`;
|
|
167
|
+
|
|
168
|
+
const ADAPTIVE_PANEL_EXAMPLE = `import { AdaptivePanel } from '@contractspec/lib.design-system/components/overlays';
|
|
169
|
+
|
|
170
|
+
<AdaptivePanel
|
|
171
|
+
open={open}
|
|
172
|
+
onOpenChange={setOpen}
|
|
173
|
+
trigger={<button type="button">Edit</button>}
|
|
174
|
+
title="Edit customer"
|
|
175
|
+
description="Update contact and site details."
|
|
176
|
+
mode="responsive"
|
|
177
|
+
mobileMode="drawer"
|
|
178
|
+
desktopMode="sheet"
|
|
179
|
+
breakpoint="md"
|
|
180
|
+
sheetSide="right"
|
|
181
|
+
drawerDirection="bottom"
|
|
182
|
+
>
|
|
183
|
+
{content}
|
|
184
|
+
</AdaptivePanel>;`;
|
|
185
|
+
|
|
186
|
+
const OBJECT_REFERENCE_PROMPT = `Find every user-facing address, phone number, email, user, customer, file, URL, and tenant-specific object reference currently rendered as inert text.
|
|
187
|
+
|
|
188
|
+
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.
|
|
189
|
+
|
|
190
|
+
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.
|
|
191
|
+
|
|
192
|
+
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.
|
|
193
|
+
|
|
194
|
+
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.
|
|
195
|
+
|
|
196
|
+
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.
|
|
197
|
+
|
|
198
|
+
After replacing references, verify keyboard access, visible affordance choice (none, underline, or icon), safe href behavior, mobile drawer layout, and desktop sheet layout.`;
|
|
199
|
+
|
|
95
200
|
export function LibrariesDesignSystemPage() {
|
|
96
201
|
return (
|
|
97
202
|
<div className="space-y-8">
|
|
@@ -134,6 +239,15 @@ export function LibrariesDesignSystemPage() {
|
|
|
134
239
|
<strong>Platform Utilities</strong>: Hooks for responsive and
|
|
135
240
|
adaptive design
|
|
136
241
|
</li>
|
|
242
|
+
<li>
|
|
243
|
+
<strong>Object References</strong>: Clickable references for
|
|
244
|
+
addresses, phone numbers, users, customers, files, URLs, and custom
|
|
245
|
+
objects
|
|
246
|
+
</li>
|
|
247
|
+
<li>
|
|
248
|
+
<strong>Adaptive Panels</strong>: One panel API that resolves to a
|
|
249
|
+
desktop sheet or mobile drawer
|
|
250
|
+
</li>
|
|
137
251
|
<li>
|
|
138
252
|
<strong>Theme Bridge</strong>: ThemeSpec to Tailwind variables,
|
|
139
253
|
presets, CSS text, and runtime light/dark mode
|
|
@@ -165,6 +279,118 @@ export function LibrariesDesignSystemPage() {
|
|
|
165
279
|
<CodeBlock language="tsx" code={FOCUSED_SUBPATHS_EXAMPLE} />
|
|
166
280
|
</div>
|
|
167
281
|
|
|
282
|
+
<div className="space-y-4">
|
|
283
|
+
<h2 className="font-bold text-2xl">Actionable object references</h2>
|
|
284
|
+
<p className="text-muted-foreground">
|
|
285
|
+
Use <code>ObjectReferenceHandler</code> whenever a product surface
|
|
286
|
+
renders an object that may need quick interaction: addresses, phone
|
|
287
|
+
numbers, emails, users, customers, files, URLs, and tenant-specific
|
|
288
|
+
objects. The goal is to avoid inert references while keeping the
|
|
289
|
+
descriptor contract declarative enough for OSS consumers and future
|
|
290
|
+
contract-generated surfaces.
|
|
291
|
+
</p>
|
|
292
|
+
<div className="grid gap-4 md:grid-cols-2">
|
|
293
|
+
<div className="card-subtle p-4">
|
|
294
|
+
<h3 className="mb-2 font-semibold">Descriptor model</h3>
|
|
295
|
+
<ul className="list-inside list-disc space-y-1 text-muted-foreground text-sm">
|
|
296
|
+
<li>
|
|
297
|
+
References use data-only descriptors: <code>id</code>,{' '}
|
|
298
|
+
<code>kind</code>, <code>label</code>, <code>value</code>,{' '}
|
|
299
|
+
<code>href</code>, <code>openTarget</code>,{' '}
|
|
300
|
+
<code>metadata</code>, <code>iconKey</code>, and{' '}
|
|
301
|
+
<code>ariaLabel</code>.
|
|
302
|
+
</li>
|
|
303
|
+
<li>
|
|
304
|
+
Rich references use nested <code>properties</code> and{' '}
|
|
305
|
+
<code>sections</code>, so one user or customer can expose email,
|
|
306
|
+
phone, address, files, and links inside the same panel.
|
|
307
|
+
</li>
|
|
308
|
+
<li>
|
|
309
|
+
Reference kinds are <code>address</code>, <code>email</code>,{' '}
|
|
310
|
+
<code>phone</code>, <code>user</code>, <code>customer</code>,{' '}
|
|
311
|
+
<code>file</code>, <code>url</code>, and <code>custom</code>.
|
|
312
|
+
</li>
|
|
313
|
+
</ul>
|
|
314
|
+
</div>
|
|
315
|
+
<div className="card-subtle p-4">
|
|
316
|
+
<h3 className="mb-2 font-semibold">Runtime behavior</h3>
|
|
317
|
+
<ul className="list-inside list-disc space-y-1 text-muted-foreground text-sm">
|
|
318
|
+
<li>
|
|
319
|
+
Choose visibility with <code>interactivityVisibility</code>:
|
|
320
|
+
<code>none</code>, <code>underline</code>, or <code>icon</code>.
|
|
321
|
+
</li>
|
|
322
|
+
<li>
|
|
323
|
+
Detail navigation defaults to <code>same-page</code>; set{' '}
|
|
324
|
+
<code>openTarget="new-page"</code> on the handler, reference, or
|
|
325
|
+
action when a new page is required.
|
|
326
|
+
</li>
|
|
327
|
+
<li>
|
|
328
|
+
Host apps provide behavior through <code>copyHandler</code>,{' '}
|
|
329
|
+
<code>openHref</code>, <code>actionHandlers</code>,{' '}
|
|
330
|
+
<code>onAction</code>, and <code>onActionError</code>.
|
|
331
|
+
</li>
|
|
332
|
+
</ul>
|
|
333
|
+
</div>
|
|
334
|
+
<div className="card-subtle p-4">
|
|
335
|
+
<h3 className="mb-2 font-semibold">Default actions</h3>
|
|
336
|
+
<ul className="list-inside list-disc space-y-1 text-muted-foreground text-sm">
|
|
337
|
+
<li>
|
|
338
|
+
<code>createDefaultObjectReferenceActions</code> adds copy,
|
|
339
|
+
open, email, phone, and map actions when the descriptor supports
|
|
340
|
+
them.
|
|
341
|
+
</li>
|
|
342
|
+
<li>
|
|
343
|
+
<code>createMapsReferenceActions</code> creates Google Maps,
|
|
344
|
+
Apple Maps, Waze, or geo actions for address references.
|
|
345
|
+
</li>
|
|
346
|
+
<li>
|
|
347
|
+
Safe href handling allows expected app, web, email, phone, and
|
|
348
|
+
map URLs while rejecting unsafe schemes.
|
|
349
|
+
</li>
|
|
350
|
+
</ul>
|
|
351
|
+
</div>
|
|
352
|
+
<div className="card-subtle p-4">
|
|
353
|
+
<h3 className="mb-2 font-semibold">Extension points</h3>
|
|
354
|
+
<ul className="list-inside list-disc space-y-1 text-muted-foreground text-sm">
|
|
355
|
+
<li>
|
|
356
|
+
Use <code>renderTrigger</code>, <code>renderDetail</code>,{' '}
|
|
357
|
+
<code>renderAction</code>, <code>renderProperty</code>,{' '}
|
|
358
|
+
<code>renderSection</code>, and <code>iconRenderer</code> to
|
|
359
|
+
wrap or overload presentation.
|
|
360
|
+
</li>
|
|
361
|
+
<li>
|
|
362
|
+
Keep tenant-specific permissions, analytics, and integration
|
|
363
|
+
side effects at the host boundary through runtime handlers.
|
|
364
|
+
</li>
|
|
365
|
+
</ul>
|
|
366
|
+
</div>
|
|
367
|
+
</div>
|
|
368
|
+
<CodeBlock language="tsx" code={OBJECT_REFERENCE_EXAMPLE} />
|
|
369
|
+
</div>
|
|
370
|
+
|
|
371
|
+
<div className="space-y-4">
|
|
372
|
+
<h2 className="font-bold text-2xl">Adaptive panels</h2>
|
|
373
|
+
<p className="text-muted-foreground">
|
|
374
|
+
<code>AdaptivePanel</code> is the shared overlay decision for surfaces
|
|
375
|
+
that should feel native on both desktop and small screens. Its default
|
|
376
|
+
responsive mode renders a sheet at the configured desktop breakpoint
|
|
377
|
+
and a drawer below it. <code>ObjectReferenceHandler</code> uses this
|
|
378
|
+
panel contract through <code>panelMode</code>,{' '}
|
|
379
|
+
<code>mobilePanelMode</code>, <code>desktopPanelMode</code>, and{' '}
|
|
380
|
+
<code>responsiveBreakpoint</code>.
|
|
381
|
+
</p>
|
|
382
|
+
<CodeBlock language="tsx" code={ADAPTIVE_PANEL_EXAMPLE} />
|
|
383
|
+
</div>
|
|
384
|
+
|
|
385
|
+
<div className="space-y-4">
|
|
386
|
+
<h2 className="font-bold text-2xl">Prompt for adoption work</h2>
|
|
387
|
+
<p className="text-muted-foreground">
|
|
388
|
+
Use this prompt when asking an agent or downstream OSS consumer to
|
|
389
|
+
replace inert references across an application.
|
|
390
|
+
</p>
|
|
391
|
+
<CodeBlock language="text" code={OBJECT_REFERENCE_PROMPT} />
|
|
392
|
+
</div>
|
|
393
|
+
|
|
168
394
|
<div className="space-y-4">
|
|
169
395
|
<h2 className="font-bold text-2xl">Data table example</h2>
|
|
170
396
|
<p className="text-muted-foreground">
|
|
@@ -218,6 +444,15 @@ export function LibrariesDesignSystemPage() {
|
|
|
218
444
|
<li>PackageManagerProvider</li>
|
|
219
445
|
</ul>
|
|
220
446
|
</div>
|
|
447
|
+
<div className="card-subtle p-4">
|
|
448
|
+
<h3 className="mb-2 font-semibold">References & Overlays</h3>
|
|
449
|
+
<ul className="space-y-1 text-muted-foreground text-sm">
|
|
450
|
+
<li>ObjectReferenceHandler</li>
|
|
451
|
+
<li>createDefaultObjectReferenceActions</li>
|
|
452
|
+
<li>createMapsReferenceActions</li>
|
|
453
|
+
<li>AdaptivePanel</li>
|
|
454
|
+
</ul>
|
|
455
|
+
</div>
|
|
221
456
|
</div>
|
|
222
457
|
</div>
|
|
223
458
|
|
|
@@ -30,6 +30,12 @@ const libraryGroups = [
|
|
|
30
30
|
'Run typed capability surfaces, execute policies, and connect runtime adapters.',
|
|
31
31
|
href: '/docs/libraries/runtime',
|
|
32
32
|
},
|
|
33
|
+
{
|
|
34
|
+
title: '@contractspec/lib.translation-runtime',
|
|
35
|
+
description:
|
|
36
|
+
'Resolve ContractSpec TranslationSpec catalogs with ICU formatting, SSR snapshots, BCP 47 locales, overrides, and optional i18next projection.',
|
|
37
|
+
href: '/docs/libraries/translation-runtime',
|
|
38
|
+
},
|
|
33
39
|
{
|
|
34
40
|
title: '@contractspec/lib.ui-kit',
|
|
35
41
|
description:
|
|
@@ -45,13 +51,13 @@ const libraryGroups = [
|
|
|
45
51
|
{
|
|
46
52
|
title: '@contractspec/lib.design-system',
|
|
47
53
|
description:
|
|
48
|
-
'Build higher-level product surfaces and documented marketing/docs primitives on top of the web and native UI packages.',
|
|
54
|
+
'Build higher-level product surfaces, actionable object references, adaptive panels, and documented marketing/docs primitives on top of the web and native UI packages.',
|
|
49
55
|
href: '/docs/libraries/design-system',
|
|
50
56
|
},
|
|
51
57
|
{
|
|
52
58
|
title: 'Application shell',
|
|
53
59
|
description:
|
|
54
|
-
'Adopt the shared sidebar, topbar, command search, mobile navigation, and PageOutline patterns for product apps.',
|
|
60
|
+
'Adopt the shared sidebar, topbar, command search, notifications, mobile navigation, and PageOutline patterns for product apps.',
|
|
55
61
|
href: '/docs/libraries/application-shell',
|
|
56
62
|
},
|
|
57
63
|
{
|