@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,52 @@
|
|
|
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
|
+
import { type StackProps } from '@mui/material/Stack';
|
|
19
|
+
export declare const CATEGORIES_ID: Aglyn.ComponentId;
|
|
20
|
+
export interface CollectionCategoriesProps extends StackProps {
|
|
21
|
+
/**
|
|
22
|
+
* Collection whose taxonomy renders (compose-time). Blank = the collection
|
|
23
|
+
* routed by the current URL on list-template screens.
|
|
24
|
+
*/
|
|
25
|
+
collectionSlug?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Label for the unfiltered pill (default "All"). Clearing the field
|
|
28
|
+
* persists `Aglyn.COLLECTION_ALL_PILL_NONE`, which omits the pill —
|
|
29
|
+
* `''` cannot be stored at all (AGL-1336).
|
|
30
|
+
*/
|
|
31
|
+
allLabel?: string;
|
|
32
|
+
/**
|
|
33
|
+
* Server-stamped pill links (`expandCollectionCategories`); never set by
|
|
34
|
+
* hand — the tenant builds them from the collection's categories and the
|
|
35
|
+
* routed category.
|
|
36
|
+
*/
|
|
37
|
+
items?: Aglyn.CollectionCategoryLink[];
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* The category filter row for a collection listing (AGL-1321): "All" plus one
|
|
41
|
+
* pill per category, each a REAL anchor to `/{collection}/category/{slug}`.
|
|
42
|
+
*
|
|
43
|
+
* Anchors, not click handlers, and that is the whole design. A JS-only toggle
|
|
44
|
+
* would be invisible to crawlers, unopenable in a new tab, unlinkable, and
|
|
45
|
+
* unreachable without hydration — and it could not exist anyway, since the
|
|
46
|
+
* filter is resolved server-side before the page is composed. The pill the
|
|
47
|
+
* current URL selected carries `aria-current="page"`, stamped on the server so
|
|
48
|
+
* it is in the HTML rather than derived after hydration.
|
|
49
|
+
*/
|
|
50
|
+
declare const CollectionCategories: import("react").ForwardRefExoticComponent<Omit<CollectionCategoriesProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
|
|
51
|
+
export declare const collectionCategoriesSchema: Aglyn.ComponentSchema<CollectionCategoriesProps>;
|
|
52
|
+
export { CollectionCategories };
|
|
@@ -0,0 +1,163 @@
|
|
|
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 { mdiTagMultipleOutline } 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 { forwardRef, useContext } from "react";
|
|
25
|
+
import { BUNDLE_ID } from "../constants/bundle-common.js";
|
|
26
|
+
// Persisted component id (AGL-551/582); the compose pipeline references it
|
|
27
|
+
// through the @aglyn/aglyn constant. Never rename.
|
|
28
|
+
export const CATEGORIES_ID = Aglyn.COLLECTION_CATEGORIES_COMPONENT_ID;
|
|
29
|
+
/** Pill look, in palette tokens so it follows the site theme in both modes. */ const pillSx = (active)=>({
|
|
30
|
+
px: 1.75,
|
|
31
|
+
py: 0.75,
|
|
32
|
+
borderRadius: 999,
|
|
33
|
+
border: '1px solid',
|
|
34
|
+
borderColor: active ? 'primary.main' : 'divider',
|
|
35
|
+
bgcolor: active ? 'primary.main' : 'transparent',
|
|
36
|
+
color: active ? 'primary.contrastText' : 'text.secondary',
|
|
37
|
+
fontSize: 14,
|
|
38
|
+
lineHeight: 1.2,
|
|
39
|
+
whiteSpace: 'nowrap',
|
|
40
|
+
'&:hover': {
|
|
41
|
+
borderColor: active ? 'primary.main' : 'text.primary',
|
|
42
|
+
color: active ? 'primary.contrastText' : 'text.primary'
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
/**
|
|
46
|
+
* The category filter row for a collection listing (AGL-1321): "All" plus one
|
|
47
|
+
* pill per category, each a REAL anchor to `/{collection}/category/{slug}`.
|
|
48
|
+
*
|
|
49
|
+
* Anchors, not click handlers, and that is the whole design. A JS-only toggle
|
|
50
|
+
* would be invisible to crawlers, unopenable in a new tab, unlinkable, and
|
|
51
|
+
* unreachable without hydration — and it could not exist anyway, since the
|
|
52
|
+
* filter is resolved server-side before the page is composed. The pill the
|
|
53
|
+
* current URL selected carries `aria-current="page"`, stamped on the server so
|
|
54
|
+
* it is in the HTML rather than derived after hydration.
|
|
55
|
+
*/ const CollectionCategories = /*#__PURE__*/ forwardRef((props, ref)=>{
|
|
56
|
+
// `collectionSlug`/`allLabel` are compose-time: the tenant resolves them
|
|
57
|
+
// while stamping `items`; strip so they never hit the DOM.
|
|
58
|
+
const { collectionSlug, allLabel, items } = props, rest = _object_without_properties_loose(props, [
|
|
59
|
+
"collectionSlug",
|
|
60
|
+
"allLabel",
|
|
61
|
+
"items"
|
|
62
|
+
]);
|
|
63
|
+
// Node styles ride the renderer-merged sx; recompose (stack.ts pattern).
|
|
64
|
+
const nodeSx = Array.isArray(props['sx']) ? props['sx'] : [
|
|
65
|
+
props['sx']
|
|
66
|
+
];
|
|
67
|
+
const { suppressNavigation } = useContext(Aglyn.ScreenLinkContext);
|
|
68
|
+
if (!(items == null ? void 0 : items.length)) {
|
|
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
|
+
p: 2,
|
|
78
|
+
border: '1px dashed',
|
|
79
|
+
borderColor: 'divider',
|
|
80
|
+
color: 'text.secondary',
|
|
81
|
+
fontSize: 12,
|
|
82
|
+
fontFamily: 'system-ui, sans-serif'
|
|
83
|
+
},
|
|
84
|
+
...nodeSx
|
|
85
|
+
],
|
|
86
|
+
children: 'Category pills — All + one pill per collection category render here'
|
|
87
|
+
}));
|
|
88
|
+
}
|
|
89
|
+
return /*#__PURE__*/ _jsx(MuiStack, _extends({
|
|
90
|
+
ref: ref,
|
|
91
|
+
direction: "row",
|
|
92
|
+
spacing: 1
|
|
93
|
+
}, rest, {
|
|
94
|
+
// MERGE, never replace (AGL-1450) — see collection-entry-meta.tsx.
|
|
95
|
+
sx: [
|
|
96
|
+
{
|
|
97
|
+
flexWrap: 'wrap',
|
|
98
|
+
rowGap: 1
|
|
99
|
+
},
|
|
100
|
+
...nodeSx
|
|
101
|
+
],
|
|
102
|
+
children: items.map((item)=>// Editing surfaces render the pill look without an href, so a click
|
|
103
|
+
// in the besigner never navigates the canvas away.
|
|
104
|
+
suppressNavigation ? /*#__PURE__*/ _jsx(Box, {
|
|
105
|
+
sx: pillSx(item.active),
|
|
106
|
+
children: item.label
|
|
107
|
+
}, item.href) : /*#__PURE__*/ _jsx(AppLink, {
|
|
108
|
+
href: item.href,
|
|
109
|
+
underline: "none",
|
|
110
|
+
"aria-current": item.active ? 'page' : undefined,
|
|
111
|
+
sx: pillSx(item.active),
|
|
112
|
+
children: item.label
|
|
113
|
+
}, item.href))
|
|
114
|
+
}));
|
|
115
|
+
});
|
|
116
|
+
CollectionCategories.displayName = 'AglynCollectionCategories';
|
|
117
|
+
export const collectionCategoriesSchema = {
|
|
118
|
+
$id: CATEGORIES_ID,
|
|
119
|
+
pluginId: BUNDLE_ID,
|
|
120
|
+
displayName: 'Category Pills',
|
|
121
|
+
description: 'A pill per collection category, each filtering the listing.',
|
|
122
|
+
category: Aglyn.ComponentCategory.NAVIGATION,
|
|
123
|
+
icon: {
|
|
124
|
+
path: mdiTagMultipleOutline.path,
|
|
125
|
+
sx: {
|
|
126
|
+
color: 'secondary.main'
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
flags: {
|
|
130
|
+
selfClosing: Aglyn.FEATURE_FLAG.ENABLED
|
|
131
|
+
},
|
|
132
|
+
attributes: [
|
|
133
|
+
{
|
|
134
|
+
name: 'collectionSlug',
|
|
135
|
+
label: 'Collection slug',
|
|
136
|
+
description: 'Content collection whose categories render as pills (e.g. ' + '"blog"). Leave blank on a list-template screen to use the ' + 'collection from the URL.',
|
|
137
|
+
component: Aglyn.FieldComponentType.TEXT_FIELD
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
name: 'allLabel',
|
|
141
|
+
label: 'All label',
|
|
142
|
+
description: 'Label for the unfiltered pill, which links to the collection ' + 'root (default "All"). Clear the box to omit that pill — it then ' + 'reads "none", which is what makes the omission stick. Typing ' + '"none" does the same thing.',
|
|
143
|
+
component: Aglyn.FieldComponentType.TEXT_FIELD,
|
|
144
|
+
// Without this the emptied field persists NOTHING (AGL-1336): ddf
|
|
145
|
+
// maps an emptied value to `clearedValue`, final-form's parse turns
|
|
146
|
+
// `''` into `undefined`, and the missing key takes the runtime
|
|
147
|
+
// default — so "clear it to omit that pill" was undoable by
|
|
148
|
+
// clicking. Same shape as FIELD_COLOR_ALT1's `'default'` (AGL-1191):
|
|
149
|
+
// a value that means something has to BE something.
|
|
150
|
+
//
|
|
151
|
+
// ddf only substitutes `clearedValue` when the field HAD an initial
|
|
152
|
+
// value (`enhancedOnChange`'s `typeof initial !== 'undefined'`),
|
|
153
|
+
// which is why its preset (collection-presets.ts) seeds `allLabel`
|
|
154
|
+
// and why the sentinel is a word an author can also type. A block
|
|
155
|
+
// that never carried the prop has an already-empty box and nothing
|
|
156
|
+
// to clear.
|
|
157
|
+
clearedValue: Aglyn.COLLECTION_ALL_PILL_NONE
|
|
158
|
+
}
|
|
159
|
+
]
|
|
160
|
+
};
|
|
161
|
+
export { CollectionCategories };
|
|
162
|
+
|
|
163
|
+
//# sourceMappingURL=collection-categories.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/components/collection-categories.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 { mdiTagMultipleOutline } 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 { forwardRef, useContext } from 'react'\nimport { BUNDLE_ID } from '../constants/bundle-common'\n\n// Persisted component id (AGL-551/582); the compose pipeline references it\n// through the @aglyn/aglyn constant. Never rename.\nexport const CATEGORIES_ID: Aglyn.ComponentId =\n Aglyn.COLLECTION_CATEGORIES_COMPONENT_ID\n\nexport interface CollectionCategoriesProps extends StackProps {\n /**\n * Collection whose taxonomy renders (compose-time). Blank = the collection\n * routed by the current URL on list-template screens.\n */\n collectionSlug?: string\n /**\n * Label for the unfiltered pill (default \"All\"). Clearing the field\n * persists `Aglyn.COLLECTION_ALL_PILL_NONE`, which omits the pill —\n * `''` cannot be stored at all (AGL-1336).\n */\n allLabel?: string\n /**\n * Server-stamped pill links (`expandCollectionCategories`); never set by\n * hand — the tenant builds them from the collection's categories and the\n * routed category.\n */\n items?: Aglyn.CollectionCategoryLink[]\n}\n\n/** Pill look, in palette tokens so it follows the site theme in both modes. */\nconst pillSx = (active: boolean) => ({\n px: 1.75,\n py: 0.75,\n borderRadius: 999,\n border: '1px solid',\n borderColor: active ? 'primary.main' : 'divider',\n bgcolor: active ? 'primary.main' : 'transparent',\n color: active ? 'primary.contrastText' : 'text.secondary',\n fontSize: 14,\n lineHeight: 1.2,\n whiteSpace: 'nowrap',\n '&:hover': {\n borderColor: active ? 'primary.main' : 'text.primary',\n color: active ? 'primary.contrastText' : 'text.primary',\n },\n})\n\n/**\n * The category filter row for a collection listing (AGL-1321): \"All\" plus one\n * pill per category, each a REAL anchor to `/{collection}/category/{slug}`.\n *\n * Anchors, not click handlers, and that is the whole design. A JS-only toggle\n * would be invisible to crawlers, unopenable in a new tab, unlinkable, and\n * unreachable without hydration — and it could not exist anyway, since the\n * filter is resolved server-side before the page is composed. The pill the\n * current URL selected carries `aria-current=\"page\"`, stamped on the server so\n * it is in the HTML rather than derived after hydration.\n */\nconst CollectionCategories = forwardRef<\n HTMLDivElement,\n CollectionCategoriesProps\n>((props, ref) => {\n // `collectionSlug`/`allLabel` are compose-time: the tenant resolves them\n // while stamping `items`; strip so they never hit the DOM.\n const { collectionSlug, allLabel, items, ...rest } = props\n // Node styles ride the renderer-merged sx; recompose (stack.ts pattern).\n const nodeSx = Array.isArray(props['sx']) ? props['sx'] : [props['sx']]\n const { suppressNavigation } = useContext(Aglyn.ScreenLinkContext)\n if (!items?.length) {\n if (!suppressNavigation) return <Box ref={ref} {...rest} />\n return (\n <Box\n ref={ref}\n {...rest}\n sx={[\n {\n p: 2,\n border: '1px dashed',\n borderColor: 'divider',\n color: 'text.secondary',\n fontSize: 12,\n fontFamily: 'system-ui, sans-serif',\n },\n ...nodeSx,\n ]}\n >\n {'Category pills — All + one pill per collection category render here'}\n </Box>\n )\n }\n return (\n <MuiStack\n ref={ref}\n direction=\"row\"\n spacing={1}\n {...rest}\n // MERGE, never replace (AGL-1450) — see collection-entry-meta.tsx.\n sx={[{ flexWrap: 'wrap', rowGap: 1 }, ...nodeSx]}\n >\n {items.map((item) =>\n // Editing surfaces render the pill look without an href, so a click\n // in the besigner never navigates the canvas away.\n suppressNavigation ? (\n <Box key={item.href} sx={pillSx(item.active)}>\n {item.label}\n </Box>\n ) : (\n <AppLink\n key={item.href}\n href={item.href}\n underline=\"none\"\n aria-current={item.active ? 'page' : undefined}\n sx={pillSx(item.active)}\n >\n {item.label}\n </AppLink>\n ),\n )}\n </MuiStack>\n )\n})\nCollectionCategories.displayName = 'AglynCollectionCategories'\n\nexport const collectionCategoriesSchema: Aglyn.ComponentSchema<CollectionCategoriesProps> =\n {\n $id: CATEGORIES_ID,\n pluginId: BUNDLE_ID,\n displayName: 'Category Pills',\n description: 'A pill per collection category, each filtering the listing.',\n category: Aglyn.ComponentCategory.NAVIGATION,\n icon: { path: mdiTagMultipleOutline.path, sx: { color: 'secondary.main' } },\n flags: { selfClosing: Aglyn.FEATURE_FLAG.ENABLED },\n attributes: [\n {\n name: 'collectionSlug',\n label: 'Collection slug',\n description:\n 'Content collection whose categories render as pills (e.g. ' +\n '\"blog\"). Leave blank on a list-template screen to use the ' +\n 'collection from the URL.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n },\n {\n name: 'allLabel',\n label: 'All label',\n description:\n 'Label for the unfiltered pill, which links to the collection ' +\n 'root (default \"All\"). Clear the box to omit that pill — it then ' +\n 'reads \"none\", which is what makes the omission stick. Typing ' +\n '\"none\" does the same thing.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n // Without this the emptied field persists NOTHING (AGL-1336): ddf\n // maps an emptied value to `clearedValue`, final-form's parse turns\n // `''` into `undefined`, and the missing key takes the runtime\n // default — so \"clear it to omit that pill\" was undoable by\n // clicking. Same shape as FIELD_COLOR_ALT1's `'default'` (AGL-1191):\n // a value that means something has to BE something.\n //\n // ddf only substitutes `clearedValue` when the field HAD an initial\n // value (`enhancedOnChange`'s `typeof initial !== 'undefined'`),\n // which is why its preset (collection-presets.ts) seeds `allLabel`\n // and why the sentinel is a word an author can also type. A block\n // that never carried the prop has an already-empty box and nothing\n // to clear.\n clearedValue: Aglyn.COLLECTION_ALL_PILL_NONE,\n },\n ],\n }\n\nexport { CollectionCategories }\n"],"names":["Aglyn","mdiTagMultipleOutline","AppLink","Box","MuiStack","forwardRef","useContext","BUNDLE_ID","CATEGORIES_ID","COLLECTION_CATEGORIES_COMPONENT_ID","pillSx","active","px","py","borderRadius","border","borderColor","bgcolor","color","fontSize","lineHeight","whiteSpace","CollectionCategories","props","ref","collectionSlug","allLabel","items","rest","nodeSx","Array","isArray","suppressNavigation","ScreenLinkContext","length","sx","p","fontFamily","direction","spacing","flexWrap","rowGap","map","item","label","href","underline","aria-current","undefined","displayName","collectionCategoriesSchema","$id","pluginId","description","category","ComponentCategory","NAVIGATION","icon","path","flags","selfClosing","FEATURE_FLAG","ENABLED","attributes","name","component","FieldComponentType","TEXT_FIELD","clearedValue","COLLECTION_ALL_PILL_NONE"],"mappings":"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"}
|
|
@@ -0,0 +1,104 @@
|
|
|
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
|
+
/**
|
|
18
|
+
* What the collection elements share (AGL-3401): the sample values the entry
|
|
19
|
+
* blocks preview with on editing surfaces, and the guards on an author href.
|
|
20
|
+
*
|
|
21
|
+
* The nine elements were one module, and the element tier loaded all of them
|
|
22
|
+
* — 68 KB with the fuzzy matcher — for a page placing any one. Each is its
|
|
23
|
+
* own module now, so a page downloads the ones it places. What two of them
|
|
24
|
+
* need lives here, or, when it draws markup only some of them render, in
|
|
25
|
+
* `collection-search-box.tsx` (Entries, Search) and
|
|
26
|
+
* `collection-author-links.tsx` (Entry Author, Author Profile) — so that
|
|
27
|
+
* Entry Meta does not carry ten platform marks, nor Category Pills an input.
|
|
28
|
+
*
|
|
29
|
+
* Each element's persisted id is declared in its own module rather than here:
|
|
30
|
+
* this module is in every one of their chunks, and an id reads its constant
|
|
31
|
+
* from the module that defines it, so nine ids here were nine modules of
|
|
32
|
+
* `@aglyn/aglyn` in every chunk (AGL-3401).
|
|
33
|
+
*/
|
|
34
|
+
/** A still-unresolved `{{token}}` (no entry context on this render). */
|
|
35
|
+
export declare const UNRESOLVED_TOKEN: RegExp;
|
|
36
|
+
/**
|
|
37
|
+
* The instant the sample cards are dated. A FIXED one, never `Date.now()`:
|
|
38
|
+
* the canvas has to render the same bytes every time it opens, and this is
|
|
39
|
+
* the date the Date-format labels use as their worked example — so the
|
|
40
|
+
* dropdown and the cards it previews agree word for word.
|
|
41
|
+
*/
|
|
42
|
+
export declare const RELATED_SAMPLE_PUBLISHED_AT: {
|
|
43
|
+
seconds: number;
|
|
44
|
+
};
|
|
45
|
+
/** Category chip text for the sample cards; names the field, not a taxonomy. */
|
|
46
|
+
export declare const RELATED_SAMPLE_CATEGORY = "Category";
|
|
47
|
+
/**
|
|
48
|
+
* THE SAMPLE VALUES THE ENTRY BLOCKS PREVIEW WITH (AGL-2486).
|
|
49
|
+
*
|
|
50
|
+
* Entry Meta and Entry Author resolve FROM the routed entry, and a besigner
|
|
51
|
+
* canvas has no routed entry — so both drew a one-line dashed strip and an
|
|
52
|
+
* author styling a byline or an author card was styling something they could
|
|
53
|
+
* not see. Related Posts had the same gap and was answered the same way: the
|
|
54
|
+
* block's REAL markup, at the author's own settings, on editing surfaces
|
|
55
|
+
* only.
|
|
56
|
+
*
|
|
57
|
+
* These two need no "this is a sample" notice the way the related CARDS do.
|
|
58
|
+
* A card carries a title, a cover and a category, which is what a real post
|
|
59
|
+
* looks like; a byline reading `Sample author` says what it is in the words
|
|
60
|
+
* themselves, and a notice above a single line of caption text would be
|
|
61
|
+
* taller than the thing it labels.
|
|
62
|
+
*
|
|
63
|
+
* The date is a FIXED instant, never `Date.now()`: the canvas has to render
|
|
64
|
+
* the same bytes every time it opens, and it is the same instant the related
|
|
65
|
+
* sample uses, so two blocks on one template never disagree about what day
|
|
66
|
+
* their example is.
|
|
67
|
+
*/
|
|
68
|
+
export declare const ENTRY_SAMPLE_PUBLISHED_AT: {
|
|
69
|
+
seconds: number;
|
|
70
|
+
};
|
|
71
|
+
/** Byline name for the samples; names the field rather than a person. */
|
|
72
|
+
export declare const ENTRY_SAMPLE_AUTHOR = "Sample author";
|
|
73
|
+
/** Category text for the samples; names the field, not a taxonomy. */
|
|
74
|
+
export declare const ENTRY_SAMPLE_CATEGORY = "Category";
|
|
75
|
+
/** Two chips, so the row previews its own wrapping and gap. */
|
|
76
|
+
export declare const ENTRY_SAMPLE_TAGS = "first tag, second tag";
|
|
77
|
+
/** Bio line for the author-card sample; one sentence, as a real one is. */
|
|
78
|
+
export declare const ENTRY_SAMPLE_BIO = "The bio from this author\u2019s record reads here, in a line or two.";
|
|
79
|
+
/**
|
|
80
|
+
* The portrait STAND-IN, for a sample that has no image to resolve.
|
|
81
|
+
*
|
|
82
|
+
* A neutral plate rather than nothing, and for the reason the related sample
|
|
83
|
+
* draws its cover slot: on an entry template the portrait arrives from the
|
|
84
|
+
* author record at render, so the slot is exactly what the author is sizing
|
|
85
|
+
* and spacing. `aria-hidden` because it depicts nothing.
|
|
86
|
+
*/
|
|
87
|
+
export declare const samplePortraitSx: (size: number) => {
|
|
88
|
+
width: number;
|
|
89
|
+
height: number;
|
|
90
|
+
flexShrink: number;
|
|
91
|
+
borderRadius: string;
|
|
92
|
+
backgroundColor: string;
|
|
93
|
+
};
|
|
94
|
+
/** Unresolved tokens render empty on the site, literal in the besigner. */
|
|
95
|
+
export declare const metaValue: (value: string | undefined, suppressNavigation: boolean | undefined) => string;
|
|
96
|
+
/**
|
|
97
|
+
* What the byline may link to — an absolute `https:` page, or a route on this
|
|
98
|
+
* site. The Social Links block guards its hrefs the same way and for the same
|
|
99
|
+
* reason: the value comes from a stored record, so `javascript:` and friends
|
|
100
|
+
* have to be unreachable rather than merely unlikely.
|
|
101
|
+
*/
|
|
102
|
+
export declare const SAFE_AUTHOR_HREF: RegExp;
|
|
103
|
+
/** An off-site author page opens in a new tab; a route on this site does not. */
|
|
104
|
+
export declare const EXTERNAL_AUTHOR_HREF: RegExp;
|
|
@@ -0,0 +1,95 @@
|
|
|
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
|
+
* What the collection elements share (AGL-3401): the sample values the entry
|
|
18
|
+
* blocks preview with on editing surfaces, and the guards on an author href.
|
|
19
|
+
*
|
|
20
|
+
* The nine elements were one module, and the element tier loaded all of them
|
|
21
|
+
* — 68 KB with the fuzzy matcher — for a page placing any one. Each is its
|
|
22
|
+
* own module now, so a page downloads the ones it places. What two of them
|
|
23
|
+
* need lives here, or, when it draws markup only some of them render, in
|
|
24
|
+
* `collection-search-box.tsx` (Entries, Search) and
|
|
25
|
+
* `collection-author-links.tsx` (Entry Author, Author Profile) — so that
|
|
26
|
+
* Entry Meta does not carry ten platform marks, nor Category Pills an input.
|
|
27
|
+
*
|
|
28
|
+
* Each element's persisted id is declared in its own module rather than here:
|
|
29
|
+
* this module is in every one of their chunks, and an id reads its constant
|
|
30
|
+
* from the module that defines it, so nine ids here were nine modules of
|
|
31
|
+
* `@aglyn/aglyn` in every chunk (AGL-3401).
|
|
32
|
+
*/ /** A still-unresolved `{{token}}` (no entry context on this render). */ export const UNRESOLVED_TOKEN = /^\{\{[^}]+\}\}$/;
|
|
33
|
+
/**
|
|
34
|
+
* The instant the sample cards are dated. A FIXED one, never `Date.now()`:
|
|
35
|
+
* the canvas has to render the same bytes every time it opens, and this is
|
|
36
|
+
* the date the Date-format labels use as their worked example — so the
|
|
37
|
+
* dropdown and the cards it previews agree word for word.
|
|
38
|
+
*/ export const RELATED_SAMPLE_PUBLISHED_AT = {
|
|
39
|
+
seconds: Date.UTC(2026, 7, 9) / 1000
|
|
40
|
+
};
|
|
41
|
+
/** Category chip text for the sample cards; names the field, not a taxonomy. */ export const RELATED_SAMPLE_CATEGORY = 'Category';
|
|
42
|
+
/**
|
|
43
|
+
* THE SAMPLE VALUES THE ENTRY BLOCKS PREVIEW WITH (AGL-2486).
|
|
44
|
+
*
|
|
45
|
+
* Entry Meta and Entry Author resolve FROM the routed entry, and a besigner
|
|
46
|
+
* canvas has no routed entry — so both drew a one-line dashed strip and an
|
|
47
|
+
* author styling a byline or an author card was styling something they could
|
|
48
|
+
* not see. Related Posts had the same gap and was answered the same way: the
|
|
49
|
+
* block's REAL markup, at the author's own settings, on editing surfaces
|
|
50
|
+
* only.
|
|
51
|
+
*
|
|
52
|
+
* These two need no "this is a sample" notice the way the related CARDS do.
|
|
53
|
+
* A card carries a title, a cover and a category, which is what a real post
|
|
54
|
+
* looks like; a byline reading `Sample author` says what it is in the words
|
|
55
|
+
* themselves, and a notice above a single line of caption text would be
|
|
56
|
+
* taller than the thing it labels.
|
|
57
|
+
*
|
|
58
|
+
* The date is a FIXED instant, never `Date.now()`: the canvas has to render
|
|
59
|
+
* the same bytes every time it opens, and it is the same instant the related
|
|
60
|
+
* sample uses, so two blocks on one template never disagree about what day
|
|
61
|
+
* their example is.
|
|
62
|
+
*/ export const ENTRY_SAMPLE_PUBLISHED_AT = RELATED_SAMPLE_PUBLISHED_AT;
|
|
63
|
+
/** Byline name for the samples; names the field rather than a person. */ export const ENTRY_SAMPLE_AUTHOR = 'Sample author';
|
|
64
|
+
/** Category text for the samples; names the field, not a taxonomy. */ export const ENTRY_SAMPLE_CATEGORY = RELATED_SAMPLE_CATEGORY;
|
|
65
|
+
/** Two chips, so the row previews its own wrapping and gap. */ export const ENTRY_SAMPLE_TAGS = 'first tag, second tag';
|
|
66
|
+
/** Bio line for the author-card sample; one sentence, as a real one is. */ export const ENTRY_SAMPLE_BIO = 'The bio from this author’s record reads here, in a line or two.';
|
|
67
|
+
/**
|
|
68
|
+
* The portrait STAND-IN, for a sample that has no image to resolve.
|
|
69
|
+
*
|
|
70
|
+
* A neutral plate rather than nothing, and for the reason the related sample
|
|
71
|
+
* draws its cover slot: on an entry template the portrait arrives from the
|
|
72
|
+
* author record at render, so the slot is exactly what the author is sizing
|
|
73
|
+
* and spacing. `aria-hidden` because it depicts nothing.
|
|
74
|
+
*/ export const samplePortraitSx = (size)=>({
|
|
75
|
+
width: size,
|
|
76
|
+
height: size,
|
|
77
|
+
flexShrink: 0,
|
|
78
|
+
borderRadius: '50%',
|
|
79
|
+
backgroundColor: 'action.hover'
|
|
80
|
+
});
|
|
81
|
+
/** Unresolved tokens render empty on the site, literal in the besigner. */ export const metaValue = (value, suppressNavigation)=>{
|
|
82
|
+
const trimmed = (value != null ? value : '').trim();
|
|
83
|
+
if (!trimmed) return '';
|
|
84
|
+
if (UNRESOLVED_TOKEN.test(trimmed) && !suppressNavigation) return '';
|
|
85
|
+
return trimmed;
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* What the byline may link to — an absolute `https:` page, or a route on this
|
|
89
|
+
* site. The Social Links block guards its hrefs the same way and for the same
|
|
90
|
+
* reason: the value comes from a stored record, so `javascript:` and friends
|
|
91
|
+
* have to be unreachable rather than merely unlikely.
|
|
92
|
+
*/ export const SAFE_AUTHOR_HREF = /^(https:\/\/|\/(?!\/))/i;
|
|
93
|
+
/** An off-site author page opens in a new tab; a route on this site does not. */ export const EXTERNAL_AUTHOR_HREF = /^https:\/\//i;
|
|
94
|
+
|
|
95
|
+
//# sourceMappingURL=collection-common.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/components/collection-common.ts"],"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\n/**\n * What the collection elements share (AGL-3401): the sample values the entry\n * blocks preview with on editing surfaces, and the guards on an author href.\n *\n * The nine elements were one module, and the element tier loaded all of them\n * — 68 KB with the fuzzy matcher — for a page placing any one. Each is its\n * own module now, so a page downloads the ones it places. What two of them\n * need lives here, or, when it draws markup only some of them render, in\n * `collection-search-box.tsx` (Entries, Search) and\n * `collection-author-links.tsx` (Entry Author, Author Profile) — so that\n * Entry Meta does not carry ten platform marks, nor Category Pills an input.\n *\n * Each element's persisted id is declared in its own module rather than here:\n * this module is in every one of their chunks, and an id reads its constant\n * from the module that defines it, so nine ids here were nine modules of\n * `@aglyn/aglyn` in every chunk (AGL-3401).\n */\n\n/** A still-unresolved `{{token}}` (no entry context on this render). */\nexport const UNRESOLVED_TOKEN = /^\\{\\{[^}]+\\}\\}$/\n\n/**\n * The instant the sample cards are dated. A FIXED one, never `Date.now()`:\n * the canvas has to render the same bytes every time it opens, and this is\n * the date the Date-format labels use as their worked example — so the\n * dropdown and the cards it previews agree word for word.\n */\nexport const RELATED_SAMPLE_PUBLISHED_AT = { seconds: Date.UTC(2026, 7, 9) / 1000 }\n\n/** Category chip text for the sample cards; names the field, not a taxonomy. */\nexport const RELATED_SAMPLE_CATEGORY = 'Category'\n\n/**\n * THE SAMPLE VALUES THE ENTRY BLOCKS PREVIEW WITH (AGL-2486).\n *\n * Entry Meta and Entry Author resolve FROM the routed entry, and a besigner\n * canvas has no routed entry — so both drew a one-line dashed strip and an\n * author styling a byline or an author card was styling something they could\n * not see. Related Posts had the same gap and was answered the same way: the\n * block's REAL markup, at the author's own settings, on editing surfaces\n * only.\n *\n * These two need no \"this is a sample\" notice the way the related CARDS do.\n * A card carries a title, a cover and a category, which is what a real post\n * looks like; a byline reading `Sample author` says what it is in the words\n * themselves, and a notice above a single line of caption text would be\n * taller than the thing it labels.\n *\n * The date is a FIXED instant, never `Date.now()`: the canvas has to render\n * the same bytes every time it opens, and it is the same instant the related\n * sample uses, so two blocks on one template never disagree about what day\n * their example is.\n */\nexport const ENTRY_SAMPLE_PUBLISHED_AT = RELATED_SAMPLE_PUBLISHED_AT\n\n/** Byline name for the samples; names the field rather than a person. */\nexport const ENTRY_SAMPLE_AUTHOR = 'Sample author'\n\n/** Category text for the samples; names the field, not a taxonomy. */\nexport const ENTRY_SAMPLE_CATEGORY = RELATED_SAMPLE_CATEGORY\n\n/** Two chips, so the row previews its own wrapping and gap. */\nexport const ENTRY_SAMPLE_TAGS = 'first tag, second tag'\n\n/** Bio line for the author-card sample; one sentence, as a real one is. */\nexport const ENTRY_SAMPLE_BIO =\n 'The bio from this author’s record reads here, in a line or two.'\n\n/**\n * The portrait STAND-IN, for a sample that has no image to resolve.\n *\n * A neutral plate rather than nothing, and for the reason the related sample\n * draws its cover slot: on an entry template the portrait arrives from the\n * author record at render, so the slot is exactly what the author is sizing\n * and spacing. `aria-hidden` because it depicts nothing.\n */\nexport const samplePortraitSx = (size: number) => ({\n width: size,\n height: size,\n flexShrink: 0,\n borderRadius: '50%',\n backgroundColor: 'action.hover',\n})\n\n/** Unresolved tokens render empty on the site, literal in the besigner. */\nexport const metaValue = (\n value: string | undefined,\n suppressNavigation: boolean | undefined,\n): string => {\n const trimmed = (value ?? '').trim()\n if (!trimmed) return ''\n if (UNRESOLVED_TOKEN.test(trimmed) && !suppressNavigation) return ''\n return trimmed\n}\n\n/**\n * What the byline may link to — an absolute `https:` page, or a route on this\n * site. The Social Links block guards its hrefs the same way and for the same\n * reason: the value comes from a stored record, so `javascript:` and friends\n * have to be unreachable rather than merely unlikely.\n */\nexport const SAFE_AUTHOR_HREF = /^(https:\\/\\/|\\/(?!\\/))/i\n\n/** An off-site author page opens in a new tab; a route on this site does not. */\nexport const EXTERNAL_AUTHOR_HREF = /^https:\\/\\//i\n"],"names":["UNRESOLVED_TOKEN","RELATED_SAMPLE_PUBLISHED_AT","seconds","Date","UTC","RELATED_SAMPLE_CATEGORY","ENTRY_SAMPLE_PUBLISHED_AT","ENTRY_SAMPLE_AUTHOR","ENTRY_SAMPLE_CATEGORY","ENTRY_SAMPLE_TAGS","ENTRY_SAMPLE_BIO","samplePortraitSx","size","width","height","flexShrink","borderRadius","backgroundColor","metaValue","value","suppressNavigation","trimmed","trim","test","SAFE_AUTHOR_HREF","EXTERNAL_AUTHOR_HREF"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;;;;;;;;;;;;;;CAgBC,GAED,sEAAsE,GACtE,OAAO,MAAMA,mBAAmB,kBAAiB;AAEjD;;;;;CAKC,GACD,OAAO,MAAMC,8BAA8B;IAAEC,SAASC,KAAKC,GAAG,CAAC,MAAM,GAAG,KAAK;AAAK,EAAC;AAEnF,8EAA8E,GAC9E,OAAO,MAAMC,0BAA0B,WAAU;AAEjD;;;;;;;;;;;;;;;;;;;;CAoBC,GACD,OAAO,MAAMC,4BAA4BL,4BAA2B;AAEpE,uEAAuE,GACvE,OAAO,MAAMM,sBAAsB,gBAAe;AAElD,oEAAoE,GACpE,OAAO,MAAMC,wBAAwBH,wBAAuB;AAE5D,6DAA6D,GAC7D,OAAO,MAAMI,oBAAoB,wBAAuB;AAExD,yEAAyE,GACzE,OAAO,MAAMC,mBACX,kEAAiE;AAEnE;;;;;;;CAOC,GACD,OAAO,MAAMC,mBAAmB,CAACC,OAAkB,CAAA;QACjDC,OAAOD;QACPE,QAAQF;QACRG,YAAY;QACZC,cAAc;QACdC,iBAAiB;IACnB,CAAA,EAAE;AAEF,yEAAyE,GACzE,OAAO,MAAMC,YAAY,CACvBC,OACAC;IAEA,MAAMC,UAAU,CAACF,gBAAAA,QAAS,IAAIG,IAAI;IAClC,IAAI,CAACD,SAAS,OAAO;IACrB,IAAIrB,iBAAiBuB,IAAI,CAACF,YAAY,CAACD,oBAAoB,OAAO;IAClE,OAAOC;AACT,EAAC;AAED;;;;;CAKC,GACD,OAAO,MAAMG,mBAAmB,0BAAyB;AAEzD,+EAA+E,GAC/E,OAAO,MAAMC,uBAAuB,eAAc"}
|
|
@@ -0,0 +1,137 @@
|
|
|
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
|
+
import { type StackProps } from '@mui/material/Stack';
|
|
19
|
+
export declare const ENTRIES_ID: Aglyn.ComponentId;
|
|
20
|
+
export interface CollectionEntriesProps extends StackProps {
|
|
21
|
+
/**
|
|
22
|
+
* Collection to repeat over (compose-time, AGL-551). Blank = the
|
|
23
|
+
* collection routed by the current URL on list-template screens.
|
|
24
|
+
*/
|
|
25
|
+
collectionSlug?: string;
|
|
26
|
+
/** Maximum entries rendered (compose-time; blank = all, capped at 100). */
|
|
27
|
+
entriesLimit?: number | string;
|
|
28
|
+
/**
|
|
29
|
+
* Only entries in this category repeat (compose-time, AGL-582).
|
|
30
|
+
* Matches the collection's category by stable id or display name.
|
|
31
|
+
*/
|
|
32
|
+
filterCategory?: string;
|
|
33
|
+
/** Only entries carrying this tag repeat (compose-time, AGL-582). */
|
|
34
|
+
filterTag?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Entries per page (compose-time, AGL-620). When set, the block renders one
|
|
37
|
+
* page window instead of the top `entriesLimit`; the built-in collection
|
|
38
|
+
* list uses this with the `page` from `/{collection}/page/{n}`.
|
|
39
|
+
*/
|
|
40
|
+
perPage?: number | string;
|
|
41
|
+
/** 1-based page for `perPage` (compose-time, AGL-620). */
|
|
42
|
+
page?: number | string;
|
|
43
|
+
/**
|
|
44
|
+
* Render this block only on page 1 of the routed listing (compose-time,
|
|
45
|
+
* AGL-1871). For a LEAD card — a block with no `perPage`, showing the top
|
|
46
|
+
* of the set — every `/{collection}/page/{n}` past the first otherwise
|
|
47
|
+
* repeats the identical entry above a page of different ones.
|
|
48
|
+
*
|
|
49
|
+
* Opt-in and default off: a block that legitimately belongs on every page
|
|
50
|
+
* of a listing (a "popular posts" rail) has exactly the same shape.
|
|
51
|
+
*/
|
|
52
|
+
firstPageOnly?: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Show a search box that filters the RENDERED entries by title/excerpt as
|
|
55
|
+
* the reader types (AGL-1516, Figma 494:1220). Opt-in and default off, so
|
|
56
|
+
* every existing instance renders exactly as before.
|
|
57
|
+
*
|
|
58
|
+
* Client-evaluated over the entries this block already holds — the page is
|
|
59
|
+
* ISR-cached, so a keystroke never costs a Firestore read. That set is
|
|
60
|
+
* whatever the expansion left the block holding, which paging, an
|
|
61
|
+
* `entriesLimit` or the 100-entry cap can each cut down. A truncated block
|
|
62
|
+
* says so under its results either way — on a miss and on a hit
|
|
63
|
+
* (AGL-1516, AGL-2569) — rather than pretending global search.
|
|
64
|
+
*/
|
|
65
|
+
search?: boolean;
|
|
66
|
+
/**
|
|
67
|
+
* What the search box DOES with a query (AGL-1525, Figma 496:1218).
|
|
68
|
+
*
|
|
69
|
+
* - `filter` (default, and the reading of an absent value) — hides the
|
|
70
|
+
* non-matching cards in place. What AGL-1516 shipped.
|
|
71
|
+
* - `suggest` — the card grid stays exactly as it was and a floating panel
|
|
72
|
+
* of matching entries opens under the field, ending in a link to the
|
|
73
|
+
* site-wide results page. The frame's toolbar behaviour: a reader
|
|
74
|
+
* skimming the list is not made to lose it to a typo.
|
|
75
|
+
*/
|
|
76
|
+
searchMode?: CollectionSearchMode;
|
|
77
|
+
/** Hint text inside the search box (blank = "Search posts…"). */
|
|
78
|
+
searchPlaceholder?: string;
|
|
79
|
+
/**
|
|
80
|
+
* Server-stamped matchable text per rendered entry
|
|
81
|
+
* (`expandCollectionEntries`, AGL-1516); never set by hand.
|
|
82
|
+
*/
|
|
83
|
+
searchIndex?: Aglyn.CollectionEntrySearchItem[];
|
|
84
|
+
/**
|
|
85
|
+
* How many entries `searchIndex` was drawn from — server-stamped by
|
|
86
|
+
* `expandCollectionEntries` alongside it (AGL-1516), never set by hand.
|
|
87
|
+
* `searchIndex.length < searchTotal` is the only honest test of whether
|
|
88
|
+
* this block holds the whole set; `perPage` is not, because
|
|
89
|
+
* `entriesLimit` and the 100-entry cap truncate too.
|
|
90
|
+
*/
|
|
91
|
+
searchTotal?: number;
|
|
92
|
+
/**
|
|
93
|
+
* Whether the read behind `searchTotal` reached its own bound — server-
|
|
94
|
+
* stamped beside it (AGL-1516), never set by hand.
|
|
95
|
+
*
|
|
96
|
+
* `searchTotal` is a count of what the server SAW, and the collection read
|
|
97
|
+
* is limited. Without this flag a block holding 100 of 400 posts satisfies
|
|
98
|
+
* `searchIndex.length === searchTotal` and renders the one empty state that
|
|
99
|
+
* claims to have looked everywhere.
|
|
100
|
+
*/
|
|
101
|
+
searchCapped?: boolean;
|
|
102
|
+
}
|
|
103
|
+
/** The two things the toolbar search box can do (AGL-1516/AGL-1525). */
|
|
104
|
+
export type CollectionSearchMode = 'filter' | 'suggest';
|
|
105
|
+
/**
|
|
106
|
+
* Author-facing choices for {@link CollectionEntriesProps.searchMode}.
|
|
107
|
+
*
|
|
108
|
+
* Both values are truthy on purpose (AGL-1453): `''` cannot survive a save,
|
|
109
|
+
* so an author who tried the other mode would have no route back. "Filter"
|
|
110
|
+
* carries the absent-value reading, which is what every block published
|
|
111
|
+
* before AGL-1525 has.
|
|
112
|
+
*/
|
|
113
|
+
export declare const COLLECTION_SEARCH_MODE_OPTIONS: ReadonlyArray<{
|
|
114
|
+
value: CollectionSearchMode;
|
|
115
|
+
label: string;
|
|
116
|
+
}>;
|
|
117
|
+
/**
|
|
118
|
+
* Repeats its children once per published entry of a content collection
|
|
119
|
+
* (AGL-551) — the collections sibling of the dataset repeatable. The tenant
|
|
120
|
+
* expands it at compose time with `{{entry.*}}` tokens; in the besigner the
|
|
121
|
+
* template renders once with literal tokens, matching the repeatable UX.
|
|
122
|
+
*
|
|
123
|
+
* Search (AGL-1516): with `search` on, a toolbar search box filters the
|
|
124
|
+
* rendered entry clones client-side against the server-stamped
|
|
125
|
+
* `searchIndex` — fuzzy, via the same Fuse the icon picker uses. The clones
|
|
126
|
+
* arrive as `children` in stamp order, one group of template roots per
|
|
127
|
+
* entry, so group N of the children IS entry N of the index. Matches keep
|
|
128
|
+
* the list's own order rather than Fuse's score order: a blog list is
|
|
129
|
+
* chronological, and search narrows it, it does not reshuffle it. In the
|
|
130
|
+
* besigner the field renders as an inert affordance (the template renders
|
|
131
|
+
* once with literal tokens and there is no index to search), matching how
|
|
132
|
+
* Category Pills go inert on editing surfaces.
|
|
133
|
+
*/
|
|
134
|
+
declare const CollectionEntries: import("react").ForwardRefExoticComponent<Omit<CollectionEntriesProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
|
|
135
|
+
export declare const collectionEntriesSchema: Aglyn.ComponentSchema<CollectionEntriesProps>;
|
|
136
|
+
export { CollectionEntries };
|
|
137
|
+
export { collectionPresets } from './collection-presets';
|