@aglyn/plugins-mui 1.0.0-beta.216 → 1.0.0-beta.218
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/README.md +2 -1
- package/package.json +9 -9
- package/src/lib/components/markdown.d.ts +3 -1
- package/src/lib/components/pagination.d.ts +1 -1
- package/src/lib/components/pagination.js +4 -0
- package/src/lib/components/pagination.js.map +1 -1
- package/src/lib/components/tabs.d.ts +1 -1
- package/src/lib/components/tabs.js +4 -0
- package/src/lib/components/tabs.js.map +1 -1
- package/src/lib/constants/field-presets.js +4 -0
- package/src/lib/constants/field-presets.js.map +1 -1
- package/src/lib/element-tier.d.ts +0 -2
- package/src/lib/element-tier.js +0 -2
- package/src/lib/element-tier.js.map +1 -1
- package/src/lib/plugin.js +0 -32
- package/src/lib/plugin.js.map +1 -1
- package/src/lib/components/function-controls.d.ts +0 -66
- package/src/lib/components/function-controls.js +0 -207
- package/src/lib/components/function-controls.js.map +0 -1
- package/src/lib/components/function-scope.d.ts +0 -110
- package/src/lib/components/function-scope.js +0 -478
- package/src/lib/components/function-scope.js.map +0 -1
- package/src/lib/components/function-widget.d.ts +0 -75
- package/src/lib/components/function-widget.js +0 -307
- package/src/lib/components/function-widget.js.map +0 -1
package/README.md
CHANGED
|
@@ -22,9 +22,10 @@ The plugin has one registrar, `registerMuiPlugin` (the `site` registrar in `plug
|
|
|
22
22
|
- Surfaces: `muiCard` and its header, content and actions, `muiAccordion` and its summary and details, `muiTabs`, `muiTabPanel`, `muiList`, `muiListItem`, `muiListItemText`.
|
|
23
23
|
- Media: `image`, `video`, `videoEmbed`, `muiImageList`, `muiImageListItem`, `socialLinks`.
|
|
24
24
|
- Data and content: `dataTable`, `collectionEntries`, `collectionEntryBody`, `collectionEntryMeta`, `collectionEntryAuthor`, `collectionRelated`, `collectionShare`, `collectionCategories`, `collectionSearch`, `contentAuthorProfile`, `product`.
|
|
25
|
-
- Functions: `functionWidget`, `functionScope`, `functionInput`, `functionOutput`, `functionShow`.
|
|
26
25
|
- Other: `reusableInstance`, `custom-html`, `marketplacePlugin`, and `div`, the root of a document.
|
|
27
26
|
|
|
27
|
+
The calculator elements that put a site function on a page are not here: they are the Calculators marketplace plugin (`libs/plugins/calculator`, ids `aglyn.calculator.*`).
|
|
28
|
+
|
|
28
29
|
**Component ids are persisted.** Every node in a saved screen document stores its `componentId` beside `pluginId: 'mui'`, so the ids above, including the legacy `mui`-prefixed ones, do not change without a document migration.
|
|
29
30
|
|
|
30
31
|
**Per-component loading.** Each element lives in its own module behind a dynamic import. `registerMuiPlugin(use)` accepts a `PluginUse` from `@aglyn/aglyn`; when `use.componentIds` names the elements a page places, only those modules are fetched. Called with no argument it registers the whole library, which is what the console and the Besigner need for their palette. Calling it again with further ids adds to what is already registered.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aglyn/plugins-mui",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.218",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"homepage": "https://aglyn.com",
|
|
6
6
|
"repository": {
|
|
@@ -25,15 +25,15 @@
|
|
|
25
25
|
"./package.json": "./package.json"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@aglyn/aglyn": "1.0.0-beta.
|
|
29
|
-
"@aglyn/shared-data-enums": "1.0.0-beta.
|
|
30
|
-
"@aglyn/shared-data-mdi": "1.0.0-beta.
|
|
31
|
-
"@aglyn/shared-ui-jsx": "1.0.0-beta.
|
|
32
|
-
"@aglyn/shared-ui-theme": "1.0.0-beta.
|
|
33
|
-
"@aglyn/shared-util-vendor": "1.0.0-beta.
|
|
28
|
+
"@aglyn/aglyn": "1.0.0-beta.218",
|
|
29
|
+
"@aglyn/shared-data-enums": "1.0.0-beta.218",
|
|
30
|
+
"@aglyn/shared-data-mdi": "1.0.0-beta.218",
|
|
31
|
+
"@aglyn/shared-ui-jsx": "1.0.0-beta.218",
|
|
32
|
+
"@aglyn/shared-ui-theme": "1.0.0-beta.218",
|
|
33
|
+
"@aglyn/shared-util-vendor": "1.0.0-beta.218",
|
|
34
34
|
"@swc/helpers": "0.5.23",
|
|
35
|
-
"mobx": "^
|
|
36
|
-
"mobx-react-lite": "^
|
|
35
|
+
"mobx": "^7.0.5",
|
|
36
|
+
"mobx-react-lite": "^5.1.0"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@mui/material": "^9.3.1",
|
|
@@ -121,7 +121,9 @@ export declare function scrollToHeading(anchor: Element, slug: string): boolean;
|
|
|
121
121
|
* so without this the aside in the besigner would keep listing the headings
|
|
122
122
|
* of the document as it was when the aside mounted.
|
|
123
123
|
*/
|
|
124
|
-
declare const TableOfContents: import("react").
|
|
124
|
+
declare const TableOfContents: import("react").ForwardRefExoticComponent<Omit<TableOfContentsProps, "ref"> & import("react").RefAttributes<HTMLElement>> & import("react").NamedExoticComponent<Omit<TableOfContentsProps, "ref"> & import("react").RefAttributes<HTMLElement>> & {
|
|
125
|
+
readonly type: import("react").ForwardRefExoticComponent<Omit<TableOfContentsProps, "ref"> & import("react").RefAttributes<HTMLElement>>;
|
|
126
|
+
};
|
|
125
127
|
export declare const markdownSchema: Aglyn.ComponentSchema<MarkdownProps>;
|
|
126
128
|
export declare const tableOfContentsSchema: Aglyn.ComponentSchema<TableOfContentsProps>;
|
|
127
129
|
export declare const markdownPresets: Aglyn.PresetSchema[];
|
|
@@ -20,7 +20,7 @@ export declare const ID: Aglyn.ComponentId;
|
|
|
20
20
|
export interface PaginationElementProps {
|
|
21
21
|
count?: number | string;
|
|
22
22
|
defaultPage?: number | string;
|
|
23
|
-
color?: 'primary' | 'secondary' | 'standard';
|
|
23
|
+
color?: 'primary' | 'secondary' | 'tertiary' | 'standard';
|
|
24
24
|
shape?: 'circular' | 'rounded';
|
|
25
25
|
size?: 'small' | 'medium' | 'large';
|
|
26
26
|
variant?: 'text' | 'outlined';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/components/pagination.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 { mdiFormatListNumbered } from '@aglyn/shared-data-mdi'\nimport MuiPagination from '@mui/material/Pagination'\nimport { forwardRef, type ReactNode } from 'react'\nimport { BUNDLE_ID } from '../constants/bundle-common'\nimport { FIELD_DISABLED, FIELD_SIZE } 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; never rename.\nexport const ID: Aglyn.ComponentId = 'muiPagination'\n\nexport interface PaginationElementProps {\n count?: number | string\n defaultPage?: number | string\n color?: 'primary' | 'secondary' | 'standard'\n shape?: 'circular' | 'rounded'\n size?: 'small' | 'medium' | 'large'\n variant?: 'text' | 'outlined'\n siblingCount?: number | string\n boundaryCount?: number | string\n showFirstButton?: boolean\n showLastButton?: boolean\n hidePrevButton?: boolean\n hideNextButton?: boolean\n disabled?: boolean\n /**\n * Accepted and dropped. The element is self-closing (see `flags`), so the\n * editor never authors children — but the renderer builds elements from\n * persisted props, and a stray child from an older document would reach\n * MUI's Pagination and render beside the page list. Declared because the\n * implementation deliberately discards it (AGL-1323).\n */\n children?: ReactNode\n}\n\n/** Number-typed attribute fields round-trip as strings. */\nfunction toCount(value: unknown, fallback: number): number {\n if (value == null || value === '') return fallback\n const parsed = Number(value)\n if (!Number.isFinite(parsed) || parsed < 0) return fallback\n return Math.round(parsed)\n}\n\n/**\n * Pagination control (https://mui.com/material-ui/react-pagination/).\n *\n * Uncontrolled: it tracks and highlights the page a visitor picks, but\n * it does not by itself fetch or filter anything — pair it with an\n * interaction, or with a repeat that reads the page. That is stated in\n * the element's own description too, because a page-picker that looks\n * wired and isn't is worse than one that says what it is.\n *\n * The `size` here is MUI's own three-value scale; the shared FIELD_SIZE\n * preset also offers `inherit`, which Pagination does not accept, so the\n * shared field is narrowed rather than re-declared.\n */\nconst PaginationElement = forwardRef<HTMLElement, PaginationElementProps>(\n (props, ref) => {\n const {\n count,\n defaultPage,\n siblingCount,\n boundaryCount,\n children: _children,\n ...spread\n } = props\n // A cleared `color`/`size` persists as null; MUI capitalizes both and\n // throws during SSR, 500ing the page (AGL-1226).\n const rest = dropClearedProps(spread)\n const total = toCount(count, 10)\n return (\n <MuiPagination\n ref={ref}\n count={total}\n // Out-of-range defaults make MUI drop the selection entirely.\n defaultPage={Math.min(Math.max(toCount(defaultPage, 1), 1), total)}\n siblingCount={toCount(siblingCount, 1)}\n boundaryCount={toCount(boundaryCount, 1)}\n {...rest}\n />\n )\n },\n)\nPaginationElement.displayName = 'AglynPagination'\n\nexport const schema: Aglyn.ComponentSchema<PaginationElementProps> = {\n $id: ID,\n pluginId: BUNDLE_ID,\n displayName: 'Pagination',\n description:\n 'Page picker. It highlights the chosen page; wire an interaction to ' +\n 'make it change what the page shows.',\n category: Aglyn.ComponentCategory.NAVIGATION,\n icon: { path: mdiFormatListNumbered.path, sx: { color: '#2196f3' } },\n flags: { selfClosing: Aglyn.FEATURE_FLAG.ENABLED },\n attributes: [\n {\n name: 'count',\n label: 'Pages',\n description: 'Total number of pages. Default 10.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n type: 'number',\n },\n {\n name: 'defaultPage',\n label: 'Starting page',\n description: 'The page selected when a visitor arrives. Default 1.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n type: 'number',\n },\n {\n name: 'variant',\n label: 'Variant',\n description: 'Outlined draws a border around each page item.',\n component: Aglyn.FieldComponentType.SELECT,\n // REAL SENTINELS here, not deletions (AGL-1453) — the opposite call\n // from Button's and Typography's \"Default\" options, for a reason that\n // is visible in the lists themselves: those name MUI's default among\n // their choices, so `''` was a duplicate. These four offered ONLY the\n // non-default alternative, so `''` was the sole route back — and it\n // could not persist (AGL-1191). Picking Outlined, Rounded, Primary or\n // Small was a one-way door: the \"(default)\" option reverted on save and\n // the field snapped back to what it was.\n //\n // Each sentinel is MUI Pagination's own literal default for that prop\n // (`Pagination.js`: `variant = 'text'`, `shape = 'circular'`,\n // `color = 'standard'`, `size = 'medium'`), so the labels stop lying\n // and a stored value renders exactly what an unset one did.\n options: [\n { value: 'text', label: 'Text (default)' },\n { value: 'outlined', label: 'Outlined' },\n ],\n },\n {\n name: 'shape',\n label: 'Shape',\n description: 'Rounded squares instead of circles.',\n component: Aglyn.FieldComponentType.SELECT,\n options: [\n { value: 'circular', label: 'Circular (default)' },\n { value: 'rounded', label: 'Rounded' },\n ],\n },\n {\n name: 'color',\n label: 'Theme color',\n description: 'Color of the selected page item.',\n component: Aglyn.FieldComponentType.SELECT,\n options: [\n { value: 'standard', label: 'Standard (default)' },\n { value: 'primary', label: 'Primary' },\n { value: 'secondary', label: 'Secondary' },\n ],\n },\n {\n // Narrowed from the shared preset: Pagination has no `inherit`\n // size, and offering it would render nothing different.\n ...FIELD_SIZE,\n options: [\n { value: 'medium', label: 'Medium (default)' },\n { value: 'small', label: 'Small' },\n { value: 'large', label: 'Large' },\n ],\n },\n {\n name: 'siblingCount',\n label: 'Sibling pages',\n description:\n 'How many page numbers to show either side of the current one.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n type: 'number',\n },\n {\n name: 'boundaryCount',\n label: 'Boundary pages',\n description:\n 'How many page numbers to always show at the start and end.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n type: 'number',\n },\n {\n name: 'showFirstButton',\n label: 'Show first-page button?',\n description: 'Adds a jump-to-first control.',\n component: Aglyn.FieldComponentType.SWITCH,\n },\n {\n name: 'showLastButton',\n label: 'Show last-page button?',\n description: 'Adds a jump-to-last control.',\n component: Aglyn.FieldComponentType.SWITCH,\n },\n {\n name: 'hidePrevButton',\n label: 'Hide previous button?',\n description: 'Removes the previous-page arrow.',\n component: Aglyn.FieldComponentType.SWITCH,\n },\n {\n name: 'hideNextButton',\n label: 'Hide next button?',\n description: 'Removes the next-page arrow.',\n component: Aglyn.FieldComponentType.SWITCH,\n },\n FIELD_DISABLED,\n ],\n}\n\nexport const presets: Aglyn.PresetSchema[] = [\n {\n $id: generatePresetId(ID),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Pagination',\n pluginId: BUNDLE_ID,\n description: 'Page picker with previous/next arrows',\n category: Aglyn.ComponentCategory.NAVIGATION,\n icon: schema.icon,\n data: {\n $id: null,\n componentId: ID,\n pluginId: BUNDLE_ID,\n props: { count: 10, color: 'primary' },\n },\n },\n]\n\nexport default PaginationElement\n"],"names":["Aglyn","mdiFormatListNumbered","MuiPagination","forwardRef","BUNDLE_ID","FIELD_DISABLED","FIELD_SIZE","dropClearedProps","generatePresetId","ID","toCount","value","fallback","parsed","Number","isFinite","Math","round","PaginationElement","props","ref","count","defaultPage","siblingCount","boundaryCount","children","_children","spread","rest","total","min","max","displayName","schema","$id","pluginId","description","category","ComponentCategory","NAVIGATION","icon","path","sx","color","flags","selfClosing","FEATURE_FLAG","ENABLED","attributes","name","label","component","FieldComponentType","TEXT_FIELD","type","SELECT","options","SWITCH","presets","NodeType","PRESET","data","componentId"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/components/pagination.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 { mdiFormatListNumbered } from '@aglyn/shared-data-mdi'\nimport MuiPagination from '@mui/material/Pagination'\nimport { forwardRef, type ReactNode } from 'react'\nimport { BUNDLE_ID } from '../constants/bundle-common'\nimport { FIELD_DISABLED, FIELD_SIZE } 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; never rename.\nexport const ID: Aglyn.ComponentId = 'muiPagination'\n\nexport interface PaginationElementProps {\n count?: number | string\n defaultPage?: number | string\n color?: 'primary' | 'secondary' | 'tertiary' | 'standard'\n shape?: 'circular' | 'rounded'\n size?: 'small' | 'medium' | 'large'\n variant?: 'text' | 'outlined'\n siblingCount?: number | string\n boundaryCount?: number | string\n showFirstButton?: boolean\n showLastButton?: boolean\n hidePrevButton?: boolean\n hideNextButton?: boolean\n disabled?: boolean\n /**\n * Accepted and dropped. The element is self-closing (see `flags`), so the\n * editor never authors children — but the renderer builds elements from\n * persisted props, and a stray child from an older document would reach\n * MUI's Pagination and render beside the page list. Declared because the\n * implementation deliberately discards it (AGL-1323).\n */\n children?: ReactNode\n}\n\n/** Number-typed attribute fields round-trip as strings. */\nfunction toCount(value: unknown, fallback: number): number {\n if (value == null || value === '') return fallback\n const parsed = Number(value)\n if (!Number.isFinite(parsed) || parsed < 0) return fallback\n return Math.round(parsed)\n}\n\n/**\n * Pagination control (https://mui.com/material-ui/react-pagination/).\n *\n * Uncontrolled: it tracks and highlights the page a visitor picks, but\n * it does not by itself fetch or filter anything — pair it with an\n * interaction, or with a repeat that reads the page. That is stated in\n * the element's own description too, because a page-picker that looks\n * wired and isn't is worse than one that says what it is.\n *\n * The `size` here is MUI's own three-value scale; the shared FIELD_SIZE\n * preset also offers `inherit`, which Pagination does not accept, so the\n * shared field is narrowed rather than re-declared.\n */\nconst PaginationElement = forwardRef<HTMLElement, PaginationElementProps>(\n (props, ref) => {\n const {\n count,\n defaultPage,\n siblingCount,\n boundaryCount,\n children: _children,\n ...spread\n } = props\n // A cleared `color`/`size` persists as null; MUI capitalizes both and\n // throws during SSR, 500ing the page (AGL-1226).\n const rest = dropClearedProps(spread)\n const total = toCount(count, 10)\n return (\n <MuiPagination\n ref={ref}\n count={total}\n // Out-of-range defaults make MUI drop the selection entirely.\n defaultPage={Math.min(Math.max(toCount(defaultPage, 1), 1), total)}\n siblingCount={toCount(siblingCount, 1)}\n boundaryCount={toCount(boundaryCount, 1)}\n {...rest}\n />\n )\n },\n)\nPaginationElement.displayName = 'AglynPagination'\n\nexport const schema: Aglyn.ComponentSchema<PaginationElementProps> = {\n $id: ID,\n pluginId: BUNDLE_ID,\n displayName: 'Pagination',\n description:\n 'Page picker. It highlights the chosen page; wire an interaction to ' +\n 'make it change what the page shows.',\n category: Aglyn.ComponentCategory.NAVIGATION,\n icon: { path: mdiFormatListNumbered.path, sx: { color: '#2196f3' } },\n flags: { selfClosing: Aglyn.FEATURE_FLAG.ENABLED },\n attributes: [\n {\n name: 'count',\n label: 'Pages',\n description: 'Total number of pages. Default 10.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n type: 'number',\n },\n {\n name: 'defaultPage',\n label: 'Starting page',\n description: 'The page selected when a visitor arrives. Default 1.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n type: 'number',\n },\n {\n name: 'variant',\n label: 'Variant',\n description: 'Outlined draws a border around each page item.',\n component: Aglyn.FieldComponentType.SELECT,\n // REAL SENTINELS here, not deletions (AGL-1453) — the opposite call\n // from Button's and Typography's \"Default\" options, for a reason that\n // is visible in the lists themselves: those name MUI's default among\n // their choices, so `''` was a duplicate. These four offered ONLY the\n // non-default alternative, so `''` was the sole route back — and it\n // could not persist (AGL-1191). Picking Outlined, Rounded, Primary or\n // Small was a one-way door: the \"(default)\" option reverted on save and\n // the field snapped back to what it was.\n //\n // Each sentinel is MUI Pagination's own literal default for that prop\n // (`Pagination.js`: `variant = 'text'`, `shape = 'circular'`,\n // `color = 'standard'`, `size = 'medium'`), so the labels stop lying\n // and a stored value renders exactly what an unset one did.\n options: [\n { value: 'text', label: 'Text (default)' },\n { value: 'outlined', label: 'Outlined' },\n ],\n },\n {\n name: 'shape',\n label: 'Shape',\n description: 'Rounded squares instead of circles.',\n component: Aglyn.FieldComponentType.SELECT,\n options: [\n { value: 'circular', label: 'Circular (default)' },\n { value: 'rounded', label: 'Rounded' },\n ],\n },\n {\n name: 'color',\n label: 'Theme color',\n description: 'Color of the selected page item.',\n component: Aglyn.FieldComponentType.SELECT,\n options: [\n { value: 'standard', label: 'Standard (default)' },\n { value: 'primary', label: 'Primary' },\n { value: 'secondary', label: 'Secondary' },\n { value: 'tertiary', label: 'Tertiary' },\n ],\n },\n {\n // Narrowed from the shared preset: Pagination has no `inherit`\n // size, and offering it would render nothing different.\n ...FIELD_SIZE,\n options: [\n { value: 'medium', label: 'Medium (default)' },\n { value: 'small', label: 'Small' },\n { value: 'large', label: 'Large' },\n ],\n },\n {\n name: 'siblingCount',\n label: 'Sibling pages',\n description:\n 'How many page numbers to show either side of the current one.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n type: 'number',\n },\n {\n name: 'boundaryCount',\n label: 'Boundary pages',\n description:\n 'How many page numbers to always show at the start and end.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n type: 'number',\n },\n {\n name: 'showFirstButton',\n label: 'Show first-page button?',\n description: 'Adds a jump-to-first control.',\n component: Aglyn.FieldComponentType.SWITCH,\n },\n {\n name: 'showLastButton',\n label: 'Show last-page button?',\n description: 'Adds a jump-to-last control.',\n component: Aglyn.FieldComponentType.SWITCH,\n },\n {\n name: 'hidePrevButton',\n label: 'Hide previous button?',\n description: 'Removes the previous-page arrow.',\n component: Aglyn.FieldComponentType.SWITCH,\n },\n {\n name: 'hideNextButton',\n label: 'Hide next button?',\n description: 'Removes the next-page arrow.',\n component: Aglyn.FieldComponentType.SWITCH,\n },\n FIELD_DISABLED,\n ],\n}\n\nexport const presets: Aglyn.PresetSchema[] = [\n {\n $id: generatePresetId(ID),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Pagination',\n pluginId: BUNDLE_ID,\n description: 'Page picker with previous/next arrows',\n category: Aglyn.ComponentCategory.NAVIGATION,\n icon: schema.icon,\n data: {\n $id: null,\n componentId: ID,\n pluginId: BUNDLE_ID,\n props: { count: 10, color: 'primary' },\n },\n },\n]\n\nexport default PaginationElement\n"],"names":["Aglyn","mdiFormatListNumbered","MuiPagination","forwardRef","BUNDLE_ID","FIELD_DISABLED","FIELD_SIZE","dropClearedProps","generatePresetId","ID","toCount","value","fallback","parsed","Number","isFinite","Math","round","PaginationElement","props","ref","count","defaultPage","siblingCount","boundaryCount","children","_children","spread","rest","total","min","max","displayName","schema","$id","pluginId","description","category","ComponentCategory","NAVIGATION","icon","path","sx","color","flags","selfClosing","FEATURE_FLAG","ENABLED","attributes","name","label","component","FieldComponentType","TEXT_FIELD","type","SELECT","options","SWITCH","presets","NodeType","PRESET","data","componentId"],"mappings":";;;AAAA;;;;;;;;;;;;;;;CAeC,GAED,YAAYA,WAAW,eAAc;AACrC,SAASC,qBAAqB,QAAQ,yBAAwB;AAC9D,OAAOC,mBAAmB,2BAA0B;AACpD,SAASC,UAAU,QAAwB,QAAO;AAClD,SAASC,SAAS,QAAQ,gCAA4B;AACtD,SAASC,cAAc,EAAEC,UAAU,QAAQ,gCAA4B;AACvE,SAASC,gBAAgB,QAAQ,iCAA6B;AAC9D,SAASC,gBAAgB,QAAQ,iCAA6B;AAE9D,iEAAiE;AACjE,OAAO,MAAMC,KAAwB,gBAAe;AA0BpD,yDAAyD,GACzD,SAASC,QAAQC,KAAc,EAAEC,QAAgB;IAC/C,IAAID,SAAS,QAAQA,UAAU,IAAI,OAAOC;IAC1C,MAAMC,SAASC,OAAOH;IACtB,IAAI,CAACG,OAAOC,QAAQ,CAACF,WAAWA,SAAS,GAAG,OAAOD;IACnD,OAAOI,KAAKC,KAAK,CAACJ;AACpB;AAEA;;;;;;;;;;;;CAYC,GACD,MAAMK,kCAAoBf,WACxB,CAACgB,OAAOC;IACN,MAAM,EACJC,KAAK,EACLC,WAAW,EACXC,YAAY,EACZC,aAAa,EACbC,UAAUC,SAAS,EAEpB,GAAGP,OADCQ,0CACDR;;;;;;;IACJ,sEAAsE;IACtE,iDAAiD;IACjD,MAAMS,OAAOrB,iBAAiBoB;IAC9B,MAAME,QAAQnB,QAAQW,OAAO;IAC7B,qBACE,KAACnB;QACCkB,KAAKA;QACLC,OAAOQ;QACP,8DAA8D;QAC9DP,aAAaN,KAAKc,GAAG,CAACd,KAAKe,GAAG,CAACrB,QAAQY,aAAa,IAAI,IAAIO;QAC5DN,cAAcb,QAAQa,cAAc;QACpCC,eAAed,QAAQc,eAAe;OAClCI;AAGV;AAEFV,kBAAkBc,WAAW,GAAG;AAEhC,OAAO,MAAMC,SAAwD;IACnEC,KAAKzB;IACL0B,UAAU/B;IACV4B,aAAa;IACbI,aACE,wEACA;IACFC,UAAUrC,MAAMsC,iBAAiB,CAACC,UAAU;IAC5CC,MAAM;QAAEC,MAAMxC,sBAAsBwC,IAAI;QAAEC,IAAI;YAAEC,OAAO;QAAU;IAAE;IACnEC,OAAO;QAAEC,aAAa7C,MAAM8C,YAAY,CAACC,OAAO;IAAC;IACjDC,YAAY;QACV;YACEC,MAAM;YACNC,OAAO;YACPd,aAAa;YACbe,WAAWnD,MAAMoD,kBAAkB,CAACC,UAAU;YAC9CC,MAAM;QACR;QACA;YACEL,MAAM;YACNC,OAAO;YACPd,aAAa;YACbe,WAAWnD,MAAMoD,kBAAkB,CAACC,UAAU;YAC9CC,MAAM;QACR;QACA;YACEL,MAAM;YACNC,OAAO;YACPd,aAAa;YACbe,WAAWnD,MAAMoD,kBAAkB,CAACG,MAAM;YAC1C,oEAAoE;YACpE,sEAAsE;YACtE,qEAAqE;YACrE,sEAAsE;YACtE,oEAAoE;YACpE,sEAAsE;YACtE,wEAAwE;YACxE,yCAAyC;YACzC,EAAE;YACF,sEAAsE;YACtE,8DAA8D;YAC9D,qEAAqE;YACrE,4DAA4D;YAC5DC,SAAS;gBACP;oBAAE7C,OAAO;oBAAQuC,OAAO;gBAAiB;gBACzC;oBAAEvC,OAAO;oBAAYuC,OAAO;gBAAW;aACxC;QACH;QACA;YACED,MAAM;YACNC,OAAO;YACPd,aAAa;YACbe,WAAWnD,MAAMoD,kBAAkB,CAACG,MAAM;YAC1CC,SAAS;gBACP;oBAAE7C,OAAO;oBAAYuC,OAAO;gBAAqB;gBACjD;oBAAEvC,OAAO;oBAAWuC,OAAO;gBAAU;aACtC;QACH;QACA;YACED,MAAM;YACNC,OAAO;YACPd,aAAa;YACbe,WAAWnD,MAAMoD,kBAAkB,CAACG,MAAM;YAC1CC,SAAS;gBACP;oBAAE7C,OAAO;oBAAYuC,OAAO;gBAAqB;gBACjD;oBAAEvC,OAAO;oBAAWuC,OAAO;gBAAU;gBACrC;oBAAEvC,OAAO;oBAAauC,OAAO;gBAAY;gBACzC;oBAAEvC,OAAO;oBAAYuC,OAAO;gBAAW;aACxC;QACH;QACA,aAGK5C;YACHkD,SAAS;gBACP;oBAAE7C,OAAO;oBAAUuC,OAAO;gBAAmB;gBAC7C;oBAAEvC,OAAO;oBAASuC,OAAO;gBAAQ;gBACjC;oBAAEvC,OAAO;oBAASuC,OAAO;gBAAQ;aAClC;;QAEH;YACED,MAAM;YACNC,OAAO;YACPd,aACE;YACFe,WAAWnD,MAAMoD,kBAAkB,CAACC,UAAU;YAC9CC,MAAM;QACR;QACA;YACEL,MAAM;YACNC,OAAO;YACPd,aACE;YACFe,WAAWnD,MAAMoD,kBAAkB,CAACC,UAAU;YAC9CC,MAAM;QACR;QACA;YACEL,MAAM;YACNC,OAAO;YACPd,aAAa;YACbe,WAAWnD,MAAMoD,kBAAkB,CAACK,MAAM;QAC5C;QACA;YACER,MAAM;YACNC,OAAO;YACPd,aAAa;YACbe,WAAWnD,MAAMoD,kBAAkB,CAACK,MAAM;QAC5C;QACA;YACER,MAAM;YACNC,OAAO;YACPd,aAAa;YACbe,WAAWnD,MAAMoD,kBAAkB,CAACK,MAAM;QAC5C;QACA;YACER,MAAM;YACNC,OAAO;YACPd,aAAa;YACbe,WAAWnD,MAAMoD,kBAAkB,CAACK,MAAM;QAC5C;QACApD;KACD;AACH,EAAC;AAED,OAAO,MAAMqD,UAAgC;IAC3C;QACExB,KAAK1B,iBAAiBC;QACtB6C,MAAMtD,MAAM2D,QAAQ,CAACC,MAAM;QAC3B5B,aAAa;QACbG,UAAU/B;QACVgC,aAAa;QACbC,UAAUrC,MAAMsC,iBAAiB,CAACC,UAAU;QAC5CC,MAAMP,OAAOO,IAAI;QACjBqB,MAAM;YACJ3B,KAAK;YACL4B,aAAarD;YACb0B,UAAU/B;YACVe,OAAO;gBAAEE,OAAO;gBAAIsB,OAAO;YAAU;QACvC;IACF;CACD,CAAA;AAED,eAAezB,kBAAiB"}
|
|
@@ -62,7 +62,7 @@ export interface TabsElementProps extends TabLinkProps {
|
|
|
62
62
|
/** Centres a standard strip; MUI ignores it when scrollable. */
|
|
63
63
|
centered?: boolean;
|
|
64
64
|
textColor?: 'primary' | 'secondary' | 'inherit';
|
|
65
|
-
indicatorColor?: 'primary' | 'secondary';
|
|
65
|
+
indicatorColor?: 'primary' | 'secondary' | 'tertiary';
|
|
66
66
|
/**
|
|
67
67
|
* Render every panel into the SSR output up front instead of building each
|
|
68
68
|
* panel the first time its tab is opened (AGL-1283 option 3).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/components/tabs.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 { mdiTab, mdiViewCarousel } from '@aglyn/shared-data-mdi'\nimport { AppLink } from '@aglyn/shared-ui-jsx'\nimport Box from '@mui/material/Box'\nimport MuiTab from '@mui/material/Tab'\nimport MuiTabs from '@mui/material/Tabs'\nimport Typography from '@mui/material/Typography'\nimport type { SxProps } from '@mui/material/styles'\nimport {\n createContext,\n forwardRef,\n type ReactNode,\n useContext,\n useState,\n} from 'react'\nimport { BUNDLE_ID } from '../constants/bundle-common'\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 TABS_ID: Aglyn.ComponentId = 'muiTabs'\nexport const TAB_PANEL_ID: Aglyn.ComponentId = 'muiTabPanel'\n\n/**\n * How many tabs in a strip can carry a screen link (AGL-1312). The strip is\n * authored as a free-form label list, so the links have to be flat props —\n * one per position — and a flat prop needs a name that exists up front.\n *\n * Eight is well past any usable navigation row (the marketing content-tabs\n * row is three) and costs nothing at render: the attributes panel only shows\n * a link picker for a tab that actually exists, so a two-tab strip shows two.\n */\nexport const TAB_LINK_SLOTS = 8\n\n/** Prop name carrying the link of the 1-based `position`-th tab. */\nexport function tabLinkProp(position: number): string {\n return `tabLink${position}`\n}\n\n/**\n * The per-tab screen links, `tabLink1`…`tabLink8`. Declared as a mapped type\n * rather than an index signature: an index signature on the props interface\n * would force `sx`, `children` and the rest to conform to it.\n */\nexport type TabLinkProps = Partial<\n Record<\n | 'tabLink1'\n | 'tabLink2'\n | 'tabLink3'\n | 'tabLink4'\n | 'tabLink5'\n | 'tabLink6'\n | 'tabLink7'\n | 'tabLink8',\n string\n >\n>\n\nexport interface TabsElementProps extends TabLinkProps {\n /** Tab labels, one per line (commas also accepted). */\n labels?: string\n /**\n * The LABEL of the tab the strip opens on (AGL-3164). Unset opens the\n * first tab, which is what every Tabs already in the wild does.\n *\n * A label rather than a position, because a position is a silent lie the\n * moment the list is edited: it keeps pointing at \"the second tab\" after\n * the author reorders or renames, and nothing on screen says the wrong\n * panel is now the one that opens. A label that no longer exists simply\n * does not match, and the strip falls back to the first tab.\n *\n * See {@link openingTabIndex} for the whole rule, and `deferLazyPanelNodes`\n * in tenant-runtime for the server side of it — the two must agree or the\n * page ships the wrong panel's markup.\n */\n opensOn?: string\n /** Accessible name of the strip; also names the nav landmark in link mode. */\n ariaLabel?: string\n orientation?: 'horizontal' | 'vertical'\n variant?: 'standard' | 'scrollable' | 'fullWidth'\n /** Centres a standard strip; MUI ignores it when scrollable. */\n centered?: boolean\n textColor?: 'primary' | 'secondary' | 'inherit'\n indicatorColor?: 'primary' | 'secondary'\n /**\n * Render every panel into the SSR output up front instead of building each\n * panel the first time its tab is opened (AGL-1283 option 3).\n *\n * Mount-on-first-selection is the DEFAULT: `/pricing` shipped eight copies\n * of a 50-row table so desktop visitors could see none of them, and any\n * large tab set pays the same tax silently. The trade is that an unopened\n * panel's content is then not in the page source — not indexable, not\n * findable — so this switch exists for the panels where that matters:\n * content that appears nowhere else on the page and must reach crawlers.\n */\n ssrPanels?: boolean\n /**\n * Legacy opt-in from when eager panels were the default (AGL-1283).\n * Lazy mounting is now the default, so this is accepted from existing\n * documents but no longer consulted — `ssrPanels` is the one switch.\n * Still destructured so an authored value never leaks onto the DOM.\n */\n lazyPanels?: boolean\n /**\n * Authored node styles, handed over by the renderer rather than typed into\n * an attribute — the merge below reads it, so it belongs on the public\n * interface. Leaving it undeclared (AGL-1284 added the reads, not the\n * declaration) meant no typed caller could pass one, including the specs\n * that exist to prove an authored `sx` survives (AGL-1323).\n */\n sx?: SxProps\n children?: ReactNode\n}\n\nexport interface TabPanelElementProps {\n /** Which tab reveals this panel; must match one of the Tabs labels. */\n label?: string\n /**\n * Set by the server when this panel's children were withheld from the page\n * payload (AGL-1285, `deferLazyPanelNodes`) — never authored, and there is\n * deliberately no attribute for it.\n *\n * It must be destructured off the prop bag either way: everything else on\n * this element is spread straight onto a `Box`, so leaving it in produced a\n * React \"does not recognize the prop\" warning for every deferred panel.\n *\n * It also drives the loading state. A withheld panel that the reader has\n * just opened has no children yet and is indistinguishable from a panel that\n * is genuinely empty, and the fetch behind it is a full server compose —\n * 3.8s cold when measured. This flag is what lets the panel say so.\n *\n * It clears itself: the patch from `/api/screen/nodes` carries the ORIGINAL\n * panel nodes, which never had the marker, so the moment the real children\n * arrive this is gone and the placeholder with it (AGL-1287).\n */\n aglynDeferred?: boolean\n /** Authored node styles, merged over the panel's own — see Tabs' `sx`. */\n sx?: SxProps\n children?: ReactNode\n}\n\n/**\n * Splits the authored label list. Newline-separated is the documented\n * form; commas are accepted because a one-line \"A, B, C\" is what people\n * type first.\n */\nexport function parseLabels(value: unknown): string[] {\n if (value == null) return []\n return String(value)\n .split(/[\\n,]/)\n .map((label) => label.trim())\n .filter(Boolean)\n}\n\n/** Stable DOM id fragment for the tab ⇄ panel aria wiring. */\nexport function labelSlug(label: string): string {\n return (\n label\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-|-$/g, '') || 'tab'\n )\n}\n\n/** Case/whitespace-insensitive: authors don't retype labels exactly. */\nexport function labelsMatch(a: unknown, b: unknown): boolean {\n return (\n String(a ?? '').trim().toLowerCase() ===\n String(b ?? '').trim().toLowerCase()\n )\n}\n\n/**\n * Which tab the strip opens on, by index into the parsed label list.\n *\n * Two rules, in order:\n *\n * 1. the tab the author NAMED in `opensOn` (AGL-3164), matched by label with\n * the same case/whitespace tolerance panels are matched with;\n * 2. otherwise the landing tab — the first one WITHOUT a screen link, which\n * is how a navigation row says \"this is the page you are on\" (AGL-1312),\n * and which is tab 0 on a strip with no links at all, i.e. exactly what\n * this element did before the attribute existed.\n *\n * The named tab is refused when it carries a screen link: a linked tab\n * navigates instead of revealing a panel (AGL-1312), so it is not a tab the\n * strip can rest on, and opening on it would show the indicator over a panel\n * nobody can see. It falls back rather than rendering nothing.\n *\n * Never returns -1. `landing` is -1 when EVERY tab navigates — the strip\n * shows no indicator there, but callers still read a label with this index.\n */\nexport function openingTabIndex(\n labels: readonly string[],\n opensOn?: unknown,\n linkIds: readonly (string | undefined)[] = [],\n): number {\n const named = labels.findIndex(\n (label, index) => !linkIds[index] && labelsMatch(label, opensOn),\n )\n if (named >= 0) return named\n const landing = labels.findIndex((_label, index) => !linkIds[index])\n return landing < 0 ? 0 : landing\n}\n\ninterface TabsContextValue {\n activeLabel: string\n /** True on the besigner canvas, where every panel is shown at once. */\n showAll: boolean\n /** Panels render nothing until first selected (AGL-1283). */\n lazyPanels: boolean\n /** Labels opened at least once — a lazily mounted panel stays mounted. */\n opened: ReadonlySet<string>\n /**\n * True when at least one tab carries a screen link (AGL-1312), which makes\n * the whole row navigation rather than a tab list — see the a11y note on\n * `TabsElement`. Panels drop `role=\"tabpanel\"` in that mode: a tabpanel\n * with no tablist to belong to is orphaned ARIA.\n */\n navMode: boolean\n}\n\nexport const TabsContext = createContext<TabsContextValue | undefined>(\n undefined,\n)\n\n/**\n * Tabs (https://mui.com/material-ui/react-tabs/).\n *\n * The strip is authored on the container as a label list, and each Tab\n * Panel child names the label it belongs to. It does **not** slice its\n * React children by index: the node renderer hands every component a\n * single `Branch` fragment rather than one element per child node\n * (`libs/aglyn-node-renderer`), so an index-based split would silently\n * put all the content behind the first tab. Matching by label also\n * survives reordering panels in the hierarchy.\n *\n * The strip renders from the author's own list, so it is complete in the\n * SSR output — no registration pass, no empty-then-filled flash, and it\n * still reads as a tab list with JavaScript disabled.\n *\n * ## Link mode (AGL-1312)\n *\n * Any tab may carry a screen link (`tabLink1`…`tabLink8`, by position). A\n * tab that has one renders as a real anchor — navigable, crawlable,\n * middle-clickable — because the row it exists for (Blog | Changelog |\n * Newsroom) is navigation ACROSS screens, which a panel switcher can only\n * fake with empty panels or a hand-styled row of buttons. The anchor is an\n * `AppLink`, never a bare `href`: a raw href full-reloads the SPA.\n *\n * A tab WITHOUT a link keeps today's behavior exactly, and mixed rows work\n * — the marketing pattern IS a mixed row, since the tab for the page you\n * are already on must not link to itself. That unlinked tab is also how the\n * author says which page this copy of the row is on: the strip lands on it,\n * so the same three-tab row placed on three screens shows the indicator in\n * the right place on each, with no \"selected tab\" attribute to keep in sync\n * — `opensOn` below is for panel rows and gives way to this one.\n *\n * ## Which tab opens (AGL-3164)\n *\n * `opensOn` names it, by LABEL. Unset opens the first tab, which is what\n * every Tabs authored before the attribute existed does; a label that no\n * longer matches opens the first tab too, rather than nothing. The rule\n * lives in {@link openingTabIndex} and is mirrored server-side by\n * `deferLazyPanelNodes` (tenant-runtime), which decides which panel's nodes\n * reach the page at all — so the tab that opens is the one that was\n * rendered, and the page does not paint one panel and swap to another.\n *\n * **Accessibility.** The row is a `tablist` only while NOTHING in it\n * navigates. As soon as one tab carries a link the whole strip is marked up\n * as navigation: a `nav` landmark, no `role=\"tab\"`, no `aria-selected`, and\n * no roving tab stop (every link is its own tab stop, as in any nav). The\n * alternative — an `<a href>` wearing `role=\"tab\"` — tells assistive tech\n * the activation will reveal a panel when it actually loads a page, and a\n * tablist whose children are not tabs is invalid either way. The tab for\n * the current screen is marked `aria-current=\"page\"`; tabs that still\n * switch panels stay buttons and keep their `aria-controls`, which is an\n * accurate disclosure relationship on its own. The half-applied version of\n * this — links inside a tablist, or panels still claiming `role=\"tabpanel\"`\n * with no tablist above them — is what this deliberately avoids.\n */\nconst TabsElement = forwardRef<HTMLDivElement, TabsElementProps>(\n (rawProps, ref) => {\n // Cleared props dropped up front (AGL-1451). The four selects below\n // already coalesce their own value, but `rest` is spread onto the root\n // and the per-tab link props are read out of it, so a `null` from the\n // field's ✕ (AGL-1226) must not survive this far.\n const props = dropClearedProps(rawProps)\n const {\n labels,\n ariaLabel,\n orientation,\n variant,\n centered,\n textColor,\n indicatorColor,\n ssrPanels,\n lazyPanels,\n opensOn,\n children,\n ...rest\n } = props\n const { editorInert, suppressNavigation } = Aglyn.useScreenLink(undefined)\n // Read the routing map directly rather than calling `useScreenLink` per\n // tab: the number of tabs changes with the label list, and a hook per\n // list item is a rules-of-hooks violation waiting for the author to add\n // a fourth tab.\n const { screens } = useContext(Aglyn.ScreenLinkContext)\n // Screen ids by tab position, lifted out of `rest` so they can never\n // reach the DOM as unknown attributes (the nav-menu does the same with\n // its legacy trigger prop).\n const linkIds: (string | undefined)[] = []\n for (let slot = 1; slot <= TAB_LINK_SLOTS; slot += 1) {\n const key = tabLinkProp(slot)\n const value = (rest as Record<string, unknown>)[key]\n linkIds.push(typeof value === 'string' && value ? value : undefined)\n delete (rest as Record<string, unknown>)[key]\n }\n const parsed = parseLabels(labels)\n // Authored links decide the mode, NOT resolved hrefs: the canvas and\n // preview suppress navigation, and they must still show the element the\n // page will actually ship (the same rule Screen Link follows).\n const navMode = parsed.some((_label, index) => !!linkIds[index])\n /**\n * The tab a navigation row LANDS on is the one with no link: the row is\n * placed on every screen it names, and on each of those the tab for that\n * screen is left unlinked, because a page that links to itself helps\n * nobody. So \"first tab with no link\" is how the author says \"this is\n * the page you are on\" — without a second attribute, and without this\n * element having to know the current route.\n *\n * `-1` means every tab navigates: nothing is current, and the strip\n * shows no indicator rather than inventing one under the first tab.\n * With no links at all this is 0, i.e. exactly today's behavior.\n */\n const landing = parsed.findIndex((_label, index) => !linkIds[index])\n // Which tab this strip opens on (AGL-3164): the one the author named,\n // and otherwise `landing` — so an unset attribute, or one naming a label\n // that has since been renamed away, behaves exactly as it always did.\n const opening = openingTabIndex(parsed, opensOn, linkIds)\n const [active, setActive] = useState(opening)\n // Once a lazy panel has been opened it stays mounted: re-tabbing between\n // two plans should not re-render 50 rows each time, and anything the\n // reader typed or scrolled inside a panel survives a round trip.\n //\n // Seeded with the OPENING label, because that panel is open from the\n // start without anyone clicking it. Leaving it out unmounted the opening\n // panel the moment the reader moved away — visibly inconsistent with\n // every other panel they had visited, and caught by the round-trip test.\n const [opened, setOpened] = useState<ReadonlySet<string>>(() => {\n const first = parsed[opening]\n return new Set<string>(first === undefined ? [] : [first])\n })\n // A label removed from the list must not leave the strip pointing at\n // a tab that no longer exists — MUI warns and drops the indicator.\n //\n // On the besigner canvas the authored attribute is read every render\n // instead of the state seeded at mount: `onChange` is inert there, so\n // nothing else can have moved the selection, and a canvas that kept\n // showing the tab that was open when the element mounted would make\n // \"Opens on\" look like it had done nothing.\n const chosen = editorInert ? opening : active < parsed.length ? active : 0\n // A tab that navigates is never the selected one; if the author has just\n // given the open tab a link, fall back to one that still has a panel.\n const activeIndex = linkIds[chosen] && landing >= 0 ? landing : chosen\n const resolvedVariant = variant || 'standard'\n const vertical = orientation === 'vertical'\n const stripLabel = ariaLabel || 'Tabs'\n\n const strip = (\n <MuiTabs\n // No indicator when every tab navigates: there is no selection to\n // show, and marking one anyway would point at the wrong page.\n value={parsed.length && landing >= 0 ? activeIndex : false}\n onChange={\n editorInert\n ? undefined\n : (_event, next: number) => {\n // A navigating tab must not move the selection on its way\n // out: the indicator would jump to a tab whose panel is\n // empty while the next page is still loading.\n if (linkIds[next]) return\n setActive(next)\n const label = parsed[next]\n if (label !== undefined) {\n setOpened((prev) =>\n prev.has(label) ? prev : new Set(prev).add(label),\n )\n }\n }\n }\n orientation={vertical ? 'vertical' : 'horizontal'}\n variant={resolvedVariant}\n // MUI ignores `centered` on a scrollable strip and warns in dev.\n centered={resolvedVariant === 'standard' ? !!centered : undefined}\n textColor={textColor || 'primary'}\n indicatorColor={indicatorColor || 'primary'}\n // Link mode is navigation, so the root becomes the `nav` landmark\n // and the inner flex row gives up `role=\"tablist\"`. The accessible\n // name moves with it: MUI puts `aria-label` on the list, which in\n // this mode is a plain div and cannot carry the landmark's name.\n {...(navMode\n ? {\n component: 'nav',\n slotProps: {\n root: { 'aria-label': stripLabel },\n list: { role: undefined },\n },\n }\n : { 'aria-label': stripLabel })}\n >\n {parsed.map((label, index) => {\n const slug = labelSlug(label)\n const key = `${slug}-${index}`\n if (!navMode) {\n return (\n <MuiTab\n key={key}\n label={label}\n id={`tab-${slug}`}\n aria-controls={`tabpanel-${slug}`}\n />\n )\n }\n // Suppressed navigation (canvas, preview) keeps the item in the\n // row but without an href, so a click cannot leave the editor.\n const href = suppressNavigation\n ? undefined\n : Aglyn.resolveScreenHref(screens, linkIds[index])\n // An authored target that the routing map does not have: the\n // screen was unpublished or deleted out from under this row\n // (AGL-1893). Computed from the MAP, never from `href`, so a\n // canvas or preview render — where nothing has an href on purpose\n // — does not paint every working link as dead.\n const broken = Aglyn.isScreenLinkBroken(screens, linkIds[index])\n return (\n <MuiTab\n key={key}\n label={label}\n id={`tab-${slug}`}\n // Only a tab that still reveals a panel controls anything.\n aria-controls={linkIds[index] ? undefined : `tabpanel-${slug}`}\n {...(href\n ? { component: AppLink, componentVariant: 'naked', href }\n : null)}\n /**\n * A tab whose screen is gone stops being a control (AGL-1893).\n *\n * It used to render as a bare `<button>` indistinguishable\n * from its working neighbours: no href, no `aria-controls`,\n * and `onChange` returns early on it because the AUTHORED id\n * is still there — so it looked live, announced live, and did\n * nothing at all. Live on `/changelog` and `/newsroom` for two\n * days without anything anywhere saying so.\n *\n * Disabled rather than hidden, on purpose:\n *\n * - the routing map differs between the render that produced\n * an ISR page and the render that hydrates it, and AGL-1268\n * settled that a node's ELEMENT must not depend on it —\n * removing the tab would make the strip's DOM shape depend\n * on it, which is strictly worse than an attribute;\n * - `MuiTabs` addresses its children by index, so dropping one\n * silently repoints `value` at the wrong tab;\n * - the failure directions are not symmetric. A wrongly\n * disabled tab is a dimmed label; a wrongly hidden one is\n * navigation that vanished from a customer's site with no\n * trace of why.\n *\n * Falling through to panel behaviour instead — the other\n * option AGL-1893 weighed — is not available to this element:\n * the node renderer hands it ONE `Branch` fragment rather than\n * per-panel children, so a Tabs container cannot know whether\n * a panel with this label exists, and on the real `/changelog`\n * shape it does not.\n *\n * `landing`, `opening`, `activeIndex`, `aria-controls` and the\n * `onChange` guard all still read the AUTHORED id, unchanged.\n * They must: `deferLazyPanelNodes` computes the opening label\n * server-side from the raw `tabLink{n}` props and has no\n * routing map to resolve ids with, so a client that resolved\n * differently would keep a panel the server withheld.\n */\n disabled={broken && !editorInert ? true : undefined}\n // On the canvas the tab stays live: the author has to be able\n // to select the node to repair it. It carries the ring and the\n // explanation instead.\n {...Aglyn.brokenScreenLinkProps(broken, !!editorInert)}\n sx={\n broken && editorInert\n ? Aglyn.BROKEN_SCREEN_LINK_SX\n : undefined\n }\n // MUI writes these before spreading the rest, so passing them\n // undefined is what removes them (see the a11y note above).\n role={undefined}\n aria-selected={undefined}\n aria-current={\n landing >= 0 && index === activeIndex ? 'page' : undefined\n }\n // Undo the roving tab stop: in a nav every item is reachable\n // with Tab, and MUI's arrow-key handler already stands down\n // because it only moves between `role=\"tab\"` siblings.\n tabIndex={undefined}\n />\n )\n })}\n </MuiTabs>\n )\n\n return (\n <TabsContext.Provider\n value={{\n activeLabel: parsed[activeIndex] ?? '',\n // Every panel at once on the canvas: a hidden panel cannot be\n // selected or styled, the same reason Accordion force-expands.\n showAll: !!editorInert,\n // Lazy is the default (AGL-1283 option 3); `ssrPanels` is the SEO\n // escape hatch. The legacy `lazyPanels` opt-in is subsumed: `true`\n // now means what the default means, and a stored `false` was only\n // ever the old default, never an author's intent.\n lazyPanels: !ssrPanels,\n opened,\n navMode,\n }}\n >\n <Box\n ref={ref}\n {...rest}\n // MERGE, never replace. `sx` written after `{...rest}` silently\n // discarded whatever the author set on the node — every Tabs on\n // every site rendered with default MUI styling and no way to\n // change it, with nothing in the editor to suggest the value had\n // been dropped (AGL-1284). Vertical orientation still needs the\n // flex row, so it goes first and the author can override it.\n sx={[\n { display: vertical ? 'flex' : undefined },\n ...(Array.isArray(rest.sx) ? rest.sx : [rest.sx]),\n ]}\n >\n {strip}\n {children}\n </Box>\n </TabsContext.Provider>\n )\n },\n)\nTabsElement.displayName = 'AglynTabs'\n\n/**\n * One tab's content. Outside a Tabs container it renders plainly rather\n * than disappearing — a panel dragged out of its tabs would otherwise\n * vanish from the canvas with no explanation.\n */\nexport const TabPanelElement = forwardRef<\n HTMLDivElement,\n TabPanelElementProps\n>((props, ref) => {\n const { label, aglynDeferred, children, ...rest } = props\n const context = useContext(TabsContext)\n const selected = !context || labelsMatch(label, context.activeLabel)\n const visible = selected || !!context?.showAll\n /**\n * With `lazyPanels`, an unopened panel renders its wrapper but not its\n * children — the wrapper stays so the `aria-controls` target and the\n * tab ⇄ panel wiring still resolve, and so nothing about the accessible\n * structure depends on whether the reader has clicked yet.\n *\n * `opened` is checked as well as `selected` because a panel that has been\n * visited stays mounted; only the never-opened ones are skipped.\n */\n const mounted =\n !context ||\n !context.lazyPanels ||\n context.showAll ||\n selected ||\n context.opened.has(String(label ?? ''))\n\n /**\n * In link mode the strip is a nav, not a tablist (AGL-1312), so a panel\n * has no tablist to belong to and drops the tab-pattern ARIA rather than\n * claiming half of it. The id stays — the button that still reveals this\n * panel points `aria-controls` at it, which is a valid relationship on\n * its own — and an orphan panel (dragged out of its Tabs, no context)\n * keeps today's markup untouched.\n */\n const navMode = !!context?.navMode\n\n return (\n <Box\n ref={ref}\n role={navMode ? undefined : 'tabpanel'}\n hidden={!visible}\n id={`tabpanel-${labelSlug(String(label ?? ''))}`}\n aria-labelledby={\n navMode ? undefined : `tab-${labelSlug(String(label ?? ''))}`\n }\n {...rest}\n // Same merge bug as the Tabs container (AGL-1284): the author's `sx`\n // was dropped, so a panel could not even have its padding changed.\n // Order matters — the default padding is first so the author can\n // override it, and the hide rule is LAST so an authored `display`\n // can never force a deselected panel back on screen.\n sx={[\n { p: 2 },\n ...(Array.isArray(rest.sx) ? rest.sx : [rest.sx]),\n ...(visible ? [] : [{ display: 'none' }]),\n ]}\n >\n {context?.showAll && !selected ? (\n // Canvas only: says which tab this content belongs to, so a\n // stack of panels is readable and a label typo is obvious.\n <Typography\n variant=\"caption\"\n color=\"text.secondary\"\n sx={{ display: 'block', mb: 0.5 }}\n >\n {label ? `Tab: ${label}` : 'Tab: (no label set)'}\n </Typography>\n ) : null}\n {mounted ? (\n aglynDeferred && visible ? (\n // Opened, but its nodes are still in flight (AGL-1287). Only while\n // VISIBLE — a deferred panel nobody has opened must stay silent, or\n // every unopened tab would render a spinner into the page.\n //\n // Deliberately not a skeleton of the content: a withheld subtree can\n // be a 50-row table or a paragraph, and this component has no way to\n // know which, so a shaped skeleton would be a guess that flashes\n // wrong. `role=\"status\"` announces it to a screen reader, which\n // otherwise gets a panel that is silently empty for seconds.\n <Typography\n role=\"status\"\n variant=\"body2\"\n color=\"text.secondary\"\n sx={{ display: 'block', py: 2 }}\n >\n {'Loading…'}\n </Typography>\n ) : (\n children\n )\n ) : null}\n </Box>\n )\n})\nTabPanelElement.displayName = 'AglynTabPanel'\n\n/** `centered` is a standard-strip-only prop; MUI warns when scrollable. */\nconst STANDARD_ONLY = { when: 'variant', is: 'scrollable', notMatch: true }\n\n/**\n * Shows a per-tab link picker only once the label list has that many tabs,\n * so a three-tab strip offers three pickers rather than eight.\n *\n * Expressed as a serialisable `pattern` rather than an `is` predicate:\n * conditions travel with the component schema, and a function in there is a\n * live grenade the day a schema is cloned or sent across a boundary. An\n * \"item\" is a run without a separator that holds something visible, and a\n * separator run swallows blank lines, so it counts exactly what\n * `parseLabels` counts.\n */\nexport function atLeastLabels(count: number): Record<string, unknown> {\n if (count <= 1) return { when: 'labels', isNotEmpty: true }\n const item = '[^\\\\n,]*\\\\S[^\\\\n,]*'\n const separator = '[\\\\n,][\\\\s,]*'\n return {\n when: 'labels',\n pattern: `(?:${item}${separator}){${count - 1}}${item}`,\n }\n}\n\n/**\n * The \"Opens on\" field's `resolveProps`: its answers are the element's OWN\n * tab labels, read from the sibling `labels` field as they are typed\n * (AGL-3164).\n *\n * A picker rather than a typed index or a typed label. An index goes on\n * meaning \"the second tab\" after a reorder, with nothing on screen to say\n * the wrong panel now opens; a typed label breaks on a rename and on every\n * typo in between. Choosing from the list the author has just written is the\n * only form of this control someone who does not write code can get right,\n * which is the whole reason it exists instead of the tabs being reordered by\n * hand to obtain a behavior.\n *\n * The answers follow the label list as it is edited because the field's\n * `condition` names `labels`: data-driven-forms subscribes a conditional\n * field to its condition's trigger fields, and that subscription is what\n * re-runs this.\n *\n * A stored label the list no longer holds is offered back as its own option,\n * named as gone. The element itself already falls back to the first tab, so\n * the page is never broken by one; but a picker that rendered BLANK would\n * read as \"not set\", and the author would never learn that the choice they\n * made has stopped being honoured — the same reason a Screen picker names a\n * target the host no longer has (AGL-1893).\n */\nexport function opensOnFieldProps(\n _props: unknown,\n field: { input?: { value?: unknown } },\n formOptions?: {\n getFieldState?: (name: string) => { value?: unknown } | undefined\n getState?: () => { values?: Record<string, unknown> } | undefined\n },\n): { options: { value: string; label: string }[] } {\n // The registered field first, the form's values as the fallback: a field\n // that has not registered yet has no state, and the values are there from\n // the first render.\n const authored =\n formOptions?.getFieldState?.('labels')?.value ??\n formOptions?.getState?.()?.values?.['labels']\n const options = parseLabels(authored).map((label) => ({\n value: label,\n label,\n }))\n const stored = field?.input?.value\n if (\n typeof stored === 'string' &&\n stored.trim() &&\n !options.some((option) => labelsMatch(option.value, stored))\n ) {\n options.push({ value: stored, label: `${stored} (no longer a tab)` })\n }\n return { options }\n}\n\n/** \"1st\", \"2nd\", \"3rd\", … for the link fields' own descriptions. */\nfunction ordinal(position: number): string {\n const suffix =\n position % 10 === 1 && position !== 11\n ? 'st'\n : position % 10 === 2 && position !== 12\n ? 'nd'\n : position % 10 === 3 && position !== 13\n ? 'rd'\n : 'th'\n return `${position}${suffix}`\n}\n\n/**\n * One Screen picker per tab position (AGL-1312), the same field the Screen\n * Link element uses — so a tab's target is chosen from the host's screens\n * and survives a slug rename, and the attributes panel needs no new UI.\n *\n * Deliberately NOT paired with a \"link mode\" switch: a mode select would\n * need its default to persist, and an `''` option value cannot (AGL-1191 —\n * the form strips it before save). Carrying a link IS the mode, per tab,\n * which is also what makes a mixed row expressible at all.\n */\nconst TAB_LINK_FIELDS: Aglyn.AglynAttributeSchema[] = Array.from(\n { length: TAB_LINK_SLOTS },\n (_unused, index) => {\n const position = index + 1\n return {\n name: tabLinkProp(position),\n label: `Tab ${position} link`,\n description:\n `Screen the ${ordinal(position)} tab navigates to. A tab with a ` +\n 'link is a real link — it can be opened in a new tab and search ' +\n 'engines follow it — and it no longer switches panels. Leave it ' +\n 'unset for a tab that just reveals its own panel, including the ' +\n 'tab for the page this row is already on.',\n component: Aglyn.FieldComponentType.SCREEN_SELECT,\n condition: atLeastLabels(position),\n }\n },\n)\n\nexport const tabsSchema: Aglyn.ComponentSchema<TabsElementProps> = {\n $id: TABS_ID,\n pluginId: BUNDLE_ID,\n displayName: 'Tabs',\n description:\n 'Tab strip whose Tab Panel children each name the tab that reveals ' +\n 'them.',\n category: Aglyn.ComponentCategory.NAVIGATION,\n icon: { path: mdiTab.path, sx: { color: '#2196f3' } },\n restrictChildren: [\n Aglyn.LinealDirectiveFlag.LIMIT_TO,\n { components: [TAB_PANEL_ID] },\n ],\n attributes: [\n {\n name: 'labels',\n label: 'Tabs',\n description:\n 'One tab label per line. Each Tab Panel below shows under the ' +\n 'tab whose label it names.',\n component: Aglyn.FieldComponentType.TEXTAREA,\n },\n ...TAB_LINK_FIELDS,\n {\n name: 'opensOn',\n label: 'Opens on',\n description:\n 'The tab a visitor lands on. Leave it unset and the first tab ' +\n 'opens, as it always has. Pick from the tabs above rather than ' +\n 'reordering them — the strip is the design, and which tab opens ' +\n 'is not. If the tab named here is later renamed or removed, the ' +\n 'first tab opens again.',\n component: Aglyn.FieldComponentType.SELECT,\n // Nothing to choose on a one-tab strip — and naming `labels` is also\n // what keeps the answers following the list (see opensOnFieldProps).\n condition: atLeastLabels(2),\n resolveProps: opensOnFieldProps,\n // The corner ✕ is the way back to \"the first tab\": no option could\n // carry that meaning, since an `''` value is stripped before save\n // (AGL-1191) and every other value names a real tab.\n clearable: true,\n },\n {\n name: 'orientation',\n label: 'Orientation',\n description:\n 'Vertical puts the strip beside the panels instead of above them.',\n component: Aglyn.FieldComponentType.SELECT,\n // Real sentinels throughout this schema rather than deletions\n // (AGL-1451): each \"(default)\" here names MUI's OWN value for that\n // prop — horizontal, standard, primary — so the option is a real\n // choice an author may want to pin, not a synonym for \"unset\".\n // Spelled `''` they could not persist at all (AGL-1191): picking\n // Horizontal on a vertical strip silently reverted to vertical.\n options: [\n { value: 'horizontal', label: 'Horizontal (default)' },\n { value: 'vertical', label: 'Vertical' },\n ],\n },\n {\n name: 'variant',\n label: 'Variant',\n description:\n 'Scrollable keeps long strips usable on small screens; full width ' +\n 'divides the available space evenly.',\n component: Aglyn.FieldComponentType.SELECT,\n options: [\n { value: 'standard', label: 'Standard (default)' },\n { value: 'scrollable', label: 'Scrollable' },\n { value: 'fullWidth', label: 'Full width' },\n ],\n },\n {\n name: 'ssrPanels',\n label: 'Keep every panel in the page source',\n description:\n 'Panels are normally built the first time their tab is opened, ' +\n 'which keeps big tab sets light. Turn this on when panel content ' +\n 'appears nowhere else on the page and search engines must be able ' +\n 'to read it — every panel is then rendered into the page source ' +\n 'up front, which can make a large tab set much heavier.',\n component: Aglyn.FieldComponentType.SWITCH,\n },\n {\n name: 'centered',\n label: 'Centered?',\n description: 'Centers the tabs in the strip.',\n component: Aglyn.FieldComponentType.SWITCH,\n // MUI ignores centered on a scrollable strip and warns in dev.\n condition: STANDARD_ONLY,\n },\n {\n name: 'textColor',\n label: 'Text color',\n description: 'Theme color of the tab labels.',\n component: Aglyn.FieldComponentType.SELECT,\n options: [\n { value: 'primary', label: 'Primary (default)' },\n { value: 'secondary', label: 'Secondary' },\n { value: 'inherit', label: 'Inherit' },\n ],\n },\n {\n name: 'indicatorColor',\n label: 'Indicator color',\n description: 'Theme color of the underline marking the active tab.',\n component: Aglyn.FieldComponentType.SELECT,\n options: [\n { value: 'primary', label: 'Primary (default)' },\n { value: 'secondary', label: 'Secondary' },\n ],\n },\n {\n name: 'ariaLabel',\n label: 'Accessible label',\n description:\n 'Names the row for screen readers. Default \"Tabs\". Give a row ' +\n 'whose tabs link to other screens its own name — it becomes a ' +\n 'navigation landmark, and two landmarks called the same thing are ' +\n 'no help to anyone.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n },\n ],\n}\n\nexport const tabPanelSchema: Aglyn.ComponentSchema<TabPanelElementProps> = {\n $id: TAB_PANEL_ID,\n pluginId: BUNDLE_ID,\n displayName: 'Tab Panel',\n description: 'The content shown under one tab.',\n category: Aglyn.ComponentCategory.NAVIGATION,\n icon: { path: mdiViewCarousel.path, sx: { color: '#2196f3' } },\n attributes: [\n {\n name: 'label',\n label: 'Shows under tab',\n description:\n \"The tab label this panel belongs to — type it exactly as it \" +\n 'appears in the Tabs list above (capitalisation is ignored).',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n },\n ],\n}\n\nconst tabPanel = (label: string, body: string) => ({\n $id: null,\n componentId: TAB_PANEL_ID,\n pluginId: BUNDLE_ID,\n props: { label },\n nodes: [\n {\n $id: null,\n componentId: 'muiTypography',\n pluginId: BUNDLE_ID,\n props: { variant: 'body2', children: body },\n },\n ],\n})\n\nexport const tabsPresets: Aglyn.PresetSchema[] = [\n {\n // Labels and panels ship already matched: the one place this element\n // can be misconfigured is never hit on the common path.\n $id: generatePresetId(TABS_ID),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Tabs',\n pluginId: BUNDLE_ID,\n description: 'Three tabs with matching panels, ready to edit',\n category: Aglyn.ComponentCategory.NAVIGATION,\n icon: tabsSchema.icon,\n data: {\n $id: null,\n componentId: TABS_ID,\n pluginId: BUNDLE_ID,\n props: { labels: 'Overview\\nDetails\\nFAQ' },\n nodes: [\n tabPanel('Overview', 'What this is, in a sentence or two.'),\n tabPanel('Details', 'The specifics that back up the overview.'),\n tabPanel('FAQ', 'The questions people actually ask.'),\n ],\n },\n },\n {\n $id: generatePresetId(TAB_PANEL_ID),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Tab Panel',\n pluginId: BUNDLE_ID,\n description: 'One more panel to add to an existing Tabs element',\n category: Aglyn.ComponentCategory.NAVIGATION,\n icon: tabPanelSchema.icon,\n data: tabPanel('', 'Name the tab this panel belongs to.'),\n },\n]\n\nexport default TabsElement\n"],"names":["Aglyn","mdiTab","mdiViewCarousel","AppLink","Box","MuiTab","MuiTabs","Typography","createContext","forwardRef","useContext","useState","BUNDLE_ID","dropClearedProps","generatePresetId","TABS_ID","TAB_PANEL_ID","TAB_LINK_SLOTS","tabLinkProp","position","parseLabels","value","String","split","map","label","trim","filter","Boolean","labelSlug","toLowerCase","replace","labelsMatch","a","b","openingTabIndex","labels","opensOn","linkIds","named","findIndex","index","landing","_label","TabsContext","undefined","TabsElement","rawProps","ref","parsed","props","ariaLabel","orientation","variant","centered","textColor","indicatorColor","ssrPanels","lazyPanels","children","rest","editorInert","suppressNavigation","useScreenLink","screens","ScreenLinkContext","slot","key","push","navMode","some","opening","active","setActive","opened","setOpened","first","Set","chosen","length","activeIndex","resolvedVariant","vertical","stripLabel","strip","onChange","_event","next","prev","has","add","component","slotProps","root","list","role","slug","id","aria-controls","href","resolveScreenHref","broken","isScreenLinkBroken","componentVariant","disabled","brokenScreenLinkProps","sx","BROKEN_SCREEN_LINK_SX","aria-selected","aria-current","tabIndex","Provider","activeLabel","showAll","display","Array","isArray","displayName","TabPanelElement","aglynDeferred","context","selected","visible","mounted","hidden","aria-labelledby","p","color","mb","py","STANDARD_ONLY","when","is","notMatch","atLeastLabels","count","isNotEmpty","item","separator","pattern","opensOnFieldProps","_props","field","formOptions","authored","getFieldState","getState","values","options","stored","input","option","ordinal","suffix","TAB_LINK_FIELDS","from","_unused","name","description","FieldComponentType","SCREEN_SELECT","condition","tabsSchema","$id","pluginId","category","ComponentCategory","NAVIGATION","icon","path","restrictChildren","LinealDirectiveFlag","LIMIT_TO","components","attributes","TEXTAREA","SELECT","resolveProps","clearable","SWITCH","TEXT_FIELD","tabPanelSchema","tabPanel","body","componentId","nodes","tabsPresets","type","NodeType","PRESET","data"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/components/tabs.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 { mdiTab, mdiViewCarousel } from '@aglyn/shared-data-mdi'\nimport { AppLink } from '@aglyn/shared-ui-jsx'\nimport Box from '@mui/material/Box'\nimport MuiTab from '@mui/material/Tab'\nimport MuiTabs from '@mui/material/Tabs'\nimport Typography from '@mui/material/Typography'\nimport type { SxProps } from '@mui/material/styles'\nimport {\n createContext,\n forwardRef,\n type ReactNode,\n useContext,\n useState,\n} from 'react'\nimport { BUNDLE_ID } from '../constants/bundle-common'\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 TABS_ID: Aglyn.ComponentId = 'muiTabs'\nexport const TAB_PANEL_ID: Aglyn.ComponentId = 'muiTabPanel'\n\n/**\n * How many tabs in a strip can carry a screen link (AGL-1312). The strip is\n * authored as a free-form label list, so the links have to be flat props —\n * one per position — and a flat prop needs a name that exists up front.\n *\n * Eight is well past any usable navigation row (the marketing content-tabs\n * row is three) and costs nothing at render: the attributes panel only shows\n * a link picker for a tab that actually exists, so a two-tab strip shows two.\n */\nexport const TAB_LINK_SLOTS = 8\n\n/** Prop name carrying the link of the 1-based `position`-th tab. */\nexport function tabLinkProp(position: number): string {\n return `tabLink${position}`\n}\n\n/**\n * The per-tab screen links, `tabLink1`…`tabLink8`. Declared as a mapped type\n * rather than an index signature: an index signature on the props interface\n * would force `sx`, `children` and the rest to conform to it.\n */\nexport type TabLinkProps = Partial<\n Record<\n | 'tabLink1'\n | 'tabLink2'\n | 'tabLink3'\n | 'tabLink4'\n | 'tabLink5'\n | 'tabLink6'\n | 'tabLink7'\n | 'tabLink8',\n string\n >\n>\n\nexport interface TabsElementProps extends TabLinkProps {\n /** Tab labels, one per line (commas also accepted). */\n labels?: string\n /**\n * The LABEL of the tab the strip opens on (AGL-3164). Unset opens the\n * first tab, which is what every Tabs already in the wild does.\n *\n * A label rather than a position, because a position is a silent lie the\n * moment the list is edited: it keeps pointing at \"the second tab\" after\n * the author reorders or renames, and nothing on screen says the wrong\n * panel is now the one that opens. A label that no longer exists simply\n * does not match, and the strip falls back to the first tab.\n *\n * See {@link openingTabIndex} for the whole rule, and `deferLazyPanelNodes`\n * in tenant-runtime for the server side of it — the two must agree or the\n * page ships the wrong panel's markup.\n */\n opensOn?: string\n /** Accessible name of the strip; also names the nav landmark in link mode. */\n ariaLabel?: string\n orientation?: 'horizontal' | 'vertical'\n variant?: 'standard' | 'scrollable' | 'fullWidth'\n /** Centres a standard strip; MUI ignores it when scrollable. */\n centered?: boolean\n textColor?: 'primary' | 'secondary' | 'inherit'\n indicatorColor?: 'primary' | 'secondary' | 'tertiary'\n /**\n * Render every panel into the SSR output up front instead of building each\n * panel the first time its tab is opened (AGL-1283 option 3).\n *\n * Mount-on-first-selection is the DEFAULT: `/pricing` shipped eight copies\n * of a 50-row table so desktop visitors could see none of them, and any\n * large tab set pays the same tax silently. The trade is that an unopened\n * panel's content is then not in the page source — not indexable, not\n * findable — so this switch exists for the panels where that matters:\n * content that appears nowhere else on the page and must reach crawlers.\n */\n ssrPanels?: boolean\n /**\n * Legacy opt-in from when eager panels were the default (AGL-1283).\n * Lazy mounting is now the default, so this is accepted from existing\n * documents but no longer consulted — `ssrPanels` is the one switch.\n * Still destructured so an authored value never leaks onto the DOM.\n */\n lazyPanels?: boolean\n /**\n * Authored node styles, handed over by the renderer rather than typed into\n * an attribute — the merge below reads it, so it belongs on the public\n * interface. Leaving it undeclared (AGL-1284 added the reads, not the\n * declaration) meant no typed caller could pass one, including the specs\n * that exist to prove an authored `sx` survives (AGL-1323).\n */\n sx?: SxProps\n children?: ReactNode\n}\n\nexport interface TabPanelElementProps {\n /** Which tab reveals this panel; must match one of the Tabs labels. */\n label?: string\n /**\n * Set by the server when this panel's children were withheld from the page\n * payload (AGL-1285, `deferLazyPanelNodes`) — never authored, and there is\n * deliberately no attribute for it.\n *\n * It must be destructured off the prop bag either way: everything else on\n * this element is spread straight onto a `Box`, so leaving it in produced a\n * React \"does not recognize the prop\" warning for every deferred panel.\n *\n * It also drives the loading state. A withheld panel that the reader has\n * just opened has no children yet and is indistinguishable from a panel that\n * is genuinely empty, and the fetch behind it is a full server compose —\n * 3.8s cold when measured. This flag is what lets the panel say so.\n *\n * It clears itself: the patch from `/api/screen/nodes` carries the ORIGINAL\n * panel nodes, which never had the marker, so the moment the real children\n * arrive this is gone and the placeholder with it (AGL-1287).\n */\n aglynDeferred?: boolean\n /** Authored node styles, merged over the panel's own — see Tabs' `sx`. */\n sx?: SxProps\n children?: ReactNode\n}\n\n/**\n * Splits the authored label list. Newline-separated is the documented\n * form; commas are accepted because a one-line \"A, B, C\" is what people\n * type first.\n */\nexport function parseLabels(value: unknown): string[] {\n if (value == null) return []\n return String(value)\n .split(/[\\n,]/)\n .map((label) => label.trim())\n .filter(Boolean)\n}\n\n/** Stable DOM id fragment for the tab ⇄ panel aria wiring. */\nexport function labelSlug(label: string): string {\n return (\n label\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-|-$/g, '') || 'tab'\n )\n}\n\n/** Case/whitespace-insensitive: authors don't retype labels exactly. */\nexport function labelsMatch(a: unknown, b: unknown): boolean {\n return (\n String(a ?? '').trim().toLowerCase() ===\n String(b ?? '').trim().toLowerCase()\n )\n}\n\n/**\n * Which tab the strip opens on, by index into the parsed label list.\n *\n * Two rules, in order:\n *\n * 1. the tab the author NAMED in `opensOn` (AGL-3164), matched by label with\n * the same case/whitespace tolerance panels are matched with;\n * 2. otherwise the landing tab — the first one WITHOUT a screen link, which\n * is how a navigation row says \"this is the page you are on\" (AGL-1312),\n * and which is tab 0 on a strip with no links at all, i.e. exactly what\n * this element did before the attribute existed.\n *\n * The named tab is refused when it carries a screen link: a linked tab\n * navigates instead of revealing a panel (AGL-1312), so it is not a tab the\n * strip can rest on, and opening on it would show the indicator over a panel\n * nobody can see. It falls back rather than rendering nothing.\n *\n * Never returns -1. `landing` is -1 when EVERY tab navigates — the strip\n * shows no indicator there, but callers still read a label with this index.\n */\nexport function openingTabIndex(\n labels: readonly string[],\n opensOn?: unknown,\n linkIds: readonly (string | undefined)[] = [],\n): number {\n const named = labels.findIndex(\n (label, index) => !linkIds[index] && labelsMatch(label, opensOn),\n )\n if (named >= 0) return named\n const landing = labels.findIndex((_label, index) => !linkIds[index])\n return landing < 0 ? 0 : landing\n}\n\ninterface TabsContextValue {\n activeLabel: string\n /** True on the besigner canvas, where every panel is shown at once. */\n showAll: boolean\n /** Panels render nothing until first selected (AGL-1283). */\n lazyPanels: boolean\n /** Labels opened at least once — a lazily mounted panel stays mounted. */\n opened: ReadonlySet<string>\n /**\n * True when at least one tab carries a screen link (AGL-1312), which makes\n * the whole row navigation rather than a tab list — see the a11y note on\n * `TabsElement`. Panels drop `role=\"tabpanel\"` in that mode: a tabpanel\n * with no tablist to belong to is orphaned ARIA.\n */\n navMode: boolean\n}\n\nexport const TabsContext = createContext<TabsContextValue | undefined>(\n undefined,\n)\n\n/**\n * Tabs (https://mui.com/material-ui/react-tabs/).\n *\n * The strip is authored on the container as a label list, and each Tab\n * Panel child names the label it belongs to. It does **not** slice its\n * React children by index: the node renderer hands every component a\n * single `Branch` fragment rather than one element per child node\n * (`libs/aglyn-node-renderer`), so an index-based split would silently\n * put all the content behind the first tab. Matching by label also\n * survives reordering panels in the hierarchy.\n *\n * The strip renders from the author's own list, so it is complete in the\n * SSR output — no registration pass, no empty-then-filled flash, and it\n * still reads as a tab list with JavaScript disabled.\n *\n * ## Link mode (AGL-1312)\n *\n * Any tab may carry a screen link (`tabLink1`…`tabLink8`, by position). A\n * tab that has one renders as a real anchor — navigable, crawlable,\n * middle-clickable — because the row it exists for (Blog | Changelog |\n * Newsroom) is navigation ACROSS screens, which a panel switcher can only\n * fake with empty panels or a hand-styled row of buttons. The anchor is an\n * `AppLink`, never a bare `href`: a raw href full-reloads the SPA.\n *\n * A tab WITHOUT a link keeps today's behavior exactly, and mixed rows work\n * — the marketing pattern IS a mixed row, since the tab for the page you\n * are already on must not link to itself. That unlinked tab is also how the\n * author says which page this copy of the row is on: the strip lands on it,\n * so the same three-tab row placed on three screens shows the indicator in\n * the right place on each, with no \"selected tab\" attribute to keep in sync\n * — `opensOn` below is for panel rows and gives way to this one.\n *\n * ## Which tab opens (AGL-3164)\n *\n * `opensOn` names it, by LABEL. Unset opens the first tab, which is what\n * every Tabs authored before the attribute existed does; a label that no\n * longer matches opens the first tab too, rather than nothing. The rule\n * lives in {@link openingTabIndex} and is mirrored server-side by\n * `deferLazyPanelNodes` (tenant-runtime), which decides which panel's nodes\n * reach the page at all — so the tab that opens is the one that was\n * rendered, and the page does not paint one panel and swap to another.\n *\n * **Accessibility.** The row is a `tablist` only while NOTHING in it\n * navigates. As soon as one tab carries a link the whole strip is marked up\n * as navigation: a `nav` landmark, no `role=\"tab\"`, no `aria-selected`, and\n * no roving tab stop (every link is its own tab stop, as in any nav). The\n * alternative — an `<a href>` wearing `role=\"tab\"` — tells assistive tech\n * the activation will reveal a panel when it actually loads a page, and a\n * tablist whose children are not tabs is invalid either way. The tab for\n * the current screen is marked `aria-current=\"page\"`; tabs that still\n * switch panels stay buttons and keep their `aria-controls`, which is an\n * accurate disclosure relationship on its own. The half-applied version of\n * this — links inside a tablist, or panels still claiming `role=\"tabpanel\"`\n * with no tablist above them — is what this deliberately avoids.\n */\nconst TabsElement = forwardRef<HTMLDivElement, TabsElementProps>(\n (rawProps, ref) => {\n // Cleared props dropped up front (AGL-1451). The four selects below\n // already coalesce their own value, but `rest` is spread onto the root\n // and the per-tab link props are read out of it, so a `null` from the\n // field's ✕ (AGL-1226) must not survive this far.\n const props = dropClearedProps(rawProps)\n const {\n labels,\n ariaLabel,\n orientation,\n variant,\n centered,\n textColor,\n indicatorColor,\n ssrPanels,\n lazyPanels,\n opensOn,\n children,\n ...rest\n } = props\n const { editorInert, suppressNavigation } = Aglyn.useScreenLink(undefined)\n // Read the routing map directly rather than calling `useScreenLink` per\n // tab: the number of tabs changes with the label list, and a hook per\n // list item is a rules-of-hooks violation waiting for the author to add\n // a fourth tab.\n const { screens } = useContext(Aglyn.ScreenLinkContext)\n // Screen ids by tab position, lifted out of `rest` so they can never\n // reach the DOM as unknown attributes (the nav-menu does the same with\n // its legacy trigger prop).\n const linkIds: (string | undefined)[] = []\n for (let slot = 1; slot <= TAB_LINK_SLOTS; slot += 1) {\n const key = tabLinkProp(slot)\n const value = (rest as Record<string, unknown>)[key]\n linkIds.push(typeof value === 'string' && value ? value : undefined)\n delete (rest as Record<string, unknown>)[key]\n }\n const parsed = parseLabels(labels)\n // Authored links decide the mode, NOT resolved hrefs: the canvas and\n // preview suppress navigation, and they must still show the element the\n // page will actually ship (the same rule Screen Link follows).\n const navMode = parsed.some((_label, index) => !!linkIds[index])\n /**\n * The tab a navigation row LANDS on is the one with no link: the row is\n * placed on every screen it names, and on each of those the tab for that\n * screen is left unlinked, because a page that links to itself helps\n * nobody. So \"first tab with no link\" is how the author says \"this is\n * the page you are on\" — without a second attribute, and without this\n * element having to know the current route.\n *\n * `-1` means every tab navigates: nothing is current, and the strip\n * shows no indicator rather than inventing one under the first tab.\n * With no links at all this is 0, i.e. exactly today's behavior.\n */\n const landing = parsed.findIndex((_label, index) => !linkIds[index])\n // Which tab this strip opens on (AGL-3164): the one the author named,\n // and otherwise `landing` — so an unset attribute, or one naming a label\n // that has since been renamed away, behaves exactly as it always did.\n const opening = openingTabIndex(parsed, opensOn, linkIds)\n const [active, setActive] = useState(opening)\n // Once a lazy panel has been opened it stays mounted: re-tabbing between\n // two plans should not re-render 50 rows each time, and anything the\n // reader typed or scrolled inside a panel survives a round trip.\n //\n // Seeded with the OPENING label, because that panel is open from the\n // start without anyone clicking it. Leaving it out unmounted the opening\n // panel the moment the reader moved away — visibly inconsistent with\n // every other panel they had visited, and caught by the round-trip test.\n const [opened, setOpened] = useState<ReadonlySet<string>>(() => {\n const first = parsed[opening]\n return new Set<string>(first === undefined ? [] : [first])\n })\n // A label removed from the list must not leave the strip pointing at\n // a tab that no longer exists — MUI warns and drops the indicator.\n //\n // On the besigner canvas the authored attribute is read every render\n // instead of the state seeded at mount: `onChange` is inert there, so\n // nothing else can have moved the selection, and a canvas that kept\n // showing the tab that was open when the element mounted would make\n // \"Opens on\" look like it had done nothing.\n const chosen = editorInert ? opening : active < parsed.length ? active : 0\n // A tab that navigates is never the selected one; if the author has just\n // given the open tab a link, fall back to one that still has a panel.\n const activeIndex = linkIds[chosen] && landing >= 0 ? landing : chosen\n const resolvedVariant = variant || 'standard'\n const vertical = orientation === 'vertical'\n const stripLabel = ariaLabel || 'Tabs'\n\n const strip = (\n <MuiTabs\n // No indicator when every tab navigates: there is no selection to\n // show, and marking one anyway would point at the wrong page.\n value={parsed.length && landing >= 0 ? activeIndex : false}\n onChange={\n editorInert\n ? undefined\n : (_event, next: number) => {\n // A navigating tab must not move the selection on its way\n // out: the indicator would jump to a tab whose panel is\n // empty while the next page is still loading.\n if (linkIds[next]) return\n setActive(next)\n const label = parsed[next]\n if (label !== undefined) {\n setOpened((prev) =>\n prev.has(label) ? prev : new Set(prev).add(label),\n )\n }\n }\n }\n orientation={vertical ? 'vertical' : 'horizontal'}\n variant={resolvedVariant}\n // MUI ignores `centered` on a scrollable strip and warns in dev.\n centered={resolvedVariant === 'standard' ? !!centered : undefined}\n textColor={textColor || 'primary'}\n indicatorColor={indicatorColor || 'primary'}\n // Link mode is navigation, so the root becomes the `nav` landmark\n // and the inner flex row gives up `role=\"tablist\"`. The accessible\n // name moves with it: MUI puts `aria-label` on the list, which in\n // this mode is a plain div and cannot carry the landmark's name.\n {...(navMode\n ? {\n component: 'nav',\n slotProps: {\n root: { 'aria-label': stripLabel },\n list: { role: undefined },\n },\n }\n : { 'aria-label': stripLabel })}\n >\n {parsed.map((label, index) => {\n const slug = labelSlug(label)\n const key = `${slug}-${index}`\n if (!navMode) {\n return (\n <MuiTab\n key={key}\n label={label}\n id={`tab-${slug}`}\n aria-controls={`tabpanel-${slug}`}\n />\n )\n }\n // Suppressed navigation (canvas, preview) keeps the item in the\n // row but without an href, so a click cannot leave the editor.\n const href = suppressNavigation\n ? undefined\n : Aglyn.resolveScreenHref(screens, linkIds[index])\n // An authored target that the routing map does not have: the\n // screen was unpublished or deleted out from under this row\n // (AGL-1893). Computed from the MAP, never from `href`, so a\n // canvas or preview render — where nothing has an href on purpose\n // — does not paint every working link as dead.\n const broken = Aglyn.isScreenLinkBroken(screens, linkIds[index])\n return (\n <MuiTab\n key={key}\n label={label}\n id={`tab-${slug}`}\n // Only a tab that still reveals a panel controls anything.\n aria-controls={linkIds[index] ? undefined : `tabpanel-${slug}`}\n {...(href\n ? { component: AppLink, componentVariant: 'naked', href }\n : null)}\n /**\n * A tab whose screen is gone stops being a control (AGL-1893).\n *\n * It used to render as a bare `<button>` indistinguishable\n * from its working neighbours: no href, no `aria-controls`,\n * and `onChange` returns early on it because the AUTHORED id\n * is still there — so it looked live, announced live, and did\n * nothing at all. Live on `/changelog` and `/newsroom` for two\n * days without anything anywhere saying so.\n *\n * Disabled rather than hidden, on purpose:\n *\n * - the routing map differs between the render that produced\n * an ISR page and the render that hydrates it, and AGL-1268\n * settled that a node's ELEMENT must not depend on it —\n * removing the tab would make the strip's DOM shape depend\n * on it, which is strictly worse than an attribute;\n * - `MuiTabs` addresses its children by index, so dropping one\n * silently repoints `value` at the wrong tab;\n * - the failure directions are not symmetric. A wrongly\n * disabled tab is a dimmed label; a wrongly hidden one is\n * navigation that vanished from a customer's site with no\n * trace of why.\n *\n * Falling through to panel behaviour instead — the other\n * option AGL-1893 weighed — is not available to this element:\n * the node renderer hands it ONE `Branch` fragment rather than\n * per-panel children, so a Tabs container cannot know whether\n * a panel with this label exists, and on the real `/changelog`\n * shape it does not.\n *\n * `landing`, `opening`, `activeIndex`, `aria-controls` and the\n * `onChange` guard all still read the AUTHORED id, unchanged.\n * They must: `deferLazyPanelNodes` computes the opening label\n * server-side from the raw `tabLink{n}` props and has no\n * routing map to resolve ids with, so a client that resolved\n * differently would keep a panel the server withheld.\n */\n disabled={broken && !editorInert ? true : undefined}\n // On the canvas the tab stays live: the author has to be able\n // to select the node to repair it. It carries the ring and the\n // explanation instead.\n {...Aglyn.brokenScreenLinkProps(broken, !!editorInert)}\n sx={\n broken && editorInert\n ? Aglyn.BROKEN_SCREEN_LINK_SX\n : undefined\n }\n // MUI writes these before spreading the rest, so passing them\n // undefined is what removes them (see the a11y note above).\n role={undefined}\n aria-selected={undefined}\n aria-current={\n landing >= 0 && index === activeIndex ? 'page' : undefined\n }\n // Undo the roving tab stop: in a nav every item is reachable\n // with Tab, and MUI's arrow-key handler already stands down\n // because it only moves between `role=\"tab\"` siblings.\n tabIndex={undefined}\n />\n )\n })}\n </MuiTabs>\n )\n\n return (\n <TabsContext.Provider\n value={{\n activeLabel: parsed[activeIndex] ?? '',\n // Every panel at once on the canvas: a hidden panel cannot be\n // selected or styled, the same reason Accordion force-expands.\n showAll: !!editorInert,\n // Lazy is the default (AGL-1283 option 3); `ssrPanels` is the SEO\n // escape hatch. The legacy `lazyPanels` opt-in is subsumed: `true`\n // now means what the default means, and a stored `false` was only\n // ever the old default, never an author's intent.\n lazyPanels: !ssrPanels,\n opened,\n navMode,\n }}\n >\n <Box\n ref={ref}\n {...rest}\n // MERGE, never replace. `sx` written after `{...rest}` silently\n // discarded whatever the author set on the node — every Tabs on\n // every site rendered with default MUI styling and no way to\n // change it, with nothing in the editor to suggest the value had\n // been dropped (AGL-1284). Vertical orientation still needs the\n // flex row, so it goes first and the author can override it.\n sx={[\n { display: vertical ? 'flex' : undefined },\n ...(Array.isArray(rest.sx) ? rest.sx : [rest.sx]),\n ]}\n >\n {strip}\n {children}\n </Box>\n </TabsContext.Provider>\n )\n },\n)\nTabsElement.displayName = 'AglynTabs'\n\n/**\n * One tab's content. Outside a Tabs container it renders plainly rather\n * than disappearing — a panel dragged out of its tabs would otherwise\n * vanish from the canvas with no explanation.\n */\nexport const TabPanelElement = forwardRef<\n HTMLDivElement,\n TabPanelElementProps\n>((props, ref) => {\n const { label, aglynDeferred, children, ...rest } = props\n const context = useContext(TabsContext)\n const selected = !context || labelsMatch(label, context.activeLabel)\n const visible = selected || !!context?.showAll\n /**\n * With `lazyPanels`, an unopened panel renders its wrapper but not its\n * children — the wrapper stays so the `aria-controls` target and the\n * tab ⇄ panel wiring still resolve, and so nothing about the accessible\n * structure depends on whether the reader has clicked yet.\n *\n * `opened` is checked as well as `selected` because a panel that has been\n * visited stays mounted; only the never-opened ones are skipped.\n */\n const mounted =\n !context ||\n !context.lazyPanels ||\n context.showAll ||\n selected ||\n context.opened.has(String(label ?? ''))\n\n /**\n * In link mode the strip is a nav, not a tablist (AGL-1312), so a panel\n * has no tablist to belong to and drops the tab-pattern ARIA rather than\n * claiming half of it. The id stays — the button that still reveals this\n * panel points `aria-controls` at it, which is a valid relationship on\n * its own — and an orphan panel (dragged out of its Tabs, no context)\n * keeps today's markup untouched.\n */\n const navMode = !!context?.navMode\n\n return (\n <Box\n ref={ref}\n role={navMode ? undefined : 'tabpanel'}\n hidden={!visible}\n id={`tabpanel-${labelSlug(String(label ?? ''))}`}\n aria-labelledby={\n navMode ? undefined : `tab-${labelSlug(String(label ?? ''))}`\n }\n {...rest}\n // Same merge bug as the Tabs container (AGL-1284): the author's `sx`\n // was dropped, so a panel could not even have its padding changed.\n // Order matters — the default padding is first so the author can\n // override it, and the hide rule is LAST so an authored `display`\n // can never force a deselected panel back on screen.\n sx={[\n { p: 2 },\n ...(Array.isArray(rest.sx) ? rest.sx : [rest.sx]),\n ...(visible ? [] : [{ display: 'none' }]),\n ]}\n >\n {context?.showAll && !selected ? (\n // Canvas only: says which tab this content belongs to, so a\n // stack of panels is readable and a label typo is obvious.\n <Typography\n variant=\"caption\"\n color=\"text.secondary\"\n sx={{ display: 'block', mb: 0.5 }}\n >\n {label ? `Tab: ${label}` : 'Tab: (no label set)'}\n </Typography>\n ) : null}\n {mounted ? (\n aglynDeferred && visible ? (\n // Opened, but its nodes are still in flight (AGL-1287). Only while\n // VISIBLE — a deferred panel nobody has opened must stay silent, or\n // every unopened tab would render a spinner into the page.\n //\n // Deliberately not a skeleton of the content: a withheld subtree can\n // be a 50-row table or a paragraph, and this component has no way to\n // know which, so a shaped skeleton would be a guess that flashes\n // wrong. `role=\"status\"` announces it to a screen reader, which\n // otherwise gets a panel that is silently empty for seconds.\n <Typography\n role=\"status\"\n variant=\"body2\"\n color=\"text.secondary\"\n sx={{ display: 'block', py: 2 }}\n >\n {'Loading…'}\n </Typography>\n ) : (\n children\n )\n ) : null}\n </Box>\n )\n})\nTabPanelElement.displayName = 'AglynTabPanel'\n\n/** `centered` is a standard-strip-only prop; MUI warns when scrollable. */\nconst STANDARD_ONLY = { when: 'variant', is: 'scrollable', notMatch: true }\n\n/**\n * Shows a per-tab link picker only once the label list has that many tabs,\n * so a three-tab strip offers three pickers rather than eight.\n *\n * Expressed as a serialisable `pattern` rather than an `is` predicate:\n * conditions travel with the component schema, and a function in there is a\n * live grenade the day a schema is cloned or sent across a boundary. An\n * \"item\" is a run without a separator that holds something visible, and a\n * separator run swallows blank lines, so it counts exactly what\n * `parseLabels` counts.\n */\nexport function atLeastLabels(count: number): Record<string, unknown> {\n if (count <= 1) return { when: 'labels', isNotEmpty: true }\n const item = '[^\\\\n,]*\\\\S[^\\\\n,]*'\n const separator = '[\\\\n,][\\\\s,]*'\n return {\n when: 'labels',\n pattern: `(?:${item}${separator}){${count - 1}}${item}`,\n }\n}\n\n/**\n * The \"Opens on\" field's `resolveProps`: its answers are the element's OWN\n * tab labels, read from the sibling `labels` field as they are typed\n * (AGL-3164).\n *\n * A picker rather than a typed index or a typed label. An index goes on\n * meaning \"the second tab\" after a reorder, with nothing on screen to say\n * the wrong panel now opens; a typed label breaks on a rename and on every\n * typo in between. Choosing from the list the author has just written is the\n * only form of this control someone who does not write code can get right,\n * which is the whole reason it exists instead of the tabs being reordered by\n * hand to obtain a behavior.\n *\n * The answers follow the label list as it is edited because the field's\n * `condition` names `labels`: data-driven-forms subscribes a conditional\n * field to its condition's trigger fields, and that subscription is what\n * re-runs this.\n *\n * A stored label the list no longer holds is offered back as its own option,\n * named as gone. The element itself already falls back to the first tab, so\n * the page is never broken by one; but a picker that rendered BLANK would\n * read as \"not set\", and the author would never learn that the choice they\n * made has stopped being honoured — the same reason a Screen picker names a\n * target the host no longer has (AGL-1893).\n */\nexport function opensOnFieldProps(\n _props: unknown,\n field: { input?: { value?: unknown } },\n formOptions?: {\n getFieldState?: (name: string) => { value?: unknown } | undefined\n getState?: () => { values?: Record<string, unknown> } | undefined\n },\n): { options: { value: string; label: string }[] } {\n // The registered field first, the form's values as the fallback: a field\n // that has not registered yet has no state, and the values are there from\n // the first render.\n const authored =\n formOptions?.getFieldState?.('labels')?.value ??\n formOptions?.getState?.()?.values?.['labels']\n const options = parseLabels(authored).map((label) => ({\n value: label,\n label,\n }))\n const stored = field?.input?.value\n if (\n typeof stored === 'string' &&\n stored.trim() &&\n !options.some((option) => labelsMatch(option.value, stored))\n ) {\n options.push({ value: stored, label: `${stored} (no longer a tab)` })\n }\n return { options }\n}\n\n/** \"1st\", \"2nd\", \"3rd\", … for the link fields' own descriptions. */\nfunction ordinal(position: number): string {\n const suffix =\n position % 10 === 1 && position !== 11\n ? 'st'\n : position % 10 === 2 && position !== 12\n ? 'nd'\n : position % 10 === 3 && position !== 13\n ? 'rd'\n : 'th'\n return `${position}${suffix}`\n}\n\n/**\n * One Screen picker per tab position (AGL-1312), the same field the Screen\n * Link element uses — so a tab's target is chosen from the host's screens\n * and survives a slug rename, and the attributes panel needs no new UI.\n *\n * Deliberately NOT paired with a \"link mode\" switch: a mode select would\n * need its default to persist, and an `''` option value cannot (AGL-1191 —\n * the form strips it before save). Carrying a link IS the mode, per tab,\n * which is also what makes a mixed row expressible at all.\n */\nconst TAB_LINK_FIELDS: Aglyn.AglynAttributeSchema[] = Array.from(\n { length: TAB_LINK_SLOTS },\n (_unused, index) => {\n const position = index + 1\n return {\n name: tabLinkProp(position),\n label: `Tab ${position} link`,\n description:\n `Screen the ${ordinal(position)} tab navigates to. A tab with a ` +\n 'link is a real link — it can be opened in a new tab and search ' +\n 'engines follow it — and it no longer switches panels. Leave it ' +\n 'unset for a tab that just reveals its own panel, including the ' +\n 'tab for the page this row is already on.',\n component: Aglyn.FieldComponentType.SCREEN_SELECT,\n condition: atLeastLabels(position),\n }\n },\n)\n\nexport const tabsSchema: Aglyn.ComponentSchema<TabsElementProps> = {\n $id: TABS_ID,\n pluginId: BUNDLE_ID,\n displayName: 'Tabs',\n description:\n 'Tab strip whose Tab Panel children each name the tab that reveals ' +\n 'them.',\n category: Aglyn.ComponentCategory.NAVIGATION,\n icon: { path: mdiTab.path, sx: { color: '#2196f3' } },\n restrictChildren: [\n Aglyn.LinealDirectiveFlag.LIMIT_TO,\n { components: [TAB_PANEL_ID] },\n ],\n attributes: [\n {\n name: 'labels',\n label: 'Tabs',\n description:\n 'One tab label per line. Each Tab Panel below shows under the ' +\n 'tab whose label it names.',\n component: Aglyn.FieldComponentType.TEXTAREA,\n },\n ...TAB_LINK_FIELDS,\n {\n name: 'opensOn',\n label: 'Opens on',\n description:\n 'The tab a visitor lands on. Leave it unset and the first tab ' +\n 'opens, as it always has. Pick from the tabs above rather than ' +\n 'reordering them — the strip is the design, and which tab opens ' +\n 'is not. If the tab named here is later renamed or removed, the ' +\n 'first tab opens again.',\n component: Aglyn.FieldComponentType.SELECT,\n // Nothing to choose on a one-tab strip — and naming `labels` is also\n // what keeps the answers following the list (see opensOnFieldProps).\n condition: atLeastLabels(2),\n resolveProps: opensOnFieldProps,\n // The corner ✕ is the way back to \"the first tab\": no option could\n // carry that meaning, since an `''` value is stripped before save\n // (AGL-1191) and every other value names a real tab.\n clearable: true,\n },\n {\n name: 'orientation',\n label: 'Orientation',\n description:\n 'Vertical puts the strip beside the panels instead of above them.',\n component: Aglyn.FieldComponentType.SELECT,\n // Real sentinels throughout this schema rather than deletions\n // (AGL-1451): each \"(default)\" here names MUI's OWN value for that\n // prop — horizontal, standard, primary — so the option is a real\n // choice an author may want to pin, not a synonym for \"unset\".\n // Spelled `''` they could not persist at all (AGL-1191): picking\n // Horizontal on a vertical strip silently reverted to vertical.\n options: [\n { value: 'horizontal', label: 'Horizontal (default)' },\n { value: 'vertical', label: 'Vertical' },\n ],\n },\n {\n name: 'variant',\n label: 'Variant',\n description:\n 'Scrollable keeps long strips usable on small screens; full width ' +\n 'divides the available space evenly.',\n component: Aglyn.FieldComponentType.SELECT,\n options: [\n { value: 'standard', label: 'Standard (default)' },\n { value: 'scrollable', label: 'Scrollable' },\n { value: 'fullWidth', label: 'Full width' },\n ],\n },\n {\n name: 'ssrPanels',\n label: 'Keep every panel in the page source',\n description:\n 'Panels are normally built the first time their tab is opened, ' +\n 'which keeps big tab sets light. Turn this on when panel content ' +\n 'appears nowhere else on the page and search engines must be able ' +\n 'to read it — every panel is then rendered into the page source ' +\n 'up front, which can make a large tab set much heavier.',\n component: Aglyn.FieldComponentType.SWITCH,\n },\n {\n name: 'centered',\n label: 'Centered?',\n description: 'Centers the tabs in the strip.',\n component: Aglyn.FieldComponentType.SWITCH,\n // MUI ignores centered on a scrollable strip and warns in dev.\n condition: STANDARD_ONLY,\n },\n {\n name: 'textColor',\n label: 'Text color',\n description: 'Theme color of the tab labels.',\n component: Aglyn.FieldComponentType.SELECT,\n options: [\n { value: 'primary', label: 'Primary (default)' },\n { value: 'secondary', label: 'Secondary' },\n { value: 'inherit', label: 'Inherit' },\n ],\n },\n {\n name: 'indicatorColor',\n label: 'Indicator color',\n description: 'Theme color of the underline marking the active tab.',\n component: Aglyn.FieldComponentType.SELECT,\n options: [\n { value: 'primary', label: 'Primary (default)' },\n { value: 'secondary', label: 'Secondary' },\n { value: 'tertiary', label: 'Tertiary' },\n ],\n },\n {\n name: 'ariaLabel',\n label: 'Accessible label',\n description:\n 'Names the row for screen readers. Default \"Tabs\". Give a row ' +\n 'whose tabs link to other screens its own name — it becomes a ' +\n 'navigation landmark, and two landmarks called the same thing are ' +\n 'no help to anyone.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n },\n ],\n}\n\nexport const tabPanelSchema: Aglyn.ComponentSchema<TabPanelElementProps> = {\n $id: TAB_PANEL_ID,\n pluginId: BUNDLE_ID,\n displayName: 'Tab Panel',\n description: 'The content shown under one tab.',\n category: Aglyn.ComponentCategory.NAVIGATION,\n icon: { path: mdiViewCarousel.path, sx: { color: '#2196f3' } },\n attributes: [\n {\n name: 'label',\n label: 'Shows under tab',\n description:\n \"The tab label this panel belongs to — type it exactly as it \" +\n 'appears in the Tabs list above (capitalisation is ignored).',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n },\n ],\n}\n\nconst tabPanel = (label: string, body: string) => ({\n $id: null,\n componentId: TAB_PANEL_ID,\n pluginId: BUNDLE_ID,\n props: { label },\n nodes: [\n {\n $id: null,\n componentId: 'muiTypography',\n pluginId: BUNDLE_ID,\n props: { variant: 'body2', children: body },\n },\n ],\n})\n\nexport const tabsPresets: Aglyn.PresetSchema[] = [\n {\n // Labels and panels ship already matched: the one place this element\n // can be misconfigured is never hit on the common path.\n $id: generatePresetId(TABS_ID),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Tabs',\n pluginId: BUNDLE_ID,\n description: 'Three tabs with matching panels, ready to edit',\n category: Aglyn.ComponentCategory.NAVIGATION,\n icon: tabsSchema.icon,\n data: {\n $id: null,\n componentId: TABS_ID,\n pluginId: BUNDLE_ID,\n props: { labels: 'Overview\\nDetails\\nFAQ' },\n nodes: [\n tabPanel('Overview', 'What this is, in a sentence or two.'),\n tabPanel('Details', 'The specifics that back up the overview.'),\n tabPanel('FAQ', 'The questions people actually ask.'),\n ],\n },\n },\n {\n $id: generatePresetId(TAB_PANEL_ID),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Tab Panel',\n pluginId: BUNDLE_ID,\n description: 'One more panel to add to an existing Tabs element',\n category: Aglyn.ComponentCategory.NAVIGATION,\n icon: tabPanelSchema.icon,\n data: tabPanel('', 'Name the tab this panel belongs to.'),\n },\n]\n\nexport default TabsElement\n"],"names":["Aglyn","mdiTab","mdiViewCarousel","AppLink","Box","MuiTab","MuiTabs","Typography","createContext","forwardRef","useContext","useState","BUNDLE_ID","dropClearedProps","generatePresetId","TABS_ID","TAB_PANEL_ID","TAB_LINK_SLOTS","tabLinkProp","position","parseLabels","value","String","split","map","label","trim","filter","Boolean","labelSlug","toLowerCase","replace","labelsMatch","a","b","openingTabIndex","labels","opensOn","linkIds","named","findIndex","index","landing","_label","TabsContext","undefined","TabsElement","rawProps","ref","parsed","props","ariaLabel","orientation","variant","centered","textColor","indicatorColor","ssrPanels","lazyPanels","children","rest","editorInert","suppressNavigation","useScreenLink","screens","ScreenLinkContext","slot","key","push","navMode","some","opening","active","setActive","opened","setOpened","first","Set","chosen","length","activeIndex","resolvedVariant","vertical","stripLabel","strip","onChange","_event","next","prev","has","add","component","slotProps","root","list","role","slug","id","aria-controls","href","resolveScreenHref","broken","isScreenLinkBroken","componentVariant","disabled","brokenScreenLinkProps","sx","BROKEN_SCREEN_LINK_SX","aria-selected","aria-current","tabIndex","Provider","activeLabel","showAll","display","Array","isArray","displayName","TabPanelElement","aglynDeferred","context","selected","visible","mounted","hidden","aria-labelledby","p","color","mb","py","STANDARD_ONLY","when","is","notMatch","atLeastLabels","count","isNotEmpty","item","separator","pattern","opensOnFieldProps","_props","field","formOptions","authored","getFieldState","getState","values","options","stored","input","option","ordinal","suffix","TAB_LINK_FIELDS","from","_unused","name","description","FieldComponentType","SCREEN_SELECT","condition","tabsSchema","$id","pluginId","category","ComponentCategory","NAVIGATION","icon","path","restrictChildren","LinealDirectiveFlag","LIMIT_TO","components","attributes","TEXTAREA","SELECT","resolveProps","clearable","SWITCH","TEXT_FIELD","tabPanelSchema","tabPanel","body","componentId","nodes","tabsPresets","type","NodeType","PRESET","data"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/constants/field-presets.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2022 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n AglynAttributeSchema,\n FieldComponentType,\n} from '@aglyn/aglyn'\n\n/**\n * Theme colour for Button and Screen Link.\n *\n * The `{ value: '', label: 'Default' }` option was DELETED (AGL-1453). It could\n * not persist — the attributes form strips `''` on change (AGL-1191) — so the\n * pick silently reverted, and it was a second name for a choice already on the\n * list: MUI's own default for both components is `primary`, offered below.\n *\n * Deliberately NOT replaced with a `'primary'` sentinel, which is where this\n * differs from the props that got one. \"Default\" means *unset*, and unset is\n * load-bearing: MUI reads a component's props through `useDefaultProps`, which\n * applies a host theme's `components.MuiButton.defaultProps.color` to\n * `undefined` ONLY. A sentinel would pin `primary` and bypass the host's own\n * default — the opposite of what an author asking for \"Default\" wants. Unset\n * stays expressible through the field's ✕, which persists `null`, and\n * `dropClearedProps` turns that back into `undefined` at the boundary.\n */\nexport const FIELD_COLOR: AglynAttributeSchema = {\n name: 'color',\n description:\n 'The color of the component. It supports those theme colors that make sense for this component.',\n component: FieldComponentType.SELECT,\n label: 'Theme color',\n options: [\n { value: 'inherit', label: 'Inherit' },\n { value: 'primary', label: 'Primary' },\n { value: 'secondary', label: 'Secondary' },\n { value: 'success', label: 'Success' },\n { value: 'error', label: 'Error' },\n { value: 'info', label: 'Info' },\n { value: 'warning', label: 'Warning' },\n ],\n}\n/**\n * App Bar theme colors. Unlike the base FIELD_COLOR (where \"Default\" means\n * \"unset — let the component decide\"), MUI AppBar's `color=\"default\"` is a\n * real value DISTINCT from its implicit default (`primary`), so the option\n * must persist. An empty-string option value never can: the attributes form\n * strips `''` on change (ddf's enhancedOnChange maps an emptied field to its\n * clearedValue, and final-form's default parse turns `''` into `undefined`),\n * so the prop key vanished before save and the pick silently reverted on\n * reload (AGL-1191). Persist the explicit `'default'` sentinel instead; an\n * author who wants \"unset\" clears the field with the ✕ affordance.\n */\nexport const FIELD_COLOR_ALT1: AglynAttributeSchema = {\n ...FIELD_COLOR,\n options: [\n { value: 'default', label: 'Default' },\n { value: 'inherit', label: 'Inherit' },\n { value: 'transparent', label: 'Transparent' },\n { value: 'primary', label: 'Primary' },\n { value: 'secondary', label: 'Secondary' },\n { value: 'tertiary', label: 'Tertiary' },\n ],\n}\nexport const FIELD_DISABLED: AglynAttributeSchema = {\n name: 'disabled',\n description: 'If true, the component is disabled.',\n component: FieldComponentType.SWITCH,\n label: 'Disabled?',\n}\nexport const FIELD_FULL_WIDTH: AglynAttributeSchema = {\n name: 'fullWidth',\n description:\n 'If true, the button will take up the full width of its container.',\n component: FieldComponentType.SWITCH,\n label: 'Full width?',\n}\nexport const FIELD_DISABLE_GUTTERS: AglynAttributeSchema = {\n name: 'disableGutters',\n description: 'If true, disables gutter padding.',\n component: FieldComponentType.SWITCH,\n label: 'Disable gutters?',\n}\n/**\n * Size for Button and Screen Link. Pagination replaces the option list.\n *\n * `{ value: '', label: 'Default' }` deleted for the same reason as\n * FIELD_COLOR's (AGL-1453): unpersistable, and a second name for `medium`,\n * which is MUI's own default and is already on the list.\n */\nexport const FIELD_SIZE: AglynAttributeSchema = {\n name: 'size',\n description:\n 'The size of the component. small is equivalent to the dense button styling.',\n component: FieldComponentType.SELECT,\n label: 'Size',\n options: [\n { value: 'inherit', label: 'Inherit' },\n { value: 'small', label: 'Small' },\n { value: 'medium', label: 'Medium' },\n { value: 'large', label: 'Large' },\n ],\n}\n/**\n * App Bar positioning.\n *\n * `{ value: '', label: 'Default' }` deleted (AGL-1453): unpersistable, and a\n * second name for `fixed`, MUI AppBar's own default, already on the list.\n */\nexport const FIELD_POSITION: AglynAttributeSchema = {\n name: 'position',\n description:\n 'The positioning type. The behavior of the different options is described in the MDN web docs. Note: sticky is not universally supported and will fall back to static when unavailable.',\n component: FieldComponentType.SELECT,\n label: 'Position',\n options: [\n { value: 'absolute', label: 'Absolute' },\n { value: 'fixed', label: 'Fixed' },\n { value: 'relative', label: 'Relative' },\n { value: 'static', label: 'Static' },\n { value: 'sticky', label: 'Sticky' },\n ],\n}\n/**\n * Text content of a text-capable component (`children` prop). Pair with the\n * `textEditable` schema flag so editor surfaces know the component renders\n * its children as editable text.\n */\nexport const FIELD_TEXT_CONTENT: AglynAttributeSchema = {\n name: 'children',\n description: 'The text content this element displays.',\n component: FieldComponentType.TEXTAREA,\n label: 'Text',\n}\n\n/**\n * Where a link opens, for the elements that render through `AppLink`.\n *\n * `'_self'` is a REAL SENTINEL, not a deletion, for the reason `renderAs`\n * carries one: the attributes form strips `''` before save (AGL-1191), so an\n * `{ value: '', label: 'Same tab' }` option could not persist and a link\n * switched to a new tab would have no route in this dropdown back. It is\n * safe to store because `linkTargetProps` resolves it to no attribute at\n * all, which is exactly what an unset target already renders.\n *\n * Deliberately no separate \"New window\" option. `target=\"_blank\"` asks for a\n * new browsing context and the browser — not the page — decides whether that\n * is a tab or a window, so a second label would be a second name for one\n * behavior. Authors who need a specific named window pick Custom and name it.\n */\nexport const FIELD_LINK_TARGET: AglynAttributeSchema = {\n name: 'target',\n description:\n 'Where this opens. Same tab keeps the visitor on the site with their ' +\n 'history intact, which is what internal navigation should do; New tab ' +\n 'suits a download or an outside site you want them to come back from.',\n component: FieldComponentType.SELECT,\n label: 'Open link in',\n options: [\n { value: '_self', label: 'Same tab' },\n { value: '_blank', label: 'New tab' },\n { value: 'custom', label: 'Custom window name' },\n ],\n}\n/**\n * The name behind FIELD_LINK_TARGET's Custom choice. Shown only for that\n * choice — on its own it is an advanced affordance, and offering a free-text\n * box beside the dropdown would invite `_blank` being typed into it.\n */\nexport const FIELD_LINK_TARGET_NAME: AglynAttributeSchema = {\n name: 'targetName',\n description:\n 'Name of the window to open in. Every link sharing a name reuses that ' +\n 'one window instead of opening another, which is how a set of links ' +\n 'can drive a single companion window.',\n component: FieldComponentType.TEXT_FIELD,\n label: 'Window name',\n condition: { when: 'target', is: 'custom' },\n}\n"],"names":["FieldComponentType","FIELD_COLOR","name","description","component","SELECT","label","options","value","FIELD_COLOR_ALT1","FIELD_DISABLED","SWITCH","FIELD_FULL_WIDTH","FIELD_DISABLE_GUTTERS","FIELD_SIZE","FIELD_POSITION","FIELD_TEXT_CONTENT","TEXTAREA","FIELD_LINK_TARGET","FIELD_LINK_TARGET_NAME","TEXT_FIELD","condition","when","is"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/constants/field-presets.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2022 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n AglynAttributeSchema,\n FieldComponentType,\n} from '@aglyn/aglyn'\n\n/**\n * Theme colour for Button and Screen Link.\n *\n * The `{ value: '', label: 'Default' }` option was DELETED (AGL-1453). It could\n * not persist — the attributes form strips `''` on change (AGL-1191) — so the\n * pick silently reverted, and it was a second name for a choice already on the\n * list: MUI's own default for both components is `primary`, offered below.\n *\n * Deliberately NOT replaced with a `'primary'` sentinel, which is where this\n * differs from the props that got one. \"Default\" means *unset*, and unset is\n * load-bearing: MUI reads a component's props through `useDefaultProps`, which\n * applies a host theme's `components.MuiButton.defaultProps.color` to\n * `undefined` ONLY. A sentinel would pin `primary` and bypass the host's own\n * default — the opposite of what an author asking for \"Default\" wants. Unset\n * stays expressible through the field's ✕, which persists `null`, and\n * `dropClearedProps` turns that back into `undefined` at the boundary.\n */\nexport const FIELD_COLOR: AglynAttributeSchema = {\n name: 'color',\n description:\n 'The color of the component. It supports those theme colors that make sense for this component.',\n component: FieldComponentType.SELECT,\n label: 'Theme color',\n options: [\n { value: 'inherit', label: 'Inherit' },\n { value: 'primary', label: 'Primary' },\n { value: 'secondary', label: 'Secondary' },\n { value: 'tertiary', label: 'Tertiary' },\n { value: 'success', label: 'Success' },\n { value: 'error', label: 'Error' },\n { value: 'info', label: 'Info' },\n { value: 'warning', label: 'Warning' },\n ],\n}\n/**\n * App Bar theme colors. Unlike the base FIELD_COLOR (where \"Default\" means\n * \"unset — let the component decide\"), MUI AppBar's `color=\"default\"` is a\n * real value DISTINCT from its implicit default (`primary`), so the option\n * must persist. An empty-string option value never can: the attributes form\n * strips `''` on change (ddf's enhancedOnChange maps an emptied field to its\n * clearedValue, and final-form's default parse turns `''` into `undefined`),\n * so the prop key vanished before save and the pick silently reverted on\n * reload (AGL-1191). Persist the explicit `'default'` sentinel instead; an\n * author who wants \"unset\" clears the field with the ✕ affordance.\n */\nexport const FIELD_COLOR_ALT1: AglynAttributeSchema = {\n ...FIELD_COLOR,\n options: [\n { value: 'default', label: 'Default' },\n { value: 'inherit', label: 'Inherit' },\n { value: 'transparent', label: 'Transparent' },\n { value: 'primary', label: 'Primary' },\n { value: 'secondary', label: 'Secondary' },\n { value: 'tertiary', label: 'Tertiary' },\n ],\n}\nexport const FIELD_DISABLED: AglynAttributeSchema = {\n name: 'disabled',\n description: 'If true, the component is disabled.',\n component: FieldComponentType.SWITCH,\n label: 'Disabled?',\n}\nexport const FIELD_FULL_WIDTH: AglynAttributeSchema = {\n name: 'fullWidth',\n description:\n 'If true, the button will take up the full width of its container.',\n component: FieldComponentType.SWITCH,\n label: 'Full width?',\n}\nexport const FIELD_DISABLE_GUTTERS: AglynAttributeSchema = {\n name: 'disableGutters',\n description: 'If true, disables gutter padding.',\n component: FieldComponentType.SWITCH,\n label: 'Disable gutters?',\n}\n/**\n * Size for Button and Screen Link. Pagination replaces the option list.\n *\n * `{ value: '', label: 'Default' }` deleted for the same reason as\n * FIELD_COLOR's (AGL-1453): unpersistable, and a second name for `medium`,\n * which is MUI's own default and is already on the list.\n */\nexport const FIELD_SIZE: AglynAttributeSchema = {\n name: 'size',\n description:\n 'The size of the component. small is equivalent to the dense button styling.',\n component: FieldComponentType.SELECT,\n label: 'Size',\n options: [\n { value: 'inherit', label: 'Inherit' },\n { value: 'small', label: 'Small' },\n { value: 'medium', label: 'Medium' },\n { value: 'large', label: 'Large' },\n ],\n}\n/**\n * App Bar positioning.\n *\n * `{ value: '', label: 'Default' }` deleted (AGL-1453): unpersistable, and a\n * second name for `fixed`, MUI AppBar's own default, already on the list.\n */\nexport const FIELD_POSITION: AglynAttributeSchema = {\n name: 'position',\n description:\n 'The positioning type. The behavior of the different options is described in the MDN web docs. Note: sticky is not universally supported and will fall back to static when unavailable.',\n component: FieldComponentType.SELECT,\n label: 'Position',\n options: [\n { value: 'absolute', label: 'Absolute' },\n { value: 'fixed', label: 'Fixed' },\n { value: 'relative', label: 'Relative' },\n { value: 'static', label: 'Static' },\n { value: 'sticky', label: 'Sticky' },\n ],\n}\n/**\n * Text content of a text-capable component (`children` prop). Pair with the\n * `textEditable` schema flag so editor surfaces know the component renders\n * its children as editable text.\n */\nexport const FIELD_TEXT_CONTENT: AglynAttributeSchema = {\n name: 'children',\n description: 'The text content this element displays.',\n component: FieldComponentType.TEXTAREA,\n label: 'Text',\n}\n\n/**\n * Where a link opens, for the elements that render through `AppLink`.\n *\n * `'_self'` is a REAL SENTINEL, not a deletion, for the reason `renderAs`\n * carries one: the attributes form strips `''` before save (AGL-1191), so an\n * `{ value: '', label: 'Same tab' }` option could not persist and a link\n * switched to a new tab would have no route in this dropdown back. It is\n * safe to store because `linkTargetProps` resolves it to no attribute at\n * all, which is exactly what an unset target already renders.\n *\n * Deliberately no separate \"New window\" option. `target=\"_blank\"` asks for a\n * new browsing context and the browser — not the page — decides whether that\n * is a tab or a window, so a second label would be a second name for one\n * behavior. Authors who need a specific named window pick Custom and name it.\n */\nexport const FIELD_LINK_TARGET: AglynAttributeSchema = {\n name: 'target',\n description:\n 'Where this opens. Same tab keeps the visitor on the site with their ' +\n 'history intact, which is what internal navigation should do; New tab ' +\n 'suits a download or an outside site you want them to come back from.',\n component: FieldComponentType.SELECT,\n label: 'Open link in',\n options: [\n { value: '_self', label: 'Same tab' },\n { value: '_blank', label: 'New tab' },\n { value: 'custom', label: 'Custom window name' },\n ],\n}\n/**\n * The name behind FIELD_LINK_TARGET's Custom choice. Shown only for that\n * choice — on its own it is an advanced affordance, and offering a free-text\n * box beside the dropdown would invite `_blank` being typed into it.\n */\nexport const FIELD_LINK_TARGET_NAME: AglynAttributeSchema = {\n name: 'targetName',\n description:\n 'Name of the window to open in. Every link sharing a name reuses that ' +\n 'one window instead of opening another, which is how a set of links ' +\n 'can drive a single companion window.',\n component: FieldComponentType.TEXT_FIELD,\n label: 'Window name',\n condition: { when: 'target', is: 'custom' },\n}\n"],"names":["FieldComponentType","FIELD_COLOR","name","description","component","SELECT","label","options","value","FIELD_COLOR_ALT1","FIELD_DISABLED","SWITCH","FIELD_FULL_WIDTH","FIELD_DISABLE_GUTTERS","FIELD_SIZE","FIELD_POSITION","FIELD_TEXT_CONTENT","TEXTAREA","FIELD_LINK_TARGET","FIELD_LINK_TARGET_NAME","TEXT_FIELD","condition","when","is"],"mappings":"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"}
|
|
@@ -110,8 +110,6 @@ export declare const languageSwitcher: () => Promise<typeof import("./components
|
|
|
110
110
|
export declare const reusableInstance: () => Promise<typeof import("./components/reusable-instance")>;
|
|
111
111
|
export declare const navMenu: () => Promise<typeof import("./components/nav-menu")>;
|
|
112
112
|
export declare const drawer: () => Promise<typeof import("./components/drawer")>;
|
|
113
|
-
export declare const functionWidget: () => Promise<typeof import("./components/function-widget")>;
|
|
114
|
-
export declare const functionScope: () => Promise<typeof import("./components/function-scope")>;
|
|
115
113
|
export declare const product: () => Promise<typeof import("./components/product")>;
|
|
116
114
|
export declare const plugin: () => Promise<typeof import("./components/plugin")>;
|
|
117
115
|
export declare const customHtml: () => Promise<typeof import("./components/custom-html")>;
|
package/src/lib/element-tier.js
CHANGED
|
@@ -110,8 +110,6 @@ export const languageSwitcher = ()=>import("./components/language-switcher.js");
|
|
|
110
110
|
export const reusableInstance = ()=>import("./components/reusable-instance.js");
|
|
111
111
|
export const navMenu = ()=>import("./components/nav-menu.js");
|
|
112
112
|
export const drawer = ()=>import("./components/drawer.js");
|
|
113
|
-
export const functionWidget = ()=>import("./components/function-widget.js");
|
|
114
|
-
export const functionScope = ()=>import("./components/function-scope.js");
|
|
115
113
|
export const product = ()=>import("./components/product.js");
|
|
116
114
|
export const plugin = ()=>import("./components/plugin.js");
|
|
117
115
|
export const customHtml = ()=>import("./components/custom-html.js");
|