@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
|
@@ -0,0 +1,527 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@businessdash/sdk/vue` — headless storefront + chat.
|
|
3
|
+
*
|
|
4
|
+
* `<Storefront>` and `<Chatbot>` are hosted pages in a sandboxed iframe: quick
|
|
5
|
+
* to adopt, but they render BusinessDash's markup rather than yours. These
|
|
6
|
+
* composables are the native path — all behaviour, no markup.
|
|
7
|
+
*
|
|
8
|
+
* Everything real lives in `store-core` / `chat-core`, shared with every other
|
|
9
|
+
* binding. This file only bridges a controller's subscribe/snapshot observable
|
|
10
|
+
* into a Vue ref, and ties teardown to the component's scope.
|
|
11
|
+
*
|
|
12
|
+
* @module
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { defineComponent, h, onScopeDispose, type PropType, type Ref, shallowRef } from "vue";
|
|
16
|
+
|
|
17
|
+
import {
|
|
18
|
+
type BlogController,
|
|
19
|
+
type BlogSnapshot,
|
|
20
|
+
createBlogController,
|
|
21
|
+
} from "../blog-core/index.js";
|
|
22
|
+
import {
|
|
23
|
+
type ChatController,
|
|
24
|
+
type ChatSnapshot,
|
|
25
|
+
createChatController,
|
|
26
|
+
} from "../chat-core/index.js";
|
|
27
|
+
import { BiabDevClient } from "../client.js";
|
|
28
|
+
import {
|
|
29
|
+
createPortalController,
|
|
30
|
+
type PortalSnapshot,
|
|
31
|
+
} from "../portal-core/index.js";
|
|
32
|
+
|
|
33
|
+
import {
|
|
34
|
+
createMarketingController,
|
|
35
|
+
type MarketingController,
|
|
36
|
+
type MarketingSnapshot,
|
|
37
|
+
} from "../marketing-core/index.js";
|
|
38
|
+
import {
|
|
39
|
+
createVerifyController,
|
|
40
|
+
type CreateVerifyControllerOptions,
|
|
41
|
+
type VerifyController,
|
|
42
|
+
type VerifySnapshot,
|
|
43
|
+
} from "../verify-core/index.js";
|
|
44
|
+
|
|
45
|
+
import {
|
|
46
|
+
createFollowersController,
|
|
47
|
+
createUserController,
|
|
48
|
+
type FollowersController,
|
|
49
|
+
type FollowersSnapshot,
|
|
50
|
+
type UserController,
|
|
51
|
+
type UserSnapshot,
|
|
52
|
+
} from "../account-core/index.js";
|
|
53
|
+
import {
|
|
54
|
+
type CheckoutController,
|
|
55
|
+
type CheckoutSnapshot,
|
|
56
|
+
createCheckoutController,
|
|
57
|
+
} from "../checkout-core/index.js";
|
|
58
|
+
import { createBiabClient } from "../sdk.js";
|
|
59
|
+
|
|
60
|
+
import type {
|
|
61
|
+
BlogCommentPostInput,
|
|
62
|
+
CartAddItemInput,
|
|
63
|
+
ChatbotFormSubmitInput,
|
|
64
|
+
ChatbotRequestHumanInput,
|
|
65
|
+
CustomerPortalMessagePostInput,
|
|
66
|
+
} from "../contracts.js";
|
|
67
|
+
import {
|
|
68
|
+
createStoreController,
|
|
69
|
+
type StoreController,
|
|
70
|
+
type StoreSnapshot,
|
|
71
|
+
} from "../store-core/index.js";
|
|
72
|
+
|
|
73
|
+
type Observable<TSnapshot> = {
|
|
74
|
+
snapshot(): TSnapshot;
|
|
75
|
+
subscribe(cb: (s: TSnapshot) => void): () => void;
|
|
76
|
+
destroy(): void;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Seed a ref from `snapshot()`, then subscribe.
|
|
81
|
+
*
|
|
82
|
+
* The seed is not optional: the cores deliberately do NOT replay on subscribe,
|
|
83
|
+
* so a ref that only listened would render empty until the first change.
|
|
84
|
+
*
|
|
85
|
+
* `shallowRef` rather than `ref` — the snapshot is replaced wholesale on every
|
|
86
|
+
* notification, so deep reactivity would walk the entire product list on each
|
|
87
|
+
* update to discover what the controller already told us.
|
|
88
|
+
*/
|
|
89
|
+
function bridge<TSnapshot>(
|
|
90
|
+
// Typed structurally rather than as a second generic: with
|
|
91
|
+
// `<TSnapshot, TController extends Observable<TSnapshot>>` only `TController`
|
|
92
|
+
// is inferable from the argument, so `TSnapshot` silently falls back to
|
|
93
|
+
// `unknown` and every consumer loses the snapshot's type.
|
|
94
|
+
controller: Observable<TSnapshot>,
|
|
95
|
+
start?: () => void,
|
|
96
|
+
): Ref<TSnapshot> {
|
|
97
|
+
const state = shallowRef<TSnapshot>(controller.snapshot());
|
|
98
|
+
const unsubscribe = controller.subscribe((next) => {
|
|
99
|
+
state.value = next;
|
|
100
|
+
});
|
|
101
|
+
start?.();
|
|
102
|
+
onScopeDispose(() => {
|
|
103
|
+
unsubscribe();
|
|
104
|
+
controller.destroy();
|
|
105
|
+
});
|
|
106
|
+
return state;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export type UseStorefrontOptions = {
|
|
110
|
+
apiKey: string;
|
|
111
|
+
baseUrl: string;
|
|
112
|
+
pageSize?: number;
|
|
113
|
+
categoryId?: string | null;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export type UseStorefrontResult = {
|
|
117
|
+
state: Ref<StoreSnapshot>;
|
|
118
|
+
} & Omit<StoreController, "snapshot" | "subscribe" | "destroy" | "load">;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Headless storefront + cart.
|
|
122
|
+
*
|
|
123
|
+
* ```vue
|
|
124
|
+
* <script setup lang="ts">
|
|
125
|
+
* const { state, addToCart } = useStorefront({ apiKey, baseUrl })
|
|
126
|
+
* </script>
|
|
127
|
+
* <template>
|
|
128
|
+
* <MyCard v-for="p in state.products" :key="p.id" :product="p" />
|
|
129
|
+
* </template>
|
|
130
|
+
* ```
|
|
131
|
+
*/
|
|
132
|
+
export function useStorefront(
|
|
133
|
+
options: UseStorefrontOptions,
|
|
134
|
+
): UseStorefrontResult {
|
|
135
|
+
const controller = createStoreController({
|
|
136
|
+
client: new BiabDevClient({
|
|
137
|
+
apiKey: options.apiKey,
|
|
138
|
+
baseUrl: options.baseUrl,
|
|
139
|
+
}),
|
|
140
|
+
...(options.pageSize ? { pageSize: options.pageSize } : {}),
|
|
141
|
+
...(options.categoryId ? { categoryId: options.categoryId } : {}),
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
const state = bridge(controller, () => void controller.load());
|
|
145
|
+
|
|
146
|
+
return {
|
|
147
|
+
state,
|
|
148
|
+
loadMore: () => controller.loadMore(),
|
|
149
|
+
filterByCategory: (id: string | null) => controller.filterByCategory(id),
|
|
150
|
+
openProduct: (id: string) => controller.openProduct(id),
|
|
151
|
+
closeProduct: () => controller.closeProduct(),
|
|
152
|
+
addToCart: (input: CartAddItemInput) => controller.addToCart(input),
|
|
153
|
+
updateQuantity: (itemId: string, quantity: number) =>
|
|
154
|
+
controller.updateQuantity(itemId, quantity),
|
|
155
|
+
removeItem: (itemId: string) => controller.removeItem(itemId),
|
|
156
|
+
applyCoupon: (code: string) => controller.applyCoupon(code),
|
|
157
|
+
removeCoupon: () => controller.removeCoupon(),
|
|
158
|
+
clearCart: () => controller.clearCart(),
|
|
159
|
+
refreshCart: () => controller.refreshCart(),
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export type UseChatOptions = { apiKey: string; baseUrl: string };
|
|
164
|
+
|
|
165
|
+
export type UseChatResult = {
|
|
166
|
+
state: Ref<ChatSnapshot>;
|
|
167
|
+
} & Omit<ChatController, "snapshot" | "subscribe" | "destroy">;
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Headless Front Desk chat — the native alternative to `<Chatbot>`.
|
|
171
|
+
*
|
|
172
|
+
* ```vue
|
|
173
|
+
* <script setup lang="ts">
|
|
174
|
+
* const { state, send } = useChat({ apiKey, baseUrl })
|
|
175
|
+
* </script>
|
|
176
|
+
* <template>
|
|
177
|
+
* <Bubble v-for="(m, i) in state.messages" :key="i" :message="m" />
|
|
178
|
+
* </template>
|
|
179
|
+
* ```
|
|
180
|
+
*/
|
|
181
|
+
export function useChat(options: UseChatOptions): UseChatResult {
|
|
182
|
+
const controller = createChatController({
|
|
183
|
+
client: new BiabDevClient({
|
|
184
|
+
apiKey: options.apiKey,
|
|
185
|
+
baseUrl: options.baseUrl,
|
|
186
|
+
}),
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
const state = bridge(controller);
|
|
190
|
+
|
|
191
|
+
return {
|
|
192
|
+
state,
|
|
193
|
+
send: (content: string) => controller.send(content),
|
|
194
|
+
reset: () => controller.reset(),
|
|
195
|
+
loadConfig: () => controller.loadConfig(),
|
|
196
|
+
refreshAvailability: () => controller.refreshAvailability(),
|
|
197
|
+
getForm: (slug: string) => controller.getForm(slug),
|
|
198
|
+
submitForm: (slug: string, input: ChatbotFormSubmitInput) =>
|
|
199
|
+
controller.submitForm(slug, input),
|
|
200
|
+
requestHuman: (input: ChatbotRequestHumanInput) =>
|
|
201
|
+
controller.requestHuman(input),
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export type UseBlogOptions = {
|
|
206
|
+
apiKey: string;
|
|
207
|
+
baseUrl: string;
|
|
208
|
+
pageSize?: number;
|
|
209
|
+
categoryId?: string | null;
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
export type UseBlogResult = {
|
|
213
|
+
state: Ref<BlogSnapshot>;
|
|
214
|
+
} & Omit<BlogController, "snapshot" | "subscribe" | "destroy" | "load">;
|
|
215
|
+
|
|
216
|
+
/** Headless blog — the native alternative to `<Blog>`. */
|
|
217
|
+
export function useBlog(options: UseBlogOptions): UseBlogResult {
|
|
218
|
+
const controller = createBlogController({
|
|
219
|
+
client: new BiabDevClient({
|
|
220
|
+
apiKey: options.apiKey,
|
|
221
|
+
baseUrl: options.baseUrl,
|
|
222
|
+
}),
|
|
223
|
+
...(options.pageSize ? { pageSize: options.pageSize } : {}),
|
|
224
|
+
...(options.categoryId ? { categoryId: options.categoryId } : {}),
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
const state = bridge(controller, () => void controller.load());
|
|
228
|
+
|
|
229
|
+
return {
|
|
230
|
+
state,
|
|
231
|
+
loadMore: () => controller.loadMore(),
|
|
232
|
+
filterByCategory: (id: string | null) => controller.filterByCategory(id),
|
|
233
|
+
openPost: (slug: string) => controller.openPost(slug),
|
|
234
|
+
closePost: () => controller.closePost(),
|
|
235
|
+
loadComments: () => controller.loadComments(),
|
|
236
|
+
loadMoreComments: () => controller.loadMoreComments(),
|
|
237
|
+
postComment: (input: BlogCommentPostInput) =>
|
|
238
|
+
controller.postComment(input),
|
|
239
|
+
toggleLike: () => controller.toggleLike(),
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
export type UseCheckoutOptions = { apiKey: string; baseUrl: string };
|
|
244
|
+
export type UseCheckoutResult = {
|
|
245
|
+
state: Ref<CheckoutSnapshot>;
|
|
246
|
+
} & Omit<CheckoutController, "snapshot" | "subscribe" | "destroy">;
|
|
247
|
+
|
|
248
|
+
/** Headless checkout. `start()` mints a session; `redirect()` navigates. */
|
|
249
|
+
export function useCheckout(options: UseCheckoutOptions): UseCheckoutResult {
|
|
250
|
+
const controller = createCheckoutController({
|
|
251
|
+
client: new BiabDevClient({
|
|
252
|
+
apiKey: options.apiKey,
|
|
253
|
+
baseUrl: options.baseUrl,
|
|
254
|
+
}),
|
|
255
|
+
});
|
|
256
|
+
const state = bridge(controller);
|
|
257
|
+
return {
|
|
258
|
+
state,
|
|
259
|
+
start: (input) => controller.start(input),
|
|
260
|
+
redirect: () => controller.redirect(),
|
|
261
|
+
resolve: (sessionId: string) => controller.resolve(sessionId),
|
|
262
|
+
reset: () => controller.reset(),
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
export type UseUserResult = {
|
|
267
|
+
state: Ref<UserSnapshot>;
|
|
268
|
+
refresh: () => Promise<UserSnapshot>;
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
/** The signed-in customer, from the auth handler's `/me`. */
|
|
272
|
+
export function useUser(options: { basePath?: string } = {}): UseUserResult {
|
|
273
|
+
const controller = createUserController(options);
|
|
274
|
+
const state = bridge(controller, () => controller.start());
|
|
275
|
+
return { state, refresh: () => controller.refresh() };
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
export type UseFollowersOptions = {
|
|
279
|
+
token: string;
|
|
280
|
+
siteId: string;
|
|
281
|
+
baseUrl?: string;
|
|
282
|
+
};
|
|
283
|
+
export type UseFollowersResult = {
|
|
284
|
+
state: Ref<FollowersSnapshot>;
|
|
285
|
+
} & Omit<FollowersController, "snapshot" | "subscribe" | "destroy">;
|
|
286
|
+
|
|
287
|
+
/** Newsletter / follower subscribe with the local already-subscribed hint. */
|
|
288
|
+
export function useFollowers(
|
|
289
|
+
options: UseFollowersOptions,
|
|
290
|
+
): UseFollowersResult {
|
|
291
|
+
const controller = createFollowersController({
|
|
292
|
+
client: createBiabClient({
|
|
293
|
+
apiKey: options.token,
|
|
294
|
+
siteId: options.siteId,
|
|
295
|
+
...(options.baseUrl ? { baseUrl: options.baseUrl } : {}),
|
|
296
|
+
}),
|
|
297
|
+
siteId: options.siteId,
|
|
298
|
+
});
|
|
299
|
+
const state = bridge(controller);
|
|
300
|
+
return {
|
|
301
|
+
state,
|
|
302
|
+
join: (input) => controller.join(input),
|
|
303
|
+
leave: (email: string) => controller.leave(email),
|
|
304
|
+
me: (email: string) => controller.me(email),
|
|
305
|
+
edit: (email: string, patch: { name?: string; source?: string }) =>
|
|
306
|
+
controller.edit(email, patch),
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
export {
|
|
311
|
+
signIn,
|
|
312
|
+
signInHref,
|
|
313
|
+
signOut,
|
|
314
|
+
signOutHref,
|
|
315
|
+
signUp,
|
|
316
|
+
signUpHref,
|
|
317
|
+
} from "../account-core/index.js";
|
|
318
|
+
|
|
319
|
+
export type UseMarketingOptions = {
|
|
320
|
+
token: string;
|
|
321
|
+
siteId: string;
|
|
322
|
+
baseUrl?: string;
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
/** Headless marketing pages — the index, plus one page at a time. */
|
|
326
|
+
export function useMarketing(options: UseMarketingOptions) {
|
|
327
|
+
const controller = createMarketingController({
|
|
328
|
+
client: createBiabClient({
|
|
329
|
+
apiKey: options.token,
|
|
330
|
+
siteId: options.siteId,
|
|
331
|
+
...(options.baseUrl ? { baseUrl: options.baseUrl } : {}),
|
|
332
|
+
}),
|
|
333
|
+
});
|
|
334
|
+
const state = bridge(controller, () => void controller.load());
|
|
335
|
+
return {
|
|
336
|
+
state,
|
|
337
|
+
open: (pageKey?: string, opts?: { skipCache?: boolean }) =>
|
|
338
|
+
controller.open(pageKey, opts),
|
|
339
|
+
prefetch: (pageKey?: string) => controller.prefetch(pageKey),
|
|
340
|
+
close: () => controller.close(),
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
export type UseVerifyOptions = {
|
|
345
|
+
apiKey: string;
|
|
346
|
+
baseUrl: string;
|
|
347
|
+
} & Omit<CreateVerifyControllerOptions, "client">;
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Headless email / phone verification.
|
|
351
|
+
*
|
|
352
|
+
* Read `state.flow` before rendering: `otp` wants a code field, `link` wants a
|
|
353
|
+
* "check your email" message and no field at all.
|
|
354
|
+
*/
|
|
355
|
+
export function useVerify(options: UseVerifyOptions) {
|
|
356
|
+
const { apiKey, baseUrl, ...rest } = options;
|
|
357
|
+
const controller = createVerifyController({
|
|
358
|
+
client: new BiabDevClient({ apiKey, baseUrl }),
|
|
359
|
+
...rest,
|
|
360
|
+
});
|
|
361
|
+
const state = bridge(controller);
|
|
362
|
+
return {
|
|
363
|
+
state,
|
|
364
|
+
start: (destination: string) => controller.start(destination),
|
|
365
|
+
resend: () => controller.resend(),
|
|
366
|
+
confirm: (token: string) => controller.confirm(token),
|
|
367
|
+
canResend: (now?: number) => controller.canResend(now),
|
|
368
|
+
reset: () => controller.reset(),
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
export type UsePortalOptions = {
|
|
373
|
+
apiKey: string;
|
|
374
|
+
baseUrl: string;
|
|
375
|
+
sessionToken: string;
|
|
376
|
+
};
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* The signed-in customer's portal — work, quotes, contracts, invoices, orders,
|
|
380
|
+
* downloads, shipping, reviews, referrals, profile and notification settings.
|
|
381
|
+
*
|
|
382
|
+
* `sessionToken` is required: every portal route is scoped to the signed-in
|
|
383
|
+
* customer, and without one the portal renders empty rather than signed-out.
|
|
384
|
+
*
|
|
385
|
+
* Note two things the API itself imposes. There are no list endpoints for
|
|
386
|
+
* invoices, quotes, contracts or shipments — `state.work` carries the counts
|
|
387
|
+
* and you open each by id. And a submitted review is queued for staff approval,
|
|
388
|
+
* so it will not appear in `state.reviews`; watch `reviewAwaitingModeration`.
|
|
389
|
+
*/
|
|
390
|
+
export function usePortal(options: UsePortalOptions) {
|
|
391
|
+
const controller = createPortalController({
|
|
392
|
+
client: new BiabDevClient({
|
|
393
|
+
apiKey: options.apiKey,
|
|
394
|
+
baseUrl: options.baseUrl,
|
|
395
|
+
}),
|
|
396
|
+
sessionToken: options.sessionToken,
|
|
397
|
+
});
|
|
398
|
+
const state: Ref<PortalSnapshot> = bridge(controller, () => void controller.load());
|
|
399
|
+
return {
|
|
400
|
+
state,
|
|
401
|
+
load: () => controller.load(),
|
|
402
|
+
loadOrders: (opts?: { limit?: number }) => controller.loadOrders(opts),
|
|
403
|
+
loadInvoices: (opts?: {
|
|
404
|
+
limit?: number;
|
|
405
|
+
status?: string;
|
|
406
|
+
unpaid?: boolean;
|
|
407
|
+
}) => controller.loadInvoices(opts),
|
|
408
|
+
loadQuotes: (opts?: { limit?: number; status?: string }) =>
|
|
409
|
+
controller.loadQuotes(opts),
|
|
410
|
+
loadContracts: (opts?: { limit?: number; status?: string }) =>
|
|
411
|
+
controller.loadContracts(opts),
|
|
412
|
+
loadShipments: (opts?: { limit?: number; active?: boolean }) =>
|
|
413
|
+
controller.loadShipments(opts),
|
|
414
|
+
loadMessages: (opts?: { limit?: number; jobId?: string }) =>
|
|
415
|
+
controller.loadMessages(opts),
|
|
416
|
+
postMessage: (input: CustomerPortalMessagePostInput) =>
|
|
417
|
+
controller.postMessage(input),
|
|
418
|
+
markMessagesRead: () => controller.markMessagesRead(),
|
|
419
|
+
loadPayments: (opts?: { limit?: number }) => controller.loadPayments(opts),
|
|
420
|
+
loadReviews: () => controller.loadReviews(),
|
|
421
|
+
loadReferrals: () => controller.loadReferrals(),
|
|
422
|
+
loadNotificationPreferences: () => controller.loadNotificationPreferences(),
|
|
423
|
+
loadOtherOrgs: () => controller.loadOtherOrgs(),
|
|
424
|
+
openJob: (id: string) => controller.openJob(id),
|
|
425
|
+
openOrder: (id: string) => controller.openOrder(id),
|
|
426
|
+
openInvoice: (id: string) => controller.openInvoice(id),
|
|
427
|
+
openQuote: (id: string) => controller.openQuote(id),
|
|
428
|
+
openContract: (id: string) => controller.openContract(id),
|
|
429
|
+
trackShipment: (id: string) => controller.trackShipment(id),
|
|
430
|
+
closeDetail: () => controller.closeDetail(),
|
|
431
|
+
postJobComment: controller.postJobComment,
|
|
432
|
+
acceptQuote: (id: string) => controller.acceptQuote(id),
|
|
433
|
+
rejectQuote: (id: string) => controller.rejectQuote(id),
|
|
434
|
+
signContract: (id: string) => controller.signContract(id),
|
|
435
|
+
payInvoice: controller.payInvoice,
|
|
436
|
+
updateProfile: controller.updateProfile,
|
|
437
|
+
updateNotificationPreferences: controller.updateNotificationPreferences,
|
|
438
|
+
submitReview: controller.submitReview,
|
|
439
|
+
submitReturnRequest: controller.submitReturnRequest,
|
|
440
|
+
contactCompany: controller.contactCompany,
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
import {
|
|
445
|
+
resolveSocialLinks,
|
|
446
|
+
SOCIAL_FALLBACK_GLYPH,
|
|
447
|
+
SOCIAL_LIST_STYLE,
|
|
448
|
+
} from "../social-core/index.js";
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* The company's social profiles as icon links.
|
|
452
|
+
*
|
|
453
|
+
* Written as a render function rather than an SFC on purpose: an SFC would put
|
|
454
|
+
* this binding back outside the typechecker, and the markup is six elements.
|
|
455
|
+
*/
|
|
456
|
+
export const SocialLinks = defineComponent({
|
|
457
|
+
name: "BiabSocialLinks",
|
|
458
|
+
props: {
|
|
459
|
+
/** The company profile's `socials` record. */
|
|
460
|
+
socials: { type: null as unknown as PropType<unknown>, required: true },
|
|
461
|
+
/** Icon colour — hex without `#`, or a CSS keyword. */
|
|
462
|
+
color: { type: String, default: undefined },
|
|
463
|
+
/** Icon edge length in px. */
|
|
464
|
+
size: { type: Number, default: 20 },
|
|
465
|
+
linkClass: { type: String, default: undefined },
|
|
466
|
+
iconClass: { type: String, default: undefined },
|
|
467
|
+
},
|
|
468
|
+
setup(props) {
|
|
469
|
+
return () => {
|
|
470
|
+
const rows = resolveSocialLinks(props.socials, { color: props.color });
|
|
471
|
+
// Nothing at all rather than an empty list — a bare <ul> in a footer
|
|
472
|
+
// is worse than no list.
|
|
473
|
+
if (rows.length === 0) return null;
|
|
474
|
+
|
|
475
|
+
return h(
|
|
476
|
+
"ul",
|
|
477
|
+
{ style: SOCIAL_LIST_STYLE },
|
|
478
|
+
rows.map((row) =>
|
|
479
|
+
h("li", { key: row.key }, [
|
|
480
|
+
h(
|
|
481
|
+
"a",
|
|
482
|
+
{
|
|
483
|
+
href: row.url,
|
|
484
|
+
target: "_blank",
|
|
485
|
+
rel: "noopener noreferrer",
|
|
486
|
+
title: row.label,
|
|
487
|
+
"aria-label": row.label,
|
|
488
|
+
class: props.linkClass,
|
|
489
|
+
},
|
|
490
|
+
[
|
|
491
|
+
row.iconUrl
|
|
492
|
+
? h("img", {
|
|
493
|
+
src: row.iconUrl,
|
|
494
|
+
alt: row.label,
|
|
495
|
+
width: props.size,
|
|
496
|
+
height: props.size,
|
|
497
|
+
loading: "lazy",
|
|
498
|
+
class: props.iconClass,
|
|
499
|
+
})
|
|
500
|
+
: h(
|
|
501
|
+
"svg",
|
|
502
|
+
{
|
|
503
|
+
viewBox: SOCIAL_FALLBACK_GLYPH.viewBox,
|
|
504
|
+
width: props.size,
|
|
505
|
+
height: props.size,
|
|
506
|
+
fill: "none",
|
|
507
|
+
stroke: "currentColor",
|
|
508
|
+
"stroke-width": SOCIAL_FALLBACK_GLYPH.strokeWidth,
|
|
509
|
+
"aria-hidden": "true",
|
|
510
|
+
class: props.iconClass,
|
|
511
|
+
},
|
|
512
|
+
[
|
|
513
|
+
h("title", null, row.label),
|
|
514
|
+
h("circle", SOCIAL_FALLBACK_GLYPH.circle),
|
|
515
|
+
h("path", { d: SOCIAL_FALLBACK_GLYPH.path }),
|
|
516
|
+
],
|
|
517
|
+
),
|
|
518
|
+
],
|
|
519
|
+
),
|
|
520
|
+
]),
|
|
521
|
+
),
|
|
522
|
+
);
|
|
523
|
+
};
|
|
524
|
+
},
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
export { resolveSocialLinks } from "../social-core/index.js";
|