tempest-react-sdk 0.64.0 → 0.65.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/README.md +4 -4
- package/dist/components/Command/Command.module.cjs.map +1 -1
- package/dist/components/Command/Command.module.js.map +1 -1
- package/dist/components/ContextMenu/ContextMenu.module.cjs.map +1 -1
- package/dist/components/ContextMenu/ContextMenu.module.js.map +1 -1
- package/dist/components/DataTable/DataTable.cjs +1 -1
- package/dist/components/DataTable/DataTable.cjs.map +1 -1
- package/dist/components/DataTable/DataTable.js +1 -0
- package/dist/components/DataTable/DataTable.js.map +1 -1
- package/dist/components/DataTable/use-dev-warnings.cjs +1 -1
- package/dist/components/DataTable/use-dev-warnings.cjs.map +1 -1
- package/dist/components/DataTable/use-dev-warnings.js +4 -3
- package/dist/components/DataTable/use-dev-warnings.js.map +1 -1
- package/dist/components/DropdownMenu/DropdownMenu.module.cjs.map +1 -1
- package/dist/components/DropdownMenu/DropdownMenu.module.js.map +1 -1
- package/dist/components/InstallBanner/InstallBanner.cjs +1 -1
- package/dist/components/InstallBanner/InstallBanner.cjs.map +1 -1
- package/dist/components/InstallBanner/InstallBanner.js +62 -37
- package/dist/components/InstallBanner/InstallBanner.js.map +1 -1
- package/dist/components/InstallBanner/InstallBanner.module.cjs +1 -1
- package/dist/components/InstallBanner/InstallBanner.module.cjs.map +1 -1
- package/dist/components/InstallBanner/InstallBanner.module.js +4 -3
- package/dist/components/InstallBanner/InstallBanner.module.js.map +1 -1
- package/dist/components/InstallButton/InstallButton.cjs +1 -1
- package/dist/components/InstallButton/InstallButton.cjs.map +1 -1
- package/dist/components/InstallButton/InstallButton.js +34 -10
- package/dist/components/InstallButton/InstallButton.js.map +1 -1
- package/dist/components/InstallButton/InstallButton.module.cjs +3 -0
- package/dist/components/InstallButton/InstallButton.module.cjs.map +1 -0
- package/dist/components/InstallButton/InstallButton.module.js +10 -0
- package/dist/components/InstallButton/InstallButton.module.js.map +1 -0
- package/dist/components/InstallButton/install-hints.cjs +2 -0
- package/dist/components/InstallButton/install-hints.cjs.map +1 -0
- package/dist/components/InstallButton/install-hints.js +32 -0
- package/dist/components/InstallButton/install-hints.js.map +1 -0
- package/dist/components/SegmentedControl/SegmentedControl.module.cjs.map +1 -1
- package/dist/components/SegmentedControl/SegmentedControl.module.js.map +1 -1
- package/dist/components/Select/Select.cjs +1 -1
- package/dist/components/Select/Select.cjs.map +1 -1
- package/dist/components/Select/Select.js +43 -40
- package/dist/components/Select/Select.js.map +1 -1
- package/dist/components/Select/Select.module.cjs +1 -1
- package/dist/components/Select/Select.module.cjs.map +1 -1
- package/dist/components/Select/Select.module.js +5 -3
- package/dist/components/Select/Select.module.js.map +1 -1
- package/dist/hooks/use-install-prompt.cjs +1 -1
- package/dist/hooks/use-install-prompt.cjs.map +1 -1
- package/dist/hooks/use-install-prompt.js +9 -2
- package/dist/hooks/use-install-prompt.js.map +1 -1
- package/dist/http/api-client.cjs +1 -1
- package/dist/http/api-client.cjs.map +1 -1
- package/dist/http/api-client.js +80 -74
- package/dist/http/api-client.js.map +1 -1
- package/dist/http/decode-response.cjs +2 -0
- package/dist/http/decode-response.cjs.map +1 -0
- package/dist/http/decode-response.js +28 -0
- package/dist/http/decode-response.js.map +1 -0
- package/dist/styles/InstallButton.css +2 -0
- package/dist/styles/actions.css +6 -1
- package/dist/styles/advanced.css +2 -2
- package/dist/styles/component/Command.css +1 -1
- package/dist/styles/component/ContextMenu.css +1 -1
- package/dist/styles/component/DropdownMenu.css +1 -1
- package/dist/styles/component/InstallBanner.css +2 -0
- package/dist/styles/component/InstallButton.css +4 -0
- package/dist/styles/component/SegmentedControl.css +1 -1
- package/dist/styles/component/Select.css +4 -0
- package/dist/styles/core.css +2 -2
- package/dist/styles/forms.css +4 -0
- package/dist/styles/manifest.json +2 -1
- package/dist/styles/navigation.css +1 -1
- package/dist/styles/tokens.css +2 -2
- package/dist/styles.css +1 -1
- package/dist/tempest-react-sdk.cjs +1 -1
- package/dist/tempest-react-sdk.d.ts +258 -26
- package/dist/tempest-react-sdk.js +319 -318
- package/dist/theme/ThemeProvider.cjs +1 -1
- package/dist/theme/ThemeProvider.cjs.map +1 -1
- package/dist/theme/ThemeProvider.js +40 -45
- package/dist/theme/ThemeProvider.js.map +1 -1
- package/dist/theme/create-theme.cjs +1 -1
- package/dist/theme/create-theme.cjs.map +1 -1
- package/dist/theme/create-theme.js +1 -1
- package/dist/theme/create-theme.js.map +1 -1
- package/dist/theme/initial-theme.cjs +2 -2
- package/dist/theme/initial-theme.cjs.map +1 -1
- package/dist/theme/initial-theme.js +7 -12
- package/dist/theme/initial-theme.js.map +1 -1
- package/dist/utils/format.cjs +1 -1
- package/dist/utils/format.cjs.map +1 -1
- package/dist/utils/format.js +5 -3
- package/dist/utils/format.js.map +1 -1
- package/dist/utils/storage.cjs +1 -1
- package/dist/utils/storage.cjs.map +1 -1
- package/dist/utils/storage.js +13 -0
- package/dist/utils/storage.js.map +1 -1
- package/package.json +1 -1
package/dist/http/api-client.js
CHANGED
|
@@ -1,67 +1,68 @@
|
|
|
1
1
|
import { randomId as e } from "../utils/ids.js";
|
|
2
2
|
import { buildApiUrl as t } from "./build-url.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { decodeByContentType as n } from "./decode-response.js";
|
|
4
|
+
import { TempestApiError as r, buildApiError as i, isRetriableStatus as a } from "./errors.js";
|
|
5
|
+
import { retry as o } from "./retry.js";
|
|
6
|
+
import { withTimeout as s } from "./timeout.js";
|
|
6
7
|
//#region src/http/api-client.ts
|
|
7
|
-
var
|
|
8
|
+
var c = /* @__PURE__ */ new Set([
|
|
8
9
|
"GET",
|
|
9
10
|
"HEAD",
|
|
10
11
|
"OPTIONS"
|
|
11
12
|
]);
|
|
12
|
-
function
|
|
13
|
-
return !
|
|
13
|
+
function l(e, t) {
|
|
14
|
+
return !c.has(t) || !(e instanceof r) ? !1 : a(e.status);
|
|
14
15
|
}
|
|
15
|
-
function
|
|
16
|
+
function u(e) {
|
|
16
17
|
return e ? e === !0 ? {} : e : null;
|
|
17
18
|
}
|
|
18
|
-
var
|
|
19
|
-
function
|
|
19
|
+
var d = 15e3, f = 3e5;
|
|
20
|
+
function p(e) {
|
|
20
21
|
return typeof FormData < "u" && e instanceof FormData;
|
|
21
22
|
}
|
|
22
|
-
function
|
|
23
|
+
function m(e) {
|
|
23
24
|
return Math.round(performance.now() - e);
|
|
24
25
|
}
|
|
25
|
-
async function
|
|
26
|
-
let
|
|
26
|
+
async function h(e, t) {
|
|
27
|
+
let n;
|
|
27
28
|
try {
|
|
28
|
-
|
|
29
|
+
n = await e.clone().json();
|
|
29
30
|
} catch {
|
|
30
31
|
try {
|
|
31
|
-
|
|
32
|
+
n = await e.text();
|
|
32
33
|
} catch {
|
|
33
|
-
|
|
34
|
+
n = null;
|
|
34
35
|
}
|
|
35
36
|
}
|
|
36
|
-
return new
|
|
37
|
+
return new r(i(e.status, n, e.headers, t));
|
|
37
38
|
}
|
|
38
|
-
function
|
|
39
|
-
let
|
|
40
|
-
function
|
|
41
|
-
let e =
|
|
39
|
+
function g(i) {
|
|
40
|
+
let a = i.fetcher ?? globalThis.fetch.bind(globalThis);
|
|
41
|
+
function c() {
|
|
42
|
+
let e = i.getToken?.();
|
|
42
43
|
return e ? { Authorization: `Bearer ${e}` } : {};
|
|
43
44
|
}
|
|
44
|
-
async function
|
|
45
|
-
let { body: l, params:
|
|
45
|
+
async function g(e, n, o) {
|
|
46
|
+
let { body: l, params: u, headers: m, signal: h, timeout: g, ..._ } = n, v = p(l), y = v ? i.uploadTimeout : i.timeout, b = g === void 0 ? y === void 0 ? v ? f : d : y : g, x = {
|
|
46
47
|
...v ? {} : { "Content-Type": "application/json" },
|
|
47
|
-
...
|
|
48
|
-
...
|
|
49
|
-
...
|
|
48
|
+
...o ? { "X-Request-ID": o } : {},
|
|
49
|
+
...i.headers,
|
|
50
|
+
...c(),
|
|
50
51
|
...m
|
|
51
|
-
}, S =
|
|
52
|
+
}, S = s(h, b), C = {
|
|
52
53
|
..._,
|
|
53
54
|
signal: S.signal,
|
|
54
55
|
headers: x,
|
|
55
|
-
credentials:
|
|
56
|
+
credentials: i.withCredentials ? "include" : _.credentials,
|
|
56
57
|
body: l == null ? void 0 : v ? l : JSON.stringify(l)
|
|
57
|
-
}, w = t(
|
|
58
|
-
prefix:
|
|
59
|
-
params:
|
|
58
|
+
}, w = t(i.baseURL, e, {
|
|
59
|
+
prefix: i.prefix,
|
|
60
|
+
params: u
|
|
60
61
|
});
|
|
61
62
|
try {
|
|
62
|
-
return await
|
|
63
|
+
return await a(w, C);
|
|
63
64
|
} catch (e) {
|
|
64
|
-
throw S.timedOut() ? new
|
|
65
|
+
throw S.timedOut() ? new r({
|
|
65
66
|
status: 0,
|
|
66
67
|
detail: `A requisição excedeu ${b}ms e foi abandonada.`
|
|
67
68
|
}) : e;
|
|
@@ -69,35 +70,35 @@ function h(r) {
|
|
|
69
70
|
S.dispose();
|
|
70
71
|
}
|
|
71
72
|
}
|
|
72
|
-
async function
|
|
73
|
-
let a =
|
|
74
|
-
if (!a) return
|
|
73
|
+
async function _(e, t, n, r) {
|
|
74
|
+
let a = i.logger;
|
|
75
|
+
if (!a) return g(e, t, n);
|
|
75
76
|
let o = performance.now();
|
|
76
77
|
try {
|
|
77
|
-
let
|
|
78
|
+
let i = await g(e, t, n), s = {
|
|
78
79
|
requestId: n,
|
|
79
|
-
status:
|
|
80
|
-
ms:
|
|
81
|
-
}, c = `${
|
|
82
|
-
return
|
|
80
|
+
status: i.status,
|
|
81
|
+
ms: m(o)
|
|
82
|
+
}, c = `${r} ${e} → ${i.status}`;
|
|
83
|
+
return i.status >= 400 ? a.warn(c, s) : a.debug(c, s), i;
|
|
83
84
|
} catch (t) {
|
|
84
|
-
throw a.warn(`${
|
|
85
|
+
throw a.warn(`${r} ${e} → no response`, {
|
|
85
86
|
requestId: n,
|
|
86
|
-
ms:
|
|
87
|
+
ms: m(o),
|
|
87
88
|
error: t
|
|
88
89
|
}), t;
|
|
89
90
|
}
|
|
90
91
|
}
|
|
91
|
-
async function
|
|
92
|
-
if (
|
|
93
|
-
|
|
92
|
+
async function v(e, t) {
|
|
93
|
+
if (i.onUnauthorized) {
|
|
94
|
+
i.logger?.warn("unauthorized — calling onUnauthorized", {
|
|
94
95
|
requestId: t,
|
|
95
96
|
status: e.status
|
|
96
97
|
});
|
|
97
98
|
try {
|
|
98
|
-
await
|
|
99
|
+
await i.onUnauthorized(e);
|
|
99
100
|
} catch (n) {
|
|
100
|
-
|
|
101
|
+
i.logger?.warn("onUnauthorized threw — keeping the original response error", {
|
|
101
102
|
requestId: t,
|
|
102
103
|
status: e.status,
|
|
103
104
|
error: n
|
|
@@ -105,63 +106,68 @@ function h(r) {
|
|
|
105
106
|
}
|
|
106
107
|
}
|
|
107
108
|
}
|
|
108
|
-
async function
|
|
109
|
-
let
|
|
110
|
-
if (
|
|
111
|
-
if (
|
|
109
|
+
async function y(t, n, r) {
|
|
110
|
+
let a = i.requestId ? i.requestId() : e(), o = (n.method ?? "GET").toUpperCase(), s = await _(t, n, a, o);
|
|
111
|
+
if (s.status === 401) {
|
|
112
|
+
if (i.refresh) {
|
|
112
113
|
try {
|
|
113
|
-
await
|
|
114
|
+
await i.refresh(), s = await _(t, n, a, o);
|
|
114
115
|
} catch {
|
|
115
|
-
throw await
|
|
116
|
+
throw await v(s, a), await h(s, a);
|
|
116
117
|
}
|
|
117
|
-
|
|
118
|
-
} else await
|
|
118
|
+
s.status === 401 && await v(s, a);
|
|
119
|
+
} else await v(s, a);
|
|
119
120
|
}
|
|
120
|
-
if (!
|
|
121
|
-
|
|
121
|
+
if (!s.ok) throw await h(s, a);
|
|
122
|
+
return r(s);
|
|
122
123
|
}
|
|
123
|
-
async function
|
|
124
|
-
let
|
|
125
|
-
if (!
|
|
126
|
-
let
|
|
127
|
-
return
|
|
128
|
-
...
|
|
129
|
-
shouldRetry:
|
|
124
|
+
async function b(e, t, n) {
|
|
125
|
+
let r = u(i.retry);
|
|
126
|
+
if (!r) return y(e, t, n);
|
|
127
|
+
let a = (t.method ?? "GET").toUpperCase();
|
|
128
|
+
return o(() => y(e, t, n), {
|
|
129
|
+
...r,
|
|
130
|
+
shouldRetry: r.shouldRetry ?? ((e) => l(e, a))
|
|
130
131
|
});
|
|
131
132
|
}
|
|
132
|
-
async function
|
|
133
|
-
return
|
|
133
|
+
async function x(e, t = {}) {
|
|
134
|
+
return b(e, t, n);
|
|
135
|
+
}
|
|
136
|
+
async function S(e, t, n = "POST", r) {
|
|
137
|
+
return x(e, {
|
|
134
138
|
...r,
|
|
135
139
|
method: n,
|
|
136
140
|
body: t
|
|
137
141
|
});
|
|
138
142
|
}
|
|
139
143
|
return {
|
|
140
|
-
request:
|
|
141
|
-
get: (e, t) =>
|
|
144
|
+
request: x,
|
|
145
|
+
get: (e, t) => x(e, {
|
|
142
146
|
...t,
|
|
143
147
|
method: "GET"
|
|
144
148
|
}),
|
|
145
|
-
post: (e, t) =>
|
|
149
|
+
post: (e, t) => x(e, {
|
|
146
150
|
...t,
|
|
147
151
|
method: "POST"
|
|
148
152
|
}),
|
|
149
|
-
put: (e, t) =>
|
|
153
|
+
put: (e, t) => x(e, {
|
|
150
154
|
...t,
|
|
151
155
|
method: "PUT"
|
|
152
156
|
}),
|
|
153
|
-
patch: (e, t) =>
|
|
157
|
+
patch: (e, t) => x(e, {
|
|
154
158
|
...t,
|
|
155
159
|
method: "PATCH"
|
|
156
160
|
}),
|
|
157
|
-
delete: (e, t) =>
|
|
161
|
+
delete: (e, t) => x(e, {
|
|
158
162
|
...t,
|
|
159
163
|
method: "DELETE"
|
|
160
164
|
}),
|
|
161
|
-
|
|
165
|
+
blob: (e, t) => b(e, { ...t }, (e) => e.blob()),
|
|
166
|
+
arrayBuffer: (e, t) => b(e, { ...t }, (e) => e.arrayBuffer()),
|
|
167
|
+
upload: S
|
|
162
168
|
};
|
|
163
169
|
}
|
|
164
170
|
//#endregion
|
|
165
|
-
export {
|
|
171
|
+
export { g as createApiClient };
|
|
166
172
|
|
|
167
173
|
//# sourceMappingURL=api-client.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-client.js","names":[],"sources":["../../src/http/api-client.ts"],"sourcesContent":["/**\n * @tempest-limits function-lines — createApiClient is over the limit and every line\n * is a request-lifecycle concern the client cannot delegate: base URL joining, the\n * auth header, the 401 refresh-and-replay, the opt-in retry wrapper and the response\n * parsing that turns a failure into a typed error.\n */\nimport { randomId } from \"../utils\";\nimport { buildApiUrl } from \"./build-url\";\nimport { buildApiError, TempestApiError, isRetriableStatus } from \"./errors\";\nimport { retry as retryWithBackoff } from \"./retry\";\nimport type { RetryOptions } from \"./retry\";\nimport { withTimeout } from \"./timeout\";\nimport type { ApiClient, ApiClientConfig, RequestOptions } from \"./types\";\n\n/**\n * Methods the built-in retry policy will replay.\n *\n * `PUT` and `DELETE` are idempotent on paper but stay out: a backend that logs,\n * bills, or fires a webhook per call still sees two, so replaying them is a\n * decision the caller makes through `shouldRetry`, not a default.\n */\nconst IDEMPOTENT_METHODS: ReadonlySet<string> = new Set([\"GET\", \"HEAD\", \"OPTIONS\"]);\n\n/**\n * Sub-500 statuses worth a second attempt: a network failure (status `0`), a\n * request timeout, a too-early replay, and a rate limit — which usually carries\n * the `Retry-After` the backoff already honours.\n */\n\n/**\n * The built-in retry policy, used when `retry` is `true` or is options carrying\n * no `shouldRetry` of their own.\n *\n * Conservative on purpose. Replaying a write can duplicate it, and replaying a\n * `400` or a `403` cannot fix a bad payload or a permission the caller does not\n * have — it only spends the user's time before showing the same error.\n *\n * @param error - Whatever the attempt threw.\n * @param method - The upper-cased HTTP method of the request.\n * @returns Whether the client should try again.\n */\nfunction isRetriableFailure(error: unknown, method: string): boolean {\n if (!IDEMPOTENT_METHODS.has(method)) return false;\n if (!(error instanceof TempestApiError)) return false;\n return isRetriableStatus(error.status);\n}\n\n/**\n * Normalize the `retry` config into options, or `null` when retrying is off.\n *\n * @param config - The `retry` field as the caller wrote it.\n * @returns Retry options to use, or `null` to run a single attempt.\n */\nfunction resolveRetry(config: boolean | RetryOptions | undefined): RetryOptions | null {\n if (!config) return null;\n return config === true ? {} : config;\n}\n\n/** Default milliseconds before a request is abandoned. */\nconst DEFAULT_TIMEOUT = 15_000;\n\n/** Default milliseconds before a `FormData` request is abandoned. */\nconst DEFAULT_UPLOAD_TIMEOUT = 300_000;\n\nfunction isFormData(body: unknown): body is FormData {\n return typeof FormData !== \"undefined\" && body instanceof FormData;\n}\n\n/**\n * Milliseconds since a `performance.now()` reading, rounded.\n *\n * `performance.now()` rather than `Date.now()` because this measures a\n * duration: the wall clock can step sideways mid-request (an NTP correction, a\n * VM resuming, the user changing the clock) and turn a 40 ms call into a\n * negative number. The monotonic clock cannot.\n *\n * @param startedAt - The reading taken before the work started.\n * @returns Whole milliseconds elapsed.\n */\nfunction elapsedMs(startedAt: number): number {\n return Math.round(performance.now() - startedAt);\n}\n\nasync function parseError(response: Response, sentRequestId?: string): Promise<TempestApiError> {\n let body: unknown;\n try {\n body = await response.clone().json();\n } catch {\n try {\n body = await response.text();\n } catch {\n body = null;\n }\n }\n return new TempestApiError(\n buildApiError(response.status, body, response.headers, sentRequestId),\n );\n}\n\n/**\n * Create a typed HTTP client backed by `fetch`.\n *\n * Handles JSON serialization, query params, bearer auth via `getToken`, uploads\n * via `FormData`, and throws a typed `ApiError` on any non-2xx response.\n *\n * **Expired sessions.** A `401` with `refresh` configured awaits the refresh and\n * replays the request once. `onUnauthorized` fires whenever that path ends\n * unauthorized anyway — the refresh threw, or the replay came back `401` — which\n * is the signal to clear the session. Without `refresh`, the first `401` calls\n * it directly.\n *\n * **Retries** are off unless you set `retry`. See {@link ApiClientConfig.retry}\n * for the built-in policy; it never replays a write.\n *\n * **Logging** is off unless you pass a `logger`. With one, every finished attempt\n * writes a line — `debug` under 400, `warn` from 400 up, plus a `warn` when\n * `onUnauthorized` fires — carrying `requestId`, `status` and elapsed `ms`, and\n * never a body, header or query string. The level and the destination belong to\n * the logger, not to a boolean here.\n *\n * @example\n * const api = createApiClient({\n * baseURL: import.meta.env.VITE_API_URL,\n * getToken: () => useAuthStore.getState().token,\n * refresh,\n * onUnauthorized: () => useAuthStore.getState().logout(),\n * logger: createLogger({ level: import.meta.env.DEV ? \"debug\" : \"warn\" }).child(\"http\"),\n * retry: true,\n * });\n *\n * @param config - Base URL plus the optional auth, retry and fetch hooks.\n * @returns A client with `request`/`get`/`post`/`put`/`patch`/`delete`/`upload`.\n */\nexport function createApiClient(config: ApiClientConfig): ApiClient {\n const fetcher = config.fetcher ?? globalThis.fetch.bind(globalThis);\n\n function authHeaders(): Record<string, string> {\n const token = config.getToken?.();\n return token ? { Authorization: `Bearer ${token}` } : {};\n }\n\n async function rawRequest(\n path: string,\n options: RequestOptions,\n requestId?: string,\n ): Promise<Response> {\n const { body, params, headers, signal, timeout, ...rest } = options;\n const isForm = isFormData(body);\n const configured = isForm ? config.uploadTimeout : config.timeout;\n const fallback = isForm ? DEFAULT_UPLOAD_TIMEOUT : DEFAULT_TIMEOUT;\n const limit =\n timeout !== undefined ? timeout : configured !== undefined ? configured : fallback;\n\n const finalHeaders: Record<string, string> = {\n ...(isForm ? {} : { \"Content-Type\": \"application/json\" }),\n ...(requestId ? { \"X-Request-ID\": requestId } : {}),\n ...config.headers,\n ...authHeaders(),\n ...(headers as Record<string, string> | undefined),\n };\n\n const timed = withTimeout(signal, limit);\n const init: RequestInit = {\n ...rest,\n signal: timed.signal,\n headers: finalHeaders,\n credentials: config.withCredentials ? \"include\" : rest.credentials,\n body:\n body === undefined || body === null\n ? undefined\n : isForm\n ? (body as FormData)\n : JSON.stringify(body),\n };\n\n const url = buildApiUrl(config.baseURL, path, { prefix: config.prefix, params });\n try {\n return await fetcher(url, init);\n } catch (cause) {\n if (timed.timedOut()) {\n throw new TempestApiError({\n status: 0,\n detail: `A requisição excedeu ${limit}ms e foi abandonada.`,\n });\n }\n throw cause;\n } finally {\n timed.dispose();\n }\n }\n\n async function send(\n path: string,\n options: RequestOptions,\n requestId: string,\n method: string,\n ): Promise<Response> {\n const log = config.logger;\n if (!log) return rawRequest(path, options, requestId);\n\n const startedAt = performance.now();\n try {\n const response = await rawRequest(path, options, requestId);\n const entry = { requestId, status: response.status, ms: elapsedMs(startedAt) };\n const line = `${method} ${path} → ${response.status}`;\n if (response.status >= 400) log.warn(line, entry);\n else log.debug(line, entry);\n return response;\n } catch (error) {\n log.warn(`${method} ${path} → no response`, {\n requestId,\n ms: elapsedMs(startedAt),\n error,\n });\n throw error;\n }\n }\n\n async function notifyUnauthorized(response: Response, requestId: string): Promise<void> {\n if (!config.onUnauthorized) return;\n config.logger?.warn(`unauthorized — calling onUnauthorized`, {\n requestId,\n status: response.status,\n });\n try {\n await config.onUnauthorized(response);\n } catch (error) {\n config.logger?.warn(`onUnauthorized threw — keeping the original response error`, {\n requestId,\n status: response.status,\n error,\n });\n }\n }\n\n async function attempt<T>(path: string, options: RequestOptions): Promise<T> {\n const requestId = config.requestId ? config.requestId() : randomId();\n const method = (options.method ?? \"GET\").toUpperCase();\n let response = await send(path, options, requestId, method);\n\n if (response.status === 401) {\n if (config.refresh) {\n try {\n await config.refresh();\n response = await send(path, options, requestId, method);\n } catch {\n await notifyUnauthorized(response, requestId);\n throw await parseError(response, requestId);\n }\n if (response.status === 401) {\n await notifyUnauthorized(response, requestId);\n }\n } else {\n await notifyUnauthorized(response, requestId);\n }\n }\n\n if (!response.ok) {\n throw await parseError(response, requestId);\n }\n\n if (response.status === 204) {\n return undefined as T;\n }\n\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n if (contentType.includes(\"application/json\")) {\n return (await response.json()) as T;\n }\n return (await response.text()) as unknown as T;\n }\n\n async function request<T>(path: string, options: RequestOptions = {}): Promise<T> {\n const retryOptions = resolveRetry(config.retry);\n if (!retryOptions) return attempt<T>(path, options);\n\n const method = (options.method ?? \"GET\").toUpperCase();\n return retryWithBackoff(() => attempt<T>(path, options), {\n ...retryOptions,\n shouldRetry:\n retryOptions.shouldRetry ?? ((error: unknown) => isRetriableFailure(error, method)),\n });\n }\n\n async function upload<T>(\n path: string,\n formData: FormData,\n method: \"POST\" | \"PUT\" | \"PATCH\" = \"POST\",\n options?: Omit<RequestOptions, \"body\" | \"method\">,\n ): Promise<T> {\n return request<T>(path, { ...options, method, body: formData });\n }\n\n return {\n request,\n get: <T>(path: string, options?: RequestOptions) =>\n request<T>(path, { ...options, method: \"GET\" }),\n post: <T>(path: string, options?: RequestOptions) =>\n request<T>(path, { ...options, method: \"POST\" }),\n put: <T>(path: string, options?: RequestOptions) =>\n request<T>(path, { ...options, method: \"PUT\" }),\n patch: <T>(path: string, options?: RequestOptions) =>\n request<T>(path, { ...options, method: \"PATCH\" }),\n delete: <T>(path: string, options?: RequestOptions) =>\n request<T>(path, { ...options, method: \"DELETE\" }),\n upload,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"api-client.js","names":[],"sources":["../../src/http/api-client.ts"],"sourcesContent":["/**\n * @tempest-limits function-lines — createApiClient is over the limit and every line\n * is a request-lifecycle concern the client cannot delegate: base URL joining, the\n * auth header, the 401 refresh-and-replay, the opt-in retry wrapper and the response\n * parsing that turns a failure into a typed error.\n */\nimport { randomId } from \"../utils\";\nimport { buildApiUrl } from \"./build-url\";\nimport { decodeByContentType } from \"./decode-response\";\nimport type { ResponseDecoder } from \"./decode-response\";\nimport { buildApiError, TempestApiError, isRetriableStatus } from \"./errors\";\nimport { retry as retryWithBackoff } from \"./retry\";\nimport type { RetryOptions } from \"./retry\";\nimport { withTimeout } from \"./timeout\";\nimport type { ApiClient, ApiClientConfig, RequestOptions } from \"./types\";\n\n/**\n * Methods the built-in retry policy will replay.\n *\n * `PUT` and `DELETE` are idempotent on paper but stay out: a backend that logs,\n * bills, or fires a webhook per call still sees two, so replaying them is a\n * decision the caller makes through `shouldRetry`, not a default.\n */\nconst IDEMPOTENT_METHODS: ReadonlySet<string> = new Set([\"GET\", \"HEAD\", \"OPTIONS\"]);\n\n/**\n * Sub-500 statuses worth a second attempt: a network failure (status `0`), a\n * request timeout, a too-early replay, and a rate limit — which usually carries\n * the `Retry-After` the backoff already honours.\n */\n\n/**\n * The built-in retry policy, used when `retry` is `true` or is options carrying\n * no `shouldRetry` of their own.\n *\n * Conservative on purpose. Replaying a write can duplicate it, and replaying a\n * `400` or a `403` cannot fix a bad payload or a permission the caller does not\n * have — it only spends the user's time before showing the same error.\n *\n * @param error - Whatever the attempt threw.\n * @param method - The upper-cased HTTP method of the request.\n * @returns Whether the client should try again.\n */\nfunction isRetriableFailure(error: unknown, method: string): boolean {\n if (!IDEMPOTENT_METHODS.has(method)) return false;\n if (!(error instanceof TempestApiError)) return false;\n return isRetriableStatus(error.status);\n}\n\n/**\n * Normalize the `retry` config into options, or `null` when retrying is off.\n *\n * @param config - The `retry` field as the caller wrote it.\n * @returns Retry options to use, or `null` to run a single attempt.\n */\nfunction resolveRetry(config: boolean | RetryOptions | undefined): RetryOptions | null {\n if (!config) return null;\n return config === true ? {} : config;\n}\n\n/** Default milliseconds before a request is abandoned. */\nconst DEFAULT_TIMEOUT = 15_000;\n\n/** Default milliseconds before a `FormData` request is abandoned. */\nconst DEFAULT_UPLOAD_TIMEOUT = 300_000;\n\nfunction isFormData(body: unknown): body is FormData {\n return typeof FormData !== \"undefined\" && body instanceof FormData;\n}\n\n/**\n * Milliseconds since a `performance.now()` reading, rounded.\n *\n * `performance.now()` rather than `Date.now()` because this measures a\n * duration: the wall clock can step sideways mid-request (an NTP correction, a\n * VM resuming, the user changing the clock) and turn a 40 ms call into a\n * negative number. The monotonic clock cannot.\n *\n * @param startedAt - The reading taken before the work started.\n * @returns Whole milliseconds elapsed.\n */\nfunction elapsedMs(startedAt: number): number {\n return Math.round(performance.now() - startedAt);\n}\n\nasync function parseError(response: Response, sentRequestId?: string): Promise<TempestApiError> {\n let body: unknown;\n try {\n body = await response.clone().json();\n } catch {\n try {\n body = await response.text();\n } catch {\n body = null;\n }\n }\n return new TempestApiError(\n buildApiError(response.status, body, response.headers, sentRequestId),\n );\n}\n\n/**\n * Create a typed HTTP client backed by `fetch`.\n *\n * Handles JSON serialization, query params, bearer auth via `getToken`, uploads\n * via `FormData`, and throws a typed `ApiError` on any non-2xx response.\n *\n * **Expired sessions.** A `401` with `refresh` configured awaits the refresh and\n * replays the request once. `onUnauthorized` fires whenever that path ends\n * unauthorized anyway — the refresh threw, or the replay came back `401` — which\n * is the signal to clear the session. Without `refresh`, the first `401` calls\n * it directly.\n *\n * **Binary bodies** have their own methods — `blob()` and `arrayBuffer()` — which\n * run the same pipeline and skip the parse. `request()` no longer decodes an\n * unknown `Content-Type` as text either: it returns a `Blob` and says so once in\n * a development build, because reading `image/jpeg` as UTF-8 destroyed the bytes\n * on the way in.\n *\n * **Retries** are off unless you set `retry`. See {@link ApiClientConfig.retry}\n * for the built-in policy; it never replays a write.\n *\n * **Logging** is off unless you pass a `logger`. With one, every finished attempt\n * writes a line — `debug` under 400, `warn` from 400 up, plus a `warn` when\n * `onUnauthorized` fires — carrying `requestId`, `status` and elapsed `ms`, and\n * never a body, header or query string. The level and the destination belong to\n * the logger, not to a boolean here.\n *\n * @example\n * const api = createApiClient({\n * baseURL: import.meta.env.VITE_API_URL,\n * getToken: () => useAuthStore.getState().token,\n * refresh,\n * onUnauthorized: () => useAuthStore.getState().logout(),\n * logger: createLogger({ level: import.meta.env.DEV ? \"debug\" : \"warn\" }).child(\"http\"),\n * retry: true,\n * });\n *\n * @param config - Base URL plus the optional auth, retry and fetch hooks.\n * @returns A client with `request`/`get`/`post`/`put`/`patch`/`delete`/`blob`/\n * `arrayBuffer`/`upload`.\n */\nexport function createApiClient(config: ApiClientConfig): ApiClient {\n const fetcher = config.fetcher ?? globalThis.fetch.bind(globalThis);\n\n function authHeaders(): Record<string, string> {\n const token = config.getToken?.();\n return token ? { Authorization: `Bearer ${token}` } : {};\n }\n\n async function rawRequest(\n path: string,\n options: RequestOptions,\n requestId?: string,\n ): Promise<Response> {\n const { body, params, headers, signal, timeout, ...rest } = options;\n const isForm = isFormData(body);\n const configured = isForm ? config.uploadTimeout : config.timeout;\n const fallback = isForm ? DEFAULT_UPLOAD_TIMEOUT : DEFAULT_TIMEOUT;\n const limit =\n timeout !== undefined ? timeout : configured !== undefined ? configured : fallback;\n\n const finalHeaders: Record<string, string> = {\n ...(isForm ? {} : { \"Content-Type\": \"application/json\" }),\n ...(requestId ? { \"X-Request-ID\": requestId } : {}),\n ...config.headers,\n ...authHeaders(),\n ...(headers as Record<string, string> | undefined),\n };\n\n const timed = withTimeout(signal, limit);\n const init: RequestInit = {\n ...rest,\n signal: timed.signal,\n headers: finalHeaders,\n credentials: config.withCredentials ? \"include\" : rest.credentials,\n body:\n body === undefined || body === null\n ? undefined\n : isForm\n ? (body as FormData)\n : JSON.stringify(body),\n };\n\n const url = buildApiUrl(config.baseURL, path, { prefix: config.prefix, params });\n try {\n return await fetcher(url, init);\n } catch (cause) {\n if (timed.timedOut()) {\n throw new TempestApiError({\n status: 0,\n detail: `A requisição excedeu ${limit}ms e foi abandonada.`,\n });\n }\n throw cause;\n } finally {\n timed.dispose();\n }\n }\n\n async function send(\n path: string,\n options: RequestOptions,\n requestId: string,\n method: string,\n ): Promise<Response> {\n const log = config.logger;\n if (!log) return rawRequest(path, options, requestId);\n\n const startedAt = performance.now();\n try {\n const response = await rawRequest(path, options, requestId);\n const entry = { requestId, status: response.status, ms: elapsedMs(startedAt) };\n const line = `${method} ${path} → ${response.status}`;\n if (response.status >= 400) log.warn(line, entry);\n else log.debug(line, entry);\n return response;\n } catch (error) {\n log.warn(`${method} ${path} → no response`, {\n requestId,\n ms: elapsedMs(startedAt),\n error,\n });\n throw error;\n }\n }\n\n async function notifyUnauthorized(response: Response, requestId: string): Promise<void> {\n if (!config.onUnauthorized) return;\n config.logger?.warn(`unauthorized — calling onUnauthorized`, {\n requestId,\n status: response.status,\n });\n try {\n await config.onUnauthorized(response);\n } catch (error) {\n config.logger?.warn(`onUnauthorized threw — keeping the original response error`, {\n requestId,\n status: response.status,\n error,\n });\n }\n }\n\n async function attempt<T>(\n path: string,\n options: RequestOptions,\n decode: ResponseDecoder<T>,\n ): Promise<T> {\n const requestId = config.requestId ? config.requestId() : randomId();\n const method = (options.method ?? \"GET\").toUpperCase();\n let response = await send(path, options, requestId, method);\n\n if (response.status === 401) {\n if (config.refresh) {\n try {\n await config.refresh();\n response = await send(path, options, requestId, method);\n } catch {\n await notifyUnauthorized(response, requestId);\n throw await parseError(response, requestId);\n }\n if (response.status === 401) {\n await notifyUnauthorized(response, requestId);\n }\n } else {\n await notifyUnauthorized(response, requestId);\n }\n }\n\n if (!response.ok) {\n throw await parseError(response, requestId);\n }\n\n return decode(response);\n }\n\n async function run<T>(\n path: string,\n options: RequestOptions,\n decode: ResponseDecoder<T>,\n ): Promise<T> {\n const retryOptions = resolveRetry(config.retry);\n if (!retryOptions) return attempt<T>(path, options, decode);\n\n const method = (options.method ?? \"GET\").toUpperCase();\n return retryWithBackoff(() => attempt<T>(path, options, decode), {\n ...retryOptions,\n shouldRetry:\n retryOptions.shouldRetry ?? ((error: unknown) => isRetriableFailure(error, method)),\n });\n }\n\n async function request<T>(path: string, options: RequestOptions = {}): Promise<T> {\n return run<T>(path, options, decodeByContentType);\n }\n\n async function upload<T>(\n path: string,\n formData: FormData,\n method: \"POST\" | \"PUT\" | \"PATCH\" = \"POST\",\n options?: Omit<RequestOptions, \"body\" | \"method\">,\n ): Promise<T> {\n return request<T>(path, { ...options, method, body: formData });\n }\n\n return {\n request,\n get: <T>(path: string, options?: RequestOptions) =>\n request<T>(path, { ...options, method: \"GET\" }),\n post: <T>(path: string, options?: RequestOptions) =>\n request<T>(path, { ...options, method: \"POST\" }),\n put: <T>(path: string, options?: RequestOptions) =>\n request<T>(path, { ...options, method: \"PUT\" }),\n patch: <T>(path: string, options?: RequestOptions) =>\n request<T>(path, { ...options, method: \"PATCH\" }),\n delete: <T>(path: string, options?: RequestOptions) =>\n request<T>(path, { ...options, method: \"DELETE\" }),\n blob: (path: string, options?: RequestOptions) =>\n run<Blob>(path, { ...options }, (response) => response.blob()),\n arrayBuffer: (path: string, options?: RequestOptions) =>\n run<ArrayBuffer>(path, { ...options }, (response) => response.arrayBuffer()),\n upload,\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("../utils/dev-mode.cjs");var t=[`xml`,`javascript`,`ecmascript`,`urlencoded`,`csv`];function n(e){return e.toLowerCase().includes(`json`)}function r(e){let n=e.trim().toLowerCase();return n===``||n.startsWith(`text/`)?!0:t.some(e=>n.includes(e))}function i(t){e.isDevBuild()&&console.warn(`[tempest] <ApiClient> received a binary response (content-type: ${t}) and returned a Blob. Call \`client.blob()\` or \`client.arrayBuffer()\` so the type matches what arrives.`)}async function a(e){if(e.status===204)return;let t=e.headers.get(`content-type`)??``;return n(t)?await e.json():r(t)?await e.text():(i(t),await e.blob())}exports.decodeByContentType=a,exports.isJsonContentType=n,exports.isTextualContentType=r;
|
|
2
|
+
//# sourceMappingURL=decode-response.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decode-response.cjs","names":[],"sources":["../../src/http/decode-response.ts"],"sourcesContent":["import { isDevBuild } from \"../utils/dev-mode\";\n\n/**\n * Media-type fragments that name something safe to read as text, for the types\n * that do not open with `text/` — `application/xml`, `application/javascript`,\n * `application/x-www-form-urlencoded`.\n */\nconst TEXTUAL_TOKENS: readonly string[] = [\"xml\", \"javascript\", \"ecmascript\", \"urlencoded\", \"csv\"];\n\n/** How a {@link createApiClient} response body becomes the value a caller awaited. */\nexport type ResponseDecoder<T> = (response: Response) => Promise<T>;\n\n/**\n * Whether a `Content-Type` names a JSON dialect.\n *\n * Matches the suffix forms as well as the plain one, so `application/json`,\n * `application/problem+json` (RFC 9457, what a FastAPI error handler sends) and\n * `application/vnd.tempest.v2+json` all decode as JSON instead of falling\n * through to text.\n *\n * @param contentType - The raw header value, possibly with parameters.\n * @returns Whether the body should be read with `response.json()`.\n */\nexport function isJsonContentType(contentType: string): boolean {\n return contentType.toLowerCase().includes(\"json\");\n}\n\n/**\n * Whether a `Content-Type` names something that survives being read as text.\n *\n * An absent header counts as textual: a backend that answers without one is\n * almost always sending text, and treating it as binary would change what\n * existing callers get back for no measured gain.\n *\n * @param contentType - The raw header value, possibly with parameters.\n * @returns Whether the body should be read with `response.text()`.\n */\nexport function isTextualContentType(contentType: string): boolean {\n const type = contentType.trim().toLowerCase();\n if (type === \"\") return true;\n if (type.startsWith(\"text/\")) return true;\n return TEXTUAL_TOKENS.some((token) => type.includes(token));\n}\n\n/**\n * Warn, in a development build, that a binary body reached the JSON/text path.\n *\n * @param contentType - The `Content-Type` that was decoded as a `Blob`.\n */\nfunction warnBinaryBody(contentType: string): void {\n if (!isDevBuild()) return;\n console.warn(\n `[tempest] <ApiClient> received a binary response (content-type: ${contentType}) and returned a Blob. ` +\n \"Call `client.blob()` or `client.arrayBuffer()` so the type matches what arrives.\",\n );\n}\n\n/**\n * Decode a response the way its `Content-Type` asks to be decoded.\n *\n * JSON is parsed, text is read as text, and **everything else comes back as a\n * `Blob`**. That last branch is the fix for a silent data defect: the client\n * used to fall back to `response.text()` for any non-JSON body, so an\n * `image/jpeg` was decoded as UTF-8 and the bytes were destroyed on the way in.\n * Measured on a bare JPEG header — `ff d8 ff e0 00 10 4a 46 49 46` — the\n * round-trip through text returns 18 bytes for the 10 that arrived, 4 of them\n * replaced by `U+FFFD`. No caller can undo that, which is why the download had\n * to leave the client entirely.\n *\n * A `204` has no body at all and resolves to `undefined`, whatever the headers\n * claim.\n *\n * @typeParam T - What the caller expects back.\n * @param response - A response already known to be successful.\n * @returns The decoded body.\n */\nexport async function decodeByContentType<T>(response: Response): Promise<T> {\n if (response.status === 204) {\n return undefined as T;\n }\n\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n if (isJsonContentType(contentType)) {\n return (await response.json()) as T;\n }\n if (isTextualContentType(contentType)) {\n return (await response.text()) as unknown as T;\n }\n\n warnBinaryBody(contentType);\n return (await response.blob()) as unknown as T;\n}\n"],"mappings":"yCAOA,IAAM,EAAoC,CAAC,MAAO,aAAc,aAAc,aAAc,KAAK,EAgBjG,SAAgB,EAAkB,EAA8B,CAC5D,OAAO,EAAY,YAAY,CAAC,CAAC,SAAS,MAAM,CACpD,CAYA,SAAgB,EAAqB,EAA8B,CAC/D,IAAM,EAAO,EAAY,KAAK,CAAC,CAAC,YAAY,EAG5C,OAFI,IAAS,IACT,EAAK,WAAW,OAAO,EAAU,GAC9B,EAAe,KAAM,GAAU,EAAK,SAAS,CAAK,CAAC,CAC9D,CAOA,SAAS,EAAe,EAA2B,CAC1C,EAAA,WAAW,GAChB,QAAQ,KACJ,mEAAmE,EAAY,4GAEnF,CACJ,CAqBA,eAAsB,EAAuB,EAAgC,CACzE,GAAI,EAAS,SAAW,IACpB,OAGJ,IAAM,EAAc,EAAS,QAAQ,IAAI,cAAc,GAAK,GAS5D,OARI,EAAkB,CAAW,EACrB,MAAM,EAAS,KAAK,EAE5B,EAAqB,CAAW,EACxB,MAAM,EAAS,KAAK,GAGhC,EAAe,CAAW,EAClB,MAAM,EAAS,KAAK,EAChC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { isDevBuild as e } from "../utils/dev-mode.js";
|
|
2
|
+
//#region src/http/decode-response.ts
|
|
3
|
+
var t = [
|
|
4
|
+
"xml",
|
|
5
|
+
"javascript",
|
|
6
|
+
"ecmascript",
|
|
7
|
+
"urlencoded",
|
|
8
|
+
"csv"
|
|
9
|
+
];
|
|
10
|
+
function n(e) {
|
|
11
|
+
return e.toLowerCase().includes("json");
|
|
12
|
+
}
|
|
13
|
+
function r(e) {
|
|
14
|
+
let n = e.trim().toLowerCase();
|
|
15
|
+
return n === "" || n.startsWith("text/") ? !0 : t.some((e) => n.includes(e));
|
|
16
|
+
}
|
|
17
|
+
function i(t) {
|
|
18
|
+
e() && console.warn(`[tempest] <ApiClient> received a binary response (content-type: ${t}) and returned a Blob. Call \`client.blob()\` or \`client.arrayBuffer()\` so the type matches what arrives.`);
|
|
19
|
+
}
|
|
20
|
+
async function a(e) {
|
|
21
|
+
if (e.status === 204) return;
|
|
22
|
+
let t = e.headers.get("content-type") ?? "";
|
|
23
|
+
return n(t) ? await e.json() : r(t) ? await e.text() : (i(t), await e.blob());
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
export { a as decodeByContentType, n as isJsonContentType, r as isTextualContentType };
|
|
27
|
+
|
|
28
|
+
//# sourceMappingURL=decode-response.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decode-response.js","names":[],"sources":["../../src/http/decode-response.ts"],"sourcesContent":["import { isDevBuild } from \"../utils/dev-mode\";\n\n/**\n * Media-type fragments that name something safe to read as text, for the types\n * that do not open with `text/` — `application/xml`, `application/javascript`,\n * `application/x-www-form-urlencoded`.\n */\nconst TEXTUAL_TOKENS: readonly string[] = [\"xml\", \"javascript\", \"ecmascript\", \"urlencoded\", \"csv\"];\n\n/** How a {@link createApiClient} response body becomes the value a caller awaited. */\nexport type ResponseDecoder<T> = (response: Response) => Promise<T>;\n\n/**\n * Whether a `Content-Type` names a JSON dialect.\n *\n * Matches the suffix forms as well as the plain one, so `application/json`,\n * `application/problem+json` (RFC 9457, what a FastAPI error handler sends) and\n * `application/vnd.tempest.v2+json` all decode as JSON instead of falling\n * through to text.\n *\n * @param contentType - The raw header value, possibly with parameters.\n * @returns Whether the body should be read with `response.json()`.\n */\nexport function isJsonContentType(contentType: string): boolean {\n return contentType.toLowerCase().includes(\"json\");\n}\n\n/**\n * Whether a `Content-Type` names something that survives being read as text.\n *\n * An absent header counts as textual: a backend that answers without one is\n * almost always sending text, and treating it as binary would change what\n * existing callers get back for no measured gain.\n *\n * @param contentType - The raw header value, possibly with parameters.\n * @returns Whether the body should be read with `response.text()`.\n */\nexport function isTextualContentType(contentType: string): boolean {\n const type = contentType.trim().toLowerCase();\n if (type === \"\") return true;\n if (type.startsWith(\"text/\")) return true;\n return TEXTUAL_TOKENS.some((token) => type.includes(token));\n}\n\n/**\n * Warn, in a development build, that a binary body reached the JSON/text path.\n *\n * @param contentType - The `Content-Type` that was decoded as a `Blob`.\n */\nfunction warnBinaryBody(contentType: string): void {\n if (!isDevBuild()) return;\n console.warn(\n `[tempest] <ApiClient> received a binary response (content-type: ${contentType}) and returned a Blob. ` +\n \"Call `client.blob()` or `client.arrayBuffer()` so the type matches what arrives.\",\n );\n}\n\n/**\n * Decode a response the way its `Content-Type` asks to be decoded.\n *\n * JSON is parsed, text is read as text, and **everything else comes back as a\n * `Blob`**. That last branch is the fix for a silent data defect: the client\n * used to fall back to `response.text()` for any non-JSON body, so an\n * `image/jpeg` was decoded as UTF-8 and the bytes were destroyed on the way in.\n * Measured on a bare JPEG header — `ff d8 ff e0 00 10 4a 46 49 46` — the\n * round-trip through text returns 18 bytes for the 10 that arrived, 4 of them\n * replaced by `U+FFFD`. No caller can undo that, which is why the download had\n * to leave the client entirely.\n *\n * A `204` has no body at all and resolves to `undefined`, whatever the headers\n * claim.\n *\n * @typeParam T - What the caller expects back.\n * @param response - A response already known to be successful.\n * @returns The decoded body.\n */\nexport async function decodeByContentType<T>(response: Response): Promise<T> {\n if (response.status === 204) {\n return undefined as T;\n }\n\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n if (isJsonContentType(contentType)) {\n return (await response.json()) as T;\n }\n if (isTextualContentType(contentType)) {\n return (await response.text()) as unknown as T;\n }\n\n warnBinaryBody(contentType);\n return (await response.blob()) as unknown as T;\n}\n"],"mappings":";;AAOA,IAAM,IAAoC;CAAC;CAAO;CAAc;CAAc;CAAc;AAAK;AAgBjG,SAAgB,EAAkB,GAA8B;CAC5D,OAAO,EAAY,YAAY,CAAC,CAAC,SAAS,MAAM;AACpD;AAYA,SAAgB,EAAqB,GAA8B;CAC/D,IAAM,IAAO,EAAY,KAAK,CAAC,CAAC,YAAY;CAG5C,OAFI,MAAS,MACT,EAAK,WAAW,OAAO,IAAU,KAC9B,EAAe,MAAM,MAAU,EAAK,SAAS,CAAK,CAAC;AAC9D;AAOA,SAAS,EAAe,GAA2B;CAC1C,EAAW,KAChB,QAAQ,KACJ,mEAAmE,EAAY,4GAEnF;AACJ;AAqBA,eAAsB,EAAuB,GAAgC;CACzE,IAAI,EAAS,WAAW,KACpB;CAGJ,IAAM,IAAc,EAAS,QAAQ,IAAI,cAAc,KAAK;CAS5D,OARI,EAAkB,CAAW,IACrB,MAAM,EAAS,KAAK,IAE5B,EAAqB,CAAW,IACxB,MAAM,EAAS,KAAK,KAGhC,EAAe,CAAW,GAClB,MAAM,EAAS,KAAK;AAChC"}
|
package/dist/styles/actions.css
CHANGED
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
.tempest_topEnd_cFA5-{bottom:calc(100% + 4px);right:0}
|
|
49
49
|
.tempest_item_T-QPZ{align-items:center;gap:var(--tempest-space-2);width:100%;padding:var(--tempest-space-2) var(--tempest-space-3);border-radius:var(--tempest-radius-sm);color:var(--tempest-text);font-family:inherit;font-size:inherit;line-height:var(--tempest-leading-snug);text-align:left;cursor:pointer;transition:var(--tempest-transition-color);background:0 0;border:none;display:flex}
|
|
50
50
|
@media (hover:hover) and (pointer:fine){.tempest_item_T-QPZ:hover:not(:disabled){background-color:var(--tempest-surface)}}
|
|
51
|
-
.tempest_item_T-QPZ:focus,.tempest_item_T-QPZ.tempest_active_WNqoX{background-color:var(--tempest-
|
|
51
|
+
.tempest_item_T-QPZ:focus,.tempest_item_T-QPZ.tempest_active_WNqoX{background-color:var(--tempest-primary-soft);color:var(--tempest-primary-on-soft);box-shadow:inset 3px 0 0 0 var(--tempest-selected-indicator);outline:none}
|
|
52
52
|
.tempest_item_T-QPZ:disabled{opacity:.55;cursor:not-allowed}
|
|
53
53
|
.tempest_item_T-QPZ.tempest_danger_C0jN3{color:var(--tempest-danger)}
|
|
54
54
|
.tempest_separator_RimQa{background-color:var(--tempest-border);height:1px;margin:var(--tempest-space-1) 0}
|
|
@@ -84,6 +84,11 @@
|
|
|
84
84
|
.tempest_description_QY25-{margin:var(--tempest-space-1) 0 0;color:var(--tempest-text-muted)}
|
|
85
85
|
.tempest_close_RN6FO{color:var(--tempest-text-muted);cursor:pointer;border-radius:var(--tempest-radius-sm);background:0 0;border:0;flex:none;justify-content:center;align-items:center;width:28px;height:28px;padding:0;display:inline-flex}
|
|
86
86
|
.tempest_close_RN6FO:hover{background:color-mix(in srgb, currentColor 10%, transparent)}
|
|
87
|
+
.tempest_hint_aYJgR{margin:var(--tempest-space-2) 0 0;color:var(--tempest-text-muted)}
|
|
88
|
+
.tempest_hint_aYJgR a{color:var(--tempest-primary)}
|
|
89
|
+
.tempest_wrapper_M6K7s{align-items:flex-start;gap:var(--tempest-space-2);font-family:var(--tempest-font-sans);flex-direction:column;display:inline-flex}
|
|
90
|
+
.tempest_hint_4lawL{max-width:36ch;color:var(--tempest-text-muted);font-size:var(--tempest-text-sm);line-height:var(--tempest-leading-snug);margin:0}
|
|
91
|
+
.tempest_hint_4lawL a{color:var(--tempest-primary)}
|
|
87
92
|
.tempest_root_vEMon{display:inline-flex;position:relative}
|
|
88
93
|
.tempest_popover_E9K9X{z-index:var(--tempest-z-popover);background-color:var(--tempest-bg);color:var(--tempest-text);border:1px solid var(--tempest-border);border-radius:var(--tempest-radius-lg);box-shadow:var(--tempest-shadow-lg);padding:var(--tempest-space-3) var(--tempest-space-4);min-width:200px;max-width:320px;font-family:var(--tempest-font-sans);font-size:var(--tempest-text-base);line-height:var(--tempest-leading-snug);animation:tempest_tempest-popover-in_W8miP var(--tempest-duration-fast) var(--tempest-ease-out);position:absolute}
|
|
89
94
|
.tempest_popover_E9K9X:focus{outline:none}
|
package/dist/styles/advanced.css
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
.tempest_groupHeading_d01fo{padding:var(--tempest-space-2) var(--tempest-space-3);font-size:var(--tempest-text-xs);font-weight:var(--tempest-weight-semibold);text-transform:uppercase;letter-spacing:.04em;color:var(--tempest-text-muted)}
|
|
17
17
|
.tempest_groupList_QFMjK{margin:0;padding:0;list-style:none}
|
|
18
18
|
.tempest_option_doqib{align-items:center;gap:var(--tempest-space-3);padding:var(--tempest-space-2) var(--tempest-space-3);border-radius:var(--tempest-radius-md);cursor:pointer;color:var(--tempest-text);transition:var(--tempest-transition-color);display:flex}
|
|
19
|
-
.tempest_option_doqib.tempest_active_LdCIJ{background-color:var(--tempest-
|
|
19
|
+
.tempest_option_doqib.tempest_active_LdCIJ{background-color:var(--tempest-primary-soft);color:var(--tempest-primary-on-soft);box-shadow:inset 3px 0 0 0 var(--tempest-selected-indicator)}
|
|
20
20
|
.tempest_icon_CyCCx{color:var(--tempest-text-muted);flex-shrink:0;justify-content:center;align-items:center;display:flex}
|
|
21
21
|
.tempest_label_QePT-{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}
|
|
22
22
|
.tempest_empty_al68D{padding:var(--tempest-space-6) var(--tempest-space-3);text-align:center;color:var(--tempest-text-muted);font-size:var(--tempest-text-sm);list-style:none}
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
.tempest_menu_MDn4t{z-index:var(--tempest-z-popover);background-color:var(--tempest-bg);border:1px solid var(--tempest-border);border-radius:var(--tempest-radius-lg);min-width:180px;max-width:320px;box-shadow:var(--tempest-shadow-lg);padding:var(--tempest-space-1);font-family:var(--tempest-font-sans);font-size:var(--tempest-text-base);animation:tempest_tempest-context-menu-in_fNuOl var(--tempest-duration-fast) var(--tempest-ease-out);margin:0;list-style:none;position:fixed}
|
|
30
30
|
.tempest_item_PoiMY{align-items:center;gap:var(--tempest-space-2);width:100%;padding:var(--tempest-space-2) var(--tempest-space-3);border-radius:var(--tempest-radius-sm);color:var(--tempest-text);font-family:inherit;font-size:inherit;line-height:var(--tempest-leading-snug);text-align:left;cursor:pointer;transition:var(--tempest-transition-color);background:0 0;border:none;display:flex}
|
|
31
31
|
@media (hover:hover) and (pointer:fine){.tempest_item_PoiMY:hover:not(:disabled){background-color:var(--tempest-surface)}}
|
|
32
|
-
.tempest_item_PoiMY:focus,.tempest_item_PoiMY.tempest_active_ATcDu{background-color:var(--tempest-
|
|
32
|
+
.tempest_item_PoiMY:focus,.tempest_item_PoiMY.tempest_active_ATcDu{background-color:var(--tempest-primary-soft);color:var(--tempest-primary-on-soft);box-shadow:inset 3px 0 0 0 var(--tempest-selected-indicator);outline:none}
|
|
33
33
|
.tempest_item_PoiMY:disabled{opacity:.55;cursor:not-allowed}
|
|
34
34
|
.tempest_item_PoiMY.tempest_danger_COgly{color:var(--tempest-danger)}
|
|
35
35
|
.tempest_separator_omuCz{background-color:var(--tempest-border);height:1px;margin:var(--tempest-space-1) 0}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
.tempest_groupHeading_d01fo{padding:var(--tempest-space-2) var(--tempest-space-3);font-size:var(--tempest-text-xs);font-weight:var(--tempest-weight-semibold);text-transform:uppercase;letter-spacing:.04em;color:var(--tempest-text-muted)}
|
|
12
12
|
.tempest_groupList_QFMjK{margin:0;padding:0;list-style:none}
|
|
13
13
|
.tempest_option_doqib{align-items:center;gap:var(--tempest-space-3);padding:var(--tempest-space-2) var(--tempest-space-3);border-radius:var(--tempest-radius-md);cursor:pointer;color:var(--tempest-text);transition:var(--tempest-transition-color);display:flex}
|
|
14
|
-
.tempest_option_doqib.tempest_active_LdCIJ{background-color:var(--tempest-
|
|
14
|
+
.tempest_option_doqib.tempest_active_LdCIJ{background-color:var(--tempest-primary-soft);color:var(--tempest-primary-on-soft);box-shadow:inset 3px 0 0 0 var(--tempest-selected-indicator)}
|
|
15
15
|
.tempest_icon_CyCCx{color:var(--tempest-text-muted);flex-shrink:0;justify-content:center;align-items:center;display:flex}
|
|
16
16
|
.tempest_label_QePT-{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}
|
|
17
17
|
.tempest_empty_al68D{padding:var(--tempest-space-6) var(--tempest-space-3);text-align:center;color:var(--tempest-text-muted);font-size:var(--tempest-text-sm);list-style:none}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
.tempest_menu_MDn4t{z-index:var(--tempest-z-popover);background-color:var(--tempest-bg);border:1px solid var(--tempest-border);border-radius:var(--tempest-radius-lg);min-width:180px;max-width:320px;box-shadow:var(--tempest-shadow-lg);padding:var(--tempest-space-1);font-family:var(--tempest-font-sans);font-size:var(--tempest-text-base);animation:tempest_tempest-context-menu-in_fNuOl var(--tempest-duration-fast) var(--tempest-ease-out);margin:0;list-style:none;position:fixed}
|
|
6
6
|
.tempest_item_PoiMY{align-items:center;gap:var(--tempest-space-2);width:100%;padding:var(--tempest-space-2) var(--tempest-space-3);border-radius:var(--tempest-radius-sm);color:var(--tempest-text);font-family:inherit;font-size:inherit;line-height:var(--tempest-leading-snug);text-align:left;cursor:pointer;transition:var(--tempest-transition-color);background:0 0;border:none;display:flex}
|
|
7
7
|
@media (hover:hover) and (pointer:fine){.tempest_item_PoiMY:hover:not(:disabled){background-color:var(--tempest-surface)}}
|
|
8
|
-
.tempest_item_PoiMY:focus,.tempest_item_PoiMY.tempest_active_ATcDu{background-color:var(--tempest-
|
|
8
|
+
.tempest_item_PoiMY:focus,.tempest_item_PoiMY.tempest_active_ATcDu{background-color:var(--tempest-primary-soft);color:var(--tempest-primary-on-soft);box-shadow:inset 3px 0 0 0 var(--tempest-selected-indicator);outline:none}
|
|
9
9
|
.tempest_item_PoiMY:disabled{opacity:.55;cursor:not-allowed}
|
|
10
10
|
.tempest_item_PoiMY.tempest_danger_COgly{color:var(--tempest-danger)}
|
|
11
11
|
.tempest_separator_omuCz{background-color:var(--tempest-border);height:1px;margin:var(--tempest-space-1) 0}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
.tempest_topEnd_cFA5-{bottom:calc(100% + 4px);right:0}
|
|
8
8
|
.tempest_item_T-QPZ{align-items:center;gap:var(--tempest-space-2);width:100%;padding:var(--tempest-space-2) var(--tempest-space-3);border-radius:var(--tempest-radius-sm);color:var(--tempest-text);font-family:inherit;font-size:inherit;line-height:var(--tempest-leading-snug);text-align:left;cursor:pointer;transition:var(--tempest-transition-color);background:0 0;border:none;display:flex}
|
|
9
9
|
@media (hover:hover) and (pointer:fine){.tempest_item_T-QPZ:hover:not(:disabled){background-color:var(--tempest-surface)}}
|
|
10
|
-
.tempest_item_T-QPZ:focus,.tempest_item_T-QPZ.tempest_active_WNqoX{background-color:var(--tempest-
|
|
10
|
+
.tempest_item_T-QPZ:focus,.tempest_item_T-QPZ.tempest_active_WNqoX{background-color:var(--tempest-primary-soft);color:var(--tempest-primary-on-soft);box-shadow:inset 3px 0 0 0 var(--tempest-selected-indicator);outline:none}
|
|
11
11
|
.tempest_item_T-QPZ:disabled{opacity:.55;cursor:not-allowed}
|
|
12
12
|
.tempest_item_T-QPZ.tempest_danger_C0jN3{color:var(--tempest-danger)}
|
|
13
13
|
.tempest_separator_RimQa{background-color:var(--tempest-border);height:1px;margin:var(--tempest-space-1) 0}
|
|
@@ -6,3 +6,5 @@
|
|
|
6
6
|
.tempest_description_QY25-{margin:var(--tempest-space-1) 0 0;color:var(--tempest-text-muted)}
|
|
7
7
|
.tempest_close_RN6FO{color:var(--tempest-text-muted);cursor:pointer;border-radius:var(--tempest-radius-sm);background:0 0;border:0;flex:none;justify-content:center;align-items:center;width:28px;height:28px;padding:0;display:inline-flex}
|
|
8
8
|
.tempest_close_RN6FO:hover{background:color-mix(in srgb, currentColor 10%, transparent)}
|
|
9
|
+
.tempest_hint_aYJgR{margin:var(--tempest-space-2) 0 0;color:var(--tempest-text-muted)}
|
|
10
|
+
.tempest_hint_aYJgR a{color:var(--tempest-primary)}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/* Generated by scripts/split-css.mjs — do not edit. */
|
|
2
|
+
.tempest_wrapper_M6K7s{align-items:flex-start;gap:var(--tempest-space-2);font-family:var(--tempest-font-sans);flex-direction:column;display:inline-flex}
|
|
3
|
+
.tempest_hint_4lawL{max-width:36ch;color:var(--tempest-text-muted);font-size:var(--tempest-text-sm);line-height:var(--tempest-leading-snug);margin:0}
|
|
4
|
+
.tempest_hint_4lawL a{color:var(--tempest-primary)}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
.tempest_group_mYyFC.tempest_md_2ixuM .tempest_segment_cu-EL{font-size:var(--tempest-text-sm);min-height:32px;padding:6px 12px}
|
|
7
7
|
.tempest_group_mYyFC.tempest_lg_2Kt7- .tempest_segment_cu-EL{font-size:var(--tempest-text-md);min-height:40px;padding:8px 14px}
|
|
8
8
|
.tempest_segment_cu-EL:hover{color:var(--tempest-text)}
|
|
9
|
-
.tempest_segment_cu-EL.tempest_active_GmyKg{background:var(--tempest-
|
|
9
|
+
.tempest_segment_cu-EL.tempest_active_GmyKg{background:var(--tempest-primary-soft);color:var(--tempest-primary-on-soft);box-shadow:inset 0 0 0 2px var(--tempest-selected-indicator), var(--tempest-shadow-xs,0 1px 2px #00000014)}
|
|
10
10
|
.tempest_segment_cu-EL:disabled{opacity:.4;cursor:not-allowed}
|
|
11
11
|
.tempest_icon_9h6GK{align-items:center;display:inline-flex}
|
|
12
12
|
.tempest_label_mS17q{line-height:1}
|
|
@@ -12,3 +12,7 @@
|
|
|
12
12
|
.tempest_error_sw9MU .tempest_select_cjdcr:focus{box-shadow:0 0 0 var(--tempest-focus-ring-width) color-mix(in srgb, var(--tempest-danger) 25%, transparent)}
|
|
13
13
|
.tempest_helper_frosK{font-size:var(--tempest-text-xs);color:var(--tempest-text-muted);line-height:var(--tempest-leading-snug)}
|
|
14
14
|
.tempest_errorText_-zd6i{font-size:var(--tempest-text-xs);color:var(--tempest-danger);line-height:var(--tempest-leading-snug)}
|
|
15
|
+
.tempest_chipWrapper_5keyI{display:inline-flex}
|
|
16
|
+
.tempest_chip_r4NVm{width:auto}
|
|
17
|
+
.tempest_chip_r4NVm .tempest_select_cjdcr{width:auto;height:var(--tempest-control-height-sm);padding:0 30px 0 var(--tempest-space-3);border-radius:var(--tempest-radius-full);background-color:var(--tempest-surface);font-size:var(--tempest-text-sm);box-shadow:none}
|
|
18
|
+
.tempest_chip_r4NVm .tempest_caret_MdCao{right:10px}
|
package/dist/styles/core.css
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* Generated by scripts/split-css.mjs — do not edit. */
|
|
2
|
-
:root{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--tempest-primary-50:#eef4ff;--tempest-primary-100:#d9e6ff;--tempest-primary-200:#b3ccff;--tempest-primary-300:#80aaff;--tempest-primary-400:#4d85ff;--tempest-primary-500:#06f;--tempest-primary-600:#0052cc;--tempest-primary-700:#003d99;--tempest-primary-800:#002e75;--tempest-primary-900:#001f4d;--tempest-primary:var(--tempest-primary-500);--tempest-primary-hover:var(--tempest-primary-600);--tempest-primary-active:var(--tempest-primary-700);--tempest-primary-soft:var(--tempest-primary-50);--tempest-primary-soft-hover:var(--tempest-primary-100);--tempest-primary-foreground:#fff;--tempest-danger-on-solid:#fff;--tempest-info-on-solid:#fff;--tempest-success-on-solid:#1f0606;--tempest-warning-on-solid:#1f0606;--tempest-neutral-on-solid:#fff;--tempest-primary-on-soft:var(--tempest-primary-600);--tempest-gray-50:#f8f9fb;--tempest-gray-100:#f1f3f6;--tempest-gray-200:#e4e7ec;--tempest-gray-300:#d0d5dd;--tempest-gray-400:#98a2b3;--tempest-gray-500:#667085;--tempest-gray-600:#475467;--tempest-gray-700:#344054;--tempest-gray-800:#1d2939;--tempest-gray-900:#101828;--tempest-bg:#fff;--tempest-surface:var(--tempest-gray-50);--tempest-surface-2:var(--tempest-gray-100);--tempest-surface-3:var(--tempest-gray-200);--tempest-border:var(--tempest-gray-200);--tempest-border-strong:var(--tempest-gray-300);--tempest-text:var(--tempest-gray-900);--tempest-text-muted:var(--tempest-gray-600);--tempest-text-subtle:var(--tempest-gray-500);--tempest-text-on-primary:#fff;--tempest-success:#15803d;--tempest-success-fg:#14532d;--tempest-success-bg:#dcfce7;--tempest-success-border:#86efac;--tempest-success-solid:#16a34a;--tempest-warning:#b45309;--tempest-warning-fg:#78350f;--tempest-warning-bg:#fef3c7;--tempest-warning-border:#fcd34d;--tempest-warning-solid:#d97706;--tempest-danger:#b91c1c;--tempest-danger-fg:#7f1d1d;--tempest-danger-bg:#fee2e2;--tempest-danger-border:#fca5a5;--tempest-danger-solid:#dc2626;--tempest-danger-hover:#991b1b;--tempest-info:#1d4ed8;--tempest-info-fg:#1e3a8a;--tempest-info-bg:#dbeafe;--tempest-info-border:#93c5fd;--tempest-info-solid:#2563eb;--tempest-focus-ring-color:#0052cc;--tempest-focus-ring-width:3px;--tempest-focus-ring-offset:2px;--tempest-radius-xs:2px;--tempest-radius-sm:4px;--tempest-radius-md:8px;--tempest-radius-lg:12px;--tempest-radius-xl:16px;--tempest-radius-2xl:24px;--tempest-radius-full:9999px;--tempest-shadow-xs:0 1px 2px #0f172a0a;--tempest-shadow-sm:0 1px 3px #0f172a14, 0 1px 2px #0f172a0a;--tempest-shadow-md:0 4px 12px #0f172a14, 0 2px 4px #0f172a0a;--tempest-shadow-lg:0 12px 32px #0f172a1f, 0 4px 8px #0f172a0f;--tempest-shadow-xl:0 24px 48px #0f172a2e, 0 8px 16px #0f172a14;--tempest-shadow-inner:inset 0 2px 4px #0f172a0f;--tempest-space-0:0px;--tempest-space-1:4px;--tempest-space-2:8px;--tempest-space-3:12px;--tempest-space-4:16px;--tempest-space-5:20px;--tempest-space-6:24px;--tempest-space-7:28px;--tempest-space-8:32px;--tempest-space-10:40px;--tempest-space-12:48px;--tempest-space-16:64px;--tempest-space-20:80px;--tempest-space-24:96px;--tempest-font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", sans-serif;--tempest-font-mono:ui-monospace, SFMono-Regular, "SF Mono", "Cascadia Code", Menlo, Consolas, "Liberation Mono", monospace;--tempest-font-display:var(--tempest-font-sans);--tempest-z-base:0;--tempest-z-raised:10;--tempest-z-dropdown:1000;--tempest-z-sticky:1020;--tempest-z-overlay:1050;--tempest-z-modal:1100;--tempest-z-popover:1150;--tempest-z-toast:1200;--tempest-z-tooltip:1300;--tempest-bp-xs:480px;--tempest-bp-sm:640px;--tempest-bp-md:768px;--tempest-bp-lg:1024px;--tempest-bp-xl:1280px;--tempest-bp-2xl:1536px;--tempest-chart-1:#2563eb;--tempest-chart-2:#16a34a;--tempest-chart-3:#f59e0b;--tempest-chart-4:#7c3aed;--tempest-chart-5:#ec4899;--tempest-chart-6:#06b6d4;--tempest-chart-7:#ea580c;--tempest-chart-8:#0f766e;--tempest-chart-sequential-1:#dde8fe;--tempest-chart-sequential-2:#acc8fe;--tempest-chart-sequential-3:#7aa7ff;--tempest-chart-sequential-4:#4983fc;--tempest-chart-sequential-5:#3667ce;--tempest-chart-sequential-6:#2b4e96;--tempest-chart-sequential-7:#25375a;--tempest-chart-diverging-1:#0f3ca1;--tempest-chart-diverging-2:#416eca;--tempest-chart-diverging-3:#7ba0e7;--tempest-chart-diverging-4:#bdd2f9;--tempest-chart-diverging-5:#e4e7ec;--tempest-chart-diverging-6:#f6c3bc;--tempest-chart-diverging-7:#de847a;--tempest-chart-diverging-8:#ba473f;--tempest-chart-diverging-9:#870f11;--tempest-chart-grid:var(--tempest-gray-200);--tempest-chart-axis:var(--tempest-gray-500);--tempest-code-comment:#5f666e;--tempest-code-punctuation:#5d6671;--tempest-code-string:#327243;--tempest-code-number:#9d5035;--tempest-code-keyword:#625baf;--tempest-code-literal:#9f4c4f;--tempest-code-function:#1a6c94;--tempest-code-tag:#974d72;--tempest-code-attribute:#127171;--tempest-code-property:#127171;--tempest-safe-area-top:env(safe-area-inset-top,0px);--tempest-safe-area-right:env(safe-area-inset-right,0px);--tempest-safe-area-bottom:env(safe-area-inset-bottom,0px);--tempest-safe-area-left:env(safe-area-inset-left,0px)}
|
|
3
|
-
[data-tempest-theme=dark]{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--tempest-primary-50:#0a1730;--tempest-primary-100:#0f2245;--tempest-primary-200:#133066;--tempest-primary-300:#1a4399;--tempest-primary-400:#2563eb;--tempest-primary-500:#3b82f6;--tempest-primary-600:#60a5fa;--tempest-primary-700:#93c5fd;--tempest-primary-800:#bfdbfe;--tempest-primary-900:#dbeafe;--tempest-primary:var(--tempest-primary-500);--tempest-primary-hover:var(--tempest-primary-600);--tempest-primary-active:var(--tempest-primary-700);--tempest-primary-soft:var(--tempest-primary-100);--tempest-primary-soft-hover:var(--tempest-primary-200);--tempest-primary-on-soft:var(--tempest-primary-700);--tempest-bg:#0b0d12;--tempest-surface:#14171f;--tempest-surface-2:#1d2230;--tempest-surface-3:#262d3f;--tempest-border:#2a3142;--tempest-border-strong:#3a4258;--tempest-text:#f1f3f8;--tempest-text-muted:#aab2c0;--tempest-text-subtle:#7b849a;--tempest-primary-foreground:#1f0606;--tempest-text-on-primary:var(--tempest-primary-foreground);--tempest-danger-on-solid:#1f0606;--tempest-info-on-solid:#1f0606;--tempest-success-on-solid:#1f0606;--tempest-warning-on-solid:#1f0606;--tempest-neutral-on-solid:#fff;--tempest-success-fg:#4ade80;--tempest-success-bg:#052e16;--tempest-success-border:#166534;--tempest-success-solid:#22c55e;--tempest-success:#4ade80;--tempest-warning-fg:#fbbf24;--tempest-warning-bg:#2c1c05;--tempest-warning-border:#78350f;--tempest-warning-solid:#f59e0b;--tempest-warning:#fbbf24;--tempest-danger-fg:#f87171;--tempest-danger-bg:#2c0a0a;--tempest-danger-border:#7f1d1d;--tempest-danger-solid:#ef4444;--tempest-danger:#f87171;--tempest-danger-hover:#f87171;--tempest-info-fg:#60a5fa;--tempest-info-bg:#0a1730;--tempest-info-border:#1e3a8a;--tempest-info-solid:#3b82f6;--tempest-info:#60a5fa;--tempest-focus-ring-color:#60a5fa;--tempest-shadow-xs:0 1px 2px #0000004d;--tempest-shadow-sm:0 1px 3px #0006, 0 1px 2px #0003;--tempest-shadow-md:0 4px 12px #0006, 0 2px 4px #0003;--tempest-shadow-lg:0 12px 32px #00000080, 0 4px 8px #0000004d;--tempest-shadow-xl:0 24px 48px #0009, 0 8px 16px #0000004d;--tempest-chart-1:#60a5fa;--tempest-chart-2:#4ade80;--tempest-chart-3:#fbbf24;--tempest-chart-4:#a78bfa;--tempest-chart-5:#f472b6;--tempest-chart-6:#22d3ee;--tempest-chart-7:#fb923c;--tempest-chart-8:#2dd4bf;--tempest-chart-sequential-1:#172849;--tempest-chart-sequential-2:#1b3c83;--tempest-chart-sequential-3:#2453b9;--tempest-chart-sequential-4:#376fe5;--tempest-chart-sequential-5:#5b90fb;--tempest-chart-sequential-6:#8cb2fa;--tempest-chart-sequential-7:#bad2fe;--tempest-chart-diverging-1:#1543a8;--tempest-chart-diverging-2:#416eca;--tempest-chart-diverging-3:#7599e0;--tempest-chart-diverging-4:#b0c5ec;--tempest-chart-diverging-5:#262d3f;--tempest-chart-diverging-6:#e8b6af;--tempest-chart-diverging-7:#d77e74;--tempest-chart-diverging-8:#ba473f;--tempest-chart-diverging-9:#94020c;--tempest-chart-grid:var(--tempest-gray-300);--tempest-chart-axis:var(--tempest-gray-600);--tempest-code-comment:#838b93;--tempest-code-punctuation:#818b95;--tempest-code-string:#589866;--tempest-code-number:#c57558;--tempest-code-keyword:#8580d8;--tempest-code-literal:#c87172;--tempest-code-function:#2893c6;--tempest-code-tag:#c07197;--tempest-code-attribute:#349897;--tempest-code-property:#349897}
|
|
2
|
+
:root{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--tempest-primary-50:#eef4ff;--tempest-primary-100:#d9e6ff;--tempest-primary-200:#b3ccff;--tempest-primary-300:#80aaff;--tempest-primary-400:#4d85ff;--tempest-primary-500:#06f;--tempest-primary-600:#0052cc;--tempest-primary-700:#003d99;--tempest-primary-800:#002e75;--tempest-primary-900:#001f4d;--tempest-primary:var(--tempest-primary-500);--tempest-primary-hover:var(--tempest-primary-600);--tempest-primary-active:var(--tempest-primary-700);--tempest-primary-soft:var(--tempest-primary-50);--tempest-primary-soft-hover:var(--tempest-primary-100);--tempest-primary-foreground:#fff;--tempest-danger-on-solid:#fff;--tempest-info-on-solid:#fff;--tempest-success-on-solid:#1f0606;--tempest-warning-on-solid:#1f0606;--tempest-neutral-on-solid:#fff;--tempest-primary-on-soft:var(--tempest-primary-600);--tempest-gray-50:#f8f9fb;--tempest-gray-100:#f1f3f6;--tempest-gray-200:#e4e7ec;--tempest-gray-300:#d0d5dd;--tempest-gray-400:#98a2b3;--tempest-gray-500:#667085;--tempest-gray-600:#475467;--tempest-gray-700:#344054;--tempest-gray-800:#1d2939;--tempest-gray-900:#101828;--tempest-bg:#fff;--tempest-surface:var(--tempest-gray-50);--tempest-surface-2:var(--tempest-gray-100);--tempest-surface-3:var(--tempest-gray-200);--tempest-border:var(--tempest-gray-200);--tempest-border-strong:var(--tempest-gray-300);--tempest-text:var(--tempest-gray-900);--tempest-text-muted:var(--tempest-gray-600);--tempest-text-subtle:var(--tempest-gray-500);--tempest-text-on-primary:#fff;--tempest-success:#15803d;--tempest-success-fg:#14532d;--tempest-success-bg:#dcfce7;--tempest-success-border:#86efac;--tempest-success-solid:#16a34a;--tempest-warning:#b45309;--tempest-warning-fg:#78350f;--tempest-warning-bg:#fef3c7;--tempest-warning-border:#fcd34d;--tempest-warning-solid:#d97706;--tempest-danger:#b91c1c;--tempest-danger-fg:#7f1d1d;--tempest-danger-bg:#fee2e2;--tempest-danger-border:#fca5a5;--tempest-danger-solid:#dc2626;--tempest-danger-hover:#991b1b;--tempest-info:#1d4ed8;--tempest-info-fg:#1e3a8a;--tempest-info-bg:#dbeafe;--tempest-info-border:#93c5fd;--tempest-info-solid:#2563eb;--tempest-focus-ring-color:#0052cc;--tempest-focus-ring-width:3px;--tempest-focus-ring-offset:2px;--tempest-selected-indicator:#0052cc;--tempest-radius-xs:2px;--tempest-radius-sm:4px;--tempest-radius-md:8px;--tempest-radius-lg:12px;--tempest-radius-xl:16px;--tempest-radius-2xl:24px;--tempest-radius-full:9999px;--tempest-shadow-xs:0 1px 2px #0f172a0a;--tempest-shadow-sm:0 1px 3px #0f172a14, 0 1px 2px #0f172a0a;--tempest-shadow-md:0 4px 12px #0f172a14, 0 2px 4px #0f172a0a;--tempest-shadow-lg:0 12px 32px #0f172a1f, 0 4px 8px #0f172a0f;--tempest-shadow-xl:0 24px 48px #0f172a2e, 0 8px 16px #0f172a14;--tempest-shadow-inner:inset 0 2px 4px #0f172a0f;--tempest-space-0:0px;--tempest-space-1:4px;--tempest-space-2:8px;--tempest-space-3:12px;--tempest-space-4:16px;--tempest-space-5:20px;--tempest-space-6:24px;--tempest-space-7:28px;--tempest-space-8:32px;--tempest-space-10:40px;--tempest-space-12:48px;--tempest-space-16:64px;--tempest-space-20:80px;--tempest-space-24:96px;--tempest-font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", sans-serif;--tempest-font-mono:ui-monospace, SFMono-Regular, "SF Mono", "Cascadia Code", Menlo, Consolas, "Liberation Mono", monospace;--tempest-font-display:var(--tempest-font-sans);--tempest-z-base:0;--tempest-z-raised:10;--tempest-z-dropdown:1000;--tempest-z-sticky:1020;--tempest-z-overlay:1050;--tempest-z-modal:1100;--tempest-z-popover:1150;--tempest-z-toast:1200;--tempest-z-tooltip:1300;--tempest-bp-xs:480px;--tempest-bp-sm:640px;--tempest-bp-md:768px;--tempest-bp-lg:1024px;--tempest-bp-xl:1280px;--tempest-bp-2xl:1536px;--tempest-chart-1:#2563eb;--tempest-chart-2:#16a34a;--tempest-chart-3:#f59e0b;--tempest-chart-4:#7c3aed;--tempest-chart-5:#ec4899;--tempest-chart-6:#06b6d4;--tempest-chart-7:#ea580c;--tempest-chart-8:#0f766e;--tempest-chart-sequential-1:#dde8fe;--tempest-chart-sequential-2:#acc8fe;--tempest-chart-sequential-3:#7aa7ff;--tempest-chart-sequential-4:#4983fc;--tempest-chart-sequential-5:#3667ce;--tempest-chart-sequential-6:#2b4e96;--tempest-chart-sequential-7:#25375a;--tempest-chart-diverging-1:#0f3ca1;--tempest-chart-diverging-2:#416eca;--tempest-chart-diverging-3:#7ba0e7;--tempest-chart-diverging-4:#bdd2f9;--tempest-chart-diverging-5:#e4e7ec;--tempest-chart-diverging-6:#f6c3bc;--tempest-chart-diverging-7:#de847a;--tempest-chart-diverging-8:#ba473f;--tempest-chart-diverging-9:#870f11;--tempest-chart-grid:var(--tempest-gray-200);--tempest-chart-axis:var(--tempest-gray-500);--tempest-code-comment:#5f666e;--tempest-code-punctuation:#5d6671;--tempest-code-string:#327243;--tempest-code-number:#9d5035;--tempest-code-keyword:#625baf;--tempest-code-literal:#9f4c4f;--tempest-code-function:#1a6c94;--tempest-code-tag:#974d72;--tempest-code-attribute:#127171;--tempest-code-property:#127171;--tempest-safe-area-top:env(safe-area-inset-top,0px);--tempest-safe-area-right:env(safe-area-inset-right,0px);--tempest-safe-area-bottom:env(safe-area-inset-bottom,0px);--tempest-safe-area-left:env(safe-area-inset-left,0px)}
|
|
3
|
+
[data-tempest-theme=dark]{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--tempest-primary-50:#0a1730;--tempest-primary-100:#0f2245;--tempest-primary-200:#133066;--tempest-primary-300:#1a4399;--tempest-primary-400:#2563eb;--tempest-primary-500:#3b82f6;--tempest-primary-600:#60a5fa;--tempest-primary-700:#93c5fd;--tempest-primary-800:#bfdbfe;--tempest-primary-900:#dbeafe;--tempest-primary:var(--tempest-primary-500);--tempest-primary-hover:var(--tempest-primary-600);--tempest-primary-active:var(--tempest-primary-700);--tempest-primary-soft:var(--tempest-primary-100);--tempest-primary-soft-hover:var(--tempest-primary-200);--tempest-primary-on-soft:var(--tempest-primary-700);--tempest-bg:#0b0d12;--tempest-surface:#14171f;--tempest-surface-2:#1d2230;--tempest-surface-3:#262d3f;--tempest-border:#2a3142;--tempest-border-strong:#3a4258;--tempest-text:#f1f3f8;--tempest-text-muted:#aab2c0;--tempest-text-subtle:#7b849a;--tempest-primary-foreground:#1f0606;--tempest-text-on-primary:var(--tempest-primary-foreground);--tempest-danger-on-solid:#1f0606;--tempest-info-on-solid:#1f0606;--tempest-success-on-solid:#1f0606;--tempest-warning-on-solid:#1f0606;--tempest-neutral-on-solid:#fff;--tempest-success-fg:#4ade80;--tempest-success-bg:#052e16;--tempest-success-border:#166534;--tempest-success-solid:#22c55e;--tempest-success:#4ade80;--tempest-warning-fg:#fbbf24;--tempest-warning-bg:#2c1c05;--tempest-warning-border:#78350f;--tempest-warning-solid:#f59e0b;--tempest-warning:#fbbf24;--tempest-danger-fg:#f87171;--tempest-danger-bg:#2c0a0a;--tempest-danger-border:#7f1d1d;--tempest-danger-solid:#ef4444;--tempest-danger:#f87171;--tempest-danger-hover:#f87171;--tempest-info-fg:#60a5fa;--tempest-info-bg:#0a1730;--tempest-info-border:#1e3a8a;--tempest-info-solid:#3b82f6;--tempest-info:#60a5fa;--tempest-focus-ring-color:#60a5fa;--tempest-selected-indicator:#60a5fa;--tempest-shadow-xs:0 1px 2px #0000004d;--tempest-shadow-sm:0 1px 3px #0006, 0 1px 2px #0003;--tempest-shadow-md:0 4px 12px #0006, 0 2px 4px #0003;--tempest-shadow-lg:0 12px 32px #00000080, 0 4px 8px #0000004d;--tempest-shadow-xl:0 24px 48px #0009, 0 8px 16px #0000004d;--tempest-chart-1:#60a5fa;--tempest-chart-2:#4ade80;--tempest-chart-3:#fbbf24;--tempest-chart-4:#a78bfa;--tempest-chart-5:#f472b6;--tempest-chart-6:#22d3ee;--tempest-chart-7:#fb923c;--tempest-chart-8:#2dd4bf;--tempest-chart-sequential-1:#172849;--tempest-chart-sequential-2:#1b3c83;--tempest-chart-sequential-3:#2453b9;--tempest-chart-sequential-4:#376fe5;--tempest-chart-sequential-5:#5b90fb;--tempest-chart-sequential-6:#8cb2fa;--tempest-chart-sequential-7:#bad2fe;--tempest-chart-diverging-1:#1543a8;--tempest-chart-diverging-2:#416eca;--tempest-chart-diverging-3:#7599e0;--tempest-chart-diverging-4:#b0c5ec;--tempest-chart-diverging-5:#262d3f;--tempest-chart-diverging-6:#e8b6af;--tempest-chart-diverging-7:#d77e74;--tempest-chart-diverging-8:#ba473f;--tempest-chart-diverging-9:#94020c;--tempest-chart-grid:var(--tempest-gray-300);--tempest-chart-axis:var(--tempest-gray-600);--tempest-code-comment:#838b93;--tempest-code-punctuation:#818b95;--tempest-code-string:#589866;--tempest-code-number:#c57558;--tempest-code-keyword:#8580d8;--tempest-code-literal:#c87172;--tempest-code-function:#2893c6;--tempest-code-tag:#c07197;--tempest-code-attribute:#349897;--tempest-code-property:#349897}
|
|
4
4
|
:root{--tempest-text-2xs:10px;--tempest-text-xs:12px;--tempest-text-sm:13px;--tempest-text-base:14px;--tempest-text-md:15px;--tempest-text-lg:16px;--tempest-text-xl:18px;--tempest-text-2xl:20px;--tempest-text-3xl:24px;--tempest-text-4xl:30px;--tempest-text-5xl:36px;--tempest-text-6xl:48px;--tempest-leading-none:1;--tempest-leading-tight:1.2;--tempest-leading-snug:1.35;--tempest-leading-normal:1.5;--tempest-leading-relaxed:1.65;--tempest-leading-loose:1.9;--tempest-weight-regular:400;--tempest-weight-medium:500;--tempest-weight-semibold:600;--tempest-weight-bold:700;--tempest-weight-extrabold:800;--tempest-tracking-tight:-.02em;--tempest-tracking-normal:0;--tempest-tracking-wide:.025em;--tempest-tracking-wider:.05em;--tempest-tracking-widest:.1em;--tempest-text-fluid-sm:clamp(13px, 12px + .2vw, 15px);--tempest-text-fluid-base:clamp(14px, 13px + .3vw, 16px);--tempest-text-fluid-lg:clamp(16px, 14px + .5vw, 20px);--tempest-text-fluid-xl:clamp(18px, 15px + .8vw, 24px);--tempest-text-fluid-2xl:clamp(20px, 16px + 1.2vw, 30px);--tempest-text-fluid-3xl:clamp(24px, 18px + 2vw, 40px);--tempest-text-fluid-4xl:clamp(28px, 20px + 3vw, 56px);--tempest-text-fluid-5xl:clamp(32px, 24px + 4vw, 72px);--tempest-text-fluid-6xl:clamp(40px, 28px + 5vw, 96px);--tempest-duration-instant:0s;--tempest-duration-fast:.12s;--tempest-duration-base:.18s;--tempest-duration-slow:.28s;--tempest-duration-slower:.42s;--tempest-ease-linear:linear;--tempest-ease-in:cubic-bezier(.4, 0, 1, 1);--tempest-ease-out:cubic-bezier(0, 0, .2, 1);--tempest-ease-in-out:cubic-bezier(.4, 0, .2, 1);--tempest-ease-emphasized:cubic-bezier(.2, 0, 0, 1);--tempest-ease-bounce:cubic-bezier(.34, 1.56, .64, 1);--tempest-transition-color:color var(--tempest-duration-fast) var(--tempest-ease-out), background-color var(--tempest-duration-fast) var(--tempest-ease-out), border-color var(--tempest-duration-fast) var(--tempest-ease-out);--tempest-transition-shadow:box-shadow var(--tempest-duration-base) var(--tempest-ease-out);--tempest-transition-transform:transform var(--tempest-duration-fast) var(--tempest-ease-out);--tempest-transition-base:color var(--tempest-duration-fast) var(--tempest-ease-out), background-color var(--tempest-duration-fast) var(--tempest-ease-out), border-color var(--tempest-duration-fast) var(--tempest-ease-out), box-shadow var(--tempest-duration-base) var(--tempest-ease-out), transform var(--tempest-duration-fast) var(--tempest-ease-out), opacity var(--tempest-duration-fast) var(--tempest-ease-out)}
|
|
5
5
|
@media (prefers-reduced-motion:reduce){:root{--tempest-duration-fast:.01ms;--tempest-duration-base:.01ms;--tempest-duration-slow:.01ms;--tempest-duration-slower:.01ms}}
|
|
6
6
|
:root,[data-tempest-density=comfortable]{--tempest-control-height-xs:24px;--tempest-control-height-sm:32px;--tempest-control-height-md:40px;--tempest-control-height-lg:48px;--tempest-control-height-xl:56px;--tempest-control-padding-xs:var(--tempest-space-2);--tempest-control-padding-sm:var(--tempest-space-3);--tempest-control-padding-md:var(--tempest-space-4);--tempest-control-padding-lg:var(--tempest-space-5);--tempest-control-padding-xl:var(--tempest-space-6);--tempest-control-font-xs:var(--tempest-text-xs);--tempest-control-font-sm:var(--tempest-text-sm);--tempest-control-font-md:var(--tempest-text-base);--tempest-control-font-lg:var(--tempest-text-lg);--tempest-control-font-xl:var(--tempest-text-xl);--tempest-control-radius:var(--tempest-radius-md);--tempest-control-gap:var(--tempest-space-2)}
|
package/dist/styles/forms.css
CHANGED
|
@@ -251,6 +251,10 @@
|
|
|
251
251
|
.tempest_error_sw9MU .tempest_select_cjdcr:focus{box-shadow:0 0 0 var(--tempest-focus-ring-width) color-mix(in srgb, var(--tempest-danger) 25%, transparent)}
|
|
252
252
|
.tempest_helper_frosK{font-size:var(--tempest-text-xs);color:var(--tempest-text-muted);line-height:var(--tempest-leading-snug)}
|
|
253
253
|
.tempest_errorText_-zd6i{font-size:var(--tempest-text-xs);color:var(--tempest-danger);line-height:var(--tempest-leading-snug)}
|
|
254
|
+
.tempest_chipWrapper_5keyI{display:inline-flex}
|
|
255
|
+
.tempest_chip_r4NVm{width:auto}
|
|
256
|
+
.tempest_chip_r4NVm .tempest_select_cjdcr{width:auto;height:var(--tempest-control-height-sm);padding:0 30px 0 var(--tempest-space-3);border-radius:var(--tempest-radius-full);background-color:var(--tempest-surface);font-size:var(--tempest-text-sm);box-shadow:none}
|
|
257
|
+
.tempest_chip_r4NVm .tempest_caret_MdCao{right:10px}
|
|
254
258
|
.tempest_pad_mrFAb{gap:var(--tempest-space-2);flex-direction:column;display:inline-flex}
|
|
255
259
|
.tempest_canvas_Jbknm{color:var(--tempest-text);background-color:var(--tempest-bg);border:1px dashed var(--tempest-border-strong);border-radius:var(--tempest-radius-md);cursor:crosshair}
|
|
256
260
|
.tempest_canvas_Jbknm:focus-visible{outline:var(--tempest-focus-ring-width) solid var(--tempest-focus-ring-color);outline-offset:var(--tempest-focus-ring-offset)}
|
|
@@ -114,7 +114,7 @@
|
|
|
114
114
|
.tempest_group_mYyFC.tempest_md_2ixuM .tempest_segment_cu-EL{font-size:var(--tempest-text-sm);min-height:32px;padding:6px 12px}
|
|
115
115
|
.tempest_group_mYyFC.tempest_lg_2Kt7- .tempest_segment_cu-EL{font-size:var(--tempest-text-md);min-height:40px;padding:8px 14px}
|
|
116
116
|
.tempest_segment_cu-EL:hover{color:var(--tempest-text)}
|
|
117
|
-
.tempest_segment_cu-EL.tempest_active_GmyKg{background:var(--tempest-
|
|
117
|
+
.tempest_segment_cu-EL.tempest_active_GmyKg{background:var(--tempest-primary-soft);color:var(--tempest-primary-on-soft);box-shadow:inset 0 0 0 2px var(--tempest-selected-indicator), var(--tempest-shadow-xs,0 1px 2px #00000014)}
|
|
118
118
|
.tempest_segment_cu-EL:disabled{opacity:.4;cursor:not-allowed}
|
|
119
119
|
.tempest_icon_9h6GK{align-items:center;display:inline-flex}
|
|
120
120
|
.tempest_label_mS17q{line-height:1}
|