@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.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var React2 = require('react');
|
|
4
4
|
|
|
5
5
|
function _interopNamespace(e) {
|
|
6
6
|
if (e && e.__esModule) return e;
|
|
@@ -20,10 +20,569 @@ function _interopNamespace(e) {
|
|
|
20
20
|
return Object.freeze(n);
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
var
|
|
23
|
+
var React2__namespace = /*#__PURE__*/_interopNamespace(React2);
|
|
24
24
|
|
|
25
25
|
// src/react.ts
|
|
26
26
|
|
|
27
|
+
// src/types.ts
|
|
28
|
+
var DEFAULT_BASE_URL = "https://api.neetru.com";
|
|
29
|
+
|
|
30
|
+
// src/account-bar.ts
|
|
31
|
+
var h = React2__namespace.createElement;
|
|
32
|
+
var DEFAULT_LABELS = {
|
|
33
|
+
accountButton: "Abrir menu da conta",
|
|
34
|
+
appsButton: "Seus produtos Neetru",
|
|
35
|
+
appsTitle: "Trocar de produto",
|
|
36
|
+
myAccount: "Minha conta Neetru",
|
|
37
|
+
accountSettings: "Configura\xE7\xF5es da conta",
|
|
38
|
+
signOut: "Sair",
|
|
39
|
+
currentBadge: "Atual",
|
|
40
|
+
emptyProducts: "Nenhum outro produto dispon\xEDvel."
|
|
41
|
+
};
|
|
42
|
+
async function fetchNeetruAccountBar(client) {
|
|
43
|
+
const auth = client.auth;
|
|
44
|
+
const idToken = typeof auth?.getIdToken === "function" ? auth.getIdToken() : null;
|
|
45
|
+
if (!idToken) return null;
|
|
46
|
+
const config = client.config;
|
|
47
|
+
const baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
48
|
+
const fetchFn = config.fetch ?? globalThis.fetch;
|
|
49
|
+
const url = `${baseUrl}/api/sdk/v1/account/bar`;
|
|
50
|
+
try {
|
|
51
|
+
const res = await fetchFn(url, {
|
|
52
|
+
headers: { authorization: `Bearer ${idToken}`, accept: "application/json" }
|
|
53
|
+
});
|
|
54
|
+
if (!res.ok) return null;
|
|
55
|
+
const body = await res.json();
|
|
56
|
+
if (!body || typeof body !== "object" || !body.account) return null;
|
|
57
|
+
return {
|
|
58
|
+
account: {
|
|
59
|
+
displayName: String(body.account.displayName ?? ""),
|
|
60
|
+
email: String(body.account.email ?? ""),
|
|
61
|
+
photoUrl: body.account.photoUrl ?? null
|
|
62
|
+
},
|
|
63
|
+
accountUrl: String(body.accountUrl ?? "https://minhaconta.neetru.com"),
|
|
64
|
+
products: Array.isArray(body.products) ? body.products.filter(
|
|
65
|
+
(p) => !!p && typeof p.slug === "string" && typeof p.url === "string"
|
|
66
|
+
) : []
|
|
67
|
+
};
|
|
68
|
+
} catch {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function initialsFrom(nameOrEmail) {
|
|
73
|
+
const s = (nameOrEmail ?? "").trim();
|
|
74
|
+
if (!s) return "?";
|
|
75
|
+
const local = s.includes("@") ? s.split("@")[0] : s;
|
|
76
|
+
const parts = local.split(/[\s._-]+/).filter(Boolean);
|
|
77
|
+
if (parts.length === 0) return local.slice(0, 1).toUpperCase();
|
|
78
|
+
if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase();
|
|
79
|
+
return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
|
|
80
|
+
}
|
|
81
|
+
var C = {
|
|
82
|
+
bg: "#ffffff",
|
|
83
|
+
bgHover: "#f5f5f5",
|
|
84
|
+
fg: "#0a0a0a",
|
|
85
|
+
muted: "#666666",
|
|
86
|
+
border: "#0a0a0a",
|
|
87
|
+
borderSoft: "#e5e5e5"
|
|
88
|
+
};
|
|
89
|
+
var SQUARE = 0;
|
|
90
|
+
function WaffleIcon({ size = 18, color = C.fg }) {
|
|
91
|
+
const dots = [0, 1, 2].flatMap((r) => [0, 1, 2].map((c) => ({ r, c })));
|
|
92
|
+
const gap = size / 3;
|
|
93
|
+
const dot = Math.max(2, size / 7);
|
|
94
|
+
return h(
|
|
95
|
+
"svg",
|
|
96
|
+
{ width: size, height: size, viewBox: `0 0 ${size} ${size}`, "aria-hidden": true, style: { display: "block" } },
|
|
97
|
+
dots.map(
|
|
98
|
+
({ r, c }) => h("rect", {
|
|
99
|
+
key: `${r}-${c}`,
|
|
100
|
+
x: c * gap + (gap - dot) / 2,
|
|
101
|
+
y: r * gap + (gap - dot) / 2,
|
|
102
|
+
width: dot,
|
|
103
|
+
height: dot,
|
|
104
|
+
fill: color
|
|
105
|
+
})
|
|
106
|
+
)
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
function focusables(container) {
|
|
110
|
+
if (!container) return [];
|
|
111
|
+
return Array.from(
|
|
112
|
+
container.querySelectorAll(
|
|
113
|
+
'a[href], button:not([disabled]), [tabindex]:not([tabindex="-1"])'
|
|
114
|
+
)
|
|
115
|
+
).filter((el) => el.offsetParent !== null || el === document.activeElement);
|
|
116
|
+
}
|
|
117
|
+
function NeetruAccountBar({
|
|
118
|
+
client,
|
|
119
|
+
currentProductSlug,
|
|
120
|
+
settingsUrl,
|
|
121
|
+
onSignOut,
|
|
122
|
+
fetchBar,
|
|
123
|
+
labels,
|
|
124
|
+
className
|
|
125
|
+
}) {
|
|
126
|
+
const L = { ...DEFAULT_LABELS, ...labels };
|
|
127
|
+
const seedAccount = React2__namespace.useMemo(() => {
|
|
128
|
+
try {
|
|
129
|
+
const u = client.auth.getUser();
|
|
130
|
+
if (!u) return null;
|
|
131
|
+
return {
|
|
132
|
+
displayName: u.displayName || u.email || "",
|
|
133
|
+
email: u.email || "",
|
|
134
|
+
photoUrl: u.photoURL ?? null
|
|
135
|
+
};
|
|
136
|
+
} catch {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
}, [client]);
|
|
140
|
+
const [data, setData] = React2__namespace.useState(null);
|
|
141
|
+
const [open, setOpen] = React2__namespace.useState(null);
|
|
142
|
+
const [signingOut, setSigningOut] = React2__namespace.useState(false);
|
|
143
|
+
const containerRef = React2__namespace.useRef(null);
|
|
144
|
+
const accountBtnRef = React2__namespace.useRef(null);
|
|
145
|
+
const appsBtnRef = React2__namespace.useRef(null);
|
|
146
|
+
const popoverRef = React2__namespace.useRef(null);
|
|
147
|
+
React2__namespace.useEffect(() => {
|
|
148
|
+
let cancelled = false;
|
|
149
|
+
const run = fetchBar ?? fetchNeetruAccountBar;
|
|
150
|
+
Promise.resolve(run(client)).then((res) => {
|
|
151
|
+
if (!cancelled && res) setData(res);
|
|
152
|
+
}).catch(() => {
|
|
153
|
+
});
|
|
154
|
+
return () => {
|
|
155
|
+
cancelled = true;
|
|
156
|
+
};
|
|
157
|
+
}, [client, fetchBar]);
|
|
158
|
+
const account = data?.account ?? seedAccount;
|
|
159
|
+
const accountUrl = data?.accountUrl ?? "https://minhaconta.neetru.com";
|
|
160
|
+
const products = data?.products ?? [];
|
|
161
|
+
const closeAndRefocus = React2__namespace.useCallback((which) => {
|
|
162
|
+
setOpen(null);
|
|
163
|
+
const trigger = which === "apps" ? appsBtnRef.current : accountBtnRef.current;
|
|
164
|
+
trigger?.focus();
|
|
165
|
+
}, []);
|
|
166
|
+
React2__namespace.useEffect(() => {
|
|
167
|
+
if (!open) return;
|
|
168
|
+
const first = focusables(popoverRef.current)[0];
|
|
169
|
+
first?.focus();
|
|
170
|
+
const onDocMouseDown = (e) => {
|
|
171
|
+
if (containerRef.current && !containerRef.current.contains(e.target)) {
|
|
172
|
+
setOpen(null);
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
document.addEventListener("mousedown", onDocMouseDown);
|
|
176
|
+
return () => document.removeEventListener("mousedown", onDocMouseDown);
|
|
177
|
+
}, [open]);
|
|
178
|
+
const onPopoverKeyDown = React2__namespace.useCallback(
|
|
179
|
+
(e) => {
|
|
180
|
+
if (e.key === "Escape") {
|
|
181
|
+
e.stopPropagation();
|
|
182
|
+
closeAndRefocus(open);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
const items = focusables(popoverRef.current);
|
|
186
|
+
if (items.length === 0) return;
|
|
187
|
+
const idx = items.indexOf(document.activeElement);
|
|
188
|
+
if (e.key === "Tab") {
|
|
189
|
+
if (e.shiftKey && idx <= 0) {
|
|
190
|
+
e.preventDefault();
|
|
191
|
+
items[items.length - 1].focus();
|
|
192
|
+
} else if (!e.shiftKey && idx === items.length - 1) {
|
|
193
|
+
e.preventDefault();
|
|
194
|
+
items[0].focus();
|
|
195
|
+
}
|
|
196
|
+
} else if (e.key === "ArrowDown") {
|
|
197
|
+
e.preventDefault();
|
|
198
|
+
items[(idx + 1) % items.length].focus();
|
|
199
|
+
} else if (e.key === "ArrowUp") {
|
|
200
|
+
e.preventDefault();
|
|
201
|
+
items[(idx - 1 + items.length) % items.length].focus();
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
[open, closeAndRefocus]
|
|
205
|
+
);
|
|
206
|
+
const handleSignOut = React2__namespace.useCallback(async () => {
|
|
207
|
+
if (signingOut) return;
|
|
208
|
+
setSigningOut(true);
|
|
209
|
+
try {
|
|
210
|
+
await client.auth.signOut();
|
|
211
|
+
} catch {
|
|
212
|
+
} finally {
|
|
213
|
+
setSigningOut(false);
|
|
214
|
+
setOpen(null);
|
|
215
|
+
onSignOut?.();
|
|
216
|
+
}
|
|
217
|
+
}, [client, signingOut, onSignOut]);
|
|
218
|
+
if (!account) return null;
|
|
219
|
+
const initials = initialsFrom(account.displayName || account.email);
|
|
220
|
+
const avatarInner = account.photoUrl ? h("img", {
|
|
221
|
+
src: account.photoUrl,
|
|
222
|
+
alt: "",
|
|
223
|
+
width: 32,
|
|
224
|
+
height: 32,
|
|
225
|
+
style: { width: 32, height: 32, objectFit: "cover", display: "block" }
|
|
226
|
+
}) : h(
|
|
227
|
+
"span",
|
|
228
|
+
{
|
|
229
|
+
"aria-hidden": true,
|
|
230
|
+
style: {
|
|
231
|
+
width: 32,
|
|
232
|
+
height: 32,
|
|
233
|
+
display: "inline-flex",
|
|
234
|
+
alignItems: "center",
|
|
235
|
+
justifyContent: "center",
|
|
236
|
+
backgroundColor: C.fg,
|
|
237
|
+
color: "#ffffff",
|
|
238
|
+
fontSize: 13,
|
|
239
|
+
fontWeight: 700,
|
|
240
|
+
letterSpacing: "0.02em"
|
|
241
|
+
}
|
|
242
|
+
},
|
|
243
|
+
initials
|
|
244
|
+
);
|
|
245
|
+
const iconBtnStyle = (active) => ({
|
|
246
|
+
display: "inline-flex",
|
|
247
|
+
alignItems: "center",
|
|
248
|
+
justifyContent: "center",
|
|
249
|
+
width: 36,
|
|
250
|
+
height: 36,
|
|
251
|
+
padding: 0,
|
|
252
|
+
borderRadius: SQUARE,
|
|
253
|
+
border: `1px solid ${active ? C.border : C.borderSoft}`,
|
|
254
|
+
backgroundColor: active ? C.bgHover : C.bg,
|
|
255
|
+
color: C.fg,
|
|
256
|
+
cursor: "pointer",
|
|
257
|
+
boxSizing: "border-box",
|
|
258
|
+
fontFamily: "inherit",
|
|
259
|
+
overflow: "hidden"
|
|
260
|
+
});
|
|
261
|
+
const appsButton = h(
|
|
262
|
+
"button",
|
|
263
|
+
{
|
|
264
|
+
type: "button",
|
|
265
|
+
ref: appsBtnRef,
|
|
266
|
+
"aria-label": L.appsButton,
|
|
267
|
+
"aria-haspopup": "menu",
|
|
268
|
+
"aria-expanded": open === "apps",
|
|
269
|
+
"data-neetru-appswitcher-button": "true",
|
|
270
|
+
onClick: () => setOpen((o) => o === "apps" ? null : "apps"),
|
|
271
|
+
style: iconBtnStyle(open === "apps")
|
|
272
|
+
},
|
|
273
|
+
h(WaffleIcon, {})
|
|
274
|
+
);
|
|
275
|
+
const accountButton = h(
|
|
276
|
+
"button",
|
|
277
|
+
{
|
|
278
|
+
type: "button",
|
|
279
|
+
ref: accountBtnRef,
|
|
280
|
+
"aria-label": `${L.accountButton}${account.displayName ? ` (${account.displayName})` : ""}`,
|
|
281
|
+
"aria-haspopup": "menu",
|
|
282
|
+
"aria-expanded": open === "account",
|
|
283
|
+
"data-neetru-account-button": "true",
|
|
284
|
+
onClick: () => setOpen((o) => o === "account" ? null : "account"),
|
|
285
|
+
style: { ...iconBtnStyle(open === "account"), width: 36, height: 36 }
|
|
286
|
+
},
|
|
287
|
+
avatarInner
|
|
288
|
+
);
|
|
289
|
+
const popoverStyle = {
|
|
290
|
+
position: "absolute",
|
|
291
|
+
top: "calc(100% + 6px)",
|
|
292
|
+
right: 0,
|
|
293
|
+
minWidth: 260,
|
|
294
|
+
maxWidth: 320,
|
|
295
|
+
backgroundColor: C.bg,
|
|
296
|
+
border: `1px solid ${C.border}`,
|
|
297
|
+
borderRadius: SQUARE,
|
|
298
|
+
zIndex: 1e3,
|
|
299
|
+
color: C.fg,
|
|
300
|
+
fontFamily: "inherit"
|
|
301
|
+
// BMW: sem sombra/glassmorphism — borda sólida define o recorte.
|
|
302
|
+
};
|
|
303
|
+
const menuItemStyle = {
|
|
304
|
+
display: "flex",
|
|
305
|
+
alignItems: "center",
|
|
306
|
+
gap: 10,
|
|
307
|
+
width: "100%",
|
|
308
|
+
padding: "10px 14px",
|
|
309
|
+
background: "transparent",
|
|
310
|
+
border: "none",
|
|
311
|
+
borderTop: `1px solid ${C.borderSoft}`,
|
|
312
|
+
color: C.fg,
|
|
313
|
+
fontSize: 14,
|
|
314
|
+
fontWeight: 400,
|
|
315
|
+
textAlign: "left",
|
|
316
|
+
textDecoration: "none",
|
|
317
|
+
cursor: "pointer",
|
|
318
|
+
boxSizing: "border-box",
|
|
319
|
+
fontFamily: "inherit"
|
|
320
|
+
};
|
|
321
|
+
const hoverHandlers = {
|
|
322
|
+
onMouseEnter: (e) => {
|
|
323
|
+
e.currentTarget.style.backgroundColor = C.bgHover;
|
|
324
|
+
},
|
|
325
|
+
onMouseLeave: (e) => {
|
|
326
|
+
e.currentTarget.style.backgroundColor = "transparent";
|
|
327
|
+
}
|
|
328
|
+
};
|
|
329
|
+
const accountPopover = open === "account" ? h(
|
|
330
|
+
"div",
|
|
331
|
+
{
|
|
332
|
+
ref: popoverRef,
|
|
333
|
+
role: "menu",
|
|
334
|
+
"aria-label": L.accountButton,
|
|
335
|
+
"data-neetru-account-menu": "true",
|
|
336
|
+
onKeyDown: onPopoverKeyDown,
|
|
337
|
+
style: popoverStyle
|
|
338
|
+
},
|
|
339
|
+
// Header identidade
|
|
340
|
+
h(
|
|
341
|
+
"div",
|
|
342
|
+
{ style: { display: "flex", gap: 12, alignItems: "center", padding: 14 } },
|
|
343
|
+
h(
|
|
344
|
+
"span",
|
|
345
|
+
{
|
|
346
|
+
"aria-hidden": true,
|
|
347
|
+
style: {
|
|
348
|
+
width: 40,
|
|
349
|
+
height: 40,
|
|
350
|
+
flexShrink: 0,
|
|
351
|
+
display: "inline-flex",
|
|
352
|
+
alignItems: "center",
|
|
353
|
+
justifyContent: "center",
|
|
354
|
+
overflow: "hidden",
|
|
355
|
+
backgroundColor: account.photoUrl ? "transparent" : C.fg,
|
|
356
|
+
color: "#ffffff",
|
|
357
|
+
fontSize: 15,
|
|
358
|
+
fontWeight: 700
|
|
359
|
+
}
|
|
360
|
+
},
|
|
361
|
+
account.photoUrl ? h("img", {
|
|
362
|
+
src: account.photoUrl,
|
|
363
|
+
alt: "",
|
|
364
|
+
width: 40,
|
|
365
|
+
height: 40,
|
|
366
|
+
style: { width: 40, height: 40, objectFit: "cover", display: "block" }
|
|
367
|
+
}) : initials
|
|
368
|
+
),
|
|
369
|
+
h(
|
|
370
|
+
"span",
|
|
371
|
+
{ style: { display: "flex", flexDirection: "column", minWidth: 0 } },
|
|
372
|
+
h(
|
|
373
|
+
"span",
|
|
374
|
+
{
|
|
375
|
+
style: {
|
|
376
|
+
fontWeight: 700,
|
|
377
|
+
fontSize: 14,
|
|
378
|
+
whiteSpace: "nowrap",
|
|
379
|
+
overflow: "hidden",
|
|
380
|
+
textOverflow: "ellipsis"
|
|
381
|
+
}
|
|
382
|
+
},
|
|
383
|
+
account.displayName || account.email
|
|
384
|
+
),
|
|
385
|
+
account.email ? h(
|
|
386
|
+
"span",
|
|
387
|
+
{
|
|
388
|
+
style: {
|
|
389
|
+
color: C.muted,
|
|
390
|
+
fontSize: 12,
|
|
391
|
+
whiteSpace: "nowrap",
|
|
392
|
+
overflow: "hidden",
|
|
393
|
+
textOverflow: "ellipsis"
|
|
394
|
+
}
|
|
395
|
+
},
|
|
396
|
+
account.email
|
|
397
|
+
) : null
|
|
398
|
+
)
|
|
399
|
+
),
|
|
400
|
+
// Minha conta Neetru
|
|
401
|
+
h(
|
|
402
|
+
"a",
|
|
403
|
+
{
|
|
404
|
+
role: "menuitem",
|
|
405
|
+
href: accountUrl,
|
|
406
|
+
target: "_blank",
|
|
407
|
+
rel: "noopener noreferrer",
|
|
408
|
+
style: menuItemStyle,
|
|
409
|
+
...hoverHandlers
|
|
410
|
+
},
|
|
411
|
+
L.myAccount
|
|
412
|
+
),
|
|
413
|
+
// Configurações da conta (deste produto)
|
|
414
|
+
settingsUrl ? h(
|
|
415
|
+
"a",
|
|
416
|
+
{ role: "menuitem", href: settingsUrl, style: menuItemStyle, ...hoverHandlers },
|
|
417
|
+
L.accountSettings
|
|
418
|
+
) : null,
|
|
419
|
+
// Sair
|
|
420
|
+
h(
|
|
421
|
+
"button",
|
|
422
|
+
{
|
|
423
|
+
type: "button",
|
|
424
|
+
role: "menuitem",
|
|
425
|
+
onClick: handleSignOut,
|
|
426
|
+
disabled: signingOut,
|
|
427
|
+
"data-neetru-signout": "true",
|
|
428
|
+
style: { ...menuItemStyle, cursor: signingOut ? "not-allowed" : "pointer" },
|
|
429
|
+
...hoverHandlers
|
|
430
|
+
},
|
|
431
|
+
signingOut ? `${L.signOut}\u2026` : L.signOut
|
|
432
|
+
)
|
|
433
|
+
) : null;
|
|
434
|
+
const appsPopover = open === "apps" ? h(
|
|
435
|
+
"div",
|
|
436
|
+
{
|
|
437
|
+
ref: popoverRef,
|
|
438
|
+
role: "menu",
|
|
439
|
+
"aria-label": L.appsTitle,
|
|
440
|
+
"data-neetru-appswitcher-menu": "true",
|
|
441
|
+
onKeyDown: onPopoverKeyDown,
|
|
442
|
+
style: { ...popoverStyle, minWidth: 280 }
|
|
443
|
+
},
|
|
444
|
+
h(
|
|
445
|
+
"div",
|
|
446
|
+
{
|
|
447
|
+
style: {
|
|
448
|
+
padding: "12px 14px 8px",
|
|
449
|
+
fontSize: 11,
|
|
450
|
+
fontWeight: 700,
|
|
451
|
+
letterSpacing: "0.08em",
|
|
452
|
+
textTransform: "uppercase",
|
|
453
|
+
color: C.muted
|
|
454
|
+
}
|
|
455
|
+
},
|
|
456
|
+
L.appsTitle
|
|
457
|
+
),
|
|
458
|
+
products.length === 0 ? h(
|
|
459
|
+
"div",
|
|
460
|
+
{ style: { padding: "4px 14px 16px", fontSize: 13, color: C.muted } },
|
|
461
|
+
L.emptyProducts
|
|
462
|
+
) : h(
|
|
463
|
+
"div",
|
|
464
|
+
{
|
|
465
|
+
style: {
|
|
466
|
+
display: "grid",
|
|
467
|
+
gridTemplateColumns: "1fr 1fr",
|
|
468
|
+
gap: 1,
|
|
469
|
+
padding: 1,
|
|
470
|
+
backgroundColor: C.borderSoft
|
|
471
|
+
}
|
|
472
|
+
},
|
|
473
|
+
products.map((p) => {
|
|
474
|
+
const isCurrent = !!currentProductSlug && p.slug === currentProductSlug;
|
|
475
|
+
return h(
|
|
476
|
+
"a",
|
|
477
|
+
{
|
|
478
|
+
key: p.slug,
|
|
479
|
+
role: "menuitem",
|
|
480
|
+
href: p.url,
|
|
481
|
+
"aria-current": isCurrent ? "true" : void 0,
|
|
482
|
+
"data-neetru-product": p.slug,
|
|
483
|
+
"data-current": isCurrent ? "true" : void 0,
|
|
484
|
+
title: p.name,
|
|
485
|
+
style: {
|
|
486
|
+
display: "flex",
|
|
487
|
+
flexDirection: "column",
|
|
488
|
+
alignItems: "center",
|
|
489
|
+
gap: 6,
|
|
490
|
+
padding: "14px 8px",
|
|
491
|
+
textDecoration: "none",
|
|
492
|
+
color: C.fg,
|
|
493
|
+
backgroundColor: isCurrent ? C.bgHover : C.bg,
|
|
494
|
+
cursor: "pointer",
|
|
495
|
+
boxSizing: "border-box"
|
|
496
|
+
},
|
|
497
|
+
onMouseEnter: (e) => {
|
|
498
|
+
e.currentTarget.style.backgroundColor = C.bgHover;
|
|
499
|
+
},
|
|
500
|
+
onMouseLeave: (e) => {
|
|
501
|
+
e.currentTarget.style.backgroundColor = isCurrent ? C.bgHover : C.bg;
|
|
502
|
+
}
|
|
503
|
+
},
|
|
504
|
+
// Tile/ícone
|
|
505
|
+
p.iconUrl ? h("img", {
|
|
506
|
+
src: p.iconUrl,
|
|
507
|
+
alt: "",
|
|
508
|
+
width: 32,
|
|
509
|
+
height: 32,
|
|
510
|
+
style: { width: 32, height: 32, objectFit: "cover", display: "block" }
|
|
511
|
+
}) : h(
|
|
512
|
+
"span",
|
|
513
|
+
{
|
|
514
|
+
"aria-hidden": true,
|
|
515
|
+
style: {
|
|
516
|
+
width: 32,
|
|
517
|
+
height: 32,
|
|
518
|
+
display: "inline-flex",
|
|
519
|
+
alignItems: "center",
|
|
520
|
+
justifyContent: "center",
|
|
521
|
+
backgroundColor: C.fg,
|
|
522
|
+
color: "#ffffff",
|
|
523
|
+
fontSize: 13,
|
|
524
|
+
fontWeight: 700
|
|
525
|
+
}
|
|
526
|
+
},
|
|
527
|
+
initialsFrom(p.name)
|
|
528
|
+
),
|
|
529
|
+
h(
|
|
530
|
+
"span",
|
|
531
|
+
{
|
|
532
|
+
style: {
|
|
533
|
+
fontSize: 12,
|
|
534
|
+
fontWeight: isCurrent ? 700 : 400,
|
|
535
|
+
textAlign: "center",
|
|
536
|
+
lineHeight: 1.2,
|
|
537
|
+
maxWidth: "100%",
|
|
538
|
+
overflow: "hidden",
|
|
539
|
+
textOverflow: "ellipsis",
|
|
540
|
+
whiteSpace: "nowrap",
|
|
541
|
+
width: "100%"
|
|
542
|
+
}
|
|
543
|
+
},
|
|
544
|
+
p.name
|
|
545
|
+
),
|
|
546
|
+
isCurrent ? h(
|
|
547
|
+
"span",
|
|
548
|
+
{
|
|
549
|
+
style: {
|
|
550
|
+
fontSize: 9,
|
|
551
|
+
fontWeight: 700,
|
|
552
|
+
letterSpacing: "0.08em",
|
|
553
|
+
textTransform: "uppercase",
|
|
554
|
+
color: C.muted
|
|
555
|
+
}
|
|
556
|
+
},
|
|
557
|
+
L.currentBadge
|
|
558
|
+
) : null
|
|
559
|
+
);
|
|
560
|
+
})
|
|
561
|
+
)
|
|
562
|
+
) : null;
|
|
563
|
+
return h(
|
|
564
|
+
"div",
|
|
565
|
+
{
|
|
566
|
+
ref: containerRef,
|
|
567
|
+
className,
|
|
568
|
+
"data-neetru-account-bar": "true",
|
|
569
|
+
style: {
|
|
570
|
+
position: "relative",
|
|
571
|
+
display: "inline-flex",
|
|
572
|
+
alignItems: "center",
|
|
573
|
+
gap: 8,
|
|
574
|
+
// Superfície de cliente = sempre claro (dark é staff-only).
|
|
575
|
+
colorScheme: "light",
|
|
576
|
+
fontFamily: "inherit"
|
|
577
|
+
}
|
|
578
|
+
},
|
|
579
|
+
appsButton,
|
|
580
|
+
accountButton,
|
|
581
|
+
accountPopover,
|
|
582
|
+
appsPopover
|
|
583
|
+
);
|
|
584
|
+
}
|
|
585
|
+
|
|
27
586
|
// src/firestore-compat.ts
|
|
28
587
|
function toDbQuery(constraints) {
|
|
29
588
|
const whereFilters = [];
|
|
@@ -64,9 +623,9 @@ function CheckoutLink({
|
|
|
64
623
|
noAutoRedirect,
|
|
65
624
|
...rest
|
|
66
625
|
}) {
|
|
67
|
-
const [submitting, setSubmitting] =
|
|
626
|
+
const [submitting, setSubmitting] = React2__namespace.useState(false);
|
|
68
627
|
const checkout = client.checkout;
|
|
69
|
-
const handleClick =
|
|
628
|
+
const handleClick = React2__namespace.useCallback(
|
|
70
629
|
async (event) => {
|
|
71
630
|
event.preventDefault();
|
|
72
631
|
if (submitting) return;
|
|
@@ -93,7 +652,7 @@ function CheckoutLink({
|
|
|
93
652
|
},
|
|
94
653
|
[submitting, checkout, productId, planId, callbackUrl, tenantType, tenantId, noAutoRedirect, onIntentCreated, onError]
|
|
95
654
|
);
|
|
96
|
-
return
|
|
655
|
+
return React2__namespace.createElement(
|
|
97
656
|
"a",
|
|
98
657
|
{
|
|
99
658
|
...rest,
|
|
@@ -109,7 +668,7 @@ var NEETRU_FLAME_PATH = "M 281 5.163 C 240.659 26.308, 211.260 52.739, 187.750 8
|
|
|
109
668
|
var NEETRU_FLAME_VIEWBOX = "0 0 527 760";
|
|
110
669
|
var NEETRU_FLAME_ASPECT = 527 / 760;
|
|
111
670
|
function NeetruFlameIcon({ fill, size = 16 }) {
|
|
112
|
-
return
|
|
671
|
+
return React2__namespace.createElement(
|
|
113
672
|
"svg",
|
|
114
673
|
{
|
|
115
674
|
viewBox: NEETRU_FLAME_VIEWBOX,
|
|
@@ -118,7 +677,7 @@ function NeetruFlameIcon({ fill, size = 16 }) {
|
|
|
118
677
|
"aria-hidden": true,
|
|
119
678
|
style: { flexShrink: 0 }
|
|
120
679
|
},
|
|
121
|
-
|
|
680
|
+
React2__namespace.createElement("path", { d: NEETRU_FLAME_PATH, fill })
|
|
122
681
|
);
|
|
123
682
|
}
|
|
124
683
|
var NEETRU_LOGIN_BUTTON_THEME = {
|
|
@@ -137,11 +696,11 @@ function NeetruLoginButton({
|
|
|
137
696
|
disabled,
|
|
138
697
|
...rest
|
|
139
698
|
}) {
|
|
140
|
-
const [isLoading, setIsLoading] =
|
|
141
|
-
const [isHover, setIsHover] =
|
|
699
|
+
const [isLoading, setIsLoading] = React2__namespace.useState(false);
|
|
700
|
+
const [isHover, setIsHover] = React2__namespace.useState(false);
|
|
142
701
|
const colors = NEETRU_LOGIN_BUTTON_THEME[theme];
|
|
143
702
|
const isDisabled = Boolean(disabled) || isLoading;
|
|
144
|
-
const handleClick =
|
|
703
|
+
const handleClick = React2__namespace.useCallback(async () => {
|
|
145
704
|
if (isDisabled) return;
|
|
146
705
|
setIsLoading(true);
|
|
147
706
|
try {
|
|
@@ -153,7 +712,7 @@ function NeetruLoginButton({
|
|
|
153
712
|
setIsLoading(false);
|
|
154
713
|
}
|
|
155
714
|
}, [client, redirectUri, scope, postLoginRedirect, isDisabled, onError]);
|
|
156
|
-
return
|
|
715
|
+
return React2__namespace.createElement(
|
|
157
716
|
"button",
|
|
158
717
|
{
|
|
159
718
|
...rest,
|
|
@@ -190,15 +749,15 @@ function NeetruLoginButton({
|
|
|
190
749
|
...style
|
|
191
750
|
}
|
|
192
751
|
},
|
|
193
|
-
|
|
194
|
-
|
|
752
|
+
React2__namespace.createElement(NeetruFlameIcon, { fill: colors.fg }),
|
|
753
|
+
React2__namespace.createElement("span", null, isLoading ? "Entrando\u2026" : label)
|
|
195
754
|
);
|
|
196
755
|
}
|
|
197
|
-
var EntitlementContext =
|
|
756
|
+
var EntitlementContext = React2__namespace.createContext({
|
|
198
757
|
readonly: false
|
|
199
758
|
});
|
|
200
759
|
function useEntitlementContext() {
|
|
201
|
-
return
|
|
760
|
+
return React2__namespace.useContext(EntitlementContext);
|
|
202
761
|
}
|
|
203
762
|
function EntitlementGate({
|
|
204
763
|
client,
|
|
@@ -209,12 +768,12 @@ function EntitlementGate({
|
|
|
209
768
|
loading,
|
|
210
769
|
children
|
|
211
770
|
}) {
|
|
212
|
-
const [state, setState] =
|
|
771
|
+
const [state, setState] = React2__namespace.useState({
|
|
213
772
|
status: "loading"
|
|
214
773
|
});
|
|
215
774
|
const resolvedSlug = productSlug ?? client.config.productId ?? "";
|
|
216
775
|
const resolvedTenantId = client.config.tenantId;
|
|
217
|
-
|
|
776
|
+
React2__namespace.useEffect(() => {
|
|
218
777
|
let cancelled = false;
|
|
219
778
|
const run = async () => {
|
|
220
779
|
try {
|
|
@@ -250,15 +809,15 @@ function EntitlementGate({
|
|
|
250
809
|
};
|
|
251
810
|
}, [client, feature, resolvedSlug, resolvedTenantId]);
|
|
252
811
|
if (state.status === "loading") {
|
|
253
|
-
return
|
|
812
|
+
return React2__namespace.createElement(React2__namespace.Fragment, null, loading ?? null);
|
|
254
813
|
}
|
|
255
814
|
const result = state.result;
|
|
256
815
|
const allowed = result?.allowed === true;
|
|
257
816
|
const isReadonly = !allowed && (mode === "readonly" || result?.behavior === "readonly");
|
|
258
817
|
if (!allowed && mode === "block" && !isReadonly) {
|
|
259
|
-
return
|
|
818
|
+
return React2__namespace.createElement(React2__namespace.Fragment, null, fallback ?? null);
|
|
260
819
|
}
|
|
261
|
-
return
|
|
820
|
+
return React2__namespace.createElement(
|
|
262
821
|
EntitlementContext.Provider,
|
|
263
822
|
{
|
|
264
823
|
value: {
|
|
@@ -303,17 +862,17 @@ function useCollection(source, options) {
|
|
|
303
862
|
const sourceKey = serializeSource(
|
|
304
863
|
source
|
|
305
864
|
);
|
|
306
|
-
const [state, setState] =
|
|
865
|
+
const [state, setState] = React2__namespace.useState({
|
|
307
866
|
data: null,
|
|
308
867
|
isLoading: sourceKey !== null,
|
|
309
868
|
error: null,
|
|
310
869
|
isStale: false,
|
|
311
870
|
lastUpdated: null
|
|
312
871
|
});
|
|
313
|
-
const mountedRef =
|
|
314
|
-
const sourceRef =
|
|
872
|
+
const mountedRef = React2__namespace.useRef(true);
|
|
873
|
+
const sourceRef = React2__namespace.useRef(source);
|
|
315
874
|
sourceRef.current = source;
|
|
316
|
-
|
|
875
|
+
React2__namespace.useEffect(() => {
|
|
317
876
|
mountedRef.current = true;
|
|
318
877
|
const current = sourceRef.current;
|
|
319
878
|
if (!current || sourceKey === null) {
|
|
@@ -382,17 +941,17 @@ function useDoc(ref, options) {
|
|
|
382
941
|
const intervalMs = options?.intervalMs ?? DEFAULT_INTERVAL_MS;
|
|
383
942
|
const poll = options?.poll ?? false;
|
|
384
943
|
const refKey = ref && ref.id ? `${ref.collection}/${ref.id}` : null;
|
|
385
|
-
const [state, setState] =
|
|
944
|
+
const [state, setState] = React2__namespace.useState({
|
|
386
945
|
data: null,
|
|
387
946
|
isLoading: refKey !== null,
|
|
388
947
|
error: null,
|
|
389
948
|
isStale: false,
|
|
390
949
|
lastUpdated: null
|
|
391
950
|
});
|
|
392
|
-
const mountedRef =
|
|
393
|
-
const refRef =
|
|
951
|
+
const mountedRef = React2__namespace.useRef(true);
|
|
952
|
+
const refRef = React2__namespace.useRef(ref);
|
|
394
953
|
refRef.current = ref;
|
|
395
|
-
|
|
954
|
+
React2__namespace.useEffect(() => {
|
|
396
955
|
mountedRef.current = true;
|
|
397
956
|
const current = refRef.current;
|
|
398
957
|
if (!current || refKey === null) {
|
|
@@ -465,7 +1024,7 @@ function resolveAuth(input) {
|
|
|
465
1024
|
function useUser(input, options) {
|
|
466
1025
|
const timeoutMs = options?.timeoutMs ?? 8e3;
|
|
467
1026
|
const auth = resolveAuth(input);
|
|
468
|
-
const [state, setState] =
|
|
1027
|
+
const [state, setState] = React2__namespace.useState(() => {
|
|
469
1028
|
let seeded = null;
|
|
470
1029
|
try {
|
|
471
1030
|
seeded = auth.getUser();
|
|
@@ -474,8 +1033,8 @@ function useUser(input, options) {
|
|
|
474
1033
|
}
|
|
475
1034
|
return { user: seeded, isLoading: seeded === null, error: null };
|
|
476
1035
|
});
|
|
477
|
-
const mountedRef =
|
|
478
|
-
|
|
1036
|
+
const mountedRef = React2__namespace.useRef(true);
|
|
1037
|
+
React2__namespace.useEffect(() => {
|
|
479
1038
|
mountedRef.current = true;
|
|
480
1039
|
let settled = false;
|
|
481
1040
|
const timer = setTimeout(() => {
|
|
@@ -509,7 +1068,10 @@ function useUser(input, options) {
|
|
|
509
1068
|
|
|
510
1069
|
exports.CheckoutLink = CheckoutLink;
|
|
511
1070
|
exports.EntitlementGate = EntitlementGate;
|
|
1071
|
+
exports.NeetruAccountBar = NeetruAccountBar;
|
|
512
1072
|
exports.NeetruLoginButton = NeetruLoginButton;
|
|
1073
|
+
exports.fetchNeetruAccountBar = fetchNeetruAccountBar;
|
|
1074
|
+
exports.initialsFrom = initialsFrom;
|
|
513
1075
|
exports.useCollection = useCollection;
|
|
514
1076
|
exports.useDoc = useDoc;
|
|
515
1077
|
exports.useEntitlementContext = useEntitlementContext;
|