@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
|
@@ -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">
|
|
@@ -187,6 +413,7 @@ export function LibrariesDesignSystemPage() {
|
|
|
187
413
|
<div className="card-subtle p-4">
|
|
188
414
|
<h3 className="mb-2 font-semibold">Organisms</h3>
|
|
189
415
|
<ul className="space-y-1 text-muted-foreground text-sm">
|
|
416
|
+
<li>AppShell, PageOutline</li>
|
|
190
417
|
<li>AppLayout, AppHeader, AppSidebar</li>
|
|
191
418
|
<li>MarketingLayout, HeroSection</li>
|
|
192
419
|
<li>ListCardPage, ListTablePage</li>
|
|
@@ -217,6 +444,15 @@ export function LibrariesDesignSystemPage() {
|
|
|
217
444
|
<li>PackageManagerProvider</li>
|
|
218
445
|
</ul>
|
|
219
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>
|
|
220
456
|
</div>
|
|
221
457
|
</div>
|
|
222
458
|
|
|
@@ -224,6 +460,14 @@ export function LibrariesDesignSystemPage() {
|
|
|
224
460
|
<h2 className="font-bold text-2xl">Where this layer fits</h2>
|
|
225
461
|
<p className="text-muted-foreground">
|
|
226
462
|
Read{' '}
|
|
463
|
+
<Link
|
|
464
|
+
href="/docs/libraries/application-shell"
|
|
465
|
+
className="text-[color:var(--rust)] underline underline-offset-4"
|
|
466
|
+
>
|
|
467
|
+
Application shell
|
|
468
|
+
</Link>{' '}
|
|
469
|
+
for the shared sidebar, topbar, command search, mobile navigation, and{' '}
|
|
470
|
+
<code>PageOutline</code> pattern. Read{' '}
|
|
227
471
|
<Link
|
|
228
472
|
href="/docs/libraries/cross-platform-ui"
|
|
229
473
|
className="text-[color:var(--rust)] underline underline-offset-4"
|
|
@@ -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,9 +51,15 @@ 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
|
},
|
|
57
|
+
{
|
|
58
|
+
title: 'Application shell',
|
|
59
|
+
description:
|
|
60
|
+
'Adopt the shared sidebar, topbar, command search, notifications, mobile navigation, and PageOutline patterns for product apps.',
|
|
61
|
+
href: '/docs/libraries/application-shell',
|
|
62
|
+
},
|
|
51
63
|
{
|
|
52
64
|
title: 'Cross-platform UI',
|
|
53
65
|
description:
|
|
@@ -1,31 +1,93 @@
|
|
|
1
1
|
import { CodeBlock, InstallCommand } from '@contractspec/lib.design-system';
|
|
2
|
+
import { HStack, VStack } from '@contractspec/lib.design-system/layout';
|
|
3
|
+
import {
|
|
4
|
+
Code,
|
|
5
|
+
H1,
|
|
6
|
+
H2,
|
|
7
|
+
P,
|
|
8
|
+
Text,
|
|
9
|
+
} from '@contractspec/lib.design-system/typography';
|
|
2
10
|
import Link from '@contractspec/lib.ui-link';
|
|
3
11
|
import { ChevronRight } from 'lucide-react';
|
|
4
12
|
|
|
13
|
+
const DATA_VIEW_PREFERENCE_EXAMPLE = `import { DataViewRenderer } from '@contractspec/lib.design-system';
|
|
14
|
+
import { resolveDataViewPreferences } from '@contractspec/lib.personalization/data-view-preferences';
|
|
15
|
+
|
|
16
|
+
const resolved = resolveDataViewPreferences({
|
|
17
|
+
spec: AccountsDataView,
|
|
18
|
+
preferences: profile.canonical,
|
|
19
|
+
insights,
|
|
20
|
+
record: savedAccountViewPreference,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<DataViewRenderer
|
|
25
|
+
spec={AccountsDataView}
|
|
26
|
+
items={accounts}
|
|
27
|
+
defaultViewMode={resolved.viewMode}
|
|
28
|
+
defaultDensity={resolved.density}
|
|
29
|
+
defaultDataDepth={resolved.dataDepth}
|
|
30
|
+
pagination={{
|
|
31
|
+
page,
|
|
32
|
+
pageSize: resolved.pageSize ?? 25,
|
|
33
|
+
total,
|
|
34
|
+
}}
|
|
35
|
+
/>
|
|
36
|
+
);`;
|
|
37
|
+
|
|
38
|
+
const DATA_VIEW_TRACKING_EXAMPLE = `tracker.trackDataViewInteraction({
|
|
39
|
+
dataViewKey: AccountsDataView.meta.key,
|
|
40
|
+
dataViewVersion: AccountsDataView.meta.version,
|
|
41
|
+
action: 'view_mode_changed',
|
|
42
|
+
viewMode: 'grid',
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
tracker.trackDataViewInteraction({
|
|
46
|
+
dataViewKey: AccountsDataView.meta.key,
|
|
47
|
+
action: 'data_depth_changed',
|
|
48
|
+
dataDepth: 'detailed',
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
tracker.trackDataViewInteraction({
|
|
52
|
+
dataViewKey: AccountsDataView.meta.key,
|
|
53
|
+
action: 'filter_changed',
|
|
54
|
+
filterKey: 'status',
|
|
55
|
+
});`;
|
|
56
|
+
|
|
57
|
+
const DATA_VIEW_PERSONALIZATION_PROMPT = `Add DataView personalization for <screen>.
|
|
58
|
+
|
|
59
|
+
Acceptance criteria:
|
|
60
|
+
- Resolve viewMode, density, dataDepth, and pageSize with resolveDataViewPreferences.
|
|
61
|
+
- Apply resolved values to DataViewRenderer as default or controlled props.
|
|
62
|
+
- Track opened, view_mode_changed, density_changed, data_depth_changed, search_changed, filter_changed, sort_changed, and page_changed actions with trackDataViewInteraction.
|
|
63
|
+
- Persist only the dimensions allowed by view.collection.personalization.persist.
|
|
64
|
+
- Ignore behavior-derived modes that are not allowed by view.collection.viewModes.allowedModes.
|
|
65
|
+
- Do not import React or design-system code into @contractspec/lib.personalization helpers.`;
|
|
66
|
+
|
|
5
67
|
export function LibrariesPersonalizationPage() {
|
|
6
68
|
return (
|
|
7
|
-
<
|
|
8
|
-
<
|
|
9
|
-
<
|
|
69
|
+
<VStack className="space-y-8">
|
|
70
|
+
<VStack className="space-y-4">
|
|
71
|
+
<H1 className="font-bold text-4xl">
|
|
10
72
|
@contractspec/lib.personalization
|
|
11
|
-
</
|
|
12
|
-
<
|
|
73
|
+
</H1>
|
|
74
|
+
<P className="text-lg text-muted-foreground">
|
|
13
75
|
Track field/feature/workflow usage, analyze drop-offs, and convert
|
|
14
76
|
insights into OverlaySpecs or workflow tweaks.
|
|
15
|
-
</
|
|
16
|
-
</
|
|
77
|
+
</P>
|
|
78
|
+
</VStack>
|
|
17
79
|
|
|
18
|
-
<
|
|
19
|
-
<
|
|
80
|
+
<VStack className="space-y-4">
|
|
81
|
+
<H2 className="font-bold text-2xl">Installation</H2>
|
|
20
82
|
<InstallCommand package="@contractspec/lib.personalization" />
|
|
21
|
-
</
|
|
83
|
+
</VStack>
|
|
22
84
|
|
|
23
|
-
<
|
|
24
|
-
<
|
|
25
|
-
<
|
|
85
|
+
<VStack className="space-y-4">
|
|
86
|
+
<H2 className="font-bold text-2xl">Tracker</H2>
|
|
87
|
+
<P className="text-muted-foreground">
|
|
26
88
|
Buffer events per tenant/user and emit OpenTelemetry counters
|
|
27
89
|
automatically.
|
|
28
|
-
</
|
|
90
|
+
</P>
|
|
29
91
|
<CodeBlock
|
|
30
92
|
language="typescript"
|
|
31
93
|
code={`import { createBehaviorTracker } from '@contractspec/lib.personalization';
|
|
@@ -38,29 +100,65 @@ const tracker = createBehaviorTracker({
|
|
|
38
100
|
tracker.trackFieldAccess({ operation: 'billing.createOrder', field: 'items' });
|
|
39
101
|
tracker.trackWorkflowStep({ workflow: 'invoice', step: 'review', status: 'entered' });`}
|
|
40
102
|
/>
|
|
41
|
-
</
|
|
103
|
+
</VStack>
|
|
104
|
+
|
|
105
|
+
<VStack className="space-y-4">
|
|
106
|
+
<H2 className="font-bold text-2xl">DataView Preferences</H2>
|
|
107
|
+
<P className="text-muted-foreground">
|
|
108
|
+
Use <Code>resolveDataViewPreferences</Code> when a collection DataView
|
|
109
|
+
should honor a user's preferred list/grid/table mode, compact or
|
|
110
|
+
comfortable density, data depth, and page size. The helper returns
|
|
111
|
+
plain values that can be passed into the renderer without coupling the
|
|
112
|
+
design-system package to personalization. Start from the{' '}
|
|
113
|
+
<Link
|
|
114
|
+
href="/docs/libraries/data-views"
|
|
115
|
+
className="text-[color:var(--rust)] underline underline-offset-4"
|
|
116
|
+
>
|
|
117
|
+
<Text>DataViews runtime guide</Text>
|
|
118
|
+
</Link>{' '}
|
|
119
|
+
when you need the contract and renderer shape.
|
|
120
|
+
</P>
|
|
121
|
+
<CodeBlock language="tsx" code={DATA_VIEW_PREFERENCE_EXAMPLE} />
|
|
122
|
+
</VStack>
|
|
42
123
|
|
|
43
|
-
<
|
|
44
|
-
<
|
|
45
|
-
<
|
|
124
|
+
<VStack className="space-y-4">
|
|
125
|
+
<H2 className="font-bold text-2xl">DataView Interaction Events</H2>
|
|
126
|
+
<P className="text-muted-foreground">
|
|
127
|
+
Track <Code>data_view_interaction</Code> events for view mode,
|
|
128
|
+
density, data depth, search, filters, sorting, and pagination. The
|
|
129
|
+
in-memory store summarizes those events, and the analyzer can derive a
|
|
130
|
+
scoped preferred collection mode from valid interaction counts.
|
|
131
|
+
</P>
|
|
132
|
+
<CodeBlock language="typescript" code={DATA_VIEW_TRACKING_EXAMPLE} />
|
|
133
|
+
</VStack>
|
|
134
|
+
|
|
135
|
+
<VStack className="space-y-4">
|
|
136
|
+
<H2 className="font-bold text-2xl">Analyzer</H2>
|
|
137
|
+
<P className="text-muted-foreground">
|
|
46
138
|
Summarize events and highlight unused UI, frequent fields, and
|
|
47
139
|
workflow bottlenecks.
|
|
48
|
-
</
|
|
140
|
+
</P>
|
|
49
141
|
<CodeBlock
|
|
50
142
|
language="typescript"
|
|
51
143
|
code={`import { BehaviorAnalyzer } from '@contractspec/lib.personalization/analyzer';
|
|
52
144
|
|
|
53
145
|
const analyzer = new BehaviorAnalyzer(store);
|
|
54
146
|
const insights = await analyzer.analyze({ tenantId: 'acme', userId: 'ops-42' });
|
|
55
|
-
// {
|
|
147
|
+
// {
|
|
148
|
+
// unusedFields: ['internalNotes'],
|
|
149
|
+
// workflowBottlenecks: [...],
|
|
150
|
+
// dataViewPreferences: {
|
|
151
|
+
// 'crm.accounts': { preferredViewMode: 'grid' }
|
|
152
|
+
// }
|
|
153
|
+
// }`}
|
|
56
154
|
/>
|
|
57
|
-
</
|
|
155
|
+
</VStack>
|
|
58
156
|
|
|
59
|
-
<
|
|
60
|
-
<
|
|
61
|
-
<
|
|
157
|
+
<VStack className="space-y-4">
|
|
158
|
+
<H2 className="font-bold text-2xl">Adapter</H2>
|
|
159
|
+
<P className="text-muted-foreground">
|
|
62
160
|
Convert insights into overlays or workflow extension hints.
|
|
63
|
-
</
|
|
161
|
+
</P>
|
|
64
162
|
<CodeBlock
|
|
65
163
|
language="typescript"
|
|
66
164
|
code={`import { insightsToOverlaySuggestion } from '@contractspec/lib.personalization/adapter';
|
|
@@ -71,16 +169,28 @@ const overlay = insightsToOverlaySuggestion(insights, {
|
|
|
71
169
|
capability: 'billing.createOrder',
|
|
72
170
|
});`}
|
|
73
171
|
/>
|
|
74
|
-
</
|
|
172
|
+
</VStack>
|
|
173
|
+
|
|
174
|
+
<VStack className="space-y-4">
|
|
175
|
+
<H2 className="font-bold text-2xl">Agent Prompt</H2>
|
|
176
|
+
<P className="text-muted-foreground">
|
|
177
|
+
Use this when asking an agent to wire DataView preferences while
|
|
178
|
+
preserving the personalization/design-system boundary.
|
|
179
|
+
</P>
|
|
180
|
+
<CodeBlock
|
|
181
|
+
language="markdown"
|
|
182
|
+
code={DATA_VIEW_PERSONALIZATION_PROMPT}
|
|
183
|
+
/>
|
|
184
|
+
</VStack>
|
|
75
185
|
|
|
76
|
-
<
|
|
186
|
+
<HStack className="items-center gap-4 pt-4">
|
|
77
187
|
<Link href="/docs/libraries" className="btn-ghost">
|
|
78
|
-
Back to Libraries
|
|
188
|
+
<Text>Back to Libraries</Text>
|
|
79
189
|
</Link>
|
|
80
190
|
<Link href="/docs/libraries/overlay-engine" className="btn-primary">
|
|
81
|
-
Next: Overlay Engine <ChevronRight size={16} />
|
|
191
|
+
<Text>Next: Overlay Engine</Text> <ChevronRight size={16} />
|
|
82
192
|
</Link>
|
|
83
|
-
</
|
|
84
|
-
</
|
|
193
|
+
</HStack>
|
|
194
|
+
</VStack>
|
|
85
195
|
);
|
|
86
196
|
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
export const translationRuntimeInstall = [
|
|
2
|
+
'@contractspec/lib.contracts-spec',
|
|
3
|
+
'@contractspec/lib.translation-runtime',
|
|
4
|
+
];
|
|
5
|
+
|
|
6
|
+
export const translationRuntimeExample = `import { createTranslationRuntime } from '@contractspec/lib.translation-runtime';
|
|
7
|
+
import { checkoutMessages } from './translations/checkout.messages';
|
|
8
|
+
|
|
9
|
+
const runtime = createTranslationRuntime({
|
|
10
|
+
catalogs: [checkoutMessages],
|
|
11
|
+
locale: 'fr-FR',
|
|
12
|
+
fallbackLocales: ['fr', 'en-US'],
|
|
13
|
+
onDiagnostic: (diagnostic) => reportTranslationIssue(diagnostic),
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
const label = runtime.t('checkout.pay', {
|
|
17
|
+
amount: 4200,
|
|
18
|
+
currency: 'EUR',
|
|
19
|
+
});`;
|
|
20
|
+
|
|
21
|
+
export const i18nextAdapterExample = `import { createInstance } from 'i18next';
|
|
22
|
+
import {
|
|
23
|
+
createI18nextInitOptions,
|
|
24
|
+
exportContractSpecToI18next,
|
|
25
|
+
} from '@contractspec/lib.translation-runtime/i18next';
|
|
26
|
+
|
|
27
|
+
const exported = exportContractSpecToI18next([checkoutMessages], {
|
|
28
|
+
locale: 'en-US',
|
|
29
|
+
assumeIcuFormatter: true,
|
|
30
|
+
});
|
|
31
|
+
const { options, diagnostics } = createI18nextInitOptions(exported, {
|
|
32
|
+
lng: 'en-US',
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const i18next = createInstance();
|
|
36
|
+
await i18next.init(options);
|
|
37
|
+
reportAdapterDiagnostics(diagnostics);`;
|
|
38
|
+
|
|
39
|
+
export const ssrHydrationExample = `// Server: negotiate once, preload catalogs, and serialize the runtime snapshot.
|
|
40
|
+
const runtime = createTranslationRuntime({
|
|
41
|
+
catalogs,
|
|
42
|
+
locale: negotiatedLocale,
|
|
43
|
+
fallbackLocales,
|
|
44
|
+
});
|
|
45
|
+
const snapshot = runtime.createSnapshot();
|
|
46
|
+
|
|
47
|
+
// Client: hydrate from the same snapshot so locale, resources, and fallback state match.
|
|
48
|
+
const hydratedRuntime = createTranslationRuntime({ snapshot });`;
|
|
49
|
+
|
|
50
|
+
export const translationRuntimeChecks = [
|
|
51
|
+
'Keep TranslationSpec as the source of truth; do not flatten metadata into i18next JSON as the canonical model.',
|
|
52
|
+
'Keep stable bundle identity in TranslationSpec.meta.key and keep BCP 47 language tags in TranslationSpec.locale.',
|
|
53
|
+
'Use ICU messages for plural, select, selectordinal, number, date, currency, list, and relative-time formatting.',
|
|
54
|
+
'Create one runtime per SSR request when tenant, project, or user overrides are involved.',
|
|
55
|
+
'Serialize the same runtime snapshot or exported adapter resources used by the server for hydration.',
|
|
56
|
+
'Configure an ICU-capable i18next formatter plugin when rendering ContractSpec ICU messages through i18next.',
|
|
57
|
+
'Treat adapter diagnostics as release blockers in production pipelines instead of silently rendering raw keys.',
|
|
58
|
+
];
|
|
59
|
+
|
|
60
|
+
export const translationRuntimePrompt = `You are integrating ContractSpec translations into a production app.
|
|
61
|
+
Use @contractspec/lib.contracts-spec/translations as the canonical contract layer and @contractspec/lib.translation-runtime as the runtime layer.
|
|
62
|
+
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.
|
|
63
|
+
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.`;
|
|
64
|
+
|
|
65
|
+
export const translationRuntimeLayers = [
|
|
66
|
+
{
|
|
67
|
+
title: 'Spec layer',
|
|
68
|
+
body: 'TranslationSpec owns keys, locales, domains, versions, owners, fallback declarations, direction, and validation metadata.',
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
title: 'Runtime layer',
|
|
72
|
+
body: 'Runtime instances negotiate locales, apply fallback chains, resolve overrides, cache compiled messages, report diagnostics, and serialize SSR snapshots.',
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
title: 'Adapter layer',
|
|
76
|
+
body: 'The i18next adapter projects ContractSpec specs or snapshots to resources and manifests for caller-owned i18next instances.',
|
|
77
|
+
},
|
|
78
|
+
];
|