@aglyn/plugins-mui 1.0.0-beta.215 → 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.
Files changed (57) hide show
  1. package/package.json +7 -7
  2. package/src/lib/components/collection-author-links.d.ts +41 -0
  3. package/src/lib/components/collection-author-links.js +135 -0
  4. package/src/lib/components/collection-author-links.js.map +1 -0
  5. package/src/lib/components/collection-author-profile.d.ts +67 -0
  6. package/src/lib/components/collection-author-profile.js +269 -0
  7. package/src/lib/components/collection-author-profile.js.map +1 -0
  8. package/src/lib/components/collection-categories.d.ts +52 -0
  9. package/src/lib/components/collection-categories.js +163 -0
  10. package/src/lib/components/collection-categories.js.map +1 -0
  11. package/src/lib/components/collection-common.d.ts +104 -0
  12. package/src/lib/components/collection-common.js +95 -0
  13. package/src/lib/components/collection-common.js.map +1 -0
  14. package/src/lib/components/collection-entries.d.ts +137 -0
  15. package/src/lib/components/collection-entries.js +358 -0
  16. package/src/lib/components/collection-entries.js.map +1 -0
  17. package/src/lib/components/collection-entry-author.d.ts +81 -0
  18. package/src/lib/components/collection-entry-author.js +259 -0
  19. package/src/lib/components/collection-entry-author.js.map +1 -0
  20. package/src/lib/components/collection-entry-body.d.ts +44 -0
  21. package/src/lib/components/collection-entry-body.js +328 -0
  22. package/src/lib/components/collection-entry-body.js.map +1 -0
  23. package/src/lib/components/collection-entry-meta.d.ts +88 -0
  24. package/src/lib/components/collection-entry-meta.js +331 -0
  25. package/src/lib/components/collection-entry-meta.js.map +1 -0
  26. package/src/lib/components/collection-presets.d.ts +18 -0
  27. package/src/lib/components/collection-presets.js +328 -0
  28. package/src/lib/components/collection-presets.js.map +1 -0
  29. package/src/lib/components/collection-related.d.ts +101 -0
  30. package/src/lib/components/collection-related.js +536 -0
  31. package/src/lib/components/collection-related.js.map +1 -0
  32. package/src/lib/components/collection-search-box.d.ts +92 -0
  33. package/src/lib/components/collection-search-box.js +334 -0
  34. package/src/lib/components/collection-search-box.js.map +1 -0
  35. package/src/lib/components/collection-search-fuse.d.ts +28 -0
  36. package/src/lib/components/collection-search-fuse.js +28 -0
  37. package/src/lib/components/collection-search-fuse.js.map +1 -0
  38. package/src/lib/components/collection-search.d.ts +62 -0
  39. package/src/lib/components/collection-search.js +140 -0
  40. package/src/lib/components/collection-search.js.map +1 -0
  41. package/src/lib/components/collection-share.d.ts +31 -0
  42. package/src/lib/components/collection-share.js +154 -0
  43. package/src/lib/components/collection-share.js.map +1 -0
  44. package/src/lib/components/collection.d.ts +19 -497
  45. package/src/lib/components/collection.js +19 -2982
  46. package/src/lib/components/collection.js.map +1 -1
  47. package/src/lib/components/image-list.d.ts +2 -2
  48. package/src/lib/components/image-list.js +4 -6
  49. package/src/lib/components/image-list.js.map +1 -1
  50. package/src/lib/element-tier.d.ts +9 -1
  51. package/src/lib/element-tier.js +12 -1
  52. package/src/lib/element-tier.js.map +1 -1
  53. package/src/lib/plugin.js +20 -12
  54. package/src/lib/plugin.js.map +1 -1
  55. package/src/lib/utils/to-count.d.ts +25 -0
  56. package/src/lib/utils/to-count.js +30 -0
  57. 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';