@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.
- 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/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,140 @@
|
|
|
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 { mdiMagnify } from "@aglyn/shared-data-mdi";
|
|
21
|
+
import Box from "@mui/material/Box";
|
|
22
|
+
import MuiStack from "@mui/material/Stack";
|
|
23
|
+
import { forwardRef, useContext } from "react";
|
|
24
|
+
import { BUNDLE_ID } from "../constants/bundle-common.js";
|
|
25
|
+
import { SuggestSearchBox, useEntryFuse } from "./collection-search-box.js";
|
|
26
|
+
// Persisted component id (AGL-551/582); the compose pipeline references it
|
|
27
|
+
// through the @aglyn/aglyn constant. Never rename.
|
|
28
|
+
export const SEARCH_ID = Aglyn.COLLECTION_SEARCH_COMPONENT_ID;
|
|
29
|
+
/**
|
|
30
|
+
* A search box for a collection that lives where the author puts it
|
|
31
|
+
* (AGL-1516, Figma 494:1220).
|
|
32
|
+
*
|
|
33
|
+
* The entries block has had a search box since AGL-1516's first half, and it
|
|
34
|
+
* renders inside that block — first child of its own stack. The frame puts
|
|
35
|
+
* the field in the listing's TOOLBAR: category pills on the left, search and
|
|
36
|
+
* RSS on the right, one row. That was unbuildable, and unbuildable in both
|
|
37
|
+
* directions — a block's own child cannot be lifted out of it, and the pills
|
|
38
|
+
* cannot be moved in, because every child of an entries block is cloned once
|
|
39
|
+
* per entry. Three passes of authoring hit the same wall.
|
|
40
|
+
*
|
|
41
|
+
* So the field became its own block. It searches the collection the listing
|
|
42
|
+
* beside it is drawn from, and answers with the suggestion panel (496:1218)
|
|
43
|
+
* — the only behaviour a standalone box can honestly have, since it owns no
|
|
44
|
+
* cards to hide. Enter submits to the site-wide results page, so the box
|
|
45
|
+
* works with no JavaScript at all.
|
|
46
|
+
*
|
|
47
|
+
* Inert on editing surfaces, like Category Pills: the besigner has no index
|
|
48
|
+
* to search, and a field that answered there would be answering about
|
|
49
|
+
* nothing.
|
|
50
|
+
*/ const CollectionSearch = /*#__PURE__*/ forwardRef((props, ref)=>{
|
|
51
|
+
// Compose-time and search-only attributes: strip so they never hit the
|
|
52
|
+
// DOM.
|
|
53
|
+
const { collectionSlug, searchPlaceholder, searchIndex, searchTotal, searchCapped } = props, rest = _object_without_properties_loose(props, [
|
|
54
|
+
"collectionSlug",
|
|
55
|
+
"searchPlaceholder",
|
|
56
|
+
"searchIndex",
|
|
57
|
+
"searchTotal",
|
|
58
|
+
"searchCapped"
|
|
59
|
+
]);
|
|
60
|
+
// Node styles ride the renderer-merged sx; recompose (stack.ts pattern).
|
|
61
|
+
const nodeSx = Array.isArray(props['sx']) ? props['sx'] : [
|
|
62
|
+
props['sx']
|
|
63
|
+
];
|
|
64
|
+
const { suppressNavigation } = useContext(Aglyn.ScreenLinkContext);
|
|
65
|
+
const { fuzzy, requestFuzzy } = useEntryFuse(searchIndex);
|
|
66
|
+
if (!suppressNavigation && !(searchIndex == null ? void 0 : searchIndex.length)) {
|
|
67
|
+
// Nothing stamped on a live surface: an unknown collection, an empty
|
|
68
|
+
// one, or a page composed before this block existed. Renders NOTHING
|
|
69
|
+
// rather than a field that can only ever answer "no matches" — that
|
|
70
|
+
// answer would read as a fact about the reader's query instead of
|
|
71
|
+
// about the absent index behind it.
|
|
72
|
+
return /*#__PURE__*/ _jsx(Box, _extends({
|
|
73
|
+
ref: ref
|
|
74
|
+
}, rest));
|
|
75
|
+
}
|
|
76
|
+
return /*#__PURE__*/ _jsx(MuiStack, _extends({
|
|
77
|
+
ref: ref
|
|
78
|
+
}, rest, {
|
|
79
|
+
sx: [
|
|
80
|
+
{
|
|
81
|
+
alignItems: 'flex-end'
|
|
82
|
+
},
|
|
83
|
+
...nodeSx
|
|
84
|
+
],
|
|
85
|
+
children: /*#__PURE__*/ _jsx(SuggestSearchBox, _extends({
|
|
86
|
+
fuzzy: fuzzy,
|
|
87
|
+
requestFuzzy: requestFuzzy
|
|
88
|
+
}, searchIndex ? {
|
|
89
|
+
items: searchIndex
|
|
90
|
+
} : {}, searchPlaceholder === undefined ? {} : {
|
|
91
|
+
placeholder: searchPlaceholder
|
|
92
|
+
}, suppressNavigation ? {
|
|
93
|
+
inert: true
|
|
94
|
+
} : {}, {
|
|
95
|
+
// The honest miss for THIS box. It searched one bounded read of the
|
|
96
|
+
// collection — never "the collection", and on a category route not
|
|
97
|
+
// even the whole of it, because the source arrives filtered. So it
|
|
98
|
+
// reports the number it actually looked through, and says plainly
|
|
99
|
+
// when that number was a ceiling rather than a total.
|
|
100
|
+
emptyText: (text)=>{
|
|
101
|
+
var _ref, _ref1;
|
|
102
|
+
return searchCapped ? `No matches for “${text}” in the ${(_ref = searchIndex == null ? void 0 : searchIndex.length) != null ? _ref : 0} ` + 'entries searched here — the collection holds more, which ' + 'this box has not read.' : `No matches for “${text}” in the ${(_ref1 = searchIndex == null ? void 0 : searchIndex.length) != null ? _ref1 : 0} ` + 'entries searched here.';
|
|
103
|
+
}
|
|
104
|
+
}))
|
|
105
|
+
}));
|
|
106
|
+
});
|
|
107
|
+
CollectionSearch.displayName = 'AglynCollectionSearch';
|
|
108
|
+
export const collectionSearchSchema = {
|
|
109
|
+
$id: SEARCH_ID,
|
|
110
|
+
pluginId: BUNDLE_ID,
|
|
111
|
+
displayName: 'Collection Search',
|
|
112
|
+
description: 'A search box for a content collection, with a suggestions dropdown.',
|
|
113
|
+
category: Aglyn.ComponentCategory.NAVIGATION,
|
|
114
|
+
icon: {
|
|
115
|
+
path: mdiMagnify.path,
|
|
116
|
+
sx: {
|
|
117
|
+
color: 'secondary.main'
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
flags: {
|
|
121
|
+
selfClosing: Aglyn.FEATURE_FLAG.ENABLED
|
|
122
|
+
},
|
|
123
|
+
attributes: [
|
|
124
|
+
{
|
|
125
|
+
name: 'collectionSlug',
|
|
126
|
+
label: 'Collection slug',
|
|
127
|
+
description: 'Content collection this box searches (e.g. "blog"). Leave blank ' + 'on a list-template screen to use the collection from the URL.',
|
|
128
|
+
component: Aglyn.FieldComponentType.TEXT_FIELD
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
name: 'searchPlaceholder',
|
|
132
|
+
label: 'Search placeholder',
|
|
133
|
+
description: 'Hint text inside this box. Blank shows "Search posts…", which is ' + 'worth changing when the collection is not posts.',
|
|
134
|
+
component: Aglyn.FieldComponentType.TEXT_FIELD
|
|
135
|
+
}
|
|
136
|
+
]
|
|
137
|
+
};
|
|
138
|
+
export { CollectionSearch };
|
|
139
|
+
|
|
140
|
+
//# sourceMappingURL=collection-search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/components/collection-search.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 { mdiMagnify } from '@aglyn/shared-data-mdi'\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'\nimport { SuggestSearchBox, useEntryFuse } from './collection-search-box'\n\n// Persisted component id (AGL-551/582); the compose pipeline references it\n// through the @aglyn/aglyn constant. Never rename.\nexport const SEARCH_ID: Aglyn.ComponentId = Aglyn.COLLECTION_SEARCH_COMPONENT_ID\n\nexport interface CollectionSearchProps extends StackProps {\n /**\n * Collection whose entries this box searches (compose-time). Blank = the\n * collection routed by the current URL on list-template screens.\n */\n collectionSlug?: string\n /** Hint text inside the box (blank = \"Search posts…\"). */\n searchPlaceholder?: string\n /**\n * Server-stamped matchable text per entry (`expandCollectionSearch`);\n * never set by hand.\n */\n searchIndex?: Aglyn.CollectionEntrySearchItem[]\n /** How many entries the index was drawn from; never set by hand. */\n searchTotal?: number\n /** Whether that read reached its bound; never set by hand. */\n searchCapped?: boolean\n}\n\n/**\n * A search box for a collection that lives where the author puts it\n * (AGL-1516, Figma 494:1220).\n *\n * The entries block has had a search box since AGL-1516's first half, and it\n * renders inside that block — first child of its own stack. The frame puts\n * the field in the listing's TOOLBAR: category pills on the left, search and\n * RSS on the right, one row. That was unbuildable, and unbuildable in both\n * directions — a block's own child cannot be lifted out of it, and the pills\n * cannot be moved in, because every child of an entries block is cloned once\n * per entry. Three passes of authoring hit the same wall.\n *\n * So the field became its own block. It searches the collection the listing\n * beside it is drawn from, and answers with the suggestion panel (496:1218)\n * — the only behaviour a standalone box can honestly have, since it owns no\n * cards to hide. Enter submits to the site-wide results page, so the box\n * works with no JavaScript at all.\n *\n * Inert on editing surfaces, like Category Pills: the besigner has no index\n * to search, and a field that answered there would be answering about\n * nothing.\n */\nconst CollectionSearch = forwardRef<HTMLDivElement, CollectionSearchProps>(\n (props, ref) => {\n // Compose-time and search-only attributes: strip so they never hit the\n // DOM.\n const {\n collectionSlug,\n searchPlaceholder,\n searchIndex,\n searchTotal,\n searchCapped,\n ...rest\n } = 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 const { fuzzy, requestFuzzy } = useEntryFuse(searchIndex)\n if (!suppressNavigation && !searchIndex?.length) {\n // Nothing stamped on a live surface: an unknown collection, an empty\n // one, or a page composed before this block existed. Renders NOTHING\n // rather than a field that can only ever answer \"no matches\" — that\n // answer would read as a fact about the reader's query instead of\n // about the absent index behind it.\n return <Box ref={ref} {...rest} />\n }\n return (\n <MuiStack ref={ref} {...rest} sx={[{ alignItems: 'flex-end' }, ...nodeSx]}>\n <SuggestSearchBox\n fuzzy={fuzzy}\n requestFuzzy={requestFuzzy}\n {...(searchIndex ? { items: searchIndex } : {})}\n {...(searchPlaceholder === undefined\n ? {}\n : { placeholder: searchPlaceholder })}\n {...(suppressNavigation ? { inert: true } : {})}\n // The honest miss for THIS box. It searched one bounded read of the\n // collection — never \"the collection\", and on a category route not\n // even the whole of it, because the source arrives filtered. So it\n // reports the number it actually looked through, and says plainly\n // when that number was a ceiling rather than a total.\n emptyText={(text) =>\n searchCapped\n ? `No matches for “${text}” in the ${searchIndex?.length ?? 0} ` +\n 'entries searched here — the collection holds more, which ' +\n 'this box has not read.'\n : `No matches for “${text}” in the ${searchIndex?.length ?? 0} ` +\n 'entries searched here.'\n }\n />\n </MuiStack>\n )\n },\n)\nCollectionSearch.displayName = 'AglynCollectionSearch'\n\nexport const collectionSearchSchema: Aglyn.ComponentSchema<CollectionSearchProps> =\n {\n $id: SEARCH_ID,\n pluginId: BUNDLE_ID,\n displayName: 'Collection Search',\n description:\n 'A search box for a content collection, with a suggestions dropdown.',\n category: Aglyn.ComponentCategory.NAVIGATION,\n icon: { path: mdiMagnify.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 this box searches (e.g. \"blog\"). Leave blank ' +\n 'on a list-template screen to use the collection from the URL.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n },\n {\n name: 'searchPlaceholder',\n label: 'Search placeholder',\n description:\n 'Hint text inside this box. Blank shows \"Search posts…\", which is ' +\n 'worth changing when the collection is not posts.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n },\n // `searchIndex`, `searchTotal` and `searchCapped` are deliberately NOT\n // attributes: all three are server-stamped facts about a read, and an\n // author who could edit them could make the box lie about its own\n // reach.\n ],\n }\n\nexport { CollectionSearch }\n"],"names":["Aglyn","mdiMagnify","Box","MuiStack","forwardRef","useContext","BUNDLE_ID","SuggestSearchBox","useEntryFuse","SEARCH_ID","COLLECTION_SEARCH_COMPONENT_ID","CollectionSearch","props","ref","collectionSlug","searchPlaceholder","searchIndex","searchTotal","searchCapped","rest","nodeSx","Array","isArray","suppressNavigation","ScreenLinkContext","fuzzy","requestFuzzy","length","sx","alignItems","items","undefined","placeholder","inert","emptyText","text","displayName","collectionSearchSchema","$id","pluginId","description","category","ComponentCategory","NAVIGATION","icon","path","color","flags","selfClosing","FEATURE_FLAG","ENABLED","attributes","name","label","component","FieldComponentType","TEXT_FIELD"],"mappings":";;;AAAA;;;;;;;;;;;;;;;CAeC,GAED,YAAYA,WAAW,eAAc;AACrC,SAASC,UAAU,QAAQ,yBAAwB;AACnD,OAAOC,SAAS,oBAAmB;AACnC,OAAOC,cAAmC,sBAAqB;AAC/D,SAASC,UAAU,EAAEC,UAAU,QAAQ,QAAO;AAC9C,SAASC,SAAS,QAAQ,gCAA4B;AACtD,SAASC,gBAAgB,EAAEC,YAAY,QAAQ,6BAAyB;AAExE,2EAA2E;AAC3E,mDAAmD;AACnD,OAAO,MAAMC,YAA+BT,MAAMU,8BAA8B,CAAA;AAqBhF;;;;;;;;;;;;;;;;;;;;;CAqBC,GACD,MAAMC,iCAAmBP,WACvB,CAACQ,OAAOC;IACN,uEAAuE;IACvE,OAAO;IACP,MAAM,EACJC,cAAc,EACdC,iBAAiB,EACjBC,WAAW,EACXC,WAAW,EACXC,YAAY,EAEb,GAAGN,OADCO,wCACDP;;;;;;;IACJ,yEAAyE;IACzE,MAAMQ,SAASC,MAAMC,OAAO,CAACV,KAAK,CAAC,KAAK,IAAIA,KAAK,CAAC,KAAK,GAAG;QAACA,KAAK,CAAC,KAAK;KAAC;IACvE,MAAM,EAAEW,kBAAkB,EAAE,GAAGlB,WAAWL,MAAMwB,iBAAiB;IACjE,MAAM,EAAEC,KAAK,EAAEC,YAAY,EAAE,GAAGlB,aAAaQ;IAC7C,IAAI,CAACO,sBAAsB,EAACP,+BAAAA,YAAaW,MAAM,GAAE;QAC/C,qEAAqE;QACrE,qEAAqE;QACrE,oEAAoE;QACpE,kEAAkE;QAClE,oCAAoC;QACpC,qBAAO,KAACzB;YAAIW,KAAKA;WAASM;IAC5B;IACA,qBACE,KAAChB;QAASU,KAAKA;OAASM;QAAMS,IAAI;YAAC;gBAAEC,YAAY;YAAW;eAAMT;SAAO;kBACvE,cAAA,KAACb;YACCkB,OAAOA;YACPC,cAAcA;WACTV,cAAc;YAAEc,OAAOd;QAAY,IAAI,CAAC,GACxCD,sBAAsBgB,YACvB,CAAC,IACD;YAAEC,aAAajB;QAAkB,GAChCQ,qBAAqB;YAAEU,OAAO;QAAK,IAAI,CAAC;YAC7C,oEAAoE;YACpE,mEAAmE;YACnE,mEAAmE;YACnE,kEAAkE;YAClE,sDAAsD;YACtDC,WAAW,CAACC;;uBACVjB,eACI,CAAC,gBAAgB,EAAEiB,KAAK,SAAS,UAAEnB,+BAAAA,YAAaW,MAAM,mBAAI,EAAE,CAAC,CAAC,GAC9D,8DACA,2BACA,CAAC,gBAAgB,EAAEQ,KAAK,SAAS,WAAEnB,+BAAAA,YAAaW,MAAM,oBAAI,EAAE,CAAC,CAAC,GAC9D;;;;AAKd;AAEFhB,iBAAiByB,WAAW,GAAG;AAE/B,OAAO,MAAMC,yBACX;IACEC,KAAK7B;IACL8B,UAAUjC;IACV8B,aAAa;IACbI,aACE;IACFC,UAAUzC,MAAM0C,iBAAiB,CAACC,UAAU;IAC5CC,MAAM;QAAEC,MAAM5C,WAAW4C,IAAI;QAAEjB,IAAI;YAAEkB,OAAO;QAAiB;IAAE;IAC/DC,OAAO;QAAEC,aAAahD,MAAMiD,YAAY,CAACC,OAAO;IAAC;IACjDC,YAAY;QACV;YACEC,MAAM;YACNC,OAAO;YACPb,aACE,qEACA;YACFc,WAAWtD,MAAMuD,kBAAkB,CAACC,UAAU;QAChD;QACA;YACEJ,MAAM;YACNC,OAAO;YACPb,aACE,sEACA;YACFc,WAAWtD,MAAMuD,kBAAkB,CAACC,UAAU;QAChD;KAKD;AACH,EAAC;AAEH,SAAS7C,gBAAgB,GAAE"}
|
|
@@ -0,0 +1,31 @@
|
|
|
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 SHARE_ID: Aglyn.ComponentId;
|
|
20
|
+
export interface CollectionShareProps extends StackProps {
|
|
21
|
+
/** Heading before the buttons; empty string hides it. */
|
|
22
|
+
heading?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Share buttons for the CURRENT page URL (AGL-582): X, LinkedIn, Facebook,
|
|
26
|
+
* and copy-link. Pure client behavior — the URL is read at click time so
|
|
27
|
+
* SSR and besigner renders stay markup-identical; editing surfaces no-op.
|
|
28
|
+
*/
|
|
29
|
+
declare const CollectionShare: import("react").ForwardRefExoticComponent<Omit<CollectionShareProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
|
|
30
|
+
export declare const collectionShareSchema: Aglyn.ComponentSchema<CollectionShareProps>;
|
|
31
|
+
export { CollectionShare };
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
2
|
+
import { _ as _object_without_properties_loose } from "@swc/helpers/_/_object_without_properties_loose";
|
|
3
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
4
|
+
/**
|
|
5
|
+
* @license
|
|
6
|
+
* Copyright 2026 Aglyn LLC
|
|
7
|
+
*
|
|
8
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
9
|
+
* you may not use this file except in compliance with the License.
|
|
10
|
+
* You may obtain a copy of the License at
|
|
11
|
+
*
|
|
12
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
13
|
+
*
|
|
14
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
15
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
16
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
17
|
+
* See the License for the specific language governing permissions and
|
|
18
|
+
* limitations under the License.
|
|
19
|
+
*/ import * as Aglyn from "@aglyn/aglyn";
|
|
20
|
+
import { mdiContentCopy, mdiFacebook, mdiLinkedin, mdiShareVariant, mdiTwitter } from "@aglyn/shared-data-mdi";
|
|
21
|
+
import { MdiIcon } from "@aglyn/shared-ui-jsx";
|
|
22
|
+
import IconButton from "@mui/material/IconButton";
|
|
23
|
+
import MuiStack from "@mui/material/Stack";
|
|
24
|
+
import Typography from "@mui/material/Typography";
|
|
25
|
+
import { forwardRef, useContext, useState } from "react";
|
|
26
|
+
import { BUNDLE_ID } from "../constants/bundle-common.js";
|
|
27
|
+
// Persisted component id (AGL-551/582); the compose pipeline references it
|
|
28
|
+
// through the @aglyn/aglyn constant. Never rename.
|
|
29
|
+
export const SHARE_ID = Aglyn.COLLECTION_SHARE_COMPONENT_ID;
|
|
30
|
+
const SHARE_TARGETS = [
|
|
31
|
+
{
|
|
32
|
+
label: 'Share on X',
|
|
33
|
+
path: mdiTwitter.path,
|
|
34
|
+
href: (url)=>`https://twitter.com/intent/tweet?url=${encodeURIComponent(url)}`
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
label: 'Share on LinkedIn',
|
|
38
|
+
path: mdiLinkedin.path,
|
|
39
|
+
href: (url)=>'https://www.linkedin.com/sharing/share-offsite/?url=' + encodeURIComponent(url)
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
label: 'Share on Facebook',
|
|
43
|
+
path: mdiFacebook.path,
|
|
44
|
+
href: (url)=>`https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(url)}`
|
|
45
|
+
}
|
|
46
|
+
];
|
|
47
|
+
/**
|
|
48
|
+
* Share buttons for the CURRENT page URL (AGL-582): X, LinkedIn, Facebook,
|
|
49
|
+
* and copy-link. Pure client behavior — the URL is read at click time so
|
|
50
|
+
* SSR and besigner renders stay markup-identical; editing surfaces no-op.
|
|
51
|
+
*/ const CollectionShare = /*#__PURE__*/ forwardRef((props, ref)=>{
|
|
52
|
+
const { heading } = props, rest = _object_without_properties_loose(props, [
|
|
53
|
+
"heading"
|
|
54
|
+
]);
|
|
55
|
+
// Node styles ride the renderer-merged sx; recompose (stack.ts pattern).
|
|
56
|
+
const nodeSx = Array.isArray(props['sx']) ? props['sx'] : [
|
|
57
|
+
props['sx']
|
|
58
|
+
];
|
|
59
|
+
const { suppressNavigation } = useContext(Aglyn.ScreenLinkContext);
|
|
60
|
+
const [copied, setCopied] = useState(false);
|
|
61
|
+
const title = heading != null ? heading : 'Share';
|
|
62
|
+
const open = (buildHref)=>()=>{
|
|
63
|
+
if (suppressNavigation || typeof window === 'undefined') return;
|
|
64
|
+
window.open(buildHref(window.location.href), '_blank', 'noopener,noreferrer');
|
|
65
|
+
};
|
|
66
|
+
const copy = async ()=>{
|
|
67
|
+
if (suppressNavigation || typeof window === 'undefined') return;
|
|
68
|
+
try {
|
|
69
|
+
await navigator.clipboard.writeText(window.location.href);
|
|
70
|
+
setCopied(true);
|
|
71
|
+
setTimeout(()=>setCopied(false), 2000);
|
|
72
|
+
} catch (unused) {
|
|
73
|
+
// Clipboard unavailable (permissions, http) — silently skip.
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
return /*#__PURE__*/ _jsxs(MuiStack, _extends({
|
|
77
|
+
ref: ref,
|
|
78
|
+
direction: "row",
|
|
79
|
+
spacing: 0.5
|
|
80
|
+
}, rest, {
|
|
81
|
+
// MERGE, never replace (AGL-1450) — see collection-entry-meta.tsx.
|
|
82
|
+
sx: [
|
|
83
|
+
{
|
|
84
|
+
alignItems: 'center'
|
|
85
|
+
},
|
|
86
|
+
...nodeSx
|
|
87
|
+
],
|
|
88
|
+
children: [
|
|
89
|
+
title ? // `component="p"` because this labels a row of buttons; it is not a
|
|
90
|
+
// section heading (AGL-2486). MUI's `defaultVariantMapping` sends
|
|
91
|
+
// `subtitle2` to `<h6>`, so without this the Share Bar puts a level-6
|
|
92
|
+
// heading into the document outline of every page carrying it. On a
|
|
93
|
+
// blog post the nearest preceding heading is an `h2`, which makes it
|
|
94
|
+
// a skipped level and a `heading-order` failure.
|
|
95
|
+
//
|
|
96
|
+
// Said here rather than as a theme-wide `variantMapping` override: a
|
|
97
|
+
// default would silently change the element under every `subtitle2`
|
|
98
|
+
// in the codebase, including surfaces where an `h6` is correct.
|
|
99
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
100
|
+
component: "p",
|
|
101
|
+
variant: "subtitle2",
|
|
102
|
+
sx: {
|
|
103
|
+
mr: 1
|
|
104
|
+
},
|
|
105
|
+
children: title
|
|
106
|
+
}) : null,
|
|
107
|
+
SHARE_TARGETS.map((target)=>/*#__PURE__*/ _jsx(IconButton, {
|
|
108
|
+
"aria-label": target.label,
|
|
109
|
+
size: "small",
|
|
110
|
+
onClick: open(target.href),
|
|
111
|
+
children: /*#__PURE__*/ _jsx(MdiIcon, {
|
|
112
|
+
path: target.path
|
|
113
|
+
})
|
|
114
|
+
}, target.label)),
|
|
115
|
+
/*#__PURE__*/ _jsx(IconButton, {
|
|
116
|
+
"aria-label": copied ? 'Link copied' : 'Copy link',
|
|
117
|
+
size: "small",
|
|
118
|
+
color: copied ? 'success' : 'default',
|
|
119
|
+
onClick: copy,
|
|
120
|
+
children: /*#__PURE__*/ _jsx(MdiIcon, {
|
|
121
|
+
path: mdiContentCopy.path
|
|
122
|
+
})
|
|
123
|
+
})
|
|
124
|
+
]
|
|
125
|
+
}));
|
|
126
|
+
});
|
|
127
|
+
CollectionShare.displayName = 'AglynCollectionShare';
|
|
128
|
+
export const collectionShareSchema = {
|
|
129
|
+
$id: SHARE_ID,
|
|
130
|
+
pluginId: BUNDLE_ID,
|
|
131
|
+
displayName: 'Share Bar',
|
|
132
|
+
description: 'Share buttons for the current page, plus a copy link.',
|
|
133
|
+
category: Aglyn.ComponentCategory.NAVIGATION,
|
|
134
|
+
icon: {
|
|
135
|
+
path: mdiShareVariant.path,
|
|
136
|
+
sx: {
|
|
137
|
+
color: 'secondary.main'
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
flags: {
|
|
141
|
+
selfClosing: Aglyn.FEATURE_FLAG.ENABLED
|
|
142
|
+
},
|
|
143
|
+
attributes: [
|
|
144
|
+
{
|
|
145
|
+
name: 'heading',
|
|
146
|
+
label: 'Heading',
|
|
147
|
+
description: 'Text before the buttons (blank hides it).',
|
|
148
|
+
component: Aglyn.FieldComponentType.TEXT_FIELD
|
|
149
|
+
}
|
|
150
|
+
]
|
|
151
|
+
};
|
|
152
|
+
export { CollectionShare };
|
|
153
|
+
|
|
154
|
+
//# sourceMappingURL=collection-share.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/components/collection-share.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 {\n mdiContentCopy,\n mdiFacebook,\n mdiLinkedin,\n mdiShareVariant,\n mdiTwitter,\n} from '@aglyn/shared-data-mdi'\nimport { MdiIcon } from '@aglyn/shared-ui-jsx'\nimport IconButton from '@mui/material/IconButton'\nimport MuiStack, { type StackProps } from '@mui/material/Stack'\nimport Typography from '@mui/material/Typography'\nimport { forwardRef, useContext, useState } 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 SHARE_ID: Aglyn.ComponentId = Aglyn.COLLECTION_SHARE_COMPONENT_ID\n\nexport interface CollectionShareProps extends StackProps {\n /** Heading before the buttons; empty string hides it. */\n heading?: string\n}\n\nconst SHARE_TARGETS = [\n {\n label: 'Share on X',\n path: mdiTwitter.path,\n href: (url: string) =>\n `https://twitter.com/intent/tweet?url=${encodeURIComponent(url)}`,\n },\n {\n label: 'Share on LinkedIn',\n path: mdiLinkedin.path,\n href: (url: string) =>\n 'https://www.linkedin.com/sharing/share-offsite/?url=' +\n encodeURIComponent(url),\n },\n {\n label: 'Share on Facebook',\n path: mdiFacebook.path,\n href: (url: string) =>\n `https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(url)}`,\n },\n]\n\n/**\n * Share buttons for the CURRENT page URL (AGL-582): X, LinkedIn, Facebook,\n * and copy-link. Pure client behavior — the URL is read at click time so\n * SSR and besigner renders stay markup-identical; editing surfaces no-op.\n */\nconst CollectionShare = forwardRef<HTMLDivElement, CollectionShareProps>(\n (props, ref) => {\n const { heading, ...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 const [copied, setCopied] = useState(false)\n const title = heading ?? 'Share'\n const open = (buildHref: (url: string) => string) => () => {\n if (suppressNavigation || typeof window === 'undefined') return\n window.open(\n buildHref(window.location.href),\n '_blank',\n 'noopener,noreferrer',\n )\n }\n const copy = async () => {\n if (suppressNavigation || typeof window === 'undefined') return\n try {\n await navigator.clipboard.writeText(window.location.href)\n setCopied(true)\n setTimeout(() => setCopied(false), 2000)\n } catch {\n // Clipboard unavailable (permissions, http) — silently skip.\n }\n }\n return (\n <MuiStack\n ref={ref}\n direction=\"row\"\n spacing={0.5}\n {...rest}\n // MERGE, never replace (AGL-1450) — see collection-entry-meta.tsx.\n sx={[{ alignItems: 'center' }, ...nodeSx]}\n >\n {title ? (\n // `component=\"p\"` because this labels a row of buttons; it is not a\n // section heading (AGL-2486). MUI's `defaultVariantMapping` sends\n // `subtitle2` to `<h6>`, so without this the Share Bar puts a level-6\n // heading into the document outline of every page carrying it. On a\n // blog post the nearest preceding heading is an `h2`, which makes it\n // a skipped level and a `heading-order` failure.\n //\n // Said here rather than as a theme-wide `variantMapping` override: a\n // default would silently change the element under every `subtitle2`\n // in the codebase, including surfaces where an `h6` is correct.\n <Typography component=\"p\" variant=\"subtitle2\" sx={{ mr: 1 }}>\n {title}\n </Typography>\n ) : null}\n {SHARE_TARGETS.map((target) => (\n <IconButton\n key={target.label}\n aria-label={target.label}\n size=\"small\"\n onClick={open(target.href)}\n >\n <MdiIcon path={target.path} />\n </IconButton>\n ))}\n <IconButton\n aria-label={copied ? 'Link copied' : 'Copy link'}\n size=\"small\"\n color={copied ? 'success' : 'default'}\n onClick={copy}\n >\n <MdiIcon path={mdiContentCopy.path} />\n </IconButton>\n </MuiStack>\n )\n },\n)\nCollectionShare.displayName = 'AglynCollectionShare'\n\nexport const collectionShareSchema: Aglyn.ComponentSchema<CollectionShareProps> =\n {\n $id: SHARE_ID,\n pluginId: BUNDLE_ID,\n displayName: 'Share Bar',\n description: 'Share buttons for the current page, plus a copy link.',\n category: Aglyn.ComponentCategory.NAVIGATION,\n icon: { path: mdiShareVariant.path, sx: { color: 'secondary.main' } },\n flags: { selfClosing: Aglyn.FEATURE_FLAG.ENABLED },\n attributes: [\n {\n name: 'heading',\n label: 'Heading',\n description: 'Text before the buttons (blank hides it).',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n },\n ],\n }\n\nexport { CollectionShare }\n"],"names":["Aglyn","mdiContentCopy","mdiFacebook","mdiLinkedin","mdiShareVariant","mdiTwitter","MdiIcon","IconButton","MuiStack","Typography","forwardRef","useContext","useState","BUNDLE_ID","SHARE_ID","COLLECTION_SHARE_COMPONENT_ID","SHARE_TARGETS","label","path","href","url","encodeURIComponent","CollectionShare","props","ref","heading","rest","nodeSx","Array","isArray","suppressNavigation","ScreenLinkContext","copied","setCopied","title","open","buildHref","window","location","copy","navigator","clipboard","writeText","setTimeout","direction","spacing","sx","alignItems","component","variant","mr","map","target","aria-label","size","onClick","color","displayName","collectionShareSchema","$id","pluginId","description","category","ComponentCategory","NAVIGATION","icon","flags","selfClosing","FEATURE_FLAG","ENABLED","attributes","name","FieldComponentType","TEXT_FIELD"],"mappings":";;;AAAA;;;;;;;;;;;;;;;CAeC,GAED,YAAYA,WAAW,eAAc;AACrC,SACEC,cAAc,EACdC,WAAW,EACXC,WAAW,EACXC,eAAe,EACfC,UAAU,QACL,yBAAwB;AAC/B,SAASC,OAAO,QAAQ,uBAAsB;AAC9C,OAAOC,gBAAgB,2BAA0B;AACjD,OAAOC,cAAmC,sBAAqB;AAC/D,OAAOC,gBAAgB,2BAA0B;AACjD,SAASC,UAAU,EAAEC,UAAU,EAAEC,QAAQ,QAAQ,QAAO;AACxD,SAASC,SAAS,QAAQ,gCAA4B;AAEtD,2EAA2E;AAC3E,mDAAmD;AACnD,OAAO,MAAMC,WAA8Bd,MAAMe,6BAA6B,CAAA;AAO9E,MAAMC,gBAAgB;IACpB;QACEC,OAAO;QACPC,MAAMb,WAAWa,IAAI;QACrBC,MAAM,CAACC,MACL,CAAC,qCAAqC,EAAEC,mBAAmBD,MAAM;IACrE;IACA;QACEH,OAAO;QACPC,MAAMf,YAAYe,IAAI;QACtBC,MAAM,CAACC,MACL,yDACAC,mBAAmBD;IACvB;IACA;QACEH,OAAO;QACPC,MAAMhB,YAAYgB,IAAI;QACtBC,MAAM,CAACC,MACL,CAAC,6CAA6C,EAAEC,mBAAmBD,MAAM;IAC7E;CACD;AAED;;;;CAIC,GACD,MAAME,gCAAkBZ,WACtB,CAACa,OAAOC;IACN,MAAM,EAAEC,OAAO,EAAW,GAAGF,OAATG,wCAASH;;;IAC7B,yEAAyE;IACzE,MAAMI,SAASC,MAAMC,OAAO,CAACN,KAAK,CAAC,KAAK,IAAIA,KAAK,CAAC,KAAK,GAAG;QAACA,KAAK,CAAC,KAAK;KAAC;IACvE,MAAM,EAAEO,kBAAkB,EAAE,GAAGnB,WAAWX,MAAM+B,iBAAiB;IACjE,MAAM,CAACC,QAAQC,UAAU,GAAGrB,SAAS;IACrC,MAAMsB,QAAQT,kBAAAA,UAAW;IACzB,MAAMU,OAAO,CAACC,YAAuC;YACnD,IAAIN,sBAAsB,OAAOO,WAAW,aAAa;YACzDA,OAAOF,IAAI,CACTC,UAAUC,OAAOC,QAAQ,CAACnB,IAAI,GAC9B,UACA;QAEJ;IACA,MAAMoB,OAAO;QACX,IAAIT,sBAAsB,OAAOO,WAAW,aAAa;QACzD,IAAI;YACF,MAAMG,UAAUC,SAAS,CAACC,SAAS,CAACL,OAAOC,QAAQ,CAACnB,IAAI;YACxDc,UAAU;YACVU,WAAW,IAAMV,UAAU,QAAQ;QACrC,EAAE,eAAM;QACN,6DAA6D;QAC/D;IACF;IACA,qBACE,MAACzB;QACCgB,KAAKA;QACLoB,WAAU;QACVC,SAAS;OACLnB;QACJ,mEAAmE;QACnEoB,IAAI;YAAC;gBAAEC,YAAY;YAAS;eAAMpB;SAAO;;YAExCO,QACC,oEAAoE;YACpE,kEAAkE;YAClE,sEAAsE;YACtE,oEAAoE;YACpE,qEAAqE;YACrE,iDAAiD;YACjD,EAAE;YACF,qEAAqE;YACrE,oEAAoE;YACpE,gEAAgE;0BAChE,KAACzB;gBAAWuC,WAAU;gBAAIC,SAAQ;gBAAYH,IAAI;oBAAEI,IAAI;gBAAE;0BACvDhB;iBAED;YACHlB,cAAcmC,GAAG,CAAC,CAACC,uBAClB,KAAC7C;oBAEC8C,cAAYD,OAAOnC,KAAK;oBACxBqC,MAAK;oBACLC,SAASpB,KAAKiB,OAAOjC,IAAI;8BAEzB,cAAA,KAACb;wBAAQY,MAAMkC,OAAOlC,IAAI;;mBALrBkC,OAAOnC,KAAK;0BAQrB,KAACV;gBACC8C,cAAYrB,SAAS,gBAAgB;gBACrCsB,MAAK;gBACLE,OAAOxB,SAAS,YAAY;gBAC5BuB,SAAShB;0BAET,cAAA,KAACjC;oBAAQY,MAAMjB,eAAeiB,IAAI;;;;;AAI1C;AAEFI,gBAAgBmC,WAAW,GAAG;AAE9B,OAAO,MAAMC,wBACX;IACEC,KAAK7C;IACL8C,UAAU/C;IACV4C,aAAa;IACbI,aAAa;IACbC,UAAU9D,MAAM+D,iBAAiB,CAACC,UAAU;IAC5CC,MAAM;QAAE/C,MAAMd,gBAAgBc,IAAI;QAAE4B,IAAI;YAAEU,OAAO;QAAiB;IAAE;IACpEU,OAAO;QAAEC,aAAanE,MAAMoE,YAAY,CAACC,OAAO;IAAC;IACjDC,YAAY;QACV;YACEC,MAAM;YACNtD,OAAO;YACP4C,aAAa;YACbb,WAAWhD,MAAMwE,kBAAkB,CAACC,UAAU;QAChD;KACD;AACH,EAAC;AAEH,SAASnD,eAAe,GAAE"}
|