@seamlet/astro 1.2.1 → 1.4.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/CHANGELOG.md +14 -0
- package/README.md +76 -0
- package/components/RequestForm.astro +192 -0
- package/dist/bridge.d.ts +2 -2
- package/dist/bridge.js +3 -2
- package/dist/chunk-2IK7D2AA.js +6 -0
- package/dist/{chunk-Y4R4YV5O.js → chunk-BCJUH3ZD.js} +1 -1
- package/dist/{chunk-OCA2WYK3.js → chunk-JQ4YD7MM.js} +8 -3
- package/dist/{chunk-UL2C2IB2.js → chunk-TMN7KG5M.js} +294 -4
- package/dist/{chunk-HFPZVDST.js → chunk-ULOKDC6D.js} +1 -1
- package/dist/cli.js +1 -1
- package/dist/client.js +8 -0
- package/dist/index.js +5 -5
- package/dist/{messages-C2OjqFmy.d.ts → messages-Dwjthhrk.d.ts} +1 -1
- package/dist/{parse-content-Bnn6Wa-l.d.ts → parse-content-CT2cUVL-.d.ts} +23 -4
- package/dist/preview-requests.d.ts +5 -3
- package/dist/preview-requests.js +5 -3
- package/dist/protocol.d.ts +3 -3
- package/dist/protocol.js +2 -2
- package/dist/request-sending-ZBTK5L7U.js +251 -0
- package/dist/routes/media.js +5 -5
- package/dist/schema.d.ts +103 -4
- package/dist/schema.js +63 -1
- package/dist/{site-description-BnHrODQX.d.ts → site-description-cKiFtNHW.d.ts} +100 -2
- package/dist/site.d.ts +7 -2
- package/dist/site.js +19 -3
- package/package.json +3 -2
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import {
|
|
2
|
+
REQUEST_FORM_SELECTOR
|
|
3
|
+
} from "./chunk-2IK7D2AA.js";
|
|
4
|
+
import {
|
|
5
|
+
CONSENT_REQUIRED_TEXT,
|
|
6
|
+
REQUEST_CONSENT_KEY,
|
|
7
|
+
REQUEST_FAILED_EVENT,
|
|
8
|
+
REQUEST_ISSUE_TEXTS,
|
|
9
|
+
REQUEST_SEND_EVENT,
|
|
10
|
+
REQUEST_SENT_EVENT,
|
|
11
|
+
isConsentGiven,
|
|
12
|
+
isJsonObject,
|
|
13
|
+
readRequestForm,
|
|
14
|
+
readRequestValues
|
|
15
|
+
} from "./chunk-TMN7KG5M.js";
|
|
16
|
+
|
|
17
|
+
// src/request-sending.ts
|
|
18
|
+
var STATUS_CREATED = 201;
|
|
19
|
+
var STATUS_UNPROCESSABLE = 422;
|
|
20
|
+
var STATUS_CONFLICT = 409;
|
|
21
|
+
var STATUS_TOO_MANY = 429;
|
|
22
|
+
var ANSWER_TIMEOUT_MS = 15e3;
|
|
23
|
+
var ISSUE_CODES = [
|
|
24
|
+
"required",
|
|
25
|
+
"too-long",
|
|
26
|
+
"invalid-phone",
|
|
27
|
+
"invalid-email",
|
|
28
|
+
"unknown-option"
|
|
29
|
+
];
|
|
30
|
+
function connectRequestForms(root, options) {
|
|
31
|
+
const elements = root.querySelectorAll(
|
|
32
|
+
REQUEST_FORM_SELECTOR
|
|
33
|
+
);
|
|
34
|
+
for (const element of elements) {
|
|
35
|
+
if (options.isPreview) keepFromSending(element);
|
|
36
|
+
else connectRequestForm(element);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function keepFromSending(element) {
|
|
40
|
+
element.addEventListener("submit", (event) => {
|
|
41
|
+
event.preventDefault();
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function connectRequestForm(element) {
|
|
45
|
+
const form = formOf(element);
|
|
46
|
+
if (form === void 0) return;
|
|
47
|
+
element.noValidate = true;
|
|
48
|
+
element.addEventListener("submit", (event) => {
|
|
49
|
+
event.preventDefault();
|
|
50
|
+
const isSending = element.dataset["seamletState"] === "sending";
|
|
51
|
+
if (!isSending) void sendRequest(element, form);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
function formOf(element) {
|
|
55
|
+
const declared = element.dataset["seamletRequestForm"];
|
|
56
|
+
if (declared === void 0) return void 0;
|
|
57
|
+
try {
|
|
58
|
+
const reading = readRequestForm(JSON.parse(declared));
|
|
59
|
+
return reading.status === "read" ? reading.form : void 0;
|
|
60
|
+
} catch {
|
|
61
|
+
return void 0;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
async function sendRequest(element, form) {
|
|
65
|
+
showState(element, "editing");
|
|
66
|
+
const entries = entriesOf(element);
|
|
67
|
+
const issues = issuesOf(form, entries);
|
|
68
|
+
showIssues(element, issues);
|
|
69
|
+
if (issues.length > 0) {
|
|
70
|
+
focusFirstIssue(element, issues);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const isSentBySite = !element.dispatchEvent(
|
|
74
|
+
new CustomEvent(REQUEST_SEND_EVENT, {
|
|
75
|
+
bubbles: true,
|
|
76
|
+
cancelable: true,
|
|
77
|
+
detail: { form: form.id, entries }
|
|
78
|
+
})
|
|
79
|
+
);
|
|
80
|
+
if (isSentBySite) return;
|
|
81
|
+
showState(element, "sending");
|
|
82
|
+
const outcome = await post(element.getAttribute("action") ?? "", entries);
|
|
83
|
+
settle(element, { form, entries, outcome });
|
|
84
|
+
}
|
|
85
|
+
function settle(element, sending) {
|
|
86
|
+
const { form, entries, outcome } = sending;
|
|
87
|
+
switch (outcome.kind) {
|
|
88
|
+
case "received":
|
|
89
|
+
showState(element, "sent");
|
|
90
|
+
HTMLFormElement.prototype.reset.call(element);
|
|
91
|
+
announceSent(element, { form: form.id, entries, id: outcome.id });
|
|
92
|
+
return;
|
|
93
|
+
case "refused":
|
|
94
|
+
showState(element, "failed");
|
|
95
|
+
showIssues(element, outcome.issues);
|
|
96
|
+
focusFirstIssue(element, outcome.issues);
|
|
97
|
+
announceFailure(element, {
|
|
98
|
+
form: form.id,
|
|
99
|
+
reason: outcome.reason,
|
|
100
|
+
issues: outcome.issues
|
|
101
|
+
});
|
|
102
|
+
return;
|
|
103
|
+
case "blocked":
|
|
104
|
+
HTMLFormElement.prototype.submit.call(element);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function announceSent(element, detail) {
|
|
108
|
+
element.dispatchEvent(
|
|
109
|
+
new CustomEvent(REQUEST_SENT_EVENT, {
|
|
110
|
+
bubbles: true,
|
|
111
|
+
detail
|
|
112
|
+
})
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
function announceFailure(element, detail) {
|
|
116
|
+
element.dispatchEvent(
|
|
117
|
+
new CustomEvent(REQUEST_FAILED_EVENT, {
|
|
118
|
+
bubbles: true,
|
|
119
|
+
detail
|
|
120
|
+
})
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
function entriesOf(element) {
|
|
124
|
+
const data = new FormData(element);
|
|
125
|
+
const pairs = [...data].flatMap(
|
|
126
|
+
([name, value]) => typeof value === "string" ? [[name, value]] : []
|
|
127
|
+
);
|
|
128
|
+
return Object.fromEntries(pairs);
|
|
129
|
+
}
|
|
130
|
+
function issuesOf(form, entries) {
|
|
131
|
+
const reading = readRequestValues(form, entries);
|
|
132
|
+
const fieldIssues = reading.status === "invalid" ? reading.issues : [];
|
|
133
|
+
const consentIssues = isConsentGiven(entries) ? [] : [{ field: REQUEST_CONSENT_KEY, code: "required" }];
|
|
134
|
+
return [...fieldIssues, ...consentIssues];
|
|
135
|
+
}
|
|
136
|
+
async function post(action, entries) {
|
|
137
|
+
const blocked = watchBlocking(action);
|
|
138
|
+
try {
|
|
139
|
+
const answer = await fetch(action, {
|
|
140
|
+
method: "POST",
|
|
141
|
+
headers: {
|
|
142
|
+
"Content-Type": "application/json",
|
|
143
|
+
Accept: "application/json"
|
|
144
|
+
},
|
|
145
|
+
body: JSON.stringify(entries),
|
|
146
|
+
signal: AbortSignal.timeout(ANSWER_TIMEOUT_MS)
|
|
147
|
+
});
|
|
148
|
+
return await outcomeOf(answer);
|
|
149
|
+
} catch {
|
|
150
|
+
return blocked.isBlocked() ? { kind: "blocked" } : { kind: "refused", reason: "unavailable", issues: [] };
|
|
151
|
+
} finally {
|
|
152
|
+
blocked.stop();
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
function watchBlocking(action) {
|
|
156
|
+
const target = new URL(action, document.baseURI).origin;
|
|
157
|
+
let isBlocked = false;
|
|
158
|
+
const hear = (event) => {
|
|
159
|
+
if (originOf(event.blockedURI) === target) isBlocked = true;
|
|
160
|
+
};
|
|
161
|
+
document.addEventListener("securitypolicyviolation", hear);
|
|
162
|
+
return {
|
|
163
|
+
isBlocked: () => isBlocked,
|
|
164
|
+
stop: () => {
|
|
165
|
+
document.removeEventListener("securitypolicyviolation", hear);
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
function originOf(address) {
|
|
170
|
+
try {
|
|
171
|
+
return new URL(address).origin;
|
|
172
|
+
} catch {
|
|
173
|
+
return void 0;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
async function outcomeOf(answer) {
|
|
177
|
+
const body = await answer.json().catch(() => void 0);
|
|
178
|
+
const record = isJsonObject(body) ? body : {};
|
|
179
|
+
const id = record["id"];
|
|
180
|
+
if (answer.status === STATUS_CREATED && typeof id === "string") {
|
|
181
|
+
return { kind: "received", id };
|
|
182
|
+
}
|
|
183
|
+
if (answer.status === STATUS_UNPROCESSABLE) {
|
|
184
|
+
const issues = readIssues(record["issues"]);
|
|
185
|
+
return { kind: "refused", reason: "invalid", issues };
|
|
186
|
+
}
|
|
187
|
+
return { kind: "refused", reason: failureOf(answer.status), issues: [] };
|
|
188
|
+
}
|
|
189
|
+
function failureOf(status) {
|
|
190
|
+
if (status === STATUS_CONFLICT) return "closed";
|
|
191
|
+
if (status === STATUS_TOO_MANY) return "too-many";
|
|
192
|
+
return "unavailable";
|
|
193
|
+
}
|
|
194
|
+
function readIssues(input) {
|
|
195
|
+
if (!Array.isArray(input)) return [];
|
|
196
|
+
const entries = input;
|
|
197
|
+
return entries.flatMap((entry) => {
|
|
198
|
+
if (!isJsonObject(entry)) return [];
|
|
199
|
+
const { field, code } = entry;
|
|
200
|
+
const isIssue = typeof field === "string" && isIssueCode(code);
|
|
201
|
+
return isIssue ? [{ field, code }] : [];
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
function isIssueCode(value) {
|
|
205
|
+
return ISSUE_CODES.some((code) => code === value);
|
|
206
|
+
}
|
|
207
|
+
function showIssues(element, issues) {
|
|
208
|
+
const messages = element.querySelectorAll(
|
|
209
|
+
"[data-seamlet-issue]"
|
|
210
|
+
);
|
|
211
|
+
for (const message of messages) {
|
|
212
|
+
const field = message.dataset["seamletIssue"] ?? "";
|
|
213
|
+
const issue = issues.find((candidate) => candidate.field === field);
|
|
214
|
+
message.textContent = issue === void 0 ? "" : issueText(issue);
|
|
215
|
+
message.hidden = issue === void 0;
|
|
216
|
+
markControl(element, field, issue !== void 0);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
function issueText(issue) {
|
|
220
|
+
return issue.field === REQUEST_CONSENT_KEY ? CONSENT_REQUIRED_TEXT : REQUEST_ISSUE_TEXTS[issue.code];
|
|
221
|
+
}
|
|
222
|
+
function controlOf(element, field) {
|
|
223
|
+
const control = element.querySelector(`[name="${field}"]`);
|
|
224
|
+
return control instanceof HTMLElement ? control : void 0;
|
|
225
|
+
}
|
|
226
|
+
function markControl(element, field, isInvalid) {
|
|
227
|
+
const control = controlOf(element, field);
|
|
228
|
+
if (isInvalid) control?.setAttribute("aria-invalid", "true");
|
|
229
|
+
else control?.removeAttribute("aria-invalid");
|
|
230
|
+
}
|
|
231
|
+
function focusFirstIssue(element, issues) {
|
|
232
|
+
const [first] = issues;
|
|
233
|
+
if (first !== void 0) controlOf(element, first.field)?.focus();
|
|
234
|
+
}
|
|
235
|
+
function showState(element, state) {
|
|
236
|
+
element.dataset["seamletState"] = state;
|
|
237
|
+
const submit = element.querySelector("[type=submit]");
|
|
238
|
+
if (submit !== null) submit.disabled = state === "sending";
|
|
239
|
+
const sent = element.querySelector("[data-seamlet-sent]");
|
|
240
|
+
const failure = element.querySelector("[data-seamlet-failed]");
|
|
241
|
+
say(sent, state === "sent");
|
|
242
|
+
say(failure, state === "failed");
|
|
243
|
+
if (state === "sent") sent?.focus();
|
|
244
|
+
}
|
|
245
|
+
function say(message, isSaid) {
|
|
246
|
+
if (message === null) return;
|
|
247
|
+
message.textContent = isSaid ? message.dataset["seamletText"] ?? "" : "";
|
|
248
|
+
}
|
|
249
|
+
export {
|
|
250
|
+
connectRequestForms
|
|
251
|
+
};
|
package/dist/routes/media.js
CHANGED
|
@@ -2,10 +2,10 @@ import {
|
|
|
2
2
|
uploadedPhotoPath
|
|
3
3
|
} from "../chunk-QCVWHHJC.js";
|
|
4
4
|
import {
|
|
5
|
-
|
|
6
|
-
} from "../chunk-
|
|
7
|
-
import "../chunk-
|
|
8
|
-
import "../chunk-
|
|
5
|
+
isUploadedFile
|
|
6
|
+
} from "../chunk-JQ4YD7MM.js";
|
|
7
|
+
import "../chunk-ULOKDC6D.js";
|
|
8
|
+
import "../chunk-TMN7KG5M.js";
|
|
9
9
|
|
|
10
10
|
// src/routes/media.ts
|
|
11
11
|
import { cmsOrigin } from "virtual:seamlet/config";
|
|
@@ -15,7 +15,7 @@ var BAD_GATEWAY = 502;
|
|
|
15
15
|
var PHOTO_TIMEOUT_MS = 1e4;
|
|
16
16
|
var GET = async ({ params }) => {
|
|
17
17
|
const fileName = params["file"];
|
|
18
|
-
const isOurs = params["site"] === site.id &&
|
|
18
|
+
const isOurs = params["site"] === site.id && isUploadedFile(fileName);
|
|
19
19
|
if (!isOurs) {
|
|
20
20
|
return new Response(null, { status: NOT_FOUND });
|
|
21
21
|
}
|
package/dist/schema.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { h as ImageValue, L as LinkValue, d as CollectionField, C as Content, F as Fields, e as RecordFields, b as ContentOf, G as GroupField, i as LinkField, T as TextField, U as UrlField, j as ChoicesField, k as TimeField, S as SlugField, I as ImageField, l as RichTextField, N as NumberField, m as ToggleField } from './parse-content-
|
|
2
|
-
export { n as ChoiceField, o as ChoiceOption, g as ContentIssue, D as DateField, c as Field, p as FieldKind, a as FieldPath, q as FieldValue, r as ImageFocus, O as OptionValue, P as ParsedContent, f as RecordOf,
|
|
3
|
-
|
|
1
|
+
import { h as ImageValue, L as LinkValue, d as CollectionField, C as Content, F as Fields, e as RecordFields, b as ContentOf, G as GroupField, i as LinkField, T as TextField, U as UrlField, j as ChoicesField, k as TimeField, S as SlugField, I as ImageField, l as RichTextField, N as NumberField, m as ToggleField } from './parse-content-CT2cUVL-.js';
|
|
2
|
+
export { n as ChoiceField, o as ChoiceOption, g as ContentIssue, D as DateField, c as Field, p as FieldKind, a as FieldPath, q as FieldValue, r as FileField, s as FileValue, t as ImageFocus, O as OptionValue, P as ParsedContent, f as RecordOf, u as ReferenceField, v as ReferencesField, w as RichBlock, x as RichLine, y as RichSpan, R as RichText, V as ValueOf, z as asOneParagraph, A as choice, B as choices, E as collection, H as countCharacters, J as date, K as defaultContent, M as defaultValue, Q as defineSchema, W as file, X as formatFieldPath, Y as group, Z as image, _ as linesOf, $ as link, a0 as normalizedLine, a1 as number, a2 as parseContent, a3 as plainTextOf, a4 as readRichText, a5 as reference, a6 as references, a7 as richText, a8 as richTextOf, a9 as slug, aa as text, ab as time, ac as toggle, ad as url } from './parse-content-CT2cUVL-.js';
|
|
3
|
+
import { R as RequestForm } from './site-description-cKiFtNHW.js';
|
|
4
|
+
export { C as CollectionPath, D as DEFAULT_LONG_TEXT_LENGTH, b as DEFAULT_TEXT_LENGTH, F as FIELD_PATH_SEPARATOR, c as FieldTarget, d as FieldsReading, H as HOME_PAGE_PATH, M as MAX_REQUEST_FIELD_LENGTH, P as PAGE_PATH_SEPARATOR, e as PageProblemReason, f as PlacedRecord, g as RECORD_PLACEHOLDER, h as RecordFieldsAt, i as RecordPagePath, j as RecordPageProblemReason, k as RecordPages, l as RequestChoiceField, m as RequestEmailField, n as RequestField, o as RequestFieldKind, p as RequestFields, q as RequestFormProblemReason, r as RequestFormReading, s as RequestLongTextField, t as RequestPhoneField, u as RequestTextField, v as SITE_DESCRIPTION_PATH, w as SchemaProblem, x as SchemaProblemReason, S as SiteDescription, y as SiteDescriptionProblem, z as SiteDescriptionReading, A as SitePageDescription, B as SiteRecordPageDescription, a as SiteRecordPages, E as checkFields, G as checkSiteDescription, I as isFormId, J as isRecordPagePath, K as isSearchTextsGroup, L as maxLengthOf, N as readFields, O as readRequestForm, Q as readSiteDescription, T as recordAddressOf, U as recordAt, V as recordPageAt, W as recordPagePath, X as recordPages, Y as requestChoice, Z as requestEmail, _ as requestForm, $ as requestLongText, a0 as requestPhone, a1 as requestText, a2 as resolveFieldPath } from './site-description-cKiFtNHW.js';
|
|
4
5
|
|
|
5
6
|
declare const FIELD_PATH_ATTRIBUTE = "data-cms-path";
|
|
6
7
|
interface FieldMarker {
|
|
@@ -234,4 +235,102 @@ declare function slugOf(words: string): string;
|
|
|
234
235
|
/** The name of the slug of a record of the collection, if its records have one. */
|
|
235
236
|
declare function slugFieldOf(item: RecordFields): string | undefined;
|
|
236
237
|
|
|
237
|
-
|
|
238
|
+
/** The id of the form the request is sent with. */
|
|
239
|
+
declare const REQUEST_FORM_KEY = "seamlet-form";
|
|
240
|
+
/** The address of the page the request is sent from: `/catalog/banya-6x4`. */
|
|
241
|
+
declare const REQUEST_PAGE_KEY = "seamlet-page";
|
|
242
|
+
/** The visitor's consent to the processing of what they send, given with the form's checkbox. */
|
|
243
|
+
declare const REQUEST_CONSENT_KEY = "seamlet-consent";
|
|
244
|
+
/**
|
|
245
|
+
* A field a person never sees and a program filling every field fills: a request that has words in
|
|
246
|
+
* it is not a person's.
|
|
247
|
+
*/
|
|
248
|
+
declare const REQUEST_TRAP_KEY = "seamlet-check";
|
|
249
|
+
/** The words of a request as they come: the names of the form's fields and its own keys. */
|
|
250
|
+
type RequestEntries = Readonly<Record<string, string>>;
|
|
251
|
+
/** A field the visitor filled in, as the business reads it. */
|
|
252
|
+
interface RequestValue {
|
|
253
|
+
/** The field's name in the form: `phone`. */
|
|
254
|
+
readonly field: string;
|
|
255
|
+
/** The field's label: «Телефон». */
|
|
256
|
+
readonly label: string;
|
|
257
|
+
readonly value: string;
|
|
258
|
+
}
|
|
259
|
+
type RequestIssueCode = "required" | "too-long" | "invalid-phone" | "invalid-email" | "unknown-option";
|
|
260
|
+
/** A field whose words the form cannot take, and why. */
|
|
261
|
+
interface RequestIssue {
|
|
262
|
+
readonly field: string;
|
|
263
|
+
readonly code: RequestIssueCode;
|
|
264
|
+
}
|
|
265
|
+
type RequestReading = {
|
|
266
|
+
readonly status: "read";
|
|
267
|
+
/** The fields the visitor filled in, in the form's order. */
|
|
268
|
+
readonly values: readonly RequestValue[];
|
|
269
|
+
} | {
|
|
270
|
+
readonly status: "invalid";
|
|
271
|
+
readonly issues: readonly RequestIssue[];
|
|
272
|
+
};
|
|
273
|
+
/** What a visitor reads under a field whose words the form cannot take. */
|
|
274
|
+
declare const REQUEST_ISSUE_TEXTS: Readonly<Record<RequestIssueCode, string>>;
|
|
275
|
+
/** What a visitor reads when the consent's checkbox is left empty. */
|
|
276
|
+
declare const CONSENT_REQUIRED_TEXT = "\u041E\u0442\u043C\u0435\u0442\u044C\u0442\u0435 \u0441\u043E\u0433\u043B\u0430\u0441\u0438\u0435 \u043D\u0430 \u043E\u0431\u0440\u0430\u0431\u043E\u0442\u043A\u0443 \u043F\u0435\u0440\u0441\u043E\u043D\u0430\u043B\u044C\u043D\u044B\u0445 \u0434\u0430\u043D\u043D\u044B\u0445";
|
|
277
|
+
/** The fields of the request as the form takes them, or every field it cannot take. */
|
|
278
|
+
declare function readRequestValues(form: RequestForm, entries: RequestEntries): RequestReading;
|
|
279
|
+
/**
|
|
280
|
+
* The entries a request's body gives: its own string values only, so a value of another type, or a
|
|
281
|
+
* name of an object's prototype, never reaches a reader.
|
|
282
|
+
*/
|
|
283
|
+
declare function readRequestEntries(input: unknown): RequestEntries;
|
|
284
|
+
/** Whether the visitor checked the consent's checkbox. */
|
|
285
|
+
declare function isConsentGiven(entries: RequestEntries): boolean;
|
|
286
|
+
/** Whether the field a person never sees was filled in: a program sent the request. */
|
|
287
|
+
declare function isTrapFilled(entries: RequestEntries): boolean;
|
|
288
|
+
/** The page the request was sent from, or the home page when the request names no page. */
|
|
289
|
+
declare function requestPageOf(entries: RequestEntries): string;
|
|
290
|
+
/** The number as typed, when it is one: `+7 (912) 345-67-89`. */
|
|
291
|
+
declare function isPhoneNumber(typed: string): boolean;
|
|
292
|
+
declare function isEmailAddress(typed: string): boolean;
|
|
293
|
+
|
|
294
|
+
/** The two texts a form's visitor reads before sending: the consent and the operator's policy. */
|
|
295
|
+
type LegalDocument = "consent" | "privacy";
|
|
296
|
+
/** Where the site's forms send their requests, on the CMS's origin. */
|
|
297
|
+
declare function requestsPathOf(siteId: string): string;
|
|
298
|
+
/** Where the CMS shows a text of the business that owns the site, to anyone. */
|
|
299
|
+
declare function legalPagePathOf(siteId: string, document: LegalDocument): string;
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Before the request is sent, once the form takes what was typed. Cancelable: a site that calls
|
|
303
|
+
* `preventDefault()` sends the request its own way, and the package sends nothing.
|
|
304
|
+
*/
|
|
305
|
+
declare const REQUEST_SEND_EVENT = "seamlet:request-send";
|
|
306
|
+
/** The CMS has kept the request. */
|
|
307
|
+
declare const REQUEST_SENT_EVENT = "seamlet:request-sent";
|
|
308
|
+
/** The CMS has not kept the request: what was typed is still in the form. */
|
|
309
|
+
declare const REQUEST_FAILED_EVENT = "seamlet:request-failed";
|
|
310
|
+
interface RequestSendDetail {
|
|
311
|
+
/** The id of the form: `callback`. */
|
|
312
|
+
readonly form: string;
|
|
313
|
+
/** What the request sends: the fields by their names, and the request's own keys. */
|
|
314
|
+
readonly entries: RequestEntries;
|
|
315
|
+
}
|
|
316
|
+
interface RequestSentDetail extends RequestSendDetail {
|
|
317
|
+
/** The id the CMS gave the request. */
|
|
318
|
+
readonly id: string;
|
|
319
|
+
}
|
|
320
|
+
/** Why the CMS did not keep the request. */
|
|
321
|
+
type RequestFailure =
|
|
322
|
+
/** A field the CMS could not take; `issues` names them. */
|
|
323
|
+
"invalid"
|
|
324
|
+
/** The business does not take requests yet: its texts of consent are not confirmed. */
|
|
325
|
+
| "closed"
|
|
326
|
+
/** Too many requests from the same visitor; a later one is taken. */
|
|
327
|
+
| "too-many"
|
|
328
|
+
/** The CMS could not be reached, or answered with an error. */
|
|
329
|
+
| "unavailable";
|
|
330
|
+
interface RequestFailedDetail {
|
|
331
|
+
readonly form: string;
|
|
332
|
+
readonly reason: RequestFailure;
|
|
333
|
+
readonly issues: readonly RequestIssue[];
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
export { CONSENT_REQUIRED_TEXT, ChoicesField, CollectionField, type CollectionRecords, Content, ContentOf, type ContentPath, FIELD_PATH_ATTRIBUTE, type FieldMarker, Fields, GroupField, ImageField, ImageValue, type JsonObject, type LegalDocument, LinkField, type LinkKind, type LinkTarget, LinkValue, MAX_SLUG_LENGTH, NumberField, RECORD_ID_KEY, REQUEST_CONSENT_KEY, REQUEST_FAILED_EVENT, REQUEST_FORM_KEY, REQUEST_ISSUE_TEXTS, REQUEST_PAGE_KEY, REQUEST_SEND_EVENT, REQUEST_SENT_EVENT, REQUEST_TRAP_KEY, REVEALED_ATTRIBUTE, REVEAL_ATTRIBUTE, REVEAL_EVENT, RecordFields, type RequestEntries, type RequestFailedDetail, type RequestFailure, RequestForm, type RequestIssue, type RequestIssueCode, type RequestReading, type RequestSendDetail, type RequestSentDetail, type RequestValue, RichTextField, SITE_CONFIG_FILE, type SiteConfig, type SiteConfigField, type SiteConfigReading, SlugField, TextField, TimeField, ToggleField, UrlField, WEEKDAYS, collectionAt, collectionFieldAt, contactsFields, editable, findRecord, hrefOf, imagePosition, isConsentGiven, isContentObject, isEmailAddress, isJsonObject, isPhoneNumber, isRecordId, isSiteId, isSlug, isTrapFilled, legalPagePathOf, linkTargetOf, newRecord, openingHoursField, productFields, readRequestEntries, readRequestValues, readSiteConfig, requestPageOf, requestsPathOf, safeHref, seoFields, slugFieldOf, slugOf, withRecordIds };
|
package/dist/schema.js
CHANGED
|
@@ -1,11 +1,23 @@
|
|
|
1
1
|
import {
|
|
2
|
+
CONSENT_REQUIRED_TEXT,
|
|
3
|
+
DEFAULT_LONG_TEXT_LENGTH,
|
|
4
|
+
DEFAULT_TEXT_LENGTH,
|
|
2
5
|
FIELD_PATH_ATTRIBUTE,
|
|
3
6
|
FIELD_PATH_SEPARATOR,
|
|
4
7
|
HOME_PAGE_PATH,
|
|
8
|
+
MAX_REQUEST_FIELD_LENGTH,
|
|
5
9
|
MAX_SLUG_LENGTH,
|
|
6
10
|
PAGE_PATH_SEPARATOR,
|
|
7
11
|
RECORD_ID_KEY,
|
|
8
12
|
RECORD_PLACEHOLDER,
|
|
13
|
+
REQUEST_CONSENT_KEY,
|
|
14
|
+
REQUEST_FAILED_EVENT,
|
|
15
|
+
REQUEST_FORM_KEY,
|
|
16
|
+
REQUEST_ISSUE_TEXTS,
|
|
17
|
+
REQUEST_PAGE_KEY,
|
|
18
|
+
REQUEST_SEND_EVENT,
|
|
19
|
+
REQUEST_SENT_EVENT,
|
|
20
|
+
REQUEST_TRAP_KEY,
|
|
9
21
|
REVEALED_ATTRIBUTE,
|
|
10
22
|
REVEAL_ATTRIBUTE,
|
|
11
23
|
REVEAL_EVENT,
|
|
@@ -27,22 +39,30 @@ import {
|
|
|
27
39
|
defaultValue,
|
|
28
40
|
defineSchema,
|
|
29
41
|
editable,
|
|
42
|
+
file,
|
|
30
43
|
findRecord,
|
|
31
44
|
formatFieldPath,
|
|
32
45
|
group,
|
|
33
46
|
hrefOf,
|
|
34
47
|
image,
|
|
35
48
|
imagePosition,
|
|
49
|
+
isConsentGiven,
|
|
36
50
|
isContentObject,
|
|
51
|
+
isEmailAddress,
|
|
52
|
+
isFormId,
|
|
37
53
|
isJsonObject,
|
|
54
|
+
isPhoneNumber,
|
|
38
55
|
isRecordId,
|
|
39
56
|
isRecordPagePath,
|
|
40
57
|
isSearchTextsGroup,
|
|
41
58
|
isSiteId,
|
|
42
59
|
isSlug,
|
|
60
|
+
isTrapFilled,
|
|
61
|
+
legalPagePathOf,
|
|
43
62
|
linesOf,
|
|
44
63
|
link,
|
|
45
64
|
linkTargetOf,
|
|
65
|
+
maxLengthOf,
|
|
46
66
|
newRecord,
|
|
47
67
|
normalizedLine,
|
|
48
68
|
number,
|
|
@@ -51,6 +71,9 @@ import {
|
|
|
51
71
|
plainTextOf,
|
|
52
72
|
productFields,
|
|
53
73
|
readFields,
|
|
74
|
+
readRequestEntries,
|
|
75
|
+
readRequestForm,
|
|
76
|
+
readRequestValues,
|
|
54
77
|
readRichText,
|
|
55
78
|
readSiteConfig,
|
|
56
79
|
readSiteDescription,
|
|
@@ -61,6 +84,14 @@ import {
|
|
|
61
84
|
recordPages,
|
|
62
85
|
reference,
|
|
63
86
|
references,
|
|
87
|
+
requestChoice,
|
|
88
|
+
requestEmail,
|
|
89
|
+
requestForm,
|
|
90
|
+
requestLongText,
|
|
91
|
+
requestPageOf,
|
|
92
|
+
requestPhone,
|
|
93
|
+
requestText,
|
|
94
|
+
requestsPathOf,
|
|
64
95
|
resolveFieldPath,
|
|
65
96
|
richText,
|
|
66
97
|
richTextOf,
|
|
@@ -74,15 +105,27 @@ import {
|
|
|
74
105
|
toggle,
|
|
75
106
|
url,
|
|
76
107
|
withRecordIds
|
|
77
|
-
} from "./chunk-
|
|
108
|
+
} from "./chunk-TMN7KG5M.js";
|
|
78
109
|
export {
|
|
110
|
+
CONSENT_REQUIRED_TEXT,
|
|
111
|
+
DEFAULT_LONG_TEXT_LENGTH,
|
|
112
|
+
DEFAULT_TEXT_LENGTH,
|
|
79
113
|
FIELD_PATH_ATTRIBUTE,
|
|
80
114
|
FIELD_PATH_SEPARATOR,
|
|
81
115
|
HOME_PAGE_PATH,
|
|
116
|
+
MAX_REQUEST_FIELD_LENGTH,
|
|
82
117
|
MAX_SLUG_LENGTH,
|
|
83
118
|
PAGE_PATH_SEPARATOR,
|
|
84
119
|
RECORD_ID_KEY,
|
|
85
120
|
RECORD_PLACEHOLDER,
|
|
121
|
+
REQUEST_CONSENT_KEY,
|
|
122
|
+
REQUEST_FAILED_EVENT,
|
|
123
|
+
REQUEST_FORM_KEY,
|
|
124
|
+
REQUEST_ISSUE_TEXTS,
|
|
125
|
+
REQUEST_PAGE_KEY,
|
|
126
|
+
REQUEST_SEND_EVENT,
|
|
127
|
+
REQUEST_SENT_EVENT,
|
|
128
|
+
REQUEST_TRAP_KEY,
|
|
86
129
|
REVEALED_ATTRIBUTE,
|
|
87
130
|
REVEAL_ATTRIBUTE,
|
|
88
131
|
REVEAL_EVENT,
|
|
@@ -104,22 +147,30 @@ export {
|
|
|
104
147
|
defaultValue,
|
|
105
148
|
defineSchema,
|
|
106
149
|
editable,
|
|
150
|
+
file,
|
|
107
151
|
findRecord,
|
|
108
152
|
formatFieldPath,
|
|
109
153
|
group,
|
|
110
154
|
hrefOf,
|
|
111
155
|
image,
|
|
112
156
|
imagePosition,
|
|
157
|
+
isConsentGiven,
|
|
113
158
|
isContentObject,
|
|
159
|
+
isEmailAddress,
|
|
160
|
+
isFormId,
|
|
114
161
|
isJsonObject,
|
|
162
|
+
isPhoneNumber,
|
|
115
163
|
isRecordId,
|
|
116
164
|
isRecordPagePath,
|
|
117
165
|
isSearchTextsGroup,
|
|
118
166
|
isSiteId,
|
|
119
167
|
isSlug,
|
|
168
|
+
isTrapFilled,
|
|
169
|
+
legalPagePathOf,
|
|
120
170
|
linesOf,
|
|
121
171
|
link,
|
|
122
172
|
linkTargetOf,
|
|
173
|
+
maxLengthOf,
|
|
123
174
|
newRecord,
|
|
124
175
|
normalizedLine,
|
|
125
176
|
number,
|
|
@@ -128,6 +179,9 @@ export {
|
|
|
128
179
|
plainTextOf,
|
|
129
180
|
productFields,
|
|
130
181
|
readFields,
|
|
182
|
+
readRequestEntries,
|
|
183
|
+
readRequestForm,
|
|
184
|
+
readRequestValues,
|
|
131
185
|
readRichText,
|
|
132
186
|
readSiteConfig,
|
|
133
187
|
readSiteDescription,
|
|
@@ -138,6 +192,14 @@ export {
|
|
|
138
192
|
recordPages,
|
|
139
193
|
reference,
|
|
140
194
|
references,
|
|
195
|
+
requestChoice,
|
|
196
|
+
requestEmail,
|
|
197
|
+
requestForm,
|
|
198
|
+
requestLongText,
|
|
199
|
+
requestPageOf,
|
|
200
|
+
requestPhone,
|
|
201
|
+
requestText,
|
|
202
|
+
requestsPathOf,
|
|
141
203
|
resolveFieldPath,
|
|
142
204
|
richText,
|
|
143
205
|
richTextOf,
|