@aglyn/plugins-mui 1.0.0-beta.250 → 1.0.0-beta.253
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
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.253",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"homepage": "https://aglyn.com",
|
|
6
6
|
"repository": {
|
|
@@ -25,12 +25,12 @@
|
|
|
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.253",
|
|
29
|
+
"@aglyn/shared-data-enums": "1.0.0-beta.253",
|
|
30
|
+
"@aglyn/shared-data-mdi": "1.0.0-beta.253",
|
|
31
|
+
"@aglyn/shared-ui-jsx": "1.0.0-beta.253",
|
|
32
|
+
"@aglyn/shared-ui-theme": "1.0.0-beta.253",
|
|
33
|
+
"@aglyn/shared-util-vendor": "1.0.0-beta.253",
|
|
34
34
|
"@swc/helpers": "0.5.23",
|
|
35
35
|
"mobx": "^7.0.5",
|
|
36
36
|
"mobx-react-lite": "^5.1.0"
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
import * as Aglyn from '@aglyn/aglyn';
|
|
18
18
|
import { type SpanBreakpoint } from '@aglyn/shared-data-enums/breakpoint-span';
|
|
19
|
+
import type { Breakpoints, SxProps, Theme } from '@mui/material/styles';
|
|
19
20
|
import { type ReactNode } from 'react';
|
|
20
21
|
export declare const ID: Aglyn.ComponentId;
|
|
21
22
|
/**
|
|
@@ -52,8 +53,32 @@ export interface GridElementProps {
|
|
|
52
53
|
direction?: 'row' | 'row-reverse';
|
|
53
54
|
/** `flex-wrap` for the container; MUI's default is `wrap`. */
|
|
54
55
|
wrap?: 'nowrap' | 'wrap' | 'wrap-reverse';
|
|
56
|
+
/**
|
|
57
|
+
* A cell that ends up alone on the last row spans the whole row instead
|
|
58
|
+
* of sitting in its first column. Read per breakpoint from the cell's own
|
|
59
|
+
* Span and its row's Columns, so a row of thirds that leaves one cell over
|
|
60
|
+
* widens it from the breakpoint the thirds start at, and a row that comes
|
|
61
|
+
* out even leaves every cell as it is. Set it on every cell of a row whose
|
|
62
|
+
* cells come and go (a hidden cell is not on the page), and whichever one
|
|
63
|
+
* is last takes it.
|
|
64
|
+
*/
|
|
65
|
+
fillLastRow?: boolean;
|
|
66
|
+
sx?: SxProps<Theme>;
|
|
55
67
|
children?: ReactNode;
|
|
56
68
|
}
|
|
69
|
+
type SpanBreakpointStyles = Record<string, Record<string, Record<string, string>>>;
|
|
70
|
+
/**
|
|
71
|
+
* The styles that widen a lone last cell to the full row (`fillLastRow`).
|
|
72
|
+
*
|
|
73
|
+
* At each breakpoint the cell's span gives how many cells share a row. A
|
|
74
|
+
* cell that is the last child AND the first of its row — `nth-child(kn+1)`
|
|
75
|
+
* for `k` per row — is alone there. Each breakpoint range gets its own
|
|
76
|
+
* bounded media query, so "two to a row" from `sm` stops at the `md` where
|
|
77
|
+
* three to a row starts, rather than still matching an odd cell that has
|
|
78
|
+
* company in a row of three. One to a row, `auto` and `grow` add nothing:
|
|
79
|
+
* the cell is already as wide as it is going to be.
|
|
80
|
+
*/
|
|
81
|
+
export declare function loneLastCellStyles(size: ReturnType<typeof parseSpan>, columns: number, breakpoints: Pick<Breakpoints, 'keys' | 'up' | 'between'>): SpanBreakpointStyles;
|
|
57
82
|
/**
|
|
58
83
|
* Parses the authored span syntax into what MUI v6+ Grid expects.
|
|
59
84
|
*
|
|
@@ -27,7 +27,7 @@ import { mdiViewGrid, mdiViewGridOutline } from "@aglyn/shared-data-mdi";
|
|
|
27
27
|
// library; they live here, one file away from the barrel.
|
|
28
28
|
import { parseBreakpointSpan, SPAN_BREAKPOINTS } from "@aglyn/shared-data-enums/breakpoint-span";
|
|
29
29
|
import MuiGrid from "@mui/material/Grid";
|
|
30
|
-
import { forwardRef } from "react";
|
|
30
|
+
import { createContext, forwardRef, useContext } from "react";
|
|
31
31
|
import { applySemanticElement, semanticElementAttribute, semanticElementLabelAttribute } from "../utils/element-picker.js";
|
|
32
32
|
import { BUNDLE_ID } from "../constants/bundle-common.js";
|
|
33
33
|
import { colorSchemeAttribute } from "../utils/color-scheme-attribute.js";
|
|
@@ -42,6 +42,52 @@ export const ID = 'muiGrid';
|
|
|
42
42
|
* (AGL-2486): the attributes panel's breakpoint row and this parser have to
|
|
43
43
|
* agree on the list, and two copies is how they stop agreeing.
|
|
44
44
|
*/ export const BREAKPOINTS = SPAN_BREAKPOINTS;
|
|
45
|
+
/** MUI's default column count, which a row with no Columns of its own uses. */ const DEFAULT_COLUMNS = 12;
|
|
46
|
+
/**
|
|
47
|
+
* The column count of the row a cell sits in. MUI keeps it in a CSS
|
|
48
|
+
* variable, which a selector cannot count with, so the row hands it down.
|
|
49
|
+
*/ const GridColumnsContext = /*#__PURE__*/ createContext(DEFAULT_COLUMNS);
|
|
50
|
+
/**
|
|
51
|
+
* The styles that widen a lone last cell to the full row (`fillLastRow`).
|
|
52
|
+
*
|
|
53
|
+
* At each breakpoint the cell's span gives how many cells share a row. A
|
|
54
|
+
* cell that is the last child AND the first of its row — `nth-child(kn+1)`
|
|
55
|
+
* for `k` per row — is alone there. Each breakpoint range gets its own
|
|
56
|
+
* bounded media query, so "two to a row" from `sm` stops at the `md` where
|
|
57
|
+
* three to a row starts, rather than still matching an odd cell that has
|
|
58
|
+
* company in a row of three. One to a row, `auto` and `grow` add nothing:
|
|
59
|
+
* the cell is already as wide as it is going to be.
|
|
60
|
+
*/ export function loneLastCellStyles(size, columns, breakpoints) {
|
|
61
|
+
if (size === undefined) return {};
|
|
62
|
+
const keys = breakpoints.keys;
|
|
63
|
+
const perRow = [];
|
|
64
|
+
let current;
|
|
65
|
+
for (const key of keys){
|
|
66
|
+
if (typeof size === 'object') {
|
|
67
|
+
if (size[key] !== undefined) current = size[key];
|
|
68
|
+
} else {
|
|
69
|
+
current = size;
|
|
70
|
+
}
|
|
71
|
+
perRow.push(typeof current === 'number' && current > 0 ? Math.floor(columns / Math.min(current, columns)) : undefined);
|
|
72
|
+
}
|
|
73
|
+
const styles = {};
|
|
74
|
+
let start = 0;
|
|
75
|
+
while(start < keys.length){
|
|
76
|
+
let end = start;
|
|
77
|
+
while(end + 1 < keys.length && perRow[end + 1] === perRow[start])end += 1;
|
|
78
|
+
const count = perRow[start];
|
|
79
|
+
if (count !== undefined && count > 1) {
|
|
80
|
+
const query = end + 1 < keys.length ? breakpoints.between(keys[start], keys[end + 1]) : breakpoints.up(keys[start]);
|
|
81
|
+
styles[query] = {
|
|
82
|
+
[`&:last-child:nth-child(${count}n + 1)`]: {
|
|
83
|
+
width: '100%'
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
start = end + 1;
|
|
88
|
+
}
|
|
89
|
+
return styles;
|
|
90
|
+
}
|
|
45
91
|
/**
|
|
46
92
|
* Parses the authored span syntax into what MUI v6+ Grid expects.
|
|
47
93
|
*
|
|
@@ -95,7 +141,7 @@ export const ID = 'muiGrid';
|
|
|
95
141
|
* One element covers both roles, matching MUI v6+: switch **Container**
|
|
96
142
|
* on for the row, leave it off and set a **Span** for each cell.
|
|
97
143
|
*/ const GridElement = /*#__PURE__*/ forwardRef((props, ref)=>{
|
|
98
|
-
const { container, size, offset, spacing, rowSpacing, columnSpacing, columns, direction, wrap, children } = props, rest = _object_without_properties_loose(props, [
|
|
144
|
+
const { container, size, offset, spacing, rowSpacing, columnSpacing, columns, direction, wrap, fillLastRow, sx, children } = props, rest = _object_without_properties_loose(props, [
|
|
99
145
|
"container",
|
|
100
146
|
"size",
|
|
101
147
|
"offset",
|
|
@@ -105,25 +151,41 @@ export const ID = 'muiGrid';
|
|
|
105
151
|
"columns",
|
|
106
152
|
"direction",
|
|
107
153
|
"wrap",
|
|
154
|
+
"fillLastRow",
|
|
155
|
+
"sx",
|
|
108
156
|
"children"
|
|
109
157
|
]);
|
|
110
|
-
|
|
158
|
+
const parentColumns = useContext(GridColumnsContext);
|
|
159
|
+
const span = parseSpan(size);
|
|
160
|
+
const ownColumns = toNumber(columns);
|
|
161
|
+
const nodeSx = Array.isArray(sx) ? sx : sx ? [
|
|
162
|
+
sx
|
|
163
|
+
] : [];
|
|
164
|
+
const grid = /*#__PURE__*/ _jsx(MuiGrid, _extends({
|
|
111
165
|
ref: ref,
|
|
112
166
|
container: !!container,
|
|
113
|
-
size:
|
|
167
|
+
size: span,
|
|
114
168
|
offset: parseOffset(offset),
|
|
115
169
|
// Spacing props only apply to containers; MUI ignores them on
|
|
116
170
|
// items, so no need to strip them here.
|
|
117
171
|
spacing: toNumber(spacing),
|
|
118
172
|
rowSpacing: toNumber(rowSpacing),
|
|
119
173
|
columnSpacing: toNumber(columnSpacing),
|
|
120
|
-
columns:
|
|
174
|
+
columns: ownColumns
|
|
121
175
|
}, dropClearedProps({
|
|
122
176
|
direction,
|
|
123
177
|
wrap
|
|
124
178
|
}), applySemanticElement(dropClearedProps(rest)), {
|
|
179
|
+
sx: [
|
|
180
|
+
fillLastRow && !container ? (theme)=>loneLastCellStyles(span, parentColumns, theme.breakpoints) : false,
|
|
181
|
+
...nodeSx
|
|
182
|
+
],
|
|
125
183
|
children: children
|
|
126
184
|
}));
|
|
185
|
+
return container ? /*#__PURE__*/ _jsx(GridColumnsContext.Provider, {
|
|
186
|
+
value: ownColumns != null ? ownColumns : DEFAULT_COLUMNS,
|
|
187
|
+
children: grid
|
|
188
|
+
}) : grid;
|
|
127
189
|
});
|
|
128
190
|
GridElement.displayName = 'AglynGrid';
|
|
129
191
|
/** Container-only props: MUI ignores these on an item. */ const CONTAINER_ONLY = {
|
|
@@ -186,6 +248,13 @@ export const schema = {
|
|
|
186
248
|
minSpan: 0,
|
|
187
249
|
condition: ITEM_ONLY
|
|
188
250
|
},
|
|
251
|
+
{
|
|
252
|
+
name: 'fillLastRow',
|
|
253
|
+
label: 'Fill the row when alone?',
|
|
254
|
+
description: 'If true, this cell spans the whole row whenever it ends up alone on ' + 'the last row, at every screen size. Turn it on for every cell of a ' + 'row whose cells can be hidden, so whichever cell is last fills in.',
|
|
255
|
+
component: Aglyn.FieldComponentType.SWITCH,
|
|
256
|
+
condition: ITEM_ONLY
|
|
257
|
+
},
|
|
189
258
|
{
|
|
190
259
|
name: 'spacing',
|
|
191
260
|
label: 'Spacing',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/components/grid.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 { mdiViewGrid, mdiViewGridOutline } from '@aglyn/shared-data-mdi'\n// Deep import, NOT the barrel (AGL-1151): `@aglyn/shared-data-enums` re-exports\n// `firebase-auth`, whose `AuthErrorCodes` is a VALUE import of `firebase/auth`.\n// This bundle is `alwaysOn`, so the barrel put the whole Firebase auth client\n// into the chunk every published tenant page loads — a database/identity SDK\n// shipped and evaluated to render static HTML that authenticates nobody. Three\n// breakpoint symbols are the entire reason this module reaches for that\n// library; they live here, one file away from the barrel.\nimport {\n parseBreakpointSpan,\n SPAN_BREAKPOINTS,\n type SpanBreakpoint,\n} from '@aglyn/shared-data-enums/breakpoint-span'\nimport MuiGrid from '@mui/material/Grid'\nimport { forwardRef, type ReactNode } from 'react'\nimport {\n applySemanticElement,\n semanticElementAttribute,\n semanticElementLabelAttribute,\n} from '../utils/element-picker'\nimport { BUNDLE_ID } from '../constants/bundle-common'\nimport { colorSchemeAttribute } from '../utils/color-scheme-attribute'\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 = 'muiGrid'\n\n/**\n * Breakpoint keys MUI's responsive `size`/`offset` objects accept.\n *\n * Re-exported from `@aglyn/shared-data-enums` rather than declared twice\n * (AGL-2486): the attributes panel's breakpoint row and this parser have to\n * agree on the list, and two copies is how they stop agreeing.\n */\nexport const BREAKPOINTS = SPAN_BREAKPOINTS\nexport type Breakpoint = SpanBreakpoint\n\nexport interface GridElementProps {\n /** Flex container behavior; items are its direct Grid children. */\n container?: boolean\n /**\n * Column span. Persisted as one string: a bare span (`6`), the keywords\n * `auto`/`grow`, or per-breakpoint pairs (`xs:12 md:6`). Authored through\n * the breakpoint row in the attributes panel (AGL-2486); the stored\n * format is unchanged from when it was a text box.\n */\n size?: string | number\n /** Empty columns before the item; same syntax as `size`, minus `grow`. */\n offset?: string | number\n spacing?: number | string\n rowSpacing?: number | string\n columnSpacing?: number | string\n /** Total columns in the container; MUI's default is 12. */\n columns?: number | string\n /**\n * Container flow. MUI supports `row`/`row-reverse` ONLY — Grid subdivides\n * a layout into columns, and `column`/`column-reverse` are documented as\n * unsupported (use a Stack for a vertical layout).\n */\n direction?: 'row' | 'row-reverse'\n /** `flex-wrap` for the container; MUI's default is `wrap`. */\n wrap?: 'nowrap' | 'wrap' | 'wrap-reverse'\n children?: ReactNode\n}\n\n/**\n * Parses the authored span syntax into what MUI v6+ Grid expects.\n *\n * MUI dropped the `item` prop and the per-breakpoint `xs=`/`md=` props in\n * v6; v9 (installed here) takes a single `size` that is either a value or\n * a `{ xs, md, … }` object. One STORED string covers both, and this parser\n * owns the translation:\n *\n * `6` → 6\n * `auto` → 'auto'\n * `grow` → 'grow'\n * `xs:12 md:6` → { xs: 12, md: 6 }\n *\n * Anything unparseable returns `undefined` rather than a partial object:\n * a half-applied breakpoint map is a layout that silently differs from\n * what the author typed.\n */\nexport function parseSpan(\n value: unknown,\n): number | 'auto' | 'grow' | Record<string, number | 'auto' | 'grow'> | undefined {\n // The reading itself is `parseBreakpointSpan` in `@aglyn/shared-data-enums`\n // (AGL-2486), shared with the attributes panel's breakpoint row so the\n // editor and the renderer cannot disagree about a stored string. This\n // function keeps its own signature and its \"unparseable means unset\"\n // contract: `raw` is what the editor hands back untouched, and what MUI\n // must never receive.\n const span = parseBreakpointSpan(value as string | number)\n if (span.raw !== undefined) return undefined\n if (span.base !== undefined) return span.base\n return span.values && Object.keys(span.values).length\n ? (span.values as Record<string, number | 'auto' | 'grow'>)\n : undefined\n}\n\n/**\n * Same syntax as `parseSpan`, minus `grow`.\n *\n * MUI's `GridOffset` is `'auto' | number` only — a `grow` offset is not\n * a wider gap, it is a value the layout cannot use, so it is dropped\n * here rather than passed through to be ignored.\n */\nexport function parseOffset(value: unknown) {\n const parsed = parseSpan(value)\n if (parsed === 'grow') return undefined\n if (parsed && typeof parsed === 'object') {\n const kept = Object.fromEntries(\n Object.entries(parsed).filter(([, span]) => span !== 'grow'),\n )\n return Object.keys(kept).length\n ? (kept as Record<string, number | 'auto'>)\n : undefined\n }\n return parsed as number | 'auto' | undefined\n}\n\n/** Spacing/columns arrive as strings from number fields; MUI wants numbers. */\nfunction toNumber(value: unknown): number | undefined {\n if (value == null || value === '') return undefined\n const parsed = Number(value)\n return Number.isFinite(parsed) ? parsed : undefined\n}\n\n/**\n * Responsive 12-column grid (https://mui.com/material-ui/react-grid/).\n * One element covers both roles, matching MUI v6+: switch **Container**\n * on for the row, leave it off and set a **Span** for each cell.\n */\nconst GridElement = forwardRef<HTMLDivElement, GridElementProps>(\n (props, ref) => {\n const {\n container,\n size,\n offset,\n spacing,\n rowSpacing,\n columnSpacing,\n columns,\n direction,\n wrap,\n children,\n ...rest\n } = props\n return (\n <MuiGrid\n ref={ref}\n container={!!container}\n size={parseSpan(size)}\n offset={parseOffset(offset)}\n // Spacing props only apply to containers; MUI ignores them on\n // items, so no need to strip them here.\n spacing={toNumber(spacing)}\n rowSpacing={toNumber(rowSpacing)}\n columnSpacing={toNumber(columnSpacing)}\n columns={toNumber(columns)}\n // A CLEARED select persists as `null`, and MUI resolves both of these\n // as responsive values — `null.xs` throws during SSR and 500s the\n // published page (the AGL-1226 shape). `undefined` is what \"cleared\"\n // has to mean by the time it reaches MUI.\n {...dropClearedProps({ direction, wrap })}\n {...applySemanticElement(dropClearedProps(rest) as Record<string, unknown>)}\n >\n {children}\n </MuiGrid>\n )\n },\n)\nGridElement.displayName = 'AglynGrid'\n\n/** Container-only props: MUI ignores these on an item. */\nconst CONTAINER_ONLY = { when: 'container', is: true }\n/** Item-only props: a container spans its parent, not a column count. */\nconst ITEM_ONLY = { when: 'container', is: true, notMatch: true }\n\nconst SPAN_HELP =\n 'How many columns this cell takes. Set **All** for every screen size, or ' +\n 'give individual breakpoints a value — `xs` applies from the smallest ' +\n 'screens up and each larger breakpoint overrides it. `auto` fits the ' +\n 'content, `grow` takes the remaining space.'\n\nexport const schema: Aglyn.ComponentSchema<GridElementProps> = {\n $id: ID,\n pluginId: BUNDLE_ID,\n displayName: 'Grid',\n // Static, and its children sit directly in its root: a subtree it heads\n // keeps its server HTML until the visitor nears it (AGL-3581).\n flags: {\n lazyHydration: Aglyn.FEATURE_FLAG.ENABLED,\n childrenInRoot: Aglyn.FEATURE_FLAG.ENABLED,\n },\n description:\n 'Responsive 12-column layout. Turn on Container for the row; give ' +\n 'each cell a Span.',\n category: Aglyn.ComponentCategory.LAYOUT,\n icon: { path: mdiViewGrid.path, sx: { color: '#2196f3' } },\n attributes: [\n semanticElementAttribute('this grid'),\n semanticElementLabelAttribute(),\n {\n name: 'container',\n label: 'Container?',\n description:\n 'If true, this grid lays its direct Grid children out in columns. ' +\n 'Leave it off for a cell inside another grid.',\n component: Aglyn.FieldComponentType.SWITCH,\n },\n {\n name: 'size',\n label: 'Span',\n description: SPAN_HELP,\n // A row of breakpoint controls rather than a text box (AGL-2486). The\n // STORED value is the same string it always was; only the way it is\n // authored changed. `xs:12 md:2` was a developer syntax documented\n // nowhere but this tooltip, so the responsive capability was there and\n // effectively unreachable.\n component: Aglyn.FieldComponentType.BREAKPOINT_SPAN,\n condition: ITEM_ONLY,\n },\n {\n name: 'offset',\n label: 'Offset',\n description:\n 'Empty columns before this cell. `auto` pushes the cell to the ' +\n 'right; `grow` is a span keyword and not an offset, so it is not ' +\n 'offered here.',\n component: Aglyn.FieldComponentType.BREAKPOINT_SPAN,\n // MUI's GridOffset is `'auto' | number`: a zero offset is a real\n // choice, and `grow` is not one at all.\n allowGrow: false,\n minSpan: 0,\n condition: ITEM_ONLY,\n },\n {\n name: 'spacing',\n label: 'Spacing',\n description:\n 'Gap between cells, in theme spacing units (1 = 8px by default).',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n type: 'number',\n condition: CONTAINER_ONLY,\n },\n {\n name: 'rowSpacing',\n label: 'Row spacing',\n description: 'Vertical gap only; overrides Spacing.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n type: 'number',\n condition: CONTAINER_ONLY,\n },\n {\n name: 'columnSpacing',\n label: 'Column spacing',\n description: 'Horizontal gap only; overrides Spacing.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n type: 'number',\n condition: CONTAINER_ONLY,\n },\n {\n name: 'columns',\n label: 'Columns',\n description: 'Total columns the row is divided into. Default 12.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n type: 'number',\n condition: CONTAINER_ONLY,\n },\n {\n name: 'direction',\n label: 'Direction',\n // The option that is NOT offered is the point of this field. MUI's own\n // API doc: \"Only `row` and `row-reverse` are supported. `column` and\n // `column-reverse` are not supported, because the Grid component is\n // designed to subdivide layouts into columns, not rows.\" Offering them\n // would be a control that silently does nothing.\n description:\n 'Sets the `flex-direction` for the row. Only Row and Row Reversed ' +\n 'are supported — Grid divides a layout into columns, so a column ' +\n 'direction does nothing. Use a Stack for a vertical layout.',\n component: Aglyn.FieldComponentType.SELECT,\n options: [\n { value: 'row', label: 'Row' },\n { value: 'row-reverse', label: 'Row Reversed' },\n ],\n condition: CONTAINER_ONLY,\n },\n {\n name: 'wrap',\n label: 'Wrap',\n description:\n 'Whether cells that do not fit move onto a new line. Default Wrap; ' +\n 'No Wrap keeps every cell on one line and lets them shrink instead.',\n component: Aglyn.FieldComponentType.SELECT,\n options: [\n { value: 'wrap', label: 'Wrap' },\n { value: 'nowrap', label: 'No Wrap' },\n { value: 'wrap-reverse', label: 'Wrap Reversed' },\n ],\n condition: CONTAINER_ONLY,\n },\n colorSchemeAttribute(),\n ],\n}\n\nconst cell = (size: string, text: string) => ({\n $id: null,\n componentId: ID,\n pluginId: BUNDLE_ID,\n props: { size },\n nodes: [\n {\n $id: null,\n componentId: 'muiTypography',\n pluginId: BUNDLE_ID,\n props: { variant: 'body2', children: text },\n },\n ],\n})\n\nexport const presets: Aglyn.PresetSchema[] = [\n {\n // Ships as a working responsive row, not a bare container: an empty\n // grid renders as nothing at all on the canvas.\n $id: generatePresetId(ID),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Grid',\n pluginId: BUNDLE_ID,\n description: 'Responsive row — three columns that stack on mobile',\n category: Aglyn.ComponentCategory.LAYOUT,\n icon: schema.icon,\n data: {\n $id: null,\n componentId: ID,\n pluginId: BUNDLE_ID,\n props: { container: true, spacing: 2 },\n nodes: [\n cell('xs:12 md:4', 'Column one'),\n cell('xs:12 md:4', 'Column two'),\n cell('xs:12 md:4', 'Column three'),\n ],\n },\n },\n {\n $id: generatePresetId(ID, 'cell'),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Grid Cell',\n pluginId: BUNDLE_ID,\n description: 'A single cell to add to an existing grid row',\n category: Aglyn.ComponentCategory.LAYOUT,\n icon: { path: mdiViewGridOutline.path, sx: { color: '#2196f3' } },\n data: cell('xs:12 md:6', 'Cell'),\n },\n]\n\nexport default GridElement\n"],"names":["Aglyn","mdiViewGrid","mdiViewGridOutline","parseBreakpointSpan","SPAN_BREAKPOINTS","MuiGrid","forwardRef","applySemanticElement","semanticElementAttribute","semanticElementLabelAttribute","BUNDLE_ID","colorSchemeAttribute","dropClearedProps","generatePresetId","ID","BREAKPOINTS","parseSpan","value","span","raw","undefined","base","values","Object","keys","length","parseOffset","parsed","kept","fromEntries","entries","filter","toNumber","Number","isFinite","GridElement","props","ref","container","size","offset","spacing","rowSpacing","columnSpacing","columns","direction","wrap","children","rest","displayName","CONTAINER_ONLY","when","is","ITEM_ONLY","notMatch","SPAN_HELP","schema","$id","pluginId","flags","lazyHydration","FEATURE_FLAG","ENABLED","childrenInRoot","description","category","ComponentCategory","LAYOUT","icon","path","sx","color","attributes","name","label","component","FieldComponentType","SWITCH","BREAKPOINT_SPAN","condition","allowGrow","minSpan","TEXT_FIELD","type","SELECT","options","cell","text","componentId","nodes","variant","presets","NodeType","PRESET","data"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/components/grid.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 { mdiViewGrid, mdiViewGridOutline } from '@aglyn/shared-data-mdi'\n// Deep import, NOT the barrel (AGL-1151): `@aglyn/shared-data-enums` re-exports\n// `firebase-auth`, whose `AuthErrorCodes` is a VALUE import of `firebase/auth`.\n// This bundle is `alwaysOn`, so the barrel put the whole Firebase auth client\n// into the chunk every published tenant page loads — a database/identity SDK\n// shipped and evaluated to render static HTML that authenticates nobody. Three\n// breakpoint symbols are the entire reason this module reaches for that\n// library; they live here, one file away from the barrel.\nimport {\n parseBreakpointSpan,\n SPAN_BREAKPOINTS,\n type SpanBreakpoint,\n} from '@aglyn/shared-data-enums/breakpoint-span'\nimport MuiGrid from '@mui/material/Grid'\nimport type { Breakpoints, SxProps, Theme } from '@mui/material/styles'\nimport { createContext, forwardRef, useContext, type ReactNode } from 'react'\nimport {\n applySemanticElement,\n semanticElementAttribute,\n semanticElementLabelAttribute,\n} from '../utils/element-picker'\nimport { BUNDLE_ID } from '../constants/bundle-common'\nimport { colorSchemeAttribute } from '../utils/color-scheme-attribute'\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 = 'muiGrid'\n\n/**\n * Breakpoint keys MUI's responsive `size`/`offset` objects accept.\n *\n * Re-exported from `@aglyn/shared-data-enums` rather than declared twice\n * (AGL-2486): the attributes panel's breakpoint row and this parser have to\n * agree on the list, and two copies is how they stop agreeing.\n */\nexport const BREAKPOINTS = SPAN_BREAKPOINTS\nexport type Breakpoint = SpanBreakpoint\n\nexport interface GridElementProps {\n /** Flex container behavior; items are its direct Grid children. */\n container?: boolean\n /**\n * Column span. Persisted as one string: a bare span (`6`), the keywords\n * `auto`/`grow`, or per-breakpoint pairs (`xs:12 md:6`). Authored through\n * the breakpoint row in the attributes panel (AGL-2486); the stored\n * format is unchanged from when it was a text box.\n */\n size?: string | number\n /** Empty columns before the item; same syntax as `size`, minus `grow`. */\n offset?: string | number\n spacing?: number | string\n rowSpacing?: number | string\n columnSpacing?: number | string\n /** Total columns in the container; MUI's default is 12. */\n columns?: number | string\n /**\n * Container flow. MUI supports `row`/`row-reverse` ONLY — Grid subdivides\n * a layout into columns, and `column`/`column-reverse` are documented as\n * unsupported (use a Stack for a vertical layout).\n */\n direction?: 'row' | 'row-reverse'\n /** `flex-wrap` for the container; MUI's default is `wrap`. */\n wrap?: 'nowrap' | 'wrap' | 'wrap-reverse'\n /**\n * A cell that ends up alone on the last row spans the whole row instead\n * of sitting in its first column. Read per breakpoint from the cell's own\n * Span and its row's Columns, so a row of thirds that leaves one cell over\n * widens it from the breakpoint the thirds start at, and a row that comes\n * out even leaves every cell as it is. Set it on every cell of a row whose\n * cells come and go (a hidden cell is not on the page), and whichever one\n * is last takes it.\n */\n fillLastRow?: boolean\n sx?: SxProps<Theme>\n children?: ReactNode\n}\n\n/** MUI's default column count, which a row with no Columns of its own uses. */\nconst DEFAULT_COLUMNS = 12\n\n/**\n * The column count of the row a cell sits in. MUI keeps it in a CSS\n * variable, which a selector cannot count with, so the row hands it down.\n */\nconst GridColumnsContext = createContext<number>(DEFAULT_COLUMNS)\n\ntype SpanBreakpointStyles = Record<string, Record<string, Record<string, string>>>\n\n/**\n * The styles that widen a lone last cell to the full row (`fillLastRow`).\n *\n * At each breakpoint the cell's span gives how many cells share a row. A\n * cell that is the last child AND the first of its row — `nth-child(kn+1)`\n * for `k` per row — is alone there. Each breakpoint range gets its own\n * bounded media query, so \"two to a row\" from `sm` stops at the `md` where\n * three to a row starts, rather than still matching an odd cell that has\n * company in a row of three. One to a row, `auto` and `grow` add nothing:\n * the cell is already as wide as it is going to be.\n */\nexport function loneLastCellStyles(\n size: ReturnType<typeof parseSpan>,\n columns: number,\n breakpoints: Pick<Breakpoints, 'keys' | 'up' | 'between'>,\n): SpanBreakpointStyles {\n if (size === undefined) return {}\n const keys = breakpoints.keys\n const perRow: Array<number | undefined> = []\n let current: number | 'auto' | 'grow' | undefined\n for (const key of keys) {\n if (typeof size === 'object') {\n if (size[key] !== undefined) current = size[key]\n } else {\n current = size\n }\n perRow.push(\n typeof current === 'number' && current > 0\n ? Math.floor(columns / Math.min(current, columns))\n : undefined,\n )\n }\n const styles: SpanBreakpointStyles = {}\n let start = 0\n while (start < keys.length) {\n let end = start\n while (end + 1 < keys.length && perRow[end + 1] === perRow[start]) end += 1\n const count = perRow[start]\n if (count !== undefined && count > 1) {\n const query =\n end + 1 < keys.length\n ? breakpoints.between(keys[start], keys[end + 1])\n : breakpoints.up(keys[start])\n styles[query] = {\n [`&:last-child:nth-child(${count}n + 1)`]: { width: '100%' },\n }\n }\n start = end + 1\n }\n return styles\n}\n\n/**\n * Parses the authored span syntax into what MUI v6+ Grid expects.\n *\n * MUI dropped the `item` prop and the per-breakpoint `xs=`/`md=` props in\n * v6; v9 (installed here) takes a single `size` that is either a value or\n * a `{ xs, md, … }` object. One STORED string covers both, and this parser\n * owns the translation:\n *\n * `6` → 6\n * `auto` → 'auto'\n * `grow` → 'grow'\n * `xs:12 md:6` → { xs: 12, md: 6 }\n *\n * Anything unparseable returns `undefined` rather than a partial object:\n * a half-applied breakpoint map is a layout that silently differs from\n * what the author typed.\n */\nexport function parseSpan(\n value: unknown,\n): number | 'auto' | 'grow' | Record<string, number | 'auto' | 'grow'> | undefined {\n // The reading itself is `parseBreakpointSpan` in `@aglyn/shared-data-enums`\n // (AGL-2486), shared with the attributes panel's breakpoint row so the\n // editor and the renderer cannot disagree about a stored string. This\n // function keeps its own signature and its \"unparseable means unset\"\n // contract: `raw` is what the editor hands back untouched, and what MUI\n // must never receive.\n const span = parseBreakpointSpan(value as string | number)\n if (span.raw !== undefined) return undefined\n if (span.base !== undefined) return span.base\n return span.values && Object.keys(span.values).length\n ? (span.values as Record<string, number | 'auto' | 'grow'>)\n : undefined\n}\n\n/**\n * Same syntax as `parseSpan`, minus `grow`.\n *\n * MUI's `GridOffset` is `'auto' | number` only — a `grow` offset is not\n * a wider gap, it is a value the layout cannot use, so it is dropped\n * here rather than passed through to be ignored.\n */\nexport function parseOffset(value: unknown) {\n const parsed = parseSpan(value)\n if (parsed === 'grow') return undefined\n if (parsed && typeof parsed === 'object') {\n const kept = Object.fromEntries(\n Object.entries(parsed).filter(([, span]) => span !== 'grow'),\n )\n return Object.keys(kept).length\n ? (kept as Record<string, number | 'auto'>)\n : undefined\n }\n return parsed as number | 'auto' | undefined\n}\n\n/** Spacing/columns arrive as strings from number fields; MUI wants numbers. */\nfunction toNumber(value: unknown): number | undefined {\n if (value == null || value === '') return undefined\n const parsed = Number(value)\n return Number.isFinite(parsed) ? parsed : undefined\n}\n\n/**\n * Responsive 12-column grid (https://mui.com/material-ui/react-grid/).\n * One element covers both roles, matching MUI v6+: switch **Container**\n * on for the row, leave it off and set a **Span** for each cell.\n */\nconst GridElement = forwardRef<HTMLDivElement, GridElementProps>(\n (props, ref) => {\n const {\n container,\n size,\n offset,\n spacing,\n rowSpacing,\n columnSpacing,\n columns,\n direction,\n wrap,\n fillLastRow,\n sx,\n children,\n ...rest\n } = props\n const parentColumns = useContext(GridColumnsContext)\n const span = parseSpan(size)\n const ownColumns = toNumber(columns)\n const nodeSx = Array.isArray(sx) ? sx : sx ? [sx] : []\n const grid = (\n <MuiGrid\n ref={ref}\n container={!!container}\n size={span}\n offset={parseOffset(offset)}\n // Spacing props only apply to containers; MUI ignores them on\n // items, so no need to strip them here.\n spacing={toNumber(spacing)}\n rowSpacing={toNumber(rowSpacing)}\n columnSpacing={toNumber(columnSpacing)}\n columns={ownColumns}\n // A CLEARED select persists as `null`, and MUI resolves both of these\n // as responsive values — `null.xs` throws during SSR and 500s the\n // published page (the AGL-1226 shape). `undefined` is what \"cleared\"\n // has to mean by the time it reaches MUI.\n {...dropClearedProps({ direction, wrap })}\n {...applySemanticElement(dropClearedProps(rest) as Record<string, unknown>)}\n sx={[\n fillLastRow && !container\n ? (theme: Theme) =>\n loneLastCellStyles(span, parentColumns, theme.breakpoints)\n : false,\n ...nodeSx,\n ]}\n >\n {children}\n </MuiGrid>\n )\n return container ? (\n <GridColumnsContext.Provider value={ownColumns ?? DEFAULT_COLUMNS}>\n {grid}\n </GridColumnsContext.Provider>\n ) : (\n grid\n )\n },\n)\nGridElement.displayName = 'AglynGrid'\n\n/** Container-only props: MUI ignores these on an item. */\nconst CONTAINER_ONLY = { when: 'container', is: true }\n/** Item-only props: a container spans its parent, not a column count. */\nconst ITEM_ONLY = { when: 'container', is: true, notMatch: true }\n\nconst SPAN_HELP =\n 'How many columns this cell takes. Set **All** for every screen size, or ' +\n 'give individual breakpoints a value — `xs` applies from the smallest ' +\n 'screens up and each larger breakpoint overrides it. `auto` fits the ' +\n 'content, `grow` takes the remaining space.'\n\nexport const schema: Aglyn.ComponentSchema<GridElementProps> = {\n $id: ID,\n pluginId: BUNDLE_ID,\n displayName: 'Grid',\n // Static, and its children sit directly in its root: a subtree it heads\n // keeps its server HTML until the visitor nears it (AGL-3581).\n flags: {\n lazyHydration: Aglyn.FEATURE_FLAG.ENABLED,\n childrenInRoot: Aglyn.FEATURE_FLAG.ENABLED,\n },\n description:\n 'Responsive 12-column layout. Turn on Container for the row; give ' +\n 'each cell a Span.',\n category: Aglyn.ComponentCategory.LAYOUT,\n icon: { path: mdiViewGrid.path, sx: { color: '#2196f3' } },\n attributes: [\n semanticElementAttribute('this grid'),\n semanticElementLabelAttribute(),\n {\n name: 'container',\n label: 'Container?',\n description:\n 'If true, this grid lays its direct Grid children out in columns. ' +\n 'Leave it off for a cell inside another grid.',\n component: Aglyn.FieldComponentType.SWITCH,\n },\n {\n name: 'size',\n label: 'Span',\n description: SPAN_HELP,\n // A row of breakpoint controls rather than a text box (AGL-2486). The\n // STORED value is the same string it always was; only the way it is\n // authored changed. `xs:12 md:2` was a developer syntax documented\n // nowhere but this tooltip, so the responsive capability was there and\n // effectively unreachable.\n component: Aglyn.FieldComponentType.BREAKPOINT_SPAN,\n condition: ITEM_ONLY,\n },\n {\n name: 'offset',\n label: 'Offset',\n description:\n 'Empty columns before this cell. `auto` pushes the cell to the ' +\n 'right; `grow` is a span keyword and not an offset, so it is not ' +\n 'offered here.',\n component: Aglyn.FieldComponentType.BREAKPOINT_SPAN,\n // MUI's GridOffset is `'auto' | number`: a zero offset is a real\n // choice, and `grow` is not one at all.\n allowGrow: false,\n minSpan: 0,\n condition: ITEM_ONLY,\n },\n {\n name: 'fillLastRow',\n label: 'Fill the row when alone?',\n description:\n 'If true, this cell spans the whole row whenever it ends up alone on ' +\n 'the last row, at every screen size. Turn it on for every cell of a ' +\n 'row whose cells can be hidden, so whichever cell is last fills in.',\n component: Aglyn.FieldComponentType.SWITCH,\n condition: ITEM_ONLY,\n },\n {\n name: 'spacing',\n label: 'Spacing',\n description:\n 'Gap between cells, in theme spacing units (1 = 8px by default).',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n type: 'number',\n condition: CONTAINER_ONLY,\n },\n {\n name: 'rowSpacing',\n label: 'Row spacing',\n description: 'Vertical gap only; overrides Spacing.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n type: 'number',\n condition: CONTAINER_ONLY,\n },\n {\n name: 'columnSpacing',\n label: 'Column spacing',\n description: 'Horizontal gap only; overrides Spacing.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n type: 'number',\n condition: CONTAINER_ONLY,\n },\n {\n name: 'columns',\n label: 'Columns',\n description: 'Total columns the row is divided into. Default 12.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n type: 'number',\n condition: CONTAINER_ONLY,\n },\n {\n name: 'direction',\n label: 'Direction',\n // The option that is NOT offered is the point of this field. MUI's own\n // API doc: \"Only `row` and `row-reverse` are supported. `column` and\n // `column-reverse` are not supported, because the Grid component is\n // designed to subdivide layouts into columns, not rows.\" Offering them\n // would be a control that silently does nothing.\n description:\n 'Sets the `flex-direction` for the row. Only Row and Row Reversed ' +\n 'are supported — Grid divides a layout into columns, so a column ' +\n 'direction does nothing. Use a Stack for a vertical layout.',\n component: Aglyn.FieldComponentType.SELECT,\n options: [\n { value: 'row', label: 'Row' },\n { value: 'row-reverse', label: 'Row Reversed' },\n ],\n condition: CONTAINER_ONLY,\n },\n {\n name: 'wrap',\n label: 'Wrap',\n description:\n 'Whether cells that do not fit move onto a new line. Default Wrap; ' +\n 'No Wrap keeps every cell on one line and lets them shrink instead.',\n component: Aglyn.FieldComponentType.SELECT,\n options: [\n { value: 'wrap', label: 'Wrap' },\n { value: 'nowrap', label: 'No Wrap' },\n { value: 'wrap-reverse', label: 'Wrap Reversed' },\n ],\n condition: CONTAINER_ONLY,\n },\n colorSchemeAttribute(),\n ],\n}\n\nconst cell = (size: string, text: string) => ({\n $id: null,\n componentId: ID,\n pluginId: BUNDLE_ID,\n props: { size },\n nodes: [\n {\n $id: null,\n componentId: 'muiTypography',\n pluginId: BUNDLE_ID,\n props: { variant: 'body2', children: text },\n },\n ],\n})\n\nexport const presets: Aglyn.PresetSchema[] = [\n {\n // Ships as a working responsive row, not a bare container: an empty\n // grid renders as nothing at all on the canvas.\n $id: generatePresetId(ID),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Grid',\n pluginId: BUNDLE_ID,\n description: 'Responsive row — three columns that stack on mobile',\n category: Aglyn.ComponentCategory.LAYOUT,\n icon: schema.icon,\n data: {\n $id: null,\n componentId: ID,\n pluginId: BUNDLE_ID,\n props: { container: true, spacing: 2 },\n nodes: [\n cell('xs:12 md:4', 'Column one'),\n cell('xs:12 md:4', 'Column two'),\n cell('xs:12 md:4', 'Column three'),\n ],\n },\n },\n {\n $id: generatePresetId(ID, 'cell'),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Grid Cell',\n pluginId: BUNDLE_ID,\n description: 'A single cell to add to an existing grid row',\n category: Aglyn.ComponentCategory.LAYOUT,\n icon: { path: mdiViewGridOutline.path, sx: { color: '#2196f3' } },\n data: cell('xs:12 md:6', 'Cell'),\n },\n]\n\nexport default GridElement\n"],"names":["Aglyn","mdiViewGrid","mdiViewGridOutline","parseBreakpointSpan","SPAN_BREAKPOINTS","MuiGrid","createContext","forwardRef","useContext","applySemanticElement","semanticElementAttribute","semanticElementLabelAttribute","BUNDLE_ID","colorSchemeAttribute","dropClearedProps","generatePresetId","ID","BREAKPOINTS","DEFAULT_COLUMNS","GridColumnsContext","loneLastCellStyles","size","columns","breakpoints","undefined","keys","perRow","current","key","push","Math","floor","min","styles","start","length","end","count","query","between","up","width","parseSpan","value","span","raw","base","values","Object","parseOffset","parsed","kept","fromEntries","entries","filter","toNumber","Number","isFinite","GridElement","props","ref","container","offset","spacing","rowSpacing","columnSpacing","direction","wrap","fillLastRow","sx","children","rest","parentColumns","ownColumns","nodeSx","Array","isArray","grid","theme","Provider","displayName","CONTAINER_ONLY","when","is","ITEM_ONLY","notMatch","SPAN_HELP","schema","$id","pluginId","flags","lazyHydration","FEATURE_FLAG","ENABLED","childrenInRoot","description","category","ComponentCategory","LAYOUT","icon","path","color","attributes","name","label","component","FieldComponentType","SWITCH","BREAKPOINT_SPAN","condition","allowGrow","minSpan","TEXT_FIELD","type","SELECT","options","cell","text","componentId","nodes","variant","presets","NodeType","PRESET","data"],"mappings":"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"}
|
|
@@ -347,9 +347,26 @@ const REPEAT_TRACKS = /^repeat\(\s*(\d+)\s*,\s*(1fr|minmax\(\s*0(?:px)?\s*,\s*1f
|
|
|
347
347
|
}
|
|
348
348
|
}
|
|
349
349
|
};
|
|
350
|
-
// The image's own max width caps it
|
|
351
|
-
// stated length, not as layout
|
|
352
|
-
|
|
350
|
+
// The image's own max width caps it. Its own pixel or viewport width is read
|
|
351
|
+
// as its own stated length (`ownLengths`), not as layout — but a width given
|
|
352
|
+
// as a share of its slot is a share of what the layout below states, so it
|
|
353
|
+
// scales that slot. It is NOT clamped at 100% the way an ancestor's is: an
|
|
354
|
+
// image set wider than its cell (`118%`, pulled out with a negative margin)
|
|
355
|
+
// really paints that wide, and a `sizes` of the cell alone downloads a
|
|
356
|
+
// candidate the box then upscales (AGL-3715).
|
|
357
|
+
if (node) {
|
|
358
|
+
var _sx_width;
|
|
359
|
+
applySizing(node, false);
|
|
360
|
+
const sx = plainSx(node.sx);
|
|
361
|
+
const widths = bandValues((_sx_width = sx['width']) != null ? _sx_width : propsOf(node)['width']);
|
|
362
|
+
for (const band of BANDS){
|
|
363
|
+
const value = length(widths[band]);
|
|
364
|
+
if ((value == null ? void 0 : value.kind) === 'fraction' && value.value !== 1) {
|
|
365
|
+
step(band, value.value);
|
|
366
|
+
stated = true;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
353
370
|
let child = node;
|
|
354
371
|
// Stored pages name the root as its own parent (`parentId: "_@_"`), so a
|
|
355
372
|
// walk that only stops at a missing parent never ends (AGL-3565). Stop at
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/utils/image-sizes.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as Aglyn from '@aglyn/aglyn'\nimport { parseBreakpointSpan } from '@aglyn/shared-data-enums'\n\n/**\n * The Image element's `sizes` attribute (AGL-3485): how wide the browser\n * should assume the picture will be, which decides the `srcset` candidate it\n * downloads.\n *\n * Every image used to say `100vw`, so a 68px navbar logo and a 302px card\n * picture both fetched a 1280px or 1920px variant. The answer is now decided\n * in this order, first answer wins:\n *\n * 1. **The author's own Sizes attribute**, verbatim. An escape hatch for\n * someone who knows the attribute; nobody needs to touch it.\n * 2. **Per breakpoint band, a pixel width the element itself states**: a\n * pixel `width` (`'320px'`, or a plain number in `sx`, which MUI reads as\n * pixels), or a pixel `height` under `width: auto` at the asset's known\n * shape. Responsive values are read per band, so the header logo's\n * `height: { xs: 44, md: 56 }` is a 54px slot on a phone and a 68px one\n * from `md` up.\n * 3. **Per band, the width the Besigner MEASURED** when the page was saved.\n * 4. **Per band, the slot the layout around the image states**\n * ({@link layoutBandWidths}): Grid spans, `repeat(n, 1fr)` grids, widths\n * and max widths, and the Container that caps the page.\n * 5. For a band nothing describes, the next narrower band's answer, and\n * `100vw` only for the narrowest band when nothing at all is known.\n *\n * Steps 2 and 4 are computed from the node tree the page renders, so they hold\n * for every page already published — on the server, with no re-save. The\n * measurement only refines what the layout cannot state.\n *\n * ## Why this does not bring back the AGL-2486 layout break\n *\n * `sizes` is not only a delivery hint: with `w` descriptors it is the image's\n * intrinsic width, which is what `width: 100%` resolves against inside a\n * shrink-to-fit parent. `sizes=\"auto\"` broke fluid images because it is\n * circular there (300px default object size). Every answer above is a real\n * width of the slot the image fills: a definite length, a share of a parent of\n * definite width, or a measurement of the very layout being described —\n * which is a fixed point, since an image whose intrinsic width is its\n * measured width lays out at its measured width.\n */\nexport interface ImageSizesInput {\n /** The author's Sizes attribute. */\n sizes?: unknown\n /** The element's `width` attribute, as the author set it. */\n width?: unknown\n /** The element's `height` attribute, as the author set it. */\n height?: unknown\n /**\n * The node's own styles. Their `width` and `height` win over the\n * attributes, as they do in the render (`sx` is composed after the\n * defaults the attributes set).\n */\n sx?: unknown\n intrinsicWidth?: unknown\n intrinsicHeight?: unknown\n /** What the Besigner measured, as the save stored it. */\n renderedWidths?: unknown\n /** What the layout around the image states, per band. */\n layoutWidths?: LayoutWidths\n}\n\nexport interface ImageSizes {\n sizes: string\n /**\n * The evidence says the image renders small everywhere it is known: a\n * pixel width of {@link SMALL_IMAGE_MAX_PX} or less, or under\n * {@link SMALL_IMAGE_MAX_PERCENT} of the page, in every band that was\n * stated, measured or derived. A lead image that is small is a logo or an\n * icon, not the page's largest paint, and gets no `fetchpriority=\"high\"`.\n */\n small: boolean\n}\n\n/** At or under this many pixels wide an image is not a hero. */\nexport const SMALL_IMAGE_MAX_PX = 240\n\n/** Under this share of the page in every known band, an image is not a hero. */\nexport const SMALL_IMAGE_MAX_PERCENT = 40\n\ntype Band = Aglyn.RenderedWidthBand\ntype BandValues<T> = Partial<Record<Band, T>>\n\nconst BANDS = Aglyn.RENDERED_WIDTH_BANDS\n\n/**\n * One slot the layout states for a band: a share of the viewport less the\n * gutters and gaps taken out of it, and the pixel width it can never exceed\n * when something above it caps the page — `min(vw% - offset, cap)`.\n */\nexport interface LayoutSlot {\n vw: number\n offsetPx?: number\n capPx?: number\n}\n\nexport type LayoutWidths = BandValues<LayoutSlot>\n\n/**\n * A responsive value's reading at every band, cascading upwards the way MUI\n * applies one: a band with no value of its own takes the nearest narrower\n * band's. A scalar applies everywhere, an array is MUI's breakpoint array,\n * and keys that are not bands — a dark-scheme slice, a raw media query — are\n * not read.\n */\nfunction bandValues(value: unknown): BandValues<unknown> {\n if (value === undefined || value === null || value === '') return {}\n let stated: BandValues<unknown>\n if (Array.isArray(value)) {\n stated = {}\n value.forEach((entry, index) => {\n if (index < BANDS.length && entry !== null && entry !== undefined) {\n stated[BANDS[index]] = entry\n }\n })\n } else if (typeof value === 'object') {\n stated = {}\n for (const band of BANDS) {\n const entry = (value as Record<string, unknown>)[band]\n if (entry !== undefined && entry !== null) stated[band] = entry\n }\n } else {\n return Object.fromEntries(BANDS.map((band) => [band, value]))\n }\n const out: BandValues<unknown> = {}\n let current: unknown\n for (const band of BANDS) {\n if (stated[band] !== undefined) current = stated[band]\n if (current !== undefined) out[band] = current\n }\n return out\n}\n\n/**\n * A CSS sizing value as MUI's `sx` reads it: a number in (0, 1] is a share of\n * the parent, any other number is pixels, and a string may be either unit.\n */\ntype Length =\n | { kind: 'px'; value: number }\n | { kind: 'fraction'; value: number }\n | { kind: 'vw'; value: number }\n | { kind: 'auto' }\n\nfunction length(value: unknown): Length | undefined {\n if (typeof value === 'number' && Number.isFinite(value)) {\n if (value > 0 && value <= 1) return { kind: 'fraction', value }\n return value > 1 ? { kind: 'px', value } : undefined\n }\n if (typeof value !== 'string') return undefined\n const text = value.trim()\n if (text === 'auto') return { kind: 'auto' }\n const match = /^(\\d+(?:\\.\\d+)?)(px|%|vw)$/.exec(text)\n if (!match) return undefined\n const amount = Number(match[1])\n if (!(amount > 0)) return undefined\n if (match[2] === 'px') return { kind: 'px', value: amount }\n if (match[2] === 'vw') return { kind: 'vw', value: amount }\n return { kind: 'fraction', value: amount / 100 }\n}\n\n/** A node's `sx` as one plain object: an array of objects merged in order. */\nfunction plainSx(sx: unknown): Record<string, unknown> {\n if (Array.isArray(sx)) {\n return Object.assign(\n {},\n ...sx.filter(\n (entry) => entry && typeof entry === 'object' && !Array.isArray(entry),\n ),\n )\n }\n return sx && typeof sx === 'object' ? (sx as Record<string, unknown>) : {}\n}\n\nconst usable = (value: unknown): value is number =>\n typeof value === 'number' && Number.isFinite(value) && value > 0\n\n/**\n * The length the element itself states per band, as a `sizes` length: a\n * pixel or viewport width, or a pixel height under `width: auto` at the\n * asset's shape. Per band, so a responsive value is read the way MUI applies\n * it; a band where the element states nothing usable is left to the layout.\n */\nfunction ownLengths(input: ImageSizesInput): BandValues<string> {\n const sx = plainSx(input.sx)\n const widths = bandValues(input.width)\n const heights = bandValues(input.height)\n const sxWidths = bandValues(sx['width'])\n const sxHeights = bandValues(sx['height'])\n const ratio =\n usable(input.intrinsicWidth) && usable(input.intrinsicHeight)\n ? input.intrinsicWidth / input.intrinsicHeight\n : undefined\n const out: BandValues<string> = {}\n for (const band of BANDS) {\n const width = length(sxWidths[band] ?? widths[band])\n if (width?.kind === 'px') {\n out[band] = `${Math.round(width.value)}px`\n continue\n }\n if (width?.kind === 'vw') {\n out[band] = `${Math.round(width.value * 10) / 10}vw`\n continue\n }\n const height = length(sxHeights[band] ?? heights[band])\n if (width?.kind === 'auto' && height?.kind === 'px' && ratio) {\n out[band] = `${Math.round(height.value * ratio)}px`\n }\n }\n return out\n}\n\n/** A layout slot as a `sizes` length for a band. */\nfunction slotLength(band: Band, slot: LayoutSlot): string {\n // A cap that binds across the whole band — the page is at least the band's\n // minimum wide, so the slot is the cap from its first pixel — is the\n // definite length. Below that, the share of the viewport is the answer, and\n // it can only overstate the slot by the gutters.\n const offset = slot.offsetPx ?? 0\n // A pixel of slack absorbs the rounding of the share and the cap.\n if (\n slot.capPx !== undefined &&\n slot.capPx <=\n (slot.vw / 100) * Aglyn.RENDERED_WIDTH_BAND_MIN[band] - offset + 1\n ) {\n return `${slot.capPx}px`\n }\n return offset >= 1 ? `calc(${slot.vw}vw - ${offset}px)` : `${slot.vw}vw`\n}\n\n/**\n * What was measured, with the layout's statement filling the bands the\n * Besigner never saw.\n *\n * A measured band wins. Above it, the layout's value is used only where it\n * says something NEW — a value that differs from the one the layout gave the\n * measured band. A value it merely carried up from the measured band's span\n * is the same slot measured more precisely, so the measurement carries\n * instead: a cell measured at 28% on a large screen is not 33% on a wider\n * one just because its span did not change.\n */\nfunction combineBandLengths(\n measured: Aglyn.RenderedWidths,\n layout: BandValues<string>,\n): BandValues<string> {\n const known: BandValues<string> = {}\n let lastMeasured: string | undefined\n let layoutWhenMeasured: string | undefined\n for (const band of BANDS) {\n const value = measured[band]\n if (value !== undefined) {\n known[band] = `${value}vw`\n lastMeasured = known[band]\n layoutWhenMeasured = layout[band]\n continue\n }\n const stated = layout[band]\n if (stated !== undefined && stated !== layoutWhenMeasured) {\n known[band] = stated\n } else if (lastMeasured !== undefined) {\n known[band] = lastMeasured\n }\n }\n return known\n}\n\n/** Whether a known length is a small slot. */\nfunction isSmall(css: string): boolean {\n if (css.endsWith('px') && !css.startsWith('calc(')) {\n return Number.parseFloat(css) <= SMALL_IMAGE_MAX_PX\n }\n const vw = /(\\d+(?:\\.\\d+)?)vw/.exec(css)\n return vw ? Number(vw[1]) < SMALL_IMAGE_MAX_PERCENT : false\n}\n\n/** The `sizes` an Image element should carry. See the module note. */\nexport function imageSizes(input: ImageSizesInput): ImageSizes {\n const authored = typeof input.sizes === 'string' ? input.sizes.trim() : ''\n if (authored) return { sizes: authored, small: false }\n const layout: BandValues<string> = {}\n for (const band of BANDS) {\n const slot = input.layoutWidths?.[band]\n if (slot) layout[band] = slotLength(band, slot)\n }\n const known = {\n ...combineBandLengths(\n Aglyn.parseRenderedWidths(input.renderedWidths),\n layout,\n ),\n ...ownLengths(input),\n }\n const values = Object.values(known) as string[]\n return {\n sizes: Aglyn.sizesFromBandLengths(known),\n small: values.length > 0 && values.every(isSmall),\n }\n}\n\n/** No published page nests deeper; a walk past this is following a cycle. */\nconst MAX_LAYOUT_DEPTH = 256\n\n/** The Grid element's persisted component id (`grid.tsx`). */\nconst GRID_COMPONENT_ID = 'muiGrid'\n\n/** The Container element's persisted component id (`container.ts`). */\nconst CONTAINER_COMPONENT_ID = 'muiContainer'\n\n/**\n * A Container's `maxWidth` keys in pixels: MUI's, `xs` floored at 444px. An\n * absent or cleared value is MUI's own `lg` (the element drops a cleared one\n * so MUI's default applies, AGL-1435); `false` caps nothing.\n */\nconst CONTAINER_MAX_WIDTHS: Readonly<Record<string, number>> = {\n xs: 444,\n sm: 600,\n md: 900,\n lg: 1200,\n xl: 1536,\n}\n\n/**\n * A Container's side gutters: MUI's `theme.spacing(2)` a side on a phone and\n * `theme.spacing(3)` from `sm` up.\n */\nconst CONTAINER_GUTTER_PX: Readonly<Record<Band, number>> = {\n xs: 16,\n sm: 24,\n md: 24,\n lg: 24,\n xl: 24,\n}\n\n/** One theme spacing unit; MUI's default, which `sx` gaps are counted in. */\nconst SPACING_PX = 8\n\n/** A gap in pixels: a number is theme spacing units, a string must be px. */\nfunction gapPixels(value: unknown): number {\n if (typeof value === 'number' && Number.isFinite(value) && value > 0) {\n return value * SPACING_PX\n }\n const text = String(value ?? '').trim()\n if (/^\\d+(?:\\.\\d+)?$/.test(text)) return Number(text) * SPACING_PX\n const match = /^(\\d+(?:\\.\\d+)?)px$/.exec(text)\n return match ? Number(match[1]) : 0\n}\n\n/** A node as the canvas holds it, as far as this walk reads it. */\nexport interface LayoutNode {\n componentId?: string\n props?: Record<string, unknown>\n resolvedProps?: Record<string, unknown>\n sx?: unknown\n parent?: LayoutNode | undefined\n}\n\nconst propsOf = (node: LayoutNode | undefined) =>\n node?.resolvedProps ?? node?.props ?? {}\n\n/** A Grid cell's span at each band: a column count, or `null` for auto/grow. */\nfunction gridSpanPerBand(size: unknown): BandValues<number | null> {\n if (size === undefined || size === null || size === '') return {}\n const span = parseBreakpointSpan(size as string | number)\n if (span.raw !== undefined) return {}\n const read = (value: unknown) => (typeof value === 'number' ? value : null)\n if (span.base !== undefined) {\n const value = read(span.base)\n return Object.fromEntries(BANDS.map((band) => [band, value]))\n }\n const values: Record<string, unknown> = {}\n for (const [band, value] of Object.entries(span.values ?? {})) {\n values[band] = read(value)\n }\n return bandValues(values) as BandValues<number | null>\n}\n\nconst FR_TRACK = /^(?:1fr|minmax\\(\\s*0(?:px)?\\s*,\\s*1fr\\s*\\))$/\nconst REPEAT_TRACKS =\n /^repeat\\(\\s*(\\d+)\\s*,\\s*(1fr|minmax\\(\\s*0(?:px)?\\s*,\\s*1fr\\s*\\))\\s*\\)$/\n\n/**\n * The equal tracks a `gridTemplateColumns` value lays out: `repeat(3, 1fr)`,\n * or the same written out, `1fr 1fr 1fr` — and a single `1fr`, which is one\n * column the full width. Anything else (fixed tracks, `auto-fill`) is not an\n * equal split this can state.\n */\nfunction equalTracks(value: unknown): number | undefined {\n const text = String(value ?? '').trim()\n const repeat = REPEAT_TRACKS.exec(text)\n if (repeat) return Number(repeat[1]) > 0 ? Number(repeat[1]) : undefined\n const tracks = text.split(/\\s+(?![^(]*\\))/).filter(Boolean)\n return tracks.length && tracks.every((track) => FR_TRACK.test(track))\n ? tracks.length\n : undefined\n}\n\n/** How many tracks a grid child spans, from its own `gridColumn`. */\nfunction spannedTracks(value: unknown, tracks: number): number {\n const text = String(value ?? '').trim()\n const span = /^span\\s+(\\d+)$/.exec(text)\n if (span) return Math.min(Number(span[1]), tracks)\n if (/^1\\s*\\/\\s*-1$/.test(text)) return tracks\n return 1\n}\n\n/**\n * The slot the layout around an image gives it, per band, from what the\n * layout STATES rather than what anyone measured — computed from the node\n * tree a page renders, so a published page has it on the server with nothing\n * re-saved. Walking up from the image:\n *\n * - every **Grid cell** it sits in takes its responsive span of its row's\n * columns (`xs:12 md:4` is a third from `md` up), less its share of the\n * row's spacing;\n * - every **CSS grid** of equal tracks (`repeat(3, 1fr)`, per breakpoint)\n * gives each child one track, or the tracks its `gridColumn` spans, less\n * its share of the gap;\n * - every **width or max width** given as a share of the parent shrinks the\n * slot by it, and one given in pixels caps it;\n * - every **Container** takes its gutters off and caps it at its max width.\n *\n * Each step maps the parent's width to the child's as `share × parent −\n * offset`, so they compose: a third of a half is a sixth, and a gap inside a\n * capped Container is still a gap. The answer per band is `min(vw% − offset,\n * cap)`. A band is answered only when something stated it and nothing between\n * the image and the page made it unknowable — an `auto` or `grow` Grid cell is\n * sized by its content, so a band where any cell is one has no answer here.\n * Theme spacing is taken at MUI's 8px, and anything this does not model\n * (padding on an ordinary Box, a flex row) is left in, so a guess errs wide:\n * a slightly larger candidate, never a blurry one.\n *\n * The same function serves the Besigner canvas and the published render; the\n * tree differs only in that the canvas has not grafted reusable components or\n * expanded repeats, which the measurement covers there.\n */\nexport function layoutBandWidths(\n node: LayoutNode | undefined,\n): LayoutWidths {\n /** Per band, the image's width as `share × W − offset` of the ancestor W. */\n const share: BandValues<number | null> = {}\n const offset: BandValues<number> = {}\n const cap: BandValues<number> = {}\n let stated = false\n const known = (band: Band) => share[band] !== null\n /** The child takes `factor × parent − minus`. */\n const step = (band: Band, factor: number | null, minus = 0) => {\n if (!known(band)) return\n if (factor === null) {\n share[band] = null\n return\n }\n const k = share[band] ?? 1\n offset[band] = (offset[band] ?? 0) + k * minus\n share[band] = k * factor\n }\n /** The child is never wider than `pixels`. */\n const capAt = (band: Band, pixels: number) => {\n if (!known(band)) return\n const scaled = (share[band] ?? 1) * pixels - (offset[band] ?? 0)\n cap[band] = Math.min(cap[band] ?? Infinity, scaled)\n }\n /** Width and max width as a share or a cap, from a node's own styles. */\n const applySizing = (target: LayoutNode, includeWidth: boolean) => {\n const sx = plainSx(target.sx)\n for (const key of includeWidth ? ['width', 'maxWidth'] : ['maxWidth']) {\n const values = bandValues(sx[key])\n for (const band of BANDS) {\n const value = length(values[band])\n if (value?.kind === 'fraction') {\n step(band, Math.min(value.value, 1))\n stated = true\n } else if (value?.kind === 'px') {\n capAt(band, value.value)\n stated = true\n }\n }\n }\n }\n // The image's own max width caps it; its own width is read as its own\n // stated length, not as layout.\n if (node) applySizing(node, false)\n let child = node\n // Stored pages name the root as its own parent (`parentId: \"_@_\"`), so a\n // walk that only stops at a missing parent never ends (AGL-3565). Stop at\n // any node already visited, and never climb further than a page can nest.\n const visited = new Set<LayoutNode>(node ? [node] : [])\n let depth = 0\n for (\n let current = node?.parent;\n current && !visited.has(current) && depth < MAX_LAYOUT_DEPTH;\n current = current.parent, depth += 1\n ) {\n visited.add(current)\n const props = propsOf(current)\n if (current.componentId === GRID_COMPONENT_ID) {\n const spans = gridSpanPerBand(props['size'])\n if (Object.keys(spans).length) {\n const row = current.parent\n const rowProps = row?.componentId === GRID_COMPONENT_ID ? propsOf(row) : {}\n const columns = Number(rowProps['columns'])\n const total = columns > 0 ? columns : 12\n const spacing = bandValues(\n rowProps['columnSpacing'] ?? rowProps['spacing'],\n )\n stated = true\n for (const band of BANDS) {\n const span = spans[band]\n if (span === undefined || span === null) {\n step(band, null)\n continue\n }\n const portion = Math.min(span / total, 1)\n step(band, portion, gapPixels(spacing[band]) * (1 - portion))\n }\n }\n }\n const sx = plainSx(current.sx)\n const templates = bandValues(sx['gridTemplateColumns'])\n const gaps = bandValues(sx['columnGap'] ?? sx['gap'])\n for (const band of BANDS) {\n const tracks = equalTracks(templates[band])\n if (tracks === undefined) continue\n const spanned = spannedTracks(\n bandValues(plainSx(child?.sx)['gridColumn'])[band],\n tracks,\n )\n const portion = spanned / tracks\n step(band, portion, gapPixels(gaps[band]) * (1 - portion))\n stated = true\n }\n applySizing(current, true)\n if (current.componentId === CONTAINER_COMPONENT_ID) {\n const maxWidth = props['maxWidth']\n const key =\n maxWidth === undefined || maxWidth === null || maxWidth === ''\n ? 'lg'\n : maxWidth\n const pixels =\n typeof key === 'string' ? CONTAINER_MAX_WIDTHS[key] : undefined\n for (const band of BANDS) {\n const gutters = props['disableGutters']\n ? 0\n : 2 * CONTAINER_GUTTER_PX[band]\n // The gutters come off whatever the page is; the cap is the max width\n // less the same gutters, since MUI pads inside the max width.\n if (pixels) capAt(band, pixels - gutters)\n step(band, 1, gutters)\n }\n stated = true\n }\n child = current\n }\n if (!stated) return {}\n const widths: LayoutWidths = {}\n for (const band of BANDS) {\n const fraction = share[band] === undefined ? 1 : share[band]\n if (typeof fraction !== 'number' || !(fraction > 0)) continue\n const minus = Math.round(offset[band] ?? 0)\n const capPx = cap[band]\n widths[band] = {\n vw: Math.round(fraction * 1000) / 10,\n ...(minus >= 1 ? { offsetPx: minus } : {}),\n ...(capPx !== undefined && Number.isFinite(capPx)\n ? { capPx: Math.round(capPx) }\n : {}),\n }\n }\n return widths\n}\n"],"names":["Aglyn","parseBreakpointSpan","SMALL_IMAGE_MAX_PX","SMALL_IMAGE_MAX_PERCENT","BANDS","RENDERED_WIDTH_BANDS","bandValues","value","undefined","stated","Array","isArray","forEach","entry","index","length","band","Object","fromEntries","map","out","current","Number","isFinite","kind","text","trim","match","exec","amount","plainSx","sx","assign","filter","usable","ownLengths","input","widths","width","heights","height","sxWidths","sxHeights","ratio","intrinsicWidth","intrinsicHeight","Math","round","slotLength","slot","offset","offsetPx","capPx","vw","RENDERED_WIDTH_BAND_MIN","combineBandLengths","measured","layout","known","lastMeasured","layoutWhenMeasured","isSmall","css","endsWith","startsWith","parseFloat","imageSizes","authored","sizes","small","layoutWidths","parseRenderedWidths","renderedWidths","values","sizesFromBandLengths","every","MAX_LAYOUT_DEPTH","GRID_COMPONENT_ID","CONTAINER_COMPONENT_ID","CONTAINER_MAX_WIDTHS","xs","sm","md","lg","xl","CONTAINER_GUTTER_PX","SPACING_PX","gapPixels","String","test","propsOf","node","resolvedProps","props","gridSpanPerBand","size","span","raw","read","base","entries","FR_TRACK","REPEAT_TRACKS","equalTracks","repeat","tracks","split","Boolean","track","spannedTracks","min","layoutBandWidths","share","cap","step","factor","minus","k","capAt","pixels","scaled","Infinity","applySizing","target","includeWidth","key","child","visited","Set","depth","parent","has","add","componentId","spans","keys","rowProps","row","columns","total","spacing","portion","templates","gaps","spanned","maxWidth","gutters","fraction"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/utils/image-sizes.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as Aglyn from '@aglyn/aglyn'\nimport { parseBreakpointSpan } from '@aglyn/shared-data-enums'\n\n/**\n * The Image element's `sizes` attribute (AGL-3485): how wide the browser\n * should assume the picture will be, which decides the `srcset` candidate it\n * downloads.\n *\n * Every image used to say `100vw`, so a 68px navbar logo and a 302px card\n * picture both fetched a 1280px or 1920px variant. The answer is now decided\n * in this order, first answer wins:\n *\n * 1. **The author's own Sizes attribute**, verbatim. An escape hatch for\n * someone who knows the attribute; nobody needs to touch it.\n * 2. **Per breakpoint band, a pixel width the element itself states**: a\n * pixel `width` (`'320px'`, or a plain number in `sx`, which MUI reads as\n * pixels), or a pixel `height` under `width: auto` at the asset's known\n * shape. Responsive values are read per band, so the header logo's\n * `height: { xs: 44, md: 56 }` is a 54px slot on a phone and a 68px one\n * from `md` up.\n * 3. **Per band, the width the Besigner MEASURED** when the page was saved.\n * 4. **Per band, the slot the layout around the image states**\n * ({@link layoutBandWidths}): Grid spans, `repeat(n, 1fr)` grids, widths\n * and max widths, and the Container that caps the page.\n * 5. For a band nothing describes, the next narrower band's answer, and\n * `100vw` only for the narrowest band when nothing at all is known.\n *\n * Steps 2 and 4 are computed from the node tree the page renders, so they hold\n * for every page already published — on the server, with no re-save. The\n * measurement only refines what the layout cannot state.\n *\n * ## Why this does not bring back the AGL-2486 layout break\n *\n * `sizes` is not only a delivery hint: with `w` descriptors it is the image's\n * intrinsic width, which is what `width: 100%` resolves against inside a\n * shrink-to-fit parent. `sizes=\"auto\"` broke fluid images because it is\n * circular there (300px default object size). Every answer above is a real\n * width of the slot the image fills: a definite length, a share of a parent of\n * definite width, or a measurement of the very layout being described —\n * which is a fixed point, since an image whose intrinsic width is its\n * measured width lays out at its measured width.\n */\nexport interface ImageSizesInput {\n /** The author's Sizes attribute. */\n sizes?: unknown\n /** The element's `width` attribute, as the author set it. */\n width?: unknown\n /** The element's `height` attribute, as the author set it. */\n height?: unknown\n /**\n * The node's own styles. Their `width` and `height` win over the\n * attributes, as they do in the render (`sx` is composed after the\n * defaults the attributes set).\n */\n sx?: unknown\n intrinsicWidth?: unknown\n intrinsicHeight?: unknown\n /** What the Besigner measured, as the save stored it. */\n renderedWidths?: unknown\n /** What the layout around the image states, per band. */\n layoutWidths?: LayoutWidths\n}\n\nexport interface ImageSizes {\n sizes: string\n /**\n * The evidence says the image renders small everywhere it is known: a\n * pixel width of {@link SMALL_IMAGE_MAX_PX} or less, or under\n * {@link SMALL_IMAGE_MAX_PERCENT} of the page, in every band that was\n * stated, measured or derived. A lead image that is small is a logo or an\n * icon, not the page's largest paint, and gets no `fetchpriority=\"high\"`.\n */\n small: boolean\n}\n\n/** At or under this many pixels wide an image is not a hero. */\nexport const SMALL_IMAGE_MAX_PX = 240\n\n/** Under this share of the page in every known band, an image is not a hero. */\nexport const SMALL_IMAGE_MAX_PERCENT = 40\n\ntype Band = Aglyn.RenderedWidthBand\ntype BandValues<T> = Partial<Record<Band, T>>\n\nconst BANDS = Aglyn.RENDERED_WIDTH_BANDS\n\n/**\n * One slot the layout states for a band: a share of the viewport less the\n * gutters and gaps taken out of it, and the pixel width it can never exceed\n * when something above it caps the page — `min(vw% - offset, cap)`.\n */\nexport interface LayoutSlot {\n vw: number\n offsetPx?: number\n capPx?: number\n}\n\nexport type LayoutWidths = BandValues<LayoutSlot>\n\n/**\n * A responsive value's reading at every band, cascading upwards the way MUI\n * applies one: a band with no value of its own takes the nearest narrower\n * band's. A scalar applies everywhere, an array is MUI's breakpoint array,\n * and keys that are not bands — a dark-scheme slice, a raw media query — are\n * not read.\n */\nfunction bandValues(value: unknown): BandValues<unknown> {\n if (value === undefined || value === null || value === '') return {}\n let stated: BandValues<unknown>\n if (Array.isArray(value)) {\n stated = {}\n value.forEach((entry, index) => {\n if (index < BANDS.length && entry !== null && entry !== undefined) {\n stated[BANDS[index]] = entry\n }\n })\n } else if (typeof value === 'object') {\n stated = {}\n for (const band of BANDS) {\n const entry = (value as Record<string, unknown>)[band]\n if (entry !== undefined && entry !== null) stated[band] = entry\n }\n } else {\n return Object.fromEntries(BANDS.map((band) => [band, value]))\n }\n const out: BandValues<unknown> = {}\n let current: unknown\n for (const band of BANDS) {\n if (stated[band] !== undefined) current = stated[band]\n if (current !== undefined) out[band] = current\n }\n return out\n}\n\n/**\n * A CSS sizing value as MUI's `sx` reads it: a number in (0, 1] is a share of\n * the parent, any other number is pixels, and a string may be either unit.\n */\ntype Length =\n | { kind: 'px'; value: number }\n | { kind: 'fraction'; value: number }\n | { kind: 'vw'; value: number }\n | { kind: 'auto' }\n\nfunction length(value: unknown): Length | undefined {\n if (typeof value === 'number' && Number.isFinite(value)) {\n if (value > 0 && value <= 1) return { kind: 'fraction', value }\n return value > 1 ? { kind: 'px', value } : undefined\n }\n if (typeof value !== 'string') return undefined\n const text = value.trim()\n if (text === 'auto') return { kind: 'auto' }\n const match = /^(\\d+(?:\\.\\d+)?)(px|%|vw)$/.exec(text)\n if (!match) return undefined\n const amount = Number(match[1])\n if (!(amount > 0)) return undefined\n if (match[2] === 'px') return { kind: 'px', value: amount }\n if (match[2] === 'vw') return { kind: 'vw', value: amount }\n return { kind: 'fraction', value: amount / 100 }\n}\n\n/** A node's `sx` as one plain object: an array of objects merged in order. */\nfunction plainSx(sx: unknown): Record<string, unknown> {\n if (Array.isArray(sx)) {\n return Object.assign(\n {},\n ...sx.filter(\n (entry) => entry && typeof entry === 'object' && !Array.isArray(entry),\n ),\n )\n }\n return sx && typeof sx === 'object' ? (sx as Record<string, unknown>) : {}\n}\n\nconst usable = (value: unknown): value is number =>\n typeof value === 'number' && Number.isFinite(value) && value > 0\n\n/**\n * The length the element itself states per band, as a `sizes` length: a\n * pixel or viewport width, or a pixel height under `width: auto` at the\n * asset's shape. Per band, so a responsive value is read the way MUI applies\n * it; a band where the element states nothing usable is left to the layout.\n */\nfunction ownLengths(input: ImageSizesInput): BandValues<string> {\n const sx = plainSx(input.sx)\n const widths = bandValues(input.width)\n const heights = bandValues(input.height)\n const sxWidths = bandValues(sx['width'])\n const sxHeights = bandValues(sx['height'])\n const ratio =\n usable(input.intrinsicWidth) && usable(input.intrinsicHeight)\n ? input.intrinsicWidth / input.intrinsicHeight\n : undefined\n const out: BandValues<string> = {}\n for (const band of BANDS) {\n const width = length(sxWidths[band] ?? widths[band])\n if (width?.kind === 'px') {\n out[band] = `${Math.round(width.value)}px`\n continue\n }\n if (width?.kind === 'vw') {\n out[band] = `${Math.round(width.value * 10) / 10}vw`\n continue\n }\n const height = length(sxHeights[band] ?? heights[band])\n if (width?.kind === 'auto' && height?.kind === 'px' && ratio) {\n out[band] = `${Math.round(height.value * ratio)}px`\n }\n }\n return out\n}\n\n/** A layout slot as a `sizes` length for a band. */\nfunction slotLength(band: Band, slot: LayoutSlot): string {\n // A cap that binds across the whole band — the page is at least the band's\n // minimum wide, so the slot is the cap from its first pixel — is the\n // definite length. Below that, the share of the viewport is the answer, and\n // it can only overstate the slot by the gutters.\n const offset = slot.offsetPx ?? 0\n // A pixel of slack absorbs the rounding of the share and the cap.\n if (\n slot.capPx !== undefined &&\n slot.capPx <=\n (slot.vw / 100) * Aglyn.RENDERED_WIDTH_BAND_MIN[band] - offset + 1\n ) {\n return `${slot.capPx}px`\n }\n return offset >= 1 ? `calc(${slot.vw}vw - ${offset}px)` : `${slot.vw}vw`\n}\n\n/**\n * What was measured, with the layout's statement filling the bands the\n * Besigner never saw.\n *\n * A measured band wins. Above it, the layout's value is used only where it\n * says something NEW — a value that differs from the one the layout gave the\n * measured band. A value it merely carried up from the measured band's span\n * is the same slot measured more precisely, so the measurement carries\n * instead: a cell measured at 28% on a large screen is not 33% on a wider\n * one just because its span did not change.\n */\nfunction combineBandLengths(\n measured: Aglyn.RenderedWidths,\n layout: BandValues<string>,\n): BandValues<string> {\n const known: BandValues<string> = {}\n let lastMeasured: string | undefined\n let layoutWhenMeasured: string | undefined\n for (const band of BANDS) {\n const value = measured[band]\n if (value !== undefined) {\n known[band] = `${value}vw`\n lastMeasured = known[band]\n layoutWhenMeasured = layout[band]\n continue\n }\n const stated = layout[band]\n if (stated !== undefined && stated !== layoutWhenMeasured) {\n known[band] = stated\n } else if (lastMeasured !== undefined) {\n known[band] = lastMeasured\n }\n }\n return known\n}\n\n/** Whether a known length is a small slot. */\nfunction isSmall(css: string): boolean {\n if (css.endsWith('px') && !css.startsWith('calc(')) {\n return Number.parseFloat(css) <= SMALL_IMAGE_MAX_PX\n }\n const vw = /(\\d+(?:\\.\\d+)?)vw/.exec(css)\n return vw ? Number(vw[1]) < SMALL_IMAGE_MAX_PERCENT : false\n}\n\n/** The `sizes` an Image element should carry. See the module note. */\nexport function imageSizes(input: ImageSizesInput): ImageSizes {\n const authored = typeof input.sizes === 'string' ? input.sizes.trim() : ''\n if (authored) return { sizes: authored, small: false }\n const layout: BandValues<string> = {}\n for (const band of BANDS) {\n const slot = input.layoutWidths?.[band]\n if (slot) layout[band] = slotLength(band, slot)\n }\n const known = {\n ...combineBandLengths(\n Aglyn.parseRenderedWidths(input.renderedWidths),\n layout,\n ),\n ...ownLengths(input),\n }\n const values = Object.values(known) as string[]\n return {\n sizes: Aglyn.sizesFromBandLengths(known),\n small: values.length > 0 && values.every(isSmall),\n }\n}\n\n/** No published page nests deeper; a walk past this is following a cycle. */\nconst MAX_LAYOUT_DEPTH = 256\n\n/** The Grid element's persisted component id (`grid.tsx`). */\nconst GRID_COMPONENT_ID = 'muiGrid'\n\n/** The Container element's persisted component id (`container.ts`). */\nconst CONTAINER_COMPONENT_ID = 'muiContainer'\n\n/**\n * A Container's `maxWidth` keys in pixels: MUI's, `xs` floored at 444px. An\n * absent or cleared value is MUI's own `lg` (the element drops a cleared one\n * so MUI's default applies, AGL-1435); `false` caps nothing.\n */\nconst CONTAINER_MAX_WIDTHS: Readonly<Record<string, number>> = {\n xs: 444,\n sm: 600,\n md: 900,\n lg: 1200,\n xl: 1536,\n}\n\n/**\n * A Container's side gutters: MUI's `theme.spacing(2)` a side on a phone and\n * `theme.spacing(3)` from `sm` up.\n */\nconst CONTAINER_GUTTER_PX: Readonly<Record<Band, number>> = {\n xs: 16,\n sm: 24,\n md: 24,\n lg: 24,\n xl: 24,\n}\n\n/** One theme spacing unit; MUI's default, which `sx` gaps are counted in. */\nconst SPACING_PX = 8\n\n/** A gap in pixels: a number is theme spacing units, a string must be px. */\nfunction gapPixels(value: unknown): number {\n if (typeof value === 'number' && Number.isFinite(value) && value > 0) {\n return value * SPACING_PX\n }\n const text = String(value ?? '').trim()\n if (/^\\d+(?:\\.\\d+)?$/.test(text)) return Number(text) * SPACING_PX\n const match = /^(\\d+(?:\\.\\d+)?)px$/.exec(text)\n return match ? Number(match[1]) : 0\n}\n\n/** A node as the canvas holds it, as far as this walk reads it. */\nexport interface LayoutNode {\n componentId?: string\n props?: Record<string, unknown>\n resolvedProps?: Record<string, unknown>\n sx?: unknown\n parent?: LayoutNode | undefined\n}\n\nconst propsOf = (node: LayoutNode | undefined) =>\n node?.resolvedProps ?? node?.props ?? {}\n\n/** A Grid cell's span at each band: a column count, or `null` for auto/grow. */\nfunction gridSpanPerBand(size: unknown): BandValues<number | null> {\n if (size === undefined || size === null || size === '') return {}\n const span = parseBreakpointSpan(size as string | number)\n if (span.raw !== undefined) return {}\n const read = (value: unknown) => (typeof value === 'number' ? value : null)\n if (span.base !== undefined) {\n const value = read(span.base)\n return Object.fromEntries(BANDS.map((band) => [band, value]))\n }\n const values: Record<string, unknown> = {}\n for (const [band, value] of Object.entries(span.values ?? {})) {\n values[band] = read(value)\n }\n return bandValues(values) as BandValues<number | null>\n}\n\nconst FR_TRACK = /^(?:1fr|minmax\\(\\s*0(?:px)?\\s*,\\s*1fr\\s*\\))$/\nconst REPEAT_TRACKS =\n /^repeat\\(\\s*(\\d+)\\s*,\\s*(1fr|minmax\\(\\s*0(?:px)?\\s*,\\s*1fr\\s*\\))\\s*\\)$/\n\n/**\n * The equal tracks a `gridTemplateColumns` value lays out: `repeat(3, 1fr)`,\n * or the same written out, `1fr 1fr 1fr` — and a single `1fr`, which is one\n * column the full width. Anything else (fixed tracks, `auto-fill`) is not an\n * equal split this can state.\n */\nfunction equalTracks(value: unknown): number | undefined {\n const text = String(value ?? '').trim()\n const repeat = REPEAT_TRACKS.exec(text)\n if (repeat) return Number(repeat[1]) > 0 ? Number(repeat[1]) : undefined\n const tracks = text.split(/\\s+(?![^(]*\\))/).filter(Boolean)\n return tracks.length && tracks.every((track) => FR_TRACK.test(track))\n ? tracks.length\n : undefined\n}\n\n/** How many tracks a grid child spans, from its own `gridColumn`. */\nfunction spannedTracks(value: unknown, tracks: number): number {\n const text = String(value ?? '').trim()\n const span = /^span\\s+(\\d+)$/.exec(text)\n if (span) return Math.min(Number(span[1]), tracks)\n if (/^1\\s*\\/\\s*-1$/.test(text)) return tracks\n return 1\n}\n\n/**\n * The slot the layout around an image gives it, per band, from what the\n * layout STATES rather than what anyone measured — computed from the node\n * tree a page renders, so a published page has it on the server with nothing\n * re-saved. Walking up from the image:\n *\n * - every **Grid cell** it sits in takes its responsive span of its row's\n * columns (`xs:12 md:4` is a third from `md` up), less its share of the\n * row's spacing;\n * - every **CSS grid** of equal tracks (`repeat(3, 1fr)`, per breakpoint)\n * gives each child one track, or the tracks its `gridColumn` spans, less\n * its share of the gap;\n * - every **width or max width** given as a share of the parent shrinks the\n * slot by it, and one given in pixels caps it;\n * - every **Container** takes its gutters off and caps it at its max width.\n *\n * Each step maps the parent's width to the child's as `share × parent −\n * offset`, so they compose: a third of a half is a sixth, and a gap inside a\n * capped Container is still a gap. The answer per band is `min(vw% − offset,\n * cap)`. A band is answered only when something stated it and nothing between\n * the image and the page made it unknowable — an `auto` or `grow` Grid cell is\n * sized by its content, so a band where any cell is one has no answer here.\n * Theme spacing is taken at MUI's 8px, and anything this does not model\n * (padding on an ordinary Box, a flex row) is left in, so a guess errs wide:\n * a slightly larger candidate, never a blurry one.\n *\n * The same function serves the Besigner canvas and the published render; the\n * tree differs only in that the canvas has not grafted reusable components or\n * expanded repeats, which the measurement covers there.\n */\nexport function layoutBandWidths(\n node: LayoutNode | undefined,\n): LayoutWidths {\n /** Per band, the image's width as `share × W − offset` of the ancestor W. */\n const share: BandValues<number | null> = {}\n const offset: BandValues<number> = {}\n const cap: BandValues<number> = {}\n let stated = false\n const known = (band: Band) => share[band] !== null\n /** The child takes `factor × parent − minus`. */\n const step = (band: Band, factor: number | null, minus = 0) => {\n if (!known(band)) return\n if (factor === null) {\n share[band] = null\n return\n }\n const k = share[band] ?? 1\n offset[band] = (offset[band] ?? 0) + k * minus\n share[band] = k * factor\n }\n /** The child is never wider than `pixels`. */\n const capAt = (band: Band, pixels: number) => {\n if (!known(band)) return\n const scaled = (share[band] ?? 1) * pixels - (offset[band] ?? 0)\n cap[band] = Math.min(cap[band] ?? Infinity, scaled)\n }\n /** Width and max width as a share or a cap, from a node's own styles. */\n const applySizing = (target: LayoutNode, includeWidth: boolean) => {\n const sx = plainSx(target.sx)\n for (const key of includeWidth ? ['width', 'maxWidth'] : ['maxWidth']) {\n const values = bandValues(sx[key])\n for (const band of BANDS) {\n const value = length(values[band])\n if (value?.kind === 'fraction') {\n step(band, Math.min(value.value, 1))\n stated = true\n } else if (value?.kind === 'px') {\n capAt(band, value.value)\n stated = true\n }\n }\n }\n }\n // The image's own max width caps it. Its own pixel or viewport width is read\n // as its own stated length (`ownLengths`), not as layout — but a width given\n // as a share of its slot is a share of what the layout below states, so it\n // scales that slot. It is NOT clamped at 100% the way an ancestor's is: an\n // image set wider than its cell (`118%`, pulled out with a negative margin)\n // really paints that wide, and a `sizes` of the cell alone downloads a\n // candidate the box then upscales (AGL-3715).\n if (node) {\n applySizing(node, false)\n const sx = plainSx(node.sx)\n const widths = bandValues(sx['width'] ?? propsOf(node)['width'])\n for (const band of BANDS) {\n const value = length(widths[band])\n if (value?.kind === 'fraction' && value.value !== 1) {\n step(band, value.value)\n stated = true\n }\n }\n }\n let child = node\n // Stored pages name the root as its own parent (`parentId: \"_@_\"`), so a\n // walk that only stops at a missing parent never ends (AGL-3565). Stop at\n // any node already visited, and never climb further than a page can nest.\n const visited = new Set<LayoutNode>(node ? [node] : [])\n let depth = 0\n for (\n let current = node?.parent;\n current && !visited.has(current) && depth < MAX_LAYOUT_DEPTH;\n current = current.parent, depth += 1\n ) {\n visited.add(current)\n const props = propsOf(current)\n if (current.componentId === GRID_COMPONENT_ID) {\n const spans = gridSpanPerBand(props['size'])\n if (Object.keys(spans).length) {\n const row = current.parent\n const rowProps = row?.componentId === GRID_COMPONENT_ID ? propsOf(row) : {}\n const columns = Number(rowProps['columns'])\n const total = columns > 0 ? columns : 12\n const spacing = bandValues(\n rowProps['columnSpacing'] ?? rowProps['spacing'],\n )\n stated = true\n for (const band of BANDS) {\n const span = spans[band]\n if (span === undefined || span === null) {\n step(band, null)\n continue\n }\n const portion = Math.min(span / total, 1)\n step(band, portion, gapPixels(spacing[band]) * (1 - portion))\n }\n }\n }\n const sx = plainSx(current.sx)\n const templates = bandValues(sx['gridTemplateColumns'])\n const gaps = bandValues(sx['columnGap'] ?? sx['gap'])\n for (const band of BANDS) {\n const tracks = equalTracks(templates[band])\n if (tracks === undefined) continue\n const spanned = spannedTracks(\n bandValues(plainSx(child?.sx)['gridColumn'])[band],\n tracks,\n )\n const portion = spanned / tracks\n step(band, portion, gapPixels(gaps[band]) * (1 - portion))\n stated = true\n }\n applySizing(current, true)\n if (current.componentId === CONTAINER_COMPONENT_ID) {\n const maxWidth = props['maxWidth']\n const key =\n maxWidth === undefined || maxWidth === null || maxWidth === ''\n ? 'lg'\n : maxWidth\n const pixels =\n typeof key === 'string' ? CONTAINER_MAX_WIDTHS[key] : undefined\n for (const band of BANDS) {\n const gutters = props['disableGutters']\n ? 0\n : 2 * CONTAINER_GUTTER_PX[band]\n // The gutters come off whatever the page is; the cap is the max width\n // less the same gutters, since MUI pads inside the max width.\n if (pixels) capAt(band, pixels - gutters)\n step(band, 1, gutters)\n }\n stated = true\n }\n child = current\n }\n if (!stated) return {}\n const widths: LayoutWidths = {}\n for (const band of BANDS) {\n const fraction = share[band] === undefined ? 1 : share[band]\n if (typeof fraction !== 'number' || !(fraction > 0)) continue\n const minus = Math.round(offset[band] ?? 0)\n const capPx = cap[band]\n widths[band] = {\n vw: Math.round(fraction * 1000) / 10,\n ...(minus >= 1 ? { offsetPx: minus } : {}),\n ...(capPx !== undefined && Number.isFinite(capPx)\n ? { capPx: Math.round(capPx) }\n : {}),\n }\n }\n return widths\n}\n"],"names":["Aglyn","parseBreakpointSpan","SMALL_IMAGE_MAX_PX","SMALL_IMAGE_MAX_PERCENT","BANDS","RENDERED_WIDTH_BANDS","bandValues","value","undefined","stated","Array","isArray","forEach","entry","index","length","band","Object","fromEntries","map","out","current","Number","isFinite","kind","text","trim","match","exec","amount","plainSx","sx","assign","filter","usable","ownLengths","input","widths","width","heights","height","sxWidths","sxHeights","ratio","intrinsicWidth","intrinsicHeight","Math","round","slotLength","slot","offset","offsetPx","capPx","vw","RENDERED_WIDTH_BAND_MIN","combineBandLengths","measured","layout","known","lastMeasured","layoutWhenMeasured","isSmall","css","endsWith","startsWith","parseFloat","imageSizes","authored","sizes","small","layoutWidths","parseRenderedWidths","renderedWidths","values","sizesFromBandLengths","every","MAX_LAYOUT_DEPTH","GRID_COMPONENT_ID","CONTAINER_COMPONENT_ID","CONTAINER_MAX_WIDTHS","xs","sm","md","lg","xl","CONTAINER_GUTTER_PX","SPACING_PX","gapPixels","String","test","propsOf","node","resolvedProps","props","gridSpanPerBand","size","span","raw","read","base","entries","FR_TRACK","REPEAT_TRACKS","equalTracks","repeat","tracks","split","Boolean","track","spannedTracks","min","layoutBandWidths","share","cap","step","factor","minus","k","capAt","pixels","scaled","Infinity","applySizing","target","includeWidth","key","child","visited","Set","depth","parent","has","add","componentId","spans","keys","rowProps","row","columns","total","spacing","portion","templates","gaps","spanned","maxWidth","gutters","fraction"],"mappings":";AAAA;;;;;;;;;;;;;;;CAeC,GAED,YAAYA,WAAW,eAAc;AACrC,SAASC,mBAAmB,QAAQ,2BAA0B;AA0E9D,8DAA8D,GAC9D,OAAO,MAAMC,qBAAqB,IAAG;AAErC,8EAA8E,GAC9E,OAAO,MAAMC,0BAA0B,GAAE;AAKzC,MAAMC,QAAQJ,MAAMK,oBAAoB;AAexC;;;;;;CAMC,GACD,SAASC,WAAWC,KAAc;IAChC,IAAIA,UAAUC,aAAaD,UAAU,QAAQA,UAAU,IAAI,OAAO,CAAC;IACnE,IAAIE;IACJ,IAAIC,MAAMC,OAAO,CAACJ,QAAQ;QACxBE,SAAS,CAAC;QACVF,MAAMK,OAAO,CAAC,CAACC,OAAOC;YACpB,IAAIA,QAAQV,MAAMW,MAAM,IAAIF,UAAU,QAAQA,UAAUL,WAAW;gBACjEC,MAAM,CAACL,KAAK,CAACU,MAAM,CAAC,GAAGD;YACzB;QACF;IACF,OAAO,IAAI,OAAON,UAAU,UAAU;QACpCE,SAAS,CAAC;QACV,KAAK,MAAMO,QAAQZ,MAAO;YACxB,MAAMS,QAAQ,AAACN,KAAiC,CAACS,KAAK;YACtD,IAAIH,UAAUL,aAAaK,UAAU,MAAMJ,MAAM,CAACO,KAAK,GAAGH;QAC5D;IACF,OAAO;QACL,OAAOI,OAAOC,WAAW,CAACd,MAAMe,GAAG,CAAC,CAACH,OAAS;gBAACA;gBAAMT;aAAM;IAC7D;IACA,MAAMa,MAA2B,CAAC;IAClC,IAAIC;IACJ,KAAK,MAAML,QAAQZ,MAAO;QACxB,IAAIK,MAAM,CAACO,KAAK,KAAKR,WAAWa,UAAUZ,MAAM,CAACO,KAAK;QACtD,IAAIK,YAAYb,WAAWY,GAAG,CAACJ,KAAK,GAAGK;IACzC;IACA,OAAOD;AACT;AAYA,SAASL,OAAOR,KAAc;IAC5B,IAAI,OAAOA,UAAU,YAAYe,OAAOC,QAAQ,CAAChB,QAAQ;QACvD,IAAIA,QAAQ,KAAKA,SAAS,GAAG,OAAO;YAAEiB,MAAM;YAAYjB;QAAM;QAC9D,OAAOA,QAAQ,IAAI;YAAEiB,MAAM;YAAMjB;QAAM,IAAIC;IAC7C;IACA,IAAI,OAAOD,UAAU,UAAU,OAAOC;IACtC,MAAMiB,OAAOlB,MAAMmB,IAAI;IACvB,IAAID,SAAS,QAAQ,OAAO;QAAED,MAAM;IAAO;IAC3C,MAAMG,QAAQ,6BAA6BC,IAAI,CAACH;IAChD,IAAI,CAACE,OAAO,OAAOnB;IACnB,MAAMqB,SAASP,OAAOK,KAAK,CAAC,EAAE;IAC9B,IAAI,CAAEE,CAAAA,SAAS,CAAA,GAAI,OAAOrB;IAC1B,IAAImB,KAAK,CAAC,EAAE,KAAK,MAAM,OAAO;QAAEH,MAAM;QAAMjB,OAAOsB;IAAO;IAC1D,IAAIF,KAAK,CAAC,EAAE,KAAK,MAAM,OAAO;QAAEH,MAAM;QAAMjB,OAAOsB;IAAO;IAC1D,OAAO;QAAEL,MAAM;QAAYjB,OAAOsB,SAAS;IAAI;AACjD;AAEA,4EAA4E,GAC5E,SAASC,QAAQC,EAAW;IAC1B,IAAIrB,MAAMC,OAAO,CAACoB,KAAK;QACrB,OAAOd,OAAOe,MAAM,CAClB,CAAC,MACED,GAAGE,MAAM,CACV,CAACpB,QAAUA,SAAS,OAAOA,UAAU,YAAY,CAACH,MAAMC,OAAO,CAACE;IAGtE;IACA,OAAOkB,MAAM,OAAOA,OAAO,WAAYA,KAAiC,CAAC;AAC3E;AAEA,MAAMG,SAAS,CAAC3B,QACd,OAAOA,UAAU,YAAYe,OAAOC,QAAQ,CAAChB,UAAUA,QAAQ;AAEjE;;;;;CAKC,GACD,SAAS4B,WAAWC,KAAsB;IACxC,MAAML,KAAKD,QAAQM,MAAML,EAAE;IAC3B,MAAMM,SAAS/B,WAAW8B,MAAME,KAAK;IACrC,MAAMC,UAAUjC,WAAW8B,MAAMI,MAAM;IACvC,MAAMC,WAAWnC,WAAWyB,EAAE,CAAC,QAAQ;IACvC,MAAMW,YAAYpC,WAAWyB,EAAE,CAAC,SAAS;IACzC,MAAMY,QACJT,OAAOE,MAAMQ,cAAc,KAAKV,OAAOE,MAAMS,eAAe,IACxDT,MAAMQ,cAAc,GAAGR,MAAMS,eAAe,GAC5CrC;IACN,MAAMY,MAA0B,CAAC;IACjC,KAAK,MAAMJ,QAAQZ,MAAO;YACHqC,gBASCC;QATtB,MAAMJ,QAAQvB,QAAO0B,iBAAAA,QAAQ,CAACzB,KAAK,YAAdyB,iBAAkBJ,MAAM,CAACrB,KAAK;QACnD,IAAIsB,CAAAA,yBAAAA,MAAOd,IAAI,MAAK,MAAM;YACxBJ,GAAG,CAACJ,KAAK,GAAG,GAAG8B,KAAKC,KAAK,CAACT,MAAM/B,KAAK,EAAE,EAAE,CAAC;YAC1C;QACF;QACA,IAAI+B,CAAAA,yBAAAA,MAAOd,IAAI,MAAK,MAAM;YACxBJ,GAAG,CAACJ,KAAK,GAAG,GAAG8B,KAAKC,KAAK,CAACT,MAAM/B,KAAK,GAAG,MAAM,GAAG,EAAE,CAAC;YACpD;QACF;QACA,MAAMiC,SAASzB,QAAO2B,kBAAAA,SAAS,CAAC1B,KAAK,YAAf0B,kBAAmBH,OAAO,CAACvB,KAAK;QACtD,IAAIsB,CAAAA,yBAAAA,MAAOd,IAAI,MAAK,UAAUgB,CAAAA,0BAAAA,OAAQhB,IAAI,MAAK,QAAQmB,OAAO;YAC5DvB,GAAG,CAACJ,KAAK,GAAG,GAAG8B,KAAKC,KAAK,CAACP,OAAOjC,KAAK,GAAGoC,OAAO,EAAE,CAAC;QACrD;IACF;IACA,OAAOvB;AACT;AAEA,kDAAkD,GAClD,SAAS4B,WAAWhC,IAAU,EAAEiC,IAAgB;QAK/BA;IAJf,2EAA2E;IAC3E,qEAAqE;IACrE,4EAA4E;IAC5E,iDAAiD;IACjD,MAAMC,UAASD,iBAAAA,KAAKE,QAAQ,YAAbF,iBAAiB;IAChC,kEAAkE;IAClE,IACEA,KAAKG,KAAK,KAAK5C,aACfyC,KAAKG,KAAK,IACR,AAACH,KAAKI,EAAE,GAAG,MAAOrD,MAAMsD,uBAAuB,CAACtC,KAAK,GAAGkC,SAAS,GACnE;QACA,OAAO,GAAGD,KAAKG,KAAK,CAAC,EAAE,CAAC;IAC1B;IACA,OAAOF,UAAU,IAAI,CAAC,KAAK,EAAED,KAAKI,EAAE,CAAC,KAAK,EAAEH,OAAO,GAAG,CAAC,GAAG,GAAGD,KAAKI,EAAE,CAAC,EAAE,CAAC;AAC1E;AAEA;;;;;;;;;;CAUC,GACD,SAASE,mBACPC,QAA8B,EAC9BC,MAA0B;IAE1B,MAAMC,QAA4B,CAAC;IACnC,IAAIC;IACJ,IAAIC;IACJ,KAAK,MAAM5C,QAAQZ,MAAO;QACxB,MAAMG,QAAQiD,QAAQ,CAACxC,KAAK;QAC5B,IAAIT,UAAUC,WAAW;YACvBkD,KAAK,CAAC1C,KAAK,GAAG,GAAGT,MAAM,EAAE,CAAC;YAC1BoD,eAAeD,KAAK,CAAC1C,KAAK;YAC1B4C,qBAAqBH,MAAM,CAACzC,KAAK;YACjC;QACF;QACA,MAAMP,SAASgD,MAAM,CAACzC,KAAK;QAC3B,IAAIP,WAAWD,aAAaC,WAAWmD,oBAAoB;YACzDF,KAAK,CAAC1C,KAAK,GAAGP;QAChB,OAAO,IAAIkD,iBAAiBnD,WAAW;YACrCkD,KAAK,CAAC1C,KAAK,GAAG2C;QAChB;IACF;IACA,OAAOD;AACT;AAEA,4CAA4C,GAC5C,SAASG,QAAQC,GAAW;IAC1B,IAAIA,IAAIC,QAAQ,CAAC,SAAS,CAACD,IAAIE,UAAU,CAAC,UAAU;QAClD,OAAO1C,OAAO2C,UAAU,CAACH,QAAQ5D;IACnC;IACA,MAAMmD,KAAK,oBAAoBzB,IAAI,CAACkC;IACpC,OAAOT,KAAK/B,OAAO+B,EAAE,CAAC,EAAE,IAAIlD,0BAA0B;AACxD;AAEA,oEAAoE,GACpE,OAAO,SAAS+D,WAAW9B,KAAsB;IAC/C,MAAM+B,WAAW,OAAO/B,MAAMgC,KAAK,KAAK,WAAWhC,MAAMgC,KAAK,CAAC1C,IAAI,KAAK;IACxE,IAAIyC,UAAU,OAAO;QAAEC,OAAOD;QAAUE,OAAO;IAAM;IACrD,MAAMZ,SAA6B,CAAC;IACpC,KAAK,MAAMzC,QAAQZ,MAAO;YACXgC;QAAb,MAAMa,QAAOb,sBAAAA,MAAMkC,YAAY,qBAAlBlC,mBAAoB,CAACpB,KAAK;QACvC,IAAIiC,MAAMQ,MAAM,CAACzC,KAAK,GAAGgC,WAAWhC,MAAMiC;IAC5C;IACA,MAAMS,QAAQ,aACTH,mBACDvD,MAAMuE,mBAAmB,CAACnC,MAAMoC,cAAc,GAC9Cf,SAECtB,WAAWC;IAEhB,MAAMqC,SAASxD,OAAOwD,MAAM,CAACf;IAC7B,OAAO;QACLU,OAAOpE,MAAM0E,oBAAoB,CAAChB;QAClCW,OAAOI,OAAO1D,MAAM,GAAG,KAAK0D,OAAOE,KAAK,CAACd;IAC3C;AACF;AAEA,2EAA2E,GAC3E,MAAMe,mBAAmB;AAEzB,4DAA4D,GAC5D,MAAMC,oBAAoB;AAE1B,qEAAqE,GACrE,MAAMC,yBAAyB;AAE/B;;;;CAIC,GACD,MAAMC,uBAAyD;IAC7DC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;AACN;AAEA;;;CAGC,GACD,MAAMC,sBAAsD;IAC1DL,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;AACN;AAEA,2EAA2E,GAC3E,MAAME,aAAa;AAEnB,2EAA2E,GAC3E,SAASC,UAAUhF,KAAc;IAC/B,IAAI,OAAOA,UAAU,YAAYe,OAAOC,QAAQ,CAAChB,UAAUA,QAAQ,GAAG;QACpE,OAAOA,QAAQ+E;IACjB;IACA,MAAM7D,OAAO+D,OAAOjF,gBAAAA,QAAS,IAAImB,IAAI;IACrC,IAAI,kBAAkB+D,IAAI,CAAChE,OAAO,OAAOH,OAAOG,QAAQ6D;IACxD,MAAM3D,QAAQ,sBAAsBC,IAAI,CAACH;IACzC,OAAOE,QAAQL,OAAOK,KAAK,CAAC,EAAE,IAAI;AACpC;AAWA,MAAM+D,UAAU,CAACC;QACfA;YAAAA,gBAAAA,wBAAAA,KAAMC,aAAa,oBAAID,wBAAAA,KAAME,KAAK,YAAlCF,OAAsC,CAAC;;AAEzC,8EAA8E,GAC9E,SAASG,gBAAgBC,IAAa;QAUOC;IAT3C,IAAID,SAASvF,aAAauF,SAAS,QAAQA,SAAS,IAAI,OAAO,CAAC;IAChE,MAAMC,OAAO/F,oBAAoB8F;IACjC,IAAIC,KAAKC,GAAG,KAAKzF,WAAW,OAAO,CAAC;IACpC,MAAM0F,OAAO,CAAC3F,QAAoB,OAAOA,UAAU,WAAWA,QAAQ;IACtE,IAAIyF,KAAKG,IAAI,KAAK3F,WAAW;QAC3B,MAAMD,QAAQ2F,KAAKF,KAAKG,IAAI;QAC5B,OAAOlF,OAAOC,WAAW,CAACd,MAAMe,GAAG,CAAC,CAACH,OAAS;gBAACA;gBAAMT;aAAM;IAC7D;IACA,MAAMkE,SAAkC,CAAC;IACzC,KAAK,MAAM,CAACzD,MAAMT,MAAM,IAAIU,OAAOmF,OAAO,EAACJ,eAAAA,KAAKvB,MAAM,YAAXuB,eAAe,CAAC,GAAI;QAC7DvB,MAAM,CAACzD,KAAK,GAAGkF,KAAK3F;IACtB;IACA,OAAOD,WAAWmE;AACpB;AAEA,MAAM4B,WAAW;AACjB,MAAMC,gBACJ;AAEF;;;;;CAKC,GACD,SAASC,YAAYhG,KAAc;IACjC,MAAMkB,OAAO+D,OAAOjF,gBAAAA,QAAS,IAAImB,IAAI;IACrC,MAAM8E,SAASF,cAAc1E,IAAI,CAACH;IAClC,IAAI+E,QAAQ,OAAOlF,OAAOkF,MAAM,CAAC,EAAE,IAAI,IAAIlF,OAAOkF,MAAM,CAAC,EAAE,IAAIhG;IAC/D,MAAMiG,SAAShF,KAAKiF,KAAK,CAAC,kBAAkBzE,MAAM,CAAC0E;IACnD,OAAOF,OAAO1F,MAAM,IAAI0F,OAAO9B,KAAK,CAAC,CAACiC,QAAUP,SAASZ,IAAI,CAACmB,UAC1DH,OAAO1F,MAAM,GACbP;AACN;AAEA,mEAAmE,GACnE,SAASqG,cAActG,KAAc,EAAEkG,MAAc;IACnD,MAAMhF,OAAO+D,OAAOjF,gBAAAA,QAAS,IAAImB,IAAI;IACrC,MAAMsE,OAAO,iBAAiBpE,IAAI,CAACH;IACnC,IAAIuE,MAAM,OAAOlD,KAAKgE,GAAG,CAACxF,OAAO0E,IAAI,CAAC,EAAE,GAAGS;IAC3C,IAAI,gBAAgBhB,IAAI,CAAChE,OAAO,OAAOgF;IACvC,OAAO;AACT;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6BC,GACD,OAAO,SAASM,iBACdpB,IAA4B;IAE5B,2EAA2E,GAC3E,MAAMqB,QAAmC,CAAC;IAC1C,MAAM9D,SAA6B,CAAC;IACpC,MAAM+D,MAA0B,CAAC;IACjC,IAAIxG,SAAS;IACb,MAAMiD,QAAQ,CAAC1C,OAAegG,KAAK,CAAChG,KAAK,KAAK;IAC9C,+CAA+C,GAC/C,MAAMkG,OAAO,CAAClG,MAAYmG,QAAuBC,QAAQ,CAAC;YAM9CJ,aACM9D;QANhB,IAAI,CAACQ,MAAM1C,OAAO;QAClB,IAAImG,WAAW,MAAM;YACnBH,KAAK,CAAChG,KAAK,GAAG;YACd;QACF;QACA,MAAMqG,KAAIL,cAAAA,KAAK,CAAChG,KAAK,YAAXgG,cAAe;QACzB9D,MAAM,CAAClC,KAAK,GAAG,EAACkC,eAAAA,MAAM,CAAClC,KAAK,YAAZkC,eAAgB,KAAKmE,IAAID;QACzCJ,KAAK,CAAChG,KAAK,GAAGqG,IAAIF;IACpB;IACA,4CAA4C,GAC5C,MAAMG,QAAQ,CAACtG,MAAYuG;YAETP,aAA8B9D,cACzB+D;QAFrB,IAAI,CAACvD,MAAM1C,OAAO;QAClB,MAAMwG,SAAS,EAACR,cAAAA,KAAK,CAAChG,KAAK,YAAXgG,cAAe,KAAKO,WAAUrE,eAAAA,MAAM,CAAClC,KAAK,YAAZkC,eAAgB;QAC9D+D,GAAG,CAACjG,KAAK,GAAG8B,KAAKgE,GAAG,EAACG,YAAAA,GAAG,CAACjG,KAAK,YAATiG,YAAaQ,UAAUD;IAC9C;IACA,uEAAuE,GACvE,MAAME,cAAc,CAACC,QAAoBC;QACvC,MAAM7F,KAAKD,QAAQ6F,OAAO5F,EAAE;QAC5B,KAAK,MAAM8F,OAAOD,eAAe;YAAC;YAAS;SAAW,GAAG;YAAC;SAAW,CAAE;YACrE,MAAMnD,SAASnE,WAAWyB,EAAE,CAAC8F,IAAI;YACjC,KAAK,MAAM7G,QAAQZ,MAAO;gBACxB,MAAMG,QAAQQ,OAAO0D,MAAM,CAACzD,KAAK;gBACjC,IAAIT,CAAAA,yBAAAA,MAAOiB,IAAI,MAAK,YAAY;oBAC9B0F,KAAKlG,MAAM8B,KAAKgE,GAAG,CAACvG,MAAMA,KAAK,EAAE;oBACjCE,SAAS;gBACX,OAAO,IAAIF,CAAAA,yBAAAA,MAAOiB,IAAI,MAAK,MAAM;oBAC/B8F,MAAMtG,MAAMT,MAAMA,KAAK;oBACvBE,SAAS;gBACX;YACF;QACF;IACF;IACA,6EAA6E;IAC7E,6EAA6E;IAC7E,2EAA2E;IAC3E,2EAA2E;IAC3E,4EAA4E;IAC5E,uEAAuE;IACvE,8CAA8C;IAC9C,IAAIkF,MAAM;YAGkB5D;QAF1B2F,YAAY/B,MAAM;QAClB,MAAM5D,KAAKD,QAAQ6D,KAAK5D,EAAE;QAC1B,MAAMM,SAAS/B,YAAWyB,YAAAA,EAAE,CAAC,QAAQ,YAAXA,YAAe2D,QAAQC,KAAK,CAAC,QAAQ;QAC/D,KAAK,MAAM3E,QAAQZ,MAAO;YACxB,MAAMG,QAAQQ,OAAOsB,MAAM,CAACrB,KAAK;YACjC,IAAIT,CAAAA,yBAAAA,MAAOiB,IAAI,MAAK,cAAcjB,MAAMA,KAAK,KAAK,GAAG;gBACnD2G,KAAKlG,MAAMT,MAAMA,KAAK;gBACtBE,SAAS;YACX;QACF;IACF;IACA,IAAIqH,QAAQnC;IACZ,yEAAyE;IACzE,0EAA0E;IAC1E,0EAA0E;IAC1E,MAAMoC,UAAU,IAAIC,IAAgBrC,OAAO;QAACA;KAAK,GAAG,EAAE;IACtD,IAAIsC,QAAQ;IACZ,IACE,IAAI5G,UAAUsE,wBAAAA,KAAMuC,MAAM,EAC1B7G,WAAW,CAAC0G,QAAQI,GAAG,CAAC9G,YAAY4G,QAAQrD,kBAC5CvD,UAAUA,QAAQ6G,MAAM,EAAED,SAAS,EACnC;YA2BwBlG;QA1BxBgG,QAAQK,GAAG,CAAC/G;QACZ,MAAMwE,QAAQH,QAAQrE;QACtB,IAAIA,QAAQgH,WAAW,KAAKxD,mBAAmB;YAC7C,MAAMyD,QAAQxC,gBAAgBD,KAAK,CAAC,OAAO;YAC3C,IAAI5E,OAAOsH,IAAI,CAACD,OAAOvH,MAAM,EAAE;oBAM3ByH;gBALF,MAAMC,MAAMpH,QAAQ6G,MAAM;gBAC1B,MAAMM,WAAWC,CAAAA,uBAAAA,IAAKJ,WAAW,MAAKxD,oBAAoBa,QAAQ+C,OAAO,CAAC;gBAC1E,MAAMC,UAAUpH,OAAOkH,QAAQ,CAAC,UAAU;gBAC1C,MAAMG,QAAQD,UAAU,IAAIA,UAAU;gBACtC,MAAME,UAAUtI,YACdkI,0BAAAA,QAAQ,CAAC,gBAAgB,YAAzBA,0BAA6BA,QAAQ,CAAC,UAAU;gBAElD/H,SAAS;gBACT,KAAK,MAAMO,QAAQZ,MAAO;oBACxB,MAAM4F,OAAOsC,KAAK,CAACtH,KAAK;oBACxB,IAAIgF,SAASxF,aAAawF,SAAS,MAAM;wBACvCkB,KAAKlG,MAAM;wBACX;oBACF;oBACA,MAAM6H,UAAU/F,KAAKgE,GAAG,CAACd,OAAO2C,OAAO;oBACvCzB,KAAKlG,MAAM6H,SAAStD,UAAUqD,OAAO,CAAC5H,KAAK,IAAK,CAAA,IAAI6H,OAAM;gBAC5D;YACF;QACF;QACA,MAAM9G,KAAKD,QAAQT,QAAQU,EAAE;QAC7B,MAAM+G,YAAYxI,WAAWyB,EAAE,CAAC,sBAAsB;QACtD,MAAMgH,OAAOzI,YAAWyB,gBAAAA,EAAE,CAAC,YAAY,YAAfA,gBAAmBA,EAAE,CAAC,MAAM;QACpD,KAAK,MAAMf,QAAQZ,MAAO;YACxB,MAAMqG,SAASF,YAAYuC,SAAS,CAAC9H,KAAK;YAC1C,IAAIyF,WAAWjG,WAAW;YAC1B,MAAMwI,UAAUnC,cACdvG,WAAWwB,QAAQgG,yBAAAA,MAAO/F,EAAE,CAAC,CAAC,aAAa,CAAC,CAACf,KAAK,EAClDyF;YAEF,MAAMoC,UAAUG,UAAUvC;YAC1BS,KAAKlG,MAAM6H,SAAStD,UAAUwD,IAAI,CAAC/H,KAAK,IAAK,CAAA,IAAI6H,OAAM;YACvDpI,SAAS;QACX;QACAiH,YAAYrG,SAAS;QACrB,IAAIA,QAAQgH,WAAW,KAAKvD,wBAAwB;YAClD,MAAMmE,WAAWpD,KAAK,CAAC,WAAW;YAClC,MAAMgC,MACJoB,aAAazI,aAAayI,aAAa,QAAQA,aAAa,KACxD,OACAA;YACN,MAAM1B,SACJ,OAAOM,QAAQ,WAAW9C,oBAAoB,CAAC8C,IAAI,GAAGrH;YACxD,KAAK,MAAMQ,QAAQZ,MAAO;gBACxB,MAAM8I,UAAUrD,KAAK,CAAC,iBAAiB,GACnC,IACA,IAAIR,mBAAmB,CAACrE,KAAK;gBACjC,sEAAsE;gBACtE,8DAA8D;gBAC9D,IAAIuG,QAAQD,MAAMtG,MAAMuG,SAAS2B;gBACjChC,KAAKlG,MAAM,GAAGkI;YAChB;YACAzI,SAAS;QACX;QACAqH,QAAQzG;IACV;IACA,IAAI,CAACZ,QAAQ,OAAO,CAAC;IACrB,MAAM4B,SAAuB,CAAC;IAC9B,KAAK,MAAMrB,QAAQZ,MAAO;YAGC8C;QAFzB,MAAMiG,WAAWnC,KAAK,CAAChG,KAAK,KAAKR,YAAY,IAAIwG,KAAK,CAAChG,KAAK;QAC5D,IAAI,OAAOmI,aAAa,YAAY,CAAEA,CAAAA,WAAW,CAAA,GAAI;QACrD,MAAM/B,QAAQtE,KAAKC,KAAK,EAACG,eAAAA,MAAM,CAAClC,KAAK,YAAZkC,eAAgB;QACzC,MAAME,QAAQ6D,GAAG,CAACjG,KAAK;QACvBqB,MAAM,CAACrB,KAAK,GAAG;YACbqC,IAAIP,KAAKC,KAAK,CAACoG,WAAW,QAAQ;WAC9B/B,SAAS,IAAI;YAAEjE,UAAUiE;QAAM,IAAI,CAAC,GACpChE,UAAU5C,aAAac,OAAOC,QAAQ,CAAC6B,SACvC;YAAEA,OAAON,KAAKC,KAAK,CAACK;QAAO,IAC3B,CAAC;IAET;IACA,OAAOf;AACT"}
|