@protobase/schema 0.22.4 → 0.22.6
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/app-address.d.ts +2 -0
- package/dist/app-address.js +5 -0
- package/dist/index.d.ts +2 -2
- package/dist/internal.d.ts +2 -1
- package/dist/internal.js +2 -1
- package/dist/model.d.ts +33 -1
- package/dist/named-list.d.ts +8 -0
- package/dist/named-list.js +18 -0
- package/dist/view-widgets.d.ts +8 -1
- package/dist/view-widgets.js +12 -6
- package/dist/view.d.ts +8 -0
- package/dist/view.js +41 -0
- package/package.json +1 -1
package/dist/app-address.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ import { AppAddress } from "./model.js";
|
|
|
5
5
|
* changes in this module alone.
|
|
6
6
|
*/
|
|
7
7
|
export declare const addressWords: {
|
|
8
|
+
/** A named list of the resource (`.namedList(...)`), in place of its own list. */
|
|
9
|
+
readonly list: "list";
|
|
8
10
|
/** A list's filter (AIP-160), as the list API takes it. An empty `filter=` means no filter, in place of the view's default. */
|
|
9
11
|
readonly filter: "filter";
|
|
10
12
|
/** A list's order (AIP-132). */
|
package/dist/app-address.js
CHANGED
|
@@ -5,6 +5,8 @@ import { encodeKey } from "./keys.js";
|
|
|
5
5
|
* changes in this module alone.
|
|
6
6
|
*/
|
|
7
7
|
const addressWords = {
|
|
8
|
+
/** A named list of the resource (`.namedList(...)`), in place of its own list. */
|
|
9
|
+
list: "list",
|
|
8
10
|
/** A list's filter (AIP-160), as the list API takes it. An empty `filter=` means no filter, in place of the view's default. */
|
|
9
11
|
filter: "filter",
|
|
10
12
|
/** A list's order (AIP-132). */
|
|
@@ -27,6 +29,7 @@ const addressWords = {
|
|
|
27
29
|
open: "open"
|
|
28
30
|
};
|
|
29
31
|
const listWords = [
|
|
32
|
+
"list",
|
|
30
33
|
"display",
|
|
31
34
|
"filter",
|
|
32
35
|
"orderBy",
|
|
@@ -136,6 +139,7 @@ const readAppPath = (pathAndQuery, pages) => {
|
|
|
136
139
|
};
|
|
137
140
|
}
|
|
138
141
|
const params = url.searchParams;
|
|
142
|
+
const list = params.get(addressWords.list) || void 0;
|
|
139
143
|
const display = params.get(addressWords.display) || void 0;
|
|
140
144
|
const filter = params.get(addressWords.filter) ?? void 0;
|
|
141
145
|
const orderBy = params.get(addressWords.orderBy) || void 0;
|
|
@@ -146,6 +150,7 @@ const readAppPath = (pathAndQuery, pages) => {
|
|
|
146
150
|
return {
|
|
147
151
|
kind: "list",
|
|
148
152
|
resource: first,
|
|
153
|
+
...list && { list },
|
|
149
154
|
...display && { display },
|
|
150
155
|
...filter !== void 0 && { filter },
|
|
151
156
|
...orderBy && { orderBy },
|
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 { ActionInputKind, ActionInputModel, ActionModel, ActionRun, AppAddress, BadgeShape, BottomBarItemModel, BottomBarModel, CalendarView, CardFavoriteModel, CardPhotosModel, ChartGranularity, ChartModel, ChartRange, CheckedFilter, CommentsSectionModel, CompareOp, CreateModel, CustomSectionModel, DatePreset, DurationLiteral, DurationUnit, EventModel, EventOperation, ExportModel, FieldFormat, FieldModel, FieldPath, FieldType, FieldViewModel, FieldWidgetModel, FileFieldModel, FilterError, FilterErrorCode, FilterExpr, FilterLayout, FilterOf, FilterValue, FilterWidgetModel, FormModel, GalleryModel, GroupChartModel, GroupItemModel, GroupModel, HelpWhen, HistorySectionModel, JsonValue, KeyValue, LayoutItemModel, ListDisplayModel, ListModel, ListQuery, Literal, MapSectionModel, MapView, NavModel, NavRecentModel, NowValue, OrderByItem, PeriodChartModel, RecordMode, RecordWhen, RelatedColumnModel, RelatedModel, ResourceModel, SaveFeedback, SaveSearchModel, SearchMatch, SearchResultModel, SearchesOfModel, SectionModel, SectionPresentation, ShowWhen, SignInPromptModel, SignInViewModel, SortSpec, Span, StatusTone, UserMenuItemModel, UserMenuModel, ViewModel } from "./model.js";
|
|
2
|
+
import { ActionInputKind, ActionInputModel, ActionModel, ActionRun, AppAddress, BadgeShape, BottomBarItemModel, BottomBarModel, CalendarView, CardFavoriteModel, CardPhotosModel, ChartGranularity, ChartModel, ChartRange, CheckedFilter, CommentsSectionModel, CompareOp, CreateModel, CustomSectionModel, DatePreset, DurationLiteral, DurationUnit, EventModel, EventOperation, ExportModel, FieldFormat, FieldModel, FieldPath, FieldType, FieldViewModel, FieldWidgetModel, FileFieldModel, FilterError, FilterErrorCode, FilterExpr, FilterLayout, FilterOf, FilterValue, FilterWidgetModel, FormModel, GalleryModel, GroupChartModel, GroupItemModel, GroupModel, HelpWhen, HistorySectionModel, JsonValue, KeyValue, LayoutItemModel, ListDisplayModel, ListModel, ListQuery, Literal, MapSectionModel, MapView, NamedListModel, NavModel, NavRecentModel, NowValue, OrderByItem, PeriodChartModel, RecordMode, RecordWhen, RelatedColumnModel, RelatedModel, ResourceModel, SaveFeedback, SaveSearchModel, SearchMatch, SearchResultModel, SearchesOfModel, SectionModel, SectionPresentation, ShowWhen, 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";
|
|
@@ -42,4 +42,4 @@ import { AccessSource, ResolveOptions, ResolvedAccess, RowFilterOperation, acces
|
|
|
42
42
|
import { restrictModel } from "./access/restrict.js";
|
|
43
43
|
import "./access/index.js";
|
|
44
44
|
import { AssistantAction, AssistantActionRequest, AssistantCardPart, AssistantDiff, AssistantEvent, AssistantMessage, AssistantMessageRequest, AssistantPart, AssistantState, AssistantStep, AssistantStepState, AssistantTablePart, AssistantTextPart, AssistantTone, AssistantWidgetPart } from "./assistant/protocol.js";
|
|
45
|
-
export { type Access, type AccessAction, type AccessContext, type AccessFn, type AccessResult, type AccessSource, type AccessUser, type ActionInputKind, type ActionInputModel, 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 CalendarView, type Capability, type CapabilityAction, type CapabilityLimit, type CapabilityScope, type CardFavoriteModel, type CardPhotosModel, type ChartGranularity, type ChartInput, type ChartModel, type ChartRange, type CheckResult, type CheckedFilter, type CommentsSectionModel, type CompareOp, type ComponentRef, type Constraint, type CreateModel, 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 ExportModel, 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 FormAddress, type FormInput, type FormModel, type GalleryModel, type Grant, type GroupChartInput, type GroupChartModel, type GroupItemModel, type GroupModel, type HeldCapability, type HelpWhen, type HistorySectionModel, type ImageFormat, type ImageVariant, type ImageVariantOptions, type InferRecord, type Issue, type JsonValue, type KeyOf, type KeyRefs, type KeyType, type KeyValue, type LayoutItemModel, type ListColumn, 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 PeriodChartInput, type PeriodChartModel, type RecordKey, type RecordMode, type RecordOf, type RecordWhen, type Ref, type Refs, type RelatedColumnModel, 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 SaveSearchModel, type SearchMatch, type SearchRef, type SearchRefs, type SearchResultModel, type SearchesOfModel, type SectionModel, type SectionPresentation, type ShowWhen, type SignInAddress, type SignInPromptModel, type SignInStep, 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, fitsKeyType, formPath, formRoute, imageFormats, isRecordCondition, keyTypes, layout as l, maxBottomBarItems, parseFilter, parseOrderBy, pickView, printFilter, printOrderBy, readAppPath, readFormAddress, readSignInAddress, resolveAccess, resource, restrictModel, rule, signInParams, signInPath, signInRoute, signInSteps, userMenu, view, where };
|
|
45
|
+
export { type Access, type AccessAction, type AccessContext, type AccessFn, type AccessResult, type AccessSource, type AccessUser, type ActionInputKind, type ActionInputModel, 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 CalendarView, type Capability, type CapabilityAction, type CapabilityLimit, type CapabilityScope, type CardFavoriteModel, type CardPhotosModel, type ChartGranularity, type ChartInput, type ChartModel, type ChartRange, type CheckResult, type CheckedFilter, type CommentsSectionModel, type CompareOp, type ComponentRef, type Constraint, type CreateModel, 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 ExportModel, 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 FormAddress, type FormInput, type FormModel, type GalleryModel, type Grant, type GroupChartInput, type GroupChartModel, type GroupItemModel, type GroupModel, type HeldCapability, type HelpWhen, type HistorySectionModel, type ImageFormat, type ImageVariant, type ImageVariantOptions, type InferRecord, type Issue, type JsonValue, type KeyOf, type KeyRefs, type KeyType, type KeyValue, type LayoutItemModel, type ListColumn, type ListDisplayModel, type ListModel, type ListQuery, type Literal, type MapSectionModel, type MapView, type NamedListModel, type NavModel, type NavRecentModel, type NowValue, type OrderByCheck, type OrderByItem, type OrderByParse, type PeriodChartInput, type PeriodChartModel, type RecordKey, type RecordMode, type RecordOf, type RecordWhen, type Ref, type Refs, type RelatedColumnModel, 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 SaveSearchModel, type SearchMatch, type SearchRef, type SearchRefs, type SearchResultModel, type SearchesOfModel, type SectionModel, type SectionPresentation, type ShowWhen, type SignInAddress, type SignInPromptModel, type SignInStep, 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, fitsKeyType, formPath, formRoute, imageFormats, isRecordCondition, keyTypes, layout as l, maxBottomBarItems, parseFilter, parseOrderBy, pickView, printFilter, printOrderBy, readAppPath, readFormAddress, readSignInAddress, resolveAccess, resource, restrictModel, rule, signInParams, signInPath, signInRoute, signInSteps, userMenu, view, where };
|
package/dist/internal.d.ts
CHANGED
|
@@ -19,4 +19,5 @@ import { AddressCheck, addressErrors } from "./address-errors.js";
|
|
|
19
19
|
import { applyAssistantEvent, emptyAssistantState } from "./assistant/apply-event.js";
|
|
20
20
|
import { readEventStream } from "./assistant/event-stream.js";
|
|
21
21
|
import { layoutItems } from "./layout-items.js";
|
|
22
|
-
|
|
22
|
+
import { viewOfList } from "./named-list.js";
|
|
23
|
+
export { type AddressCheck, type PluginHost, type PluginRequirement, type PropShapes, type RefShape, type SearchTerm, actionInputErrors, addressErrors, addressPlaceholders, appHrefError, applyAssistantEvent, boardErrors, bottomBarFor, calendarErrors, cardPhotoLimit, chartFields, checkEventFilter, checkedAccept, checkedProvider, decodeKey, defaultRecentLimit, displayFields, emptyAssistantState, encodeKey, fieldRefsIn, fillAddress, hrefField, hrefPlaceholders, inRange, isFieldRef, isGroupChart, layoutItems, leavesApp, linkActionError, markFieldRefs, matchedSearchField, matchesSearch, navRecentErrors, parseSize, pluginProblem, promptError, promptFields, pruneByShape, readEventStream, redactSecrets, renderPrompt, searchTerms, shapes, shownInputs, statusTones, tableDisplay, termMatches, unmarkFieldRefs, updateSetErrors, updateValues, viewOfList, webhookResources };
|
package/dist/internal.js
CHANGED
|
@@ -3,6 +3,7 @@ import { promptError, promptFields, renderPrompt } from "./ai-prompt.js";
|
|
|
3
3
|
import { checkedAccept, checkedProvider, parseSize } from "./files/file-options.js";
|
|
4
4
|
import { matchedSearchField, matchesSearch, searchTerms, termMatches } from "./search-match.js";
|
|
5
5
|
import { checkEventFilter } from "./events/event-models.js";
|
|
6
|
+
import { viewOfList } from "./named-list.js";
|
|
6
7
|
import { defaultRecentLimit, navRecentErrors, statusTones } from "./nav-recent.js";
|
|
7
8
|
import { actionInputErrors, shownInputs } from "./action-inputs.js";
|
|
8
9
|
import { updateSetErrors, updateValues } from "./update-set.js";
|
|
@@ -19,4 +20,4 @@ import { addressErrors } from "./address-errors.js";
|
|
|
19
20
|
import { applyAssistantEvent, emptyAssistantState } from "./assistant/apply-event.js";
|
|
20
21
|
import { readEventStream } from "./assistant/event-stream.js";
|
|
21
22
|
import { layoutItems } from "./layout-items.js";
|
|
22
|
-
export { actionInputErrors, addressErrors, addressPlaceholders, appHrefError, applyAssistantEvent, boardErrors, bottomBarFor, calendarErrors, cardPhotoLimit, chartFields, checkEventFilter, checkedAccept, checkedProvider, decodeKey, defaultRecentLimit, displayFields, emptyAssistantState, encodeKey, fieldRefsIn, fillAddress, hrefField, hrefPlaceholders, inRange, isFieldRef, isGroupChart, layoutItems, leavesApp, linkActionError, markFieldRefs, matchedSearchField, matchesSearch, navRecentErrors, parseSize, pluginProblem, promptError, promptFields, pruneByShape, readEventStream, redactSecrets, renderPrompt, searchTerms, shapes, shownInputs, statusTones, tableDisplay, termMatches, unmarkFieldRefs, updateSetErrors, updateValues, webhookResources };
|
|
23
|
+
export { actionInputErrors, addressErrors, addressPlaceholders, appHrefError, applyAssistantEvent, boardErrors, bottomBarFor, calendarErrors, cardPhotoLimit, chartFields, checkEventFilter, checkedAccept, checkedProvider, decodeKey, defaultRecentLimit, displayFields, emptyAssistantState, encodeKey, fieldRefsIn, fillAddress, hrefField, hrefPlaceholders, inRange, isFieldRef, isGroupChart, layoutItems, leavesApp, linkActionError, markFieldRefs, matchedSearchField, matchesSearch, navRecentErrors, parseSize, pluginProblem, promptError, promptFields, pruneByShape, readEventStream, redactSecrets, renderPrompt, searchTerms, shapes, shownInputs, statusTones, tableDisplay, termMatches, unmarkFieldRefs, updateSetErrors, updateValues, viewOfList, webhookResources };
|
package/dist/model.d.ts
CHANGED
|
@@ -189,6 +189,8 @@ export type AppAddress = {
|
|
|
189
189
|
kind: 'list';
|
|
190
190
|
/** The resource listed. */
|
|
191
191
|
resource: string;
|
|
192
|
+
/** A named list of the resource's view (`.namedList(...)`); its own list when omitted. */
|
|
193
|
+
list?: string;
|
|
192
194
|
/** An AIP-160 filter on the list. */
|
|
193
195
|
filter?: string;
|
|
194
196
|
/** An AIP-132 order of the list. */
|
|
@@ -568,7 +570,7 @@ export type DatePreset = 'today' | 'yesterday' | '24h' | '7d' | '30d' | '90d' |
|
|
|
568
570
|
* A filter widget above a list (`.filters((r, w) => ...)`), on a filterable field; see
|
|
569
571
|
* [Filters and the chart](website/src/content/docs/reference/ui-config.mdx#filters-and-the-chart).
|
|
570
572
|
*/
|
|
571
|
-
export type FilterWidgetModel = {
|
|
573
|
+
export type FilterWidgetModel = ({
|
|
572
574
|
/** A slider between the lowest and highest value. */
|
|
573
575
|
kind: 'range';
|
|
574
576
|
/** The field it filters. */
|
|
@@ -601,6 +603,9 @@ export type FilterWidgetModel = {
|
|
|
601
603
|
fields: string[];
|
|
602
604
|
/** The menu's label. */
|
|
603
605
|
label: string;
|
|
606
|
+
}) & {
|
|
607
|
+
/** Shown behind the bar's "More filters" menu until it is picked there or set. */
|
|
608
|
+
secondary?: boolean;
|
|
604
609
|
};
|
|
605
610
|
/**
|
|
606
611
|
* Records of another resource on the record page: those whose `field` holds this record's key or, with `through`,
|
|
@@ -1086,6 +1091,33 @@ export type ViewModel = {
|
|
|
1086
1091
|
create?: CreateModel;
|
|
1087
1092
|
/** Public forms that create its records for people without an account, each at `/-/forms/<name>`. */
|
|
1088
1093
|
forms?: FormModel[];
|
|
1094
|
+
/** Other lists of the resource, each with its own sidebar entry and address. */
|
|
1095
|
+
lists?: NamedListModel[];
|
|
1096
|
+
};
|
|
1097
|
+
/**
|
|
1098
|
+
* Another list of a view's resource (`.namedList(...)`), with its own sidebar entry at `/<resource>?list=<name>`: its
|
|
1099
|
+
* own names, list, filter widgets and chart in place of the view's. Its records open at the resource's own address.
|
|
1100
|
+
*/
|
|
1101
|
+
export type NamedListModel = {
|
|
1102
|
+
/** Its address, `?list=<name>`: lowercase letters, digits, `-` and `_`, unique in its view. */
|
|
1103
|
+
name: string;
|
|
1104
|
+
/** What its records are called; `plural` is its sidebar entry and title. */
|
|
1105
|
+
names: {
|
|
1106
|
+
/** One record's name, as in "New repair". */
|
|
1107
|
+
singular: string;
|
|
1108
|
+
/** The records' name, as its sidebar entry and title. */
|
|
1109
|
+
plural: string;
|
|
1110
|
+
};
|
|
1111
|
+
/** Where it sits in the sidebar; without `recent`. */
|
|
1112
|
+
nav?: NavModel;
|
|
1113
|
+
/** A line under its title. */
|
|
1114
|
+
help?: string;
|
|
1115
|
+
/** Its list; the resource's first six fields as columns when omitted. */
|
|
1116
|
+
list?: ListModel;
|
|
1117
|
+
/** Its filter widgets, in order. */
|
|
1118
|
+
filters: FilterWidgetModel[];
|
|
1119
|
+
/** Its chart. */
|
|
1120
|
+
chart?: ChartModel;
|
|
1089
1121
|
};
|
|
1090
1122
|
/**
|
|
1091
1123
|
* A public form (`.form(...)`): anyone, signed in or not, opens it at `/-/forms/<name>` and creates a record with its
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ViewModel } from "./model.js";
|
|
2
|
+
//#region src/named-list.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* The view a list page shows: `view` itself, or, with `list`, the view with that named list's names, nav, help, list,
|
|
5
|
+
* filters and chart in place of its own, and no named lists; none when the view has no list by that name.
|
|
6
|
+
*/
|
|
7
|
+
export declare const viewOfList: (view: ViewModel | undefined, list: string | undefined) => ViewModel | undefined;
|
|
8
|
+
//#endregion
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
//#region src/named-list.ts
|
|
2
|
+
/**
|
|
3
|
+
* The view a list page shows: `view` itself, or, with `list`, the view with that named list's names, nav, help, list,
|
|
4
|
+
* filters and chart in place of its own, and no named lists; none when the view has no list by that name.
|
|
5
|
+
*/
|
|
6
|
+
const viewOfList = (view, list) => {
|
|
7
|
+
if (list === void 0) return view;
|
|
8
|
+
const named = view?.lists?.find((entry) => entry.name === list);
|
|
9
|
+
if (!view || !named) return void 0;
|
|
10
|
+
const { list: _list, chart: _chart, help: _help, nav: _nav, lists: _lists, names: _names, ...rest } = view;
|
|
11
|
+
const { name: _name, ...parts } = named;
|
|
12
|
+
return {
|
|
13
|
+
...rest,
|
|
14
|
+
...parts
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
//#endregion
|
|
18
|
+
export { viewOfList };
|
package/dist/view-widgets.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { DatePreset, FilterWidgetModel } from "./model.js";
|
|
2
2
|
import { Ref } from "./refs.js";
|
|
3
3
|
//#region src/view-widgets.d.ts
|
|
4
|
+
/** Every widget also takes `secondary: true`, which puts it behind the bar's "More filters" menu until it is picked there or set. */
|
|
4
5
|
export declare const widgets: {
|
|
5
6
|
/** A slider between the field's lowest and highest value; `histogram` draws the values' histogram behind it. */
|
|
6
7
|
range: (ref: Ref, o?: {
|
|
7
8
|
histogram?: boolean;
|
|
9
|
+
secondary?: boolean;
|
|
8
10
|
}) => FilterWidgetModel;
|
|
9
11
|
/**
|
|
10
12
|
* A menu of the field's values with counts; `search` adds a search box for long lists. On a relation it searches the
|
|
@@ -12,19 +14,24 @@ export declare const widgets: {
|
|
|
12
14
|
*/
|
|
13
15
|
facets: (ref: Ref, o?: {
|
|
14
16
|
search?: boolean;
|
|
17
|
+
secondary?: boolean;
|
|
15
18
|
}) => FilterWidgetModel;
|
|
16
19
|
/** A date range with buttons for the `presets`, such as `today` and `30d`. */
|
|
17
20
|
dateRange: (ref: Ref, o?: {
|
|
18
21
|
presets?: DatePreset[];
|
|
22
|
+
secondary?: boolean;
|
|
19
23
|
}) => FilterWidgetModel;
|
|
20
24
|
/** A switch for a boolean field. */
|
|
21
|
-
toggle: (ref: Ref
|
|
25
|
+
toggle: (ref: Ref, o?: {
|
|
26
|
+
secondary?: boolean;
|
|
27
|
+
}) => FilterWidgetModel;
|
|
22
28
|
/**
|
|
23
29
|
* A menu of boolean fields under one `label`, such as "for sale" and "for rent": a record shows when any chosen field
|
|
24
30
|
* is true, so one that is both shows under each.
|
|
25
31
|
*/
|
|
26
32
|
flags: (refs: Ref<string, boolean | null>[], o: {
|
|
27
33
|
label: string;
|
|
34
|
+
secondary?: boolean;
|
|
28
35
|
}) => FilterWidgetModel;
|
|
29
36
|
};
|
|
30
37
|
//#endregion
|
package/dist/view-widgets.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
//#region src/view-widgets.ts
|
|
2
|
+
/** Every widget also takes `secondary: true`, which puts it behind the bar's "More filters" menu until it is picked there or set. */
|
|
2
3
|
const widgets = {
|
|
3
4
|
/** A slider between the field's lowest and highest value; `histogram` draws the values' histogram behind it. */
|
|
4
5
|
range: (ref, o = {}) => ({
|
|
5
6
|
kind: "range",
|
|
6
7
|
field: ref.name,
|
|
7
|
-
histogram: o.histogram ?? false
|
|
8
|
+
histogram: o.histogram ?? false,
|
|
9
|
+
...o.secondary && { secondary: true }
|
|
8
10
|
}),
|
|
9
11
|
/**
|
|
10
12
|
* A menu of the field's values with counts; `search` adds a search box for long lists. On a relation it searches the
|
|
@@ -13,18 +15,21 @@ const widgets = {
|
|
|
13
15
|
facets: (ref, o = {}) => ({
|
|
14
16
|
kind: "facets",
|
|
15
17
|
field: ref.name,
|
|
16
|
-
search: o.search ?? false
|
|
18
|
+
search: o.search ?? false,
|
|
19
|
+
...o.secondary && { secondary: true }
|
|
17
20
|
}),
|
|
18
21
|
/** A date range with buttons for the `presets`, such as `today` and `30d`. */
|
|
19
22
|
dateRange: (ref, o = {}) => ({
|
|
20
23
|
kind: "dateRange",
|
|
21
24
|
field: ref.name,
|
|
22
|
-
presets: o.presets ?? []
|
|
25
|
+
presets: o.presets ?? [],
|
|
26
|
+
...o.secondary && { secondary: true }
|
|
23
27
|
}),
|
|
24
28
|
/** A switch for a boolean field. */
|
|
25
|
-
toggle: (ref) => ({
|
|
29
|
+
toggle: (ref, o = {}) => ({
|
|
26
30
|
kind: "toggle",
|
|
27
|
-
field: ref.name
|
|
31
|
+
field: ref.name,
|
|
32
|
+
...o.secondary && { secondary: true }
|
|
28
33
|
}),
|
|
29
34
|
/**
|
|
30
35
|
* A menu of boolean fields under one `label`, such as "for sale" and "for rent": a record shows when any chosen field
|
|
@@ -33,7 +38,8 @@ const widgets = {
|
|
|
33
38
|
flags: (refs, o) => ({
|
|
34
39
|
kind: "flags",
|
|
35
40
|
fields: refs.map((ref) => ref.name),
|
|
36
|
-
label: o.label
|
|
41
|
+
label: o.label,
|
|
42
|
+
...o.secondary && { secondary: true }
|
|
37
43
|
})
|
|
38
44
|
};
|
|
39
45
|
//#endregion
|
package/dist/view.d.ts
CHANGED
|
@@ -88,6 +88,14 @@ export declare class ViewBuilder<R extends {
|
|
|
88
88
|
* `w.toggle` and `w.flags`. Together they write the list's `?filter=`.
|
|
89
89
|
*/
|
|
90
90
|
filters(build: (r: FieldRefs<FieldsOf<R>>, w: typeof widgets) => FilterWidgetModel[]): ViewBuilder<R>;
|
|
91
|
+
/**
|
|
92
|
+
* Another list of this resource, with its own sidebar entry and address (`/<resource>?list=<name>`). `build` gets a
|
|
93
|
+
* fresh view and sets its `names` (the sidebar entry, required), `nav`, `help`, `list`, `filters` and `chart`, none of
|
|
94
|
+
* which come from the view's own list. Its records open at the resource's own address. Throws on a name that does not
|
|
95
|
+
* fit an address or repeats, on anything else set, on `nav.recent`, and in `toModel` when the view has `listOf` or
|
|
96
|
+
* `searchesOf`. See [More than one list](website/src/content/docs/reference/ui-config.mdx#more-than-one-list).
|
|
97
|
+
*/
|
|
98
|
+
namedList(name: string, build: (v: ViewBuilder<R>) => ViewBuilder<R>): ViewBuilder<R>;
|
|
91
99
|
/**
|
|
92
100
|
* The record page, as items of `l` in order: sections, sidebar cards, related records, maps and custom components.
|
|
93
101
|
* Without it the page shows one section with every field.
|
package/dist/view.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { createRefs, ref } from "./refs.js";
|
|
2
|
+
import { formNamePattern } from "./form-address.js";
|
|
2
3
|
import { isMenuHref } from "./menu-href.js";
|
|
4
|
+
import { viewOfList } from "./named-list.js";
|
|
3
5
|
import { navRecentErrors } from "./nav-recent.js";
|
|
4
6
|
import { actions } from "./view-actions.js";
|
|
5
7
|
import { chartModel } from "./view-chart.js";
|
|
@@ -9,6 +11,15 @@ import { boardErrors, calendarErrors, displayErrors, displayFields, displays } f
|
|
|
9
11
|
import { FieldView } from "./view-field.js";
|
|
10
12
|
import { widgets } from "./view-widgets.js";
|
|
11
13
|
//#region src/view.ts
|
|
14
|
+
const namedListParts = /* @__PURE__ */ new Set([
|
|
15
|
+
"resource",
|
|
16
|
+
"names",
|
|
17
|
+
"nav",
|
|
18
|
+
"help",
|
|
19
|
+
"list",
|
|
20
|
+
"filters",
|
|
21
|
+
"chart"
|
|
22
|
+
]);
|
|
12
23
|
const searchesOfErrors = (searches, resource) => {
|
|
13
24
|
const typed = (role, name, type) => name === void 0 || resource.fields[name]?.type === type ? [] : [`${role} "${name}" is not a ${type} field of the resource`];
|
|
14
25
|
return [
|
|
@@ -111,6 +122,34 @@ var ViewBuilder = class ViewBuilder {
|
|
|
111
122
|
return this.next({ filters: build(this.refs(), widgets) });
|
|
112
123
|
}
|
|
113
124
|
/**
|
|
125
|
+
* Another list of this resource, with its own sidebar entry and address (`/<resource>?list=<name>`). `build` gets a
|
|
126
|
+
* fresh view and sets its `names` (the sidebar entry, required), `nav`, `help`, `list`, `filters` and `chart`, none of
|
|
127
|
+
* which come from the view's own list. Its records open at the resource's own address. Throws on a name that does not
|
|
128
|
+
* fit an address or repeats, on anything else set, on `nav.recent`, and in `toModel` when the view has `listOf` or
|
|
129
|
+
* `searchesOf`. See [More than one list](website/src/content/docs/reference/ui-config.mdx#more-than-one-list).
|
|
130
|
+
*/
|
|
131
|
+
namedList(name, build) {
|
|
132
|
+
const where = `View "${this.state.resource}": named list "${name}"`;
|
|
133
|
+
if (!formNamePattern.test(name)) throw new Error(`${where}: its name goes in its address, so it takes lowercase letters, digits, - and _`);
|
|
134
|
+
if (this.state.lists?.some((entry) => entry.name === name)) throw new Error(`${where} is declared twice`);
|
|
135
|
+
const start = view(this.state.resource);
|
|
136
|
+
const { state } = build(start);
|
|
137
|
+
const extra = Object.keys(state).filter((key) => !namedListParts.has(key) && state[key] !== start.state[key]);
|
|
138
|
+
if (extra.length > 0) throw new Error(`${where} sets ${extra.join(", ")}; a named list takes names, nav, help, list, filters and chart`);
|
|
139
|
+
if (!state.names) throw new Error(`${where} needs .names(...), its sidebar entry`);
|
|
140
|
+
if (state.nav?.recent) throw new Error(`${where}: recent records are the view's own, not a named list's`);
|
|
141
|
+
const named = {
|
|
142
|
+
name,
|
|
143
|
+
names: state.names,
|
|
144
|
+
filters: state.filters,
|
|
145
|
+
...state.nav && { nav: state.nav },
|
|
146
|
+
...state.help !== void 0 && { help: state.help },
|
|
147
|
+
...state.list && { list: state.list },
|
|
148
|
+
...state.chart && { chart: state.chart }
|
|
149
|
+
};
|
|
150
|
+
return this.next({ lists: [...this.state.lists ?? [], named] });
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
114
153
|
* The record page, as items of `l` in order: sections, sidebar cards, related records, maps and custom components.
|
|
115
154
|
* Without it the page shows one section with every field.
|
|
116
155
|
*/
|
|
@@ -281,6 +320,8 @@ var ViewBuilder = class ViewBuilder {
|
|
|
281
320
|
}
|
|
282
321
|
const recentErrors = resource && nav?.recent ? navRecentErrors(nav.recent, resource) : [];
|
|
283
322
|
if (recentErrors.length > 0) throw new Error(`View "${this.state.resource}": nav.recent ${recentErrors.join("; ")}`);
|
|
323
|
+
if (this.state.lists?.length && (listOf !== void 0 || this.state.searchesOf)) throw new Error(`View "${this.state.resource}": named lists cannot go with listOf or searchesOf, which replace the list page`);
|
|
324
|
+
for (const named of this.state.lists ?? []) new ViewBuilder(viewOfList(this.state, named.name)).toModel(resource);
|
|
284
325
|
return structuredClone(this.state);
|
|
285
326
|
}
|
|
286
327
|
refs() {
|