udp-stencil-component-library 26.9.0-beta.0 → 26.9.0-beta.2
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/dist/cjs/{base-map_4.cjs.entry.js → base-map_3.cjs.entry.js} +0 -59
- package/dist/cjs/{codecs-CzM31cMq.js → codecs-ClSB_OaD.js} +156 -63
- package/dist/cjs/form-metadata-display_2.cjs.entry.js +105 -0
- package/dist/cjs/{form-metadata-display_9.cjs.entry.js → image-upload_8.cjs.entry.js} +68 -62
- package/dist/cjs/index-CZB9dMeB.js +22 -46
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/slot-index-Dzl7Zum5.js +77 -0
- package/dist/cjs/stencil-library.cjs.js +1 -1
- package/dist/cjs/{udp-container-query_2.cjs.entry.js → udp-container-query-grid.cjs.entry.js} +0 -33
- package/dist/cjs/udp-container-query.cjs.entry.js +37 -0
- package/dist/cjs/udp-detail-list_9.cjs.entry.js +2286 -0
- package/dist/cjs/udp-fluent-inline-edit_5.cjs.entry.js +299 -77
- package/dist/cjs/udp-question-form-builder.cjs.entry.js +1 -1
- package/dist/collection/components/forms/udp-question-form/core/slot-index.js +32 -0
- package/dist/collection/components/forms/udp-question-form/renderer/runtime/codecs.js +140 -64
- package/dist/collection/components/forms/udp-question-form/renderer/runtime/parse.js +14 -2
- package/dist/collection/components/forms/udp-question-form/renderer/runtime/types.js +17 -0
- package/dist/collection/components/forms/udp-question-form/renderer/udp-question-form-renderer.js +259 -23
- package/dist/collection/components/forms/udp-question-form/renderer/ui/adapters/udp-question-tally-adapter.js +3 -3
- package/dist/collection/components/forms/udp-question-form/renderer/ui/form-shell.js +3 -2
- package/dist/collection/components/forms/udp-question-form/renderer/ui/question-renderer.js +17 -4
- package/dist/collection/components/forms/udp-question-form/renderer/ui/question-view-renderer.js +6 -1
- package/dist/collection/components/forms/udp-question-form/renderer/ui/section-card.js +4 -2
- package/dist/collection/components/inputs/location-input/build-static-map-url.js +19 -0
- package/dist/collection/components/inputs/location-input/location-input.js +19 -20
- package/dist/collection/components/inputs/location-input/resolve-display-location.js +29 -0
- package/dist/components/location-input2.js +1 -1
- package/dist/components/udp-detail-list-item.js +1 -1
- package/dist/components/udp-detail-list-item2.js +1 -0
- package/dist/components/udp-detail-list.js +1 -1
- package/dist/components/udp-detail-list2.js +1 -0
- package/dist/components/udp-fluent-file-input.js +1 -1
- package/dist/components/udp-fluent-file-input2.js +1 -0
- package/dist/components/udp-fluent-image.js +1 -1
- package/dist/components/udp-fluent-image2.js +1 -0
- package/dist/components/udp-fluent-list-input.js +1 -1
- package/dist/components/udp-fluent-list-input2.js +1 -0
- package/dist/components/udp-fluent-location-input.js +1 -1
- package/dist/components/udp-fluent-location-input2.js +1 -0
- package/dist/components/udp-fluent-signature-input.js +1 -1
- package/dist/components/udp-fluent-signature-input2.js +1 -0
- package/dist/components/udp-fluent-table-input.js +1 -1
- package/dist/components/udp-fluent-table-input2.js +1 -0
- package/dist/components/udp-question-form-builder.js +1 -1
- package/dist/components/udp-question-form-renderer2.js +1 -1
- package/dist/components/udp-question-tally-adapter.js +1 -1
- package/dist/components/udp-question-tally-adapter2.js +1 -0
- package/dist/docs.json +657 -43
- package/dist/esm/{base-map_4.entry.js → base-map_3.entry.js} +1 -59
- package/dist/esm/{codecs-bR6Ih0TV.js → codecs-CI_fHfY1.js} +156 -63
- package/dist/esm/form-metadata-display_2.entry.js +102 -0
- package/dist/esm/{form-metadata-display_9.entry.js → image-upload_8.entry.js} +70 -63
- package/dist/esm/index-15aY63VA.js +22 -46
- package/dist/esm/loader.js +1 -1
- package/dist/esm/slot-index-aYrr8BJl.js +74 -0
- package/dist/esm/stencil-library.js +1 -1
- package/dist/esm/{udp-container-query_2.entry.js → udp-container-query-grid.entry.js} +1 -33
- package/dist/esm/udp-container-query.entry.js +35 -0
- package/dist/esm/udp-detail-list_9.entry.js +2269 -0
- package/dist/esm/udp-fluent-inline-edit_5.entry.js +298 -76
- package/dist/esm/udp-question-form-builder.entry.js +1 -1
- package/dist/stencil-library/{base-map_4.entry.js → base-map_3.entry.js} +1 -1
- package/dist/stencil-library/codecs-CI_fHfY1.js +1 -0
- package/dist/stencil-library/form-metadata-display_2.entry.js +1 -0
- package/dist/stencil-library/image-upload_8.entry.js +1 -0
- package/dist/stencil-library/slot-index-aYrr8BJl.js +1 -0
- package/dist/stencil-library/stencil-library.esm.js +1 -1
- package/dist/stencil-library/udp-container-query-grid.entry.js +1 -0
- package/dist/stencil-library/udp-container-query.entry.js +1 -0
- package/dist/stencil-library/udp-detail-list_9.entry.js +1 -0
- package/dist/stencil-library/udp-fluent-inline-edit_5.entry.js +1 -1
- package/dist/stencil-library/udp-question-form-builder.entry.js +1 -1
- package/dist/types/components/forms/udp-question-form/core/slot-index.d.ts +19 -6
- package/dist/types/components/forms/udp-question-form/renderer/runtime/codecs.d.ts +11 -7
- package/dist/types/components/forms/udp-question-form/renderer/runtime/types.d.ts +19 -3
- package/dist/types/components/forms/udp-question-form/renderer/udp-question-form-renderer.d.ts +99 -7
- package/dist/types/components/forms/udp-question-form/renderer/ui/form-shell.d.ts +13 -0
- package/dist/types/components/forms/udp-question-form/renderer/ui/question-renderer.d.ts +8 -0
- package/dist/types/components/inputs/location-input/build-static-map-url.d.ts +20 -0
- package/dist/types/components/inputs/location-input/resolve-display-location.d.ts +15 -0
- package/package.json +1 -1
- package/dist/cjs/udp-detail-list-item.cjs.entry.js +0 -41
- package/dist/cjs/udp-detail-list.cjs.entry.js +0 -152
- package/dist/cjs/udp-fluent-file-input.cjs.entry.js +0 -632
- package/dist/cjs/udp-fluent-image.cjs.entry.js +0 -27
- package/dist/cjs/udp-fluent-list-input.cjs.entry.js +0 -46
- package/dist/cjs/udp-fluent-location-input.cjs.entry.js +0 -558
- package/dist/cjs/udp-fluent-signature-input.cjs.entry.js +0 -385
- package/dist/cjs/udp-fluent-table-input.cjs.entry.js +0 -347
- package/dist/cjs/udp-question-tally-adapter.cjs.entry.js +0 -138
- package/dist/esm/udp-detail-list-item.entry.js +0 -39
- package/dist/esm/udp-detail-list.entry.js +0 -150
- package/dist/esm/udp-fluent-file-input.entry.js +0 -630
- package/dist/esm/udp-fluent-image.entry.js +0 -25
- package/dist/esm/udp-fluent-list-input.entry.js +0 -44
- package/dist/esm/udp-fluent-location-input.entry.js +0 -550
- package/dist/esm/udp-fluent-signature-input.entry.js +0 -379
- package/dist/esm/udp-fluent-table-input.entry.js +0 -345
- package/dist/esm/udp-question-tally-adapter.entry.js +0 -136
- package/dist/stencil-library/codecs-bR6Ih0TV.js +0 -1
- package/dist/stencil-library/form-metadata-display_9.entry.js +0 -1
- package/dist/stencil-library/udp-container-query_2.entry.js +0 -1
- package/dist/stencil-library/udp-detail-list-item.entry.js +0 -1
- package/dist/stencil-library/udp-detail-list.entry.js +0 -1
- package/dist/stencil-library/udp-fluent-file-input.entry.js +0 -1
- package/dist/stencil-library/udp-fluent-image.entry.js +0 -1
- package/dist/stencil-library/udp-fluent-list-input.entry.js +0 -1
- package/dist/stencil-library/udp-fluent-location-input.entry.js +0 -1
- package/dist/stencil-library/udp-fluent-signature-input.entry.js +0 -1
- package/dist/stencil-library/udp-fluent-table-input.entry.js +0 -1
- package/dist/stencil-library/udp-question-tally-adapter.entry.js +0 -1
|
@@ -683,65 +683,6 @@ const StencilField = class {
|
|
|
683
683
|
get el() { return index.getElement(this); }
|
|
684
684
|
};
|
|
685
685
|
|
|
686
|
-
const tallyCss = () => `:host{display:block;width:100%}.tally-container{display:flex;flex-direction:column;gap:var(--spacing-02, 8px)}.tally-label{font-weight:600;margin-bottom:var(--spacing-02, 8px)}.tally-loading{display:flex;align-items:center;justify-content:center;padding:var(--spacing-04, 16px);color:var(--text-secondary, #6b7280)}.tally-content{display:flex;flex-direction:column;gap:var(--spacing-03, 12px)}.tally-stats{display:flex;gap:var(--spacing-04, 16px);flex-wrap:wrap}.tally-item{display:flex;flex-direction:column;align-items:center;padding:var(--spacing-03, 12px) var(--spacing-04, 16px);border-radius:var(--border-radius-01, 4px);border:1px solid var(--border-subtle, #e5e7eb);background-color:var(--layer-01, #ffffff);min-width:80px;flex:1;max-width:120px}.tally-item.tally-yes{border-color:var(--support-success, #42be65);background-color:var(--support-success-hover, #f6f8ff)}.tally-item.tally-no{border-color:var(--support-error, #da1e28);background-color:var(--support-error-hover, #fff1f1)}.tally-item.tally-unanswered{border-color:var(--support-warning, #f1c21b);background-color:var(--support-warning-hover, #fcf4d6)}.tally-count{font-weight:700;line-height:1.2;margin-bottom:var(--spacing-01, 4px)}.tally-yes .tally-count{color:var(--support-success, #42be65)}.tally-no .tally-count{color:var(--support-error, #da1e28)}.tally-unanswered .tally-count{color:var(--support-warning, #f1c21b)}.tally-item .tally-label{margin:0;font-weight:500;text-transform:uppercase;font-size:0.75rem;letter-spacing:0.02em}.tally-summary{padding:var(--spacing-02, 8px) 0;border-top:1px solid var(--border-subtle, #e5e7eb);text-align:center}.error-message{margin-top:var(--spacing-02, 8px);padding:var(--spacing-02, 8px);border-radius:var(--border-radius-01, 4px);background-color:var(--support-error-hover, #fff1f1);border:1px solid var(--support-error, #da1e28)}:host(.udp-input--size-small) .tally-item{padding:var(--spacing-02, 8px) var(--spacing-03, 12px);min-width:60px;max-width:90px}:host(.udp-input--size-small) .tally-count{font-size:1.25rem}:host(.udp-input--size-large) .tally-item{padding:var(--spacing-04, 16px) var(--spacing-05, 20px);min-width:100px;max-width:150px}:host(.udp-input--size-large) .tally-count{font-size:2rem}:host(.udp-input--margin-none) .tally-container{gap:0}:host(.udp-input--margin-dense) .tally-container{gap:var(--spacing-01, 4px)}:host(.udp-input--margin-comfortable) .tally-container{gap:var(--spacing-04, 16px)}:host(.udp-input--disabled) .tally-item{opacity:0.5;pointer-events:none}:host(.udp-input--readonly) .tally-item{background-color:var(--field-01, #f4f4f4)}@media (max-width: 480px){.tally-stats{flex-direction:column}.tally-item{max-width:none;flex:none}}`;
|
|
687
|
-
|
|
688
|
-
const TallyDisplay = class {
|
|
689
|
-
constructor(hostRef) {
|
|
690
|
-
index.registerInstance(this, hostRef);
|
|
691
|
-
/**
|
|
692
|
-
* Label for the tally display.
|
|
693
|
-
*/
|
|
694
|
-
this.label = 'Response Tally';
|
|
695
|
-
/**
|
|
696
|
-
* Number of Yes responses.
|
|
697
|
-
*/
|
|
698
|
-
this.yesCount = 0;
|
|
699
|
-
/**
|
|
700
|
-
* Number of No responses.
|
|
701
|
-
*/
|
|
702
|
-
this.noCount = 0;
|
|
703
|
-
/**
|
|
704
|
-
* Number of Not Applicable responses.
|
|
705
|
-
*/
|
|
706
|
-
this.naCount = 0;
|
|
707
|
-
/**
|
|
708
|
-
* Total number of fields being tallied.
|
|
709
|
-
*/
|
|
710
|
-
this.totalFields = 0;
|
|
711
|
-
/**
|
|
712
|
-
* Whether the component is disabled.
|
|
713
|
-
*/
|
|
714
|
-
this.disabled = false;
|
|
715
|
-
/**
|
|
716
|
-
* Whether the component is read-only.
|
|
717
|
-
*/
|
|
718
|
-
this.readonly = false;
|
|
719
|
-
/**
|
|
720
|
-
* Size variant for the tally display.
|
|
721
|
-
*/
|
|
722
|
-
this.size = 'normal';
|
|
723
|
-
/**
|
|
724
|
-
* Margin variant for the component spacing.
|
|
725
|
-
*/
|
|
726
|
-
this.margin = 'normal';
|
|
727
|
-
}
|
|
728
|
-
render() {
|
|
729
|
-
const isError = !!this.error;
|
|
730
|
-
const answeredCount = this.yesCount + this.noCount + this.naCount;
|
|
731
|
-
const unansweredCount = this.totalFields - answeredCount;
|
|
732
|
-
return (index.h(index.Host, { key: '4e1b03c99dbe1d333b6144a232dc386b15f6053f', class: {
|
|
733
|
-
'udp-input': true,
|
|
734
|
-
'udp-input--error': isError,
|
|
735
|
-
'udp-input--disabled': this.disabled,
|
|
736
|
-
'udp-input--readonly': this.readonly,
|
|
737
|
-
[`udp-input--size-${this.size}`]: true,
|
|
738
|
-
[`udp-input--margin-${this.margin}`]: true,
|
|
739
|
-
} }, index.h("div", { key: '55d69a511e24a845ae28c3ffb05a6b564f1fbbdf', class: "tally-container" }, this.label && (index.h("unity-typography", { key: '30439676a573ad086d2280974106be9f683bc808', variant: "caption-text" }, index.h("label", { key: '7e39f59eb0fcdd5e0f35f0de36b80bae4d199e8c', htmlFor: this.id, class: "tally-label" }, this.label))), index.h("div", { key: '40ecef47645a053be156a17c50f0ed4a3e2c2d2e', class: "tally-content", id: this.id }, index.h("div", { key: '34808d7cd994a1888bd0b825fae1634ad730ebb8', class: "tally-stats" }, index.h("div", { key: '0e49084939f51ff2dd72221d0f89987b80bc5399', class: "tally-item tally-yes" }, index.h("unity-typography", { key: '81bb681a92294513faf31275cd4e569ffa8a15fa', variant: "h4", class: "tally-count" }, this.yesCount), index.h("unity-typography", { key: '9440146b8adcc4cf9da3c2e3eea229703e0284dc', variant: "caption-text", class: "tally-label" }, "Yes")), index.h("div", { key: '453033c26001d2683181a91e0ebec682ad5d4d38', class: "tally-item tally-no" }, index.h("unity-typography", { key: 'c840b3783bdc163242f4e18c784e0b489fd4c301', variant: "h4", class: "tally-count" }, this.noCount), index.h("unity-typography", { key: '0af346f74b0e574e99efa717f111b18375bd15dd', variant: "caption-text", class: "tally-label" }, "No")), index.h("div", { key: '8a9355d09c683110350f62dd24af0aa404b23c87', class: "tally-item tally-na" }, index.h("unity-typography", { key: '9bb906130f240bf423c6c4920c75b8f9890647b1', variant: "h4", class: "tally-count" }, this.naCount), index.h("unity-typography", { key: '7c51faeeb2c29a7c2e936efaec66677ab50d67b0', variant: "caption-text", class: "tally-label" }, "Not Applicable")), unansweredCount > 0 && (index.h("div", { key: '225d3f0d49da9f15eeae6c3829d7105d0d80c560', class: "tally-item tally-unanswered" }, index.h("unity-typography", { key: 'f167b42959297823e1ffa199be60b558a520d922', variant: "h4", class: "tally-count" }, unansweredCount), index.h("unity-typography", { key: 'de96f235c61bbdd1eb4a4a102a2c80513c543dba', variant: "caption-text", class: "tally-label" }, "Unanswered")))), index.h("div", { key: 'f2abf82180e67933ed34e1d102581c036c7d2614', class: "tally-summary" }, index.h("unity-typography", { key: '7becceb75df4182f6d477b2aa14e8e5464e4534e', variant: "caption-text" }, "Total Questions: ", this.totalFields))), isError && (index.h("div", { key: '56f57a775f1cde86c97e55d1bd4eeb7c2b0b0db7', class: "error-message" }, index.h("unity-typography", { key: 'ef3370bdd1d122fdc9df92fcd990e064989da81e', variant: "caption-text", color: "error" }, this.error))))));
|
|
740
|
-
}
|
|
741
|
-
};
|
|
742
|
-
TallyDisplay.style = tallyCss();
|
|
743
|
-
|
|
744
686
|
exports.base_map = BaseMap;
|
|
745
687
|
exports.selectable_list = SelectableList;
|
|
746
688
|
exports.stencil_field = StencilField;
|
|
747
|
-
exports.tally_display = TallyDisplay;
|
|
@@ -1940,6 +1940,23 @@ function getDriveFileId(file) {
|
|
|
1940
1940
|
const id = file.driveFileId;
|
|
1941
1941
|
return typeof id === 'string' && id.length > 0 ? id : null;
|
|
1942
1942
|
}
|
|
1943
|
+
/**
|
|
1944
|
+
* Tag a legacy (pre-v2, non-JSON) Location wire value onto a decoded value so
|
|
1945
|
+
* an unedited re-save can round-trip it byte-for-byte — same trick as
|
|
1946
|
+
* `driveFileId` above, an extra runtime-only property rather than a field on
|
|
1947
|
+
* the component's public `FluentLocationValue` type. Cleared automatically
|
|
1948
|
+
* the moment the user picks a new location, since `udp-fluent-location-input`
|
|
1949
|
+
* always emits a fresh plain object with only the canonical value keys.
|
|
1950
|
+
*/
|
|
1951
|
+
function tagLegacyLocationToken(value, token) {
|
|
1952
|
+
value.legacyValueToken = token;
|
|
1953
|
+
return value;
|
|
1954
|
+
}
|
|
1955
|
+
/** Reads the tag set by `tagLegacyLocationToken`. */
|
|
1956
|
+
function getLegacyLocationToken(value) {
|
|
1957
|
+
const token = value === null || value === void 0 ? void 0 : value.legacyValueToken;
|
|
1958
|
+
return typeof token === 'string' && token.length > 0 ? token : null;
|
|
1959
|
+
}
|
|
1943
1960
|
exports.SubmissionStatus = void 0;
|
|
1944
1961
|
(function (SubmissionStatus) {
|
|
1945
1962
|
SubmissionStatus[SubmissionStatus["InProgress"] = 1] = "InProgress";
|
|
@@ -1991,48 +2008,64 @@ const multiSelectCodec = {
|
|
|
1991
2008
|
},
|
|
1992
2009
|
encode: value => (value == null || value.length === 0 ? '' : value.join(',')),
|
|
1993
2010
|
};
|
|
2011
|
+
function buildAddressDetailFromFlat(flat) {
|
|
2012
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
2013
|
+
const freeform = (_a = flat.address) !== null && _a !== void 0 ? _a : '';
|
|
2014
|
+
const hasAddress = freeform.length > 0 ||
|
|
2015
|
+
flat.streetNumber != null ||
|
|
2016
|
+
flat.streetName != null ||
|
|
2017
|
+
flat.municipality != null ||
|
|
2018
|
+
flat.countrySubdivisionName != null ||
|
|
2019
|
+
flat.postalCode != null ||
|
|
2020
|
+
flat.country != null;
|
|
2021
|
+
if (!hasAddress)
|
|
2022
|
+
return null;
|
|
2023
|
+
return {
|
|
2024
|
+
freeformAddress: freeform,
|
|
2025
|
+
streetNumber: (_b = flat.streetNumber) !== null && _b !== void 0 ? _b : undefined,
|
|
2026
|
+
streetName: (_c = flat.streetName) !== null && _c !== void 0 ? _c : undefined,
|
|
2027
|
+
municipality: (_d = flat.municipality) !== null && _d !== void 0 ? _d : undefined,
|
|
2028
|
+
countrySubdivisionName: (_e = flat.countrySubdivisionName) !== null && _e !== void 0 ? _e : undefined,
|
|
2029
|
+
postalCode: (_f = flat.postalCode) !== null && _f !== void 0 ? _f : undefined,
|
|
2030
|
+
country: (_g = flat.country) !== null && _g !== void 0 ? _g : undefined,
|
|
2031
|
+
};
|
|
2032
|
+
}
|
|
1994
2033
|
const locationCodec = {
|
|
1995
2034
|
decode: wire => {
|
|
1996
|
-
var _a, _b, _c
|
|
2035
|
+
var _a, _b, _c;
|
|
1997
2036
|
if (wire == null || wire === '')
|
|
1998
2037
|
return null;
|
|
1999
2038
|
let parsed;
|
|
2000
2039
|
try {
|
|
2001
2040
|
parsed = JSON.parse(wire);
|
|
2002
2041
|
}
|
|
2003
|
-
catch (
|
|
2004
|
-
|
|
2042
|
+
catch (_d) {
|
|
2043
|
+
// Not v2 JSON — a v1 map-screenshot file token. Tag it so `encode` can
|
|
2044
|
+
// round-trip it byte-for-byte if the user never edits this field;
|
|
2045
|
+
// `hydrateValueWithMetadata()` fills in real lat/lng/address from
|
|
2046
|
+
// `metadata.location`.
|
|
2047
|
+
const shell = {
|
|
2048
|
+
latitude: null,
|
|
2049
|
+
longitude: null,
|
|
2050
|
+
address: null,
|
|
2051
|
+
timestamp: null,
|
|
2052
|
+
};
|
|
2053
|
+
return tagLegacyLocationToken(shell, wire);
|
|
2005
2054
|
}
|
|
2006
|
-
const freeform = (_a = parsed.address) !== null && _a !== void 0 ? _a : '';
|
|
2007
|
-
const hasAddress = freeform.length > 0 ||
|
|
2008
|
-
parsed.streetNumber != null ||
|
|
2009
|
-
parsed.streetName != null ||
|
|
2010
|
-
parsed.municipality != null ||
|
|
2011
|
-
parsed.countrySubdivisionName != null ||
|
|
2012
|
-
parsed.postalCode != null ||
|
|
2013
|
-
parsed.country != null;
|
|
2014
|
-
const address = hasAddress
|
|
2015
|
-
? {
|
|
2016
|
-
freeformAddress: freeform,
|
|
2017
|
-
streetNumber: parsed.streetNumber,
|
|
2018
|
-
streetName: parsed.streetName,
|
|
2019
|
-
municipality: parsed.municipality,
|
|
2020
|
-
countrySubdivisionName: parsed.countrySubdivisionName,
|
|
2021
|
-
postalCode: parsed.postalCode,
|
|
2022
|
-
country: parsed.country,
|
|
2023
|
-
}
|
|
2024
|
-
: null;
|
|
2025
2055
|
return {
|
|
2026
|
-
latitude: (
|
|
2027
|
-
longitude: (
|
|
2028
|
-
address,
|
|
2029
|
-
timestamp: (
|
|
2056
|
+
latitude: (_a = parsed.latitude) !== null && _a !== void 0 ? _a : null,
|
|
2057
|
+
longitude: (_b = parsed.longitude) !== null && _b !== void 0 ? _b : null,
|
|
2058
|
+
address: buildAddressDetailFromFlat(parsed),
|
|
2059
|
+
timestamp: (_c = parsed.timestamp) !== null && _c !== void 0 ? _c : null,
|
|
2030
2060
|
};
|
|
2031
2061
|
},
|
|
2032
2062
|
encode: value => {
|
|
2033
2063
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
2034
2064
|
if (value == null)
|
|
2035
2065
|
return '';
|
|
2066
|
+
const legacyToken = getLegacyLocationToken(value);
|
|
2067
|
+
if (legacyToken != null)
|
|
2068
|
+
return legacyToken;
|
|
2036
2069
|
if (value.latitude == null && value.longitude == null && !value.address)
|
|
2037
2070
|
return '';
|
|
2038
2071
|
const wire = {
|
|
@@ -2283,31 +2316,55 @@ function isPassOneFieldType(fieldTypeId) {
|
|
|
2283
2316
|
}
|
|
2284
2317
|
/**
|
|
2285
2318
|
* Merge metadata-sidecar fields onto the decoded value for types where the
|
|
2286
|
-
* "value" string alone isn't the full user-visible state
|
|
2287
|
-
* `Signature`
|
|
2288
|
-
*
|
|
2289
|
-
*
|
|
2319
|
+
* "value" string alone isn't the full user-visible state:
|
|
2320
|
+
* - `Signature` — `metadata.signature` carries `fullName` and the
|
|
2321
|
+
* lat/lng/timestamp captured at stroke-end.
|
|
2322
|
+
* - `Location` — a legacy (v1) answer's real lat/lng/address live in
|
|
2323
|
+
* `metadata.location`, not `.value` (see `locationCodec`'s doc comment).
|
|
2324
|
+
* Returns the value untouched for every other type.
|
|
2290
2325
|
*/
|
|
2291
2326
|
function hydrateValueWithMetadata(fieldTypeId, decoded, metadata) {
|
|
2292
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
2293
|
-
if (fieldTypeId
|
|
2327
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
2328
|
+
if (fieldTypeId === types.FieldTypeId.Signature) {
|
|
2329
|
+
const sig = (_a = metadata === null || metadata === void 0 ? void 0 : metadata.signature) !== null && _a !== void 0 ? _a : null;
|
|
2330
|
+
const baseValue = (decoded !== null && decoded !== void 0 ? decoded : null);
|
|
2331
|
+
if (!sig && !baseValue)
|
|
2332
|
+
return null;
|
|
2333
|
+
const next = {
|
|
2334
|
+
file: (_b = baseValue === null || baseValue === void 0 ? void 0 : baseValue.file) !== null && _b !== void 0 ? _b : null,
|
|
2335
|
+
fullName: (_d = (_c = sig === null || sig === void 0 ? void 0 : sig.fullName) !== null && _c !== void 0 ? _c : baseValue === null || baseValue === void 0 ? void 0 : baseValue.fullName) !== null && _d !== void 0 ? _d : null,
|
|
2336
|
+
metadata: sig != null
|
|
2337
|
+
? {
|
|
2338
|
+
timestamp: (_e = sig.timestamp) !== null && _e !== void 0 ? _e : null,
|
|
2339
|
+
latitude: (_f = sig.latitude) !== null && _f !== void 0 ? _f : null,
|
|
2340
|
+
longitude: (_g = sig.longitude) !== null && _g !== void 0 ? _g : null,
|
|
2341
|
+
}
|
|
2342
|
+
: (_h = baseValue === null || baseValue === void 0 ? void 0 : baseValue.metadata) !== null && _h !== void 0 ? _h : null,
|
|
2343
|
+
};
|
|
2344
|
+
return next;
|
|
2345
|
+
}
|
|
2346
|
+
if (fieldTypeId === types.FieldTypeId.Location) {
|
|
2347
|
+
return hydrateLocationWithMetadata(decoded, (_j = metadata === null || metadata === void 0 ? void 0 : metadata.location) !== null && _j !== void 0 ? _j : null);
|
|
2348
|
+
}
|
|
2349
|
+
return decoded;
|
|
2350
|
+
}
|
|
2351
|
+
function hydrateLocationWithMetadata(decoded, loc) {
|
|
2352
|
+
var _a, _b, _c;
|
|
2353
|
+
// A genuine v2-native decode already has real coordinates/address —
|
|
2354
|
+
// `metadata.location` in that case is legacy server-side noise, ignore it.
|
|
2355
|
+
if (decoded && (decoded.latitude != null || decoded.longitude != null || decoded.address != null)) {
|
|
2294
2356
|
return decoded;
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
? {
|
|
2304
|
-
timestamp: (_e = sig.timestamp) !== null && _e !== void 0 ? _e : null,
|
|
2305
|
-
latitude: (_f = sig.latitude) !== null && _f !== void 0 ? _f : null,
|
|
2306
|
-
longitude: (_g = sig.longitude) !== null && _g !== void 0 ? _g : null,
|
|
2307
|
-
}
|
|
2308
|
-
: (_h = baseValue === null || baseValue === void 0 ? void 0 : baseValue.metadata) !== null && _h !== void 0 ? _h : null,
|
|
2357
|
+
}
|
|
2358
|
+
if (!loc)
|
|
2359
|
+
return decoded;
|
|
2360
|
+
const merged = {
|
|
2361
|
+
latitude: (_a = loc.latitude) !== null && _a !== void 0 ? _a : null,
|
|
2362
|
+
longitude: (_b = loc.longitude) !== null && _b !== void 0 ? _b : null,
|
|
2363
|
+
address: buildAddressDetailFromFlat(loc),
|
|
2364
|
+
timestamp: (_c = loc.timestamp) !== null && _c !== void 0 ? _c : null,
|
|
2309
2365
|
};
|
|
2310
|
-
|
|
2366
|
+
const legacyToken = getLegacyLocationToken(decoded);
|
|
2367
|
+
return legacyToken != null ? tagLegacyLocationToken(merged, legacyToken) : merged;
|
|
2311
2368
|
}
|
|
2312
2369
|
/**
|
|
2313
2370
|
* Walk a per-question-instance iterator and the values map to collect every
|
|
@@ -2374,29 +2431,65 @@ function extractFilesFromValues(loadedForm, values) {
|
|
|
2374
2431
|
/**
|
|
2375
2432
|
* Produce the metadata blob to write into the envelope for a given question.
|
|
2376
2433
|
* For `Signature`, derives `metadata.signature` from the decoded value
|
|
2377
|
-
* (fullName + lat/lng/timestamp)
|
|
2378
|
-
*
|
|
2379
|
-
*
|
|
2434
|
+
* (fullName + lat/lng/timestamp). For `Location`, derives `metadata.location`
|
|
2435
|
+
* so the legacy (v1) renderer can still hydrate its map/address on load — see
|
|
2436
|
+
* `locationCodec`'s doc comment — while leaving an unedited legacy answer's
|
|
2437
|
+
* metadata byte-identical. For every other type, passes through the existing
|
|
2438
|
+
* metadata untouched. Returns `undefined` when nothing should be written.
|
|
2380
2439
|
*/
|
|
2381
2440
|
function buildResponseMetadata(fieldTypeId, decodedValue, existingMetadata) {
|
|
2382
2441
|
var _a, _b, _c, _d, _e;
|
|
2383
|
-
if (fieldTypeId
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2442
|
+
if (fieldTypeId === types.FieldTypeId.Signature) {
|
|
2443
|
+
const sv = decodedValue;
|
|
2444
|
+
const hasFile = (sv === null || sv === void 0 ? void 0 : sv.file) instanceof File;
|
|
2445
|
+
const fullName = (_a = sv === null || sv === void 0 ? void 0 : sv.fullName) !== null && _a !== void 0 ? _a : null;
|
|
2446
|
+
const meta = (_b = sv === null || sv === void 0 ? void 0 : sv.metadata) !== null && _b !== void 0 ? _b : null;
|
|
2447
|
+
const hasAny = hasFile || (fullName != null && fullName !== '') || meta != null;
|
|
2448
|
+
if (!hasAny)
|
|
2449
|
+
return existingMetadata;
|
|
2450
|
+
const base = existingMetadata != null && typeof existingMetadata === 'object'
|
|
2451
|
+
? existingMetadata
|
|
2452
|
+
: {};
|
|
2453
|
+
return Object.assign(Object.assign({}, base), { signature: {
|
|
2454
|
+
latitude: (_c = meta === null || meta === void 0 ? void 0 : meta.latitude) !== null && _c !== void 0 ? _c : null,
|
|
2455
|
+
longitude: (_d = meta === null || meta === void 0 ? void 0 : meta.longitude) !== null && _d !== void 0 ? _d : null,
|
|
2456
|
+
timestamp: (_e = meta === null || meta === void 0 ? void 0 : meta.timestamp) !== null && _e !== void 0 ? _e : null,
|
|
2457
|
+
fullName,
|
|
2458
|
+
} });
|
|
2459
|
+
}
|
|
2460
|
+
if (fieldTypeId === types.FieldTypeId.Location) {
|
|
2461
|
+
return buildLocationResponseMetadata(decodedValue, existingMetadata);
|
|
2462
|
+
}
|
|
2463
|
+
return existingMetadata;
|
|
2464
|
+
}
|
|
2465
|
+
function buildLocationResponseMetadata(value, existingMetadata) {
|
|
2466
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
|
|
2467
|
+
// Untouched legacy answer — leave metadata exactly as loaded so re-saving
|
|
2468
|
+
// an unedited v1-captured Location doesn't disturb its stored data.
|
|
2469
|
+
if (getLegacyLocationToken(value) != null)
|
|
2391
2470
|
return existingMetadata;
|
|
2392
2471
|
const base = existingMetadata != null && typeof existingMetadata === 'object'
|
|
2393
2472
|
? existingMetadata
|
|
2394
2473
|
: {};
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2474
|
+
const hasData = value != null && (value.latitude != null || value.longitude != null || value.address != null);
|
|
2475
|
+
if (!hasData) {
|
|
2476
|
+
// Nothing to clear if there was never a location recorded — don't
|
|
2477
|
+
// fabricate a metadata object where none existed.
|
|
2478
|
+
if (base.location == null)
|
|
2479
|
+
return existingMetadata;
|
|
2480
|
+
return Object.assign(Object.assign({}, base), { location: null });
|
|
2481
|
+
}
|
|
2482
|
+
return Object.assign(Object.assign({}, base), { location: {
|
|
2483
|
+
latitude: (_a = value.latitude) !== null && _a !== void 0 ? _a : null,
|
|
2484
|
+
longitude: (_b = value.longitude) !== null && _b !== void 0 ? _b : null,
|
|
2485
|
+
timestamp: (_c = value.timestamp) !== null && _c !== void 0 ? _c : null,
|
|
2486
|
+
address: (_e = (_d = value.address) === null || _d === void 0 ? void 0 : _d.freeformAddress) !== null && _e !== void 0 ? _e : null,
|
|
2487
|
+
streetNumber: (_g = (_f = value.address) === null || _f === void 0 ? void 0 : _f.streetNumber) !== null && _g !== void 0 ? _g : null,
|
|
2488
|
+
streetName: (_j = (_h = value.address) === null || _h === void 0 ? void 0 : _h.streetName) !== null && _j !== void 0 ? _j : null,
|
|
2489
|
+
municipality: (_l = (_k = value.address) === null || _k === void 0 ? void 0 : _k.municipality) !== null && _l !== void 0 ? _l : null,
|
|
2490
|
+
countrySubdivisionName: (_o = (_m = value.address) === null || _m === void 0 ? void 0 : _m.countrySubdivisionName) !== null && _o !== void 0 ? _o : null,
|
|
2491
|
+
country: (_q = (_p = value.address) === null || _p === void 0 ? void 0 : _p.country) !== null && _q !== void 0 ? _q : null,
|
|
2492
|
+
postalCode: (_s = (_r = value.address) === null || _r === void 0 ? void 0 : _r.postalCode) !== null && _s !== void 0 ? _s : null,
|
|
2400
2493
|
} });
|
|
2401
2494
|
}
|
|
2402
2495
|
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var index = require('./index-CZB9dMeB.js');
|
|
4
|
+
var utils = require('./utils-Bp02BX38.js');
|
|
5
|
+
|
|
6
|
+
const formMetadataDisplayCss = () => `:host{display:block}.container{display:grid;gap:10px;padding:12px 14px;background:var(--unity-color-surface, #fff)}.row{display:grid;grid-template-columns:130px 1fr;align-items:baseline;column-gap:12px}.label{font-size:12px;line-height:1.2;letter-spacing:0.02em;text-transform:uppercase;color:var(--unity-color-text-secondary, rgba(0, 0, 0, 0.65))}.value{color:var(--unity-color-text, rgba(0, 0, 0, 0.9));overflow-wrap:anywhere}@media (max-width: 420px){.row{grid-template-columns:1fr;row-gap:4px}}`;
|
|
7
|
+
|
|
8
|
+
const FormMetadataDisplay = class {
|
|
9
|
+
constructor(hostRef) {
|
|
10
|
+
index.registerInstance(this, hostRef);
|
|
11
|
+
/**
|
|
12
|
+
* Toggles rendering of the "Name" row.
|
|
13
|
+
* Defaults to true.
|
|
14
|
+
*/
|
|
15
|
+
this.displayOwnerFullName = true;
|
|
16
|
+
/**
|
|
17
|
+
* Toggles rendering of the "Email" row.
|
|
18
|
+
* Defaults to true.
|
|
19
|
+
*/
|
|
20
|
+
this.displayOwnerEmail = true;
|
|
21
|
+
/**
|
|
22
|
+
* Toggles rendering of the "Submitted on" row.
|
|
23
|
+
* Defaults to true.
|
|
24
|
+
*/
|
|
25
|
+
this.displaySubmissionDate = true;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Renders a single metadata row using a standard label/value layout.
|
|
29
|
+
* @internal
|
|
30
|
+
*/
|
|
31
|
+
renderRow(label, value) {
|
|
32
|
+
return (index.h("div", { class: "row" }, index.h("span", { class: "label" }, label), index.h("unity-typography", { class: "value", variant: "h4" }, value)));
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Renders the metadata container. Rows are conditionally included based on flags + data presence.
|
|
36
|
+
* @internal
|
|
37
|
+
*/
|
|
38
|
+
render() {
|
|
39
|
+
return (
|
|
40
|
+
// role/aria-label provide a lightweight accessible grouping for screen readers
|
|
41
|
+
index.h("div", { key: 'e76c4a74661c13b2962c090efec64c8d0b1134cc', class: "container", role: "group", "aria-label": "Form metadata" }, this.displayOwnerFullName && this.userDisplayName && this.renderRow('Name', this.userDisplayName), this.displayOwnerEmail && this.userEmail && this.renderRow('Email', this.userEmail), this.displaySubmissionDate && this.submittedOn && this.renderRow('Submitted on', utils.dateFormatter(this.submittedOn, 'long'))));
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
FormMetadataDisplay.style = formMetadataDisplayCss();
|
|
45
|
+
|
|
46
|
+
const tallyCss = () => `:host{display:block;width:100%}.tally-container{display:flex;flex-direction:column;gap:var(--spacing-02, 8px)}.tally-label{font-weight:600;margin-bottom:var(--spacing-02, 8px)}.tally-loading{display:flex;align-items:center;justify-content:center;padding:var(--spacing-04, 16px);color:var(--text-secondary, #6b7280)}.tally-content{display:flex;flex-direction:column;gap:var(--spacing-03, 12px)}.tally-stats{display:flex;gap:var(--spacing-04, 16px);flex-wrap:wrap}.tally-item{display:flex;flex-direction:column;align-items:center;padding:var(--spacing-03, 12px) var(--spacing-04, 16px);border-radius:var(--border-radius-01, 4px);border:1px solid var(--border-subtle, #e5e7eb);background-color:var(--layer-01, #ffffff);min-width:80px;flex:1;max-width:120px}.tally-item.tally-yes{border-color:var(--support-success, #42be65);background-color:var(--support-success-hover, #f6f8ff)}.tally-item.tally-no{border-color:var(--support-error, #da1e28);background-color:var(--support-error-hover, #fff1f1)}.tally-item.tally-unanswered{border-color:var(--support-warning, #f1c21b);background-color:var(--support-warning-hover, #fcf4d6)}.tally-count{font-weight:700;line-height:1.2;margin-bottom:var(--spacing-01, 4px)}.tally-yes .tally-count{color:var(--support-success, #42be65)}.tally-no .tally-count{color:var(--support-error, #da1e28)}.tally-unanswered .tally-count{color:var(--support-warning, #f1c21b)}.tally-item .tally-label{margin:0;font-weight:500;text-transform:uppercase;font-size:0.75rem;letter-spacing:0.02em}.tally-summary{padding:var(--spacing-02, 8px) 0;border-top:1px solid var(--border-subtle, #e5e7eb);text-align:center}.error-message{margin-top:var(--spacing-02, 8px);padding:var(--spacing-02, 8px);border-radius:var(--border-radius-01, 4px);background-color:var(--support-error-hover, #fff1f1);border:1px solid var(--support-error, #da1e28)}:host(.udp-input--size-small) .tally-item{padding:var(--spacing-02, 8px) var(--spacing-03, 12px);min-width:60px;max-width:90px}:host(.udp-input--size-small) .tally-count{font-size:1.25rem}:host(.udp-input--size-large) .tally-item{padding:var(--spacing-04, 16px) var(--spacing-05, 20px);min-width:100px;max-width:150px}:host(.udp-input--size-large) .tally-count{font-size:2rem}:host(.udp-input--margin-none) .tally-container{gap:0}:host(.udp-input--margin-dense) .tally-container{gap:var(--spacing-01, 4px)}:host(.udp-input--margin-comfortable) .tally-container{gap:var(--spacing-04, 16px)}:host(.udp-input--disabled) .tally-item{opacity:0.5;pointer-events:none}:host(.udp-input--readonly) .tally-item{background-color:var(--field-01, #f4f4f4)}@media (max-width: 480px){.tally-stats{flex-direction:column}.tally-item{max-width:none;flex:none}}`;
|
|
47
|
+
|
|
48
|
+
const TallyDisplay = class {
|
|
49
|
+
constructor(hostRef) {
|
|
50
|
+
index.registerInstance(this, hostRef);
|
|
51
|
+
/**
|
|
52
|
+
* Label for the tally display.
|
|
53
|
+
*/
|
|
54
|
+
this.label = 'Response Tally';
|
|
55
|
+
/**
|
|
56
|
+
* Number of Yes responses.
|
|
57
|
+
*/
|
|
58
|
+
this.yesCount = 0;
|
|
59
|
+
/**
|
|
60
|
+
* Number of No responses.
|
|
61
|
+
*/
|
|
62
|
+
this.noCount = 0;
|
|
63
|
+
/**
|
|
64
|
+
* Number of Not Applicable responses.
|
|
65
|
+
*/
|
|
66
|
+
this.naCount = 0;
|
|
67
|
+
/**
|
|
68
|
+
* Total number of fields being tallied.
|
|
69
|
+
*/
|
|
70
|
+
this.totalFields = 0;
|
|
71
|
+
/**
|
|
72
|
+
* Whether the component is disabled.
|
|
73
|
+
*/
|
|
74
|
+
this.disabled = false;
|
|
75
|
+
/**
|
|
76
|
+
* Whether the component is read-only.
|
|
77
|
+
*/
|
|
78
|
+
this.readonly = false;
|
|
79
|
+
/**
|
|
80
|
+
* Size variant for the tally display.
|
|
81
|
+
*/
|
|
82
|
+
this.size = 'normal';
|
|
83
|
+
/**
|
|
84
|
+
* Margin variant for the component spacing.
|
|
85
|
+
*/
|
|
86
|
+
this.margin = 'normal';
|
|
87
|
+
}
|
|
88
|
+
render() {
|
|
89
|
+
const isError = !!this.error;
|
|
90
|
+
const answeredCount = this.yesCount + this.noCount + this.naCount;
|
|
91
|
+
const unansweredCount = this.totalFields - answeredCount;
|
|
92
|
+
return (index.h(index.Host, { key: '4e1b03c99dbe1d333b6144a232dc386b15f6053f', class: {
|
|
93
|
+
'udp-input': true,
|
|
94
|
+
'udp-input--error': isError,
|
|
95
|
+
'udp-input--disabled': this.disabled,
|
|
96
|
+
'udp-input--readonly': this.readonly,
|
|
97
|
+
[`udp-input--size-${this.size}`]: true,
|
|
98
|
+
[`udp-input--margin-${this.margin}`]: true,
|
|
99
|
+
} }, index.h("div", { key: '55d69a511e24a845ae28c3ffb05a6b564f1fbbdf', class: "tally-container" }, this.label && (index.h("unity-typography", { key: '30439676a573ad086d2280974106be9f683bc808', variant: "caption-text" }, index.h("label", { key: '7e39f59eb0fcdd5e0f35f0de36b80bae4d199e8c', htmlFor: this.id, class: "tally-label" }, this.label))), index.h("div", { key: '40ecef47645a053be156a17c50f0ed4a3e2c2d2e', class: "tally-content", id: this.id }, index.h("div", { key: '34808d7cd994a1888bd0b825fae1634ad730ebb8', class: "tally-stats" }, index.h("div", { key: '0e49084939f51ff2dd72221d0f89987b80bc5399', class: "tally-item tally-yes" }, index.h("unity-typography", { key: '81bb681a92294513faf31275cd4e569ffa8a15fa', variant: "h4", class: "tally-count" }, this.yesCount), index.h("unity-typography", { key: '9440146b8adcc4cf9da3c2e3eea229703e0284dc', variant: "caption-text", class: "tally-label" }, "Yes")), index.h("div", { key: '453033c26001d2683181a91e0ebec682ad5d4d38', class: "tally-item tally-no" }, index.h("unity-typography", { key: 'c840b3783bdc163242f4e18c784e0b489fd4c301', variant: "h4", class: "tally-count" }, this.noCount), index.h("unity-typography", { key: '0af346f74b0e574e99efa717f111b18375bd15dd', variant: "caption-text", class: "tally-label" }, "No")), index.h("div", { key: '8a9355d09c683110350f62dd24af0aa404b23c87', class: "tally-item tally-na" }, index.h("unity-typography", { key: '9bb906130f240bf423c6c4920c75b8f9890647b1', variant: "h4", class: "tally-count" }, this.naCount), index.h("unity-typography", { key: '7c51faeeb2c29a7c2e936efaec66677ab50d67b0', variant: "caption-text", class: "tally-label" }, "Not Applicable")), unansweredCount > 0 && (index.h("div", { key: '225d3f0d49da9f15eeae6c3829d7105d0d80c560', class: "tally-item tally-unanswered" }, index.h("unity-typography", { key: 'f167b42959297823e1ffa199be60b558a520d922', variant: "h4", class: "tally-count" }, unansweredCount), index.h("unity-typography", { key: 'de96f235c61bbdd1eb4a4a102a2c80513c543dba', variant: "caption-text", class: "tally-label" }, "Unanswered")))), index.h("div", { key: 'f2abf82180e67933ed34e1d102581c036c7d2614', class: "tally-summary" }, index.h("unity-typography", { key: '7becceb75df4182f6d477b2aa14e8e5464e4534e', variant: "caption-text" }, "Total Questions: ", this.totalFields))), isError && (index.h("div", { key: '56f57a775f1cde86c97e55d1bd4eeb7c2b0b0db7', class: "error-message" }, index.h("unity-typography", { key: 'ef3370bdd1d122fdc9df92fcd990e064989da81e', variant: "caption-text", color: "error" }, this.error))))));
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
TallyDisplay.style = tallyCss();
|
|
103
|
+
|
|
104
|
+
exports.form_metadata_display = FormMetadataDisplay;
|
|
105
|
+
exports.tally_display = TallyDisplay;
|