@businessdash/sdk 0.9.80 → 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.
Files changed (264) hide show
  1. package/README.md +133 -949
  2. package/assets/{biab-sw.js → bd-sw.js} +2 -2
  3. package/dist/account-core/index.d.ts +1 -1
  4. package/dist/account-core/index.d.ts.map +1 -1
  5. package/dist/adapters-revalidate.d.ts +2 -2
  6. package/dist/adapters-revalidate.js +2 -2
  7. package/dist/adapters-revalidate.js.map +1 -1
  8. package/dist/analytics-core.d.ts +6 -6
  9. package/dist/analytics-core.d.ts.map +1 -1
  10. package/dist/analytics-core.js +4 -4
  11. package/dist/analytics-core.js.map +1 -1
  12. package/dist/analytics-server.d.ts +6 -6
  13. package/dist/analytics-server.d.ts.map +1 -1
  14. package/dist/analytics-server.js +5 -5
  15. package/dist/auth-handler.d.ts +14 -14
  16. package/dist/auth-handler.d.ts.map +1 -1
  17. package/dist/auth-handler.js +16 -16
  18. package/dist/auth-handler.js.map +1 -1
  19. package/dist/auth-links.d.ts +2 -2
  20. package/dist/auth-links.d.ts.map +1 -1
  21. package/dist/auth-links.js +2 -2
  22. package/dist/auth-links.js.map +1 -1
  23. package/dist/{biab-forms.css → bd-forms.css} +158 -158
  24. package/dist/cli.d.ts +4 -4
  25. package/dist/cli.js +78 -78
  26. package/dist/cli.js.map +1 -1
  27. package/dist/client.d.ts +158 -147
  28. package/dist/client.d.ts.map +1 -1
  29. package/dist/client.js +156 -137
  30. package/dist/client.js.map +1 -1
  31. package/dist/consent-core/index.cjs +2 -2
  32. package/dist/consent-core/index.d.ts +2 -2
  33. package/dist/consent-core/index.d.ts.map +1 -1
  34. package/dist/consent-core/index.js +10 -8
  35. package/dist/consent-core/index.js.map +1 -1
  36. package/dist/contracts.d.ts +411 -52
  37. package/dist/contracts.d.ts.map +1 -1
  38. package/dist/contracts.js +89 -15
  39. package/dist/contracts.js.map +1 -1
  40. package/dist/data-model-schema.d.ts +15 -15
  41. package/dist/data-model-schema.d.ts.map +1 -1
  42. package/dist/data-model-schema.js +19 -17
  43. package/dist/data-model-schema.js.map +1 -1
  44. package/dist/distribution.d.ts +5 -5
  45. package/dist/distribution.d.ts.map +1 -1
  46. package/dist/distribution.js +4 -4
  47. package/dist/element.d.ts +36 -36
  48. package/dist/element.d.ts.map +1 -1
  49. package/dist/element.js +43 -43
  50. package/dist/element.js.map +1 -1
  51. package/dist/embed-protocol.d.ts +11 -11
  52. package/dist/embed-protocol.d.ts.map +1 -1
  53. package/dist/embed-protocol.js +1 -1
  54. package/dist/embed-protocol.js.map +1 -1
  55. package/dist/errors.d.ts +15 -15
  56. package/dist/errors.d.ts.map +1 -1
  57. package/dist/errors.js +18 -18
  58. package/dist/errors.js.map +1 -1
  59. package/dist/forms-core/autocomplete.d.ts +3 -3
  60. package/dist/forms-core/autocomplete.d.ts.map +1 -1
  61. package/dist/forms-core/autocomplete.js +2 -2
  62. package/dist/forms-core/controller.d.ts +10 -10
  63. package/dist/forms-core/controller.d.ts.map +1 -1
  64. package/dist/forms-core/controller.js +4 -4
  65. package/dist/forms-core/controller.js.map +1 -1
  66. package/dist/forms-core/elements.d.ts +4 -4
  67. package/dist/forms-core/elements.d.ts.map +1 -1
  68. package/dist/forms-core/elements.js +7 -7
  69. package/dist/forms-core/elements.js.map +1 -1
  70. package/dist/forms-core/formula.d.ts +1 -1
  71. package/dist/forms-core/formula.js +1 -1
  72. package/dist/forms-core/index.d.ts +6 -6
  73. package/dist/forms-core/index.d.ts.map +1 -1
  74. package/dist/forms-core/index.js +5 -5
  75. package/dist/forms-core/index.js.map +1 -1
  76. package/dist/forms-core/units.d.ts +1 -1
  77. package/dist/forms-core/units.js +1 -1
  78. package/dist/forms-core/us-states.d.ts +1 -1
  79. package/dist/forms-core/us-states.js +1 -1
  80. package/dist/forms-core/validation.d.ts +12 -3
  81. package/dist/forms-core/validation.d.ts.map +1 -1
  82. package/dist/forms-core/validation.js +152 -17
  83. package/dist/forms-core/validation.js.map +1 -1
  84. package/dist/forms.d.ts +2 -2
  85. package/dist/forms.d.ts.map +1 -1
  86. package/dist/forms.js +2 -2
  87. package/dist/forms.js.map +1 -1
  88. package/dist/framework-support.js +1 -1
  89. package/dist/framework-support.js.map +1 -1
  90. package/dist/gallery-types.d.ts +1 -1
  91. package/dist/graphql.d.ts +3 -3
  92. package/dist/graphql.d.ts.map +1 -1
  93. package/dist/graphql.js +3 -3
  94. package/dist/graphql.js.map +1 -1
  95. package/dist/index.cjs +351 -272
  96. package/dist/index.d.cts +5 -5
  97. package/dist/index.d.mts +5 -5
  98. package/dist/index.d.ts +5 -5
  99. package/dist/index.d.ts.map +1 -1
  100. package/dist/index.js +5 -5
  101. package/dist/index.js.map +1 -1
  102. package/dist/legal-core/index.cjs +8 -8
  103. package/dist/legal-core/index.d.ts +3 -3
  104. package/dist/legal-core/index.d.ts.map +1 -1
  105. package/dist/legal-core/index.js +11 -11
  106. package/dist/legal-core/index.js.map +1 -1
  107. package/dist/marketing-core/index.d.ts +51 -1
  108. package/dist/marketing-core/index.d.ts.map +1 -1
  109. package/dist/marketing-core/index.js +35 -0
  110. package/dist/marketing-core/index.js.map +1 -1
  111. package/dist/marketing-schema.d.ts +9 -9
  112. package/dist/marketing-schema.d.ts.map +1 -1
  113. package/dist/marketing-schema.js +1 -1
  114. package/dist/mcp.d.ts +4 -4
  115. package/dist/mcp.js +4 -4
  116. package/dist/native.d.ts +6 -6
  117. package/dist/native.d.ts.map +1 -1
  118. package/dist/native.js +4 -4
  119. package/dist/native.js.map +1 -1
  120. package/dist/next-revalidate.d.ts +8 -8
  121. package/dist/next-revalidate.d.ts.map +1 -1
  122. package/dist/next-revalidate.js +7 -7
  123. package/dist/next-revalidate.js.map +1 -1
  124. package/dist/notifications-core/index.d.ts +1 -1
  125. package/dist/notifications-core/index.js +1 -1
  126. package/dist/parallel-pages.d.ts +4 -4
  127. package/dist/parallel-pages.d.ts.map +1 -1
  128. package/dist/parallel-pages.js +5 -5
  129. package/dist/parallel-pages.js.map +1 -1
  130. package/dist/portal-core/index.d.ts +1 -1
  131. package/dist/portal-core/index.js +1 -1
  132. package/dist/proxy.d.ts +18 -18
  133. package/dist/proxy.d.ts.map +1 -1
  134. package/dist/proxy.js +10 -10
  135. package/dist/proxy.js.map +1 -1
  136. package/dist/push-core/index.cjs +6 -2
  137. package/dist/push-core/index.d.ts +1 -1
  138. package/dist/push-core/index.d.ts.map +1 -1
  139. package/dist/push-core/index.js +6 -2
  140. package/dist/push-core/index.js.map +1 -1
  141. package/dist/react-analytics.d.ts +14 -14
  142. package/dist/react-analytics.d.ts.map +1 -1
  143. package/dist/react-analytics.js +15 -15
  144. package/dist/react-analytics.js.map +1 -1
  145. package/dist/react-attribution.d.ts +2 -2
  146. package/dist/react-attribution.d.ts.map +1 -1
  147. package/dist/react-attribution.js +1 -1
  148. package/dist/react-marketing.js +5 -5
  149. package/dist/react-marketing.js.map +1 -1
  150. package/dist/react.d.ts +38 -61
  151. package/dist/react.d.ts.map +1 -1
  152. package/dist/react.js +247 -261
  153. package/dist/react.js.map +1 -1
  154. package/dist/reserved-paths.d.ts +2 -2
  155. package/dist/reserved-paths.js +3 -3
  156. package/dist/reserved-paths.js.map +1 -1
  157. package/dist/revalidate-verify.d.ts +3 -3
  158. package/dist/revalidate-verify.d.ts.map +1 -1
  159. package/dist/revalidate-verify.js +1 -1
  160. package/dist/revalidate-verify.js.map +1 -1
  161. package/dist/sdk.d.ts +51 -45
  162. package/dist/sdk.d.ts.map +1 -1
  163. package/dist/sdk.js +48 -50
  164. package/dist/sdk.js.map +1 -1
  165. package/dist/seed-core/index.js +8 -8
  166. package/dist/seed-core/index.js.map +1 -1
  167. package/dist/seo-core/blog.d.ts +1 -1
  168. package/dist/seo-core/blog.js +1 -1
  169. package/dist/seo-core/blog.js.map +1 -1
  170. package/dist/seo-core/index.cjs +2 -2
  171. package/dist/seo-core/index.js +1 -1
  172. package/dist/seo-core/index.js.map +1 -1
  173. package/dist/seo.d.ts +1 -1
  174. package/dist/seo.d.ts.map +1 -1
  175. package/dist/seo.js +1 -1
  176. package/dist/seo.js.map +1 -1
  177. package/dist/sitemap-core/index.cjs +5 -5
  178. package/dist/sitemap-core/index.d.ts +13 -5
  179. package/dist/sitemap-core/index.d.ts.map +1 -1
  180. package/dist/sitemap-core/index.js +4 -4
  181. package/dist/sitemap-core/index.js.map +1 -1
  182. package/dist/socials.d.ts +6 -6
  183. package/dist/socials.d.ts.map +1 -1
  184. package/dist/socials.js +5 -5
  185. package/dist/socials.js.map +1 -1
  186. package/dist/solid-compat.d.ts +1 -1
  187. package/dist/solid-compat.js +4 -4
  188. package/dist/solid-compat.js.map +1 -1
  189. package/dist/store-core/index.d.ts +1 -1
  190. package/dist/vanilla.d.ts +12 -12
  191. package/dist/vanilla.d.ts.map +1 -1
  192. package/dist/vanilla.js +192 -145
  193. package/dist/vanilla.js.map +1 -1
  194. package/openapi.json +264 -1
  195. package/package.json +8 -8
  196. package/src/account-core/index.ts +1 -1
  197. package/src/adapters-revalidate.ts +3 -3
  198. package/src/analytics-core.ts +8 -8
  199. package/src/analytics-server.ts +6 -6
  200. package/src/angular/{biab-form.component.ts → bd-form.component.ts} +269 -161
  201. package/src/angular/headless.ts +12 -12
  202. package/src/angular/index.ts +9 -9
  203. package/src/auth-handler.ts +22 -22
  204. package/src/auth-links.ts +2 -2
  205. package/src/cli.ts +81 -81
  206. package/src/client.ts +218 -193
  207. package/src/consent-core/index.ts +10 -8
  208. package/src/contracts.ts +99 -15
  209. package/src/data-model-schema.ts +29 -26
  210. package/src/distribution.ts +5 -5
  211. package/src/element.ts +54 -54
  212. package/src/embed-protocol.ts +14 -14
  213. package/src/errors.ts +27 -27
  214. package/src/forms-core/autocomplete.ts +3 -3
  215. package/src/forms-core/controller.ts +12 -12
  216. package/src/forms-core/elements.ts +7 -7
  217. package/src/forms-core/formula.ts +1 -1
  218. package/src/forms-core/index.ts +8 -8
  219. package/src/forms-core/units.ts +1 -1
  220. package/src/forms-core/us-states.ts +1 -1
  221. package/src/forms-core/validation.ts +158 -14
  222. package/src/forms.ts +2 -2
  223. package/src/framework-support.ts +1 -1
  224. package/src/gallery-types.ts +1 -1
  225. package/src/graphql.ts +4 -4
  226. package/src/index.ts +38 -38
  227. package/src/legal-core/index.ts +12 -12
  228. package/src/marketing-core/index.ts +62 -0
  229. package/src/marketing-schema.ts +9 -9
  230. package/src/mcp.ts +4 -4
  231. package/src/native.ts +14 -14
  232. package/src/next-revalidate.ts +10 -10
  233. package/src/notifications-core/index.ts +1 -1
  234. package/src/parallel-pages.ts +6 -6
  235. package/src/portal-core/index.ts +1 -1
  236. package/src/proxy.ts +28 -28
  237. package/src/push-core/index.ts +11 -5
  238. package/src/qwik.tsx +262 -166
  239. package/src/react-analytics.tsx +17 -17
  240. package/src/react-attribution.tsx +2 -2
  241. package/src/react-marketing.tsx +5 -5
  242. package/src/react.tsx +541 -500
  243. package/src/reserved-paths.ts +3 -3
  244. package/src/revalidate-verify.ts +5 -5
  245. package/src/sdk.ts +131 -101
  246. package/src/seed-core/index.ts +8 -8
  247. package/src/seo-core/blog.ts +2 -2
  248. package/src/seo-core/index.ts +1 -1
  249. package/src/seo.ts +1 -1
  250. package/src/sitemap-core/index.ts +17 -9
  251. package/src/socials.ts +6 -6
  252. package/src/solid-compat.tsx +5 -5
  253. package/src/solid-surfaces.tsx +28 -28
  254. package/src/solid.tsx +264 -175
  255. package/src/store-core/index.ts +1 -1
  256. package/src/styles/{biab-forms.css → bd-forms.css} +158 -158
  257. package/src/svelte/{BiabForm.svelte → BdForm.svelte} +240 -173
  258. package/src/svelte/context.ts +16 -16
  259. package/src/svelte/headless.ts +10 -10
  260. package/src/svelte/index.ts +16 -16
  261. package/src/vanilla.ts +250 -169
  262. package/src/vue/{BiabForm.vue → BdForm.vue} +270 -157
  263. package/src/vue/headless.ts +11 -11
  264. package/src/vue/index.ts +26 -26
@@ -1,30 +1,30 @@
1
1
  <!--
2
- @businessdash/sdk/svelte — <BiabForm> drop-in (Svelte 5, runes).
2
+ @businessdash/sdk/svelte — <BdForm> drop-in (Svelte 5, runes).
3
3
 
4
- Renders a BIAB form end-to-end from the headless core
4
+ Renders a BD form end-to-end from the headless core
5
5
  (`createFormController` in `@businessdash/sdk/forms`). It is a faithful port of
6
6
  the dashboard `FormPreview` renderer: per-type field rendering, the
7
7
  condition_block / or_condition / input_group / flex_row tree walk,
8
8
  multi-step ("consecutive") navigation + progress (bar | steps),
9
9
  concurrent-reveal gating, and the schema's render settings
10
- (animation, org icon). All markup uses the `biab-*` light-DOM class
10
+ (animation, org icon). All markup uses the `bd-*` light-DOM class
11
11
  convention so the consumer's CSS cascades — no shadow root.
12
12
 
13
13
  Two data paths (consistent with the other framework bindings):
14
14
 
15
- • client mode — pass a `BiabClient` (prop or `setBiabClient` context).
15
+ • client mode — pass a `BdClient` (prop or `setBdClient` context).
16
16
  The controller fetches the schema (when only `slug` is given) and
17
17
  submits / uploads through the SDK directly. Only safe where the bearer
18
18
  key never reaches the browser.
19
19
 
20
20
  • schema + submitAction mode — pass a pre-fetched `schema` (SSR-loaded
21
- via your server `BiabClient`) plus a `submitAction(payload, opts)` that
22
- POSTs to your own endpoint (e.g. SvelteKit `/api/biab/forms/[slug]`).
21
+ via your server `BdClient`) plus a `submitAction(payload, opts)` that
22
+ POSTs to your own endpoint (e.g. SvelteKit `/api/bd/forms/[slug]`).
23
23
  The bearer key stays in `$lib/server`. This is the recommended
24
24
  SvelteKit pattern and the one the starter wires up.
25
25
  -->
26
26
  <script lang="ts" module>
27
- import type { BiabClient } from "../sdk.js";
27
+ import type { BdClient } from "../sdk.js";
28
28
  import type {
29
29
  FormCoreField,
30
30
  FormSnapshot,
@@ -34,34 +34,34 @@
34
34
  } from "../forms-core/index.js";
35
35
 
36
36
  /** A successful submit result (`ok === true`). */
37
- export type BiabFormSuccess = Extract<FormSubmitResult, { ok: true }>;
37
+ export type BdFormSuccess = Extract<FormSubmitResult, { ok: true }>;
38
38
  /** A failed submit result (`ok === false`). */
39
- export type BiabFormFailure = Extract<FormSubmitResult, { ok: false }>;
39
+ export type BdFormFailure = Extract<FormSubmitResult, { ok: false }>;
40
40
 
41
41
  /**
42
42
  * Re-key the working data (by field `id`) to the published output `key`,
43
43
  * then POST it to your own endpoint. Returning a {@link FormSubmitResult}
44
- * lets `<BiabForm>` surface inline server-side field errors; returning
44
+ * lets `<BdForm>` surface inline server-side field errors; returning
45
45
  * void/anything else is treated as a generic success.
46
46
  */
47
- export type BiabFormSubmitAction = (
47
+ export type BdFormSubmitAction = (
48
48
  payload: Record<string, unknown>,
49
49
  options: FormSubmitOptions,
50
50
  ) => Promise<FormSubmitResult | void> | FormSubmitResult | void;
51
51
 
52
- export interface BiabFormProps {
52
+ export interface BdFormProps {
53
53
  /** Form slug — required in client mode (or when `schema` lacks a slug). */
54
54
  slug?: string;
55
55
  /** Pre-fetched schema (SSR). When present, no client is needed to render. */
56
56
  schema?: FormSchema;
57
- /** SDK client. Falls back to `setBiabClient` context. Omit in schema+action mode. */
58
- client?: BiabClient;
57
+ /** SDK client. Falls back to `setBdClient` context. Omit in schema+action mode. */
58
+ client?: BdClient;
59
59
  /**
60
- * Submit override. When provided, `<BiabForm>` validates locally, re-keys
60
+ * Submit override. When provided, `<BdForm>` validates locally, re-keys
61
61
  * the payload to output keys, then calls this instead of the SDK — the
62
62
  * server-safe SvelteKit path. Takes precedence over `client.forms.submit`.
63
63
  */
64
- submitAction?: BiabFormSubmitAction;
64
+ submitAction?: BdFormSubmitAction;
65
65
  /** Submit button label (final step). Default "Submit". */
66
66
  submitLabel?: string;
67
67
  /** Merged into every submit (e.g. `source`, `metadata`). */
@@ -69,12 +69,12 @@
69
69
  /** Server-validates but stores nothing. */
70
70
  dryRun?: boolean;
71
71
  /** Fired after a successful submit. */
72
- onSuccess?: (result: BiabFormSuccess) => void;
72
+ onSuccess?: (result: BdFormSuccess) => void;
73
73
  /** Fired after a failed submit. */
74
- onError?: (result: BiabFormFailure) => void;
74
+ onError?: (result: BdFormFailure) => void;
75
75
  /** Convenience: fired with the re-keyed payload on a successful submit. */
76
76
  onSubmit?: (payload: Record<string, unknown>) => void;
77
- /** Extra class on the root `.biab-form`. (`className` alias also accepted.) */
77
+ /** Extra class on the root `.bd-form`. (`className` alias also accepted.) */
78
78
  class?: string;
79
79
  /** React-style alias for `class`. */
80
80
  className?: string;
@@ -112,7 +112,7 @@
112
112
  resolveFieldAutocomplete,
113
113
  } from "../forms-core/autocomplete.js";
114
114
 
115
- import { formStore, getBiabClient } from "./context.js";
115
+ import { formStore, getBdClient } from "./context.js";
116
116
 
117
117
  let {
118
118
  slug,
@@ -130,7 +130,7 @@
130
130
  successMessage = "Thanks — your response was received.",
131
131
  autoComplete,
132
132
  fieldAutoComplete,
133
- }: BiabFormProps = $props();
133
+ }: BdFormProps = $props();
134
134
 
135
135
  // HTML autofill config threaded to every value-bearing input. `enabled` only
136
136
  // when the global switch is set; `overrides` only when per-field tokens exist
@@ -146,7 +146,7 @@
146
146
  // values without registering a reactive dependency, which also silences
147
147
  // Svelte's `state_referenced_locally` hint for this deliberate one-time read.
148
148
  const init = untrack(() => ({
149
- client: client ?? getBiabClient(),
149
+ client: client ?? getBdClient(),
150
150
  slug,
151
151
  schema,
152
152
  submitOptions: { ...submitOptions, ...(dryRun ? { dryRun: true } : {}) },
@@ -176,7 +176,7 @@
176
176
  const snap = formStore(controller);
177
177
 
178
178
  const rootClass = $derived(
179
- ["biab-form", klass, className].filter(Boolean).join(" "),
179
+ ["bd-form", klass, className].filter(Boolean).join(" "),
180
180
  );
181
181
 
182
182
  // ── Submit: route through `submitAction` (server-safe) or the SDK. ─────────
@@ -207,23 +207,23 @@
207
207
  return;
208
208
  }
209
209
  // No structured result → treat as success.
210
- const synthetic: BiabFormSuccess = {
210
+ const synthetic: BdFormSuccess = {
211
211
  ok: true,
212
212
  status: 200,
213
213
  submissionId: "",
214
- } as BiabFormSuccess;
214
+ } as BdFormSuccess;
215
215
  actionResult = synthetic;
216
216
  onSubmit?.(payload);
217
217
  onSuccess?.(synthetic);
218
218
  } catch (err) {
219
219
  submittingViaAction = false;
220
- const failure: BiabFormFailure = {
220
+ const failure: BdFormFailure = {
221
221
  ok: false,
222
222
  status: 0,
223
223
  reason: "network_error",
224
224
  message:
225
225
  err instanceof Error ? err.message : "The submission failed.",
226
- } as BiabFormFailure;
226
+ } as BdFormFailure;
227
227
  actionResult = failure;
228
228
  onError?.(failure);
229
229
  }
@@ -424,22 +424,22 @@
424
424
  {@const ac = resolveFieldAutocomplete(field, autocompleteConfig)}
425
425
  {@const acOff = ac === "off"}
426
426
  {#if field.type === "title"}
427
- <h2 class="biab-field__title">{field.label || "Untitled"}</h2>
427
+ <h2 class="bd-field__title">{field.label || "Untitled"}</h2>
428
428
  {:else if field.type === "subtitle"}
429
- <h3 class="biab-field__subtitle">{field.label || ""}</h3>
429
+ <h3 class="bd-field__subtitle">{field.label || ""}</h3>
430
430
  {:else if field.type === "separator"}
431
- <hr class="biab-field__separator" />
431
+ <hr class="bd-field__separator" />
432
432
  {:else if field.type === "richtext"}
433
433
  <!-- richtext is pre-sanitized server-side; rendered as-is. -->
434
- <div class="biab-field__richtext">{@html field.content ?? ""}</div>
434
+ <div class="bd-field__richtext">{@html field.content ?? ""}</div>
435
435
  {:else if field.type === "image"}
436
436
  {#if asStr(field.content)}
437
- <img class="biab-field__image" src={asStr(field.content)} alt={field.label ?? ""} />
437
+ <img class="bd-field__image" src={asStr(field.content)} alt={field.label ?? ""} />
438
438
  {/if}
439
439
  {:else if field.type === "textarea"}
440
440
  {@const taRows = (field.textareaConfig as { rows?: number } | undefined)?.rows ?? 4}
441
441
  <textarea
442
- class="biab-textarea biab-field__control"
442
+ class="bd-textarea bd-field__control"
443
443
  rows={taRows}
444
444
  placeholder={field.placeholder ?? ""}
445
445
  autocomplete={ac ?? undefined}
@@ -451,21 +451,21 @@
451
451
  default. `input list` + `datalist` is native typeahead: no JS, no
452
452
  styling opinion, which is the SDK's contract. -->
453
453
  <input
454
- class="biab-input biab-combobox biab-field__control"
454
+ class="bd-input bd-combobox bd-field__control"
455
455
  type="text"
456
- list={`biab-list-${field.id}`}
456
+ list={`bd-list-${field.id}`}
457
457
  placeholder={field.placeholder || "Search…"}
458
458
  value={asStr(value)}
459
459
  oninput={(e) => onFieldInput(field.id, e.currentTarget.value)}
460
460
  />
461
- <datalist id={`biab-list-${field.id}`}>
461
+ <datalist id={`bd-list-${field.id}`}>
462
462
  {#each field.options ?? [] as opt (opt)}
463
463
  <option value={opt}></option>
464
464
  {/each}
465
465
  </datalist>
466
466
  {:else if field.type === "select"}
467
467
  <select
468
- class="biab-select biab-field__control"
468
+ class="bd-select bd-field__control"
469
469
  value={asStr(value)}
470
470
  onchange={(e) => onFieldInput(field.id, e.currentTarget.value)}
471
471
  >
@@ -478,25 +478,25 @@
478
478
  <!-- The value is an icon NAME; art resolves against the platform's icon
479
479
  route, so no icon library ships in the SDK bundle. -->
480
480
  {@const names = iconPool(field)}
481
- <div class="biab-iconselect">
481
+ <div class="bd-iconselect">
482
482
  <input
483
- class="biab-input biab-iconselect__search"
483
+ class="bd-input bd-iconselect__search"
484
484
  type="text"
485
485
  placeholder={field.placeholder || "Search icons…"}
486
486
  value={iconQuery}
487
487
  oninput={(e) => (iconQuery = e.currentTarget.value)}
488
488
  />
489
489
  {#if asStr(value)}
490
- <span class="biab-iconselect__current">
490
+ <span class="bd-iconselect__current">
491
491
  <img src={iconUrl(asStr(value))} alt={asStr(value)} width="16" height="16" />
492
- <button type="button" class="biab-iconselect__clear" onclick={() => onFieldInput(field.id, "")}>×</button>
492
+ <button type="button" class="bd-iconselect__clear" onclick={() => onFieldInput(field.id, "")}>×</button>
493
493
  </span>
494
494
  {/if}
495
- <div class="biab-iconselect__grid">
495
+ <div class="bd-iconselect__grid">
496
496
  {#each filterIconNames(names, iconQuery) as name (name)}
497
497
  <button
498
498
  type="button"
499
- class="biab-iconselect__item"
499
+ class="bd-iconselect__item"
500
500
  class:is-selected={asStr(value) === name}
501
501
  title={name}
502
502
  aria-label={name}
@@ -512,19 +512,19 @@
512
512
  <!-- One image, either source; the submitted value is a plain URL string. -->
513
513
  {@const cfg = field.imageInputConfig ?? {}}
514
514
  {@const sources = cfg.sources ?? "both"}
515
- <div class="biab-imageinput">
515
+ <div class="bd-imageinput">
516
516
  {#if sources === "both"}
517
- <div class="biab-imageinput__modes">
517
+ <div class="bd-imageinput__modes">
518
518
  <button
519
519
  type="button"
520
- class="biab-imageinput__mode"
520
+ class="bd-imageinput__mode"
521
521
  class:is-active={imageMode === "upload"}
522
522
  aria-pressed={imageMode === "upload"}
523
523
  onclick={() => (imageMode = "upload")}>Upload</button
524
524
  >
525
525
  <button
526
526
  type="button"
527
- class="biab-imageinput__mode"
527
+ class="bd-imageinput__mode"
528
528
  class:is-active={imageMode === "url"}
529
529
  aria-pressed={imageMode === "url"}
530
530
  onclick={() => (imageMode = "url")}>Paste URL</button
@@ -533,14 +533,14 @@
533
533
  {/if}
534
534
  {#if imageMode === "upload" && sources !== "url" && hasClient}
535
535
  <input
536
- class="biab-input biab-imageinput__file"
536
+ class="bd-input bd-imageinput__file"
537
537
  type="file"
538
538
  accept={(cfg.allowedTypes ?? ["image/*"]).join(",")}
539
539
  onchange={(e) => onImagePick(field, e.currentTarget.files, cfg.maxSize ?? 5)}
540
540
  />
541
541
  {:else}
542
542
  <input
543
- class="biab-input biab-imageinput__url"
543
+ class="bd-input bd-imageinput__url"
544
544
  type="url"
545
545
  placeholder={field.placeholder || "https://example.com/image.png"}
546
546
  value={asStr(value)}
@@ -548,13 +548,13 @@
548
548
  />
549
549
  {/if}
550
550
  {#if cfg.showPreview !== false && asStr(value)}
551
- <img class="biab-imageinput__preview" src={asStr(value)} alt="" />
551
+ <img class="bd-imageinput__preview" src={asStr(value)} alt="" />
552
552
  {/if}
553
553
  </div>
554
554
  {:else if field.type === "radio"}
555
- <div class="biab-field__radios">
555
+ <div class="bd-field__radios">
556
556
  {#each field.options ?? [] as opt (opt)}
557
- <label class="biab-field__radio">
557
+ <label class="bd-field__radio">
558
558
  <input
559
559
  type="radio"
560
560
  name={field.id}
@@ -568,9 +568,9 @@
568
568
  </div>
569
569
  {:else if field.type === "checkbox"}
570
570
  {@const arr = Array.isArray(value) ? (value as string[]) : []}
571
- <div class="biab-field__checks">
571
+ <div class="bd-field__checks">
572
572
  {#each field.options ?? [] as opt (opt)}
573
- <label class="biab-field__check">
573
+ <label class="bd-field__check">
574
574
  <input
575
575
  type="checkbox"
576
576
  checked={arr.includes(opt)}
@@ -587,7 +587,7 @@
587
587
  {/each}
588
588
  </div>
589
589
  {:else if field.type === "boolean"}
590
- <label class="biab-field__toggle">
590
+ <label class="bd-field__toggle">
591
591
  <input
592
592
  type="checkbox"
593
593
  checked={value === true}
@@ -597,7 +597,7 @@
597
597
  </label>
598
598
  {:else if field.type === "date"}
599
599
  <input
600
- class="biab-input biab-field__control"
600
+ class="bd-input bd-field__control"
601
601
  type="date"
602
602
  value={asStr(value)}
603
603
  onchange={(e) => onFieldInput(field.id, e.currentTarget.value)}
@@ -606,7 +606,7 @@
606
606
  {@const mode = field.timeConfig?.mode ?? "simple"}
607
607
  {#if mode === "simple"}
608
608
  <select
609
- class="biab-select biab-field__control"
609
+ class="bd-select bd-field__control"
610
610
  value={asStr(value)}
611
611
  onchange={(e) => onFieldInput(field.id, e.currentTarget.value)}
612
612
  >
@@ -617,21 +617,21 @@
617
617
  </select>
618
618
  {:else if mode === "time_block"}
619
619
  {@const v = asObj(value)}
620
- <div class="biab-field__grid2">
621
- <label class="biab-field__sub">
622
- <span class="biab-field__sublabel">Start</span>
620
+ <div class="bd-field__grid2">
621
+ <label class="bd-field__sub">
622
+ <span class="bd-field__sublabel">Start</span>
623
623
  <input
624
- class="biab-input"
624
+ class="bd-input"
625
625
  type="time"
626
626
  value={asStr(v.start)}
627
627
  onchange={(e) =>
628
628
  onFieldInput(field.id, { ...v, start: e.currentTarget.value })}
629
629
  />
630
630
  </label>
631
- <label class="biab-field__sub">
632
- <span class="biab-field__sublabel">End</span>
631
+ <label class="bd-field__sub">
632
+ <span class="bd-field__sublabel">End</span>
633
633
  <input
634
- class="biab-input"
634
+ class="bd-input"
635
635
  type="time"
636
636
  value={asStr(v.end)}
637
637
  onchange={(e) =>
@@ -641,21 +641,21 @@
641
641
  </div>
642
642
  {:else}
643
643
  {@const v = asObj(value)}
644
- <div class="biab-field__grid2">
645
- <label class="biab-field__sub">
646
- <span class="biab-field__sublabel">Date</span>
644
+ <div class="bd-field__grid2">
645
+ <label class="bd-field__sub">
646
+ <span class="bd-field__sublabel">Date</span>
647
647
  <input
648
- class="biab-input"
648
+ class="bd-input"
649
649
  type="date"
650
650
  value={asStr(v.date)}
651
651
  onchange={(e) =>
652
652
  onFieldInput(field.id, { ...v, date: e.currentTarget.value })}
653
653
  />
654
654
  </label>
655
- <label class="biab-field__sub">
656
- <span class="biab-field__sublabel">Time</span>
655
+ <label class="bd-field__sub">
656
+ <span class="bd-field__sublabel">Time</span>
657
657
  <input
658
- class="biab-input"
658
+ class="bd-input"
659
659
  type="time"
660
660
  value={asStr(v.time)}
661
661
  onchange={(e) =>
@@ -666,21 +666,21 @@
666
666
  {/if}
667
667
  {:else if field.type === "date_range"}
668
668
  {@const v = asObj(value)}
669
- <div class="biab-field__grid2">
670
- <label class="biab-field__sub">
671
- <span class="biab-field__sublabel">Start</span>
669
+ <div class="bd-field__grid2">
670
+ <label class="bd-field__sub">
671
+ <span class="bd-field__sublabel">Start</span>
672
672
  <input
673
- class="biab-input"
673
+ class="bd-input"
674
674
  type="date"
675
675
  value={asStr(v.start)}
676
676
  onchange={(e) =>
677
677
  onFieldInput(field.id, { ...v, start: e.currentTarget.value })}
678
678
  />
679
679
  </label>
680
- <label class="biab-field__sub">
681
- <span class="biab-field__sublabel">End</span>
680
+ <label class="bd-field__sub">
681
+ <span class="bd-field__sublabel">End</span>
682
682
  <input
683
- class="biab-input"
683
+ class="bd-input"
684
684
  type="date"
685
685
  value={asStr(v.end)}
686
686
  onchange={(e) =>
@@ -693,8 +693,8 @@
693
693
  {@const max = field.sliderConfig?.max ?? 100}
694
694
  {@const step = field.sliderConfig?.step ?? 1}
695
695
  {@const v = asNum(value, min)}
696
- <div class="biab-field__slider">
697
- <div class="biab-field__slider-meta">
696
+ <div class="bd-field__slider">
697
+ <div class="bd-field__slider-meta">
698
698
  <span>{min}</span><span>{v}</span><span>{max}</span>
699
699
  </div>
700
700
  <input
@@ -710,12 +710,12 @@
710
710
  {@const max = field.starRatingConfig?.maxStars ?? 5}
711
711
  {@const v = asNum(value, 0)}
712
712
  {@const stars = Array.from({ length: max }, (_unused, i) => i)}
713
- <div class="biab-field__stars">
713
+ <div class="bd-field__stars">
714
714
  {#each stars as i (i)}
715
715
  <button
716
716
  type="button"
717
- class="biab-field__star"
718
- class:biab-field__star--on={i < v}
717
+ class="bd-field__star"
718
+ class:bd-field__star--on={i < v}
719
719
  aria-label={`Rate ${i + 1}`}
720
720
  onclick={() => onFieldInput(field.id, i + 1)}
721
721
  >
@@ -725,12 +725,12 @@
725
725
  </div>
726
726
  {:else if field.type === "happiness_rating"}
727
727
  {@const v = asNum(value, -1)}
728
- <div class="biab-field__happiness">
728
+ <div class="bd-field__happiness">
729
729
  {#each ["😞", "😕", "😐", "🙂", "😄"] as emoji, i (emoji)}
730
730
  <button
731
731
  type="button"
732
- class="biab-field__emoji"
733
- class:biab-field__emoji--on={i === v}
732
+ class="bd-field__emoji"
733
+ class:bd-field__emoji--on={i === v}
734
734
  onclick={() => onFieldInput(field.id, i)}
735
735
  >
736
736
  {emoji}
@@ -739,48 +739,115 @@
739
739
  </div>
740
740
  {:else if field.type === "stepper"}
741
741
  {@const v = asNum(value, 0)}
742
- <div class="biab-field__stepper">
743
- <button type="button" class="biab-btn biab-btn--ghost" onclick={() => onFieldInput(field.id, v - 1)}>−</button>
744
- <span class="biab-field__stepper-value">{v}</span>
745
- <button type="button" class="biab-btn biab-btn--ghost" onclick={() => onFieldInput(field.id, v + 1)}>+</button>
742
+ <div class="bd-field__stepper">
743
+ <button type="button" class="bd-btn bd-btn--ghost" onclick={() => onFieldInput(field.id, v - 1)}>−</button>
744
+ <span class="bd-field__stepper-value">{v}</span>
745
+ <button type="button" class="bd-btn bd-btn--ghost" onclick={() => onFieldInput(field.id, v + 1)}>+</button>
746
+ </div>
747
+ {:else if field.type === "name"}
748
+ {@const v = asObj(value)}
749
+ {@const cfg = field.nameConfig ?? {}}
750
+ {@const nicknamesText = Array.isArray(v.nicknames) ? v.nicknames.join(", ") : asStr(v.nicknames)}
751
+ <div class="bd-field__name">
752
+ {#if cfg.prefix}
753
+ <label class="bd-field__sub">
754
+ <span class="bd-field__sublabel">Title</span>
755
+ <input class="bd-input" autocomplete={acOff ? "off" : "honorific-prefix"} placeholder="Dr." value={asStr(v.prefix)}
756
+ oninput={(e) => onFieldInput(field.id, { ...v, prefix: e.currentTarget.value })} />
757
+ </label>
758
+ {/if}
759
+ <div class="bd-field__grid2">
760
+ <label class="bd-field__sub">
761
+ <span class="bd-field__sublabel">First name</span>
762
+ <input class="bd-input" autocomplete={acOff ? "off" : "given-name"} placeholder="Jane" value={asStr(v.first)}
763
+ oninput={(e) => onFieldInput(field.id, { ...v, first: e.currentTarget.value })} />
764
+ </label>
765
+ {#if cfg.middle}
766
+ <label class="bd-field__sub">
767
+ <span class="bd-field__sublabel">Middle name</span>
768
+ <input class="bd-input" autocomplete={acOff ? "off" : "additional-name"} placeholder="Quinn" value={asStr(v.middle)}
769
+ oninput={(e) => onFieldInput(field.id, { ...v, middle: e.currentTarget.value })} />
770
+ </label>
771
+ {:else}
772
+ <label class="bd-field__sub">
773
+ <span class="bd-field__sublabel">Last name</span>
774
+ <input class="bd-input" autocomplete={acOff ? "off" : "family-name"} placeholder="Doe" value={asStr(v.last)}
775
+ oninput={(e) => onFieldInput(field.id, { ...v, last: e.currentTarget.value })} />
776
+ </label>
777
+ {/if}
778
+ </div>
779
+ {#if cfg.middle && cfg.suffix}
780
+ <div class="bd-field__grid2">
781
+ <label class="bd-field__sub">
782
+ <span class="bd-field__sublabel">Last name</span>
783
+ <input class="bd-input" autocomplete={acOff ? "off" : "family-name"} placeholder="Doe" value={asStr(v.last)}
784
+ oninput={(e) => onFieldInput(field.id, { ...v, last: e.currentTarget.value })} />
785
+ </label>
786
+ <label class="bd-field__sub">
787
+ <span class="bd-field__sublabel">Suffix</span>
788
+ <input class="bd-input" autocomplete={acOff ? "off" : "honorific-suffix"} placeholder="Jr." value={asStr(v.suffix)}
789
+ oninput={(e) => onFieldInput(field.id, { ...v, suffix: e.currentTarget.value })} />
790
+ </label>
791
+ </div>
792
+ {:else if cfg.middle}
793
+ <label class="bd-field__sub">
794
+ <span class="bd-field__sublabel">Last name</span>
795
+ <input class="bd-input" autocomplete={acOff ? "off" : "family-name"} placeholder="Doe" value={asStr(v.last)}
796
+ oninput={(e) => onFieldInput(field.id, { ...v, last: e.currentTarget.value })} />
797
+ </label>
798
+ {:else if cfg.suffix}
799
+ <label class="bd-field__sub">
800
+ <span class="bd-field__sublabel">Suffix</span>
801
+ <input class="bd-input" autocomplete={acOff ? "off" : "honorific-suffix"} placeholder="Jr." value={asStr(v.suffix)}
802
+ oninput={(e) => onFieldInput(field.id, { ...v, suffix: e.currentTarget.value })} />
803
+ </label>
804
+ {/if}
805
+ {#if cfg.nicknames}
806
+ <!-- Raw comma-separated string while typing; submit normalizes it into a string[]. -->
807
+ <label class="bd-field__sub">
808
+ <span class="bd-field__sublabel">Nicknames</span>
809
+ <input class="bd-input" placeholder="Johnny, JM — separate with commas" value={nicknamesText}
810
+ oninput={(e) => onFieldInput(field.id, { ...v, nicknames: e.currentTarget.value })} />
811
+ </label>
812
+ {/if}
746
813
  </div>
747
814
  {:else if field.type === "address"}
748
815
  {@const v = asObj(value)}
749
- <div class="biab-field__address">
750
- <label class="biab-field__sub">
751
- <span class="biab-field__sublabel">Address Line 1</span>
752
- <input class="biab-input" autocomplete={acOff ? "off" : "street-address"} value={asStr(v.line1)}
816
+ <div class="bd-field__address">
817
+ <label class="bd-field__sub">
818
+ <span class="bd-field__sublabel">Address Line 1</span>
819
+ <input class="bd-input" autocomplete={acOff ? "off" : "street-address"} value={asStr(v.line1)}
753
820
  oninput={(e) => onFieldInput(field.id, { ...v, line1: e.currentTarget.value })} />
754
821
  </label>
755
- <label class="biab-field__sub">
756
- <span class="biab-field__sublabel">Address Line 2</span>
757
- <input class="biab-input" autocomplete={acOff ? "off" : "address-line2"} value={asStr(v.line2)}
822
+ <label class="bd-field__sub">
823
+ <span class="bd-field__sublabel">Address Line 2</span>
824
+ <input class="bd-input" autocomplete={acOff ? "off" : "address-line2"} value={asStr(v.line2)}
758
825
  oninput={(e) => onFieldInput(field.id, { ...v, line2: e.currentTarget.value })} />
759
826
  </label>
760
- <label class="biab-field__sub">
761
- <span class="biab-field__sublabel">City</span>
762
- <input class="biab-input" autocomplete={acOff ? "off" : "address-level2"} value={asStr(v.city)}
827
+ <label class="bd-field__sub">
828
+ <span class="bd-field__sublabel">City</span>
829
+ <input class="bd-input" autocomplete={acOff ? "off" : "address-level2"} value={asStr(v.city)}
763
830
  oninput={(e) => onFieldInput(field.id, { ...v, city: e.currentTarget.value })} />
764
831
  </label>
765
- <label class="biab-field__sub">
766
- <span class="biab-field__sublabel">State</span>
767
- <input class="biab-input" autocomplete={acOff ? "off" : "address-level1"} value={asStr(v.state)}
832
+ <label class="bd-field__sub">
833
+ <span class="bd-field__sublabel">State</span>
834
+ <input class="bd-input" autocomplete={acOff ? "off" : "address-level1"} value={asStr(v.state)}
768
835
  oninput={(e) => onFieldInput(field.id, { ...v, state: e.currentTarget.value })} />
769
836
  </label>
770
- <label class="biab-field__sub">
771
- <span class="biab-field__sublabel">Zip</span>
772
- <input class="biab-input" autocomplete={acOff ? "off" : "postal-code"} value={asStr(v.zip)}
837
+ <label class="bd-field__sub">
838
+ <span class="bd-field__sublabel">Zip</span>
839
+ <input class="bd-input" autocomplete={acOff ? "off" : "postal-code"} value={asStr(v.zip)}
773
840
  oninput={(e) => onFieldInput(field.id, { ...v, zip: e.currentTarget.value })} />
774
841
  </label>
775
842
  </div>
776
843
  {:else if field.type === "color_picker"}
777
844
  {@const v = asStr(value)}
778
- <div class="biab-field__colors">
845
+ <div class="bd-field__colors">
779
846
  {#each field.options ?? [] as color (color)}
780
847
  <button
781
848
  type="button"
782
- class="biab-field__color"
783
- class:biab-field__color--on={v === color}
849
+ class="bd-field__color"
850
+ class:bd-field__color--on={v === color}
784
851
  style={`background-color:${color}`}
785
852
  title={color}
786
853
  aria-label={color}
@@ -791,7 +858,7 @@
791
858
  {:else if field.type === "file_upload"}
792
859
  {@const list = Array.isArray(value) ? (value as Array<{ name?: string; size?: number }>) : []}
793
860
  {#if hasClient}
794
- <div class="biab-field__file">
861
+ <div class="bd-field__file">
795
862
  <input
796
863
  type="file"
797
864
  multiple={(field.fileConfig?.maxFiles ?? 1) > 1}
@@ -799,24 +866,24 @@
799
866
  disabled={snapshot.uploading}
800
867
  onchange={(e) => onFilePick(field, e.currentTarget.files)}
801
868
  />
802
- {#if snapshot.uploading}<span class="biab-field__file-status">Uploading…</span>{/if}
869
+ {#if snapshot.uploading}<span class="bd-field__file-status">Uploading…</span>{/if}
803
870
  {#if list.length > 0}
804
- <ul class="biab-field__file-list">
871
+ <ul class="bd-field__file-list">
805
872
  {#each list as f, i (i)}
806
873
  <li>{f.name ?? "file"}{f.size ? ` · ${Math.round((f.size ?? 0) / 1024)} KB` : ""}</li>
807
874
  {/each}
808
875
  </ul>
809
876
  {/if}
810
- {#if uploadError}<p class="biab-field__error">{uploadError}</p>{/if}
877
+ {#if uploadError}<p class="bd-field__error">{uploadError}</p>{/if}
811
878
  </div>
812
879
  {:else}
813
- <div class="biab-field__file biab-field__file--disabled">
880
+ <div class="bd-field__file bd-field__file--disabled">
814
881
  File upload requires an SDK client (uploads are disabled in schema-only mode).
815
882
  </div>
816
883
  {/if}
817
884
  {:else if field.type === "phone"}
818
885
  <input
819
- class="biab-input biab-field__control"
886
+ class="bd-input bd-field__control"
820
887
  type="tel"
821
888
  placeholder={field.placeholder ||
822
889
  (field.phoneConfig?.international ? "+1 (555) 000-0000" : "(555) 000-0000")}
@@ -826,7 +893,7 @@
826
893
  />
827
894
  {:else if field.type === "email"}
828
895
  <input
829
- class="biab-input biab-field__control"
896
+ class="bd-input bd-field__control"
830
897
  type="email"
831
898
  placeholder={field.placeholder || "you@example.com"}
832
899
  autocomplete={ac ?? undefined}
@@ -835,7 +902,7 @@
835
902
  />
836
903
  {:else if field.type === "number"}
837
904
  <input
838
- class="biab-input biab-field__control"
905
+ class="bd-input bd-field__control"
839
906
  type="number"
840
907
  placeholder={field.placeholder ?? ""}
841
908
  value={typeof value === "number" ? value : asStr(value)}
@@ -844,7 +911,7 @@
844
911
  />
845
912
  {:else}
846
913
  <input
847
- class="biab-input biab-field__control"
914
+ class="bd-input bd-field__control"
848
915
  placeholder={field.placeholder ?? ""}
849
916
  autocomplete={ac ?? undefined}
850
917
  value={asStr(value)}
@@ -856,38 +923,38 @@
856
923
  {#snippet fieldRow(field: FormCoreField, snapshot: FormSnapshot)}
857
924
  {@const errored = Boolean(snapshot.errors[field.id])}
858
925
  <div
859
- class="biab-field biab-field--{field.type}"
860
- class:biab-field--required={field.required}
861
- class:biab-field--error={errored}
926
+ class="bd-field bd-field--{field.type}"
927
+ class:bd-field--required={field.required}
928
+ class:bd-field--error={errored}
862
929
  data-field-id={field.id}
863
- data-biab-field={fieldCssKey(field)}
864
- data-biab-type={field.type}
930
+ data-bd-field={fieldCssKey(field)}
931
+ data-bd-type={field.type}
865
932
  >
866
933
  {#if !LABELLESS.has(field.type)}
867
- <span class="biab-label biab-field__label">
868
- {field.label || ""}{#if field.required}<span class="biab-field__required"> *</span>{/if}
934
+ <span class="bd-label bd-field__label">
935
+ {field.label || ""}{#if field.required}<span class="bd-field__required"> *</span>{/if}
869
936
  </span>
870
937
  {/if}
871
938
  {@render fieldInput(field, snapshot)}
872
939
  {#if errored}
873
- <p class="biab-field__error">{snapshot.errors[field.id]?.message}</p>
940
+ <p class="bd-field__error">{snapshot.errors[field.id]?.message}</p>
874
941
  {/if}
875
942
  {#if field.helpText}
876
- <p class="biab-field__help">{field.helpText}</p>
943
+ <p class="bd-field__help">{field.helpText}</p>
877
944
  {/if}
878
945
  </div>
879
946
  {/snippet}
880
947
 
881
948
  <!-- The recursive tree walk — mirrors FormPreview's RenderTree. -->
882
949
  {#snippet renderTree(nodes: FormCoreField[], snapshot: FormSnapshot, flat: boolean)}
883
- <div class="biab-tree">
950
+ <div class="bd-tree">
884
951
  {#each nodes as f (f.id)}
885
952
  {#if f.type === "input_group"}
886
953
  {@const kids = (f.children ?? []) as FormCoreField[]}
887
954
  {@const reveal = revealCountFor(f, snapshot.values)}
888
- <div class="biab-group" class:biab-group--card={!flat} data-biab-group={fieldCssKey(f)}>
955
+ <div class="bd-group" class:bd-group--card={!flat} data-bd-group={fieldCssKey(f)}>
889
956
  {#if f.label && f.showGroupLabel}
890
- <div class="biab-group__label">{f.label}</div>
957
+ <div class="bd-group__label">{f.label}</div>
891
958
  {/if}
892
959
  {@render renderTree(kids.slice(0, reveal), snapshot, false)}
893
960
  </div>
@@ -900,32 +967,32 @@
900
967
  {@const errored = Boolean(snapshot.errors[f.id])}
901
968
  {@const left = f.children?.[0]}
902
969
  {@const right = f.children?.[1]}
903
- <div class="biab-or" class:biab-or--error={errored}>
970
+ <div class="bd-or" class:bd-or--error={errored}>
904
971
  {#if f.label}
905
- <div class="biab-or__label">
906
- {f.label}<span class="biab-or__hint"> Fill at least one side</span>
972
+ <div class="bd-or__label">
973
+ {f.label}<span class="bd-or__hint"> Fill at least one side</span>
907
974
  </div>
908
975
  {/if}
909
- <div class="biab-or__cols">
910
- <div class="biab-or__col">
911
- <div class="biab-or__col-label">{f.orConditionConfig?.leftLabel || "Option A"}</div>
976
+ <div class="bd-or__cols">
977
+ <div class="bd-or__col">
978
+ <div class="bd-or__col-label">{f.orConditionConfig?.leftLabel || "Option A"}</div>
912
979
  {#if left}{@render renderTree([left], snapshot, false)}{/if}
913
980
  </div>
914
- <div class="biab-or__sep">OR</div>
915
- <div class="biab-or__col">
916
- <div class="biab-or__col-label">{f.orConditionConfig?.rightLabel || "Option B"}</div>
981
+ <div class="bd-or__sep">OR</div>
982
+ <div class="bd-or__col">
983
+ <div class="bd-or__col-label">{f.orConditionConfig?.rightLabel || "Option B"}</div>
917
984
  {#if right}{@render renderTree([right], snapshot, false)}{/if}
918
985
  </div>
919
986
  </div>
920
987
  {#if errored}
921
- <p class="biab-field__error">Fill in at least one side to continue.</p>
988
+ <p class="bd-field__error">Fill in at least one side to continue.</p>
922
989
  {/if}
923
990
  </div>
924
991
  {:else if f.type === "flex_row"}
925
992
  {@const rowKids = (f.children ?? []) as FormCoreField[]}
926
- <div class="biab-flex-row">
993
+ <div class="bd-flex-row">
927
994
  {#each rowKids as child (child.id)}
928
- <div class="biab-flex-row__cell">
995
+ <div class="bd-flex-row__cell">
929
996
  {@render fieldRow(child, snapshot)}
930
997
  </div>
931
998
  {/each}
@@ -939,43 +1006,43 @@
939
1006
 
940
1007
  <section class={rootClass}>
941
1008
  {#if $snap.orgIcon}
942
- <img class="biab-form__org-icon" src={$snap.orgIcon} alt="" />
1009
+ <img class="bd-form__org-icon" src={$snap.orgIcon} alt="" />
943
1010
  {/if}
944
1011
 
945
1012
  {#if $snap.status === "loading"}
946
- <div class="biab-loading">Loading form…</div>
1013
+ <div class="bd-loading">Loading form…</div>
947
1014
  {:else if $snap.status === "error"}
948
- <div class="biab-empty biab-form__error">{$snap.loadError ?? "Couldn't load the form."}</div>
1015
+ <div class="bd-empty bd-form__error">{$snap.loadError ?? "Couldn't load the form."}</div>
949
1016
  {:else if submitted}
950
- <div class="biab-card biab-form__success" role="status">
951
- <span class="biab-badge">Received</span>
1017
+ <div class="bd-card bd-form__success" role="status">
1018
+ <span class="bd-badge">Received</span>
952
1019
  <p>{successMessage}</p>
953
1020
  </div>
954
1021
  {:else}
955
1022
  {#if $snap.title || $snap.description}
956
- <div class="biab-form__lead">
957
- {#if $snap.title}<h2 class="biab-section__title">{$snap.title}</h2>{/if}
958
- {#if $snap.description}<p class="biab-section__sub">{$snap.description}</p>{/if}
1023
+ <div class="bd-form__lead">
1024
+ {#if $snap.title}<h2 class="bd-section__title">{$snap.title}</h2>{/if}
1025
+ {#if $snap.description}<p class="bd-section__sub">{$snap.description}</p>{/if}
959
1026
  </div>
960
1027
  {/if}
961
1028
 
962
1029
  <!-- Multi-step progress: "steps" indicator. -->
963
1030
  {#if $snap.settings.isConsecutive && $snap.settings.showProgress && $snap.settings.progressStyle !== "bar" && $snap.stepCount > 1}
964
- <div class="biab-progress biab-progress--steps">
965
- <div class="biab-progress__heading">Form Progress</div>
966
- <ol class="biab-progress__steps">
1031
+ <div class="bd-progress bd-progress--steps">
1032
+ <div class="bd-progress__heading">Form Progress</div>
1033
+ <ol class="bd-progress__steps">
967
1034
  {#each $snap.steps as s, i (i)}
968
1035
  {@const head = s[0]}
969
1036
  {@const stepLabel = head?.stepTitle || head?.label || `Step ${i + 1}`}
970
1037
  <li
971
- class="biab-progress__step"
972
- class:biab-progress__step--current={i === $snap.step}
973
- class:biab-progress__step--done={i < $snap.step}
1038
+ class="bd-progress__step"
1039
+ class:bd-progress__step--current={i === $snap.step}
1040
+ class:bd-progress__step--done={i < $snap.step}
974
1041
  >
975
- <button type="button" class="biab-progress__dot" onclick={() => controller.goToStep(i)}>
1042
+ <button type="button" class="bd-progress__dot" onclick={() => controller.goToStep(i)}>
976
1043
  {i < $snap.step ? "✓" : i + 1}
977
1044
  </button>
978
- <span class="biab-progress__label">{stepLabel}</span>
1045
+ <span class="bd-progress__label">{stepLabel}</span>
979
1046
  </li>
980
1047
  {/each}
981
1048
  </ol>
@@ -984,20 +1051,20 @@
984
1051
 
985
1052
  <!-- Multi-step progress: thin "bar". -->
986
1053
  {#if $snap.settings.isConsecutive && $snap.settings.showProgress && $snap.settings.progressStyle === "bar" && $snap.stepCount > 1}
987
- <div class="biab-progress biab-progress--bar">
988
- <span class="biab-progress__count">{$snap.step + 1} / {$snap.stepCount}</span>
989
- <div class="biab-progress__track">
990
- <div class="biab-progress__fill" style={`width:${$snap.progressPercent}%`}></div>
1054
+ <div class="bd-progress bd-progress--bar">
1055
+ <span class="bd-progress__count">{$snap.step + 1} / {$snap.stepCount}</span>
1056
+ <div class="bd-progress__track">
1057
+ <div class="bd-progress__fill" style={`width:${$snap.progressPercent}%`}></div>
991
1058
  </div>
992
1059
  </div>
993
1060
  {/if}
994
1061
 
995
1062
  {#if $snap.errorList.length > 0}
996
- <div class="biab-form__errors" role="alert">
997
- <div class="biab-form__errors-title">
1063
+ <div class="bd-form__errors" role="alert">
1064
+ <div class="bd-form__errors-title">
998
1065
  Please complete the highlighted required field{$snap.errorList.length === 1 ? "" : "s"}.
999
1066
  </div>
1000
- <div class="biab-form__errors-list">
1067
+ <div class="bd-form__errors-list">
1001
1068
  {$snap.errorList.map((e) => e.label).join(", ")}
1002
1069
  </div>
1003
1070
  </div>
@@ -1005,7 +1072,7 @@
1005
1072
 
1006
1073
  <!-- The active step's subtree (single-page = all fields). -->
1007
1074
  {#if $snap.settings.animation === "scroll"}
1008
- <div class="biab-tree">
1075
+ <div class="bd-tree">
1009
1076
  {#each $snap.visibleFields as vf (vf.id)}
1010
1077
  {@render renderTree([vf], $snap, $snap.settings.isConsecutive)}
1011
1078
  {/each}
@@ -1019,15 +1086,15 @@
1019
1086
  {/if}
1020
1087
 
1021
1088
  {#if submitError}
1022
- <div class="biab-form__submit-error" role="alert">{submitError}</div>
1089
+ <div class="bd-form__submit-error" role="alert">{submitError}</div>
1023
1090
  {/if}
1024
1091
 
1025
1092
  <!-- Nav: multi-step (Back / Next / Submit) or single-page (Submit). -->
1026
1093
  {#if $snap.settings.isConsecutive && $snap.stepCount > 1}
1027
- <div class="biab-nav">
1094
+ <div class="bd-nav">
1028
1095
  <button
1029
1096
  type="button"
1030
- class="biab-btn biab-btn--ghost biab-btn--back"
1097
+ class="bd-btn bd-btn--ghost bd-btn--back"
1031
1098
  disabled={$snap.isFirstStep}
1032
1099
  onclick={() => controller.back()}
1033
1100
  >
@@ -1036,7 +1103,7 @@
1036
1103
  {#if !$snap.isLastStep}
1037
1104
  <button
1038
1105
  type="button"
1039
- class="biab-btn biab-btn--next"
1106
+ class="bd-btn bd-btn--next"
1040
1107
  disabled={!$snap.canAdvance}
1041
1108
  onclick={() => controller.next()}
1042
1109
  >
@@ -1045,7 +1112,7 @@
1045
1112
  {:else}
1046
1113
  <button
1047
1114
  type="button"
1048
- class="biab-btn biab-btn--submit"
1115
+ class="bd-btn bd-btn--submit"
1049
1116
  disabled={submitting}
1050
1117
  onclick={() => void handleSubmit()}
1051
1118
  >
@@ -1054,10 +1121,10 @@
1054
1121
  {/if}
1055
1122
  </div>
1056
1123
  {:else}
1057
- <div class="biab-nav">
1124
+ <div class="bd-nav">
1058
1125
  <button
1059
1126
  type="button"
1060
- class="biab-btn biab-btn--submit"
1127
+ class="bd-btn bd-btn--submit"
1061
1128
  disabled={submitting}
1062
1129
  onclick={() => void handleSubmit()}
1063
1130
  >