@businessdash/sdk 0.9.60 → 0.9.80
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 +991 -295
- package/assets/biab-sw.js +92 -0
- package/dist/account-core/index.d.ts +126 -0
- package/dist/account-core/index.d.ts.map +1 -0
- package/dist/account-core/index.js +191 -0
- package/dist/account-core/index.js.map +1 -0
- package/dist/account.d.ts +11 -0
- package/dist/account.d.ts.map +1 -0
- package/dist/account.js +11 -0
- package/dist/account.js.map +1 -0
- package/dist/auth-handler.d.ts +1 -1
- package/dist/auth-links.d.ts +33 -0
- package/dist/auth-links.d.ts.map +1 -0
- package/dist/auth-links.js +64 -0
- package/dist/auth-links.js.map +1 -0
- package/dist/blog-core/index.d.ts +112 -0
- package/dist/blog-core/index.d.ts.map +1 -0
- package/dist/blog-core/index.js +330 -0
- package/dist/blog-core/index.js.map +1 -0
- package/dist/blog.d.ts +11 -0
- package/dist/blog.d.ts.map +1 -0
- package/dist/blog.js +11 -0
- package/dist/blog.js.map +1 -0
- package/dist/chat-core/index.d.ts +97 -0
- package/dist/chat-core/index.d.ts.map +1 -0
- package/dist/chat-core/index.js +237 -0
- package/dist/chat-core/index.js.map +1 -0
- package/dist/chat.d.ts +11 -0
- package/dist/chat.d.ts.map +1 -0
- package/dist/chat.js +11 -0
- package/dist/chat.js.map +1 -0
- package/dist/checkout-core/index.d.ts +65 -0
- package/dist/checkout-core/index.d.ts.map +1 -0
- package/dist/checkout-core/index.js +159 -0
- package/dist/checkout-core/index.js.map +1 -0
- package/dist/checkout.d.ts +10 -0
- package/dist/checkout.d.ts.map +1 -0
- package/dist/checkout.js +10 -0
- package/dist/checkout.js.map +1 -0
- package/dist/cli.js +133 -25
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +622 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +888 -1
- package/dist/client.js.map +1 -1
- package/dist/consent-core/index.cjs +107 -0
- package/dist/consent-core/index.d.ts +103 -0
- package/dist/consent-core/index.d.ts.map +1 -0
- package/dist/consent-core/index.js +157 -0
- package/dist/consent-core/index.js.map +1 -0
- package/dist/contracts.d.ts +3526 -767
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js +571 -4
- package/dist/contracts.js.map +1 -1
- package/dist/data-model-schema.d.ts +1 -1
- package/dist/data-model-schema.d.ts.map +1 -1
- package/dist/element.d.ts +30 -0
- package/dist/element.d.ts.map +1 -1
- package/dist/element.js +56 -0
- package/dist/element.js.map +1 -1
- package/dist/embed-protocol.d.ts +86 -0
- package/dist/embed-protocol.d.ts.map +1 -0
- package/dist/embed-protocol.js +60 -0
- package/dist/embed-protocol.js.map +1 -0
- package/dist/framework-support.d.ts +122 -0
- package/dist/framework-support.d.ts.map +1 -0
- package/dist/framework-support.js +323 -0
- package/dist/framework-support.js.map +1 -0
- package/dist/index.cjs +1355 -24
- package/dist/legal-core/index.cjs +115 -0
- package/dist/legal-core/index.d.ts +160 -0
- package/dist/legal-core/index.d.ts.map +1 -0
- package/dist/legal-core/index.js +220 -0
- package/dist/legal-core/index.js.map +1 -0
- package/dist/marketing-core/index.d.ts +66 -0
- package/dist/marketing-core/index.d.ts.map +1 -0
- package/dist/marketing-core/index.js +154 -0
- package/dist/marketing-core/index.js.map +1 -0
- package/dist/marketing.d.ts +7 -0
- package/dist/marketing.d.ts.map +1 -0
- package/dist/marketing.js +7 -0
- package/dist/marketing.js.map +1 -0
- package/dist/mcp-adapters/index.d.ts +135 -0
- package/dist/mcp-adapters/index.d.ts.map +1 -0
- package/dist/mcp-adapters/index.js +187 -0
- package/dist/mcp-adapters/index.js.map +1 -0
- package/dist/mcp-adapters.d.ts +7 -0
- package/dist/mcp-adapters.d.ts.map +1 -0
- package/dist/mcp-adapters.js +7 -0
- package/dist/mcp-adapters.js.map +1 -0
- package/dist/model3d-core/index.cjs +95 -0
- package/dist/model3d-core/index.d.ts +167 -0
- package/dist/model3d-core/index.d.ts.map +1 -0
- package/dist/model3d-core/index.js +158 -0
- package/dist/model3d-core/index.js.map +1 -0
- package/dist/notifications-core/index.cjs +315 -0
- package/dist/notifications-core/index.d.ts +229 -0
- package/dist/notifications-core/index.d.ts.map +1 -0
- package/dist/notifications-core/index.js +445 -0
- package/dist/notifications-core/index.js.map +1 -0
- package/dist/portal-core/index.d.ts +451 -0
- package/dist/portal-core/index.d.ts.map +1 -0
- package/dist/portal-core/index.js +819 -0
- package/dist/portal-core/index.js.map +1 -0
- package/dist/portal.d.ts +7 -0
- package/dist/portal.d.ts.map +1 -0
- package/dist/portal.js +7 -0
- package/dist/portal.js.map +1 -0
- package/dist/push-core/index.cjs +171 -0
- package/dist/push-core/index.d.ts +149 -0
- package/dist/push-core/index.d.ts.map +1 -0
- package/dist/push-core/index.js +231 -0
- package/dist/push-core/index.js.map +1 -0
- package/dist/react-marketing.d.ts +1 -17
- package/dist/react-marketing.d.ts.map +1 -1
- package/dist/react-marketing.js +4 -0
- package/dist/react-marketing.js.map +1 -1
- package/dist/react.d.ts +294 -101
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +302 -246
- package/dist/react.js.map +1 -1
- package/dist/seed-core/index.d.ts +354 -0
- package/dist/seed-core/index.d.ts.map +1 -0
- package/dist/seed-core/index.js +420 -0
- package/dist/seed-core/index.js.map +1 -0
- package/dist/seed.d.ts +7 -0
- package/dist/seed.d.ts.map +1 -0
- package/dist/seed.js +7 -0
- package/dist/seed.js.map +1 -0
- package/dist/seo-core/blog.d.ts +94 -0
- package/dist/seo-core/blog.d.ts.map +1 -0
- package/dist/seo-core/blog.js +149 -0
- package/dist/seo-core/blog.js.map +1 -0
- package/dist/seo-core/commerce.d.ts +64 -0
- package/dist/seo-core/commerce.d.ts.map +1 -0
- package/dist/seo-core/commerce.js +87 -0
- package/dist/seo-core/commerce.js.map +1 -0
- package/dist/seo-core/index.cjs +751 -0
- package/dist/seo-core/index.d.ts +226 -0
- package/dist/seo-core/index.d.ts.map +1 -0
- package/dist/seo-core/index.js +455 -0
- package/dist/seo-core/index.js.map +1 -0
- package/dist/seo-core/local.d.ts +181 -0
- package/dist/seo-core/local.d.ts.map +1 -0
- package/dist/seo-core/local.js +193 -0
- package/dist/seo-core/local.js.map +1 -0
- package/dist/sitemap-core/index.cjs +167 -0
- package/dist/sitemap-core/index.d.ts +155 -0
- package/dist/sitemap-core/index.d.ts.map +1 -0
- package/dist/sitemap-core/index.js +195 -0
- package/dist/sitemap-core/index.js.map +1 -0
- package/dist/social-core/index.d.ts +74 -0
- package/dist/social-core/index.d.ts.map +1 -0
- package/dist/social-core/index.js +72 -0
- package/dist/social-core/index.js.map +1 -0
- package/dist/social.d.ts +7 -0
- package/dist/social.d.ts.map +1 -0
- package/dist/social.js +7 -0
- package/dist/social.js.map +1 -0
- package/dist/solid-compat.d.ts +204 -0
- package/dist/solid-compat.d.ts.map +1 -0
- package/dist/solid-compat.js +221 -0
- package/dist/solid-compat.js.map +1 -0
- package/dist/store-core/index.d.ts +141 -0
- package/dist/store-core/index.d.ts.map +1 -0
- package/dist/store-core/index.js +277 -0
- package/dist/store-core/index.js.map +1 -0
- package/dist/store.d.ts +12 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +12 -0
- package/dist/store.js.map +1 -0
- package/dist/vanilla.d.ts +111 -0
- package/dist/vanilla.d.ts.map +1 -1
- package/dist/vanilla.js +206 -0
- package/dist/vanilla.js.map +1 -1
- package/dist/verify-core/index.d.ts +98 -0
- package/dist/verify-core/index.d.ts.map +1 -0
- package/dist/verify-core/index.js +186 -0
- package/dist/verify-core/index.js.map +1 -0
- package/dist/verify.d.ts +8 -0
- package/dist/verify.d.ts.map +1 -0
- package/dist/verify.js +8 -0
- package/dist/verify.js.map +1 -0
- package/openapi.json +4516 -1311
- package/package.json +128 -11
- package/src/account-core/index.ts +309 -0
- package/src/account.ts +11 -0
- package/src/angular/headless.ts +519 -0
- package/src/angular/index.ts +3 -0
- package/src/auth-links.ts +76 -0
- package/src/blog-core/index.ts +423 -0
- package/src/blog.ts +11 -0
- package/src/chat-core/index.ts +335 -0
- package/src/chat.ts +11 -0
- package/src/checkout-core/index.ts +225 -0
- package/src/checkout.ts +10 -0
- package/src/cli.ts +184 -28
- package/src/client.ts +1097 -0
- package/src/consent-core/index.ts +213 -0
- package/src/contracts.ts +768 -11
- package/src/data-model-schema.ts +1 -1
- package/src/element.ts +102 -0
- package/src/embed-protocol.ts +100 -0
- package/src/framework-support.ts +440 -0
- package/src/legal-core/index.ts +276 -0
- package/src/marketing-core/index.ts +209 -0
- package/src/marketing.ts +7 -0
- package/src/mcp-adapters/index.ts +264 -0
- package/src/mcp-adapters.ts +7 -0
- package/src/model3d-core/index.ts +248 -0
- package/src/notifications-core/index.ts +650 -0
- package/src/portal-core/index.ts +1564 -0
- package/src/portal.ts +7 -0
- package/src/push-core/index.ts +335 -0
- package/src/qwik.tsx +602 -2
- package/src/react-marketing.tsx +5 -0
- package/src/react.tsx +434 -319
- package/src/seed-core/index.ts +735 -0
- package/src/seed.ts +7 -0
- package/src/seo-core/blog.ts +216 -0
- package/src/seo-core/commerce.ts +138 -0
- package/src/seo-core/index.ts +605 -0
- package/src/seo-core/local.ts +333 -0
- package/src/sitemap-core/index.ts +296 -0
- package/src/social-core/index.ts +103 -0
- package/src/social.ts +7 -0
- package/src/solid-compat.tsx +347 -0
- package/src/solid-surfaces.tsx +1311 -0
- package/src/solid.tsx +82 -60
- package/src/store-core/index.ts +426 -0
- package/src/store.ts +12 -0
- package/src/svelte/SocialLinks.svelte +84 -0
- package/src/svelte/headless.ts +435 -0
- package/src/svelte/index.ts +9 -0
- package/src/vanilla.ts +367 -0
- package/src/verify-core/index.ts +288 -0
- package/src/verify.ts +8 -0
- package/src/vue/headless.ts +527 -0
- package/src/vue/index.ts +3 -0
package/src/qwik.tsx
CHANGED
|
@@ -269,13 +269,16 @@ const BiabFieldInput = component$<{
|
|
|
269
269
|
) : null;
|
|
270
270
|
|
|
271
271
|
case "textarea":
|
|
272
|
+
// `autocomplete` and `accept` below are SPREAD rather than passed as
|
|
273
|
+
// `attr={maybeUndefined}`. Under `exactOptionalPropertyTypes` an
|
|
274
|
+
// optional attribute must be absent, not present-and-undefined.
|
|
272
275
|
return (
|
|
273
276
|
<textarea
|
|
274
277
|
class="biab-input biab-textarea"
|
|
275
278
|
value={asString(value)}
|
|
276
279
|
placeholder={field.placeholder || ""}
|
|
277
280
|
rows={4}
|
|
278
|
-
|
|
281
|
+
{...(autoComplete ? { autocomplete: autoComplete as AutoFill } : {})}
|
|
279
282
|
onInput$={(_, el) => void set((el as HTMLTextAreaElement).value)}
|
|
280
283
|
/>
|
|
281
284
|
);
|
|
@@ -656,7 +659,7 @@ const BiabFieldInput = component$<{
|
|
|
656
659
|
class="biab-file__input"
|
|
657
660
|
type="file"
|
|
658
661
|
multiple={maxFiles > 1}
|
|
659
|
-
accept
|
|
662
|
+
{...(accept ? { accept } : {})}
|
|
660
663
|
disabled={uploading || remaining === 0}
|
|
661
664
|
onChange$={async (_, el) => {
|
|
662
665
|
const picked = (el as HTMLInputElement).files;
|
|
@@ -1232,3 +1235,600 @@ export const BiabForm = component$<BiabFormProps>((props) => {
|
|
|
1232
1235
|
});
|
|
1233
1236
|
|
|
1234
1237
|
export default BiabForm;
|
|
1238
|
+
|
|
1239
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1240
|
+
// Native storefront + chat
|
|
1241
|
+
//
|
|
1242
|
+
// The controllers are NOT serializable, so they can never live in a `useStore`
|
|
1243
|
+
// or cross Qwik's resumability boundary. They are created inside
|
|
1244
|
+
// `useVisibleTask$` — client-side, after hydration — and their snapshots are
|
|
1245
|
+
// copied into a serializable signal that the template reads. That is the same
|
|
1246
|
+
// shape `<BiabForm>` already uses for its controller.
|
|
1247
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1248
|
+
|
|
1249
|
+
import {
|
|
1250
|
+
createFollowersController,
|
|
1251
|
+
createUserController,
|
|
1252
|
+
type FollowersController,
|
|
1253
|
+
type FollowersSnapshot,
|
|
1254
|
+
type UserController,
|
|
1255
|
+
type UserSnapshot,
|
|
1256
|
+
} from "./account-core/index.js";
|
|
1257
|
+
import {
|
|
1258
|
+
type CheckoutController,
|
|
1259
|
+
type CheckoutSnapshot,
|
|
1260
|
+
createCheckoutController,
|
|
1261
|
+
} from "./checkout-core/index.js";
|
|
1262
|
+
import {
|
|
1263
|
+
createPortalController,
|
|
1264
|
+
type PortalController,
|
|
1265
|
+
type PortalSnapshot,
|
|
1266
|
+
} from "./portal-core/index.js";
|
|
1267
|
+
import {
|
|
1268
|
+
createMarketingController,
|
|
1269
|
+
type MarketingController,
|
|
1270
|
+
type MarketingSnapshot,
|
|
1271
|
+
} from "./marketing-core/index.js";
|
|
1272
|
+
import {
|
|
1273
|
+
type CreateVerifyControllerOptions,
|
|
1274
|
+
createVerifyController,
|
|
1275
|
+
type VerifyController,
|
|
1276
|
+
type VerifySnapshot,
|
|
1277
|
+
} from "./verify-core/index.js";
|
|
1278
|
+
import { createBiabClient as createBiabClientForFollowers } from "./sdk.js";
|
|
1279
|
+
import {
|
|
1280
|
+
type BlogController,
|
|
1281
|
+
type BlogSnapshot,
|
|
1282
|
+
createBlogController,
|
|
1283
|
+
} from "./blog-core/index.js";
|
|
1284
|
+
import {
|
|
1285
|
+
type ChatController,
|
|
1286
|
+
type ChatSnapshot,
|
|
1287
|
+
createChatController,
|
|
1288
|
+
} from "./chat-core/index.js";
|
|
1289
|
+
import { BiabDevClient as BiabDevClientForSurfaces } from "./client.js";
|
|
1290
|
+
import {
|
|
1291
|
+
createStoreController,
|
|
1292
|
+
type StoreController,
|
|
1293
|
+
type StoreSnapshot,
|
|
1294
|
+
} from "./store-core/index.js";
|
|
1295
|
+
|
|
1296
|
+
export type UseStorefrontOptions = {
|
|
1297
|
+
apiKey: string;
|
|
1298
|
+
baseUrl: string;
|
|
1299
|
+
pageSize?: number;
|
|
1300
|
+
categoryId?: string | null;
|
|
1301
|
+
};
|
|
1302
|
+
|
|
1303
|
+
/**
|
|
1304
|
+
* Headless storefront + cart.
|
|
1305
|
+
*
|
|
1306
|
+
* Returns a signal of the snapshot plus QRL-safe actions. Actions are plain
|
|
1307
|
+
* functions closed over the client-side controller, so call them from an
|
|
1308
|
+
* event handler (`onClick$`) rather than during render.
|
|
1309
|
+
*
|
|
1310
|
+
* ```tsx
|
|
1311
|
+
* const store = useStorefront({ apiKey, baseUrl });
|
|
1312
|
+
* return <>{store.state.value.products.map((p) => <MyCard product={p} />)}</>;
|
|
1313
|
+
* ```
|
|
1314
|
+
*/
|
|
1315
|
+
export function useStorefront(options: UseStorefrontOptions) {
|
|
1316
|
+
const state = useSignal<StoreSnapshot | null>(null);
|
|
1317
|
+
// `noSerialize` is mandatory, not stylistic: a controller holds a client, a
|
|
1318
|
+
// subscriber set and timers. Qwik would try to serialise it into the HTML on
|
|
1319
|
+
// pause and throw. Marked this way it simply becomes `undefined` after a
|
|
1320
|
+
// resume, which is correct — the visible task recreates it client-side.
|
|
1321
|
+
const actions = useStore<{ current: NoSerialize<StoreController> | undefined }>(
|
|
1322
|
+
{ current: undefined },
|
|
1323
|
+
{ deep: false },
|
|
1324
|
+
);
|
|
1325
|
+
|
|
1326
|
+
useVisibleTask$(({ cleanup }) => {
|
|
1327
|
+
const controller = createStoreController({
|
|
1328
|
+
client: new BiabDevClientForSurfaces({
|
|
1329
|
+
apiKey: options.apiKey,
|
|
1330
|
+
baseUrl: options.baseUrl,
|
|
1331
|
+
}),
|
|
1332
|
+
...(options.pageSize ? { pageSize: options.pageSize } : {}),
|
|
1333
|
+
...(options.categoryId ? { categoryId: options.categoryId } : {}),
|
|
1334
|
+
});
|
|
1335
|
+
actions.current = noSerialize(controller);
|
|
1336
|
+
state.value = controller.snapshot();
|
|
1337
|
+
const unsubscribe = controller.subscribe((next) => {
|
|
1338
|
+
state.value = next;
|
|
1339
|
+
});
|
|
1340
|
+
void controller.load();
|
|
1341
|
+
cleanup(() => {
|
|
1342
|
+
unsubscribe();
|
|
1343
|
+
controller.destroy();
|
|
1344
|
+
actions.current = undefined;
|
|
1345
|
+
});
|
|
1346
|
+
});
|
|
1347
|
+
|
|
1348
|
+
return {
|
|
1349
|
+
state,
|
|
1350
|
+
loadMore: () => actions.current?.loadMore(),
|
|
1351
|
+
filterByCategory: (id: string | null) =>
|
|
1352
|
+
actions.current?.filterByCategory(id),
|
|
1353
|
+
openProduct: (id: string) => actions.current?.openProduct(id),
|
|
1354
|
+
closeProduct: () => actions.current?.closeProduct(),
|
|
1355
|
+
// biome-ignore lint/suspicious/noExplicitAny: input mirrors CartAddItemInput
|
|
1356
|
+
addToCart: (input: any) => actions.current?.addToCart(input),
|
|
1357
|
+
updateQuantity: (itemId: string, quantity: number) =>
|
|
1358
|
+
actions.current?.updateQuantity(itemId, quantity),
|
|
1359
|
+
removeItem: (itemId: string) => actions.current?.removeItem(itemId),
|
|
1360
|
+
applyCoupon: (code: string) => actions.current?.applyCoupon(code),
|
|
1361
|
+
removeCoupon: () => actions.current?.removeCoupon(),
|
|
1362
|
+
clearCart: () => actions.current?.clearCart(),
|
|
1363
|
+
refreshCart: () => actions.current?.refreshCart(),
|
|
1364
|
+
};
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1367
|
+
export type UseChatOptions = { apiKey: string; baseUrl: string };
|
|
1368
|
+
|
|
1369
|
+
/** Headless Front Desk chat — the native alternative to the iframe widget. */
|
|
1370
|
+
export function useChat(options: UseChatOptions) {
|
|
1371
|
+
const state = useSignal<ChatSnapshot | null>(null);
|
|
1372
|
+
const actions = useStore<{ current: NoSerialize<ChatController> | undefined }>(
|
|
1373
|
+
{ current: undefined },
|
|
1374
|
+
{ deep: false },
|
|
1375
|
+
);
|
|
1376
|
+
|
|
1377
|
+
useVisibleTask$(({ cleanup }) => {
|
|
1378
|
+
const controller = createChatController({
|
|
1379
|
+
client: new BiabDevClientForSurfaces({
|
|
1380
|
+
apiKey: options.apiKey,
|
|
1381
|
+
baseUrl: options.baseUrl,
|
|
1382
|
+
}),
|
|
1383
|
+
});
|
|
1384
|
+
actions.current = noSerialize(controller);
|
|
1385
|
+
state.value = controller.snapshot();
|
|
1386
|
+
const unsubscribe = controller.subscribe((next) => {
|
|
1387
|
+
state.value = next;
|
|
1388
|
+
});
|
|
1389
|
+
cleanup(() => {
|
|
1390
|
+
unsubscribe();
|
|
1391
|
+
controller.destroy();
|
|
1392
|
+
actions.current = undefined;
|
|
1393
|
+
});
|
|
1394
|
+
});
|
|
1395
|
+
|
|
1396
|
+
return {
|
|
1397
|
+
state,
|
|
1398
|
+
send: (content: string) => actions.current?.send(content),
|
|
1399
|
+
reset: () => actions.current?.reset(),
|
|
1400
|
+
loadConfig: () => actions.current?.loadConfig(),
|
|
1401
|
+
refreshAvailability: () => actions.current?.refreshAvailability(),
|
|
1402
|
+
getForm: (slug: string) => actions.current?.getForm(slug),
|
|
1403
|
+
// biome-ignore lint/suspicious/noExplicitAny: input mirrors ChatbotFormSubmitInput
|
|
1404
|
+
submitForm: (slug: string, input: any) =>
|
|
1405
|
+
actions.current?.submitForm(slug, input),
|
|
1406
|
+
// biome-ignore lint/suspicious/noExplicitAny: input mirrors ChatbotRequestHumanInput
|
|
1407
|
+
requestHuman: (input: any) => actions.current?.requestHuman(input),
|
|
1408
|
+
};
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
export type UseBlogOptions = {
|
|
1412
|
+
apiKey: string;
|
|
1413
|
+
baseUrl: string;
|
|
1414
|
+
pageSize?: number;
|
|
1415
|
+
categoryId?: string | null;
|
|
1416
|
+
};
|
|
1417
|
+
|
|
1418
|
+
/** Headless blog — the native alternative to the hosted `<Blog>` iframe. */
|
|
1419
|
+
export function useBlog(options: UseBlogOptions) {
|
|
1420
|
+
const state = useSignal<BlogSnapshot | null>(null);
|
|
1421
|
+
const actions = useStore<{ current: NoSerialize<BlogController> | undefined }>(
|
|
1422
|
+
{ current: undefined },
|
|
1423
|
+
{ deep: false },
|
|
1424
|
+
);
|
|
1425
|
+
|
|
1426
|
+
useVisibleTask$(({ cleanup }) => {
|
|
1427
|
+
const controller = createBlogController({
|
|
1428
|
+
client: new BiabDevClientForSurfaces({
|
|
1429
|
+
apiKey: options.apiKey,
|
|
1430
|
+
baseUrl: options.baseUrl,
|
|
1431
|
+
}),
|
|
1432
|
+
...(options.pageSize ? { pageSize: options.pageSize } : {}),
|
|
1433
|
+
...(options.categoryId ? { categoryId: options.categoryId } : {}),
|
|
1434
|
+
});
|
|
1435
|
+
actions.current = noSerialize(controller);
|
|
1436
|
+
state.value = controller.snapshot();
|
|
1437
|
+
const unsubscribe = controller.subscribe((next) => {
|
|
1438
|
+
state.value = next;
|
|
1439
|
+
});
|
|
1440
|
+
void controller.load();
|
|
1441
|
+
cleanup(() => {
|
|
1442
|
+
unsubscribe();
|
|
1443
|
+
controller.destroy();
|
|
1444
|
+
actions.current = undefined;
|
|
1445
|
+
});
|
|
1446
|
+
});
|
|
1447
|
+
|
|
1448
|
+
return {
|
|
1449
|
+
state,
|
|
1450
|
+
loadMore: () => actions.current?.loadMore(),
|
|
1451
|
+
filterByCategory: (id: string | null) =>
|
|
1452
|
+
actions.current?.filterByCategory(id),
|
|
1453
|
+
openPost: (slug: string) => actions.current?.openPost(slug),
|
|
1454
|
+
closePost: () => actions.current?.closePost(),
|
|
1455
|
+
loadComments: () => actions.current?.loadComments(),
|
|
1456
|
+
loadMoreComments: () => actions.current?.loadMoreComments(),
|
|
1457
|
+
// biome-ignore lint/suspicious/noExplicitAny: input mirrors BlogCommentPostInput
|
|
1458
|
+
postComment: (input: any) => actions.current?.postComment(input),
|
|
1459
|
+
toggleLike: () => actions.current?.toggleLike(),
|
|
1460
|
+
};
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
/** Headless checkout. `start()` mints a session; `redirect()` navigates. */
|
|
1464
|
+
export function useCheckout(options: { apiKey: string; baseUrl: string }) {
|
|
1465
|
+
const state = useSignal<CheckoutSnapshot | null>(null);
|
|
1466
|
+
const actions = useStore<{
|
|
1467
|
+
current: NoSerialize<CheckoutController> | undefined;
|
|
1468
|
+
}>({ current: undefined }, { deep: false });
|
|
1469
|
+
|
|
1470
|
+
useVisibleTask$(({ cleanup }) => {
|
|
1471
|
+
const controller = createCheckoutController({
|
|
1472
|
+
client: new BiabDevClientForSurfaces({
|
|
1473
|
+
apiKey: options.apiKey,
|
|
1474
|
+
baseUrl: options.baseUrl,
|
|
1475
|
+
}),
|
|
1476
|
+
});
|
|
1477
|
+
actions.current = noSerialize(controller);
|
|
1478
|
+
state.value = controller.snapshot();
|
|
1479
|
+
const unsubscribe = controller.subscribe((next) => {
|
|
1480
|
+
state.value = next;
|
|
1481
|
+
});
|
|
1482
|
+
cleanup(() => {
|
|
1483
|
+
unsubscribe();
|
|
1484
|
+
controller.destroy();
|
|
1485
|
+
actions.current = undefined;
|
|
1486
|
+
});
|
|
1487
|
+
});
|
|
1488
|
+
|
|
1489
|
+
return {
|
|
1490
|
+
state,
|
|
1491
|
+
// biome-ignore lint/suspicious/noExplicitAny: input mirrors CheckoutSessionInput
|
|
1492
|
+
start: (input: any) => actions.current?.start(input),
|
|
1493
|
+
redirect: () => actions.current?.redirect(),
|
|
1494
|
+
resolve: (sessionId: string) => actions.current?.resolve(sessionId),
|
|
1495
|
+
reset: () => actions.current?.reset(),
|
|
1496
|
+
};
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1499
|
+
/** The signed-in customer, from the auth handler's `/me`. */
|
|
1500
|
+
export function useUser(options: { basePath?: string } = {}) {
|
|
1501
|
+
const state = useSignal<UserSnapshot | null>(null);
|
|
1502
|
+
const actions = useStore<{ current: NoSerialize<UserController> | undefined }>(
|
|
1503
|
+
{ current: undefined },
|
|
1504
|
+
{ deep: false },
|
|
1505
|
+
);
|
|
1506
|
+
|
|
1507
|
+
useVisibleTask$(({ cleanup }) => {
|
|
1508
|
+
const controller = createUserController(options);
|
|
1509
|
+
actions.current = noSerialize(controller);
|
|
1510
|
+
state.value = controller.snapshot();
|
|
1511
|
+
const unsubscribe = controller.subscribe((next) => {
|
|
1512
|
+
state.value = next;
|
|
1513
|
+
});
|
|
1514
|
+
controller.start();
|
|
1515
|
+
cleanup(() => {
|
|
1516
|
+
unsubscribe();
|
|
1517
|
+
controller.destroy();
|
|
1518
|
+
actions.current = undefined;
|
|
1519
|
+
});
|
|
1520
|
+
});
|
|
1521
|
+
|
|
1522
|
+
return { state, refresh: () => actions.current?.refresh() };
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1525
|
+
/** Newsletter / follower subscribe with the local already-subscribed hint. */
|
|
1526
|
+
export function useFollowers(options: {
|
|
1527
|
+
token: string;
|
|
1528
|
+
siteId: string;
|
|
1529
|
+
baseUrl?: string;
|
|
1530
|
+
}) {
|
|
1531
|
+
const state = useSignal<FollowersSnapshot | null>(null);
|
|
1532
|
+
const actions = useStore<{
|
|
1533
|
+
current: NoSerialize<FollowersController> | undefined;
|
|
1534
|
+
}>({ current: undefined }, { deep: false });
|
|
1535
|
+
|
|
1536
|
+
useVisibleTask$(({ cleanup }) => {
|
|
1537
|
+
const controller = createFollowersController({
|
|
1538
|
+
client: createBiabClientForFollowers({
|
|
1539
|
+
apiKey: options.token,
|
|
1540
|
+
siteId: options.siteId,
|
|
1541
|
+
...(options.baseUrl ? { baseUrl: options.baseUrl } : {}),
|
|
1542
|
+
}),
|
|
1543
|
+
siteId: options.siteId,
|
|
1544
|
+
});
|
|
1545
|
+
actions.current = noSerialize(controller);
|
|
1546
|
+
state.value = controller.snapshot();
|
|
1547
|
+
const unsubscribe = controller.subscribe((next) => {
|
|
1548
|
+
state.value = next;
|
|
1549
|
+
});
|
|
1550
|
+
cleanup(() => {
|
|
1551
|
+
unsubscribe();
|
|
1552
|
+
controller.destroy();
|
|
1553
|
+
actions.current = undefined;
|
|
1554
|
+
});
|
|
1555
|
+
});
|
|
1556
|
+
|
|
1557
|
+
return {
|
|
1558
|
+
state,
|
|
1559
|
+
join: (input: { email: string; name?: string; source?: string }) =>
|
|
1560
|
+
actions.current?.join(input),
|
|
1561
|
+
leave: (email: string) => actions.current?.leave(email),
|
|
1562
|
+
me: (email: string) => actions.current?.me(email),
|
|
1563
|
+
edit: (email: string, patch: { name?: string; source?: string }) =>
|
|
1564
|
+
actions.current?.edit(email, patch),
|
|
1565
|
+
};
|
|
1566
|
+
}
|
|
1567
|
+
|
|
1568
|
+
export {
|
|
1569
|
+
signIn,
|
|
1570
|
+
signInHref,
|
|
1571
|
+
signOut,
|
|
1572
|
+
signOutHref,
|
|
1573
|
+
signUp,
|
|
1574
|
+
signUpHref,
|
|
1575
|
+
} from "./account-core/index.js";
|
|
1576
|
+
|
|
1577
|
+
/** Headless marketing pages — the index, plus one page at a time. */
|
|
1578
|
+
export function useMarketing(options: {
|
|
1579
|
+
token: string;
|
|
1580
|
+
siteId: string;
|
|
1581
|
+
baseUrl?: string;
|
|
1582
|
+
}) {
|
|
1583
|
+
const state = useSignal<MarketingSnapshot | null>(null);
|
|
1584
|
+
const actions = useStore<{
|
|
1585
|
+
current: NoSerialize<MarketingController> | undefined;
|
|
1586
|
+
}>({ current: undefined }, { deep: false });
|
|
1587
|
+
|
|
1588
|
+
useVisibleTask$(({ cleanup }) => {
|
|
1589
|
+
const controller = createMarketingController({
|
|
1590
|
+
client: createBiabClientForFollowers({
|
|
1591
|
+
apiKey: options.token,
|
|
1592
|
+
siteId: options.siteId,
|
|
1593
|
+
...(options.baseUrl ? { baseUrl: options.baseUrl } : {}),
|
|
1594
|
+
}),
|
|
1595
|
+
});
|
|
1596
|
+
actions.current = noSerialize(controller);
|
|
1597
|
+
state.value = controller.snapshot();
|
|
1598
|
+
const unsubscribe = controller.subscribe((next) => {
|
|
1599
|
+
state.value = next;
|
|
1600
|
+
});
|
|
1601
|
+
void controller.load();
|
|
1602
|
+
cleanup(() => {
|
|
1603
|
+
unsubscribe();
|
|
1604
|
+
controller.destroy();
|
|
1605
|
+
actions.current = undefined;
|
|
1606
|
+
});
|
|
1607
|
+
});
|
|
1608
|
+
|
|
1609
|
+
return {
|
|
1610
|
+
state,
|
|
1611
|
+
open: (pageKey?: string, opts?: { skipCache?: boolean }) =>
|
|
1612
|
+
actions.current?.open(pageKey, opts),
|
|
1613
|
+
prefetch: (pageKey?: string) => actions.current?.prefetch(pageKey),
|
|
1614
|
+
close: () => actions.current?.close(),
|
|
1615
|
+
};
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
/** Headless email / phone verification. Read `state.value.flow` before rendering. */
|
|
1619
|
+
export function useVerify(
|
|
1620
|
+
options: { apiKey: string; baseUrl: string } & Omit<
|
|
1621
|
+
CreateVerifyControllerOptions,
|
|
1622
|
+
"client"
|
|
1623
|
+
>,
|
|
1624
|
+
) {
|
|
1625
|
+
const state = useSignal<VerifySnapshot | null>(null);
|
|
1626
|
+
const actions = useStore<{
|
|
1627
|
+
current: NoSerialize<VerifyController> | undefined;
|
|
1628
|
+
}>({ current: undefined }, { deep: false });
|
|
1629
|
+
|
|
1630
|
+
useVisibleTask$(({ cleanup }) => {
|
|
1631
|
+
const { apiKey, baseUrl, ...rest } = options;
|
|
1632
|
+
const controller = createVerifyController({
|
|
1633
|
+
client: new BiabDevClientForSurfaces({ apiKey, baseUrl }),
|
|
1634
|
+
...rest,
|
|
1635
|
+
});
|
|
1636
|
+
actions.current = noSerialize(controller);
|
|
1637
|
+
state.value = controller.snapshot();
|
|
1638
|
+
const unsubscribe = controller.subscribe((next) => {
|
|
1639
|
+
state.value = next;
|
|
1640
|
+
});
|
|
1641
|
+
cleanup(() => {
|
|
1642
|
+
unsubscribe();
|
|
1643
|
+
controller.destroy();
|
|
1644
|
+
actions.current = undefined;
|
|
1645
|
+
});
|
|
1646
|
+
});
|
|
1647
|
+
|
|
1648
|
+
return {
|
|
1649
|
+
state,
|
|
1650
|
+
start: (destination: string) => actions.current?.start(destination),
|
|
1651
|
+
resend: () => actions.current?.resend(),
|
|
1652
|
+
confirm: (token: string) => actions.current?.confirm(token),
|
|
1653
|
+
canResend: (now?: number) => actions.current?.canResend(now) ?? false,
|
|
1654
|
+
reset: () => actions.current?.reset(),
|
|
1655
|
+
};
|
|
1656
|
+
}
|
|
1657
|
+
|
|
1658
|
+
/**
|
|
1659
|
+
* The signed-in customer's portal. `sessionToken` is required — every portal
|
|
1660
|
+
* route is scoped to the customer.
|
|
1661
|
+
*
|
|
1662
|
+
* There are no list endpoints for invoices, quotes, contracts or shipments:
|
|
1663
|
+
* `state.value.work` carries the counts and you open each by id. A submitted
|
|
1664
|
+
* review is queued for staff approval and will not appear in `reviews`.
|
|
1665
|
+
*/
|
|
1666
|
+
export function usePortal(options: {
|
|
1667
|
+
apiKey: string;
|
|
1668
|
+
baseUrl: string;
|
|
1669
|
+
sessionToken: string;
|
|
1670
|
+
}) {
|
|
1671
|
+
const state = useSignal<PortalSnapshot | null>(null);
|
|
1672
|
+
const actions = useStore<{
|
|
1673
|
+
current: NoSerialize<PortalController> | undefined;
|
|
1674
|
+
}>({ current: undefined }, { deep: false });
|
|
1675
|
+
|
|
1676
|
+
useVisibleTask$(({ cleanup }) => {
|
|
1677
|
+
const controller = createPortalController({
|
|
1678
|
+
client: new BiabDevClientForSurfaces({
|
|
1679
|
+
apiKey: options.apiKey,
|
|
1680
|
+
baseUrl: options.baseUrl,
|
|
1681
|
+
}),
|
|
1682
|
+
sessionToken: options.sessionToken,
|
|
1683
|
+
});
|
|
1684
|
+
actions.current = noSerialize(controller);
|
|
1685
|
+
state.value = controller.snapshot();
|
|
1686
|
+
const unsubscribe = controller.subscribe((next) => {
|
|
1687
|
+
state.value = next;
|
|
1688
|
+
});
|
|
1689
|
+
void controller.load();
|
|
1690
|
+
cleanup(() => {
|
|
1691
|
+
unsubscribe();
|
|
1692
|
+
controller.destroy();
|
|
1693
|
+
actions.current = undefined;
|
|
1694
|
+
});
|
|
1695
|
+
});
|
|
1696
|
+
|
|
1697
|
+
return {
|
|
1698
|
+
state,
|
|
1699
|
+
loadOrders: (opts?: { limit?: number }) =>
|
|
1700
|
+
actions.current?.loadOrders(opts),
|
|
1701
|
+
loadInvoices: (opts?: {
|
|
1702
|
+
limit?: number;
|
|
1703
|
+
status?: string;
|
|
1704
|
+
unpaid?: boolean;
|
|
1705
|
+
}) => actions.current?.loadInvoices(opts),
|
|
1706
|
+
loadQuotes: (opts?: { limit?: number; status?: string }) =>
|
|
1707
|
+
actions.current?.loadQuotes(opts),
|
|
1708
|
+
loadContracts: (opts?: { limit?: number; status?: string }) =>
|
|
1709
|
+
actions.current?.loadContracts(opts),
|
|
1710
|
+
loadShipments: (opts?: { limit?: number; active?: boolean }) =>
|
|
1711
|
+
actions.current?.loadShipments(opts),
|
|
1712
|
+
loadMessages: (opts?: { limit?: number; jobId?: string }) =>
|
|
1713
|
+
actions.current?.loadMessages(opts),
|
|
1714
|
+
// biome-ignore lint/suspicious/noExplicitAny: input mirrors the contract
|
|
1715
|
+
postMessage: (input: any) => actions.current?.postMessage(input),
|
|
1716
|
+
markMessagesRead: () => actions.current?.markMessagesRead(),
|
|
1717
|
+
loadPayments: (opts?: { limit?: number }) =>
|
|
1718
|
+
actions.current?.loadPayments(opts),
|
|
1719
|
+
loadReviews: () => actions.current?.loadReviews(),
|
|
1720
|
+
loadReferrals: () => actions.current?.loadReferrals(),
|
|
1721
|
+
loadNotificationPreferences: () =>
|
|
1722
|
+
actions.current?.loadNotificationPreferences(),
|
|
1723
|
+
loadOtherOrgs: () => actions.current?.loadOtherOrgs(),
|
|
1724
|
+
openJob: (id: string) => actions.current?.openJob(id),
|
|
1725
|
+
openOrder: (id: string) => actions.current?.openOrder(id),
|
|
1726
|
+
openInvoice: (id: string) => actions.current?.openInvoice(id),
|
|
1727
|
+
openQuote: (id: string) => actions.current?.openQuote(id),
|
|
1728
|
+
openContract: (id: string) => actions.current?.openContract(id),
|
|
1729
|
+
trackShipment: (id: string) => actions.current?.trackShipment(id),
|
|
1730
|
+
closeDetail: () => actions.current?.closeDetail(),
|
|
1731
|
+
// biome-ignore lint/suspicious/noExplicitAny: inputs mirror the contracts
|
|
1732
|
+
postJobComment: (jobId: string, input: any) =>
|
|
1733
|
+
actions.current?.postJobComment(jobId, input),
|
|
1734
|
+
acceptQuote: (id: string) => actions.current?.acceptQuote(id),
|
|
1735
|
+
rejectQuote: (id: string) => actions.current?.rejectQuote(id),
|
|
1736
|
+
signContract: (id: string) => actions.current?.signContract(id),
|
|
1737
|
+
// biome-ignore lint/suspicious/noExplicitAny: inputs mirror the contracts
|
|
1738
|
+
payInvoice: (id: string, opts?: any) =>
|
|
1739
|
+
actions.current?.payInvoice(id, opts),
|
|
1740
|
+
// biome-ignore lint/suspicious/noExplicitAny: inputs mirror the contracts
|
|
1741
|
+
updateProfile: (input: any) => actions.current?.updateProfile(input),
|
|
1742
|
+
// biome-ignore lint/suspicious/noExplicitAny: inputs mirror the contracts
|
|
1743
|
+
updateNotificationPreferences: (input: any) =>
|
|
1744
|
+
actions.current?.updateNotificationPreferences(input),
|
|
1745
|
+
// biome-ignore lint/suspicious/noExplicitAny: inputs mirror the contracts
|
|
1746
|
+
submitReview: (input: any) => actions.current?.submitReview(input),
|
|
1747
|
+
// biome-ignore lint/suspicious/noExplicitAny: inputs mirror the contracts
|
|
1748
|
+
submitReturnRequest: (orderId: string, input?: any) =>
|
|
1749
|
+
actions.current?.submitReturnRequest(orderId, input),
|
|
1750
|
+
// biome-ignore lint/suspicious/noExplicitAny: inputs mirror the contracts
|
|
1751
|
+
contactCompany: (input: any) => actions.current?.contactCompany(input),
|
|
1752
|
+
};
|
|
1753
|
+
}
|
|
1754
|
+
|
|
1755
|
+
import {
|
|
1756
|
+
resolveSocialLinks,
|
|
1757
|
+
SOCIAL_FALLBACK_GLYPH,
|
|
1758
|
+
SOCIAL_LIST_STYLE,
|
|
1759
|
+
} from "./social-core/index.js";
|
|
1760
|
+
|
|
1761
|
+
export type SocialLinksProps = {
|
|
1762
|
+
/** The company profile's `socials` record. */
|
|
1763
|
+
socials: unknown;
|
|
1764
|
+
/** Icon colour — hex without `#`, or a CSS keyword. */
|
|
1765
|
+
color?: string;
|
|
1766
|
+
/** Icon edge length in px. */
|
|
1767
|
+
size?: number;
|
|
1768
|
+
linkClass?: string;
|
|
1769
|
+
iconClass?: string;
|
|
1770
|
+
};
|
|
1771
|
+
|
|
1772
|
+
/**
|
|
1773
|
+
* The company's social profiles as icon links.
|
|
1774
|
+
*
|
|
1775
|
+
* Pure render from serializable props, so it needs no `useVisibleTask$` and
|
|
1776
|
+
* survives resumption untouched — unlike the controller-backed surfaces above.
|
|
1777
|
+
*/
|
|
1778
|
+
export const SocialLinks = component$<SocialLinksProps>((props) => {
|
|
1779
|
+
const size = props.size ?? 20;
|
|
1780
|
+
const rows = resolveSocialLinks(props.socials, {
|
|
1781
|
+
...(props.color ? { color: props.color } : {}),
|
|
1782
|
+
});
|
|
1783
|
+
// Nothing at all rather than an empty <ul> in a footer.
|
|
1784
|
+
if (rows.length === 0) return null;
|
|
1785
|
+
|
|
1786
|
+
return (
|
|
1787
|
+
<ul style={SOCIAL_LIST_STYLE}>
|
|
1788
|
+
{rows.map((row) => (
|
|
1789
|
+
<li key={row.key}>
|
|
1790
|
+
<a
|
|
1791
|
+
aria-label={row.label}
|
|
1792
|
+
class={props.linkClass}
|
|
1793
|
+
href={row.url}
|
|
1794
|
+
rel="noopener noreferrer"
|
|
1795
|
+
target="_blank"
|
|
1796
|
+
title={row.label}
|
|
1797
|
+
>
|
|
1798
|
+
{row.iconUrl ? (
|
|
1799
|
+
<img
|
|
1800
|
+
alt={row.label}
|
|
1801
|
+
class={props.iconClass}
|
|
1802
|
+
height={size}
|
|
1803
|
+
loading="lazy"
|
|
1804
|
+
src={row.iconUrl}
|
|
1805
|
+
width={size}
|
|
1806
|
+
/>
|
|
1807
|
+
) : (
|
|
1808
|
+
<svg
|
|
1809
|
+
aria-hidden="true"
|
|
1810
|
+
class={props.iconClass}
|
|
1811
|
+
fill="none"
|
|
1812
|
+
height={size}
|
|
1813
|
+
stroke="currentColor"
|
|
1814
|
+
stroke-width={SOCIAL_FALLBACK_GLYPH.strokeWidth}
|
|
1815
|
+
viewBox={SOCIAL_FALLBACK_GLYPH.viewBox}
|
|
1816
|
+
width={size}
|
|
1817
|
+
>
|
|
1818
|
+
<title>{row.label}</title>
|
|
1819
|
+
<circle
|
|
1820
|
+
cx={SOCIAL_FALLBACK_GLYPH.circle.cx}
|
|
1821
|
+
cy={SOCIAL_FALLBACK_GLYPH.circle.cy}
|
|
1822
|
+
r={SOCIAL_FALLBACK_GLYPH.circle.r}
|
|
1823
|
+
/>
|
|
1824
|
+
<path d={SOCIAL_FALLBACK_GLYPH.path} />
|
|
1825
|
+
</svg>
|
|
1826
|
+
)}
|
|
1827
|
+
</a>
|
|
1828
|
+
</li>
|
|
1829
|
+
))}
|
|
1830
|
+
</ul>
|
|
1831
|
+
);
|
|
1832
|
+
});
|
|
1833
|
+
|
|
1834
|
+
export { resolveSocialLinks } from "./social-core/index.js";
|
package/src/react-marketing.tsx
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* React hooks for the schema-driven marketing-page flow.
|
|
3
5
|
*
|
|
6
|
+
* Marked client-side in its own right, not just via `react.tsx`, so a deep
|
|
7
|
+
* import lands on the same boundary as the barrel export.
|
|
8
|
+
*
|
|
4
9
|
* The base SDK file (`react.tsx`) is already past the workspace's
|
|
5
10
|
* "stop and ask before growing" file-size threshold, so these new hooks
|
|
6
11
|
* live alongside it in their own module. Same import target for
|