bhl-forms 0.0.3 → 0.0.4

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.
@@ -4391,6 +4391,33 @@ var __spreadValues2 = (a2, b2) => {
4391
4391
  return a2;
4392
4392
  };
4393
4393
  var __spreadProps2 = (a2, b2) => __defProps2(a2, __getOwnPropDescs2(b2));
4394
+ function usePrepop() {
4395
+ let prepopSettings = {};
4396
+ const urlParams2 = new URLSearchParams(window.location.search);
4397
+ const prepopPlugin2 = (node) => {
4398
+ if (node.props.type == "form") {
4399
+ prepopSettings = node.props.attrs.prepop || prepopSettings;
4400
+ return true;
4401
+ }
4402
+ if (node.props.type == "group") {
4403
+ return true;
4404
+ }
4405
+ if (prepopSettings) {
4406
+ let value;
4407
+ if (prepopSettings.values) {
4408
+ value = prepopSettings.values[node.name];
4409
+ }
4410
+ if (prepopSettings.fromURL && urlParams2.has(node.name)) {
4411
+ value = urlParams2.get(node.name);
4412
+ }
4413
+ if (value) {
4414
+ console.debug("Setting prepop value for:", node.name, value);
4415
+ node.input(value);
4416
+ }
4417
+ }
4418
+ };
4419
+ return { prepopPlugin: prepopPlugin2, prepopSettings };
4420
+ }
4394
4421
  function token$1() {
4395
4422
  return Math.random().toString(36).substring(2, 15);
4396
4423
  }
@@ -5237,42 +5264,134 @@ function clearErrors$1$1(node, context, clearChildErrors = true) {
5237
5264
  }
5238
5265
  return node;
5239
5266
  }
5267
+ const postJSON = async (url3, data) => {
5268
+ console.debug("Posting to " + url3);
5269
+ const raw2 = await fetch(url3, {
5270
+ method: "POST",
5271
+ headers: {
5272
+ "Accept": "application/json",
5273
+ "Content-Type": "application/json"
5274
+ },
5275
+ body: JSON.stringify(data)
5276
+ });
5277
+ if (!raw2.ok) {
5278
+ let error2 = new Error(raw2.statusText);
5279
+ Object.assign(error2, { response: raw2 });
5280
+ throw error2;
5281
+ }
5282
+ const res = await raw2.json();
5283
+ console.debug("POST response:" + JSON.stringify(res, null, 2));
5284
+ return res;
5285
+ };
5286
+ const redirect = (url3) => {
5287
+ window.location.href = url3;
5288
+ };
5289
+ const handleSubmitError = (err, node) => {
5290
+ if (err.response) {
5291
+ const code = err.response.status;
5292
+ if (node.props.attrs.errorCodes && code in node.props.attrs.errorCodes) {
5293
+ const value = node.props.attrs.errorCodes[code];
5294
+ let message2 = null;
5295
+ let abort = true;
5296
+ if (typeof value === "string") {
5297
+ message2 = value;
5298
+ } else {
5299
+ if ("message" in value) {
5300
+ message2 = value.message;
5301
+ }
5302
+ if ("abort" in value) {
5303
+ abort = value.abort;
5304
+ }
5305
+ }
5306
+ if (message2) {
5307
+ node.setErrors(message2);
5308
+ }
5309
+ return abort;
5310
+ }
5311
+ }
5312
+ node.setErrors(err.toString());
5313
+ return true;
5314
+ };
5315
+ const keyValOverlap = (o1, o2, multiple = true) => {
5316
+ let result = null;
5317
+ for (var input2 of Object.keys(o1)) {
5318
+ const value = o1[input2];
5319
+ if (o2[input2] && o2[input2][value]) {
5320
+ if (result !== null && !multiple) {
5321
+ throw Error("Multiple values not allowed");
5322
+ }
5323
+ result = o2[input2][value];
5324
+ break;
5325
+ }
5326
+ }
5327
+ if (result === null) {
5328
+ if ("*" in o2) {
5329
+ return o2["*"];
5330
+ }
5331
+ throw Error("result not found and no default specified");
5332
+ }
5333
+ return result;
5334
+ };
5335
+ const getKey = (d2, path) => {
5336
+ if (typeof path === "string") {
5337
+ path = path.split(".");
5338
+ }
5339
+ return path.reduce((x2, y) => x2[y], d2);
5340
+ };
5341
+ const strSubUrl = (str, obj) => str.replace(/\${(.*?)}/g, (x2, g2) => encodeURIComponent(getKey(obj, g2)));
5240
5342
  function useSteps() {
5241
5343
  const activeStep2 = ref("");
5242
5344
  const steps2 = reactive({});
5243
5345
  let defaultOrder2 = [];
5244
- let stepOrder2 = ref([]);
5245
- const setStepOrder2 = (order2) => {
5246
- stepOrder2.value = order2;
5247
- console.debug("new stepOrder", order2);
5346
+ let stepQueue2 = ref([]);
5347
+ let stepHistory2 = ref([]);
5348
+ const lastItem = (x2) => {
5349
+ return x2.value[x2.value.length - 1];
5248
5350
  };
5249
5351
  const firstStep2 = () => {
5250
- const stepNames = Object.keys(steps2);
5251
- return stepNames[0];
5352
+ if (stepHistory2.value.length > 0) {
5353
+ return stepHistory2.value[0];
5354
+ }
5355
+ return stepQueue2.value[0];
5252
5356
  };
5253
5357
  const lastStep2 = () => {
5254
- return stepOrder2.value[stepOrder2.value.length - 1];
5358
+ if (stepQueue2.value.length > 0) {
5359
+ return lastItem(stepQueue2);
5360
+ }
5361
+ return lastItem(stepHistory2);
5255
5362
  };
5256
- const currentIndex = () => {
5257
- console.debug("currentIndex of", activeStep2.value, "is", stepOrder2.value.indexOf(activeStep2.value));
5258
- return stepOrder2.value.indexOf(activeStep2.value);
5363
+ const enabledSteps2 = () => {
5364
+ return [...stepHistory2.value, ...stepQueue2.value];
5259
5365
  };
5260
- const setStepIndex = (index2) => {
5261
- activeStep2.value = stepOrder2.value[index2];
5366
+ const setStepQueue = (value) => {
5367
+ stepQueue2.value = [...value];
5262
5368
  };
5263
- const setStepName = (name) => {
5264
- const index2 = stepOrder2.value.indexOf(name);
5265
- if (index2 < 0) {
5266
- throw Error("Invalid step name " + name);
5369
+ const queueStep = (stepName, next = false) => {
5370
+ if (next == true) {
5371
+ stepQueue2.value.unshift(stepName);
5372
+ } else {
5373
+ stepQueue2.value.push(stepName);
5267
5374
  }
5268
- activeStep2.value = stepOrder2.value[index2];
5375
+ };
5376
+ const advanceStep = (stepCount) => {
5377
+ if (stepCount == 1) {
5378
+ const done = stepQueue2.value.shift();
5379
+ stepHistory2.value.push(done);
5380
+ activeStep2.value = stepQueue2.value[0];
5381
+ } else if (stepCount == -1) {
5382
+ const undone = stepHistory2.value.pop();
5383
+ queueStep(undone, true);
5384
+ activeStep2.value = undone;
5385
+ } else {
5386
+ throw Error("Invalid stepCount: " + JSON.stringify(stepCount));
5387
+ }
5388
+ };
5389
+ const getNextStepsFromMap = (node, nextStepMap) => {
5390
+ return keyValOverlap(node.value, nextStepMap, false);
5269
5391
  };
5270
5392
  const setStep2 = ({ nextStep = 1, validate: validate2 = true } = {}) => {
5271
- console.debug("activeStep", activeStep2.value, "nextStep", nextStep, "validate", validate2);
5393
+ const node = steps2[activeStep2.value].node;
5272
5394
  if (validate2) {
5273
- const currentStep = activeStep2.value;
5274
- console.debug("validating", currentStep);
5275
- const node = steps2[currentStep].node;
5276
5395
  node.walk((n2) => {
5277
5396
  n2.store.set(createMessage$1({
5278
5397
  key: "submitted",
@@ -5284,22 +5403,23 @@ function useSteps() {
5284
5403
  return;
5285
5404
  }
5286
5405
  }
5287
- if (nextStep instanceof Function) {
5288
- const nextStep2 = nextStepFunc();
5289
- setStepName(nextStep2);
5290
- } else if (typeof nextStep === "string") {
5291
- setStepName(nextStep);
5292
- } else if (typeof nextStep === "number") {
5293
- setStepIndex(nextStep);
5406
+ if (node.props.attrs.nextStepMap) {
5407
+ const nextSteps = getNextStepsFromMap(node, node.props.attrs.nextStepMap);
5408
+ if (nextSteps) {
5409
+ setStepQueue([activeStep2.value, ...nextSteps]);
5410
+ }
5411
+ }
5412
+ if (typeof nextStep === "number") {
5413
+ advanceStep(nextStep);
5294
5414
  } else {
5295
5415
  throw Error("Unexpected value for nextStep: " + nextStep);
5296
5416
  }
5297
5417
  };
5298
5418
  const setNextStep2 = () => {
5299
- setStep2({ nextStep: currentIndex() + 1 });
5419
+ setStep2({ nextStep: 1 });
5300
5420
  };
5301
5421
  const setPreviousStep2 = () => {
5302
- setStep2({ nextStep: currentIndex() - 1, validate: false });
5422
+ setStep2({ nextStep: -1, validate: false });
5303
5423
  };
5304
5424
  const stepPlugin2 = (node) => {
5305
5425
  if (node.props.type == "form") {
@@ -5309,16 +5429,17 @@ function useSteps() {
5309
5429
  return true;
5310
5430
  }
5311
5431
  if (node.props.type == "group") {
5312
- console.debug("Adding step node", node);
5313
- steps2[node.name] = steps2[node.name] || {};
5314
- steps2[node.name].node = node;
5315
5432
  if (defaultOrder2.length > 0) {
5316
- if (stepOrder2.value.length === 0) {
5317
- stepOrder2.value = defaultOrder2;
5433
+ if (Object.keys(steps2).length === 0) {
5434
+ setStepQueue(defaultOrder2);
5318
5435
  }
5319
5436
  } else {
5320
- stepOrder2.value.push(node.name);
5437
+ if (!(node.name in steps2)) {
5438
+ queueStep(node.name);
5439
+ }
5321
5440
  }
5441
+ steps2[node.name] = steps2[node.name] || {};
5442
+ steps2[node.name].node = node;
5322
5443
  node.on("created", () => {
5323
5444
  steps2[node.name].valid = toRef(node.context.state, "valid");
5324
5445
  });
@@ -5334,56 +5455,23 @@ function useSteps() {
5334
5455
  return false;
5335
5456
  }
5336
5457
  };
5337
- return { stepPlugin: stepPlugin2, steps: steps2, stepOrder: stepOrder2, defaultOrder: defaultOrder2, setStepOrder: setStepOrder2, activeStep: activeStep2, firstStep: firstStep2, lastStep: lastStep2, setStep: setStep2, setNextStep: setNextStep2, setPreviousStep: setPreviousStep2 };
5458
+ return { stepPlugin: stepPlugin2, steps: steps2, stepHistory: stepHistory2, stepQueue: stepQueue2, enabledSteps: enabledSteps2, defaultOrder: defaultOrder2, activeStep: activeStep2, firstStep: firstStep2, lastStep: lastStep2, setStep: setStep2, setStepQueue, setNextStep: setNextStep2, setPreviousStep: setPreviousStep2 };
5338
5459
  }
5339
- const postJSON = async (url3, data) => {
5340
- console.debug("Posting to " + url3);
5341
- const rawResponse = await fetch(url3, {
5342
- method: "POST",
5343
- headers: {
5344
- "Accept": "application/json",
5345
- "Content-Type": "application/json"
5346
- },
5347
- body: JSON.stringify(data)
5348
- });
5349
- const res = await rawResponse.json();
5350
- console.debug("POST response:" + JSON.stringify(res, null, 2));
5351
- return res;
5352
- };
5353
- const redirect = (url3) => {
5354
- console.debug("redirect to " + url3);
5355
- window.location.href = url3;
5356
- };
5357
- const getKey = (d2, path) => {
5358
- if (typeof path === "string") {
5359
- path = path.split(".");
5360
- }
5361
- return path.reduce((x2, y) => x2[y], d2);
5362
- };
5363
- const strSubUrl = (str, obj) => str.replace(/\${(.*?)}/g, (x2, g2) => encodeURIComponent(getKey(obj, g2)));
5364
- let { stepPlugin, steps, stepOrder, defaultOrder, setStepOrder, activeStep, firstStep, lastStep, setStep, setNextStep, setPreviousStep } = useSteps();
5365
- let prepopValues = {};
5366
- const prepopPlugin = (node) => {
5367
- if (node.props.type == "form") {
5368
- prepopValues = node.props.attrs.prepop || prepopValues;
5369
- return true;
5370
- }
5371
- if (node.props.type == "group") {
5372
- return true;
5373
- }
5374
- if (prepopValues[node.name]) {
5375
- console.debug("Setting prepop value for:", node.name, prepopValues[node.name]);
5376
- node.input(prepopValues[node.name]);
5377
- }
5378
- };
5460
+ let { prepopPlugin } = usePrepop();
5461
+ let { stepPlugin, steps, stepHistory, stepQueue, enabledSteps, defaultOrder, activeStep, firstStep, lastStep, setStep, setNextStep, setPreviousStep } = useSteps();
5462
+ const urlParams = new URLSearchParams(window.location.search);
5379
5463
  const dataDefaults = {
5380
5464
  steps,
5381
- stepOrder,
5382
5465
  activeStep,
5466
+ stepHistory,
5467
+ stepQueue,
5383
5468
  plugins: [
5384
5469
  stepPlugin,
5385
5470
  prepopPlugin
5386
5471
  ],
5472
+ urlParam: (name, backup = null) => {
5473
+ return urlParams.get(name) || backup;
5474
+ },
5387
5475
  firstStep: () => {
5388
5476
  return firstStep();
5389
5477
  },
@@ -5397,37 +5485,53 @@ const dataDefaults = {
5397
5485
  setPreviousStep();
5398
5486
  },
5399
5487
  setStep: (nextStep, validate2) => () => {
5400
- console.debug("setStep:", nextStep, validate2);
5401
5488
  setStep({ nextStep, validate: validate2 });
5402
5489
  },
5403
- setStepOrder: (target) => () => {
5404
- setStepOrder(target);
5405
- },
5406
- redirect: (target) => () => {
5407
- redirect("https://www.google.com");
5408
- },
5409
- log: (target) => () => {
5410
- console.log("target:", target);
5411
- },
5412
5490
  stepIsValid: (stepName) => {
5413
5491
  return steps[stepName].valid && steps[stepName].errorCount === 0;
5414
5492
  },
5415
5493
  stepIsEnabled: (stepName) => {
5416
- if (!stepOrder.value.length) {
5494
+ if (!enabledSteps().length) {
5417
5495
  return true;
5418
5496
  }
5419
- return stepOrder.value.indexOf(stepName) > -1;
5497
+ return enabledSteps().indexOf(stepName) > -1;
5420
5498
  },
5421
- submit: (postUrl, redirectUrl = null) => async (formData, node) => {
5499
+ inputIsEnabled: (node, key, inputName) => {
5500
+ if (!node || !key || !node.attrs.inputMap) {
5501
+ return true;
5502
+ }
5503
+ if (node.attrs.inputMap[key].indexOf(inputName) < 0) {
5504
+ return false;
5505
+ }
5506
+ return true;
5507
+ },
5508
+ getRedirect: (formData, node) => {
5509
+ if (!node || !node.props.attrs.redirectMap) {
5510
+ return;
5511
+ }
5512
+ return keyValOverlap(formData, node.props.attrs.redirectMap, false);
5513
+ },
5514
+ submit: (postUrl, prepData2 = null, redirectUrl = null) => async (formData, node) => {
5515
+ if (prepData2 && prepData2 != "null") {
5516
+ if (!(prepData2 instanceof Function)) {
5517
+ throw "prepData must be a function";
5518
+ }
5519
+ formData = prepData2(formData);
5520
+ }
5521
+ let abort = false;
5422
5522
  try {
5423
5523
  const res = await postJSON(postUrl, formData);
5424
5524
  node.clearErrors();
5425
- alert("Submitted successfully!");
5426
5525
  } catch (err) {
5427
- console.error(err);
5428
- node.setErrors(err.formErrors, err.fieldErrors);
5526
+ abort = handleSubmitError(err, node);
5527
+ }
5528
+ if (abort) {
5529
+ return;
5429
5530
  }
5430
- if (redirectUrl) {
5531
+ if (redirectUrl instanceof Function) {
5532
+ redirectUrl = redirectUrl(formData, node);
5533
+ }
5534
+ if (redirectUrl && redirectUrl !== "null") {
5431
5535
  if (formData) {
5432
5536
  redirectUrl = strSubUrl(redirectUrl, formData);
5433
5537
  }
@@ -5445,7 +5549,14 @@ const _sfc_main = /* @__PURE__ */ Object.assign(__default__, {
5445
5549
  },
5446
5550
  setup(__props) {
5447
5551
  const props2 = __props;
5448
- const mergedData = reactive(Object.assign({}, dataDefaults, props2.data));
5552
+ const meta = {};
5553
+ for (var node of props2.schema) {
5554
+ if (!node.type || node.type !== "meta") {
5555
+ continue;
5556
+ }
5557
+ Object.assign(meta, node.data || {});
5558
+ }
5559
+ const mergedData = reactive(Object.assign({}, dataDefaults, { meta }, props2.data));
5449
5560
  console.debug("FormKitSchema data:", mergedData);
5450
5561
  return (_ctx, _cache) => {
5451
5562
  const _component_FormKitSchema = resolveComponent("FormKitSchema");
@@ -10509,6 +10620,58 @@ function G(t2, o2) {
10509
10620
  function F(t2, o2, e2) {
10510
10621
  return { location: t2, current: o2, previous: e2 };
10511
10622
  }
10623
+ const EXPERIMENT_KEY = "__form_experiments";
10624
+ function chooseVariant(exp) {
10625
+ let variant = null, active = {}, fromCache = false;
10626
+ active = C(EXPERIMENT_KEY) || {};
10627
+ if (!exp.noCache && active && active[exp.name]) {
10628
+ variant = active[exp.name];
10629
+ fromCache = true;
10630
+ } else {
10631
+ const vs = exp.variants;
10632
+ variant = vs[Math.floor(Math.random() * vs.length)];
10633
+ active[exp.name] = variant;
10634
+ L(EXPERIMENT_KEY, active);
10635
+ }
10636
+ console.debug("Chose variant:", variant, "fromCache:", fromCache);
10637
+ return { variant, fromCache };
10638
+ }
10639
+ async function schemaFromUrl(url3) {
10640
+ console.debug("Fetching:", url3);
10641
+ const res = await fetch(url3);
10642
+ schemaObj = await res.json();
10643
+ console.debug("Got schema:", schemaObj);
10644
+ return schemaObj;
10645
+ }
10646
+ const flattenObj = (obj) => {
10647
+ const flattened = {};
10648
+ Object.keys(obj).forEach((key) => {
10649
+ const value = obj[key];
10650
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) {
10651
+ Object.assign(flattened, flattenObj(value));
10652
+ } else {
10653
+ flattened[key] = value;
10654
+ }
10655
+ });
10656
+ return flattened;
10657
+ };
10658
+ function prepData(formData) {
10659
+ const props2 = flattenObj(formData);
10660
+ props2.vid = "";
10661
+ props2.sid = "";
10662
+ props2.cid = "";
10663
+ if (typeof window.zar !== "undefined") {
10664
+ props2.vid = window.zar.getVID();
10665
+ props2.sid = window.zar.getSID();
10666
+ props2.cid = window.zar.getCID();
10667
+ }
10668
+ const data = {
10669
+ post_source: window.location.hostname,
10670
+ vertical: props2.vertical,
10671
+ properties: props2
10672
+ };
10673
+ return data;
10674
+ }
10512
10675
  const textClassification = {
10513
10676
  label: "block mb-1 font-bold text-sm formkit-invalid:text-red-500",
10514
10677
  inner: `
@@ -10532,7 +10695,7 @@ const boxClassification = {
10532
10695
  };
10533
10696
  const buttonClassification = {
10534
10697
  wrapper: "mb-1",
10535
- input: "bg-blue-500 hover:bg-blue-700 text-white text-sm font-normal py-3 px-5 rounded"
10698
+ input: "bg-red-500 hover:bg-blue-700 text-white text-lg font-normal py-3 px-5 rounded"
10536
10699
  };
10537
10700
  var theme = {
10538
10701
  global: {
@@ -10581,48 +10744,31 @@ var theme = {
10581
10744
  week: textClassification
10582
10745
  };
10583
10746
  var index = "";
10584
- const EXPERIMENT_KEY = "__form_experiments";
10585
10747
  const classes = generateClasses(theme);
10586
10748
  const forms = window.bhlForms || [];
10587
10749
  const apps = {};
10588
- function chooseVariant(exp) {
10589
- let variant = null, active = {}, fromCache = false;
10590
- active = C(EXPERIMENT_KEY) || {};
10591
- if (!exp.noCache && active && active[exp.name]) {
10592
- variant = active[exp.name];
10593
- fromCache = true;
10594
- } else {
10595
- const vs = exp.variants;
10596
- variant = vs[Math.floor(Math.random() * vs.length)];
10597
- active[exp.name] = variant;
10598
- L(EXPERIMENT_KEY, active);
10599
- }
10600
- console.debug("Chose variant:", variant, "fromCache:", fromCache);
10601
- return { variant, fromCache };
10602
- }
10603
10750
  forms.forEach(async function(form2) {
10604
10751
  console.debug("Mounting form:", form2);
10605
- if (form2.schema && form2.schemaExperiment) {
10606
- throw Error("Only one of schema and schemaExperiment allowed");
10752
+ if (form2.schema && form2.experiment) {
10753
+ throw Error("Only one of schema and experiment allowed");
10607
10754
  }
10608
10755
  let schema;
10609
10756
  if (form2.schema) {
10610
10757
  schema = form2.schema;
10611
- } else if (form2.schemaExperiment) {
10612
- const res = chooseVariant(form2.schemaExperiment);
10758
+ } else if (form2.experiment) {
10759
+ const res = chooseVariant(form2.experiment);
10613
10760
  schema = res.variant.schema;
10614
10761
  if (form2.experimentCallback) {
10615
10762
  experimentCallback(form2, res.variant, res.fromCache);
10616
10763
  }
10617
10764
  }
10618
- let schemaObj = schema;
10765
+ let schemaObj2 = schema;
10619
10766
  if (typeof schema === "string") {
10620
- console.debug("Fetching:", schema);
10621
- const res = await fetch(schema);
10622
- schemaObj = await res.json();
10623
- console.debug("Got schema:", schemaObj);
10767
+ schemaObj2 = await schemaFromUrl(schema);
10624
10768
  }
10625
- const app = createApp(_sfc_main, { schema: schemaObj }).use(plugin$1, defaultConfig({
10769
+ const data = form2.data || {};
10770
+ data.prepData = data.prepData || prepData;
10771
+ const app = createApp(_sfc_main, { schema: schemaObj2, data }).use(plugin$1, defaultConfig({
10626
10772
  config: {
10627
10773
  classes
10628
10774
  }