@twinfinity/printing 6.0.1-ci.28952-beta → 6.0.2-beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/BuildInfo.js +3 -3
- package/dist/BuildInfo.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/layout/analyzeTemplate.js.map +1 -1
- package/dist/layout/clipUtils.js.map +1 -1
- package/dist/layout/colorConstants.js.map +1 -1
- package/dist/layout/elementKinds.js.map +1 -1
- package/dist/layout/exportDrawing.js.map +1 -1
- package/dist/layout/filters.js.map +1 -1
- package/dist/layout/geometryConstants.js.map +1 -1
- package/dist/layout/index.js.map +1 -1
- package/dist/layout/itemBuilders.js.map +1 -1
- package/dist/layout/labelsRender.js.map +1 -1
- package/dist/layout/legendConstants.js.map +1 -1
- package/dist/layout/legendRender.js.map +1 -1
- package/dist/layout/legendRows.js.map +1 -1
- package/dist/layout/legendUtils.js.map +1 -1
- package/dist/layout/metadata.js.map +1 -1
- package/dist/layout/model.js.map +1 -1
- package/dist/layout/options.js.map +1 -1
- package/dist/layout/presets.js.map +1 -1
- package/dist/layout/qrRender.js.map +1 -1
- package/dist/layout/renderDrawing.js.map +1 -1
- package/dist/layout/renderUtils.js.map +1 -1
- package/dist/layout/sectionValidation.js.map +1 -1
- package/dist/layout/templateVariables.js.map +1 -1
- package/dist/layout/typeGuards.js.map +1 -1
- package/dist/layout/types.js.map +1 -1
- package/dist/layout/utils.js.map +1 -1
- package/dist/layout/validation.js.map +1 -1
- package/dist/layout/validationHelpers.js.map +1 -1
- package/dist/layout/validationUtils.js.map +1 -1
- package/dist/layout/viewportPrep.js.map +1 -1
- package/dist/layout/viewportRender.js.map +1 -1
- package/dist/layout/viewportUtils.js.map +1 -1
- package/dist/layout/warnings.js.map +1 -1
- package/dist/printToPdf.js.map +1 -1
- package/dist/printToSvg.js.map +1 -1
- package/dist/sections.js.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +2 -2
- package/src/BuildInfo.ts +41 -41
- package/src/index.ts +10 -10
- package/src/layout/analyzeTemplate.ts +218 -218
- package/src/layout/clipUtils.ts +193 -193
- package/src/layout/colorConstants.ts +16 -16
- package/src/layout/elementKinds.ts +35 -35
- package/src/layout/exportDrawing.ts +206 -206
- package/src/layout/filters.ts +80 -80
- package/src/layout/geometryConstants.ts +11 -11
- package/src/layout/index.ts +671 -671
- package/src/layout/itemBuilders.ts +159 -159
- package/src/layout/labelsRender.ts +170 -170
- package/src/layout/legendConstants.ts +11 -11
- package/src/layout/legendRender.ts +543 -543
- package/src/layout/legendRows.ts +62 -62
- package/src/layout/legendUtils.ts +144 -144
- package/src/layout/metadata.ts +210 -210
- package/src/layout/model.ts +372 -372
- package/src/layout/options.ts +17 -17
- package/src/layout/presets.ts +51 -51
- package/src/layout/qrRender.ts +126 -126
- package/src/layout/qrcode.d.ts +2 -2
- package/src/layout/renderDrawing.ts +710 -710
- package/src/layout/renderUtils.ts +138 -138
- package/src/layout/sectionValidation.ts +2 -2
- package/src/layout/templateVariables.ts +317 -317
- package/src/layout/typeGuards.ts +9 -9
- package/src/layout/types.ts +835 -835
- package/src/layout/utils.ts +85 -85
- package/src/layout/validation.ts +392 -392
- package/src/layout/validationHelpers.ts +59 -59
- package/src/layout/validationUtils.ts +6 -6
- package/src/layout/viewportPrep.ts +351 -351
- package/src/layout/viewportRender.ts +442 -442
- package/src/layout/viewportUtils.ts +50 -50
- package/src/layout/warnings.ts +3 -3
- package/src/printToPdf.ts +108 -108
- package/src/printToSvg.ts +188 -188
- package/src/sections.ts +1019 -1019
- package/src/types.ts +49 -49
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"itemBuilders.js","sourceRoot":"/","sources":["layout/itemBuilders.ts"],"names":[],"mappings":"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","sourcesContent":["import type { SectionRenderState } from '@twinfinity/geometry';\r\nimport { normalizePropertySets } from './metadata';\r\nimport { getPathValue } from './renderUtils';\r\nimport { buildModelViewFromRaw } from './model';\r\nimport { ProductFieldPaths, NormalizedProductItem, SvgModelView, LabelStyle } from './types';\r\n\r\nimport { getProp } from './typeGuards';\r\n\r\nexport interface ProductLike {\r\n product?: any;\r\n polylines?: Array<{ points?: Array<{ x: number; z: number }> }>;\r\n}\r\n\r\nexport interface BuildViewportItemsOptions {\r\n productFields?: ProductFieldPaths;\r\n}\r\n\r\n/**\r\n * Normalize a single product entry using explicit field paths.\r\n */\r\nexport const normalizeProductEntry = (entry: ProductLike, productFields: ProductFieldPaths): NormalizedProductItem => {\r\n if (!productFields?.idPath || !productFields?.namePath || !productFields?.areaPath) {\r\n throw new Error(\r\n 'productFields must include idPath, namePath, and areaPath using propertySets.<Set>.<Prop>.value.'\r\n );\r\n }\r\n const product = getProp(entry, 'product') ?? entry;\r\n const propertySets = normalizePropertySets(product);\r\n const getVal = (path: string): unknown => getPathValue({ propertySets }, path);\r\n const idVal = getVal(productFields.idPath) ?? getProp(product, 'gid');\r\n const nameVal = getVal(productFields.namePath);\r\n const areaVal = getVal(productFields.areaPath);\r\n // class.type = IfcClassType (\"space\", \"walls\", etc.) — used by template filters\r\n // class.id = PredefinedIfcClassId (\"IfcSpace\", \"IfcWall\", etc.) — used as fallback\r\n // classPath from propertySets may contain a PredefinedIfcClassId\r\n const classPathVal = productFields.classPath ? getVal(productFields.classPath) : null;\r\n const productClass = getProp(product, 'class');\r\n const classType = getProp(productClass, 'type') as string | null; // IfcClassType\r\n const classId = getProp(productClass, 'id') as string | null; // PredefinedIfcClassId\r\n // ifcClass = IfcClassType category; ifcClassId = PredefinedIfcClassId\r\n const ifcClass = (classType ?? null) as string | null;\r\n const ifcClassId = (classPathVal ?? classId ?? null) as string | null;\r\n // Try multiple sources for coordinates:\r\n // 1. BBox center from product\r\n // 2. Polylines center from entry\r\n // 3. Direct x/z on entry or product\r\n let { x, z } = getBBoxCenter(product);\r\n if (x === null || z === null) {\r\n const polyCenter = computePolylinesCenter(entry);\r\n x = polyCenter.x ?? x;\r\n z = polyCenter.z ?? z;\r\n }\r\n if (x === null || z === null) {\r\n const directX = getProp(entry, 'x') ?? getProp(product, 'x');\r\n const directZ = getProp(entry, 'z') ?? getProp(product, 'z');\r\n if (Number.isFinite(directX)) x = directX as number;\r\n if (Number.isFinite(directZ)) z = directZ as number;\r\n }\r\n const rawPolylines = getProp(entry, 'polylines');\r\n return {\r\n gid: getProp(product, 'gid') as string | undefined,\r\n ifcClass,\r\n ifcClassId,\r\n propertySets,\r\n productId: idVal ? String(idVal) : '-',\r\n productName: typeof nameVal === 'string' && nameVal.trim().length ? nameVal.trim() : '-',\r\n area: typeof areaVal === 'number' && Number.isFinite(areaVal) ? areaVal : null,\r\n x,\r\n z,\r\n text: typeof nameVal === 'string' && nameVal.trim().length ? nameVal.trim() : '-',\r\n polylines: Array.isArray(rawPolylines) ? rawPolylines : undefined\r\n };\r\n};\r\n\r\nconst getBBoxCenter = (product: unknown): { x: number | null; z: number | null } => {\r\n try {\r\n const boundingInfo = getProp(product, 'boundingInfo');\r\n const boundingInfoResult = typeof boundingInfo === 'function' ? boundingInfo() : null;\r\n const bbox = getProp(boundingInfoResult, 'boundingBox');\r\n const min = getProp(bbox, 'minimumWorld') ?? getProp(bbox, 'minimum');\r\n const max = getProp(bbox, 'maximumWorld') ?? getProp(bbox, 'maximum');\r\n const minX = getProp(min, 'x');\r\n const maxX = getProp(max, 'x');\r\n const minZ = getProp(min, 'z');\r\n const maxZ = getProp(max, 'z');\r\n if (Number.isFinite(minX) && Number.isFinite(maxX) && Number.isFinite(minZ) && Number.isFinite(maxZ)) {\r\n return { x: ((minX as number) + (maxX as number)) * 0.5, z: ((minZ as number) + (maxZ as number)) * 0.5 };\r\n }\r\n } catch {\r\n // Bounding info access may fail for products without geometry or with malformed data structures.\r\n // This is expected behavior - we return null coordinates as fallback.\r\n }\r\n return { x: null, z: null };\r\n};\r\n\r\nexport const computePolylinesCenter = (entry: unknown): { x: number | null; z: number | null } => {\r\n try {\r\n const polylines = getProp(entry, 'polylines');\r\n if (!Array.isArray(polylines) || !polylines.length) {\r\n return { x: null, z: null };\r\n }\r\n let sumX = 0;\r\n let sumZ = 0;\r\n let count = 0;\r\n for (const polyline of polylines) {\r\n const points = getProp(polyline, 'points');\r\n if (!Array.isArray(points)) continue;\r\n for (const pt of points) {\r\n const px = getProp(pt, 'x');\r\n const pz = getProp(pt, 'z');\r\n if (Number.isFinite(px) && Number.isFinite(pz)) {\r\n sumX += px as number;\r\n sumZ += pz as number;\r\n count++;\r\n }\r\n }\r\n }\r\n if (count > 0) {\r\n return { x: sumX / count, z: sumZ / count };\r\n }\r\n } catch {\r\n // Polyline access may fail - return null\r\n }\r\n return { x: null, z: null };\r\n};\r\n\r\n/**\r\n * Normalize raw product entries into viewport items using explicit field paths.\r\n * Requires productFields (id/name/area/class) pointing to propertySets.<Set>.<Prop>.value.\r\n */\r\nexport const buildViewportItems = (\r\n entries: ProductLike[],\r\n options?: BuildViewportItemsOptions\r\n): NormalizedProductItem[] => {\r\n if (!options?.productFields) {\r\n throw new Error('buildViewportItems requires productFields (idPath/namePath/areaPath/classPath).');\r\n }\r\n const { idPath, namePath, areaPath } = options.productFields;\r\n if (!idPath || !namePath || !areaPath) {\r\n throw new Error(\r\n 'productFields must include idPath, namePath, and areaPath using propertySets.<Set>.<Prop>.value.'\r\n );\r\n }\r\n return (entries ?? []).map((entry: any) => normalizeProductEntry(entry, options.productFields!));\r\n};\r\n\r\nexport function sectionStateToModelView(state: SectionRenderState, labelStyle?: LabelStyle): SvgModelView {\r\n const model = buildModelViewFromRaw(\r\n state.paths,\r\n state.labels,\r\n state.transform,\r\n state.geometryTransform,\r\n labelStyle\r\n );\r\n if (!model) {\r\n throw new Error('sectionStateToModelView requires paths, transform, and geometryTransform.');\r\n }\r\n return model;\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"itemBuilders.js","sourceRoot":"/","sources":["layout/itemBuilders.ts"],"names":[],"mappings":"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","sourcesContent":["import type { SectionRenderState } from '@twinfinity/geometry';\nimport { normalizePropertySets } from './metadata';\nimport { getPathValue } from './renderUtils';\nimport { buildModelViewFromRaw } from './model';\nimport { ProductFieldPaths, NormalizedProductItem, SvgModelView, LabelStyle } from './types';\n\nimport { getProp } from './typeGuards';\n\nexport interface ProductLike {\n product?: any;\n polylines?: Array<{ points?: Array<{ x: number; z: number }> }>;\n}\n\nexport interface BuildViewportItemsOptions {\n productFields?: ProductFieldPaths;\n}\n\n/**\n * Normalize a single product entry using explicit field paths.\n */\nexport const normalizeProductEntry = (entry: ProductLike, productFields: ProductFieldPaths): NormalizedProductItem => {\n if (!productFields?.idPath || !productFields?.namePath || !productFields?.areaPath) {\n throw new Error(\n 'productFields must include idPath, namePath, and areaPath using propertySets.<Set>.<Prop>.value.'\n );\n }\n const product = getProp(entry, 'product') ?? entry;\n const propertySets = normalizePropertySets(product);\n const getVal = (path: string): unknown => getPathValue({ propertySets }, path);\n const idVal = getVal(productFields.idPath) ?? getProp(product, 'gid');\n const nameVal = getVal(productFields.namePath);\n const areaVal = getVal(productFields.areaPath);\n // class.type = IfcClassType (\"space\", \"walls\", etc.) — used by template filters\n // class.id = PredefinedIfcClassId (\"IfcSpace\", \"IfcWall\", etc.) — used as fallback\n // classPath from propertySets may contain a PredefinedIfcClassId\n const classPathVal = productFields.classPath ? getVal(productFields.classPath) : null;\n const productClass = getProp(product, 'class');\n const classType = getProp(productClass, 'type') as string | null; // IfcClassType\n const classId = getProp(productClass, 'id') as string | null; // PredefinedIfcClassId\n // ifcClass = IfcClassType category; ifcClassId = PredefinedIfcClassId\n const ifcClass = (classType ?? null) as string | null;\n const ifcClassId = (classPathVal ?? classId ?? null) as string | null;\n // Try multiple sources for coordinates:\n // 1. BBox center from product\n // 2. Polylines center from entry\n // 3. Direct x/z on entry or product\n let { x, z } = getBBoxCenter(product);\n if (x === null || z === null) {\n const polyCenter = computePolylinesCenter(entry);\n x = polyCenter.x ?? x;\n z = polyCenter.z ?? z;\n }\n if (x === null || z === null) {\n const directX = getProp(entry, 'x') ?? getProp(product, 'x');\n const directZ = getProp(entry, 'z') ?? getProp(product, 'z');\n if (Number.isFinite(directX)) x = directX as number;\n if (Number.isFinite(directZ)) z = directZ as number;\n }\n const rawPolylines = getProp(entry, 'polylines');\n return {\n gid: getProp(product, 'gid') as string | undefined,\n ifcClass,\n ifcClassId,\n propertySets,\n productId: idVal ? String(idVal) : '-',\n productName: typeof nameVal === 'string' && nameVal.trim().length ? nameVal.trim() : '-',\n area: typeof areaVal === 'number' && Number.isFinite(areaVal) ? areaVal : null,\n x,\n z,\n text: typeof nameVal === 'string' && nameVal.trim().length ? nameVal.trim() : '-',\n polylines: Array.isArray(rawPolylines) ? rawPolylines : undefined\n };\n};\n\nconst getBBoxCenter = (product: unknown): { x: number | null; z: number | null } => {\n try {\n const boundingInfo = getProp(product, 'boundingInfo');\n const boundingInfoResult = typeof boundingInfo === 'function' ? boundingInfo() : null;\n const bbox = getProp(boundingInfoResult, 'boundingBox');\n const min = getProp(bbox, 'minimumWorld') ?? getProp(bbox, 'minimum');\n const max = getProp(bbox, 'maximumWorld') ?? getProp(bbox, 'maximum');\n const minX = getProp(min, 'x');\n const maxX = getProp(max, 'x');\n const minZ = getProp(min, 'z');\n const maxZ = getProp(max, 'z');\n if (Number.isFinite(minX) && Number.isFinite(maxX) && Number.isFinite(minZ) && Number.isFinite(maxZ)) {\n return { x: ((minX as number) + (maxX as number)) * 0.5, z: ((minZ as number) + (maxZ as number)) * 0.5 };\n }\n } catch {\n // Bounding info access may fail for products without geometry or with malformed data structures.\n // This is expected behavior - we return null coordinates as fallback.\n }\n return { x: null, z: null };\n};\n\nexport const computePolylinesCenter = (entry: unknown): { x: number | null; z: number | null } => {\n try {\n const polylines = getProp(entry, 'polylines');\n if (!Array.isArray(polylines) || !polylines.length) {\n return { x: null, z: null };\n }\n let sumX = 0;\n let sumZ = 0;\n let count = 0;\n for (const polyline of polylines) {\n const points = getProp(polyline, 'points');\n if (!Array.isArray(points)) continue;\n for (const pt of points) {\n const px = getProp(pt, 'x');\n const pz = getProp(pt, 'z');\n if (Number.isFinite(px) && Number.isFinite(pz)) {\n sumX += px as number;\n sumZ += pz as number;\n count++;\n }\n }\n }\n if (count > 0) {\n return { x: sumX / count, z: sumZ / count };\n }\n } catch {\n // Polyline access may fail - return null\n }\n return { x: null, z: null };\n};\n\n/**\n * Normalize raw product entries into viewport items using explicit field paths.\n * Requires productFields (id/name/area/class) pointing to propertySets.<Set>.<Prop>.value.\n */\nexport const buildViewportItems = (\n entries: ProductLike[],\n options?: BuildViewportItemsOptions\n): NormalizedProductItem[] => {\n if (!options?.productFields) {\n throw new Error('buildViewportItems requires productFields (idPath/namePath/areaPath/classPath).');\n }\n const { idPath, namePath, areaPath } = options.productFields;\n if (!idPath || !namePath || !areaPath) {\n throw new Error(\n 'productFields must include idPath, namePath, and areaPath using propertySets.<Set>.<Prop>.value.'\n );\n }\n return (entries ?? []).map((entry: any) => normalizeProductEntry(entry, options.productFields!));\n};\n\nexport function sectionStateToModelView(state: SectionRenderState, labelStyle?: LabelStyle): SvgModelView {\n const model = buildModelViewFromRaw(\n state.paths,\n state.labels,\n state.transform,\n state.geometryTransform,\n labelStyle\n );\n if (!model) {\n throw new Error('sectionStateToModelView requires paths, transform, and geometryTransform.');\n }\n return model;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"labelsRender.js","sourceRoot":"/","sources":["layout/labelsRender.ts"],"names":[],"mappings":"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","sourcesContent":["import { LabelsElement, LayoutData } from './types';\r\nimport { matchesV2Filter } from './filters';\r\nimport { pointInPolygon } from './clipUtils';\r\nimport { getPathValue, resolvePath, escapeAttr, escapeText } from './renderUtils';\r\n\r\nimport { isRecord, getProp } from './typeGuards';\r\n\r\nexport interface ViewportRenderInfo {\r\n mmPerModel: number;\r\n contentWidthMm: number;\r\n contentHeightMm: number;\r\n offsetX: number;\r\n offsetY: number;\r\n rotationDeg: number;\r\n transform: {\r\n viewMinX: number;\r\n viewMaxX: number;\r\n viewMinZ: number;\r\n viewMaxZ: number;\r\n viewWidth: number;\r\n viewHeight: number;\r\n };\r\n centerX: number;\r\n centerY: number;\r\n centerModelX: number;\r\n centerModelY: number;\r\n}\r\n\r\nexport const renderLabels = (\r\n labelElements: LabelsElement[],\r\n data: LayoutData,\r\n viewportRenderInfo: Record<string, ViewportRenderInfo>,\r\n viewportClipLabels: Record<string, boolean>,\r\n viewportClipPolygonsLocal: Record<string, Array<Array<{ x: number; y: number }>>>,\r\n viewportClipPolygonsWorld: Record<string, Array<Array<{ x: number; z: number }>>>,\r\n styles: Record<string, unknown>,\r\n dataWithViewport: unknown,\r\n warnings: string[]\r\n): string[] => {\r\n const parts: string[] = [];\r\n\r\n for (const dl of labelElements) {\r\n const vpInfo = viewportRenderInfo[dl.viewport];\r\n if (!vpInfo) {\r\n warnings.push(`Labels '${dl.id}' missing viewport '${dl.viewport}'.`);\r\n continue;\r\n }\r\n if (vpInfo.rotationDeg !== 0) {\r\n warnings.push(`Labels '${dl.id}' skipped because rotation is not supported.`);\r\n continue;\r\n }\r\n if (!vpInfo.transform) {\r\n warnings.push(`Labels '${dl.id}' skipped because model transform is missing.`);\r\n continue;\r\n }\r\n // Items come from the bound viewport's data\r\n const items = getPathValue(data, `viewports.${dl.viewport}.items`);\r\n if (!Array.isArray(items) || !items.length) {\r\n continue;\r\n }\r\n // Filter by class + where\r\n let filteredItems =\r\n dl.class || dl.where ? items.filter((item) => matchesV2Filter(item, dl.class, dl.where)) : items;\r\n\r\n console.log(`[Labels ${dl.id}] Total items:`, items.length, 'After class+where filter:', filteredItems.length);\r\n\r\n // If matchClipFilter is true, filter by spatial position inside clip polygon\r\n if (dl.matchClipFilter && viewportClipPolygonsWorld[dl.viewport]?.length) {\r\n const clipPolygons = viewportClipPolygonsWorld[dl.viewport];\r\n console.log(`[Labels ${dl.id}] Applying matchClipFilter (spatial) with ${clipPolygons.length} polygons`);\r\n const beforeClipFilter = filteredItems.length;\r\n filteredItems = filteredItems.filter((item) => {\r\n const ix = getProp(item, 'x');\r\n const iz = getProp(item, 'z');\r\n if (!Number.isFinite(ix) || !Number.isFinite(iz)) return false;\r\n return clipPolygons.some((poly) => {\r\n // pointInPolygon expects y coordinate, but we use z for world space\r\n const polyWith2D = poly.map((p) => ({ x: p.x, y: p.z }));\r\n return pointInPolygon(polyWith2D, ix as number, iz as number);\r\n });\r\n });\r\n console.log(\r\n `[Labels ${dl.id}] After matchClipFilter (spatial):`,\r\n filteredItems.length,\r\n '(was:',\r\n beforeClipFilter,\r\n ')'\r\n );\r\n\r\n // Debug: log first few items to see their properties\r\n if (filteredItems.length === 0 && beforeClipFilter > 0) {\r\n console.log('[Labels] Sample item that was filtered out:', items[0]);\r\n }\r\n }\r\n\r\n if (!filteredItems.length) {\r\n console.log(`[Labels ${dl.id}] No items left after filtering, skipping.`);\r\n continue;\r\n }\r\n const styleName = dl.textStyle;\r\n const style = styleName && isRecord(styles) ? getProp(styles, styleName) : undefined;\r\n if (!isRecord(style)) {\r\n warnings.push(`Labels '${dl.id}' missing textStyle '${styleName ?? '(none)'}'.`);\r\n continue;\r\n }\r\n const anchor = dl.align === 'center' ? 'middle' : dl.align === 'right' ? 'end' : 'start';\r\n const t = vpInfo.transform;\r\n\r\n let renderedCount = 0;\r\n let spatiallyFilteredCount = 0;\r\n\r\n filteredItems.forEach((item) => {\r\n // Hardcoded x/z for BIM floor plane convention\r\n const xVal = getProp(item, 'x');\r\n const yVal = getProp(item, 'z');\r\n if (!Number.isFinite(xVal as number) || !Number.isFinite(yVal as number)) {\r\n return;\r\n }\r\n const viewX = (xVal as number) - t.viewMinX;\r\n const viewY = t.viewMaxZ - (yVal as number);\r\n const centerModelX = vpInfo.centerModelX;\r\n const centerModelY = vpInfo.centerModelY;\r\n const xMm = vpInfo.centerX + (viewX - centerModelX) * vpInfo.mmPerModel;\r\n const yMm = vpInfo.centerY + (viewY - centerModelY) * vpInfo.mmPerModel;\r\n\r\n if (viewportClipLabels[dl.viewport] && viewportClipPolygonsLocal[dl.viewport]?.length) {\r\n const inside = viewportClipPolygonsLocal[dl.viewport].some((poly) =>\r\n pointInPolygon(poly, viewX, viewY)\r\n );\r\n if (!inside) {\r\n spatiallyFilteredCount++;\r\n return;\r\n }\r\n }\r\n\r\n renderedCount++;\r\n\r\n const text = escapeText(\r\n dl.text && typeof dl.text === 'string'\r\n ? dl.text.replace(/\\{\\{\\s*([^}]+?)\\s*\\}\\}/g, (_m, path) => {\r\n const val = resolvePath(item, path) ?? getPathValue(dataWithViewport, path);\r\n return val === undefined || val === null || typeof val === 'object' ? '' : String(val);\r\n })\r\n : ''\r\n );\r\n\r\n const fontFamily = getProp(style, 'fontFamily');\r\n const fontSizeMm = getProp(style, 'fontSizeMm');\r\n const fontWeight = getProp(style, 'fontWeight');\r\n const color = getProp(style, 'color');\r\n const letterSpacingMm = getProp(style, 'letterSpacingMm');\r\n const lineHeightMm = getProp(style, 'lineHeightMm');\r\n\r\n parts.push(\r\n `<text x=\"${xMm}\" y=\"${yMm}\" font-family=\"${escapeAttr(String(fontFamily))}\" font-size=\"${fontSizeMm}\"` +\r\n (fontWeight ? ` font-weight=\"${escapeAttr(String(fontWeight))}\"` : '') +\r\n (color ? ` fill=\"${escapeAttr(String(color))}\"` : '') +\r\n (letterSpacingMm !== undefined ? ` letter-spacing=\"${letterSpacingMm}\"` : '') +\r\n (lineHeightMm !== undefined ? ` line-height=\"${lineHeightMm}\"` : '') +\r\n ` text-anchor=\"${anchor}\">${text}</text>`\r\n );\r\n });\r\n\r\n console.log(\r\n `[Labels ${dl.id}] Rendered ${renderedCount} labels. Spatially filtered out: ${spatiallyFilteredCount}`\r\n );\r\n }\r\n\r\n return parts;\r\n};\r\n"]}
|
|
1
|
+
{"version":3,"file":"labelsRender.js","sourceRoot":"/","sources":["layout/labelsRender.ts"],"names":[],"mappings":"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","sourcesContent":["import { LabelsElement, LayoutData } from './types';\nimport { matchesV2Filter } from './filters';\nimport { pointInPolygon } from './clipUtils';\nimport { getPathValue, resolvePath, escapeAttr, escapeText } from './renderUtils';\n\nimport { isRecord, getProp } from './typeGuards';\n\nexport interface ViewportRenderInfo {\n mmPerModel: number;\n contentWidthMm: number;\n contentHeightMm: number;\n offsetX: number;\n offsetY: number;\n rotationDeg: number;\n transform: {\n viewMinX: number;\n viewMaxX: number;\n viewMinZ: number;\n viewMaxZ: number;\n viewWidth: number;\n viewHeight: number;\n };\n centerX: number;\n centerY: number;\n centerModelX: number;\n centerModelY: number;\n}\n\nexport const renderLabels = (\n labelElements: LabelsElement[],\n data: LayoutData,\n viewportRenderInfo: Record<string, ViewportRenderInfo>,\n viewportClipLabels: Record<string, boolean>,\n viewportClipPolygonsLocal: Record<string, Array<Array<{ x: number; y: number }>>>,\n viewportClipPolygonsWorld: Record<string, Array<Array<{ x: number; z: number }>>>,\n styles: Record<string, unknown>,\n dataWithViewport: unknown,\n warnings: string[]\n): string[] => {\n const parts: string[] = [];\n\n for (const dl of labelElements) {\n const vpInfo = viewportRenderInfo[dl.viewport];\n if (!vpInfo) {\n warnings.push(`Labels '${dl.id}' missing viewport '${dl.viewport}'.`);\n continue;\n }\n if (vpInfo.rotationDeg !== 0) {\n warnings.push(`Labels '${dl.id}' skipped because rotation is not supported.`);\n continue;\n }\n if (!vpInfo.transform) {\n warnings.push(`Labels '${dl.id}' skipped because model transform is missing.`);\n continue;\n }\n // Items come from the bound viewport's data\n const items = getPathValue(data, `viewports.${dl.viewport}.items`);\n if (!Array.isArray(items) || !items.length) {\n continue;\n }\n // Filter by class + where\n let filteredItems =\n dl.class || dl.where ? items.filter((item) => matchesV2Filter(item, dl.class, dl.where)) : items;\n\n console.log(`[Labels ${dl.id}] Total items:`, items.length, 'After class+where filter:', filteredItems.length);\n\n // If matchClipFilter is true, filter by spatial position inside clip polygon\n if (dl.matchClipFilter && viewportClipPolygonsWorld[dl.viewport]?.length) {\n const clipPolygons = viewportClipPolygonsWorld[dl.viewport];\n console.log(`[Labels ${dl.id}] Applying matchClipFilter (spatial) with ${clipPolygons.length} polygons`);\n const beforeClipFilter = filteredItems.length;\n filteredItems = filteredItems.filter((item) => {\n const ix = getProp(item, 'x');\n const iz = getProp(item, 'z');\n if (!Number.isFinite(ix) || !Number.isFinite(iz)) return false;\n return clipPolygons.some((poly) => {\n // pointInPolygon expects y coordinate, but we use z for world space\n const polyWith2D = poly.map((p) => ({ x: p.x, y: p.z }));\n return pointInPolygon(polyWith2D, ix as number, iz as number);\n });\n });\n console.log(\n `[Labels ${dl.id}] After matchClipFilter (spatial):`,\n filteredItems.length,\n '(was:',\n beforeClipFilter,\n ')'\n );\n\n // Debug: log first few items to see their properties\n if (filteredItems.length === 0 && beforeClipFilter > 0) {\n console.log('[Labels] Sample item that was filtered out:', items[0]);\n }\n }\n\n if (!filteredItems.length) {\n console.log(`[Labels ${dl.id}] No items left after filtering, skipping.`);\n continue;\n }\n const styleName = dl.textStyle;\n const style = styleName && isRecord(styles) ? getProp(styles, styleName) : undefined;\n if (!isRecord(style)) {\n warnings.push(`Labels '${dl.id}' missing textStyle '${styleName ?? '(none)'}'.`);\n continue;\n }\n const anchor = dl.align === 'center' ? 'middle' : dl.align === 'right' ? 'end' : 'start';\n const t = vpInfo.transform;\n\n let renderedCount = 0;\n let spatiallyFilteredCount = 0;\n\n filteredItems.forEach((item) => {\n // Hardcoded x/z for BIM floor plane convention\n const xVal = getProp(item, 'x');\n const yVal = getProp(item, 'z');\n if (!Number.isFinite(xVal as number) || !Number.isFinite(yVal as number)) {\n return;\n }\n const viewX = (xVal as number) - t.viewMinX;\n const viewY = t.viewMaxZ - (yVal as number);\n const centerModelX = vpInfo.centerModelX;\n const centerModelY = vpInfo.centerModelY;\n const xMm = vpInfo.centerX + (viewX - centerModelX) * vpInfo.mmPerModel;\n const yMm = vpInfo.centerY + (viewY - centerModelY) * vpInfo.mmPerModel;\n\n if (viewportClipLabels[dl.viewport] && viewportClipPolygonsLocal[dl.viewport]?.length) {\n const inside = viewportClipPolygonsLocal[dl.viewport].some((poly) =>\n pointInPolygon(poly, viewX, viewY)\n );\n if (!inside) {\n spatiallyFilteredCount++;\n return;\n }\n }\n\n renderedCount++;\n\n const text = escapeText(\n dl.text && typeof dl.text === 'string'\n ? dl.text.replace(/\\{\\{\\s*([^}]+?)\\s*\\}\\}/g, (_m, path) => {\n const val = resolvePath(item, path) ?? getPathValue(dataWithViewport, path);\n return val === undefined || val === null || typeof val === 'object' ? '' : String(val);\n })\n : ''\n );\n\n const fontFamily = getProp(style, 'fontFamily');\n const fontSizeMm = getProp(style, 'fontSizeMm');\n const fontWeight = getProp(style, 'fontWeight');\n const color = getProp(style, 'color');\n const letterSpacingMm = getProp(style, 'letterSpacingMm');\n const lineHeightMm = getProp(style, 'lineHeightMm');\n\n parts.push(\n `<text x=\"${xMm}\" y=\"${yMm}\" font-family=\"${escapeAttr(String(fontFamily))}\" font-size=\"${fontSizeMm}\"` +\n (fontWeight ? ` font-weight=\"${escapeAttr(String(fontWeight))}\"` : '') +\n (color ? ` fill=\"${escapeAttr(String(color))}\"` : '') +\n (letterSpacingMm !== undefined ? ` letter-spacing=\"${letterSpacingMm}\"` : '') +\n (lineHeightMm !== undefined ? ` line-height=\"${lineHeightMm}\"` : '') +\n ` text-anchor=\"${anchor}\">${text}</text>`\n );\n });\n\n console.log(\n `[Labels ${dl.id}] Rendered ${renderedCount} labels. Spatially filtered out: ${spatiallyFilteredCount}`\n );\n }\n\n return parts;\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"legendConstants.js","sourceRoot":"/","sources":["layout/legendConstants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,SAAS,GAAG,EAAE,GAAG,IAAI,CAAC;AACnC,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAC;AAChD,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAC;AAChD,MAAM,CAAC,MAAM,8BAA8B,GAAG,IAAI,CAAC;AACnD,MAAM,CAAC,MAAM,4BAA4B,GAAG,IAAI,CAAC;AACjD,MAAM,CAAC,MAAM,8BAA8B,GAAG,IAAI,CAAC;AACnD,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC;AAC1C,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAG,CAAC;AAC5C,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAC;AAC7C,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAG,CAAC;AAC/C,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,CAAC","sourcesContent":["export const PX_PER_MM = 96 / 25.4;\
|
|
1
|
+
{"version":3,"file":"legendConstants.js","sourceRoot":"/","sources":["layout/legendConstants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,SAAS,GAAG,EAAE,GAAG,IAAI,CAAC;AACnC,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAC;AAChD,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAC;AAChD,MAAM,CAAC,MAAM,8BAA8B,GAAG,IAAI,CAAC;AACnD,MAAM,CAAC,MAAM,4BAA4B,GAAG,IAAI,CAAC;AACjD,MAAM,CAAC,MAAM,8BAA8B,GAAG,IAAI,CAAC;AACnD,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC;AAC1C,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAG,CAAC;AAC5C,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAC;AAC7C,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAG,CAAC;AAC/C,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,CAAC","sourcesContent":["export const PX_PER_MM = 96 / 25.4;\nexport const DEFAULT_LEGEND_SWATCH_WIDTH_MM = 8;\nexport const DEFAULT_LEGEND_CELL_PADDING_MM = 2;\nexport const DEFAULT_LEGEND_BORDER_WIDTH_MM = 0.25;\nexport const DEFAULT_LEGEND_GRID_WIDTH_MM = 0.25;\nexport const DEFAULT_LEGEND_HEADER_WIDTH_MM = 0.65;\nexport const DEFAULT_LEGEND_OFFSET_MM = 5;\nexport const LEGEND_TEXT_WIDTH_FACTOR = 0.7;\nexport const LEGEND_MIN_CONTENT_WIDTH_EM = 4;\nexport const LEGEND_TEXT_Y_OFFSET_FACTOR = 0.3;\nexport const MAX_LEGEND_ROWS = 200;\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"legendRender.js","sourceRoot":"/","sources":["layout/legendRender.ts"],"names":[],"mappings":"AACA,OAAO,EACH,8BAA8B,EAC9B,8BAA8B,EAC9B,8BAA8B,EAC9B,4BAA4B,EAC5B,8BAA8B,EAC9B,wBAAwB,EACxB,eAAe,EAClB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACH,yBAAyB,EACzB,wBAAwB,EACxB,gBAAgB,EAChB,iBAAiB,EACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C;;;;GAIG;AACH,SAAS,QAAQ,CAAC,CAAS,EAAE,CAAS,EAAE,CAAS;IAC7C,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;IACZ,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;IACZ,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;IAEZ,MAAM,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAChD,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAEpB,MAAM,QAAQ,GAAG,CAAC,CAAS,EAAU,EAAE;QACnC,IAAI,CAAC,GAAG,CAAC;YAAE,CAAC,IAAI,CAAC,CAAC;QAClB,IAAI,CAAC,GAAG,CAAC;YAAE,CAAC,IAAI,CAAC,CAAC;QAClB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC1C,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO,CAAC,CAAC;QACxB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;QACpD,OAAO,CAAC,CAAC;IACb,CAAC,CAAC;IAEF,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;IAChD,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;IACxC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;IAEhD,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AACrB,CAAC;AAED;;;GAGG;AACH,SAAS,oBAAoB,CAAC,KAAa,EAAE,OAA2B;IACpE,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACzB,0CAA0C;QAC1C,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7B,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;QAC7C,CAAC;QACD,OAAO,MAAM,CAAC;IAClB,CAAC;IAED,2EAA2E;IAC3E,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,KAAK,CAAC;QAC9B,MAAM,UAAU,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;QACrC,MAAM,SAAS,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;QAEpC,yCAAyC;QACzC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;QACvD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEjD,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC7B,UAAqB,EACrB,MAAqB,EACrB,SAAoB,EACpB,yBAAiF,EACjF,kBAA2D,EAClD,EAAE;IACX,0BAA0B;IAC1B,IAAI,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC;QAChC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,eAAe,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QAC9E,CAAC,CAAC,EAAE,CAAC;IACT,IAAI,CAAC,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAE9B,IAAI,MAAM,CAAC,cAAc,EAAE,CAAC;QACxB,MAAM,gBAAgB,GAAG,MAAM,CAAC,QAAQ,CAAC;QACzC,MAAM,KAAK,GAAG,gBAAgB,CAAC,CAAC,CAAC,yBAAyB,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACpF,MAAM,MAAM,GAAG,gBAAgB,CAAC,CAAC,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC9E,MAAM,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACjE,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,IAAI,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;YACvC,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;YACxC,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;YACxC,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;gBAC/D,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE;oBACvB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;oBAC/B,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;oBAC/B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;wBAAE,OAAO,KAAK,CAAC;oBACnE,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC;oBACtC,MAAM,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;oBACtC,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;gBACpE,CAAC,CAAC,CAAC;YACP,CAAC;QACL,CAAC;IACL,CAAC;IAED,OAAO,IAAI,CAAC;AAChB,CAAC,CAAC;AAOF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC5B,MAAqB,EACrB,MAA4B,EAC5B,IAAc,EACd,QAA4B,EAC5B,UAAqB,EACrB,WAAoB,EACD,EAAE;IACrB,IAAI,CAAC,MAAM,IAAI,CAAC,UAAU,IAAI,CAAC,UAAU,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAE9D,4BAA4B;IAC5B,+FAA+F;IAC/F,wBAAwB;IACxB,4CAA4C;IAC5C,8CAA8C;IAC9C,qCAAqC;IACrC,mEAAmE;IACnE,mDAAmD;IACnD,MAAM;IACN,6IAA6I;IAC7I,IAAI;IAEJ,MAAM,UAAU,GAAG,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/D,MAAM,SAAS,GAAG,CAAC,MAAM,CAAC,SAAS,IAAI,MAAM,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC;IACvF,MAAM,UAAU,GAAG,OAAO,SAAS,EAAE,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IACxF,MAAM,UAAU,GAAG,SAAS,EAAE,UAAU,IAAI,mBAAmB,CAAC;IAChE,MAAM,SAAS,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IAEzF,mFAAmF;IACnF,MAAM,eAAe,GAAG,MAAM,CAAC,eAAe,KAAK,KAAK,CAAC;IACzD,MAAM,kBAAkB,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,kBAAkB,IAAI,8BAA8B,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/G,MAAM,QAAQ,GAAG,WAAW,KAAK,SAAS,CAAC;IAC3C,uHAAuH;IACvH,MAAM,aAAa,GAAG,MAAM,CAAC,aAAa,IAAI,8BAA8B,CAAC;IAC7E,MAAM,mBAAmB,GAAG,MAAM,CAAC,mBAAmB,IAAI,8BAA8B,CAAC;IACzF,MAAM,iBAAiB,GAAG,MAAM,CAAC,iBAAiB,IAAI,SAAS,CAAC;IAChE,MAAM,iBAAiB,GAAG,MAAM,CAAC,iBAAiB,IAAI,4BAA4B,CAAC;IACnF,MAAM,eAAe,GAAG,MAAM,CAAC,eAAe,IAAI,SAAS,CAAC;IAC5D,MAAM,mBAAmB,GAAG,MAAM,CAAC,mBAAmB,IAAI,8BAA8B,CAAC;IACzF,MAAM,iBAAiB,GAAG,MAAM,CAAC,iBAAiB,IAAI,SAAS,CAAC;IAChE,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,WAAW,CAAC;IAC5C,MAAM,cAAc,GAAG,MAAM,CAAC,QAAQ,IAAI,wBAAwB,CAAC;IAEnE,qCAAqC;IACrC,IAAI,aAAa,GAAG,UAAU,CAAC;IAC/B,IAAI,MAAM,CAAC,OAAO,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;QACvD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAqB,CAAC;QAE5C,2CAA2C;QAC3C,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;YAC3B,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;YAChE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACxB,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;YAC7B,CAAC;YACD,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpC,CAAC;QAED,2GAA2G;QAC3G,gDAAgD;QAChD,2BAA2B;QAC3B,4EAA4E;QAC5E,MAAM;QACN,IAAI;QAEJ,uBAAuB;QACvB,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE;YAC1D,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC;YAChD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC;YAEhD,2EAA2E;YAC3E,MAAM,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;YAC9B,MAAM,UAAU,GAAQ,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,GAAI,QAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAE1G,oCAAoC;YACpC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBAC/B,MAAM,MAAM,GAAU,EAAE,CAAC;gBACzB,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;oBAC1B,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;oBAC3C,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;wBACpC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;oBACrB,CAAC;gBACL,CAAC;gBAED,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;oBAAE,SAAS;gBAElC,oDAAoD;gBACpD,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;oBAClC,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;oBAC9D,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;gBAC/C,CAAC,CAAC,CAAC;gBAEH,IAAI,UAAU,EAAE,CAAC;oBACb,uBAAuB;oBACvB,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;wBACjC,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;wBAC9D,OAAO,GAAG,GAAG,GAAG,CAAC;oBACrB,CAAC,EAAE,CAAC,CAAC,CAAC;oBAEN,gCAAgC;oBAChC,gDAAgD;oBAChD,gEAAgE;oBAChE,yFAAyF;oBACzF,gCAAgC;oBAChC,sBAAsB;oBACtB,eAAe;oBACf,QAAQ;oBACR,IAAI;oBAEJ,4DAA4D;oBAC5D,MAAM,SAAS,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;oBAC1C,IAAI,MAAM,GAAG,UAAU,CAAC;oBACxB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;wBAC5C,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;4BACxB,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;wBAC9B,CAAC;wBACD,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;oBAClC,CAAC;oBACD,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;gBAClD,CAAC;gBACD,4EAA4E;YAChF,CAAC;YAED,OAAO,UAAU,CAAC;QACtB,CAAC,CAAC,CAAC;IACP,CAAC;IAED,6CAA6C;IAC7C,IAAI,eAAe,GAAoB,IAAI,CAAC;IAC5C,IAAI,QAAyC,CAAC;IAE9C,IAAI,MAAM,CAAC,YAAY,EAAE,OAAO,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,MAAM,CAAC,YAAY,CAAC,OAAO,IAAI,MAAM,CAAC;QACtD,eAAe,GAAG,oBAAoB,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACtE,mGAAmG;QAEnG,4CAA4C;QAC5C,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,QAAQ,GAAG,IAAI,GAAG,EAAE,CAAC;YACrB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,aAAa,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC5C,MAAM,GAAG,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;gBAC7B,MAAM,UAAU,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;gBAClE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;oBAC5B,QAAQ,CAAC,GAAG,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;oBAC7C,kFAAkF;gBACtF,CAAC;YACL,CAAC;YACD,oGAAoG;QACxG,CAAC;aAAM,CAAC;YACJ,OAAO,CAAC,IAAI,CAAC,kEAAkE,CAAC,CAAC;QACrF,CAAC;IACL,CAAC;IAED,MAAM,UAAU,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,GAAY,EAAE,KAAa,EAAE,EAAE;QACjE,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;YACtC,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC3C,OAAO,iBAAiB,CAAC,GAAG,EAAE,GAAG,CAAC,MAAa,CAAC,CAAC;QACrD,CAAC,CAAC,CAAC;QAEH,mFAAmF;QACnF,IAAI,WAAmB,CAAC;QACxB,IAAI,eAAe,EAAE,CAAC;YAClB,WAAW,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;QACzC,CAAC;aAAM,CAAC;YACJ,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YACzC,MAAM,IAAI,GAAG,gBAAgB,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;YAC5E,WAAW,GAAG,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC;QAC1D,CAAC;QAED,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC5C,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,UAAU,EAAE,CAAC,CAAC,UAAU;QACxB,UAAU,EAAE,CAAC,CAAC,UAAU;KAC3B,CAAC,CAAC,CAAC;IACJ,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,GAAG,yBAAyB,CAC1D,YAAY,EACZ,UAAU,EACV,UAAU,EACV,aAAa,EACb,kBAAkB,EAClB,UAAU,CACb,CAAC;IAEF,MAAM,WAAW,GAAG,UAAU,GAAG,aAAa,GAAG,CAAC,CAAC;IACnD,MAAM,cAAc,GAAG,WAAW,CAAC;IACnC,MAAM,YAAY,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAEhE,8BAA8B;IAC9B,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACxD,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,EAAE,KAAK,IAAI,OAAO,CAAC;IACtD,MAAM,eAAe,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAE/C,MAAM,aAAa,GAAG,cAAc,GAAG,UAAU,CAAC,MAAM,GAAG,WAAW,GAAG,eAAe,GAAG,WAAW,CAAC;IAEvG,MAAM,SAAS,GAAG,MAAM,CAAC,gBAAgB,CAAC;IAC1C,MAAM,YAAY,GACd,SAAS;QACT,OAAO,SAAS,CAAC,GAAG,KAAK,QAAQ;QACjC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC;QAC9B,OAAO,SAAS,CAAC,GAAG,KAAK,QAAQ;QACjC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAEnC,IAAI,SAAS,GAAG,UAAU,GAAG,cAAc,CAAC;IAC5C,IAAI,SAAS,GAAG,UAAU,GAAG,cAAc,CAAC;IAE5C,IAAI,YAAY,EAAE,CAAC;QACf,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,SAAyC,CAAC;QAC/D,QAAQ,MAAM,EAAE,CAAC;YACb,KAAK,UAAU;gBACX,SAAS,GAAG,GAAG,CAAC;gBAChB,SAAS,GAAG,GAAG,CAAC;gBAChB,MAAM;YACV,KAAK,WAAW;gBACZ,SAAS,GAAG,GAAG,GAAG,YAAY,CAAC;gBAC/B,SAAS,GAAG,GAAG,CAAC;gBAChB,MAAM;YACV,KAAK,aAAa;gBACd,SAAS,GAAG,GAAG,CAAC;gBAChB,SAAS,GAAG,GAAG,GAAG,aAAa,CAAC;gBAChC,MAAM;YACV,KAAK,cAAc,CAAC;YACpB;gBACI,SAAS,GAAG,GAAG,GAAG,YAAY,CAAC;gBAC/B,SAAS,GAAG,GAAG,GAAG,aAAa,CAAC;gBAChC,MAAM;QACd,CAAC;IACL,CAAC;SAAM,CAAC;QACJ,IAAI,MAAM,KAAK,WAAW,IAAI,MAAM,KAAK,cAAc,EAAE,CAAC;YACtD,SAAS,GAAG,IAAI,CAAC,OAAO,GAAG,UAAU,GAAG,cAAc,GAAG,YAAY,CAAC;QAC1E,CAAC;QACD,IAAI,MAAM,KAAK,cAAc,IAAI,MAAM,KAAK,aAAa,EAAE,CAAC;YACxD,SAAS,GAAG,IAAI,CAAC,QAAQ,GAAG,UAAU,GAAG,cAAc,GAAG,aAAa,CAAC;QAC5E,CAAC;IACL,CAAC;IAED,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;QACtB,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACjB,GAAG,IAAI,CAAC,CAAC;IACb,CAAC,CAAC,CAAC;IAEH,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,MAAM,eAAe,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,MAAM,gBAAgB,GAAG,SAAS,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;IACpD,MAAM,eAAe,GAAG,SAAS,GAAG,cAAc,CAAC;IAEnD,KAAK,CAAC,IAAI,CACN,aAAa,gBAAgB,SAAS,SAAS,SAAS,SAAS,GAAG,YAAY,SAAS,SAAS,aAAa,iBAAiB,mBAAmB,mBAAmB,MAAM,CAC/K,CAAC;IACF,KAAK,CAAC,IAAI,CACN,aAAa,gBAAgB,SAAS,SAAS,SAAS,gBAAgB,SAAS,eAAe,aAAa,iBAAiB,mBAAmB,mBAAmB,MAAM,CAC7K,CAAC;IACF,0EAA0E;IAC1E,MAAM,kBAAkB,GAAG,cAAc,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS,CAAC;IACzE,KAAK,CAAC,IAAI,CACN,aAAa,kBAAkB,SAAS,SAAS,GAAG,aAAa,SAAS,SAAS,GAAG,YAAY,SAAS,SAAS,GAAG,aAAa,aAAa,iBAAiB,mBAAmB,mBAAmB,MAAM,CACjN,CAAC;IACF,KAAK,CAAC,IAAI,CACN,aAAa,SAAS,GAAG,YAAY,SAAS,SAAS,SAAS,SAAS,GAAG,YAAY,SAAS,SAAS,GAAG,aAAa,aAAa,iBAAiB,mBAAmB,mBAAmB,MAAM,CACvM,CAAC;IACF,0DAA0D;IAC1D,MAAM,cAAc,GAAG,cAAc;QACjC,CAAC,CAAC,SAAS,GAAG,cAAc,GAAG,UAAU,CAAC,MAAM,GAAG,WAAW;QAC9D,CAAC,CAAC,SAAS,GAAG,aAAa,CAAC;IAChC,KAAK,CAAC,IAAI,CACN,aAAa,SAAS,SAAS,eAAe,SAAS,SAAS,SAAS,cAAc,aAAa,iBAAiB,mBAAmB,mBAAmB,MAAM,CACpK,CAAC;IAEF,kDAAkD;IAClD,KAAK,CAAC,IAAI,CACN,aAAa,gBAAgB,SAAS,eAAe,SAAS,gBAAgB,SAAS,SAAS,GAAG,aAAa,aAAa,iBAAiB,mBAAmB,mBAAmB,MAAM,CAC7L,CAAC;IAEF,KAAK,CAAC,IAAI,CACN,aAAa,SAAS,SAAS,SAAS,GAAG,cAAc,SAAS,SAAS,GAAG,YAAY,SAAS,SAAS,GAAG,cAAc,aAAa,iBAAiB,mBAAmB,mBAAmB,MAAM,CAC1M,CAAC;IAEF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,MAAM,CAAC,GAAG,SAAS,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QAChC,KAAK,CAAC,IAAI,CACN,aAAa,CAAC,SAAS,SAAS,SAAS,CAAC,SAAS,SAAS,GAAG,aAAa,aAAa,eAAe,mBAAmB,mBAAmB,MAAM,CACvJ,CAAC;IACN,CAAC;IAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,oFAAoF;QACpF,IAAI,CAAC,KAAK,UAAU,CAAC,MAAM,IAAI,cAAc;YAAE,SAAS;QAExD,MAAM,CAAC,GAAG,SAAS,GAAG,cAAc,GAAG,CAAC,GAAG,WAAW,CAAC;QACvD,KAAK,CAAC,IAAI,CACN,aAAa,SAAS,SAAS,CAAC,SAAS,SAAS,GAAG,YAAY,SAAS,CAAC,aAAa,eAAe,mBAAmB,mBAAmB,MAAM,CACtJ,CAAC;IACN,CAAC;IAED,MAAM,aAAa,GAAG,wBAAwB,CAAC,UAAU,CAAC,CAAC;IAC3D,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,GAAG,eAAe,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QACxE,MAAM,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC,GAAG,GAAG,eAAe,CAAC,CAAC;QAC3D,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,GAAG,eAAe,CAAC,CAAC;QACpD,MAAM,QAAQ,GAAG,aAAa,GAAG,iBAAiB,GAAG,GAAG,CAAC;QACzD,MAAM,CAAC,GACH,GAAG,CAAC,KAAK,KAAK,QAAQ;YAClB,CAAC,CAAC,QAAQ,GAAG,QAAQ,GAAG,CAAC;YACzB,CAAC,CAAC,GAAG,CAAC,KAAK,KAAK,OAAO;gBACrB,CAAC,CAAC,QAAQ,GAAG,QAAQ,GAAG,QAAQ;gBAChC,CAAC,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAChC,MAAM,CAAC,GAAG,SAAS,GAAG,cAAc,GAAG,CAAC,GAAG,aAAa,CAAC;QACzD,MAAM,UAAU,GAAG,GAAG,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC;QAC/F,KAAK,CAAC,IAAI,CACN,YAAY,CAAC,QAAQ,CAAC,kBAAkB,UAAU,gBAAgB,UAAU,WAAW,SAAS,6CAA6C,UAAU,KAAK,GAAG,CAAC,KAAK,SAAS,CACjL,CAAC;IACN,CAAC,CAAC,CAAC;IAEH,MAAM,aAAa,GAAG,OAAO,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAElG,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;QACzD,MAAM,IAAI,GAAG,SAAS,GAAG,cAAc,GAAG,MAAM,GAAG,WAAW,CAAC;QAE/D,IAAI,eAAe,EAAE,CAAC;YAClB,6DAA6D;YAC7D,IAAI,QAAQ,EAAE,CAAC;gBACX,mFAAmF;gBACnF,MAAM,UAAU,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,6BAA6B;gBAC3D,MAAM,WAAW,GAAG,aAAa,GAAG,CAAC,CAAC,CAAC,CAAC,kBAAkB,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC3F,KAAK,CAAC,IAAI,CACN,YAAY,SAAS,GAAG,MAAM,CAAC,CAAC,CAAC,QAAQ,IAAI,YAAY,WAAW,CAAC,CAAC,CAAC,aAAa,WAAW,WAAW,UAAU,IAAI,WAAW,mBAAmB,CACzJ,CAAC;YACN,CAAC;iBAAM,CAAC;gBACJ,+DAA+D;gBAC/D,KAAK,CAAC,IAAI,CACN,YAAY,SAAS,GAAG,MAAM,CAAC,CAAC,CAAC,QAAQ,IAAI,YAAY,WAAW,CAAC,CAAC,CAAC,aAAa,WAAW,gCAAgC,CAClI,CAAC;YACN,CAAC;QACL,CAAC;QAED,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,GAAG,eAAe,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE;YACzE,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACpC,IAAI,CAAC,IAAI;gBAAE,OAAO;YAClB,MAAM,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC,IAAI,GAAG,eAAe,CAAC,CAAC;YAC5D,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,GAAG,eAAe,CAAC,CAAC;YACrD,MAAM,QAAQ,GAAG,aAAa,GAAG,iBAAiB,GAAG,GAAG,CAAC;YACzD,MAAM,CAAC,GACH,GAAG,CAAC,KAAK,KAAK,QAAQ;gBAClB,CAAC,CAAC,QAAQ,GAAG,QAAQ,GAAG,CAAC;gBACzB,CAAC,CAAC,GAAG,CAAC,KAAK,KAAK,OAAO;oBACrB,CAAC,CAAC,QAAQ,GAAG,QAAQ,GAAG,QAAQ;oBAChC,CAAC,CAAC,QAAQ,GAAG,QAAQ,CAAC;YAChC,MAAM,CAAC,GAAG,IAAI,GAAG,WAAW,GAAG,CAAC,GAAG,aAAa,CAAC;YACjD,MAAM,UAAU,GAAG,GAAG,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC;YAC/F,KAAK,CAAC,IAAI,CACN,YAAY,CAAC,QAAQ,CAAC,kBAAkB,UAAU,gBAAgB,UAAU,WAAW,SAAS,6CAA6C,UAAU,KAAK,IAAI,SAAS,CAC5K,CAAC;QACN,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,kCAAkC;IAClC,IAAI,cAAc,EAAE,CAAC;QACjB,MAAM,eAAe,GAAG,UAAU,CAAC,MAAM,CAAC;QAC1C,MAAM,IAAI,GAAG,SAAS,GAAG,cAAc,GAAG,eAAe,GAAG,WAAW,CAAC;QAExE,0DAA0D;QAC1D,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;YAC7C,IAAI,CAAC,GAAG,CAAC,OAAO;gBAAE,OAAO,EAAE,CAAC;YAE5B,kFAAkF;YAClF,IAAI,GAAG,GAAG,CAAC,CAAC;YACZ,IAAI,SAAS,GAAG,KAAK,CAAC;YACtB,KAAK,MAAM,OAAO,IAAI,aAAa,EAAE,CAAC;gBAClC,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;gBACpD,MAAM,QAAQ,GAAG,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;gBACxF,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAChD,GAAG,IAAI,QAAQ,CAAC;oBAChB,SAAS,GAAG,IAAI,CAAC;gBACrB,CAAC;YACL,CAAC;YAED,oDAAoD;YACpD,OAAO,SAAS,CAAC,CAAC,CAAC,iBAAiB,CAAC,GAAG,EAAE,GAAG,CAAC,MAAa,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACtE,CAAC,CAAC,CAAC;QAEH,4CAA4C;QAC5C,KAAK,CAAC,IAAI,CACN,aAAa,SAAS,SAAS,IAAI,SAAS,SAAS,GAAG,YAAY,SAAS,IAAI,aAAa,iBAAiB,mBAAmB,mBAAmB,MAAM,CAC9J,CAAC;QAEF,sDAAsD;QACtD,MAAM,QAAQ,GAAG,aAAa,GAAG,iBAAiB,GAAG,GAAG,CAAC;QACzD,MAAM,MAAM,GAAG,gBAAgB,GAAG,QAAQ,CAAC;QAC3C,MAAM,MAAM,GAAG,IAAI,GAAG,WAAW,GAAG,CAAC,GAAG,aAAa,CAAC;QACtD,KAAK,CAAC,IAAI,CACN,YAAY,MAAM,QAAQ,MAAM,kBAAkB,UAAU,gBAAgB,UAAU,WAAW,SAAS,uEAAuE,YAAY,SAAS,CACzM,CAAC;QAEF,0CAA0C;QAC1C,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,GAAG,eAAe,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE;YACzE,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;YAClD,IAAI,CAAC,WAAW;gBAAE,OAAO;YAEzB,MAAM,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC,IAAI,GAAG,eAAe,GAAG,CAAC,CAAC,CAAC;YAChE,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,GAAG,eAAe,GAAG,CAAC,CAAC,CAAC;YACzD,MAAM,CAAC,GACH,GAAG,CAAC,KAAK,KAAK,QAAQ;gBAClB,CAAC,CAAC,QAAQ,GAAG,QAAQ,GAAG,CAAC;gBACzB,CAAC,CAAC,GAAG,CAAC,KAAK,KAAK,OAAO;oBACrB,CAAC,CAAC,QAAQ,GAAG,QAAQ,GAAG,QAAQ;oBAChC,CAAC,CAAC,QAAQ,GAAG,QAAQ,CAAC;YAChC,MAAM,CAAC,GAAG,IAAI,GAAG,WAAW,GAAG,CAAC,GAAG,aAAa,CAAC;YACjD,MAAM,UAAU,GAAG,GAAG,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC;YAC/F,KAAK,CAAC,IAAI,CACN,YAAY,CAAC,QAAQ,CAAC,kBAAkB,UAAU,gBAAgB,UAAU,WAAW,SAAS,gEAAgE,UAAU,KAAK,WAAW,SAAS,CACtM,CAAC;QACN,CAAC,CAAC,CAAC;IACP,CAAC;IAED,MAAM,GAAG,GAAG,CAAC,iBAAiB,EAAE,GAAG,KAAK,EAAE,GAAG,KAAK,EAAE,GAAG,KAAK,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC/E,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC;AAC7B,CAAC,CAAC","sourcesContent":["import { LegendElement, PageSpec, StyleMap } from './types';\r\nimport {\r\n DEFAULT_LEGEND_SWATCH_WIDTH_MM,\r\n DEFAULT_LEGEND_CELL_PADDING_MM,\r\n DEFAULT_LEGEND_BORDER_WIDTH_MM,\r\n DEFAULT_LEGEND_GRID_WIDTH_MM,\r\n DEFAULT_LEGEND_HEADER_WIDTH_MM,\r\n DEFAULT_LEGEND_OFFSET_MM,\r\n MAX_LEGEND_ROWS\r\n} from './legendConstants';\r\nimport {\r\n computeLegendColumnWidths,\r\n computeLegendTextYOffset,\r\n parseLegendColor,\r\n formatLegendValue\r\n} from './legendUtils';\r\nimport { resolvePath } from './renderUtils';\r\nimport { matchesV2Filter } from './filters';\r\nimport { pointInPolygon } from './clipUtils';\r\n\r\n/**\r\n * Convert HSL to RGB for PDF compatibility.\r\n * H: 0-360, S: 0-100, L: 0-100\r\n * Returns [R, G, B] where each component is 0-255\r\n */\r\nfunction hslToRgb(h: number, s: number, l: number): [number, number, number] {\r\n h = h / 360;\r\n s = s / 100;\r\n l = l / 100;\r\n\r\n const q = l < 0.5 ? l * (1 + s) : l + s - l * s;\r\n const p = 2 * l - q;\r\n\r\n const hueToRgb = (t: number): number => {\r\n if (t < 0) t += 1;\r\n if (t > 1) t -= 1;\r\n if (t < 1 / 6) return p + (q - p) * 6 * t;\r\n if (t < 1 / 2) return q;\r\n if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;\r\n return p;\r\n };\r\n\r\n const r = Math.round(hueToRgb(h + 1 / 3) * 255);\r\n const g = Math.round(hueToRgb(h) * 255);\r\n const b = Math.round(hueToRgb(h - 1 / 3) * 255);\r\n\r\n return [r, g, b];\r\n}\r\n\r\n/**\r\n * Generate distinct colors for legend rows.\r\n * Uses a predefined palette or auto-generates RGB colors (for PDF compatibility).\r\n */\r\nfunction generateLegendColors(count: number, palette?: 'auto' | string[]): string[] {\r\n if (Array.isArray(palette)) {\r\n // Use provided palette, cycling if needed\r\n const colors: string[] = [];\r\n for (let i = 0; i < count; i++) {\r\n colors.push(palette[i % palette.length]);\r\n }\r\n return colors;\r\n }\r\n\r\n // Auto-generate colors using HSL then convert to RGB for PDF compatibility\r\n const colors: string[] = [];\r\n for (let i = 0; i < count; i++) {\r\n const hue = (i * 360) / count;\r\n const saturation = 65 + (i % 3) * 10;\r\n const lightness = 50 + (i % 2) * 10;\r\n\r\n // Convert to RGB for jsPDF compatibility\r\n const [r, g, b] = hslToRgb(hue, saturation, lightness);\r\n colors.push(`rgb(${r},${g},${b})`);\r\n }\r\n return colors;\r\n}\r\n\r\nimport { isRecord, getProp } from './typeGuards';\r\n\r\nexport const applyLegendFilter = (\r\n legendData: unknown[],\r\n legend: LegendElement,\r\n viewports: unknown[],\r\n viewportClipPolygonsLocal: Record<string, Array<Array<{ x: number; y: number }>>>,\r\n viewportRenderInfo: Record<string, { transform?: unknown }>\r\n): unknown[] => {\r\n // Filter by class + where\r\n let rows = Array.isArray(legendData)\r\n ? legendData.filter((row) => matchesV2Filter(row, legend.class, legend.where))\r\n : [];\r\n if (!rows.length) return rows;\r\n\r\n if (legend.clipToViewport) {\r\n const targetViewportId = legend.viewport;\r\n const polys = targetViewportId ? viewportClipPolygonsLocal[targetViewportId] : null;\r\n const vpInfo = targetViewportId ? viewportRenderInfo[targetViewportId] : null;\r\n const t = isRecord(vpInfo) ? getProp(vpInfo, 'transform') : null;\r\n if (polys && polys.length && isRecord(t)) {\r\n const viewMinX = getProp(t, 'viewMinX');\r\n const viewMaxZ = getProp(t, 'viewMaxZ');\r\n if (typeof viewMinX === 'number' && typeof viewMaxZ === 'number') {\r\n rows = rows.filter((row) => {\r\n const rowX = getProp(row, 'x');\r\n const rowZ = getProp(row, 'z');\r\n if (!Number.isFinite(rowX) || !Number.isFinite(rowZ)) return false;\r\n const viewX = Number(rowX) - viewMinX;\r\n const viewY = viewMaxZ - Number(rowZ);\r\n return polys.some((poly) => pointInPolygon(poly, viewX, viewY));\r\n });\r\n }\r\n }\r\n }\r\n\r\n return rows;\r\n};\r\n\r\nexport interface LegendResult {\r\n svg: string;\r\n colorMap?: Map<string, string>; // Maps property value to color\r\n}\r\n\r\nexport const buildLegendGroup = (\r\n legend: LegendElement,\r\n styles: StyleMap | undefined,\r\n page: PageSpec,\r\n marginMm: number | undefined,\r\n legendData: unknown[],\r\n fillOpacity?: number\r\n): LegendResult | null => {\r\n if (!legend || !legendData || !legendData.length) return null;\r\n\r\n // Debug: Log raw input data\r\n // console.log(`[LEGEND INPUT] Received ${legendData.length} items for legend \"${legend.id}\"`);\r\n // if (legend.groupBy) {\r\n // // Count duplicates by groupBy property\r\n // const counts = new Map<string, number>();\r\n // for (const item of legendData) {\r\n // const key = String(resolvePath(item, legend.groupBy) ?? '');\r\n // counts.set(key, (counts.get(key) || 0) + 1);\r\n // }\r\n // console.log('[LEGEND INPUT] Items per group (before grouping):', Array.from(counts.entries()).map(([k, v]) => `${k}: ${v}`).join(', '));\r\n // }\r\n\r\n const pageMargin = typeof marginMm === 'number' ? marginMm : 0;\r\n const fontStyle = (legend.textStyle && styles?.[legend.textStyle]) || styles?.['body'];\r\n const fontSizeMm = typeof fontStyle?.fontSizeMm === 'number' ? fontStyle.fontSizeMm : 5;\r\n const fontFamily = fontStyle?.fontFamily ?? 'Arial, sans-serif';\r\n const fontColor = isRecord(fontStyle) ? (getProp(fontStyle, 'color') ?? '#000') : '#000';\r\n\r\n // Show color column if enabled (but swatches will be empty if no fills configured)\r\n const showColorColumn = legend.showColorColumn !== false;\r\n const colorColumnWidthMm = showColorColumn ? (legend.colorColumnWidthMm ?? DEFAULT_LEGEND_SWATCH_WIDTH_MM) : 0;\r\n const hasFills = fillOpacity !== undefined;\r\n // console.log(`[LEGEND RENDER] fillOpacity=${fillOpacity}, hasFills=${hasFills}, showColorColumn=${showColorColumn}`);\r\n const cellPaddingMm = legend.cellPaddingMm ?? DEFAULT_LEGEND_CELL_PADDING_MM;\r\n const borderStrokeWidthMm = legend.borderStrokeWidthMm ?? DEFAULT_LEGEND_BORDER_WIDTH_MM;\r\n const borderStrokeColor = legend.borderStrokeColor ?? '#000000';\r\n const gridStrokeWidthMm = legend.gridStrokeWidthMm ?? DEFAULT_LEGEND_GRID_WIDTH_MM;\r\n const gridStrokeColor = legend.gridStrokeColor ?? '#000000';\r\n const headerStrokeWidthMm = legend.headerStrokeWidthMm ?? DEFAULT_LEGEND_HEADER_WIDTH_MM;\r\n const headerStrokeColor = legend.headerStrokeColor ?? '#000000';\r\n const anchor = legend.anchor ?? 'top-right';\r\n const legendMarginMm = legend.marginMm ?? DEFAULT_LEGEND_OFFSET_MM;\r\n\r\n // Group rows if groupBy is specified\r\n let processedData = legendData;\r\n if (legend.groupBy && typeof legend.groupBy === 'string') {\r\n const groups = new Map<string, unknown[]>();\r\n\r\n // Group rows by the groupBy property value\r\n for (const row of legendData) {\r\n const groupKey = String(resolvePath(row, legend.groupBy) ?? '');\r\n if (!groups.has(groupKey)) {\r\n groups.set(groupKey, []);\r\n }\r\n groups.get(groupKey)!.push(row);\r\n }\r\n\r\n // console.log(`[LEGEND GROUPING] Total input rows: ${legendData.length}, Groups created: ${groups.size}`);\r\n // for (const [key, rows] of groups.entries()) {\r\n // if (rows.length > 1) {\r\n // console.log(`[LEGEND GROUPING] Group \"${key}\": ${rows.length} rows`);\r\n // }\r\n // }\r\n\r\n // Aggregate each group\r\n processedData = Array.from(groups.values()).map((groupRows) => {\r\n if (groupRows.length === 0) return groupRows[0];\r\n if (groupRows.length === 1) return groupRows[0];\r\n\r\n // Create aggregated row (ensure first row is object-like before spreading)\r\n const firstRow = groupRows[0];\r\n const aggregated: any = typeof firstRow === 'object' && firstRow !== null ? { ...(firstRow as any) } : {};\r\n\r\n // For each column, aggregate values\r\n for (const col of legend.columns) {\r\n const values: any[] = [];\r\n for (const row of groupRows) {\r\n const val = resolvePath(row, col.property);\r\n if (val !== undefined && val !== null) {\r\n values.push(val);\r\n }\r\n }\r\n\r\n if (values.length === 0) continue;\r\n\r\n // Check if all values are numeric - if so, sum them\r\n const allNumeric = values.every((v) => {\r\n const num = typeof v === 'number' ? v : parseFloat(String(v));\r\n return !isNaN(num) && Number.isFinite(num);\r\n });\r\n\r\n if (allNumeric) {\r\n // Sum numerical values\r\n const sum = values.reduce((acc, v) => {\r\n const num = typeof v === 'number' ? v : parseFloat(String(v));\r\n return acc + num;\r\n }, 0);\r\n\r\n // Debug logging for aggregation\r\n // if (groupRows.length > 1 && legend.groupBy) {\r\n // const groupKey = resolvePath(groupRows[0], legend.groupBy);\r\n // console.log(`[LEGEND AGGREGATION] Group \"${groupKey}\", Column \"${col.property}\":`, {\r\n // itemCount: values.length,\r\n // values: values,\r\n // sum: sum\r\n // });\r\n // }\r\n\r\n // Set the aggregated value in the nested property structure\r\n const pathParts = col.property.split('.');\r\n let target = aggregated;\r\n for (let i = 0; i < pathParts.length - 1; i++) {\r\n if (!target[pathParts[i]]) {\r\n target[pathParts[i]] = {};\r\n }\r\n target = target[pathParts[i]];\r\n }\r\n target[pathParts[pathParts.length - 1]] = sum;\r\n }\r\n // For non-numeric, keep the first value (already in aggregated from spread)\r\n }\r\n\r\n return aggregated;\r\n });\r\n }\r\n\r\n // Generate colors if assignColors is enabled\r\n let generatedColors: string[] | null = null;\r\n let colorMap: Map<string, string> | undefined;\r\n\r\n if (legend.assignColors?.enabled) {\r\n const palette = legend.assignColors.palette ?? 'auto';\r\n generatedColors = generateLegendColors(processedData.length, palette);\r\n // console.log(`[LEGEND COLORS] assignColors enabled, generated ${generatedColors.length} colors`);\r\n\r\n // Build color map based on groupBy property\r\n if (legend.groupBy) {\r\n colorMap = new Map();\r\n for (let i = 0; i < processedData.length; i++) {\r\n const row = processedData[i];\r\n const groupValue = String(resolvePath(row, legend.groupBy) ?? '');\r\n if (!colorMap.has(groupValue)) {\r\n colorMap.set(groupValue, generatedColors[i]);\r\n // console.log(`[LEGEND COLORS] Mapped \"${groupValue}\" -> ${generatedColors[i]}`);\r\n }\r\n }\r\n // console.log(`[LEGEND COLORS] Generated ${colorMap.size} colors for groupBy=\"${legend.groupBy}\"`);\r\n } else {\r\n console.warn(`[LEGEND COLORS] assignColors enabled but no groupBy property set`);\r\n }\r\n }\r\n\r\n const rowsMapped = processedData.map((row: unknown, index: number) => {\r\n const values = legend.columns.map((col) => {\r\n const raw = resolvePath(row, col.property);\r\n return formatLegendValue(raw, col.format as any);\r\n });\r\n\r\n // Use generated color if assignColors is enabled, otherwise sample from item.color\r\n let swatchColor: string;\r\n if (generatedColors) {\r\n swatchColor = generatedColors[index];\r\n } else {\r\n const colorValue = getProp(row, 'color');\r\n const rgba = parseLegendColor(colorValue, values[0] ?? JSON.stringify(row));\r\n swatchColor = `rgb(${rgba[0]},${rgba[1]},${rgba[2]})`;\r\n }\r\n\r\n return { values, color: swatchColor };\r\n });\r\n\r\n const columnLabels = legend.columns.map((c) => ({\r\n label: c.label,\r\n minWidthMm: c.minWidthMm,\r\n maxWidthMm: c.maxWidthMm\r\n }));\r\n const { colWidthsMm, columnCount } = computeLegendColumnWidths(\r\n columnLabels,\r\n rowsMapped,\r\n fontSizeMm,\r\n cellPaddingMm,\r\n colorColumnWidthMm,\r\n fontFamily\r\n );\r\n\r\n const rowHeightMm = fontSizeMm + cellPaddingMm * 2;\r\n const headerHeightMm = rowHeightMm;\r\n const tableWidthMm = colWidthsMm.reduce((sum, w) => sum + w, 0);\r\n\r\n // Check if summary is enabled\r\n const summaryEnabled = legend.summary?.enabled === true;\r\n const summaryLabel = legend.summary?.label ?? 'Total';\r\n const summaryRowCount = summaryEnabled ? 1 : 0;\r\n\r\n const tableHeightMm = headerHeightMm + rowsMapped.length * rowHeightMm + summaryRowCount * rowHeightMm;\r\n\r\n const anchorPos = legend.anchorPositionMm;\r\n const hasAnchorPos =\r\n anchorPos &&\r\n typeof anchorPos.xMm === 'number' &&\r\n Number.isFinite(anchorPos.xMm) &&\r\n typeof anchorPos.yMm === 'number' &&\r\n Number.isFinite(anchorPos.yMm);\r\n\r\n let originXmm = pageMargin + legendMarginMm;\r\n let originYmm = pageMargin + legendMarginMm;\r\n\r\n if (hasAnchorPos) {\r\n const { xMm, yMm } = anchorPos as { xMm: number; yMm: number };\r\n switch (anchor) {\r\n case 'top-left':\r\n originXmm = xMm;\r\n originYmm = yMm;\r\n break;\r\n case 'top-right':\r\n originXmm = xMm - tableWidthMm;\r\n originYmm = yMm;\r\n break;\r\n case 'bottom-left':\r\n originXmm = xMm;\r\n originYmm = yMm - tableHeightMm;\r\n break;\r\n case 'bottom-right':\r\n default:\r\n originXmm = xMm - tableWidthMm;\r\n originYmm = yMm - tableHeightMm;\r\n break;\r\n }\r\n } else {\r\n if (anchor === 'top-right' || anchor === 'bottom-right') {\r\n originXmm = page.widthMm - pageMargin - legendMarginMm - tableWidthMm;\r\n }\r\n if (anchor === 'bottom-right' || anchor === 'bottom-left') {\r\n originYmm = page.heightMm - pageMargin - legendMarginMm - tableHeightMm;\r\n }\r\n }\r\n\r\n const colXmm: number[] = [];\r\n let acc = 0;\r\n colWidthsMm.forEach((w) => {\r\n colXmm.push(acc);\r\n acc += w;\r\n });\r\n\r\n const rects: string[] = [];\r\n const texts: string[] = [];\r\n const lines: string[] = [];\r\n\r\n const dataColStartIdx = showColorColumn ? 1 : 0;\r\n const contentOriginXmm = originXmm + colWidthsMm[0];\r\n const headerBottomYmm = originYmm + headerHeightMm;\r\n\r\n lines.push(\r\n `<line x1=\"${contentOriginXmm}\" y1=\"${originYmm}\" x2=\"${originXmm + tableWidthMm}\" y2=\"${originYmm}\" stroke=\"${borderStrokeColor}\" stroke-width=\"${borderStrokeWidthMm}\" />`\r\n );\r\n lines.push(\r\n `<line x1=\"${contentOriginXmm}\" y1=\"${originYmm}\" x2=\"${contentOriginXmm}\" y2=\"${headerBottomYmm}\" stroke=\"${borderStrokeColor}\" stroke-width=\"${borderStrokeWidthMm}\" />`\r\n );\r\n // Bottom border: if summary enabled, only under numbers (not under label)\r\n const bottomBorderStartX = summaryEnabled ? contentOriginXmm : originXmm;\r\n lines.push(\r\n `<line x1=\"${bottomBorderStartX}\" y1=\"${originYmm + tableHeightMm}\" x2=\"${originXmm + tableWidthMm}\" y2=\"${originYmm + tableHeightMm}\" stroke=\"${borderStrokeColor}\" stroke-width=\"${borderStrokeWidthMm}\" />`\r\n );\r\n lines.push(\r\n `<line x1=\"${originXmm + tableWidthMm}\" y1=\"${originYmm}\" x2=\"${originXmm + tableWidthMm}\" y2=\"${originYmm + tableHeightMm}\" stroke=\"${borderStrokeColor}\" stroke-width=\"${borderStrokeWidthMm}\" />`\r\n );\r\n // Left edge - stops before summary row if summary enabled\r\n const leftEdgeEndYmm = summaryEnabled\r\n ? originYmm + headerHeightMm + rowsMapped.length * rowHeightMm\r\n : originYmm + tableHeightMm;\r\n lines.push(\r\n `<line x1=\"${originXmm}\" y1=\"${headerBottomYmm}\" x2=\"${originXmm}\" y2=\"${leftEdgeEndYmm}\" stroke=\"${borderStrokeColor}\" stroke-width=\"${borderStrokeWidthMm}\" />`\r\n );\r\n\r\n // Color column divider - extends all the way down\r\n lines.push(\r\n `<line x1=\"${contentOriginXmm}\" y1=\"${headerBottomYmm}\" x2=\"${contentOriginXmm}\" y2=\"${originYmm + tableHeightMm}\" stroke=\"${borderStrokeColor}\" stroke-width=\"${borderStrokeWidthMm}\" />`\r\n );\r\n\r\n lines.push(\r\n `<line x1=\"${originXmm}\" y1=\"${originYmm + headerHeightMm}\" x2=\"${originXmm + tableWidthMm}\" y2=\"${originYmm + headerHeightMm}\" stroke=\"${headerStrokeColor}\" stroke-width=\"${headerStrokeWidthMm}\" />`\r\n );\r\n\r\n for (let i = 2; i < columnCount; i++) {\r\n const x = originXmm + colXmm[i];\r\n lines.push(\r\n `<line x1=\"${x}\" y1=\"${originYmm}\" x2=\"${x}\" y2=\"${originYmm + tableHeightMm}\" stroke=\"${gridStrokeColor}\" stroke-width=\"${borderStrokeWidthMm}\" />`\r\n );\r\n }\r\n\r\n for (let r = 0; r <= rowsMapped.length; r++) {\r\n // Skip last grid line if summary enabled (we draw a heavier separator line instead)\r\n if (r === rowsMapped.length && summaryEnabled) continue;\r\n\r\n const y = originYmm + headerHeightMm + r * rowHeightMm;\r\n lines.push(\r\n `<line x1=\"${originXmm}\" y1=\"${y}\" x2=\"${originXmm + tableWidthMm}\" y2=\"${y}\" stroke=\"${gridStrokeColor}\" stroke-width=\"${borderStrokeWidthMm}\" />`\r\n );\r\n }\r\n\r\n const textYOffsetMm = computeLegendTextYOffset(fontSizeMm);\r\n legend.columns.slice(0, columnCount - dataColStartIdx).forEach((col, idx) => {\r\n const colStart = originXmm + colXmm[idx + dataColStartIdx];\r\n const colWidth = colWidthsMm[idx + dataColStartIdx];\r\n const innerPad = cellPaddingMm + gridStrokeWidthMm * 0.5;\r\n const x =\r\n col.align === 'center'\r\n ? colStart + colWidth / 2\r\n : col.align === 'right'\r\n ? colStart + colWidth - innerPad\r\n : colStart + innerPad;\r\n const y = originYmm + headerHeightMm / 2 + textYOffsetMm;\r\n const anchorText = col.align === 'center' ? 'middle' : col.align === 'right' ? 'end' : 'start';\r\n texts.push(\r\n `<text x=\"${x}\" y=\"${y}\" font-family=\"${fontFamily}\" font-size=\"${fontSizeMm}\" fill=\"${fontColor}\" dominant-baseline=\"middle\" text-anchor=\"${anchorText}\">${col.label}</text>`\r\n );\r\n });\r\n\r\n const swatchOpacity = typeof fillOpacity === 'number' ? Math.min(Math.max(fillOpacity, 0), 1) : 1;\r\n\r\n rowsMapped.slice(0, MAX_LEGEND_ROWS).forEach((row, rIndex) => {\r\n const yTop = originYmm + headerHeightMm + rIndex * rowHeightMm;\r\n\r\n if (showColorColumn) {\r\n // Only show fill colors if the viewport has fills configured\r\n if (hasFills) {\r\n // row.color can be either a CSS color string (from generated colors) or RGB string\r\n const swatchFill = row.color; // Already a CSS color string\r\n const opacityAttr = swatchOpacity < 1 ? ` fill-opacity=\"${swatchOpacity.toFixed(3)}\"` : '';\r\n rects.push(\r\n `<rect x=\"${originXmm + colXmm[0]}\" y=\"${yTop}\" width=\"${colWidthsMm[0]}\" height=\"${rowHeightMm}\" fill=\"${swatchFill}\"${opacityAttr} stroke=\"none\" />`\r\n );\r\n } else {\r\n // Empty swatch when no fills configured - just the border cell\r\n rects.push(\r\n `<rect x=\"${originXmm + colXmm[0]}\" y=\"${yTop}\" width=\"${colWidthsMm[0]}\" height=\"${rowHeightMm}\" fill=\"none\" stroke=\"none\" />`\r\n );\r\n }\r\n }\r\n\r\n legend.columns.slice(0, columnCount - dataColStartIdx).forEach((col, cIdx) => {\r\n const text = row.values[cIdx] ?? '';\r\n if (!text) return;\r\n const colStart = originXmm + colXmm[cIdx + dataColStartIdx];\r\n const colWidth = colWidthsMm[cIdx + dataColStartIdx];\r\n const innerPad = cellPaddingMm + gridStrokeWidthMm * 0.5;\r\n const x =\r\n col.align === 'center'\r\n ? colStart + colWidth / 2\r\n : col.align === 'right'\r\n ? colStart + colWidth - innerPad\r\n : colStart + innerPad;\r\n const y = yTop + rowHeightMm / 2 + textYOffsetMm;\r\n const anchorText = col.align === 'center' ? 'middle' : col.align === 'right' ? 'end' : 'start';\r\n texts.push(\r\n `<text x=\"${x}\" y=\"${y}\" font-family=\"${fontFamily}\" font-size=\"${fontSizeMm}\" fill=\"${fontColor}\" dominant-baseline=\"middle\" text-anchor=\"${anchorText}\">${text}</text>`\r\n );\r\n });\r\n });\r\n\r\n // Render summary row (if enabled)\r\n if (summaryEnabled) {\r\n const summaryRowIndex = rowsMapped.length;\r\n const yTop = originYmm + headerHeightMm + summaryRowIndex * rowHeightMm;\r\n\r\n // Calculate summary values for columns with summary: true\r\n const summaryValues = legend.columns.map((col) => {\r\n if (!col.summary) return '';\r\n\r\n // Sum all numerical values in this column (use processedData to reflect grouping)\r\n let sum = 0;\r\n let hasValues = false;\r\n for (const dataRow of processedData) {\r\n const rawValue = resolvePath(dataRow, col.property);\r\n const numValue = typeof rawValue === 'number' ? rawValue : parseFloat(String(rawValue));\r\n if (!isNaN(numValue) && Number.isFinite(numValue)) {\r\n sum += numValue;\r\n hasValues = true;\r\n }\r\n }\r\n\r\n // Format the sum using the column's format settings\r\n return hasValues ? formatLegendValue(sum, col.format as any) : '';\r\n });\r\n\r\n // Add heavier border line above summary row\r\n lines.push(\r\n `<line x1=\"${originXmm}\" y1=\"${yTop}\" x2=\"${originXmm + tableWidthMm}\" y2=\"${yTop}\" stroke=\"${headerStrokeColor}\" stroke-width=\"${headerStrokeWidthMm}\" />`\r\n );\r\n\r\n // Render summary label aligned with first data column\r\n const innerPad = cellPaddingMm + gridStrokeWidthMm * 0.5;\r\n const labelX = contentOriginXmm + innerPad;\r\n const labelY = yTop + rowHeightMm / 2 + textYOffsetMm;\r\n texts.push(\r\n `<text x=\"${labelX}\" y=\"${labelY}\" font-family=\"${fontFamily}\" font-size=\"${fontSizeMm}\" fill=\"${fontColor}\" font-weight=\"bold\" dominant-baseline=\"middle\" text-anchor=\"start\">${summaryLabel}</text>`\r\n );\r\n\r\n // Render summary values for other columns\r\n legend.columns.slice(1, columnCount - dataColStartIdx).forEach((col, cIdx) => {\r\n const summaryText = summaryValues[cIdx + 1] ?? '';\r\n if (!summaryText) return;\r\n\r\n const colStart = originXmm + colXmm[cIdx + dataColStartIdx + 1];\r\n const colWidth = colWidthsMm[cIdx + dataColStartIdx + 1];\r\n const x =\r\n col.align === 'center'\r\n ? colStart + colWidth / 2\r\n : col.align === 'right'\r\n ? colStart + colWidth - innerPad\r\n : colStart + innerPad;\r\n const y = yTop + rowHeightMm / 2 + textYOffsetMm;\r\n const anchorText = col.align === 'center' ? 'middle' : col.align === 'right' ? 'end' : 'start';\r\n texts.push(\r\n `<text x=\"${x}\" y=\"${y}\" font-family=\"${fontFamily}\" font-size=\"${fontSizeMm}\" fill=\"${fontColor}\" font-weight=\"bold\" dominant-baseline=\"middle\" text-anchor=\"${anchorText}\">${summaryText}</text>`\r\n );\r\n });\r\n }\r\n\r\n const svg = [`<g id=\"legend\">`, ...rects, ...lines, ...texts, `</g>`].join('');\r\n return { svg, colorMap };\r\n};\r\n"]}
|
|
1
|
+
{"version":3,"file":"legendRender.js","sourceRoot":"/","sources":["layout/legendRender.ts"],"names":[],"mappings":"AACA,OAAO,EACH,8BAA8B,EAC9B,8BAA8B,EAC9B,8BAA8B,EAC9B,4BAA4B,EAC5B,8BAA8B,EAC9B,wBAAwB,EACxB,eAAe,EAClB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACH,yBAAyB,EACzB,wBAAwB,EACxB,gBAAgB,EAChB,iBAAiB,EACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C;;;;GAIG;AACH,SAAS,QAAQ,CAAC,CAAS,EAAE,CAAS,EAAE,CAAS;IAC7C,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;IACZ,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;IACZ,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;IAEZ,MAAM,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAChD,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAEpB,MAAM,QAAQ,GAAG,CAAC,CAAS,EAAU,EAAE;QACnC,IAAI,CAAC,GAAG,CAAC;YAAE,CAAC,IAAI,CAAC,CAAC;QAClB,IAAI,CAAC,GAAG,CAAC;YAAE,CAAC,IAAI,CAAC,CAAC;QAClB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC1C,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO,CAAC,CAAC;QACxB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;QACpD,OAAO,CAAC,CAAC;IACb,CAAC,CAAC;IAEF,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;IAChD,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;IACxC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;IAEhD,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AACrB,CAAC;AAED;;;GAGG;AACH,SAAS,oBAAoB,CAAC,KAAa,EAAE,OAA2B;IACpE,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACzB,0CAA0C;QAC1C,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7B,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;QAC7C,CAAC;QACD,OAAO,MAAM,CAAC;IAClB,CAAC;IAED,2EAA2E;IAC3E,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,KAAK,CAAC;QAC9B,MAAM,UAAU,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;QACrC,MAAM,SAAS,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;QAEpC,yCAAyC;QACzC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;QACvD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEjD,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC7B,UAAqB,EACrB,MAAqB,EACrB,SAAoB,EACpB,yBAAiF,EACjF,kBAA2D,EAClD,EAAE;IACX,0BAA0B;IAC1B,IAAI,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC;QAChC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,eAAe,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QAC9E,CAAC,CAAC,EAAE,CAAC;IACT,IAAI,CAAC,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAE9B,IAAI,MAAM,CAAC,cAAc,EAAE,CAAC;QACxB,MAAM,gBAAgB,GAAG,MAAM,CAAC,QAAQ,CAAC;QACzC,MAAM,KAAK,GAAG,gBAAgB,CAAC,CAAC,CAAC,yBAAyB,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACpF,MAAM,MAAM,GAAG,gBAAgB,CAAC,CAAC,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC9E,MAAM,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACjE,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,IAAI,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;YACvC,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;YACxC,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;YACxC,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;gBAC/D,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE;oBACvB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;oBAC/B,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;oBAC/B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;wBAAE,OAAO,KAAK,CAAC;oBACnE,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC;oBACtC,MAAM,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;oBACtC,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;gBACpE,CAAC,CAAC,CAAC;YACP,CAAC;QACL,CAAC;IACL,CAAC;IAED,OAAO,IAAI,CAAC;AAChB,CAAC,CAAC;AAOF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC5B,MAAqB,EACrB,MAA4B,EAC5B,IAAc,EACd,QAA4B,EAC5B,UAAqB,EACrB,WAAoB,EACD,EAAE;IACrB,IAAI,CAAC,MAAM,IAAI,CAAC,UAAU,IAAI,CAAC,UAAU,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAE9D,4BAA4B;IAC5B,+FAA+F;IAC/F,wBAAwB;IACxB,4CAA4C;IAC5C,8CAA8C;IAC9C,qCAAqC;IACrC,mEAAmE;IACnE,mDAAmD;IACnD,MAAM;IACN,6IAA6I;IAC7I,IAAI;IAEJ,MAAM,UAAU,GAAG,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/D,MAAM,SAAS,GAAG,CAAC,MAAM,CAAC,SAAS,IAAI,MAAM,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC;IACvF,MAAM,UAAU,GAAG,OAAO,SAAS,EAAE,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IACxF,MAAM,UAAU,GAAG,SAAS,EAAE,UAAU,IAAI,mBAAmB,CAAC;IAChE,MAAM,SAAS,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IAEzF,mFAAmF;IACnF,MAAM,eAAe,GAAG,MAAM,CAAC,eAAe,KAAK,KAAK,CAAC;IACzD,MAAM,kBAAkB,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,kBAAkB,IAAI,8BAA8B,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/G,MAAM,QAAQ,GAAG,WAAW,KAAK,SAAS,CAAC;IAC3C,uHAAuH;IACvH,MAAM,aAAa,GAAG,MAAM,CAAC,aAAa,IAAI,8BAA8B,CAAC;IAC7E,MAAM,mBAAmB,GAAG,MAAM,CAAC,mBAAmB,IAAI,8BAA8B,CAAC;IACzF,MAAM,iBAAiB,GAAG,MAAM,CAAC,iBAAiB,IAAI,SAAS,CAAC;IAChE,MAAM,iBAAiB,GAAG,MAAM,CAAC,iBAAiB,IAAI,4BAA4B,CAAC;IACnF,MAAM,eAAe,GAAG,MAAM,CAAC,eAAe,IAAI,SAAS,CAAC;IAC5D,MAAM,mBAAmB,GAAG,MAAM,CAAC,mBAAmB,IAAI,8BAA8B,CAAC;IACzF,MAAM,iBAAiB,GAAG,MAAM,CAAC,iBAAiB,IAAI,SAAS,CAAC;IAChE,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,WAAW,CAAC;IAC5C,MAAM,cAAc,GAAG,MAAM,CAAC,QAAQ,IAAI,wBAAwB,CAAC;IAEnE,qCAAqC;IACrC,IAAI,aAAa,GAAG,UAAU,CAAC;IAC/B,IAAI,MAAM,CAAC,OAAO,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;QACvD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAqB,CAAC;QAE5C,2CAA2C;QAC3C,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;YAC3B,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;YAChE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACxB,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;YAC7B,CAAC;YACD,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpC,CAAC;QAED,2GAA2G;QAC3G,gDAAgD;QAChD,2BAA2B;QAC3B,4EAA4E;QAC5E,MAAM;QACN,IAAI;QAEJ,uBAAuB;QACvB,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE;YAC1D,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC;YAChD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC;YAEhD,2EAA2E;YAC3E,MAAM,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;YAC9B,MAAM,UAAU,GAAQ,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,GAAI,QAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAE1G,oCAAoC;YACpC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBAC/B,MAAM,MAAM,GAAU,EAAE,CAAC;gBACzB,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;oBAC1B,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;oBAC3C,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;wBACpC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;oBACrB,CAAC;gBACL,CAAC;gBAED,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;oBAAE,SAAS;gBAElC,oDAAoD;gBACpD,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;oBAClC,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;oBAC9D,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;gBAC/C,CAAC,CAAC,CAAC;gBAEH,IAAI,UAAU,EAAE,CAAC;oBACb,uBAAuB;oBACvB,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;wBACjC,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;wBAC9D,OAAO,GAAG,GAAG,GAAG,CAAC;oBACrB,CAAC,EAAE,CAAC,CAAC,CAAC;oBAEN,gCAAgC;oBAChC,gDAAgD;oBAChD,gEAAgE;oBAChE,yFAAyF;oBACzF,gCAAgC;oBAChC,sBAAsB;oBACtB,eAAe;oBACf,QAAQ;oBACR,IAAI;oBAEJ,4DAA4D;oBAC5D,MAAM,SAAS,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;oBAC1C,IAAI,MAAM,GAAG,UAAU,CAAC;oBACxB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;wBAC5C,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;4BACxB,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;wBAC9B,CAAC;wBACD,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;oBAClC,CAAC;oBACD,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;gBAClD,CAAC;gBACD,4EAA4E;YAChF,CAAC;YAED,OAAO,UAAU,CAAC;QACtB,CAAC,CAAC,CAAC;IACP,CAAC;IAED,6CAA6C;IAC7C,IAAI,eAAe,GAAoB,IAAI,CAAC;IAC5C,IAAI,QAAyC,CAAC;IAE9C,IAAI,MAAM,CAAC,YAAY,EAAE,OAAO,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,MAAM,CAAC,YAAY,CAAC,OAAO,IAAI,MAAM,CAAC;QACtD,eAAe,GAAG,oBAAoB,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACtE,mGAAmG;QAEnG,4CAA4C;QAC5C,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,QAAQ,GAAG,IAAI,GAAG,EAAE,CAAC;YACrB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,aAAa,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC5C,MAAM,GAAG,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;gBAC7B,MAAM,UAAU,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;gBAClE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;oBAC5B,QAAQ,CAAC,GAAG,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;oBAC7C,kFAAkF;gBACtF,CAAC;YACL,CAAC;YACD,oGAAoG;QACxG,CAAC;aAAM,CAAC;YACJ,OAAO,CAAC,IAAI,CAAC,kEAAkE,CAAC,CAAC;QACrF,CAAC;IACL,CAAC;IAED,MAAM,UAAU,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,GAAY,EAAE,KAAa,EAAE,EAAE;QACjE,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;YACtC,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC3C,OAAO,iBAAiB,CAAC,GAAG,EAAE,GAAG,CAAC,MAAa,CAAC,CAAC;QACrD,CAAC,CAAC,CAAC;QAEH,mFAAmF;QACnF,IAAI,WAAmB,CAAC;QACxB,IAAI,eAAe,EAAE,CAAC;YAClB,WAAW,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;QACzC,CAAC;aAAM,CAAC;YACJ,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YACzC,MAAM,IAAI,GAAG,gBAAgB,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;YAC5E,WAAW,GAAG,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC;QAC1D,CAAC;QAED,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC5C,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,UAAU,EAAE,CAAC,CAAC,UAAU;QACxB,UAAU,EAAE,CAAC,CAAC,UAAU;KAC3B,CAAC,CAAC,CAAC;IACJ,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,GAAG,yBAAyB,CAC1D,YAAY,EACZ,UAAU,EACV,UAAU,EACV,aAAa,EACb,kBAAkB,EAClB,UAAU,CACb,CAAC;IAEF,MAAM,WAAW,GAAG,UAAU,GAAG,aAAa,GAAG,CAAC,CAAC;IACnD,MAAM,cAAc,GAAG,WAAW,CAAC;IACnC,MAAM,YAAY,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAEhE,8BAA8B;IAC9B,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACxD,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,EAAE,KAAK,IAAI,OAAO,CAAC;IACtD,MAAM,eAAe,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAE/C,MAAM,aAAa,GAAG,cAAc,GAAG,UAAU,CAAC,MAAM,GAAG,WAAW,GAAG,eAAe,GAAG,WAAW,CAAC;IAEvG,MAAM,SAAS,GAAG,MAAM,CAAC,gBAAgB,CAAC;IAC1C,MAAM,YAAY,GACd,SAAS;QACT,OAAO,SAAS,CAAC,GAAG,KAAK,QAAQ;QACjC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC;QAC9B,OAAO,SAAS,CAAC,GAAG,KAAK,QAAQ;QACjC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAEnC,IAAI,SAAS,GAAG,UAAU,GAAG,cAAc,CAAC;IAC5C,IAAI,SAAS,GAAG,UAAU,GAAG,cAAc,CAAC;IAE5C,IAAI,YAAY,EAAE,CAAC;QACf,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,SAAyC,CAAC;QAC/D,QAAQ,MAAM,EAAE,CAAC;YACb,KAAK,UAAU;gBACX,SAAS,GAAG,GAAG,CAAC;gBAChB,SAAS,GAAG,GAAG,CAAC;gBAChB,MAAM;YACV,KAAK,WAAW;gBACZ,SAAS,GAAG,GAAG,GAAG,YAAY,CAAC;gBAC/B,SAAS,GAAG,GAAG,CAAC;gBAChB,MAAM;YACV,KAAK,aAAa;gBACd,SAAS,GAAG,GAAG,CAAC;gBAChB,SAAS,GAAG,GAAG,GAAG,aAAa,CAAC;gBAChC,MAAM;YACV,KAAK,cAAc,CAAC;YACpB;gBACI,SAAS,GAAG,GAAG,GAAG,YAAY,CAAC;gBAC/B,SAAS,GAAG,GAAG,GAAG,aAAa,CAAC;gBAChC,MAAM;QACd,CAAC;IACL,CAAC;SAAM,CAAC;QACJ,IAAI,MAAM,KAAK,WAAW,IAAI,MAAM,KAAK,cAAc,EAAE,CAAC;YACtD,SAAS,GAAG,IAAI,CAAC,OAAO,GAAG,UAAU,GAAG,cAAc,GAAG,YAAY,CAAC;QAC1E,CAAC;QACD,IAAI,MAAM,KAAK,cAAc,IAAI,MAAM,KAAK,aAAa,EAAE,CAAC;YACxD,SAAS,GAAG,IAAI,CAAC,QAAQ,GAAG,UAAU,GAAG,cAAc,GAAG,aAAa,CAAC;QAC5E,CAAC;IACL,CAAC;IAED,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;QACtB,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACjB,GAAG,IAAI,CAAC,CAAC;IACb,CAAC,CAAC,CAAC;IAEH,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,MAAM,eAAe,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,MAAM,gBAAgB,GAAG,SAAS,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;IACpD,MAAM,eAAe,GAAG,SAAS,GAAG,cAAc,CAAC;IAEnD,KAAK,CAAC,IAAI,CACN,aAAa,gBAAgB,SAAS,SAAS,SAAS,SAAS,GAAG,YAAY,SAAS,SAAS,aAAa,iBAAiB,mBAAmB,mBAAmB,MAAM,CAC/K,CAAC;IACF,KAAK,CAAC,IAAI,CACN,aAAa,gBAAgB,SAAS,SAAS,SAAS,gBAAgB,SAAS,eAAe,aAAa,iBAAiB,mBAAmB,mBAAmB,MAAM,CAC7K,CAAC;IACF,0EAA0E;IAC1E,MAAM,kBAAkB,GAAG,cAAc,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS,CAAC;IACzE,KAAK,CAAC,IAAI,CACN,aAAa,kBAAkB,SAAS,SAAS,GAAG,aAAa,SAAS,SAAS,GAAG,YAAY,SAAS,SAAS,GAAG,aAAa,aAAa,iBAAiB,mBAAmB,mBAAmB,MAAM,CACjN,CAAC;IACF,KAAK,CAAC,IAAI,CACN,aAAa,SAAS,GAAG,YAAY,SAAS,SAAS,SAAS,SAAS,GAAG,YAAY,SAAS,SAAS,GAAG,aAAa,aAAa,iBAAiB,mBAAmB,mBAAmB,MAAM,CACvM,CAAC;IACF,0DAA0D;IAC1D,MAAM,cAAc,GAAG,cAAc;QACjC,CAAC,CAAC,SAAS,GAAG,cAAc,GAAG,UAAU,CAAC,MAAM,GAAG,WAAW;QAC9D,CAAC,CAAC,SAAS,GAAG,aAAa,CAAC;IAChC,KAAK,CAAC,IAAI,CACN,aAAa,SAAS,SAAS,eAAe,SAAS,SAAS,SAAS,cAAc,aAAa,iBAAiB,mBAAmB,mBAAmB,MAAM,CACpK,CAAC;IAEF,kDAAkD;IAClD,KAAK,CAAC,IAAI,CACN,aAAa,gBAAgB,SAAS,eAAe,SAAS,gBAAgB,SAAS,SAAS,GAAG,aAAa,aAAa,iBAAiB,mBAAmB,mBAAmB,MAAM,CAC7L,CAAC;IAEF,KAAK,CAAC,IAAI,CACN,aAAa,SAAS,SAAS,SAAS,GAAG,cAAc,SAAS,SAAS,GAAG,YAAY,SAAS,SAAS,GAAG,cAAc,aAAa,iBAAiB,mBAAmB,mBAAmB,MAAM,CAC1M,CAAC;IAEF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,MAAM,CAAC,GAAG,SAAS,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QAChC,KAAK,CAAC,IAAI,CACN,aAAa,CAAC,SAAS,SAAS,SAAS,CAAC,SAAS,SAAS,GAAG,aAAa,aAAa,eAAe,mBAAmB,mBAAmB,MAAM,CACvJ,CAAC;IACN,CAAC;IAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,oFAAoF;QACpF,IAAI,CAAC,KAAK,UAAU,CAAC,MAAM,IAAI,cAAc;YAAE,SAAS;QAExD,MAAM,CAAC,GAAG,SAAS,GAAG,cAAc,GAAG,CAAC,GAAG,WAAW,CAAC;QACvD,KAAK,CAAC,IAAI,CACN,aAAa,SAAS,SAAS,CAAC,SAAS,SAAS,GAAG,YAAY,SAAS,CAAC,aAAa,eAAe,mBAAmB,mBAAmB,MAAM,CACtJ,CAAC;IACN,CAAC;IAED,MAAM,aAAa,GAAG,wBAAwB,CAAC,UAAU,CAAC,CAAC;IAC3D,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,GAAG,eAAe,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QACxE,MAAM,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC,GAAG,GAAG,eAAe,CAAC,CAAC;QAC3D,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,GAAG,eAAe,CAAC,CAAC;QACpD,MAAM,QAAQ,GAAG,aAAa,GAAG,iBAAiB,GAAG,GAAG,CAAC;QACzD,MAAM,CAAC,GACH,GAAG,CAAC,KAAK,KAAK,QAAQ;YAClB,CAAC,CAAC,QAAQ,GAAG,QAAQ,GAAG,CAAC;YACzB,CAAC,CAAC,GAAG,CAAC,KAAK,KAAK,OAAO;gBACrB,CAAC,CAAC,QAAQ,GAAG,QAAQ,GAAG,QAAQ;gBAChC,CAAC,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAChC,MAAM,CAAC,GAAG,SAAS,GAAG,cAAc,GAAG,CAAC,GAAG,aAAa,CAAC;QACzD,MAAM,UAAU,GAAG,GAAG,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC;QAC/F,KAAK,CAAC,IAAI,CACN,YAAY,CAAC,QAAQ,CAAC,kBAAkB,UAAU,gBAAgB,UAAU,WAAW,SAAS,6CAA6C,UAAU,KAAK,GAAG,CAAC,KAAK,SAAS,CACjL,CAAC;IACN,CAAC,CAAC,CAAC;IAEH,MAAM,aAAa,GAAG,OAAO,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAElG,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;QACzD,MAAM,IAAI,GAAG,SAAS,GAAG,cAAc,GAAG,MAAM,GAAG,WAAW,CAAC;QAE/D,IAAI,eAAe,EAAE,CAAC;YAClB,6DAA6D;YAC7D,IAAI,QAAQ,EAAE,CAAC;gBACX,mFAAmF;gBACnF,MAAM,UAAU,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,6BAA6B;gBAC3D,MAAM,WAAW,GAAG,aAAa,GAAG,CAAC,CAAC,CAAC,CAAC,kBAAkB,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC3F,KAAK,CAAC,IAAI,CACN,YAAY,SAAS,GAAG,MAAM,CAAC,CAAC,CAAC,QAAQ,IAAI,YAAY,WAAW,CAAC,CAAC,CAAC,aAAa,WAAW,WAAW,UAAU,IAAI,WAAW,mBAAmB,CACzJ,CAAC;YACN,CAAC;iBAAM,CAAC;gBACJ,+DAA+D;gBAC/D,KAAK,CAAC,IAAI,CACN,YAAY,SAAS,GAAG,MAAM,CAAC,CAAC,CAAC,QAAQ,IAAI,YAAY,WAAW,CAAC,CAAC,CAAC,aAAa,WAAW,gCAAgC,CAClI,CAAC;YACN,CAAC;QACL,CAAC;QAED,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,GAAG,eAAe,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE;YACzE,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACpC,IAAI,CAAC,IAAI;gBAAE,OAAO;YAClB,MAAM,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC,IAAI,GAAG,eAAe,CAAC,CAAC;YAC5D,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,GAAG,eAAe,CAAC,CAAC;YACrD,MAAM,QAAQ,GAAG,aAAa,GAAG,iBAAiB,GAAG,GAAG,CAAC;YACzD,MAAM,CAAC,GACH,GAAG,CAAC,KAAK,KAAK,QAAQ;gBAClB,CAAC,CAAC,QAAQ,GAAG,QAAQ,GAAG,CAAC;gBACzB,CAAC,CAAC,GAAG,CAAC,KAAK,KAAK,OAAO;oBACrB,CAAC,CAAC,QAAQ,GAAG,QAAQ,GAAG,QAAQ;oBAChC,CAAC,CAAC,QAAQ,GAAG,QAAQ,CAAC;YAChC,MAAM,CAAC,GAAG,IAAI,GAAG,WAAW,GAAG,CAAC,GAAG,aAAa,CAAC;YACjD,MAAM,UAAU,GAAG,GAAG,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC;YAC/F,KAAK,CAAC,IAAI,CACN,YAAY,CAAC,QAAQ,CAAC,kBAAkB,UAAU,gBAAgB,UAAU,WAAW,SAAS,6CAA6C,UAAU,KAAK,IAAI,SAAS,CAC5K,CAAC;QACN,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,kCAAkC;IAClC,IAAI,cAAc,EAAE,CAAC;QACjB,MAAM,eAAe,GAAG,UAAU,CAAC,MAAM,CAAC;QAC1C,MAAM,IAAI,GAAG,SAAS,GAAG,cAAc,GAAG,eAAe,GAAG,WAAW,CAAC;QAExE,0DAA0D;QAC1D,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;YAC7C,IAAI,CAAC,GAAG,CAAC,OAAO;gBAAE,OAAO,EAAE,CAAC;YAE5B,kFAAkF;YAClF,IAAI,GAAG,GAAG,CAAC,CAAC;YACZ,IAAI,SAAS,GAAG,KAAK,CAAC;YACtB,KAAK,MAAM,OAAO,IAAI,aAAa,EAAE,CAAC;gBAClC,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;gBACpD,MAAM,QAAQ,GAAG,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;gBACxF,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAChD,GAAG,IAAI,QAAQ,CAAC;oBAChB,SAAS,GAAG,IAAI,CAAC;gBACrB,CAAC;YACL,CAAC;YAED,oDAAoD;YACpD,OAAO,SAAS,CAAC,CAAC,CAAC,iBAAiB,CAAC,GAAG,EAAE,GAAG,CAAC,MAAa,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACtE,CAAC,CAAC,CAAC;QAEH,4CAA4C;QAC5C,KAAK,CAAC,IAAI,CACN,aAAa,SAAS,SAAS,IAAI,SAAS,SAAS,GAAG,YAAY,SAAS,IAAI,aAAa,iBAAiB,mBAAmB,mBAAmB,MAAM,CAC9J,CAAC;QAEF,sDAAsD;QACtD,MAAM,QAAQ,GAAG,aAAa,GAAG,iBAAiB,GAAG,GAAG,CAAC;QACzD,MAAM,MAAM,GAAG,gBAAgB,GAAG,QAAQ,CAAC;QAC3C,MAAM,MAAM,GAAG,IAAI,GAAG,WAAW,GAAG,CAAC,GAAG,aAAa,CAAC;QACtD,KAAK,CAAC,IAAI,CACN,YAAY,MAAM,QAAQ,MAAM,kBAAkB,UAAU,gBAAgB,UAAU,WAAW,SAAS,uEAAuE,YAAY,SAAS,CACzM,CAAC;QAEF,0CAA0C;QAC1C,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,GAAG,eAAe,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE;YACzE,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;YAClD,IAAI,CAAC,WAAW;gBAAE,OAAO;YAEzB,MAAM,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC,IAAI,GAAG,eAAe,GAAG,CAAC,CAAC,CAAC;YAChE,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,GAAG,eAAe,GAAG,CAAC,CAAC,CAAC;YACzD,MAAM,CAAC,GACH,GAAG,CAAC,KAAK,KAAK,QAAQ;gBAClB,CAAC,CAAC,QAAQ,GAAG,QAAQ,GAAG,CAAC;gBACzB,CAAC,CAAC,GAAG,CAAC,KAAK,KAAK,OAAO;oBACrB,CAAC,CAAC,QAAQ,GAAG,QAAQ,GAAG,QAAQ;oBAChC,CAAC,CAAC,QAAQ,GAAG,QAAQ,CAAC;YAChC,MAAM,CAAC,GAAG,IAAI,GAAG,WAAW,GAAG,CAAC,GAAG,aAAa,CAAC;YACjD,MAAM,UAAU,GAAG,GAAG,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC;YAC/F,KAAK,CAAC,IAAI,CACN,YAAY,CAAC,QAAQ,CAAC,kBAAkB,UAAU,gBAAgB,UAAU,WAAW,SAAS,gEAAgE,UAAU,KAAK,WAAW,SAAS,CACtM,CAAC;QACN,CAAC,CAAC,CAAC;IACP,CAAC;IAED,MAAM,GAAG,GAAG,CAAC,iBAAiB,EAAE,GAAG,KAAK,EAAE,GAAG,KAAK,EAAE,GAAG,KAAK,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC/E,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC;AAC7B,CAAC,CAAC","sourcesContent":["import { LegendElement, PageSpec, StyleMap } from './types';\nimport {\n DEFAULT_LEGEND_SWATCH_WIDTH_MM,\n DEFAULT_LEGEND_CELL_PADDING_MM,\n DEFAULT_LEGEND_BORDER_WIDTH_MM,\n DEFAULT_LEGEND_GRID_WIDTH_MM,\n DEFAULT_LEGEND_HEADER_WIDTH_MM,\n DEFAULT_LEGEND_OFFSET_MM,\n MAX_LEGEND_ROWS\n} from './legendConstants';\nimport {\n computeLegendColumnWidths,\n computeLegendTextYOffset,\n parseLegendColor,\n formatLegendValue\n} from './legendUtils';\nimport { resolvePath } from './renderUtils';\nimport { matchesV2Filter } from './filters';\nimport { pointInPolygon } from './clipUtils';\n\n/**\n * Convert HSL to RGB for PDF compatibility.\n * H: 0-360, S: 0-100, L: 0-100\n * Returns [R, G, B] where each component is 0-255\n */\nfunction hslToRgb(h: number, s: number, l: number): [number, number, number] {\n h = h / 360;\n s = s / 100;\n l = l / 100;\n\n const q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n const p = 2 * l - q;\n\n const hueToRgb = (t: number): number => {\n if (t < 0) t += 1;\n if (t > 1) t -= 1;\n if (t < 1 / 6) return p + (q - p) * 6 * t;\n if (t < 1 / 2) return q;\n if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;\n return p;\n };\n\n const r = Math.round(hueToRgb(h + 1 / 3) * 255);\n const g = Math.round(hueToRgb(h) * 255);\n const b = Math.round(hueToRgb(h - 1 / 3) * 255);\n\n return [r, g, b];\n}\n\n/**\n * Generate distinct colors for legend rows.\n * Uses a predefined palette or auto-generates RGB colors (for PDF compatibility).\n */\nfunction generateLegendColors(count: number, palette?: 'auto' | string[]): string[] {\n if (Array.isArray(palette)) {\n // Use provided palette, cycling if needed\n const colors: string[] = [];\n for (let i = 0; i < count; i++) {\n colors.push(palette[i % palette.length]);\n }\n return colors;\n }\n\n // Auto-generate colors using HSL then convert to RGB for PDF compatibility\n const colors: string[] = [];\n for (let i = 0; i < count; i++) {\n const hue = (i * 360) / count;\n const saturation = 65 + (i % 3) * 10;\n const lightness = 50 + (i % 2) * 10;\n\n // Convert to RGB for jsPDF compatibility\n const [r, g, b] = hslToRgb(hue, saturation, lightness);\n colors.push(`rgb(${r},${g},${b})`);\n }\n return colors;\n}\n\nimport { isRecord, getProp } from './typeGuards';\n\nexport const applyLegendFilter = (\n legendData: unknown[],\n legend: LegendElement,\n viewports: unknown[],\n viewportClipPolygonsLocal: Record<string, Array<Array<{ x: number; y: number }>>>,\n viewportRenderInfo: Record<string, { transform?: unknown }>\n): unknown[] => {\n // Filter by class + where\n let rows = Array.isArray(legendData)\n ? legendData.filter((row) => matchesV2Filter(row, legend.class, legend.where))\n : [];\n if (!rows.length) return rows;\n\n if (legend.clipToViewport) {\n const targetViewportId = legend.viewport;\n const polys = targetViewportId ? viewportClipPolygonsLocal[targetViewportId] : null;\n const vpInfo = targetViewportId ? viewportRenderInfo[targetViewportId] : null;\n const t = isRecord(vpInfo) ? getProp(vpInfo, 'transform') : null;\n if (polys && polys.length && isRecord(t)) {\n const viewMinX = getProp(t, 'viewMinX');\n const viewMaxZ = getProp(t, 'viewMaxZ');\n if (typeof viewMinX === 'number' && typeof viewMaxZ === 'number') {\n rows = rows.filter((row) => {\n const rowX = getProp(row, 'x');\n const rowZ = getProp(row, 'z');\n if (!Number.isFinite(rowX) || !Number.isFinite(rowZ)) return false;\n const viewX = Number(rowX) - viewMinX;\n const viewY = viewMaxZ - Number(rowZ);\n return polys.some((poly) => pointInPolygon(poly, viewX, viewY));\n });\n }\n }\n }\n\n return rows;\n};\n\nexport interface LegendResult {\n svg: string;\n colorMap?: Map<string, string>; // Maps property value to color\n}\n\nexport const buildLegendGroup = (\n legend: LegendElement,\n styles: StyleMap | undefined,\n page: PageSpec,\n marginMm: number | undefined,\n legendData: unknown[],\n fillOpacity?: number\n): LegendResult | null => {\n if (!legend || !legendData || !legendData.length) return null;\n\n // Debug: Log raw input data\n // console.log(`[LEGEND INPUT] Received ${legendData.length} items for legend \"${legend.id}\"`);\n // if (legend.groupBy) {\n // // Count duplicates by groupBy property\n // const counts = new Map<string, number>();\n // for (const item of legendData) {\n // const key = String(resolvePath(item, legend.groupBy) ?? '');\n // counts.set(key, (counts.get(key) || 0) + 1);\n // }\n // console.log('[LEGEND INPUT] Items per group (before grouping):', Array.from(counts.entries()).map(([k, v]) => `${k}: ${v}`).join(', '));\n // }\n\n const pageMargin = typeof marginMm === 'number' ? marginMm : 0;\n const fontStyle = (legend.textStyle && styles?.[legend.textStyle]) || styles?.['body'];\n const fontSizeMm = typeof fontStyle?.fontSizeMm === 'number' ? fontStyle.fontSizeMm : 5;\n const fontFamily = fontStyle?.fontFamily ?? 'Arial, sans-serif';\n const fontColor = isRecord(fontStyle) ? (getProp(fontStyle, 'color') ?? '#000') : '#000';\n\n // Show color column if enabled (but swatches will be empty if no fills configured)\n const showColorColumn = legend.showColorColumn !== false;\n const colorColumnWidthMm = showColorColumn ? (legend.colorColumnWidthMm ?? DEFAULT_LEGEND_SWATCH_WIDTH_MM) : 0;\n const hasFills = fillOpacity !== undefined;\n // console.log(`[LEGEND RENDER] fillOpacity=${fillOpacity}, hasFills=${hasFills}, showColorColumn=${showColorColumn}`);\n const cellPaddingMm = legend.cellPaddingMm ?? DEFAULT_LEGEND_CELL_PADDING_MM;\n const borderStrokeWidthMm = legend.borderStrokeWidthMm ?? DEFAULT_LEGEND_BORDER_WIDTH_MM;\n const borderStrokeColor = legend.borderStrokeColor ?? '#000000';\n const gridStrokeWidthMm = legend.gridStrokeWidthMm ?? DEFAULT_LEGEND_GRID_WIDTH_MM;\n const gridStrokeColor = legend.gridStrokeColor ?? '#000000';\n const headerStrokeWidthMm = legend.headerStrokeWidthMm ?? DEFAULT_LEGEND_HEADER_WIDTH_MM;\n const headerStrokeColor = legend.headerStrokeColor ?? '#000000';\n const anchor = legend.anchor ?? 'top-right';\n const legendMarginMm = legend.marginMm ?? DEFAULT_LEGEND_OFFSET_MM;\n\n // Group rows if groupBy is specified\n let processedData = legendData;\n if (legend.groupBy && typeof legend.groupBy === 'string') {\n const groups = new Map<string, unknown[]>();\n\n // Group rows by the groupBy property value\n for (const row of legendData) {\n const groupKey = String(resolvePath(row, legend.groupBy) ?? '');\n if (!groups.has(groupKey)) {\n groups.set(groupKey, []);\n }\n groups.get(groupKey)!.push(row);\n }\n\n // console.log(`[LEGEND GROUPING] Total input rows: ${legendData.length}, Groups created: ${groups.size}`);\n // for (const [key, rows] of groups.entries()) {\n // if (rows.length > 1) {\n // console.log(`[LEGEND GROUPING] Group \"${key}\": ${rows.length} rows`);\n // }\n // }\n\n // Aggregate each group\n processedData = Array.from(groups.values()).map((groupRows) => {\n if (groupRows.length === 0) return groupRows[0];\n if (groupRows.length === 1) return groupRows[0];\n\n // Create aggregated row (ensure first row is object-like before spreading)\n const firstRow = groupRows[0];\n const aggregated: any = typeof firstRow === 'object' && firstRow !== null ? { ...(firstRow as any) } : {};\n\n // For each column, aggregate values\n for (const col of legend.columns) {\n const values: any[] = [];\n for (const row of groupRows) {\n const val = resolvePath(row, col.property);\n if (val !== undefined && val !== null) {\n values.push(val);\n }\n }\n\n if (values.length === 0) continue;\n\n // Check if all values are numeric - if so, sum them\n const allNumeric = values.every((v) => {\n const num = typeof v === 'number' ? v : parseFloat(String(v));\n return !isNaN(num) && Number.isFinite(num);\n });\n\n if (allNumeric) {\n // Sum numerical values\n const sum = values.reduce((acc, v) => {\n const num = typeof v === 'number' ? v : parseFloat(String(v));\n return acc + num;\n }, 0);\n\n // Debug logging for aggregation\n // if (groupRows.length > 1 && legend.groupBy) {\n // const groupKey = resolvePath(groupRows[0], legend.groupBy);\n // console.log(`[LEGEND AGGREGATION] Group \"${groupKey}\", Column \"${col.property}\":`, {\n // itemCount: values.length,\n // values: values,\n // sum: sum\n // });\n // }\n\n // Set the aggregated value in the nested property structure\n const pathParts = col.property.split('.');\n let target = aggregated;\n for (let i = 0; i < pathParts.length - 1; i++) {\n if (!target[pathParts[i]]) {\n target[pathParts[i]] = {};\n }\n target = target[pathParts[i]];\n }\n target[pathParts[pathParts.length - 1]] = sum;\n }\n // For non-numeric, keep the first value (already in aggregated from spread)\n }\n\n return aggregated;\n });\n }\n\n // Generate colors if assignColors is enabled\n let generatedColors: string[] | null = null;\n let colorMap: Map<string, string> | undefined;\n\n if (legend.assignColors?.enabled) {\n const palette = legend.assignColors.palette ?? 'auto';\n generatedColors = generateLegendColors(processedData.length, palette);\n // console.log(`[LEGEND COLORS] assignColors enabled, generated ${generatedColors.length} colors`);\n\n // Build color map based on groupBy property\n if (legend.groupBy) {\n colorMap = new Map();\n for (let i = 0; i < processedData.length; i++) {\n const row = processedData[i];\n const groupValue = String(resolvePath(row, legend.groupBy) ?? '');\n if (!colorMap.has(groupValue)) {\n colorMap.set(groupValue, generatedColors[i]);\n // console.log(`[LEGEND COLORS] Mapped \"${groupValue}\" -> ${generatedColors[i]}`);\n }\n }\n // console.log(`[LEGEND COLORS] Generated ${colorMap.size} colors for groupBy=\"${legend.groupBy}\"`);\n } else {\n console.warn(`[LEGEND COLORS] assignColors enabled but no groupBy property set`);\n }\n }\n\n const rowsMapped = processedData.map((row: unknown, index: number) => {\n const values = legend.columns.map((col) => {\n const raw = resolvePath(row, col.property);\n return formatLegendValue(raw, col.format as any);\n });\n\n // Use generated color if assignColors is enabled, otherwise sample from item.color\n let swatchColor: string;\n if (generatedColors) {\n swatchColor = generatedColors[index];\n } else {\n const colorValue = getProp(row, 'color');\n const rgba = parseLegendColor(colorValue, values[0] ?? JSON.stringify(row));\n swatchColor = `rgb(${rgba[0]},${rgba[1]},${rgba[2]})`;\n }\n\n return { values, color: swatchColor };\n });\n\n const columnLabels = legend.columns.map((c) => ({\n label: c.label,\n minWidthMm: c.minWidthMm,\n maxWidthMm: c.maxWidthMm\n }));\n const { colWidthsMm, columnCount } = computeLegendColumnWidths(\n columnLabels,\n rowsMapped,\n fontSizeMm,\n cellPaddingMm,\n colorColumnWidthMm,\n fontFamily\n );\n\n const rowHeightMm = fontSizeMm + cellPaddingMm * 2;\n const headerHeightMm = rowHeightMm;\n const tableWidthMm = colWidthsMm.reduce((sum, w) => sum + w, 0);\n\n // Check if summary is enabled\n const summaryEnabled = legend.summary?.enabled === true;\n const summaryLabel = legend.summary?.label ?? 'Total';\n const summaryRowCount = summaryEnabled ? 1 : 0;\n\n const tableHeightMm = headerHeightMm + rowsMapped.length * rowHeightMm + summaryRowCount * rowHeightMm;\n\n const anchorPos = legend.anchorPositionMm;\n const hasAnchorPos =\n anchorPos &&\n typeof anchorPos.xMm === 'number' &&\n Number.isFinite(anchorPos.xMm) &&\n typeof anchorPos.yMm === 'number' &&\n Number.isFinite(anchorPos.yMm);\n\n let originXmm = pageMargin + legendMarginMm;\n let originYmm = pageMargin + legendMarginMm;\n\n if (hasAnchorPos) {\n const { xMm, yMm } = anchorPos as { xMm: number; yMm: number };\n switch (anchor) {\n case 'top-left':\n originXmm = xMm;\n originYmm = yMm;\n break;\n case 'top-right':\n originXmm = xMm - tableWidthMm;\n originYmm = yMm;\n break;\n case 'bottom-left':\n originXmm = xMm;\n originYmm = yMm - tableHeightMm;\n break;\n case 'bottom-right':\n default:\n originXmm = xMm - tableWidthMm;\n originYmm = yMm - tableHeightMm;\n break;\n }\n } else {\n if (anchor === 'top-right' || anchor === 'bottom-right') {\n originXmm = page.widthMm - pageMargin - legendMarginMm - tableWidthMm;\n }\n if (anchor === 'bottom-right' || anchor === 'bottom-left') {\n originYmm = page.heightMm - pageMargin - legendMarginMm - tableHeightMm;\n }\n }\n\n const colXmm: number[] = [];\n let acc = 0;\n colWidthsMm.forEach((w) => {\n colXmm.push(acc);\n acc += w;\n });\n\n const rects: string[] = [];\n const texts: string[] = [];\n const lines: string[] = [];\n\n const dataColStartIdx = showColorColumn ? 1 : 0;\n const contentOriginXmm = originXmm + colWidthsMm[0];\n const headerBottomYmm = originYmm + headerHeightMm;\n\n lines.push(\n `<line x1=\"${contentOriginXmm}\" y1=\"${originYmm}\" x2=\"${originXmm + tableWidthMm}\" y2=\"${originYmm}\" stroke=\"${borderStrokeColor}\" stroke-width=\"${borderStrokeWidthMm}\" />`\n );\n lines.push(\n `<line x1=\"${contentOriginXmm}\" y1=\"${originYmm}\" x2=\"${contentOriginXmm}\" y2=\"${headerBottomYmm}\" stroke=\"${borderStrokeColor}\" stroke-width=\"${borderStrokeWidthMm}\" />`\n );\n // Bottom border: if summary enabled, only under numbers (not under label)\n const bottomBorderStartX = summaryEnabled ? contentOriginXmm : originXmm;\n lines.push(\n `<line x1=\"${bottomBorderStartX}\" y1=\"${originYmm + tableHeightMm}\" x2=\"${originXmm + tableWidthMm}\" y2=\"${originYmm + tableHeightMm}\" stroke=\"${borderStrokeColor}\" stroke-width=\"${borderStrokeWidthMm}\" />`\n );\n lines.push(\n `<line x1=\"${originXmm + tableWidthMm}\" y1=\"${originYmm}\" x2=\"${originXmm + tableWidthMm}\" y2=\"${originYmm + tableHeightMm}\" stroke=\"${borderStrokeColor}\" stroke-width=\"${borderStrokeWidthMm}\" />`\n );\n // Left edge - stops before summary row if summary enabled\n const leftEdgeEndYmm = summaryEnabled\n ? originYmm + headerHeightMm + rowsMapped.length * rowHeightMm\n : originYmm + tableHeightMm;\n lines.push(\n `<line x1=\"${originXmm}\" y1=\"${headerBottomYmm}\" x2=\"${originXmm}\" y2=\"${leftEdgeEndYmm}\" stroke=\"${borderStrokeColor}\" stroke-width=\"${borderStrokeWidthMm}\" />`\n );\n\n // Color column divider - extends all the way down\n lines.push(\n `<line x1=\"${contentOriginXmm}\" y1=\"${headerBottomYmm}\" x2=\"${contentOriginXmm}\" y2=\"${originYmm + tableHeightMm}\" stroke=\"${borderStrokeColor}\" stroke-width=\"${borderStrokeWidthMm}\" />`\n );\n\n lines.push(\n `<line x1=\"${originXmm}\" y1=\"${originYmm + headerHeightMm}\" x2=\"${originXmm + tableWidthMm}\" y2=\"${originYmm + headerHeightMm}\" stroke=\"${headerStrokeColor}\" stroke-width=\"${headerStrokeWidthMm}\" />`\n );\n\n for (let i = 2; i < columnCount; i++) {\n const x = originXmm + colXmm[i];\n lines.push(\n `<line x1=\"${x}\" y1=\"${originYmm}\" x2=\"${x}\" y2=\"${originYmm + tableHeightMm}\" stroke=\"${gridStrokeColor}\" stroke-width=\"${borderStrokeWidthMm}\" />`\n );\n }\n\n for (let r = 0; r <= rowsMapped.length; r++) {\n // Skip last grid line if summary enabled (we draw a heavier separator line instead)\n if (r === rowsMapped.length && summaryEnabled) continue;\n\n const y = originYmm + headerHeightMm + r * rowHeightMm;\n lines.push(\n `<line x1=\"${originXmm}\" y1=\"${y}\" x2=\"${originXmm + tableWidthMm}\" y2=\"${y}\" stroke=\"${gridStrokeColor}\" stroke-width=\"${borderStrokeWidthMm}\" />`\n );\n }\n\n const textYOffsetMm = computeLegendTextYOffset(fontSizeMm);\n legend.columns.slice(0, columnCount - dataColStartIdx).forEach((col, idx) => {\n const colStart = originXmm + colXmm[idx + dataColStartIdx];\n const colWidth = colWidthsMm[idx + dataColStartIdx];\n const innerPad = cellPaddingMm + gridStrokeWidthMm * 0.5;\n const x =\n col.align === 'center'\n ? colStart + colWidth / 2\n : col.align === 'right'\n ? colStart + colWidth - innerPad\n : colStart + innerPad;\n const y = originYmm + headerHeightMm / 2 + textYOffsetMm;\n const anchorText = col.align === 'center' ? 'middle' : col.align === 'right' ? 'end' : 'start';\n texts.push(\n `<text x=\"${x}\" y=\"${y}\" font-family=\"${fontFamily}\" font-size=\"${fontSizeMm}\" fill=\"${fontColor}\" dominant-baseline=\"middle\" text-anchor=\"${anchorText}\">${col.label}</text>`\n );\n });\n\n const swatchOpacity = typeof fillOpacity === 'number' ? Math.min(Math.max(fillOpacity, 0), 1) : 1;\n\n rowsMapped.slice(0, MAX_LEGEND_ROWS).forEach((row, rIndex) => {\n const yTop = originYmm + headerHeightMm + rIndex * rowHeightMm;\n\n if (showColorColumn) {\n // Only show fill colors if the viewport has fills configured\n if (hasFills) {\n // row.color can be either a CSS color string (from generated colors) or RGB string\n const swatchFill = row.color; // Already a CSS color string\n const opacityAttr = swatchOpacity < 1 ? ` fill-opacity=\"${swatchOpacity.toFixed(3)}\"` : '';\n rects.push(\n `<rect x=\"${originXmm + colXmm[0]}\" y=\"${yTop}\" width=\"${colWidthsMm[0]}\" height=\"${rowHeightMm}\" fill=\"${swatchFill}\"${opacityAttr} stroke=\"none\" />`\n );\n } else {\n // Empty swatch when no fills configured - just the border cell\n rects.push(\n `<rect x=\"${originXmm + colXmm[0]}\" y=\"${yTop}\" width=\"${colWidthsMm[0]}\" height=\"${rowHeightMm}\" fill=\"none\" stroke=\"none\" />`\n );\n }\n }\n\n legend.columns.slice(0, columnCount - dataColStartIdx).forEach((col, cIdx) => {\n const text = row.values[cIdx] ?? '';\n if (!text) return;\n const colStart = originXmm + colXmm[cIdx + dataColStartIdx];\n const colWidth = colWidthsMm[cIdx + dataColStartIdx];\n const innerPad = cellPaddingMm + gridStrokeWidthMm * 0.5;\n const x =\n col.align === 'center'\n ? colStart + colWidth / 2\n : col.align === 'right'\n ? colStart + colWidth - innerPad\n : colStart + innerPad;\n const y = yTop + rowHeightMm / 2 + textYOffsetMm;\n const anchorText = col.align === 'center' ? 'middle' : col.align === 'right' ? 'end' : 'start';\n texts.push(\n `<text x=\"${x}\" y=\"${y}\" font-family=\"${fontFamily}\" font-size=\"${fontSizeMm}\" fill=\"${fontColor}\" dominant-baseline=\"middle\" text-anchor=\"${anchorText}\">${text}</text>`\n );\n });\n });\n\n // Render summary row (if enabled)\n if (summaryEnabled) {\n const summaryRowIndex = rowsMapped.length;\n const yTop = originYmm + headerHeightMm + summaryRowIndex * rowHeightMm;\n\n // Calculate summary values for columns with summary: true\n const summaryValues = legend.columns.map((col) => {\n if (!col.summary) return '';\n\n // Sum all numerical values in this column (use processedData to reflect grouping)\n let sum = 0;\n let hasValues = false;\n for (const dataRow of processedData) {\n const rawValue = resolvePath(dataRow, col.property);\n const numValue = typeof rawValue === 'number' ? rawValue : parseFloat(String(rawValue));\n if (!isNaN(numValue) && Number.isFinite(numValue)) {\n sum += numValue;\n hasValues = true;\n }\n }\n\n // Format the sum using the column's format settings\n return hasValues ? formatLegendValue(sum, col.format as any) : '';\n });\n\n // Add heavier border line above summary row\n lines.push(\n `<line x1=\"${originXmm}\" y1=\"${yTop}\" x2=\"${originXmm + tableWidthMm}\" y2=\"${yTop}\" stroke=\"${headerStrokeColor}\" stroke-width=\"${headerStrokeWidthMm}\" />`\n );\n\n // Render summary label aligned with first data column\n const innerPad = cellPaddingMm + gridStrokeWidthMm * 0.5;\n const labelX = contentOriginXmm + innerPad;\n const labelY = yTop + rowHeightMm / 2 + textYOffsetMm;\n texts.push(\n `<text x=\"${labelX}\" y=\"${labelY}\" font-family=\"${fontFamily}\" font-size=\"${fontSizeMm}\" fill=\"${fontColor}\" font-weight=\"bold\" dominant-baseline=\"middle\" text-anchor=\"start\">${summaryLabel}</text>`\n );\n\n // Render summary values for other columns\n legend.columns.slice(1, columnCount - dataColStartIdx).forEach((col, cIdx) => {\n const summaryText = summaryValues[cIdx + 1] ?? '';\n if (!summaryText) return;\n\n const colStart = originXmm + colXmm[cIdx + dataColStartIdx + 1];\n const colWidth = colWidthsMm[cIdx + dataColStartIdx + 1];\n const x =\n col.align === 'center'\n ? colStart + colWidth / 2\n : col.align === 'right'\n ? colStart + colWidth - innerPad\n : colStart + innerPad;\n const y = yTop + rowHeightMm / 2 + textYOffsetMm;\n const anchorText = col.align === 'center' ? 'middle' : col.align === 'right' ? 'end' : 'start';\n texts.push(\n `<text x=\"${x}\" y=\"${y}\" font-family=\"${fontFamily}\" font-size=\"${fontSizeMm}\" fill=\"${fontColor}\" font-weight=\"bold\" dominant-baseline=\"middle\" text-anchor=\"${anchorText}\">${summaryText}</text>`\n );\n });\n }\n\n const svg = [`<g id=\"legend\">`, ...rects, ...lines, ...texts, `</g>`].join('');\n return { svg, colorMap };\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"legendRows.js","sourceRoot":"/","sources":["layout/legendRows.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAoBjD;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,KAAgB,EAAE,OAA0B,EAAe,EAAE;IACzF,MAAM,YAAY,GAAG,OAAO,EAAE,YAAY,IAAI,WAAW,CAAC;IAC1D,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAa,EAAE;QAC/D,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,EAAE,YAAY,CAAC,IAAI,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAClG,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACzC,MAAM,KAAK,GAAG,gBAAgB,CAAC,SAAS,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC5D,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,UAAU,CAAC;QACnD,MAAM,SAAS,GAAG,CAAC,GAAG,EAAE;YACpB,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YAC/C,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,IAAI;gBAAE,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC;YACzE,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;YAC/C,IAAI,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACrB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACxC,MAAM,YAAY,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;oBACrE,MAAM,SAAS,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;oBACjF,IAAI,SAAS,KAAK,SAAS,IAAI,SAAS,KAAK,IAAI;wBAAE,OAAO,MAAM,CAAC,SAAS,CAAC,CAAC;gBAChF,CAAC;YACL,CAAC;YACD,OAAO,IAAI,CAAC;QAChB,CAAC,CAAC,EAAE,CAAC;QACL,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACtC,MAAM,IAAI,GAAG,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;QACzF,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAE,IAAgC,CAAC,CAAC,CAAC,EAAE,CAAC;QACxE,OAAO;YACH,GAAG,OAAO;YACV,SAAS;YACT,IAAI;YACJ,KAAK;SACR,CAAC;IACN,CAAC,CAAC,CAAC;AACP,CAAC,CAAC","sourcesContent":["import { getPathValue } from './renderUtils';\
|
|
1
|
+
{"version":3,"file":"legendRows.js","sourceRoot":"/","sources":["layout/legendRows.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAoBjD;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,KAAgB,EAAE,OAA0B,EAAe,EAAE;IACzF,MAAM,YAAY,GAAG,OAAO,EAAE,YAAY,IAAI,WAAW,CAAC;IAC1D,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAa,EAAE;QAC/D,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,EAAE,YAAY,CAAC,IAAI,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAClG,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACzC,MAAM,KAAK,GAAG,gBAAgB,CAAC,SAAS,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC5D,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,UAAU,CAAC;QACnD,MAAM,SAAS,GAAG,CAAC,GAAG,EAAE;YACpB,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YAC/C,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,IAAI;gBAAE,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC;YACzE,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;YAC/C,IAAI,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACrB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACxC,MAAM,YAAY,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;oBACrE,MAAM,SAAS,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;oBACjF,IAAI,SAAS,KAAK,SAAS,IAAI,SAAS,KAAK,IAAI;wBAAE,OAAO,MAAM,CAAC,SAAS,CAAC,CAAC;gBAChF,CAAC;YACL,CAAC;YACD,OAAO,IAAI,CAAC;QAChB,CAAC,CAAC,EAAE,CAAC;QACL,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACtC,MAAM,IAAI,GAAG,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;QACzF,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAE,IAAgC,CAAC,CAAC,CAAC,EAAE,CAAC;QACxE,OAAO;YACH,GAAG,OAAO;YACV,SAAS;YACT,IAAI;YACJ,KAAK;SACR,CAAC;IACN,CAAC,CAAC,CAAC;AACP,CAAC,CAAC","sourcesContent":["import { getPathValue } from './renderUtils';\nimport { parseLegendColor } from './legendUtils';\n\nimport { isRecord, getProp } from './typeGuards';\n\nexport interface LegendRowOptions {\n colorKeyPath?: string;\n classPath?: string;\n}\n\nexport interface LegendRow {\n productId?: string;\n productName?: string;\n area?: number | string | null;\n className?: string | null;\n x?: number;\n z?: number;\n properties?: unknown;\n propertySets?: unknown;\n color?: [number, number, number, number];\n [key: string]: unknown;\n}\n\n/**\n * Build standard legend rows from product items.\n * Expected fields on input item:\n * - productId / productName / area\n * - x / z (model coords)\n * - properties / propertySets\n * - gid (fallback id)\n */\nexport const buildLegendRows = (items: unknown[], options?: LegendRowOptions): LegendRow[] => {\n const colorKeyPath = options?.colorKeyPath ?? 'productId';\n return (Array.isArray(items) ? items : []).map((item): LegendRow => {\n const colorKey = getPathValue(item, colorKeyPath) ?? getProp(item, 'gid') ?? JSON.stringify(item);\n const itemColor = getProp(item, 'color');\n const color = parseLegendColor(itemColor, String(colorKey));\n const classPath = options?.classPath ?? 'ifcClass';\n const className = (() => {\n const explicit = getPathValue(item, classPath);\n if (explicit !== undefined && explicit !== null) return String(explicit);\n const propSets = getProp(item, 'propertySets');\n if (isRecord(propSets)) {\n for (const set of Object.values(propSets)) {\n const ifcClassProp = isRecord(set) ? getProp(set, 'ifcClass') : null;\n const candidate = isRecord(ifcClassProp) ? getProp(ifcClassProp, 'value') : null;\n if (candidate !== undefined && candidate !== null) return String(candidate);\n }\n }\n return null;\n })();\n const areaVal = getProp(item, 'area');\n const area = typeof areaVal === 'number' || typeof areaVal === 'string' ? areaVal : null;\n const baseObj = isRecord(item) ? (item as Record<string, unknown>) : {};\n return {\n ...baseObj,\n className,\n area,\n color\n };\n });\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"legendUtils.js","sourceRoot":"/","sources":["layout/legendUtils.ts"],"names":[],"mappings":"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","sourcesContent":["import {\r\n LEGEND_TEXT_WIDTH_FACTOR,\r\n LEGEND_MIN_CONTENT_WIDTH_EM,\r\n LEGEND_TEXT_Y_OFFSET_FACTOR,\r\n PX_PER_MM\r\n} from './legendConstants';\r\n// v2 format: { digits?: number; prefix?: string; suffix?: string } or undefined\r\ntype LegendFormat = { digits?: number; prefix?: string; suffix?: string } | string | undefined;\r\nimport {\r\n RGB_MAX,\r\n RED_SHIFT,\r\n GREEN_SHIFT,\r\n HASH_COLOR_MODULO,\r\n HASH_GREEN_SHIFT,\r\n HASH_BLUE_SHIFT,\r\n RGB_MIN\r\n} from './colorConstants';\r\n\r\nimport { isRecord, getProp } from './typeGuards';\r\n\r\nexport function parseLegendColor(value: unknown, fallbackKey: string): [number, number, number, number] {\r\n if (Array.isArray(value) && (value.length === 3 || value.length === 4)) {\r\n const [r, g, b, a = RGB_MAX] = value.map((v) => Number(v) || 0);\r\n return [clampColor(r), clampColor(g), clampColor(b), clampColor(a)];\r\n }\r\n if (typeof value === 'string') {\r\n const hex = value.trim();\r\n const match = /^#?([a-fA-F0-9]{6})([a-fA-F0-9]{2})?$/.exec(hex);\r\n if (match) {\r\n const intVal = parseInt(match[1], 16);\r\n const aHex = match[2];\r\n return [\r\n (intVal >> RED_SHIFT) & 0xff,\r\n (intVal >> GREEN_SHIFT) & 0xff,\r\n intVal & 0xff,\r\n aHex ? parseInt(aHex, 16) : RGB_MAX\r\n ];\r\n }\r\n }\r\n const hash = Math.abs(hashCode(fallbackKey || ''));\r\n return [\r\n hash % HASH_COLOR_MODULO,\r\n (hash >> HASH_GREEN_SHIFT) % HASH_COLOR_MODULO,\r\n (hash >> HASH_BLUE_SHIFT) % HASH_COLOR_MODULO,\r\n RGB_MAX\r\n ];\r\n}\r\n\r\nexport function formatLegendValue(value: unknown, fmt?: LegendFormat): string {\r\n if (fmt === undefined || fmt === null || fmt === 'string') {\r\n return value === undefined || value === null ? '' : String(value);\r\n }\r\n\r\n if (typeof fmt === 'string') {\r\n const fixedMatch = /^fixed\\((\\d+)(?:,\\s*([^)]*))?\\)$/i.exec(fmt);\r\n if (fixedMatch) {\r\n const digits = parseInt(fixedMatch[1], 10);\r\n const suffix = fixedMatch[2] || '';\r\n const num = Number(value);\r\n if (Number.isFinite(num)) {\r\n return `${num.toFixed(digits)}${suffix ? ` ${suffix.trim()}` : ''}`.trim();\r\n }\r\n }\r\n return String(value ?? '');\r\n }\r\n\r\n if (isRecord(fmt)) {\r\n const digits = getProp(fmt, 'digits');\r\n const prefix = getProp(fmt, 'prefix');\r\n const suffix = getProp(fmt, 'suffix');\r\n const num = Number(value);\r\n if (Number.isFinite(num) && typeof digits === 'number') {\r\n const prefixStr = typeof prefix === 'string' ? prefix : '';\r\n const suffixStr = typeof suffix === 'string' ? suffix : '';\r\n return `${prefixStr}${num.toFixed(digits)}${suffixStr}`;\r\n }\r\n return String(value ?? '');\r\n }\r\n\r\n return String(value ?? '');\r\n}\r\n\r\nexport function computeLegendColumnWidths(\r\n columnLabels: { label: string; minWidthMm?: number; maxWidthMm?: number }[],\r\n rows: { values: string[] }[],\r\n fontSizeMm: number,\r\n cellPaddingMm: number,\r\n swatchWidthMm: number,\r\n fontFamily: string\r\n): { colWidthsMm: number[]; columnCount: number } {\r\n const columnCount = Math.min(6, Math.max(2, columnLabels.length + 1));\r\n const colWidthsMm: number[] = new Array(columnCount).fill(0);\r\n colWidthsMm[0] = swatchWidthMm;\r\n const measureTextWidthMm = createLegendTextMeasurer(fontFamily, fontSizeMm);\r\n\r\n for (let c = 1; c < columnCount; c++) {\r\n const colIdx = c - 1;\r\n const col = columnLabels[colIdx];\r\n const minWidth = col.minWidthMm ?? fontSizeMm * LEGEND_MIN_CONTENT_WIDTH_EM;\r\n const maxWidth = col.maxWidthMm ?? Number.POSITIVE_INFINITY;\r\n let maxWidthMeasured = measureTextWidthMm(col.label ?? '');\r\n rows.forEach((row) => {\r\n const text = row.values[colIdx] ?? '';\r\n maxWidthMeasured = Math.max(maxWidthMeasured, measureTextWidthMm(text));\r\n });\r\n const contentWidth = Math.max(minWidth, Math.min(maxWidth, maxWidthMeasured + cellPaddingMm * 2));\r\n colWidthsMm[c] = contentWidth;\r\n }\r\n\r\n return { colWidthsMm, columnCount };\r\n}\r\n\r\nexport function computeLegendTextYOffset(fontSizeMm: number): number {\r\n return fontSizeMm * LEGEND_TEXT_Y_OFFSET_FACTOR;\r\n}\r\n\r\nexport const createLegendTextMeasurer = (fontFamily: string, fontSizeMm: number): ((text: string) => number) => {\r\n if (typeof document !== 'undefined') {\r\n const canvas = document.createElement('canvas');\r\n canvas.width = 1024;\r\n canvas.height = 64;\r\n const canvasCtx = canvas.getContext('2d');\r\n if (canvasCtx) {\r\n canvasCtx.font = `${fontSizeMm * PX_PER_MM}px ${fontFamily}`;\r\n const measureTextWidthMm = (text: string): number => {\r\n const metrics = canvasCtx.measureText(text);\r\n return metrics.width / PX_PER_MM;\r\n };\r\n return measureTextWidthMm;\r\n }\r\n }\r\n return (text: string): number => text.length * fontSizeMm * LEGEND_TEXT_WIDTH_FACTOR;\r\n};\r\n\r\nconst clampColor = (value: number): number => Math.max(RGB_MIN, Math.min(RGB_MAX, Math.round(value)));\r\n\r\nconst hashCode = (str: string): number => {\r\n let hash = 0;\r\n for (let i = 0; i < str.length; i++) {\r\n hash = (hash << 5) - hash + str.charCodeAt(i);\r\n hash |= 0;\r\n }\r\n return hash;\r\n};\r\n"]}
|
|
1
|
+
{"version":3,"file":"legendUtils.js","sourceRoot":"/","sources":["layout/legendUtils.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n LEGEND_TEXT_WIDTH_FACTOR,\n LEGEND_MIN_CONTENT_WIDTH_EM,\n LEGEND_TEXT_Y_OFFSET_FACTOR,\n PX_PER_MM\n} from './legendConstants';\n// v2 format: { digits?: number; prefix?: string; suffix?: string } or undefined\ntype LegendFormat = { digits?: number; prefix?: string; suffix?: string } | string | undefined;\nimport {\n RGB_MAX,\n RED_SHIFT,\n GREEN_SHIFT,\n HASH_COLOR_MODULO,\n HASH_GREEN_SHIFT,\n HASH_BLUE_SHIFT,\n RGB_MIN\n} from './colorConstants';\n\nimport { isRecord, getProp } from './typeGuards';\n\nexport function parseLegendColor(value: unknown, fallbackKey: string): [number, number, number, number] {\n if (Array.isArray(value) && (value.length === 3 || value.length === 4)) {\n const [r, g, b, a = RGB_MAX] = value.map((v) => Number(v) || 0);\n return [clampColor(r), clampColor(g), clampColor(b), clampColor(a)];\n }\n if (typeof value === 'string') {\n const hex = value.trim();\n const match = /^#?([a-fA-F0-9]{6})([a-fA-F0-9]{2})?$/.exec(hex);\n if (match) {\n const intVal = parseInt(match[1], 16);\n const aHex = match[2];\n return [\n (intVal >> RED_SHIFT) & 0xff,\n (intVal >> GREEN_SHIFT) & 0xff,\n intVal & 0xff,\n aHex ? parseInt(aHex, 16) : RGB_MAX\n ];\n }\n }\n const hash = Math.abs(hashCode(fallbackKey || ''));\n return [\n hash % HASH_COLOR_MODULO,\n (hash >> HASH_GREEN_SHIFT) % HASH_COLOR_MODULO,\n (hash >> HASH_BLUE_SHIFT) % HASH_COLOR_MODULO,\n RGB_MAX\n ];\n}\n\nexport function formatLegendValue(value: unknown, fmt?: LegendFormat): string {\n if (fmt === undefined || fmt === null || fmt === 'string') {\n return value === undefined || value === null ? '' : String(value);\n }\n\n if (typeof fmt === 'string') {\n const fixedMatch = /^fixed\\((\\d+)(?:,\\s*([^)]*))?\\)$/i.exec(fmt);\n if (fixedMatch) {\n const digits = parseInt(fixedMatch[1], 10);\n const suffix = fixedMatch[2] || '';\n const num = Number(value);\n if (Number.isFinite(num)) {\n return `${num.toFixed(digits)}${suffix ? ` ${suffix.trim()}` : ''}`.trim();\n }\n }\n return String(value ?? '');\n }\n\n if (isRecord(fmt)) {\n const digits = getProp(fmt, 'digits');\n const prefix = getProp(fmt, 'prefix');\n const suffix = getProp(fmt, 'suffix');\n const num = Number(value);\n if (Number.isFinite(num) && typeof digits === 'number') {\n const prefixStr = typeof prefix === 'string' ? prefix : '';\n const suffixStr = typeof suffix === 'string' ? suffix : '';\n return `${prefixStr}${num.toFixed(digits)}${suffixStr}`;\n }\n return String(value ?? '');\n }\n\n return String(value ?? '');\n}\n\nexport function computeLegendColumnWidths(\n columnLabels: { label: string; minWidthMm?: number; maxWidthMm?: number }[],\n rows: { values: string[] }[],\n fontSizeMm: number,\n cellPaddingMm: number,\n swatchWidthMm: number,\n fontFamily: string\n): { colWidthsMm: number[]; columnCount: number } {\n const columnCount = Math.min(6, Math.max(2, columnLabels.length + 1));\n const colWidthsMm: number[] = new Array(columnCount).fill(0);\n colWidthsMm[0] = swatchWidthMm;\n const measureTextWidthMm = createLegendTextMeasurer(fontFamily, fontSizeMm);\n\n for (let c = 1; c < columnCount; c++) {\n const colIdx = c - 1;\n const col = columnLabels[colIdx];\n const minWidth = col.minWidthMm ?? fontSizeMm * LEGEND_MIN_CONTENT_WIDTH_EM;\n const maxWidth = col.maxWidthMm ?? Number.POSITIVE_INFINITY;\n let maxWidthMeasured = measureTextWidthMm(col.label ?? '');\n rows.forEach((row) => {\n const text = row.values[colIdx] ?? '';\n maxWidthMeasured = Math.max(maxWidthMeasured, measureTextWidthMm(text));\n });\n const contentWidth = Math.max(minWidth, Math.min(maxWidth, maxWidthMeasured + cellPaddingMm * 2));\n colWidthsMm[c] = contentWidth;\n }\n\n return { colWidthsMm, columnCount };\n}\n\nexport function computeLegendTextYOffset(fontSizeMm: number): number {\n return fontSizeMm * LEGEND_TEXT_Y_OFFSET_FACTOR;\n}\n\nexport const createLegendTextMeasurer = (fontFamily: string, fontSizeMm: number): ((text: string) => number) => {\n if (typeof document !== 'undefined') {\n const canvas = document.createElement('canvas');\n canvas.width = 1024;\n canvas.height = 64;\n const canvasCtx = canvas.getContext('2d');\n if (canvasCtx) {\n canvasCtx.font = `${fontSizeMm * PX_PER_MM}px ${fontFamily}`;\n const measureTextWidthMm = (text: string): number => {\n const metrics = canvasCtx.measureText(text);\n return metrics.width / PX_PER_MM;\n };\n return measureTextWidthMm;\n }\n }\n return (text: string): number => text.length * fontSizeMm * LEGEND_TEXT_WIDTH_FACTOR;\n};\n\nconst clampColor = (value: number): number => Math.max(RGB_MIN, Math.min(RGB_MAX, Math.round(value)));\n\nconst hashCode = (str: string): number => {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n hash = (hash << 5) - hash + str.charCodeAt(i);\n hash |= 0;\n }\n return hash;\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadata.js","sourceRoot":"/","sources":["layout/metadata.ts"],"names":[],"mappings":"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","sourcesContent":["import { getPathValue as getValueByPath } from './renderUtils';\r\nimport type { LayoutTemplate, ResolvedIncludeFilter, WhereCondition } from './types';\r\n\r\nexport interface ModelMetadataEntry {\r\n productId?: string;\r\n ifcClass?: string;\r\n ifcClassId?: string;\r\n properties?: unknown;\r\n [key: string]: unknown;\r\n}\r\n\r\nexport type ModelMetadata = Record<string, ModelMetadataEntry>;\r\n\r\nimport { isRecord, getProp } from './typeGuards';\r\nimport { normalizeClass } from './filters';\r\n\r\n/** Resolve the IFC class name from a BIM product object's `.class` property. */\r\nexport const resolveIfcClassName = (product: unknown): string | null => {\r\n const classObj = getProp(product, 'class');\r\n if (!classObj) return null;\r\n return normalizeClass(getProp(classObj, 'name') ?? getProp(classObj, 'type') ?? getProp(classObj, 'id'));\r\n};\r\n\r\n/** Resolve the predefined IFC class ID (e.g. \"USERDEFINED\") from `.class.id`. */\r\nexport const resolveIfcClassId = (product: unknown): string | null => {\r\n const classObj = getProp(product, 'class');\r\n if (!classObj) return null;\r\n const id = getProp(classObj, 'id');\r\n return typeof id === 'string' ? id : null;\r\n};\r\n\r\nexport const normalizePropertySets = (\r\n product: unknown\r\n): Record<string, Record<string, { value: unknown; unit?: string; type?: string }>> => {\r\n const properties = getProp(product, 'properties');\r\n // BIM products may have properties at various paths:\r\n // - product.properties.data (Twinfinity standard)\r\n // - product.properties.propertySets (BIM API)\r\n // - product.propertySets (direct)\r\n // - product.properties (fallback)\r\n // New T8 API: product.propertySets → Record<string, T8PropertySet>\r\n // where T8PropertySet.properties → Record<string, T8Property { value, type, unit }>\r\n // Legacy: product.properties.data / product.properties.sets → Record<string, Record<string, unknown>>\r\n const raw =\r\n getProp(product, 'propertySets') ??\r\n getProp(properties, 'data') ??\r\n getProp(properties, 'sets') ??\r\n properties ??\r\n {};\r\n const propertySets: Record<string, Record<string, { value: unknown; unit?: string; type?: string }>> = {};\r\n if (!isRecord(raw)) return propertySets;\r\n Object.entries(raw).forEach(([setName, setValue]) => {\r\n if (!isRecord(setValue)) return;\r\n // T8PropertySet has a .properties sub-record with T8Property entries\r\n const innerProps = getProp(setValue, 'properties');\r\n const source = isRecord(innerProps) ? innerProps : setValue;\r\n const props: Record<string, { value: unknown; unit?: string; type?: string }> = {};\r\n Object.entries(source).forEach(([propName, propVal]) => {\r\n if (isRecord(propVal) && 'value' in propVal) {\r\n props[propName] = propVal as { value: unknown; unit?: string; type?: string };\r\n } else {\r\n props[propName] = { value: propVal };\r\n }\r\n });\r\n propertySets[setName] = props;\r\n });\r\n return propertySets;\r\n};\r\n\r\nexport const buildMetadataMap = (entries: unknown[]): ModelMetadata => {\r\n const out: ModelMetadata = {};\r\n if (!Array.isArray(entries)) return out;\r\n entries.forEach((entry) => {\r\n const product = getProp(entry, 'product') ?? entry;\r\n const gid = getProp(product, 'gid') ?? getProp(product, 'id') ?? null;\r\n if (!gid) return;\r\n const propertySets = normalizePropertySets(product);\r\n const ifcClass = resolveIfcClassName(product) ?? undefined;\r\n const ifcClassId = resolveIfcClassId(product) ?? undefined;\r\n out[String(gid)] = {\r\n productId: String(gid),\r\n ifcClass,\r\n ifcClassId,\r\n properties: propertySets,\r\n propertySets\r\n };\r\n });\r\n return out;\r\n};\r\n\r\nexport const resolveMeta = (meta: unknown, metadataById?: ModelMetadata): unknown => {\r\n const productId = getProp(meta, 'productId') ?? getProp(meta, 'gid') ?? getProp(meta, 'id');\r\n const base = productId && metadataById ? metadataById[String(productId)] : undefined;\r\n if (!base) {\r\n return meta;\r\n }\r\n const baseProps = getProp(base, 'properties');\r\n const metaProps = getProp(meta, 'properties');\r\n const mergedProps =\r\n baseProps || metaProps\r\n ? { ...(isRecord(baseProps) ? baseProps : {}), ...(isRecord(metaProps) ? metaProps : {}) }\r\n : undefined;\r\n return mergedProps\r\n ? { ...base, ...(isRecord(meta) ? meta : {}), productId, properties: mergedProps }\r\n : { ...base, ...(isRecord(meta) ? meta : {}), productId };\r\n};\r\n\r\n/**\r\n * Resolve includeClasses config to an array of filters.\r\n *\r\n * Supports:\r\n * - String arrays: [\"space\", \"walls\"]\r\n * - Filter objects: [{ class: \"space\", where: { \"BIP.spacetype\": \"ROOM\" } }]\r\n * - Preset references: { preset: \"defaultBuilding\" }\r\n * - Mixed arrays: [\"walls\", { class: \"space\", where: {...} }]\r\n *\r\n * @returns Array of filters (strings or class+where objects), or null if no filters\r\n */\r\nexport const resolveIncludeClasses = (\r\n includeClasses: unknown,\r\n currentIncludePresets: Record<string, string[]>\r\n): ResolvedIncludeFilter[] | null => {\r\n if (!includeClasses) return null;\r\n\r\n // Handle array of filters (strings or objects)\r\n if (Array.isArray(includeClasses)) {\r\n const result: ResolvedIncludeFilter[] = [];\r\n for (const item of includeClasses) {\r\n if (typeof item === 'string' && item.length > 0) {\r\n result.push(item);\r\n } else if (isRecord(item)) {\r\n const cls = getProp(item, 'class');\r\n const where = getProp(item, 'where');\r\n // Must have either class or where (or both)\r\n if (cls !== undefined || (where && isRecord(where))) {\r\n result.push({ class: cls as string | string[] | undefined, where: where as WhereCondition });\r\n }\r\n }\r\n }\r\n return result.length > 0 ? result : null;\r\n }\r\n\r\n // Handle preset reference or filter object\r\n if (isRecord(includeClasses)) {\r\n const preset = getProp(includeClasses, 'preset');\r\n const cls = getProp(includeClasses, 'class');\r\n const where = getProp(includeClasses, 'where');\r\n\r\n // Preset reference: { preset: \"name\" }\r\n if (typeof preset === 'string') {\r\n const presetName = preset;\r\n const base = currentIncludePresets[presetName] ?? [];\r\n const addProp = getProp(includeClasses, 'add');\r\n const removeProp = getProp(includeClasses, 'remove');\r\n const add = Array.isArray(addProp) ? addProp : [];\r\n const remove = Array.isArray(removeProp) ? removeProp : [];\r\n const set = new Set<string>();\r\n base.forEach((c: string) => set.add(c));\r\n add.forEach((c: unknown) => typeof c === 'string' && set.add(c));\r\n remove.forEach((c: unknown) => typeof c === 'string' && set.delete(c));\r\n const strings = Array.from(set).filter((c) => typeof c === 'string' && c.length > 0);\r\n return strings.length > 0 ? strings : null;\r\n }\r\n\r\n // Filter object: { class: \"space\", where: {...} }\r\n if (cls !== undefined || (where && isRecord(where))) {\r\n return [{ class: cls as string | string[] | undefined, where: where as WhereCondition }];\r\n }\r\n }\r\n\r\n return null;\r\n};\r\n\r\n/**\r\n * Resolve allowed class names from template/viewport includeClasses config.\r\n *\r\n * Extracts only string filters (class names), ignoring filter objects with where conditions.\r\n * Used for backward compatibility and simple class-based filtering.\r\n *\r\n * @returns Set of normalized class names, or null if no filters\r\n */\r\nexport const resolveAllowedClasses = (layoutTemplate: LayoutTemplate, viewportId = 'main'): Set<string> | null => {\r\n if (!layoutTemplate) return null;\r\n const presets = layoutTemplate.presets?.includeClasses ?? {};\r\n const templateClasses = resolveIncludeClasses(getProp(layoutTemplate, 'includeClasses'), presets);\r\n const elements = layoutTemplate.elements;\r\n const viewportEl = Array.isArray(elements)\r\n ? elements.find((el) => isRecord(el) && getProp(el, 'kind') === 'viewport' && getProp(el, 'id') === viewportId)\r\n : undefined;\r\n const viewportClasses = resolveIncludeClasses(getProp(viewportEl, 'includeClasses'), presets);\r\n const resolved = viewportClasses ?? templateClasses;\r\n if (!resolved || !resolved.length) {\r\n return null;\r\n }\r\n // Extract only string filters (class names)\r\n const classNames = new Set<string>();\r\n for (const filter of resolved) {\r\n if (typeof filter === 'string') {\r\n classNames.add(filter);\r\n } else if (isRecord(filter) && filter.class) {\r\n const classes = Array.isArray(filter.class) ? filter.class : [filter.class];\r\n for (const c of classes) {\r\n if (typeof c === 'string') classNames.add(c);\r\n }\r\n }\r\n }\r\n return classNames.size > 0 ? classNames : null;\r\n};\r\n\r\nexport const getPathValue = (obj: unknown, path: string): unknown => getValueByPath(obj, path);\r\n"]}
|
|
1
|
+
{"version":3,"file":"metadata.js","sourceRoot":"/","sources":["layout/metadata.ts"],"names":[],"mappings":"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","sourcesContent":["import { getPathValue as getValueByPath } from './renderUtils';\nimport type { LayoutTemplate, ResolvedIncludeFilter, WhereCondition } from './types';\n\nexport interface ModelMetadataEntry {\n productId?: string;\n ifcClass?: string;\n ifcClassId?: string;\n properties?: unknown;\n [key: string]: unknown;\n}\n\nexport type ModelMetadata = Record<string, ModelMetadataEntry>;\n\nimport { isRecord, getProp } from './typeGuards';\nimport { normalizeClass } from './filters';\n\n/** Resolve the IFC class name from a BIM product object's `.class` property. */\nexport const resolveIfcClassName = (product: unknown): string | null => {\n const classObj = getProp(product, 'class');\n if (!classObj) return null;\n return normalizeClass(getProp(classObj, 'name') ?? getProp(classObj, 'type') ?? getProp(classObj, 'id'));\n};\n\n/** Resolve the predefined IFC class ID (e.g. \"USERDEFINED\") from `.class.id`. */\nexport const resolveIfcClassId = (product: unknown): string | null => {\n const classObj = getProp(product, 'class');\n if (!classObj) return null;\n const id = getProp(classObj, 'id');\n return typeof id === 'string' ? id : null;\n};\n\nexport const normalizePropertySets = (\n product: unknown\n): Record<string, Record<string, { value: unknown; unit?: string; type?: string }>> => {\n const properties = getProp(product, 'properties');\n // BIM products may have properties at various paths:\n // - product.properties.data (Twinfinity standard)\n // - product.properties.propertySets (BIM API)\n // - product.propertySets (direct)\n // - product.properties (fallback)\n // New T8 API: product.propertySets → Record<string, T8PropertySet>\n // where T8PropertySet.properties → Record<string, T8Property { value, type, unit }>\n // Legacy: product.properties.data / product.properties.sets → Record<string, Record<string, unknown>>\n const raw =\n getProp(product, 'propertySets') ??\n getProp(properties, 'data') ??\n getProp(properties, 'sets') ??\n properties ??\n {};\n const propertySets: Record<string, Record<string, { value: unknown; unit?: string; type?: string }>> = {};\n if (!isRecord(raw)) return propertySets;\n Object.entries(raw).forEach(([setName, setValue]) => {\n if (!isRecord(setValue)) return;\n // T8PropertySet has a .properties sub-record with T8Property entries\n const innerProps = getProp(setValue, 'properties');\n const source = isRecord(innerProps) ? innerProps : setValue;\n const props: Record<string, { value: unknown; unit?: string; type?: string }> = {};\n Object.entries(source).forEach(([propName, propVal]) => {\n if (isRecord(propVal) && 'value' in propVal) {\n props[propName] = propVal as { value: unknown; unit?: string; type?: string };\n } else {\n props[propName] = { value: propVal };\n }\n });\n propertySets[setName] = props;\n });\n return propertySets;\n};\n\nexport const buildMetadataMap = (entries: unknown[]): ModelMetadata => {\n const out: ModelMetadata = {};\n if (!Array.isArray(entries)) return out;\n entries.forEach((entry) => {\n const product = getProp(entry, 'product') ?? entry;\n const gid = getProp(product, 'gid') ?? getProp(product, 'id') ?? null;\n if (!gid) return;\n const propertySets = normalizePropertySets(product);\n const ifcClass = resolveIfcClassName(product) ?? undefined;\n const ifcClassId = resolveIfcClassId(product) ?? undefined;\n out[String(gid)] = {\n productId: String(gid),\n ifcClass,\n ifcClassId,\n properties: propertySets,\n propertySets\n };\n });\n return out;\n};\n\nexport const resolveMeta = (meta: unknown, metadataById?: ModelMetadata): unknown => {\n const productId = getProp(meta, 'productId') ?? getProp(meta, 'gid') ?? getProp(meta, 'id');\n const base = productId && metadataById ? metadataById[String(productId)] : undefined;\n if (!base) {\n return meta;\n }\n const baseProps = getProp(base, 'properties');\n const metaProps = getProp(meta, 'properties');\n const mergedProps =\n baseProps || metaProps\n ? { ...(isRecord(baseProps) ? baseProps : {}), ...(isRecord(metaProps) ? metaProps : {}) }\n : undefined;\n return mergedProps\n ? { ...base, ...(isRecord(meta) ? meta : {}), productId, properties: mergedProps }\n : { ...base, ...(isRecord(meta) ? meta : {}), productId };\n};\n\n/**\n * Resolve includeClasses config to an array of filters.\n *\n * Supports:\n * - String arrays: [\"space\", \"walls\"]\n * - Filter objects: [{ class: \"space\", where: { \"BIP.spacetype\": \"ROOM\" } }]\n * - Preset references: { preset: \"defaultBuilding\" }\n * - Mixed arrays: [\"walls\", { class: \"space\", where: {...} }]\n *\n * @returns Array of filters (strings or class+where objects), or null if no filters\n */\nexport const resolveIncludeClasses = (\n includeClasses: unknown,\n currentIncludePresets: Record<string, string[]>\n): ResolvedIncludeFilter[] | null => {\n if (!includeClasses) return null;\n\n // Handle array of filters (strings or objects)\n if (Array.isArray(includeClasses)) {\n const result: ResolvedIncludeFilter[] = [];\n for (const item of includeClasses) {\n if (typeof item === 'string' && item.length > 0) {\n result.push(item);\n } else if (isRecord(item)) {\n const cls = getProp(item, 'class');\n const where = getProp(item, 'where');\n // Must have either class or where (or both)\n if (cls !== undefined || (where && isRecord(where))) {\n result.push({ class: cls as string | string[] | undefined, where: where as WhereCondition });\n }\n }\n }\n return result.length > 0 ? result : null;\n }\n\n // Handle preset reference or filter object\n if (isRecord(includeClasses)) {\n const preset = getProp(includeClasses, 'preset');\n const cls = getProp(includeClasses, 'class');\n const where = getProp(includeClasses, 'where');\n\n // Preset reference: { preset: \"name\" }\n if (typeof preset === 'string') {\n const presetName = preset;\n const base = currentIncludePresets[presetName] ?? [];\n const addProp = getProp(includeClasses, 'add');\n const removeProp = getProp(includeClasses, 'remove');\n const add = Array.isArray(addProp) ? addProp : [];\n const remove = Array.isArray(removeProp) ? removeProp : [];\n const set = new Set<string>();\n base.forEach((c: string) => set.add(c));\n add.forEach((c: unknown) => typeof c === 'string' && set.add(c));\n remove.forEach((c: unknown) => typeof c === 'string' && set.delete(c));\n const strings = Array.from(set).filter((c) => typeof c === 'string' && c.length > 0);\n return strings.length > 0 ? strings : null;\n }\n\n // Filter object: { class: \"space\", where: {...} }\n if (cls !== undefined || (where && isRecord(where))) {\n return [{ class: cls as string | string[] | undefined, where: where as WhereCondition }];\n }\n }\n\n return null;\n};\n\n/**\n * Resolve allowed class names from template/viewport includeClasses config.\n *\n * Extracts only string filters (class names), ignoring filter objects with where conditions.\n * Used for backward compatibility and simple class-based filtering.\n *\n * @returns Set of normalized class names, or null if no filters\n */\nexport const resolveAllowedClasses = (layoutTemplate: LayoutTemplate, viewportId = 'main'): Set<string> | null => {\n if (!layoutTemplate) return null;\n const presets = layoutTemplate.presets?.includeClasses ?? {};\n const templateClasses = resolveIncludeClasses(getProp(layoutTemplate, 'includeClasses'), presets);\n const elements = layoutTemplate.elements;\n const viewportEl = Array.isArray(elements)\n ? elements.find((el) => isRecord(el) && getProp(el, 'kind') === 'viewport' && getProp(el, 'id') === viewportId)\n : undefined;\n const viewportClasses = resolveIncludeClasses(getProp(viewportEl, 'includeClasses'), presets);\n const resolved = viewportClasses ?? templateClasses;\n if (!resolved || !resolved.length) {\n return null;\n }\n // Extract only string filters (class names)\n const classNames = new Set<string>();\n for (const filter of resolved) {\n if (typeof filter === 'string') {\n classNames.add(filter);\n } else if (isRecord(filter) && filter.class) {\n const classes = Array.isArray(filter.class) ? filter.class : [filter.class];\n for (const c of classes) {\n if (typeof c === 'string') classNames.add(c);\n }\n }\n }\n return classNames.size > 0 ? classNames : null;\n};\n\nexport const getPathValue = (obj: unknown, path: string): unknown => getValueByPath(obj, path);\n"]}
|