@businessdash/sdk 0.9.81 → 0.9.90
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 +115 -902
- package/assets/{biab-sw.js → bd-sw.js} +2 -2
- package/dist/account-core/index.d.ts +1 -1
- package/dist/account-core/index.d.ts.map +1 -1
- package/dist/adapters-revalidate.d.ts +2 -2
- package/dist/adapters-revalidate.js +2 -2
- package/dist/adapters-revalidate.js.map +1 -1
- package/dist/analytics-core.d.ts +6 -6
- package/dist/analytics-core.d.ts.map +1 -1
- package/dist/analytics-core.js +4 -4
- package/dist/analytics-core.js.map +1 -1
- package/dist/analytics-server.d.ts +6 -6
- package/dist/analytics-server.d.ts.map +1 -1
- package/dist/analytics-server.js +5 -5
- package/dist/auth-handler.d.ts +14 -14
- package/dist/auth-handler.d.ts.map +1 -1
- package/dist/auth-handler.js +16 -16
- package/dist/auth-handler.js.map +1 -1
- package/dist/auth-links.d.ts +2 -2
- package/dist/auth-links.d.ts.map +1 -1
- package/dist/auth-links.js +2 -2
- package/dist/auth-links.js.map +1 -1
- package/dist/{biab-forms.css → bd-forms.css} +158 -158
- package/dist/cli.d.ts +4 -4
- package/dist/cli.js +78 -78
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +158 -147
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +156 -137
- package/dist/client.js.map +1 -1
- package/dist/consent-core/index.cjs +2 -2
- package/dist/consent-core/index.d.ts +2 -2
- package/dist/consent-core/index.d.ts.map +1 -1
- package/dist/consent-core/index.js +10 -8
- package/dist/consent-core/index.js.map +1 -1
- package/dist/contracts.d.ts +411 -52
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js +89 -15
- package/dist/contracts.js.map +1 -1
- package/dist/data-model-schema.d.ts +15 -15
- package/dist/data-model-schema.d.ts.map +1 -1
- package/dist/data-model-schema.js +19 -17
- package/dist/data-model-schema.js.map +1 -1
- package/dist/distribution.d.ts +5 -5
- package/dist/distribution.d.ts.map +1 -1
- package/dist/distribution.js +4 -4
- package/dist/element.d.ts +36 -36
- package/dist/element.d.ts.map +1 -1
- package/dist/element.js +43 -43
- package/dist/element.js.map +1 -1
- package/dist/embed-protocol.d.ts +11 -11
- package/dist/embed-protocol.d.ts.map +1 -1
- package/dist/embed-protocol.js +1 -1
- package/dist/embed-protocol.js.map +1 -1
- package/dist/errors.d.ts +15 -15
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +18 -18
- package/dist/errors.js.map +1 -1
- package/dist/forms-core/autocomplete.d.ts +3 -3
- package/dist/forms-core/autocomplete.d.ts.map +1 -1
- package/dist/forms-core/autocomplete.js +2 -2
- package/dist/forms-core/controller.d.ts +10 -10
- package/dist/forms-core/controller.d.ts.map +1 -1
- package/dist/forms-core/controller.js +4 -4
- package/dist/forms-core/controller.js.map +1 -1
- package/dist/forms-core/elements.d.ts +4 -4
- package/dist/forms-core/elements.d.ts.map +1 -1
- package/dist/forms-core/elements.js +7 -7
- package/dist/forms-core/elements.js.map +1 -1
- package/dist/forms-core/formula.d.ts +1 -1
- package/dist/forms-core/formula.js +1 -1
- package/dist/forms-core/index.d.ts +6 -6
- package/dist/forms-core/index.d.ts.map +1 -1
- package/dist/forms-core/index.js +5 -5
- package/dist/forms-core/index.js.map +1 -1
- package/dist/forms-core/units.d.ts +1 -1
- package/dist/forms-core/units.js +1 -1
- package/dist/forms-core/us-states.d.ts +1 -1
- package/dist/forms-core/us-states.js +1 -1
- package/dist/forms-core/validation.d.ts +12 -3
- package/dist/forms-core/validation.d.ts.map +1 -1
- package/dist/forms-core/validation.js +152 -17
- package/dist/forms-core/validation.js.map +1 -1
- package/dist/forms.d.ts +2 -2
- package/dist/forms.d.ts.map +1 -1
- package/dist/forms.js +2 -2
- package/dist/forms.js.map +1 -1
- package/dist/framework-support.js +1 -1
- package/dist/framework-support.js.map +1 -1
- package/dist/gallery-types.d.ts +1 -1
- package/dist/graphql.d.ts +3 -3
- package/dist/graphql.d.ts.map +1 -1
- package/dist/graphql.js +3 -3
- package/dist/graphql.js.map +1 -1
- package/dist/index.cjs +350 -273
- package/dist/index.d.cts +5 -5
- package/dist/index.d.mts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -5
- package/dist/index.js.map +1 -1
- package/dist/legal-core/index.cjs +8 -8
- package/dist/legal-core/index.d.ts +3 -3
- package/dist/legal-core/index.d.ts.map +1 -1
- package/dist/legal-core/index.js +11 -11
- package/dist/legal-core/index.js.map +1 -1
- package/dist/marketing-core/index.d.ts +51 -1
- package/dist/marketing-core/index.d.ts.map +1 -1
- package/dist/marketing-core/index.js +35 -0
- package/dist/marketing-core/index.js.map +1 -1
- package/dist/marketing-schema.d.ts +9 -9
- package/dist/marketing-schema.d.ts.map +1 -1
- package/dist/marketing-schema.js +1 -1
- package/dist/mcp.d.ts +4 -4
- package/dist/mcp.js +4 -4
- package/dist/native.d.ts +6 -6
- package/dist/native.d.ts.map +1 -1
- package/dist/native.js +4 -4
- package/dist/native.js.map +1 -1
- package/dist/next-revalidate.d.ts +8 -8
- package/dist/next-revalidate.d.ts.map +1 -1
- package/dist/next-revalidate.js +7 -7
- package/dist/next-revalidate.js.map +1 -1
- package/dist/notifications-core/index.d.ts +1 -1
- package/dist/notifications-core/index.js +1 -1
- package/dist/parallel-pages.d.ts +4 -4
- package/dist/parallel-pages.d.ts.map +1 -1
- package/dist/parallel-pages.js +5 -5
- package/dist/parallel-pages.js.map +1 -1
- package/dist/portal-core/index.d.ts +1 -1
- package/dist/portal-core/index.js +1 -1
- package/dist/proxy.d.ts +18 -18
- package/dist/proxy.d.ts.map +1 -1
- package/dist/proxy.js +10 -10
- package/dist/proxy.js.map +1 -1
- package/dist/push-core/index.cjs +1 -1
- package/dist/push-core/index.d.ts +1 -1
- package/dist/push-core/index.js +1 -1
- package/dist/push-core/index.js.map +1 -1
- package/dist/react-analytics.d.ts +14 -14
- package/dist/react-analytics.d.ts.map +1 -1
- package/dist/react-analytics.js +15 -15
- package/dist/react-analytics.js.map +1 -1
- package/dist/react-attribution.d.ts +2 -2
- package/dist/react-attribution.d.ts.map +1 -1
- package/dist/react-attribution.js +1 -1
- package/dist/react-marketing.js +5 -5
- package/dist/react-marketing.js.map +1 -1
- package/dist/react.d.ts +38 -61
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +247 -261
- package/dist/react.js.map +1 -1
- package/dist/reserved-paths.d.ts +2 -2
- package/dist/reserved-paths.js +3 -3
- package/dist/reserved-paths.js.map +1 -1
- package/dist/revalidate-verify.d.ts +3 -3
- package/dist/revalidate-verify.d.ts.map +1 -1
- package/dist/revalidate-verify.js +1 -1
- package/dist/revalidate-verify.js.map +1 -1
- package/dist/sdk.d.ts +49 -49
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +47 -51
- package/dist/sdk.js.map +1 -1
- package/dist/seed-core/index.js +8 -8
- package/dist/seed-core/index.js.map +1 -1
- package/dist/seo-core/blog.d.ts +1 -1
- package/dist/seo-core/blog.js +1 -1
- package/dist/seo-core/blog.js.map +1 -1
- package/dist/seo-core/index.cjs +2 -2
- package/dist/seo-core/index.js +1 -1
- package/dist/seo-core/index.js.map +1 -1
- package/dist/seo.d.ts +1 -1
- package/dist/seo.d.ts.map +1 -1
- package/dist/seo.js +1 -1
- package/dist/seo.js.map +1 -1
- package/dist/sitemap-core/index.cjs +3 -3
- package/dist/sitemap-core/index.js +2 -2
- package/dist/sitemap-core/index.js.map +1 -1
- package/dist/socials.d.ts +6 -6
- package/dist/socials.d.ts.map +1 -1
- package/dist/socials.js +5 -5
- package/dist/socials.js.map +1 -1
- package/dist/solid-compat.d.ts +1 -1
- package/dist/solid-compat.js +4 -4
- package/dist/solid-compat.js.map +1 -1
- package/dist/store-core/index.d.ts +1 -1
- package/dist/vanilla.d.ts +12 -12
- package/dist/vanilla.d.ts.map +1 -1
- package/dist/vanilla.js +192 -145
- package/dist/vanilla.js.map +1 -1
- package/openapi.json +264 -1
- package/package.json +8 -8
- package/src/account-core/index.ts +1 -1
- package/src/adapters-revalidate.ts +3 -3
- package/src/analytics-core.ts +8 -8
- package/src/analytics-server.ts +6 -6
- package/src/angular/{biab-form.component.ts → bd-form.component.ts} +269 -161
- package/src/angular/headless.ts +12 -12
- package/src/angular/index.ts +9 -9
- package/src/auth-handler.ts +22 -22
- package/src/auth-links.ts +2 -2
- package/src/cli.ts +81 -81
- package/src/client.ts +218 -193
- package/src/consent-core/index.ts +10 -8
- package/src/contracts.ts +99 -15
- package/src/data-model-schema.ts +29 -26
- package/src/distribution.ts +5 -5
- package/src/element.ts +54 -54
- package/src/embed-protocol.ts +14 -14
- package/src/errors.ts +27 -27
- package/src/forms-core/autocomplete.ts +3 -3
- package/src/forms-core/controller.ts +12 -12
- package/src/forms-core/elements.ts +7 -7
- package/src/forms-core/formula.ts +1 -1
- package/src/forms-core/index.ts +8 -8
- package/src/forms-core/units.ts +1 -1
- package/src/forms-core/us-states.ts +1 -1
- package/src/forms-core/validation.ts +158 -14
- package/src/forms.ts +2 -2
- package/src/framework-support.ts +1 -1
- package/src/gallery-types.ts +1 -1
- package/src/graphql.ts +4 -4
- package/src/index.ts +38 -38
- package/src/legal-core/index.ts +12 -12
- package/src/marketing-core/index.ts +62 -0
- package/src/marketing-schema.ts +9 -9
- package/src/mcp.ts +4 -4
- package/src/native.ts +14 -14
- package/src/next-revalidate.ts +10 -10
- package/src/notifications-core/index.ts +1 -1
- package/src/parallel-pages.ts +6 -6
- package/src/portal-core/index.ts +1 -1
- package/src/proxy.ts +28 -28
- package/src/push-core/index.ts +2 -2
- package/src/qwik.tsx +262 -166
- package/src/react-analytics.tsx +17 -17
- package/src/react-attribution.tsx +2 -2
- package/src/react-marketing.tsx +5 -5
- package/src/react.tsx +541 -500
- package/src/reserved-paths.ts +3 -3
- package/src/revalidate-verify.ts +5 -5
- package/src/sdk.ts +106 -110
- package/src/seed-core/index.ts +8 -8
- package/src/seo-core/blog.ts +2 -2
- package/src/seo-core/index.ts +1 -1
- package/src/seo.ts +1 -1
- package/src/sitemap-core/index.ts +2 -2
- package/src/socials.ts +6 -6
- package/src/solid-compat.tsx +5 -5
- package/src/solid-surfaces.tsx +28 -28
- package/src/solid.tsx +264 -175
- package/src/store-core/index.ts +1 -1
- package/src/styles/{biab-forms.css → bd-forms.css} +158 -158
- package/src/svelte/{BiabForm.svelte → BdForm.svelte} +240 -173
- package/src/svelte/context.ts +16 -16
- package/src/svelte/headless.ts +10 -10
- package/src/svelte/index.ts +16 -16
- package/src/vanilla.ts +250 -169
- package/src/vue/{BiabForm.vue → BdForm.vue} +270 -157
- package/src/vue/headless.ts +11 -11
- package/src/vue/index.ts +26 -26
package/src/qwik.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** @jsxImportSource @builder.io/qwik */
|
|
2
2
|
/**
|
|
3
|
-
* `@businessdash/sdk/qwik` — the `<
|
|
3
|
+
* `@businessdash/sdk/qwik` — the `<BdForm>` drop-in for Qwik / Qwik City.
|
|
4
4
|
*
|
|
5
5
|
* Ship mode: SOURCE (.tsx). The consumer's Qwik optimizer compiles this file —
|
|
6
6
|
* it is never tsc-built into `dist`. Keep it syntactically valid Qwik JSX and
|
|
@@ -10,16 +10,16 @@
|
|
|
10
10
|
* ─── Architecture ────────────────────────────────────────────────────────────
|
|
11
11
|
* The headless `createFormController` (`@businessdash/sdk/forms`) owns ALL of the
|
|
12
12
|
* form's runtime state and behaviour — values, condition-aware visibility,
|
|
13
|
-
* validation mirrored 1:1 from the
|
|
13
|
+
* validation mirrored 1:1 from the BD server, multi-step nav + progress,
|
|
14
14
|
* concurrent-reveal gating, the submit lifecycle, and file uploads. This binding
|
|
15
15
|
* stays dumb: it
|
|
16
16
|
* 1. builds the controller (client-side, inside `useVisibleTask$`),
|
|
17
17
|
* 2. mirrors its `snapshot()` into a Qwik `useStore` on every `subscribe`
|
|
18
18
|
* notify (the idiomatic bridge from an external observable into Qwik
|
|
19
19
|
* reactivity), and
|
|
20
|
-
* 3. renders the nested field tree by `type` using the `
|
|
20
|
+
* 3. renders the nested field tree by `type` using the `bd-*` light-DOM
|
|
21
21
|
* class convention — the SAME classes the dashboard `FormPreview` renderer
|
|
22
|
-
* uses, so a consumer's `
|
|
22
|
+
* uses, so a consumer's `bd-*` CSS overrides cascade identically and the
|
|
23
23
|
* drop-in reproduces the dashboard preview (animation, multi-step progress
|
|
24
24
|
* bar/labels, concurrent reveal, org icon).
|
|
25
25
|
*
|
|
@@ -46,7 +46,7 @@ import {
|
|
|
46
46
|
$,
|
|
47
47
|
} from "@builder.io/qwik";
|
|
48
48
|
|
|
49
|
-
import type {
|
|
49
|
+
import type { BdClient } from "@businessdash/sdk";
|
|
50
50
|
import {
|
|
51
51
|
type FormCoreField,
|
|
52
52
|
type FormController,
|
|
@@ -87,7 +87,7 @@ type ServerCompatQRL<Args extends unknown[], R> = QRL<
|
|
|
87
87
|
// Public props — consistent with the other framework bindings.
|
|
88
88
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
89
89
|
|
|
90
|
-
export interface
|
|
90
|
+
export interface BdFormProps {
|
|
91
91
|
/**
|
|
92
92
|
* Pre-fetched form schema (SSR / `routeLoader$`). PREFERRED on Qwik — it is
|
|
93
93
|
* serializable, keeps the bearer key server-side, and renders without a
|
|
@@ -99,7 +99,7 @@ export interface BiabFormProps {
|
|
|
99
99
|
* it pulls the schema and (unless `submit$` is given) submits from the
|
|
100
100
|
* browser. For SSR apps, prefer `schema` + `submit$`.
|
|
101
101
|
*/
|
|
102
|
-
client?:
|
|
102
|
+
client?: BdClient;
|
|
103
103
|
/** Form slug. Required with `client` (the pre-fetched `schema` carries its own). */
|
|
104
104
|
slug?: string;
|
|
105
105
|
|
|
@@ -159,7 +159,7 @@ export interface BiabFormProps {
|
|
|
159
159
|
/** Fires after a failed submit (`result.ok === false`). */
|
|
160
160
|
onError$?: QRL<(result: Extract<FormSubmitResult, { ok: false }>) => void>;
|
|
161
161
|
|
|
162
|
-
/** Extra class on the root `.
|
|
162
|
+
/** Extra class on the root `.bd-form`. Both `class` and `className` work. */
|
|
163
163
|
class?: string;
|
|
164
164
|
className?: string;
|
|
165
165
|
}
|
|
@@ -176,7 +176,7 @@ type SnapshotState = { snap: FormSnapshot | null };
|
|
|
176
176
|
type ControllerRef = { value: FormController | undefined };
|
|
177
177
|
|
|
178
178
|
/** The resolved server-side upload delegate threaded to `file_upload` fields. */
|
|
179
|
-
type UploadDelegate =
|
|
179
|
+
type UploadDelegate = BdFormProps["uploadFile$"];
|
|
180
180
|
|
|
181
181
|
/**
|
|
182
182
|
* Build the initial snapshot for SSR from a pre-fetched schema so the fields
|
|
@@ -198,7 +198,7 @@ function seedSnapshot(schema: FormSchema | undefined): FormSnapshot | null {
|
|
|
198
198
|
|
|
199
199
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
200
200
|
// Field rendering — a faithful port of the dashboard `FormPreview` per-type
|
|
201
|
-
// switch, using `
|
|
201
|
+
// switch, using `bd-*` classes (light DOM). Qwik JSX uses `class`, not
|
|
202
202
|
// `className`, and `onInput$` / `onClick$` event QRLs.
|
|
203
203
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
204
204
|
|
|
@@ -211,7 +211,7 @@ const NO_LABEL_TYPES = new Set([
|
|
|
211
211
|
"image",
|
|
212
212
|
]);
|
|
213
213
|
|
|
214
|
-
/** Stable, override-friendly CSS hook for a field (the `data-
|
|
214
|
+
/** Stable, override-friendly CSS hook for a field (the `data-bd-field` value). */
|
|
215
215
|
function fieldCssKey(field: FormCoreField): string {
|
|
216
216
|
const explicit =
|
|
217
217
|
typeof field.outputKey === "string" ? field.outputKey.trim() : "";
|
|
@@ -233,7 +233,7 @@ function asString(value: unknown): string {
|
|
|
233
233
|
* via the controller's `setValue` / `uploadFile`. Renders by `type` exactly as
|
|
234
234
|
* the dashboard preview does.
|
|
235
235
|
*/
|
|
236
|
-
const
|
|
236
|
+
const BdFieldInput = component$<{
|
|
237
237
|
field: FormCoreField;
|
|
238
238
|
controllerSig: ControllerRef;
|
|
239
239
|
state: SnapshotState;
|
|
@@ -253,19 +253,19 @@ const BiabFieldInput = component$<{
|
|
|
253
253
|
|
|
254
254
|
switch (field.type) {
|
|
255
255
|
case "title":
|
|
256
|
-
return <h2 class="
|
|
256
|
+
return <h2 class="bd-field__title">{field.label || "Untitled"}</h2>;
|
|
257
257
|
case "subtitle":
|
|
258
|
-
return <h3 class="
|
|
258
|
+
return <h3 class="bd-field__subtitle">{field.label || ""}</h3>;
|
|
259
259
|
case "separator":
|
|
260
|
-
return <hr class="
|
|
260
|
+
return <hr class="bd-field__separator" />;
|
|
261
261
|
case "richtext":
|
|
262
262
|
// `content` is server-sanitized HTML on publish.
|
|
263
263
|
return field.content ? (
|
|
264
|
-
<div class="
|
|
264
|
+
<div class="bd-field__richtext" dangerouslySetInnerHTML={field.content} />
|
|
265
265
|
) : null;
|
|
266
266
|
case "image":
|
|
267
267
|
return field.content ? (
|
|
268
|
-
<img class="
|
|
268
|
+
<img class="bd-field__image" src={field.content} alt={field.label || ""} />
|
|
269
269
|
) : null;
|
|
270
270
|
|
|
271
271
|
case "textarea":
|
|
@@ -274,7 +274,7 @@ const BiabFieldInput = component$<{
|
|
|
274
274
|
// optional attribute must be absent, not present-and-undefined.
|
|
275
275
|
return (
|
|
276
276
|
<textarea
|
|
277
|
-
class="
|
|
277
|
+
class="bd-input bd-textarea"
|
|
278
278
|
value={asString(value)}
|
|
279
279
|
placeholder={field.placeholder || ""}
|
|
280
280
|
rows={4}
|
|
@@ -286,7 +286,7 @@ const BiabFieldInput = component$<{
|
|
|
286
286
|
case "select":
|
|
287
287
|
return (
|
|
288
288
|
<select
|
|
289
|
-
class="
|
|
289
|
+
class="bd-input bd-select"
|
|
290
290
|
value={asString(value)}
|
|
291
291
|
onChange$={(_, el) => void set((el as HTMLSelectElement).value)}
|
|
292
292
|
>
|
|
@@ -301,9 +301,9 @@ const BiabFieldInput = component$<{
|
|
|
301
301
|
|
|
302
302
|
case "radio":
|
|
303
303
|
return (
|
|
304
|
-
<div class="
|
|
304
|
+
<div class="bd-radio-group">
|
|
305
305
|
{(field.options ?? []).map((opt) => (
|
|
306
|
-
<label class="
|
|
306
|
+
<label class="bd-radio" key={opt}>
|
|
307
307
|
<input
|
|
308
308
|
type="radio"
|
|
309
309
|
name={field.id}
|
|
@@ -320,11 +320,11 @@ const BiabFieldInput = component$<{
|
|
|
320
320
|
case "checkbox": {
|
|
321
321
|
const arr = Array.isArray(value) ? (value as string[]) : [];
|
|
322
322
|
return (
|
|
323
|
-
<div class="
|
|
323
|
+
<div class="bd-checkbox-group">
|
|
324
324
|
{(field.options ?? []).map((opt) => {
|
|
325
325
|
const checked = arr.includes(opt);
|
|
326
326
|
return (
|
|
327
|
-
<label class="
|
|
327
|
+
<label class="bd-checkbox" key={opt}>
|
|
328
328
|
<input
|
|
329
329
|
type="checkbox"
|
|
330
330
|
checked={checked}
|
|
@@ -345,20 +345,20 @@ const BiabFieldInput = component$<{
|
|
|
345
345
|
|
|
346
346
|
case "boolean":
|
|
347
347
|
return (
|
|
348
|
-
<label class="
|
|
348
|
+
<label class="bd-switch">
|
|
349
349
|
<input
|
|
350
350
|
type="checkbox"
|
|
351
351
|
checked={value === true}
|
|
352
352
|
onChange$={(_, el) => void set((el as HTMLInputElement).checked)}
|
|
353
353
|
/>
|
|
354
|
-
<span class="
|
|
354
|
+
<span class="bd-switch__label">{field.placeholder || "Yes / No"}</span>
|
|
355
355
|
</label>
|
|
356
356
|
);
|
|
357
357
|
|
|
358
358
|
case "date":
|
|
359
359
|
return (
|
|
360
360
|
<input
|
|
361
|
-
class="
|
|
361
|
+
class="bd-input bd-date"
|
|
362
362
|
type="date"
|
|
363
363
|
value={asString(value)}
|
|
364
364
|
onInput$={(_, el) => void set((el as HTMLInputElement).value)}
|
|
@@ -371,11 +371,11 @@ const BiabFieldInput = component$<{
|
|
|
371
371
|
? (value as { start?: string; end?: string })
|
|
372
372
|
: { start: "", end: "" };
|
|
373
373
|
return (
|
|
374
|
-
<div class="
|
|
375
|
-
<label class="
|
|
376
|
-
<span class="
|
|
374
|
+
<div class="bd-date-range">
|
|
375
|
+
<label class="bd-date-range__field">
|
|
376
|
+
<span class="bd-date-range__label">Start</span>
|
|
377
377
|
<input
|
|
378
|
-
class="
|
|
378
|
+
class="bd-input"
|
|
379
379
|
type="date"
|
|
380
380
|
value={v.start ?? ""}
|
|
381
381
|
onInput$={(_, el) =>
|
|
@@ -383,10 +383,10 @@ const BiabFieldInput = component$<{
|
|
|
383
383
|
}
|
|
384
384
|
/>
|
|
385
385
|
</label>
|
|
386
|
-
<label class="
|
|
387
|
-
<span class="
|
|
386
|
+
<label class="bd-date-range__field">
|
|
387
|
+
<span class="bd-date-range__label">End</span>
|
|
388
388
|
<input
|
|
389
|
-
class="
|
|
389
|
+
class="bd-input"
|
|
390
390
|
type="date"
|
|
391
391
|
value={v.end ?? ""}
|
|
392
392
|
onInput$={(_, el) =>
|
|
@@ -421,7 +421,7 @@ const BiabFieldInput = component$<{
|
|
|
421
421
|
};
|
|
422
422
|
return (
|
|
423
423
|
<select
|
|
424
|
-
class="
|
|
424
|
+
class="bd-input bd-select bd-time"
|
|
425
425
|
value={asString(value)}
|
|
426
426
|
onChange$={(_, el) => void set((el as HTMLSelectElement).value)}
|
|
427
427
|
>
|
|
@@ -440,11 +440,11 @@ const BiabFieldInput = component$<{
|
|
|
440
440
|
? (value as { start?: string; end?: string })
|
|
441
441
|
: { start: "", end: "" };
|
|
442
442
|
return (
|
|
443
|
-
<div class="
|
|
444
|
-
<label class="
|
|
445
|
-
<span class="
|
|
443
|
+
<div class="bd-time-block">
|
|
444
|
+
<label class="bd-time-block__field">
|
|
445
|
+
<span class="bd-time-block__label">Start</span>
|
|
446
446
|
<input
|
|
447
|
-
class="
|
|
447
|
+
class="bd-input"
|
|
448
448
|
type="time"
|
|
449
449
|
value={v.start ?? ""}
|
|
450
450
|
onInput$={(_, el) =>
|
|
@@ -452,10 +452,10 @@ const BiabFieldInput = component$<{
|
|
|
452
452
|
}
|
|
453
453
|
/>
|
|
454
454
|
</label>
|
|
455
|
-
<label class="
|
|
456
|
-
<span class="
|
|
455
|
+
<label class="bd-time-block__field">
|
|
456
|
+
<span class="bd-time-block__label">End</span>
|
|
457
457
|
<input
|
|
458
|
-
class="
|
|
458
|
+
class="bd-input"
|
|
459
459
|
type="time"
|
|
460
460
|
value={v.end ?? ""}
|
|
461
461
|
onInput$={(_, el) =>
|
|
@@ -472,11 +472,11 @@ const BiabFieldInput = component$<{
|
|
|
472
472
|
? (value as { date?: string; time?: string })
|
|
473
473
|
: { date: "", time: "" };
|
|
474
474
|
return (
|
|
475
|
-
<div class="
|
|
476
|
-
<label class="
|
|
477
|
-
<span class="
|
|
475
|
+
<div class="bd-appointment">
|
|
476
|
+
<label class="bd-appointment__field">
|
|
477
|
+
<span class="bd-appointment__label">Date</span>
|
|
478
478
|
<input
|
|
479
|
-
class="
|
|
479
|
+
class="bd-input"
|
|
480
480
|
type="date"
|
|
481
481
|
value={v.date ?? ""}
|
|
482
482
|
onInput$={(_, el) =>
|
|
@@ -484,10 +484,10 @@ const BiabFieldInput = component$<{
|
|
|
484
484
|
}
|
|
485
485
|
/>
|
|
486
486
|
</label>
|
|
487
|
-
<label class="
|
|
488
|
-
<span class="
|
|
487
|
+
<label class="bd-appointment__field">
|
|
488
|
+
<span class="bd-appointment__label">Time</span>
|
|
489
489
|
<input
|
|
490
|
-
class="
|
|
490
|
+
class="bd-input"
|
|
491
491
|
type="time"
|
|
492
492
|
value={v.time ?? ""}
|
|
493
493
|
onInput$={(_, el) =>
|
|
@@ -508,14 +508,14 @@ const BiabFieldInput = component$<{
|
|
|
508
508
|
const fmt = (n: number) =>
|
|
509
509
|
unit === "currency" ? `$${n}` : unit === "percent" ? `${n}%` : `${n}`;
|
|
510
510
|
return (
|
|
511
|
-
<div class="
|
|
512
|
-
<div class="
|
|
511
|
+
<div class="bd-slider">
|
|
512
|
+
<div class="bd-slider__scale">
|
|
513
513
|
<span>{fmt(min)}</span>
|
|
514
|
-
<span class="
|
|
514
|
+
<span class="bd-slider__value">{fmt(v)}</span>
|
|
515
515
|
<span>{fmt(max)}</span>
|
|
516
516
|
</div>
|
|
517
517
|
<input
|
|
518
|
-
class="
|
|
518
|
+
class="bd-slider__input"
|
|
519
519
|
type="range"
|
|
520
520
|
min={min}
|
|
521
521
|
max={max}
|
|
@@ -531,12 +531,12 @@ const BiabFieldInput = component$<{
|
|
|
531
531
|
const max = field.starRatingConfig?.maxStars ?? 5;
|
|
532
532
|
const v = typeof value === "number" ? value : 0;
|
|
533
533
|
return (
|
|
534
|
-
<div class="
|
|
534
|
+
<div class="bd-stars">
|
|
535
535
|
{Array.from({ length: max }).map((_, i) => (
|
|
536
536
|
<button
|
|
537
537
|
key={`${field.id}-star-${i}`}
|
|
538
538
|
type="button"
|
|
539
|
-
class={classOf("
|
|
539
|
+
class={classOf("bd-star", i < v && "bd-star--on")}
|
|
540
540
|
aria-label={`${i + 1} star${i === 0 ? "" : "s"}`}
|
|
541
541
|
onClick$={() => void set(i + 1)}
|
|
542
542
|
>
|
|
@@ -551,12 +551,12 @@ const BiabFieldInput = component$<{
|
|
|
551
551
|
const v = typeof value === "number" ? value : -1;
|
|
552
552
|
const faces = ["😞", "😕", "😐", "🙂", "😄"];
|
|
553
553
|
return (
|
|
554
|
-
<div class="
|
|
554
|
+
<div class="bd-happiness">
|
|
555
555
|
{faces.map((emoji, i) => (
|
|
556
556
|
<button
|
|
557
557
|
key={emoji}
|
|
558
558
|
type="button"
|
|
559
|
-
class={classOf("
|
|
559
|
+
class={classOf("bd-happiness__face", i === v && "bd-happiness__face--on")}
|
|
560
560
|
onClick$={() => void set(i)}
|
|
561
561
|
>
|
|
562
562
|
{emoji}
|
|
@@ -569,18 +569,18 @@ const BiabFieldInput = component$<{
|
|
|
569
569
|
case "stepper": {
|
|
570
570
|
const v = typeof value === "number" ? value : 0;
|
|
571
571
|
return (
|
|
572
|
-
<div class="
|
|
572
|
+
<div class="bd-stepper">
|
|
573
573
|
<button
|
|
574
574
|
type="button"
|
|
575
|
-
class="
|
|
575
|
+
class="bd-stepper__btn bd-stepper__btn--dec"
|
|
576
576
|
onClick$={() => void set(v - 1)}
|
|
577
577
|
>
|
|
578
578
|
−
|
|
579
579
|
</button>
|
|
580
|
-
<span class="
|
|
580
|
+
<span class="bd-stepper__value">{v}</span>
|
|
581
581
|
<button
|
|
582
582
|
type="button"
|
|
583
|
-
class="
|
|
583
|
+
class="bd-stepper__btn bd-stepper__btn--inc"
|
|
584
584
|
onClick$={() => void set(v + 1)}
|
|
585
585
|
>
|
|
586
586
|
+
|
|
@@ -592,12 +592,12 @@ const BiabFieldInput = component$<{
|
|
|
592
592
|
case "color_picker": {
|
|
593
593
|
const v = asString(value);
|
|
594
594
|
return (
|
|
595
|
-
<div class="
|
|
595
|
+
<div class="bd-colors">
|
|
596
596
|
{(field.options ?? []).map((color) => (
|
|
597
597
|
<button
|
|
598
598
|
key={color}
|
|
599
599
|
type="button"
|
|
600
|
-
class={classOf("
|
|
600
|
+
class={classOf("bd-color", v === color && "bd-color--on")}
|
|
601
601
|
style={{ backgroundColor: color }}
|
|
602
602
|
title={color}
|
|
603
603
|
aria-label={color}
|
|
@@ -608,6 +608,102 @@ const BiabFieldInput = component$<{
|
|
|
608
608
|
);
|
|
609
609
|
}
|
|
610
610
|
|
|
611
|
+
case "name": {
|
|
612
|
+
const v = (value && typeof value === "object" ? value : {}) as {
|
|
613
|
+
prefix?: string;
|
|
614
|
+
first?: string;
|
|
615
|
+
middle?: string;
|
|
616
|
+
last?: string;
|
|
617
|
+
suffix?: string;
|
|
618
|
+
nicknames?: string[] | string;
|
|
619
|
+
};
|
|
620
|
+
const cfg: NonNullable<FormCoreField["nameConfig"]> =
|
|
621
|
+
field.nameConfig ?? {};
|
|
622
|
+
// Per-subfield autofill tokens (given/family/honorifics), suppressed
|
|
623
|
+
// to "off" when autofill is off for this field (global switch or override).
|
|
624
|
+
const acOff = autoComplete === "off";
|
|
625
|
+
const part = (
|
|
626
|
+
key: "prefix" | "first" | "middle" | "last" | "suffix",
|
|
627
|
+
label: string,
|
|
628
|
+
ac: string,
|
|
629
|
+
placeholder: string,
|
|
630
|
+
full = false,
|
|
631
|
+
) => (
|
|
632
|
+
<label
|
|
633
|
+
class={classOf(
|
|
634
|
+
"bd-name__field",
|
|
635
|
+
`bd-name__field--${key}`,
|
|
636
|
+
full && "bd-name__field--full",
|
|
637
|
+
)}
|
|
638
|
+
>
|
|
639
|
+
<span class="bd-name__label">{label}</span>
|
|
640
|
+
<input
|
|
641
|
+
class="bd-input"
|
|
642
|
+
value={v[key] ?? ""}
|
|
643
|
+
placeholder={placeholder}
|
|
644
|
+
autoComplete={acOff ? "off" : ac}
|
|
645
|
+
onInput$={(_, el) =>
|
|
646
|
+
void set({ ...v, [key]: (el as HTMLInputElement).value })
|
|
647
|
+
}
|
|
648
|
+
/>
|
|
649
|
+
</label>
|
|
650
|
+
);
|
|
651
|
+
// The nicknames input keeps the raw comma-separated string while the
|
|
652
|
+
// visitor types; submit normalizes it into a string[] (and the server
|
|
653
|
+
// re-normalizes authoritatively).
|
|
654
|
+
const nicknamesText = Array.isArray(v.nicknames)
|
|
655
|
+
? v.nicknames.join(", ")
|
|
656
|
+
: typeof v.nicknames === "string"
|
|
657
|
+
? v.nicknames
|
|
658
|
+
: "";
|
|
659
|
+
return (
|
|
660
|
+
<div class="bd-name">
|
|
661
|
+
{cfg.prefix &&
|
|
662
|
+
part("prefix", "Title", "honorific-prefix", "Dr.", true)}
|
|
663
|
+
{part("first", "First name", "given-name", "Jane")}
|
|
664
|
+
{cfg.middle &&
|
|
665
|
+
part("middle", "Middle name", "additional-name", "Quinn")}
|
|
666
|
+
{part(
|
|
667
|
+
"last",
|
|
668
|
+
"Last name",
|
|
669
|
+
"family-name",
|
|
670
|
+
"Doe",
|
|
671
|
+
cfg.middle === true && cfg.suffix !== true,
|
|
672
|
+
)}
|
|
673
|
+
{cfg.suffix &&
|
|
674
|
+
part(
|
|
675
|
+
"suffix",
|
|
676
|
+
"Suffix",
|
|
677
|
+
"honorific-suffix",
|
|
678
|
+
"Jr.",
|
|
679
|
+
cfg.middle !== true,
|
|
680
|
+
)}
|
|
681
|
+
{cfg.nicknames && (
|
|
682
|
+
<label
|
|
683
|
+
class={classOf(
|
|
684
|
+
"bd-name__field",
|
|
685
|
+
"bd-name__field--nicknames",
|
|
686
|
+
"bd-name__field--full",
|
|
687
|
+
)}
|
|
688
|
+
>
|
|
689
|
+
<span class="bd-name__label">Nicknames</span>
|
|
690
|
+
<input
|
|
691
|
+
class="bd-input"
|
|
692
|
+
value={nicknamesText}
|
|
693
|
+
placeholder="Johnny, JM — separate with commas"
|
|
694
|
+
onInput$={(_, el) =>
|
|
695
|
+
void set({
|
|
696
|
+
...v,
|
|
697
|
+
nicknames: (el as HTMLInputElement).value,
|
|
698
|
+
})
|
|
699
|
+
}
|
|
700
|
+
/>
|
|
701
|
+
</label>
|
|
702
|
+
)}
|
|
703
|
+
</div>
|
|
704
|
+
);
|
|
705
|
+
}
|
|
706
|
+
|
|
611
707
|
case "address": {
|
|
612
708
|
const v = (value && typeof value === "object" ? value : {}) as Record<
|
|
613
709
|
string,
|
|
@@ -621,10 +717,10 @@ const BiabFieldInput = component$<{
|
|
|
621
717
|
label: string,
|
|
622
718
|
ac: string,
|
|
623
719
|
) => (
|
|
624
|
-
<label class={classOf("
|
|
625
|
-
<span class="
|
|
720
|
+
<label class={classOf("bd-address__field", `bd-address__field--${key}`)}>
|
|
721
|
+
<span class="bd-address__label">{label}</span>
|
|
626
722
|
<input
|
|
627
|
-
class="
|
|
723
|
+
class="bd-input"
|
|
628
724
|
value={v[key] ?? ""}
|
|
629
725
|
autoComplete={acOff ? "off" : ac}
|
|
630
726
|
onInput$={(_, el) =>
|
|
@@ -634,7 +730,7 @@ const BiabFieldInput = component$<{
|
|
|
634
730
|
</label>
|
|
635
731
|
);
|
|
636
732
|
return (
|
|
637
|
-
<div class="
|
|
733
|
+
<div class="bd-address">
|
|
638
734
|
{part("line1", "Address Line 1", "street-address")}
|
|
639
735
|
{part("line2", "Address Line 2", "address-line2")}
|
|
640
736
|
{part("city", "City", "address-level2")}
|
|
@@ -654,9 +750,9 @@ const BiabFieldInput = component$<{
|
|
|
654
750
|
const remaining = Math.max(maxFiles - files.length, 0);
|
|
655
751
|
const uploading = state.snap?.uploading === true;
|
|
656
752
|
return (
|
|
657
|
-
<div class="
|
|
753
|
+
<div class="bd-file">
|
|
658
754
|
<input
|
|
659
|
-
class="
|
|
755
|
+
class="bd-file__input"
|
|
660
756
|
type="file"
|
|
661
757
|
multiple={maxFiles > 1}
|
|
662
758
|
{...(accept ? { accept } : {})}
|
|
@@ -692,13 +788,13 @@ const BiabFieldInput = component$<{
|
|
|
692
788
|
(el as HTMLInputElement).value = "";
|
|
693
789
|
}}
|
|
694
790
|
/>
|
|
695
|
-
{uploading ? <span class="
|
|
791
|
+
{uploading ? <span class="bd-file__status">Uploading…</span> : null}
|
|
696
792
|
{files.length > 0 ? (
|
|
697
|
-
<ul class="
|
|
793
|
+
<ul class="bd-file__list">
|
|
698
794
|
{files.map((f, idx) => (
|
|
699
|
-
<li class="
|
|
700
|
-
<span class="
|
|
701
|
-
<span class="
|
|
795
|
+
<li class="bd-file__item" key={`${f.url}-${idx}`}>
|
|
796
|
+
<span class="bd-file__name">{f.name}</span>
|
|
797
|
+
<span class="bd-file__size">
|
|
702
798
|
{Math.round(f.size / 1024)} KB
|
|
703
799
|
</span>
|
|
704
800
|
</li>
|
|
@@ -712,7 +808,7 @@ const BiabFieldInput = component$<{
|
|
|
712
808
|
case "phone":
|
|
713
809
|
return (
|
|
714
810
|
<input
|
|
715
|
-
class="
|
|
811
|
+
class="bd-input bd-phone"
|
|
716
812
|
type="tel"
|
|
717
813
|
value={asString(value)}
|
|
718
814
|
placeholder={
|
|
@@ -729,7 +825,7 @@ const BiabFieldInput = component$<{
|
|
|
729
825
|
case "email":
|
|
730
826
|
return (
|
|
731
827
|
<input
|
|
732
|
-
class="
|
|
828
|
+
class="bd-input bd-email"
|
|
733
829
|
type="email"
|
|
734
830
|
value={asString(value)}
|
|
735
831
|
placeholder={field.placeholder || "you@example.com"}
|
|
@@ -741,7 +837,7 @@ const BiabFieldInput = component$<{
|
|
|
741
837
|
case "number":
|
|
742
838
|
return (
|
|
743
839
|
<input
|
|
744
|
-
class="
|
|
840
|
+
class="bd-input bd-number"
|
|
745
841
|
type="number"
|
|
746
842
|
value={typeof value === "number" ? value : asString(value)}
|
|
747
843
|
placeholder={field.placeholder || ""}
|
|
@@ -755,7 +851,7 @@ const BiabFieldInput = component$<{
|
|
|
755
851
|
default:
|
|
756
852
|
return (
|
|
757
853
|
<input
|
|
758
|
-
class="
|
|
854
|
+
class="bd-input bd-text"
|
|
759
855
|
type="text"
|
|
760
856
|
value={asString(value)}
|
|
761
857
|
placeholder={field.placeholder || ""}
|
|
@@ -767,10 +863,10 @@ const BiabFieldInput = component$<{
|
|
|
767
863
|
});
|
|
768
864
|
|
|
769
865
|
/**
|
|
770
|
-
* One field "row": the `
|
|
866
|
+
* One field "row": the `bd-field` wrapper with stable data-attrs + error /
|
|
771
867
|
* help text, mirroring the dashboard `FieldRow`.
|
|
772
868
|
*/
|
|
773
|
-
const
|
|
869
|
+
const BdFieldRow = component$<{
|
|
774
870
|
field: FormCoreField;
|
|
775
871
|
controllerSig: ControllerRef;
|
|
776
872
|
state: SnapshotState;
|
|
@@ -782,30 +878,30 @@ const BiabFieldRow = component$<{
|
|
|
782
878
|
return (
|
|
783
879
|
<div
|
|
784
880
|
class={classOf(
|
|
785
|
-
"
|
|
786
|
-
`
|
|
787
|
-
field.required && "
|
|
788
|
-
error && "
|
|
881
|
+
"bd-field",
|
|
882
|
+
`bd-field--${field.type}`,
|
|
883
|
+
field.required && "bd-field--required",
|
|
884
|
+
error && "bd-field--error",
|
|
789
885
|
)}
|
|
790
|
-
data-
|
|
791
|
-
data-
|
|
886
|
+
data-bd-field={fieldCssKey(field)}
|
|
887
|
+
data-bd-type={field.type}
|
|
792
888
|
>
|
|
793
889
|
{showLabel ? (
|
|
794
|
-
<label class="
|
|
890
|
+
<label class="bd-field__label">
|
|
795
891
|
{field.label || ""}
|
|
796
|
-
{field.required ? <span class="
|
|
892
|
+
{field.required ? <span class="bd-field__required">*</span> : null}
|
|
797
893
|
</label>
|
|
798
894
|
) : null}
|
|
799
|
-
<
|
|
895
|
+
<BdFieldInput
|
|
800
896
|
field={field}
|
|
801
897
|
controllerSig={controllerSig}
|
|
802
898
|
state={state}
|
|
803
899
|
uploadFn={uploadFn}
|
|
804
900
|
acConfig={acConfig}
|
|
805
901
|
/>
|
|
806
|
-
{error ? <p class="
|
|
902
|
+
{error ? <p class="bd-field__error">{error.message}</p> : null}
|
|
807
903
|
{field.helpText ? (
|
|
808
|
-
<p class="
|
|
904
|
+
<p class="bd-field__help">{field.helpText}</p>
|
|
809
905
|
) : null}
|
|
810
906
|
</div>
|
|
811
907
|
);
|
|
@@ -815,9 +911,9 @@ const BiabFieldRow = component$<{
|
|
|
815
911
|
* Recursive render of the nested field tree — mirrors `FormPreview.RenderTree`:
|
|
816
912
|
* `input_group` (with concurrent-reveal gating + optional group label),
|
|
817
913
|
* `condition_block` (skipped when its rule is false), `or_condition` (two sides
|
|
818
|
-
* with an OR divider), `flex_row` (inline row), else a `
|
|
914
|
+
* with an OR divider), `flex_row` (inline row), else a `BdFieldRow`.
|
|
819
915
|
*/
|
|
820
|
-
const
|
|
916
|
+
const BdRenderTree = component$<{
|
|
821
917
|
fields: FormCoreField[];
|
|
822
918
|
controllerSig: ControllerRef;
|
|
823
919
|
state: SnapshotState;
|
|
@@ -827,7 +923,7 @@ const BiabRenderTree = component$<{
|
|
|
827
923
|
}>(({ fields, controllerSig, state, uploadFn, acConfig, flat }) => {
|
|
828
924
|
const data = state.snap?.values ?? {};
|
|
829
925
|
return (
|
|
830
|
-
<div class="
|
|
926
|
+
<div class="bd-tree">
|
|
831
927
|
{fields.map((f) => {
|
|
832
928
|
if (f.type === "input_group") {
|
|
833
929
|
const children = (f.children ?? []) as FormCoreField[];
|
|
@@ -840,13 +936,13 @@ const BiabRenderTree = component$<{
|
|
|
840
936
|
return (
|
|
841
937
|
<div
|
|
842
938
|
key={f.id}
|
|
843
|
-
class={classOf("
|
|
844
|
-
data-
|
|
939
|
+
class={classOf("bd-group", flat && "bd-group--flat")}
|
|
940
|
+
data-bd-group={fieldCssKey(f)}
|
|
845
941
|
>
|
|
846
942
|
{f.label && showGroupLabel ? (
|
|
847
|
-
<div class="
|
|
943
|
+
<div class="bd-group__label">{f.label}</div>
|
|
848
944
|
) : null}
|
|
849
|
-
<
|
|
945
|
+
<BdRenderTree
|
|
850
946
|
fields={shown}
|
|
851
947
|
controllerSig={controllerSig}
|
|
852
948
|
state={state}
|
|
@@ -860,7 +956,7 @@ const BiabRenderTree = component$<{
|
|
|
860
956
|
if (f.type === "condition_block") {
|
|
861
957
|
if (!evalCondition(f.conditionRule, data)) return null;
|
|
862
958
|
return (
|
|
863
|
-
<
|
|
959
|
+
<BdRenderTree
|
|
864
960
|
key={f.id}
|
|
865
961
|
fields={(f.children ?? []) as FormCoreField[]}
|
|
866
962
|
controllerSig={controllerSig}
|
|
@@ -878,22 +974,22 @@ const BiabRenderTree = component$<{
|
|
|
878
974
|
return (
|
|
879
975
|
<div
|
|
880
976
|
key={f.id}
|
|
881
|
-
class={classOf("
|
|
882
|
-
data-
|
|
977
|
+
class={classOf("bd-or", error && "bd-or--error")}
|
|
978
|
+
data-bd-or={fieldCssKey(f)}
|
|
883
979
|
>
|
|
884
980
|
{f.label ? (
|
|
885
|
-
<div class="
|
|
981
|
+
<div class="bd-or__label">
|
|
886
982
|
{f.label}
|
|
887
|
-
<span class="
|
|
983
|
+
<span class="bd-or__hint">Fill at least one side</span>
|
|
888
984
|
</div>
|
|
889
985
|
) : null}
|
|
890
|
-
<div class="
|
|
891
|
-
<div class="
|
|
892
|
-
<div class="
|
|
986
|
+
<div class="bd-or__grid">
|
|
987
|
+
<div class="bd-or__side bd-or__side--left">
|
|
988
|
+
<div class="bd-or__side-label">
|
|
893
989
|
{f.orConditionConfig?.leftLabel || "Option A"}
|
|
894
990
|
</div>
|
|
895
991
|
{left ? (
|
|
896
|
-
<
|
|
992
|
+
<BdRenderTree
|
|
897
993
|
fields={[left]}
|
|
898
994
|
controllerSig={controllerSig}
|
|
899
995
|
state={state}
|
|
@@ -902,15 +998,15 @@ const BiabRenderTree = component$<{
|
|
|
902
998
|
/>
|
|
903
999
|
) : null}
|
|
904
1000
|
</div>
|
|
905
|
-
<div class="
|
|
906
|
-
<span class="
|
|
1001
|
+
<div class="bd-or__divider">
|
|
1002
|
+
<span class="bd-or__badge">OR</span>
|
|
907
1003
|
</div>
|
|
908
|
-
<div class="
|
|
909
|
-
<div class="
|
|
1004
|
+
<div class="bd-or__side bd-or__side--right">
|
|
1005
|
+
<div class="bd-or__side-label">
|
|
910
1006
|
{f.orConditionConfig?.rightLabel || "Option B"}
|
|
911
1007
|
</div>
|
|
912
1008
|
{right ? (
|
|
913
|
-
<
|
|
1009
|
+
<BdRenderTree
|
|
914
1010
|
fields={[right]}
|
|
915
1011
|
controllerSig={controllerSig}
|
|
916
1012
|
state={state}
|
|
@@ -921,7 +1017,7 @@ const BiabRenderTree = component$<{
|
|
|
921
1017
|
</div>
|
|
922
1018
|
</div>
|
|
923
1019
|
{error ? (
|
|
924
|
-
<p class="
|
|
1020
|
+
<p class="bd-or__error">Fill in at least one side to continue.</p>
|
|
925
1021
|
) : null}
|
|
926
1022
|
</div>
|
|
927
1023
|
);
|
|
@@ -930,10 +1026,10 @@ const BiabRenderTree = component$<{
|
|
|
930
1026
|
if (f.type === "flex_row") {
|
|
931
1027
|
const children = (f.children ?? []) as FormCoreField[];
|
|
932
1028
|
return (
|
|
933
|
-
<div key={f.id} class="
|
|
1029
|
+
<div key={f.id} class="bd-flex-row">
|
|
934
1030
|
{children.map((child) => (
|
|
935
|
-
<div class="
|
|
936
|
-
<
|
|
1031
|
+
<div class="bd-flex-row__cell" key={child.id}>
|
|
1032
|
+
<BdFieldRow
|
|
937
1033
|
field={child}
|
|
938
1034
|
controllerSig={controllerSig}
|
|
939
1035
|
state={state}
|
|
@@ -947,7 +1043,7 @@ const BiabRenderTree = component$<{
|
|
|
947
1043
|
}
|
|
948
1044
|
|
|
949
1045
|
return (
|
|
950
|
-
<
|
|
1046
|
+
<BdFieldRow
|
|
951
1047
|
key={f.id}
|
|
952
1048
|
field={f}
|
|
953
1049
|
controllerSig={controllerSig}
|
|
@@ -962,10 +1058,10 @@ const BiabRenderTree = component$<{
|
|
|
962
1058
|
});
|
|
963
1059
|
|
|
964
1060
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
965
|
-
// <
|
|
1061
|
+
// <BdForm> — the drop-in.
|
|
966
1062
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
967
1063
|
|
|
968
|
-
export const
|
|
1064
|
+
export const BdForm = component$<BdFormProps>((props) => {
|
|
969
1065
|
// The controller lives only on the client (it's a non-serializable closure).
|
|
970
1066
|
// `noSerialize()` tells Qwik to drop it from the resumable state instead of
|
|
971
1067
|
// trying (and failing) to serialize the closure; it is re-created in the
|
|
@@ -1023,7 +1119,7 @@ export const BiabForm = component$<BiabFormProps>((props) => {
|
|
|
1023
1119
|
});
|
|
1024
1120
|
});
|
|
1025
1121
|
|
|
1026
|
-
const rootClass = classOf("
|
|
1122
|
+
const rootClass = classOf("bd-form", props.class, props.className);
|
|
1027
1123
|
|
|
1028
1124
|
// HTML autofill config threaded to every field input. A plain serializable
|
|
1029
1125
|
// object (Qwik-friendly): the global switch + per-field overrides. Mirrors the
|
|
@@ -1070,16 +1166,16 @@ export const BiabForm = component$<BiabFormProps>((props) => {
|
|
|
1070
1166
|
const snap = state.snap;
|
|
1071
1167
|
if (!snap || snap.status === "loading" || snap.status === "idle") {
|
|
1072
1168
|
return (
|
|
1073
|
-
<div class={rootClass} data-
|
|
1169
|
+
<div class={rootClass} data-bd-status="loading">
|
|
1074
1170
|
<Slot name="loading" />
|
|
1075
1171
|
</div>
|
|
1076
1172
|
);
|
|
1077
1173
|
}
|
|
1078
1174
|
if (snap.status === "error") {
|
|
1079
1175
|
return (
|
|
1080
|
-
<div class={rootClass} data-
|
|
1176
|
+
<div class={rootClass} data-bd-status="error">
|
|
1081
1177
|
<Slot name="error" />
|
|
1082
|
-
<p class="
|
|
1178
|
+
<p class="bd-form__load-error">
|
|
1083
1179
|
{snap.loadError ?? "Could not load the form."}
|
|
1084
1180
|
</p>
|
|
1085
1181
|
</div>
|
|
@@ -1100,34 +1196,34 @@ export const BiabForm = component$<BiabFormProps>((props) => {
|
|
|
1100
1196
|
snap.stepCount > 1;
|
|
1101
1197
|
|
|
1102
1198
|
// Animation entrance class (per dashboard `entranceClass`). "scroll" is left
|
|
1103
|
-
// to the consumer's CSS via the `
|
|
1199
|
+
// to the consumer's CSS via the `bd-form--anim-scroll` hook.
|
|
1104
1200
|
const animClass =
|
|
1105
|
-
settings.animation === "none" ? "" : `
|
|
1106
|
-
const dirClass = snap.forward ? "
|
|
1201
|
+
settings.animation === "none" ? "" : `bd-form--anim-${settings.animation}`;
|
|
1202
|
+
const dirClass = snap.forward ? "bd-form--forward" : "bd-form--back";
|
|
1107
1203
|
|
|
1108
1204
|
if (snap.submitted) {
|
|
1109
1205
|
return (
|
|
1110
|
-
<div class={classOf(rootClass, "
|
|
1206
|
+
<div class={classOf(rootClass, "bd-form--submitted")} data-bd-status="submitted">
|
|
1111
1207
|
<Slot name="success" />
|
|
1112
1208
|
</div>
|
|
1113
1209
|
);
|
|
1114
1210
|
}
|
|
1115
1211
|
|
|
1116
1212
|
return (
|
|
1117
|
-
<div class={rootClass} data-
|
|
1213
|
+
<div class={rootClass} data-bd-status="ready" data-bd-animation={settings.animation}>
|
|
1118
1214
|
{snap.orgIcon ? (
|
|
1119
|
-
<img class="
|
|
1215
|
+
<img class="bd-form__org-icon" src={snap.orgIcon} alt="" />
|
|
1120
1216
|
) : null}
|
|
1121
1217
|
|
|
1122
|
-
{snap.title ? <h2 class="
|
|
1218
|
+
{snap.title ? <h2 class="bd-form__title">{snap.title}</h2> : null}
|
|
1123
1219
|
{snap.description ? (
|
|
1124
|
-
<p class="
|
|
1220
|
+
<p class="bd-form__description">{snap.description}</p>
|
|
1125
1221
|
) : null}
|
|
1126
1222
|
|
|
1127
1223
|
{showSteps ? (
|
|
1128
|
-
<div class="
|
|
1129
|
-
<div class="
|
|
1130
|
-
<ol class="
|
|
1224
|
+
<div class="bd-progress bd-progress--steps">
|
|
1225
|
+
<div class="bd-progress__heading">Form Progress</div>
|
|
1226
|
+
<ol class="bd-progress__steps">
|
|
1131
1227
|
{snap.steps.map((s, i) => {
|
|
1132
1228
|
const head = s[0];
|
|
1133
1229
|
const title = head?.stepTitle || head?.label || `Step ${i + 1}`;
|
|
@@ -1135,15 +1231,15 @@ export const BiabForm = component$<BiabFormProps>((props) => {
|
|
|
1135
1231
|
const current = i === snap.step;
|
|
1136
1232
|
return (
|
|
1137
1233
|
<li
|
|
1138
|
-
key={`
|
|
1234
|
+
key={`bd-step-${i}`}
|
|
1139
1235
|
class={classOf(
|
|
1140
|
-
"
|
|
1141
|
-
current && "
|
|
1142
|
-
done && "
|
|
1236
|
+
"bd-progress__step",
|
|
1237
|
+
current && "bd-progress__step--current",
|
|
1238
|
+
done && "bd-progress__step--done",
|
|
1143
1239
|
)}
|
|
1144
1240
|
>
|
|
1145
|
-
<span class="
|
|
1146
|
-
<span class="
|
|
1241
|
+
<span class="bd-progress__marker">{done ? "✓" : i + 1}</span>
|
|
1242
|
+
<span class="bd-progress__title">{title}</span>
|
|
1147
1243
|
</li>
|
|
1148
1244
|
);
|
|
1149
1245
|
})}
|
|
@@ -1152,13 +1248,13 @@ export const BiabForm = component$<BiabFormProps>((props) => {
|
|
|
1152
1248
|
) : null}
|
|
1153
1249
|
|
|
1154
1250
|
{showBar ? (
|
|
1155
|
-
<div class="
|
|
1156
|
-
<span class="
|
|
1251
|
+
<div class="bd-progress bd-progress--bar">
|
|
1252
|
+
<span class="bd-progress__count">
|
|
1157
1253
|
{snap.step + 1} / {snap.stepCount}
|
|
1158
1254
|
</span>
|
|
1159
|
-
<div class="
|
|
1255
|
+
<div class="bd-progress__track">
|
|
1160
1256
|
<div
|
|
1161
|
-
class="
|
|
1257
|
+
class="bd-progress__fill"
|
|
1162
1258
|
style={{ width: `${snap.progressPercent}%` }}
|
|
1163
1259
|
/>
|
|
1164
1260
|
</div>
|
|
@@ -1166,19 +1262,19 @@ export const BiabForm = component$<BiabFormProps>((props) => {
|
|
|
1166
1262
|
) : null}
|
|
1167
1263
|
|
|
1168
1264
|
{snap.errorList.length > 0 ? (
|
|
1169
|
-
<div class="
|
|
1170
|
-
<div class="
|
|
1265
|
+
<div class="bd-form__errors" role="alert">
|
|
1266
|
+
<div class="bd-form__errors-heading">
|
|
1171
1267
|
Please complete the highlighted required field
|
|
1172
1268
|
{snap.errorList.length === 1 ? "" : "s"}.
|
|
1173
1269
|
</div>
|
|
1174
|
-
<div class="
|
|
1270
|
+
<div class="bd-form__errors-list">
|
|
1175
1271
|
{snap.errorList.map((e) => e.label).join(", ")}
|
|
1176
1272
|
</div>
|
|
1177
1273
|
</div>
|
|
1178
1274
|
) : null}
|
|
1179
1275
|
|
|
1180
|
-
<div class={classOf("
|
|
1181
|
-
<
|
|
1276
|
+
<div class={classOf("bd-form__body", animClass, dirClass)} key={`bd-body-${snap.step}`}>
|
|
1277
|
+
<BdRenderTree
|
|
1182
1278
|
fields={snap.visibleFields}
|
|
1183
1279
|
controllerSig={controllerSig}
|
|
1184
1280
|
state={state}
|
|
@@ -1189,10 +1285,10 @@ export const BiabForm = component$<BiabFormProps>((props) => {
|
|
|
1189
1285
|
</div>
|
|
1190
1286
|
|
|
1191
1287
|
{consecutive && snap.stepCount > 1 ? (
|
|
1192
|
-
<div class="
|
|
1288
|
+
<div class="bd-nav">
|
|
1193
1289
|
<button
|
|
1194
1290
|
type="button"
|
|
1195
|
-
class="
|
|
1291
|
+
class="bd-btn bd-btn--back"
|
|
1196
1292
|
disabled={snap.isFirstStep}
|
|
1197
1293
|
onClick$={() => controllerSig.value?.back()}
|
|
1198
1294
|
>
|
|
@@ -1201,7 +1297,7 @@ export const BiabForm = component$<BiabFormProps>((props) => {
|
|
|
1201
1297
|
{snap.isLastStep ? (
|
|
1202
1298
|
<button
|
|
1203
1299
|
type="button"
|
|
1204
|
-
class="
|
|
1300
|
+
class="bd-btn bd-btn--submit"
|
|
1205
1301
|
disabled={snap.submitting || snap.uploading}
|
|
1206
1302
|
onClick$={handleSubmit}
|
|
1207
1303
|
>
|
|
@@ -1210,7 +1306,7 @@ export const BiabForm = component$<BiabFormProps>((props) => {
|
|
|
1210
1306
|
) : (
|
|
1211
1307
|
<button
|
|
1212
1308
|
type="button"
|
|
1213
|
-
class="
|
|
1309
|
+
class="bd-btn bd-btn--next"
|
|
1214
1310
|
disabled={!snap.canAdvance}
|
|
1215
1311
|
onClick$={() => controllerSig.value?.next()}
|
|
1216
1312
|
>
|
|
@@ -1219,10 +1315,10 @@ export const BiabForm = component$<BiabFormProps>((props) => {
|
|
|
1219
1315
|
)}
|
|
1220
1316
|
</div>
|
|
1221
1317
|
) : (
|
|
1222
|
-
<div class="
|
|
1318
|
+
<div class="bd-nav">
|
|
1223
1319
|
<button
|
|
1224
1320
|
type="button"
|
|
1225
|
-
class="
|
|
1321
|
+
class="bd-btn bd-btn--submit"
|
|
1226
1322
|
disabled={snap.submitting || snap.uploading}
|
|
1227
1323
|
onClick$={handleSubmit}
|
|
1228
1324
|
>
|
|
@@ -1234,7 +1330,7 @@ export const BiabForm = component$<BiabFormProps>((props) => {
|
|
|
1234
1330
|
);
|
|
1235
1331
|
});
|
|
1236
1332
|
|
|
1237
|
-
export default
|
|
1333
|
+
export default BdForm;
|
|
1238
1334
|
|
|
1239
1335
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
1240
1336
|
// Native storefront + chat
|
|
@@ -1243,7 +1339,7 @@ export default BiabForm;
|
|
|
1243
1339
|
// or cross Qwik's resumability boundary. They are created inside
|
|
1244
1340
|
// `useVisibleTask$` — client-side, after hydration — and their snapshots are
|
|
1245
1341
|
// copied into a serializable signal that the template reads. That is the same
|
|
1246
|
-
// shape `<
|
|
1342
|
+
// shape `<BdForm>` already uses for its controller.
|
|
1247
1343
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
1248
1344
|
|
|
1249
1345
|
import {
|
|
@@ -1275,7 +1371,7 @@ import {
|
|
|
1275
1371
|
type VerifyController,
|
|
1276
1372
|
type VerifySnapshot,
|
|
1277
1373
|
} from "./verify-core/index.js";
|
|
1278
|
-
import {
|
|
1374
|
+
import { createBdClient as createBdClientForFollowers } from "./sdk.js";
|
|
1279
1375
|
import {
|
|
1280
1376
|
type BlogController,
|
|
1281
1377
|
type BlogSnapshot,
|
|
@@ -1286,7 +1382,7 @@ import {
|
|
|
1286
1382
|
type ChatSnapshot,
|
|
1287
1383
|
createChatController,
|
|
1288
1384
|
} from "./chat-core/index.js";
|
|
1289
|
-
import {
|
|
1385
|
+
import { BdApiClient as BdClientForSurfaces } from "./client.js";
|
|
1290
1386
|
import {
|
|
1291
1387
|
createStoreController,
|
|
1292
1388
|
type StoreController,
|
|
@@ -1325,7 +1421,7 @@ export function useStorefront(options: UseStorefrontOptions) {
|
|
|
1325
1421
|
|
|
1326
1422
|
useVisibleTask$(({ cleanup }) => {
|
|
1327
1423
|
const controller = createStoreController({
|
|
1328
|
-
client: new
|
|
1424
|
+
client: new BdClientForSurfaces({
|
|
1329
1425
|
apiKey: options.apiKey,
|
|
1330
1426
|
baseUrl: options.baseUrl,
|
|
1331
1427
|
}),
|
|
@@ -1376,7 +1472,7 @@ export function useChat(options: UseChatOptions) {
|
|
|
1376
1472
|
|
|
1377
1473
|
useVisibleTask$(({ cleanup }) => {
|
|
1378
1474
|
const controller = createChatController({
|
|
1379
|
-
client: new
|
|
1475
|
+
client: new BdClientForSurfaces({
|
|
1380
1476
|
apiKey: options.apiKey,
|
|
1381
1477
|
baseUrl: options.baseUrl,
|
|
1382
1478
|
}),
|
|
@@ -1425,7 +1521,7 @@ export function useBlog(options: UseBlogOptions) {
|
|
|
1425
1521
|
|
|
1426
1522
|
useVisibleTask$(({ cleanup }) => {
|
|
1427
1523
|
const controller = createBlogController({
|
|
1428
|
-
client: new
|
|
1524
|
+
client: new BdClientForSurfaces({
|
|
1429
1525
|
apiKey: options.apiKey,
|
|
1430
1526
|
baseUrl: options.baseUrl,
|
|
1431
1527
|
}),
|
|
@@ -1469,7 +1565,7 @@ export function useCheckout(options: { apiKey: string; baseUrl: string }) {
|
|
|
1469
1565
|
|
|
1470
1566
|
useVisibleTask$(({ cleanup }) => {
|
|
1471
1567
|
const controller = createCheckoutController({
|
|
1472
|
-
client: new
|
|
1568
|
+
client: new BdClientForSurfaces({
|
|
1473
1569
|
apiKey: options.apiKey,
|
|
1474
1570
|
baseUrl: options.baseUrl,
|
|
1475
1571
|
}),
|
|
@@ -1535,7 +1631,7 @@ export function useFollowers(options: {
|
|
|
1535
1631
|
|
|
1536
1632
|
useVisibleTask$(({ cleanup }) => {
|
|
1537
1633
|
const controller = createFollowersController({
|
|
1538
|
-
client:
|
|
1634
|
+
client: createBdClientForFollowers({
|
|
1539
1635
|
apiKey: options.token,
|
|
1540
1636
|
siteId: options.siteId,
|
|
1541
1637
|
...(options.baseUrl ? { baseUrl: options.baseUrl } : {}),
|
|
@@ -1587,7 +1683,7 @@ export function useMarketing(options: {
|
|
|
1587
1683
|
|
|
1588
1684
|
useVisibleTask$(({ cleanup }) => {
|
|
1589
1685
|
const controller = createMarketingController({
|
|
1590
|
-
client:
|
|
1686
|
+
client: createBdClientForFollowers({
|
|
1591
1687
|
apiKey: options.token,
|
|
1592
1688
|
siteId: options.siteId,
|
|
1593
1689
|
...(options.baseUrl ? { baseUrl: options.baseUrl } : {}),
|
|
@@ -1630,7 +1726,7 @@ export function useVerify(
|
|
|
1630
1726
|
useVisibleTask$(({ cleanup }) => {
|
|
1631
1727
|
const { apiKey, baseUrl, ...rest } = options;
|
|
1632
1728
|
const controller = createVerifyController({
|
|
1633
|
-
client: new
|
|
1729
|
+
client: new BdClientForSurfaces({ apiKey, baseUrl }),
|
|
1634
1730
|
...rest,
|
|
1635
1731
|
});
|
|
1636
1732
|
actions.current = noSerialize(controller);
|
|
@@ -1675,7 +1771,7 @@ export function usePortal(options: {
|
|
|
1675
1771
|
|
|
1676
1772
|
useVisibleTask$(({ cleanup }) => {
|
|
1677
1773
|
const controller = createPortalController({
|
|
1678
|
-
client: new
|
|
1774
|
+
client: new BdClientForSurfaces({
|
|
1679
1775
|
apiKey: options.apiKey,
|
|
1680
1776
|
baseUrl: options.baseUrl,
|
|
1681
1777
|
}),
|