@aglyn/plugins-mui 1.0.0-beta.214 → 1.0.0-beta.216
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/package.json +7 -7
- package/src/lib/components/collection-author-links.d.ts +41 -0
- package/src/lib/components/collection-author-links.js +135 -0
- package/src/lib/components/collection-author-links.js.map +1 -0
- package/src/lib/components/collection-author-profile.d.ts +67 -0
- package/src/lib/components/collection-author-profile.js +269 -0
- package/src/lib/components/collection-author-profile.js.map +1 -0
- package/src/lib/components/collection-categories.d.ts +52 -0
- package/src/lib/components/collection-categories.js +163 -0
- package/src/lib/components/collection-categories.js.map +1 -0
- package/src/lib/components/collection-common.d.ts +104 -0
- package/src/lib/components/collection-common.js +95 -0
- package/src/lib/components/collection-common.js.map +1 -0
- package/src/lib/components/collection-entries.d.ts +137 -0
- package/src/lib/components/collection-entries.js +358 -0
- package/src/lib/components/collection-entries.js.map +1 -0
- package/src/lib/components/collection-entry-author.d.ts +81 -0
- package/src/lib/components/collection-entry-author.js +259 -0
- package/src/lib/components/collection-entry-author.js.map +1 -0
- package/src/lib/components/collection-entry-body.d.ts +44 -0
- package/src/lib/components/collection-entry-body.js +328 -0
- package/src/lib/components/collection-entry-body.js.map +1 -0
- package/src/lib/components/collection-entry-meta.d.ts +88 -0
- package/src/lib/components/collection-entry-meta.js +331 -0
- package/src/lib/components/collection-entry-meta.js.map +1 -0
- package/src/lib/components/collection-presets.d.ts +18 -0
- package/src/lib/components/collection-presets.js +328 -0
- package/src/lib/components/collection-presets.js.map +1 -0
- package/src/lib/components/collection-related.d.ts +101 -0
- package/src/lib/components/collection-related.js +536 -0
- package/src/lib/components/collection-related.js.map +1 -0
- package/src/lib/components/collection-search-box.d.ts +92 -0
- package/src/lib/components/collection-search-box.js +334 -0
- package/src/lib/components/collection-search-box.js.map +1 -0
- package/src/lib/components/collection-search-fuse.d.ts +28 -0
- package/src/lib/components/collection-search-fuse.js +28 -0
- package/src/lib/components/collection-search-fuse.js.map +1 -0
- package/src/lib/components/collection-search.d.ts +62 -0
- package/src/lib/components/collection-search.js +140 -0
- package/src/lib/components/collection-search.js.map +1 -0
- package/src/lib/components/collection-share.d.ts +31 -0
- package/src/lib/components/collection-share.js +154 -0
- package/src/lib/components/collection-share.js.map +1 -0
- package/src/lib/components/collection.d.ts +19 -497
- package/src/lib/components/collection.js +19 -2982
- package/src/lib/components/collection.js.map +1 -1
- package/src/lib/components/image-list.d.ts +2 -2
- package/src/lib/components/image-list.js +4 -6
- package/src/lib/components/image-list.js.map +1 -1
- package/src/lib/components/theme-mode-switcher.js +19 -19
- package/src/lib/components/theme-mode-switcher.js.map +1 -1
- package/src/lib/element-tier.d.ts +9 -1
- package/src/lib/element-tier.js +12 -1
- package/src/lib/element-tier.js.map +1 -1
- package/src/lib/plugin.js +20 -12
- package/src/lib/plugin.js.map +1 -1
- package/src/lib/utils/to-count.d.ts +25 -0
- package/src/lib/utils/to-count.js +30 -0
- package/src/lib/utils/to-count.js.map +1 -0
|
@@ -0,0 +1,259 @@
|
|
|
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, jsxs as _jsxs } 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 { mdiAccountCircleOutline } from "@aglyn/shared-data-mdi";
|
|
21
|
+
import { AppLink } from "@aglyn/shared-ui-jsx";
|
|
22
|
+
import Box from "@mui/material/Box";
|
|
23
|
+
import MuiStack from "@mui/material/Stack";
|
|
24
|
+
import Typography from "@mui/material/Typography";
|
|
25
|
+
import { forwardRef, useContext } from "react";
|
|
26
|
+
import { BUNDLE_ID } from "../constants/bundle-common.js";
|
|
27
|
+
import { UNRESOLVED_TOKEN, ENTRY_SAMPLE_AUTHOR, ENTRY_SAMPLE_BIO, samplePortraitSx, metaValue, SAFE_AUTHOR_HREF, EXTERNAL_AUTHOR_HREF } from "./collection-common.js";
|
|
28
|
+
import { AuthorLinkRows, safeAuthorLinks } from "./collection-author-links.js";
|
|
29
|
+
// Persisted component id (AGL-551/582); the compose pipeline references it
|
|
30
|
+
// through the @aglyn/aglyn constant. Never rename.
|
|
31
|
+
export const ENTRY_AUTHOR_ID = Aglyn.COLLECTION_ENTRY_AUTHOR_COMPONENT_ID;
|
|
32
|
+
/** The card's portrait, larger than the byline's 36px mark (Figma 170:190). */ const AUTHOR_AVATAR_SIZE = 48;
|
|
33
|
+
/**
|
|
34
|
+
* The author card that closes an article (AGL-2486) — portrait, byline, bio.
|
|
35
|
+
*
|
|
36
|
+
* Entry Meta prints a NAME beside a date, which is all an entry carried when
|
|
37
|
+
* it was written: one free-typed string. Custom authors made the byline a
|
|
38
|
+
* record with a portrait, a bio and a url, and a template that wanted the
|
|
39
|
+
* card the article frame draws still had to type the name and the blurb in as
|
|
40
|
+
* literal text — text that keeps saying whatever it said under posts somebody
|
|
41
|
+
* else wrote, and that no edit to the author record can ever reach. This is
|
|
42
|
+
* that card, filled from the record.
|
|
43
|
+
*
|
|
44
|
+
* Every field is independently overridable and every one of them collapses
|
|
45
|
+
* when empty: an author with no portrait renders the text alone rather than a
|
|
46
|
+
* gap where a face would be, and an entry with no author at all renders
|
|
47
|
+
* nothing — never an empty bordered box.
|
|
48
|
+
*/ const CollectionEntryAuthor = /*#__PURE__*/ forwardRef((props, ref)=>{
|
|
49
|
+
// None of these are DOM attributes (`name` least of all), so they are
|
|
50
|
+
// destructured rather than spread — the stack.ts pattern.
|
|
51
|
+
const { name, bio, image, url, pageUrl, links, showBio, showAvatar, showLinks } = props, rest = _object_without_properties_loose(props, [
|
|
52
|
+
"name",
|
|
53
|
+
"bio",
|
|
54
|
+
"image",
|
|
55
|
+
"url",
|
|
56
|
+
"pageUrl",
|
|
57
|
+
"links",
|
|
58
|
+
"showBio",
|
|
59
|
+
"showAvatar",
|
|
60
|
+
"showLinks"
|
|
61
|
+
]);
|
|
62
|
+
const nodeSx = Array.isArray(props['sx']) ? props['sx'] : [
|
|
63
|
+
props['sx']
|
|
64
|
+
];
|
|
65
|
+
const { suppressNavigation } = useContext(Aglyn.ScreenLinkContext);
|
|
66
|
+
const { hostId } = Aglyn.useSite();
|
|
67
|
+
const nameValue = metaValue(name, suppressNavigation);
|
|
68
|
+
const bioValue = showBio !== false ? metaValue(bio, suppressNavigation) : '';
|
|
69
|
+
// Their page here first, their own site second (AGL-2519) — see `pageUrl`.
|
|
70
|
+
const hrefRaw = metaValue(pageUrl, suppressNavigation) || metaValue(url, suppressNavigation);
|
|
71
|
+
const urlValue = SAFE_AUTHOR_HREF.test(hrefRaw) ? hrefRaw : '';
|
|
72
|
+
// An unresolved token empties on EVERY surface, as in the byline: a literal
|
|
73
|
+
// `{{…}}` in a src is a broken portrait in the canvas.
|
|
74
|
+
const imageRaw = (image != null ? image : '').trim();
|
|
75
|
+
const imageSrc = showAvatar !== false && imageRaw && !UNRESOLVED_TOKEN.test(imageRaw) ? Aglyn.resolveMediaSrc(imageRaw, {
|
|
76
|
+
hostId
|
|
77
|
+
}) : '';
|
|
78
|
+
// Nothing to show and nothing to route from: an editing surface previews
|
|
79
|
+
// the card's own markup at the author's own settings, and a published page
|
|
80
|
+
// renders nothing at all (AGL-2486). Every part still answers its own
|
|
81
|
+
// switch, so a card with Show bio off previews as portrait and name.
|
|
82
|
+
const sample = !nameValue && !bioValue && !imageSrc && Boolean(suppressNavigation);
|
|
83
|
+
const displayName = sample ? ENTRY_SAMPLE_AUTHOR : nameValue;
|
|
84
|
+
const displayBio = sample && showBio !== false ? ENTRY_SAMPLE_BIO : bioValue;
|
|
85
|
+
// The record's portrait arrives at compose time, so there is none to
|
|
86
|
+
// resolve on the canvas — the card draws its slot, which is the thing its
|
|
87
|
+
// spacing is built around.
|
|
88
|
+
const samplePortrait = sample && showAvatar !== false;
|
|
89
|
+
/**
|
|
90
|
+
* The rows this card will actually draw (AGL-2516).
|
|
91
|
+
*
|
|
92
|
+
* Guarded here rather than trusted from the store: these arrive as PROPS,
|
|
93
|
+
* so a link can reach the renderer without passing the record normalizer,
|
|
94
|
+
* and `javascript:` has to be unreachable rather than merely unlikely — the
|
|
95
|
+
* same reason the byline's own `url` is checked twice.
|
|
96
|
+
*/ const linkRows = safeAuthorLinks(links, showLinks);
|
|
97
|
+
if (!displayName && !displayBio && !imageSrc && !samplePortrait && !linkRows.length) {
|
|
98
|
+
return /*#__PURE__*/ _jsx(Box, _extends({
|
|
99
|
+
ref: ref
|
|
100
|
+
}, rest));
|
|
101
|
+
}
|
|
102
|
+
return /*#__PURE__*/ _jsxs(MuiStack, _extends({
|
|
103
|
+
ref: ref,
|
|
104
|
+
direction: "row",
|
|
105
|
+
spacing: 2
|
|
106
|
+
}, rest, {
|
|
107
|
+
// MERGE, never replace (AGL-1450): `rest.sx` is the array leaf.tsx
|
|
108
|
+
// builds, and spreading it into an object drops every authored value.
|
|
109
|
+
sx: [
|
|
110
|
+
{
|
|
111
|
+
alignItems: 'flex-start',
|
|
112
|
+
p: 2.5,
|
|
113
|
+
border: '1px solid',
|
|
114
|
+
borderColor: 'divider',
|
|
115
|
+
borderRadius: 1
|
|
116
|
+
},
|
|
117
|
+
...nodeSx
|
|
118
|
+
],
|
|
119
|
+
children: [
|
|
120
|
+
imageSrc ? /*#__PURE__*/ _jsx(Box, _extends({
|
|
121
|
+
component: "img",
|
|
122
|
+
src: imageSrc,
|
|
123
|
+
// Decorative: the card names the author in text right beside it.
|
|
124
|
+
alt: "",
|
|
125
|
+
sx: {
|
|
126
|
+
display: 'block',
|
|
127
|
+
flexShrink: 0,
|
|
128
|
+
width: AUTHOR_AVATAR_SIZE,
|
|
129
|
+
height: AUTHOR_AVATAR_SIZE,
|
|
130
|
+
borderRadius: '50%',
|
|
131
|
+
objectFit: 'cover'
|
|
132
|
+
}
|
|
133
|
+
}, Aglyn.DEFERRED_IMAGE_ATTRIBUTES)) : samplePortrait ? /*#__PURE__*/ _jsx(Box, {
|
|
134
|
+
"aria-hidden": true,
|
|
135
|
+
sx: samplePortraitSx(AUTHOR_AVATAR_SIZE)
|
|
136
|
+
}) : null,
|
|
137
|
+
/*#__PURE__*/ _jsxs(MuiStack, {
|
|
138
|
+
spacing: 0.5,
|
|
139
|
+
sx: {
|
|
140
|
+
minWidth: 0
|
|
141
|
+
},
|
|
142
|
+
children: [
|
|
143
|
+
displayName ? /*#__PURE__*/ _jsx(Typography, {
|
|
144
|
+
component: "p",
|
|
145
|
+
variant: "subtitle2",
|
|
146
|
+
children: urlValue ? /*#__PURE__*/ _jsx(AppLink, _extends({
|
|
147
|
+
href: urlValue,
|
|
148
|
+
sx: {
|
|
149
|
+
color: 'inherit'
|
|
150
|
+
},
|
|
151
|
+
underline: "hover"
|
|
152
|
+
}, EXTERNAL_AUTHOR_HREF.test(urlValue) ? {
|
|
153
|
+
target: '_blank',
|
|
154
|
+
rel: 'noopener noreferrer'
|
|
155
|
+
} : {}, {
|
|
156
|
+
children: displayName
|
|
157
|
+
})) : displayName
|
|
158
|
+
}) : null,
|
|
159
|
+
displayBio ? /*#__PURE__*/ _jsx(Typography, {
|
|
160
|
+
variant: "body2",
|
|
161
|
+
sx: {
|
|
162
|
+
color: 'text.secondary'
|
|
163
|
+
},
|
|
164
|
+
children: displayBio
|
|
165
|
+
}) : null,
|
|
166
|
+
/*#__PURE__*/ _jsx(AuthorLinkRows, {
|
|
167
|
+
links: linkRows
|
|
168
|
+
})
|
|
169
|
+
]
|
|
170
|
+
})
|
|
171
|
+
]
|
|
172
|
+
}));
|
|
173
|
+
});
|
|
174
|
+
CollectionEntryAuthor.displayName = 'AglynCollectionEntryAuthor';
|
|
175
|
+
export const collectionEntryAuthorSchema = {
|
|
176
|
+
$id: ENTRY_AUTHOR_ID,
|
|
177
|
+
pluginId: BUNDLE_ID,
|
|
178
|
+
displayName: 'Entry Author',
|
|
179
|
+
description: 'The author card for an entry — portrait, byline and bio.',
|
|
180
|
+
category: Aglyn.ComponentCategory.TEXT,
|
|
181
|
+
icon: {
|
|
182
|
+
path: mdiAccountCircleOutline.path,
|
|
183
|
+
sx: {
|
|
184
|
+
color: 'secondary.main'
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
flags: {
|
|
188
|
+
selfClosing: Aglyn.FEATURE_FLAG.ENABLED
|
|
189
|
+
},
|
|
190
|
+
attributes: [
|
|
191
|
+
{
|
|
192
|
+
name: 'name',
|
|
193
|
+
label: 'Name',
|
|
194
|
+
description: 'Blank shows the name from the entry’s author record. Type here ' + '(or bind {{entry.author}}) to sign this card differently from ' + 'the byline above the article.',
|
|
195
|
+
component: Aglyn.FieldComponentType.TEXT_FIELD
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
name: 'bio',
|
|
199
|
+
label: 'Bio',
|
|
200
|
+
description: 'Blank shows the bio from the author’s record. Type here (or bind ' + '{{entry.authorBio}}) only to override it.',
|
|
201
|
+
component: Aglyn.FieldComponentType.TEXTAREA
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
name: 'image',
|
|
205
|
+
label: 'Portrait',
|
|
206
|
+
description: 'Blank shows the portrait from the author’s record. Pick from your ' + 'media library with "Browse media" only to override it.',
|
|
207
|
+
component: Aglyn.FieldComponentType.TEXT_FIELD
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
name: 'pageUrl',
|
|
211
|
+
label: 'Name links to',
|
|
212
|
+
description: 'Blank sends the name to the author’s page on this site — ' + 'everything they wrote. Falls back to their own url when they have ' + 'no page; type here to override both.',
|
|
213
|
+
component: Aglyn.FieldComponentType.TEXT_FIELD
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
name: 'url',
|
|
217
|
+
label: 'Their own site',
|
|
218
|
+
description: 'Blank uses the url on the author’s record. Used only when they ' + 'have no page on this site for the name to link to.',
|
|
219
|
+
component: Aglyn.FieldComponentType.TEXT_FIELD
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
name: 'showLinks',
|
|
223
|
+
label: 'Show links',
|
|
224
|
+
description: 'Off hides the author’s profile links. They come from the author ' + 'record — a known platform brings its own mark, and a custom link ' + 'brings the icon and label chosen there.',
|
|
225
|
+
component: Aglyn.FieldComponentType.SWITCH,
|
|
226
|
+
// Unset means SHOWN in the renderer above, so the switch has to open
|
|
227
|
+
// in that position or it lies about the card in front of the author
|
|
228
|
+
// (AGL-2506).
|
|
229
|
+
initialValue: true
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
name: 'showBio',
|
|
233
|
+
label: 'Show bio',
|
|
234
|
+
description: 'Off leaves the card as a portrait and a name — for a masthead ' + 'where the blurb would repeat what the page already says.',
|
|
235
|
+
component: Aglyn.FieldComponentType.SWITCH,
|
|
236
|
+
// Unset means SHOWN in the renderer above, so the switch has to
|
|
237
|
+
// OPEN in that position or it lies about the block in front of
|
|
238
|
+
// the author — and the first click, which writes the `true` that
|
|
239
|
+
// was already in effect, changes nothing and reads as a dead
|
|
240
|
+
// control (AGL-2506).
|
|
241
|
+
initialValue: true
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
name: 'showAvatar',
|
|
245
|
+
label: 'Show portrait',
|
|
246
|
+
description: 'Off leaves the text alone, with no space held for a picture.',
|
|
247
|
+
component: Aglyn.FieldComponentType.SWITCH,
|
|
248
|
+
// Unset means SHOWN in the renderer above, so the switch has to
|
|
249
|
+
// OPEN in that position or it lies about the block in front of
|
|
250
|
+
// the author — and the first click, which writes the `true` that
|
|
251
|
+
// was already in effect, changes nothing and reads as a dead
|
|
252
|
+
// control (AGL-2506).
|
|
253
|
+
initialValue: true
|
|
254
|
+
}
|
|
255
|
+
]
|
|
256
|
+
};
|
|
257
|
+
export { CollectionEntryAuthor };
|
|
258
|
+
|
|
259
|
+
//# sourceMappingURL=collection-entry-author.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/components/collection-entry-author.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as Aglyn from '@aglyn/aglyn'\nimport { mdiAccountCircleOutline } from '@aglyn/shared-data-mdi'\nimport { AppLink } from '@aglyn/shared-ui-jsx'\nimport Box from '@mui/material/Box'\nimport MuiStack, { type StackProps } from '@mui/material/Stack'\nimport Typography from '@mui/material/Typography'\nimport { forwardRef, useContext } from 'react'\nimport { BUNDLE_ID } from '../constants/bundle-common'\nimport {\n UNRESOLVED_TOKEN,\n ENTRY_SAMPLE_AUTHOR,\n ENTRY_SAMPLE_BIO,\n samplePortraitSx,\n metaValue,\n SAFE_AUTHOR_HREF,\n EXTERNAL_AUTHOR_HREF,\n} from './collection-common'\nimport { AuthorLinkRows, safeAuthorLinks } from './collection-author-links'\n\n// Persisted component id (AGL-551/582); the compose pipeline references it\n// through the @aglyn/aglyn constant. Never rename.\nexport const ENTRY_AUTHOR_ID: Aglyn.ComponentId =\n Aglyn.COLLECTION_ENTRY_AUTHOR_COMPONENT_ID\n\nexport interface CollectionEntryAuthorProps extends StackProps {\n /**\n * The byline. Server-filled from the routed entry's author record on entry\n * templates (`expandCollectionEntryAuthor`), exactly like Entry Meta's\n * fields; set it — or bind `{{entry.author}}` — only to override.\n */\n name?: string\n /**\n * The author's blurb, from their record's `bio`; bind\n * `{{entry.authorBio}}` to override.\n */\n bio?: string\n /**\n * Portrait or logo — a media reference (AGL-1215) or any URL. Server-filled\n * from the author record, so the face changes with the byline instead of\n * being picked once on the template the way Entry Meta's avatar is.\n */\n image?: string\n /** The author's own site; offered as a link row beside the profile ones. */\n url?: string\n /**\n * The author's page on THIS site (AGL-2519), server-filled from the routed\n * entry. The name links here.\n *\n * It wins over {@link url} for the NAME, and the ordering is the point: a\n * reader who clicks a byline at the end of an article is asking \"what else\n * has this person written here\", not \"take me off this site\". Their own\n * url is still reachable — it is one of the link rows — so nothing is lost\n * by giving the name the destination that answers the question asked.\n */\n pageUrl?: string\n /**\n * The author's profile links, server-filled from their record (AGL-2516).\n *\n * Not authorable as text: each row carries a platform or a picked icon, and\n * the console's author editor is where those are chosen. `Show links` is\n * the template's control over them.\n */\n links?: Aglyn.ContentAuthorLink[]\n showBio?: boolean\n showAvatar?: boolean\n showLinks?: boolean\n}\n\n/** The card's portrait, larger than the byline's 36px mark (Figma 170:190). */\nconst AUTHOR_AVATAR_SIZE = 48\n\n/**\n * The author card that closes an article (AGL-2486) — portrait, byline, bio.\n *\n * Entry Meta prints a NAME beside a date, which is all an entry carried when\n * it was written: one free-typed string. Custom authors made the byline a\n * record with a portrait, a bio and a url, and a template that wanted the\n * card the article frame draws still had to type the name and the blurb in as\n * literal text — text that keeps saying whatever it said under posts somebody\n * else wrote, and that no edit to the author record can ever reach. This is\n * that card, filled from the record.\n *\n * Every field is independently overridable and every one of them collapses\n * when empty: an author with no portrait renders the text alone rather than a\n * gap where a face would be, and an entry with no author at all renders\n * nothing — never an empty bordered box.\n */\nconst CollectionEntryAuthor = forwardRef<\n HTMLDivElement,\n CollectionEntryAuthorProps\n>((props, ref) => {\n // None of these are DOM attributes (`name` least of all), so they are\n // destructured rather than spread — the stack.ts pattern.\n const {\n name,\n bio,\n image,\n url,\n pageUrl,\n links,\n showBio,\n showAvatar,\n showLinks,\n ...rest\n } = props\n const nodeSx = Array.isArray(props['sx']) ? props['sx'] : [props['sx']]\n const { suppressNavigation } = useContext(Aglyn.ScreenLinkContext)\n const { hostId } = Aglyn.useSite()\n const nameValue = metaValue(name, suppressNavigation)\n const bioValue = showBio !== false ? metaValue(bio, suppressNavigation) : ''\n // Their page here first, their own site second (AGL-2519) — see `pageUrl`.\n const hrefRaw = metaValue(pageUrl, suppressNavigation) ||\n metaValue(url, suppressNavigation)\n const urlValue = SAFE_AUTHOR_HREF.test(hrefRaw) ? hrefRaw : ''\n // An unresolved token empties on EVERY surface, as in the byline: a literal\n // `{{…}}` in a src is a broken portrait in the canvas.\n const imageRaw = (image ?? '').trim()\n const imageSrc =\n showAvatar !== false && imageRaw && !UNRESOLVED_TOKEN.test(imageRaw)\n ? Aglyn.resolveMediaSrc(imageRaw, { hostId })\n : ''\n // Nothing to show and nothing to route from: an editing surface previews\n // the card's own markup at the author's own settings, and a published page\n // renders nothing at all (AGL-2486). Every part still answers its own\n // switch, so a card with Show bio off previews as portrait and name.\n const sample = !nameValue && !bioValue && !imageSrc && Boolean(suppressNavigation)\n const displayName = sample ? ENTRY_SAMPLE_AUTHOR : nameValue\n const displayBio = sample && showBio !== false ? ENTRY_SAMPLE_BIO : bioValue\n // The record's portrait arrives at compose time, so there is none to\n // resolve on the canvas — the card draws its slot, which is the thing its\n // spacing is built around.\n const samplePortrait = sample && showAvatar !== false\n /**\n * The rows this card will actually draw (AGL-2516).\n *\n * Guarded here rather than trusted from the store: these arrive as PROPS,\n * so a link can reach the renderer without passing the record normalizer,\n * and `javascript:` has to be unreachable rather than merely unlikely — the\n * same reason the byline's own `url` is checked twice.\n */\n const linkRows = safeAuthorLinks(links, showLinks)\n if (\n !displayName &&\n !displayBio &&\n !imageSrc &&\n !samplePortrait &&\n !linkRows.length\n ) {\n return <Box ref={ref} {...rest} />\n }\n return (\n <MuiStack\n ref={ref}\n direction=\"row\"\n spacing={2}\n {...rest}\n // MERGE, never replace (AGL-1450): `rest.sx` is the array leaf.tsx\n // builds, and spreading it into an object drops every authored value.\n sx={[\n {\n alignItems: 'flex-start',\n p: 2.5,\n border: '1px solid',\n borderColor: 'divider',\n borderRadius: 1,\n },\n ...nodeSx,\n ]}\n >\n {imageSrc ? (\n <Box\n component=\"img\"\n src={imageSrc}\n // Decorative: the card names the author in text right beside it.\n alt=\"\"\n sx={{\n display: 'block',\n flexShrink: 0,\n width: AUTHOR_AVATAR_SIZE,\n height: AUTHOR_AVATAR_SIZE,\n borderRadius: '50%',\n objectFit: 'cover',\n }}\n {...Aglyn.DEFERRED_IMAGE_ATTRIBUTES}\n />\n ) : samplePortrait ? (\n <Box aria-hidden sx={samplePortraitSx(AUTHOR_AVATAR_SIZE)} />\n ) : null}\n <MuiStack spacing={0.5} sx={{ minWidth: 0 }}>\n {displayName ? (\n <Typography component=\"p\" variant=\"subtitle2\">\n {urlValue ? (\n <AppLink\n href={urlValue}\n sx={{ color: 'inherit' }}\n underline=\"hover\"\n {...(EXTERNAL_AUTHOR_HREF.test(urlValue)\n ? { target: '_blank', rel: 'noopener noreferrer' }\n : {})}\n >\n {displayName}\n </AppLink>\n ) : (\n displayName\n )}\n </Typography>\n ) : null}\n {displayBio ? (\n <Typography variant=\"body2\" sx={{ color: 'text.secondary' }}>\n {displayBio}\n </Typography>\n ) : null}\n <AuthorLinkRows links={linkRows} />\n </MuiStack>\n </MuiStack>\n )\n})\nCollectionEntryAuthor.displayName = 'AglynCollectionEntryAuthor'\n\nexport const collectionEntryAuthorSchema: Aglyn.ComponentSchema<CollectionEntryAuthorProps> =\n {\n $id: ENTRY_AUTHOR_ID,\n pluginId: BUNDLE_ID,\n displayName: 'Entry Author',\n description: 'The author card for an entry — portrait, byline and bio.',\n category: Aglyn.ComponentCategory.TEXT,\n icon: {\n path: mdiAccountCircleOutline.path,\n sx: { color: 'secondary.main' },\n },\n flags: { selfClosing: Aglyn.FEATURE_FLAG.ENABLED },\n attributes: [\n {\n name: 'name',\n label: 'Name',\n description:\n 'Blank shows the name from the entry’s author record. Type here ' +\n '(or bind {{entry.author}}) to sign this card differently from ' +\n 'the byline above the article.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n },\n {\n name: 'bio',\n label: 'Bio',\n description:\n 'Blank shows the bio from the author’s record. Type here (or bind ' +\n '{{entry.authorBio}}) only to override it.',\n component: Aglyn.FieldComponentType.TEXTAREA,\n },\n {\n name: 'image',\n label: 'Portrait',\n description:\n 'Blank shows the portrait from the author’s record. Pick from your ' +\n 'media library with \"Browse media\" only to override it.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n },\n {\n name: 'pageUrl',\n label: 'Name links to',\n description:\n 'Blank sends the name to the author’s page on this site — ' +\n 'everything they wrote. Falls back to their own url when they have ' +\n 'no page; type here to override both.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n },\n {\n name: 'url',\n label: 'Their own site',\n description:\n 'Blank uses the url on the author’s record. Used only when they ' +\n 'have no page on this site for the name to link to.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n },\n {\n name: 'showLinks',\n label: 'Show links',\n description:\n 'Off hides the author’s profile links. They come from the author ' +\n 'record — a known platform brings its own mark, and a custom link ' +\n 'brings the icon and label chosen there.',\n component: Aglyn.FieldComponentType.SWITCH,\n // Unset means SHOWN in the renderer above, so the switch has to open\n // in that position or it lies about the card in front of the author\n // (AGL-2506).\n initialValue: true,\n },\n {\n name: 'showBio',\n label: 'Show bio',\n description:\n 'Off leaves the card as a portrait and a name — for a masthead ' +\n 'where the blurb would repeat what the page already says.',\n component: Aglyn.FieldComponentType.SWITCH,\n // Unset means SHOWN in the renderer above, so the switch has to\n // OPEN in that position or it lies about the block in front of\n // the author — and the first click, which writes the `true` that\n // was already in effect, changes nothing and reads as a dead\n // control (AGL-2506).\n initialValue: true,\n },\n {\n name: 'showAvatar',\n label: 'Show portrait',\n description:\n 'Off leaves the text alone, with no space held for a picture.',\n component: Aglyn.FieldComponentType.SWITCH,\n // Unset means SHOWN in the renderer above, so the switch has to\n // OPEN in that position or it lies about the block in front of\n // the author — and the first click, which writes the `true` that\n // was already in effect, changes nothing and reads as a dead\n // control (AGL-2506).\n initialValue: true,\n },\n ],\n }\n\nexport { CollectionEntryAuthor }\n"],"names":["Aglyn","mdiAccountCircleOutline","AppLink","Box","MuiStack","Typography","forwardRef","useContext","BUNDLE_ID","UNRESOLVED_TOKEN","ENTRY_SAMPLE_AUTHOR","ENTRY_SAMPLE_BIO","samplePortraitSx","metaValue","SAFE_AUTHOR_HREF","EXTERNAL_AUTHOR_HREF","AuthorLinkRows","safeAuthorLinks","ENTRY_AUTHOR_ID","COLLECTION_ENTRY_AUTHOR_COMPONENT_ID","AUTHOR_AVATAR_SIZE","CollectionEntryAuthor","props","ref","name","bio","image","url","pageUrl","links","showBio","showAvatar","showLinks","rest","nodeSx","Array","isArray","suppressNavigation","ScreenLinkContext","hostId","useSite","nameValue","bioValue","hrefRaw","urlValue","test","imageRaw","trim","imageSrc","resolveMediaSrc","sample","Boolean","displayName","displayBio","samplePortrait","linkRows","length","direction","spacing","sx","alignItems","p","border","borderColor","borderRadius","component","src","alt","display","flexShrink","width","height","objectFit","DEFERRED_IMAGE_ATTRIBUTES","aria-hidden","minWidth","variant","href","color","underline","target","rel","collectionEntryAuthorSchema","$id","pluginId","description","category","ComponentCategory","TEXT","icon","path","flags","selfClosing","FEATURE_FLAG","ENABLED","attributes","label","FieldComponentType","TEXT_FIELD","TEXTAREA","SWITCH","initialValue"],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
import * as Aglyn from '@aglyn/aglyn';
|
|
18
|
+
export declare const ENTRY_BODY_ID: Aglyn.ComponentId;
|
|
19
|
+
export interface CollectionEntryBodyProps {
|
|
20
|
+
/**
|
|
21
|
+
* Markdown-lite source. On entry-template screens `{{entry.body}}`
|
|
22
|
+
* resolves to the rendered entry's body at compose time.
|
|
23
|
+
*/
|
|
24
|
+
markdown?: string;
|
|
25
|
+
/**
|
|
26
|
+
* The pixel pair of each library image this body names, keyed by the target
|
|
27
|
+
* as the body writes it, stamped by the composition from the assets' DAM
|
|
28
|
+
* records (AGL-3149) — never set by hand, and never on the template, where
|
|
29
|
+
* `markdown` is still the `{{entry.body}}` token and names no asset.
|
|
30
|
+
*/
|
|
31
|
+
intrinsicSizes?: Record<string, {
|
|
32
|
+
width: number;
|
|
33
|
+
height: number;
|
|
34
|
+
}>;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Renders a content entry's markdown-lite body as themed MUI elements
|
|
38
|
+
* (AGL-551): headings, paragraphs, lists, and images pick up the site
|
|
39
|
+
* theme's typography instead of the old unthemed article HTML. Parsing is
|
|
40
|
+
* pure, so the full body server-renders (SEO keeps the article text).
|
|
41
|
+
*/
|
|
42
|
+
declare const CollectionEntryBody: import("react").ForwardRefExoticComponent<CollectionEntryBodyProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
43
|
+
export declare const collectionEntryBodySchema: Aglyn.ComponentSchema<CollectionEntryBodyProps>;
|
|
44
|
+
export { CollectionEntryBody };
|