@xemahq/ui-kernel 0.25.1 → 0.27.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 (39) hide show
  1. package/dist/registry/index.d.ts +5 -1
  2. package/dist/registry/index.d.ts.map +1 -1
  3. package/dist/registry/index.js +5 -1
  4. package/dist/registry/index.js.map +1 -1
  5. package/dist/registry/lib/biome-presence-context.d.ts +8 -0
  6. package/dist/registry/lib/biome-presence-context.d.ts.map +1 -0
  7. package/dist/registry/lib/biome-presence-context.js +22 -0
  8. package/dist/registry/lib/biome-presence-context.js.map +1 -0
  9. package/dist/registry/lib/biome-presence-error-card.d.ts +8 -0
  10. package/dist/registry/lib/biome-presence-error-card.d.ts.map +1 -0
  11. package/dist/registry/lib/biome-presence-error-card.js +7 -0
  12. package/dist/registry/lib/biome-presence-error-card.js.map +1 -0
  13. package/dist/registry/lib/biome-presence-error-title.d.ts +3 -0
  14. package/dist/registry/lib/biome-presence-error-title.d.ts.map +1 -0
  15. package/dist/registry/lib/biome-presence-error-title.js +10 -0
  16. package/dist/registry/lib/biome-presence-error-title.js.map +1 -0
  17. package/dist/registry/lib/biome-presence-gate.d.ts +8 -0
  18. package/dist/registry/lib/biome-presence-gate.d.ts.map +1 -0
  19. package/dist/registry/lib/biome-presence-gate.js +19 -0
  20. package/dist/registry/lib/biome-presence-gate.js.map +1 -0
  21. package/dist/registry/lib/biome-presence.d.ts +28 -0
  22. package/dist/registry/lib/biome-presence.d.ts.map +1 -0
  23. package/dist/registry/lib/biome-presence.js +14 -0
  24. package/dist/registry/lib/biome-presence.js.map +1 -0
  25. package/dist/registry/lib/biome-slot.d.ts.map +1 -1
  26. package/dist/registry/lib/biome-slot.js +31 -10
  27. package/dist/registry/lib/biome-slot.js.map +1 -1
  28. package/dist/ui/branding/app-branding-provider.d.ts.map +1 -1
  29. package/dist/ui/branding/app-branding-provider.js +15 -10
  30. package/dist/ui/branding/app-branding-provider.js.map +1 -1
  31. package/dist/ui/branding/sanitize.d.ts +5 -3
  32. package/dist/ui/branding/sanitize.d.ts.map +1 -1
  33. package/dist/ui/branding/sanitize.js +9 -32
  34. package/dist/ui/branding/sanitize.js.map +1 -1
  35. package/package.json +5 -5
  36. package/dist/registry/lib/biome-applicability-context.d.ts +0 -4
  37. package/dist/registry/lib/biome-applicability-context.d.ts.map +0 -1
  38. package/dist/registry/lib/biome-applicability-context.js +0 -8
  39. package/dist/registry/lib/biome-applicability-context.js.map +0 -1
@@ -1,7 +1,11 @@
1
1
  export * from './lib/extension-points';
2
2
  export * from './lib/agent-validation-host';
3
3
  export * from './lib/biome-slot';
4
- export * from './lib/biome-applicability-context';
4
+ export * from './lib/biome-presence';
5
+ export * from './lib/biome-presence-context';
6
+ export * from './lib/biome-presence-error-card';
7
+ export * from './lib/biome-presence-error-title';
8
+ export * from './lib/biome-presence-gate';
5
9
  export * from './lib/biomes-enabled-context';
6
10
  export * from './lib/session-selectors';
7
11
  export * from './lib/session-context-builder';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/registry/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kBAAkB,CAAC;AACjC,cAAc,mCAAmC,CAAC;AAClD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,yBAAyB,CAAC;AACxC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,uBAAuB,CAAC;AACtC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/registry/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,iCAAiC,CAAC;AAChD,cAAc,kCAAkC,CAAC;AACjD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,yBAAyB,CAAC;AACxC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,uBAAuB,CAAC;AACtC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kBAAkB,CAAC"}
@@ -1,7 +1,11 @@
1
1
  export * from './lib/extension-points';
2
2
  export * from './lib/agent-validation-host';
3
3
  export * from './lib/biome-slot';
4
- export * from './lib/biome-applicability-context';
4
+ export * from './lib/biome-presence';
5
+ export * from './lib/biome-presence-context';
6
+ export * from './lib/biome-presence-error-card';
7
+ export * from './lib/biome-presence-error-title';
8
+ export * from './lib/biome-presence-gate';
5
9
  export * from './lib/biomes-enabled-context';
6
10
  export * from './lib/session-selectors';
7
11
  export * from './lib/session-context-builder';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/registry/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kBAAkB,CAAC;AACjC,cAAc,mCAAmC,CAAC;AAClD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,yBAAyB,CAAC;AACxC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,uBAAuB,CAAC;AACtC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/registry/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,iCAAiC,CAAC;AAChD,cAAc,kCAAkC,CAAC;AACjD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,yBAAyB,CAAC;AACxC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,uBAAuB,CAAC;AACtC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kBAAkB,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { BiomePresenceAnswer, BiomePresenceLookup } from './biome-presence';
2
+ export declare const BiomePresenceContext: import("react").Context<BiomePresenceLookup | null>;
3
+ export declare class MissingBiomePresenceProviderError extends Error {
4
+ constructor();
5
+ }
6
+ export declare function useBiomePresenceLookup(): BiomePresenceLookup;
7
+ export declare function useBiomePresence(biomeId: string): BiomePresenceAnswer;
8
+ //# sourceMappingURL=biome-presence-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"biome-presence-context.d.ts","sourceRoot":"","sources":["../../../src/registry/lib/biome-presence-context.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AA4BjF,eAAO,MAAM,oBAAoB,qDAAkD,CAAC;AAIpF,qBAAa,iCAAkC,SAAQ,KAAK;;CAS3D;AAOD,wBAAgB,sBAAsB,IAAI,mBAAmB,CAM5D;AAOD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,mBAAmB,CAErE"}
@@ -0,0 +1,22 @@
1
+ import { createContext, useContext } from 'react';
2
+ export const BiomePresenceContext = createContext(null);
3
+ BiomePresenceContext.displayName = 'BiomePresenceContext';
4
+ export class MissingBiomePresenceProviderError extends Error {
5
+ constructor() {
6
+ super('No BiomePresenceContext provider: BiomeSlot, BiomePresenceGate and useBiomePresence ' +
7
+ 'need the host to mount <BiomePresenceContext.Provider> with its installed-set lookup ' +
8
+ 'above them.');
9
+ this.name = 'MissingBiomePresenceProviderError';
10
+ }
11
+ }
12
+ export function useBiomePresenceLookup() {
13
+ const lookup = useContext(BiomePresenceContext);
14
+ if (lookup === null) {
15
+ throw new MissingBiomePresenceProviderError();
16
+ }
17
+ return lookup;
18
+ }
19
+ export function useBiomePresence(biomeId) {
20
+ return useBiomePresenceLookup()(biomeId);
21
+ }
22
+ //# sourceMappingURL=biome-presence-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"biome-presence-context.js","sourceRoot":"","sources":["../../../src/registry/lib/biome-presence-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AA8BlD,MAAM,CAAC,MAAM,oBAAoB,GAAG,aAAa,CAA6B,IAAI,CAAC,CAAC;AACpF,oBAAoB,CAAC,WAAW,GAAG,sBAAsB,CAAC;AAG1D,MAAM,OAAO,iCAAkC,SAAQ,KAAK;IAC1D;QACE,KAAK,CACH,sFAAsF;YACpF,uFAAuF;YACvF,aAAa,CAChB,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,mCAAmC,CAAC;IAClD,CAAC;CACF;AAOD,MAAM,UAAU,sBAAsB;IACpC,MAAM,MAAM,GAAG,UAAU,CAAC,oBAAoB,CAAC,CAAC;IAChD,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QACpB,MAAM,IAAI,iCAAiC,EAAE,CAAC;IAChD,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAOD,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,OAAO,sBAAsB,EAAE,CAAC,OAAO,CAAC,CAAC;AAC3C,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { type BiomePresenceError } from './biome-presence';
2
+ import type { ReactElement } from 'react';
3
+ export interface BiomePresenceErrorCardProps {
4
+ readonly biomeId: string;
5
+ readonly answer: BiomePresenceError;
6
+ }
7
+ export declare function BiomePresenceErrorCard({ biomeId, answer, }: BiomePresenceErrorCardProps): ReactElement;
8
+ //# sourceMappingURL=biome-presence-error-card.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"biome-presence-error-card.d.ts","sourceRoot":"","sources":["../../../src/registry/lib/biome-presence-error-card.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAI3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAE1C,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC;CACrC;AAMD,wBAAgB,sBAAsB,CAAC,EACrC,OAAO,EACP,MAAM,GACP,EAAE,2BAA2B,GAAG,YAAY,CAE5C"}
@@ -0,0 +1,7 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { biomePresenceErrorTitle } from './biome-presence-error-title';
3
+ import ErrorCard from '../../ui/chrome/ErrorCard';
4
+ export function BiomePresenceErrorCard({ biomeId, answer, }) {
5
+ return _jsx(ErrorCard, { title: biomePresenceErrorTitle(biomeId, answer.reason), error: answer.error });
6
+ }
7
+ //# sourceMappingURL=biome-presence-error-card.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"biome-presence-error-card.js","sourceRoot":"","sources":["../../../src/registry/lib/biome-presence-error-card.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,SAAS,MAAM,2BAA2B,CAAC;AAalD,MAAM,UAAU,sBAAsB,CAAC,EACrC,OAAO,EACP,MAAM,GACsB;IAC5B,OAAO,KAAC,SAAS,IAAC,KAAK,EAAE,uBAAuB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,GAAI,CAAC;AACpG,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { BiomePresenceErrorReason } from './biome-presence';
2
+ export declare function biomePresenceErrorTitle(biomeId: string, reason: BiomePresenceErrorReason): string;
3
+ //# sourceMappingURL=biome-presence-error-title.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"biome-presence-error-title.d.ts","sourceRoot":"","sources":["../../../src/registry/lib/biome-presence-error-title.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAY5D,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,wBAAwB,GAAG,MAAM,CAEjG"}
@@ -0,0 +1,10 @@
1
+ import { BiomePresenceErrorReason } from './biome-presence';
2
+ const TITLE_BY_REASON = {
3
+ [BiomePresenceErrorReason.LookupFailed]: (biomeId) => `Couldn't check whether ${biomeId} is installed`,
4
+ [BiomePresenceErrorReason.ProviderUnavailable]: (biomeId) => `${biomeId} is installed but unavailable`,
5
+ [BiomePresenceErrorReason.AuthorizationDenied]: (biomeId) => `You don't have access to check whether ${biomeId} is installed`,
6
+ };
7
+ export function biomePresenceErrorTitle(biomeId, reason) {
8
+ return TITLE_BY_REASON[reason](biomeId);
9
+ }
10
+ //# sourceMappingURL=biome-presence-error-title.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"biome-presence-error-title.js","sourceRoot":"","sources":["../../../src/registry/lib/biome-presence-error-title.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAE5D,MAAM,eAAe,GAA4E;IAC/F,CAAC,wBAAwB,CAAC,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,CACnD,0BAA0B,OAAO,eAAe;IAClD,CAAC,wBAAwB,CAAC,mBAAmB,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,CAC1D,GAAG,OAAO,+BAA+B;IAC3C,CAAC,wBAAwB,CAAC,mBAAmB,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,CAC1D,0CAA0C,OAAO,eAAe;CACnE,CAAC;AAGF,MAAM,UAAU,uBAAuB,CAAC,OAAe,EAAE,MAAgC;IACvF,OAAO,eAAe,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC;AAC1C,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { ReactElement, ReactNode } from 'react';
2
+ export interface BiomePresenceGateProps {
3
+ readonly biomeId: string;
4
+ readonly children: ReactNode;
5
+ readonly loading?: ReactNode;
6
+ }
7
+ export declare function BiomePresenceGate({ biomeId, children, loading, }: BiomePresenceGateProps): ReactElement | null;
8
+ //# sourceMappingURL=biome-presence-gate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"biome-presence-gate.d.ts","sourceRoot":"","sources":["../../../src/registry/lib/biome-presence-gate.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAErD,MAAM,WAAW,sBAAsB;IAErC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC;IAE7B,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC;CAC9B;AAWD,wBAAgB,iBAAiB,CAAC,EAChC,OAAO,EACP,QAAQ,EACR,OAAO,GACR,EAAE,sBAAsB,GAAG,YAAY,GAAG,IAAI,CAY9C"}
@@ -0,0 +1,19 @@
1
+ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
2
+ import { BiomePresence } from './biome-presence';
3
+ import { useBiomePresence } from './biome-presence-context';
4
+ import { BiomePresenceErrorCard } from './biome-presence-error-card';
5
+ import LoadingState from '../../ui/chrome/LoadingState';
6
+ export function BiomePresenceGate({ biomeId, children, loading, }) {
7
+ const answer = useBiomePresence(biomeId);
8
+ switch (answer.presence) {
9
+ case BiomePresence.Installed:
10
+ return _jsx(_Fragment, { children: children });
11
+ case BiomePresence.Loading:
12
+ return _jsx(_Fragment, { children: loading ?? _jsx(LoadingState, {}) });
13
+ case BiomePresence.Absent:
14
+ return null;
15
+ case BiomePresence.Error:
16
+ return _jsx(BiomePresenceErrorCard, { biomeId: biomeId, answer: answer });
17
+ }
18
+ }
19
+ //# sourceMappingURL=biome-presence-gate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"biome-presence-gate.js","sourceRoot":"","sources":["../../../src/registry/lib/biome-presence-gate.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,YAAY,MAAM,8BAA8B,CAAC;AAsBxD,MAAM,UAAU,iBAAiB,CAAC,EAChC,OAAO,EACP,QAAQ,EACR,OAAO,GACgB;IACvB,MAAM,MAAM,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACzC,QAAQ,MAAM,CAAC,QAAQ,EAAE,CAAC;QACxB,KAAK,aAAa,CAAC,SAAS;YAC1B,OAAO,4BAAG,QAAQ,GAAI,CAAC;QACzB,KAAK,aAAa,CAAC,OAAO;YACxB,OAAO,4BAAG,OAAO,IAAI,KAAC,YAAY,KAAG,GAAI,CAAC;QAC5C,KAAK,aAAa,CAAC,MAAM;YACvB,OAAO,IAAI,CAAC;QACd,KAAK,aAAa,CAAC,KAAK;YACtB,OAAO,KAAC,sBAAsB,IAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAI,CAAC;IACxE,CAAC;AACH,CAAC"}
@@ -0,0 +1,28 @@
1
+ export declare enum BiomePresence {
2
+ Loading = "loading",
3
+ Installed = "installed",
4
+ Absent = "absent",
5
+ Error = "error"
6
+ }
7
+ export declare enum BiomePresenceErrorReason {
8
+ LookupFailed = "lookup_failed",
9
+ ProviderUnavailable = "provider_unavailable",
10
+ AuthorizationDenied = "authorization_denied"
11
+ }
12
+ export interface BiomePresenceLoading {
13
+ readonly presence: BiomePresence.Loading;
14
+ }
15
+ export interface BiomePresenceInstalled {
16
+ readonly presence: BiomePresence.Installed;
17
+ }
18
+ export interface BiomePresenceAbsent {
19
+ readonly presence: BiomePresence.Absent;
20
+ }
21
+ export interface BiomePresenceError {
22
+ readonly presence: BiomePresence.Error;
23
+ readonly reason: BiomePresenceErrorReason;
24
+ readonly error: unknown;
25
+ }
26
+ export type BiomePresenceAnswer = BiomePresenceLoading | BiomePresenceInstalled | BiomePresenceAbsent | BiomePresenceError;
27
+ export type BiomePresenceLookup = (biomeId: string) => BiomePresenceAnswer;
28
+ //# sourceMappingURL=biome-presence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"biome-presence.d.ts","sourceRoot":"","sources":["../../../src/registry/lib/biome-presence.ts"],"names":[],"mappings":"AA+BA,oBAAY,aAAa;IAEvB,OAAO,YAAY;IAEnB,SAAS,cAAc;IAEvB,MAAM,WAAW;IAEjB,KAAK,UAAU;CAChB;AAGD,oBAAY,wBAAwB;IAElC,YAAY,kBAAkB;IAE9B,mBAAmB,yBAAyB;IAE5C,mBAAmB,yBAAyB;CAC7C;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC,OAAO,CAAC;CAC1C;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC,SAAS,CAAC;CAC5C;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC,MAAM,CAAC;CACzC;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC,KAAK,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE,wBAAwB,CAAC;IAE1C,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAGD,MAAM,MAAM,mBAAmB,GAC3B,oBAAoB,GACpB,sBAAsB,GACtB,mBAAmB,GACnB,kBAAkB,CAAC;AAGvB,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,mBAAmB,CAAC"}
@@ -0,0 +1,14 @@
1
+ export var BiomePresence;
2
+ (function (BiomePresence) {
3
+ BiomePresence["Loading"] = "loading";
4
+ BiomePresence["Installed"] = "installed";
5
+ BiomePresence["Absent"] = "absent";
6
+ BiomePresence["Error"] = "error";
7
+ })(BiomePresence || (BiomePresence = {}));
8
+ export var BiomePresenceErrorReason;
9
+ (function (BiomePresenceErrorReason) {
10
+ BiomePresenceErrorReason["LookupFailed"] = "lookup_failed";
11
+ BiomePresenceErrorReason["ProviderUnavailable"] = "provider_unavailable";
12
+ BiomePresenceErrorReason["AuthorizationDenied"] = "authorization_denied";
13
+ })(BiomePresenceErrorReason || (BiomePresenceErrorReason = {}));
14
+ //# sourceMappingURL=biome-presence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"biome-presence.js","sourceRoot":"","sources":["../../../src/registry/lib/biome-presence.ts"],"names":[],"mappings":"AA+BA,MAAM,CAAN,IAAY,aASX;AATD,WAAY,aAAa;IAEvB,oCAAmB,CAAA;IAEnB,wCAAuB,CAAA;IAEvB,kCAAiB,CAAA;IAEjB,gCAAe,CAAA;AACjB,CAAC,EATW,aAAa,KAAb,aAAa,QASxB;AAGD,MAAM,CAAN,IAAY,wBAOX;AAPD,WAAY,wBAAwB;IAElC,0DAA8B,CAAA;IAE9B,wEAA4C,CAAA;IAE5C,wEAA4C,CAAA;AAC9C,CAAC,EAPW,wBAAwB,KAAxB,wBAAwB,QAOnC"}
@@ -1 +1 @@
1
- {"version":3,"file":"biome-slot.d.ts","sourceRoot":"","sources":["../../../src/registry/lib/biome-slot.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,YAAY,EAAE,MAAM,OAAO,CAAC;AAMpD,MAAM,WAAW,cAAc;IAE7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,QAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;CACzC;AAqBD,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,YAAY,GAAG,IAAI,CAqCpE"}
1
+ {"version":3,"file":"biome-slot.d.ts","sourceRoot":"","sources":["../../../src/registry/lib/biome-slot.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAwB,KAAK,YAAY,EAAE,MAAM,OAAO,CAAC;AAWhE,MAAM,WAAW,cAAc;IAE7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,QAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;CACzC;AAwBD,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,YAAY,GAAG,IAAI,CAkEpE"}
@@ -1,21 +1,42 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { Fragment } from 'react';
3
- import { useBiomeApplicability } from './biome-applicability-context';
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Fragment, useContext } from 'react';
3
+ import { BiomePresence } from './biome-presence';
4
+ import { BiomePresenceContext, MissingBiomePresenceProviderError, } from './biome-presence-context';
5
+ import { BiomePresenceErrorCard } from './biome-presence-error-card';
4
6
  import { useBiomesEnabled } from './biomes-enabled-context';
5
7
  import { biomeRegistry, useBiomeRegistryRevision } from '../../index';
6
8
  export function BiomeSlot(props) {
7
9
  useBiomeRegistryRevision();
8
10
  const enabled = useBiomesEnabled();
9
- const applies = useBiomeApplicability();
11
+ const presenceOf = useContext(BiomePresenceContext);
10
12
  if (!enabled) {
11
13
  return props.fallback ?? null;
12
14
  }
13
- const entries = biomeRegistry
14
- .panelEntriesForSlot(props.name)
15
- .filter((entry) => applies(entry.biomeId));
16
- if (entries.length === 0) {
17
- return props.fallback ?? null;
15
+ if (presenceOf === null) {
16
+ throw new MissingBiomePresenceProviderError();
17
+ }
18
+ const installed = [];
19
+ const failed = [];
20
+ let unresolved = false;
21
+ for (const entry of biomeRegistry.panelEntriesForSlot(props.name)) {
22
+ const answer = presenceOf(entry.biomeId);
23
+ switch (answer.presence) {
24
+ case BiomePresence.Installed:
25
+ installed.push({ key: entry.panel.id, node: _jsx(_Fragment, { children: entry.panel.render() }) });
26
+ break;
27
+ case BiomePresence.Error:
28
+ failed.push({ key: entry.panel.id, biomeId: entry.biomeId, answer });
29
+ break;
30
+ case BiomePresence.Loading:
31
+ unresolved = true;
32
+ break;
33
+ case BiomePresence.Absent:
34
+ break;
35
+ }
36
+ }
37
+ if (installed.length === 0 && failed.length === 0) {
38
+ return unresolved ? null : (props.fallback ?? null);
18
39
  }
19
- return (_jsx(Fragment, { children: entries.map((entry) => (_jsx(Fragment, { children: entry.panel.render() }, entry.panel.id))) }));
40
+ return (_jsxs(Fragment, { children: [installed.map(({ key, node }) => (_jsx(Fragment, { children: node }, key))), failed.map(({ key, biomeId, answer }) => (_jsx(BiomePresenceErrorCard, { biomeId: biomeId, answer: answer }, key)))] }));
20
41
  }
21
42
  //# sourceMappingURL=biome-slot.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"biome-slot.js","sourceRoot":"","sources":["../../../src/registry/lib/biome-slot.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAqB,MAAM,OAAO,CAAC;AAEpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AA4BtE,MAAM,UAAU,SAAS,CAAC,KAAqB;IAE7C,wBAAwB,EAAE,CAAC;IAC3B,MAAM,OAAO,GAAG,gBAAgB,EAAE,CAAC;IAInC,MAAM,OAAO,GAAG,qBAAqB,EAAE,CAAC;IACxC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,KAAK,CAAC,QAAQ,IAAI,IAAI,CAAC;IAChC,CAAC;IAcD,MAAM,OAAO,GAAG,aAAa;SAC1B,mBAAmB,CAAC,KAAK,CAAC,IAAI,CAAC;SAC/B,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;IAC7C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC,QAAQ,IAAI,IAAI,CAAC;IAChC,CAAC;IACD,OAAO,CACL,KAAC,QAAQ,cACN,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CACtB,KAAC,QAAQ,cAAuB,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,IAArC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAmC,CACjE,CAAC,GACO,CACZ,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"biome-slot.js","sourceRoot":"","sources":["../../../src/registry/lib/biome-slot.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAqB,MAAM,OAAO,CAAC;AAEhE,OAAO,EAAE,aAAa,EAA2B,MAAM,kBAAkB,CAAC;AAC1E,OAAO,EACL,oBAAoB,EACpB,iCAAiC,GAClC,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AA+BtE,MAAM,UAAU,SAAS,CAAC,KAAqB;IAE7C,wBAAwB,EAAE,CAAC;IAC3B,MAAM,OAAO,GAAG,gBAAgB,EAAE,CAAC;IAMnC,MAAM,UAAU,GAAG,UAAU,CAAC,oBAAoB,CAAC,CAAC;IACpD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,KAAK,CAAC,QAAQ,IAAI,IAAI,CAAC;IAChC,CAAC;IACD,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;QACxB,MAAM,IAAI,iCAAiC,EAAE,CAAC;IAChD,CAAC;IAmBD,MAAM,SAAS,GAA4D,EAAE,CAAC;IAC9E,MAAM,MAAM,GAA8F,EAAE,CAAC;IAC7G,IAAI,UAAU,GAAG,KAAK,CAAC;IACvB,KAAK,MAAM,KAAK,IAAI,aAAa,CAAC,mBAAmB,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAClE,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACzC,QAAQ,MAAM,CAAC,QAAQ,EAAE,CAAC;YACxB,KAAK,aAAa,CAAC,SAAS;gBAC1B,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,4BAAG,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,GAAI,EAAE,CAAC,CAAC;gBAC3E,MAAM;YACR,KAAK,aAAa,CAAC,KAAK;gBACtB,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;gBACrE,MAAM;YACR,KAAK,aAAa,CAAC,OAAO;gBACxB,UAAU,GAAG,IAAI,CAAC;gBAClB,MAAM;YACR,KAAK,aAAa,CAAC,MAAM;gBACvB,MAAM;QACV,CAAC;IACH,CAAC;IACD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClD,OAAO,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC;IACtD,CAAC;IACD,OAAO,CACL,MAAC,QAAQ,eACN,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAChC,KAAC,QAAQ,cAAY,IAAI,IAAV,GAAG,CAAmB,CACtC,CAAC,EACD,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CACxC,KAAC,sBAAsB,IAAW,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,IAArC,GAAG,CAAsC,CACvE,CAAC,IACO,CACZ,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"app-branding-provider.d.ts","sourceRoot":"","sources":["../../../src/ui/branding/app-branding-provider.tsx"],"names":[],"mappings":"AAoBA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAa/B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAGrE,eAAO,MAAM,qBAAqB,wBAAwB,CAAC;AAE3D,MAAM,WAAW,wBAAwB;IAEvC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAOlC,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IAElD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CACpC;AAgDD,wBAAgB,mBAAmB,CAAC,EAClC,QAAQ,EACR,cAAc,EACd,SAAS,EACT,QAAQ,GACT,EAAE,wBAAwB,GAAG,KAAK,CAAC,YAAY,CAmB/C"}
1
+ {"version":3,"file":"app-branding-provider.d.ts","sourceRoot":"","sources":["../../../src/ui/branding/app-branding-provider.tsx"],"names":[],"mappings":"AA8BA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAS/B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAUrE,eAAO,MAAM,qBAAqB,wBAAwB,CAAC;AAE3D,MAAM,WAAW,wBAAwB;IAEvC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAOlC,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IAElD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CACpC;AAsDD,wBAAgB,mBAAmB,CAAC,EAClC,QAAQ,EACR,cAAc,EACd,SAAS,EACT,QAAQ,GACT,EAAE,wBAAwB,GAAG,KAAK,CAAC,YAAY,CAmB/C"}
@@ -1,28 +1,33 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { BrandingConfigSchema } from '@xemahq/contracts/app-platform';
3
+ import { assertSafeCssTokenValue, CSS_TOKEN_KEY_PATTERN, UnsafeCssValueError, } from '@xemahq/contracts/css-safe';
2
4
  import * as React from 'react';
3
5
  import { cn } from '../cn';
4
6
  import { AppBrandingContext, } from './app-branding-context';
5
- import { sanitizeCssCustomPropertyName, sanitizeCssValue, sanitizeLogoUrl, } from './sanitize';
7
+ import { assertSafeLogoUrl } from './sanitize';
8
+ const PRIMARY_COLOR_PROBE_NAME = 'primaryColor';
6
9
  export const APP_PRIMARY_COLOR_VAR = '--app-primary-color';
7
10
  function resolveBranding(branding, tenantBranding) {
8
11
  const displayName = tenantBranding?.displayName ?? branding.displayName;
9
12
  const rawPrimary = tenantBranding?.primaryColor ?? branding.primaryColor;
10
13
  const rawLogo = tenantBranding?.logoUrl ?? branding.logoUrl;
11
14
  const cssTokens = { ...branding.cssTokens, ...tenantBranding?.cssTokens };
12
- const primaryColor = rawPrimary !== undefined
13
- ? (sanitizeCssValue(rawPrimary) ?? undefined)
14
- : undefined;
15
- const logoUrl = sanitizeLogoUrl(rawLogo);
15
+ const primaryColor = rawPrimary === undefined
16
+ ? undefined
17
+ : BrandingConfigSchema.parse({
18
+ displayName: PRIMARY_COLOR_PROBE_NAME,
19
+ primaryColor: rawPrimary,
20
+ }).primaryColor;
21
+ const logoUrl = assertSafeLogoUrl(rawLogo);
16
22
  const cssVars = {};
17
23
  if (primaryColor !== undefined) {
18
24
  cssVars[APP_PRIMARY_COLOR_VAR] = primaryColor;
19
25
  }
20
- for (const [rawKey, rawValue] of Object.entries(cssTokens)) {
21
- const name = sanitizeCssCustomPropertyName(rawKey);
22
- const value = sanitizeCssValue(rawValue);
23
- if (name !== null && value !== null) {
24
- cssVars[name] = value;
26
+ for (const [key, value] of Object.entries(cssTokens)) {
27
+ if (!CSS_TOKEN_KEY_PATTERN.test(key)) {
28
+ throw new UnsafeCssValueError(`cssTokens.${key}`, 'a token key is lowercase kebab-case without the leading "--", at most 64 characters');
25
29
  }
30
+ cssVars[`--${key}`] = assertSafeCssTokenValue(`cssTokens.${key}`, value);
26
31
  }
27
32
  return {
28
33
  context: { displayName, logoUrl, primaryColor },
@@ -1 +1 @@
1
- {"version":3,"file":"app-branding-provider.js","sourceRoot":"","sources":["../../../src/ui/branding/app-branding-provider.tsx"],"names":[],"mappings":";AAoBA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAC3B,OAAO,EACL,kBAAkB,GAEnB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,6BAA6B,EAC7B,gBAAgB,EAChB,eAAe,GAChB,MAAM,YAAY,CAAC;AAKpB,MAAM,CAAC,MAAM,qBAAqB,GAAG,qBAAqB,CAAC;AAqB3D,SAAS,eAAe,CACtB,QAAwB,EACxB,cAAmD;IAKnD,MAAM,WAAW,GAAG,cAAc,EAAE,WAAW,IAAI,QAAQ,CAAC,WAAW,CAAC;IACxE,MAAM,UAAU,GAAG,cAAc,EAAE,YAAY,IAAI,QAAQ,CAAC,YAAY,CAAC;IACzE,MAAM,OAAO,GAAG,cAAc,EAAE,OAAO,IAAI,QAAQ,CAAC,OAAO,CAAC;IAC5D,MAAM,SAAS,GAAG,EAAE,GAAG,QAAQ,CAAC,SAAS,EAAE,GAAG,cAAc,EAAE,SAAS,EAAE,CAAC;IAE1E,MAAM,YAAY,GAChB,UAAU,KAAK,SAAS;QACtB,CAAC,CAAC,CAAC,gBAAgB,CAAC,UAAU,CAAC,IAAI,SAAS,CAAC;QAC7C,CAAC,CAAC,SAAS,CAAC;IAChB,MAAM,OAAO,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IAEzC,MAAM,OAAO,GAA2B,EAAE,CAAC;IAC3C,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,CAAC,qBAAqB,CAAC,GAAG,YAAY,CAAC;IAChD,CAAC;IACD,KAAK,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3D,MAAM,IAAI,GAAG,6BAA6B,CAAC,MAAM,CAAC,CAAC;QACnD,MAAM,KAAK,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QACzC,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACpC,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;QACxB,CAAC;IACH,CAAC;IAED,OAAO;QACL,OAAO,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,YAAY,EAAE;QAC/C,OAAO;KACR,CAAC;AACJ,CAAC;AAQD,MAAM,UAAU,mBAAmB,CAAC,EAClC,QAAQ,EACR,cAAc,EACd,SAAS,EACT,QAAQ,GACiB;IACzB,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC,OAAO,CACxC,GAAG,EAAE,CAAC,eAAe,CAAC,QAAQ,EAAE,cAAc,CAAC,EAC/C,CAAC,QAAQ,EAAE,cAAc,CAAC,CAC3B,CAAC;IAEF,OAAO,CACL,KAAC,kBAAkB,CAAC,QAAQ,IAAC,KAAK,EAAE,OAAO,YACzC,mCACoB,EAAE,EACpB,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,EAGxB,KAAK,EAAE,OAAO,YAEb,QAAQ,GACL,GACsB,CAC/B,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"app-branding-provider.js","sourceRoot":"","sources":["../../../src/ui/branding/app-branding-provider.tsx"],"names":[],"mappings":";AAwBA,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAC3B,OAAO,EACL,kBAAkB,GAEnB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAS/C,MAAM,wBAAwB,GAAG,cAAc,CAAC;AAGhD,MAAM,CAAC,MAAM,qBAAqB,GAAG,qBAAqB,CAAC;AAsB3D,SAAS,eAAe,CACtB,QAAwB,EACxB,cAAmD;IAKnD,MAAM,WAAW,GAAG,cAAc,EAAE,WAAW,IAAI,QAAQ,CAAC,WAAW,CAAC;IACxE,MAAM,UAAU,GAAG,cAAc,EAAE,YAAY,IAAI,QAAQ,CAAC,YAAY,CAAC;IACzE,MAAM,OAAO,GAAG,cAAc,EAAE,OAAO,IAAI,QAAQ,CAAC,OAAO,CAAC;IAC5D,MAAM,SAAS,GAAG,EAAE,GAAG,QAAQ,CAAC,SAAS,EAAE,GAAG,cAAc,EAAE,SAAS,EAAE,CAAC;IAE1E,MAAM,YAAY,GAChB,UAAU,KAAK,SAAS;QACtB,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,oBAAoB,CAAC,KAAK,CAAC;YACzB,WAAW,EAAE,wBAAwB;YACrC,YAAY,EAAE,UAAU;SACzB,CAAC,CAAC,YAAY,CAAC;IACtB,MAAM,OAAO,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAE3C,MAAM,OAAO,GAA2B,EAAE,CAAC;IAC3C,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,CAAC,qBAAqB,CAAC,GAAG,YAAY,CAAC;IAChD,CAAC;IACD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QACrD,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACrC,MAAM,IAAI,mBAAmB,CAC3B,aAAa,GAAG,EAAE,EAClB,qFAAqF,CACtF,CAAC;QACJ,CAAC;QACD,OAAO,CAAC,KAAK,GAAG,EAAE,CAAC,GAAG,uBAAuB,CAAC,aAAa,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC;IAC3E,CAAC;IAED,OAAO;QACL,OAAO,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,YAAY,EAAE;QAC/C,OAAO;KACR,CAAC;AACJ,CAAC;AAQD,MAAM,UAAU,mBAAmB,CAAC,EAClC,QAAQ,EACR,cAAc,EACd,SAAS,EACT,QAAQ,GACiB;IACzB,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC,OAAO,CACxC,GAAG,EAAE,CAAC,eAAe,CAAC,QAAQ,EAAE,cAAc,CAAC,EAC/C,CAAC,QAAQ,EAAE,cAAc,CAAC,CAC3B,CAAC;IAEF,OAAO,CACL,KAAC,kBAAkB,CAAC,QAAQ,IAAC,KAAK,EAAE,OAAO,YACzC,mCACoB,EAAE,EACpB,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,EAGxB,KAAK,EAAE,OAAO,YAEb,QAAQ,GACL,GACsB,CAC/B,CAAC;AACJ,CAAC"}
@@ -1,4 +1,6 @@
1
- export declare function sanitizeCssValue(raw: string): string | null;
2
- export declare function sanitizeCssCustomPropertyName(rawKey: string): string | null;
3
- export declare function sanitizeLogoUrl(raw: string | undefined): string | undefined;
1
+ export declare class UnsafeLogoUrlError extends Error {
2
+ readonly field: string;
3
+ constructor(field: string, reason: string);
4
+ }
5
+ export declare function assertSafeLogoUrl(raw: string | undefined): string | undefined;
4
6
  //# sourceMappingURL=sanitize.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../../src/ui/branding/sanitize.ts"],"names":[],"mappings":"AA2CA,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAY3D;AAMD,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAM3E;AAOD,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAc3E"}
1
+ {"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../../src/ui/branding/sanitize.ts"],"names":[],"mappings":"AAWA,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAEX,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAK1C;AAOD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAc7E"}
@@ -1,35 +1,12 @@
1
- const CSS_VALUE_UNSAFE = /[;{}<>\\]|\/\*|\*\//;
2
- const CSS_CUSTOM_PROPERTY_NAME = /^[a-zA-Z_][a-zA-Z0-9_-]*$/;
3
- function hasControlChar(value) {
4
- for (let i = 0; i < value.length; i += 1) {
5
- const code = value.charCodeAt(i);
6
- if (code < 0x20 || code === 0x7f) {
7
- return true;
8
- }
1
+ export class UnsafeLogoUrlError extends Error {
2
+ field;
3
+ constructor(field, reason) {
4
+ super(`Refusing to render '${field}' as an image source: ${reason}.`);
5
+ this.name = 'UnsafeLogoUrlError';
6
+ this.field = field;
9
7
  }
10
- return false;
11
8
  }
12
- export function sanitizeCssValue(raw) {
13
- const value = raw.trim();
14
- if (value.length === 0) {
15
- return null;
16
- }
17
- if (CSS_VALUE_UNSAFE.test(value)) {
18
- return null;
19
- }
20
- if (hasControlChar(value)) {
21
- return null;
22
- }
23
- return value;
24
- }
25
- export function sanitizeCssCustomPropertyName(rawKey) {
26
- const name = rawKey.trim();
27
- if (!CSS_CUSTOM_PROPERTY_NAME.test(name)) {
28
- return null;
29
- }
30
- return `--${name}`;
31
- }
32
- export function sanitizeLogoUrl(raw) {
9
+ export function assertSafeLogoUrl(raw) {
33
10
  if (raw === undefined) {
34
11
  return undefined;
35
12
  }
@@ -38,10 +15,10 @@ export function sanitizeLogoUrl(raw) {
38
15
  parsed = new URL(raw);
39
16
  }
40
17
  catch {
41
- return undefined;
18
+ throw new UnsafeLogoUrlError('logoUrl', 'the value is not an absolute URL');
42
19
  }
43
20
  if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
44
- return undefined;
21
+ throw new UnsafeLogoUrlError('logoUrl', 'only http(s) URLs are allowed');
45
22
  }
46
23
  return parsed.href;
47
24
  }
@@ -1 +1 @@
1
- {"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../../../src/ui/branding/sanitize.ts"],"names":[],"mappings":"AAmBA,MAAM,gBAAgB,GAAG,qBAAqB,CAAC;AAO/C,MAAM,wBAAwB,GAAG,2BAA2B,CAAC;AAG7D,SAAS,cAAc,CAAC,KAAa;IACnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACzC,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QACjC,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YACjC,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAMD,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IACzB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACjC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAMD,MAAM,UAAU,6BAA6B,CAAC,MAAc;IAC1D,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IAC3B,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACzC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,KAAK,IAAI,EAAE,CAAC;AACrB,CAAC;AAOD,MAAM,UAAU,eAAe,CAAC,GAAuB;IACrD,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,MAAW,CAAC;IAChB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAChE,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC"}
1
+ {"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../../../src/ui/branding/sanitize.ts"],"names":[],"mappings":"AAWA,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAClC,KAAK,CAAS;IAEvB,YAAY,KAAa,EAAE,MAAc;QACvC,KAAK,CAAC,uBAAuB,KAAK,yBAAyB,MAAM,GAAG,CAAC,CAAC;QACtE,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;QACjC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;CACF;AAOD,MAAM,UAAU,iBAAiB,CAAC,GAAuB;IACvD,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,MAAW,CAAC;IAChB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,kBAAkB,CAAC,SAAS,EAAE,kCAAkC,CAAC,CAAC;IAC9E,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAChE,MAAM,IAAI,kBAAkB,CAAC,SAAS,EAAE,+BAA+B,CAAC,CAAC;IAC3E,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xemahq/ui-kernel",
3
- "version": "0.25.1",
3
+ "version": "0.27.0",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "description": "Host-framework-agnostic UI kernel for Xema. 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.",
@@ -62,7 +62,7 @@
62
62
  "peerDependencies": {
63
63
  "@tanstack/react-query": "^5.0.0",
64
64
  "react": "^18.3.1",
65
- "@xemahq/contracts": ">=0.4.0"
65
+ "@xemahq/contracts": ">=0.90.0"
66
66
  },
67
67
  "peerDependenciesMeta": {
68
68
  "@tanstack/react-query": {
@@ -74,14 +74,14 @@
74
74
  "@types/node": "25.2.3",
75
75
  "@types/react": "^18.3.30",
76
76
  "@types/react-dom": "^18.3.7",
77
- "@xemahq/contracts": "^0.79.0",
77
+ "@xemahq/contracts": "^0.90.0",
78
78
  "eslint": "^9.39.4",
79
79
  "prettier": "3.6.2",
80
80
  "react": "^18.3.1",
81
81
  "react-dom": "^18.3.1",
82
82
  "typescript": "5.9.3",
83
83
  "vitest": "^3.2.4",
84
- "@xemahq/eslint-config": "0.14.0"
84
+ "@xemahq/eslint-config": "0.14.1"
85
85
  },
86
86
  "exports": {
87
87
  ".": {
@@ -119,6 +119,6 @@
119
119
  "typecheck": "tsc -p tsconfig.lint.json --noEmit"
120
120
  },
121
121
  "xemaRelease": {
122
- "sourceDigest": "sha256:5a2f772fbd3db90cf259986714ab70187641c76c164abcaf315852b181235921"
122
+ "sourceDigest": "sha256:7543ee6ff94afbaa3a2e75b2a11f429b08ebccf70725986bd21d350b9f46b5e1"
123
123
  }
124
124
  }
@@ -1,4 +0,0 @@
1
- export type BiomeApplicability = (biomeId: string) => boolean;
2
- export declare const BiomeApplicabilityContext: import("react").Context<BiomeApplicability>;
3
- export declare function useBiomeApplicability(): BiomeApplicability;
4
- //# sourceMappingURL=biome-applicability-context.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"biome-applicability-context.d.ts","sourceRoot":"","sources":["../../../src/registry/lib/biome-applicability-context.ts"],"names":[],"mappings":"AAwCA,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;AAI9D,eAAO,MAAM,yBAAyB,6CACoB,CAAC;AAG3D,wBAAgB,qBAAqB,IAAI,kBAAkB,CAE1D"}
@@ -1,8 +0,0 @@
1
- import { createContext, useContext } from 'react';
2
- const APPLIES_TO_EVERYTHING = () => true;
3
- export const BiomeApplicabilityContext = createContext(APPLIES_TO_EVERYTHING);
4
- BiomeApplicabilityContext.displayName = 'BiomeApplicabilityContext';
5
- export function useBiomeApplicability() {
6
- return useContext(BiomeApplicabilityContext);
7
- }
8
- //# sourceMappingURL=biome-applicability-context.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"biome-applicability-context.js","sourceRoot":"","sources":["../../../src/registry/lib/biome-applicability-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AA0ClD,MAAM,qBAAqB,GAAuB,GAAG,EAAE,CAAC,IAAI,CAAC;AAE7D,MAAM,CAAC,MAAM,yBAAyB,GACpC,aAAa,CAAqB,qBAAqB,CAAC,CAAC;AAC3D,yBAAyB,CAAC,WAAW,GAAG,2BAA2B,CAAC;AAEpE,MAAM,UAAU,qBAAqB;IACnC,OAAO,UAAU,CAAC,yBAAyB,CAAC,CAAC;AAC/C,CAAC"}