@phis/ui 0.3.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/components/cms/phi-cms-layout-renderer.js +1 -1
- package/components/controls/phi-collection-header-control.js +1 -1
- package/components/controls/phi-collection-view-control.js +2 -1
- package/components/controls/phi-drawer-control-adapter.d.ts +1 -1
- package/components/controls/phi-drawer-control-adapter.js +2 -2
- package/components/controls/phi-image-control.d.ts +6 -1
- package/components/controls/phi-image-control.js +23 -4
- package/components/controls/phi-lightbox-image-control-adapter.d.ts +2 -0
- package/components/controls/phi-lightbox-image-control-adapter.js +11 -0
- package/components/controls/phi-lightbox-image-control.d.ts +3 -2
- package/components/controls/phi-lightbox-image-control.js +7 -3
- package/components/controls/phi-modal-control-adapter.d.ts +1 -1
- package/components/controls/phi-modal-control-adapter.js +5 -2
- package/components/controls/phi-overlay-control-contract.d.ts +5 -0
- package/components/controls/phi-pagination-control-adapter.d.ts +2 -0
- package/components/controls/phi-pagination-control-adapter.js +15 -0
- package/components/controls/phi-pagination-control.d.ts +2 -1
- package/components/controls/phi-pagination-control.js +11 -7
- package/components/controls/phi-table-control.js +1 -1
- package/components/controls/phi-timeline-control-adapter.d.ts +2 -0
- package/components/controls/phi-timeline-control-adapter.js +28 -0
- package/components/controls/phi-timeline-control.d.ts +3 -1
- package/components/controls/phi-timeline-control.js +8 -22
- package/components/controls/phi-tour-control.js +25 -7
- package/components/controls/phi-tour-viewport.d.ts +36 -0
- package/components/controls/phi-tour-viewport.js +86 -0
- package/components/controls/phi-zoom-image-overlay.d.ts +17 -0
- package/components/controls/phi-zoom-image-overlay.js +58 -0
- package/components/layouts/layout-definitions.d.ts +0 -18
- package/components/layouts/layout-definitions.js +7 -1
- package/components/layouts/plugins/carousel-layout-plugin.js +2 -1
- package/components/media/aspect-ratios.d.ts +14 -0
- package/components/media/aspect-ratios.js +13 -0
- package/components/motion/phi-sequence-run.d.ts +27 -0
- package/components/motion/phi-sequence-run.js +87 -0
- package/components/motion/phi-sequence-viewport.d.ts +16 -0
- package/components/motion/phi-sequence-viewport.js +97 -34
- package/components/overlays/phi-overlay-container-client.js +5 -2
- package/components/runtime/runtime-visual-anchors.d.ts +13 -2
- package/components/runtime/runtime-visual-anchors.js +49 -3
- package/components/widgets/config/image-variant-options.d.ts +3 -5
- package/components/widgets/config/image-variant-options.js +11 -11
- package/components/widgets/config/sequence-settings.d.ts +75 -0
- package/components/widgets/config/sequence-settings.js +173 -0
- package/components/widgets/label-sets/content-entries.d.ts +9 -0
- package/components/widgets/label-sets/content-entries.js +17 -0
- package/components/widgets/label-types/gallery.d.ts +2 -10
- package/components/widgets/label-types/sequence.d.ts +18 -0
- package/components/widgets/label-types/sequence.js +1 -0
- package/helpers/cms-layout-defaults.js +9 -2
- package/helpers/cms-region-keys.d.ts +1 -1
- package/helpers/motion.d.ts +7 -0
- package/helpers/motion.js +7 -0
- package/package.json +1 -1
- package/plugins/runtime-modules/asset/data-providers.d.ts +4 -0
- package/plugins/runtime-modules/asset/data-providers.js +1 -0
- package/plugins/runtime-modules/asset/definition.d.ts +4 -0
- package/plugins/runtime-modules/asset/presets.d.ts +53 -1
- package/plugins/runtime-modules/asset/presets.js +16 -12
- package/plugins/runtime-modules/asset/tour.d.ts +44 -0
- package/plugins/runtime-modules/asset/tour.js +53 -0
- package/plugins/runtime-modules/builder/clients/inspector-config-field.js +42 -18
- package/plugins/runtime-modules/builder/clients/inspector-image-field.js +2 -2
- package/plugins/runtime-modules/builder/clients/workspace-scope-boundary.js +10 -0
- package/plugins/runtime-modules/builder/controller/workspace-controller.js +18 -3
- package/plugins/runtime-modules/builder/plugin-meta-labels.js +8 -0
- package/plugins/runtime-modules/builder/presets.js +5 -3
- package/plugins/runtime-modules/builder/tour.d.ts +316 -0
- package/plugins/runtime-modules/builder/tour.js +337 -0
- package/plugins/runtime-modules/builder/trees/phi-builder-inspector-area-overlay-tree.server.js +8 -1
- package/plugins/runtime-modules/builder/widgets/structure-region/built-in.js +3 -2
- package/plugins/runtime-modules/core/widgets/collection-view/client.js +10 -0
- package/plugins/runtime-modules/core/widgets/description/config.d.ts +25 -1
- package/plugins/runtime-modules/core/widgets/entry-detail/config.d.ts +2 -0
- package/plugins/runtime-modules/core/widgets/entry-detail/config.js +8 -1
- package/plugins/runtime-modules/core/widgets/entry-header/config.d.ts +3 -0
- package/plugins/runtime-modules/core/widgets/entry-header/config.js +8 -1
- package/plugins/runtime-modules/core/widgets/entry-list/client.d.ts +4 -1
- package/plugins/runtime-modules/core/widgets/entry-list/client.js +3 -2
- package/plugins/runtime-modules/core/widgets/entry-list/config.d.ts +392 -93
- package/plugins/runtime-modules/core/widgets/entry-list/config.js +21 -3
- package/plugins/runtime-modules/core/widgets/entry-list/server.js +2 -0
- package/plugins/runtime-modules/core/widgets/gallery/authoring.js +62 -10
- package/plugins/runtime-modules/core/widgets/gallery/client.d.ts +6 -1
- package/plugins/runtime-modules/core/widgets/gallery/client.js +7 -79
- package/plugins/runtime-modules/core/widgets/gallery/config.d.ts +337 -144
- package/plugins/runtime-modules/core/widgets/gallery/config.js +52 -113
- package/plugins/runtime-modules/core/widgets/gallery/defaults.d.ts +15 -0
- package/plugins/runtime-modules/core/widgets/gallery/defaults.js +20 -0
- package/plugins/runtime-modules/core/widgets/image/client.js +1 -1
- package/plugins/runtime-modules/core/widgets/image/config.d.ts +29 -4
- package/plugins/runtime-modules/core/widgets/image/config.js +19 -2
- package/plugins/runtime-modules/core/widgets/image/editor.js +1 -1
- package/plugins/runtime-modules/core/widgets/result/config.d.ts +25 -1
- package/plugins/runtime-modules/core/widgets/simple-text/config.d.ts +25 -1
- package/plugins/runtime-modules/core/widgets/table/config.d.ts +79 -3
- package/plugins/runtime-modules/core/widgets/tour-button/client.js +1 -1
- package/plugins/runtime-modules/revisions/presets.d.ts +53 -2
- package/plugins/runtime-modules/revisions/presets.js +16 -12
- package/plugins/runtime-modules/revisions/tour.d.ts +43 -0
- package/plugins/runtime-modules/revisions/tour.js +51 -0
- package/plugins/runtime-modules/theme/presets.d.ts +36 -4
- package/plugins/runtime-modules/theme/tour.d.ts +45 -11
- package/plugins/runtime-modules/theme/tour.js +39 -8
- package/plugins/runtime-modules/tour/controller/address.js +2 -2
- package/plugins/runtime-modules/tour/controller/client.js +43 -2
- package/plugins/runtime-modules/tour/controller/definition.js +2 -1
- package/server-helpers/cms-request.js +1 -0
- package/server-helpers/page-tour.d.ts +10 -3
- package/server-helpers/page-tour.js +25 -12
- package/types/cms-config.d.ts +3 -1
- package/types/cms-config.js +3 -3
- package/types/cms-plugins.d.ts +31 -4
- package/types/tour-controller.d.ts +10 -0
- package/types/tour-controller.js +13 -0
- package/types/tours.d.ts +27 -25
- package/types/tours.js +9 -23
- package/types/visual-anchors.d.ts +15 -0
- package/types/visual-anchors.js +12 -0
- package/types.d.ts +2 -0
- package/types.js +4 -1
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
import { PHI_SIGNAL_VALUE_SCHEMAS } from "../../../types/signals";
|
|
2
|
+
import { PhiCmsRegionType } from "../../../constants/phi-cms";
|
|
3
|
+
import { createPhiPresetCmsInstanceId, createPhiPresetCmsInstanceIdMap, } from "../../../types/cms-instance-id";
|
|
4
|
+
import { PHI_BUILDER_AREA_SETTINGS_WIDGET_IDS } from "./addresses";
|
|
5
|
+
import { PHI_BUILDER_RUNTIME_MODULE_ID } from "./ids";
|
|
6
|
+
import { createPhiBuilderControllerAddress } from "./controller/address";
|
|
7
|
+
import { PHI_BUILDER_INSPECTOR_LAYOUT_IDS, PHI_BUILDER_INSPECTOR_OVERLAY_IDS, PHI_BUILDER_INSPECTOR_SECTION_WIDGET_IDS, } from "./inspector-overlay-addresses";
|
|
8
|
+
/*
|
|
9
|
+
* The ids the workspace tree hands its nodes once it is remapped to the route's preset
|
|
10
|
+
* (`remapBuilderPresetTreeInstanceIds`): the same Module, domain and node keys, under the Page's preset
|
|
11
|
+
* key.
|
|
12
|
+
*/
|
|
13
|
+
function builderWorkspaceWidgetIds(presetKey) {
|
|
14
|
+
return createPhiPresetCmsInstanceIdMap({
|
|
15
|
+
domain: "area",
|
|
16
|
+
ownerModuleId: PHI_BUILDER_RUNTIME_MODULE_ID,
|
|
17
|
+
presetKey,
|
|
18
|
+
}, [
|
|
19
|
+
"widgetBuilderModeSwitch",
|
|
20
|
+
"widgetToolbar",
|
|
21
|
+
"widgetDraftStatus",
|
|
22
|
+
"widgetCanvas",
|
|
23
|
+
"widgetStructureSiderFullHeightSwitch",
|
|
24
|
+
"widgetPagesHeaderSelector",
|
|
25
|
+
"widgetPagesMetaToolbar",
|
|
26
|
+
"widgetNavigationSource",
|
|
27
|
+
"widgetNavigationItems",
|
|
28
|
+
]);
|
|
29
|
+
}
|
|
30
|
+
/*
|
|
31
|
+
* The Area selector stands in the Builder's Shell and keeps the Shell's own id. A Page Tour does not make a
|
|
32
|
+
* Shell frame live; this one is found because its signal routes make it live already.
|
|
33
|
+
*/
|
|
34
|
+
const AREA_SELECTOR_ID = createPhiPresetCmsInstanceId({
|
|
35
|
+
domain: "area",
|
|
36
|
+
ownerModuleId: PHI_BUILDER_RUNTIME_MODULE_ID,
|
|
37
|
+
presetKey: "builder-area-preset",
|
|
38
|
+
nodeKey: "widgetBuilderAreaSelector",
|
|
39
|
+
});
|
|
40
|
+
/**
|
|
41
|
+
* Clicking a region, then what that click opens. The second step selects the region the first one pointed
|
|
42
|
+
* at, the way the click does -- through the Builder Controller's `selection` -- so its Inspector is open
|
|
43
|
+
* while it is described, and puts the Inspector away again when the step is left.
|
|
44
|
+
*/
|
|
45
|
+
function inspectorSteps(canvasId, regionKey, regionType) {
|
|
46
|
+
return [
|
|
47
|
+
{
|
|
48
|
+
key: "select",
|
|
49
|
+
target: `cms:${canvasId}:${regionKey}`,
|
|
50
|
+
title: "Setting something up",
|
|
51
|
+
description: "A click on a region, a Layout or a Widget opens its Inspector, where everything about it is set up.",
|
|
52
|
+
placement: "bottom",
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
key: "inspector",
|
|
56
|
+
target: `cms:${PHI_BUILDER_INSPECTOR_OVERLAY_IDS.regionInspector}`,
|
|
57
|
+
title: "The Inspector",
|
|
58
|
+
description: "For a region: its size and whether it stays put while the Page scrolls, the screens and the Pages it shows on, its spacing and its surface. A Layout and a Widget open an Inspector of their own, with their settings and the signals they send and hear. A change shows on the canvas at once and is part of the draft.",
|
|
59
|
+
placement: "left",
|
|
60
|
+
prepare: [{
|
|
61
|
+
receiver: createPhiBuilderControllerAddress(),
|
|
62
|
+
channel: "selection",
|
|
63
|
+
action: "change",
|
|
64
|
+
valueType: "json",
|
|
65
|
+
valueSchema: PHI_SIGNAL_VALUE_SCHEMAS.builderNodeSelection,
|
|
66
|
+
value: { nodeKind: "region", nodeKey: `region:${regionKey}`, regionKey, regionType },
|
|
67
|
+
}],
|
|
68
|
+
release: [INSPECTOR_CLOSE],
|
|
69
|
+
},
|
|
70
|
+
];
|
|
71
|
+
}
|
|
72
|
+
const INSPECTOR_CLOSE = {
|
|
73
|
+
receiver: createPhiBuilderControllerAddress(),
|
|
74
|
+
channel: "inspectorVisibility",
|
|
75
|
+
action: "change",
|
|
76
|
+
valueType: "boolean",
|
|
77
|
+
value: false,
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* The Layout Inspector, section by section. Each step selects the Region's root Layout -- by the Region,
|
|
81
|
+
* since a Site's node ids are not known here -- and opens its section of the Inspector; it closes the
|
|
82
|
+
* Inspector when left. From one step to the next the close and the selection arrive together, so the
|
|
83
|
+
* Inspector stays open and only the section changes. A Region without a Layout opens nothing, and the
|
|
84
|
+
* steps are passed over.
|
|
85
|
+
*
|
|
86
|
+
* The slot keys follow the order of the Layout Inspector's sections in
|
|
87
|
+
* `trees/phi-builder-inspector-area-overlay-tree.server.ts`.
|
|
88
|
+
*/
|
|
89
|
+
function layoutInspectorSteps(regionKey) {
|
|
90
|
+
const selectLayout = {
|
|
91
|
+
receiver: createPhiBuilderControllerAddress(),
|
|
92
|
+
channel: "selection",
|
|
93
|
+
action: "change",
|
|
94
|
+
valueType: "json",
|
|
95
|
+
valueSchema: PHI_SIGNAL_VALUE_SCHEMAS.builderNodeSelection,
|
|
96
|
+
value: { nodeKind: "layout", nodeKey: "layout", regionKey },
|
|
97
|
+
};
|
|
98
|
+
const openSection = (slotKey) => ({
|
|
99
|
+
receiver: `cms:${PHI_BUILDER_INSPECTOR_LAYOUT_IDS.layoutInspectorBody}`,
|
|
100
|
+
channel: "slot",
|
|
101
|
+
action: "open",
|
|
102
|
+
valueType: "string",
|
|
103
|
+
value: slotKey,
|
|
104
|
+
});
|
|
105
|
+
const step = (key, target, slotKey, title, description) => ({
|
|
106
|
+
key,
|
|
107
|
+
target: `cms:${target}`,
|
|
108
|
+
title,
|
|
109
|
+
description,
|
|
110
|
+
placement: "left",
|
|
111
|
+
ifMissing: "skip",
|
|
112
|
+
prepare: [selectLayout, openSection(slotKey)],
|
|
113
|
+
// Back to the section the Inspector opens with, so the next click finds it as it always does.
|
|
114
|
+
release: [INSPECTOR_CLOSE, openSection("slot_0")],
|
|
115
|
+
});
|
|
116
|
+
const ids = PHI_BUILDER_INSPECTOR_SECTION_WIDGET_IDS;
|
|
117
|
+
return [
|
|
118
|
+
/*
|
|
119
|
+
* The whole Inspector rather than its Settings section: a kind that declares no settings hides the
|
|
120
|
+
* section, and a step waiting for it would hold the Tour until its wait runs out.
|
|
121
|
+
*/
|
|
122
|
+
step("layout-settings", PHI_BUILDER_INSPECTOR_OVERLAY_IDS.layoutInspector, "slot_0", "What only this Layout has", "A Layout's Inspector starts with the settings of its kind: the columns of a grid, the direction and the gaps of a row, the slides of a carousel. A kind without settings of its own starts with the anchor. Every kind of Layout and Widget brings its own."),
|
|
123
|
+
step("layout-anchor", ids.layoutAnchor, "slot_1", "Where it sits", "The anchor aligns the Layout in the space it is given: to an edge, to a corner, or in the middle."),
|
|
124
|
+
step("layout-padding", ids.layoutPadding, "slot_2", "Room inside", "Besides the paddings at its edges, the Layout has a gap in the middle: the space between the things that stand in it, side by side or one below the other. One value keeps them all the same distance apart."),
|
|
125
|
+
step("layout-viewport", ids.layoutViewport, "slot_3", "On which screens", "Whether the Layout shows on compact, medium and wide screens -- hidden on one, it is still there on the others."),
|
|
126
|
+
step("layout-surface", ids.layoutSurface, "slot_4", "What it stands on", "The surface is what the Layout stands on: none, one of the Theme's styles -- Card or Wash -- or Custom, which opens its background (a colour or an image), its border and its shadow. Mode draws it in the Page's colours, always light, always dark, or the other way round. A region has one as well; a Widget usually stands on its Layout's."),
|
|
127
|
+
step("layout-signals", ids.layoutSignals, "slot_5", "What it says and hears", "Signals connect the Layout with other parts of the Page: what it sends when something happens in it, and what it answers to -- a button that opens a slot, a list that follows a choice."),
|
|
128
|
+
];
|
|
129
|
+
}
|
|
130
|
+
const SHELLS_IDS = builderWorkspaceWidgetIds("builder-shells-page");
|
|
131
|
+
const PAGES_IDS = builderWorkspaceWidgetIds("builder-pages-page");
|
|
132
|
+
/**
|
|
133
|
+
* The Shells workspace's Tour. What the workspace does not say is what a Shell is: the frame every Page
|
|
134
|
+
* of the Area stands in, so a change here reaches all of them at once. The rest is the order a person
|
|
135
|
+
* meets the workspace in, ending where the work goes live. The canvas steps point at single Regions
|
|
136
|
+
* (`cms:<canvas>:<regionKey>`): the canvas is taller than the window, and pointing at all of it scrolled
|
|
137
|
+
* it under the Builder's header and lit the header up with it.
|
|
138
|
+
*/
|
|
139
|
+
export const PHI_BUILDER_SHELLS_TOUR = {
|
|
140
|
+
id: `${PHI_BUILDER_RUNTIME_MODULE_ID}/shells`,
|
|
141
|
+
version: 1,
|
|
142
|
+
steps: [
|
|
143
|
+
{
|
|
144
|
+
key: "area",
|
|
145
|
+
target: `cms:${AREA_SELECTOR_ID}`,
|
|
146
|
+
title: "Which Area you are building",
|
|
147
|
+
description: "Every Area has its own Shell, and everything in this workspace applies to the Area chosen here. Usually only Public and App are worked on; the other Areas come as their Modules build them.",
|
|
148
|
+
placement: "bottom",
|
|
149
|
+
ifMissing: "skip",
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
key: "shell",
|
|
153
|
+
target: `cms:${SHELLS_IDS.widgetCanvas}:header_main`,
|
|
154
|
+
title: "The frame of every Page",
|
|
155
|
+
description: "The Shell is what every Page of the Area shares: the rows of the header, the left sider and the footer. What you change here appears on all of them.",
|
|
156
|
+
placement: "bottom",
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
key: "regions",
|
|
160
|
+
target: `cms:${SHELLS_IDS.widgetCanvas}:sider_left`,
|
|
161
|
+
title: "Regions and what stands in them",
|
|
162
|
+
description: "A region holds only Layouts, and a Layout holds further Layouts or Widgets, so the first thing placed in an empty region is always a Layout.",
|
|
163
|
+
placement: "right",
|
|
164
|
+
},
|
|
165
|
+
...inspectorSteps(SHELLS_IDS.widgetCanvas, "header_top", PhiCmsRegionType.HeaderTop),
|
|
166
|
+
...layoutInspectorSteps("header_top"),
|
|
167
|
+
{
|
|
168
|
+
key: "mode",
|
|
169
|
+
target: `cms:${SHELLS_IDS.widgetBuilderModeSwitch}`,
|
|
170
|
+
title: "Editor and Preview",
|
|
171
|
+
description: "Editor shows the regions to work in. Preview gives a first impression of your changes without saving them -- a sketch, not exactly what a visitor will see.",
|
|
172
|
+
placement: "bottom",
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
key: "sider",
|
|
176
|
+
target: `cms:${SHELLS_IDS.widgetStructureSiderFullHeightSwitch}`,
|
|
177
|
+
title: "How tall the sider is",
|
|
178
|
+
description: "Whether the left sider runs the full height of the Shell, or stands beside the content between header and footer.",
|
|
179
|
+
placement: "bottom",
|
|
180
|
+
ifMissing: "skip",
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
key: "area-settings",
|
|
184
|
+
target: `cms:${PHI_BUILDER_AREA_SETTINGS_WIDGET_IDS.areaSettingsAction}`,
|
|
185
|
+
title: "What the Area says about itself",
|
|
186
|
+
description: "What the Area's own address shows, how Page titles are built, and for the public Area whether search engines may find it.",
|
|
187
|
+
placement: "bottom",
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
key: "commands",
|
|
191
|
+
target: `cms:${SHELLS_IDS.widgetToolbar}`,
|
|
192
|
+
title: "Saving and publishing",
|
|
193
|
+
description: "Save keeps your changes as a draft, and Live preview opens the Area with it. Publish puts the Shell live on every Page; publishing takes the Publisher role. Undo and Redo step through your changes, and Reset discards the draft without touching what is live.",
|
|
194
|
+
placement: "bottom",
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
key: "draft-status",
|
|
198
|
+
target: `cms:${SHELLS_IDS.widgetDraftStatus}`,
|
|
199
|
+
title: "Where your changes stand",
|
|
200
|
+
description: "What you change here is a draft. Visitors see the published Shell until the draft is published.",
|
|
201
|
+
placement: "bottom",
|
|
202
|
+
},
|
|
203
|
+
],
|
|
204
|
+
};
|
|
205
|
+
/**
|
|
206
|
+
* The Pages workspace's Tour. Its first point is the split with Shells: a Page owns its own regions, and
|
|
207
|
+
* the frame around them is not edited here. A new or deleted Page is a draft like any other change.
|
|
208
|
+
*/
|
|
209
|
+
export const PHI_BUILDER_PAGES_TOUR = {
|
|
210
|
+
id: `${PHI_BUILDER_RUNTIME_MODULE_ID}/pages`,
|
|
211
|
+
version: 1,
|
|
212
|
+
steps: [
|
|
213
|
+
{
|
|
214
|
+
key: "area",
|
|
215
|
+
target: `cms:${AREA_SELECTOR_ID}`,
|
|
216
|
+
title: "Which Area you are building",
|
|
217
|
+
description: "Every Area has its own Pages, and the Page list below holds those of the Area chosen here. Usually only Public and App are worked on; the other Areas come as their Modules build them.",
|
|
218
|
+
placement: "bottom",
|
|
219
|
+
ifMissing: "skip",
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
key: "page-choice",
|
|
223
|
+
target: `cms:${PAGES_IDS.widgetPagesHeaderSelector}`,
|
|
224
|
+
title: "Which Page you are building",
|
|
225
|
+
description: "Every Page of the Area, the ones created here and the ones a Module brings.",
|
|
226
|
+
placement: "bottom",
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
key: "page",
|
|
230
|
+
target: `cms:${PAGES_IDS.widgetCanvas}:content`,
|
|
231
|
+
title: "What belongs to this Page",
|
|
232
|
+
description: "The content, the hero, the row under the header, the right sider, the row above the footer and the drawer are this Page's alone. The frame around them is the Shell, edited under Shells.",
|
|
233
|
+
placement: "top",
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
key: "regions",
|
|
237
|
+
target: `cms:${PAGES_IDS.widgetCanvas}:hero`,
|
|
238
|
+
title: "Regions and what stands in them",
|
|
239
|
+
description: "A region holds only Layouts, and a Layout holds further Layouts or Widgets, so the first thing placed in an empty region is always a Layout.",
|
|
240
|
+
placement: "bottom",
|
|
241
|
+
},
|
|
242
|
+
...inspectorSteps(PAGES_IDS.widgetCanvas, "header_bottom", PhiCmsRegionType.HeaderBottom),
|
|
243
|
+
...layoutInspectorSteps("content"),
|
|
244
|
+
{
|
|
245
|
+
key: "page-commands",
|
|
246
|
+
target: `cms:${PAGES_IDS.widgetPagesMetaToolbar}`,
|
|
247
|
+
title: "New Pages and what a Page says",
|
|
248
|
+
description: "New page creates one in this Area. Page meta sets its title, its description and whether search engines may find it. Delete takes the Page away once the change is published.",
|
|
249
|
+
placement: "bottom",
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
key: "mode",
|
|
253
|
+
target: `cms:${PAGES_IDS.widgetBuilderModeSwitch}`,
|
|
254
|
+
title: "Editor and Preview",
|
|
255
|
+
description: "Editor shows the regions to work in. Preview gives a first impression of your changes without saving them -- a sketch, not exactly what a visitor will see.",
|
|
256
|
+
placement: "bottom",
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
key: "commands",
|
|
260
|
+
target: `cms:${PAGES_IDS.widgetToolbar}`,
|
|
261
|
+
title: "Saving and publishing",
|
|
262
|
+
description: "Save keeps your changes as a draft, and Live preview opens the Page with it. Publish puts it live, and a new Page exists for visitors only from then on; publishing takes the Publisher role. Undo and Redo step through your changes, and Reset discards the draft without touching what is live.",
|
|
263
|
+
placement: "bottom",
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
key: "draft-status",
|
|
267
|
+
target: `cms:${PAGES_IDS.widgetDraftStatus}`,
|
|
268
|
+
title: "Where your changes stand",
|
|
269
|
+
description: "What you change here is a draft. Visitors see the published Page until the draft is published.",
|
|
270
|
+
placement: "bottom",
|
|
271
|
+
},
|
|
272
|
+
],
|
|
273
|
+
};
|
|
274
|
+
const NAVIGATION_IDS = builderWorkspaceWidgetIds("builder-navigation-page");
|
|
275
|
+
/**
|
|
276
|
+
* The Navigation workspace's Tour. What the workspace does not say is that a Site has several
|
|
277
|
+
* navigations, that a Page is linked by dragging it across rather than by typing its path, and that the
|
|
278
|
+
* items a Module brings stand in the same list as the Site's own.
|
|
279
|
+
*/
|
|
280
|
+
export const PHI_BUILDER_NAVIGATION_TOUR = {
|
|
281
|
+
id: `${PHI_BUILDER_RUNTIME_MODULE_ID}/navigation`,
|
|
282
|
+
version: 1,
|
|
283
|
+
steps: [
|
|
284
|
+
{
|
|
285
|
+
key: "choice",
|
|
286
|
+
target: `cms:${NAVIGATION_IDS.widgetNavigationItems}:filters`,
|
|
287
|
+
title: "Which navigation",
|
|
288
|
+
description: "A Site has more than one navigation -- the main menu, the one in the footer, a sider's. Everything below belongs to the one chosen here, and the plus beside it adds a new one under a key of its own.",
|
|
289
|
+
placement: "bottom",
|
|
290
|
+
ifMissing: "skip",
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
key: "source",
|
|
294
|
+
target: `cms:${NAVIGATION_IDS.widgetNavigationSource}`,
|
|
295
|
+
title: "The Pages to link",
|
|
296
|
+
description: "Every Page of the Area chosen above the list. Drag one into the navigation to link it, onto a container to put it inside; the link follows the Page wherever its path goes.",
|
|
297
|
+
placement: "right",
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
key: "items",
|
|
301
|
+
target: `cms:${NAVIGATION_IDS.widgetNavigationItems}:header`,
|
|
302
|
+
title: "What the navigation holds",
|
|
303
|
+
description: "A row per item, in the order it is shown. Drag a row to move it, into a container to nest it. A click on a label or an icon changes it in place. Origin says whether the item is the Site's own or came with a Module.",
|
|
304
|
+
placement: "bottom",
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
key: "add",
|
|
308
|
+
target: `cms:${NAVIGATION_IDS.widgetNavigationItems}:toolbar`,
|
|
309
|
+
title: "Links, containers, separators",
|
|
310
|
+
description: "Add link adds a link to an address outside the Site, written in its Path; a Page of the Site is linked by dragging it in. A container holds further items and opens as a group; a separator draws a line between them.",
|
|
311
|
+
placement: "bottom",
|
|
312
|
+
ifMissing: "skip",
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
key: "row-actions",
|
|
316
|
+
target: `cms:${NAVIGATION_IDS.widgetNavigationItems}:row-actions`,
|
|
317
|
+
title: "Hiding and deleting",
|
|
318
|
+
description: "A hidden item stays in the list and keeps its place, but visitors do not see it. Delete takes it out; Undo brings it back.",
|
|
319
|
+
placement: "left",
|
|
320
|
+
ifMissing: "skip",
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
key: "commands",
|
|
324
|
+
target: `cms:${NAVIGATION_IDS.widgetToolbar}`,
|
|
325
|
+
title: "Saving and publishing",
|
|
326
|
+
description: "Save keeps your changes as a draft, and Live preview shows the Site with it. Publish puts the navigation live; publishing takes the Publisher role. Undo and Redo step through your changes, and Reset discards the draft without touching what is live.",
|
|
327
|
+
placement: "bottom",
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
key: "draft-status",
|
|
331
|
+
target: `cms:${NAVIGATION_IDS.widgetDraftStatus}`,
|
|
332
|
+
title: "Where your changes stand",
|
|
333
|
+
description: "What you change here is a draft. Visitors see the published navigation until the draft is published.",
|
|
334
|
+
placement: "bottom",
|
|
335
|
+
},
|
|
336
|
+
],
|
|
337
|
+
};
|
package/plugins/runtime-modules/builder/trees/phi-builder-inspector-area-overlay-tree.server.js
CHANGED
|
@@ -243,7 +243,7 @@ export async function buildPhiBuilderInspectorAreaOverlayTree({ page, runtime, }
|
|
|
243
243
|
], [
|
|
244
244
|
PHI_BUILDER_INSPECTOR_LAYOUT_IDS.widgetInspectorBody,
|
|
245
245
|
PHI_BUILDER_INSPECTOR_SECTIONS.widget,
|
|
246
|
-
]].map(([id, sections]) => nodes.layout({
|
|
246
|
+
]].map(([id, sections], index) => nodes.layout({
|
|
247
247
|
typeKey: "collapsible",
|
|
248
248
|
id,
|
|
249
249
|
parentLayoutNodeId: null,
|
|
@@ -262,6 +262,13 @@ export async function buildPhiBuilderInspectorAreaOverlayTree({ page, runtime, }
|
|
|
262
262
|
innerPadding: PHI_SPACE.sm,
|
|
263
263
|
slotTitles: sections.map(([, , sectionKey]) => resolveBuilderInspectorSectionTitle(inspectorLabels, sectionKey)),
|
|
264
264
|
defaultOpenSlotKeys: ["slot_0"],
|
|
265
|
+
/*
|
|
266
|
+
* A section opened by name: the Builder Tour opens one after another while it describes them
|
|
267
|
+
* (`builder/tour.ts`). `slot_<index>` in the order of `PHI_BUILDER_INSPECTOR_SECTIONS`.
|
|
268
|
+
*/
|
|
269
|
+
signalRoutes: {
|
|
270
|
+
listens: [{ routeKey: `builder-inspector-section-open-${index}`, capabilityId: "slotOpen", scope: "area", channel: "slot", action: "open", valueType: "string", receiver: createPhiSignalAddress("cms", id) }],
|
|
271
|
+
},
|
|
265
272
|
},
|
|
266
273
|
})),
|
|
267
274
|
nodes.layout({
|
|
@@ -18,6 +18,7 @@ import { createPhiSignalAddress, } from "../../../../../types/signals";
|
|
|
18
18
|
import { resolvePhiShellRegionTypography, resolvePhiShellRegionZIndex } from "../../../../../helpers/shell-region-style";
|
|
19
19
|
import { phiCmsRegionAcceptsWidget, resolvePhiCmsRegionType } from "../../../../../helpers/cms-region-keys";
|
|
20
20
|
import { usePhiRuntimeModuleState } from "../../../../../components/runtime/runtime-module-context";
|
|
21
|
+
import { PHI_VISUAL_ANCHOR_PART_ATTRIBUTE } from "../../../../../types/visual-anchors";
|
|
21
22
|
import { renderPhiRootNodeScaffold, resolveLayoutNodeRootProps, } from "../../../../../plugins/runtime-modules/builder/render-root-node-scaffold";
|
|
22
23
|
import { PhiBuilderInsertPickerControl } from "../../../../../components/controls/phi-builder-insert-picker-control";
|
|
23
24
|
import { readPhiBuilderRegionRootChildLayouts, readPhiBuilderRegionRootChildWidgets, withPhiBuilderRegionRootChildren, } from "../../../../../plugins/runtime-modules/builder/region-root-node";
|
|
@@ -1193,7 +1194,7 @@ export function PhiStructureRegionScaffold({ config, serverPreview, structureDra
|
|
|
1193
1194
|
: shouldStretchAvailableHeight
|
|
1194
1195
|
? "100%"
|
|
1195
1196
|
: undefined;
|
|
1196
|
-
return (_jsx("div", { "data-phi-region-slot": config.regionKey, className: ["phi-builder-structure-region__slot", regionToneClassName].filter(Boolean).join(" "), "data-phi-builder-region-mode": "preview", "data-phi-builder-region-has-root-node": hasRootNode ? "true" : "false", "data-phi-builder-region-selected": "false", "data-phi-builder-region-picking": "false", style: {
|
|
1197
|
+
return (_jsx("div", { "data-phi-region-slot": config.regionKey, [PHI_VISUAL_ANCHOR_PART_ATTRIBUTE]: config.regionKey, className: ["phi-builder-structure-region__slot", regionToneClassName].filter(Boolean).join(" "), "data-phi-builder-region-mode": "preview", "data-phi-builder-region-has-root-node": hasRootNode ? "true" : "false", "data-phi-builder-region-selected": "false", "data-phi-builder-region-picking": "false", style: {
|
|
1197
1198
|
width: slotWidth,
|
|
1198
1199
|
minWidth: slotMinWidth,
|
|
1199
1200
|
maxWidth: slotMaxWidth,
|
|
@@ -1226,7 +1227,7 @@ export function PhiStructureRegionScaffold({ config, serverPreview, structureDra
|
|
|
1226
1227
|
shouldFillAvailableHeight ? "phi-builder-structure-region--full-height" : null,
|
|
1227
1228
|
!shouldFillAvailableHeight ? "phi-builder-structure-region--compact" : null,
|
|
1228
1229
|
containerClassName,
|
|
1229
|
-
].filter(Boolean).join(" "), "data-phi-builder-region-mode": isPreviewMode ? "preview" : "editor", "data-phi-builder-region-has-root-node": hasRootNode ? "true" : "false", "data-phi-builder-region-selected": isSelected ? "true" : "false", "data-phi-builder-region-picking": isPicking ? "true" : "false", role: config.allowSelect && !isPreviewMode ? "button" : undefined, tabIndex: config.allowSelect && !isPreviewMode ? 0 : undefined, style: {
|
|
1230
|
+
].filter(Boolean).join(" "), [PHI_VISUAL_ANCHOR_PART_ATTRIBUTE]: config.regionKey, "data-phi-builder-region-mode": isPreviewMode ? "preview" : "editor", "data-phi-builder-region-has-root-node": hasRootNode ? "true" : "false", "data-phi-builder-region-selected": isSelected ? "true" : "false", "data-phi-builder-region-picking": isPicking ? "true" : "false", role: config.allowSelect && !isPreviewMode ? "button" : undefined, tabIndex: config.allowSelect && !isPreviewMode ? 0 : undefined, style: {
|
|
1230
1231
|
border: `1px dashed ${token.colorBorderSecondary}`,
|
|
1231
1232
|
// The area a Region lives in: a faint layout tint so the Theme Root Background stays visible.
|
|
1232
1233
|
backgroundColor: `color-mix(in srgb, ${token.colorBgLayout} 20%, transparent)`,
|
|
@@ -6,15 +6,25 @@ import { PhiCollectionViewSkeletonControl } from "../../../../../components/cont
|
|
|
6
6
|
import { normalizePhiCssSize } from "../../../../../components/layouts/phi-layout-contract";
|
|
7
7
|
import { usePhiConfig } from "../../../../../components/root/phi-config-provider";
|
|
8
8
|
import { usePhiRuntimeModuleRenderClient } from "../../../../../components/runtime/runtime-module-render-client-manifest";
|
|
9
|
+
import { usePhiSignalIdentity } from "../../../../../components/runtime/runtime-signal-identity";
|
|
10
|
+
import { usePhiVisualAnchorParts } from "../../../../../components/runtime/runtime-visual-anchors";
|
|
9
11
|
import { createPhiSignalAddress } from "../../../../../types/signals";
|
|
10
12
|
import { usePhiControlSignalController } from "../../../../../components/widgets/client/shared/phi-control-signals";
|
|
11
13
|
import { usePhiCollectionViewBinding } from "../../../../../components/widgets/client/shared/phi-collection-view-binding";
|
|
14
|
+
/**
|
|
15
|
+
* The parts of a Collection View a Tour can point at, as `cms:<instanceId>:<part>` (design/TOURS.md): the
|
|
16
|
+
* filters and search, the toolbar, the items and the pagination. A part the view does not draw is simply
|
|
17
|
+
* not found, and the step pointing at it does what its `ifMissing` says.
|
|
18
|
+
*/
|
|
19
|
+
const PHI_COLLECTION_VIEW_VISUAL_ANCHOR_PARTS = ["filters", "toolbar", "items", "pagination"];
|
|
12
20
|
function PhiCollectionViewWidgetPreview({ config, skeletonActive = true, }) {
|
|
13
21
|
const { token } = usePhiConfig();
|
|
14
22
|
const presentation = config?.presentation;
|
|
15
23
|
return (_jsx(PhiCollectionViewSkeletonControl, { mode: presentation?.mode ?? "grid", gap: normalizePhiCssSize(presentation?.gap) ?? token.paddingSM, minColumnWidth: normalizePhiCssSize(presentation?.minColumnWidth) ?? 102, active: skeletonActive }));
|
|
16
24
|
}
|
|
17
25
|
function PhiCollectionViewWidgetLive({ config, labels, widgetId, }) {
|
|
26
|
+
const signalIdentity = usePhiSignalIdentity();
|
|
27
|
+
usePhiVisualAnchorParts(signalIdentity.receiver?.startsWith("cms:") ? signalIdentity.receiver : null, PHI_COLLECTION_VIEW_VISUAL_ANCHOR_PARTS);
|
|
18
28
|
const source = config?.source ?? null;
|
|
19
29
|
const { resource, bindingError, binding } = usePhiCollectionViewBinding({
|
|
20
30
|
source,
|
|
@@ -68,6 +68,7 @@ export declare const PHI_DESCRIPTION_WIDGET_DEFINITION: {
|
|
|
68
68
|
} & {
|
|
69
69
|
type: "data-provider";
|
|
70
70
|
providerKind?: import("../../../../../types").PhiRuntimeDataProviderKind;
|
|
71
|
+
providerKey?: import("@phis/contracts/controls").PhiRuntimeDataProviderKey;
|
|
71
72
|
}) | ({
|
|
72
73
|
key: string;
|
|
73
74
|
label: string;
|
|
@@ -241,10 +242,33 @@ export declare const PHI_DESCRIPTION_WIDGET_DEFINITION: {
|
|
|
241
242
|
editorPlacement?: "inspector" | "geometry" | "toolbar";
|
|
242
243
|
visibleWhen?: import("../../../../../types").PhiCmsConfigFieldVisibilityRule | readonly import("../../../../../types").PhiCmsConfigFieldVisibilityRule[];
|
|
243
244
|
heading?: string;
|
|
245
|
+
} & {
|
|
246
|
+
type: "choice";
|
|
247
|
+
valueType: "number";
|
|
248
|
+
options: import("@phis/contracts/controls").PhiControlOption<number>[];
|
|
249
|
+
emptyOption?: import("@phis/contracts/controls").PhiControlOption;
|
|
250
|
+
emptyValue?: null | undefined;
|
|
251
|
+
placeholder?: string;
|
|
252
|
+
mode?: never;
|
|
253
|
+
presentation?: never;
|
|
254
|
+
optionsProvider?: never;
|
|
255
|
+
allowCustom?: never;
|
|
256
|
+
createBehavior?: never;
|
|
257
|
+
filter?: never;
|
|
258
|
+
patchOnChange?: never;
|
|
259
|
+
optionPresets?: never;
|
|
260
|
+
}) | ({
|
|
261
|
+
key: string;
|
|
262
|
+
label: string;
|
|
263
|
+
description?: string;
|
|
264
|
+
required?: boolean;
|
|
265
|
+
editorPlacement?: "inspector" | "geometry" | "toolbar";
|
|
266
|
+
visibleWhen?: import("../../../../../types").PhiCmsConfigFieldVisibilityRule | readonly import("../../../../../types").PhiCmsConfigFieldVisibilityRule[];
|
|
267
|
+
heading?: string;
|
|
244
268
|
} & {
|
|
245
269
|
type: "choice";
|
|
246
270
|
mode?: import("../../../../../types").PhiCmsConfigFieldChoiceMode;
|
|
247
|
-
valueType?: import("../../../../../types").PhiCmsConfigFieldChoiceValueType
|
|
271
|
+
valueType?: Exclude<import("../../../../../types").PhiCmsConfigFieldChoiceValueType, "number">;
|
|
248
272
|
presentation?: import("../../../../../types").PhiCmsConfigFieldChoicePresentation;
|
|
249
273
|
options?: import("@phis/contracts/controls").PhiControlOption[];
|
|
250
274
|
optionsProvider?: import("@phis/contracts/controls").PhiControlOptionsProviderConfig;
|
|
@@ -24,6 +24,7 @@ export declare const PHI_ENTRY_DETAIL_WIDGET_DEFINITION: {
|
|
|
24
24
|
key: string;
|
|
25
25
|
type: "data-provider";
|
|
26
26
|
providerKind: "record";
|
|
27
|
+
providerKey: `${string}/${string}`;
|
|
27
28
|
label: string;
|
|
28
29
|
options?: undefined;
|
|
29
30
|
} | {
|
|
@@ -56,6 +57,7 @@ export declare const PHI_ENTRY_DETAIL_WIDGET_DEFINITION: {
|
|
|
56
57
|
readonly label: "Link";
|
|
57
58
|
})[];
|
|
58
59
|
providerKind?: undefined;
|
|
60
|
+
providerKey?: undefined;
|
|
59
61
|
})[];
|
|
60
62
|
defaultConfig: PhiEntryDetailWidgetConfig;
|
|
61
63
|
parseConfig: (config: Record<string, unknown>) => PhiEntryDetailWidgetConfig;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PHI_CORE_RUNTIME_DATA_PROVIDER_KEYS } from "../../../../../constants/core-data-provider-keys";
|
|
1
2
|
import { isPhiRecord } from "../../../../../helpers/is-record";
|
|
2
3
|
import { resolvePhiCmsWidgetPluginKey } from "../../../../../constants/cms-widget-types";
|
|
3
4
|
import { readPhiContentEntryRecordBinding } from "../../../../../helpers/content-entry-record-binding";
|
|
@@ -27,7 +28,13 @@ export const PHI_ENTRY_DETAIL_WIDGET_DEFINITION = {
|
|
|
27
28
|
icon: "antd:read",
|
|
28
29
|
slotSizePolicy: "fill-inline",
|
|
29
30
|
fields: [
|
|
30
|
-
{
|
|
31
|
+
{
|
|
32
|
+
key: "entry",
|
|
33
|
+
type: "data-provider",
|
|
34
|
+
providerKind: "record",
|
|
35
|
+
providerKey: PHI_CORE_RUNTIME_DATA_PROVIDER_KEYS.contentEntry,
|
|
36
|
+
label: "Entry",
|
|
37
|
+
},
|
|
31
38
|
{ key: "show", type: "flags", label: "Show", options: phiContentEntryPartOptions(PHI_ENTRY_DETAIL_PARTS) },
|
|
32
39
|
],
|
|
33
40
|
defaultConfig: normalizePhiEntryDetailWidgetConfig(null),
|
|
@@ -30,6 +30,7 @@ export declare const PHI_ENTRY_HEADER_WIDGET_DEFINITION: {
|
|
|
30
30
|
key: string;
|
|
31
31
|
type: "data-provider";
|
|
32
32
|
providerKind: "record";
|
|
33
|
+
providerKey: `${string}/${string}`;
|
|
33
34
|
label: string;
|
|
34
35
|
options?: undefined;
|
|
35
36
|
} | {
|
|
@@ -62,6 +63,7 @@ export declare const PHI_ENTRY_HEADER_WIDGET_DEFINITION: {
|
|
|
62
63
|
readonly label: "Link";
|
|
63
64
|
})[];
|
|
64
65
|
providerKind?: undefined;
|
|
66
|
+
providerKey?: undefined;
|
|
65
67
|
} | {
|
|
66
68
|
key: string;
|
|
67
69
|
type: "choice";
|
|
@@ -71,6 +73,7 @@ export declare const PHI_ENTRY_HEADER_WIDGET_DEFINITION: {
|
|
|
71
73
|
label: string;
|
|
72
74
|
}[];
|
|
73
75
|
providerKind?: undefined;
|
|
76
|
+
providerKey?: undefined;
|
|
74
77
|
})[];
|
|
75
78
|
defaultConfig: PhiEntryHeaderWidgetConfig;
|
|
76
79
|
parseConfig: (config: Record<string, unknown>) => PhiEntryHeaderWidgetConfig;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PHI_CORE_RUNTIME_DATA_PROVIDER_KEYS } from "../../../../../constants/core-data-provider-keys";
|
|
1
2
|
import { isPhiRecord } from "../../../../../helpers/is-record";
|
|
2
3
|
import { resolvePhiCmsWidgetPluginKey } from "../../../../../constants/cms-widget-types";
|
|
3
4
|
import { readPhiContentEntryRecordBinding } from "../../../../../helpers/content-entry-record-binding";
|
|
@@ -32,7 +33,13 @@ export const PHI_ENTRY_HEADER_WIDGET_DEFINITION = {
|
|
|
32
33
|
icon: "antd:profile",
|
|
33
34
|
slotSizePolicy: "fill-inline",
|
|
34
35
|
fields: [
|
|
35
|
-
{
|
|
36
|
+
{
|
|
37
|
+
key: "entry",
|
|
38
|
+
type: "data-provider",
|
|
39
|
+
providerKind: "record",
|
|
40
|
+
providerKey: PHI_CORE_RUNTIME_DATA_PROVIDER_KEYS.contentEntry,
|
|
41
|
+
label: "Entry",
|
|
42
|
+
},
|
|
36
43
|
{ key: "show", type: "flags", label: "Show", options: phiContentEntryPartOptions(PHI_ENTRY_HEADER_PARTS) },
|
|
37
44
|
{
|
|
38
45
|
key: "titleLevel",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type PhiMarkdownBlock } from "../../../../../components/widgets/shared/markdown-body-client";
|
|
2
|
+
import type { PhiSequenceSettings } from "../../../../../components/widgets/config/sequence-settings";
|
|
2
3
|
import type { PhiEntryListPresentation } from "./config";
|
|
3
4
|
import type { PhiContentEntryReaderLabels } from "../../../../../components/widgets/label-sets/content-entries";
|
|
4
5
|
/**
|
|
@@ -53,6 +54,8 @@ export type PhiEntryListWidgetClientProps = {
|
|
|
53
54
|
parts: number;
|
|
54
55
|
/** The list's own heading, drawn only above entries -- an empty related list leaves no heading behind. */
|
|
55
56
|
title?: string;
|
|
57
|
+
/** How a slideshow moves; only a slideshow is handed one. */
|
|
58
|
+
sequence?: PhiSequenceSettings;
|
|
56
59
|
/** Whether no entries is said or simply nothing: a related list under an entry says nothing. */
|
|
57
60
|
emptyBehavior?: "say" | "hide";
|
|
58
61
|
};
|
|
@@ -92,4 +95,4 @@ export declare function PhiEntryBody({ entry, parts, labels, }: {
|
|
|
92
95
|
* through one: the Controls are where antd lives, and a server component cannot use them. Nothing here
|
|
93
96
|
* depends on the visitor, so the first paint already carries every entry.
|
|
94
97
|
*/
|
|
95
|
-
export declare function PhiEntryListWidgetClient({ entries, labels, presentation, parts, title, emptyBehavior, }: PhiEntryListWidgetClientProps): import("react").JSX.Element | null;
|
|
98
|
+
export declare function PhiEntryListWidgetClient({ entries, labels, presentation, parts, title, sequence, emptyBehavior, }: PhiEntryListWidgetClientProps): import("react").JSX.Element | null;
|
|
@@ -10,6 +10,7 @@ import { PhiLink } from "../../../../../components/navigation/phi-link";
|
|
|
10
10
|
import { PhiMarkdownWidgetClient, } from "../../../../../components/widgets/shared/markdown-body-client";
|
|
11
11
|
import { PhiCollectionLayoutControl } from "../../../../../components/controls/phi-collection-layout-control";
|
|
12
12
|
import { PhiCardWidgetClient } from "../../../../../components/widgets/shared/card-body-client";
|
|
13
|
+
import { PhiSequenceRun } from "../../../../../components/motion/phi-sequence-run";
|
|
13
14
|
import { PHI_SURFACE_CARD } from "../../../../../helpers/surface-presets";
|
|
14
15
|
import { PHI_FONT_SIZE, PHI_SPACE } from "../../../../../theme/antd-css-var-contract";
|
|
15
16
|
import { hasPhiContentEntryPart, PhiContentEntryPart } from "../../../../../constants/content-entry-parts";
|
|
@@ -113,7 +114,7 @@ function PhiEntryArticle({ entry, labels, parts, }) {
|
|
|
113
114
|
* through one: the Controls are where antd lives, and a server component cannot use them. Nothing here
|
|
114
115
|
* depends on the visitor, so the first paint already carries every entry.
|
|
115
116
|
*/
|
|
116
|
-
export function PhiEntryListWidgetClient({ entries, labels, presentation, parts, title, emptyBehavior = "say", }) {
|
|
117
|
+
export function PhiEntryListWidgetClient({ entries, labels, presentation, parts, title, sequence, emptyBehavior = "say", }) {
|
|
117
118
|
if (entries.length === 0) {
|
|
118
119
|
if (emptyBehavior === "hide")
|
|
119
120
|
return null;
|
|
@@ -125,6 +126,6 @@ export function PhiEntryListWidgetClient({ entries, labels, presentation, parts,
|
|
|
125
126
|
* Still an `h2`, in the rule, so the Page's outline keeps it.
|
|
126
127
|
*/
|
|
127
128
|
const heading = title ? (_jsx(PhiDividerControl, { titlePlacement: "start", style: { margin: 0 }, children: _jsx(PhiTypographyControl, { presentation: "title", level: 2, style: { margin: 0, fontSize: PHI_FONT_SIZE.lg }, children: title }) })) : null;
|
|
128
|
-
const body = presentation === "cards" ? (_jsx(PhiCollectionLayoutControl, { mode: "grid", gap: PHI_SPACE.base, minColumnWidth: ENTRY_CARD_MIN_COLUMN_WIDTH, items: entries.map((entry) => _jsx(PhiEntryCard, { entry: entry, parts: parts }, entry.id)) })) : presentation === "compact" ? (_jsx(PhiFlexControl, { vertical: true, gap: PHI_SPACE.base, children: entries.map((entry) => _jsx(PhiEntryLine, { entry: entry, parts: parts }, entry.id)) })) : (_jsx(PhiFlexControl, { vertical: true, gap: PHI_SPACE.lg, children: entries.map((entry, index) => (_jsxs(PhiFlexControl, { vertical: true, gap: PHI_SPACE.lg, children: [index > 0 ? _jsx(PhiDividerControl, { style: { margin: 0 } }) : null, _jsx(PhiEntryArticle, { entry: entry, labels: labels, parts: parts })] }, entry.id))) }));
|
|
129
|
+
const body = presentation === "slideshow" ? (_jsx(PhiSequenceRun, { items: entries.map((entry) => _jsx(PhiEntryCard, { entry: entry, parts: parts }, entry.id)), settings: sequence, labels: labels.sequence })) : presentation === "cards" ? (_jsx(PhiCollectionLayoutControl, { mode: "grid", gap: PHI_SPACE.base, minColumnWidth: ENTRY_CARD_MIN_COLUMN_WIDTH, items: entries.map((entry) => _jsx(PhiEntryCard, { entry: entry, parts: parts }, entry.id)) })) : presentation === "compact" ? (_jsx(PhiFlexControl, { vertical: true, gap: PHI_SPACE.base, children: entries.map((entry) => _jsx(PhiEntryLine, { entry: entry, parts: parts }, entry.id)) })) : (_jsx(PhiFlexControl, { vertical: true, gap: PHI_SPACE.lg, children: entries.map((entry, index) => (_jsxs(PhiFlexControl, { vertical: true, gap: PHI_SPACE.lg, children: [index > 0 ? _jsx(PhiDividerControl, { style: { margin: 0 } }) : null, _jsx(PhiEntryArticle, { entry: entry, labels: labels, parts: parts })] }, entry.id))) }));
|
|
129
130
|
return heading ? (_jsxs(PhiFlexControl, { vertical: true, gap: PHI_SPACE.base, children: [heading, body] })) : body;
|
|
130
131
|
}
|