@marktiderman/genesis-forms 0.4.1 → 0.5.0
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 +89 -5
- package/dist/destinations.cjs +92 -4
- package/dist/destinations.cjs.map +1 -1
- package/dist/destinations.d.cts +1 -1
- package/dist/destinations.d.ts +1 -1
- package/dist/destinations.js +92 -4
- package/dist/destinations.js.map +1 -1
- package/dist/{engine-Dz9J5ej2.d.ts → engine-BDq0XJ21.d.cts} +25 -2
- package/dist/{engine-BkNuzlna.d.cts → engine-Qzp6bX6O.d.ts} +25 -2
- package/dist/index.cjs +383 -59
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +121 -76
- package/dist/index.d.ts +121 -76
- package/dist/index.js +360 -60
- package/dist/index.js.map +1 -1
- package/dist/server.cjs +387 -62
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +39 -5
- package/dist/server.d.ts +39 -5
- package/dist/server.js +385 -63
- package/dist/server.js.map +1 -1
- package/dist/testing.cjs +386 -61
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +4 -4
- package/dist/testing.d.ts +4 -4
- package/dist/testing.js +386 -61
- package/dist/testing.js.map +1 -1
- package/dist/{types-BBKBQ8sp.d.cts → types-BhYUbLJ-.d.cts} +21 -1
- package/dist/{types-BBKBQ8sp.d.ts → types-BhYUbLJ-.d.ts} +21 -1
- package/dist/validate-Bs1lyoOl.d.ts +131 -0
- package/dist/validate-BsZ0YTQS.d.cts +131 -0
- package/package.json +1 -1
- package/dist/validate-BXXqi0fq.d.cts +0 -30
- package/dist/validate-BjNwF1UE.d.ts +0 -30
package/dist/destinations.d.cts
CHANGED
package/dist/destinations.d.ts
CHANGED
package/dist/destinations.js
CHANGED
|
@@ -326,6 +326,79 @@ var structuredFieldTypes = [
|
|
|
326
326
|
}
|
|
327
327
|
];
|
|
328
328
|
|
|
329
|
+
// src/photo.ts
|
|
330
|
+
var PHOTO_TYPE = "photo";
|
|
331
|
+
var PHOTO_FORMATS = {
|
|
332
|
+
jpeg: ["image/jpeg"],
|
|
333
|
+
png: ["image/png"],
|
|
334
|
+
heic: ["image/heic", "image/heif"],
|
|
335
|
+
webp: ["image/webp"]
|
|
336
|
+
};
|
|
337
|
+
var FORMAT_NAMES = { jpeg: "JPEG", png: "PNG", heic: "HEIC", webp: "WebP" };
|
|
338
|
+
var ALL_FORMATS = Object.keys(PHOTO_FORMATS);
|
|
339
|
+
var DEFAULT_PHOTO_FILES = 3;
|
|
340
|
+
var MAX_PHOTO_FILES = 5;
|
|
341
|
+
var DEFAULT_PHOTO_SIZE_MB = 10;
|
|
342
|
+
var MAX_PHOTO_SIZE_MB = 25;
|
|
343
|
+
var MAX_PHOTO_ID_LENGTH = 200;
|
|
344
|
+
var MAX_PHOTO_NAME_LENGTH = 255;
|
|
345
|
+
var wholeIn = (v, min, max) => typeof v === "number" && Number.isInteger(v) && v >= min && v <= max;
|
|
346
|
+
function photoLimits(field) {
|
|
347
|
+
const maxFiles = wholeIn(field.props?.maxFiles, 1, MAX_PHOTO_FILES) ? field.props.maxFiles : DEFAULT_PHOTO_FILES;
|
|
348
|
+
const maxSizeMb = wholeIn(field.props?.maxSizeMb, 1, MAX_PHOTO_SIZE_MB) ? field.props.maxSizeMb : DEFAULT_PHOTO_SIZE_MB;
|
|
349
|
+
const raw = field.props?.formats;
|
|
350
|
+
const picked = Array.isArray(raw) ? ALL_FORMATS.filter((f) => raw.includes(f)) : [];
|
|
351
|
+
const formats = picked.length ? picked : [...ALL_FORMATS];
|
|
352
|
+
return {
|
|
353
|
+
maxFiles,
|
|
354
|
+
maxSizeMb,
|
|
355
|
+
maxBytes: maxSizeMb * 1024 * 1024,
|
|
356
|
+
formats,
|
|
357
|
+
mimeTypes: formats.flatMap((f) => PHOTO_FORMATS[f])
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
function isPhotoRef(v) {
|
|
361
|
+
if (!v || typeof v !== "object" || Array.isArray(v)) return false;
|
|
362
|
+
const r = v;
|
|
363
|
+
return typeof r.id === "string" && r.id.length > 0 && r.id.length <= MAX_PHOTO_ID_LENGTH && typeof r.name === "string" && r.name.length <= MAX_PHOTO_NAME_LENGTH && typeof r.type === "string" && typeof r.size === "number" && Number.isInteger(r.size) && r.size > 0;
|
|
364
|
+
}
|
|
365
|
+
function photoRefs(value) {
|
|
366
|
+
if (!Array.isArray(value)) return [];
|
|
367
|
+
const refs = [];
|
|
368
|
+
for (const r of value) if (isPhotoRef(r)) refs.push({ id: r.id, name: r.name, type: r.type, size: r.size });
|
|
369
|
+
return refs;
|
|
370
|
+
}
|
|
371
|
+
var plural2 = (n, one, many = `${one}s`) => `${n} ${n === 1 ? one : many}`;
|
|
372
|
+
function photoFormatList(formats) {
|
|
373
|
+
const names = formats.map((f) => FORMAT_NAMES[f]);
|
|
374
|
+
return names.length > 1 ? `${names.slice(0, -1).join(", ")} or ${names[names.length - 1]}` : names[0] ?? "";
|
|
375
|
+
}
|
|
376
|
+
var photoTypeMessage = (field) => `Use a ${photoFormatList(photoLimits(field).formats)} photo.`;
|
|
377
|
+
var photoSizeMessage = (field) => `Each photo must be ${photoLimits(field).maxSizeMb} MB or smaller.`;
|
|
378
|
+
var photoCountMessage = (field) => `Add at most ${plural2(photoLimits(field).maxFiles, "photo")}.`;
|
|
379
|
+
var photoFieldType = {
|
|
380
|
+
type: PHOTO_TYPE,
|
|
381
|
+
label: "Photo",
|
|
382
|
+
category: "media",
|
|
383
|
+
value: { json: true },
|
|
384
|
+
operators: ["answered", "empty"],
|
|
385
|
+
a11y: { semantics: "group" },
|
|
386
|
+
isEmpty: (value) => value === void 0 || value === null || Array.isArray(value) && value.length === 0,
|
|
387
|
+
validate: (value, field) => {
|
|
388
|
+
if (!Array.isArray(value) || !value.every(isPhotoRef)) return "Add a photo.";
|
|
389
|
+
const limits = photoLimits(field);
|
|
390
|
+
if (value.length > limits.maxFiles) return photoCountMessage(field);
|
|
391
|
+
const refs = value;
|
|
392
|
+
if (new Set(refs.map((r) => r.id)).size !== refs.length) return "Each photo can be added once.";
|
|
393
|
+
if (refs.some((r) => !limits.mimeTypes.includes(r.type.toLowerCase()))) return photoTypeMessage(field);
|
|
394
|
+
if (refs.some((r) => r.size > limits.maxBytes)) return photoSizeMessage(field);
|
|
395
|
+
return null;
|
|
396
|
+
},
|
|
397
|
+
normalize: (value) => Array.isArray(value) && value.every(isPhotoRef) ? photoRefs(value) : value,
|
|
398
|
+
summarize: (value) => photoRefs(value).map((r) => r.name || "Photo").join(", "),
|
|
399
|
+
samples: () => [[{ id: "sample-photo", name: "photo.jpg", type: "image/jpeg", size: 1024 }]]
|
|
400
|
+
};
|
|
401
|
+
|
|
329
402
|
// src/fields.ts
|
|
330
403
|
var REGISTRY = /* @__PURE__ */ Symbol.for("@marktiderman/genesis-forms/field-types");
|
|
331
404
|
var globalScope = globalThis;
|
|
@@ -361,6 +434,20 @@ function summarizeValue(value, field) {
|
|
|
361
434
|
if (Array.isArray(value)) return value.join(", ");
|
|
362
435
|
return String(value);
|
|
363
436
|
}
|
|
437
|
+
var OTHER_MAX_LENGTH = 200;
|
|
438
|
+
function otherOption(field) {
|
|
439
|
+
const other = field.props?.other;
|
|
440
|
+
if (other === true) return { label: "Other" };
|
|
441
|
+
if (other && typeof other === "object" && !Array.isArray(other)) {
|
|
442
|
+
const label = typeof other.label === "string" && other.label.trim() ? other.label.trim() : "Other";
|
|
443
|
+
return { label };
|
|
444
|
+
}
|
|
445
|
+
return null;
|
|
446
|
+
}
|
|
447
|
+
function isOtherValue(field, value) {
|
|
448
|
+
return otherOption(field) !== null && typeof value === "string" && !choiceOptions(field).some((o) => o.value === value);
|
|
449
|
+
}
|
|
450
|
+
var typedOther = (field, value) => isOtherValue(field, value) && value.trim() !== "" && value.length <= OTHER_MAX_LENGTH;
|
|
364
451
|
function choiceOptions(field) {
|
|
365
452
|
const raw = field.props?.options;
|
|
366
453
|
if (!Array.isArray(raw)) return [];
|
|
@@ -486,7 +573,7 @@ var builtins = [
|
|
|
486
573
|
value: { json: true },
|
|
487
574
|
operators: ["eq", "neq", "in", "answered", "empty"],
|
|
488
575
|
a11y: { semantics: "group" },
|
|
489
|
-
validate: (value, field) => typeof value === "string" && choiceOptions(field).some((o) => o.value === value) ? null : "Choose one of the options.",
|
|
576
|
+
validate: (value, field) => typeof value === "string" && (choiceOptions(field).some((o) => o.value === value) || typedOther(field, value)) ? null : "Choose one of the options.",
|
|
490
577
|
summarize: (value, field) => optionLabel(field, String(value))
|
|
491
578
|
},
|
|
492
579
|
{
|
|
@@ -498,7 +585,8 @@ var builtins = [
|
|
|
498
585
|
a11y: { semantics: "group" },
|
|
499
586
|
validate: (value, field) => {
|
|
500
587
|
const allowed = new Set(choiceOptions(field).map((o) => o.value));
|
|
501
|
-
|
|
588
|
+
const others = Array.isArray(value) ? value.filter((v) => typeof v === "string" && !allowed.has(v)) : [];
|
|
589
|
+
return Array.isArray(value) && new Set(value).size === value.length && value.every((v) => typeof v === "string") && (others.length === 0 || others.length === 1 && typedOther(field, others[0])) ? null : "Choose from the options.";
|
|
502
590
|
},
|
|
503
591
|
summarize: (value, field) => Array.isArray(value) ? value.map((v) => optionLabel(field, String(v))).join(", ") : String(value)
|
|
504
592
|
},
|
|
@@ -519,7 +607,7 @@ var builtins = [
|
|
|
519
607
|
value: { json: true },
|
|
520
608
|
operators: ["eq", "neq", "in", "answered", "empty"],
|
|
521
609
|
a11y: { semantics: "control" },
|
|
522
|
-
validate: (value, field) => typeof value === "string" && choiceOptions(field).some((o) => o.value === value) ? null : "Choose one of the options.",
|
|
610
|
+
validate: (value, field) => typeof value === "string" && (choiceOptions(field).some((o) => o.value === value) || typedOther(field, value)) ? null : "Choose one of the options.",
|
|
523
611
|
summarize: (value, field) => optionLabel(field, String(value))
|
|
524
612
|
},
|
|
525
613
|
{
|
|
@@ -626,7 +714,7 @@ function dateLimits(field) {
|
|
|
626
714
|
if (typeof max === "string" && isIsoDate(max)) out.max = max;
|
|
627
715
|
return out;
|
|
628
716
|
}
|
|
629
|
-
for (const manifest of [...builtins, ...structuredFieldTypes, calculatedFieldType]) registerFieldType(manifest);
|
|
717
|
+
for (const manifest of [...builtins, ...structuredFieldTypes, calculatedFieldType, photoFieldType]) registerFieldType(manifest);
|
|
630
718
|
|
|
631
719
|
// src/logic.ts
|
|
632
720
|
function own(record, key) {
|