@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.
Files changed (177) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +22 -0
  3. package/package.json +47 -0
  4. package/src/index.d.ts +21 -0
  5. package/src/index.js +22 -0
  6. package/src/index.js.map +1 -0
  7. package/src/lib/components/accordion.d.ts +96 -0
  8. package/src/lib/components/accordion.js +392 -0
  9. package/src/lib/components/accordion.js.map +1 -0
  10. package/src/lib/components/app-bar.d.ts +32 -0
  11. package/src/lib/components/app-bar.js +86 -0
  12. package/src/lib/components/app-bar.js.map +1 -0
  13. package/src/lib/components/blocks.d.ts +46 -0
  14. package/src/lib/components/blocks.js +1007 -0
  15. package/src/lib/components/blocks.js.map +1 -0
  16. package/src/lib/components/box.d.ts +47 -0
  17. package/src/lib/components/box.js +125 -0
  18. package/src/lib/components/box.js.map +1 -0
  19. package/src/lib/components/breadcrumbs.d.ts +44 -0
  20. package/src/lib/components/breadcrumbs.js +172 -0
  21. package/src/lib/components/breadcrumbs.js.map +1 -0
  22. package/src/lib/components/button.d.ts +89 -0
  23. package/src/lib/components/button.js +272 -0
  24. package/src/lib/components/button.js.map +1 -0
  25. package/src/lib/components/card.d.ts +61 -0
  26. package/src/lib/components/card.js +336 -0
  27. package/src/lib/components/card.js.map +1 -0
  28. package/src/lib/components/collection.d.ts +514 -0
  29. package/src/lib/components/collection.js +2999 -0
  30. package/src/lib/components/collection.js.map +1 -0
  31. package/src/lib/components/container.d.ts +42 -0
  32. package/src/lib/components/container.js +169 -0
  33. package/src/lib/components/container.js.map +1 -0
  34. package/src/lib/components/custom-html.d.ts +78 -0
  35. package/src/lib/components/custom-html.js +219 -0
  36. package/src/lib/components/custom-html.js.map +1 -0
  37. package/src/lib/components/data-table.d.ts +57 -0
  38. package/src/lib/components/data-table.js +216 -0
  39. package/src/lib/components/data-table.js.map +1 -0
  40. package/src/lib/components/document-root.d.ts +77 -0
  41. package/src/lib/components/document-root.js +118 -0
  42. package/src/lib/components/document-root.js.map +1 -0
  43. package/src/lib/components/drawer.d.ts +93 -0
  44. package/src/lib/components/drawer.js +566 -0
  45. package/src/lib/components/drawer.js.map +1 -0
  46. package/src/lib/components/function-controls.d.ts +66 -0
  47. package/src/lib/components/function-controls.js +207 -0
  48. package/src/lib/components/function-controls.js.map +1 -0
  49. package/src/lib/components/function-scope.d.ts +110 -0
  50. package/src/lib/components/function-scope.js +478 -0
  51. package/src/lib/components/function-scope.js.map +1 -0
  52. package/src/lib/components/function-widget.d.ts +75 -0
  53. package/src/lib/components/function-widget.js +307 -0
  54. package/src/lib/components/function-widget.js.map +1 -0
  55. package/src/lib/components/grid.d.ts +91 -0
  56. package/src/lib/components/grid.js +322 -0
  57. package/src/lib/components/grid.js.map +1 -0
  58. package/src/lib/components/icon.d.ts +54 -0
  59. package/src/lib/components/icon.js +163 -0
  60. package/src/lib/components/icon.js.map +1 -0
  61. package/src/lib/components/image-list.d.ts +58 -0
  62. package/src/lib/components/image-list.js +336 -0
  63. package/src/lib/components/image-list.js.map +1 -0
  64. package/src/lib/components/image.d.ts +154 -0
  65. package/src/lib/components/image.js +451 -0
  66. package/src/lib/components/image.js.map +1 -0
  67. package/src/lib/components/inline-text.d.ts +74 -0
  68. package/src/lib/components/inline-text.js +407 -0
  69. package/src/lib/components/inline-text.js.map +1 -0
  70. package/src/lib/components/language-switcher.d.ts +35 -0
  71. package/src/lib/components/language-switcher.js +179 -0
  72. package/src/lib/components/language-switcher.js.map +1 -0
  73. package/src/lib/components/layout-slot.d.ts +68 -0
  74. package/src/lib/components/layout-slot.js +192 -0
  75. package/src/lib/components/layout-slot.js.map +1 -0
  76. package/src/lib/components/link-box-accessible-name.d.ts +79 -0
  77. package/src/lib/components/link-box-accessible-name.js +158 -0
  78. package/src/lib/components/link-box-accessible-name.js.map +1 -0
  79. package/src/lib/components/link-box.d.ts +66 -0
  80. package/src/lib/components/link-box.js +212 -0
  81. package/src/lib/components/link-box.js.map +1 -0
  82. package/src/lib/components/list-item-text.d.ts +22 -0
  83. package/src/lib/components/list-item-text.js +86 -0
  84. package/src/lib/components/list-item-text.js.map +1 -0
  85. package/src/lib/components/list-item.d.ts +32 -0
  86. package/src/lib/components/list-item.js +127 -0
  87. package/src/lib/components/list-item.js.map +1 -0
  88. package/src/lib/components/list.d.ts +34 -0
  89. package/src/lib/components/list.js +108 -0
  90. package/src/lib/components/list.js.map +1 -0
  91. package/src/lib/components/markdown.d.ts +129 -0
  92. package/src/lib/components/markdown.js +853 -0
  93. package/src/lib/components/markdown.js.map +1 -0
  94. package/src/lib/components/nav-menu.d.ts +68 -0
  95. package/src/lib/components/nav-menu.js +683 -0
  96. package/src/lib/components/nav-menu.js.map +1 -0
  97. package/src/lib/components/pagination.d.ts +59 -0
  98. package/src/lib/components/pagination.js +243 -0
  99. package/src/lib/components/pagination.js.map +1 -0
  100. package/src/lib/components/paper.d.ts +47 -0
  101. package/src/lib/components/paper.js +202 -0
  102. package/src/lib/components/paper.js.map +1 -0
  103. package/src/lib/components/plugin-frame.d.ts +64 -0
  104. package/src/lib/components/plugin-frame.js +335 -0
  105. package/src/lib/components/plugin-frame.js.map +1 -0
  106. package/src/lib/components/plugin.d.ts +95 -0
  107. package/src/lib/components/plugin.js +304 -0
  108. package/src/lib/components/plugin.js.map +1 -0
  109. package/src/lib/components/product.d.ts +40 -0
  110. package/src/lib/components/product.js +287 -0
  111. package/src/lib/components/product.js.map +1 -0
  112. package/src/lib/components/reusable-instance.d.ts +57 -0
  113. package/src/lib/components/reusable-instance.js +126 -0
  114. package/src/lib/components/reusable-instance.js.map +1 -0
  115. package/src/lib/components/screen-link.d.ts +85 -0
  116. package/src/lib/components/screen-link.js +324 -0
  117. package/src/lib/components/screen-link.js.map +1 -0
  118. package/src/lib/components/search-box.d.ts +41 -0
  119. package/src/lib/components/search-box.js +125 -0
  120. package/src/lib/components/search-box.js.map +1 -0
  121. package/src/lib/components/section.d.ts +56 -0
  122. package/src/lib/components/section.js +132 -0
  123. package/src/lib/components/section.js.map +1 -0
  124. package/src/lib/components/stack.d.ts +55 -0
  125. package/src/lib/components/stack.js +309 -0
  126. package/src/lib/components/stack.js.map +1 -0
  127. package/src/lib/components/tabs.d.ts +288 -0
  128. package/src/lib/components/tabs.js +788 -0
  129. package/src/lib/components/tabs.js.map +1 -0
  130. package/src/lib/components/theme-mode-switcher.d.ts +38 -0
  131. package/src/lib/components/theme-mode-switcher.js +168 -0
  132. package/src/lib/components/theme-mode-switcher.js.map +1 -0
  133. package/src/lib/components/toolbar.d.ts +37 -0
  134. package/src/lib/components/toolbar.js +117 -0
  135. package/src/lib/components/toolbar.js.map +1 -0
  136. package/src/lib/components/typography.d.ts +33 -0
  137. package/src/lib/components/typography.js +433 -0
  138. package/src/lib/components/typography.js.map +1 -0
  139. package/src/lib/components/video-lightbox-controls.d.ts +131 -0
  140. package/src/lib/components/video-lightbox-controls.js +536 -0
  141. package/src/lib/components/video-lightbox-controls.js.map +1 -0
  142. package/src/lib/components/video-lightbox.d.ts +60 -0
  143. package/src/lib/components/video-lightbox.js +247 -0
  144. package/src/lib/components/video-lightbox.js.map +1 -0
  145. package/src/lib/components/video-playback-beacon.d.ts +80 -0
  146. package/src/lib/components/video-playback-beacon.js +128 -0
  147. package/src/lib/components/video-playback-beacon.js.map +1 -0
  148. package/src/lib/components/video-player-frame.d.ts +58 -0
  149. package/src/lib/components/video-player-frame.js +51 -0
  150. package/src/lib/components/video-player-frame.js.map +1 -0
  151. package/src/lib/components/video.d.ts +220 -0
  152. package/src/lib/components/video.js +874 -0
  153. package/src/lib/components/video.js.map +1 -0
  154. package/src/lib/constants/bundle-common.d.ts +17 -0
  155. package/src/lib/constants/bundle-common.js +18 -0
  156. package/src/lib/constants/bundle-common.js.map +1 -0
  157. package/src/lib/constants/field-presets.d.ts +93 -0
  158. package/src/lib/constants/field-presets.js +248 -0
  159. package/src/lib/constants/field-presets.js.map +1 -0
  160. package/src/lib/plugin.d.ts +80 -0
  161. package/src/lib/plugin.js +599 -0
  162. package/src/lib/plugin.js.map +1 -0
  163. package/src/lib/utils/author-html-label.d.ts +73 -0
  164. package/src/lib/utils/author-html-label.js +89 -0
  165. package/src/lib/utils/author-html-label.js.map +1 -0
  166. package/src/lib/utils/drop-cleared-props.d.ts +18 -0
  167. package/src/lib/utils/drop-cleared-props.js +74 -0
  168. package/src/lib/utils/drop-cleared-props.js.map +1 -0
  169. package/src/lib/utils/element-picker.d.ts +99 -0
  170. package/src/lib/utils/element-picker.js +140 -0
  171. package/src/lib/utils/element-picker.js.map +1 -0
  172. package/src/lib/utils/generate-preset-id.d.ts +19 -0
  173. package/src/lib/utils/generate-preset-id.js +25 -0
  174. package/src/lib/utils/generate-preset-id.js.map +1 -0
  175. package/src/lib/utils/link-target-props.d.ts +53 -0
  176. package/src/lib/utils/link-target-props.js +53 -0
  177. package/src/lib/utils/link-target-props.js.map +1 -0
@@ -0,0 +1,73 @@
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 type { ReactNode } from 'react';
18
+ /**
19
+ * The formatted label of a CONTROL — a Button, a Screen Link, an Accordion
20
+ * Summary (AGL-2557).
21
+ *
22
+ * ## The three parts that have to travel together
23
+ *
24
+ * The inline editor's rich mode commits sanitized markup into an `html` prop
25
+ * and keeps `children` as the plain-text fallback. Until this existed,
26
+ * `typography.tsx` was the only component that read `html` back, so setting
27
+ * the editor's flag anywhere else would have shipped a toolbar whose output
28
+ * was discarded: bold while typing, plain the moment it committed. A
29
+ * component earns the flag by declaring the prop, rendering it through here,
30
+ * and only then turning the flag on.
31
+ *
32
+ * ## Sanitized on EVERY render (AGL-497)
33
+ *
34
+ * The editor sanitizes at commit, and that is not where the guarantee comes
35
+ * from. Screen node props are written straight through the Firebase client
36
+ * SDK, so a host editor can plant arbitrary `html` on a node without the
37
+ * editor ever seeing it — and it would then execute on the published site
38
+ * AND on the besigner canvas at app.aglyn.com. `sanitizeAuthorHtml` is pure
39
+ * and needs no DOM (AGL-1901), so the server and the first client render
40
+ * compute the same bytes and hydration is clean by construction.
41
+ *
42
+ * ## Why the narrowed allowlist
43
+ *
44
+ * A control's content model is phrasing content with no interactive
45
+ * descendant, so this passes {@link Aglyn.INLINE_AUTHOR_HTML_ELEMENTS}: no
46
+ * lists, no blocks, no nested anchor. That is a rendering requirement, not a
47
+ * tidiness one — the parser closes a `<button>` on a `<div>` start tag and
48
+ * promotes the rest to a sibling, which is a React hydration mismatch on the
49
+ * tenant. The toolbar declines to OFFER those commands for these components
50
+ * (`richTextCommands`), and this is what holds the line for markup that
51
+ * arrived some other way.
52
+ *
53
+ * ## Why `<aglyn-text>` and not a `<span>`
54
+ *
55
+ * The canvas edits a leaf's own `<aglyn-text>` when it renders one, and
56
+ * falls back to the leaf root otherwise (AGL-2556). For a composite like
57
+ * Accordion Summary the root is the `<button>`, and in-place editing EMPTIES
58
+ * whatever it is handed — which would take MUI's content wrapper, and its
59
+ * `textAlign: 'start'`, with it for the length of the edit. Rendering the
60
+ * formatted label into the same element the plain label uses keeps one edit
61
+ * target for both modes.
62
+ */
63
+ export declare function authorHtmlLabel(html: unknown): ReactNode | null;
64
+ /**
65
+ * `props` with the formatted label substituted for its children, or `props`
66
+ * itself when the node carries no `html`.
67
+ *
68
+ * Returned BY IDENTITY in the unformatted case, which is the overwhelmingly
69
+ * common one — a Screen Link is the busiest element on a published page at
70
+ * 70–77 nodes — so an element nobody has formatted allocates nothing and
71
+ * renders the tree it always did.
72
+ */
73
+ export declare function withAuthorHtmlLabel<P extends object>(props: P, html: unknown): P;
@@ -0,0 +1,89 @@
1
+ import { _ as _extends } from "@swc/helpers/_/_extends";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ /**
4
+ * @license
5
+ * Copyright 2026 Aglyn LLC
6
+ *
7
+ * Licensed under the Apache License, Version 2.0 (the "License");
8
+ * you may not use this file except in compliance with the License.
9
+ * You may obtain a copy of the License at
10
+ *
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ */ import * as Aglyn from "@aglyn/aglyn";
19
+ import { AglynText } from "@aglyn/shared-ui-jsx";
20
+ /**
21
+ * The formatted label of a CONTROL — a Button, a Screen Link, an Accordion
22
+ * Summary (AGL-2557).
23
+ *
24
+ * ## The three parts that have to travel together
25
+ *
26
+ * The inline editor's rich mode commits sanitized markup into an `html` prop
27
+ * and keeps `children` as the plain-text fallback. Until this existed,
28
+ * `typography.tsx` was the only component that read `html` back, so setting
29
+ * the editor's flag anywhere else would have shipped a toolbar whose output
30
+ * was discarded: bold while typing, plain the moment it committed. A
31
+ * component earns the flag by declaring the prop, rendering it through here,
32
+ * and only then turning the flag on.
33
+ *
34
+ * ## Sanitized on EVERY render (AGL-497)
35
+ *
36
+ * The editor sanitizes at commit, and that is not where the guarantee comes
37
+ * from. Screen node props are written straight through the Firebase client
38
+ * SDK, so a host editor can plant arbitrary `html` on a node without the
39
+ * editor ever seeing it — and it would then execute on the published site
40
+ * AND on the besigner canvas at app.aglyn.com. `sanitizeAuthorHtml` is pure
41
+ * and needs no DOM (AGL-1901), so the server and the first client render
42
+ * compute the same bytes and hydration is clean by construction.
43
+ *
44
+ * ## Why the narrowed allowlist
45
+ *
46
+ * A control's content model is phrasing content with no interactive
47
+ * descendant, so this passes {@link Aglyn.INLINE_AUTHOR_HTML_ELEMENTS}: no
48
+ * lists, no blocks, no nested anchor. That is a rendering requirement, not a
49
+ * tidiness one — the parser closes a `<button>` on a `<div>` start tag and
50
+ * promotes the rest to a sibling, which is a React hydration mismatch on the
51
+ * tenant. The toolbar declines to OFFER those commands for these components
52
+ * (`richTextCommands`), and this is what holds the line for markup that
53
+ * arrived some other way.
54
+ *
55
+ * ## Why `<aglyn-text>` and not a `<span>`
56
+ *
57
+ * The canvas edits a leaf's own `<aglyn-text>` when it renders one, and
58
+ * falls back to the leaf root otherwise (AGL-2556). For a composite like
59
+ * Accordion Summary the root is the `<button>`, and in-place editing EMPTIES
60
+ * whatever it is handed — which would take MUI's content wrapper, and its
61
+ * `textAlign: 'start'`, with it for the length of the edit. Rendering the
62
+ * formatted label into the same element the plain label uses keeps one edit
63
+ * target for both modes.
64
+ */ export function authorHtmlLabel(html) {
65
+ if (typeof html !== 'string' || !html) return null;
66
+ return /*#__PURE__*/ _jsx(AglynText, {
67
+ dangerouslySetInnerHTML: {
68
+ __html: Aglyn.sanitizeAuthorHtml(html, undefined, {
69
+ allowedElements: Aglyn.INLINE_AUTHOR_HTML_ELEMENTS
70
+ })
71
+ }
72
+ });
73
+ }
74
+ /**
75
+ * `props` with the formatted label substituted for its children, or `props`
76
+ * itself when the node carries no `html`.
77
+ *
78
+ * Returned BY IDENTITY in the unformatted case, which is the overwhelmingly
79
+ * common one — a Screen Link is the busiest element on a published page at
80
+ * 70–77 nodes — so an element nobody has formatted allocates nothing and
81
+ * renders the tree it always did.
82
+ */ export function withAuthorHtmlLabel(props, html) {
83
+ const label = authorHtmlLabel(html);
84
+ return label ? _extends({}, props, {
85
+ children: label
86
+ }) : props;
87
+ }
88
+
89
+ //# sourceMappingURL=author-html-label.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/utils/author-html-label.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 { AglynText } from '@aglyn/shared-ui-jsx'\nimport type { ReactNode } from 'react'\n\n/**\n * The formatted label of a CONTROL — a Button, a Screen Link, an Accordion\n * Summary (AGL-2557).\n *\n * ## The three parts that have to travel together\n *\n * The inline editor's rich mode commits sanitized markup into an `html` prop\n * and keeps `children` as the plain-text fallback. Until this existed,\n * `typography.tsx` was the only component that read `html` back, so setting\n * the editor's flag anywhere else would have shipped a toolbar whose output\n * was discarded: bold while typing, plain the moment it committed. A\n * component earns the flag by declaring the prop, rendering it through here,\n * and only then turning the flag on.\n *\n * ## Sanitized on EVERY render (AGL-497)\n *\n * The editor sanitizes at commit, and that is not where the guarantee comes\n * from. Screen node props are written straight through the Firebase client\n * SDK, so a host editor can plant arbitrary `html` on a node without the\n * editor ever seeing it — and it would then execute on the published site\n * AND on the besigner canvas at app.aglyn.com. `sanitizeAuthorHtml` is pure\n * and needs no DOM (AGL-1901), so the server and the first client render\n * compute the same bytes and hydration is clean by construction.\n *\n * ## Why the narrowed allowlist\n *\n * A control's content model is phrasing content with no interactive\n * descendant, so this passes {@link Aglyn.INLINE_AUTHOR_HTML_ELEMENTS}: no\n * lists, no blocks, no nested anchor. That is a rendering requirement, not a\n * tidiness one — the parser closes a `<button>` on a `<div>` start tag and\n * promotes the rest to a sibling, which is a React hydration mismatch on the\n * tenant. The toolbar declines to OFFER those commands for these components\n * (`richTextCommands`), and this is what holds the line for markup that\n * arrived some other way.\n *\n * ## Why `<aglyn-text>` and not a `<span>`\n *\n * The canvas edits a leaf's own `<aglyn-text>` when it renders one, and\n * falls back to the leaf root otherwise (AGL-2556). For a composite like\n * Accordion Summary the root is the `<button>`, and in-place editing EMPTIES\n * whatever it is handed — which would take MUI's content wrapper, and its\n * `textAlign: 'start'`, with it for the length of the edit. Rendering the\n * formatted label into the same element the plain label uses keeps one edit\n * target for both modes.\n */\nexport function authorHtmlLabel(html: unknown): ReactNode | null {\n if (typeof html !== 'string' || !html) return null\n return (\n <AglynText\n dangerouslySetInnerHTML={{\n __html: Aglyn.sanitizeAuthorHtml(html, undefined, {\n allowedElements: Aglyn.INLINE_AUTHOR_HTML_ELEMENTS,\n }),\n }}\n />\n )\n}\n\n/**\n * `props` with the formatted label substituted for its children, or `props`\n * itself when the node carries no `html`.\n *\n * Returned BY IDENTITY in the unformatted case, which is the overwhelmingly\n * common one — a Screen Link is the busiest element on a published page at\n * 70–77 nodes — so an element nobody has formatted allocates nothing and\n * renders the tree it always did.\n */\nexport function withAuthorHtmlLabel<P extends object>(\n props: P,\n html: unknown,\n): P {\n const label = authorHtmlLabel(html)\n return label ? ({ ...props, children: label } as P) : props\n}\n"],"names":["Aglyn","AglynText","authorHtmlLabel","html","dangerouslySetInnerHTML","__html","sanitizeAuthorHtml","undefined","allowedElements","INLINE_AUTHOR_HTML_ELEMENTS","withAuthorHtmlLabel","props","label","children"],"mappings":";;AAAA;;;;;;;;;;;;;;;CAeC,GAED,YAAYA,WAAW,eAAc;AACrC,SAASC,SAAS,QAAQ,uBAAsB;AAGhD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4CC,GACD,OAAO,SAASC,gBAAgBC,IAAa;IAC3C,IAAI,OAAOA,SAAS,YAAY,CAACA,MAAM,OAAO;IAC9C,qBACE,KAACF;QACCG,yBAAyB;YACvBC,QAAQL,MAAMM,kBAAkB,CAACH,MAAMI,WAAW;gBAChDC,iBAAiBR,MAAMS,2BAA2B;YACpD;QACF;;AAGN;AAEA;;;;;;;;CAQC,GACD,OAAO,SAASC,oBACdC,KAAQ,EACRR,IAAa;IAEb,MAAMS,QAAQV,gBAAgBC;IAC9B,OAAOS,QAAS,aAAKD;QAAOE,UAAUD;SAAgBD;AACxD"}
@@ -0,0 +1,18 @@
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
+ export declare function dropClearedProps<T extends Record<string, any>>(props: T): T;
18
+ export default dropClearedProps;
@@ -0,0 +1,74 @@
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
+ * Drops props an author CLEARED, so MUI's own defaults apply (AGL-1226).
18
+ *
19
+ * The besigner persists a cleared attribute as `null` (or `''`), and React
20
+ * only falls back to a default for `undefined` — an explicit `null` is a
21
+ * value. So `<Button color={null}>` does NOT become `color="primary"`; the
22
+ * null travels all the way into MUI, which builds its class names with
23
+ * `` `color${capitalize(color)}` `` and throws:
24
+ *
25
+ * Minified MUI error #7 — capitalize(string) expects a string argument
26
+ *
27
+ * That is a SERVER-SIDE THROW during render, so the whole page 500s. It took
28
+ * down every `/product/*` page on the public marketing site, uncached
29
+ * (`x-vercel-cache: MISS` every time), for as long as one button carried a
30
+ * cleared colour.
31
+ *
32
+ * Stripping the key instead is what the author meant by clearing it: fall
33
+ * back to the component's default. Applied at the wrapper boundary rather
34
+ * than fixing the two offending documents, because a data fix leaves every
35
+ * other site one cleared dropdown away from the same 500.
36
+ *
37
+ * `0` and `false` are kept — those are real values an author can mean.
38
+ *
39
+ * `data-*` and `aria-*` are kept whatever their value. Only an authored
40
+ * ATTRIBUTE can be cleared, and neither of those is one: they are stamped by
41
+ * the renderer, and the canvas writes its flags PRESENCE-BASED — `''` for on,
42
+ * `undefined` for off — which is the same empty string a cleared select
43
+ * persists as. Dropping them took out every presence flag on every component
44
+ * that funnels through here: `data-aglyn-revealed`, so a panel carrying the
45
+ * hidden class could never be shown for designing; `data-aglyn-selected-within`,
46
+ * which is how a nav menu and a drawer know to open while they are being
47
+ * authored; and `data-aglyn-bound`, the outline on an element whose props
48
+ * carry bindings. They are also incapable of the crash above — both go
49
+ * straight to the DOM, where an empty attribute is ordinary HTML and nothing
50
+ * calls `capitalize()` on the value.
51
+ */ function isRendererAttribute(key) {
52
+ return key.startsWith('data-') || key.startsWith('aria-');
53
+ }
54
+ export function dropClearedProps(props) {
55
+ let cleared = false;
56
+ for(const key in props){
57
+ const value = props[key];
58
+ if ((value === null || value === '') && !isRendererAttribute(key)) {
59
+ cleared = true;
60
+ break;
61
+ }
62
+ }
63
+ if (!cleared) return props;
64
+ const next = {};
65
+ for(const key in props){
66
+ const value = props[key];
67
+ if ((value === null || value === '') && !isRendererAttribute(key)) continue;
68
+ next[key] = value;
69
+ }
70
+ return next;
71
+ }
72
+ export default dropClearedProps;
73
+
74
+ //# sourceMappingURL=drop-cleared-props.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/utils/drop-cleared-props.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Drops props an author CLEARED, so MUI's own defaults apply (AGL-1226).\n *\n * The besigner persists a cleared attribute as `null` (or `''`), and React\n * only falls back to a default for `undefined` — an explicit `null` is a\n * value. So `<Button color={null}>` does NOT become `color=\"primary\"`; the\n * null travels all the way into MUI, which builds its class names with\n * `` `color${capitalize(color)}` `` and throws:\n *\n * Minified MUI error #7 — capitalize(string) expects a string argument\n *\n * That is a SERVER-SIDE THROW during render, so the whole page 500s. It took\n * down every `/product/*` page on the public marketing site, uncached\n * (`x-vercel-cache: MISS` every time), for as long as one button carried a\n * cleared colour.\n *\n * Stripping the key instead is what the author meant by clearing it: fall\n * back to the component's default. Applied at the wrapper boundary rather\n * than fixing the two offending documents, because a data fix leaves every\n * other site one cleared dropdown away from the same 500.\n *\n * `0` and `false` are kept — those are real values an author can mean.\n *\n * `data-*` and `aria-*` are kept whatever their value. Only an authored\n * ATTRIBUTE can be cleared, and neither of those is one: they are stamped by\n * the renderer, and the canvas writes its flags PRESENCE-BASED — `''` for on,\n * `undefined` for off — which is the same empty string a cleared select\n * persists as. Dropping them took out every presence flag on every component\n * that funnels through here: `data-aglyn-revealed`, so a panel carrying the\n * hidden class could never be shown for designing; `data-aglyn-selected-within`,\n * which is how a nav menu and a drawer know to open while they are being\n * authored; and `data-aglyn-bound`, the outline on an element whose props\n * carry bindings. They are also incapable of the crash above — both go\n * straight to the DOM, where an empty attribute is ordinary HTML and nothing\n * calls `capitalize()` on the value.\n */\nfunction isRendererAttribute(key: string): boolean {\n return key.startsWith('data-') || key.startsWith('aria-')\n}\n\nexport function dropClearedProps<T extends Record<string, any>>(props: T): T {\n let cleared = false\n for (const key in props) {\n const value = props[key]\n if ((value === null || value === '') && !isRendererAttribute(key)) {\n cleared = true\n break\n }\n }\n if (!cleared) return props\n const next: Record<string, any> = {}\n for (const key in props) {\n const value = props[key]\n if ((value === null || value === '') && !isRendererAttribute(key)) continue\n next[key] = value\n }\n return next as T\n}\n\nexport default dropClearedProps\n"],"names":["isRendererAttribute","key","startsWith","dropClearedProps","props","cleared","value","next"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmCC,GACD,SAASA,oBAAoBC,GAAW;IACtC,OAAOA,IAAIC,UAAU,CAAC,YAAYD,IAAIC,UAAU,CAAC;AACnD;AAEA,OAAO,SAASC,iBAAgDC,KAAQ;IACtE,IAAIC,UAAU;IACd,IAAK,MAAMJ,OAAOG,MAAO;QACvB,MAAME,QAAQF,KAAK,CAACH,IAAI;QACxB,IAAI,AAACK,CAAAA,UAAU,QAAQA,UAAU,EAAC,KAAM,CAACN,oBAAoBC,MAAM;YACjEI,UAAU;YACV;QACF;IACF;IACA,IAAI,CAACA,SAAS,OAAOD;IACrB,MAAMG,OAA4B,CAAC;IACnC,IAAK,MAAMN,OAAOG,MAAO;QACvB,MAAME,QAAQF,KAAK,CAACH,IAAI;QACxB,IAAI,AAACK,CAAAA,UAAU,QAAQA,UAAU,EAAC,KAAM,CAACN,oBAAoBC,MAAM;QACnEM,IAAI,CAACN,IAAI,GAAGK;IACd;IACA,OAAOC;AACT;AAEA,eAAeJ,iBAAgB"}
@@ -0,0 +1,99 @@
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
+ /**
19
+ * THE ELEMENT PICKER EVERY CONTAINER GETS (AGL-2525).
20
+ *
21
+ * Section owned the semantic elements alone, so an author who wanted their nav
22
+ * row to BE the `nav` had to wrap it in a second element to say so — and on
23
+ * `aglyn.com` nobody did, which is why the published page had no navigation
24
+ * landmark at all. Wrapping to name a thing is the same shape of
25
+ * element-nobody-authored that AGL-2521 removed from component placements,
26
+ * arriving by a different route.
27
+ *
28
+ * ⛔ `main` IS NOT ON THIS LIST. A page carries exactly one, placed by
29
+ * `stampDocumentLandmark` on the Document layer or the Layout Slot — the two
30
+ * nodes that appear at most once per document. Everything using this picker can
31
+ * be placed any number of times, so an author-selected `main` here could only
32
+ * ever be the second one.
33
+ *
34
+ * An allow-list rather than free text: the value is persisted and rendered
35
+ * verbatim, so a typed one would put `script` into every visitor's page.
36
+ */
37
+ export declare const SEMANTIC_ELEMENTS: readonly ["div", "section", "article", "aside", "nav", "header", "footer"];
38
+ export type SemanticElement = (typeof SEMANTIC_ELEMENTS)[number];
39
+ /**
40
+ * The element to render, or `undefined` to leave the component's own default
41
+ * alone.
42
+ *
43
+ * Returning `undefined` rather than `'div'` is what lets this be added to a
44
+ * component that does NOT default to a div — App Bar renders `header` unless
45
+ * told otherwise, and a resolver that answered `'div'` for "unset" would have
46
+ * silently stripped the banner landmark off every site's chrome the moment the
47
+ * picker appeared.
48
+ */
49
+ export declare function resolveSemanticElement(value: unknown): SemanticElement | undefined;
50
+ /**
51
+ * The elements that BECOME a landmark, and so want a name (AGL-2525).
52
+ *
53
+ * `div` is the odd one out: it has no role, so an `aria-label` on it names
54
+ * nothing. Everything else is announced as a region, and a page with two of
55
+ * the same kind — a header nav and a footer nav, say — is a page where
56
+ * "navigation, navigation" is all a screen-reader user hears without one.
57
+ */
58
+ export declare const LANDMARK_ELEMENTS: ("article" | "aside" | "footer" | "header" | "nav" | "section")[];
59
+ /**
60
+ * Consume the picker's props and return what the underlying MUI component
61
+ * should receive.
62
+ *
63
+ * Takes the whole props bag rather than one value because both keys have to
64
+ * be REMOVED as well as translated: `ariaLabel` spread onto a DOM element is
65
+ * an unknown React prop, warned about on the canvas and serialized onto the
66
+ * published page, which is the shape of the `propValues` leak in AGL-2486.
67
+ */
68
+ export declare function applySemanticElement<P extends Record<string, unknown>>(props: P): Omit<P, 'component' | 'ariaLabel'> & {
69
+ component?: SemanticElement;
70
+ 'aria-label'?: string;
71
+ };
72
+ /**
73
+ * Spreadable `component` prop: present only when the author chose one, so an
74
+ * unset picker is indistinguishable from never having had one.
75
+ */
76
+ export declare function semanticElementProp(value: unknown): {
77
+ component?: SemanticElement;
78
+ };
79
+ /**
80
+ * The attribute schema. `subject` names what renders, e.g. "this stack".
81
+ *
82
+ * Labelled `Component`, the name Box, Typography, the Document layer and the
83
+ * Layout Slot already use — Section and Inline text keep `element` as their
84
+ * stored KEY because their values are persisted in published screens, but the
85
+ * panel says one thing everywhere (AGL-2514).
86
+ */
87
+ export declare function semanticElementAttribute(subject: string): Aglyn.AglynAttributeSchema;
88
+ /**
89
+ * The name for the landmark the picker just made, shown only once one exists.
90
+ *
91
+ * Gated on the element rather than always visible because on a `div` — the
92
+ * default, and what most of these elements stay — the field would do nothing
93
+ * at all, and a control that silently does nothing is worse than no control.
94
+ *
95
+ * This is the half Section already had and the picker did not. Naming stops
96
+ * being optional the moment a page has two landmarks of a kind: a site nav and
97
+ * a footer nav both announce as "navigation" until one of them says which.
98
+ */
99
+ export declare function semanticElementLabelAttribute(): Aglyn.AglynAttributeSchema;
@@ -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
+ /**
4
+ * @license
5
+ * Copyright 2026 Aglyn LLC
6
+ *
7
+ * Licensed under the Apache License, Version 2.0 (the "License");
8
+ * you may not use this file except in compliance with the License.
9
+ * You may obtain a copy of the License at
10
+ *
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ */ import * as Aglyn from "@aglyn/aglyn";
19
+ /**
20
+ * THE ELEMENT PICKER EVERY CONTAINER GETS (AGL-2525).
21
+ *
22
+ * Section owned the semantic elements alone, so an author who wanted their nav
23
+ * row to BE the `nav` had to wrap it in a second element to say so — and on
24
+ * `aglyn.com` nobody did, which is why the published page had no navigation
25
+ * landmark at all. Wrapping to name a thing is the same shape of
26
+ * element-nobody-authored that AGL-2521 removed from component placements,
27
+ * arriving by a different route.
28
+ *
29
+ * ⛔ `main` IS NOT ON THIS LIST. A page carries exactly one, placed by
30
+ * `stampDocumentLandmark` on the Document layer or the Layout Slot — the two
31
+ * nodes that appear at most once per document. Everything using this picker can
32
+ * be placed any number of times, so an author-selected `main` here could only
33
+ * ever be the second one.
34
+ *
35
+ * An allow-list rather than free text: the value is persisted and rendered
36
+ * verbatim, so a typed one would put `script` into every visitor's page.
37
+ */ export const SEMANTIC_ELEMENTS = [
38
+ 'div',
39
+ 'section',
40
+ 'article',
41
+ 'aside',
42
+ 'nav',
43
+ 'header',
44
+ 'footer'
45
+ ];
46
+ /**
47
+ * The element to render, or `undefined` to leave the component's own default
48
+ * alone.
49
+ *
50
+ * Returning `undefined` rather than `'div'` is what lets this be added to a
51
+ * component that does NOT default to a div — App Bar renders `header` unless
52
+ * told otherwise, and a resolver that answered `'div'` for "unset" would have
53
+ * silently stripped the banner landmark off every site's chrome the moment the
54
+ * picker appeared.
55
+ */ export function resolveSemanticElement(value) {
56
+ return SEMANTIC_ELEMENTS.includes(String(value != null ? value : '')) ? value : undefined;
57
+ }
58
+ /**
59
+ * The elements that BECOME a landmark, and so want a name (AGL-2525).
60
+ *
61
+ * `div` is the odd one out: it has no role, so an `aria-label` on it names
62
+ * nothing. Everything else is announced as a region, and a page with two of
63
+ * the same kind — a header nav and a footer nav, say — is a page where
64
+ * "navigation, navigation" is all a screen-reader user hears without one.
65
+ */ export const LANDMARK_ELEMENTS = SEMANTIC_ELEMENTS.filter((element)=>element !== 'div');
66
+ /**
67
+ * Consume the picker's props and return what the underlying MUI component
68
+ * should receive.
69
+ *
70
+ * Takes the whole props bag rather than one value because both keys have to
71
+ * be REMOVED as well as translated: `ariaLabel` spread onto a DOM element is
72
+ * an unknown React prop, warned about on the canvas and serialized onto the
73
+ * published page, which is the shape of the `propValues` leak in AGL-2486.
74
+ */ export function applySemanticElement(props) {
75
+ const { component, ariaLabel } = props, rest = _object_without_properties_loose(props, [
76
+ "component",
77
+ "ariaLabel"
78
+ ]);
79
+ const element = resolveSemanticElement(component);
80
+ const label = typeof ariaLabel === 'string' ? ariaLabel.trim() : '';
81
+ return _extends({}, rest, element ? {
82
+ component: element
83
+ } : {}, element && element !== 'div' && label ? {
84
+ 'aria-label': label
85
+ } : {});
86
+ }
87
+ /**
88
+ * Spreadable `component` prop: present only when the author chose one, so an
89
+ * unset picker is indistinguishable from never having had one.
90
+ */ export function semanticElementProp(value) {
91
+ const element = resolveSemanticElement(value);
92
+ return element ? {
93
+ component: element
94
+ } : {};
95
+ }
96
+ /**
97
+ * The attribute schema. `subject` names what renders, e.g. "this stack".
98
+ *
99
+ * Labelled `Component`, the name Box, Typography, the Document layer and the
100
+ * Layout Slot already use — Section and Inline text keep `element` as their
101
+ * stored KEY because their values are persisted in published screens, but the
102
+ * panel says one thing everywhere (AGL-2514).
103
+ */ export function semanticElementAttribute(subject) {
104
+ return {
105
+ name: 'component',
106
+ label: 'Component',
107
+ description: `The DOM element ${subject} renders as. Use section/article/aside/nav/` + 'header/footer to give the region meaning for assistive tech and search ' + 'engines; div for purely visual grouping. "main" is not offered — the ' + 'page’s content region carries that one.',
108
+ component: Aglyn.FieldComponentType.SELECT,
109
+ options: SEMANTIC_ELEMENTS.map((value)=>({
110
+ value,
111
+ label: value
112
+ }))
113
+ };
114
+ }
115
+ /**
116
+ * The name for the landmark the picker just made, shown only once one exists.
117
+ *
118
+ * Gated on the element rather than always visible because on a `div` — the
119
+ * default, and what most of these elements stay — the field would do nothing
120
+ * at all, and a control that silently does nothing is worse than no control.
121
+ *
122
+ * This is the half Section already had and the picker did not. Naming stops
123
+ * being optional the moment a page has two landmarks of a kind: a site nav and
124
+ * a footer nav both announce as "navigation" until one of them says which.
125
+ */ export function semanticElementLabelAttribute() {
126
+ return {
127
+ name: 'ariaLabel',
128
+ label: 'Accessible label',
129
+ description: 'Names this region for screen readers. Required in practice once a ' + 'page has two landmarks of the same kind — a site nav and a footer ' + 'nav are both announced as "navigation" until one of them says which.',
130
+ component: Aglyn.FieldComponentType.TEXT_FIELD,
131
+ condition: {
132
+ when: 'component',
133
+ is: [
134
+ ...LANDMARK_ELEMENTS
135
+ ]
136
+ }
137
+ };
138
+ }
139
+
140
+ //# sourceMappingURL=element-picker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/utils/element-picker.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as Aglyn from '@aglyn/aglyn'\n\n/**\n * THE ELEMENT PICKER EVERY CONTAINER GETS (AGL-2525).\n *\n * Section owned the semantic elements alone, so an author who wanted their nav\n * row to BE the `nav` had to wrap it in a second element to say so — and on\n * `aglyn.com` nobody did, which is why the published page had no navigation\n * landmark at all. Wrapping to name a thing is the same shape of\n * element-nobody-authored that AGL-2521 removed from component placements,\n * arriving by a different route.\n *\n * ⛔ `main` IS NOT ON THIS LIST. A page carries exactly one, placed by\n * `stampDocumentLandmark` on the Document layer or the Layout Slot — the two\n * nodes that appear at most once per document. Everything using this picker can\n * be placed any number of times, so an author-selected `main` here could only\n * ever be the second one.\n *\n * An allow-list rather than free text: the value is persisted and rendered\n * verbatim, so a typed one would put `script` into every visitor's page.\n */\nexport const SEMANTIC_ELEMENTS = [\n 'div',\n 'section',\n 'article',\n 'aside',\n 'nav',\n 'header',\n 'footer',\n] as const\nexport type SemanticElement = (typeof SEMANTIC_ELEMENTS)[number]\n\n/**\n * The element to render, or `undefined` to leave the component's own default\n * alone.\n *\n * Returning `undefined` rather than `'div'` is what lets this be added to a\n * component that does NOT default to a div — App Bar renders `header` unless\n * told otherwise, and a resolver that answered `'div'` for \"unset\" would have\n * silently stripped the banner landmark off every site's chrome the moment the\n * picker appeared.\n */\nexport function resolveSemanticElement(value: unknown): SemanticElement | undefined {\n return (SEMANTIC_ELEMENTS as readonly string[]).includes(String(value ?? ''))\n ? (value as SemanticElement)\n : undefined\n}\n\n/**\n * The elements that BECOME a landmark, and so want a name (AGL-2525).\n *\n * `div` is the odd one out: it has no role, so an `aria-label` on it names\n * nothing. Everything else is announced as a region, and a page with two of\n * the same kind — a header nav and a footer nav, say — is a page where\n * \"navigation, navigation\" is all a screen-reader user hears without one.\n */\nexport const LANDMARK_ELEMENTS = SEMANTIC_ELEMENTS.filter(\n (element) => element !== 'div',\n)\n\n/**\n * Consume the picker's props and return what the underlying MUI component\n * should receive.\n *\n * Takes the whole props bag rather than one value because both keys have to\n * be REMOVED as well as translated: `ariaLabel` spread onto a DOM element is\n * an unknown React prop, warned about on the canvas and serialized onto the\n * published page, which is the shape of the `propValues` leak in AGL-2486.\n */\nexport function applySemanticElement<P extends Record<string, unknown>>(\n props: P,\n): Omit<P, 'component' | 'ariaLabel'> & {\n component?: SemanticElement\n 'aria-label'?: string\n} {\n const { component, ariaLabel, ...rest } = props as P & {\n component?: unknown\n ariaLabel?: unknown\n }\n const element = resolveSemanticElement(component)\n const label = typeof ariaLabel === 'string' ? ariaLabel.trim() : ''\n return {\n ...(rest as Omit<P, 'component' | 'ariaLabel'>),\n ...(element ? { component: element } : {}),\n // Only on a landmark: a name on a role-less `div` is announced by\n // nothing and is one more attribute in every visitor's markup.\n ...(element && element !== 'div' && label ? { 'aria-label': label } : {}),\n }\n}\n\n/**\n * Spreadable `component` prop: present only when the author chose one, so an\n * unset picker is indistinguishable from never having had one.\n */\nexport function semanticElementProp(\n value: unknown,\n): { component?: SemanticElement } {\n const element = resolveSemanticElement(value)\n return element ? { component: element } : {}\n}\n\n/**\n * The attribute schema. `subject` names what renders, e.g. \"this stack\".\n *\n * Labelled `Component`, the name Box, Typography, the Document layer and the\n * Layout Slot already use — Section and Inline text keep `element` as their\n * stored KEY because their values are persisted in published screens, but the\n * panel says one thing everywhere (AGL-2514).\n */\nexport function semanticElementAttribute(\n subject: string,\n): Aglyn.AglynAttributeSchema {\n return {\n name: 'component',\n label: 'Component',\n description:\n `The DOM element ${subject} renders as. Use section/article/aside/nav/` +\n 'header/footer to give the region meaning for assistive tech and search ' +\n 'engines; div for purely visual grouping. \"main\" is not offered — the ' +\n 'page’s content region carries that one.',\n component: Aglyn.FieldComponentType.SELECT,\n options: SEMANTIC_ELEMENTS.map((value) => ({ value, label: value })),\n } as Aglyn.AglynAttributeSchema\n}\n\n/**\n * The name for the landmark the picker just made, shown only once one exists.\n *\n * Gated on the element rather than always visible because on a `div` — the\n * default, and what most of these elements stay — the field would do nothing\n * at all, and a control that silently does nothing is worse than no control.\n *\n * This is the half Section already had and the picker did not. Naming stops\n * being optional the moment a page has two landmarks of a kind: a site nav and\n * a footer nav both announce as \"navigation\" until one of them says which.\n */\nexport function semanticElementLabelAttribute(): Aglyn.AglynAttributeSchema {\n return {\n name: 'ariaLabel',\n label: 'Accessible label',\n description:\n 'Names this region for screen readers. Required in practice once a ' +\n 'page has two landmarks of the same kind — a site nav and a footer ' +\n 'nav are both announced as \"navigation\" until one of them says which.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n condition: { when: 'component', is: [...LANDMARK_ELEMENTS] },\n } as Aglyn.AglynAttributeSchema\n}\n"],"names":["Aglyn","SEMANTIC_ELEMENTS","resolveSemanticElement","value","includes","String","undefined","LANDMARK_ELEMENTS","filter","element","applySemanticElement","props","component","ariaLabel","rest","label","trim","semanticElementProp","semanticElementAttribute","subject","name","description","FieldComponentType","SELECT","options","map","semanticElementLabelAttribute","TEXT_FIELD","condition","when","is"],"mappings":";;AAAA;;;;;;;;;;;;;;;CAeC,GAED,YAAYA,WAAW,eAAc;AAErC;;;;;;;;;;;;;;;;;;CAkBC,GACD,OAAO,MAAMC,oBAAoB;IAC/B;IACA;IACA;IACA;IACA;IACA;IACA;CACD,CAAS;AAGV;;;;;;;;;CASC,GACD,OAAO,SAASC,uBAAuBC,KAAc;IACnD,OAAO,AAACF,kBAAwCG,QAAQ,CAACC,OAAOF,gBAAAA,QAAS,OACpEA,QACDG;AACN;AAEA;;;;;;;CAOC,GACD,OAAO,MAAMC,oBAAoBN,kBAAkBO,MAAM,CACvD,CAACC,UAAYA,YAAY,OAC1B;AAED;;;;;;;;CAQC,GACD,OAAO,SAASC,qBACdC,KAAQ;IAKR,MAAM,EAAEC,SAAS,EAAEC,SAAS,EAAW,GAAGF,OAATG,wCAASH;;;;IAI1C,MAAMF,UAAUP,uBAAuBU;IACvC,MAAMG,QAAQ,OAAOF,cAAc,WAAWA,UAAUG,IAAI,KAAK;IACjE,OAAO,aACDF,MACAL,UAAU;QAAEG,WAAWH;IAAQ,IAAI,CAAC,GAGpCA,WAAWA,YAAY,SAASM,QAAQ;QAAE,cAAcA;IAAM,IAAI,CAAC;AAE3E;AAEA;;;CAGC,GACD,OAAO,SAASE,oBACdd,KAAc;IAEd,MAAMM,UAAUP,uBAAuBC;IACvC,OAAOM,UAAU;QAAEG,WAAWH;IAAQ,IAAI,CAAC;AAC7C;AAEA;;;;;;;CAOC,GACD,OAAO,SAASS,yBACdC,OAAe;IAEf,OAAO;QACLC,MAAM;QACNL,OAAO;QACPM,aACE,CAAC,gBAAgB,EAAEF,QAAQ,2CAA2C,CAAC,GACvE,4EACA,0EACA;QACFP,WAAWZ,MAAMsB,kBAAkB,CAACC,MAAM;QAC1CC,SAASvB,kBAAkBwB,GAAG,CAAC,CAACtB,QAAW,CAAA;gBAAEA;gBAAOY,OAAOZ;YAAM,CAAA;IACnE;AACF;AAEA;;;;;;;;;;CAUC,GACD,OAAO,SAASuB;IACd,OAAO;QACLN,MAAM;QACNL,OAAO;QACPM,aACE,uEACA,uEACA;QACFT,WAAWZ,MAAMsB,kBAAkB,CAACK,UAAU;QAC9CC,WAAW;YAAEC,MAAM;YAAaC,IAAI;mBAAIvB;aAAkB;QAAC;IAC7D;AACF"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022 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 type { ComponentId } from '@aglyn/aglyn';
18
+ export declare const generatePresetId: (componentId: ComponentId, ...other: string[]) => ComponentId;
19
+ export default generatePresetId;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022 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
+ */ import { BUNDLE_ID } from "../constants/bundle-common.js";
17
+ export const generatePresetId = (componentId, ...other)=>{
18
+ return `${BUNDLE_ID}:${[
19
+ componentId,
20
+ ...other
21
+ ].join('.')}`;
22
+ };
23
+ export default generatePresetId;
24
+
25
+ //# sourceMappingURL=generate-preset-id.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/utils/generate-preset-id.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2022 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 type { ComponentId } from '@aglyn/aglyn'\nimport { BUNDLE_ID } from '../constants/bundle-common'\n\nexport const generatePresetId = (\n componentId: ComponentId,\n ...other: string[]\n): ComponentId => {\n return `${BUNDLE_ID}:${[componentId, ...other].join('.')}`\n}\n\nexport default generatePresetId\n"],"names":["BUNDLE_ID","generatePresetId","componentId","other","join"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAGD,SAASA,SAAS,QAAQ,gCAA4B;AAEtD,OAAO,MAAMC,mBAAmB,CAC9BC,aACA,GAAGC;IAEH,OAAO,GAAGH,UAAU,CAAC,EAAE;QAACE;WAAgBC;KAAM,CAACC,IAAI,CAAC,MAAM;AAC5D,EAAC;AAED,eAAeH,iBAAgB"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ /**
18
+ * Where a link opens, as authored. Persisted in screen documents; never
19
+ * rename a value.
20
+ *
21
+ * - `'_self'` (or unset) — stays in the current tab, the browser default.
22
+ * - `'_blank'` — a new tab.
23
+ * - `'custom'` — a NAMED window, read from the companion `targetName` prop.
24
+ * Not an anchor value itself; it is the sentinel that reveals the name
25
+ * field, and never reaches the DOM.
26
+ */
27
+ export type LinkTargetChoice = '_self' | '_blank' | 'custom';
28
+ /** The anchor attributes a {@link LinkTargetChoice} resolves to. */
29
+ export interface LinkTargetProps {
30
+ target?: string;
31
+ rel?: string;
32
+ }
33
+ /**
34
+ * Resolves the authored target pair to the attributes an anchor should carry.
35
+ *
36
+ * Returns NOTHING for the default choice rather than an explicit
37
+ * `target="_self"`: the two behave identically, and an absent attribute is
38
+ * what every link authored before this existed already renders — so adding
39
+ * the control moves no published markup.
40
+ *
41
+ * `rel` rides along because a target that opens elsewhere hands the new
42
+ * context a live `window.opener` handle back into this page. `noreferrer` is
43
+ * added only when the destination leaves the site: stripping the referrer
44
+ * from a link to one of the site's own screens would make the landing page
45
+ * read as direct traffic in its own analytics, which is a reporting defect,
46
+ * not a safety win.
47
+ *
48
+ * A cleared attribute persists as `null` or `''`, and a custom choice with
49
+ * an empty name is an author mid-edit — both fall back to the default rather
50
+ * than stamping an empty `target` on the anchor.
51
+ */
52
+ export declare function linkTargetProps(target: LinkTargetChoice | string | null | undefined, targetName: string | null | undefined, leavesSite: boolean): LinkTargetProps;
53
+ export default linkTargetProps;