@neetru/sdk 3.4.0 → 3.4.2
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/CHANGELOG.md +31 -0
- package/dist/ai.d.cts +1 -1
- package/dist/ai.d.ts +1 -1
- package/dist/auth.cjs +230 -38
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.d.cts +1 -1
- package/dist/auth.d.ts +1 -1
- package/dist/auth.mjs +230 -38
- package/dist/auth.mjs.map +1 -1
- package/dist/build-guard.cjs +41 -6
- package/dist/build-guard.cjs.map +1 -1
- package/dist/build-guard.d.cts +24 -1
- package/dist/build-guard.d.ts +24 -1
- package/dist/build-guard.mjs +40 -7
- package/dist/build-guard.mjs.map +1 -1
- package/dist/catalog.d.cts +1 -1
- package/dist/catalog.d.ts +1 -1
- package/dist/checkout.d.cts +1 -1
- package/dist/checkout.d.ts +1 -1
- package/dist/db-react.d.cts +1 -1
- package/dist/db-react.d.ts +1 -1
- package/dist/db.cjs +230 -38
- package/dist/db.cjs.map +1 -1
- package/dist/db.d.cts +1 -1
- package/dist/db.d.ts +1 -1
- package/dist/db.mjs +230 -38
- package/dist/db.mjs.map +1 -1
- package/dist/entitlements.d.cts +1 -1
- package/dist/entitlements.d.ts +1 -1
- package/dist/firestore-compat.d.cts +1 -1
- package/dist/firestore-compat.d.ts +1 -1
- package/dist/index.cjs +231 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.mjs +231 -39
- package/dist/index.mjs.map +1 -1
- package/dist/mocks.d.cts +1 -1
- package/dist/mocks.d.ts +1 -1
- package/dist/notifications.d.cts +1 -1
- package/dist/notifications.d.ts +1 -1
- package/dist/react.cjs +593 -31
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +97 -2
- package/dist/react.d.ts +97 -2
- package/dist/react.mjs +590 -31
- package/dist/react.mjs.map +1 -1
- package/dist/support.d.cts +1 -1
- package/dist/support.d.ts +1 -1
- package/dist/telemetry.d.cts +1 -1
- package/dist/telemetry.d.ts +1 -1
- package/dist/{types-DdJyqBy-.d.ts → types-BlOLDMR0.d.ts} +79 -6
- package/dist/{types-BoFSCHF_.d.cts → types-D-QdG502.d.cts} +79 -6
- package/dist/usage.d.cts +1 -1
- package/dist/usage.d.ts +1 -1
- package/dist/webhooks.d.cts +1 -1
- package/dist/webhooks.d.ts +1 -1
- package/package.json +1 -1
package/dist/react.mjs
CHANGED
|
@@ -1,7 +1,566 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as React2 from 'react';
|
|
2
2
|
|
|
3
3
|
// src/react.ts
|
|
4
4
|
|
|
5
|
+
// src/types.ts
|
|
6
|
+
var DEFAULT_BASE_URL = "https://api.neetru.com";
|
|
7
|
+
|
|
8
|
+
// src/account-bar.ts
|
|
9
|
+
var h = React2.createElement;
|
|
10
|
+
var DEFAULT_LABELS = {
|
|
11
|
+
accountButton: "Abrir menu da conta",
|
|
12
|
+
appsButton: "Seus produtos Neetru",
|
|
13
|
+
appsTitle: "Trocar de produto",
|
|
14
|
+
myAccount: "Minha conta Neetru",
|
|
15
|
+
accountSettings: "Configura\xE7\xF5es da conta",
|
|
16
|
+
signOut: "Sair",
|
|
17
|
+
currentBadge: "Atual",
|
|
18
|
+
emptyProducts: "Nenhum outro produto dispon\xEDvel."
|
|
19
|
+
};
|
|
20
|
+
async function fetchNeetruAccountBar(client) {
|
|
21
|
+
const auth = client.auth;
|
|
22
|
+
const idToken = typeof auth?.getIdToken === "function" ? auth.getIdToken() : null;
|
|
23
|
+
if (!idToken) return null;
|
|
24
|
+
const config = client.config;
|
|
25
|
+
const baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
26
|
+
const fetchFn = config.fetch ?? globalThis.fetch;
|
|
27
|
+
const url = `${baseUrl}/api/sdk/v1/account/bar`;
|
|
28
|
+
try {
|
|
29
|
+
const res = await fetchFn(url, {
|
|
30
|
+
headers: { authorization: `Bearer ${idToken}`, accept: "application/json" }
|
|
31
|
+
});
|
|
32
|
+
if (!res.ok) return null;
|
|
33
|
+
const body = await res.json();
|
|
34
|
+
if (!body || typeof body !== "object" || !body.account) return null;
|
|
35
|
+
return {
|
|
36
|
+
account: {
|
|
37
|
+
displayName: String(body.account.displayName ?? ""),
|
|
38
|
+
email: String(body.account.email ?? ""),
|
|
39
|
+
photoUrl: body.account.photoUrl ?? null
|
|
40
|
+
},
|
|
41
|
+
accountUrl: String(body.accountUrl ?? "https://minhaconta.neetru.com"),
|
|
42
|
+
products: Array.isArray(body.products) ? body.products.filter(
|
|
43
|
+
(p) => !!p && typeof p.slug === "string" && typeof p.url === "string"
|
|
44
|
+
) : []
|
|
45
|
+
};
|
|
46
|
+
} catch {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function initialsFrom(nameOrEmail) {
|
|
51
|
+
const s = (nameOrEmail ?? "").trim();
|
|
52
|
+
if (!s) return "?";
|
|
53
|
+
const local = s.includes("@") ? s.split("@")[0] : s;
|
|
54
|
+
const parts = local.split(/[\s._-]+/).filter(Boolean);
|
|
55
|
+
if (parts.length === 0) return local.slice(0, 1).toUpperCase();
|
|
56
|
+
if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase();
|
|
57
|
+
return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
|
|
58
|
+
}
|
|
59
|
+
var C = {
|
|
60
|
+
bg: "#ffffff",
|
|
61
|
+
bgHover: "#f5f5f5",
|
|
62
|
+
fg: "#0a0a0a",
|
|
63
|
+
muted: "#666666",
|
|
64
|
+
border: "#0a0a0a",
|
|
65
|
+
borderSoft: "#e5e5e5"
|
|
66
|
+
};
|
|
67
|
+
var SQUARE = 0;
|
|
68
|
+
function WaffleIcon({ size = 18, color = C.fg }) {
|
|
69
|
+
const dots = [0, 1, 2].flatMap((r) => [0, 1, 2].map((c) => ({ r, c })));
|
|
70
|
+
const gap = size / 3;
|
|
71
|
+
const dot = Math.max(2, size / 7);
|
|
72
|
+
return h(
|
|
73
|
+
"svg",
|
|
74
|
+
{ width: size, height: size, viewBox: `0 0 ${size} ${size}`, "aria-hidden": true, style: { display: "block" } },
|
|
75
|
+
dots.map(
|
|
76
|
+
({ r, c }) => h("rect", {
|
|
77
|
+
key: `${r}-${c}`,
|
|
78
|
+
x: c * gap + (gap - dot) / 2,
|
|
79
|
+
y: r * gap + (gap - dot) / 2,
|
|
80
|
+
width: dot,
|
|
81
|
+
height: dot,
|
|
82
|
+
fill: color
|
|
83
|
+
})
|
|
84
|
+
)
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
function focusables(container) {
|
|
88
|
+
if (!container) return [];
|
|
89
|
+
return Array.from(
|
|
90
|
+
container.querySelectorAll(
|
|
91
|
+
'a[href], button:not([disabled]), [tabindex]:not([tabindex="-1"])'
|
|
92
|
+
)
|
|
93
|
+
).filter((el) => el.offsetParent !== null || el === document.activeElement);
|
|
94
|
+
}
|
|
95
|
+
function NeetruAccountBar({
|
|
96
|
+
client,
|
|
97
|
+
currentProductSlug,
|
|
98
|
+
settingsUrl,
|
|
99
|
+
onSignOut,
|
|
100
|
+
fetchBar,
|
|
101
|
+
labels,
|
|
102
|
+
className
|
|
103
|
+
}) {
|
|
104
|
+
const L = { ...DEFAULT_LABELS, ...labels };
|
|
105
|
+
const seedAccount = React2.useMemo(() => {
|
|
106
|
+
try {
|
|
107
|
+
const u = client.auth.getUser();
|
|
108
|
+
if (!u) return null;
|
|
109
|
+
return {
|
|
110
|
+
displayName: u.displayName || u.email || "",
|
|
111
|
+
email: u.email || "",
|
|
112
|
+
photoUrl: u.photoURL ?? null
|
|
113
|
+
};
|
|
114
|
+
} catch {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
}, [client]);
|
|
118
|
+
const [data, setData] = React2.useState(null);
|
|
119
|
+
const [open, setOpen] = React2.useState(null);
|
|
120
|
+
const [signingOut, setSigningOut] = React2.useState(false);
|
|
121
|
+
const containerRef = React2.useRef(null);
|
|
122
|
+
const accountBtnRef = React2.useRef(null);
|
|
123
|
+
const appsBtnRef = React2.useRef(null);
|
|
124
|
+
const popoverRef = React2.useRef(null);
|
|
125
|
+
React2.useEffect(() => {
|
|
126
|
+
let cancelled = false;
|
|
127
|
+
const run = fetchBar ?? fetchNeetruAccountBar;
|
|
128
|
+
Promise.resolve(run(client)).then((res) => {
|
|
129
|
+
if (!cancelled && res) setData(res);
|
|
130
|
+
}).catch(() => {
|
|
131
|
+
});
|
|
132
|
+
return () => {
|
|
133
|
+
cancelled = true;
|
|
134
|
+
};
|
|
135
|
+
}, [client, fetchBar]);
|
|
136
|
+
const account = data?.account ?? seedAccount;
|
|
137
|
+
const accountUrl = data?.accountUrl ?? "https://minhaconta.neetru.com";
|
|
138
|
+
const products = data?.products ?? [];
|
|
139
|
+
const closeAndRefocus = React2.useCallback((which) => {
|
|
140
|
+
setOpen(null);
|
|
141
|
+
const trigger = which === "apps" ? appsBtnRef.current : accountBtnRef.current;
|
|
142
|
+
trigger?.focus();
|
|
143
|
+
}, []);
|
|
144
|
+
React2.useEffect(() => {
|
|
145
|
+
if (!open) return;
|
|
146
|
+
const first = focusables(popoverRef.current)[0];
|
|
147
|
+
first?.focus();
|
|
148
|
+
const onDocMouseDown = (e) => {
|
|
149
|
+
if (containerRef.current && !containerRef.current.contains(e.target)) {
|
|
150
|
+
setOpen(null);
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
document.addEventListener("mousedown", onDocMouseDown);
|
|
154
|
+
return () => document.removeEventListener("mousedown", onDocMouseDown);
|
|
155
|
+
}, [open]);
|
|
156
|
+
const onPopoverKeyDown = React2.useCallback(
|
|
157
|
+
(e) => {
|
|
158
|
+
if (e.key === "Escape") {
|
|
159
|
+
e.stopPropagation();
|
|
160
|
+
closeAndRefocus(open);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
const items = focusables(popoverRef.current);
|
|
164
|
+
if (items.length === 0) return;
|
|
165
|
+
const idx = items.indexOf(document.activeElement);
|
|
166
|
+
if (e.key === "Tab") {
|
|
167
|
+
if (e.shiftKey && idx <= 0) {
|
|
168
|
+
e.preventDefault();
|
|
169
|
+
items[items.length - 1].focus();
|
|
170
|
+
} else if (!e.shiftKey && idx === items.length - 1) {
|
|
171
|
+
e.preventDefault();
|
|
172
|
+
items[0].focus();
|
|
173
|
+
}
|
|
174
|
+
} else if (e.key === "ArrowDown") {
|
|
175
|
+
e.preventDefault();
|
|
176
|
+
items[(idx + 1) % items.length].focus();
|
|
177
|
+
} else if (e.key === "ArrowUp") {
|
|
178
|
+
e.preventDefault();
|
|
179
|
+
items[(idx - 1 + items.length) % items.length].focus();
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
[open, closeAndRefocus]
|
|
183
|
+
);
|
|
184
|
+
const handleSignOut = React2.useCallback(async () => {
|
|
185
|
+
if (signingOut) return;
|
|
186
|
+
setSigningOut(true);
|
|
187
|
+
try {
|
|
188
|
+
await client.auth.signOut();
|
|
189
|
+
} catch {
|
|
190
|
+
} finally {
|
|
191
|
+
setSigningOut(false);
|
|
192
|
+
setOpen(null);
|
|
193
|
+
onSignOut?.();
|
|
194
|
+
}
|
|
195
|
+
}, [client, signingOut, onSignOut]);
|
|
196
|
+
if (!account) return null;
|
|
197
|
+
const initials = initialsFrom(account.displayName || account.email);
|
|
198
|
+
const avatarInner = account.photoUrl ? h("img", {
|
|
199
|
+
src: account.photoUrl,
|
|
200
|
+
alt: "",
|
|
201
|
+
width: 32,
|
|
202
|
+
height: 32,
|
|
203
|
+
style: { width: 32, height: 32, objectFit: "cover", display: "block" }
|
|
204
|
+
}) : h(
|
|
205
|
+
"span",
|
|
206
|
+
{
|
|
207
|
+
"aria-hidden": true,
|
|
208
|
+
style: {
|
|
209
|
+
width: 32,
|
|
210
|
+
height: 32,
|
|
211
|
+
display: "inline-flex",
|
|
212
|
+
alignItems: "center",
|
|
213
|
+
justifyContent: "center",
|
|
214
|
+
backgroundColor: C.fg,
|
|
215
|
+
color: "#ffffff",
|
|
216
|
+
fontSize: 13,
|
|
217
|
+
fontWeight: 700,
|
|
218
|
+
letterSpacing: "0.02em"
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
initials
|
|
222
|
+
);
|
|
223
|
+
const iconBtnStyle = (active) => ({
|
|
224
|
+
display: "inline-flex",
|
|
225
|
+
alignItems: "center",
|
|
226
|
+
justifyContent: "center",
|
|
227
|
+
width: 36,
|
|
228
|
+
height: 36,
|
|
229
|
+
padding: 0,
|
|
230
|
+
borderRadius: SQUARE,
|
|
231
|
+
border: `1px solid ${active ? C.border : C.borderSoft}`,
|
|
232
|
+
backgroundColor: active ? C.bgHover : C.bg,
|
|
233
|
+
color: C.fg,
|
|
234
|
+
cursor: "pointer",
|
|
235
|
+
boxSizing: "border-box",
|
|
236
|
+
fontFamily: "inherit",
|
|
237
|
+
overflow: "hidden"
|
|
238
|
+
});
|
|
239
|
+
const appsButton = h(
|
|
240
|
+
"button",
|
|
241
|
+
{
|
|
242
|
+
type: "button",
|
|
243
|
+
ref: appsBtnRef,
|
|
244
|
+
"aria-label": L.appsButton,
|
|
245
|
+
"aria-haspopup": "menu",
|
|
246
|
+
"aria-expanded": open === "apps",
|
|
247
|
+
"data-neetru-appswitcher-button": "true",
|
|
248
|
+
onClick: () => setOpen((o) => o === "apps" ? null : "apps"),
|
|
249
|
+
style: iconBtnStyle(open === "apps")
|
|
250
|
+
},
|
|
251
|
+
h(WaffleIcon, {})
|
|
252
|
+
);
|
|
253
|
+
const accountButton = h(
|
|
254
|
+
"button",
|
|
255
|
+
{
|
|
256
|
+
type: "button",
|
|
257
|
+
ref: accountBtnRef,
|
|
258
|
+
"aria-label": `${L.accountButton}${account.displayName ? ` (${account.displayName})` : ""}`,
|
|
259
|
+
"aria-haspopup": "menu",
|
|
260
|
+
"aria-expanded": open === "account",
|
|
261
|
+
"data-neetru-account-button": "true",
|
|
262
|
+
onClick: () => setOpen((o) => o === "account" ? null : "account"),
|
|
263
|
+
style: { ...iconBtnStyle(open === "account"), width: 36, height: 36 }
|
|
264
|
+
},
|
|
265
|
+
avatarInner
|
|
266
|
+
);
|
|
267
|
+
const popoverStyle = {
|
|
268
|
+
position: "absolute",
|
|
269
|
+
top: "calc(100% + 6px)",
|
|
270
|
+
right: 0,
|
|
271
|
+
minWidth: 260,
|
|
272
|
+
maxWidth: 320,
|
|
273
|
+
backgroundColor: C.bg,
|
|
274
|
+
border: `1px solid ${C.border}`,
|
|
275
|
+
borderRadius: SQUARE,
|
|
276
|
+
zIndex: 1e3,
|
|
277
|
+
color: C.fg,
|
|
278
|
+
fontFamily: "inherit"
|
|
279
|
+
// BMW: sem sombra/glassmorphism — borda sólida define o recorte.
|
|
280
|
+
};
|
|
281
|
+
const menuItemStyle = {
|
|
282
|
+
display: "flex",
|
|
283
|
+
alignItems: "center",
|
|
284
|
+
gap: 10,
|
|
285
|
+
width: "100%",
|
|
286
|
+
padding: "10px 14px",
|
|
287
|
+
background: "transparent",
|
|
288
|
+
border: "none",
|
|
289
|
+
borderTop: `1px solid ${C.borderSoft}`,
|
|
290
|
+
color: C.fg,
|
|
291
|
+
fontSize: 14,
|
|
292
|
+
fontWeight: 400,
|
|
293
|
+
textAlign: "left",
|
|
294
|
+
textDecoration: "none",
|
|
295
|
+
cursor: "pointer",
|
|
296
|
+
boxSizing: "border-box",
|
|
297
|
+
fontFamily: "inherit"
|
|
298
|
+
};
|
|
299
|
+
const hoverHandlers = {
|
|
300
|
+
onMouseEnter: (e) => {
|
|
301
|
+
e.currentTarget.style.backgroundColor = C.bgHover;
|
|
302
|
+
},
|
|
303
|
+
onMouseLeave: (e) => {
|
|
304
|
+
e.currentTarget.style.backgroundColor = "transparent";
|
|
305
|
+
}
|
|
306
|
+
};
|
|
307
|
+
const accountPopover = open === "account" ? h(
|
|
308
|
+
"div",
|
|
309
|
+
{
|
|
310
|
+
ref: popoverRef,
|
|
311
|
+
role: "menu",
|
|
312
|
+
"aria-label": L.accountButton,
|
|
313
|
+
"data-neetru-account-menu": "true",
|
|
314
|
+
onKeyDown: onPopoverKeyDown,
|
|
315
|
+
style: popoverStyle
|
|
316
|
+
},
|
|
317
|
+
// Header identidade
|
|
318
|
+
h(
|
|
319
|
+
"div",
|
|
320
|
+
{ style: { display: "flex", gap: 12, alignItems: "center", padding: 14 } },
|
|
321
|
+
h(
|
|
322
|
+
"span",
|
|
323
|
+
{
|
|
324
|
+
"aria-hidden": true,
|
|
325
|
+
style: {
|
|
326
|
+
width: 40,
|
|
327
|
+
height: 40,
|
|
328
|
+
flexShrink: 0,
|
|
329
|
+
display: "inline-flex",
|
|
330
|
+
alignItems: "center",
|
|
331
|
+
justifyContent: "center",
|
|
332
|
+
overflow: "hidden",
|
|
333
|
+
backgroundColor: account.photoUrl ? "transparent" : C.fg,
|
|
334
|
+
color: "#ffffff",
|
|
335
|
+
fontSize: 15,
|
|
336
|
+
fontWeight: 700
|
|
337
|
+
}
|
|
338
|
+
},
|
|
339
|
+
account.photoUrl ? h("img", {
|
|
340
|
+
src: account.photoUrl,
|
|
341
|
+
alt: "",
|
|
342
|
+
width: 40,
|
|
343
|
+
height: 40,
|
|
344
|
+
style: { width: 40, height: 40, objectFit: "cover", display: "block" }
|
|
345
|
+
}) : initials
|
|
346
|
+
),
|
|
347
|
+
h(
|
|
348
|
+
"span",
|
|
349
|
+
{ style: { display: "flex", flexDirection: "column", minWidth: 0 } },
|
|
350
|
+
h(
|
|
351
|
+
"span",
|
|
352
|
+
{
|
|
353
|
+
style: {
|
|
354
|
+
fontWeight: 700,
|
|
355
|
+
fontSize: 14,
|
|
356
|
+
whiteSpace: "nowrap",
|
|
357
|
+
overflow: "hidden",
|
|
358
|
+
textOverflow: "ellipsis"
|
|
359
|
+
}
|
|
360
|
+
},
|
|
361
|
+
account.displayName || account.email
|
|
362
|
+
),
|
|
363
|
+
account.email ? h(
|
|
364
|
+
"span",
|
|
365
|
+
{
|
|
366
|
+
style: {
|
|
367
|
+
color: C.muted,
|
|
368
|
+
fontSize: 12,
|
|
369
|
+
whiteSpace: "nowrap",
|
|
370
|
+
overflow: "hidden",
|
|
371
|
+
textOverflow: "ellipsis"
|
|
372
|
+
}
|
|
373
|
+
},
|
|
374
|
+
account.email
|
|
375
|
+
) : null
|
|
376
|
+
)
|
|
377
|
+
),
|
|
378
|
+
// Minha conta Neetru
|
|
379
|
+
h(
|
|
380
|
+
"a",
|
|
381
|
+
{
|
|
382
|
+
role: "menuitem",
|
|
383
|
+
href: accountUrl,
|
|
384
|
+
target: "_blank",
|
|
385
|
+
rel: "noopener noreferrer",
|
|
386
|
+
style: menuItemStyle,
|
|
387
|
+
...hoverHandlers
|
|
388
|
+
},
|
|
389
|
+
L.myAccount
|
|
390
|
+
),
|
|
391
|
+
// Configurações da conta (deste produto)
|
|
392
|
+
settingsUrl ? h(
|
|
393
|
+
"a",
|
|
394
|
+
{ role: "menuitem", href: settingsUrl, style: menuItemStyle, ...hoverHandlers },
|
|
395
|
+
L.accountSettings
|
|
396
|
+
) : null,
|
|
397
|
+
// Sair
|
|
398
|
+
h(
|
|
399
|
+
"button",
|
|
400
|
+
{
|
|
401
|
+
type: "button",
|
|
402
|
+
role: "menuitem",
|
|
403
|
+
onClick: handleSignOut,
|
|
404
|
+
disabled: signingOut,
|
|
405
|
+
"data-neetru-signout": "true",
|
|
406
|
+
style: { ...menuItemStyle, cursor: signingOut ? "not-allowed" : "pointer" },
|
|
407
|
+
...hoverHandlers
|
|
408
|
+
},
|
|
409
|
+
signingOut ? `${L.signOut}\u2026` : L.signOut
|
|
410
|
+
)
|
|
411
|
+
) : null;
|
|
412
|
+
const appsPopover = open === "apps" ? h(
|
|
413
|
+
"div",
|
|
414
|
+
{
|
|
415
|
+
ref: popoverRef,
|
|
416
|
+
role: "menu",
|
|
417
|
+
"aria-label": L.appsTitle,
|
|
418
|
+
"data-neetru-appswitcher-menu": "true",
|
|
419
|
+
onKeyDown: onPopoverKeyDown,
|
|
420
|
+
style: { ...popoverStyle, minWidth: 280 }
|
|
421
|
+
},
|
|
422
|
+
h(
|
|
423
|
+
"div",
|
|
424
|
+
{
|
|
425
|
+
style: {
|
|
426
|
+
padding: "12px 14px 8px",
|
|
427
|
+
fontSize: 11,
|
|
428
|
+
fontWeight: 700,
|
|
429
|
+
letterSpacing: "0.08em",
|
|
430
|
+
textTransform: "uppercase",
|
|
431
|
+
color: C.muted
|
|
432
|
+
}
|
|
433
|
+
},
|
|
434
|
+
L.appsTitle
|
|
435
|
+
),
|
|
436
|
+
products.length === 0 ? h(
|
|
437
|
+
"div",
|
|
438
|
+
{ style: { padding: "4px 14px 16px", fontSize: 13, color: C.muted } },
|
|
439
|
+
L.emptyProducts
|
|
440
|
+
) : h(
|
|
441
|
+
"div",
|
|
442
|
+
{
|
|
443
|
+
style: {
|
|
444
|
+
display: "grid",
|
|
445
|
+
gridTemplateColumns: "1fr 1fr",
|
|
446
|
+
gap: 1,
|
|
447
|
+
padding: 1,
|
|
448
|
+
backgroundColor: C.borderSoft
|
|
449
|
+
}
|
|
450
|
+
},
|
|
451
|
+
products.map((p) => {
|
|
452
|
+
const isCurrent = !!currentProductSlug && p.slug === currentProductSlug;
|
|
453
|
+
return h(
|
|
454
|
+
"a",
|
|
455
|
+
{
|
|
456
|
+
key: p.slug,
|
|
457
|
+
role: "menuitem",
|
|
458
|
+
href: p.url,
|
|
459
|
+
"aria-current": isCurrent ? "true" : void 0,
|
|
460
|
+
"data-neetru-product": p.slug,
|
|
461
|
+
"data-current": isCurrent ? "true" : void 0,
|
|
462
|
+
title: p.name,
|
|
463
|
+
style: {
|
|
464
|
+
display: "flex",
|
|
465
|
+
flexDirection: "column",
|
|
466
|
+
alignItems: "center",
|
|
467
|
+
gap: 6,
|
|
468
|
+
padding: "14px 8px",
|
|
469
|
+
textDecoration: "none",
|
|
470
|
+
color: C.fg,
|
|
471
|
+
backgroundColor: isCurrent ? C.bgHover : C.bg,
|
|
472
|
+
cursor: "pointer",
|
|
473
|
+
boxSizing: "border-box"
|
|
474
|
+
},
|
|
475
|
+
onMouseEnter: (e) => {
|
|
476
|
+
e.currentTarget.style.backgroundColor = C.bgHover;
|
|
477
|
+
},
|
|
478
|
+
onMouseLeave: (e) => {
|
|
479
|
+
e.currentTarget.style.backgroundColor = isCurrent ? C.bgHover : C.bg;
|
|
480
|
+
}
|
|
481
|
+
},
|
|
482
|
+
// Tile/ícone
|
|
483
|
+
p.iconUrl ? h("img", {
|
|
484
|
+
src: p.iconUrl,
|
|
485
|
+
alt: "",
|
|
486
|
+
width: 32,
|
|
487
|
+
height: 32,
|
|
488
|
+
style: { width: 32, height: 32, objectFit: "cover", display: "block" }
|
|
489
|
+
}) : h(
|
|
490
|
+
"span",
|
|
491
|
+
{
|
|
492
|
+
"aria-hidden": true,
|
|
493
|
+
style: {
|
|
494
|
+
width: 32,
|
|
495
|
+
height: 32,
|
|
496
|
+
display: "inline-flex",
|
|
497
|
+
alignItems: "center",
|
|
498
|
+
justifyContent: "center",
|
|
499
|
+
backgroundColor: C.fg,
|
|
500
|
+
color: "#ffffff",
|
|
501
|
+
fontSize: 13,
|
|
502
|
+
fontWeight: 700
|
|
503
|
+
}
|
|
504
|
+
},
|
|
505
|
+
initialsFrom(p.name)
|
|
506
|
+
),
|
|
507
|
+
h(
|
|
508
|
+
"span",
|
|
509
|
+
{
|
|
510
|
+
style: {
|
|
511
|
+
fontSize: 12,
|
|
512
|
+
fontWeight: isCurrent ? 700 : 400,
|
|
513
|
+
textAlign: "center",
|
|
514
|
+
lineHeight: 1.2,
|
|
515
|
+
maxWidth: "100%",
|
|
516
|
+
overflow: "hidden",
|
|
517
|
+
textOverflow: "ellipsis",
|
|
518
|
+
whiteSpace: "nowrap",
|
|
519
|
+
width: "100%"
|
|
520
|
+
}
|
|
521
|
+
},
|
|
522
|
+
p.name
|
|
523
|
+
),
|
|
524
|
+
isCurrent ? h(
|
|
525
|
+
"span",
|
|
526
|
+
{
|
|
527
|
+
style: {
|
|
528
|
+
fontSize: 9,
|
|
529
|
+
fontWeight: 700,
|
|
530
|
+
letterSpacing: "0.08em",
|
|
531
|
+
textTransform: "uppercase",
|
|
532
|
+
color: C.muted
|
|
533
|
+
}
|
|
534
|
+
},
|
|
535
|
+
L.currentBadge
|
|
536
|
+
) : null
|
|
537
|
+
);
|
|
538
|
+
})
|
|
539
|
+
)
|
|
540
|
+
) : null;
|
|
541
|
+
return h(
|
|
542
|
+
"div",
|
|
543
|
+
{
|
|
544
|
+
ref: containerRef,
|
|
545
|
+
className,
|
|
546
|
+
"data-neetru-account-bar": "true",
|
|
547
|
+
style: {
|
|
548
|
+
position: "relative",
|
|
549
|
+
display: "inline-flex",
|
|
550
|
+
alignItems: "center",
|
|
551
|
+
gap: 8,
|
|
552
|
+
// Superfície de cliente = sempre claro (dark é staff-only).
|
|
553
|
+
colorScheme: "light",
|
|
554
|
+
fontFamily: "inherit"
|
|
555
|
+
}
|
|
556
|
+
},
|
|
557
|
+
appsButton,
|
|
558
|
+
accountButton,
|
|
559
|
+
accountPopover,
|
|
560
|
+
appsPopover
|
|
561
|
+
);
|
|
562
|
+
}
|
|
563
|
+
|
|
5
564
|
// src/firestore-compat.ts
|
|
6
565
|
function toDbQuery(constraints) {
|
|
7
566
|
const whereFilters = [];
|
|
@@ -42,9 +601,9 @@ function CheckoutLink({
|
|
|
42
601
|
noAutoRedirect,
|
|
43
602
|
...rest
|
|
44
603
|
}) {
|
|
45
|
-
const [submitting, setSubmitting] =
|
|
604
|
+
const [submitting, setSubmitting] = React2.useState(false);
|
|
46
605
|
const checkout = client.checkout;
|
|
47
|
-
const handleClick =
|
|
606
|
+
const handleClick = React2.useCallback(
|
|
48
607
|
async (event) => {
|
|
49
608
|
event.preventDefault();
|
|
50
609
|
if (submitting) return;
|
|
@@ -71,7 +630,7 @@ function CheckoutLink({
|
|
|
71
630
|
},
|
|
72
631
|
[submitting, checkout, productId, planId, callbackUrl, tenantType, tenantId, noAutoRedirect, onIntentCreated, onError]
|
|
73
632
|
);
|
|
74
|
-
return
|
|
633
|
+
return React2.createElement(
|
|
75
634
|
"a",
|
|
76
635
|
{
|
|
77
636
|
...rest,
|
|
@@ -87,7 +646,7 @@ var NEETRU_FLAME_PATH = "M 281 5.163 C 240.659 26.308, 211.260 52.739, 187.750 8
|
|
|
87
646
|
var NEETRU_FLAME_VIEWBOX = "0 0 527 760";
|
|
88
647
|
var NEETRU_FLAME_ASPECT = 527 / 760;
|
|
89
648
|
function NeetruFlameIcon({ fill, size = 16 }) {
|
|
90
|
-
return
|
|
649
|
+
return React2.createElement(
|
|
91
650
|
"svg",
|
|
92
651
|
{
|
|
93
652
|
viewBox: NEETRU_FLAME_VIEWBOX,
|
|
@@ -96,7 +655,7 @@ function NeetruFlameIcon({ fill, size = 16 }) {
|
|
|
96
655
|
"aria-hidden": true,
|
|
97
656
|
style: { flexShrink: 0 }
|
|
98
657
|
},
|
|
99
|
-
|
|
658
|
+
React2.createElement("path", { d: NEETRU_FLAME_PATH, fill })
|
|
100
659
|
);
|
|
101
660
|
}
|
|
102
661
|
var NEETRU_LOGIN_BUTTON_THEME = {
|
|
@@ -115,11 +674,11 @@ function NeetruLoginButton({
|
|
|
115
674
|
disabled,
|
|
116
675
|
...rest
|
|
117
676
|
}) {
|
|
118
|
-
const [isLoading, setIsLoading] =
|
|
119
|
-
const [isHover, setIsHover] =
|
|
677
|
+
const [isLoading, setIsLoading] = React2.useState(false);
|
|
678
|
+
const [isHover, setIsHover] = React2.useState(false);
|
|
120
679
|
const colors = NEETRU_LOGIN_BUTTON_THEME[theme];
|
|
121
680
|
const isDisabled = Boolean(disabled) || isLoading;
|
|
122
|
-
const handleClick =
|
|
681
|
+
const handleClick = React2.useCallback(async () => {
|
|
123
682
|
if (isDisabled) return;
|
|
124
683
|
setIsLoading(true);
|
|
125
684
|
try {
|
|
@@ -131,7 +690,7 @@ function NeetruLoginButton({
|
|
|
131
690
|
setIsLoading(false);
|
|
132
691
|
}
|
|
133
692
|
}, [client, redirectUri, scope, postLoginRedirect, isDisabled, onError]);
|
|
134
|
-
return
|
|
693
|
+
return React2.createElement(
|
|
135
694
|
"button",
|
|
136
695
|
{
|
|
137
696
|
...rest,
|
|
@@ -168,15 +727,15 @@ function NeetruLoginButton({
|
|
|
168
727
|
...style
|
|
169
728
|
}
|
|
170
729
|
},
|
|
171
|
-
|
|
172
|
-
|
|
730
|
+
React2.createElement(NeetruFlameIcon, { fill: colors.fg }),
|
|
731
|
+
React2.createElement("span", null, isLoading ? "Entrando\u2026" : label)
|
|
173
732
|
);
|
|
174
733
|
}
|
|
175
|
-
var EntitlementContext =
|
|
734
|
+
var EntitlementContext = React2.createContext({
|
|
176
735
|
readonly: false
|
|
177
736
|
});
|
|
178
737
|
function useEntitlementContext() {
|
|
179
|
-
return
|
|
738
|
+
return React2.useContext(EntitlementContext);
|
|
180
739
|
}
|
|
181
740
|
function EntitlementGate({
|
|
182
741
|
client,
|
|
@@ -187,12 +746,12 @@ function EntitlementGate({
|
|
|
187
746
|
loading,
|
|
188
747
|
children
|
|
189
748
|
}) {
|
|
190
|
-
const [state, setState] =
|
|
749
|
+
const [state, setState] = React2.useState({
|
|
191
750
|
status: "loading"
|
|
192
751
|
});
|
|
193
752
|
const resolvedSlug = productSlug ?? client.config.productId ?? "";
|
|
194
753
|
const resolvedTenantId = client.config.tenantId;
|
|
195
|
-
|
|
754
|
+
React2.useEffect(() => {
|
|
196
755
|
let cancelled = false;
|
|
197
756
|
const run = async () => {
|
|
198
757
|
try {
|
|
@@ -228,15 +787,15 @@ function EntitlementGate({
|
|
|
228
787
|
};
|
|
229
788
|
}, [client, feature, resolvedSlug, resolvedTenantId]);
|
|
230
789
|
if (state.status === "loading") {
|
|
231
|
-
return
|
|
790
|
+
return React2.createElement(React2.Fragment, null, loading ?? null);
|
|
232
791
|
}
|
|
233
792
|
const result = state.result;
|
|
234
793
|
const allowed = result?.allowed === true;
|
|
235
794
|
const isReadonly = !allowed && (mode === "readonly" || result?.behavior === "readonly");
|
|
236
795
|
if (!allowed && mode === "block" && !isReadonly) {
|
|
237
|
-
return
|
|
796
|
+
return React2.createElement(React2.Fragment, null, fallback ?? null);
|
|
238
797
|
}
|
|
239
|
-
return
|
|
798
|
+
return React2.createElement(
|
|
240
799
|
EntitlementContext.Provider,
|
|
241
800
|
{
|
|
242
801
|
value: {
|
|
@@ -281,17 +840,17 @@ function useCollection(source, options) {
|
|
|
281
840
|
const sourceKey = serializeSource(
|
|
282
841
|
source
|
|
283
842
|
);
|
|
284
|
-
const [state, setState] =
|
|
843
|
+
const [state, setState] = React2.useState({
|
|
285
844
|
data: null,
|
|
286
845
|
isLoading: sourceKey !== null,
|
|
287
846
|
error: null,
|
|
288
847
|
isStale: false,
|
|
289
848
|
lastUpdated: null
|
|
290
849
|
});
|
|
291
|
-
const mountedRef =
|
|
292
|
-
const sourceRef =
|
|
850
|
+
const mountedRef = React2.useRef(true);
|
|
851
|
+
const sourceRef = React2.useRef(source);
|
|
293
852
|
sourceRef.current = source;
|
|
294
|
-
|
|
853
|
+
React2.useEffect(() => {
|
|
295
854
|
mountedRef.current = true;
|
|
296
855
|
const current = sourceRef.current;
|
|
297
856
|
if (!current || sourceKey === null) {
|
|
@@ -360,17 +919,17 @@ function useDoc(ref, options) {
|
|
|
360
919
|
const intervalMs = options?.intervalMs ?? DEFAULT_INTERVAL_MS;
|
|
361
920
|
const poll = options?.poll ?? false;
|
|
362
921
|
const refKey = ref && ref.id ? `${ref.collection}/${ref.id}` : null;
|
|
363
|
-
const [state, setState] =
|
|
922
|
+
const [state, setState] = React2.useState({
|
|
364
923
|
data: null,
|
|
365
924
|
isLoading: refKey !== null,
|
|
366
925
|
error: null,
|
|
367
926
|
isStale: false,
|
|
368
927
|
lastUpdated: null
|
|
369
928
|
});
|
|
370
|
-
const mountedRef =
|
|
371
|
-
const refRef =
|
|
929
|
+
const mountedRef = React2.useRef(true);
|
|
930
|
+
const refRef = React2.useRef(ref);
|
|
372
931
|
refRef.current = ref;
|
|
373
|
-
|
|
932
|
+
React2.useEffect(() => {
|
|
374
933
|
mountedRef.current = true;
|
|
375
934
|
const current = refRef.current;
|
|
376
935
|
if (!current || refKey === null) {
|
|
@@ -443,7 +1002,7 @@ function resolveAuth(input) {
|
|
|
443
1002
|
function useUser(input, options) {
|
|
444
1003
|
const timeoutMs = options?.timeoutMs ?? 8e3;
|
|
445
1004
|
const auth = resolveAuth(input);
|
|
446
|
-
const [state, setState] =
|
|
1005
|
+
const [state, setState] = React2.useState(() => {
|
|
447
1006
|
let seeded = null;
|
|
448
1007
|
try {
|
|
449
1008
|
seeded = auth.getUser();
|
|
@@ -452,8 +1011,8 @@ function useUser(input, options) {
|
|
|
452
1011
|
}
|
|
453
1012
|
return { user: seeded, isLoading: seeded === null, error: null };
|
|
454
1013
|
});
|
|
455
|
-
const mountedRef =
|
|
456
|
-
|
|
1014
|
+
const mountedRef = React2.useRef(true);
|
|
1015
|
+
React2.useEffect(() => {
|
|
457
1016
|
mountedRef.current = true;
|
|
458
1017
|
let settled = false;
|
|
459
1018
|
const timer = setTimeout(() => {
|
|
@@ -485,6 +1044,6 @@ function useUser(input, options) {
|
|
|
485
1044
|
return state;
|
|
486
1045
|
}
|
|
487
1046
|
|
|
488
|
-
export { CheckoutLink, EntitlementGate, NeetruLoginButton, useCollection, useDoc, useEntitlementContext, useUser };
|
|
1047
|
+
export { CheckoutLink, EntitlementGate, NeetruAccountBar, NeetruLoginButton, fetchNeetruAccountBar, initialsFrom, useCollection, useDoc, useEntitlementContext, useUser };
|
|
489
1048
|
//# sourceMappingURL=react.mjs.map
|
|
490
1049
|
//# sourceMappingURL=react.mjs.map
|