rl-core-front 0.19.9 → 0.19.10
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/package.json
CHANGED
|
@@ -549,12 +549,19 @@ export function AppShell({
|
|
|
549
549
|
<Menu className="h-5 w-5" />
|
|
550
550
|
</Button>
|
|
551
551
|
|
|
552
|
-
|
|
552
|
+
{/* A marca leva para a raiz do projeto: é o gesto que todo site tem,
|
|
553
|
+
e sem ele o caminho de volta ao início é achar "Painel" no menu. */}
|
|
554
|
+
<button
|
|
555
|
+
type="button"
|
|
556
|
+
onClick={() => go("/")}
|
|
557
|
+
aria-label={brand.name || t("app.name")}
|
|
558
|
+
className="flex cursor-pointer items-center gap-2 rounded-lg px-1.5 py-1 transition-colors hover:bg-accent"
|
|
559
|
+
>
|
|
553
560
|
{brand.mark}
|
|
554
561
|
<span className="hidden text-lg font-extrabold sm:block">
|
|
555
562
|
{brand.name}
|
|
556
563
|
</span>
|
|
557
|
-
</
|
|
564
|
+
</button>
|
|
558
565
|
|
|
559
566
|
<div className="flex-1" />
|
|
560
567
|
|
|
@@ -623,10 +630,15 @@ export function AppShell({
|
|
|
623
630
|
onClick={() => setMobileOpen(false)}
|
|
624
631
|
/>
|
|
625
632
|
<aside className="absolute left-0 top-0 flex h-full w-64 flex-col border-r border-border bg-card">
|
|
626
|
-
<
|
|
633
|
+
<button
|
|
634
|
+
type="button"
|
|
635
|
+
onClick={() => go("/")}
|
|
636
|
+
aria-label={brand.name || t("app.name")}
|
|
637
|
+
className="flex h-16 w-full cursor-pointer items-center gap-2 border-b border-border px-4 text-left transition-colors hover:bg-accent"
|
|
638
|
+
>
|
|
627
639
|
{brand.mark}
|
|
628
640
|
<span className="text-lg font-extrabold">{brand.name}</span>
|
|
629
|
-
</
|
|
641
|
+
</button>
|
|
630
642
|
<NavContent
|
|
631
643
|
mini={false}
|
|
632
644
|
nav={nav}
|
|
@@ -89,7 +89,23 @@ export function useTabState<T extends string>(
|
|
|
89
89
|
if (!hydrated) {
|
|
90
90
|
return;
|
|
91
91
|
}
|
|
92
|
-
|
|
92
|
+
|
|
93
|
+
/*
|
|
94
|
+
A URL de **agora**, e não a do render que criou este efeito: chegando por
|
|
95
|
+
um link, o Next troca a querystring no commit, depois que esta tela já
|
|
96
|
+
renderizou lendo a URL anterior. Aí `tab` ainda é o do armazenamento, e
|
|
97
|
+
escrevê-lo apagaria justamente a aba que o link pediu — a tela abria na
|
|
98
|
+
aba de ontem com a URL reescrita para ela, e só um F5 acertava.
|
|
99
|
+
|
|
100
|
+
Aba válida na URL manda, sempre: não há o que espelhar.
|
|
101
|
+
*/
|
|
102
|
+
const atual = readUrlParam(param);
|
|
103
|
+
|
|
104
|
+
if (atual !== null && (known.current as readonly string[]).includes(atual)) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (tab !== undefined) {
|
|
93
109
|
writeUrlTab(tab);
|
|
94
110
|
}
|
|
95
111
|
}, [hydrated, tab, param, writeUrlTab]);
|
|
@@ -5,7 +5,51 @@ import { useCallback, useSyncExternalStore } from "react";
|
|
|
5
5
|
/** Quem lê a querystring, para saber que ela mudou por aqui. */
|
|
6
6
|
const listeners = new Set<() => void>();
|
|
7
7
|
|
|
8
|
+
const notify = (): void => {
|
|
9
|
+
for (const listener of listeners) {
|
|
10
|
+
listener();
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
/** A instrumentação do histórico é instalada uma vez só, no primeiro leitor. */
|
|
15
|
+
let watchingHistory = false;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Faz `pushState` e `replaceState` avisarem quem lê a querystring.
|
|
19
|
+
*
|
|
20
|
+
* Nenhum dos dois dispara evento — `popstate` é só do "voltar" do navegador —,
|
|
21
|
+
* e **a navegação do Next é `pushState`**: o App Router troca a URL num efeito
|
|
22
|
+
* (`HistoryUpdater`) depois que a tela nova já renderizou. Sem este aviso,
|
|
23
|
+
* quem abriu a tela por um link com `?tab=` lia a URL *anterior*, caía no
|
|
24
|
+
* valor guardado e ficava nele — a URL dizia uma aba e a tela mostrava outra,
|
|
25
|
+
* e só um F5 acertava.
|
|
26
|
+
*
|
|
27
|
+
* Instrumentar o histórico, e não `useSearchParams` do Next: aquele não
|
|
28
|
+
* enxerga o `replaceState` que este arquivo faz (o `?filter=`, o `?month=`),
|
|
29
|
+
* e obrigaria todo consumidor a nascer dentro de um `<Suspense>`.
|
|
30
|
+
*/
|
|
31
|
+
const watchHistory = (): void => {
|
|
32
|
+
if (watchingHistory || typeof window === "undefined") {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
watchingHistory = true;
|
|
37
|
+
|
|
38
|
+
for (const method of ["pushState", "replaceState"] as const) {
|
|
39
|
+
const original = window.history[method];
|
|
40
|
+
|
|
41
|
+
window.history[method] = function patched(
|
|
42
|
+
this: History,
|
|
43
|
+
...args: Parameters<History["pushState"]>
|
|
44
|
+
): void {
|
|
45
|
+
original.apply(this, args);
|
|
46
|
+
notify();
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
8
51
|
const subscribe = (onChange: () => void): (() => void) => {
|
|
52
|
+
watchHistory();
|
|
9
53
|
listeners.add(onChange);
|
|
10
54
|
// O "voltar" do navegador também troca o valor, e esse não passa por aqui.
|
|
11
55
|
window.addEventListener("popstate", onChange);
|
|
@@ -28,6 +72,12 @@ export const readUrlParam = (name: string): string | null =>
|
|
|
28
72
|
* da tela.
|
|
29
73
|
*/
|
|
30
74
|
export const writeUrlParam = (name: string, value: string | null): void => {
|
|
75
|
+
// Escrever pode acontecer antes de qualquer leitor montar — e é o
|
|
76
|
+
// `replaceState` instrumentado que avisa. Sem esta linha, o aviso dependeria
|
|
77
|
+
// da ordem em que as coisas montaram, que é o tipo de laço que funciona até
|
|
78
|
+
// o dia em que alguém escreve primeiro.
|
|
79
|
+
watchHistory();
|
|
80
|
+
|
|
31
81
|
const params = new URLSearchParams(window.location.search);
|
|
32
82
|
|
|
33
83
|
if (value === null) {
|
|
@@ -43,11 +93,8 @@ export const writeUrlParam = (name: string, value: string | null): void => {
|
|
|
43
93
|
query ? `${window.location.pathname}?${query}` : window.location.pathname,
|
|
44
94
|
);
|
|
45
95
|
|
|
46
|
-
//
|
|
47
|
-
//
|
|
48
|
-
for (const listener of listeners) {
|
|
49
|
-
listener();
|
|
50
|
-
}
|
|
96
|
+
// O aviso vem do `replaceState` instrumentado (`watchHistory`), que avisa
|
|
97
|
+
// por qualquer caminho — inclusive pelas trocas de URL do próprio Next.
|
|
51
98
|
};
|
|
52
99
|
|
|
53
100
|
/**
|