@ikonai/sdk-react-ui 1.8.0 → 1.11.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 (130) hide show
  1. package/account/use-account-removal.d.ts +37 -0
  2. package/account/use-account-removal.d.ts.map +1 -0
  3. package/app/boot-snapshot-variant.d.ts +2 -1
  4. package/app/boot-snapshot-variant.d.ts.map +1 -0
  5. package/app/connection-recovery.d.ts +1 -0
  6. package/app/connection-recovery.d.ts.map +1 -0
  7. package/app/connection-state-renderer.d.ts +6 -5
  8. package/app/connection-state-renderer.d.ts.map +1 -0
  9. package/app/feedback/feedback-controls.d.ts +24 -0
  10. package/app/feedback/feedback-controls.d.ts.map +1 -0
  11. package/app/feedback/feedback-form.d.ts +26 -0
  12. package/app/feedback/feedback-form.d.ts.map +1 -0
  13. package/app/feedback/platform-layer.d.ts +32 -0
  14. package/app/feedback/platform-layer.d.ts.map +1 -0
  15. package/app/feedback/use-ikon-feedback.d.ts +13 -0
  16. package/app/feedback/use-ikon-feedback.d.ts.map +1 -0
  17. package/app/ikon-app.d.ts +4 -3
  18. package/app/ikon-app.d.ts.map +1 -0
  19. package/app/index.d.ts +2 -0
  20. package/app/index.d.ts.map +1 -0
  21. package/app/use-ikon-app.d.ts +35 -9
  22. package/app/use-ikon-app.d.ts.map +1 -0
  23. package/app/use-ikon-debug.d.ts +3 -2
  24. package/app/use-ikon-debug.d.ts.map +1 -0
  25. package/auth/auth-context.d.ts +2 -1
  26. package/auth/auth-context.d.ts.map +1 -0
  27. package/auth/auth-service.d.ts +38 -5
  28. package/auth/auth-service.d.ts.map +1 -0
  29. package/auth/index.d.ts +5 -3
  30. package/auth/index.d.ts.map +1 -0
  31. package/auth/oauth-continuation.d.ts +16 -1
  32. package/auth/oauth-continuation.d.ts.map +1 -0
  33. package/auth/storage.d.ts +1 -0
  34. package/auth/storage.d.ts.map +1 -0
  35. package/auth/types.d.ts +19 -4
  36. package/auth/types.d.ts.map +1 -0
  37. package/auth/use-auth-guard.d.ts +1 -0
  38. package/auth/use-auth-guard.d.ts.map +1 -0
  39. package/auth/use-sso-sign-in.d.ts +18 -0
  40. package/auth/use-sso-sign-in.d.ts.map +1 -0
  41. package/base/base-div.d.ts +1 -0
  42. package/base/base-div.d.ts.map +1 -0
  43. package/base/base-module.d.ts +1 -0
  44. package/base/base-module.d.ts.map +1 -0
  45. package/consent/use-consent.d.ts +35 -0
  46. package/consent/use-consent.d.ts.map +1 -0
  47. package/debug/debug-overlay.d.ts +2 -1
  48. package/debug/debug-overlay.d.ts.map +1 -0
  49. package/feedback-form-BSy2olwD.js +511 -0
  50. package/hooks/index.d.ts +1 -0
  51. package/hooks/index.d.ts.map +1 -0
  52. package/hooks/use-ikon-reactive.d.ts +2 -1
  53. package/hooks/use-ikon-reactive.d.ts.map +1 -0
  54. package/hooks/use-reactive.d.ts +2 -1
  55. package/hooks/use-reactive.d.ts.map +1 -0
  56. package/hooks/use-toasts.d.ts +1 -0
  57. package/hooks/use-toasts.d.ts.map +1 -0
  58. package/i18n/i18n.d.ts +2 -1
  59. package/i18n/i18n.d.ts.map +1 -0
  60. package/i18n/index.d.ts +1 -0
  61. package/i18n/index.d.ts.map +1 -0
  62. package/ikon-ui-registry.d.ts +1 -0
  63. package/ikon-ui-registry.d.ts.map +1 -0
  64. package/ikon-ui.d.ts +3 -2
  65. package/ikon-ui.d.ts.map +1 -0
  66. package/index.d.ts +10 -7
  67. package/index.d.ts.map +1 -0
  68. package/index.js +2045 -1850
  69. package/inspect/inspect-overlay.d.ts +1 -0
  70. package/inspect/inspect-overlay.d.ts.map +1 -0
  71. package/media/audio-player.d.ts +1 -0
  72. package/media/audio-player.d.ts.map +1 -0
  73. package/media/media-module.d.ts +1 -0
  74. package/media/media-module.d.ts.map +1 -0
  75. package/media/use-media-capture.d.ts +2 -1
  76. package/media/use-media-capture.d.ts.map +1 -0
  77. package/media/use-sibling-client.d.ts +2 -1
  78. package/media/use-sibling-client.d.ts.map +1 -0
  79. package/media/video-canvas.d.ts +1 -0
  80. package/media/video-canvas.d.ts.map +1 -0
  81. package/media/video-stream-view.d.ts +3 -2
  82. package/media/video-stream-view.d.ts.map +1 -0
  83. package/motion/motion-controller.d.ts +2 -1
  84. package/motion/motion-controller.d.ts.map +1 -0
  85. package/package.json +1 -1
  86. package/parallax-view.d.ts +5 -4
  87. package/parallax-view.d.ts.map +1 -0
  88. package/renderer/component-library.d.ts +1 -0
  89. package/renderer/component-library.d.ts.map +1 -0
  90. package/renderer/index.d.ts +3 -1
  91. package/renderer/index.d.ts.map +1 -0
  92. package/renderer/lazy-resolver.d.ts +10 -0
  93. package/renderer/lazy-resolver.d.ts.map +1 -0
  94. package/renderer/types.d.ts +17 -5
  95. package/renderer/types.d.ts.map +1 -0
  96. package/renderer/ui-renderer.d.ts +6 -5
  97. package/renderer/ui-renderer.d.ts.map +1 -0
  98. package/renderer/use-root-view.d.ts +2 -1
  99. package/renderer/use-root-view.d.ts.map +1 -0
  100. package/renderer/use-ui-node.d.ts +2 -1
  101. package/renderer/use-ui-node.d.ts.map +1 -0
  102. package/renderer/use-ui-store.d.ts +2 -1
  103. package/renderer/use-ui-store.d.ts.map +1 -0
  104. package/shadertoy/shadertoy-gl.d.ts +1 -0
  105. package/shadertoy/shadertoy-gl.d.ts.map +1 -0
  106. package/shadertoy/shadertoy-module.d.ts +4 -3
  107. package/shadertoy/shadertoy-module.d.ts.map +1 -0
  108. package/shadertoy/shadertoy-renderer.d.ts +1 -1
  109. package/shadertoy/shadertoy-renderer.d.ts.map +1 -0
  110. package/shadertoy/shadertoy-type.d.ts +2 -0
  111. package/shadertoy/shadertoy-type.d.ts.map +1 -0
  112. package/shadertoy-renderer-Cq1lOXBs.js +428 -0
  113. package/shadertoy-type-Cs2WeCWV.js +15 -0
  114. package/shared/render-motion-letters.d.ts +1 -0
  115. package/shared/render-motion-letters.d.ts.map +1 -0
  116. package/surface.d.ts +10 -7
  117. package/surface.d.ts.map +1 -0
  118. package/theme/ikon-app.css +3 -1
  119. package/theme/ikon-auth.css +7 -5
  120. package/use-ikon-styles.d.ts +2 -1
  121. package/use-ikon-styles.d.ts.map +1 -0
  122. package/use-ikon-ui-stores.d.ts +2 -0
  123. package/use-ikon-ui-stores.d.ts.map +1 -0
  124. package/auth/auth-context.spec.d.ts +0 -1
  125. package/base/focus-hint-scroll.spec.d.ts +0 -1
  126. package/media/use-media-capture.spec.d.ts +0 -1
  127. package/media/use-sibling-client.spec.d.ts +0 -1
  128. package/media/video-stream-view.spec.d.ts +0 -1
  129. package/renderer/unresolved-node.spec.d.ts +0 -1
  130. package/vite.config.d.ts +0 -2
package/auth/types.d.ts CHANGED
@@ -4,6 +4,13 @@
4
4
  * anonymous identity (all visitors collapse onto a shared app instance).
5
5
  */
6
6
  export type LoginMethod = 'google' | 'facebook' | 'apple' | 'microsoft' | 'signicat' | 'email' | 'passkey' | 'guest' | 'global';
7
+ /**
8
+ * A method a space can offer: every {@link LoginMethod} plus 'sso', the space's own identity
9
+ * providers. 'sso' has no single button — which connection a person signs in through is found at
10
+ * runtime (`findSsoConnectionsForHost`, `discoverSsoConnection`) and started with `loginWithSso` —
11
+ * so it is kept out of `LoginMethod`, which apps key their per-provider button maps on.
12
+ */
13
+ export type AuthMethod = LoginMethod | 'sso';
7
14
  /**
8
15
  * Authenticated user information.
9
16
  *
@@ -12,7 +19,7 @@ export type LoginMethod = 'google' | 'facebook' | 'apple' | 'microsoft' | 'signi
12
19
  */
13
20
  export interface AuthUser {
14
21
  id: string;
15
- provider: LoginMethod | 'anonymous' | 'dev';
22
+ provider: AuthMethod | 'anonymous' | 'dev';
16
23
  token: string;
17
24
  authenticatedAt: number;
18
25
  /**
@@ -35,7 +42,7 @@ export interface AuthState {
35
42
  * Authentication configuration.
36
43
  */
37
44
  export interface AuthConfig {
38
- methods: LoginMethod[];
45
+ methods: AuthMethod[];
39
46
  spaceId: string;
40
47
  /**
41
48
  * When true, the frontend shows a mandatory sign-in wall before the app loads; listing 'guest' in
@@ -68,7 +75,7 @@ export interface AuthConfig {
68
75
  */
69
76
  export interface AuthSession {
70
77
  token: string;
71
- provider: LoginMethod | 'anonymous' | 'dev';
78
+ provider: AuthMethod | 'anonymous' | 'dev';
72
79
  authenticatedAt: number;
73
80
  /** Set when the token is short-lived and a refresh cookie stands behind it. */
74
81
  expiresAt?: string;
@@ -78,7 +85,7 @@ export interface AuthSession {
78
85
  * load that a session exists and whose it is, and nothing that can be used as a credential.
79
86
  */
80
87
  export interface RefreshableSession {
81
- provider: LoginMethod | 'anonymous' | 'dev';
88
+ provider: AuthMethod | 'anonymous' | 'dev';
82
89
  /** When the person actually signed in. Unchanged by renewals — those renew a token, not a login. */
83
90
  authenticatedAt: number;
84
91
  /** Last successful renewal, which is what the cookie's own lifetime runs from. */
@@ -90,9 +97,17 @@ export interface RefreshableSession {
90
97
  export interface AuthContextValue {
91
98
  state: AuthState;
92
99
  login: (method: LoginMethod) => Promise<void>;
100
+ /**
101
+ * Signs in through one of the space's SSO connections. `linkSessionToken`, the session this
102
+ * browser already holds, joins that account instead of making a new one.
103
+ */
104
+ loginWithSso: (connectionId: string, options?: {
105
+ linkSessionToken?: string;
106
+ }) => Promise<void>;
93
107
  logout: () => void;
94
108
  getToken: () => string | null;
95
109
  registerPasskey: (name?: string) => Promise<void>;
96
110
  requestEmailCode: (email: string) => Promise<void>;
97
111
  submitEmailCode: (email: string, code: string) => Promise<void>;
98
112
  }
113
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../sdk/sdk-react-ui/src/auth/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,UAAU,GAAG,OAAO,GAAG,WAAW,GAAG,UAAU,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEhI;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG,WAAW,GAAG,KAAK,CAAC;AAE7C;;;;;GAKG;AACH,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,UAAU,GAAG,WAAW,GAAG,KAAK,CAAC;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,eAAe,EAAE,OAAO,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kIAAkI;IAClI,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2FAA2F;IAC3F,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,2EAA2E;IAC3E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,UAAU,GAAG,WAAW,GAAG,KAAK,CAAC;IAC3C,eAAe,EAAE,MAAM,CAAC;IACxB,+EAA+E;IAC/E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,UAAU,GAAG,WAAW,GAAG,KAAK,CAAC;IAC3C,oGAAoG;IACpG,eAAe,EAAE,MAAM,CAAC;IACxB,kFAAkF;IAClF,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,SAAS,CAAC;IACjB,KAAK,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C;;;OAGG;IACH,YAAY,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,gBAAgB,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/F,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,QAAQ,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IAC9B,eAAe,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,gBAAgB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,eAAe,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACjE"}
@@ -50,3 +50,4 @@ export interface UseAuthGuardResult {
50
50
  * Returns state that can be used to conditionally render auth UI or protected content.
51
51
  */
52
52
  export declare function useAuthGuard(options: UseAuthGuardOptions): UseAuthGuardResult;
53
+ //# sourceMappingURL=use-auth-guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-auth-guard.d.ts","sourceRoot":"","sources":["../../../../sdk/sdk-react-ui/src/auth/use-auth-guard.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,MAAM,EAAE,UAAU,CAAC;IAEnB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,oBAAoB,EAAE,OAAO,CAAC;IAE9B;;OAEG;IACH,cAAc,EAAE,OAAO,CAAC;IAExB;;OAEG;IACH,eAAe,EAAE,OAAO,CAAC;IAEzB;;OAEG;IACH,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAErB;;;;OAIG;IACH,aAAa,EAAE,OAAO,CAAC;IAEvB;;OAEG;IACH,kBAAkB,EAAE,MAAM,IAAI,CAAC;IAE/B;;;;;OAKG;IACH,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,kBAAkB,CAiI7E"}
@@ -0,0 +1,18 @@
1
+ import { SsoConnectionHint } from './auth-service';
2
+ import { AuthConfig } from './types';
3
+ export interface UseSsoSignInResult {
4
+ /** The connections this host offers up front — the tenant's own IdP on the tenant's own host. */
5
+ hostConnections: SsoConnectionHint[];
6
+ isDiscovering: boolean;
7
+ /** Set when an address matched no connection, or the lookup failed. */
8
+ discoverError: string | null;
9
+ /** Finds the connection an address belongs to and starts signing in through it. */
10
+ discover: (email: string) => Promise<void>;
11
+ signIn: (connectionId: string) => Promise<void>;
12
+ }
13
+ /**
14
+ * What a sign-in screen needs to offer a space's own identity providers. Enabled when the app lists
15
+ * `sso` among its methods; which connection a person gets is found at runtime, never configured.
16
+ */
17
+ export declare function useSsoSignIn(config: AuthConfig): UseSsoSignInResult;
18
+ //# sourceMappingURL=use-sso-sign-in.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-sso-sign-in.d.ts","sourceRoot":"","sources":["../../../../sdk/sdk-react-ui/src/auth/use-sso-sign-in.ts"],"names":[],"mappings":"AAEA,OAAO,EAAoD,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAE1G,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C,MAAM,WAAW,kBAAkB;IACjC,iGAAiG;IACjG,eAAe,EAAE,iBAAiB,EAAE,CAAC;IACrC,aAAa,EAAE,OAAO,CAAC;IACvB,uEAAuE;IACvE,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,mFAAmF;IACnF,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,MAAM,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACjD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,kBAAkB,CAwDnE"}
@@ -1,3 +1,4 @@
1
1
  import { IkonUiComponentResolver } from '../ikon-ui-registry';
2
2
  export declare function createBaseDivResolver(): IkonUiComponentResolver;
3
3
  export declare function createBaseResolvers(): IkonUiComponentResolver[];
4
+ //# sourceMappingURL=base-div.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-div.d.ts","sourceRoot":"","sources":["../../../../sdk/sdk-react-ui/src/base/base-div.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAmbnE,wBAAgB,qBAAqB,IAAI,uBAAuB,CAmD/D;AAsDD,wBAAgB,mBAAmB,IAAI,uBAAuB,EAAE,CAO/D"}
@@ -4,3 +4,4 @@ export declare const IKON_UI_BASE_MODULE = "base";
4
4
  export declare const loadBaseModule: IkonUiModuleLoader;
5
5
  export declare function registerBaseModule(registry: IkonUiRegistry): void;
6
6
  export { createBaseResolvers };
7
+ //# sourceMappingURL=base-module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-module.d.ts","sourceRoot":"","sources":["../../../../sdk/sdk-react-ui/src/base/base-module.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC9E,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEjD,eAAO,MAAM,mBAAmB,SAAS,CAAC;AAE1C,eAAO,MAAM,cAAc,EAAE,kBAAsD,CAAC;AAEpF,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI,CAEjE;AAED,OAAO,EAAE,mBAAmB,EAAE,CAAC"}
@@ -0,0 +1,35 @@
1
+ import { ConsentAnswers, ConsentRecord, IkonClient } from '@ikonai/sdk';
2
+ export interface UseConsentOptions {
3
+ /** The connected client the answers are read through. Nothing is read while it is null. */
4
+ client: IkonClient | null;
5
+ /** The purposes this screen asks about. */
6
+ purposes: readonly string[];
7
+ }
8
+ export interface UseConsentResult {
9
+ /** Every answer the signed-in user has given, keyed by purpose. */
10
+ answers: ConsentAnswers;
11
+ /** True while the answers are being read. */
12
+ isLoading: boolean;
13
+ /** True while an answer is being recorded. */
14
+ isSubmitting: boolean;
15
+ /** The last failure, in the app's own words, or null. */
16
+ error: string | null;
17
+ /** The answer for one purpose; not-asked when there is none. Never granted by default. */
18
+ consentFor(purpose: string): ConsentRecord;
19
+ /** Whether one purpose is granted today. False while the answers are still loading. */
20
+ isGranted(purpose: string): boolean;
21
+ grant(purpose: string): Promise<void>;
22
+ revoke(purpose: string): Promise<void>;
23
+ reload(): Promise<void>;
24
+ }
25
+ /**
26
+ * The signed-in user's consent for the purposes this screen asks about: what they have answered, and
27
+ * the two calls that record an answer and take it back.
28
+ *
29
+ * Nothing here is granted until it has been read and the answer is a yes — while the answers are
30
+ * loading, while the client is offline, and for a visitor the app cannot name, every purpose reads
31
+ * as not granted. Gate the feature on {@link UseConsentResult.isGranted}, and say that the feature
32
+ * is off rather than letting it look as though it is running.
33
+ */
34
+ export declare function useConsent({ client, purposes }: UseConsentOptions): UseConsentResult;
35
+ //# sourceMappingURL=use-consent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-consent.d.ts","sourceRoot":"","sources":["../../../../sdk/sdk-react-ui/src/consent/use-consent.ts"],"names":[],"mappings":"AACA,OAAO,EAA0E,KAAK,cAAc,EAAE,KAAK,aAAa,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAE/J,MAAM,WAAW,iBAAiB;IAChC,2FAA2F;IAC3F,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;IAC1B,2CAA2C;IAC3C,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,gBAAgB;IAC/B,mEAAmE;IACnE,OAAO,EAAE,cAAc,CAAC;IACxB,6CAA6C;IAC7C,SAAS,EAAE,OAAO,CAAC;IACnB,8CAA8C;IAC9C,YAAY,EAAE,OAAO,CAAC;IACtB,yDAAyD;IACzD,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,0FAA0F;IAC1F,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,CAAC;IAC3C,uFAAuF;IACvF,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;IACpC,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACzB;AAUD;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,iBAAiB,GAAG,gBAAgB,CA2FpF"}
@@ -21,4 +21,5 @@ export interface DebugOverlayProps {
21
21
  /**
22
22
  * The overlay component. Returns null unless `?ikon-debug-overlay=true` is set or `forceVisible`.
23
23
  */
24
- export declare function DebugOverlay({ state, forceVisible }: DebugOverlayProps): import("react").JSX.Element | null;
24
+ export declare function DebugOverlay({ state, forceVisible }: DebugOverlayProps): import('react').JSX.Element | null;
25
+ //# sourceMappingURL=debug-overlay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debug-overlay.d.ts","sourceRoot":"","sources":["../../../../sdk/sdk-react-ui/src/debug/debug-overlay.tsx"],"names":[],"mappings":"AAGA;;;;;;;;;;;GAWG;AAEH,eAAO,MAAM,qBAAqB,SAM9B,CAAC;AAuGL,MAAM,WAAW,iBAAiB;IAChC;sFACkF;IAClF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iGAAiG;IACjG,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,EAAE,KAAU,EAAE,YAAoB,EAAE,EAAE,iBAAiB,sCAkDnF"}
@@ -0,0 +1,511 @@
1
+ import { FeedbackRequestError as e, IKON_CAPTURE_EXCLUDE_ATTRIBUTE as t, collectFeedbackContext as n, randomUuid as r, submitFeedbackReport as i } from "@ikonai/sdk";
2
+ import { useEffect as a, useId as o, useMemo as s, useRef as c, useState as l } from "react";
3
+ import { jsx as u, jsxs as d } from "react/jsx-runtime";
4
+ //#region src/app/feedback/feedback-form.tsx
5
+ var f = [
6
+ {
7
+ kind: "bug",
8
+ label: "Something's wrong"
9
+ },
10
+ {
11
+ kind: "idea",
12
+ label: "Idea"
13
+ },
14
+ {
15
+ kind: "confusing",
16
+ label: "Confusing"
17
+ },
18
+ {
19
+ kind: "praise",
20
+ label: "Love this"
21
+ }
22
+ ], p = 10, m = 26214400, h = 52428800, g = 10001, _ = 1e4;
23
+ function v({ access: e, screenshot: g, appSession: v, clientSession: y, onClose: x, onDirtyChange: C }) {
24
+ let w = o(), T = o(), [E, D] = l("bug"), [O, k] = l(""), [A, j] = l([]), [M, N] = l(null), [P, F] = l(g ? { status: "pending" } : { status: "none" }), [I, L] = l({ status: "idle" }), [R, z] = l(!1), [B] = l(() => r()), V = c(null), H = c(null);
25
+ a(() => {
26
+ H.current?.focus();
27
+ }, []), a(() => {
28
+ if (!g) return;
29
+ let e = !1, t = null, n = setTimeout(() => {
30
+ e = !0, F({ status: "failed" });
31
+ }, _);
32
+ return g.then((r) => {
33
+ e || (clearTimeout(n), t = URL.createObjectURL(r.png), F({
34
+ status: "ready",
35
+ image: r,
36
+ url: t
37
+ }));
38
+ }, () => {
39
+ e || (clearTimeout(n), F({ status: "failed" }));
40
+ }), () => {
41
+ e = !0, clearTimeout(n), t && URL.revokeObjectURL(t);
42
+ };
43
+ }, [g]);
44
+ let U = P.status === "ready" ? P.image.png : null, W = O.trim().length > 0 || A.length > 0;
45
+ a(() => {
46
+ C?.(W);
47
+ }, [W, C]);
48
+ let G = (e) => {
49
+ if (e.length === 0) return;
50
+ let t = [...A], n = [], r = t.reduce((e, t) => e + t.size, 0) + (U?.size ?? 0);
51
+ for (let i of e) t.length >= p ? n.push(`${i.name} (at most ${p} files)`) : i.size > m ? n.push(`${i.name} (over 25 MB)`) : r + i.size > h ? n.push(`${i.name} (the report would pass 50 MB)`) : (t.push(i), r += i.size);
52
+ j(t), N(n.length > 0 ? `Not attached: ${n.join(", ")}` : null);
53
+ }, K = (e) => {
54
+ j((t) => t.filter((t, n) => n !== e)), N(null);
55
+ }, q = () => {
56
+ P.status === "ready" && URL.revokeObjectURL(P.url), F({ status: "none" });
57
+ }, J = I.status !== "sending" && P.status !== "pending" && (O.trim().length > 0 || A.length > 0 || U !== null), Y = async () => {
58
+ if (J) {
59
+ if (!e) {
60
+ L({
61
+ status: "failed",
62
+ message: "Feedback cannot be sent from this page because it is not signed in to the app."
63
+ });
64
+ return;
65
+ }
66
+ L({ status: "sending" });
67
+ try {
68
+ await i(e, {
69
+ kind: E,
70
+ text: O.trim(),
71
+ context: n(),
72
+ appSession: v,
73
+ clientSession: y
74
+ }, {
75
+ files: A,
76
+ screenshot: U
77
+ }, { draftId: B }), L({ status: "sent" });
78
+ } catch (e) {
79
+ L({
80
+ status: "failed",
81
+ message: ee(e)
82
+ });
83
+ }
84
+ }
85
+ }, X = c(null), Z = (e) => {
86
+ if (e.key === "Escape" && I.status !== "sending") {
87
+ e.stopPropagation(), x();
88
+ return;
89
+ }
90
+ e.key === "Tab" && b(e, X.current);
91
+ }, te = (e) => {
92
+ let t = e.key === "ArrowRight" || e.key === "ArrowDown" ? 1 : e.key === "ArrowLeft" || e.key === "ArrowUp" ? -1 : 0;
93
+ if (t === 0) return;
94
+ e.preventDefault();
95
+ let n = f[(f.findIndex((e) => e.kind === E) + t + f.length) % f.length];
96
+ D(n.kind), e.currentTarget.querySelector(`[data-kind="${n.kind}"]`)?.focus();
97
+ }, ne = (e) => {
98
+ e.preventDefault(), z(!1), G(Array.from(e.dataTransfer?.files ?? []));
99
+ }, Q = { [t]: "" }, $ = s(() => S(R), [R]);
100
+ return I.status === "sent" ? /* @__PURE__ */ u("div", {
101
+ ...Q,
102
+ style: $.scrim,
103
+ onKeyDown: Z,
104
+ children: /* @__PURE__ */ d("div", {
105
+ ref: X,
106
+ role: "dialog",
107
+ "aria-modal": "true",
108
+ "aria-labelledby": w,
109
+ style: $.panel,
110
+ children: [
111
+ /* @__PURE__ */ u("h2", {
112
+ id: w,
113
+ style: $.title,
114
+ children: "Thanks, your report was sent"
115
+ }),
116
+ /* @__PURE__ */ u("p", {
117
+ style: $.note,
118
+ children: "The people building this app will read it."
119
+ }),
120
+ /* @__PURE__ */ u("div", {
121
+ style: $.actions,
122
+ children: /* @__PURE__ */ u("button", {
123
+ type: "button",
124
+ style: $.primary,
125
+ onClick: x,
126
+ autoFocus: !0,
127
+ children: "Close"
128
+ })
129
+ })
130
+ ]
131
+ })
132
+ }) : /* @__PURE__ */ u("div", {
133
+ ...Q,
134
+ style: $.scrim,
135
+ onKeyDown: Z,
136
+ children: /* @__PURE__ */ d("div", {
137
+ ref: X,
138
+ role: "dialog",
139
+ "aria-modal": "true",
140
+ "aria-labelledby": w,
141
+ style: $.panel,
142
+ onDragOver: (e) => {
143
+ e.preventDefault(), z(!0);
144
+ },
145
+ onDragLeave: () => z(!1),
146
+ onDrop: ne,
147
+ children: [
148
+ /* @__PURE__ */ u("h2", {
149
+ id: w,
150
+ style: $.title,
151
+ children: "Send feedback"
152
+ }),
153
+ /* @__PURE__ */ u("div", {
154
+ role: "radiogroup",
155
+ "aria-label": "Kind of feedback",
156
+ style: $.kinds,
157
+ onKeyDown: te,
158
+ children: f.map((e) => /* @__PURE__ */ u("button", {
159
+ type: "button",
160
+ role: "radio",
161
+ "data-kind": e.kind,
162
+ "aria-checked": E === e.kind,
163
+ tabIndex: E === e.kind ? 0 : -1,
164
+ style: E === e.kind ? $.kindSelected : $.kind,
165
+ onClick: () => D(e.kind),
166
+ children: e.label
167
+ }, e.kind))
168
+ }),
169
+ /* @__PURE__ */ u("label", {
170
+ htmlFor: T,
171
+ style: $.label,
172
+ children: "What would you like to tell us?"
173
+ }),
174
+ /* @__PURE__ */ u("textarea", {
175
+ ref: H,
176
+ id: T,
177
+ value: O,
178
+ onChange: (e) => k(e.target.value),
179
+ rows: 5,
180
+ style: $.textarea
181
+ }),
182
+ /* @__PURE__ */ d("div", {
183
+ style: $.attachRow,
184
+ children: [
185
+ /* @__PURE__ */ u("button", {
186
+ type: "button",
187
+ style: $.secondary,
188
+ onClick: () => V.current?.click(),
189
+ children: "Attach files"
190
+ }),
191
+ /* @__PURE__ */ u("span", {
192
+ style: $.note,
193
+ children: "or drop them here"
194
+ }),
195
+ /* @__PURE__ */ u("input", {
196
+ ref: V,
197
+ type: "file",
198
+ multiple: !0,
199
+ hidden: !0,
200
+ "aria-label": "Attach files",
201
+ onChange: (e) => {
202
+ G(Array.from(e.target.files ?? [])), e.target.value = "";
203
+ }
204
+ })
205
+ ]
206
+ }),
207
+ A.length > 0 && /* @__PURE__ */ u("ul", {
208
+ "aria-label": "Attached files",
209
+ style: $.fileList,
210
+ children: A.map((e, t) => /* @__PURE__ */ d("li", {
211
+ style: $.fileItem,
212
+ children: [/* @__PURE__ */ u("span", {
213
+ style: $.fileName,
214
+ children: e.name
215
+ }), /* @__PURE__ */ u("button", {
216
+ type: "button",
217
+ style: $.link,
218
+ "aria-label": `Remove ${e.name}`,
219
+ onClick: () => K(t),
220
+ children: "Remove"
221
+ })]
222
+ }, `${e.name}-${t}`))
223
+ }),
224
+ M && /* @__PURE__ */ u("p", {
225
+ role: "status",
226
+ style: $.warning,
227
+ children: M
228
+ }),
229
+ /* @__PURE__ */ u("p", {
230
+ "aria-live": "polite",
231
+ style: P.status === "pending" ? $.note : $.hidden,
232
+ children: P.status === "pending" ? "Taking a screenshot…" : ""
233
+ }),
234
+ P.status === "failed" && /* @__PURE__ */ u("p", {
235
+ style: $.note,
236
+ children: "The screenshot could not be taken."
237
+ }),
238
+ P.status === "ready" && /* @__PURE__ */ d("figure", {
239
+ style: $.screenshot,
240
+ children: [/* @__PURE__ */ u("img", {
241
+ src: P.url,
242
+ alt: "Screenshot of the app, sent with the report",
243
+ style: $.thumbnail
244
+ }), /* @__PURE__ */ d("figcaption", {
245
+ style: $.screenshotCaption,
246
+ children: [P.image.lostContent && /* @__PURE__ */ u("span", {
247
+ style: $.note,
248
+ children: "Some content could not be captured and shows as grey."
249
+ }), /* @__PURE__ */ u("button", {
250
+ type: "button",
251
+ style: $.link,
252
+ onClick: q,
253
+ children: "Remove screenshot"
254
+ })]
255
+ })]
256
+ }),
257
+ /* @__PURE__ */ u("p", {
258
+ style: $.note,
259
+ children: "Read by the app's team and AI. Includes this screen, the page address and your device details."
260
+ }),
261
+ I.status === "failed" && /* @__PURE__ */ u("p", {
262
+ role: "alert",
263
+ style: $.error,
264
+ children: I.message
265
+ }),
266
+ /* @__PURE__ */ d("div", {
267
+ style: $.actions,
268
+ children: [/* @__PURE__ */ u("button", {
269
+ type: "button",
270
+ style: $.secondary,
271
+ onClick: x,
272
+ disabled: I.status === "sending",
273
+ children: "Cancel"
274
+ }), /* @__PURE__ */ u("button", {
275
+ type: "button",
276
+ style: J ? $.primary : $.primaryDisabled,
277
+ onClick: () => void Y(),
278
+ disabled: !J,
279
+ children: I.status === "sending" ? "Sending…" : I.status === "failed" ? "Try again" : "Send"
280
+ })]
281
+ })
282
+ ]
283
+ })
284
+ });
285
+ }
286
+ var y = "button:not([disabled]), textarea:not([disabled]), input:not([disabled]):not([type=\"hidden\"]):not([hidden]), [href], [tabindex]:not([tabindex=\"-1\"])";
287
+ function b(e, t) {
288
+ if (!t) return;
289
+ let n = Array.from(t.querySelectorAll(y));
290
+ if (n.length === 0) {
291
+ e.preventDefault();
292
+ return;
293
+ }
294
+ let r = n[0], i = n[n.length - 1], a = t.ownerDocument.activeElement;
295
+ e.shiftKey && (a === r || !t.contains(a)) ? (e.preventDefault(), i.focus()) : !e.shiftKey && (a === i || !t.contains(a)) && (e.preventDefault(), r.focus());
296
+ }
297
+ function ee(t) {
298
+ return t instanceof e ? t.status === 0 ? "Your report could not be sent: the feedback service is unreachable. Check the connection and try again." : t.status === 401 || t.status === 403 ? `Your report could not be sent: this account may not send feedback for this app (${t.message}).` : t.status === 413 ? "Your report could not be sent: the attachments are too large. Remove some and try again." : t.status === 429 ? "Your report could not be sent: too many reports in a short time. Try again later." : `Your report could not be sent: ${t.message}` : `Your report could not be sent: ${t instanceof Error ? t.message : String(t)}`;
299
+ }
300
+ var x = {
301
+ card: "var(--ikon-bg-card, #ffffff)",
302
+ subtle: "var(--ikon-bg-subtle, #f4f4f5)",
303
+ solid: "var(--ikon-bg-solid, #161618)",
304
+ onSolid: "var(--ikon-text-on-solid, #ffffff)",
305
+ text: "var(--ikon-text-primary, #161618)",
306
+ muted: "var(--ikon-text-tertiary, #6e6e74)",
307
+ border: "var(--ikon-border-primary, #d4d4d7)",
308
+ borderSoft: "var(--ikon-border-secondary, #e8e8ea)",
309
+ error: "var(--ikon-error-text, #b32218)",
310
+ errorSurface: "var(--ikon-error-surface, #fef2f1)",
311
+ warning: "var(--ikon-status-warning, #db6803)",
312
+ scrim: "var(--ikon-overlay-scrim, rgba(22, 22, 24, 0.5))",
313
+ focus: "var(--ikon-brand-500, #f5277f)"
314
+ };
315
+ function S(e) {
316
+ let t = {
317
+ minHeight: 40,
318
+ padding: "0 14px",
319
+ borderRadius: "var(--ikon-radius-md, 4px)",
320
+ font: "inherit",
321
+ fontSize: 14,
322
+ cursor: "pointer"
323
+ }, n = {
324
+ ...t,
325
+ minHeight: 36,
326
+ borderRadius: "var(--ikon-radius-full, 9999px)",
327
+ border: `1px solid ${x.border}`,
328
+ background: x.card,
329
+ color: x.text
330
+ };
331
+ return {
332
+ scrim: {
333
+ position: "fixed",
334
+ top: 0,
335
+ right: 0,
336
+ bottom: 0,
337
+ left: 0,
338
+ zIndex: g,
339
+ display: "flex",
340
+ alignItems: "center",
341
+ justifyContent: "center",
342
+ padding: 16,
343
+ background: x.scrim,
344
+ boxSizing: "border-box"
345
+ },
346
+ panel: {
347
+ boxSizing: "border-box",
348
+ width: "100%",
349
+ maxWidth: 460,
350
+ maxHeight: "100%",
351
+ overflowY: "auto",
352
+ padding: 20,
353
+ display: "flex",
354
+ flexDirection: "column",
355
+ gap: 12,
356
+ background: x.card,
357
+ color: x.text,
358
+ border: `1px ${e ? "dashed" : "solid"} ${e ? x.focus : x.borderSoft}`,
359
+ borderRadius: "var(--ikon-radius-xl, 8px)",
360
+ boxShadow: "0 12px 40px rgba(0, 0, 0, 0.25)",
361
+ font: "15px/1.45 var(--ikon-font-body, system-ui, -apple-system, \"Segoe UI\", sans-serif)"
362
+ },
363
+ title: {
364
+ margin: 0,
365
+ fontSize: 18,
366
+ fontWeight: 600
367
+ },
368
+ kinds: {
369
+ display: "flex",
370
+ flexWrap: "wrap",
371
+ gap: 8
372
+ },
373
+ kind: n,
374
+ kindSelected: {
375
+ ...n,
376
+ background: x.solid,
377
+ color: x.onSolid,
378
+ borderColor: x.solid
379
+ },
380
+ label: {
381
+ fontSize: 14,
382
+ fontWeight: 500
383
+ },
384
+ textarea: {
385
+ boxSizing: "border-box",
386
+ width: "100%",
387
+ padding: 10,
388
+ resize: "vertical",
389
+ font: "inherit",
390
+ color: x.text,
391
+ background: x.card,
392
+ border: `1px solid ${x.border}`,
393
+ borderRadius: "var(--ikon-radius-md, 4px)"
394
+ },
395
+ attachRow: {
396
+ display: "flex",
397
+ alignItems: "center",
398
+ gap: 10
399
+ },
400
+ fileList: {
401
+ margin: 0,
402
+ padding: 0,
403
+ listStyle: "none",
404
+ display: "flex",
405
+ flexDirection: "column",
406
+ gap: 4
407
+ },
408
+ fileItem: {
409
+ display: "flex",
410
+ alignItems: "center",
411
+ justifyContent: "space-between",
412
+ gap: 8,
413
+ padding: "4px 8px",
414
+ background: x.subtle,
415
+ borderRadius: "var(--ikon-radius-md, 4px)"
416
+ },
417
+ fileName: {
418
+ overflow: "hidden",
419
+ textOverflow: "ellipsis",
420
+ whiteSpace: "nowrap",
421
+ fontSize: 14
422
+ },
423
+ screenshot: {
424
+ margin: 0,
425
+ display: "flex",
426
+ gap: 10,
427
+ alignItems: "flex-start"
428
+ },
429
+ thumbnail: {
430
+ width: 120,
431
+ maxHeight: 120,
432
+ objectFit: "contain",
433
+ objectPosition: "top left",
434
+ border: `1px solid ${x.borderSoft}`,
435
+ borderRadius: "var(--ikon-radius-md, 4px)",
436
+ background: x.subtle
437
+ },
438
+ screenshotCaption: {
439
+ display: "flex",
440
+ flexDirection: "column",
441
+ alignItems: "flex-start",
442
+ gap: 4
443
+ },
444
+ note: {
445
+ margin: 0,
446
+ fontSize: 13,
447
+ color: x.muted
448
+ },
449
+ hidden: {
450
+ position: "absolute",
451
+ width: 1,
452
+ height: 1,
453
+ margin: -1,
454
+ padding: 0,
455
+ overflow: "hidden",
456
+ clip: "rect(0 0 0 0)",
457
+ border: 0
458
+ },
459
+ warning: {
460
+ margin: 0,
461
+ fontSize: 13,
462
+ color: x.warning
463
+ },
464
+ error: {
465
+ margin: 0,
466
+ padding: "8px 10px",
467
+ fontSize: 14,
468
+ color: x.error,
469
+ background: x.errorSurface,
470
+ borderRadius: "var(--ikon-radius-md, 4px)"
471
+ },
472
+ actions: {
473
+ display: "flex",
474
+ justifyContent: "flex-end",
475
+ gap: 8,
476
+ marginTop: 4
477
+ },
478
+ primary: {
479
+ ...t,
480
+ border: "1px solid transparent",
481
+ background: x.solid,
482
+ color: x.onSolid
483
+ },
484
+ primaryDisabled: {
485
+ ...t,
486
+ border: "1px solid transparent",
487
+ background: x.solid,
488
+ color: x.onSolid,
489
+ opacity: .5,
490
+ cursor: "default"
491
+ },
492
+ secondary: {
493
+ ...t,
494
+ border: `1px solid ${x.border}`,
495
+ background: x.card,
496
+ color: x.text
497
+ },
498
+ link: {
499
+ padding: 0,
500
+ border: "none",
501
+ background: "none",
502
+ color: x.text,
503
+ font: "inherit",
504
+ fontSize: 13,
505
+ textDecoration: "underline",
506
+ cursor: "pointer"
507
+ }
508
+ };
509
+ }
510
+ //#endregion
511
+ export { g as FEEDBACK_DIALOG_Z_INDEX, f as FEEDBACK_KIND_OPTIONS, v as FeedbackForm, _ as SCREENSHOT_WAIT_MS };