@reopt-ai/opt-ui 1.11.0 → 1.12.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 (73) hide show
  1. package/COMPONENT_CATALOG.md +394 -201
  2. package/README.md +43 -5
  3. package/dist/core/index.cjs +2 -2
  4. package/dist/core/index.d.cts +2 -2
  5. package/dist/core/index.d.ts +2 -2
  6. package/dist/core/index.js +2 -2
  7. package/dist/docs/02-components/01-core.md +150 -84
  8. package/dist/docs/02-components/02-visuals.md +1 -1
  9. package/dist/docs/02-components/03-shells.md +258 -117
  10. package/dist/docs/02-components/04-surfaces.md +1 -1
  11. package/dist/docs/02-components/index.md +5 -5
  12. package/dist/docs/03-recipes/02-dashboards.md +126 -10
  13. package/dist/{field-sidebar-DAuN4jPV.cjs → field-sidebar-BYgEmdy0.cjs} +1539 -1536
  14. package/dist/{field-sidebar-BXl5RJ3q.js → field-sidebar-BuO37l4c.js} +1540 -1539
  15. package/dist/{field-sidebar-B5SQC35J.d.cts → field-sidebar-CrYlRZew.d.ts} +164 -154
  16. package/dist/{field-sidebar-CBeWE8xX.d.ts → field-sidebar-uXmoyvd7.d.cts} +164 -154
  17. package/dist/id-registry.cjs +78 -6
  18. package/dist/id-registry.d.cts +1 -2
  19. package/dist/id-registry.d.ts +1 -2
  20. package/dist/id-registry.js +78 -8
  21. package/dist/id-registry.json +168 -19
  22. package/dist/index.cjs +1127 -224
  23. package/dist/index.d.cts +567 -58
  24. package/dist/index.d.ts +567 -58
  25. package/dist/index.js +1118 -227
  26. package/dist/{key-pad-menu-BxTy_u0Q.d.cts → key-pad-menu-CwcY_Vps.d.cts} +2 -3
  27. package/dist/{key-pad-menu-wXkWn1I1.js → key-pad-menu-Di2aRGbM.js} +4 -6
  28. package/dist/{key-pad-menu-Cg6rZBie.cjs → key-pad-menu-SItoHPLu.cjs} +1 -1
  29. package/dist/{key-pad-menu-u5GTJl9B.d.ts → key-pad-menu-WBJShCJn.d.ts} +3 -4
  30. package/dist/meta.cjs +678 -19
  31. package/dist/meta.d.cts +12 -36
  32. package/dist/meta.d.ts +12 -36
  33. package/dist/meta.js +678 -21
  34. package/dist/query.d.cts +1 -2
  35. package/dist/query.d.ts +1 -2
  36. package/dist/query.js +0 -2
  37. package/dist/shells/index.cjs +1 -1
  38. package/dist/shells/index.d.cts +1 -1
  39. package/dist/shells/index.d.ts +1 -1
  40. package/dist/shells/index.js +1 -1
  41. package/dist/{text-truncate-DW78lg4S.d.cts → text-truncate-CQyfUZvq.d.cts} +31 -3
  42. package/dist/{text-truncate-DW78lg4S.d.ts → text-truncate-CQyfUZvq.d.ts} +31 -3
  43. package/dist/{text-truncate-C17HHCR-.js → text-truncate-DSuZECy0.js} +43 -10
  44. package/dist/{text-truncate-BZdL1k5Z.cjs → text-truncate-I1XLWmRa.cjs} +48 -7
  45. package/dist/theme/server.d.cts +1 -2
  46. package/dist/theme/server.d.ts +1 -2
  47. package/dist/theme/server.js +0 -2
  48. package/dist/visuals/index.js +0 -1
  49. package/package.json +4 -3
  50. package/dist/field-sidebar-B5SQC35J.d.cts.map +0 -1
  51. package/dist/field-sidebar-BXl5RJ3q.js.map +0 -1
  52. package/dist/field-sidebar-CBeWE8xX.d.ts.map +0 -1
  53. package/dist/id-registry.d.cts.map +0 -1
  54. package/dist/id-registry.d.ts.map +0 -1
  55. package/dist/id-registry.js.map +0 -1
  56. package/dist/index.d.cts.map +0 -1
  57. package/dist/index.d.ts.map +0 -1
  58. package/dist/index.js.map +0 -1
  59. package/dist/key-pad-menu-BxTy_u0Q.d.cts.map +0 -1
  60. package/dist/key-pad-menu-u5GTJl9B.d.ts.map +0 -1
  61. package/dist/key-pad-menu-wXkWn1I1.js.map +0 -1
  62. package/dist/meta.d.cts.map +0 -1
  63. package/dist/meta.d.ts.map +0 -1
  64. package/dist/meta.js.map +0 -1
  65. package/dist/query.d.cts.map +0 -1
  66. package/dist/query.d.ts.map +0 -1
  67. package/dist/query.js.map +0 -1
  68. package/dist/text-truncate-C17HHCR-.js.map +0 -1
  69. package/dist/text-truncate-DW78lg4S.d.cts.map +0 -1
  70. package/dist/text-truncate-DW78lg4S.d.ts.map +0 -1
  71. package/dist/theme/server.d.cts.map +0 -1
  72. package/dist/theme/server.d.ts.map +0 -1
  73. package/dist/theme/server.js.map +0 -1
@@ -380,18 +380,134 @@ export function ActivityDashboard() {
380
380
  }
381
381
  ```
382
382
 
383
+ ## 4. Analytics Detail Investigation
384
+
385
+ Keep the result list visible while the reader investigates one profile. The
386
+ row owns identity fallback, the flyout owns disclosure and focus return, and
387
+ the evidence inside the panel stays semantic: facts are a definition list,
388
+ score axes are named, and events preserve session boundaries.
389
+
390
+ ```tsx
391
+ "use client";
392
+
393
+ import { useState } from "react";
394
+ import {
395
+ Button,
396
+ DescriptionList,
397
+ EventTimeline,
398
+ Flyout,
399
+ Identity,
400
+ ScoreBreakdown,
401
+ type EventTimelineGroup,
402
+ } from "@reopt-ai/opt-ui";
403
+
404
+ const customer = {
405
+ id: "usr_01J5Q8M2N7W4",
406
+ name: "Mina Park",
407
+ email: "mina.park@example.com",
408
+ company: "Northstar Labs",
409
+ };
410
+
411
+ const sessions: EventTimelineGroup[] = [
412
+ {
413
+ id: "checkout-recovery",
414
+ title: "Checkout recovery",
415
+ meta: "12m · 2 events",
416
+ items: [
417
+ {
418
+ id: "order",
419
+ name: "Order completed",
420
+ timestamp: "2026-08-27T01:17:44.000Z",
421
+ tone: "success",
422
+ properties: { order_id: "R-1842", value: 128000 },
423
+ },
424
+ {
425
+ id: "coupon",
426
+ name: "Recovery coupon applied",
427
+ timestamp: "2026-08-27T01:14:09.000Z",
428
+ properties: { code: "RECOVER20" },
429
+ },
430
+ ],
431
+ },
432
+ ];
433
+
434
+ export function CustomerInvestigation() {
435
+ const [open, setOpen] = useState(false);
436
+
437
+ return (
438
+ <div className="grid gap-group lg:grid-cols-[1fr_30rem]">
439
+ <button type="button" onClick={() => setOpen(true)}>
440
+ <Identity
441
+ name={customer.name}
442
+ secondary={customer.email}
443
+ id={customer.id}
444
+ state="identified"
445
+ />
446
+ </button>
447
+
448
+ <Flyout
449
+ open={open}
450
+ onClose={() => setOpen(false)}
451
+ type="inline"
452
+ title={customer.name}
453
+ footer={
454
+ <Button variant="secondary" onClick={() => setOpen(false)}>
455
+ Close
456
+ </Button>
457
+ }
458
+ >
459
+ <div className="flex flex-col gap-group">
460
+ <DescriptionList
461
+ columns={2}
462
+ items={[
463
+ {
464
+ id: "id",
465
+ term: "Profile ID",
466
+ description: customer.id,
467
+ copyValue: customer.id,
468
+ },
469
+ {
470
+ id: "company",
471
+ term: "Company",
472
+ description: customer.company,
473
+ },
474
+ ]}
475
+ />
476
+ <ScoreBreakdown
477
+ score={76}
478
+ axes={[
479
+ { id: "recency", label: "Recency", value: 92, weight: 0.5 },
480
+ { id: "depth", label: "Depth", value: 60, weight: 0.5 },
481
+ ]}
482
+ />
483
+ <EventTimeline groups={sessions} showGaps />
484
+ </div>
485
+ </Flyout>
486
+ </div>
487
+ );
488
+ }
489
+ ```
490
+
491
+ Do not wrap an interactive `StatCard` or `Identity` row in a second control.
492
+ Let the component or one row button own the focus stop. `Flyout` is deliberately
493
+ non-modal, so use it for comparison and investigation; use `Dialog` when the
494
+ reader must finish or cancel a blocking task before returning to the page.
495
+
383
496
  ## Composition Notes
384
497
 
385
- | Pattern | Key Components | Data Types |
386
- | ------------------- | ---------------------------------------- | ---------------------------------------- |
387
- | KPI stats row | `SummaryRow` | `StatCard[]` (aliased as `StatCardType`) |
388
- | Trend visualization | `TrendChart` or `ChartContainer` + chart | `ChartDataPoint[]` + `ChartSeriesDef[]` |
389
- | Tabular detail | `DataTable` | `ColumnDef<T>[]` + data array |
390
- | Date filtering | `TimeRangeSelector` | `DateRange` |
391
- | Segment filtering | `FilterBar` | `FilterGroupDef[]` |
392
- | Quick metrics | `MetricsCard` | inline props + `sparklineData: number[]` |
393
- | Activity timeline | `ActivityFeed` | `ActivityDef[]` |
394
- | Task tracking | `TaskList` | `TaskDef[]` |
498
+ | Pattern | Key Components | Data Types |
499
+ | -------------------- | ---------------------------------------- | ---------------------------------------- |
500
+ | KPI stats row | `SummaryRow` | `StatCard[]` (aliased as `StatCardType`) |
501
+ | Trend visualization | `TrendChart` or `ChartContainer` + chart | `ChartDataPoint[]` + `ChartSeriesDef[]` |
502
+ | Tabular detail | `DataTable` | `ColumnDef<T>[]` + data array |
503
+ | Date filtering | `TimeRangeSelector` | `DateRange` |
504
+ | Segment filtering | `FilterBar` | `FilterGroupDef[]` |
505
+ | Quick metrics | `MetricsCard` | inline props + `sparklineData: number[]` |
506
+ | Activity timeline | `ActivityFeed` | `ActivityDef[]` |
507
+ | Detail investigation | `Identity`, `Flyout`, `DescriptionList` | profile + labelled facts |
508
+ | Explainable score | `ScoreBreakdown` | `ScoreAxis[]` + `ScoreBand[]` |
509
+ | Session evidence | `EventTimeline` | `EventTimelineGroup[]` |
510
+ | Task tracking | `TaskList` | `TaskDef[]` |
395
511
 
396
512
  All page-level layouts use `SurfaceLayout` for consistent `gap-section` spacing.
397
513
  Use `gap-group` for grid gaps and `gap-element` for tightly spaced items.