@xemahq/ui-kernel 0.1.5 → 0.1.7

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 (178) hide show
  1. package/dist/lib/biome-host/create-biome-orval-config.d.ts +14 -0
  2. package/dist/lib/biome-host/create-biome-orval-config.d.ts.map +1 -0
  3. package/dist/lib/biome-host/create-biome-orval-config.js +22 -0
  4. package/dist/lib/biome-host/create-biome-orval-config.js.map +1 -0
  5. package/dist/lib/biome-host/host-bridge.d.ts +2 -0
  6. package/dist/lib/biome-host/host-bridge.d.ts.map +1 -1
  7. package/dist/lib/biome-host/host-bridge.js.map +1 -1
  8. package/dist/lib/biome-host/host-sources.d.ts +2 -0
  9. package/dist/lib/biome-host/host-sources.d.ts.map +1 -1
  10. package/dist/lib/biome-host/index.d.ts +1 -0
  11. package/dist/lib/biome-host/index.d.ts.map +1 -1
  12. package/dist/lib/biome-host/index.js +1 -0
  13. package/dist/lib/biome-host/index.js.map +1 -1
  14. package/dist/session-kit/approvals/ApprovalButton.d.ts +14 -0
  15. package/dist/session-kit/approvals/ApprovalButton.d.ts.map +1 -0
  16. package/dist/session-kit/approvals/ApprovalButton.js +45 -0
  17. package/dist/session-kit/approvals/ApprovalButton.js.map +1 -0
  18. package/dist/session-kit/approvals/ApprovalCard.d.ts +12 -0
  19. package/dist/session-kit/approvals/ApprovalCard.d.ts.map +1 -0
  20. package/dist/session-kit/approvals/ApprovalCard.js +117 -0
  21. package/dist/session-kit/approvals/ApprovalCard.js.map +1 -0
  22. package/dist/session-kit/approvals/ApprovalsCenter.d.ts +11 -0
  23. package/dist/session-kit/approvals/ApprovalsCenter.d.ts.map +1 -0
  24. package/dist/session-kit/approvals/ApprovalsCenter.js +127 -0
  25. package/dist/session-kit/approvals/ApprovalsCenter.js.map +1 -0
  26. package/dist/session-kit/approvals/CapabilityApprovalStickyBar.d.ts +12 -0
  27. package/dist/session-kit/approvals/CapabilityApprovalStickyBar.d.ts.map +1 -0
  28. package/dist/session-kit/approvals/CapabilityApprovalStickyBar.js +36 -0
  29. package/dist/session-kit/approvals/CapabilityApprovalStickyBar.js.map +1 -0
  30. package/dist/session-kit/approvals/Obligation.d.ts +15 -0
  31. package/dist/session-kit/approvals/Obligation.d.ts.map +1 -0
  32. package/dist/session-kit/approvals/Obligation.js +42 -0
  33. package/dist/session-kit/approvals/Obligation.js.map +1 -0
  34. package/dist/session-kit/approvals/ScopedBody.d.ts +9 -0
  35. package/dist/session-kit/approvals/ScopedBody.d.ts.map +1 -0
  36. package/dist/session-kit/approvals/ScopedBody.js +145 -0
  37. package/dist/session-kit/approvals/ScopedBody.js.map +1 -0
  38. package/dist/session-kit/approvals/approval-icons.d.ts +15 -0
  39. package/dist/session-kit/approvals/approval-icons.d.ts.map +1 -0
  40. package/dist/session-kit/approvals/approval-icons.js +3 -0
  41. package/dist/session-kit/approvals/approval-icons.js.map +1 -0
  42. package/dist/session-kit/approvals/approval-model.d.ts +83 -0
  43. package/dist/session-kit/approvals/approval-model.d.ts.map +1 -0
  44. package/dist/session-kit/approvals/approval-model.js +25 -0
  45. package/dist/session-kit/approvals/approval-model.js.map +1 -0
  46. package/dist/session-kit/approvals/index.d.ts +12 -0
  47. package/dist/session-kit/approvals/index.d.ts.map +1 -0
  48. package/dist/session-kit/approvals/index.js +28 -0
  49. package/dist/session-kit/approvals/index.js.map +1 -0
  50. package/dist/session-kit/approvals/obligation-display.d.ts +17 -0
  51. package/dist/session-kit/approvals/obligation-display.d.ts.map +1 -0
  52. package/dist/session-kit/approvals/obligation-display.js +58 -0
  53. package/dist/session-kit/approvals/obligation-display.js.map +1 -0
  54. package/dist/session-kit/approvals/risk-accent.d.ts +8 -0
  55. package/dist/session-kit/approvals/risk-accent.d.ts.map +1 -0
  56. package/dist/session-kit/approvals/risk-accent.js +28 -0
  57. package/dist/session-kit/approvals/risk-accent.js.map +1 -0
  58. package/dist/session-kit/approvals/scope-icons.d.ts +12 -0
  59. package/dist/session-kit/approvals/scope-icons.d.ts.map +1 -0
  60. package/dist/session-kit/approvals/scope-icons.js +14 -0
  61. package/dist/session-kit/approvals/scope-icons.js.map +1 -0
  62. package/dist/session-kit/combobox/Combobox.d.ts +46 -0
  63. package/dist/session-kit/combobox/Combobox.d.ts.map +1 -0
  64. package/dist/session-kit/combobox/Combobox.js +113 -0
  65. package/dist/session-kit/combobox/Combobox.js.map +1 -0
  66. package/dist/session-kit/combobox/use-click-outside.d.ts +3 -0
  67. package/dist/session-kit/combobox/use-click-outside.d.ts.map +1 -0
  68. package/dist/session-kit/combobox/use-click-outside.js +18 -0
  69. package/dist/session-kit/combobox/use-click-outside.js.map +1 -0
  70. package/dist/session-kit/display/ContextHeader.d.ts +27 -0
  71. package/dist/session-kit/display/ContextHeader.d.ts.map +1 -0
  72. package/dist/session-kit/display/ContextHeader.js +47 -0
  73. package/dist/session-kit/display/ContextHeader.js.map +1 -0
  74. package/dist/session-kit/display/FileDiffCard.d.ts +18 -0
  75. package/dist/session-kit/display/FileDiffCard.d.ts.map +1 -0
  76. package/dist/session-kit/display/FileDiffCard.js +58 -0
  77. package/dist/session-kit/display/FileDiffCard.js.map +1 -0
  78. package/dist/session-kit/display/MD.d.ts +7 -0
  79. package/dist/session-kit/display/MD.d.ts.map +1 -0
  80. package/dist/session-kit/display/MD.js +89 -0
  81. package/dist/session-kit/display/MD.js.map +1 -0
  82. package/dist/session-kit/display/MessageTurn.d.ts +21 -0
  83. package/dist/session-kit/display/MessageTurn.d.ts.map +1 -0
  84. package/dist/session-kit/display/MessageTurn.js +62 -0
  85. package/dist/session-kit/display/MessageTurn.js.map +1 -0
  86. package/dist/session-kit/display/ThinkingPanel.d.ts +12 -0
  87. package/dist/session-kit/display/ThinkingPanel.d.ts.map +1 -0
  88. package/dist/session-kit/display/ThinkingPanel.js +30 -0
  89. package/dist/session-kit/display/ThinkingPanel.js.map +1 -0
  90. package/dist/session-kit/display/TodoChecklist.d.ts +17 -0
  91. package/dist/session-kit/display/TodoChecklist.d.ts.map +1 -0
  92. package/dist/session-kit/display/TodoChecklist.js +50 -0
  93. package/dist/session-kit/display/TodoChecklist.js.map +1 -0
  94. package/dist/session-kit/display/TokenMeter.d.ts +15 -0
  95. package/dist/session-kit/display/TokenMeter.d.ts.map +1 -0
  96. package/dist/session-kit/display/TokenMeter.js +35 -0
  97. package/dist/session-kit/display/TokenMeter.js.map +1 -0
  98. package/dist/session-kit/display/ToolStrip.d.ts +31 -0
  99. package/dist/session-kit/display/ToolStrip.d.ts.map +1 -0
  100. package/dist/session-kit/display/ToolStrip.js +99 -0
  101. package/dist/session-kit/display/ToolStrip.js.map +1 -0
  102. package/dist/session-kit/display/TypingDots.d.ts +3 -0
  103. package/dist/session-kit/display/TypingDots.d.ts.map +1 -0
  104. package/dist/session-kit/display/TypingDots.js +14 -0
  105. package/dist/session-kit/display/TypingDots.js.map +1 -0
  106. package/dist/session-kit/index.d.ts +21 -0
  107. package/dist/session-kit/index.d.ts.map +1 -0
  108. package/dist/session-kit/index.js +37 -0
  109. package/dist/session-kit/index.js.map +1 -0
  110. package/dist/session-kit/lib/enums.d.ts +34 -0
  111. package/dist/session-kit/lib/enums.d.ts.map +1 -0
  112. package/dist/session-kit/lib/enums.js +44 -0
  113. package/dist/session-kit/lib/enums.js.map +1 -0
  114. package/dist/session-kit/lib/portal-accent.d.ts +3 -0
  115. package/dist/session-kit/lib/portal-accent.d.ts.map +1 -0
  116. package/dist/session-kit/lib/portal-accent.js +9 -0
  117. package/dist/session-kit/lib/portal-accent.js.map +1 -0
  118. package/dist/session-kit/lib/status-dot.d.ts +10 -0
  119. package/dist/session-kit/lib/status-dot.d.ts.map +1 -0
  120. package/dist/session-kit/lib/status-dot.js +43 -0
  121. package/dist/session-kit/lib/status-dot.js.map +1 -0
  122. package/dist/session-kit/primitives/Avatar.d.ts +10 -0
  123. package/dist/session-kit/primitives/Avatar.d.ts.map +1 -0
  124. package/dist/session-kit/primitives/Avatar.js +21 -0
  125. package/dist/session-kit/primitives/Avatar.js.map +1 -0
  126. package/dist/session-kit/primitives/PortalGlyph.d.ts +12 -0
  127. package/dist/session-kit/primitives/PortalGlyph.d.ts.map +1 -0
  128. package/dist/session-kit/primitives/PortalGlyph.js +21 -0
  129. package/dist/session-kit/primitives/PortalGlyph.js.map +1 -0
  130. package/dist/session-kit/primitives/RiskPill.d.ts +12 -0
  131. package/dist/session-kit/primitives/RiskPill.d.ts.map +1 -0
  132. package/dist/session-kit/primitives/RiskPill.js +53 -0
  133. package/dist/session-kit/primitives/RiskPill.js.map +1 -0
  134. package/dist/session-kit/primitives/ScopeDot.d.ts +9 -0
  135. package/dist/session-kit/primitives/ScopeDot.d.ts.map +1 -0
  136. package/dist/session-kit/primitives/ScopeDot.js +23 -0
  137. package/dist/session-kit/primitives/ScopeDot.js.map +1 -0
  138. package/dist/session-kit/primitives/Segmented.d.ts +16 -0
  139. package/dist/session-kit/primitives/Segmented.d.ts.map +1 -0
  140. package/dist/session-kit/primitives/Segmented.js +31 -0
  141. package/dist/session-kit/primitives/Segmented.js.map +1 -0
  142. package/package.json +3 -3
  143. package/src/lib/biome-host/create-biome-orval-config.ts +76 -0
  144. package/src/lib/biome-host/host-bridge.ts +22 -0
  145. package/src/lib/biome-host/host-sources.ts +13 -0
  146. package/src/lib/biome-host/index.ts +1 -0
  147. package/src/session-kit/approvals/ApprovalButton.tsx +89 -0
  148. package/src/session-kit/approvals/ApprovalCard.tsx +336 -0
  149. package/src/session-kit/approvals/ApprovalsCenter.tsx +327 -0
  150. package/src/session-kit/approvals/CapabilityApprovalStickyBar.tsx +118 -0
  151. package/src/session-kit/approvals/Obligation.tsx +111 -0
  152. package/src/session-kit/approvals/ScopedBody.tsx +392 -0
  153. package/src/session-kit/approvals/approval-icons.ts +31 -0
  154. package/src/session-kit/approvals/approval-model.ts +205 -0
  155. package/src/session-kit/approvals/index.ts +22 -0
  156. package/src/session-kit/approvals/obligation-display.ts +100 -0
  157. package/src/session-kit/approvals/risk-accent.ts +47 -0
  158. package/src/session-kit/approvals/scope-icons.ts +19 -0
  159. package/src/session-kit/combobox/Combobox.tsx +327 -0
  160. package/src/session-kit/combobox/use-click-outside.ts +21 -0
  161. package/src/session-kit/display/ContextHeader.tsx +148 -0
  162. package/src/session-kit/display/FileDiffCard.tsx +140 -0
  163. package/src/session-kit/display/MD.tsx +153 -0
  164. package/src/session-kit/display/MessageTurn.tsx +157 -0
  165. package/src/session-kit/display/ThinkingPanel.tsx +78 -0
  166. package/src/session-kit/display/TodoChecklist.tsx +120 -0
  167. package/src/session-kit/display/TokenMeter.tsx +89 -0
  168. package/src/session-kit/display/ToolStrip.tsx +278 -0
  169. package/src/session-kit/display/TypingDots.tsx +24 -0
  170. package/src/session-kit/index.ts +44 -0
  171. package/src/session-kit/lib/enums.ts +66 -0
  172. package/src/session-kit/lib/portal-accent.ts +30 -0
  173. package/src/session-kit/lib/status-dot.ts +68 -0
  174. package/src/session-kit/primitives/Avatar.tsx +44 -0
  175. package/src/session-kit/primitives/PortalGlyph.tsx +51 -0
  176. package/src/session-kit/primitives/RiskPill.tsx +95 -0
  177. package/src/session-kit/primitives/ScopeDot.tsx +47 -0
  178. package/src/session-kit/primitives/Segmented.tsx +71 -0
@@ -0,0 +1,10 @@
1
+ import type { CSSProperties, ReactElement } from 'react';
2
+ export interface AvatarProps {
3
+ readonly initials: string;
4
+ readonly size?: number;
5
+ readonly color?: string;
6
+ readonly ink?: string;
7
+ readonly style?: CSSProperties;
8
+ }
9
+ export declare function Avatar({ initials, size, color, ink, style, }: AvatarProps): ReactElement;
10
+ //# sourceMappingURL=Avatar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Avatar.d.ts","sourceRoot":"","sources":["../../../src/session-kit/primitives/Avatar.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAEzD,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAEvB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAExB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC;CAChC;AAED,wBAAgB,MAAM,CAAC,EACrB,QAAQ,EACR,IAAS,EACT,KAAkD,EAClD,GAAkD,EAClD,KAAK,GACN,EAAE,WAAW,GAAG,YAAY,CAsB5B"}
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Avatar = Avatar;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ function Avatar({ initials, size = 26, color = 'hsl(var(--accent-2, var(--accent-tint)))', ink = 'hsl(var(--primary-ink, var(--accent-ink)))', style, }) {
6
+ return ((0, jsx_runtime_1.jsx)("span", { className: "mono", style: {
7
+ width: size,
8
+ height: size,
9
+ borderRadius: '50%',
10
+ flexShrink: 0,
11
+ display: 'grid',
12
+ placeItems: 'center',
13
+ background: color,
14
+ color: ink,
15
+ fontSize: size * 0.4,
16
+ fontWeight: 600,
17
+ letterSpacing: '-0.02em',
18
+ ...style,
19
+ }, children: initials }));
20
+ }
21
+ //# sourceMappingURL=Avatar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Avatar.js","sourceRoot":"","sources":["../../../src/session-kit/primitives/Avatar.tsx"],"names":[],"mappings":";;AAeA,wBA4BC;;AA5BD,SAAgB,MAAM,CAAC,EACrB,QAAQ,EACR,IAAI,GAAG,EAAE,EACT,KAAK,GAAG,0CAA0C,EAClD,GAAG,GAAG,4CAA4C,EAClD,KAAK,GACO;IACZ,OAAO,CACL,iCACE,SAAS,EAAC,MAAM,EAChB,KAAK,EAAE;YACL,KAAK,EAAE,IAAI;YACX,MAAM,EAAE,IAAI;YACZ,YAAY,EAAE,KAAK;YACnB,UAAU,EAAE,CAAC;YACb,OAAO,EAAE,MAAM;YACf,UAAU,EAAE,QAAQ;YACpB,UAAU,EAAE,KAAK;YACjB,KAAK,EAAE,GAAG;YACV,QAAQ,EAAE,IAAI,GAAG,GAAG;YACpB,UAAU,EAAE,GAAG;YACf,aAAa,EAAE,SAAS;YACxB,GAAG,KAAK;SACT,YAEA,QAAQ,GACJ,CACR,CAAC;AACJ,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { type PortalAccentVar } from '../lib/portal-accent';
2
+ import type { CSSProperties, ReactElement, ReactNode } from 'react';
3
+ export interface PortalGlyphProps {
4
+ readonly accentVar?: PortalAccentVar;
5
+ readonly icon: ReactNode;
6
+ readonly size?: number;
7
+ readonly radius?: number;
8
+ readonly active?: boolean;
9
+ readonly style?: CSSProperties;
10
+ }
11
+ export declare function PortalGlyph({ accentVar, icon, size, radius, active, style, }: PortalGlyphProps): ReactElement;
12
+ //# sourceMappingURL=PortalGlyph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PortalGlyph.d.ts","sourceRoot":"","sources":["../../../src/session-kit/primitives/PortalGlyph.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAgB,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE1E,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGpE,MAAM,WAAW,gBAAgB;IAE/B,QAAQ,CAAC,SAAS,CAAC,EAAE,eAAe,CAAC;IAErC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAEzB,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC;CAChC;AAED,wBAAgB,WAAW,CAAC,EAC1B,SAAS,EACT,IAAI,EACJ,IAAS,EACT,MAAU,EACV,MAAc,EACd,KAAK,GACN,EAAE,gBAAgB,GAAG,YAAY,CAoBjC"}
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PortalGlyph = PortalGlyph;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const portal_accent_1 = require("../lib/portal-accent");
6
+ function PortalGlyph({ accentVar, icon, size = 34, radius = 9, active = false, style, }) {
7
+ return ((0, jsx_runtime_1.jsx)("span", { style: {
8
+ width: size,
9
+ height: size,
10
+ borderRadius: radius,
11
+ flexShrink: 0,
12
+ display: 'grid',
13
+ placeItems: 'center',
14
+ background: (0, portal_accent_1.portalAccent)(accentVar, 0.13),
15
+ color: (0, portal_accent_1.portalAccent)(accentVar),
16
+ border: `1px solid ${(0, portal_accent_1.portalAccent)(accentVar, active ? 0.5 : 0.22)}`,
17
+ boxShadow: active ? `0 0 0 1px ${(0, portal_accent_1.portalAccent)(accentVar, 0.25)}` : 'none',
18
+ ...style,
19
+ }, children: icon }));
20
+ }
21
+ //# sourceMappingURL=PortalGlyph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PortalGlyph.js","sourceRoot":"","sources":["../../../src/session-kit/primitives/PortalGlyph.tsx"],"names":[],"mappings":";;AAuBA,kCA2BC;;AA5CD,wDAA0E;AAiB1E,SAAgB,WAAW,CAAC,EAC1B,SAAS,EACT,IAAI,EACJ,IAAI,GAAG,EAAE,EACT,MAAM,GAAG,CAAC,EACV,MAAM,GAAG,KAAK,EACd,KAAK,GACY;IACjB,OAAO,CACL,iCACE,KAAK,EAAE;YACL,KAAK,EAAE,IAAI;YACX,MAAM,EAAE,IAAI;YACZ,YAAY,EAAE,MAAM;YACpB,UAAU,EAAE,CAAC;YACb,OAAO,EAAE,MAAM;YACf,UAAU,EAAE,QAAQ;YACpB,UAAU,EAAE,IAAA,4BAAY,EAAC,SAAS,EAAE,IAAI,CAAC;YACzC,KAAK,EAAE,IAAA,4BAAY,EAAC,SAAS,CAAC;YAC9B,MAAM,EAAE,aAAa,IAAA,4BAAY,EAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE;YACnE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,aAAa,IAAA,4BAAY,EAAC,SAAS,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM;YACzE,GAAG,KAAK;SACT,YAEA,IAAI,GACA,CACR,CAAC;AACJ,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { CapabilityRiskTier } from '@xemahq/kernel-contracts/capability';
2
+ import type { CSSProperties, ReactElement, ReactNode } from 'react';
3
+ export { CapabilityRiskTier };
4
+ export type RiskPillSize = 'xs' | 'sm';
5
+ export interface RiskPillProps {
6
+ readonly tier: CapabilityRiskTier;
7
+ readonly size?: RiskPillSize;
8
+ readonly criticalIcon?: ReactNode;
9
+ readonly style?: CSSProperties;
10
+ }
11
+ export declare function RiskPill({ tier, size, criticalIcon, style, }: RiskPillProps): ReactElement;
12
+ //# sourceMappingURL=RiskPill.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RiskPill.d.ts","sourceRoot":"","sources":["../../../src/session-kit/primitives/RiskPill.tsx"],"names":[],"mappings":"AAYA,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAEzE,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEpE,OAAO,EAAE,kBAAkB,EAAE,CAAC;AAsC9B,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,IAAI,CAAC;AAEvC,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,QAAQ,CAAC,IAAI,CAAC,EAAE,YAAY,CAAC;IAE7B,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,CAAC;IAClC,QAAQ,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC;CAChC;AAED,wBAAgB,QAAQ,CAAC,EACvB,IAAI,EACJ,IAAW,EACX,YAAY,EACZ,KAAK,GACN,EAAE,aAAa,GAAG,YAAY,CAyB9B"}
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CapabilityRiskTier = void 0;
4
+ exports.RiskPill = RiskPill;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const capability_1 = require("@xemahq/kernel-contracts/capability");
7
+ Object.defineProperty(exports, "CapabilityRiskTier", { enumerable: true, get: function () { return capability_1.CapabilityRiskTier; } });
8
+ const DANGER = 'var(--destructive, var(--danger))';
9
+ const RISK = {
10
+ [capability_1.CapabilityRiskTier.Low]: {
11
+ label: 'Low',
12
+ fg: 'hsl(var(--ink-3))',
13
+ bg: 'hsl(var(--muted))',
14
+ bd: 'hsl(var(--rule))',
15
+ },
16
+ [capability_1.CapabilityRiskTier.Medium]: {
17
+ label: 'Medium',
18
+ fg: 'hsl(var(--info))',
19
+ bg: 'hsl(var(--info) / 0.09)',
20
+ bd: 'hsl(var(--info) / 0.28)',
21
+ },
22
+ [capability_1.CapabilityRiskTier.High]: {
23
+ label: 'High',
24
+ fg: 'hsl(var(--warning))',
25
+ bg: 'hsl(var(--warning) / 0.1)',
26
+ bd: 'hsl(var(--warning) / 0.3)',
27
+ },
28
+ [capability_1.CapabilityRiskTier.Critical]: {
29
+ label: 'Critical',
30
+ fg: `hsl(${DANGER})`,
31
+ bg: `hsl(${DANGER} / 0.09)`,
32
+ bd: `hsl(${DANGER} / 0.32)`,
33
+ },
34
+ };
35
+ function RiskPill({ tier, size = 'sm', criticalIcon, style, }) {
36
+ const r = RISK[tier];
37
+ return ((0, jsx_runtime_1.jsxs)("span", { className: "mono", style: {
38
+ display: 'inline-flex',
39
+ alignItems: 'center',
40
+ gap: 4,
41
+ padding: size === 'xs' ? '1px 6px' : '2px 8px',
42
+ fontSize: size === 'xs' ? 9.5 : 10,
43
+ fontWeight: 600,
44
+ textTransform: 'uppercase',
45
+ letterSpacing: '0.06em',
46
+ color: r.fg,
47
+ background: r.bg,
48
+ border: `1px solid ${r.bd}`,
49
+ borderRadius: 5,
50
+ ...style,
51
+ }, children: [tier === capability_1.CapabilityRiskTier.Critical && criticalIcon, r.label] }));
52
+ }
53
+ //# sourceMappingURL=RiskPill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RiskPill.js","sourceRoot":"","sources":["../../../src/session-kit/primitives/RiskPill.tsx"],"names":[],"mappings":";;;AAgEA,4BA8BC;;AAlFD,oEAAyE;AAIhE,mGAJA,+BAAkB,OAIA;AAS3B,MAAM,MAAM,GAAG,mCAAmC,CAAC;AAEnD,MAAM,IAAI,GAA0C;IAClD,CAAC,+BAAkB,CAAC,GAAG,CAAC,EAAE;QACxB,KAAK,EAAE,KAAK;QACZ,EAAE,EAAE,mBAAmB;QACvB,EAAE,EAAE,mBAAmB;QACvB,EAAE,EAAE,kBAAkB;KACvB;IACD,CAAC,+BAAkB,CAAC,MAAM,CAAC,EAAE;QAC3B,KAAK,EAAE,QAAQ;QACf,EAAE,EAAE,kBAAkB;QACtB,EAAE,EAAE,yBAAyB;QAC7B,EAAE,EAAE,yBAAyB;KAC9B;IACD,CAAC,+BAAkB,CAAC,IAAI,CAAC,EAAE;QACzB,KAAK,EAAE,MAAM;QACb,EAAE,EAAE,qBAAqB;QACzB,EAAE,EAAE,2BAA2B;QAC/B,EAAE,EAAE,2BAA2B;KAChC;IACD,CAAC,+BAAkB,CAAC,QAAQ,CAAC,EAAE;QAC7B,KAAK,EAAE,UAAU;QACjB,EAAE,EAAE,OAAO,MAAM,GAAG;QACpB,EAAE,EAAE,OAAO,MAAM,UAAU;QAC3B,EAAE,EAAE,OAAO,MAAM,UAAU;KAC5B;CACF,CAAC;AAYF,SAAgB,QAAQ,CAAC,EACvB,IAAI,EACJ,IAAI,GAAG,IAAI,EACX,YAAY,EACZ,KAAK,GACS;IACd,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;IACrB,OAAO,CACL,kCACE,SAAS,EAAC,MAAM,EAChB,KAAK,EAAE;YACL,OAAO,EAAE,aAAa;YACtB,UAAU,EAAE,QAAQ;YACpB,GAAG,EAAE,CAAC;YACN,OAAO,EAAE,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;YAC9C,QAAQ,EAAE,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;YAClC,UAAU,EAAE,GAAG;YACf,aAAa,EAAE,WAAW;YAC1B,aAAa,EAAE,QAAQ;YACvB,KAAK,EAAE,CAAC,CAAC,EAAE;YACX,UAAU,EAAE,CAAC,CAAC,EAAE;YAChB,MAAM,EAAE,aAAa,CAAC,CAAC,EAAE,EAAE;YAC3B,YAAY,EAAE,CAAC;YACf,GAAG,KAAK;SACT,aAEA,IAAI,KAAK,+BAAkB,CAAC,QAAQ,IAAI,YAAY,EACpD,CAAC,CAAC,KAAK,IACH,CACR,CAAC;AACJ,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { BiomeScope } from '../lib/enums';
2
+ import type { CSSProperties, ReactElement } from 'react';
3
+ export interface ScopeDotProps {
4
+ readonly scope: BiomeScope;
5
+ readonly size?: number;
6
+ readonly style?: CSSProperties;
7
+ }
8
+ export declare function ScopeDot({ scope, size, style, }: ScopeDotProps): ReactElement;
9
+ //# sourceMappingURL=ScopeDot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ScopeDot.d.ts","sourceRoot":"","sources":["../../../src/session-kit/primitives/ScopeDot.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAczD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC;CAChC;AAED,wBAAgB,QAAQ,CAAC,EACvB,KAAK,EACL,IAAQ,EACR,KAAK,GACN,EAAE,aAAa,GAAG,YAAY,CAgB9B"}
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ScopeDot = ScopeDot;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const enums_1 = require("../lib/enums");
6
+ const SCOPE = {
7
+ [enums_1.BiomeScope.System]: { color: 'hsl(var(--ink-4))', label: 'System' },
8
+ [enums_1.BiomeScope.Platform]: { color: 'hsl(var(--primary))', label: 'Platform' },
9
+ [enums_1.BiomeScope.Community]: { color: 'hsl(var(--p-people))', label: 'Community' },
10
+ };
11
+ function ScopeDot({ scope, size = 7, style, }) {
12
+ const s = SCOPE[scope];
13
+ return ((0, jsx_runtime_1.jsx)("span", { title: s.label, style: {
14
+ width: size,
15
+ height: size,
16
+ borderRadius: '50%',
17
+ background: s.color,
18
+ flexShrink: 0,
19
+ display: 'inline-block',
20
+ ...style,
21
+ } }));
22
+ }
23
+ //# sourceMappingURL=ScopeDot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ScopeDot.js","sourceRoot":"","sources":["../../../src/session-kit/primitives/ScopeDot.tsx"],"names":[],"mappings":";;AA0BA,4BAoBC;;AA1CD,wCAA0C;AAU1C,MAAM,KAAK,GAAmC;IAC5C,CAAC,kBAAU,CAAC,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,QAAQ,EAAE;IACpE,CAAC,kBAAU,CAAC,QAAQ,CAAC,EAAE,EAAE,KAAK,EAAE,qBAAqB,EAAE,KAAK,EAAE,UAAU,EAAE;IAC1E,CAAC,kBAAU,CAAC,SAAS,CAAC,EAAE,EAAE,KAAK,EAAE,sBAAsB,EAAE,KAAK,EAAE,WAAW,EAAE;CAC9E,CAAC;AAQF,SAAgB,QAAQ,CAAC,EACvB,KAAK,EACL,IAAI,GAAG,CAAC,EACR,KAAK,GACS;IACd,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;IACvB,OAAO,CACL,iCACE,KAAK,EAAE,CAAC,CAAC,KAAK,EACd,KAAK,EAAE;YACL,KAAK,EAAE,IAAI;YACX,MAAM,EAAE,IAAI;YACZ,YAAY,EAAE,KAAK;YACnB,UAAU,EAAE,CAAC,CAAC,KAAK;YACnB,UAAU,EAAE,CAAC;YACb,OAAO,EAAE,cAAc;YACvB,GAAG,KAAK;SACT,GACD,CACH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { CSSProperties, ReactElement, ReactNode } from 'react';
2
+ export interface SegmentedOption<V extends string> {
3
+ readonly value: V;
4
+ readonly label: ReactNode;
5
+ readonly icon?: ReactNode;
6
+ }
7
+ export type SegmentedSize = 'sm' | 'md';
8
+ export interface SegmentedProps<V extends string> {
9
+ readonly options: ReadonlyArray<SegmentedOption<V>>;
10
+ readonly value: V;
11
+ readonly onChange: (value: V) => void;
12
+ readonly size?: SegmentedSize;
13
+ readonly style?: CSSProperties;
14
+ }
15
+ export declare function Segmented<V extends string>({ options, value, onChange, size, style, }: SegmentedProps<V>): ReactElement;
16
+ //# sourceMappingURL=Segmented.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Segmented.d.ts","sourceRoot":"","sources":["../../../src/session-kit/primitives/Segmented.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEpE,MAAM,WAAW,eAAe,CAAC,CAAC,SAAS,MAAM;IAC/C,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IAClB,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAE1B,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC;CAC3B;AAED,MAAM,MAAM,aAAa,GAAG,IAAI,GAAG,IAAI,CAAC;AAExC,MAAM,WAAW,cAAc,CAAC,CAAC,SAAS,MAAM;IAC9C,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;IACpD,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IAClB,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;IACtC,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC;IAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC;CAChC;AAED,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,EAAE,EAC1C,OAAO,EACP,KAAK,EACL,QAAQ,EACR,IAAW,EACX,KAAK,GACN,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,YAAY,CAyClC"}
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Segmented = Segmented;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ function Segmented({ options, value, onChange, size = 'sm', style, }) {
6
+ return ((0, jsx_runtime_1.jsx)("div", { style: {
7
+ display: 'inline-flex',
8
+ padding: 2,
9
+ gap: 2,
10
+ background: 'hsl(var(--paper-sunk))',
11
+ border: '1px solid hsl(var(--rule))',
12
+ borderRadius: 8,
13
+ ...style,
14
+ }, children: options.map((option) => {
15
+ const on = option.value === value;
16
+ return ((0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: () => onChange(option.value), style: {
17
+ display: 'inline-flex',
18
+ alignItems: 'center',
19
+ gap: 5,
20
+ padding: size === 'sm' ? '4px 10px' : '6px 12px',
21
+ fontSize: size === 'sm' ? 12 : 13,
22
+ fontWeight: on ? 600 : 450,
23
+ borderRadius: 6,
24
+ color: on ? 'hsl(var(--ink))' : 'hsl(var(--ink-3))',
25
+ background: on ? 'hsl(var(--paper-elev))' : 'transparent',
26
+ boxShadow: on ? 'var(--shadow-2, var(--shadow-1))' : 'none',
27
+ transition: 'background 140ms ease, color 140ms ease, box-shadow 140ms ease',
28
+ }, children: [option.icon, option.label] }, option.value));
29
+ }) }));
30
+ }
31
+ //# sourceMappingURL=Segmented.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Segmented.js","sourceRoot":"","sources":["../../../src/session-kit/primitives/Segmented.tsx"],"names":[],"mappings":";;AAuBA,8BA+CC;;AA/CD,SAAgB,SAAS,CAAmB,EAC1C,OAAO,EACP,KAAK,EACL,QAAQ,EACR,IAAI,GAAG,IAAI,EACX,KAAK,GACa;IAClB,OAAO,CACL,gCACE,KAAK,EAAE;YACL,OAAO,EAAE,aAAa;YACtB,OAAO,EAAE,CAAC;YACV,GAAG,EAAE,CAAC;YACN,UAAU,EAAE,wBAAwB;YACpC,MAAM,EAAE,4BAA4B;YACpC,YAAY,EAAE,CAAC;YACf,GAAG,KAAK;SACT,YAEA,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;YACtB,MAAM,EAAE,GAAG,MAAM,CAAC,KAAK,KAAK,KAAK,CAAC;YAClC,OAAO,CACL,oCAEE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,EACrC,KAAK,EAAE;oBACL,OAAO,EAAE,aAAa;oBACtB,UAAU,EAAE,QAAQ;oBACpB,GAAG,EAAE,CAAC;oBACN,OAAO,EAAE,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU;oBAChD,QAAQ,EAAE,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE;oBACjC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG;oBAC1B,YAAY,EAAE,CAAC;oBACf,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,mBAAmB;oBACnD,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,aAAa;oBACzD,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC,kCAAkC,CAAC,CAAC,CAAC,MAAM;oBAC3D,UAAU,EAAE,gEAAgE;iBAC7E,aAEA,MAAM,CAAC,IAAI,EACX,MAAM,CAAC,KAAK,KAlBR,MAAM,CAAC,KAAK,CAmBV,CACV,CAAC;QACJ,CAAC,CAAC,GACE,CACP,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xemahq/ui-kernel",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "Host-framework-agnostic UI kernel for the Xema OS. Defines the SystemBus orchestration contract (capability.invoke, cross-biome intents, command palette, xema:// deeplinks, window manager) AND the biome-host contract surface (FrontendBiome/FrontendBiomeFactory, HostBridge, the singleton biomeRegistry, session contributions) that every frontend biome composes against. No Vite, Next.js, or React-Router — React itself IS allowed as the shared component model (the contracts traffic in ReactNode/ComponentType and a React context). Concrete host adapters (router/auth/toast wiring) live in separate packages that consume this kernel. The SystemBus is pure orchestration: it never authorizes, the backend capability-router enforces all policy.",
5
5
  "keywords": [
6
6
  "xema",
@@ -35,10 +35,10 @@
35
35
  "LICENSE"
36
36
  ],
37
37
  "dependencies": {
38
- "@xemahq/kernel-contracts": "^0.2.0",
38
+ "@xemahq/kernel-contracts": "^0.3.0",
39
39
  "clsx": "^2.1.1",
40
40
  "tailwind-merge": "^2.5.4",
41
- "@xemahq/registry": "0.1.2"
41
+ "@xemahq/registry": "0.1.3"
42
42
  },
43
43
  "peerDependencies": {
44
44
  "@tanstack/react-query": "^5.0.0",
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Shared Orval-client wiring for frontend biomes.
3
+ *
4
+ * Every biome that calls a platform API through an Orval-generated client must
5
+ * configure that client with the SAME auth/header/401 behavior the host shell
6
+ * uses for its own clients. Hand-copying a `configureOrgDbClient`-style helper
7
+ * into each biome (as `org-databases` did across three hook files) duplicates
8
+ * the correlation-id + org-header + token logic and lets it drift from the
9
+ * host. This factory centralizes it: a biome builds one config from its
10
+ * `HostBridge` and feeds it straight into the client's `configureClient(...)`.
11
+ *
12
+ * Auth/refresh/redirect stay HOST-owned — this only READS the bridge's
13
+ * host-implemented methods (`getActorToken`, `ensureFreshToken`,
14
+ * `onUnauthorized`, `getOrgId`). It owns no auth state of its own.
15
+ */
16
+ import type { HostBridge } from './host-bridge';
17
+
18
+ /**
19
+ * The Orval client config shape every generated `configureClient(...)` accepts.
20
+ * Kept structural (not imported from a client package) so the kernel stays free
21
+ * of any concrete service-client dependency — biomes pass the result straight
22
+ * into their own client's `configureClient`, which validates the shape.
23
+ */
24
+ export interface BiomeOrvalConfig {
25
+ readonly baseUrl: string;
26
+ readonly maxRetries: number;
27
+ getAuthToken(): Promise<string>;
28
+ getHeaders(): Promise<Record<string, string>>;
29
+ onUnauthorized(): Promise<void>;
30
+ }
31
+
32
+ export interface CreateBiomeOrvalConfigOptions {
33
+ /** Absolute base URL of the target service. */
34
+ readonly baseUrl: string;
35
+ /**
36
+ * Retry budget for the underlying fetch wrapper. Defaults to 1 — a single
37
+ * retry covers the `onUnauthorized` refresh-then-retry path without turning
38
+ * a hard failure into a retry storm.
39
+ */
40
+ readonly maxRetries?: number;
41
+ }
42
+
43
+ /**
44
+ * Build an Orval client config from a `HostBridge`. Wires:
45
+ * - `getAuthToken` → `bridge.auth.ensureFreshToken()` (proactive refresh;
46
+ * the host owns the refresh + login-redirect single-flight).
47
+ * - `getHeaders` → a fresh `X-Correlation-Id` per call, plus `X-Org-Id` when
48
+ * an org is selected. Per-call headers set by the caller still win in the
49
+ * client's own header merge.
50
+ * - `onUnauthorized` → `bridge.auth.onUnauthorized()` (host force-refresh +
51
+ * redirect-on-failure).
52
+ *
53
+ * @example
54
+ * configureClient(createBiomeOrvalConfig(bridge, { baseUrl: API_BASE_URL }));
55
+ */
56
+ export function createBiomeOrvalConfig(
57
+ bridge: HostBridge,
58
+ opts: CreateBiomeOrvalConfigOptions,
59
+ ): BiomeOrvalConfig {
60
+ return {
61
+ baseUrl: opts.baseUrl,
62
+ maxRetries: opts.maxRetries ?? 1,
63
+ getAuthToken: () => bridge.auth.ensureFreshToken(),
64
+ getHeaders: async () => {
65
+ const headers: Record<string, string> = {
66
+ 'X-Correlation-Id': crypto.randomUUID(),
67
+ };
68
+ const orgId = bridge.auth.getOrgId();
69
+ if (orgId) {
70
+ headers['X-Org-Id'] = orgId;
71
+ }
72
+ return headers;
73
+ },
74
+ onUnauthorized: () => bridge.auth.onUnauthorized(),
75
+ };
76
+ }
@@ -58,6 +58,28 @@ export interface HostBridgeAuth {
58
58
  getProjectId(): string | null;
59
59
  /** Returns the current actor's user id (subject), or null. */
60
60
  getUserId(): string | null;
61
+ /**
62
+ * Proactively refresh the actor token if it is within `minValiditySeconds`
63
+ * of expiry, then return a guaranteed-valid bearer. The refresh + any
64
+ * redirect-on-failure stays HOST-owned (the host owns the auth client and
65
+ * the single-flight login guard) — biomes only reach it through this method
66
+ * so an Orval client's `getAuthToken` can be wired against the SAME refresh
67
+ * path the host uses, instead of each biome re-implementing token freshness.
68
+ *
69
+ * @param minValiditySeconds Refresh when fewer than this many seconds of
70
+ * validity remain. Defaults to a host-chosen safe window.
71
+ * @returns A valid bearer token string. Implementations that cannot produce
72
+ * one (session expired) trigger the host login redirect and reject.
73
+ */
74
+ ensureFreshToken(minValiditySeconds?: number): Promise<string>;
75
+ /**
76
+ * Handle a 401 from a downstream API call: force-refresh the token and, if
77
+ * that fails, redirect to login. HOST-owned for the same reason as
78
+ * {@link HostBridgeAuth.ensureFreshToken} — there is ONE login-redirect
79
+ * single-flight guard and one refresh-dedup path in the host; biomes funnel
80
+ * 401 recovery through here rather than forking that logic.
81
+ */
82
+ onUnauthorized(): Promise<void>;
61
83
  }
62
84
 
63
85
  export interface HostBridgeToast {
@@ -25,6 +25,19 @@ export interface AuthSource {
25
25
  getProjectId(): string | null;
26
26
  /** Subject (user) id of the actor, or null when unauthenticated. */
27
27
  getUserId(): string | null;
28
+ /**
29
+ * Proactively refresh the token if it is within `minValiditySeconds` of
30
+ * expiry and return a valid bearer. Backed by the host's auth client
31
+ * (keycloak-js `updateToken`, …) and its single-flight login redirect.
32
+ * Mirrors {@link HostBridgeAuth.ensureFreshToken} — the bridge delegates
33
+ * straight through to this source.
34
+ */
35
+ ensureFreshToken(minValiditySeconds?: number): Promise<string>;
36
+ /**
37
+ * Force-refresh on a 401 and redirect to login on failure. Backed by the
38
+ * host's auth-guard. Mirrors {@link HostBridgeAuth.onUnauthorized}.
39
+ */
40
+ onUnauthorized(): Promise<void>;
28
41
  }
29
42
 
30
43
  /**
@@ -14,6 +14,7 @@
14
14
  */
15
15
  export * from './frontend-biome';
16
16
  export * from './host-bridge';
17
+ export * from './create-biome-orval-config';
17
18
  export * from './biome-registry';
18
19
  export * from './session-contributions';
19
20
  export * from './session-profiles';
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Minimal action button used by the approval surfaces (card / sticky bar /
3
+ * Center). The kit carries no button primitive, so this is a small,
4
+ * inline-styled control matching the design's `Btn` (ghost / soft /
5
+ * primary, with an optional accent override for critical-tier approve).
6
+ *
7
+ * Kept inside the approvals folder because it is only the approval
8
+ * actions — it is NOT a general-purpose kit button.
9
+ */
10
+ import type { CSSProperties, ReactElement, ReactNode } from 'react';
11
+
12
+ export type ApprovalButtonVariant = 'ghost' | 'soft' | 'primary';
13
+ export type ApprovalButtonSize = 'xs' | 'sm';
14
+
15
+ export interface ApprovalButtonProps {
16
+ readonly variant?: ApprovalButtonVariant;
17
+ readonly size?: ApprovalButtonSize;
18
+ /** Accent for the `primary` variant background (e.g. portal/risk accent). */
19
+ readonly accent?: string;
20
+ readonly icon?: ReactNode;
21
+ readonly disabled?: boolean;
22
+ readonly onClick?: () => void;
23
+ readonly children: ReactNode;
24
+ }
25
+
26
+ const PAD: Record<ApprovalButtonSize, string> = {
27
+ xs: '3px 9px',
28
+ sm: '5px 11px',
29
+ };
30
+
31
+ const FONT: Record<ApprovalButtonSize, number> = { xs: 12, sm: 12.5 };
32
+
33
+ export function ApprovalButton({
34
+ variant = 'ghost',
35
+ size = 'sm',
36
+ accent = 'hsl(var(--primary))',
37
+ icon,
38
+ disabled = false,
39
+ onClick,
40
+ children,
41
+ }: ApprovalButtonProps): ReactElement {
42
+ const base: CSSProperties = {
43
+ display: 'inline-flex',
44
+ alignItems: 'center',
45
+ gap: 5,
46
+ padding: PAD[size],
47
+ fontSize: FONT[size],
48
+ fontWeight: 550,
49
+ borderRadius: 7,
50
+ cursor: disabled ? 'not-allowed' : 'pointer',
51
+ opacity: disabled ? 0.5 : 1,
52
+ whiteSpace: 'nowrap',
53
+ lineHeight: 1.2,
54
+ };
55
+ const variantStyle = resolveVariantStyle(variant, accent);
56
+ return (
57
+ <button
58
+ type="button"
59
+ disabled={disabled}
60
+ onClick={onClick}
61
+ style={{ ...base, ...variantStyle }}
62
+ >
63
+ {icon}
64
+ {children}
65
+ </button>
66
+ );
67
+ }
68
+
69
+ function resolveVariantStyle(
70
+ variant: ApprovalButtonVariant,
71
+ accent: string,
72
+ ): CSSProperties {
73
+ switch (variant) {
74
+ case 'primary':
75
+ return { background: accent, color: '#fff', border: '1px solid transparent' };
76
+ case 'soft':
77
+ return {
78
+ background: 'hsl(var(--muted))',
79
+ color: 'hsl(var(--ink))',
80
+ border: '1px solid hsl(var(--rule))',
81
+ };
82
+ case 'ghost':
83
+ return {
84
+ background: 'transparent',
85
+ color: 'hsl(var(--ink-2))',
86
+ border: '1px solid transparent',
87
+ };
88
+ }
89
+ }