@aglyn/plugins-mui 1.0.0-beta.223 → 1.0.0-beta.225
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +7 -7
- package/src/lib/components/box.js +6 -0
- package/src/lib/components/box.js.map +1 -1
- package/src/lib/components/button.js +2 -0
- package/src/lib/components/button.js.map +1 -1
- package/src/lib/components/container.js +6 -0
- package/src/lib/components/container.js.map +1 -1
- package/src/lib/components/grid.js +6 -0
- package/src/lib/components/grid.js.map +1 -1
- package/src/lib/components/icon.js +2 -0
- package/src/lib/components/icon.js.map +1 -1
- package/src/lib/components/image.js +2 -0
- package/src/lib/components/image.js.map +1 -1
- package/src/lib/components/inline-text.js +2 -0
- package/src/lib/components/inline-text.js.map +1 -1
- package/src/lib/components/layout-slot.js +4 -0
- package/src/lib/components/layout-slot.js.map +1 -1
- package/src/lib/components/link-box.js +6 -0
- package/src/lib/components/link-box.js.map +1 -1
- package/src/lib/components/list-item-text.js +2 -0
- package/src/lib/components/list-item-text.js.map +1 -1
- package/src/lib/components/list-item.js +4 -0
- package/src/lib/components/list-item.js.map +1 -1
- package/src/lib/components/list.js +4 -0
- package/src/lib/components/list.js.map +1 -1
- package/src/lib/components/paper.js +6 -0
- package/src/lib/components/paper.js.map +1 -1
- package/src/lib/components/screen-link.js +2 -0
- package/src/lib/components/screen-link.js.map +1 -1
- package/src/lib/components/section.js +6 -0
- package/src/lib/components/section.js.map +1 -1
- package/src/lib/components/stack.js +4 -0
- package/src/lib/components/stack.js.map +1 -1
- package/src/lib/components/typography.js +2 -0
- package/src/lib/components/typography.js.map +1 -1
- package/src/lib/utils/image-sizes.js +10 -1
- package/src/lib/utils/image-sizes.js.map +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/components/list-item.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'\nimport {\n mdiFormatListText,\n} from '@aglyn/shared-data-mdi'\nimport MuiListItem, { type ListItemProps } from '@mui/material/ListItem'\nimport { createElement, forwardRef } from 'react'\nimport { BUNDLE_ID } from '../constants/bundle-common'\nimport { dropClearedProps } from '../utils/drop-cleared-props'\nimport { generatePresetId } from '../utils/generate-preset-id'\nimport {\n presets as listItemTextPresets,\n schema as listItemTextSchema,\n} from './list-item-text'\n\n/**\n * MUI's ListItem behind the cleared-prop guard (AGL-1451).\n *\n * Exported raw, so every one of its five authorable attributes reached MUI\n * as authored — including `alignItems`, whose `''` option is not `undefined`\n * (so the `alignItems = 'center'` destructuring default never fires) and is\n * falsy (so the `alignItems === 'flex-start'` branch is skipped), leaving a\n * row that carries neither utility class.\n */\nconst ListItem = forwardRef<HTMLLIElement, ListItemProps>((props, ref) =>\n createElement(MuiListItem, { ...dropClearedProps(props), ref }),\n)\nListItem.displayName = 'AglynListItem'\n\n// Component ids are persisted in screen documents; keep the legacy ids.\nexport const ID: Aglyn.ComponentId = 'muiListItem'\n\nexport const schema: Aglyn.ComponentSchema<ListItemProps> = {\n $id: ID,\n pluginId: BUNDLE_ID,\n displayName: 'List Item',\n description: 'One row of a list.',\n category: Aglyn.ComponentCategory.DATA_DISPLAY,\n icon: { path: mdiFormatListText.path },\n restrictChildren: [\n Aglyn.LinealDirectiveFlag.LIMIT_TO,\n {\n components: [listItemTextSchema.$id],\n },\n ],\n // Like List, this had NO attributes: dividers, density and gutters are\n // the first things anyone reaches for on a list row, and none of them\n // were reachable from the inspector.\n attributes: [\n {\n name: 'divider',\n label: 'Divider?',\n description: 'If true, a 1px line is drawn under the item.',\n component: Aglyn.FieldComponentType.SWITCH,\n },\n {\n name: 'alignItems',\n label: 'Align items',\n description:\n 'Vertical alignment of the row content. Use flex-start when the ' +\n 'secondary text wraps to several lines.',\n component: Aglyn.FieldComponentType.SELECT,\n // `center` is MUI's own value and the one an author needs to move a\n // row BACK off Top, so it stays in the list as a real sentinel\n // rather than being deleted (AGL-1451). As `''` that move could not\n // persist (AGL-1191).\n options: [\n { value: 'center', label: 'Center (default)' },\n { value: 'flex-start', label: 'Top' },\n ],\n },\n {\n name: 'dense',\n label: 'Dense?',\n description:\n 'If true, this row is compacted vertically. The parent list’s ' +\n 'Dense setting already applies to every row.',\n component: Aglyn.FieldComponentType.SWITCH,\n },\n {\n name: 'disableGutters',\n label: 'Disable gutters?',\n description:\n 'Removes this row’s side padding, so its text lines up with content ' +\n 'outside the list instead of being indented from it.',\n component: Aglyn.FieldComponentType.SWITCH,\n },\n {\n name: 'disablePadding',\n label: 'Disable padding?',\n description: 'If true, all padding is removed.',\n component: Aglyn.FieldComponentType.SWITCH,\n },\n ],\n}\n\nexport const presets: Aglyn.PresetSchema[] = [\n {\n $id: generatePresetId(ID),\n type: Aglyn.NodeType.PRESET,\n displayName: 'List Item',\n icon: { path: mdiFormatListText.path },\n category: Aglyn.ComponentCategory.DATA_DISPLAY,\n data: {\n $id: null,\n componentId: ID,\n pluginId: BUNDLE_ID,\n nodes: [\n {\n ...listItemTextPresets[0].data,\n },\n ],\n },\n },\n]\n\nexport default ListItem\n"],"names":["Aglyn","mdiFormatListText","MuiListItem","createElement","forwardRef","BUNDLE_ID","dropClearedProps","generatePresetId","presets","listItemTextPresets","schema","listItemTextSchema","ListItem","props","ref","displayName","ID","$id","pluginId","description","category","ComponentCategory","DATA_DISPLAY","icon","path","restrictChildren","LinealDirectiveFlag","LIMIT_TO","components","attributes","name","label","component","FieldComponentType","SWITCH","SELECT","options","value","type","NodeType","PRESET","data","componentId","nodes"],"mappings":";AAAA;;;;;;;;;;;;;;;CAeC,GAED,YAAYA,WAAW,eAAc;AACrC,SACEC,iBAAiB,QACZ,yBAAwB;AAC/B,OAAOC,iBAAyC,yBAAwB;AACxE,SAASC,aAAa,EAAEC,UAAU,QAAQ,QAAO;AACjD,SAASC,SAAS,QAAQ,gCAA4B;AACtD,SAASC,gBAAgB,QAAQ,iCAA6B;AAC9D,SAASC,gBAAgB,QAAQ,iCAA6B;AAC9D,SACEC,WAAWC,mBAAmB,EAC9BC,UAAUC,kBAAkB,QACvB,sBAAkB;AAEzB;;;;;;;;CAQC,GACD,MAAMC,WAAWR,WAAyC,CAACS,OAAOC,MAChEX,cAAcD,aAAa,aAAKI,iBAAiBO;QAAQC;;AAE3DF,SAASG,WAAW,GAAG;AAEvB,wEAAwE;AACxE,OAAO,MAAMC,KAAwB,cAAa;AAElD,OAAO,MAAMN,SAA+C;IAC1DO,KAAKD;IACLE,UAAUb;IACVU,aAAa;
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/components/list-item.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'\nimport {\n mdiFormatListText,\n} from '@aglyn/shared-data-mdi'\nimport MuiListItem, { type ListItemProps } from '@mui/material/ListItem'\nimport { createElement, forwardRef } from 'react'\nimport { BUNDLE_ID } from '../constants/bundle-common'\nimport { dropClearedProps } from '../utils/drop-cleared-props'\nimport { generatePresetId } from '../utils/generate-preset-id'\nimport {\n presets as listItemTextPresets,\n schema as listItemTextSchema,\n} from './list-item-text'\n\n/**\n * MUI's ListItem behind the cleared-prop guard (AGL-1451).\n *\n * Exported raw, so every one of its five authorable attributes reached MUI\n * as authored — including `alignItems`, whose `''` option is not `undefined`\n * (so the `alignItems = 'center'` destructuring default never fires) and is\n * falsy (so the `alignItems === 'flex-start'` branch is skipped), leaving a\n * row that carries neither utility class.\n */\nconst ListItem = forwardRef<HTMLLIElement, ListItemProps>((props, ref) =>\n createElement(MuiListItem, { ...dropClearedProps(props), ref }),\n)\nListItem.displayName = 'AglynListItem'\n\n// Component ids are persisted in screen documents; keep the legacy ids.\nexport const ID: Aglyn.ComponentId = 'muiListItem'\n\nexport const schema: Aglyn.ComponentSchema<ListItemProps> = {\n $id: ID,\n pluginId: BUNDLE_ID,\n displayName: 'List Item',\n // Static: may sit in a subtree that keeps its server HTML (AGL-3581).\n flags: { lazyHydration: Aglyn.FEATURE_FLAG.ENABLED },\n description: 'One row of a list.',\n category: Aglyn.ComponentCategory.DATA_DISPLAY,\n icon: { path: mdiFormatListText.path },\n restrictChildren: [\n Aglyn.LinealDirectiveFlag.LIMIT_TO,\n {\n components: [listItemTextSchema.$id],\n },\n ],\n // Like List, this had NO attributes: dividers, density and gutters are\n // the first things anyone reaches for on a list row, and none of them\n // were reachable from the inspector.\n attributes: [\n {\n name: 'divider',\n label: 'Divider?',\n description: 'If true, a 1px line is drawn under the item.',\n component: Aglyn.FieldComponentType.SWITCH,\n },\n {\n name: 'alignItems',\n label: 'Align items',\n description:\n 'Vertical alignment of the row content. Use flex-start when the ' +\n 'secondary text wraps to several lines.',\n component: Aglyn.FieldComponentType.SELECT,\n // `center` is MUI's own value and the one an author needs to move a\n // row BACK off Top, so it stays in the list as a real sentinel\n // rather than being deleted (AGL-1451). As `''` that move could not\n // persist (AGL-1191).\n options: [\n { value: 'center', label: 'Center (default)' },\n { value: 'flex-start', label: 'Top' },\n ],\n },\n {\n name: 'dense',\n label: 'Dense?',\n description:\n 'If true, this row is compacted vertically. The parent list’s ' +\n 'Dense setting already applies to every row.',\n component: Aglyn.FieldComponentType.SWITCH,\n },\n {\n name: 'disableGutters',\n label: 'Disable gutters?',\n description:\n 'Removes this row’s side padding, so its text lines up with content ' +\n 'outside the list instead of being indented from it.',\n component: Aglyn.FieldComponentType.SWITCH,\n },\n {\n name: 'disablePadding',\n label: 'Disable padding?',\n description: 'If true, all padding is removed.',\n component: Aglyn.FieldComponentType.SWITCH,\n },\n ],\n}\n\nexport const presets: Aglyn.PresetSchema[] = [\n {\n $id: generatePresetId(ID),\n type: Aglyn.NodeType.PRESET,\n displayName: 'List Item',\n icon: { path: mdiFormatListText.path },\n category: Aglyn.ComponentCategory.DATA_DISPLAY,\n data: {\n $id: null,\n componentId: ID,\n pluginId: BUNDLE_ID,\n nodes: [\n {\n ...listItemTextPresets[0].data,\n },\n ],\n },\n },\n]\n\nexport default ListItem\n"],"names":["Aglyn","mdiFormatListText","MuiListItem","createElement","forwardRef","BUNDLE_ID","dropClearedProps","generatePresetId","presets","listItemTextPresets","schema","listItemTextSchema","ListItem","props","ref","displayName","ID","$id","pluginId","flags","lazyHydration","FEATURE_FLAG","ENABLED","description","category","ComponentCategory","DATA_DISPLAY","icon","path","restrictChildren","LinealDirectiveFlag","LIMIT_TO","components","attributes","name","label","component","FieldComponentType","SWITCH","SELECT","options","value","type","NodeType","PRESET","data","componentId","nodes"],"mappings":";AAAA;;;;;;;;;;;;;;;CAeC,GAED,YAAYA,WAAW,eAAc;AACrC,SACEC,iBAAiB,QACZ,yBAAwB;AAC/B,OAAOC,iBAAyC,yBAAwB;AACxE,SAASC,aAAa,EAAEC,UAAU,QAAQ,QAAO;AACjD,SAASC,SAAS,QAAQ,gCAA4B;AACtD,SAASC,gBAAgB,QAAQ,iCAA6B;AAC9D,SAASC,gBAAgB,QAAQ,iCAA6B;AAC9D,SACEC,WAAWC,mBAAmB,EAC9BC,UAAUC,kBAAkB,QACvB,sBAAkB;AAEzB;;;;;;;;CAQC,GACD,MAAMC,WAAWR,WAAyC,CAACS,OAAOC,MAChEX,cAAcD,aAAa,aAAKI,iBAAiBO;QAAQC;;AAE3DF,SAASG,WAAW,GAAG;AAEvB,wEAAwE;AACxE,OAAO,MAAMC,KAAwB,cAAa;AAElD,OAAO,MAAMN,SAA+C;IAC1DO,KAAKD;IACLE,UAAUb;IACVU,aAAa;IACb,sEAAsE;IACtEI,OAAO;QAAEC,eAAepB,MAAMqB,YAAY,CAACC,OAAO;IAAC;IACnDC,aAAa;IACbC,UAAUxB,MAAMyB,iBAAiB,CAACC,YAAY;IAC9CC,MAAM;QAAEC,MAAM3B,kBAAkB2B,IAAI;IAAC;IACrCC,kBAAkB;QAChB7B,MAAM8B,mBAAmB,CAACC,QAAQ;QAClC;YACEC,YAAY;gBAACrB,mBAAmBM,GAAG;aAAC;QACtC;KACD;IACD,uEAAuE;IACvE,sEAAsE;IACtE,qCAAqC;IACrCgB,YAAY;QACV;YACEC,MAAM;YACNC,OAAO;YACPZ,aAAa;YACba,WAAWpC,MAAMqC,kBAAkB,CAACC,MAAM;QAC5C;QACA;YACEJ,MAAM;YACNC,OAAO;YACPZ,aACE,oEACA;YACFa,WAAWpC,MAAMqC,kBAAkB,CAACE,MAAM;YAC1C,oEAAoE;YACpE,+DAA+D;YAC/D,oEAAoE;YACpE,sBAAsB;YACtBC,SAAS;gBACP;oBAAEC,OAAO;oBAAUN,OAAO;gBAAmB;gBAC7C;oBAAEM,OAAO;oBAAcN,OAAO;gBAAM;aACrC;QACH;QACA;YACED,MAAM;YACNC,OAAO;YACPZ,aACE,kEACA;YACFa,WAAWpC,MAAMqC,kBAAkB,CAACC,MAAM;QAC5C;QACA;YACEJ,MAAM;YACNC,OAAO;YACPZ,aACE,wEACA;YACFa,WAAWpC,MAAMqC,kBAAkB,CAACC,MAAM;QAC5C;QACA;YACEJ,MAAM;YACNC,OAAO;YACPZ,aAAa;YACba,WAAWpC,MAAMqC,kBAAkB,CAACC,MAAM;QAC5C;KACD;AACH,EAAC;AAED,OAAO,MAAM9B,UAAgC;IAC3C;QACES,KAAKV,iBAAiBS;QACtB0B,MAAM1C,MAAM2C,QAAQ,CAACC,MAAM;QAC3B7B,aAAa;QACbY,MAAM;YAAEC,MAAM3B,kBAAkB2B,IAAI;QAAC;QACrCJ,UAAUxB,MAAMyB,iBAAiB,CAACC,YAAY;QAC9CmB,MAAM;YACJ5B,KAAK;YACL6B,aAAa9B;YACbE,UAAUb;YACV0C,OAAO;gBACL,aACKtC,mBAAmB,CAAC,EAAE,CAACoC,IAAI;aAEjC;QACH;IACF;CACD,CAAA;AAED,eAAejC,SAAQ"}
|
|
@@ -47,6 +47,10 @@ export const schema = {
|
|
|
47
47
|
$id: ID,
|
|
48
48
|
pluginId: BUNDLE_ID,
|
|
49
49
|
displayName: 'List',
|
|
50
|
+
// Static: may sit in a subtree that keeps its server HTML (AGL-3581).
|
|
51
|
+
flags: {
|
|
52
|
+
lazyHydration: Aglyn.FEATURE_FLAG.ENABLED
|
|
53
|
+
},
|
|
50
54
|
description: 'Vertical list of items, optionally under a sticky heading.',
|
|
51
55
|
category: Aglyn.ComponentCategory.DATA_DISPLAY,
|
|
52
56
|
icon: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/components/list.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'\nimport {\n mdiFormatListBulletedSquare,\n} from '@aglyn/shared-data-mdi'\nimport MuiList, { type ListProps } from '@mui/material/List'\nimport ListSubheader from '@mui/material/ListSubheader'\nimport { createElement, forwardRef } from 'react'\nimport { BUNDLE_ID } from '../constants/bundle-common'\nimport { generatePresetId } from '../utils/generate-preset-id'\nimport {\n presets as listItemPresets,\n schema as listItemSchema,\n} from './list-item'\n\n// Component ids are persisted in screen documents; keep the legacy ids.\nexport const ID: Aglyn.ComponentId = 'muiList'\n\nexport interface ListElementProps extends Omit<ListProps, 'subheader'> {\n /** Sticky heading above the items; omitted entirely when blank. */\n subheader?: string\n}\n\n/**\n * List (https://mui.com/material-ui/react-list/).\n *\n * Wraps MUI's List only to turn the authored `subheader` string into a\n * real `ListSubheader`: MUI types the prop as a node, so a bare string\n * renders as unstyled text outside the list's own heading treatment.\n */\nconst List = forwardRef<HTMLUListElement, ListElementProps>((props, ref) => {\n const { subheader, ...rest } = props\n return createElement(MuiList, {\n ref,\n // ListSubheader defaults to `li`, which is what belongs inside the\n // `ul` List renders.\n subheader: subheader\n ? createElement(ListSubheader, null, subheader)\n : undefined,\n ...rest,\n })\n})\nList.displayName = 'AglynList'\n\nexport const schema: Aglyn.ComponentSchema<ListElementProps> = {\n $id: ID,\n pluginId: BUNDLE_ID,\n displayName: 'List',\n description: 'Vertical list of items, optionally under a sticky heading.',\n category: Aglyn.ComponentCategory.DATA_DISPLAY,\n icon: { path: mdiFormatListBulletedSquare.path },\n restrictChildren: [\n Aglyn.LinealDirectiveFlag.LIMIT_TO,\n {\n components: [listItemSchema.$id],\n },\n ],\n // The list had NO attributes at all: density and padding were only\n // reachable by hand-writing sx, which is not where authors look.\n attributes: [\n {\n name: 'subheader',\n label: 'Heading',\n description:\n 'Sticky heading rendered above the items. Leave blank for none.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n },\n {\n name: 'dense',\n label: 'Dense?',\n description:\n 'If true, items are compacted vertically. Applies to every item ' +\n 'in the list.',\n component: Aglyn.FieldComponentType.SWITCH,\n },\n {\n name: 'disablePadding',\n label: 'Disable padding?',\n description: 'If true, the padding above and below the list is removed.',\n component: Aglyn.FieldComponentType.SWITCH,\n },\n ],\n}\n\nexport const presets: Aglyn.PresetSchema[] = [\n {\n $id: generatePresetId(ID),\n type: Aglyn.NodeType.PRESET,\n displayName: 'List',\n icon: { path: mdiFormatListBulletedSquare.path },\n category: Aglyn.ComponentCategory.DATA_DISPLAY,\n data: {\n $id: null,\n componentId: ID,\n pluginId: BUNDLE_ID,\n nodes: [\n {\n ...listItemPresets[0].data,\n },\n {\n ...listItemPresets[0].data,\n },\n ],\n },\n },\n]\n\nexport default List\n"],"names":["Aglyn","mdiFormatListBulletedSquare","MuiList","ListSubheader","createElement","forwardRef","BUNDLE_ID","generatePresetId","presets","listItemPresets","schema","listItemSchema","ID","List","props","ref","subheader","rest","undefined","displayName","$id","pluginId","description","category","ComponentCategory","DATA_DISPLAY","icon","path","restrictChildren","LinealDirectiveFlag","LIMIT_TO","components","attributes","name","label","component","FieldComponentType","TEXT_FIELD","SWITCH","type","NodeType","PRESET","data","componentId","nodes"],"mappings":";;AAAA;;;;;;;;;;;;;;;CAeC,GAED,YAAYA,WAAW,eAAc;AACrC,SACEC,2BAA2B,QACtB,yBAAwB;AAC/B,OAAOC,aAAiC,qBAAoB;AAC5D,OAAOC,mBAAmB,8BAA6B;AACvD,SAASC,aAAa,EAAEC,UAAU,QAAQ,QAAO;AACjD,SAASC,SAAS,QAAQ,gCAA4B;AACtD,SAASC,gBAAgB,QAAQ,iCAA6B;AAC9D,SACEC,WAAWC,eAAe,EAC1BC,UAAUC,cAAc,QACnB,iBAAa;AAEpB,wEAAwE;AACxE,OAAO,MAAMC,KAAwB,UAAS;AAO9C;;;;;;CAMC,GACD,MAAMC,OAAOR,WAA+C,CAACS,OAAOC;IAClE,MAAM,EAAEC,SAAS,EAAW,GAAGF,OAATG,wCAASH;;;IAC/B,OAAOV,cAAcF,SAAS;QAC5Ba;QACA,mEAAmE;QACnE,qBAAqB;QACrBC,WAAWA,YACPZ,cAAcD,eAAe,MAAMa,aACnCE;OACDD;AAEP;AACAJ,KAAKM,WAAW,GAAG;AAEnB,OAAO,MAAMT,SAAkD;IAC7DU,KAAKR;IACLS,UAAUf;IACVa,aAAa;
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/components/list.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'\nimport {\n mdiFormatListBulletedSquare,\n} from '@aglyn/shared-data-mdi'\nimport MuiList, { type ListProps } from '@mui/material/List'\nimport ListSubheader from '@mui/material/ListSubheader'\nimport { createElement, forwardRef } from 'react'\nimport { BUNDLE_ID } from '../constants/bundle-common'\nimport { generatePresetId } from '../utils/generate-preset-id'\nimport {\n presets as listItemPresets,\n schema as listItemSchema,\n} from './list-item'\n\n// Component ids are persisted in screen documents; keep the legacy ids.\nexport const ID: Aglyn.ComponentId = 'muiList'\n\nexport interface ListElementProps extends Omit<ListProps, 'subheader'> {\n /** Sticky heading above the items; omitted entirely when blank. */\n subheader?: string\n}\n\n/**\n * List (https://mui.com/material-ui/react-list/).\n *\n * Wraps MUI's List only to turn the authored `subheader` string into a\n * real `ListSubheader`: MUI types the prop as a node, so a bare string\n * renders as unstyled text outside the list's own heading treatment.\n */\nconst List = forwardRef<HTMLUListElement, ListElementProps>((props, ref) => {\n const { subheader, ...rest } = props\n return createElement(MuiList, {\n ref,\n // ListSubheader defaults to `li`, which is what belongs inside the\n // `ul` List renders.\n subheader: subheader\n ? createElement(ListSubheader, null, subheader)\n : undefined,\n ...rest,\n })\n})\nList.displayName = 'AglynList'\n\nexport const schema: Aglyn.ComponentSchema<ListElementProps> = {\n $id: ID,\n pluginId: BUNDLE_ID,\n displayName: 'List',\n // Static: may sit in a subtree that keeps its server HTML (AGL-3581).\n flags: { lazyHydration: Aglyn.FEATURE_FLAG.ENABLED },\n description: 'Vertical list of items, optionally under a sticky heading.',\n category: Aglyn.ComponentCategory.DATA_DISPLAY,\n icon: { path: mdiFormatListBulletedSquare.path },\n restrictChildren: [\n Aglyn.LinealDirectiveFlag.LIMIT_TO,\n {\n components: [listItemSchema.$id],\n },\n ],\n // The list had NO attributes at all: density and padding were only\n // reachable by hand-writing sx, which is not where authors look.\n attributes: [\n {\n name: 'subheader',\n label: 'Heading',\n description:\n 'Sticky heading rendered above the items. Leave blank for none.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n },\n {\n name: 'dense',\n label: 'Dense?',\n description:\n 'If true, items are compacted vertically. Applies to every item ' +\n 'in the list.',\n component: Aglyn.FieldComponentType.SWITCH,\n },\n {\n name: 'disablePadding',\n label: 'Disable padding?',\n description: 'If true, the padding above and below the list is removed.',\n component: Aglyn.FieldComponentType.SWITCH,\n },\n ],\n}\n\nexport const presets: Aglyn.PresetSchema[] = [\n {\n $id: generatePresetId(ID),\n type: Aglyn.NodeType.PRESET,\n displayName: 'List',\n icon: { path: mdiFormatListBulletedSquare.path },\n category: Aglyn.ComponentCategory.DATA_DISPLAY,\n data: {\n $id: null,\n componentId: ID,\n pluginId: BUNDLE_ID,\n nodes: [\n {\n ...listItemPresets[0].data,\n },\n {\n ...listItemPresets[0].data,\n },\n ],\n },\n },\n]\n\nexport default List\n"],"names":["Aglyn","mdiFormatListBulletedSquare","MuiList","ListSubheader","createElement","forwardRef","BUNDLE_ID","generatePresetId","presets","listItemPresets","schema","listItemSchema","ID","List","props","ref","subheader","rest","undefined","displayName","$id","pluginId","flags","lazyHydration","FEATURE_FLAG","ENABLED","description","category","ComponentCategory","DATA_DISPLAY","icon","path","restrictChildren","LinealDirectiveFlag","LIMIT_TO","components","attributes","name","label","component","FieldComponentType","TEXT_FIELD","SWITCH","type","NodeType","PRESET","data","componentId","nodes"],"mappings":";;AAAA;;;;;;;;;;;;;;;CAeC,GAED,YAAYA,WAAW,eAAc;AACrC,SACEC,2BAA2B,QACtB,yBAAwB;AAC/B,OAAOC,aAAiC,qBAAoB;AAC5D,OAAOC,mBAAmB,8BAA6B;AACvD,SAASC,aAAa,EAAEC,UAAU,QAAQ,QAAO;AACjD,SAASC,SAAS,QAAQ,gCAA4B;AACtD,SAASC,gBAAgB,QAAQ,iCAA6B;AAC9D,SACEC,WAAWC,eAAe,EAC1BC,UAAUC,cAAc,QACnB,iBAAa;AAEpB,wEAAwE;AACxE,OAAO,MAAMC,KAAwB,UAAS;AAO9C;;;;;;CAMC,GACD,MAAMC,OAAOR,WAA+C,CAACS,OAAOC;IAClE,MAAM,EAAEC,SAAS,EAAW,GAAGF,OAATG,wCAASH;;;IAC/B,OAAOV,cAAcF,SAAS;QAC5Ba;QACA,mEAAmE;QACnE,qBAAqB;QACrBC,WAAWA,YACPZ,cAAcD,eAAe,MAAMa,aACnCE;OACDD;AAEP;AACAJ,KAAKM,WAAW,GAAG;AAEnB,OAAO,MAAMT,SAAkD;IAC7DU,KAAKR;IACLS,UAAUf;IACVa,aAAa;IACb,sEAAsE;IACtEG,OAAO;QAAEC,eAAevB,MAAMwB,YAAY,CAACC,OAAO;IAAC;IACnDC,aAAa;IACbC,UAAU3B,MAAM4B,iBAAiB,CAACC,YAAY;IAC9CC,MAAM;QAAEC,MAAM9B,4BAA4B8B,IAAI;IAAC;IAC/CC,kBAAkB;QAChBhC,MAAMiC,mBAAmB,CAACC,QAAQ;QAClC;YACEC,YAAY;gBAACxB,eAAeS,GAAG;aAAC;QAClC;KACD;IACD,mEAAmE;IACnE,iEAAiE;IACjEgB,YAAY;QACV;YACEC,MAAM;YACNC,OAAO;YACPZ,aACE;YACFa,WAAWvC,MAAMwC,kBAAkB,CAACC,UAAU;QAChD;QACA;YACEJ,MAAM;YACNC,OAAO;YACPZ,aACE,oEACA;YACFa,WAAWvC,MAAMwC,kBAAkB,CAACE,MAAM;QAC5C;QACA;YACEL,MAAM;YACNC,OAAO;YACPZ,aAAa;YACba,WAAWvC,MAAMwC,kBAAkB,CAACE,MAAM;QAC5C;KACD;AACH,EAAC;AAED,OAAO,MAAMlC,UAAgC;IAC3C;QACEY,KAAKb,iBAAiBK;QACtB+B,MAAM3C,MAAM4C,QAAQ,CAACC,MAAM;QAC3B1B,aAAa;QACbW,MAAM;YAAEC,MAAM9B,4BAA4B8B,IAAI;QAAC;QAC/CJ,UAAU3B,MAAM4B,iBAAiB,CAACC,YAAY;QAC9CiB,MAAM;YACJ1B,KAAK;YACL2B,aAAanC;YACbS,UAAUf;YACV0C,OAAO;gBACL,aACKvC,eAAe,CAAC,EAAE,CAACqC,IAAI;gBAE5B,aACKrC,eAAe,CAAC,EAAE,CAACqC,IAAI;aAE7B;QACH;IACF;CACD,CAAA;AAED,eAAejC,KAAI"}
|
|
@@ -75,6 +75,12 @@ export const schema = {
|
|
|
75
75
|
$id: ID,
|
|
76
76
|
pluginId: BUNDLE_ID,
|
|
77
77
|
displayName: 'Paper',
|
|
78
|
+
// Static, and its children sit directly in its root: a subtree it heads
|
|
79
|
+
// keeps its server HTML until the visitor nears it (AGL-3581).
|
|
80
|
+
flags: {
|
|
81
|
+
lazyHydration: Aglyn.FEATURE_FLAG.ENABLED,
|
|
82
|
+
childrenInRoot: Aglyn.FEATURE_FLAG.ENABLED
|
|
83
|
+
},
|
|
78
84
|
description: 'Themed surface with a shadow or an outline.',
|
|
79
85
|
category: Aglyn.ComponentCategory.SURFACE,
|
|
80
86
|
icon: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/components/paper.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 { mdiFileDocumentOutline } from '@aglyn/shared-data-mdi'\nimport MuiPaper from '@mui/material/Paper'\nimport { forwardRef, type ReactNode } from 'react'\nimport { BUNDLE_ID } from '../constants/bundle-common'\nimport {\n applySemanticElement,\n semanticElementAttribute,\n semanticElementLabelAttribute,\n} from '../utils/element-picker'\nimport { dropClearedProps } from '../utils/drop-cleared-props'\nimport { generatePresetId } from '../utils/generate-preset-id'\n\n// Component ids are persisted in screen documents; never rename.\nexport const ID: Aglyn.ComponentId = 'muiPaper'\n\nexport interface PaperElementProps {\n /** Shadow depth, 0–24. Ignored by MUI when `variant` is `outlined`. */\n elevation?: number | string\n variant?: 'elevation' | 'outlined'\n /** If true, corners are not rounded. */\n square?: boolean\n children?: ReactNode\n}\n\n/** MUI's shadow scale tops out at 24; anything above renders unshadowed. */\nexport const MAX_ELEVATION = 24\n\n/**\n * Coerces a persisted elevation to the number MUI's shadow lookup needs.\n *\n * Number-typed attribute fields round-trip through the document as\n * strings often enough that this can't be assumed away: `elevation=\"3\"`\n * indexes MUI's shadow array with a string and yields `undefined`, i.e. a\n * paper the author gave a shadow renders completely flat.\n */\nexport function toElevation(value: unknown): number | undefined {\n if (value === '' || value == null) return undefined\n const parsed = Number(value)\n if (!Number.isFinite(parsed)) return undefined\n return Math.min(Math.max(Math.round(parsed), 0), MAX_ELEVATION)\n}\n\n/**\n * Surface primitive (https://mui.com/material-ui/react-paper/): the\n * themed background + shadow that Card, Accordion and Drawer are all\n * built on, exposed on its own for panels and callouts.\n */\nconst PaperElement = forwardRef<HTMLDivElement, PaperElementProps>(\n (rawProps, ref) => {\n // Cleared props dropped before anything reads them (AGL-1451): `square`\n // and everything else in `rest` spread straight into MUI, where a `null`\n // from the field's ✕ (AGL-1226) is a value rather than an absence.\n const props = dropClearedProps(rawProps)\n const { elevation, variant, children, ...rest } = props\n const resolved = toElevation(elevation)\n return (\n <MuiPaper\n ref={ref}\n // `outlined` has no shadow; passing an elevation alongside it is\n // silently ignored by MUI, so don't pretend otherwise.\n variant={variant === 'outlined' ? 'outlined' : 'elevation'}\n elevation={variant === 'outlined' ? undefined : resolved}\n {...applySemanticElement(rest as Record<string, unknown>)}\n >\n {children}\n </MuiPaper>\n )\n },\n)\nPaperElement.displayName = 'AglynPaper'\n\n/** Elevation only means anything on the (default) `elevation` variant. */\nconst ELEVATION_ONLY = { when: 'variant', is: 'outlined', notMatch: true }\n\nexport const schema: Aglyn.ComponentSchema<PaperElementProps> = {\n $id: ID,\n pluginId: BUNDLE_ID,\n displayName: 'Paper',\n description: 'Themed surface with a shadow or an outline.',\n category: Aglyn.ComponentCategory.SURFACE,\n icon: { path: mdiFileDocumentOutline.path, sx: { color: '#2196f3' } },\n attributes: [\n semanticElementAttribute('this surface'),\n semanticElementLabelAttribute(),\n {\n name: 'variant',\n label: 'Variant',\n description:\n 'Elevation raises the surface with a shadow; outlined draws a ' +\n '1px border instead and has no shadow.',\n component: Aglyn.FieldComponentType.SELECT,\n // A real sentinel rather than a deletion (AGL-1451): unlike Container,\n // \"elevation\" is not a second name for something else in the list —\n // it is MUI's own variant value, the other half of a two-way choice,\n // and the one the Elevation control below is conditioned on. It was\n // spelled `''`, which the attributes form strips on change (AGL-1191),\n // so picking it reverted the field on save.\n options: [\n { value: 'elevation', label: 'Elevation (default)' },\n { value: 'outlined', label: 'Outlined' },\n ],\n },\n {\n name: 'elevation',\n label: 'Elevation',\n description:\n 'Shadow depth from 0 (flat) to 24. In dark mode MUI also lightens ' +\n 'the background as this rises.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n type: 'number',\n // Offering a shadow control on the outlined variant would be a\n // control that silently does nothing.\n condition: ELEVATION_ONLY,\n },\n {\n name: 'square',\n label: 'Square corners?',\n description: 'If true, the corners are not rounded.',\n component: Aglyn.FieldComponentType.SWITCH,\n },\n ],\n}\n\nexport const presets: Aglyn.PresetSchema[] = [\n {\n $id: generatePresetId(ID),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Paper',\n pluginId: BUNDLE_ID,\n description: 'Raised surface for panels and callouts',\n category: Aglyn.ComponentCategory.SURFACE,\n icon: schema.icon,\n data: {\n $id: null,\n componentId: ID,\n pluginId: BUNDLE_ID,\n props: { elevation: 1 },\n // Node-level sx (AGL-1346) — the record the Styles panel edits.\n sx: { paddingTop: 2, paddingRight: 2, paddingBottom: 2, paddingLeft: 2 },\n nodes: [\n {\n $id: null,\n componentId: 'muiTypography',\n pluginId: BUNDLE_ID,\n props: {\n variant: 'body1',\n children: 'Paper is a themed surface. Drop anything inside it.',\n },\n },\n ],\n },\n },\n {\n $id: generatePresetId(ID, 'outlined'),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Paper Outlined',\n pluginId: BUNDLE_ID,\n description: 'Flat surface with a border instead of a shadow',\n category: Aglyn.ComponentCategory.SURFACE,\n icon: schema.icon,\n data: {\n $id: null,\n componentId: ID,\n pluginId: BUNDLE_ID,\n props: { variant: 'outlined' },\n sx: { paddingTop: 2, paddingRight: 2, paddingBottom: 2, paddingLeft: 2 },\n nodes: [\n {\n $id: null,\n componentId: 'muiTypography',\n pluginId: BUNDLE_ID,\n props: {\n variant: 'body1',\n children: 'Outlined paper has a border and no shadow.',\n },\n },\n ],\n },\n },\n]\n\nexport default PaperElement\n"],"names":["Aglyn","mdiFileDocumentOutline","MuiPaper","forwardRef","BUNDLE_ID","applySemanticElement","semanticElementAttribute","semanticElementLabelAttribute","dropClearedProps","generatePresetId","ID","MAX_ELEVATION","toElevation","value","undefined","parsed","Number","isFinite","Math","min","max","round","PaperElement","rawProps","ref","props","elevation","variant","children","rest","resolved","displayName","ELEVATION_ONLY","when","is","notMatch","schema","$id","pluginId","description","category","ComponentCategory","SURFACE","icon","path","sx","color","attributes","name","label","component","FieldComponentType","SELECT","options","TEXT_FIELD","type","condition","SWITCH","presets","NodeType","PRESET","data","componentId","paddingTop","paddingRight","paddingBottom","paddingLeft","nodes"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/components/paper.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 { mdiFileDocumentOutline } from '@aglyn/shared-data-mdi'\nimport MuiPaper from '@mui/material/Paper'\nimport { forwardRef, type ReactNode } from 'react'\nimport { BUNDLE_ID } from '../constants/bundle-common'\nimport {\n applySemanticElement,\n semanticElementAttribute,\n semanticElementLabelAttribute,\n} from '../utils/element-picker'\nimport { dropClearedProps } from '../utils/drop-cleared-props'\nimport { generatePresetId } from '../utils/generate-preset-id'\n\n// Component ids are persisted in screen documents; never rename.\nexport const ID: Aglyn.ComponentId = 'muiPaper'\n\nexport interface PaperElementProps {\n /** Shadow depth, 0–24. Ignored by MUI when `variant` is `outlined`. */\n elevation?: number | string\n variant?: 'elevation' | 'outlined'\n /** If true, corners are not rounded. */\n square?: boolean\n children?: ReactNode\n}\n\n/** MUI's shadow scale tops out at 24; anything above renders unshadowed. */\nexport const MAX_ELEVATION = 24\n\n/**\n * Coerces a persisted elevation to the number MUI's shadow lookup needs.\n *\n * Number-typed attribute fields round-trip through the document as\n * strings often enough that this can't be assumed away: `elevation=\"3\"`\n * indexes MUI's shadow array with a string and yields `undefined`, i.e. a\n * paper the author gave a shadow renders completely flat.\n */\nexport function toElevation(value: unknown): number | undefined {\n if (value === '' || value == null) return undefined\n const parsed = Number(value)\n if (!Number.isFinite(parsed)) return undefined\n return Math.min(Math.max(Math.round(parsed), 0), MAX_ELEVATION)\n}\n\n/**\n * Surface primitive (https://mui.com/material-ui/react-paper/): the\n * themed background + shadow that Card, Accordion and Drawer are all\n * built on, exposed on its own for panels and callouts.\n */\nconst PaperElement = forwardRef<HTMLDivElement, PaperElementProps>(\n (rawProps, ref) => {\n // Cleared props dropped before anything reads them (AGL-1451): `square`\n // and everything else in `rest` spread straight into MUI, where a `null`\n // from the field's ✕ (AGL-1226) is a value rather than an absence.\n const props = dropClearedProps(rawProps)\n const { elevation, variant, children, ...rest } = props\n const resolved = toElevation(elevation)\n return (\n <MuiPaper\n ref={ref}\n // `outlined` has no shadow; passing an elevation alongside it is\n // silently ignored by MUI, so don't pretend otherwise.\n variant={variant === 'outlined' ? 'outlined' : 'elevation'}\n elevation={variant === 'outlined' ? undefined : resolved}\n {...applySemanticElement(rest as Record<string, unknown>)}\n >\n {children}\n </MuiPaper>\n )\n },\n)\nPaperElement.displayName = 'AglynPaper'\n\n/** Elevation only means anything on the (default) `elevation` variant. */\nconst ELEVATION_ONLY = { when: 'variant', is: 'outlined', notMatch: true }\n\nexport const schema: Aglyn.ComponentSchema<PaperElementProps> = {\n $id: ID,\n pluginId: BUNDLE_ID,\n displayName: 'Paper',\n // Static, and its children sit directly in its root: a subtree it heads\n // keeps its server HTML until the visitor nears it (AGL-3581).\n flags: {\n lazyHydration: Aglyn.FEATURE_FLAG.ENABLED,\n childrenInRoot: Aglyn.FEATURE_FLAG.ENABLED,\n },\n description: 'Themed surface with a shadow or an outline.',\n category: Aglyn.ComponentCategory.SURFACE,\n icon: { path: mdiFileDocumentOutline.path, sx: { color: '#2196f3' } },\n attributes: [\n semanticElementAttribute('this surface'),\n semanticElementLabelAttribute(),\n {\n name: 'variant',\n label: 'Variant',\n description:\n 'Elevation raises the surface with a shadow; outlined draws a ' +\n '1px border instead and has no shadow.',\n component: Aglyn.FieldComponentType.SELECT,\n // A real sentinel rather than a deletion (AGL-1451): unlike Container,\n // \"elevation\" is not a second name for something else in the list —\n // it is MUI's own variant value, the other half of a two-way choice,\n // and the one the Elevation control below is conditioned on. It was\n // spelled `''`, which the attributes form strips on change (AGL-1191),\n // so picking it reverted the field on save.\n options: [\n { value: 'elevation', label: 'Elevation (default)' },\n { value: 'outlined', label: 'Outlined' },\n ],\n },\n {\n name: 'elevation',\n label: 'Elevation',\n description:\n 'Shadow depth from 0 (flat) to 24. In dark mode MUI also lightens ' +\n 'the background as this rises.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n type: 'number',\n // Offering a shadow control on the outlined variant would be a\n // control that silently does nothing.\n condition: ELEVATION_ONLY,\n },\n {\n name: 'square',\n label: 'Square corners?',\n description: 'If true, the corners are not rounded.',\n component: Aglyn.FieldComponentType.SWITCH,\n },\n ],\n}\n\nexport const presets: Aglyn.PresetSchema[] = [\n {\n $id: generatePresetId(ID),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Paper',\n pluginId: BUNDLE_ID,\n description: 'Raised surface for panels and callouts',\n category: Aglyn.ComponentCategory.SURFACE,\n icon: schema.icon,\n data: {\n $id: null,\n componentId: ID,\n pluginId: BUNDLE_ID,\n props: { elevation: 1 },\n // Node-level sx (AGL-1346) — the record the Styles panel edits.\n sx: { paddingTop: 2, paddingRight: 2, paddingBottom: 2, paddingLeft: 2 },\n nodes: [\n {\n $id: null,\n componentId: 'muiTypography',\n pluginId: BUNDLE_ID,\n props: {\n variant: 'body1',\n children: 'Paper is a themed surface. Drop anything inside it.',\n },\n },\n ],\n },\n },\n {\n $id: generatePresetId(ID, 'outlined'),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Paper Outlined',\n pluginId: BUNDLE_ID,\n description: 'Flat surface with a border instead of a shadow',\n category: Aglyn.ComponentCategory.SURFACE,\n icon: schema.icon,\n data: {\n $id: null,\n componentId: ID,\n pluginId: BUNDLE_ID,\n props: { variant: 'outlined' },\n sx: { paddingTop: 2, paddingRight: 2, paddingBottom: 2, paddingLeft: 2 },\n nodes: [\n {\n $id: null,\n componentId: 'muiTypography',\n pluginId: BUNDLE_ID,\n props: {\n variant: 'body1',\n children: 'Outlined paper has a border and no shadow.',\n },\n },\n ],\n },\n },\n]\n\nexport default PaperElement\n"],"names":["Aglyn","mdiFileDocumentOutline","MuiPaper","forwardRef","BUNDLE_ID","applySemanticElement","semanticElementAttribute","semanticElementLabelAttribute","dropClearedProps","generatePresetId","ID","MAX_ELEVATION","toElevation","value","undefined","parsed","Number","isFinite","Math","min","max","round","PaperElement","rawProps","ref","props","elevation","variant","children","rest","resolved","displayName","ELEVATION_ONLY","when","is","notMatch","schema","$id","pluginId","flags","lazyHydration","FEATURE_FLAG","ENABLED","childrenInRoot","description","category","ComponentCategory","SURFACE","icon","path","sx","color","attributes","name","label","component","FieldComponentType","SELECT","options","TEXT_FIELD","type","condition","SWITCH","presets","NodeType","PRESET","data","componentId","paddingTop","paddingRight","paddingBottom","paddingLeft","nodes"],"mappings":"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"}
|
|
@@ -198,6 +198,8 @@ export const schema = {
|
|
|
198
198
|
}
|
|
199
199
|
},
|
|
200
200
|
flags: {
|
|
201
|
+
// Static: may sit in a subtree that keeps its server HTML (AGL-3581).
|
|
202
|
+
lazyHydration: Aglyn.FEATURE_FLAG.ENABLED,
|
|
201
203
|
textEditable: Aglyn.FEATURE_FLAG.ENABLED,
|
|
202
204
|
richTextEditable: Aglyn.FEATURE_FLAG.ENABLED
|
|
203
205
|
},
|
|
@@ -1 +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: 'Page Link',\n description: 'Links to another page 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 'Page this link navigates to. The address is generated from the ' +\n 'published path at render time, so it keeps working when the ' +\n \"page's slug or parent changes.\",\n component: Aglyn.FieldComponentType.SCREEN_SELECT,\n label: 'Page',\n },\n {\n name: 'href',\n description:\n 'Where this link goes when it points off this site. Ignored while ' +\n 'Page 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: 'Page 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: 'Page 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":"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"}
|
|
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: 'Page Link',\n description: 'Links to another page 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 // Static: may sit in a subtree that keeps its server HTML (AGL-3581).\n lazyHydration: Aglyn.FEATURE_FLAG.ENABLED,\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 'Page this link navigates to. The address is generated from the ' +\n 'published path at render time, so it keeps working when the ' +\n \"page's slug or parent changes.\",\n component: Aglyn.FieldComponentType.SCREEN_SELECT,\n label: 'Page',\n },\n {\n name: 'href',\n description:\n 'Where this link goes when it points off this site. Ignored while ' +\n 'Page 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: 'Page 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: 'Page 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","lazyHydration","FEATURE_FLAG","ENABLED","textEditable","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":"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"}
|
|
@@ -77,6 +77,12 @@ export const schema = {
|
|
|
77
77
|
$id: ID,
|
|
78
78
|
pluginId: BUNDLE_ID,
|
|
79
79
|
displayName: 'Section',
|
|
80
|
+
// Static, and its children sit directly in its root: a subtree it heads
|
|
81
|
+
// keeps its server HTML until the visitor nears it (AGL-3581).
|
|
82
|
+
flags: {
|
|
83
|
+
lazyHydration: Aglyn.FEATURE_FLAG.ENABLED,
|
|
84
|
+
childrenInRoot: Aglyn.FEATURE_FLAG.ENABLED
|
|
85
|
+
},
|
|
80
86
|
description: 'Groups components inside a semantic HTML element (section, article, nav, …).',
|
|
81
87
|
category: Aglyn.ComponentCategory.LAYOUT,
|
|
82
88
|
icon: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/components/section.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 { mdiPageLayoutBody } from '@aglyn/shared-data-mdi'\nimport Box from '@mui/material/Box'\nimport { forwardRef } from 'react'\nimport { BUNDLE_ID } from '../constants/bundle-common'\nimport { colorSchemeAttribute } from '../utils/color-scheme-attribute'\nimport { generatePresetId } from '../utils/generate-preset-id'\n\n// Component ids are persisted in screen documents; never rename.\nexport const ID: Aglyn.ComponentId = 'section'\n\n/**\n * W3C sectioning/grouping elements the component may render as (AGL-336).\n *\n * ⛔ `main` IS NOT ONE OF THEM (AGL-2486). A published page carries exactly\n * one `main` landmark, placed by composition on the page's content region —\n * the layout's slot, or the screen root when there is no layout, each of which\n * offers its own element picker. An author-selectable `main` on a grouping\n * container that may appear any number of times per page could only ever\n * produce a SECOND one — and two `main` elements is a worse\n * accessibility outcome than none, because the landmark stops naming anything\n * in particular. It was offered in this select, with field help recommending\n * it, which made the duplicate the documented choice rather than a mistake.\n *\n * Removing it degrades rather than breaks: the resolver below falls back to\n * `section` for any value not in this list, so a stored `element: 'main'` on a\n * published screen renders as `<section>` — still a grouping element, still\n * where the author put it, and no longer competing with the layout's landmark.\n */\nexport const SECTION_ELEMENTS = [\n 'section',\n 'div',\n 'article',\n 'aside',\n 'nav',\n 'header',\n 'footer',\n] as const\nexport type SectionElement = (typeof SECTION_ELEMENTS)[number]\n\nexport interface SectionProps {\n /** The DOM element rendered; defaults to `section`. */\n element?: SectionElement\n /** Accessible name announced for landmark elements. */\n ariaLabel?: string\n children?: JSX.Children\n}\n\n/**\n * Semantic grouping container (AGL-336): renders children inside the\n * chosen W3C element so pages keep meaningful document structure\n * (landmarks for assistive tech, better SEO outlines) instead of\n * div-soup. Behaves like any container: droppable, stylable via sx,\n * classes, and interactions.\n */\nconst Section = forwardRef<HTMLElement, SectionProps>((props, ref) => {\n const { element, ariaLabel, children, ...rest } = props\n const component = SECTION_ELEMENTS.includes(element as SectionElement)\n ? (element as SectionElement)\n : 'section'\n return (\n <Box\n ref={ref}\n component={component}\n aria-label={ariaLabel || undefined}\n {...rest}\n >\n {children}\n </Box>\n )\n})\nSection.displayName = 'AglynSection'\n\nexport const schema: Aglyn.ComponentSchema<SectionProps> = {\n $id: ID,\n pluginId: BUNDLE_ID,\n displayName: 'Section',\n description:\n 'Groups components inside a semantic HTML element (section, article, nav, …).',\n category: Aglyn.ComponentCategory.LAYOUT,\n icon: { path: mdiPageLayoutBody.path, sx: { color: '#2196f3' } },\n attributes: [\n {\n name: 'element',\n label: 'Component',\n description:\n 'The DOM element this section renders as, per W3C semantics. ' +\n 'Use section/article/aside/nav/header/footer for meaningful ' +\n 'structure; div for purely visual grouping.',\n component: Aglyn.FieldComponentType.SELECT,\n options: SECTION_ELEMENTS.map((value) => ({ value, label: value })),\n },\n {\n name: 'ariaLabel',\n label: 'Accessible label',\n description:\n 'Names the landmark for screen readers (recommended when a page ' +\n 'has several of the same element).',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n },\n colorSchemeAttribute(),\n ],\n}\n\nexport const presets: Aglyn.PresetSchema[] = [\n {\n $id: generatePresetId(ID),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Section',\n pluginId: BUNDLE_ID,\n description: 'Semantic grouping container (section/div/article/…)',\n category: Aglyn.ComponentCategory.LAYOUT,\n icon: { path: mdiPageLayoutBody.path, sx: { color: '#2196f3' } },\n data: {\n $id: null,\n componentId: ID,\n pluginId: BUNDLE_ID,\n props: { element: 'section' },\n },\n },\n]\n\nexport default Section\n"],"names":["Aglyn","mdiPageLayoutBody","Box","forwardRef","BUNDLE_ID","colorSchemeAttribute","generatePresetId","ID","SECTION_ELEMENTS","Section","props","ref","element","ariaLabel","children","rest","component","includes","aria-label","undefined","displayName","schema","$id","pluginId","description","category","ComponentCategory","LAYOUT","icon","path","sx","color","attributes","name","label","FieldComponentType","SELECT","options","map","value","TEXT_FIELD","presets","type","NodeType","PRESET","data","componentId"],"mappings":";;;AAAA;;;;;;;;;;;;;;;CAeC,GAED,YAAYA,WAAW,eAAc;AACrC,SAASC,iBAAiB,QAAQ,yBAAwB;AAC1D,OAAOC,SAAS,oBAAmB;AACnC,SAASC,UAAU,QAAQ,QAAO;AAClC,SAASC,SAAS,QAAQ,gCAA4B;AACtD,SAASC,oBAAoB,QAAQ,qCAAiC;AACtE,SAASC,gBAAgB,QAAQ,iCAA6B;AAE9D,iEAAiE;AACjE,OAAO,MAAMC,KAAwB,UAAS;AAE9C;;;;;;;;;;;;;;;;;CAiBC,GACD,OAAO,MAAMC,mBAAmB;IAC9B;IACA;IACA;IACA;IACA;IACA;IACA;CACD,CAAS;AAWV;;;;;;CAMC,GACD,MAAMC,wBAAUN,WAAsC,CAACO,OAAOC;IAC5D,MAAM,EAAEC,OAAO,EAAEC,SAAS,EAAEC,QAAQ,EAAW,GAAGJ,OAATK,wCAASL;;;;;IAClD,MAAMM,YAAYR,iBAAiBS,QAAQ,CAACL,WACvCA,UACD;IACJ,qBACE,KAACV;QACCS,KAAKA;QACLK,WAAWA;QACXE,cAAYL,aAAaM;OACrBJ;kBAEHD;;AAGP;AACAL,QAAQW,WAAW,GAAG;AAEtB,OAAO,MAAMC,SAA8C;IACzDC,KAAKf;IACLgB,UAAUnB;IACVgB,aAAa;
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/components/section.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 { mdiPageLayoutBody } from '@aglyn/shared-data-mdi'\nimport Box from '@mui/material/Box'\nimport { forwardRef } from 'react'\nimport { BUNDLE_ID } from '../constants/bundle-common'\nimport { colorSchemeAttribute } from '../utils/color-scheme-attribute'\nimport { generatePresetId } from '../utils/generate-preset-id'\n\n// Component ids are persisted in screen documents; never rename.\nexport const ID: Aglyn.ComponentId = 'section'\n\n/**\n * W3C sectioning/grouping elements the component may render as (AGL-336).\n *\n * ⛔ `main` IS NOT ONE OF THEM (AGL-2486). A published page carries exactly\n * one `main` landmark, placed by composition on the page's content region —\n * the layout's slot, or the screen root when there is no layout, each of which\n * offers its own element picker. An author-selectable `main` on a grouping\n * container that may appear any number of times per page could only ever\n * produce a SECOND one — and two `main` elements is a worse\n * accessibility outcome than none, because the landmark stops naming anything\n * in particular. It was offered in this select, with field help recommending\n * it, which made the duplicate the documented choice rather than a mistake.\n *\n * Removing it degrades rather than breaks: the resolver below falls back to\n * `section` for any value not in this list, so a stored `element: 'main'` on a\n * published screen renders as `<section>` — still a grouping element, still\n * where the author put it, and no longer competing with the layout's landmark.\n */\nexport const SECTION_ELEMENTS = [\n 'section',\n 'div',\n 'article',\n 'aside',\n 'nav',\n 'header',\n 'footer',\n] as const\nexport type SectionElement = (typeof SECTION_ELEMENTS)[number]\n\nexport interface SectionProps {\n /** The DOM element rendered; defaults to `section`. */\n element?: SectionElement\n /** Accessible name announced for landmark elements. */\n ariaLabel?: string\n children?: JSX.Children\n}\n\n/**\n * Semantic grouping container (AGL-336): renders children inside the\n * chosen W3C element so pages keep meaningful document structure\n * (landmarks for assistive tech, better SEO outlines) instead of\n * div-soup. Behaves like any container: droppable, stylable via sx,\n * classes, and interactions.\n */\nconst Section = forwardRef<HTMLElement, SectionProps>((props, ref) => {\n const { element, ariaLabel, children, ...rest } = props\n const component = SECTION_ELEMENTS.includes(element as SectionElement)\n ? (element as SectionElement)\n : 'section'\n return (\n <Box\n ref={ref}\n component={component}\n aria-label={ariaLabel || undefined}\n {...rest}\n >\n {children}\n </Box>\n )\n})\nSection.displayName = 'AglynSection'\n\nexport const schema: Aglyn.ComponentSchema<SectionProps> = {\n $id: ID,\n pluginId: BUNDLE_ID,\n displayName: 'Section',\n // Static, and its children sit directly in its root: a subtree it heads\n // keeps its server HTML until the visitor nears it (AGL-3581).\n flags: {\n lazyHydration: Aglyn.FEATURE_FLAG.ENABLED,\n childrenInRoot: Aglyn.FEATURE_FLAG.ENABLED,\n },\n description:\n 'Groups components inside a semantic HTML element (section, article, nav, …).',\n category: Aglyn.ComponentCategory.LAYOUT,\n icon: { path: mdiPageLayoutBody.path, sx: { color: '#2196f3' } },\n attributes: [\n {\n name: 'element',\n label: 'Component',\n description:\n 'The DOM element this section renders as, per W3C semantics. ' +\n 'Use section/article/aside/nav/header/footer for meaningful ' +\n 'structure; div for purely visual grouping.',\n component: Aglyn.FieldComponentType.SELECT,\n options: SECTION_ELEMENTS.map((value) => ({ value, label: value })),\n },\n {\n name: 'ariaLabel',\n label: 'Accessible label',\n description:\n 'Names the landmark for screen readers (recommended when a page ' +\n 'has several of the same element).',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n },\n colorSchemeAttribute(),\n ],\n}\n\nexport const presets: Aglyn.PresetSchema[] = [\n {\n $id: generatePresetId(ID),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Section',\n pluginId: BUNDLE_ID,\n description: 'Semantic grouping container (section/div/article/…)',\n category: Aglyn.ComponentCategory.LAYOUT,\n icon: { path: mdiPageLayoutBody.path, sx: { color: '#2196f3' } },\n data: {\n $id: null,\n componentId: ID,\n pluginId: BUNDLE_ID,\n props: { element: 'section' },\n },\n },\n]\n\nexport default Section\n"],"names":["Aglyn","mdiPageLayoutBody","Box","forwardRef","BUNDLE_ID","colorSchemeAttribute","generatePresetId","ID","SECTION_ELEMENTS","Section","props","ref","element","ariaLabel","children","rest","component","includes","aria-label","undefined","displayName","schema","$id","pluginId","flags","lazyHydration","FEATURE_FLAG","ENABLED","childrenInRoot","description","category","ComponentCategory","LAYOUT","icon","path","sx","color","attributes","name","label","FieldComponentType","SELECT","options","map","value","TEXT_FIELD","presets","type","NodeType","PRESET","data","componentId"],"mappings":";;;AAAA;;;;;;;;;;;;;;;CAeC,GAED,YAAYA,WAAW,eAAc;AACrC,SAASC,iBAAiB,QAAQ,yBAAwB;AAC1D,OAAOC,SAAS,oBAAmB;AACnC,SAASC,UAAU,QAAQ,QAAO;AAClC,SAASC,SAAS,QAAQ,gCAA4B;AACtD,SAASC,oBAAoB,QAAQ,qCAAiC;AACtE,SAASC,gBAAgB,QAAQ,iCAA6B;AAE9D,iEAAiE;AACjE,OAAO,MAAMC,KAAwB,UAAS;AAE9C;;;;;;;;;;;;;;;;;CAiBC,GACD,OAAO,MAAMC,mBAAmB;IAC9B;IACA;IACA;IACA;IACA;IACA;IACA;CACD,CAAS;AAWV;;;;;;CAMC,GACD,MAAMC,wBAAUN,WAAsC,CAACO,OAAOC;IAC5D,MAAM,EAAEC,OAAO,EAAEC,SAAS,EAAEC,QAAQ,EAAW,GAAGJ,OAATK,wCAASL;;;;;IAClD,MAAMM,YAAYR,iBAAiBS,QAAQ,CAACL,WACvCA,UACD;IACJ,qBACE,KAACV;QACCS,KAAKA;QACLK,WAAWA;QACXE,cAAYL,aAAaM;OACrBJ;kBAEHD;;AAGP;AACAL,QAAQW,WAAW,GAAG;AAEtB,OAAO,MAAMC,SAA8C;IACzDC,KAAKf;IACLgB,UAAUnB;IACVgB,aAAa;IACb,wEAAwE;IACxE,+DAA+D;IAC/DI,OAAO;QACLC,eAAezB,MAAM0B,YAAY,CAACC,OAAO;QACzCC,gBAAgB5B,MAAM0B,YAAY,CAACC,OAAO;IAC5C;IACAE,aACE;IACFC,UAAU9B,MAAM+B,iBAAiB,CAACC,MAAM;IACxCC,MAAM;QAAEC,MAAMjC,kBAAkBiC,IAAI;QAAEC,IAAI;YAAEC,OAAO;QAAU;IAAE;IAC/DC,YAAY;QACV;YACEC,MAAM;YACNC,OAAO;YACPV,aACE,iEACA,gEACA;YACFb,WAAWhB,MAAMwC,kBAAkB,CAACC,MAAM;YAC1CC,SAASlC,iBAAiBmC,GAAG,CAAC,CAACC,QAAW,CAAA;oBAAEA;oBAAOL,OAAOK;gBAAM,CAAA;QAClE;QACA;YACEN,MAAM;YACNC,OAAO;YACPV,aACE,oEACA;YACFb,WAAWhB,MAAMwC,kBAAkB,CAACK,UAAU;QAChD;QACAxC;KACD;AACH,EAAC;AAED,OAAO,MAAMyC,UAAgC;IAC3C;QACExB,KAAKhB,iBAAiBC;QACtBwC,MAAM/C,MAAMgD,QAAQ,CAACC,MAAM;QAC3B7B,aAAa;QACbG,UAAUnB;QACVyB,aAAa;QACbC,UAAU9B,MAAM+B,iBAAiB,CAACC,MAAM;QACxCC,MAAM;YAAEC,MAAMjC,kBAAkBiC,IAAI;YAAEC,IAAI;gBAAEC,OAAO;YAAU;QAAE;QAC/Dc,MAAM;YACJ5B,KAAK;YACL6B,aAAa5C;YACbgB,UAAUnB;YACVM,OAAO;gBAAEE,SAAS;YAAU;QAC9B;IACF;CACD,CAAA;AAED,eAAeH,QAAO"}
|
|
@@ -134,6 +134,10 @@ export const schema = {
|
|
|
134
134
|
$id: ID,
|
|
135
135
|
pluginId: BUNDLE_ID,
|
|
136
136
|
displayName: 'Stack',
|
|
137
|
+
// Static: may sit in a subtree that keeps its server HTML (AGL-3581).
|
|
138
|
+
flags: {
|
|
139
|
+
lazyHydration: Aglyn.FEATURE_FLAG.ENABLED
|
|
140
|
+
},
|
|
137
141
|
description: 'Lays children out in a row or column with even spacing — the workhorse for most layouts.',
|
|
138
142
|
category: Aglyn.ComponentCategory.LAYOUT,
|
|
139
143
|
icon: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/components/stack.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'\nimport {\n mdiViewColumn,\n mdiViewSequential,\n} from '@aglyn/shared-data-mdi'\nimport MuiDivider from '@mui/material/Divider'\nimport MuiStack, { type StackProps } from '@mui/material/Stack'\nimport type { CSSProperties, ReactElement } from 'react'\nimport { createElement, forwardRef } from 'react'\nimport { BUNDLE_ID } from '../constants/bundle-common'\nimport { colorSchemeAttribute } from '../utils/color-scheme-attribute'\nimport {\n applySemanticElement,\n semanticElementAttribute,\n semanticElementLabelAttribute,\n} from '../utils/element-picker'\nimport { dropClearedProps } from '../utils/drop-cleared-props'\nimport { generatePresetId } from '../utils/generate-preset-id'\n\n/**\n * The dividers the `divider` attribute can name (AGL-2486).\n *\n * MUI's own `divider` prop takes a NODE, which an attributes panel cannot\n * author — so the persisted value is a style name and this file builds the\n * element. Anything else (an author's stray string, a paste) renders no\n * divider rather than the literal text between every pair of children.\n */\nconst DIVIDER_STYLES = {\n line: {},\n dashed: { borderStyle: 'dashed' },\n} as const\n\nexport type StackDivider = keyof typeof DIVIDER_STYLES\n\n// justifyContent/alignItems/flexWrap are not direct StackProps in MUI v6+;\n// pass them through sx.\ntype StackWithFlexProps = Omit<StackProps, 'divider'> & {\n justifyContent?: CSSProperties['justifyContent']\n alignItems?: CSSProperties['alignItems']\n flexWrap?: CSSProperties['flexWrap']\n /** Divider STYLE name, not a node — see {@link DIVIDER_STYLES}. */\n divider?: StackDivider | string\n /**\n * A repeat's directives (AGL-103, AGL-181). The published page's\n * composition consumes them before anything renders; a surface that renders\n * the stored node as written, like a component editor, still hands them over.\n */\n repeatDataset?: string\n repeatLimit?: number | string\n repeatFilter?: string\n repeatSort?: string\n}\n\n/**\n * A Stack's divider runs ACROSS the flow, so its orientation is the\n * opposite of the stack's own axis. A responsive `direction` (an array or\n * object) is not authorable here, so only the string form is inspected;\n * anything else falls back to MUI's default horizontal rule.\n */\nfunction buildDivider(\n divider: unknown,\n direction: unknown,\n): ReactElement | undefined {\n if (typeof divider !== 'string') return undefined\n // `hasOwnProperty`, not a truthiness test on the lookup: `\"constructor\"`\n // and friends resolve through Object.prototype and would sail past one.\n if (!Object.prototype.hasOwnProperty.call(DIVIDER_STYLES, divider)) {\n return undefined\n }\n const style = DIVIDER_STYLES[divider as StackDivider]\n const horizontal =\n typeof direction === 'string' && direction.startsWith('row')\n return createElement(MuiDivider, {\n orientation: horizontal ? 'vertical' : 'horizontal',\n // Without it a vertical divider collapses to zero height in a flex row.\n flexItem: horizontal,\n sx: style,\n })\n}\n\n/**\n * Displays that make a Stack the flex container MUI's `spacing` assumes.\n */\nconst FLEX_DISPLAYS = new Set(['flex', 'inline-flex'])\n\n/**\n * Whether an author's `sx` takes the Stack out of flex at any breakpoint\n * (AGL-3214).\n *\n * A function `sx` cannot be read without a theme, so it counts as flex and\n * the stack keeps MUI's own behaviour.\n */\nfunction hasNonFlexDisplay(sx: unknown): boolean {\n if (Array.isArray(sx)) return sx.some(hasNonFlexDisplay)\n if (!sx || typeof sx !== 'object') return false\n const display = (sx as Record<string, unknown>).display\n const notFlex = (value: unknown) =>\n typeof value === 'string' && !FLEX_DISPLAYS.has(value)\n if (typeof display === 'string') return notFlex(display)\n // Responsive, in either of the forms the styles panel writes: an array of\n // breakpoint values, or a `{ xs, md }` map.\n if (Array.isArray(display)) return display.some(notFlex)\n if (display && typeof display === 'object')\n return Object.values(display).some(notFlex)\n return false\n}\n\nconst Stack = forwardRef<HTMLDivElement, StackWithFlexProps>(\n // repeatDataset/repeatLimit are compose-time attributes (AGL-103): the\n // tenant expands them before render; strip so they never hit the DOM.\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n ({ justifyContent, alignItems, flexWrap, divider, useFlexGap, repeatDataset, repeatLimit, repeatFilter, repeatSort, sx, ...props }, ref) =>\n createElement(MuiStack, {\n ref,\n sx: [\n { justifyContent, alignItems, flexWrap },\n ...(Array.isArray(sx) ? sx : sx ? [sx] : []),\n ],\n // The stored value is a style NAME; MUI wants a node (AGL-2486).\n divider: buildDivider(divider, props.direction),\n // A cleared `direction` persists as null, and MUI resolves it as a\n // responsive value — `null.xs` throws during SSR and 500s the page.\n // Same class as the AGL-1226 button colour, different sharp edge.\n // Last, so an author's element wins over anything `props` carried\n // (AGL-2525). A stack IS the nav row on most sites; before this it\n // could only be wrapped in one.\n ...applySemanticElement(dropClearedProps(props) as Record<string, unknown>),\n // After the spread, so the element picker cannot carry a `useFlexGap`\n // past it. `spacing` reaches children as `margin-left` unless this is\n // on, and those margins assume flex: on a grid they land INSIDE the\n // track, so every item but the first sits a spacing-step right of its\n // column and the left gutter goes ragged (AGL-3214). `gap` is correct\n // for grid, multi-column and flex alike, and an author's own `sx` gap\n // still wins over it. A cleared switch persists as null, which is why\n // this reads `??` and not `||` — an author's explicit OFF stands.\n useFlexGap: useFlexGap ?? (hasNonFlexDisplay(sx) || undefined),\n }),\n)\n\n// Component ids are persisted in screen documents; keep the legacy ids.\nexport const ID: Aglyn.ComponentId = 'muiStack'\n\nexport const schema: Aglyn.ComponentSchema = {\n $id: ID,\n pluginId: BUNDLE_ID,\n displayName: 'Stack',\n description:\n 'Lays children out in a row or column with even spacing — the workhorse for most layouts.',\n category: Aglyn.ComponentCategory.LAYOUT,\n icon: {\n path: mdiViewColumn.path,\n sx: { color: '#2196f3' },\n },\n attributes: [\n semanticElementAttribute('this stack'),\n semanticElementLabelAttribute(),\n {\n name: 'direction',\n label: 'Direction',\n description:\n 'Defines the directional flow using the `flex-direction` style property. It is applied for all screen sizes.',\n component: Aglyn.FieldComponentType.SELECT,\n // \"Default\" deleted (AGL-1453): unpersistable, and a second name for\n // `column`, MUI Stack's own default, already on the list.\n options: [\n { value: 'column', label: 'Column' },\n { value: 'column-reverse', label: 'Column Reversed' },\n { value: 'row', label: 'Row' },\n { value: 'row-reverse', label: 'Row Reversed' },\n ],\n },\n {\n name: 'justifyContent',\n label: 'Justify Content',\n description:\n 'Defines how the browser distributes space between and around content items along the main-axis of the container.',\n component: Aglyn.FieldComponentType.SELECT,\n // \"Default\" deleted (AGL-1453). Unpersistable, and a second name for\n // `flex-start`: CSS's initial `justify-content` is `normal`, which on a\n // flex container — which a Stack always is — behaves as `flex-start`.\n //\n // Deleted rather than sentinelled for a second reason specific to this\n // prop: `justifyContent` is destructured out ABOVE and pushed into\n // `sx`, so it never passes through `dropClearedProps`. It is the one\n // attribute on this component the guard does not cover, so the right\n // move is to stop minting values it would have to catch.\n options: [\n { value: 'flex-start', label: 'Flex Start' },\n { value: 'center', label: 'Center' },\n { value: 'flex-end', label: 'Flex End' },\n { value: 'space-between', label: 'Space Between' },\n { value: 'space-around', label: 'Space Around' },\n { value: 'space-evenly', label: 'Space Evenly' },\n ],\n },\n {\n name: 'alignItems',\n label: 'Align Items',\n description:\n 'Defines how the browser distributes space between and around ' +\n 'content items along the cross-axis of the container — the axis ' +\n 'across the Direction.',\n component: Aglyn.FieldComponentType.SELECT,\n // No \"Default\" sentinel (AGL-1453): `stretch` is CSS's own initial\n // `align-items` and is already on the list, and like `justifyContent`\n // this prop is pushed into `sx` rather than through\n // `dropClearedProps`, so an unpersistable `''` would not be caught.\n options: [\n { value: 'stretch', label: 'Stretch' },\n { value: 'flex-start', label: 'Flex Start' },\n { value: 'center', label: 'Center' },\n { value: 'flex-end', label: 'Flex End' },\n { value: 'baseline', label: 'Baseline' },\n ],\n },\n {\n name: 'spacing',\n label: 'Spacing',\n description: 'Defines the space/gap between its immediate children.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n type: 'number',\n },\n {\n name: 'useFlexGap',\n label: 'Use flex gap',\n description:\n 'Space children with the CSS `gap` property instead of margins. ' +\n 'Required for Spacing to survive wrapping, and it leaves child ' +\n 'margins alone — but `gap` is unsupported in some older browsers.',\n component: Aglyn.FieldComponentType.SWITCH,\n },\n {\n name: 'flexWrap',\n label: 'Wrap',\n description:\n 'Whether children that do not fit move onto a new line. Turn on ' +\n 'Use flex gap as well, or Spacing is applied as margins and the ' +\n 'wrapped rows get an uneven gap.',\n component: Aglyn.FieldComponentType.SELECT,\n options: [\n { value: 'nowrap', label: 'No Wrap' },\n { value: 'wrap', label: 'Wrap' },\n { value: 'wrap-reverse', label: 'Wrap Reversed' },\n ],\n },\n {\n name: 'divider',\n label: 'Divider',\n description:\n 'Draws a rule between each pair of children, across the ' +\n 'Direction. Clear the field for no divider.',\n component: Aglyn.FieldComponentType.SELECT,\n // MUI's own prop takes a node; the persisted value is a style name and\n // the component builds the element. No `''` option (AGL-1453) — \"no\n // divider\" is the field's ✕, which persists as cleared.\n options: [\n { value: 'line', label: 'Line' },\n { value: 'dashed', label: 'Dashed' },\n ],\n },\n // No Repeat fields: every element's Attributes panel draws the same Repeat\n // section (AGL-3111), writing the props a Stack has always stored.\n colorSchemeAttribute(),\n ],\n}\n\nexport const presets: Aglyn.PresetSchema[] = [\n {\n $id: generatePresetId(ID),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Stack Horizontal',\n icon: {\n path: mdiViewColumn.path,\n sx: { color: '#2196f3' },\n },\n category: Aglyn.ComponentCategory.LAYOUT,\n data: {\n $id: null,\n componentId: ID,\n pluginId: BUNDLE_ID,\n props: { direction: 'row' },\n },\n },\n {\n $id: generatePresetId(ID, 'vertical'),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Stack Vertical',\n icon: {\n path: mdiViewSequential.path,\n sx: { color: '#2196f3' },\n },\n category: Aglyn.ComponentCategory.LAYOUT,\n data: {\n $id: null,\n componentId: ID,\n pluginId: BUNDLE_ID,\n props: { direction: 'column' },\n },\n },\n]\n\nexport default Stack\n"],"names":["Aglyn","mdiViewColumn","mdiViewSequential","MuiDivider","MuiStack","createElement","forwardRef","BUNDLE_ID","colorSchemeAttribute","applySemanticElement","semanticElementAttribute","semanticElementLabelAttribute","dropClearedProps","generatePresetId","DIVIDER_STYLES","line","dashed","borderStyle","buildDivider","divider","direction","undefined","Object","prototype","hasOwnProperty","call","style","horizontal","startsWith","orientation","flexItem","sx","FLEX_DISPLAYS","Set","hasNonFlexDisplay","Array","isArray","some","display","notFlex","value","has","values","Stack","justifyContent","alignItems","flexWrap","useFlexGap","repeatDataset","repeatLimit","repeatFilter","repeatSort","props","ref","ID","schema","$id","pluginId","displayName","description","category","ComponentCategory","LAYOUT","icon","path","color","attributes","name","label","component","FieldComponentType","SELECT","options","TEXT_FIELD","type","SWITCH","presets","NodeType","PRESET","data","componentId"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/components/stack.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'\nimport {\n mdiViewColumn,\n mdiViewSequential,\n} from '@aglyn/shared-data-mdi'\nimport MuiDivider from '@mui/material/Divider'\nimport MuiStack, { type StackProps } from '@mui/material/Stack'\nimport type { CSSProperties, ReactElement } from 'react'\nimport { createElement, forwardRef } from 'react'\nimport { BUNDLE_ID } from '../constants/bundle-common'\nimport { colorSchemeAttribute } from '../utils/color-scheme-attribute'\nimport {\n applySemanticElement,\n semanticElementAttribute,\n semanticElementLabelAttribute,\n} from '../utils/element-picker'\nimport { dropClearedProps } from '../utils/drop-cleared-props'\nimport { generatePresetId } from '../utils/generate-preset-id'\n\n/**\n * The dividers the `divider` attribute can name (AGL-2486).\n *\n * MUI's own `divider` prop takes a NODE, which an attributes panel cannot\n * author — so the persisted value is a style name and this file builds the\n * element. Anything else (an author's stray string, a paste) renders no\n * divider rather than the literal text between every pair of children.\n */\nconst DIVIDER_STYLES = {\n line: {},\n dashed: { borderStyle: 'dashed' },\n} as const\n\nexport type StackDivider = keyof typeof DIVIDER_STYLES\n\n// justifyContent/alignItems/flexWrap are not direct StackProps in MUI v6+;\n// pass them through sx.\ntype StackWithFlexProps = Omit<StackProps, 'divider'> & {\n justifyContent?: CSSProperties['justifyContent']\n alignItems?: CSSProperties['alignItems']\n flexWrap?: CSSProperties['flexWrap']\n /** Divider STYLE name, not a node — see {@link DIVIDER_STYLES}. */\n divider?: StackDivider | string\n /**\n * A repeat's directives (AGL-103, AGL-181). The published page's\n * composition consumes them before anything renders; a surface that renders\n * the stored node as written, like a component editor, still hands them over.\n */\n repeatDataset?: string\n repeatLimit?: number | string\n repeatFilter?: string\n repeatSort?: string\n}\n\n/**\n * A Stack's divider runs ACROSS the flow, so its orientation is the\n * opposite of the stack's own axis. A responsive `direction` (an array or\n * object) is not authorable here, so only the string form is inspected;\n * anything else falls back to MUI's default horizontal rule.\n */\nfunction buildDivider(\n divider: unknown,\n direction: unknown,\n): ReactElement | undefined {\n if (typeof divider !== 'string') return undefined\n // `hasOwnProperty`, not a truthiness test on the lookup: `\"constructor\"`\n // and friends resolve through Object.prototype and would sail past one.\n if (!Object.prototype.hasOwnProperty.call(DIVIDER_STYLES, divider)) {\n return undefined\n }\n const style = DIVIDER_STYLES[divider as StackDivider]\n const horizontal =\n typeof direction === 'string' && direction.startsWith('row')\n return createElement(MuiDivider, {\n orientation: horizontal ? 'vertical' : 'horizontal',\n // Without it a vertical divider collapses to zero height in a flex row.\n flexItem: horizontal,\n sx: style,\n })\n}\n\n/**\n * Displays that make a Stack the flex container MUI's `spacing` assumes.\n */\nconst FLEX_DISPLAYS = new Set(['flex', 'inline-flex'])\n\n/**\n * Whether an author's `sx` takes the Stack out of flex at any breakpoint\n * (AGL-3214).\n *\n * A function `sx` cannot be read without a theme, so it counts as flex and\n * the stack keeps MUI's own behaviour.\n */\nfunction hasNonFlexDisplay(sx: unknown): boolean {\n if (Array.isArray(sx)) return sx.some(hasNonFlexDisplay)\n if (!sx || typeof sx !== 'object') return false\n const display = (sx as Record<string, unknown>).display\n const notFlex = (value: unknown) =>\n typeof value === 'string' && !FLEX_DISPLAYS.has(value)\n if (typeof display === 'string') return notFlex(display)\n // Responsive, in either of the forms the styles panel writes: an array of\n // breakpoint values, or a `{ xs, md }` map.\n if (Array.isArray(display)) return display.some(notFlex)\n if (display && typeof display === 'object')\n return Object.values(display).some(notFlex)\n return false\n}\n\nconst Stack = forwardRef<HTMLDivElement, StackWithFlexProps>(\n // repeatDataset/repeatLimit are compose-time attributes (AGL-103): the\n // tenant expands them before render; strip so they never hit the DOM.\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n ({ justifyContent, alignItems, flexWrap, divider, useFlexGap, repeatDataset, repeatLimit, repeatFilter, repeatSort, sx, ...props }, ref) =>\n createElement(MuiStack, {\n ref,\n sx: [\n { justifyContent, alignItems, flexWrap },\n ...(Array.isArray(sx) ? sx : sx ? [sx] : []),\n ],\n // The stored value is a style NAME; MUI wants a node (AGL-2486).\n divider: buildDivider(divider, props.direction),\n // A cleared `direction` persists as null, and MUI resolves it as a\n // responsive value — `null.xs` throws during SSR and 500s the page.\n // Same class as the AGL-1226 button colour, different sharp edge.\n // Last, so an author's element wins over anything `props` carried\n // (AGL-2525). A stack IS the nav row on most sites; before this it\n // could only be wrapped in one.\n ...applySemanticElement(dropClearedProps(props) as Record<string, unknown>),\n // After the spread, so the element picker cannot carry a `useFlexGap`\n // past it. `spacing` reaches children as `margin-left` unless this is\n // on, and those margins assume flex: on a grid they land INSIDE the\n // track, so every item but the first sits a spacing-step right of its\n // column and the left gutter goes ragged (AGL-3214). `gap` is correct\n // for grid, multi-column and flex alike, and an author's own `sx` gap\n // still wins over it. A cleared switch persists as null, which is why\n // this reads `??` and not `||` — an author's explicit OFF stands.\n useFlexGap: useFlexGap ?? (hasNonFlexDisplay(sx) || undefined),\n }),\n)\n\n// Component ids are persisted in screen documents; keep the legacy ids.\nexport const ID: Aglyn.ComponentId = 'muiStack'\n\nexport const schema: Aglyn.ComponentSchema = {\n $id: ID,\n pluginId: BUNDLE_ID,\n displayName: 'Stack',\n // Static: may sit in a subtree that keeps its server HTML (AGL-3581).\n flags: { lazyHydration: Aglyn.FEATURE_FLAG.ENABLED },\n description:\n 'Lays children out in a row or column with even spacing — the workhorse for most layouts.',\n category: Aglyn.ComponentCategory.LAYOUT,\n icon: {\n path: mdiViewColumn.path,\n sx: { color: '#2196f3' },\n },\n attributes: [\n semanticElementAttribute('this stack'),\n semanticElementLabelAttribute(),\n {\n name: 'direction',\n label: 'Direction',\n description:\n 'Defines the directional flow using the `flex-direction` style property. It is applied for all screen sizes.',\n component: Aglyn.FieldComponentType.SELECT,\n // \"Default\" deleted (AGL-1453): unpersistable, and a second name for\n // `column`, MUI Stack's own default, already on the list.\n options: [\n { value: 'column', label: 'Column' },\n { value: 'column-reverse', label: 'Column Reversed' },\n { value: 'row', label: 'Row' },\n { value: 'row-reverse', label: 'Row Reversed' },\n ],\n },\n {\n name: 'justifyContent',\n label: 'Justify Content',\n description:\n 'Defines how the browser distributes space between and around content items along the main-axis of the container.',\n component: Aglyn.FieldComponentType.SELECT,\n // \"Default\" deleted (AGL-1453). Unpersistable, and a second name for\n // `flex-start`: CSS's initial `justify-content` is `normal`, which on a\n // flex container — which a Stack always is — behaves as `flex-start`.\n //\n // Deleted rather than sentinelled for a second reason specific to this\n // prop: `justifyContent` is destructured out ABOVE and pushed into\n // `sx`, so it never passes through `dropClearedProps`. It is the one\n // attribute on this component the guard does not cover, so the right\n // move is to stop minting values it would have to catch.\n options: [\n { value: 'flex-start', label: 'Flex Start' },\n { value: 'center', label: 'Center' },\n { value: 'flex-end', label: 'Flex End' },\n { value: 'space-between', label: 'Space Between' },\n { value: 'space-around', label: 'Space Around' },\n { value: 'space-evenly', label: 'Space Evenly' },\n ],\n },\n {\n name: 'alignItems',\n label: 'Align Items',\n description:\n 'Defines how the browser distributes space between and around ' +\n 'content items along the cross-axis of the container — the axis ' +\n 'across the Direction.',\n component: Aglyn.FieldComponentType.SELECT,\n // No \"Default\" sentinel (AGL-1453): `stretch` is CSS's own initial\n // `align-items` and is already on the list, and like `justifyContent`\n // this prop is pushed into `sx` rather than through\n // `dropClearedProps`, so an unpersistable `''` would not be caught.\n options: [\n { value: 'stretch', label: 'Stretch' },\n { value: 'flex-start', label: 'Flex Start' },\n { value: 'center', label: 'Center' },\n { value: 'flex-end', label: 'Flex End' },\n { value: 'baseline', label: 'Baseline' },\n ],\n },\n {\n name: 'spacing',\n label: 'Spacing',\n description: 'Defines the space/gap between its immediate children.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n type: 'number',\n },\n {\n name: 'useFlexGap',\n label: 'Use flex gap',\n description:\n 'Space children with the CSS `gap` property instead of margins. ' +\n 'Required for Spacing to survive wrapping, and it leaves child ' +\n 'margins alone — but `gap` is unsupported in some older browsers.',\n component: Aglyn.FieldComponentType.SWITCH,\n },\n {\n name: 'flexWrap',\n label: 'Wrap',\n description:\n 'Whether children that do not fit move onto a new line. Turn on ' +\n 'Use flex gap as well, or Spacing is applied as margins and the ' +\n 'wrapped rows get an uneven gap.',\n component: Aglyn.FieldComponentType.SELECT,\n options: [\n { value: 'nowrap', label: 'No Wrap' },\n { value: 'wrap', label: 'Wrap' },\n { value: 'wrap-reverse', label: 'Wrap Reversed' },\n ],\n },\n {\n name: 'divider',\n label: 'Divider',\n description:\n 'Draws a rule between each pair of children, across the ' +\n 'Direction. Clear the field for no divider.',\n component: Aglyn.FieldComponentType.SELECT,\n // MUI's own prop takes a node; the persisted value is a style name and\n // the component builds the element. No `''` option (AGL-1453) — \"no\n // divider\" is the field's ✕, which persists as cleared.\n options: [\n { value: 'line', label: 'Line' },\n { value: 'dashed', label: 'Dashed' },\n ],\n },\n // No Repeat fields: every element's Attributes panel draws the same Repeat\n // section (AGL-3111), writing the props a Stack has always stored.\n colorSchemeAttribute(),\n ],\n}\n\nexport const presets: Aglyn.PresetSchema[] = [\n {\n $id: generatePresetId(ID),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Stack Horizontal',\n icon: {\n path: mdiViewColumn.path,\n sx: { color: '#2196f3' },\n },\n category: Aglyn.ComponentCategory.LAYOUT,\n data: {\n $id: null,\n componentId: ID,\n pluginId: BUNDLE_ID,\n props: { direction: 'row' },\n },\n },\n {\n $id: generatePresetId(ID, 'vertical'),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Stack Vertical',\n icon: {\n path: mdiViewSequential.path,\n sx: { color: '#2196f3' },\n },\n category: Aglyn.ComponentCategory.LAYOUT,\n data: {\n $id: null,\n componentId: ID,\n pluginId: BUNDLE_ID,\n props: { direction: 'column' },\n },\n },\n]\n\nexport default Stack\n"],"names":["Aglyn","mdiViewColumn","mdiViewSequential","MuiDivider","MuiStack","createElement","forwardRef","BUNDLE_ID","colorSchemeAttribute","applySemanticElement","semanticElementAttribute","semanticElementLabelAttribute","dropClearedProps","generatePresetId","DIVIDER_STYLES","line","dashed","borderStyle","buildDivider","divider","direction","undefined","Object","prototype","hasOwnProperty","call","style","horizontal","startsWith","orientation","flexItem","sx","FLEX_DISPLAYS","Set","hasNonFlexDisplay","Array","isArray","some","display","notFlex","value","has","values","Stack","justifyContent","alignItems","flexWrap","useFlexGap","repeatDataset","repeatLimit","repeatFilter","repeatSort","props","ref","ID","schema","$id","pluginId","displayName","flags","lazyHydration","FEATURE_FLAG","ENABLED","description","category","ComponentCategory","LAYOUT","icon","path","color","attributes","name","label","component","FieldComponentType","SELECT","options","TEXT_FIELD","type","SWITCH","presets","NodeType","PRESET","data","componentId"],"mappings":"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"}
|
|
@@ -162,6 +162,8 @@ export const schema = {
|
|
|
162
162
|
}
|
|
163
163
|
},
|
|
164
164
|
flags: {
|
|
165
|
+
// Static: may sit in a subtree that keeps its server HTML (AGL-3581).
|
|
166
|
+
lazyHydration: Aglyn.FEATURE_FLAG.ENABLED,
|
|
165
167
|
textEditable: Aglyn.FEATURE_FLAG.ENABLED,
|
|
166
168
|
richTextEditable: Aglyn.FEATURE_FLAG.ENABLED
|
|
167
169
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/components/typography.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as Aglyn from '@aglyn/aglyn'\nimport {\n mdiAlphabetical,\n mdiFormatHeader1,\n mdiFormatHeader2,\n mdiFormatHeader3,\n mdiFormatHeader4,\n mdiFormatHeader5,\n mdiFormatHeader6,\n mdiFormatText,\n} from '@aglyn/shared-data-mdi'\nimport Typography, { type TypographyProps } from '@mui/material/Typography'\nimport { forwardRef } from 'react'\nimport { BUNDLE_ID } from '../constants/bundle-common'\nimport { FIELD_TEXT_CONTENT } from '../constants/field-presets'\nimport { dropClearedProps } from '../utils/drop-cleared-props'\nimport { generatePresetId } from '../utils/generate-preset-id'\n\n// Component ids are persisted in screen documents; keep the legacy ids.\nexport const ID: Aglyn.ComponentId = 'muiTypography'\n// The brand's own rungs sit alongside MUI's. They were added to the theme\n// (AGL-1308 for the body scale, for the display rung) but never to\n// this list, so the only way to reach one was to hand-write its pixels into\n// the Styles panel — which is the very thing the tokens exist to stop.\n// Display first: the list reads largest to smallest.\n//\n// Exported because it is the theme's rung list, not this element's: any block\n// that offers a type step has to offer the SAME one, or a rung added to the\n// theme becomes reachable from the Typography element and nowhere else.\nexport const typographyVariants = [\n {\n value: 'displayXl',\n label: 'Display XL',\n icon: { path: mdiFormatHeader1.path },\n },\n { value: 'h1', label: 'Heading 1', icon: { path: mdiFormatHeader1.path } },\n { value: 'h2', label: 'Heading 2', icon: { path: mdiFormatHeader2.path } },\n { value: 'h3', label: 'Heading 3', icon: { path: mdiFormatHeader3.path } },\n { value: 'h4', label: 'Heading 4', icon: { path: mdiFormatHeader4.path } },\n { value: 'h5', label: 'Heading 5', icon: { path: mdiFormatHeader5.path } },\n { value: 'h6', label: 'Heading 6', icon: { path: mdiFormatHeader6.path } },\n {\n value: 'subtitle1',\n label: 'Subtitle 1',\n icon: { path: mdiFormatText.path },\n },\n {\n value: 'subtitle2',\n label: 'Subtitle 2',\n icon: { path: mdiFormatText.path },\n },\n { value: 'body1', label: 'Body 1', icon: { path: mdiFormatText.path } },\n { value: 'body2', label: 'Body 2', icon: { path: mdiFormatText.path } },\n { value: 'lede', label: 'Lede', icon: { path: mdiFormatText.path } },\n { value: 'overline', label: 'Overline', icon: { path: mdiFormatText.path } },\n { value: 'caption', label: 'Caption', icon: { path: mdiFormatText.path } },\n {\n value: 'bodyCompact',\n label: 'Body compact',\n icon: { path: mdiFormatText.path },\n },\n { value: 'micro', label: 'Micro', icon: { path: mdiFormatText.path } },\n]\n\nexport const schema: Aglyn.ComponentSchema = {\n $id: ID,\n pluginId: BUNDLE_ID,\n displayName: 'Typography',\n description: \"A block of text in one of the theme's type styles.\",\n category: Aglyn.ComponentCategory.TEXT,\n icon: {\n path: mdiAlphabetical.path,\n sx: { color: '#057822' },\n },\n flags: {\n textEditable: Aglyn.FEATURE_FLAG.ENABLED,\n richTextEditable: Aglyn.FEATURE_FLAG.ENABLED,\n },\n attributes: [\n FIELD_TEXT_CONTENT,\n // FIELD_COLOR,\n {\n name: 'variant',\n description:\n 'Which typography step from the site theme this text uses — h1–h6, ' +\n 'body, subtitle, caption, overline. It sets size, weight and line ' +\n 'height together; it does NOT change the HTML element, which is the ' +\n 'field below.',\n component: Aglyn.FieldComponentType.SELECT,\n label: 'Variant',\n // \"Default\" deleted (AGL-1453): unpersistable, and a second name for\n // `body1`, MUI's own default, already in `typographyVariants`.\n options: [...typographyVariants],\n },\n {\n name: 'component',\n description: 'The html element to use.',\n component: Aglyn.FieldComponentType.SELECT,\n label: 'Component',\n // \"Default\" deleted rather than given a sentinel (AGL-1453), and this\n // is the prop that shows why a sentinel is not always available: MUI\n // derives the element from `variantMapping[variant]`, so \"Default\"\n // resolves to a DIFFERENT tag per variant — `h2` for a Heading 2, `p`\n // for Body 1. No single value on this list expresses that, and picking\n // one would pin the tag and change the document outline. Unset is the\n // only thing that means \"let the variant decide\", and the field's ✕ is\n // how an author says it.\n options: [\n { value: 'h1', label: 'Heading 1' },\n { value: 'h2', label: 'Heading 2' },\n { value: 'h3', label: 'Heading 3' },\n { value: 'h4', label: 'Heading 4' },\n { value: 'h5', label: 'Heading 5' },\n { value: 'h6', label: 'Heading 6' },\n { value: 'p', label: 'Paragraph' },\n { value: 'div', label: 'Div' },\n { value: 'span', label: 'Span' },\n ],\n },\n {\n name: 'align',\n description: 'The text alignment',\n component: Aglyn.FieldComponentType.SELECT,\n label: 'Alignment',\n // \"Default\" deleted (AGL-1453): unpersistable, and a second name for\n // `inherit`, MUI Typography's own default, already on the list.\n options: [\n { value: 'inherit', label: 'Inherit' },\n { value: 'left', label: 'Left' },\n { value: 'center', label: 'Center' },\n { value: 'right', label: 'Right' },\n { value: 'justify', label: 'Justified' },\n ],\n },\n {\n name: 'noWrap',\n description: 'If true, the text will not wrap/fold.',\n component: Aglyn.FieldComponentType.SWITCH,\n label: 'Disable wrapping?',\n },\n {\n name: 'gutterBottom',\n description: 'If true, the text will have a space beneath.',\n component: Aglyn.FieldComponentType.SWITCH,\n label: 'Gutter bottom?',\n },\n ],\n}\n\nexport const presets: Aglyn.PresetSchema[] = [\n ...typographyVariants.map((item): Aglyn.PresetSchema => ({\n $id: generatePresetId(ID, item.value),\n type: Aglyn.NodeType.PRESET,\n displayName: item.label,\n pluginId: BUNDLE_ID,\n description: `Element with ${item.label} styles`,\n category: Aglyn.ComponentCategory.TEXT,\n icon: {\n sx: { color: '#057822' },\n ...item.icon,\n },\n data: {\n $id: null,\n componentId: ID,\n pluginId: BUNDLE_ID,\n props: {\n variant: item.value,\n children: item.label,\n },\n },\n })),\n]\n\n/**\n * Typography that renders rich text (AGL-54): when the node carries an\n * `html` prop it renders as innerHTML; otherwise plain `children`.\n *\n * The `html` prop is re-sanitized on EVERY render (AGL-497). The inline\n * editor sanitizes at commit, but screen node props are written directly via\n * the Firebase client SDK, so a host editor can plant arbitrary `html`\n * (bypassing the editor) that would execute on the public site AND in the\n * besigner canvas on app.aglyn.com.\n *\n * The sanitizer is `Aglyn.sanitizeAuthorHtml` (AGL-1901), which needs no DOM\n * and so runs on the server too — the DOMPurify call this replaced could\n * not, which is why the content used to be deferred to an effect and left\n * every rich-text body out of the server response. The allowlist it enforces\n * is a subset of the old DOMPurify config's, pinned pair by pair in\n * `rich-text-hydration.spec.tsx`.\n */\nfunction sanitizeTypographyHtml(html: string): string {\n return Aglyn.sanitizeAuthorHtml(html)\n}\n\n/**\n * MUI's own `defaultVariantMapping`, plus its `span` fallback — the element\n * Typography will actually render for a given variant. Copied rather than\n * imported because MUI does not export it; `author-html-round-trip.spec.tsx`\n * asserts this table still matches what MUI actually renders, so a MUI upgrade that\n * changed the mapping fails there rather than silently reopening the\n * reparenting hazard below.\n */\n/**\n * The element each variant renders as, and the ONE place that decides\n *.\n *\n * MUI's own `variantMapping` sends `subtitle1` and `subtitle2` to `<h6>`.\n * That is a typographic choice made in a component library, and on a page\n * builder it is a document-outline decision made by somebody who has never\n * seen the page: a subtitle is a label, not a section, and every one on every\n * Aglyn site was silently inserting an `<h6>` into the heading order. It is\n * what Lighthouse's `heading-order` was reporting — a \"Open source &\n * self-hostable\" card label rendering ahead of the page's own `<h1>`, from a\n * node whose author had selected Subtitle 1 and nothing else.\n *\n * Subtitles render as `<p>` here. An author who wants a heading still says so\n * with the Component field, which is the control for exactly that question\n * and is unchanged.\n *\n * Passed to MUI as `variantMapping` rather than only consulted by\n * `blockSafeComponent`, so the table cannot describe one thing while the\n * element is another.\n */\nconst VARIANT_ELEMENT: Record<string, string> = {\n h1: 'h1', h2: 'h2', h3: 'h3', h4: 'h4', h5: 'h5', h6: 'h6',\n subtitle1: 'p', subtitle2: 'p', body1: 'p', body2: 'p', inherit: 'p',\n}\n\n/**\n * The element the rich-text body is put INSIDE, which may have to be a\n * `<div>` rather than the one the variant implies (AGL-1901).\n *\n * The parser closes a `<p>` on any block start tag, and a heading on any\n * other heading. So a body with an `<h2>` in it, served inside the `<p>` MUI\n * renders for `body1`, arrives at the browser as\n * `<p class=\"MuiTypography-root\"></p><h2>…</h2>` — the container emptied and\n * the body promoted to a sibling. React then hydrates against a DOM that is\n * not the one it described and reports a mismatch: the live React #418 shape\n * on tenant (AGL-1926), which this change must not add to.\n *\n * This never mattered before because the server `<p>` was EMPTY and the body\n * arrived through an `innerHTML` assignment, which parses in the CONTEXT of\n * the `<p>` and so does not reparent. Serving the body is what makes the\n * container's element type load-bearing.\n *\n * `authorHtmlBreaksContainer` holds the rule, next to the table of tags it\n * depends on. Returns `'div'` to override, or `undefined` to leave MUI's\n * choice alone; the decision is a pure function of props, so the server and\n * the client make it identically.\n */\nfunction blockSafeComponent(\n sanitized: string,\n rest: TypographyProps,\n): 'div' | undefined {\n const element =\n (rest.component as string | undefined) ??\n // MUI's own default variant is `body1`, which maps to `p` — the case that\n // matters, since a Typography with no variant set is the shape nearly\n // every rich-text node has. (`paragraph` is gone in MUI v7, so the\n // variant mapping is the only other input.)\n VARIANT_ELEMENT[(rest.variant as string) ?? 'body1'] ??\n 'span'\n return Aglyn.authorHtmlBreaksContainer(sanitized, element) ? 'div' : undefined\n}\n\nconst AglynTypography = forwardRef<\n HTMLElement,\n TypographyProps & { html?: string }\n>(function AglynTypography(props, ref) {\n const { html, children, ...spread } = props\n // A cleared `align` persists as null and MUI capitalizes it — an SSR throw\n // that 500s the page (AGL-1226, same shape as the button colour).\n const rest = dropClearedProps(spread)\n const hasHtml = typeof html === 'string' && Boolean(html)\n // Sanitized DURING render, on the server and in the browser alike\n // (AGL-1901). The effect this replaced existed because DOMPurify needs a\n // DOM: the server rendered nothing, so the first client render had to\n // render nothing too or hydration would mismatch (AGL-1268) — the two\n // sides agreed only by both being empty, and the body never reached a\n // crawler. `sanitizeAuthorHtml` is a pure function of the string with no\n // DOM dependency, so both sides now compute the same bytes from the same\n // prop and agree on the CONTENT instead of on the absence of it.\n const sanitized = hasHtml ? sanitizeTypographyHtml(html as string) : null\n if (sanitized !== null) {\n // A `<p>` cannot hold the block content a rich-text body may contain —\n // see `blockSafeComponent`. `undefined` leaves MUI's own choice alone.\n const component = blockSafeComponent(sanitized, rest as TypographyProps)\n return (\n <Typography\n ref={ref}\n variantMapping={VARIANT_ELEMENT}\n {...rest}\n {...(component ? { component } : {})}\n dangerouslySetInnerHTML={{ __html: sanitized }}\n />\n )\n }\n return (\n <Typography ref={ref} variantMapping={VARIANT_ELEMENT} {...rest}>\n {children}\n </Typography>\n )\n})\n\nexport default AglynTypography\n"],"names":["Aglyn","mdiAlphabetical","mdiFormatHeader1","mdiFormatHeader2","mdiFormatHeader3","mdiFormatHeader4","mdiFormatHeader5","mdiFormatHeader6","mdiFormatText","Typography","forwardRef","BUNDLE_ID","FIELD_TEXT_CONTENT","dropClearedProps","generatePresetId","ID","typographyVariants","value","label","icon","path","schema","$id","pluginId","displayName","description","category","ComponentCategory","TEXT","sx","color","flags","textEditable","FEATURE_FLAG","ENABLED","richTextEditable","attributes","name","component","FieldComponentType","SELECT","options","SWITCH","presets","map","item","type","NodeType","PRESET","data","componentId","props","variant","children","sanitizeTypographyHtml","html","sanitizeAuthorHtml","VARIANT_ELEMENT","h1","h2","h3","h4","h5","h6","subtitle1","subtitle2","body1","body2","inherit","blockSafeComponent","sanitized","rest","element","authorHtmlBreaksContainer","undefined","AglynTypography","ref","spread","hasHtml","Boolean","variantMapping","dangerouslySetInnerHTML","__html"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/components/typography.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as Aglyn from '@aglyn/aglyn'\nimport {\n mdiAlphabetical,\n mdiFormatHeader1,\n mdiFormatHeader2,\n mdiFormatHeader3,\n mdiFormatHeader4,\n mdiFormatHeader5,\n mdiFormatHeader6,\n mdiFormatText,\n} from '@aglyn/shared-data-mdi'\nimport Typography, { type TypographyProps } from '@mui/material/Typography'\nimport { forwardRef } from 'react'\nimport { BUNDLE_ID } from '../constants/bundle-common'\nimport { FIELD_TEXT_CONTENT } from '../constants/field-presets'\nimport { dropClearedProps } from '../utils/drop-cleared-props'\nimport { generatePresetId } from '../utils/generate-preset-id'\n\n// Component ids are persisted in screen documents; keep the legacy ids.\nexport const ID: Aglyn.ComponentId = 'muiTypography'\n// The brand's own rungs sit alongside MUI's. They were added to the theme\n// (AGL-1308 for the body scale, for the display rung) but never to\n// this list, so the only way to reach one was to hand-write its pixels into\n// the Styles panel — which is the very thing the tokens exist to stop.\n// Display first: the list reads largest to smallest.\n//\n// Exported because it is the theme's rung list, not this element's: any block\n// that offers a type step has to offer the SAME one, or a rung added to the\n// theme becomes reachable from the Typography element and nowhere else.\nexport const typographyVariants = [\n {\n value: 'displayXl',\n label: 'Display XL',\n icon: { path: mdiFormatHeader1.path },\n },\n { value: 'h1', label: 'Heading 1', icon: { path: mdiFormatHeader1.path } },\n { value: 'h2', label: 'Heading 2', icon: { path: mdiFormatHeader2.path } },\n { value: 'h3', label: 'Heading 3', icon: { path: mdiFormatHeader3.path } },\n { value: 'h4', label: 'Heading 4', icon: { path: mdiFormatHeader4.path } },\n { value: 'h5', label: 'Heading 5', icon: { path: mdiFormatHeader5.path } },\n { value: 'h6', label: 'Heading 6', icon: { path: mdiFormatHeader6.path } },\n {\n value: 'subtitle1',\n label: 'Subtitle 1',\n icon: { path: mdiFormatText.path },\n },\n {\n value: 'subtitle2',\n label: 'Subtitle 2',\n icon: { path: mdiFormatText.path },\n },\n { value: 'body1', label: 'Body 1', icon: { path: mdiFormatText.path } },\n { value: 'body2', label: 'Body 2', icon: { path: mdiFormatText.path } },\n { value: 'lede', label: 'Lede', icon: { path: mdiFormatText.path } },\n { value: 'overline', label: 'Overline', icon: { path: mdiFormatText.path } },\n { value: 'caption', label: 'Caption', icon: { path: mdiFormatText.path } },\n {\n value: 'bodyCompact',\n label: 'Body compact',\n icon: { path: mdiFormatText.path },\n },\n { value: 'micro', label: 'Micro', icon: { path: mdiFormatText.path } },\n]\n\nexport const schema: Aglyn.ComponentSchema = {\n $id: ID,\n pluginId: BUNDLE_ID,\n displayName: 'Typography',\n description: \"A block of text in one of the theme's type styles.\",\n category: Aglyn.ComponentCategory.TEXT,\n icon: {\n path: mdiAlphabetical.path,\n sx: { color: '#057822' },\n },\n flags: {\n // Static: may sit in a subtree that keeps its server HTML (AGL-3581).\n lazyHydration: Aglyn.FEATURE_FLAG.ENABLED,\n textEditable: Aglyn.FEATURE_FLAG.ENABLED,\n richTextEditable: Aglyn.FEATURE_FLAG.ENABLED,\n },\n attributes: [\n FIELD_TEXT_CONTENT,\n // FIELD_COLOR,\n {\n name: 'variant',\n description:\n 'Which typography step from the site theme this text uses — h1–h6, ' +\n 'body, subtitle, caption, overline. It sets size, weight and line ' +\n 'height together; it does NOT change the HTML element, which is the ' +\n 'field below.',\n component: Aglyn.FieldComponentType.SELECT,\n label: 'Variant',\n // \"Default\" deleted (AGL-1453): unpersistable, and a second name for\n // `body1`, MUI's own default, already in `typographyVariants`.\n options: [...typographyVariants],\n },\n {\n name: 'component',\n description: 'The html element to use.',\n component: Aglyn.FieldComponentType.SELECT,\n label: 'Component',\n // \"Default\" deleted rather than given a sentinel (AGL-1453), and this\n // is the prop that shows why a sentinel is not always available: MUI\n // derives the element from `variantMapping[variant]`, so \"Default\"\n // resolves to a DIFFERENT tag per variant — `h2` for a Heading 2, `p`\n // for Body 1. No single value on this list expresses that, and picking\n // one would pin the tag and change the document outline. Unset is the\n // only thing that means \"let the variant decide\", and the field's ✕ is\n // how an author says it.\n options: [\n { value: 'h1', label: 'Heading 1' },\n { value: 'h2', label: 'Heading 2' },\n { value: 'h3', label: 'Heading 3' },\n { value: 'h4', label: 'Heading 4' },\n { value: 'h5', label: 'Heading 5' },\n { value: 'h6', label: 'Heading 6' },\n { value: 'p', label: 'Paragraph' },\n { value: 'div', label: 'Div' },\n { value: 'span', label: 'Span' },\n ],\n },\n {\n name: 'align',\n description: 'The text alignment',\n component: Aglyn.FieldComponentType.SELECT,\n label: 'Alignment',\n // \"Default\" deleted (AGL-1453): unpersistable, and a second name for\n // `inherit`, MUI Typography's own default, already on the list.\n options: [\n { value: 'inherit', label: 'Inherit' },\n { value: 'left', label: 'Left' },\n { value: 'center', label: 'Center' },\n { value: 'right', label: 'Right' },\n { value: 'justify', label: 'Justified' },\n ],\n },\n {\n name: 'noWrap',\n description: 'If true, the text will not wrap/fold.',\n component: Aglyn.FieldComponentType.SWITCH,\n label: 'Disable wrapping?',\n },\n {\n name: 'gutterBottom',\n description: 'If true, the text will have a space beneath.',\n component: Aglyn.FieldComponentType.SWITCH,\n label: 'Gutter bottom?',\n },\n ],\n}\n\nexport const presets: Aglyn.PresetSchema[] = [\n ...typographyVariants.map((item): Aglyn.PresetSchema => ({\n $id: generatePresetId(ID, item.value),\n type: Aglyn.NodeType.PRESET,\n displayName: item.label,\n pluginId: BUNDLE_ID,\n description: `Element with ${item.label} styles`,\n category: Aglyn.ComponentCategory.TEXT,\n icon: {\n sx: { color: '#057822' },\n ...item.icon,\n },\n data: {\n $id: null,\n componentId: ID,\n pluginId: BUNDLE_ID,\n props: {\n variant: item.value,\n children: item.label,\n },\n },\n })),\n]\n\n/**\n * Typography that renders rich text (AGL-54): when the node carries an\n * `html` prop it renders as innerHTML; otherwise plain `children`.\n *\n * The `html` prop is re-sanitized on EVERY render (AGL-497). The inline\n * editor sanitizes at commit, but screen node props are written directly via\n * the Firebase client SDK, so a host editor can plant arbitrary `html`\n * (bypassing the editor) that would execute on the public site AND in the\n * besigner canvas on app.aglyn.com.\n *\n * The sanitizer is `Aglyn.sanitizeAuthorHtml` (AGL-1901), which needs no DOM\n * and so runs on the server too — the DOMPurify call this replaced could\n * not, which is why the content used to be deferred to an effect and left\n * every rich-text body out of the server response. The allowlist it enforces\n * is a subset of the old DOMPurify config's, pinned pair by pair in\n * `rich-text-hydration.spec.tsx`.\n */\nfunction sanitizeTypographyHtml(html: string): string {\n return Aglyn.sanitizeAuthorHtml(html)\n}\n\n/**\n * MUI's own `defaultVariantMapping`, plus its `span` fallback — the element\n * Typography will actually render for a given variant. Copied rather than\n * imported because MUI does not export it; `author-html-round-trip.spec.tsx`\n * asserts this table still matches what MUI actually renders, so a MUI upgrade that\n * changed the mapping fails there rather than silently reopening the\n * reparenting hazard below.\n */\n/**\n * The element each variant renders as, and the ONE place that decides\n *.\n *\n * MUI's own `variantMapping` sends `subtitle1` and `subtitle2` to `<h6>`.\n * That is a typographic choice made in a component library, and on a page\n * builder it is a document-outline decision made by somebody who has never\n * seen the page: a subtitle is a label, not a section, and every one on every\n * Aglyn site was silently inserting an `<h6>` into the heading order. It is\n * what Lighthouse's `heading-order` was reporting — a \"Open source &\n * self-hostable\" card label rendering ahead of the page's own `<h1>`, from a\n * node whose author had selected Subtitle 1 and nothing else.\n *\n * Subtitles render as `<p>` here. An author who wants a heading still says so\n * with the Component field, which is the control for exactly that question\n * and is unchanged.\n *\n * Passed to MUI as `variantMapping` rather than only consulted by\n * `blockSafeComponent`, so the table cannot describe one thing while the\n * element is another.\n */\nconst VARIANT_ELEMENT: Record<string, string> = {\n h1: 'h1', h2: 'h2', h3: 'h3', h4: 'h4', h5: 'h5', h6: 'h6',\n subtitle1: 'p', subtitle2: 'p', body1: 'p', body2: 'p', inherit: 'p',\n}\n\n/**\n * The element the rich-text body is put INSIDE, which may have to be a\n * `<div>` rather than the one the variant implies (AGL-1901).\n *\n * The parser closes a `<p>` on any block start tag, and a heading on any\n * other heading. So a body with an `<h2>` in it, served inside the `<p>` MUI\n * renders for `body1`, arrives at the browser as\n * `<p class=\"MuiTypography-root\"></p><h2>…</h2>` — the container emptied and\n * the body promoted to a sibling. React then hydrates against a DOM that is\n * not the one it described and reports a mismatch: the live React #418 shape\n * on tenant (AGL-1926), which this change must not add to.\n *\n * This never mattered before because the server `<p>` was EMPTY and the body\n * arrived through an `innerHTML` assignment, which parses in the CONTEXT of\n * the `<p>` and so does not reparent. Serving the body is what makes the\n * container's element type load-bearing.\n *\n * `authorHtmlBreaksContainer` holds the rule, next to the table of tags it\n * depends on. Returns `'div'` to override, or `undefined` to leave MUI's\n * choice alone; the decision is a pure function of props, so the server and\n * the client make it identically.\n */\nfunction blockSafeComponent(\n sanitized: string,\n rest: TypographyProps,\n): 'div' | undefined {\n const element =\n (rest.component as string | undefined) ??\n // MUI's own default variant is `body1`, which maps to `p` — the case that\n // matters, since a Typography with no variant set is the shape nearly\n // every rich-text node has. (`paragraph` is gone in MUI v7, so the\n // variant mapping is the only other input.)\n VARIANT_ELEMENT[(rest.variant as string) ?? 'body1'] ??\n 'span'\n return Aglyn.authorHtmlBreaksContainer(sanitized, element) ? 'div' : undefined\n}\n\nconst AglynTypography = forwardRef<\n HTMLElement,\n TypographyProps & { html?: string }\n>(function AglynTypography(props, ref) {\n const { html, children, ...spread } = props\n // A cleared `align` persists as null and MUI capitalizes it — an SSR throw\n // that 500s the page (AGL-1226, same shape as the button colour).\n const rest = dropClearedProps(spread)\n const hasHtml = typeof html === 'string' && Boolean(html)\n // Sanitized DURING render, on the server and in the browser alike\n // (AGL-1901). The effect this replaced existed because DOMPurify needs a\n // DOM: the server rendered nothing, so the first client render had to\n // render nothing too or hydration would mismatch (AGL-1268) — the two\n // sides agreed only by both being empty, and the body never reached a\n // crawler. `sanitizeAuthorHtml` is a pure function of the string with no\n // DOM dependency, so both sides now compute the same bytes from the same\n // prop and agree on the CONTENT instead of on the absence of it.\n const sanitized = hasHtml ? sanitizeTypographyHtml(html as string) : null\n if (sanitized !== null) {\n // A `<p>` cannot hold the block content a rich-text body may contain —\n // see `blockSafeComponent`. `undefined` leaves MUI's own choice alone.\n const component = blockSafeComponent(sanitized, rest as TypographyProps)\n return (\n <Typography\n ref={ref}\n variantMapping={VARIANT_ELEMENT}\n {...rest}\n {...(component ? { component } : {})}\n dangerouslySetInnerHTML={{ __html: sanitized }}\n />\n )\n }\n return (\n <Typography ref={ref} variantMapping={VARIANT_ELEMENT} {...rest}>\n {children}\n </Typography>\n )\n})\n\nexport default AglynTypography\n"],"names":["Aglyn","mdiAlphabetical","mdiFormatHeader1","mdiFormatHeader2","mdiFormatHeader3","mdiFormatHeader4","mdiFormatHeader5","mdiFormatHeader6","mdiFormatText","Typography","forwardRef","BUNDLE_ID","FIELD_TEXT_CONTENT","dropClearedProps","generatePresetId","ID","typographyVariants","value","label","icon","path","schema","$id","pluginId","displayName","description","category","ComponentCategory","TEXT","sx","color","flags","lazyHydration","FEATURE_FLAG","ENABLED","textEditable","richTextEditable","attributes","name","component","FieldComponentType","SELECT","options","SWITCH","presets","map","item","type","NodeType","PRESET","data","componentId","props","variant","children","sanitizeTypographyHtml","html","sanitizeAuthorHtml","VARIANT_ELEMENT","h1","h2","h3","h4","h5","h6","subtitle1","subtitle2","body1","body2","inherit","blockSafeComponent","sanitized","rest","element","authorHtmlBreaksContainer","undefined","AglynTypography","ref","spread","hasHtml","Boolean","variantMapping","dangerouslySetInnerHTML","__html"],"mappings":";;;AAAA;;;;;;;;;;;;;;;CAeC,GAED,YAAYA,WAAW,eAAc;AACrC,SACEC,eAAe,EACfC,gBAAgB,EAChBC,gBAAgB,EAChBC,gBAAgB,EAChBC,gBAAgB,EAChBC,gBAAgB,EAChBC,gBAAgB,EAChBC,aAAa,QACR,yBAAwB;AAC/B,OAAOC,gBAA0C,2BAA0B;AAC3E,SAASC,UAAU,QAAQ,QAAO;AAClC,SAASC,SAAS,QAAQ,gCAA4B;AACtD,SAASC,kBAAkB,QAAQ,gCAA4B;AAC/D,SAASC,gBAAgB,QAAQ,iCAA6B;AAC9D,SAASC,gBAAgB,QAAQ,iCAA6B;AAE9D,wEAAwE;AACxE,OAAO,MAAMC,KAAwB,gBAAe;AACpD,0EAA0E;AAC1E,mEAAmE;AACnE,4EAA4E;AAC5E,uEAAuE;AACvE,qDAAqD;AACrD,EAAE;AACF,8EAA8E;AAC9E,4EAA4E;AAC5E,wEAAwE;AACxE,OAAO,MAAMC,qBAAqB;IAChC;QACEC,OAAO;QACPC,OAAO;QACPC,MAAM;YAAEC,MAAMlB,iBAAiBkB,IAAI;QAAC;IACtC;IACA;QAAEH,OAAO;QAAMC,OAAO;QAAaC,MAAM;YAAEC,MAAMlB,iBAAiBkB,IAAI;QAAC;IAAE;IACzE;QAAEH,OAAO;QAAMC,OAAO;QAAaC,MAAM;YAAEC,MAAMjB,iBAAiBiB,IAAI;QAAC;IAAE;IACzE;QAAEH,OAAO;QAAMC,OAAO;QAAaC,MAAM;YAAEC,MAAMhB,iBAAiBgB,IAAI;QAAC;IAAE;IACzE;QAAEH,OAAO;QAAMC,OAAO;QAAaC,MAAM;YAAEC,MAAMf,iBAAiBe,IAAI;QAAC;IAAE;IACzE;QAAEH,OAAO;QAAMC,OAAO;QAAaC,MAAM;YAAEC,MAAMd,iBAAiBc,IAAI;QAAC;IAAE;IACzE;QAAEH,OAAO;QAAMC,OAAO;QAAaC,MAAM;YAAEC,MAAMb,iBAAiBa,IAAI;QAAC;IAAE;IACzE;QACEH,OAAO;QACPC,OAAO;QACPC,MAAM;YAAEC,MAAMZ,cAAcY,IAAI;QAAC;IACnC;IACA;QACEH,OAAO;QACPC,OAAO;QACPC,MAAM;YAAEC,MAAMZ,cAAcY,IAAI;QAAC;IACnC;IACA;QAAEH,OAAO;QAASC,OAAO;QAAUC,MAAM;YAAEC,MAAMZ,cAAcY,IAAI;QAAC;IAAE;IACtE;QAAEH,OAAO;QAASC,OAAO;QAAUC,MAAM;YAAEC,MAAMZ,cAAcY,IAAI;QAAC;IAAE;IACtE;QAAEH,OAAO;QAAQC,OAAO;QAAQC,MAAM;YAAEC,MAAMZ,cAAcY,IAAI;QAAC;IAAE;IACnE;QAAEH,OAAO;QAAYC,OAAO;QAAYC,MAAM;YAAEC,MAAMZ,cAAcY,IAAI;QAAC;IAAE;IAC3E;QAAEH,OAAO;QAAWC,OAAO;QAAWC,MAAM;YAAEC,MAAMZ,cAAcY,IAAI;QAAC;IAAE;IACzE;QACEH,OAAO;QACPC,OAAO;QACPC,MAAM;YAAEC,MAAMZ,cAAcY,IAAI;QAAC;IACnC;IACA;QAAEH,OAAO;QAASC,OAAO;QAASC,MAAM;YAAEC,MAAMZ,cAAcY,IAAI;QAAC;IAAE;CACtE,CAAA;AAED,OAAO,MAAMC,SAAgC;IAC3CC,KAAKP;IACLQ,UAAUZ;IACVa,aAAa;IACbC,aAAa;IACbC,UAAU1B,MAAM2B,iBAAiB,CAACC,IAAI;IACtCT,MAAM;QACJC,MAAMnB,gBAAgBmB,IAAI;QAC1BS,IAAI;YAAEC,OAAO;QAAU;IACzB;IACAC,OAAO;QACL,sEAAsE;QACtEC,eAAehC,MAAMiC,YAAY,CAACC,OAAO;QACzCC,cAAcnC,MAAMiC,YAAY,CAACC,OAAO;QACxCE,kBAAkBpC,MAAMiC,YAAY,CAACC,OAAO;IAC9C;IACAG,YAAY;QACVzB;QACA,eAAe;QACf;YACE0B,MAAM;YACNb,aACE,uEACA,sEACA,wEACA;YACFc,WAAWvC,MAAMwC,kBAAkB,CAACC,MAAM;YAC1CvB,OAAO;YACP,qEAAqE;YACrE,+DAA+D;YAC/DwB,SAAS;mBAAI1B;aAAmB;QAClC;QACA;YACEsB,MAAM;YACNb,aAAa;YACbc,WAAWvC,MAAMwC,kBAAkB,CAACC,MAAM;YAC1CvB,OAAO;YACP,sEAAsE;YACtE,qEAAqE;YACrE,mEAAmE;YACnE,sEAAsE;YACtE,uEAAuE;YACvE,sEAAsE;YACtE,uEAAuE;YACvE,yBAAyB;YACzBwB,SAAS;gBACP;oBAAEzB,OAAO;oBAAMC,OAAO;gBAAY;gBAClC;oBAAED,OAAO;oBAAMC,OAAO;gBAAY;gBAClC;oBAAED,OAAO;oBAAMC,OAAO;gBAAY;gBAClC;oBAAED,OAAO;oBAAMC,OAAO;gBAAY;gBAClC;oBAAED,OAAO;oBAAMC,OAAO;gBAAY;gBAClC;oBAAED,OAAO;oBAAMC,OAAO;gBAAY;gBAClC;oBAAED,OAAO;oBAAKC,OAAO;gBAAY;gBACjC;oBAAED,OAAO;oBAAOC,OAAO;gBAAM;gBAC7B;oBAAED,OAAO;oBAAQC,OAAO;gBAAO;aAChC;QACH;QACA;YACEoB,MAAM;YACNb,aAAa;YACbc,WAAWvC,MAAMwC,kBAAkB,CAACC,MAAM;YAC1CvB,OAAO;YACP,qEAAqE;YACrE,gEAAgE;YAChEwB,SAAS;gBACP;oBAAEzB,OAAO;oBAAWC,OAAO;gBAAU;gBACrC;oBAAED,OAAO;oBAAQC,OAAO;gBAAO;gBAC/B;oBAAED,OAAO;oBAAUC,OAAO;gBAAS;gBACnC;oBAAED,OAAO;oBAASC,OAAO;gBAAQ;gBACjC;oBAAED,OAAO;oBAAWC,OAAO;gBAAY;aACxC;QACH;QACA;YACEoB,MAAM;YACNb,aAAa;YACbc,WAAWvC,MAAMwC,kBAAkB,CAACG,MAAM;YAC1CzB,OAAO;QACT;QACA;YACEoB,MAAM;YACNb,aAAa;YACbc,WAAWvC,MAAMwC,kBAAkB,CAACG,MAAM;YAC1CzB,OAAO;QACT;KACD;AACH,EAAC;AAED,OAAO,MAAM0B,UAAgC;OACxC5B,mBAAmB6B,GAAG,CAAC,CAACC,OAA8B,CAAA;YACvDxB,KAAKR,iBAAiBC,IAAI+B,KAAK7B,KAAK;YACpC8B,MAAM/C,MAAMgD,QAAQ,CAACC,MAAM;YAC3BzB,aAAasB,KAAK5B,KAAK;YACvBK,UAAUZ;YACVc,aAAa,CAAC,aAAa,EAAEqB,KAAK5B,KAAK,CAAC,OAAO,CAAC;YAChDQ,UAAU1B,MAAM2B,iBAAiB,CAACC,IAAI;YACtCT,MAAM;gBACJU,IAAI;oBAAEC,OAAO;gBAAU;eACpBgB,KAAK3B,IAAI;YAEd+B,MAAM;gBACJ5B,KAAK;gBACL6B,aAAapC;gBACbQ,UAAUZ;gBACVyC,OAAO;oBACLC,SAASP,KAAK7B,KAAK;oBACnBqC,UAAUR,KAAK5B,KAAK;gBACtB;YACF;QACF,CAAA;CACD,CAAA;AAED;;;;;;;;;;;;;;;;CAgBC,GACD,SAASqC,uBAAuBC,IAAY;IAC1C,OAAOxD,MAAMyD,kBAAkB,CAACD;AAClC;AAEA;;;;;;;CAOC,GACD;;;;;;;;;;;;;;;;;;;;CAoBC,GACD,MAAME,kBAA0C;IAC9CC,IAAI;IAAMC,IAAI;IAAMC,IAAI;IAAMC,IAAI;IAAMC,IAAI;IAAMC,IAAI;IACtDC,WAAW;IAAKC,WAAW;IAAKC,OAAO;IAAKC,OAAO;IAAKC,SAAS;AACnE;AAEA;;;;;;;;;;;;;;;;;;;;;CAqBC,GACD,SAASC,mBACPC,SAAiB,EACjBC,IAAqB;QAGnB,MAACA,iBAKgBA;IANnB,MAAMC,WACJ,QAACD,kBAAAA,KAAKjC,SAAS,YAAdiC,kBACD,0EAA0E;IAC1E,sEAAsE;IACtE,mEAAmE;IACnE,4CAA4C;IAC5Cd,eAAe,EAAEc,gBAAAA,KAAKnB,OAAO,YAAZmB,gBAA2B,QAAQ,YALpD,OAMA;IACF,OAAOxE,MAAM0E,yBAAyB,CAACH,WAAWE,WAAW,QAAQE;AACvE;AAEA,MAAMC,gCAAkBlE,WAGtB,SAASkE,gBAAgBxB,KAAK,EAAEyB,GAAG;IACnC,MAAM,EAAErB,IAAI,EAAEF,QAAQ,EAAa,GAAGF,OAAX0B,0CAAW1B;;;;IACtC,2EAA2E;IAC3E,kEAAkE;IAClE,MAAMoB,OAAO3D,iBAAiBiE;IAC9B,MAAMC,UAAU,OAAOvB,SAAS,YAAYwB,QAAQxB;IACpD,kEAAkE;IAClE,yEAAyE;IACzE,sEAAsE;IACtE,sEAAsE;IACtE,sEAAsE;IACtE,yEAAyE;IACzE,yEAAyE;IACzE,iEAAiE;IACjE,MAAMe,YAAYQ,UAAUxB,uBAAuBC,QAAkB;IACrE,IAAIe,cAAc,MAAM;QACtB,uEAAuE;QACvE,uEAAuE;QACvE,MAAMhC,YAAY+B,mBAAmBC,WAAWC;QAChD,qBACE,KAAC/D;YACCoE,KAAKA;YACLI,gBAAgBvB;WACZc,MACCjC,YAAY;YAAEA;QAAU,IAAI,CAAC;YAClC2C,yBAAyB;gBAAEC,QAAQZ;YAAU;;IAGnD;IACA,qBACE,KAAC9D;QAAWoE,KAAKA;QAAKI,gBAAgBvB;OAAqBc;kBACxDlB;;AAGP;AAEA,eAAesB,gBAAe"}
|