@ramme-io/ui 4.0.1 → 4.1.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 (64) hide show
  1. package/README.md +158 -7
  2. package/dist/blocks/ai/Actions.js +2 -2
  3. package/dist/blocks/ai/PromptInput.js +6 -6
  4. package/dist/component-registry.js +386 -359
  5. package/dist/components/ai/AIChatThread/AIChatThread.js +81 -73
  6. package/dist/components/ai/ArchitectureReferenceCard/ArchitectureReferenceCard.d.ts +28 -0
  7. package/dist/components/ai/ArchitectureReferenceCard/ArchitectureReferenceCard.js +70 -0
  8. package/dist/components/ai/ArchitectureReferenceCard/index.d.ts +2 -0
  9. package/dist/components/ai/CounterpartyGraphCard/CounterpartyGraphCard.d.ts +30 -0
  10. package/dist/components/ai/CounterpartyGraphCard/CounterpartyGraphCard.js +82 -0
  11. package/dist/components/ai/CounterpartyGraphCard/index.d.ts +2 -0
  12. package/dist/components/ai/DivergenceMetricsCard/DivergenceMetricsCard.d.ts +29 -0
  13. package/dist/components/ai/DivergenceMetricsCard/DivergenceMetricsCard.js +69 -0
  14. package/dist/components/ai/DivergenceMetricsCard/index.d.ts +2 -0
  15. package/dist/components/ai/KeyInjectionOverlay.d.ts +10 -0
  16. package/dist/components/ai/KeyInjectionOverlay.js +11 -11
  17. package/dist/components/auth/AuthLayout.js +4 -4
  18. package/dist/components/data-display/CodeBlock.d.ts +33 -7
  19. package/dist/components/data-display/CodeBlock.js +134 -41
  20. package/dist/components/data-display/Table.js +8 -8
  21. package/dist/components/feedback/EmptyState.js +9 -9
  22. package/dist/components/feedback/ToastProvider.js +4 -4
  23. package/dist/components/forms/Checkbox.js +5 -5
  24. package/dist/components/forms/Radio.js +6 -6
  25. package/dist/components/forms/SegmentedControl.d.ts +1 -1
  26. package/dist/components/forms/SegmentedControl.js +28 -11
  27. package/dist/components/forms/Textarea.js +9 -9
  28. package/dist/components/forms/ToggleSwitch.js +9 -9
  29. package/dist/components/layout/AboutRamme.d.ts +8 -0
  30. package/dist/components/layout/Accordion.js +13 -13
  31. package/dist/components/layout/AppShell.js +7 -7
  32. package/dist/components/layout/DetailDrawer.js +2 -2
  33. package/dist/components/layout/Drawer.js +50 -51
  34. package/dist/components/layout/List.js +9 -9
  35. package/dist/components/layout/Modal.js +5 -5
  36. package/dist/components/layout/PageHeader.js +7 -7
  37. package/dist/components/layout/SectionHeader.js +4 -4
  38. package/dist/components/layout/SettingsContainer.d.ts +12 -0
  39. package/dist/components/layout/SettingsContainer.js +20 -18
  40. package/dist/components/layout/Sidebar.js +1 -1
  41. package/dist/components/layout/UserNav.d.ts +13 -0
  42. package/dist/components/layout/UserNav.js +17 -17
  43. package/dist/components/molecular/ConnectorOverlay.d.ts +12 -0
  44. package/dist/components/navigation/Breadcrumbs.js +8 -8
  45. package/dist/components/navigation/Menu.js +6 -6
  46. package/dist/components/navigation/MobileNav.js +1 -1
  47. package/dist/components/navigation/Pagination.js +46 -41
  48. package/dist/components/navigation/Stepper.js +17 -17
  49. package/dist/components/navigation/Tabs.js +12 -12
  50. package/dist/components/theme/ThemeLab.d.ts +7 -1
  51. package/dist/components/theme/ThemeLab.js +175 -154
  52. package/dist/contexts/ThemeContext.js +111 -82
  53. package/dist/data/mockData.d.ts +0 -3
  54. package/dist/index.css +1 -1
  55. package/dist/index.d.ts +8 -0
  56. package/dist/index.js +203 -185
  57. package/dist/lib/hooks/useBodyScrollLock.d.ts +27 -0
  58. package/dist/lib/hooks/useBodyScrollLock.js +18 -0
  59. package/dist/lib/theme/themeUtils.d.ts +21 -0
  60. package/dist/lib/theme/themeUtils.js +31 -17
  61. package/dist/wizardManifest.js +234 -9
  62. package/package.json +2 -3
  63. package/src/wizardManifest.ts +234 -9
  64. package/tailwind.preset.js +98 -10
@@ -1,17 +1,18 @@
1
+ import { DEFAULT_THEME_TOKENS as d } from "@ramme-io/shared";
1
2
  const m = (o, p) => {
2
3
  const a = o.split(" ").map(Number);
3
4
  if (a.length !== 3) return o;
4
5
  const r = (t) => Math.max(0, Math.min(255, t));
5
6
  return `${r(a[0] + p)} ${r(a[1] + p)} ${r(a[2] + p)}`;
6
- }, d = (o) => {
7
+ }, g = (o) => {
7
8
  const [p, a, r] = o.split(" ").map(Number);
8
9
  return (0.2126 * p + 0.7152 * a + 0.0722 * r) / 255 > 0.45 ? "15 23 42" : "255 255 255";
9
- }, h = (o, p) => {
10
+ }, f = (o, p) => {
10
11
  if (!o || typeof o != "object") return;
11
12
  const a = p || document.documentElement, r = { ...o }, t = r["--app-primary-color"];
12
- t && (r["--app-primary-foreground-color"] = d(t));
13
+ t && (r["--app-primary-foreground-color"] = g(t));
13
14
  const l = r["--app-bg-color"];
14
- l && (r["--app-text-color"] = d(l)), Object.entries({
15
+ l && (r["--app-text-color"] = g(l)), Object.entries({
15
16
  "--primary": "--app-primary-color",
16
17
  "--bg": "--app-bg-color",
17
18
  "--text": "--app-text-color",
@@ -32,33 +33,44 @@ const m = (o, p) => {
32
33
  ].join(", "), r["--app-secondary-color"] || (r["--app-secondary-color"] = "100 116 139"), r["--app-accent-color"] || (r["--app-accent-color"] = r["--app-primary-color"]), r["--app-input-bg-color"] || (r["--app-input-bg-color"] = r["--app-card-bg-color"]), r["--app-input-border-color"] || (r["--app-input-border-color"] = r["--app-border-color"]), r["--app-border-radius-md"] || (r["--app-border-radius-md"] = "0.375rem"), Object.entries(r).forEach(([s, i]) => {
33
34
  s.startsWith("--app-") && a.style.setProperty(s, String(i));
34
35
  });
35
- }, u = (o, p) => {
36
+ }, b = (o, p) => {
36
37
  const a = document.head, r = "dynamic-google-fonts", t = document.getElementById(r);
37
38
  t && a.removeChild(t);
38
39
  const l = `${o.replace(/ /g, "+")}:wght@400;700&family=${p.replace(/ /g, "+")}:wght@400;500;700`, n = document.createElement("link");
39
40
  n.id = r, n.rel = "stylesheet", n.crossOrigin = "anonymous", n.href = `https://fonts.googleapis.com/css2?family=${l}&display=swap`, a.insertBefore(n, a.firstChild);
40
41
  const e = document.documentElement;
41
42
  e.style.setProperty("--app-font-sans", `"${p}", sans-serif`), e.style.setProperty("--app-font-serif", `"${o}", serif`), console.log(`[FontEngine] Applied: ${o} (H) / ${p} (B)`);
42
- }, f = (o) => {
43
+ }, y = (o) => {
43
44
  const p = o.replace("#", ""), a = parseInt(p.substring(0, 2), 16), r = parseInt(p.substring(2, 4), 16), t = parseInt(p.substring(4, 6), 16);
44
45
  return `${a} ${r} ${t}`;
45
- }, g = {
46
+ }, u = {
46
47
  none: "0",
47
48
  sm: "0.25rem",
48
49
  md: "0.375rem",
49
50
  lg: "0.5rem",
50
51
  full: "9999px"
51
- }, b = (o) => ({
52
+ }, $ = [
53
+ "--app-primary-color",
54
+ "--app-secondary-color",
55
+ "--app-success-color",
56
+ "--app-warning-color",
57
+ "--app-danger-color",
58
+ "--app-border-radius-md"
59
+ ], E = (o) => o ? Object.keys(d).some((p) => o[p] !== void 0 && o[p] !== d[p]) : !1, M = (o) => ({
52
60
  "--app-primary-color": o.primary ?? "13 110 253",
53
61
  "--app-secondary-color": o.neutral ?? "24 24 27",
54
62
  "--app-success-color": o.success ?? "34 197 94",
55
63
  "--app-warning-color": o.warning ?? "234 179 8",
56
- "--app-destructive-color": o.destructive ?? "239 68 68",
57
- "--app-border-radius-md": g[o.radius ?? "md"] ?? "0.375rem"
64
+ // NOT `--app-destructive-color`, which this wrote until now: that variable
65
+ // is defined nowhere in index.css and read by nothing, so the Destructive
66
+ // swatch in ThemeLab changed a value no stylesheet consumed. The token the
67
+ // preset actually maps `destructive` on to is `--app-danger-color`.
68
+ "--app-danger-color": o.destructive ?? "239 68 68",
69
+ "--app-border-radius-md": u[o.radius ?? "md"] ?? "0.375rem"
58
70
  }), c = (o = 0, p = 255) => {
59
71
  const a = Math.floor(Math.random() * (p - o) + o), r = Math.floor(Math.random() * (p - o) + o), t = Math.floor(Math.random() * (p - o) + o);
60
72
  return `${a} ${r} ${t}`;
61
- }, y = () => {
73
+ }, T = () => {
62
74
  const o = Math.random() > 0.5, p = o ? c(10, 40) : c(240, 255), a = o ? c(220, 255) : c(20, 60), r = c(50, 200);
63
75
  return {
64
76
  "--app-primary-color": r,
@@ -73,11 +85,13 @@ const m = (o, p) => {
73
85
  };
74
86
  };
75
87
  export {
76
- h as applyThemeToDom,
77
- y as generateRandomTheme,
78
- d as getContrastColor,
79
- f as hexToRgbTriplet,
80
- u as loadGoogleFont,
88
+ $ as THEME_TOKEN_VARS,
89
+ f as applyThemeToDom,
90
+ T as generateRandomTheme,
91
+ g as getContrastColor,
92
+ y as hexToRgbTriplet,
93
+ E as isCustomTheme,
94
+ b as loadGoogleFont,
81
95
  c as randomRgb,
82
- b as tokensToVars
96
+ M as tokensToVars
83
97
  };
@@ -398,6 +398,25 @@ const e = {
398
398
  humanLabel: "AIChatThread",
399
399
  humanDescription: "A complete chat surface — message history, streaming indicator, error banner, provider/model attribution, and the composer. Strategic purpose: the presentational half of a chat feature, driven entirely by props from kernel's useRammeAI(). It holds no transport of its own, and takes a `renderMessage` override so products can add markdown or rich rendering without pulling those deps into @ramme-io/ui."
400
400
  },
401
+ {
402
+ id: "architecture-reference-card",
403
+ name: "ArchitectureReferenceCard",
404
+ version: "1.0.0",
405
+ description: "AI-generated card summarizing this platform's own data architecture — stack, data model, AI pipelines, and sentinel fleet",
406
+ tags: [
407
+ "ai",
408
+ "architecture",
409
+ "reference",
410
+ "generative-ui"
411
+ ],
412
+ category: "ai",
413
+ props: [],
414
+ importPath: "./components/ai/ArchitectureReferenceCard/ArchitectureReferenceCard",
415
+ filePath: "src/components/ai/ArchitectureReferenceCard/ArchitectureReferenceCard.tsx",
416
+ sku: "@molecule/ai/architecture-reference-card",
417
+ humanLabel: "ArchitectureReferenceCard",
418
+ humanDescription: "AI-generated card summarizing this platform's own data architecture — stack, data model, AI pipelines, and sentinel fleet"
419
+ },
401
420
  {
402
421
  id: "company-profile-card",
403
422
  name: "CompanyProfileCard",
@@ -425,6 +444,77 @@ const e = {
425
444
  humanLabel: "CompanyProfileCard",
426
445
  humanDescription: "A company summary for a ticker — sector, industry, and description — fetched on demand and cached. Strategic purpose: a generative-UI block an AI tool call can render directly into a chat thread. Surfaces its own provenance, distinguishing a live fetch from a cached or stale answer instead of presenting all three as equally fresh."
427
446
  },
447
+ {
448
+ id: "counterparty-graph-card",
449
+ name: "CounterpartyGraphCard",
450
+ version: "1.0.0",
451
+ description: "AI-generated counterparty relationship card showing suppliers, customers, partners, and competitors inferred from alternative signals",
452
+ tags: [
453
+ "ai",
454
+ "counterparty",
455
+ "graph",
456
+ "relationships",
457
+ "generative-ui"
458
+ ],
459
+ category: "ai",
460
+ props: [],
461
+ importPath: "./components/ai/CounterpartyGraphCard/CounterpartyGraphCard",
462
+ filePath: "src/components/ai/CounterpartyGraphCard/CounterpartyGraphCard.tsx",
463
+ sku: "@molecule/ai/counterparty-graph-card",
464
+ humanLabel: "CounterpartyGraphCard",
465
+ humanDescription: "AI-generated counterparty relationship card showing suppliers, customers, partners, and competitors inferred from alternative signals"
466
+ },
467
+ {
468
+ id: "divergence-metrics-card",
469
+ name: "DivergenceMetricsCard",
470
+ version: "1.0.0",
471
+ description: "AI-generated card showing operational and customer divergence scores — a signed delta between expected and observed performance",
472
+ tags: [
473
+ "ai",
474
+ "divergence",
475
+ "metrics",
476
+ "generative-ui"
477
+ ],
478
+ category: "ai",
479
+ props: [],
480
+ importPath: "./components/ai/DivergenceMetricsCard/DivergenceMetricsCard",
481
+ filePath: "src/components/ai/DivergenceMetricsCard/DivergenceMetricsCard.tsx",
482
+ sku: "@molecule/ai/divergence-metrics-card",
483
+ humanLabel: "DivergenceMetricsCard",
484
+ humanDescription: "AI-generated card showing operational and customer divergence scores — a signed delta between expected and observed performance"
485
+ },
486
+ {
487
+ id: "key-injection-overlay",
488
+ name: "KeyInjectionOverlay",
489
+ version: "1.0.0",
490
+ description: "Blocks the app and collects an AI provider key when the gateway reports one is missing or expired. Strategic purpose: the BYOK prompt, in one place, so a key request looks the same everywhere and never becomes an inline form somebody rebuilds per feature. Renders nothing unless status is 'BYOK_REQUIRED' or 'KEY_EXPIRED', so it can stay mounted at the shell level.",
491
+ tags: [
492
+ "ai",
493
+ "byok",
494
+ "overlay",
495
+ "auth",
496
+ "gateway",
497
+ "key"
498
+ ],
499
+ category: "ai",
500
+ props: [
501
+ {
502
+ name: "status",
503
+ type: "string",
504
+ description: "Gateway status. The overlay shows only for 'BYOK_REQUIRED' or 'KEY_EXPIRED'."
505
+ },
506
+ {
507
+ name: "setSessionKey",
508
+ type: "function",
509
+ description: "Receives the entered key when the form is submitted."
510
+ }
511
+ ],
512
+ importPath: "./components/ai/KeyInjectionOverlay",
513
+ filePath: "src/components/ai/KeyInjectionOverlay.tsx",
514
+ sku: "@molecule/ai/key-injection-overlay",
515
+ humanLabel: "KeyInjectionOverlay",
516
+ humanDescription: "Blocks the app and collects an AI provider key when the gateway reports one is missing or expired. Strategic purpose: the BYOK prompt, in one place, so a key request looks the same everywhere and never becomes an inline form somebody rebuilds per feature. Renders nothing unless status is 'BYOK_REQUIRED' or 'KEY_EXPIRED', so it can stay mounted at the shell level."
517
+ },
428
518
  {
429
519
  id: "live-quote-card",
430
520
  name: "LiveQuoteCard",
@@ -751,31 +841,58 @@ const e = {
751
841
  {
752
842
  id: "code-block",
753
843
  name: "CodeBlock",
754
- version: "1.0.0",
755
- description: "A component for displaying formatted and syntax-highlighted code snippets.",
844
+ version: "1.0.1",
845
+ description: "The one way to show code. Syntax-highlighted, theme-aware, with a copy button that works on touch and outside secure contexts. Use for every snippet in docs and tutorials — do not hand-roll a <pre>. Long lines scroll inside the block so the page never scrolls sideways on a phone.",
756
846
  tags: [
757
847
  "ui",
758
848
  "data-display",
759
- "code"
849
+ "code",
850
+ "docs",
851
+ "tutorial"
760
852
  ],
761
853
  category: "ui",
762
854
  props: [
763
855
  {
764
856
  name: "code",
765
857
  type: "string",
766
- description: "The string of code to display."
858
+ description: "The snippet to display. Outer blank lines are trimmed."
767
859
  },
768
860
  {
769
861
  name: "language",
770
862
  type: "string",
771
- description: "The programming language for syntax highlighting (e.g., 'tsx', 'css', 'javascript')."
863
+ description: "Prism language id — 'tsx', 'bash', 'css', 'json'. Defaults to 'tsx'."
864
+ },
865
+ {
866
+ name: "filename",
867
+ type: "string",
868
+ description: "Header label. Prefer a real path like 'src/App.tsx'; falls back to the language."
869
+ },
870
+ {
871
+ name: "showLineNumbers",
872
+ type: "boolean",
873
+ description: "Show gutter line numbers. Use when the surrounding prose cites line numbers."
874
+ },
875
+ {
876
+ name: "highlightLines",
877
+ type: "number[]",
878
+ description: '1-based lines to emphasise, for "change this line" steps.'
879
+ },
880
+ {
881
+ name: "wrap",
882
+ type: "boolean",
883
+ description: "Wrap long lines instead of scrolling them. Off by default."
884
+ },
885
+ {
886
+ name: "hideCopy",
887
+ type: "boolean",
888
+ description: "Hide the copy button, for snippets that are not meant to be run."
772
889
  }
773
890
  ],
774
891
  importPath: "./components/data-display/CodeBlock",
775
892
  filePath: "src/components/data-display/CodeBlock.tsx",
776
893
  sku: "@atom/primitive/code-block",
777
894
  humanLabel: "CodeBlock",
778
- humanDescription: "A component for displaying formatted and syntax-highlighted code snippets."
895
+ humanDescription: "The one way to show code. Syntax-highlighted, theme-aware, with a copy button that works on touch and outside secure contexts. Use for every snippet in docs and tutorials — do not hand-roll a <pre>. Long lines scroll inside the block so the page never scrolls sideways on a phone."
779
896
  },
780
897
  {
781
898
  id: "data-table",
@@ -1748,8 +1865,8 @@ const e = {
1748
1865
  {
1749
1866
  id: "segmented-control",
1750
1867
  name: "SegmentedControl",
1751
- version: "1.0.0",
1752
- description: 'A theme-aware linear toggle component. Ideal for switching between discrete modes (e.g., "Map / List").',
1868
+ version: "1.0.1",
1869
+ description: 'A theme-aware linear toggle component. Ideal for switching between discrete modes (e.g., "Map / List"). Every size clears the 24px WCAG 2.5.8 (AA) target-size minimum — xs 24px, sm ~25px, md ~36px. None reaches the 44px 2.5.5 (AAA) figure, so for a primary control on a touch screen prefer md or give the control its own 44px row; xs and sm are density sizes for pointer-driven toolbars.',
1753
1870
  tags: [
1754
1871
  "input",
1755
1872
  "toggle",
@@ -1763,7 +1880,7 @@ const e = {
1763
1880
  filePath: "src/components/forms/SegmentedControl.tsx",
1764
1881
  sku: "@atom/form/segmented-control",
1765
1882
  humanLabel: "SegmentedControl",
1766
- humanDescription: 'A theme-aware linear toggle component. Ideal for switching between discrete modes (e.g., "Map / List").'
1883
+ humanDescription: 'A theme-aware linear toggle component. Ideal for switching between discrete modes (e.g., "Map / List"). Every size clears the 24px WCAG 2.5.8 (AA) target-size minimum — xs 24px, sm ~25px, md ~36px. None reaches the 44px 2.5.5 (AAA) figure, so for a primary control on a touch screen prefer md or give the control its own 44px row; xs and sm are density sizes for pointer-driven toolbars.'
1767
1884
  },
1768
1885
  {
1769
1886
  id: "select",
@@ -2238,6 +2355,48 @@ const e = {
2238
2355
  humanLabel: "SectionHeader",
2239
2356
  humanDescription: "A simple, consistent header for organizing sections of content within a page."
2240
2357
  },
2358
+ {
2359
+ id: "connector-overlay",
2360
+ name: "ConnectorOverlay",
2361
+ version: "1.0.0",
2362
+ description: "Covers a panel while its data source is connecting, and explains itself when the connection fails. Strategic purpose: the standard treatment for a live region that has no data yet — telemetry panels, market feeds, device dashboards — so every product says the same thing about a dead socket instead of inventing a spinner. Renders nothing once status is 'connected', so it can stay mounted.",
2363
+ tags: [
2364
+ "feedback",
2365
+ "overlay",
2366
+ "connection",
2367
+ "realtime",
2368
+ "loading",
2369
+ "error"
2370
+ ],
2371
+ category: "feedback",
2372
+ props: [
2373
+ {
2374
+ name: "status",
2375
+ type: "string",
2376
+ description: "'connecting' | 'connected' | 'error'. Renders null when connected."
2377
+ },
2378
+ {
2379
+ name: "message",
2380
+ type: "ReactNode",
2381
+ description: "Replaces the default copy for the current status."
2382
+ },
2383
+ {
2384
+ name: "onRetry",
2385
+ type: "function",
2386
+ description: "Shows a retry action in the error state when provided."
2387
+ },
2388
+ {
2389
+ name: "className",
2390
+ type: "string",
2391
+ description: "Additional CSS classes."
2392
+ }
2393
+ ],
2394
+ importPath: "./components/molecular/ConnectorOverlay",
2395
+ filePath: "src/components/molecular/ConnectorOverlay.tsx",
2396
+ sku: "@molecule/feedback/connector-overlay",
2397
+ humanLabel: "ConnectorOverlay",
2398
+ humanDescription: "Covers a panel while its data source is connecting, and explains itself when the connection fails. Strategic purpose: the standard treatment for a live region that has no data yet — telemetry panels, market feeds, device dashboards — so every product says the same thing about a dead socket instead of inventing a spinner. Renders nothing once status is 'connected', so it can stay mounted."
2399
+ },
2241
2400
  {
2242
2401
  id: "data-card",
2243
2402
  name: "DataCard",
@@ -2978,6 +3137,26 @@ const e = {
2978
3137
  humanLabel: "AuthLayout",
2979
3138
  humanDescription: "The centred, chrome-free frame for unauthenticated screens, rendering the matched child route via an Outlet. Strategic purpose: sign-in and sign-up must not show the app shell's sidebar or header — wrap those routes in this instead of conditionally hiding chrome inside AppShell."
2980
3139
  },
3140
+ {
3141
+ id: "about-ramme",
3142
+ name: "AboutRamme",
3143
+ version: "1.0.0",
3144
+ description: `The "About" panel for a Settings Console — what the framework is, which packages make it up, and why it is built this way. Strategic purpose: ships the explanation with the framework so every product's about screen stays accurate as the architecture moves, instead of each one carrying a copy that goes stale. Takes no props; drop it into a settings tab.`,
3145
+ tags: [
3146
+ "layout",
3147
+ "settings",
3148
+ "about",
3149
+ "documentation",
3150
+ "panel"
3151
+ ],
3152
+ category: "layout",
3153
+ props: [],
3154
+ importPath: "./components/layout/AboutRamme",
3155
+ filePath: "src/components/layout/AboutRamme.tsx",
3156
+ sku: "@chassis/layout/about-ramme",
3157
+ humanLabel: "AboutRamme",
3158
+ humanDescription: `The "About" panel for a Settings Console — what the framework is, which packages make it up, and why it is built this way. Strategic purpose: ships the explanation with the framework so every product's about screen stays accurate as the architecture moves, instead of each one carrying a copy that goes stale. Takes no props; drop it into a settings tab.`
3159
+ },
2981
3160
  {
2982
3161
  id: "accordion-item",
2983
3162
  name: "AccordionItem",
@@ -4122,6 +4301,52 @@ const e = {
4122
4301
  sku: "@chassis/layout/user-nav",
4123
4302
  humanLabel: "UserNav",
4124
4303
  humanDescription: "The signed-in user's avatar menu — identity plus account actions. Strategic purpose: the standard account affordance for the app shell's header, with logout, settings, profile, and an optional theme toggle already wired. Compose extra entries with ButtonItem rather than rebuilding the menu."
4304
+ },
4305
+ {
4306
+ id: "button-item",
4307
+ name: "ButtonItem",
4308
+ version: "1.0.0",
4309
+ description: 'A single row inside a UserNav menu — icon, label, action. Strategic purpose: the sanctioned way to add an entry to the account menu, so extra actions match the built-in ones instead of arriving as a hand-styled button. Use `variant="destructive"` for anything that removes or signs out.',
4310
+ tags: [
4311
+ "layout",
4312
+ "navigation",
4313
+ "menu",
4314
+ "item",
4315
+ "user-nav"
4316
+ ],
4317
+ category: "layout",
4318
+ props: [
4319
+ {
4320
+ name: "icon",
4321
+ type: "string",
4322
+ description: "Lucide icon name shown before the label."
4323
+ },
4324
+ {
4325
+ name: "label",
4326
+ type: "string",
4327
+ description: "The menu entry text."
4328
+ },
4329
+ {
4330
+ name: "onClick",
4331
+ type: "function",
4332
+ description: "Called when the entry is activated."
4333
+ },
4334
+ {
4335
+ name: "variant",
4336
+ type: "string",
4337
+ description: "'default' | 'destructive'. Destructive tints the row for sign-out and delete."
4338
+ },
4339
+ {
4340
+ name: "className",
4341
+ type: "string",
4342
+ description: "Additional CSS classes."
4343
+ }
4344
+ ],
4345
+ importPath: "./components/layout/UserNav",
4346
+ filePath: "src/components/layout/UserNav.tsx",
4347
+ sku: "@chassis/layout/button-item",
4348
+ humanLabel: "ButtonItem",
4349
+ humanDescription: 'A single row inside a UserNav menu — icon, label, action. Strategic purpose: the sanctioned way to add an entry to the account menu, so extra actions match the built-in ones instead of arriving as a hand-styled button. Use `variant="destructive"` for anything that removes or signs out.'
4125
4350
  }
4126
4351
  ],
4127
4352
  utils: [],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ramme-io/ui",
3
- "version": "4.0.1",
3
+ "version": "4.1.0",
4
4
  "description": "The structural component library for the Ramme Framework.",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -25,7 +25,6 @@
25
25
  "files": [
26
26
  "dist",
27
27
  "tailwind.preset.js",
28
- "index.css",
29
28
  "src/wizardManifest.ts"
30
29
  ],
31
30
  "publishConfig": {
@@ -55,7 +54,7 @@
55
54
  "tailwind-merge": "^3.3.1",
56
55
  "tippy.js": "^6.3.7",
57
56
  "zod": "^3.23.8",
58
- "@ramme-io/shared": "3.1.1"
57
+ "@ramme-io/shared": "3.1.2"
59
58
  },
60
59
  "devDependencies": {
61
60
  "@storybook/addon-links": "^10.5.9",