@aglyn/plugins-mui 1.0.0-beta.143
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +22 -0
- package/package.json +47 -0
- package/src/index.d.ts +21 -0
- package/src/index.js +22 -0
- package/src/index.js.map +1 -0
- package/src/lib/components/accordion.d.ts +96 -0
- package/src/lib/components/accordion.js +392 -0
- package/src/lib/components/accordion.js.map +1 -0
- package/src/lib/components/app-bar.d.ts +32 -0
- package/src/lib/components/app-bar.js +86 -0
- package/src/lib/components/app-bar.js.map +1 -0
- package/src/lib/components/blocks.d.ts +46 -0
- package/src/lib/components/blocks.js +1007 -0
- package/src/lib/components/blocks.js.map +1 -0
- package/src/lib/components/box.d.ts +47 -0
- package/src/lib/components/box.js +125 -0
- package/src/lib/components/box.js.map +1 -0
- package/src/lib/components/breadcrumbs.d.ts +44 -0
- package/src/lib/components/breadcrumbs.js +172 -0
- package/src/lib/components/breadcrumbs.js.map +1 -0
- package/src/lib/components/button.d.ts +89 -0
- package/src/lib/components/button.js +272 -0
- package/src/lib/components/button.js.map +1 -0
- package/src/lib/components/card.d.ts +61 -0
- package/src/lib/components/card.js +336 -0
- package/src/lib/components/card.js.map +1 -0
- package/src/lib/components/collection.d.ts +514 -0
- package/src/lib/components/collection.js +2999 -0
- package/src/lib/components/collection.js.map +1 -0
- package/src/lib/components/container.d.ts +42 -0
- package/src/lib/components/container.js +169 -0
- package/src/lib/components/container.js.map +1 -0
- package/src/lib/components/custom-html.d.ts +78 -0
- package/src/lib/components/custom-html.js +219 -0
- package/src/lib/components/custom-html.js.map +1 -0
- package/src/lib/components/data-table.d.ts +57 -0
- package/src/lib/components/data-table.js +216 -0
- package/src/lib/components/data-table.js.map +1 -0
- package/src/lib/components/document-root.d.ts +77 -0
- package/src/lib/components/document-root.js +118 -0
- package/src/lib/components/document-root.js.map +1 -0
- package/src/lib/components/drawer.d.ts +93 -0
- package/src/lib/components/drawer.js +566 -0
- package/src/lib/components/drawer.js.map +1 -0
- package/src/lib/components/function-controls.d.ts +66 -0
- package/src/lib/components/function-controls.js +207 -0
- package/src/lib/components/function-controls.js.map +1 -0
- package/src/lib/components/function-scope.d.ts +110 -0
- package/src/lib/components/function-scope.js +478 -0
- package/src/lib/components/function-scope.js.map +1 -0
- package/src/lib/components/function-widget.d.ts +75 -0
- package/src/lib/components/function-widget.js +307 -0
- package/src/lib/components/function-widget.js.map +1 -0
- package/src/lib/components/grid.d.ts +91 -0
- package/src/lib/components/grid.js +322 -0
- package/src/lib/components/grid.js.map +1 -0
- package/src/lib/components/icon.d.ts +54 -0
- package/src/lib/components/icon.js +163 -0
- package/src/lib/components/icon.js.map +1 -0
- package/src/lib/components/image-list.d.ts +58 -0
- package/src/lib/components/image-list.js +336 -0
- package/src/lib/components/image-list.js.map +1 -0
- package/src/lib/components/image.d.ts +154 -0
- package/src/lib/components/image.js +451 -0
- package/src/lib/components/image.js.map +1 -0
- package/src/lib/components/inline-text.d.ts +74 -0
- package/src/lib/components/inline-text.js +407 -0
- package/src/lib/components/inline-text.js.map +1 -0
- package/src/lib/components/language-switcher.d.ts +35 -0
- package/src/lib/components/language-switcher.js +179 -0
- package/src/lib/components/language-switcher.js.map +1 -0
- package/src/lib/components/layout-slot.d.ts +68 -0
- package/src/lib/components/layout-slot.js +192 -0
- package/src/lib/components/layout-slot.js.map +1 -0
- package/src/lib/components/link-box-accessible-name.d.ts +79 -0
- package/src/lib/components/link-box-accessible-name.js +158 -0
- package/src/lib/components/link-box-accessible-name.js.map +1 -0
- package/src/lib/components/link-box.d.ts +66 -0
- package/src/lib/components/link-box.js +212 -0
- package/src/lib/components/link-box.js.map +1 -0
- package/src/lib/components/list-item-text.d.ts +22 -0
- package/src/lib/components/list-item-text.js +86 -0
- package/src/lib/components/list-item-text.js.map +1 -0
- package/src/lib/components/list-item.d.ts +32 -0
- package/src/lib/components/list-item.js +127 -0
- package/src/lib/components/list-item.js.map +1 -0
- package/src/lib/components/list.d.ts +34 -0
- package/src/lib/components/list.js +108 -0
- package/src/lib/components/list.js.map +1 -0
- package/src/lib/components/markdown.d.ts +129 -0
- package/src/lib/components/markdown.js +853 -0
- package/src/lib/components/markdown.js.map +1 -0
- package/src/lib/components/nav-menu.d.ts +68 -0
- package/src/lib/components/nav-menu.js +683 -0
- package/src/lib/components/nav-menu.js.map +1 -0
- package/src/lib/components/pagination.d.ts +59 -0
- package/src/lib/components/pagination.js +243 -0
- package/src/lib/components/pagination.js.map +1 -0
- package/src/lib/components/paper.d.ts +47 -0
- package/src/lib/components/paper.js +202 -0
- package/src/lib/components/paper.js.map +1 -0
- package/src/lib/components/plugin-frame.d.ts +64 -0
- package/src/lib/components/plugin-frame.js +335 -0
- package/src/lib/components/plugin-frame.js.map +1 -0
- package/src/lib/components/plugin.d.ts +95 -0
- package/src/lib/components/plugin.js +304 -0
- package/src/lib/components/plugin.js.map +1 -0
- package/src/lib/components/product.d.ts +40 -0
- package/src/lib/components/product.js +287 -0
- package/src/lib/components/product.js.map +1 -0
- package/src/lib/components/reusable-instance.d.ts +57 -0
- package/src/lib/components/reusable-instance.js +126 -0
- package/src/lib/components/reusable-instance.js.map +1 -0
- package/src/lib/components/screen-link.d.ts +85 -0
- package/src/lib/components/screen-link.js +324 -0
- package/src/lib/components/screen-link.js.map +1 -0
- package/src/lib/components/search-box.d.ts +41 -0
- package/src/lib/components/search-box.js +125 -0
- package/src/lib/components/search-box.js.map +1 -0
- package/src/lib/components/section.d.ts +56 -0
- package/src/lib/components/section.js +132 -0
- package/src/lib/components/section.js.map +1 -0
- package/src/lib/components/stack.d.ts +55 -0
- package/src/lib/components/stack.js +309 -0
- package/src/lib/components/stack.js.map +1 -0
- package/src/lib/components/tabs.d.ts +288 -0
- package/src/lib/components/tabs.js +788 -0
- package/src/lib/components/tabs.js.map +1 -0
- package/src/lib/components/theme-mode-switcher.d.ts +38 -0
- package/src/lib/components/theme-mode-switcher.js +168 -0
- package/src/lib/components/theme-mode-switcher.js.map +1 -0
- package/src/lib/components/toolbar.d.ts +37 -0
- package/src/lib/components/toolbar.js +117 -0
- package/src/lib/components/toolbar.js.map +1 -0
- package/src/lib/components/typography.d.ts +33 -0
- package/src/lib/components/typography.js +433 -0
- package/src/lib/components/typography.js.map +1 -0
- package/src/lib/components/video-lightbox-controls.d.ts +131 -0
- package/src/lib/components/video-lightbox-controls.js +536 -0
- package/src/lib/components/video-lightbox-controls.js.map +1 -0
- package/src/lib/components/video-lightbox.d.ts +60 -0
- package/src/lib/components/video-lightbox.js +247 -0
- package/src/lib/components/video-lightbox.js.map +1 -0
- package/src/lib/components/video-playback-beacon.d.ts +80 -0
- package/src/lib/components/video-playback-beacon.js +128 -0
- package/src/lib/components/video-playback-beacon.js.map +1 -0
- package/src/lib/components/video-player-frame.d.ts +58 -0
- package/src/lib/components/video-player-frame.js +51 -0
- package/src/lib/components/video-player-frame.js.map +1 -0
- package/src/lib/components/video.d.ts +220 -0
- package/src/lib/components/video.js +874 -0
- package/src/lib/components/video.js.map +1 -0
- package/src/lib/constants/bundle-common.d.ts +17 -0
- package/src/lib/constants/bundle-common.js +18 -0
- package/src/lib/constants/bundle-common.js.map +1 -0
- package/src/lib/constants/field-presets.d.ts +93 -0
- package/src/lib/constants/field-presets.js +248 -0
- package/src/lib/constants/field-presets.js.map +1 -0
- package/src/lib/plugin.d.ts +80 -0
- package/src/lib/plugin.js +599 -0
- package/src/lib/plugin.js.map +1 -0
- package/src/lib/utils/author-html-label.d.ts +73 -0
- package/src/lib/utils/author-html-label.js +89 -0
- package/src/lib/utils/author-html-label.js.map +1 -0
- package/src/lib/utils/drop-cleared-props.d.ts +18 -0
- package/src/lib/utils/drop-cleared-props.js +74 -0
- package/src/lib/utils/drop-cleared-props.js.map +1 -0
- package/src/lib/utils/element-picker.d.ts +99 -0
- package/src/lib/utils/element-picker.js +140 -0
- package/src/lib/utils/element-picker.js.map +1 -0
- package/src/lib/utils/generate-preset-id.d.ts +19 -0
- package/src/lib/utils/generate-preset-id.js +25 -0
- package/src/lib/utils/generate-preset-id.js.map +1 -0
- package/src/lib/utils/link-target-props.d.ts +53 -0
- package/src/lib/utils/link-target-props.js +53 -0
- package/src/lib/utils/link-target-props.js.map +1 -0
|
@@ -0,0 +1,324 @@
|
|
|
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 { mdiLinkVariant } from "@aglyn/shared-data-mdi";
|
|
21
|
+
import { AppLink } from "@aglyn/shared-ui-jsx";
|
|
22
|
+
import Button from "@mui/material/Button";
|
|
23
|
+
import Link from "@mui/material/Link";
|
|
24
|
+
import { forwardRef } from "react";
|
|
25
|
+
import { BUNDLE_ID } from "../constants/bundle-common.js";
|
|
26
|
+
import { FIELD_COLOR, FIELD_FULL_WIDTH, FIELD_LINK_TARGET, FIELD_LINK_TARGET_NAME, FIELD_SIZE, FIELD_TEXT_CONTENT } from "../constants/field-presets.js";
|
|
27
|
+
import { withAuthorHtmlLabel } from "../utils/author-html-label.js";
|
|
28
|
+
import { dropClearedProps } from "../utils/drop-cleared-props.js";
|
|
29
|
+
import { generatePresetId } from "../utils/generate-preset-id.js";
|
|
30
|
+
import { linkTargetProps } from "../utils/link-target-props.js";
|
|
31
|
+
// Component ids are persisted in screen documents; never rename.
|
|
32
|
+
export const ID = 'muiScreenLink';
|
|
33
|
+
/**
|
|
34
|
+
* What a button-styled LINK renders as with nothing to point at (canvas,
|
|
35
|
+
* preview, unresolved screen). `role: undefined` is the load-bearing half:
|
|
36
|
+
* MUI's `ButtonBase` stamps `role="button"` onto any non-`<button>` root,
|
|
37
|
+
* and merges the caller's props AFTER its own, so an explicit `undefined`
|
|
38
|
+
* is what removes it.
|
|
39
|
+
*/ const STYLED_LINK_PLACEHOLDER = {
|
|
40
|
+
component: 'span',
|
|
41
|
+
role: undefined
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Link that targets a screen by id, never a hardcoded path. Degrades to a
|
|
45
|
+
* plain button when the id doesn't resolve (unpublished/deleted screen) and
|
|
46
|
+
* when navigation is suppressed (besigner canvas, preview).
|
|
47
|
+
*
|
|
48
|
+
* `renderAs="link"` renders MUI's `Link` instead of `Button` (AGL-1195).
|
|
49
|
+
* Footer and inline navigation are *text*: as buttons they inherit button
|
|
50
|
+
* typography, uppercase transforms and the wrong role for assistive tech.
|
|
51
|
+
* The button-only props are dropped in that mode rather than passed through
|
|
52
|
+
* — `variant` means the typography variant on a `Link`, so forwarding
|
|
53
|
+
* `"contained"` would silently produce an unstyled element.
|
|
54
|
+
*
|
|
55
|
+
* `renderAs="linkButton"` splits the two halves that used to travel together
|
|
56
|
+
* (AGL-1347). A pill row whose chips all navigate — docs URLs, `mailto:`,
|
|
57
|
+
* social profiles — is a legitimate design, but every chip announced as a
|
|
58
|
+
* button, which tells a screen-reader user to expect an action and costs
|
|
59
|
+
* them the link-list and open-in-new-tab affordances. This mode keeps the
|
|
60
|
+
* button's `variant`/`size`/`fullWidth` and drops the role, exactly as MUI's
|
|
61
|
+
* own `Button component={Link}` does. It is a THIRD value rather than
|
|
62
|
+
* `variant` becoming live in `"link"` mode, because a node switched to Text
|
|
63
|
+
* link keeps whatever `variant` it was authored with (the shipped preset is
|
|
64
|
+
* `variant: 'outlined'`) — honouring those would repaint the site's nav and
|
|
65
|
+
* footer as outlined pills.
|
|
66
|
+
*/ const ScreenLink = /*#__PURE__*/ forwardRef((props, ref)=>{
|
|
67
|
+
const { screenId, href: externalHref, renderAs, target, targetName, html } = props, spread = _object_without_properties_loose(props, [
|
|
68
|
+
"screenId",
|
|
69
|
+
"href",
|
|
70
|
+
"renderAs",
|
|
71
|
+
"target",
|
|
72
|
+
"targetName",
|
|
73
|
+
"html"
|
|
74
|
+
]);
|
|
75
|
+
// A CLEARED attribute persists as null, and null is not "use the default"
|
|
76
|
+
// in React — `color={null}` reaches MUI, which capitalizes it and throws
|
|
77
|
+
// error #7 during SSR, 500ing the page (AGL-1226). This is the site's
|
|
78
|
+
// most-used element (70–77 nodes per page), so the guard runs BEFORE
|
|
79
|
+
// `variant`/`size`/`fullWidth` are split out: they are forwarded as named
|
|
80
|
+
// attributes, and guarding only the spread would leave those three exposed.
|
|
81
|
+
//
|
|
82
|
+
// The formatted label (AGL-2557) is substituted for `children` in the same
|
|
83
|
+
// breath, so all five shapes below carry it without five more spreads —
|
|
84
|
+
// and an unformatted link, which is nearly all of them, gets the very
|
|
85
|
+
// object `dropClearedProps` returned.
|
|
86
|
+
const _withAuthorHtmlLabel = withAuthorHtmlLabel(dropClearedProps(spread), html), { variant, size, fullWidth } = _withAuthorHtmlLabel, rest = _object_without_properties_loose(_withAuthorHtmlLabel, [
|
|
87
|
+
"variant",
|
|
88
|
+
"size",
|
|
89
|
+
"fullWidth"
|
|
90
|
+
]);
|
|
91
|
+
// Id-vs-URL precedence and the `javascript:`/`data:` guard live in
|
|
92
|
+
// `useLinkTarget` (AGL-1335) — one copy for every linking element, and
|
|
93
|
+
// the only place that knows a `screen:`-prefixed value is a reference.
|
|
94
|
+
const { href, suppressNavigation, editorInert, broken, leavesSite } = Aglyn.useLinkTarget(screenId, externalHref);
|
|
95
|
+
// Resolved rather than spread: `'custom'` is an authoring sentinel, and an
|
|
96
|
+
// anchor carrying `target="custom"` would open a window literally named
|
|
97
|
+
// that. The pair is destructured OUT of `spread` above, so the inert canvas
|
|
98
|
+
// branches below never see either half.
|
|
99
|
+
const targetAttrs = linkTargetProps(target, targetName, leavesSite);
|
|
100
|
+
/**
|
|
101
|
+
* The same dead-target problem Tabs had, on the element there are 326 of
|
|
102
|
+
* (AGL-1893). Here it is less violent — an unresolved Screen Link already
|
|
103
|
+
* degrades to inert content rather than to a fake control — but it is just
|
|
104
|
+
* as silent: unpublish a screen and every link to it quietly stops
|
|
105
|
+
* navigating, with nothing in the editor to say which ones.
|
|
106
|
+
*
|
|
107
|
+
* So the LIVE rendering is deliberately unchanged, and only the authoring
|
|
108
|
+
* surface gains anything: on the besigner canvas the link wears a warning
|
|
109
|
+
* ring and explains itself on hover. A live restyle would be the riskier
|
|
110
|
+
* half of this by far — it would repaint any published CTA whose screen is
|
|
111
|
+
* temporarily unpublished, on sites whose owners never asked.
|
|
112
|
+
*/ const flagged = Aglyn.brokenScreenLinkProps(broken, editorInert);
|
|
113
|
+
const asLink = renderAs === 'link';
|
|
114
|
+
// Semantics and appearance are independent choices now (AGL-1347): a
|
|
115
|
+
// styled link takes the button's styling props and none of its role.
|
|
116
|
+
const asStyledLink = renderAs === 'linkButton';
|
|
117
|
+
if (!href || suppressNavigation) {
|
|
118
|
+
// The canvas must not lie about which element the page will ship, so
|
|
119
|
+
// the unresolved/suppressed case mirrors the same three shapes.
|
|
120
|
+
//
|
|
121
|
+
// `sx` is lifted out of the spread so the editor ring can be merged
|
|
122
|
+
// rather than replace the author's styles — the AGL-1284 mistake, in a
|
|
123
|
+
// place where the symptom would be "my link lost all its styling the
|
|
124
|
+
// day its screen was unpublished". The ring goes LAST, and is the one
|
|
125
|
+
// thing here allowed to outrank an authored value: it is a diagnostic
|
|
126
|
+
// on a surface only the author sees, not a style.
|
|
127
|
+
const { sx: authoredSx } = rest, restNoSx = _object_without_properties_loose(rest, [
|
|
128
|
+
"sx"
|
|
129
|
+
]);
|
|
130
|
+
const inertSx = [
|
|
131
|
+
...Array.isArray(authoredSx) ? authoredSx : authoredSx ? [
|
|
132
|
+
authoredSx
|
|
133
|
+
] : [],
|
|
134
|
+
...broken && editorInert ? [
|
|
135
|
+
Aglyn.BROKEN_SCREEN_LINK_SX
|
|
136
|
+
] : []
|
|
137
|
+
];
|
|
138
|
+
if (asLink) {
|
|
139
|
+
return /*#__PURE__*/ _jsx(Link, _extends({
|
|
140
|
+
ref: ref,
|
|
141
|
+
component: "span",
|
|
142
|
+
underline: "hover"
|
|
143
|
+
}, flagged, restNoSx, {
|
|
144
|
+
sx: inertSx
|
|
145
|
+
}));
|
|
146
|
+
}
|
|
147
|
+
return /*#__PURE__*/ _jsx(Button, _extends({
|
|
148
|
+
ref: ref
|
|
149
|
+
}, asStyledLink ? STYLED_LINK_PLACEHOLDER : {}, {
|
|
150
|
+
variant: variant,
|
|
151
|
+
size: size,
|
|
152
|
+
fullWidth: fullWidth
|
|
153
|
+
}, flagged, restNoSx, {
|
|
154
|
+
sx: inertSx
|
|
155
|
+
}));
|
|
156
|
+
}
|
|
157
|
+
return asLink ? /*#__PURE__*/ _jsx(AppLink, _extends({
|
|
158
|
+
ref: ref,
|
|
159
|
+
underline: "hover",
|
|
160
|
+
href: href
|
|
161
|
+
}, targetAttrs, rest)) : /*#__PURE__*/ _jsx(AppLink, _extends({
|
|
162
|
+
ref: ref,
|
|
163
|
+
componentVariant: "button",
|
|
164
|
+
href: href
|
|
165
|
+
}, targetAttrs, {
|
|
166
|
+
// The whole defect in one attribute. `ButtonBase` adds `role="button"`
|
|
167
|
+
// to every non-`<button>` root, so the button LOOK used to drag the
|
|
168
|
+
// button ROLE onto a navigating anchor. It spreads the caller's props
|
|
169
|
+
// after its own, so passing `undefined` here is what clears it — and
|
|
170
|
+
// only for the mode that asked to be a link.
|
|
171
|
+
role: asStyledLink ? undefined : 'button',
|
|
172
|
+
variant: variant,
|
|
173
|
+
size: size,
|
|
174
|
+
fullWidth: fullWidth
|
|
175
|
+
}, rest));
|
|
176
|
+
});
|
|
177
|
+
ScreenLink.displayName = 'ScreenLink';
|
|
178
|
+
/**
|
|
179
|
+
* Shows an attribute in the two modes that wear button styling — Button and
|
|
180
|
+
* Link (button styling). `notMatch` inverts `is`, so an unset `renderAs` —
|
|
181
|
+
* every link authored before AGL-1195 — still counts as a button and keeps
|
|
182
|
+
* its controls, and only Text link hides them.
|
|
183
|
+
*/ const BUTTON_STYLED = {
|
|
184
|
+
when: 'renderAs',
|
|
185
|
+
is: 'link',
|
|
186
|
+
notMatch: true
|
|
187
|
+
};
|
|
188
|
+
export const schema = {
|
|
189
|
+
$id: ID,
|
|
190
|
+
pluginId: BUNDLE_ID,
|
|
191
|
+
displayName: 'Screen Link',
|
|
192
|
+
description: 'Links to another screen by id, so it survives a slug change.',
|
|
193
|
+
category: Aglyn.ComponentCategory.NAVIGATION,
|
|
194
|
+
icon: {
|
|
195
|
+
path: mdiLinkVariant.path,
|
|
196
|
+
sx: {
|
|
197
|
+
color: '#2196f3'
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
flags: {
|
|
201
|
+
textEditable: Aglyn.FEATURE_FLAG.ENABLED,
|
|
202
|
+
richTextEditable: Aglyn.FEATURE_FLAG.ENABLED
|
|
203
|
+
},
|
|
204
|
+
// Emphasis only (AGL-2557). Every mode of this element ships an anchor or
|
|
205
|
+
// a button, and neither may contain a list or a second control.
|
|
206
|
+
richTextCommands: [
|
|
207
|
+
Aglyn.RICH_TEXT_COMMANDS.EMPHASIS
|
|
208
|
+
],
|
|
209
|
+
attributes: [
|
|
210
|
+
FIELD_TEXT_CONTENT,
|
|
211
|
+
{
|
|
212
|
+
name: 'screenId',
|
|
213
|
+
description: 'Screen this link navigates to. The address is generated from the ' + 'published path at render time, so it keeps working when the ' + "screen's slug or parent changes.",
|
|
214
|
+
component: Aglyn.FieldComponentType.SCREEN_SELECT,
|
|
215
|
+
label: 'Screen'
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
name: 'href',
|
|
219
|
+
description: 'Where this link goes when it points off this site. Ignored while ' + 'Screen names one — that field wins, so clear it to use a URL.',
|
|
220
|
+
component: Aglyn.FieldComponentType.TEXT_FIELD,
|
|
221
|
+
label: 'External URL',
|
|
222
|
+
// A bare `#fragment` saves and goes nowhere (AGL-2867).
|
|
223
|
+
resolveProps: Aglyn.bareFragmentLinkFieldProps
|
|
224
|
+
},
|
|
225
|
+
FIELD_LINK_TARGET,
|
|
226
|
+
FIELD_LINK_TARGET_NAME,
|
|
227
|
+
{
|
|
228
|
+
name: 'renderAs',
|
|
229
|
+
description: 'What this announces as. Button is for calls to action; both link ' + 'options announce as a link, which is what navigation should be — ' + 'pick "Link (button styling)" to keep the button look on something ' + 'that navigates.',
|
|
230
|
+
component: Aglyn.FieldComponentType.SELECT,
|
|
231
|
+
label: 'Render as',
|
|
232
|
+
// `'button'` is a REAL SENTINEL, not a deletion (AGL-1453): `''` here
|
|
233
|
+
// spelled an author's actual choice, and the one they could not make.
|
|
234
|
+
// The attributes form strips `''` before save (AGL-1191), so a link
|
|
235
|
+
// switched to Text link had NO route in this dropdown back to Button —
|
|
236
|
+
// and 213 of the 326 Screen Links in the corpus are in that mode.
|
|
237
|
+
//
|
|
238
|
+
// Safe because `renderAs` never reaches MUI: it is destructured out
|
|
239
|
+
// above and read only as `=== 'link'` / `=== 'linkButton'`, so
|
|
240
|
+
// `'button'` and an absent value take the identical branch. That is
|
|
241
|
+
// also what keeps every link authored before AGL-1195 rendering
|
|
242
|
+
// unchanged.
|
|
243
|
+
options: [
|
|
244
|
+
{
|
|
245
|
+
value: 'button',
|
|
246
|
+
label: 'Button'
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
value: 'link',
|
|
250
|
+
label: 'Text link'
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
value: 'linkButton',
|
|
254
|
+
label: 'Link (button styling)'
|
|
255
|
+
}
|
|
256
|
+
]
|
|
257
|
+
},
|
|
258
|
+
// `color` survives both shapes — MUI's Link takes it too.
|
|
259
|
+
FIELD_COLOR,
|
|
260
|
+
// The rest are appearance: the renderer drops them in Text link mode, so
|
|
261
|
+
// leaving them on screen there would offer three controls that silently
|
|
262
|
+
// do nothing — but they are live in Link (button styling), which is the
|
|
263
|
+
// point of that mode. Spread rather than mutate — these presets are
|
|
264
|
+
// shared.
|
|
265
|
+
_extends({}, FIELD_SIZE, {
|
|
266
|
+
condition: BUTTON_STYLED
|
|
267
|
+
}),
|
|
268
|
+
_extends({}, FIELD_FULL_WIDTH, {
|
|
269
|
+
condition: BUTTON_STYLED
|
|
270
|
+
}),
|
|
271
|
+
{
|
|
272
|
+
name: 'variant',
|
|
273
|
+
description: 'How the link is drawn once its style is Button: Contained is a ' + 'filled call to action, Outlined a secondary one, Text the lightest. ' + 'Ignored while the link is styled as plain text.',
|
|
274
|
+
component: Aglyn.FieldComponentType.SELECT,
|
|
275
|
+
label: 'Variant',
|
|
276
|
+
// "Default" deleted (AGL-1453): unpersistable, and a second name for
|
|
277
|
+
// `text`, MUI Button's own default, already on the list.
|
|
278
|
+
options: [
|
|
279
|
+
{
|
|
280
|
+
value: 'text',
|
|
281
|
+
label: 'Text'
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
value: 'outlined',
|
|
285
|
+
label: 'Outlined'
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
value: 'contained',
|
|
289
|
+
label: 'Contained'
|
|
290
|
+
}
|
|
291
|
+
],
|
|
292
|
+
condition: BUTTON_STYLED
|
|
293
|
+
}
|
|
294
|
+
]
|
|
295
|
+
};
|
|
296
|
+
export const presets = [
|
|
297
|
+
{
|
|
298
|
+
$id: generatePresetId(ID),
|
|
299
|
+
type: Aglyn.NodeType.PRESET,
|
|
300
|
+
displayName: 'Screen Link',
|
|
301
|
+
icon: {
|
|
302
|
+
path: mdiLinkVariant.path,
|
|
303
|
+
sx: {
|
|
304
|
+
color: '#2196f3'
|
|
305
|
+
}
|
|
306
|
+
},
|
|
307
|
+
category: Aglyn.ComponentCategory.NAVIGATION,
|
|
308
|
+
data: {
|
|
309
|
+
$id: null,
|
|
310
|
+
componentId: ID,
|
|
311
|
+
pluginId: BUNDLE_ID,
|
|
312
|
+
props: {
|
|
313
|
+
children: 'Screen Link',
|
|
314
|
+
// Same visible-on-any-surface defaults as the button preset; the
|
|
315
|
+
// default text color disappears against a same-hue appbar.
|
|
316
|
+
variant: 'outlined',
|
|
317
|
+
color: 'inherit'
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
];
|
|
322
|
+
export default ScreenLink;
|
|
323
|
+
|
|
324
|
+
//# sourceMappingURL=screen-link.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/components/screen-link.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 { mdiLinkVariant } from '@aglyn/shared-data-mdi'\nimport { AppLink } from '@aglyn/shared-ui-jsx'\nimport Button, { type ButtonProps } from '@mui/material/Button'\nimport Link from '@mui/material/Link'\nimport { forwardRef } from 'react'\nimport { BUNDLE_ID } from '../constants/bundle-common'\nimport {\n FIELD_COLOR,\n FIELD_FULL_WIDTH,\n FIELD_LINK_TARGET,\n FIELD_LINK_TARGET_NAME,\n FIELD_SIZE,\n FIELD_TEXT_CONTENT,\n} from '../constants/field-presets'\nimport { withAuthorHtmlLabel } from '../utils/author-html-label'\nimport { dropClearedProps } from '../utils/drop-cleared-props'\nimport { generatePresetId } from '../utils/generate-preset-id'\nimport {\n type LinkTargetChoice,\n linkTargetProps,\n} from '../utils/link-target-props'\n\n// Component ids are persisted in screen documents; never rename.\nexport const ID: Aglyn.ComponentId = 'muiScreenLink'\n\nexport interface ScreenLinkProps extends ButtonProps {\n /**\n * Target screen id. The href is resolved from the host routing map at\n * render time (see `ScreenLinkContext`), so slug renames and re-parenting\n * never break the link — which is what makes navigation inside a shared\n * layout viable.\n */\n screenId?: string\n /** External URL escape hatch, used only when no `screenId` is set. */\n href?: string\n /**\n * Which element this ships as (AGL-1195, AGL-1347). Persisted in screen\n * documents; never rename, and `undefined` must keep meaning `'button'` —\n * every link authored before this existed is one.\n *\n * - `'button'` (or unset) — `<a role=\"button\">` with the button's look.\n * - `'link'` — a plain text link; the button-only props are dropped.\n * - `'linkButton'` — a plain `<a>` with NO role, wearing the button's\n * `variant`/`size`/`fullWidth`. Appearance without semantics: a pill\n * that navigates announces as the link it is.\n */\n renderAs?: 'button' | 'link' | 'linkButton'\n /**\n * Where the link opens. Persisted in screen documents; never rename a\n * value, and `undefined` must keep meaning `'_self'` — every link authored\n * before this existed stays in the tab.\n */\n target?: LinkTargetChoice\n /** Window name used only when `target` is `'custom'`. */\n targetName?: string\n /**\n * Sanitized emphasis markup for the label, written by the inline editor's\n * rich mode (AGL-2557). `children` keeps the plain-text reading of it, and\n * is what every surface that cannot render markup falls back to.\n */\n html?: string\n}\n\n/**\n * What a button-styled LINK renders as with nothing to point at (canvas,\n * preview, unresolved screen). `role: undefined` is the load-bearing half:\n * MUI's `ButtonBase` stamps `role=\"button\"` onto any non-`<button>` root,\n * and merges the caller's props AFTER its own, so an explicit `undefined`\n * is what removes it.\n */\nconst STYLED_LINK_PLACEHOLDER = { component: 'span', role: undefined } as const\n\n/**\n * Link that targets a screen by id, never a hardcoded path. Degrades to a\n * plain button when the id doesn't resolve (unpublished/deleted screen) and\n * when navigation is suppressed (besigner canvas, preview).\n *\n * `renderAs=\"link\"` renders MUI's `Link` instead of `Button` (AGL-1195).\n * Footer and inline navigation are *text*: as buttons they inherit button\n * typography, uppercase transforms and the wrong role for assistive tech.\n * The button-only props are dropped in that mode rather than passed through\n * — `variant` means the typography variant on a `Link`, so forwarding\n * `\"contained\"` would silently produce an unstyled element.\n *\n * `renderAs=\"linkButton\"` splits the two halves that used to travel together\n * (AGL-1347). A pill row whose chips all navigate — docs URLs, `mailto:`,\n * social profiles — is a legitimate design, but every chip announced as a\n * button, which tells a screen-reader user to expect an action and costs\n * them the link-list and open-in-new-tab affordances. This mode keeps the\n * button's `variant`/`size`/`fullWidth` and drops the role, exactly as MUI's\n * own `Button component={Link}` does. It is a THIRD value rather than\n * `variant` becoming live in `\"link\"` mode, because a node switched to Text\n * link keeps whatever `variant` it was authored with (the shipped preset is\n * `variant: 'outlined'`) — honouring those would repaint the site's nav and\n * footer as outlined pills.\n */\nconst ScreenLink = forwardRef<any, ScreenLinkProps>((props, ref) => {\n const {\n screenId,\n href: externalHref,\n renderAs,\n target,\n targetName,\n html,\n ...spread\n } = props\n // A CLEARED attribute persists as null, and null is not \"use the default\"\n // in React — `color={null}` reaches MUI, which capitalizes it and throws\n // error #7 during SSR, 500ing the page (AGL-1226). This is the site's\n // most-used element (70–77 nodes per page), so the guard runs BEFORE\n // `variant`/`size`/`fullWidth` are split out: they are forwarded as named\n // attributes, and guarding only the spread would leave those three exposed.\n //\n // The formatted label (AGL-2557) is substituted for `children` in the same\n // breath, so all five shapes below carry it without five more spreads —\n // and an unformatted link, which is nearly all of them, gets the very\n // object `dropClearedProps` returned.\n const { variant, size, fullWidth, ...rest } = withAuthorHtmlLabel(\n dropClearedProps(spread),\n html,\n )\n // Id-vs-URL precedence and the `javascript:`/`data:` guard live in\n // `useLinkTarget` (AGL-1335) — one copy for every linking element, and\n // the only place that knows a `screen:`-prefixed value is a reference.\n const { href, suppressNavigation, editorInert, broken, leavesSite } =\n Aglyn.useLinkTarget(screenId, externalHref)\n // Resolved rather than spread: `'custom'` is an authoring sentinel, and an\n // anchor carrying `target=\"custom\"` would open a window literally named\n // that. The pair is destructured OUT of `spread` above, so the inert canvas\n // branches below never see either half.\n const targetAttrs = linkTargetProps(target, targetName, leavesSite)\n /**\n * The same dead-target problem Tabs had, on the element there are 326 of\n * (AGL-1893). Here it is less violent — an unresolved Screen Link already\n * degrades to inert content rather than to a fake control — but it is just\n * as silent: unpublish a screen and every link to it quietly stops\n * navigating, with nothing in the editor to say which ones.\n *\n * So the LIVE rendering is deliberately unchanged, and only the authoring\n * surface gains anything: on the besigner canvas the link wears a warning\n * ring and explains itself on hover. A live restyle would be the riskier\n * half of this by far — it would repaint any published CTA whose screen is\n * temporarily unpublished, on sites whose owners never asked.\n */\n const flagged = Aglyn.brokenScreenLinkProps(broken, editorInert)\n const asLink = renderAs === 'link'\n // Semantics and appearance are independent choices now (AGL-1347): a\n // styled link takes the button's styling props and none of its role.\n const asStyledLink = renderAs === 'linkButton'\n\n if (!href || suppressNavigation) {\n // The canvas must not lie about which element the page will ship, so\n // the unresolved/suppressed case mirrors the same three shapes.\n //\n // `sx` is lifted out of the spread so the editor ring can be merged\n // rather than replace the author's styles — the AGL-1284 mistake, in a\n // place where the symptom would be \"my link lost all its styling the\n // day its screen was unpublished\". The ring goes LAST, and is the one\n // thing here allowed to outrank an authored value: it is a diagnostic\n // on a surface only the author sees, not a style.\n const { sx: authoredSx, ...restNoSx } = rest as Record<string, any>\n const inertSx = [\n ...(Array.isArray(authoredSx) ? authoredSx : authoredSx ? [authoredSx] : []),\n ...(broken && editorInert ? [Aglyn.BROKEN_SCREEN_LINK_SX] : []),\n ]\n if (asLink) {\n return (\n <Link\n ref={ref}\n component=\"span\"\n underline=\"hover\"\n {...flagged}\n {...restNoSx}\n sx={inertSx}\n />\n )\n }\n return (\n <Button\n ref={ref}\n {...(asStyledLink ? STYLED_LINK_PLACEHOLDER : {})}\n variant={variant}\n size={size}\n fullWidth={fullWidth}\n {...flagged}\n {...restNoSx}\n sx={inertSx}\n />\n )\n }\n return asLink ? (\n <AppLink\n ref={ref}\n underline=\"hover\"\n href={href}\n {...targetAttrs}\n {...rest}\n />\n ) : (\n <AppLink\n ref={ref}\n componentVariant=\"button\"\n href={href}\n {...targetAttrs}\n // The whole defect in one attribute. `ButtonBase` adds `role=\"button\"`\n // to every non-`<button>` root, so the button LOOK used to drag the\n // button ROLE onto a navigating anchor. It spreads the caller's props\n // after its own, so passing `undefined` here is what clears it — and\n // only for the mode that asked to be a link.\n role={asStyledLink ? undefined : 'button'}\n variant={variant}\n size={size}\n fullWidth={fullWidth}\n {...rest}\n />\n )\n})\nScreenLink.displayName = 'ScreenLink'\n\n/**\n * Shows an attribute in the two modes that wear button styling — Button and\n * Link (button styling). `notMatch` inverts `is`, so an unset `renderAs` —\n * every link authored before AGL-1195 — still counts as a button and keeps\n * its controls, and only Text link hides them.\n */\nconst BUTTON_STYLED = { when: 'renderAs', is: 'link', notMatch: true }\n\nexport const schema: Aglyn.ComponentSchema<ScreenLinkProps> = {\n $id: ID,\n pluginId: BUNDLE_ID,\n displayName: 'Screen Link',\n description: 'Links to another screen by id, so it survives a slug change.',\n category: Aglyn.ComponentCategory.NAVIGATION,\n icon: {\n path: mdiLinkVariant.path,\n sx: { color: '#2196f3' },\n },\n flags: {\n textEditable: Aglyn.FEATURE_FLAG.ENABLED,\n richTextEditable: Aglyn.FEATURE_FLAG.ENABLED,\n },\n // Emphasis only (AGL-2557). Every mode of this element ships an anchor or\n // a button, and neither may contain a list or a second control.\n richTextCommands: [Aglyn.RICH_TEXT_COMMANDS.EMPHASIS],\n attributes: [\n FIELD_TEXT_CONTENT,\n {\n name: 'screenId',\n description:\n 'Screen this link navigates to. The address is generated from the ' +\n 'published path at render time, so it keeps working when the ' +\n \"screen's slug or parent changes.\",\n component: Aglyn.FieldComponentType.SCREEN_SELECT,\n label: 'Screen',\n },\n {\n name: 'href',\n description:\n 'Where this link goes when it points off this site. Ignored while ' +\n 'Screen names one — that field wins, so clear it to use a URL.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n label: 'External URL',\n // A bare `#fragment` saves and goes nowhere (AGL-2867).\n resolveProps: Aglyn.bareFragmentLinkFieldProps,\n },\n FIELD_LINK_TARGET,\n FIELD_LINK_TARGET_NAME,\n {\n name: 'renderAs',\n description:\n 'What this announces as. Button is for calls to action; both link ' +\n 'options announce as a link, which is what navigation should be — ' +\n 'pick \"Link (button styling)\" to keep the button look on something ' +\n 'that navigates.',\n component: Aglyn.FieldComponentType.SELECT,\n label: 'Render as',\n // `'button'` is a REAL SENTINEL, not a deletion (AGL-1453): `''` here\n // spelled an author's actual choice, and the one they could not make.\n // The attributes form strips `''` before save (AGL-1191), so a link\n // switched to Text link had NO route in this dropdown back to Button —\n // and 213 of the 326 Screen Links in the corpus are in that mode.\n //\n // Safe because `renderAs` never reaches MUI: it is destructured out\n // above and read only as `=== 'link'` / `=== 'linkButton'`, so\n // `'button'` and an absent value take the identical branch. That is\n // also what keeps every link authored before AGL-1195 rendering\n // unchanged.\n options: [\n { value: 'button', label: 'Button' },\n { value: 'link', label: 'Text link' },\n { value: 'linkButton', label: 'Link (button styling)' },\n ],\n },\n // `color` survives both shapes — MUI's Link takes it too.\n FIELD_COLOR,\n // The rest are appearance: the renderer drops them in Text link mode, so\n // leaving them on screen there would offer three controls that silently\n // do nothing — but they are live in Link (button styling), which is the\n // point of that mode. Spread rather than mutate — these presets are\n // shared.\n { ...FIELD_SIZE, condition: BUTTON_STYLED },\n { ...FIELD_FULL_WIDTH, condition: BUTTON_STYLED },\n {\n name: 'variant',\n description:\n 'How the link is drawn once its style is Button: Contained is a ' +\n 'filled call to action, Outlined a secondary one, Text the lightest. ' +\n 'Ignored while the link is styled as plain text.',\n component: Aglyn.FieldComponentType.SELECT,\n label: 'Variant',\n // \"Default\" deleted (AGL-1453): unpersistable, and a second name for\n // `text`, MUI Button's own default, already on the list.\n options: [\n { value: 'text', label: 'Text' },\n { value: 'outlined', label: 'Outlined' },\n { value: 'contained', label: 'Contained' },\n ],\n condition: BUTTON_STYLED,\n },\n ],\n}\n\nexport const presets: Aglyn.PresetSchema[] = [\n {\n $id: generatePresetId(ID),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Screen Link',\n icon: {\n path: mdiLinkVariant.path,\n sx: { color: '#2196f3' },\n },\n category: Aglyn.ComponentCategory.NAVIGATION,\n data: {\n $id: null,\n componentId: ID,\n pluginId: BUNDLE_ID,\n props: {\n children: 'Screen Link',\n // Same visible-on-any-surface defaults as the button preset; the\n // default text color disappears against a same-hue appbar.\n variant: 'outlined',\n color: 'inherit',\n },\n },\n },\n]\n\nexport default ScreenLink\n"],"names":["Aglyn","mdiLinkVariant","AppLink","Button","Link","forwardRef","BUNDLE_ID","FIELD_COLOR","FIELD_FULL_WIDTH","FIELD_LINK_TARGET","FIELD_LINK_TARGET_NAME","FIELD_SIZE","FIELD_TEXT_CONTENT","withAuthorHtmlLabel","dropClearedProps","generatePresetId","linkTargetProps","ID","STYLED_LINK_PLACEHOLDER","component","role","undefined","ScreenLink","props","ref","screenId","href","externalHref","renderAs","target","targetName","html","spread","variant","size","fullWidth","rest","suppressNavigation","editorInert","broken","leavesSite","useLinkTarget","targetAttrs","flagged","brokenScreenLinkProps","asLink","asStyledLink","sx","authoredSx","restNoSx","inertSx","Array","isArray","BROKEN_SCREEN_LINK_SX","underline","componentVariant","displayName","BUTTON_STYLED","when","is","notMatch","schema","$id","pluginId","description","category","ComponentCategory","NAVIGATION","icon","path","color","flags","textEditable","FEATURE_FLAG","ENABLED","richTextEditable","richTextCommands","RICH_TEXT_COMMANDS","EMPHASIS","attributes","name","FieldComponentType","SCREEN_SELECT","label","TEXT_FIELD","resolveProps","bareFragmentLinkFieldProps","SELECT","options","value","condition","presets","type","NodeType","PRESET","data","componentId","children"],"mappings":";;;AAAA;;;;;;;;;;;;;;;CAeC,GAED,YAAYA,WAAW,eAAc;AACrC,SAASC,cAAc,QAAQ,yBAAwB;AACvD,SAASC,OAAO,QAAQ,uBAAsB;AAC9C,OAAOC,YAAkC,uBAAsB;AAC/D,OAAOC,UAAU,qBAAoB;AACrC,SAASC,UAAU,QAAQ,QAAO;AAClC,SAASC,SAAS,QAAQ,gCAA4B;AACtD,SACEC,WAAW,EACXC,gBAAgB,EAChBC,iBAAiB,EACjBC,sBAAsB,EACtBC,UAAU,EACVC,kBAAkB,QACb,gCAA4B;AACnC,SAASC,mBAAmB,QAAQ,gCAA4B;AAChE,SAASC,gBAAgB,QAAQ,iCAA6B;AAC9D,SAASC,gBAAgB,QAAQ,iCAA6B;AAC9D,SAEEC,eAAe,QACV,gCAA4B;AAEnC,iEAAiE;AACjE,OAAO,MAAMC,KAAwB,gBAAe;AAwCpD;;;;;;CAMC,GACD,MAAMC,0BAA0B;IAAEC,WAAW;IAAQC,MAAMC;AAAU;AAErE;;;;;;;;;;;;;;;;;;;;;;;CAuBC,GACD,MAAMC,2BAAajB,WAAiC,CAACkB,OAAOC;IAC1D,MAAM,EACJC,QAAQ,EACRC,MAAMC,YAAY,EAClBC,QAAQ,EACRC,MAAM,EACNC,UAAU,EACVC,IAAI,EAEL,GAAGR,OADCS,0CACDT;;;;;;;;IACJ,0EAA0E;IAC1E,yEAAyE;IACzE,sEAAsE;IACtE,qEAAqE;IACrE,0EAA0E;IAC1E,4EAA4E;IAC5E,EAAE;IACF,2EAA2E;IAC3E,wEAAwE;IACxE,sEAAsE;IACtE,sCAAsC;IACtC,MAA8CV,uBAAAA,oBAC5CC,iBAAiBkB,SACjBD,OAFI,EAAEE,OAAO,EAAEC,IAAI,EAAEC,SAAS,EAAW,GAAGtB,sBAATuB,wCAASvB;;;;;IAI9C,mEAAmE;IACnE,uEAAuE;IACvE,uEAAuE;IACvE,MAAM,EAAEa,IAAI,EAAEW,kBAAkB,EAAEC,WAAW,EAAEC,MAAM,EAAEC,UAAU,EAAE,GACjExC,MAAMyC,aAAa,CAAChB,UAAUE;IAChC,2EAA2E;IAC3E,wEAAwE;IACxE,4EAA4E;IAC5E,wCAAwC;IACxC,MAAMe,cAAc1B,gBAAgBa,QAAQC,YAAYU;IACxD;;;;;;;;;;;;GAYC,GACD,MAAMG,UAAU3C,MAAM4C,qBAAqB,CAACL,QAAQD;IACpD,MAAMO,SAASjB,aAAa;IAC5B,qEAAqE;IACrE,qEAAqE;IACrE,MAAMkB,eAAelB,aAAa;IAElC,IAAI,CAACF,QAAQW,oBAAoB;QAC/B,qEAAqE;QACrE,gEAAgE;QAChE,EAAE;QACF,oEAAoE;QACpE,uEAAuE;QACvE,qEAAqE;QACrE,sEAAsE;QACtE,sEAAsE;QACtE,kDAAkD;QAClD,MAAM,EAAEU,IAAIC,UAAU,EAAe,GAAGZ,MAAba,4CAAab;;;QACxC,MAAMc,UAAU;eACVC,MAAMC,OAAO,CAACJ,cAAcA,aAAaA,aAAa;gBAACA;aAAW,GAAG,EAAE;eACvET,UAAUD,cAAc;gBAACtC,MAAMqD,qBAAqB;aAAC,GAAG,EAAE;SAC/D;QACD,IAAIR,QAAQ;YACV,qBACE,KAACzC;gBACCoB,KAAKA;gBACLL,WAAU;gBACVmC,WAAU;eACNX,SACAM;gBACJF,IAAIG;;QAGV;QACA,qBACE,KAAC/C;YACCqB,KAAKA;WACAsB,eAAe5B,0BAA0B,CAAC;YAC/Ce,SAASA;YACTC,MAAMA;YACNC,WAAWA;WACPQ,SACAM;YACJF,IAAIG;;IAGV;IACA,OAAOL,uBACL,KAAC3C;QACCsB,KAAKA;QACL8B,WAAU;QACV5B,MAAMA;OACFgB,aACAN,uBAGN,KAAClC;QACCsB,KAAKA;QACL+B,kBAAiB;QACjB7B,MAAMA;OACFgB;QACJ,uEAAuE;QACvE,oEAAoE;QACpE,sEAAsE;QACtE,qEAAqE;QACrE,6CAA6C;QAC7CtB,MAAM0B,eAAezB,YAAY;QACjCY,SAASA;QACTC,MAAMA;QACNC,WAAWA;OACPC;AAGV;AACAd,WAAWkC,WAAW,GAAG;AAEzB;;;;;CAKC,GACD,MAAMC,gBAAgB;IAAEC,MAAM;IAAYC,IAAI;IAAQC,UAAU;AAAK;AAErE,OAAO,MAAMC,SAAiD;IAC5DC,KAAK7C;IACL8C,UAAUzD;IACVkD,aAAa;IACbQ,aAAa;IACbC,UAAUjE,MAAMkE,iBAAiB,CAACC,UAAU;IAC5CC,MAAM;QACJC,MAAMpE,eAAeoE,IAAI;QACzBtB,IAAI;YAAEuB,OAAO;QAAU;IACzB;IACAC,OAAO;QACLC,cAAcxE,MAAMyE,YAAY,CAACC,OAAO;QACxCC,kBAAkB3E,MAAMyE,YAAY,CAACC,OAAO;IAC9C;IACA,0EAA0E;IAC1E,gEAAgE;IAChEE,kBAAkB;QAAC5E,MAAM6E,kBAAkB,CAACC,QAAQ;KAAC;IACrDC,YAAY;QACVnE;QACA;YACEoE,MAAM;YACNhB,aACE,sEACA,iEACA;YACF7C,WAAWnB,MAAMiF,kBAAkB,CAACC,aAAa;YACjDC,OAAO;QACT;QACA;YACEH,MAAM;YACNhB,aACE,sEACA;YACF7C,WAAWnB,MAAMiF,kBAAkB,CAACG,UAAU;YAC9CD,OAAO;YACP,wDAAwD;YACxDE,cAAcrF,MAAMsF,0BAA0B;QAChD;QACA7E;QACAC;QACA;YACEsE,MAAM;YACNhB,aACE,sEACA,sEACA,uEACA;YACF7C,WAAWnB,MAAMiF,kBAAkB,CAACM,MAAM;YAC1CJ,OAAO;YACP,sEAAsE;YACtE,sEAAsE;YACtE,oEAAoE;YACpE,uEAAuE;YACvE,kEAAkE;YAClE,EAAE;YACF,oEAAoE;YACpE,+DAA+D;YAC/D,oEAAoE;YACpE,gEAAgE;YAChE,aAAa;YACbK,SAAS;gBACP;oBAAEC,OAAO;oBAAUN,OAAO;gBAAS;gBACnC;oBAAEM,OAAO;oBAAQN,OAAO;gBAAY;gBACpC;oBAAEM,OAAO;oBAAcN,OAAO;gBAAwB;aACvD;QACH;QACA,0DAA0D;QAC1D5E;QACA,yEAAyE;QACzE,wEAAwE;QACxE,wEAAwE;QACxE,oEAAoE;QACpE,UAAU;QACV,aAAKI;YAAY+E,WAAWjC;;QAC5B,aAAKjD;YAAkBkF,WAAWjC;;QAClC;YACEuB,MAAM;YACNhB,aACE,oEACA,yEACA;YACF7C,WAAWnB,MAAMiF,kBAAkB,CAACM,MAAM;YAC1CJ,OAAO;YACP,qEAAqE;YACrE,yDAAyD;YACzDK,SAAS;gBACP;oBAAEC,OAAO;oBAAQN,OAAO;gBAAO;gBAC/B;oBAAEM,OAAO;oBAAYN,OAAO;gBAAW;gBACvC;oBAAEM,OAAO;oBAAaN,OAAO;gBAAY;aAC1C;YACDO,WAAWjC;QACb;KACD;AACH,EAAC;AAED,OAAO,MAAMkC,UAAgC;IAC3C;QACE7B,KAAK/C,iBAAiBE;QACtB2E,MAAM5F,MAAM6F,QAAQ,CAACC,MAAM;QAC3BtC,aAAa;QACbY,MAAM;YACJC,MAAMpE,eAAeoE,IAAI;YACzBtB,IAAI;gBAAEuB,OAAO;YAAU;QACzB;QACAL,UAAUjE,MAAMkE,iBAAiB,CAACC,UAAU;QAC5C4B,MAAM;YACJjC,KAAK;YACLkC,aAAa/E;YACb8C,UAAUzD;YACViB,OAAO;gBACL0E,UAAU;gBACV,iEAAiE;gBACjE,2DAA2D;gBAC3DhE,SAAS;gBACTqC,OAAO;YACT;QACF;IACF;CACD,CAAA;AAED,eAAehD,WAAU"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
import * as Aglyn from '@aglyn/aglyn';
|
|
18
|
+
export declare const ID: Aglyn.ComponentId;
|
|
19
|
+
export interface SearchBoxProps {
|
|
20
|
+
placeholder?: string;
|
|
21
|
+
/**
|
|
22
|
+
* What the field starts with (AGL-2513). The results page prefills the
|
|
23
|
+
* query it is showing, so a reader can refine it where they are rather
|
|
24
|
+
* than going back for the box they typed into.
|
|
25
|
+
*
|
|
26
|
+
* Uncontrolled on purpose: this component holds no state and issues no
|
|
27
|
+
* request, and a `value` would freeze the field the moment the reader
|
|
28
|
+
* typed into it.
|
|
29
|
+
*/
|
|
30
|
+
defaultValue?: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Site search box (AGL-88): a plain GET form to the tenant's /search page,
|
|
34
|
+
* so it works with zero JavaScript and is inert in the besigner (the
|
|
35
|
+
* console has no /search route to submit to; navigation there is a no-op
|
|
36
|
+
* form post the editor never triggers).
|
|
37
|
+
*/
|
|
38
|
+
declare const SearchBox: import("react").ForwardRefExoticComponent<SearchBoxProps & import("react").RefAttributes<HTMLFormElement>>;
|
|
39
|
+
export declare const schema: Aglyn.ComponentSchema<SearchBoxProps>;
|
|
40
|
+
export declare const presets: Aglyn.PresetSchema[];
|
|
41
|
+
export default SearchBox;
|
|
@@ -0,0 +1,125 @@
|
|
|
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 IconButton from "@mui/material/IconButton";
|
|
22
|
+
import InputAdornment from "@mui/material/InputAdornment";
|
|
23
|
+
import TextField from "@mui/material/TextField";
|
|
24
|
+
import { MdiIcon } from "@aglyn/shared-ui-jsx";
|
|
25
|
+
import { forwardRef } from "react";
|
|
26
|
+
import { BUNDLE_ID } from "../constants/bundle-common.js";
|
|
27
|
+
import { generatePresetId } from "../utils/generate-preset-id.js";
|
|
28
|
+
// Component ids are persisted in screen documents; never rename.
|
|
29
|
+
export const ID = 'searchBox';
|
|
30
|
+
/**
|
|
31
|
+
* Site search box (AGL-88): a plain GET form to the tenant's /search page,
|
|
32
|
+
* so it works with zero JavaScript and is inert in the besigner (the
|
|
33
|
+
* console has no /search route to submit to; navigation there is a no-op
|
|
34
|
+
* form post the editor never triggers).
|
|
35
|
+
*/ const SearchBox = /*#__PURE__*/ forwardRef((props, ref)=>{
|
|
36
|
+
const { placeholder, defaultValue } = props, rest = _object_without_properties_loose(props, [
|
|
37
|
+
"placeholder",
|
|
38
|
+
"defaultValue"
|
|
39
|
+
]);
|
|
40
|
+
return /*#__PURE__*/ _jsx("form", _extends({
|
|
41
|
+
ref: ref,
|
|
42
|
+
action: "/search",
|
|
43
|
+
method: "get",
|
|
44
|
+
role: "search"
|
|
45
|
+
}, rest, {
|
|
46
|
+
children: /*#__PURE__*/ _jsx(TextField, {
|
|
47
|
+
name: "q",
|
|
48
|
+
size: "small",
|
|
49
|
+
placeholder: placeholder || 'Search…',
|
|
50
|
+
defaultValue: defaultValue || '',
|
|
51
|
+
slotProps: {
|
|
52
|
+
input: {
|
|
53
|
+
endAdornment: /*#__PURE__*/ _jsx(InputAdornment, {
|
|
54
|
+
position: "end",
|
|
55
|
+
children: /*#__PURE__*/ _jsx(IconButton, {
|
|
56
|
+
type: "submit",
|
|
57
|
+
size: "small",
|
|
58
|
+
"aria-label": "search",
|
|
59
|
+
children: /*#__PURE__*/ _jsx(MdiIcon, {
|
|
60
|
+
path: mdiMagnify.path,
|
|
61
|
+
fontSize: "small"
|
|
62
|
+
})
|
|
63
|
+
})
|
|
64
|
+
})
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
}));
|
|
69
|
+
});
|
|
70
|
+
SearchBox.displayName = 'AglynSearchBox';
|
|
71
|
+
export const schema = {
|
|
72
|
+
$id: ID,
|
|
73
|
+
pluginId: BUNDLE_ID,
|
|
74
|
+
displayName: 'Search Box',
|
|
75
|
+
description: "A search field that opens the site's search page. It works without JavaScript.",
|
|
76
|
+
category: Aglyn.ComponentCategory.FORMS,
|
|
77
|
+
icon: {
|
|
78
|
+
path: mdiMagnify.path,
|
|
79
|
+
sx: {
|
|
80
|
+
color: '#455a64'
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
flags: {
|
|
84
|
+
selfClosing: Aglyn.FEATURE_FLAG.ENABLED
|
|
85
|
+
},
|
|
86
|
+
attributes: [
|
|
87
|
+
{
|
|
88
|
+
name: 'placeholder',
|
|
89
|
+
description: 'Placeholder text inside the search field.',
|
|
90
|
+
component: Aglyn.FieldComponentType.TEXT_FIELD,
|
|
91
|
+
label: 'Placeholder'
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
name: 'defaultValue',
|
|
95
|
+
description: 'Text the field starts with. The search results page fills in the ' + 'query it is showing.',
|
|
96
|
+
component: Aglyn.FieldComponentType.TEXT_FIELD,
|
|
97
|
+
label: 'Starting text'
|
|
98
|
+
}
|
|
99
|
+
]
|
|
100
|
+
};
|
|
101
|
+
export const presets = [
|
|
102
|
+
{
|
|
103
|
+
$id: generatePresetId(ID),
|
|
104
|
+
type: Aglyn.NodeType.PRESET,
|
|
105
|
+
displayName: 'Search Box',
|
|
106
|
+
pluginId: BUNDLE_ID,
|
|
107
|
+
description: 'Search field that opens the site search page',
|
|
108
|
+
category: Aglyn.ComponentCategory.FORMS,
|
|
109
|
+
icon: {
|
|
110
|
+
path: mdiMagnify.path,
|
|
111
|
+
sx: {
|
|
112
|
+
color: '#455a64'
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
data: {
|
|
116
|
+
$id: null,
|
|
117
|
+
componentId: ID,
|
|
118
|
+
pluginId: BUNDLE_ID,
|
|
119
|
+
props: {}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
];
|
|
123
|
+
export default SearchBox;
|
|
124
|
+
|
|
125
|
+
//# sourceMappingURL=search-box.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/components/search-box.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 IconButton from '@mui/material/IconButton'\nimport InputAdornment from '@mui/material/InputAdornment'\nimport TextField from '@mui/material/TextField'\nimport { MdiIcon } from '@aglyn/shared-ui-jsx'\nimport { forwardRef } from 'react'\nimport { BUNDLE_ID } from '../constants/bundle-common'\nimport { generatePresetId } from '../utils/generate-preset-id'\n\n// Component ids are persisted in screen documents; never rename.\nexport const ID: Aglyn.ComponentId = 'searchBox'\n\nexport interface SearchBoxProps {\n placeholder?: string\n /**\n * What the field starts with (AGL-2513). The results page prefills the\n * query it is showing, so a reader can refine it where they are rather\n * than going back for the box they typed into.\n *\n * Uncontrolled on purpose: this component holds no state and issues no\n * request, and a `value` would freeze the field the moment the reader\n * typed into it.\n */\n defaultValue?: string\n}\n\n/**\n * Site search box (AGL-88): a plain GET form to the tenant's /search page,\n * so it works with zero JavaScript and is inert in the besigner (the\n * console has no /search route to submit to; navigation there is a no-op\n * form post the editor never triggers).\n */\nconst SearchBox = forwardRef<HTMLFormElement, SearchBoxProps>(\n (props, ref) => {\n const { placeholder, defaultValue, ...rest } = props\n return (\n <form ref={ref} action=\"/search\" method=\"get\" role=\"search\" {...rest}>\n <TextField\n name=\"q\"\n size=\"small\"\n placeholder={placeholder || 'Search…'}\n defaultValue={defaultValue || ''}\n slotProps={{\n input: {\n endAdornment: (\n <InputAdornment position=\"end\">\n <IconButton type=\"submit\" size=\"small\" aria-label=\"search\">\n <MdiIcon path={mdiMagnify.path} fontSize=\"small\" />\n </IconButton>\n </InputAdornment>\n ),\n },\n }}\n />\n </form>\n )\n },\n)\nSearchBox.displayName = 'AglynSearchBox'\n\nexport const schema: Aglyn.ComponentSchema<SearchBoxProps> = {\n $id: ID,\n pluginId: BUNDLE_ID,\n displayName: 'Search Box',\n description:\n \"A search field that opens the site's search page. It works without JavaScript.\",\n category: Aglyn.ComponentCategory.FORMS,\n icon: { path: mdiMagnify.path, sx: { color: '#455a64' } },\n flags: { selfClosing: Aglyn.FEATURE_FLAG.ENABLED },\n attributes: [\n {\n name: 'placeholder',\n description: 'Placeholder text inside the search field.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n label: 'Placeholder',\n },\n {\n name: 'defaultValue',\n description:\n 'Text the field starts with. The search results page fills in the ' +\n 'query it is showing.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n label: 'Starting text',\n },\n ],\n}\n\nexport const presets: Aglyn.PresetSchema[] = [\n {\n $id: generatePresetId(ID),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Search Box',\n pluginId: BUNDLE_ID,\n description: 'Search field that opens the site search page',\n category: Aglyn.ComponentCategory.FORMS,\n icon: { path: mdiMagnify.path, sx: { color: '#455a64' } },\n data: {\n $id: null,\n componentId: ID,\n pluginId: BUNDLE_ID,\n props: {},\n },\n },\n]\n\nexport default SearchBox\n"],"names":["Aglyn","mdiMagnify","IconButton","InputAdornment","TextField","MdiIcon","forwardRef","BUNDLE_ID","generatePresetId","ID","SearchBox","props","ref","placeholder","defaultValue","rest","form","action","method","role","name","size","slotProps","input","endAdornment","position","type","aria-label","path","fontSize","displayName","schema","$id","pluginId","description","category","ComponentCategory","FORMS","icon","sx","color","flags","selfClosing","FEATURE_FLAG","ENABLED","attributes","component","FieldComponentType","TEXT_FIELD","label","presets","NodeType","PRESET","data","componentId"],"mappings":";;;AAAA;;;;;;;;;;;;;;;CAeC,GAED,YAAYA,WAAW,eAAc;AACrC,SAASC,UAAU,QAAQ,yBAAwB;AACnD,OAAOC,gBAAgB,2BAA0B;AACjD,OAAOC,oBAAoB,+BAA8B;AACzD,OAAOC,eAAe,0BAAyB;AAC/C,SAASC,OAAO,QAAQ,uBAAsB;AAC9C,SAASC,UAAU,QAAQ,QAAO;AAClC,SAASC,SAAS,QAAQ,gCAA4B;AACtD,SAASC,gBAAgB,QAAQ,iCAA6B;AAE9D,iEAAiE;AACjE,OAAO,MAAMC,KAAwB,YAAW;AAgBhD;;;;;CAKC,GACD,MAAMC,0BAAYJ,WAChB,CAACK,OAAOC;IACN,MAAM,EAAEC,WAAW,EAAEC,YAAY,EAAW,GAAGH,OAATI,wCAASJ;;;;IAC/C,qBACE,KAACK;QAAKJ,KAAKA;QAAKK,QAAO;QAAUC,QAAO;QAAMC,MAAK;OAAaJ;kBAC9D,cAAA,KAACX;YACCgB,MAAK;YACLC,MAAK;YACLR,aAAaA,eAAe;YAC5BC,cAAcA,gBAAgB;YAC9BQ,WAAW;gBACTC,OAAO;oBACLC,4BACE,KAACrB;wBAAesB,UAAS;kCACvB,cAAA,KAACvB;4BAAWwB,MAAK;4BAASL,MAAK;4BAAQM,cAAW;sCAChD,cAAA,KAACtB;gCAAQuB,MAAM3B,WAAW2B,IAAI;gCAAEC,UAAS;;;;gBAIjD;YACF;;;AAIR;AAEFnB,UAAUoB,WAAW,GAAG;AAExB,OAAO,MAAMC,SAAgD;IAC3DC,KAAKvB;IACLwB,UAAU1B;IACVuB,aAAa;IACbI,aACE;IACFC,UAAUnC,MAAMoC,iBAAiB,CAACC,KAAK;IACvCC,MAAM;QAAEV,MAAM3B,WAAW2B,IAAI;QAAEW,IAAI;YAAEC,OAAO;QAAU;IAAE;IACxDC,OAAO;QAAEC,aAAa1C,MAAM2C,YAAY,CAACC,OAAO;IAAC;IACjDC,YAAY;QACV;YACEzB,MAAM;YACNc,aAAa;YACbY,WAAW9C,MAAM+C,kBAAkB,CAACC,UAAU;YAC9CC,OAAO;QACT;QACA;YACE7B,MAAM;YACNc,aACE,sEACA;YACFY,WAAW9C,MAAM+C,kBAAkB,CAACC,UAAU;YAC9CC,OAAO;QACT;KACD;AACH,EAAC;AAED,OAAO,MAAMC,UAAgC;IAC3C;QACElB,KAAKxB,iBAAiBC;QACtBiB,MAAM1B,MAAMmD,QAAQ,CAACC,MAAM;QAC3BtB,aAAa;QACbG,UAAU1B;QACV2B,aAAa;QACbC,UAAUnC,MAAMoC,iBAAiB,CAACC,KAAK;QACvCC,MAAM;YAAEV,MAAM3B,WAAW2B,IAAI;YAAEW,IAAI;gBAAEC,OAAO;YAAU;QAAE;QACxDa,MAAM;YACJrB,KAAK;YACLsB,aAAa7C;YACbwB,UAAU1B;YACVI,OAAO,CAAC;QACV;IACF;CACD,CAAA;AAED,eAAeD,UAAS"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
import * as Aglyn from '@aglyn/aglyn';
|
|
18
|
+
export declare const ID: Aglyn.ComponentId;
|
|
19
|
+
/**
|
|
20
|
+
* W3C sectioning/grouping elements the component may render as (AGL-336).
|
|
21
|
+
*
|
|
22
|
+
* ⛔ `main` IS NOT ONE OF THEM (AGL-2486). A published page carries exactly
|
|
23
|
+
* one `main` landmark, placed by composition on the page's content region —
|
|
24
|
+
* the layout's slot, or the screen root when there is no layout, each of which
|
|
25
|
+
* offers its own element picker. An author-selectable `main` on a grouping
|
|
26
|
+
* container that may appear any number of times per page could only ever
|
|
27
|
+
* produce a SECOND one — and two `main` elements is a worse
|
|
28
|
+
* accessibility outcome than none, because the landmark stops naming anything
|
|
29
|
+
* in particular. It was offered in this select, with field help recommending
|
|
30
|
+
* it, which made the duplicate the documented choice rather than a mistake.
|
|
31
|
+
*
|
|
32
|
+
* Removing it degrades rather than breaks: the resolver below falls back to
|
|
33
|
+
* `section` for any value not in this list, so a stored `element: 'main'` on a
|
|
34
|
+
* published screen renders as `<section>` — still a grouping element, still
|
|
35
|
+
* where the author put it, and no longer competing with the layout's landmark.
|
|
36
|
+
*/
|
|
37
|
+
export declare const SECTION_ELEMENTS: readonly ["section", "div", "article", "aside", "nav", "header", "footer"];
|
|
38
|
+
export type SectionElement = (typeof SECTION_ELEMENTS)[number];
|
|
39
|
+
export interface SectionProps {
|
|
40
|
+
/** The DOM element rendered; defaults to `section`. */
|
|
41
|
+
element?: SectionElement;
|
|
42
|
+
/** Accessible name announced for landmark elements. */
|
|
43
|
+
ariaLabel?: string;
|
|
44
|
+
children?: JSX.Children;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Semantic grouping container (AGL-336): renders children inside the
|
|
48
|
+
* chosen W3C element so pages keep meaningful document structure
|
|
49
|
+
* (landmarks for assistive tech, better SEO outlines) instead of
|
|
50
|
+
* div-soup. Behaves like any container: droppable, stylable via sx,
|
|
51
|
+
* classes, and interactions.
|
|
52
|
+
*/
|
|
53
|
+
declare const Section: import("react").ForwardRefExoticComponent<SectionProps & import("react").RefAttributes<HTMLElement>>;
|
|
54
|
+
export declare const schema: Aglyn.ComponentSchema<SectionProps>;
|
|
55
|
+
export declare const presets: Aglyn.PresetSchema[];
|
|
56
|
+
export default Section;
|