@burdenoff/fe-libs 2026.1022.2 → 2026.1022.3
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.
|
@@ -12,6 +12,16 @@ export interface LanguageSwitcherProps {
|
|
|
12
12
|
/** Show as icon only (for small screens) */
|
|
13
13
|
compact?: boolean;
|
|
14
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* Accessible name of the switcher's trigger button.
|
|
17
|
+
*
|
|
18
|
+
* WCAG 2.5.3 (Label in Name; axe `label-content-name-mismatch`): when the
|
|
19
|
+
* trigger shows the current language code, its accessible name must contain
|
|
20
|
+
* that visible text, so a speech-input user who says "click EN" hits it. The
|
|
21
|
+
* name therefore leads with the code ("EN, Change language"). The compact
|
|
22
|
+
* trigger shows only a globe icon, so its name stays the plain action label.
|
|
23
|
+
*/
|
|
24
|
+
export declare function languageTriggerLabel(currentCode: string | undefined, changeLabel: string, compact: boolean): string;
|
|
15
25
|
/**
|
|
16
26
|
* LanguageSwitcher Component
|
|
17
27
|
*
|
|
@@ -3,46 +3,50 @@ import { useAssistantControl as t } from "../shared/assistant/appControls/useAss
|
|
|
3
3
|
import { useEffect as n, useMemo as r, useRef as i, useState as a } from "react";
|
|
4
4
|
import { Fragment as o, jsx as s, jsxs as c } from "react/jsx-runtime";
|
|
5
5
|
//#region src/chrome/LanguageSwitcher.tsx
|
|
6
|
-
|
|
7
|
-
let
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
function l(e, t, n) {
|
|
7
|
+
let r = e?.trim().toUpperCase();
|
|
8
|
+
return n || !r ? t : `${r}, ${t}`;
|
|
9
|
+
}
|
|
10
|
+
var u = ({ languages: u, currentLanguage: d, onLanguageChange: f, compact: p = !1 }) => {
|
|
11
|
+
let m = e(), [h, g] = a(!1), _ = i(null), v = u.find((e) => e.code === d) || u[0], y = i({
|
|
12
|
+
languages: u,
|
|
13
|
+
currentLanguage: d,
|
|
14
|
+
onLanguageChange: f
|
|
11
15
|
});
|
|
12
|
-
|
|
13
|
-
languages:
|
|
14
|
-
currentLanguage:
|
|
15
|
-
onLanguageChange:
|
|
16
|
+
y.current = {
|
|
17
|
+
languages: u,
|
|
18
|
+
currentLanguage: d,
|
|
19
|
+
onLanguageChange: f
|
|
16
20
|
};
|
|
17
|
-
let
|
|
18
|
-
t("language", r(() =>
|
|
19
|
-
languages: () =>
|
|
21
|
+
let b = f !== void 0;
|
|
22
|
+
t("language", r(() => b ? {
|
|
23
|
+
languages: () => y.current.languages.map((e) => ({
|
|
20
24
|
code: e.code,
|
|
21
25
|
label: e.nativeName || e.name
|
|
22
26
|
})),
|
|
23
|
-
current: () =>
|
|
27
|
+
current: () => y.current.currentLanguage,
|
|
24
28
|
set: (e) => {
|
|
25
|
-
let { languages: t, currentLanguage: n, onLanguageChange: r } =
|
|
29
|
+
let { languages: t, currentLanguage: n, onLanguageChange: r } = y.current, i = t.find((t) => t.code.toLowerCase() === e.toLowerCase());
|
|
26
30
|
return !i || !r ? { status: "failed" } : i.code === n ? { status: "already" } : (r(i), { status: "done" });
|
|
27
31
|
}
|
|
28
|
-
} : null, [
|
|
32
|
+
} : null, [b])), n(() => {
|
|
29
33
|
let e = (e) => {
|
|
30
|
-
|
|
34
|
+
_.current && !_.current.contains(e.target) && g(!1);
|
|
31
35
|
};
|
|
32
|
-
if (
|
|
33
|
-
}, [
|
|
34
|
-
let
|
|
35
|
-
|
|
36
|
+
if (h) return document.addEventListener("mousedown", e), () => document.removeEventListener("mousedown", e);
|
|
37
|
+
}, [h]);
|
|
38
|
+
let x = (e) => {
|
|
39
|
+
f && f(e), g(!1);
|
|
36
40
|
};
|
|
37
41
|
return /* @__PURE__ */ c("div", {
|
|
38
42
|
className: "relative",
|
|
39
|
-
ref:
|
|
43
|
+
ref: _,
|
|
40
44
|
children: [/* @__PURE__ */ s("button", {
|
|
41
|
-
onClick: () =>
|
|
42
|
-
className: `flex items-center gap-2 px-3 py-2 rounded-button hover:bg-bg-sunken transition-colors ${
|
|
43
|
-
"aria-label":
|
|
44
|
-
"aria-expanded":
|
|
45
|
-
children:
|
|
45
|
+
onClick: () => g(!h),
|
|
46
|
+
className: `flex items-center gap-2 px-3 py-2 rounded-button hover:bg-bg-sunken transition-colors ${h ? "bg-bg-sunken" : ""}`,
|
|
47
|
+
"aria-label": l(v?.code, m("languageSwitcher.change", "Change language"), p),
|
|
48
|
+
"aria-expanded": h,
|
|
49
|
+
children: p ? /* @__PURE__ */ s("svg", {
|
|
46
50
|
className: "size-5 text-text-primary",
|
|
47
51
|
fill: "none",
|
|
48
52
|
stroke: "currentColor",
|
|
@@ -55,9 +59,9 @@ var l = ({ languages: l, currentLanguage: u, onLanguageChange: d, compact: f = !
|
|
|
55
59
|
})
|
|
56
60
|
}) : /* @__PURE__ */ c(o, { children: [/* @__PURE__ */ s("span", {
|
|
57
61
|
className: "text-body-sm font-medium text-text-primary uppercase",
|
|
58
|
-
children:
|
|
62
|
+
children: v?.code.toUpperCase()
|
|
59
63
|
}), /* @__PURE__ */ s("svg", {
|
|
60
|
-
className: `w-4 h-4 text-text-secondary transition-transform ${
|
|
64
|
+
className: `w-4 h-4 text-text-secondary transition-transform ${h ? "rotate-180" : ""}`,
|
|
61
65
|
fill: "none",
|
|
62
66
|
stroke: "currentColor",
|
|
63
67
|
viewBox: "0 0 24 24",
|
|
@@ -68,19 +72,19 @@ var l = ({ languages: l, currentLanguage: u, onLanguageChange: d, compact: f = !
|
|
|
68
72
|
d: "M19 9l-7 7-7-7"
|
|
69
73
|
})
|
|
70
74
|
})] })
|
|
71
|
-
}),
|
|
75
|
+
}), h && /* @__PURE__ */ c("div", {
|
|
72
76
|
className: "absolute right-0 mt-2 w-[calc(100vw-1.5rem)] sm:w-64 max-w-64 bg-bg-elevated border border-border-subtle rounded-card shadow-[var(--shadow-elevation-4)] z-50 py-2 overflow-hidden animate-in fade-in-0 zoom-in-95 slide-in-from-top-2 duration-200",
|
|
73
77
|
children: [/* @__PURE__ */ s("div", {
|
|
74
78
|
className: "px-4 py-2 border-b border-border-subtle",
|
|
75
79
|
children: /* @__PURE__ */ s("p", {
|
|
76
80
|
className: "text-[11px] font-medium text-text-muted uppercase tracking-wider",
|
|
77
|
-
children:
|
|
81
|
+
children: m("languageSwitcher.title", "Select Language")
|
|
78
82
|
})
|
|
79
83
|
}), /* @__PURE__ */ s("div", {
|
|
80
84
|
className: "py-1 max-h-96 overflow-y-auto",
|
|
81
|
-
children:
|
|
82
|
-
onClick: () =>
|
|
83
|
-
className: `w-full flex items-center gap-3 px-4 py-2.5 text-body-sm transition-colors ${e.code ===
|
|
85
|
+
children: u.map((e) => /* @__PURE__ */ c("button", {
|
|
86
|
+
onClick: () => x(e),
|
|
87
|
+
className: `w-full flex items-center gap-3 px-4 py-2.5 text-body-sm transition-colors ${e.code === d ? "bg-[var(--color-accent-soft)] text-text-primary font-medium" : "text-text-primary hover:bg-bg-sunken"}`,
|
|
84
88
|
children: [
|
|
85
89
|
e.flag && /* @__PURE__ */ s("span", {
|
|
86
90
|
className: "text-xl flex-shrink-0",
|
|
@@ -96,7 +100,7 @@ var l = ({ languages: l, currentLanguage: u, onLanguageChange: d, compact: f = !
|
|
|
96
100
|
children: e.name
|
|
97
101
|
})]
|
|
98
102
|
}),
|
|
99
|
-
e.code ===
|
|
103
|
+
e.code === d && /* @__PURE__ */ s("svg", {
|
|
100
104
|
className: "size-5 text-action-primary-bg flex-shrink-0",
|
|
101
105
|
fill: "currentColor",
|
|
102
106
|
viewBox: "0 0 20 20",
|
|
@@ -113,4 +117,4 @@ var l = ({ languages: l, currentLanguage: u, onLanguageChange: d, compact: f = !
|
|
|
113
117
|
});
|
|
114
118
|
};
|
|
115
119
|
//#endregion
|
|
116
|
-
export {
|
|
120
|
+
export { u as LanguageSwitcher };
|
|
@@ -83,7 +83,7 @@ function g({ children: n, defaultMode: r = "system", defaultBrand: l = "default"
|
|
|
83
83
|
let n = document.documentElement;
|
|
84
84
|
if (n.setAttribute("data-theme", P), n.setAttribute("data-brand", t(x)), n.setAttribute("data-density", L), n.setAttribute("data-typography", R), n.setAttribute("data-glass", z), n.toggleAttribute("data-reduce-motion", B), I === "dark" ? n.classList.add("dark") : n.classList.remove("dark"), N) {
|
|
85
85
|
let e = N.accent;
|
|
86
|
-
n.style.setProperty("--color-action-primary-bg", e), n.style.setProperty("--color-action-primary-bgHover", `color-mix(in oklab, ${e} 84%, black)`), n.style.setProperty("--color-action-primary-bgActive", `color-mix(in oklab, ${e} 70%, black)`),
|
|
86
|
+
n.style.setProperty("--color-action-primary-bg", e), n.style.setProperty("--color-action-primary-bgHover", `color-mix(in oklab, ${e} 84%, black)`), n.style.setProperty("--color-action-primary-bgActive", `color-mix(in oklab, ${e} 70%, black)`), n.style.setProperty("--color-action-primary-text", p(e) ? "#0a0a0a" : "#ffffff");
|
|
87
87
|
} else n.style.removeProperty("--color-action-primary-bg"), n.style.removeProperty("--color-action-primary-bgHover"), n.style.removeProperty("--color-action-primary-bgActive"), n.style.removeProperty("--color-action-primary-text");
|
|
88
88
|
let r = () => {
|
|
89
89
|
let t = getComputedStyle(n).getPropertyValue("--color-bg-canvas").trim();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@burdenoff/fe-libs",
|
|
3
|
-
"version": "2026.1022.
|
|
3
|
+
"version": "2026.1022.3",
|
|
4
4
|
"description": "Burdenoff frontend primitives and domain libraries",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -330,7 +330,7 @@
|
|
|
330
330
|
"test:package-livekit-optional": "node scripts/validate-livekit-optional.mjs",
|
|
331
331
|
"verify:package": "node scripts/verify-package-contents.mjs",
|
|
332
332
|
"test:handsfree-browser": "node scripts/handsfree-browser-run.mjs",
|
|
333
|
-
"test": "bun test scripts/graphql-schema-drift/__tests__ scripts/a11y-audit/__tests__ scripts/i18n/__tests__ src/credentials src/connections src/storage src/shared/assistant src/shared/feature-flags src/platform-pages src/admin-overview src/shared/components src/shared/graphql/links/sse-link.test.ts src/shared/graphql/fetch.test.ts src/shared/graphql/prepareWorkspaceRequest.test.ts src/shared/graphql/client.test.ts src/shared/utils/apollo.test.ts src/shared/utils/canvasTokens.test.ts src/shared/graphql/tourWorkspaceAuth.test.ts src/shared/config/gatewayUrls.test.ts src/shared/config/authBridgeUrls.test.ts src/shared/config/shellRoutes.test.ts src/shared/config/gatewayFallback.test.ts scripts/__tests__ src/shared/config/products.test.ts src/shared/config/docsUrls.test.ts src/shared/config/productSlug.test.ts src/shared/hooks/shell/useProducts.test.ts src/shared/hooks/shell/useGlobalSearch.test.ts src/shared/providers/shell/brandAttribute.test.ts src/chrome/ProductSwitcher.test.ts src/shared/utils/backendErrors.test.ts src/shared/utils/gatewayFetchRewrite.test.ts src/shared/utils/authCookie.test.ts src/shared/utils/redirectAllowlist.test.ts src/shared/providers/shell/ProfileStorageManager.test.ts src/shared/providers/AppShellProvider.test.ts src/shared/providers/shell/interpolate.test.ts src/shared/providers/shell/resolveTranslation.test.ts src/shared/providers/shell/I18nProvider.render.test.tsx src/shared/providers/shell/I18nProvider.client.test.tsx src/shared/providers/shell/translationStore.test.ts src/shared/providers/shell/translationLayers.test.ts src/shared/providers/shell/directionMode.test.ts src/shared/providers/shell/authProvider/ssoRelay.test.ts src/shared/providers/shell/authProvider/useAuthActions.signOut.test.tsx src/shared/providers/shell/personaSurfaceRemote.test.ts src/shared/providers/shell/workspaceSwitch.client.test.tsx src/shared/events/sinks/RybbitSink.test.ts src/shared/events/sinks/RybbitSink.client.test.tsx src/shell-native src/shared/native src/shared/navigation src/shared/tours src/chrome/__tests__ src/ui/__tests__",
|
|
333
|
+
"test": "bun test scripts/graphql-schema-drift/__tests__ scripts/a11y-audit/__tests__ scripts/i18n/__tests__ src/credentials src/connections src/storage src/shared/assistant src/shared/feature-flags src/platform-pages src/admin-overview src/shared/components src/shared/graphql/links/sse-link.test.ts src/shared/graphql/fetch.test.ts src/shared/graphql/prepareWorkspaceRequest.test.ts src/shared/graphql/client.test.ts src/shared/utils/apollo.test.ts src/shared/utils/canvasTokens.test.ts src/shared/utils/brandContrast.test.ts src/shared/graphql/tourWorkspaceAuth.test.ts src/shared/config/gatewayUrls.test.ts src/shared/config/authBridgeUrls.test.ts src/shared/config/shellRoutes.test.ts src/shared/config/gatewayFallback.test.ts scripts/__tests__ src/shared/config/products.test.ts src/shared/config/docsUrls.test.ts src/shared/config/productSlug.test.ts src/shared/hooks/shell/useProducts.test.ts src/shared/hooks/shell/useGlobalSearch.test.ts src/shared/providers/shell/brandAttribute.test.ts src/chrome/ProductSwitcher.test.ts src/shared/utils/backendErrors.test.ts src/shared/utils/gatewayFetchRewrite.test.ts src/shared/utils/authCookie.test.ts src/shared/utils/redirectAllowlist.test.ts src/shared/providers/shell/ProfileStorageManager.test.ts src/shared/providers/AppShellProvider.test.ts src/shared/providers/shell/interpolate.test.ts src/shared/providers/shell/resolveTranslation.test.ts src/shared/providers/shell/I18nProvider.render.test.tsx src/shared/providers/shell/I18nProvider.client.test.tsx src/shared/providers/shell/translationStore.test.ts src/shared/providers/shell/translationLayers.test.ts src/shared/providers/shell/directionMode.test.ts src/shared/providers/shell/authProvider/ssoRelay.test.ts src/shared/providers/shell/authProvider/useAuthActions.signOut.test.tsx src/shared/providers/shell/personaSurfaceRemote.test.ts src/shared/providers/shell/workspaceSwitch.client.test.tsx src/shared/events/sinks/RybbitSink.test.ts src/shared/events/sinks/RybbitSink.client.test.tsx src/shell-native src/shared/native src/shared/navigation src/shared/tours src/chrome/__tests__ src/ui/__tests__",
|
|
334
334
|
"sanity": "bash scripts/build-limits.sh --gate bash -c 'bun run lint:sanity && bun run format && bun run type:check && bun run test && bun run build && bun run verify:package'",
|
|
335
335
|
"switch:status": "bun scripts/deps-mode.ts status",
|
|
336
336
|
"switch:remote": "bun scripts/deps-mode.ts remote",
|
|
@@ -1,6 +1,25 @@
|
|
|
1
|
-
/* FluidGrids brand overrides
|
|
1
|
+
/* FluidGrids brand overrides
|
|
2
|
+
*
|
|
3
|
+
* WCAG 2.1 AA (1.4.3), parity G23. The accent is both the primary-button fill
|
|
4
|
+
* (white label) and, through --color-accent-primary, small accent text on the
|
|
5
|
+
* canvas, so one cyan cannot serve both themes:
|
|
6
|
+
* - light: cyan-700 #0E7490 carries a white label at 5.36:1. The former
|
|
7
|
+
* cyan-600 #0891B2 measured 3.68:1 and failed axe color-contrast on every
|
|
8
|
+
* primary button of the landing page.
|
|
9
|
+
* - dark: cyan-600 stays (5.2:1 as accent text on the #0A0E16 canvas), and
|
|
10
|
+
* the button label turns dark (5.7:1); hover/active step LIGHTER so the
|
|
11
|
+
* dark label keeps its contrast in every state.
|
|
12
|
+
*/
|
|
2
13
|
[data-brand="fluidgrids"] {
|
|
14
|
+
--color-action-primary-bg: #0E7490;
|
|
15
|
+
--color-action-primary-bgHover: #155E75;
|
|
16
|
+
--color-action-primary-bgActive: #164E63;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
:root.dark[data-brand="fluidgrids"],
|
|
20
|
+
[data-brand="fluidgrids"].dark {
|
|
3
21
|
--color-action-primary-bg: #0891B2;
|
|
4
|
-
--color-action-primary-bgHover: #
|
|
5
|
-
--color-action-primary-bgActive: #
|
|
22
|
+
--color-action-primary-bgHover: #06B6D4;
|
|
23
|
+
--color-action-primary-bgActive: #22D3EE;
|
|
24
|
+
--color-action-primary-text: #0A0E16;
|
|
6
25
|
}
|