@ikonai/sdk-react-ui 1.7.0 → 1.10.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.
- package/app/connection-state-renderer.d.ts +4 -4
- package/app/connection-state-renderer.spec.d.ts +1 -0
- package/app/ikon-app.d.ts +3 -3
- package/app/ikon-app.spec.d.ts +1 -0
- package/app/use-ikon-app.d.ts +6 -8
- package/app/use-ikon-debug.d.ts +1 -1
- package/auth/auth-service.d.ts +9 -0
- package/auth/index.d.ts +1 -1
- package/auth/oauth-continuation.d.ts +15 -1
- package/index.d.ts +1 -1
- package/index.js +902 -832
- package/package.json +1 -1
- package/parallax-view.d.ts +2 -2
- package/renderer/index.d.ts +1 -1
- package/renderer/types.d.ts +12 -1
- package/renderer/ui-renderer.d.ts +2 -2
- package/surface.d.ts +2 -2
- package/theme/ikon-app.css +261 -250
- package/theme/ikon-auth.css +290 -271
- package/theme/ikon-surface.css +107 -94
- package/theme/ikon-tokens.css +97 -95
package/package.json
CHANGED
package/parallax-view.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IkonClient } from '../sdk/sdk/src/index.ts';
|
|
2
2
|
import { IkonUiStoreEntry } from './surface';
|
|
3
|
-
import { UiComponentLibrary } from './renderer';
|
|
3
|
+
import { DispatchActionOptions, UiComponentLibrary } from './renderer';
|
|
4
4
|
/**
|
|
5
5
|
* Mounts a named Parallax sub-tree into a host-controlled container.
|
|
6
6
|
*
|
|
@@ -22,6 +22,6 @@ export interface ParallaxViewProps {
|
|
|
22
22
|
/** Connected Ikon client; required for media-bearing UIs (video, audio). */
|
|
23
23
|
client?: IkonClient | null;
|
|
24
24
|
/** Optional handler for ParallaxView-internal action dispatches. */
|
|
25
|
-
onAction?: (actionId: string, payload?: string) => void;
|
|
25
|
+
onAction?: (actionId: string, payload?: string, options?: DispatchActionOptions) => void;
|
|
26
26
|
}
|
|
27
27
|
export declare function ParallaxView({ mount, stores, registry, client, onAction }: ParallaxViewProps): import("react").JSX.Element;
|
package/renderer/index.d.ts
CHANGED
|
@@ -3,4 +3,4 @@ export { UiComponentRegistry, createComponentLibrary, } from './component-librar
|
|
|
3
3
|
export { useUiStore } from './use-ui-store';
|
|
4
4
|
export { useUiNode } from './use-ui-node';
|
|
5
5
|
export { useRootView } from './use-root-view';
|
|
6
|
-
export type { UiComponentRenderer, UiComponentLibrary, UiNode, UiRenderContext, UiComponentRendererProps, ParsedUiUpdate, UiSnapshot, UiFullSnapshot, UiDiffSnapshot, UiNodeDiff, TextDelta, UiNodeProps, UiUpdateType, UiStoreSnapshot, } from './types';
|
|
6
|
+
export type { DispatchActionOptions, UiComponentRenderer, UiComponentLibrary, UiNode, UiRenderContext, UiComponentRendererProps, ParsedUiUpdate, UiSnapshot, UiFullSnapshot, UiDiffSnapshot, UiNodeDiff, TextDelta, UiNodeProps, UiUpdateType, UiStoreSnapshot, } from './types';
|
package/renderer/types.d.ts
CHANGED
|
@@ -3,6 +3,17 @@ import { HandlerCache, UiNode, UiStreamStore } from '../../sdk/sdk-ui/src/index.
|
|
|
3
3
|
import { IkonClient, IkonVideoPlayback } from '../../sdk/sdk/src/index.ts';
|
|
4
4
|
import { ComponentType, ReactNode } from 'react';
|
|
5
5
|
export { type UiUpdateType, type UiNodeProps, type UiNode, type UiNodeDiff, type UiSnapshot, type UiFullSnapshot, type UiDiffSnapshot, type UiSnapshotMetadata, type TextDelta, type ParsedUiUpdate, type UiStoreSnapshot, } from '../../sdk/sdk-ui/src/index.ts';
|
|
6
|
+
/** How a dispatched action should be treated when the server cannot run it. */
|
|
7
|
+
export interface DispatchActionOptions {
|
|
8
|
+
/**
|
|
9
|
+
* The dispatch is the component's own bookkeeping rather than something a person did, so a
|
|
10
|
+
* server refusal is not worth a person's attention. A controlled overlay reports itself closed
|
|
11
|
+
* as it unmounts; when the whole subtree is being removed the server has already retired that
|
|
12
|
+
* action, and the refusal that comes back describes a state it reached on its own. Failures of
|
|
13
|
+
* a best-effort dispatch are logged at debug instead of error.
|
|
14
|
+
*/
|
|
15
|
+
bestEffort?: boolean;
|
|
16
|
+
}
|
|
6
17
|
/**
|
|
7
18
|
* Context for rendering UI nodes.
|
|
8
19
|
* Provides access to payloads, action dispatch, and rendering utilities.
|
|
@@ -15,7 +26,7 @@ export interface UiRenderContext {
|
|
|
15
26
|
/** Render a view by ID */
|
|
16
27
|
renderView: (viewId: string) => ReactNode;
|
|
17
28
|
/** Dispatch an action with optional payload */
|
|
18
|
-
dispatchAction: (actionId: string, payload?: unknown) => void;
|
|
29
|
+
dispatchAction: (actionId: string, payload?: unknown, options?: DispatchActionOptions) => void;
|
|
19
30
|
/** The Ikon client instance */
|
|
20
31
|
client?: IkonClient | null;
|
|
21
32
|
/** Video playback API */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { IkonClient, IkonVideoPlayback } from '../../sdk/sdk/src/index.ts';
|
|
2
2
|
import { UiStreamStore } from '../../sdk/sdk-ui/src/index.ts';
|
|
3
3
|
import { ReactNode } from 'react';
|
|
4
|
-
import { UiComponentLibrary, UiNode, UiRenderContext } from './types';
|
|
4
|
+
import { DispatchActionOptions, UiComponentLibrary, UiNode, UiRenderContext } from './types';
|
|
5
5
|
/**
|
|
6
6
|
* Render children nodes by their IDs.
|
|
7
7
|
* Used by component renderers to render their children.
|
|
@@ -14,7 +14,7 @@ export interface UiRendererProps {
|
|
|
14
14
|
readonly library: UiComponentLibrary;
|
|
15
15
|
readonly viewId?: string;
|
|
16
16
|
readonly emptyFallback?: ReactNode;
|
|
17
|
-
readonly onAction?: (actionId: string, payloadJson: string) => void;
|
|
17
|
+
readonly onAction?: (actionId: string, payloadJson: string, options?: DispatchActionOptions) => void;
|
|
18
18
|
readonly client?: IkonClient | null;
|
|
19
19
|
readonly video?: IkonVideoPlayback | null;
|
|
20
20
|
}
|
package/surface.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { UIStreamCategories } from '../shared/protocol/src/index.ts';
|
|
2
2
|
import { UiStreamStore } from '../sdk/sdk-ui/src/index.ts';
|
|
3
|
-
import { UiComponentLibrary } from './renderer';
|
|
3
|
+
import { DispatchActionOptions, UiComponentLibrary } from './renderer';
|
|
4
4
|
import { IkonClient } from '../sdk/sdk/src/index.ts';
|
|
5
5
|
export declare const IKON_UI_STREAM_CATEGORY: "ikon-ui";
|
|
6
6
|
export type IkonUiCategory = UIStreamCategories | typeof IKON_UI_STREAM_CATEGORY | (string & {});
|
|
@@ -13,7 +13,7 @@ export interface IkonUiSurfaceProps {
|
|
|
13
13
|
stores: ReadonlyMap<string, IkonUiStoreEntry>;
|
|
14
14
|
registry: UiComponentLibrary;
|
|
15
15
|
category?: IkonUiCategory;
|
|
16
|
-
onAction?: (actionId: string, payload?: string) => void;
|
|
16
|
+
onAction?: (actionId: string, payload?: string, options?: DispatchActionOptions) => void;
|
|
17
17
|
client?: IkonClient | null;
|
|
18
18
|
}
|
|
19
19
|
export declare const IkonUiSurface: import('react').MemoExoticComponent<({ stores, registry, category, onAction, client }: IkonUiSurfaceProps) => import("react").JSX.Element | null>;
|
package/theme/ikon-app.css
CHANGED
|
@@ -1,284 +1,295 @@
|
|
|
1
1
|
/* Ikon app-shell styles: the connection overlays, the toast strip and the hero layout.
|
|
2
2
|
|
|
3
|
-
Override any of
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
3
|
+
Override any of them from your own src/app.css, which loads after this sheet: at equal
|
|
4
|
+
specificity yours wins, with no `!important`. A few rules here are more specific than one class
|
|
5
|
+
— `.ikon-hero h1`, `.ikon-reconnecting-chip span`, the `:hover` and `:focus` states — so match
|
|
6
|
+
that shape to override those. */
|
|
7
|
+
.ikon-app {
|
|
8
|
+
display: flex;
|
|
9
|
+
align-items: center;
|
|
10
|
+
justify-content: center;
|
|
11
|
+
padding: 32px max(20px, env(safe-area-inset-left)) calc(32px + env(safe-area-inset-bottom));
|
|
12
|
+
box-sizing: border-box;
|
|
13
|
+
}
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
15
|
+
.ikon-hero {
|
|
16
|
+
position: relative;
|
|
17
|
+
z-index: 1;
|
|
18
|
+
display: flex;
|
|
19
|
+
flex-direction: column;
|
|
20
|
+
align-items: center;
|
|
21
|
+
gap: 16px;
|
|
22
|
+
max-width: 460px;
|
|
23
|
+
text-align: center;
|
|
24
|
+
}
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
26
|
+
.ikon-hero h1 {
|
|
27
|
+
margin: 0;
|
|
28
|
+
font-family: var(--ikon-font-display);
|
|
29
|
+
font-size: clamp(24px, 7vw, 40px);
|
|
30
|
+
font-weight: 600;
|
|
31
|
+
line-height: 1.15;
|
|
32
|
+
letter-spacing: -0.02em;
|
|
33
|
+
color: var(--ikon-text-primary);
|
|
34
|
+
text-wrap: balance;
|
|
35
|
+
}
|
|
35
36
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
37
|
+
.ikon-info {
|
|
38
|
+
margin: 0;
|
|
39
|
+
font-size: 15px;
|
|
40
|
+
line-height: 1.6;
|
|
41
|
+
color: var(--ikon-text-secondary);
|
|
42
|
+
text-wrap: pretty;
|
|
43
|
+
}
|
|
43
44
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
45
|
+
.ikon-error {
|
|
46
|
+
margin: 0;
|
|
47
|
+
font-family: var(--ikon-font-mono);
|
|
48
|
+
font-size: 13px;
|
|
49
|
+
line-height: 1.5;
|
|
50
|
+
color: var(--ikon-status-error);
|
|
51
|
+
word-break: break-word;
|
|
52
|
+
}
|
|
52
53
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
54
|
+
.ikon-connecting-overlay {
|
|
55
|
+
position: fixed;
|
|
56
|
+
top: 0;
|
|
57
|
+
left: 0;
|
|
58
|
+
right: 0;
|
|
59
|
+
display: flex;
|
|
60
|
+
justify-content: center;
|
|
61
|
+
padding-top: max(16px, env(safe-area-inset-top));
|
|
62
|
+
z-index: 9998;
|
|
63
|
+
pointer-events: none;
|
|
64
|
+
}
|
|
64
65
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
66
|
+
.ikon-connecting-chip {
|
|
67
|
+
display: flex;
|
|
68
|
+
align-items: center;
|
|
69
|
+
gap: 8px;
|
|
70
|
+
padding: 8px 14px;
|
|
71
|
+
background: var(--ikon-bg-card);
|
|
72
|
+
border: 1px solid var(--ikon-border-secondary);
|
|
73
|
+
border-radius: var(--ikon-radius-full);
|
|
74
|
+
color: var(--ikon-text-secondary);
|
|
75
|
+
font-family: var(--ikon-font-body);
|
|
76
|
+
font-size: 13px;
|
|
77
|
+
font-weight: 500;
|
|
78
|
+
pointer-events: auto;
|
|
79
|
+
animation: ikon-fade-in 0.3s ease-out;
|
|
80
|
+
}
|
|
80
81
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
82
|
+
.ikon-connecting-spinner {
|
|
83
|
+
width: 13px;
|
|
84
|
+
height: 13px;
|
|
85
|
+
border: 2px solid var(--ikon-border-primary);
|
|
86
|
+
border-top-color: var(--ikon-text-tertiary);
|
|
87
|
+
border-radius: var(--ikon-radius-full);
|
|
88
|
+
animation: ikon-spin 0.9s linear infinite;
|
|
89
|
+
}
|
|
89
90
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
91
|
+
.ikon-reconnecting-overlay,
|
|
92
|
+
.ikon-offline-overlay {
|
|
93
|
+
position: fixed;
|
|
94
|
+
/* The `inset` shorthand is Chromium 87; the longhands position this on older screens. */
|
|
95
|
+
top: 0;
|
|
96
|
+
right: 0;
|
|
97
|
+
bottom: 0;
|
|
98
|
+
left: 0;
|
|
99
|
+
inset: 0;
|
|
100
|
+
display: flex;
|
|
101
|
+
align-items: center;
|
|
102
|
+
justify-content: center;
|
|
103
|
+
padding: 24px;
|
|
104
|
+
z-index: 9999;
|
|
105
|
+
background: var(--ikon-overlay-scrim);
|
|
106
|
+
/* The prefixed form first: the minifier folds this pair into whichever is written last, and
|
|
107
|
+
Chromium has dropped `-webkit-backdrop-filter`, so standard-last is the one that blurs. */
|
|
108
|
+
-webkit-backdrop-filter: blur(8px);
|
|
109
|
+
backdrop-filter: blur(8px);
|
|
110
|
+
animation: ikon-fade-in 0.4s ease-out;
|
|
111
|
+
}
|
|
104
112
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
113
|
+
.ikon-reconnecting-chip,
|
|
114
|
+
.ikon-offline-chip {
|
|
115
|
+
box-sizing: border-box;
|
|
116
|
+
display: flex;
|
|
117
|
+
flex-direction: column;
|
|
118
|
+
align-items: center;
|
|
119
|
+
gap: 8px;
|
|
120
|
+
width: 100%;
|
|
121
|
+
max-width: 380px;
|
|
122
|
+
text-align: center;
|
|
123
|
+
color: var(--ikon-text-primary);
|
|
124
|
+
font-family: var(--ikon-font-body);
|
|
125
|
+
}
|
|
118
126
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
127
|
+
.ikon-reconnecting-spinner {
|
|
128
|
+
width: 28px;
|
|
129
|
+
height: 28px;
|
|
130
|
+
margin-bottom: 4px;
|
|
131
|
+
border: 2px solid var(--ikon-border-primary);
|
|
132
|
+
border-top-color: var(--ikon-text-tertiary);
|
|
133
|
+
border-radius: var(--ikon-radius-full);
|
|
134
|
+
animation: ikon-spin 0.9s linear infinite;
|
|
135
|
+
}
|
|
128
136
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
137
|
+
.ikon-reconnecting-chip span {
|
|
138
|
+
font-size: 15px;
|
|
139
|
+
font-weight: 500;
|
|
140
|
+
color: var(--ikon-text-secondary);
|
|
141
|
+
}
|
|
134
142
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
+
.ikon-offline-title {
|
|
144
|
+
font-family: var(--ikon-font-display);
|
|
145
|
+
font-size: clamp(20px, 5.5vw, 24px);
|
|
146
|
+
font-weight: 600;
|
|
147
|
+
line-height: 1.25;
|
|
148
|
+
letter-spacing: -0.015em;
|
|
149
|
+
text-wrap: balance;
|
|
150
|
+
}
|
|
143
151
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
152
|
+
.ikon-offline-message {
|
|
153
|
+
font-size: 14px;
|
|
154
|
+
line-height: 1.6;
|
|
155
|
+
color: var(--ikon-text-secondary);
|
|
156
|
+
text-wrap: pretty;
|
|
157
|
+
}
|
|
150
158
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
159
|
+
.ikon-offline-error {
|
|
160
|
+
margin-top: 6px;
|
|
161
|
+
font-family: var(--ikon-font-mono);
|
|
162
|
+
font-size: 12px;
|
|
163
|
+
line-height: 1.5;
|
|
164
|
+
color: var(--ikon-text-quaternary);
|
|
165
|
+
max-width: 100%;
|
|
166
|
+
word-break: break-word;
|
|
167
|
+
}
|
|
160
168
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
169
|
+
/* An installed PWA has no reload control the user can reach, so this button is the only way back
|
|
170
|
+
into the app — sized for a thumb rather than as a secondary affordance. */
|
|
171
|
+
.ikon-offline-action {
|
|
172
|
+
display: flex;
|
|
173
|
+
align-items: center;
|
|
174
|
+
justify-content: center;
|
|
175
|
+
min-width: 160px;
|
|
176
|
+
min-height: 44px;
|
|
177
|
+
margin-top: 12px;
|
|
178
|
+
padding: 0 20px;
|
|
179
|
+
background: var(--ikon-bg-solid);
|
|
180
|
+
border: 1px solid transparent;
|
|
181
|
+
border-radius: var(--ikon-radius-md);
|
|
182
|
+
font-family: inherit;
|
|
183
|
+
font-size: 15px;
|
|
184
|
+
font-weight: 500;
|
|
185
|
+
line-height: 1;
|
|
186
|
+
cursor: pointer;
|
|
187
|
+
transition: background-color 0.15s ease;
|
|
188
|
+
}
|
|
181
189
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
190
|
+
/* Crosswind's preflight resets `button { color: inherit }` unlayered, and an unlayered rule beats
|
|
191
|
+
a layered one whatever its specificity — so colouring the button itself loses the contrast and
|
|
192
|
+
paints the label in the chip's text colour on the solid fill. The span is not something the
|
|
193
|
+
reset targets, which keeps this a normal cascade an app can still override without !important. */
|
|
194
|
+
.ikon-offline-action-label {
|
|
195
|
+
color: var(--ikon-text-on-solid);
|
|
196
|
+
}
|
|
189
197
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
198
|
+
.ikon-offline-action:hover {
|
|
199
|
+
background: var(--ikon-bg-solid-hover);
|
|
200
|
+
}
|
|
193
201
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
202
|
+
.ikon-offline-action:focus {
|
|
203
|
+
outline: 2px solid var(--ikon-focus-ring);
|
|
204
|
+
outline-offset: 2px;
|
|
205
|
+
}
|
|
198
206
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
}
|
|
207
|
+
.ikon-offline-action:focus:not(:focus-visible) {
|
|
208
|
+
outline: none;
|
|
209
|
+
}
|
|
203
210
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
}
|
|
209
|
-
}
|
|
211
|
+
@keyframes ikon-fade-in {
|
|
212
|
+
from { opacity: 0; }
|
|
213
|
+
to { opacity: 1; }
|
|
214
|
+
}
|
|
210
215
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
right: 0;
|
|
216
|
-
display: flex;
|
|
217
|
-
flex-direction: column;
|
|
218
|
-
align-items: center;
|
|
219
|
-
gap: 8px;
|
|
220
|
-
padding-top: max(16px, env(safe-area-inset-top));
|
|
221
|
-
z-index: 9998;
|
|
222
|
-
pointer-events: none;
|
|
216
|
+
@media (prefers-reduced-motion: reduce) {
|
|
217
|
+
.ikon-connecting-spinner,
|
|
218
|
+
.ikon-reconnecting-spinner {
|
|
219
|
+
animation-duration: 2.4s;
|
|
223
220
|
}
|
|
221
|
+
}
|
|
224
222
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
pointer-events: auto;
|
|
239
|
-
cursor: pointer;
|
|
240
|
-
animation: ikon-fade-in 0.3s ease-out;
|
|
241
|
-
}
|
|
223
|
+
.ikon-toast-overlay {
|
|
224
|
+
position: fixed;
|
|
225
|
+
top: 0;
|
|
226
|
+
left: 0;
|
|
227
|
+
right: 0;
|
|
228
|
+
display: flex;
|
|
229
|
+
flex-direction: column;
|
|
230
|
+
align-items: center;
|
|
231
|
+
gap: 8px;
|
|
232
|
+
padding-top: max(16px, env(safe-area-inset-top));
|
|
233
|
+
z-index: 9998;
|
|
234
|
+
pointer-events: none;
|
|
235
|
+
}
|
|
242
236
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
237
|
+
.ikon-toast-overlay-chip {
|
|
238
|
+
display: flex;
|
|
239
|
+
align-items: center;
|
|
240
|
+
gap: 8px;
|
|
241
|
+
max-width: min(440px, calc(100vw - 32px));
|
|
242
|
+
padding: 8px 14px;
|
|
243
|
+
border: 1px solid var(--ikon-border-secondary);
|
|
244
|
+
border-radius: var(--ikon-radius-lg);
|
|
245
|
+
background: var(--ikon-bg-card);
|
|
246
|
+
color: var(--ikon-text-primary);
|
|
247
|
+
font-family: var(--ikon-font-body);
|
|
248
|
+
font-size: 13px;
|
|
249
|
+
font-weight: 500;
|
|
250
|
+
pointer-events: auto;
|
|
251
|
+
cursor: pointer;
|
|
252
|
+
animation: ikon-fade-in 0.3s ease-out;
|
|
253
|
+
}
|
|
246
254
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
255
|
+
.ikon-toast-overlay-chip--warn {
|
|
256
|
+
border-left: 3px solid var(--ikon-status-warning);
|
|
257
|
+
}
|
|
250
258
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
259
|
+
.ikon-toast-overlay-chip--warn .ikon-toast-overlay-icon {
|
|
260
|
+
color: var(--ikon-status-warning);
|
|
261
|
+
}
|
|
254
262
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
263
|
+
.ikon-toast-overlay-chip--error {
|
|
264
|
+
border-left: 3px solid var(--ikon-status-error);
|
|
265
|
+
}
|
|
258
266
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
line-height: 1;
|
|
263
|
-
}
|
|
267
|
+
.ikon-toast-overlay-chip--error .ikon-toast-overlay-icon {
|
|
268
|
+
color: var(--ikon-status-error);
|
|
269
|
+
}
|
|
264
270
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
}
|
|
271
|
+
.ikon-toast-overlay-icon {
|
|
272
|
+
flex-shrink: 0;
|
|
273
|
+
font-size: 13px;
|
|
274
|
+
line-height: 1;
|
|
275
|
+
}
|
|
271
276
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
277
|
+
.ikon-toast-overlay-content {
|
|
278
|
+
display: flex;
|
|
279
|
+
align-items: baseline;
|
|
280
|
+
gap: 6px;
|
|
281
|
+
min-width: 0;
|
|
282
|
+
}
|
|
278
283
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
+
.ikon-toast-overlay-component {
|
|
285
|
+
flex: none;
|
|
286
|
+
font-family: var(--ikon-font-mono);
|
|
287
|
+
font-size: 11px;
|
|
288
|
+
color: var(--ikon-text-quaternary);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
.ikon-toast-overlay-message {
|
|
292
|
+
font-size: 13px;
|
|
293
|
+
white-space: pre-wrap;
|
|
294
|
+
word-break: break-word;
|
|
284
295
|
}
|