@aglyn/plugins-mui 1.0.0-beta.143
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/LICENSE +201 -0
- package/README.md +22 -0
- package/package.json +47 -0
- package/src/index.d.ts +21 -0
- package/src/index.js +22 -0
- package/src/index.js.map +1 -0
- package/src/lib/components/accordion.d.ts +96 -0
- package/src/lib/components/accordion.js +392 -0
- package/src/lib/components/accordion.js.map +1 -0
- package/src/lib/components/app-bar.d.ts +32 -0
- package/src/lib/components/app-bar.js +86 -0
- package/src/lib/components/app-bar.js.map +1 -0
- package/src/lib/components/blocks.d.ts +46 -0
- package/src/lib/components/blocks.js +1007 -0
- package/src/lib/components/blocks.js.map +1 -0
- package/src/lib/components/box.d.ts +47 -0
- package/src/lib/components/box.js +125 -0
- package/src/lib/components/box.js.map +1 -0
- package/src/lib/components/breadcrumbs.d.ts +44 -0
- package/src/lib/components/breadcrumbs.js +172 -0
- package/src/lib/components/breadcrumbs.js.map +1 -0
- package/src/lib/components/button.d.ts +89 -0
- package/src/lib/components/button.js +272 -0
- package/src/lib/components/button.js.map +1 -0
- package/src/lib/components/card.d.ts +61 -0
- package/src/lib/components/card.js +336 -0
- package/src/lib/components/card.js.map +1 -0
- package/src/lib/components/collection.d.ts +514 -0
- package/src/lib/components/collection.js +2999 -0
- package/src/lib/components/collection.js.map +1 -0
- package/src/lib/components/container.d.ts +42 -0
- package/src/lib/components/container.js +169 -0
- package/src/lib/components/container.js.map +1 -0
- package/src/lib/components/custom-html.d.ts +78 -0
- package/src/lib/components/custom-html.js +219 -0
- package/src/lib/components/custom-html.js.map +1 -0
- package/src/lib/components/data-table.d.ts +57 -0
- package/src/lib/components/data-table.js +216 -0
- package/src/lib/components/data-table.js.map +1 -0
- package/src/lib/components/document-root.d.ts +77 -0
- package/src/lib/components/document-root.js +118 -0
- package/src/lib/components/document-root.js.map +1 -0
- package/src/lib/components/drawer.d.ts +93 -0
- package/src/lib/components/drawer.js +566 -0
- package/src/lib/components/drawer.js.map +1 -0
- package/src/lib/components/function-controls.d.ts +66 -0
- package/src/lib/components/function-controls.js +207 -0
- package/src/lib/components/function-controls.js.map +1 -0
- package/src/lib/components/function-scope.d.ts +110 -0
- package/src/lib/components/function-scope.js +478 -0
- package/src/lib/components/function-scope.js.map +1 -0
- package/src/lib/components/function-widget.d.ts +75 -0
- package/src/lib/components/function-widget.js +307 -0
- package/src/lib/components/function-widget.js.map +1 -0
- package/src/lib/components/grid.d.ts +91 -0
- package/src/lib/components/grid.js +322 -0
- package/src/lib/components/grid.js.map +1 -0
- package/src/lib/components/icon.d.ts +54 -0
- package/src/lib/components/icon.js +163 -0
- package/src/lib/components/icon.js.map +1 -0
- package/src/lib/components/image-list.d.ts +58 -0
- package/src/lib/components/image-list.js +336 -0
- package/src/lib/components/image-list.js.map +1 -0
- package/src/lib/components/image.d.ts +154 -0
- package/src/lib/components/image.js +451 -0
- package/src/lib/components/image.js.map +1 -0
- package/src/lib/components/inline-text.d.ts +74 -0
- package/src/lib/components/inline-text.js +407 -0
- package/src/lib/components/inline-text.js.map +1 -0
- package/src/lib/components/language-switcher.d.ts +35 -0
- package/src/lib/components/language-switcher.js +179 -0
- package/src/lib/components/language-switcher.js.map +1 -0
- package/src/lib/components/layout-slot.d.ts +68 -0
- package/src/lib/components/layout-slot.js +192 -0
- package/src/lib/components/layout-slot.js.map +1 -0
- package/src/lib/components/link-box-accessible-name.d.ts +79 -0
- package/src/lib/components/link-box-accessible-name.js +158 -0
- package/src/lib/components/link-box-accessible-name.js.map +1 -0
- package/src/lib/components/link-box.d.ts +66 -0
- package/src/lib/components/link-box.js +212 -0
- package/src/lib/components/link-box.js.map +1 -0
- package/src/lib/components/list-item-text.d.ts +22 -0
- package/src/lib/components/list-item-text.js +86 -0
- package/src/lib/components/list-item-text.js.map +1 -0
- package/src/lib/components/list-item.d.ts +32 -0
- package/src/lib/components/list-item.js +127 -0
- package/src/lib/components/list-item.js.map +1 -0
- package/src/lib/components/list.d.ts +34 -0
- package/src/lib/components/list.js +108 -0
- package/src/lib/components/list.js.map +1 -0
- package/src/lib/components/markdown.d.ts +129 -0
- package/src/lib/components/markdown.js +853 -0
- package/src/lib/components/markdown.js.map +1 -0
- package/src/lib/components/nav-menu.d.ts +68 -0
- package/src/lib/components/nav-menu.js +683 -0
- package/src/lib/components/nav-menu.js.map +1 -0
- package/src/lib/components/pagination.d.ts +59 -0
- package/src/lib/components/pagination.js +243 -0
- package/src/lib/components/pagination.js.map +1 -0
- package/src/lib/components/paper.d.ts +47 -0
- package/src/lib/components/paper.js +202 -0
- package/src/lib/components/paper.js.map +1 -0
- package/src/lib/components/plugin-frame.d.ts +64 -0
- package/src/lib/components/plugin-frame.js +335 -0
- package/src/lib/components/plugin-frame.js.map +1 -0
- package/src/lib/components/plugin.d.ts +95 -0
- package/src/lib/components/plugin.js +304 -0
- package/src/lib/components/plugin.js.map +1 -0
- package/src/lib/components/product.d.ts +40 -0
- package/src/lib/components/product.js +287 -0
- package/src/lib/components/product.js.map +1 -0
- package/src/lib/components/reusable-instance.d.ts +57 -0
- package/src/lib/components/reusable-instance.js +126 -0
- package/src/lib/components/reusable-instance.js.map +1 -0
- package/src/lib/components/screen-link.d.ts +85 -0
- package/src/lib/components/screen-link.js +324 -0
- package/src/lib/components/screen-link.js.map +1 -0
- package/src/lib/components/search-box.d.ts +41 -0
- package/src/lib/components/search-box.js +125 -0
- package/src/lib/components/search-box.js.map +1 -0
- package/src/lib/components/section.d.ts +56 -0
- package/src/lib/components/section.js +132 -0
- package/src/lib/components/section.js.map +1 -0
- package/src/lib/components/stack.d.ts +55 -0
- package/src/lib/components/stack.js +309 -0
- package/src/lib/components/stack.js.map +1 -0
- package/src/lib/components/tabs.d.ts +288 -0
- package/src/lib/components/tabs.js +788 -0
- package/src/lib/components/tabs.js.map +1 -0
- package/src/lib/components/theme-mode-switcher.d.ts +38 -0
- package/src/lib/components/theme-mode-switcher.js +168 -0
- package/src/lib/components/theme-mode-switcher.js.map +1 -0
- package/src/lib/components/toolbar.d.ts +37 -0
- package/src/lib/components/toolbar.js +117 -0
- package/src/lib/components/toolbar.js.map +1 -0
- package/src/lib/components/typography.d.ts +33 -0
- package/src/lib/components/typography.js +433 -0
- package/src/lib/components/typography.js.map +1 -0
- package/src/lib/components/video-lightbox-controls.d.ts +131 -0
- package/src/lib/components/video-lightbox-controls.js +536 -0
- package/src/lib/components/video-lightbox-controls.js.map +1 -0
- package/src/lib/components/video-lightbox.d.ts +60 -0
- package/src/lib/components/video-lightbox.js +247 -0
- package/src/lib/components/video-lightbox.js.map +1 -0
- package/src/lib/components/video-playback-beacon.d.ts +80 -0
- package/src/lib/components/video-playback-beacon.js +128 -0
- package/src/lib/components/video-playback-beacon.js.map +1 -0
- package/src/lib/components/video-player-frame.d.ts +58 -0
- package/src/lib/components/video-player-frame.js +51 -0
- package/src/lib/components/video-player-frame.js.map +1 -0
- package/src/lib/components/video.d.ts +220 -0
- package/src/lib/components/video.js +874 -0
- package/src/lib/components/video.js.map +1 -0
- package/src/lib/constants/bundle-common.d.ts +17 -0
- package/src/lib/constants/bundle-common.js +18 -0
- package/src/lib/constants/bundle-common.js.map +1 -0
- package/src/lib/constants/field-presets.d.ts +93 -0
- package/src/lib/constants/field-presets.js +248 -0
- package/src/lib/constants/field-presets.js.map +1 -0
- package/src/lib/plugin.d.ts +80 -0
- package/src/lib/plugin.js +599 -0
- package/src/lib/plugin.js.map +1 -0
- package/src/lib/utils/author-html-label.d.ts +73 -0
- package/src/lib/utils/author-html-label.js +89 -0
- package/src/lib/utils/author-html-label.js.map +1 -0
- package/src/lib/utils/drop-cleared-props.d.ts +18 -0
- package/src/lib/utils/drop-cleared-props.js +74 -0
- package/src/lib/utils/drop-cleared-props.js.map +1 -0
- package/src/lib/utils/element-picker.d.ts +99 -0
- package/src/lib/utils/element-picker.js +140 -0
- package/src/lib/utils/element-picker.js.map +1 -0
- package/src/lib/utils/generate-preset-id.d.ts +19 -0
- package/src/lib/utils/generate-preset-id.js +25 -0
- package/src/lib/utils/generate-preset-id.js.map +1 -0
- package/src/lib/utils/link-target-props.d.ts +53 -0
- package/src/lib/utils/link-target-props.js +53 -0
- package/src/lib/utils/link-target-props.js.map +1 -0
|
@@ -0,0 +1,1007 @@
|
|
|
1
|
+
import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
2
|
+
import { _ as _object_without_properties_loose } from "@swc/helpers/_/_object_without_properties_loose";
|
|
3
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
4
|
+
/**
|
|
5
|
+
* @license
|
|
6
|
+
* Copyright 2026 Aglyn LLC
|
|
7
|
+
*
|
|
8
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
9
|
+
* you may not use this file except in compliance with the License.
|
|
10
|
+
* You may obtain a copy of the License at
|
|
11
|
+
*
|
|
12
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
13
|
+
*
|
|
14
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
15
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
16
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
17
|
+
* See the License for the specific language governing permissions and
|
|
18
|
+
* limitations under the License.
|
|
19
|
+
*/ import * as Aglyn from "@aglyn/aglyn";
|
|
20
|
+
import { mdiBullhorn, mdiCurrencyUsd, mdiFacebook, mdiFormatQuoteClose, mdiGestureTapButton, mdiGithub, mdiHelpCircle, mdiImage as mdiImageIcon, mdiImageText, mdiInstagram, mdiLinkedin, mdiPageLayoutFooter, mdiPageLayoutHeader, mdiPlayCircle, mdiRocketLaunchOutline, mdiTwitter, mdiViewGridOutline, mdiYoutube } from "@aglyn/shared-data-mdi";
|
|
21
|
+
import { AppLink, MdiIcon } from "@aglyn/shared-ui-jsx";
|
|
22
|
+
import Box from "@mui/material/Box";
|
|
23
|
+
import Stack from "@mui/material/Stack";
|
|
24
|
+
import { forwardRef, useContext } from "react";
|
|
25
|
+
import { BUNDLE_ID } from "../constants/bundle-common.js";
|
|
26
|
+
import { generatePresetId } from "../utils/generate-preset-id.js";
|
|
27
|
+
// Component ids are persisted in screen documents; never rename.
|
|
28
|
+
export const VIDEO_EMBED_ID = 'videoEmbed';
|
|
29
|
+
export const SOCIAL_LINKS_ID = 'socialLinks';
|
|
30
|
+
/**
|
|
31
|
+
* Builds the embed src from a PARSED video id — the raw user URL is never
|
|
32
|
+
* placed in the iframe, so only youtube-nocookie/vimeo player origins can
|
|
33
|
+
* ever load (block-library security posture).
|
|
34
|
+
*/ export function parseVideoEmbedSrc(url) {
|
|
35
|
+
try {
|
|
36
|
+
const parsed = new URL(url.trim());
|
|
37
|
+
const host = parsed.hostname.replace(/^www\./, '');
|
|
38
|
+
if (host === 'youtu.be') {
|
|
39
|
+
const id = parsed.pathname.slice(1);
|
|
40
|
+
return /^[\w-]{6,20}$/.test(id) ? `https://www.youtube-nocookie.com/embed/${id}` : null;
|
|
41
|
+
}
|
|
42
|
+
if (host === 'youtube.com' || host === 'm.youtube.com') {
|
|
43
|
+
var _parsed_searchParams_get;
|
|
44
|
+
const id = (_parsed_searchParams_get = parsed.searchParams.get('v')) != null ? _parsed_searchParams_get : parsed.pathname.startsWith('/embed/') ? parsed.pathname.split('/')[2] : parsed.pathname.startsWith('/shorts/') ? parsed.pathname.split('/')[2] : '';
|
|
45
|
+
return id && /^[\w-]{6,20}$/.test(id) ? `https://www.youtube-nocookie.com/embed/${id}` : null;
|
|
46
|
+
}
|
|
47
|
+
if (host === 'vimeo.com' || host === 'player.vimeo.com') {
|
|
48
|
+
const id = parsed.pathname.split('/').find((part)=>/^\d{6,}$/.test(part));
|
|
49
|
+
return id ? `https://player.vimeo.com/video/${id}` : null;
|
|
50
|
+
}
|
|
51
|
+
} catch (unused) {
|
|
52
|
+
/* invalid URL */ }
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
const VideoEmbed = /*#__PURE__*/ forwardRef((props, ref)=>{
|
|
56
|
+
const { url, height } = props, rest = _object_without_properties_loose(props, [
|
|
57
|
+
"url",
|
|
58
|
+
"height"
|
|
59
|
+
]);
|
|
60
|
+
// Node styles ride the renderer-merged sx; recompose (stack.ts pattern).
|
|
61
|
+
const nodeSx = Array.isArray(props['sx']) ? props['sx'] : [
|
|
62
|
+
props['sx']
|
|
63
|
+
];
|
|
64
|
+
const { suppressNavigation } = useContext(Aglyn.ScreenLinkContext);
|
|
65
|
+
const src = url ? parseVideoEmbedSrc(url) : null;
|
|
66
|
+
if (!src) {
|
|
67
|
+
// The hint is for the author, so only editing surfaces draw it; a
|
|
68
|
+
// published page renders the bare element.
|
|
69
|
+
if (!suppressNavigation) return /*#__PURE__*/ _jsx(Box, _extends({
|
|
70
|
+
ref: ref
|
|
71
|
+
}, rest));
|
|
72
|
+
return /*#__PURE__*/ _jsx(Box, _extends({
|
|
73
|
+
ref: ref
|
|
74
|
+
}, rest, {
|
|
75
|
+
sx: [
|
|
76
|
+
{
|
|
77
|
+
width: '100%',
|
|
78
|
+
height: height || 315,
|
|
79
|
+
display: 'flex',
|
|
80
|
+
alignItems: 'center',
|
|
81
|
+
justifyContent: 'center',
|
|
82
|
+
border: '1px dashed',
|
|
83
|
+
borderColor: 'divider',
|
|
84
|
+
color: 'text.secondary',
|
|
85
|
+
fontSize: 12,
|
|
86
|
+
fontFamily: 'system-ui, sans-serif'
|
|
87
|
+
},
|
|
88
|
+
...nodeSx
|
|
89
|
+
],
|
|
90
|
+
children: 'Video — paste a YouTube or Vimeo URL'
|
|
91
|
+
}));
|
|
92
|
+
}
|
|
93
|
+
return /*#__PURE__*/ _jsx(Box, _extends({
|
|
94
|
+
ref: ref,
|
|
95
|
+
component: "iframe",
|
|
96
|
+
src: src,
|
|
97
|
+
title: "Embedded video",
|
|
98
|
+
loading: "lazy",
|
|
99
|
+
allow: "accelerometer; encrypted-media; picture-in-picture",
|
|
100
|
+
allowFullScreen: true,
|
|
101
|
+
sandbox: "allow-scripts allow-same-origin allow-presentation allow-popups"
|
|
102
|
+
}, rest, {
|
|
103
|
+
sx: [
|
|
104
|
+
{
|
|
105
|
+
display: 'block',
|
|
106
|
+
width: '100%',
|
|
107
|
+
height: height || 315,
|
|
108
|
+
border: 0
|
|
109
|
+
},
|
|
110
|
+
...nodeSx
|
|
111
|
+
]
|
|
112
|
+
}));
|
|
113
|
+
});
|
|
114
|
+
VideoEmbed.displayName = 'AglynVideoEmbed';
|
|
115
|
+
export const videoEmbedSchema = {
|
|
116
|
+
$id: VIDEO_EMBED_ID,
|
|
117
|
+
pluginId: BUNDLE_ID,
|
|
118
|
+
displayName: 'Video',
|
|
119
|
+
description: "Embeds a YouTube or Vimeo player from the video's URL.",
|
|
120
|
+
category: Aglyn.ComponentCategory.MEDIA,
|
|
121
|
+
icon: {
|
|
122
|
+
path: mdiPlayCircle.path,
|
|
123
|
+
sx: {
|
|
124
|
+
color: '#d32f2f'
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
flags: {
|
|
128
|
+
selfClosing: Aglyn.FEATURE_FLAG.ENABLED
|
|
129
|
+
},
|
|
130
|
+
attributes: [
|
|
131
|
+
{
|
|
132
|
+
name: 'url',
|
|
133
|
+
description: 'YouTube or Vimeo video URL.',
|
|
134
|
+
component: Aglyn.FieldComponentType.TEXT_FIELD,
|
|
135
|
+
label: 'Video URL'
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
name: 'height',
|
|
139
|
+
description: 'Height of the embed — a number plus a unit, e.g. 315px or 50vh.',
|
|
140
|
+
component: Aglyn.FieldComponentType.CSS_DIMENSION,
|
|
141
|
+
label: 'Height'
|
|
142
|
+
}
|
|
143
|
+
]
|
|
144
|
+
};
|
|
145
|
+
const SOCIAL_NETWORKS = [
|
|
146
|
+
{
|
|
147
|
+
key: 'twitter',
|
|
148
|
+
label: 'Twitter / X',
|
|
149
|
+
path: mdiTwitter.path
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
key: 'instagram',
|
|
153
|
+
label: 'Instagram',
|
|
154
|
+
path: mdiInstagram.path
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
key: 'facebook',
|
|
158
|
+
label: 'Facebook',
|
|
159
|
+
path: mdiFacebook.path
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
key: 'linkedin',
|
|
163
|
+
label: 'LinkedIn',
|
|
164
|
+
path: mdiLinkedin.path
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
key: 'youtube',
|
|
168
|
+
label: 'YouTube',
|
|
169
|
+
path: mdiYoutube.path
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
key: 'github',
|
|
173
|
+
label: 'GitHub',
|
|
174
|
+
path: mdiGithub.path
|
|
175
|
+
}
|
|
176
|
+
];
|
|
177
|
+
const SAFE_SOCIAL_HREF = /^https:\/\//i;
|
|
178
|
+
const SocialLinks = /*#__PURE__*/ forwardRef((props, ref)=>{
|
|
179
|
+
const { suppressNavigation } = useContext(Aglyn.ScreenLinkContext);
|
|
180
|
+
// The profile fields are this element's data, not attributes of its row.
|
|
181
|
+
// Spread onto the Stack, each would be written into the page's HTML as a
|
|
182
|
+
// second copy of the URL, including a URL the filter below refuses.
|
|
183
|
+
const rowProps = _extends({}, props);
|
|
184
|
+
for (const { key } of SOCIAL_NETWORKS)delete rowProps[key];
|
|
185
|
+
const entries = SOCIAL_NETWORKS.map(({ key, label, path })=>{
|
|
186
|
+
var _props_key;
|
|
187
|
+
return {
|
|
188
|
+
key,
|
|
189
|
+
label,
|
|
190
|
+
path,
|
|
191
|
+
href: (_props_key = props[key]) == null ? void 0 : _props_key.trim()
|
|
192
|
+
};
|
|
193
|
+
}).filter((entry)=>entry.href && SAFE_SOCIAL_HREF.test(entry.href));
|
|
194
|
+
return /*#__PURE__*/ _jsx(Stack, _extends({
|
|
195
|
+
ref: ref,
|
|
196
|
+
direction: "row",
|
|
197
|
+
spacing: 0.5
|
|
198
|
+
}, rowProps, {
|
|
199
|
+
children: entries.length ? entries.map((entry)=>/*#__PURE__*/ _jsx(AppLink, {
|
|
200
|
+
componentVariant: "icon-button",
|
|
201
|
+
href: entry.href,
|
|
202
|
+
target: "_blank",
|
|
203
|
+
rel: "noopener noreferrer",
|
|
204
|
+
"aria-label": entry.label,
|
|
205
|
+
size: "small",
|
|
206
|
+
children: /*#__PURE__*/ _jsx(MdiIcon, {
|
|
207
|
+
path: entry.path
|
|
208
|
+
})
|
|
209
|
+
}, entry.key)) : suppressNavigation ? // Editing surfaces only: a visitor has no Attributes panel.
|
|
210
|
+
/*#__PURE__*/ _jsx(Box, {
|
|
211
|
+
sx: {
|
|
212
|
+
color: 'text.secondary',
|
|
213
|
+
fontSize: 12,
|
|
214
|
+
fontFamily: 'system-ui, sans-serif',
|
|
215
|
+
p: 1
|
|
216
|
+
},
|
|
217
|
+
children: 'Social links — add profile URLs in Attributes'
|
|
218
|
+
}) : null
|
|
219
|
+
}));
|
|
220
|
+
});
|
|
221
|
+
SocialLinks.displayName = 'AglynSocialLinks';
|
|
222
|
+
export const socialLinksSchema = {
|
|
223
|
+
$id: SOCIAL_LINKS_ID,
|
|
224
|
+
pluginId: BUNDLE_ID,
|
|
225
|
+
displayName: 'Social Links',
|
|
226
|
+
description: 'A row of icon links to whichever social profiles you fill in.',
|
|
227
|
+
category: Aglyn.ComponentCategory.NAVIGATION,
|
|
228
|
+
icon: {
|
|
229
|
+
path: mdiTwitter.path,
|
|
230
|
+
sx: {
|
|
231
|
+
color: '#1976d2'
|
|
232
|
+
}
|
|
233
|
+
},
|
|
234
|
+
flags: {
|
|
235
|
+
selfClosing: Aglyn.FEATURE_FLAG.ENABLED
|
|
236
|
+
},
|
|
237
|
+
attributes: SOCIAL_NETWORKS.map(({ key, label })=>({
|
|
238
|
+
name: key,
|
|
239
|
+
description: `${label} profile URL (https).`,
|
|
240
|
+
component: Aglyn.FieldComponentType.TEXT_FIELD,
|
|
241
|
+
label
|
|
242
|
+
}))
|
|
243
|
+
};
|
|
244
|
+
/* ── Section presets (composed from existing components) ────────────────── */ /**
|
|
245
|
+
* Preset styling is authored on the node's OWN `sx`, never inside `props`
|
|
246
|
+
* (AGL-1346).
|
|
247
|
+
*
|
|
248
|
+
* Both records render — `Leaf` composes `(sx, props.sx, node.sx)` — but
|
|
249
|
+
* only `node.sx` is the one the Styles panel writes, so a preset that put
|
|
250
|
+
* its styling in `props.sx` authored values the panel could display but no
|
|
251
|
+
* click could ever change or clear. The renderer composes `node.sx` LAST,
|
|
252
|
+
* so moving a preset's styles here changes nothing about how a fresh
|
|
253
|
+
* insert looks; it only makes them editable. Existing documents keep their
|
|
254
|
+
* `props.sx` and still render from it.
|
|
255
|
+
*
|
|
256
|
+
* `plugin.spec.ts` holds every preset in this bundle to that rule.
|
|
257
|
+
*/ const text = (variant, children, extra)=>{
|
|
258
|
+
const _ref = extra != null ? extra : {}, { sx } = _ref, props = _object_without_properties_loose(_ref, [
|
|
259
|
+
"sx"
|
|
260
|
+
]);
|
|
261
|
+
return _extends({
|
|
262
|
+
$id: null,
|
|
263
|
+
componentId: 'muiTypography',
|
|
264
|
+
pluginId: BUNDLE_ID,
|
|
265
|
+
props: _extends({
|
|
266
|
+
variant,
|
|
267
|
+
children
|
|
268
|
+
}, props)
|
|
269
|
+
}, sx ? {
|
|
270
|
+
sx
|
|
271
|
+
} : {});
|
|
272
|
+
};
|
|
273
|
+
const testimonialCard = (quote, name)=>({
|
|
274
|
+
$id: null,
|
|
275
|
+
componentId: 'muiStack',
|
|
276
|
+
pluginId: BUNDLE_ID,
|
|
277
|
+
props: {
|
|
278
|
+
spacing: 1
|
|
279
|
+
},
|
|
280
|
+
sx: {
|
|
281
|
+
flex: 1,
|
|
282
|
+
paddingTop: 3,
|
|
283
|
+
paddingRight: 3,
|
|
284
|
+
paddingBottom: 3,
|
|
285
|
+
paddingLeft: 3
|
|
286
|
+
},
|
|
287
|
+
nodes: [
|
|
288
|
+
text('body1', `“${quote}”`),
|
|
289
|
+
text('subtitle2', `— ${name}`)
|
|
290
|
+
]
|
|
291
|
+
});
|
|
292
|
+
const pricingColumn = (tier, price, features, highlighted)=>({
|
|
293
|
+
$id: null,
|
|
294
|
+
componentId: 'muiStack',
|
|
295
|
+
pluginId: BUNDLE_ID,
|
|
296
|
+
props: {
|
|
297
|
+
spacing: 1
|
|
298
|
+
},
|
|
299
|
+
sx: _extends({
|
|
300
|
+
flex: 1,
|
|
301
|
+
paddingTop: 3,
|
|
302
|
+
paddingRight: 3,
|
|
303
|
+
paddingBottom: 3,
|
|
304
|
+
paddingLeft: 3,
|
|
305
|
+
alignItems: 'center'
|
|
306
|
+
}, highlighted && {
|
|
307
|
+
border: '2px solid',
|
|
308
|
+
borderColor: 'primary.main',
|
|
309
|
+
borderRadius: 2
|
|
310
|
+
}),
|
|
311
|
+
nodes: [
|
|
312
|
+
text('h5', tier),
|
|
313
|
+
text('h3', price),
|
|
314
|
+
...features.map((feature)=>text('body2', feature)),
|
|
315
|
+
{
|
|
316
|
+
$id: null,
|
|
317
|
+
componentId: 'muiButton',
|
|
318
|
+
pluginId: BUNDLE_ID,
|
|
319
|
+
props: {
|
|
320
|
+
variant: highlighted ? 'contained' : 'outlined',
|
|
321
|
+
children: 'Choose plan'
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
]
|
|
325
|
+
});
|
|
326
|
+
const faqItem = (question, answer)=>[
|
|
327
|
+
text('subtitle1', question),
|
|
328
|
+
text('body2', answer, {
|
|
329
|
+
gutterBottom: true
|
|
330
|
+
})
|
|
331
|
+
];
|
|
332
|
+
/** Screen link with the visible-on-any-surface nav defaults (AGL-539). */ const navLink = (label)=>({
|
|
333
|
+
$id: null,
|
|
334
|
+
componentId: 'muiScreenLink',
|
|
335
|
+
pluginId: BUNDLE_ID,
|
|
336
|
+
props: {
|
|
337
|
+
children: label,
|
|
338
|
+
color: 'inherit'
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
const featureColumn = (title, body)=>({
|
|
342
|
+
$id: null,
|
|
343
|
+
componentId: 'muiStack',
|
|
344
|
+
pluginId: BUNDLE_ID,
|
|
345
|
+
props: {
|
|
346
|
+
spacing: 1
|
|
347
|
+
},
|
|
348
|
+
sx: {
|
|
349
|
+
flex: 1,
|
|
350
|
+
minWidth: 220,
|
|
351
|
+
paddingTop: 2,
|
|
352
|
+
paddingRight: 2,
|
|
353
|
+
paddingBottom: 2,
|
|
354
|
+
paddingLeft: 2
|
|
355
|
+
},
|
|
356
|
+
nodes: [
|
|
357
|
+
text('h5', title),
|
|
358
|
+
text('body1', body)
|
|
359
|
+
]
|
|
360
|
+
});
|
|
361
|
+
/**
|
|
362
|
+
* A section block's outer band, with its content held to a readable width
|
|
363
|
+
* (AGL-2544).
|
|
364
|
+
*
|
|
365
|
+
* These presets used to be a bare `muiStack` dropped straight into
|
|
366
|
+
* `Document`, so every one of them rendered edge to edge: a Feature Grid ran
|
|
367
|
+
* the full viewport while the page's prose sat at 900px, and the FAQ — which
|
|
368
|
+
* had `maxWidth` but no auto margins — hugged the left edge. That is the
|
|
369
|
+
* result of the documented happy path on a fresh screen, with no misuse, and
|
|
370
|
+
* a subscriber has no reason to suspect the block needs wrapping.
|
|
371
|
+
*
|
|
372
|
+
* The band and the content are separated rather than the whole thing being
|
|
373
|
+
* wrapped, because a CTA or hero genuinely wants a full-bleed background with
|
|
374
|
+
* contained content — wrapping the outer node would take that away to fix the
|
|
375
|
+
* width. So `bandSx` (padding, background) stays outside and the Container
|
|
376
|
+
* goes within it.
|
|
377
|
+
*
|
|
378
|
+
* `layout` moves a row block's own direction onto an inner Stack: dropping a
|
|
379
|
+
* Container between a `direction: 'row'` Stack and its columns would leave
|
|
380
|
+
* the Container as the single flex child and collapse the row.
|
|
381
|
+
*/ const section = ({ bandSx, layout, layoutSx, maxWidth = 'lg', nodes })=>_extends({
|
|
382
|
+
$id: null,
|
|
383
|
+
componentId: 'muiStack',
|
|
384
|
+
pluginId: BUNDLE_ID,
|
|
385
|
+
props: {}
|
|
386
|
+
}, bandSx ? {
|
|
387
|
+
sx: bandSx
|
|
388
|
+
} : {}, {
|
|
389
|
+
nodes: [
|
|
390
|
+
{
|
|
391
|
+
$id: null,
|
|
392
|
+
componentId: 'muiContainer',
|
|
393
|
+
pluginId: BUNDLE_ID,
|
|
394
|
+
props: {
|
|
395
|
+
maxWidth
|
|
396
|
+
},
|
|
397
|
+
nodes: layout || layoutSx ? [
|
|
398
|
+
_extends({
|
|
399
|
+
$id: null,
|
|
400
|
+
componentId: 'muiStack',
|
|
401
|
+
pluginId: BUNDLE_ID,
|
|
402
|
+
props: layout != null ? layout : {}
|
|
403
|
+
}, layoutSx ? {
|
|
404
|
+
sx: layoutSx
|
|
405
|
+
} : {}, {
|
|
406
|
+
nodes
|
|
407
|
+
})
|
|
408
|
+
] : nodes
|
|
409
|
+
}
|
|
410
|
+
]
|
|
411
|
+
});
|
|
412
|
+
export const blockPresets = [
|
|
413
|
+
{
|
|
414
|
+
$id: generatePresetId(VIDEO_EMBED_ID),
|
|
415
|
+
type: Aglyn.NodeType.PRESET,
|
|
416
|
+
displayName: 'Video',
|
|
417
|
+
pluginId: BUNDLE_ID,
|
|
418
|
+
description: 'Embedded YouTube or Vimeo video',
|
|
419
|
+
category: Aglyn.ComponentCategory.MEDIA,
|
|
420
|
+
icon: {
|
|
421
|
+
path: mdiPlayCircle.path,
|
|
422
|
+
sx: {
|
|
423
|
+
color: '#d32f2f'
|
|
424
|
+
}
|
|
425
|
+
},
|
|
426
|
+
data: {
|
|
427
|
+
$id: null,
|
|
428
|
+
componentId: VIDEO_EMBED_ID,
|
|
429
|
+
pluginId: BUNDLE_ID,
|
|
430
|
+
props: {}
|
|
431
|
+
}
|
|
432
|
+
},
|
|
433
|
+
{
|
|
434
|
+
$id: generatePresetId(SOCIAL_LINKS_ID),
|
|
435
|
+
type: Aglyn.NodeType.PRESET,
|
|
436
|
+
displayName: 'Social Links',
|
|
437
|
+
pluginId: BUNDLE_ID,
|
|
438
|
+
description: 'Icon links to social profiles',
|
|
439
|
+
category: Aglyn.ComponentCategory.NAVIGATION,
|
|
440
|
+
icon: {
|
|
441
|
+
path: mdiTwitter.path,
|
|
442
|
+
sx: {
|
|
443
|
+
color: '#1976d2'
|
|
444
|
+
}
|
|
445
|
+
},
|
|
446
|
+
data: {
|
|
447
|
+
$id: null,
|
|
448
|
+
componentId: SOCIAL_LINKS_ID,
|
|
449
|
+
pluginId: BUNDLE_ID,
|
|
450
|
+
props: {}
|
|
451
|
+
}
|
|
452
|
+
},
|
|
453
|
+
{
|
|
454
|
+
$id: generatePresetId('muiStack', 'gallery'),
|
|
455
|
+
type: Aglyn.NodeType.PRESET,
|
|
456
|
+
displayName: 'Image Gallery',
|
|
457
|
+
pluginId: BUNDLE_ID,
|
|
458
|
+
description: 'Three-across image row',
|
|
459
|
+
category: Aglyn.ComponentCategory.BLOCKS,
|
|
460
|
+
icon: {
|
|
461
|
+
path: mdiImageIcon.path,
|
|
462
|
+
sx: {
|
|
463
|
+
color: '#7b1fa2'
|
|
464
|
+
}
|
|
465
|
+
},
|
|
466
|
+
data: {
|
|
467
|
+
$id: null,
|
|
468
|
+
componentId: 'muiStack',
|
|
469
|
+
pluginId: BUNDLE_ID,
|
|
470
|
+
props: {
|
|
471
|
+
direction: 'row',
|
|
472
|
+
spacing: 2
|
|
473
|
+
},
|
|
474
|
+
sx: {
|
|
475
|
+
paddingTop: 4,
|
|
476
|
+
paddingBottom: 4
|
|
477
|
+
},
|
|
478
|
+
nodes: [
|
|
479
|
+
1,
|
|
480
|
+
2,
|
|
481
|
+
3
|
|
482
|
+
].map((index)=>({
|
|
483
|
+
$id: null,
|
|
484
|
+
componentId: 'image',
|
|
485
|
+
pluginId: BUNDLE_ID,
|
|
486
|
+
props: {
|
|
487
|
+
alt: `Gallery image ${index}`,
|
|
488
|
+
height: '240px'
|
|
489
|
+
}
|
|
490
|
+
}))
|
|
491
|
+
}
|
|
492
|
+
},
|
|
493
|
+
{
|
|
494
|
+
$id: generatePresetId('muiStack', 'testimonials'),
|
|
495
|
+
type: Aglyn.NodeType.PRESET,
|
|
496
|
+
displayName: 'Testimonials',
|
|
497
|
+
pluginId: BUNDLE_ID,
|
|
498
|
+
description: 'Three customer quotes',
|
|
499
|
+
category: Aglyn.ComponentCategory.BLOCKS,
|
|
500
|
+
icon: {
|
|
501
|
+
path: mdiFormatQuoteClose.path,
|
|
502
|
+
sx: {
|
|
503
|
+
color: '#0288d1'
|
|
504
|
+
}
|
|
505
|
+
},
|
|
506
|
+
data: {
|
|
507
|
+
$id: null,
|
|
508
|
+
componentId: 'muiStack',
|
|
509
|
+
pluginId: BUNDLE_ID,
|
|
510
|
+
props: {
|
|
511
|
+
direction: 'row',
|
|
512
|
+
spacing: 2
|
|
513
|
+
},
|
|
514
|
+
sx: {
|
|
515
|
+
paddingTop: 4,
|
|
516
|
+
paddingBottom: 4
|
|
517
|
+
},
|
|
518
|
+
nodes: [
|
|
519
|
+
testimonialCard('Exactly what our team needed to ship the site fast.', 'Customer One'),
|
|
520
|
+
testimonialCard('The editor is a joy — we update pages in minutes.', 'Customer Two'),
|
|
521
|
+
testimonialCard('Best decision we made for our online presence.', 'Customer Three')
|
|
522
|
+
]
|
|
523
|
+
}
|
|
524
|
+
},
|
|
525
|
+
{
|
|
526
|
+
$id: generatePresetId('muiStack', 'pricing'),
|
|
527
|
+
type: Aglyn.NodeType.PRESET,
|
|
528
|
+
displayName: 'Pricing Table',
|
|
529
|
+
pluginId: BUNDLE_ID,
|
|
530
|
+
description: 'Three plan columns with features and CTAs',
|
|
531
|
+
category: Aglyn.ComponentCategory.BLOCKS,
|
|
532
|
+
icon: {
|
|
533
|
+
path: mdiCurrencyUsd.path,
|
|
534
|
+
sx: {
|
|
535
|
+
color: '#2e7d32'
|
|
536
|
+
}
|
|
537
|
+
},
|
|
538
|
+
data: {
|
|
539
|
+
$id: null,
|
|
540
|
+
componentId: 'muiStack',
|
|
541
|
+
pluginId: BUNDLE_ID,
|
|
542
|
+
props: {
|
|
543
|
+
direction: 'row',
|
|
544
|
+
spacing: 2
|
|
545
|
+
},
|
|
546
|
+
sx: {
|
|
547
|
+
paddingTop: 4,
|
|
548
|
+
paddingBottom: 4
|
|
549
|
+
},
|
|
550
|
+
nodes: [
|
|
551
|
+
pricingColumn('Basic', '$9', [
|
|
552
|
+
'One project',
|
|
553
|
+
'Email support'
|
|
554
|
+
]),
|
|
555
|
+
pricingColumn('Pro', '$29', [
|
|
556
|
+
'Five projects',
|
|
557
|
+
'Priority support',
|
|
558
|
+
'Analytics'
|
|
559
|
+
], true),
|
|
560
|
+
pricingColumn('Team', '$79', [
|
|
561
|
+
'Unlimited projects',
|
|
562
|
+
'Dedicated support',
|
|
563
|
+
'SSO'
|
|
564
|
+
])
|
|
565
|
+
]
|
|
566
|
+
}
|
|
567
|
+
},
|
|
568
|
+
{
|
|
569
|
+
$id: generatePresetId('muiStack', 'faq'),
|
|
570
|
+
type: Aglyn.NodeType.PRESET,
|
|
571
|
+
displayName: 'FAQ',
|
|
572
|
+
pluginId: BUNDLE_ID,
|
|
573
|
+
description: 'Question and answer list',
|
|
574
|
+
category: Aglyn.ComponentCategory.BLOCKS,
|
|
575
|
+
icon: {
|
|
576
|
+
path: mdiHelpCircle.path,
|
|
577
|
+
sx: {
|
|
578
|
+
color: '#f57c00'
|
|
579
|
+
}
|
|
580
|
+
},
|
|
581
|
+
data: section({
|
|
582
|
+
bandSx: {
|
|
583
|
+
paddingTop: 4,
|
|
584
|
+
paddingBottom: 4
|
|
585
|
+
},
|
|
586
|
+
// `md`, not the old bare `maxWidth: 720`. The width was never the
|
|
587
|
+
// defect — the missing auto margins were, which is why this block
|
|
588
|
+
// rendered hard against the left viewport edge.
|
|
589
|
+
maxWidth: 'md',
|
|
590
|
+
layout: {
|
|
591
|
+
spacing: 1
|
|
592
|
+
},
|
|
593
|
+
nodes: [
|
|
594
|
+
text('h4', 'Frequently asked questions', {
|
|
595
|
+
gutterBottom: true
|
|
596
|
+
}),
|
|
597
|
+
...faqItem('How do I get started?', 'Answer the question in a sentence or two so visitors keep reading.'),
|
|
598
|
+
...faqItem('Can I change plans later?', 'Yes — describe how flexible your offering is.'),
|
|
599
|
+
...faqItem('Do you offer support?', 'Tell visitors how and when they can reach you.')
|
|
600
|
+
]
|
|
601
|
+
})
|
|
602
|
+
},
|
|
603
|
+
{
|
|
604
|
+
$id: generatePresetId('muiStack', 'announcement'),
|
|
605
|
+
type: Aglyn.NodeType.PRESET,
|
|
606
|
+
displayName: 'Announcement Bar',
|
|
607
|
+
pluginId: BUNDLE_ID,
|
|
608
|
+
description: 'Accent strip with a message and link',
|
|
609
|
+
category: Aglyn.ComponentCategory.BLOCKS,
|
|
610
|
+
icon: {
|
|
611
|
+
path: mdiBullhorn.path,
|
|
612
|
+
sx: {
|
|
613
|
+
color: '#c2185b'
|
|
614
|
+
}
|
|
615
|
+
},
|
|
616
|
+
data: {
|
|
617
|
+
$id: null,
|
|
618
|
+
componentId: 'muiStack',
|
|
619
|
+
pluginId: BUNDLE_ID,
|
|
620
|
+
props: {
|
|
621
|
+
direction: 'row',
|
|
622
|
+
spacing: 2
|
|
623
|
+
},
|
|
624
|
+
sx: {
|
|
625
|
+
paddingTop: 1,
|
|
626
|
+
paddingBottom: 1,
|
|
627
|
+
paddingLeft: 2,
|
|
628
|
+
paddingRight: 2,
|
|
629
|
+
alignItems: 'center',
|
|
630
|
+
justifyContent: 'center',
|
|
631
|
+
backgroundColor: 'primary.main',
|
|
632
|
+
color: 'primary.contrastText'
|
|
633
|
+
},
|
|
634
|
+
nodes: [
|
|
635
|
+
text('body2', 'Big news — announce a launch, sale, or update here.'),
|
|
636
|
+
{
|
|
637
|
+
$id: null,
|
|
638
|
+
componentId: 'muiScreenLink',
|
|
639
|
+
pluginId: BUNDLE_ID,
|
|
640
|
+
props: {
|
|
641
|
+
children: 'Learn more',
|
|
642
|
+
size: 'small',
|
|
643
|
+
color: 'inherit'
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
]
|
|
647
|
+
}
|
|
648
|
+
},
|
|
649
|
+
// ── Composed page sections (AGL-539) ──────────────────────────────────
|
|
650
|
+
// The pieces every real site needs, insertable without raw-JSON
|
|
651
|
+
// authoring. Node shapes mirror apps/console starter templates; only
|
|
652
|
+
// persisted component ids are referenced.
|
|
653
|
+
{
|
|
654
|
+
$id: generatePresetId('muiAppBar', 'navbar'),
|
|
655
|
+
type: Aglyn.NodeType.PRESET,
|
|
656
|
+
displayName: 'Nav Bar',
|
|
657
|
+
pluginId: BUNDLE_ID,
|
|
658
|
+
description: 'Header bar with brand text and screen links',
|
|
659
|
+
category: Aglyn.ComponentCategory.BLOCKS,
|
|
660
|
+
icon: {
|
|
661
|
+
path: mdiPageLayoutHeader.path,
|
|
662
|
+
sx: {
|
|
663
|
+
color: '#1976d2'
|
|
664
|
+
}
|
|
665
|
+
},
|
|
666
|
+
data: {
|
|
667
|
+
$id: null,
|
|
668
|
+
componentId: 'muiAppBar',
|
|
669
|
+
pluginId: BUNDLE_ID,
|
|
670
|
+
// Static so the bar sits in the page flow; switch the Position
|
|
671
|
+
// attribute to Sticky/Fixed for a pinned header.
|
|
672
|
+
props: {
|
|
673
|
+
position: 'static'
|
|
674
|
+
},
|
|
675
|
+
nodes: [
|
|
676
|
+
{
|
|
677
|
+
$id: null,
|
|
678
|
+
componentId: 'muiToolbar',
|
|
679
|
+
pluginId: BUNDLE_ID,
|
|
680
|
+
props: {},
|
|
681
|
+
nodes: [
|
|
682
|
+
text('h6', 'Your Brand', {
|
|
683
|
+
sx: {
|
|
684
|
+
flexGrow: 1
|
|
685
|
+
}
|
|
686
|
+
}),
|
|
687
|
+
{
|
|
688
|
+
$id: null,
|
|
689
|
+
componentId: 'muiStack',
|
|
690
|
+
pluginId: BUNDLE_ID,
|
|
691
|
+
props: {
|
|
692
|
+
direction: 'row',
|
|
693
|
+
spacing: 1
|
|
694
|
+
},
|
|
695
|
+
nodes: [
|
|
696
|
+
navLink('Home'),
|
|
697
|
+
navLink('About'),
|
|
698
|
+
navLink('Contact')
|
|
699
|
+
]
|
|
700
|
+
}
|
|
701
|
+
]
|
|
702
|
+
}
|
|
703
|
+
]
|
|
704
|
+
}
|
|
705
|
+
},
|
|
706
|
+
{
|
|
707
|
+
$id: generatePresetId('muiStack', 'hero'),
|
|
708
|
+
type: Aglyn.NodeType.PRESET,
|
|
709
|
+
displayName: 'Hero',
|
|
710
|
+
pluginId: BUNDLE_ID,
|
|
711
|
+
description: 'Centered headline, tagline, and call-to-action button',
|
|
712
|
+
category: Aglyn.ComponentCategory.BLOCKS,
|
|
713
|
+
icon: {
|
|
714
|
+
path: mdiRocketLaunchOutline.path,
|
|
715
|
+
sx: {
|
|
716
|
+
color: '#f57c00'
|
|
717
|
+
}
|
|
718
|
+
},
|
|
719
|
+
data: section({
|
|
720
|
+
bandSx: {
|
|
721
|
+
paddingTop: 10,
|
|
722
|
+
paddingBottom: 10,
|
|
723
|
+
paddingLeft: 4,
|
|
724
|
+
paddingRight: 4
|
|
725
|
+
},
|
|
726
|
+
layout: {
|
|
727
|
+
spacing: 2
|
|
728
|
+
},
|
|
729
|
+
layoutSx: {
|
|
730
|
+
alignItems: 'center'
|
|
731
|
+
},
|
|
732
|
+
nodes: [
|
|
733
|
+
text('h2', 'A headline that sells your idea', {
|
|
734
|
+
align: 'center'
|
|
735
|
+
}),
|
|
736
|
+
text('h6', 'One clear sentence about the value you deliver.', {
|
|
737
|
+
align: 'center'
|
|
738
|
+
}),
|
|
739
|
+
{
|
|
740
|
+
$id: null,
|
|
741
|
+
componentId: 'muiButton',
|
|
742
|
+
pluginId: BUNDLE_ID,
|
|
743
|
+
props: {
|
|
744
|
+
variant: 'contained',
|
|
745
|
+
size: 'large',
|
|
746
|
+
children: 'Get started'
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
]
|
|
750
|
+
})
|
|
751
|
+
},
|
|
752
|
+
{
|
|
753
|
+
$id: generatePresetId('muiStack', 'features'),
|
|
754
|
+
type: Aglyn.NodeType.PRESET,
|
|
755
|
+
displayName: 'Feature Grid',
|
|
756
|
+
pluginId: BUNDLE_ID,
|
|
757
|
+
description: 'Three selling points in a wrapping row',
|
|
758
|
+
category: Aglyn.ComponentCategory.BLOCKS,
|
|
759
|
+
icon: {
|
|
760
|
+
path: mdiViewGridOutline.path,
|
|
761
|
+
sx: {
|
|
762
|
+
color: '#2e7d32'
|
|
763
|
+
}
|
|
764
|
+
},
|
|
765
|
+
data: section({
|
|
766
|
+
bandSx: {
|
|
767
|
+
paddingLeft: 4,
|
|
768
|
+
paddingRight: 4,
|
|
769
|
+
paddingTop: 6,
|
|
770
|
+
paddingBottom: 6
|
|
771
|
+
},
|
|
772
|
+
layout: {
|
|
773
|
+
direction: 'row',
|
|
774
|
+
spacing: 2
|
|
775
|
+
},
|
|
776
|
+
layoutSx: {
|
|
777
|
+
flexWrap: 'wrap'
|
|
778
|
+
},
|
|
779
|
+
nodes: [
|
|
780
|
+
featureColumn('Fast', 'Explain the first reason customers pick you.'),
|
|
781
|
+
featureColumn('Simple', 'Explain the second reason customers pick you.'),
|
|
782
|
+
featureColumn('Reliable', 'Explain the third reason customers pick you.')
|
|
783
|
+
]
|
|
784
|
+
})
|
|
785
|
+
},
|
|
786
|
+
{
|
|
787
|
+
$id: generatePresetId('muiStack', 'imagetext'),
|
|
788
|
+
type: Aglyn.NodeType.PRESET,
|
|
789
|
+
displayName: 'Image + Text',
|
|
790
|
+
pluginId: BUNDLE_ID,
|
|
791
|
+
description: 'Image beside a heading, copy, and link',
|
|
792
|
+
category: Aglyn.ComponentCategory.BLOCKS,
|
|
793
|
+
icon: {
|
|
794
|
+
path: mdiImageText.path,
|
|
795
|
+
sx: {
|
|
796
|
+
color: '#7b1fa2'
|
|
797
|
+
}
|
|
798
|
+
},
|
|
799
|
+
data: {
|
|
800
|
+
$id: null,
|
|
801
|
+
componentId: 'muiStack',
|
|
802
|
+
pluginId: BUNDLE_ID,
|
|
803
|
+
props: {
|
|
804
|
+
direction: 'row',
|
|
805
|
+
spacing: 4
|
|
806
|
+
},
|
|
807
|
+
sx: {
|
|
808
|
+
paddingLeft: 4,
|
|
809
|
+
paddingRight: 4,
|
|
810
|
+
paddingTop: 6,
|
|
811
|
+
paddingBottom: 6,
|
|
812
|
+
alignItems: 'center',
|
|
813
|
+
flexWrap: 'wrap'
|
|
814
|
+
},
|
|
815
|
+
nodes: [
|
|
816
|
+
{
|
|
817
|
+
$id: null,
|
|
818
|
+
componentId: 'muiStack',
|
|
819
|
+
pluginId: BUNDLE_ID,
|
|
820
|
+
props: {},
|
|
821
|
+
sx: {
|
|
822
|
+
flex: 1,
|
|
823
|
+
minWidth: 280
|
|
824
|
+
},
|
|
825
|
+
nodes: [
|
|
826
|
+
{
|
|
827
|
+
$id: null,
|
|
828
|
+
componentId: 'image',
|
|
829
|
+
pluginId: BUNDLE_ID,
|
|
830
|
+
props: {
|
|
831
|
+
alt: 'Feature image',
|
|
832
|
+
height: '320px'
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
]
|
|
836
|
+
},
|
|
837
|
+
{
|
|
838
|
+
$id: null,
|
|
839
|
+
componentId: 'muiStack',
|
|
840
|
+
pluginId: BUNDLE_ID,
|
|
841
|
+
props: {
|
|
842
|
+
spacing: 2
|
|
843
|
+
},
|
|
844
|
+
sx: {
|
|
845
|
+
flex: 1,
|
|
846
|
+
minWidth: 280
|
|
847
|
+
},
|
|
848
|
+
nodes: [
|
|
849
|
+
text('h4', 'Show, then tell'),
|
|
850
|
+
text('body1', 'Pair a strong visual with a short paragraph that explains ' + 'what visitors are looking at and why it matters.'),
|
|
851
|
+
{
|
|
852
|
+
$id: null,
|
|
853
|
+
componentId: 'muiButton',
|
|
854
|
+
pluginId: BUNDLE_ID,
|
|
855
|
+
props: {
|
|
856
|
+
variant: 'outlined',
|
|
857
|
+
children: 'Learn more'
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
]
|
|
861
|
+
}
|
|
862
|
+
]
|
|
863
|
+
}
|
|
864
|
+
},
|
|
865
|
+
{
|
|
866
|
+
$id: generatePresetId('muiStack', 'cta'),
|
|
867
|
+
type: Aglyn.NodeType.PRESET,
|
|
868
|
+
displayName: 'Call to Action',
|
|
869
|
+
pluginId: BUNDLE_ID,
|
|
870
|
+
description: 'Accent band with a heading and button',
|
|
871
|
+
category: Aglyn.ComponentCategory.BLOCKS,
|
|
872
|
+
icon: {
|
|
873
|
+
path: mdiGestureTapButton.path,
|
|
874
|
+
sx: {
|
|
875
|
+
color: '#c2185b'
|
|
876
|
+
}
|
|
877
|
+
},
|
|
878
|
+
data: section({
|
|
879
|
+
// The accent band stays full-bleed — that is the point of a CTA —
|
|
880
|
+
// while its content is held to the page's width inside it.
|
|
881
|
+
bandSx: {
|
|
882
|
+
paddingTop: 8,
|
|
883
|
+
paddingBottom: 8,
|
|
884
|
+
paddingLeft: 4,
|
|
885
|
+
paddingRight: 4,
|
|
886
|
+
backgroundColor: 'primary.main',
|
|
887
|
+
color: 'primary.contrastText'
|
|
888
|
+
},
|
|
889
|
+
maxWidth: 'md',
|
|
890
|
+
layout: {
|
|
891
|
+
spacing: 2
|
|
892
|
+
},
|
|
893
|
+
layoutSx: {
|
|
894
|
+
alignItems: 'center'
|
|
895
|
+
},
|
|
896
|
+
nodes: [
|
|
897
|
+
text('h4', 'Ready to get started?', {
|
|
898
|
+
align: 'center'
|
|
899
|
+
}),
|
|
900
|
+
text('body1', 'Tell visitors the one thing to do next.', {
|
|
901
|
+
align: 'center'
|
|
902
|
+
}),
|
|
903
|
+
{
|
|
904
|
+
$id: null,
|
|
905
|
+
componentId: 'muiButton',
|
|
906
|
+
pluginId: BUNDLE_ID,
|
|
907
|
+
props: {
|
|
908
|
+
variant: 'contained',
|
|
909
|
+
color: 'primary',
|
|
910
|
+
size: 'large',
|
|
911
|
+
children: 'Get started'
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
]
|
|
915
|
+
})
|
|
916
|
+
},
|
|
917
|
+
// Contact Section moved to @aglyn/plugins-forms (AGL-395): a preset that
|
|
918
|
+
// places `form` nodes has to stamp them with the bundle that registers
|
|
919
|
+
// them, and this one is the only block preset that does.
|
|
920
|
+
{
|
|
921
|
+
$id: generatePresetId('section', 'footer'),
|
|
922
|
+
type: Aglyn.NodeType.PRESET,
|
|
923
|
+
displayName: 'Footer',
|
|
924
|
+
pluginId: BUNDLE_ID,
|
|
925
|
+
description: 'Semantic footer with brand, links, social, and copyright',
|
|
926
|
+
category: Aglyn.ComponentCategory.BLOCKS,
|
|
927
|
+
icon: {
|
|
928
|
+
path: mdiPageLayoutFooter.path,
|
|
929
|
+
sx: {
|
|
930
|
+
color: '#455a64'
|
|
931
|
+
}
|
|
932
|
+
},
|
|
933
|
+
data: {
|
|
934
|
+
$id: null,
|
|
935
|
+
componentId: 'section',
|
|
936
|
+
pluginId: BUNDLE_ID,
|
|
937
|
+
props: {
|
|
938
|
+
element: 'footer',
|
|
939
|
+
ariaLabel: 'Site footer'
|
|
940
|
+
},
|
|
941
|
+
sx: {
|
|
942
|
+
paddingLeft: 4,
|
|
943
|
+
paddingRight: 4,
|
|
944
|
+
paddingTop: 6,
|
|
945
|
+
paddingBottom: 6,
|
|
946
|
+
borderTop: 1,
|
|
947
|
+
borderColor: 'divider'
|
|
948
|
+
},
|
|
949
|
+
nodes: [
|
|
950
|
+
{
|
|
951
|
+
$id: null,
|
|
952
|
+
componentId: 'muiStack',
|
|
953
|
+
pluginId: BUNDLE_ID,
|
|
954
|
+
props: {
|
|
955
|
+
spacing: 2
|
|
956
|
+
},
|
|
957
|
+
nodes: [
|
|
958
|
+
{
|
|
959
|
+
$id: null,
|
|
960
|
+
componentId: 'muiStack',
|
|
961
|
+
pluginId: BUNDLE_ID,
|
|
962
|
+
props: {
|
|
963
|
+
direction: 'row',
|
|
964
|
+
spacing: 2
|
|
965
|
+
},
|
|
966
|
+
sx: {
|
|
967
|
+
justifyContent: 'space-between',
|
|
968
|
+
alignItems: 'center',
|
|
969
|
+
flexWrap: 'wrap'
|
|
970
|
+
},
|
|
971
|
+
nodes: [
|
|
972
|
+
text('h6', 'Your Brand'),
|
|
973
|
+
{
|
|
974
|
+
$id: null,
|
|
975
|
+
componentId: 'muiStack',
|
|
976
|
+
pluginId: BUNDLE_ID,
|
|
977
|
+
props: {
|
|
978
|
+
direction: 'row',
|
|
979
|
+
spacing: 1
|
|
980
|
+
},
|
|
981
|
+
nodes: [
|
|
982
|
+
navLink('Home'),
|
|
983
|
+
navLink('About'),
|
|
984
|
+
navLink('Contact')
|
|
985
|
+
]
|
|
986
|
+
}
|
|
987
|
+
]
|
|
988
|
+
},
|
|
989
|
+
{
|
|
990
|
+
$id: null,
|
|
991
|
+
componentId: SOCIAL_LINKS_ID,
|
|
992
|
+
pluginId: BUNDLE_ID,
|
|
993
|
+
props: {}
|
|
994
|
+
},
|
|
995
|
+
text('caption', '© Your Company. All rights reserved.', {
|
|
996
|
+
color: 'text.secondary'
|
|
997
|
+
})
|
|
998
|
+
]
|
|
999
|
+
}
|
|
1000
|
+
]
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
];
|
|
1004
|
+
export { SocialLinks, VideoEmbed };
|
|
1005
|
+
export default VideoEmbed;
|
|
1006
|
+
|
|
1007
|
+
//# sourceMappingURL=blocks.js.map
|