@protobase/schema 0.14.0 → 0.14.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/index.d.ts +2 -2
- package/dist/internal.d.ts +2 -2
- package/dist/internal.js +2 -2
- package/dist/model.d.ts +49 -1
- package/dist/view-displays.d.ts +8 -2
- package/dist/view-displays.js +9 -3
- package/dist/view.d.ts +16 -2
- package/dist/view.js +23 -2
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FileOptions, FileProcessor, FileProcessorInput, ImageFormat, ImageVariant, ImageVariantOptions, imageFormats } from "./files/file-options.js";
|
|
2
|
-
import { ActionModel, ActionRun, AppAddress, BadgeShape, BottomBarItemModel, BottomBarModel, CardPhotosModel, ChartGranularity, ChartModel, ChartRange, CheckedFilter, CompareOp, CustomSectionModel, DatePreset, DurationLiteral, DurationUnit, EventModel, EventOperation, FieldFormat, FieldModel, FieldPath, FieldType, FieldViewModel, FieldWidgetModel, FileFieldModel, FilterError, FilterErrorCode, FilterExpr, FilterLayout, FilterOf, FilterValue, FilterWidgetModel, JsonValue, KeyValue, LayoutItemModel, ListDisplayModel, ListModel, ListQuery, Literal, MapSectionModel, MapView, NavModel, NavRecentModel, NowValue, OrderByItem, RelatedModel, ResourceModel, SaveFeedback, SearchMatch, SearchResultModel, SortSpec, Span, StatusTone, UserMenuItemModel, UserMenuModel, ViewModel } from "./model.js";
|
|
2
|
+
import { ActionModel, ActionRun, AppAddress, BadgeShape, BottomBarItemModel, BottomBarModel, CardFavoriteModel, CardPhotosModel, ChartGranularity, ChartModel, ChartRange, CheckedFilter, CompareOp, CustomSectionModel, DatePreset, DurationLiteral, DurationUnit, EventModel, EventOperation, FieldFormat, FieldModel, FieldPath, FieldType, FieldViewModel, FieldWidgetModel, FileFieldModel, FilterError, FilterErrorCode, FilterExpr, FilterLayout, FilterOf, FilterValue, FilterWidgetModel, JsonValue, KeyValue, LayoutItemModel, ListDisplayModel, ListModel, ListQuery, Literal, MapSectionModel, MapView, NavModel, NavRecentModel, NowValue, OrderByItem, RelatedModel, ResourceModel, SaveFeedback, SearchMatch, SearchResultModel, SignInPromptModel, SignInViewModel, SortSpec, Span, StatusTone, UserMenuItemModel, UserMenuModel, ViewModel } from "./model.js";
|
|
3
3
|
import { AccessAction, AccessContext, AccessFn, AccessResult, AccessUser, FieldAccess, FieldRule } from "./access/types.js";
|
|
4
4
|
import { AnyField, Constraint, Field, FieldMeta, FieldTypeDef } from "./field.js";
|
|
5
5
|
import { RelationField } from "./relation-field.js";
|
|
@@ -36,4 +36,4 @@ import { AccessSource, ResolveOptions, ResolvedAccess, RowFilterOperation, acces
|
|
|
36
36
|
import { restrictModel } from "./access/restrict.js";
|
|
37
37
|
import "./access/index.js";
|
|
38
38
|
import { AssistantAction, AssistantActionRequest, AssistantCardPart, AssistantDiff, AssistantEvent, AssistantMessage, AssistantMessageRequest, AssistantPart, AssistantState, AssistantStep, AssistantStepState, AssistantTablePart, AssistantTextPart, AssistantTone, AssistantWidgetPart } from "./assistant/protocol.js";
|
|
39
|
-
export { type Access, type AccessAction, type AccessContext, type AccessFn, type AccessResult, type AccessSource, type AccessUser, type ActionModel, type ActionRun, type AnyField, type AppAddress, type AssistantAction, type AssistantActionRequest, type AssistantCardPart, type AssistantDiff, type AssistantEvent, type AssistantMessage, type AssistantMessageRequest, type AssistantPart, type AssistantState, type AssistantStep, type AssistantStepState, type AssistantTablePart, type AssistantTextPart, type AssistantTone, type AssistantWidgetPart, type BadgeShape, type BottomBarItemModel, type BottomBarModel, type BottomBarNames, type BottomBarSource, type Capability, type CapabilityAction, type CapabilityLimit, type CapabilityScope, type CardPhotosModel, type ChartGranularity, type ChartModel, type ChartRange, type CheckResult, type CheckedFilter, type CompareOp, type ComponentRef, type Constraint, type CreatedOptions, type CustomSectionModel, type DatePreset, type DeletedOptions, type DurationLiteral, type DurationUnit, type EvaluateOptions, type EventActor, type EventContext, type EventHelpers, type EventMatch, type EventModel, type EventOperation, type EventSpec, type Field, type FieldAccess, type FieldFormat, type FieldMeta, type FieldModel, type FieldPath, type FieldRefValue, type FieldRefs, type FieldRule, type FieldType, type FieldTypeDef, type FieldView, type FieldViewModel, type FieldViews, type FieldWidgetModel, type FieldsInput, type FileField, type FileFieldModel, type FileOptions, type FileProcessor, type FileProcessorInput, type FilterError, type FilterErrorCode, type FilterExpr, type FilterLayout, type FilterLimits, type FilterOf, type FilterParse, type FilterValue, type FilterWidgetModel, type Grant, type HeldCapability, type ImageFormat, type ImageVariant, type ImageVariantOptions, type InferRecord, type Issue, type JsonValue, type KeyOf, type KeyRefs, type KeyType, type KeyValue, type LayoutItemModel, type ListDisplayModel, type ListModel, type ListQuery, type Literal, type MapSectionModel, type MapView, type NavModel, type NavRecentModel, type NowValue, type OrderByCheck, type OrderByItem, type OrderByParse, type RecordKey, type RecordOf, type Ref, type Refs, type RelatedModel, type RelationField, type ResolveOptions, type ResolvedAccess, type ResourceBuilder, type ResourceModel, type RoleEntry, type RoleLimit, type Roles, type RolesOptions, type RowFilterOperation, type Rule, type SaveFeedback, type SearchMatch, type SearchRef, type SearchRefs, type SearchResultModel, type SortSpec, type Span, type StatusTone, type UndeletedOptions, type UpdatedOptions, type UserMenuItemModel, type UserMenuModel, type UserMenuSource, type Validator, type ViewBuilder, type ViewModel, type ViewProps, accessWarnings, addressWords, anonymousRole, appPath, bottomBar, bottomBarErrors, checkFilter, checkOrderBy, checkRecord, createWhere, defineRoles, enumLabel, evaluateFilter, f, fieldRef, fieldsUsedBy, imageFormats, keyTypes, layout as l, maxBottomBarItems, parseFilter, parseOrderBy, pickView, printFilter, printOrderBy, readAppPath, resolveAccess, resource, restrictModel, rule, userMenu, view, where };
|
|
39
|
+
export { type Access, type AccessAction, type AccessContext, type AccessFn, type AccessResult, type AccessSource, type AccessUser, type ActionModel, type ActionRun, type AnyField, type AppAddress, type AssistantAction, type AssistantActionRequest, type AssistantCardPart, type AssistantDiff, type AssistantEvent, type AssistantMessage, type AssistantMessageRequest, type AssistantPart, type AssistantState, type AssistantStep, type AssistantStepState, type AssistantTablePart, type AssistantTextPart, type AssistantTone, type AssistantWidgetPart, type BadgeShape, type BottomBarItemModel, type BottomBarModel, type BottomBarNames, type BottomBarSource, type Capability, type CapabilityAction, type CapabilityLimit, type CapabilityScope, type CardFavoriteModel, type CardPhotosModel, type ChartGranularity, type ChartModel, type ChartRange, type CheckResult, type CheckedFilter, type CompareOp, type ComponentRef, type Constraint, type CreatedOptions, type CustomSectionModel, type DatePreset, type DeletedOptions, type DurationLiteral, type DurationUnit, type EvaluateOptions, type EventActor, type EventContext, type EventHelpers, type EventMatch, type EventModel, type EventOperation, type EventSpec, type Field, type FieldAccess, type FieldFormat, type FieldMeta, type FieldModel, type FieldPath, type FieldRefValue, type FieldRefs, type FieldRule, type FieldType, type FieldTypeDef, type FieldView, type FieldViewModel, type FieldViews, type FieldWidgetModel, type FieldsInput, type FileField, type FileFieldModel, type FileOptions, type FileProcessor, type FileProcessorInput, type FilterError, type FilterErrorCode, type FilterExpr, type FilterLayout, type FilterLimits, type FilterOf, type FilterParse, type FilterValue, type FilterWidgetModel, type Grant, type HeldCapability, type ImageFormat, type ImageVariant, type ImageVariantOptions, type InferRecord, type Issue, type JsonValue, type KeyOf, type KeyRefs, type KeyType, type KeyValue, type LayoutItemModel, type ListDisplayModel, type ListModel, type ListQuery, type Literal, type MapSectionModel, type MapView, type NavModel, type NavRecentModel, type NowValue, type OrderByCheck, type OrderByItem, type OrderByParse, type RecordKey, type RecordOf, type Ref, type Refs, type RelatedModel, type RelationField, type ResolveOptions, type ResolvedAccess, type ResourceBuilder, type ResourceModel, type RoleEntry, type RoleLimit, type Roles, type RolesOptions, type RowFilterOperation, type Rule, type SaveFeedback, type SearchMatch, type SearchRef, type SearchRefs, type SearchResultModel, type SignInPromptModel, type SignInViewModel, type SortSpec, type Span, type StatusTone, type UndeletedOptions, type UpdatedOptions, type UserMenuItemModel, type UserMenuModel, type UserMenuSource, type Validator, type ViewBuilder, type ViewModel, type ViewProps, accessWarnings, addressWords, anonymousRole, appPath, bottomBar, bottomBarErrors, checkFilter, checkOrderBy, checkRecord, createWhere, defineRoles, enumLabel, evaluateFilter, f, fieldRef, fieldsUsedBy, imageFormats, keyTypes, layout as l, maxBottomBarItems, parseFilter, parseOrderBy, pickView, printFilter, printOrderBy, readAppPath, resolveAccess, resource, restrictModel, rule, userMenu, view, where };
|
package/dist/internal.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { checkedAccept, checkedProvider, parseSize } from "./files/file-options.js";
|
|
2
|
-
import { displayFields, tableDisplay } from "./view-displays.js";
|
|
2
|
+
import { cardPhotoLimit, displayFields, tableDisplay } from "./view-displays.js";
|
|
3
3
|
import { fieldRefsIn, isFieldRef, markFieldRefs, unmarkFieldRefs } from "./field-ref.js";
|
|
4
4
|
import { bottomBarFor } from "./bottom-bar.js";
|
|
5
5
|
import { decodeKey, encodeKey } from "./keys.js";
|
|
@@ -14,4 +14,4 @@ import { addressPlaceholders, appHrefError, fillAddress, hrefPlaceholders, leave
|
|
|
14
14
|
import { AddressCheck, addressErrors } from "./address-errors.js";
|
|
15
15
|
import { applyAssistantEvent, emptyAssistantState } from "./assistant/apply-event.js";
|
|
16
16
|
import { readEventStream } from "./assistant/event-stream.js";
|
|
17
|
-
export { type AddressCheck, type PluginHost, type PluginRequirement, type PropShapes, type RefShape, type SearchTerm, addressErrors, addressPlaceholders, appHrefError, applyAssistantEvent, bottomBarFor, checkEventFilter, checkedAccept, checkedProvider, decodeKey, defaultRecentLimit, displayFields, emptyAssistantState, encodeKey, fieldRefsIn, fillAddress, hrefPlaceholders, inRange, isFieldRef, leavesApp, markFieldRefs, matchedSearchField, matchesSearch, navRecentErrors, parseSize, pluginProblem, pruneByShape, readEventStream, redactSecrets, searchTerms, shapes, statusTones, tableDisplay, termMatches, unmarkFieldRefs, webhookResources };
|
|
17
|
+
export { type AddressCheck, type PluginHost, type PluginRequirement, type PropShapes, type RefShape, type SearchTerm, addressErrors, addressPlaceholders, appHrefError, applyAssistantEvent, bottomBarFor, cardPhotoLimit, checkEventFilter, checkedAccept, checkedProvider, decodeKey, defaultRecentLimit, displayFields, emptyAssistantState, encodeKey, fieldRefsIn, fillAddress, hrefPlaceholders, inRange, isFieldRef, leavesApp, markFieldRefs, matchedSearchField, matchesSearch, navRecentErrors, parseSize, pluginProblem, pruneByShape, readEventStream, redactSecrets, searchTerms, shapes, statusTones, tableDisplay, termMatches, unmarkFieldRefs, webhookResources };
|
package/dist/internal.js
CHANGED
|
@@ -3,7 +3,7 @@ import { checkEventFilter } from "./events/event-models.js";
|
|
|
3
3
|
import { defaultRecentLimit, navRecentErrors, statusTones } from "./nav-recent.js";
|
|
4
4
|
import { addressPlaceholders, appHrefError, fillAddress, hrefPlaceholders, leavesApp } from "./address-template.js";
|
|
5
5
|
import { fieldRefsIn, isFieldRef, markFieldRefs, unmarkFieldRefs } from "./field-ref.js";
|
|
6
|
-
import { displayFields, tableDisplay } from "./view-displays.js";
|
|
6
|
+
import { cardPhotoLimit, displayFields, tableDisplay } from "./view-displays.js";
|
|
7
7
|
import { bottomBarFor } from "./bottom-bar.js";
|
|
8
8
|
import { decodeKey, encodeKey } from "./keys.js";
|
|
9
9
|
import { webhookResources } from "./webhooks/webhook-resources.js";
|
|
@@ -14,4 +14,4 @@ import { redactSecrets } from "./redact-secrets.js";
|
|
|
14
14
|
import { addressErrors } from "./address-errors.js";
|
|
15
15
|
import { applyAssistantEvent, emptyAssistantState } from "./assistant/apply-event.js";
|
|
16
16
|
import { readEventStream } from "./assistant/event-stream.js";
|
|
17
|
-
export { addressErrors, addressPlaceholders, appHrefError, applyAssistantEvent, bottomBarFor, checkEventFilter, checkedAccept, checkedProvider, decodeKey, defaultRecentLimit, displayFields, emptyAssistantState, encodeKey, fieldRefsIn, fillAddress, hrefPlaceholders, inRange, isFieldRef, leavesApp, markFieldRefs, matchedSearchField, matchesSearch, navRecentErrors, parseSize, pluginProblem, pruneByShape, readEventStream, redactSecrets, searchTerms, shapes, statusTones, tableDisplay, termMatches, unmarkFieldRefs, webhookResources };
|
|
17
|
+
export { addressErrors, addressPlaceholders, appHrefError, applyAssistantEvent, bottomBarFor, cardPhotoLimit, checkEventFilter, checkedAccept, checkedProvider, decodeKey, defaultRecentLimit, displayFields, emptyAssistantState, encodeKey, fieldRefsIn, fillAddress, hrefPlaceholders, inRange, isFieldRef, leavesApp, markFieldRefs, matchedSearchField, matchesSearch, navRecentErrors, parseSize, pluginProblem, pruneByShape, readEventStream, redactSecrets, searchTerms, shapes, statusTones, tableDisplay, termMatches, unmarkFieldRefs, webhookResources };
|
package/dist/model.d.ts
CHANGED
|
@@ -273,6 +273,8 @@ export type ListDisplayModel = {
|
|
|
273
273
|
card?: string;
|
|
274
274
|
/** Where the card's further photos come from. */
|
|
275
275
|
photos?: CardPhotosModel;
|
|
276
|
+
/** The button in the card's top right corner that saves the record to the user's own list, such as favorites. */
|
|
277
|
+
favorite?: CardFavoriteModel;
|
|
276
278
|
} | {
|
|
277
279
|
/** A map of the records at their position. */
|
|
278
280
|
kind: 'map';
|
|
@@ -306,7 +308,8 @@ export type ListDisplayModel = {
|
|
|
306
308
|
};
|
|
307
309
|
/**
|
|
308
310
|
* Where a card's further photos come from: the records of `resource` whose relation `field` points at the card's record,
|
|
309
|
-
* in `sort` order, each shown by its file field `image`.
|
|
311
|
+
* in `sort` order, each shown by its file field `image`. They come with the list's records, in the same request, so
|
|
312
|
+
* an index on `field` and the sorted fields serves them. See
|
|
310
313
|
* [Card photos](website/src/content/docs/reference/ui-config.mdx#card-photos).
|
|
311
314
|
*/
|
|
312
315
|
export type CardPhotosModel = {
|
|
@@ -319,6 +322,47 @@ export type CardPhotosModel = {
|
|
|
319
322
|
/** An AIP-132 order of the photos. */
|
|
320
323
|
sort?: string;
|
|
321
324
|
};
|
|
325
|
+
/**
|
|
326
|
+
* The button in a card's top right corner that saves its record for the signed-in user: a record of `resource` whose
|
|
327
|
+
* relation `field` points at the card's record, created on a press and deleted on the next. The resource has an owner,
|
|
328
|
+
* so each user lists and saves their own. A visitor who is not signed in gets the resource's sign-in prompt instead
|
|
329
|
+
* (`.signIn(...)` on its view). See [Favorites](website/src/content/docs/reference/ui-config.mdx#favorites).
|
|
330
|
+
*/
|
|
331
|
+
export type CardFavoriteModel = {
|
|
332
|
+
/** The resource holding the saved records, such as favorites. */
|
|
333
|
+
resource: string;
|
|
334
|
+
/** Its filterable relation that points at the card's record. */
|
|
335
|
+
field: string;
|
|
336
|
+
/** The button's accessible name, pressed while the record is saved; "Favorite" when omitted. */
|
|
337
|
+
label?: string;
|
|
338
|
+
};
|
|
339
|
+
/**
|
|
340
|
+
* What a visitor who is not signed in is told about a resource they could use once signed in (`.signIn(...)`): on its
|
|
341
|
+
* list page, in place of the list, and in the dialog of a card's favorite button that saves to it. See
|
|
342
|
+
* [Sign-in prompts](website/src/content/docs/reference/ui-config.mdx#sign-in-prompts).
|
|
343
|
+
*/
|
|
344
|
+
export type SignInPromptModel = {
|
|
345
|
+
/** The heading, such as "Keep the homes you like". */
|
|
346
|
+
title: string;
|
|
347
|
+
/** A line under it, saying what signing in gives. */
|
|
348
|
+
description: string;
|
|
349
|
+
/** What the visitor can do once signed in, one short line each. */
|
|
350
|
+
benefits?: string[];
|
|
351
|
+
/** The prompt's icon, a name `icon` hints take; a sign-in icon when omitted. */
|
|
352
|
+
icon?: string;
|
|
353
|
+
/** A page where a visitor makes an account, `https:`, `http:` or `mailto:`, offered beside "Sign in"; none when omitted. */
|
|
354
|
+
signUp?: {
|
|
355
|
+
/** The button's text, such as "Create an account". */
|
|
356
|
+
label: string;
|
|
357
|
+
/** The page's address. */
|
|
358
|
+
href: string;
|
|
359
|
+
};
|
|
360
|
+
};
|
|
361
|
+
/** A resource a visitor cannot open until they sign in, as `/meta` names it: what its view calls it and its prompt. */
|
|
362
|
+
export type SignInViewModel = Pick<ViewModel, 'resource' | 'names' | 'nav'> & {
|
|
363
|
+
/** What the visitor is told. */
|
|
364
|
+
signIn: SignInPromptModel;
|
|
365
|
+
};
|
|
322
366
|
/** A view's list page (`.list(...)`). */
|
|
323
367
|
export type ListModel = {
|
|
324
368
|
/** The table's columns, in order. */
|
|
@@ -670,6 +714,10 @@ export type ViewModel = {
|
|
|
670
714
|
saveFeedback?: SaveFeedback;
|
|
671
715
|
/** The named actions of its records. */
|
|
672
716
|
actions: ActionModel[];
|
|
717
|
+
/** The relation field whose records the list page shows instead of this resource's rows, in their own view's list. */
|
|
718
|
+
listOf?: string;
|
|
719
|
+
/** What a visitor who is not signed in is told in place of the list, and by a card's favorite button that saves here. */
|
|
720
|
+
signIn?: SignInPromptModel;
|
|
673
721
|
};
|
|
674
722
|
/** Where a part of a filter or order stands in its text, as character offsets. */
|
|
675
723
|
export type Span = {
|
package/dist/view-displays.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CardPhotosModel, ListDisplayModel } from "./model.js";
|
|
1
|
+
import { CardFavoriteModel, CardPhotosModel, ListDisplayModel } from "./model.js";
|
|
2
2
|
import { Ref } from "./refs.js";
|
|
3
3
|
//#region src/view-displays.d.ts
|
|
4
4
|
/** A custom component as `component(name)` from `@protobase/layout` declares it. */
|
|
@@ -16,6 +16,8 @@ type Naming = {
|
|
|
16
16
|
label?: string;
|
|
17
17
|
icon?: string;
|
|
18
18
|
};
|
|
19
|
+
/** The most photos a card steps through, its own image among them, each marked by a dot: a list includes this many of each record's photos. */
|
|
20
|
+
export declare const cardPhotoLimit = 10;
|
|
19
21
|
/** The name of the list's own display, which every list has. */
|
|
20
22
|
export declare const tableDisplay = "table";
|
|
21
23
|
export declare const displays: {
|
|
@@ -27,7 +29,10 @@ export declare const displays: {
|
|
|
27
29
|
* With `card`, a component of the project or a plugin draws each card's content instead, from the row of those
|
|
28
30
|
* fields (`{ row }`); without it, or when it throws, the card is the built-in one. With `photos`, the built-in card's
|
|
29
31
|
* picture gets arrows through the `image` of the records of another resource that point at the card's record, after
|
|
30
|
-
* its own `image
|
|
32
|
+
* its own `image`, ten pictures at most; they come with the list's records, so its dots mark the one shown from the
|
|
33
|
+
* start. A list's cards displays name the same `photos`. With `favorite`, a heart in the card's top right corner saves
|
|
34
|
+
* the record to the signed-in user's own records of another resource, such as favorites, and takes it off again; a
|
|
35
|
+
* visitor who is not signed in is told why to sign in. Named `cards` unless `name` says otherwise.
|
|
31
36
|
*/
|
|
32
37
|
cards: (fields: {
|
|
33
38
|
image?: Ref;
|
|
@@ -41,6 +46,7 @@ export declare const displays: {
|
|
|
41
46
|
}, o?: Naming & {
|
|
42
47
|
card?: ComponentRef<never>;
|
|
43
48
|
photos?: CardPhotosModel;
|
|
49
|
+
favorite?: CardFavoriteModel;
|
|
44
50
|
}) => ListDisplayModel;
|
|
45
51
|
/**
|
|
46
52
|
* A map of the records at their `latitude` and `longitude`, filterable fields in decimal degrees, drawn with the app's
|
package/dist/view-displays.js
CHANGED
|
@@ -4,6 +4,8 @@ const naming = ({ label, icon }) => ({
|
|
|
4
4
|
...label !== void 0 && { label },
|
|
5
5
|
...icon !== void 0 && { icon }
|
|
6
6
|
});
|
|
7
|
+
/** The most photos a card steps through, its own image among them, each marked by a dot: a list includes this many of each record's photos. */
|
|
8
|
+
const cardPhotoLimit = 10;
|
|
7
9
|
/** The name of the list's own display, which every list has. */
|
|
8
10
|
const tableDisplay = "table";
|
|
9
11
|
/** The component of a custom display or section, which must be a project's, not a built-in block. */
|
|
@@ -20,7 +22,10 @@ const displays = {
|
|
|
20
22
|
* With `card`, a component of the project or a plugin draws each card's content instead, from the row of those
|
|
21
23
|
* fields (`{ row }`); without it, or when it throws, the card is the built-in one. With `photos`, the built-in card's
|
|
22
24
|
* picture gets arrows through the `image` of the records of another resource that point at the card's record, after
|
|
23
|
-
* its own `image
|
|
25
|
+
* its own `image`, ten pictures at most; they come with the list's records, so its dots mark the one shown from the
|
|
26
|
+
* start. A list's cards displays name the same `photos`. With `favorite`, a heart in the card's top right corner saves
|
|
27
|
+
* the record to the signed-in user's own records of another resource, such as favorites, and takes it off again; a
|
|
28
|
+
* visitor who is not signed in is told why to sign in. Named `cards` unless `name` says otherwise.
|
|
24
29
|
*/
|
|
25
30
|
cards: (fields, o = {}) => ({
|
|
26
31
|
kind: "cards",
|
|
@@ -35,7 +40,8 @@ const displays = {
|
|
|
35
40
|
...fields.footer && { footer: fields.footer.map((ref) => ref.name) },
|
|
36
41
|
...fields.flags && { flags: fields.flags.map((ref) => ref.name) },
|
|
37
42
|
...o.card && { card: customComponent(o.card, "d.cards card") },
|
|
38
|
-
...o.photos && { photos: { ...o.photos } }
|
|
43
|
+
...o.photos && { photos: { ...o.photos } },
|
|
44
|
+
...o.favorite && { favorite: { ...o.favorite } }
|
|
39
45
|
}),
|
|
40
46
|
/**
|
|
41
47
|
* A map of the records at their `latitude` and `longitude`, filterable fields in decimal degrees, drawn with the app's
|
|
@@ -94,4 +100,4 @@ const displayFields = (display) => {
|
|
|
94
100
|
].filter((name) => name !== void 0);
|
|
95
101
|
};
|
|
96
102
|
//#endregion
|
|
97
|
-
export { customComponent, displayErrors, displayFields, displays, tableDisplay };
|
|
103
|
+
export { cardPhotoLimit, customComponent, displayErrors, displayFields, displays, tableDisplay };
|
package/dist/view.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ActionModel, ChartGranularity, ChartRange, FilterWidgetModel, LayoutItemModel, ListDisplayModel, NavModel, NavRecentModel, ResourceModel, SaveFeedback, ViewModel } from "./model.js";
|
|
1
|
+
import { ActionModel, ChartGranularity, ChartRange, FilterWidgetModel, LayoutItemModel, ListDisplayModel, NavModel, NavRecentModel, ResourceModel, SaveFeedback, SignInPromptModel, ViewModel } from "./model.js";
|
|
2
2
|
import { FieldRefs, Ref } from "./refs.js";
|
|
3
3
|
import { actions } from "./view-actions.js";
|
|
4
4
|
import { displays } from "./view-displays.js";
|
|
@@ -98,7 +98,21 @@ export declare class ViewBuilder<R extends {
|
|
|
98
98
|
* `a.remove` and `a.link` need no code, `a.action` runs a handler the app registers.
|
|
99
99
|
*/
|
|
100
100
|
actions(build: (a: typeof actions) => ActionModel[]): ViewBuilder<R>;
|
|
101
|
-
/**
|
|
101
|
+
/**
|
|
102
|
+
* The list page shows the records this relation field points at instead of this resource's rows, in their own view's
|
|
103
|
+
* list with its displays, filters and search: the listings among a member's favorites, say. The record pages stay this
|
|
104
|
+
* resource's. Throws in `toModel` when the field is not a relation.
|
|
105
|
+
*/
|
|
106
|
+
listOf(pick: (r: FieldRefs<FieldsOf<R>>) => Ref): ViewBuilder<R>;
|
|
107
|
+
/**
|
|
108
|
+
* What a visitor who is not signed in is told about this resource, which they could use once signed in: on its list
|
|
109
|
+
* page, in place of the list, and in the dialog of a card's favorite button that saves here. The page offers "Sign
|
|
110
|
+
* in", and a page to make an account when `signUp` names one. With it, the resource keeps its place in the bottom
|
|
111
|
+
* bar and the sidebar of visitors. Throws when `signUp.href` is not `https:`, `http:` or `mailto:`. See
|
|
112
|
+
* [Sign-in prompts](website/src/content/docs/reference/ui-config.mdx#sign-in-prompts).
|
|
113
|
+
*/
|
|
114
|
+
signIn(prompt: SignInPromptModel): ViewBuilder<R>;
|
|
115
|
+
/** With the resource's model, also verifies the title, search result and list display fields, `listOf` and the sidebar's `recent` group. */
|
|
102
116
|
toModel(resource?: ResourceModel): ViewModel;
|
|
103
117
|
private refs;
|
|
104
118
|
private next;
|
package/dist/view.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createRefs, ref } from "./refs.js";
|
|
2
|
+
import { isMenuHref } from "./menu-href.js";
|
|
2
3
|
import { navRecentErrors } from "./nav-recent.js";
|
|
3
4
|
import { actions } from "./view-actions.js";
|
|
4
5
|
import { displayErrors, displayFields, displays } from "./view-displays.js";
|
|
@@ -111,9 +112,28 @@ var ViewBuilder = class ViewBuilder {
|
|
|
111
112
|
actions(build) {
|
|
112
113
|
return this.next({ actions: build(actions) });
|
|
113
114
|
}
|
|
114
|
-
/**
|
|
115
|
+
/**
|
|
116
|
+
* The list page shows the records this relation field points at instead of this resource's rows, in their own view's
|
|
117
|
+
* list with its displays, filters and search: the listings among a member's favorites, say. The record pages stay this
|
|
118
|
+
* resource's. Throws in `toModel` when the field is not a relation.
|
|
119
|
+
*/
|
|
120
|
+
listOf(pick) {
|
|
121
|
+
return this.next({ listOf: pick(this.refs()).name });
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* What a visitor who is not signed in is told about this resource, which they could use once signed in: on its list
|
|
125
|
+
* page, in place of the list, and in the dialog of a card's favorite button that saves here. The page offers "Sign
|
|
126
|
+
* in", and a page to make an account when `signUp` names one. With it, the resource keeps its place in the bottom
|
|
127
|
+
* bar and the sidebar of visitors. Throws when `signUp.href` is not `https:`, `http:` or `mailto:`. See
|
|
128
|
+
* [Sign-in prompts](website/src/content/docs/reference/ui-config.mdx#sign-in-prompts).
|
|
129
|
+
*/
|
|
130
|
+
signIn(prompt) {
|
|
131
|
+
if (prompt.signUp && !isMenuHref(prompt.signUp.href)) throw new Error(`View "${this.state.resource}": signIn signUp.href must start with https://, http:// or mailto:`);
|
|
132
|
+
return this.next({ signIn: structuredClone(prompt) });
|
|
133
|
+
}
|
|
134
|
+
/** With the resource's model, also verifies the title, search result and list display fields, `listOf` and the sidebar's `recent` group. */
|
|
115
135
|
toModel(resource) {
|
|
116
|
-
const { title, nav, searchResult, list } = this.state;
|
|
136
|
+
const { title, nav, searchResult, list, listOf } = this.state;
|
|
117
137
|
if (resource && title !== void 0 && !Object.hasOwn(resource.fields, title)) throw new Error(`View "${this.state.resource}": title field "${title}" does not exist on the resource`);
|
|
118
138
|
const missing = resource ? [...searchResult?.title ?? [], ...searchResult?.subtitle ? [searchResult.subtitle] : []].filter((name) => !Object.hasOwn(resource.fields, name)) : [];
|
|
119
139
|
if (missing.length > 0) throw new Error(`View "${this.state.resource}": search result field "${missing[0]}" does not exist on the resource`);
|
|
@@ -124,6 +144,7 @@ var ViewBuilder = class ViewBuilder {
|
|
|
124
144
|
const flag = display.kind === "cards" ? display.flags?.find((name) => resource.fields[name].type !== "boolean") : void 0;
|
|
125
145
|
if (flag !== void 0) throw new Error(`View "${this.state.resource}": display "${display.name}" shows "${flag}" as a flag, which is not a boolean field`);
|
|
126
146
|
}
|
|
147
|
+
if (resource && listOf !== void 0 && (!Object.hasOwn(resource.fields, listOf) || resource.fields[listOf].type !== "relation")) throw new Error(`View "${this.state.resource}": listOf names "${listOf}", which is not a relation field of the resource`);
|
|
127
148
|
const recentErrors = resource && nav?.recent ? navRecentErrors(nav.recent, resource) : [];
|
|
128
149
|
if (recentErrors.length > 0) throw new Error(`View "${this.state.resource}": nav.recent ${recentErrors.join("; ")}`);
|
|
129
150
|
return structuredClone(this.state);
|