@seamlet/astro 0.2.0 → 0.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/README.md +49 -0
- package/dist/bridge.d.ts +3 -3
- package/dist/bridge.js +2 -2
- package/dist/{chunk-2MRY5Z6U.js → chunk-GLXC5OLC.js} +262 -4
- package/dist/{chunk-LADJH7RU.js → chunk-XCBYYKWR.js} +1 -1
- package/dist/{content-CD5TXi4R.d.ts → content-C_WpiWBm.d.ts} +44 -6
- package/dist/{messages-BQSbv5YE.d.ts → messages-CBf5diaN.d.ts} +2 -2
- package/dist/{parse-content-CVoASb5i.d.ts → parse-content-9RIWhb6z.d.ts} +7 -2
- package/dist/protocol.d.ts +3 -3
- package/dist/protocol.js +2 -2
- package/dist/schema.d.ts +105 -6
- package/dist/schema.js +29 -3
- package/dist/site.d.ts +1 -1
- package/dist/site.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -90,6 +90,8 @@ The site's pages take their published content with `site.loadPublishedContent()`
|
|
|
90
90
|
| `toggle({ label })` | `true` or `false` | `false` |
|
|
91
91
|
| `choice({ label, options })` | the `value` of one option | `null` |
|
|
92
92
|
| `choices({ label, options })` | the `value`s of any number of options | `[]` |
|
|
93
|
+
| `reference({ label, collection })` | the `id` of a record of a collection of the schema | `null` |
|
|
94
|
+
| `references({ label, collection })` | the `id`s of any number of such records | `[]` |
|
|
93
95
|
| `group({ label, fields })` | named fields shown together | each field empty |
|
|
94
96
|
| `collection({ label, item, itemTitle? })` | a list of records of the same fields | `[]` |
|
|
95
97
|
|
|
@@ -113,6 +115,53 @@ item: { name: text({ label: "Название" }), isHidden: toggle({ label: "С
|
|
|
113
115
|
// content.practices.filter((practice) => !practice.isHidden)
|
|
114
116
|
```
|
|
115
117
|
|
|
118
|
+
A photo may carry the point that must stay in view when the site crops it, chosen in the editor: put `imagePosition(photo)` into its `object-position` (the middle when no point is chosen):
|
|
119
|
+
|
|
120
|
+
```astro
|
|
121
|
+
<img
|
|
122
|
+
src={photo.src}
|
|
123
|
+
alt={photo.alt}
|
|
124
|
+
style={`object-fit: cover; object-position: ${imagePosition(photo)}`}
|
|
125
|
+
/>
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Presets
|
|
129
|
+
|
|
130
|
+
Sets of fields almost every site has, edited the same way everywhere; they are plain groups and collections, rendered as the site likes:
|
|
131
|
+
|
|
132
|
+
- `seoFields()` — `title`, `description` and `image` of a page for search engines and links shared in messengers;
|
|
133
|
+
- `contactsFields()` — `phone` (a link), `address`, `map` (an address) and `messengers` (links);
|
|
134
|
+
- `openingHoursField()` — rows of `days` (`WEEKDAYS`), `opens` and `closes` times and a `note`.
|
|
135
|
+
|
|
136
|
+
Each takes `{ label }` to name it otherwise.
|
|
137
|
+
|
|
138
|
+
## Records and references
|
|
139
|
+
|
|
140
|
+
Every record of a collection has an `id` of its own, which never changes when records move, so a record has no field named `id`. The CMS gives ids to records that have none (`withRecordIds`), so a site's initial content may leave them out, unless something refers to those records.
|
|
141
|
+
|
|
142
|
+
A reference points at a record of another collection by its id: the teacher of a practice is chosen from the teachers, so renaming the teacher changes every practice at once. `collection` is where the collection is, its name or a path through groups:
|
|
143
|
+
|
|
144
|
+
```ts
|
|
145
|
+
const schema = defineSchema({
|
|
146
|
+
teachers: collection({
|
|
147
|
+
label: "Преподаватели",
|
|
148
|
+
itemTitle: "name",
|
|
149
|
+
item: { name: text({ label: "Имя" }) },
|
|
150
|
+
}),
|
|
151
|
+
practices: collection({
|
|
152
|
+
label: "Практики",
|
|
153
|
+
itemTitle: "name",
|
|
154
|
+
item: {
|
|
155
|
+
name: text({ label: "Название" }),
|
|
156
|
+
teacher: reference({ label: "Ведёт", collection: "teachers" }),
|
|
157
|
+
},
|
|
158
|
+
}),
|
|
159
|
+
});
|
|
160
|
+
// findRecord(content.teachers, practice.teacher)?.name
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
A reference to a record removed since is kept, with the issue `missing-record`: the content is not saved until the person picks another one or clears it.
|
|
164
|
+
|
|
116
165
|
## What the page hides
|
|
117
166
|
|
|
118
167
|
A field is edited where it is seen, so the editor opens what hides it when a person chooses it in the list of fields. A native `<details>` needs nothing: a click on its summary opens it in the editor too. A part the site hides and shows by itself (its own accordion, a step of a quiz, a dialog, a tab) gets the attribute `data-cms-reveal` (`REVEAL_ATTRIBUTE`). When a field inside it is chosen, the bridge sets `data-cms-revealed` on it and sends it the event `cms:reveal`, which bubbles; the site shows the part with CSS or with its own script:
|
package/dist/bridge.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { F as Fields } from './content-
|
|
2
|
-
import { P as PageMessage, E as EditorMessage } from './messages-
|
|
3
|
-
import './parse-content-
|
|
1
|
+
import { F as Fields } from './content-C_WpiWBm.js';
|
|
2
|
+
import { P as PageMessage, E as EditorMessage } from './messages-CBf5diaN.js';
|
|
3
|
+
import './parse-content-9RIWhb6z.js';
|
|
4
4
|
|
|
5
5
|
interface BridgeOptions {
|
|
6
6
|
/** The origin of the CMS whose editor may frame the page, such as `https://cms.example.com`. */
|
package/dist/bridge.js
CHANGED
|
@@ -5,13 +5,13 @@ import {
|
|
|
5
5
|
imageFieldAt,
|
|
6
6
|
readEditorMessage,
|
|
7
7
|
shortcutOf
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-XCBYYKWR.js";
|
|
9
9
|
import {
|
|
10
10
|
FIELD_PATH_ATTRIBUTE,
|
|
11
11
|
REVEALED_ATTRIBUTE,
|
|
12
12
|
REVEAL_ATTRIBUTE,
|
|
13
13
|
REVEAL_EVENT
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-GLXC5OLC.js";
|
|
15
15
|
|
|
16
16
|
// src/bridge/page-markers.ts
|
|
17
17
|
var MARKER_SELECTOR = `[${FIELD_PATH_ATTRIBUTE}]`;
|
|
@@ -32,6 +32,12 @@ function url(options) {
|
|
|
32
32
|
function time(options) {
|
|
33
33
|
return { kind: "time", ...options };
|
|
34
34
|
}
|
|
35
|
+
function reference(options) {
|
|
36
|
+
return { kind: "reference", ...options };
|
|
37
|
+
}
|
|
38
|
+
function references(options) {
|
|
39
|
+
return { kind: "references", ...options };
|
|
40
|
+
}
|
|
35
41
|
function group(options) {
|
|
36
42
|
return { kind: "group", ...options };
|
|
37
43
|
}
|
|
@@ -47,6 +53,7 @@ function defaultValue(field) {
|
|
|
47
53
|
case "toggle":
|
|
48
54
|
return false;
|
|
49
55
|
case "choices":
|
|
56
|
+
case "references":
|
|
50
57
|
return [];
|
|
51
58
|
case "number":
|
|
52
59
|
case "date":
|
|
@@ -55,6 +62,7 @@ function defaultValue(field) {
|
|
|
55
62
|
case "choice":
|
|
56
63
|
case "url":
|
|
57
64
|
case "time":
|
|
65
|
+
case "reference":
|
|
58
66
|
return null;
|
|
59
67
|
case "group":
|
|
60
68
|
return defaultContent(field.fields);
|
|
@@ -139,6 +147,132 @@ function withoutPrefix(address, prefix) {
|
|
|
139
147
|
return hasPrefix ? address.slice(prefix.length) : void 0;
|
|
140
148
|
}
|
|
141
149
|
|
|
150
|
+
// src/schema/record-ids.ts
|
|
151
|
+
var RECORD_ID_KEY = "id";
|
|
152
|
+
var RECORD_ID_PATTERN = /^[A-Za-z0-9_-]{1,64}$/u;
|
|
153
|
+
function isRecordId(value) {
|
|
154
|
+
return typeof value === "string" && RECORD_ID_PATTERN.test(value);
|
|
155
|
+
}
|
|
156
|
+
function newRecord(collection2, id) {
|
|
157
|
+
return { ...defaultContent(collection2.item), [RECORD_ID_KEY]: id };
|
|
158
|
+
}
|
|
159
|
+
function withRecordIds(schema, content, newId) {
|
|
160
|
+
return withIdsInFields(schema, content, newId);
|
|
161
|
+
}
|
|
162
|
+
var COLLECTION_PATH_SEPARATOR = ".";
|
|
163
|
+
function collectionAt(schema, content, path) {
|
|
164
|
+
return collectionIn(schema, content, path.split(COLLECTION_PATH_SEPARATOR));
|
|
165
|
+
}
|
|
166
|
+
function collectionIn(fields, content, names) {
|
|
167
|
+
const [name, ...rest] = names;
|
|
168
|
+
const field = name !== void 0 && Object.hasOwn(fields, name) ? fields[name] : void 0;
|
|
169
|
+
if (name === void 0 || field === void 0) return void 0;
|
|
170
|
+
const value = content[name];
|
|
171
|
+
if (rest.length === 0 && field.kind === "collection") {
|
|
172
|
+
const records = Array.isArray(value) ? value.filter(isContent) : [];
|
|
173
|
+
return { collection: field, records };
|
|
174
|
+
}
|
|
175
|
+
if (rest.length > 0 && field.kind === "group" && isContent(value)) {
|
|
176
|
+
return collectionIn(field.fields, value, rest);
|
|
177
|
+
}
|
|
178
|
+
return void 0;
|
|
179
|
+
}
|
|
180
|
+
function findRecord(records, id) {
|
|
181
|
+
if (id === null) return void 0;
|
|
182
|
+
return records.find((record) => record.id === id);
|
|
183
|
+
}
|
|
184
|
+
function withIdsInFields(fields, content, newId) {
|
|
185
|
+
const entries = Object.entries(content).map(([name, value]) => {
|
|
186
|
+
const field = Object.hasOwn(fields, name) ? fields[name] : void 0;
|
|
187
|
+
return [name, field === void 0 ? value : withIdsIn(field, value, newId)];
|
|
188
|
+
});
|
|
189
|
+
return Object.fromEntries(entries);
|
|
190
|
+
}
|
|
191
|
+
function withIdsIn(field, value, newId) {
|
|
192
|
+
if (field.kind === "group" && isContent(value)) {
|
|
193
|
+
return withIdsInFields(field.fields, value, newId);
|
|
194
|
+
}
|
|
195
|
+
if (field.kind === "collection" && Array.isArray(value)) {
|
|
196
|
+
return withIdsInRecords(field, value.filter(isContent), newId);
|
|
197
|
+
}
|
|
198
|
+
return value;
|
|
199
|
+
}
|
|
200
|
+
function withIdsInRecords(collection2, records, newId) {
|
|
201
|
+
const taken = /* @__PURE__ */ new Set();
|
|
202
|
+
return records.map((record) => {
|
|
203
|
+
const own = record[RECORD_ID_KEY];
|
|
204
|
+
const isOwnFree = isRecordId(own) && !taken.has(own);
|
|
205
|
+
const id = isOwnFree ? own : newId();
|
|
206
|
+
taken.add(id);
|
|
207
|
+
const fields = withIdsInFields(collection2.item, record, newId);
|
|
208
|
+
return { ...fields, [RECORD_ID_KEY]: id };
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
function isContent(value) {
|
|
212
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// src/schema/reference-checks.ts
|
|
216
|
+
function missingRecordIssues(schema, content) {
|
|
217
|
+
const idsOf = (collection2) => recordIdsAt(schema, content, collection2);
|
|
218
|
+
return issuesInFields(schema, content, [], idsOf);
|
|
219
|
+
}
|
|
220
|
+
function issuesInFields(fields, content, path, idsOf) {
|
|
221
|
+
return Object.entries(fields).flatMap(
|
|
222
|
+
([name, field]) => issuesInField(field, content[name], [...path, name], idsOf)
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
function issuesInField(field, value, path, idsOf) {
|
|
226
|
+
switch (field.kind) {
|
|
227
|
+
case "reference":
|
|
228
|
+
return missingIds(
|
|
229
|
+
typeof value === "string" ? [value] : [],
|
|
230
|
+
field,
|
|
231
|
+
path,
|
|
232
|
+
idsOf
|
|
233
|
+
);
|
|
234
|
+
case "references":
|
|
235
|
+
return missingIds(stringsOf(value), field, path, idsOf);
|
|
236
|
+
case "group":
|
|
237
|
+
return isContent2(value) ? issuesInFields(field.fields, value, path, idsOf) : [];
|
|
238
|
+
case "collection":
|
|
239
|
+
return recordsOf(value).flatMap(
|
|
240
|
+
(record, index) => issuesInFields(field.item, record, [...path, index], idsOf)
|
|
241
|
+
);
|
|
242
|
+
case "text":
|
|
243
|
+
case "number":
|
|
244
|
+
case "date":
|
|
245
|
+
case "image":
|
|
246
|
+
case "link":
|
|
247
|
+
case "toggle":
|
|
248
|
+
case "choice":
|
|
249
|
+
case "choices":
|
|
250
|
+
case "url":
|
|
251
|
+
case "time":
|
|
252
|
+
return [];
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
function missingIds(ids, field, path, idsOf) {
|
|
256
|
+
const known = idsOf(field.collection);
|
|
257
|
+
const missing = ids.filter((id) => !known.has(id));
|
|
258
|
+
return missing.map((id) => ({ path, code: "missing-record", id }));
|
|
259
|
+
}
|
|
260
|
+
function recordIdsAt(schema, content, path) {
|
|
261
|
+
const records = collectionAt(schema, content, path)?.records ?? [];
|
|
262
|
+
const ids = records.map((record) => record[RECORD_ID_KEY]);
|
|
263
|
+
return new Set(ids.filter((id) => typeof id === "string"));
|
|
264
|
+
}
|
|
265
|
+
function recordsOf(value) {
|
|
266
|
+
return Array.isArray(value) ? value.filter(isContent2) : [];
|
|
267
|
+
}
|
|
268
|
+
function stringsOf(value) {
|
|
269
|
+
const list = Array.isArray(value) ? value : [];
|
|
270
|
+
return list.filter((id) => typeof id === "string");
|
|
271
|
+
}
|
|
272
|
+
function isContent2(value) {
|
|
273
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
274
|
+
}
|
|
275
|
+
|
|
142
276
|
// src/schema/parse-content.ts
|
|
143
277
|
var DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/u;
|
|
144
278
|
var TIME_PATTERN = /^(?:[01]\d|2[0-3]):[0-5]\d$/u;
|
|
@@ -151,7 +285,11 @@ function countCharacters(text2) {
|
|
|
151
285
|
}
|
|
152
286
|
function parseContent(schema, input) {
|
|
153
287
|
const parsed = parseFields(schema, input, []);
|
|
154
|
-
|
|
288
|
+
const missingRecords = missingRecordIssues(schema, parsed.value);
|
|
289
|
+
return {
|
|
290
|
+
content: parsed.value,
|
|
291
|
+
issues: [...parsed.issues, ...missingRecords]
|
|
292
|
+
};
|
|
155
293
|
}
|
|
156
294
|
function parseFields(fields, input, path) {
|
|
157
295
|
if (!isRecord(input)) {
|
|
@@ -192,6 +330,10 @@ function parseField(field, input, path) {
|
|
|
192
330
|
return parseUrl(field, input, path);
|
|
193
331
|
case "time":
|
|
194
332
|
return parseTime(field, input, path);
|
|
333
|
+
case "reference":
|
|
334
|
+
return parseReference(field, input, path);
|
|
335
|
+
case "references":
|
|
336
|
+
return parseReferences(field, input, path);
|
|
195
337
|
case "group":
|
|
196
338
|
return parseFields(field.fields, input, path);
|
|
197
339
|
case "collection":
|
|
@@ -256,7 +398,8 @@ function parseImage(field, input, path) {
|
|
|
256
398
|
if (typeof src !== "string" || typeof alt !== "string") {
|
|
257
399
|
return invalidType(defaultValue(field), path);
|
|
258
400
|
}
|
|
259
|
-
const
|
|
401
|
+
const focus = isRecord(input) ? focusOf(input["focus"]) : void 0;
|
|
402
|
+
const image2 = focus === void 0 ? { src, alt } : { src, alt, focus };
|
|
260
403
|
if (src.trim() === "") {
|
|
261
404
|
return { value: image2, issues: [{ path, code: "missing-image-src" }] };
|
|
262
405
|
}
|
|
@@ -346,13 +489,48 @@ function parseCollection(field, input, path) {
|
|
|
346
489
|
}
|
|
347
490
|
const records = input;
|
|
348
491
|
const parsedRecords = records.map(
|
|
349
|
-
(record, index) =>
|
|
492
|
+
(record, index) => parseRecord(field, record, [...path, index])
|
|
350
493
|
);
|
|
351
494
|
return {
|
|
352
495
|
value: parsedRecords.map((parsed) => parsed.value),
|
|
353
496
|
issues: parsedRecords.flatMap((parsed) => parsed.issues)
|
|
354
497
|
};
|
|
355
498
|
}
|
|
499
|
+
function parseRecord(field, input, path) {
|
|
500
|
+
const parsed = parseFields(field.item, input, path);
|
|
501
|
+
const id = isRecord(input) ? input[RECORD_ID_KEY] : void 0;
|
|
502
|
+
if (!isRecordId(id)) return parsed;
|
|
503
|
+
return {
|
|
504
|
+
value: { ...parsed.value, [RECORD_ID_KEY]: id },
|
|
505
|
+
issues: parsed.issues
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
function parseReference(field, input, path) {
|
|
509
|
+
if (input === null) {
|
|
510
|
+
return valid(null);
|
|
511
|
+
}
|
|
512
|
+
if (!isRecordId(input)) {
|
|
513
|
+
return invalidType(defaultValue(field), path);
|
|
514
|
+
}
|
|
515
|
+
return valid(input);
|
|
516
|
+
}
|
|
517
|
+
function parseReferences(field, input, path) {
|
|
518
|
+
const isListOfIds = Array.isArray(input) && input.every((id) => isRecordId(id));
|
|
519
|
+
if (!isListOfIds) {
|
|
520
|
+
return invalidType(defaultValue(field), path);
|
|
521
|
+
}
|
|
522
|
+
const ids = [...new Set(input)];
|
|
523
|
+
return valid(ids);
|
|
524
|
+
}
|
|
525
|
+
function focusOf(input) {
|
|
526
|
+
if (!isRecord(input)) return void 0;
|
|
527
|
+
const { x, y } = input;
|
|
528
|
+
const isInside = isFraction(x) && isFraction(y);
|
|
529
|
+
return isInside ? { x, y } : void 0;
|
|
530
|
+
}
|
|
531
|
+
function isFraction(value) {
|
|
532
|
+
return typeof value === "number" && value >= 0 && value <= 1;
|
|
533
|
+
}
|
|
356
534
|
function isCalendarDate(value) {
|
|
357
535
|
if (!DATE_PATTERN.test(value)) {
|
|
358
536
|
return false;
|
|
@@ -420,6 +598,73 @@ var REVEAL_ATTRIBUTE = "data-cms-reveal";
|
|
|
420
598
|
var REVEALED_ATTRIBUTE = "data-cms-revealed";
|
|
421
599
|
var REVEAL_EVENT = "cms:reveal";
|
|
422
600
|
|
|
601
|
+
// src/schema/image-position.ts
|
|
602
|
+
var PERCENT = 100;
|
|
603
|
+
var STEPS_PER_PERCENT = 10;
|
|
604
|
+
var MIDDLE = 0.5;
|
|
605
|
+
function imagePosition(image2) {
|
|
606
|
+
const x = image2?.focus?.x ?? MIDDLE;
|
|
607
|
+
const y = image2?.focus?.y ?? MIDDLE;
|
|
608
|
+
return `${percentOf(x)} ${percentOf(y)}`;
|
|
609
|
+
}
|
|
610
|
+
function percentOf(fraction) {
|
|
611
|
+
const steps = Math.round(fraction * PERCENT * STEPS_PER_PERCENT);
|
|
612
|
+
const rounded = steps / STEPS_PER_PERCENT;
|
|
613
|
+
return `${String(rounded)}%`;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
// src/schema/presets.ts
|
|
617
|
+
function seoFields(options = {}) {
|
|
618
|
+
return group({
|
|
619
|
+
label: options.label ?? "\u041F\u043E\u0438\u0441\u043A\u043E\u0432\u0438\u043A\u0438 \u0438 \u0441\u043E\u0446\u0441\u0435\u0442\u0438",
|
|
620
|
+
fields: {
|
|
621
|
+
title: text({ label: "\u0417\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A \u0432 \u043F\u043E\u0438\u0441\u043A\u0435", maxLength: 60 }),
|
|
622
|
+
description: text({
|
|
623
|
+
label: "\u041E\u043F\u0438\u0441\u0430\u043D\u0438\u0435 \u0432 \u043F\u043E\u0438\u0441\u043A\u0435",
|
|
624
|
+
multiline: true,
|
|
625
|
+
maxLength: 160
|
|
626
|
+
}),
|
|
627
|
+
image: image({ label: "\u041A\u0430\u0440\u0442\u0438\u043D\u043A\u0430 \u0434\u043B\u044F \u0441\u043E\u0446\u0441\u0435\u0442\u0435\u0439" })
|
|
628
|
+
}
|
|
629
|
+
});
|
|
630
|
+
}
|
|
631
|
+
function contactsFields(options = {}) {
|
|
632
|
+
return group({
|
|
633
|
+
label: options.label ?? "\u041A\u043E\u043D\u0442\u0430\u043A\u0442\u044B",
|
|
634
|
+
fields: {
|
|
635
|
+
phone: link({ label: "\u0422\u0435\u043B\u0435\u0444\u043E\u043D" }),
|
|
636
|
+
address: text({ label: "\u0410\u0434\u0440\u0435\u0441", multiline: true }),
|
|
637
|
+
map: url({ label: "\u0421\u0441\u044B\u043B\u043A\u0430 \u043D\u0430 \u043A\u0430\u0440\u0442\u0443" }),
|
|
638
|
+
messengers: collection({
|
|
639
|
+
label: "\u041C\u0435\u0441\u0441\u0435\u043D\u0434\u0436\u0435\u0440\u044B \u0438 \u0441\u043E\u0446\u0441\u0435\u0442\u0438",
|
|
640
|
+
itemTitle: "link",
|
|
641
|
+
item: { link: link({ label: "\u0421\u0441\u044B\u043B\u043A\u0430" }) }
|
|
642
|
+
})
|
|
643
|
+
}
|
|
644
|
+
});
|
|
645
|
+
}
|
|
646
|
+
var WEEKDAYS = [
|
|
647
|
+
{ value: "mon", label: "\u041F\u043D" },
|
|
648
|
+
{ value: "tue", label: "\u0412\u0442" },
|
|
649
|
+
{ value: "wed", label: "\u0421\u0440" },
|
|
650
|
+
{ value: "thu", label: "\u0427\u0442" },
|
|
651
|
+
{ value: "fri", label: "\u041F\u0442" },
|
|
652
|
+
{ value: "sat", label: "\u0421\u0431" },
|
|
653
|
+
{ value: "sun", label: "\u0412\u0441" }
|
|
654
|
+
];
|
|
655
|
+
function openingHoursField(options = {}) {
|
|
656
|
+
return collection({
|
|
657
|
+
label: options.label ?? "\u0427\u0430\u0441\u044B \u0440\u0430\u0431\u043E\u0442\u044B",
|
|
658
|
+
itemTitle: "note",
|
|
659
|
+
item: {
|
|
660
|
+
days: choices({ label: "\u0414\u043D\u0438", options: WEEKDAYS }),
|
|
661
|
+
opens: time({ label: "\u041E\u0442\u043A\u0440\u044B\u0432\u0430\u0435\u0442\u0441\u044F" }),
|
|
662
|
+
closes: time({ label: "\u0417\u0430\u043A\u0440\u044B\u0432\u0430\u0435\u0442\u0441\u044F" }),
|
|
663
|
+
note: text({ label: "\u041F\u043E\u0434\u043F\u0438\u0441\u044C", maxLength: 40 })
|
|
664
|
+
}
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
|
|
423
668
|
export {
|
|
424
669
|
defineSchema,
|
|
425
670
|
text,
|
|
@@ -432,12 +677,20 @@ export {
|
|
|
432
677
|
choices,
|
|
433
678
|
url,
|
|
434
679
|
time,
|
|
680
|
+
reference,
|
|
681
|
+
references,
|
|
435
682
|
group,
|
|
436
683
|
collection,
|
|
437
684
|
defaultValue,
|
|
438
685
|
defaultContent,
|
|
439
686
|
linkTargetOf,
|
|
440
687
|
hrefOf,
|
|
688
|
+
RECORD_ID_KEY,
|
|
689
|
+
isRecordId,
|
|
690
|
+
newRecord,
|
|
691
|
+
withRecordIds,
|
|
692
|
+
collectionAt,
|
|
693
|
+
findRecord,
|
|
441
694
|
formatFieldPath,
|
|
442
695
|
countCharacters,
|
|
443
696
|
parseContent,
|
|
@@ -446,5 +699,10 @@ export {
|
|
|
446
699
|
resolveFieldPath,
|
|
447
700
|
REVEAL_ATTRIBUTE,
|
|
448
701
|
REVEALED_ATTRIBUTE,
|
|
449
|
-
REVEAL_EVENT
|
|
702
|
+
REVEAL_EVENT,
|
|
703
|
+
imagePosition,
|
|
704
|
+
seoFields,
|
|
705
|
+
contactsFields,
|
|
706
|
+
WEEKDAYS,
|
|
707
|
+
openingHoursField
|
|
450
708
|
};
|
|
@@ -64,26 +64,48 @@ interface TimeField {
|
|
|
64
64
|
readonly kind: "time";
|
|
65
65
|
readonly label: string;
|
|
66
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* A record of a collection of the schema, by its id: the teacher of a practice. `collection` is
|
|
69
|
+
* where that collection is, its name or a path through groups: "teachers", "studio.teachers".
|
|
70
|
+
*/
|
|
71
|
+
interface ReferenceField {
|
|
72
|
+
readonly kind: "reference";
|
|
73
|
+
readonly label: string;
|
|
74
|
+
readonly collection: string;
|
|
75
|
+
}
|
|
76
|
+
/** Any number of records of a collection of the schema, by their ids: the practices a teacher leads. */
|
|
77
|
+
interface ReferencesField {
|
|
78
|
+
readonly kind: "references";
|
|
79
|
+
readonly label: string;
|
|
80
|
+
readonly collection: string;
|
|
81
|
+
}
|
|
67
82
|
/** Named fields shown and stored together, for example the first screen of a page. */
|
|
68
83
|
interface GroupField<F extends Fields = Fields> {
|
|
69
84
|
readonly kind: "group";
|
|
70
85
|
readonly label: string;
|
|
71
86
|
readonly fields: F;
|
|
72
87
|
}
|
|
73
|
-
/**
|
|
74
|
-
|
|
88
|
+
/**
|
|
89
|
+
* A list of records of the same shape, for example the items of a menu. Every record also has an
|
|
90
|
+
* `id` of its own, which never changes (see withRecordIds), so a record has no field named `id`.
|
|
91
|
+
*/
|
|
92
|
+
interface CollectionField<F extends RecordFields = RecordFields> {
|
|
75
93
|
readonly kind: "collection";
|
|
76
94
|
readonly label: string;
|
|
77
95
|
readonly item: F;
|
|
78
96
|
/** The field of a record that names it in the editor: a text field, or a link by its text. */
|
|
79
97
|
readonly itemTitle?: keyof F & string;
|
|
80
98
|
}
|
|
81
|
-
type Field = TextField | NumberField | DateField | ImageField | LinkField | ToggleField | ChoiceField | ChoicesField | UrlField | TimeField | GroupField | CollectionField;
|
|
99
|
+
type Field = TextField | NumberField | DateField | ImageField | LinkField | ToggleField | ChoiceField | ChoicesField | UrlField | TimeField | ReferenceField | ReferencesField | GroupField | CollectionField;
|
|
82
100
|
type FieldKind = Field["kind"];
|
|
83
101
|
/** Field names to fields; the order of the keys is the order of the form. */
|
|
84
102
|
interface Fields {
|
|
85
103
|
readonly [name: string]: Field;
|
|
86
104
|
}
|
|
105
|
+
/** The fields of a record of a collection: any fields but `id`, which is the record's own. */
|
|
106
|
+
type RecordFields = Fields & {
|
|
107
|
+
readonly id?: never;
|
|
108
|
+
};
|
|
87
109
|
type FieldOptions<F extends Field> = Omit<F, "kind">;
|
|
88
110
|
/** The root of a site's schema. Only checks the shape and keeps the literal types. */
|
|
89
111
|
declare function defineSchema<F extends Fields>(fields: F): F;
|
|
@@ -98,12 +120,21 @@ declare function choice<const O extends readonly ChoiceOption[]>(options: FieldO
|
|
|
98
120
|
declare function choices<const O extends readonly ChoiceOption[]>(options: FieldOptions<ChoicesField<O>>): ChoicesField<O>;
|
|
99
121
|
declare function url(options: FieldOptions<UrlField>): UrlField;
|
|
100
122
|
declare function time(options: FieldOptions<TimeField>): TimeField;
|
|
123
|
+
declare function reference(options: FieldOptions<ReferenceField>): ReferenceField;
|
|
124
|
+
declare function references(options: FieldOptions<ReferencesField>): ReferencesField;
|
|
101
125
|
declare function group<F extends Fields>(options: FieldOptions<GroupField<F>>): GroupField<F>;
|
|
102
|
-
declare function collection<F extends
|
|
126
|
+
declare function collection<F extends RecordFields>(options: FieldOptions<CollectionField<F>>): CollectionField<F>;
|
|
103
127
|
|
|
128
|
+
/** The point of a photo that must stay in view when a site crops it: 0 to 1 from the left and the top. */
|
|
129
|
+
interface ImageFocus {
|
|
130
|
+
readonly x: number;
|
|
131
|
+
readonly y: number;
|
|
132
|
+
}
|
|
104
133
|
interface ImageValue {
|
|
105
134
|
readonly src: string;
|
|
106
135
|
readonly alt: string;
|
|
136
|
+
/** Unset: the middle of the photo (see imagePosition). */
|
|
137
|
+
readonly focus?: ImageFocus;
|
|
107
138
|
}
|
|
108
139
|
interface LinkValue {
|
|
109
140
|
readonly text: string;
|
|
@@ -114,7 +145,14 @@ interface LinkValue {
|
|
|
114
145
|
* The value of each field. A text can be empty (""), the other scalar fields can be unset (null):
|
|
115
146
|
* content is filled in by people, so a site must be ready for a missing price or date.
|
|
116
147
|
*/
|
|
117
|
-
type ValueOf<F extends Field> = F extends TextField ? string : F extends NumberField ? number | null : F extends DateField ? string | null : F extends ImageField ? ImageValue | null : F extends LinkField ? LinkValue | null : F extends ToggleField ? boolean : F extends ChoiceField<infer Options> ? OptionValue<Options> | null : F extends ChoicesField<infer Options> ? readonly OptionValue<Options>[] : F extends UrlField ? string | null : F extends TimeField ? string | null : F extends GroupField<infer Group> ? ContentOf<Group> : F extends CollectionField<infer Item> ? readonly
|
|
148
|
+
type ValueOf<F extends Field> = F extends TextField ? string : F extends NumberField ? number | null : F extends DateField ? string | null : F extends ImageField ? ImageValue | null : F extends LinkField ? LinkValue | null : F extends ToggleField ? boolean : F extends ChoiceField<infer Options> ? OptionValue<Options> | null : F extends ChoicesField<infer Options> ? readonly OptionValue<Options>[] : F extends UrlField ? string | null : F extends TimeField ? string | null : F extends ReferenceField ? string | null : F extends ReferencesField ? readonly string[] : F extends GroupField<infer Group> ? ContentOf<Group> : F extends CollectionField<infer Item> ? readonly RecordOf<Item>[] : never;
|
|
149
|
+
/**
|
|
150
|
+
* A record of a collection: its fields and its id. The id is missing only in content no editor has
|
|
151
|
+
* saved yet, such as a site's initial content (see withRecordIds).
|
|
152
|
+
*/
|
|
153
|
+
type RecordOf<F extends RecordFields> = ContentOf<F> & {
|
|
154
|
+
readonly id?: string;
|
|
155
|
+
};
|
|
118
156
|
/** The values a list of options stores: `"soft" | "active"` for options with those values. */
|
|
119
157
|
type OptionValue<O extends readonly ChoiceOption[]> = O[number]["value"];
|
|
120
158
|
/** The content a schema describes: `ContentOf<typeof schema>` is the type a site renders. */
|
|
@@ -129,4 +167,4 @@ type FieldValue = string | number | boolean | null | readonly string[] | ImageVa
|
|
|
129
167
|
declare function defaultValue(field: Field): FieldValue;
|
|
130
168
|
declare function defaultContent(fields: Fields): Content;
|
|
131
169
|
|
|
132
|
-
export {
|
|
170
|
+
export { number as A, reference as B, type ContentOf as C, type DateField as D, references as E, type Fields as F, type GroupField as G, text as H, type ImageField as I, time as J, toggle as K, type LinkValue as L, url as M, type NumberField as N, type OptionValue as O, type RecordFields as R, type TextField as T, type UrlField as U, type ValueOf as V, type Content as a, type ImageValue as b, type Field as c, type CollectionField as d, type LinkField as e, type ChoicesField as f, type TimeField as g, type ChoiceField as h, type ChoiceOption as i, type FieldKind as j, type FieldValue as k, type ImageFocus as l, type RecordOf as m, type ReferenceField as n, type ReferencesField as o, type ToggleField as p, choice as q, choices as r, collection as s, date as t, defaultContent as u, defaultValue as v, defineSchema as w, group as x, image as y, link as z };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { F as Fields, a as Content } from './content-
|
|
2
|
-
import { F as FieldPath } from './parse-content-
|
|
1
|
+
import { F as Fields, a as Content } from './content-C_WpiWBm.js';
|
|
2
|
+
import { F as FieldPath } from './parse-content-9RIWhb6z.js';
|
|
3
3
|
|
|
4
4
|
interface Box {
|
|
5
5
|
readonly top: number;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { F as Fields, C as ContentOf } from './content-
|
|
1
|
+
import { F as Fields, C as ContentOf } from './content-C_WpiWBm.js';
|
|
2
2
|
|
|
3
3
|
/** Where a value lives in the content: field names and, inside a collection, record indexes. */
|
|
4
4
|
type FieldPath = readonly (string | number)[];
|
|
@@ -39,6 +39,10 @@ type ContentIssue = {
|
|
|
39
39
|
readonly path: FieldPath;
|
|
40
40
|
readonly code: "unknown-choice";
|
|
41
41
|
readonly value: string;
|
|
42
|
+
} | {
|
|
43
|
+
readonly path: FieldPath;
|
|
44
|
+
readonly code: "missing-record";
|
|
45
|
+
readonly id: string;
|
|
42
46
|
};
|
|
43
47
|
interface ParsedContent<C> {
|
|
44
48
|
readonly content: C;
|
|
@@ -56,7 +60,8 @@ declare function countCharacters(text: string): number;
|
|
|
56
60
|
* - a value of the wrong type or format gets the default too, and an issue;
|
|
57
61
|
* - a value of the right type that breaks a rule of its field (too long, below the minimum) is
|
|
58
62
|
* kept, with an issue: nothing a person typed is lost;
|
|
59
|
-
* - keys the schema does not know are dropped
|
|
63
|
+
* - keys the schema does not know are dropped; a record keeps its id (see withRecordIds);
|
|
64
|
+
* - a reference to a record its collection does not have (removed since) is kept, with an issue.
|
|
60
65
|
* Content with issues is valid to show and edit, but not to save.
|
|
61
66
|
*/
|
|
62
67
|
declare function parseContent<F extends Fields>(schema: F, input: unknown): ParsedContent<ContentOf<F>>;
|
package/dist/protocol.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { B as Box, a as EditorKey, E as EditorMessage, I as InlineEditingOutcome, L as LinkBox, M as MarkerBox, b as PROTOCOL_VERSION, c as PageLayout, P as PageMessage, d as Point, S as Shortcut, V as Viewport, r as readEditorMessage, e as readPageMessage, s as shortcutOf } from './messages-
|
|
2
|
-
import { F as Fields, I as ImageField } from './content-
|
|
3
|
-
import { F as FieldPath } from './parse-content-
|
|
1
|
+
export { B as Box, a as EditorKey, E as EditorMessage, I as InlineEditingOutcome, L as LinkBox, M as MarkerBox, b as PROTOCOL_VERSION, c as PageLayout, P as PageMessage, d as Point, S as Shortcut, V as Viewport, r as readEditorMessage, e as readPageMessage, s as shortcutOf } from './messages-CBf5diaN.js';
|
|
2
|
+
import { F as Fields, I as ImageField } from './content-C_WpiWBm.js';
|
|
3
|
+
import { F as FieldPath } from './parse-content-9RIWhb6z.js';
|
|
4
4
|
|
|
5
5
|
declare function carriesFiles(event: DragEvent): boolean;
|
|
6
6
|
|
package/dist/protocol.js
CHANGED
package/dist/schema.d.ts
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
import { b as ImageValue, L as LinkValue, c as Field, d as CollectionField, F as Fields } from './content-
|
|
2
|
-
export {
|
|
3
|
-
import { F as FieldPath } from './parse-content-
|
|
4
|
-
export { C as ContentIssue, P as ParsedContent, c as countCharacters, f as formatFieldPath, p as parseContent } from './parse-content-
|
|
1
|
+
import { b as ImageValue, L as LinkValue, c as Field, d as CollectionField, F as Fields, a as Content, R as RecordFields, C as ContentOf, G as GroupField, e as LinkField, T as TextField, U as UrlField, f as ChoicesField, g as TimeField, I as ImageField } from './content-C_WpiWBm.js';
|
|
2
|
+
export { h as ChoiceField, i as ChoiceOption, D as DateField, j as FieldKind, k as FieldValue, l as ImageFocus, N as NumberField, O as OptionValue, m as RecordOf, n as ReferenceField, o as ReferencesField, p as ToggleField, V as ValueOf, q as choice, r as choices, s as collection, t as date, u as defaultContent, v as defaultValue, w as defineSchema, x as group, y as image, z as link, A as number, B as reference, E as references, H as text, J as time, K as toggle, M as url } from './content-C_WpiWBm.js';
|
|
3
|
+
import { F as FieldPath } from './parse-content-9RIWhb6z.js';
|
|
4
|
+
export { C as ContentIssue, P as ParsedContent, c as countCharacters, f as formatFieldPath, p as parseContent } from './parse-content-9RIWhb6z.js';
|
|
5
5
|
|
|
6
6
|
declare const FIELD_PATH_ATTRIBUTE = "data-cms-path";
|
|
7
7
|
interface FieldMarker {
|
|
8
8
|
readonly [FIELD_PATH_ATTRIBUTE]: string;
|
|
9
9
|
}
|
|
10
|
+
type Leaf = string | number | boolean | null | ImageValue | LinkValue | readonly string[];
|
|
10
11
|
/**
|
|
11
12
|
* Every path in content of type C, as a tuple: ["hero"], ["hero", "title"], ["menu", 2],
|
|
12
13
|
* ["menu", 2, "price"]. Scalars, images and links are leaves: an image is one field, not two.
|
|
13
14
|
*/
|
|
14
|
-
type ContentPath<C> = C extends readonly (infer Record)[] ? [number] | [number, ...ContentPath<Record>] :
|
|
15
|
+
type ContentPath<C> = C extends Leaf ? never : C extends readonly (infer Record)[] ? [number] | [number, ...ContentPath<Record>] : {
|
|
15
16
|
[Name in keyof C & string]: [Name] | [Name, ...ContentPath<C[Name]>];
|
|
16
17
|
}[keyof C & string];
|
|
17
18
|
/**
|
|
@@ -39,6 +40,29 @@ type FieldTarget = {
|
|
|
39
40
|
*/
|
|
40
41
|
declare function resolveFieldPath(schema: Fields, text: string): FieldTarget | undefined;
|
|
41
42
|
|
|
43
|
+
declare const RECORD_ID_KEY = "id";
|
|
44
|
+
declare function isRecordId(value: unknown): value is string;
|
|
45
|
+
/** A new record of a collection: its fields empty, its id the given one. */
|
|
46
|
+
declare function newRecord<F extends RecordFields>(collection: CollectionField<F>, id: string): Content;
|
|
47
|
+
/**
|
|
48
|
+
* The content with an id given to every record that has none, and a new one to a record whose id
|
|
49
|
+
* another record of its collection already has (a copy). Records with ids of their own keep them.
|
|
50
|
+
*/
|
|
51
|
+
declare function withRecordIds<F extends Fields>(schema: F, content: ContentOf<F>, newId: () => string): ContentOf<F>;
|
|
52
|
+
interface CollectionRecords {
|
|
53
|
+
readonly collection: CollectionField;
|
|
54
|
+
readonly records: readonly Content[];
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The collection a reference points at, `"teachers"` or `"studio.teachers"` through groups, with
|
|
58
|
+
* its records in the content; undefined when the schema has no collection there.
|
|
59
|
+
*/
|
|
60
|
+
declare function collectionAt(schema: Fields, content: Content, path: string): CollectionRecords | undefined;
|
|
61
|
+
/** The record of the list with the id, if it is there. */
|
|
62
|
+
declare function findRecord<R extends {
|
|
63
|
+
readonly id?: string;
|
|
64
|
+
}>(records: readonly R[], id: string | null): R | undefined;
|
|
65
|
+
|
|
42
66
|
/** On the element the site hides and shows itself: `<div data-cms-reveal hidden>`. */
|
|
43
67
|
declare const REVEAL_ATTRIBUTE = "data-cms-reveal";
|
|
44
68
|
/** Set by the bridge on a part it revealed; a site can show it with CSS alone. */
|
|
@@ -72,4 +96,79 @@ declare function linkTargetOf(href: string): LinkTarget | undefined;
|
|
|
72
96
|
*/
|
|
73
97
|
declare function hrefOf(target: LinkTarget): string;
|
|
74
98
|
|
|
75
|
-
|
|
99
|
+
/** `object-position` of the photo: "50% 30%"; the middle when no point is chosen. */
|
|
100
|
+
declare function imagePosition(image: ImageValue | null): string;
|
|
101
|
+
|
|
102
|
+
/** What search engines and a link shared in a messenger show: one per page. */
|
|
103
|
+
declare function seoFields(options?: {
|
|
104
|
+
readonly label?: string;
|
|
105
|
+
}): GroupField<{
|
|
106
|
+
title: TextField;
|
|
107
|
+
description: TextField;
|
|
108
|
+
image: ImageField;
|
|
109
|
+
}>;
|
|
110
|
+
/** How to reach the business: the phone, the address with a map, the messengers. */
|
|
111
|
+
declare function contactsFields(options?: {
|
|
112
|
+
readonly label?: string;
|
|
113
|
+
}): GroupField<{
|
|
114
|
+
phone: LinkField;
|
|
115
|
+
address: TextField;
|
|
116
|
+
map: UrlField;
|
|
117
|
+
messengers: CollectionField<{
|
|
118
|
+
link: LinkField;
|
|
119
|
+
}>;
|
|
120
|
+
}>;
|
|
121
|
+
declare const WEEKDAYS: readonly [{
|
|
122
|
+
readonly value: "mon";
|
|
123
|
+
readonly label: "Пн";
|
|
124
|
+
}, {
|
|
125
|
+
readonly value: "tue";
|
|
126
|
+
readonly label: "Вт";
|
|
127
|
+
}, {
|
|
128
|
+
readonly value: "wed";
|
|
129
|
+
readonly label: "Ср";
|
|
130
|
+
}, {
|
|
131
|
+
readonly value: "thu";
|
|
132
|
+
readonly label: "Чт";
|
|
133
|
+
}, {
|
|
134
|
+
readonly value: "fri";
|
|
135
|
+
readonly label: "Пт";
|
|
136
|
+
}, {
|
|
137
|
+
readonly value: "sat";
|
|
138
|
+
readonly label: "Сб";
|
|
139
|
+
}, {
|
|
140
|
+
readonly value: "sun";
|
|
141
|
+
readonly label: "Вс";
|
|
142
|
+
}];
|
|
143
|
+
/** When the business is open: rows of days with the same hours, «Пн–Пт 08:00–21:00». */
|
|
144
|
+
declare function openingHoursField(options?: {
|
|
145
|
+
readonly label?: string;
|
|
146
|
+
}): CollectionField<{
|
|
147
|
+
days: ChoicesField<readonly [{
|
|
148
|
+
readonly value: "mon";
|
|
149
|
+
readonly label: "Пн";
|
|
150
|
+
}, {
|
|
151
|
+
readonly value: "tue";
|
|
152
|
+
readonly label: "Вт";
|
|
153
|
+
}, {
|
|
154
|
+
readonly value: "wed";
|
|
155
|
+
readonly label: "Ср";
|
|
156
|
+
}, {
|
|
157
|
+
readonly value: "thu";
|
|
158
|
+
readonly label: "Чт";
|
|
159
|
+
}, {
|
|
160
|
+
readonly value: "fri";
|
|
161
|
+
readonly label: "Пт";
|
|
162
|
+
}, {
|
|
163
|
+
readonly value: "sat";
|
|
164
|
+
readonly label: "Сб";
|
|
165
|
+
}, {
|
|
166
|
+
readonly value: "sun";
|
|
167
|
+
readonly label: "Вс";
|
|
168
|
+
}]>;
|
|
169
|
+
opens: TimeField;
|
|
170
|
+
closes: TimeField;
|
|
171
|
+
note: TextField;
|
|
172
|
+
}>;
|
|
173
|
+
|
|
174
|
+
export { ChoicesField, CollectionField, type CollectionRecords, Content, ContentOf, type ContentPath, FIELD_PATH_ATTRIBUTE, Field, type FieldMarker, FieldPath, type FieldTarget, Fields, GroupField, ImageField, ImageValue, LinkField, type LinkKind, type LinkTarget, LinkValue, RECORD_ID_KEY, REVEALED_ATTRIBUTE, REVEAL_ATTRIBUTE, REVEAL_EVENT, RecordFields, TextField, TimeField, UrlField, WEEKDAYS, collectionAt, contactsFields, editable, findRecord, hrefOf, imagePosition, isRecordId, linkTargetOf, newRecord, openingHoursField, resolveFieldPath, seoFields, withRecordIds };
|
package/dist/schema.js
CHANGED
|
@@ -1,56 +1,82 @@
|
|
|
1
1
|
import {
|
|
2
2
|
FIELD_PATH_ATTRIBUTE,
|
|
3
|
+
RECORD_ID_KEY,
|
|
3
4
|
REVEALED_ATTRIBUTE,
|
|
4
5
|
REVEAL_ATTRIBUTE,
|
|
5
6
|
REVEAL_EVENT,
|
|
7
|
+
WEEKDAYS,
|
|
6
8
|
choice,
|
|
7
9
|
choices,
|
|
8
10
|
collection,
|
|
11
|
+
collectionAt,
|
|
12
|
+
contactsFields,
|
|
9
13
|
countCharacters,
|
|
10
14
|
date,
|
|
11
15
|
defaultContent,
|
|
12
16
|
defaultValue,
|
|
13
17
|
defineSchema,
|
|
14
18
|
editable,
|
|
19
|
+
findRecord,
|
|
15
20
|
formatFieldPath,
|
|
16
21
|
group,
|
|
17
22
|
hrefOf,
|
|
18
23
|
image,
|
|
24
|
+
imagePosition,
|
|
25
|
+
isRecordId,
|
|
19
26
|
link,
|
|
20
27
|
linkTargetOf,
|
|
28
|
+
newRecord,
|
|
21
29
|
number,
|
|
30
|
+
openingHoursField,
|
|
22
31
|
parseContent,
|
|
32
|
+
reference,
|
|
33
|
+
references,
|
|
23
34
|
resolveFieldPath,
|
|
35
|
+
seoFields,
|
|
24
36
|
text,
|
|
25
37
|
time,
|
|
26
38
|
toggle,
|
|
27
|
-
url
|
|
28
|
-
|
|
39
|
+
url,
|
|
40
|
+
withRecordIds
|
|
41
|
+
} from "./chunk-GLXC5OLC.js";
|
|
29
42
|
export {
|
|
30
43
|
FIELD_PATH_ATTRIBUTE,
|
|
44
|
+
RECORD_ID_KEY,
|
|
31
45
|
REVEALED_ATTRIBUTE,
|
|
32
46
|
REVEAL_ATTRIBUTE,
|
|
33
47
|
REVEAL_EVENT,
|
|
48
|
+
WEEKDAYS,
|
|
34
49
|
choice,
|
|
35
50
|
choices,
|
|
36
51
|
collection,
|
|
52
|
+
collectionAt,
|
|
53
|
+
contactsFields,
|
|
37
54
|
countCharacters,
|
|
38
55
|
date,
|
|
39
56
|
defaultContent,
|
|
40
57
|
defaultValue,
|
|
41
58
|
defineSchema,
|
|
42
59
|
editable,
|
|
60
|
+
findRecord,
|
|
43
61
|
formatFieldPath,
|
|
44
62
|
group,
|
|
45
63
|
hrefOf,
|
|
46
64
|
image,
|
|
65
|
+
imagePosition,
|
|
66
|
+
isRecordId,
|
|
47
67
|
link,
|
|
48
68
|
linkTargetOf,
|
|
69
|
+
newRecord,
|
|
49
70
|
number,
|
|
71
|
+
openingHoursField,
|
|
50
72
|
parseContent,
|
|
73
|
+
reference,
|
|
74
|
+
references,
|
|
51
75
|
resolveFieldPath,
|
|
76
|
+
seoFields,
|
|
52
77
|
text,
|
|
53
78
|
time,
|
|
54
79
|
toggle,
|
|
55
|
-
url
|
|
80
|
+
url,
|
|
81
|
+
withRecordIds
|
|
56
82
|
};
|
package/dist/site.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AstroComponentFactory } from 'astro/runtime/server/index.js';
|
|
2
|
-
import { F as Fields, C as ContentOf } from './content-
|
|
2
|
+
import { F as Fields, C as ContentOf } from './content-C_WpiWBm.js';
|
|
3
3
|
|
|
4
4
|
interface SeamletSiteDefinition<F extends Fields> {
|
|
5
5
|
/** The site's address in the CMS: `/sites/<id>`. */
|
package/dist/site.js
CHANGED
package/package.json
CHANGED