@hraness/design-kit 0.31.1 → 0.33.0

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.
Files changed (43) hide show
  1. package/AGENT_SETUP.md +89 -0
  2. package/ARTICLE_COPY.md +1 -1
  3. package/MARKETING_COPY.md +13 -1
  4. package/README.md +17 -4
  5. package/dist/{chunk-7b1586eb.js → chunk-4d79eskk.js} +62 -33
  6. package/dist/{chunk-44djxk16.js → chunk-95mpmzc9.js} +678 -619
  7. package/dist/{chunk-eh71jz57.js → chunk-vst6p4wd.js} +96 -9
  8. package/dist/index.js +6 -2
  9. package/dist/mockups/client.js +19 -18
  10. package/dist/provider-marks.js +1 -1
  11. package/dist/react/index.js +1617 -649
  12. package/dist/react/server.js +4 -2
  13. package/dist/stylex-manifest.json +1 -1
  14. package/dist/stylex.css +216 -4
  15. package/package.json +7 -3
  16. package/portfolio-inventory.json +1 -1
  17. package/src/agent-setup.ts +47 -0
  18. package/src/index.ts +1 -0
  19. package/src/mockups/client.tsx +26 -22
  20. package/src/mockups.css +44 -13
  21. package/src/product-marketing.css +7 -2
  22. package/src/provider-marks.generated.ts +16 -0
  23. package/src/provider-marks.ts +14 -15
  24. package/src/react/agent-setup-prompt.stylex.ts +196 -0
  25. package/src/react/agent-setup-prompt.tsx +413 -0
  26. package/src/react/article.tsx +12 -20
  27. package/src/react/design-gallery.tsx +30 -2
  28. package/src/react/index.ts +1 -0
  29. package/src/react/launch-beats.tsx +7 -4
  30. package/src/react/product-marketing.stylex.ts +29 -4
  31. package/src/react/product-marketing.tsx +45 -12
  32. package/src/react/provider-mark.stylex.ts +17 -10
  33. package/src/react/provider-mark.tsx +6 -16
  34. package/vendor/provider-marks/MEM0-LICENSE +201 -0
  35. package/vendor/provider-marks/SUPERMEMORY-LICENSE +21 -0
  36. package/vendor/provider-marks/UPSTREAM.md +12 -1
  37. package/vendor/provider-marks/lobehub/githubcopilot.svg +1 -0
  38. package/vendor/provider-marks/lobehub/obsidian-color.svg +1 -0
  39. package/vendor/provider-marks/lobehub/obsidian.svg +1 -0
  40. package/vendor/provider-marks/mem0-art.svg +1 -0
  41. package/vendor/provider-marks/mem0-glyph.svg +1 -0
  42. package/vendor/provider-marks/mem0.svg +1 -0
  43. package/vendor/provider-marks/supermemory.svg +1 -0
package/dist/stylex.css CHANGED
@@ -57,10 +57,30 @@
57
57
  padding: .3rem .85rem;
58
58
  }
59
59
 
60
+ .xk2ntsi {
61
+ padding: .4rem .4rem 0 1rem;
62
+ }
63
+
60
64
  .x3699eh {
61
65
  padding: .55rem .9rem;
62
66
  }
63
67
 
68
+ .x1xplop1 {
69
+ padding: .5rem 1rem 1rem;
70
+ }
71
+
72
+ .xde91s7 {
73
+ padding: .5rem 1rem 4rem;
74
+ }
75
+
76
+ .x1i4hug3 {
77
+ padding: .65rem .8rem;
78
+ }
79
+
80
+ .xz0q7xm {
81
+ padding: .6rem .8rem;
82
+ }
83
+
64
84
  .x19qf9ol {
65
85
  padding: .6rem 1.1rem;
66
86
  }
@@ -77,10 +97,18 @@
77
97
  padding: 0;
78
98
  }
79
99
 
100
+ .x194jd1b {
101
+ padding: 1.1rem 7rem 1rem 1rem;
102
+ }
103
+
80
104
  .x1dk9mx5 {
81
105
  padding: 1.25rem clamp(.8rem, 2vw, 1.5rem);
82
106
  }
83
107
 
108
+ .x67o20r {
109
+ padding: 1rem 1rem 0;
110
+ }
111
+
84
112
  .x1nn0urv {
85
113
  padding: clamp(1.25rem, 2.5vw, 1.75rem);
86
114
  }
@@ -208,6 +236,10 @@
208
236
  border-bottom: var(--hraness-marketing-surface-rule);
209
237
  }
210
238
 
239
+ .x3ugid2 {
240
+ border-color: color-mix(in srgb,var(--foreground, CanvasText) 15%,transparent);
241
+ }
242
+
211
243
  .x1agitey {
212
244
  border-color: color-mix(in srgb,var(--hraness-design-procedural-ripple-color) 46%,transparent);
213
245
  }
@@ -444,6 +476,10 @@
444
476
  gap: .3rem 1rem;
445
477
  }
446
478
 
479
+ .xbcm6b9 {
480
+ gap: .3rem;
481
+ }
482
+
447
483
  .x1rcpt3j {
448
484
  gap: .45rem;
449
485
  }
@@ -452,6 +488,10 @@
452
488
  gap: .4rem;
453
489
  }
454
490
 
491
+ .xpraio3 {
492
+ gap: .55rem;
493
+ }
494
+
455
495
  .x339ura {
456
496
  gap: .5rem 1.25rem;
457
497
  }
@@ -788,6 +828,10 @@
788
828
  border-radius: .25rem;
789
829
  }
790
830
 
831
+ .xr5lfjo:focus-visible {
832
+ outline: 2px solid var(--focus, Highlight);
833
+ }
834
+
791
835
  .x11dsm9b:focus-visible {
792
836
  outline: 2px solid var(--hraness-marketing-accent, var(--focus, Highlight));
793
837
  }
@@ -1195,6 +1239,10 @@
1195
1239
  background-color: var(--_mark-accent);
1196
1240
  }
1197
1241
 
1242
+ .x17tv4j5 {
1243
+ background-color: var(--background, Canvas);
1244
+ }
1245
+
1198
1246
  .x11gw9ax {
1199
1247
  background-color: var(--background);
1200
1248
  }
@@ -1203,6 +1251,10 @@
1203
1251
  background-color: var(--card, var(--surface, #111217));
1204
1252
  }
1205
1253
 
1254
+ .x11tn3as {
1255
+ background-color: var(--foreground, CanvasText);
1256
+ }
1257
+
1206
1258
  .x1uslotl {
1207
1259
  background-color: var(--grid);
1208
1260
  }
@@ -1279,6 +1331,10 @@
1279
1331
  background-color: var(--secondary);
1280
1332
  }
1281
1333
 
1334
+ .xw51l6n {
1335
+ background-color: var(--surface, Canvas);
1336
+ }
1337
+
1282
1338
  .xuvt9l {
1283
1339
  background-color: var(--surface);
1284
1340
  }
@@ -1307,10 +1363,6 @@
1307
1363
  background-image: linear-gradient(142deg, #d8dce7 0, #666d7d 22%, #f4f5f8 43%, #4f5563 67%, #c9ced9 100%);
1308
1364
  }
1309
1365
 
1310
- .xs51ml9 {
1311
- background-image: linear-gradient(180deg,#ffffff38,transparent 52%),linear-gradient(160deg,transparent,color-mix(in srgb,var(--_mark-accent) 78%,black));
1312
- }
1313
-
1314
1366
  .x1hkejs3 {
1315
1367
  background-image: linear-gradient(180deg,#ffffff3d,transparent 48%),linear-gradient(160deg,color-mix(in srgb,var(--_mark-accent) 26%,transparent),color-mix(in srgb,var(--_mark-accent) 6%,transparent) 74%);
1316
1368
  }
@@ -1855,6 +1907,10 @@
1855
1907
  color: var(--_mark-on-accent, #f7f6f2);
1856
1908
  }
1857
1909
 
1910
+ .x19ydol1 {
1911
+ color: var(--background, Canvas);
1912
+ }
1913
+
1858
1914
  .x1gu5z8g {
1859
1915
  color: var(--card-foreground, var(--foreground, currentColor));
1860
1916
  }
@@ -1951,6 +2007,10 @@
1951
2007
  contain: paint;
1952
2008
  }
1953
2009
 
2010
+ .x1w8g7s4 {
2011
+ container-name: hraness-agent-setup;
2012
+ }
2013
+
1954
2014
  .x1bd2tma {
1955
2015
  container-name: hraness-platform-install;
1956
2016
  }
@@ -2059,6 +2119,10 @@
2059
2119
  font-family: inherit;
2060
2120
  }
2061
2121
 
2122
+ .x1nbx2l5 {
2123
+ font-family: var(--font-mono, ui-monospace,monospace);
2124
+ }
2125
+
2062
2126
  .xpw0y0u {
2063
2127
  font-family: var(--font-mono);
2064
2128
  }
@@ -2067,6 +2131,10 @@
2067
2131
  font-family: var(--font-text, system-ui,sans-serif);
2068
2132
  }
2069
2133
 
2134
+ .xtls1wf {
2135
+ font-family: var(--font-text, ui-sans-serif,system-ui,sans-serif);
2136
+ }
2137
+
2070
2138
  .x1d3so1v {
2071
2139
  font-family: var(--font-text);
2072
2140
  }
@@ -2351,10 +2419,18 @@
2351
2419
  grid-template-columns: minmax(0, 1fr) auto;
2352
2420
  }
2353
2421
 
2422
+ .x1mkdm3x {
2423
+ grid-template-columns: minmax(0, 1fr);
2424
+ }
2425
+
2354
2426
  .x1xdnkkc {
2355
2427
  grid-template-columns: minmax(12rem, .6fr) minmax(0, 1.4fr);
2356
2428
  }
2357
2429
 
2430
+ .x5m93ek {
2431
+ grid-template-columns: repeat(auto-fit, minmax(min(100%, 10rem), 1fr));
2432
+ }
2433
+
2358
2434
  .x1p797x9 {
2359
2435
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
2360
2436
  }
@@ -2367,6 +2443,14 @@
2367
2443
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
2368
2444
  }
2369
2445
 
2446
+ .x1v4bfo1 {
2447
+ grid-template-columns: repeat(auto-fit,minmax(min(100%,var(--_hraness-marketing-grid-track, 16rem)),1fr));
2448
+ }
2449
+
2450
+ .x1ui45ma {
2451
+ grid-template-columns: repeat(auto-fit,minmax(min(100%,var(--_hraness-marketing-grid-track, 18rem)),1fr));
2452
+ }
2453
+
2370
2454
  .x3g07o8 {
2371
2455
  grid-template-columns: repeat(var(--hraness-marketing-fact-columns, 4),minmax(0,1fr));
2372
2456
  }
@@ -2375,6 +2459,10 @@
2375
2459
  grid-template-columns: repeat(var(--hraness-marketing-pillar-columns, 3),minmax(0,1fr));
2376
2460
  }
2377
2461
 
2462
+ .xkewwhh {
2463
+ grid-template-columns: var(--_hraness-agent-setup-columns, minmax(0,1fr));
2464
+ }
2465
+
2378
2466
  .x16p6thf {
2379
2467
  grid-template-rows: auto minmax(0, 1fr);
2380
2468
  }
@@ -2471,6 +2559,10 @@
2471
2559
  inset-block-start: calc(100% + .5rem);
2472
2560
  }
2473
2561
 
2562
+ .xe388cy {
2563
+ inset-inline-end: .5rem;
2564
+ }
2565
+
2474
2566
  .xtijo5x {
2475
2567
  inset-inline-end: 0;
2476
2568
  }
@@ -2595,6 +2687,10 @@
2595
2687
  line-height: 1.6;
2596
2688
  }
2597
2689
 
2690
+ .x11m8ghp {
2691
+ line-height: 1.65;
2692
+ }
2693
+
2598
2694
  .xo5v014 {
2599
2695
  line-height: 1;
2600
2696
  }
@@ -2655,10 +2751,19 @@
2655
2751
  margin-block-start: .8rem;
2656
2752
  }
2657
2753
 
2754
+ .xsyyole {
2755
+ margin-block-start: 1.5rem;
2756
+ }
2757
+
2658
2758
  .xvc5jky {
2659
2759
  margin-inline-start: auto;
2660
2760
  }
2661
2761
 
2762
+ .xn48363 {
2763
+ -webkit-mask-image: linear-gradient(#000 55%, #0000);
2764
+ mask-image: linear-gradient(#000 55%, #0000);
2765
+ }
2766
+
2662
2767
  .x885qll {
2663
2768
  -webkit-mask-image: radial-gradient(#000 8%, #0000 78%);
2664
2769
  mask-image: radial-gradient(#000 8%, #0000 78%);
@@ -2957,10 +3062,18 @@
2957
3062
  outline-offset: -2px;
2958
3063
  }
2959
3064
 
3065
+ .x1v57pqu {
3066
+ outline-offset: -3px;
3067
+ }
3068
+
2960
3069
  .x1y3gkto {
2961
3070
  outline-offset: 1px;
2962
3071
  }
2963
3072
 
3073
+ .x1hl8ikr {
3074
+ outline-offset: 2px;
3075
+ }
3076
+
2964
3077
  .x1ewu8gn {
2965
3078
  outline-offset: 3px;
2966
3079
  }
@@ -3230,6 +3343,10 @@
3230
3343
  white-space: nowrap;
3231
3344
  }
3232
3345
 
3346
+ .x126k92a {
3347
+ white-space: pre-wrap;
3348
+ }
3349
+
3233
3350
  .x1sdyfia {
3234
3351
  white-space: pre;
3235
3352
  }
@@ -3410,6 +3527,14 @@
3410
3527
  background-color: #0000;
3411
3528
  }
3412
3529
 
3530
+ .x1jf9jbc:hover {
3531
+ background-color: var(--background, Canvas);
3532
+ }
3533
+
3534
+ .x1w11x55:hover {
3535
+ background-color: var(--foreground, CanvasText);
3536
+ }
3537
+
3413
3538
  .xr4j8zq:hover {
3414
3539
  background-color: var(--hraness-foil-surface, var(--surface, var(--background, Canvas)));
3415
3540
  }
@@ -3418,6 +3543,10 @@
3418
3543
  background-color: var(--hraness-marketing-surface, var(--surface, Canvas));
3419
3544
  }
3420
3545
 
3546
+ .x1lf5oka:hover {
3547
+ background-color: var(--surface, Canvas);
3548
+ }
3549
+
3421
3550
  .xn3cpwa:hover {
3422
3551
  background-image: none;
3423
3552
  }
@@ -3442,6 +3571,14 @@
3442
3571
  box-shadow: 0 1px 4px color-mix(in srgb,var(--foreground, CanvasText) 12%,transparent);
3443
3572
  }
3444
3573
 
3574
+ .x54addn:hover {
3575
+ color: var(--background, Canvas);
3576
+ }
3577
+
3578
+ .x10zor9s:hover {
3579
+ color: var(--foreground, CanvasText);
3580
+ }
3581
+
3445
3582
  .xucth70:hover {
3446
3583
  color: var(--hraness-marketing-accent-ink);
3447
3584
  }
@@ -3744,7 +3881,16 @@
3744
3881
  .x1e5rwe6.x1e5rwe6 {
3745
3882
  margin-inline-start: calc(-1 * var(--hraness-marketing-gutter));
3746
3883
  }
3884
+ }
3885
+
3886
+ @media (forced-colors: active) {
3887
+ .x1fww0mx.x1fww0mx {
3888
+ -webkit-mask-image: none;
3889
+ mask-image: none;
3890
+ }
3891
+ }
3747
3892
 
3893
+ @media (width <= 48rem) {
3748
3894
  .x6ri7ij.x6ri7ij {
3749
3895
  max-inline-size: 16ch;
3750
3896
  }
@@ -3982,6 +4128,10 @@
3982
4128
  border-top-width: 2px;
3983
4129
  }
3984
4130
 
4131
+ .x1of4z1n {
4132
+ bottom: .5rem;
4133
+ }
4134
+
3985
4135
  .x1ey2m1c {
3986
4136
  bottom: 0;
3987
4137
  }
@@ -4006,6 +4156,10 @@
4006
4156
  height: 1px;
4007
4157
  }
4008
4158
 
4159
+ .x1l36t39 {
4160
+ height: 1rem;
4161
+ }
4162
+
4009
4163
  .x36qwtl {
4010
4164
  height: 2px;
4011
4165
  }
@@ -4082,6 +4236,14 @@
4082
4236
  margin-bottom: var(--space-2);
4083
4237
  }
4084
4238
 
4239
+ .xz6j1ir {
4240
+ max-height: 10rem;
4241
+ }
4242
+
4243
+ .x1q2tmi7 {
4244
+ max-height: 11rem;
4245
+ }
4246
+
4085
4247
  .x193iq5w {
4086
4248
  max-width: 100%;
4087
4249
  }
@@ -4094,6 +4256,10 @@
4094
4256
  min-height: 2.5rem;
4095
4257
  }
4096
4258
 
4259
+ .xgbkey0 {
4260
+ min-height: 2.75rem;
4261
+ }
4262
+
4097
4263
  .xjjci79 {
4098
4264
  min-height: 250px;
4099
4265
  }
@@ -4102,6 +4268,10 @@
4102
4268
  min-height: 2rem;
4103
4269
  }
4104
4270
 
4271
+ .x13gjtz1 {
4272
+ min-height: 3.5rem;
4273
+ }
4274
+
4105
4275
  .xe8gcm {
4106
4276
  min-height: 3rem;
4107
4277
  }
@@ -4202,6 +4372,10 @@
4202
4372
  width: 1px;
4203
4373
  }
4204
4374
 
4375
+ .xcdlrvm {
4376
+ width: 1rem;
4377
+ }
4378
+
4205
4379
  .x1endk3i {
4206
4380
  width: 64%;
4207
4381
  }
@@ -4391,6 +4565,10 @@
4391
4565
  color: var(--hraness-marketing-muted);
4392
4566
  }
4393
4567
 
4568
+ .x13c0qn1::marker {
4569
+ content: "";
4570
+ }
4571
+
4394
4572
  .x1cpjm7i:before, .x1s928wv:after {
4395
4573
  content: "";
4396
4574
  }
@@ -5091,6 +5269,14 @@
5091
5269
  --_hraness-foil-mark-display: none;
5092
5270
  }
5093
5271
 
5272
+ .x9wro72 {
5273
+ --_hraness-marketing-grid-track: max(16rem,calc((100% - (var(--hraness-marketing-grid-columns) - 1) * 1rem) / var(--hraness-marketing-grid-columns)));
5274
+ }
5275
+
5276
+ .xwl1ywu {
5277
+ --_hraness-marketing-grid-track: max(18rem,calc((100% - (var(--hraness-marketing-grid-columns) - 1) * 1rem) / var(--hraness-marketing-grid-columns)));
5278
+ }
5279
+
5094
5280
  .xojny72 {
5095
5281
  --hraness-appearance-accent-foreground: var(--hraness-material-ink, var(--ui-accent-foreground, ButtonText));
5096
5282
  }
@@ -5183,6 +5369,26 @@
5183
5369
  --hraness-marketing-fact-columns: 4;
5184
5370
  }
5185
5371
 
5372
+ .x166dvhg {
5373
+ --hraness-marketing-grid-columns: 1;
5374
+ }
5375
+
5376
+ .x10q4e6v {
5377
+ --hraness-marketing-grid-columns: 2;
5378
+ }
5379
+
5380
+ .xyqi4l0 {
5381
+ --hraness-marketing-grid-columns: 3;
5382
+ }
5383
+
5384
+ .x1g57y38 {
5385
+ --hraness-marketing-grid-columns: 4;
5386
+ }
5387
+
5388
+ .xogmzgw {
5389
+ --hraness-marketing-grid-columns: initial;
5390
+ }
5391
+
5186
5392
  .xphms39 {
5187
5393
  --hraness-marketing-pillar-columns: 1;
5188
5394
  }
@@ -5337,6 +5543,12 @@
5337
5543
  }
5338
5544
  }
5339
5545
 
5546
+ @container hraness-agent-setup (width >= 42rem) {
5547
+ .x18n472x.x18n472x {
5548
+ --_hraness-agent-setup-columns: minmax(0,1fr) minmax(11rem,14rem);
5549
+ }
5550
+ }
5551
+
5340
5552
  @container hraness-platform-install (width <= 30rem) {
5341
5553
  .x1rp0mr4.x1rp0mr4 {
5342
5554
  --_hraness-platform-install-narrow-tab-font-size: .8125rem;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hraness/design-kit",
3
- "version": "0.31.1",
3
+ "version": "0.33.0",
4
4
  "description": "React components and CSS for Hraness apps and product sites: application shells, marketing sections, charts, themes, effects, and syntax highlighting. Built on @hraness/ui.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -292,7 +292,11 @@
292
292
  "src/mockups/index.ts",
293
293
  "src/mockups/surfaces.tsx",
294
294
  "src/mockups.css",
295
- "src/testing.ts"
295
+ "src/testing.ts",
296
+ "src/agent-setup.ts",
297
+ "src/react/agent-setup-prompt.tsx",
298
+ "src/react/agent-setup-prompt.stylex.ts",
299
+ "AGENT_SETUP.md"
296
300
  ],
297
301
  "scripts": {
298
302
  "build": "bun run ./scripts/build.ts",
@@ -306,7 +310,7 @@
306
310
  "browser:install": "bun ./node_modules/playwright-core/cli.js install chromium",
307
311
  "test:browser": "bun run test:browser:marketing && bun run test:browser:rest",
308
312
  "test:browser:marketing": "bun run ./scripts/product-marketing-browser.ts",
309
- "test:browser:rest": "bun run ./scripts/site-shell-browser.ts && bun run ./scripts/palette-browser.ts && bun run ./scripts/gallery-browser.ts && bun run ./scripts/global-error-browser.ts && bun run ./scripts/security-delivery-browser.ts && bun run ./scripts/paper-theme-browser.ts && bun run ./scripts/product-marketing-preset-browser.ts && bun run ./scripts/lantern-material-browser.ts && bun run ./scripts/foil-browser.ts && bun run ./scripts/hero-light-browser.ts && bun run ./scripts/status-page-browser.ts && bun run ./scripts/platform-install-browser.ts && bun run ./scripts/mockups-browser.ts",
313
+ "test:browser:rest": "bun run ./scripts/site-shell-browser.ts && bun run ./scripts/palette-browser.ts && bun run ./scripts/gallery-browser.ts && bun run ./scripts/global-error-browser.ts && bun run ./scripts/security-delivery-browser.ts && bun run ./scripts/paper-theme-browser.ts && bun run ./scripts/product-marketing-preset-browser.ts && bun run ./scripts/lantern-material-browser.ts && bun run ./scripts/foil-browser.ts && bun run ./scripts/hero-light-browser.ts && bun run ./scripts/status-page-browser.ts && bun run ./scripts/platform-install-browser.ts && bun run ./scripts/mockups-browser.ts && bun run ./scripts/agent-setup-browser.ts",
310
314
  "test:package": "bun run ./scripts/package-smoke.ts && bun run ./scripts/mockups-import.ts",
311
315
  "kb:refresh": "bunx --bun --package https://github.com/hraness/wordcell/releases/download/v0.24.0/hraness-wordcell-0.24.0.tgz wordcell refresh --root kb",
312
316
  "kb:check:lane": "bunx --bun --package https://github.com/hraness/wordcell/releases/download/v0.24.0/hraness-wordcell-0.24.0.tgz wordcell check --root kb --no-catalog",
@@ -6,7 +6,7 @@
6
6
  "name": "@hraness/design-kit",
7
7
  "path": ".",
8
8
  "visibility": "public",
9
- "version": "0.31.1"
9
+ "version": "0.33.0"
10
10
  }
11
11
  ],
12
12
  "contract": "hraness.portfolio-inventory/v1",
@@ -0,0 +1,47 @@
1
+ import type { ProviderMarkId } from "./provider-marks.js";
2
+
3
+ export type ComputerAgentId = "dot" | "grok-bot" | "muse" | "cursor" | "codex-app" | "devin";
4
+
5
+ /** A documented product entry or a link that fills a composer without sending. */
6
+ export interface AgentSetupDestination {
7
+ readonly id: ComputerAgentId;
8
+ readonly label: string;
9
+ readonly mark: ProviderMarkId;
10
+ readonly href: string;
11
+ readonly mode: "prefill" | "copy-and-open";
12
+ /** Filter cloud computers out when a product needs the user's local machine. */
13
+ readonly host: "local" | "cloud";
14
+ }
15
+
16
+ export interface AgentSetupTargetOptions {
17
+ /** Use prompt-free entry links when a product keeps its prompt out of URLs. */
18
+ readonly prefill?: boolean;
19
+ }
20
+
21
+ /** Cursor's documented maximum; longer prompts use copy and an ordinary entry link. */
22
+ export const MAX_AGENT_SETUP_URL = 10_000;
23
+
24
+ /**
25
+ * Product prompts stay with their callers. These destinations are shared by
26
+ * install pages; capability and URL sources are recorded in AGENT_SETUP.md.
27
+ * None of these actions sends a prompt or starts work automatically.
28
+ */
29
+ export function agentSetupTargets(
30
+ prompt: string,
31
+ options: AgentSetupTargetOptions = {},
32
+ ): readonly AgentSetupDestination[] {
33
+ if (typeof prompt !== "string" || prompt.trim() === "") throw new RangeError("Agent setup prompt must contain text.");
34
+ const encoded = options.prefill === false ? "" : encodeURIComponent(prompt);
35
+ const prefill = (href: string, entry: string) => options.prefill !== false && href.length <= MAX_AGENT_SETUP_URL
36
+ ? { href, mode: "prefill" as const }
37
+ : { href: entry, mode: "copy-and-open" as const };
38
+ const codex = prefill(`codex://new?prompt=${encoded}`, "https://chatgpt.com/codex");
39
+ return [
40
+ { id: "dot", label: "OpenAI Dot", mark: "openai", href: "https://chatgpt.com/", mode: "copy-and-open", host: "cloud" },
41
+ { id: "grok-bot", label: "Grok Bot", mark: "xai", href: "https://cursor.com/dashboard/bot", mode: "copy-and-open", host: "cloud" },
42
+ { id: "muse", label: "Muse", mark: "meta", href: "https://applink.muse.ai/", mode: "copy-and-open", host: "cloud" },
43
+ { id: "cursor", label: "Cursor", mark: "cursor", host: "local", ...prefill(`https://cursor.com/link/prompt?text=${encoded}`, "https://cursor.com/") },
44
+ { id: "codex-app", label: "Codex", mark: "codex", host: codex.mode === "prefill" ? "local" : "cloud", ...codex },
45
+ { id: "devin", label: "Devin", mark: "devin", href: "https://app.devin.ai/", mode: "copy-and-open", host: "cloud" },
46
+ ];
47
+ }
package/src/index.ts CHANGED
@@ -10,6 +10,7 @@ export * from "./status-page-html.js";
10
10
  export * from "./provider-marks.js";
11
11
  export * from "./platforms.js";
12
12
  export * from "./relative-time.js";
13
+ export * from "./agent-setup.js";
13
14
 
14
15
  export const colors = {
15
16
  light: {
@@ -40,10 +40,10 @@ function itemAt<T>(items: readonly T[], index: number, what: string): T {
40
40
  return item;
41
41
  }
42
42
 
43
- function assertCaption(caption: string, component: string): void {
44
- if (typeof caption !== "string" || caption.trim() === "") {
45
- throw new TypeError(`${component} needs a caption that says the picture is an illustration.`);
46
- }
43
+ function optionalText(value: string | undefined, component: string): string | undefined {
44
+ if (value === undefined) return undefined;
45
+ if (typeof value !== "string") throw new TypeError(`${component} text must be a string.`);
46
+ return value.trim() || undefined;
47
47
  }
48
48
 
49
49
  /** Arrow, Home, and End move between tabs, as in the WAI-ARIA tabs pattern. */
@@ -109,8 +109,8 @@ export function FitToWidth({ children, className, minWidth = 400 }: Readonly<{ c
109
109
  /* ModeShowcase */
110
110
  /* ------------------------------------------------------------------ */
111
111
 
112
- /** One choice on a showcase axis. `hint` says in one sentence what the choice does. */
113
- export type ShowcaseChoice<I extends string> = Readonly<{ id: I; label: string; hint: string }>;
112
+ /** One choice on a showcase axis. Add a hint only when its label needs context. */
113
+ export type ShowcaseChoice<I extends string> = Readonly<{ id: I; label: string; hint?: string }>;
114
114
 
115
115
  /** What a surface's render function receives. */
116
116
  export type ShowcaseState<M extends string, O extends string = string> = Readonly<{
@@ -143,8 +143,8 @@ export type ModeShowcaseProps<S extends string, M extends string, O extends stri
143
143
  initial?: Readonly<{ surface?: S; mode?: M; option?: O }>;
144
144
  /** A live line under the stage that says what the current state shows. */
145
145
  status?: (state: Readonly<{ surface: S; mode: M; option: O | undefined }>) => ReactNode;
146
- /** Required. Say it is an illustration, such as "Illustration. Names and text are made up." */
147
- caption: string;
146
+ /** Optional context that adds to the visual. Omit repeated descriptions or generic disclaimers. */
147
+ caption?: string;
148
148
  /** Page-window height in CSS pixels at full scale. */
149
149
  height?: number;
150
150
  /** Narrowest layout width before the stage scales down. */
@@ -180,7 +180,7 @@ export function ModeShowcase<S extends string, M extends string, O extends strin
180
180
  assertUniqueIds(surfaces, "ModeShowcase surface");
181
181
  assertUniqueIds(modes, "ModeShowcase mode");
182
182
  if (options !== undefined) assertUniqueIds(options, "ModeShowcase option");
183
- assertCaption(caption, "ModeShowcase");
183
+ const captionText = optionalText(caption, "ModeShowcase");
184
184
  if (!(height > 0)) throw new RangeError("ModeShowcase height must be positive.");
185
185
 
186
186
  const id = useId();
@@ -221,6 +221,11 @@ export function ModeShowcase<S extends string, M extends string, O extends strin
221
221
  };
222
222
 
223
223
  const statusNode = status?.({ mode, option, surface: surface.id });
224
+ const hint = [modeChoice.hint, optionInactive ? undefined : optionChoice?.hint]
225
+ .map((text) => optionalText(text, "ModeShowcase hint"))
226
+ .filter((text) => text !== undefined)
227
+ .join(" ");
228
+ const hasStatus = statusNode !== undefined && statusNode !== null && statusNode !== false && statusNode !== "";
224
229
  return (
225
230
  <figure
226
231
  aria-label={label?.(surface) ?? `Illustration of ${surface.label.toLowerCase()}`}
@@ -277,10 +282,7 @@ export function ModeShowcase<S extends string, M extends string, O extends strin
277
282
  </div>
278
283
  )}
279
284
  </div>
280
- <p className="hkm-showcase-hint">
281
- {modeChoice.hint}
282
- {optionChoice === undefined || optionInactive ? null : ` ${optionChoice.hint}`}
283
- </p>
285
+ {hint === "" ? null : <p className="hkm-showcase-hint">{hint}</p>}
284
286
  </div>
285
287
  <div
286
288
  aria-labelledby={surfaces.length > 1 ? `${id}-tab-${surface.id}` : undefined}
@@ -295,10 +297,12 @@ export function ModeShowcase<S extends string, M extends string, O extends strin
295
297
  {surface.render({ animated, mode, option, previousMode, theme })}
296
298
  </FitToWidth>
297
299
  </div>
298
- <figcaption className="hkm-showcase-caption">
299
- {statusNode === undefined ? null : <span aria-live="polite" className="hkm-showcase-status">{statusNode}</span>}
300
- <span>{caption}</span>
301
- </figcaption>
300
+ {!hasStatus && captionText === undefined ? null : (
301
+ <figcaption className="hkm-showcase-caption">
302
+ {hasStatus ? <span aria-live="polite" className="hkm-showcase-status">{statusNode}</span> : null}
303
+ {captionText === undefined ? null : <span>{captionText}</span>}
304
+ </figcaption>
305
+ )}
302
306
  </figure>
303
307
  );
304
308
  }
@@ -330,7 +334,7 @@ export function StepThrough({
330
334
  theme,
331
335
  }: Readonly<{
332
336
  steps: readonly ThroughStep[];
333
- caption: string;
337
+ caption?: string;
334
338
  initial?: string;
335
339
  label?: string;
336
340
  minWidth?: number;
@@ -338,7 +342,7 @@ export function StepThrough({
338
342
  className?: string;
339
343
  }>) {
340
344
  assertUniqueIds(steps, "StepThrough step");
341
- assertCaption(caption, "StepThrough");
345
+ const captionText = optionalText(caption, "StepThrough");
342
346
  const id = useId();
343
347
  const [index, setIndex] = useState(() => Math.max(0, steps.findIndex((step) => step.id === initial)));
344
348
  const [animated, setAnimated] = useState(false);
@@ -407,9 +411,9 @@ export function StepThrough({
407
411
  Next
408
412
  </button>
409
413
  </div>
410
- <figcaption className="hkm-showcase-caption">
411
- <span>{caption}</span>
412
- </figcaption>
414
+ {captionText === undefined ? null : (
415
+ <figcaption className="hkm-showcase-caption"><span>{captionText}</span></figcaption>
416
+ )}
413
417
  </figure>
414
418
  );
415
419
  }