@toolbox-web/grid 0.2.7 → 0.3.0
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 +13 -13
- package/all.d.ts +25 -5659
- package/all.d.ts.map +1 -0
- package/all.js +524 -450
- package/all.js.map +1 -1
- package/index.d.ts +8 -2678
- package/index.d.ts.map +1 -0
- package/index.js +3929 -25
- package/index.js.map +1 -1
- package/lib/core/constants.d.ts +114 -0
- package/lib/core/constants.d.ts.map +1 -0
- package/lib/core/grid.d.ts +337 -0
- package/lib/core/grid.d.ts.map +1 -0
- package/lib/core/internal/aggregators.d.ts +67 -0
- package/lib/core/internal/aggregators.d.ts.map +1 -0
- package/lib/core/internal/column-state.d.ts +124 -0
- package/lib/core/internal/column-state.d.ts.map +1 -0
- package/lib/core/internal/columns.d.ts +107 -0
- package/lib/core/internal/columns.d.ts.map +1 -0
- package/lib/core/internal/dom-builder.d.ts +115 -0
- package/lib/core/internal/dom-builder.d.ts.map +1 -0
- package/lib/core/internal/editing.d.ts +76 -0
- package/lib/core/internal/editing.d.ts.map +1 -0
- package/lib/core/internal/editors.d.ts +8 -0
- package/lib/core/internal/editors.d.ts.map +1 -0
- package/lib/core/internal/event-delegation.d.ts +11 -0
- package/lib/core/internal/event-delegation.d.ts.map +1 -0
- package/lib/core/internal/grid-internals.d.ts +83 -0
- package/lib/core/internal/grid-internals.d.ts.map +1 -0
- package/lib/core/internal/header.d.ts +7 -0
- package/lib/core/internal/header.d.ts.map +1 -0
- package/lib/core/internal/idle-scheduler.d.ts +65 -0
- package/lib/core/internal/idle-scheduler.d.ts.map +1 -0
- package/lib/core/internal/inference.d.ts +12 -0
- package/lib/core/internal/inference.d.ts.map +1 -0
- package/lib/core/internal/keyboard.d.ts +18 -0
- package/lib/core/internal/keyboard.d.ts.map +1 -0
- package/lib/core/internal/resize.d.ts +3 -0
- package/lib/core/internal/resize.d.ts.map +1 -0
- package/lib/core/internal/rows.d.ts +35 -0
- package/lib/core/internal/rows.d.ts.map +1 -0
- package/lib/core/internal/sanitize.d.ts +13 -0
- package/lib/core/internal/sanitize.d.ts.map +1 -0
- package/lib/core/internal/shell.d.ts +228 -0
- package/lib/core/internal/shell.d.ts.map +1 -0
- package/lib/core/internal/sorting.d.ts +24 -0
- package/lib/core/internal/sorting.d.ts.map +1 -0
- package/lib/core/internal/touch-scroll.d.ts +54 -0
- package/lib/core/internal/touch-scroll.d.ts.map +1 -0
- package/lib/core/internal/utils.d.ts +38 -0
- package/lib/core/internal/utils.d.ts.map +1 -0
- package/lib/core/internal/virtualization.d.ts +66 -0
- package/lib/core/internal/virtualization.d.ts.map +1 -0
- package/lib/core/plugin/base-plugin.d.ts +616 -0
- package/lib/core/plugin/base-plugin.d.ts.map +1 -0
- package/lib/core/plugin/index.d.ts +11 -0
- package/lib/core/plugin/index.d.ts.map +1 -0
- package/lib/core/plugin/plugin-manager.d.ts +183 -0
- package/lib/core/plugin/plugin-manager.d.ts.map +1 -0
- package/lib/core/plugin/types.d.ts +196 -0
- package/lib/core/plugin/types.d.ts.map +1 -0
- package/lib/core/types.d.ts +841 -0
- package/lib/core/types.d.ts.map +1 -0
- package/lib/plugins/clipboard/ClipboardPlugin.d.ts +46 -0
- package/lib/plugins/clipboard/ClipboardPlugin.d.ts.map +1 -0
- package/lib/plugins/clipboard/copy.d.ts +47 -0
- package/lib/plugins/clipboard/copy.d.ts.map +1 -0
- package/lib/plugins/clipboard/index.d.ts +7 -0
- package/lib/plugins/clipboard/index.d.ts.map +1 -0
- package/lib/plugins/clipboard/index.js.map +1 -1
- package/lib/plugins/clipboard/paste.d.ts +25 -0
- package/lib/plugins/clipboard/paste.d.ts.map +1 -0
- package/lib/plugins/clipboard/types.d.ts +40 -0
- package/lib/plugins/clipboard/types.d.ts.map +1 -0
- package/lib/plugins/column-virtualization/ColumnVirtualizationPlugin.d.ts +54 -0
- package/lib/plugins/column-virtualization/ColumnVirtualizationPlugin.d.ts.map +1 -0
- package/lib/plugins/column-virtualization/column-virtualization.d.ts +53 -0
- package/lib/plugins/column-virtualization/column-virtualization.d.ts.map +1 -0
- package/lib/plugins/column-virtualization/index.d.ts +7 -0
- package/lib/plugins/column-virtualization/index.d.ts.map +1 -0
- package/lib/plugins/column-virtualization/index.js.map +1 -1
- package/lib/plugins/column-virtualization/types.d.ts +41 -0
- package/lib/plugins/column-virtualization/types.d.ts.map +1 -0
- package/lib/plugins/context-menu/ContextMenuPlugin.d.ts +52 -0
- package/lib/plugins/context-menu/ContextMenuPlugin.d.ts.map +1 -0
- package/lib/plugins/context-menu/index.d.ts +7 -0
- package/lib/plugins/context-menu/index.d.ts.map +1 -0
- package/lib/plugins/context-menu/index.js +24 -24
- package/lib/plugins/context-menu/index.js.map +1 -1
- package/lib/plugins/context-menu/menu.d.ts +38 -0
- package/lib/plugins/context-menu/menu.d.ts.map +1 -0
- package/lib/plugins/context-menu/types.d.ts +77 -0
- package/lib/plugins/context-menu/types.d.ts.map +1 -0
- package/lib/plugins/export/ExportPlugin.d.ts +53 -0
- package/lib/plugins/export/ExportPlugin.d.ts.map +1 -0
- package/lib/plugins/export/csv.d.ts +31 -0
- package/lib/plugins/export/csv.d.ts.map +1 -0
- package/lib/plugins/export/excel.d.ts +12 -0
- package/lib/plugins/export/excel.d.ts.map +1 -0
- package/lib/plugins/export/index.d.ts +7 -0
- package/lib/plugins/export/index.d.ts.map +1 -0
- package/lib/plugins/export/index.js.map +1 -1
- package/lib/plugins/export/types.d.ts +57 -0
- package/lib/plugins/export/types.d.ts.map +1 -0
- package/lib/plugins/filtering/FilteringPlugin.d.ts +128 -0
- package/lib/plugins/filtering/FilteringPlugin.d.ts.map +1 -0
- package/lib/plugins/filtering/filter-model.d.ts +38 -0
- package/lib/plugins/filtering/filter-model.d.ts.map +1 -0
- package/lib/plugins/filtering/index.d.ts +7 -0
- package/lib/plugins/filtering/index.d.ts.map +1 -0
- package/lib/plugins/filtering/index.js +5 -5
- package/lib/plugins/filtering/index.js.map +1 -1
- package/lib/plugins/filtering/types.d.ts +157 -0
- package/lib/plugins/filtering/types.d.ts.map +1 -0
- package/lib/plugins/grouping-columns/GroupingColumnsPlugin.d.ts +51 -0
- package/lib/plugins/grouping-columns/GroupingColumnsPlugin.d.ts.map +1 -0
- package/lib/plugins/grouping-columns/grouping-columns.d.ts +41 -0
- package/lib/plugins/grouping-columns/grouping-columns.d.ts.map +1 -0
- package/lib/plugins/grouping-columns/index.d.ts +7 -0
- package/lib/plugins/grouping-columns/index.d.ts.map +1 -0
- package/lib/plugins/grouping-columns/index.js +58 -42
- package/lib/plugins/grouping-columns/index.js.map +1 -1
- package/lib/plugins/grouping-columns/types.d.ts +91 -0
- package/lib/plugins/grouping-columns/types.d.ts.map +1 -0
- package/lib/plugins/grouping-rows/GroupingRowsPlugin.d.ts +120 -0
- package/lib/plugins/grouping-rows/GroupingRowsPlugin.d.ts.map +1 -0
- package/lib/plugins/grouping-rows/grouping-rows.d.ts +51 -0
- package/lib/plugins/grouping-rows/grouping-rows.d.ts.map +1 -0
- package/lib/plugins/grouping-rows/index.d.ts +7 -0
- package/lib/plugins/grouping-rows/index.d.ts.map +1 -0
- package/lib/plugins/grouping-rows/index.js +51 -51
- package/lib/plugins/grouping-rows/index.js.map +1 -1
- package/lib/plugins/grouping-rows/types.d.ts +95 -0
- package/lib/plugins/grouping-rows/types.d.ts.map +1 -0
- package/lib/plugins/master-detail/MasterDetailPlugin.d.ts +147 -0
- package/lib/plugins/master-detail/MasterDetailPlugin.d.ts.map +1 -0
- package/lib/plugins/master-detail/index.d.ts +7 -0
- package/lib/plugins/master-detail/index.d.ts.map +1 -0
- package/lib/plugins/master-detail/index.js +235 -78
- package/lib/plugins/master-detail/index.js.map +1 -1
- package/lib/plugins/master-detail/master-detail.d.ts +30 -0
- package/lib/plugins/master-detail/master-detail.d.ts.map +1 -0
- package/lib/plugins/master-detail/types.d.ts +40 -0
- package/lib/plugins/master-detail/types.d.ts.map +1 -0
- package/lib/plugins/multi-sort/MultiSortPlugin.d.ts +58 -0
- package/lib/plugins/multi-sort/MultiSortPlugin.d.ts.map +1 -0
- package/lib/plugins/multi-sort/index.d.ts +7 -0
- package/lib/plugins/multi-sort/index.d.ts.map +1 -0
- package/lib/plugins/multi-sort/index.js.map +1 -1
- package/lib/plugins/multi-sort/multi-sort.d.ts +51 -0
- package/lib/plugins/multi-sort/multi-sort.d.ts.map +1 -0
- package/lib/plugins/multi-sort/types.d.ts +25 -0
- package/lib/plugins/multi-sort/types.d.ts.map +1 -0
- package/lib/plugins/pinned-columns/PinnedColumnsPlugin.d.ts +58 -0
- package/lib/plugins/pinned-columns/PinnedColumnsPlugin.d.ts.map +1 -0
- package/lib/plugins/pinned-columns/index.d.ts +7 -0
- package/lib/plugins/pinned-columns/index.d.ts.map +1 -0
- package/lib/plugins/pinned-columns/index.js.map +1 -1
- package/lib/plugins/pinned-columns/pinned-columns.d.ts +62 -0
- package/lib/plugins/pinned-columns/pinned-columns.d.ts.map +1 -0
- package/lib/plugins/pinned-columns/types.d.ts +20 -0
- package/lib/plugins/pinned-columns/types.d.ts.map +1 -0
- package/lib/plugins/pinned-rows/PinnedRowsPlugin.d.ts +64 -0
- package/lib/plugins/pinned-rows/PinnedRowsPlugin.d.ts.map +1 -0
- package/lib/plugins/pinned-rows/index.d.ts +7 -0
- package/lib/plugins/pinned-rows/index.d.ts.map +1 -0
- package/lib/plugins/pinned-rows/index.js +1 -1
- package/lib/plugins/pinned-rows/index.js.map +1 -1
- package/lib/plugins/pinned-rows/pinned-rows.d.ts +43 -0
- package/lib/plugins/pinned-rows/pinned-rows.d.ts.map +1 -0
- package/lib/plugins/pinned-rows/types.d.ts +95 -0
- package/lib/plugins/pinned-rows/types.d.ts.map +1 -0
- package/lib/plugins/pivot/PivotPlugin.d.ts +94 -0
- package/lib/plugins/pivot/PivotPlugin.d.ts.map +1 -0
- package/lib/plugins/pivot/index.d.ts +7 -0
- package/lib/plugins/pivot/index.d.ts.map +1 -0
- package/lib/plugins/pivot/index.js.map +1 -1
- package/lib/plugins/pivot/pivot-engine.d.ts +50 -0
- package/lib/plugins/pivot/pivot-engine.d.ts.map +1 -0
- package/lib/plugins/pivot/pivot-model.d.ts +6 -0
- package/lib/plugins/pivot/pivot-model.d.ts.map +1 -0
- package/lib/plugins/pivot/pivot-panel.d.ts +25 -0
- package/lib/plugins/pivot/pivot-panel.d.ts.map +1 -0
- package/lib/plugins/pivot/pivot-rows.d.ts +33 -0
- package/lib/plugins/pivot/pivot-rows.d.ts.map +1 -0
- package/lib/plugins/pivot/types.d.ts +62 -0
- package/lib/plugins/pivot/types.d.ts.map +1 -0
- package/lib/plugins/reorder/ReorderPlugin.d.ts +81 -0
- package/lib/plugins/reorder/ReorderPlugin.d.ts.map +1 -0
- package/lib/plugins/reorder/column-drag.d.ts +41 -0
- package/lib/plugins/reorder/column-drag.d.ts.map +1 -0
- package/lib/plugins/reorder/index.d.ts +7 -0
- package/lib/plugins/reorder/index.d.ts.map +1 -0
- package/lib/plugins/reorder/index.js +51 -48
- package/lib/plugins/reorder/index.js.map +1 -1
- package/lib/plugins/reorder/types.d.ts +54 -0
- package/lib/plugins/reorder/types.d.ts.map +1 -0
- package/lib/plugins/selection/SelectionPlugin.d.ts +77 -0
- package/lib/plugins/selection/SelectionPlugin.d.ts.map +1 -0
- package/lib/plugins/selection/index.d.ts +8 -0
- package/lib/plugins/selection/index.d.ts.map +1 -0
- package/lib/plugins/selection/index.js +86 -75
- package/lib/plugins/selection/index.js.map +1 -1
- package/lib/plugins/selection/range-selection.d.ts +109 -0
- package/lib/plugins/selection/range-selection.d.ts.map +1 -0
- package/lib/plugins/selection/row-selection.d.ts +48 -0
- package/lib/plugins/selection/row-selection.d.ts.map +1 -0
- package/lib/plugins/selection/types.d.ts +80 -0
- package/lib/plugins/selection/types.d.ts.map +1 -0
- package/lib/plugins/server-side/ServerSidePlugin.d.ts +56 -0
- package/lib/plugins/server-side/ServerSidePlugin.d.ts.map +1 -0
- package/lib/plugins/server-side/cache.d.ts +14 -0
- package/lib/plugins/server-side/cache.d.ts.map +1 -0
- package/lib/plugins/server-side/datasource.d.ts +12 -0
- package/lib/plugins/server-side/datasource.d.ts.map +1 -0
- package/lib/plugins/server-side/index.d.ts +7 -0
- package/lib/plugins/server-side/index.d.ts.map +1 -0
- package/lib/plugins/server-side/index.js.map +1 -1
- package/lib/plugins/server-side/types.d.ts +43 -0
- package/lib/plugins/server-side/types.d.ts.map +1 -0
- package/lib/plugins/tree/TreePlugin.d.ts +49 -0
- package/lib/plugins/tree/TreePlugin.d.ts.map +1 -0
- package/lib/plugins/tree/index.d.ts +8 -0
- package/lib/plugins/tree/index.d.ts.map +1 -0
- package/lib/plugins/tree/index.js.map +1 -1
- package/lib/plugins/tree/tree-data.d.ts +42 -0
- package/lib/plugins/tree/tree-data.d.ts.map +1 -0
- package/lib/plugins/tree/tree-detect.d.ts +24 -0
- package/lib/plugins/tree/tree-detect.d.ts.map +1 -0
- package/lib/plugins/tree/types.d.ts +61 -0
- package/lib/plugins/tree/types.d.ts.map +1 -0
- package/lib/plugins/undo-redo/UndoRedoPlugin.d.ts +68 -0
- package/lib/plugins/undo-redo/UndoRedoPlugin.d.ts.map +1 -0
- package/lib/plugins/undo-redo/history.d.ts +64 -0
- package/lib/plugins/undo-redo/history.d.ts.map +1 -0
- package/lib/plugins/undo-redo/index.d.ts +7 -0
- package/lib/plugins/undo-redo/index.d.ts.map +1 -0
- package/lib/plugins/undo-redo/index.js.map +1 -1
- package/lib/plugins/undo-redo/types.d.ts +41 -0
- package/lib/plugins/undo-redo/types.d.ts.map +1 -0
- package/lib/plugins/visibility/VisibilityPlugin.d.ts +135 -0
- package/lib/plugins/visibility/VisibilityPlugin.d.ts.map +1 -0
- package/lib/plugins/visibility/index.d.ts +8 -0
- package/lib/plugins/visibility/index.d.ts.map +1 -0
- package/lib/plugins/visibility/index.js.map +1 -1
- package/lib/plugins/visibility/types.d.ts +33 -0
- package/lib/plugins/visibility/types.d.ts.map +1 -0
- package/lib/plugins/visibility/visibility.d.ts +30 -0
- package/lib/plugins/visibility/visibility.d.ts.map +1 -0
- package/package.json +6 -2
- package/public.d.ts +52 -0
- package/public.d.ts.map +1 -0
- package/umd/grid.all.umd.js +32 -74
- package/umd/grid.all.umd.js.map +1 -1
- package/umd/grid.umd.js +22 -64
- package/umd/grid.umd.js.map +1 -1
- package/umd/plugins/context-menu.umd.js +1 -1
- package/umd/plugins/context-menu.umd.js.map +1 -1
- package/umd/plugins/filtering.umd.js +1 -1
- package/umd/plugins/filtering.umd.js.map +1 -1
- package/umd/plugins/grouping-columns.umd.js +1 -1
- package/umd/plugins/grouping-columns.umd.js.map +1 -1
- package/umd/plugins/grouping-rows.umd.js +1 -1
- package/umd/plugins/grouping-rows.umd.js.map +1 -1
- package/umd/plugins/master-detail.umd.js +1 -1
- package/umd/plugins/master-detail.umd.js.map +1 -1
- package/umd/plugins/pinned-rows.umd.js +1 -1
- package/umd/plugins/pinned-rows.umd.js.map +1 -1
- package/umd/plugins/pivot.umd.js.map +1 -1
- package/umd/plugins/selection.umd.js +1 -1
- package/umd/plugins/selection.umd.js.map +1 -1
- package/index-DG2CZ_Zo.js +0 -3229
- package/index-DG2CZ_Zo.js.map +0 -1
package/all.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"all.js","sources":["../../../libs/grid/src/lib/plugins/clipboard/copy.ts","../../../libs/grid/src/lib/plugins/clipboard/paste.ts","../../../libs/grid/src/lib/plugins/clipboard/ClipboardPlugin.ts","../../../libs/grid/src/lib/plugins/column-virtualization/column-virtualization.ts","../../../libs/grid/src/lib/plugins/column-virtualization/ColumnVirtualizationPlugin.ts","../../../libs/grid/src/lib/plugins/context-menu/menu.ts","../../../libs/grid/src/lib/plugins/context-menu/ContextMenuPlugin.ts","../../../libs/grid/src/lib/plugins/export/csv.ts","../../../libs/grid/src/lib/plugins/export/excel.ts","../../../libs/grid/src/lib/plugins/export/ExportPlugin.ts","../../../libs/grid/src/lib/core/internal/virtualization.ts","../../../libs/grid/src/lib/plugins/filtering/filter-model.ts","../../../libs/grid/src/lib/plugins/filtering/FilteringPlugin.ts","../../../libs/grid/src/lib/plugins/grouping-columns/grouping-columns.ts","../../../libs/grid/src/lib/plugins/grouping-columns/GroupingColumnsPlugin.ts","../../../libs/grid/src/lib/plugins/grouping-rows/grouping-rows.ts","../../../libs/grid/src/lib/plugins/grouping-rows/GroupingRowsPlugin.ts","../../../libs/grid/src/lib/plugins/master-detail/master-detail.ts","../../../libs/grid/src/lib/plugins/master-detail/MasterDetailPlugin.ts","../../../libs/grid/src/lib/plugins/multi-sort/multi-sort.ts","../../../libs/grid/src/lib/plugins/multi-sort/MultiSortPlugin.ts","../../../libs/grid/src/lib/plugins/pinned-columns/pinned-columns.ts","../../../libs/grid/src/lib/plugins/pinned-columns/PinnedColumnsPlugin.ts","../../../libs/grid/src/lib/plugins/pinned-rows/pinned-rows.ts","../../../libs/grid/src/lib/plugins/pinned-rows/PinnedRowsPlugin.ts","../../../libs/grid/src/lib/plugins/pivot/pivot-model.ts","../../../libs/grid/src/lib/plugins/pivot/pivot-engine.ts","../../../libs/grid/src/lib/plugins/pivot/pivot-panel.ts","../../../libs/grid/src/lib/plugins/pivot/pivot-rows.ts","../../../libs/grid/src/lib/plugins/pivot/PivotPlugin.ts","../../../libs/grid/src/lib/plugins/reorder/column-drag.ts","../../../libs/grid/src/lib/plugins/reorder/ReorderPlugin.ts","../../../libs/grid/src/lib/plugins/selection/range-selection.ts","../../../libs/grid/src/lib/plugins/selection/SelectionPlugin.ts","../../../libs/grid/src/lib/plugins/server-side/datasource.ts","../../../libs/grid/src/lib/plugins/server-side/ServerSidePlugin.ts","../../../libs/grid/src/lib/plugins/tree/tree-data.ts","../../../libs/grid/src/lib/plugins/tree/tree-detect.ts","../../../libs/grid/src/lib/plugins/tree/TreePlugin.ts","../../../libs/grid/src/lib/plugins/undo-redo/history.ts","../../../libs/grid/src/lib/plugins/undo-redo/UndoRedoPlugin.ts","../../../libs/grid/src/lib/plugins/visibility/VisibilityPlugin.ts"],"sourcesContent":["/**\n * Clipboard Copy Logic\n *\n * Pure functions for copying grid data to clipboard.\n */\n\nimport type { ColumnConfig } from '../../core/types';\nimport type { ClipboardConfig } from './types';\n\n/** Parameters for building clipboard text */\nexport interface CopyParams {\n /** All grid rows */\n rows: unknown[];\n /** Column configurations */\n columns: ColumnConfig[];\n /** Selected row indices */\n selectedIndices: Set<number> | number[];\n /** Clipboard configuration */\n config: ClipboardConfig;\n}\n\n/**\n * Format a cell value for clipboard output.\n *\n * Uses custom processCell if provided, otherwise applies default formatting:\n * - null/undefined → empty string\n * - Date → ISO string\n * - Object → JSON string\n * - Other → String conversion with optional quoting\n *\n * @param value - The cell value to format\n * @param field - The field name\n * @param row - The full row object\n * @param config - Clipboard configuration\n * @returns Formatted string value\n */\nexport function formatCellValue(value: unknown, field: string, row: unknown, config: ClipboardConfig): string {\n if (config.processCell) {\n return config.processCell(value, field, row);\n }\n\n if (value == null) return '';\n if (value instanceof Date) return value.toISOString();\n if (typeof value === 'object') return JSON.stringify(value);\n\n const str = String(value);\n const delimiter = config.delimiter ?? '\\t';\n const newline = config.newline ?? '\\n';\n\n // Quote if contains delimiter, newline, or quotes (or if quoteStrings is enabled)\n if (config.quoteStrings || str.includes(delimiter) || str.includes(newline) || str.includes('\"')) {\n return `\"${str.replace(/\"/g, '\"\"')}\"`;\n }\n\n return str;\n}\n\n/**\n * Build clipboard text from selected rows and columns.\n *\n * @param params - Copy parameters including rows, columns, selection, and config\n * @returns Tab-separated (or custom delimiter) text ready for clipboard\n */\nexport function buildClipboardText(params: CopyParams): string {\n const { rows, columns, selectedIndices, config } = params;\n const delimiter = config.delimiter ?? '\\t';\n const newline = config.newline ?? '\\n';\n\n // Filter to visible columns (not hidden, not internal __ prefixed)\n const visibleColumns = columns.filter((c) => !c.hidden && !c.field.startsWith('__'));\n\n const lines: string[] = [];\n\n // Add header row if configured\n if (config.includeHeaders) {\n const headerCells = visibleColumns.map((c) => {\n const header = c.header || c.field;\n // Quote headers if they contain special characters\n if (header.includes(delimiter) || header.includes(newline) || header.includes('\"')) {\n return `\"${header.replace(/\"/g, '\"\"')}\"`;\n }\n return header;\n });\n lines.push(headerCells.join(delimiter));\n }\n\n // Convert indices to sorted array\n const indices = selectedIndices instanceof Set ? [...selectedIndices] : selectedIndices;\n const sortedIndices = [...indices].sort((a, b) => a - b);\n\n // Build data rows\n for (const idx of sortedIndices) {\n const row = rows[idx];\n if (!row) continue;\n\n const cells = visibleColumns.map((col) =>\n formatCellValue((row as Record<string, unknown>)[col.field], col.field, row, config)\n );\n lines.push(cells.join(delimiter));\n }\n\n return lines.join(newline);\n}\n\n/**\n * Copy text to the system clipboard.\n *\n * Uses the modern Clipboard API when available, with fallback\n * to execCommand for older browsers.\n *\n * @param text - The text to copy\n * @returns Promise resolving to true if successful, false otherwise\n */\nexport async function copyToClipboard(text: string): Promise<boolean> {\n try {\n await navigator.clipboard.writeText(text);\n return true;\n } catch {\n // Fallback for older browsers or when Clipboard API is not available\n const textarea = document.createElement('textarea');\n textarea.value = text;\n textarea.style.position = 'fixed';\n textarea.style.opacity = '0';\n textarea.style.pointerEvents = 'none';\n document.body.appendChild(textarea);\n textarea.select();\n const success = document.execCommand('copy');\n document.body.removeChild(textarea);\n return success;\n }\n}\n","/**\n * Clipboard Paste Logic\n *\n * Pure functions for reading and parsing clipboard data.\n */\n\nimport type { ClipboardConfig } from './types';\n\n/**\n * Parse clipboard text into a 2D array of cell values.\n *\n * Handles:\n * - Quoted values (with escaped double quotes \"\")\n * - Multi-line quoted values (newlines within quotes are preserved)\n * - Custom delimiters and newlines\n * - Empty lines (filtered out only if they contain no data)\n *\n * @param text - Raw clipboard text\n * @param config - Clipboard configuration\n * @returns 2D array where each sub-array is a row of cell values\n */\nexport function parseClipboardText(text: string, config: ClipboardConfig): string[][] {\n const delimiter = config.delimiter ?? '\\t';\n const newline = config.newline ?? '\\n';\n\n // Handle Windows CRLF line endings\n const normalizedText = text.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n');\n\n // Parse the entire text handling quoted fields that may span multiple lines\n const rows: string[][] = [];\n let currentRow: string[] = [];\n let currentCell = '';\n let inQuotes = false;\n\n for (let i = 0; i < normalizedText.length; i++) {\n const char = normalizedText[i];\n\n if (char === '\"' && !inQuotes) {\n // Start of quoted field\n inQuotes = true;\n } else if (char === '\"' && inQuotes) {\n // Check for escaped quote (\"\")\n if (normalizedText[i + 1] === '\"') {\n currentCell += '\"';\n i++; // Skip the second quote\n } else {\n // End of quoted field\n inQuotes = false;\n }\n } else if (char === delimiter && !inQuotes) {\n // Field separator\n currentRow.push(currentCell);\n currentCell = '';\n } else if (char === newline && !inQuotes) {\n // Row separator (only if not inside quotes)\n currentRow.push(currentCell);\n currentCell = '';\n // Only add non-empty rows (at least one non-empty cell or multiple cells)\n if (currentRow.length > 1 || currentRow.some((c) => c.trim() !== '')) {\n rows.push(currentRow);\n }\n currentRow = [];\n } else {\n currentCell += char;\n }\n }\n\n // Handle the last cell and row\n currentRow.push(currentCell);\n if (currentRow.length > 1 || currentRow.some((c) => c.trim() !== '')) {\n rows.push(currentRow);\n }\n\n return rows;\n}\n\n/**\n * Read text from the system clipboard.\n *\n * Uses the modern Clipboard API. Returns empty string if\n * the API is not available or permission is denied.\n *\n * @returns Promise resolving to clipboard text or empty string\n */\nexport async function readFromClipboard(): Promise<string> {\n try {\n return await navigator.clipboard.readText();\n } catch {\n // Permission denied or API not available\n return '';\n }\n}\n","/**\n * Clipboard Plugin (Class-based)\n *\n * Provides copy/paste functionality for tbw-grid.\n * Supports Ctrl+C/Cmd+C for copying and Ctrl+V/Cmd+V for pasting.\n *\n * **With Selection plugin:** Copy selected rows as a range\n * - includeHeaders: true → adds header row at top\n * - includeHeaders: false → data rows only\n *\n * **Without Selection plugin:** Copy focused cell only\n * - includeHeaders: true → \"Header: value\" format\n * - includeHeaders: false → value only\n */\n\nimport { BaseGridPlugin } from '../../core/plugin/base-plugin';\nimport { buildClipboardText, copyToClipboard } from './copy';\nimport { parseClipboardText, readFromClipboard } from './paste';\nimport type { ClipboardConfig, CopyDetail, PasteDetail } from './types';\n\n/**\n * Clipboard Plugin for tbw-grid\n *\n * @example\n * ```ts\n * new ClipboardPlugin({ includeHeaders: true })\n * ```\n */\nexport class ClipboardPlugin extends BaseGridPlugin<ClipboardConfig> {\n readonly name = 'clipboard';\n override readonly version = '1.0.0';\n\n protected override get defaultConfig(): Partial<ClipboardConfig> {\n return {\n includeHeaders: false,\n delimiter: '\\t',\n newline: '\\n',\n quoteStrings: false,\n };\n }\n\n // #region Internal State\n /** The last copied text (for reference/debugging) */\n private lastCopied: { text: string; timestamp: number } | null = null;\n // #endregion\n\n // #region Lifecycle\n\n override detach(): void {\n this.lastCopied = null;\n }\n // #endregion\n\n // #region Event Handlers\n\n override onKeyDown(event: KeyboardEvent): boolean {\n const isCopy = (event.ctrlKey || event.metaKey) && event.key === 'c';\n const isPaste = (event.ctrlKey || event.metaKey) && event.key === 'v';\n\n if (isCopy) {\n this.#handleCopy(event.target as HTMLElement);\n return true; // Prevent default browser behavior\n }\n\n if (isPaste) {\n this.#handlePaste();\n return true; // Prevent default browser behavior\n }\n\n return false;\n }\n // #endregion\n\n // #region Private Methods\n\n /**\n * Handle copy operation\n */\n #handleCopy(target: HTMLElement): void {\n // Try to get selection from selection plugin (if available)\n // Use dynamic import to avoid circular dependency issues\n const selectionPlugin = this.#getSelectionPlugin();\n\n // Check for different selection types\n const selectedRows = selectionPlugin?.getSelectedRows() ?? [];\n const hasRowSelection = selectedRows.length > 0;\n const ranges = selectionPlugin?.getRanges() ?? [];\n const hasRangeSelection = ranges.length > 0;\n const hasCellSelection = selectionPlugin?.getSelectedCell() != null;\n\n let text: string;\n let rowCount: number;\n let columnCount: number;\n\n if (hasRowSelection && selectionPlugin) {\n // Row selection mode - copy full rows\n text = buildClipboardText({\n rows: this.rows as unknown[],\n columns: [...this.columns],\n selectedIndices: selectedRows,\n config: this.config,\n });\n rowCount = selectedRows.length;\n columnCount = this.columns.filter((c) => !c.hidden && !c.field.startsWith('__')).length;\n } else if (hasRangeSelection && selectionPlugin) {\n // Range selection mode - copy rectangular range (use last range as active)\n const range = ranges[ranges.length - 1];\n const result = this.#buildRangeText({\n startRow: range.from.row,\n startCol: range.from.col,\n endRow: range.to.row,\n endCol: range.to.col,\n });\n text = result.text;\n rowCount = result.rowCount;\n columnCount = result.columnCount;\n } else if (hasCellSelection && selectionPlugin) {\n // Cell selection mode - copy single cell\n const cell = selectionPlugin.getSelectedCell()!;\n const result = this.#buildCellText(cell.row, cell.col);\n if (!result) return;\n text = result.text;\n rowCount = 1;\n columnCount = 1;\n } else {\n // Fallback: try to find focused cell from DOM\n const result = this.#buildSingleCellText(target);\n if (!result) return;\n text = result.text;\n rowCount = 1;\n columnCount = 1;\n }\n\n copyToClipboard(text).then(() => {\n this.lastCopied = { text, timestamp: Date.now() };\n this.emit<CopyDetail>('copy', { text, rowCount, columnCount });\n });\n }\n\n /**\n * Handle paste operation\n */\n #handlePaste(): void {\n readFromClipboard().then((text) => {\n if (!text) return;\n const parsed = parseClipboardText(text, this.config);\n this.emit<PasteDetail>('paste', { rows: parsed, text });\n });\n }\n\n /**\n * Get the selection plugin instance if available.\n */\n #getSelectionPlugin(): SelectionPluginInterface | undefined {\n // Dynamically get the SelectionPlugin class to avoid import order issues\n try {\n // Use getPlugin with the class - this requires the class to be imported\n // For now, we'll use a duck-typing approach via the grid's plugin registry\n const grid = this.grid as any;\n if (grid?._plugins) {\n for (const plugin of grid._plugins) {\n if (plugin.name === 'selection') {\n return plugin as SelectionPluginInterface;\n }\n }\n }\n } catch {\n // Selection plugin not available\n }\n return undefined;\n }\n\n /**\n * Build text for a single cell by row/col index.\n */\n #buildCellText(rowIndex: number, colIndex: number): { text: string } | null {\n const rowData = this.rows[rowIndex] as Record<string, unknown> | undefined;\n if (!rowData) return null;\n\n const column = this.columns[colIndex];\n if (!column) return null;\n\n const value = rowData[column.field];\n const header = column.header || column.field;\n\n let text: string;\n if (this.config.includeHeaders) {\n const formattedValue = value == null ? '' : String(value);\n text = `${header}: ${formattedValue}`;\n } else {\n text = value == null ? '' : String(value);\n }\n\n return { text };\n }\n\n /**\n * Build text for a rectangular range of cells.\n */\n #buildRangeText(range: { startRow: number; startCol: number; endRow: number; endCol: number }): {\n text: string;\n rowCount: number;\n columnCount: number;\n } {\n const { startRow, startCol, endRow, endCol } = range;\n const minRow = Math.min(startRow, endRow);\n const maxRow = Math.max(startRow, endRow);\n const minCol = Math.min(startCol, endCol);\n const maxCol = Math.max(startCol, endCol);\n\n const delimiter = this.config.delimiter ?? '\\t';\n const newline = this.config.newline ?? '\\n';\n const lines: string[] = [];\n\n // Get columns in the range\n const rangeColumns = this.columns.slice(minCol, maxCol + 1);\n\n // Add header row if configured\n if (this.config.includeHeaders) {\n const headerCells = rangeColumns.map((c) => c.header || c.field);\n lines.push(headerCells.join(delimiter));\n }\n\n // Add data rows\n for (let r = minRow; r <= maxRow; r++) {\n const rowData = this.rows[r] as Record<string, unknown> | undefined;\n if (!rowData) continue;\n\n const cells = rangeColumns.map((col) => {\n const value = rowData[col.field];\n if (value == null) return '';\n if (value instanceof Date) return value.toISOString();\n return String(value);\n });\n lines.push(cells.join(delimiter));\n }\n\n return {\n text: lines.join(newline),\n rowCount: maxRow - minRow + 1,\n columnCount: maxCol - minCol + 1,\n };\n }\n\n /**\n * Build text for a single focused cell from DOM.\n * Used when selection plugin is not available or no rows are selected.\n */\n #buildSingleCellText(target: HTMLElement): { text: string; field: string; value: unknown } | null {\n // Find the cell element - cells use data-field-cache for the field name\n const cell = target.closest('[data-field-cache]') as HTMLElement | null;\n if (!cell) return null;\n\n const field = cell.dataset.fieldCache;\n if (!field) return null;\n\n // Get row index from data-row attribute on the cell\n const rowIndexStr = cell.dataset.row;\n if (!rowIndexStr) return null;\n\n const rowIndex = parseInt(rowIndexStr, 10);\n if (isNaN(rowIndex)) return null;\n\n const rowData = this.rows[rowIndex] as Record<string, unknown> | undefined;\n if (!rowData) return null;\n\n const value = rowData[field];\n const column = this.columns.find((c) => c.field === field);\n const header = column?.header || field;\n\n // Format the text based on includeHeaders config\n let text: string;\n if (this.config.includeHeaders) {\n // Format: \"{header}: {value}\"\n const formattedValue = value == null ? '' : String(value);\n text = `${header}: ${formattedValue}`;\n } else {\n // Just the value\n text = value == null ? '' : String(value);\n }\n\n return { text, field, value };\n }\n // #endregion\n\n // #region Public API\n\n /**\n * Copy currently selected rows to clipboard.\n * @returns The copied text\n */\n async copy(): Promise<string> {\n const selectionPlugin = this.#getSelectionPlugin();\n const indices = selectionPlugin?.getSelectedRows() ?? [];\n\n const text = buildClipboardText({\n rows: this.rows as unknown[],\n columns: [...this.columns],\n selectedIndices: indices,\n config: this.config,\n });\n\n await copyToClipboard(text);\n this.lastCopied = { text, timestamp: Date.now() };\n return text;\n }\n\n /**\n * Copy specific rows by index to clipboard.\n * @param indices - Array of row indices to copy\n * @returns The copied text\n */\n async copyRows(indices: number[]): Promise<string> {\n const text = buildClipboardText({\n rows: this.rows as unknown[],\n columns: [...this.columns],\n selectedIndices: indices,\n config: this.config,\n });\n\n await copyToClipboard(text);\n this.lastCopied = { text, timestamp: Date.now() };\n return text;\n }\n\n /**\n * Read and parse clipboard content.\n * @returns Parsed 2D array of cell values, or null if clipboard is empty\n */\n async paste(): Promise<string[][] | null> {\n const text = await readFromClipboard();\n if (!text) return null;\n return parseClipboardText(text, this.config);\n }\n\n /**\n * Get the last copied text and timestamp.\n * @returns The last copied info or null\n */\n getLastCopied(): { text: string; timestamp: number } | null {\n return this.lastCopied;\n }\n // #endregion\n}\n\n// #region Internal Types\n\n/**\n * Interface for SelectionPlugin methods we need.\n * This avoids circular imports while providing type safety.\n */\ninterface SelectionPluginInterface {\n name: string;\n /** Get selected row indices (row mode) */\n getSelectedRows(): number[];\n /** Get all selected cell ranges (range mode) */\n getRanges(): Array<{ from: { row: number; col: number }; to: { row: number; col: number } }>;\n /** Get selected cell (cell mode) */\n getSelectedCell(): { row: number; col: number } | null;\n}\n// #endregion\n\n// Re-export types\nexport type { ClipboardConfig, CopyDetail, PasteDetail } from './types';\n","/**\n * Column Virtualization Core Logic\n *\n * Pure functions for horizontal column virtualization operations.\n */\n\nimport type { ColumnConfig } from '../../core/types';\nimport type { ColumnVirtualizationViewport } from './types';\n\n/** Default column width when not specified */\nconst DEFAULT_COLUMN_WIDTH = 100;\n\n/**\n * Parse a column width value to pixels.\n * Handles number (px) and string formats.\n *\n * @param width - The width value from column config\n * @returns Width in pixels\n */\nexport function parseColumnWidth(width: string | number | undefined): number {\n if (width === undefined || width === null) {\n return DEFAULT_COLUMN_WIDTH;\n }\n\n if (typeof width === 'number') {\n return width;\n }\n\n // Handle string values - extract numeric part\n const numeric = parseFloat(width);\n if (!isNaN(numeric)) {\n return numeric;\n }\n\n return DEFAULT_COLUMN_WIDTH;\n}\n\n/**\n * Get array of column widths in pixels.\n *\n * @param columns - Column configurations\n * @returns Array of widths in pixels\n */\nexport function getColumnWidths(columns: readonly ColumnConfig[]): number[] {\n return columns.map((col) => parseColumnWidth(col.width));\n}\n\n/**\n * Compute cumulative left offsets for each column.\n *\n * @param columns - Column configurations\n * @returns Array of left offsets in pixels\n */\nexport function computeColumnOffsets(columns: readonly ColumnConfig[]): number[] {\n const offsets: number[] = [];\n let offset = 0;\n\n for (const col of columns) {\n offsets.push(offset);\n offset += parseColumnWidth(col.width);\n }\n\n return offsets;\n}\n\n/**\n * Compute total width of all columns.\n *\n * @param columns - Column configurations\n * @returns Total width in pixels\n */\nexport function computeTotalWidth(columns: readonly ColumnConfig[]): number {\n return columns.reduce((sum, col) => sum + parseColumnWidth(col.width), 0);\n}\n\n/**\n * Find the visible column range based on scroll position.\n * Uses binary search for efficient lookup in large column sets.\n *\n * @param scrollLeft - Current horizontal scroll position\n * @param viewportWidth - Width of the visible viewport\n * @param columnOffsets - Array of column left offsets\n * @param columnWidths - Array of column widths\n * @param overscan - Number of extra columns to render on each side\n * @returns Viewport information with visible column indices\n */\nexport function getVisibleColumnRange(\n scrollLeft: number,\n viewportWidth: number,\n columnOffsets: number[],\n columnWidths: number[],\n overscan: number\n): ColumnVirtualizationViewport {\n const columnCount = columnOffsets.length;\n\n if (columnCount === 0) {\n return { startCol: 0, endCol: 0, visibleColumns: [] };\n }\n\n // Binary search for first visible column\n let startCol = binarySearchFirstVisible(scrollLeft, columnOffsets, columnWidths);\n startCol = Math.max(0, startCol - overscan);\n\n // Find last visible column (without overscan first)\n const rightEdge = scrollLeft + viewportWidth;\n let endCol = startCol;\n\n for (let i = startCol; i < columnCount; i++) {\n if (columnOffsets[i] >= rightEdge) {\n endCol = i - 1;\n break;\n }\n endCol = i;\n }\n\n // Apply overscan to end (only once)\n endCol = Math.min(columnCount - 1, endCol + overscan);\n\n // Build array of visible column indices\n const visibleColumns: number[] = [];\n for (let i = startCol; i <= endCol; i++) {\n visibleColumns.push(i);\n }\n\n return { startCol, endCol, visibleColumns };\n}\n\n/**\n * Binary search to find the first column that is visible.\n *\n * @param scrollLeft - Current scroll position\n * @param columnOffsets - Array of column offsets\n * @param columnWidths - Array of column widths\n * @returns Index of first visible column\n */\nfunction binarySearchFirstVisible(scrollLeft: number, columnOffsets: number[], columnWidths: number[]): number {\n let low = 0;\n let high = columnOffsets.length - 1;\n\n while (low < high) {\n const mid = Math.floor((low + high) / 2);\n const colRight = columnOffsets[mid] + columnWidths[mid];\n\n if (colRight <= scrollLeft) {\n low = mid + 1;\n } else {\n high = mid;\n }\n }\n\n return low;\n}\n\n/**\n * Determine if column virtualization should be active.\n *\n * @param columnCount - Number of columns\n * @param threshold - Column count threshold\n * @param autoEnable - Whether auto-enable is configured\n * @returns True if virtualization should be active\n */\nexport function shouldVirtualize(columnCount: number, threshold: number, autoEnable: boolean): boolean {\n if (!autoEnable) return false;\n return columnCount > threshold;\n}\n","/**\n * Column Virtualization Plugin (Class-based)\n *\n * Provides horizontal column virtualization for grids with many columns.\n * Significantly improves rendering performance when dealing with >30 columns.\n */\n\nimport { BaseGridPlugin, ScrollEvent } from '../../core/plugin/base-plugin';\nimport type { ColumnConfig } from '../../core/types';\nimport {\n computeColumnOffsets,\n computeTotalWidth,\n getColumnWidths,\n getVisibleColumnRange,\n shouldVirtualize,\n} from './column-virtualization';\nimport type { ColumnVirtualizationConfig } from './types';\n\n/**\n * Column Virtualization Plugin for tbw-grid\n *\n * @example\n * ```ts\n * new ColumnVirtualizationPlugin({ threshold: 30, overscan: 3 })\n * ```\n */\nexport class ColumnVirtualizationPlugin extends BaseGridPlugin<ColumnVirtualizationConfig> {\n readonly name = 'columnVirtualization';\n override readonly version = '1.0.0';\n\n protected override get defaultConfig(): Partial<ColumnVirtualizationConfig> {\n return {\n autoEnable: true,\n threshold: 30,\n overscan: 3,\n };\n }\n\n // #region Internal State\n private isVirtualized = false;\n private startCol = 0;\n private endCol = 0;\n private scrollLeft = 0;\n private totalWidth = 0;\n private columnWidths: number[] = [];\n private columnOffsets: number[] = [];\n // #endregion\n\n // #region Lifecycle\n\n override attach(grid: import('../../core/plugin/base-plugin').GridElement): void {\n super.attach(grid);\n\n // Initialize state from current columns\n const columns = this.columns;\n this.columnWidths = getColumnWidths(columns);\n this.columnOffsets = computeColumnOffsets(columns);\n this.totalWidth = computeTotalWidth(columns);\n this.endCol = columns.length - 1;\n }\n\n override detach(): void {\n this.columnWidths = [];\n this.columnOffsets = [];\n this.isVirtualized = false;\n this.startCol = 0;\n this.endCol = 0;\n this.scrollLeft = 0;\n this.totalWidth = 0;\n }\n // #endregion\n\n // #region Hooks\n\n override processColumns(columns: readonly ColumnConfig[]): ColumnConfig[] {\n const isVirtualized = shouldVirtualize(columns.length, this.config.threshold ?? 30, this.config.autoEnable ?? true);\n\n // Update state with current column metrics\n this.isVirtualized = isVirtualized ?? false;\n this.columnWidths = getColumnWidths(columns);\n this.columnOffsets = computeColumnOffsets(columns);\n this.totalWidth = computeTotalWidth(columns);\n\n if (!isVirtualized) {\n this.startCol = 0;\n this.endCol = columns.length - 1;\n return [...columns];\n }\n\n // Get viewport width from grid element\n const viewportWidth = (this.grid as unknown as HTMLElement).clientWidth || 800;\n const viewport = getVisibleColumnRange(\n this.scrollLeft,\n viewportWidth,\n this.columnOffsets,\n this.columnWidths,\n this.config.overscan ?? 3,\n );\n\n this.startCol = viewport.startCol;\n this.endCol = viewport.endCol;\n\n // Return only visible columns\n return viewport.visibleColumns.map((i) => columns[i]);\n }\n\n override afterRender(): void {\n if (!this.isVirtualized) return;\n\n const shadowRoot = this.shadowRoot;\n if (!shadowRoot) return;\n\n // Apply left padding to offset scrolled-out columns\n const leftPadding = this.columnOffsets[this.startCol] ?? 0;\n\n const headerRow = shadowRoot.querySelector('.header-row');\n const bodyRows = shadowRoot.querySelectorAll('.data-grid-row');\n\n if (headerRow) {\n (headerRow as HTMLElement).style.paddingLeft = `${leftPadding}px`;\n }\n\n bodyRows.forEach((row) => {\n (row as HTMLElement).style.paddingLeft = `${leftPadding}px`;\n });\n\n // Set total width for horizontal scrolling on the rows container\n const rowsContainer = shadowRoot.querySelector('.rows-viewport .rows');\n if (rowsContainer) {\n (rowsContainer as HTMLElement).style.width = `${this.totalWidth}px`;\n }\n }\n\n override onScroll(event: ScrollEvent): void {\n if (!this.isVirtualized) return;\n\n // Check if horizontal scroll position changed significantly\n const scrollDelta = Math.abs(event.scrollLeft - this.scrollLeft);\n if (scrollDelta < 1) return;\n\n // Update scroll position\n this.scrollLeft = event.scrollLeft;\n\n // Recalculate visible columns and request re-render\n this.requestRender();\n }\n // #endregion\n\n // #region Public API\n\n /**\n * Check if column virtualization is currently active.\n */\n getIsVirtualized(): boolean {\n return this.isVirtualized;\n }\n\n /**\n * Get the current visible column range.\n */\n getVisibleColumnRange(): { start: number; end: number } {\n return { start: this.startCol, end: this.endCol };\n }\n\n /**\n * Scroll the grid to bring a specific column into view.\n * @param columnIndex - Index of the column to scroll to\n */\n scrollToColumn(columnIndex: number): void {\n const offset = this.columnOffsets[columnIndex] ?? 0;\n const gridEl = this.grid as unknown as HTMLElement;\n // Scroll the grid element itself (it's the scroll container)\n gridEl.scrollLeft = offset;\n }\n\n /**\n * Get the left offset for a specific column.\n * @param columnIndex - Index of the column\n */\n getColumnOffset(columnIndex: number): number {\n return this.columnOffsets[columnIndex] ?? 0;\n }\n\n /**\n * Get the total width of all columns.\n */\n getTotalWidth(): number {\n return this.totalWidth;\n }\n // #endregion\n}\n","/**\n * Context Menu Rendering Logic\n *\n * Pure functions for building and positioning context menus.\n */\n\nimport type { IconValue } from '../../core/types';\nimport { DEFAULT_GRID_ICONS } from '../../core/types';\nimport type { ContextMenuItem, ContextMenuParams } from './types';\n\n/**\n * Build the visible menu items by resolving dynamic items and filtering hidden ones.\n *\n * @param items - Menu items configuration (array or factory function)\n * @param params - Context menu parameters for evaluating dynamic properties\n * @returns Filtered array of visible menu items\n */\nexport function buildMenuItems(\n items: ContextMenuItem[] | ((params: ContextMenuParams) => ContextMenuItem[]),\n params: ContextMenuParams\n): ContextMenuItem[] {\n const menuItems = typeof items === 'function' ? items(params) : items;\n\n return menuItems.filter((item) => {\n if (item.hidden === true) return false;\n if (typeof item.hidden === 'function' && item.hidden(params)) return false;\n return true;\n });\n}\n\n/**\n * Check if a menu item is disabled.\n *\n * @param item - The menu item to check\n * @param params - Context menu parameters for evaluating dynamic disabled state\n * @returns True if the item is disabled\n */\nexport function isItemDisabled(item: ContextMenuItem, params: ContextMenuParams): boolean {\n if (item.disabled === true) return true;\n if (typeof item.disabled === 'function') return item.disabled(params);\n return false;\n}\n\n/**\n * Create the menu DOM element from a list of menu items.\n *\n * @param items - Array of menu items to render\n * @param params - Context menu parameters for evaluating dynamic properties\n * @param onAction - Callback when a menu item action is triggered\n * @param submenuArrow - Optional custom submenu arrow icon\n * @returns The created menu element\n */\nexport function createMenuElement(\n items: ContextMenuItem[],\n params: ContextMenuParams,\n onAction: (item: ContextMenuItem) => void,\n submenuArrow: IconValue = DEFAULT_GRID_ICONS.submenuArrow\n): HTMLElement {\n const menu = document.createElement('div');\n menu.className = 'tbw-context-menu';\n menu.setAttribute('role', 'menu');\n\n for (const item of items) {\n if (item.separator) {\n const separator = document.createElement('div');\n separator.className = 'tbw-context-menu-separator';\n separator.setAttribute('role', 'separator');\n menu.appendChild(separator);\n continue;\n }\n\n const menuItem = document.createElement('div');\n menuItem.className = 'tbw-context-menu-item';\n if (item.cssClass) menuItem.classList.add(item.cssClass);\n menuItem.setAttribute('role', 'menuitem');\n menuItem.setAttribute('data-id', item.id);\n\n const disabled = isItemDisabled(item, params);\n if (disabled) {\n menuItem.classList.add('disabled');\n menuItem.setAttribute('aria-disabled', 'true');\n }\n\n if (item.icon) {\n const icon = document.createElement('span');\n icon.className = 'tbw-context-menu-icon';\n icon.innerHTML = item.icon;\n menuItem.appendChild(icon);\n }\n\n const label = document.createElement('span');\n label.className = 'tbw-context-menu-label';\n label.textContent = item.name;\n menuItem.appendChild(label);\n\n if (item.shortcut) {\n const shortcut = document.createElement('span');\n shortcut.className = 'tbw-context-menu-shortcut';\n shortcut.textContent = item.shortcut;\n menuItem.appendChild(shortcut);\n }\n\n if (item.subMenu?.length) {\n const arrow = document.createElement('span');\n arrow.className = 'tbw-context-menu-arrow';\n // Use provided submenu arrow icon (string or HTMLElement)\n if (typeof submenuArrow === 'string') {\n arrow.innerHTML = submenuArrow;\n } else if (submenuArrow instanceof HTMLElement) {\n arrow.appendChild(submenuArrow.cloneNode(true));\n }\n menuItem.appendChild(arrow);\n\n // Add submenu on hover\n menuItem.addEventListener('mouseenter', () => {\n const existingSubMenu = menuItem.querySelector('.tbw-context-menu');\n if (existingSubMenu) return;\n if (!item.subMenu) return;\n\n const subMenuItems = buildMenuItems(item.subMenu, params);\n const subMenu = createMenuElement(subMenuItems, params, onAction, submenuArrow);\n subMenu.classList.add('tbw-context-submenu');\n subMenu.style.position = 'absolute';\n subMenu.style.left = '100%';\n subMenu.style.top = '0';\n menuItem.style.position = 'relative';\n menuItem.appendChild(subMenu);\n });\n\n menuItem.addEventListener('mouseleave', () => {\n const subMenu = menuItem.querySelector('.tbw-context-menu');\n if (subMenu) subMenu.remove();\n });\n }\n\n if (!disabled && item.action && !item.subMenu) {\n menuItem.addEventListener('click', (e) => {\n e.stopPropagation();\n onAction(item);\n });\n }\n\n menu.appendChild(menuItem);\n }\n\n return menu;\n}\n\n/**\n * Position the menu at the given viewport coordinates.\n * Menu is rendered in document.body with fixed positioning for top-layer behavior.\n *\n * @param menu - The menu element to position\n * @param x - Desired X coordinate (viewport)\n * @param y - Desired Y coordinate (viewport)\n */\nexport function positionMenu(menu: HTMLElement, x: number, y: number): void {\n // Use fixed positioning for top-layer behavior\n menu.style.position = 'fixed';\n menu.style.left = `${x}px`;\n menu.style.top = `${y}px`;\n menu.style.visibility = 'hidden';\n menu.style.zIndex = '10000';\n\n // Force layout to get dimensions\n const menuRect = menu.getBoundingClientRect();\n\n // Calculate visible area within viewport\n const viewportWidth = window.innerWidth;\n const viewportHeight = window.innerHeight;\n\n let left = x;\n let top = y;\n\n // Check if menu overflows right edge of viewport\n if (x + menuRect.width > viewportWidth) {\n left = x - menuRect.width;\n }\n // Check if menu overflows bottom edge of viewport\n if (y + menuRect.height > viewportHeight) {\n top = y - menuRect.height;\n }\n\n // Ensure we don't go negative\n left = Math.max(0, left);\n top = Math.max(0, top);\n\n menu.style.left = `${left}px`;\n menu.style.top = `${top}px`;\n menu.style.visibility = 'visible';\n}\n","/**\n * Context Menu Plugin (Class-based)\n *\n * Provides right-click context menu functionality for tbw-grid.\n * Supports custom menu items, submenus, icons, shortcuts, and dynamic item generation.\n */\n\nimport { BaseGridPlugin } from '../../core/plugin/base-plugin';\nimport contextMenuStyles from './context-menu.css?inline';\nimport { buildMenuItems, createMenuElement, positionMenu } from './menu';\nimport type { ContextMenuConfig, ContextMenuItem, ContextMenuParams } from './types';\n\n/** Global click handler reference for cleanup */\nlet globalClickHandler: ((e: Event) => void) | null = null;\n/** Global keydown handler reference for cleanup */\nlet globalKeydownHandler: ((e: KeyboardEvent) => void) | null = null;\n/** Global stylesheet for context menu (injected once) */\nlet globalStyleSheet: HTMLStyleElement | null = null;\n/** Reference count for instances using global handlers */\nlet globalHandlerRefCount = 0;\n\n/** Default menu items when none are configured */\nconst defaultItems: ContextMenuItem[] = [\n {\n id: 'copy',\n name: 'Copy',\n shortcut: 'Ctrl+C',\n action: (params) => {\n const grid = (params as ContextMenuParams & { grid?: { plugins?: { clipboard?: { copy?: () => void } } } }).grid;\n grid?.plugins?.clipboard?.copy?.();\n },\n },\n { separator: true, id: 'sep1', name: '' },\n {\n id: 'export-csv',\n name: 'Export CSV',\n action: (params) => {\n const grid = (params as ContextMenuParams & { grid?: { plugins?: { export?: { exportCsv?: () => void } } } })\n .grid;\n grid?.plugins?.export?.exportCsv?.();\n },\n },\n];\n\n/**\n * Context Menu Plugin for tbw-grid\n *\n * @example\n * ```ts\n * new ContextMenuPlugin({\n * enabled: true,\n * items: [\n * { id: 'edit', name: 'Edit', action: (params) => console.log('Edit', params) },\n * { separator: true, id: 'sep', name: '' },\n * { id: 'delete', name: 'Delete', action: (params) => console.log('Delete', params) },\n * ],\n * })\n * ```\n */\nexport class ContextMenuPlugin extends BaseGridPlugin<ContextMenuConfig> {\n readonly name = 'contextMenu';\n override readonly version = '1.0.0';\n\n protected override get defaultConfig(): Partial<ContextMenuConfig> {\n return {\n items: defaultItems,\n };\n }\n\n // #region Internal State\n private isOpen = false;\n private position = { x: 0, y: 0 };\n private params: ContextMenuParams | null = null;\n private menuElement: HTMLElement | null = null;\n // #endregion\n\n // #region Lifecycle\n\n override attach(grid: import('../../core/plugin/base-plugin').GridElement): void {\n super.attach(grid);\n this.installGlobalHandlers();\n globalHandlerRefCount++;\n }\n\n override detach(): void {\n if (this.menuElement) {\n this.menuElement.remove();\n this.menuElement = null;\n }\n this.isOpen = false;\n this.params = null;\n this.uninstallGlobalHandlers();\n }\n // #endregion\n\n // #region Private Methods\n\n private installGlobalHandlers(): void {\n // Inject global stylesheet for context menu (once)\n if (!globalStyleSheet && typeof document !== 'undefined') {\n globalStyleSheet = document.createElement('style');\n globalStyleSheet.id = 'tbw-context-menu-styles';\n globalStyleSheet.textContent = contextMenuStyles;\n document.head.appendChild(globalStyleSheet);\n }\n\n // Close menu on click outside\n if (!globalClickHandler) {\n globalClickHandler = () => {\n const menus = document.querySelectorAll('.tbw-context-menu');\n menus.forEach((menu) => menu.remove());\n };\n document.addEventListener('click', globalClickHandler);\n }\n\n // Close on escape\n if (!globalKeydownHandler) {\n globalKeydownHandler = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n const menus = document.querySelectorAll('.tbw-context-menu');\n menus.forEach((menu) => menu.remove());\n }\n };\n document.addEventListener('keydown', globalKeydownHandler);\n }\n }\n\n /**\n * Clean up global handlers when the last instance detaches.\n * Uses reference counting to ensure handlers persist while any grid uses the plugin.\n */\n private uninstallGlobalHandlers(): void {\n globalHandlerRefCount--;\n if (globalHandlerRefCount > 0) return;\n\n // Last instance - clean up all global resources\n if (globalClickHandler) {\n document.removeEventListener('click', globalClickHandler);\n globalClickHandler = null;\n }\n if (globalKeydownHandler) {\n document.removeEventListener('keydown', globalKeydownHandler);\n globalKeydownHandler = null;\n }\n if (globalStyleSheet) {\n globalStyleSheet.remove();\n globalStyleSheet = null;\n }\n }\n // #endregion\n\n // #region Hooks\n\n override afterRender(): void {\n const shadowRoot = this.shadowRoot;\n if (!shadowRoot) return;\n\n const container = shadowRoot.children[0];\n if (!container) return;\n\n // Check if handler already attached\n if (container.getAttribute('data-context-menu-bound') === 'true') return;\n container.setAttribute('data-context-menu-bound', 'true');\n\n container.addEventListener('contextmenu', (e: Event) => {\n const event = e as MouseEvent;\n event.preventDefault();\n\n const target = event.target as HTMLElement;\n const cell = target.closest('[data-row][data-col]');\n const header = target.closest('.header-cell');\n\n let params: ContextMenuParams;\n\n if (cell) {\n const rowIndex = parseInt(cell.getAttribute('data-row') ?? '-1', 10);\n const colIndex = parseInt(cell.getAttribute('data-col') ?? '-1', 10);\n const column = this.columns[colIndex];\n const row = this.rows[rowIndex];\n\n params = {\n row,\n rowIndex,\n column,\n columnIndex: colIndex,\n field: column?.field ?? '',\n value: row?.[column?.field as keyof typeof row] ?? null,\n isHeader: false,\n event,\n };\n } else if (header) {\n const colIndex = parseInt(header.getAttribute('data-col') ?? '-1', 10);\n const column = this.columns[colIndex];\n\n params = {\n row: null,\n rowIndex: -1,\n column,\n columnIndex: colIndex,\n field: column?.field ?? '',\n value: null,\n isHeader: true,\n event,\n };\n } else {\n return;\n }\n\n this.params = params;\n this.position = { x: event.clientX, y: event.clientY };\n\n const items = buildMenuItems(this.config.items ?? defaultItems, params);\n if (!items.length) return;\n\n if (this.menuElement) {\n this.menuElement.remove();\n }\n\n this.menuElement = createMenuElement(\n items,\n params,\n (item) => {\n if (item.action) {\n item.action(params);\n }\n this.menuElement?.remove();\n this.menuElement = null;\n this.isOpen = false;\n },\n this.gridIcons.submenuArrow,\n );\n\n document.body.appendChild(this.menuElement);\n positionMenu(this.menuElement, event.clientX, event.clientY);\n this.isOpen = true;\n\n this.emit('context-menu-open', { params, items });\n });\n }\n // #endregion\n\n // #region Public API\n\n /**\n * Programmatically show the context menu at the specified position.\n * @param x - X coordinate\n * @param y - Y coordinate\n * @param params - Partial context menu parameters\n */\n showMenu(x: number, y: number, params: Partial<ContextMenuParams>): void {\n const fullParams: ContextMenuParams = {\n row: params.row ?? null,\n rowIndex: params.rowIndex ?? -1,\n column: params.column ?? null,\n columnIndex: params.columnIndex ?? -1,\n field: params.field ?? '',\n value: params.value ?? null,\n isHeader: params.isHeader ?? false,\n event: params.event ?? new MouseEvent('contextmenu'),\n };\n\n const items = buildMenuItems(this.config.items ?? defaultItems, fullParams);\n\n if (this.menuElement) {\n this.menuElement.remove();\n }\n\n this.menuElement = createMenuElement(\n items,\n fullParams,\n (item) => {\n if (item.action) item.action(fullParams);\n this.menuElement?.remove();\n this.menuElement = null;\n this.isOpen = false;\n },\n this.gridIcons.submenuArrow,\n );\n\n document.body.appendChild(this.menuElement);\n positionMenu(this.menuElement, x, y);\n this.isOpen = true;\n }\n\n /**\n * Hide the context menu.\n */\n hideMenu(): void {\n if (this.menuElement) {\n this.menuElement.remove();\n this.menuElement = null;\n this.isOpen = false;\n }\n }\n\n /**\n * Check if the context menu is currently open.\n * @returns Whether the menu is open\n */\n isMenuOpen(): boolean {\n return this.isOpen;\n }\n // #endregion\n\n // Styles are injected globally via installGlobalHandlers() since menu renders in document.body\n}\n","/**\n * CSV Export Utilities\n *\n * Functions for building and downloading CSV content.\n */\n\nimport type { ColumnConfig } from '../../core/types';\nimport type { ExportParams } from './types';\n\n/** CSV export options */\nexport interface CsvOptions {\n /** Field delimiter (default: ',') */\n delimiter?: string;\n /** Line separator (default: '\\n') */\n newline?: string;\n /** Whether to quote strings containing special characters (default: true) */\n quoteStrings?: boolean;\n /** Add UTF-8 BOM for Excel compatibility (default: false) */\n bom?: boolean;\n}\n\n/**\n * Format a value for CSV output.\n * Handles null, Date, objects, and strings with special characters.\n */\nexport function formatCsvValue(value: any, quote = true): string {\n if (value == null) return '';\n if (value instanceof Date) return value.toISOString();\n if (typeof value === 'object') return JSON.stringify(value);\n\n const str = String(value);\n\n // Quote if contains special characters (comma, quote, newline)\n if (quote && (str.includes(',') || str.includes('\"') || str.includes('\\n') || str.includes('\\r'))) {\n return `\"${str.replace(/\"/g, '\"\"')}\"`;\n }\n\n return str;\n}\n\n/**\n * Build CSV content from rows and columns.\n */\nexport function buildCsv(rows: any[], columns: ColumnConfig[], params: ExportParams, options: CsvOptions = {}): string {\n const delimiter = options.delimiter ?? ',';\n const newline = options.newline ?? '\\n';\n const lines: string[] = [];\n\n // UTF-8 BOM for Excel compatibility\n const bom = options.bom ? '\\uFEFF' : '';\n\n // Build header row\n if (params.includeHeaders !== false) {\n const headerRow = columns.map((col) => {\n const header = col.header || col.field;\n const processed = params.processHeader ? params.processHeader(header, col.field) : header;\n return formatCsvValue(processed);\n });\n lines.push(headerRow.join(delimiter));\n }\n\n // Build data rows\n for (const row of rows) {\n const cells = columns.map((col) => {\n let value = row[col.field];\n if (params.processCell) {\n value = params.processCell(value, col.field, row);\n }\n return formatCsvValue(value);\n });\n lines.push(cells.join(delimiter));\n }\n\n return bom + lines.join(newline);\n}\n\n/**\n * Download a Blob as a file.\n */\nexport function downloadBlob(blob: Blob, fileName: string): void {\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.download = fileName;\n link.style.display = 'none';\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n URL.revokeObjectURL(url);\n}\n\n/**\n * Download CSV content as a file.\n */\nexport function downloadCsv(content: string, fileName: string): void {\n const blob = new Blob([content], { type: 'text/csv;charset=utf-8;' });\n downloadBlob(blob, fileName);\n}\n","/**\n * Excel Export Utilities\n *\n * Simple Excel XML format export (no external dependencies).\n * Produces XML Spreadsheet 2003 format which opens in Excel.\n */\n\nimport type { ColumnConfig } from '../../core/types';\nimport type { ExportParams } from './types';\nimport { downloadBlob } from './csv';\n\n/**\n * Escape XML special characters.\n */\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n}\n\n/**\n * Build Excel XML content from rows and columns.\n * Uses XML Spreadsheet 2003 format for broad compatibility.\n */\nexport function buildExcelXml(rows: any[], columns: ColumnConfig[], params: ExportParams): string {\n let xml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<?mso-application progid=\"Excel.Sheet\"?>\n<Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\"\n xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\">\n<Worksheet ss:Name=\"Sheet1\">\n<Table>`;\n\n // Build header row\n if (params.includeHeaders !== false) {\n xml += '\\n<Row>';\n for (const col of columns) {\n const header = col.header || col.field;\n const processed = params.processHeader ? params.processHeader(header, col.field) : header;\n xml += `<Cell><Data ss:Type=\"String\">${escapeXml(processed)}</Data></Cell>`;\n }\n xml += '</Row>';\n }\n\n // Build data rows\n for (const row of rows) {\n xml += '\\n<Row>';\n for (const col of columns) {\n let value = row[col.field];\n if (params.processCell) {\n value = params.processCell(value, col.field, row);\n }\n\n // Determine cell type based on value\n let type: 'Number' | 'String' | 'DateTime' = 'String';\n let displayValue = '';\n\n if (value == null) {\n displayValue = '';\n } else if (typeof value === 'number' && !isNaN(value)) {\n type = 'Number';\n displayValue = String(value);\n } else if (value instanceof Date) {\n type = 'DateTime';\n displayValue = value.toISOString();\n } else {\n displayValue = escapeXml(String(value));\n }\n\n xml += `<Cell><Data ss:Type=\"${type}\">${displayValue}</Data></Cell>`;\n }\n xml += '</Row>';\n }\n\n xml += '\\n</Table>\\n</Worksheet>\\n</Workbook>';\n return xml;\n}\n\n/**\n * Download Excel XML content as a file.\n */\nexport function downloadExcel(content: string, fileName: string): void {\n const finalName = fileName.endsWith('.xls') ? fileName : `${fileName}.xls`;\n const blob = new Blob([content], {\n type: 'application/vnd.ms-excel;charset=utf-8;',\n });\n downloadBlob(blob, finalName);\n}\n","/**\n * Export Plugin (Class-based)\n *\n * Provides data export functionality for tbw-grid.\n * Supports CSV, Excel (XML), and JSON formats.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { BaseGridPlugin } from '../../core/plugin/base-plugin';\nimport type { ColumnConfig } from '../../core/types';\nimport { buildCsv, downloadBlob, downloadCsv } from './csv';\nimport { buildExcelXml, downloadExcel } from './excel';\nimport type { ExportCompleteDetail, ExportConfig, ExportFormat, ExportParams } from './types';\n\n/** Selection plugin state interface for type safety */\ninterface SelectionPluginState {\n selected: Set<number>;\n}\n\n/**\n * Export Plugin for tbw-grid\n *\n * @example\n * ```ts\n * new ExportPlugin({\n * enabled: true,\n * fileName: 'my-data',\n * includeHeaders: true,\n * onlyVisible: true,\n * })\n * ```\n */\nexport class ExportPlugin extends BaseGridPlugin<ExportConfig> {\n readonly name = 'export';\n override readonly version = '1.0.0';\n\n protected override get defaultConfig(): Partial<ExportConfig> {\n return {\n fileName: 'export',\n includeHeaders: true,\n onlyVisible: true,\n onlySelected: false,\n };\n }\n\n // #region Internal State\n private isExportingFlag = false;\n private lastExportInfo: { format: ExportFormat; timestamp: Date } | null = null;\n // #endregion\n\n // #region Private Methods\n\n private performExport(format: ExportFormat, params?: Partial<ExportParams>): void {\n const config = this.config;\n\n // Build full params with defaults\n const fullParams: ExportParams = {\n format,\n fileName: params?.fileName ?? config.fileName ?? 'export',\n includeHeaders: params?.includeHeaders ?? config.includeHeaders,\n processCell: params?.processCell,\n processHeader: params?.processHeader,\n columns: params?.columns,\n rowIndices: params?.rowIndices,\n };\n\n // Get columns to export\n let columns = [...this.columns] as ColumnConfig[];\n if (config.onlyVisible) {\n columns = columns.filter((c) => !c.hidden && !c.field.startsWith('__'));\n }\n if (params?.columns) {\n const colSet = new Set(params.columns);\n columns = columns.filter((c) => colSet.has(c.field));\n }\n\n // Get rows to export\n let rows = [...this.rows] as any[];\n if (config.onlySelected) {\n const selectionState = this.getSelectionState();\n if (selectionState?.selected?.size) {\n const sortedIndices = [...selectionState.selected].sort((a, b) => a - b);\n rows = sortedIndices.map((i) => this.rows[i]).filter(Boolean);\n }\n }\n if (params?.rowIndices) {\n rows = params.rowIndices.map((i) => this.rows[i]).filter(Boolean);\n }\n\n this.isExportingFlag = true;\n let fileName = fullParams.fileName!;\n\n try {\n switch (format) {\n case 'csv': {\n const content = buildCsv(rows, columns, fullParams, { bom: true });\n fileName = fileName.endsWith('.csv') ? fileName : `${fileName}.csv`;\n downloadCsv(content, fileName);\n break;\n }\n\n case 'excel': {\n const content = buildExcelXml(rows, columns, fullParams);\n fileName = fileName.endsWith('.xls') ? fileName : `${fileName}.xls`;\n downloadExcel(content, fileName);\n break;\n }\n\n case 'json': {\n const jsonData = rows.map((row) => {\n const obj: Record<string, any> = {};\n for (const col of columns) {\n let value = row[col.field];\n if (fullParams.processCell) {\n value = fullParams.processCell(value, col.field, row);\n }\n obj[col.field] = value;\n }\n return obj;\n });\n const content = JSON.stringify(jsonData, null, 2);\n fileName = fileName.endsWith('.json') ? fileName : `${fileName}.json`;\n const blob = new Blob([content], { type: 'application/json' });\n downloadBlob(blob, fileName);\n break;\n }\n }\n\n this.lastExportInfo = { format, timestamp: new Date() };\n\n this.emit<ExportCompleteDetail>('export-complete', {\n format,\n fileName,\n rowCount: rows.length,\n columnCount: columns.length,\n });\n } finally {\n this.isExportingFlag = false;\n }\n }\n\n private getSelectionState(): SelectionPluginState | null {\n try {\n const grid = this.grid as any;\n return grid?.getPluginState?.('selection') ?? null;\n } catch {\n return null;\n }\n }\n // #endregion\n\n // #region Public API\n\n /**\n * Export data to CSV format.\n * @param params - Optional export parameters\n */\n exportCsv(params?: Partial<ExportParams>): void {\n this.performExport('csv', params);\n }\n\n /**\n * Export data to Excel format (XML Spreadsheet).\n * @param params - Optional export parameters\n */\n exportExcel(params?: Partial<ExportParams>): void {\n this.performExport('excel', params);\n }\n\n /**\n * Export data to JSON format.\n * @param params - Optional export parameters\n */\n exportJson(params?: Partial<ExportParams>): void {\n this.performExport('json', params);\n }\n\n /**\n * Check if an export is currently in progress.\n * @returns Whether export is in progress\n */\n isExporting(): boolean {\n return this.isExportingFlag;\n }\n\n /**\n * Get information about the last export.\n * @returns Export info or null if no export has occurred\n */\n getLastExport(): { format: ExportFormat; timestamp: Date } | null {\n return this.lastExportInfo;\n }\n // #endregion\n}\n","/**\n * Row Virtualization Core Logic\n *\n * Pure functions for vertical row virtualization operations.\n * Manages which rows are rendered based on scroll position and viewport size.\n */\n\n/** Result of computing a virtual window */\nexport interface VirtualWindow {\n /** First row index to render (inclusive) */\n start: number;\n /** Last row index to render (exclusive) */\n end: number;\n /** Pixel offset to apply to the rows container (translateY) */\n offsetY: number;\n /** Total height of the scrollable content */\n totalHeight: number;\n}\n\n/** Parameters for computing the virtual window */\nexport interface VirtualWindowParams {\n /** Total number of rows */\n totalRows: number;\n /** Height of the viewport in pixels */\n viewportHeight: number;\n /** Current scroll top position */\n scrollTop: number;\n /** Height of each row in pixels */\n rowHeight: number;\n /** Number of extra rows to render above/below viewport */\n overscan: number;\n /** Previous scroll position for velocity calculation */\n prevScrollTop?: number;\n}\n\n/**\n * Compute the virtual row window based on scroll position and viewport.\n * Uses directional overscan - renders more rows in the scroll direction.\n *\n * @param params - Parameters for computing the window\n * @returns VirtualWindow with start/end indices and transforms\n */\nexport function computeVirtualWindow(params: VirtualWindowParams): VirtualWindow {\n const { totalRows, viewportHeight, scrollTop, rowHeight, overscan } = params;\n\n // Simple approach: render a large fixed window centered on current position\n // This is more predictable than velocity-based sizing\n const visibleRows = Math.ceil(viewportHeight / rowHeight);\n\n // Render overscan rows in each direction (total window = visible + 2*overscan)\n let start = Math.floor(scrollTop / rowHeight) - overscan;\n if (start < 0) start = 0;\n\n let end = start + visibleRows + overscan * 2;\n if (end > totalRows) end = totalRows;\n\n // Ensure start is adjusted if we hit the end\n if (end === totalRows && start > 0) {\n start = Math.max(0, end - visibleRows - overscan * 2);\n }\n\n return {\n start,\n end,\n offsetY: start * rowHeight,\n totalHeight: totalRows * rowHeight,\n };\n}\n\n/**\n * Determine if virtualization should be bypassed for small datasets.\n * When there are very few items, the overhead of virtualization isn't worth it.\n *\n * @param totalRows - Total number of items\n * @param threshold - Bypass threshold (skip virtualization if totalRows <= threshold)\n * @returns True if virtualization should be bypassed\n */\nexport function shouldBypassVirtualization(totalRows: number, threshold: number): boolean {\n return totalRows <= threshold;\n}\n\n/**\n * Compute the row index from a Y pixel position.\n *\n * @param y - Y position in pixels (relative to content top)\n * @param rowHeight - Height of each row\n * @returns Row index at that position\n */\nexport function getRowIndexFromY(y: number, rowHeight: number): number {\n return Math.floor(y / rowHeight);\n}\n\n/**\n * Compute the Y offset for a given row index.\n *\n * @param rowIndex - Row index\n * @param rowHeight - Height of each row\n * @returns Y position in pixels\n */\nexport function getRowOffsetY(rowIndex: number, rowHeight: number): number {\n return rowIndex * rowHeight;\n}\n","/**\n * Filter Model Core Logic\n *\n * Pure functions for filtering operations.\n */\n\nimport type { FilterModel } from './types';\n\n/**\n * Check if a single row matches a filter condition.\n *\n * @param row - The row data object\n * @param filter - The filter to apply\n * @param caseSensitive - Whether text comparisons are case sensitive\n * @returns True if the row matches the filter\n */\nexport function matchesFilter(row: Record<string, unknown>, filter: FilterModel, caseSensitive = false): boolean {\n const rawValue = row[filter.field];\n\n // Handle blank/notBlank first - these work on null/undefined/empty\n if (filter.operator === 'blank') {\n return rawValue == null || rawValue === '';\n }\n if (filter.operator === 'notBlank') {\n return rawValue != null && rawValue !== '';\n }\n\n // Null/undefined values don't match other filters\n if (rawValue == null) return false;\n\n // Prepare values for comparison\n const stringValue = String(rawValue);\n const compareValue = caseSensitive ? stringValue : stringValue.toLowerCase();\n const filterValue = caseSensitive ? String(filter.value) : String(filter.value).toLowerCase();\n\n switch (filter.operator) {\n // Text operators\n case 'contains':\n return compareValue.includes(filterValue);\n\n case 'notContains':\n return !compareValue.includes(filterValue);\n\n case 'equals':\n return compareValue === filterValue;\n\n case 'notEquals':\n return compareValue !== filterValue;\n\n case 'startsWith':\n return compareValue.startsWith(filterValue);\n\n case 'endsWith':\n return compareValue.endsWith(filterValue);\n\n // Number/Date operators (use raw numeric values)\n case 'lessThan':\n return Number(rawValue) < Number(filter.value);\n\n case 'lessThanOrEqual':\n return Number(rawValue) <= Number(filter.value);\n\n case 'greaterThan':\n return Number(rawValue) > Number(filter.value);\n\n case 'greaterThanOrEqual':\n return Number(rawValue) >= Number(filter.value);\n\n case 'between':\n return Number(rawValue) >= Number(filter.value) && Number(rawValue) <= Number(filter.valueTo);\n\n // Set operators\n case 'in':\n return Array.isArray(filter.value) && filter.value.includes(rawValue);\n\n case 'notIn':\n return Array.isArray(filter.value) && !filter.value.includes(rawValue);\n\n default:\n return true;\n }\n}\n\n/**\n * Filter rows based on multiple filter conditions (AND logic).\n * All filters must match for a row to be included.\n *\n * @param rows - The rows to filter\n * @param filters - Array of filters to apply\n * @param caseSensitive - Whether text comparisons are case sensitive\n * @returns Filtered rows\n */\nexport function filterRows<T extends Record<string, unknown>>(\n rows: T[],\n filters: FilterModel[],\n caseSensitive = false\n): T[] {\n if (!filters.length) return rows;\n return rows.filter((row) => filters.every((f) => matchesFilter(row, f, caseSensitive)));\n}\n\n/**\n * Compute a cache key for a set of filters.\n * Used for memoization of filter results.\n *\n * @param filters - Array of filters\n * @returns Stable string key for the filter set\n */\nexport function computeFilterCacheKey(filters: FilterModel[]): string {\n return JSON.stringify(\n filters.map((f) => ({\n field: f.field,\n operator: f.operator,\n value: f.value,\n valueTo: f.valueTo,\n }))\n );\n}\n\n/**\n * Extract unique values from a field across all rows.\n * Useful for populating \"set\" filter dropdowns.\n *\n * @param rows - The rows to extract values from\n * @param field - The field name\n * @returns Sorted array of unique non-null values\n */\nexport function getUniqueValues<T extends Record<string, unknown>>(rows: T[], field: string): unknown[] {\n const values = new Set<unknown>();\n for (const row of rows) {\n const value = row[field];\n if (value != null) {\n values.add(value);\n }\n }\n return [...values].sort((a, b) => {\n // Handle mixed types gracefully\n if (typeof a === 'number' && typeof b === 'number') {\n return a - b;\n }\n return String(a).localeCompare(String(b));\n });\n}\n","/**\n * Filtering Plugin (Class-based)\n *\n * Provides comprehensive filtering functionality for tbw-grid.\n * Supports text, number, date, set, and boolean filters with caching.\n * Includes UI with filter buttons in headers and dropdown filter panels.\n */\n\nimport { computeVirtualWindow, shouldBypassVirtualization } from '../../core/internal/virtualization';\nimport { BaseGridPlugin, type GridElement } from '../../core/plugin/base-plugin';\nimport type { ColumnConfig, ColumnState } from '../../core/types';\nimport { computeFilterCacheKey, filterRows, getUniqueValues } from './filter-model';\nimport styles from './filtering.css?inline';\nimport filterPanelStyles from './FilteringPlugin.css?inline';\nimport type { FilterChangeDetail, FilterConfig, FilterModel, FilterPanelParams } from './types';\n\n/**\n * Filtering Plugin for tbw-grid\n *\n * @example\n * ```ts\n * new FilteringPlugin({ enabled: true, debounceMs: 300 })\n * ```\n */\nexport class FilteringPlugin extends BaseGridPlugin<FilterConfig> {\n readonly name = 'filtering';\n override readonly version = '1.0.0';\n\n protected override get defaultConfig(): Partial<FilterConfig> {\n return {\n debounceMs: 300,\n caseSensitive: false,\n trimInput: true,\n useWorker: true,\n };\n }\n\n // #region Internal State\n private filters: Map<string, FilterModel> = new Map();\n private cachedResult: unknown[] | null = null;\n private cacheKey: string | null = null;\n private openPanelField: string | null = null;\n private panelElement: HTMLElement | null = null;\n private searchText: Map<string, string> = new Map();\n private excludedValues: Map<string, Set<unknown>> = new Map();\n private panelAbortController: AbortController | null = null; // For panel-scoped listeners\n private globalStylesInjected = false;\n\n // Virtualization constants for filter value list\n private static readonly LIST_ITEM_HEIGHT = 28;\n private static readonly LIST_OVERSCAN = 3;\n private static readonly LIST_BYPASS_THRESHOLD = 50; // Don't virtualize if < 50 items\n // #endregion\n\n // #region Lifecycle\n\n override attach(grid: GridElement): void {\n super.attach(grid);\n this.injectGlobalStyles();\n }\n\n override detach(): void {\n this.filters.clear();\n this.cachedResult = null;\n this.cacheKey = null;\n this.openPanelField = null;\n if (this.panelElement) {\n this.panelElement.remove();\n this.panelElement = null;\n }\n this.searchText.clear();\n this.excludedValues.clear();\n // Abort panel-scoped listeners (document click handler, etc.)\n this.panelAbortController?.abort();\n this.panelAbortController = null;\n }\n // #endregion\n\n // #region Hooks\n\n override processRows(rows: readonly unknown[]): unknown[] {\n const filterList = [...this.filters.values()];\n if (!filterList.length) return [...rows];\n\n // If using async filterHandler, processRows becomes a passthrough\n // Actual filtering happens in applyFiltersAsync and rows are set directly on grid\n if (this.config.filterHandler) {\n // Return cached result if available (set by async handler)\n if (this.cachedResult) return this.cachedResult;\n // Otherwise return rows as-is (filtering happens async)\n return [...rows];\n }\n\n // Check cache\n const newCacheKey = computeFilterCacheKey(filterList);\n if (this.cacheKey === newCacheKey && this.cachedResult) {\n return this.cachedResult;\n }\n\n // Filter rows synchronously (worker support can be added later)\n const result = filterRows([...rows] as Record<string, unknown>[], filterList, this.config.caseSensitive);\n\n // Update cache\n this.cachedResult = result;\n this.cacheKey = newCacheKey;\n\n return result;\n }\n\n override afterRender(): void {\n const shadowRoot = this.shadowRoot;\n if (!shadowRoot) return;\n\n // Find all header cells (using part attribute, not class)\n const headerCells = shadowRoot.querySelectorAll('[part~=\"header-cell\"]');\n headerCells.forEach((cell) => {\n const colIndex = cell.getAttribute('data-col');\n if (colIndex === null) return;\n\n // Use visibleColumns since data-col is the index within _visibleColumns\n const col = this.visibleColumns[parseInt(colIndex, 10)] as ColumnConfig;\n if (!col || col.filterable === false) return;\n\n const field = col.field;\n if (!field) return;\n\n const hasFilter = this.filters.has(field);\n\n // Check if button already exists\n let filterBtn = cell.querySelector('.tbw-filter-btn') as HTMLElement | null;\n\n if (filterBtn) {\n // Update active state of existing button\n filterBtn.classList.toggle('active', hasFilter);\n (cell as HTMLElement).classList.toggle('filtered', hasFilter);\n return;\n }\n\n // Create filter button\n filterBtn = document.createElement('button');\n filterBtn.className = 'tbw-filter-btn';\n filterBtn.setAttribute('aria-label', `Filter ${col.header ?? field}`);\n filterBtn.innerHTML = `<svg viewBox=\"0 0 16 16\" width=\"12\" height=\"12\"><path fill=\"currentColor\" d=\"M6 10.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5z\"/></svg>`;\n\n // Mark button as active if filter exists\n if (hasFilter) {\n filterBtn.classList.add('active');\n (cell as HTMLElement).classList.add('filtered');\n }\n\n filterBtn.addEventListener('click', (e) => {\n e.stopPropagation();\n this.toggleFilterPanel(field, col, filterBtn!);\n });\n\n // Append to header cell\n cell.appendChild(filterBtn);\n });\n }\n // #endregion\n\n // #region Public API\n\n /**\n * Set a filter on a specific field.\n * Pass null to remove the filter.\n */\n setFilter(field: string, filter: Omit<FilterModel, 'field'> | null): void {\n if (filter === null) {\n this.filters.delete(field);\n this.excludedValues.delete(field);\n } else {\n this.filters.set(field, { ...filter, field });\n // Sync excludedValues for set filters so the panel reflects correct state\n if (filter.type === 'set' && filter.operator === 'notIn' && Array.isArray(filter.value)) {\n this.excludedValues.set(field, new Set(filter.value));\n } else if (filter.type === 'set') {\n // Other set operators may have different semantics; clear for safety\n this.excludedValues.delete(field);\n }\n }\n // Invalidate cache\n this.cachedResult = null;\n this.cacheKey = null;\n\n this.emit<FilterChangeDetail>('filter-change', {\n filters: [...this.filters.values()],\n filteredRowCount: 0, // Will be accurate after processRows\n });\n this.requestRender();\n }\n\n /**\n * Get the current filter for a field.\n */\n getFilter(field: string): FilterModel | undefined {\n return this.filters.get(field);\n }\n\n /**\n * Get all active filters.\n */\n getFilters(): FilterModel[] {\n return [...this.filters.values()];\n }\n\n /**\n * Alias for getFilters() to match functional API naming.\n */\n getFilterModel(): FilterModel[] {\n return this.getFilters();\n }\n\n /**\n * Set filters from an array (replaces all existing filters).\n */\n setFilterModel(filters: FilterModel[]): void {\n this.filters.clear();\n this.excludedValues.clear();\n for (const filter of filters) {\n this.filters.set(filter.field, filter);\n // Sync excludedValues for set filters so the panel reflects correct state\n if (filter.type === 'set' && filter.operator === 'notIn' && Array.isArray(filter.value)) {\n this.excludedValues.set(filter.field, new Set(filter.value));\n }\n }\n this.cachedResult = null;\n this.cacheKey = null;\n\n this.emit<FilterChangeDetail>('filter-change', {\n filters: [...this.filters.values()],\n filteredRowCount: 0,\n });\n this.requestRender();\n }\n\n /**\n * Clear all filters.\n */\n clearAllFilters(): void {\n this.filters.clear();\n this.excludedValues.clear();\n this.searchText.clear();\n\n this.applyFiltersInternal();\n }\n\n /**\n * Clear filter for a specific field.\n */\n clearFieldFilter(field: string): void {\n this.filters.delete(field);\n this.excludedValues.delete(field);\n this.searchText.delete(field);\n\n this.applyFiltersInternal();\n }\n\n /**\n * Check if a field has an active filter.\n */\n isFieldFiltered(field: string): boolean {\n return this.filters.has(field);\n }\n\n /**\n * Get the count of filtered rows (from cache).\n */\n getFilteredRowCount(): number {\n return this.cachedResult?.length ?? this.rows.length;\n }\n\n /**\n * Get all active filters (alias for getFilters).\n */\n getActiveFilters(): FilterModel[] {\n return this.getFilters();\n }\n\n /**\n * Get unique values for a field (for set filter dropdowns).\n * Uses sourceRows to include all values regardless of current filter.\n */\n getUniqueValues(field: string): unknown[] {\n return getUniqueValues(this.sourceRows as Record<string, unknown>[], field);\n }\n // #endregion\n\n // #region Private Methods\n\n /**\n * Inject global styles for filter panel (rendered in document.body)\n */\n private injectGlobalStyles(): void {\n if (this.globalStylesInjected) return;\n if (document.getElementById('tbw-filter-panel-styles')) {\n this.globalStylesInjected = true;\n return;\n }\n const style = document.createElement('style');\n style.id = 'tbw-filter-panel-styles';\n style.textContent = filterPanelStyles;\n document.head.appendChild(style);\n this.globalStylesInjected = true;\n }\n\n /**\n * Toggle the filter panel for a field\n */\n private toggleFilterPanel(field: string, column: ColumnConfig, buttonEl: HTMLElement): void {\n // Close if already open\n if (this.openPanelField === field) {\n this.closeFilterPanel();\n return;\n }\n\n // Close any existing panel\n this.closeFilterPanel();\n\n // Create panel\n const panel = document.createElement('div');\n panel.className = 'tbw-filter-panel';\n this.panelElement = panel;\n this.openPanelField = field;\n\n // If using async valuesHandler, show loading state and fetch values\n if (this.config.valuesHandler) {\n panel.innerHTML = '<div class=\"tbw-filter-loading\">Loading...</div>';\n document.body.appendChild(panel);\n this.positionPanel(panel, buttonEl);\n this.setupPanelCloseHandler(panel, buttonEl);\n\n this.config.valuesHandler(field, column).then((values) => {\n // Check if panel is still open for this field\n if (this.openPanelField !== field || !this.panelElement) return;\n panel.innerHTML = '';\n this.renderPanelContent(field, column, panel, values);\n });\n return;\n }\n\n // Sync path: get unique values from local rows\n const uniqueValues = getUniqueValues(this.sourceRows as Record<string, unknown>[], field);\n this.renderPanelContent(field, column, panel, uniqueValues);\n\n // Position and append to body\n document.body.appendChild(panel);\n this.positionPanel(panel, buttonEl);\n this.setupPanelCloseHandler(panel, buttonEl);\n }\n\n /**\n * Render filter panel content with given values\n */\n private renderPanelContent(field: string, column: ColumnConfig, panel: HTMLElement, uniqueValues: unknown[]): void {\n // Get current excluded values or initialize empty\n let excludedSet = this.excludedValues.get(field);\n if (!excludedSet) {\n excludedSet = new Set();\n this.excludedValues.set(field, excludedSet);\n }\n\n // Get current search text\n const currentSearchText = this.searchText.get(field) ?? '';\n\n // Create panel params for custom renderer\n const params: FilterPanelParams = {\n field,\n column,\n uniqueValues,\n excludedValues: excludedSet,\n searchText: currentSearchText,\n applySetFilter: (excluded: unknown[]) => {\n this.applySetFilter(field, excluded);\n this.closeFilterPanel();\n },\n applyTextFilter: (operator, value, valueTo) => {\n this.applyTextFilter(field, operator, value, valueTo);\n this.closeFilterPanel();\n },\n clearFilter: () => {\n this.clearFieldFilter(field);\n this.closeFilterPanel();\n },\n closePanel: () => this.closeFilterPanel(),\n };\n\n // Use custom renderer or default\n // Custom renderer can return undefined to fall back to default panel for specific columns\n let usedCustomRenderer = false;\n if (this.config.filterPanelRenderer) {\n this.config.filterPanelRenderer(panel, params);\n // If renderer added content to panel, it handled rendering\n usedCustomRenderer = panel.children.length > 0;\n }\n if (!usedCustomRenderer) {\n this.renderDefaultFilterPanel(panel, params, uniqueValues, excludedSet);\n }\n }\n\n /**\n * Setup click-outside handler to close the panel\n */\n private setupPanelCloseHandler(panel: HTMLElement, buttonEl: HTMLElement): void {\n // Create abort controller for panel-scoped listeners\n // This allows cleanup when panel closes OR when grid disconnects\n this.panelAbortController = new AbortController();\n\n // Add global click handler to close on outside click\n // Defer to next tick to avoid immediate close from the click that opened the panel\n setTimeout(() => {\n document.addEventListener(\n 'click',\n (e: MouseEvent) => {\n if (!panel.contains(e.target as Node) && e.target !== buttonEl) {\n this.closeFilterPanel();\n }\n },\n { signal: this.panelAbortController?.signal },\n );\n }, 0);\n }\n\n /**\n * Close the filter panel\n */\n private closeFilterPanel(): void {\n if (this.panelElement) {\n this.panelElement.remove();\n this.panelElement = null;\n }\n this.openPanelField = null;\n // Abort panel-scoped listeners (document click handler)\n this.panelAbortController?.abort();\n this.panelAbortController = null;\n }\n\n /**\n * Position the panel below the button\n */\n private positionPanel(panel: HTMLElement, buttonEl: HTMLElement): void {\n const rect = buttonEl.getBoundingClientRect();\n panel.style.position = 'fixed';\n panel.style.top = `${rect.bottom + 4}px`;\n panel.style.left = `${rect.left}px`;\n\n // Adjust if overflows right edge\n requestAnimationFrame(() => {\n const panelRect = panel.getBoundingClientRect();\n if (panelRect.right > window.innerWidth - 8) {\n panel.style.left = `${window.innerWidth - panelRect.width - 8}px`;\n }\n // Adjust if overflows bottom\n if (panelRect.bottom > window.innerHeight - 8) {\n panel.style.top = `${rect.top - panelRect.height - 4}px`;\n }\n });\n }\n\n /**\n * Render the default filter panel content\n */\n private renderDefaultFilterPanel(\n panel: HTMLElement,\n params: FilterPanelParams,\n uniqueValues: unknown[],\n excludedValues: Set<unknown>,\n ): void {\n const { field } = params;\n\n // Search input\n const searchContainer = document.createElement('div');\n searchContainer.className = 'tbw-filter-search';\n\n const searchInput = document.createElement('input');\n searchInput.type = 'text';\n searchInput.placeholder = 'Search...';\n searchInput.className = 'tbw-filter-search-input';\n searchInput.value = this.searchText.get(field) ?? '';\n searchContainer.appendChild(searchInput);\n panel.appendChild(searchContainer);\n\n // Select All tristate checkbox\n const actionsRow = document.createElement('div');\n actionsRow.className = 'tbw-filter-actions';\n\n const selectAllLabel = document.createElement('label');\n selectAllLabel.className = 'tbw-filter-value-item';\n selectAllLabel.style.padding = '0';\n selectAllLabel.style.margin = '0';\n\n const selectAllCheckbox = document.createElement('input');\n selectAllCheckbox.type = 'checkbox';\n selectAllCheckbox.className = 'tbw-filter-checkbox';\n\n const selectAllText = document.createElement('span');\n selectAllText.textContent = 'Select All';\n\n selectAllLabel.appendChild(selectAllCheckbox);\n selectAllLabel.appendChild(selectAllText);\n actionsRow.appendChild(selectAllLabel);\n\n // Update tristate checkbox based on checkState\n const updateSelectAllState = () => {\n const values = [...checkState.values()];\n const allChecked = values.every((v) => v);\n const noneChecked = values.every((v) => !v);\n\n selectAllCheckbox.checked = allChecked;\n selectAllCheckbox.indeterminate = !allChecked && !noneChecked;\n };\n\n // Toggle all on click\n selectAllCheckbox.addEventListener('change', () => {\n const newState = selectAllCheckbox.checked;\n for (const key of checkState.keys()) {\n checkState.set(key, newState);\n }\n updateSelectAllState();\n renderVisibleItems();\n });\n\n panel.appendChild(actionsRow);\n\n // Values container with virtualization support\n const valuesContainer = document.createElement('div');\n valuesContainer.className = 'tbw-filter-values';\n\n // Spacer for virtual height\n const spacer = document.createElement('div');\n spacer.className = 'tbw-filter-values-spacer';\n valuesContainer.appendChild(spacer);\n\n // Content container positioned absolutely\n const contentContainer = document.createElement('div');\n contentContainer.className = 'tbw-filter-values-content';\n valuesContainer.appendChild(contentContainer);\n\n // Track current check state for values (persists across virtualizations)\n const checkState = new Map<string, boolean>();\n uniqueValues.forEach((value) => {\n const key = value == null ? '__null__' : String(value);\n checkState.set(key, !excludedValues.has(value));\n });\n\n // Initialize select all state\n updateSelectAllState();\n\n // Filtered values cache\n let filteredValues: unknown[] = [];\n\n // Create a single checkbox item element\n const createItem = (value: unknown, index: number): HTMLElement => {\n const strValue = value == null ? '(Blank)' : String(value);\n const key = value == null ? '__null__' : String(value);\n\n const item = document.createElement('label');\n item.className = 'tbw-filter-value-item';\n item.style.position = 'absolute';\n item.style.top = `${index * FilteringPlugin.LIST_ITEM_HEIGHT}px`;\n item.style.left = '0';\n item.style.right = '0';\n item.style.height = `${FilteringPlugin.LIST_ITEM_HEIGHT}px`;\n item.style.boxSizing = 'border-box';\n\n const checkbox = document.createElement('input');\n checkbox.type = 'checkbox';\n checkbox.className = 'tbw-filter-checkbox';\n checkbox.checked = checkState.get(key) ?? true;\n checkbox.dataset.value = key;\n\n // Sync check state on change and update tristate checkbox\n checkbox.addEventListener('change', () => {\n checkState.set(key, checkbox.checked);\n updateSelectAllState();\n });\n\n const label = document.createElement('span');\n label.textContent = strValue;\n\n item.appendChild(checkbox);\n item.appendChild(label);\n return item;\n };\n\n // Render visible items using virtualization\n const renderVisibleItems = () => {\n const totalItems = filteredValues.length;\n const viewportHeight = valuesContainer.clientHeight;\n const scrollTop = valuesContainer.scrollTop;\n\n // Set total height for scrollbar\n spacer.style.height = `${totalItems * FilteringPlugin.LIST_ITEM_HEIGHT}px`;\n\n // Bypass virtualization for small lists\n if (shouldBypassVirtualization(totalItems, FilteringPlugin.LIST_BYPASS_THRESHOLD / 3)) {\n contentContainer.innerHTML = '';\n contentContainer.style.transform = 'translateY(0px)';\n filteredValues.forEach((value, idx) => {\n contentContainer.appendChild(createItem(value, idx));\n });\n return;\n }\n\n // Use computeVirtualWindow for real-scroll virtualization\n const window = computeVirtualWindow({\n totalRows: totalItems,\n viewportHeight,\n scrollTop,\n rowHeight: FilteringPlugin.LIST_ITEM_HEIGHT,\n overscan: FilteringPlugin.LIST_OVERSCAN,\n });\n\n // Position content container\n contentContainer.style.transform = `translateY(${window.offsetY}px)`;\n\n // Clear and render visible items\n contentContainer.innerHTML = '';\n for (let i = window.start; i < window.end; i++) {\n contentContainer.appendChild(createItem(filteredValues[i], i - window.start));\n }\n };\n\n // Filter and re-render values\n const renderValues = (filterText: string) => {\n const lowerFilter = filterText.toLowerCase();\n\n // Filter the unique values\n filteredValues = uniqueValues.filter((value) => {\n const strValue = value == null ? '(Blank)' : String(value);\n return !filterText || strValue.toLowerCase().includes(lowerFilter);\n });\n\n if (filteredValues.length === 0) {\n spacer.style.height = '0px';\n contentContainer.innerHTML = '';\n const noMatch = document.createElement('div');\n noMatch.className = 'tbw-filter-no-match';\n noMatch.textContent = 'No matching values';\n contentContainer.appendChild(noMatch);\n return;\n }\n\n renderVisibleItems();\n };\n\n // Scroll handler for virtualization\n valuesContainer.addEventListener(\n 'scroll',\n () => {\n if (filteredValues.length > 0) {\n renderVisibleItems();\n }\n },\n { passive: true },\n );\n\n renderValues(searchInput.value);\n panel.appendChild(valuesContainer);\n\n // Debounced search\n let debounceTimer: ReturnType<typeof setTimeout>;\n searchInput.addEventListener('input', () => {\n clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => {\n this.searchText.set(field, searchInput.value);\n renderValues(searchInput.value);\n }, this.config.debounceMs ?? 150);\n });\n\n // Apply/Clear buttons\n const buttonRow = document.createElement('div');\n buttonRow.className = 'tbw-filter-buttons';\n\n const applyBtn = document.createElement('button');\n applyBtn.className = 'tbw-filter-apply-btn';\n applyBtn.textContent = 'Apply';\n applyBtn.addEventListener('click', () => {\n // Read from checkState map (works with virtualization)\n const excluded: unknown[] = [];\n for (const [key, isChecked] of checkState) {\n if (!isChecked) {\n if (key === '__null__') {\n excluded.push(null);\n } else {\n // Try to match original value type\n const original = uniqueValues.find((v) => String(v) === key);\n excluded.push(original !== undefined ? original : key);\n }\n }\n }\n params.applySetFilter(excluded);\n });\n buttonRow.appendChild(applyBtn);\n\n const clearBtn = document.createElement('button');\n clearBtn.className = 'tbw-filter-clear-btn';\n clearBtn.textContent = 'Clear Filter';\n clearBtn.addEventListener('click', () => {\n params.clearFilter();\n });\n buttonRow.appendChild(clearBtn);\n\n panel.appendChild(buttonRow);\n }\n\n /**\n * Apply a set filter (exclude values)\n */\n private applySetFilter(field: string, excluded: unknown[]): void {\n // Store excluded values\n this.excludedValues.set(field, new Set(excluded));\n\n if (excluded.length === 0) {\n // No exclusions = no filter\n this.filters.delete(field);\n } else {\n // Create \"notIn\" filter\n this.filters.set(field, {\n field,\n type: 'set',\n operator: 'notIn',\n value: excluded,\n });\n }\n\n this.applyFiltersInternal();\n }\n\n /**\n * Apply a text filter\n */\n private applyTextFilter(field: string, operator: FilterModel['operator'], value: string, valueTo?: string): void {\n this.filters.set(field, {\n field,\n type: 'text',\n operator,\n value,\n valueTo,\n });\n\n this.applyFiltersInternal();\n }\n\n /**\n * Internal method to apply filters (sync or async based on config)\n */\n private applyFiltersInternal(): void {\n this.cachedResult = null;\n this.cacheKey = null;\n\n const filterList = [...this.filters.values()];\n\n // If using async filterHandler, delegate to server\n if (this.config.filterHandler) {\n const gridEl = this.grid as HTMLElement;\n gridEl.setAttribute('aria-busy', 'true');\n\n const result = this.config.filterHandler(filterList, this.sourceRows as unknown[]);\n\n // Handle async or sync result\n const handleResult = (rows: unknown[]) => {\n gridEl.removeAttribute('aria-busy');\n this.cachedResult = rows;\n\n // Update grid rows directly for async filtering\n (this.grid as unknown as { rows: unknown[] }).rows = rows;\n\n this.emit<FilterChangeDetail>('filter-change', {\n filters: filterList,\n filteredRowCount: rows.length,\n });\n\n // Trigger afterRender to update filter button active state\n this.requestRender();\n };\n\n if (result && typeof (result as Promise<unknown[]>).then === 'function') {\n (result as Promise<unknown[]>).then(handleResult);\n } else {\n handleResult(result as unknown[]);\n }\n return;\n }\n\n // Sync path: emit event and re-render (processRows will handle filtering)\n this.emit<FilterChangeDetail>('filter-change', {\n filters: filterList,\n filteredRowCount: 0,\n });\n this.requestRender();\n }\n // #endregion\n\n // #region Column State Hooks\n\n /**\n * Return filter state for a column if it has an active filter.\n */\n override getColumnState(field: string): Partial<ColumnState> | undefined {\n const filterModel = this.filters.get(field);\n if (!filterModel) return undefined;\n\n return {\n filter: {\n type: filterModel.type,\n operator: filterModel.operator,\n value: filterModel.value,\n valueTo: filterModel.valueTo,\n },\n };\n }\n\n /**\n * Apply filter state from column state.\n */\n override applyColumnState(field: string, state: ColumnState): void {\n // Only process if the column has filter state\n if (!state.filter) {\n this.filters.delete(field);\n return;\n }\n\n // Reconstruct the FilterModel from the stored state\n const filterModel: FilterModel = {\n field,\n type: state.filter.type,\n operator: state.filter.operator as FilterModel['operator'],\n value: state.filter.value,\n valueTo: state.filter.valueTo,\n };\n\n this.filters.set(field, filterModel);\n // Invalidate cache so filter is reapplied\n this.cachedResult = null;\n this.cacheKey = null;\n }\n // #endregion\n\n // #region Styles\n\n override readonly styles = styles;\n // #endregion\n}\n","/**\n * Column Groups Core Logic\n *\n * Pure functions for computing and managing column header groups.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { ColumnConfig } from '../../core/types';\nimport type { ColumnGroup, ColumnGroupInternal } from './types';\n\n/**\n * Compute column groups from column configuration.\n * Handles explicit groups (via column.group) and creates implicit groups for ungrouped columns.\n *\n * @param columns - Array of column configurations\n * @returns Array of column groups, or empty if no meaningful groups\n */\nexport function computeColumnGroups<T>(columns: ColumnConfig<T>[]): ColumnGroup<T>[] {\n if (!columns.length) return [];\n\n const explicitMap = new Map<string, ColumnGroupInternal<T>>();\n const groupsOrdered: ColumnGroupInternal<T>[] = [];\n\n // Helper to push unnamed implicit group for a run of ungrouped columns\n const pushImplicit = (startIdx: number, cols: ColumnConfig<T>[]) => {\n if (!cols.length) return;\n // Merge with previous implicit group if adjacent to reduce noise\n const prev = groupsOrdered[groupsOrdered.length - 1];\n if (prev && prev.implicit && prev.firstIndex + prev.columns.length === startIdx) {\n prev.columns.push(...cols);\n return;\n }\n groupsOrdered.push({\n id: '__implicit__' + startIdx,\n label: undefined,\n columns: cols,\n firstIndex: startIdx,\n implicit: true,\n });\n };\n\n let run: ColumnConfig<T>[] = [];\n let runStart = 0;\n\n columns.forEach((col, idx) => {\n const g: any = (col as any).group;\n if (!g) {\n if (run.length === 0) runStart = idx;\n run.push(col);\n return;\n }\n // Close any pending implicit run\n if (run.length) {\n pushImplicit(runStart, run.slice());\n run = [];\n }\n const id = typeof g === 'string' ? g : g.id;\n let group = explicitMap.get(id);\n if (!group) {\n group = {\n id,\n label: typeof g === 'string' ? undefined : g.label,\n columns: [],\n firstIndex: idx,\n };\n explicitMap.set(id, group);\n groupsOrdered.push(group);\n }\n group.columns.push(col);\n });\n\n // Trailing implicit run\n if (run.length) pushImplicit(runStart, run);\n\n // If we only have a single implicit group covering all columns, treat as no groups\n if (\n groupsOrdered.length === 1 &&\n groupsOrdered[0].implicit &&\n groupsOrdered[0].columns.length === columns.length\n ) {\n return [];\n }\n\n return groupsOrdered as ColumnGroup<T>[];\n}\n\n/**\n * Apply CSS classes to header cells based on their group membership.\n *\n * @param headerRowEl - The header row element\n * @param groups - The computed column groups\n * @param columns - The column configurations\n */\nexport function applyGroupedHeaderCellClasses(\n headerRowEl: HTMLElement | null,\n groups: ColumnGroup[],\n columns: ColumnConfig<any>[]\n): void {\n if (!groups.length || !headerRowEl) return;\n\n const fieldToGroup = new Map<string, string>();\n for (const g of groups) {\n for (const c of g.columns) {\n if ((c as any)?.field) {\n fieldToGroup.set((c as any).field, g.id);\n }\n }\n }\n\n const headerCells = Array.from(headerRowEl.querySelectorAll('.cell[data-field]')) as HTMLElement[];\n headerCells.forEach((cell) => {\n const f = cell.getAttribute('data-field') || '';\n const gid = fieldToGroup.get(f);\n if (gid) {\n cell.classList.add('grouped');\n if (!cell.getAttribute('data-group')) {\n cell.setAttribute('data-group', gid);\n }\n }\n });\n\n // Mark group end cells for styling\n for (const g of groups) {\n const last = g.columns[g.columns.length - 1];\n const cell = headerCells.find((c) => c.getAttribute('data-field') === (last as any).field);\n if (cell) cell.classList.add('group-end');\n }\n}\n\n/**\n * Build the group header row element.\n *\n * @param groups - The computed column groups\n * @param columns - The column configurations\n * @returns The group header row element, or null if no groups\n */\nexport function buildGroupHeaderRow(\n groups: ColumnGroup[],\n columns: ColumnConfig<any>[]\n): HTMLElement | null {\n if (groups.length === 0) return null;\n\n const groupRow = document.createElement('div');\n groupRow.className = 'header-group-row';\n groupRow.setAttribute('role', 'row');\n\n for (const g of groups) {\n const startIndex =\n g.firstIndex != null\n ? g.firstIndex\n : columns.findIndex((c) => (g.columns as any[]).includes(c));\n\n const isImplicit = String(g.id).startsWith('__implicit__');\n const label = isImplicit ? '' : g.label || g.id;\n\n const cell = document.createElement('div');\n cell.className = 'cell header-group-cell';\n if (isImplicit) cell.classList.add('implicit-group');\n cell.setAttribute('data-group', String(g.id));\n cell.style.gridColumn = `${startIndex + 1} / span ${g.columns.length}`;\n cell.textContent = label;\n groupRow.appendChild(cell);\n }\n\n return groupRow;\n}\n\n/**\n * Check if any columns have group configuration.\n *\n * @param columns - The column configurations\n * @returns True if at least one column has a group\n */\nexport function hasColumnGroups(columns: ColumnConfig<any>[]): boolean {\n return columns.some((col) => (col as any).group != null);\n}\n\n/**\n * Get group ID for a specific column.\n *\n * @param column - The column configuration\n * @returns The group ID, or undefined if not grouped\n */\nexport function getColumnGroupId(column: ColumnConfig<any>): string | undefined {\n const g = (column as any).group;\n if (!g) return undefined;\n return typeof g === 'string' ? g : g.id;\n}\n","/**\n * Column Groups Plugin (Class-based)\n *\n * Enables multi-level column header grouping.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { BaseGridPlugin } from '../../core/plugin/base-plugin';\nimport type { ColumnConfig } from '../../core/types';\nimport {\n applyGroupedHeaderCellClasses,\n buildGroupHeaderRow,\n computeColumnGroups,\n hasColumnGroups,\n} from './grouping-columns';\nimport styles from './grouping-columns.css?inline';\nimport type { ColumnGroup, GroupingColumnsConfig } from './types';\n\n/**\n * Column Groups Plugin for tbw-grid\n *\n * @example\n * ```ts\n * new GroupingColumnsPlugin({\n * enabled: true,\n * showGroupBorders: true,\n * })\n * ```\n */\nexport class GroupingColumnsPlugin extends BaseGridPlugin<GroupingColumnsConfig> {\n readonly name = 'groupingColumns';\n override readonly version = '1.0.0';\n\n protected override get defaultConfig(): Partial<GroupingColumnsConfig> {\n return {\n showGroupBorders: true,\n };\n }\n\n // #region Internal State\n private groups: ColumnGroup[] = [];\n private isActive = false;\n // #endregion\n\n // #region Lifecycle\n\n override detach(): void {\n this.groups = [];\n this.isActive = false;\n }\n // #endregion\n\n // #region Static Detection\n\n /**\n * Auto-detect column groups from column configuration.\n */\n static detect(rows: readonly any[], config: any): boolean {\n const columns = config?.columns;\n if (!Array.isArray(columns)) return false;\n return hasColumnGroups(columns);\n }\n // #endregion\n\n // #region Hooks\n\n override processColumns(columns: readonly ColumnConfig[]): ColumnConfig[] {\n // Compute groups from column definitions\n const groups = computeColumnGroups(columns as ColumnConfig[]);\n\n if (groups.length === 0) {\n this.isActive = false;\n this.groups = [];\n return [...columns];\n }\n\n this.isActive = true;\n this.groups = groups;\n\n // Return columns unchanged - the afterRender hook will add the group header\n return [...columns];\n }\n\n override afterRender(): void {\n if (!this.isActive || this.groups.length === 0) {\n // Remove any existing group header\n const header = this.shadowRoot?.querySelector('.header');\n const existingGroupRow = header?.querySelector('.header-group-row');\n if (existingGroupRow) existingGroupRow.remove();\n return;\n }\n\n const header = this.shadowRoot?.querySelector('.header');\n if (!header) return;\n\n // Remove existing group row if present\n const existingGroupRow = header.querySelector('.header-group-row');\n if (existingGroupRow) existingGroupRow.remove();\n\n // Build and insert group header row\n const groupRow = buildGroupHeaderRow(this.groups, this.columns as ColumnConfig[]);\n if (groupRow) {\n // Toggle border visibility class\n groupRow.classList.toggle('no-borders', !this.config.showGroupBorders);\n\n const headerRow = header.querySelector('.header-row');\n if (headerRow) {\n header.insertBefore(groupRow, headerRow);\n } else {\n header.appendChild(groupRow);\n }\n }\n\n // Apply classes to header cells\n const headerRow = header.querySelector('.header-row') as HTMLElement;\n if (headerRow) {\n // Toggle border visibility on header cells\n headerRow.classList.toggle('no-group-borders', !this.config.showGroupBorders);\n applyGroupedHeaderCellClasses(headerRow, this.groups, this.columns as ColumnConfig[]);\n }\n }\n // #endregion\n\n // #region Public API\n\n /**\n * Check if column groups are active.\n * @returns Whether grouping is active\n */\n isGroupingActive(): boolean {\n return this.isActive;\n }\n\n /**\n * Get the computed column groups.\n * @returns Array of column groups\n */\n getGroups(): ColumnGroup[] {\n return this.groups;\n }\n\n /**\n * Get columns in a specific group.\n * @param groupId - The group ID to find\n * @returns Array of columns in the group\n */\n getGroupColumns(groupId: string): ColumnConfig[] {\n const group = this.groups.find((g) => g.id === groupId);\n return group ? group.columns : [];\n }\n\n /**\n * Refresh column groups (recompute from current columns).\n */\n refresh(): void {\n this.requestRender();\n }\n // #endregion\n\n // #region Styles\n\n override readonly styles = styles;\n // #endregion\n}\n","/**\n * Row Grouping Core Logic\n *\n * Pure functions for building grouped row models and aggregations.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { RenderRow, RowGroupingConfig } from './types';\n\n// Re-export aggregator functions from core for backward compatibility\nexport { getAggregator, listAggregators, registerAggregator, runAggregator } from '../../core/internal/aggregators';\n\ninterface GroupNode {\n key: string; // composite key\n value: any;\n depth: number;\n rows: any[];\n children: Map<string, GroupNode>;\n parent?: GroupNode;\n}\n\ninterface BuildGroupingArgs {\n rows: any[];\n config: RowGroupingConfig;\n expanded: Set<string>;\n}\n\n/**\n * Build a flattened grouping projection (collapsed by default).\n * Returns empty array when groupOn not configured or all rows ungrouped.\n *\n * @param args - The grouping arguments\n * @returns Flattened array of render rows (groups + data rows)\n */\nexport function buildGroupedRowModel({ rows, config, expanded }: BuildGroupingArgs): RenderRow[] {\n const groupOn = config.groupOn;\n if (typeof groupOn !== 'function') {\n return [];\n }\n\n const root: GroupNode = { key: '__root__', value: null, depth: -1, rows: [], children: new Map() };\n\n // Build tree structure\n rows.forEach((r) => {\n let path: any = groupOn(r);\n if (path == null || path === false) path = ['__ungrouped__'];\n else if (!Array.isArray(path)) path = [path];\n\n let parent = root;\n path.forEach((rawVal: any, depthIdx: number) => {\n const seg = rawVal == null ? '∅' : String(rawVal);\n const composite = parent.key === '__root__' ? seg : parent.key + '||' + seg;\n let node = parent.children.get(seg);\n if (!node) {\n node = { key: composite, value: rawVal, depth: depthIdx, rows: [], children: new Map(), parent };\n parent.children.set(seg, node);\n }\n parent = node;\n });\n parent.rows.push(r);\n });\n\n // All ungrouped? treat as no grouping\n if (root.children.size === 1 && root.children.has('__ungrouped__')) {\n const only = root.children.get('__ungrouped__')!;\n if (only.rows.length === rows.length) return [];\n }\n\n // Flatten tree to array\n const flat: RenderRow[] = [];\n const visit = (node: GroupNode) => {\n if (node === root) {\n node.children.forEach((c) => visit(c));\n return;\n }\n\n const isExpanded = expanded.has(node.key);\n flat.push({\n kind: 'group',\n key: node.key,\n value: node.value,\n depth: node.depth,\n rows: node.rows,\n expanded: isExpanded,\n });\n\n if (isExpanded) {\n if (node.children.size) {\n node.children.forEach((c) => visit(c));\n } else {\n node.rows.forEach((r) => flat.push({ kind: 'data', row: r, rowIndex: rows.indexOf(r) }));\n }\n }\n };\n visit(root);\n\n return flat;\n}\n\n/**\n * Toggle expansion state for a group key.\n *\n * @param expandedKeys - Current set of expanded keys\n * @param key - The group key to toggle\n * @returns New set with toggled state\n */\nexport function toggleGroupExpansion(expandedKeys: Set<string>, key: string): Set<string> {\n const newSet = new Set(expandedKeys);\n if (newSet.has(key)) {\n newSet.delete(key);\n } else {\n newSet.add(key);\n }\n return newSet;\n}\n\n/**\n * Expand all groups.\n *\n * @param rows - The flattened render rows\n * @returns Set of all group keys\n */\nexport function expandAllGroups(rows: RenderRow[]): Set<string> {\n const keys = new Set<string>();\n for (const row of rows) {\n if (row.kind === 'group') {\n keys.add(row.key);\n }\n }\n return keys;\n}\n\n/**\n * Collapse all groups.\n *\n * @returns Empty set\n */\nexport function collapseAllGroups(): Set<string> {\n return new Set();\n}\n\n/**\n * Get all group keys from a flattened model.\n *\n * @param rows - The flattened render rows\n * @returns Array of group keys\n */\nexport function getGroupKeys(rows: RenderRow[]): string[] {\n return rows.filter((r) => r.kind === 'group').map((r) => (r as any).key);\n}\n\n/**\n * Count total rows in a group (including nested groups).\n *\n * @param groupRow - The group row\n * @returns Total row count\n */\nexport function getGroupRowCount(groupRow: RenderRow): number {\n if (groupRow.kind !== 'group') return 0;\n return groupRow.rows.length;\n}\n","/**\n * Row Grouping Plugin (Class-based)\n *\n * Enables hierarchical row grouping with expand/collapse and aggregations.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { BaseGridPlugin, CellClickEvent } from '../../core/plugin/base-plugin';\nimport type { GridConfig } from '../../core/types';\nimport {\n buildGroupedRowModel,\n collapseAllGroups,\n expandAllGroups,\n getGroupRowCount,\n runAggregator,\n toggleGroupExpansion,\n} from './grouping-rows';\nimport styles from './grouping-rows.css?inline';\nimport type {\n ExpandCollapseAnimation,\n GroupingRowsConfig,\n GroupRowModelItem,\n GroupToggleDetail,\n RenderRow,\n} from './types';\n\ninterface GridWithConfig {\n effectiveConfig?: GridConfig;\n}\n\n/**\n * Group state information returned by getGroupState()\n */\nexport interface GroupState {\n /** Whether grouping is currently active */\n isActive: boolean;\n /** Number of expanded groups */\n expandedCount: number;\n /** Total number of groups */\n totalGroups: number;\n /** Array of expanded group keys */\n expandedKeys: string[];\n}\n\n/**\n * Row Grouping Plugin for tbw-grid\n *\n * @example\n * ```ts\n * new GroupingRowsPlugin({\n * enabled: true,\n * groupOn: (row) => row.category,\n * defaultExpanded: false,\n * showRowCount: true,\n * })\n * ```\n */\nexport class GroupingRowsPlugin extends BaseGridPlugin<GroupingRowsConfig> {\n readonly name = 'groupingRows';\n override readonly version = '1.0.0';\n\n protected override get defaultConfig(): Partial<GroupingRowsConfig> {\n return {\n defaultExpanded: false,\n showRowCount: true,\n indentWidth: 20,\n aggregators: {},\n animation: 'slide',\n };\n }\n\n // #region Internal State\n private expandedKeys: Set<string> = new Set();\n private flattenedRows: RenderRow[] = [];\n private isActive = false;\n private previousVisibleKeys = new Set<string>();\n private keysToAnimate = new Set<string>();\n // #endregion\n\n // #region Animation\n\n private get animationStyle(): ExpandCollapseAnimation {\n const gridEl = this.grid as unknown as GridWithConfig;\n const mode = gridEl.effectiveConfig?.animation?.mode ?? 'reduced-motion';\n\n if (mode === false || mode === 'off') return false;\n if (mode !== true && mode !== 'on') {\n const host = this.shadowRoot?.host as HTMLElement | undefined;\n if (host && getComputedStyle(host).getPropertyValue('--tbw-animation-enabled').trim() === '0') {\n return false;\n }\n }\n return this.config.animation ?? 'slide';\n }\n\n // #endregion\n\n // #region Lifecycle\n\n override detach(): void {\n this.expandedKeys.clear();\n this.flattenedRows = [];\n this.isActive = false;\n this.previousVisibleKeys.clear();\n this.keysToAnimate.clear();\n }\n // #endregion\n\n // #region Hooks\n\n /**\n * Auto-detect grouping configuration from grid config.\n * Called by plugin system to determine if plugin should activate.\n */\n static detect(rows: readonly any[], config: any): boolean {\n return typeof config?.groupOn === 'function' || typeof config?.enableRowGrouping === 'boolean';\n }\n\n override processRows(rows: readonly any[]): any[] {\n const config = this.config;\n\n // Check if grouping is configured\n if (typeof config.groupOn !== 'function') {\n this.isActive = false;\n this.flattenedRows = [];\n return [...rows];\n }\n\n // Build grouped model\n const grouped = buildGroupedRowModel({\n rows: rows as any[],\n config: config,\n expanded: this.expandedKeys,\n });\n\n // If no grouping produced, return original rows\n if (grouped.length === 0) {\n this.isActive = false;\n this.flattenedRows = [];\n return [...rows];\n }\n\n this.isActive = true;\n this.flattenedRows = grouped;\n\n // Track which data rows are newly visible (for animation)\n this.keysToAnimate.clear();\n const currentVisibleKeys = new Set<string>();\n grouped.forEach((item, idx) => {\n if (item.kind === 'data') {\n const key = `data-${idx}`;\n currentVisibleKeys.add(key);\n if (!this.previousVisibleKeys.has(key)) {\n this.keysToAnimate.add(key);\n }\n }\n });\n this.previousVisibleKeys = currentVisibleKeys;\n\n // Return flattened rows for rendering\n // The grid will need to handle group rows specially\n return grouped.map((item) => {\n if (item.kind === 'group') {\n return {\n __isGroupRow: true,\n __groupKey: item.key,\n __groupValue: item.value,\n __groupDepth: item.depth,\n __groupRows: item.rows,\n __groupExpanded: item.expanded,\n __groupRowCount: getGroupRowCount(item),\n };\n }\n return item.row;\n });\n }\n\n override onCellClick(event: CellClickEvent): boolean | void {\n const row = event.row;\n\n // Check if this is a group row toggle\n if (row?.__isGroupRow) {\n const target = event.originalEvent.target as HTMLElement;\n if (target?.closest('.group-toggle')) {\n this.toggle(row.__groupKey);\n return true; // Prevent default\n }\n }\n }\n\n /**\n * Render a row. Returns true if we handled the row (group row), false otherwise.\n */\n override renderRow(row: any, rowEl: HTMLElement, _rowIndex: number): boolean {\n // Only handle group rows\n if (!row?.__isGroupRow) {\n return false;\n }\n\n const config = this.config;\n\n // If a custom renderer is provided, use it\n if (config.groupRowRenderer) {\n const toggleExpand = () => {\n this.toggle(row.__groupKey);\n };\n\n const result = config.groupRowRenderer({\n key: row.__groupKey,\n value: row.__groupValue,\n depth: row.__groupDepth,\n rows: row.__groupRows,\n expanded: row.__groupExpanded,\n toggleExpand,\n });\n\n if (result) {\n rowEl.className = 'group-row';\n (rowEl as any).__isCustomRow = true; // Mark for proper class reset on recycle\n rowEl.setAttribute('data-group-depth', String(row.__groupDepth));\n if (typeof result === 'string') {\n rowEl.innerHTML = result;\n } else {\n rowEl.innerHTML = '';\n rowEl.appendChild(result);\n }\n return true;\n }\n }\n\n // Helper to toggle expansion\n const handleToggle = () => {\n this.toggle(row.__groupKey);\n };\n\n // Default group row rendering\n rowEl.className = 'group-row';\n (rowEl as any).__isCustomRow = true; // Mark for proper class reset on recycle\n rowEl.setAttribute('data-group-depth', String(row.__groupDepth));\n rowEl.setAttribute('role', 'row');\n rowEl.setAttribute('aria-expanded', String(row.__groupExpanded));\n rowEl.style.paddingLeft = `${(row.__groupDepth || 0) * (config.indentWidth ?? 20)}px`;\n rowEl.innerHTML = '';\n\n const isFullWidth = config.fullWidth !== false; // default true\n\n if (isFullWidth) {\n this.renderFullWidthGroupRow(row, rowEl, handleToggle);\n } else {\n this.renderPerColumnGroupRow(row, rowEl, handleToggle);\n }\n\n return true;\n }\n\n override afterRender(): void {\n const style = this.animationStyle;\n if (style === false || this.keysToAnimate.size === 0) return;\n\n const body = this.shadowRoot?.querySelector('.rows');\n if (!body) return;\n\n const animClass = style === 'fade' ? 'tbw-group-fade-in' : 'tbw-group-slide-in';\n for (const rowEl of body.querySelectorAll('.data-grid-row:not(.group-row)')) {\n const cell = rowEl.querySelector('.cell[data-row]');\n const idx = cell ? parseInt(cell.getAttribute('data-row') ?? '-1', 10) : -1;\n const item = this.flattenedRows[idx];\n const key = item?.kind === 'data' ? `data-${idx}` : undefined;\n\n if (key && this.keysToAnimate.has(key)) {\n rowEl.classList.add(animClass);\n rowEl.addEventListener('animationend', () => rowEl.classList.remove(animClass), { once: true });\n }\n }\n this.keysToAnimate.clear();\n }\n // #endregion\n\n // #region Private Rendering Helpers\n\n private renderFullWidthGroupRow(row: any, rowEl: HTMLElement, handleToggle: () => void): void {\n const config = this.config;\n\n // Full-width mode: single spanning cell with toggle + label + count\n const cell = document.createElement('div');\n cell.className = 'cell group-full';\n cell.style.gridColumn = '1 / -1';\n cell.setAttribute('role', 'gridcell');\n\n // Toggle button with click handler\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = `group-toggle${row.__groupExpanded ? ' expanded' : ''}`;\n btn.setAttribute('aria-label', row.__groupExpanded ? 'Collapse group' : 'Expand group');\n this.setIcon(btn, this.resolveIcon(row.__groupExpanded ? 'collapse' : 'expand'));\n btn.addEventListener('click', (e) => {\n e.stopPropagation();\n handleToggle();\n });\n cell.appendChild(btn);\n\n // Group label - use formatLabel if provided\n const label = document.createElement('span');\n label.className = 'group-label';\n const labelText = config.formatLabel\n ? config.formatLabel(row.__groupValue, row.__groupDepth || 0, row.__groupKey)\n : String(row.__groupValue);\n label.textContent = labelText;\n cell.appendChild(label);\n\n // Row count\n if (config.showRowCount !== false) {\n const count = document.createElement('span');\n count.className = 'group-count';\n count.textContent = `(${row.__groupRowCount ?? row.__groupRows?.length ?? 0})`;\n cell.appendChild(count);\n }\n\n rowEl.appendChild(cell);\n }\n\n private renderPerColumnGroupRow(row: any, rowEl: HTMLElement, handleToggle: () => void): void {\n const config = this.config;\n const aggregators = config.aggregators ?? {};\n const columns = this.columns;\n const groupRows = row.__groupRows ?? [];\n\n // Get grid template from the grid element\n const bodyEl = this.shadowRoot?.querySelector('.body') as HTMLElement | null;\n const gridTemplate = bodyEl?.style.gridTemplateColumns || '';\n if (gridTemplate) {\n rowEl.style.display = 'grid';\n rowEl.style.gridTemplateColumns = gridTemplate;\n }\n\n columns.forEach((col, colIdx) => {\n const cell = document.createElement('div');\n cell.className = 'cell group-cell';\n cell.setAttribute('data-col', String(colIdx));\n cell.setAttribute('role', 'gridcell');\n\n if (colIdx === 0) {\n // First column: toggle button + label\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = `group-toggle${row.__groupExpanded ? ' expanded' : ''}`;\n btn.setAttribute('aria-label', row.__groupExpanded ? 'Collapse group' : 'Expand group');\n this.setIcon(btn, this.resolveIcon(row.__groupExpanded ? 'collapse' : 'expand'));\n btn.addEventListener('click', (e) => {\n e.stopPropagation();\n handleToggle();\n });\n cell.appendChild(btn);\n\n const label = document.createElement('span');\n const firstColAgg = aggregators[col.field];\n if (firstColAgg) {\n const aggResult = runAggregator(firstColAgg, groupRows, col.field, col);\n label.textContent = aggResult != null ? String(aggResult) : String(row.__groupValue);\n } else {\n const labelText = config.formatLabel\n ? config.formatLabel(row.__groupValue, row.__groupDepth || 0, row.__groupKey)\n : String(row.__groupValue);\n label.textContent = labelText;\n }\n cell.appendChild(label);\n\n if (config.showRowCount !== false) {\n const count = document.createElement('span');\n count.className = 'group-count';\n count.textContent = ` (${groupRows.length})`;\n cell.appendChild(count);\n }\n } else {\n // Other columns: run aggregator if defined\n const aggRef = aggregators[col.field];\n if (aggRef) {\n const result = runAggregator(aggRef, groupRows, col.field, col);\n cell.textContent = result != null ? String(result) : '';\n } else {\n cell.textContent = '';\n }\n }\n\n rowEl.appendChild(cell);\n });\n }\n // #endregion\n\n // #region Public API\n\n /**\n * Expand all groups.\n */\n expandAll(): void {\n this.expandedKeys = expandAllGroups(this.flattenedRows);\n this.requestRender();\n }\n\n /**\n * Collapse all groups.\n */\n collapseAll(): void {\n this.expandedKeys = collapseAllGroups();\n this.requestRender();\n }\n\n /**\n * Toggle expansion of a specific group.\n * @param key - The group key to toggle\n */\n toggle(key: string): void {\n this.expandedKeys = toggleGroupExpansion(this.expandedKeys, key);\n\n // Find the group to emit event details\n const group = this.flattenedRows.find((r) => r.kind === 'group' && r.key === key) as GroupRowModelItem | undefined;\n\n this.emit<GroupToggleDetail>('group-toggle', {\n key,\n expanded: this.expandedKeys.has(key),\n value: group?.value,\n depth: group?.depth ?? 0,\n });\n\n this.requestRender();\n }\n\n /**\n * Check if a specific group is expanded.\n * @param key - The group key to check\n * @returns Whether the group is expanded\n */\n isExpanded(key: string): boolean {\n return this.expandedKeys.has(key);\n }\n\n /**\n * Expand a specific group.\n * @param key - The group key to expand\n */\n expand(key: string): void {\n if (!this.expandedKeys.has(key)) {\n this.expandedKeys = new Set([...this.expandedKeys, key]);\n this.requestRender();\n }\n }\n\n /**\n * Collapse a specific group.\n * @param key - The group key to collapse\n */\n collapse(key: string): void {\n if (this.expandedKeys.has(key)) {\n const newKeys = new Set(this.expandedKeys);\n newKeys.delete(key);\n this.expandedKeys = newKeys;\n this.requestRender();\n }\n }\n\n /**\n * Get the current group state.\n * @returns Group state information\n */\n getGroupState(): GroupState {\n const groupRows = this.flattenedRows.filter((r) => r.kind === 'group');\n return {\n isActive: this.isActive,\n expandedCount: this.expandedKeys.size,\n totalGroups: groupRows.length,\n expandedKeys: [...this.expandedKeys],\n };\n }\n\n /**\n * Get the total count of visible rows (including group headers).\n * @returns Number of visible rows\n */\n getRowCount(): number {\n return this.flattenedRows.length;\n }\n\n /**\n * Refresh the grouped row model.\n * Call this after modifying groupOn or other config options.\n */\n refreshGroups(): void {\n this.requestRender();\n }\n\n /**\n * Get current expanded group keys.\n * @returns Array of expanded group keys\n */\n getExpandedGroups(): string[] {\n return [...this.expandedKeys];\n }\n\n /**\n * Get the flattened row model.\n * @returns Array of render rows (groups + data rows)\n */\n getFlattenedRows(): RenderRow[] {\n return this.flattenedRows;\n }\n\n /**\n * Check if grouping is currently active.\n * @returns Whether grouping is active\n */\n isGroupingActive(): boolean {\n return this.isActive;\n }\n\n /**\n * Set the groupOn function dynamically.\n * @param fn - The groupOn function or undefined to disable\n */\n setGroupOn(fn: ((row: any) => any[] | any | null | false) | undefined): void {\n (this.config as GroupingRowsConfig).groupOn = fn;\n this.requestRender();\n }\n // #endregion\n\n // #region Styles\n\n override readonly styles = styles;\n // #endregion\n}\n","/**\n * Master/Detail Core Logic\n *\n * Pure functions for managing detail row expansion state.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n// Uses `any` for maximum flexibility with user-defined row types.\n\n/**\n * Toggle the expansion state of a detail row.\n * Returns a new Set with the updated state.\n */\nexport function toggleDetailRow(expandedRows: Set<object>, row: object): Set<object> {\n const newExpanded = new Set(expandedRows);\n if (newExpanded.has(row)) {\n newExpanded.delete(row);\n } else {\n newExpanded.add(row);\n }\n return newExpanded;\n}\n\n/**\n * Expand a detail row.\n * Returns a new Set with the row added.\n */\nexport function expandDetailRow(expandedRows: Set<object>, row: object): Set<object> {\n const newExpanded = new Set(expandedRows);\n newExpanded.add(row);\n return newExpanded;\n}\n\n/**\n * Collapse a detail row.\n * Returns a new Set with the row removed.\n */\nexport function collapseDetailRow(expandedRows: Set<object>, row: object): Set<object> {\n const newExpanded = new Set(expandedRows);\n newExpanded.delete(row);\n return newExpanded;\n}\n\n/**\n * Check if a detail row is expanded.\n */\nexport function isDetailExpanded(expandedRows: Set<object>, row: object): boolean {\n return expandedRows.has(row);\n}\n\n/**\n * Create a detail element for a given row.\n * The element spans all columns and contains the rendered content.\n */\nexport function createDetailElement(\n row: any,\n rowIndex: number,\n renderer: (row: any, rowIndex: number) => HTMLElement | string,\n columnCount: number\n): HTMLElement {\n const detailRow = document.createElement('div');\n detailRow.className = 'master-detail-row';\n detailRow.setAttribute('data-detail-for', String(rowIndex));\n detailRow.setAttribute('role', 'row');\n\n const detailCell = document.createElement('div');\n detailCell.className = 'master-detail-cell';\n detailCell.setAttribute('role', 'cell');\n detailCell.style.gridColumn = `1 / ${columnCount + 1}`;\n\n const content = renderer(row, rowIndex);\n if (typeof content === 'string') {\n detailCell.innerHTML = content;\n } else if (content instanceof HTMLElement) {\n detailCell.appendChild(content);\n }\n\n detailRow.appendChild(detailCell);\n return detailRow;\n}\n","/**\n * Master/Detail Plugin (Class-based)\n *\n * Enables expandable detail rows showing additional content for each row.\n * Animation style is plugin-configured; respects grid-level animation.mode.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { BaseGridPlugin, RowClickEvent } from '../../core/plugin/base-plugin';\nimport type { GridConfig } from '../../core/types';\nimport {\n collapseDetailRow,\n createDetailElement,\n expandDetailRow,\n isDetailExpanded,\n toggleDetailRow,\n} from './master-detail';\nimport styles from './master-detail.css?inline';\nimport type { DetailExpandDetail, ExpandCollapseAnimation, MasterDetailConfig } from './types';\n\n/** Extended grid interface for accessing effective config */\ninterface GridWithConfig {\n effectiveConfig?: GridConfig;\n}\n\n/**\n * Master/Detail Plugin for tbw-grid\n *\n * @example\n * ```ts\n * new MasterDetailPlugin({\n * enabled: true,\n * detailRenderer: (row) => `<div>Details for ${row.name}</div>`,\n * expandOnRowClick: true,\n * })\n * ```\n */\nexport class MasterDetailPlugin extends BaseGridPlugin<MasterDetailConfig> {\n readonly name = 'masterDetail';\n override readonly version = '1.0.0';\n\n protected override get defaultConfig(): Partial<MasterDetailConfig> {\n return {\n detailHeight: 'auto',\n expandOnRowClick: false,\n collapseOnClickOutside: false,\n showExpandColumn: true,\n animation: 'slide', // Plugin's own default\n };\n }\n\n // #region Animation Helpers\n\n /**\n * Check if animations are enabled at the grid level.\n * Respects gridConfig.animation.mode and CSS variable.\n */\n private get isAnimationEnabled(): boolean {\n const gridEl = this.grid as unknown as GridWithConfig;\n const mode = gridEl.effectiveConfig?.animation?.mode ?? 'reduced-motion';\n\n if (mode === false || mode === 'off') return false;\n if (mode === true || mode === 'on') return true;\n\n // reduced-motion: check CSS variable\n const host = this.shadowRoot?.host as HTMLElement | undefined;\n if (host) {\n const enabled = getComputedStyle(host).getPropertyValue('--tbw-animation-enabled').trim();\n return enabled !== '0';\n }\n return true;\n }\n\n /**\n * Get expand/collapse animation style from plugin config.\n */\n private get animationStyle(): ExpandCollapseAnimation {\n if (!this.isAnimationEnabled) return false;\n return this.config.animation ?? 'slide'; // Plugin default\n }\n\n /**\n * Get animation duration from CSS variable (set by grid).\n */\n private get animationDuration(): number {\n const host = this.shadowRoot?.host as HTMLElement | undefined;\n if (host) {\n const durationStr = getComputedStyle(host).getPropertyValue('--tbw-animation-duration').trim();\n const parsed = parseInt(durationStr, 10);\n if (!isNaN(parsed)) return parsed;\n }\n return 200; // Default\n }\n\n /**\n * Apply expand animation to a detail element.\n */\n private animateExpand(detailEl: HTMLElement): void {\n if (!this.isAnimationEnabled || this.animationStyle === false) return;\n\n detailEl.classList.add('tbw-expanding');\n detailEl.addEventListener(\n 'animationend',\n () => {\n detailEl.classList.remove('tbw-expanding');\n },\n { once: true },\n );\n }\n\n /**\n * Apply collapse animation to a detail element and remove after animation.\n */\n private animateCollapse(detailEl: HTMLElement, onComplete: () => void): void {\n if (!this.isAnimationEnabled || this.animationStyle === false) {\n onComplete();\n return;\n }\n\n detailEl.classList.add('tbw-collapsing');\n const cleanup = () => {\n detailEl.classList.remove('tbw-collapsing');\n onComplete();\n };\n detailEl.addEventListener('animationend', cleanup, { once: true });\n // Fallback timeout in case animation doesn't fire\n setTimeout(cleanup, this.animationDuration + 50);\n }\n\n // #endregion\n\n // #region Internal State\n private expandedRows: Set<any> = new Set();\n private detailElements: Map<any, HTMLElement> = new Map();\n // #endregion\n\n // #region Lifecycle\n\n override detach(): void {\n this.expandedRows.clear();\n this.detailElements.clear();\n }\n // #endregion\n\n // #region Hooks\n\n override processColumns(\n columns: readonly import('../../core/types').ColumnConfig[],\n ): import('../../core/types').ColumnConfig[] {\n if (!this.config.detailRenderer) {\n return [...columns];\n }\n\n // Wrap first column's renderer to add expand/collapse toggle\n const cols = [...columns];\n if (cols.length > 0) {\n const firstCol = { ...cols[0] };\n const originalRenderer = firstCol.viewRenderer;\n\n // Skip if already wrapped by this plugin (prevents double-wrapping on re-render)\n if ((originalRenderer as any)?.__masterDetailWrapped) {\n return cols;\n }\n\n const wrappedRenderer = (renderCtx: Parameters<NonNullable<typeof originalRenderer>>[0]) => {\n const { value, row } = renderCtx;\n const isExpanded = this.expandedRows.has(row);\n\n const container = document.createElement('span');\n container.className = 'master-detail-cell-wrapper';\n\n // Expand/collapse toggle icon\n const toggle = document.createElement('span');\n toggle.className = `master-detail-toggle${isExpanded ? ' expanded' : ''}`;\n // Use grid-level icons (fall back to defaults)\n this.setIcon(toggle, this.resolveIcon(isExpanded ? 'collapse' : 'expand'));\n // role=\"button\" is required for aria-expanded to be valid\n toggle.setAttribute('role', 'button');\n toggle.setAttribute('tabindex', '0');\n toggle.setAttribute('aria-expanded', String(isExpanded));\n toggle.setAttribute('aria-label', isExpanded ? 'Collapse details' : 'Expand details');\n toggle.addEventListener('click', (e) => {\n e.stopPropagation();\n const rowIndex = this.rows.indexOf(row);\n this.expandedRows = toggleDetailRow(this.expandedRows, row);\n this.emit<DetailExpandDetail>('detail-expand', {\n rowIndex,\n row,\n expanded: this.expandedRows.has(row),\n });\n this.requestRender();\n });\n container.appendChild(toggle);\n\n // Cell content\n const content = document.createElement('span');\n if (originalRenderer) {\n const rendered = originalRenderer(renderCtx);\n if (rendered instanceof Node) {\n content.appendChild(rendered);\n } else {\n content.textContent = String(rendered ?? value ?? '');\n }\n } else {\n content.textContent = String(value ?? '');\n }\n container.appendChild(content);\n\n return container;\n };\n\n // Mark renderer as wrapped to prevent double-wrapping\n (wrappedRenderer as any).__masterDetailWrapped = true;\n firstCol.viewRenderer = wrappedRenderer;\n\n cols[0] = firstCol;\n }\n\n return cols;\n }\n\n override onRowClick(event: RowClickEvent): boolean | void {\n if (!this.config.expandOnRowClick || !this.config.detailRenderer) return;\n\n this.expandedRows = toggleDetailRow(this.expandedRows, event.row);\n\n this.emit<DetailExpandDetail>('detail-expand', {\n rowIndex: event.rowIndex,\n row: event.row,\n expanded: this.expandedRows.has(event.row),\n });\n\n this.requestRender();\n return false;\n }\n\n override onCellClick(): boolean | void {\n // Sync detail rows after cell click triggers refreshVirtualWindow\n // This runs in microtask to ensure DOM updates are complete\n if (this.expandedRows.size > 0) {\n queueMicrotask(() => this.#syncDetailRows());\n }\n return; // Don't prevent default\n }\n\n override afterRender(): void {\n this.#syncDetailRows();\n }\n\n /**\n * Called on scroll to sync detail elements with visible rows.\n * Removes details for rows that scrolled out of view and reattaches for visible rows.\n */\n override onScrollRender(): void {\n if (!this.config.detailRenderer || this.expandedRows.size === 0) return;\n // Full sync needed on scroll to clean up orphaned details\n this.#syncDetailRows();\n }\n\n /**\n * Full sync of detail rows - cleans up stale elements and creates new ones.\n * Detail rows are inserted as siblings AFTER their master row to survive row rebuilds.\n */\n #syncDetailRows(): void {\n if (!this.config.detailRenderer) return;\n\n const body = this.shadowRoot?.querySelector('.rows');\n if (!body) return;\n\n // Build a map of row index -> row element for visible rows\n const visibleRowMap = new Map<number, Element>();\n const dataRows = body.querySelectorAll('.data-grid-row');\n const columnCount = this.columns.length;\n\n for (const rowEl of dataRows) {\n const firstCell = rowEl.querySelector('.cell[data-row]');\n const rowIndex = firstCell ? parseInt(firstCell.getAttribute('data-row') ?? '-1', 10) : -1;\n if (rowIndex >= 0) {\n visibleRowMap.set(rowIndex, rowEl);\n }\n }\n\n // Remove detail rows whose parent row is no longer visible or no longer expanded\n const existingDetails = body.querySelectorAll('.master-detail-row');\n for (const detailEl of existingDetails) {\n const forIndex = parseInt(detailEl.getAttribute('data-detail-for') ?? '-1', 10);\n const row = forIndex >= 0 ? this.rows[forIndex] : undefined;\n const isStillExpanded = row && this.expandedRows.has(row);\n const isRowVisible = visibleRowMap.has(forIndex);\n\n // Remove detail if not expanded or if parent row scrolled out\n if (!isStillExpanded || !isRowVisible) {\n detailEl.remove();\n if (row) this.detailElements.delete(row);\n }\n }\n\n // Insert detail rows for expanded rows that are visible\n for (const [rowIndex, rowEl] of visibleRowMap) {\n const row = this.rows[rowIndex];\n if (!row || !this.expandedRows.has(row)) continue;\n\n // Check if detail already exists for this row\n const existingDetail = this.detailElements.get(row);\n if (existingDetail) {\n // Ensure it's positioned correctly (as next sibling of row element)\n if (existingDetail.previousElementSibling !== rowEl) {\n rowEl.after(existingDetail);\n }\n continue;\n }\n\n // Create new detail element\n const detailEl = createDetailElement(row, rowIndex, this.config.detailRenderer, columnCount);\n\n if (typeof this.config.detailHeight === 'number') {\n detailEl.style.height = `${this.config.detailHeight}px`;\n }\n\n // Insert as sibling after the row element (not as child)\n rowEl.after(detailEl);\n this.detailElements.set(row, detailEl);\n\n // Apply expand animation\n this.animateExpand(detailEl);\n }\n }\n\n /**\n * Return total extra height from all expanded detail rows.\n * Used by grid virtualization to adjust scrollbar height.\n */\n override getExtraHeight(): number {\n let totalHeight = 0;\n for (const row of this.expandedRows) {\n const detailEl = this.detailElements.get(row);\n if (detailEl) {\n totalHeight += detailEl.offsetHeight;\n } else {\n // Detail not yet rendered - estimate based on config or default\n const configHeight = this.config?.detailHeight;\n totalHeight += typeof configHeight === 'number' ? configHeight : 150;\n }\n }\n return totalHeight;\n }\n\n /**\n * Return extra height that appears before a given row index.\n * This is the sum of heights of all expanded details whose parent row is before the given index.\n */\n override getExtraHeightBefore(beforeRowIndex: number): number {\n let totalHeight = 0;\n for (const row of this.expandedRows) {\n const rowIndex = this.rows.indexOf(row);\n // Include detail if it's for a row before the given index\n if (rowIndex >= 0 && rowIndex < beforeRowIndex) {\n const detailEl = this.detailElements.get(row);\n if (detailEl) {\n totalHeight += detailEl.offsetHeight;\n } else {\n const configHeight = this.config?.detailHeight;\n totalHeight += typeof configHeight === 'number' ? configHeight : 150;\n }\n }\n }\n return totalHeight;\n }\n\n /**\n * Adjust the virtualization start index to keep expanded row visible while its detail is visible.\n * This ensures the detail scrolls smoothly out of view instead of disappearing abruptly.\n */\n override adjustVirtualStart(start: number, scrollTop: number, rowHeight: number): number {\n if (this.expandedRows.size === 0) return start;\n\n // Build sorted list of expanded row indices for cumulative height calculation\n const expandedIndices: Array<{ index: number; row: any }> = [];\n for (const row of this.expandedRows) {\n const index = this.rows.indexOf(row);\n if (index >= 0) {\n expandedIndices.push({ index, row });\n }\n }\n expandedIndices.sort((a, b) => a.index - b.index);\n\n let minStart = start;\n\n // Calculate actual scroll position for each expanded row,\n // accounting for cumulative detail heights before it\n let cumulativeExtraHeight = 0;\n\n for (const { index: rowIndex, row } of expandedIndices) {\n // Actual position includes all detail heights before this row\n const actualRowTop = rowIndex * rowHeight + cumulativeExtraHeight;\n const detailEl = this.detailElements.get(row);\n const detailHeight =\n detailEl?.offsetHeight ?? (typeof this.config?.detailHeight === 'number' ? this.config.detailHeight : 150);\n const actualDetailBottom = actualRowTop + rowHeight + detailHeight;\n\n // Update cumulative height for next iteration\n cumulativeExtraHeight += detailHeight;\n\n // Skip rows that are at or after the calculated start\n if (rowIndex >= start) continue;\n\n // If any part of the detail is still visible (below the scroll position),\n // we need to keep the parent row in the render range\n if (actualDetailBottom > scrollTop) {\n if (rowIndex < minStart) {\n minStart = rowIndex;\n }\n }\n }\n\n return minStart;\n }\n // #endregion\n\n // #region Public API\n\n /**\n * Expand the detail row at the given index.\n * @param rowIndex - Index of the row to expand\n */\n expand(rowIndex: number): void {\n const row = this.rows[rowIndex];\n if (row) {\n this.expandedRows = expandDetailRow(this.expandedRows, row);\n this.requestRender();\n }\n }\n\n /**\n * Collapse the detail row at the given index.\n * @param rowIndex - Index of the row to collapse\n */\n collapse(rowIndex: number): void {\n const row = this.rows[rowIndex];\n if (row) {\n this.expandedRows = collapseDetailRow(this.expandedRows, row);\n this.requestRender();\n }\n }\n\n /**\n * Toggle the detail row at the given index.\n * @param rowIndex - Index of the row to toggle\n */\n toggle(rowIndex: number): void {\n const row = this.rows[rowIndex];\n if (row) {\n this.expandedRows = toggleDetailRow(this.expandedRows, row);\n this.requestRender();\n }\n }\n\n /**\n * Check if the detail row at the given index is expanded.\n * @param rowIndex - Index of the row to check\n * @returns Whether the detail row is expanded\n */\n isExpanded(rowIndex: number): boolean {\n const row = this.rows[rowIndex];\n return row ? isDetailExpanded(this.expandedRows, row) : false;\n }\n\n /**\n * Expand all detail rows.\n */\n expandAll(): void {\n for (const row of this.rows) {\n this.expandedRows.add(row);\n }\n this.requestRender();\n }\n\n /**\n * Collapse all detail rows.\n */\n collapseAll(): void {\n this.expandedRows.clear();\n this.requestRender();\n }\n\n /**\n * Get the indices of all expanded rows.\n * @returns Array of row indices that are expanded\n */\n getExpandedRows(): number[] {\n const indices: number[] = [];\n for (const row of this.expandedRows) {\n const idx = this.rows.indexOf(row);\n if (idx >= 0) indices.push(idx);\n }\n return indices;\n }\n\n /**\n * Get the detail element for a specific row.\n * @param rowIndex - Index of the row\n * @returns The detail HTMLElement or undefined\n */\n getDetailElement(rowIndex: number): HTMLElement | undefined {\n const row = this.rows[rowIndex];\n return row ? this.detailElements.get(row) : undefined;\n }\n // #endregion\n\n // #region Styles\n override readonly styles = styles;\n // #endregion\n}\n","/**\n * Multi-Sort Core Logic\n *\n * Pure functions for multi-column sorting operations.\n */\n\nimport type { ColumnConfig } from '../../core/types';\nimport type { SortModel } from './types';\n\n/**\n * Apply multiple sort columns to a row array.\n * Sorts are applied in order - first sort has highest priority.\n *\n * @param rows - Array of row objects to sort\n * @param sorts - Ordered array of sort configurations\n * @param columns - Column configurations (for custom comparators)\n * @returns New sorted array (does not mutate original)\n */\nexport function applySorts<TRow = unknown>(rows: TRow[], sorts: SortModel[], columns: ColumnConfig<TRow>[]): TRow[] {\n if (!sorts.length) return [...rows];\n\n return [...rows].sort((a, b) => {\n for (const sort of sorts) {\n const col = columns.find((c) => c.field === sort.field);\n const comparator = col?.sortComparator ?? defaultComparator;\n const aVal = (a as Record<string, unknown>)[sort.field];\n const bVal = (b as Record<string, unknown>)[sort.field];\n const result = comparator(aVal, bVal, a, b);\n if (result !== 0) {\n return sort.direction === 'asc' ? result : -result;\n }\n }\n return 0;\n });\n}\n\n/**\n * Default comparator for sorting values.\n * Handles nulls, numbers, dates, and strings.\n *\n * @param a - First value\n * @param b - Second value\n * @returns Comparison result (-1, 0, 1)\n */\nexport function defaultComparator(a: unknown, b: unknown): number {\n // Handle nulls/undefined - push to end\n if (a == null && b == null) return 0;\n if (a == null) return 1;\n if (b == null) return -1;\n\n // Type-aware comparison\n if (typeof a === 'number' && typeof b === 'number') {\n return a - b;\n }\n\n if (a instanceof Date && b instanceof Date) {\n return a.getTime() - b.getTime();\n }\n\n // Boolean comparison\n if (typeof a === 'boolean' && typeof b === 'boolean') {\n return a === b ? 0 : a ? -1 : 1;\n }\n\n // String comparison (fallback)\n return String(a).localeCompare(String(b));\n}\n\n/**\n * Toggle sort state for a field.\n * With shift key: adds/toggles in multi-sort list\n * Without shift key: replaces entire sort with single column\n *\n * @param current - Current sort model\n * @param field - Field to toggle\n * @param shiftKey - Whether shift key is held (multi-sort mode)\n * @param maxColumns - Maximum columns allowed in sort\n * @returns New sort model\n */\nexport function toggleSort(current: SortModel[], field: string, shiftKey: boolean, maxColumns: number): SortModel[] {\n const existing = current.find((s) => s.field === field);\n\n if (shiftKey) {\n // Multi-sort: add/toggle in list\n if (existing) {\n if (existing.direction === 'asc') {\n // Flip to descending\n return current.map((s) => (s.field === field ? { ...s, direction: 'desc' as const } : s));\n } else {\n // Remove from sort\n return current.filter((s) => s.field !== field);\n }\n } else if (current.length < maxColumns) {\n // Add new sort column\n return [...current, { field, direction: 'asc' as const }];\n }\n // Max columns reached, return unchanged\n return current;\n } else {\n // Single sort: replace all\n if (existing?.direction === 'asc') {\n return [{ field, direction: 'desc' }];\n } else if (existing?.direction === 'desc') {\n return [];\n }\n return [{ field, direction: 'asc' }];\n }\n}\n\n/**\n * Get the sort index (1-based) for a field in the sort model.\n * Returns undefined if the field is not in the sort model.\n *\n * @param sortModel - Current sort model\n * @param field - Field to check\n * @returns 1-based index or undefined\n */\nexport function getSortIndex(sortModel: SortModel[], field: string): number | undefined {\n const index = sortModel.findIndex((s) => s.field === field);\n return index >= 0 ? index + 1 : undefined;\n}\n\n/**\n * Get the sort direction for a field in the sort model.\n *\n * @param sortModel - Current sort model\n * @param field - Field to check\n * @returns Sort direction or undefined if not sorted\n */\nexport function getSortDirection(sortModel: SortModel[], field: string): 'asc' | 'desc' | undefined {\n return sortModel.find((s) => s.field === field)?.direction;\n}\n","/**\n * Multi-Sort Plugin (Class-based)\n *\n * Provides multi-column sorting capabilities for tbw-grid.\n * Supports shift+click for adding secondary sort columns.\n */\n\nimport { BaseGridPlugin, HeaderClickEvent } from '../../core/plugin/base-plugin';\nimport type { ColumnState } from '../../core/types';\nimport { applySorts, getSortDirection, getSortIndex, toggleSort } from './multi-sort';\nimport styles from './multi-sort.css?inline';\nimport type { MultiSortConfig, SortModel } from './types';\n\n/**\n * Multi-Sort Plugin for tbw-grid\n *\n * @example\n * ```ts\n * new MultiSortPlugin({ maxSortColumns: 3, showSortIndex: true })\n * ```\n */\nexport class MultiSortPlugin extends BaseGridPlugin<MultiSortConfig> {\n readonly name = 'multiSort';\n override readonly version = '1.0.0';\n\n protected override get defaultConfig(): Partial<MultiSortConfig> {\n return {\n maxSortColumns: 3,\n showSortIndex: true,\n };\n }\n\n // #region Internal State\n private sortModel: SortModel[] = [];\n // #endregion\n\n // #region Lifecycle\n\n override detach(): void {\n this.sortModel = [];\n }\n // #endregion\n\n // #region Hooks\n\n override processRows(rows: readonly unknown[]): unknown[] {\n if (this.sortModel.length === 0) {\n return [...rows];\n }\n return applySorts([...rows], this.sortModel, [...this.columns]);\n }\n\n override onHeaderClick(event: HeaderClickEvent): boolean {\n const column = this.columns.find((c) => c.field === event.field);\n if (!column?.sortable) return false;\n\n const shiftKey = event.originalEvent.shiftKey;\n const maxColumns = this.config.maxSortColumns ?? 3;\n\n this.sortModel = toggleSort(this.sortModel, event.field, shiftKey, maxColumns);\n\n this.emit('sort-change', { sortModel: [...this.sortModel] });\n this.requestRender();\n\n return true;\n }\n\n override afterRender(): void {\n const shadowRoot = this.shadowRoot;\n if (!shadowRoot) return;\n\n const showIndex = this.config.showSortIndex !== false;\n\n // Update all sortable header cells with sort indicators\n const headerCells = shadowRoot.querySelectorAll('.header-row .cell[data-field]');\n headerCells.forEach((cell) => {\n const field = cell.getAttribute('data-field');\n if (!field) return;\n\n const sortIndex = getSortIndex(this.sortModel, field);\n const sortDir = getSortDirection(this.sortModel, field);\n\n // Remove existing sort index badge (always clean up)\n const existingBadge = cell.querySelector('.sort-index');\n existingBadge?.remove();\n\n if (sortDir) {\n // Column is sorted - remove base indicator and add our own\n const existingIndicator = cell.querySelector('[part~=\"sort-indicator\"], .sort-indicator');\n existingIndicator?.remove();\n\n cell.setAttribute('data-sort', sortDir);\n\n // Add sort arrow indicator\n const indicator = document.createElement('span');\n indicator.className = 'sort-indicator';\n // Use grid-level icons (fall back to defaults)\n this.setIcon(indicator, this.resolveIcon(sortDir === 'asc' ? 'sortAsc' : 'sortDesc'));\n cell.appendChild(indicator);\n\n // Add sort index badge if multiple columns sorted and showSortIndex is enabled\n if (showIndex && this.sortModel.length > 1 && sortIndex !== undefined) {\n const badge = document.createElement('span');\n badge.className = 'sort-index';\n badge.textContent = String(sortIndex);\n cell.appendChild(badge);\n }\n } else {\n cell.removeAttribute('data-sort');\n // For unsorted columns, leave the base indicator (⇅) alone\n }\n });\n }\n // #endregion\n\n // #region Public API\n\n /**\n * Get the current sort model.\n * @returns Copy of the current sort model\n */\n getSortModel(): SortModel[] {\n return [...this.sortModel];\n }\n\n /**\n * Set the sort model programmatically.\n * @param model - New sort model to apply\n */\n setSortModel(model: SortModel[]): void {\n this.sortModel = [...model];\n this.emit('sort-change', { sortModel: [...model] });\n this.requestRender();\n }\n\n /**\n * Clear all sorting.\n */\n clearSort(): void {\n this.sortModel = [];\n this.emit('sort-change', { sortModel: [] });\n this.requestRender();\n }\n\n /**\n * Get the sort index (1-based) for a specific field.\n * @param field - Field to check\n * @returns 1-based index or undefined if not sorted\n */\n getSortIndex(field: string): number | undefined {\n return getSortIndex(this.sortModel, field);\n }\n\n /**\n * Get the sort direction for a specific field.\n * @param field - Field to check\n * @returns Sort direction or undefined if not sorted\n */\n getSortDirection(field: string): 'asc' | 'desc' | undefined {\n return getSortDirection(this.sortModel, field);\n }\n // #endregion\n\n // #region Column State Hooks\n\n /**\n * Return sort state for a column if it's in the sort model.\n */\n override getColumnState(field: string): Partial<ColumnState> | undefined {\n const index = this.sortModel.findIndex((s) => s.field === field);\n if (index === -1) return undefined;\n\n const sortEntry = this.sortModel[index];\n return {\n sort: {\n direction: sortEntry.direction,\n priority: index,\n },\n };\n }\n\n /**\n * Apply sort state from column state.\n * Rebuilds the sort model from all column states.\n */\n override applyColumnState(field: string, state: ColumnState): void {\n // Only process if the column has sort state\n if (!state.sort) {\n // Remove this field from sortModel if it exists\n this.sortModel = this.sortModel.filter((s) => s.field !== field);\n return;\n }\n\n // Find existing entry or add new one\n const existingIndex = this.sortModel.findIndex((s) => s.field === field);\n const newEntry: SortModel = {\n field,\n direction: state.sort.direction,\n };\n\n if (existingIndex !== -1) {\n // Update existing entry\n this.sortModel[existingIndex] = newEntry;\n } else {\n // Add at the correct priority position\n this.sortModel.splice(state.sort.priority, 0, newEntry);\n }\n\n // Re-sort the model by priority to ensure correct order\n // This is handled after all columns are processed, but we maintain order here\n }\n // #endregion\n\n // #region Styles\n\n override readonly styles = styles;\n // #endregion\n}\n","/**\n * Sticky Columns Core Logic\n *\n * Pure functions for applying sticky (pinned) column positioning.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { StickyPosition } from './types';\n\n/**\n * Get columns that should be sticky on the left.\n *\n * @param columns - Array of column configurations\n * @returns Array of columns with sticky='left'\n */\nexport function getLeftStickyColumns(columns: any[]): any[] {\n return columns.filter((col) => col.sticky === 'left');\n}\n\n/**\n * Get columns that should be sticky on the right.\n *\n * @param columns - Array of column configurations\n * @returns Array of columns with sticky='right'\n */\nexport function getRightStickyColumns(columns: any[]): any[] {\n return columns.filter((col) => col.sticky === 'right');\n}\n\n/**\n * Check if any columns have sticky positioning.\n *\n * @param columns - Array of column configurations\n * @returns True if any column has sticky position\n */\nexport function hasStickyColumns(columns: any[]): boolean {\n return columns.some((col) => col.sticky === 'left' || col.sticky === 'right');\n}\n\n/**\n * Get the sticky position of a column.\n *\n * @param column - Column configuration\n * @returns The sticky position or null if not sticky\n */\nexport function getColumnStickyPosition(column: any): StickyPosition | null {\n if (column.sticky === 'left') return 'left';\n if (column.sticky === 'right') return 'right';\n return null;\n}\n\n/**\n * Calculate left offsets for sticky-left columns.\n * Returns a map of field -> offset in pixels.\n *\n * @param columns - Array of column configurations (in order)\n * @param getColumnWidth - Function to get column width by field\n * @returns Map of field to left offset\n */\nexport function calculateLeftStickyOffsets(\n columns: any[],\n getColumnWidth: (field: string) => number,\n): Map<string, number> {\n const offsets = new Map<string, number>();\n let currentOffset = 0;\n\n for (const col of columns) {\n if (col.sticky === 'left') {\n offsets.set(col.field, currentOffset);\n currentOffset += getColumnWidth(col.field);\n }\n }\n\n return offsets;\n}\n\n/**\n * Calculate right offsets for sticky-right columns.\n * Processes columns in reverse order.\n *\n * @param columns - Array of column configurations (in order)\n * @param getColumnWidth - Function to get column width by field\n * @returns Map of field to right offset\n */\nexport function calculateRightStickyOffsets(\n columns: any[],\n getColumnWidth: (field: string) => number,\n): Map<string, number> {\n const offsets = new Map<string, number>();\n let currentOffset = 0;\n\n // Process in reverse for right-sticky columns\n const reversed = [...columns].reverse();\n for (const col of reversed) {\n if (col.sticky === 'right') {\n offsets.set(col.field, currentOffset);\n currentOffset += getColumnWidth(col.field);\n }\n }\n\n return offsets;\n}\n\n/**\n * Apply sticky offsets to header and body cells.\n * This modifies the DOM elements in place.\n *\n * @param host - The grid host element\n * @param columns - Array of column configurations\n */\nexport function applyStickyOffsets(host: HTMLElement, columns: any[]): void {\n const shadowRoot = host.shadowRoot;\n if (!shadowRoot) return;\n\n const headerCells = Array.from(shadowRoot.querySelectorAll('.header-row .cell')) as HTMLElement[];\n if (!headerCells.length) return;\n\n // Build column index map for matching body cells (which use data-col, not data-field)\n const fieldToIndex = new Map<string, number>();\n columns.forEach((col, i) => {\n if (col.field) fieldToIndex.set(col.field, i);\n });\n\n // Apply left sticky\n let left = 0;\n for (const col of columns) {\n if (col.sticky === 'left') {\n const colIndex = fieldToIndex.get(col.field);\n const cell = headerCells.find((c) => c.getAttribute('data-field') === col.field);\n if (cell) {\n cell.classList.add('sticky-left');\n cell.style.position = 'sticky';\n cell.style.left = left + 'px';\n // Body cells use data-col (column index), not data-field\n if (colIndex !== undefined) {\n shadowRoot.querySelectorAll(`.data-grid-row .cell[data-col=\"${colIndex}\"]`).forEach((el) => {\n el.classList.add('sticky-left');\n (el as HTMLElement).style.position = 'sticky';\n (el as HTMLElement).style.left = left + 'px';\n });\n }\n left += cell.offsetWidth;\n }\n }\n }\n\n // Apply right sticky (process in reverse)\n let right = 0;\n for (const col of [...columns].reverse()) {\n if (col.sticky === 'right') {\n const colIndex = fieldToIndex.get(col.field);\n const cell = headerCells.find((c) => c.getAttribute('data-field') === col.field);\n if (cell) {\n cell.classList.add('sticky-right');\n cell.style.position = 'sticky';\n cell.style.right = right + 'px';\n // Body cells use data-col (column index), not data-field\n if (colIndex !== undefined) {\n shadowRoot.querySelectorAll(`.data-grid-row .cell[data-col=\"${colIndex}\"]`).forEach((el) => {\n el.classList.add('sticky-right');\n (el as HTMLElement).style.position = 'sticky';\n (el as HTMLElement).style.right = right + 'px';\n });\n }\n right += cell.offsetWidth;\n }\n }\n }\n}\n\n/**\n * Clear sticky positioning from all cells.\n *\n * @param host - The grid host element\n */\nexport function clearStickyOffsets(host: HTMLElement): void {\n const shadowRoot = host.shadowRoot;\n if (!shadowRoot) return;\n\n const cells = shadowRoot.querySelectorAll('.sticky-left, .sticky-right');\n cells.forEach((cell) => {\n cell.classList.remove('sticky-left', 'sticky-right');\n (cell as HTMLElement).style.position = '';\n (cell as HTMLElement).style.left = '';\n (cell as HTMLElement).style.right = '';\n });\n}\n","/**\n * Pinned Columns Plugin (Class-based)\n *\n * Enables column pinning (sticky left/right positioning).\n */\n\nimport { BaseGridPlugin, PLUGIN_QUERIES, type PluginQuery } from '../../core/plugin/base-plugin';\nimport type { ColumnConfig } from '../../core/types';\nimport {\n applyStickyOffsets,\n clearStickyOffsets,\n getLeftStickyColumns,\n getRightStickyColumns,\n hasStickyColumns,\n} from './pinned-columns';\nimport type { PinnedColumnsConfig } from './types';\n\n/**\n * Pinned Columns Plugin for tbw-grid\n *\n * @example\n * ```ts\n * new PinnedColumnsPlugin({ enabled: true })\n * ```\n */\nexport class PinnedColumnsPlugin extends BaseGridPlugin<PinnedColumnsConfig> {\n readonly name = 'pinnedColumns';\n override readonly version = '1.0.0';\n\n protected override get defaultConfig(): Partial<PinnedColumnsConfig> {\n return {};\n }\n\n // #region Internal State\n private isApplied = false;\n private leftOffsets = new Map<string, number>();\n private rightOffsets = new Map<string, number>();\n // #endregion\n\n // #region Lifecycle\n\n override detach(): void {\n this.leftOffsets.clear();\n this.rightOffsets.clear();\n this.isApplied = false;\n }\n // #endregion\n\n // #region Detection\n\n /**\n * Auto-detect sticky columns from column configuration.\n */\n static detect(rows: readonly unknown[], config: { columns?: ColumnConfig[] }): boolean {\n const columns = config?.columns;\n if (!Array.isArray(columns)) return false;\n return hasStickyColumns(columns);\n }\n // #endregion\n\n // #region Hooks\n\n override processColumns(columns: readonly ColumnConfig[]): ColumnConfig[] {\n // Mark that we have sticky columns to apply\n this.isApplied = hasStickyColumns([...columns]);\n return [...columns];\n }\n\n override afterRender(): void {\n if (!this.isApplied) {\n return;\n }\n\n const host = this.grid as unknown as HTMLElement;\n const columns = [...this.columns];\n\n if (!hasStickyColumns(columns)) {\n clearStickyOffsets(host);\n this.isApplied = false;\n return;\n }\n\n // Apply sticky offsets after a microtask to ensure DOM is ready\n queueMicrotask(() => {\n applyStickyOffsets(host, columns);\n });\n }\n\n /**\n * Handle inter-plugin queries.\n */\n override onPluginQuery(query: PluginQuery): unknown {\n switch (query.type) {\n case PLUGIN_QUERIES.CAN_MOVE_COLUMN: {\n // Prevent pinned columns from being moved/reordered.\n // Pinned columns have fixed positions and should not be draggable.\n const column = query.context as ColumnConfig;\n const sticky = (column as ColumnConfig & { sticky?: 'left' | 'right' }).sticky;\n if (sticky === 'left' || sticky === 'right') {\n return false;\n }\n // Also check meta.sticky for backwards compatibility\n const metaSticky = (column.meta as { sticky?: 'left' | 'right' } | undefined)?.sticky;\n if (metaSticky === 'left' || metaSticky === 'right') {\n return false;\n }\n return undefined; // Let other plugins or default behavior decide\n }\n default:\n return undefined;\n }\n }\n // #endregion\n\n // #region Public API\n\n /**\n * Re-apply sticky offsets (e.g., after column resize).\n */\n refreshStickyOffsets(): void {\n const columns = [...this.columns];\n applyStickyOffsets(this.grid as unknown as HTMLElement, columns);\n }\n\n /**\n * Get columns pinned to the left.\n */\n getLeftPinnedColumns(): ColumnConfig[] {\n const columns = [...this.columns];\n return getLeftStickyColumns(columns);\n }\n\n /**\n * Get columns pinned to the right.\n */\n getRightPinnedColumns(): ColumnConfig[] {\n const columns = [...this.columns];\n return getRightStickyColumns(columns);\n }\n\n /**\n * Clear all sticky positioning.\n */\n clearStickyPositions(): void {\n clearStickyOffsets(this.grid as unknown as HTMLElement);\n }\n\n /**\n * Report horizontal scroll boundary offsets for pinned columns.\n * Used by keyboard navigation to ensure focused cells aren't hidden behind sticky columns.\n */\n override getHorizontalScrollOffsets(\n rowEl?: HTMLElement,\n focusedCell?: HTMLElement,\n ): { left: number; right: number; skipScroll?: boolean } | undefined {\n if (!this.isApplied) {\n return undefined;\n }\n\n let left = 0;\n let right = 0;\n\n if (rowEl) {\n // Calculate from rendered cells in the row\n const stickyLeftCells = rowEl.querySelectorAll('.sticky-left');\n const stickyRightCells = rowEl.querySelectorAll('.sticky-right');\n stickyLeftCells.forEach((el) => {\n left += (el as HTMLElement).offsetWidth;\n });\n stickyRightCells.forEach((el) => {\n right += (el as HTMLElement).offsetWidth;\n });\n } else {\n // Fall back to header row if no row element provided\n const host = this.grid as unknown as HTMLElement;\n const shadowRoot = host.shadowRoot;\n if (shadowRoot) {\n const headerCells = shadowRoot.querySelectorAll('.header-row .cell');\n headerCells.forEach((cell) => {\n if (cell.classList.contains('sticky-left')) {\n left += (cell as HTMLElement).offsetWidth;\n } else if (cell.classList.contains('sticky-right')) {\n right += (cell as HTMLElement).offsetWidth;\n }\n });\n }\n }\n\n // Skip horizontal scrolling if focused cell is pinned (it's always visible)\n const skipScroll =\n focusedCell?.classList.contains('sticky-left') || focusedCell?.classList.contains('sticky-right');\n\n return { left, right, skipScroll };\n }\n // #endregion\n}\n","/**\n * Status Bar Rendering Logic\n *\n * Pure functions for creating and updating the status bar UI.\n * Includes both info bar and aggregation row rendering.\n */\n\nimport { getAggregator } from '../../core/internal/aggregators';\nimport type { ColumnConfig } from '../../core/types';\nimport type {\n AggregationRowConfig,\n AggregatorConfig,\n AggregatorDefinition,\n PinnedRowsConfig,\n PinnedRowsContext,\n PinnedRowsPanel,\n} from './types';\n\n/**\n * Check if an aggregator definition is a full config object (with aggFunc and optional formatter).\n */\nfunction isAggregatorConfig(def: AggregatorDefinition): def is AggregatorConfig {\n return typeof def === 'object' && def !== null && 'aggFunc' in def;\n}\n\n/**\n * Creates the info bar DOM element with all configured panels.\n *\n * @param config - The status bar configuration\n * @param context - The current grid context for rendering\n * @returns The complete info bar element\n */\nexport function createInfoBarElement(config: PinnedRowsConfig, context: PinnedRowsContext): HTMLElement {\n const pinnedRows = document.createElement('div');\n pinnedRows.className = 'tbw-pinned-rows';\n pinnedRows.setAttribute('role', 'presentation');\n pinnedRows.setAttribute('aria-live', 'polite');\n\n const left = document.createElement('div');\n left.className = 'tbw-pinned-rows-left';\n\n const center = document.createElement('div');\n center.className = 'tbw-pinned-rows-center';\n\n const right = document.createElement('div');\n right.className = 'tbw-pinned-rows-right';\n\n // Default panels - row count\n if (config.showRowCount !== false) {\n const rowCount = document.createElement('span');\n rowCount.className = 'tbw-status-panel tbw-status-panel-row-count';\n rowCount.textContent = `Total: ${context.totalRows} rows`;\n left.appendChild(rowCount);\n }\n\n // Filtered count panel (only shows when filter is active)\n if (config.showFilteredCount && context.filteredRows !== context.totalRows) {\n const filteredCount = document.createElement('span');\n filteredCount.className = 'tbw-status-panel tbw-status-panel-filtered-count';\n filteredCount.textContent = `Filtered: ${context.filteredRows}`;\n left.appendChild(filteredCount);\n }\n\n // Selected count panel (only shows when rows are selected)\n if (config.showSelectedCount && context.selectedRows > 0) {\n const selectedCount = document.createElement('span');\n selectedCount.className = 'tbw-status-panel tbw-status-panel-selected-count';\n selectedCount.textContent = `Selected: ${context.selectedRows}`;\n right.appendChild(selectedCount);\n }\n\n // Render custom panels\n if (config.customPanels) {\n for (const panel of config.customPanels) {\n const panelEl = renderCustomPanel(panel, context);\n switch (panel.position) {\n case 'left':\n left.appendChild(panelEl);\n break;\n case 'center':\n center.appendChild(panelEl);\n break;\n case 'right':\n right.appendChild(panelEl);\n break;\n }\n }\n }\n\n pinnedRows.appendChild(left);\n pinnedRows.appendChild(center);\n pinnedRows.appendChild(right);\n\n return pinnedRows;\n}\n\n/**\n * Creates a container for aggregation rows at top or bottom.\n *\n * @param position - 'top' or 'bottom'\n * @returns The container element\n */\nexport function createAggregationContainer(position: 'top' | 'bottom'): HTMLElement {\n const container = document.createElement('div');\n container.className = `tbw-aggregation-rows tbw-aggregation-rows-${position}`;\n // Use presentation role since aggregation rows are outside the role=\"grid\" element for layout reasons\n container.setAttribute('role', 'presentation');\n return container;\n}\n\n/**\n * Renders aggregation rows into a container.\n *\n * @param container - The container to render into\n * @param rows - Aggregation row configurations\n * @param columns - Current column configuration\n * @param dataRows - Current row data for aggregation calculations\n */\nexport function renderAggregationRows(\n container: HTMLElement,\n rows: AggregationRowConfig[],\n columns: ColumnConfig[],\n dataRows: unknown[],\n): void {\n container.innerHTML = '';\n\n for (const rowConfig of rows) {\n const rowEl = document.createElement('div');\n rowEl.className = 'tbw-aggregation-row';\n // Use presentation role since aggregation rows are outside the role=\"grid\" element\n rowEl.setAttribute('role', 'presentation');\n if (rowConfig.id) {\n rowEl.setAttribute('data-aggregation-id', rowConfig.id);\n }\n\n if (rowConfig.fullWidth) {\n // Full-width mode: single cell spanning all columns\n const cell = document.createElement('div');\n cell.className = 'tbw-aggregation-cell tbw-aggregation-cell-full';\n cell.style.gridColumn = '1 / -1';\n cell.textContent = rowConfig.label || '';\n rowEl.appendChild(cell);\n } else {\n // Per-column mode: one cell per column with aggregated/static values\n for (const col of columns) {\n const cell = document.createElement('div');\n cell.className = 'tbw-aggregation-cell';\n cell.setAttribute('data-field', col.field);\n\n let value: unknown;\n let formatter: ((value: unknown, field: string, column?: ColumnConfig) => string) | undefined;\n\n // Check for aggregator first\n const aggDef = rowConfig.aggregators?.[col.field];\n if (aggDef) {\n // Handle both simple ref and full config object\n if (isAggregatorConfig(aggDef)) {\n const aggFn = getAggregator(aggDef.aggFunc);\n if (aggFn) {\n value = aggFn(dataRows, col.field, col);\n }\n formatter = aggDef.formatter;\n } else {\n const aggFn = getAggregator(aggDef);\n if (aggFn) {\n value = aggFn(dataRows, col.field, col);\n }\n }\n } else if (rowConfig.cells && Object.prototype.hasOwnProperty.call(rowConfig.cells, col.field)) {\n // Static or computed cell value\n const staticVal = rowConfig.cells[col.field];\n if (typeof staticVal === 'function') {\n value = staticVal(dataRows, col.field, col);\n } else {\n value = staticVal;\n }\n }\n\n // Apply formatter if provided, otherwise convert to string\n if (value != null) {\n cell.textContent = formatter ? formatter(value, col.field, col) : String(value);\n } else {\n cell.textContent = '';\n }\n rowEl.appendChild(cell);\n }\n }\n\n container.appendChild(rowEl);\n }\n}\n\n/**\n * Renders a custom panel element.\n *\n * @param panel - The panel definition\n * @param context - The current grid context\n * @returns The panel DOM element\n */\nfunction renderCustomPanel(panel: PinnedRowsPanel, context: PinnedRowsContext): HTMLElement {\n const panelEl = document.createElement('div');\n panelEl.className = 'tbw-status-panel tbw-status-panel-custom';\n panelEl.id = `status-panel-${panel.id}`;\n\n const content = panel.render(context);\n\n if (typeof content === 'string') {\n panelEl.innerHTML = content;\n } else {\n panelEl.appendChild(content);\n }\n\n return panelEl;\n}\n\n/**\n * Builds the status bar context from grid state and plugin states.\n *\n * @param rows - Current row data\n * @param columns - Current column configuration\n * @param grid - Grid element reference\n * @param selectionState - Optional selection plugin state\n * @param filterState - Optional filtering plugin state\n * @returns The status bar context\n */\nexport function buildContext(\n rows: unknown[],\n columns: unknown[],\n grid: HTMLElement,\n selectionState?: { selected: Set<number> } | null,\n filterState?: { cachedResult: unknown[] | null } | null,\n): PinnedRowsContext {\n return {\n totalRows: rows.length,\n filteredRows: filterState?.cachedResult?.length ?? rows.length,\n selectedRows: selectionState?.selected?.size ?? 0,\n columns: columns as PinnedRowsContext['columns'],\n rows,\n grid,\n };\n}\n\n// Keep old name as alias for backwards compatibility\nexport const createPinnedRowsElement = createInfoBarElement;\n","/**\n * Pinned Rows Plugin (Class-based)\n *\n * Adds info bars and aggregation rows to the grid.\n * - Info bar: Shows row counts, selection info, and custom panels\n * - Aggregation rows: Footer/header rows with computed values (sum, avg, etc.)\n */\n\nimport { BaseGridPlugin } from '../../core/plugin/base-plugin';\nimport type { ColumnConfig } from '../../core/types';\nimport { buildContext, createAggregationContainer, createInfoBarElement, renderAggregationRows } from './pinned-rows';\nimport styles from './pinned-rows.css?inline';\nimport type { AggregationRowConfig, PinnedRowsConfig, PinnedRowsContext, PinnedRowsPanel } from './types';\n\n/**\n * Pinned Rows Plugin for tbw-grid\n *\n * @example\n * ```ts\n * new PinnedRowsPlugin({\n * enabled: true,\n * position: 'bottom',\n * showRowCount: true,\n * showSelectedCount: true,\n * aggregationRows: [\n * { id: 'totals', position: 'bottom', values: { amount: 'sum' } },\n * ],\n * })\n * ```\n */\nexport class PinnedRowsPlugin extends BaseGridPlugin<PinnedRowsConfig> {\n readonly name = 'pinnedRows';\n override readonly version = '1.0.0';\n\n protected override get defaultConfig(): Partial<PinnedRowsConfig> {\n return {\n position: 'bottom',\n showRowCount: true,\n showSelectedCount: true,\n showFilteredCount: true,\n };\n }\n\n // #region Internal State\n private infoBarElement: HTMLElement | null = null;\n private topAggregationContainer: HTMLElement | null = null;\n private bottomAggregationContainer: HTMLElement | null = null;\n private footerWrapper: HTMLElement | null = null;\n // #endregion\n\n // #region Lifecycle\n override detach(): void {\n if (this.infoBarElement) {\n this.infoBarElement.remove();\n this.infoBarElement = null;\n }\n if (this.topAggregationContainer) {\n this.topAggregationContainer.remove();\n this.topAggregationContainer = null;\n }\n if (this.bottomAggregationContainer) {\n this.bottomAggregationContainer.remove();\n this.bottomAggregationContainer = null;\n }\n if (this.footerWrapper) {\n this.footerWrapper.remove();\n this.footerWrapper = null;\n }\n }\n // #endregion\n\n // #region Hooks\n override afterRender(): void {\n const shadowRoot = this.shadowRoot;\n if (!shadowRoot) return;\n\n // Use .tbw-scroll-area so footer is inside the horizontal scroll area,\n // otherwise fall back to .tbw-grid-content or root container\n const container =\n shadowRoot.querySelector('.tbw-scroll-area') ??\n shadowRoot.querySelector('.tbw-grid-content') ??\n shadowRoot.children[0];\n if (!container) return;\n\n // Build context with plugin states\n const selectionState = this.getSelectionState();\n const filterState = this.getFilterState();\n\n const context = buildContext(\n this.rows as unknown[],\n this.columns as unknown[],\n this.grid as unknown as HTMLElement,\n selectionState,\n filterState,\n );\n\n // #region Handle Aggregation Rows\n const aggregationRows = this.config.aggregationRows || [];\n const topRows = aggregationRows.filter((r) => r.position === 'top');\n const bottomRows = aggregationRows.filter((r) => r.position !== 'top');\n\n // Top aggregation rows\n if (topRows.length > 0) {\n if (!this.topAggregationContainer) {\n this.topAggregationContainer = createAggregationContainer('top');\n const header = shadowRoot.querySelector('.header');\n if (header && header.nextSibling) {\n container.insertBefore(this.topAggregationContainer, header.nextSibling);\n } else {\n container.appendChild(this.topAggregationContainer);\n }\n }\n renderAggregationRows(\n this.topAggregationContainer,\n topRows,\n this.visibleColumns as ColumnConfig[],\n this.rows as unknown[],\n );\n } else if (this.topAggregationContainer) {\n this.topAggregationContainer.remove();\n this.topAggregationContainer = null;\n }\n\n // Handle footer\n const hasInfoContent =\n this.config.showRowCount !== false ||\n (this.config.showSelectedCount && context.selectedRows > 0) ||\n (this.config.showFilteredCount && context.filteredRows !== context.totalRows) ||\n (this.config.customPanels && this.config.customPanels.length > 0);\n const hasBottomInfoBar = hasInfoContent && this.config.position !== 'top';\n const needsFooter = bottomRows.length > 0 || hasBottomInfoBar;\n\n // Handle top info bar\n if (hasInfoContent && this.config.position === 'top') {\n if (!this.infoBarElement) {\n this.infoBarElement = createInfoBarElement(this.config, context);\n container.insertBefore(this.infoBarElement, container.firstChild);\n } else {\n const newInfoBar = createInfoBarElement(this.config, context);\n this.infoBarElement.replaceWith(newInfoBar);\n this.infoBarElement = newInfoBar;\n }\n } else if (this.config.position === 'top' && this.infoBarElement) {\n this.infoBarElement.remove();\n this.infoBarElement = null;\n }\n\n // Create/manage footer wrapper\n if (needsFooter) {\n if (!this.footerWrapper) {\n this.footerWrapper = document.createElement('div');\n this.footerWrapper.className = 'tbw-footer';\n container.appendChild(this.footerWrapper);\n }\n\n this.footerWrapper.innerHTML = '';\n\n if (bottomRows.length > 0) {\n if (!this.bottomAggregationContainer) {\n this.bottomAggregationContainer = createAggregationContainer('bottom');\n }\n this.footerWrapper.appendChild(this.bottomAggregationContainer);\n renderAggregationRows(\n this.bottomAggregationContainer,\n bottomRows,\n this.visibleColumns as ColumnConfig[],\n this.rows as unknown[],\n );\n }\n\n if (hasBottomInfoBar) {\n this.infoBarElement = createInfoBarElement(this.config, context);\n this.footerWrapper.appendChild(this.infoBarElement);\n }\n } else {\n this.cleanupFooter();\n }\n // #endregion\n }\n // #endregion\n\n // #region Private Methods\n private cleanup(): void {\n if (this.infoBarElement) {\n this.infoBarElement.remove();\n this.infoBarElement = null;\n }\n if (this.topAggregationContainer) {\n this.topAggregationContainer.remove();\n this.topAggregationContainer = null;\n }\n if (this.bottomAggregationContainer) {\n this.bottomAggregationContainer.remove();\n this.bottomAggregationContainer = null;\n }\n if (this.footerWrapper) {\n this.footerWrapper.remove();\n this.footerWrapper = null;\n }\n }\n\n private cleanupFooter(): void {\n if (this.footerWrapper) {\n this.footerWrapper.remove();\n this.footerWrapper = null;\n }\n if (this.bottomAggregationContainer) {\n this.bottomAggregationContainer.remove();\n this.bottomAggregationContainer = null;\n }\n if (this.infoBarElement && this.config.position !== 'top') {\n this.infoBarElement.remove();\n this.infoBarElement = null;\n }\n }\n\n private getSelectionState(): { selected: Set<number> } | null {\n // Try to get selection plugin state\n try {\n const grid = this.grid as any;\n return grid?.getPluginState?.('selection') ?? null;\n } catch {\n return null;\n }\n }\n\n private getFilterState(): { cachedResult: unknown[] | null } | null {\n try {\n const grid = this.grid as any;\n return grid?.getPluginState?.('filtering') ?? null;\n } catch {\n return null;\n }\n }\n // #endregion\n\n // #region Public API\n /**\n * Refresh the status bar to reflect current grid state.\n */\n refresh(): void {\n this.requestRender();\n }\n\n /**\n * Get the current status bar context.\n * @returns The context with row counts and other info\n */\n getContext(): PinnedRowsContext {\n const selectionState = this.getSelectionState();\n const filterState = this.getFilterState();\n\n return buildContext(\n this.rows as unknown[],\n this.columns as unknown[],\n this.grid as unknown as HTMLElement,\n selectionState,\n filterState,\n );\n }\n\n /**\n * Add a custom panel to the info bar.\n * @param panel - The panel configuration to add\n */\n addPanel(panel: PinnedRowsPanel): void {\n if (!this.config.customPanels) {\n this.config.customPanels = [];\n }\n this.config.customPanels.push(panel);\n this.requestRender();\n }\n\n /**\n * Remove a custom panel by ID.\n * @param id - The panel ID to remove\n */\n removePanel(id: string): void {\n if (this.config.customPanels) {\n this.config.customPanels = this.config.customPanels.filter((p) => p.id !== id);\n this.requestRender();\n }\n }\n\n /**\n * Add an aggregation row.\n * @param row - The aggregation row configuration\n */\n addAggregationRow(row: AggregationRowConfig): void {\n if (!this.config.aggregationRows) {\n this.config.aggregationRows = [];\n }\n this.config.aggregationRows.push(row);\n this.requestRender();\n }\n\n /**\n * Remove an aggregation row by ID.\n * @param id - The aggregation row ID to remove\n */\n removeAggregationRow(id: string): void {\n if (this.config.aggregationRows) {\n this.config.aggregationRows = this.config.aggregationRows.filter((r) => r.id !== id);\n this.requestRender();\n }\n }\n // #endregion\n\n // #region Styles\n override readonly styles = styles;\n // #endregion\n}\n","import { getValueAggregator } from '../../core/internal/aggregators';\nimport type { PivotConfig } from './types';\n\n// Re-export for backward compatibility within pivot plugin\nexport const getPivotAggregator = getValueAggregator;\n\nexport function validatePivotConfig(config: PivotConfig): string[] {\n const errors: string[] = [];\n\n if (!config.rowGroupFields?.length && !config.columnGroupFields?.length) {\n errors.push('At least one row or column group field is required');\n }\n\n if (!config.valueFields?.length) {\n errors.push('At least one value field is required');\n }\n\n return errors;\n}\n\nexport function createValueKey(columnValues: string[], valueField: string): string {\n return [...columnValues, valueField].join('|');\n}\n","import { createValueKey, getPivotAggregator } from './pivot-model';\nimport type { PivotConfig, PivotResult, PivotRow, PivotValueField } from './types';\n\nexport type PivotDataRow = Record<string, unknown>;\n\n/**\n * Build a hierarchical pivot result from flat data.\n * Supports multiple row group fields for nested hierarchy.\n */\nexport function buildPivot(rows: PivotDataRow[], config: PivotConfig): PivotResult {\n const rowGroupFields = config.rowGroupFields ?? [];\n const columnGroupFields = config.columnGroupFields ?? [];\n const valueFields = config.valueFields ?? [];\n\n // Get unique column combinations\n const columnKeys = getUniqueColumnKeys(rows, columnGroupFields);\n\n // Build hierarchical pivot rows\n const pivotRows = buildHierarchicalPivotRows(\n rows,\n rowGroupFields,\n columnGroupFields,\n columnKeys,\n valueFields,\n 0, // starting depth\n '', // parent key prefix\n );\n\n // Calculate grand totals\n const totals = calculateTotals(pivotRows, columnKeys, valueFields);\n const grandTotal = Object.values(totals).reduce((a, b) => a + b, 0);\n\n return {\n rows: pivotRows,\n columnKeys,\n totals,\n grandTotal,\n };\n}\n\n/**\n * Get unique column key combinations from the data.\n */\nexport function getUniqueColumnKeys(rows: PivotDataRow[], columnFields: string[]): string[] {\n if (columnFields.length === 0) return ['value'];\n\n const keys = new Set<string>();\n for (const row of rows) {\n const key = columnFields.map((f) => String(row[f] ?? '')).join('|');\n keys.add(key);\n }\n return [...keys].sort();\n}\n\n/**\n * Group rows by a single field.\n */\nexport function groupByField(rows: PivotDataRow[], field: string): Map<string, PivotDataRow[]> {\n const groups = new Map<string, PivotDataRow[]>();\n\n for (const row of rows) {\n const key = String(row[field] ?? '');\n const existing = groups.get(key);\n if (existing) {\n existing.push(row);\n } else {\n groups.set(key, [row]);\n }\n }\n\n return groups;\n}\n\n/**\n * Group rows by multiple fields (legacy flat grouping).\n */\nexport function groupByFields(rows: PivotDataRow[], fields: string[]): Map<string, PivotDataRow[]> {\n const groups = new Map<string, PivotDataRow[]>();\n\n for (const row of rows) {\n const key = fields.map((f) => String(row[f] ?? '')).join('|');\n const existing = groups.get(key);\n if (existing) {\n existing.push(row);\n } else {\n groups.set(key, [row]);\n }\n }\n\n return groups;\n}\n\n/**\n * Build hierarchical pivot rows recursively.\n * Each level of rowGroupFields creates a new depth level.\n */\nexport function buildHierarchicalPivotRows(\n rows: PivotDataRow[],\n rowGroupFields: string[],\n columnFields: string[],\n columnKeys: string[],\n valueFields: PivotValueField[],\n depth: number,\n parentKey: string,\n): PivotRow[] {\n const result: PivotRow[] = [];\n\n // If no more row group fields, we're at the leaf level - aggregate the data\n if (rowGroupFields.length === 0) {\n // This shouldn't normally happen as we need at least one grouping field\n // But handle it by creating a single aggregated row\n const values = aggregateValues(rows, columnFields, columnKeys, valueFields);\n const total = calculateRowTotal(values);\n result.push({\n rowKey: parentKey || 'all',\n rowLabel: parentKey || 'All',\n depth,\n values,\n total,\n isGroup: false,\n rowCount: rows.length,\n });\n return result;\n }\n\n // Get the current grouping field\n const currentField = rowGroupFields[0];\n const remainingFields = rowGroupFields.slice(1);\n const hasChildren = remainingFields.length > 0;\n\n // Group rows by current field\n const grouped = groupByField(rows, currentField);\n\n for (const [groupValue, groupRows] of grouped) {\n const rowKey = parentKey ? `${parentKey}|${groupValue}` : groupValue;\n\n // Aggregate values for this group (sum of all child rows)\n const values = aggregateValues(groupRows, columnFields, columnKeys, valueFields);\n const total = calculateRowTotal(values);\n\n // Build children if there are more grouping levels\n let children: PivotRow[] | undefined;\n if (hasChildren) {\n children = buildHierarchicalPivotRows(\n groupRows,\n remainingFields,\n columnFields,\n columnKeys,\n valueFields,\n depth + 1,\n rowKey,\n );\n }\n\n result.push({\n rowKey,\n rowLabel: groupValue || '(blank)',\n depth,\n values,\n total,\n isGroup: hasChildren,\n children,\n rowCount: groupRows.length,\n });\n }\n\n return result;\n}\n\n/**\n * Aggregate values for a set of rows across all column keys.\n */\nexport function aggregateValues(\n rows: PivotDataRow[],\n columnFields: string[],\n columnKeys: string[],\n valueFields: PivotValueField[],\n): Record<string, number | null> {\n const values: Record<string, number | null> = {};\n\n for (const colKey of columnKeys) {\n for (const vf of valueFields) {\n // Filter rows that match this column key\n const matchingRows =\n columnFields.length > 0\n ? rows.filter((r) => columnFields.map((f) => String(r[f] ?? '')).join('|') === colKey)\n : rows;\n\n const nums = matchingRows.map((r) => Number(r[vf.field]) || 0);\n const aggregator = getPivotAggregator(vf.aggFunc);\n const aggregatedResult = nums.length > 0 ? aggregator(nums) : null;\n\n const valueKey = createValueKey([colKey], vf.field);\n values[valueKey] = aggregatedResult;\n }\n }\n\n return values;\n}\n\n/**\n * Calculate the total for a row's values.\n */\nexport function calculateRowTotal(values: Record<string, number | null>): number {\n let sum = 0;\n for (const val of Object.values(values)) {\n sum += val ?? 0;\n }\n return sum;\n}\n\n/**\n * Legacy flat pivot row building (for backwards compatibility).\n */\nexport function buildPivotRows(\n groupedData: Map<string, PivotDataRow[]>,\n columnFields: string[],\n columnKeys: string[],\n valueFields: PivotValueField[],\n depth: number,\n): PivotRow[] {\n const result: PivotRow[] = [];\n\n for (const [rowKey, groupRows] of groupedData) {\n const values = aggregateValues(groupRows, columnFields, columnKeys, valueFields);\n const total = calculateRowTotal(values);\n\n result.push({\n rowKey,\n rowLabel: rowKey || '(blank)',\n depth,\n values,\n total,\n isGroup: false,\n rowCount: groupRows.length,\n });\n }\n\n return result;\n}\n\n/**\n * Calculate grand totals across all pivot rows.\n */\nexport function calculateTotals(\n pivotRows: PivotRow[],\n columnKeys: string[],\n valueFields: PivotValueField[],\n): Record<string, number> {\n const totals: Record<string, number> = {};\n\n // Recursively sum all rows (including nested children)\n function sumRows(rows: PivotRow[]) {\n for (const row of rows) {\n // Only count leaf rows to avoid double-counting\n if (!row.isGroup || !row.children?.length) {\n for (const colKey of columnKeys) {\n for (const vf of valueFields) {\n const valueKey = createValueKey([colKey], vf.field);\n totals[valueKey] = (totals[valueKey] ?? 0) + (row.values[valueKey] ?? 0);\n }\n }\n } else if (row.children) {\n sumRows(row.children);\n }\n }\n }\n\n sumRows(pivotRows);\n return totals;\n}\n\n/**\n * Flatten hierarchical pivot rows for rendering.\n * Respects expanded state - only includes children of expanded groups.\n */\nexport function flattenPivotRows(rows: PivotRow[], expandedKeys?: Set<string>, defaultExpanded = true): PivotRow[] {\n const result: PivotRow[] = [];\n\n function flatten(row: PivotRow) {\n result.push(row);\n\n // Check if this group is expanded\n const isExpanded = expandedKeys ? expandedKeys.has(row.rowKey) : defaultExpanded;\n\n // Only include children if expanded\n if (row.children && isExpanded) {\n for (const child of row.children) {\n flatten(child);\n }\n }\n }\n\n for (const row of rows) {\n flatten(row);\n }\n\n return result;\n}\n\n/**\n * Get all group keys from pivot rows (for expand all / collapse all).\n */\nexport function getAllGroupKeys(rows: PivotRow[]): string[] {\n const keys: string[] = [];\n\n function collectKeys(row: PivotRow) {\n if (row.isGroup) {\n keys.push(row.rowKey);\n }\n if (row.children) {\n for (const child of row.children) {\n collectKeys(child);\n }\n }\n }\n\n for (const row of rows) {\n collectKeys(row);\n }\n\n return keys;\n}\n","/**\n * Pivot Tool Panel Rendering\n *\n * Pure functions for rendering the pivot configuration panel.\n * Separated from PivotPlugin for better code organization.\n */\n\nimport type { AggFunc, PivotConfig, PivotValueField } from './types';\n\n/** All available aggregation functions */\nexport const AGG_FUNCS: AggFunc[] = ['sum', 'avg', 'count', 'min', 'max', 'first', 'last'];\n\n/** Field info for available fields */\nexport interface FieldInfo {\n field: string;\n header: string;\n}\n\n/** Callbacks for panel interactions */\nexport interface PanelCallbacks {\n onTogglePivot: (enabled: boolean) => void;\n onAddFieldToZone: (field: string, zone: 'rowGroups' | 'columnGroups') => void;\n onRemoveFieldFromZone: (field: string, zone: 'rowGroups' | 'columnGroups') => void;\n onAddValueField: (field: string, aggFunc: AggFunc) => void;\n onRemoveValueField: (field: string) => void;\n onUpdateValueAggFunc: (field: string, aggFunc: AggFunc) => void;\n onOptionChange: (option: 'showTotals' | 'showGrandTotal', value: boolean) => void;\n getAvailableFields: () => FieldInfo[];\n}\n\n/** Internal context passed to rendering functions */\ninterface RenderContext {\n config: PivotConfig;\n callbacks: PanelCallbacks;\n signal: AbortSignal;\n}\n\n/**\n * Render the complete pivot panel content.\n * Returns a cleanup function that removes all event listeners and DOM elements.\n */\nexport function renderPivotPanel(\n container: HTMLElement,\n config: PivotConfig,\n isActive: boolean,\n callbacks: PanelCallbacks,\n): () => void {\n // Create AbortController for automatic listener cleanup\n const controller = new AbortController();\n const ctx: RenderContext = { config, callbacks, signal: controller.signal };\n\n const wrapper = document.createElement('div');\n wrapper.className = 'tbw-pivot-panel';\n\n // Options section (at top, includes pivot toggle)\n wrapper.appendChild(createSection('Options', () => createOptionsPanel(isActive, ctx)));\n\n // Row Groups section\n wrapper.appendChild(createSection('Row Groups', () => createFieldZone('rowGroups', ctx)));\n\n // Column Groups section\n wrapper.appendChild(createSection('Column Groups', () => createFieldZone('columnGroups', ctx)));\n\n // Values section\n wrapper.appendChild(createSection('Values', () => createValuesZone(ctx)));\n\n // Available fields section\n wrapper.appendChild(createSection('Available Fields', () => createAvailableFieldsZone(ctx)));\n\n container.appendChild(wrapper);\n\n // Cleanup: abort all listeners, then remove DOM\n return () => {\n controller.abort();\n wrapper.remove();\n };\n}\n\n/**\n * Create a collapsible section wrapper.\n */\nfunction createSection(title: string, contentFactory: () => HTMLElement): HTMLElement {\n const section = document.createElement('div');\n section.className = 'tbw-pivot-section';\n\n const header = document.createElement('div');\n header.className = 'tbw-pivot-section-header';\n header.textContent = title;\n\n const content = document.createElement('div');\n content.className = 'tbw-pivot-section-content';\n content.appendChild(contentFactory());\n\n section.appendChild(header);\n section.appendChild(content);\n\n return section;\n}\n\n/**\n * Create a drop zone for row/column group fields.\n */\nfunction createFieldZone(zoneType: 'rowGroups' | 'columnGroups', ctx: RenderContext): HTMLElement {\n const { config, callbacks, signal } = ctx;\n const zone = document.createElement('div');\n zone.className = 'tbw-pivot-drop-zone';\n zone.setAttribute('data-zone', zoneType);\n\n const currentFields = zoneType === 'rowGroups' ? (config.rowGroupFields ?? []) : (config.columnGroupFields ?? []);\n\n if (currentFields.length === 0) {\n const placeholder = document.createElement('div');\n placeholder.className = 'tbw-pivot-placeholder';\n placeholder.textContent = 'Drag fields here or click to add';\n zone.appendChild(placeholder);\n } else {\n for (const field of currentFields) {\n zone.appendChild(createFieldChip(field, zoneType, ctx));\n }\n }\n\n // Drop handling\n zone.addEventListener(\n 'dragover',\n (e) => {\n e.preventDefault();\n zone.classList.add('drag-over');\n },\n { signal },\n );\n\n zone.addEventListener(\n 'dragleave',\n () => {\n zone.classList.remove('drag-over');\n },\n { signal },\n );\n\n zone.addEventListener(\n 'drop',\n (e) => {\n e.preventDefault();\n zone.classList.remove('drag-over');\n\n const field = e.dataTransfer?.getData('text/plain');\n if (field) {\n callbacks.onAddFieldToZone(field, zoneType);\n }\n },\n { signal },\n );\n\n return zone;\n}\n\n/**\n * Create a field chip for row/column zones.\n */\nfunction createFieldChip(field: string, zoneType: 'rowGroups' | 'columnGroups', ctx: RenderContext): HTMLElement {\n const { callbacks, signal } = ctx;\n const chip = document.createElement('div');\n chip.className = 'tbw-pivot-field-chip';\n chip.draggable = true;\n\n const fieldInfo = callbacks.getAvailableFields().find((f) => f.field === field);\n const label = document.createElement('span');\n label.className = 'tbw-pivot-chip-label';\n label.textContent = fieldInfo?.header ?? field;\n\n const removeBtn = document.createElement('button');\n removeBtn.className = 'tbw-pivot-chip-remove';\n removeBtn.innerHTML = '×';\n removeBtn.title = 'Remove field';\n removeBtn.addEventListener(\n 'click',\n (e) => {\n e.stopPropagation();\n callbacks.onRemoveFieldFromZone(field, zoneType);\n },\n { signal },\n );\n\n chip.appendChild(label);\n chip.appendChild(removeBtn);\n\n // Drag handling for reordering\n chip.addEventListener(\n 'dragstart',\n (e) => {\n e.dataTransfer?.setData('text/plain', field);\n e.dataTransfer?.setData('source-zone', zoneType);\n chip.classList.add('dragging');\n },\n { signal },\n );\n\n chip.addEventListener(\n 'dragend',\n () => {\n chip.classList.remove('dragging');\n },\n { signal },\n );\n\n return chip;\n}\n\n/**\n * Create the values zone with aggregation controls.\n */\nfunction createValuesZone(ctx: RenderContext): HTMLElement {\n const { config, callbacks, signal } = ctx;\n const zone = document.createElement('div');\n zone.className = 'tbw-pivot-drop-zone tbw-pivot-values-zone';\n zone.setAttribute('data-zone', 'values');\n\n const currentValues = config.valueFields ?? [];\n\n if (currentValues.length === 0) {\n const placeholder = document.createElement('div');\n placeholder.className = 'tbw-pivot-placeholder';\n placeholder.textContent = 'Drag numeric fields here for aggregation';\n zone.appendChild(placeholder);\n } else {\n for (const valueField of currentValues) {\n zone.appendChild(createValueChip(valueField, ctx));\n }\n }\n\n // Drop handling with signal for cleanup\n zone.addEventListener(\n 'dragover',\n (e) => {\n e.preventDefault();\n zone.classList.add('drag-over');\n },\n { signal },\n );\n\n zone.addEventListener(\n 'dragleave',\n () => {\n zone.classList.remove('drag-over');\n },\n { signal },\n );\n\n zone.addEventListener(\n 'drop',\n (e) => {\n e.preventDefault();\n zone.classList.remove('drag-over');\n const field = e.dataTransfer?.getData('text/plain');\n if (field) {\n callbacks.onAddValueField(field, 'sum');\n }\n },\n { signal },\n );\n\n return zone;\n}\n\n/**\n * Create a value chip with aggregation selector.\n */\nfunction createValueChip(valueField: PivotValueField, ctx: RenderContext): HTMLElement {\n const { callbacks, signal } = ctx;\n const chip = document.createElement('div');\n chip.className = 'tbw-pivot-field-chip tbw-pivot-value-chip';\n\n const fieldInfo = callbacks.getAvailableFields().find((f) => f.field === valueField.field);\n\n const labelWrapper = document.createElement('div');\n labelWrapper.className = 'tbw-pivot-value-label-wrapper';\n\n const label = document.createElement('span');\n label.className = 'tbw-pivot-chip-label';\n label.textContent = fieldInfo?.header ?? valueField.field;\n\n const aggSelect = document.createElement('select');\n aggSelect.className = 'tbw-pivot-agg-select';\n aggSelect.title = 'Aggregation function';\n\n for (const aggFunc of AGG_FUNCS) {\n const option = document.createElement('option');\n option.value = aggFunc;\n option.textContent = aggFunc.toUpperCase();\n option.selected = aggFunc === valueField.aggFunc;\n aggSelect.appendChild(option);\n }\n\n aggSelect.addEventListener(\n 'change',\n () => {\n callbacks.onUpdateValueAggFunc(valueField.field, aggSelect.value as AggFunc);\n },\n { signal },\n );\n\n const removeBtn = document.createElement('button');\n removeBtn.className = 'tbw-pivot-chip-remove';\n removeBtn.innerHTML = '×';\n removeBtn.title = 'Remove value field';\n removeBtn.addEventListener(\n 'click',\n (e) => {\n e.stopPropagation();\n callbacks.onRemoveValueField(valueField.field);\n },\n { signal },\n );\n\n labelWrapper.appendChild(label);\n labelWrapper.appendChild(aggSelect);\n\n chip.appendChild(labelWrapper);\n chip.appendChild(removeBtn);\n\n return chip;\n}\n\n/**\n * Create the available fields zone.\n */\nfunction createAvailableFieldsZone(ctx: RenderContext): HTMLElement {\n const { config, callbacks, signal } = ctx;\n const zone = document.createElement('div');\n zone.className = 'tbw-pivot-available-fields';\n\n const allFields = callbacks.getAvailableFields();\n const usedFields = new Set([\n ...(config.rowGroupFields ?? []),\n ...(config.columnGroupFields ?? []),\n ...(config.valueFields?.map((v) => v.field) ?? []),\n ]);\n\n // Filter to show only unused fields\n const availableFields = allFields.filter((f) => !usedFields.has(f.field));\n\n if (availableFields.length === 0) {\n const empty = document.createElement('div');\n empty.className = 'tbw-pivot-placeholder';\n empty.textContent = 'All fields are in use';\n zone.appendChild(empty);\n } else {\n for (const field of availableFields) {\n const chip = document.createElement('div');\n chip.className = 'tbw-pivot-field-chip available';\n chip.textContent = field.header;\n chip.draggable = true;\n chip.title = `Drag to add \"${field.field}\" to a zone`;\n\n chip.addEventListener(\n 'dragstart',\n (e) => {\n e.dataTransfer?.setData('text/plain', field.field);\n chip.classList.add('dragging');\n },\n { signal },\n );\n\n chip.addEventListener(\n 'dragend',\n () => {\n chip.classList.remove('dragging');\n },\n { signal },\n );\n\n zone.appendChild(chip);\n }\n }\n\n return zone;\n}\n\n/**\n * Create the options panel with pivot toggle and checkboxes for totals.\n */\nfunction createOptionsPanel(isActive: boolean, ctx: RenderContext): HTMLElement {\n const { config, callbacks, signal } = ctx;\n const panel = document.createElement('div');\n panel.className = 'tbw-pivot-options';\n\n // Pivot Mode toggle\n panel.appendChild(\n createCheckbox(\n 'Enable Pivot View',\n isActive,\n (checked) => {\n callbacks.onTogglePivot(checked);\n },\n signal,\n ),\n );\n\n // Show Totals checkbox\n panel.appendChild(\n createCheckbox(\n 'Show Row Totals',\n config.showTotals ?? true,\n (checked) => {\n callbacks.onOptionChange('showTotals', checked);\n },\n signal,\n ),\n );\n\n // Show Grand Total checkbox\n panel.appendChild(\n createCheckbox(\n 'Show Grand Total',\n config.showGrandTotal ?? true,\n (checked) => {\n callbacks.onOptionChange('showGrandTotal', checked);\n },\n signal,\n ),\n );\n\n return panel;\n}\n\n/**\n * Create a checkbox with label.\n */\nfunction createCheckbox(\n label: string,\n checked: boolean,\n onChange: (checked: boolean) => void,\n signal: AbortSignal,\n): HTMLElement {\n const wrapper = document.createElement('label');\n wrapper.className = 'tbw-pivot-checkbox';\n\n const input = document.createElement('input');\n input.type = 'checkbox';\n input.checked = checked;\n input.addEventListener('change', () => onChange(input.checked), { signal });\n\n const span = document.createElement('span');\n span.textContent = label;\n\n wrapper.appendChild(input);\n wrapper.appendChild(span);\n\n return wrapper;\n}\n","/**\n * Pivot Row Rendering\n *\n * Pure functions for rendering pivot rows (group rows, leaf rows, grand total).\n * Separated from PivotPlugin for better code organization.\n */\n\nimport type { ColumnConfig, IconValue } from '../../core/types';\n\n/** Row data with pivot metadata */\nexport interface PivotRowData {\n __pivotRowKey?: string;\n __pivotLabel?: string;\n __pivotDepth?: number;\n __pivotIndent?: number;\n __pivotExpanded?: boolean;\n __pivotHasChildren?: boolean;\n __pivotRowCount?: number;\n __pivotIsGrandTotal?: boolean;\n [key: string]: unknown;\n}\n\n/** Context for row rendering */\nexport interface RowRenderContext {\n columns: ColumnConfig[];\n onToggle: (key: string) => void;\n resolveIcon: (iconKey: 'expand' | 'collapse') => IconValue;\n setIcon: (element: HTMLElement, icon: IconValue) => void;\n}\n\n/**\n * Render a pivot group row (has children, can expand/collapse).\n */\nexport function renderPivotGroupRow(row: PivotRowData, rowEl: HTMLElement, ctx: RowRenderContext): boolean {\n rowEl.className = 'pivot-group-row';\n rowEl.setAttribute('data-pivot-depth', String(row.__pivotDepth ?? 0));\n rowEl.setAttribute('data-pivot-key', String(row.__pivotRowKey ?? ''));\n rowEl.setAttribute('role', 'row');\n // Note: aria-expanded is not set here because it's only valid in treegrid, not grid\n // The expand/collapse state is conveyed via the toggle button's aria-label\n rowEl.innerHTML = '';\n\n ctx.columns.forEach((col, colIdx) => {\n const cell = document.createElement('div');\n cell.className = 'cell';\n cell.setAttribute('data-col', String(colIdx));\n cell.setAttribute('role', 'gridcell');\n\n if (colIdx === 0) {\n // First column: indent + toggle + label + count\n const indent = Number(row.__pivotIndent) || 0;\n cell.style.paddingLeft = `${indent}px`;\n\n // Toggle button\n const rowKey = String(row.__pivotRowKey);\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'pivot-toggle';\n btn.setAttribute('aria-label', row.__pivotExpanded ? 'Collapse group' : 'Expand group');\n ctx.setIcon(btn, ctx.resolveIcon(row.__pivotExpanded ? 'collapse' : 'expand'));\n btn.addEventListener('click', (e) => {\n e.stopPropagation();\n ctx.onToggle(rowKey);\n });\n cell.appendChild(btn);\n\n // Group label\n const label = document.createElement('span');\n label.className = 'pivot-label';\n label.textContent = String(row.__pivotLabel ?? '');\n cell.appendChild(label);\n\n // Row count\n const count = document.createElement('span');\n count.className = 'pivot-count';\n count.textContent = ` (${Number(row.__pivotRowCount) || 0})`;\n cell.appendChild(count);\n } else {\n // Other columns: render value\n const value = row[col.field];\n cell.textContent = value != null ? String(value) : '';\n }\n\n rowEl.appendChild(cell);\n });\n\n return true;\n}\n\n/**\n * Render a pivot leaf row (no children, just indentation).\n */\nexport function renderPivotLeafRow(row: PivotRowData, rowEl: HTMLElement, columns: ColumnConfig[]): boolean {\n rowEl.className = 'pivot-leaf-row';\n rowEl.setAttribute('data-pivot-depth', String(row.__pivotDepth ?? 0));\n rowEl.setAttribute('data-pivot-key', String(row.__pivotRowKey ?? ''));\n rowEl.innerHTML = '';\n\n columns.forEach((col, colIdx) => {\n const cell = document.createElement('div');\n cell.className = 'cell';\n cell.setAttribute('data-col', String(colIdx));\n cell.setAttribute('role', 'gridcell');\n\n if (colIdx === 0) {\n // First column: indent + label (no toggle for leaves)\n const indent = Number(row.__pivotIndent) || 0;\n // Add extra indent for alignment with toggle button\n cell.style.paddingLeft = `${indent + 20}px`;\n\n const label = document.createElement('span');\n label.className = 'pivot-label';\n label.textContent = String(row.__pivotLabel ?? '');\n cell.appendChild(label);\n } else {\n // Other columns: render value\n const value = row[col.field];\n cell.textContent = value != null ? String(value) : '';\n }\n\n rowEl.appendChild(cell);\n });\n\n return true;\n}\n\n/**\n * Render the grand total row.\n */\nexport function renderPivotGrandTotalRow(row: PivotRowData, rowEl: HTMLElement, columns: ColumnConfig[]): boolean {\n rowEl.className = 'pivot-grand-total-row';\n // Use role=presentation since grand total is rendered outside the role=grid element\n rowEl.setAttribute('role', 'presentation');\n rowEl.innerHTML = '';\n\n columns.forEach((col, colIdx) => {\n const cell = document.createElement('div');\n cell.className = 'cell';\n cell.setAttribute('data-col', String(colIdx));\n // No role attribute - parent row has role=presentation so children don't need grid semantics\n\n if (colIdx === 0) {\n // First column: Grand Total label\n const label = document.createElement('span');\n label.className = 'pivot-label';\n label.textContent = 'Grand Total';\n cell.appendChild(label);\n } else {\n // Other columns: render totals\n const value = row[col.field];\n cell.textContent = value != null ? String(value) : '';\n }\n\n rowEl.appendChild(cell);\n });\n\n return true;\n}\n","/**\n * Pivot Plugin (Class-based)\n *\n * Provides pivot table functionality for tbw-grid.\n * Transforms flat data into grouped, aggregated pivot views.\n * Includes a tool panel for interactive pivot configuration.\n */\n\nimport { BaseGridPlugin } from '../../core/plugin/base-plugin';\nimport type { ColumnConfig, GridConfig, ToolPanelDefinition } from '../../core/types';\nimport { buildPivot, flattenPivotRows, getAllGroupKeys, type PivotDataRow } from './pivot-engine';\nimport { createValueKey, validatePivotConfig } from './pivot-model';\nimport { renderPivotPanel, type FieldInfo, type PanelCallbacks } from './pivot-panel';\nimport { renderPivotGrandTotalRow, renderPivotGroupRow, renderPivotLeafRow, type PivotRowData } from './pivot-rows';\nimport type { AggFunc, ExpandCollapseAnimation, PivotConfig, PivotResult, PivotValueField } from './types';\n\n// Import CSS as inline string (Vite handles this)\nimport styles from './pivot.css?inline';\n\n/** Extended grid interface with column access */\ninterface GridWithColumns {\n shadowRoot: ShadowRoot | null;\n effectiveConfig?: GridConfig;\n getAllColumns(): Array<{ field: string; header: string; visible: boolean }>;\n columns: ColumnConfig[];\n rows: unknown[];\n requestRender(): void;\n openToolPanel(id: string): void;\n closeToolPanel(): void;\n toggleToolPanel(id: string): void;\n activeToolPanel: string | undefined;\n}\n\n/**\n * Pivot Plugin for tbw-grid\n *\n * @example\n * ```ts\n * new PivotPlugin({\n * rowGroupFields: ['category'],\n * columnGroupFields: ['region'],\n * valueFields: [{ field: 'sales', aggFunc: 'sum' }]\n * })\n * ```\n */\nexport class PivotPlugin extends BaseGridPlugin<PivotConfig> {\n readonly name = 'pivot';\n override readonly version = '1.0.0';\n\n /** Tool panel ID for shell integration */\n static readonly PANEL_ID = 'pivot';\n\n protected override get defaultConfig(): Partial<PivotConfig> {\n return {\n active: true,\n showTotals: true,\n showGrandTotal: true,\n showToolPanel: true,\n animation: 'slide',\n };\n }\n\n // #region Internal State\n private isActive = false;\n private hasInitialized = false;\n private pivotResult: PivotResult | null = null;\n private fieldHeaderMap: Map<string, string> = new Map();\n private expandedKeys: Set<string> = new Set();\n private defaultExpanded = true;\n private originalColumns: Array<{ field: string; header: string }> = [];\n private panelContainer: HTMLElement | null = null;\n private grandTotalFooter: HTMLElement | null = null;\n private previousVisibleKeys = new Set<string>();\n private keysToAnimate = new Set<string>();\n\n /**\n * Check if the plugin has valid pivot configuration (at least value fields).\n */\n private hasValidPivotConfig(): boolean {\n return (this.config.valueFields?.length ?? 0) > 0;\n }\n\n /**\n * Get animation style respecting grid-level animation mode.\n */\n private get animationStyle(): ExpandCollapseAnimation {\n const gridEl = this.grid as unknown as GridWithColumns;\n const mode = gridEl.effectiveConfig?.animation?.mode ?? 'reduced-motion';\n\n if (mode === false || mode === 'off') return false;\n if (mode !== true && mode !== 'on') {\n const host = this.shadowRoot?.host as HTMLElement | undefined;\n if (host && getComputedStyle(host).getPropertyValue('--tbw-animation-enabled').trim() === '0') {\n return false;\n }\n }\n return this.config.animation ?? 'slide';\n }\n\n // #endregion\n\n // #region Lifecycle\n\n override detach(): void {\n this.isActive = false;\n this.hasInitialized = false;\n this.pivotResult = null;\n this.fieldHeaderMap.clear();\n this.originalColumns = [];\n this.panelContainer = null;\n this.cleanupGrandTotalFooter();\n this.previousVisibleKeys.clear();\n this.keysToAnimate.clear();\n }\n\n // #endregion\n\n // #region Shell Integration\n\n override getToolPanel(): ToolPanelDefinition | undefined {\n // Allow users to disable the tool panel for programmatic-only pivot\n // Check userConfig first (works before attach), then merged config\n const showToolPanel = this.config?.showToolPanel ?? this.userConfig?.showToolPanel ?? true;\n if (showToolPanel === false) {\n return undefined;\n }\n\n return {\n id: PivotPlugin.PANEL_ID,\n title: 'Pivot',\n icon: '⊞',\n tooltip: 'Configure pivot table',\n order: 90,\n render: (container) => this.renderPanel(container),\n };\n }\n\n // #endregion\n\n // #region Hooks\n\n override processRows(rows: readonly unknown[]): PivotDataRow[] {\n // Auto-enable pivot if config.active is true and we have valid pivot fields\n if (!this.hasInitialized && this.config.active !== false && this.hasValidPivotConfig()) {\n this.hasInitialized = true;\n this.isActive = true;\n }\n\n if (!this.isActive) {\n return [...rows] as PivotDataRow[];\n }\n\n const errors = validatePivotConfig(this.config);\n if (errors.length > 0) {\n this.warn(`Config errors: ${errors.join(', ')}`);\n return [...rows] as PivotDataRow[];\n }\n\n this.buildFieldHeaderMap();\n this.defaultExpanded = this.config.defaultExpanded ?? true;\n\n // Initialize expanded state with defaults if first build\n if (this.expandedKeys.size === 0 && this.defaultExpanded && this.pivotResult) {\n const allKeys = getAllGroupKeys(this.pivotResult.rows);\n for (const key of allKeys) {\n this.expandedKeys.add(key);\n }\n }\n\n // Build pivot\n this.pivotResult = buildPivot(rows as PivotDataRow[], this.config);\n\n // If default expanded and we just built the pivot, add all group keys\n if (this.expandedKeys.size === 0 && this.defaultExpanded) {\n const allKeys = getAllGroupKeys(this.pivotResult.rows);\n for (const key of allKeys) {\n this.expandedKeys.add(key);\n }\n }\n\n // Return flattened pivot rows respecting expanded state\n const indentWidth = this.config.indentWidth ?? 20;\n const flatRows: PivotDataRow[] = flattenPivotRows(\n this.pivotResult.rows,\n this.expandedKeys,\n this.defaultExpanded,\n ).map((pr) => ({\n __pivotRowKey: pr.rowKey,\n __pivotLabel: pr.rowLabel,\n __pivotDepth: pr.depth,\n __pivotIsGroup: pr.isGroup,\n __pivotHasChildren: Boolean(pr.children?.length),\n __pivotExpanded: this.expandedKeys.has(pr.rowKey),\n __pivotRowCount: pr.rowCount ?? 0,\n __pivotIndent: pr.depth * indentWidth,\n __pivotTotal: pr.total,\n ...pr.values,\n }));\n\n // Track which rows are newly visible (for animation)\n this.keysToAnimate.clear();\n const currentVisibleKeys = new Set<string>();\n for (const row of flatRows) {\n const key = row.__pivotRowKey;\n currentVisibleKeys.add(key);\n // Animate non-root rows that weren't previously visible\n if (!this.previousVisibleKeys.has(key) && row.__pivotDepth > 0) {\n this.keysToAnimate.add(key);\n }\n }\n this.previousVisibleKeys = currentVisibleKeys;\n\n // Grand total is rendered as a pinned footer row in afterRender,\n // not as part of the scrolling row data\n\n return flatRows;\n }\n\n override processColumns(columns: readonly ColumnConfig[]): ColumnConfig[] {\n if (!this.isActive || !this.pivotResult) {\n return [...columns];\n }\n\n const pivotColumns: ColumnConfig[] = [];\n\n // Row label column\n const rowGroupHeaders = (this.config.rowGroupFields ?? []).map((f) => this.fieldHeaderMap.get(f) ?? f).join(' / ');\n pivotColumns.push({\n field: '__pivotLabel',\n header: rowGroupHeaders || 'Group',\n width: 200,\n });\n\n // Value columns for each column key\n for (const colKey of this.pivotResult.columnKeys) {\n for (const vf of this.config.valueFields ?? []) {\n const valueKey = createValueKey([colKey], vf.field);\n const valueHeader = vf.header || this.fieldHeaderMap.get(vf.field) || vf.field;\n pivotColumns.push({\n field: valueKey,\n header: `${colKey} - ${valueHeader} (${vf.aggFunc})`,\n width: 120,\n type: 'number',\n });\n }\n }\n\n // Totals column\n if (this.config.showTotals) {\n pivotColumns.push({\n field: '__pivotTotal',\n header: 'Total',\n width: 100,\n type: 'number',\n });\n }\n\n return pivotColumns;\n }\n\n override renderRow(row: Record<string, unknown>, rowEl: HTMLElement): boolean {\n const pivotRow = row as PivotRowData;\n\n // Handle pivot group row (has children)\n if (pivotRow.__pivotRowKey && pivotRow.__pivotHasChildren) {\n return renderPivotGroupRow(pivotRow, rowEl, {\n columns: this.gridColumns,\n onToggle: (key) => this.toggle(key),\n resolveIcon: (iconKey) => this.resolveIcon(iconKey),\n setIcon: (el, icon) => this.setIcon(el, icon),\n });\n }\n\n // Handle pivot leaf row (no children but in pivot mode)\n if (pivotRow.__pivotRowKey !== undefined && this.isActive) {\n return renderPivotLeafRow(pivotRow, rowEl, this.gridColumns);\n }\n\n // Clean up any leftover pivot styling from pooled row elements\n this.cleanupPivotStyling(rowEl);\n\n return false;\n }\n\n /**\n * Remove pivot-specific classes, attributes, and inline styles from a row element.\n * Called when pivot mode is disabled to clean up reused DOM elements.\n * Clears innerHTML so the grid's default renderer can rebuild the row.\n */\n private cleanupPivotStyling(rowEl: HTMLElement): void {\n // Check if this row was previously rendered by pivot (has pivot classes)\n const wasPivotRow =\n rowEl.classList.contains('pivot-group-row') ||\n rowEl.classList.contains('pivot-leaf-row') ||\n rowEl.classList.contains('pivot-grand-total-row');\n\n if (wasPivotRow) {\n // Remove pivot row classes and restore the default grid row class\n rowEl.classList.remove('pivot-group-row', 'pivot-leaf-row', 'pivot-grand-total-row');\n rowEl.classList.add('data-grid-row');\n\n // Remove pivot-specific attributes\n rowEl.removeAttribute('data-pivot-depth');\n\n // Clear the row content so the default renderer can rebuild it\n rowEl.innerHTML = '';\n }\n }\n\n override afterRender(): void {\n // Render grand total as a sticky pinned footer when pivot is active\n if (this.isActive && this.config.showGrandTotal && this.pivotResult) {\n this.renderGrandTotalFooter();\n } else {\n this.cleanupGrandTotalFooter();\n }\n\n // Apply animations to newly visible rows\n const style = this.animationStyle;\n if (style === false || this.keysToAnimate.size === 0) return;\n\n const body = this.shadowRoot?.querySelector('.rows');\n if (!body) return;\n\n const animClass = style === 'fade' ? 'tbw-pivot-fade-in' : 'tbw-pivot-slide-in';\n for (const rowEl of body.querySelectorAll('.pivot-group-row, .pivot-leaf-row')) {\n const key = (rowEl as HTMLElement).dataset.pivotKey;\n if (key && this.keysToAnimate.has(key)) {\n rowEl.classList.add(animClass);\n rowEl.addEventListener('animationend', () => rowEl.classList.remove(animClass), { once: true });\n }\n }\n this.keysToAnimate.clear();\n }\n\n /**\n * Render the grand total row as a sticky footer pinned to the bottom.\n */\n private renderGrandTotalFooter(): void {\n if (!this.pivotResult) return;\n\n const shadowRoot = this.shadowRoot;\n if (!shadowRoot) return;\n\n // Find the scroll container to append the footer\n const container =\n shadowRoot.querySelector('.tbw-scroll-area') ??\n shadowRoot.querySelector('.tbw-grid-content') ??\n shadowRoot.children[0];\n if (!container) return;\n\n // Create footer if it doesn't exist\n if (!this.grandTotalFooter) {\n this.grandTotalFooter = document.createElement('div');\n this.grandTotalFooter.className = 'pivot-grand-total-footer';\n container.appendChild(this.grandTotalFooter);\n }\n\n // Build the row data for grand total\n const grandTotalRow: PivotRowData = {\n __pivotRowKey: '__grandTotal',\n __pivotLabel: 'Grand Total',\n __pivotIsGrandTotal: true,\n __pivotTotal: this.pivotResult.grandTotal,\n ...this.pivotResult.totals,\n };\n\n // Render the grand total row into the footer\n renderPivotGrandTotalRow(grandTotalRow, this.grandTotalFooter, this.gridColumns);\n }\n\n /**\n * Remove the grand total footer element.\n */\n private cleanupGrandTotalFooter(): void {\n if (this.grandTotalFooter) {\n this.grandTotalFooter.remove();\n this.grandTotalFooter = null;\n }\n }\n\n // #endregion\n\n // #region Expand/Collapse API\n\n toggle(key: string): void {\n if (this.expandedKeys.has(key)) {\n this.expandedKeys.delete(key);\n } else {\n this.expandedKeys.add(key);\n }\n this.requestRender();\n }\n\n expand(key: string): void {\n this.expandedKeys.add(key);\n this.requestRender();\n }\n\n collapse(key: string): void {\n this.expandedKeys.delete(key);\n this.requestRender();\n }\n\n expandAll(): void {\n if (this.pivotResult) {\n const allKeys = getAllGroupKeys(this.pivotResult.rows);\n for (const key of allKeys) {\n this.expandedKeys.add(key);\n }\n this.requestRender();\n }\n }\n\n collapseAll(): void {\n this.expandedKeys.clear();\n this.requestRender();\n }\n\n isExpanded(key: string): boolean {\n return this.expandedKeys.has(key);\n }\n\n // #endregion\n\n // #region Public API\n\n enablePivot(): void {\n if (this.originalColumns.length === 0) {\n this.captureOriginalColumns();\n }\n this.isActive = true;\n this.requestRender();\n }\n\n disablePivot(): void {\n this.isActive = false;\n this.pivotResult = null;\n this.requestRender();\n }\n\n isPivotActive(): boolean {\n return this.isActive;\n }\n\n getPivotResult(): PivotResult | null {\n return this.pivotResult;\n }\n\n setRowGroupFields(fields: string[]): void {\n this.config.rowGroupFields = fields;\n this.requestRender();\n }\n\n setColumnGroupFields(fields: string[]): void {\n this.config.columnGroupFields = fields;\n this.requestRender();\n }\n\n setValueFields(fields: PivotValueField[]): void {\n this.config.valueFields = fields;\n this.requestRender();\n }\n\n refresh(): void {\n this.pivotResult = null;\n this.requestRender();\n }\n\n // #endregion\n\n // #region Tool Panel API\n\n showPanel(): void {\n const grid = this.grid as unknown as GridWithColumns;\n grid.openToolPanel(PivotPlugin.PANEL_ID);\n }\n\n hidePanel(): void {\n const grid = this.grid as unknown as GridWithColumns;\n grid.closeToolPanel();\n }\n\n togglePanel(): void {\n const grid = this.grid as unknown as GridWithColumns;\n grid.toggleToolPanel(PivotPlugin.PANEL_ID);\n }\n\n isPanelVisible(): boolean {\n const grid = this.grid as unknown as GridWithColumns;\n return grid.activeToolPanel === PivotPlugin.PANEL_ID;\n }\n\n // #endregion\n\n // #region Private Helpers\n\n private get gridColumns(): ColumnConfig[] {\n const grid = this.grid as unknown as GridWithColumns;\n return grid.columns ?? [];\n }\n\n private buildFieldHeaderMap(): void {\n const availableFields = this.getAvailableFields();\n this.fieldHeaderMap.clear();\n for (const field of availableFields) {\n this.fieldHeaderMap.set(field.field, field.header);\n }\n }\n\n private getAvailableFields(): FieldInfo[] {\n if (this.originalColumns.length > 0) {\n return this.originalColumns;\n }\n return this.captureOriginalColumns();\n }\n\n private captureOriginalColumns(): FieldInfo[] {\n const grid = this.grid as unknown as GridWithColumns;\n try {\n const columns = grid.getAllColumns?.() ?? grid.columns ?? [];\n this.originalColumns = columns\n .filter((col: { field: string }) => !col.field.startsWith('__pivot'))\n .map((col: { field: string; header?: string }) => ({\n field: col.field,\n header: col.header ?? col.field,\n }));\n return this.originalColumns;\n } catch {\n return [];\n }\n }\n\n private renderPanel(container: HTMLElement): (() => void) | void {\n this.panelContainer = container;\n\n if (this.originalColumns.length === 0) {\n this.captureOriginalColumns();\n }\n\n const callbacks: PanelCallbacks = {\n onTogglePivot: (enabled) => {\n if (enabled) {\n this.enablePivot();\n } else {\n this.disablePivot();\n }\n this.refreshPanel();\n },\n onAddFieldToZone: (field, zone) => this.addFieldToZone(field, zone),\n onRemoveFieldFromZone: (field, zone) => this.removeFieldFromZone(field, zone),\n onAddValueField: (field, aggFunc) => this.addValueField(field, aggFunc),\n onRemoveValueField: (field) => this.removeValueField(field),\n onUpdateValueAggFunc: (field, aggFunc) => this.updateValueAggFunc(field, aggFunc),\n onOptionChange: (option, value) => {\n this.config[option] = value;\n if (this.isActive) this.refresh();\n },\n getAvailableFields: () => this.getAvailableFields(),\n };\n\n return renderPivotPanel(container, this.config, this.isActive, callbacks);\n }\n\n private refreshPanel(): void {\n if (!this.panelContainer) return;\n this.panelContainer.innerHTML = '';\n this.renderPanel(this.panelContainer);\n }\n\n private addFieldToZone(field: string, zoneType: 'rowGroups' | 'columnGroups'): void {\n if (zoneType === 'rowGroups') {\n const current = this.config.rowGroupFields ?? [];\n if (!current.includes(field)) {\n this.config.rowGroupFields = [...current, field];\n }\n } else {\n const current = this.config.columnGroupFields ?? [];\n if (!current.includes(field)) {\n this.config.columnGroupFields = [...current, field];\n }\n }\n\n this.removeFromOtherZones(field, zoneType);\n if (this.isActive) this.refresh();\n this.refreshPanel();\n }\n\n private removeFieldFromZone(field: string, zoneType: 'rowGroups' | 'columnGroups'): void {\n if (zoneType === 'rowGroups') {\n this.config.rowGroupFields = (this.config.rowGroupFields ?? []).filter((f) => f !== field);\n } else {\n this.config.columnGroupFields = (this.config.columnGroupFields ?? []).filter((f) => f !== field);\n }\n\n if (this.isActive) this.refresh();\n this.refreshPanel();\n }\n\n private removeFromOtherZones(field: string, targetZone: 'rowGroups' | 'columnGroups' | 'values'): void {\n if (targetZone !== 'rowGroups') {\n this.config.rowGroupFields = (this.config.rowGroupFields ?? []).filter((f) => f !== field);\n }\n if (targetZone !== 'columnGroups') {\n this.config.columnGroupFields = (this.config.columnGroupFields ?? []).filter((f) => f !== field);\n }\n if (targetZone !== 'values') {\n this.config.valueFields = (this.config.valueFields ?? []).filter((v) => v.field !== field);\n }\n }\n\n private addValueField(field: string, aggFunc: AggFunc): void {\n const current = this.config.valueFields ?? [];\n if (!current.some((v) => v.field === field)) {\n this.config.valueFields = [...current, { field, aggFunc }];\n }\n\n this.removeFromOtherZones(field, 'values');\n if (this.isActive) this.refresh();\n this.refreshPanel();\n }\n\n private removeValueField(field: string): void {\n this.config.valueFields = (this.config.valueFields ?? []).filter((v) => v.field !== field);\n if (this.isActive) this.refresh();\n this.refreshPanel();\n }\n\n private updateValueAggFunc(field: string, aggFunc: AggFunc): void {\n const valueFields = this.config.valueFields ?? [];\n const fieldIndex = valueFields.findIndex((v) => v.field === field);\n if (fieldIndex >= 0) {\n valueFields[fieldIndex] = { ...valueFields[fieldIndex], aggFunc };\n this.config.valueFields = [...valueFields];\n }\n if (this.isActive) this.refresh();\n }\n\n // #endregion\n\n // #region Styles\n\n override readonly styles = styles;\n\n // #endregion\n}\n","/**\n * Column Reordering Core Logic\n *\n * Pure functions for column drag and reordering operations.\n */\n\nimport type { ColumnConfig } from '../../core/types';\n\n/**\n * Check if a column can be moved based on its own metadata.\n * This checks column-level properties like lockPosition and suppressMovable.\n *\n * Note: For full movability checks including plugin constraints (e.g., pinned columns),\n * use `grid.queryPlugins({ type: PLUGIN_QUERIES.CAN_MOVE_COLUMN, context: column })`\n * which queries all plugins via the generic plugin query system.\n *\n * @param column - The column configuration to check\n * @returns True if the column can be moved based on its metadata\n */\nexport function canMoveColumn<TRow = unknown>(column: ColumnConfig<TRow>): boolean {\n // Check for lockPosition or suppressMovable properties in the column config\n const meta = column.meta ?? {};\n return meta.lockPosition !== true && meta.suppressMovable !== true;\n}\n\n/**\n * Move a column from one position to another in the order array.\n *\n * @param columns - Array of field names in current order\n * @param fromIndex - The current index of the column to move\n * @param toIndex - The target index to move the column to\n * @returns New array with updated order\n */\nexport function moveColumn(columns: string[], fromIndex: number, toIndex: number): string[] {\n if (fromIndex === toIndex) return columns;\n if (fromIndex < 0 || fromIndex >= columns.length) return columns;\n if (toIndex < 0 || toIndex > columns.length) return columns;\n\n const result = [...columns];\n const [removed] = result.splice(fromIndex, 1);\n result.splice(toIndex, 0, removed);\n return result;\n}\n\n/**\n * Calculate the drop index based on the current drag position.\n *\n * @param dragX - The current X position of the drag\n * @param headerRect - The bounding rect of the header container\n * @param columnWidths - Array of column widths in order\n * @returns The index where the column should be dropped\n */\nexport function getDropIndex(dragX: number, headerRect: DOMRect, columnWidths: number[]): number {\n let x = headerRect.left;\n\n for (let i = 0; i < columnWidths.length; i++) {\n const mid = x + columnWidths[i] / 2;\n if (dragX < mid) return i;\n x += columnWidths[i];\n }\n\n return columnWidths.length;\n}\n\n/**\n * Reorder columns according to a specified order.\n * Columns not in the order array are appended at the end.\n *\n * @param columns - Array of column configurations\n * @param order - Array of field names specifying the desired order\n * @returns New array of columns in the specified order\n */\nexport function reorderColumns<TRow = unknown>(columns: ColumnConfig<TRow>[], order: string[]): ColumnConfig<TRow>[] {\n const columnMap = new Map<string, ColumnConfig<TRow>>(columns.map((c) => [c.field as string, c]));\n const reordered: ColumnConfig<TRow>[] = [];\n\n // Add columns in specified order\n for (const field of order) {\n const col = columnMap.get(field);\n if (col) {\n reordered.push(col);\n columnMap.delete(field);\n }\n }\n\n // Add any remaining columns not in order\n for (const col of columnMap.values()) {\n reordered.push(col);\n }\n\n return reordered;\n}\n","/**\n * Column Reordering Plugin (Class-based)\n *\n * Provides drag-and-drop column reordering functionality for tbw-grid.\n * Supports keyboard and mouse interactions with visual feedback.\n * Uses FLIP animation technique for smooth column transitions.\n *\n * Animation respects grid-level animation.mode setting but style is plugin-configured.\n */\n\nimport { ensureCellVisible } from '../../core/internal/keyboard';\nimport { BaseGridPlugin, PLUGIN_QUERIES } from '../../core/plugin/base-plugin';\nimport type { ColumnConfig, GridConfig } from '../../core/types';\nimport { canMoveColumn, moveColumn } from './column-drag';\nimport styles from './reorder.css?inline';\nimport type { ColumnMoveDetail, ReorderConfig } from './types';\n\n/** Extended grid interface with column order methods */\ninterface GridWithColumnOrder {\n setColumnOrder(order: string[]): void;\n getColumnOrder(): string[];\n requestStateChange?: () => void;\n /** Query plugins for inter-plugin communication */\n queryPlugins<T>(query: { type: string; context: unknown }): T[];\n /** Effective grid config */\n effectiveConfig?: GridConfig;\n}\n\n/**\n * Column Reordering Plugin for tbw-grid\n *\n * @example\n * ```ts\n * new ReorderPlugin()\n * ```\n */\nexport class ReorderPlugin extends BaseGridPlugin<ReorderConfig> {\n readonly name = 'reorder';\n override readonly version = '1.0.0';\n\n protected override get defaultConfig(): Partial<ReorderConfig> {\n return {\n animation: 'flip', // Plugin's own default\n };\n }\n\n /**\n * Resolve animation type from plugin config.\n * Respects grid-level animation.mode (disabled = no animation).\n */\n private get animationType(): false | 'flip' | 'fade' {\n // Check if animations are globally disabled\n if (!this.isAnimationEnabled) return false;\n\n // Plugin config (with default from defaultConfig)\n if (this.config.animation !== undefined) return this.config.animation;\n\n // Legacy viewTransition fallback\n if (this.config.viewTransition === false) return false;\n if (this.config.viewTransition === true) return 'flip';\n\n return 'flip'; // Plugin default\n }\n\n /**\n * Check if animations are enabled at the grid level.\n * Respects gridConfig.animation.mode and CSS variable.\n */\n private get isAnimationEnabled(): boolean {\n const gridEl = this.grid as unknown as GridWithColumnOrder;\n const mode = gridEl.effectiveConfig?.animation?.mode ?? 'reduced-motion';\n\n // Explicit off = disabled\n if (mode === false || mode === 'off') return false;\n\n // Explicit on = always enabled\n if (mode === true || mode === 'on') return true;\n\n // reduced-motion: check CSS variable (set by grid based on media query)\n const host = this.shadowRoot?.host as HTMLElement | undefined;\n if (host) {\n const enabled = getComputedStyle(host).getPropertyValue('--tbw-animation-enabled').trim();\n return enabled !== '0';\n }\n\n return true; // Default to enabled\n }\n\n /**\n * Get animation duration from CSS variable (set by grid config).\n */\n private get animationDuration(): number {\n // Plugin config override\n if (this.config.animationDuration !== undefined) {\n return this.config.animationDuration;\n }\n\n // Read from CSS variable (already set by grid from gridConfig.animation.duration)\n const host = this.shadowRoot?.host as HTMLElement | undefined;\n if (host) {\n const durationStr = getComputedStyle(host).getPropertyValue('--tbw-animation-duration').trim();\n const parsed = parseInt(durationStr, 10);\n if (!isNaN(parsed)) return parsed;\n }\n\n return 200; // Default\n }\n\n // #region Internal State\n private isDragging = false;\n private draggedField: string | null = null;\n private draggedIndex: number | null = null;\n private dropIndex: number | null = null;\n // #endregion\n\n // #region Lifecycle\n\n override attach(grid: import('../../core/plugin/base-plugin').GridElement): void {\n super.attach(grid);\n\n // Listen for reorder requests from other plugins (e.g., VisibilityPlugin)\n // Uses disconnectSignal for automatic cleanup - no need for manual removeEventListener\n (grid as unknown as HTMLElement).addEventListener(\n 'column-reorder-request',\n (e: Event) => {\n const detail = (e as CustomEvent).detail;\n if (detail?.field && typeof detail.toIndex === 'number') {\n this.moveColumn(detail.field, detail.toIndex);\n }\n },\n { signal: this.disconnectSignal },\n );\n }\n\n override detach(): void {\n this.isDragging = false;\n this.draggedField = null;\n this.draggedIndex = null;\n this.dropIndex = null;\n }\n // #endregion\n\n // #region Hooks\n\n override afterRender(): void {\n const shadowRoot = this.shadowRoot;\n if (!shadowRoot) return;\n\n const headers = shadowRoot.querySelectorAll('.header-row > .cell');\n\n headers.forEach((header) => {\n const headerEl = header as HTMLElement;\n const field = headerEl.getAttribute('data-field');\n if (!field) return;\n\n const column = this.columns.find((c) => c.field === field);\n // Check both local metadata and plugin queries (e.g., PinnedColumnsPlugin)\n const gridEl = this.grid as unknown as GridWithColumnOrder;\n const pluginResponses = gridEl.queryPlugins<boolean>({\n type: PLUGIN_QUERIES.CAN_MOVE_COLUMN,\n context: column as ColumnConfig,\n });\n const pluginAllows = !pluginResponses.includes(false);\n if (!column || !canMoveColumn(column) || !pluginAllows) {\n headerEl.draggable = false;\n return;\n }\n\n headerEl.draggable = true;\n\n // Remove existing listeners to prevent duplicates\n if (headerEl.getAttribute('data-dragstart-bound')) return;\n headerEl.setAttribute('data-dragstart-bound', 'true');\n\n headerEl.addEventListener('dragstart', (e: DragEvent) => {\n const currentOrder = this.getColumnOrder();\n const orderIndex = currentOrder.indexOf(field);\n this.isDragging = true;\n this.draggedField = field;\n this.draggedIndex = orderIndex;\n\n if (e.dataTransfer) {\n e.dataTransfer.effectAllowed = 'move';\n e.dataTransfer.setData('text/plain', field);\n }\n\n headerEl.classList.add('dragging');\n });\n\n headerEl.addEventListener('dragend', () => {\n this.isDragging = false;\n this.draggedField = null;\n this.draggedIndex = null;\n this.dropIndex = null;\n\n shadowRoot.querySelectorAll('.header-row > .cell').forEach((h) => {\n h.classList.remove('dragging', 'drop-target', 'drop-before', 'drop-after');\n });\n });\n\n headerEl.addEventListener('dragover', (e: DragEvent) => {\n e.preventDefault();\n if (!this.isDragging || this.draggedField === field) return;\n\n const rect = headerEl.getBoundingClientRect();\n const midX = rect.left + rect.width / 2;\n\n const currentOrder = this.getColumnOrder();\n const orderIndex = currentOrder.indexOf(field);\n this.dropIndex = e.clientX < midX ? orderIndex : orderIndex + 1;\n\n headerEl.classList.add('drop-target');\n headerEl.classList.toggle('drop-before', e.clientX < midX);\n headerEl.classList.toggle('drop-after', e.clientX >= midX);\n });\n\n headerEl.addEventListener('dragleave', () => {\n headerEl.classList.remove('drop-target', 'drop-before', 'drop-after');\n });\n\n headerEl.addEventListener('drop', (e: DragEvent) => {\n e.preventDefault();\n const draggedField = this.draggedField;\n const draggedIndex = this.draggedIndex;\n const dropIndex = this.dropIndex;\n\n if (!this.isDragging || draggedField === null || draggedIndex === null || dropIndex === null) {\n return;\n }\n\n const effectiveToIndex = dropIndex > draggedIndex ? dropIndex - 1 : dropIndex;\n const currentOrder = this.getColumnOrder();\n const newOrder = moveColumn(currentOrder, draggedIndex, effectiveToIndex);\n\n const detail: ColumnMoveDetail = {\n field: draggedField,\n fromIndex: draggedIndex,\n toIndex: effectiveToIndex,\n columnOrder: newOrder,\n };\n\n // Update the grid's column order (with optional view transition)\n this.updateColumnOrder(newOrder);\n\n this.emit('column-move', detail);\n });\n });\n }\n\n /**\n * Handle Alt+Arrow keyboard shortcuts for column reordering.\n */\n override onKeyDown(event: KeyboardEvent): boolean | void {\n if (!event.altKey || (event.key !== 'ArrowLeft' && event.key !== 'ArrowRight')) {\n return;\n }\n\n const grid = this.grid as unknown as { _focusCol: number; _visibleColumns: ColumnConfig[] };\n const focusCol = grid._focusCol;\n const columns = grid._visibleColumns;\n\n if (focusCol < 0 || focusCol >= columns.length) return;\n\n const column = columns[focusCol];\n if (!column || !canMoveColumn(column)) return;\n\n // Check plugin queries (e.g., PinnedColumnsPlugin)\n const gridEl = this.grid as unknown as GridWithColumnOrder;\n const pluginResponses = gridEl.queryPlugins<boolean>({\n type: PLUGIN_QUERIES.CAN_MOVE_COLUMN,\n context: column,\n });\n if (pluginResponses.includes(false)) return;\n\n const currentOrder = this.getColumnOrder();\n const fromIndex = currentOrder.indexOf(column.field);\n if (fromIndex === -1) return;\n\n const toIndex = event.key === 'ArrowLeft' ? fromIndex - 1 : fromIndex + 1;\n\n // Check bounds\n if (toIndex < 0 || toIndex >= currentOrder.length) return;\n\n // Check if target position is allowed (e.g., not into pinned area)\n const targetColumn = columns.find((c) => c.field === currentOrder[toIndex]);\n if (targetColumn) {\n const targetResponses = gridEl.queryPlugins<boolean>({\n type: PLUGIN_QUERIES.CAN_MOVE_COLUMN,\n context: targetColumn,\n });\n if (targetResponses.includes(false)) return;\n }\n\n this.moveColumn(column.field, toIndex);\n\n // Update focus to follow the moved column and refresh visual focus state\n grid._focusCol = toIndex;\n ensureCellVisible(this.grid as any);\n\n event.preventDefault();\n event.stopPropagation();\n return true;\n }\n // #endregion\n\n // #region Public API\n\n /**\n * Get the current column order from the grid.\n * @returns Array of field names in display order\n */\n getColumnOrder(): string[] {\n return (this.grid as unknown as GridWithColumnOrder).getColumnOrder();\n }\n\n /**\n * Move a column to a new position.\n * @param field - The field name of the column to move\n * @param toIndex - The target index\n */\n moveColumn(field: string, toIndex: number): void {\n const currentOrder = this.getColumnOrder();\n const fromIndex = currentOrder.indexOf(field);\n if (fromIndex === -1) return;\n\n const newOrder = moveColumn(currentOrder, fromIndex, toIndex);\n\n // Update with view transition\n this.updateColumnOrder(newOrder);\n\n this.emit<ColumnMoveDetail>('column-move', {\n field,\n fromIndex,\n toIndex,\n columnOrder: newOrder,\n });\n }\n\n /**\n * Set a specific column order.\n * @param order - Array of field names in desired order\n */\n setColumnOrder(order: string[]): void {\n this.updateColumnOrder(order);\n }\n\n /**\n * Reset column order to the original configuration order.\n */\n resetColumnOrder(): void {\n const originalOrder = this.columns.map((c) => c.field);\n this.updateColumnOrder(originalOrder);\n }\n // #endregion\n\n // #region View Transition\n\n /**\n * Capture header cell positions before reorder.\n */\n private captureHeaderPositions(): Map<string, number> {\n const positions = new Map<string, number>();\n this.shadowRoot?.querySelectorAll('.header-row > .cell[data-field]').forEach((cell) => {\n const field = cell.getAttribute('data-field');\n if (field) positions.set(field, cell.getBoundingClientRect().left);\n });\n return positions;\n }\n\n /**\n * Apply FLIP animation for column reorder.\n * Uses CSS transitions - JS sets initial transform and toggles class.\n * @param oldPositions - Header positions captured before DOM change\n */\n private animateFLIP(oldPositions: Map<string, number>): void {\n const shadowRoot = this.shadowRoot;\n if (!shadowRoot || oldPositions.size === 0) return;\n\n // Compute deltas from header cells (stable reference points)\n const deltas = new Map<string, number>();\n shadowRoot.querySelectorAll('.header-row > .cell[data-field]').forEach((cell) => {\n const field = cell.getAttribute('data-field');\n if (!field) return;\n const oldLeft = oldPositions.get(field);\n if (oldLeft === undefined) return;\n const deltaX = oldLeft - cell.getBoundingClientRect().left;\n if (Math.abs(deltaX) > 1) deltas.set(field, deltaX);\n });\n\n if (deltas.size === 0) return;\n\n // Set initial transform (First → Last position offset)\n const cells: HTMLElement[] = [];\n shadowRoot.querySelectorAll('.cell[data-field]').forEach((cell) => {\n const deltaX = deltas.get(cell.getAttribute('data-field') ?? '');\n if (deltaX !== undefined) {\n const el = cell as HTMLElement;\n el.style.transform = `translateX(${deltaX}px)`;\n cells.push(el);\n }\n });\n\n if (cells.length === 0) return;\n\n // Force reflow then animate to final position via CSS transition\n void (shadowRoot.host as HTMLElement).offsetHeight;\n\n const duration = this.animationDuration;\n\n requestAnimationFrame(() => {\n cells.forEach((el) => {\n el.classList.add('flip-animating');\n el.style.transform = '';\n });\n\n // Cleanup after animation\n setTimeout(() => {\n cells.forEach((el) => {\n el.style.transform = '';\n el.classList.remove('flip-animating');\n });\n }, duration + 50);\n });\n }\n\n /**\n * Apply crossfade animation for moved columns.\n * Uses CSS keyframes - JS just toggles classes.\n */\n private animateFade(applyChange: () => void): void {\n const shadowRoot = this.shadowRoot;\n if (!shadowRoot) {\n applyChange();\n return;\n }\n\n // Capture old positions to detect which columns moved\n const oldPositions = this.captureHeaderPositions();\n\n // Apply the change first\n applyChange();\n\n // Find which columns changed position\n const movedFields = new Set<string>();\n shadowRoot.querySelectorAll('.header-row > .cell[data-field]').forEach((cell) => {\n const field = cell.getAttribute('data-field');\n if (!field) return;\n const oldLeft = oldPositions.get(field);\n if (oldLeft === undefined) return;\n const newLeft = cell.getBoundingClientRect().left;\n if (Math.abs(oldLeft - newLeft) > 1) {\n movedFields.add(field);\n }\n });\n\n if (movedFields.size === 0) return;\n\n // Add animation class to moved columns (headers + body cells)\n const cells: HTMLElement[] = [];\n shadowRoot.querySelectorAll('.cell[data-field]').forEach((cell) => {\n const field = cell.getAttribute('data-field');\n if (field && movedFields.has(field)) {\n const el = cell as HTMLElement;\n el.classList.add('fade-animating');\n cells.push(el);\n }\n });\n\n if (cells.length === 0) return;\n\n // Remove class after animation completes\n const duration = this.animationDuration;\n setTimeout(() => {\n cells.forEach((el) => el.classList.remove('fade-animating'));\n }, duration + 50);\n }\n\n /**\n * Update column order with configured animation.\n */\n private updateColumnOrder(newOrder: string[]): void {\n const gridEl = this.grid as unknown as GridWithColumnOrder;\n const animation = this.animationType;\n\n if (animation === 'flip' && this.shadowRoot) {\n const oldPositions = this.captureHeaderPositions();\n gridEl.setColumnOrder(newOrder);\n void (this.shadowRoot.host as HTMLElement).offsetHeight;\n this.animateFLIP(oldPositions);\n } else if (animation === 'fade') {\n this.animateFade(() => gridEl.setColumnOrder(newOrder));\n } else {\n gridEl.setColumnOrder(newOrder);\n }\n\n gridEl.requestStateChange?.();\n }\n // #endregion\n\n // #region Styles\n\n override readonly styles = styles;\n // #endregion\n}\n","/**\n * Cell Range Selection Core Logic\n *\n * Pure functions for cell range selection operations.\n */\n\nimport type { InternalCellRange, CellRange } from './types';\n\n/**\n * Normalize a range so startRow/startCol are always <= endRow/endCol.\n * This handles cases where user drags from bottom-right to top-left.\n *\n * @param range - The range to normalize\n * @returns Normalized range with start <= end for both dimensions\n */\nexport function normalizeRange(range: InternalCellRange): InternalCellRange {\n return {\n startRow: Math.min(range.startRow, range.endRow),\n startCol: Math.min(range.startCol, range.endCol),\n endRow: Math.max(range.startRow, range.endRow),\n endCol: Math.max(range.startCol, range.endCol),\n };\n}\n\n/**\n * Convert an internal range to the public event format.\n *\n * @param range - The internal range to convert\n * @returns Public CellRange format with from/to coordinates\n */\nexport function toPublicRange(range: InternalCellRange): CellRange {\n const normalized = normalizeRange(range);\n return {\n from: { row: normalized.startRow, col: normalized.startCol },\n to: { row: normalized.endRow, col: normalized.endCol },\n };\n}\n\n/**\n * Convert multiple internal ranges to public format.\n *\n * @param ranges - Array of internal ranges\n * @returns Array of public CellRange format\n */\nexport function toPublicRanges(ranges: InternalCellRange[]): CellRange[] {\n return ranges.map(toPublicRange);\n}\n\n/**\n * Check if a cell is within a specific range.\n *\n * @param row - The row index to check\n * @param col - The column index to check\n * @param range - The range to check against\n * @returns True if the cell is within the range\n */\nexport function isCellInRange(row: number, col: number, range: InternalCellRange): boolean {\n const normalized = normalizeRange(range);\n return (\n row >= normalized.startRow && row <= normalized.endRow && col >= normalized.startCol && col <= normalized.endCol\n );\n}\n\n/**\n * Check if a cell is within any of the provided ranges.\n *\n * @param row - The row index to check\n * @param col - The column index to check\n * @param ranges - Array of ranges to check against\n * @returns True if the cell is within any range\n */\nexport function isCellInAnyRange(row: number, col: number, ranges: InternalCellRange[]): boolean {\n return ranges.some((range) => isCellInRange(row, col, range));\n}\n\n/**\n * Get all cells within a range as an array of {row, col} objects.\n *\n * @param range - The range to enumerate\n * @returns Array of all cell coordinates in the range\n */\nexport function getCellsInRange(range: InternalCellRange): Array<{ row: number; col: number }> {\n const cells: Array<{ row: number; col: number }> = [];\n const normalized = normalizeRange(range);\n\n for (let row = normalized.startRow; row <= normalized.endRow; row++) {\n for (let col = normalized.startCol; col <= normalized.endCol; col++) {\n cells.push({ row, col });\n }\n }\n\n return cells;\n}\n\n/**\n * Get all unique cells across multiple ranges.\n * Deduplicates cells that appear in overlapping ranges.\n *\n * @param ranges - Array of ranges to enumerate\n * @returns Array of unique cell coordinates\n */\nexport function getAllCellsInRanges(ranges: InternalCellRange[]): Array<{ row: number; col: number }> {\n const cellMap = new Map<string, { row: number; col: number }>();\n\n for (const range of ranges) {\n for (const cell of getCellsInRange(range)) {\n cellMap.set(`${cell.row},${cell.col}`, cell);\n }\n }\n\n return [...cellMap.values()];\n}\n\n/**\n * Merge overlapping or adjacent ranges into fewer ranges.\n * Simple implementation - returns ranges as-is for now.\n * More complex merging logic can be added later for optimization.\n *\n * @param ranges - Array of ranges to merge\n * @returns Merged array of ranges\n */\nexport function mergeRanges(ranges: InternalCellRange[]): InternalCellRange[] {\n // Simple implementation - more complex merging can be added later\n return ranges;\n}\n\n/**\n * Create a range from an anchor cell to a current cell position.\n * The range is not normalized - it preserves the direction of selection.\n *\n * @param anchor - The anchor cell (where selection started)\n * @param current - The current cell (where selection ends)\n * @returns An InternalCellRange from anchor to current\n */\nexport function createRangeFromAnchor(\n anchor: { row: number; col: number },\n current: { row: number; col: number }\n): InternalCellRange {\n return {\n startRow: anchor.row,\n startCol: anchor.col,\n endRow: current.row,\n endCol: current.col,\n };\n}\n\n/**\n * Calculate the number of cells in a range.\n *\n * @param range - The range to measure\n * @returns Total number of cells in the range\n */\nexport function getRangeCellCount(range: InternalCellRange): number {\n const normalized = normalizeRange(range);\n const rowCount = normalized.endRow - normalized.startRow + 1;\n const colCount = normalized.endCol - normalized.startCol + 1;\n return rowCount * colCount;\n}\n\n/**\n * Check if two ranges are equal (same boundaries).\n *\n * @param a - First range\n * @param b - Second range\n * @returns True if ranges have same boundaries after normalization\n */\nexport function rangesEqual(a: InternalCellRange, b: InternalCellRange): boolean {\n const normA = normalizeRange(a);\n const normB = normalizeRange(b);\n return (\n normA.startRow === normB.startRow &&\n normA.startCol === normB.startCol &&\n normA.endRow === normB.endRow &&\n normA.endCol === normB.endCol\n );\n}\n\n/**\n * Check if a range is a single cell (1x1).\n *\n * @param range - The range to check\n * @returns True if the range is exactly one cell\n */\nexport function isSingleCell(range: InternalCellRange): boolean {\n const normalized = normalizeRange(range);\n return normalized.startRow === normalized.endRow && normalized.startCol === normalized.endCol;\n}\n","/**\n * Selection Plugin (Class-based)\n *\n * Provides selection functionality for tbw-grid.\n * Supports three modes:\n * - 'cell': Single cell selection (default). No border, just focus highlight.\n * - 'row': Row selection. Clicking a cell selects the entire row.\n * - 'range': Range selection. Shift+click or drag to select rectangular cell ranges.\n */\n\nimport { BaseGridPlugin, CellClickEvent, CellMouseEvent } from '../../core/plugin/base-plugin';\nimport {\n createRangeFromAnchor,\n getAllCellsInRanges,\n isCellInAnyRange,\n normalizeRange,\n toPublicRanges,\n} from './range-selection';\nimport styles from './selection.css?inline';\nimport type { CellRange, InternalCellRange, SelectionChangeDetail, SelectionConfig, SelectionMode } from './types';\n\n/**\n * Build the selection change event detail for the current state.\n */\nfunction buildSelectionEvent(\n mode: SelectionMode,\n state: {\n selectedCell: { row: number; col: number } | null;\n selected: Set<number>;\n ranges: InternalCellRange[];\n },\n colCount: number,\n): SelectionChangeDetail {\n if (mode === 'cell' && state.selectedCell) {\n return {\n mode,\n ranges: [\n {\n from: { row: state.selectedCell.row, col: state.selectedCell.col },\n to: { row: state.selectedCell.row, col: state.selectedCell.col },\n },\n ],\n };\n }\n\n if (mode === 'row' && state.selected.size > 0) {\n const ranges = [...state.selected].map((rowIndex) => ({\n from: { row: rowIndex, col: 0 },\n to: { row: rowIndex, col: colCount - 1 },\n }));\n return { mode, ranges };\n }\n\n if (mode === 'range' && state.ranges.length > 0) {\n return { mode, ranges: toPublicRanges(state.ranges) };\n }\n\n return { mode, ranges: [] };\n}\n\n/**\n * Selection Plugin for tbw-grid\n *\n * @example\n * ```ts\n * new SelectionPlugin({ mode: 'range' })\n * ```\n */\nexport class SelectionPlugin extends BaseGridPlugin<SelectionConfig> {\n readonly name = 'selection';\n override readonly version = '1.0.0';\n\n protected override get defaultConfig(): Partial<SelectionConfig> {\n return {\n mode: 'cell',\n };\n }\n\n // #region Internal State\n /** Row selection state (row mode) */\n private selected = new Set<number>();\n private lastSelected: number | null = null;\n private anchor: number | null = null;\n\n /** Range selection state (range mode) */\n private ranges: InternalCellRange[] = [];\n private activeRange: InternalCellRange | null = null;\n private cellAnchor: { row: number; col: number } | null = null;\n private isDragging = false;\n\n /** Pending keyboard navigation update (processed in afterRender) */\n private pendingKeyboardUpdate: { shiftKey: boolean } | null = null;\n\n /** Cell selection state (cell mode) */\n private selectedCell: { row: number; col: number } | null = null;\n\n // #endregion\n\n // #region Lifecycle\n\n override detach(): void {\n this.selected.clear();\n this.ranges = [];\n this.activeRange = null;\n this.cellAnchor = null;\n this.isDragging = false;\n this.selectedCell = null;\n this.pendingKeyboardUpdate = null;\n }\n\n // #endregion\n\n // #region Event Handlers\n\n override onCellClick(event: CellClickEvent): boolean {\n const { rowIndex, colIndex, originalEvent } = event;\n const { mode } = this.config;\n\n // CELL MODE: Single cell selection\n if (mode === 'cell') {\n this.selectedCell = { row: rowIndex, col: colIndex };\n this.emit<SelectionChangeDetail>('selection-change', this.#buildEvent());\n this.requestAfterRender();\n return false;\n }\n\n // ROW MODE: Select entire row\n if (mode === 'row') {\n this.selected.clear();\n this.selected.add(rowIndex);\n this.lastSelected = rowIndex;\n\n this.emit<SelectionChangeDetail>('selection-change', this.#buildEvent());\n this.requestAfterRender();\n return false;\n }\n\n // RANGE MODE: Shift+click extends selection, click starts new\n if (mode === 'range') {\n const shiftKey = originalEvent.shiftKey;\n const ctrlKey = originalEvent.ctrlKey || originalEvent.metaKey;\n\n if (shiftKey && this.cellAnchor) {\n // Extend selection from anchor\n const newRange = createRangeFromAnchor(this.cellAnchor, { row: rowIndex, col: colIndex });\n\n if (ctrlKey) {\n if (this.ranges.length > 0) {\n this.ranges[this.ranges.length - 1] = newRange;\n } else {\n this.ranges.push(newRange);\n }\n } else {\n this.ranges = [newRange];\n }\n this.activeRange = newRange;\n } else if (ctrlKey) {\n const newRange: InternalCellRange = {\n startRow: rowIndex,\n startCol: colIndex,\n endRow: rowIndex,\n endCol: colIndex,\n };\n this.ranges.push(newRange);\n this.activeRange = newRange;\n this.cellAnchor = { row: rowIndex, col: colIndex };\n } else {\n const newRange: InternalCellRange = {\n startRow: rowIndex,\n startCol: colIndex,\n endRow: rowIndex,\n endCol: colIndex,\n };\n this.ranges = [newRange];\n this.activeRange = newRange;\n this.cellAnchor = { row: rowIndex, col: colIndex };\n }\n\n this.emit<SelectionChangeDetail>('selection-change', this.#buildEvent());\n\n this.requestAfterRender();\n return false;\n }\n\n return false;\n }\n\n override onKeyDown(event: KeyboardEvent): boolean {\n const { mode } = this.config;\n const navKeys = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Tab', 'Home', 'End', 'PageUp', 'PageDown'];\n const isNavKey = navKeys.includes(event.key);\n\n // Escape clears selection in all modes\n if (event.key === 'Escape') {\n if (mode === 'cell') {\n this.selectedCell = null;\n } else if (mode === 'row') {\n this.selected.clear();\n this.anchor = null;\n } else if (mode === 'range') {\n this.ranges = [];\n this.activeRange = null;\n this.cellAnchor = null;\n }\n this.emit<SelectionChangeDetail>('selection-change', this.#buildEvent());\n this.requestAfterRender();\n return true;\n }\n\n // CELL MODE: Selection follows focus\n if (mode === 'cell' && isNavKey) {\n // Use queueMicrotask so grid's handler runs first and updates focusRow/focusCol\n queueMicrotask(() => {\n this.selectedCell = { row: this.grid._focusRow, col: this.grid._focusCol };\n this.emit<SelectionChangeDetail>('selection-change', this.#buildEvent());\n this.requestAfterRender();\n });\n return false; // Let grid handle navigation\n }\n\n // ROW MODE: Only Up/Down arrows move row selection\n if (mode === 'row' && (event.key === 'ArrowUp' || event.key === 'ArrowDown')) {\n // Let grid move focus first, then sync row selection\n queueMicrotask(() => {\n this.selected.clear();\n this.selected.add(this.grid._focusRow);\n this.lastSelected = this.grid._focusRow;\n this.emit<SelectionChangeDetail>('selection-change', this.#buildEvent());\n this.requestAfterRender();\n });\n return false; // Let grid handle navigation\n }\n\n // RANGE MODE: Shift+Arrow extends, plain Arrow resets\n if (mode === 'range' && isNavKey) {\n // Capture anchor BEFORE grid moves focus (synchronous)\n // This ensures the anchor is the starting point, not the destination\n if (event.shiftKey && !this.cellAnchor) {\n this.cellAnchor = { row: this.grid._focusRow, col: this.grid._focusCol };\n }\n\n // Mark pending update - will be processed in afterRender when grid updates focus\n this.pendingKeyboardUpdate = { shiftKey: event.shiftKey };\n\n // Schedule afterRender to run after grid's keyboard handler completes\n // Grid's refreshVirtualWindow(false) skips afterRender for performance,\n // so we explicitly request it to process pendingKeyboardUpdate\n queueMicrotask(() => this.requestAfterRender());\n\n return false; // Let grid handle navigation\n }\n\n // Ctrl+A selects all in range mode\n if (mode === 'range' && event.key === 'a' && (event.ctrlKey || event.metaKey)) {\n const rowCount = this.rows.length;\n const colCount = this.columns.length;\n if (rowCount > 0 && colCount > 0) {\n const allRange: InternalCellRange = {\n startRow: 0,\n startCol: 0,\n endRow: rowCount - 1,\n endCol: colCount - 1,\n };\n this.ranges = [allRange];\n this.activeRange = allRange;\n this.emit<SelectionChangeDetail>('selection-change', this.#buildEvent());\n this.requestAfterRender();\n return true;\n }\n }\n\n return false;\n }\n\n override onCellMouseDown(event: CellMouseEvent): boolean | void {\n if (this.config.mode !== 'range') return;\n if (event.rowIndex === undefined || event.colIndex === undefined) return;\n if (event.rowIndex < 0) return; // Header\n\n // Let onCellClick handle shift+click for range extension\n if (event.originalEvent.shiftKey && this.cellAnchor) {\n return;\n }\n\n // Start drag selection\n this.isDragging = true;\n const rowIndex = event.rowIndex;\n const colIndex = event.colIndex;\n this.cellAnchor = { row: rowIndex, col: colIndex };\n\n const ctrlKey = event.originalEvent.ctrlKey || event.originalEvent.metaKey;\n if (!ctrlKey) {\n this.ranges = [];\n }\n\n const newRange: InternalCellRange = {\n startRow: rowIndex,\n startCol: colIndex,\n endRow: rowIndex,\n endCol: colIndex,\n };\n this.ranges.push(newRange);\n this.activeRange = newRange;\n\n this.emit<SelectionChangeDetail>('selection-change', this.#buildEvent());\n this.requestAfterRender();\n return true;\n }\n\n override onCellMouseMove(event: CellMouseEvent): boolean | void {\n if (this.config.mode !== 'range') return;\n if (!this.isDragging || !this.cellAnchor) return;\n if (event.rowIndex === undefined || event.colIndex === undefined) return;\n if (event.rowIndex < 0) return;\n\n const newRange = createRangeFromAnchor(this.cellAnchor, { row: event.rowIndex, col: event.colIndex });\n\n if (this.ranges.length > 0) {\n this.ranges[this.ranges.length - 1] = newRange;\n } else {\n this.ranges.push(newRange);\n }\n this.activeRange = newRange;\n\n this.emit<SelectionChangeDetail>('selection-change', this.#buildEvent());\n this.requestAfterRender();\n return true;\n }\n\n override onCellMouseUp(_event: CellMouseEvent): boolean | void {\n if (this.config.mode !== 'range') return;\n if (this.isDragging) {\n this.isDragging = false;\n return true;\n }\n }\n\n /**\n * Apply selection classes to visible cells/rows.\n * Shared by afterRender and onScrollRender.\n */\n #applySelectionClasses(): void {\n const shadowRoot = this.shadowRoot;\n if (!shadowRoot) return;\n\n const { mode } = this.config;\n\n // Clear all selection classes first\n const allCells = shadowRoot.querySelectorAll('.cell');\n allCells.forEach((cell) => {\n cell.classList.remove('selected', 'top', 'bottom', 'first', 'last');\n });\n\n const allRows = shadowRoot.querySelectorAll('.data-grid-row');\n allRows.forEach((row) => {\n row.classList.remove('selected', 'row-focus');\n });\n\n // ROW MODE: Add row-focus class to selected rows, disable cell-focus\n if (mode === 'row') {\n // In row mode, disable ALL cell-focus styling - row selection takes precedence\n shadowRoot.querySelectorAll('.cell-focus').forEach((cell) => cell.classList.remove('cell-focus'));\n\n allRows.forEach((row) => {\n const firstCell = row.querySelector('.cell[data-row]');\n const rowIndex = parseInt(firstCell?.getAttribute('data-row') ?? '-1', 10);\n if (rowIndex >= 0 && this.selected.has(rowIndex)) {\n row.classList.add('selected', 'row-focus');\n }\n });\n }\n\n // RANGE MODE: Add selected and edge classes to cells\n if (mode === 'range' && this.ranges.length > 0) {\n const normalized = this.activeRange ? normalizeRange(this.activeRange) : null;\n\n const cells = shadowRoot.querySelectorAll('.cell[data-row][data-col]');\n cells.forEach((cell) => {\n const rowIndex = parseInt(cell.getAttribute('data-row') ?? '-1', 10);\n const colIndex = parseInt(cell.getAttribute('data-col') ?? '-1', 10);\n if (rowIndex >= 0 && colIndex >= 0) {\n const inRange = isCellInAnyRange(rowIndex, colIndex, this.ranges);\n\n if (inRange) {\n cell.classList.add('selected');\n // Remove cell-focus from selected cells - selection highlight takes precedence\n cell.classList.remove('cell-focus');\n\n if (normalized) {\n if (rowIndex === normalized.startRow) cell.classList.add('top');\n if (rowIndex === normalized.endRow) cell.classList.add('bottom');\n if (colIndex === normalized.startCol) cell.classList.add('first');\n if (colIndex === normalized.endCol) cell.classList.add('last');\n }\n }\n }\n });\n }\n\n // CELL MODE: Remove cell-focus when selection plugin handles focus\n if (mode === 'cell' && this.selectedCell) {\n // Remove all cell-focus - the selection plugin manages focus styling\n shadowRoot.querySelectorAll('.cell-focus').forEach((cell) => cell.classList.remove('cell-focus'));\n }\n }\n\n override afterRender(): void {\n const shadowRoot = this.shadowRoot;\n if (!shadowRoot) return;\n\n const container = shadowRoot.children[0];\n const { mode } = this.config;\n\n // Process pending keyboard navigation update (range mode)\n // This runs AFTER the grid has updated focusRow/focusCol\n if (this.pendingKeyboardUpdate && mode === 'range') {\n const { shiftKey } = this.pendingKeyboardUpdate;\n this.pendingKeyboardUpdate = null;\n\n const currentRow = this.grid._focusRow;\n const currentCol = this.grid._focusCol;\n\n if (shiftKey && this.cellAnchor) {\n // Extend selection from anchor to current focus\n const newRange = createRangeFromAnchor(this.cellAnchor, { row: currentRow, col: currentCol });\n this.ranges = [newRange];\n this.activeRange = newRange;\n } else if (!shiftKey) {\n // Without shift, clear selection (cell-focus will show instead)\n this.ranges = [];\n this.activeRange = null;\n this.cellAnchor = { row: currentRow, col: currentCol }; // Reset anchor to current position\n }\n\n this.emit<SelectionChangeDetail>('selection-change', this.#buildEvent());\n }\n\n // Set data attribute on host for CSS variable scoping\n (this.grid as unknown as Element).setAttribute('data-selection-mode', mode);\n\n // Toggle .selecting class during drag to prevent text selection\n if (container) {\n container.classList.toggle('selecting', this.isDragging);\n }\n\n this.#applySelectionClasses();\n }\n\n /**\n * Called after scroll-triggered row rendering.\n * Reapplies selection classes to recycled DOM elements.\n */\n override onScrollRender(): void {\n this.#applySelectionClasses();\n }\n\n // #endregion\n\n // #region Public API\n\n /**\n * Get the selected cell (cell mode only).\n */\n getSelectedCell(): { row: number; col: number } | null {\n return this.selectedCell;\n }\n\n /**\n * Get all selected row indices (row mode).\n */\n getSelectedRows(): number[] {\n return [...this.selected];\n }\n\n /**\n * Get all selected cell ranges in public format.\n */\n getRanges(): CellRange[] {\n return toPublicRanges(this.ranges);\n }\n\n /**\n * Get all selected cells across all ranges.\n */\n getSelectedCells(): Array<{ row: number; col: number }> {\n return getAllCellsInRanges(this.ranges);\n }\n\n /**\n * Check if a specific cell is in range selection.\n */\n isCellSelected(row: number, col: number): boolean {\n return isCellInAnyRange(row, col, this.ranges);\n }\n\n /**\n * Clear all selection.\n */\n clearSelection(): void {\n this.selectedCell = null;\n this.selected.clear();\n this.anchor = null;\n this.ranges = [];\n this.activeRange = null;\n this.cellAnchor = null;\n this.emit<SelectionChangeDetail>('selection-change', { mode: this.config.mode, ranges: [] });\n this.requestAfterRender();\n }\n\n /**\n * Set selected ranges programmatically.\n */\n setRanges(ranges: CellRange[]): void {\n this.ranges = ranges.map((r) => ({\n startRow: r.from.row,\n startCol: r.from.col,\n endRow: r.to.row,\n endCol: r.to.col,\n }));\n this.activeRange = this.ranges.length > 0 ? this.ranges[this.ranges.length - 1] : null;\n this.emit<SelectionChangeDetail>('selection-change', {\n mode: this.config.mode,\n ranges: toPublicRanges(this.ranges),\n });\n this.requestAfterRender();\n }\n\n // #endregion\n\n // #region Private Helpers\n\n #buildEvent(): SelectionChangeDetail {\n return buildSelectionEvent(\n this.config.mode,\n {\n selectedCell: this.selectedCell,\n selected: this.selected,\n ranges: this.ranges,\n },\n this.columns.length,\n );\n }\n\n // #endregion\n\n // #region Styles\n\n override readonly styles = styles;\n\n // #endregion\n}\n","import type { ServerSideDataSource, GetRowsParams, GetRowsResult } from './types';\n\nexport function getBlockNumber(rowIndex: number, blockSize: number): number {\n return Math.floor(rowIndex / blockSize);\n}\n\nexport function getBlockRange(blockNumber: number, blockSize: number): { start: number; end: number } {\n return {\n start: blockNumber * blockSize,\n end: (blockNumber + 1) * blockSize,\n };\n}\n\nexport function getRequiredBlocks(startRow: number, endRow: number, blockSize: number): number[] {\n const startBlock = getBlockNumber(startRow, blockSize);\n const endBlock = getBlockNumber(endRow - 1, blockSize);\n\n const blocks: number[] = [];\n for (let i = startBlock; i <= endBlock; i++) {\n blocks.push(i);\n }\n return blocks;\n}\n\nexport async function loadBlock(\n dataSource: ServerSideDataSource,\n blockNumber: number,\n blockSize: number,\n params: Partial<GetRowsParams>\n): Promise<GetRowsResult> {\n const range = getBlockRange(blockNumber, blockSize);\n\n return dataSource.getRows({\n startRow: range.start,\n endRow: range.end,\n sortModel: params.sortModel,\n filterModel: params.filterModel,\n });\n}\n\nexport function getRowFromCache(\n rowIndex: number,\n blockSize: number,\n loadedBlocks: Map<number, any[]>\n): any | undefined {\n const blockNumber = getBlockNumber(rowIndex, blockSize);\n const block = loadedBlocks.get(blockNumber);\n if (!block) return undefined;\n\n const indexInBlock = rowIndex % blockSize;\n return block[indexInBlock];\n}\n\nexport function isBlockLoaded(blockNumber: number, loadedBlocks: Map<number, any[]>): boolean {\n return loadedBlocks.has(blockNumber);\n}\n\nexport function isBlockLoading(blockNumber: number, loadingBlocks: Set<number>): boolean {\n return loadingBlocks.has(blockNumber);\n}\n","/**\n * Server-Side Data Plugin (Class-based)\n *\n * Provides server-side data loading with caching and lazy loading.\n */\n\nimport { BaseGridPlugin, ScrollEvent } from '../../core/plugin/base-plugin';\nimport { getBlockNumber, getRequiredBlocks, getRowFromCache, loadBlock } from './datasource';\nimport type { ServerSideConfig, ServerSideDataSource } from './types';\n\n/** Scroll debounce delay in ms */\nconst SCROLL_DEBOUNCE_MS = 100;\n\n/**\n * Server-Side Plugin for tbw-grid\n *\n * @example\n * ```ts\n * const plugin = new ServerSidePlugin({ cacheBlockSize: 100 });\n * plugin.setDataSource(myDataSource);\n * ```\n */\nexport class ServerSidePlugin extends BaseGridPlugin<ServerSideConfig> {\n readonly name = 'serverSide';\n override readonly version = '1.0.0';\n\n protected override get defaultConfig(): Partial<ServerSideConfig> {\n return {\n pageSize: 100,\n cacheBlockSize: 100,\n maxConcurrentRequests: 2,\n };\n }\n\n // #region Internal State\n private dataSource: ServerSideDataSource | null = null;\n private totalRowCount = 0;\n private loadedBlocks = new Map<number, unknown[]>();\n private loadingBlocks = new Set<number>();\n private lastRequestId = 0;\n private scrollDebounceTimer?: ReturnType<typeof setTimeout>;\n // #endregion\n\n // #region Lifecycle\n\n override detach(): void {\n this.dataSource = null;\n this.totalRowCount = 0;\n this.loadedBlocks.clear();\n this.loadingBlocks.clear();\n this.lastRequestId = 0;\n if (this.scrollDebounceTimer) {\n clearTimeout(this.scrollDebounceTimer);\n this.scrollDebounceTimer = undefined;\n }\n }\n // #endregion\n\n // #region Private Methods\n\n /**\n * Check current viewport and load any missing blocks.\n */\n private loadRequiredBlocks(): void {\n if (!this.dataSource) return;\n\n // Get fresh viewport from grid's virtualization state\n const gridRef = this.grid as unknown as { _virtualization: { start: number; end: number } };\n const blockSize = this.config.cacheBlockSize ?? 100;\n const viewport = { startRow: gridRef._virtualization.start, endRow: gridRef._virtualization.end };\n\n // Determine which blocks are needed for current viewport\n const requiredBlocks = getRequiredBlocks(viewport.startRow, viewport.endRow, blockSize);\n\n // Load missing blocks\n for (const blockNum of requiredBlocks) {\n if (this.loadedBlocks.has(blockNum) || this.loadingBlocks.has(blockNum)) {\n continue;\n }\n\n // Check concurrent request limit\n if (this.loadingBlocks.size >= (this.config.maxConcurrentRequests ?? 2)) {\n break;\n }\n\n this.loadingBlocks.add(blockNum);\n\n loadBlock(this.dataSource, blockNum, blockSize, {})\n .then((result) => {\n this.loadedBlocks.set(blockNum, result.rows);\n this.totalRowCount = result.totalRowCount;\n this.loadingBlocks.delete(blockNum);\n this.requestRender();\n // Re-check with fresh viewport: user may have scrolled further\n this.loadRequiredBlocks();\n })\n .catch(() => {\n this.loadingBlocks.delete(blockNum);\n });\n }\n }\n // #endregion\n\n // #region Hooks\n\n override processRows(rows: readonly unknown[]): unknown[] {\n if (!this.dataSource) return [...rows];\n\n // Create placeholder rows for total count\n const result: unknown[] = [];\n for (let i = 0; i < this.totalRowCount; i++) {\n const cached = getRowFromCache(i, this.config.cacheBlockSize ?? 100, this.loadedBlocks);\n result.push(cached ?? { __loading: true, __index: i });\n }\n\n return result;\n }\n\n override onScroll(event: ScrollEvent): void {\n if (!this.dataSource) return;\n\n // Immediate check for blocks\n this.loadRequiredBlocks();\n\n // Debounce: when scrolling stops, do a final check with fresh viewport\n if (this.scrollDebounceTimer) {\n clearTimeout(this.scrollDebounceTimer);\n }\n this.scrollDebounceTimer = setTimeout(() => {\n this.loadRequiredBlocks();\n }, SCROLL_DEBOUNCE_MS);\n }\n // #endregion\n\n // #region Public API\n\n /**\n * Set the data source for server-side loading.\n * @param dataSource - Data source implementing the getRows method\n */\n setDataSource(dataSource: ServerSideDataSource): void {\n this.dataSource = dataSource;\n this.loadedBlocks.clear();\n this.loadingBlocks.clear();\n\n // Load first block\n const blockSize = this.config.cacheBlockSize ?? 100;\n loadBlock(dataSource, 0, blockSize, {}).then((result) => {\n this.loadedBlocks.set(0, result.rows);\n this.totalRowCount = result.totalRowCount;\n this.requestRender();\n });\n }\n\n /**\n * Refresh all data from the server.\n */\n refresh(): void {\n if (!this.dataSource) return;\n this.loadedBlocks.clear();\n this.loadingBlocks.clear();\n this.requestRender();\n }\n\n /**\n * Clear all cached data without refreshing.\n */\n purgeCache(): void {\n this.loadedBlocks.clear();\n }\n\n /**\n * Get the total row count from the server.\n */\n getTotalRowCount(): number {\n return this.totalRowCount;\n }\n\n /**\n * Check if a specific row is loaded in the cache.\n * @param rowIndex - Row index to check\n */\n isRowLoaded(rowIndex: number): boolean {\n const blockSize = this.config.cacheBlockSize ?? 100;\n const blockNum = getBlockNumber(rowIndex, blockSize);\n return this.loadedBlocks.has(blockNum);\n }\n\n /**\n * Get the number of loaded cache blocks.\n */\n getLoadedBlockCount(): number {\n return this.loadedBlocks.size;\n }\n // #endregion\n}\n","/**\n * Core Tree Data Logic\n *\n * Pure functions for tree flattening, expansion, and traversal.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n// The tree plugin intentionally uses `any` for maximum flexibility with user-defined row types.\n\nimport type { FlattenedTreeRow, TreeConfig } from './types';\n\n/**\n * Generates a unique key for a row.\n * Uses row.id if available, otherwise generates from path.\n */\nexport function generateRowKey(row: any, index: number, parentKey: string | null): string {\n if (row.id !== undefined) return String(row.id);\n return parentKey ? `${parentKey}-${index}` : String(index);\n}\n\n/**\n * Flattens a hierarchical tree into a flat array of rows with metadata.\n * Only includes children of expanded nodes.\n */\nexport function flattenTree(\n rows: any[],\n config: TreeConfig,\n expandedKeys: Set<string>,\n parentKey: string | null = null,\n depth = 0\n): FlattenedTreeRow[] {\n const childrenField = config.childrenField ?? 'children';\n const result: FlattenedTreeRow[] = [];\n\n for (let i = 0; i < rows.length; i++) {\n const row = rows[i];\n const key = generateRowKey(row, i, parentKey);\n const children = row[childrenField];\n const hasChildren = Array.isArray(children) && children.length > 0;\n const isExpanded = expandedKeys.has(key);\n\n result.push({\n key,\n data: row,\n depth,\n hasChildren,\n isExpanded,\n parentKey,\n });\n\n // Recursively add children if expanded\n if (hasChildren && isExpanded) {\n const childRows = flattenTree(children, config, expandedKeys, key, depth + 1);\n result.push(...childRows);\n }\n }\n\n return result;\n}\n\n/**\n * Toggles the expansion state of a row.\n * Returns a new Set with the toggled state.\n */\nexport function toggleExpand(expandedKeys: Set<string>, key: string): Set<string> {\n const newExpanded = new Set(expandedKeys);\n if (newExpanded.has(key)) {\n newExpanded.delete(key);\n } else {\n newExpanded.add(key);\n }\n return newExpanded;\n}\n\n/**\n * Expands all nodes in the tree.\n * Returns a Set of all parent row keys.\n */\nexport function expandAll(rows: any[], config: TreeConfig, parentKey: string | null = null, depth = 0): Set<string> {\n const childrenField = config.childrenField ?? 'children';\n const keys = new Set<string>();\n\n for (let i = 0; i < rows.length; i++) {\n const row = rows[i];\n const key = generateRowKey(row, i, parentKey);\n const children = row[childrenField];\n\n if (Array.isArray(children) && children.length > 0) {\n keys.add(key);\n const childKeys = expandAll(children, config, key, depth + 1);\n for (const k of childKeys) keys.add(k);\n }\n }\n\n return keys;\n}\n\n/**\n * Collapses all nodes.\n * Returns an empty Set.\n */\nexport function collapseAll(): Set<string> {\n return new Set();\n}\n\n/**\n * Gets all descendants of a node from the flattened row list.\n * Useful for operations that need to affect an entire subtree.\n */\nexport function getDescendants(flattenedRows: FlattenedTreeRow[], parentKey: string): FlattenedTreeRow[] {\n const descendants: FlattenedTreeRow[] = [];\n let collecting = false;\n let parentDepth = -1;\n\n for (const row of flattenedRows) {\n if (row.key === parentKey) {\n collecting = true;\n parentDepth = row.depth;\n continue;\n }\n\n if (collecting) {\n if (row.depth > parentDepth) {\n descendants.push(row);\n } else {\n break; // No longer a descendant\n }\n }\n }\n\n return descendants;\n}\n\n/**\n * Finds the path from root to a specific row key.\n * Returns an array of keys from root to the target (inclusive).\n */\nexport function getPathToKey(\n rows: any[],\n targetKey: string,\n config: TreeConfig,\n parentKey: string | null = null,\n depth = 0\n): string[] | null {\n const childrenField = config.childrenField ?? 'children';\n\n for (let i = 0; i < rows.length; i++) {\n const row = rows[i];\n const key = generateRowKey(row, i, parentKey);\n\n if (key === targetKey) {\n return [key];\n }\n\n const children = row[childrenField];\n if (Array.isArray(children) && children.length > 0) {\n const childPath = getPathToKey(children, targetKey, config, key, depth + 1);\n if (childPath) {\n return [key, ...childPath];\n }\n }\n }\n\n return null;\n}\n\n/**\n * Expands all ancestors of a specific row to make it visible.\n * Returns a new Set with the required keys added.\n */\nexport function expandToKey(\n rows: any[],\n targetKey: string,\n config: TreeConfig,\n existingExpanded: Set<string>\n): Set<string> {\n const path = getPathToKey(rows, targetKey, config);\n if (!path) return existingExpanded;\n\n const newExpanded = new Set(existingExpanded);\n // Add all keys except the last one (the target itself)\n for (let i = 0; i < path.length - 1; i++) {\n newExpanded.add(path[i]);\n }\n return newExpanded;\n}\n","/**\n * Tree Structure Auto-Detection\n *\n * Utilities for detecting hierarchical tree data structures.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n// The tree plugin intentionally uses `any` for maximum flexibility with user-defined row types.\n\n/**\n * Detects if the data has a tree structure by checking for children arrays.\n */\nexport function detectTreeStructure(rows: any[], childrenField = 'children'): boolean {\n if (!Array.isArray(rows) || rows.length === 0) return false;\n\n // Check if any row has a non-empty children array\n for (const row of rows) {\n if (row && Array.isArray(row[childrenField]) && row[childrenField].length > 0) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Attempts to infer the children field name from common patterns.\n * Returns the first field that contains an array with items.\n */\nexport function inferChildrenField(rows: any[]): string | null {\n if (!Array.isArray(rows) || rows.length === 0) return null;\n\n const commonArrayFields = ['children', 'items', 'nodes', 'subRows', 'nested'];\n\n for (const row of rows) {\n if (!row || typeof row !== 'object') continue;\n\n for (const field of commonArrayFields) {\n if (Array.isArray(row[field]) && row[field].length > 0) {\n return field;\n }\n }\n }\n\n return null;\n}\n\n/**\n * Calculates the maximum depth of the tree.\n * Useful for layout calculations and virtualization.\n */\nexport function getMaxDepth(rows: any[], childrenField = 'children', currentDepth = 0): number {\n if (!Array.isArray(rows) || rows.length === 0) return currentDepth;\n\n let maxDepth = currentDepth;\n\n for (const row of rows) {\n if (!row) continue;\n const children = row[childrenField];\n if (Array.isArray(children) && children.length > 0) {\n const childDepth = getMaxDepth(children, childrenField, currentDepth + 1);\n if (childDepth > maxDepth) {\n maxDepth = childDepth;\n }\n }\n }\n\n return maxDepth;\n}\n\n/**\n * Counts total nodes in the tree (including all descendants).\n */\nexport function countNodes(rows: any[], childrenField = 'children'): number {\n if (!Array.isArray(rows)) return 0;\n\n let count = 0;\n for (const row of rows) {\n if (!row) continue;\n count++;\n const children = row[childrenField];\n if (Array.isArray(children)) {\n count += countNodes(children, childrenField);\n }\n }\n\n return count;\n}\n","/**\n * Tree Data Plugin\n *\n * Enables hierarchical tree data with expand/collapse, sorting, and auto-detection.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { BaseGridPlugin, CellClickEvent, HeaderClickEvent } from '../../core/plugin/base-plugin';\nimport type { ColumnConfig, GridConfig } from '../../core/types';\nimport { collapseAll, expandAll, expandToKey, toggleExpand } from './tree-data';\nimport { detectTreeStructure, inferChildrenField } from './tree-detect';\nimport styles from './tree.css?inline';\nimport type { ExpandCollapseAnimation, FlattenedTreeRow, TreeConfig, TreeExpandDetail } from './types';\n\ninterface GridWithConfig {\n effectiveConfig?: GridConfig;\n _sortState?: { field: string; direction: 1 | -1 } | null;\n}\n\n/**\n * Tree Data Plugin for tbw-grid\n *\n * @example\n * ```ts\n * new TreePlugin({ defaultExpanded: true, indentWidth: 24 })\n * ```\n */\nexport class TreePlugin extends BaseGridPlugin<TreeConfig> {\n readonly name = 'tree';\n override readonly version = '1.0.0';\n override readonly styles = styles;\n\n protected override get defaultConfig(): Partial<TreeConfig> {\n return {\n childrenField: 'children',\n autoDetect: true,\n defaultExpanded: false,\n indentWidth: 20,\n showExpandIcons: true,\n animation: 'slide',\n };\n }\n\n // #region State\n\n private expandedKeys = new Set<string>();\n private initialExpansionDone = false;\n private flattenedRows: FlattenedTreeRow[] = [];\n private rowKeyMap = new Map<string, FlattenedTreeRow>();\n private previousVisibleKeys = new Set<string>();\n private keysToAnimate = new Set<string>();\n private sortState: { field: string; direction: 1 | -1 } | null = null;\n\n override detach(): void {\n this.expandedKeys.clear();\n this.initialExpansionDone = false;\n this.flattenedRows = [];\n this.rowKeyMap.clear();\n this.previousVisibleKeys.clear();\n this.keysToAnimate.clear();\n this.sortState = null;\n }\n\n // #endregion\n\n // #region Animation\n\n private get animationStyle(): ExpandCollapseAnimation {\n const gridEl = this.grid as unknown as GridWithConfig;\n const mode = gridEl.effectiveConfig?.animation?.mode ?? 'reduced-motion';\n\n if (mode === false || mode === 'off') return false;\n if (mode !== true && mode !== 'on') {\n const host = this.shadowRoot?.host as HTMLElement | undefined;\n if (host && getComputedStyle(host).getPropertyValue('--tbw-animation-enabled').trim() === '0') {\n return false;\n }\n }\n return this.config.animation ?? 'slide';\n }\n\n // #endregion\n\n // #region Auto-Detection\n\n detect(rows: readonly unknown[]): boolean {\n if (!this.config.autoDetect) return false;\n const field = this.config.childrenField ?? inferChildrenField(rows as any[]) ?? 'children';\n return detectTreeStructure(rows as any[], field);\n }\n\n // #endregion\n\n // #region Data Processing\n\n override processRows(rows: readonly unknown[]): any[] {\n const childrenField = this.config.childrenField ?? 'children';\n\n if (!detectTreeStructure(rows as any[], childrenField)) {\n this.flattenedRows = [];\n this.rowKeyMap.clear();\n this.previousVisibleKeys.clear();\n return [...rows];\n }\n\n // Assign stable keys, then optionally sort\n let data = this.withStableKeys(rows as any[]);\n if (this.sortState) {\n data = this.sortTree(data, this.sortState.field, this.sortState.direction);\n }\n\n // Initialize expansion if needed\n if (this.config.defaultExpanded && !this.initialExpansionDone) {\n this.expandedKeys = expandAll(data, this.config);\n this.initialExpansionDone = true;\n }\n\n // Flatten and track animations\n this.flattenedRows = this.flattenTree(data, this.expandedKeys);\n this.rowKeyMap.clear();\n this.keysToAnimate.clear();\n const currentKeys = new Set<string>();\n\n for (const row of this.flattenedRows) {\n this.rowKeyMap.set(row.key, row);\n currentKeys.add(row.key);\n if (!this.previousVisibleKeys.has(row.key) && row.depth > 0) {\n this.keysToAnimate.add(row.key);\n }\n }\n this.previousVisibleKeys = currentKeys;\n\n return this.flattenedRows.map((r) => ({\n ...r.data,\n __treeKey: r.key,\n __treeDepth: r.depth,\n __treeHasChildren: r.hasChildren,\n __treeExpanded: r.isExpanded,\n }));\n }\n\n /** Assign stable keys to rows (preserves key across sort operations) */\n private withStableKeys(rows: any[], parentKey: string | null = null): any[] {\n const childrenField = this.config.childrenField ?? 'children';\n return rows.map((row, i) => {\n const key =\n row.id !== undefined ? String(row.id) : (row.__stableKey ?? (parentKey ? `${parentKey}-${i}` : String(i)));\n const children = row[childrenField];\n const hasChildren = Array.isArray(children) && children.length > 0;\n return {\n ...row,\n __stableKey: key,\n ...(hasChildren ? { [childrenField]: this.withStableKeys(children, key) } : {}),\n };\n });\n }\n\n /** Flatten tree using stable keys */\n private flattenTree(rows: any[], expanded: Set<string>, depth = 0): FlattenedTreeRow[] {\n const childrenField = this.config.childrenField ?? 'children';\n const result: FlattenedTreeRow[] = [];\n\n for (const row of rows) {\n const key = row.__stableKey ?? row.id ?? '?';\n const children = row[childrenField];\n const hasChildren = Array.isArray(children) && children.length > 0;\n const isExpanded = expanded.has(key);\n\n result.push({\n key,\n data: row,\n depth,\n hasChildren,\n isExpanded,\n parentKey: depth > 0 ? key.substring(0, key.lastIndexOf('-')) || null : null,\n });\n\n if (hasChildren && isExpanded) {\n result.push(...this.flattenTree(children, expanded, depth + 1));\n }\n }\n return result;\n }\n\n /** Sort tree recursively, keeping children with parents */\n private sortTree(rows: any[], field: string, dir: 1 | -1): any[] {\n const childrenField = this.config.childrenField ?? 'children';\n const sorted = [...rows].sort((a, b) => {\n const aVal = a[field],\n bVal = b[field];\n if (aVal == null && bVal == null) return 0;\n if (aVal == null) return -1;\n if (bVal == null) return 1;\n return aVal > bVal ? dir : aVal < bVal ? -dir : 0;\n });\n return sorted.map((row) => {\n const children = row[childrenField];\n return Array.isArray(children) && children.length > 0\n ? { ...row, [childrenField]: this.sortTree(children, field, dir) }\n : row;\n });\n }\n\n override processColumns(columns: readonly ColumnConfig[]): ColumnConfig[] {\n if (this.flattenedRows.length === 0) return [...columns];\n\n const cols = [...columns] as ColumnConfig[];\n if (cols.length === 0) return cols;\n\n const firstCol = { ...cols[0] };\n const original = firstCol.viewRenderer;\n if ((original as any)?.__treeWrapped) return cols;\n\n const getConfig = () => this.config;\n const setIcon = this.setIcon.bind(this);\n const resolveIcon = this.resolveIcon.bind(this);\n\n const wrapped = (ctx: Parameters<NonNullable<typeof original>>[0]) => {\n const { value, row } = ctx;\n const { indentWidth = 20, showExpandIcons = true } = getConfig();\n\n const container = document.createElement('span');\n container.className = 'tree-cell';\n container.style.setProperty('--tree-depth', String(row.__treeDepth ?? 0));\n container.style.setProperty('--tbw-tree-indent', `${indentWidth}px`);\n\n if (row.__treeHasChildren && showExpandIcons) {\n const icon = document.createElement('span');\n icon.className = `tree-toggle${row.__treeExpanded ? ' expanded' : ''}`;\n setIcon(icon, resolveIcon(row.__treeExpanded ? 'collapse' : 'expand'));\n icon.setAttribute('data-tree-key', row.__treeKey);\n container.appendChild(icon);\n } else if (showExpandIcons) {\n const spacer = document.createElement('span');\n spacer.className = 'tree-spacer';\n container.appendChild(spacer);\n }\n\n const content = document.createElement('span');\n if (original) {\n const rendered = original(ctx);\n if (rendered instanceof Node) {\n content.appendChild(rendered);\n } else {\n content.textContent = String(rendered ?? value ?? '');\n }\n } else {\n content.textContent = String(value ?? '');\n }\n container.appendChild(content);\n return container;\n };\n\n (wrapped as any).__treeWrapped = true;\n firstCol.viewRenderer = wrapped;\n cols[0] = firstCol;\n return cols;\n }\n\n // #endregion\n\n // #region Event Handlers\n\n override onCellClick(event: CellClickEvent): boolean {\n const target = event.originalEvent?.target as HTMLElement;\n if (!target?.classList.contains('tree-toggle')) return false;\n\n const key = target.getAttribute('data-tree-key');\n const flatRow = key ? this.rowKeyMap.get(key) : null;\n if (!flatRow) return false;\n\n this.expandedKeys = toggleExpand(this.expandedKeys, key!);\n this.emit<TreeExpandDetail>('tree-expand', {\n key: key!,\n row: flatRow.data,\n expanded: this.expandedKeys.has(key!),\n depth: flatRow.depth,\n });\n this.requestRender();\n return true;\n }\n\n override onHeaderClick(event: HeaderClickEvent): boolean {\n if (this.flattenedRows.length === 0 || !event.column.sortable) return false;\n\n const { field } = event.column;\n if (!this.sortState || this.sortState.field !== field) {\n this.sortState = { field, direction: 1 };\n } else if (this.sortState.direction === 1) {\n this.sortState = { field, direction: -1 };\n } else {\n this.sortState = null;\n }\n\n // Sync grid sort indicator\n const gridEl = this.grid as unknown as GridWithConfig;\n if (gridEl._sortState !== undefined) {\n gridEl._sortState = this.sortState ? { ...this.sortState } : null;\n }\n\n this.emit('sort-change', { field, direction: this.sortState?.direction ?? 0 });\n this.requestRender();\n return true;\n }\n\n override afterRender(): void {\n const style = this.animationStyle;\n if (style === false || this.keysToAnimate.size === 0) return;\n\n const body = this.shadowRoot?.querySelector('.rows');\n if (!body) return;\n\n const animClass = style === 'fade' ? 'tbw-tree-fade-in' : 'tbw-tree-slide-in';\n for (const rowEl of body.querySelectorAll('.data-grid-row')) {\n const cell = rowEl.querySelector('.cell[data-row]');\n const idx = cell ? parseInt(cell.getAttribute('data-row') ?? '-1', 10) : -1;\n const key = this.flattenedRows[idx]?.key;\n\n if (key && this.keysToAnimate.has(key)) {\n rowEl.classList.add(animClass);\n rowEl.addEventListener('animationend', () => rowEl.classList.remove(animClass), { once: true });\n }\n }\n this.keysToAnimate.clear();\n }\n\n // #endregion\n\n // #region Public API\n\n expand(key: string): void {\n this.expandedKeys.add(key);\n this.requestRender();\n }\n\n collapse(key: string): void {\n this.expandedKeys.delete(key);\n this.requestRender();\n }\n\n toggle(key: string): void {\n this.expandedKeys = toggleExpand(this.expandedKeys, key);\n this.requestRender();\n }\n\n expandAll(): void {\n this.expandedKeys = expandAll(this.rows as any[], this.config);\n this.requestRender();\n }\n\n collapseAll(): void {\n this.expandedKeys = collapseAll();\n this.requestRender();\n }\n\n isExpanded(key: string): boolean {\n return this.expandedKeys.has(key);\n }\n\n getExpandedKeys(): string[] {\n return [...this.expandedKeys];\n }\n\n getFlattenedRows(): FlattenedTreeRow[] {\n return [...this.flattenedRows];\n }\n\n getRowByKey(key: string): any | undefined {\n return this.rowKeyMap.get(key)?.data;\n }\n\n expandToKey(key: string): void {\n this.expandedKeys = expandToKey(this.rows as any[], key, this.config, this.expandedKeys);\n this.requestRender();\n }\n\n // #endregion\n}\n","/**\n * Undo/Redo History Management\n *\n * Pure functions for managing the undo/redo stacks.\n * These functions are stateless and return new state objects.\n */\n\nimport type { EditAction, UndoRedoState } from './types';\n\n/**\n * Push a new action onto the undo stack.\n * Clears the redo stack since new actions invalidate redo history.\n *\n * @param state - Current undo/redo state\n * @param action - The action to add\n * @param maxSize - Maximum history size\n * @returns New state with the action added\n */\nexport function pushAction(state: UndoRedoState, action: EditAction, maxSize: number): UndoRedoState {\n const undoStack = [...state.undoStack, action];\n\n // Trim oldest actions if over max size\n while (undoStack.length > maxSize) {\n undoStack.shift();\n }\n\n return {\n undoStack,\n redoStack: [], // Clear redo on new action\n };\n}\n\n/**\n * Undo the most recent action.\n * Moves the action from undo stack to redo stack.\n *\n * @param state - Current undo/redo state\n * @returns New state and the action that was undone (or null if nothing to undo)\n */\nexport function undo(state: UndoRedoState): {\n newState: UndoRedoState;\n action: EditAction | null;\n} {\n if (state.undoStack.length === 0) {\n return { newState: state, action: null };\n }\n\n const undoStack = [...state.undoStack];\n const action = undoStack.pop();\n\n // This should never happen due to the length check above,\n // but TypeScript needs the explicit check\n if (!action) {\n return { newState: state, action: null };\n }\n\n return {\n newState: {\n undoStack,\n redoStack: [...state.redoStack, action],\n },\n action,\n };\n}\n\n/**\n * Redo the most recently undone action.\n * Moves the action from redo stack back to undo stack.\n *\n * @param state - Current undo/redo state\n * @returns New state and the action that was redone (or null if nothing to redo)\n */\nexport function redo(state: UndoRedoState): {\n newState: UndoRedoState;\n action: EditAction | null;\n} {\n if (state.redoStack.length === 0) {\n return { newState: state, action: null };\n }\n\n const redoStack = [...state.redoStack];\n const action = redoStack.pop();\n\n // This should never happen due to the length check above,\n // but TypeScript needs the explicit check\n if (!action) {\n return { newState: state, action: null };\n }\n\n return {\n newState: {\n undoStack: [...state.undoStack, action],\n redoStack,\n },\n action,\n };\n}\n\n/**\n * Check if there are any actions that can be undone.\n *\n * @param state - Current undo/redo state\n * @returns True if undo is available\n */\nexport function canUndo(state: UndoRedoState): boolean {\n return state.undoStack.length > 0;\n}\n\n/**\n * Check if there are any actions that can be redone.\n *\n * @param state - Current undo/redo state\n * @returns True if redo is available\n */\nexport function canRedo(state: UndoRedoState): boolean {\n return state.redoStack.length > 0;\n}\n\n/**\n * Clear all history, returning an empty state.\n *\n * @returns Fresh empty state\n */\nexport function clearHistory(): UndoRedoState {\n return { undoStack: [], redoStack: [] };\n}\n\n/**\n * Create a new edit action with the current timestamp.\n *\n * @param rowIndex - The row index where the edit occurred\n * @param field - The field (column key) that was edited\n * @param oldValue - The value before the edit\n * @param newValue - The value after the edit\n * @returns A new EditAction object\n */\nexport function createEditAction(rowIndex: number, field: string, oldValue: unknown, newValue: unknown): EditAction {\n return {\n type: 'cell-edit',\n rowIndex,\n field,\n oldValue,\n newValue,\n timestamp: Date.now(),\n };\n}\n","/**\n * Undo/Redo Plugin (Class-based)\n *\n * Provides undo/redo functionality for cell edits in tbw-grid.\n * Supports Ctrl+Z/Cmd+Z for undo and Ctrl+Y/Cmd+Y (or Ctrl+Shift+Z) for redo.\n */\n\nimport { BaseGridPlugin } from '../../core/plugin/base-plugin';\nimport { canRedo, canUndo, clearHistory, createEditAction, pushAction, redo, undo } from './history';\nimport type { EditAction, UndoRedoConfig, UndoRedoDetail } from './types';\n\n/**\n * Class-based Undo/Redo plugin for tbw-grid.\n *\n * Tracks cell edits and provides undo/redo functionality via keyboard shortcuts\n * or programmatic API.\n */\nexport class UndoRedoPlugin extends BaseGridPlugin<UndoRedoConfig> {\n readonly name = 'undoRedo';\n override readonly version = '1.0.0';\n\n protected override get defaultConfig(): Partial<UndoRedoConfig> {\n return {\n maxHistorySize: 100,\n };\n }\n\n // State as class properties\n private undoStack: EditAction[] = [];\n private redoStack: EditAction[] = [];\n\n /**\n * Clean up state when plugin is detached.\n */\n override detach(): void {\n this.undoStack = [];\n this.redoStack = [];\n }\n\n /**\n * Handle keyboard shortcuts for undo/redo.\n * - Ctrl+Z / Cmd+Z: Undo\n * - Ctrl+Y / Cmd+Y / Ctrl+Shift+Z / Cmd+Shift+Z: Redo\n */\n override onKeyDown(event: KeyboardEvent): boolean {\n const isUndo = (event.ctrlKey || event.metaKey) && event.key === 'z' && !event.shiftKey;\n const isRedo = (event.ctrlKey || event.metaKey) && (event.key === 'y' || (event.key === 'z' && event.shiftKey));\n\n if (isUndo) {\n const result = undo({ undoStack: this.undoStack, redoStack: this.redoStack });\n if (result.action) {\n // Apply undo - restore old value\n const rows = this.rows as Record<string, unknown>[];\n if (rows[result.action.rowIndex]) {\n rows[result.action.rowIndex][result.action.field] = result.action.oldValue;\n }\n\n // Update state from result\n this.undoStack = result.newState.undoStack;\n this.redoStack = result.newState.redoStack;\n\n this.emit<UndoRedoDetail>('undo', {\n action: result.action,\n type: 'undo',\n });\n\n this.requestRender();\n }\n return true;\n }\n\n if (isRedo) {\n const result = redo({ undoStack: this.undoStack, redoStack: this.redoStack });\n if (result.action) {\n // Apply redo - restore new value\n const rows = this.rows as Record<string, unknown>[];\n if (rows[result.action.rowIndex]) {\n rows[result.action.rowIndex][result.action.field] = result.action.newValue;\n }\n\n // Update state from result\n this.undoStack = result.newState.undoStack;\n this.redoStack = result.newState.redoStack;\n\n this.emit<UndoRedoDetail>('redo', {\n action: result.action,\n type: 'redo',\n });\n\n this.requestRender();\n }\n return true;\n }\n\n return false;\n }\n\n // #region Public API Methods\n\n /**\n * Record a cell edit for undo/redo tracking.\n * Call this when a cell value changes.\n *\n * @param rowIndex - The row index where the edit occurred\n * @param field - The field (column key) that was edited\n * @param oldValue - The value before the edit\n * @param newValue - The value after the edit\n */\n recordEdit(rowIndex: number, field: string, oldValue: unknown, newValue: unknown): void {\n const action = createEditAction(rowIndex, field, oldValue, newValue);\n const newState = pushAction(\n { undoStack: this.undoStack, redoStack: this.redoStack },\n action,\n this.config.maxHistorySize ?? 100,\n );\n this.undoStack = newState.undoStack;\n this.redoStack = newState.redoStack;\n }\n\n /**\n * Programmatically undo the last action.\n *\n * @returns The undone action, or null if nothing to undo\n */\n undo(): EditAction | null {\n const result = undo({ undoStack: this.undoStack, redoStack: this.redoStack });\n if (result.action) {\n const rows = this.rows as Record<string, unknown>[];\n if (rows[result.action.rowIndex]) {\n rows[result.action.rowIndex][result.action.field] = result.action.oldValue;\n }\n this.undoStack = result.newState.undoStack;\n this.redoStack = result.newState.redoStack;\n this.requestRender();\n }\n return result.action;\n }\n\n /**\n * Programmatically redo the last undone action.\n *\n * @returns The redone action, or null if nothing to redo\n */\n redo(): EditAction | null {\n const result = redo({ undoStack: this.undoStack, redoStack: this.redoStack });\n if (result.action) {\n const rows = this.rows as Record<string, unknown>[];\n if (rows[result.action.rowIndex]) {\n rows[result.action.rowIndex][result.action.field] = result.action.newValue;\n }\n this.undoStack = result.newState.undoStack;\n this.redoStack = result.newState.redoStack;\n this.requestRender();\n }\n return result.action;\n }\n\n /**\n * Check if there are any actions that can be undone.\n */\n canUndo(): boolean {\n return canUndo({ undoStack: this.undoStack, redoStack: this.redoStack });\n }\n\n /**\n * Check if there are any actions that can be redone.\n */\n canRedo(): boolean {\n return canRedo({ undoStack: this.undoStack, redoStack: this.redoStack });\n }\n\n /**\n * Clear all undo/redo history.\n */\n clearHistory(): void {\n const newState = clearHistory();\n this.undoStack = newState.undoStack;\n this.redoStack = newState.redoStack;\n }\n\n /**\n * Get a copy of the current undo stack.\n */\n getUndoStack(): EditAction[] {\n return [...this.undoStack];\n }\n\n /**\n * Get a copy of the current redo stack.\n */\n getRedoStack(): EditAction[] {\n return [...this.redoStack];\n }\n // #endregion\n}\n","/**\n * Column Visibility Plugin (Class-based)\n *\n * Provides a UI for column visibility control via the shell's tool panel system.\n * Column visibility is a core grid feature - this plugin provides:\n * - A tool panel for column visibility management (registered with the shell)\n * - Backward-compatible API methods that delegate to grid.setColumnVisible(), etc.\n *\n * The grid emits 'column-visibility' events when columns are shown/hidden,\n * allowing consumers to save user preferences.\n *\n * When a reorder plugin is present, column rows become draggable for reordering.\n * Drag-drop emits 'column-reorder-request' events that the ReorderPlugin can listen for.\n */\n\nimport { BaseGridPlugin } from '../../core/plugin/base-plugin';\nimport type { ColumnConfig, ToolPanelDefinition } from '../../core/types';\nimport type { VisibilityConfig } from './types';\nimport styles from './visibility.css?inline';\n\n/**\n * Detail for column-reorder-request events emitted when users drag-drop in the visibility panel.\n */\nexport interface ColumnReorderRequestDetail {\n /** The field name of the column to move */\n field: string;\n /** The source index (before move) */\n fromIndex: number;\n /** The target index (after move) */\n toIndex: number;\n}\n\n/**\n * Check if a column can be moved (respects lockPosition/suppressMovable).\n * Inlined to avoid importing from reorder plugin.\n */\nfunction canMoveColumn(column: ColumnConfig): boolean {\n const meta = column.meta ?? {};\n return meta.lockPosition !== true && meta.suppressMovable !== true;\n}\n\n/** Extended grid interface with visibility methods */\ninterface GridWithVisibility {\n shadowRoot: ShadowRoot | null;\n getAllColumns(): Array<{ field: string; header: string; visible: boolean; lockVisible?: boolean }>;\n setColumnVisible(field: string, visible: boolean): void;\n toggleColumnVisibility(field: string): void;\n showAllColumns(): void;\n isColumnVisible(field: string): boolean;\n requestRender(): void;\n openToolPanel(id: string): void;\n closeToolPanel(): void;\n toggleToolPanel(id: string): void;\n activeToolPanel: string | undefined;\n}\n\n/**\n * Column Visibility Plugin for tbw-grid\n *\n * @example\n * ```ts\n * new VisibilityPlugin({ enabled: true, allowHideAll: false })\n * ```\n */\nexport class VisibilityPlugin extends BaseGridPlugin<VisibilityConfig> {\n readonly name = 'visibility';\n override readonly version = '1.0.0';\n\n /** Tool panel ID for shell integration */\n static readonly PANEL_ID = 'columns';\n\n protected override get defaultConfig(): Partial<VisibilityConfig> {\n return {\n allowHideAll: false,\n };\n }\n\n // #region Internal State\n private columnListElement: HTMLElement | null = null;\n\n // Drag state for reorder integration\n private isDragging = false;\n private draggedField: string | null = null;\n private draggedIndex: number | null = null;\n private dropIndex: number | null = null;\n // #endregion\n\n // #region Lifecycle\n\n override detach(): void {\n this.columnListElement = null;\n this.isDragging = false;\n this.draggedField = null;\n this.draggedIndex = null;\n this.dropIndex = null;\n }\n // #endregion\n\n // #region Shell Integration\n\n /**\n * Register the column visibility tool panel with the shell.\n */\n override getToolPanel(): ToolPanelDefinition | undefined {\n return {\n id: VisibilityPlugin.PANEL_ID,\n title: 'Columns',\n icon: '☰',\n tooltip: 'Column visibility',\n order: 100, // High order so it appears last\n render: (container) => this.renderPanelContent(container),\n };\n }\n // #endregion\n\n // #region Public API\n\n /**\n * Show the visibility sidebar panel.\n */\n show(): void {\n const grid = this.grid as unknown as GridWithVisibility;\n grid.openToolPanel(VisibilityPlugin.PANEL_ID);\n }\n\n /**\n * Hide the visibility sidebar panel.\n */\n hide(): void {\n const grid = this.grid as unknown as GridWithVisibility;\n grid.closeToolPanel();\n }\n\n /**\n * Toggle the visibility sidebar panel.\n */\n toggle(): void {\n const grid = this.grid as unknown as GridWithVisibility;\n grid.toggleToolPanel(VisibilityPlugin.PANEL_ID);\n }\n\n /**\n * Check if a specific column is visible.\n * Delegates to grid.isColumnVisible().\n * @param field - The field name to check\n * @returns True if the column is visible\n */\n isColumnVisible(field: string): boolean {\n const grid = this.grid as unknown as GridWithVisibility;\n return grid.isColumnVisible(field);\n }\n\n /**\n * Set visibility for a specific column.\n * Delegates to grid.setColumnVisible().\n * @param field - The field name of the column\n * @param visible - Whether the column should be visible\n */\n setColumnVisible(field: string, visible: boolean): void {\n const grid = this.grid as unknown as GridWithVisibility;\n grid.setColumnVisible(field, visible);\n }\n\n /**\n * Get list of all visible column fields.\n * @returns Array of visible field names\n */\n getVisibleColumns(): string[] {\n const grid = this.grid as unknown as GridWithVisibility;\n return grid\n .getAllColumns()\n .filter((c) => c.visible)\n .map((c) => c.field);\n }\n\n /**\n * Get list of all hidden column fields.\n * @returns Array of hidden field names\n */\n getHiddenColumns(): string[] {\n const grid = this.grid as unknown as GridWithVisibility;\n return grid\n .getAllColumns()\n .filter((c) => !c.visible)\n .map((c) => c.field);\n }\n\n /**\n * Show all columns.\n * Delegates to grid.showAllColumns().\n */\n showAll(): void {\n const grid = this.grid as unknown as GridWithVisibility;\n grid.showAllColumns();\n }\n\n /**\n * Toggle visibility for a specific column.\n * Delegates to grid.toggleColumnVisibility().\n * @param field - The field name of the column\n */\n toggleColumn(field: string): void {\n const grid = this.grid as unknown as GridWithVisibility;\n grid.toggleColumnVisibility(field);\n }\n\n /**\n * Show a specific column.\n * Delegates to grid.setColumnVisible().\n * @param field - The field name of the column to show\n */\n showColumn(field: string): void {\n const grid = this.grid as unknown as GridWithVisibility;\n grid.setColumnVisible(field, true);\n }\n\n /**\n * Hide a specific column.\n * Delegates to grid.setColumnVisible().\n * @param field - The field name of the column to hide\n */\n hideColumn(field: string): void {\n const grid = this.grid as unknown as GridWithVisibility;\n grid.setColumnVisible(field, false);\n }\n\n /**\n * Get all columns with their visibility status.\n * Useful for building visibility UI.\n * @returns Array of column info with visibility status\n */\n getAllColumns(): Array<{ field: string; header: string; visible: boolean; lockVisible?: boolean }> {\n const grid = this.grid as unknown as GridWithVisibility;\n return grid.getAllColumns();\n }\n\n /**\n * Check if the sidebar panel is currently open.\n * @returns True if the panel is open\n */\n isPanelVisible(): boolean {\n const grid = this.grid as unknown as GridWithVisibility;\n return grid.activeToolPanel === VisibilityPlugin.PANEL_ID;\n }\n // #endregion\n\n // #region Private Methods\n\n /**\n * Render the panel content into the shell's tool panel container.\n * Returns a cleanup function.\n */\n private renderPanelContent(container: HTMLElement): (() => void) | void {\n const grid = this.grid as unknown as GridWithVisibility;\n\n // Create content wrapper\n const wrapper = document.createElement('div');\n wrapper.className = 'tbw-visibility-content';\n\n // Column list container\n const columnList = document.createElement('div');\n columnList.className = 'tbw-visibility-list';\n wrapper.appendChild(columnList);\n\n // Show all button\n const showAllBtn = document.createElement('button');\n showAllBtn.className = 'tbw-visibility-show-all';\n showAllBtn.textContent = 'Show All';\n showAllBtn.addEventListener('click', () => {\n grid.showAllColumns();\n this.rebuildToggles(columnList);\n });\n wrapper.appendChild(showAllBtn);\n\n // Store reference\n this.columnListElement = columnList;\n\n // Build initial toggles\n this.rebuildToggles(columnList);\n\n // Append to container\n container.appendChild(wrapper);\n\n // Return cleanup function\n return () => {\n this.columnListElement = null;\n wrapper.remove();\n };\n }\n\n /**\n * Check if a reorder plugin is present (by name to avoid static import).\n */\n private hasReorderPlugin(): boolean {\n const plugin = this.grid?.getPluginByName?.('reorder');\n // Duck-type check - just verify the plugin exists and has a moveColumn method\n return !!(plugin && typeof (plugin as { moveColumn?: unknown }).moveColumn === 'function');\n }\n\n /**\n * Build the column toggle checkboxes.\n * When a reorder plugin is present, adds drag handles for reordering.\n */\n private rebuildToggles(columnList: HTMLElement): void {\n const grid = this.grid as unknown as GridWithVisibility;\n const reorderEnabled = this.hasReorderPlugin();\n\n columnList.innerHTML = '';\n\n // getAllColumns() now returns columns in their effective display order\n const allColumns = grid.getAllColumns();\n\n for (let i = 0; i < allColumns.length; i++) {\n const col = allColumns[i];\n const label = col.header || col.field;\n\n const row = document.createElement('div');\n row.className = col.lockVisible ? 'tbw-visibility-row locked' : 'tbw-visibility-row';\n row.setAttribute('data-field', col.field);\n row.setAttribute('data-index', String(i));\n\n // Add drag handle if reorder is enabled\n if (reorderEnabled && canMoveColumn(col as unknown as ColumnConfig)) {\n row.draggable = true;\n row.classList.add('reorderable');\n\n this.setupDragListeners(row, col.field, i, columnList);\n }\n\n const labelWrapper = document.createElement('label');\n labelWrapper.className = 'tbw-visibility-label';\n\n const checkbox = document.createElement('input');\n checkbox.type = 'checkbox';\n checkbox.checked = col.visible;\n checkbox.disabled = col.lockVisible ?? false;\n checkbox.addEventListener('change', () => {\n grid.toggleColumnVisibility(col.field);\n // Refresh after toggle (grid may re-render)\n setTimeout(() => this.rebuildToggles(columnList), 0);\n });\n\n const text = document.createElement('span');\n text.textContent = label;\n\n labelWrapper.appendChild(checkbox);\n labelWrapper.appendChild(text);\n\n // Add drag handle icon if reorderable\n if (reorderEnabled && canMoveColumn(col as unknown as ColumnConfig)) {\n const handle = document.createElement('span');\n handle.className = 'tbw-visibility-handle';\n // Use grid-level icons (fall back to defaults)\n this.setIcon(handle, this.resolveIcon('dragHandle'));\n handle.title = 'Drag to reorder';\n row.appendChild(handle);\n }\n\n row.appendChild(labelWrapper);\n columnList.appendChild(row);\n }\n }\n\n /**\n * Set up drag-and-drop event listeners for a row.\n * On drop, emits a 'column-reorder-request' event for other plugins to handle.\n */\n private setupDragListeners(row: HTMLElement, field: string, index: number, columnList: HTMLElement): void {\n row.addEventListener('dragstart', (e: DragEvent) => {\n this.isDragging = true;\n this.draggedField = field;\n this.draggedIndex = index;\n\n if (e.dataTransfer) {\n e.dataTransfer.effectAllowed = 'move';\n e.dataTransfer.setData('text/plain', field);\n }\n\n row.classList.add('dragging');\n });\n\n row.addEventListener('dragend', () => {\n this.isDragging = false;\n this.draggedField = null;\n this.draggedIndex = null;\n this.dropIndex = null;\n\n columnList.querySelectorAll('.tbw-visibility-row').forEach((r) => {\n r.classList.remove('dragging', 'drop-target', 'drop-before', 'drop-after');\n });\n });\n\n row.addEventListener('dragover', (e: DragEvent) => {\n e.preventDefault();\n if (!this.isDragging || this.draggedField === field) return;\n\n const rect = row.getBoundingClientRect();\n const midY = rect.top + rect.height / 2;\n\n this.dropIndex = e.clientY < midY ? index : index + 1;\n\n // Clear other row highlights\n columnList.querySelectorAll('.tbw-visibility-row').forEach((r) => {\n if (r !== row) r.classList.remove('drop-target', 'drop-before', 'drop-after');\n });\n\n row.classList.add('drop-target');\n row.classList.toggle('drop-before', e.clientY < midY);\n row.classList.toggle('drop-after', e.clientY >= midY);\n });\n\n row.addEventListener('dragleave', () => {\n row.classList.remove('drop-target', 'drop-before', 'drop-after');\n });\n\n row.addEventListener('drop', (e: DragEvent) => {\n e.preventDefault();\n const draggedField = this.draggedField;\n const draggedIndex = this.draggedIndex;\n const dropIndex = this.dropIndex;\n\n if (!this.isDragging || draggedField === null || draggedIndex === null || dropIndex === null) {\n return;\n }\n\n // Calculate the effective target index\n const effectiveToIndex = dropIndex > draggedIndex ? dropIndex - 1 : dropIndex;\n\n if (effectiveToIndex !== draggedIndex) {\n // Emit a request event - other plugins (like ReorderPlugin) can listen and handle\n const detail: ColumnReorderRequestDetail = {\n field: draggedField,\n fromIndex: draggedIndex,\n toIndex: effectiveToIndex,\n };\n this.emit<ColumnReorderRequestDetail>('column-reorder-request', detail);\n\n // Rebuild the panel after reorder (deferred to allow re-render)\n setTimeout(() => {\n this.rebuildToggles(columnList);\n }, 0);\n }\n });\n }\n // #endregion\n\n // #region Styles\n\n override readonly styles = styles;\n // #endregion\n}\n"],"names":["formatCellValue","value","field","row","config","str","delimiter","newline","buildClipboardText","params","rows","columns","selectedIndices","visibleColumns","c","lines","headerCells","header","sortedIndices","a","b","idx","cells","col","copyToClipboard","text","textarea","success","parseClipboardText","normalizedText","currentRow","currentCell","inQuotes","i","char","readFromClipboard","ClipboardPlugin","BaseGridPlugin","event","isCopy","isPaste","#handleCopy","#handlePaste","target","selectionPlugin","#getSelectionPlugin","selectedRows","hasRowSelection","ranges","hasRangeSelection","hasCellSelection","rowCount","columnCount","range","result","#buildRangeText","cell","#buildCellText","#buildSingleCellText","parsed","grid","plugin","rowIndex","colIndex","rowData","column","formattedValue","startRow","startCol","endRow","endCol","minRow","maxRow","minCol","maxCol","rangeColumns","r","rowIndexStr","indices","DEFAULT_COLUMN_WIDTH","parseColumnWidth","width","numeric","getColumnWidths","computeColumnOffsets","offsets","offset","computeTotalWidth","sum","getVisibleColumnRange","scrollLeft","viewportWidth","columnOffsets","columnWidths","overscan","binarySearchFirstVisible","rightEdge","low","high","mid","shouldVirtualize","threshold","autoEnable","ColumnVirtualizationPlugin","isVirtualized","viewport","shadowRoot","leftPadding","headerRow","bodyRows","rowsContainer","columnIndex","gridEl","buildMenuItems","items","item","isItemDisabled","createMenuElement","onAction","submenuArrow","DEFAULT_GRID_ICONS","menu","separator","menuItem","disabled","icon","label","shortcut","arrow","subMenuItems","subMenu","e","positionMenu","x","y","menuRect","viewportHeight","left","top","globalClickHandler","globalKeydownHandler","globalStyleSheet","globalHandlerRefCount","defaultItems","ContextMenuPlugin","contextMenuStyles","container","fullParams","formatCsvValue","quote","buildCsv","options","bom","processed","downloadBlob","blob","fileName","url","link","downloadCsv","content","escapeXml","buildExcelXml","xml","type","displayValue","downloadExcel","finalName","ExportPlugin","format","colSet","selectionState","jsonData","obj","computeVirtualWindow","totalRows","scrollTop","rowHeight","visibleRows","start","end","shouldBypassVirtualization","matchesFilter","filter","caseSensitive","rawValue","stringValue","compareValue","filterValue","filterRows","filters","f","computeFilterCacheKey","getUniqueValues","values","FilteringPlugin","filterList","newCacheKey","hasFilter","filterBtn","style","filterPanelStyles","buttonEl","panel","uniqueValues","excludedSet","currentSearchText","excluded","operator","valueTo","usedCustomRenderer","rect","panelRect","excludedValues","searchContainer","searchInput","actionsRow","selectAllLabel","selectAllCheckbox","selectAllText","updateSelectAllState","checkState","allChecked","v","noneChecked","newState","key","renderVisibleItems","valuesContainer","spacer","contentContainer","filteredValues","createItem","index","strValue","checkbox","totalItems","window","renderValues","filterText","lowerFilter","noMatch","debounceTimer","buttonRow","applyBtn","isChecked","original","clearBtn","handleResult","filterModel","state","styles","computeColumnGroups","explicitMap","groupsOrdered","pushImplicit","startIdx","cols","prev","run","runStart","g","id","group","applyGroupedHeaderCellClasses","headerRowEl","groups","fieldToGroup","gid","last","buildGroupHeaderRow","groupRow","startIndex","isImplicit","hasColumnGroups","GroupingColumnsPlugin","existingGroupRow","groupId","buildGroupedRowModel","expanded","groupOn","root","path","parent","rawVal","depthIdx","seg","composite","node","flat","visit","isExpanded","toggleGroupExpansion","expandedKeys","newSet","expandAllGroups","keys","collapseAllGroups","getGroupRowCount","GroupingRowsPlugin","mode","host","grouped","currentVisibleKeys","rowEl","_rowIndex","toggleExpand","handleToggle","body","animClass","btn","labelText","count","aggregators","groupRows","gridTemplate","colIdx","firstColAgg","aggResult","runAggregator","aggRef","newKeys","fn","toggleDetailRow","expandedRows","newExpanded","expandDetailRow","collapseDetailRow","isDetailExpanded","createDetailElement","renderer","detailRow","detailCell","MasterDetailPlugin","durationStr","detailEl","onComplete","cleanup","firstCol","originalRenderer","wrappedRenderer","renderCtx","toggle","rendered","#syncDetailRows","visibleRowMap","dataRows","firstCell","existingDetails","forIndex","isStillExpanded","isRowVisible","existingDetail","totalHeight","configHeight","beforeRowIndex","expandedIndices","minStart","cumulativeExtraHeight","actualRowTop","detailHeight","actualDetailBottom","applySorts","sorts","sort","comparator","defaultComparator","aVal","bVal","toggleSort","current","shiftKey","maxColumns","existing","s","getSortIndex","sortModel","getSortDirection","MultiSortPlugin","showIndex","sortIndex","sortDir","indicator","badge","model","existingIndex","newEntry","getLeftStickyColumns","getRightStickyColumns","hasStickyColumns","applyStickyOffsets","fieldToIndex","el","right","clearStickyOffsets","PinnedColumnsPlugin","query","PLUGIN_QUERIES","sticky","metaSticky","focusedCell","stickyLeftCells","stickyRightCells","skipScroll","isAggregatorConfig","def","createInfoBarElement","context","pinnedRows","center","filteredCount","selectedCount","panelEl","renderCustomPanel","createAggregationContainer","position","renderAggregationRows","rowConfig","formatter","aggDef","aggFn","getAggregator","staticVal","buildContext","filterState","PinnedRowsPlugin","aggregationRows","topRows","bottomRows","hasInfoContent","hasBottomInfoBar","needsFooter","newInfoBar","p","getPivotAggregator","getValueAggregator","validatePivotConfig","errors","createValueKey","columnValues","valueField","buildPivot","rowGroupFields","columnGroupFields","valueFields","columnKeys","getUniqueColumnKeys","pivotRows","buildHierarchicalPivotRows","totals","calculateTotals","grandTotal","columnFields","groupByField","depth","parentKey","aggregateValues","total","calculateRowTotal","currentField","remainingFields","hasChildren","groupValue","rowKey","children","colKey","vf","nums","aggregator","aggregatedResult","valueKey","val","sumRows","flattenPivotRows","defaultExpanded","flatten","child","getAllGroupKeys","collectKeys","AGG_FUNCS","renderPivotPanel","isActive","callbacks","controller","ctx","wrapper","createSection","createOptionsPanel","createFieldZone","createValuesZone","createAvailableFieldsZone","title","contentFactory","section","zoneType","signal","zone","currentFields","placeholder","createFieldChip","chip","fieldInfo","removeBtn","currentValues","createValueChip","labelWrapper","aggSelect","aggFunc","option","allFields","usedFields","availableFields","empty","createCheckbox","checked","onChange","input","span","renderPivotGroupRow","indent","renderPivotLeafRow","renderPivotGrandTotalRow","PivotPlugin","allKeys","indentWidth","flatRows","pr","pivotColumns","rowGroupHeaders","valueHeader","pivotRow","iconKey","grandTotalRow","fields","enabled","targetZone","fieldIndex","canMoveColumn","meta","moveColumn","fromIndex","toIndex","removed","ReorderPlugin","detail","headerEl","pluginAllows","orderIndex","h","midX","draggedField","draggedIndex","dropIndex","effectiveToIndex","currentOrder","newOrder","focusCol","targetColumn","ensureCellVisible","order","originalOrder","positions","oldPositions","deltas","oldLeft","deltaX","duration","applyChange","movedFields","newLeft","animation","normalizeRange","toPublicRange","normalized","toPublicRanges","isCellInRange","isCellInAnyRange","getCellsInRange","getAllCellsInRanges","cellMap","createRangeFromAnchor","anchor","buildSelectionEvent","colCount","SelectionPlugin","originalEvent","#buildEvent","ctrlKey","newRange","isNavKey","allRange","_event","#applySelectionClasses","allRows","currentCol","getBlockNumber","blockSize","getBlockRange","blockNumber","getRequiredBlocks","startBlock","endBlock","blocks","loadBlock","dataSource","getRowFromCache","loadedBlocks","block","indexInBlock","SCROLL_DEBOUNCE_MS","ServerSidePlugin","gridRef","requiredBlocks","blockNum","cached","generateRowKey","expandAll","childrenField","childKeys","k","collapseAll","getPathToKey","targetKey","childPath","expandToKey","existingExpanded","detectTreeStructure","inferChildrenField","commonArrayFields","TreePlugin","data","currentKeys","dir","getConfig","setIcon","resolveIcon","wrapped","showExpandIcons","flatRow","pushAction","action","maxSize","undoStack","undo","redo","redoStack","canUndo","canRedo","clearHistory","createEditAction","oldValue","newValue","UndoRedoPlugin","isUndo","isRedo","VisibilityPlugin","visible","columnList","showAllBtn","reorderEnabled","allColumns","handle","midY"],"mappings":";;AAoCO,SAASA,GAAgBC,GAAgBC,GAAeC,GAAcC,GAAiC;AAC5G,MAAIA,EAAO;AACT,WAAOA,EAAO,YAAYH,GAAOC,GAAOC,CAAG;AAG7C,MAAIF,KAAS,KAAM,QAAO;AAC1B,MAAIA,aAAiB,KAAM,QAAOA,EAAM,YAAA;AACxC,MAAI,OAAOA,KAAU,SAAU,QAAO,KAAK,UAAUA,CAAK;AAE1D,QAAMI,IAAM,OAAOJ,CAAK,GAClBK,IAAYF,EAAO,aAAa,KAChCG,IAAUH,EAAO,WAAW;AAAA;AAGlC,SAAIA,EAAO,gBAAgBC,EAAI,SAASC,CAAS,KAAKD,EAAI,SAASE,CAAO,KAAKF,EAAI,SAAS,GAAG,IACtF,IAAIA,EAAI,QAAQ,MAAM,IAAI,CAAC,MAG7BA;AACT;AAQO,SAASG,EAAmBC,GAA4B;AAC7D,QAAM,EAAE,MAAAC,GAAM,SAAAC,GAAS,iBAAAC,GAAiB,QAAAR,MAAWK,GAC7CH,IAAYF,EAAO,aAAa,KAChCG,IAAUH,EAAO,WAAW;AAAA,GAG5BS,IAAiBF,EAAQ,OAAO,CAACG,MAAM,CAACA,EAAE,UAAU,CAACA,EAAE,MAAM,WAAW,IAAI,CAAC,GAE7EC,IAAkB,CAAA;AAGxB,MAAIX,EAAO,gBAAgB;AACzB,UAAMY,IAAcH,EAAe,IAAI,CAACC,MAAM;AAC5C,YAAMG,IAASH,EAAE,UAAUA,EAAE;AAE7B,aAAIG,EAAO,SAASX,CAAS,KAAKW,EAAO,SAASV,CAAO,KAAKU,EAAO,SAAS,GAAG,IACxE,IAAIA,EAAO,QAAQ,MAAM,IAAI,CAAC,MAEhCA;AAAA,IACT,CAAC;AACD,IAAAF,EAAM,KAAKC,EAAY,KAAKV,CAAS,CAAC;AAAA,EACxC;AAIA,QAAMY,IAAgB,CAAC,GADPN,aAA2B,MAAM,CAAC,GAAGA,CAAe,IAAIA,CACvC,EAAE,KAAK,CAACO,GAAGC,MAAMD,IAAIC,CAAC;AAGvD,aAAWC,KAAOH,GAAe;AAC/B,UAAMf,IAAMO,EAAKW,CAAG;AACpB,QAAI,CAAClB,EAAK;AAEV,UAAMmB,IAAQT,EAAe;AAAA,MAAI,CAACU,MAChCvB,GAAiBG,EAAgCoB,EAAI,KAAK,GAAGA,EAAI,OAAOpB,GAAKC,CAAM;AAAA,IAAA;AAErF,IAAAW,EAAM,KAAKO,EAAM,KAAKhB,CAAS,CAAC;AAAA,EAClC;AAEA,SAAOS,EAAM,KAAKR,CAAO;AAC3B;AAWA,eAAsBiB,EAAgBC,GAAgC;AACpE,MAAI;AACF,iBAAM,UAAU,UAAU,UAAUA,CAAI,GACjC;AAAA,EACT,QAAQ;AAEN,UAAMC,IAAW,SAAS,cAAc,UAAU;AAClD,IAAAA,EAAS,QAAQD,GACjBC,EAAS,MAAM,WAAW,SAC1BA,EAAS,MAAM,UAAU,KACzBA,EAAS,MAAM,gBAAgB,QAC/B,SAAS,KAAK,YAAYA,CAAQ,GAClCA,EAAS,OAAA;AACT,UAAMC,IAAU,SAAS,YAAY,MAAM;AAC3C,oBAAS,KAAK,YAAYD,CAAQ,GAC3BC;AAAA,EACT;AACF;AC7GO,SAASC,GAAmBH,GAAcrB,GAAqC;AACpF,QAAME,IAAYF,EAAO,aAAa,KAChCG,IAAUH,EAAO,WAAW;AAAA,GAG5ByB,IAAiBJ,EAAK,QAAQ,SAAS;AAAA,CAAI,EAAE,QAAQ,OAAO;AAAA,CAAI,GAGhEf,IAAmB,CAAA;AACzB,MAAIoB,IAAuB,CAAA,GACvBC,IAAc,IACdC,IAAW;AAEf,WAASC,IAAI,GAAGA,IAAIJ,EAAe,QAAQI,KAAK;AAC9C,UAAMC,IAAOL,EAAeI,CAAC;AAE7B,IAAIC,MAAS,OAAO,CAACF,IAEnBA,IAAW,KACFE,MAAS,OAAOF,IAErBH,EAAeI,IAAI,CAAC,MAAM,OAC5BF,KAAe,KACfE,OAGAD,IAAW,KAEJE,MAAS5B,KAAa,CAAC0B,KAEhCF,EAAW,KAAKC,CAAW,GAC3BA,IAAc,MACLG,MAAS3B,KAAW,CAACyB,KAE9BF,EAAW,KAAKC,CAAW,GAC3BA,IAAc,KAEVD,EAAW,SAAS,KAAKA,EAAW,KAAK,CAAChB,MAAMA,EAAE,KAAA,MAAW,EAAE,MACjEJ,EAAK,KAAKoB,CAAU,GAEtBA,IAAa,CAAA,KAEbC,KAAeG;AAAA,EAEnB;AAGA,SAAAJ,EAAW,KAAKC,CAAW,IACvBD,EAAW,SAAS,KAAKA,EAAW,KAAK,CAAChB,MAAMA,EAAE,KAAA,MAAW,EAAE,MACjEJ,EAAK,KAAKoB,CAAU,GAGfpB;AACT;AAUA,eAAsByB,KAAqC;AACzD,MAAI;AACF,WAAO,MAAM,UAAU,UAAU,SAAA;AAAA,EACnC,QAAQ;AAEN,WAAO;AAAA,EACT;AACF;AC/DO,MAAMC,WAAwBC,EAAgC;AAAA,EAC1D,OAAO;AAAA,EACE,UAAU;AAAA,EAE5B,IAAuB,gBAA0C;AAC/D,WAAO;AAAA,MACL,gBAAgB;AAAA,MAChB,WAAW;AAAA,MACX,SAAS;AAAA;AAAA,MACT,cAAc;AAAA,IAAA;AAAA,EAElB;AAAA;AAAA;AAAA,EAIQ,aAAyD;AAAA;AAAA;AAAA,EAKxD,SAAe;AACtB,SAAK,aAAa;AAAA,EACpB;AAAA;AAAA;AAAA,EAKS,UAAUC,GAA+B;AAChD,UAAMC,KAAUD,EAAM,WAAWA,EAAM,YAAYA,EAAM,QAAQ,KAC3DE,KAAWF,EAAM,WAAWA,EAAM,YAAYA,EAAM,QAAQ;AAElE,WAAIC,KACF,KAAKE,GAAYH,EAAM,MAAqB,GACrC,MAGLE,KACF,KAAKE,GAAA,GACE,MAGF;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQAD,GAAYE,GAA2B;AAGrC,UAAMC,IAAkB,KAAKC,GAAA,GAGvBC,IAAeF,GAAiB,gBAAA,KAAqB,CAAA,GACrDG,IAAkBD,EAAa,SAAS,GACxCE,IAASJ,GAAiB,UAAA,KAAe,CAAA,GACzCK,IAAoBD,EAAO,SAAS,GACpCE,IAAmBN,GAAiB,gBAAA,KAAqB;AAE/D,QAAInB,GACA0B,GACAC;AAEJ,QAAIL,KAAmBH;AAErB,MAAAnB,IAAOjB,EAAmB;AAAA,QACxB,MAAM,KAAK;AAAA,QACX,SAAS,CAAC,GAAG,KAAK,OAAO;AAAA,QACzB,iBAAiBsC;AAAA,QACjB,QAAQ,KAAK;AAAA,MAAA,CACd,GACDK,IAAWL,EAAa,QACxBM,IAAc,KAAK,QAAQ,OAAO,CAACtC,MAAM,CAACA,EAAE,UAAU,CAACA,EAAE,MAAM,WAAW,IAAI,CAAC,EAAE;AAAA,aACxEmC,KAAqBL,GAAiB;AAE/C,YAAMS,IAAQL,EAAOA,EAAO,SAAS,CAAC,GAChCM,IAAS,KAAKC,GAAgB;AAAA,QAClC,UAAUF,EAAM,KAAK;AAAA,QACrB,UAAUA,EAAM,KAAK;AAAA,QACrB,QAAQA,EAAM,GAAG;AAAA,QACjB,QAAQA,EAAM,GAAG;AAAA,MAAA,CAClB;AACD,MAAA5B,IAAO6B,EAAO,MACdH,IAAWG,EAAO,UAClBF,IAAcE,EAAO;AAAA,IACvB,WAAWJ,KAAoBN,GAAiB;AAE9C,YAAMY,IAAOZ,EAAgB,gBAAA,GACvBU,IAAS,KAAKG,GAAeD,EAAK,KAAKA,EAAK,GAAG;AACrD,UAAI,CAACF,EAAQ;AACb,MAAA7B,IAAO6B,EAAO,MACdH,IAAW,GACXC,IAAc;AAAA,IAChB,OAAO;AAEL,YAAME,IAAS,KAAKI,GAAqBf,CAAM;AAC/C,UAAI,CAACW,EAAQ;AACb,MAAA7B,IAAO6B,EAAO,MACdH,IAAW,GACXC,IAAc;AAAA,IAChB;AAEA,IAAA5B,EAAgBC,CAAI,EAAE,KAAK,MAAM;AAC/B,WAAK,aAAa,EAAE,MAAAA,GAAM,WAAW,KAAK,MAAI,GAC9C,KAAK,KAAiB,QAAQ,EAAE,MAAAA,GAAM,UAAA0B,GAAU,aAAAC,GAAa;AAAA,IAC/D,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKAV,KAAqB;AACnB,IAAAP,GAAA,EAAoB,KAAK,CAACV,MAAS;AACjC,UAAI,CAACA,EAAM;AACX,YAAMkC,IAAS/B,GAAmBH,GAAM,KAAK,MAAM;AACnD,WAAK,KAAkB,SAAS,EAAE,MAAMkC,GAAQ,MAAAlC,GAAM;AAAA,IACxD,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKAoB,KAA4D;AAE1D,QAAI;AAGF,YAAMe,IAAO,KAAK;AAClB,UAAIA,GAAM;AACR,mBAAWC,KAAUD,EAAK;AACxB,cAAIC,EAAO,SAAS;AAClB,mBAAOA;AAAA;AAAA,IAIf,QAAQ;AAAA,IAER;AAAA,EAEF;AAAA;AAAA;AAAA;AAAA,EAKAJ,GAAeK,GAAkBC,GAA2C;AAC1E,UAAMC,IAAU,KAAK,KAAKF,CAAQ;AAClC,QAAI,CAACE,EAAS,QAAO;AAErB,UAAMC,IAAS,KAAK,QAAQF,CAAQ;AACpC,QAAI,CAACE,EAAQ,QAAO;AAEpB,UAAMhE,IAAQ+D,EAAQC,EAAO,KAAK,GAC5BhD,IAASgD,EAAO,UAAUA,EAAO;AAEvC,QAAIxC;AACJ,QAAI,KAAK,OAAO,gBAAgB;AAC9B,YAAMyC,IAAiBjE,KAAS,OAAO,KAAK,OAAOA,CAAK;AACxD,MAAAwB,IAAO,GAAGR,CAAM,KAAKiD,CAAc;AAAA,IACrC;AACE,MAAAzC,IAAOxB,KAAS,OAAO,KAAK,OAAOA,CAAK;AAG1C,WAAO,EAAE,MAAAwB,EAAA;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA8B,GAAgBF,GAId;AACA,UAAM,EAAE,UAAAc,GAAU,UAAAC,GAAU,QAAAC,GAAQ,QAAAC,MAAWjB,GACzCkB,IAAS,KAAK,IAAIJ,GAAUE,CAAM,GAClCG,IAAS,KAAK,IAAIL,GAAUE,CAAM,GAClCI,IAAS,KAAK,IAAIL,GAAUE,CAAM,GAClCI,IAAS,KAAK,IAAIN,GAAUE,CAAM,GAElChE,IAAY,KAAK,OAAO,aAAa,KACrCC,IAAU,KAAK,OAAO,WAAW;AAAA,GACjCQ,IAAkB,CAAA,GAGlB4D,IAAe,KAAK,QAAQ,MAAMF,GAAQC,IAAS,CAAC;AAG1D,QAAI,KAAK,OAAO,gBAAgB;AAC9B,YAAM1D,IAAc2D,EAAa,IAAI,CAAC7D,MAAMA,EAAE,UAAUA,EAAE,KAAK;AAC/D,MAAAC,EAAM,KAAKC,EAAY,KAAKV,CAAS,CAAC;AAAA,IACxC;AAGA,aAASsE,IAAIL,GAAQK,KAAKJ,GAAQI,KAAK;AACrC,YAAMZ,IAAU,KAAK,KAAKY,CAAC;AAC3B,UAAI,CAACZ,EAAS;AAEd,YAAM1C,IAAQqD,EAAa,IAAI,CAACpD,MAAQ;AACtC,cAAMtB,IAAQ+D,EAAQzC,EAAI,KAAK;AAC/B,eAAItB,KAAS,OAAa,KACtBA,aAAiB,OAAaA,EAAM,YAAA,IACjC,OAAOA,CAAK;AAAA,MACrB,CAAC;AACD,MAAAc,EAAM,KAAKO,EAAM,KAAKhB,CAAS,CAAC;AAAA,IAClC;AAEA,WAAO;AAAA,MACL,MAAMS,EAAM,KAAKR,CAAO;AAAA,MACxB,UAAUiE,IAASD,IAAS;AAAA,MAC5B,aAAaG,IAASD,IAAS;AAAA,IAAA;AAAA,EAEnC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMAf,GAAqBf,GAA6E;AAEhG,UAAMa,IAAOb,EAAO,QAAQ,oBAAoB;AAChD,QAAI,CAACa,EAAM,QAAO;AAElB,UAAMtD,IAAQsD,EAAK,QAAQ;AAC3B,QAAI,CAACtD,EAAO,QAAO;AAGnB,UAAM2E,IAAcrB,EAAK,QAAQ;AACjC,QAAI,CAACqB,EAAa,QAAO;AAEzB,UAAMf,IAAW,SAASe,GAAa,EAAE;AACzC,QAAI,MAAMf,CAAQ,EAAG,QAAO;AAE5B,UAAME,IAAU,KAAK,KAAKF,CAAQ;AAClC,QAAI,CAACE,EAAS,QAAO;AAErB,UAAM/D,IAAQ+D,EAAQ9D,CAAK,GAErBe,IADS,KAAK,QAAQ,KAAK,CAACH,MAAMA,EAAE,UAAUZ,CAAK,GAClC,UAAUA;AAGjC,QAAIuB;AACJ,QAAI,KAAK,OAAO,gBAAgB;AAE9B,YAAMyC,IAAiBjE,KAAS,OAAO,KAAK,OAAOA,CAAK;AACxD,MAAAwB,IAAO,GAAGR,CAAM,KAAKiD,CAAc;AAAA,IACrC;AAEE,MAAAzC,IAAOxB,KAAS,OAAO,KAAK,OAAOA,CAAK;AAG1C,WAAO,EAAE,MAAAwB,GAAM,OAAAvB,GAAO,OAAAD,EAAA;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,OAAwB;AAE5B,UAAM6E,IADkB,KAAKjC,GAAA,GACI,gBAAA,KAAqB,CAAA,GAEhDpB,IAAOjB,EAAmB;AAAA,MAC9B,MAAM,KAAK;AAAA,MACX,SAAS,CAAC,GAAG,KAAK,OAAO;AAAA,MACzB,iBAAiBsE;AAAA,MACjB,QAAQ,KAAK;AAAA,IAAA,CACd;AAED,iBAAMtD,EAAgBC,CAAI,GAC1B,KAAK,aAAa,EAAE,MAAAA,GAAM,WAAW,KAAK,MAAI,GACvCA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,SAASqD,GAAoC;AACjD,UAAMrD,IAAOjB,EAAmB;AAAA,MAC9B,MAAM,KAAK;AAAA,MACX,SAAS,CAAC,GAAG,KAAK,OAAO;AAAA,MACzB,iBAAiBsE;AAAA,MACjB,QAAQ,KAAK;AAAA,IAAA,CACd;AAED,iBAAMtD,EAAgBC,CAAI,GAC1B,KAAK,aAAa,EAAE,MAAAA,GAAM,WAAW,KAAK,MAAI,GACvCA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,QAAoC;AACxC,UAAMA,IAAO,MAAMU,GAAA;AACnB,WAAKV,IACEG,GAAmBH,GAAM,KAAK,MAAM,IADzB;AAAA,EAEpB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAA4D;AAC1D,WAAO,KAAK;AAAA,EACd;AAAA;AAEF;AC7UA,MAAMsD,KAAuB;AAStB,SAASC,GAAiBC,GAA4C;AAC3E,MAA2BA,KAAU;AACnC,WAAOF;AAGT,MAAI,OAAOE,KAAU;AACnB,WAAOA;AAIT,QAAMC,IAAU,WAAWD,CAAK;AAChC,SAAK,MAAMC,CAAO,IAIXH,KAHEG;AAIX;AAQO,SAASC,GAAgBxE,GAA4C;AAC1E,SAAOA,EAAQ,IAAI,CAACY,MAAQyD,GAAiBzD,EAAI,KAAK,CAAC;AACzD;AAQO,SAAS6D,GAAqBzE,GAA4C;AAC/E,QAAM0E,IAAoB,CAAA;AAC1B,MAAIC,IAAS;AAEb,aAAW/D,KAAOZ;AAChB,IAAA0E,EAAQ,KAAKC,CAAM,GACnBA,KAAUN,GAAiBzD,EAAI,KAAK;AAGtC,SAAO8D;AACT;AAQO,SAASE,GAAkB5E,GAA0C;AAC1E,SAAOA,EAAQ,OAAO,CAAC6E,GAAKjE,MAAQiE,IAAMR,GAAiBzD,EAAI,KAAK,GAAG,CAAC;AAC1E;AAaO,SAASkE,GACdC,GACAC,GACAC,GACAC,GACAC,GAC8B;AAC9B,QAAM1C,IAAcwC,EAAc;AAElC,MAAIxC,MAAgB;AAClB,WAAO,EAAE,UAAU,GAAG,QAAQ,GAAG,gBAAgB,GAAC;AAIpD,MAAIgB,IAAW2B,GAAyBL,GAAYE,GAAeC,CAAY;AAC/E,EAAAzB,IAAW,KAAK,IAAI,GAAGA,IAAW0B,CAAQ;AAG1C,QAAME,IAAYN,IAAaC;AAC/B,MAAIrB,IAASF;AAEb,WAASnC,IAAImC,GAAUnC,IAAImB,GAAanB,KAAK;AAC3C,QAAI2D,EAAc3D,CAAC,KAAK+D,GAAW;AACjC,MAAA1B,IAASrC,IAAI;AACb;AAAA,IACF;AACA,IAAAqC,IAASrC;AAAA,EACX;AAGA,EAAAqC,IAAS,KAAK,IAAIlB,IAAc,GAAGkB,IAASwB,CAAQ;AAGpD,QAAMjF,IAA2B,CAAA;AACjC,WAASoB,IAAImC,GAAUnC,KAAKqC,GAAQrC;AAClC,IAAApB,EAAe,KAAKoB,CAAC;AAGvB,SAAO,EAAE,UAAAmC,GAAU,QAAAE,GAAQ,gBAAAzD,EAAA;AAC7B;AAUA,SAASkF,GAAyBL,GAAoBE,GAAyBC,GAAgC;AAC7G,MAAII,IAAM,GACNC,IAAON,EAAc,SAAS;AAElC,SAAOK,IAAMC,KAAM;AACjB,UAAMC,IAAM,KAAK,OAAOF,IAAMC,KAAQ,CAAC;AAGvC,IAFiBN,EAAcO,CAAG,IAAIN,EAAaM,CAAG,KAEtCT,IACdO,IAAME,IAAM,IAEZD,IAAOC;AAAA,EAEX;AAEA,SAAOF;AACT;AAUO,SAASG,GAAiBhD,GAAqBiD,GAAmBC,GAA8B;AACrG,SAAKA,IACElD,IAAciD,IADG;AAE1B;AC1IO,MAAME,WAAmClE,EAA2C;AAAA,EAChF,OAAO;AAAA,EACE,UAAU;AAAA,EAE5B,IAAuB,gBAAqD;AAC1E,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,WAAW;AAAA,MACX,UAAU;AAAA,IAAA;AAAA,EAEd;AAAA;AAAA,EAGQ,gBAAgB;AAAA,EAChB,WAAW;AAAA,EACX,SAAS;AAAA,EACT,aAAa;AAAA,EACb,aAAa;AAAA,EACb,eAAyB,CAAA;AAAA,EACzB,gBAA0B,CAAA;AAAA;AAAA;AAAA,EAKzB,OAAOuB,GAAiE;AAC/E,UAAM,OAAOA,CAAI;AAGjB,UAAMjD,IAAU,KAAK;AACrB,SAAK,eAAewE,GAAgBxE,CAAO,GAC3C,KAAK,gBAAgByE,GAAqBzE,CAAO,GACjD,KAAK,aAAa4E,GAAkB5E,CAAO,GAC3C,KAAK,SAASA,EAAQ,SAAS;AAAA,EACjC;AAAA,EAES,SAAe;AACtB,SAAK,eAAe,CAAA,GACpB,KAAK,gBAAgB,CAAA,GACrB,KAAK,gBAAgB,IACrB,KAAK,WAAW,GAChB,KAAK,SAAS,GACd,KAAK,aAAa,GAClB,KAAK,aAAa;AAAA,EACpB;AAAA;AAAA;AAAA,EAKS,eAAeA,GAAkD;AACxE,UAAM6F,IAAgBJ,GAAiBzF,EAAQ,QAAQ,KAAK,OAAO,aAAa,IAAI,KAAK,OAAO,cAAc,EAAI;AAQlH,QALA,KAAK,gBAAgB6F,KAAiB,IACtC,KAAK,eAAerB,GAAgBxE,CAAO,GAC3C,KAAK,gBAAgByE,GAAqBzE,CAAO,GACjD,KAAK,aAAa4E,GAAkB5E,CAAO,GAEvC,CAAC6F;AACH,kBAAK,WAAW,GAChB,KAAK,SAAS7F,EAAQ,SAAS,GACxB,CAAC,GAAGA,CAAO;AAIpB,UAAMgF,IAAiB,KAAK,KAAgC,eAAe,KACrEc,IAAWhB;AAAA,MACf,KAAK;AAAA,MACLE;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK,OAAO,YAAY;AAAA,IAAA;AAG1B,gBAAK,WAAWc,EAAS,UACzB,KAAK,SAASA,EAAS,QAGhBA,EAAS,eAAe,IAAI,CAAC,MAAM9F,EAAQ,CAAC,CAAC;AAAA,EACtD;AAAA,EAES,cAAoB;AAC3B,QAAI,CAAC,KAAK,cAAe;AAEzB,UAAM+F,IAAa,KAAK;AACxB,QAAI,CAACA,EAAY;AAGjB,UAAMC,IAAc,KAAK,cAAc,KAAK,QAAQ,KAAK,GAEnDC,IAAYF,EAAW,cAAc,aAAa,GAClDG,IAAWH,EAAW,iBAAiB,gBAAgB;AAE7D,IAAIE,MACDA,EAA0B,MAAM,cAAc,GAAGD,CAAW,OAG/DE,EAAS,QAAQ,CAAC1G,MAAQ;AACvB,MAAAA,EAAoB,MAAM,cAAc,GAAGwG,CAAW;AAAA,IACzD,CAAC;AAGD,UAAMG,IAAgBJ,EAAW,cAAc,sBAAsB;AACrE,IAAII,MACDA,EAA8B,MAAM,QAAQ,GAAG,KAAK,UAAU;AAAA,EAEnE;AAAA,EAES,SAASxE,GAA0B;AAK1C,IAJI,CAAC,KAAK,iBAGU,KAAK,IAAIA,EAAM,aAAa,KAAK,UAAU,IAC7C,MAGlB,KAAK,aAAaA,EAAM,YAGxB,KAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,mBAA4B;AAC1B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,wBAAwD;AACtD,WAAO,EAAE,OAAO,KAAK,UAAU,KAAK,KAAK,OAAA;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,eAAeyE,GAA2B;AACxC,UAAMzB,IAAS,KAAK,cAAcyB,CAAW,KAAK,GAC5CC,IAAS,KAAK;AAEpB,IAAAA,EAAO,aAAa1B;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAgByB,GAA6B;AAC3C,WAAO,KAAK,cAAcA,CAAW,KAAK;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAwB;AACtB,WAAO,KAAK;AAAA,EACd;AAAA;AAEF;;AC7KO,SAASE,EACdC,GACAzG,GACmB;AAGnB,UAFkB,OAAOyG,KAAU,aAAaA,EAAMzG,CAAM,IAAIyG,GAE/C,OAAO,CAACC,MACnB,EAAAA,EAAK,WAAW,MAChB,OAAOA,EAAK,UAAW,cAAcA,EAAK,OAAO1G,CAAM,EAE5D;AACH;AASO,SAAS2G,GAAeD,GAAuB1G,GAAoC;AACxF,SAAI0G,EAAK,aAAa,KAAa,KAC/B,OAAOA,EAAK,YAAa,aAAmBA,EAAK,SAAS1G,CAAM,IAC7D;AACT;AAWO,SAAS4G,EACdH,GACAzG,GACA6G,GACAC,IAA0BC,GAAmB,cAChC;AACb,QAAMC,IAAO,SAAS,cAAc,KAAK;AACzC,EAAAA,EAAK,YAAY,oBACjBA,EAAK,aAAa,QAAQ,MAAM;AAEhC,aAAWN,KAAQD,GAAO;AACxB,QAAIC,EAAK,WAAW;AAClB,YAAMO,IAAY,SAAS,cAAc,KAAK;AAC9C,MAAAA,EAAU,YAAY,8BACtBA,EAAU,aAAa,QAAQ,WAAW,GAC1CD,EAAK,YAAYC,CAAS;AAC1B;AAAA,IACF;AAEA,UAAMC,IAAW,SAAS,cAAc,KAAK;AAC7C,IAAAA,EAAS,YAAY,yBACjBR,EAAK,YAAUQ,EAAS,UAAU,IAAIR,EAAK,QAAQ,GACvDQ,EAAS,aAAa,QAAQ,UAAU,GACxCA,EAAS,aAAa,WAAWR,EAAK,EAAE;AAExC,UAAMS,IAAWR,GAAeD,GAAM1G,CAAM;AAM5C,QALImH,MACFD,EAAS,UAAU,IAAI,UAAU,GACjCA,EAAS,aAAa,iBAAiB,MAAM,IAG3CR,EAAK,MAAM;AACb,YAAMU,IAAO,SAAS,cAAc,MAAM;AAC1C,MAAAA,EAAK,YAAY,yBACjBA,EAAK,YAAYV,EAAK,MACtBQ,EAAS,YAAYE,CAAI;AAAA,IAC3B;AAEA,UAAMC,IAAQ,SAAS,cAAc,MAAM;AAK3C,QAJAA,EAAM,YAAY,0BAClBA,EAAM,cAAcX,EAAK,MACzBQ,EAAS,YAAYG,CAAK,GAEtBX,EAAK,UAAU;AACjB,YAAMY,IAAW,SAAS,cAAc,MAAM;AAC9C,MAAAA,EAAS,YAAY,6BACrBA,EAAS,cAAcZ,EAAK,UAC5BQ,EAAS,YAAYI,CAAQ;AAAA,IAC/B;AAEA,QAAIZ,EAAK,SAAS,QAAQ;AACxB,YAAMa,IAAQ,SAAS,cAAc,MAAM;AAC3C,MAAAA,EAAM,YAAY,0BAEd,OAAOT,KAAiB,WAC1BS,EAAM,YAAYT,IACTA,aAAwB,eACjCS,EAAM,YAAYT,EAAa,UAAU,EAAI,CAAC,GAEhDI,EAAS,YAAYK,CAAK,GAG1BL,EAAS,iBAAiB,cAAc,MAAM;AAG5C,YAFwBA,EAAS,cAAc,mBAAmB,KAE9D,CAACR,EAAK,QAAS;AAEnB,cAAMc,IAAehB,EAAeE,EAAK,SAAS1G,CAAM,GAClDyH,IAAUb,EAAkBY,GAAcxH,GAAQ6G,GAAUC,CAAY;AAC9E,QAAAW,EAAQ,UAAU,IAAI,qBAAqB,GAC3CA,EAAQ,MAAM,WAAW,YACzBA,EAAQ,MAAM,OAAO,QACrBA,EAAQ,MAAM,MAAM,KACpBP,EAAS,MAAM,WAAW,YAC1BA,EAAS,YAAYO,CAAO;AAAA,MAC9B,CAAC,GAEDP,EAAS,iBAAiB,cAAc,MAAM;AAC5C,cAAMO,IAAUP,EAAS,cAAc,mBAAmB;AAC1D,QAAIO,OAAiB,OAAA;AAAA,MACvB,CAAC;AAAA,IACH;AAEA,IAAI,CAACN,KAAYT,EAAK,UAAU,CAACA,EAAK,WACpCQ,EAAS,iBAAiB,SAAS,CAACQ,MAAM;AACxC,MAAAA,EAAE,gBAAA,GACFb,EAASH,CAAI;AAAA,IACf,CAAC,GAGHM,EAAK,YAAYE,CAAQ;AAAA,EAC3B;AAEA,SAAOF;AACT;AAUO,SAASW,GAAaX,GAAmBY,GAAWC,GAAiB;AAE1E,EAAAb,EAAK,MAAM,WAAW,SACtBA,EAAK,MAAM,OAAO,GAAGY,CAAC,MACtBZ,EAAK,MAAM,MAAM,GAAGa,CAAC,MACrBb,EAAK,MAAM,aAAa,UACxBA,EAAK,MAAM,SAAS;AAGpB,QAAMc,IAAWd,EAAK,sBAAA,GAGhB9B,IAAgB,OAAO,YACvB6C,IAAiB,OAAO;AAE9B,MAAIC,IAAOJ,GACPK,IAAMJ;AAGV,EAAID,IAAIE,EAAS,QAAQ5C,MACvB8C,IAAOJ,IAAIE,EAAS,QAGlBD,IAAIC,EAAS,SAASC,MACxBE,IAAMJ,IAAIC,EAAS,SAIrBE,IAAO,KAAK,IAAI,GAAGA,CAAI,GACvBC,IAAM,KAAK,IAAI,GAAGA,CAAG,GAErBjB,EAAK,MAAM,OAAO,GAAGgB,CAAI,MACzBhB,EAAK,MAAM,MAAM,GAAGiB,CAAG,MACvBjB,EAAK,MAAM,aAAa;AAC1B;ACjLA,IAAIkB,IAAkD,MAElDC,IAA4D,MAE5DC,IAA4C,MAE5CC,IAAwB;AAG5B,MAAMC,IAAkC;AAAA,EACtC;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,UAAU;AAAA,IACV,QAAQ,CAACtI,MAAW;AAElB,MADcA,EAA8F,MACtG,SAAS,WAAW,OAAA;AAAA,IAC5B;AAAA,EAAA;AAAA,EAEF,EAAE,WAAW,IAAM,IAAI,QAAQ,MAAM,GAAA;AAAA,EACrC;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,QAAQ,CAACA,MAAW;AAGlB,MAFcA,EACX,MACG,SAAS,QAAQ,YAAA;AAAA,IACzB;AAAA,EAAA;AAEJ;AAiBO,MAAMuI,WAA0B3G,EAAkC;AAAA,EAC9D,OAAO;AAAA,EACE,UAAU;AAAA,EAE5B,IAAuB,gBAA4C;AACjE,WAAO;AAAA,MACL,OAAO0G;AAAA,IAAA;AAAA,EAEX;AAAA;AAAA,EAGQ,SAAS;AAAA,EACT,WAAW,EAAE,GAAG,GAAG,GAAG,EAAA;AAAA,EACtB,SAAmC;AAAA,EACnC,cAAkC;AAAA;AAAA;AAAA,EAKjC,OAAOnF,GAAiE;AAC/E,UAAM,OAAOA,CAAI,GACjB,KAAK,sBAAA,GACLkF;AAAA,EACF;AAAA,EAES,SAAe;AACtB,IAAI,KAAK,gBACP,KAAK,YAAY,OAAA,GACjB,KAAK,cAAc,OAErB,KAAK,SAAS,IACd,KAAK,SAAS,MACd,KAAK,wBAAA;AAAA,EACP;AAAA;AAAA;AAAA,EAKQ,wBAA8B;AAEpC,IAAI,CAACD,KAAoB,OAAO,WAAa,QAC3CA,IAAmB,SAAS,cAAc,OAAO,GACjDA,EAAiB,KAAK,2BACtBA,EAAiB,cAAcI,IAC/B,SAAS,KAAK,YAAYJ,CAAgB,IAIvCF,MACHA,IAAqB,MAAM;AAEzB,MADc,SAAS,iBAAiB,mBAAmB,EACrD,QAAQ,CAAClB,MAASA,EAAK,QAAQ;AAAA,IACvC,GACA,SAAS,iBAAiB,SAASkB,CAAkB,IAIlDC,MACHA,IAAuB,CAAC,MAAqB;AAC3C,MAAI,EAAE,QAAQ,YACE,SAAS,iBAAiB,mBAAmB,EACrD,QAAQ,CAACnB,MAASA,EAAK,QAAQ;AAAA,IAEzC,GACA,SAAS,iBAAiB,WAAWmB,CAAoB;AAAA,EAE7D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,0BAAgC;AAEtC,IADAE,KACI,EAAAA,IAAwB,OAGxBH,MACF,SAAS,oBAAoB,SAASA,CAAkB,GACxDA,IAAqB,OAEnBC,MACF,SAAS,oBAAoB,WAAWA,CAAoB,GAC5DA,IAAuB,OAErBC,MACFA,EAAiB,OAAA,GACjBA,IAAmB;AAAA,EAEvB;AAAA;AAAA;AAAA,EAKS,cAAoB;AAC3B,UAAMnC,IAAa,KAAK;AACxB,QAAI,CAACA,EAAY;AAEjB,UAAMwC,IAAYxC,EAAW,SAAS,CAAC;AACvC,IAAKwC,KAGDA,EAAU,aAAa,yBAAyB,MAAM,WAC1DA,EAAU,aAAa,2BAA2B,MAAM,GAExDA,EAAU,iBAAiB,eAAe,CAACf,MAAa;AACtD,YAAM7F,IAAQ6F;AACd,MAAA7F,EAAM,eAAA;AAEN,YAAMK,IAASL,EAAM,QACfkB,IAAOb,EAAO,QAAQ,sBAAsB,GAC5C1B,IAAS0B,EAAO,QAAQ,cAAc;AAE5C,UAAIlC;AAEJ,UAAI+C,GAAM;AACR,cAAMM,IAAW,SAASN,EAAK,aAAa,UAAU,KAAK,MAAM,EAAE,GAC7DO,IAAW,SAASP,EAAK,aAAa,UAAU,KAAK,MAAM,EAAE,GAC7DS,IAAS,KAAK,QAAQF,CAAQ,GAC9B5D,IAAM,KAAK,KAAK2D,CAAQ;AAE9B,QAAArD,IAAS;AAAA,UACP,KAAAN;AAAA,UACA,UAAA2D;AAAA,UACA,QAAAG;AAAA,UACA,aAAaF;AAAA,UACb,OAAOE,GAAQ,SAAS;AAAA,UACxB,OAAO9D,IAAM8D,GAAQ,KAAyB,KAAK;AAAA,UACnD,UAAU;AAAA,UACV,OAAA3B;AAAA,QAAA;AAAA,MAEJ,WAAWrB,GAAQ;AACjB,cAAM8C,IAAW,SAAS9C,EAAO,aAAa,UAAU,KAAK,MAAM,EAAE,GAC/DgD,IAAS,KAAK,QAAQF,CAAQ;AAEpC,QAAAtD,IAAS;AAAA,UACP,KAAK;AAAA,UACL,UAAU;AAAA,UACV,QAAAwD;AAAA,UACA,aAAaF;AAAA,UACb,OAAOE,GAAQ,SAAS;AAAA,UACxB,OAAO;AAAA,UACP,UAAU;AAAA,UACV,OAAA3B;AAAA,QAAA;AAAA,MAEJ;AACE;AAGF,WAAK,SAAS7B,GACd,KAAK,WAAW,EAAE,GAAG6B,EAAM,SAAS,GAAGA,EAAM,QAAA;AAE7C,YAAM4E,IAAQD,EAAe,KAAK,OAAO,SAAS8B,GAActI,CAAM;AACtE,MAAKyG,EAAM,WAEP,KAAK,eACP,KAAK,YAAY,OAAA,GAGnB,KAAK,cAAcG;AAAA,QACjBH;AAAA,QACAzG;AAAA,QACA,CAAC0G,MAAS;AACR,UAAIA,EAAK,UACPA,EAAK,OAAO1G,CAAM,GAEpB,KAAK,aAAa,OAAA,GAClB,KAAK,cAAc,MACnB,KAAK,SAAS;AAAA,QAChB;AAAA,QACA,KAAK,UAAU;AAAA,MAAA,GAGjB,SAAS,KAAK,YAAY,KAAK,WAAW,GAC1C2H,GAAa,KAAK,aAAa9F,EAAM,SAASA,EAAM,OAAO,GAC3D,KAAK,SAAS,IAEd,KAAK,KAAK,qBAAqB,EAAE,QAAA7B,GAAQ,OAAAyG,GAAO;AAAA,IAClD,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,SAASmB,GAAWC,GAAW7H,GAA0C;AACvE,UAAM0I,IAAgC;AAAA,MACpC,KAAK1I,EAAO,OAAO;AAAA,MACnB,UAAUA,EAAO,YAAY;AAAA,MAC7B,QAAQA,EAAO,UAAU;AAAA,MACzB,aAAaA,EAAO,eAAe;AAAA,MACnC,OAAOA,EAAO,SAAS;AAAA,MACvB,OAAOA,EAAO,SAAS;AAAA,MACvB,UAAUA,EAAO,YAAY;AAAA,MAC7B,OAAOA,EAAO,SAAS,IAAI,WAAW,aAAa;AAAA,IAAA,GAG/CyG,IAAQD,EAAe,KAAK,OAAO,SAAS8B,GAAcI,CAAU;AAE1E,IAAI,KAAK,eACP,KAAK,YAAY,OAAA,GAGnB,KAAK,cAAc9B;AAAA,MACjBH;AAAA,MACAiC;AAAA,MACA,CAAChC,MAAS;AACR,QAAIA,EAAK,UAAQA,EAAK,OAAOgC,CAAU,GACvC,KAAK,aAAa,OAAA,GAClB,KAAK,cAAc,MACnB,KAAK,SAAS;AAAA,MAChB;AAAA,MACA,KAAK,UAAU;AAAA,IAAA,GAGjB,SAAS,KAAK,YAAY,KAAK,WAAW,GAC1Cf,GAAa,KAAK,aAAaC,GAAGC,CAAC,GACnC,KAAK,SAAS;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,WAAiB;AACf,IAAI,KAAK,gBACP,KAAK,YAAY,OAAA,GACjB,KAAK,cAAc,MACnB,KAAK,SAAS;AAAA,EAElB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAsB;AACpB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAIF;ACxRO,SAASc,GAAenJ,GAAYoJ,IAAQ,IAAc;AAC/D,MAAIpJ,KAAS,KAAM,QAAO;AAC1B,MAAIA,aAAiB,KAAM,QAAOA,EAAM,YAAA;AACxC,MAAI,OAAOA,KAAU,SAAU,QAAO,KAAK,UAAUA,CAAK;AAE1D,QAAMI,IAAM,OAAOJ,CAAK;AAGxB,SAAIoJ,MAAUhJ,EAAI,SAAS,GAAG,KAAKA,EAAI,SAAS,GAAG,KAAKA,EAAI,SAAS;AAAA,CAAI,KAAKA,EAAI,SAAS,IAAI,KACtF,IAAIA,EAAI,QAAQ,MAAM,IAAI,CAAC,MAG7BA;AACT;AAKO,SAASiJ,GAAS5I,GAAaC,GAAyBF,GAAsB8I,IAAsB,CAAA,GAAY;AACrH,QAAMjJ,IAAYiJ,EAAQ,aAAa,KACjChJ,IAAUgJ,EAAQ,WAAW;AAAA,GAC7BxI,IAAkB,CAAA,GAGlByI,IAAMD,EAAQ,MAAM,WAAW;AAGrC,MAAI9I,EAAO,mBAAmB,IAAO;AACnC,UAAMmG,IAAYjG,EAAQ,IAAI,CAACY,MAAQ;AACrC,YAAMN,IAASM,EAAI,UAAUA,EAAI,OAC3BkI,IAAYhJ,EAAO,gBAAgBA,EAAO,cAAcQ,GAAQM,EAAI,KAAK,IAAIN;AACnF,aAAOmI,GAAeK,CAAS;AAAA,IACjC,CAAC;AACD,IAAA1I,EAAM,KAAK6F,EAAU,KAAKtG,CAAS,CAAC;AAAA,EACtC;AAGA,aAAWH,KAAOO,GAAM;AACtB,UAAMY,IAAQX,EAAQ,IAAI,CAACY,MAAQ;AACjC,UAAItB,IAAQE,EAAIoB,EAAI,KAAK;AACzB,aAAId,EAAO,gBACTR,IAAQQ,EAAO,YAAYR,GAAOsB,EAAI,OAAOpB,CAAG,IAE3CiJ,GAAenJ,CAAK;AAAA,IAC7B,CAAC;AACD,IAAAc,EAAM,KAAKO,EAAM,KAAKhB,CAAS,CAAC;AAAA,EAClC;AAEA,SAAOkJ,IAAMzI,EAAM,KAAKR,CAAO;AACjC;AAKO,SAASmJ,GAAaC,GAAYC,GAAwB;AAC/D,QAAMC,IAAM,IAAI,gBAAgBF,CAAI,GAC9BG,IAAO,SAAS,cAAc,GAAG;AACvC,EAAAA,EAAK,OAAOD,GACZC,EAAK,WAAWF,GAChBE,EAAK,MAAM,UAAU,QACrB,SAAS,KAAK,YAAYA,CAAI,GAC9BA,EAAK,MAAA,GACL,SAAS,KAAK,YAAYA,CAAI,GAC9B,IAAI,gBAAgBD,CAAG;AACzB;AAKO,SAASE,GAAYC,GAAiBJ,GAAwB;AACnE,QAAMD,IAAO,IAAI,KAAK,CAACK,CAAO,GAAG,EAAE,MAAM,2BAA2B;AACpE,EAAAN,GAAaC,GAAMC,CAAQ;AAC7B;ACnFA,SAASK,GAAU5J,GAAqB;AACtC,SAAOA,EACJ,QAAQ,MAAM,OAAO,EACrB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,QAAQ,EACtB,QAAQ,MAAM,QAAQ;AAC3B;AAMO,SAAS6J,GAAcxJ,GAAaC,GAAyBF,GAA8B;AAChG,MAAI0J,IAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAQV,MAAI1J,EAAO,mBAAmB,IAAO;AACnC,IAAA0J,KAAO;AAAA;AACP,eAAW5I,KAAOZ,GAAS;AACzB,YAAMM,IAASM,EAAI,UAAUA,EAAI,OAC3BkI,IAAYhJ,EAAO,gBAAgBA,EAAO,cAAcQ,GAAQM,EAAI,KAAK,IAAIN;AACnF,MAAAkJ,KAAO,gCAAgCF,GAAUR,CAAS,CAAC;AAAA,IAC7D;AACA,IAAAU,KAAO;AAAA,EACT;AAGA,aAAWhK,KAAOO,GAAM;AACtB,IAAAyJ,KAAO;AAAA;AACP,eAAW5I,KAAOZ,GAAS;AACzB,UAAIV,IAAQE,EAAIoB,EAAI,KAAK;AACzB,MAAId,EAAO,gBACTR,IAAQQ,EAAO,YAAYR,GAAOsB,EAAI,OAAOpB,CAAG;AAIlD,UAAIiK,IAAyC,UACzCC,IAAe;AAEnB,MAAIpK,KAAS,OACXoK,IAAe,KACN,OAAOpK,KAAU,YAAY,CAAC,MAAMA,CAAK,KAClDmK,IAAO,UACPC,IAAe,OAAOpK,CAAK,KAClBA,aAAiB,QAC1BmK,IAAO,YACPC,IAAepK,EAAM,YAAA,KAErBoK,IAAeJ,GAAU,OAAOhK,CAAK,CAAC,GAGxCkK,KAAO,wBAAwBC,CAAI,KAAKC,CAAY;AAAA,IACtD;AACA,IAAAF,KAAO;AAAA,EACT;AAEA,SAAAA,KAAO;AAAA;AAAA;AAAA,cACAA;AACT;AAKO,SAASG,GAAcN,GAAiBJ,GAAwB;AACrE,QAAMW,IAAYX,EAAS,SAAS,MAAM,IAAIA,IAAW,GAAGA,CAAQ,QAC9DD,IAAO,IAAI,KAAK,CAACK,CAAO,GAAG;AAAA,IAC/B,MAAM;AAAA,EAAA,CACP;AACD,EAAAN,GAAaC,GAAMY,CAAS;AAC9B;ACxDO,MAAMC,WAAqBnI,EAA6B;AAAA,EACpD,OAAO;AAAA,EACE,UAAU;AAAA,EAE5B,IAAuB,gBAAuC;AAC5D,WAAO;AAAA,MACL,UAAU;AAAA,MACV,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,cAAc;AAAA,IAAA;AAAA,EAElB;AAAA;AAAA,EAGQ,kBAAkB;AAAA,EAClB,iBAAmE;AAAA;AAAA;AAAA,EAKnE,cAAcoI,GAAsBhK,GAAsC;AAChF,UAAML,IAAS,KAAK,QAGd+I,IAA2B;AAAA,MAC/B,QAAAsB;AAAA,MACA,UAAUhK,GAAQ,YAAYL,EAAO,YAAY;AAAA,MACjD,gBAAgBK,GAAQ,kBAAkBL,EAAO;AAAA,MACjD,aAAaK,GAAQ;AAAA,MACrB,eAAeA,GAAQ;AAAA,MACvB,SAASA,GAAQ;AAAA,MACjB,YAAYA,GAAQ;AAAA,IAAA;AAItB,QAAIE,IAAU,CAAC,GAAG,KAAK,OAAO;AAI9B,QAHIP,EAAO,gBACTO,IAAUA,EAAQ,OAAO,CAACG,MAAM,CAACA,EAAE,UAAU,CAACA,EAAE,MAAM,WAAW,IAAI,CAAC,IAEpEL,GAAQ,SAAS;AACnB,YAAMiK,IAAS,IAAI,IAAIjK,EAAO,OAAO;AACrC,MAAAE,IAAUA,EAAQ,OAAO,CAACG,MAAM4J,EAAO,IAAI5J,EAAE,KAAK,CAAC;AAAA,IACrD;AAGA,QAAIJ,IAAO,CAAC,GAAG,KAAK,IAAI;AACxB,QAAIN,EAAO,cAAc;AACvB,YAAMuK,IAAiB,KAAK,kBAAA;AAC5B,MAAIA,GAAgB,UAAU,SAE5BjK,IADsB,CAAC,GAAGiK,EAAe,QAAQ,EAAE,KAAK,CAACxJ,GAAGC,MAAMD,IAAIC,CAAC,EAClD,IAAI,CAACa,MAAM,KAAK,KAAKA,CAAC,CAAC,EAAE,OAAO,OAAO;AAAA,IAEhE;AACA,IAAIxB,GAAQ,eACVC,IAAOD,EAAO,WAAW,IAAI,CAACwB,MAAM,KAAK,KAAKA,CAAC,CAAC,EAAE,OAAO,OAAO,IAGlE,KAAK,kBAAkB;AACvB,QAAI2H,IAAWT,EAAW;AAE1B,QAAI;AACF,cAAQsB,GAAA;AAAA,QACN,KAAK,OAAO;AACV,gBAAMT,IAAUV,GAAS5I,GAAMC,GAASwI,GAAY,EAAE,KAAK,IAAM;AACjE,UAAAS,IAAWA,EAAS,SAAS,MAAM,IAAIA,IAAW,GAAGA,CAAQ,QAC7DG,GAAYC,GAASJ,CAAQ;AAC7B;AAAA,QACF;AAAA,QAEA,KAAK,SAAS;AACZ,gBAAMI,IAAUE,GAAcxJ,GAAMC,GAASwI,CAAU;AACvD,UAAAS,IAAWA,EAAS,SAAS,MAAM,IAAIA,IAAW,GAAGA,CAAQ,QAC7DU,GAAcN,GAASJ,CAAQ;AAC/B;AAAA,QACF;AAAA,QAEA,KAAK,QAAQ;AACX,gBAAMgB,IAAWlK,EAAK,IAAI,CAACP,MAAQ;AACjC,kBAAM0K,IAA2B,CAAA;AACjC,uBAAWtJ,KAAOZ,GAAS;AACzB,kBAAIV,IAAQE,EAAIoB,EAAI,KAAK;AACzB,cAAI4H,EAAW,gBACblJ,IAAQkJ,EAAW,YAAYlJ,GAAOsB,EAAI,OAAOpB,CAAG,IAEtD0K,EAAItJ,EAAI,KAAK,IAAItB;AAAA,YACnB;AACA,mBAAO4K;AAAA,UACT,CAAC,GACKb,IAAU,KAAK,UAAUY,GAAU,MAAM,CAAC;AAChD,UAAAhB,IAAWA,EAAS,SAAS,OAAO,IAAIA,IAAW,GAAGA,CAAQ;AAC9D,gBAAMD,IAAO,IAAI,KAAK,CAACK,CAAO,GAAG,EAAE,MAAM,oBAAoB;AAC7D,UAAAN,GAAaC,GAAMC,CAAQ;AAC3B;AAAA,QACF;AAAA,MAAA;AAGF,WAAK,iBAAiB,EAAE,QAAAa,GAAQ,WAAW,oBAAI,OAAK,GAEpD,KAAK,KAA2B,mBAAmB;AAAA,QACjD,QAAAA;AAAA,QACA,UAAAb;AAAA,QACA,UAAUlJ,EAAK;AAAA,QACf,aAAaC,EAAQ;AAAA,MAAA,CACtB;AAAA,IACH,UAAA;AACE,WAAK,kBAAkB;AAAA,IACzB;AAAA,EACF;AAAA,EAEQ,oBAAiD;AACvD,QAAI;AAEF,aADa,KAAK,MACL,iBAAiB,WAAW,KAAK;AAAA,IAChD,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,UAAUF,GAAsC;AAC9C,SAAK,cAAc,OAAOA,CAAM;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAYA,GAAsC;AAChD,SAAK,cAAc,SAASA,CAAM;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,WAAWA,GAAsC;AAC/C,SAAK,cAAc,QAAQA,CAAM;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cAAuB;AACrB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAkE;AAChE,WAAO,KAAK;AAAA,EACd;AAAA;AAEF;ACxJO,SAASqK,GAAqBrK,GAA4C;AAC/E,QAAM,EAAE,WAAAsK,GAAW,gBAAAvC,GAAgB,WAAAwC,GAAW,WAAAC,GAAW,UAAAnF,MAAarF,GAIhEyK,IAAc,KAAK,KAAK1C,IAAiByC,CAAS;AAGxD,MAAIE,IAAQ,KAAK,MAAMH,IAAYC,CAAS,IAAInF;AAChD,EAAIqF,IAAQ,MAAGA,IAAQ;AAEvB,MAAIC,IAAMD,IAAQD,IAAcpF,IAAW;AAC3C,SAAIsF,IAAML,MAAWK,IAAML,IAGvBK,MAAQL,KAAaI,IAAQ,MAC/BA,IAAQ,KAAK,IAAI,GAAGC,IAAMF,IAAcpF,IAAW,CAAC,IAG/C;AAAA,IACL,OAAAqF;AAAA,IACA,KAAAC;AAAA,IACA,SAASD,IAAQF;AAAA,IACjB,aAAaF,IAAYE;AAAA,EAAA;AAE7B;AAUO,SAASI,GAA2BN,GAAmB1E,GAA4B;AACxF,SAAO0E,KAAa1E;AACtB;AC/DO,SAASiF,GAAcnL,GAA8BoL,GAAqBC,IAAgB,IAAgB;AAC/G,QAAMC,IAAWtL,EAAIoL,EAAO,KAAK;AAGjC,MAAIA,EAAO,aAAa;AACtB,WAAOE,KAAY,QAAQA,MAAa;AAE1C,MAAIF,EAAO,aAAa;AACtB,WAAOE,KAAY,QAAQA,MAAa;AAI1C,MAAIA,KAAY,KAAM,QAAO;AAG7B,QAAMC,IAAc,OAAOD,CAAQ,GAC7BE,IAAeH,IAAgBE,IAAcA,EAAY,YAAA,GACzDE,IAAcJ,IAAgB,OAAOD,EAAO,KAAK,IAAI,OAAOA,EAAO,KAAK,EAAE,YAAA;AAEhF,UAAQA,EAAO,UAAA;AAAA;AAAA,IAEb,KAAK;AACH,aAAOI,EAAa,SAASC,CAAW;AAAA,IAE1C,KAAK;AACH,aAAO,CAACD,EAAa,SAASC,CAAW;AAAA,IAE3C,KAAK;AACH,aAAOD,MAAiBC;AAAA,IAE1B,KAAK;AACH,aAAOD,MAAiBC;AAAA,IAE1B,KAAK;AACH,aAAOD,EAAa,WAAWC,CAAW;AAAA,IAE5C,KAAK;AACH,aAAOD,EAAa,SAASC,CAAW;AAAA;AAAA,IAG1C,KAAK;AACH,aAAO,OAAOH,CAAQ,IAAI,OAAOF,EAAO,KAAK;AAAA,IAE/C,KAAK;AACH,aAAO,OAAOE,CAAQ,KAAK,OAAOF,EAAO,KAAK;AAAA,IAEhD,KAAK;AACH,aAAO,OAAOE,CAAQ,IAAI,OAAOF,EAAO,KAAK;AAAA,IAE/C,KAAK;AACH,aAAO,OAAOE,CAAQ,KAAK,OAAOF,EAAO,KAAK;AAAA,IAEhD,KAAK;AACH,aAAO,OAAOE,CAAQ,KAAK,OAAOF,EAAO,KAAK,KAAK,OAAOE,CAAQ,KAAK,OAAOF,EAAO,OAAO;AAAA;AAAA,IAG9F,KAAK;AACH,aAAO,MAAM,QAAQA,EAAO,KAAK,KAAKA,EAAO,MAAM,SAASE,CAAQ;AAAA,IAEtE,KAAK;AACH,aAAO,MAAM,QAAQF,EAAO,KAAK,KAAK,CAACA,EAAO,MAAM,SAASE,CAAQ;AAAA,IAEvE;AACE,aAAO;AAAA,EAAA;AAEb;AAWO,SAASI,GACdnL,GACAoL,GACAN,IAAgB,IACX;AACL,SAAKM,EAAQ,SACNpL,EAAK,OAAO,CAACP,MAAQ2L,EAAQ,MAAM,CAACC,MAAMT,GAAcnL,GAAK4L,GAAGP,CAAa,CAAC,CAAC,IAD1D9K;AAE9B;AASO,SAASsL,GAAsBF,GAAgC;AACpE,SAAO,KAAK;AAAA,IACVA,EAAQ,IAAI,CAACC,OAAO;AAAA,MAClB,OAAOA,EAAE;AAAA,MACT,UAAUA,EAAE;AAAA,MACZ,OAAOA,EAAE;AAAA,MACT,SAASA,EAAE;AAAA,IAAA,EACX;AAAA,EAAA;AAEN;AAUO,SAASE,GAAmDvL,GAAWR,GAA0B;AACtG,QAAMgM,wBAAa,IAAA;AACnB,aAAW/L,KAAOO,GAAM;AACtB,UAAMT,IAAQE,EAAID,CAAK;AACvB,IAAID,KAAS,QACXiM,EAAO,IAAIjM,CAAK;AAAA,EAEpB;AACA,SAAO,CAAC,GAAGiM,CAAM,EAAE,KAAK,CAAC/K,GAAGC,MAEtB,OAAOD,KAAM,YAAY,OAAOC,KAAM,WACjCD,IAAIC,IAEN,OAAOD,CAAC,EAAE,cAAc,OAAOC,CAAC,CAAC,CACzC;AACH;;ACtHO,MAAM+K,UAAwB9J,EAA6B;AAAA,EACvD,OAAO;AAAA,EACE,UAAU;AAAA,EAE5B,IAAuB,gBAAuC;AAC5D,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,eAAe;AAAA,MACf,WAAW;AAAA,MACX,WAAW;AAAA,IAAA;AAAA,EAEf;AAAA;AAAA,EAGQ,8BAAwC,IAAA;AAAA,EACxC,eAAiC;AAAA,EACjC,WAA0B;AAAA,EAC1B,iBAAgC;AAAA,EAChC,eAAmC;AAAA,EACnC,iCAAsC,IAAA;AAAA,EACtC,qCAAgD,IAAA;AAAA,EAChD,uBAA+C;AAAA;AAAA,EAC/C,uBAAuB;AAAA;AAAA,EAG/B,OAAwB,mBAAmB;AAAA,EAC3C,OAAwB,gBAAgB;AAAA,EACxC,OAAwB,wBAAwB;AAAA;AAAA;AAAA;AAAA,EAKvC,OAAOuB,GAAyB;AACvC,UAAM,OAAOA,CAAI,GACjB,KAAK,mBAAA;AAAA,EACP;AAAA,EAES,SAAe;AACtB,SAAK,QAAQ,MAAA,GACb,KAAK,eAAe,MACpB,KAAK,WAAW,MAChB,KAAK,iBAAiB,MAClB,KAAK,iBACP,KAAK,aAAa,OAAA,GAClB,KAAK,eAAe,OAEtB,KAAK,WAAW,MAAA,GAChB,KAAK,eAAe,MAAA,GAEpB,KAAK,sBAAsB,MAAA,GAC3B,KAAK,uBAAuB;AAAA,EAC9B;AAAA;AAAA;AAAA,EAKS,YAAYlD,GAAqC;AACxD,UAAM0L,IAAa,CAAC,GAAG,KAAK,QAAQ,QAAQ;AAC5C,QAAI,CAACA,EAAW,OAAQ,QAAO,CAAC,GAAG1L,CAAI;AAIvC,QAAI,KAAK,OAAO;AAEd,aAAI,KAAK,eAAqB,KAAK,eAE5B,CAAC,GAAGA,CAAI;AAIjB,UAAM2L,IAAcL,GAAsBI,CAAU;AACpD,QAAI,KAAK,aAAaC,KAAe,KAAK;AACxC,aAAO,KAAK;AAId,UAAM/I,IAASuI,GAAW,CAAC,GAAGnL,CAAI,GAAgC0L,GAAY,KAAK,OAAO,aAAa;AAGvG,gBAAK,eAAe9I,GACpB,KAAK,WAAW+I,GAET/I;AAAA,EACT;AAAA,EAES,cAAoB;AAC3B,UAAMoD,IAAa,KAAK;AACxB,QAAI,CAACA,EAAY;AAIjB,IADoBA,EAAW,iBAAiB,uBAAuB,EAC3D,QAAQ,CAAClD,MAAS;AAC5B,YAAMO,IAAWP,EAAK,aAAa,UAAU;AAC7C,UAAIO,MAAa,KAAM;AAGvB,YAAMxC,IAAM,KAAK,eAAe,SAASwC,GAAU,EAAE,CAAC;AACtD,UAAI,CAACxC,KAAOA,EAAI,eAAe,GAAO;AAEtC,YAAMrB,IAAQqB,EAAI;AAClB,UAAI,CAACrB,EAAO;AAEZ,YAAMoM,IAAY,KAAK,QAAQ,IAAIpM,CAAK;AAGxC,UAAIqM,IAAY/I,EAAK,cAAc,iBAAiB;AAEpD,UAAI+I,GAAW;AAEb,QAAAA,EAAU,UAAU,OAAO,UAAUD,CAAS,GAC7C9I,EAAqB,UAAU,OAAO,YAAY8I,CAAS;AAC5D;AAAA,MACF;AAGA,MAAAC,IAAY,SAAS,cAAc,QAAQ,GAC3CA,EAAU,YAAY,kBACtBA,EAAU,aAAa,cAAc,UAAUhL,EAAI,UAAUrB,CAAK,EAAE,GACpEqM,EAAU,YAAY,kRAGlBD,MACFC,EAAU,UAAU,IAAI,QAAQ,GAC/B/I,EAAqB,UAAU,IAAI,UAAU,IAGhD+I,EAAU,iBAAiB,SAAS,CAACpE,MAAM;AACzC,QAAAA,EAAE,gBAAA,GACF,KAAK,kBAAkBjI,GAAOqB,GAAKgL,CAAU;AAAA,MAC/C,CAAC,GAGD/I,EAAK,YAAY+I,CAAS;AAAA,IAC5B,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,UAAUrM,GAAeqL,GAAiD;AACxE,IAAIA,MAAW,QACb,KAAK,QAAQ,OAAOrL,CAAK,GACzB,KAAK,eAAe,OAAOA,CAAK,MAEhC,KAAK,QAAQ,IAAIA,GAAO,EAAE,GAAGqL,GAAQ,OAAArL,GAAO,GAExCqL,EAAO,SAAS,SAASA,EAAO,aAAa,WAAW,MAAM,QAAQA,EAAO,KAAK,IACpF,KAAK,eAAe,IAAIrL,GAAO,IAAI,IAAIqL,EAAO,KAAK,CAAC,IAC3CA,EAAO,SAAS,SAEzB,KAAK,eAAe,OAAOrL,CAAK,IAIpC,KAAK,eAAe,MACpB,KAAK,WAAW,MAEhB,KAAK,KAAyB,iBAAiB;AAAA,MAC7C,SAAS,CAAC,GAAG,KAAK,QAAQ,QAAQ;AAAA,MAClC,kBAAkB;AAAA;AAAA,IAAA,CACnB,GACD,KAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKA,UAAUA,GAAwC;AAChD,WAAO,KAAK,QAAQ,IAAIA,CAAK;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,aAA4B;AAC1B,WAAO,CAAC,GAAG,KAAK,QAAQ,QAAQ;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAgC;AAC9B,WAAO,KAAK,WAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,eAAe4L,GAA8B;AAC3C,SAAK,QAAQ,MAAA,GACb,KAAK,eAAe,MAAA;AACpB,eAAWP,KAAUO;AACnB,WAAK,QAAQ,IAAIP,EAAO,OAAOA,CAAM,GAEjCA,EAAO,SAAS,SAASA,EAAO,aAAa,WAAW,MAAM,QAAQA,EAAO,KAAK,KACpF,KAAK,eAAe,IAAIA,EAAO,OAAO,IAAI,IAAIA,EAAO,KAAK,CAAC;AAG/D,SAAK,eAAe,MACpB,KAAK,WAAW,MAEhB,KAAK,KAAyB,iBAAiB;AAAA,MAC7C,SAAS,CAAC,GAAG,KAAK,QAAQ,QAAQ;AAAA,MAClC,kBAAkB;AAAA,IAAA,CACnB,GACD,KAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAwB;AACtB,SAAK,QAAQ,MAAA,GACb,KAAK,eAAe,MAAA,GACpB,KAAK,WAAW,MAAA,GAEhB,KAAK,qBAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAiBrL,GAAqB;AACpC,SAAK,QAAQ,OAAOA,CAAK,GACzB,KAAK,eAAe,OAAOA,CAAK,GAChC,KAAK,WAAW,OAAOA,CAAK,GAE5B,KAAK,qBAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgBA,GAAwB;AACtC,WAAO,KAAK,QAAQ,IAAIA,CAAK;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,sBAA8B;AAC5B,WAAO,KAAK,cAAc,UAAU,KAAK,KAAK;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAkC;AAChC,WAAO,KAAK,WAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAgBA,GAA0B;AACxC,WAAO+L,GAAgB,KAAK,YAAyC/L,CAAK;AAAA,EAC5E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,qBAA2B;AACjC,QAAI,KAAK,qBAAsB;AAC/B,QAAI,SAAS,eAAe,yBAAyB,GAAG;AACtD,WAAK,uBAAuB;AAC5B;AAAA,IACF;AACA,UAAMsM,IAAQ,SAAS,cAAc,OAAO;AAC5C,IAAAA,EAAM,KAAK,2BACXA,EAAM,cAAcC,IACpB,SAAS,KAAK,YAAYD,CAAK,GAC/B,KAAK,uBAAuB;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKQ,kBAAkBtM,GAAe+D,GAAsByI,GAA6B;AAE1F,QAAI,KAAK,mBAAmBxM,GAAO;AACjC,WAAK,iBAAA;AACL;AAAA,IACF;AAGA,SAAK,iBAAA;AAGL,UAAMyM,IAAQ,SAAS,cAAc,KAAK;AAM1C,QALAA,EAAM,YAAY,oBAClB,KAAK,eAAeA,GACpB,KAAK,iBAAiBzM,GAGlB,KAAK,OAAO,eAAe;AAC7B,MAAAyM,EAAM,YAAY,oDAClB,SAAS,KAAK,YAAYA,CAAK,GAC/B,KAAK,cAAcA,GAAOD,CAAQ,GAClC,KAAK,uBAAuBC,GAAOD,CAAQ,GAE3C,KAAK,OAAO,cAAcxM,GAAO+D,CAAM,EAAE,KAAK,CAACiI,MAAW;AAExD,QAAI,KAAK,mBAAmBhM,KAAS,CAAC,KAAK,iBAC3CyM,EAAM,YAAY,IAClB,KAAK,mBAAmBzM,GAAO+D,GAAQ0I,GAAOT,CAAM;AAAA,MACtD,CAAC;AACD;AAAA,IACF;AAGA,UAAMU,IAAeX,GAAgB,KAAK,YAAyC/L,CAAK;AACxF,SAAK,mBAAmBA,GAAO+D,GAAQ0I,GAAOC,CAAY,GAG1D,SAAS,KAAK,YAAYD,CAAK,GAC/B,KAAK,cAAcA,GAAOD,CAAQ,GAClC,KAAK,uBAAuBC,GAAOD,CAAQ;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKQ,mBAAmBxM,GAAe+D,GAAsB0I,GAAoBC,GAA+B;AAEjH,QAAIC,IAAc,KAAK,eAAe,IAAI3M,CAAK;AAC/C,IAAK2M,MACHA,wBAAkB,IAAA,GAClB,KAAK,eAAe,IAAI3M,GAAO2M,CAAW;AAI5C,UAAMC,IAAoB,KAAK,WAAW,IAAI5M,CAAK,KAAK,IAGlDO,IAA4B;AAAA,MAChC,OAAAP;AAAA,MACA,QAAA+D;AAAA,MACA,cAAA2I;AAAA,MACA,gBAAgBC;AAAA,MAChB,YAAYC;AAAA,MACZ,gBAAgB,CAACC,MAAwB;AACvC,aAAK,eAAe7M,GAAO6M,CAAQ,GACnC,KAAK,iBAAA;AAAA,MACP;AAAA,MACA,iBAAiB,CAACC,GAAU/M,GAAOgN,MAAY;AAC7C,aAAK,gBAAgB/M,GAAO8M,GAAU/M,GAAOgN,CAAO,GACpD,KAAK,iBAAA;AAAA,MACP;AAAA,MACA,aAAa,MAAM;AACjB,aAAK,iBAAiB/M,CAAK,GAC3B,KAAK,iBAAA;AAAA,MACP;AAAA,MACA,YAAY,MAAM,KAAK,iBAAA;AAAA,IAAiB;AAK1C,QAAIgN,IAAqB;AACzB,IAAI,KAAK,OAAO,wBACd,KAAK,OAAO,oBAAoBP,GAAOlM,CAAM,GAE7CyM,IAAqBP,EAAM,SAAS,SAAS,IAE1CO,KACH,KAAK,yBAAyBP,GAAOlM,GAAQmM,GAAcC,CAAW;AAAA,EAE1E;AAAA;AAAA;AAAA;AAAA,EAKQ,uBAAuBF,GAAoBD,GAA6B;AAG9E,SAAK,uBAAuB,IAAI,gBAAA,GAIhC,WAAW,MAAM;AACf,eAAS;AAAA,QACP;AAAA,QACA,CAACvE,MAAkB;AACjB,UAAI,CAACwE,EAAM,SAASxE,EAAE,MAAc,KAAKA,EAAE,WAAWuE,KACpD,KAAK,iBAAA;AAAA,QAET;AAAA,QACA,EAAE,QAAQ,KAAK,sBAAsB,OAAA;AAAA,MAAO;AAAA,IAEhD,GAAG,CAAC;AAAA,EACN;AAAA;AAAA;AAAA;AAAA,EAKQ,mBAAyB;AAC/B,IAAI,KAAK,iBACP,KAAK,aAAa,OAAA,GAClB,KAAK,eAAe,OAEtB,KAAK,iBAAiB,MAEtB,KAAK,sBAAsB,MAAA,GAC3B,KAAK,uBAAuB;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKQ,cAAcC,GAAoBD,GAA6B;AACrE,UAAMS,IAAOT,EAAS,sBAAA;AACtB,IAAAC,EAAM,MAAM,WAAW,SACvBA,EAAM,MAAM,MAAM,GAAGQ,EAAK,SAAS,CAAC,MACpCR,EAAM,MAAM,OAAO,GAAGQ,EAAK,IAAI,MAG/B,sBAAsB,MAAM;AAC1B,YAAMC,IAAYT,EAAM,sBAAA;AACxB,MAAIS,EAAU,QAAQ,OAAO,aAAa,MACxCT,EAAM,MAAM,OAAO,GAAG,OAAO,aAAaS,EAAU,QAAQ,CAAC,OAG3DA,EAAU,SAAS,OAAO,cAAc,MAC1CT,EAAM,MAAM,MAAM,GAAGQ,EAAK,MAAMC,EAAU,SAAS,CAAC;AAAA,IAExD,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKQ,yBACNT,GACAlM,GACAmM,GACAS,GACM;AACN,UAAM,EAAE,OAAAnN,MAAUO,GAGZ6M,IAAkB,SAAS,cAAc,KAAK;AACpD,IAAAA,EAAgB,YAAY;AAE5B,UAAMC,IAAc,SAAS,cAAc,OAAO;AAClD,IAAAA,EAAY,OAAO,QACnBA,EAAY,cAAc,aAC1BA,EAAY,YAAY,2BACxBA,EAAY,QAAQ,KAAK,WAAW,IAAIrN,CAAK,KAAK,IAClDoN,EAAgB,YAAYC,CAAW,GACvCZ,EAAM,YAAYW,CAAe;AAGjC,UAAME,IAAa,SAAS,cAAc,KAAK;AAC/C,IAAAA,EAAW,YAAY;AAEvB,UAAMC,IAAiB,SAAS,cAAc,OAAO;AACrD,IAAAA,EAAe,YAAY,yBAC3BA,EAAe,MAAM,UAAU,KAC/BA,EAAe,MAAM,SAAS;AAE9B,UAAMC,IAAoB,SAAS,cAAc,OAAO;AACxD,IAAAA,EAAkB,OAAO,YACzBA,EAAkB,YAAY;AAE9B,UAAMC,IAAgB,SAAS,cAAc,MAAM;AACnD,IAAAA,EAAc,cAAc,cAE5BF,EAAe,YAAYC,CAAiB,GAC5CD,EAAe,YAAYE,CAAa,GACxCH,EAAW,YAAYC,CAAc;AAGrC,UAAMG,IAAuB,MAAM;AACjC,YAAM1B,IAAS,CAAC,GAAG2B,EAAW,QAAQ,GAChCC,IAAa5B,EAAO,MAAM,CAAC6B,MAAMA,CAAC,GAClCC,IAAc9B,EAAO,MAAM,CAAC6B,MAAM,CAACA,CAAC;AAE1C,MAAAL,EAAkB,UAAUI,GAC5BJ,EAAkB,gBAAgB,CAACI,KAAc,CAACE;AAAA,IACpD;AAGA,IAAAN,EAAkB,iBAAiB,UAAU,MAAM;AACjD,YAAMO,IAAWP,EAAkB;AACnC,iBAAWQ,KAAOL,EAAW;AAC3B,QAAAA,EAAW,IAAIK,GAAKD,CAAQ;AAE9B,MAAAL,EAAA,GACAO,EAAA;AAAA,IACF,CAAC,GAEDxB,EAAM,YAAYa,CAAU;AAG5B,UAAMY,IAAkB,SAAS,cAAc,KAAK;AACpD,IAAAA,EAAgB,YAAY;AAG5B,UAAMC,IAAS,SAAS,cAAc,KAAK;AAC3C,IAAAA,EAAO,YAAY,4BACnBD,EAAgB,YAAYC,CAAM;AAGlC,UAAMC,IAAmB,SAAS,cAAc,KAAK;AACrD,IAAAA,EAAiB,YAAY,6BAC7BF,EAAgB,YAAYE,CAAgB;AAG5C,UAAMT,wBAAiB,IAAA;AACvB,IAAAjB,EAAa,QAAQ,CAAC3M,MAAU;AAC9B,YAAMiO,IAAMjO,KAAS,OAAO,aAAa,OAAOA,CAAK;AACrD,MAAA4N,EAAW,IAAIK,GAAK,CAACb,EAAe,IAAIpN,CAAK,CAAC;AAAA,IAChD,CAAC,GAGD2N,EAAA;AAGA,QAAIW,IAA4B,CAAA;AAGhC,UAAMC,IAAa,CAACvO,GAAgBwO,MAA+B;AACjE,YAAMC,IAAWzO,KAAS,OAAO,YAAY,OAAOA,CAAK,GACnDiO,IAAMjO,KAAS,OAAO,aAAa,OAAOA,CAAK,GAE/CkH,IAAO,SAAS,cAAc,OAAO;AAC3C,MAAAA,EAAK,YAAY,yBACjBA,EAAK,MAAM,WAAW,YACtBA,EAAK,MAAM,MAAM,GAAGsH,IAAQtC,EAAgB,gBAAgB,MAC5DhF,EAAK,MAAM,OAAO,KAClBA,EAAK,MAAM,QAAQ,KACnBA,EAAK,MAAM,SAAS,GAAGgF,EAAgB,gBAAgB,MACvDhF,EAAK,MAAM,YAAY;AAEvB,YAAMwH,IAAW,SAAS,cAAc,OAAO;AAC/C,MAAAA,EAAS,OAAO,YAChBA,EAAS,YAAY,uBACrBA,EAAS,UAAUd,EAAW,IAAIK,CAAG,KAAK,IAC1CS,EAAS,QAAQ,QAAQT,GAGzBS,EAAS,iBAAiB,UAAU,MAAM;AACxC,QAAAd,EAAW,IAAIK,GAAKS,EAAS,OAAO,GACpCf,EAAA;AAAA,MACF,CAAC;AAED,YAAM9F,KAAQ,SAAS,cAAc,MAAM;AAC3C,aAAAA,GAAM,cAAc4G,GAEpBvH,EAAK,YAAYwH,CAAQ,GACzBxH,EAAK,YAAYW,EAAK,GACfX;AAAA,IACT,GAGMgH,IAAqB,MAAM;AAC/B,YAAMS,IAAaL,EAAe,QAC5B/F,IAAiB4F,EAAgB,cACjCpD,IAAYoD,EAAgB;AAMlC,UAHAC,EAAO,MAAM,SAAS,GAAGO,IAAazC,EAAgB,gBAAgB,MAGlEd,GAA2BuD,GAAYzC,EAAgB,wBAAwB,CAAC,GAAG;AACrF,QAAAmC,EAAiB,YAAY,IAC7BA,EAAiB,MAAM,YAAY,mBACnCC,EAAe,QAAQ,CAACtO,GAAOoB,MAAQ;AACrC,UAAAiN,EAAiB,YAAYE,EAAWvO,GAAOoB,CAAG,CAAC;AAAA,QACrD,CAAC;AACD;AAAA,MACF;AAGA,YAAMwN,IAAS/D,GAAqB;AAAA,QAClC,WAAW8D;AAAA,QACX,gBAAApG;AAAA,QACA,WAAAwC;AAAA,QACA,WAAWmB,EAAgB;AAAA,QAC3B,UAAUA,EAAgB;AAAA,MAAA,CAC3B;AAGD,MAAAmC,EAAiB,MAAM,YAAY,cAAcO,EAAO,OAAO,OAG/DP,EAAiB,YAAY;AAC7B,eAASrM,IAAI4M,EAAO,OAAO5M,IAAI4M,EAAO,KAAK5M;AACzC,QAAAqM,EAAiB,YAAYE,EAAWD,EAAetM,CAAC,GAAGA,IAAI4M,EAAO,KAAK,CAAC;AAAA,IAEhF,GAGMC,KAAe,CAACC,MAAuB;AAC3C,YAAMC,IAAcD,EAAW,YAAA;AAQ/B,UALAR,IAAiB3B,EAAa,OAAO,CAAC3M,MAAU;AAC9C,cAAMyO,IAAWzO,KAAS,OAAO,YAAY,OAAOA,CAAK;AACzD,eAAO,CAAC8O,KAAcL,EAAS,YAAA,EAAc,SAASM,CAAW;AAAA,MACnE,CAAC,GAEGT,EAAe,WAAW,GAAG;AAC/B,QAAAF,EAAO,MAAM,SAAS,OACtBC,EAAiB,YAAY;AAC7B,cAAMW,IAAU,SAAS,cAAc,KAAK;AAC5C,QAAAA,EAAQ,YAAY,uBACpBA,EAAQ,cAAc,sBACtBX,EAAiB,YAAYW,CAAO;AACpC;AAAA,MACF;AAEA,MAAAd,EAAA;AAAA,IACF;AAGA,IAAAC,EAAgB;AAAA,MACd;AAAA,MACA,MAAM;AACJ,QAAIG,EAAe,SAAS,KAC1BJ,EAAA;AAAA,MAEJ;AAAA,MACA,EAAE,SAAS,GAAA;AAAA,IAAK,GAGlBW,GAAavB,EAAY,KAAK,GAC9BZ,EAAM,YAAYyB,CAAe;AAGjC,QAAIc;AACJ,IAAA3B,EAAY,iBAAiB,SAAS,MAAM;AAC1C,mBAAa2B,EAAa,GAC1BA,KAAgB,WAAW,MAAM;AAC/B,aAAK,WAAW,IAAIhP,GAAOqN,EAAY,KAAK,GAC5CuB,GAAavB,EAAY,KAAK;AAAA,MAChC,GAAG,KAAK,OAAO,cAAc,GAAG;AAAA,IAClC,CAAC;AAGD,UAAM4B,IAAY,SAAS,cAAc,KAAK;AAC9C,IAAAA,EAAU,YAAY;AAEtB,UAAMC,IAAW,SAAS,cAAc,QAAQ;AAChD,IAAAA,EAAS,YAAY,wBACrBA,EAAS,cAAc,SACvBA,EAAS,iBAAiB,SAAS,MAAM;AAEvC,YAAMrC,IAAsB,CAAA;AAC5B,iBAAW,CAACmB,GAAKmB,CAAS,KAAKxB;AAC7B,YAAI,CAACwB;AACH,cAAInB,MAAQ;AACV,YAAAnB,EAAS,KAAK,IAAI;AAAA,eACb;AAEL,kBAAMuC,IAAW1C,EAAa,KAAK,CAACmB,MAAM,OAAOA,CAAC,MAAMG,CAAG;AAC3D,YAAAnB,EAAS,KAAKuC,MAAa,SAAYA,IAAWpB,CAAG;AAAA,UACvD;AAGJ,MAAAzN,EAAO,eAAesM,CAAQ;AAAA,IAChC,CAAC,GACDoC,EAAU,YAAYC,CAAQ;AAE9B,UAAMG,IAAW,SAAS,cAAc,QAAQ;AAChD,IAAAA,EAAS,YAAY,wBACrBA,EAAS,cAAc,gBACvBA,EAAS,iBAAiB,SAAS,MAAM;AACvC,MAAA9O,EAAO,YAAA;AAAA,IACT,CAAC,GACD0O,EAAU,YAAYI,CAAQ,GAE9B5C,EAAM,YAAYwC,CAAS;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAejP,GAAe6M,GAA2B;AAE/D,SAAK,eAAe,IAAI7M,GAAO,IAAI,IAAI6M,CAAQ,CAAC,GAE5CA,EAAS,WAAW,IAEtB,KAAK,QAAQ,OAAO7M,CAAK,IAGzB,KAAK,QAAQ,IAAIA,GAAO;AAAA,MACtB,OAAAA;AAAA,MACA,MAAM;AAAA,MACN,UAAU;AAAA,MACV,OAAO6M;AAAA,IAAA,CACR,GAGH,KAAK,qBAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKQ,gBAAgB7M,GAAe8M,GAAmC/M,GAAegN,GAAwB;AAC/G,SAAK,QAAQ,IAAI/M,GAAO;AAAA,MACtB,OAAAA;AAAA,MACA,MAAM;AAAA,MACN,UAAA8M;AAAA,MACA,OAAA/M;AAAA,MACA,SAAAgN;AAAA,IAAA,CACD,GAED,KAAK,qBAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKQ,uBAA6B;AACnC,SAAK,eAAe,MACpB,KAAK,WAAW;AAEhB,UAAMb,IAAa,CAAC,GAAG,KAAK,QAAQ,QAAQ;AAG5C,QAAI,KAAK,OAAO,eAAe;AAC7B,YAAMpF,IAAS,KAAK;AACpB,MAAAA,EAAO,aAAa,aAAa,MAAM;AAEvC,YAAM1D,IAAS,KAAK,OAAO,cAAc8I,GAAY,KAAK,UAAuB,GAG3EoD,IAAe,CAAC9O,MAAoB;AACxC,QAAAsG,EAAO,gBAAgB,WAAW,GAClC,KAAK,eAAetG,GAGnB,KAAK,KAAwC,OAAOA,GAErD,KAAK,KAAyB,iBAAiB;AAAA,UAC7C,SAAS0L;AAAA,UACT,kBAAkB1L,EAAK;AAAA,QAAA,CACxB,GAGD,KAAK,cAAA;AAAA,MACP;AAEA,MAAI4C,KAAU,OAAQA,EAA8B,QAAS,aAC1DA,EAA8B,KAAKkM,CAAY,IAEhDA,EAAalM,CAAmB;AAElC;AAAA,IACF;AAGA,SAAK,KAAyB,iBAAiB;AAAA,MAC7C,SAAS8I;AAAA,MACT,kBAAkB;AAAA,IAAA,CACnB,GACD,KAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQS,eAAelM,GAAiD;AACvE,UAAMuP,IAAc,KAAK,QAAQ,IAAIvP,CAAK;AAC1C,QAAKuP;AAEL,aAAO;AAAA,QACL,QAAQ;AAAA,UACN,MAAMA,EAAY;AAAA,UAClB,UAAUA,EAAY;AAAA,UACtB,OAAOA,EAAY;AAAA,UACnB,SAASA,EAAY;AAAA,QAAA;AAAA,MACvB;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA,EAKS,iBAAiBvP,GAAewP,GAA0B;AAEjE,QAAI,CAACA,EAAM,QAAQ;AACjB,WAAK,QAAQ,OAAOxP,CAAK;AACzB;AAAA,IACF;AAGA,UAAMuP,IAA2B;AAAA,MAC/B,OAAAvP;AAAA,MACA,MAAMwP,EAAM,OAAO;AAAA,MACnB,UAAUA,EAAM,OAAO;AAAA,MACvB,OAAOA,EAAM,OAAO;AAAA,MACpB,SAASA,EAAM,OAAO;AAAA,IAAA;AAGxB,SAAK,QAAQ,IAAIxP,GAAOuP,CAAW,GAEnC,KAAK,eAAe,MACpB,KAAK,WAAW;AAAA,EAClB;AAAA;AAAA;AAAA,EAKkB,SAASE;AAAAA;AAE7B;ACzzBO,SAASC,GAAuBjP,GAA8C;AACnF,MAAI,CAACA,EAAQ,OAAQ,QAAO,CAAA;AAE5B,QAAMkP,wBAAkB,IAAA,GAClBC,IAA0C,CAAA,GAG1CC,IAAe,CAACC,GAAkBC,MAA4B;AAClE,QAAI,CAACA,EAAK,OAAQ;AAElB,UAAMC,IAAOJ,EAAcA,EAAc,SAAS,CAAC;AACnD,QAAII,KAAQA,EAAK,YAAYA,EAAK,aAAaA,EAAK,QAAQ,WAAWF,GAAU;AAC/E,MAAAE,EAAK,QAAQ,KAAK,GAAGD,CAAI;AACzB;AAAA,IACF;AACA,IAAAH,EAAc,KAAK;AAAA,MACjB,IAAI,iBAAiBE;AAAA,MACrB,OAAO;AAAA,MACP,SAASC;AAAA,MACT,YAAYD;AAAA,MACZ,UAAU;AAAA,IAAA,CACX;AAAA,EACH;AAEA,MAAIG,IAAyB,CAAA,GACzBC,IAAW;AAiCf,SA/BAzP,EAAQ,QAAQ,CAACY,GAAKF,MAAQ;AAC5B,UAAMgP,IAAU9O,EAAY;AAC5B,QAAI,CAAC8O,GAAG;AACN,MAAIF,EAAI,WAAW,MAAGC,IAAW/O,IACjC8O,EAAI,KAAK5O,CAAG;AACZ;AAAA,IACF;AAEA,IAAI4O,EAAI,WACNJ,EAAaK,GAAUD,EAAI,OAAO,GAClCA,IAAM,CAAA;AAER,UAAMG,IAAK,OAAOD,KAAM,WAAWA,IAAIA,EAAE;AACzC,QAAIE,IAAQV,EAAY,IAAIS,CAAE;AAC9B,IAAKC,MACHA,IAAQ;AAAA,MACN,IAAAD;AAAA,MACA,OAAO,OAAOD,KAAM,WAAW,SAAYA,EAAE;AAAA,MAC7C,SAAS,CAAA;AAAA,MACT,YAAYhP;AAAA,IAAA,GAEdwO,EAAY,IAAIS,GAAIC,CAAK,GACzBT,EAAc,KAAKS,CAAK,IAE1BA,EAAM,QAAQ,KAAKhP,CAAG;AAAA,EACxB,CAAC,GAGG4O,EAAI,UAAQJ,EAAaK,GAAUD,CAAG,GAIxCL,EAAc,WAAW,KACzBA,EAAc,CAAC,EAAE,YACjBA,EAAc,CAAC,EAAE,QAAQ,WAAWnP,EAAQ,SAErC,CAAA,IAGFmP;AACT;AASO,SAASU,GACdC,GACAC,GACA/P,GACM;AACN,MAAI,CAAC+P,EAAO,UAAU,CAACD,EAAa;AAEpC,QAAME,wBAAmB,IAAA;AACzB,aAAWN,KAAKK;AACd,eAAW5P,KAAKuP,EAAE;AAChB,MAAKvP,GAAW,SACd6P,EAAa,IAAK7P,EAAU,OAAOuP,EAAE,EAAE;AAK7C,QAAMrP,IAAc,MAAM,KAAKyP,EAAY,iBAAiB,mBAAmB,CAAC;AAChF,EAAAzP,EAAY,QAAQ,CAACwC,MAAS;AAC5B,UAAMuI,IAAIvI,EAAK,aAAa,YAAY,KAAK,IACvCoN,IAAMD,EAAa,IAAI5E,CAAC;AAC9B,IAAI6E,MACFpN,EAAK,UAAU,IAAI,SAAS,GACvBA,EAAK,aAAa,YAAY,KACjCA,EAAK,aAAa,cAAcoN,CAAG;AAAA,EAGzC,CAAC;AAGD,aAAWP,KAAKK,GAAQ;AACtB,UAAMG,IAAOR,EAAE,QAAQA,EAAE,QAAQ,SAAS,CAAC,GACrC7M,IAAOxC,EAAY,KAAK,CAACF,MAAMA,EAAE,aAAa,YAAY,MAAO+P,EAAa,KAAK;AACzF,IAAIrN,KAAMA,EAAK,UAAU,IAAI,WAAW;AAAA,EAC1C;AACF;AASO,SAASsN,GACdJ,GACA/P,GACoB;AACpB,MAAI+P,EAAO,WAAW,EAAG,QAAO;AAEhC,QAAMK,IAAW,SAAS,cAAc,KAAK;AAC7C,EAAAA,EAAS,YAAY,oBACrBA,EAAS,aAAa,QAAQ,KAAK;AAEnC,aAAWV,KAAKK,GAAQ;AACtB,UAAMM,IACJX,EAAE,cAAc,OACZA,EAAE,aACF1P,EAAQ,UAAU,CAACG,MAAOuP,EAAE,QAAkB,SAASvP,CAAC,CAAC,GAEzDmQ,IAAa,OAAOZ,EAAE,EAAE,EAAE,WAAW,cAAc,GACnDvI,IAAQmJ,IAAa,KAAKZ,EAAE,SAASA,EAAE,IAEvC7M,IAAO,SAAS,cAAc,KAAK;AACzC,IAAAA,EAAK,YAAY,0BACbyN,KAAYzN,EAAK,UAAU,IAAI,gBAAgB,GACnDA,EAAK,aAAa,cAAc,OAAO6M,EAAE,EAAE,CAAC,GAC5C7M,EAAK,MAAM,aAAa,GAAGwN,IAAa,CAAC,WAAWX,EAAE,QAAQ,MAAM,IACpE7M,EAAK,cAAcsE,GACnBiJ,EAAS,YAAYvN,CAAI;AAAA,EAC3B;AAEA,SAAOuN;AACT;AAQO,SAASG,GAAgBvQ,GAAuC;AACrE,SAAOA,EAAQ,KAAK,CAACY,MAASA,EAAY,SAAS,IAAI;AACzD;;AClJO,MAAM4P,WAA8B9O,EAAsC;AAAA,EACtE,OAAO;AAAA,EACE,UAAU;AAAA,EAE5B,IAAuB,gBAAgD;AACrE,WAAO;AAAA,MACL,kBAAkB;AAAA,IAAA;AAAA,EAEtB;AAAA;AAAA,EAGQ,SAAwB,CAAA;AAAA,EACxB,WAAW;AAAA;AAAA;AAAA,EAKV,SAAe;AACtB,SAAK,SAAS,CAAA,GACd,KAAK,WAAW;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,OAAO3B,GAAsBN,GAAsB;AACxD,UAAMO,IAAUP,GAAQ;AACxB,WAAK,MAAM,QAAQO,CAAO,IACnBuQ,GAAgBvQ,CAAO,IADM;AAAA,EAEtC;AAAA;AAAA;AAAA,EAKS,eAAeA,GAAkD;AAExE,UAAM+P,IAASd,GAAoBjP,CAAyB;AAE5D,WAAI+P,EAAO,WAAW,KACpB,KAAK,WAAW,IAChB,KAAK,SAAS,CAAA,GACP,CAAC,GAAG/P,CAAO,MAGpB,KAAK,WAAW,IAChB,KAAK,SAAS+P,GAGP,CAAC,GAAG/P,CAAO;AAAA,EACpB;AAAA,EAES,cAAoB;AAC3B,QAAI,CAAC,KAAK,YAAY,KAAK,OAAO,WAAW,GAAG;AAG9C,YAAMyQ,IADS,KAAK,YAAY,cAAc,SAAS,GACtB,cAAc,mBAAmB;AAClE,MAAIA,KAAkBA,EAAiB,OAAA;AACvC;AAAA,IACF;AAEA,UAAMnQ,IAAS,KAAK,YAAY,cAAc,SAAS;AACvD,QAAI,CAACA,EAAQ;AAGb,UAAMmQ,IAAmBnQ,EAAO,cAAc,mBAAmB;AACjE,IAAImQ,OAAmC,OAAA;AAGvC,UAAML,IAAWD,GAAoB,KAAK,QAAQ,KAAK,OAAyB;AAChF,QAAIC,GAAU;AAEZ,MAAAA,EAAS,UAAU,OAAO,cAAc,CAAC,KAAK,OAAO,gBAAgB;AAErE,YAAMnK,IAAY3F,EAAO,cAAc,aAAa;AACpD,MAAI2F,IACF3F,EAAO,aAAa8P,GAAUnK,CAAS,IAEvC3F,EAAO,YAAY8P,CAAQ;AAAA,IAE/B;AAGA,UAAMnK,IAAY3F,EAAO,cAAc,aAAa;AACpD,IAAI2F,MAEFA,EAAU,UAAU,OAAO,oBAAoB,CAAC,KAAK,OAAO,gBAAgB,GAC5E4J,GAA8B5J,GAAW,KAAK,QAAQ,KAAK,OAAyB;AAAA,EAExF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,mBAA4B;AAC1B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAA2B;AACzB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,gBAAgByK,GAAiC;AAC/C,UAAMd,IAAQ,KAAK,OAAO,KAAK,CAACF,MAAMA,EAAE,OAAOgB,CAAO;AACtD,WAAOd,IAAQA,EAAM,UAAU,CAAA;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKA,UAAgB;AACd,SAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA,EAKkB,SAASZ;AAAAA;AAE7B;ACjIO,SAAS2B,GAAqB,EAAE,MAAA5Q,GAAM,QAAAN,GAAQ,UAAAmR,KAA4C;AAC/F,QAAMC,IAAUpR,EAAO;AACvB,MAAI,OAAOoR,KAAY;AACrB,WAAO,CAAA;AAGT,QAAMC,IAAkB,EAAE,KAAK,YAAY,OAAO,MAAM,OAAO,IAAI,MAAM,CAAA,GAAI,UAAU,oBAAI,MAAI;AAuB/F,MApBA/Q,EAAK,QAAQ,CAACkE,MAAM;AAClB,QAAI8M,IAAYF,EAAQ5M,CAAC;AACzB,IAAI8M,KAAQ,QAAQA,MAAS,KAAOA,IAAO,CAAC,eAAe,IACjD,MAAM,QAAQA,CAAI,MAAGA,IAAO,CAACA,CAAI;AAE3C,QAAIC,IAASF;AACb,IAAAC,EAAK,QAAQ,CAACE,GAAaC,MAAqB;AAC9C,YAAMC,IAAMF,KAAU,OAAO,MAAM,OAAOA,CAAM,GAC1CG,IAAYJ,EAAO,QAAQ,aAAaG,IAAMH,EAAO,MAAM,OAAOG;AACxE,UAAIE,IAAOL,EAAO,SAAS,IAAIG,CAAG;AAClC,MAAKE,MACHA,IAAO,EAAE,KAAKD,GAAW,OAAOH,GAAQ,OAAOC,GAAU,MAAM,CAAA,GAAI,UAAU,oBAAI,IAAA,GAAO,QAAAF,EAAA,GACxFA,EAAO,SAAS,IAAIG,GAAKE,CAAI,IAE/BL,IAASK;AAAA,IACX,CAAC,GACDL,EAAO,KAAK,KAAK/M,CAAC;AAAA,EACpB,CAAC,GAGG6M,EAAK,SAAS,SAAS,KAAKA,EAAK,SAAS,IAAI,eAAe,KAClDA,EAAK,SAAS,IAAI,eAAe,EACrC,KAAK,WAAW/Q,EAAK;WAAe,CAAA;AAI/C,QAAMuR,IAAoB,CAAA,GACpBC,IAAQ,CAACF,MAAoB;AACjC,QAAIA,MAASP,GAAM;AACjB,MAAAO,EAAK,SAAS,QAAQ,CAAClR,MAAMoR,EAAMpR,CAAC,CAAC;AACrC;AAAA,IACF;AAEA,UAAMqR,IAAaZ,EAAS,IAAIS,EAAK,GAAG;AACxC,IAAAC,EAAK,KAAK;AAAA,MACR,MAAM;AAAA,MACN,KAAKD,EAAK;AAAA,MACV,OAAOA,EAAK;AAAA,MACZ,OAAOA,EAAK;AAAA,MACZ,MAAMA,EAAK;AAAA,MACX,UAAUG;AAAA,IAAA,CACX,GAEGA,MACEH,EAAK,SAAS,OAChBA,EAAK,SAAS,QAAQ,CAAClR,MAAMoR,EAAMpR,CAAC,CAAC,IAErCkR,EAAK,KAAK,QAAQ,CAACpN,MAAMqN,EAAK,KAAK,EAAE,MAAM,QAAQ,KAAKrN,GAAG,UAAUlE,EAAK,QAAQkE,CAAC,EAAA,CAAG,CAAC;AAAA,EAG7F;AACA,SAAAsN,EAAMT,CAAI,GAEHQ;AACT;AASO,SAASG,GAAqBC,GAA2BnE,GAA0B;AACxF,QAAMoE,IAAS,IAAI,IAAID,CAAY;AACnC,SAAIC,EAAO,IAAIpE,CAAG,IAChBoE,EAAO,OAAOpE,CAAG,IAEjBoE,EAAO,IAAIpE,CAAG,GAEToE;AACT;AAQO,SAASC,GAAgB7R,GAAgC;AAC9D,QAAM8R,wBAAW,IAAA;AACjB,aAAWrS,KAAOO;AAChB,IAAIP,EAAI,SAAS,WACfqS,EAAK,IAAIrS,EAAI,GAAG;AAGpB,SAAOqS;AACT;AAOO,SAASC,KAAiC;AAC/C,6BAAW,IAAA;AACb;AAkBO,SAASC,GAAiB3B,GAA6B;AAC5D,SAAIA,EAAS,SAAS,UAAgB,IAC/BA,EAAS,KAAK;AACvB;;ACvGO,MAAM4B,WAA2BtQ,EAAmC;AAAA,EAChE,OAAO;AAAA,EACE,UAAU;AAAA,EAE5B,IAAuB,gBAA6C;AAClE,WAAO;AAAA,MACL,iBAAiB;AAAA,MACjB,cAAc;AAAA,MACd,aAAa;AAAA,MACb,aAAa,CAAA;AAAA,MACb,WAAW;AAAA,IAAA;AAAA,EAEf;AAAA;AAAA,EAGQ,mCAAgC,IAAA;AAAA,EAChC,gBAA6B,CAAA;AAAA,EAC7B,WAAW;AAAA,EACX,0CAA0B,IAAA;AAAA,EAC1B,oCAAoB,IAAA;AAAA;AAAA;AAAA,EAK5B,IAAY,iBAA0C;AAEpD,UAAMuQ,IADS,KAAK,KACA,iBAAiB,WAAW,QAAQ;AAExD,QAAIA,MAAS,MAASA,MAAS,MAAO,QAAO;AAC7C,QAAIA,MAAS,MAAQA,MAAS,MAAM;AAClC,YAAMC,IAAO,KAAK,YAAY;AAC9B,UAAIA,KAAQ,iBAAiBA,CAAI,EAAE,iBAAiB,yBAAyB,EAAE,KAAA,MAAW;AACxF,eAAO;AAAA,IAEX;AACA,WAAO,KAAK,OAAO,aAAa;AAAA,EAClC;AAAA;AAAA;AAAA,EAMS,SAAe;AACtB,SAAK,aAAa,MAAA,GAClB,KAAK,gBAAgB,CAAA,GACrB,KAAK,WAAW,IAChB,KAAK,oBAAoB,MAAA,GACzB,KAAK,cAAc,MAAA;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAO,OAAOnS,GAAsBN,GAAsB;AACxD,WAAO,OAAOA,GAAQ,WAAY,cAAc,OAAOA,GAAQ,qBAAsB;AAAA,EACvF;AAAA,EAES,YAAYM,GAA6B;AAChD,UAAMN,IAAS,KAAK;AAGpB,QAAI,OAAOA,EAAO,WAAY;AAC5B,kBAAK,WAAW,IAChB,KAAK,gBAAgB,CAAA,GACd,CAAC,GAAGM,CAAI;AAIjB,UAAMoS,IAAUxB,GAAqB;AAAA,MACnC,MAAA5Q;AAAA,MACA,QAAAN;AAAA,MACA,UAAU,KAAK;AAAA,IAAA,CAChB;AAGD,QAAI0S,EAAQ,WAAW;AACrB,kBAAK,WAAW,IAChB,KAAK,gBAAgB,CAAA,GACd,CAAC,GAAGpS,CAAI;AAGjB,SAAK,WAAW,IAChB,KAAK,gBAAgBoS,GAGrB,KAAK,cAAc,MAAA;AACnB,UAAMC,wBAAyB,IAAA;AAC/B,WAAAD,EAAQ,QAAQ,CAAC3L,GAAM9F,MAAQ;AAC7B,UAAI8F,EAAK,SAAS,QAAQ;AACxB,cAAM+G,IAAM,QAAQ7M,CAAG;AACvB,QAAA0R,EAAmB,IAAI7E,CAAG,GACrB,KAAK,oBAAoB,IAAIA,CAAG,KACnC,KAAK,cAAc,IAAIA,CAAG;AAAA,MAE9B;AAAA,IACF,CAAC,GACD,KAAK,sBAAsB6E,GAIpBD,EAAQ,IAAI,CAAC3L,MACdA,EAAK,SAAS,UACT;AAAA,MACL,cAAc;AAAA,MACd,YAAYA,EAAK;AAAA,MACjB,cAAcA,EAAK;AAAA,MACnB,cAAcA,EAAK;AAAA,MACnB,aAAaA,EAAK;AAAA,MAClB,iBAAiBA,EAAK;AAAA,MACtB,iBAAiBuL,GAAiBvL,CAAI;AAAA,IAAA,IAGnCA,EAAK,GACb;AAAA,EACH;AAAA,EAES,YAAY7E,GAAuC;AAC1D,UAAMnC,IAAMmC,EAAM;AAGlB,QAAInC,GAAK,gBACQmC,EAAM,cAAc,QACvB,QAAQ,eAAe;AACjC,kBAAK,OAAOnC,EAAI,UAAU,GACnB;AAAA,EAGb;AAAA;AAAA;AAAA;AAAA,EAKS,UAAUA,GAAU6S,GAAoBC,GAA4B;AAE3E,QAAI,CAAC9S,GAAK;AACR,aAAO;AAGT,UAAMC,IAAS,KAAK;AAGpB,QAAIA,EAAO,kBAAkB;AAC3B,YAAM8S,IAAe,MAAM;AACzB,aAAK,OAAO/S,EAAI,UAAU;AAAA,MAC5B,GAEMmD,IAASlD,EAAO,iBAAiB;AAAA,QACrC,KAAKD,EAAI;AAAA,QACT,OAAOA,EAAI;AAAA,QACX,OAAOA,EAAI;AAAA,QACX,MAAMA,EAAI;AAAA,QACV,UAAUA,EAAI;AAAA,QACd,cAAA+S;AAAA,MAAA,CACD;AAED,UAAI5P;AACF,eAAA0P,EAAM,YAAY,aACjBA,EAAc,gBAAgB,IAC/BA,EAAM,aAAa,oBAAoB,OAAO7S,EAAI,YAAY,CAAC,GAC3D,OAAOmD,KAAW,WACpB0P,EAAM,YAAY1P,KAElB0P,EAAM,YAAY,IAClBA,EAAM,YAAY1P,CAAM,IAEnB;AAAA,IAEX;AAGA,UAAM6P,IAAe,MAAM;AACzB,WAAK,OAAOhT,EAAI,UAAU;AAAA,IAC5B;AAGA,WAAA6S,EAAM,YAAY,aACjBA,EAAc,gBAAgB,IAC/BA,EAAM,aAAa,oBAAoB,OAAO7S,EAAI,YAAY,CAAC,GAC/D6S,EAAM,aAAa,QAAQ,KAAK,GAChCA,EAAM,aAAa,iBAAiB,OAAO7S,EAAI,eAAe,CAAC,GAC/D6S,EAAM,MAAM,cAAc,IAAI7S,EAAI,gBAAgB,MAAMC,EAAO,eAAe,GAAG,MACjF4S,EAAM,YAAY,IAEE5S,EAAO,cAAc,KAGvC,KAAK,wBAAwBD,GAAK6S,GAAOG,CAAY,IAErD,KAAK,wBAAwBhT,GAAK6S,GAAOG,CAAY,GAGhD;AAAA,EACT;AAAA,EAES,cAAoB;AAC3B,UAAM3G,IAAQ,KAAK;AACnB,QAAIA,MAAU,MAAS,KAAK,cAAc,SAAS,EAAG;AAEtD,UAAM4G,IAAO,KAAK,YAAY,cAAc,OAAO;AACnD,QAAI,CAACA,EAAM;AAEX,UAAMC,IAAY7G,MAAU,SAAS,sBAAsB;AAC3D,eAAWwG,KAASI,EAAK,iBAAiB,gCAAgC,GAAG;AAC3E,YAAM5P,IAAOwP,EAAM,cAAc,iBAAiB,GAC5C3R,IAAMmC,IAAO,SAASA,EAAK,aAAa,UAAU,KAAK,MAAM,EAAE,IAAI,IAEnE0K,IADO,KAAK,cAAc7M,CAAG,GACjB,SAAS,SAAS,QAAQA,CAAG,KAAK;AAEpD,MAAI6M,KAAO,KAAK,cAAc,IAAIA,CAAG,MACnC8E,EAAM,UAAU,IAAIK,CAAS,GAC7BL,EAAM,iBAAiB,gBAAgB,MAAMA,EAAM,UAAU,OAAOK,CAAS,GAAG,EAAE,MAAM,GAAA,CAAM;AAAA,IAElG;AACA,SAAK,cAAc,MAAA;AAAA,EACrB;AAAA;AAAA;AAAA,EAKQ,wBAAwBlT,GAAU6S,GAAoBG,GAAgC;AAC5F,UAAM/S,IAAS,KAAK,QAGdoD,IAAO,SAAS,cAAc,KAAK;AACzC,IAAAA,EAAK,YAAY,mBACjBA,EAAK,MAAM,aAAa,UACxBA,EAAK,aAAa,QAAQ,UAAU;AAGpC,UAAM8P,IAAM,SAAS,cAAc,QAAQ;AAC3C,IAAAA,EAAI,OAAO,UACXA,EAAI,YAAY,eAAenT,EAAI,kBAAkB,cAAc,EAAE,IACrEmT,EAAI,aAAa,cAAcnT,EAAI,kBAAkB,mBAAmB,cAAc,GACtF,KAAK,QAAQmT,GAAK,KAAK,YAAYnT,EAAI,kBAAkB,aAAa,QAAQ,CAAC,GAC/EmT,EAAI,iBAAiB,SAAS,CAACnL,MAAM;AACnC,MAAAA,EAAE,gBAAA,GACFgL,EAAA;AAAA,IACF,CAAC,GACD3P,EAAK,YAAY8P,CAAG;AAGpB,UAAMxL,IAAQ,SAAS,cAAc,MAAM;AAC3C,IAAAA,EAAM,YAAY;AAClB,UAAMyL,IAAYnT,EAAO,cACrBA,EAAO,YAAYD,EAAI,cAAcA,EAAI,gBAAgB,GAAGA,EAAI,UAAU,IAC1E,OAAOA,EAAI,YAAY;AAK3B,QAJA2H,EAAM,cAAcyL,GACpB/P,EAAK,YAAYsE,CAAK,GAGlB1H,EAAO,iBAAiB,IAAO;AACjC,YAAMoT,IAAQ,SAAS,cAAc,MAAM;AAC3C,MAAAA,EAAM,YAAY,eAClBA,EAAM,cAAc,IAAIrT,EAAI,mBAAmBA,EAAI,aAAa,UAAU,CAAC,KAC3EqD,EAAK,YAAYgQ,CAAK;AAAA,IACxB;AAEA,IAAAR,EAAM,YAAYxP,CAAI;AAAA,EACxB;AAAA,EAEQ,wBAAwBrD,GAAU6S,GAAoBG,GAAgC;AAC5F,UAAM/S,IAAS,KAAK,QACdqT,IAAcrT,EAAO,eAAe,CAAA,GACpCO,IAAU,KAAK,SACf+S,IAAYvT,EAAI,eAAe,CAAA,GAI/BwT,IADS,KAAK,YAAY,cAAc,OAAO,GACxB,MAAM,uBAAuB;AAC1D,IAAIA,MACFX,EAAM,MAAM,UAAU,QACtBA,EAAM,MAAM,sBAAsBW,IAGpChT,EAAQ,QAAQ,CAACY,GAAKqS,MAAW;AAC/B,YAAMpQ,IAAO,SAAS,cAAc,KAAK;AAKzC,UAJAA,EAAK,YAAY,mBACjBA,EAAK,aAAa,YAAY,OAAOoQ,CAAM,CAAC,GAC5CpQ,EAAK,aAAa,QAAQ,UAAU,GAEhCoQ,MAAW,GAAG;AAEhB,cAAMN,IAAM,SAAS,cAAc,QAAQ;AAC3C,QAAAA,EAAI,OAAO,UACXA,EAAI,YAAY,eAAenT,EAAI,kBAAkB,cAAc,EAAE,IACrEmT,EAAI,aAAa,cAAcnT,EAAI,kBAAkB,mBAAmB,cAAc,GACtF,KAAK,QAAQmT,GAAK,KAAK,YAAYnT,EAAI,kBAAkB,aAAa,QAAQ,CAAC,GAC/EmT,EAAI,iBAAiB,SAAS,CAACnL,MAAM;AACnC,UAAAA,EAAE,gBAAA,GACFgL,EAAA;AAAA,QACF,CAAC,GACD3P,EAAK,YAAY8P,CAAG;AAEpB,cAAMxL,IAAQ,SAAS,cAAc,MAAM,GACrC+L,IAAcJ,EAAYlS,EAAI,KAAK;AACzC,YAAIsS,GAAa;AACf,gBAAMC,IAAYC,GAAcF,GAAaH,GAAWnS,EAAI,OAAOA,CAAG;AACtE,UAAAuG,EAAM,cAAcgM,KAAa,OAAO,OAAOA,CAAS,IAAI,OAAO3T,EAAI,YAAY;AAAA,QACrF,OAAO;AACL,gBAAMoT,IAAYnT,EAAO,cACrBA,EAAO,YAAYD,EAAI,cAAcA,EAAI,gBAAgB,GAAGA,EAAI,UAAU,IAC1E,OAAOA,EAAI,YAAY;AAC3B,UAAA2H,EAAM,cAAcyL;AAAA,QACtB;AAGA,YAFA/P,EAAK,YAAYsE,CAAK,GAElB1H,EAAO,iBAAiB,IAAO;AACjC,gBAAMoT,IAAQ,SAAS,cAAc,MAAM;AAC3C,UAAAA,EAAM,YAAY,eAClBA,EAAM,cAAc,KAAKE,EAAU,MAAM,KACzClQ,EAAK,YAAYgQ,CAAK;AAAA,QACxB;AAAA,MACF,OAAO;AAEL,cAAMQ,IAASP,EAAYlS,EAAI,KAAK;AACpC,YAAIyS,GAAQ;AACV,gBAAM1Q,IAASyQ,GAAcC,GAAQN,GAAWnS,EAAI,OAAOA,CAAG;AAC9D,UAAAiC,EAAK,cAAcF,KAAU,OAAO,OAAOA,CAAM,IAAI;AAAA,QACvD;AACE,UAAAE,EAAK,cAAc;AAAA,MAEvB;AAEA,MAAAwP,EAAM,YAAYxP,CAAI;AAAA,IACxB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,YAAkB;AAChB,SAAK,eAAe+O,GAAgB,KAAK,aAAa,GACtD,KAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKA,cAAoB;AAClB,SAAK,eAAeE,GAAA,GACpB,KAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAOvE,GAAmB;AACxB,SAAK,eAAekE,GAAqB,KAAK,cAAclE,CAAG;AAG/D,UAAMqC,IAAQ,KAAK,cAAc,KAAK,CAAC3L,MAAMA,EAAE,SAAS,WAAWA,EAAE,QAAQsJ,CAAG;AAEhF,SAAK,KAAwB,gBAAgB;AAAA,MAC3C,KAAAA;AAAA,MACA,UAAU,KAAK,aAAa,IAAIA,CAAG;AAAA,MACnC,OAAOqC,GAAO;AAAA,MACd,OAAOA,GAAO,SAAS;AAAA,IAAA,CACxB,GAED,KAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAAWrC,GAAsB;AAC/B,WAAO,KAAK,aAAa,IAAIA,CAAG;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAOA,GAAmB;AACxB,IAAK,KAAK,aAAa,IAAIA,CAAG,MAC5B,KAAK,mCAAmB,IAAI,CAAC,GAAG,KAAK,cAAcA,CAAG,CAAC,GACvD,KAAK,cAAA;AAAA,EAET;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,SAASA,GAAmB;AAC1B,QAAI,KAAK,aAAa,IAAIA,CAAG,GAAG;AAC9B,YAAM+F,IAAU,IAAI,IAAI,KAAK,YAAY;AACzC,MAAAA,EAAQ,OAAO/F,CAAG,GAClB,KAAK,eAAe+F,GACpB,KAAK,cAAA;AAAA,IACP;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAA4B;AAC1B,UAAMP,IAAY,KAAK,cAAc,OAAO,CAAC9O,MAAMA,EAAE,SAAS,OAAO;AACrE,WAAO;AAAA,MACL,UAAU,KAAK;AAAA,MACf,eAAe,KAAK,aAAa;AAAA,MACjC,aAAa8O,EAAU;AAAA,MACvB,cAAc,CAAC,GAAG,KAAK,YAAY;AAAA,IAAA;AAAA,EAEvC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cAAsB;AACpB,WAAO,KAAK,cAAc;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAsB;AACpB,SAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,oBAA8B;AAC5B,WAAO,CAAC,GAAG,KAAK,YAAY;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,mBAAgC;AAC9B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,mBAA4B;AAC1B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,WAAWQ,GAAkE;AAC1E,SAAK,OAA8B,UAAUA,GAC9C,KAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA,EAKkB,SAASvE;AAAAA;AAE7B;ACpgBO,SAASwE,EAAgBC,GAA2BjU,GAA0B;AACnF,QAAMkU,IAAc,IAAI,IAAID,CAAY;AACxC,SAAIC,EAAY,IAAIlU,CAAG,IACrBkU,EAAY,OAAOlU,CAAG,IAEtBkU,EAAY,IAAIlU,CAAG,GAEdkU;AACT;AAMO,SAASC,GAAgBF,GAA2BjU,GAA0B;AACnF,QAAMkU,IAAc,IAAI,IAAID,CAAY;AACxC,SAAAC,EAAY,IAAIlU,CAAG,GACZkU;AACT;AAMO,SAASE,GAAkBH,GAA2BjU,GAA0B;AACrF,QAAMkU,IAAc,IAAI,IAAID,CAAY;AACxC,SAAAC,EAAY,OAAOlU,CAAG,GACfkU;AACT;AAKO,SAASG,GAAiBJ,GAA2BjU,GAAsB;AAChF,SAAOiU,EAAa,IAAIjU,CAAG;AAC7B;AAMO,SAASsU,GACdtU,GACA2D,GACA4Q,GACAtR,GACa;AACb,QAAMuR,IAAY,SAAS,cAAc,KAAK;AAC9C,EAAAA,EAAU,YAAY,qBACtBA,EAAU,aAAa,mBAAmB,OAAO7Q,CAAQ,CAAC,GAC1D6Q,EAAU,aAAa,QAAQ,KAAK;AAEpC,QAAMC,IAAa,SAAS,cAAc,KAAK;AAC/C,EAAAA,EAAW,YAAY,sBACvBA,EAAW,aAAa,QAAQ,MAAM,GACtCA,EAAW,MAAM,aAAa,OAAOxR,IAAc,CAAC;AAEpD,QAAM4G,IAAU0K,EAASvU,GAAK2D,CAAQ;AACtC,SAAI,OAAOkG,KAAY,WACrB4K,EAAW,YAAY5K,IACdA,aAAmB,eAC5B4K,EAAW,YAAY5K,CAAO,GAGhC2K,EAAU,YAAYC,CAAU,GACzBD;AACT;;ACzCO,MAAME,WAA2BxS,EAAmC;AAAA,EAChE,OAAO;AAAA,EACE,UAAU;AAAA,EAE5B,IAAuB,gBAA6C;AAClE,WAAO;AAAA,MACL,cAAc;AAAA,MACd,kBAAkB;AAAA,MAClB,wBAAwB;AAAA,MACxB,kBAAkB;AAAA,MAClB,WAAW;AAAA;AAAA,IAAA;AAAA,EAEf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,IAAY,qBAA8B;AAExC,UAAMuQ,IADS,KAAK,KACA,iBAAiB,WAAW,QAAQ;AAExD,QAAIA,MAAS,MAASA,MAAS,MAAO,QAAO;AAC7C,QAAIA,MAAS,MAAQA,MAAS,KAAM,QAAO;AAG3C,UAAMC,IAAO,KAAK,YAAY;AAC9B,WAAIA,IACc,iBAAiBA,CAAI,EAAE,iBAAiB,yBAAyB,EAAE,KAAA,MAChE,MAEd;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,IAAY,iBAA0C;AACpD,WAAK,KAAK,qBACH,KAAK,OAAO,aAAa,UADK;AAAA,EAEvC;AAAA;AAAA;AAAA;AAAA,EAKA,IAAY,oBAA4B;AACtC,UAAMA,IAAO,KAAK,YAAY;AAC9B,QAAIA,GAAM;AACR,YAAMiC,IAAc,iBAAiBjC,CAAI,EAAE,iBAAiB,0BAA0B,EAAE,KAAA,GAClFlP,IAAS,SAASmR,GAAa,EAAE;AACvC,UAAI,CAAC,MAAMnR,CAAM,EAAG,QAAOA;AAAA,IAC7B;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,cAAcoR,GAA6B;AACjD,IAAI,CAAC,KAAK,sBAAsB,KAAK,mBAAmB,OAExDA,EAAS,UAAU,IAAI,eAAe,GACtCA,EAAS;AAAA,MACP;AAAA,MACA,MAAM;AACJ,QAAAA,EAAS,UAAU,OAAO,eAAe;AAAA,MAC3C;AAAA,MACA,EAAE,MAAM,GAAA;AAAA,IAAK;AAAA,EAEjB;AAAA;AAAA;AAAA;AAAA,EAKQ,gBAAgBA,GAAuBC,GAA8B;AAC3E,QAAI,CAAC,KAAK,sBAAsB,KAAK,mBAAmB,IAAO;AAC7D,MAAAA,EAAA;AACA;AAAA,IACF;AAEA,IAAAD,EAAS,UAAU,IAAI,gBAAgB;AACvC,UAAME,IAAU,MAAM;AACpB,MAAAF,EAAS,UAAU,OAAO,gBAAgB,GAC1CC,EAAA;AAAA,IACF;AACA,IAAAD,EAAS,iBAAiB,gBAAgBE,GAAS,EAAE,MAAM,IAAM,GAEjE,WAAWA,GAAS,KAAK,oBAAoB,EAAE;AAAA,EACjD;AAAA;AAAA;AAAA,EAKQ,mCAA6B,IAAA;AAAA,EAC7B,qCAA4C,IAAA;AAAA;AAAA;AAAA,EAK3C,SAAe;AACtB,SAAK,aAAa,MAAA,GAClB,KAAK,eAAe,MAAA;AAAA,EACtB;AAAA;AAAA;AAAA,EAKS,eACPtU,GAC2C;AAC3C,QAAI,CAAC,KAAK,OAAO;AACf,aAAO,CAAC,GAAGA,CAAO;AAIpB,UAAMsP,IAAO,CAAC,GAAGtP,CAAO;AACxB,QAAIsP,EAAK,SAAS,GAAG;AACnB,YAAMiF,IAAW,EAAE,GAAGjF,EAAK,CAAC,EAAA,GACtBkF,IAAmBD,EAAS;AAGlC,UAAKC,GAA0B;AAC7B,eAAOlF;AAGT,YAAMmF,IAAkB,CAACC,MAAmE;AAC1F,cAAM,EAAE,OAAApV,GAAO,KAAAE,EAAA,IAAQkV,GACjBlD,IAAa,KAAK,aAAa,IAAIhS,CAAG,GAEtC+I,IAAY,SAAS,cAAc,MAAM;AAC/C,QAAAA,EAAU,YAAY;AAGtB,cAAMoM,IAAS,SAAS,cAAc,MAAM;AAC5C,QAAAA,EAAO,YAAY,uBAAuBnD,IAAa,cAAc,EAAE,IAEvE,KAAK,QAAQmD,GAAQ,KAAK,YAAYnD,IAAa,aAAa,QAAQ,CAAC,GAEzEmD,EAAO,aAAa,QAAQ,QAAQ,GACpCA,EAAO,aAAa,YAAY,GAAG,GACnCA,EAAO,aAAa,iBAAiB,OAAOnD,CAAU,CAAC,GACvDmD,EAAO,aAAa,cAAcnD,IAAa,qBAAqB,gBAAgB,GACpFmD,EAAO,iBAAiB,SAAS,CAACnN,MAAM;AACtC,UAAAA,EAAE,gBAAA;AACF,gBAAMrE,IAAW,KAAK,KAAK,QAAQ3D,CAAG;AACtC,eAAK,eAAegU,EAAgB,KAAK,cAAchU,CAAG,GAC1D,KAAK,KAAyB,iBAAiB;AAAA,YAC7C,UAAA2D;AAAA,YACA,KAAA3D;AAAA,YACA,UAAU,KAAK,aAAa,IAAIA,CAAG;AAAA,UAAA,CACpC,GACD,KAAK,cAAA;AAAA,QACP,CAAC,GACD+I,EAAU,YAAYoM,CAAM;AAG5B,cAAMtL,IAAU,SAAS,cAAc,MAAM;AAC7C,YAAImL,GAAkB;AACpB,gBAAMI,IAAWJ,EAAiBE,CAAS;AAC3C,UAAIE,aAAoB,OACtBvL,EAAQ,YAAYuL,CAAQ,IAE5BvL,EAAQ,cAAc,OAAOuL,KAAYtV,KAAS,EAAE;AAAA,QAExD;AACE,UAAA+J,EAAQ,cAAc,OAAO/J,KAAS,EAAE;AAE1C,eAAAiJ,EAAU,YAAYc,CAAO,GAEtBd;AAAA,MACT;AAGC,MAAAkM,EAAwB,wBAAwB,IACjDF,EAAS,eAAeE,GAExBnF,EAAK,CAAC,IAAIiF;AAAA,IACZ;AAEA,WAAOjF;AAAA,EACT;AAAA,EAES,WAAW3N,GAAsC;AACxD,QAAI,GAAC,KAAK,OAAO,oBAAoB,CAAC,KAAK,OAAO;AAElD,kBAAK,eAAe6R,EAAgB,KAAK,cAAc7R,EAAM,GAAG,GAEhE,KAAK,KAAyB,iBAAiB;AAAA,QAC7C,UAAUA,EAAM;AAAA,QAChB,KAAKA,EAAM;AAAA,QACX,UAAU,KAAK,aAAa,IAAIA,EAAM,GAAG;AAAA,MAAA,CAC1C,GAED,KAAK,cAAA,GACE;AAAA,EACT;AAAA,EAES,cAA8B;AAGrC,IAAI,KAAK,aAAa,OAAO,KAC3B,eAAe,MAAM,KAAKkT,IAAiB;AAAA,EAG/C;AAAA,EAES,cAAoB;AAC3B,SAAKA,GAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA,EAMS,iBAAuB;AAC9B,IAAI,CAAC,KAAK,OAAO,kBAAkB,KAAK,aAAa,SAAS,KAE9D,KAAKA,GAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA,EAMAA,KAAwB;AACtB,QAAI,CAAC,KAAK,OAAO,eAAgB;AAEjC,UAAMpC,IAAO,KAAK,YAAY,cAAc,OAAO;AACnD,QAAI,CAACA,EAAM;AAGX,UAAMqC,wBAAoB,IAAA,GACpBC,IAAWtC,EAAK,iBAAiB,gBAAgB,GACjDhQ,IAAc,KAAK,QAAQ;AAEjC,eAAW4P,KAAS0C,GAAU;AAC5B,YAAMC,IAAY3C,EAAM,cAAc,iBAAiB,GACjDlP,IAAW6R,IAAY,SAASA,EAAU,aAAa,UAAU,KAAK,MAAM,EAAE,IAAI;AACxF,MAAI7R,KAAY,KACd2R,EAAc,IAAI3R,GAAUkP,CAAK;AAAA,IAErC;AAGA,UAAM4C,IAAkBxC,EAAK,iBAAiB,oBAAoB;AAClE,eAAW2B,KAAYa,GAAiB;AACtC,YAAMC,IAAW,SAASd,EAAS,aAAa,iBAAiB,KAAK,MAAM,EAAE,GACxE5U,IAAM0V,KAAY,IAAI,KAAK,KAAKA,CAAQ,IAAI,QAC5CC,IAAkB3V,KAAO,KAAK,aAAa,IAAIA,CAAG,GAClD4V,IAAeN,EAAc,IAAII,CAAQ;AAG/C,OAAI,CAACC,KAAmB,CAACC,OACvBhB,EAAS,OAAA,GACL5U,KAAK,KAAK,eAAe,OAAOA,CAAG;AAAA,IAE3C;AAGA,eAAW,CAAC2D,GAAUkP,CAAK,KAAKyC,GAAe;AAC7C,YAAMtV,IAAM,KAAK,KAAK2D,CAAQ;AAC9B,UAAI,CAAC3D,KAAO,CAAC,KAAK,aAAa,IAAIA,CAAG,EAAG;AAGzC,YAAM6V,IAAiB,KAAK,eAAe,IAAI7V,CAAG;AAClD,UAAI6V,GAAgB;AAElB,QAAIA,EAAe,2BAA2BhD,KAC5CA,EAAM,MAAMgD,CAAc;AAE5B;AAAA,MACF;AAGA,YAAMjB,IAAWN,GAAoBtU,GAAK2D,GAAU,KAAK,OAAO,gBAAgBV,CAAW;AAE3F,MAAI,OAAO,KAAK,OAAO,gBAAiB,aACtC2R,EAAS,MAAM,SAAS,GAAG,KAAK,OAAO,YAAY,OAIrD/B,EAAM,MAAM+B,CAAQ,GACpB,KAAK,eAAe,IAAI5U,GAAK4U,CAAQ,GAGrC,KAAK,cAAcA,CAAQ;AAAA,IAC7B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMS,iBAAyB;AAChC,QAAIkB,IAAc;AAClB,eAAW9V,KAAO,KAAK,cAAc;AACnC,YAAM4U,IAAW,KAAK,eAAe,IAAI5U,CAAG;AAC5C,UAAI4U;AACF,QAAAkB,KAAelB,EAAS;AAAA,WACnB;AAEL,cAAMmB,IAAe,KAAK,QAAQ;AAClC,QAAAD,KAAe,OAAOC,KAAiB,WAAWA,IAAe;AAAA,MACnE;AAAA,IACF;AACA,WAAOD;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMS,qBAAqBE,GAAgC;AAC5D,QAAIF,IAAc;AAClB,eAAW9V,KAAO,KAAK,cAAc;AACnC,YAAM2D,IAAW,KAAK,KAAK,QAAQ3D,CAAG;AAEtC,UAAI2D,KAAY,KAAKA,IAAWqS,GAAgB;AAC9C,cAAMpB,IAAW,KAAK,eAAe,IAAI5U,CAAG;AAC5C,YAAI4U;AACF,UAAAkB,KAAelB,EAAS;AAAA,aACnB;AACL,gBAAMmB,IAAe,KAAK,QAAQ;AAClC,UAAAD,KAAe,OAAOC,KAAiB,WAAWA,IAAe;AAAA,QACnE;AAAA,MACF;AAAA,IACF;AACA,WAAOD;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMS,mBAAmB9K,GAAeH,GAAmBC,GAA2B;AACvF,QAAI,KAAK,aAAa,SAAS,EAAG,QAAOE;AAGzC,UAAMiL,IAAsD,CAAA;AAC5D,eAAWjW,KAAO,KAAK,cAAc;AACnC,YAAMsO,IAAQ,KAAK,KAAK,QAAQtO,CAAG;AACnC,MAAIsO,KAAS,KACX2H,EAAgB,KAAK,EAAE,OAAA3H,GAAO,KAAAtO,EAAA,CAAK;AAAA,IAEvC;AACA,IAAAiW,EAAgB,KAAK,CAACjV,GAAGC,MAAMD,EAAE,QAAQC,EAAE,KAAK;AAEhD,QAAIiV,IAAWlL,GAIXmL,IAAwB;AAE5B,eAAW,EAAE,OAAOxS,GAAU,KAAA3D,EAAA,KAASiW,GAAiB;AAEtD,YAAMG,IAAezS,IAAWmH,IAAYqL,GAEtCE,IADW,KAAK,eAAe,IAAIrW,CAAG,GAEhC,iBAAiB,OAAO,KAAK,QAAQ,gBAAiB,WAAW,KAAK,OAAO,eAAe,MAClGsW,IAAqBF,IAAetL,IAAYuL;AAMtD,MAHAF,KAAyBE,GAGrB,EAAA1S,KAAYqH,MAIZsL,IAAqBzL,KACnBlH,IAAWuS,MACbA,IAAWvS;AAAA,IAGjB;AAEA,WAAOuS;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAOvS,GAAwB;AAC7B,UAAM3D,IAAM,KAAK,KAAK2D,CAAQ;AAC9B,IAAI3D,MACF,KAAK,eAAemU,GAAgB,KAAK,cAAcnU,CAAG,GAC1D,KAAK,cAAA;AAAA,EAET;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,SAAS2D,GAAwB;AAC/B,UAAM3D,IAAM,KAAK,KAAK2D,CAAQ;AAC9B,IAAI3D,MACF,KAAK,eAAeoU,GAAkB,KAAK,cAAcpU,CAAG,GAC5D,KAAK,cAAA;AAAA,EAET;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO2D,GAAwB;AAC7B,UAAM3D,IAAM,KAAK,KAAK2D,CAAQ;AAC9B,IAAI3D,MACF,KAAK,eAAegU,EAAgB,KAAK,cAAchU,CAAG,GAC1D,KAAK,cAAA;AAAA,EAET;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAAW2D,GAA2B;AACpC,UAAM3D,IAAM,KAAK,KAAK2D,CAAQ;AAC9B,WAAO3D,IAAMqU,GAAiB,KAAK,cAAcrU,CAAG,IAAI;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA,EAKA,YAAkB;AAChB,eAAWA,KAAO,KAAK;AACrB,WAAK,aAAa,IAAIA,CAAG;AAE3B,SAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKA,cAAoB;AAClB,SAAK,aAAa,MAAA,GAClB,KAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,kBAA4B;AAC1B,UAAM2E,IAAoB,CAAA;AAC1B,eAAW3E,KAAO,KAAK,cAAc;AACnC,YAAMkB,IAAM,KAAK,KAAK,QAAQlB,CAAG;AACjC,MAAIkB,KAAO,KAAGyD,EAAQ,KAAKzD,CAAG;AAAA,IAChC;AACA,WAAOyD;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,iBAAiBhB,GAA2C;AAC1D,UAAM3D,IAAM,KAAK,KAAK2D,CAAQ;AAC9B,WAAO3D,IAAM,KAAK,eAAe,IAAIA,CAAG,IAAI;AAAA,EAC9C;AAAA;AAAA;AAAA,EAIkB,SAASwP;AAAAA;AAE7B;AC/eO,SAAS+G,GAA2BhW,GAAciW,GAAoBhW,GAAuC;AAClH,SAAKgW,EAAM,SAEJ,CAAC,GAAGjW,CAAI,EAAE,KAAK,CAACS,GAAGC,MAAM;AAC9B,eAAWwV,KAAQD,GAAO;AAExB,YAAME,IADMlW,EAAQ,KAAK,CAACG,MAAMA,EAAE,UAAU8V,EAAK,KAAK,GAC9B,kBAAkBE,IACpCC,IAAQ5V,EAA8ByV,EAAK,KAAK,GAChDI,IAAQ5V,EAA8BwV,EAAK,KAAK,GAChDtT,IAASuT,EAAWE,GAAMC,GAAM7V,GAAGC,CAAC;AAC1C,UAAIkC,MAAW;AACb,eAAOsT,EAAK,cAAc,QAAQtT,IAAS,CAACA;AAAA,IAEhD;AACA,WAAO;AAAA,EACT,CAAC,IAdyB,CAAC,GAAG5C,CAAI;AAepC;AAUO,SAASoW,GAAkB3V,GAAYC,GAAoB;AAEhE,SAAID,KAAK,QAAQC,KAAK,OAAa,IAC/BD,KAAK,OAAa,IAClBC,KAAK,OAAa,KAGlB,OAAOD,KAAM,YAAY,OAAOC,KAAM,WACjCD,IAAIC,IAGTD,aAAa,QAAQC,aAAa,OAC7BD,EAAE,YAAYC,EAAE,QAAA,IAIrB,OAAOD,KAAM,aAAa,OAAOC,KAAM,YAClCD,MAAMC,IAAI,IAAID,IAAI,KAAK,IAIzB,OAAOA,CAAC,EAAE,cAAc,OAAOC,CAAC,CAAC;AAC1C;AAaO,SAAS6V,GAAWC,GAAsBhX,GAAeiX,GAAmBC,GAAiC;AAClH,QAAMC,IAAWH,EAAQ,KAAK,CAACI,MAAMA,EAAE,UAAUpX,CAAK;AAEtD,SAAIiX,IAEEE,IACEA,EAAS,cAAc,QAElBH,EAAQ,IAAI,CAACI,MAAOA,EAAE,UAAUpX,IAAQ,EAAE,GAAGoX,GAAG,WAAW,OAAA,IAAoBA,CAAE,IAGjFJ,EAAQ,OAAO,CAACI,MAAMA,EAAE,UAAUpX,CAAK,IAEvCgX,EAAQ,SAASE,IAEnB,CAAC,GAAGF,GAAS,EAAE,OAAAhX,GAAO,WAAW,OAAgB,IAGnDgX,IAGHG,GAAU,cAAc,QACnB,CAAC,EAAE,OAAAnX,GAAO,WAAW,QAAQ,IAC3BmX,GAAU,cAAc,SAC1B,CAAA,IAEF,CAAC,EAAE,OAAAnX,GAAO,WAAW,OAAO;AAEvC;AAUO,SAASqX,GAAaC,GAAwBtX,GAAmC;AACtF,QAAMuO,IAAQ+I,EAAU,UAAU,CAACF,MAAMA,EAAE,UAAUpX,CAAK;AAC1D,SAAOuO,KAAS,IAAIA,IAAQ,IAAI;AAClC;AASO,SAASgJ,GAAiBD,GAAwBtX,GAA2C;AAClG,SAAOsX,EAAU,KAAK,CAACF,MAAMA,EAAE,UAAUpX,CAAK,GAAG;AACnD;;AC9GO,MAAMwX,WAAwBrV,EAAgC;AAAA,EAC1D,OAAO;AAAA,EACE,UAAU;AAAA,EAE5B,IAAuB,gBAA0C;AAC/D,WAAO;AAAA,MACL,gBAAgB;AAAA,MAChB,eAAe;AAAA,IAAA;AAAA,EAEnB;AAAA;AAAA,EAGQ,YAAyB,CAAA;AAAA;AAAA;AAAA,EAKxB,SAAe;AACtB,SAAK,YAAY,CAAA;AAAA,EACnB;AAAA;AAAA;AAAA,EAKS,YAAY3B,GAAqC;AACxD,WAAI,KAAK,UAAU,WAAW,IACrB,CAAC,GAAGA,CAAI,IAEVgW,GAAW,CAAC,GAAGhW,CAAI,GAAG,KAAK,WAAW,CAAC,GAAG,KAAK,OAAO,CAAC;AAAA,EAChE;AAAA,EAES,cAAc4B,GAAkC;AAEvD,QAAI,CADW,KAAK,QAAQ,KAAK,CAACxB,MAAMA,EAAE,UAAUwB,EAAM,KAAK,GAClD,SAAU,QAAO;AAE9B,UAAM6U,IAAW7U,EAAM,cAAc,UAC/B8U,IAAa,KAAK,OAAO,kBAAkB;AAEjD,gBAAK,YAAYH,GAAW,KAAK,WAAW3U,EAAM,OAAO6U,GAAUC,CAAU,GAE7E,KAAK,KAAK,eAAe,EAAE,WAAW,CAAC,GAAG,KAAK,SAAS,GAAG,GAC3D,KAAK,cAAA,GAEE;AAAA,EACT;AAAA,EAES,cAAoB;AAC3B,UAAM1Q,IAAa,KAAK;AACxB,QAAI,CAACA,EAAY;AAEjB,UAAMiR,IAAY,KAAK,OAAO,kBAAkB;AAIhD,IADoBjR,EAAW,iBAAiB,+BAA+B,EACnE,QAAQ,CAAClD,MAAS;AAC5B,YAAMtD,IAAQsD,EAAK,aAAa,YAAY;AAC5C,UAAI,CAACtD,EAAO;AAEZ,YAAM0X,IAAYL,GAAa,KAAK,WAAWrX,CAAK,GAC9C2X,IAAUJ,GAAiB,KAAK,WAAWvX,CAAK;AAMtD,UAHsBsD,EAAK,cAAc,aAAa,GACvC,OAAA,GAEXqU,GAAS;AAGX,QAD0BrU,EAAK,cAAc,2CAA2C,GACrE,OAAA,GAEnBA,EAAK,aAAa,aAAaqU,CAAO;AAGtC,cAAMC,IAAY,SAAS,cAAc,MAAM;AAO/C,YANAA,EAAU,YAAY,kBAEtB,KAAK,QAAQA,GAAW,KAAK,YAAYD,MAAY,QAAQ,YAAY,UAAU,CAAC,GACpFrU,EAAK,YAAYsU,CAAS,GAGtBH,KAAa,KAAK,UAAU,SAAS,KAAKC,MAAc,QAAW;AACrE,gBAAMG,IAAQ,SAAS,cAAc,MAAM;AAC3C,UAAAA,EAAM,YAAY,cAClBA,EAAM,cAAc,OAAOH,CAAS,GACpCpU,EAAK,YAAYuU,CAAK;AAAA,QACxB;AAAA,MACF;AACE,QAAAvU,EAAK,gBAAgB,WAAW;AAAA,IAGpC,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,eAA4B;AAC1B,WAAO,CAAC,GAAG,KAAK,SAAS;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAawU,GAA0B;AACrC,SAAK,YAAY,CAAC,GAAGA,CAAK,GAC1B,KAAK,KAAK,eAAe,EAAE,WAAW,CAAC,GAAGA,CAAK,GAAG,GAClD,KAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKA,YAAkB;AAChB,SAAK,YAAY,CAAA,GACjB,KAAK,KAAK,eAAe,EAAE,WAAW,CAAA,GAAI,GAC1C,KAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,aAAa9X,GAAmC;AAC9C,WAAOqX,GAAa,KAAK,WAAWrX,CAAK;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,iBAAiBA,GAA2C;AAC1D,WAAOuX,GAAiB,KAAK,WAAWvX,CAAK;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQS,eAAeA,GAAiD;AACvE,UAAMuO,IAAQ,KAAK,UAAU,UAAU,CAAC6I,MAAMA,EAAE,UAAUpX,CAAK;AAC/D,WAAIuO,MAAU,KAAI,SAGX;AAAA,MACL,MAAM;AAAA,QACJ,WAHc,KAAK,UAAUA,CAAK,EAGb;AAAA,QACrB,UAAUA;AAAA,MAAA;AAAA,IACZ;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMS,iBAAiBvO,GAAewP,GAA0B;AAEjE,QAAI,CAACA,EAAM,MAAM;AAEf,WAAK,YAAY,KAAK,UAAU,OAAO,CAAC4H,MAAMA,EAAE,UAAUpX,CAAK;AAC/D;AAAA,IACF;AAGA,UAAM+X,IAAgB,KAAK,UAAU,UAAU,CAACX,MAAMA,EAAE,UAAUpX,CAAK,GACjEgY,IAAsB;AAAA,MAC1B,OAAAhY;AAAA,MACA,WAAWwP,EAAM,KAAK;AAAA,IAAA;AAGxB,IAAIuI,MAAkB,KAEpB,KAAK,UAAUA,CAAa,IAAIC,IAGhC,KAAK,UAAU,OAAOxI,EAAM,KAAK,UAAU,GAAGwI,CAAQ;AAAA,EAK1D;AAAA;AAAA;AAAA,EAKkB,SAASvI;AAAAA;AAE7B;ACzMO,SAASwI,GAAqBxX,GAAuB;AAC1D,SAAOA,EAAQ,OAAO,CAACY,MAAQA,EAAI,WAAW,MAAM;AACtD;AAQO,SAAS6W,GAAsBzX,GAAuB;AAC3D,SAAOA,EAAQ,OAAO,CAACY,MAAQA,EAAI,WAAW,OAAO;AACvD;AAQO,SAAS8W,EAAiB1X,GAAyB;AACxD,SAAOA,EAAQ,KAAK,CAACY,MAAQA,EAAI,WAAW,UAAUA,EAAI,WAAW,OAAO;AAC9E;AAyEO,SAAS+W,GAAmBzF,GAAmBlS,GAAsB;AAC1E,QAAM+F,IAAamM,EAAK;AACxB,MAAI,CAACnM,EAAY;AAEjB,QAAM1F,IAAc,MAAM,KAAK0F,EAAW,iBAAiB,mBAAmB,CAAC;AAC/E,MAAI,CAAC1F,EAAY,OAAQ;AAGzB,QAAMuX,wBAAmB,IAAA;AACzB,EAAA5X,EAAQ,QAAQ,CAACY,GAAKU,MAAM;AAC1B,IAAIV,EAAI,SAAOgX,EAAa,IAAIhX,EAAI,OAAOU,CAAC;AAAA,EAC9C,CAAC;AAGD,MAAIwG,IAAO;AACX,aAAWlH,KAAOZ;AAChB,QAAIY,EAAI,WAAW,QAAQ;AACzB,YAAMwC,IAAWwU,EAAa,IAAIhX,EAAI,KAAK,GACrCiC,IAAOxC,EAAY,KAAK,CAAC,MAAM,EAAE,aAAa,YAAY,MAAMO,EAAI,KAAK;AAC/E,MAAIiC,MACFA,EAAK,UAAU,IAAI,aAAa,GAChCA,EAAK,MAAM,WAAW,UACtBA,EAAK,MAAM,OAAOiF,IAAO,MAErB1E,MAAa,UACf2C,EAAW,iBAAiB,kCAAkC3C,CAAQ,IAAI,EAAE,QAAQ,CAACyU,MAAO;AAC1F,QAAAA,EAAG,UAAU,IAAI,aAAa,GAC7BA,EAAmB,MAAM,WAAW,UACpCA,EAAmB,MAAM,OAAO/P,IAAO;AAAA,MAC1C,CAAC,GAEHA,KAAQjF,EAAK;AAAA,IAEjB;AAIF,MAAIiV,IAAQ;AACZ,aAAWlX,KAAO,CAAC,GAAGZ,CAAO,EAAE;AAC7B,QAAIY,EAAI,WAAW,SAAS;AAC1B,YAAMwC,IAAWwU,EAAa,IAAIhX,EAAI,KAAK,GACrCiC,IAAOxC,EAAY,KAAK,CAAC,MAAM,EAAE,aAAa,YAAY,MAAMO,EAAI,KAAK;AAC/E,MAAIiC,MACFA,EAAK,UAAU,IAAI,cAAc,GACjCA,EAAK,MAAM,WAAW,UACtBA,EAAK,MAAM,QAAQiV,IAAQ,MAEvB1U,MAAa,UACf2C,EAAW,iBAAiB,kCAAkC3C,CAAQ,IAAI,EAAE,QAAQ,CAACyU,MAAO;AAC1F,QAAAA,EAAG,UAAU,IAAI,cAAc,GAC9BA,EAAmB,MAAM,WAAW,UACpCA,EAAmB,MAAM,QAAQC,IAAQ;AAAA,MAC5C,CAAC,GAEHA,KAASjV,EAAK;AAAA,IAElB;AAEJ;AAOO,SAASkV,GAAmB7F,GAAyB;AAC1D,QAAMnM,IAAamM,EAAK;AACxB,MAAI,CAACnM,EAAY;AAGjB,EADcA,EAAW,iBAAiB,6BAA6B,EACjE,QAAQ,CAAClD,MAAS;AACtB,IAAAA,EAAK,UAAU,OAAO,eAAe,cAAc,GAClDA,EAAqB,MAAM,WAAW,IACtCA,EAAqB,MAAM,OAAO,IAClCA,EAAqB,MAAM,QAAQ;AAAA,EACtC,CAAC;AACH;AClKO,MAAMmV,WAA4BtW,EAAoC;AAAA,EAClE,OAAO;AAAA,EACE,UAAU;AAAA,EAE5B,IAAuB,gBAA8C;AACnE,WAAO,CAAA;AAAA,EACT;AAAA;AAAA,EAGQ,YAAY;AAAA,EACZ,kCAAkB,IAAA;AAAA,EAClB,mCAAmB,IAAA;AAAA;AAAA;AAAA,EAKlB,SAAe;AACtB,SAAK,YAAY,MAAA,GACjB,KAAK,aAAa,MAAA,GAClB,KAAK,YAAY;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,OAAO3B,GAA0BN,GAA+C;AACrF,UAAMO,IAAUP,GAAQ;AACxB,WAAK,MAAM,QAAQO,CAAO,IACnB0X,EAAiB1X,CAAO,IADK;AAAA,EAEtC;AAAA;AAAA;AAAA,EAKS,eAAeA,GAAkD;AAExE,gBAAK,YAAY0X,EAAiB,CAAC,GAAG1X,CAAO,CAAC,GACvC,CAAC,GAAGA,CAAO;AAAA,EACpB;AAAA,EAES,cAAoB;AAC3B,QAAI,CAAC,KAAK;AACR;AAGF,UAAMkS,IAAO,KAAK,MACZlS,IAAU,CAAC,GAAG,KAAK,OAAO;AAEhC,QAAI,CAAC0X,EAAiB1X,CAAO,GAAG;AAC9B,MAAA+X,GAAmB7F,CAAI,GACvB,KAAK,YAAY;AACjB;AAAA,IACF;AAGA,mBAAe,MAAM;AACnB,MAAAyF,GAAmBzF,GAAMlS,CAAO;AAAA,IAClC,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKS,cAAciY,GAA6B;AAClD,YAAQA,EAAM,MAAA;AAAA,MACZ,KAAKC,EAAe,iBAAiB;AAGnC,cAAM5U,IAAS2U,EAAM,SACfE,IAAU7U,EAAwD;AACxE,YAAI6U,MAAW,UAAUA,MAAW;AAClC,iBAAO;AAGT,cAAMC,IAAc9U,EAAO,MAAoD;AAC/E,eAAI8U,MAAe,UAAUA,MAAe,UACnC,KAET;AAAA,MACF;AAAA,MACA;AACE;AAAA,IAAO;AAAA,EAEb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,uBAA6B;AAC3B,UAAMpY,IAAU,CAAC,GAAG,KAAK,OAAO;AAChC,IAAA2X,GAAmB,KAAK,MAAgC3X,CAAO;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA,EAKA,uBAAuC;AACrC,UAAMA,IAAU,CAAC,GAAG,KAAK,OAAO;AAChC,WAAOwX,GAAqBxX,CAAO;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA,EAKA,wBAAwC;AACtC,UAAMA,IAAU,CAAC,GAAG,KAAK,OAAO;AAChC,WAAOyX,GAAsBzX,CAAO;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,uBAA6B;AAC3B,IAAA+X,GAAmB,KAAK,IAA8B;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMS,2BACP1F,GACAgG,GACmE;AACnE,QAAI,CAAC,KAAK;AACR;AAGF,QAAIvQ,IAAO,GACPgQ,IAAQ;AAEZ,QAAIzF,GAAO;AAET,YAAMiG,IAAkBjG,EAAM,iBAAiB,cAAc,GACvDkG,IAAmBlG,EAAM,iBAAiB,eAAe;AAC/D,MAAAiG,EAAgB,QAAQ,CAACT,MAAO;AAC9B,QAAA/P,KAAS+P,EAAmB;AAAA,MAC9B,CAAC,GACDU,EAAiB,QAAQ,CAACV,MAAO;AAC/B,QAAAC,KAAUD,EAAmB;AAAA,MAC/B,CAAC;AAAA,IACH,OAAO;AAGL,YAAM9R,IADO,KAAK,KACM;AACxB,MAAIA,KACkBA,EAAW,iBAAiB,mBAAmB,EACvD,QAAQ,CAAClD,MAAS;AAC5B,QAAIA,EAAK,UAAU,SAAS,aAAa,IACvCiF,KAASjF,EAAqB,cACrBA,EAAK,UAAU,SAAS,cAAc,MAC/CiV,KAAUjV,EAAqB;AAAA,MAEnC,CAAC;AAAA,IAEL;AAGA,UAAM2V,IACJH,GAAa,UAAU,SAAS,aAAa,KAAKA,GAAa,UAAU,SAAS,cAAc;AAElG,WAAO,EAAE,MAAAvQ,GAAM,OAAAgQ,GAAO,YAAAU,EAAA;AAAA,EACxB;AAAA;AAEF;AC9KA,SAASC,GAAmBC,GAAoD;AAC9E,SAAO,OAAOA,KAAQ,YAAYA,MAAQ,QAAQ,aAAaA;AACjE;AASO,SAASC,EAAqBlZ,GAA0BmZ,GAAyC;AACtG,QAAMC,IAAa,SAAS,cAAc,KAAK;AAC/C,EAAAA,EAAW,YAAY,mBACvBA,EAAW,aAAa,QAAQ,cAAc,GAC9CA,EAAW,aAAa,aAAa,QAAQ;AAE7C,QAAM/Q,IAAO,SAAS,cAAc,KAAK;AACzC,EAAAA,EAAK,YAAY;AAEjB,QAAMgR,IAAS,SAAS,cAAc,KAAK;AAC3C,EAAAA,EAAO,YAAY;AAEnB,QAAMhB,IAAQ,SAAS,cAAc,KAAK;AAI1C,MAHAA,EAAM,YAAY,yBAGdrY,EAAO,iBAAiB,IAAO;AACjC,UAAM+C,IAAW,SAAS,cAAc,MAAM;AAC9C,IAAAA,EAAS,YAAY,+CACrBA,EAAS,cAAc,UAAUoW,EAAQ,SAAS,SAClD9Q,EAAK,YAAYtF,CAAQ;AAAA,EAC3B;AAGA,MAAI/C,EAAO,qBAAqBmZ,EAAQ,iBAAiBA,EAAQ,WAAW;AAC1E,UAAMG,IAAgB,SAAS,cAAc,MAAM;AACnD,IAAAA,EAAc,YAAY,oDAC1BA,EAAc,cAAc,aAAaH,EAAQ,YAAY,IAC7D9Q,EAAK,YAAYiR,CAAa;AAAA,EAChC;AAGA,MAAItZ,EAAO,qBAAqBmZ,EAAQ,eAAe,GAAG;AACxD,UAAMI,IAAgB,SAAS,cAAc,MAAM;AACnD,IAAAA,EAAc,YAAY,oDAC1BA,EAAc,cAAc,aAAaJ,EAAQ,YAAY,IAC7Dd,EAAM,YAAYkB,CAAa;AAAA,EACjC;AAGA,MAAIvZ,EAAO;AACT,eAAWuM,KAASvM,EAAO,cAAc;AACvC,YAAMwZ,IAAUC,GAAkBlN,GAAO4M,CAAO;AAChD,cAAQ5M,EAAM,UAAA;AAAA,QACZ,KAAK;AACH,UAAAlE,EAAK,YAAYmR,CAAO;AACxB;AAAA,QACF,KAAK;AACH,UAAAH,EAAO,YAAYG,CAAO;AAC1B;AAAA,QACF,KAAK;AACH,UAAAnB,EAAM,YAAYmB,CAAO;AACzB;AAAA,MAAA;AAAA,IAEN;AAGF,SAAAJ,EAAW,YAAY/Q,CAAI,GAC3B+Q,EAAW,YAAYC,CAAM,GAC7BD,EAAW,YAAYf,CAAK,GAErBe;AACT;AAQO,SAASM,GAA2BC,GAAyC;AAClF,QAAM7Q,IAAY,SAAS,cAAc,KAAK;AAC9C,SAAAA,EAAU,YAAY,6CAA6C6Q,CAAQ,IAE3E7Q,EAAU,aAAa,QAAQ,cAAc,GACtCA;AACT;AAUO,SAAS8Q,GACd9Q,GACAxI,GACAC,GACA+U,GACM;AACN,EAAAxM,EAAU,YAAY;AAEtB,aAAW+Q,KAAavZ,GAAM;AAC5B,UAAMsS,IAAQ,SAAS,cAAc,KAAK;AAQ1C,QAPAA,EAAM,YAAY,uBAElBA,EAAM,aAAa,QAAQ,cAAc,GACrCiH,EAAU,MACZjH,EAAM,aAAa,uBAAuBiH,EAAU,EAAE,GAGpDA,EAAU,WAAW;AAEvB,YAAMzW,IAAO,SAAS,cAAc,KAAK;AACzC,MAAAA,EAAK,YAAY,kDACjBA,EAAK,MAAM,aAAa,UACxBA,EAAK,cAAcyW,EAAU,SAAS,IACtCjH,EAAM,YAAYxP,CAAI;AAAA,IACxB;AAEE,iBAAWjC,KAAOZ,GAAS;AACzB,cAAM6C,IAAO,SAAS,cAAc,KAAK;AACzC,QAAAA,EAAK,YAAY,wBACjBA,EAAK,aAAa,cAAcjC,EAAI,KAAK;AAEzC,YAAItB,GACAia;AAGJ,cAAMC,IAASF,EAAU,cAAc1Y,EAAI,KAAK;AAChD,YAAI4Y;AAEF,cAAIf,GAAmBe,CAAM,GAAG;AAC9B,kBAAMC,IAAQC,GAAcF,EAAO,OAAO;AAC1C,YAAIC,MACFna,IAAQma,EAAM1E,GAAUnU,EAAI,OAAOA,CAAG,IAExC2Y,IAAYC,EAAO;AAAA,UACrB,OAAO;AACL,kBAAMC,IAAQC,GAAcF,CAAM;AAClC,YAAIC,MACFna,IAAQma,EAAM1E,GAAUnU,EAAI,OAAOA,CAAG;AAAA,UAE1C;AAAA,iBACS0Y,EAAU,SAAS,OAAO,UAAU,eAAe,KAAKA,EAAU,OAAO1Y,EAAI,KAAK,GAAG;AAE9F,gBAAM+Y,IAAYL,EAAU,MAAM1Y,EAAI,KAAK;AAC3C,UAAI,OAAO+Y,KAAc,aACvBra,IAAQqa,EAAU5E,GAAUnU,EAAI,OAAOA,CAAG,IAE1CtB,IAAQqa;AAAA,QAEZ;AAGA,QAAIra,KAAS,OACXuD,EAAK,cAAc0W,IAAYA,EAAUja,GAAOsB,EAAI,OAAOA,CAAG,IAAI,OAAOtB,CAAK,IAE9EuD,EAAK,cAAc,IAErBwP,EAAM,YAAYxP,CAAI;AAAA,MACxB;AAGF,IAAA0F,EAAU,YAAY8J,CAAK;AAAA,EAC7B;AACF;AASA,SAAS6G,GAAkBlN,GAAwB4M,GAAyC;AAC1F,QAAMK,IAAU,SAAS,cAAc,KAAK;AAC5C,EAAAA,EAAQ,YAAY,4CACpBA,EAAQ,KAAK,gBAAgBjN,EAAM,EAAE;AAErC,QAAM3C,IAAU2C,EAAM,OAAO4M,CAAO;AAEpC,SAAI,OAAOvP,KAAY,WACrB4P,EAAQ,YAAY5P,IAEpB4P,EAAQ,YAAY5P,CAAO,GAGtB4P;AACT;AAYO,SAASW,GACd7Z,GACAC,GACAiD,GACA+G,GACA6P,GACmB;AACnB,SAAO;AAAA,IACL,WAAW9Z,EAAK;AAAA,IAChB,cAAc8Z,GAAa,cAAc,UAAU9Z,EAAK;AAAA,IACxD,cAAciK,GAAgB,UAAU,QAAQ;AAAA,IAChD,SAAAhK;AAAA,IACA,MAAAD;AAAA,IACA,MAAAkD;AAAA,EAAA;AAEJ;;AClNO,MAAM6W,WAAyBpY,EAAiC;AAAA,EAC5D,OAAO;AAAA,EACE,UAAU;AAAA,EAE5B,IAAuB,gBAA2C;AAChE,WAAO;AAAA,MACL,UAAU;AAAA,MACV,cAAc;AAAA,MACd,mBAAmB;AAAA,MACnB,mBAAmB;AAAA,IAAA;AAAA,EAEvB;AAAA;AAAA,EAGQ,iBAAqC;AAAA,EACrC,0BAA8C;AAAA,EAC9C,6BAAiD;AAAA,EACjD,gBAAoC;AAAA;AAAA;AAAA,EAInC,SAAe;AACtB,IAAI,KAAK,mBACP,KAAK,eAAe,OAAA,GACpB,KAAK,iBAAiB,OAEpB,KAAK,4BACP,KAAK,wBAAwB,OAAA,GAC7B,KAAK,0BAA0B,OAE7B,KAAK,+BACP,KAAK,2BAA2B,OAAA,GAChC,KAAK,6BAA6B,OAEhC,KAAK,kBACP,KAAK,cAAc,OAAA,GACnB,KAAK,gBAAgB;AAAA,EAEzB;AAAA;AAAA;AAAA,EAIS,cAAoB;AAC3B,UAAMqE,IAAa,KAAK;AACxB,QAAI,CAACA,EAAY;AAIjB,UAAMwC,IACJxC,EAAW,cAAc,kBAAkB,KAC3CA,EAAW,cAAc,mBAAmB,KAC5CA,EAAW,SAAS,CAAC;AACvB,QAAI,CAACwC,EAAW;AAGhB,UAAMyB,IAAiB,KAAK,kBAAA,GACtB6P,IAAc,KAAK,eAAA,GAEnBjB,IAAUgB;AAAA,MACd,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL5P;AAAA,MACA6P;AAAA,IAAA,GAIIE,IAAkB,KAAK,OAAO,mBAAmB,CAAA,GACjDC,IAAUD,EAAgB,OAAO,CAAC9V,MAAMA,EAAE,aAAa,KAAK,GAC5DgW,IAAaF,EAAgB,OAAO,CAAC9V,MAAMA,EAAE,aAAa,KAAK;AAGrE,QAAI+V,EAAQ,SAAS,GAAG;AACtB,UAAI,CAAC,KAAK,yBAAyB;AACjC,aAAK,0BAA0Bb,GAA2B,KAAK;AAC/D,cAAM7Y,IAASyF,EAAW,cAAc,SAAS;AACjD,QAAIzF,KAAUA,EAAO,cACnBiI,EAAU,aAAa,KAAK,yBAAyBjI,EAAO,WAAW,IAEvEiI,EAAU,YAAY,KAAK,uBAAuB;AAAA,MAEtD;AACA,MAAA8Q;AAAA,QACE,KAAK;AAAA,QACLW;AAAA,QACA,KAAK;AAAA,QACL,KAAK;AAAA,MAAA;AAAA,IAET,MAAA,CAAW,KAAK,4BACd,KAAK,wBAAwB,OAAA,GAC7B,KAAK,0BAA0B;AAIjC,UAAME,IACJ,KAAK,OAAO,iBAAiB,MAC5B,KAAK,OAAO,qBAAqBtB,EAAQ,eAAe,KACxD,KAAK,OAAO,qBAAqBA,EAAQ,iBAAiBA,EAAQ,aAClE,KAAK,OAAO,gBAAgB,KAAK,OAAO,aAAa,SAAS,GAC3DuB,IAAmBD,KAAkB,KAAK,OAAO,aAAa,OAC9DE,IAAcH,EAAW,SAAS,KAAKE;AAG7C,QAAID,KAAkB,KAAK,OAAO,aAAa;AAC7C,UAAI,CAAC,KAAK;AACR,aAAK,iBAAiBvB,EAAqB,KAAK,QAAQC,CAAO,GAC/DrQ,EAAU,aAAa,KAAK,gBAAgBA,EAAU,UAAU;AAAA,WAC3D;AACL,cAAM8R,IAAa1B,EAAqB,KAAK,QAAQC,CAAO;AAC5D,aAAK,eAAe,YAAYyB,CAAU,GAC1C,KAAK,iBAAiBA;AAAA,MACxB;AAAA,SACS,KAAK,OAAO,aAAa,SAAS,KAAK,mBAChD,KAAK,eAAe,OAAA,GACpB,KAAK,iBAAiB;AAIxB,IAAID,KACG,KAAK,kBACR,KAAK,gBAAgB,SAAS,cAAc,KAAK,GACjD,KAAK,cAAc,YAAY,cAC/B7R,EAAU,YAAY,KAAK,aAAa,IAG1C,KAAK,cAAc,YAAY,IAE3B0R,EAAW,SAAS,MACjB,KAAK,+BACR,KAAK,6BAA6Bd,GAA2B,QAAQ,IAEvE,KAAK,cAAc,YAAY,KAAK,0BAA0B,GAC9DE;AAAA,MACE,KAAK;AAAA,MACLY;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,IAAA,IAILE,MACF,KAAK,iBAAiBxB,EAAqB,KAAK,QAAQC,CAAO,GAC/D,KAAK,cAAc,YAAY,KAAK,cAAc,MAGpD,KAAK,cAAA;AAAA,EAGT;AAAA;AAAA;AAAA,EAIQ,UAAgB;AACtB,IAAI,KAAK,mBACP,KAAK,eAAe,OAAA,GACpB,KAAK,iBAAiB,OAEpB,KAAK,4BACP,KAAK,wBAAwB,OAAA,GAC7B,KAAK,0BAA0B,OAE7B,KAAK,+BACP,KAAK,2BAA2B,OAAA,GAChC,KAAK,6BAA6B,OAEhC,KAAK,kBACP,KAAK,cAAc,OAAA,GACnB,KAAK,gBAAgB;AAAA,EAEzB;AAAA,EAEQ,gBAAsB;AAC5B,IAAI,KAAK,kBACP,KAAK,cAAc,OAAA,GACnB,KAAK,gBAAgB,OAEnB,KAAK,+BACP,KAAK,2BAA2B,OAAA,GAChC,KAAK,6BAA6B,OAEhC,KAAK,kBAAkB,KAAK,OAAO,aAAa,UAClD,KAAK,eAAe,OAAA,GACpB,KAAK,iBAAiB;AAAA,EAE1B;AAAA,EAEQ,oBAAsD;AAE5D,QAAI;AAEF,aADa,KAAK,MACL,iBAAiB,WAAW,KAAK;AAAA,IAChD,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEQ,iBAA4D;AAClE,QAAI;AAEF,aADa,KAAK,MACL,iBAAiB,WAAW,KAAK;AAAA,IAChD,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,UAAgB;AACd,SAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAgC;AAC9B,UAAM5O,IAAiB,KAAK,kBAAA,GACtB6P,IAAc,KAAK,eAAA;AAEzB,WAAOD;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL5P;AAAA,MACA6P;AAAA,IAAA;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,SAAS7N,GAA8B;AACrC,IAAK,KAAK,OAAO,iBACf,KAAK,OAAO,eAAe,CAAA,IAE7B,KAAK,OAAO,aAAa,KAAKA,CAAK,GACnC,KAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY2D,GAAkB;AAC5B,IAAI,KAAK,OAAO,iBACd,KAAK,OAAO,eAAe,KAAK,OAAO,aAAa,OAAO,CAAC2K,MAAMA,EAAE,OAAO3K,CAAE,GAC7E,KAAK,cAAA;AAAA,EAET;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,kBAAkBnQ,GAAiC;AACjD,IAAK,KAAK,OAAO,oBACf,KAAK,OAAO,kBAAkB,CAAA,IAEhC,KAAK,OAAO,gBAAgB,KAAKA,CAAG,GACpC,KAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,qBAAqBmQ,GAAkB;AACrC,IAAI,KAAK,OAAO,oBACd,KAAK,OAAO,kBAAkB,KAAK,OAAO,gBAAgB,OAAO,CAAC1L,MAAMA,EAAE,OAAO0L,CAAE,GACnF,KAAK,cAAA;AAAA,EAET;AAAA;AAAA;AAAA,EAIkB,SAASX;AAAAA;AAE7B;ACnTO,MAAMuL,KAAqBC;AAE3B,SAASC,GAAoBhb,GAA+B;AACjE,QAAMib,IAAmB,CAAA;AAEzB,SAAI,CAACjb,EAAO,gBAAgB,UAAU,CAACA,EAAO,mBAAmB,UAC/Dib,EAAO,KAAK,oDAAoD,GAG7Djb,EAAO,aAAa,UACvBib,EAAO,KAAK,sCAAsC,GAG7CA;AACT;AAEO,SAASC,GAAeC,GAAwBC,GAA4B;AACjF,SAAO,CAAC,GAAGD,GAAcC,CAAU,EAAE,KAAK,GAAG;AAC/C;ACbO,SAASC,GAAW/a,GAAsBN,GAAkC;AACjF,QAAMsb,IAAiBtb,EAAO,kBAAkB,CAAA,GAC1Cub,IAAoBvb,EAAO,qBAAqB,CAAA,GAChDwb,IAAcxb,EAAO,eAAe,CAAA,GAGpCyb,IAAaC,GAAoBpb,GAAMib,CAAiB,GAGxDI,IAAYC;AAAA,IAChBtb;AAAA,IACAgb;AAAA,IACAC;AAAA,IACAE;AAAA,IACAD;AAAA,IACA;AAAA;AAAA,IACA;AAAA;AAAA,EAAA,GAIIK,IAASC,GAAgBH,GAAWF,GAAYD,CAAW,GAC3DO,IAAa,OAAO,OAAOF,CAAM,EAAE,OAAO,CAAC9a,GAAGC,MAAMD,IAAIC,GAAG,CAAC;AAElE,SAAO;AAAA,IACL,MAAM2a;AAAA,IACN,YAAAF;AAAA,IACA,QAAAI;AAAA,IACA,YAAAE;AAAA,EAAA;AAEJ;AAKO,SAASL,GAAoBpb,GAAsB0b,GAAkC;AAC1F,MAAIA,EAAa,WAAW,EAAG,QAAO,CAAC,OAAO;AAE9C,QAAM5J,wBAAW,IAAA;AACjB,aAAWrS,KAAOO,GAAM;AACtB,UAAMwN,IAAMkO,EAAa,IAAI,CAACrQ,MAAM,OAAO5L,EAAI4L,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,GAAG;AAClE,IAAAyG,EAAK,IAAItE,CAAG;AAAA,EACd;AACA,SAAO,CAAC,GAAGsE,CAAI,EAAE,KAAA;AACnB;AAKO,SAAS6J,GAAa3b,GAAsBR,GAA4C;AAC7F,QAAMwQ,wBAAa,IAAA;AAEnB,aAAWvQ,KAAOO,GAAM;AACtB,UAAMwN,IAAM,OAAO/N,EAAID,CAAK,KAAK,EAAE,GAC7BmX,IAAW3G,EAAO,IAAIxC,CAAG;AAC/B,IAAImJ,IACFA,EAAS,KAAKlX,CAAG,IAEjBuQ,EAAO,IAAIxC,GAAK,CAAC/N,CAAG,CAAC;AAAA,EAEzB;AAEA,SAAOuQ;AACT;AAyBO,SAASsL,GACdtb,GACAgb,GACAU,GACAP,GACAD,GACAU,GACAC,GACY;AACZ,QAAMjZ,IAAqB,CAAA;AAG3B,MAAIoY,EAAe,WAAW,GAAG;AAG/B,UAAMxP,IAASsQ,GAAgB9b,GAAM0b,GAAcP,GAAYD,CAAW,GACpEa,IAAQC,GAAkBxQ,CAAM;AACtC,WAAA5I,EAAO,KAAK;AAAA,MACV,QAAQiZ,KAAa;AAAA,MACrB,UAAUA,KAAa;AAAA,MACvB,OAAAD;AAAA,MACA,QAAApQ;AAAA,MACA,OAAAuQ;AAAA,MACA,SAAS;AAAA,MACT,UAAU/b,EAAK;AAAA,IAAA,CAChB,GACM4C;AAAA,EACT;AAGA,QAAMqZ,IAAejB,EAAe,CAAC,GAC/BkB,IAAkBlB,EAAe,MAAM,CAAC,GACxCmB,IAAcD,EAAgB,SAAS,GAGvC9J,IAAUuJ,GAAa3b,GAAMic,CAAY;AAE/C,aAAW,CAACG,GAAYpJ,CAAS,KAAKZ,GAAS;AAC7C,UAAMiK,IAASR,IAAY,GAAGA,CAAS,IAAIO,CAAU,KAAKA,GAGpD5Q,IAASsQ,GAAgB9I,GAAW0I,GAAcP,GAAYD,CAAW,GACzEa,IAAQC,GAAkBxQ,CAAM;AAGtC,QAAI8Q;AACJ,IAAIH,MACFG,IAAWhB;AAAA,MACTtI;AAAA,MACAkJ;AAAA,MACAR;AAAA,MACAP;AAAA,MACAD;AAAA,MACAU,IAAQ;AAAA,MACRS;AAAA,IAAA,IAIJzZ,EAAO,KAAK;AAAA,MACV,QAAAyZ;AAAA,MACA,UAAUD,KAAc;AAAA,MACxB,OAAAR;AAAA,MACA,QAAApQ;AAAA,MACA,OAAAuQ;AAAA,MACA,SAASI;AAAA,MACT,UAAAG;AAAA,MACA,UAAUtJ,EAAU;AAAA,IAAA,CACrB;AAAA,EACH;AAEA,SAAOpQ;AACT;AAKO,SAASkZ,GACd9b,GACA0b,GACAP,GACAD,GAC+B;AAC/B,QAAM1P,IAAwC,CAAA;AAE9C,aAAW+Q,KAAUpB;AACnB,eAAWqB,KAAMtB,GAAa;AAO5B,YAAMuB,KAJJf,EAAa,SAAS,IAClB1b,EAAK,OAAO,CAACkE,MAAMwX,EAAa,IAAI,CAACrQ,MAAM,OAAOnH,EAAEmH,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,GAAG,MAAMkR,CAAM,IACnFvc,GAEoB,IAAI,CAACkE,MAAM,OAAOA,EAAEsY,EAAG,KAAK,CAAC,KAAK,CAAC,GACvDE,IAAalC,GAAmBgC,EAAG,OAAO,GAC1CG,IAAmBF,EAAK,SAAS,IAAIC,EAAWD,CAAI,IAAI,MAExDG,IAAWhC,GAAe,CAAC2B,CAAM,GAAGC,EAAG,KAAK;AAClD,MAAAhR,EAAOoR,CAAQ,IAAID;AAAA,IACrB;AAGF,SAAOnR;AACT;AAKO,SAASwQ,GAAkBxQ,GAA+C;AAC/E,MAAI1G,IAAM;AACV,aAAW+X,KAAO,OAAO,OAAOrR,CAAM;AACpC,IAAA1G,KAAO+X,KAAO;AAEhB,SAAO/X;AACT;AAmCO,SAAS0W,GACdH,GACAF,GACAD,GACwB;AACxB,QAAMK,IAAiC,CAAA;AAGvC,WAASuB,EAAQ9c,GAAkB;AACjC,eAAWP,KAAOO;AAEhB,UAAI,CAACP,EAAI,WAAW,CAACA,EAAI,UAAU;AACjC,mBAAW8c,KAAUpB;AACnB,qBAAWqB,KAAMtB,GAAa;AAC5B,kBAAM0B,IAAWhC,GAAe,CAAC2B,CAAM,GAAGC,EAAG,KAAK;AAClD,YAAAjB,EAAOqB,CAAQ,KAAKrB,EAAOqB,CAAQ,KAAK,MAAMnd,EAAI,OAAOmd,CAAQ,KAAK;AAAA,UACxE;AAAA,UAEJ,CAAWnd,EAAI,YACbqd,EAAQrd,EAAI,QAAQ;AAAA,EAG1B;AAEA,SAAAqd,EAAQzB,CAAS,GACVE;AACT;AAMO,SAASwB,GAAiB/c,GAAkB2R,GAA4BqL,IAAkB,IAAkB;AACjH,QAAMpa,IAAqB,CAAA;AAE3B,WAASqa,EAAQxd,GAAe;AAC9B,IAAAmD,EAAO,KAAKnD,CAAG;AAGf,UAAMgS,IAAaE,IAAeA,EAAa,IAAIlS,EAAI,MAAM,IAAIud;AAGjE,QAAIvd,EAAI,YAAYgS;AAClB,iBAAWyL,KAASzd,EAAI;AACtB,QAAAwd,EAAQC,CAAK;AAAA,EAGnB;AAEA,aAAWzd,KAAOO;AAChB,IAAAid,EAAQxd,CAAG;AAGb,SAAOmD;AACT;AAKO,SAASua,EAAgBnd,GAA4B;AAC1D,QAAM8R,IAAiB,CAAA;AAEvB,WAASsL,EAAY3d,GAAe;AAIlC,QAHIA,EAAI,WACNqS,EAAK,KAAKrS,EAAI,MAAM,GAElBA,EAAI;AACN,iBAAWyd,KAASzd,EAAI;AACtB,QAAA2d,EAAYF,CAAK;AAAA,EAGvB;AAEA,aAAWzd,KAAOO;AAChB,IAAAod,EAAY3d,CAAG;AAGjB,SAAOqS;AACT;ACxTO,MAAMuL,KAAuB,CAAC,OAAO,OAAO,SAAS,OAAO,OAAO,SAAS,MAAM;AA+BlF,SAASC,GACd9U,GACA9I,GACA6d,GACAC,GACY;AAEZ,QAAMC,IAAa,IAAI,gBAAA,GACjBC,IAAqB,EAAE,QAAAhe,GAAQ,WAAA8d,GAAW,QAAQC,EAAW,OAAA,GAE7DE,IAAU,SAAS,cAAc,KAAK;AAC5C,SAAAA,EAAQ,YAAY,mBAGpBA,EAAQ,YAAYC,EAAc,WAAW,MAAMC,GAAmBN,GAAUG,CAAG,CAAC,CAAC,GAGrFC,EAAQ,YAAYC,EAAc,cAAc,MAAME,GAAgB,aAAaJ,CAAG,CAAC,CAAC,GAGxFC,EAAQ,YAAYC,EAAc,iBAAiB,MAAME,GAAgB,gBAAgBJ,CAAG,CAAC,CAAC,GAG9FC,EAAQ,YAAYC,EAAc,UAAU,MAAMG,GAAiBL,CAAG,CAAC,CAAC,GAGxEC,EAAQ,YAAYC,EAAc,oBAAoB,MAAMI,GAA0BN,CAAG,CAAC,CAAC,GAE3FlV,EAAU,YAAYmV,CAAO,GAGtB,MAAM;AACX,IAAAF,EAAW,MAAA,GACXE,EAAQ,OAAA;AAAA,EACV;AACF;AAKA,SAASC,EAAcK,GAAeC,GAAgD;AACpF,QAAMC,IAAU,SAAS,cAAc,KAAK;AAC5C,EAAAA,EAAQ,YAAY;AAEpB,QAAM5d,IAAS,SAAS,cAAc,KAAK;AAC3C,EAAAA,EAAO,YAAY,4BACnBA,EAAO,cAAc0d;AAErB,QAAM3U,IAAU,SAAS,cAAc,KAAK;AAC5C,SAAAA,EAAQ,YAAY,6BACpBA,EAAQ,YAAY4U,GAAgB,GAEpCC,EAAQ,YAAY5d,CAAM,GAC1B4d,EAAQ,YAAY7U,CAAO,GAEpB6U;AACT;AAKA,SAASL,GAAgBM,GAAwCV,GAAiC;AAChG,QAAM,EAAE,QAAAhe,GAAQ,WAAA8d,GAAW,QAAAa,EAAA,IAAWX,GAChCY,IAAO,SAAS,cAAc,KAAK;AACzC,EAAAA,EAAK,YAAY,uBACjBA,EAAK,aAAa,aAAaF,CAAQ;AAEvC,QAAMG,IAAgBH,MAAa,cAAe1e,EAAO,kBAAkB,CAAA,IAAOA,EAAO,qBAAqB,CAAA;AAE9G,MAAI6e,EAAc,WAAW,GAAG;AAC9B,UAAMC,IAAc,SAAS,cAAc,KAAK;AAChD,IAAAA,EAAY,YAAY,yBACxBA,EAAY,cAAc,oCAC1BF,EAAK,YAAYE,CAAW;AAAA,EAC9B;AACE,eAAWhf,KAAS+e;AAClB,MAAAD,EAAK,YAAYG,GAAgBjf,GAAO4e,GAAUV,CAAG,CAAC;AAK1D,SAAAY,EAAK;AAAA,IACH;AAAA,IACA,CAAC7W,MAAM;AACL,MAAAA,EAAE,eAAA,GACF6W,EAAK,UAAU,IAAI,WAAW;AAAA,IAChC;AAAA,IACA,EAAE,QAAAD,EAAA;AAAA,EAAO,GAGXC,EAAK;AAAA,IACH;AAAA,IACA,MAAM;AACJ,MAAAA,EAAK,UAAU,OAAO,WAAW;AAAA,IACnC;AAAA,IACA,EAAE,QAAAD,EAAA;AAAA,EAAO,GAGXC,EAAK;AAAA,IACH;AAAA,IACA,CAAC7W,MAAM;AACL,MAAAA,EAAE,eAAA,GACF6W,EAAK,UAAU,OAAO,WAAW;AAEjC,YAAM9e,IAAQiI,EAAE,cAAc,QAAQ,YAAY;AAClD,MAAIjI,KACFge,EAAU,iBAAiBhe,GAAO4e,CAAQ;AAAA,IAE9C;AAAA,IACA,EAAE,QAAAC,EAAA;AAAA,EAAO,GAGJC;AACT;AAKA,SAASG,GAAgBjf,GAAe4e,GAAwCV,GAAiC;AAC/G,QAAM,EAAE,WAAAF,GAAW,QAAAa,EAAA,IAAWX,GACxBgB,IAAO,SAAS,cAAc,KAAK;AACzC,EAAAA,EAAK,YAAY,wBACjBA,EAAK,YAAY;AAEjB,QAAMC,IAAYnB,EAAU,qBAAqB,KAAK,CAACnS,MAAMA,EAAE,UAAU7L,CAAK,GACxE4H,IAAQ,SAAS,cAAc,MAAM;AAC3C,EAAAA,EAAM,YAAY,wBAClBA,EAAM,cAAcuX,GAAW,UAAUnf;AAEzC,QAAMof,IAAY,SAAS,cAAc,QAAQ;AACjD,SAAAA,EAAU,YAAY,yBACtBA,EAAU,YAAY,KACtBA,EAAU,QAAQ,gBAClBA,EAAU;AAAA,IACR;AAAA,IACA,CAACnX,MAAM;AACL,MAAAA,EAAE,gBAAA,GACF+V,EAAU,sBAAsBhe,GAAO4e,CAAQ;AAAA,IACjD;AAAA,IACA,EAAE,QAAAC,EAAA;AAAA,EAAO,GAGXK,EAAK,YAAYtX,CAAK,GACtBsX,EAAK,YAAYE,CAAS,GAG1BF,EAAK;AAAA,IACH;AAAA,IACA,CAACjX,MAAM;AACL,MAAAA,EAAE,cAAc,QAAQ,cAAcjI,CAAK,GAC3CiI,EAAE,cAAc,QAAQ,eAAe2W,CAAQ,GAC/CM,EAAK,UAAU,IAAI,UAAU;AAAA,IAC/B;AAAA,IACA,EAAE,QAAAL,EAAA;AAAA,EAAO,GAGXK,EAAK;AAAA,IACH;AAAA,IACA,MAAM;AACJ,MAAAA,EAAK,UAAU,OAAO,UAAU;AAAA,IAClC;AAAA,IACA,EAAE,QAAAL,EAAA;AAAA,EAAO,GAGJK;AACT;AAKA,SAASX,GAAiBL,GAAiC;AACzD,QAAM,EAAE,QAAAhe,GAAQ,WAAA8d,GAAW,QAAAa,EAAA,IAAWX,GAChCY,IAAO,SAAS,cAAc,KAAK;AACzC,EAAAA,EAAK,YAAY,6CACjBA,EAAK,aAAa,aAAa,QAAQ;AAEvC,QAAMO,IAAgBnf,EAAO,eAAe,CAAA;AAE5C,MAAImf,EAAc,WAAW,GAAG;AAC9B,UAAML,IAAc,SAAS,cAAc,KAAK;AAChD,IAAAA,EAAY,YAAY,yBACxBA,EAAY,cAAc,4CAC1BF,EAAK,YAAYE,CAAW;AAAA,EAC9B;AACE,eAAW1D,KAAc+D;AACvB,MAAAP,EAAK,YAAYQ,GAAgBhE,GAAY4C,CAAG,CAAC;AAKrD,SAAAY,EAAK;AAAA,IACH;AAAA,IACA,CAAC7W,MAAM;AACL,MAAAA,EAAE,eAAA,GACF6W,EAAK,UAAU,IAAI,WAAW;AAAA,IAChC;AAAA,IACA,EAAE,QAAAD,EAAA;AAAA,EAAO,GAGXC,EAAK;AAAA,IACH;AAAA,IACA,MAAM;AACJ,MAAAA,EAAK,UAAU,OAAO,WAAW;AAAA,IACnC;AAAA,IACA,EAAE,QAAAD,EAAA;AAAA,EAAO,GAGXC,EAAK;AAAA,IACH;AAAA,IACA,CAAC7W,MAAM;AACL,MAAAA,EAAE,eAAA,GACF6W,EAAK,UAAU,OAAO,WAAW;AACjC,YAAM9e,IAAQiI,EAAE,cAAc,QAAQ,YAAY;AAClD,MAAIjI,KACFge,EAAU,gBAAgBhe,GAAO,KAAK;AAAA,IAE1C;AAAA,IACA,EAAE,QAAA6e,EAAA;AAAA,EAAO,GAGJC;AACT;AAKA,SAASQ,GAAgBhE,GAA6B4C,GAAiC;AACrF,QAAM,EAAE,WAAAF,GAAW,QAAAa,EAAA,IAAWX,GACxBgB,IAAO,SAAS,cAAc,KAAK;AACzC,EAAAA,EAAK,YAAY;AAEjB,QAAMC,IAAYnB,EAAU,mBAAA,EAAqB,KAAK,CAACnS,MAAMA,EAAE,UAAUyP,EAAW,KAAK,GAEnFiE,IAAe,SAAS,cAAc,KAAK;AACjD,EAAAA,EAAa,YAAY;AAEzB,QAAM3X,IAAQ,SAAS,cAAc,MAAM;AAC3C,EAAAA,EAAM,YAAY,wBAClBA,EAAM,cAAcuX,GAAW,UAAU7D,EAAW;AAEpD,QAAMkE,IAAY,SAAS,cAAc,QAAQ;AACjD,EAAAA,EAAU,YAAY,wBACtBA,EAAU,QAAQ;AAElB,aAAWC,KAAW5B,IAAW;AAC/B,UAAM6B,IAAS,SAAS,cAAc,QAAQ;AAC9C,IAAAA,EAAO,QAAQD,GACfC,EAAO,cAAcD,EAAQ,YAAA,GAC7BC,EAAO,WAAWD,MAAYnE,EAAW,SACzCkE,EAAU,YAAYE,CAAM;AAAA,EAC9B;AAEA,EAAAF,EAAU;AAAA,IACR;AAAA,IACA,MAAM;AACJ,MAAAxB,EAAU,qBAAqB1C,EAAW,OAAOkE,EAAU,KAAgB;AAAA,IAC7E;AAAA,IACA,EAAE,QAAAX,EAAA;AAAA,EAAO;AAGX,QAAMO,IAAY,SAAS,cAAc,QAAQ;AACjD,SAAAA,EAAU,YAAY,yBACtBA,EAAU,YAAY,KACtBA,EAAU,QAAQ,sBAClBA,EAAU;AAAA,IACR;AAAA,IACA,CAACnX,MAAM;AACL,MAAAA,EAAE,gBAAA,GACF+V,EAAU,mBAAmB1C,EAAW,KAAK;AAAA,IAC/C;AAAA,IACA,EAAE,QAAAuD,EAAA;AAAA,EAAO,GAGXU,EAAa,YAAY3X,CAAK,GAC9B2X,EAAa,YAAYC,CAAS,GAElCN,EAAK,YAAYK,CAAY,GAC7BL,EAAK,YAAYE,CAAS,GAEnBF;AACT;AAKA,SAASV,GAA0BN,GAAiC;AAClE,QAAM,EAAE,QAAAhe,GAAQ,WAAA8d,GAAW,QAAAa,EAAA,IAAWX,GAChCY,IAAO,SAAS,cAAc,KAAK;AACzC,EAAAA,EAAK,YAAY;AAEjB,QAAMa,IAAY3B,EAAU,mBAAA,GACtB4B,wBAAiB,IAAI;AAAA,IACzB,GAAI1f,EAAO,kBAAkB,CAAA;AAAA,IAC7B,GAAIA,EAAO,qBAAqB,CAAA;AAAA,IAChC,GAAIA,EAAO,aAAa,IAAI,CAAC2N,MAAMA,EAAE,KAAK,KAAK,CAAA;AAAA,EAAC,CACjD,GAGKgS,IAAkBF,EAAU,OAAO,CAAC9T,MAAM,CAAC+T,EAAW,IAAI/T,EAAE,KAAK,CAAC;AAExE,MAAIgU,EAAgB,WAAW,GAAG;AAChC,UAAMC,IAAQ,SAAS,cAAc,KAAK;AAC1C,IAAAA,EAAM,YAAY,yBAClBA,EAAM,cAAc,yBACpBhB,EAAK,YAAYgB,CAAK;AAAA,EACxB;AACE,eAAW9f,KAAS6f,GAAiB;AACnC,YAAMX,IAAO,SAAS,cAAc,KAAK;AACzC,MAAAA,EAAK,YAAY,kCACjBA,EAAK,cAAclf,EAAM,QACzBkf,EAAK,YAAY,IACjBA,EAAK,QAAQ,gBAAgBlf,EAAM,KAAK,eAExCkf,EAAK;AAAA,QACH;AAAA,QACA,CAACjX,MAAM;AACL,UAAAA,EAAE,cAAc,QAAQ,cAAcjI,EAAM,KAAK,GACjDkf,EAAK,UAAU,IAAI,UAAU;AAAA,QAC/B;AAAA,QACA,EAAE,QAAAL,EAAA;AAAA,MAAO,GAGXK,EAAK;AAAA,QACH;AAAA,QACA,MAAM;AACJ,UAAAA,EAAK,UAAU,OAAO,UAAU;AAAA,QAClC;AAAA,QACA,EAAE,QAAAL,EAAA;AAAA,MAAO,GAGXC,EAAK,YAAYI,CAAI;AAAA,IACvB;AAGF,SAAOJ;AACT;AAKA,SAAST,GAAmBN,GAAmBG,GAAiC;AAC9E,QAAM,EAAE,QAAAhe,GAAQ,WAAA8d,GAAW,QAAAa,EAAA,IAAWX,GAChCzR,IAAQ,SAAS,cAAc,KAAK;AAC1C,SAAAA,EAAM,YAAY,qBAGlBA,EAAM;AAAA,IACJsT;AAAA,MACE;AAAA,MACAhC;AAAA,MACA,CAACiC,MAAY;AACX,QAAAhC,EAAU,cAAcgC,CAAO;AAAA,MACjC;AAAA,MACAnB;AAAA,IAAA;AAAA,EACF,GAIFpS,EAAM;AAAA,IACJsT;AAAA,MACE;AAAA,MACA7f,EAAO,cAAc;AAAA,MACrB,CAAC8f,MAAY;AACX,QAAAhC,EAAU,eAAe,cAAcgC,CAAO;AAAA,MAChD;AAAA,MACAnB;AAAA,IAAA;AAAA,EACF,GAIFpS,EAAM;AAAA,IACJsT;AAAA,MACE;AAAA,MACA7f,EAAO,kBAAkB;AAAA,MACzB,CAAC8f,MAAY;AACX,QAAAhC,EAAU,eAAe,kBAAkBgC,CAAO;AAAA,MACpD;AAAA,MACAnB;AAAA,IAAA;AAAA,EACF,GAGKpS;AACT;AAKA,SAASsT,EACPnY,GACAoY,GACAC,GACApB,GACa;AACb,QAAMV,IAAU,SAAS,cAAc,OAAO;AAC9C,EAAAA,EAAQ,YAAY;AAEpB,QAAM+B,IAAQ,SAAS,cAAc,OAAO;AAC5C,EAAAA,EAAM,OAAO,YACbA,EAAM,UAAUF,GAChBE,EAAM,iBAAiB,UAAU,MAAMD,EAASC,EAAM,OAAO,GAAG,EAAE,QAAArB,GAAQ;AAE1E,QAAMsB,IAAO,SAAS,cAAc,MAAM;AAC1C,SAAAA,EAAK,cAAcvY,GAEnBuW,EAAQ,YAAY+B,CAAK,GACzB/B,EAAQ,YAAYgC,CAAI,GAEjBhC;AACT;AChaO,SAASiC,GAAoBngB,GAAmB6S,GAAoBoL,GAAgC;AACzG,SAAApL,EAAM,YAAY,mBAClBA,EAAM,aAAa,oBAAoB,OAAO7S,EAAI,gBAAgB,CAAC,CAAC,GACpE6S,EAAM,aAAa,kBAAkB,OAAO7S,EAAI,iBAAiB,EAAE,CAAC,GACpE6S,EAAM,aAAa,QAAQ,KAAK,GAGhCA,EAAM,YAAY,IAElBoL,EAAI,QAAQ,QAAQ,CAAC7c,GAAKqS,MAAW;AACnC,UAAMpQ,IAAO,SAAS,cAAc,KAAK;AAKzC,QAJAA,EAAK,YAAY,QACjBA,EAAK,aAAa,YAAY,OAAOoQ,CAAM,CAAC,GAC5CpQ,EAAK,aAAa,QAAQ,UAAU,GAEhCoQ,MAAW,GAAG;AAEhB,YAAM2M,IAAS,OAAOpgB,EAAI,aAAa,KAAK;AAC5C,MAAAqD,EAAK,MAAM,cAAc,GAAG+c,CAAM;AAGlC,YAAMxD,IAAS,OAAO5c,EAAI,aAAa,GACjCmT,IAAM,SAAS,cAAc,QAAQ;AAC3C,MAAAA,EAAI,OAAO,UACXA,EAAI,YAAY,gBAChBA,EAAI,aAAa,cAAcnT,EAAI,kBAAkB,mBAAmB,cAAc,GACtFie,EAAI,QAAQ9K,GAAK8K,EAAI,YAAYje,EAAI,kBAAkB,aAAa,QAAQ,CAAC,GAC7EmT,EAAI,iBAAiB,SAAS,CAACnL,MAAM;AACnC,QAAAA,EAAE,gBAAA,GACFiW,EAAI,SAASrB,CAAM;AAAA,MACrB,CAAC,GACDvZ,EAAK,YAAY8P,CAAG;AAGpB,YAAMxL,IAAQ,SAAS,cAAc,MAAM;AAC3C,MAAAA,EAAM,YAAY,eAClBA,EAAM,cAAc,OAAO3H,EAAI,gBAAgB,EAAE,GACjDqD,EAAK,YAAYsE,CAAK;AAGtB,YAAM0L,IAAQ,SAAS,cAAc,MAAM;AAC3C,MAAAA,EAAM,YAAY,eAClBA,EAAM,cAAc,KAAK,OAAOrT,EAAI,eAAe,KAAK,CAAC,KACzDqD,EAAK,YAAYgQ,CAAK;AAAA,IACxB,OAAO;AAEL,YAAMvT,IAAQE,EAAIoB,EAAI,KAAK;AAC3B,MAAAiC,EAAK,cAAcvD,KAAS,OAAO,OAAOA,CAAK,IAAI;AAAA,IACrD;AAEA,IAAA+S,EAAM,YAAYxP,CAAI;AAAA,EACxB,CAAC,GAEM;AACT;AAKO,SAASgd,GAAmBrgB,GAAmB6S,GAAoBrS,GAAkC;AAC1G,SAAAqS,EAAM,YAAY,kBAClBA,EAAM,aAAa,oBAAoB,OAAO7S,EAAI,gBAAgB,CAAC,CAAC,GACpE6S,EAAM,aAAa,kBAAkB,OAAO7S,EAAI,iBAAiB,EAAE,CAAC,GACpE6S,EAAM,YAAY,IAElBrS,EAAQ,QAAQ,CAACY,GAAKqS,MAAW;AAC/B,UAAMpQ,IAAO,SAAS,cAAc,KAAK;AAKzC,QAJAA,EAAK,YAAY,QACjBA,EAAK,aAAa,YAAY,OAAOoQ,CAAM,CAAC,GAC5CpQ,EAAK,aAAa,QAAQ,UAAU,GAEhCoQ,MAAW,GAAG;AAEhB,YAAM2M,IAAS,OAAOpgB,EAAI,aAAa,KAAK;AAE5C,MAAAqD,EAAK,MAAM,cAAc,GAAG+c,IAAS,EAAE;AAEvC,YAAMzY,IAAQ,SAAS,cAAc,MAAM;AAC3C,MAAAA,EAAM,YAAY,eAClBA,EAAM,cAAc,OAAO3H,EAAI,gBAAgB,EAAE,GACjDqD,EAAK,YAAYsE,CAAK;AAAA,IACxB,OAAO;AAEL,YAAM7H,IAAQE,EAAIoB,EAAI,KAAK;AAC3B,MAAAiC,EAAK,cAAcvD,KAAS,OAAO,OAAOA,CAAK,IAAI;AAAA,IACrD;AAEA,IAAA+S,EAAM,YAAYxP,CAAI;AAAA,EACxB,CAAC,GAEM;AACT;AAKO,SAASid,GAAyBtgB,GAAmB6S,GAAoBrS,GAAkC;AAChH,SAAAqS,EAAM,YAAY,yBAElBA,EAAM,aAAa,QAAQ,cAAc,GACzCA,EAAM,YAAY,IAElBrS,EAAQ,QAAQ,CAACY,GAAKqS,MAAW;AAC/B,UAAMpQ,IAAO,SAAS,cAAc,KAAK;AAKzC,QAJAA,EAAK,YAAY,QACjBA,EAAK,aAAa,YAAY,OAAOoQ,CAAM,CAAC,GAGxCA,MAAW,GAAG;AAEhB,YAAM9L,IAAQ,SAAS,cAAc,MAAM;AAC3C,MAAAA,EAAM,YAAY,eAClBA,EAAM,cAAc,eACpBtE,EAAK,YAAYsE,CAAK;AAAA,IACxB,OAAO;AAEL,YAAM7H,IAAQE,EAAIoB,EAAI,KAAK;AAC3B,MAAAiC,EAAK,cAAcvD,KAAS,OAAO,OAAOA,CAAK,IAAI;AAAA,IACrD;AAEA,IAAA+S,EAAM,YAAYxP,CAAI;AAAA,EACxB,CAAC,GAEM;AACT;;AChHO,MAAMkd,UAAoBre,EAA4B;AAAA,EAClD,OAAO;AAAA,EACE,UAAU;AAAA;AAAA,EAG5B,OAAgB,WAAW;AAAA,EAE3B,IAAuB,gBAAsC;AAC3D,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,eAAe;AAAA,MACf,WAAW;AAAA,IAAA;AAAA,EAEf;AAAA;AAAA,EAGQ,WAAW;AAAA,EACX,iBAAiB;AAAA,EACjB,cAAkC;AAAA,EAClC,qCAA0C,IAAA;AAAA,EAC1C,mCAAgC,IAAA;AAAA,EAChC,kBAAkB;AAAA,EAClB,kBAA4D,CAAA;AAAA,EAC5D,iBAAqC;AAAA,EACrC,mBAAuC;AAAA,EACvC,0CAA0B,IAAA;AAAA,EAC1B,oCAAoB,IAAA;AAAA;AAAA;AAAA;AAAA,EAKpB,sBAA+B;AACrC,YAAQ,KAAK,OAAO,aAAa,UAAU,KAAK;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA,EAKA,IAAY,iBAA0C;AAEpD,UAAMuQ,IADS,KAAK,KACA,iBAAiB,WAAW,QAAQ;AAExD,QAAIA,MAAS,MAASA,MAAS,MAAO,QAAO;AAC7C,QAAIA,MAAS,MAAQA,MAAS,MAAM;AAClC,YAAMC,IAAO,KAAK,YAAY;AAC9B,UAAIA,KAAQ,iBAAiBA,CAAI,EAAE,iBAAiB,yBAAyB,EAAE,KAAA,MAAW;AACxF,eAAO;AAAA,IAEX;AACA,WAAO,KAAK,OAAO,aAAa;AAAA,EAClC;AAAA;AAAA;AAAA,EAMS,SAAe;AACtB,SAAK,WAAW,IAChB,KAAK,iBAAiB,IACtB,KAAK,cAAc,MACnB,KAAK,eAAe,MAAA,GACpB,KAAK,kBAAkB,CAAA,GACvB,KAAK,iBAAiB,MACtB,KAAK,wBAAA,GACL,KAAK,oBAAoB,MAAA,GACzB,KAAK,cAAc,MAAA;AAAA,EACrB;AAAA;AAAA;AAAA,EAMS,eAAgD;AAIvD,SADsB,KAAK,QAAQ,iBAAiB,KAAK,YAAY,iBAAiB,QAChE;AAItB,aAAO;AAAA,QACL,IAAI6N,EAAY;AAAA,QAChB,OAAO;AAAA,QACP,MAAM;AAAA,QACN,SAAS;AAAA,QACT,OAAO;AAAA,QACP,QAAQ,CAACxX,MAAc,KAAK,YAAYA,CAAS;AAAA,MAAA;AAAA,EAErD;AAAA;AAAA;AAAA,EAMS,YAAYxI,GAA0C;AAO7D,QALI,CAAC,KAAK,kBAAkB,KAAK,OAAO,WAAW,MAAS,KAAK,0BAC/D,KAAK,iBAAiB,IACtB,KAAK,WAAW,KAGd,CAAC,KAAK;AACR,aAAO,CAAC,GAAGA,CAAI;AAGjB,UAAM2a,IAASD,GAAoB,KAAK,MAAM;AAC9C,QAAIC,EAAO,SAAS;AAClB,kBAAK,KAAK,kBAAkBA,EAAO,KAAK,IAAI,CAAC,EAAE,GACxC,CAAC,GAAG3a,CAAI;AAOjB,QAJA,KAAK,oBAAA,GACL,KAAK,kBAAkB,KAAK,OAAO,mBAAmB,IAGlD,KAAK,aAAa,SAAS,KAAK,KAAK,mBAAmB,KAAK,aAAa;AAC5E,YAAMigB,IAAU9C,EAAgB,KAAK,YAAY,IAAI;AACrD,iBAAW3P,KAAOyS;AAChB,aAAK,aAAa,IAAIzS,CAAG;AAAA,IAE7B;AAMA,QAHA,KAAK,cAAcuN,GAAW/a,GAAwB,KAAK,MAAM,GAG7D,KAAK,aAAa,SAAS,KAAK,KAAK,iBAAiB;AACxD,YAAMigB,IAAU9C,EAAgB,KAAK,YAAY,IAAI;AACrD,iBAAW3P,KAAOyS;AAChB,aAAK,aAAa,IAAIzS,CAAG;AAAA,IAE7B;AAGA,UAAM0S,IAAc,KAAK,OAAO,eAAe,IACzCC,IAA2BpD;AAAA,MAC/B,KAAK,YAAY;AAAA,MACjB,KAAK;AAAA,MACL,KAAK;AAAA,IAAA,EACL,IAAI,CAACqD,OAAQ;AAAA,MACb,eAAeA,EAAG;AAAA,MAClB,cAAcA,EAAG;AAAA,MACjB,cAAcA,EAAG;AAAA,MACjB,gBAAgBA,EAAG;AAAA,MACnB,oBAAoB,EAAQA,EAAG,UAAU;AAAA,MACzC,iBAAiB,KAAK,aAAa,IAAIA,EAAG,MAAM;AAAA,MAChD,iBAAiBA,EAAG,YAAY;AAAA,MAChC,eAAeA,EAAG,QAAQF;AAAA,MAC1B,cAAcE,EAAG;AAAA,MACjB,GAAGA,EAAG;AAAA,IAAA,EACN;AAGF,SAAK,cAAc,MAAA;AACnB,UAAM/N,wBAAyB,IAAA;AAC/B,eAAW5S,KAAO0gB,GAAU;AAC1B,YAAM3S,IAAM/N,EAAI;AAChB,MAAA4S,EAAmB,IAAI7E,CAAG,GAEtB,CAAC,KAAK,oBAAoB,IAAIA,CAAG,KAAK/N,EAAI,eAAe,KAC3D,KAAK,cAAc,IAAI+N,CAAG;AAAA,IAE9B;AACA,gBAAK,sBAAsB6E,GAKpB8N;AAAA,EACT;AAAA,EAES,eAAelgB,GAAkD;AACxE,QAAI,CAAC,KAAK,YAAY,CAAC,KAAK;AAC1B,aAAO,CAAC,GAAGA,CAAO;AAGpB,UAAMogB,IAA+B,CAAA,GAG/BC,KAAmB,KAAK,OAAO,kBAAkB,CAAA,GAAI,IAAI,CAACjV,MAAM,KAAK,eAAe,IAAIA,CAAC,KAAKA,CAAC,EAAE,KAAK,KAAK;AACjH,IAAAgV,EAAa,KAAK;AAAA,MAChB,OAAO;AAAA,MACP,QAAQC,KAAmB;AAAA,MAC3B,OAAO;AAAA,IAAA,CACR;AAGD,eAAW/D,KAAU,KAAK,YAAY;AACpC,iBAAWC,KAAM,KAAK,OAAO,eAAe,CAAA,GAAI;AAC9C,cAAMI,IAAWhC,GAAe,CAAC2B,CAAM,GAAGC,EAAG,KAAK,GAC5C+D,IAAc/D,EAAG,UAAU,KAAK,eAAe,IAAIA,EAAG,KAAK,KAAKA,EAAG;AACzE,QAAA6D,EAAa,KAAK;AAAA,UAChB,OAAOzD;AAAA,UACP,QAAQ,GAAGL,CAAM,MAAMgE,CAAW,KAAK/D,EAAG,OAAO;AAAA,UACjD,OAAO;AAAA,UACP,MAAM;AAAA,QAAA,CACP;AAAA,MACH;AAIF,WAAI,KAAK,OAAO,cACd6D,EAAa,KAAK;AAAA,MAChB,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,MAAM;AAAA,IAAA,CACP,GAGIA;AAAA,EACT;AAAA,EAES,UAAU5gB,GAA8B6S,GAA6B;AAC5E,UAAMkO,IAAW/gB;AAGjB,WAAI+gB,EAAS,iBAAiBA,EAAS,qBAC9BZ,GAAoBY,GAAUlO,GAAO;AAAA,MAC1C,SAAS,KAAK;AAAA,MACd,UAAU,CAAC9E,MAAQ,KAAK,OAAOA,CAAG;AAAA,MAClC,aAAa,CAACiT,MAAY,KAAK,YAAYA,CAAO;AAAA,MAClD,SAAS,CAAC3I,GAAI3Q,MAAS,KAAK,QAAQ2Q,GAAI3Q,CAAI;AAAA,IAAA,CAC7C,IAICqZ,EAAS,kBAAkB,UAAa,KAAK,WACxCV,GAAmBU,GAAUlO,GAAO,KAAK,WAAW,KAI7D,KAAK,oBAAoBA,CAAK,GAEvB;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,oBAAoBA,GAA0B;AAOpD,KAJEA,EAAM,UAAU,SAAS,iBAAiB,KAC1CA,EAAM,UAAU,SAAS,gBAAgB,KACzCA,EAAM,UAAU,SAAS,uBAAuB,OAIhDA,EAAM,UAAU,OAAO,mBAAmB,kBAAkB,uBAAuB,GACnFA,EAAM,UAAU,IAAI,eAAe,GAGnCA,EAAM,gBAAgB,kBAAkB,GAGxCA,EAAM,YAAY;AAAA,EAEtB;AAAA,EAES,cAAoB;AAE3B,IAAI,KAAK,YAAY,KAAK,OAAO,kBAAkB,KAAK,cACtD,KAAK,uBAAA,IAEL,KAAK,wBAAA;AAIP,UAAMxG,IAAQ,KAAK;AACnB,QAAIA,MAAU,MAAS,KAAK,cAAc,SAAS,EAAG;AAEtD,UAAM4G,IAAO,KAAK,YAAY,cAAc,OAAO;AACnD,QAAI,CAACA,EAAM;AAEX,UAAMC,IAAY7G,MAAU,SAAS,sBAAsB;AAC3D,eAAWwG,KAASI,EAAK,iBAAiB,mCAAmC,GAAG;AAC9E,YAAMlF,IAAO8E,EAAsB,QAAQ;AAC3C,MAAI9E,KAAO,KAAK,cAAc,IAAIA,CAAG,MACnC8E,EAAM,UAAU,IAAIK,CAAS,GAC7BL,EAAM,iBAAiB,gBAAgB,MAAMA,EAAM,UAAU,OAAOK,CAAS,GAAG,EAAE,MAAM,GAAA,CAAM;AAAA,IAElG;AACA,SAAK,cAAc,MAAA;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKQ,yBAA+B;AACrC,QAAI,CAAC,KAAK,YAAa;AAEvB,UAAM3M,IAAa,KAAK;AACxB,QAAI,CAACA,EAAY;AAGjB,UAAMwC,IACJxC,EAAW,cAAc,kBAAkB,KAC3CA,EAAW,cAAc,mBAAmB,KAC5CA,EAAW,SAAS,CAAC;AACvB,QAAI,CAACwC,EAAW;AAGhB,IAAK,KAAK,qBACR,KAAK,mBAAmB,SAAS,cAAc,KAAK,GACpD,KAAK,iBAAiB,YAAY,4BAClCA,EAAU,YAAY,KAAK,gBAAgB;AAI7C,UAAMkY,IAA8B;AAAA,MAClC,eAAe;AAAA,MACf,cAAc;AAAA,MACd,qBAAqB;AAAA,MACrB,cAAc,KAAK,YAAY;AAAA,MAC/B,GAAG,KAAK,YAAY;AAAA,IAAA;AAItB,IAAAX,GAAyBW,GAAe,KAAK,kBAAkB,KAAK,WAAW;AAAA,EACjF;AAAA;AAAA;AAAA;AAAA,EAKQ,0BAAgC;AACtC,IAAI,KAAK,qBACP,KAAK,iBAAiB,OAAA,GACtB,KAAK,mBAAmB;AAAA,EAE5B;AAAA;AAAA;AAAA,EAMA,OAAOlT,GAAmB;AACxB,IAAI,KAAK,aAAa,IAAIA,CAAG,IAC3B,KAAK,aAAa,OAAOA,CAAG,IAE5B,KAAK,aAAa,IAAIA,CAAG,GAE3B,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,OAAOA,GAAmB;AACxB,SAAK,aAAa,IAAIA,CAAG,GACzB,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,SAASA,GAAmB;AAC1B,SAAK,aAAa,OAAOA,CAAG,GAC5B,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,YAAkB;AAChB,QAAI,KAAK,aAAa;AACpB,YAAMyS,IAAU9C,EAAgB,KAAK,YAAY,IAAI;AACrD,iBAAW3P,KAAOyS;AAChB,aAAK,aAAa,IAAIzS,CAAG;AAE3B,WAAK,cAAA;AAAA,IACP;AAAA,EACF;AAAA,EAEA,cAAoB;AAClB,SAAK,aAAa,MAAA,GAClB,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,WAAWA,GAAsB;AAC/B,WAAO,KAAK,aAAa,IAAIA,CAAG;AAAA,EAClC;AAAA;AAAA;AAAA,EAMA,cAAoB;AAClB,IAAI,KAAK,gBAAgB,WAAW,KAClC,KAAK,uBAAA,GAEP,KAAK,WAAW,IAChB,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,eAAqB;AACnB,SAAK,WAAW,IAChB,KAAK,cAAc,MACnB,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,gBAAyB;AACvB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,iBAAqC;AACnC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,kBAAkBmT,GAAwB;AACxC,SAAK,OAAO,iBAAiBA,GAC7B,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,qBAAqBA,GAAwB;AAC3C,SAAK,OAAO,oBAAoBA,GAChC,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,eAAeA,GAAiC;AAC9C,SAAK,OAAO,cAAcA,GAC1B,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,UAAgB;AACd,SAAK,cAAc,MACnB,KAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA,EAMA,YAAkB;AAEhB,IADa,KAAK,KACb,cAAcX,EAAY,QAAQ;AAAA,EACzC;AAAA,EAEA,YAAkB;AAEhB,IADa,KAAK,KACb,eAAA;AAAA,EACP;AAAA,EAEA,cAAoB;AAElB,IADa,KAAK,KACb,gBAAgBA,EAAY,QAAQ;AAAA,EAC3C;AAAA,EAEA,iBAA0B;AAExB,WADa,KAAK,KACN,oBAAoBA,EAAY;AAAA,EAC9C;AAAA;AAAA;AAAA,EAMA,IAAY,cAA8B;AAExC,WADa,KAAK,KACN,WAAW,CAAA;AAAA,EACzB;AAAA,EAEQ,sBAA4B;AAClC,UAAMX,IAAkB,KAAK,mBAAA;AAC7B,SAAK,eAAe,MAAA;AACpB,eAAW7f,KAAS6f;AAClB,WAAK,eAAe,IAAI7f,EAAM,OAAOA,EAAM,MAAM;AAAA,EAErD;AAAA,EAEQ,qBAAkC;AACxC,WAAI,KAAK,gBAAgB,SAAS,IACzB,KAAK,kBAEP,KAAK,uBAAA;AAAA,EACd;AAAA,EAEQ,yBAAsC;AAC5C,UAAM0D,IAAO,KAAK;AAClB,QAAI;AACF,YAAMjD,IAAUiD,EAAK,gBAAA,KAAqBA,EAAK,WAAW,CAAA;AAC1D,kBAAK,kBAAkBjD,EACpB,OAAO,CAACY,MAA2B,CAACA,EAAI,MAAM,WAAW,SAAS,CAAC,EACnE,IAAI,CAACA,OAA6C;AAAA,QACjD,OAAOA,EAAI;AAAA,QACX,QAAQA,EAAI,UAAUA,EAAI;AAAA,MAAA,EAC1B,GACG,KAAK;AAAA,IACd,QAAQ;AACN,aAAO,CAAA;AAAA,IACT;AAAA,EACF;AAAA,EAEQ,YAAY2H,GAA6C;AAC/D,SAAK,iBAAiBA,GAElB,KAAK,gBAAgB,WAAW,KAClC,KAAK,uBAAA;AAGP,UAAMgV,IAA4B;AAAA,MAChC,eAAe,CAACoD,MAAY;AAC1B,QAAIA,IACF,KAAK,YAAA,IAEL,KAAK,aAAA,GAEP,KAAK,aAAA;AAAA,MACP;AAAA,MACA,kBAAkB,CAACphB,GAAO8e,MAAS,KAAK,eAAe9e,GAAO8e,CAAI;AAAA,MAClE,uBAAuB,CAAC9e,GAAO8e,MAAS,KAAK,oBAAoB9e,GAAO8e,CAAI;AAAA,MAC5E,iBAAiB,CAAC9e,GAAOyf,MAAY,KAAK,cAAczf,GAAOyf,CAAO;AAAA,MACtE,oBAAoB,CAACzf,MAAU,KAAK,iBAAiBA,CAAK;AAAA,MAC1D,sBAAsB,CAACA,GAAOyf,MAAY,KAAK,mBAAmBzf,GAAOyf,CAAO;AAAA,MAChF,gBAAgB,CAACC,GAAQ3f,MAAU;AACjC,aAAK,OAAO2f,CAAM,IAAI3f,GAClB,KAAK,YAAU,KAAK,QAAA;AAAA,MAC1B;AAAA,MACA,oBAAoB,MAAM,KAAK,mBAAA;AAAA,IAAmB;AAGpD,WAAO+d,GAAiB9U,GAAW,KAAK,QAAQ,KAAK,UAAUgV,CAAS;AAAA,EAC1E;AAAA,EAEQ,eAAqB;AAC3B,IAAK,KAAK,mBACV,KAAK,eAAe,YAAY,IAChC,KAAK,YAAY,KAAK,cAAc;AAAA,EACtC;AAAA,EAEQ,eAAehe,GAAe4e,GAA8C;AAClF,QAAIA,MAAa,aAAa;AAC5B,YAAM5H,IAAU,KAAK,OAAO,kBAAkB,CAAA;AAC9C,MAAKA,EAAQ,SAAShX,CAAK,MACzB,KAAK,OAAO,iBAAiB,CAAC,GAAGgX,GAAShX,CAAK;AAAA,IAEnD,OAAO;AACL,YAAMgX,IAAU,KAAK,OAAO,qBAAqB,CAAA;AACjD,MAAKA,EAAQ,SAAShX,CAAK,MACzB,KAAK,OAAO,oBAAoB,CAAC,GAAGgX,GAAShX,CAAK;AAAA,IAEtD;AAEA,SAAK,qBAAqBA,GAAO4e,CAAQ,GACrC,KAAK,YAAU,KAAK,QAAA,GACxB,KAAK,aAAA;AAAA,EACP;AAAA,EAEQ,oBAAoB5e,GAAe4e,GAA8C;AACvF,IAAIA,MAAa,cACf,KAAK,OAAO,kBAAkB,KAAK,OAAO,kBAAkB,CAAA,GAAI,OAAO,CAAC/S,MAAMA,MAAM7L,CAAK,IAEzF,KAAK,OAAO,qBAAqB,KAAK,OAAO,qBAAqB,CAAA,GAAI,OAAO,CAAC6L,MAAMA,MAAM7L,CAAK,GAG7F,KAAK,YAAU,KAAK,QAAA,GACxB,KAAK,aAAA;AAAA,EACP;AAAA,EAEQ,qBAAqBA,GAAeqhB,GAA2D;AACrG,IAAIA,MAAe,gBACjB,KAAK,OAAO,kBAAkB,KAAK,OAAO,kBAAkB,CAAA,GAAI,OAAO,CAACxV,MAAMA,MAAM7L,CAAK,IAEvFqhB,MAAe,mBACjB,KAAK,OAAO,qBAAqB,KAAK,OAAO,qBAAqB,CAAA,GAAI,OAAO,CAACxV,MAAMA,MAAM7L,CAAK,IAE7FqhB,MAAe,aACjB,KAAK,OAAO,eAAe,KAAK,OAAO,eAAe,CAAA,GAAI,OAAO,CAACxT,MAAMA,EAAE,UAAU7N,CAAK;AAAA,EAE7F;AAAA,EAEQ,cAAcA,GAAeyf,GAAwB;AAC3D,UAAMzI,IAAU,KAAK,OAAO,eAAe,CAAA;AAC3C,IAAKA,EAAQ,KAAK,CAACnJ,MAAMA,EAAE,UAAU7N,CAAK,MACxC,KAAK,OAAO,cAAc,CAAC,GAAGgX,GAAS,EAAE,OAAAhX,GAAO,SAAAyf,GAAS,IAG3D,KAAK,qBAAqBzf,GAAO,QAAQ,GACrC,KAAK,YAAU,KAAK,QAAA,GACxB,KAAK,aAAA;AAAA,EACP;AAAA,EAEQ,iBAAiBA,GAAqB;AAC5C,SAAK,OAAO,eAAe,KAAK,OAAO,eAAe,CAAA,GAAI,OAAO,CAAC6N,MAAMA,EAAE,UAAU7N,CAAK,GACrF,KAAK,YAAU,KAAK,QAAA,GACxB,KAAK,aAAA;AAAA,EACP;AAAA,EAEQ,mBAAmBA,GAAeyf,GAAwB;AAChE,UAAM/D,IAAc,KAAK,OAAO,eAAe,CAAA,GACzC4F,IAAa5F,EAAY,UAAU,CAAC7N,MAAMA,EAAE,UAAU7N,CAAK;AACjE,IAAIshB,KAAc,MAChB5F,EAAY4F,CAAU,IAAI,EAAE,GAAG5F,EAAY4F,CAAU,GAAG,SAAA7B,EAAA,GACxD,KAAK,OAAO,cAAc,CAAC,GAAG/D,CAAW,IAEvC,KAAK,YAAU,KAAK,QAAA;AAAA,EAC1B;AAAA;AAAA;AAAA,EAMkB,SAASjM;AAAAA;AAG7B;AClnBO,SAAS8R,GAA8Bxd,GAAqC;AAEjF,QAAMyd,IAAOzd,EAAO,QAAQ,CAAA;AAC5B,SAAOyd,EAAK,iBAAiB,MAAQA,EAAK,oBAAoB;AAChE;AAUO,SAASC,GAAWhhB,GAAmBihB,GAAmBC,GAA2B;AAG1F,MAFID,MAAcC,KACdD,IAAY,KAAKA,KAAajhB,EAAQ,UACtCkhB,IAAU,KAAKA,IAAUlhB,EAAQ,OAAQ,QAAOA;AAEpD,QAAM2C,IAAS,CAAC,GAAG3C,CAAO,GACpB,CAACmhB,CAAO,IAAIxe,EAAO,OAAOse,GAAW,CAAC;AAC5C,SAAAte,EAAO,OAAOue,GAAS,GAAGC,CAAO,GAC1Bxe;AACT;;ACNO,MAAMye,WAAsB1f,EAA8B;AAAA,EACtD,OAAO;AAAA,EACE,UAAU;AAAA,EAE5B,IAAuB,gBAAwC;AAC7D,WAAO;AAAA,MACL,WAAW;AAAA;AAAA,IAAA;AAAA,EAEf;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAY,gBAAyC;AAEnD,WAAK,KAAK,qBAGN,KAAK,OAAO,cAAc,SAAkB,KAAK,OAAO,YAGxD,KAAK,OAAO,mBAAmB,KAAc,MAC7C,KAAK,OAAO,mBAAmB,IAAa,UAPX;AAAA,EAUvC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAY,qBAA8B;AAExC,UAAMuQ,IADS,KAAK,KACA,iBAAiB,WAAW,QAAQ;AAGxD,QAAIA,MAAS,MAASA,MAAS,MAAO,QAAO;AAG7C,QAAIA,MAAS,MAAQA,MAAS,KAAM,QAAO;AAG3C,UAAMC,IAAO,KAAK,YAAY;AAC9B,WAAIA,IACc,iBAAiBA,CAAI,EAAE,iBAAiB,yBAAyB,EAAE,KAAA,MAChE,MAGd;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,IAAY,oBAA4B;AAEtC,QAAI,KAAK,OAAO,sBAAsB;AACpC,aAAO,KAAK,OAAO;AAIrB,UAAMA,IAAO,KAAK,YAAY;AAC9B,QAAIA,GAAM;AACR,YAAMiC,IAAc,iBAAiBjC,CAAI,EAAE,iBAAiB,0BAA0B,EAAE,KAAA,GAClFlP,IAAS,SAASmR,GAAa,EAAE;AACvC,UAAI,CAAC,MAAMnR,CAAM,EAAG,QAAOA;AAAA,IAC7B;AAEA,WAAO;AAAA,EACT;AAAA;AAAA,EAGQ,aAAa;AAAA,EACb,eAA8B;AAAA,EAC9B,eAA8B;AAAA,EAC9B,YAA2B;AAAA;AAAA;AAAA,EAK1B,OAAOC,GAAiE;AAC/E,UAAM,OAAOA,CAAI,GAIhBA,EAAgC;AAAA,MAC/B;AAAA,MACA,CAACuE,MAAa;AACZ,cAAM6Z,IAAU7Z,EAAkB;AAClC,QAAI6Z,GAAQ,SAAS,OAAOA,EAAO,WAAY,YAC7C,KAAK,WAAWA,EAAO,OAAOA,EAAO,OAAO;AAAA,MAEhD;AAAA,MACA,EAAE,QAAQ,KAAK,iBAAA;AAAA,IAAiB;AAAA,EAEpC;AAAA,EAES,SAAe;AACtB,SAAK,aAAa,IAClB,KAAK,eAAe,MACpB,KAAK,eAAe,MACpB,KAAK,YAAY;AAAA,EACnB;AAAA;AAAA;AAAA,EAKS,cAAoB;AAC3B,UAAMtb,IAAa,KAAK;AACxB,QAAI,CAACA,EAAY;AAIjB,IAFgBA,EAAW,iBAAiB,qBAAqB,EAEzD,QAAQ,CAACzF,MAAW;AAC1B,YAAMghB,IAAWhhB,GACXf,IAAQ+hB,EAAS,aAAa,YAAY;AAChD,UAAI,CAAC/hB,EAAO;AAEZ,YAAM+D,IAAS,KAAK,QAAQ,KAAK,CAAC,MAAM,EAAE,UAAU/D,CAAK,GAOnDgiB,IAAe,CALN,KAAK,KACW,aAAsB;AAAA,QACnD,MAAMrJ,EAAe;AAAA,QACrB,SAAS5U;AAAA,MAAA,CACV,EACqC,SAAS,EAAK;AACpD,UAAI,CAACA,KAAU,CAACwd,GAAcxd,CAAM,KAAK,CAACie,GAAc;AACtD,QAAAD,EAAS,YAAY;AACrB;AAAA,MACF;AAKA,MAHAA,EAAS,YAAY,IAGjB,CAAAA,EAAS,aAAa,sBAAsB,MAChDA,EAAS,aAAa,wBAAwB,MAAM,GAEpDA,EAAS,iBAAiB,aAAa,CAAC9Z,MAAiB;AAEvD,cAAMga,IADe,KAAK,eAAA,EACM,QAAQjiB,CAAK;AAC7C,aAAK,aAAa,IAClB,KAAK,eAAeA,GACpB,KAAK,eAAeiiB,GAEhBha,EAAE,iBACJA,EAAE,aAAa,gBAAgB,QAC/BA,EAAE,aAAa,QAAQ,cAAcjI,CAAK,IAG5C+hB,EAAS,UAAU,IAAI,UAAU;AAAA,MACnC,CAAC,GAEDA,EAAS,iBAAiB,WAAW,MAAM;AACzC,aAAK,aAAa,IAClB,KAAK,eAAe,MACpB,KAAK,eAAe,MACpB,KAAK,YAAY,MAEjBvb,EAAW,iBAAiB,qBAAqB,EAAE,QAAQ,CAAC0b,MAAM;AAChE,UAAAA,EAAE,UAAU,OAAO,YAAY,eAAe,eAAe,YAAY;AAAA,QAC3E,CAAC;AAAA,MACH,CAAC,GAEDH,EAAS,iBAAiB,YAAY,CAAC9Z,MAAiB;AAEtD,YADAA,EAAE,eAAA,GACE,CAAC,KAAK,cAAc,KAAK,iBAAiBjI,EAAO;AAErD,cAAMiN,IAAO8U,EAAS,sBAAA,GAChBI,IAAOlV,EAAK,OAAOA,EAAK,QAAQ,GAGhCgV,IADe,KAAK,eAAA,EACM,QAAQjiB,CAAK;AAC7C,aAAK,YAAYiI,EAAE,UAAUka,IAAOF,IAAaA,IAAa,GAE9DF,EAAS,UAAU,IAAI,aAAa,GACpCA,EAAS,UAAU,OAAO,eAAe9Z,EAAE,UAAUka,CAAI,GACzDJ,EAAS,UAAU,OAAO,cAAc9Z,EAAE,WAAWka,CAAI;AAAA,MAC3D,CAAC,GAEDJ,EAAS,iBAAiB,aAAa,MAAM;AAC3C,QAAAA,EAAS,UAAU,OAAO,eAAe,eAAe,YAAY;AAAA,MACtE,CAAC,GAEDA,EAAS,iBAAiB,QAAQ,CAAC9Z,MAAiB;AAClD,QAAAA,EAAE,eAAA;AACF,cAAMma,IAAe,KAAK,cACpBC,IAAe,KAAK,cACpBC,IAAY,KAAK;AAEvB,YAAI,CAAC,KAAK,cAAcF,MAAiB,QAAQC,MAAiB,QAAQC,MAAc;AACtF;AAGF,cAAMC,IAAmBD,IAAYD,IAAeC,IAAY,IAAIA,GAC9DE,IAAe,KAAK,eAAA,GACpBC,IAAWhB,GAAWe,GAAcH,GAAcE,CAAgB,GAElET,IAA2B;AAAA,UAC/B,OAAOM;AAAA,UACP,WAAWC;AAAA,UACX,SAASE;AAAA,UACT,aAAaE;AAAA,QAAA;AAIf,aAAK,kBAAkBA,CAAQ,GAE/B,KAAK,KAAK,eAAeX,CAAM;AAAA,MACjC,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKS,UAAU1f,GAAsC;AACvD,QAAI,CAACA,EAAM,UAAWA,EAAM,QAAQ,eAAeA,EAAM,QAAQ;AAC/D;AAGF,UAAMsB,IAAO,KAAK,MACZgf,IAAWhf,EAAK,WAChBjD,IAAUiD,EAAK;AAErB,QAAIgf,IAAW,KAAKA,KAAYjiB,EAAQ,OAAQ;AAEhD,UAAMsD,IAAStD,EAAQiiB,CAAQ;AAC/B,QAAI,CAAC3e,KAAU,CAACwd,GAAcxd,CAAM,EAAG;AAGvC,UAAM+C,IAAS,KAAK;AAKpB,QAJwBA,EAAO,aAAsB;AAAA,MACnD,MAAM6R,EAAe;AAAA,MACrB,SAAS5U;AAAA,IAAA,CACV,EACmB,SAAS,EAAK,EAAG;AAErC,UAAMye,IAAe,KAAK,eAAA,GACpBd,IAAYc,EAAa,QAAQze,EAAO,KAAK;AACnD,QAAI2d,MAAc,GAAI;AAEtB,UAAMC,IAAUvf,EAAM,QAAQ,cAAcsf,IAAY,IAAIA,IAAY;AAGxE,QAAIC,IAAU,KAAKA,KAAWa,EAAa,OAAQ;AAGnD,UAAMG,IAAeliB,EAAQ,KAAK,CAACG,MAAMA,EAAE,UAAU4hB,EAAab,CAAO,CAAC;AAC1E,QAAI,EAAAgB,KACsB7b,EAAO,aAAsB;AAAA,MACnD,MAAM6R,EAAe;AAAA,MACrB,SAASgK;AAAA,IAAA,CACV,EACmB,SAAS,EAAK;AAGpC,kBAAK,WAAW5e,EAAO,OAAO4d,CAAO,GAGrCje,EAAK,YAAYie,GACjBiB,GAAkB,KAAK,IAAW,GAElCxgB,EAAM,eAAA,GACNA,EAAM,gBAAA,GACC;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,iBAA2B;AACzB,WAAQ,KAAK,KAAwC,eAAA;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAAWpC,GAAe2hB,GAAuB;AAC/C,UAAMa,IAAe,KAAK,eAAA,GACpBd,IAAYc,EAAa,QAAQxiB,CAAK;AAC5C,QAAI0hB,MAAc,GAAI;AAEtB,UAAMe,IAAWhB,GAAWe,GAAcd,GAAWC,CAAO;AAG5D,SAAK,kBAAkBc,CAAQ,GAE/B,KAAK,KAAuB,eAAe;AAAA,MACzC,OAAAziB;AAAA,MACA,WAAA0hB;AAAA,MACA,SAAAC;AAAA,MACA,aAAac;AAAA,IAAA,CACd;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,eAAeI,GAAuB;AACpC,SAAK,kBAAkBA,CAAK;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAyB;AACvB,UAAMC,IAAgB,KAAK,QAAQ,IAAI,CAACliB,MAAMA,EAAE,KAAK;AACrD,SAAK,kBAAkBkiB,CAAa;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,yBAA8C;AACpD,UAAMC,wBAAgB,IAAA;AACtB,gBAAK,YAAY,iBAAiB,iCAAiC,EAAE,QAAQ,CAACzf,MAAS;AACrF,YAAMtD,IAAQsD,EAAK,aAAa,YAAY;AAC5C,MAAItD,KAAO+iB,EAAU,IAAI/iB,GAAOsD,EAAK,sBAAA,EAAwB,IAAI;AAAA,IACnE,CAAC,GACMyf;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,YAAYC,GAAyC;AAC3D,UAAMxc,IAAa,KAAK;AACxB,QAAI,CAACA,KAAcwc,EAAa,SAAS,EAAG;AAG5C,UAAMC,wBAAa,IAAA;AAUnB,QATAzc,EAAW,iBAAiB,iCAAiC,EAAE,QAAQ,CAAClD,MAAS;AAC/E,YAAMtD,IAAQsD,EAAK,aAAa,YAAY;AAC5C,UAAI,CAACtD,EAAO;AACZ,YAAMkjB,IAAUF,EAAa,IAAIhjB,CAAK;AACtC,UAAIkjB,MAAY,OAAW;AAC3B,YAAMC,IAASD,IAAU5f,EAAK,sBAAA,EAAwB;AACtD,MAAI,KAAK,IAAI6f,CAAM,IAAI,KAAGF,EAAO,IAAIjjB,GAAOmjB,CAAM;AAAA,IACpD,CAAC,GAEGF,EAAO,SAAS,EAAG;AAGvB,UAAM7hB,IAAuB,CAAA;AAU7B,QATAoF,EAAW,iBAAiB,mBAAmB,EAAE,QAAQ,CAAClD,MAAS;AACjE,YAAM6f,IAASF,EAAO,IAAI3f,EAAK,aAAa,YAAY,KAAK,EAAE;AAC/D,UAAI6f,MAAW,QAAW;AACxB,cAAM7K,IAAKhV;AACX,QAAAgV,EAAG,MAAM,YAAY,cAAc6K,CAAM,OACzC/hB,EAAM,KAAKkX,CAAE;AAAA,MACf;AAAA,IACF,CAAC,GAEGlX,EAAM,WAAW,EAAG;AAGxB,IAAMoF,EAAW,KAAqB;AAEtC,UAAM4c,IAAW,KAAK;AAEtB,0BAAsB,MAAM;AAC1B,MAAAhiB,EAAM,QAAQ,CAACkX,MAAO;AACpB,QAAAA,EAAG,UAAU,IAAI,gBAAgB,GACjCA,EAAG,MAAM,YAAY;AAAA,MACvB,CAAC,GAGD,WAAW,MAAM;AACf,QAAAlX,EAAM,QAAQ,CAACkX,MAAO;AACpB,UAAAA,EAAG,MAAM,YAAY,IACrBA,EAAG,UAAU,OAAO,gBAAgB;AAAA,QACtC,CAAC;AAAA,MACH,GAAG8K,IAAW,EAAE;AAAA,IAClB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,YAAYC,GAA+B;AACjD,UAAM7c,IAAa,KAAK;AACxB,QAAI,CAACA,GAAY;AACf,MAAA6c,EAAA;AACA;AAAA,IACF;AAGA,UAAML,IAAe,KAAK,uBAAA;AAG1B,IAAAK,EAAA;AAGA,UAAMC,wBAAkB,IAAA;AAYxB,QAXA9c,EAAW,iBAAiB,iCAAiC,EAAE,QAAQ,CAAClD,MAAS;AAC/E,YAAMtD,IAAQsD,EAAK,aAAa,YAAY;AAC5C,UAAI,CAACtD,EAAO;AACZ,YAAMkjB,IAAUF,EAAa,IAAIhjB,CAAK;AACtC,UAAIkjB,MAAY,OAAW;AAC3B,YAAMK,IAAUjgB,EAAK,sBAAA,EAAwB;AAC7C,MAAI,KAAK,IAAI4f,IAAUK,CAAO,IAAI,KAChCD,EAAY,IAAItjB,CAAK;AAAA,IAEzB,CAAC,GAEGsjB,EAAY,SAAS,EAAG;AAG5B,UAAMliB,IAAuB,CAAA;AAU7B,QATAoF,EAAW,iBAAiB,mBAAmB,EAAE,QAAQ,CAAClD,MAAS;AACjE,YAAMtD,IAAQsD,EAAK,aAAa,YAAY;AAC5C,UAAItD,KAASsjB,EAAY,IAAItjB,CAAK,GAAG;AACnC,cAAMsY,IAAKhV;AACX,QAAAgV,EAAG,UAAU,IAAI,gBAAgB,GACjClX,EAAM,KAAKkX,CAAE;AAAA,MACf;AAAA,IACF,CAAC,GAEGlX,EAAM,WAAW,EAAG;AAGxB,UAAMgiB,IAAW,KAAK;AACtB,eAAW,MAAM;AACf,MAAAhiB,EAAM,QAAQ,CAACkX,MAAOA,EAAG,UAAU,OAAO,gBAAgB,CAAC;AAAA,IAC7D,GAAG8K,IAAW,EAAE;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKQ,kBAAkBX,GAA0B;AAClD,UAAM3b,IAAS,KAAK,MACd0c,IAAY,KAAK;AAEvB,QAAIA,MAAc,UAAU,KAAK,YAAY;AAC3C,YAAMR,IAAe,KAAK,uBAAA;AAC1B,MAAAlc,EAAO,eAAe2b,CAAQ,GACxB,KAAK,WAAW,KAAqB,cAC3C,KAAK,YAAYO,CAAY;AAAA,IAC/B,MAAA,CAAWQ,MAAc,SACvB,KAAK,YAAY,MAAM1c,EAAO,eAAe2b,CAAQ,CAAC,IAEtD3b,EAAO,eAAe2b,CAAQ;AAGhC,IAAA3b,EAAO,qBAAA;AAAA,EACT;AAAA;AAAA;AAAA,EAKkB,SAAS2I;AAAAA;AAE7B;ACxeO,SAASgU,EAAetgB,GAA6C;AAC1E,SAAO;AAAA,IACL,UAAU,KAAK,IAAIA,EAAM,UAAUA,EAAM,MAAM;AAAA,IAC/C,UAAU,KAAK,IAAIA,EAAM,UAAUA,EAAM,MAAM;AAAA,IAC/C,QAAQ,KAAK,IAAIA,EAAM,UAAUA,EAAM,MAAM;AAAA,IAC7C,QAAQ,KAAK,IAAIA,EAAM,UAAUA,EAAM,MAAM;AAAA,EAAA;AAEjD;AAQO,SAASugB,GAAcvgB,GAAqC;AACjE,QAAMwgB,IAAaF,EAAetgB,CAAK;AACvC,SAAO;AAAA,IACL,MAAM,EAAE,KAAKwgB,EAAW,UAAU,KAAKA,EAAW,SAAA;AAAA,IAClD,IAAI,EAAE,KAAKA,EAAW,QAAQ,KAAKA,EAAW,OAAA;AAAA,EAAO;AAEzD;AAQO,SAASC,EAAe9gB,GAA0C;AACvE,SAAOA,EAAO,IAAI4gB,EAAa;AACjC;AAUO,SAASG,GAAc5jB,GAAaoB,GAAa8B,GAAmC;AACzF,QAAMwgB,IAAaF,EAAetgB,CAAK;AACvC,SACElD,KAAO0jB,EAAW,YAAY1jB,KAAO0jB,EAAW,UAAUtiB,KAAOsiB,EAAW,YAAYtiB,KAAOsiB,EAAW;AAE9G;AAUO,SAASG,GAAiB7jB,GAAaoB,GAAayB,GAAsC;AAC/F,SAAOA,EAAO,KAAK,CAACK,MAAU0gB,GAAc5jB,GAAKoB,GAAK8B,CAAK,CAAC;AAC9D;AAQO,SAAS4gB,GAAgB5gB,GAA+D;AAC7F,QAAM/B,IAA6C,CAAA,GAC7CuiB,IAAaF,EAAetgB,CAAK;AAEvC,WAASlD,IAAM0jB,EAAW,UAAU1jB,KAAO0jB,EAAW,QAAQ1jB;AAC5D,aAASoB,IAAMsiB,EAAW,UAAUtiB,KAAOsiB,EAAW,QAAQtiB;AAC5D,MAAAD,EAAM,KAAK,EAAE,KAAAnB,GAAK,KAAAoB,EAAA,CAAK;AAI3B,SAAOD;AACT;AASO,SAAS4iB,GAAoBlhB,GAAkE;AACpG,QAAMmhB,wBAAc,IAAA;AAEpB,aAAW9gB,KAASL;AAClB,eAAWQ,KAAQygB,GAAgB5gB,CAAK;AACtC,MAAA8gB,EAAQ,IAAI,GAAG3gB,EAAK,GAAG,IAAIA,EAAK,GAAG,IAAIA,CAAI;AAI/C,SAAO,CAAC,GAAG2gB,EAAQ,QAAQ;AAC7B;AAuBO,SAASC,EACdC,GACAnN,GACmB;AACnB,SAAO;AAAA,IACL,UAAUmN,EAAO;AAAA,IACjB,UAAUA,EAAO;AAAA,IACjB,QAAQnN,EAAQ;AAAA,IAChB,QAAQA,EAAQ;AAAA,EAAA;AAEpB;;ACxHA,SAASoN,GACP1R,GACAlD,GAKA6U,GACuB;AACvB,MAAI3R,MAAS,UAAUlD,EAAM;AAC3B,WAAO;AAAA,MACL,MAAAkD;AAAA,MACA,QAAQ;AAAA,QACN;AAAA,UACE,MAAM,EAAE,KAAKlD,EAAM,aAAa,KAAK,KAAKA,EAAM,aAAa,IAAA;AAAA,UAC7D,IAAI,EAAE,KAAKA,EAAM,aAAa,KAAK,KAAKA,EAAM,aAAa,IAAA;AAAA,QAAI;AAAA,MACjE;AAAA,IACF;AAIJ,MAAIkD,MAAS,SAASlD,EAAM,SAAS,OAAO,GAAG;AAC7C,UAAM1M,IAAS,CAAC,GAAG0M,EAAM,QAAQ,EAAE,IAAI,CAAC5L,OAAc;AAAA,MACpD,MAAM,EAAE,KAAKA,GAAU,KAAK,EAAA;AAAA,MAC5B,IAAI,EAAE,KAAKA,GAAU,KAAKygB,IAAW,EAAA;AAAA,IAAE,EACvC;AACF,WAAO,EAAE,MAAA3R,GAAM,QAAA5P,EAAA;AAAA,EACjB;AAEA,SAAI4P,MAAS,WAAWlD,EAAM,OAAO,SAAS,IACrC,EAAE,MAAAkD,GAAM,QAAQkR,EAAepU,EAAM,MAAM,EAAA,IAG7C,EAAE,MAAAkD,GAAM,QAAQ,GAAC;AAC1B;AAUO,MAAM4R,WAAwBniB,EAAgC;AAAA,EAC1D,OAAO;AAAA,EACE,UAAU;AAAA,EAE5B,IAAuB,gBAA0C;AAC/D,WAAO;AAAA,MACL,MAAM;AAAA,IAAA;AAAA,EAEV;AAAA;AAAA;AAAA,EAIQ,+BAAe,IAAA;AAAA,EACf,eAA8B;AAAA,EAC9B,SAAwB;AAAA;AAAA,EAGxB,SAA8B,CAAA;AAAA,EAC9B,cAAwC;AAAA,EACxC,aAAkD;AAAA,EAClD,aAAa;AAAA;AAAA,EAGb,wBAAsD;AAAA;AAAA,EAGtD,eAAoD;AAAA;AAAA;AAAA,EAMnD,SAAe;AACtB,SAAK,SAAS,MAAA,GACd,KAAK,SAAS,CAAA,GACd,KAAK,cAAc,MACnB,KAAK,aAAa,MAClB,KAAK,aAAa,IAClB,KAAK,eAAe,MACpB,KAAK,wBAAwB;AAAA,EAC/B;AAAA;AAAA;AAAA,EAMS,YAAYC,GAAgC;AACnD,UAAM,EAAE,UAAAwB,GAAU,UAAAC,GAAU,eAAA0gB,EAAA,IAAkBniB,GACxC,EAAE,MAAAsQ,MAAS,KAAK;AAGtB,QAAIA,MAAS;AACX,kBAAK,eAAe,EAAE,KAAK9O,GAAU,KAAKC,EAAA,GAC1C,KAAK,KAA4B,oBAAoB,KAAK2gB,GAAA,CAAa,GACvE,KAAK,mBAAA,GACE;AAIT,QAAI9R,MAAS;AACX,kBAAK,SAAS,MAAA,GACd,KAAK,SAAS,IAAI9O,CAAQ,GAC1B,KAAK,eAAeA,GAEpB,KAAK,KAA4B,oBAAoB,KAAK4gB,GAAA,CAAa,GACvE,KAAK,mBAAA,GACE;AAIT,QAAI9R,MAAS,SAAS;AACpB,YAAMuE,IAAWsN,EAAc,UACzBE,IAAUF,EAAc,WAAWA,EAAc;AAEvD,UAAItN,KAAY,KAAK,YAAY;AAE/B,cAAMyN,IAAWR,EAAsB,KAAK,YAAY,EAAE,KAAKtgB,GAAU,KAAKC,GAAU;AAExF,QAAI4gB,IACE,KAAK,OAAO,SAAS,IACvB,KAAK,OAAO,KAAK,OAAO,SAAS,CAAC,IAAIC,IAEtC,KAAK,OAAO,KAAKA,CAAQ,IAG3B,KAAK,SAAS,CAACA,CAAQ,GAEzB,KAAK,cAAcA;AAAA,MACrB,WAAWD,GAAS;AAClB,cAAMC,IAA8B;AAAA,UAClC,UAAU9gB;AAAA,UACV,UAAUC;AAAA,UACV,QAAQD;AAAA,UACR,QAAQC;AAAA,QAAA;AAEV,aAAK,OAAO,KAAK6gB,CAAQ,GACzB,KAAK,cAAcA,GACnB,KAAK,aAAa,EAAE,KAAK9gB,GAAU,KAAKC,EAAA;AAAA,MAC1C,OAAO;AACL,cAAM6gB,IAA8B;AAAA,UAClC,UAAU9gB;AAAA,UACV,UAAUC;AAAA,UACV,QAAQD;AAAA,UACR,QAAQC;AAAA,QAAA;AAEV,aAAK,SAAS,CAAC6gB,CAAQ,GACvB,KAAK,cAAcA,GACnB,KAAK,aAAa,EAAE,KAAK9gB,GAAU,KAAKC,EAAA;AAAA,MAC1C;AAEA,kBAAK,KAA4B,oBAAoB,KAAK2gB,GAAA,CAAa,GAEvE,KAAK,mBAAA,GACE;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA,EAES,UAAUpiB,GAA+B;AAChD,UAAM,EAAE,MAAAsQ,MAAS,KAAK,QAEhBiS,IADU,CAAC,WAAW,aAAa,aAAa,cAAc,OAAO,QAAQ,OAAO,UAAU,UAAU,EACrF,SAASviB,EAAM,GAAG;AAG3C,QAAIA,EAAM,QAAQ;AAChB,aAAIsQ,MAAS,SACX,KAAK,eAAe,OACXA,MAAS,SAClB,KAAK,SAAS,MAAA,GACd,KAAK,SAAS,QACLA,MAAS,YAClB,KAAK,SAAS,CAAA,GACd,KAAK,cAAc,MACnB,KAAK,aAAa,OAEpB,KAAK,KAA4B,oBAAoB,KAAK8R,GAAA,CAAa,GACvE,KAAK,mBAAA,GACE;AAIT,QAAI9R,MAAS,UAAUiS;AAErB,4BAAe,MAAM;AACnB,aAAK,eAAe,EAAE,KAAK,KAAK,KAAK,WAAW,KAAK,KAAK,KAAK,UAAA,GAC/D,KAAK,KAA4B,oBAAoB,KAAKH,GAAA,CAAa,GACvE,KAAK,mBAAA;AAAA,MACP,CAAC,GACM;AAIT,QAAI9R,MAAS,UAAUtQ,EAAM,QAAQ,aAAaA,EAAM,QAAQ;AAE9D,4BAAe,MAAM;AACnB,aAAK,SAAS,MAAA,GACd,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS,GACrC,KAAK,eAAe,KAAK,KAAK,WAC9B,KAAK,KAA4B,oBAAoB,KAAKoiB,GAAA,CAAa,GACvE,KAAK,mBAAA;AAAA,MACP,CAAC,GACM;AAIT,QAAI9R,MAAS,WAAWiS;AAGtB,aAAIviB,EAAM,YAAY,CAAC,KAAK,eAC1B,KAAK,aAAa,EAAE,KAAK,KAAK,KAAK,WAAW,KAAK,KAAK,KAAK,UAAA,IAI/D,KAAK,wBAAwB,EAAE,UAAUA,EAAM,SAAA,GAK/C,eAAe,MAAM,KAAK,oBAAoB,GAEvC;AAIT,QAAIsQ,MAAS,WAAWtQ,EAAM,QAAQ,QAAQA,EAAM,WAAWA,EAAM,UAAU;AAC7E,YAAMa,IAAW,KAAK,KAAK,QACrBohB,IAAW,KAAK,QAAQ;AAC9B,UAAIphB,IAAW,KAAKohB,IAAW,GAAG;AAChC,cAAMO,IAA8B;AAAA,UAClC,UAAU;AAAA,UACV,UAAU;AAAA,UACV,QAAQ3hB,IAAW;AAAA,UACnB,QAAQohB,IAAW;AAAA,QAAA;AAErB,oBAAK,SAAS,CAACO,CAAQ,GACvB,KAAK,cAAcA,GACnB,KAAK,KAA4B,oBAAoB,KAAKJ,GAAA,CAAa,GACvE,KAAK,mBAAA,GACE;AAAA,MACT;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAES,gBAAgBpiB,GAAuC;AAM9D,QALI,KAAK,OAAO,SAAS,WACrBA,EAAM,aAAa,UAAaA,EAAM,aAAa,UACnDA,EAAM,WAAW,KAGjBA,EAAM,cAAc,YAAY,KAAK;AACvC;AAIF,SAAK,aAAa;AAClB,UAAMwB,IAAWxB,EAAM,UACjByB,IAAWzB,EAAM;AACvB,SAAK,aAAa,EAAE,KAAKwB,GAAU,KAAKC,EAAA,GAExBzB,EAAM,cAAc,WAAWA,EAAM,cAAc,YAEjE,KAAK,SAAS,CAAA;AAGhB,UAAMsiB,IAA8B;AAAA,MAClC,UAAU9gB;AAAA,MACV,UAAUC;AAAA,MACV,QAAQD;AAAA,MACR,QAAQC;AAAA,IAAA;AAEV,gBAAK,OAAO,KAAK6gB,CAAQ,GACzB,KAAK,cAAcA,GAEnB,KAAK,KAA4B,oBAAoB,KAAKF,GAAA,CAAa,GACvE,KAAK,mBAAA,GACE;AAAA,EACT;AAAA,EAES,gBAAgBpiB,GAAuC;AAI9D,QAHI,KAAK,OAAO,SAAS,WACrB,CAAC,KAAK,cAAc,CAAC,KAAK,cAC1BA,EAAM,aAAa,UAAaA,EAAM,aAAa,UACnDA,EAAM,WAAW,EAAG;AAExB,UAAMsiB,IAAWR,EAAsB,KAAK,YAAY,EAAE,KAAK9hB,EAAM,UAAU,KAAKA,EAAM,SAAA,CAAU;AAEpG,WAAI,KAAK,OAAO,SAAS,IACvB,KAAK,OAAO,KAAK,OAAO,SAAS,CAAC,IAAIsiB,IAEtC,KAAK,OAAO,KAAKA,CAAQ,GAE3B,KAAK,cAAcA,GAEnB,KAAK,KAA4B,oBAAoB,KAAKF,GAAA,CAAa,GACvE,KAAK,mBAAA,GACE;AAAA,EACT;AAAA,EAES,cAAcK,GAAwC;AAC7D,QAAI,KAAK,OAAO,SAAS,WACrB,KAAK;AACP,kBAAK,aAAa,IACX;AAAA,EAEX;AAAA;AAAA;AAAA;AAAA;AAAA,EAMAC,KAA+B;AAC7B,UAAMte,IAAa,KAAK;AACxB,QAAI,CAACA,EAAY;AAEjB,UAAM,EAAE,MAAAkM,MAAS,KAAK;AAItB,IADiBlM,EAAW,iBAAiB,OAAO,EAC3C,QAAQ,CAAClD,MAAS;AACzB,MAAAA,EAAK,UAAU,OAAO,YAAY,OAAO,UAAU,SAAS,MAAM;AAAA,IACpE,CAAC;AAED,UAAMyhB,IAAUve,EAAW,iBAAiB,gBAAgB;AAoB5D,QAnBAue,EAAQ,QAAQ,CAAC9kB,MAAQ;AACvB,MAAAA,EAAI,UAAU,OAAO,YAAY,WAAW;AAAA,IAC9C,CAAC,GAGGyS,MAAS,UAEXlM,EAAW,iBAAiB,aAAa,EAAE,QAAQ,CAAClD,MAASA,EAAK,UAAU,OAAO,YAAY,CAAC,GAEhGyhB,EAAQ,QAAQ,CAAC9kB,MAAQ;AACvB,YAAMwV,IAAYxV,EAAI,cAAc,iBAAiB,GAC/C2D,IAAW,SAAS6R,GAAW,aAAa,UAAU,KAAK,MAAM,EAAE;AACzE,MAAI7R,KAAY,KAAK,KAAK,SAAS,IAAIA,CAAQ,KAC7C3D,EAAI,UAAU,IAAI,YAAY,WAAW;AAAA,IAE7C,CAAC,IAICyS,MAAS,WAAW,KAAK,OAAO,SAAS,GAAG;AAC9C,YAAMiR,IAAa,KAAK,cAAcF,EAAe,KAAK,WAAW,IAAI;AAGzE,MADcjd,EAAW,iBAAiB,2BAA2B,EAC/D,QAAQ,CAAClD,MAAS;AACtB,cAAMM,IAAW,SAASN,EAAK,aAAa,UAAU,KAAK,MAAM,EAAE,GAC7DO,IAAW,SAASP,EAAK,aAAa,UAAU,KAAK,MAAM,EAAE;AACnE,QAAIM,KAAY,KAAKC,KAAY,KACfigB,GAAiBlgB,GAAUC,GAAU,KAAK,MAAM,MAG9DP,EAAK,UAAU,IAAI,UAAU,GAE7BA,EAAK,UAAU,OAAO,YAAY,GAE9BqgB,MACE/f,MAAa+f,EAAW,YAAUrgB,EAAK,UAAU,IAAI,KAAK,GAC1DM,MAAa+f,EAAW,UAAQrgB,EAAK,UAAU,IAAI,QAAQ,GAC3DO,MAAa8f,EAAW,YAAUrgB,EAAK,UAAU,IAAI,OAAO,GAC5DO,MAAa8f,EAAW,UAAQrgB,EAAK,UAAU,IAAI,MAAM;AAAA,MAIrE,CAAC;AAAA,IACH;AAGA,IAAIoP,MAAS,UAAU,KAAK,gBAE1BlM,EAAW,iBAAiB,aAAa,EAAE,QAAQ,CAAClD,MAASA,EAAK,UAAU,OAAO,YAAY,CAAC;AAAA,EAEpG;AAAA,EAES,cAAoB;AAC3B,UAAMkD,IAAa,KAAK;AACxB,QAAI,CAACA,EAAY;AAEjB,UAAMwC,IAAYxC,EAAW,SAAS,CAAC,GACjC,EAAE,MAAAkM,MAAS,KAAK;AAItB,QAAI,KAAK,yBAAyBA,MAAS,SAAS;AAClD,YAAM,EAAE,UAAAuE,MAAa,KAAK;AAC1B,WAAK,wBAAwB;AAE7B,YAAMrV,IAAa,KAAK,KAAK,WACvBojB,IAAa,KAAK,KAAK;AAE7B,UAAI/N,KAAY,KAAK,YAAY;AAE/B,cAAMyN,IAAWR,EAAsB,KAAK,YAAY,EAAE,KAAKtiB,GAAY,KAAKojB,GAAY;AAC5F,aAAK,SAAS,CAACN,CAAQ,GACvB,KAAK,cAAcA;AAAA,MACrB,MAAA,CAAYzN,MAEV,KAAK,SAAS,CAAA,GACd,KAAK,cAAc,MACnB,KAAK,aAAa,EAAE,KAAKrV,GAAY,KAAKojB,EAAA;AAG5C,WAAK,KAA4B,oBAAoB,KAAKR,GAAA,CAAa;AAAA,IACzE;AAGC,SAAK,KAA4B,aAAa,uBAAuB9R,CAAI,GAGtE1J,KACFA,EAAU,UAAU,OAAO,aAAa,KAAK,UAAU,GAGzD,KAAK8b,GAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA,EAMS,iBAAuB;AAC9B,SAAKA,GAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,kBAAuD;AACrD,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,kBAA4B;AAC1B,WAAO,CAAC,GAAG,KAAK,QAAQ;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,YAAyB;AACvB,WAAOlB,EAAe,KAAK,MAAM;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAwD;AACtD,WAAOI,GAAoB,KAAK,MAAM;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA,EAKA,eAAe/jB,GAAaoB,GAAsB;AAChD,WAAOyiB,GAAiB7jB,GAAKoB,GAAK,KAAK,MAAM;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAuB;AACrB,SAAK,eAAe,MACpB,KAAK,SAAS,MAAA,GACd,KAAK,SAAS,MACd,KAAK,SAAS,CAAA,GACd,KAAK,cAAc,MACnB,KAAK,aAAa,MAClB,KAAK,KAA4B,oBAAoB,EAAE,MAAM,KAAK,OAAO,MAAM,QAAQ,CAAA,GAAI,GAC3F,KAAK,mBAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKA,UAAUyB,GAA2B;AACnC,SAAK,SAASA,EAAO,IAAI,CAAC4B,OAAO;AAAA,MAC/B,UAAUA,EAAE,KAAK;AAAA,MACjB,UAAUA,EAAE,KAAK;AAAA,MACjB,QAAQA,EAAE,GAAG;AAAA,MACb,QAAQA,EAAE,GAAG;AAAA,IAAA,EACb,GACF,KAAK,cAAc,KAAK,OAAO,SAAS,IAAI,KAAK,OAAO,KAAK,OAAO,SAAS,CAAC,IAAI,MAClF,KAAK,KAA4B,oBAAoB;AAAA,MACnD,MAAM,KAAK,OAAO;AAAA,MAClB,QAAQkf,EAAe,KAAK,MAAM;AAAA,IAAA,CACnC,GACD,KAAK,mBAAA;AAAA,EACP;AAAA;AAAA;AAAA,EAMAY,KAAqC;AACnC,WAAOJ;AAAA,MACL,KAAK,OAAO;AAAA,MACZ;AAAA,QACE,cAAc,KAAK;AAAA,QACnB,UAAU,KAAK;AAAA,QACf,QAAQ,KAAK;AAAA,MAAA;AAAA,MAEf,KAAK,QAAQ;AAAA,IAAA;AAAA,EAEjB;AAAA;AAAA;AAAA,EAMkB,SAAS3U;AAAAA;AAG7B;ACpiBO,SAASwV,EAAerhB,GAAkBshB,GAA2B;AAC1E,SAAO,KAAK,MAAMthB,IAAWshB,CAAS;AACxC;AAEO,SAASC,GAAcC,GAAqBF,GAAmD;AACpG,SAAO;AAAA,IACL,OAAOE,IAAcF;AAAA,IACrB,MAAME,IAAc,KAAKF;AAAA,EAAA;AAE7B;AAEO,SAASG,GAAkBphB,GAAkBE,GAAgB+gB,GAA6B;AAC/F,QAAMI,IAAaL,EAAehhB,GAAUihB,CAAS,GAC/CK,IAAWN,EAAe9gB,IAAS,GAAG+gB,CAAS,GAE/CM,IAAmB,CAAA;AACzB,WAASzjB,IAAIujB,GAAYvjB,KAAKwjB,GAAUxjB;AACtC,IAAAyjB,EAAO,KAAKzjB,CAAC;AAEf,SAAOyjB;AACT;AAEA,eAAsBC,GACpBC,GACAN,GACAF,GACA3kB,GACwB;AACxB,QAAM4C,IAAQgiB,GAAcC,GAAaF,CAAS;AAElD,SAAOQ,EAAW,QAAQ;AAAA,IACxB,UAAUviB,EAAM;AAAA,IAChB,QAAQA,EAAM;AAAA,IACd,WAAW5C,EAAO;AAAA,IAClB,aAAaA,EAAO;AAAA,EAAA,CACrB;AACH;AAEO,SAASolB,GACd/hB,GACAshB,GACAU,GACiB;AACjB,QAAMR,IAAcH,EAAerhB,GAAUshB,CAAS,GAChDW,IAAQD,EAAa,IAAIR,CAAW;AAC1C,MAAI,CAACS,EAAO;AAEZ,QAAMC,IAAeliB,IAAWshB;AAChC,SAAOW,EAAMC,CAAY;AAC3B;ACxCA,MAAMC,KAAqB;AAWpB,MAAMC,WAAyB7jB,EAAiC;AAAA,EAC5D,OAAO;AAAA,EACE,UAAU;AAAA,EAE5B,IAAuB,gBAA2C;AAChE,WAAO;AAAA,MACL,UAAU;AAAA,MACV,gBAAgB;AAAA,MAChB,uBAAuB;AAAA,IAAA;AAAA,EAE3B;AAAA;AAAA,EAGQ,aAA0C;AAAA,EAC1C,gBAAgB;AAAA,EAChB,mCAAmB,IAAA;AAAA,EACnB,oCAAoB,IAAA;AAAA,EACpB,gBAAgB;AAAA,EAChB;AAAA;AAAA;AAAA,EAKC,SAAe;AACtB,SAAK,aAAa,MAClB,KAAK,gBAAgB,GACrB,KAAK,aAAa,MAAA,GAClB,KAAK,cAAc,MAAA,GACnB,KAAK,gBAAgB,GACjB,KAAK,wBACP,aAAa,KAAK,mBAAmB,GACrC,KAAK,sBAAsB;AAAA,EAE/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,qBAA2B;AACjC,QAAI,CAAC,KAAK,WAAY;AAGtB,UAAM8jB,IAAU,KAAK,MACff,IAAY,KAAK,OAAO,kBAAkB,KAC1C3e,IAAW,EAAE,UAAU0f,EAAQ,gBAAgB,OAAO,QAAQA,EAAQ,gBAAgB,IAAA,GAGtFC,IAAiBb,GAAkB9e,EAAS,UAAUA,EAAS,QAAQ2e,CAAS;AAGtF,eAAWiB,KAAYD;AACrB,UAAI,OAAK,aAAa,IAAIC,CAAQ,KAAK,KAAK,cAAc,IAAIA,CAAQ,IAKtE;AAAA,YAAI,KAAK,cAAc,SAAS,KAAK,OAAO,yBAAyB;AACnE;AAGF,aAAK,cAAc,IAAIA,CAAQ,GAE/BV,GAAU,KAAK,YAAYU,GAAUjB,GAAW,EAAE,EAC/C,KAAK,CAAC9hB,MAAW;AAChB,eAAK,aAAa,IAAI+iB,GAAU/iB,EAAO,IAAI,GAC3C,KAAK,gBAAgBA,EAAO,eAC5B,KAAK,cAAc,OAAO+iB,CAAQ,GAClC,KAAK,cAAA,GAEL,KAAK,mBAAA;AAAA,QACP,CAAC,EACA,MAAM,MAAM;AACX,eAAK,cAAc,OAAOA,CAAQ;AAAA,QACpC,CAAC;AAAA;AAAA,EAEP;AAAA;AAAA;AAAA,EAKS,YAAY3lB,GAAqC;AACxD,QAAI,CAAC,KAAK,WAAY,QAAO,CAAC,GAAGA,CAAI;AAGrC,UAAM4C,IAAoB,CAAA;AAC1B,aAASrB,IAAI,GAAGA,IAAI,KAAK,eAAeA,KAAK;AAC3C,YAAMqkB,IAAST,GAAgB5jB,GAAG,KAAK,OAAO,kBAAkB,KAAK,KAAK,YAAY;AACtF,MAAAqB,EAAO,KAAKgjB,KAAU,EAAE,WAAW,IAAM,SAASrkB,GAAG;AAAA,IACvD;AAEA,WAAOqB;AAAA,EACT;AAAA,EAES,SAAShB,GAA0B;AAC1C,IAAK,KAAK,eAGV,KAAK,mBAAA,GAGD,KAAK,uBACP,aAAa,KAAK,mBAAmB,GAEvC,KAAK,sBAAsB,WAAW,MAAM;AAC1C,WAAK,mBAAA;AAAA,IACP,GAAG2jB,EAAkB;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,cAAcL,GAAwC;AACpD,SAAK,aAAaA,GAClB,KAAK,aAAa,MAAA,GAClB,KAAK,cAAc,MAAA;AAGnB,UAAMR,IAAY,KAAK,OAAO,kBAAkB;AAChD,IAAAO,GAAUC,GAAY,GAAGR,GAAW,CAAA,CAAE,EAAE,KAAK,CAAC9hB,MAAW;AACvD,WAAK,aAAa,IAAI,GAAGA,EAAO,IAAI,GACpC,KAAK,gBAAgBA,EAAO,eAC5B,KAAK,cAAA;AAAA,IACP,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,UAAgB;AACd,IAAK,KAAK,eACV,KAAK,aAAa,MAAA,GAClB,KAAK,cAAc,MAAA,GACnB,KAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKA,aAAmB;AACjB,SAAK,aAAa,MAAA;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA,EAKA,mBAA2B;AACzB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAYQ,GAA2B;AACrC,UAAMshB,IAAY,KAAK,OAAO,kBAAkB,KAC1CiB,IAAWlB,EAAerhB,GAAUshB,CAAS;AACnD,WAAO,KAAK,aAAa,IAAIiB,CAAQ;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA,EAKA,sBAA8B;AAC5B,WAAO,KAAK,aAAa;AAAA,EAC3B;AAAA;AAEF;ACpLO,SAASE,GAAepmB,GAAUsO,GAAe8N,GAAkC;AACxF,SAAIpc,EAAI,OAAO,SAAkB,OAAOA,EAAI,EAAE,IACvCoc,IAAY,GAAGA,CAAS,IAAI9N,CAAK,KAAK,OAAOA,CAAK;AAC3D;AA8CO,SAASyE,GAAab,GAA2BnE,GAA0B;AAChF,QAAMmG,IAAc,IAAI,IAAIhC,CAAY;AACxC,SAAIgC,EAAY,IAAInG,CAAG,IACrBmG,EAAY,OAAOnG,CAAG,IAEtBmG,EAAY,IAAInG,CAAG,GAEdmG;AACT;AAMO,SAASmS,EAAU9lB,GAAaN,GAAoBmc,IAA2B,MAAMD,IAAQ,GAAgB;AAClH,QAAMmK,IAAgBrmB,EAAO,iBAAiB,YACxCoS,wBAAW,IAAA;AAEjB,WAASvQ,IAAI,GAAGA,IAAIvB,EAAK,QAAQuB,KAAK;AACpC,UAAM9B,IAAMO,EAAKuB,CAAC,GACZiM,IAAMqY,GAAepmB,GAAK8B,GAAGsa,CAAS,GACtCS,IAAW7c,EAAIsmB,CAAa;AAElC,QAAI,MAAM,QAAQzJ,CAAQ,KAAKA,EAAS,SAAS,GAAG;AAClD,MAAAxK,EAAK,IAAItE,CAAG;AACZ,YAAMwY,IAAYF,EAAUxJ,GAAU5c,GAAQ8N,GAAKoO,IAAQ,CAAC;AAC5D,iBAAWqK,KAAKD,EAAW,CAAAlU,EAAK,IAAImU,CAAC;AAAA,IACvC;AAAA,EACF;AAEA,SAAOnU;AACT;AAMO,SAASoU,KAA2B;AACzC,6BAAW,IAAA;AACb;AAkCO,SAASC,GACdnmB,GACAomB,GACA1mB,GACAmc,IAA2B,MAC3BD,IAAQ,GACS;AACjB,QAAMmK,IAAgBrmB,EAAO,iBAAiB;AAE9C,WAAS6B,IAAI,GAAGA,IAAIvB,EAAK,QAAQuB,KAAK;AACpC,UAAM9B,IAAMO,EAAKuB,CAAC,GACZiM,IAAMqY,GAAepmB,GAAK8B,GAAGsa,CAAS;AAE5C,QAAIrO,MAAQ4Y;AACV,aAAO,CAAC5Y,CAAG;AAGb,UAAM8O,IAAW7c,EAAIsmB,CAAa;AAClC,QAAI,MAAM,QAAQzJ,CAAQ,KAAKA,EAAS,SAAS,GAAG;AAClD,YAAM+J,IAAYF,GAAa7J,GAAU8J,GAAW1mB,GAAQ8N,GAAKoO,IAAQ,CAAC;AAC1E,UAAIyK;AACF,eAAO,CAAC7Y,GAAK,GAAG6Y,CAAS;AAAA,IAE7B;AAAA,EACF;AAEA,SAAO;AACT;AAMO,SAASC,GACdtmB,GACAomB,GACA1mB,GACA6mB,GACa;AACb,QAAMvV,IAAOmV,GAAanmB,GAAMomB,GAAW1mB,CAAM;AACjD,MAAI,CAACsR,EAAM,QAAOuV;AAElB,QAAM5S,IAAc,IAAI,IAAI4S,CAAgB;AAE5C,WAAShlB,IAAI,GAAGA,IAAIyP,EAAK,SAAS,GAAGzP;AACnC,IAAAoS,EAAY,IAAI3C,EAAKzP,CAAC,CAAC;AAEzB,SAAOoS;AACT;AC7KO,SAAS6S,GAAoBxmB,GAAa+lB,IAAgB,YAAqB;AACpF,MAAI,CAAC,MAAM,QAAQ/lB,CAAI,KAAKA,EAAK,WAAW,EAAG,QAAO;AAGtD,aAAWP,KAAOO;AAChB,QAAIP,KAAO,MAAM,QAAQA,EAAIsmB,CAAa,CAAC,KAAKtmB,EAAIsmB,CAAa,EAAE,SAAS;AAC1E,aAAO;AAIX,SAAO;AACT;AAMO,SAASU,GAAmBzmB,GAA4B;AAC7D,MAAI,CAAC,MAAM,QAAQA,CAAI,KAAKA,EAAK,WAAW,EAAG,QAAO;AAEtD,QAAM0mB,IAAoB,CAAC,YAAY,SAAS,SAAS,WAAW,QAAQ;AAE5E,aAAWjnB,KAAOO;AAChB,QAAI,GAACP,KAAO,OAAOA,KAAQ;AAE3B,iBAAWD,KAASknB;AAClB,YAAI,MAAM,QAAQjnB,EAAID,CAAK,CAAC,KAAKC,EAAID,CAAK,EAAE,SAAS;AACnD,iBAAOA;AAAA;AAKb,SAAO;AACT;;ACjBO,MAAMmnB,WAAmBhlB,EAA2B;AAAA,EAChD,OAAO;AAAA,EACE,UAAU;AAAA,EACV,SAASsN;AAAAA,EAE3B,IAAuB,gBAAqC;AAC1D,WAAO;AAAA,MACL,eAAe;AAAA,MACf,YAAY;AAAA,MACZ,iBAAiB;AAAA,MACjB,aAAa;AAAA,MACb,iBAAiB;AAAA,MACjB,WAAW;AAAA,IAAA;AAAA,EAEf;AAAA;AAAA,EAIQ,mCAAmB,IAAA;AAAA,EACnB,uBAAuB;AAAA,EACvB,gBAAoC,CAAA;AAAA,EACpC,gCAAgB,IAAA;AAAA,EAChB,0CAA0B,IAAA;AAAA,EAC1B,oCAAoB,IAAA;AAAA,EACpB,YAAyD;AAAA,EAExD,SAAe;AACtB,SAAK,aAAa,MAAA,GAClB,KAAK,uBAAuB,IAC5B,KAAK,gBAAgB,CAAA,GACrB,KAAK,UAAU,MAAA,GACf,KAAK,oBAAoB,MAAA,GACzB,KAAK,cAAc,MAAA,GACnB,KAAK,YAAY;AAAA,EACnB;AAAA;AAAA;AAAA,EAMA,IAAY,iBAA0C;AAEpD,UAAMiD,IADS,KAAK,KACA,iBAAiB,WAAW,QAAQ;AAExD,QAAIA,MAAS,MAASA,MAAS,MAAO,QAAO;AAC7C,QAAIA,MAAS,MAAQA,MAAS,MAAM;AAClC,YAAMC,IAAO,KAAK,YAAY;AAC9B,UAAIA,KAAQ,iBAAiBA,CAAI,EAAE,iBAAiB,yBAAyB,EAAE,KAAA,MAAW;AACxF,eAAO;AAAA,IAEX;AACA,WAAO,KAAK,OAAO,aAAa;AAAA,EAClC;AAAA;AAAA;AAAA,EAMA,OAAOnS,GAAmC;AACxC,QAAI,CAAC,KAAK,OAAO,WAAY,QAAO;AACpC,UAAMR,IAAQ,KAAK,OAAO,iBAAiBinB,GAAmBzmB,CAAa,KAAK;AAChF,WAAOwmB,GAAoBxmB,GAAeR,CAAK;AAAA,EACjD;AAAA;AAAA;AAAA,EAMS,YAAYQ,GAAiC;AACpD,UAAM+lB,IAAgB,KAAK,OAAO,iBAAiB;AAEnD,QAAI,CAACS,GAAoBxmB,GAAe+lB,CAAa;AACnD,kBAAK,gBAAgB,CAAA,GACrB,KAAK,UAAU,MAAA,GACf,KAAK,oBAAoB,MAAA,GAClB,CAAC,GAAG/lB,CAAI;AAIjB,QAAI4mB,IAAO,KAAK,eAAe5mB,CAAa;AAC5C,IAAI,KAAK,cACP4mB,IAAO,KAAK,SAASA,GAAM,KAAK,UAAU,OAAO,KAAK,UAAU,SAAS,IAIvE,KAAK,OAAO,mBAAmB,CAAC,KAAK,yBACvC,KAAK,eAAed,EAAUc,GAAM,KAAK,MAAM,GAC/C,KAAK,uBAAuB,KAI9B,KAAK,gBAAgB,KAAK,YAAYA,GAAM,KAAK,YAAY,GAC7D,KAAK,UAAU,MAAA,GACf,KAAK,cAAc,MAAA;AACnB,UAAMC,wBAAkB,IAAA;AAExB,eAAWpnB,KAAO,KAAK;AACrB,WAAK,UAAU,IAAIA,EAAI,KAAKA,CAAG,GAC/BonB,EAAY,IAAIpnB,EAAI,GAAG,GACnB,CAAC,KAAK,oBAAoB,IAAIA,EAAI,GAAG,KAAKA,EAAI,QAAQ,KACxD,KAAK,cAAc,IAAIA,EAAI,GAAG;AAGlC,gBAAK,sBAAsBonB,GAEpB,KAAK,cAAc,IAAI,CAAC3iB,OAAO;AAAA,MACpC,GAAGA,EAAE;AAAA,MACL,WAAWA,EAAE;AAAA,MACb,aAAaA,EAAE;AAAA,MACf,mBAAmBA,EAAE;AAAA,MACrB,gBAAgBA,EAAE;AAAA,IAAA,EAClB;AAAA,EACJ;AAAA;AAAA,EAGQ,eAAelE,GAAa6b,IAA2B,MAAa;AAC1E,UAAMkK,IAAgB,KAAK,OAAO,iBAAiB;AACnD,WAAO/lB,EAAK,IAAI,CAACP,GAAK,MAAM;AAC1B,YAAM+N,IACJ/N,EAAI,OAAO,SAAY,OAAOA,EAAI,EAAE,IAAKA,EAAI,gBAAgBoc,IAAY,GAAGA,CAAS,IAAI,CAAC,KAAK,OAAO,CAAC,IACnGS,IAAW7c,EAAIsmB,CAAa,GAC5B5J,IAAc,MAAM,QAAQG,CAAQ,KAAKA,EAAS,SAAS;AACjE,aAAO;AAAA,QACL,GAAG7c;AAAA,QACH,aAAa+N;AAAA,QACb,GAAI2O,IAAc,EAAE,CAAC4J,CAAa,GAAG,KAAK,eAAezJ,GAAU9O,CAAG,MAAM,CAAA;AAAA,MAAC;AAAA,IAEjF,CAAC;AAAA,EACH;AAAA;AAAA,EAGQ,YAAYxN,GAAa6Q,GAAuB+K,IAAQ,GAAuB;AACrF,UAAMmK,IAAgB,KAAK,OAAO,iBAAiB,YAC7CnjB,IAA6B,CAAA;AAEnC,eAAWnD,KAAOO,GAAM;AACtB,YAAMwN,IAAM/N,EAAI,eAAeA,EAAI,MAAM,KACnC6c,IAAW7c,EAAIsmB,CAAa,GAC5B5J,IAAc,MAAM,QAAQG,CAAQ,KAAKA,EAAS,SAAS,GAC3D7K,IAAaZ,EAAS,IAAIrD,CAAG;AAEnC,MAAA5K,EAAO,KAAK;AAAA,QACV,KAAA4K;AAAA,QACA,MAAM/N;AAAA,QACN,OAAAmc;AAAA,QACA,aAAAO;AAAA,QACA,YAAA1K;AAAA,QACA,WAAWmK,IAAQ,KAAIpO,EAAI,UAAU,GAAGA,EAAI,YAAY,GAAG,CAAC,KAAK;AAAA,MAAO,CACzE,GAEG2O,KAAe1K,KACjB7O,EAAO,KAAK,GAAG,KAAK,YAAY0Z,GAAUzL,GAAU+K,IAAQ,CAAC,CAAC;AAAA,IAElE;AACA,WAAOhZ;AAAA,EACT;AAAA;AAAA,EAGQ,SAAS5C,GAAaR,GAAesnB,GAAoB;AAC/D,UAAMf,IAAgB,KAAK,OAAO,iBAAiB;AASnD,WARe,CAAC,GAAG/lB,CAAI,EAAE,KAAK,CAACS,GAAGC,MAAM;AACtC,YAAM2V,IAAO5V,EAAEjB,CAAK,GAClB8W,IAAO5V,EAAElB,CAAK;AAChB,aAAI6W,KAAQ,QAAQC,KAAQ,OAAa,IACrCD,KAAQ,OAAa,KACrBC,KAAQ,OAAa,IAClBD,IAAOC,IAAOwQ,IAAMzQ,IAAOC,IAAO,CAACwQ,IAAM;AAAA,IAClD,CAAC,EACa,IAAI,CAACrnB,MAAQ;AACzB,YAAM6c,IAAW7c,EAAIsmB,CAAa;AAClC,aAAO,MAAM,QAAQzJ,CAAQ,KAAKA,EAAS,SAAS,IAChD,EAAE,GAAG7c,GAAK,CAACsmB,CAAa,GAAG,KAAK,SAASzJ,GAAU9c,GAAOsnB,CAAG,MAC7DrnB;AAAA,IACN,CAAC;AAAA,EACH;AAAA,EAES,eAAeQ,GAAkD;AACxE,QAAI,KAAK,cAAc,WAAW,EAAG,QAAO,CAAC,GAAGA,CAAO;AAEvD,UAAMsP,IAAO,CAAC,GAAGtP,CAAO;AACxB,QAAIsP,EAAK,WAAW,EAAG,QAAOA;AAE9B,UAAMiF,IAAW,EAAE,GAAGjF,EAAK,CAAC,EAAA,GACtBX,IAAW4F,EAAS;AAC1B,QAAK5F,GAAkB,cAAe,QAAOW;AAE7C,UAAMwX,IAAY,MAAM,KAAK,QACvBC,IAAU,KAAK,QAAQ,KAAK,IAAI,GAChCC,IAAc,KAAK,YAAY,KAAK,IAAI,GAExCC,IAAU,CAACxJ,MAAqD;AACpE,YAAM,EAAE,OAAAne,GAAO,KAAAE,EAAA,IAAQie,GACjB,EAAE,aAAAwC,IAAc,IAAI,iBAAAiH,IAAkB,GAAA,IAASJ,EAAA,GAE/Cve,IAAY,SAAS,cAAc,MAAM;AAK/C,UAJAA,EAAU,YAAY,aACtBA,EAAU,MAAM,YAAY,gBAAgB,OAAO/I,EAAI,eAAe,CAAC,CAAC,GACxE+I,EAAU,MAAM,YAAY,qBAAqB,GAAG0X,CAAW,IAAI,GAE/DzgB,EAAI,qBAAqB0nB,GAAiB;AAC5C,cAAMhgB,IAAO,SAAS,cAAc,MAAM;AAC1C,QAAAA,EAAK,YAAY,cAAc1H,EAAI,iBAAiB,cAAc,EAAE,IACpEunB,EAAQ7f,GAAM8f,EAAYxnB,EAAI,iBAAiB,aAAa,QAAQ,CAAC,GACrE0H,EAAK,aAAa,iBAAiB1H,EAAI,SAAS,GAChD+I,EAAU,YAAYrB,CAAI;AAAA,MAC5B,WAAWggB,GAAiB;AAC1B,cAAMxZ,IAAS,SAAS,cAAc,MAAM;AAC5C,QAAAA,EAAO,YAAY,eACnBnF,EAAU,YAAYmF,CAAM;AAAA,MAC9B;AAEA,YAAMrE,IAAU,SAAS,cAAc,MAAM;AAC7C,UAAIsF,GAAU;AACZ,cAAMiG,IAAWjG,EAAS8O,CAAG;AAC7B,QAAI7I,aAAoB,OACtBvL,EAAQ,YAAYuL,CAAQ,IAE5BvL,EAAQ,cAAc,OAAOuL,KAAYtV,KAAS,EAAE;AAAA,MAExD;AACE,QAAA+J,EAAQ,cAAc,OAAO/J,KAAS,EAAE;AAE1C,aAAAiJ,EAAU,YAAYc,CAAO,GACtBd;AAAA,IACT;AAEC,WAAA0e,EAAgB,gBAAgB,IACjC1S,EAAS,eAAe0S,GACxB3X,EAAK,CAAC,IAAIiF,GACHjF;AAAA,EACT;AAAA;AAAA;AAAA,EAMS,YAAY3N,GAAgC;AACnD,UAAMK,IAASL,EAAM,eAAe;AACpC,QAAI,CAACK,GAAQ,UAAU,SAAS,aAAa,EAAG,QAAO;AAEvD,UAAMuL,IAAMvL,EAAO,aAAa,eAAe,GACzCmlB,IAAU5Z,IAAM,KAAK,UAAU,IAAIA,CAAG,IAAI;AAChD,WAAK4Z,KAEL,KAAK,eAAe5U,GAAa,KAAK,cAAchF,CAAI,GACxD,KAAK,KAAuB,eAAe;AAAA,MACzC,KAAAA;AAAA,MACA,KAAK4Z,EAAQ;AAAA,MACb,UAAU,KAAK,aAAa,IAAI5Z,CAAI;AAAA,MACpC,OAAO4Z,EAAQ;AAAA,IAAA,CAChB,GACD,KAAK,cAAA,GACE,MAVc;AAAA,EAWvB;AAAA,EAES,cAAcxlB,GAAkC;AACvD,QAAI,KAAK,cAAc,WAAW,KAAK,CAACA,EAAM,OAAO,SAAU,QAAO;AAEtE,UAAM,EAAE,OAAApC,MAAUoC,EAAM;AACxB,IAAI,CAAC,KAAK,aAAa,KAAK,UAAU,UAAUpC,IAC9C,KAAK,YAAY,EAAE,OAAAA,GAAO,WAAW,EAAA,IAC5B,KAAK,UAAU,cAAc,IACtC,KAAK,YAAY,EAAE,OAAAA,GAAO,WAAW,GAAA,IAErC,KAAK,YAAY;AAInB,UAAM8G,IAAS,KAAK;AACpB,WAAIA,EAAO,eAAe,WACxBA,EAAO,aAAa,KAAK,YAAY,EAAE,GAAG,KAAK,cAAc,OAG/D,KAAK,KAAK,eAAe,EAAE,OAAA9G,GAAO,WAAW,KAAK,WAAW,aAAa,GAAG,GAC7E,KAAK,cAAA,GACE;AAAA,EACT;AAAA,EAES,cAAoB;AAC3B,UAAMsM,IAAQ,KAAK;AACnB,QAAIA,MAAU,MAAS,KAAK,cAAc,SAAS,EAAG;AAEtD,UAAM4G,IAAO,KAAK,YAAY,cAAc,OAAO;AACnD,QAAI,CAACA,EAAM;AAEX,UAAMC,IAAY7G,MAAU,SAAS,qBAAqB;AAC1D,eAAWwG,KAASI,EAAK,iBAAiB,gBAAgB,GAAG;AAC3D,YAAM5P,IAAOwP,EAAM,cAAc,iBAAiB,GAC5C3R,IAAMmC,IAAO,SAASA,EAAK,aAAa,UAAU,KAAK,MAAM,EAAE,IAAI,IACnE0K,IAAM,KAAK,cAAc7M,CAAG,GAAG;AAErC,MAAI6M,KAAO,KAAK,cAAc,IAAIA,CAAG,MACnC8E,EAAM,UAAU,IAAIK,CAAS,GAC7BL,EAAM,iBAAiB,gBAAgB,MAAMA,EAAM,UAAU,OAAOK,CAAS,GAAG,EAAE,MAAM,GAAA,CAAM;AAAA,IAElG;AACA,SAAK,cAAc,MAAA;AAAA,EACrB;AAAA;AAAA;AAAA,EAMA,OAAOnF,GAAmB;AACxB,SAAK,aAAa,IAAIA,CAAG,GACzB,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,SAASA,GAAmB;AAC1B,SAAK,aAAa,OAAOA,CAAG,GAC5B,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,OAAOA,GAAmB;AACxB,SAAK,eAAegF,GAAa,KAAK,cAAchF,CAAG,GACvD,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,YAAkB;AAChB,SAAK,eAAesY,EAAU,KAAK,MAAe,KAAK,MAAM,GAC7D,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,cAAoB;AAClB,SAAK,eAAeI,GAAA,GACpB,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,WAAW1Y,GAAsB;AAC/B,WAAO,KAAK,aAAa,IAAIA,CAAG;AAAA,EAClC;AAAA,EAEA,kBAA4B;AAC1B,WAAO,CAAC,GAAG,KAAK,YAAY;AAAA,EAC9B;AAAA,EAEA,mBAAuC;AACrC,WAAO,CAAC,GAAG,KAAK,aAAa;AAAA,EAC/B;AAAA,EAEA,YAAYA,GAA8B;AACxC,WAAO,KAAK,UAAU,IAAIA,CAAG,GAAG;AAAA,EAClC;AAAA,EAEA,YAAYA,GAAmB;AAC7B,SAAK,eAAe8Y,GAAY,KAAK,MAAe9Y,GAAK,KAAK,QAAQ,KAAK,YAAY,GACvF,KAAK,cAAA;AAAA,EACP;AAAA;AAGF;ACxWO,SAAS6Z,GAAWrY,GAAsBsY,GAAoBC,GAAgC;AACnG,QAAMC,IAAY,CAAC,GAAGxY,EAAM,WAAWsY,CAAM;AAG7C,SAAOE,EAAU,SAASD;AACxB,IAAAC,EAAU,MAAA;AAGZ,SAAO;AAAA,IACL,WAAAA;AAAA,IACA,WAAW,CAAA;AAAA;AAAA,EAAC;AAEhB;AASO,SAASC,GAAKzY,GAGnB;AACA,MAAIA,EAAM,UAAU,WAAW;AAC7B,WAAO,EAAE,UAAUA,GAAO,QAAQ,KAAA;AAGpC,QAAMwY,IAAY,CAAC,GAAGxY,EAAM,SAAS,GAC/BsY,IAASE,EAAU,IAAA;AAIzB,SAAKF,IAIE;AAAA,IACL,UAAU;AAAA,MACR,WAAAE;AAAA,MACA,WAAW,CAAC,GAAGxY,EAAM,WAAWsY,CAAM;AAAA,IAAA;AAAA,IAExC,QAAAA;AAAA,EAAA,IARO,EAAE,UAAUtY,GAAO,QAAQ,KAAA;AAUtC;AASO,SAAS0Y,GAAK1Y,GAGnB;AACA,MAAIA,EAAM,UAAU,WAAW;AAC7B,WAAO,EAAE,UAAUA,GAAO,QAAQ,KAAA;AAGpC,QAAM2Y,IAAY,CAAC,GAAG3Y,EAAM,SAAS,GAC/BsY,IAASK,EAAU,IAAA;AAIzB,SAAKL,IAIE;AAAA,IACL,UAAU;AAAA,MACR,WAAW,CAAC,GAAGtY,EAAM,WAAWsY,CAAM;AAAA,MACtC,WAAAK;AAAA,IAAA;AAAA,IAEF,QAAAL;AAAA,EAAA,IARO,EAAE,UAAUtY,GAAO,QAAQ,KAAA;AAUtC;AAQO,SAAS4Y,GAAQ5Y,GAA+B;AACrD,SAAOA,EAAM,UAAU,SAAS;AAClC;AAQO,SAAS6Y,GAAQ7Y,GAA+B;AACrD,SAAOA,EAAM,UAAU,SAAS;AAClC;AAOO,SAAS8Y,KAA8B;AAC5C,SAAO,EAAE,WAAW,IAAI,WAAW,CAAA,EAAC;AACtC;AAWO,SAASC,GAAiB3kB,GAAkB5D,GAAewoB,GAAmBC,GAA+B;AAClH,SAAO;AAAA,IACL,MAAM;AAAA,IACN,UAAA7kB;AAAA,IACA,OAAA5D;AAAA,IACA,UAAAwoB;AAAA,IACA,UAAAC;AAAA,IACA,WAAW,KAAK,IAAA;AAAA,EAAI;AAExB;AChIO,MAAMC,WAAuBvmB,EAA+B;AAAA,EACxD,OAAO;AAAA,EACE,UAAU;AAAA,EAE5B,IAAuB,gBAAyC;AAC9D,WAAO;AAAA,MACL,gBAAgB;AAAA,IAAA;AAAA,EAEpB;AAAA;AAAA,EAGQ,YAA0B,CAAA;AAAA,EAC1B,YAA0B,CAAA;AAAA;AAAA;AAAA;AAAA,EAKzB,SAAe;AACtB,SAAK,YAAY,CAAA,GACjB,KAAK,YAAY,CAAA;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOS,UAAUC,GAA+B;AAChD,UAAMumB,KAAUvmB,EAAM,WAAWA,EAAM,YAAYA,EAAM,QAAQ,OAAO,CAACA,EAAM,UACzEwmB,KAAUxmB,EAAM,WAAWA,EAAM,aAAaA,EAAM,QAAQ,OAAQA,EAAM,QAAQ,OAAOA,EAAM;AAErG,QAAIumB,GAAQ;AACV,YAAMvlB,IAAS6kB,GAAK,EAAE,WAAW,KAAK,WAAW,WAAW,KAAK,WAAW;AAC5E,UAAI7kB,EAAO,QAAQ;AAEjB,cAAM5C,IAAO,KAAK;AAClB,QAAIA,EAAK4C,EAAO,OAAO,QAAQ,MAC7B5C,EAAK4C,EAAO,OAAO,QAAQ,EAAEA,EAAO,OAAO,KAAK,IAAIA,EAAO,OAAO,WAIpE,KAAK,YAAYA,EAAO,SAAS,WACjC,KAAK,YAAYA,EAAO,SAAS,WAEjC,KAAK,KAAqB,QAAQ;AAAA,UAChC,QAAQA,EAAO;AAAA,UACf,MAAM;AAAA,QAAA,CACP,GAED,KAAK,cAAA;AAAA,MACP;AACA,aAAO;AAAA,IACT;AAEA,QAAIwlB,GAAQ;AACV,YAAMxlB,IAAS8kB,GAAK,EAAE,WAAW,KAAK,WAAW,WAAW,KAAK,WAAW;AAC5E,UAAI9kB,EAAO,QAAQ;AAEjB,cAAM5C,IAAO,KAAK;AAClB,QAAIA,EAAK4C,EAAO,OAAO,QAAQ,MAC7B5C,EAAK4C,EAAO,OAAO,QAAQ,EAAEA,EAAO,OAAO,KAAK,IAAIA,EAAO,OAAO,WAIpE,KAAK,YAAYA,EAAO,SAAS,WACjC,KAAK,YAAYA,EAAO,SAAS,WAEjC,KAAK,KAAqB,QAAQ;AAAA,UAChC,QAAQA,EAAO;AAAA,UACf,MAAM;AAAA,QAAA,CACP,GAED,KAAK,cAAA;AAAA,MACP;AACA,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,WAAWQ,GAAkB5D,GAAewoB,GAAmBC,GAAyB;AACtF,UAAMX,IAASS,GAAiB3kB,GAAU5D,GAAOwoB,GAAUC,CAAQ,GAC7D1a,IAAW8Z;AAAA,MACf,EAAE,WAAW,KAAK,WAAW,WAAW,KAAK,UAAA;AAAA,MAC7CC;AAAA,MACA,KAAK,OAAO,kBAAkB;AAAA,IAAA;AAEhC,SAAK,YAAY/Z,EAAS,WAC1B,KAAK,YAAYA,EAAS;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAA0B;AACxB,UAAM3K,IAAS6kB,GAAK,EAAE,WAAW,KAAK,WAAW,WAAW,KAAK,WAAW;AAC5E,QAAI7kB,EAAO,QAAQ;AACjB,YAAM5C,IAAO,KAAK;AAClB,MAAIA,EAAK4C,EAAO,OAAO,QAAQ,MAC7B5C,EAAK4C,EAAO,OAAO,QAAQ,EAAEA,EAAO,OAAO,KAAK,IAAIA,EAAO,OAAO,WAEpE,KAAK,YAAYA,EAAO,SAAS,WACjC,KAAK,YAAYA,EAAO,SAAS,WACjC,KAAK,cAAA;AAAA,IACP;AACA,WAAOA,EAAO;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAA0B;AACxB,UAAMA,IAAS8kB,GAAK,EAAE,WAAW,KAAK,WAAW,WAAW,KAAK,WAAW;AAC5E,QAAI9kB,EAAO,QAAQ;AACjB,YAAM5C,IAAO,KAAK;AAClB,MAAIA,EAAK4C,EAAO,OAAO,QAAQ,MAC7B5C,EAAK4C,EAAO,OAAO,QAAQ,EAAEA,EAAO,OAAO,KAAK,IAAIA,EAAO,OAAO,WAEpE,KAAK,YAAYA,EAAO,SAAS,WACjC,KAAK,YAAYA,EAAO,SAAS,WACjC,KAAK,cAAA;AAAA,IACP;AACA,WAAOA,EAAO;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,UAAmB;AACjB,WAAOglB,GAAQ,EAAE,WAAW,KAAK,WAAW,WAAW,KAAK,WAAW;AAAA,EACzE;AAAA;AAAA;AAAA;AAAA,EAKA,UAAmB;AACjB,WAAOC,GAAQ,EAAE,WAAW,KAAK,WAAW,WAAW,KAAK,WAAW;AAAA,EACzE;AAAA;AAAA;AAAA;AAAA,EAKA,eAAqB;AACnB,UAAMta,IAAWua,GAAA;AACjB,SAAK,YAAYva,EAAS,WAC1B,KAAK,YAAYA,EAAS;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA,EAKA,eAA6B;AAC3B,WAAO,CAAC,GAAG,KAAK,SAAS;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKA,eAA6B;AAC3B,WAAO,CAAC,GAAG,KAAK,SAAS;AAAA,EAC3B;AAAA;AAEF;;AC9JA,SAASwT,GAAcxd,GAA+B;AACpD,QAAMyd,IAAOzd,EAAO,QAAQ,CAAA;AAC5B,SAAOyd,EAAK,iBAAiB,MAAQA,EAAK,oBAAoB;AAChE;AAyBO,MAAMqH,UAAyB1mB,EAAiC;AAAA,EAC5D,OAAO;AAAA,EACE,UAAU;AAAA;AAAA,EAG5B,OAAgB,WAAW;AAAA,EAE3B,IAAuB,gBAA2C;AAChE,WAAO;AAAA,MACL,cAAc;AAAA,IAAA;AAAA,EAElB;AAAA;AAAA,EAGQ,oBAAwC;AAAA;AAAA,EAGxC,aAAa;AAAA,EACb,eAA8B;AAAA,EAC9B,eAA8B;AAAA,EAC9B,YAA2B;AAAA;AAAA;AAAA,EAK1B,SAAe;AACtB,SAAK,oBAAoB,MACzB,KAAK,aAAa,IAClB,KAAK,eAAe,MACpB,KAAK,eAAe,MACpB,KAAK,YAAY;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQS,eAAgD;AACvD,WAAO;AAAA,MACL,IAAI0mB,EAAiB;AAAA,MACrB,OAAO;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,OAAO;AAAA;AAAA,MACP,QAAQ,CAAC7f,MAAc,KAAK,mBAAmBA,CAAS;AAAA,IAAA;AAAA,EAE5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAa;AAEX,IADa,KAAK,KACb,cAAc6f,EAAiB,QAAQ;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA,EAKA,OAAa;AAEX,IADa,KAAK,KACb,eAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKA,SAAe;AAEb,IADa,KAAK,KACb,gBAAgBA,EAAiB,QAAQ;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,gBAAgB7oB,GAAwB;AAEtC,WADa,KAAK,KACN,gBAAgBA,CAAK;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,iBAAiBA,GAAe8oB,GAAwB;AAEtD,IADa,KAAK,KACb,iBAAiB9oB,GAAO8oB,CAAO;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,oBAA8B;AAE5B,WADa,KAAK,KAEf,cAAA,EACA,OAAO,CAACloB,MAAMA,EAAE,OAAO,EACvB,IAAI,CAACA,MAAMA,EAAE,KAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,mBAA6B;AAE3B,WADa,KAAK,KAEf,cAAA,EACA,OAAO,CAACA,MAAM,CAACA,EAAE,OAAO,EACxB,IAAI,CAACA,MAAMA,EAAE,KAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAgB;AAEd,IADa,KAAK,KACb,eAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,aAAaZ,GAAqB;AAEhC,IADa,KAAK,KACb,uBAAuBA,CAAK;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAAWA,GAAqB;AAE9B,IADa,KAAK,KACb,iBAAiBA,GAAO,EAAI;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAAWA,GAAqB;AAE9B,IADa,KAAK,KACb,iBAAiBA,GAAO,EAAK;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,gBAAmG;AAEjG,WADa,KAAK,KACN,cAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,iBAA0B;AAExB,WADa,KAAK,KACN,oBAAoB6oB,EAAiB;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,mBAAmB7f,GAA6C;AACtE,UAAMtF,IAAO,KAAK,MAGZya,IAAU,SAAS,cAAc,KAAK;AAC5C,IAAAA,EAAQ,YAAY;AAGpB,UAAM4K,IAAa,SAAS,cAAc,KAAK;AAC/C,IAAAA,EAAW,YAAY,uBACvB5K,EAAQ,YAAY4K,CAAU;AAG9B,UAAMC,IAAa,SAAS,cAAc,QAAQ;AAClD,WAAAA,EAAW,YAAY,2BACvBA,EAAW,cAAc,YACzBA,EAAW,iBAAiB,SAAS,MAAM;AACzC,MAAAtlB,EAAK,eAAA,GACL,KAAK,eAAeqlB,CAAU;AAAA,IAChC,CAAC,GACD5K,EAAQ,YAAY6K,CAAU,GAG9B,KAAK,oBAAoBD,GAGzB,KAAK,eAAeA,CAAU,GAG9B/f,EAAU,YAAYmV,CAAO,GAGtB,MAAM;AACX,WAAK,oBAAoB,MACzBA,EAAQ,OAAA;AAAA,IACV;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,mBAA4B;AAClC,UAAMxa,IAAS,KAAK,MAAM,kBAAkB,SAAS;AAErD,WAAO,CAAC,EAAEA,KAAU,OAAQA,EAAoC,cAAe;AAAA,EACjF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,eAAeolB,GAA+B;AACpD,UAAMrlB,IAAO,KAAK,MACZulB,IAAiB,KAAK,iBAAA;AAE5B,IAAAF,EAAW,YAAY;AAGvB,UAAMG,IAAaxlB,EAAK,cAAA;AAExB,aAAS,IAAI,GAAG,IAAIwlB,EAAW,QAAQ,KAAK;AAC1C,YAAM7nB,IAAM6nB,EAAW,CAAC,GAClBthB,IAAQvG,EAAI,UAAUA,EAAI,OAE1BpB,IAAM,SAAS,cAAc,KAAK;AACxC,MAAAA,EAAI,YAAYoB,EAAI,cAAc,8BAA8B,sBAChEpB,EAAI,aAAa,cAAcoB,EAAI,KAAK,GACxCpB,EAAI,aAAa,cAAc,OAAO,CAAC,CAAC,GAGpCgpB,KAAkB1H,GAAclgB,CAA8B,MAChEpB,EAAI,YAAY,IAChBA,EAAI,UAAU,IAAI,aAAa,GAE/B,KAAK,mBAAmBA,GAAKoB,EAAI,OAAO,GAAG0nB,CAAU;AAGvD,YAAMxJ,IAAe,SAAS,cAAc,OAAO;AACnD,MAAAA,EAAa,YAAY;AAEzB,YAAM9Q,IAAW,SAAS,cAAc,OAAO;AAC/C,MAAAA,EAAS,OAAO,YAChBA,EAAS,UAAUpN,EAAI,SACvBoN,EAAS,WAAWpN,EAAI,eAAe,IACvCoN,EAAS,iBAAiB,UAAU,MAAM;AACxC,QAAA/K,EAAK,uBAAuBrC,EAAI,KAAK,GAErC,WAAW,MAAM,KAAK,eAAe0nB,CAAU,GAAG,CAAC;AAAA,MACrD,CAAC;AAED,YAAMxnB,IAAO,SAAS,cAAc,MAAM;AAO1C,UANAA,EAAK,cAAcqG,GAEnB2X,EAAa,YAAY9Q,CAAQ,GACjC8Q,EAAa,YAAYhe,CAAI,GAGzB0nB,KAAkB1H,GAAclgB,CAA8B,GAAG;AACnE,cAAM8nB,IAAS,SAAS,cAAc,MAAM;AAC5C,QAAAA,EAAO,YAAY,yBAEnB,KAAK,QAAQA,GAAQ,KAAK,YAAY,YAAY,CAAC,GACnDA,EAAO,QAAQ,mBACflpB,EAAI,YAAYkpB,CAAM;AAAA,MACxB;AAEA,MAAAlpB,EAAI,YAAYsf,CAAY,GAC5BwJ,EAAW,YAAY9oB,CAAG;AAAA,IAC5B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,mBAAmBA,GAAkBD,GAAeuO,GAAewa,GAA+B;AACxG,IAAA9oB,EAAI,iBAAiB,aAAa,CAACgI,MAAiB;AAClD,WAAK,aAAa,IAClB,KAAK,eAAejI,GACpB,KAAK,eAAeuO,GAEhBtG,EAAE,iBACJA,EAAE,aAAa,gBAAgB,QAC/BA,EAAE,aAAa,QAAQ,cAAcjI,CAAK,IAG5CC,EAAI,UAAU,IAAI,UAAU;AAAA,IAC9B,CAAC,GAEDA,EAAI,iBAAiB,WAAW,MAAM;AACpC,WAAK,aAAa,IAClB,KAAK,eAAe,MACpB,KAAK,eAAe,MACpB,KAAK,YAAY,MAEjB8oB,EAAW,iBAAiB,qBAAqB,EAAE,QAAQ,CAACrkB,MAAM;AAChE,QAAAA,EAAE,UAAU,OAAO,YAAY,eAAe,eAAe,YAAY;AAAA,MAC3E,CAAC;AAAA,IACH,CAAC,GAEDzE,EAAI,iBAAiB,YAAY,CAACgI,MAAiB;AAEjD,UADAA,EAAE,eAAA,GACE,CAAC,KAAK,cAAc,KAAK,iBAAiBjI,EAAO;AAErD,YAAMiN,IAAOhN,EAAI,sBAAA,GACXmpB,IAAOnc,EAAK,MAAMA,EAAK,SAAS;AAEtC,WAAK,YAAYhF,EAAE,UAAUmhB,IAAO7a,IAAQA,IAAQ,GAGpDwa,EAAW,iBAAiB,qBAAqB,EAAE,QAAQ,CAACrkB,MAAM;AAChE,QAAIA,MAAMzE,KAAKyE,EAAE,UAAU,OAAO,eAAe,eAAe,YAAY;AAAA,MAC9E,CAAC,GAEDzE,EAAI,UAAU,IAAI,aAAa,GAC/BA,EAAI,UAAU,OAAO,eAAegI,EAAE,UAAUmhB,CAAI,GACpDnpB,EAAI,UAAU,OAAO,cAAcgI,EAAE,WAAWmhB,CAAI;AAAA,IACtD,CAAC,GAEDnpB,EAAI,iBAAiB,aAAa,MAAM;AACtC,MAAAA,EAAI,UAAU,OAAO,eAAe,eAAe,YAAY;AAAA,IACjE,CAAC,GAEDA,EAAI,iBAAiB,QAAQ,CAACgI,MAAiB;AAC7C,MAAAA,EAAE,eAAA;AACF,YAAMma,IAAe,KAAK,cACpBC,IAAe,KAAK,cACpBC,IAAY,KAAK;AAEvB,UAAI,CAAC,KAAK,cAAcF,MAAiB,QAAQC,MAAiB,QAAQC,MAAc;AACtF;AAIF,YAAMC,IAAmBD,IAAYD,IAAeC,IAAY,IAAIA;AAEpE,UAAIC,MAAqBF,GAAc;AAErC,cAAMP,IAAqC;AAAA,UACzC,OAAOM;AAAA,UACP,WAAWC;AAAA,UACX,SAASE;AAAA,QAAA;AAEX,aAAK,KAAiC,0BAA0BT,CAAM,GAGtE,WAAW,MAAM;AACf,eAAK,eAAeiH,CAAU;AAAA,QAChC,GAAG,CAAC;AAAA,MACN;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA,EAKkB,SAAStZ;AAAA;AAE7B;"}
|
|
1
|
+
{"version":3,"file":"all.js","sources":["../../../libs/grid/src/lib/plugins/clipboard/copy.ts","../../../libs/grid/src/lib/plugins/clipboard/paste.ts","../../../libs/grid/src/lib/plugins/clipboard/ClipboardPlugin.ts","../../../libs/grid/src/lib/plugins/column-virtualization/column-virtualization.ts","../../../libs/grid/src/lib/plugins/column-virtualization/ColumnVirtualizationPlugin.ts","../../../libs/grid/src/lib/plugins/context-menu/menu.ts","../../../libs/grid/src/lib/plugins/context-menu/ContextMenuPlugin.ts","../../../libs/grid/src/lib/plugins/export/csv.ts","../../../libs/grid/src/lib/plugins/export/excel.ts","../../../libs/grid/src/lib/plugins/export/ExportPlugin.ts","../../../libs/grid/src/lib/core/internal/virtualization.ts","../../../libs/grid/src/lib/plugins/filtering/filter-model.ts","../../../libs/grid/src/lib/plugins/filtering/FilteringPlugin.ts","../../../libs/grid/src/lib/plugins/grouping-columns/grouping-columns.ts","../../../libs/grid/src/lib/plugins/grouping-columns/GroupingColumnsPlugin.ts","../../../libs/grid/src/lib/plugins/grouping-rows/grouping-rows.ts","../../../libs/grid/src/lib/plugins/grouping-rows/GroupingRowsPlugin.ts","../../../libs/grid/src/lib/plugins/master-detail/master-detail.ts","../../../libs/grid/src/lib/plugins/master-detail/MasterDetailPlugin.ts","../../../libs/grid/src/lib/plugins/multi-sort/multi-sort.ts","../../../libs/grid/src/lib/plugins/multi-sort/MultiSortPlugin.ts","../../../libs/grid/src/lib/plugins/pinned-columns/pinned-columns.ts","../../../libs/grid/src/lib/plugins/pinned-columns/PinnedColumnsPlugin.ts","../../../libs/grid/src/lib/plugins/pinned-rows/pinned-rows.ts","../../../libs/grid/src/lib/plugins/pinned-rows/PinnedRowsPlugin.ts","../../../libs/grid/src/lib/plugins/pivot/pivot-model.ts","../../../libs/grid/src/lib/plugins/pivot/pivot-engine.ts","../../../libs/grid/src/lib/plugins/pivot/pivot-panel.ts","../../../libs/grid/src/lib/plugins/pivot/pivot-rows.ts","../../../libs/grid/src/lib/plugins/pivot/PivotPlugin.ts","../../../libs/grid/src/lib/plugins/reorder/column-drag.ts","../../../libs/grid/src/lib/plugins/reorder/ReorderPlugin.ts","../../../libs/grid/src/lib/plugins/selection/range-selection.ts","../../../libs/grid/src/lib/plugins/selection/SelectionPlugin.ts","../../../libs/grid/src/lib/plugins/server-side/datasource.ts","../../../libs/grid/src/lib/plugins/server-side/ServerSidePlugin.ts","../../../libs/grid/src/lib/plugins/tree/tree-data.ts","../../../libs/grid/src/lib/plugins/tree/tree-detect.ts","../../../libs/grid/src/lib/plugins/tree/TreePlugin.ts","../../../libs/grid/src/lib/plugins/undo-redo/history.ts","../../../libs/grid/src/lib/plugins/undo-redo/UndoRedoPlugin.ts","../../../libs/grid/src/lib/plugins/visibility/VisibilityPlugin.ts"],"sourcesContent":["/**\n * Clipboard Copy Logic\n *\n * Pure functions for copying grid data to clipboard.\n */\n\nimport type { ColumnConfig } from '../../core/types';\nimport type { ClipboardConfig } from './types';\n\n/** Parameters for building clipboard text */\nexport interface CopyParams {\n /** All grid rows */\n rows: unknown[];\n /** Column configurations */\n columns: ColumnConfig[];\n /** Selected row indices */\n selectedIndices: Set<number> | number[];\n /** Clipboard configuration */\n config: ClipboardConfig;\n}\n\n/**\n * Format a cell value for clipboard output.\n *\n * Uses custom processCell if provided, otherwise applies default formatting:\n * - null/undefined → empty string\n * - Date → ISO string\n * - Object → JSON string\n * - Other → String conversion with optional quoting\n *\n * @param value - The cell value to format\n * @param field - The field name\n * @param row - The full row object\n * @param config - Clipboard configuration\n * @returns Formatted string value\n */\nexport function formatCellValue(value: unknown, field: string, row: unknown, config: ClipboardConfig): string {\n if (config.processCell) {\n return config.processCell(value, field, row);\n }\n\n if (value == null) return '';\n if (value instanceof Date) return value.toISOString();\n if (typeof value === 'object') return JSON.stringify(value);\n\n const str = String(value);\n const delimiter = config.delimiter ?? '\\t';\n const newline = config.newline ?? '\\n';\n\n // Quote if contains delimiter, newline, or quotes (or if quoteStrings is enabled)\n if (config.quoteStrings || str.includes(delimiter) || str.includes(newline) || str.includes('\"')) {\n return `\"${str.replace(/\"/g, '\"\"')}\"`;\n }\n\n return str;\n}\n\n/**\n * Build clipboard text from selected rows and columns.\n *\n * @param params - Copy parameters including rows, columns, selection, and config\n * @returns Tab-separated (or custom delimiter) text ready for clipboard\n */\nexport function buildClipboardText(params: CopyParams): string {\n const { rows, columns, selectedIndices, config } = params;\n const delimiter = config.delimiter ?? '\\t';\n const newline = config.newline ?? '\\n';\n\n // Filter to visible columns (not hidden, not internal __ prefixed)\n const visibleColumns = columns.filter((c) => !c.hidden && !c.field.startsWith('__'));\n\n const lines: string[] = [];\n\n // Add header row if configured\n if (config.includeHeaders) {\n const headerCells = visibleColumns.map((c) => {\n const header = c.header || c.field;\n // Quote headers if they contain special characters\n if (header.includes(delimiter) || header.includes(newline) || header.includes('\"')) {\n return `\"${header.replace(/\"/g, '\"\"')}\"`;\n }\n return header;\n });\n lines.push(headerCells.join(delimiter));\n }\n\n // Convert indices to sorted array\n const indices = selectedIndices instanceof Set ? [...selectedIndices] : selectedIndices;\n const sortedIndices = [...indices].sort((a, b) => a - b);\n\n // Build data rows\n for (const idx of sortedIndices) {\n const row = rows[idx];\n if (!row) continue;\n\n const cells = visibleColumns.map((col) =>\n formatCellValue((row as Record<string, unknown>)[col.field], col.field, row, config)\n );\n lines.push(cells.join(delimiter));\n }\n\n return lines.join(newline);\n}\n\n/**\n * Copy text to the system clipboard.\n *\n * Uses the modern Clipboard API when available, with fallback\n * to execCommand for older browsers.\n *\n * @param text - The text to copy\n * @returns Promise resolving to true if successful, false otherwise\n */\nexport async function copyToClipboard(text: string): Promise<boolean> {\n try {\n await navigator.clipboard.writeText(text);\n return true;\n } catch {\n // Fallback for older browsers or when Clipboard API is not available\n const textarea = document.createElement('textarea');\n textarea.value = text;\n textarea.style.position = 'fixed';\n textarea.style.opacity = '0';\n textarea.style.pointerEvents = 'none';\n document.body.appendChild(textarea);\n textarea.select();\n const success = document.execCommand('copy');\n document.body.removeChild(textarea);\n return success;\n }\n}\n","/**\n * Clipboard Paste Logic\n *\n * Pure functions for reading and parsing clipboard data.\n */\n\nimport type { ClipboardConfig } from './types';\n\n/**\n * Parse clipboard text into a 2D array of cell values.\n *\n * Handles:\n * - Quoted values (with escaped double quotes \"\")\n * - Multi-line quoted values (newlines within quotes are preserved)\n * - Custom delimiters and newlines\n * - Empty lines (filtered out only if they contain no data)\n *\n * @param text - Raw clipboard text\n * @param config - Clipboard configuration\n * @returns 2D array where each sub-array is a row of cell values\n */\nexport function parseClipboardText(text: string, config: ClipboardConfig): string[][] {\n const delimiter = config.delimiter ?? '\\t';\n const newline = config.newline ?? '\\n';\n\n // Handle Windows CRLF line endings\n const normalizedText = text.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n');\n\n // Parse the entire text handling quoted fields that may span multiple lines\n const rows: string[][] = [];\n let currentRow: string[] = [];\n let currentCell = '';\n let inQuotes = false;\n\n for (let i = 0; i < normalizedText.length; i++) {\n const char = normalizedText[i];\n\n if (char === '\"' && !inQuotes) {\n // Start of quoted field\n inQuotes = true;\n } else if (char === '\"' && inQuotes) {\n // Check for escaped quote (\"\")\n if (normalizedText[i + 1] === '\"') {\n currentCell += '\"';\n i++; // Skip the second quote\n } else {\n // End of quoted field\n inQuotes = false;\n }\n } else if (char === delimiter && !inQuotes) {\n // Field separator\n currentRow.push(currentCell);\n currentCell = '';\n } else if (char === newline && !inQuotes) {\n // Row separator (only if not inside quotes)\n currentRow.push(currentCell);\n currentCell = '';\n // Only add non-empty rows (at least one non-empty cell or multiple cells)\n if (currentRow.length > 1 || currentRow.some((c) => c.trim() !== '')) {\n rows.push(currentRow);\n }\n currentRow = [];\n } else {\n currentCell += char;\n }\n }\n\n // Handle the last cell and row\n currentRow.push(currentCell);\n if (currentRow.length > 1 || currentRow.some((c) => c.trim() !== '')) {\n rows.push(currentRow);\n }\n\n return rows;\n}\n\n/**\n * Read text from the system clipboard.\n *\n * Uses the modern Clipboard API. Returns empty string if\n * the API is not available or permission is denied.\n *\n * @returns Promise resolving to clipboard text or empty string\n */\nexport async function readFromClipboard(): Promise<string> {\n try {\n return await navigator.clipboard.readText();\n } catch {\n // Permission denied or API not available\n return '';\n }\n}\n","/**\n * Clipboard Plugin (Class-based)\n *\n * Provides copy/paste functionality for tbw-grid.\n * Supports Ctrl+C/Cmd+C for copying and Ctrl+V/Cmd+V for pasting.\n *\n * **With Selection plugin:** Copy selected rows as a range\n * - includeHeaders: true → adds header row at top\n * - includeHeaders: false → data rows only\n *\n * **Without Selection plugin:** Copy focused cell only\n * - includeHeaders: true → \"Header: value\" format\n * - includeHeaders: false → value only\n */\n\nimport { BaseGridPlugin } from '../../core/plugin/base-plugin';\nimport { buildClipboardText, copyToClipboard } from './copy';\nimport { parseClipboardText, readFromClipboard } from './paste';\nimport type { ClipboardConfig, CopyDetail, PasteDetail } from './types';\n\n/**\n * Clipboard Plugin for tbw-grid\n *\n * @example\n * ```ts\n * new ClipboardPlugin({ includeHeaders: true })\n * ```\n */\nexport class ClipboardPlugin extends BaseGridPlugin<ClipboardConfig> {\n readonly name = 'clipboard';\n override readonly version = '1.0.0';\n\n protected override get defaultConfig(): Partial<ClipboardConfig> {\n return {\n includeHeaders: false,\n delimiter: '\\t',\n newline: '\\n',\n quoteStrings: false,\n };\n }\n\n // #region Internal State\n /** The last copied text (for reference/debugging) */\n private lastCopied: { text: string; timestamp: number } | null = null;\n // #endregion\n\n // #region Lifecycle\n\n override detach(): void {\n this.lastCopied = null;\n }\n // #endregion\n\n // #region Event Handlers\n\n override onKeyDown(event: KeyboardEvent): boolean {\n const isCopy = (event.ctrlKey || event.metaKey) && event.key === 'c';\n const isPaste = (event.ctrlKey || event.metaKey) && event.key === 'v';\n\n if (isCopy) {\n this.#handleCopy(event.target as HTMLElement);\n return true; // Prevent default browser behavior\n }\n\n if (isPaste) {\n this.#handlePaste();\n return true; // Prevent default browser behavior\n }\n\n return false;\n }\n // #endregion\n\n // #region Private Methods\n\n /**\n * Handle copy operation\n */\n #handleCopy(target: HTMLElement): void {\n // Try to get selection from selection plugin (if available)\n // Use dynamic import to avoid circular dependency issues\n const selectionPlugin = this.#getSelectionPlugin();\n\n // Check for different selection types\n const selectedRows = selectionPlugin?.getSelectedRows() ?? [];\n const hasRowSelection = selectedRows.length > 0;\n const ranges = selectionPlugin?.getRanges() ?? [];\n const hasRangeSelection = ranges.length > 0;\n const hasCellSelection = selectionPlugin?.getSelectedCell() != null;\n\n let text: string;\n let rowCount: number;\n let columnCount: number;\n\n if (hasRowSelection && selectionPlugin) {\n // Row selection mode - copy full rows\n text = buildClipboardText({\n rows: this.rows as unknown[],\n columns: [...this.columns],\n selectedIndices: selectedRows,\n config: this.config,\n });\n rowCount = selectedRows.length;\n columnCount = this.columns.filter((c) => !c.hidden && !c.field.startsWith('__')).length;\n } else if (hasRangeSelection && selectionPlugin) {\n // Range selection mode - copy rectangular range (use last range as active)\n const range = ranges[ranges.length - 1];\n const result = this.#buildRangeText({\n startRow: range.from.row,\n startCol: range.from.col,\n endRow: range.to.row,\n endCol: range.to.col,\n });\n text = result.text;\n rowCount = result.rowCount;\n columnCount = result.columnCount;\n } else if (hasCellSelection && selectionPlugin) {\n // Cell selection mode - copy single cell\n const cell = selectionPlugin.getSelectedCell()!;\n const result = this.#buildCellText(cell.row, cell.col);\n if (!result) return;\n text = result.text;\n rowCount = 1;\n columnCount = 1;\n } else {\n // Fallback: try to find focused cell from DOM\n const result = this.#buildSingleCellText(target);\n if (!result) return;\n text = result.text;\n rowCount = 1;\n columnCount = 1;\n }\n\n copyToClipboard(text).then(() => {\n this.lastCopied = { text, timestamp: Date.now() };\n this.emit<CopyDetail>('copy', { text, rowCount, columnCount });\n });\n }\n\n /**\n * Handle paste operation\n */\n #handlePaste(): void {\n readFromClipboard().then((text) => {\n if (!text) return;\n const parsed = parseClipboardText(text, this.config);\n this.emit<PasteDetail>('paste', { rows: parsed, text });\n });\n }\n\n /**\n * Get the selection plugin instance if available.\n */\n #getSelectionPlugin(): SelectionPluginInterface | undefined {\n // Dynamically get the SelectionPlugin class to avoid import order issues\n try {\n // Use getPlugin with the class - this requires the class to be imported\n // For now, we'll use a duck-typing approach via the grid's plugin registry\n const grid = this.grid as any;\n if (grid?._plugins) {\n for (const plugin of grid._plugins) {\n if (plugin.name === 'selection') {\n return plugin as SelectionPluginInterface;\n }\n }\n }\n } catch {\n // Selection plugin not available\n }\n return undefined;\n }\n\n /**\n * Build text for a single cell by row/col index.\n */\n #buildCellText(rowIndex: number, colIndex: number): { text: string } | null {\n const rowData = this.rows[rowIndex] as Record<string, unknown> | undefined;\n if (!rowData) return null;\n\n const column = this.columns[colIndex];\n if (!column) return null;\n\n const value = rowData[column.field];\n const header = column.header || column.field;\n\n let text: string;\n if (this.config.includeHeaders) {\n const formattedValue = value == null ? '' : String(value);\n text = `${header}: ${formattedValue}`;\n } else {\n text = value == null ? '' : String(value);\n }\n\n return { text };\n }\n\n /**\n * Build text for a rectangular range of cells.\n */\n #buildRangeText(range: { startRow: number; startCol: number; endRow: number; endCol: number }): {\n text: string;\n rowCount: number;\n columnCount: number;\n } {\n const { startRow, startCol, endRow, endCol } = range;\n const minRow = Math.min(startRow, endRow);\n const maxRow = Math.max(startRow, endRow);\n const minCol = Math.min(startCol, endCol);\n const maxCol = Math.max(startCol, endCol);\n\n const delimiter = this.config.delimiter ?? '\\t';\n const newline = this.config.newline ?? '\\n';\n const lines: string[] = [];\n\n // Get columns in the range\n const rangeColumns = this.columns.slice(minCol, maxCol + 1);\n\n // Add header row if configured\n if (this.config.includeHeaders) {\n const headerCells = rangeColumns.map((c) => c.header || c.field);\n lines.push(headerCells.join(delimiter));\n }\n\n // Add data rows\n for (let r = minRow; r <= maxRow; r++) {\n const rowData = this.rows[r] as Record<string, unknown> | undefined;\n if (!rowData) continue;\n\n const cells = rangeColumns.map((col) => {\n const value = rowData[col.field];\n if (value == null) return '';\n if (value instanceof Date) return value.toISOString();\n return String(value);\n });\n lines.push(cells.join(delimiter));\n }\n\n return {\n text: lines.join(newline),\n rowCount: maxRow - minRow + 1,\n columnCount: maxCol - minCol + 1,\n };\n }\n\n /**\n * Build text for a single focused cell from DOM.\n * Used when selection plugin is not available or no rows are selected.\n */\n #buildSingleCellText(target: HTMLElement): { text: string; field: string; value: unknown } | null {\n // Find the cell element - cells use data-field-cache for the field name\n const cell = target.closest('[data-field-cache]') as HTMLElement | null;\n if (!cell) return null;\n\n const field = cell.dataset.fieldCache;\n if (!field) return null;\n\n // Get row index from data-row attribute on the cell\n const rowIndexStr = cell.dataset.row;\n if (!rowIndexStr) return null;\n\n const rowIndex = parseInt(rowIndexStr, 10);\n if (isNaN(rowIndex)) return null;\n\n const rowData = this.rows[rowIndex] as Record<string, unknown> | undefined;\n if (!rowData) return null;\n\n const value = rowData[field];\n const column = this.columns.find((c) => c.field === field);\n const header = column?.header || field;\n\n // Format the text based on includeHeaders config\n let text: string;\n if (this.config.includeHeaders) {\n // Format: \"{header}: {value}\"\n const formattedValue = value == null ? '' : String(value);\n text = `${header}: ${formattedValue}`;\n } else {\n // Just the value\n text = value == null ? '' : String(value);\n }\n\n return { text, field, value };\n }\n // #endregion\n\n // #region Public API\n\n /**\n * Copy currently selected rows to clipboard.\n * @returns The copied text\n */\n async copy(): Promise<string> {\n const selectionPlugin = this.#getSelectionPlugin();\n const indices = selectionPlugin?.getSelectedRows() ?? [];\n\n const text = buildClipboardText({\n rows: this.rows as unknown[],\n columns: [...this.columns],\n selectedIndices: indices,\n config: this.config,\n });\n\n await copyToClipboard(text);\n this.lastCopied = { text, timestamp: Date.now() };\n return text;\n }\n\n /**\n * Copy specific rows by index to clipboard.\n * @param indices - Array of row indices to copy\n * @returns The copied text\n */\n async copyRows(indices: number[]): Promise<string> {\n const text = buildClipboardText({\n rows: this.rows as unknown[],\n columns: [...this.columns],\n selectedIndices: indices,\n config: this.config,\n });\n\n await copyToClipboard(text);\n this.lastCopied = { text, timestamp: Date.now() };\n return text;\n }\n\n /**\n * Read and parse clipboard content.\n * @returns Parsed 2D array of cell values, or null if clipboard is empty\n */\n async paste(): Promise<string[][] | null> {\n const text = await readFromClipboard();\n if (!text) return null;\n return parseClipboardText(text, this.config);\n }\n\n /**\n * Get the last copied text and timestamp.\n * @returns The last copied info or null\n */\n getLastCopied(): { text: string; timestamp: number } | null {\n return this.lastCopied;\n }\n // #endregion\n}\n\n// #region Internal Types\n\n/**\n * Interface for SelectionPlugin methods we need.\n * This avoids circular imports while providing type safety.\n */\ninterface SelectionPluginInterface {\n name: string;\n /** Get selected row indices (row mode) */\n getSelectedRows(): number[];\n /** Get all selected cell ranges (range mode) */\n getRanges(): Array<{ from: { row: number; col: number }; to: { row: number; col: number } }>;\n /** Get selected cell (cell mode) */\n getSelectedCell(): { row: number; col: number } | null;\n}\n// #endregion\n\n// Re-export types\nexport type { ClipboardConfig, CopyDetail, PasteDetail } from './types';\n","/**\n * Column Virtualization Core Logic\n *\n * Pure functions for horizontal column virtualization operations.\n */\n\nimport type { ColumnConfig } from '../../core/types';\nimport type { ColumnVirtualizationViewport } from './types';\n\n/** Default column width when not specified */\nconst DEFAULT_COLUMN_WIDTH = 100;\n\n/**\n * Parse a column width value to pixels.\n * Handles number (px) and string formats.\n *\n * @param width - The width value from column config\n * @returns Width in pixels\n */\nexport function parseColumnWidth(width: string | number | undefined): number {\n if (width === undefined || width === null) {\n return DEFAULT_COLUMN_WIDTH;\n }\n\n if (typeof width === 'number') {\n return width;\n }\n\n // Handle string values - extract numeric part\n const numeric = parseFloat(width);\n if (!isNaN(numeric)) {\n return numeric;\n }\n\n return DEFAULT_COLUMN_WIDTH;\n}\n\n/**\n * Get array of column widths in pixels.\n *\n * @param columns - Column configurations\n * @returns Array of widths in pixels\n */\nexport function getColumnWidths(columns: readonly ColumnConfig[]): number[] {\n return columns.map((col) => parseColumnWidth(col.width));\n}\n\n/**\n * Compute cumulative left offsets for each column.\n *\n * @param columns - Column configurations\n * @returns Array of left offsets in pixels\n */\nexport function computeColumnOffsets(columns: readonly ColumnConfig[]): number[] {\n const offsets: number[] = [];\n let offset = 0;\n\n for (const col of columns) {\n offsets.push(offset);\n offset += parseColumnWidth(col.width);\n }\n\n return offsets;\n}\n\n/**\n * Compute total width of all columns.\n *\n * @param columns - Column configurations\n * @returns Total width in pixels\n */\nexport function computeTotalWidth(columns: readonly ColumnConfig[]): number {\n return columns.reduce((sum, col) => sum + parseColumnWidth(col.width), 0);\n}\n\n/**\n * Find the visible column range based on scroll position.\n * Uses binary search for efficient lookup in large column sets.\n *\n * @param scrollLeft - Current horizontal scroll position\n * @param viewportWidth - Width of the visible viewport\n * @param columnOffsets - Array of column left offsets\n * @param columnWidths - Array of column widths\n * @param overscan - Number of extra columns to render on each side\n * @returns Viewport information with visible column indices\n */\nexport function getVisibleColumnRange(\n scrollLeft: number,\n viewportWidth: number,\n columnOffsets: number[],\n columnWidths: number[],\n overscan: number\n): ColumnVirtualizationViewport {\n const columnCount = columnOffsets.length;\n\n if (columnCount === 0) {\n return { startCol: 0, endCol: 0, visibleColumns: [] };\n }\n\n // Binary search for first visible column\n let startCol = binarySearchFirstVisible(scrollLeft, columnOffsets, columnWidths);\n startCol = Math.max(0, startCol - overscan);\n\n // Find last visible column (without overscan first)\n const rightEdge = scrollLeft + viewportWidth;\n let endCol = startCol;\n\n for (let i = startCol; i < columnCount; i++) {\n if (columnOffsets[i] >= rightEdge) {\n endCol = i - 1;\n break;\n }\n endCol = i;\n }\n\n // Apply overscan to end (only once)\n endCol = Math.min(columnCount - 1, endCol + overscan);\n\n // Build array of visible column indices\n const visibleColumns: number[] = [];\n for (let i = startCol; i <= endCol; i++) {\n visibleColumns.push(i);\n }\n\n return { startCol, endCol, visibleColumns };\n}\n\n/**\n * Binary search to find the first column that is visible.\n *\n * @param scrollLeft - Current scroll position\n * @param columnOffsets - Array of column offsets\n * @param columnWidths - Array of column widths\n * @returns Index of first visible column\n */\nfunction binarySearchFirstVisible(scrollLeft: number, columnOffsets: number[], columnWidths: number[]): number {\n let low = 0;\n let high = columnOffsets.length - 1;\n\n while (low < high) {\n const mid = Math.floor((low + high) / 2);\n const colRight = columnOffsets[mid] + columnWidths[mid];\n\n if (colRight <= scrollLeft) {\n low = mid + 1;\n } else {\n high = mid;\n }\n }\n\n return low;\n}\n\n/**\n * Determine if column virtualization should be active.\n *\n * @param columnCount - Number of columns\n * @param threshold - Column count threshold\n * @param autoEnable - Whether auto-enable is configured\n * @returns True if virtualization should be active\n */\nexport function shouldVirtualize(columnCount: number, threshold: number, autoEnable: boolean): boolean {\n if (!autoEnable) return false;\n return columnCount > threshold;\n}\n","/**\n * Column Virtualization Plugin (Class-based)\n *\n * Provides horizontal column virtualization for grids with many columns.\n * Significantly improves rendering performance when dealing with >30 columns.\n */\n\nimport { BaseGridPlugin, ScrollEvent } from '../../core/plugin/base-plugin';\nimport type { ColumnConfig } from '../../core/types';\nimport {\n computeColumnOffsets,\n computeTotalWidth,\n getColumnWidths,\n getVisibleColumnRange,\n shouldVirtualize,\n} from './column-virtualization';\nimport type { ColumnVirtualizationConfig } from './types';\n\n/**\n * Column Virtualization Plugin for tbw-grid\n *\n * @example\n * ```ts\n * new ColumnVirtualizationPlugin({ threshold: 30, overscan: 3 })\n * ```\n */\nexport class ColumnVirtualizationPlugin extends BaseGridPlugin<ColumnVirtualizationConfig> {\n readonly name = 'columnVirtualization';\n override readonly version = '1.0.0';\n\n protected override get defaultConfig(): Partial<ColumnVirtualizationConfig> {\n return {\n autoEnable: true,\n threshold: 30,\n overscan: 3,\n };\n }\n\n // #region Internal State\n private isVirtualized = false;\n private startCol = 0;\n private endCol = 0;\n private scrollLeft = 0;\n private totalWidth = 0;\n private columnWidths: number[] = [];\n private columnOffsets: number[] = [];\n // #endregion\n\n // #region Lifecycle\n\n override attach(grid: import('../../core/plugin/base-plugin').GridElement): void {\n super.attach(grid);\n\n // Initialize state from current columns\n const columns = this.columns;\n this.columnWidths = getColumnWidths(columns);\n this.columnOffsets = computeColumnOffsets(columns);\n this.totalWidth = computeTotalWidth(columns);\n this.endCol = columns.length - 1;\n }\n\n override detach(): void {\n this.columnWidths = [];\n this.columnOffsets = [];\n this.isVirtualized = false;\n this.startCol = 0;\n this.endCol = 0;\n this.scrollLeft = 0;\n this.totalWidth = 0;\n }\n // #endregion\n\n // #region Hooks\n\n override processColumns(columns: readonly ColumnConfig[]): ColumnConfig[] {\n const isVirtualized = shouldVirtualize(columns.length, this.config.threshold ?? 30, this.config.autoEnable ?? true);\n\n // Update state with current column metrics\n this.isVirtualized = isVirtualized ?? false;\n this.columnWidths = getColumnWidths(columns);\n this.columnOffsets = computeColumnOffsets(columns);\n this.totalWidth = computeTotalWidth(columns);\n\n if (!isVirtualized) {\n this.startCol = 0;\n this.endCol = columns.length - 1;\n return [...columns];\n }\n\n // Get viewport width from grid element\n const viewportWidth = (this.grid as unknown as HTMLElement).clientWidth || 800;\n const viewport = getVisibleColumnRange(\n this.scrollLeft,\n viewportWidth,\n this.columnOffsets,\n this.columnWidths,\n this.config.overscan ?? 3,\n );\n\n this.startCol = viewport.startCol;\n this.endCol = viewport.endCol;\n\n // Return only visible columns\n return viewport.visibleColumns.map((i) => columns[i]);\n }\n\n override afterRender(): void {\n if (!this.isVirtualized) return;\n\n const shadowRoot = this.shadowRoot;\n if (!shadowRoot) return;\n\n // Apply left padding to offset scrolled-out columns\n const leftPadding = this.columnOffsets[this.startCol] ?? 0;\n\n const headerRow = shadowRoot.querySelector('.header-row');\n const bodyRows = shadowRoot.querySelectorAll('.data-grid-row');\n\n if (headerRow) {\n (headerRow as HTMLElement).style.paddingLeft = `${leftPadding}px`;\n }\n\n bodyRows.forEach((row) => {\n (row as HTMLElement).style.paddingLeft = `${leftPadding}px`;\n });\n\n // Set total width for horizontal scrolling on the rows container\n const rowsContainer = shadowRoot.querySelector('.rows-viewport .rows');\n if (rowsContainer) {\n (rowsContainer as HTMLElement).style.width = `${this.totalWidth}px`;\n }\n }\n\n override onScroll(event: ScrollEvent): void {\n if (!this.isVirtualized) return;\n\n // Check if horizontal scroll position changed significantly\n const scrollDelta = Math.abs(event.scrollLeft - this.scrollLeft);\n if (scrollDelta < 1) return;\n\n // Update scroll position\n this.scrollLeft = event.scrollLeft;\n\n // Recalculate visible columns and request re-render\n this.requestRender();\n }\n // #endregion\n\n // #region Public API\n\n /**\n * Check if column virtualization is currently active.\n */\n getIsVirtualized(): boolean {\n return this.isVirtualized;\n }\n\n /**\n * Get the current visible column range.\n */\n getVisibleColumnRange(): { start: number; end: number } {\n return { start: this.startCol, end: this.endCol };\n }\n\n /**\n * Scroll the grid to bring a specific column into view.\n * @param columnIndex - Index of the column to scroll to\n */\n scrollToColumn(columnIndex: number): void {\n const offset = this.columnOffsets[columnIndex] ?? 0;\n const gridEl = this.grid as unknown as HTMLElement;\n // Scroll the grid element itself (it's the scroll container)\n gridEl.scrollLeft = offset;\n }\n\n /**\n * Get the left offset for a specific column.\n * @param columnIndex - Index of the column\n */\n getColumnOffset(columnIndex: number): number {\n return this.columnOffsets[columnIndex] ?? 0;\n }\n\n /**\n * Get the total width of all columns.\n */\n getTotalWidth(): number {\n return this.totalWidth;\n }\n // #endregion\n}\n","/**\n * Context Menu Rendering Logic\n *\n * Pure functions for building and positioning context menus.\n */\n\nimport type { IconValue } from '../../core/types';\nimport { DEFAULT_GRID_ICONS } from '../../core/types';\nimport type { ContextMenuItem, ContextMenuParams } from './types';\n\n/**\n * Build the visible menu items by resolving dynamic items and filtering hidden ones.\n *\n * @param items - Menu items configuration (array or factory function)\n * @param params - Context menu parameters for evaluating dynamic properties\n * @returns Filtered array of visible menu items\n */\nexport function buildMenuItems(\n items: ContextMenuItem[] | ((params: ContextMenuParams) => ContextMenuItem[]),\n params: ContextMenuParams\n): ContextMenuItem[] {\n const menuItems = typeof items === 'function' ? items(params) : items;\n\n return menuItems.filter((item) => {\n if (item.hidden === true) return false;\n if (typeof item.hidden === 'function' && item.hidden(params)) return false;\n return true;\n });\n}\n\n/**\n * Check if a menu item is disabled.\n *\n * @param item - The menu item to check\n * @param params - Context menu parameters for evaluating dynamic disabled state\n * @returns True if the item is disabled\n */\nexport function isItemDisabled(item: ContextMenuItem, params: ContextMenuParams): boolean {\n if (item.disabled === true) return true;\n if (typeof item.disabled === 'function') return item.disabled(params);\n return false;\n}\n\n/**\n * Create the menu DOM element from a list of menu items.\n *\n * @param items - Array of menu items to render\n * @param params - Context menu parameters for evaluating dynamic properties\n * @param onAction - Callback when a menu item action is triggered\n * @param submenuArrow - Optional custom submenu arrow icon\n * @returns The created menu element\n */\nexport function createMenuElement(\n items: ContextMenuItem[],\n params: ContextMenuParams,\n onAction: (item: ContextMenuItem) => void,\n submenuArrow: IconValue = DEFAULT_GRID_ICONS.submenuArrow\n): HTMLElement {\n const menu = document.createElement('div');\n menu.className = 'tbw-context-menu';\n menu.setAttribute('role', 'menu');\n\n for (const item of items) {\n if (item.separator) {\n const separator = document.createElement('div');\n separator.className = 'tbw-context-menu-separator';\n separator.setAttribute('role', 'separator');\n menu.appendChild(separator);\n continue;\n }\n\n const menuItem = document.createElement('div');\n menuItem.className = 'tbw-context-menu-item';\n if (item.cssClass) menuItem.classList.add(item.cssClass);\n menuItem.setAttribute('role', 'menuitem');\n menuItem.setAttribute('data-id', item.id);\n\n const disabled = isItemDisabled(item, params);\n if (disabled) {\n menuItem.classList.add('disabled');\n menuItem.setAttribute('aria-disabled', 'true');\n }\n\n if (item.icon) {\n const icon = document.createElement('span');\n icon.className = 'tbw-context-menu-icon';\n icon.innerHTML = item.icon;\n menuItem.appendChild(icon);\n }\n\n const label = document.createElement('span');\n label.className = 'tbw-context-menu-label';\n label.textContent = item.name;\n menuItem.appendChild(label);\n\n if (item.shortcut) {\n const shortcut = document.createElement('span');\n shortcut.className = 'tbw-context-menu-shortcut';\n shortcut.textContent = item.shortcut;\n menuItem.appendChild(shortcut);\n }\n\n if (item.subMenu?.length) {\n const arrow = document.createElement('span');\n arrow.className = 'tbw-context-menu-arrow';\n // Use provided submenu arrow icon (string or HTMLElement)\n if (typeof submenuArrow === 'string') {\n arrow.innerHTML = submenuArrow;\n } else if (submenuArrow instanceof HTMLElement) {\n arrow.appendChild(submenuArrow.cloneNode(true));\n }\n menuItem.appendChild(arrow);\n\n // Add submenu on hover\n menuItem.addEventListener('mouseenter', () => {\n const existingSubMenu = menuItem.querySelector('.tbw-context-menu');\n if (existingSubMenu) return;\n if (!item.subMenu) return;\n\n const subMenuItems = buildMenuItems(item.subMenu, params);\n const subMenu = createMenuElement(subMenuItems, params, onAction, submenuArrow);\n subMenu.classList.add('tbw-context-submenu');\n subMenu.style.position = 'absolute';\n subMenu.style.left = '100%';\n subMenu.style.top = '0';\n menuItem.style.position = 'relative';\n menuItem.appendChild(subMenu);\n });\n\n menuItem.addEventListener('mouseleave', () => {\n const subMenu = menuItem.querySelector('.tbw-context-menu');\n if (subMenu) subMenu.remove();\n });\n }\n\n if (!disabled && item.action && !item.subMenu) {\n menuItem.addEventListener('click', (e) => {\n e.stopPropagation();\n onAction(item);\n });\n }\n\n menu.appendChild(menuItem);\n }\n\n return menu;\n}\n\n/**\n * Position the menu at the given viewport coordinates.\n * Menu is rendered in document.body with fixed positioning for top-layer behavior.\n *\n * @param menu - The menu element to position\n * @param x - Desired X coordinate (viewport)\n * @param y - Desired Y coordinate (viewport)\n */\nexport function positionMenu(menu: HTMLElement, x: number, y: number): void {\n // Use fixed positioning for top-layer behavior\n menu.style.position = 'fixed';\n menu.style.left = `${x}px`;\n menu.style.top = `${y}px`;\n menu.style.visibility = 'hidden';\n menu.style.zIndex = '10000';\n\n // Force layout to get dimensions\n const menuRect = menu.getBoundingClientRect();\n\n // Calculate visible area within viewport\n const viewportWidth = window.innerWidth;\n const viewportHeight = window.innerHeight;\n\n let left = x;\n let top = y;\n\n // Check if menu overflows right edge of viewport\n if (x + menuRect.width > viewportWidth) {\n left = x - menuRect.width;\n }\n // Check if menu overflows bottom edge of viewport\n if (y + menuRect.height > viewportHeight) {\n top = y - menuRect.height;\n }\n\n // Ensure we don't go negative\n left = Math.max(0, left);\n top = Math.max(0, top);\n\n menu.style.left = `${left}px`;\n menu.style.top = `${top}px`;\n menu.style.visibility = 'visible';\n}\n","/**\n * Context Menu Plugin (Class-based)\n *\n * Provides right-click context menu functionality for tbw-grid.\n * Supports custom menu items, submenus, icons, shortcuts, and dynamic item generation.\n */\n\nimport { BaseGridPlugin } from '../../core/plugin/base-plugin';\nimport contextMenuStyles from './context-menu.css?inline';\nimport { buildMenuItems, createMenuElement, positionMenu } from './menu';\nimport type { ContextMenuConfig, ContextMenuItem, ContextMenuParams } from './types';\n\n/** Global click handler reference for cleanup */\nlet globalClickHandler: ((e: Event) => void) | null = null;\n/** Global keydown handler reference for cleanup */\nlet globalKeydownHandler: ((e: KeyboardEvent) => void) | null = null;\n/** Global stylesheet for context menu (injected once) */\nlet globalStyleSheet: HTMLStyleElement | null = null;\n/** Reference count for instances using global handlers */\nlet globalHandlerRefCount = 0;\n\n/** Default menu items when none are configured */\nconst defaultItems: ContextMenuItem[] = [\n {\n id: 'copy',\n name: 'Copy',\n shortcut: 'Ctrl+C',\n action: (params) => {\n const grid = (params as ContextMenuParams & { grid?: { plugins?: { clipboard?: { copy?: () => void } } } }).grid;\n grid?.plugins?.clipboard?.copy?.();\n },\n },\n { separator: true, id: 'sep1', name: '' },\n {\n id: 'export-csv',\n name: 'Export CSV',\n action: (params) => {\n const grid = (params as ContextMenuParams & { grid?: { plugins?: { export?: { exportCsv?: () => void } } } })\n .grid;\n grid?.plugins?.export?.exportCsv?.();\n },\n },\n];\n\n/**\n * Context Menu Plugin for tbw-grid\n *\n * @example\n * ```ts\n * new ContextMenuPlugin({\n * enabled: true,\n * items: [\n * { id: 'edit', name: 'Edit', action: (params) => console.log('Edit', params) },\n * { separator: true, id: 'sep', name: '' },\n * { id: 'delete', name: 'Delete', action: (params) => console.log('Delete', params) },\n * ],\n * })\n * ```\n */\nexport class ContextMenuPlugin extends BaseGridPlugin<ContextMenuConfig> {\n readonly name = 'contextMenu';\n override readonly version = '1.0.0';\n\n protected override get defaultConfig(): Partial<ContextMenuConfig> {\n return {\n items: defaultItems,\n };\n }\n\n // #region Internal State\n private isOpen = false;\n private position = { x: 0, y: 0 };\n private params: ContextMenuParams | null = null;\n private menuElement: HTMLElement | null = null;\n // #endregion\n\n // #region Lifecycle\n\n override attach(grid: import('../../core/plugin/base-plugin').GridElement): void {\n super.attach(grid);\n this.installGlobalHandlers();\n globalHandlerRefCount++;\n }\n\n override detach(): void {\n if (this.menuElement) {\n this.menuElement.remove();\n this.menuElement = null;\n }\n this.isOpen = false;\n this.params = null;\n this.uninstallGlobalHandlers();\n }\n // #endregion\n\n // #region Private Methods\n\n private installGlobalHandlers(): void {\n // Inject global stylesheet for context menu (once)\n // Only inject if we have valid CSS text (Vite's ?inline import)\n // When importing from source without Vite, the import is a module object, not a string\n if (\n !globalStyleSheet &&\n typeof document !== 'undefined' &&\n typeof contextMenuStyles === 'string' &&\n contextMenuStyles\n ) {\n globalStyleSheet = document.createElement('style');\n globalStyleSheet.id = 'tbw-context-menu-styles';\n globalStyleSheet.textContent = contextMenuStyles;\n document.head.appendChild(globalStyleSheet);\n }\n\n // Close menu on click outside\n if (!globalClickHandler) {\n globalClickHandler = () => {\n const menus = document.querySelectorAll('.tbw-context-menu');\n menus.forEach((menu) => menu.remove());\n };\n document.addEventListener('click', globalClickHandler);\n }\n\n // Close on escape\n if (!globalKeydownHandler) {\n globalKeydownHandler = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n const menus = document.querySelectorAll('.tbw-context-menu');\n menus.forEach((menu) => menu.remove());\n }\n };\n document.addEventListener('keydown', globalKeydownHandler);\n }\n }\n\n /**\n * Clean up global handlers when the last instance detaches.\n * Uses reference counting to ensure handlers persist while any grid uses the plugin.\n */\n private uninstallGlobalHandlers(): void {\n globalHandlerRefCount--;\n if (globalHandlerRefCount > 0) return;\n\n // Last instance - clean up all global resources\n if (globalClickHandler) {\n document.removeEventListener('click', globalClickHandler);\n globalClickHandler = null;\n }\n if (globalKeydownHandler) {\n document.removeEventListener('keydown', globalKeydownHandler);\n globalKeydownHandler = null;\n }\n if (globalStyleSheet) {\n globalStyleSheet.remove();\n globalStyleSheet = null;\n }\n }\n // #endregion\n\n // #region Hooks\n\n override afterRender(): void {\n const shadowRoot = this.shadowRoot;\n if (!shadowRoot) return;\n\n const container = shadowRoot.children[0];\n if (!container) return;\n\n // Check if handler already attached\n if (container.getAttribute('data-context-menu-bound') === 'true') return;\n container.setAttribute('data-context-menu-bound', 'true');\n\n container.addEventListener('contextmenu', (e: Event) => {\n const event = e as MouseEvent;\n event.preventDefault();\n\n const target = event.target as HTMLElement;\n const cell = target.closest('[data-row][data-col]');\n const header = target.closest('.header-cell');\n\n let params: ContextMenuParams;\n\n if (cell) {\n const rowIndex = parseInt(cell.getAttribute('data-row') ?? '-1', 10);\n const colIndex = parseInt(cell.getAttribute('data-col') ?? '-1', 10);\n const column = this.columns[colIndex];\n const row = this.rows[rowIndex];\n\n params = {\n row,\n rowIndex,\n column,\n columnIndex: colIndex,\n field: column?.field ?? '',\n value: row?.[column?.field as keyof typeof row] ?? null,\n isHeader: false,\n event,\n };\n } else if (header) {\n const colIndex = parseInt(header.getAttribute('data-col') ?? '-1', 10);\n const column = this.columns[colIndex];\n\n params = {\n row: null,\n rowIndex: -1,\n column,\n columnIndex: colIndex,\n field: column?.field ?? '',\n value: null,\n isHeader: true,\n event,\n };\n } else {\n return;\n }\n\n this.params = params;\n this.position = { x: event.clientX, y: event.clientY };\n\n const items = buildMenuItems(this.config.items ?? defaultItems, params);\n if (!items.length) return;\n\n if (this.menuElement) {\n this.menuElement.remove();\n }\n\n this.menuElement = createMenuElement(\n items,\n params,\n (item) => {\n if (item.action) {\n item.action(params);\n }\n this.menuElement?.remove();\n this.menuElement = null;\n this.isOpen = false;\n },\n this.gridIcons.submenuArrow,\n );\n\n document.body.appendChild(this.menuElement);\n positionMenu(this.menuElement, event.clientX, event.clientY);\n this.isOpen = true;\n\n this.emit('context-menu-open', { params, items });\n });\n }\n // #endregion\n\n // #region Public API\n\n /**\n * Programmatically show the context menu at the specified position.\n * @param x - X coordinate\n * @param y - Y coordinate\n * @param params - Partial context menu parameters\n */\n showMenu(x: number, y: number, params: Partial<ContextMenuParams>): void {\n const fullParams: ContextMenuParams = {\n row: params.row ?? null,\n rowIndex: params.rowIndex ?? -1,\n column: params.column ?? null,\n columnIndex: params.columnIndex ?? -1,\n field: params.field ?? '',\n value: params.value ?? null,\n isHeader: params.isHeader ?? false,\n event: params.event ?? new MouseEvent('contextmenu'),\n };\n\n const items = buildMenuItems(this.config.items ?? defaultItems, fullParams);\n\n if (this.menuElement) {\n this.menuElement.remove();\n }\n\n this.menuElement = createMenuElement(\n items,\n fullParams,\n (item) => {\n if (item.action) item.action(fullParams);\n this.menuElement?.remove();\n this.menuElement = null;\n this.isOpen = false;\n },\n this.gridIcons.submenuArrow,\n );\n\n document.body.appendChild(this.menuElement);\n positionMenu(this.menuElement, x, y);\n this.isOpen = true;\n }\n\n /**\n * Hide the context menu.\n */\n hideMenu(): void {\n if (this.menuElement) {\n this.menuElement.remove();\n this.menuElement = null;\n this.isOpen = false;\n }\n }\n\n /**\n * Check if the context menu is currently open.\n * @returns Whether the menu is open\n */\n isMenuOpen(): boolean {\n return this.isOpen;\n }\n // #endregion\n\n // Styles are injected globally via installGlobalHandlers() since menu renders in document.body\n}\n","/**\n * CSV Export Utilities\n *\n * Functions for building and downloading CSV content.\n */\n\nimport type { ColumnConfig } from '../../core/types';\nimport type { ExportParams } from './types';\n\n/** CSV export options */\nexport interface CsvOptions {\n /** Field delimiter (default: ',') */\n delimiter?: string;\n /** Line separator (default: '\\n') */\n newline?: string;\n /** Whether to quote strings containing special characters (default: true) */\n quoteStrings?: boolean;\n /** Add UTF-8 BOM for Excel compatibility (default: false) */\n bom?: boolean;\n}\n\n/**\n * Format a value for CSV output.\n * Handles null, Date, objects, and strings with special characters.\n */\nexport function formatCsvValue(value: any, quote = true): string {\n if (value == null) return '';\n if (value instanceof Date) return value.toISOString();\n if (typeof value === 'object') return JSON.stringify(value);\n\n const str = String(value);\n\n // Quote if contains special characters (comma, quote, newline)\n if (quote && (str.includes(',') || str.includes('\"') || str.includes('\\n') || str.includes('\\r'))) {\n return `\"${str.replace(/\"/g, '\"\"')}\"`;\n }\n\n return str;\n}\n\n/**\n * Build CSV content from rows and columns.\n */\nexport function buildCsv(rows: any[], columns: ColumnConfig[], params: ExportParams, options: CsvOptions = {}): string {\n const delimiter = options.delimiter ?? ',';\n const newline = options.newline ?? '\\n';\n const lines: string[] = [];\n\n // UTF-8 BOM for Excel compatibility\n const bom = options.bom ? '\\uFEFF' : '';\n\n // Build header row\n if (params.includeHeaders !== false) {\n const headerRow = columns.map((col) => {\n const header = col.header || col.field;\n const processed = params.processHeader ? params.processHeader(header, col.field) : header;\n return formatCsvValue(processed);\n });\n lines.push(headerRow.join(delimiter));\n }\n\n // Build data rows\n for (const row of rows) {\n const cells = columns.map((col) => {\n let value = row[col.field];\n if (params.processCell) {\n value = params.processCell(value, col.field, row);\n }\n return formatCsvValue(value);\n });\n lines.push(cells.join(delimiter));\n }\n\n return bom + lines.join(newline);\n}\n\n/**\n * Download a Blob as a file.\n */\nexport function downloadBlob(blob: Blob, fileName: string): void {\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.download = fileName;\n link.style.display = 'none';\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n URL.revokeObjectURL(url);\n}\n\n/**\n * Download CSV content as a file.\n */\nexport function downloadCsv(content: string, fileName: string): void {\n const blob = new Blob([content], { type: 'text/csv;charset=utf-8;' });\n downloadBlob(blob, fileName);\n}\n","/**\n * Excel Export Utilities\n *\n * Simple Excel XML format export (no external dependencies).\n * Produces XML Spreadsheet 2003 format which opens in Excel.\n */\n\nimport type { ColumnConfig } from '../../core/types';\nimport type { ExportParams } from './types';\nimport { downloadBlob } from './csv';\n\n/**\n * Escape XML special characters.\n */\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n}\n\n/**\n * Build Excel XML content from rows and columns.\n * Uses XML Spreadsheet 2003 format for broad compatibility.\n */\nexport function buildExcelXml(rows: any[], columns: ColumnConfig[], params: ExportParams): string {\n let xml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<?mso-application progid=\"Excel.Sheet\"?>\n<Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\"\n xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\">\n<Worksheet ss:Name=\"Sheet1\">\n<Table>`;\n\n // Build header row\n if (params.includeHeaders !== false) {\n xml += '\\n<Row>';\n for (const col of columns) {\n const header = col.header || col.field;\n const processed = params.processHeader ? params.processHeader(header, col.field) : header;\n xml += `<Cell><Data ss:Type=\"String\">${escapeXml(processed)}</Data></Cell>`;\n }\n xml += '</Row>';\n }\n\n // Build data rows\n for (const row of rows) {\n xml += '\\n<Row>';\n for (const col of columns) {\n let value = row[col.field];\n if (params.processCell) {\n value = params.processCell(value, col.field, row);\n }\n\n // Determine cell type based on value\n let type: 'Number' | 'String' | 'DateTime' = 'String';\n let displayValue = '';\n\n if (value == null) {\n displayValue = '';\n } else if (typeof value === 'number' && !isNaN(value)) {\n type = 'Number';\n displayValue = String(value);\n } else if (value instanceof Date) {\n type = 'DateTime';\n displayValue = value.toISOString();\n } else {\n displayValue = escapeXml(String(value));\n }\n\n xml += `<Cell><Data ss:Type=\"${type}\">${displayValue}</Data></Cell>`;\n }\n xml += '</Row>';\n }\n\n xml += '\\n</Table>\\n</Worksheet>\\n</Workbook>';\n return xml;\n}\n\n/**\n * Download Excel XML content as a file.\n */\nexport function downloadExcel(content: string, fileName: string): void {\n const finalName = fileName.endsWith('.xls') ? fileName : `${fileName}.xls`;\n const blob = new Blob([content], {\n type: 'application/vnd.ms-excel;charset=utf-8;',\n });\n downloadBlob(blob, finalName);\n}\n","/**\n * Export Plugin (Class-based)\n *\n * Provides data export functionality for tbw-grid.\n * Supports CSV, Excel (XML), and JSON formats.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { BaseGridPlugin } from '../../core/plugin/base-plugin';\nimport type { ColumnConfig } from '../../core/types';\nimport { buildCsv, downloadBlob, downloadCsv } from './csv';\nimport { buildExcelXml, downloadExcel } from './excel';\nimport type { ExportCompleteDetail, ExportConfig, ExportFormat, ExportParams } from './types';\n\n/** Selection plugin state interface for type safety */\ninterface SelectionPluginState {\n selected: Set<number>;\n}\n\n/**\n * Export Plugin for tbw-grid\n *\n * @example\n * ```ts\n * new ExportPlugin({\n * enabled: true,\n * fileName: 'my-data',\n * includeHeaders: true,\n * onlyVisible: true,\n * })\n * ```\n */\nexport class ExportPlugin extends BaseGridPlugin<ExportConfig> {\n readonly name = 'export';\n override readonly version = '1.0.0';\n\n protected override get defaultConfig(): Partial<ExportConfig> {\n return {\n fileName: 'export',\n includeHeaders: true,\n onlyVisible: true,\n onlySelected: false,\n };\n }\n\n // #region Internal State\n private isExportingFlag = false;\n private lastExportInfo: { format: ExportFormat; timestamp: Date } | null = null;\n // #endregion\n\n // #region Private Methods\n\n private performExport(format: ExportFormat, params?: Partial<ExportParams>): void {\n const config = this.config;\n\n // Build full params with defaults\n const fullParams: ExportParams = {\n format,\n fileName: params?.fileName ?? config.fileName ?? 'export',\n includeHeaders: params?.includeHeaders ?? config.includeHeaders,\n processCell: params?.processCell,\n processHeader: params?.processHeader,\n columns: params?.columns,\n rowIndices: params?.rowIndices,\n };\n\n // Get columns to export\n let columns = [...this.columns] as ColumnConfig[];\n if (config.onlyVisible) {\n columns = columns.filter((c) => !c.hidden && !c.field.startsWith('__'));\n }\n if (params?.columns) {\n const colSet = new Set(params.columns);\n columns = columns.filter((c) => colSet.has(c.field));\n }\n\n // Get rows to export\n let rows = [...this.rows] as any[];\n if (config.onlySelected) {\n const selectionState = this.getSelectionState();\n if (selectionState?.selected?.size) {\n const sortedIndices = [...selectionState.selected].sort((a, b) => a - b);\n rows = sortedIndices.map((i) => this.rows[i]).filter(Boolean);\n }\n }\n if (params?.rowIndices) {\n rows = params.rowIndices.map((i) => this.rows[i]).filter(Boolean);\n }\n\n this.isExportingFlag = true;\n let fileName = fullParams.fileName!;\n\n try {\n switch (format) {\n case 'csv': {\n const content = buildCsv(rows, columns, fullParams, { bom: true });\n fileName = fileName.endsWith('.csv') ? fileName : `${fileName}.csv`;\n downloadCsv(content, fileName);\n break;\n }\n\n case 'excel': {\n const content = buildExcelXml(rows, columns, fullParams);\n fileName = fileName.endsWith('.xls') ? fileName : `${fileName}.xls`;\n downloadExcel(content, fileName);\n break;\n }\n\n case 'json': {\n const jsonData = rows.map((row) => {\n const obj: Record<string, any> = {};\n for (const col of columns) {\n let value = row[col.field];\n if (fullParams.processCell) {\n value = fullParams.processCell(value, col.field, row);\n }\n obj[col.field] = value;\n }\n return obj;\n });\n const content = JSON.stringify(jsonData, null, 2);\n fileName = fileName.endsWith('.json') ? fileName : `${fileName}.json`;\n const blob = new Blob([content], { type: 'application/json' });\n downloadBlob(blob, fileName);\n break;\n }\n }\n\n this.lastExportInfo = { format, timestamp: new Date() };\n\n this.emit<ExportCompleteDetail>('export-complete', {\n format,\n fileName,\n rowCount: rows.length,\n columnCount: columns.length,\n });\n } finally {\n this.isExportingFlag = false;\n }\n }\n\n private getSelectionState(): SelectionPluginState | null {\n try {\n const grid = this.grid as any;\n return grid?.getPluginState?.('selection') ?? null;\n } catch {\n return null;\n }\n }\n // #endregion\n\n // #region Public API\n\n /**\n * Export data to CSV format.\n * @param params - Optional export parameters\n */\n exportCsv(params?: Partial<ExportParams>): void {\n this.performExport('csv', params);\n }\n\n /**\n * Export data to Excel format (XML Spreadsheet).\n * @param params - Optional export parameters\n */\n exportExcel(params?: Partial<ExportParams>): void {\n this.performExport('excel', params);\n }\n\n /**\n * Export data to JSON format.\n * @param params - Optional export parameters\n */\n exportJson(params?: Partial<ExportParams>): void {\n this.performExport('json', params);\n }\n\n /**\n * Check if an export is currently in progress.\n * @returns Whether export is in progress\n */\n isExporting(): boolean {\n return this.isExportingFlag;\n }\n\n /**\n * Get information about the last export.\n * @returns Export info or null if no export has occurred\n */\n getLastExport(): { format: ExportFormat; timestamp: Date } | null {\n return this.lastExportInfo;\n }\n // #endregion\n}\n","/**\n * Row Virtualization Core Logic\n *\n * Pure functions for vertical row virtualization operations.\n * Manages which rows are rendered based on scroll position and viewport size.\n */\n\n/** Result of computing a virtual window */\nexport interface VirtualWindow {\n /** First row index to render (inclusive) */\n start: number;\n /** Last row index to render (exclusive) */\n end: number;\n /** Pixel offset to apply to the rows container (translateY) */\n offsetY: number;\n /** Total height of the scrollable content */\n totalHeight: number;\n}\n\n/** Parameters for computing the virtual window */\nexport interface VirtualWindowParams {\n /** Total number of rows */\n totalRows: number;\n /** Height of the viewport in pixels */\n viewportHeight: number;\n /** Current scroll top position */\n scrollTop: number;\n /** Height of each row in pixels */\n rowHeight: number;\n /** Number of extra rows to render above/below viewport */\n overscan: number;\n /** Previous scroll position for velocity calculation */\n prevScrollTop?: number;\n}\n\n/**\n * Compute the virtual row window based on scroll position and viewport.\n * Uses directional overscan - renders more rows in the scroll direction.\n *\n * @param params - Parameters for computing the window\n * @returns VirtualWindow with start/end indices and transforms\n */\nexport function computeVirtualWindow(params: VirtualWindowParams): VirtualWindow {\n const { totalRows, viewportHeight, scrollTop, rowHeight, overscan } = params;\n\n // Simple approach: render a large fixed window centered on current position\n // This is more predictable than velocity-based sizing\n const visibleRows = Math.ceil(viewportHeight / rowHeight);\n\n // Render overscan rows in each direction (total window = visible + 2*overscan)\n let start = Math.floor(scrollTop / rowHeight) - overscan;\n if (start < 0) start = 0;\n\n let end = start + visibleRows + overscan * 2;\n if (end > totalRows) end = totalRows;\n\n // Ensure start is adjusted if we hit the end\n if (end === totalRows && start > 0) {\n start = Math.max(0, end - visibleRows - overscan * 2);\n }\n\n return {\n start,\n end,\n offsetY: start * rowHeight,\n totalHeight: totalRows * rowHeight,\n };\n}\n\n/**\n * Determine if virtualization should be bypassed for small datasets.\n * When there are very few items, the overhead of virtualization isn't worth it.\n *\n * @param totalRows - Total number of items\n * @param threshold - Bypass threshold (skip virtualization if totalRows <= threshold)\n * @returns True if virtualization should be bypassed\n */\nexport function shouldBypassVirtualization(totalRows: number, threshold: number): boolean {\n return totalRows <= threshold;\n}\n\n/**\n * Compute the row index from a Y pixel position.\n *\n * @param y - Y position in pixels (relative to content top)\n * @param rowHeight - Height of each row\n * @returns Row index at that position\n */\nexport function getRowIndexFromY(y: number, rowHeight: number): number {\n return Math.floor(y / rowHeight);\n}\n\n/**\n * Compute the Y offset for a given row index.\n *\n * @param rowIndex - Row index\n * @param rowHeight - Height of each row\n * @returns Y position in pixels\n */\nexport function getRowOffsetY(rowIndex: number, rowHeight: number): number {\n return rowIndex * rowHeight;\n}\n","/**\n * Filter Model Core Logic\n *\n * Pure functions for filtering operations.\n */\n\nimport type { FilterModel } from './types';\n\n/**\n * Check if a single row matches a filter condition.\n *\n * @param row - The row data object\n * @param filter - The filter to apply\n * @param caseSensitive - Whether text comparisons are case sensitive\n * @returns True if the row matches the filter\n */\nexport function matchesFilter(row: Record<string, unknown>, filter: FilterModel, caseSensitive = false): boolean {\n const rawValue = row[filter.field];\n\n // Handle blank/notBlank first - these work on null/undefined/empty\n if (filter.operator === 'blank') {\n return rawValue == null || rawValue === '';\n }\n if (filter.operator === 'notBlank') {\n return rawValue != null && rawValue !== '';\n }\n\n // Null/undefined values don't match other filters\n if (rawValue == null) return false;\n\n // Prepare values for comparison\n const stringValue = String(rawValue);\n const compareValue = caseSensitive ? stringValue : stringValue.toLowerCase();\n const filterValue = caseSensitive ? String(filter.value) : String(filter.value).toLowerCase();\n\n switch (filter.operator) {\n // Text operators\n case 'contains':\n return compareValue.includes(filterValue);\n\n case 'notContains':\n return !compareValue.includes(filterValue);\n\n case 'equals':\n return compareValue === filterValue;\n\n case 'notEquals':\n return compareValue !== filterValue;\n\n case 'startsWith':\n return compareValue.startsWith(filterValue);\n\n case 'endsWith':\n return compareValue.endsWith(filterValue);\n\n // Number/Date operators (use raw numeric values)\n case 'lessThan':\n return Number(rawValue) < Number(filter.value);\n\n case 'lessThanOrEqual':\n return Number(rawValue) <= Number(filter.value);\n\n case 'greaterThan':\n return Number(rawValue) > Number(filter.value);\n\n case 'greaterThanOrEqual':\n return Number(rawValue) >= Number(filter.value);\n\n case 'between':\n return Number(rawValue) >= Number(filter.value) && Number(rawValue) <= Number(filter.valueTo);\n\n // Set operators\n case 'in':\n return Array.isArray(filter.value) && filter.value.includes(rawValue);\n\n case 'notIn':\n return Array.isArray(filter.value) && !filter.value.includes(rawValue);\n\n default:\n return true;\n }\n}\n\n/**\n * Filter rows based on multiple filter conditions (AND logic).\n * All filters must match for a row to be included.\n *\n * @param rows - The rows to filter\n * @param filters - Array of filters to apply\n * @param caseSensitive - Whether text comparisons are case sensitive\n * @returns Filtered rows\n */\nexport function filterRows<T extends Record<string, unknown>>(\n rows: T[],\n filters: FilterModel[],\n caseSensitive = false\n): T[] {\n if (!filters.length) return rows;\n return rows.filter((row) => filters.every((f) => matchesFilter(row, f, caseSensitive)));\n}\n\n/**\n * Compute a cache key for a set of filters.\n * Used for memoization of filter results.\n *\n * @param filters - Array of filters\n * @returns Stable string key for the filter set\n */\nexport function computeFilterCacheKey(filters: FilterModel[]): string {\n return JSON.stringify(\n filters.map((f) => ({\n field: f.field,\n operator: f.operator,\n value: f.value,\n valueTo: f.valueTo,\n }))\n );\n}\n\n/**\n * Extract unique values from a field across all rows.\n * Useful for populating \"set\" filter dropdowns.\n *\n * @param rows - The rows to extract values from\n * @param field - The field name\n * @returns Sorted array of unique non-null values\n */\nexport function getUniqueValues<T extends Record<string, unknown>>(rows: T[], field: string): unknown[] {\n const values = new Set<unknown>();\n for (const row of rows) {\n const value = row[field];\n if (value != null) {\n values.add(value);\n }\n }\n return [...values].sort((a, b) => {\n // Handle mixed types gracefully\n if (typeof a === 'number' && typeof b === 'number') {\n return a - b;\n }\n return String(a).localeCompare(String(b));\n });\n}\n","/**\n * Filtering Plugin (Class-based)\n *\n * Provides comprehensive filtering functionality for tbw-grid.\n * Supports text, number, date, set, and boolean filters with caching.\n * Includes UI with filter buttons in headers and dropdown filter panels.\n */\n\nimport { computeVirtualWindow, shouldBypassVirtualization } from '../../core/internal/virtualization';\nimport { BaseGridPlugin, type GridElement } from '../../core/plugin/base-plugin';\nimport type { ColumnConfig, ColumnState } from '../../core/types';\nimport { computeFilterCacheKey, filterRows, getUniqueValues } from './filter-model';\nimport styles from './filtering.css?inline';\nimport filterPanelStyles from './FilteringPlugin.css?inline';\nimport type { FilterChangeDetail, FilterConfig, FilterModel, FilterPanelParams } from './types';\n\n/**\n * Filtering Plugin for tbw-grid\n *\n * @example\n * ```ts\n * new FilteringPlugin({ enabled: true, debounceMs: 300 })\n * ```\n */\nexport class FilteringPlugin extends BaseGridPlugin<FilterConfig> {\n readonly name = 'filtering';\n override readonly version = '1.0.0';\n\n protected override get defaultConfig(): Partial<FilterConfig> {\n return {\n debounceMs: 300,\n caseSensitive: false,\n trimInput: true,\n useWorker: true,\n };\n }\n\n // #region Internal State\n private filters: Map<string, FilterModel> = new Map();\n private cachedResult: unknown[] | null = null;\n private cacheKey: string | null = null;\n private openPanelField: string | null = null;\n private panelElement: HTMLElement | null = null;\n private searchText: Map<string, string> = new Map();\n private excludedValues: Map<string, Set<unknown>> = new Map();\n private panelAbortController: AbortController | null = null; // For panel-scoped listeners\n private globalStylesInjected = false;\n\n // Virtualization constants for filter value list\n private static readonly LIST_ITEM_HEIGHT = 28;\n private static readonly LIST_OVERSCAN = 3;\n private static readonly LIST_BYPASS_THRESHOLD = 50; // Don't virtualize if < 50 items\n // #endregion\n\n // #region Lifecycle\n\n override attach(grid: GridElement): void {\n super.attach(grid);\n this.injectGlobalStyles();\n }\n\n override detach(): void {\n this.filters.clear();\n this.cachedResult = null;\n this.cacheKey = null;\n this.openPanelField = null;\n if (this.panelElement) {\n this.panelElement.remove();\n this.panelElement = null;\n }\n this.searchText.clear();\n this.excludedValues.clear();\n // Abort panel-scoped listeners (document click handler, etc.)\n this.panelAbortController?.abort();\n this.panelAbortController = null;\n }\n // #endregion\n\n // #region Hooks\n\n override processRows(rows: readonly unknown[]): unknown[] {\n const filterList = [...this.filters.values()];\n if (!filterList.length) return [...rows];\n\n // If using async filterHandler, processRows becomes a passthrough\n // Actual filtering happens in applyFiltersAsync and rows are set directly on grid\n if (this.config.filterHandler) {\n // Return cached result if available (set by async handler)\n if (this.cachedResult) return this.cachedResult;\n // Otherwise return rows as-is (filtering happens async)\n return [...rows];\n }\n\n // Check cache\n const newCacheKey = computeFilterCacheKey(filterList);\n if (this.cacheKey === newCacheKey && this.cachedResult) {\n return this.cachedResult;\n }\n\n // Filter rows synchronously (worker support can be added later)\n const result = filterRows([...rows] as Record<string, unknown>[], filterList, this.config.caseSensitive);\n\n // Update cache\n this.cachedResult = result;\n this.cacheKey = newCacheKey;\n\n return result;\n }\n\n override afterRender(): void {\n const shadowRoot = this.shadowRoot;\n if (!shadowRoot) return;\n\n // Find all header cells (using part attribute, not class)\n const headerCells = shadowRoot.querySelectorAll('[part~=\"header-cell\"]');\n headerCells.forEach((cell) => {\n const colIndex = cell.getAttribute('data-col');\n if (colIndex === null) return;\n\n // Use visibleColumns since data-col is the index within _visibleColumns\n const col = this.visibleColumns[parseInt(colIndex, 10)] as ColumnConfig;\n if (!col || col.filterable === false) return;\n\n const field = col.field;\n if (!field) return;\n\n const hasFilter = this.filters.has(field);\n\n // Check if button already exists\n let filterBtn = cell.querySelector('.tbw-filter-btn') as HTMLElement | null;\n\n if (filterBtn) {\n // Update active state of existing button\n filterBtn.classList.toggle('active', hasFilter);\n (cell as HTMLElement).classList.toggle('filtered', hasFilter);\n return;\n }\n\n // Create filter button\n filterBtn = document.createElement('button');\n filterBtn.className = 'tbw-filter-btn';\n filterBtn.setAttribute('aria-label', `Filter ${col.header ?? field}`);\n filterBtn.innerHTML = `<svg viewBox=\"0 0 16 16\" width=\"12\" height=\"12\"><path fill=\"currentColor\" d=\"M6 10.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5z\"/></svg>`;\n\n // Mark button as active if filter exists\n if (hasFilter) {\n filterBtn.classList.add('active');\n (cell as HTMLElement).classList.add('filtered');\n }\n\n filterBtn.addEventListener('click', (e) => {\n e.stopPropagation();\n this.toggleFilterPanel(field, col, filterBtn!);\n });\n\n // Append to header cell\n cell.appendChild(filterBtn);\n });\n }\n // #endregion\n\n // #region Public API\n\n /**\n * Set a filter on a specific field.\n * Pass null to remove the filter.\n */\n setFilter(field: string, filter: Omit<FilterModel, 'field'> | null): void {\n if (filter === null) {\n this.filters.delete(field);\n this.excludedValues.delete(field);\n } else {\n this.filters.set(field, { ...filter, field });\n // Sync excludedValues for set filters so the panel reflects correct state\n if (filter.type === 'set' && filter.operator === 'notIn' && Array.isArray(filter.value)) {\n this.excludedValues.set(field, new Set(filter.value));\n } else if (filter.type === 'set') {\n // Other set operators may have different semantics; clear for safety\n this.excludedValues.delete(field);\n }\n }\n // Invalidate cache\n this.cachedResult = null;\n this.cacheKey = null;\n\n this.emit<FilterChangeDetail>('filter-change', {\n filters: [...this.filters.values()],\n filteredRowCount: 0, // Will be accurate after processRows\n });\n this.requestRender();\n }\n\n /**\n * Get the current filter for a field.\n */\n getFilter(field: string): FilterModel | undefined {\n return this.filters.get(field);\n }\n\n /**\n * Get all active filters.\n */\n getFilters(): FilterModel[] {\n return [...this.filters.values()];\n }\n\n /**\n * Alias for getFilters() to match functional API naming.\n */\n getFilterModel(): FilterModel[] {\n return this.getFilters();\n }\n\n /**\n * Set filters from an array (replaces all existing filters).\n */\n setFilterModel(filters: FilterModel[]): void {\n this.filters.clear();\n this.excludedValues.clear();\n for (const filter of filters) {\n this.filters.set(filter.field, filter);\n // Sync excludedValues for set filters so the panel reflects correct state\n if (filter.type === 'set' && filter.operator === 'notIn' && Array.isArray(filter.value)) {\n this.excludedValues.set(filter.field, new Set(filter.value));\n }\n }\n this.cachedResult = null;\n this.cacheKey = null;\n\n this.emit<FilterChangeDetail>('filter-change', {\n filters: [...this.filters.values()],\n filteredRowCount: 0,\n });\n this.requestRender();\n }\n\n /**\n * Clear all filters.\n */\n clearAllFilters(): void {\n this.filters.clear();\n this.excludedValues.clear();\n this.searchText.clear();\n\n this.applyFiltersInternal();\n }\n\n /**\n * Clear filter for a specific field.\n */\n clearFieldFilter(field: string): void {\n this.filters.delete(field);\n this.excludedValues.delete(field);\n this.searchText.delete(field);\n\n this.applyFiltersInternal();\n }\n\n /**\n * Check if a field has an active filter.\n */\n isFieldFiltered(field: string): boolean {\n return this.filters.has(field);\n }\n\n /**\n * Get the count of filtered rows (from cache).\n */\n getFilteredRowCount(): number {\n return this.cachedResult?.length ?? this.rows.length;\n }\n\n /**\n * Get all active filters (alias for getFilters).\n */\n getActiveFilters(): FilterModel[] {\n return this.getFilters();\n }\n\n /**\n * Get unique values for a field (for set filter dropdowns).\n * Uses sourceRows to include all values regardless of current filter.\n */\n getUniqueValues(field: string): unknown[] {\n return getUniqueValues(this.sourceRows as Record<string, unknown>[], field);\n }\n // #endregion\n\n // #region Private Methods\n\n /**\n * Inject global styles for filter panel (rendered in document.body)\n */\n private injectGlobalStyles(): void {\n if (this.globalStylesInjected) return;\n if (document.getElementById('tbw-filter-panel-styles')) {\n this.globalStylesInjected = true;\n return;\n }\n // Only inject if we have valid CSS text (Vite's ?inline import)\n // When importing from source without Vite, the import is a module object, not a string\n if (typeof filterPanelStyles !== 'string' || !filterPanelStyles) {\n this.globalStylesInjected = true;\n return;\n }\n const style = document.createElement('style');\n style.id = 'tbw-filter-panel-styles';\n style.textContent = filterPanelStyles;\n document.head.appendChild(style);\n this.globalStylesInjected = true;\n }\n\n /**\n * Toggle the filter panel for a field\n */\n private toggleFilterPanel(field: string, column: ColumnConfig, buttonEl: HTMLElement): void {\n // Close if already open\n if (this.openPanelField === field) {\n this.closeFilterPanel();\n return;\n }\n\n // Close any existing panel\n this.closeFilterPanel();\n\n // Create panel\n const panel = document.createElement('div');\n panel.className = 'tbw-filter-panel';\n this.panelElement = panel;\n this.openPanelField = field;\n\n // If using async valuesHandler, show loading state and fetch values\n if (this.config.valuesHandler) {\n panel.innerHTML = '<div class=\"tbw-filter-loading\">Loading...</div>';\n document.body.appendChild(panel);\n this.positionPanel(panel, buttonEl);\n this.setupPanelCloseHandler(panel, buttonEl);\n\n this.config.valuesHandler(field, column).then((values) => {\n // Check if panel is still open for this field\n if (this.openPanelField !== field || !this.panelElement) return;\n panel.innerHTML = '';\n this.renderPanelContent(field, column, panel, values);\n });\n return;\n }\n\n // Sync path: get unique values from local rows\n const uniqueValues = getUniqueValues(this.sourceRows as Record<string, unknown>[], field);\n this.renderPanelContent(field, column, panel, uniqueValues);\n\n // Position and append to body\n document.body.appendChild(panel);\n this.positionPanel(panel, buttonEl);\n this.setupPanelCloseHandler(panel, buttonEl);\n }\n\n /**\n * Render filter panel content with given values\n */\n private renderPanelContent(field: string, column: ColumnConfig, panel: HTMLElement, uniqueValues: unknown[]): void {\n // Get current excluded values or initialize empty\n let excludedSet = this.excludedValues.get(field);\n if (!excludedSet) {\n excludedSet = new Set();\n this.excludedValues.set(field, excludedSet);\n }\n\n // Get current search text\n const currentSearchText = this.searchText.get(field) ?? '';\n\n // Create panel params for custom renderer\n const params: FilterPanelParams = {\n field,\n column,\n uniqueValues,\n excludedValues: excludedSet,\n searchText: currentSearchText,\n applySetFilter: (excluded: unknown[]) => {\n this.applySetFilter(field, excluded);\n this.closeFilterPanel();\n },\n applyTextFilter: (operator, value, valueTo) => {\n this.applyTextFilter(field, operator, value, valueTo);\n this.closeFilterPanel();\n },\n clearFilter: () => {\n this.clearFieldFilter(field);\n this.closeFilterPanel();\n },\n closePanel: () => this.closeFilterPanel(),\n };\n\n // Use custom renderer or default\n // Custom renderer can return undefined to fall back to default panel for specific columns\n let usedCustomRenderer = false;\n if (this.config.filterPanelRenderer) {\n this.config.filterPanelRenderer(panel, params);\n // If renderer added content to panel, it handled rendering\n usedCustomRenderer = panel.children.length > 0;\n }\n if (!usedCustomRenderer) {\n this.renderDefaultFilterPanel(panel, params, uniqueValues, excludedSet);\n }\n }\n\n /**\n * Setup click-outside handler to close the panel\n */\n private setupPanelCloseHandler(panel: HTMLElement, buttonEl: HTMLElement): void {\n // Create abort controller for panel-scoped listeners\n // This allows cleanup when panel closes OR when grid disconnects\n this.panelAbortController = new AbortController();\n\n // Add global click handler to close on outside click\n // Defer to next tick to avoid immediate close from the click that opened the panel\n setTimeout(() => {\n document.addEventListener(\n 'click',\n (e: MouseEvent) => {\n if (!panel.contains(e.target as Node) && e.target !== buttonEl) {\n this.closeFilterPanel();\n }\n },\n { signal: this.panelAbortController?.signal },\n );\n }, 0);\n }\n\n /**\n * Close the filter panel\n */\n private closeFilterPanel(): void {\n if (this.panelElement) {\n this.panelElement.remove();\n this.panelElement = null;\n }\n this.openPanelField = null;\n // Abort panel-scoped listeners (document click handler)\n this.panelAbortController?.abort();\n this.panelAbortController = null;\n }\n\n /**\n * Position the panel below the button\n */\n private positionPanel(panel: HTMLElement, buttonEl: HTMLElement): void {\n const rect = buttonEl.getBoundingClientRect();\n panel.style.position = 'fixed';\n panel.style.top = `${rect.bottom + 4}px`;\n panel.style.left = `${rect.left}px`;\n\n // Adjust if overflows right edge\n requestAnimationFrame(() => {\n const panelRect = panel.getBoundingClientRect();\n if (panelRect.right > window.innerWidth - 8) {\n panel.style.left = `${window.innerWidth - panelRect.width - 8}px`;\n }\n // Adjust if overflows bottom\n if (panelRect.bottom > window.innerHeight - 8) {\n panel.style.top = `${rect.top - panelRect.height - 4}px`;\n }\n });\n }\n\n /**\n * Render the default filter panel content\n */\n private renderDefaultFilterPanel(\n panel: HTMLElement,\n params: FilterPanelParams,\n uniqueValues: unknown[],\n excludedValues: Set<unknown>,\n ): void {\n const { field } = params;\n\n // Search input\n const searchContainer = document.createElement('div');\n searchContainer.className = 'tbw-filter-search';\n\n const searchInput = document.createElement('input');\n searchInput.type = 'text';\n searchInput.placeholder = 'Search...';\n searchInput.className = 'tbw-filter-search-input';\n searchInput.value = this.searchText.get(field) ?? '';\n searchContainer.appendChild(searchInput);\n panel.appendChild(searchContainer);\n\n // Select All tristate checkbox\n const actionsRow = document.createElement('div');\n actionsRow.className = 'tbw-filter-actions';\n\n const selectAllLabel = document.createElement('label');\n selectAllLabel.className = 'tbw-filter-value-item';\n selectAllLabel.style.padding = '0';\n selectAllLabel.style.margin = '0';\n\n const selectAllCheckbox = document.createElement('input');\n selectAllCheckbox.type = 'checkbox';\n selectAllCheckbox.className = 'tbw-filter-checkbox';\n\n const selectAllText = document.createElement('span');\n selectAllText.textContent = 'Select All';\n\n selectAllLabel.appendChild(selectAllCheckbox);\n selectAllLabel.appendChild(selectAllText);\n actionsRow.appendChild(selectAllLabel);\n\n // Update tristate checkbox based on checkState\n const updateSelectAllState = () => {\n const values = [...checkState.values()];\n const allChecked = values.every((v) => v);\n const noneChecked = values.every((v) => !v);\n\n selectAllCheckbox.checked = allChecked;\n selectAllCheckbox.indeterminate = !allChecked && !noneChecked;\n };\n\n // Toggle all on click\n selectAllCheckbox.addEventListener('change', () => {\n const newState = selectAllCheckbox.checked;\n for (const key of checkState.keys()) {\n checkState.set(key, newState);\n }\n updateSelectAllState();\n renderVisibleItems();\n });\n\n panel.appendChild(actionsRow);\n\n // Values container with virtualization support\n const valuesContainer = document.createElement('div');\n valuesContainer.className = 'tbw-filter-values';\n\n // Spacer for virtual height\n const spacer = document.createElement('div');\n spacer.className = 'tbw-filter-values-spacer';\n valuesContainer.appendChild(spacer);\n\n // Content container positioned absolutely\n const contentContainer = document.createElement('div');\n contentContainer.className = 'tbw-filter-values-content';\n valuesContainer.appendChild(contentContainer);\n\n // Track current check state for values (persists across virtualizations)\n const checkState = new Map<string, boolean>();\n uniqueValues.forEach((value) => {\n const key = value == null ? '__null__' : String(value);\n checkState.set(key, !excludedValues.has(value));\n });\n\n // Initialize select all state\n updateSelectAllState();\n\n // Filtered values cache\n let filteredValues: unknown[] = [];\n\n // Create a single checkbox item element\n const createItem = (value: unknown, index: number): HTMLElement => {\n const strValue = value == null ? '(Blank)' : String(value);\n const key = value == null ? '__null__' : String(value);\n\n const item = document.createElement('label');\n item.className = 'tbw-filter-value-item';\n item.style.position = 'absolute';\n item.style.top = `${index * FilteringPlugin.LIST_ITEM_HEIGHT}px`;\n item.style.left = '0';\n item.style.right = '0';\n item.style.height = `${FilteringPlugin.LIST_ITEM_HEIGHT}px`;\n item.style.boxSizing = 'border-box';\n\n const checkbox = document.createElement('input');\n checkbox.type = 'checkbox';\n checkbox.className = 'tbw-filter-checkbox';\n checkbox.checked = checkState.get(key) ?? true;\n checkbox.dataset.value = key;\n\n // Sync check state on change and update tristate checkbox\n checkbox.addEventListener('change', () => {\n checkState.set(key, checkbox.checked);\n updateSelectAllState();\n });\n\n const label = document.createElement('span');\n label.textContent = strValue;\n\n item.appendChild(checkbox);\n item.appendChild(label);\n return item;\n };\n\n // Render visible items using virtualization\n const renderVisibleItems = () => {\n const totalItems = filteredValues.length;\n const viewportHeight = valuesContainer.clientHeight;\n const scrollTop = valuesContainer.scrollTop;\n\n // Set total height for scrollbar\n spacer.style.height = `${totalItems * FilteringPlugin.LIST_ITEM_HEIGHT}px`;\n\n // Bypass virtualization for small lists\n if (shouldBypassVirtualization(totalItems, FilteringPlugin.LIST_BYPASS_THRESHOLD / 3)) {\n contentContainer.innerHTML = '';\n contentContainer.style.transform = 'translateY(0px)';\n filteredValues.forEach((value, idx) => {\n contentContainer.appendChild(createItem(value, idx));\n });\n return;\n }\n\n // Use computeVirtualWindow for real-scroll virtualization\n const window = computeVirtualWindow({\n totalRows: totalItems,\n viewportHeight,\n scrollTop,\n rowHeight: FilteringPlugin.LIST_ITEM_HEIGHT,\n overscan: FilteringPlugin.LIST_OVERSCAN,\n });\n\n // Position content container\n contentContainer.style.transform = `translateY(${window.offsetY}px)`;\n\n // Clear and render visible items\n contentContainer.innerHTML = '';\n for (let i = window.start; i < window.end; i++) {\n contentContainer.appendChild(createItem(filteredValues[i], i - window.start));\n }\n };\n\n // Filter and re-render values\n const renderValues = (filterText: string) => {\n const lowerFilter = filterText.toLowerCase();\n\n // Filter the unique values\n filteredValues = uniqueValues.filter((value) => {\n const strValue = value == null ? '(Blank)' : String(value);\n return !filterText || strValue.toLowerCase().includes(lowerFilter);\n });\n\n if (filteredValues.length === 0) {\n spacer.style.height = '0px';\n contentContainer.innerHTML = '';\n const noMatch = document.createElement('div');\n noMatch.className = 'tbw-filter-no-match';\n noMatch.textContent = 'No matching values';\n contentContainer.appendChild(noMatch);\n return;\n }\n\n renderVisibleItems();\n };\n\n // Scroll handler for virtualization\n valuesContainer.addEventListener(\n 'scroll',\n () => {\n if (filteredValues.length > 0) {\n renderVisibleItems();\n }\n },\n { passive: true },\n );\n\n renderValues(searchInput.value);\n panel.appendChild(valuesContainer);\n\n // Debounced search\n let debounceTimer: ReturnType<typeof setTimeout>;\n searchInput.addEventListener('input', () => {\n clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => {\n this.searchText.set(field, searchInput.value);\n renderValues(searchInput.value);\n }, this.config.debounceMs ?? 150);\n });\n\n // Apply/Clear buttons\n const buttonRow = document.createElement('div');\n buttonRow.className = 'tbw-filter-buttons';\n\n const applyBtn = document.createElement('button');\n applyBtn.className = 'tbw-filter-apply-btn';\n applyBtn.textContent = 'Apply';\n applyBtn.addEventListener('click', () => {\n // Read from checkState map (works with virtualization)\n const excluded: unknown[] = [];\n for (const [key, isChecked] of checkState) {\n if (!isChecked) {\n if (key === '__null__') {\n excluded.push(null);\n } else {\n // Try to match original value type\n const original = uniqueValues.find((v) => String(v) === key);\n excluded.push(original !== undefined ? original : key);\n }\n }\n }\n params.applySetFilter(excluded);\n });\n buttonRow.appendChild(applyBtn);\n\n const clearBtn = document.createElement('button');\n clearBtn.className = 'tbw-filter-clear-btn';\n clearBtn.textContent = 'Clear Filter';\n clearBtn.addEventListener('click', () => {\n params.clearFilter();\n });\n buttonRow.appendChild(clearBtn);\n\n panel.appendChild(buttonRow);\n }\n\n /**\n * Apply a set filter (exclude values)\n */\n private applySetFilter(field: string, excluded: unknown[]): void {\n // Store excluded values\n this.excludedValues.set(field, new Set(excluded));\n\n if (excluded.length === 0) {\n // No exclusions = no filter\n this.filters.delete(field);\n } else {\n // Create \"notIn\" filter\n this.filters.set(field, {\n field,\n type: 'set',\n operator: 'notIn',\n value: excluded,\n });\n }\n\n this.applyFiltersInternal();\n }\n\n /**\n * Apply a text filter\n */\n private applyTextFilter(field: string, operator: FilterModel['operator'], value: string, valueTo?: string): void {\n this.filters.set(field, {\n field,\n type: 'text',\n operator,\n value,\n valueTo,\n });\n\n this.applyFiltersInternal();\n }\n\n /**\n * Internal method to apply filters (sync or async based on config)\n */\n private applyFiltersInternal(): void {\n this.cachedResult = null;\n this.cacheKey = null;\n\n const filterList = [...this.filters.values()];\n\n // If using async filterHandler, delegate to server\n if (this.config.filterHandler) {\n const gridEl = this.grid as unknown as Element;\n gridEl.setAttribute('aria-busy', 'true');\n\n const result = this.config.filterHandler(filterList, this.sourceRows as unknown[]);\n\n // Handle async or sync result\n const handleResult = (rows: unknown[]) => {\n gridEl.removeAttribute('aria-busy');\n this.cachedResult = rows;\n\n // Update grid rows directly for async filtering\n (this.grid as unknown as { rows: unknown[] }).rows = rows;\n\n this.emit<FilterChangeDetail>('filter-change', {\n filters: filterList,\n filteredRowCount: rows.length,\n });\n\n // Trigger afterRender to update filter button active state\n this.requestRender();\n };\n\n if (result && typeof (result as Promise<unknown[]>).then === 'function') {\n (result as Promise<unknown[]>).then(handleResult);\n } else {\n handleResult(result as unknown[]);\n }\n return;\n }\n\n // Sync path: emit event and re-render (processRows will handle filtering)\n this.emit<FilterChangeDetail>('filter-change', {\n filters: filterList,\n filteredRowCount: 0,\n });\n this.requestRender();\n }\n // #endregion\n\n // #region Column State Hooks\n\n /**\n * Return filter state for a column if it has an active filter.\n */\n override getColumnState(field: string): Partial<ColumnState> | undefined {\n const filterModel = this.filters.get(field);\n if (!filterModel) return undefined;\n\n return {\n filter: {\n type: filterModel.type,\n operator: filterModel.operator,\n value: filterModel.value,\n valueTo: filterModel.valueTo,\n },\n };\n }\n\n /**\n * Apply filter state from column state.\n */\n override applyColumnState(field: string, state: ColumnState): void {\n // Only process if the column has filter state\n if (!state.filter) {\n this.filters.delete(field);\n return;\n }\n\n // Reconstruct the FilterModel from the stored state\n const filterModel: FilterModel = {\n field,\n type: state.filter.type,\n operator: state.filter.operator as FilterModel['operator'],\n value: state.filter.value,\n valueTo: state.filter.valueTo,\n };\n\n this.filters.set(field, filterModel);\n // Invalidate cache so filter is reapplied\n this.cachedResult = null;\n this.cacheKey = null;\n }\n // #endregion\n\n // #region Styles\n\n override readonly styles = styles;\n // #endregion\n}\n","/**\n * Column Groups Core Logic\n *\n * Pure functions for computing and managing column header groups.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { ColumnConfig } from '../../core/types';\nimport type { ColumnGroup, ColumnGroupInternal } from './types';\n\n/**\n * Compute column groups from column configuration.\n * Handles explicit groups (via column.group) and creates implicit groups for ungrouped columns.\n *\n * @param columns - Array of column configurations\n * @returns Array of column groups, or empty if no meaningful groups\n */\nexport function computeColumnGroups<T>(columns: ColumnConfig<T>[]): ColumnGroup<T>[] {\n if (!columns.length) return [];\n\n const explicitMap = new Map<string, ColumnGroupInternal<T>>();\n const groupsOrdered: ColumnGroupInternal<T>[] = [];\n\n // Helper to push unnamed implicit group for a run of ungrouped columns\n const pushImplicit = (startIdx: number, cols: ColumnConfig<T>[]) => {\n if (!cols.length) return;\n // Merge with previous implicit group if adjacent to reduce noise\n const prev = groupsOrdered[groupsOrdered.length - 1];\n if (prev && prev.implicit && prev.firstIndex + prev.columns.length === startIdx) {\n prev.columns.push(...cols);\n return;\n }\n groupsOrdered.push({\n id: '__implicit__' + startIdx,\n label: undefined,\n columns: cols,\n firstIndex: startIdx,\n implicit: true,\n });\n };\n\n let run: ColumnConfig<T>[] = [];\n let runStart = 0;\n\n columns.forEach((col, idx) => {\n const g: any = (col as any).group;\n if (!g) {\n if (run.length === 0) runStart = idx;\n run.push(col);\n return;\n }\n // Close any pending implicit run\n if (run.length) {\n pushImplicit(runStart, run.slice());\n run = [];\n }\n const id = typeof g === 'string' ? g : g.id;\n let group = explicitMap.get(id);\n if (!group) {\n group = {\n id,\n label: typeof g === 'string' ? undefined : g.label,\n columns: [],\n firstIndex: idx,\n };\n explicitMap.set(id, group);\n groupsOrdered.push(group);\n }\n group.columns.push(col);\n });\n\n // Trailing implicit run\n if (run.length) pushImplicit(runStart, run);\n\n // If we only have a single implicit group covering all columns, treat as no groups\n if (\n groupsOrdered.length === 1 &&\n groupsOrdered[0].implicit &&\n groupsOrdered[0].columns.length === columns.length\n ) {\n return [];\n }\n\n return groupsOrdered as ColumnGroup<T>[];\n}\n\n/**\n * Apply CSS classes to header cells based on their group membership.\n *\n * @param headerRowEl - The header row element\n * @param groups - The computed column groups\n * @param columns - The column configurations\n */\nexport function applyGroupedHeaderCellClasses(\n headerRowEl: HTMLElement | null,\n groups: ColumnGroup[],\n columns: ColumnConfig<any>[]\n): void {\n if (!groups.length || !headerRowEl) return;\n\n const fieldToGroup = new Map<string, string>();\n for (const g of groups) {\n for (const c of g.columns) {\n if ((c as any)?.field) {\n fieldToGroup.set((c as any).field, g.id);\n }\n }\n }\n\n const headerCells = Array.from(headerRowEl.querySelectorAll('.cell[data-field]')) as HTMLElement[];\n headerCells.forEach((cell) => {\n const f = cell.getAttribute('data-field') || '';\n const gid = fieldToGroup.get(f);\n if (gid) {\n cell.classList.add('grouped');\n if (!cell.getAttribute('data-group')) {\n cell.setAttribute('data-group', gid);\n }\n }\n });\n\n // Mark group end cells for styling\n for (const g of groups) {\n const last = g.columns[g.columns.length - 1];\n const cell = headerCells.find((c) => c.getAttribute('data-field') === (last as any).field);\n if (cell) cell.classList.add('group-end');\n }\n}\n\n/**\n * Build the group header row element.\n *\n * @param groups - The computed column groups\n * @param columns - The column configurations\n * @returns The group header row element, or null if no groups\n */\nexport function buildGroupHeaderRow(\n groups: ColumnGroup[],\n columns: ColumnConfig<any>[]\n): HTMLElement | null {\n if (groups.length === 0) return null;\n\n const groupRow = document.createElement('div');\n groupRow.className = 'header-group-row';\n groupRow.setAttribute('role', 'row');\n\n for (const g of groups) {\n const startIndex =\n g.firstIndex != null\n ? g.firstIndex\n : columns.findIndex((c) => (g.columns as any[]).includes(c));\n\n const isImplicit = String(g.id).startsWith('__implicit__');\n const label = isImplicit ? '' : g.label || g.id;\n\n const cell = document.createElement('div');\n cell.className = 'cell header-group-cell';\n if (isImplicit) cell.classList.add('implicit-group');\n cell.setAttribute('data-group', String(g.id));\n cell.style.gridColumn = `${startIndex + 1} / span ${g.columns.length}`;\n cell.textContent = label;\n groupRow.appendChild(cell);\n }\n\n return groupRow;\n}\n\n/**\n * Check if any columns have group configuration.\n *\n * @param columns - The column configurations\n * @returns True if at least one column has a group\n */\nexport function hasColumnGroups(columns: ColumnConfig<any>[]): boolean {\n return columns.some((col) => (col as any).group != null);\n}\n\n/**\n * Get group ID for a specific column.\n *\n * @param column - The column configuration\n * @returns The group ID, or undefined if not grouped\n */\nexport function getColumnGroupId(column: ColumnConfig<any>): string | undefined {\n const g = (column as any).group;\n if (!g) return undefined;\n return typeof g === 'string' ? g : g.id;\n}\n","/**\n * Column Groups Plugin (Class-based)\n *\n * Enables multi-level column header grouping.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { BaseGridPlugin } from '../../core/plugin/base-plugin';\nimport type { ColumnConfig } from '../../core/types';\nimport {\n applyGroupedHeaderCellClasses,\n buildGroupHeaderRow,\n computeColumnGroups,\n hasColumnGroups,\n} from './grouping-columns';\nimport styles from './grouping-columns.css?inline';\nimport type { ColumnGroup, GroupingColumnsConfig } from './types';\n\n/**\n * Column Groups Plugin for tbw-grid\n *\n * @example\n * ```ts\n * new GroupingColumnsPlugin({\n * enabled: true,\n * showGroupBorders: true,\n * })\n * ```\n */\nexport class GroupingColumnsPlugin extends BaseGridPlugin<GroupingColumnsConfig> {\n readonly name = 'groupingColumns';\n override readonly version = '1.0.0';\n\n protected override get defaultConfig(): Partial<GroupingColumnsConfig> {\n return {\n showGroupBorders: true,\n };\n }\n\n // #region Internal State\n private groups: ColumnGroup[] = [];\n private isActive = false;\n // #endregion\n\n // #region Lifecycle\n\n override detach(): void {\n this.groups = [];\n this.isActive = false;\n }\n // #endregion\n\n // #region Static Detection\n\n /**\n * Auto-detect column groups from column configuration.\n * Detects both inline `column.group` properties and declarative `columnGroups` config.\n */\n static detect(rows: readonly any[], config: any): boolean {\n // Check for declarative columnGroups in config\n if (config?.columnGroups && Array.isArray(config.columnGroups) && config.columnGroups.length > 0) {\n return true;\n }\n // Check for inline group properties on columns\n const columns = config?.columns;\n if (!Array.isArray(columns)) return false;\n return hasColumnGroups(columns);\n }\n // #endregion\n\n // #region Hooks\n\n override processColumns(columns: readonly ColumnConfig[]): ColumnConfig[] {\n // First, check if gridConfig.columnGroups is defined and apply to columns\n const columnGroups = this.grid?.gridConfig?.columnGroups;\n let processedColumns: ColumnConfig[];\n\n if (columnGroups && Array.isArray(columnGroups) && columnGroups.length > 0) {\n // Build a map of field -> group info from the declarative config\n const fieldToGroup = new Map<string, { id: string; label: string }>();\n for (const group of columnGroups) {\n for (const field of group.children) {\n fieldToGroup.set(field, { id: group.id, label: group.header });\n }\n }\n\n // Apply group property to columns that don't already have one\n processedColumns = columns.map((col) => {\n const groupInfo = fieldToGroup.get(col.field);\n if (groupInfo && !col.group) {\n return { ...col, group: groupInfo };\n }\n return col;\n });\n } else {\n processedColumns = [...columns];\n }\n\n // Compute groups from column definitions (now including applied groups)\n const groups = computeColumnGroups(processedColumns);\n\n if (groups.length === 0) {\n this.isActive = false;\n this.groups = [];\n return processedColumns;\n }\n\n this.isActive = true;\n this.groups = groups;\n\n // Return columns with group info applied\n return processedColumns;\n }\n\n override afterRender(): void {\n if (!this.isActive || this.groups.length === 0) {\n // Remove any existing group header\n const header = this.shadowRoot?.querySelector('.header');\n const existingGroupRow = header?.querySelector('.header-group-row');\n if (existingGroupRow) existingGroupRow.remove();\n return;\n }\n\n const header = this.shadowRoot?.querySelector('.header');\n if (!header) return;\n\n // Remove existing group row if present\n const existingGroupRow = header.querySelector('.header-group-row');\n if (existingGroupRow) existingGroupRow.remove();\n\n // Build and insert group header row\n const groupRow = buildGroupHeaderRow(this.groups, this.columns as ColumnConfig[]);\n if (groupRow) {\n // Toggle border visibility class\n groupRow.classList.toggle('no-borders', !this.config.showGroupBorders);\n\n const headerRow = header.querySelector('.header-row');\n if (headerRow) {\n header.insertBefore(groupRow, headerRow);\n } else {\n header.appendChild(groupRow);\n }\n }\n\n // Apply classes to header cells\n const headerRow = header.querySelector('.header-row') as HTMLElement;\n if (headerRow) {\n // Toggle border visibility on header cells\n headerRow.classList.toggle('no-group-borders', !this.config.showGroupBorders);\n applyGroupedHeaderCellClasses(headerRow, this.groups, this.columns as ColumnConfig[]);\n }\n }\n // #endregion\n\n // #region Public API\n\n /**\n * Check if column groups are active.\n * @returns Whether grouping is active\n */\n isGroupingActive(): boolean {\n return this.isActive;\n }\n\n /**\n * Get the computed column groups.\n * @returns Array of column groups\n */\n getGroups(): ColumnGroup[] {\n return this.groups;\n }\n\n /**\n * Get columns in a specific group.\n * @param groupId - The group ID to find\n * @returns Array of columns in the group\n */\n getGroupColumns(groupId: string): ColumnConfig[] {\n const group = this.groups.find((g) => g.id === groupId);\n return group ? group.columns : [];\n }\n\n /**\n * Refresh column groups (recompute from current columns).\n */\n refresh(): void {\n this.requestRender();\n }\n // #endregion\n\n // #region Styles\n\n override readonly styles = styles;\n // #endregion\n}\n","/**\n * Row Grouping Core Logic\n *\n * Pure functions for building grouped row models and aggregations.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { RenderRow, RowGroupingConfig } from './types';\n\n// Re-export aggregator functions from core for backward compatibility\nexport { getAggregator, listAggregators, registerAggregator, runAggregator } from '../../core/internal/aggregators';\n\ninterface GroupNode {\n key: string; // composite key\n value: any;\n depth: number;\n rows: any[];\n children: Map<string, GroupNode>;\n parent?: GroupNode;\n}\n\ninterface BuildGroupingArgs {\n rows: any[];\n config: RowGroupingConfig;\n expanded: Set<string>;\n}\n\n/**\n * Build a flattened grouping projection (collapsed by default).\n * Returns empty array when groupOn not configured or all rows ungrouped.\n *\n * @param args - The grouping arguments\n * @returns Flattened array of render rows (groups + data rows)\n */\nexport function buildGroupedRowModel({ rows, config, expanded }: BuildGroupingArgs): RenderRow[] {\n const groupOn = config.groupOn;\n if (typeof groupOn !== 'function') {\n return [];\n }\n\n const root: GroupNode = { key: '__root__', value: null, depth: -1, rows: [], children: new Map() };\n\n // Build tree structure\n rows.forEach((r) => {\n let path: any = groupOn(r);\n if (path == null || path === false) path = ['__ungrouped__'];\n else if (!Array.isArray(path)) path = [path];\n\n let parent = root;\n path.forEach((rawVal: any, depthIdx: number) => {\n const seg = rawVal == null ? '∅' : String(rawVal);\n const composite = parent.key === '__root__' ? seg : parent.key + '||' + seg;\n let node = parent.children.get(seg);\n if (!node) {\n node = { key: composite, value: rawVal, depth: depthIdx, rows: [], children: new Map(), parent };\n parent.children.set(seg, node);\n }\n parent = node;\n });\n parent.rows.push(r);\n });\n\n // All ungrouped? treat as no grouping\n if (root.children.size === 1 && root.children.has('__ungrouped__')) {\n const only = root.children.get('__ungrouped__')!;\n if (only.rows.length === rows.length) return [];\n }\n\n // Flatten tree to array\n const flat: RenderRow[] = [];\n const visit = (node: GroupNode) => {\n if (node === root) {\n node.children.forEach((c) => visit(c));\n return;\n }\n\n const isExpanded = expanded.has(node.key);\n flat.push({\n kind: 'group',\n key: node.key,\n value: node.value,\n depth: node.depth,\n rows: node.rows,\n expanded: isExpanded,\n });\n\n if (isExpanded) {\n if (node.children.size) {\n node.children.forEach((c) => visit(c));\n } else {\n node.rows.forEach((r) => flat.push({ kind: 'data', row: r, rowIndex: rows.indexOf(r) }));\n }\n }\n };\n visit(root);\n\n return flat;\n}\n\n/**\n * Toggle expansion state for a group key.\n *\n * @param expandedKeys - Current set of expanded keys\n * @param key - The group key to toggle\n * @returns New set with toggled state\n */\nexport function toggleGroupExpansion(expandedKeys: Set<string>, key: string): Set<string> {\n const newSet = new Set(expandedKeys);\n if (newSet.has(key)) {\n newSet.delete(key);\n } else {\n newSet.add(key);\n }\n return newSet;\n}\n\n/**\n * Expand all groups.\n *\n * @param rows - The flattened render rows\n * @returns Set of all group keys\n */\nexport function expandAllGroups(rows: RenderRow[]): Set<string> {\n const keys = new Set<string>();\n for (const row of rows) {\n if (row.kind === 'group') {\n keys.add(row.key);\n }\n }\n return keys;\n}\n\n/**\n * Collapse all groups.\n *\n * @returns Empty set\n */\nexport function collapseAllGroups(): Set<string> {\n return new Set();\n}\n\n/**\n * Get all group keys from a flattened model.\n *\n * @param rows - The flattened render rows\n * @returns Array of group keys\n */\nexport function getGroupKeys(rows: RenderRow[]): string[] {\n return rows.filter((r) => r.kind === 'group').map((r) => (r as any).key);\n}\n\n/**\n * Count total rows in a group (including nested groups).\n *\n * @param groupRow - The group row\n * @returns Total row count\n */\nexport function getGroupRowCount(groupRow: RenderRow): number {\n if (groupRow.kind !== 'group') return 0;\n return groupRow.rows.length;\n}\n","/**\n * Row Grouping Plugin (Class-based)\n *\n * Enables hierarchical row grouping with expand/collapse and aggregations.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { BaseGridPlugin, CellClickEvent } from '../../core/plugin/base-plugin';\nimport type { GridConfig } from '../../core/types';\nimport {\n buildGroupedRowModel,\n collapseAllGroups,\n expandAllGroups,\n getGroupRowCount,\n runAggregator,\n toggleGroupExpansion,\n} from './grouping-rows';\nimport styles from './grouping-rows.css?inline';\nimport type {\n ExpandCollapseAnimation,\n GroupingRowsConfig,\n GroupRowModelItem,\n GroupToggleDetail,\n RenderRow,\n} from './types';\n\ninterface GridWithConfig {\n effectiveConfig?: GridConfig;\n}\n\n/**\n * Group state information returned by getGroupState()\n */\nexport interface GroupState {\n /** Whether grouping is currently active */\n isActive: boolean;\n /** Number of expanded groups */\n expandedCount: number;\n /** Total number of groups */\n totalGroups: number;\n /** Array of expanded group keys */\n expandedKeys: string[];\n}\n\n/**\n * Row Grouping Plugin for tbw-grid\n *\n * @example\n * ```ts\n * new GroupingRowsPlugin({\n * enabled: true,\n * groupOn: (row) => row.category,\n * defaultExpanded: false,\n * showRowCount: true,\n * })\n * ```\n */\nexport class GroupingRowsPlugin extends BaseGridPlugin<GroupingRowsConfig> {\n readonly name = 'groupingRows';\n override readonly version = '1.0.0';\n\n protected override get defaultConfig(): Partial<GroupingRowsConfig> {\n return {\n defaultExpanded: false,\n showRowCount: true,\n indentWidth: 20,\n aggregators: {},\n animation: 'slide',\n };\n }\n\n // #region Internal State\n private expandedKeys: Set<string> = new Set();\n private flattenedRows: RenderRow[] = [];\n private isActive = false;\n private previousVisibleKeys = new Set<string>();\n private keysToAnimate = new Set<string>();\n // #endregion\n\n // #region Animation\n\n private get animationStyle(): ExpandCollapseAnimation {\n const gridEl = this.grid as unknown as GridWithConfig;\n const mode = gridEl.effectiveConfig?.animation?.mode ?? 'reduced-motion';\n\n if (mode === false || mode === 'off') return false;\n if (mode !== true && mode !== 'on') {\n const host = this.shadowRoot?.host as HTMLElement | undefined;\n if (host && getComputedStyle(host).getPropertyValue('--tbw-animation-enabled').trim() === '0') {\n return false;\n }\n }\n return this.config.animation ?? 'slide';\n }\n\n // #endregion\n\n // #region Lifecycle\n\n override detach(): void {\n this.expandedKeys.clear();\n this.flattenedRows = [];\n this.isActive = false;\n this.previousVisibleKeys.clear();\n this.keysToAnimate.clear();\n }\n // #endregion\n\n // #region Hooks\n\n /**\n * Auto-detect grouping configuration from grid config.\n * Called by plugin system to determine if plugin should activate.\n */\n static detect(rows: readonly any[], config: any): boolean {\n return typeof config?.groupOn === 'function' || typeof config?.enableRowGrouping === 'boolean';\n }\n\n override processRows(rows: readonly any[]): any[] {\n const config = this.config;\n\n // Check if grouping is configured\n if (typeof config.groupOn !== 'function') {\n this.isActive = false;\n this.flattenedRows = [];\n return [...rows];\n }\n\n // Build grouped model\n const grouped = buildGroupedRowModel({\n rows: rows as any[],\n config: config,\n expanded: this.expandedKeys,\n });\n\n // If no grouping produced, return original rows\n if (grouped.length === 0) {\n this.isActive = false;\n this.flattenedRows = [];\n return [...rows];\n }\n\n this.isActive = true;\n this.flattenedRows = grouped;\n\n // Track which data rows are newly visible (for animation)\n this.keysToAnimate.clear();\n const currentVisibleKeys = new Set<string>();\n grouped.forEach((item, idx) => {\n if (item.kind === 'data') {\n const key = `data-${idx}`;\n currentVisibleKeys.add(key);\n if (!this.previousVisibleKeys.has(key)) {\n this.keysToAnimate.add(key);\n }\n }\n });\n this.previousVisibleKeys = currentVisibleKeys;\n\n // Return flattened rows for rendering\n // The grid will need to handle group rows specially\n return grouped.map((item) => {\n if (item.kind === 'group') {\n return {\n __isGroupRow: true,\n __groupKey: item.key,\n __groupValue: item.value,\n __groupDepth: item.depth,\n __groupRows: item.rows,\n __groupExpanded: item.expanded,\n __groupRowCount: getGroupRowCount(item),\n };\n }\n return item.row;\n });\n }\n\n override onCellClick(event: CellClickEvent): boolean | void {\n const row = event.row as Record<string, unknown> | undefined;\n\n // Check if this is a group row toggle\n if (row?.__isGroupRow) {\n const target = event.originalEvent.target as HTMLElement;\n if (target?.closest('.group-toggle')) {\n this.toggle(row.__groupKey as string);\n return true; // Prevent default\n }\n }\n }\n\n /**\n * Render a row. Returns true if we handled the row (group row), false otherwise.\n */\n override renderRow(row: any, rowEl: HTMLElement, _rowIndex: number): boolean {\n // Only handle group rows\n if (!row?.__isGroupRow) {\n return false;\n }\n\n const config = this.config;\n\n // If a custom renderer is provided, use it\n if (config.groupRowRenderer) {\n const toggleExpand = () => {\n this.toggle(row.__groupKey);\n };\n\n const result = config.groupRowRenderer({\n key: row.__groupKey,\n value: row.__groupValue,\n depth: row.__groupDepth,\n rows: row.__groupRows,\n expanded: row.__groupExpanded,\n toggleExpand,\n });\n\n if (result) {\n rowEl.className = 'group-row';\n (rowEl as any).__isCustomRow = true; // Mark for proper class reset on recycle\n rowEl.setAttribute('data-group-depth', String(row.__groupDepth));\n if (typeof result === 'string') {\n rowEl.innerHTML = result;\n } else {\n rowEl.innerHTML = '';\n rowEl.appendChild(result);\n }\n return true;\n }\n }\n\n // Helper to toggle expansion\n const handleToggle = () => {\n this.toggle(row.__groupKey);\n };\n\n // Default group row rendering\n rowEl.className = 'group-row';\n (rowEl as any).__isCustomRow = true; // Mark for proper class reset on recycle\n rowEl.setAttribute('data-group-depth', String(row.__groupDepth));\n rowEl.setAttribute('role', 'row');\n rowEl.setAttribute('aria-expanded', String(row.__groupExpanded));\n rowEl.style.paddingLeft = `${(row.__groupDepth || 0) * (config.indentWidth ?? 20)}px`;\n rowEl.innerHTML = '';\n\n const isFullWidth = config.fullWidth !== false; // default true\n\n if (isFullWidth) {\n this.renderFullWidthGroupRow(row, rowEl, handleToggle);\n } else {\n this.renderPerColumnGroupRow(row, rowEl, handleToggle);\n }\n\n return true;\n }\n\n override afterRender(): void {\n const style = this.animationStyle;\n if (style === false || this.keysToAnimate.size === 0) return;\n\n const body = this.shadowRoot?.querySelector('.rows');\n if (!body) return;\n\n const animClass = style === 'fade' ? 'tbw-group-fade-in' : 'tbw-group-slide-in';\n for (const rowEl of body.querySelectorAll('.data-grid-row:not(.group-row)')) {\n const cell = rowEl.querySelector('.cell[data-row]');\n const idx = cell ? parseInt(cell.getAttribute('data-row') ?? '-1', 10) : -1;\n const item = this.flattenedRows[idx];\n const key = item?.kind === 'data' ? `data-${idx}` : undefined;\n\n if (key && this.keysToAnimate.has(key)) {\n rowEl.classList.add(animClass);\n rowEl.addEventListener('animationend', () => rowEl.classList.remove(animClass), { once: true });\n }\n }\n this.keysToAnimate.clear();\n }\n // #endregion\n\n // #region Private Rendering Helpers\n\n private renderFullWidthGroupRow(row: any, rowEl: HTMLElement, handleToggle: () => void): void {\n const config = this.config;\n\n // Full-width mode: single spanning cell with toggle + label + count\n const cell = document.createElement('div');\n cell.className = 'cell group-full';\n cell.style.gridColumn = '1 / -1';\n cell.setAttribute('role', 'gridcell');\n\n // Toggle button with click handler\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = `group-toggle${row.__groupExpanded ? ' expanded' : ''}`;\n btn.setAttribute('aria-label', row.__groupExpanded ? 'Collapse group' : 'Expand group');\n this.setIcon(btn, this.resolveIcon(row.__groupExpanded ? 'collapse' : 'expand'));\n btn.addEventListener('click', (e) => {\n e.stopPropagation();\n handleToggle();\n });\n cell.appendChild(btn);\n\n // Group label - use formatLabel if provided\n const label = document.createElement('span');\n label.className = 'group-label';\n const labelText = config.formatLabel\n ? config.formatLabel(row.__groupValue, row.__groupDepth || 0, row.__groupKey)\n : String(row.__groupValue);\n label.textContent = labelText;\n cell.appendChild(label);\n\n // Row count\n if (config.showRowCount !== false) {\n const count = document.createElement('span');\n count.className = 'group-count';\n count.textContent = `(${row.__groupRowCount ?? row.__groupRows?.length ?? 0})`;\n cell.appendChild(count);\n }\n\n rowEl.appendChild(cell);\n }\n\n private renderPerColumnGroupRow(row: any, rowEl: HTMLElement, handleToggle: () => void): void {\n const config = this.config;\n const aggregators = config.aggregators ?? {};\n const columns = this.columns;\n const groupRows = row.__groupRows ?? [];\n\n // Get grid template from the grid element\n const bodyEl = this.shadowRoot?.querySelector('.body') as HTMLElement | null;\n const gridTemplate = bodyEl?.style.gridTemplateColumns || '';\n if (gridTemplate) {\n rowEl.style.display = 'grid';\n rowEl.style.gridTemplateColumns = gridTemplate;\n }\n\n columns.forEach((col, colIdx) => {\n const cell = document.createElement('div');\n cell.className = 'cell group-cell';\n cell.setAttribute('data-col', String(colIdx));\n cell.setAttribute('role', 'gridcell');\n\n if (colIdx === 0) {\n // First column: toggle button + label\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = `group-toggle${row.__groupExpanded ? ' expanded' : ''}`;\n btn.setAttribute('aria-label', row.__groupExpanded ? 'Collapse group' : 'Expand group');\n this.setIcon(btn, this.resolveIcon(row.__groupExpanded ? 'collapse' : 'expand'));\n btn.addEventListener('click', (e) => {\n e.stopPropagation();\n handleToggle();\n });\n cell.appendChild(btn);\n\n const label = document.createElement('span');\n const firstColAgg = aggregators[col.field];\n if (firstColAgg) {\n const aggResult = runAggregator(firstColAgg, groupRows, col.field, col);\n label.textContent = aggResult != null ? String(aggResult) : String(row.__groupValue);\n } else {\n const labelText = config.formatLabel\n ? config.formatLabel(row.__groupValue, row.__groupDepth || 0, row.__groupKey)\n : String(row.__groupValue);\n label.textContent = labelText;\n }\n cell.appendChild(label);\n\n if (config.showRowCount !== false) {\n const count = document.createElement('span');\n count.className = 'group-count';\n count.textContent = ` (${groupRows.length})`;\n cell.appendChild(count);\n }\n } else {\n // Other columns: run aggregator if defined\n const aggRef = aggregators[col.field];\n if (aggRef) {\n const result = runAggregator(aggRef, groupRows, col.field, col);\n cell.textContent = result != null ? String(result) : '';\n } else {\n cell.textContent = '';\n }\n }\n\n rowEl.appendChild(cell);\n });\n }\n // #endregion\n\n // #region Public API\n\n /**\n * Expand all groups.\n */\n expandAll(): void {\n this.expandedKeys = expandAllGroups(this.flattenedRows);\n this.requestRender();\n }\n\n /**\n * Collapse all groups.\n */\n collapseAll(): void {\n this.expandedKeys = collapseAllGroups();\n this.requestRender();\n }\n\n /**\n * Toggle expansion of a specific group.\n * @param key - The group key to toggle\n */\n toggle(key: string): void {\n this.expandedKeys = toggleGroupExpansion(this.expandedKeys, key);\n\n // Find the group to emit event details\n const group = this.flattenedRows.find((r) => r.kind === 'group' && r.key === key) as GroupRowModelItem | undefined;\n\n this.emit<GroupToggleDetail>('group-toggle', {\n key,\n expanded: this.expandedKeys.has(key),\n value: group?.value,\n depth: group?.depth ?? 0,\n });\n\n this.requestRender();\n }\n\n /**\n * Check if a specific group is expanded.\n * @param key - The group key to check\n * @returns Whether the group is expanded\n */\n isExpanded(key: string): boolean {\n return this.expandedKeys.has(key);\n }\n\n /**\n * Expand a specific group.\n * @param key - The group key to expand\n */\n expand(key: string): void {\n if (!this.expandedKeys.has(key)) {\n this.expandedKeys = new Set([...this.expandedKeys, key]);\n this.requestRender();\n }\n }\n\n /**\n * Collapse a specific group.\n * @param key - The group key to collapse\n */\n collapse(key: string): void {\n if (this.expandedKeys.has(key)) {\n const newKeys = new Set(this.expandedKeys);\n newKeys.delete(key);\n this.expandedKeys = newKeys;\n this.requestRender();\n }\n }\n\n /**\n * Get the current group state.\n * @returns Group state information\n */\n getGroupState(): GroupState {\n const groupRows = this.flattenedRows.filter((r) => r.kind === 'group');\n return {\n isActive: this.isActive,\n expandedCount: this.expandedKeys.size,\n totalGroups: groupRows.length,\n expandedKeys: [...this.expandedKeys],\n };\n }\n\n /**\n * Get the total count of visible rows (including group headers).\n * @returns Number of visible rows\n */\n getRowCount(): number {\n return this.flattenedRows.length;\n }\n\n /**\n * Refresh the grouped row model.\n * Call this after modifying groupOn or other config options.\n */\n refreshGroups(): void {\n this.requestRender();\n }\n\n /**\n * Get current expanded group keys.\n * @returns Array of expanded group keys\n */\n getExpandedGroups(): string[] {\n return [...this.expandedKeys];\n }\n\n /**\n * Get the flattened row model.\n * @returns Array of render rows (groups + data rows)\n */\n getFlattenedRows(): RenderRow[] {\n return this.flattenedRows;\n }\n\n /**\n * Check if grouping is currently active.\n * @returns Whether grouping is active\n */\n isGroupingActive(): boolean {\n return this.isActive;\n }\n\n /**\n * Set the groupOn function dynamically.\n * @param fn - The groupOn function or undefined to disable\n */\n setGroupOn(fn: ((row: any) => any[] | any | null | false) | undefined): void {\n (this.config as GroupingRowsConfig).groupOn = fn;\n this.requestRender();\n }\n // #endregion\n\n // #region Styles\n\n override readonly styles = styles;\n // #endregion\n}\n","/**\n * Master/Detail Core Logic\n *\n * Pure functions for managing detail row expansion state.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n// Uses `any` for maximum flexibility with user-defined row types.\n\n/**\n * Toggle the expansion state of a detail row.\n * Returns a new Set with the updated state.\n */\nexport function toggleDetailRow(expandedRows: Set<object>, row: object): Set<object> {\n const newExpanded = new Set(expandedRows);\n if (newExpanded.has(row)) {\n newExpanded.delete(row);\n } else {\n newExpanded.add(row);\n }\n return newExpanded;\n}\n\n/**\n * Expand a detail row.\n * Returns a new Set with the row added.\n */\nexport function expandDetailRow(expandedRows: Set<object>, row: object): Set<object> {\n const newExpanded = new Set(expandedRows);\n newExpanded.add(row);\n return newExpanded;\n}\n\n/**\n * Collapse a detail row.\n * Returns a new Set with the row removed.\n */\nexport function collapseDetailRow(expandedRows: Set<object>, row: object): Set<object> {\n const newExpanded = new Set(expandedRows);\n newExpanded.delete(row);\n return newExpanded;\n}\n\n/**\n * Check if a detail row is expanded.\n */\nexport function isDetailExpanded(expandedRows: Set<object>, row: object): boolean {\n return expandedRows.has(row);\n}\n\n/**\n * Create a detail element for a given row.\n * The element spans all columns and contains the rendered content.\n */\nexport function createDetailElement(\n row: any,\n rowIndex: number,\n renderer: (row: any, rowIndex: number) => HTMLElement | string,\n columnCount: number\n): HTMLElement {\n const detailRow = document.createElement('div');\n detailRow.className = 'master-detail-row';\n detailRow.setAttribute('data-detail-for', String(rowIndex));\n detailRow.setAttribute('role', 'row');\n\n const detailCell = document.createElement('div');\n detailCell.className = 'master-detail-cell';\n detailCell.setAttribute('role', 'cell');\n detailCell.style.gridColumn = `1 / ${columnCount + 1}`;\n\n const content = renderer(row, rowIndex);\n if (typeof content === 'string') {\n detailCell.innerHTML = content;\n } else if (content instanceof HTMLElement) {\n detailCell.appendChild(content);\n }\n\n detailRow.appendChild(detailCell);\n return detailRow;\n}\n","/**\n * Master/Detail Plugin (Class-based)\n *\n * Enables expandable detail rows showing additional content for each row.\n * Animation style is plugin-configured; respects grid-level animation.mode.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { evalTemplateString, sanitizeHTML } from '../../core/internal/sanitize';\nimport { BaseGridPlugin, GridElement, RowClickEvent } from '../../core/plugin/base-plugin';\nimport type { ColumnConfig, GridConfig } from '../../core/types';\nimport {\n collapseDetailRow,\n createDetailElement,\n expandDetailRow,\n isDetailExpanded,\n toggleDetailRow,\n} from './master-detail';\nimport styles from './master-detail.css?inline';\nimport type { DetailExpandDetail, ExpandCollapseAnimation, MasterDetailConfig } from './types';\n\n/** Extended grid interface for accessing effective config */\ninterface GridWithConfig {\n effectiveConfig?: GridConfig;\n}\n\n/**\n * Master/Detail Plugin for tbw-grid\n *\n * @example\n * ```ts\n * new MasterDetailPlugin({\n * enabled: true,\n * detailRenderer: (row) => `<div>Details for ${row.name}</div>`,\n * expandOnRowClick: true,\n * })\n * ```\n */\nexport class MasterDetailPlugin extends BaseGridPlugin<MasterDetailConfig> {\n readonly name = 'masterDetail';\n override readonly version = '1.0.0';\n\n protected override get defaultConfig(): Partial<MasterDetailConfig> {\n return {\n detailHeight: 'auto',\n expandOnRowClick: false,\n collapseOnClickOutside: false,\n showExpandColumn: true,\n animation: 'slide', // Plugin's own default\n };\n }\n\n // #region Light DOM Parsing\n\n /**\n * Called when plugin is attached to the grid.\n * Parses light DOM for `<tbw-grid-detail>` elements to configure detail templates.\n */\n override attach(grid: GridElement): void {\n super.attach(grid);\n this.parseLightDomDetail();\n }\n\n /**\n * Parse `<tbw-grid-detail>` elements from the grid's light DOM.\n *\n * Allows declarative configuration:\n * ```html\n * <tbw-grid [rows]=\"data\">\n * <tbw-grid-detail>\n * <div class=\"detail-content\">\n * <p>Name: {{ row.name }}</p>\n * <p>Email: {{ row.email }}</p>\n * </div>\n * </tbw-grid-detail>\n * </tbw-grid>\n * ```\n *\n * Attributes:\n * - `animation`: 'slide' | 'fade' | 'false' (default: 'slide')\n * - `show-expand-column`: 'true' | 'false' (default: 'true')\n * - `expand-on-row-click`: 'true' | 'false' (default: 'false')\n * - `collapse-on-click-outside`: 'true' | 'false' (default: 'false')\n * - `height`: number (pixels) or 'auto' (default: 'auto')\n */\n private parseLightDomDetail(): void {\n const gridEl = this.grid as unknown as Element;\n if (!gridEl || typeof gridEl.querySelector !== 'function') return;\n\n const detailEl = gridEl.querySelector('tbw-grid-detail');\n if (!detailEl) return;\n\n // Check if a framework adapter wants to handle this element\n // (e.g., Angular adapter intercepts for ng-template rendering)\n const gridWithAdapter = gridEl as unknown as {\n __frameworkAdapter?: {\n parseDetailElement?: (el: Element) => ((row: any, rowIndex: number) => HTMLElement | string) | undefined;\n };\n };\n if (gridWithAdapter.__frameworkAdapter?.parseDetailElement) {\n const adapterRenderer = gridWithAdapter.__frameworkAdapter.parseDetailElement(detailEl);\n if (adapterRenderer) {\n this.config = { ...this.config, detailRenderer: adapterRenderer };\n return;\n }\n }\n\n // Parse attributes for configuration\n const animation = detailEl.getAttribute('animation');\n const showExpandColumn = detailEl.getAttribute('show-expand-column');\n const expandOnRowClick = detailEl.getAttribute('expand-on-row-click');\n const collapseOnClickOutside = detailEl.getAttribute('collapse-on-click-outside');\n const heightAttr = detailEl.getAttribute('height');\n\n const configUpdates: Partial<MasterDetailConfig> = {};\n\n if (animation !== null) {\n configUpdates.animation = animation === 'false' ? false : (animation as 'slide' | 'fade');\n }\n if (showExpandColumn !== null) {\n configUpdates.showExpandColumn = showExpandColumn !== 'false';\n }\n if (expandOnRowClick !== null) {\n configUpdates.expandOnRowClick = expandOnRowClick === 'true';\n }\n if (collapseOnClickOutside !== null) {\n configUpdates.collapseOnClickOutside = collapseOnClickOutside === 'true';\n }\n if (heightAttr !== null) {\n configUpdates.detailHeight = heightAttr === 'auto' ? 'auto' : parseInt(heightAttr, 10);\n }\n\n // Get template content from innerHTML\n const templateHTML = detailEl.innerHTML.trim();\n if (templateHTML && !this.config.detailRenderer) {\n // Create a template-based renderer using the inner HTML\n configUpdates.detailRenderer = (row: any, _rowIndex: number): string => {\n // Evaluate template expressions like {{ row.field }}\n const evaluated = evalTemplateString(templateHTML, { value: row, row });\n // Sanitize the result to prevent XSS\n return sanitizeHTML(evaluated);\n };\n }\n\n // Merge updates into config\n if (Object.keys(configUpdates).length > 0) {\n this.config = { ...this.config, ...configUpdates };\n }\n }\n\n // #endregion\n\n // #region Animation Helpers\n\n /**\n * Check if animations are enabled at the grid level.\n * Respects gridConfig.animation.mode and CSS variable.\n */\n private get isAnimationEnabled(): boolean {\n const gridEl = this.grid as unknown as GridWithConfig;\n const mode = gridEl.effectiveConfig?.animation?.mode ?? 'reduced-motion';\n\n if (mode === false || mode === 'off') return false;\n if (mode === true || mode === 'on') return true;\n\n // reduced-motion: check CSS variable\n const host = this.shadowRoot?.host as HTMLElement | undefined;\n if (host) {\n const enabled = getComputedStyle(host).getPropertyValue('--tbw-animation-enabled').trim();\n return enabled !== '0';\n }\n return true;\n }\n\n /**\n * Get expand/collapse animation style from plugin config.\n */\n private get animationStyle(): ExpandCollapseAnimation {\n if (!this.isAnimationEnabled) return false;\n return this.config.animation ?? 'slide'; // Plugin default\n }\n\n /**\n * Get animation duration from CSS variable (set by grid).\n */\n private get animationDuration(): number {\n const host = this.shadowRoot?.host as HTMLElement | undefined;\n if (host) {\n const durationStr = getComputedStyle(host).getPropertyValue('--tbw-animation-duration').trim();\n const parsed = parseInt(durationStr, 10);\n if (!isNaN(parsed)) return parsed;\n }\n return 200; // Default\n }\n\n /**\n * Apply expand animation to a detail element.\n */\n private animateExpand(detailEl: HTMLElement): void {\n if (!this.isAnimationEnabled || this.animationStyle === false) return;\n\n detailEl.classList.add('tbw-expanding');\n detailEl.addEventListener(\n 'animationend',\n () => {\n detailEl.classList.remove('tbw-expanding');\n },\n { once: true },\n );\n }\n\n /**\n * Apply collapse animation to a detail element and remove after animation.\n */\n private animateCollapse(detailEl: HTMLElement, onComplete: () => void): void {\n if (!this.isAnimationEnabled || this.animationStyle === false) {\n onComplete();\n return;\n }\n\n detailEl.classList.add('tbw-collapsing');\n const cleanup = () => {\n detailEl.classList.remove('tbw-collapsing');\n onComplete();\n };\n detailEl.addEventListener('animationend', cleanup, { once: true });\n // Fallback timeout in case animation doesn't fire\n setTimeout(cleanup, this.animationDuration + 50);\n }\n\n // #endregion\n\n // #region Internal State\n private expandedRows: Set<any> = new Set();\n private detailElements: Map<any, HTMLElement> = new Map();\n // #endregion\n\n // #region Lifecycle\n\n override detach(): void {\n this.expandedRows.clear();\n this.detailElements.clear();\n }\n // #endregion\n\n // #region Hooks\n\n override processColumns(columns: readonly ColumnConfig[]): ColumnConfig[] {\n if (!this.config.detailRenderer) {\n return [...columns];\n }\n\n // Wrap first column's renderer to add expand/collapse toggle\n const cols = [...columns];\n if (cols.length > 0) {\n const firstCol = { ...cols[0] };\n const originalRenderer = firstCol.viewRenderer;\n\n // Skip if already wrapped by this plugin (prevents double-wrapping on re-render)\n if ((originalRenderer as any)?.__masterDetailWrapped) {\n return cols;\n }\n\n const wrappedRenderer = (renderCtx: Parameters<NonNullable<typeof originalRenderer>>[0]) => {\n const { value, row } = renderCtx;\n const isExpanded = this.expandedRows.has(row);\n\n const container = document.createElement('span');\n container.className = 'master-detail-cell-wrapper';\n\n // Expand/collapse toggle icon\n const toggle = document.createElement('span');\n toggle.className = `master-detail-toggle${isExpanded ? ' expanded' : ''}`;\n // Use grid-level icons (fall back to defaults)\n this.setIcon(toggle, this.resolveIcon(isExpanded ? 'collapse' : 'expand'));\n // role=\"button\" is required for aria-expanded to be valid\n toggle.setAttribute('role', 'button');\n toggle.setAttribute('tabindex', '0');\n toggle.setAttribute('aria-expanded', String(isExpanded));\n toggle.setAttribute('aria-label', isExpanded ? 'Collapse details' : 'Expand details');\n toggle.addEventListener('click', (e) => {\n e.stopPropagation();\n const rowIndex = this.rows.indexOf(row);\n this.expandedRows = toggleDetailRow(this.expandedRows, row);\n this.emit<DetailExpandDetail>('detail-expand', {\n rowIndex,\n row,\n expanded: this.expandedRows.has(row),\n });\n this.requestRender();\n });\n container.appendChild(toggle);\n\n // Cell content\n const content = document.createElement('span');\n if (originalRenderer) {\n const rendered = originalRenderer(renderCtx);\n if (rendered instanceof Node) {\n content.appendChild(rendered);\n } else {\n content.textContent = String(rendered ?? value ?? '');\n }\n } else {\n content.textContent = String(value ?? '');\n }\n container.appendChild(content);\n\n return container;\n };\n\n // Mark renderer as wrapped to prevent double-wrapping\n (wrappedRenderer as any).__masterDetailWrapped = true;\n firstCol.viewRenderer = wrappedRenderer;\n\n cols[0] = firstCol;\n }\n\n return cols;\n }\n\n override onRowClick(event: RowClickEvent): boolean | void {\n if (!this.config.expandOnRowClick || !this.config.detailRenderer) return;\n\n this.expandedRows = toggleDetailRow(this.expandedRows, event.row as object);\n\n this.emit<DetailExpandDetail>('detail-expand', {\n rowIndex: event.rowIndex,\n row: event.row,\n expanded: this.expandedRows.has(event.row as object),\n });\n\n this.requestRender();\n return false;\n }\n\n override onCellClick(): boolean | void {\n // Sync detail rows after cell click triggers refreshVirtualWindow\n // This runs in microtask to ensure DOM updates are complete\n if (this.expandedRows.size > 0) {\n queueMicrotask(() => this.#syncDetailRows());\n }\n return; // Don't prevent default\n }\n\n override afterRender(): void {\n this.#syncDetailRows();\n }\n\n /**\n * Called on scroll to sync detail elements with visible rows.\n * Removes details for rows that scrolled out of view and reattaches for visible rows.\n */\n override onScrollRender(): void {\n if (!this.config.detailRenderer || this.expandedRows.size === 0) return;\n // Full sync needed on scroll to clean up orphaned details\n this.#syncDetailRows();\n }\n\n /**\n * Full sync of detail rows - cleans up stale elements and creates new ones.\n * Detail rows are inserted as siblings AFTER their master row to survive row rebuilds.\n */\n #syncDetailRows(): void {\n if (!this.config.detailRenderer) return;\n\n const body = this.shadowRoot?.querySelector('.rows');\n if (!body) return;\n\n // Build a map of row index -> row element for visible rows\n const visibleRowMap = new Map<number, Element>();\n const dataRows = body.querySelectorAll('.data-grid-row');\n const columnCount = this.columns.length;\n\n for (const rowEl of dataRows) {\n const firstCell = rowEl.querySelector('.cell[data-row]');\n const rowIndex = firstCell ? parseInt(firstCell.getAttribute('data-row') ?? '-1', 10) : -1;\n if (rowIndex >= 0) {\n visibleRowMap.set(rowIndex, rowEl);\n }\n }\n\n // Remove detail rows whose parent row is no longer visible or no longer expanded\n const existingDetails = body.querySelectorAll('.master-detail-row');\n for (const detailEl of existingDetails) {\n const forIndex = parseInt(detailEl.getAttribute('data-detail-for') ?? '-1', 10);\n const row = forIndex >= 0 ? this.rows[forIndex] : undefined;\n const isStillExpanded = row && this.expandedRows.has(row);\n const isRowVisible = visibleRowMap.has(forIndex);\n\n // Remove detail if not expanded or if parent row scrolled out\n if (!isStillExpanded || !isRowVisible) {\n detailEl.remove();\n if (row) this.detailElements.delete(row);\n }\n }\n\n // Insert detail rows for expanded rows that are visible\n for (const [rowIndex, rowEl] of visibleRowMap) {\n const row = this.rows[rowIndex];\n if (!row || !this.expandedRows.has(row)) continue;\n\n // Check if detail already exists for this row\n const existingDetail = this.detailElements.get(row);\n if (existingDetail) {\n // Ensure it's positioned correctly (as next sibling of row element)\n if (existingDetail.previousElementSibling !== rowEl) {\n rowEl.after(existingDetail);\n }\n continue;\n }\n\n // Create new detail element\n const detailEl = createDetailElement(row, rowIndex, this.config.detailRenderer, columnCount);\n\n if (typeof this.config.detailHeight === 'number') {\n detailEl.style.height = `${this.config.detailHeight}px`;\n }\n\n // Insert as sibling after the row element (not as child)\n rowEl.after(detailEl);\n this.detailElements.set(row, detailEl);\n\n // Apply expand animation\n this.animateExpand(detailEl);\n }\n }\n\n /**\n * Return total extra height from all expanded detail rows.\n * Used by grid virtualization to adjust scrollbar height.\n */\n override getExtraHeight(): number {\n let totalHeight = 0;\n for (const row of this.expandedRows) {\n const detailEl = this.detailElements.get(row);\n if (detailEl) {\n totalHeight += detailEl.offsetHeight;\n } else {\n // Detail not yet rendered - estimate based on config or default\n const configHeight = this.config?.detailHeight;\n totalHeight += typeof configHeight === 'number' ? configHeight : 150;\n }\n }\n return totalHeight;\n }\n\n /**\n * Return extra height that appears before a given row index.\n * This is the sum of heights of all expanded details whose parent row is before the given index.\n */\n override getExtraHeightBefore(beforeRowIndex: number): number {\n let totalHeight = 0;\n for (const row of this.expandedRows) {\n const rowIndex = this.rows.indexOf(row);\n // Include detail if it's for a row before the given index\n if (rowIndex >= 0 && rowIndex < beforeRowIndex) {\n const detailEl = this.detailElements.get(row);\n if (detailEl) {\n totalHeight += detailEl.offsetHeight;\n } else {\n const configHeight = this.config?.detailHeight;\n totalHeight += typeof configHeight === 'number' ? configHeight : 150;\n }\n }\n }\n return totalHeight;\n }\n\n /**\n * Adjust the virtualization start index to keep expanded row visible while its detail is visible.\n * This ensures the detail scrolls smoothly out of view instead of disappearing abruptly.\n */\n override adjustVirtualStart(start: number, scrollTop: number, rowHeight: number): number {\n if (this.expandedRows.size === 0) return start;\n\n // Build sorted list of expanded row indices for cumulative height calculation\n const expandedIndices: Array<{ index: number; row: any }> = [];\n for (const row of this.expandedRows) {\n const index = this.rows.indexOf(row);\n if (index >= 0) {\n expandedIndices.push({ index, row });\n }\n }\n expandedIndices.sort((a, b) => a.index - b.index);\n\n let minStart = start;\n\n // Calculate actual scroll position for each expanded row,\n // accounting for cumulative detail heights before it\n let cumulativeExtraHeight = 0;\n\n for (const { index: rowIndex, row } of expandedIndices) {\n // Actual position includes all detail heights before this row\n const actualRowTop = rowIndex * rowHeight + cumulativeExtraHeight;\n const detailEl = this.detailElements.get(row);\n const detailHeight =\n detailEl?.offsetHeight ?? (typeof this.config?.detailHeight === 'number' ? this.config.detailHeight : 150);\n const actualDetailBottom = actualRowTop + rowHeight + detailHeight;\n\n // Update cumulative height for next iteration\n cumulativeExtraHeight += detailHeight;\n\n // Skip rows that are at or after the calculated start\n if (rowIndex >= start) continue;\n\n // If any part of the detail is still visible (below the scroll position),\n // we need to keep the parent row in the render range\n if (actualDetailBottom > scrollTop) {\n if (rowIndex < minStart) {\n minStart = rowIndex;\n }\n }\n }\n\n return minStart;\n }\n // #endregion\n\n // #region Public API\n\n /**\n * Expand the detail row at the given index.\n * @param rowIndex - Index of the row to expand\n */\n expand(rowIndex: number): void {\n const row = this.rows[rowIndex];\n if (row) {\n this.expandedRows = expandDetailRow(this.expandedRows, row);\n this.requestRender();\n }\n }\n\n /**\n * Collapse the detail row at the given index.\n * @param rowIndex - Index of the row to collapse\n */\n collapse(rowIndex: number): void {\n const row = this.rows[rowIndex];\n if (row) {\n this.expandedRows = collapseDetailRow(this.expandedRows, row);\n this.requestRender();\n }\n }\n\n /**\n * Toggle the detail row at the given index.\n * @param rowIndex - Index of the row to toggle\n */\n toggle(rowIndex: number): void {\n const row = this.rows[rowIndex];\n if (row) {\n this.expandedRows = toggleDetailRow(this.expandedRows, row);\n this.requestRender();\n }\n }\n\n /**\n * Check if the detail row at the given index is expanded.\n * @param rowIndex - Index of the row to check\n * @returns Whether the detail row is expanded\n */\n isExpanded(rowIndex: number): boolean {\n const row = this.rows[rowIndex];\n return row ? isDetailExpanded(this.expandedRows, row) : false;\n }\n\n /**\n * Expand all detail rows.\n */\n expandAll(): void {\n for (const row of this.rows) {\n this.expandedRows.add(row);\n }\n this.requestRender();\n }\n\n /**\n * Collapse all detail rows.\n */\n collapseAll(): void {\n this.expandedRows.clear();\n this.requestRender();\n }\n\n /**\n * Get the indices of all expanded rows.\n * @returns Array of row indices that are expanded\n */\n getExpandedRows(): number[] {\n const indices: number[] = [];\n for (const row of this.expandedRows) {\n const idx = this.rows.indexOf(row);\n if (idx >= 0) indices.push(idx);\n }\n return indices;\n }\n\n /**\n * Get the detail element for a specific row.\n * @param rowIndex - Index of the row\n * @returns The detail HTMLElement or undefined\n */\n getDetailElement(rowIndex: number): HTMLElement | undefined {\n const row = this.rows[rowIndex];\n return row ? this.detailElements.get(row) : undefined;\n }\n\n /**\n * Re-parse light DOM to refresh the detail renderer.\n * Call this after framework templates are registered (e.g., Angular ngAfterContentInit).\n *\n * This allows frameworks to register templates asynchronously and then\n * update the plugin's detailRenderer.\n */\n refreshDetailRenderer(): void {\n // Force re-parse by temporarily clearing the renderer\n const currentRenderer = this.config.detailRenderer;\n this.config = { ...this.config, detailRenderer: undefined };\n this.parseLightDomDetail();\n\n // If no new renderer was found, restore the original\n if (!this.config.detailRenderer && currentRenderer) {\n this.config = { ...this.config, detailRenderer: currentRenderer };\n }\n }\n // #endregion\n\n // #region Styles\n override readonly styles = styles;\n // #endregion\n}\n","/**\n * Multi-Sort Core Logic\n *\n * Pure functions for multi-column sorting operations.\n */\n\nimport type { ColumnConfig } from '../../core/types';\nimport type { SortModel } from './types';\n\n/**\n * Apply multiple sort columns to a row array.\n * Sorts are applied in order - first sort has highest priority.\n *\n * @param rows - Array of row objects to sort\n * @param sorts - Ordered array of sort configurations\n * @param columns - Column configurations (for custom comparators)\n * @returns New sorted array (does not mutate original)\n */\nexport function applySorts<TRow = unknown>(rows: TRow[], sorts: SortModel[], columns: ColumnConfig<TRow>[]): TRow[] {\n if (!sorts.length) return [...rows];\n\n return [...rows].sort((a, b) => {\n for (const sort of sorts) {\n const col = columns.find((c) => c.field === sort.field);\n const comparator = col?.sortComparator ?? defaultComparator;\n const aVal = (a as Record<string, unknown>)[sort.field];\n const bVal = (b as Record<string, unknown>)[sort.field];\n const result = comparator(aVal, bVal, a, b);\n if (result !== 0) {\n return sort.direction === 'asc' ? result : -result;\n }\n }\n return 0;\n });\n}\n\n/**\n * Default comparator for sorting values.\n * Handles nulls, numbers, dates, and strings.\n *\n * @param a - First value\n * @param b - Second value\n * @returns Comparison result (-1, 0, 1)\n */\nexport function defaultComparator(a: unknown, b: unknown): number {\n // Handle nulls/undefined - push to end\n if (a == null && b == null) return 0;\n if (a == null) return 1;\n if (b == null) return -1;\n\n // Type-aware comparison\n if (typeof a === 'number' && typeof b === 'number') {\n return a - b;\n }\n\n if (a instanceof Date && b instanceof Date) {\n return a.getTime() - b.getTime();\n }\n\n // Boolean comparison\n if (typeof a === 'boolean' && typeof b === 'boolean') {\n return a === b ? 0 : a ? -1 : 1;\n }\n\n // String comparison (fallback)\n return String(a).localeCompare(String(b));\n}\n\n/**\n * Toggle sort state for a field.\n * With shift key: adds/toggles in multi-sort list\n * Without shift key: replaces entire sort with single column\n *\n * @param current - Current sort model\n * @param field - Field to toggle\n * @param shiftKey - Whether shift key is held (multi-sort mode)\n * @param maxColumns - Maximum columns allowed in sort\n * @returns New sort model\n */\nexport function toggleSort(current: SortModel[], field: string, shiftKey: boolean, maxColumns: number): SortModel[] {\n const existing = current.find((s) => s.field === field);\n\n if (shiftKey) {\n // Multi-sort: add/toggle in list\n if (existing) {\n if (existing.direction === 'asc') {\n // Flip to descending\n return current.map((s) => (s.field === field ? { ...s, direction: 'desc' as const } : s));\n } else {\n // Remove from sort\n return current.filter((s) => s.field !== field);\n }\n } else if (current.length < maxColumns) {\n // Add new sort column\n return [...current, { field, direction: 'asc' as const }];\n }\n // Max columns reached, return unchanged\n return current;\n } else {\n // Single sort: replace all\n if (existing?.direction === 'asc') {\n return [{ field, direction: 'desc' }];\n } else if (existing?.direction === 'desc') {\n return [];\n }\n return [{ field, direction: 'asc' }];\n }\n}\n\n/**\n * Get the sort index (1-based) for a field in the sort model.\n * Returns undefined if the field is not in the sort model.\n *\n * @param sortModel - Current sort model\n * @param field - Field to check\n * @returns 1-based index or undefined\n */\nexport function getSortIndex(sortModel: SortModel[], field: string): number | undefined {\n const index = sortModel.findIndex((s) => s.field === field);\n return index >= 0 ? index + 1 : undefined;\n}\n\n/**\n * Get the sort direction for a field in the sort model.\n *\n * @param sortModel - Current sort model\n * @param field - Field to check\n * @returns Sort direction or undefined if not sorted\n */\nexport function getSortDirection(sortModel: SortModel[], field: string): 'asc' | 'desc' | undefined {\n return sortModel.find((s) => s.field === field)?.direction;\n}\n","/**\n * Multi-Sort Plugin (Class-based)\n *\n * Provides multi-column sorting capabilities for tbw-grid.\n * Supports shift+click for adding secondary sort columns.\n */\n\nimport { BaseGridPlugin, HeaderClickEvent } from '../../core/plugin/base-plugin';\nimport type { ColumnState } from '../../core/types';\nimport { applySorts, getSortDirection, getSortIndex, toggleSort } from './multi-sort';\nimport styles from './multi-sort.css?inline';\nimport type { MultiSortConfig, SortModel } from './types';\n\n/**\n * Multi-Sort Plugin for tbw-grid\n *\n * @example\n * ```ts\n * new MultiSortPlugin({ maxSortColumns: 3, showSortIndex: true })\n * ```\n */\nexport class MultiSortPlugin extends BaseGridPlugin<MultiSortConfig> {\n readonly name = 'multiSort';\n override readonly version = '1.0.0';\n\n protected override get defaultConfig(): Partial<MultiSortConfig> {\n return {\n maxSortColumns: 3,\n showSortIndex: true,\n };\n }\n\n // #region Internal State\n private sortModel: SortModel[] = [];\n // #endregion\n\n // #region Lifecycle\n\n override detach(): void {\n this.sortModel = [];\n }\n // #endregion\n\n // #region Hooks\n\n override processRows(rows: readonly unknown[]): unknown[] {\n if (this.sortModel.length === 0) {\n return [...rows];\n }\n return applySorts([...rows], this.sortModel, [...this.columns]);\n }\n\n override onHeaderClick(event: HeaderClickEvent): boolean {\n const column = this.columns.find((c) => c.field === event.field);\n if (!column?.sortable) return false;\n\n const shiftKey = event.originalEvent.shiftKey;\n const maxColumns = this.config.maxSortColumns ?? 3;\n\n this.sortModel = toggleSort(this.sortModel, event.field, shiftKey, maxColumns);\n\n this.emit('sort-change', { sortModel: [...this.sortModel] });\n this.requestRender();\n\n return true;\n }\n\n override afterRender(): void {\n const shadowRoot = this.shadowRoot;\n if (!shadowRoot) return;\n\n const showIndex = this.config.showSortIndex !== false;\n\n // Update all sortable header cells with sort indicators\n const headerCells = shadowRoot.querySelectorAll('.header-row .cell[data-field]');\n headerCells.forEach((cell) => {\n const field = cell.getAttribute('data-field');\n if (!field) return;\n\n const sortIndex = getSortIndex(this.sortModel, field);\n const sortDir = getSortDirection(this.sortModel, field);\n\n // Remove existing sort index badge (always clean up)\n const existingBadge = cell.querySelector('.sort-index');\n existingBadge?.remove();\n\n if (sortDir) {\n // Column is sorted - remove base indicator and add our own\n const existingIndicator = cell.querySelector('[part~=\"sort-indicator\"], .sort-indicator');\n existingIndicator?.remove();\n\n cell.setAttribute('data-sort', sortDir);\n\n // Add sort arrow indicator\n const indicator = document.createElement('span');\n indicator.className = 'sort-indicator';\n // Use grid-level icons (fall back to defaults)\n this.setIcon(indicator, this.resolveIcon(sortDir === 'asc' ? 'sortAsc' : 'sortDesc'));\n cell.appendChild(indicator);\n\n // Add sort index badge if multiple columns sorted and showSortIndex is enabled\n if (showIndex && this.sortModel.length > 1 && sortIndex !== undefined) {\n const badge = document.createElement('span');\n badge.className = 'sort-index';\n badge.textContent = String(sortIndex);\n cell.appendChild(badge);\n }\n } else {\n cell.removeAttribute('data-sort');\n // For unsorted columns, leave the base indicator (⇅) alone\n }\n });\n }\n // #endregion\n\n // #region Public API\n\n /**\n * Get the current sort model.\n * @returns Copy of the current sort model\n */\n getSortModel(): SortModel[] {\n return [...this.sortModel];\n }\n\n /**\n * Set the sort model programmatically.\n * @param model - New sort model to apply\n */\n setSortModel(model: SortModel[]): void {\n this.sortModel = [...model];\n this.emit('sort-change', { sortModel: [...model] });\n this.requestRender();\n }\n\n /**\n * Clear all sorting.\n */\n clearSort(): void {\n this.sortModel = [];\n this.emit('sort-change', { sortModel: [] });\n this.requestRender();\n }\n\n /**\n * Get the sort index (1-based) for a specific field.\n * @param field - Field to check\n * @returns 1-based index or undefined if not sorted\n */\n getSortIndex(field: string): number | undefined {\n return getSortIndex(this.sortModel, field);\n }\n\n /**\n * Get the sort direction for a specific field.\n * @param field - Field to check\n * @returns Sort direction or undefined if not sorted\n */\n getSortDirection(field: string): 'asc' | 'desc' | undefined {\n return getSortDirection(this.sortModel, field);\n }\n // #endregion\n\n // #region Column State Hooks\n\n /**\n * Return sort state for a column if it's in the sort model.\n */\n override getColumnState(field: string): Partial<ColumnState> | undefined {\n const index = this.sortModel.findIndex((s) => s.field === field);\n if (index === -1) return undefined;\n\n const sortEntry = this.sortModel[index];\n return {\n sort: {\n direction: sortEntry.direction,\n priority: index,\n },\n };\n }\n\n /**\n * Apply sort state from column state.\n * Rebuilds the sort model from all column states.\n */\n override applyColumnState(field: string, state: ColumnState): void {\n // Only process if the column has sort state\n if (!state.sort) {\n // Remove this field from sortModel if it exists\n this.sortModel = this.sortModel.filter((s) => s.field !== field);\n return;\n }\n\n // Find existing entry or add new one\n const existingIndex = this.sortModel.findIndex((s) => s.field === field);\n const newEntry: SortModel = {\n field,\n direction: state.sort.direction,\n };\n\n if (existingIndex !== -1) {\n // Update existing entry\n this.sortModel[existingIndex] = newEntry;\n } else {\n // Add at the correct priority position\n this.sortModel.splice(state.sort.priority, 0, newEntry);\n }\n\n // Re-sort the model by priority to ensure correct order\n // This is handled after all columns are processed, but we maintain order here\n }\n // #endregion\n\n // #region Styles\n\n override readonly styles = styles;\n // #endregion\n}\n","/**\n * Sticky Columns Core Logic\n *\n * Pure functions for applying sticky (pinned) column positioning.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { StickyPosition } from './types';\n\n/**\n * Get columns that should be sticky on the left.\n *\n * @param columns - Array of column configurations\n * @returns Array of columns with sticky='left'\n */\nexport function getLeftStickyColumns(columns: any[]): any[] {\n return columns.filter((col) => col.sticky === 'left');\n}\n\n/**\n * Get columns that should be sticky on the right.\n *\n * @param columns - Array of column configurations\n * @returns Array of columns with sticky='right'\n */\nexport function getRightStickyColumns(columns: any[]): any[] {\n return columns.filter((col) => col.sticky === 'right');\n}\n\n/**\n * Check if any columns have sticky positioning.\n *\n * @param columns - Array of column configurations\n * @returns True if any column has sticky position\n */\nexport function hasStickyColumns(columns: any[]): boolean {\n return columns.some((col) => col.sticky === 'left' || col.sticky === 'right');\n}\n\n/**\n * Get the sticky position of a column.\n *\n * @param column - Column configuration\n * @returns The sticky position or null if not sticky\n */\nexport function getColumnStickyPosition(column: any): StickyPosition | null {\n if (column.sticky === 'left') return 'left';\n if (column.sticky === 'right') return 'right';\n return null;\n}\n\n/**\n * Calculate left offsets for sticky-left columns.\n * Returns a map of field -> offset in pixels.\n *\n * @param columns - Array of column configurations (in order)\n * @param getColumnWidth - Function to get column width by field\n * @returns Map of field to left offset\n */\nexport function calculateLeftStickyOffsets(\n columns: any[],\n getColumnWidth: (field: string) => number,\n): Map<string, number> {\n const offsets = new Map<string, number>();\n let currentOffset = 0;\n\n for (const col of columns) {\n if (col.sticky === 'left') {\n offsets.set(col.field, currentOffset);\n currentOffset += getColumnWidth(col.field);\n }\n }\n\n return offsets;\n}\n\n/**\n * Calculate right offsets for sticky-right columns.\n * Processes columns in reverse order.\n *\n * @param columns - Array of column configurations (in order)\n * @param getColumnWidth - Function to get column width by field\n * @returns Map of field to right offset\n */\nexport function calculateRightStickyOffsets(\n columns: any[],\n getColumnWidth: (field: string) => number,\n): Map<string, number> {\n const offsets = new Map<string, number>();\n let currentOffset = 0;\n\n // Process in reverse for right-sticky columns\n const reversed = [...columns].reverse();\n for (const col of reversed) {\n if (col.sticky === 'right') {\n offsets.set(col.field, currentOffset);\n currentOffset += getColumnWidth(col.field);\n }\n }\n\n return offsets;\n}\n\n/**\n * Apply sticky offsets to header and body cells.\n * This modifies the DOM elements in place.\n *\n * @param host - The grid host element\n * @param columns - Array of column configurations\n */\nexport function applyStickyOffsets(host: HTMLElement, columns: any[]): void {\n const shadowRoot = host.shadowRoot;\n if (!shadowRoot) return;\n\n const headerCells = Array.from(shadowRoot.querySelectorAll('.header-row .cell')) as HTMLElement[];\n if (!headerCells.length) return;\n\n // Build column index map for matching body cells (which use data-col, not data-field)\n const fieldToIndex = new Map<string, number>();\n columns.forEach((col, i) => {\n if (col.field) fieldToIndex.set(col.field, i);\n });\n\n // Apply left sticky\n let left = 0;\n for (const col of columns) {\n if (col.sticky === 'left') {\n const colIndex = fieldToIndex.get(col.field);\n const cell = headerCells.find((c) => c.getAttribute('data-field') === col.field);\n if (cell) {\n cell.classList.add('sticky-left');\n cell.style.position = 'sticky';\n cell.style.left = left + 'px';\n // Body cells use data-col (column index), not data-field\n if (colIndex !== undefined) {\n shadowRoot.querySelectorAll(`.data-grid-row .cell[data-col=\"${colIndex}\"]`).forEach((el) => {\n el.classList.add('sticky-left');\n (el as HTMLElement).style.position = 'sticky';\n (el as HTMLElement).style.left = left + 'px';\n });\n }\n left += cell.offsetWidth;\n }\n }\n }\n\n // Apply right sticky (process in reverse)\n let right = 0;\n for (const col of [...columns].reverse()) {\n if (col.sticky === 'right') {\n const colIndex = fieldToIndex.get(col.field);\n const cell = headerCells.find((c) => c.getAttribute('data-field') === col.field);\n if (cell) {\n cell.classList.add('sticky-right');\n cell.style.position = 'sticky';\n cell.style.right = right + 'px';\n // Body cells use data-col (column index), not data-field\n if (colIndex !== undefined) {\n shadowRoot.querySelectorAll(`.data-grid-row .cell[data-col=\"${colIndex}\"]`).forEach((el) => {\n el.classList.add('sticky-right');\n (el as HTMLElement).style.position = 'sticky';\n (el as HTMLElement).style.right = right + 'px';\n });\n }\n right += cell.offsetWidth;\n }\n }\n }\n}\n\n/**\n * Clear sticky positioning from all cells.\n *\n * @param host - The grid host element\n */\nexport function clearStickyOffsets(host: HTMLElement): void {\n const shadowRoot = host.shadowRoot;\n if (!shadowRoot) return;\n\n const cells = shadowRoot.querySelectorAll('.sticky-left, .sticky-right');\n cells.forEach((cell) => {\n cell.classList.remove('sticky-left', 'sticky-right');\n (cell as HTMLElement).style.position = '';\n (cell as HTMLElement).style.left = '';\n (cell as HTMLElement).style.right = '';\n });\n}\n","/**\n * Pinned Columns Plugin (Class-based)\n *\n * Enables column pinning (sticky left/right positioning).\n */\n\nimport { BaseGridPlugin, PLUGIN_QUERIES, type PluginQuery } from '../../core/plugin/base-plugin';\nimport type { ColumnConfig } from '../../core/types';\nimport {\n applyStickyOffsets,\n clearStickyOffsets,\n getLeftStickyColumns,\n getRightStickyColumns,\n hasStickyColumns,\n} from './pinned-columns';\nimport type { PinnedColumnsConfig } from './types';\n\n/**\n * Pinned Columns Plugin for tbw-grid\n *\n * @example\n * ```ts\n * new PinnedColumnsPlugin({ enabled: true })\n * ```\n */\nexport class PinnedColumnsPlugin extends BaseGridPlugin<PinnedColumnsConfig> {\n readonly name = 'pinnedColumns';\n override readonly version = '1.0.0';\n\n protected override get defaultConfig(): Partial<PinnedColumnsConfig> {\n return {};\n }\n\n // #region Internal State\n private isApplied = false;\n private leftOffsets = new Map<string, number>();\n private rightOffsets = new Map<string, number>();\n // #endregion\n\n // #region Lifecycle\n\n override detach(): void {\n this.leftOffsets.clear();\n this.rightOffsets.clear();\n this.isApplied = false;\n }\n // #endregion\n\n // #region Detection\n\n /**\n * Auto-detect sticky columns from column configuration.\n */\n static detect(rows: readonly unknown[], config: { columns?: ColumnConfig[] }): boolean {\n const columns = config?.columns;\n if (!Array.isArray(columns)) return false;\n return hasStickyColumns(columns);\n }\n // #endregion\n\n // #region Hooks\n\n override processColumns(columns: readonly ColumnConfig[]): ColumnConfig[] {\n // Mark that we have sticky columns to apply\n this.isApplied = hasStickyColumns([...columns]);\n return [...columns];\n }\n\n override afterRender(): void {\n if (!this.isApplied) {\n return;\n }\n\n const host = this.grid as unknown as HTMLElement;\n const columns = [...this.columns];\n\n if (!hasStickyColumns(columns)) {\n clearStickyOffsets(host);\n this.isApplied = false;\n return;\n }\n\n // Apply sticky offsets after a microtask to ensure DOM is ready\n queueMicrotask(() => {\n applyStickyOffsets(host, columns);\n });\n }\n\n /**\n * Handle inter-plugin queries.\n */\n override onPluginQuery(query: PluginQuery): unknown {\n switch (query.type) {\n case PLUGIN_QUERIES.CAN_MOVE_COLUMN: {\n // Prevent pinned columns from being moved/reordered.\n // Pinned columns have fixed positions and should not be draggable.\n const column = query.context as ColumnConfig;\n const sticky = (column as ColumnConfig & { sticky?: 'left' | 'right' }).sticky;\n if (sticky === 'left' || sticky === 'right') {\n return false;\n }\n // Also check meta.sticky for backwards compatibility\n const metaSticky = (column.meta as { sticky?: 'left' | 'right' } | undefined)?.sticky;\n if (metaSticky === 'left' || metaSticky === 'right') {\n return false;\n }\n return undefined; // Let other plugins or default behavior decide\n }\n default:\n return undefined;\n }\n }\n // #endregion\n\n // #region Public API\n\n /**\n * Re-apply sticky offsets (e.g., after column resize).\n */\n refreshStickyOffsets(): void {\n const columns = [...this.columns];\n applyStickyOffsets(this.grid as unknown as HTMLElement, columns);\n }\n\n /**\n * Get columns pinned to the left.\n */\n getLeftPinnedColumns(): ColumnConfig[] {\n const columns = [...this.columns];\n return getLeftStickyColumns(columns);\n }\n\n /**\n * Get columns pinned to the right.\n */\n getRightPinnedColumns(): ColumnConfig[] {\n const columns = [...this.columns];\n return getRightStickyColumns(columns);\n }\n\n /**\n * Clear all sticky positioning.\n */\n clearStickyPositions(): void {\n clearStickyOffsets(this.grid as unknown as HTMLElement);\n }\n\n /**\n * Report horizontal scroll boundary offsets for pinned columns.\n * Used by keyboard navigation to ensure focused cells aren't hidden behind sticky columns.\n */\n override getHorizontalScrollOffsets(\n rowEl?: HTMLElement,\n focusedCell?: HTMLElement,\n ): { left: number; right: number; skipScroll?: boolean } | undefined {\n if (!this.isApplied) {\n return undefined;\n }\n\n let left = 0;\n let right = 0;\n\n if (rowEl) {\n // Calculate from rendered cells in the row\n const stickyLeftCells = rowEl.querySelectorAll('.sticky-left');\n const stickyRightCells = rowEl.querySelectorAll('.sticky-right');\n stickyLeftCells.forEach((el) => {\n left += (el as HTMLElement).offsetWidth;\n });\n stickyRightCells.forEach((el) => {\n right += (el as HTMLElement).offsetWidth;\n });\n } else {\n // Fall back to header row if no row element provided\n const host = this.grid as unknown as HTMLElement;\n const shadowRoot = host.shadowRoot;\n if (shadowRoot) {\n const headerCells = shadowRoot.querySelectorAll('.header-row .cell');\n headerCells.forEach((cell) => {\n if (cell.classList.contains('sticky-left')) {\n left += (cell as HTMLElement).offsetWidth;\n } else if (cell.classList.contains('sticky-right')) {\n right += (cell as HTMLElement).offsetWidth;\n }\n });\n }\n }\n\n // Skip horizontal scrolling if focused cell is pinned (it's always visible)\n const skipScroll =\n focusedCell?.classList.contains('sticky-left') || focusedCell?.classList.contains('sticky-right');\n\n return { left, right, skipScroll };\n }\n // #endregion\n}\n","/**\n * Status Bar Rendering Logic\n *\n * Pure functions for creating and updating the status bar UI.\n * Includes both info bar and aggregation row rendering.\n */\n\nimport { getAggregator } from '../../core/internal/aggregators';\nimport type { ColumnConfig } from '../../core/types';\nimport type {\n AggregationRowConfig,\n AggregatorConfig,\n AggregatorDefinition,\n PinnedRowsConfig,\n PinnedRowsContext,\n PinnedRowsPanel,\n} from './types';\n\n/**\n * Check if an aggregator definition is a full config object (with aggFunc and optional formatter).\n */\nfunction isAggregatorConfig(def: AggregatorDefinition): def is AggregatorConfig {\n return typeof def === 'object' && def !== null && 'aggFunc' in def;\n}\n\n/**\n * Creates the info bar DOM element with all configured panels.\n *\n * @param config - The status bar configuration\n * @param context - The current grid context for rendering\n * @returns The complete info bar element\n */\nexport function createInfoBarElement(config: PinnedRowsConfig, context: PinnedRowsContext): HTMLElement {\n const pinnedRows = document.createElement('div');\n pinnedRows.className = 'tbw-pinned-rows';\n pinnedRows.setAttribute('role', 'presentation');\n pinnedRows.setAttribute('aria-live', 'polite');\n\n const left = document.createElement('div');\n left.className = 'tbw-pinned-rows-left';\n\n const center = document.createElement('div');\n center.className = 'tbw-pinned-rows-center';\n\n const right = document.createElement('div');\n right.className = 'tbw-pinned-rows-right';\n\n // Default panels - row count\n if (config.showRowCount !== false) {\n const rowCount = document.createElement('span');\n rowCount.className = 'tbw-status-panel tbw-status-panel-row-count';\n rowCount.textContent = `Total: ${context.totalRows} rows`;\n left.appendChild(rowCount);\n }\n\n // Filtered count panel (only shows when filter is active)\n if (config.showFilteredCount && context.filteredRows !== context.totalRows) {\n const filteredCount = document.createElement('span');\n filteredCount.className = 'tbw-status-panel tbw-status-panel-filtered-count';\n filteredCount.textContent = `Filtered: ${context.filteredRows}`;\n left.appendChild(filteredCount);\n }\n\n // Selected count panel (only shows when rows are selected)\n if (config.showSelectedCount && context.selectedRows > 0) {\n const selectedCount = document.createElement('span');\n selectedCount.className = 'tbw-status-panel tbw-status-panel-selected-count';\n selectedCount.textContent = `Selected: ${context.selectedRows}`;\n right.appendChild(selectedCount);\n }\n\n // Render custom panels\n if (config.customPanels) {\n for (const panel of config.customPanels) {\n const panelEl = renderCustomPanel(panel, context);\n switch (panel.position) {\n case 'left':\n left.appendChild(panelEl);\n break;\n case 'center':\n center.appendChild(panelEl);\n break;\n case 'right':\n right.appendChild(panelEl);\n break;\n }\n }\n }\n\n pinnedRows.appendChild(left);\n pinnedRows.appendChild(center);\n pinnedRows.appendChild(right);\n\n return pinnedRows;\n}\n\n/**\n * Creates a container for aggregation rows at top or bottom.\n *\n * @param position - 'top' or 'bottom'\n * @returns The container element\n */\nexport function createAggregationContainer(position: 'top' | 'bottom'): HTMLElement {\n const container = document.createElement('div');\n container.className = `tbw-aggregation-rows tbw-aggregation-rows-${position}`;\n // Use presentation role since aggregation rows are outside the role=\"grid\" element for layout reasons\n container.setAttribute('role', 'presentation');\n return container;\n}\n\n/**\n * Renders aggregation rows into a container.\n *\n * @param container - The container to render into\n * @param rows - Aggregation row configurations\n * @param columns - Current column configuration\n * @param dataRows - Current row data for aggregation calculations\n */\nexport function renderAggregationRows(\n container: HTMLElement,\n rows: AggregationRowConfig[],\n columns: ColumnConfig[],\n dataRows: unknown[],\n): void {\n container.innerHTML = '';\n\n for (const rowConfig of rows) {\n const rowEl = document.createElement('div');\n rowEl.className = 'tbw-aggregation-row';\n // Use presentation role since aggregation rows are outside the role=\"grid\" element\n rowEl.setAttribute('role', 'presentation');\n if (rowConfig.id) {\n rowEl.setAttribute('data-aggregation-id', rowConfig.id);\n }\n\n if (rowConfig.fullWidth) {\n // Full-width mode: single cell spanning all columns\n const cell = document.createElement('div');\n cell.className = 'tbw-aggregation-cell tbw-aggregation-cell-full';\n cell.style.gridColumn = '1 / -1';\n cell.textContent = rowConfig.label || '';\n rowEl.appendChild(cell);\n } else {\n // Per-column mode: one cell per column with aggregated/static values\n for (const col of columns) {\n const cell = document.createElement('div');\n cell.className = 'tbw-aggregation-cell';\n cell.setAttribute('data-field', col.field);\n\n let value: unknown;\n let formatter: ((value: unknown, field: string, column?: ColumnConfig) => string) | undefined;\n\n // Check for aggregator first\n const aggDef = rowConfig.aggregators?.[col.field];\n if (aggDef) {\n // Handle both simple ref and full config object\n if (isAggregatorConfig(aggDef)) {\n const aggFn = getAggregator(aggDef.aggFunc);\n if (aggFn) {\n value = aggFn(dataRows, col.field, col);\n }\n formatter = aggDef.formatter;\n } else {\n const aggFn = getAggregator(aggDef);\n if (aggFn) {\n value = aggFn(dataRows, col.field, col);\n }\n }\n } else if (rowConfig.cells && Object.prototype.hasOwnProperty.call(rowConfig.cells, col.field)) {\n // Static or computed cell value\n const staticVal = rowConfig.cells[col.field];\n if (typeof staticVal === 'function') {\n value = staticVal(dataRows, col.field, col);\n } else {\n value = staticVal;\n }\n }\n\n // Apply formatter if provided, otherwise convert to string\n if (value != null) {\n cell.textContent = formatter ? formatter(value, col.field, col) : String(value);\n } else {\n cell.textContent = '';\n }\n rowEl.appendChild(cell);\n }\n }\n\n container.appendChild(rowEl);\n }\n}\n\n/**\n * Renders a custom panel element.\n *\n * @param panel - The panel definition\n * @param context - The current grid context\n * @returns The panel DOM element\n */\nfunction renderCustomPanel(panel: PinnedRowsPanel, context: PinnedRowsContext): HTMLElement {\n const panelEl = document.createElement('div');\n panelEl.className = 'tbw-status-panel tbw-status-panel-custom';\n panelEl.id = `status-panel-${panel.id}`;\n\n const content = panel.render(context);\n\n if (typeof content === 'string') {\n panelEl.innerHTML = content;\n } else {\n panelEl.appendChild(content);\n }\n\n return panelEl;\n}\n\n/**\n * Builds the status bar context from grid state and plugin states.\n *\n * @param rows - Current row data\n * @param columns - Current column configuration\n * @param grid - Grid element reference\n * @param selectionState - Optional selection plugin state\n * @param filterState - Optional filtering plugin state\n * @returns The status bar context\n */\nexport function buildContext(\n rows: unknown[],\n columns: unknown[],\n grid: HTMLElement,\n selectionState?: { selected: Set<number> } | null,\n filterState?: { cachedResult: unknown[] | null } | null,\n): PinnedRowsContext {\n return {\n totalRows: rows.length,\n filteredRows: filterState?.cachedResult?.length ?? rows.length,\n selectedRows: selectionState?.selected?.size ?? 0,\n columns: columns as PinnedRowsContext['columns'],\n rows,\n grid,\n };\n}\n\n// Keep old name as alias for backwards compatibility\nexport const createPinnedRowsElement = createInfoBarElement;\n","/**\n * Pinned Rows Plugin (Class-based)\n *\n * Adds info bars and aggregation rows to the grid.\n * - Info bar: Shows row counts, selection info, and custom panels\n * - Aggregation rows: Footer/header rows with computed values (sum, avg, etc.)\n */\n\nimport { BaseGridPlugin } from '../../core/plugin/base-plugin';\nimport type { ColumnConfig } from '../../core/types';\nimport { buildContext, createAggregationContainer, createInfoBarElement, renderAggregationRows } from './pinned-rows';\nimport styles from './pinned-rows.css?inline';\nimport type { AggregationRowConfig, PinnedRowsConfig, PinnedRowsContext, PinnedRowsPanel } from './types';\n\n/**\n * Pinned Rows Plugin for tbw-grid\n *\n * @example\n * ```ts\n * new PinnedRowsPlugin({\n * enabled: true,\n * position: 'bottom',\n * showRowCount: true,\n * showSelectedCount: true,\n * aggregationRows: [\n * { id: 'totals', position: 'bottom', values: { amount: 'sum' } },\n * ],\n * })\n * ```\n */\nexport class PinnedRowsPlugin extends BaseGridPlugin<PinnedRowsConfig> {\n readonly name = 'pinnedRows';\n override readonly version = '1.0.0';\n\n protected override get defaultConfig(): Partial<PinnedRowsConfig> {\n return {\n position: 'bottom',\n showRowCount: true,\n showSelectedCount: true,\n showFilteredCount: true,\n };\n }\n\n // #region Internal State\n private infoBarElement: HTMLElement | null = null;\n private topAggregationContainer: HTMLElement | null = null;\n private bottomAggregationContainer: HTMLElement | null = null;\n private footerWrapper: HTMLElement | null = null;\n // #endregion\n\n // #region Lifecycle\n override detach(): void {\n if (this.infoBarElement) {\n this.infoBarElement.remove();\n this.infoBarElement = null;\n }\n if (this.topAggregationContainer) {\n this.topAggregationContainer.remove();\n this.topAggregationContainer = null;\n }\n if (this.bottomAggregationContainer) {\n this.bottomAggregationContainer.remove();\n this.bottomAggregationContainer = null;\n }\n if (this.footerWrapper) {\n this.footerWrapper.remove();\n this.footerWrapper = null;\n }\n }\n // #endregion\n\n // #region Hooks\n override afterRender(): void {\n const shadowRoot = this.shadowRoot;\n if (!shadowRoot) return;\n\n // Use .tbw-scroll-area so footer is inside the horizontal scroll area,\n // otherwise fall back to .tbw-grid-content or root container\n const container =\n shadowRoot.querySelector('.tbw-scroll-area') ??\n shadowRoot.querySelector('.tbw-grid-content') ??\n shadowRoot.children[0];\n if (!container) return;\n\n // Build context with plugin states\n const selectionState = this.getSelectionState();\n const filterState = this.getFilterState();\n\n const context = buildContext(\n this.rows as unknown[],\n this.columns as unknown[],\n this.grid as unknown as HTMLElement,\n selectionState,\n filterState,\n );\n\n // #region Handle Aggregation Rows\n const aggregationRows = this.config.aggregationRows || [];\n const topRows = aggregationRows.filter((r) => r.position === 'top');\n const bottomRows = aggregationRows.filter((r) => r.position !== 'top');\n\n // Top aggregation rows\n if (topRows.length > 0) {\n if (!this.topAggregationContainer) {\n this.topAggregationContainer = createAggregationContainer('top');\n const header = shadowRoot.querySelector('.header');\n if (header && header.nextSibling) {\n container.insertBefore(this.topAggregationContainer, header.nextSibling);\n } else {\n container.appendChild(this.topAggregationContainer);\n }\n }\n renderAggregationRows(\n this.topAggregationContainer,\n topRows,\n this.visibleColumns as ColumnConfig[],\n this.rows as unknown[],\n );\n } else if (this.topAggregationContainer) {\n this.topAggregationContainer.remove();\n this.topAggregationContainer = null;\n }\n\n // Handle footer\n const hasInfoContent =\n this.config.showRowCount !== false ||\n (this.config.showSelectedCount && context.selectedRows > 0) ||\n (this.config.showFilteredCount && context.filteredRows !== context.totalRows) ||\n (this.config.customPanels && this.config.customPanels.length > 0);\n const hasBottomInfoBar = hasInfoContent && this.config.position !== 'top';\n const needsFooter = bottomRows.length > 0 || hasBottomInfoBar;\n\n // Handle top info bar\n if (hasInfoContent && this.config.position === 'top') {\n if (!this.infoBarElement) {\n this.infoBarElement = createInfoBarElement(this.config, context);\n container.insertBefore(this.infoBarElement, container.firstChild);\n } else {\n const newInfoBar = createInfoBarElement(this.config, context);\n this.infoBarElement.replaceWith(newInfoBar);\n this.infoBarElement = newInfoBar;\n }\n } else if (this.config.position === 'top' && this.infoBarElement) {\n this.infoBarElement.remove();\n this.infoBarElement = null;\n }\n\n // Create/manage footer wrapper\n if (needsFooter) {\n if (!this.footerWrapper) {\n this.footerWrapper = document.createElement('div');\n this.footerWrapper.className = 'tbw-footer';\n container.appendChild(this.footerWrapper);\n }\n\n this.footerWrapper.innerHTML = '';\n\n if (bottomRows.length > 0) {\n if (!this.bottomAggregationContainer) {\n this.bottomAggregationContainer = createAggregationContainer('bottom');\n }\n this.footerWrapper.appendChild(this.bottomAggregationContainer);\n renderAggregationRows(\n this.bottomAggregationContainer,\n bottomRows,\n this.visibleColumns as ColumnConfig[],\n this.rows as unknown[],\n );\n }\n\n if (hasBottomInfoBar) {\n this.infoBarElement = createInfoBarElement(this.config, context);\n this.footerWrapper.appendChild(this.infoBarElement);\n }\n } else {\n this.cleanupFooter();\n }\n // #endregion\n }\n // #endregion\n\n // #region Private Methods\n private cleanup(): void {\n if (this.infoBarElement) {\n this.infoBarElement.remove();\n this.infoBarElement = null;\n }\n if (this.topAggregationContainer) {\n this.topAggregationContainer.remove();\n this.topAggregationContainer = null;\n }\n if (this.bottomAggregationContainer) {\n this.bottomAggregationContainer.remove();\n this.bottomAggregationContainer = null;\n }\n if (this.footerWrapper) {\n this.footerWrapper.remove();\n this.footerWrapper = null;\n }\n }\n\n private cleanupFooter(): void {\n if (this.footerWrapper) {\n this.footerWrapper.remove();\n this.footerWrapper = null;\n }\n if (this.bottomAggregationContainer) {\n this.bottomAggregationContainer.remove();\n this.bottomAggregationContainer = null;\n }\n if (this.infoBarElement && this.config.position !== 'top') {\n this.infoBarElement.remove();\n this.infoBarElement = null;\n }\n }\n\n private getSelectionState(): { selected: Set<number> } | null {\n // Try to get selection plugin state\n try {\n const grid = this.grid as any;\n return grid?.getPluginState?.('selection') ?? null;\n } catch {\n return null;\n }\n }\n\n private getFilterState(): { cachedResult: unknown[] | null } | null {\n try {\n const grid = this.grid as any;\n return grid?.getPluginState?.('filtering') ?? null;\n } catch {\n return null;\n }\n }\n // #endregion\n\n // #region Public API\n /**\n * Refresh the status bar to reflect current grid state.\n */\n refresh(): void {\n this.requestRender();\n }\n\n /**\n * Get the current status bar context.\n * @returns The context with row counts and other info\n */\n getContext(): PinnedRowsContext {\n const selectionState = this.getSelectionState();\n const filterState = this.getFilterState();\n\n return buildContext(\n this.rows as unknown[],\n this.columns as unknown[],\n this.grid as unknown as HTMLElement,\n selectionState,\n filterState,\n );\n }\n\n /**\n * Add a custom panel to the info bar.\n * @param panel - The panel configuration to add\n */\n addPanel(panel: PinnedRowsPanel): void {\n if (!this.config.customPanels) {\n this.config.customPanels = [];\n }\n this.config.customPanels.push(panel);\n this.requestRender();\n }\n\n /**\n * Remove a custom panel by ID.\n * @param id - The panel ID to remove\n */\n removePanel(id: string): void {\n if (this.config.customPanels) {\n this.config.customPanels = this.config.customPanels.filter((p) => p.id !== id);\n this.requestRender();\n }\n }\n\n /**\n * Add an aggregation row.\n * @param row - The aggregation row configuration\n */\n addAggregationRow(row: AggregationRowConfig): void {\n if (!this.config.aggregationRows) {\n this.config.aggregationRows = [];\n }\n this.config.aggregationRows.push(row);\n this.requestRender();\n }\n\n /**\n * Remove an aggregation row by ID.\n * @param id - The aggregation row ID to remove\n */\n removeAggregationRow(id: string): void {\n if (this.config.aggregationRows) {\n this.config.aggregationRows = this.config.aggregationRows.filter((r) => r.id !== id);\n this.requestRender();\n }\n }\n // #endregion\n\n // #region Styles\n override readonly styles = styles;\n // #endregion\n}\n","import { getValueAggregator } from '../../core/internal/aggregators';\nimport type { PivotConfig } from './types';\n\n// Re-export for backward compatibility within pivot plugin\nexport const getPivotAggregator = getValueAggregator;\n\nexport function validatePivotConfig(config: PivotConfig): string[] {\n const errors: string[] = [];\n\n if (!config.rowGroupFields?.length && !config.columnGroupFields?.length) {\n errors.push('At least one row or column group field is required');\n }\n\n if (!config.valueFields?.length) {\n errors.push('At least one value field is required');\n }\n\n return errors;\n}\n\nexport function createValueKey(columnValues: string[], valueField: string): string {\n return [...columnValues, valueField].join('|');\n}\n","import { createValueKey, getPivotAggregator } from './pivot-model';\nimport type { PivotConfig, PivotResult, PivotRow, PivotValueField } from './types';\n\nexport type PivotDataRow = Record<string, unknown>;\n\n/**\n * Build a hierarchical pivot result from flat data.\n * Supports multiple row group fields for nested hierarchy.\n */\nexport function buildPivot(rows: PivotDataRow[], config: PivotConfig): PivotResult {\n const rowGroupFields = config.rowGroupFields ?? [];\n const columnGroupFields = config.columnGroupFields ?? [];\n const valueFields = config.valueFields ?? [];\n\n // Get unique column combinations\n const columnKeys = getUniqueColumnKeys(rows, columnGroupFields);\n\n // Build hierarchical pivot rows\n const pivotRows = buildHierarchicalPivotRows(\n rows,\n rowGroupFields,\n columnGroupFields,\n columnKeys,\n valueFields,\n 0, // starting depth\n '', // parent key prefix\n );\n\n // Calculate grand totals\n const totals = calculateTotals(pivotRows, columnKeys, valueFields);\n const grandTotal = Object.values(totals).reduce((a, b) => a + b, 0);\n\n return {\n rows: pivotRows,\n columnKeys,\n totals,\n grandTotal,\n };\n}\n\n/**\n * Get unique column key combinations from the data.\n */\nexport function getUniqueColumnKeys(rows: PivotDataRow[], columnFields: string[]): string[] {\n if (columnFields.length === 0) return ['value'];\n\n const keys = new Set<string>();\n for (const row of rows) {\n const key = columnFields.map((f) => String(row[f] ?? '')).join('|');\n keys.add(key);\n }\n return [...keys].sort();\n}\n\n/**\n * Group rows by a single field.\n */\nexport function groupByField(rows: PivotDataRow[], field: string): Map<string, PivotDataRow[]> {\n const groups = new Map<string, PivotDataRow[]>();\n\n for (const row of rows) {\n const key = String(row[field] ?? '');\n const existing = groups.get(key);\n if (existing) {\n existing.push(row);\n } else {\n groups.set(key, [row]);\n }\n }\n\n return groups;\n}\n\n/**\n * Group rows by multiple fields (legacy flat grouping).\n */\nexport function groupByFields(rows: PivotDataRow[], fields: string[]): Map<string, PivotDataRow[]> {\n const groups = new Map<string, PivotDataRow[]>();\n\n for (const row of rows) {\n const key = fields.map((f) => String(row[f] ?? '')).join('|');\n const existing = groups.get(key);\n if (existing) {\n existing.push(row);\n } else {\n groups.set(key, [row]);\n }\n }\n\n return groups;\n}\n\n/**\n * Build hierarchical pivot rows recursively.\n * Each level of rowGroupFields creates a new depth level.\n */\nexport function buildHierarchicalPivotRows(\n rows: PivotDataRow[],\n rowGroupFields: string[],\n columnFields: string[],\n columnKeys: string[],\n valueFields: PivotValueField[],\n depth: number,\n parentKey: string,\n): PivotRow[] {\n const result: PivotRow[] = [];\n\n // If no more row group fields, we're at the leaf level - aggregate the data\n if (rowGroupFields.length === 0) {\n // This shouldn't normally happen as we need at least one grouping field\n // But handle it by creating a single aggregated row\n const values = aggregateValues(rows, columnFields, columnKeys, valueFields);\n const total = calculateRowTotal(values);\n result.push({\n rowKey: parentKey || 'all',\n rowLabel: parentKey || 'All',\n depth,\n values,\n total,\n isGroup: false,\n rowCount: rows.length,\n });\n return result;\n }\n\n // Get the current grouping field\n const currentField = rowGroupFields[0];\n const remainingFields = rowGroupFields.slice(1);\n const hasChildren = remainingFields.length > 0;\n\n // Group rows by current field\n const grouped = groupByField(rows, currentField);\n\n for (const [groupValue, groupRows] of grouped) {\n const rowKey = parentKey ? `${parentKey}|${groupValue}` : groupValue;\n\n // Aggregate values for this group (sum of all child rows)\n const values = aggregateValues(groupRows, columnFields, columnKeys, valueFields);\n const total = calculateRowTotal(values);\n\n // Build children if there are more grouping levels\n let children: PivotRow[] | undefined;\n if (hasChildren) {\n children = buildHierarchicalPivotRows(\n groupRows,\n remainingFields,\n columnFields,\n columnKeys,\n valueFields,\n depth + 1,\n rowKey,\n );\n }\n\n result.push({\n rowKey,\n rowLabel: groupValue || '(blank)',\n depth,\n values,\n total,\n isGroup: hasChildren,\n children,\n rowCount: groupRows.length,\n });\n }\n\n return result;\n}\n\n/**\n * Aggregate values for a set of rows across all column keys.\n */\nexport function aggregateValues(\n rows: PivotDataRow[],\n columnFields: string[],\n columnKeys: string[],\n valueFields: PivotValueField[],\n): Record<string, number | null> {\n const values: Record<string, number | null> = {};\n\n for (const colKey of columnKeys) {\n for (const vf of valueFields) {\n // Filter rows that match this column key\n const matchingRows =\n columnFields.length > 0\n ? rows.filter((r) => columnFields.map((f) => String(r[f] ?? '')).join('|') === colKey)\n : rows;\n\n const nums = matchingRows.map((r) => Number(r[vf.field]) || 0);\n const aggregator = getPivotAggregator(vf.aggFunc);\n const aggregatedResult = nums.length > 0 ? aggregator(nums) : null;\n\n const valueKey = createValueKey([colKey], vf.field);\n values[valueKey] = aggregatedResult;\n }\n }\n\n return values;\n}\n\n/**\n * Calculate the total for a row's values.\n */\nexport function calculateRowTotal(values: Record<string, number | null>): number {\n let sum = 0;\n for (const val of Object.values(values)) {\n sum += val ?? 0;\n }\n return sum;\n}\n\n/**\n * Legacy flat pivot row building (for backwards compatibility).\n */\nexport function buildPivotRows(\n groupedData: Map<string, PivotDataRow[]>,\n columnFields: string[],\n columnKeys: string[],\n valueFields: PivotValueField[],\n depth: number,\n): PivotRow[] {\n const result: PivotRow[] = [];\n\n for (const [rowKey, groupRows] of groupedData) {\n const values = aggregateValues(groupRows, columnFields, columnKeys, valueFields);\n const total = calculateRowTotal(values);\n\n result.push({\n rowKey,\n rowLabel: rowKey || '(blank)',\n depth,\n values,\n total,\n isGroup: false,\n rowCount: groupRows.length,\n });\n }\n\n return result;\n}\n\n/**\n * Calculate grand totals across all pivot rows.\n */\nexport function calculateTotals(\n pivotRows: PivotRow[],\n columnKeys: string[],\n valueFields: PivotValueField[],\n): Record<string, number> {\n const totals: Record<string, number> = {};\n\n // Recursively sum all rows (including nested children)\n function sumRows(rows: PivotRow[]) {\n for (const row of rows) {\n // Only count leaf rows to avoid double-counting\n if (!row.isGroup || !row.children?.length) {\n for (const colKey of columnKeys) {\n for (const vf of valueFields) {\n const valueKey = createValueKey([colKey], vf.field);\n totals[valueKey] = (totals[valueKey] ?? 0) + (row.values[valueKey] ?? 0);\n }\n }\n } else if (row.children) {\n sumRows(row.children);\n }\n }\n }\n\n sumRows(pivotRows);\n return totals;\n}\n\n/**\n * Flatten hierarchical pivot rows for rendering.\n * Respects expanded state - only includes children of expanded groups.\n */\nexport function flattenPivotRows(rows: PivotRow[], expandedKeys?: Set<string>, defaultExpanded = true): PivotRow[] {\n const result: PivotRow[] = [];\n\n function flatten(row: PivotRow) {\n result.push(row);\n\n // Check if this group is expanded\n const isExpanded = expandedKeys ? expandedKeys.has(row.rowKey) : defaultExpanded;\n\n // Only include children if expanded\n if (row.children && isExpanded) {\n for (const child of row.children) {\n flatten(child);\n }\n }\n }\n\n for (const row of rows) {\n flatten(row);\n }\n\n return result;\n}\n\n/**\n * Get all group keys from pivot rows (for expand all / collapse all).\n */\nexport function getAllGroupKeys(rows: PivotRow[]): string[] {\n const keys: string[] = [];\n\n function collectKeys(row: PivotRow) {\n if (row.isGroup) {\n keys.push(row.rowKey);\n }\n if (row.children) {\n for (const child of row.children) {\n collectKeys(child);\n }\n }\n }\n\n for (const row of rows) {\n collectKeys(row);\n }\n\n return keys;\n}\n","/**\n * Pivot Tool Panel Rendering\n *\n * Pure functions for rendering the pivot configuration panel.\n * Separated from PivotPlugin for better code organization.\n */\n\nimport type { AggFunc, PivotConfig, PivotValueField } from './types';\n\n/** All available aggregation functions */\nexport const AGG_FUNCS: AggFunc[] = ['sum', 'avg', 'count', 'min', 'max', 'first', 'last'];\n\n/** Field info for available fields */\nexport interface FieldInfo {\n field: string;\n header: string;\n}\n\n/** Callbacks for panel interactions */\nexport interface PanelCallbacks {\n onTogglePivot: (enabled: boolean) => void;\n onAddFieldToZone: (field: string, zone: 'rowGroups' | 'columnGroups') => void;\n onRemoveFieldFromZone: (field: string, zone: 'rowGroups' | 'columnGroups') => void;\n onAddValueField: (field: string, aggFunc: AggFunc) => void;\n onRemoveValueField: (field: string) => void;\n onUpdateValueAggFunc: (field: string, aggFunc: AggFunc) => void;\n onOptionChange: (option: 'showTotals' | 'showGrandTotal', value: boolean) => void;\n getAvailableFields: () => FieldInfo[];\n}\n\n/** Internal context passed to rendering functions */\ninterface RenderContext {\n config: PivotConfig;\n callbacks: PanelCallbacks;\n signal: AbortSignal;\n}\n\n/**\n * Render the complete pivot panel content.\n * Returns a cleanup function that removes all event listeners and DOM elements.\n */\nexport function renderPivotPanel(\n container: HTMLElement,\n config: PivotConfig,\n isActive: boolean,\n callbacks: PanelCallbacks,\n): () => void {\n // Create AbortController for automatic listener cleanup\n const controller = new AbortController();\n const ctx: RenderContext = { config, callbacks, signal: controller.signal };\n\n const wrapper = document.createElement('div');\n wrapper.className = 'tbw-pivot-panel';\n\n // Options section (at top, includes pivot toggle)\n wrapper.appendChild(createSection('Options', () => createOptionsPanel(isActive, ctx)));\n\n // Row Groups section\n wrapper.appendChild(createSection('Row Groups', () => createFieldZone('rowGroups', ctx)));\n\n // Column Groups section\n wrapper.appendChild(createSection('Column Groups', () => createFieldZone('columnGroups', ctx)));\n\n // Values section\n wrapper.appendChild(createSection('Values', () => createValuesZone(ctx)));\n\n // Available fields section\n wrapper.appendChild(createSection('Available Fields', () => createAvailableFieldsZone(ctx)));\n\n container.appendChild(wrapper);\n\n // Cleanup: abort all listeners, then remove DOM\n return () => {\n controller.abort();\n wrapper.remove();\n };\n}\n\n/**\n * Create a collapsible section wrapper.\n */\nfunction createSection(title: string, contentFactory: () => HTMLElement): HTMLElement {\n const section = document.createElement('div');\n section.className = 'tbw-pivot-section';\n\n const header = document.createElement('div');\n header.className = 'tbw-pivot-section-header';\n header.textContent = title;\n\n const content = document.createElement('div');\n content.className = 'tbw-pivot-section-content';\n content.appendChild(contentFactory());\n\n section.appendChild(header);\n section.appendChild(content);\n\n return section;\n}\n\n/**\n * Create a drop zone for row/column group fields.\n */\nfunction createFieldZone(zoneType: 'rowGroups' | 'columnGroups', ctx: RenderContext): HTMLElement {\n const { config, callbacks, signal } = ctx;\n const zone = document.createElement('div');\n zone.className = 'tbw-pivot-drop-zone';\n zone.setAttribute('data-zone', zoneType);\n\n const currentFields = zoneType === 'rowGroups' ? (config.rowGroupFields ?? []) : (config.columnGroupFields ?? []);\n\n if (currentFields.length === 0) {\n const placeholder = document.createElement('div');\n placeholder.className = 'tbw-pivot-placeholder';\n placeholder.textContent = 'Drag fields here or click to add';\n zone.appendChild(placeholder);\n } else {\n for (const field of currentFields) {\n zone.appendChild(createFieldChip(field, zoneType, ctx));\n }\n }\n\n // Drop handling\n zone.addEventListener(\n 'dragover',\n (e) => {\n e.preventDefault();\n zone.classList.add('drag-over');\n },\n { signal },\n );\n\n zone.addEventListener(\n 'dragleave',\n () => {\n zone.classList.remove('drag-over');\n },\n { signal },\n );\n\n zone.addEventListener(\n 'drop',\n (e) => {\n e.preventDefault();\n zone.classList.remove('drag-over');\n\n const field = e.dataTransfer?.getData('text/plain');\n if (field) {\n callbacks.onAddFieldToZone(field, zoneType);\n }\n },\n { signal },\n );\n\n return zone;\n}\n\n/**\n * Create a field chip for row/column zones.\n */\nfunction createFieldChip(field: string, zoneType: 'rowGroups' | 'columnGroups', ctx: RenderContext): HTMLElement {\n const { callbacks, signal } = ctx;\n const chip = document.createElement('div');\n chip.className = 'tbw-pivot-field-chip';\n chip.draggable = true;\n\n const fieldInfo = callbacks.getAvailableFields().find((f) => f.field === field);\n const label = document.createElement('span');\n label.className = 'tbw-pivot-chip-label';\n label.textContent = fieldInfo?.header ?? field;\n\n const removeBtn = document.createElement('button');\n removeBtn.className = 'tbw-pivot-chip-remove';\n removeBtn.innerHTML = '×';\n removeBtn.title = 'Remove field';\n removeBtn.addEventListener(\n 'click',\n (e) => {\n e.stopPropagation();\n callbacks.onRemoveFieldFromZone(field, zoneType);\n },\n { signal },\n );\n\n chip.appendChild(label);\n chip.appendChild(removeBtn);\n\n // Drag handling for reordering\n chip.addEventListener(\n 'dragstart',\n (e) => {\n e.dataTransfer?.setData('text/plain', field);\n e.dataTransfer?.setData('source-zone', zoneType);\n chip.classList.add('dragging');\n },\n { signal },\n );\n\n chip.addEventListener(\n 'dragend',\n () => {\n chip.classList.remove('dragging');\n },\n { signal },\n );\n\n return chip;\n}\n\n/**\n * Create the values zone with aggregation controls.\n */\nfunction createValuesZone(ctx: RenderContext): HTMLElement {\n const { config, callbacks, signal } = ctx;\n const zone = document.createElement('div');\n zone.className = 'tbw-pivot-drop-zone tbw-pivot-values-zone';\n zone.setAttribute('data-zone', 'values');\n\n const currentValues = config.valueFields ?? [];\n\n if (currentValues.length === 0) {\n const placeholder = document.createElement('div');\n placeholder.className = 'tbw-pivot-placeholder';\n placeholder.textContent = 'Drag numeric fields here for aggregation';\n zone.appendChild(placeholder);\n } else {\n for (const valueField of currentValues) {\n zone.appendChild(createValueChip(valueField, ctx));\n }\n }\n\n // Drop handling with signal for cleanup\n zone.addEventListener(\n 'dragover',\n (e) => {\n e.preventDefault();\n zone.classList.add('drag-over');\n },\n { signal },\n );\n\n zone.addEventListener(\n 'dragleave',\n () => {\n zone.classList.remove('drag-over');\n },\n { signal },\n );\n\n zone.addEventListener(\n 'drop',\n (e) => {\n e.preventDefault();\n zone.classList.remove('drag-over');\n const field = e.dataTransfer?.getData('text/plain');\n if (field) {\n callbacks.onAddValueField(field, 'sum');\n }\n },\n { signal },\n );\n\n return zone;\n}\n\n/**\n * Create a value chip with aggregation selector.\n */\nfunction createValueChip(valueField: PivotValueField, ctx: RenderContext): HTMLElement {\n const { callbacks, signal } = ctx;\n const chip = document.createElement('div');\n chip.className = 'tbw-pivot-field-chip tbw-pivot-value-chip';\n\n const fieldInfo = callbacks.getAvailableFields().find((f) => f.field === valueField.field);\n\n const labelWrapper = document.createElement('div');\n labelWrapper.className = 'tbw-pivot-value-label-wrapper';\n\n const label = document.createElement('span');\n label.className = 'tbw-pivot-chip-label';\n label.textContent = fieldInfo?.header ?? valueField.field;\n\n const aggSelect = document.createElement('select');\n aggSelect.className = 'tbw-pivot-agg-select';\n aggSelect.title = 'Aggregation function';\n\n for (const aggFunc of AGG_FUNCS) {\n const option = document.createElement('option');\n option.value = aggFunc;\n option.textContent = aggFunc.toUpperCase();\n option.selected = aggFunc === valueField.aggFunc;\n aggSelect.appendChild(option);\n }\n\n aggSelect.addEventListener(\n 'change',\n () => {\n callbacks.onUpdateValueAggFunc(valueField.field, aggSelect.value as AggFunc);\n },\n { signal },\n );\n\n const removeBtn = document.createElement('button');\n removeBtn.className = 'tbw-pivot-chip-remove';\n removeBtn.innerHTML = '×';\n removeBtn.title = 'Remove value field';\n removeBtn.addEventListener(\n 'click',\n (e) => {\n e.stopPropagation();\n callbacks.onRemoveValueField(valueField.field);\n },\n { signal },\n );\n\n labelWrapper.appendChild(label);\n labelWrapper.appendChild(aggSelect);\n\n chip.appendChild(labelWrapper);\n chip.appendChild(removeBtn);\n\n return chip;\n}\n\n/**\n * Create the available fields zone.\n */\nfunction createAvailableFieldsZone(ctx: RenderContext): HTMLElement {\n const { config, callbacks, signal } = ctx;\n const zone = document.createElement('div');\n zone.className = 'tbw-pivot-available-fields';\n\n const allFields = callbacks.getAvailableFields();\n const usedFields = new Set([\n ...(config.rowGroupFields ?? []),\n ...(config.columnGroupFields ?? []),\n ...(config.valueFields?.map((v) => v.field) ?? []),\n ]);\n\n // Filter to show only unused fields\n const availableFields = allFields.filter((f) => !usedFields.has(f.field));\n\n if (availableFields.length === 0) {\n const empty = document.createElement('div');\n empty.className = 'tbw-pivot-placeholder';\n empty.textContent = 'All fields are in use';\n zone.appendChild(empty);\n } else {\n for (const field of availableFields) {\n const chip = document.createElement('div');\n chip.className = 'tbw-pivot-field-chip available';\n chip.textContent = field.header;\n chip.draggable = true;\n chip.title = `Drag to add \"${field.field}\" to a zone`;\n\n chip.addEventListener(\n 'dragstart',\n (e) => {\n e.dataTransfer?.setData('text/plain', field.field);\n chip.classList.add('dragging');\n },\n { signal },\n );\n\n chip.addEventListener(\n 'dragend',\n () => {\n chip.classList.remove('dragging');\n },\n { signal },\n );\n\n zone.appendChild(chip);\n }\n }\n\n return zone;\n}\n\n/**\n * Create the options panel with pivot toggle and checkboxes for totals.\n */\nfunction createOptionsPanel(isActive: boolean, ctx: RenderContext): HTMLElement {\n const { config, callbacks, signal } = ctx;\n const panel = document.createElement('div');\n panel.className = 'tbw-pivot-options';\n\n // Pivot Mode toggle\n panel.appendChild(\n createCheckbox(\n 'Enable Pivot View',\n isActive,\n (checked) => {\n callbacks.onTogglePivot(checked);\n },\n signal,\n ),\n );\n\n // Show Totals checkbox\n panel.appendChild(\n createCheckbox(\n 'Show Row Totals',\n config.showTotals ?? true,\n (checked) => {\n callbacks.onOptionChange('showTotals', checked);\n },\n signal,\n ),\n );\n\n // Show Grand Total checkbox\n panel.appendChild(\n createCheckbox(\n 'Show Grand Total',\n config.showGrandTotal ?? true,\n (checked) => {\n callbacks.onOptionChange('showGrandTotal', checked);\n },\n signal,\n ),\n );\n\n return panel;\n}\n\n/**\n * Create a checkbox with label.\n */\nfunction createCheckbox(\n label: string,\n checked: boolean,\n onChange: (checked: boolean) => void,\n signal: AbortSignal,\n): HTMLElement {\n const wrapper = document.createElement('label');\n wrapper.className = 'tbw-pivot-checkbox';\n\n const input = document.createElement('input');\n input.type = 'checkbox';\n input.checked = checked;\n input.addEventListener('change', () => onChange(input.checked), { signal });\n\n const span = document.createElement('span');\n span.textContent = label;\n\n wrapper.appendChild(input);\n wrapper.appendChild(span);\n\n return wrapper;\n}\n","/**\n * Pivot Row Rendering\n *\n * Pure functions for rendering pivot rows (group rows, leaf rows, grand total).\n * Separated from PivotPlugin for better code organization.\n */\n\nimport type { ColumnConfig, IconValue } from '../../core/types';\n\n/** Row data with pivot metadata */\nexport interface PivotRowData {\n __pivotRowKey?: string;\n __pivotLabel?: string;\n __pivotDepth?: number;\n __pivotIndent?: number;\n __pivotExpanded?: boolean;\n __pivotHasChildren?: boolean;\n __pivotRowCount?: number;\n __pivotIsGrandTotal?: boolean;\n [key: string]: unknown;\n}\n\n/** Context for row rendering */\nexport interface RowRenderContext {\n columns: ColumnConfig[];\n onToggle: (key: string) => void;\n resolveIcon: (iconKey: 'expand' | 'collapse') => IconValue;\n setIcon: (element: HTMLElement, icon: IconValue) => void;\n}\n\n/**\n * Render a pivot group row (has children, can expand/collapse).\n */\nexport function renderPivotGroupRow(row: PivotRowData, rowEl: HTMLElement, ctx: RowRenderContext): boolean {\n rowEl.className = 'pivot-group-row';\n rowEl.setAttribute('data-pivot-depth', String(row.__pivotDepth ?? 0));\n rowEl.setAttribute('data-pivot-key', String(row.__pivotRowKey ?? ''));\n rowEl.setAttribute('role', 'row');\n // Note: aria-expanded is not set here because it's only valid in treegrid, not grid\n // The expand/collapse state is conveyed via the toggle button's aria-label\n rowEl.innerHTML = '';\n\n ctx.columns.forEach((col, colIdx) => {\n const cell = document.createElement('div');\n cell.className = 'cell';\n cell.setAttribute('data-col', String(colIdx));\n cell.setAttribute('role', 'gridcell');\n\n if (colIdx === 0) {\n // First column: indent + toggle + label + count\n const indent = Number(row.__pivotIndent) || 0;\n cell.style.paddingLeft = `${indent}px`;\n\n // Toggle button\n const rowKey = String(row.__pivotRowKey);\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'pivot-toggle';\n btn.setAttribute('aria-label', row.__pivotExpanded ? 'Collapse group' : 'Expand group');\n ctx.setIcon(btn, ctx.resolveIcon(row.__pivotExpanded ? 'collapse' : 'expand'));\n btn.addEventListener('click', (e) => {\n e.stopPropagation();\n ctx.onToggle(rowKey);\n });\n cell.appendChild(btn);\n\n // Group label\n const label = document.createElement('span');\n label.className = 'pivot-label';\n label.textContent = String(row.__pivotLabel ?? '');\n cell.appendChild(label);\n\n // Row count\n const count = document.createElement('span');\n count.className = 'pivot-count';\n count.textContent = ` (${Number(row.__pivotRowCount) || 0})`;\n cell.appendChild(count);\n } else {\n // Other columns: render value\n const value = row[col.field];\n cell.textContent = value != null ? String(value) : '';\n }\n\n rowEl.appendChild(cell);\n });\n\n return true;\n}\n\n/**\n * Render a pivot leaf row (no children, just indentation).\n */\nexport function renderPivotLeafRow(row: PivotRowData, rowEl: HTMLElement, columns: ColumnConfig[]): boolean {\n rowEl.className = 'pivot-leaf-row';\n rowEl.setAttribute('data-pivot-depth', String(row.__pivotDepth ?? 0));\n rowEl.setAttribute('data-pivot-key', String(row.__pivotRowKey ?? ''));\n rowEl.innerHTML = '';\n\n columns.forEach((col, colIdx) => {\n const cell = document.createElement('div');\n cell.className = 'cell';\n cell.setAttribute('data-col', String(colIdx));\n cell.setAttribute('role', 'gridcell');\n\n if (colIdx === 0) {\n // First column: indent + label (no toggle for leaves)\n const indent = Number(row.__pivotIndent) || 0;\n // Add extra indent for alignment with toggle button\n cell.style.paddingLeft = `${indent + 20}px`;\n\n const label = document.createElement('span');\n label.className = 'pivot-label';\n label.textContent = String(row.__pivotLabel ?? '');\n cell.appendChild(label);\n } else {\n // Other columns: render value\n const value = row[col.field];\n cell.textContent = value != null ? String(value) : '';\n }\n\n rowEl.appendChild(cell);\n });\n\n return true;\n}\n\n/**\n * Render the grand total row.\n */\nexport function renderPivotGrandTotalRow(row: PivotRowData, rowEl: HTMLElement, columns: ColumnConfig[]): boolean {\n rowEl.className = 'pivot-grand-total-row';\n // Use role=presentation since grand total is rendered outside the role=grid element\n rowEl.setAttribute('role', 'presentation');\n rowEl.innerHTML = '';\n\n columns.forEach((col, colIdx) => {\n const cell = document.createElement('div');\n cell.className = 'cell';\n cell.setAttribute('data-col', String(colIdx));\n // No role attribute - parent row has role=presentation so children don't need grid semantics\n\n if (colIdx === 0) {\n // First column: Grand Total label\n const label = document.createElement('span');\n label.className = 'pivot-label';\n label.textContent = 'Grand Total';\n cell.appendChild(label);\n } else {\n // Other columns: render totals\n const value = row[col.field];\n cell.textContent = value != null ? String(value) : '';\n }\n\n rowEl.appendChild(cell);\n });\n\n return true;\n}\n","/**\n * Pivot Plugin (Class-based)\n *\n * Provides pivot table functionality for tbw-grid.\n * Transforms flat data into grouped, aggregated pivot views.\n * Includes a tool panel for interactive pivot configuration.\n */\n\nimport { BaseGridPlugin } from '../../core/plugin/base-plugin';\nimport type { ColumnConfig, GridConfig, ToolPanelDefinition } from '../../core/types';\nimport { buildPivot, flattenPivotRows, getAllGroupKeys, type PivotDataRow } from './pivot-engine';\nimport { createValueKey, validatePivotConfig } from './pivot-model';\nimport { renderPivotPanel, type FieldInfo, type PanelCallbacks } from './pivot-panel';\nimport { renderPivotGrandTotalRow, renderPivotGroupRow, renderPivotLeafRow, type PivotRowData } from './pivot-rows';\nimport type { AggFunc, ExpandCollapseAnimation, PivotConfig, PivotResult, PivotValueField } from './types';\n\n// Import CSS as inline string (Vite handles this)\nimport styles from './pivot.css?inline';\n\n/** Extended grid interface with column access */\ninterface GridWithColumns {\n shadowRoot: ShadowRoot | null;\n effectiveConfig?: GridConfig;\n getAllColumns(): Array<{ field: string; header: string; visible: boolean }>;\n columns: unknown[];\n rows: unknown[];\n requestRender(): void;\n openToolPanel(id: string): void;\n closeToolPanel(): void;\n toggleToolPanel(id: string): void;\n activeToolPanel: string | undefined;\n}\n\n/**\n * Pivot Plugin for tbw-grid\n *\n * @example\n * ```ts\n * new PivotPlugin({\n * rowGroupFields: ['category'],\n * columnGroupFields: ['region'],\n * valueFields: [{ field: 'sales', aggFunc: 'sum' }]\n * })\n * ```\n */\nexport class PivotPlugin extends BaseGridPlugin<PivotConfig> {\n readonly name = 'pivot';\n override readonly version = '1.0.0';\n\n /** Tool panel ID for shell integration */\n static readonly PANEL_ID = 'pivot';\n\n protected override get defaultConfig(): Partial<PivotConfig> {\n return {\n active: true,\n showTotals: true,\n showGrandTotal: true,\n showToolPanel: true,\n animation: 'slide',\n };\n }\n\n // #region Internal State\n private isActive = false;\n private hasInitialized = false;\n private pivotResult: PivotResult | null = null;\n private fieldHeaderMap: Map<string, string> = new Map();\n private expandedKeys: Set<string> = new Set();\n private defaultExpanded = true;\n private originalColumns: Array<{ field: string; header: string }> = [];\n private panelContainer: HTMLElement | null = null;\n private grandTotalFooter: HTMLElement | null = null;\n private previousVisibleKeys = new Set<string>();\n private keysToAnimate = new Set<string>();\n\n /**\n * Check if the plugin has valid pivot configuration (at least value fields).\n */\n private hasValidPivotConfig(): boolean {\n return (this.config.valueFields?.length ?? 0) > 0;\n }\n\n /**\n * Get animation style respecting grid-level animation mode.\n */\n private get animationStyle(): ExpandCollapseAnimation {\n const gridEl = this.grid as unknown as GridWithColumns;\n const mode = gridEl.effectiveConfig?.animation?.mode ?? 'reduced-motion';\n\n if (mode === false || mode === 'off') return false;\n if (mode !== true && mode !== 'on') {\n const host = this.shadowRoot?.host as HTMLElement | undefined;\n if (host && getComputedStyle(host).getPropertyValue('--tbw-animation-enabled').trim() === '0') {\n return false;\n }\n }\n return this.config.animation ?? 'slide';\n }\n\n // #endregion\n\n // #region Lifecycle\n\n override detach(): void {\n this.isActive = false;\n this.hasInitialized = false;\n this.pivotResult = null;\n this.fieldHeaderMap.clear();\n this.originalColumns = [];\n this.panelContainer = null;\n this.cleanupGrandTotalFooter();\n this.previousVisibleKeys.clear();\n this.keysToAnimate.clear();\n }\n\n // #endregion\n\n // #region Shell Integration\n\n override getToolPanel(): ToolPanelDefinition | undefined {\n // Allow users to disable the tool panel for programmatic-only pivot\n // Check userConfig first (works before attach), then merged config\n const showToolPanel = this.config?.showToolPanel ?? this.userConfig?.showToolPanel ?? true;\n if (showToolPanel === false) {\n return undefined;\n }\n\n return {\n id: PivotPlugin.PANEL_ID,\n title: 'Pivot',\n icon: '⊞',\n tooltip: 'Configure pivot table',\n order: 90,\n render: (container) => this.renderPanel(container),\n };\n }\n\n // #endregion\n\n // #region Hooks\n\n override processRows(rows: readonly unknown[]): PivotDataRow[] {\n // Auto-enable pivot if config.active is true and we have valid pivot fields\n if (!this.hasInitialized && this.config.active !== false && this.hasValidPivotConfig()) {\n this.hasInitialized = true;\n this.isActive = true;\n }\n\n if (!this.isActive) {\n return [...rows] as PivotDataRow[];\n }\n\n const errors = validatePivotConfig(this.config);\n if (errors.length > 0) {\n this.warn(`Config errors: ${errors.join(', ')}`);\n return [...rows] as PivotDataRow[];\n }\n\n this.buildFieldHeaderMap();\n this.defaultExpanded = this.config.defaultExpanded ?? true;\n\n // Initialize expanded state with defaults if first build\n if (this.expandedKeys.size === 0 && this.defaultExpanded && this.pivotResult) {\n const allKeys = getAllGroupKeys(this.pivotResult.rows);\n for (const key of allKeys) {\n this.expandedKeys.add(key);\n }\n }\n\n // Build pivot\n this.pivotResult = buildPivot(rows as PivotDataRow[], this.config);\n\n // If default expanded and we just built the pivot, add all group keys\n if (this.expandedKeys.size === 0 && this.defaultExpanded) {\n const allKeys = getAllGroupKeys(this.pivotResult.rows);\n for (const key of allKeys) {\n this.expandedKeys.add(key);\n }\n }\n\n // Return flattened pivot rows respecting expanded state\n const indentWidth = this.config.indentWidth ?? 20;\n const flatRows: PivotDataRow[] = flattenPivotRows(\n this.pivotResult.rows,\n this.expandedKeys,\n this.defaultExpanded,\n ).map((pr) => ({\n __pivotRowKey: pr.rowKey,\n __pivotLabel: pr.rowLabel,\n __pivotDepth: pr.depth,\n __pivotIsGroup: pr.isGroup,\n __pivotHasChildren: Boolean(pr.children?.length),\n __pivotExpanded: this.expandedKeys.has(pr.rowKey),\n __pivotRowCount: pr.rowCount ?? 0,\n __pivotIndent: pr.depth * indentWidth,\n __pivotTotal: pr.total,\n ...pr.values,\n }));\n\n // Track which rows are newly visible (for animation)\n this.keysToAnimate.clear();\n const currentVisibleKeys = new Set<string>();\n for (const row of flatRows) {\n const key = row.__pivotRowKey as string;\n currentVisibleKeys.add(key);\n // Animate non-root rows that weren't previously visible\n if (!this.previousVisibleKeys.has(key) && (row.__pivotDepth as number) > 0) {\n this.keysToAnimate.add(key);\n }\n }\n this.previousVisibleKeys = currentVisibleKeys;\n\n // Grand total is rendered as a pinned footer row in afterRender,\n // not as part of the scrolling row data\n\n return flatRows;\n }\n\n override processColumns(columns: readonly ColumnConfig[]): ColumnConfig[] {\n if (!this.isActive || !this.pivotResult) {\n return [...columns];\n }\n\n const pivotColumns: ColumnConfig[] = [];\n\n // Row label column\n const rowGroupHeaders = (this.config.rowGroupFields ?? []).map((f) => this.fieldHeaderMap.get(f) ?? f).join(' / ');\n pivotColumns.push({\n field: '__pivotLabel',\n header: rowGroupHeaders || 'Group',\n width: 200,\n });\n\n // Value columns for each column key\n for (const colKey of this.pivotResult.columnKeys) {\n for (const vf of this.config.valueFields ?? []) {\n const valueKey = createValueKey([colKey], vf.field);\n const valueHeader = vf.header || this.fieldHeaderMap.get(vf.field) || vf.field;\n pivotColumns.push({\n field: valueKey,\n header: `${colKey} - ${valueHeader} (${vf.aggFunc})`,\n width: 120,\n type: 'number',\n });\n }\n }\n\n // Totals column\n if (this.config.showTotals) {\n pivotColumns.push({\n field: '__pivotTotal',\n header: 'Total',\n width: 100,\n type: 'number',\n });\n }\n\n return pivotColumns;\n }\n\n override renderRow(row: Record<string, unknown>, rowEl: HTMLElement): boolean {\n const pivotRow = row as PivotRowData;\n\n // Handle pivot group row (has children)\n if (pivotRow.__pivotRowKey && pivotRow.__pivotHasChildren) {\n return renderPivotGroupRow(pivotRow, rowEl, {\n columns: this.gridColumns,\n onToggle: (key) => this.toggle(key),\n resolveIcon: (iconKey) => this.resolveIcon(iconKey),\n setIcon: (el, icon) => this.setIcon(el, icon),\n });\n }\n\n // Handle pivot leaf row (no children but in pivot mode)\n if (pivotRow.__pivotRowKey !== undefined && this.isActive) {\n return renderPivotLeafRow(pivotRow, rowEl, this.gridColumns);\n }\n\n // Clean up any leftover pivot styling from pooled row elements\n this.cleanupPivotStyling(rowEl);\n\n return false;\n }\n\n /**\n * Remove pivot-specific classes, attributes, and inline styles from a row element.\n * Called when pivot mode is disabled to clean up reused DOM elements.\n * Clears innerHTML so the grid's default renderer can rebuild the row.\n */\n private cleanupPivotStyling(rowEl: HTMLElement): void {\n // Check if this row was previously rendered by pivot (has pivot classes)\n const wasPivotRow =\n rowEl.classList.contains('pivot-group-row') ||\n rowEl.classList.contains('pivot-leaf-row') ||\n rowEl.classList.contains('pivot-grand-total-row');\n\n if (wasPivotRow) {\n // Remove pivot row classes and restore the default grid row class\n rowEl.classList.remove('pivot-group-row', 'pivot-leaf-row', 'pivot-grand-total-row');\n rowEl.classList.add('data-grid-row');\n\n // Remove pivot-specific attributes\n rowEl.removeAttribute('data-pivot-depth');\n\n // Clear the row content so the default renderer can rebuild it\n rowEl.innerHTML = '';\n }\n }\n\n override afterRender(): void {\n // Render grand total as a sticky pinned footer when pivot is active\n if (this.isActive && this.config.showGrandTotal && this.pivotResult) {\n this.renderGrandTotalFooter();\n } else {\n this.cleanupGrandTotalFooter();\n }\n\n // Apply animations to newly visible rows\n const style = this.animationStyle;\n if (style === false || this.keysToAnimate.size === 0) return;\n\n const body = this.shadowRoot?.querySelector('.rows');\n if (!body) return;\n\n const animClass = style === 'fade' ? 'tbw-pivot-fade-in' : 'tbw-pivot-slide-in';\n for (const rowEl of body.querySelectorAll('.pivot-group-row, .pivot-leaf-row')) {\n const key = (rowEl as HTMLElement).dataset.pivotKey;\n if (key && this.keysToAnimate.has(key)) {\n rowEl.classList.add(animClass);\n rowEl.addEventListener('animationend', () => rowEl.classList.remove(animClass), { once: true });\n }\n }\n this.keysToAnimate.clear();\n }\n\n /**\n * Render the grand total row as a sticky footer pinned to the bottom.\n */\n private renderGrandTotalFooter(): void {\n if (!this.pivotResult) return;\n\n const shadowRoot = this.shadowRoot;\n if (!shadowRoot) return;\n\n // Find the scroll container to append the footer\n const container =\n shadowRoot.querySelector('.tbw-scroll-area') ??\n shadowRoot.querySelector('.tbw-grid-content') ??\n shadowRoot.children[0];\n if (!container) return;\n\n // Create footer if it doesn't exist\n if (!this.grandTotalFooter) {\n this.grandTotalFooter = document.createElement('div');\n this.grandTotalFooter.className = 'pivot-grand-total-footer';\n container.appendChild(this.grandTotalFooter);\n }\n\n // Build the row data for grand total\n const grandTotalRow: PivotRowData = {\n __pivotRowKey: '__grandTotal',\n __pivotLabel: 'Grand Total',\n __pivotIsGrandTotal: true,\n __pivotTotal: this.pivotResult.grandTotal,\n ...this.pivotResult.totals,\n };\n\n // Render the grand total row into the footer\n renderPivotGrandTotalRow(grandTotalRow, this.grandTotalFooter, this.gridColumns);\n }\n\n /**\n * Remove the grand total footer element.\n */\n private cleanupGrandTotalFooter(): void {\n if (this.grandTotalFooter) {\n this.grandTotalFooter.remove();\n this.grandTotalFooter = null;\n }\n }\n\n // #endregion\n\n // #region Expand/Collapse API\n\n toggle(key: string): void {\n if (this.expandedKeys.has(key)) {\n this.expandedKeys.delete(key);\n } else {\n this.expandedKeys.add(key);\n }\n this.requestRender();\n }\n\n expand(key: string): void {\n this.expandedKeys.add(key);\n this.requestRender();\n }\n\n collapse(key: string): void {\n this.expandedKeys.delete(key);\n this.requestRender();\n }\n\n expandAll(): void {\n if (this.pivotResult) {\n const allKeys = getAllGroupKeys(this.pivotResult.rows);\n for (const key of allKeys) {\n this.expandedKeys.add(key);\n }\n this.requestRender();\n }\n }\n\n collapseAll(): void {\n this.expandedKeys.clear();\n this.requestRender();\n }\n\n isExpanded(key: string): boolean {\n return this.expandedKeys.has(key);\n }\n\n // #endregion\n\n // #region Public API\n\n enablePivot(): void {\n if (this.originalColumns.length === 0) {\n this.captureOriginalColumns();\n }\n this.isActive = true;\n this.requestRender();\n }\n\n disablePivot(): void {\n this.isActive = false;\n this.pivotResult = null;\n this.requestRender();\n }\n\n isPivotActive(): boolean {\n return this.isActive;\n }\n\n getPivotResult(): PivotResult | null {\n return this.pivotResult;\n }\n\n setRowGroupFields(fields: string[]): void {\n this.config.rowGroupFields = fields;\n this.requestRender();\n }\n\n setColumnGroupFields(fields: string[]): void {\n this.config.columnGroupFields = fields;\n this.requestRender();\n }\n\n setValueFields(fields: PivotValueField[]): void {\n this.config.valueFields = fields;\n this.requestRender();\n }\n\n refresh(): void {\n this.pivotResult = null;\n this.requestRender();\n }\n\n // #endregion\n\n // #region Tool Panel API\n\n showPanel(): void {\n const grid = this.grid as unknown as GridWithColumns;\n grid.openToolPanel(PivotPlugin.PANEL_ID);\n }\n\n hidePanel(): void {\n const grid = this.grid as unknown as GridWithColumns;\n grid.closeToolPanel();\n }\n\n togglePanel(): void {\n const grid = this.grid as unknown as GridWithColumns;\n grid.toggleToolPanel(PivotPlugin.PANEL_ID);\n }\n\n isPanelVisible(): boolean {\n const grid = this.grid as unknown as GridWithColumns;\n return grid.activeToolPanel === PivotPlugin.PANEL_ID;\n }\n\n // #endregion\n\n // #region Private Helpers\n\n private get gridColumns(): ColumnConfig[] {\n const grid = this.grid as unknown as GridWithColumns;\n return (grid.columns ?? []) as ColumnConfig[];\n }\n\n private buildFieldHeaderMap(): void {\n const availableFields = this.getAvailableFields();\n this.fieldHeaderMap.clear();\n for (const field of availableFields) {\n this.fieldHeaderMap.set(field.field, field.header);\n }\n }\n\n private getAvailableFields(): FieldInfo[] {\n if (this.originalColumns.length > 0) {\n return this.originalColumns;\n }\n return this.captureOriginalColumns();\n }\n\n private captureOriginalColumns(): FieldInfo[] {\n const grid = this.grid as unknown as GridWithColumns;\n try {\n const columns = grid.getAllColumns?.() ?? grid.columns ?? [];\n this.originalColumns = columns\n .filter((col: { field: string }) => !col.field.startsWith('__pivot'))\n .map((col: { field: string; header?: string }) => ({\n field: col.field,\n header: col.header ?? col.field,\n }));\n return this.originalColumns;\n } catch {\n return [];\n }\n }\n\n private renderPanel(container: HTMLElement): (() => void) | void {\n this.panelContainer = container;\n\n if (this.originalColumns.length === 0) {\n this.captureOriginalColumns();\n }\n\n const callbacks: PanelCallbacks = {\n onTogglePivot: (enabled) => {\n if (enabled) {\n this.enablePivot();\n } else {\n this.disablePivot();\n }\n this.refreshPanel();\n },\n onAddFieldToZone: (field, zone) => this.addFieldToZone(field, zone),\n onRemoveFieldFromZone: (field, zone) => this.removeFieldFromZone(field, zone),\n onAddValueField: (field, aggFunc) => this.addValueField(field, aggFunc),\n onRemoveValueField: (field) => this.removeValueField(field),\n onUpdateValueAggFunc: (field, aggFunc) => this.updateValueAggFunc(field, aggFunc),\n onOptionChange: (option, value) => {\n this.config[option] = value;\n if (this.isActive) this.refresh();\n },\n getAvailableFields: () => this.getAvailableFields(),\n };\n\n return renderPivotPanel(container, this.config, this.isActive, callbacks);\n }\n\n private refreshPanel(): void {\n if (!this.panelContainer) return;\n this.panelContainer.innerHTML = '';\n this.renderPanel(this.panelContainer);\n }\n\n private addFieldToZone(field: string, zoneType: 'rowGroups' | 'columnGroups'): void {\n if (zoneType === 'rowGroups') {\n const current = this.config.rowGroupFields ?? [];\n if (!current.includes(field)) {\n this.config.rowGroupFields = [...current, field];\n }\n } else {\n const current = this.config.columnGroupFields ?? [];\n if (!current.includes(field)) {\n this.config.columnGroupFields = [...current, field];\n }\n }\n\n this.removeFromOtherZones(field, zoneType);\n if (this.isActive) this.refresh();\n this.refreshPanel();\n }\n\n private removeFieldFromZone(field: string, zoneType: 'rowGroups' | 'columnGroups'): void {\n if (zoneType === 'rowGroups') {\n this.config.rowGroupFields = (this.config.rowGroupFields ?? []).filter((f) => f !== field);\n } else {\n this.config.columnGroupFields = (this.config.columnGroupFields ?? []).filter((f) => f !== field);\n }\n\n if (this.isActive) this.refresh();\n this.refreshPanel();\n }\n\n private removeFromOtherZones(field: string, targetZone: 'rowGroups' | 'columnGroups' | 'values'): void {\n if (targetZone !== 'rowGroups') {\n this.config.rowGroupFields = (this.config.rowGroupFields ?? []).filter((f) => f !== field);\n }\n if (targetZone !== 'columnGroups') {\n this.config.columnGroupFields = (this.config.columnGroupFields ?? []).filter((f) => f !== field);\n }\n if (targetZone !== 'values') {\n this.config.valueFields = (this.config.valueFields ?? []).filter((v) => v.field !== field);\n }\n }\n\n private addValueField(field: string, aggFunc: AggFunc): void {\n const current = this.config.valueFields ?? [];\n if (!current.some((v) => v.field === field)) {\n this.config.valueFields = [...current, { field, aggFunc }];\n }\n\n this.removeFromOtherZones(field, 'values');\n if (this.isActive) this.refresh();\n this.refreshPanel();\n }\n\n private removeValueField(field: string): void {\n this.config.valueFields = (this.config.valueFields ?? []).filter((v) => v.field !== field);\n if (this.isActive) this.refresh();\n this.refreshPanel();\n }\n\n private updateValueAggFunc(field: string, aggFunc: AggFunc): void {\n const valueFields = this.config.valueFields ?? [];\n const fieldIndex = valueFields.findIndex((v) => v.field === field);\n if (fieldIndex >= 0) {\n valueFields[fieldIndex] = { ...valueFields[fieldIndex], aggFunc };\n this.config.valueFields = [...valueFields];\n }\n if (this.isActive) this.refresh();\n }\n\n // #endregion\n\n // #region Styles\n\n override readonly styles = styles;\n\n // #endregion\n}\n","/**\n * Column Reordering Core Logic\n *\n * Pure functions for column drag and reordering operations.\n */\n\nimport type { ColumnConfig } from '../../core/types';\n\n/**\n * Check if a column can be moved based on its own metadata.\n * This checks column-level properties like lockPosition and suppressMovable.\n *\n * Note: For full movability checks including plugin constraints (e.g., pinned columns),\n * use `grid.queryPlugins({ type: PLUGIN_QUERIES.CAN_MOVE_COLUMN, context: column })`\n * which queries all plugins via the generic plugin query system.\n *\n * @param column - The column configuration to check\n * @returns True if the column can be moved based on its metadata\n */\nexport function canMoveColumn<TRow = unknown>(column: ColumnConfig<TRow>): boolean {\n // Check for lockPosition or suppressMovable properties in the column config\n const meta = column.meta ?? {};\n return meta.lockPosition !== true && meta.suppressMovable !== true;\n}\n\n/**\n * Move a column from one position to another in the order array.\n *\n * @param columns - Array of field names in current order\n * @param fromIndex - The current index of the column to move\n * @param toIndex - The target index to move the column to\n * @returns New array with updated order\n */\nexport function moveColumn(columns: string[], fromIndex: number, toIndex: number): string[] {\n if (fromIndex === toIndex) return columns;\n if (fromIndex < 0 || fromIndex >= columns.length) return columns;\n if (toIndex < 0 || toIndex > columns.length) return columns;\n\n const result = [...columns];\n const [removed] = result.splice(fromIndex, 1);\n result.splice(toIndex, 0, removed);\n return result;\n}\n\n/**\n * Calculate the drop index based on the current drag position.\n *\n * @param dragX - The current X position of the drag\n * @param headerRect - The bounding rect of the header container\n * @param columnWidths - Array of column widths in order\n * @returns The index where the column should be dropped\n */\nexport function getDropIndex(dragX: number, headerRect: DOMRect, columnWidths: number[]): number {\n let x = headerRect.left;\n\n for (let i = 0; i < columnWidths.length; i++) {\n const mid = x + columnWidths[i] / 2;\n if (dragX < mid) return i;\n x += columnWidths[i];\n }\n\n return columnWidths.length;\n}\n\n/**\n * Reorder columns according to a specified order.\n * Columns not in the order array are appended at the end.\n *\n * @param columns - Array of column configurations\n * @param order - Array of field names specifying the desired order\n * @returns New array of columns in the specified order\n */\nexport function reorderColumns<TRow = unknown>(columns: ColumnConfig<TRow>[], order: string[]): ColumnConfig<TRow>[] {\n const columnMap = new Map<string, ColumnConfig<TRow>>(columns.map((c) => [c.field as string, c]));\n const reordered: ColumnConfig<TRow>[] = [];\n\n // Add columns in specified order\n for (const field of order) {\n const col = columnMap.get(field);\n if (col) {\n reordered.push(col);\n columnMap.delete(field);\n }\n }\n\n // Add any remaining columns not in order\n for (const col of columnMap.values()) {\n reordered.push(col);\n }\n\n return reordered;\n}\n","/**\n * Column Reordering Plugin (Class-based)\n *\n * Provides drag-and-drop column reordering functionality for tbw-grid.\n * Supports keyboard and mouse interactions with visual feedback.\n * Uses FLIP animation technique for smooth column transitions.\n *\n * Animation respects grid-level animation.mode setting but style is plugin-configured.\n */\n\nimport { ensureCellVisible } from '../../core/internal/keyboard';\nimport { BaseGridPlugin, PLUGIN_QUERIES } from '../../core/plugin/base-plugin';\nimport type { ColumnConfig, GridConfig } from '../../core/types';\nimport { canMoveColumn, moveColumn } from './column-drag';\nimport styles from './reorder.css?inline';\nimport type { ColumnMoveDetail, ReorderConfig } from './types';\n\n/** Extended grid interface with column order methods */\ninterface GridWithColumnOrder {\n setColumnOrder(order: string[]): void;\n getColumnOrder(): string[];\n requestStateChange?: () => void;\n /** Query plugins for inter-plugin communication */\n queryPlugins<T>(query: { type: string; context: unknown }): T[];\n /** Effective grid config */\n effectiveConfig?: GridConfig;\n}\n\n/**\n * Column Reordering Plugin for tbw-grid\n *\n * @example\n * ```ts\n * new ReorderPlugin()\n * ```\n */\nexport class ReorderPlugin extends BaseGridPlugin<ReorderConfig> {\n readonly name = 'reorder';\n override readonly version = '1.0.0';\n\n protected override get defaultConfig(): Partial<ReorderConfig> {\n return {\n animation: 'flip', // Plugin's own default\n };\n }\n\n /**\n * Resolve animation type from plugin config.\n * Respects grid-level animation.mode (disabled = no animation).\n */\n private get animationType(): false | 'flip' | 'fade' {\n // Check if animations are globally disabled\n if (!this.isAnimationEnabled) return false;\n\n // Plugin config (with default from defaultConfig)\n if (this.config.animation !== undefined) return this.config.animation;\n\n // Legacy viewTransition fallback\n if (this.config.viewTransition === false) return false;\n if (this.config.viewTransition === true) return 'flip';\n\n return 'flip'; // Plugin default\n }\n\n /**\n * Check if animations are enabled at the grid level.\n * Respects gridConfig.animation.mode and CSS variable.\n */\n private get isAnimationEnabled(): boolean {\n const gridEl = this.grid as unknown as GridWithColumnOrder;\n const mode = gridEl.effectiveConfig?.animation?.mode ?? 'reduced-motion';\n\n // Explicit off = disabled\n if (mode === false || mode === 'off') return false;\n\n // Explicit on = always enabled\n if (mode === true || mode === 'on') return true;\n\n // reduced-motion: check CSS variable (set by grid based on media query)\n const host = this.shadowRoot?.host as HTMLElement | undefined;\n if (host) {\n const enabled = getComputedStyle(host).getPropertyValue('--tbw-animation-enabled').trim();\n return enabled !== '0';\n }\n\n return true; // Default to enabled\n }\n\n /**\n * Get animation duration from CSS variable (set by grid config).\n */\n private get animationDuration(): number {\n // Plugin config override\n if (this.config.animationDuration !== undefined) {\n return this.config.animationDuration;\n }\n\n // Read from CSS variable (already set by grid from gridConfig.animation.duration)\n const host = this.shadowRoot?.host as HTMLElement | undefined;\n if (host) {\n const durationStr = getComputedStyle(host).getPropertyValue('--tbw-animation-duration').trim();\n const parsed = parseInt(durationStr, 10);\n if (!isNaN(parsed)) return parsed;\n }\n\n return 200; // Default\n }\n\n // #region Internal State\n private isDragging = false;\n private draggedField: string | null = null;\n private draggedIndex: number | null = null;\n private dropIndex: number | null = null;\n // #endregion\n\n // #region Lifecycle\n\n override attach(grid: import('../../core/plugin/base-plugin').GridElement): void {\n super.attach(grid);\n\n // Listen for reorder requests from other plugins (e.g., VisibilityPlugin)\n // Uses disconnectSignal for automatic cleanup - no need for manual removeEventListener\n (grid as unknown as HTMLElement).addEventListener(\n 'column-reorder-request',\n (e: Event) => {\n const detail = (e as CustomEvent).detail;\n if (detail?.field && typeof detail.toIndex === 'number') {\n this.moveColumn(detail.field, detail.toIndex);\n }\n },\n { signal: this.disconnectSignal },\n );\n }\n\n override detach(): void {\n this.isDragging = false;\n this.draggedField = null;\n this.draggedIndex = null;\n this.dropIndex = null;\n }\n // #endregion\n\n // #region Hooks\n\n override afterRender(): void {\n const shadowRoot = this.shadowRoot;\n if (!shadowRoot) return;\n\n const headers = shadowRoot.querySelectorAll('.header-row > .cell');\n\n headers.forEach((header) => {\n const headerEl = header as HTMLElement;\n const field = headerEl.getAttribute('data-field');\n if (!field) return;\n\n const column = this.columns.find((c) => c.field === field);\n // Check both local metadata and plugin queries (e.g., PinnedColumnsPlugin)\n const gridEl = this.grid as unknown as GridWithColumnOrder;\n const pluginResponses = gridEl.queryPlugins<boolean>({\n type: PLUGIN_QUERIES.CAN_MOVE_COLUMN,\n context: column as ColumnConfig,\n });\n const pluginAllows = !pluginResponses.includes(false);\n if (!column || !canMoveColumn(column) || !pluginAllows) {\n headerEl.draggable = false;\n return;\n }\n\n headerEl.draggable = true;\n\n // Remove existing listeners to prevent duplicates\n if (headerEl.getAttribute('data-dragstart-bound')) return;\n headerEl.setAttribute('data-dragstart-bound', 'true');\n\n headerEl.addEventListener('dragstart', (e: DragEvent) => {\n const currentOrder = this.getColumnOrder();\n const orderIndex = currentOrder.indexOf(field);\n this.isDragging = true;\n this.draggedField = field;\n this.draggedIndex = orderIndex;\n\n if (e.dataTransfer) {\n e.dataTransfer.effectAllowed = 'move';\n e.dataTransfer.setData('text/plain', field);\n }\n\n headerEl.classList.add('dragging');\n });\n\n headerEl.addEventListener('dragend', () => {\n this.isDragging = false;\n this.draggedField = null;\n this.draggedIndex = null;\n this.dropIndex = null;\n\n shadowRoot.querySelectorAll('.header-row > .cell').forEach((h) => {\n h.classList.remove('dragging', 'drop-target', 'drop-before', 'drop-after');\n });\n });\n\n headerEl.addEventListener('dragover', (e: DragEvent) => {\n e.preventDefault();\n if (!this.isDragging || this.draggedField === field) return;\n\n const rect = headerEl.getBoundingClientRect();\n const midX = rect.left + rect.width / 2;\n\n const currentOrder = this.getColumnOrder();\n const orderIndex = currentOrder.indexOf(field);\n this.dropIndex = e.clientX < midX ? orderIndex : orderIndex + 1;\n\n headerEl.classList.add('drop-target');\n headerEl.classList.toggle('drop-before', e.clientX < midX);\n headerEl.classList.toggle('drop-after', e.clientX >= midX);\n });\n\n headerEl.addEventListener('dragleave', () => {\n headerEl.classList.remove('drop-target', 'drop-before', 'drop-after');\n });\n\n headerEl.addEventListener('drop', (e: DragEvent) => {\n e.preventDefault();\n const draggedField = this.draggedField;\n const draggedIndex = this.draggedIndex;\n const dropIndex = this.dropIndex;\n\n if (!this.isDragging || draggedField === null || draggedIndex === null || dropIndex === null) {\n return;\n }\n\n const effectiveToIndex = dropIndex > draggedIndex ? dropIndex - 1 : dropIndex;\n const currentOrder = this.getColumnOrder();\n const newOrder = moveColumn(currentOrder, draggedIndex, effectiveToIndex);\n\n const detail: ColumnMoveDetail = {\n field: draggedField,\n fromIndex: draggedIndex,\n toIndex: effectiveToIndex,\n columnOrder: newOrder,\n };\n\n // Update the grid's column order (with optional view transition)\n this.updateColumnOrder(newOrder);\n\n this.emit('column-move', detail);\n });\n });\n }\n\n /**\n * Handle Alt+Arrow keyboard shortcuts for column reordering.\n */\n override onKeyDown(event: KeyboardEvent): boolean | void {\n if (!event.altKey || (event.key !== 'ArrowLeft' && event.key !== 'ArrowRight')) {\n return;\n }\n\n const grid = this.grid as unknown as { _focusCol: number; _visibleColumns: ColumnConfig[] };\n const focusCol = grid._focusCol;\n const columns = grid._visibleColumns;\n\n if (focusCol < 0 || focusCol >= columns.length) return;\n\n const column = columns[focusCol];\n if (!column || !canMoveColumn(column)) return;\n\n // Check plugin queries (e.g., PinnedColumnsPlugin)\n const gridEl = this.grid as unknown as GridWithColumnOrder;\n const pluginResponses = gridEl.queryPlugins<boolean>({\n type: PLUGIN_QUERIES.CAN_MOVE_COLUMN,\n context: column,\n });\n if (pluginResponses.includes(false)) return;\n\n const currentOrder = this.getColumnOrder();\n const fromIndex = currentOrder.indexOf(column.field);\n if (fromIndex === -1) return;\n\n const toIndex = event.key === 'ArrowLeft' ? fromIndex - 1 : fromIndex + 1;\n\n // Check bounds\n if (toIndex < 0 || toIndex >= currentOrder.length) return;\n\n // Check if target position is allowed (e.g., not into pinned area)\n const targetColumn = columns.find((c) => c.field === currentOrder[toIndex]);\n if (targetColumn) {\n const targetResponses = gridEl.queryPlugins<boolean>({\n type: PLUGIN_QUERIES.CAN_MOVE_COLUMN,\n context: targetColumn,\n });\n if (targetResponses.includes(false)) return;\n }\n\n this.moveColumn(column.field, toIndex);\n\n // Update focus to follow the moved column and refresh visual focus state\n grid._focusCol = toIndex;\n ensureCellVisible(this.grid as any);\n\n event.preventDefault();\n event.stopPropagation();\n return true;\n }\n // #endregion\n\n // #region Public API\n\n /**\n * Get the current column order from the grid.\n * @returns Array of field names in display order\n */\n getColumnOrder(): string[] {\n return (this.grid as unknown as GridWithColumnOrder).getColumnOrder();\n }\n\n /**\n * Move a column to a new position.\n * @param field - The field name of the column to move\n * @param toIndex - The target index\n */\n moveColumn(field: string, toIndex: number): void {\n const currentOrder = this.getColumnOrder();\n const fromIndex = currentOrder.indexOf(field);\n if (fromIndex === -1) return;\n\n const newOrder = moveColumn(currentOrder, fromIndex, toIndex);\n\n // Update with view transition\n this.updateColumnOrder(newOrder);\n\n this.emit<ColumnMoveDetail>('column-move', {\n field,\n fromIndex,\n toIndex,\n columnOrder: newOrder,\n });\n }\n\n /**\n * Set a specific column order.\n * @param order - Array of field names in desired order\n */\n setColumnOrder(order: string[]): void {\n this.updateColumnOrder(order);\n }\n\n /**\n * Reset column order to the original configuration order.\n */\n resetColumnOrder(): void {\n const originalOrder = this.columns.map((c) => c.field);\n this.updateColumnOrder(originalOrder);\n }\n // #endregion\n\n // #region View Transition\n\n /**\n * Capture header cell positions before reorder.\n */\n private captureHeaderPositions(): Map<string, number> {\n const positions = new Map<string, number>();\n this.shadowRoot?.querySelectorAll('.header-row > .cell[data-field]').forEach((cell) => {\n const field = cell.getAttribute('data-field');\n if (field) positions.set(field, cell.getBoundingClientRect().left);\n });\n return positions;\n }\n\n /**\n * Apply FLIP animation for column reorder.\n * Uses CSS transitions - JS sets initial transform and toggles class.\n * @param oldPositions - Header positions captured before DOM change\n */\n private animateFLIP(oldPositions: Map<string, number>): void {\n const shadowRoot = this.shadowRoot;\n if (!shadowRoot || oldPositions.size === 0) return;\n\n // Compute deltas from header cells (stable reference points)\n const deltas = new Map<string, number>();\n shadowRoot.querySelectorAll('.header-row > .cell[data-field]').forEach((cell) => {\n const field = cell.getAttribute('data-field');\n if (!field) return;\n const oldLeft = oldPositions.get(field);\n if (oldLeft === undefined) return;\n const deltaX = oldLeft - cell.getBoundingClientRect().left;\n if (Math.abs(deltaX) > 1) deltas.set(field, deltaX);\n });\n\n if (deltas.size === 0) return;\n\n // Set initial transform (First → Last position offset)\n const cells: HTMLElement[] = [];\n shadowRoot.querySelectorAll('.cell[data-field]').forEach((cell) => {\n const deltaX = deltas.get(cell.getAttribute('data-field') ?? '');\n if (deltaX !== undefined) {\n const el = cell as HTMLElement;\n el.style.transform = `translateX(${deltaX}px)`;\n cells.push(el);\n }\n });\n\n if (cells.length === 0) return;\n\n // Force reflow then animate to final position via CSS transition\n void (shadowRoot.host as HTMLElement).offsetHeight;\n\n const duration = this.animationDuration;\n\n requestAnimationFrame(() => {\n cells.forEach((el) => {\n el.classList.add('flip-animating');\n el.style.transform = '';\n });\n\n // Cleanup after animation\n setTimeout(() => {\n cells.forEach((el) => {\n el.style.transform = '';\n el.classList.remove('flip-animating');\n });\n }, duration + 50);\n });\n }\n\n /**\n * Apply crossfade animation for moved columns.\n * Uses CSS keyframes - JS just toggles classes.\n */\n private animateFade(applyChange: () => void): void {\n const shadowRoot = this.shadowRoot;\n if (!shadowRoot) {\n applyChange();\n return;\n }\n\n // Capture old positions to detect which columns moved\n const oldPositions = this.captureHeaderPositions();\n\n // Apply the change first\n applyChange();\n\n // Find which columns changed position\n const movedFields = new Set<string>();\n shadowRoot.querySelectorAll('.header-row > .cell[data-field]').forEach((cell) => {\n const field = cell.getAttribute('data-field');\n if (!field) return;\n const oldLeft = oldPositions.get(field);\n if (oldLeft === undefined) return;\n const newLeft = cell.getBoundingClientRect().left;\n if (Math.abs(oldLeft - newLeft) > 1) {\n movedFields.add(field);\n }\n });\n\n if (movedFields.size === 0) return;\n\n // Add animation class to moved columns (headers + body cells)\n const cells: HTMLElement[] = [];\n shadowRoot.querySelectorAll('.cell[data-field]').forEach((cell) => {\n const field = cell.getAttribute('data-field');\n if (field && movedFields.has(field)) {\n const el = cell as HTMLElement;\n el.classList.add('fade-animating');\n cells.push(el);\n }\n });\n\n if (cells.length === 0) return;\n\n // Remove class after animation completes\n const duration = this.animationDuration;\n setTimeout(() => {\n cells.forEach((el) => el.classList.remove('fade-animating'));\n }, duration + 50);\n }\n\n /**\n * Update column order with configured animation.\n */\n private updateColumnOrder(newOrder: string[]): void {\n const gridEl = this.grid as unknown as GridWithColumnOrder;\n const animation = this.animationType;\n\n if (animation === 'flip' && this.shadowRoot) {\n const oldPositions = this.captureHeaderPositions();\n gridEl.setColumnOrder(newOrder);\n void (this.shadowRoot.host as HTMLElement).offsetHeight;\n this.animateFLIP(oldPositions);\n } else if (animation === 'fade') {\n this.animateFade(() => gridEl.setColumnOrder(newOrder));\n } else {\n gridEl.setColumnOrder(newOrder);\n }\n\n gridEl.requestStateChange?.();\n }\n // #endregion\n\n // #region Styles\n\n override readonly styles = styles;\n // #endregion\n}\n","/**\n * Cell Range Selection Core Logic\n *\n * Pure functions for cell range selection operations.\n */\n\nimport type { InternalCellRange, CellRange } from './types';\n\n/**\n * Normalize a range so startRow/startCol are always <= endRow/endCol.\n * This handles cases where user drags from bottom-right to top-left.\n *\n * @param range - The range to normalize\n * @returns Normalized range with start <= end for both dimensions\n */\nexport function normalizeRange(range: InternalCellRange): InternalCellRange {\n return {\n startRow: Math.min(range.startRow, range.endRow),\n startCol: Math.min(range.startCol, range.endCol),\n endRow: Math.max(range.startRow, range.endRow),\n endCol: Math.max(range.startCol, range.endCol),\n };\n}\n\n/**\n * Convert an internal range to the public event format.\n *\n * @param range - The internal range to convert\n * @returns Public CellRange format with from/to coordinates\n */\nexport function toPublicRange(range: InternalCellRange): CellRange {\n const normalized = normalizeRange(range);\n return {\n from: { row: normalized.startRow, col: normalized.startCol },\n to: { row: normalized.endRow, col: normalized.endCol },\n };\n}\n\n/**\n * Convert multiple internal ranges to public format.\n *\n * @param ranges - Array of internal ranges\n * @returns Array of public CellRange format\n */\nexport function toPublicRanges(ranges: InternalCellRange[]): CellRange[] {\n return ranges.map(toPublicRange);\n}\n\n/**\n * Check if a cell is within a specific range.\n *\n * @param row - The row index to check\n * @param col - The column index to check\n * @param range - The range to check against\n * @returns True if the cell is within the range\n */\nexport function isCellInRange(row: number, col: number, range: InternalCellRange): boolean {\n const normalized = normalizeRange(range);\n return (\n row >= normalized.startRow && row <= normalized.endRow && col >= normalized.startCol && col <= normalized.endCol\n );\n}\n\n/**\n * Check if a cell is within any of the provided ranges.\n *\n * @param row - The row index to check\n * @param col - The column index to check\n * @param ranges - Array of ranges to check against\n * @returns True if the cell is within any range\n */\nexport function isCellInAnyRange(row: number, col: number, ranges: InternalCellRange[]): boolean {\n return ranges.some((range) => isCellInRange(row, col, range));\n}\n\n/**\n * Get all cells within a range as an array of {row, col} objects.\n *\n * @param range - The range to enumerate\n * @returns Array of all cell coordinates in the range\n */\nexport function getCellsInRange(range: InternalCellRange): Array<{ row: number; col: number }> {\n const cells: Array<{ row: number; col: number }> = [];\n const normalized = normalizeRange(range);\n\n for (let row = normalized.startRow; row <= normalized.endRow; row++) {\n for (let col = normalized.startCol; col <= normalized.endCol; col++) {\n cells.push({ row, col });\n }\n }\n\n return cells;\n}\n\n/**\n * Get all unique cells across multiple ranges.\n * Deduplicates cells that appear in overlapping ranges.\n *\n * @param ranges - Array of ranges to enumerate\n * @returns Array of unique cell coordinates\n */\nexport function getAllCellsInRanges(ranges: InternalCellRange[]): Array<{ row: number; col: number }> {\n const cellMap = new Map<string, { row: number; col: number }>();\n\n for (const range of ranges) {\n for (const cell of getCellsInRange(range)) {\n cellMap.set(`${cell.row},${cell.col}`, cell);\n }\n }\n\n return [...cellMap.values()];\n}\n\n/**\n * Merge overlapping or adjacent ranges into fewer ranges.\n * Simple implementation - returns ranges as-is for now.\n * More complex merging logic can be added later for optimization.\n *\n * @param ranges - Array of ranges to merge\n * @returns Merged array of ranges\n */\nexport function mergeRanges(ranges: InternalCellRange[]): InternalCellRange[] {\n // Simple implementation - more complex merging can be added later\n return ranges;\n}\n\n/**\n * Create a range from an anchor cell to a current cell position.\n * The range is not normalized - it preserves the direction of selection.\n *\n * @param anchor - The anchor cell (where selection started)\n * @param current - The current cell (where selection ends)\n * @returns An InternalCellRange from anchor to current\n */\nexport function createRangeFromAnchor(\n anchor: { row: number; col: number },\n current: { row: number; col: number }\n): InternalCellRange {\n return {\n startRow: anchor.row,\n startCol: anchor.col,\n endRow: current.row,\n endCol: current.col,\n };\n}\n\n/**\n * Calculate the number of cells in a range.\n *\n * @param range - The range to measure\n * @returns Total number of cells in the range\n */\nexport function getRangeCellCount(range: InternalCellRange): number {\n const normalized = normalizeRange(range);\n const rowCount = normalized.endRow - normalized.startRow + 1;\n const colCount = normalized.endCol - normalized.startCol + 1;\n return rowCount * colCount;\n}\n\n/**\n * Check if two ranges are equal (same boundaries).\n *\n * @param a - First range\n * @param b - Second range\n * @returns True if ranges have same boundaries after normalization\n */\nexport function rangesEqual(a: InternalCellRange, b: InternalCellRange): boolean {\n const normA = normalizeRange(a);\n const normB = normalizeRange(b);\n return (\n normA.startRow === normB.startRow &&\n normA.startCol === normB.startCol &&\n normA.endRow === normB.endRow &&\n normA.endCol === normB.endCol\n );\n}\n\n/**\n * Check if a range is a single cell (1x1).\n *\n * @param range - The range to check\n * @returns True if the range is exactly one cell\n */\nexport function isSingleCell(range: InternalCellRange): boolean {\n const normalized = normalizeRange(range);\n return normalized.startRow === normalized.endRow && normalized.startCol === normalized.endCol;\n}\n","/**\n * Selection Plugin (Class-based)\n *\n * Provides selection functionality for tbw-grid.\n * Supports three modes:\n * - 'cell': Single cell selection (default). No border, just focus highlight.\n * - 'row': Row selection. Clicking a cell selects the entire row.\n * - 'range': Range selection. Shift+click or drag to select rectangular cell ranges.\n */\n\nimport { clearCellFocus, getRowIndexFromCell } from '../../core/internal/utils';\nimport { BaseGridPlugin, CellClickEvent, CellMouseEvent } from '../../core/plugin/base-plugin';\nimport {\n createRangeFromAnchor,\n getAllCellsInRanges,\n isCellInAnyRange,\n normalizeRange,\n toPublicRanges,\n} from './range-selection';\nimport styles from './selection.css?inline';\nimport type { CellRange, InternalCellRange, SelectionChangeDetail, SelectionConfig, SelectionMode } from './types';\n\n/**\n * Build the selection change event detail for the current state.\n */\nfunction buildSelectionEvent(\n mode: SelectionMode,\n state: {\n selectedCell: { row: number; col: number } | null;\n selected: Set<number>;\n ranges: InternalCellRange[];\n },\n colCount: number,\n): SelectionChangeDetail {\n if (mode === 'cell' && state.selectedCell) {\n return {\n mode,\n ranges: [\n {\n from: { row: state.selectedCell.row, col: state.selectedCell.col },\n to: { row: state.selectedCell.row, col: state.selectedCell.col },\n },\n ],\n };\n }\n\n if (mode === 'row' && state.selected.size > 0) {\n const ranges = [...state.selected].map((rowIndex) => ({\n from: { row: rowIndex, col: 0 },\n to: { row: rowIndex, col: colCount - 1 },\n }));\n return { mode, ranges };\n }\n\n if (mode === 'range' && state.ranges.length > 0) {\n return { mode, ranges: toPublicRanges(state.ranges) };\n }\n\n return { mode, ranges: [] };\n}\n\n/**\n * Selection Plugin for tbw-grid\n *\n * @example\n * ```ts\n * new SelectionPlugin({ mode: 'range' })\n * ```\n */\nexport class SelectionPlugin extends BaseGridPlugin<SelectionConfig> {\n readonly name = 'selection';\n override readonly version = '1.0.0';\n\n protected override get defaultConfig(): Partial<SelectionConfig> {\n return {\n mode: 'cell',\n };\n }\n\n // #region Internal State\n /** Row selection state (row mode) */\n private selected = new Set<number>();\n private lastSelected: number | null = null;\n private anchor: number | null = null;\n\n /** Range selection state (range mode) */\n private ranges: InternalCellRange[] = [];\n private activeRange: InternalCellRange | null = null;\n private cellAnchor: { row: number; col: number } | null = null;\n private isDragging = false;\n\n /** Pending keyboard navigation update (processed in afterRender) */\n private pendingKeyboardUpdate: { shiftKey: boolean } | null = null;\n\n /** Cell selection state (cell mode) */\n private selectedCell: { row: number; col: number } | null = null;\n\n // #endregion\n\n // #region Lifecycle\n\n override detach(): void {\n this.selected.clear();\n this.ranges = [];\n this.activeRange = null;\n this.cellAnchor = null;\n this.isDragging = false;\n this.selectedCell = null;\n this.pendingKeyboardUpdate = null;\n }\n\n // #endregion\n\n // #region Event Handlers\n\n override onCellClick(event: CellClickEvent): boolean {\n const { rowIndex, colIndex, originalEvent } = event;\n const { mode } = this.config;\n\n // CELL MODE: Single cell selection\n if (mode === 'cell') {\n this.selectedCell = { row: rowIndex, col: colIndex };\n this.emit<SelectionChangeDetail>('selection-change', this.#buildEvent());\n this.requestAfterRender();\n return false;\n }\n\n // ROW MODE: Select entire row\n if (mode === 'row') {\n this.selected.clear();\n this.selected.add(rowIndex);\n this.lastSelected = rowIndex;\n\n this.emit<SelectionChangeDetail>('selection-change', this.#buildEvent());\n this.requestAfterRender();\n return false;\n }\n\n // RANGE MODE: Shift+click extends selection, click starts new\n if (mode === 'range') {\n const shiftKey = originalEvent.shiftKey;\n const ctrlKey = originalEvent.ctrlKey || originalEvent.metaKey;\n\n if (shiftKey && this.cellAnchor) {\n // Extend selection from anchor\n const newRange = createRangeFromAnchor(this.cellAnchor, { row: rowIndex, col: colIndex });\n\n if (ctrlKey) {\n if (this.ranges.length > 0) {\n this.ranges[this.ranges.length - 1] = newRange;\n } else {\n this.ranges.push(newRange);\n }\n } else {\n this.ranges = [newRange];\n }\n this.activeRange = newRange;\n } else if (ctrlKey) {\n const newRange: InternalCellRange = {\n startRow: rowIndex,\n startCol: colIndex,\n endRow: rowIndex,\n endCol: colIndex,\n };\n this.ranges.push(newRange);\n this.activeRange = newRange;\n this.cellAnchor = { row: rowIndex, col: colIndex };\n } else {\n const newRange: InternalCellRange = {\n startRow: rowIndex,\n startCol: colIndex,\n endRow: rowIndex,\n endCol: colIndex,\n };\n this.ranges = [newRange];\n this.activeRange = newRange;\n this.cellAnchor = { row: rowIndex, col: colIndex };\n }\n\n this.emit<SelectionChangeDetail>('selection-change', this.#buildEvent());\n\n this.requestAfterRender();\n return false;\n }\n\n return false;\n }\n\n override onKeyDown(event: KeyboardEvent): boolean {\n const { mode } = this.config;\n const navKeys = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Tab', 'Home', 'End', 'PageUp', 'PageDown'];\n const isNavKey = navKeys.includes(event.key);\n\n // Escape clears selection in all modes\n if (event.key === 'Escape') {\n if (mode === 'cell') {\n this.selectedCell = null;\n } else if (mode === 'row') {\n this.selected.clear();\n this.anchor = null;\n } else if (mode === 'range') {\n this.ranges = [];\n this.activeRange = null;\n this.cellAnchor = null;\n }\n this.emit<SelectionChangeDetail>('selection-change', this.#buildEvent());\n this.requestAfterRender();\n return true;\n }\n\n // CELL MODE: Selection follows focus\n if (mode === 'cell' && isNavKey) {\n // Use queueMicrotask so grid's handler runs first and updates focusRow/focusCol\n queueMicrotask(() => {\n this.selectedCell = { row: this.grid._focusRow, col: this.grid._focusCol };\n this.emit<SelectionChangeDetail>('selection-change', this.#buildEvent());\n this.requestAfterRender();\n });\n return false; // Let grid handle navigation\n }\n\n // ROW MODE: Only Up/Down arrows move row selection\n if (mode === 'row' && (event.key === 'ArrowUp' || event.key === 'ArrowDown')) {\n // Let grid move focus first, then sync row selection\n queueMicrotask(() => {\n this.selected.clear();\n this.selected.add(this.grid._focusRow);\n this.lastSelected = this.grid._focusRow;\n this.emit<SelectionChangeDetail>('selection-change', this.#buildEvent());\n this.requestAfterRender();\n });\n return false; // Let grid handle navigation\n }\n\n // RANGE MODE: Shift+Arrow extends, plain Arrow resets\n // Tab key always navigates without extending (even with Shift)\n if (mode === 'range' && isNavKey) {\n // Tab should not extend selection - it just navigates to the next/previous cell\n const isTabKey = event.key === 'Tab';\n const shouldExtend = event.shiftKey && !isTabKey;\n\n // Capture anchor BEFORE grid moves focus (synchronous)\n // This ensures the anchor is the starting point, not the destination\n if (shouldExtend && !this.cellAnchor) {\n this.cellAnchor = { row: this.grid._focusRow, col: this.grid._focusCol };\n }\n\n // Mark pending update - will be processed in afterRender when grid updates focus\n this.pendingKeyboardUpdate = { shiftKey: shouldExtend };\n\n // Schedule afterRender to run after grid's keyboard handler completes\n // Grid's refreshVirtualWindow(false) skips afterRender for performance,\n // so we explicitly request it to process pendingKeyboardUpdate\n queueMicrotask(() => this.requestAfterRender());\n\n return false; // Let grid handle navigation\n }\n\n // Ctrl+A selects all in range mode\n if (mode === 'range' && event.key === 'a' && (event.ctrlKey || event.metaKey)) {\n const rowCount = this.rows.length;\n const colCount = this.columns.length;\n if (rowCount > 0 && colCount > 0) {\n const allRange: InternalCellRange = {\n startRow: 0,\n startCol: 0,\n endRow: rowCount - 1,\n endCol: colCount - 1,\n };\n this.ranges = [allRange];\n this.activeRange = allRange;\n this.emit<SelectionChangeDetail>('selection-change', this.#buildEvent());\n this.requestAfterRender();\n return true;\n }\n }\n\n return false;\n }\n\n override onCellMouseDown(event: CellMouseEvent): boolean | void {\n if (this.config.mode !== 'range') return;\n if (event.rowIndex === undefined || event.colIndex === undefined) return;\n if (event.rowIndex < 0) return; // Header\n\n // Let onCellClick handle shift+click for range extension\n if (event.originalEvent.shiftKey && this.cellAnchor) {\n return;\n }\n\n // Start drag selection\n this.isDragging = true;\n const rowIndex = event.rowIndex;\n const colIndex = event.colIndex;\n this.cellAnchor = { row: rowIndex, col: colIndex };\n\n const ctrlKey = event.originalEvent.ctrlKey || event.originalEvent.metaKey;\n if (!ctrlKey) {\n this.ranges = [];\n }\n\n const newRange: InternalCellRange = {\n startRow: rowIndex,\n startCol: colIndex,\n endRow: rowIndex,\n endCol: colIndex,\n };\n this.ranges.push(newRange);\n this.activeRange = newRange;\n\n this.emit<SelectionChangeDetail>('selection-change', this.#buildEvent());\n this.requestAfterRender();\n return true;\n }\n\n override onCellMouseMove(event: CellMouseEvent): boolean | void {\n if (this.config.mode !== 'range') return;\n if (!this.isDragging || !this.cellAnchor) return;\n if (event.rowIndex === undefined || event.colIndex === undefined) return;\n if (event.rowIndex < 0) return;\n\n const newRange = createRangeFromAnchor(this.cellAnchor, { row: event.rowIndex, col: event.colIndex });\n\n if (this.ranges.length > 0) {\n this.ranges[this.ranges.length - 1] = newRange;\n } else {\n this.ranges.push(newRange);\n }\n this.activeRange = newRange;\n\n this.emit<SelectionChangeDetail>('selection-change', this.#buildEvent());\n this.requestAfterRender();\n return true;\n }\n\n override onCellMouseUp(_event: CellMouseEvent): boolean | void {\n if (this.config.mode !== 'range') return;\n if (this.isDragging) {\n this.isDragging = false;\n return true;\n }\n }\n\n /**\n * Apply selection classes to visible cells/rows.\n * Shared by afterRender and onScrollRender.\n */\n #applySelectionClasses(): void {\n const shadowRoot = this.shadowRoot;\n if (!shadowRoot) return;\n\n const { mode } = this.config;\n\n // Clear all selection classes first\n const allCells = shadowRoot.querySelectorAll('.cell');\n allCells.forEach((cell) => {\n cell.classList.remove('selected', 'top', 'bottom', 'first', 'last');\n });\n\n const allRows = shadowRoot.querySelectorAll('.data-grid-row');\n allRows.forEach((row) => {\n row.classList.remove('selected', 'row-focus');\n });\n\n // ROW MODE: Add row-focus class to selected rows, disable cell-focus\n if (mode === 'row') {\n // In row mode, disable ALL cell-focus styling - row selection takes precedence\n clearCellFocus(shadowRoot);\n\n allRows.forEach((row) => {\n const firstCell = row.querySelector('.cell[data-row]');\n const rowIndex = getRowIndexFromCell(firstCell);\n if (rowIndex >= 0 && this.selected.has(rowIndex)) {\n row.classList.add('selected', 'row-focus');\n }\n });\n }\n\n // RANGE MODE: Add selected and edge classes to cells\n if (mode === 'range' && this.ranges.length > 0) {\n // Clear all cell-focus first - selection plugin manages focus styling in range mode\n clearCellFocus(shadowRoot);\n\n const normalized = this.activeRange ? normalizeRange(this.activeRange) : null;\n\n const cells = shadowRoot.querySelectorAll('.cell[data-row][data-col]');\n cells.forEach((cell) => {\n const rowIndex = parseInt(cell.getAttribute('data-row') ?? '-1', 10);\n const colIndex = parseInt(cell.getAttribute('data-col') ?? '-1', 10);\n if (rowIndex >= 0 && colIndex >= 0) {\n const inRange = isCellInAnyRange(rowIndex, colIndex, this.ranges);\n\n if (inRange) {\n cell.classList.add('selected');\n\n if (normalized) {\n if (rowIndex === normalized.startRow) cell.classList.add('top');\n if (rowIndex === normalized.endRow) cell.classList.add('bottom');\n if (colIndex === normalized.startCol) cell.classList.add('first');\n if (colIndex === normalized.endCol) cell.classList.add('last');\n }\n }\n }\n });\n }\n\n // CELL MODE: Remove cell-focus when selection plugin handles focus\n if (mode === 'cell' && this.selectedCell) {\n // Remove all cell-focus - the selection plugin manages focus styling\n clearCellFocus(shadowRoot);\n }\n }\n\n override afterRender(): void {\n const shadowRoot = this.shadowRoot;\n if (!shadowRoot) return;\n\n const container = shadowRoot.children[0];\n const { mode } = this.config;\n\n // Process pending keyboard navigation update (range mode)\n // This runs AFTER the grid has updated focusRow/focusCol\n if (this.pendingKeyboardUpdate && mode === 'range') {\n const { shiftKey } = this.pendingKeyboardUpdate;\n this.pendingKeyboardUpdate = null;\n\n const currentRow = this.grid._focusRow;\n const currentCol = this.grid._focusCol;\n\n if (shiftKey && this.cellAnchor) {\n // Extend selection from anchor to current focus\n const newRange = createRangeFromAnchor(this.cellAnchor, { row: currentRow, col: currentCol });\n this.ranges = [newRange];\n this.activeRange = newRange;\n } else if (!shiftKey) {\n // Without shift, clear selection (cell-focus will show instead)\n this.ranges = [];\n this.activeRange = null;\n this.cellAnchor = { row: currentRow, col: currentCol }; // Reset anchor to current position\n }\n\n this.emit<SelectionChangeDetail>('selection-change', this.#buildEvent());\n }\n\n // Set data attribute on host for CSS variable scoping\n (this.grid as unknown as Element).setAttribute('data-selection-mode', mode);\n\n // Toggle .selecting class during drag to prevent text selection\n if (container) {\n container.classList.toggle('selecting', this.isDragging);\n }\n\n this.#applySelectionClasses();\n }\n\n /**\n * Called after scroll-triggered row rendering.\n * Reapplies selection classes to recycled DOM elements.\n */\n override onScrollRender(): void {\n this.#applySelectionClasses();\n }\n\n // #endregion\n\n // #region Public API\n\n /**\n * Get the selected cell (cell mode only).\n */\n getSelectedCell(): { row: number; col: number } | null {\n return this.selectedCell;\n }\n\n /**\n * Get all selected row indices (row mode).\n */\n getSelectedRows(): number[] {\n return [...this.selected];\n }\n\n /**\n * Get all selected cell ranges in public format.\n */\n getRanges(): CellRange[] {\n return toPublicRanges(this.ranges);\n }\n\n /**\n * Get all selected cells across all ranges.\n */\n getSelectedCells(): Array<{ row: number; col: number }> {\n return getAllCellsInRanges(this.ranges);\n }\n\n /**\n * Check if a specific cell is in range selection.\n */\n isCellSelected(row: number, col: number): boolean {\n return isCellInAnyRange(row, col, this.ranges);\n }\n\n /**\n * Clear all selection.\n */\n clearSelection(): void {\n this.selectedCell = null;\n this.selected.clear();\n this.anchor = null;\n this.ranges = [];\n this.activeRange = null;\n this.cellAnchor = null;\n this.emit<SelectionChangeDetail>('selection-change', { mode: this.config.mode, ranges: [] });\n this.requestAfterRender();\n }\n\n /**\n * Set selected ranges programmatically.\n */\n setRanges(ranges: CellRange[]): void {\n this.ranges = ranges.map((r) => ({\n startRow: r.from.row,\n startCol: r.from.col,\n endRow: r.to.row,\n endCol: r.to.col,\n }));\n this.activeRange = this.ranges.length > 0 ? this.ranges[this.ranges.length - 1] : null;\n this.emit<SelectionChangeDetail>('selection-change', {\n mode: this.config.mode,\n ranges: toPublicRanges(this.ranges),\n });\n this.requestAfterRender();\n }\n\n // #endregion\n\n // #region Private Helpers\n\n #buildEvent(): SelectionChangeDetail {\n return buildSelectionEvent(\n this.config.mode,\n {\n selectedCell: this.selectedCell,\n selected: this.selected,\n ranges: this.ranges,\n },\n this.columns.length,\n );\n }\n\n // #endregion\n\n // #region Styles\n\n override readonly styles = styles;\n\n // #endregion\n}\n","import type { ServerSideDataSource, GetRowsParams, GetRowsResult } from './types';\n\nexport function getBlockNumber(rowIndex: number, blockSize: number): number {\n return Math.floor(rowIndex / blockSize);\n}\n\nexport function getBlockRange(blockNumber: number, blockSize: number): { start: number; end: number } {\n return {\n start: blockNumber * blockSize,\n end: (blockNumber + 1) * blockSize,\n };\n}\n\nexport function getRequiredBlocks(startRow: number, endRow: number, blockSize: number): number[] {\n const startBlock = getBlockNumber(startRow, blockSize);\n const endBlock = getBlockNumber(endRow - 1, blockSize);\n\n const blocks: number[] = [];\n for (let i = startBlock; i <= endBlock; i++) {\n blocks.push(i);\n }\n return blocks;\n}\n\nexport async function loadBlock(\n dataSource: ServerSideDataSource,\n blockNumber: number,\n blockSize: number,\n params: Partial<GetRowsParams>\n): Promise<GetRowsResult> {\n const range = getBlockRange(blockNumber, blockSize);\n\n return dataSource.getRows({\n startRow: range.start,\n endRow: range.end,\n sortModel: params.sortModel,\n filterModel: params.filterModel,\n });\n}\n\nexport function getRowFromCache(\n rowIndex: number,\n blockSize: number,\n loadedBlocks: Map<number, any[]>\n): any | undefined {\n const blockNumber = getBlockNumber(rowIndex, blockSize);\n const block = loadedBlocks.get(blockNumber);\n if (!block) return undefined;\n\n const indexInBlock = rowIndex % blockSize;\n return block[indexInBlock];\n}\n\nexport function isBlockLoaded(blockNumber: number, loadedBlocks: Map<number, any[]>): boolean {\n return loadedBlocks.has(blockNumber);\n}\n\nexport function isBlockLoading(blockNumber: number, loadingBlocks: Set<number>): boolean {\n return loadingBlocks.has(blockNumber);\n}\n","/**\n * Server-Side Data Plugin (Class-based)\n *\n * Provides server-side data loading with caching and lazy loading.\n */\n\nimport { BaseGridPlugin, ScrollEvent } from '../../core/plugin/base-plugin';\nimport { getBlockNumber, getRequiredBlocks, getRowFromCache, loadBlock } from './datasource';\nimport type { ServerSideConfig, ServerSideDataSource } from './types';\n\n/** Scroll debounce delay in ms */\nconst SCROLL_DEBOUNCE_MS = 100;\n\n/**\n * Server-Side Plugin for tbw-grid\n *\n * @example\n * ```ts\n * const plugin = new ServerSidePlugin({ cacheBlockSize: 100 });\n * plugin.setDataSource(myDataSource);\n * ```\n */\nexport class ServerSidePlugin extends BaseGridPlugin<ServerSideConfig> {\n readonly name = 'serverSide';\n override readonly version = '1.0.0';\n\n protected override get defaultConfig(): Partial<ServerSideConfig> {\n return {\n pageSize: 100,\n cacheBlockSize: 100,\n maxConcurrentRequests: 2,\n };\n }\n\n // #region Internal State\n private dataSource: ServerSideDataSource | null = null;\n private totalRowCount = 0;\n private loadedBlocks = new Map<number, unknown[]>();\n private loadingBlocks = new Set<number>();\n private lastRequestId = 0;\n private scrollDebounceTimer?: ReturnType<typeof setTimeout>;\n // #endregion\n\n // #region Lifecycle\n\n override detach(): void {\n this.dataSource = null;\n this.totalRowCount = 0;\n this.loadedBlocks.clear();\n this.loadingBlocks.clear();\n this.lastRequestId = 0;\n if (this.scrollDebounceTimer) {\n clearTimeout(this.scrollDebounceTimer);\n this.scrollDebounceTimer = undefined;\n }\n }\n // #endregion\n\n // #region Private Methods\n\n /**\n * Check current viewport and load any missing blocks.\n */\n private loadRequiredBlocks(): void {\n if (!this.dataSource) return;\n\n // Get fresh viewport from grid's virtualization state\n const gridRef = this.grid as unknown as { _virtualization: { start: number; end: number } };\n const blockSize = this.config.cacheBlockSize ?? 100;\n const viewport = { startRow: gridRef._virtualization.start, endRow: gridRef._virtualization.end };\n\n // Determine which blocks are needed for current viewport\n const requiredBlocks = getRequiredBlocks(viewport.startRow, viewport.endRow, blockSize);\n\n // Load missing blocks\n for (const blockNum of requiredBlocks) {\n if (this.loadedBlocks.has(blockNum) || this.loadingBlocks.has(blockNum)) {\n continue;\n }\n\n // Check concurrent request limit\n if (this.loadingBlocks.size >= (this.config.maxConcurrentRequests ?? 2)) {\n break;\n }\n\n this.loadingBlocks.add(blockNum);\n\n loadBlock(this.dataSource, blockNum, blockSize, {})\n .then((result) => {\n this.loadedBlocks.set(blockNum, result.rows);\n this.totalRowCount = result.totalRowCount;\n this.loadingBlocks.delete(blockNum);\n this.requestRender();\n // Re-check with fresh viewport: user may have scrolled further\n this.loadRequiredBlocks();\n })\n .catch(() => {\n this.loadingBlocks.delete(blockNum);\n });\n }\n }\n // #endregion\n\n // #region Hooks\n\n override processRows(rows: readonly unknown[]): unknown[] {\n if (!this.dataSource) return [...rows];\n\n // Create placeholder rows for total count\n const result: unknown[] = [];\n for (let i = 0; i < this.totalRowCount; i++) {\n const cached = getRowFromCache(i, this.config.cacheBlockSize ?? 100, this.loadedBlocks);\n result.push(cached ?? { __loading: true, __index: i });\n }\n\n return result;\n }\n\n override onScroll(event: ScrollEvent): void {\n if (!this.dataSource) return;\n\n // Immediate check for blocks\n this.loadRequiredBlocks();\n\n // Debounce: when scrolling stops, do a final check with fresh viewport\n if (this.scrollDebounceTimer) {\n clearTimeout(this.scrollDebounceTimer);\n }\n this.scrollDebounceTimer = setTimeout(() => {\n this.loadRequiredBlocks();\n }, SCROLL_DEBOUNCE_MS);\n }\n // #endregion\n\n // #region Public API\n\n /**\n * Set the data source for server-side loading.\n * @param dataSource - Data source implementing the getRows method\n */\n setDataSource(dataSource: ServerSideDataSource): void {\n this.dataSource = dataSource;\n this.loadedBlocks.clear();\n this.loadingBlocks.clear();\n\n // Load first block\n const blockSize = this.config.cacheBlockSize ?? 100;\n loadBlock(dataSource, 0, blockSize, {}).then((result) => {\n this.loadedBlocks.set(0, result.rows);\n this.totalRowCount = result.totalRowCount;\n this.requestRender();\n });\n }\n\n /**\n * Refresh all data from the server.\n */\n refresh(): void {\n if (!this.dataSource) return;\n this.loadedBlocks.clear();\n this.loadingBlocks.clear();\n this.requestRender();\n }\n\n /**\n * Clear all cached data without refreshing.\n */\n purgeCache(): void {\n this.loadedBlocks.clear();\n }\n\n /**\n * Get the total row count from the server.\n */\n getTotalRowCount(): number {\n return this.totalRowCount;\n }\n\n /**\n * Check if a specific row is loaded in the cache.\n * @param rowIndex - Row index to check\n */\n isRowLoaded(rowIndex: number): boolean {\n const blockSize = this.config.cacheBlockSize ?? 100;\n const blockNum = getBlockNumber(rowIndex, blockSize);\n return this.loadedBlocks.has(blockNum);\n }\n\n /**\n * Get the number of loaded cache blocks.\n */\n getLoadedBlockCount(): number {\n return this.loadedBlocks.size;\n }\n // #endregion\n}\n","/**\n * Core Tree Data Logic\n *\n * Pure functions for tree flattening, expansion, and traversal.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n// The tree plugin intentionally uses `any` for maximum flexibility with user-defined row types.\n\nimport type { FlattenedTreeRow, TreeConfig } from './types';\n\n/**\n * Generates a unique key for a row.\n * Uses row.id if available, otherwise generates from path.\n */\nexport function generateRowKey(row: any, index: number, parentKey: string | null): string {\n if (row.id !== undefined) return String(row.id);\n return parentKey ? `${parentKey}-${index}` : String(index);\n}\n\n/**\n * Flattens a hierarchical tree into a flat array of rows with metadata.\n * Only includes children of expanded nodes.\n */\nexport function flattenTree(\n rows: any[],\n config: TreeConfig,\n expandedKeys: Set<string>,\n parentKey: string | null = null,\n depth = 0\n): FlattenedTreeRow[] {\n const childrenField = config.childrenField ?? 'children';\n const result: FlattenedTreeRow[] = [];\n\n for (let i = 0; i < rows.length; i++) {\n const row = rows[i];\n const key = generateRowKey(row, i, parentKey);\n const children = row[childrenField];\n const hasChildren = Array.isArray(children) && children.length > 0;\n const isExpanded = expandedKeys.has(key);\n\n result.push({\n key,\n data: row,\n depth,\n hasChildren,\n isExpanded,\n parentKey,\n });\n\n // Recursively add children if expanded\n if (hasChildren && isExpanded) {\n const childRows = flattenTree(children, config, expandedKeys, key, depth + 1);\n result.push(...childRows);\n }\n }\n\n return result;\n}\n\n/**\n * Toggles the expansion state of a row.\n * Returns a new Set with the toggled state.\n */\nexport function toggleExpand(expandedKeys: Set<string>, key: string): Set<string> {\n const newExpanded = new Set(expandedKeys);\n if (newExpanded.has(key)) {\n newExpanded.delete(key);\n } else {\n newExpanded.add(key);\n }\n return newExpanded;\n}\n\n/**\n * Expands all nodes in the tree.\n * Returns a Set of all parent row keys.\n */\nexport function expandAll(rows: any[], config: TreeConfig, parentKey: string | null = null, depth = 0): Set<string> {\n const childrenField = config.childrenField ?? 'children';\n const keys = new Set<string>();\n\n for (let i = 0; i < rows.length; i++) {\n const row = rows[i];\n const key = generateRowKey(row, i, parentKey);\n const children = row[childrenField];\n\n if (Array.isArray(children) && children.length > 0) {\n keys.add(key);\n const childKeys = expandAll(children, config, key, depth + 1);\n for (const k of childKeys) keys.add(k);\n }\n }\n\n return keys;\n}\n\n/**\n * Collapses all nodes.\n * Returns an empty Set.\n */\nexport function collapseAll(): Set<string> {\n return new Set();\n}\n\n/**\n * Gets all descendants of a node from the flattened row list.\n * Useful for operations that need to affect an entire subtree.\n */\nexport function getDescendants(flattenedRows: FlattenedTreeRow[], parentKey: string): FlattenedTreeRow[] {\n const descendants: FlattenedTreeRow[] = [];\n let collecting = false;\n let parentDepth = -1;\n\n for (const row of flattenedRows) {\n if (row.key === parentKey) {\n collecting = true;\n parentDepth = row.depth;\n continue;\n }\n\n if (collecting) {\n if (row.depth > parentDepth) {\n descendants.push(row);\n } else {\n break; // No longer a descendant\n }\n }\n }\n\n return descendants;\n}\n\n/**\n * Finds the path from root to a specific row key.\n * Returns an array of keys from root to the target (inclusive).\n */\nexport function getPathToKey(\n rows: any[],\n targetKey: string,\n config: TreeConfig,\n parentKey: string | null = null,\n depth = 0\n): string[] | null {\n const childrenField = config.childrenField ?? 'children';\n\n for (let i = 0; i < rows.length; i++) {\n const row = rows[i];\n const key = generateRowKey(row, i, parentKey);\n\n if (key === targetKey) {\n return [key];\n }\n\n const children = row[childrenField];\n if (Array.isArray(children) && children.length > 0) {\n const childPath = getPathToKey(children, targetKey, config, key, depth + 1);\n if (childPath) {\n return [key, ...childPath];\n }\n }\n }\n\n return null;\n}\n\n/**\n * Expands all ancestors of a specific row to make it visible.\n * Returns a new Set with the required keys added.\n */\nexport function expandToKey(\n rows: any[],\n targetKey: string,\n config: TreeConfig,\n existingExpanded: Set<string>\n): Set<string> {\n const path = getPathToKey(rows, targetKey, config);\n if (!path) return existingExpanded;\n\n const newExpanded = new Set(existingExpanded);\n // Add all keys except the last one (the target itself)\n for (let i = 0; i < path.length - 1; i++) {\n newExpanded.add(path[i]);\n }\n return newExpanded;\n}\n","/**\n * Tree Structure Auto-Detection\n *\n * Utilities for detecting hierarchical tree data structures.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n// The tree plugin intentionally uses `any` for maximum flexibility with user-defined row types.\n\n/**\n * Detects if the data has a tree structure by checking for children arrays.\n */\nexport function detectTreeStructure(rows: any[], childrenField = 'children'): boolean {\n if (!Array.isArray(rows) || rows.length === 0) return false;\n\n // Check if any row has a non-empty children array\n for (const row of rows) {\n if (row && Array.isArray(row[childrenField]) && row[childrenField].length > 0) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Attempts to infer the children field name from common patterns.\n * Returns the first field that contains an array with items.\n */\nexport function inferChildrenField(rows: any[]): string | null {\n if (!Array.isArray(rows) || rows.length === 0) return null;\n\n const commonArrayFields = ['children', 'items', 'nodes', 'subRows', 'nested'];\n\n for (const row of rows) {\n if (!row || typeof row !== 'object') continue;\n\n for (const field of commonArrayFields) {\n if (Array.isArray(row[field]) && row[field].length > 0) {\n return field;\n }\n }\n }\n\n return null;\n}\n\n/**\n * Calculates the maximum depth of the tree.\n * Useful for layout calculations and virtualization.\n */\nexport function getMaxDepth(rows: any[], childrenField = 'children', currentDepth = 0): number {\n if (!Array.isArray(rows) || rows.length === 0) return currentDepth;\n\n let maxDepth = currentDepth;\n\n for (const row of rows) {\n if (!row) continue;\n const children = row[childrenField];\n if (Array.isArray(children) && children.length > 0) {\n const childDepth = getMaxDepth(children, childrenField, currentDepth + 1);\n if (childDepth > maxDepth) {\n maxDepth = childDepth;\n }\n }\n }\n\n return maxDepth;\n}\n\n/**\n * Counts total nodes in the tree (including all descendants).\n */\nexport function countNodes(rows: any[], childrenField = 'children'): number {\n if (!Array.isArray(rows)) return 0;\n\n let count = 0;\n for (const row of rows) {\n if (!row) continue;\n count++;\n const children = row[childrenField];\n if (Array.isArray(children)) {\n count += countNodes(children, childrenField);\n }\n }\n\n return count;\n}\n","/**\n * Tree Data Plugin\n *\n * Enables hierarchical tree data with expand/collapse, sorting, and auto-detection.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { BaseGridPlugin, CellClickEvent, HeaderClickEvent } from '../../core/plugin/base-plugin';\nimport type { ColumnConfig, GridConfig } from '../../core/types';\nimport { collapseAll, expandAll, expandToKey, toggleExpand } from './tree-data';\nimport { detectTreeStructure, inferChildrenField } from './tree-detect';\nimport styles from './tree.css?inline';\nimport type { ExpandCollapseAnimation, FlattenedTreeRow, TreeConfig, TreeExpandDetail } from './types';\n\ninterface GridWithConfig {\n effectiveConfig?: GridConfig;\n _sortState?: { field: string; direction: 1 | -1 } | null;\n}\n\n/**\n * Tree Data Plugin for tbw-grid\n *\n * @example\n * ```ts\n * new TreePlugin({ defaultExpanded: true, indentWidth: 24 })\n * ```\n */\nexport class TreePlugin extends BaseGridPlugin<TreeConfig> {\n readonly name = 'tree';\n override readonly version = '1.0.0';\n override readonly styles = styles;\n\n protected override get defaultConfig(): Partial<TreeConfig> {\n return {\n childrenField: 'children',\n autoDetect: true,\n defaultExpanded: false,\n indentWidth: 20,\n showExpandIcons: true,\n animation: 'slide',\n };\n }\n\n // #region State\n\n private expandedKeys = new Set<string>();\n private initialExpansionDone = false;\n private flattenedRows: FlattenedTreeRow[] = [];\n private rowKeyMap = new Map<string, FlattenedTreeRow>();\n private previousVisibleKeys = new Set<string>();\n private keysToAnimate = new Set<string>();\n private sortState: { field: string; direction: 1 | -1 } | null = null;\n\n override detach(): void {\n this.expandedKeys.clear();\n this.initialExpansionDone = false;\n this.flattenedRows = [];\n this.rowKeyMap.clear();\n this.previousVisibleKeys.clear();\n this.keysToAnimate.clear();\n this.sortState = null;\n }\n\n // #endregion\n\n // #region Animation\n\n private get animationStyle(): ExpandCollapseAnimation {\n const gridEl = this.grid as unknown as GridWithConfig;\n const mode = gridEl.effectiveConfig?.animation?.mode ?? 'reduced-motion';\n\n if (mode === false || mode === 'off') return false;\n if (mode !== true && mode !== 'on') {\n const host = this.shadowRoot?.host as HTMLElement | undefined;\n if (host && getComputedStyle(host).getPropertyValue('--tbw-animation-enabled').trim() === '0') {\n return false;\n }\n }\n return this.config.animation ?? 'slide';\n }\n\n // #endregion\n\n // #region Auto-Detection\n\n detect(rows: readonly unknown[]): boolean {\n if (!this.config.autoDetect) return false;\n const field = this.config.childrenField ?? inferChildrenField(rows as any[]) ?? 'children';\n return detectTreeStructure(rows as any[], field);\n }\n\n // #endregion\n\n // #region Data Processing\n\n override processRows(rows: readonly unknown[]): any[] {\n const childrenField = this.config.childrenField ?? 'children';\n\n if (!detectTreeStructure(rows as any[], childrenField)) {\n this.flattenedRows = [];\n this.rowKeyMap.clear();\n this.previousVisibleKeys.clear();\n return [...rows];\n }\n\n // Assign stable keys, then optionally sort\n let data = this.withStableKeys(rows as any[]);\n if (this.sortState) {\n data = this.sortTree(data, this.sortState.field, this.sortState.direction);\n }\n\n // Initialize expansion if needed\n if (this.config.defaultExpanded && !this.initialExpansionDone) {\n this.expandedKeys = expandAll(data, this.config);\n this.initialExpansionDone = true;\n }\n\n // Flatten and track animations\n this.flattenedRows = this.flattenTree(data, this.expandedKeys);\n this.rowKeyMap.clear();\n this.keysToAnimate.clear();\n const currentKeys = new Set<string>();\n\n for (const row of this.flattenedRows) {\n this.rowKeyMap.set(row.key, row);\n currentKeys.add(row.key);\n if (!this.previousVisibleKeys.has(row.key) && row.depth > 0) {\n this.keysToAnimate.add(row.key);\n }\n }\n this.previousVisibleKeys = currentKeys;\n\n return this.flattenedRows.map((r) => ({\n ...r.data,\n __treeKey: r.key,\n __treeDepth: r.depth,\n __treeHasChildren: r.hasChildren,\n __treeExpanded: r.isExpanded,\n }));\n }\n\n /** Assign stable keys to rows (preserves key across sort operations) */\n private withStableKeys(rows: any[], parentKey: string | null = null): any[] {\n const childrenField = this.config.childrenField ?? 'children';\n return rows.map((row, i) => {\n const key =\n row.id !== undefined ? String(row.id) : (row.__stableKey ?? (parentKey ? `${parentKey}-${i}` : String(i)));\n const children = row[childrenField];\n const hasChildren = Array.isArray(children) && children.length > 0;\n return {\n ...row,\n __stableKey: key,\n ...(hasChildren ? { [childrenField]: this.withStableKeys(children, key) } : {}),\n };\n });\n }\n\n /** Flatten tree using stable keys */\n private flattenTree(rows: any[], expanded: Set<string>, depth = 0): FlattenedTreeRow[] {\n const childrenField = this.config.childrenField ?? 'children';\n const result: FlattenedTreeRow[] = [];\n\n for (const row of rows) {\n const key = row.__stableKey ?? row.id ?? '?';\n const children = row[childrenField];\n const hasChildren = Array.isArray(children) && children.length > 0;\n const isExpanded = expanded.has(key);\n\n result.push({\n key,\n data: row,\n depth,\n hasChildren,\n isExpanded,\n parentKey: depth > 0 ? key.substring(0, key.lastIndexOf('-')) || null : null,\n });\n\n if (hasChildren && isExpanded) {\n result.push(...this.flattenTree(children, expanded, depth + 1));\n }\n }\n return result;\n }\n\n /** Sort tree recursively, keeping children with parents */\n private sortTree(rows: any[], field: string, dir: 1 | -1): any[] {\n const childrenField = this.config.childrenField ?? 'children';\n const sorted = [...rows].sort((a, b) => {\n const aVal = a[field],\n bVal = b[field];\n if (aVal == null && bVal == null) return 0;\n if (aVal == null) return -1;\n if (bVal == null) return 1;\n return aVal > bVal ? dir : aVal < bVal ? -dir : 0;\n });\n return sorted.map((row) => {\n const children = row[childrenField];\n return Array.isArray(children) && children.length > 0\n ? { ...row, [childrenField]: this.sortTree(children, field, dir) }\n : row;\n });\n }\n\n override processColumns(columns: readonly ColumnConfig[]): ColumnConfig[] {\n if (this.flattenedRows.length === 0) return [...columns];\n\n const cols = [...columns] as ColumnConfig[];\n if (cols.length === 0) return cols;\n\n const firstCol = { ...cols[0] };\n const original = firstCol.viewRenderer;\n if ((original as any)?.__treeWrapped) return cols;\n\n const getConfig = () => this.config;\n const setIcon = this.setIcon.bind(this);\n const resolveIcon = this.resolveIcon.bind(this);\n\n const wrapped = (ctx: Parameters<NonNullable<typeof original>>[0]) => {\n const { value, row } = ctx;\n const { indentWidth = 20, showExpandIcons = true } = getConfig();\n\n const container = document.createElement('span');\n container.className = 'tree-cell';\n container.style.setProperty('--tree-depth', String(row.__treeDepth ?? 0));\n container.style.setProperty('--tbw-tree-indent', `${indentWidth}px`);\n\n if (row.__treeHasChildren && showExpandIcons) {\n const icon = document.createElement('span');\n icon.className = `tree-toggle${row.__treeExpanded ? ' expanded' : ''}`;\n setIcon(icon, resolveIcon(row.__treeExpanded ? 'collapse' : 'expand'));\n icon.setAttribute('data-tree-key', row.__treeKey);\n container.appendChild(icon);\n } else if (showExpandIcons) {\n const spacer = document.createElement('span');\n spacer.className = 'tree-spacer';\n container.appendChild(spacer);\n }\n\n const content = document.createElement('span');\n if (original) {\n const rendered = original(ctx);\n if (rendered instanceof Node) {\n content.appendChild(rendered);\n } else {\n content.textContent = String(rendered ?? value ?? '');\n }\n } else {\n content.textContent = String(value ?? '');\n }\n container.appendChild(content);\n return container;\n };\n\n (wrapped as any).__treeWrapped = true;\n firstCol.viewRenderer = wrapped;\n cols[0] = firstCol;\n return cols;\n }\n\n // #endregion\n\n // #region Event Handlers\n\n override onCellClick(event: CellClickEvent): boolean {\n const target = event.originalEvent?.target as HTMLElement;\n if (!target?.classList.contains('tree-toggle')) return false;\n\n const key = target.getAttribute('data-tree-key');\n const flatRow = key ? this.rowKeyMap.get(key) : null;\n if (!flatRow) return false;\n\n this.expandedKeys = toggleExpand(this.expandedKeys, key!);\n this.emit<TreeExpandDetail>('tree-expand', {\n key: key!,\n row: flatRow.data,\n expanded: this.expandedKeys.has(key!),\n depth: flatRow.depth,\n });\n this.requestRender();\n return true;\n }\n\n override onHeaderClick(event: HeaderClickEvent): boolean {\n if (this.flattenedRows.length === 0 || !event.column.sortable) return false;\n\n const { field } = event.column;\n if (!this.sortState || this.sortState.field !== field) {\n this.sortState = { field, direction: 1 };\n } else if (this.sortState.direction === 1) {\n this.sortState = { field, direction: -1 };\n } else {\n this.sortState = null;\n }\n\n // Sync grid sort indicator\n const gridEl = this.grid as unknown as GridWithConfig;\n if (gridEl._sortState !== undefined) {\n gridEl._sortState = this.sortState ? { ...this.sortState } : null;\n }\n\n this.emit('sort-change', { field, direction: this.sortState?.direction ?? 0 });\n this.requestRender();\n return true;\n }\n\n override afterRender(): void {\n const style = this.animationStyle;\n if (style === false || this.keysToAnimate.size === 0) return;\n\n const body = this.shadowRoot?.querySelector('.rows');\n if (!body) return;\n\n const animClass = style === 'fade' ? 'tbw-tree-fade-in' : 'tbw-tree-slide-in';\n for (const rowEl of body.querySelectorAll('.data-grid-row')) {\n const cell = rowEl.querySelector('.cell[data-row]');\n const idx = cell ? parseInt(cell.getAttribute('data-row') ?? '-1', 10) : -1;\n const key = this.flattenedRows[idx]?.key;\n\n if (key && this.keysToAnimate.has(key)) {\n rowEl.classList.add(animClass);\n rowEl.addEventListener('animationend', () => rowEl.classList.remove(animClass), { once: true });\n }\n }\n this.keysToAnimate.clear();\n }\n\n // #endregion\n\n // #region Public API\n\n expand(key: string): void {\n this.expandedKeys.add(key);\n this.requestRender();\n }\n\n collapse(key: string): void {\n this.expandedKeys.delete(key);\n this.requestRender();\n }\n\n toggle(key: string): void {\n this.expandedKeys = toggleExpand(this.expandedKeys, key);\n this.requestRender();\n }\n\n expandAll(): void {\n this.expandedKeys = expandAll(this.rows as any[], this.config);\n this.requestRender();\n }\n\n collapseAll(): void {\n this.expandedKeys = collapseAll();\n this.requestRender();\n }\n\n isExpanded(key: string): boolean {\n return this.expandedKeys.has(key);\n }\n\n getExpandedKeys(): string[] {\n return [...this.expandedKeys];\n }\n\n getFlattenedRows(): FlattenedTreeRow[] {\n return [...this.flattenedRows];\n }\n\n getRowByKey(key: string): any | undefined {\n return this.rowKeyMap.get(key)?.data;\n }\n\n expandToKey(key: string): void {\n this.expandedKeys = expandToKey(this.rows as any[], key, this.config, this.expandedKeys);\n this.requestRender();\n }\n\n // #endregion\n}\n","/**\n * Undo/Redo History Management\n *\n * Pure functions for managing the undo/redo stacks.\n * These functions are stateless and return new state objects.\n */\n\nimport type { EditAction, UndoRedoState } from './types';\n\n/**\n * Push a new action onto the undo stack.\n * Clears the redo stack since new actions invalidate redo history.\n *\n * @param state - Current undo/redo state\n * @param action - The action to add\n * @param maxSize - Maximum history size\n * @returns New state with the action added\n */\nexport function pushAction(state: UndoRedoState, action: EditAction, maxSize: number): UndoRedoState {\n const undoStack = [...state.undoStack, action];\n\n // Trim oldest actions if over max size\n while (undoStack.length > maxSize) {\n undoStack.shift();\n }\n\n return {\n undoStack,\n redoStack: [], // Clear redo on new action\n };\n}\n\n/**\n * Undo the most recent action.\n * Moves the action from undo stack to redo stack.\n *\n * @param state - Current undo/redo state\n * @returns New state and the action that was undone (or null if nothing to undo)\n */\nexport function undo(state: UndoRedoState): {\n newState: UndoRedoState;\n action: EditAction | null;\n} {\n if (state.undoStack.length === 0) {\n return { newState: state, action: null };\n }\n\n const undoStack = [...state.undoStack];\n const action = undoStack.pop();\n\n // This should never happen due to the length check above,\n // but TypeScript needs the explicit check\n if (!action) {\n return { newState: state, action: null };\n }\n\n return {\n newState: {\n undoStack,\n redoStack: [...state.redoStack, action],\n },\n action,\n };\n}\n\n/**\n * Redo the most recently undone action.\n * Moves the action from redo stack back to undo stack.\n *\n * @param state - Current undo/redo state\n * @returns New state and the action that was redone (or null if nothing to redo)\n */\nexport function redo(state: UndoRedoState): {\n newState: UndoRedoState;\n action: EditAction | null;\n} {\n if (state.redoStack.length === 0) {\n return { newState: state, action: null };\n }\n\n const redoStack = [...state.redoStack];\n const action = redoStack.pop();\n\n // This should never happen due to the length check above,\n // but TypeScript needs the explicit check\n if (!action) {\n return { newState: state, action: null };\n }\n\n return {\n newState: {\n undoStack: [...state.undoStack, action],\n redoStack,\n },\n action,\n };\n}\n\n/**\n * Check if there are any actions that can be undone.\n *\n * @param state - Current undo/redo state\n * @returns True if undo is available\n */\nexport function canUndo(state: UndoRedoState): boolean {\n return state.undoStack.length > 0;\n}\n\n/**\n * Check if there are any actions that can be redone.\n *\n * @param state - Current undo/redo state\n * @returns True if redo is available\n */\nexport function canRedo(state: UndoRedoState): boolean {\n return state.redoStack.length > 0;\n}\n\n/**\n * Clear all history, returning an empty state.\n *\n * @returns Fresh empty state\n */\nexport function clearHistory(): UndoRedoState {\n return { undoStack: [], redoStack: [] };\n}\n\n/**\n * Create a new edit action with the current timestamp.\n *\n * @param rowIndex - The row index where the edit occurred\n * @param field - The field (column key) that was edited\n * @param oldValue - The value before the edit\n * @param newValue - The value after the edit\n * @returns A new EditAction object\n */\nexport function createEditAction(rowIndex: number, field: string, oldValue: unknown, newValue: unknown): EditAction {\n return {\n type: 'cell-edit',\n rowIndex,\n field,\n oldValue,\n newValue,\n timestamp: Date.now(),\n };\n}\n","/**\n * Undo/Redo Plugin (Class-based)\n *\n * Provides undo/redo functionality for cell edits in tbw-grid.\n * Supports Ctrl+Z/Cmd+Z for undo and Ctrl+Y/Cmd+Y (or Ctrl+Shift+Z) for redo.\n */\n\nimport { BaseGridPlugin } from '../../core/plugin/base-plugin';\nimport { canRedo, canUndo, clearHistory, createEditAction, pushAction, redo, undo } from './history';\nimport type { EditAction, UndoRedoConfig, UndoRedoDetail } from './types';\n\n/**\n * Class-based Undo/Redo plugin for tbw-grid.\n *\n * Tracks cell edits and provides undo/redo functionality via keyboard shortcuts\n * or programmatic API.\n */\nexport class UndoRedoPlugin extends BaseGridPlugin<UndoRedoConfig> {\n readonly name = 'undoRedo';\n override readonly version = '1.0.0';\n\n protected override get defaultConfig(): Partial<UndoRedoConfig> {\n return {\n maxHistorySize: 100,\n };\n }\n\n // State as class properties\n private undoStack: EditAction[] = [];\n private redoStack: EditAction[] = [];\n\n /**\n * Clean up state when plugin is detached.\n */\n override detach(): void {\n this.undoStack = [];\n this.redoStack = [];\n }\n\n /**\n * Handle keyboard shortcuts for undo/redo.\n * - Ctrl+Z / Cmd+Z: Undo\n * - Ctrl+Y / Cmd+Y / Ctrl+Shift+Z / Cmd+Shift+Z: Redo\n */\n override onKeyDown(event: KeyboardEvent): boolean {\n const isUndo = (event.ctrlKey || event.metaKey) && event.key === 'z' && !event.shiftKey;\n const isRedo = (event.ctrlKey || event.metaKey) && (event.key === 'y' || (event.key === 'z' && event.shiftKey));\n\n if (isUndo) {\n const result = undo({ undoStack: this.undoStack, redoStack: this.redoStack });\n if (result.action) {\n // Apply undo - restore old value\n const rows = this.rows as Record<string, unknown>[];\n if (rows[result.action.rowIndex]) {\n rows[result.action.rowIndex][result.action.field] = result.action.oldValue;\n }\n\n // Update state from result\n this.undoStack = result.newState.undoStack;\n this.redoStack = result.newState.redoStack;\n\n this.emit<UndoRedoDetail>('undo', {\n action: result.action,\n type: 'undo',\n });\n\n this.requestRender();\n }\n return true;\n }\n\n if (isRedo) {\n const result = redo({ undoStack: this.undoStack, redoStack: this.redoStack });\n if (result.action) {\n // Apply redo - restore new value\n const rows = this.rows as Record<string, unknown>[];\n if (rows[result.action.rowIndex]) {\n rows[result.action.rowIndex][result.action.field] = result.action.newValue;\n }\n\n // Update state from result\n this.undoStack = result.newState.undoStack;\n this.redoStack = result.newState.redoStack;\n\n this.emit<UndoRedoDetail>('redo', {\n action: result.action,\n type: 'redo',\n });\n\n this.requestRender();\n }\n return true;\n }\n\n return false;\n }\n\n // #region Public API Methods\n\n /**\n * Record a cell edit for undo/redo tracking.\n * Call this when a cell value changes.\n *\n * @param rowIndex - The row index where the edit occurred\n * @param field - The field (column key) that was edited\n * @param oldValue - The value before the edit\n * @param newValue - The value after the edit\n */\n recordEdit(rowIndex: number, field: string, oldValue: unknown, newValue: unknown): void {\n const action = createEditAction(rowIndex, field, oldValue, newValue);\n const newState = pushAction(\n { undoStack: this.undoStack, redoStack: this.redoStack },\n action,\n this.config.maxHistorySize ?? 100,\n );\n this.undoStack = newState.undoStack;\n this.redoStack = newState.redoStack;\n }\n\n /**\n * Programmatically undo the last action.\n *\n * @returns The undone action, or null if nothing to undo\n */\n undo(): EditAction | null {\n const result = undo({ undoStack: this.undoStack, redoStack: this.redoStack });\n if (result.action) {\n const rows = this.rows as Record<string, unknown>[];\n if (rows[result.action.rowIndex]) {\n rows[result.action.rowIndex][result.action.field] = result.action.oldValue;\n }\n this.undoStack = result.newState.undoStack;\n this.redoStack = result.newState.redoStack;\n this.requestRender();\n }\n return result.action;\n }\n\n /**\n * Programmatically redo the last undone action.\n *\n * @returns The redone action, or null if nothing to redo\n */\n redo(): EditAction | null {\n const result = redo({ undoStack: this.undoStack, redoStack: this.redoStack });\n if (result.action) {\n const rows = this.rows as Record<string, unknown>[];\n if (rows[result.action.rowIndex]) {\n rows[result.action.rowIndex][result.action.field] = result.action.newValue;\n }\n this.undoStack = result.newState.undoStack;\n this.redoStack = result.newState.redoStack;\n this.requestRender();\n }\n return result.action;\n }\n\n /**\n * Check if there are any actions that can be undone.\n */\n canUndo(): boolean {\n return canUndo({ undoStack: this.undoStack, redoStack: this.redoStack });\n }\n\n /**\n * Check if there are any actions that can be redone.\n */\n canRedo(): boolean {\n return canRedo({ undoStack: this.undoStack, redoStack: this.redoStack });\n }\n\n /**\n * Clear all undo/redo history.\n */\n clearHistory(): void {\n const newState = clearHistory();\n this.undoStack = newState.undoStack;\n this.redoStack = newState.redoStack;\n }\n\n /**\n * Get a copy of the current undo stack.\n */\n getUndoStack(): EditAction[] {\n return [...this.undoStack];\n }\n\n /**\n * Get a copy of the current redo stack.\n */\n getRedoStack(): EditAction[] {\n return [...this.redoStack];\n }\n // #endregion\n}\n","/**\n * Column Visibility Plugin (Class-based)\n *\n * Provides a UI for column visibility control via the shell's tool panel system.\n * Column visibility is a core grid feature - this plugin provides:\n * - A tool panel for column visibility management (registered with the shell)\n * - Backward-compatible API methods that delegate to grid.setColumnVisible(), etc.\n *\n * The grid emits 'column-visibility' events when columns are shown/hidden,\n * allowing consumers to save user preferences.\n *\n * When a reorder plugin is present, column rows become draggable for reordering.\n * Drag-drop emits 'column-reorder-request' events that the ReorderPlugin can listen for.\n */\n\nimport { BaseGridPlugin } from '../../core/plugin/base-plugin';\nimport type { ColumnConfig, ToolPanelDefinition } from '../../core/types';\nimport type { VisibilityConfig } from './types';\nimport styles from './visibility.css?inline';\n\n/**\n * Detail for column-reorder-request events emitted when users drag-drop in the visibility panel.\n */\nexport interface ColumnReorderRequestDetail {\n /** The field name of the column to move */\n field: string;\n /** The source index (before move) */\n fromIndex: number;\n /** The target index (after move) */\n toIndex: number;\n}\n\n/**\n * Check if a column can be moved (respects lockPosition/suppressMovable).\n * Inlined to avoid importing from reorder plugin.\n */\nfunction canMoveColumn(column: ColumnConfig): boolean {\n const meta = column.meta ?? {};\n return meta.lockPosition !== true && meta.suppressMovable !== true;\n}\n\n/** Extended grid interface with visibility methods */\ninterface GridWithVisibility {\n shadowRoot: ShadowRoot | null;\n getAllColumns(): Array<{ field: string; header: string; visible: boolean; lockVisible?: boolean }>;\n setColumnVisible(field: string, visible: boolean): void;\n toggleColumnVisibility(field: string): void;\n showAllColumns(): void;\n isColumnVisible(field: string): boolean;\n requestRender(): void;\n openToolPanel(id: string): void;\n closeToolPanel(): void;\n toggleToolPanel(id: string): void;\n activeToolPanel: string | undefined;\n}\n\n/**\n * Column Visibility Plugin for tbw-grid\n *\n * @example\n * ```ts\n * new VisibilityPlugin({ enabled: true, allowHideAll: false })\n * ```\n */\nexport class VisibilityPlugin extends BaseGridPlugin<VisibilityConfig> {\n readonly name = 'visibility';\n override readonly version = '1.0.0';\n\n /** Tool panel ID for shell integration */\n static readonly PANEL_ID = 'columns';\n\n protected override get defaultConfig(): Partial<VisibilityConfig> {\n return {\n allowHideAll: false,\n };\n }\n\n // #region Internal State\n private columnListElement: HTMLElement | null = null;\n\n // Drag state for reorder integration\n private isDragging = false;\n private draggedField: string | null = null;\n private draggedIndex: number | null = null;\n private dropIndex: number | null = null;\n // #endregion\n\n // #region Lifecycle\n\n override detach(): void {\n this.columnListElement = null;\n this.isDragging = false;\n this.draggedField = null;\n this.draggedIndex = null;\n this.dropIndex = null;\n }\n // #endregion\n\n // #region Shell Integration\n\n /**\n * Register the column visibility tool panel with the shell.\n */\n override getToolPanel(): ToolPanelDefinition | undefined {\n return {\n id: VisibilityPlugin.PANEL_ID,\n title: 'Columns',\n icon: '☰',\n tooltip: 'Column visibility',\n order: 100, // High order so it appears last\n render: (container) => this.renderPanelContent(container),\n };\n }\n // #endregion\n\n // #region Public API\n\n /**\n * Show the visibility sidebar panel.\n */\n show(): void {\n const grid = this.grid as unknown as GridWithVisibility;\n grid.openToolPanel(VisibilityPlugin.PANEL_ID);\n }\n\n /**\n * Hide the visibility sidebar panel.\n */\n hide(): void {\n const grid = this.grid as unknown as GridWithVisibility;\n grid.closeToolPanel();\n }\n\n /**\n * Toggle the visibility sidebar panel.\n */\n toggle(): void {\n const grid = this.grid as unknown as GridWithVisibility;\n grid.toggleToolPanel(VisibilityPlugin.PANEL_ID);\n }\n\n /**\n * Check if a specific column is visible.\n * Delegates to grid.isColumnVisible().\n * @param field - The field name to check\n * @returns True if the column is visible\n */\n isColumnVisible(field: string): boolean {\n const grid = this.grid as unknown as GridWithVisibility;\n return grid.isColumnVisible(field);\n }\n\n /**\n * Set visibility for a specific column.\n * Delegates to grid.setColumnVisible().\n * @param field - The field name of the column\n * @param visible - Whether the column should be visible\n */\n setColumnVisible(field: string, visible: boolean): void {\n const grid = this.grid as unknown as GridWithVisibility;\n grid.setColumnVisible(field, visible);\n }\n\n /**\n * Get list of all visible column fields.\n * @returns Array of visible field names\n */\n getVisibleColumns(): string[] {\n const grid = this.grid as unknown as GridWithVisibility;\n return grid\n .getAllColumns()\n .filter((c) => c.visible)\n .map((c) => c.field);\n }\n\n /**\n * Get list of all hidden column fields.\n * @returns Array of hidden field names\n */\n getHiddenColumns(): string[] {\n const grid = this.grid as unknown as GridWithVisibility;\n return grid\n .getAllColumns()\n .filter((c) => !c.visible)\n .map((c) => c.field);\n }\n\n /**\n * Show all columns.\n * Delegates to grid.showAllColumns().\n */\n showAll(): void {\n const grid = this.grid as unknown as GridWithVisibility;\n grid.showAllColumns();\n }\n\n /**\n * Toggle visibility for a specific column.\n * Delegates to grid.toggleColumnVisibility().\n * @param field - The field name of the column\n */\n toggleColumn(field: string): void {\n const grid = this.grid as unknown as GridWithVisibility;\n grid.toggleColumnVisibility(field);\n }\n\n /**\n * Show a specific column.\n * Delegates to grid.setColumnVisible().\n * @param field - The field name of the column to show\n */\n showColumn(field: string): void {\n const grid = this.grid as unknown as GridWithVisibility;\n grid.setColumnVisible(field, true);\n }\n\n /**\n * Hide a specific column.\n * Delegates to grid.setColumnVisible().\n * @param field - The field name of the column to hide\n */\n hideColumn(field: string): void {\n const grid = this.grid as unknown as GridWithVisibility;\n grid.setColumnVisible(field, false);\n }\n\n /**\n * Get all columns with their visibility status.\n * Useful for building visibility UI.\n * @returns Array of column info with visibility status\n */\n getAllColumns(): Array<{ field: string; header: string; visible: boolean; lockVisible?: boolean }> {\n const grid = this.grid as unknown as GridWithVisibility;\n return grid.getAllColumns();\n }\n\n /**\n * Check if the sidebar panel is currently open.\n * @returns True if the panel is open\n */\n isPanelVisible(): boolean {\n const grid = this.grid as unknown as GridWithVisibility;\n return grid.activeToolPanel === VisibilityPlugin.PANEL_ID;\n }\n // #endregion\n\n // #region Private Methods\n\n /**\n * Render the panel content into the shell's tool panel container.\n * Returns a cleanup function.\n */\n private renderPanelContent(container: HTMLElement): (() => void) | void {\n const grid = this.grid as unknown as GridWithVisibility;\n\n // Create content wrapper\n const wrapper = document.createElement('div');\n wrapper.className = 'tbw-visibility-content';\n\n // Column list container\n const columnList = document.createElement('div');\n columnList.className = 'tbw-visibility-list';\n wrapper.appendChild(columnList);\n\n // Show all button\n const showAllBtn = document.createElement('button');\n showAllBtn.className = 'tbw-visibility-show-all';\n showAllBtn.textContent = 'Show All';\n showAllBtn.addEventListener('click', () => {\n grid.showAllColumns();\n this.rebuildToggles(columnList);\n });\n wrapper.appendChild(showAllBtn);\n\n // Store reference\n this.columnListElement = columnList;\n\n // Build initial toggles\n this.rebuildToggles(columnList);\n\n // Append to container\n container.appendChild(wrapper);\n\n // Return cleanup function\n return () => {\n this.columnListElement = null;\n wrapper.remove();\n };\n }\n\n /**\n * Check if a reorder plugin is present (by name to avoid static import).\n */\n private hasReorderPlugin(): boolean {\n const plugin = this.grid?.getPluginByName?.('reorder');\n // Duck-type check - just verify the plugin exists and has a moveColumn method\n return !!(plugin && typeof (plugin as { moveColumn?: unknown }).moveColumn === 'function');\n }\n\n /**\n * Build the column toggle checkboxes.\n * When a reorder plugin is present, adds drag handles for reordering.\n */\n private rebuildToggles(columnList: HTMLElement): void {\n const grid = this.grid as unknown as GridWithVisibility;\n const reorderEnabled = this.hasReorderPlugin();\n\n columnList.innerHTML = '';\n\n // getAllColumns() now returns columns in their effective display order\n const allColumns = grid.getAllColumns();\n\n for (let i = 0; i < allColumns.length; i++) {\n const col = allColumns[i];\n const label = col.header || col.field;\n\n const row = document.createElement('div');\n row.className = col.lockVisible ? 'tbw-visibility-row locked' : 'tbw-visibility-row';\n row.setAttribute('data-field', col.field);\n row.setAttribute('data-index', String(i));\n\n // Add drag handle if reorder is enabled\n if (reorderEnabled && canMoveColumn(col as unknown as ColumnConfig)) {\n row.draggable = true;\n row.classList.add('reorderable');\n\n this.setupDragListeners(row, col.field, i, columnList);\n }\n\n const labelWrapper = document.createElement('label');\n labelWrapper.className = 'tbw-visibility-label';\n\n const checkbox = document.createElement('input');\n checkbox.type = 'checkbox';\n checkbox.checked = col.visible;\n checkbox.disabled = col.lockVisible ?? false;\n checkbox.addEventListener('change', () => {\n grid.toggleColumnVisibility(col.field);\n // Refresh after toggle (grid may re-render)\n setTimeout(() => this.rebuildToggles(columnList), 0);\n });\n\n const text = document.createElement('span');\n text.textContent = label;\n\n labelWrapper.appendChild(checkbox);\n labelWrapper.appendChild(text);\n\n // Add drag handle icon if reorderable\n if (reorderEnabled && canMoveColumn(col as unknown as ColumnConfig)) {\n const handle = document.createElement('span');\n handle.className = 'tbw-visibility-handle';\n // Use grid-level icons (fall back to defaults)\n this.setIcon(handle, this.resolveIcon('dragHandle'));\n handle.title = 'Drag to reorder';\n row.appendChild(handle);\n }\n\n row.appendChild(labelWrapper);\n columnList.appendChild(row);\n }\n }\n\n /**\n * Set up drag-and-drop event listeners for a row.\n * On drop, emits a 'column-reorder-request' event for other plugins to handle.\n */\n private setupDragListeners(row: HTMLElement, field: string, index: number, columnList: HTMLElement): void {\n row.addEventListener('dragstart', (e: DragEvent) => {\n this.isDragging = true;\n this.draggedField = field;\n this.draggedIndex = index;\n\n if (e.dataTransfer) {\n e.dataTransfer.effectAllowed = 'move';\n e.dataTransfer.setData('text/plain', field);\n }\n\n row.classList.add('dragging');\n });\n\n row.addEventListener('dragend', () => {\n this.isDragging = false;\n this.draggedField = null;\n this.draggedIndex = null;\n this.dropIndex = null;\n\n columnList.querySelectorAll('.tbw-visibility-row').forEach((r) => {\n r.classList.remove('dragging', 'drop-target', 'drop-before', 'drop-after');\n });\n });\n\n row.addEventListener('dragover', (e: DragEvent) => {\n e.preventDefault();\n if (!this.isDragging || this.draggedField === field) return;\n\n const rect = row.getBoundingClientRect();\n const midY = rect.top + rect.height / 2;\n\n this.dropIndex = e.clientY < midY ? index : index + 1;\n\n // Clear other row highlights\n columnList.querySelectorAll('.tbw-visibility-row').forEach((r) => {\n if (r !== row) r.classList.remove('drop-target', 'drop-before', 'drop-after');\n });\n\n row.classList.add('drop-target');\n row.classList.toggle('drop-before', e.clientY < midY);\n row.classList.toggle('drop-after', e.clientY >= midY);\n });\n\n row.addEventListener('dragleave', () => {\n row.classList.remove('drop-target', 'drop-before', 'drop-after');\n });\n\n row.addEventListener('drop', (e: DragEvent) => {\n e.preventDefault();\n const draggedField = this.draggedField;\n const draggedIndex = this.draggedIndex;\n const dropIndex = this.dropIndex;\n\n if (!this.isDragging || draggedField === null || draggedIndex === null || dropIndex === null) {\n return;\n }\n\n // Calculate the effective target index\n const effectiveToIndex = dropIndex > draggedIndex ? dropIndex - 1 : dropIndex;\n\n if (effectiveToIndex !== draggedIndex) {\n // Emit a request event - other plugins (like ReorderPlugin) can listen and handle\n const detail: ColumnReorderRequestDetail = {\n field: draggedField,\n fromIndex: draggedIndex,\n toIndex: effectiveToIndex,\n };\n this.emit<ColumnReorderRequestDetail>('column-reorder-request', detail);\n\n // Rebuild the panel after reorder (deferred to allow re-render)\n setTimeout(() => {\n this.rebuildToggles(columnList);\n }, 0);\n }\n });\n }\n // #endregion\n\n // #region Styles\n\n override readonly styles = styles;\n // #endregion\n}\n"],"names":["formatCellValue","value","field","row","config","str","delimiter","newline","buildClipboardText","params","rows","columns","selectedIndices","visibleColumns","c","lines","headerCells","header","sortedIndices","a","b","idx","cells","col","copyToClipboard","text","textarea","success","parseClipboardText","normalizedText","currentRow","currentCell","inQuotes","i","char","readFromClipboard","ClipboardPlugin","BaseGridPlugin","event","isCopy","isPaste","#handleCopy","#handlePaste","target","selectionPlugin","#getSelectionPlugin","selectedRows","hasRowSelection","ranges","hasRangeSelection","hasCellSelection","rowCount","columnCount","range","result","#buildRangeText","cell","#buildCellText","#buildSingleCellText","parsed","grid","plugin","rowIndex","colIndex","rowData","column","formattedValue","startRow","startCol","endRow","endCol","minRow","maxRow","minCol","maxCol","rangeColumns","r","rowIndexStr","indices","DEFAULT_COLUMN_WIDTH","parseColumnWidth","width","numeric","getColumnWidths","computeColumnOffsets","offsets","offset","computeTotalWidth","sum","getVisibleColumnRange","scrollLeft","viewportWidth","columnOffsets","columnWidths","overscan","binarySearchFirstVisible","rightEdge","low","high","mid","shouldVirtualize","threshold","autoEnable","ColumnVirtualizationPlugin","isVirtualized","viewport","shadowRoot","leftPadding","headerRow","bodyRows","rowsContainer","columnIndex","gridEl","buildMenuItems","items","item","isItemDisabled","createMenuElement","onAction","submenuArrow","DEFAULT_GRID_ICONS","menu","separator","menuItem","disabled","icon","label","shortcut","arrow","subMenuItems","subMenu","e","positionMenu","x","y","menuRect","viewportHeight","left","top","globalClickHandler","globalKeydownHandler","globalStyleSheet","globalHandlerRefCount","defaultItems","ContextMenuPlugin","contextMenuStyles","container","fullParams","formatCsvValue","quote","buildCsv","options","bom","processed","downloadBlob","blob","fileName","url","link","downloadCsv","content","escapeXml","buildExcelXml","xml","type","displayValue","downloadExcel","finalName","ExportPlugin","format","colSet","selectionState","jsonData","obj","computeVirtualWindow","totalRows","scrollTop","rowHeight","visibleRows","start","end","shouldBypassVirtualization","matchesFilter","filter","caseSensitive","rawValue","stringValue","compareValue","filterValue","filterRows","filters","f","computeFilterCacheKey","getUniqueValues","values","FilteringPlugin","filterList","newCacheKey","hasFilter","filterBtn","style","filterPanelStyles","buttonEl","panel","uniqueValues","excludedSet","currentSearchText","excluded","operator","valueTo","usedCustomRenderer","rect","panelRect","excludedValues","searchContainer","searchInput","actionsRow","selectAllLabel","selectAllCheckbox","selectAllText","updateSelectAllState","checkState","allChecked","v","noneChecked","newState","key","renderVisibleItems","valuesContainer","spacer","contentContainer","filteredValues","createItem","index","strValue","checkbox","totalItems","window","renderValues","filterText","lowerFilter","noMatch","debounceTimer","buttonRow","applyBtn","isChecked","original","clearBtn","handleResult","filterModel","state","styles","computeColumnGroups","explicitMap","groupsOrdered","pushImplicit","startIdx","cols","prev","run","runStart","g","id","group","applyGroupedHeaderCellClasses","headerRowEl","groups","fieldToGroup","gid","last","buildGroupHeaderRow","groupRow","startIndex","isImplicit","hasColumnGroups","GroupingColumnsPlugin","columnGroups","processedColumns","groupInfo","existingGroupRow","groupId","buildGroupedRowModel","expanded","groupOn","root","path","parent","rawVal","depthIdx","seg","composite","node","flat","visit","isExpanded","toggleGroupExpansion","expandedKeys","newSet","expandAllGroups","keys","collapseAllGroups","getGroupRowCount","GroupingRowsPlugin","mode","host","grouped","currentVisibleKeys","rowEl","_rowIndex","toggleExpand","handleToggle","body","animClass","btn","labelText","count","aggregators","groupRows","gridTemplate","colIdx","firstColAgg","aggResult","runAggregator","aggRef","newKeys","fn","toggleDetailRow","expandedRows","newExpanded","expandDetailRow","collapseDetailRow","isDetailExpanded","createDetailElement","renderer","detailRow","detailCell","MasterDetailPlugin","detailEl","gridWithAdapter","adapterRenderer","animation","showExpandColumn","expandOnRowClick","collapseOnClickOutside","heightAttr","configUpdates","templateHTML","evaluated","evalTemplateString","sanitizeHTML","durationStr","onComplete","cleanup","firstCol","originalRenderer","wrappedRenderer","renderCtx","toggle","rendered","#syncDetailRows","visibleRowMap","dataRows","firstCell","existingDetails","forIndex","isStillExpanded","isRowVisible","existingDetail","totalHeight","configHeight","beforeRowIndex","expandedIndices","minStart","cumulativeExtraHeight","actualRowTop","detailHeight","actualDetailBottom","currentRenderer","applySorts","sorts","sort","comparator","defaultComparator","aVal","bVal","toggleSort","current","shiftKey","maxColumns","existing","s","getSortIndex","sortModel","getSortDirection","MultiSortPlugin","showIndex","sortIndex","sortDir","indicator","badge","model","existingIndex","newEntry","getLeftStickyColumns","getRightStickyColumns","hasStickyColumns","applyStickyOffsets","fieldToIndex","el","right","clearStickyOffsets","PinnedColumnsPlugin","query","PLUGIN_QUERIES","sticky","metaSticky","focusedCell","stickyLeftCells","stickyRightCells","skipScroll","isAggregatorConfig","def","createInfoBarElement","context","pinnedRows","center","filteredCount","selectedCount","panelEl","renderCustomPanel","createAggregationContainer","position","renderAggregationRows","rowConfig","formatter","aggDef","aggFn","getAggregator","staticVal","buildContext","filterState","PinnedRowsPlugin","aggregationRows","topRows","bottomRows","hasInfoContent","hasBottomInfoBar","needsFooter","newInfoBar","p","getPivotAggregator","getValueAggregator","validatePivotConfig","errors","createValueKey","columnValues","valueField","buildPivot","rowGroupFields","columnGroupFields","valueFields","columnKeys","getUniqueColumnKeys","pivotRows","buildHierarchicalPivotRows","totals","calculateTotals","grandTotal","columnFields","groupByField","depth","parentKey","aggregateValues","total","calculateRowTotal","currentField","remainingFields","hasChildren","groupValue","rowKey","children","colKey","vf","nums","aggregator","aggregatedResult","valueKey","val","sumRows","flattenPivotRows","defaultExpanded","flatten","child","getAllGroupKeys","collectKeys","AGG_FUNCS","renderPivotPanel","isActive","callbacks","controller","ctx","wrapper","createSection","createOptionsPanel","createFieldZone","createValuesZone","createAvailableFieldsZone","title","contentFactory","section","zoneType","signal","zone","currentFields","placeholder","createFieldChip","chip","fieldInfo","removeBtn","currentValues","createValueChip","labelWrapper","aggSelect","aggFunc","option","allFields","usedFields","availableFields","empty","createCheckbox","checked","onChange","input","span","renderPivotGroupRow","indent","renderPivotLeafRow","renderPivotGrandTotalRow","PivotPlugin","allKeys","indentWidth","flatRows","pr","pivotColumns","rowGroupHeaders","valueHeader","pivotRow","iconKey","grandTotalRow","fields","enabled","targetZone","fieldIndex","canMoveColumn","meta","moveColumn","fromIndex","toIndex","removed","ReorderPlugin","detail","headerEl","pluginAllows","orderIndex","h","midX","draggedField","draggedIndex","dropIndex","effectiveToIndex","currentOrder","newOrder","focusCol","targetColumn","ensureCellVisible","order","originalOrder","positions","oldPositions","deltas","oldLeft","deltaX","duration","applyChange","movedFields","newLeft","normalizeRange","toPublicRange","normalized","toPublicRanges","isCellInRange","isCellInAnyRange","getCellsInRange","getAllCellsInRanges","cellMap","createRangeFromAnchor","anchor","buildSelectionEvent","colCount","SelectionPlugin","originalEvent","#buildEvent","ctrlKey","newRange","isNavKey","isTabKey","shouldExtend","allRange","_event","#applySelectionClasses","allRows","clearCellFocus","getRowIndexFromCell","currentCol","getBlockNumber","blockSize","getBlockRange","blockNumber","getRequiredBlocks","startBlock","endBlock","blocks","loadBlock","dataSource","getRowFromCache","loadedBlocks","block","indexInBlock","SCROLL_DEBOUNCE_MS","ServerSidePlugin","gridRef","requiredBlocks","blockNum","cached","generateRowKey","expandAll","childrenField","childKeys","k","collapseAll","getPathToKey","targetKey","childPath","expandToKey","existingExpanded","detectTreeStructure","inferChildrenField","commonArrayFields","TreePlugin","data","currentKeys","dir","getConfig","setIcon","resolveIcon","wrapped","showExpandIcons","flatRow","pushAction","action","maxSize","undoStack","undo","redo","redoStack","canUndo","canRedo","clearHistory","createEditAction","oldValue","newValue","UndoRedoPlugin","isUndo","isRedo","VisibilityPlugin","visible","columnList","showAllBtn","reorderEnabled","allColumns","handle","midY"],"mappings":";;AAoCO,SAASA,GAAgBC,GAAgBC,GAAeC,GAAcC,GAAiC;AAC5G,MAAIA,EAAO;AACT,WAAOA,EAAO,YAAYH,GAAOC,GAAOC,CAAG;AAG7C,MAAIF,KAAS,KAAM,QAAO;AAC1B,MAAIA,aAAiB,KAAM,QAAOA,EAAM,YAAA;AACxC,MAAI,OAAOA,KAAU,SAAU,QAAO,KAAK,UAAUA,CAAK;AAE1D,QAAMI,IAAM,OAAOJ,CAAK,GAClBK,IAAYF,EAAO,aAAa,KAChCG,IAAUH,EAAO,WAAW;AAAA;AAGlC,SAAIA,EAAO,gBAAgBC,EAAI,SAASC,CAAS,KAAKD,EAAI,SAASE,CAAO,KAAKF,EAAI,SAAS,GAAG,IACtF,IAAIA,EAAI,QAAQ,MAAM,IAAI,CAAC,MAG7BA;AACT;AAQO,SAASG,EAAmBC,GAA4B;AAC7D,QAAM,EAAE,MAAAC,GAAM,SAAAC,GAAS,iBAAAC,GAAiB,QAAAR,MAAWK,GAC7CH,IAAYF,EAAO,aAAa,KAChCG,IAAUH,EAAO,WAAW;AAAA,GAG5BS,IAAiBF,EAAQ,OAAO,CAACG,MAAM,CAACA,EAAE,UAAU,CAACA,EAAE,MAAM,WAAW,IAAI,CAAC,GAE7EC,IAAkB,CAAA;AAGxB,MAAIX,EAAO,gBAAgB;AACzB,UAAMY,IAAcH,EAAe,IAAI,CAACC,MAAM;AAC5C,YAAMG,IAASH,EAAE,UAAUA,EAAE;AAE7B,aAAIG,EAAO,SAASX,CAAS,KAAKW,EAAO,SAASV,CAAO,KAAKU,EAAO,SAAS,GAAG,IACxE,IAAIA,EAAO,QAAQ,MAAM,IAAI,CAAC,MAEhCA;AAAA,IACT,CAAC;AACD,IAAAF,EAAM,KAAKC,EAAY,KAAKV,CAAS,CAAC;AAAA,EACxC;AAIA,QAAMY,IAAgB,CAAC,GADPN,aAA2B,MAAM,CAAC,GAAGA,CAAe,IAAIA,CACvC,EAAE,KAAK,CAACO,GAAGC,MAAMD,IAAIC,CAAC;AAGvD,aAAWC,KAAOH,GAAe;AAC/B,UAAMf,IAAMO,EAAKW,CAAG;AACpB,QAAI,CAAClB,EAAK;AAEV,UAAMmB,IAAQT,EAAe;AAAA,MAAI,CAACU,MAChCvB,GAAiBG,EAAgCoB,EAAI,KAAK,GAAGA,EAAI,OAAOpB,GAAKC,CAAM;AAAA,IAAA;AAErF,IAAAW,EAAM,KAAKO,EAAM,KAAKhB,CAAS,CAAC;AAAA,EAClC;AAEA,SAAOS,EAAM,KAAKR,CAAO;AAC3B;AAWA,eAAsBiB,EAAgBC,GAAgC;AACpE,MAAI;AACF,iBAAM,UAAU,UAAU,UAAUA,CAAI,GACjC;AAAA,EACT,QAAQ;AAEN,UAAMC,IAAW,SAAS,cAAc,UAAU;AAClD,IAAAA,EAAS,QAAQD,GACjBC,EAAS,MAAM,WAAW,SAC1BA,EAAS,MAAM,UAAU,KACzBA,EAAS,MAAM,gBAAgB,QAC/B,SAAS,KAAK,YAAYA,CAAQ,GAClCA,EAAS,OAAA;AACT,UAAMC,IAAU,SAAS,YAAY,MAAM;AAC3C,oBAAS,KAAK,YAAYD,CAAQ,GAC3BC;AAAA,EACT;AACF;AC7GO,SAASC,GAAmBH,GAAcrB,GAAqC;AACpF,QAAME,IAAYF,EAAO,aAAa,KAChCG,IAAUH,EAAO,WAAW;AAAA,GAG5ByB,IAAiBJ,EAAK,QAAQ,SAAS;AAAA,CAAI,EAAE,QAAQ,OAAO;AAAA,CAAI,GAGhEf,IAAmB,CAAA;AACzB,MAAIoB,IAAuB,CAAA,GACvBC,IAAc,IACdC,IAAW;AAEf,WAASC,IAAI,GAAGA,IAAIJ,EAAe,QAAQI,KAAK;AAC9C,UAAMC,IAAOL,EAAeI,CAAC;AAE7B,IAAIC,MAAS,OAAO,CAACF,IAEnBA,IAAW,KACFE,MAAS,OAAOF,IAErBH,EAAeI,IAAI,CAAC,MAAM,OAC5BF,KAAe,KACfE,OAGAD,IAAW,KAEJE,MAAS5B,KAAa,CAAC0B,KAEhCF,EAAW,KAAKC,CAAW,GAC3BA,IAAc,MACLG,MAAS3B,KAAW,CAACyB,KAE9BF,EAAW,KAAKC,CAAW,GAC3BA,IAAc,KAEVD,EAAW,SAAS,KAAKA,EAAW,KAAK,CAAChB,MAAMA,EAAE,KAAA,MAAW,EAAE,MACjEJ,EAAK,KAAKoB,CAAU,GAEtBA,IAAa,CAAA,KAEbC,KAAeG;AAAA,EAEnB;AAGA,SAAAJ,EAAW,KAAKC,CAAW,IACvBD,EAAW,SAAS,KAAKA,EAAW,KAAK,CAAChB,MAAMA,EAAE,KAAA,MAAW,EAAE,MACjEJ,EAAK,KAAKoB,CAAU,GAGfpB;AACT;AAUA,eAAsByB,KAAqC;AACzD,MAAI;AACF,WAAO,MAAM,UAAU,UAAU,SAAA;AAAA,EACnC,QAAQ;AAEN,WAAO;AAAA,EACT;AACF;AC/DO,MAAMC,WAAwBC,EAAgC;AAAA,EAC1D,OAAO;AAAA,EACE,UAAU;AAAA,EAE5B,IAAuB,gBAA0C;AAC/D,WAAO;AAAA,MACL,gBAAgB;AAAA,MAChB,WAAW;AAAA,MACX,SAAS;AAAA;AAAA,MACT,cAAc;AAAA,IAAA;AAAA,EAElB;AAAA;AAAA;AAAA,EAIQ,aAAyD;AAAA;AAAA;AAAA,EAKxD,SAAe;AACtB,SAAK,aAAa;AAAA,EACpB;AAAA;AAAA;AAAA,EAKS,UAAUC,GAA+B;AAChD,UAAMC,KAAUD,EAAM,WAAWA,EAAM,YAAYA,EAAM,QAAQ,KAC3DE,KAAWF,EAAM,WAAWA,EAAM,YAAYA,EAAM,QAAQ;AAElE,WAAIC,KACF,KAAKE,GAAYH,EAAM,MAAqB,GACrC,MAGLE,KACF,KAAKE,GAAA,GACE,MAGF;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQAD,GAAYE,GAA2B;AAGrC,UAAMC,IAAkB,KAAKC,GAAA,GAGvBC,IAAeF,GAAiB,gBAAA,KAAqB,CAAA,GACrDG,IAAkBD,EAAa,SAAS,GACxCE,IAASJ,GAAiB,UAAA,KAAe,CAAA,GACzCK,IAAoBD,EAAO,SAAS,GACpCE,IAAmBN,GAAiB,gBAAA,KAAqB;AAE/D,QAAInB,GACA0B,GACAC;AAEJ,QAAIL,KAAmBH;AAErB,MAAAnB,IAAOjB,EAAmB;AAAA,QACxB,MAAM,KAAK;AAAA,QACX,SAAS,CAAC,GAAG,KAAK,OAAO;AAAA,QACzB,iBAAiBsC;AAAA,QACjB,QAAQ,KAAK;AAAA,MAAA,CACd,GACDK,IAAWL,EAAa,QACxBM,IAAc,KAAK,QAAQ,OAAO,CAACtC,MAAM,CAACA,EAAE,UAAU,CAACA,EAAE,MAAM,WAAW,IAAI,CAAC,EAAE;AAAA,aACxEmC,KAAqBL,GAAiB;AAE/C,YAAMS,IAAQL,EAAOA,EAAO,SAAS,CAAC,GAChCM,IAAS,KAAKC,GAAgB;AAAA,QAClC,UAAUF,EAAM,KAAK;AAAA,QACrB,UAAUA,EAAM,KAAK;AAAA,QACrB,QAAQA,EAAM,GAAG;AAAA,QACjB,QAAQA,EAAM,GAAG;AAAA,MAAA,CAClB;AACD,MAAA5B,IAAO6B,EAAO,MACdH,IAAWG,EAAO,UAClBF,IAAcE,EAAO;AAAA,IACvB,WAAWJ,KAAoBN,GAAiB;AAE9C,YAAMY,IAAOZ,EAAgB,gBAAA,GACvBU,IAAS,KAAKG,GAAeD,EAAK,KAAKA,EAAK,GAAG;AACrD,UAAI,CAACF,EAAQ;AACb,MAAA7B,IAAO6B,EAAO,MACdH,IAAW,GACXC,IAAc;AAAA,IAChB,OAAO;AAEL,YAAME,IAAS,KAAKI,GAAqBf,CAAM;AAC/C,UAAI,CAACW,EAAQ;AACb,MAAA7B,IAAO6B,EAAO,MACdH,IAAW,GACXC,IAAc;AAAA,IAChB;AAEA,IAAA5B,EAAgBC,CAAI,EAAE,KAAK,MAAM;AAC/B,WAAK,aAAa,EAAE,MAAAA,GAAM,WAAW,KAAK,MAAI,GAC9C,KAAK,KAAiB,QAAQ,EAAE,MAAAA,GAAM,UAAA0B,GAAU,aAAAC,GAAa;AAAA,IAC/D,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKAV,KAAqB;AACnB,IAAAP,GAAA,EAAoB,KAAK,CAACV,MAAS;AACjC,UAAI,CAACA,EAAM;AACX,YAAMkC,IAAS/B,GAAmBH,GAAM,KAAK,MAAM;AACnD,WAAK,KAAkB,SAAS,EAAE,MAAMkC,GAAQ,MAAAlC,GAAM;AAAA,IACxD,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKAoB,KAA4D;AAE1D,QAAI;AAGF,YAAMe,IAAO,KAAK;AAClB,UAAIA,GAAM;AACR,mBAAWC,KAAUD,EAAK;AACxB,cAAIC,EAAO,SAAS;AAClB,mBAAOA;AAAA;AAAA,IAIf,QAAQ;AAAA,IAER;AAAA,EAEF;AAAA;AAAA;AAAA;AAAA,EAKAJ,GAAeK,GAAkBC,GAA2C;AAC1E,UAAMC,IAAU,KAAK,KAAKF,CAAQ;AAClC,QAAI,CAACE,EAAS,QAAO;AAErB,UAAMC,IAAS,KAAK,QAAQF,CAAQ;AACpC,QAAI,CAACE,EAAQ,QAAO;AAEpB,UAAMhE,IAAQ+D,EAAQC,EAAO,KAAK,GAC5BhD,IAASgD,EAAO,UAAUA,EAAO;AAEvC,QAAIxC;AACJ,QAAI,KAAK,OAAO,gBAAgB;AAC9B,YAAMyC,IAAiBjE,KAAS,OAAO,KAAK,OAAOA,CAAK;AACxD,MAAAwB,IAAO,GAAGR,CAAM,KAAKiD,CAAc;AAAA,IACrC;AACE,MAAAzC,IAAOxB,KAAS,OAAO,KAAK,OAAOA,CAAK;AAG1C,WAAO,EAAE,MAAAwB,EAAA;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA8B,GAAgBF,GAId;AACA,UAAM,EAAE,UAAAc,GAAU,UAAAC,GAAU,QAAAC,GAAQ,QAAAC,MAAWjB,GACzCkB,IAAS,KAAK,IAAIJ,GAAUE,CAAM,GAClCG,IAAS,KAAK,IAAIL,GAAUE,CAAM,GAClCI,IAAS,KAAK,IAAIL,GAAUE,CAAM,GAClCI,IAAS,KAAK,IAAIN,GAAUE,CAAM,GAElChE,IAAY,KAAK,OAAO,aAAa,KACrCC,IAAU,KAAK,OAAO,WAAW;AAAA,GACjCQ,IAAkB,CAAA,GAGlB4D,IAAe,KAAK,QAAQ,MAAMF,GAAQC,IAAS,CAAC;AAG1D,QAAI,KAAK,OAAO,gBAAgB;AAC9B,YAAM1D,IAAc2D,EAAa,IAAI,CAAC7D,MAAMA,EAAE,UAAUA,EAAE,KAAK;AAC/D,MAAAC,EAAM,KAAKC,EAAY,KAAKV,CAAS,CAAC;AAAA,IACxC;AAGA,aAASsE,IAAIL,GAAQK,KAAKJ,GAAQI,KAAK;AACrC,YAAMZ,IAAU,KAAK,KAAKY,CAAC;AAC3B,UAAI,CAACZ,EAAS;AAEd,YAAM1C,IAAQqD,EAAa,IAAI,CAACpD,MAAQ;AACtC,cAAMtB,IAAQ+D,EAAQzC,EAAI,KAAK;AAC/B,eAAItB,KAAS,OAAa,KACtBA,aAAiB,OAAaA,EAAM,YAAA,IACjC,OAAOA,CAAK;AAAA,MACrB,CAAC;AACD,MAAAc,EAAM,KAAKO,EAAM,KAAKhB,CAAS,CAAC;AAAA,IAClC;AAEA,WAAO;AAAA,MACL,MAAMS,EAAM,KAAKR,CAAO;AAAA,MACxB,UAAUiE,IAASD,IAAS;AAAA,MAC5B,aAAaG,IAASD,IAAS;AAAA,IAAA;AAAA,EAEnC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMAf,GAAqBf,GAA6E;AAEhG,UAAMa,IAAOb,EAAO,QAAQ,oBAAoB;AAChD,QAAI,CAACa,EAAM,QAAO;AAElB,UAAMtD,IAAQsD,EAAK,QAAQ;AAC3B,QAAI,CAACtD,EAAO,QAAO;AAGnB,UAAM2E,IAAcrB,EAAK,QAAQ;AACjC,QAAI,CAACqB,EAAa,QAAO;AAEzB,UAAMf,IAAW,SAASe,GAAa,EAAE;AACzC,QAAI,MAAMf,CAAQ,EAAG,QAAO;AAE5B,UAAME,IAAU,KAAK,KAAKF,CAAQ;AAClC,QAAI,CAACE,EAAS,QAAO;AAErB,UAAM/D,IAAQ+D,EAAQ9D,CAAK,GAErBe,IADS,KAAK,QAAQ,KAAK,CAACH,MAAMA,EAAE,UAAUZ,CAAK,GAClC,UAAUA;AAGjC,QAAIuB;AACJ,QAAI,KAAK,OAAO,gBAAgB;AAE9B,YAAMyC,IAAiBjE,KAAS,OAAO,KAAK,OAAOA,CAAK;AACxD,MAAAwB,IAAO,GAAGR,CAAM,KAAKiD,CAAc;AAAA,IACrC;AAEE,MAAAzC,IAAOxB,KAAS,OAAO,KAAK,OAAOA,CAAK;AAG1C,WAAO,EAAE,MAAAwB,GAAM,OAAAvB,GAAO,OAAAD,EAAA;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,OAAwB;AAE5B,UAAM6E,IADkB,KAAKjC,GAAA,GACI,gBAAA,KAAqB,CAAA,GAEhDpB,IAAOjB,EAAmB;AAAA,MAC9B,MAAM,KAAK;AAAA,MACX,SAAS,CAAC,GAAG,KAAK,OAAO;AAAA,MACzB,iBAAiBsE;AAAA,MACjB,QAAQ,KAAK;AAAA,IAAA,CACd;AAED,iBAAMtD,EAAgBC,CAAI,GAC1B,KAAK,aAAa,EAAE,MAAAA,GAAM,WAAW,KAAK,MAAI,GACvCA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,SAASqD,GAAoC;AACjD,UAAMrD,IAAOjB,EAAmB;AAAA,MAC9B,MAAM,KAAK;AAAA,MACX,SAAS,CAAC,GAAG,KAAK,OAAO;AAAA,MACzB,iBAAiBsE;AAAA,MACjB,QAAQ,KAAK;AAAA,IAAA,CACd;AAED,iBAAMtD,EAAgBC,CAAI,GAC1B,KAAK,aAAa,EAAE,MAAAA,GAAM,WAAW,KAAK,MAAI,GACvCA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,QAAoC;AACxC,UAAMA,IAAO,MAAMU,GAAA;AACnB,WAAKV,IACEG,GAAmBH,GAAM,KAAK,MAAM,IADzB;AAAA,EAEpB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAA4D;AAC1D,WAAO,KAAK;AAAA,EACd;AAAA;AAEF;AC7UA,MAAMsD,KAAuB;AAStB,SAASC,GAAiBC,GAA4C;AAC3E,MAA2BA,KAAU;AACnC,WAAOF;AAGT,MAAI,OAAOE,KAAU;AACnB,WAAOA;AAIT,QAAMC,IAAU,WAAWD,CAAK;AAChC,SAAK,MAAMC,CAAO,IAIXH,KAHEG;AAIX;AAQO,SAASC,GAAgBxE,GAA4C;AAC1E,SAAOA,EAAQ,IAAI,CAACY,MAAQyD,GAAiBzD,EAAI,KAAK,CAAC;AACzD;AAQO,SAAS6D,GAAqBzE,GAA4C;AAC/E,QAAM0E,IAAoB,CAAA;AAC1B,MAAIC,IAAS;AAEb,aAAW/D,KAAOZ;AAChB,IAAA0E,EAAQ,KAAKC,CAAM,GACnBA,KAAUN,GAAiBzD,EAAI,KAAK;AAGtC,SAAO8D;AACT;AAQO,SAASE,GAAkB5E,GAA0C;AAC1E,SAAOA,EAAQ,OAAO,CAAC6E,GAAKjE,MAAQiE,IAAMR,GAAiBzD,EAAI,KAAK,GAAG,CAAC;AAC1E;AAaO,SAASkE,GACdC,GACAC,GACAC,GACAC,GACAC,GAC8B;AAC9B,QAAM1C,IAAcwC,EAAc;AAElC,MAAIxC,MAAgB;AAClB,WAAO,EAAE,UAAU,GAAG,QAAQ,GAAG,gBAAgB,GAAC;AAIpD,MAAIgB,IAAW2B,GAAyBL,GAAYE,GAAeC,CAAY;AAC/E,EAAAzB,IAAW,KAAK,IAAI,GAAGA,IAAW0B,CAAQ;AAG1C,QAAME,IAAYN,IAAaC;AAC/B,MAAIrB,IAASF;AAEb,WAASnC,IAAImC,GAAUnC,IAAImB,GAAanB,KAAK;AAC3C,QAAI2D,EAAc3D,CAAC,KAAK+D,GAAW;AACjC,MAAA1B,IAASrC,IAAI;AACb;AAAA,IACF;AACA,IAAAqC,IAASrC;AAAA,EACX;AAGA,EAAAqC,IAAS,KAAK,IAAIlB,IAAc,GAAGkB,IAASwB,CAAQ;AAGpD,QAAMjF,IAA2B,CAAA;AACjC,WAASoB,IAAImC,GAAUnC,KAAKqC,GAAQrC;AAClC,IAAApB,EAAe,KAAKoB,CAAC;AAGvB,SAAO,EAAE,UAAAmC,GAAU,QAAAE,GAAQ,gBAAAzD,EAAA;AAC7B;AAUA,SAASkF,GAAyBL,GAAoBE,GAAyBC,GAAgC;AAC7G,MAAII,IAAM,GACNC,IAAON,EAAc,SAAS;AAElC,SAAOK,IAAMC,KAAM;AACjB,UAAMC,IAAM,KAAK,OAAOF,IAAMC,KAAQ,CAAC;AAGvC,IAFiBN,EAAcO,CAAG,IAAIN,EAAaM,CAAG,KAEtCT,IACdO,IAAME,IAAM,IAEZD,IAAOC;AAAA,EAEX;AAEA,SAAOF;AACT;AAUO,SAASG,GAAiBhD,GAAqBiD,GAAmBC,GAA8B;AACrG,SAAKA,IACElD,IAAciD,IADG;AAE1B;AC1IO,MAAME,WAAmClE,EAA2C;AAAA,EAChF,OAAO;AAAA,EACE,UAAU;AAAA,EAE5B,IAAuB,gBAAqD;AAC1E,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,WAAW;AAAA,MACX,UAAU;AAAA,IAAA;AAAA,EAEd;AAAA;AAAA,EAGQ,gBAAgB;AAAA,EAChB,WAAW;AAAA,EACX,SAAS;AAAA,EACT,aAAa;AAAA,EACb,aAAa;AAAA,EACb,eAAyB,CAAA;AAAA,EACzB,gBAA0B,CAAA;AAAA;AAAA;AAAA,EAKzB,OAAOuB,GAAiE;AAC/E,UAAM,OAAOA,CAAI;AAGjB,UAAMjD,IAAU,KAAK;AACrB,SAAK,eAAewE,GAAgBxE,CAAO,GAC3C,KAAK,gBAAgByE,GAAqBzE,CAAO,GACjD,KAAK,aAAa4E,GAAkB5E,CAAO,GAC3C,KAAK,SAASA,EAAQ,SAAS;AAAA,EACjC;AAAA,EAES,SAAe;AACtB,SAAK,eAAe,CAAA,GACpB,KAAK,gBAAgB,CAAA,GACrB,KAAK,gBAAgB,IACrB,KAAK,WAAW,GAChB,KAAK,SAAS,GACd,KAAK,aAAa,GAClB,KAAK,aAAa;AAAA,EACpB;AAAA;AAAA;AAAA,EAKS,eAAeA,GAAkD;AACxE,UAAM6F,IAAgBJ,GAAiBzF,EAAQ,QAAQ,KAAK,OAAO,aAAa,IAAI,KAAK,OAAO,cAAc,EAAI;AAQlH,QALA,KAAK,gBAAgB6F,KAAiB,IACtC,KAAK,eAAerB,GAAgBxE,CAAO,GAC3C,KAAK,gBAAgByE,GAAqBzE,CAAO,GACjD,KAAK,aAAa4E,GAAkB5E,CAAO,GAEvC,CAAC6F;AACH,kBAAK,WAAW,GAChB,KAAK,SAAS7F,EAAQ,SAAS,GACxB,CAAC,GAAGA,CAAO;AAIpB,UAAMgF,IAAiB,KAAK,KAAgC,eAAe,KACrEc,IAAWhB;AAAA,MACf,KAAK;AAAA,MACLE;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK,OAAO,YAAY;AAAA,IAAA;AAG1B,gBAAK,WAAWc,EAAS,UACzB,KAAK,SAASA,EAAS,QAGhBA,EAAS,eAAe,IAAI,CAAC,MAAM9F,EAAQ,CAAC,CAAC;AAAA,EACtD;AAAA,EAES,cAAoB;AAC3B,QAAI,CAAC,KAAK,cAAe;AAEzB,UAAM+F,IAAa,KAAK;AACxB,QAAI,CAACA,EAAY;AAGjB,UAAMC,IAAc,KAAK,cAAc,KAAK,QAAQ,KAAK,GAEnDC,IAAYF,EAAW,cAAc,aAAa,GAClDG,IAAWH,EAAW,iBAAiB,gBAAgB;AAE7D,IAAIE,MACDA,EAA0B,MAAM,cAAc,GAAGD,CAAW,OAG/DE,EAAS,QAAQ,CAAC1G,MAAQ;AACvB,MAAAA,EAAoB,MAAM,cAAc,GAAGwG,CAAW;AAAA,IACzD,CAAC;AAGD,UAAMG,IAAgBJ,EAAW,cAAc,sBAAsB;AACrE,IAAII,MACDA,EAA8B,MAAM,QAAQ,GAAG,KAAK,UAAU;AAAA,EAEnE;AAAA,EAES,SAASxE,GAA0B;AAK1C,IAJI,CAAC,KAAK,iBAGU,KAAK,IAAIA,EAAM,aAAa,KAAK,UAAU,IAC7C,MAGlB,KAAK,aAAaA,EAAM,YAGxB,KAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,mBAA4B;AAC1B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,wBAAwD;AACtD,WAAO,EAAE,OAAO,KAAK,UAAU,KAAK,KAAK,OAAA;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,eAAeyE,GAA2B;AACxC,UAAMzB,IAAS,KAAK,cAAcyB,CAAW,KAAK,GAC5CC,IAAS,KAAK;AAEpB,IAAAA,EAAO,aAAa1B;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAgByB,GAA6B;AAC3C,WAAO,KAAK,cAAcA,CAAW,KAAK;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAwB;AACtB,WAAO,KAAK;AAAA,EACd;AAAA;AAEF;;AC7KO,SAASE,EACdC,GACAzG,GACmB;AAGnB,UAFkB,OAAOyG,KAAU,aAAaA,EAAMzG,CAAM,IAAIyG,GAE/C,OAAO,CAACC,MACnB,EAAAA,EAAK,WAAW,MAChB,OAAOA,EAAK,UAAW,cAAcA,EAAK,OAAO1G,CAAM,EAE5D;AACH;AASO,SAAS2G,GAAeD,GAAuB1G,GAAoC;AACxF,SAAI0G,EAAK,aAAa,KAAa,KAC/B,OAAOA,EAAK,YAAa,aAAmBA,EAAK,SAAS1G,CAAM,IAC7D;AACT;AAWO,SAAS4G,EACdH,GACAzG,GACA6G,GACAC,IAA0BC,GAAmB,cAChC;AACb,QAAMC,IAAO,SAAS,cAAc,KAAK;AACzC,EAAAA,EAAK,YAAY,oBACjBA,EAAK,aAAa,QAAQ,MAAM;AAEhC,aAAWN,KAAQD,GAAO;AACxB,QAAIC,EAAK,WAAW;AAClB,YAAMO,IAAY,SAAS,cAAc,KAAK;AAC9C,MAAAA,EAAU,YAAY,8BACtBA,EAAU,aAAa,QAAQ,WAAW,GAC1CD,EAAK,YAAYC,CAAS;AAC1B;AAAA,IACF;AAEA,UAAMC,IAAW,SAAS,cAAc,KAAK;AAC7C,IAAAA,EAAS,YAAY,yBACjBR,EAAK,YAAUQ,EAAS,UAAU,IAAIR,EAAK,QAAQ,GACvDQ,EAAS,aAAa,QAAQ,UAAU,GACxCA,EAAS,aAAa,WAAWR,EAAK,EAAE;AAExC,UAAMS,IAAWR,GAAeD,GAAM1G,CAAM;AAM5C,QALImH,MACFD,EAAS,UAAU,IAAI,UAAU,GACjCA,EAAS,aAAa,iBAAiB,MAAM,IAG3CR,EAAK,MAAM;AACb,YAAMU,IAAO,SAAS,cAAc,MAAM;AAC1C,MAAAA,EAAK,YAAY,yBACjBA,EAAK,YAAYV,EAAK,MACtBQ,EAAS,YAAYE,CAAI;AAAA,IAC3B;AAEA,UAAMC,IAAQ,SAAS,cAAc,MAAM;AAK3C,QAJAA,EAAM,YAAY,0BAClBA,EAAM,cAAcX,EAAK,MACzBQ,EAAS,YAAYG,CAAK,GAEtBX,EAAK,UAAU;AACjB,YAAMY,IAAW,SAAS,cAAc,MAAM;AAC9C,MAAAA,EAAS,YAAY,6BACrBA,EAAS,cAAcZ,EAAK,UAC5BQ,EAAS,YAAYI,CAAQ;AAAA,IAC/B;AAEA,QAAIZ,EAAK,SAAS,QAAQ;AACxB,YAAMa,IAAQ,SAAS,cAAc,MAAM;AAC3C,MAAAA,EAAM,YAAY,0BAEd,OAAOT,KAAiB,WAC1BS,EAAM,YAAYT,IACTA,aAAwB,eACjCS,EAAM,YAAYT,EAAa,UAAU,EAAI,CAAC,GAEhDI,EAAS,YAAYK,CAAK,GAG1BL,EAAS,iBAAiB,cAAc,MAAM;AAG5C,YAFwBA,EAAS,cAAc,mBAAmB,KAE9D,CAACR,EAAK,QAAS;AAEnB,cAAMc,IAAehB,EAAeE,EAAK,SAAS1G,CAAM,GAClDyH,IAAUb,EAAkBY,GAAcxH,GAAQ6G,GAAUC,CAAY;AAC9E,QAAAW,EAAQ,UAAU,IAAI,qBAAqB,GAC3CA,EAAQ,MAAM,WAAW,YACzBA,EAAQ,MAAM,OAAO,QACrBA,EAAQ,MAAM,MAAM,KACpBP,EAAS,MAAM,WAAW,YAC1BA,EAAS,YAAYO,CAAO;AAAA,MAC9B,CAAC,GAEDP,EAAS,iBAAiB,cAAc,MAAM;AAC5C,cAAMO,IAAUP,EAAS,cAAc,mBAAmB;AAC1D,QAAIO,OAAiB,OAAA;AAAA,MACvB,CAAC;AAAA,IACH;AAEA,IAAI,CAACN,KAAYT,EAAK,UAAU,CAACA,EAAK,WACpCQ,EAAS,iBAAiB,SAAS,CAACQ,MAAM;AACxC,MAAAA,EAAE,gBAAA,GACFb,EAASH,CAAI;AAAA,IACf,CAAC,GAGHM,EAAK,YAAYE,CAAQ;AAAA,EAC3B;AAEA,SAAOF;AACT;AAUO,SAASW,GAAaX,GAAmBY,GAAWC,GAAiB;AAE1E,EAAAb,EAAK,MAAM,WAAW,SACtBA,EAAK,MAAM,OAAO,GAAGY,CAAC,MACtBZ,EAAK,MAAM,MAAM,GAAGa,CAAC,MACrBb,EAAK,MAAM,aAAa,UACxBA,EAAK,MAAM,SAAS;AAGpB,QAAMc,IAAWd,EAAK,sBAAA,GAGhB9B,IAAgB,OAAO,YACvB6C,IAAiB,OAAO;AAE9B,MAAIC,IAAOJ,GACPK,IAAMJ;AAGV,EAAID,IAAIE,EAAS,QAAQ5C,MACvB8C,IAAOJ,IAAIE,EAAS,QAGlBD,IAAIC,EAAS,SAASC,MACxBE,IAAMJ,IAAIC,EAAS,SAIrBE,IAAO,KAAK,IAAI,GAAGA,CAAI,GACvBC,IAAM,KAAK,IAAI,GAAGA,CAAG,GAErBjB,EAAK,MAAM,OAAO,GAAGgB,CAAI,MACzBhB,EAAK,MAAM,MAAM,GAAGiB,CAAG,MACvBjB,EAAK,MAAM,aAAa;AAC1B;ACjLA,IAAIkB,IAAkD,MAElDC,IAA4D,MAE5DC,IAA4C,MAE5CC,IAAwB;AAG5B,MAAMC,IAAkC;AAAA,EACtC;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,UAAU;AAAA,IACV,QAAQ,CAACtI,MAAW;AAElB,MADcA,EAA8F,MACtG,SAAS,WAAW,OAAA;AAAA,IAC5B;AAAA,EAAA;AAAA,EAEF,EAAE,WAAW,IAAM,IAAI,QAAQ,MAAM,GAAA;AAAA,EACrC;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,QAAQ,CAACA,MAAW;AAGlB,MAFcA,EACX,MACG,SAAS,QAAQ,YAAA;AAAA,IACzB;AAAA,EAAA;AAEJ;AAiBO,MAAMuI,WAA0B3G,EAAkC;AAAA,EAC9D,OAAO;AAAA,EACE,UAAU;AAAA,EAE5B,IAAuB,gBAA4C;AACjE,WAAO;AAAA,MACL,OAAO0G;AAAA,IAAA;AAAA,EAEX;AAAA;AAAA,EAGQ,SAAS;AAAA,EACT,WAAW,EAAE,GAAG,GAAG,GAAG,EAAA;AAAA,EACtB,SAAmC;AAAA,EACnC,cAAkC;AAAA;AAAA;AAAA,EAKjC,OAAOnF,GAAiE;AAC/E,UAAM,OAAOA,CAAI,GACjB,KAAK,sBAAA,GACLkF;AAAA,EACF;AAAA,EAES,SAAe;AACtB,IAAI,KAAK,gBACP,KAAK,YAAY,OAAA,GACjB,KAAK,cAAc,OAErB,KAAK,SAAS,IACd,KAAK,SAAS,MACd,KAAK,wBAAA;AAAA,EACP;AAAA;AAAA;AAAA,EAKQ,wBAA8B;AAIpC,IACE,CAACD,KACD,OAAO,WAAa,OACpB,OAAOI,KAAsB,YAC7BA,MAEAJ,IAAmB,SAAS,cAAc,OAAO,GACjDA,EAAiB,KAAK,2BACtBA,EAAiB,cAAcI,GAC/B,SAAS,KAAK,YAAYJ,CAAgB,IAIvCF,MACHA,IAAqB,MAAM;AAEzB,MADc,SAAS,iBAAiB,mBAAmB,EACrD,QAAQ,CAAClB,MAASA,EAAK,QAAQ;AAAA,IACvC,GACA,SAAS,iBAAiB,SAASkB,CAAkB,IAIlDC,MACHA,IAAuB,CAAC,MAAqB;AAC3C,MAAI,EAAE,QAAQ,YACE,SAAS,iBAAiB,mBAAmB,EACrD,QAAQ,CAACnB,MAASA,EAAK,QAAQ;AAAA,IAEzC,GACA,SAAS,iBAAiB,WAAWmB,CAAoB;AAAA,EAE7D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,0BAAgC;AAEtC,IADAE,KACI,EAAAA,IAAwB,OAGxBH,MACF,SAAS,oBAAoB,SAASA,CAAkB,GACxDA,IAAqB,OAEnBC,MACF,SAAS,oBAAoB,WAAWA,CAAoB,GAC5DA,IAAuB,OAErBC,MACFA,EAAiB,OAAA,GACjBA,IAAmB;AAAA,EAEvB;AAAA;AAAA;AAAA,EAKS,cAAoB;AAC3B,UAAMnC,IAAa,KAAK;AACxB,QAAI,CAACA,EAAY;AAEjB,UAAMwC,IAAYxC,EAAW,SAAS,CAAC;AACvC,IAAKwC,KAGDA,EAAU,aAAa,yBAAyB,MAAM,WAC1DA,EAAU,aAAa,2BAA2B,MAAM,GAExDA,EAAU,iBAAiB,eAAe,CAACf,MAAa;AACtD,YAAM7F,IAAQ6F;AACd,MAAA7F,EAAM,eAAA;AAEN,YAAMK,IAASL,EAAM,QACfkB,IAAOb,EAAO,QAAQ,sBAAsB,GAC5C1B,IAAS0B,EAAO,QAAQ,cAAc;AAE5C,UAAIlC;AAEJ,UAAI+C,GAAM;AACR,cAAMM,IAAW,SAASN,EAAK,aAAa,UAAU,KAAK,MAAM,EAAE,GAC7DO,IAAW,SAASP,EAAK,aAAa,UAAU,KAAK,MAAM,EAAE,GAC7DS,IAAS,KAAK,QAAQF,CAAQ,GAC9B5D,IAAM,KAAK,KAAK2D,CAAQ;AAE9B,QAAArD,IAAS;AAAA,UACP,KAAAN;AAAA,UACA,UAAA2D;AAAA,UACA,QAAAG;AAAA,UACA,aAAaF;AAAA,UACb,OAAOE,GAAQ,SAAS;AAAA,UACxB,OAAO9D,IAAM8D,GAAQ,KAAyB,KAAK;AAAA,UACnD,UAAU;AAAA,UACV,OAAA3B;AAAA,QAAA;AAAA,MAEJ,WAAWrB,GAAQ;AACjB,cAAM8C,IAAW,SAAS9C,EAAO,aAAa,UAAU,KAAK,MAAM,EAAE,GAC/DgD,IAAS,KAAK,QAAQF,CAAQ;AAEpC,QAAAtD,IAAS;AAAA,UACP,KAAK;AAAA,UACL,UAAU;AAAA,UACV,QAAAwD;AAAA,UACA,aAAaF;AAAA,UACb,OAAOE,GAAQ,SAAS;AAAA,UACxB,OAAO;AAAA,UACP,UAAU;AAAA,UACV,OAAA3B;AAAA,QAAA;AAAA,MAEJ;AACE;AAGF,WAAK,SAAS7B,GACd,KAAK,WAAW,EAAE,GAAG6B,EAAM,SAAS,GAAGA,EAAM,QAAA;AAE7C,YAAM4E,IAAQD,EAAe,KAAK,OAAO,SAAS8B,GAActI,CAAM;AACtE,MAAKyG,EAAM,WAEP,KAAK,eACP,KAAK,YAAY,OAAA,GAGnB,KAAK,cAAcG;AAAA,QACjBH;AAAA,QACAzG;AAAA,QACA,CAAC0G,MAAS;AACR,UAAIA,EAAK,UACPA,EAAK,OAAO1G,CAAM,GAEpB,KAAK,aAAa,OAAA,GAClB,KAAK,cAAc,MACnB,KAAK,SAAS;AAAA,QAChB;AAAA,QACA,KAAK,UAAU;AAAA,MAAA,GAGjB,SAAS,KAAK,YAAY,KAAK,WAAW,GAC1C2H,GAAa,KAAK,aAAa9F,EAAM,SAASA,EAAM,OAAO,GAC3D,KAAK,SAAS,IAEd,KAAK,KAAK,qBAAqB,EAAE,QAAA7B,GAAQ,OAAAyG,GAAO;AAAA,IAClD,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,SAASmB,GAAWC,GAAW7H,GAA0C;AACvE,UAAM0I,IAAgC;AAAA,MACpC,KAAK1I,EAAO,OAAO;AAAA,MACnB,UAAUA,EAAO,YAAY;AAAA,MAC7B,QAAQA,EAAO,UAAU;AAAA,MACzB,aAAaA,EAAO,eAAe;AAAA,MACnC,OAAOA,EAAO,SAAS;AAAA,MACvB,OAAOA,EAAO,SAAS;AAAA,MACvB,UAAUA,EAAO,YAAY;AAAA,MAC7B,OAAOA,EAAO,SAAS,IAAI,WAAW,aAAa;AAAA,IAAA,GAG/CyG,IAAQD,EAAe,KAAK,OAAO,SAAS8B,GAAcI,CAAU;AAE1E,IAAI,KAAK,eACP,KAAK,YAAY,OAAA,GAGnB,KAAK,cAAc9B;AAAA,MACjBH;AAAA,MACAiC;AAAA,MACA,CAAChC,MAAS;AACR,QAAIA,EAAK,UAAQA,EAAK,OAAOgC,CAAU,GACvC,KAAK,aAAa,OAAA,GAClB,KAAK,cAAc,MACnB,KAAK,SAAS;AAAA,MAChB;AAAA,MACA,KAAK,UAAU;AAAA,IAAA,GAGjB,SAAS,KAAK,YAAY,KAAK,WAAW,GAC1Cf,GAAa,KAAK,aAAaC,GAAGC,CAAC,GACnC,KAAK,SAAS;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,WAAiB;AACf,IAAI,KAAK,gBACP,KAAK,YAAY,OAAA,GACjB,KAAK,cAAc,MACnB,KAAK,SAAS;AAAA,EAElB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAsB;AACpB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAIF;AC/RO,SAASc,GAAenJ,GAAYoJ,IAAQ,IAAc;AAC/D,MAAIpJ,KAAS,KAAM,QAAO;AAC1B,MAAIA,aAAiB,KAAM,QAAOA,EAAM,YAAA;AACxC,MAAI,OAAOA,KAAU,SAAU,QAAO,KAAK,UAAUA,CAAK;AAE1D,QAAMI,IAAM,OAAOJ,CAAK;AAGxB,SAAIoJ,MAAUhJ,EAAI,SAAS,GAAG,KAAKA,EAAI,SAAS,GAAG,KAAKA,EAAI,SAAS;AAAA,CAAI,KAAKA,EAAI,SAAS,IAAI,KACtF,IAAIA,EAAI,QAAQ,MAAM,IAAI,CAAC,MAG7BA;AACT;AAKO,SAASiJ,GAAS5I,GAAaC,GAAyBF,GAAsB8I,IAAsB,CAAA,GAAY;AACrH,QAAMjJ,IAAYiJ,EAAQ,aAAa,KACjChJ,IAAUgJ,EAAQ,WAAW;AAAA,GAC7BxI,IAAkB,CAAA,GAGlByI,IAAMD,EAAQ,MAAM,WAAW;AAGrC,MAAI9I,EAAO,mBAAmB,IAAO;AACnC,UAAMmG,IAAYjG,EAAQ,IAAI,CAACY,MAAQ;AACrC,YAAMN,IAASM,EAAI,UAAUA,EAAI,OAC3BkI,IAAYhJ,EAAO,gBAAgBA,EAAO,cAAcQ,GAAQM,EAAI,KAAK,IAAIN;AACnF,aAAOmI,GAAeK,CAAS;AAAA,IACjC,CAAC;AACD,IAAA1I,EAAM,KAAK6F,EAAU,KAAKtG,CAAS,CAAC;AAAA,EACtC;AAGA,aAAWH,KAAOO,GAAM;AACtB,UAAMY,IAAQX,EAAQ,IAAI,CAACY,MAAQ;AACjC,UAAItB,IAAQE,EAAIoB,EAAI,KAAK;AACzB,aAAId,EAAO,gBACTR,IAAQQ,EAAO,YAAYR,GAAOsB,EAAI,OAAOpB,CAAG,IAE3CiJ,GAAenJ,CAAK;AAAA,IAC7B,CAAC;AACD,IAAAc,EAAM,KAAKO,EAAM,KAAKhB,CAAS,CAAC;AAAA,EAClC;AAEA,SAAOkJ,IAAMzI,EAAM,KAAKR,CAAO;AACjC;AAKO,SAASmJ,GAAaC,GAAYC,GAAwB;AAC/D,QAAMC,IAAM,IAAI,gBAAgBF,CAAI,GAC9BG,IAAO,SAAS,cAAc,GAAG;AACvC,EAAAA,EAAK,OAAOD,GACZC,EAAK,WAAWF,GAChBE,EAAK,MAAM,UAAU,QACrB,SAAS,KAAK,YAAYA,CAAI,GAC9BA,EAAK,MAAA,GACL,SAAS,KAAK,YAAYA,CAAI,GAC9B,IAAI,gBAAgBD,CAAG;AACzB;AAKO,SAASE,GAAYC,GAAiBJ,GAAwB;AACnE,QAAMD,IAAO,IAAI,KAAK,CAACK,CAAO,GAAG,EAAE,MAAM,2BAA2B;AACpE,EAAAN,GAAaC,GAAMC,CAAQ;AAC7B;ACnFA,SAASK,GAAU5J,GAAqB;AACtC,SAAOA,EACJ,QAAQ,MAAM,OAAO,EACrB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,QAAQ,EACtB,QAAQ,MAAM,QAAQ;AAC3B;AAMO,SAAS6J,GAAcxJ,GAAaC,GAAyBF,GAA8B;AAChG,MAAI0J,IAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAQV,MAAI1J,EAAO,mBAAmB,IAAO;AACnC,IAAA0J,KAAO;AAAA;AACP,eAAW5I,KAAOZ,GAAS;AACzB,YAAMM,IAASM,EAAI,UAAUA,EAAI,OAC3BkI,IAAYhJ,EAAO,gBAAgBA,EAAO,cAAcQ,GAAQM,EAAI,KAAK,IAAIN;AACnF,MAAAkJ,KAAO,gCAAgCF,GAAUR,CAAS,CAAC;AAAA,IAC7D;AACA,IAAAU,KAAO;AAAA,EACT;AAGA,aAAWhK,KAAOO,GAAM;AACtB,IAAAyJ,KAAO;AAAA;AACP,eAAW5I,KAAOZ,GAAS;AACzB,UAAIV,IAAQE,EAAIoB,EAAI,KAAK;AACzB,MAAId,EAAO,gBACTR,IAAQQ,EAAO,YAAYR,GAAOsB,EAAI,OAAOpB,CAAG;AAIlD,UAAIiK,IAAyC,UACzCC,IAAe;AAEnB,MAAIpK,KAAS,OACXoK,IAAe,KACN,OAAOpK,KAAU,YAAY,CAAC,MAAMA,CAAK,KAClDmK,IAAO,UACPC,IAAe,OAAOpK,CAAK,KAClBA,aAAiB,QAC1BmK,IAAO,YACPC,IAAepK,EAAM,YAAA,KAErBoK,IAAeJ,GAAU,OAAOhK,CAAK,CAAC,GAGxCkK,KAAO,wBAAwBC,CAAI,KAAKC,CAAY;AAAA,IACtD;AACA,IAAAF,KAAO;AAAA,EACT;AAEA,SAAAA,KAAO;AAAA;AAAA;AAAA,cACAA;AACT;AAKO,SAASG,GAAcN,GAAiBJ,GAAwB;AACrE,QAAMW,IAAYX,EAAS,SAAS,MAAM,IAAIA,IAAW,GAAGA,CAAQ,QAC9DD,IAAO,IAAI,KAAK,CAACK,CAAO,GAAG;AAAA,IAC/B,MAAM;AAAA,EAAA,CACP;AACD,EAAAN,GAAaC,GAAMY,CAAS;AAC9B;ACxDO,MAAMC,WAAqBnI,EAA6B;AAAA,EACpD,OAAO;AAAA,EACE,UAAU;AAAA,EAE5B,IAAuB,gBAAuC;AAC5D,WAAO;AAAA,MACL,UAAU;AAAA,MACV,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,cAAc;AAAA,IAAA;AAAA,EAElB;AAAA;AAAA,EAGQ,kBAAkB;AAAA,EAClB,iBAAmE;AAAA;AAAA;AAAA,EAKnE,cAAcoI,GAAsBhK,GAAsC;AAChF,UAAML,IAAS,KAAK,QAGd+I,IAA2B;AAAA,MAC/B,QAAAsB;AAAA,MACA,UAAUhK,GAAQ,YAAYL,EAAO,YAAY;AAAA,MACjD,gBAAgBK,GAAQ,kBAAkBL,EAAO;AAAA,MACjD,aAAaK,GAAQ;AAAA,MACrB,eAAeA,GAAQ;AAAA,MACvB,SAASA,GAAQ;AAAA,MACjB,YAAYA,GAAQ;AAAA,IAAA;AAItB,QAAIE,IAAU,CAAC,GAAG,KAAK,OAAO;AAI9B,QAHIP,EAAO,gBACTO,IAAUA,EAAQ,OAAO,CAACG,MAAM,CAACA,EAAE,UAAU,CAACA,EAAE,MAAM,WAAW,IAAI,CAAC,IAEpEL,GAAQ,SAAS;AACnB,YAAMiK,IAAS,IAAI,IAAIjK,EAAO,OAAO;AACrC,MAAAE,IAAUA,EAAQ,OAAO,CAACG,MAAM4J,EAAO,IAAI5J,EAAE,KAAK,CAAC;AAAA,IACrD;AAGA,QAAIJ,IAAO,CAAC,GAAG,KAAK,IAAI;AACxB,QAAIN,EAAO,cAAc;AACvB,YAAMuK,IAAiB,KAAK,kBAAA;AAC5B,MAAIA,GAAgB,UAAU,SAE5BjK,IADsB,CAAC,GAAGiK,EAAe,QAAQ,EAAE,KAAK,CAACxJ,GAAGC,MAAMD,IAAIC,CAAC,EAClD,IAAI,CAACa,MAAM,KAAK,KAAKA,CAAC,CAAC,EAAE,OAAO,OAAO;AAAA,IAEhE;AACA,IAAIxB,GAAQ,eACVC,IAAOD,EAAO,WAAW,IAAI,CAACwB,MAAM,KAAK,KAAKA,CAAC,CAAC,EAAE,OAAO,OAAO,IAGlE,KAAK,kBAAkB;AACvB,QAAI2H,IAAWT,EAAW;AAE1B,QAAI;AACF,cAAQsB,GAAA;AAAA,QACN,KAAK,OAAO;AACV,gBAAMT,IAAUV,GAAS5I,GAAMC,GAASwI,GAAY,EAAE,KAAK,IAAM;AACjE,UAAAS,IAAWA,EAAS,SAAS,MAAM,IAAIA,IAAW,GAAGA,CAAQ,QAC7DG,GAAYC,GAASJ,CAAQ;AAC7B;AAAA,QACF;AAAA,QAEA,KAAK,SAAS;AACZ,gBAAMI,IAAUE,GAAcxJ,GAAMC,GAASwI,CAAU;AACvD,UAAAS,IAAWA,EAAS,SAAS,MAAM,IAAIA,IAAW,GAAGA,CAAQ,QAC7DU,GAAcN,GAASJ,CAAQ;AAC/B;AAAA,QACF;AAAA,QAEA,KAAK,QAAQ;AACX,gBAAMgB,IAAWlK,EAAK,IAAI,CAACP,MAAQ;AACjC,kBAAM0K,IAA2B,CAAA;AACjC,uBAAWtJ,KAAOZ,GAAS;AACzB,kBAAIV,IAAQE,EAAIoB,EAAI,KAAK;AACzB,cAAI4H,EAAW,gBACblJ,IAAQkJ,EAAW,YAAYlJ,GAAOsB,EAAI,OAAOpB,CAAG,IAEtD0K,EAAItJ,EAAI,KAAK,IAAItB;AAAA,YACnB;AACA,mBAAO4K;AAAA,UACT,CAAC,GACKb,IAAU,KAAK,UAAUY,GAAU,MAAM,CAAC;AAChD,UAAAhB,IAAWA,EAAS,SAAS,OAAO,IAAIA,IAAW,GAAGA,CAAQ;AAC9D,gBAAMD,IAAO,IAAI,KAAK,CAACK,CAAO,GAAG,EAAE,MAAM,oBAAoB;AAC7D,UAAAN,GAAaC,GAAMC,CAAQ;AAC3B;AAAA,QACF;AAAA,MAAA;AAGF,WAAK,iBAAiB,EAAE,QAAAa,GAAQ,WAAW,oBAAI,OAAK,GAEpD,KAAK,KAA2B,mBAAmB;AAAA,QACjD,QAAAA;AAAA,QACA,UAAAb;AAAA,QACA,UAAUlJ,EAAK;AAAA,QACf,aAAaC,EAAQ;AAAA,MAAA,CACtB;AAAA,IACH,UAAA;AACE,WAAK,kBAAkB;AAAA,IACzB;AAAA,EACF;AAAA,EAEQ,oBAAiD;AACvD,QAAI;AAEF,aADa,KAAK,MACL,iBAAiB,WAAW,KAAK;AAAA,IAChD,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,UAAUF,GAAsC;AAC9C,SAAK,cAAc,OAAOA,CAAM;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAYA,GAAsC;AAChD,SAAK,cAAc,SAASA,CAAM;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,WAAWA,GAAsC;AAC/C,SAAK,cAAc,QAAQA,CAAM;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cAAuB;AACrB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAkE;AAChE,WAAO,KAAK;AAAA,EACd;AAAA;AAEF;ACxJO,SAASqK,GAAqBrK,GAA4C;AAC/E,QAAM,EAAE,WAAAsK,GAAW,gBAAAvC,GAAgB,WAAAwC,GAAW,WAAAC,GAAW,UAAAnF,MAAarF,GAIhEyK,IAAc,KAAK,KAAK1C,IAAiByC,CAAS;AAGxD,MAAIE,IAAQ,KAAK,MAAMH,IAAYC,CAAS,IAAInF;AAChD,EAAIqF,IAAQ,MAAGA,IAAQ;AAEvB,MAAIC,IAAMD,IAAQD,IAAcpF,IAAW;AAC3C,SAAIsF,IAAML,MAAWK,IAAML,IAGvBK,MAAQL,KAAaI,IAAQ,MAC/BA,IAAQ,KAAK,IAAI,GAAGC,IAAMF,IAAcpF,IAAW,CAAC,IAG/C;AAAA,IACL,OAAAqF;AAAA,IACA,KAAAC;AAAA,IACA,SAASD,IAAQF;AAAA,IACjB,aAAaF,IAAYE;AAAA,EAAA;AAE7B;AAUO,SAASI,GAA2BN,GAAmB1E,GAA4B;AACxF,SAAO0E,KAAa1E;AACtB;AC/DO,SAASiF,GAAcnL,GAA8BoL,GAAqBC,IAAgB,IAAgB;AAC/G,QAAMC,IAAWtL,EAAIoL,EAAO,KAAK;AAGjC,MAAIA,EAAO,aAAa;AACtB,WAAOE,KAAY,QAAQA,MAAa;AAE1C,MAAIF,EAAO,aAAa;AACtB,WAAOE,KAAY,QAAQA,MAAa;AAI1C,MAAIA,KAAY,KAAM,QAAO;AAG7B,QAAMC,IAAc,OAAOD,CAAQ,GAC7BE,IAAeH,IAAgBE,IAAcA,EAAY,YAAA,GACzDE,IAAcJ,IAAgB,OAAOD,EAAO,KAAK,IAAI,OAAOA,EAAO,KAAK,EAAE,YAAA;AAEhF,UAAQA,EAAO,UAAA;AAAA;AAAA,IAEb,KAAK;AACH,aAAOI,EAAa,SAASC,CAAW;AAAA,IAE1C,KAAK;AACH,aAAO,CAACD,EAAa,SAASC,CAAW;AAAA,IAE3C,KAAK;AACH,aAAOD,MAAiBC;AAAA,IAE1B,KAAK;AACH,aAAOD,MAAiBC;AAAA,IAE1B,KAAK;AACH,aAAOD,EAAa,WAAWC,CAAW;AAAA,IAE5C,KAAK;AACH,aAAOD,EAAa,SAASC,CAAW;AAAA;AAAA,IAG1C,KAAK;AACH,aAAO,OAAOH,CAAQ,IAAI,OAAOF,EAAO,KAAK;AAAA,IAE/C,KAAK;AACH,aAAO,OAAOE,CAAQ,KAAK,OAAOF,EAAO,KAAK;AAAA,IAEhD,KAAK;AACH,aAAO,OAAOE,CAAQ,IAAI,OAAOF,EAAO,KAAK;AAAA,IAE/C,KAAK;AACH,aAAO,OAAOE,CAAQ,KAAK,OAAOF,EAAO,KAAK;AAAA,IAEhD,KAAK;AACH,aAAO,OAAOE,CAAQ,KAAK,OAAOF,EAAO,KAAK,KAAK,OAAOE,CAAQ,KAAK,OAAOF,EAAO,OAAO;AAAA;AAAA,IAG9F,KAAK;AACH,aAAO,MAAM,QAAQA,EAAO,KAAK,KAAKA,EAAO,MAAM,SAASE,CAAQ;AAAA,IAEtE,KAAK;AACH,aAAO,MAAM,QAAQF,EAAO,KAAK,KAAK,CAACA,EAAO,MAAM,SAASE,CAAQ;AAAA,IAEvE;AACE,aAAO;AAAA,EAAA;AAEb;AAWO,SAASI,GACdnL,GACAoL,GACAN,IAAgB,IACX;AACL,SAAKM,EAAQ,SACNpL,EAAK,OAAO,CAACP,MAAQ2L,EAAQ,MAAM,CAACC,MAAMT,GAAcnL,GAAK4L,GAAGP,CAAa,CAAC,CAAC,IAD1D9K;AAE9B;AASO,SAASsL,GAAsBF,GAAgC;AACpE,SAAO,KAAK;AAAA,IACVA,EAAQ,IAAI,CAACC,OAAO;AAAA,MAClB,OAAOA,EAAE;AAAA,MACT,UAAUA,EAAE;AAAA,MACZ,OAAOA,EAAE;AAAA,MACT,SAASA,EAAE;AAAA,IAAA,EACX;AAAA,EAAA;AAEN;AAUO,SAASE,GAAmDvL,GAAWR,GAA0B;AACtG,QAAMgM,wBAAa,IAAA;AACnB,aAAW/L,KAAOO,GAAM;AACtB,UAAMT,IAAQE,EAAID,CAAK;AACvB,IAAID,KAAS,QACXiM,EAAO,IAAIjM,CAAK;AAAA,EAEpB;AACA,SAAO,CAAC,GAAGiM,CAAM,EAAE,KAAK,CAAC/K,GAAGC,MAEtB,OAAOD,KAAM,YAAY,OAAOC,KAAM,WACjCD,IAAIC,IAEN,OAAOD,CAAC,EAAE,cAAc,OAAOC,CAAC,CAAC,CACzC;AACH;;ACtHO,MAAM+K,UAAwB9J,EAA6B;AAAA,EACvD,OAAO;AAAA,EACE,UAAU;AAAA,EAE5B,IAAuB,gBAAuC;AAC5D,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,eAAe;AAAA,MACf,WAAW;AAAA,MACX,WAAW;AAAA,IAAA;AAAA,EAEf;AAAA;AAAA,EAGQ,8BAAwC,IAAA;AAAA,EACxC,eAAiC;AAAA,EACjC,WAA0B;AAAA,EAC1B,iBAAgC;AAAA,EAChC,eAAmC;AAAA,EACnC,iCAAsC,IAAA;AAAA,EACtC,qCAAgD,IAAA;AAAA,EAChD,uBAA+C;AAAA;AAAA,EAC/C,uBAAuB;AAAA;AAAA,EAG/B,OAAwB,mBAAmB;AAAA,EAC3C,OAAwB,gBAAgB;AAAA,EACxC,OAAwB,wBAAwB;AAAA;AAAA;AAAA;AAAA,EAKvC,OAAOuB,GAAyB;AACvC,UAAM,OAAOA,CAAI,GACjB,KAAK,mBAAA;AAAA,EACP;AAAA,EAES,SAAe;AACtB,SAAK,QAAQ,MAAA,GACb,KAAK,eAAe,MACpB,KAAK,WAAW,MAChB,KAAK,iBAAiB,MAClB,KAAK,iBACP,KAAK,aAAa,OAAA,GAClB,KAAK,eAAe,OAEtB,KAAK,WAAW,MAAA,GAChB,KAAK,eAAe,MAAA,GAEpB,KAAK,sBAAsB,MAAA,GAC3B,KAAK,uBAAuB;AAAA,EAC9B;AAAA;AAAA;AAAA,EAKS,YAAYlD,GAAqC;AACxD,UAAM0L,IAAa,CAAC,GAAG,KAAK,QAAQ,QAAQ;AAC5C,QAAI,CAACA,EAAW,OAAQ,QAAO,CAAC,GAAG1L,CAAI;AAIvC,QAAI,KAAK,OAAO;AAEd,aAAI,KAAK,eAAqB,KAAK,eAE5B,CAAC,GAAGA,CAAI;AAIjB,UAAM2L,IAAcL,GAAsBI,CAAU;AACpD,QAAI,KAAK,aAAaC,KAAe,KAAK;AACxC,aAAO,KAAK;AAId,UAAM/I,IAASuI,GAAW,CAAC,GAAGnL,CAAI,GAAgC0L,GAAY,KAAK,OAAO,aAAa;AAGvG,gBAAK,eAAe9I,GACpB,KAAK,WAAW+I,GAET/I;AAAA,EACT;AAAA,EAES,cAAoB;AAC3B,UAAMoD,IAAa,KAAK;AACxB,QAAI,CAACA,EAAY;AAIjB,IADoBA,EAAW,iBAAiB,uBAAuB,EAC3D,QAAQ,CAAClD,MAAS;AAC5B,YAAMO,IAAWP,EAAK,aAAa,UAAU;AAC7C,UAAIO,MAAa,KAAM;AAGvB,YAAMxC,IAAM,KAAK,eAAe,SAASwC,GAAU,EAAE,CAAC;AACtD,UAAI,CAACxC,KAAOA,EAAI,eAAe,GAAO;AAEtC,YAAMrB,IAAQqB,EAAI;AAClB,UAAI,CAACrB,EAAO;AAEZ,YAAMoM,IAAY,KAAK,QAAQ,IAAIpM,CAAK;AAGxC,UAAIqM,IAAY/I,EAAK,cAAc,iBAAiB;AAEpD,UAAI+I,GAAW;AAEb,QAAAA,EAAU,UAAU,OAAO,UAAUD,CAAS,GAC7C9I,EAAqB,UAAU,OAAO,YAAY8I,CAAS;AAC5D;AAAA,MACF;AAGA,MAAAC,IAAY,SAAS,cAAc,QAAQ,GAC3CA,EAAU,YAAY,kBACtBA,EAAU,aAAa,cAAc,UAAUhL,EAAI,UAAUrB,CAAK,EAAE,GACpEqM,EAAU,YAAY,kRAGlBD,MACFC,EAAU,UAAU,IAAI,QAAQ,GAC/B/I,EAAqB,UAAU,IAAI,UAAU,IAGhD+I,EAAU,iBAAiB,SAAS,CAACpE,MAAM;AACzC,QAAAA,EAAE,gBAAA,GACF,KAAK,kBAAkBjI,GAAOqB,GAAKgL,CAAU;AAAA,MAC/C,CAAC,GAGD/I,EAAK,YAAY+I,CAAS;AAAA,IAC5B,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,UAAUrM,GAAeqL,GAAiD;AACxE,IAAIA,MAAW,QACb,KAAK,QAAQ,OAAOrL,CAAK,GACzB,KAAK,eAAe,OAAOA,CAAK,MAEhC,KAAK,QAAQ,IAAIA,GAAO,EAAE,GAAGqL,GAAQ,OAAArL,GAAO,GAExCqL,EAAO,SAAS,SAASA,EAAO,aAAa,WAAW,MAAM,QAAQA,EAAO,KAAK,IACpF,KAAK,eAAe,IAAIrL,GAAO,IAAI,IAAIqL,EAAO,KAAK,CAAC,IAC3CA,EAAO,SAAS,SAEzB,KAAK,eAAe,OAAOrL,CAAK,IAIpC,KAAK,eAAe,MACpB,KAAK,WAAW,MAEhB,KAAK,KAAyB,iBAAiB;AAAA,MAC7C,SAAS,CAAC,GAAG,KAAK,QAAQ,QAAQ;AAAA,MAClC,kBAAkB;AAAA;AAAA,IAAA,CACnB,GACD,KAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKA,UAAUA,GAAwC;AAChD,WAAO,KAAK,QAAQ,IAAIA,CAAK;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,aAA4B;AAC1B,WAAO,CAAC,GAAG,KAAK,QAAQ,QAAQ;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAgC;AAC9B,WAAO,KAAK,WAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,eAAe4L,GAA8B;AAC3C,SAAK,QAAQ,MAAA,GACb,KAAK,eAAe,MAAA;AACpB,eAAWP,KAAUO;AACnB,WAAK,QAAQ,IAAIP,EAAO,OAAOA,CAAM,GAEjCA,EAAO,SAAS,SAASA,EAAO,aAAa,WAAW,MAAM,QAAQA,EAAO,KAAK,KACpF,KAAK,eAAe,IAAIA,EAAO,OAAO,IAAI,IAAIA,EAAO,KAAK,CAAC;AAG/D,SAAK,eAAe,MACpB,KAAK,WAAW,MAEhB,KAAK,KAAyB,iBAAiB;AAAA,MAC7C,SAAS,CAAC,GAAG,KAAK,QAAQ,QAAQ;AAAA,MAClC,kBAAkB;AAAA,IAAA,CACnB,GACD,KAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAwB;AACtB,SAAK,QAAQ,MAAA,GACb,KAAK,eAAe,MAAA,GACpB,KAAK,WAAW,MAAA,GAEhB,KAAK,qBAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAiBrL,GAAqB;AACpC,SAAK,QAAQ,OAAOA,CAAK,GACzB,KAAK,eAAe,OAAOA,CAAK,GAChC,KAAK,WAAW,OAAOA,CAAK,GAE5B,KAAK,qBAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgBA,GAAwB;AACtC,WAAO,KAAK,QAAQ,IAAIA,CAAK;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,sBAA8B;AAC5B,WAAO,KAAK,cAAc,UAAU,KAAK,KAAK;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAkC;AAChC,WAAO,KAAK,WAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAgBA,GAA0B;AACxC,WAAO+L,GAAgB,KAAK,YAAyC/L,CAAK;AAAA,EAC5E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,qBAA2B;AACjC,QAAI,KAAK,qBAAsB;AAC/B,QAAI,SAAS,eAAe,yBAAyB,GAAG;AACtD,WAAK,uBAAuB;AAC5B;AAAA,IACF;AAOA,UAAMsM,IAAQ,SAAS,cAAc,OAAO;AAC5C,IAAAA,EAAM,KAAK,2BACXA,EAAM,cAAcC,IACpB,SAAS,KAAK,YAAYD,CAAK,GAC/B,KAAK,uBAAuB;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKQ,kBAAkBtM,GAAe+D,GAAsByI,GAA6B;AAE1F,QAAI,KAAK,mBAAmBxM,GAAO;AACjC,WAAK,iBAAA;AACL;AAAA,IACF;AAGA,SAAK,iBAAA;AAGL,UAAMyM,IAAQ,SAAS,cAAc,KAAK;AAM1C,QALAA,EAAM,YAAY,oBAClB,KAAK,eAAeA,GACpB,KAAK,iBAAiBzM,GAGlB,KAAK,OAAO,eAAe;AAC7B,MAAAyM,EAAM,YAAY,oDAClB,SAAS,KAAK,YAAYA,CAAK,GAC/B,KAAK,cAAcA,GAAOD,CAAQ,GAClC,KAAK,uBAAuBC,GAAOD,CAAQ,GAE3C,KAAK,OAAO,cAAcxM,GAAO+D,CAAM,EAAE,KAAK,CAACiI,MAAW;AAExD,QAAI,KAAK,mBAAmBhM,KAAS,CAAC,KAAK,iBAC3CyM,EAAM,YAAY,IAClB,KAAK,mBAAmBzM,GAAO+D,GAAQ0I,GAAOT,CAAM;AAAA,MACtD,CAAC;AACD;AAAA,IACF;AAGA,UAAMU,IAAeX,GAAgB,KAAK,YAAyC/L,CAAK;AACxF,SAAK,mBAAmBA,GAAO+D,GAAQ0I,GAAOC,CAAY,GAG1D,SAAS,KAAK,YAAYD,CAAK,GAC/B,KAAK,cAAcA,GAAOD,CAAQ,GAClC,KAAK,uBAAuBC,GAAOD,CAAQ;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKQ,mBAAmBxM,GAAe+D,GAAsB0I,GAAoBC,GAA+B;AAEjH,QAAIC,IAAc,KAAK,eAAe,IAAI3M,CAAK;AAC/C,IAAK2M,MACHA,wBAAkB,IAAA,GAClB,KAAK,eAAe,IAAI3M,GAAO2M,CAAW;AAI5C,UAAMC,IAAoB,KAAK,WAAW,IAAI5M,CAAK,KAAK,IAGlDO,IAA4B;AAAA,MAChC,OAAAP;AAAA,MACA,QAAA+D;AAAA,MACA,cAAA2I;AAAA,MACA,gBAAgBC;AAAA,MAChB,YAAYC;AAAA,MACZ,gBAAgB,CAACC,MAAwB;AACvC,aAAK,eAAe7M,GAAO6M,CAAQ,GACnC,KAAK,iBAAA;AAAA,MACP;AAAA,MACA,iBAAiB,CAACC,GAAU/M,GAAOgN,MAAY;AAC7C,aAAK,gBAAgB/M,GAAO8M,GAAU/M,GAAOgN,CAAO,GACpD,KAAK,iBAAA;AAAA,MACP;AAAA,MACA,aAAa,MAAM;AACjB,aAAK,iBAAiB/M,CAAK,GAC3B,KAAK,iBAAA;AAAA,MACP;AAAA,MACA,YAAY,MAAM,KAAK,iBAAA;AAAA,IAAiB;AAK1C,QAAIgN,IAAqB;AACzB,IAAI,KAAK,OAAO,wBACd,KAAK,OAAO,oBAAoBP,GAAOlM,CAAM,GAE7CyM,IAAqBP,EAAM,SAAS,SAAS,IAE1CO,KACH,KAAK,yBAAyBP,GAAOlM,GAAQmM,GAAcC,CAAW;AAAA,EAE1E;AAAA;AAAA;AAAA;AAAA,EAKQ,uBAAuBF,GAAoBD,GAA6B;AAG9E,SAAK,uBAAuB,IAAI,gBAAA,GAIhC,WAAW,MAAM;AACf,eAAS;AAAA,QACP;AAAA,QACA,CAACvE,MAAkB;AACjB,UAAI,CAACwE,EAAM,SAASxE,EAAE,MAAc,KAAKA,EAAE,WAAWuE,KACpD,KAAK,iBAAA;AAAA,QAET;AAAA,QACA,EAAE,QAAQ,KAAK,sBAAsB,OAAA;AAAA,MAAO;AAAA,IAEhD,GAAG,CAAC;AAAA,EACN;AAAA;AAAA;AAAA;AAAA,EAKQ,mBAAyB;AAC/B,IAAI,KAAK,iBACP,KAAK,aAAa,OAAA,GAClB,KAAK,eAAe,OAEtB,KAAK,iBAAiB,MAEtB,KAAK,sBAAsB,MAAA,GAC3B,KAAK,uBAAuB;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKQ,cAAcC,GAAoBD,GAA6B;AACrE,UAAMS,IAAOT,EAAS,sBAAA;AACtB,IAAAC,EAAM,MAAM,WAAW,SACvBA,EAAM,MAAM,MAAM,GAAGQ,EAAK,SAAS,CAAC,MACpCR,EAAM,MAAM,OAAO,GAAGQ,EAAK,IAAI,MAG/B,sBAAsB,MAAM;AAC1B,YAAMC,IAAYT,EAAM,sBAAA;AACxB,MAAIS,EAAU,QAAQ,OAAO,aAAa,MACxCT,EAAM,MAAM,OAAO,GAAG,OAAO,aAAaS,EAAU,QAAQ,CAAC,OAG3DA,EAAU,SAAS,OAAO,cAAc,MAC1CT,EAAM,MAAM,MAAM,GAAGQ,EAAK,MAAMC,EAAU,SAAS,CAAC;AAAA,IAExD,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKQ,yBACNT,GACAlM,GACAmM,GACAS,GACM;AACN,UAAM,EAAE,OAAAnN,MAAUO,GAGZ6M,IAAkB,SAAS,cAAc,KAAK;AACpD,IAAAA,EAAgB,YAAY;AAE5B,UAAMC,IAAc,SAAS,cAAc,OAAO;AAClD,IAAAA,EAAY,OAAO,QACnBA,EAAY,cAAc,aAC1BA,EAAY,YAAY,2BACxBA,EAAY,QAAQ,KAAK,WAAW,IAAIrN,CAAK,KAAK,IAClDoN,EAAgB,YAAYC,CAAW,GACvCZ,EAAM,YAAYW,CAAe;AAGjC,UAAME,IAAa,SAAS,cAAc,KAAK;AAC/C,IAAAA,EAAW,YAAY;AAEvB,UAAMC,IAAiB,SAAS,cAAc,OAAO;AACrD,IAAAA,EAAe,YAAY,yBAC3BA,EAAe,MAAM,UAAU,KAC/BA,EAAe,MAAM,SAAS;AAE9B,UAAMC,IAAoB,SAAS,cAAc,OAAO;AACxD,IAAAA,EAAkB,OAAO,YACzBA,EAAkB,YAAY;AAE9B,UAAMC,IAAgB,SAAS,cAAc,MAAM;AACnD,IAAAA,EAAc,cAAc,cAE5BF,EAAe,YAAYC,CAAiB,GAC5CD,EAAe,YAAYE,CAAa,GACxCH,EAAW,YAAYC,CAAc;AAGrC,UAAMG,IAAuB,MAAM;AACjC,YAAM1B,IAAS,CAAC,GAAG2B,EAAW,QAAQ,GAChCC,IAAa5B,EAAO,MAAM,CAAC6B,MAAMA,CAAC,GAClCC,IAAc9B,EAAO,MAAM,CAAC6B,MAAM,CAACA,CAAC;AAE1C,MAAAL,EAAkB,UAAUI,GAC5BJ,EAAkB,gBAAgB,CAACI,KAAc,CAACE;AAAA,IACpD;AAGA,IAAAN,EAAkB,iBAAiB,UAAU,MAAM;AACjD,YAAMO,IAAWP,EAAkB;AACnC,iBAAWQ,KAAOL,EAAW;AAC3B,QAAAA,EAAW,IAAIK,GAAKD,CAAQ;AAE9B,MAAAL,EAAA,GACAO,EAAA;AAAA,IACF,CAAC,GAEDxB,EAAM,YAAYa,CAAU;AAG5B,UAAMY,IAAkB,SAAS,cAAc,KAAK;AACpD,IAAAA,EAAgB,YAAY;AAG5B,UAAMC,IAAS,SAAS,cAAc,KAAK;AAC3C,IAAAA,EAAO,YAAY,4BACnBD,EAAgB,YAAYC,CAAM;AAGlC,UAAMC,IAAmB,SAAS,cAAc,KAAK;AACrD,IAAAA,EAAiB,YAAY,6BAC7BF,EAAgB,YAAYE,CAAgB;AAG5C,UAAMT,wBAAiB,IAAA;AACvB,IAAAjB,EAAa,QAAQ,CAAC3M,MAAU;AAC9B,YAAMiO,IAAMjO,KAAS,OAAO,aAAa,OAAOA,CAAK;AACrD,MAAA4N,EAAW,IAAIK,GAAK,CAACb,EAAe,IAAIpN,CAAK,CAAC;AAAA,IAChD,CAAC,GAGD2N,EAAA;AAGA,QAAIW,IAA4B,CAAA;AAGhC,UAAMC,IAAa,CAACvO,GAAgBwO,MAA+B;AACjE,YAAMC,IAAWzO,KAAS,OAAO,YAAY,OAAOA,CAAK,GACnDiO,IAAMjO,KAAS,OAAO,aAAa,OAAOA,CAAK,GAE/CkH,IAAO,SAAS,cAAc,OAAO;AAC3C,MAAAA,EAAK,YAAY,yBACjBA,EAAK,MAAM,WAAW,YACtBA,EAAK,MAAM,MAAM,GAAGsH,IAAQtC,EAAgB,gBAAgB,MAC5DhF,EAAK,MAAM,OAAO,KAClBA,EAAK,MAAM,QAAQ,KACnBA,EAAK,MAAM,SAAS,GAAGgF,EAAgB,gBAAgB,MACvDhF,EAAK,MAAM,YAAY;AAEvB,YAAMwH,IAAW,SAAS,cAAc,OAAO;AAC/C,MAAAA,EAAS,OAAO,YAChBA,EAAS,YAAY,uBACrBA,EAAS,UAAUd,EAAW,IAAIK,CAAG,KAAK,IAC1CS,EAAS,QAAQ,QAAQT,GAGzBS,EAAS,iBAAiB,UAAU,MAAM;AACxC,QAAAd,EAAW,IAAIK,GAAKS,EAAS,OAAO,GACpCf,EAAA;AAAA,MACF,CAAC;AAED,YAAM9F,KAAQ,SAAS,cAAc,MAAM;AAC3C,aAAAA,GAAM,cAAc4G,GAEpBvH,EAAK,YAAYwH,CAAQ,GACzBxH,EAAK,YAAYW,EAAK,GACfX;AAAA,IACT,GAGMgH,IAAqB,MAAM;AAC/B,YAAMS,IAAaL,EAAe,QAC5B/F,IAAiB4F,EAAgB,cACjCpD,IAAYoD,EAAgB;AAMlC,UAHAC,EAAO,MAAM,SAAS,GAAGO,IAAazC,EAAgB,gBAAgB,MAGlEd,GAA2BuD,GAAYzC,EAAgB,wBAAwB,CAAC,GAAG;AACrF,QAAAmC,EAAiB,YAAY,IAC7BA,EAAiB,MAAM,YAAY,mBACnCC,EAAe,QAAQ,CAACtO,GAAOoB,MAAQ;AACrC,UAAAiN,EAAiB,YAAYE,EAAWvO,GAAOoB,CAAG,CAAC;AAAA,QACrD,CAAC;AACD;AAAA,MACF;AAGA,YAAMwN,IAAS/D,GAAqB;AAAA,QAClC,WAAW8D;AAAA,QACX,gBAAApG;AAAA,QACA,WAAAwC;AAAA,QACA,WAAWmB,EAAgB;AAAA,QAC3B,UAAUA,EAAgB;AAAA,MAAA,CAC3B;AAGD,MAAAmC,EAAiB,MAAM,YAAY,cAAcO,EAAO,OAAO,OAG/DP,EAAiB,YAAY;AAC7B,eAASrM,IAAI4M,EAAO,OAAO5M,IAAI4M,EAAO,KAAK5M;AACzC,QAAAqM,EAAiB,YAAYE,EAAWD,EAAetM,CAAC,GAAGA,IAAI4M,EAAO,KAAK,CAAC;AAAA,IAEhF,GAGMC,KAAe,CAACC,MAAuB;AAC3C,YAAMC,IAAcD,EAAW,YAAA;AAQ/B,UALAR,IAAiB3B,EAAa,OAAO,CAAC3M,MAAU;AAC9C,cAAMyO,IAAWzO,KAAS,OAAO,YAAY,OAAOA,CAAK;AACzD,eAAO,CAAC8O,KAAcL,EAAS,YAAA,EAAc,SAASM,CAAW;AAAA,MACnE,CAAC,GAEGT,EAAe,WAAW,GAAG;AAC/B,QAAAF,EAAO,MAAM,SAAS,OACtBC,EAAiB,YAAY;AAC7B,cAAMW,IAAU,SAAS,cAAc,KAAK;AAC5C,QAAAA,EAAQ,YAAY,uBACpBA,EAAQ,cAAc,sBACtBX,EAAiB,YAAYW,CAAO;AACpC;AAAA,MACF;AAEA,MAAAd,EAAA;AAAA,IACF;AAGA,IAAAC,EAAgB;AAAA,MACd;AAAA,MACA,MAAM;AACJ,QAAIG,EAAe,SAAS,KAC1BJ,EAAA;AAAA,MAEJ;AAAA,MACA,EAAE,SAAS,GAAA;AAAA,IAAK,GAGlBW,GAAavB,EAAY,KAAK,GAC9BZ,EAAM,YAAYyB,CAAe;AAGjC,QAAIc;AACJ,IAAA3B,EAAY,iBAAiB,SAAS,MAAM;AAC1C,mBAAa2B,EAAa,GAC1BA,KAAgB,WAAW,MAAM;AAC/B,aAAK,WAAW,IAAIhP,GAAOqN,EAAY,KAAK,GAC5CuB,GAAavB,EAAY,KAAK;AAAA,MAChC,GAAG,KAAK,OAAO,cAAc,GAAG;AAAA,IAClC,CAAC;AAGD,UAAM4B,IAAY,SAAS,cAAc,KAAK;AAC9C,IAAAA,EAAU,YAAY;AAEtB,UAAMC,IAAW,SAAS,cAAc,QAAQ;AAChD,IAAAA,EAAS,YAAY,wBACrBA,EAAS,cAAc,SACvBA,EAAS,iBAAiB,SAAS,MAAM;AAEvC,YAAMrC,IAAsB,CAAA;AAC5B,iBAAW,CAACmB,GAAKmB,CAAS,KAAKxB;AAC7B,YAAI,CAACwB;AACH,cAAInB,MAAQ;AACV,YAAAnB,EAAS,KAAK,IAAI;AAAA,eACb;AAEL,kBAAMuC,IAAW1C,EAAa,KAAK,CAACmB,MAAM,OAAOA,CAAC,MAAMG,CAAG;AAC3D,YAAAnB,EAAS,KAAKuC,MAAa,SAAYA,IAAWpB,CAAG;AAAA,UACvD;AAGJ,MAAAzN,EAAO,eAAesM,CAAQ;AAAA,IAChC,CAAC,GACDoC,EAAU,YAAYC,CAAQ;AAE9B,UAAMG,IAAW,SAAS,cAAc,QAAQ;AAChD,IAAAA,EAAS,YAAY,wBACrBA,EAAS,cAAc,gBACvBA,EAAS,iBAAiB,SAAS,MAAM;AACvC,MAAA9O,EAAO,YAAA;AAAA,IACT,CAAC,GACD0O,EAAU,YAAYI,CAAQ,GAE9B5C,EAAM,YAAYwC,CAAS;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAejP,GAAe6M,GAA2B;AAE/D,SAAK,eAAe,IAAI7M,GAAO,IAAI,IAAI6M,CAAQ,CAAC,GAE5CA,EAAS,WAAW,IAEtB,KAAK,QAAQ,OAAO7M,CAAK,IAGzB,KAAK,QAAQ,IAAIA,GAAO;AAAA,MACtB,OAAAA;AAAA,MACA,MAAM;AAAA,MACN,UAAU;AAAA,MACV,OAAO6M;AAAA,IAAA,CACR,GAGH,KAAK,qBAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKQ,gBAAgB7M,GAAe8M,GAAmC/M,GAAegN,GAAwB;AAC/G,SAAK,QAAQ,IAAI/M,GAAO;AAAA,MACtB,OAAAA;AAAA,MACA,MAAM;AAAA,MACN,UAAA8M;AAAA,MACA,OAAA/M;AAAA,MACA,SAAAgN;AAAA,IAAA,CACD,GAED,KAAK,qBAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKQ,uBAA6B;AACnC,SAAK,eAAe,MACpB,KAAK,WAAW;AAEhB,UAAMb,IAAa,CAAC,GAAG,KAAK,QAAQ,QAAQ;AAG5C,QAAI,KAAK,OAAO,eAAe;AAC7B,YAAMpF,IAAS,KAAK;AACpB,MAAAA,EAAO,aAAa,aAAa,MAAM;AAEvC,YAAM1D,IAAS,KAAK,OAAO,cAAc8I,GAAY,KAAK,UAAuB,GAG3EoD,IAAe,CAAC9O,MAAoB;AACxC,QAAAsG,EAAO,gBAAgB,WAAW,GAClC,KAAK,eAAetG,GAGnB,KAAK,KAAwC,OAAOA,GAErD,KAAK,KAAyB,iBAAiB;AAAA,UAC7C,SAAS0L;AAAA,UACT,kBAAkB1L,EAAK;AAAA,QAAA,CACxB,GAGD,KAAK,cAAA;AAAA,MACP;AAEA,MAAI4C,KAAU,OAAQA,EAA8B,QAAS,aAC1DA,EAA8B,KAAKkM,CAAY,IAEhDA,EAAalM,CAAmB;AAElC;AAAA,IACF;AAGA,SAAK,KAAyB,iBAAiB;AAAA,MAC7C,SAAS8I;AAAA,MACT,kBAAkB;AAAA,IAAA,CACnB,GACD,KAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQS,eAAelM,GAAiD;AACvE,UAAMuP,IAAc,KAAK,QAAQ,IAAIvP,CAAK;AAC1C,QAAKuP;AAEL,aAAO;AAAA,QACL,QAAQ;AAAA,UACN,MAAMA,EAAY;AAAA,UAClB,UAAUA,EAAY;AAAA,UACtB,OAAOA,EAAY;AAAA,UACnB,SAASA,EAAY;AAAA,QAAA;AAAA,MACvB;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA,EAKS,iBAAiBvP,GAAewP,GAA0B;AAEjE,QAAI,CAACA,EAAM,QAAQ;AACjB,WAAK,QAAQ,OAAOxP,CAAK;AACzB;AAAA,IACF;AAGA,UAAMuP,IAA2B;AAAA,MAC/B,OAAAvP;AAAA,MACA,MAAMwP,EAAM,OAAO;AAAA,MACnB,UAAUA,EAAM,OAAO;AAAA,MACvB,OAAOA,EAAM,OAAO;AAAA,MACpB,SAASA,EAAM,OAAO;AAAA,IAAA;AAGxB,SAAK,QAAQ,IAAIxP,GAAOuP,CAAW,GAEnC,KAAK,eAAe,MACpB,KAAK,WAAW;AAAA,EAClB;AAAA;AAAA;AAAA,EAKkB,SAASE;AAAAA;AAE7B;AC/zBO,SAASC,GAAuBjP,GAA8C;AACnF,MAAI,CAACA,EAAQ,OAAQ,QAAO,CAAA;AAE5B,QAAMkP,wBAAkB,IAAA,GAClBC,IAA0C,CAAA,GAG1CC,IAAe,CAACC,GAAkBC,MAA4B;AAClE,QAAI,CAACA,EAAK,OAAQ;AAElB,UAAMC,IAAOJ,EAAcA,EAAc,SAAS,CAAC;AACnD,QAAII,KAAQA,EAAK,YAAYA,EAAK,aAAaA,EAAK,QAAQ,WAAWF,GAAU;AAC/E,MAAAE,EAAK,QAAQ,KAAK,GAAGD,CAAI;AACzB;AAAA,IACF;AACA,IAAAH,EAAc,KAAK;AAAA,MACjB,IAAI,iBAAiBE;AAAA,MACrB,OAAO;AAAA,MACP,SAASC;AAAA,MACT,YAAYD;AAAA,MACZ,UAAU;AAAA,IAAA,CACX;AAAA,EACH;AAEA,MAAIG,IAAyB,CAAA,GACzBC,IAAW;AAiCf,SA/BAzP,EAAQ,QAAQ,CAACY,GAAKF,MAAQ;AAC5B,UAAMgP,IAAU9O,EAAY;AAC5B,QAAI,CAAC8O,GAAG;AACN,MAAIF,EAAI,WAAW,MAAGC,IAAW/O,IACjC8O,EAAI,KAAK5O,CAAG;AACZ;AAAA,IACF;AAEA,IAAI4O,EAAI,WACNJ,EAAaK,GAAUD,EAAI,OAAO,GAClCA,IAAM,CAAA;AAER,UAAMG,IAAK,OAAOD,KAAM,WAAWA,IAAIA,EAAE;AACzC,QAAIE,IAAQV,EAAY,IAAIS,CAAE;AAC9B,IAAKC,MACHA,IAAQ;AAAA,MACN,IAAAD;AAAA,MACA,OAAO,OAAOD,KAAM,WAAW,SAAYA,EAAE;AAAA,MAC7C,SAAS,CAAA;AAAA,MACT,YAAYhP;AAAA,IAAA,GAEdwO,EAAY,IAAIS,GAAIC,CAAK,GACzBT,EAAc,KAAKS,CAAK,IAE1BA,EAAM,QAAQ,KAAKhP,CAAG;AAAA,EACxB,CAAC,GAGG4O,EAAI,UAAQJ,EAAaK,GAAUD,CAAG,GAIxCL,EAAc,WAAW,KACzBA,EAAc,CAAC,EAAE,YACjBA,EAAc,CAAC,EAAE,QAAQ,WAAWnP,EAAQ,SAErC,CAAA,IAGFmP;AACT;AASO,SAASU,GACdC,GACAC,GACA/P,GACM;AACN,MAAI,CAAC+P,EAAO,UAAU,CAACD,EAAa;AAEpC,QAAME,wBAAmB,IAAA;AACzB,aAAWN,KAAKK;AACd,eAAW5P,KAAKuP,EAAE;AAChB,MAAKvP,GAAW,SACd6P,EAAa,IAAK7P,EAAU,OAAOuP,EAAE,EAAE;AAK7C,QAAMrP,IAAc,MAAM,KAAKyP,EAAY,iBAAiB,mBAAmB,CAAC;AAChF,EAAAzP,EAAY,QAAQ,CAACwC,MAAS;AAC5B,UAAMuI,IAAIvI,EAAK,aAAa,YAAY,KAAK,IACvCoN,IAAMD,EAAa,IAAI5E,CAAC;AAC9B,IAAI6E,MACFpN,EAAK,UAAU,IAAI,SAAS,GACvBA,EAAK,aAAa,YAAY,KACjCA,EAAK,aAAa,cAAcoN,CAAG;AAAA,EAGzC,CAAC;AAGD,aAAWP,KAAKK,GAAQ;AACtB,UAAMG,IAAOR,EAAE,QAAQA,EAAE,QAAQ,SAAS,CAAC,GACrC7M,IAAOxC,EAAY,KAAK,CAACF,MAAMA,EAAE,aAAa,YAAY,MAAO+P,EAAa,KAAK;AACzF,IAAIrN,KAAMA,EAAK,UAAU,IAAI,WAAW;AAAA,EAC1C;AACF;AASO,SAASsN,GACdJ,GACA/P,GACoB;AACpB,MAAI+P,EAAO,WAAW,EAAG,QAAO;AAEhC,QAAMK,IAAW,SAAS,cAAc,KAAK;AAC7C,EAAAA,EAAS,YAAY,oBACrBA,EAAS,aAAa,QAAQ,KAAK;AAEnC,aAAWV,KAAKK,GAAQ;AACtB,UAAMM,IACJX,EAAE,cAAc,OACZA,EAAE,aACF1P,EAAQ,UAAU,CAACG,MAAOuP,EAAE,QAAkB,SAASvP,CAAC,CAAC,GAEzDmQ,IAAa,OAAOZ,EAAE,EAAE,EAAE,WAAW,cAAc,GACnDvI,IAAQmJ,IAAa,KAAKZ,EAAE,SAASA,EAAE,IAEvC7M,IAAO,SAAS,cAAc,KAAK;AACzC,IAAAA,EAAK,YAAY,0BACbyN,KAAYzN,EAAK,UAAU,IAAI,gBAAgB,GACnDA,EAAK,aAAa,cAAc,OAAO6M,EAAE,EAAE,CAAC,GAC5C7M,EAAK,MAAM,aAAa,GAAGwN,IAAa,CAAC,WAAWX,EAAE,QAAQ,MAAM,IACpE7M,EAAK,cAAcsE,GACnBiJ,EAAS,YAAYvN,CAAI;AAAA,EAC3B;AAEA,SAAOuN;AACT;AAQO,SAASG,GAAgBvQ,GAAuC;AACrE,SAAOA,EAAQ,KAAK,CAACY,MAASA,EAAY,SAAS,IAAI;AACzD;;AClJO,MAAM4P,WAA8B9O,EAAsC;AAAA,EACtE,OAAO;AAAA,EACE,UAAU;AAAA,EAE5B,IAAuB,gBAAgD;AACrE,WAAO;AAAA,MACL,kBAAkB;AAAA,IAAA;AAAA,EAEtB;AAAA;AAAA,EAGQ,SAAwB,CAAA;AAAA,EACxB,WAAW;AAAA;AAAA;AAAA,EAKV,SAAe;AACtB,SAAK,SAAS,CAAA,GACd,KAAK,WAAW;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAO,OAAO3B,GAAsBN,GAAsB;AAExD,QAAIA,GAAQ,gBAAgB,MAAM,QAAQA,EAAO,YAAY,KAAKA,EAAO,aAAa,SAAS;AAC7F,aAAO;AAGT,UAAMO,IAAUP,GAAQ;AACxB,WAAK,MAAM,QAAQO,CAAO,IACnBuQ,GAAgBvQ,CAAO,IADM;AAAA,EAEtC;AAAA;AAAA;AAAA,EAKS,eAAeA,GAAkD;AAExE,UAAMyQ,IAAe,KAAK,MAAM,YAAY;AAC5C,QAAIC;AAEJ,QAAID,KAAgB,MAAM,QAAQA,CAAY,KAAKA,EAAa,SAAS,GAAG;AAE1E,YAAMT,wBAAmB,IAAA;AACzB,iBAAWJ,KAASa;AAClB,mBAAWlR,KAASqQ,EAAM;AACxB,UAAAI,EAAa,IAAIzQ,GAAO,EAAE,IAAIqQ,EAAM,IAAI,OAAOA,EAAM,QAAQ;AAKjE,MAAAc,IAAmB1Q,EAAQ,IAAI,CAACY,MAAQ;AACtC,cAAM+P,IAAYX,EAAa,IAAIpP,EAAI,KAAK;AAC5C,eAAI+P,KAAa,CAAC/P,EAAI,QACb,EAAE,GAAGA,GAAK,OAAO+P,EAAA,IAEnB/P;AAAA,MACT,CAAC;AAAA,IACH;AACE,MAAA8P,IAAmB,CAAC,GAAG1Q,CAAO;AAIhC,UAAM+P,IAASd,GAAoByB,CAAgB;AAEnD,WAAIX,EAAO,WAAW,KACpB,KAAK,WAAW,IAChB,KAAK,SAAS,CAAA,GACPW,MAGT,KAAK,WAAW,IAChB,KAAK,SAASX,GAGPW;AAAA,EACT;AAAA,EAES,cAAoB;AAC3B,QAAI,CAAC,KAAK,YAAY,KAAK,OAAO,WAAW,GAAG;AAG9C,YAAME,IADS,KAAK,YAAY,cAAc,SAAS,GACtB,cAAc,mBAAmB;AAClE,MAAIA,KAAkBA,EAAiB,OAAA;AACvC;AAAA,IACF;AAEA,UAAMtQ,IAAS,KAAK,YAAY,cAAc,SAAS;AACvD,QAAI,CAACA,EAAQ;AAGb,UAAMsQ,IAAmBtQ,EAAO,cAAc,mBAAmB;AACjE,IAAIsQ,OAAmC,OAAA;AAGvC,UAAMR,IAAWD,GAAoB,KAAK,QAAQ,KAAK,OAAyB;AAChF,QAAIC,GAAU;AAEZ,MAAAA,EAAS,UAAU,OAAO,cAAc,CAAC,KAAK,OAAO,gBAAgB;AAErE,YAAMnK,IAAY3F,EAAO,cAAc,aAAa;AACpD,MAAI2F,IACF3F,EAAO,aAAa8P,GAAUnK,CAAS,IAEvC3F,EAAO,YAAY8P,CAAQ;AAAA,IAE/B;AAGA,UAAMnK,IAAY3F,EAAO,cAAc,aAAa;AACpD,IAAI2F,MAEFA,EAAU,UAAU,OAAO,oBAAoB,CAAC,KAAK,OAAO,gBAAgB,GAC5E4J,GAA8B5J,GAAW,KAAK,QAAQ,KAAK,OAAyB;AAAA,EAExF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,mBAA4B;AAC1B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAA2B;AACzB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,gBAAgB4K,GAAiC;AAC/C,UAAMjB,IAAQ,KAAK,OAAO,KAAK,CAACF,MAAMA,EAAE,OAAOmB,CAAO;AACtD,WAAOjB,IAAQA,EAAM,UAAU,CAAA;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKA,UAAgB;AACd,SAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA,EAKkB,SAASZ;AAAAA;AAE7B;AChKO,SAAS8B,GAAqB,EAAE,MAAA/Q,GAAM,QAAAN,GAAQ,UAAAsR,KAA4C;AAC/F,QAAMC,IAAUvR,EAAO;AACvB,MAAI,OAAOuR,KAAY;AACrB,WAAO,CAAA;AAGT,QAAMC,IAAkB,EAAE,KAAK,YAAY,OAAO,MAAM,OAAO,IAAI,MAAM,CAAA,GAAI,UAAU,oBAAI,MAAI;AAuB/F,MApBAlR,EAAK,QAAQ,CAACkE,MAAM;AAClB,QAAIiN,IAAYF,EAAQ/M,CAAC;AACzB,IAAIiN,KAAQ,QAAQA,MAAS,KAAOA,IAAO,CAAC,eAAe,IACjD,MAAM,QAAQA,CAAI,MAAGA,IAAO,CAACA,CAAI;AAE3C,QAAIC,IAASF;AACb,IAAAC,EAAK,QAAQ,CAACE,GAAaC,MAAqB;AAC9C,YAAMC,IAAMF,KAAU,OAAO,MAAM,OAAOA,CAAM,GAC1CG,IAAYJ,EAAO,QAAQ,aAAaG,IAAMH,EAAO,MAAM,OAAOG;AACxE,UAAIE,IAAOL,EAAO,SAAS,IAAIG,CAAG;AAClC,MAAKE,MACHA,IAAO,EAAE,KAAKD,GAAW,OAAOH,GAAQ,OAAOC,GAAU,MAAM,CAAA,GAAI,UAAU,oBAAI,IAAA,GAAO,QAAAF,EAAA,GACxFA,EAAO,SAAS,IAAIG,GAAKE,CAAI,IAE/BL,IAASK;AAAA,IACX,CAAC,GACDL,EAAO,KAAK,KAAKlN,CAAC;AAAA,EACpB,CAAC,GAGGgN,EAAK,SAAS,SAAS,KAAKA,EAAK,SAAS,IAAI,eAAe,KAClDA,EAAK,SAAS,IAAI,eAAe,EACrC,KAAK,WAAWlR,EAAK;WAAe,CAAA;AAI/C,QAAM0R,IAAoB,CAAA,GACpBC,IAAQ,CAACF,MAAoB;AACjC,QAAIA,MAASP,GAAM;AACjB,MAAAO,EAAK,SAAS,QAAQ,CAACrR,MAAMuR,EAAMvR,CAAC,CAAC;AACrC;AAAA,IACF;AAEA,UAAMwR,IAAaZ,EAAS,IAAIS,EAAK,GAAG;AACxC,IAAAC,EAAK,KAAK;AAAA,MACR,MAAM;AAAA,MACN,KAAKD,EAAK;AAAA,MACV,OAAOA,EAAK;AAAA,MACZ,OAAOA,EAAK;AAAA,MACZ,MAAMA,EAAK;AAAA,MACX,UAAUG;AAAA,IAAA,CACX,GAEGA,MACEH,EAAK,SAAS,OAChBA,EAAK,SAAS,QAAQ,CAACrR,MAAMuR,EAAMvR,CAAC,CAAC,IAErCqR,EAAK,KAAK,QAAQ,CAACvN,MAAMwN,EAAK,KAAK,EAAE,MAAM,QAAQ,KAAKxN,GAAG,UAAUlE,EAAK,QAAQkE,CAAC,EAAA,CAAG,CAAC;AAAA,EAG7F;AACA,SAAAyN,EAAMT,CAAI,GAEHQ;AACT;AASO,SAASG,GAAqBC,GAA2BtE,GAA0B;AACxF,QAAMuE,IAAS,IAAI,IAAID,CAAY;AACnC,SAAIC,EAAO,IAAIvE,CAAG,IAChBuE,EAAO,OAAOvE,CAAG,IAEjBuE,EAAO,IAAIvE,CAAG,GAETuE;AACT;AAQO,SAASC,GAAgBhS,GAAgC;AAC9D,QAAMiS,wBAAW,IAAA;AACjB,aAAWxS,KAAOO;AAChB,IAAIP,EAAI,SAAS,WACfwS,EAAK,IAAIxS,EAAI,GAAG;AAGpB,SAAOwS;AACT;AAOO,SAASC,KAAiC;AAC/C,6BAAW,IAAA;AACb;AAkBO,SAASC,GAAiB9B,GAA6B;AAC5D,SAAIA,EAAS,SAAS,UAAgB,IAC/BA,EAAS,KAAK;AACvB;;ACvGO,MAAM+B,WAA2BzQ,EAAmC;AAAA,EAChE,OAAO;AAAA,EACE,UAAU;AAAA,EAE5B,IAAuB,gBAA6C;AAClE,WAAO;AAAA,MACL,iBAAiB;AAAA,MACjB,cAAc;AAAA,MACd,aAAa;AAAA,MACb,aAAa,CAAA;AAAA,MACb,WAAW;AAAA,IAAA;AAAA,EAEf;AAAA;AAAA,EAGQ,mCAAgC,IAAA;AAAA,EAChC,gBAA6B,CAAA;AAAA,EAC7B,WAAW;AAAA,EACX,0CAA0B,IAAA;AAAA,EAC1B,oCAAoB,IAAA;AAAA;AAAA;AAAA,EAK5B,IAAY,iBAA0C;AAEpD,UAAM0Q,IADS,KAAK,KACA,iBAAiB,WAAW,QAAQ;AAExD,QAAIA,MAAS,MAASA,MAAS,MAAO,QAAO;AAC7C,QAAIA,MAAS,MAAQA,MAAS,MAAM;AAClC,YAAMC,IAAO,KAAK,YAAY;AAC9B,UAAIA,KAAQ,iBAAiBA,CAAI,EAAE,iBAAiB,yBAAyB,EAAE,KAAA,MAAW;AACxF,eAAO;AAAA,IAEX;AACA,WAAO,KAAK,OAAO,aAAa;AAAA,EAClC;AAAA;AAAA;AAAA,EAMS,SAAe;AACtB,SAAK,aAAa,MAAA,GAClB,KAAK,gBAAgB,CAAA,GACrB,KAAK,WAAW,IAChB,KAAK,oBAAoB,MAAA,GACzB,KAAK,cAAc,MAAA;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAO,OAAOtS,GAAsBN,GAAsB;AACxD,WAAO,OAAOA,GAAQ,WAAY,cAAc,OAAOA,GAAQ,qBAAsB;AAAA,EACvF;AAAA,EAES,YAAYM,GAA6B;AAChD,UAAMN,IAAS,KAAK;AAGpB,QAAI,OAAOA,EAAO,WAAY;AAC5B,kBAAK,WAAW,IAChB,KAAK,gBAAgB,CAAA,GACd,CAAC,GAAGM,CAAI;AAIjB,UAAMuS,IAAUxB,GAAqB;AAAA,MACnC,MAAA/Q;AAAA,MACA,QAAAN;AAAA,MACA,UAAU,KAAK;AAAA,IAAA,CAChB;AAGD,QAAI6S,EAAQ,WAAW;AACrB,kBAAK,WAAW,IAChB,KAAK,gBAAgB,CAAA,GACd,CAAC,GAAGvS,CAAI;AAGjB,SAAK,WAAW,IAChB,KAAK,gBAAgBuS,GAGrB,KAAK,cAAc,MAAA;AACnB,UAAMC,wBAAyB,IAAA;AAC/B,WAAAD,EAAQ,QAAQ,CAAC9L,GAAM9F,MAAQ;AAC7B,UAAI8F,EAAK,SAAS,QAAQ;AACxB,cAAM+G,IAAM,QAAQ7M,CAAG;AACvB,QAAA6R,EAAmB,IAAIhF,CAAG,GACrB,KAAK,oBAAoB,IAAIA,CAAG,KACnC,KAAK,cAAc,IAAIA,CAAG;AAAA,MAE9B;AAAA,IACF,CAAC,GACD,KAAK,sBAAsBgF,GAIpBD,EAAQ,IAAI,CAAC9L,MACdA,EAAK,SAAS,UACT;AAAA,MACL,cAAc;AAAA,MACd,YAAYA,EAAK;AAAA,MACjB,cAAcA,EAAK;AAAA,MACnB,cAAcA,EAAK;AAAA,MACnB,aAAaA,EAAK;AAAA,MAClB,iBAAiBA,EAAK;AAAA,MACtB,iBAAiB0L,GAAiB1L,CAAI;AAAA,IAAA,IAGnCA,EAAK,GACb;AAAA,EACH;AAAA,EAES,YAAY7E,GAAuC;AAC1D,UAAMnC,IAAMmC,EAAM;AAGlB,QAAInC,GAAK,gBACQmC,EAAM,cAAc,QACvB,QAAQ,eAAe;AACjC,kBAAK,OAAOnC,EAAI,UAAoB,GAC7B;AAAA,EAGb;AAAA;AAAA;AAAA;AAAA,EAKS,UAAUA,GAAUgT,GAAoBC,GAA4B;AAE3E,QAAI,CAACjT,GAAK;AACR,aAAO;AAGT,UAAMC,IAAS,KAAK;AAGpB,QAAIA,EAAO,kBAAkB;AAC3B,YAAMiT,IAAe,MAAM;AACzB,aAAK,OAAOlT,EAAI,UAAU;AAAA,MAC5B,GAEMmD,IAASlD,EAAO,iBAAiB;AAAA,QACrC,KAAKD,EAAI;AAAA,QACT,OAAOA,EAAI;AAAA,QACX,OAAOA,EAAI;AAAA,QACX,MAAMA,EAAI;AAAA,QACV,UAAUA,EAAI;AAAA,QACd,cAAAkT;AAAA,MAAA,CACD;AAED,UAAI/P;AACF,eAAA6P,EAAM,YAAY,aACjBA,EAAc,gBAAgB,IAC/BA,EAAM,aAAa,oBAAoB,OAAOhT,EAAI,YAAY,CAAC,GAC3D,OAAOmD,KAAW,WACpB6P,EAAM,YAAY7P,KAElB6P,EAAM,YAAY,IAClBA,EAAM,YAAY7P,CAAM,IAEnB;AAAA,IAEX;AAGA,UAAMgQ,IAAe,MAAM;AACzB,WAAK,OAAOnT,EAAI,UAAU;AAAA,IAC5B;AAGA,WAAAgT,EAAM,YAAY,aACjBA,EAAc,gBAAgB,IAC/BA,EAAM,aAAa,oBAAoB,OAAOhT,EAAI,YAAY,CAAC,GAC/DgT,EAAM,aAAa,QAAQ,KAAK,GAChCA,EAAM,aAAa,iBAAiB,OAAOhT,EAAI,eAAe,CAAC,GAC/DgT,EAAM,MAAM,cAAc,IAAIhT,EAAI,gBAAgB,MAAMC,EAAO,eAAe,GAAG,MACjF+S,EAAM,YAAY,IAEE/S,EAAO,cAAc,KAGvC,KAAK,wBAAwBD,GAAKgT,GAAOG,CAAY,IAErD,KAAK,wBAAwBnT,GAAKgT,GAAOG,CAAY,GAGhD;AAAA,EACT;AAAA,EAES,cAAoB;AAC3B,UAAM9G,IAAQ,KAAK;AACnB,QAAIA,MAAU,MAAS,KAAK,cAAc,SAAS,EAAG;AAEtD,UAAM+G,IAAO,KAAK,YAAY,cAAc,OAAO;AACnD,QAAI,CAACA,EAAM;AAEX,UAAMC,IAAYhH,MAAU,SAAS,sBAAsB;AAC3D,eAAW2G,KAASI,EAAK,iBAAiB,gCAAgC,GAAG;AAC3E,YAAM/P,IAAO2P,EAAM,cAAc,iBAAiB,GAC5C9R,IAAMmC,IAAO,SAASA,EAAK,aAAa,UAAU,KAAK,MAAM,EAAE,IAAI,IAEnE0K,IADO,KAAK,cAAc7M,CAAG,GACjB,SAAS,SAAS,QAAQA,CAAG,KAAK;AAEpD,MAAI6M,KAAO,KAAK,cAAc,IAAIA,CAAG,MACnCiF,EAAM,UAAU,IAAIK,CAAS,GAC7BL,EAAM,iBAAiB,gBAAgB,MAAMA,EAAM,UAAU,OAAOK,CAAS,GAAG,EAAE,MAAM,GAAA,CAAM;AAAA,IAElG;AACA,SAAK,cAAc,MAAA;AAAA,EACrB;AAAA;AAAA;AAAA,EAKQ,wBAAwBrT,GAAUgT,GAAoBG,GAAgC;AAC5F,UAAMlT,IAAS,KAAK,QAGdoD,IAAO,SAAS,cAAc,KAAK;AACzC,IAAAA,EAAK,YAAY,mBACjBA,EAAK,MAAM,aAAa,UACxBA,EAAK,aAAa,QAAQ,UAAU;AAGpC,UAAMiQ,IAAM,SAAS,cAAc,QAAQ;AAC3C,IAAAA,EAAI,OAAO,UACXA,EAAI,YAAY,eAAetT,EAAI,kBAAkB,cAAc,EAAE,IACrEsT,EAAI,aAAa,cAActT,EAAI,kBAAkB,mBAAmB,cAAc,GACtF,KAAK,QAAQsT,GAAK,KAAK,YAAYtT,EAAI,kBAAkB,aAAa,QAAQ,CAAC,GAC/EsT,EAAI,iBAAiB,SAAS,CAACtL,MAAM;AACnC,MAAAA,EAAE,gBAAA,GACFmL,EAAA;AAAA,IACF,CAAC,GACD9P,EAAK,YAAYiQ,CAAG;AAGpB,UAAM3L,IAAQ,SAAS,cAAc,MAAM;AAC3C,IAAAA,EAAM,YAAY;AAClB,UAAM4L,IAAYtT,EAAO,cACrBA,EAAO,YAAYD,EAAI,cAAcA,EAAI,gBAAgB,GAAGA,EAAI,UAAU,IAC1E,OAAOA,EAAI,YAAY;AAK3B,QAJA2H,EAAM,cAAc4L,GACpBlQ,EAAK,YAAYsE,CAAK,GAGlB1H,EAAO,iBAAiB,IAAO;AACjC,YAAMuT,IAAQ,SAAS,cAAc,MAAM;AAC3C,MAAAA,EAAM,YAAY,eAClBA,EAAM,cAAc,IAAIxT,EAAI,mBAAmBA,EAAI,aAAa,UAAU,CAAC,KAC3EqD,EAAK,YAAYmQ,CAAK;AAAA,IACxB;AAEA,IAAAR,EAAM,YAAY3P,CAAI;AAAA,EACxB;AAAA,EAEQ,wBAAwBrD,GAAUgT,GAAoBG,GAAgC;AAC5F,UAAMlT,IAAS,KAAK,QACdwT,IAAcxT,EAAO,eAAe,CAAA,GACpCO,IAAU,KAAK,SACfkT,IAAY1T,EAAI,eAAe,CAAA,GAI/B2T,IADS,KAAK,YAAY,cAAc,OAAO,GACxB,MAAM,uBAAuB;AAC1D,IAAIA,MACFX,EAAM,MAAM,UAAU,QACtBA,EAAM,MAAM,sBAAsBW,IAGpCnT,EAAQ,QAAQ,CAACY,GAAKwS,MAAW;AAC/B,YAAMvQ,IAAO,SAAS,cAAc,KAAK;AAKzC,UAJAA,EAAK,YAAY,mBACjBA,EAAK,aAAa,YAAY,OAAOuQ,CAAM,CAAC,GAC5CvQ,EAAK,aAAa,QAAQ,UAAU,GAEhCuQ,MAAW,GAAG;AAEhB,cAAMN,IAAM,SAAS,cAAc,QAAQ;AAC3C,QAAAA,EAAI,OAAO,UACXA,EAAI,YAAY,eAAetT,EAAI,kBAAkB,cAAc,EAAE,IACrEsT,EAAI,aAAa,cAActT,EAAI,kBAAkB,mBAAmB,cAAc,GACtF,KAAK,QAAQsT,GAAK,KAAK,YAAYtT,EAAI,kBAAkB,aAAa,QAAQ,CAAC,GAC/EsT,EAAI,iBAAiB,SAAS,CAACtL,MAAM;AACnC,UAAAA,EAAE,gBAAA,GACFmL,EAAA;AAAA,QACF,CAAC,GACD9P,EAAK,YAAYiQ,CAAG;AAEpB,cAAM3L,IAAQ,SAAS,cAAc,MAAM,GACrCkM,IAAcJ,EAAYrS,EAAI,KAAK;AACzC,YAAIyS,GAAa;AACf,gBAAMC,IAAYC,GAAcF,GAAaH,GAAWtS,EAAI,OAAOA,CAAG;AACtE,UAAAuG,EAAM,cAAcmM,KAAa,OAAO,OAAOA,CAAS,IAAI,OAAO9T,EAAI,YAAY;AAAA,QACrF,OAAO;AACL,gBAAMuT,IAAYtT,EAAO,cACrBA,EAAO,YAAYD,EAAI,cAAcA,EAAI,gBAAgB,GAAGA,EAAI,UAAU,IAC1E,OAAOA,EAAI,YAAY;AAC3B,UAAA2H,EAAM,cAAc4L;AAAA,QACtB;AAGA,YAFAlQ,EAAK,YAAYsE,CAAK,GAElB1H,EAAO,iBAAiB,IAAO;AACjC,gBAAMuT,IAAQ,SAAS,cAAc,MAAM;AAC3C,UAAAA,EAAM,YAAY,eAClBA,EAAM,cAAc,KAAKE,EAAU,MAAM,KACzCrQ,EAAK,YAAYmQ,CAAK;AAAA,QACxB;AAAA,MACF,OAAO;AAEL,cAAMQ,IAASP,EAAYrS,EAAI,KAAK;AACpC,YAAI4S,GAAQ;AACV,gBAAM7Q,IAAS4Q,GAAcC,GAAQN,GAAWtS,EAAI,OAAOA,CAAG;AAC9D,UAAAiC,EAAK,cAAcF,KAAU,OAAO,OAAOA,CAAM,IAAI;AAAA,QACvD;AACE,UAAAE,EAAK,cAAc;AAAA,MAEvB;AAEA,MAAA2P,EAAM,YAAY3P,CAAI;AAAA,IACxB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,YAAkB;AAChB,SAAK,eAAekP,GAAgB,KAAK,aAAa,GACtD,KAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKA,cAAoB;AAClB,SAAK,eAAeE,GAAA,GACpB,KAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO1E,GAAmB;AACxB,SAAK,eAAeqE,GAAqB,KAAK,cAAcrE,CAAG;AAG/D,UAAMqC,IAAQ,KAAK,cAAc,KAAK,CAAC3L,MAAMA,EAAE,SAAS,WAAWA,EAAE,QAAQsJ,CAAG;AAEhF,SAAK,KAAwB,gBAAgB;AAAA,MAC3C,KAAAA;AAAA,MACA,UAAU,KAAK,aAAa,IAAIA,CAAG;AAAA,MACnC,OAAOqC,GAAO;AAAA,MACd,OAAOA,GAAO,SAAS;AAAA,IAAA,CACxB,GAED,KAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAAWrC,GAAsB;AAC/B,WAAO,KAAK,aAAa,IAAIA,CAAG;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAOA,GAAmB;AACxB,IAAK,KAAK,aAAa,IAAIA,CAAG,MAC5B,KAAK,mCAAmB,IAAI,CAAC,GAAG,KAAK,cAAcA,CAAG,CAAC,GACvD,KAAK,cAAA;AAAA,EAET;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,SAASA,GAAmB;AAC1B,QAAI,KAAK,aAAa,IAAIA,CAAG,GAAG;AAC9B,YAAMkG,IAAU,IAAI,IAAI,KAAK,YAAY;AACzC,MAAAA,EAAQ,OAAOlG,CAAG,GAClB,KAAK,eAAekG,GACpB,KAAK,cAAA;AAAA,IACP;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAA4B;AAC1B,UAAMP,IAAY,KAAK,cAAc,OAAO,CAACjP,MAAMA,EAAE,SAAS,OAAO;AACrE,WAAO;AAAA,MACL,UAAU,KAAK;AAAA,MACf,eAAe,KAAK,aAAa;AAAA,MACjC,aAAaiP,EAAU;AAAA,MACvB,cAAc,CAAC,GAAG,KAAK,YAAY;AAAA,IAAA;AAAA,EAEvC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cAAsB;AACpB,WAAO,KAAK,cAAc;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAsB;AACpB,SAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,oBAA8B;AAC5B,WAAO,CAAC,GAAG,KAAK,YAAY;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,mBAAgC;AAC9B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,mBAA4B;AAC1B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,WAAWQ,GAAkE;AAC1E,SAAK,OAA8B,UAAUA,GAC9C,KAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA,EAKkB,SAAS1E;AAAAA;AAE7B;ACpgBO,SAAS2E,EAAgBC,GAA2BpU,GAA0B;AACnF,QAAMqU,IAAc,IAAI,IAAID,CAAY;AACxC,SAAIC,EAAY,IAAIrU,CAAG,IACrBqU,EAAY,OAAOrU,CAAG,IAEtBqU,EAAY,IAAIrU,CAAG,GAEdqU;AACT;AAMO,SAASC,GAAgBF,GAA2BpU,GAA0B;AACnF,QAAMqU,IAAc,IAAI,IAAID,CAAY;AACxC,SAAAC,EAAY,IAAIrU,CAAG,GACZqU;AACT;AAMO,SAASE,GAAkBH,GAA2BpU,GAA0B;AACrF,QAAMqU,IAAc,IAAI,IAAID,CAAY;AACxC,SAAAC,EAAY,OAAOrU,CAAG,GACfqU;AACT;AAKO,SAASG,GAAiBJ,GAA2BpU,GAAsB;AAChF,SAAOoU,EAAa,IAAIpU,CAAG;AAC7B;AAMO,SAASyU,GACdzU,GACA2D,GACA+Q,GACAzR,GACa;AACb,QAAM0R,IAAY,SAAS,cAAc,KAAK;AAC9C,EAAAA,EAAU,YAAY,qBACtBA,EAAU,aAAa,mBAAmB,OAAOhR,CAAQ,CAAC,GAC1DgR,EAAU,aAAa,QAAQ,KAAK;AAEpC,QAAMC,IAAa,SAAS,cAAc,KAAK;AAC/C,EAAAA,EAAW,YAAY,sBACvBA,EAAW,aAAa,QAAQ,MAAM,GACtCA,EAAW,MAAM,aAAa,OAAO3R,IAAc,CAAC;AAEpD,QAAM4G,IAAU6K,EAAS1U,GAAK2D,CAAQ;AACtC,SAAI,OAAOkG,KAAY,WACrB+K,EAAW,YAAY/K,IACdA,aAAmB,eAC5B+K,EAAW,YAAY/K,CAAO,GAGhC8K,EAAU,YAAYC,CAAU,GACzBD;AACT;;ACxCO,MAAME,WAA2B3S,EAAmC;AAAA,EAChE,OAAO;AAAA,EACE,UAAU;AAAA,EAE5B,IAAuB,gBAA6C;AAClE,WAAO;AAAA,MACL,cAAc;AAAA,MACd,kBAAkB;AAAA,MAClB,wBAAwB;AAAA,MACxB,kBAAkB;AAAA,MAClB,WAAW;AAAA;AAAA,IAAA;AAAA,EAEf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQS,OAAOuB,GAAyB;AACvC,UAAM,OAAOA,CAAI,GACjB,KAAK,oBAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwBQ,sBAA4B;AAClC,UAAMoD,IAAS,KAAK;AACpB,QAAI,CAACA,KAAU,OAAOA,EAAO,iBAAkB,WAAY;AAE3D,UAAMiO,IAAWjO,EAAO,cAAc,iBAAiB;AACvD,QAAI,CAACiO,EAAU;AAIf,UAAMC,IAAkBlO;AAKxB,QAAIkO,EAAgB,oBAAoB,oBAAoB;AAC1D,YAAMC,IAAkBD,EAAgB,mBAAmB,mBAAmBD,CAAQ;AACtF,UAAIE,GAAiB;AACnB,aAAK,SAAS,EAAE,GAAG,KAAK,QAAQ,gBAAgBA,EAAA;AAChD;AAAA,MACF;AAAA,IACF;AAGA,UAAMC,IAAYH,EAAS,aAAa,WAAW,GAC7CI,IAAmBJ,EAAS,aAAa,oBAAoB,GAC7DK,IAAmBL,EAAS,aAAa,qBAAqB,GAC9DM,IAAyBN,EAAS,aAAa,2BAA2B,GAC1EO,IAAaP,EAAS,aAAa,QAAQ,GAE3CQ,IAA6C,CAAA;AAEnD,IAAIL,MAAc,SAChBK,EAAc,YAAYL,MAAc,UAAU,KAASA,IAEzDC,MAAqB,SACvBI,EAAc,mBAAmBJ,MAAqB,UAEpDC,MAAqB,SACvBG,EAAc,mBAAmBH,MAAqB,SAEpDC,MAA2B,SAC7BE,EAAc,yBAAyBF,MAA2B,SAEhEC,MAAe,SACjBC,EAAc,eAAeD,MAAe,SAAS,SAAS,SAASA,GAAY,EAAE;AAIvF,UAAME,IAAeT,EAAS,UAAU,KAAA;AACxC,IAAIS,KAAgB,CAAC,KAAK,OAAO,mBAE/BD,EAAc,iBAAiB,CAACtV,GAAUiT,MAA8B;AAEtE,YAAMuC,IAAYC,GAAmBF,GAAc,EAAE,OAAOvV,GAAK,KAAAA,GAAK;AAEtE,aAAO0V,GAAaF,CAAS;AAAA,IAC/B,IAIE,OAAO,KAAKF,CAAa,EAAE,SAAS,MACtC,KAAK,SAAS,EAAE,GAAG,KAAK,QAAQ,GAAGA,EAAA;AAAA,EAEvC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,IAAY,qBAA8B;AAExC,UAAM1C,IADS,KAAK,KACA,iBAAiB,WAAW,QAAQ;AAExD,QAAIA,MAAS,MAASA,MAAS,MAAO,QAAO;AAC7C,QAAIA,MAAS,MAAQA,MAAS,KAAM,QAAO;AAG3C,UAAMC,IAAO,KAAK,YAAY;AAC9B,WAAIA,IACc,iBAAiBA,CAAI,EAAE,iBAAiB,yBAAyB,EAAE,KAAA,MAChE,MAEd;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,IAAY,iBAA0C;AACpD,WAAK,KAAK,qBACH,KAAK,OAAO,aAAa,UADK;AAAA,EAEvC;AAAA;AAAA;AAAA;AAAA,EAKA,IAAY,oBAA4B;AACtC,UAAMA,IAAO,KAAK,YAAY;AAC9B,QAAIA,GAAM;AACR,YAAM8C,IAAc,iBAAiB9C,CAAI,EAAE,iBAAiB,0BAA0B,EAAE,KAAA,GAClFrP,IAAS,SAASmS,GAAa,EAAE;AACvC,UAAI,CAAC,MAAMnS,CAAM,EAAG,QAAOA;AAAA,IAC7B;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,cAAcsR,GAA6B;AACjD,IAAI,CAAC,KAAK,sBAAsB,KAAK,mBAAmB,OAExDA,EAAS,UAAU,IAAI,eAAe,GACtCA,EAAS;AAAA,MACP;AAAA,MACA,MAAM;AACJ,QAAAA,EAAS,UAAU,OAAO,eAAe;AAAA,MAC3C;AAAA,MACA,EAAE,MAAM,GAAA;AAAA,IAAK;AAAA,EAEjB;AAAA;AAAA;AAAA;AAAA,EAKQ,gBAAgBA,GAAuBc,GAA8B;AAC3E,QAAI,CAAC,KAAK,sBAAsB,KAAK,mBAAmB,IAAO;AAC7D,MAAAA,EAAA;AACA;AAAA,IACF;AAEA,IAAAd,EAAS,UAAU,IAAI,gBAAgB;AACvC,UAAMe,IAAU,MAAM;AACpB,MAAAf,EAAS,UAAU,OAAO,gBAAgB,GAC1Cc,EAAA;AAAA,IACF;AACA,IAAAd,EAAS,iBAAiB,gBAAgBe,GAAS,EAAE,MAAM,IAAM,GAEjE,WAAWA,GAAS,KAAK,oBAAoB,EAAE;AAAA,EACjD;AAAA;AAAA;AAAA,EAKQ,mCAA6B,IAAA;AAAA,EAC7B,qCAA4C,IAAA;AAAA;AAAA;AAAA,EAK3C,SAAe;AACtB,SAAK,aAAa,MAAA,GAClB,KAAK,eAAe,MAAA;AAAA,EACtB;AAAA;AAAA;AAAA,EAKS,eAAerV,GAAkD;AACxE,QAAI,CAAC,KAAK,OAAO;AACf,aAAO,CAAC,GAAGA,CAAO;AAIpB,UAAMsP,IAAO,CAAC,GAAGtP,CAAO;AACxB,QAAIsP,EAAK,SAAS,GAAG;AACnB,YAAMgG,IAAW,EAAE,GAAGhG,EAAK,CAAC,EAAA,GACtBiG,IAAmBD,EAAS;AAGlC,UAAKC,GAA0B;AAC7B,eAAOjG;AAGT,YAAMkG,IAAkB,CAACC,MAAmE;AAC1F,cAAM,EAAE,OAAAnW,GAAO,KAAAE,EAAA,IAAQiW,GACjB9D,IAAa,KAAK,aAAa,IAAInS,CAAG,GAEtC+I,IAAY,SAAS,cAAc,MAAM;AAC/C,QAAAA,EAAU,YAAY;AAGtB,cAAMmN,IAAS,SAAS,cAAc,MAAM;AAC5C,QAAAA,EAAO,YAAY,uBAAuB/D,IAAa,cAAc,EAAE,IAEvE,KAAK,QAAQ+D,GAAQ,KAAK,YAAY/D,IAAa,aAAa,QAAQ,CAAC,GAEzE+D,EAAO,aAAa,QAAQ,QAAQ,GACpCA,EAAO,aAAa,YAAY,GAAG,GACnCA,EAAO,aAAa,iBAAiB,OAAO/D,CAAU,CAAC,GACvD+D,EAAO,aAAa,cAAc/D,IAAa,qBAAqB,gBAAgB,GACpF+D,EAAO,iBAAiB,SAAS,CAAClO,MAAM;AACtC,UAAAA,EAAE,gBAAA;AACF,gBAAMrE,IAAW,KAAK,KAAK,QAAQ3D,CAAG;AACtC,eAAK,eAAemU,EAAgB,KAAK,cAAcnU,CAAG,GAC1D,KAAK,KAAyB,iBAAiB;AAAA,YAC7C,UAAA2D;AAAA,YACA,KAAA3D;AAAA,YACA,UAAU,KAAK,aAAa,IAAIA,CAAG;AAAA,UAAA,CACpC,GACD,KAAK,cAAA;AAAA,QACP,CAAC,GACD+I,EAAU,YAAYmN,CAAM;AAG5B,cAAMrM,IAAU,SAAS,cAAc,MAAM;AAC7C,YAAIkM,GAAkB;AACpB,gBAAMI,IAAWJ,EAAiBE,CAAS;AAC3C,UAAIE,aAAoB,OACtBtM,EAAQ,YAAYsM,CAAQ,IAE5BtM,EAAQ,cAAc,OAAOsM,KAAYrW,KAAS,EAAE;AAAA,QAExD;AACE,UAAA+J,EAAQ,cAAc,OAAO/J,KAAS,EAAE;AAE1C,eAAAiJ,EAAU,YAAYc,CAAO,GAEtBd;AAAA,MACT;AAGC,MAAAiN,EAAwB,wBAAwB,IACjDF,EAAS,eAAeE,GAExBlG,EAAK,CAAC,IAAIgG;AAAA,IACZ;AAEA,WAAOhG;AAAA,EACT;AAAA,EAES,WAAW3N,GAAsC;AACxD,QAAI,GAAC,KAAK,OAAO,oBAAoB,CAAC,KAAK,OAAO;AAElD,kBAAK,eAAegS,EAAgB,KAAK,cAAchS,EAAM,GAAa,GAE1E,KAAK,KAAyB,iBAAiB;AAAA,QAC7C,UAAUA,EAAM;AAAA,QAChB,KAAKA,EAAM;AAAA,QACX,UAAU,KAAK,aAAa,IAAIA,EAAM,GAAa;AAAA,MAAA,CACpD,GAED,KAAK,cAAA,GACE;AAAA,EACT;AAAA,EAES,cAA8B;AAGrC,IAAI,KAAK,aAAa,OAAO,KAC3B,eAAe,MAAM,KAAKiU,IAAiB;AAAA,EAG/C;AAAA,EAES,cAAoB;AAC3B,SAAKA,GAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA,EAMS,iBAAuB;AAC9B,IAAI,CAAC,KAAK,OAAO,kBAAkB,KAAK,aAAa,SAAS,KAE9D,KAAKA,GAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA,EAMAA,KAAwB;AACtB,QAAI,CAAC,KAAK,OAAO,eAAgB;AAEjC,UAAMhD,IAAO,KAAK,YAAY,cAAc,OAAO;AACnD,QAAI,CAACA,EAAM;AAGX,UAAMiD,wBAAoB,IAAA,GACpBC,IAAWlD,EAAK,iBAAiB,gBAAgB,GACjDnQ,IAAc,KAAK,QAAQ;AAEjC,eAAW+P,KAASsD,GAAU;AAC5B,YAAMC,IAAYvD,EAAM,cAAc,iBAAiB,GACjDrP,IAAW4S,IAAY,SAASA,EAAU,aAAa,UAAU,KAAK,MAAM,EAAE,IAAI;AACxF,MAAI5S,KAAY,KACd0S,EAAc,IAAI1S,GAAUqP,CAAK;AAAA,IAErC;AAGA,UAAMwD,IAAkBpD,EAAK,iBAAiB,oBAAoB;AAClE,eAAW0B,KAAY0B,GAAiB;AACtC,YAAMC,IAAW,SAAS3B,EAAS,aAAa,iBAAiB,KAAK,MAAM,EAAE,GACxE9U,IAAMyW,KAAY,IAAI,KAAK,KAAKA,CAAQ,IAAI,QAC5CC,IAAkB1W,KAAO,KAAK,aAAa,IAAIA,CAAG,GAClD2W,IAAeN,EAAc,IAAII,CAAQ;AAG/C,OAAI,CAACC,KAAmB,CAACC,OACvB7B,EAAS,OAAA,GACL9U,KAAK,KAAK,eAAe,OAAOA,CAAG;AAAA,IAE3C;AAGA,eAAW,CAAC2D,GAAUqP,CAAK,KAAKqD,GAAe;AAC7C,YAAMrW,IAAM,KAAK,KAAK2D,CAAQ;AAC9B,UAAI,CAAC3D,KAAO,CAAC,KAAK,aAAa,IAAIA,CAAG,EAAG;AAGzC,YAAM4W,IAAiB,KAAK,eAAe,IAAI5W,CAAG;AAClD,UAAI4W,GAAgB;AAElB,QAAIA,EAAe,2BAA2B5D,KAC5CA,EAAM,MAAM4D,CAAc;AAE5B;AAAA,MACF;AAGA,YAAM9B,IAAWL,GAAoBzU,GAAK2D,GAAU,KAAK,OAAO,gBAAgBV,CAAW;AAE3F,MAAI,OAAO,KAAK,OAAO,gBAAiB,aACtC6R,EAAS,MAAM,SAAS,GAAG,KAAK,OAAO,YAAY,OAIrD9B,EAAM,MAAM8B,CAAQ,GACpB,KAAK,eAAe,IAAI9U,GAAK8U,CAAQ,GAGrC,KAAK,cAAcA,CAAQ;AAAA,IAC7B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMS,iBAAyB;AAChC,QAAI+B,IAAc;AAClB,eAAW7W,KAAO,KAAK,cAAc;AACnC,YAAM8U,IAAW,KAAK,eAAe,IAAI9U,CAAG;AAC5C,UAAI8U;AACF,QAAA+B,KAAe/B,EAAS;AAAA,WACnB;AAEL,cAAMgC,IAAe,KAAK,QAAQ;AAClC,QAAAD,KAAe,OAAOC,KAAiB,WAAWA,IAAe;AAAA,MACnE;AAAA,IACF;AACA,WAAOD;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMS,qBAAqBE,GAAgC;AAC5D,QAAIF,IAAc;AAClB,eAAW7W,KAAO,KAAK,cAAc;AACnC,YAAM2D,IAAW,KAAK,KAAK,QAAQ3D,CAAG;AAEtC,UAAI2D,KAAY,KAAKA,IAAWoT,GAAgB;AAC9C,cAAMjC,IAAW,KAAK,eAAe,IAAI9U,CAAG;AAC5C,YAAI8U;AACF,UAAA+B,KAAe/B,EAAS;AAAA,aACnB;AACL,gBAAMgC,IAAe,KAAK,QAAQ;AAClC,UAAAD,KAAe,OAAOC,KAAiB,WAAWA,IAAe;AAAA,QACnE;AAAA,MACF;AAAA,IACF;AACA,WAAOD;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMS,mBAAmB7L,GAAeH,GAAmBC,GAA2B;AACvF,QAAI,KAAK,aAAa,SAAS,EAAG,QAAOE;AAGzC,UAAMgM,IAAsD,CAAA;AAC5D,eAAWhX,KAAO,KAAK,cAAc;AACnC,YAAMsO,IAAQ,KAAK,KAAK,QAAQtO,CAAG;AACnC,MAAIsO,KAAS,KACX0I,EAAgB,KAAK,EAAE,OAAA1I,GAAO,KAAAtO,EAAA,CAAK;AAAA,IAEvC;AACA,IAAAgX,EAAgB,KAAK,CAAChW,GAAGC,MAAMD,EAAE,QAAQC,EAAE,KAAK;AAEhD,QAAIgW,IAAWjM,GAIXkM,IAAwB;AAE5B,eAAW,EAAE,OAAOvT,GAAU,KAAA3D,EAAA,KAASgX,GAAiB;AAEtD,YAAMG,IAAexT,IAAWmH,IAAYoM,GAEtCE,IADW,KAAK,eAAe,IAAIpX,CAAG,GAEhC,iBAAiB,OAAO,KAAK,QAAQ,gBAAiB,WAAW,KAAK,OAAO,eAAe,MAClGqX,IAAqBF,IAAerM,IAAYsM;AAMtD,MAHAF,KAAyBE,GAGrB,EAAAzT,KAAYqH,MAIZqM,IAAqBxM,KACnBlH,IAAWsT,MACbA,IAAWtT;AAAA,IAGjB;AAEA,WAAOsT;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAOtT,GAAwB;AAC7B,UAAM3D,IAAM,KAAK,KAAK2D,CAAQ;AAC9B,IAAI3D,MACF,KAAK,eAAesU,GAAgB,KAAK,cAActU,CAAG,GAC1D,KAAK,cAAA;AAAA,EAET;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,SAAS2D,GAAwB;AAC/B,UAAM3D,IAAM,KAAK,KAAK2D,CAAQ;AAC9B,IAAI3D,MACF,KAAK,eAAeuU,GAAkB,KAAK,cAAcvU,CAAG,GAC5D,KAAK,cAAA;AAAA,EAET;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO2D,GAAwB;AAC7B,UAAM3D,IAAM,KAAK,KAAK2D,CAAQ;AAC9B,IAAI3D,MACF,KAAK,eAAemU,EAAgB,KAAK,cAAcnU,CAAG,GAC1D,KAAK,cAAA;AAAA,EAET;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAAW2D,GAA2B;AACpC,UAAM3D,IAAM,KAAK,KAAK2D,CAAQ;AAC9B,WAAO3D,IAAMwU,GAAiB,KAAK,cAAcxU,CAAG,IAAI;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA,EAKA,YAAkB;AAChB,eAAWA,KAAO,KAAK;AACrB,WAAK,aAAa,IAAIA,CAAG;AAE3B,SAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKA,cAAoB;AAClB,SAAK,aAAa,MAAA,GAClB,KAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,kBAA4B;AAC1B,UAAM2E,IAAoB,CAAA;AAC1B,eAAW3E,KAAO,KAAK,cAAc;AACnC,YAAMkB,IAAM,KAAK,KAAK,QAAQlB,CAAG;AACjC,MAAIkB,KAAO,KAAGyD,EAAQ,KAAKzD,CAAG;AAAA,IAChC;AACA,WAAOyD;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,iBAAiBhB,GAA2C;AAC1D,UAAM3D,IAAM,KAAK,KAAK2D,CAAQ;AAC9B,WAAO3D,IAAM,KAAK,eAAe,IAAIA,CAAG,IAAI;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,wBAA8B;AAE5B,UAAMsX,IAAkB,KAAK,OAAO;AACpC,SAAK,SAAS,EAAE,GAAG,KAAK,QAAQ,gBAAgB,OAAA,GAChD,KAAK,oBAAA,GAGD,CAAC,KAAK,OAAO,kBAAkBA,MACjC,KAAK,SAAS,EAAE,GAAG,KAAK,QAAQ,gBAAgBA,EAAA;AAAA,EAEpD;AAAA;AAAA;AAAA,EAIkB,SAAS9H;AAAAA;AAE7B;ACrmBO,SAAS+H,GAA2BhX,GAAciX,GAAoBhX,GAAuC;AAClH,SAAKgX,EAAM,SAEJ,CAAC,GAAGjX,CAAI,EAAE,KAAK,CAACS,GAAGC,MAAM;AAC9B,eAAWwW,KAAQD,GAAO;AAExB,YAAME,IADMlX,EAAQ,KAAK,CAACG,MAAMA,EAAE,UAAU8W,EAAK,KAAK,GAC9B,kBAAkBE,IACpCC,IAAQ5W,EAA8ByW,EAAK,KAAK,GAChDI,IAAQ5W,EAA8BwW,EAAK,KAAK,GAChDtU,IAASuU,EAAWE,GAAMC,GAAM7W,GAAGC,CAAC;AAC1C,UAAIkC,MAAW;AACb,eAAOsU,EAAK,cAAc,QAAQtU,IAAS,CAACA;AAAA,IAEhD;AACA,WAAO;AAAA,EACT,CAAC,IAdyB,CAAC,GAAG5C,CAAI;AAepC;AAUO,SAASoX,GAAkB3W,GAAYC,GAAoB;AAEhE,SAAID,KAAK,QAAQC,KAAK,OAAa,IAC/BD,KAAK,OAAa,IAClBC,KAAK,OAAa,KAGlB,OAAOD,KAAM,YAAY,OAAOC,KAAM,WACjCD,IAAIC,IAGTD,aAAa,QAAQC,aAAa,OAC7BD,EAAE,YAAYC,EAAE,QAAA,IAIrB,OAAOD,KAAM,aAAa,OAAOC,KAAM,YAClCD,MAAMC,IAAI,IAAID,IAAI,KAAK,IAIzB,OAAOA,CAAC,EAAE,cAAc,OAAOC,CAAC,CAAC;AAC1C;AAaO,SAAS6W,GAAWC,GAAsBhY,GAAeiY,GAAmBC,GAAiC;AAClH,QAAMC,IAAWH,EAAQ,KAAK,CAACI,MAAMA,EAAE,UAAUpY,CAAK;AAEtD,SAAIiY,IAEEE,IACEA,EAAS,cAAc,QAElBH,EAAQ,IAAI,CAACI,MAAOA,EAAE,UAAUpY,IAAQ,EAAE,GAAGoY,GAAG,WAAW,OAAA,IAAoBA,CAAE,IAGjFJ,EAAQ,OAAO,CAACI,MAAMA,EAAE,UAAUpY,CAAK,IAEvCgY,EAAQ,SAASE,IAEnB,CAAC,GAAGF,GAAS,EAAE,OAAAhY,GAAO,WAAW,OAAgB,IAGnDgY,IAGHG,GAAU,cAAc,QACnB,CAAC,EAAE,OAAAnY,GAAO,WAAW,QAAQ,IAC3BmY,GAAU,cAAc,SAC1B,CAAA,IAEF,CAAC,EAAE,OAAAnY,GAAO,WAAW,OAAO;AAEvC;AAUO,SAASqY,GAAaC,GAAwBtY,GAAmC;AACtF,QAAMuO,IAAQ+J,EAAU,UAAU,CAACF,MAAMA,EAAE,UAAUpY,CAAK;AAC1D,SAAOuO,KAAS,IAAIA,IAAQ,IAAI;AAClC;AASO,SAASgK,GAAiBD,GAAwBtY,GAA2C;AAClG,SAAOsY,EAAU,KAAK,CAACF,MAAMA,EAAE,UAAUpY,CAAK,GAAG;AACnD;;AC9GO,MAAMwY,WAAwBrW,EAAgC;AAAA,EAC1D,OAAO;AAAA,EACE,UAAU;AAAA,EAE5B,IAAuB,gBAA0C;AAC/D,WAAO;AAAA,MACL,gBAAgB;AAAA,MAChB,eAAe;AAAA,IAAA;AAAA,EAEnB;AAAA;AAAA,EAGQ,YAAyB,CAAA;AAAA;AAAA;AAAA,EAKxB,SAAe;AACtB,SAAK,YAAY,CAAA;AAAA,EACnB;AAAA;AAAA;AAAA,EAKS,YAAY3B,GAAqC;AACxD,WAAI,KAAK,UAAU,WAAW,IACrB,CAAC,GAAGA,CAAI,IAEVgX,GAAW,CAAC,GAAGhX,CAAI,GAAG,KAAK,WAAW,CAAC,GAAG,KAAK,OAAO,CAAC;AAAA,EAChE;AAAA,EAES,cAAc4B,GAAkC;AAEvD,QAAI,CADW,KAAK,QAAQ,KAAK,CAACxB,MAAMA,EAAE,UAAUwB,EAAM,KAAK,GAClD,SAAU,QAAO;AAE9B,UAAM6V,IAAW7V,EAAM,cAAc,UAC/B8V,IAAa,KAAK,OAAO,kBAAkB;AAEjD,gBAAK,YAAYH,GAAW,KAAK,WAAW3V,EAAM,OAAO6V,GAAUC,CAAU,GAE7E,KAAK,KAAK,eAAe,EAAE,WAAW,CAAC,GAAG,KAAK,SAAS,GAAG,GAC3D,KAAK,cAAA,GAEE;AAAA,EACT;AAAA,EAES,cAAoB;AAC3B,UAAM1R,IAAa,KAAK;AACxB,QAAI,CAACA,EAAY;AAEjB,UAAMiS,IAAY,KAAK,OAAO,kBAAkB;AAIhD,IADoBjS,EAAW,iBAAiB,+BAA+B,EACnE,QAAQ,CAAClD,MAAS;AAC5B,YAAMtD,IAAQsD,EAAK,aAAa,YAAY;AAC5C,UAAI,CAACtD,EAAO;AAEZ,YAAM0Y,IAAYL,GAAa,KAAK,WAAWrY,CAAK,GAC9C2Y,IAAUJ,GAAiB,KAAK,WAAWvY,CAAK;AAMtD,UAHsBsD,EAAK,cAAc,aAAa,GACvC,OAAA,GAEXqV,GAAS;AAGX,QAD0BrV,EAAK,cAAc,2CAA2C,GACrE,OAAA,GAEnBA,EAAK,aAAa,aAAaqV,CAAO;AAGtC,cAAMC,IAAY,SAAS,cAAc,MAAM;AAO/C,YANAA,EAAU,YAAY,kBAEtB,KAAK,QAAQA,GAAW,KAAK,YAAYD,MAAY,QAAQ,YAAY,UAAU,CAAC,GACpFrV,EAAK,YAAYsV,CAAS,GAGtBH,KAAa,KAAK,UAAU,SAAS,KAAKC,MAAc,QAAW;AACrE,gBAAMG,IAAQ,SAAS,cAAc,MAAM;AAC3C,UAAAA,EAAM,YAAY,cAClBA,EAAM,cAAc,OAAOH,CAAS,GACpCpV,EAAK,YAAYuV,CAAK;AAAA,QACxB;AAAA,MACF;AACE,QAAAvV,EAAK,gBAAgB,WAAW;AAAA,IAGpC,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,eAA4B;AAC1B,WAAO,CAAC,GAAG,KAAK,SAAS;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAawV,GAA0B;AACrC,SAAK,YAAY,CAAC,GAAGA,CAAK,GAC1B,KAAK,KAAK,eAAe,EAAE,WAAW,CAAC,GAAGA,CAAK,GAAG,GAClD,KAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKA,YAAkB;AAChB,SAAK,YAAY,CAAA,GACjB,KAAK,KAAK,eAAe,EAAE,WAAW,CAAA,GAAI,GAC1C,KAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,aAAa9Y,GAAmC;AAC9C,WAAOqY,GAAa,KAAK,WAAWrY,CAAK;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,iBAAiBA,GAA2C;AAC1D,WAAOuY,GAAiB,KAAK,WAAWvY,CAAK;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQS,eAAeA,GAAiD;AACvE,UAAMuO,IAAQ,KAAK,UAAU,UAAU,CAAC6J,MAAMA,EAAE,UAAUpY,CAAK;AAC/D,WAAIuO,MAAU,KAAI,SAGX;AAAA,MACL,MAAM;AAAA,QACJ,WAHc,KAAK,UAAUA,CAAK,EAGb;AAAA,QACrB,UAAUA;AAAA,MAAA;AAAA,IACZ;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMS,iBAAiBvO,GAAewP,GAA0B;AAEjE,QAAI,CAACA,EAAM,MAAM;AAEf,WAAK,YAAY,KAAK,UAAU,OAAO,CAAC4I,MAAMA,EAAE,UAAUpY,CAAK;AAC/D;AAAA,IACF;AAGA,UAAM+Y,IAAgB,KAAK,UAAU,UAAU,CAACX,MAAMA,EAAE,UAAUpY,CAAK,GACjEgZ,IAAsB;AAAA,MAC1B,OAAAhZ;AAAA,MACA,WAAWwP,EAAM,KAAK;AAAA,IAAA;AAGxB,IAAIuJ,MAAkB,KAEpB,KAAK,UAAUA,CAAa,IAAIC,IAGhC,KAAK,UAAU,OAAOxJ,EAAM,KAAK,UAAU,GAAGwJ,CAAQ;AAAA,EAK1D;AAAA;AAAA;AAAA,EAKkB,SAASvJ;AAAAA;AAE7B;ACzMO,SAASwJ,GAAqBxY,GAAuB;AAC1D,SAAOA,EAAQ,OAAO,CAACY,MAAQA,EAAI,WAAW,MAAM;AACtD;AAQO,SAAS6X,GAAsBzY,GAAuB;AAC3D,SAAOA,EAAQ,OAAO,CAACY,MAAQA,EAAI,WAAW,OAAO;AACvD;AAQO,SAAS8X,EAAiB1Y,GAAyB;AACxD,SAAOA,EAAQ,KAAK,CAACY,MAAQA,EAAI,WAAW,UAAUA,EAAI,WAAW,OAAO;AAC9E;AAyEO,SAAS+X,GAAmBtG,GAAmBrS,GAAsB;AAC1E,QAAM+F,IAAasM,EAAK;AACxB,MAAI,CAACtM,EAAY;AAEjB,QAAM1F,IAAc,MAAM,KAAK0F,EAAW,iBAAiB,mBAAmB,CAAC;AAC/E,MAAI,CAAC1F,EAAY,OAAQ;AAGzB,QAAMuY,wBAAmB,IAAA;AACzB,EAAA5Y,EAAQ,QAAQ,CAACY,GAAKU,MAAM;AAC1B,IAAIV,EAAI,SAAOgY,EAAa,IAAIhY,EAAI,OAAOU,CAAC;AAAA,EAC9C,CAAC;AAGD,MAAIwG,IAAO;AACX,aAAWlH,KAAOZ;AAChB,QAAIY,EAAI,WAAW,QAAQ;AACzB,YAAMwC,IAAWwV,EAAa,IAAIhY,EAAI,KAAK,GACrCiC,IAAOxC,EAAY,KAAK,CAAC,MAAM,EAAE,aAAa,YAAY,MAAMO,EAAI,KAAK;AAC/E,MAAIiC,MACFA,EAAK,UAAU,IAAI,aAAa,GAChCA,EAAK,MAAM,WAAW,UACtBA,EAAK,MAAM,OAAOiF,IAAO,MAErB1E,MAAa,UACf2C,EAAW,iBAAiB,kCAAkC3C,CAAQ,IAAI,EAAE,QAAQ,CAACyV,MAAO;AAC1F,QAAAA,EAAG,UAAU,IAAI,aAAa,GAC7BA,EAAmB,MAAM,WAAW,UACpCA,EAAmB,MAAM,OAAO/Q,IAAO;AAAA,MAC1C,CAAC,GAEHA,KAAQjF,EAAK;AAAA,IAEjB;AAIF,MAAIiW,IAAQ;AACZ,aAAWlY,KAAO,CAAC,GAAGZ,CAAO,EAAE;AAC7B,QAAIY,EAAI,WAAW,SAAS;AAC1B,YAAMwC,IAAWwV,EAAa,IAAIhY,EAAI,KAAK,GACrCiC,IAAOxC,EAAY,KAAK,CAAC,MAAM,EAAE,aAAa,YAAY,MAAMO,EAAI,KAAK;AAC/E,MAAIiC,MACFA,EAAK,UAAU,IAAI,cAAc,GACjCA,EAAK,MAAM,WAAW,UACtBA,EAAK,MAAM,QAAQiW,IAAQ,MAEvB1V,MAAa,UACf2C,EAAW,iBAAiB,kCAAkC3C,CAAQ,IAAI,EAAE,QAAQ,CAACyV,MAAO;AAC1F,QAAAA,EAAG,UAAU,IAAI,cAAc,GAC9BA,EAAmB,MAAM,WAAW,UACpCA,EAAmB,MAAM,QAAQC,IAAQ;AAAA,MAC5C,CAAC,GAEHA,KAASjW,EAAK;AAAA,IAElB;AAEJ;AAOO,SAASkW,GAAmB1G,GAAyB;AAC1D,QAAMtM,IAAasM,EAAK;AACxB,MAAI,CAACtM,EAAY;AAGjB,EADcA,EAAW,iBAAiB,6BAA6B,EACjE,QAAQ,CAAClD,MAAS;AACtB,IAAAA,EAAK,UAAU,OAAO,eAAe,cAAc,GAClDA,EAAqB,MAAM,WAAW,IACtCA,EAAqB,MAAM,OAAO,IAClCA,EAAqB,MAAM,QAAQ;AAAA,EACtC,CAAC;AACH;AClKO,MAAMmW,WAA4BtX,EAAoC;AAAA,EAClE,OAAO;AAAA,EACE,UAAU;AAAA,EAE5B,IAAuB,gBAA8C;AACnE,WAAO,CAAA;AAAA,EACT;AAAA;AAAA,EAGQ,YAAY;AAAA,EACZ,kCAAkB,IAAA;AAAA,EAClB,mCAAmB,IAAA;AAAA;AAAA;AAAA,EAKlB,SAAe;AACtB,SAAK,YAAY,MAAA,GACjB,KAAK,aAAa,MAAA,GAClB,KAAK,YAAY;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,OAAO3B,GAA0BN,GAA+C;AACrF,UAAMO,IAAUP,GAAQ;AACxB,WAAK,MAAM,QAAQO,CAAO,IACnB0Y,EAAiB1Y,CAAO,IADK;AAAA,EAEtC;AAAA;AAAA;AAAA,EAKS,eAAeA,GAAkD;AAExE,gBAAK,YAAY0Y,EAAiB,CAAC,GAAG1Y,CAAO,CAAC,GACvC,CAAC,GAAGA,CAAO;AAAA,EACpB;AAAA,EAES,cAAoB;AAC3B,QAAI,CAAC,KAAK;AACR;AAGF,UAAMqS,IAAO,KAAK,MACZrS,IAAU,CAAC,GAAG,KAAK,OAAO;AAEhC,QAAI,CAAC0Y,EAAiB1Y,CAAO,GAAG;AAC9B,MAAA+Y,GAAmB1G,CAAI,GACvB,KAAK,YAAY;AACjB;AAAA,IACF;AAGA,mBAAe,MAAM;AACnB,MAAAsG,GAAmBtG,GAAMrS,CAAO;AAAA,IAClC,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKS,cAAciZ,GAA6B;AAClD,YAAQA,EAAM,MAAA;AAAA,MACZ,KAAKC,EAAe,iBAAiB;AAGnC,cAAM5V,IAAS2V,EAAM,SACfE,IAAU7V,EAAwD;AACxE,YAAI6V,MAAW,UAAUA,MAAW;AAClC,iBAAO;AAGT,cAAMC,IAAc9V,EAAO,MAAoD;AAC/E,eAAI8V,MAAe,UAAUA,MAAe,UACnC,KAET;AAAA,MACF;AAAA,MACA;AACE;AAAA,IAAO;AAAA,EAEb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,uBAA6B;AAC3B,UAAMpZ,IAAU,CAAC,GAAG,KAAK,OAAO;AAChC,IAAA2Y,GAAmB,KAAK,MAAgC3Y,CAAO;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA,EAKA,uBAAuC;AACrC,UAAMA,IAAU,CAAC,GAAG,KAAK,OAAO;AAChC,WAAOwY,GAAqBxY,CAAO;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA,EAKA,wBAAwC;AACtC,UAAMA,IAAU,CAAC,GAAG,KAAK,OAAO;AAChC,WAAOyY,GAAsBzY,CAAO;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,uBAA6B;AAC3B,IAAA+Y,GAAmB,KAAK,IAA8B;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMS,2BACPvG,GACA6G,GACmE;AACnE,QAAI,CAAC,KAAK;AACR;AAGF,QAAIvR,IAAO,GACPgR,IAAQ;AAEZ,QAAItG,GAAO;AAET,YAAM8G,IAAkB9G,EAAM,iBAAiB,cAAc,GACvD+G,IAAmB/G,EAAM,iBAAiB,eAAe;AAC/D,MAAA8G,EAAgB,QAAQ,CAACT,MAAO;AAC9B,QAAA/Q,KAAS+Q,EAAmB;AAAA,MAC9B,CAAC,GACDU,EAAiB,QAAQ,CAACV,MAAO;AAC/B,QAAAC,KAAUD,EAAmB;AAAA,MAC/B,CAAC;AAAA,IACH,OAAO;AAGL,YAAM9S,IADO,KAAK,KACM;AACxB,MAAIA,KACkBA,EAAW,iBAAiB,mBAAmB,EACvD,QAAQ,CAAClD,MAAS;AAC5B,QAAIA,EAAK,UAAU,SAAS,aAAa,IACvCiF,KAASjF,EAAqB,cACrBA,EAAK,UAAU,SAAS,cAAc,MAC/CiW,KAAUjW,EAAqB;AAAA,MAEnC,CAAC;AAAA,IAEL;AAGA,UAAM2W,IACJH,GAAa,UAAU,SAAS,aAAa,KAAKA,GAAa,UAAU,SAAS,cAAc;AAElG,WAAO,EAAE,MAAAvR,GAAM,OAAAgR,GAAO,YAAAU,EAAA;AAAA,EACxB;AAAA;AAEF;AC9KA,SAASC,GAAmBC,GAAoD;AAC9E,SAAO,OAAOA,KAAQ,YAAYA,MAAQ,QAAQ,aAAaA;AACjE;AASO,SAASC,EAAqBla,GAA0Bma,GAAyC;AACtG,QAAMC,IAAa,SAAS,cAAc,KAAK;AAC/C,EAAAA,EAAW,YAAY,mBACvBA,EAAW,aAAa,QAAQ,cAAc,GAC9CA,EAAW,aAAa,aAAa,QAAQ;AAE7C,QAAM/R,IAAO,SAAS,cAAc,KAAK;AACzC,EAAAA,EAAK,YAAY;AAEjB,QAAMgS,IAAS,SAAS,cAAc,KAAK;AAC3C,EAAAA,EAAO,YAAY;AAEnB,QAAMhB,IAAQ,SAAS,cAAc,KAAK;AAI1C,MAHAA,EAAM,YAAY,yBAGdrZ,EAAO,iBAAiB,IAAO;AACjC,UAAM+C,IAAW,SAAS,cAAc,MAAM;AAC9C,IAAAA,EAAS,YAAY,+CACrBA,EAAS,cAAc,UAAUoX,EAAQ,SAAS,SAClD9R,EAAK,YAAYtF,CAAQ;AAAA,EAC3B;AAGA,MAAI/C,EAAO,qBAAqBma,EAAQ,iBAAiBA,EAAQ,WAAW;AAC1E,UAAMG,IAAgB,SAAS,cAAc,MAAM;AACnD,IAAAA,EAAc,YAAY,oDAC1BA,EAAc,cAAc,aAAaH,EAAQ,YAAY,IAC7D9R,EAAK,YAAYiS,CAAa;AAAA,EAChC;AAGA,MAAIta,EAAO,qBAAqBma,EAAQ,eAAe,GAAG;AACxD,UAAMI,IAAgB,SAAS,cAAc,MAAM;AACnD,IAAAA,EAAc,YAAY,oDAC1BA,EAAc,cAAc,aAAaJ,EAAQ,YAAY,IAC7Dd,EAAM,YAAYkB,CAAa;AAAA,EACjC;AAGA,MAAIva,EAAO;AACT,eAAWuM,KAASvM,EAAO,cAAc;AACvC,YAAMwa,IAAUC,GAAkBlO,GAAO4N,CAAO;AAChD,cAAQ5N,EAAM,UAAA;AAAA,QACZ,KAAK;AACH,UAAAlE,EAAK,YAAYmS,CAAO;AACxB;AAAA,QACF,KAAK;AACH,UAAAH,EAAO,YAAYG,CAAO;AAC1B;AAAA,QACF,KAAK;AACH,UAAAnB,EAAM,YAAYmB,CAAO;AACzB;AAAA,MAAA;AAAA,IAEN;AAGF,SAAAJ,EAAW,YAAY/R,CAAI,GAC3B+R,EAAW,YAAYC,CAAM,GAC7BD,EAAW,YAAYf,CAAK,GAErBe;AACT;AAQO,SAASM,GAA2BC,GAAyC;AAClF,QAAM7R,IAAY,SAAS,cAAc,KAAK;AAC9C,SAAAA,EAAU,YAAY,6CAA6C6R,CAAQ,IAE3E7R,EAAU,aAAa,QAAQ,cAAc,GACtCA;AACT;AAUO,SAAS8R,GACd9R,GACAxI,GACAC,GACA8V,GACM;AACN,EAAAvN,EAAU,YAAY;AAEtB,aAAW+R,KAAava,GAAM;AAC5B,UAAMyS,IAAQ,SAAS,cAAc,KAAK;AAQ1C,QAPAA,EAAM,YAAY,uBAElBA,EAAM,aAAa,QAAQ,cAAc,GACrC8H,EAAU,MACZ9H,EAAM,aAAa,uBAAuB8H,EAAU,EAAE,GAGpDA,EAAU,WAAW;AAEvB,YAAMzX,IAAO,SAAS,cAAc,KAAK;AACzC,MAAAA,EAAK,YAAY,kDACjBA,EAAK,MAAM,aAAa,UACxBA,EAAK,cAAcyX,EAAU,SAAS,IACtC9H,EAAM,YAAY3P,CAAI;AAAA,IACxB;AAEE,iBAAWjC,KAAOZ,GAAS;AACzB,cAAM6C,IAAO,SAAS,cAAc,KAAK;AACzC,QAAAA,EAAK,YAAY,wBACjBA,EAAK,aAAa,cAAcjC,EAAI,KAAK;AAEzC,YAAItB,GACAib;AAGJ,cAAMC,IAASF,EAAU,cAAc1Z,EAAI,KAAK;AAChD,YAAI4Z;AAEF,cAAIf,GAAmBe,CAAM,GAAG;AAC9B,kBAAMC,IAAQC,GAAcF,EAAO,OAAO;AAC1C,YAAIC,MACFnb,IAAQmb,EAAM3E,GAAUlV,EAAI,OAAOA,CAAG,IAExC2Z,IAAYC,EAAO;AAAA,UACrB,OAAO;AACL,kBAAMC,IAAQC,GAAcF,CAAM;AAClC,YAAIC,MACFnb,IAAQmb,EAAM3E,GAAUlV,EAAI,OAAOA,CAAG;AAAA,UAE1C;AAAA,iBACS0Z,EAAU,SAAS,OAAO,UAAU,eAAe,KAAKA,EAAU,OAAO1Z,EAAI,KAAK,GAAG;AAE9F,gBAAM+Z,IAAYL,EAAU,MAAM1Z,EAAI,KAAK;AAC3C,UAAI,OAAO+Z,KAAc,aACvBrb,IAAQqb,EAAU7E,GAAUlV,EAAI,OAAOA,CAAG,IAE1CtB,IAAQqb;AAAA,QAEZ;AAGA,QAAIrb,KAAS,OACXuD,EAAK,cAAc0X,IAAYA,EAAUjb,GAAOsB,EAAI,OAAOA,CAAG,IAAI,OAAOtB,CAAK,IAE9EuD,EAAK,cAAc,IAErB2P,EAAM,YAAY3P,CAAI;AAAA,MACxB;AAGF,IAAA0F,EAAU,YAAYiK,CAAK;AAAA,EAC7B;AACF;AASA,SAAS0H,GAAkBlO,GAAwB4N,GAAyC;AAC1F,QAAMK,IAAU,SAAS,cAAc,KAAK;AAC5C,EAAAA,EAAQ,YAAY,4CACpBA,EAAQ,KAAK,gBAAgBjO,EAAM,EAAE;AAErC,QAAM3C,IAAU2C,EAAM,OAAO4N,CAAO;AAEpC,SAAI,OAAOvQ,KAAY,WACrB4Q,EAAQ,YAAY5Q,IAEpB4Q,EAAQ,YAAY5Q,CAAO,GAGtB4Q;AACT;AAYO,SAASW,GACd7a,GACAC,GACAiD,GACA+G,GACA6Q,GACmB;AACnB,SAAO;AAAA,IACL,WAAW9a,EAAK;AAAA,IAChB,cAAc8a,GAAa,cAAc,UAAU9a,EAAK;AAAA,IACxD,cAAciK,GAAgB,UAAU,QAAQ;AAAA,IAChD,SAAAhK;AAAA,IACA,MAAAD;AAAA,IACA,MAAAkD;AAAA,EAAA;AAEJ;;AClNO,MAAM6X,WAAyBpZ,EAAiC;AAAA,EAC5D,OAAO;AAAA,EACE,UAAU;AAAA,EAE5B,IAAuB,gBAA2C;AAChE,WAAO;AAAA,MACL,UAAU;AAAA,MACV,cAAc;AAAA,MACd,mBAAmB;AAAA,MACnB,mBAAmB;AAAA,IAAA;AAAA,EAEvB;AAAA;AAAA,EAGQ,iBAAqC;AAAA,EACrC,0BAA8C;AAAA,EAC9C,6BAAiD;AAAA,EACjD,gBAAoC;AAAA;AAAA;AAAA,EAInC,SAAe;AACtB,IAAI,KAAK,mBACP,KAAK,eAAe,OAAA,GACpB,KAAK,iBAAiB,OAEpB,KAAK,4BACP,KAAK,wBAAwB,OAAA,GAC7B,KAAK,0BAA0B,OAE7B,KAAK,+BACP,KAAK,2BAA2B,OAAA,GAChC,KAAK,6BAA6B,OAEhC,KAAK,kBACP,KAAK,cAAc,OAAA,GACnB,KAAK,gBAAgB;AAAA,EAEzB;AAAA;AAAA;AAAA,EAIS,cAAoB;AAC3B,UAAMqE,IAAa,KAAK;AACxB,QAAI,CAACA,EAAY;AAIjB,UAAMwC,IACJxC,EAAW,cAAc,kBAAkB,KAC3CA,EAAW,cAAc,mBAAmB,KAC5CA,EAAW,SAAS,CAAC;AACvB,QAAI,CAACwC,EAAW;AAGhB,UAAMyB,IAAiB,KAAK,kBAAA,GACtB6Q,IAAc,KAAK,eAAA,GAEnBjB,IAAUgB;AAAA,MACd,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL5Q;AAAA,MACA6Q;AAAA,IAAA,GAIIE,IAAkB,KAAK,OAAO,mBAAmB,CAAA,GACjDC,IAAUD,EAAgB,OAAO,CAAC9W,MAAMA,EAAE,aAAa,KAAK,GAC5DgX,IAAaF,EAAgB,OAAO,CAAC9W,MAAMA,EAAE,aAAa,KAAK;AAGrE,QAAI+W,EAAQ,SAAS,GAAG;AACtB,UAAI,CAAC,KAAK,yBAAyB;AACjC,aAAK,0BAA0Bb,GAA2B,KAAK;AAC/D,cAAM7Z,IAASyF,EAAW,cAAc,SAAS;AACjD,QAAIzF,KAAUA,EAAO,cACnBiI,EAAU,aAAa,KAAK,yBAAyBjI,EAAO,WAAW,IAEvEiI,EAAU,YAAY,KAAK,uBAAuB;AAAA,MAEtD;AACA,MAAA8R;AAAA,QACE,KAAK;AAAA,QACLW;AAAA,QACA,KAAK;AAAA,QACL,KAAK;AAAA,MAAA;AAAA,IAET,MAAA,CAAW,KAAK,4BACd,KAAK,wBAAwB,OAAA,GAC7B,KAAK,0BAA0B;AAIjC,UAAME,IACJ,KAAK,OAAO,iBAAiB,MAC5B,KAAK,OAAO,qBAAqBtB,EAAQ,eAAe,KACxD,KAAK,OAAO,qBAAqBA,EAAQ,iBAAiBA,EAAQ,aAClE,KAAK,OAAO,gBAAgB,KAAK,OAAO,aAAa,SAAS,GAC3DuB,IAAmBD,KAAkB,KAAK,OAAO,aAAa,OAC9DE,IAAcH,EAAW,SAAS,KAAKE;AAG7C,QAAID,KAAkB,KAAK,OAAO,aAAa;AAC7C,UAAI,CAAC,KAAK;AACR,aAAK,iBAAiBvB,EAAqB,KAAK,QAAQC,CAAO,GAC/DrR,EAAU,aAAa,KAAK,gBAAgBA,EAAU,UAAU;AAAA,WAC3D;AACL,cAAM8S,IAAa1B,EAAqB,KAAK,QAAQC,CAAO;AAC5D,aAAK,eAAe,YAAYyB,CAAU,GAC1C,KAAK,iBAAiBA;AAAA,MACxB;AAAA,SACS,KAAK,OAAO,aAAa,SAAS,KAAK,mBAChD,KAAK,eAAe,OAAA,GACpB,KAAK,iBAAiB;AAIxB,IAAID,KACG,KAAK,kBACR,KAAK,gBAAgB,SAAS,cAAc,KAAK,GACjD,KAAK,cAAc,YAAY,cAC/B7S,EAAU,YAAY,KAAK,aAAa,IAG1C,KAAK,cAAc,YAAY,IAE3B0S,EAAW,SAAS,MACjB,KAAK,+BACR,KAAK,6BAA6Bd,GAA2B,QAAQ,IAEvE,KAAK,cAAc,YAAY,KAAK,0BAA0B,GAC9DE;AAAA,MACE,KAAK;AAAA,MACLY;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,IAAA,IAILE,MACF,KAAK,iBAAiBxB,EAAqB,KAAK,QAAQC,CAAO,GAC/D,KAAK,cAAc,YAAY,KAAK,cAAc,MAGpD,KAAK,cAAA;AAAA,EAGT;AAAA;AAAA;AAAA,EAIQ,UAAgB;AACtB,IAAI,KAAK,mBACP,KAAK,eAAe,OAAA,GACpB,KAAK,iBAAiB,OAEpB,KAAK,4BACP,KAAK,wBAAwB,OAAA,GAC7B,KAAK,0BAA0B,OAE7B,KAAK,+BACP,KAAK,2BAA2B,OAAA,GAChC,KAAK,6BAA6B,OAEhC,KAAK,kBACP,KAAK,cAAc,OAAA,GACnB,KAAK,gBAAgB;AAAA,EAEzB;AAAA,EAEQ,gBAAsB;AAC5B,IAAI,KAAK,kBACP,KAAK,cAAc,OAAA,GACnB,KAAK,gBAAgB,OAEnB,KAAK,+BACP,KAAK,2BAA2B,OAAA,GAChC,KAAK,6BAA6B,OAEhC,KAAK,kBAAkB,KAAK,OAAO,aAAa,UAClD,KAAK,eAAe,OAAA,GACpB,KAAK,iBAAiB;AAAA,EAE1B;AAAA,EAEQ,oBAAsD;AAE5D,QAAI;AAEF,aADa,KAAK,MACL,iBAAiB,WAAW,KAAK;AAAA,IAChD,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEQ,iBAA4D;AAClE,QAAI;AAEF,aADa,KAAK,MACL,iBAAiB,WAAW,KAAK;AAAA,IAChD,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,UAAgB;AACd,SAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAgC;AAC9B,UAAM5P,IAAiB,KAAK,kBAAA,GACtB6Q,IAAc,KAAK,eAAA;AAEzB,WAAOD;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL5Q;AAAA,MACA6Q;AAAA,IAAA;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,SAAS7O,GAA8B;AACrC,IAAK,KAAK,OAAO,iBACf,KAAK,OAAO,eAAe,CAAA,IAE7B,KAAK,OAAO,aAAa,KAAKA,CAAK,GACnC,KAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY2D,GAAkB;AAC5B,IAAI,KAAK,OAAO,iBACd,KAAK,OAAO,eAAe,KAAK,OAAO,aAAa,OAAO,CAAC2L,MAAMA,EAAE,OAAO3L,CAAE,GAC7E,KAAK,cAAA;AAAA,EAET;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,kBAAkBnQ,GAAiC;AACjD,IAAK,KAAK,OAAO,oBACf,KAAK,OAAO,kBAAkB,CAAA,IAEhC,KAAK,OAAO,gBAAgB,KAAKA,CAAG,GACpC,KAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,qBAAqBmQ,GAAkB;AACrC,IAAI,KAAK,OAAO,oBACd,KAAK,OAAO,kBAAkB,KAAK,OAAO,gBAAgB,OAAO,CAAC1L,MAAMA,EAAE,OAAO0L,CAAE,GACnF,KAAK,cAAA;AAAA,EAET;AAAA;AAAA;AAAA,EAIkB,SAASX;AAAAA;AAE7B;ACnTO,MAAMuM,KAAqBC;AAE3B,SAASC,GAAoBhc,GAA+B;AACjE,QAAMic,IAAmB,CAAA;AAEzB,SAAI,CAACjc,EAAO,gBAAgB,UAAU,CAACA,EAAO,mBAAmB,UAC/Dic,EAAO,KAAK,oDAAoD,GAG7Djc,EAAO,aAAa,UACvBic,EAAO,KAAK,sCAAsC,GAG7CA;AACT;AAEO,SAASC,GAAeC,GAAwBC,GAA4B;AACjF,SAAO,CAAC,GAAGD,GAAcC,CAAU,EAAE,KAAK,GAAG;AAC/C;ACbO,SAASC,GAAW/b,GAAsBN,GAAkC;AACjF,QAAMsc,IAAiBtc,EAAO,kBAAkB,CAAA,GAC1Cuc,IAAoBvc,EAAO,qBAAqB,CAAA,GAChDwc,IAAcxc,EAAO,eAAe,CAAA,GAGpCyc,IAAaC,GAAoBpc,GAAMic,CAAiB,GAGxDI,IAAYC;AAAA,IAChBtc;AAAA,IACAgc;AAAA,IACAC;AAAA,IACAE;AAAA,IACAD;AAAA,IACA;AAAA;AAAA,IACA;AAAA;AAAA,EAAA,GAIIK,IAASC,GAAgBH,GAAWF,GAAYD,CAAW,GAC3DO,IAAa,OAAO,OAAOF,CAAM,EAAE,OAAO,CAAC9b,GAAGC,MAAMD,IAAIC,GAAG,CAAC;AAElE,SAAO;AAAA,IACL,MAAM2b;AAAA,IACN,YAAAF;AAAA,IACA,QAAAI;AAAA,IACA,YAAAE;AAAA,EAAA;AAEJ;AAKO,SAASL,GAAoBpc,GAAsB0c,GAAkC;AAC1F,MAAIA,EAAa,WAAW,EAAG,QAAO,CAAC,OAAO;AAE9C,QAAMzK,wBAAW,IAAA;AACjB,aAAWxS,KAAOO,GAAM;AACtB,UAAMwN,IAAMkP,EAAa,IAAI,CAACrR,MAAM,OAAO5L,EAAI4L,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,GAAG;AAClE,IAAA4G,EAAK,IAAIzE,CAAG;AAAA,EACd;AACA,SAAO,CAAC,GAAGyE,CAAI,EAAE,KAAA;AACnB;AAKO,SAAS0K,GAAa3c,GAAsBR,GAA4C;AAC7F,QAAMwQ,wBAAa,IAAA;AAEnB,aAAWvQ,KAAOO,GAAM;AACtB,UAAMwN,IAAM,OAAO/N,EAAID,CAAK,KAAK,EAAE,GAC7BmY,IAAW3H,EAAO,IAAIxC,CAAG;AAC/B,IAAImK,IACFA,EAAS,KAAKlY,CAAG,IAEjBuQ,EAAO,IAAIxC,GAAK,CAAC/N,CAAG,CAAC;AAAA,EAEzB;AAEA,SAAOuQ;AACT;AAyBO,SAASsM,GACdtc,GACAgc,GACAU,GACAP,GACAD,GACAU,GACAC,GACY;AACZ,QAAMja,IAAqB,CAAA;AAG3B,MAAIoZ,EAAe,WAAW,GAAG;AAG/B,UAAMxQ,IAASsR,GAAgB9c,GAAM0c,GAAcP,GAAYD,CAAW,GACpEa,IAAQC,GAAkBxR,CAAM;AACtC,WAAA5I,EAAO,KAAK;AAAA,MACV,QAAQia,KAAa;AAAA,MACrB,UAAUA,KAAa;AAAA,MACvB,OAAAD;AAAA,MACA,QAAApR;AAAA,MACA,OAAAuR;AAAA,MACA,SAAS;AAAA,MACT,UAAU/c,EAAK;AAAA,IAAA,CAChB,GACM4C;AAAA,EACT;AAGA,QAAMqa,IAAejB,EAAe,CAAC,GAC/BkB,IAAkBlB,EAAe,MAAM,CAAC,GACxCmB,IAAcD,EAAgB,SAAS,GAGvC3K,IAAUoK,GAAa3c,GAAMid,CAAY;AAE/C,aAAW,CAACG,GAAYjK,CAAS,KAAKZ,GAAS;AAC7C,UAAM8K,IAASR,IAAY,GAAGA,CAAS,IAAIO,CAAU,KAAKA,GAGpD5R,IAASsR,GAAgB3J,GAAWuJ,GAAcP,GAAYD,CAAW,GACzEa,IAAQC,GAAkBxR,CAAM;AAGtC,QAAI8R;AACJ,IAAIH,MACFG,IAAWhB;AAAA,MACTnJ;AAAA,MACA+J;AAAA,MACAR;AAAA,MACAP;AAAA,MACAD;AAAA,MACAU,IAAQ;AAAA,MACRS;AAAA,IAAA,IAIJza,EAAO,KAAK;AAAA,MACV,QAAAya;AAAA,MACA,UAAUD,KAAc;AAAA,MACxB,OAAAR;AAAA,MACA,QAAApR;AAAA,MACA,OAAAuR;AAAA,MACA,SAASI;AAAA,MACT,UAAAG;AAAA,MACA,UAAUnK,EAAU;AAAA,IAAA,CACrB;AAAA,EACH;AAEA,SAAOvQ;AACT;AAKO,SAASka,GACd9c,GACA0c,GACAP,GACAD,GAC+B;AAC/B,QAAM1Q,IAAwC,CAAA;AAE9C,aAAW+R,KAAUpB;AACnB,eAAWqB,KAAMtB,GAAa;AAO5B,YAAMuB,KAJJf,EAAa,SAAS,IAClB1c,EAAK,OAAO,CAACkE,MAAMwY,EAAa,IAAI,CAAC,MAAM,OAAOxY,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,GAAG,MAAMqZ,CAAM,IACnFvd,GAEoB,IAAI,CAACkE,MAAM,OAAOA,EAAEsZ,EAAG,KAAK,CAAC,KAAK,CAAC,GACvDE,IAAalC,GAAmBgC,EAAG,OAAO,GAC1CG,IAAmBF,EAAK,SAAS,IAAIC,EAAWD,CAAI,IAAI,MAExDG,IAAWhC,GAAe,CAAC2B,CAAM,GAAGC,EAAG,KAAK;AAClD,MAAAhS,EAAOoS,CAAQ,IAAID;AAAA,IACrB;AAGF,SAAOnS;AACT;AAKO,SAASwR,GAAkBxR,GAA+C;AAC/E,MAAI1G,IAAM;AACV,aAAW+Y,KAAO,OAAO,OAAOrS,CAAM;AACpC,IAAA1G,KAAO+Y,KAAO;AAEhB,SAAO/Y;AACT;AAmCO,SAAS0X,GACdH,GACAF,GACAD,GACwB;AACxB,QAAMK,IAAiC,CAAA;AAGvC,WAASuB,EAAQ9d,GAAkB;AACjC,eAAWP,KAAOO;AAEhB,UAAI,CAACP,EAAI,WAAW,CAACA,EAAI,UAAU;AACjC,mBAAW8d,KAAUpB;AACnB,qBAAWqB,KAAMtB,GAAa;AAC5B,kBAAM0B,IAAWhC,GAAe,CAAC2B,CAAM,GAAGC,EAAG,KAAK;AAClD,YAAAjB,EAAOqB,CAAQ,KAAKrB,EAAOqB,CAAQ,KAAK,MAAMne,EAAI,OAAOme,CAAQ,KAAK;AAAA,UACxE;AAAA,UAEJ,CAAWne,EAAI,YACbqe,EAAQre,EAAI,QAAQ;AAAA,EAG1B;AAEA,SAAAqe,EAAQzB,CAAS,GACVE;AACT;AAMO,SAASwB,GAAiB/d,GAAkB8R,GAA4BkM,IAAkB,IAAkB;AACjH,QAAMpb,IAAqB,CAAA;AAE3B,WAASqb,EAAQxe,GAAe;AAC9B,IAAAmD,EAAO,KAAKnD,CAAG;AAGf,UAAMmS,IAAaE,IAAeA,EAAa,IAAIrS,EAAI,MAAM,IAAIue;AAGjE,QAAIve,EAAI,YAAYmS;AAClB,iBAAWsM,KAASze,EAAI;AACtB,QAAAwe,EAAQC,CAAK;AAAA,EAGnB;AAEA,aAAWze,KAAOO;AAChB,IAAAie,EAAQxe,CAAG;AAGb,SAAOmD;AACT;AAKO,SAASub,EAAgBne,GAA4B;AAC1D,QAAMiS,IAAiB,CAAA;AAEvB,WAASmM,EAAY3e,GAAe;AAIlC,QAHIA,EAAI,WACNwS,EAAK,KAAKxS,EAAI,MAAM,GAElBA,EAAI;AACN,iBAAWye,KAASze,EAAI;AACtB,QAAA2e,EAAYF,CAAK;AAAA,EAGvB;AAEA,aAAWze,KAAOO;AAChB,IAAAoe,EAAY3e,CAAG;AAGjB,SAAOwS;AACT;ACxTO,MAAMoM,KAAuB,CAAC,OAAO,OAAO,SAAS,OAAO,OAAO,SAAS,MAAM;AA+BlF,SAASC,GACd9V,GACA9I,GACA6e,GACAC,GACY;AAEZ,QAAMC,IAAa,IAAI,gBAAA,GACjBC,IAAqB,EAAE,QAAAhf,GAAQ,WAAA8e,GAAW,QAAQC,EAAW,OAAA,GAE7DE,IAAU,SAAS,cAAc,KAAK;AAC5C,SAAAA,EAAQ,YAAY,mBAGpBA,EAAQ,YAAYC,EAAc,WAAW,MAAMC,GAAmBN,GAAUG,CAAG,CAAC,CAAC,GAGrFC,EAAQ,YAAYC,EAAc,cAAc,MAAME,GAAgB,aAAaJ,CAAG,CAAC,CAAC,GAGxFC,EAAQ,YAAYC,EAAc,iBAAiB,MAAME,GAAgB,gBAAgBJ,CAAG,CAAC,CAAC,GAG9FC,EAAQ,YAAYC,EAAc,UAAU,MAAMG,GAAiBL,CAAG,CAAC,CAAC,GAGxEC,EAAQ,YAAYC,EAAc,oBAAoB,MAAMI,GAA0BN,CAAG,CAAC,CAAC,GAE3FlW,EAAU,YAAYmW,CAAO,GAGtB,MAAM;AACX,IAAAF,EAAW,MAAA,GACXE,EAAQ,OAAA;AAAA,EACV;AACF;AAKA,SAASC,EAAcK,GAAeC,GAAgD;AACpF,QAAMC,IAAU,SAAS,cAAc,KAAK;AAC5C,EAAAA,EAAQ,YAAY;AAEpB,QAAM5e,IAAS,SAAS,cAAc,KAAK;AAC3C,EAAAA,EAAO,YAAY,4BACnBA,EAAO,cAAc0e;AAErB,QAAM3V,IAAU,SAAS,cAAc,KAAK;AAC5C,SAAAA,EAAQ,YAAY,6BACpBA,EAAQ,YAAY4V,GAAgB,GAEpCC,EAAQ,YAAY5e,CAAM,GAC1B4e,EAAQ,YAAY7V,CAAO,GAEpB6V;AACT;AAKA,SAASL,GAAgBM,GAAwCV,GAAiC;AAChG,QAAM,EAAE,QAAAhf,GAAQ,WAAA8e,GAAW,QAAAa,EAAA,IAAWX,GAChCY,IAAO,SAAS,cAAc,KAAK;AACzC,EAAAA,EAAK,YAAY,uBACjBA,EAAK,aAAa,aAAaF,CAAQ;AAEvC,QAAMG,IAAgBH,MAAa,cAAe1f,EAAO,kBAAkB,CAAA,IAAOA,EAAO,qBAAqB,CAAA;AAE9G,MAAI6f,EAAc,WAAW,GAAG;AAC9B,UAAMC,IAAc,SAAS,cAAc,KAAK;AAChD,IAAAA,EAAY,YAAY,yBACxBA,EAAY,cAAc,oCAC1BF,EAAK,YAAYE,CAAW;AAAA,EAC9B;AACE,eAAWhgB,KAAS+f;AAClB,MAAAD,EAAK,YAAYG,GAAgBjgB,GAAO4f,GAAUV,CAAG,CAAC;AAK1D,SAAAY,EAAK;AAAA,IACH;AAAA,IACA,CAAC7X,MAAM;AACL,MAAAA,EAAE,eAAA,GACF6X,EAAK,UAAU,IAAI,WAAW;AAAA,IAChC;AAAA,IACA,EAAE,QAAAD,EAAA;AAAA,EAAO,GAGXC,EAAK;AAAA,IACH;AAAA,IACA,MAAM;AACJ,MAAAA,EAAK,UAAU,OAAO,WAAW;AAAA,IACnC;AAAA,IACA,EAAE,QAAAD,EAAA;AAAA,EAAO,GAGXC,EAAK;AAAA,IACH;AAAA,IACA,CAAC7X,MAAM;AACL,MAAAA,EAAE,eAAA,GACF6X,EAAK,UAAU,OAAO,WAAW;AAEjC,YAAM9f,IAAQiI,EAAE,cAAc,QAAQ,YAAY;AAClD,MAAIjI,KACFgf,EAAU,iBAAiBhf,GAAO4f,CAAQ;AAAA,IAE9C;AAAA,IACA,EAAE,QAAAC,EAAA;AAAA,EAAO,GAGJC;AACT;AAKA,SAASG,GAAgBjgB,GAAe4f,GAAwCV,GAAiC;AAC/G,QAAM,EAAE,WAAAF,GAAW,QAAAa,EAAA,IAAWX,GACxBgB,IAAO,SAAS,cAAc,KAAK;AACzC,EAAAA,EAAK,YAAY,wBACjBA,EAAK,YAAY;AAEjB,QAAMC,IAAYnB,EAAU,qBAAqB,KAAK,CAACnT,MAAMA,EAAE,UAAU7L,CAAK,GACxE4H,IAAQ,SAAS,cAAc,MAAM;AAC3C,EAAAA,EAAM,YAAY,wBAClBA,EAAM,cAAcuY,GAAW,UAAUngB;AAEzC,QAAMogB,IAAY,SAAS,cAAc,QAAQ;AACjD,SAAAA,EAAU,YAAY,yBACtBA,EAAU,YAAY,KACtBA,EAAU,QAAQ,gBAClBA,EAAU;AAAA,IACR;AAAA,IACA,CAACnY,MAAM;AACL,MAAAA,EAAE,gBAAA,GACF+W,EAAU,sBAAsBhf,GAAO4f,CAAQ;AAAA,IACjD;AAAA,IACA,EAAE,QAAAC,EAAA;AAAA,EAAO,GAGXK,EAAK,YAAYtY,CAAK,GACtBsY,EAAK,YAAYE,CAAS,GAG1BF,EAAK;AAAA,IACH;AAAA,IACA,CAACjY,MAAM;AACL,MAAAA,EAAE,cAAc,QAAQ,cAAcjI,CAAK,GAC3CiI,EAAE,cAAc,QAAQ,eAAe2X,CAAQ,GAC/CM,EAAK,UAAU,IAAI,UAAU;AAAA,IAC/B;AAAA,IACA,EAAE,QAAAL,EAAA;AAAA,EAAO,GAGXK,EAAK;AAAA,IACH;AAAA,IACA,MAAM;AACJ,MAAAA,EAAK,UAAU,OAAO,UAAU;AAAA,IAClC;AAAA,IACA,EAAE,QAAAL,EAAA;AAAA,EAAO,GAGJK;AACT;AAKA,SAASX,GAAiBL,GAAiC;AACzD,QAAM,EAAE,QAAAhf,GAAQ,WAAA8e,GAAW,QAAAa,EAAA,IAAWX,GAChCY,IAAO,SAAS,cAAc,KAAK;AACzC,EAAAA,EAAK,YAAY,6CACjBA,EAAK,aAAa,aAAa,QAAQ;AAEvC,QAAMO,IAAgBngB,EAAO,eAAe,CAAA;AAE5C,MAAImgB,EAAc,WAAW,GAAG;AAC9B,UAAML,IAAc,SAAS,cAAc,KAAK;AAChD,IAAAA,EAAY,YAAY,yBACxBA,EAAY,cAAc,4CAC1BF,EAAK,YAAYE,CAAW;AAAA,EAC9B;AACE,eAAW1D,KAAc+D;AACvB,MAAAP,EAAK,YAAYQ,GAAgBhE,GAAY4C,CAAG,CAAC;AAKrD,SAAAY,EAAK;AAAA,IACH;AAAA,IACA,CAAC7X,MAAM;AACL,MAAAA,EAAE,eAAA,GACF6X,EAAK,UAAU,IAAI,WAAW;AAAA,IAChC;AAAA,IACA,EAAE,QAAAD,EAAA;AAAA,EAAO,GAGXC,EAAK;AAAA,IACH;AAAA,IACA,MAAM;AACJ,MAAAA,EAAK,UAAU,OAAO,WAAW;AAAA,IACnC;AAAA,IACA,EAAE,QAAAD,EAAA;AAAA,EAAO,GAGXC,EAAK;AAAA,IACH;AAAA,IACA,CAAC7X,MAAM;AACL,MAAAA,EAAE,eAAA,GACF6X,EAAK,UAAU,OAAO,WAAW;AACjC,YAAM9f,IAAQiI,EAAE,cAAc,QAAQ,YAAY;AAClD,MAAIjI,KACFgf,EAAU,gBAAgBhf,GAAO,KAAK;AAAA,IAE1C;AAAA,IACA,EAAE,QAAA6f,EAAA;AAAA,EAAO,GAGJC;AACT;AAKA,SAASQ,GAAgBhE,GAA6B4C,GAAiC;AACrF,QAAM,EAAE,WAAAF,GAAW,QAAAa,EAAA,IAAWX,GACxBgB,IAAO,SAAS,cAAc,KAAK;AACzC,EAAAA,EAAK,YAAY;AAEjB,QAAMC,IAAYnB,EAAU,mBAAA,EAAqB,KAAK,CAACnT,MAAMA,EAAE,UAAUyQ,EAAW,KAAK,GAEnFiE,IAAe,SAAS,cAAc,KAAK;AACjD,EAAAA,EAAa,YAAY;AAEzB,QAAM3Y,IAAQ,SAAS,cAAc,MAAM;AAC3C,EAAAA,EAAM,YAAY,wBAClBA,EAAM,cAAcuY,GAAW,UAAU7D,EAAW;AAEpD,QAAMkE,IAAY,SAAS,cAAc,QAAQ;AACjD,EAAAA,EAAU,YAAY,wBACtBA,EAAU,QAAQ;AAElB,aAAWC,KAAW5B,IAAW;AAC/B,UAAM6B,IAAS,SAAS,cAAc,QAAQ;AAC9C,IAAAA,EAAO,QAAQD,GACfC,EAAO,cAAcD,EAAQ,YAAA,GAC7BC,EAAO,WAAWD,MAAYnE,EAAW,SACzCkE,EAAU,YAAYE,CAAM;AAAA,EAC9B;AAEA,EAAAF,EAAU;AAAA,IACR;AAAA,IACA,MAAM;AACJ,MAAAxB,EAAU,qBAAqB1C,EAAW,OAAOkE,EAAU,KAAgB;AAAA,IAC7E;AAAA,IACA,EAAE,QAAAX,EAAA;AAAA,EAAO;AAGX,QAAMO,IAAY,SAAS,cAAc,QAAQ;AACjD,SAAAA,EAAU,YAAY,yBACtBA,EAAU,YAAY,KACtBA,EAAU,QAAQ,sBAClBA,EAAU;AAAA,IACR;AAAA,IACA,CAACnY,MAAM;AACL,MAAAA,EAAE,gBAAA,GACF+W,EAAU,mBAAmB1C,EAAW,KAAK;AAAA,IAC/C;AAAA,IACA,EAAE,QAAAuD,EAAA;AAAA,EAAO,GAGXU,EAAa,YAAY3Y,CAAK,GAC9B2Y,EAAa,YAAYC,CAAS,GAElCN,EAAK,YAAYK,CAAY,GAC7BL,EAAK,YAAYE,CAAS,GAEnBF;AACT;AAKA,SAASV,GAA0BN,GAAiC;AAClE,QAAM,EAAE,QAAAhf,GAAQ,WAAA8e,GAAW,QAAAa,EAAA,IAAWX,GAChCY,IAAO,SAAS,cAAc,KAAK;AACzC,EAAAA,EAAK,YAAY;AAEjB,QAAMa,IAAY3B,EAAU,mBAAA,GACtB4B,wBAAiB,IAAI;AAAA,IACzB,GAAI1gB,EAAO,kBAAkB,CAAA;AAAA,IAC7B,GAAIA,EAAO,qBAAqB,CAAA;AAAA,IAChC,GAAIA,EAAO,aAAa,IAAI,CAAC2N,MAAMA,EAAE,KAAK,KAAK,CAAA;AAAA,EAAC,CACjD,GAGKgT,IAAkBF,EAAU,OAAO,CAAC9U,MAAM,CAAC+U,EAAW,IAAI/U,EAAE,KAAK,CAAC;AAExE,MAAIgV,EAAgB,WAAW,GAAG;AAChC,UAAMC,IAAQ,SAAS,cAAc,KAAK;AAC1C,IAAAA,EAAM,YAAY,yBAClBA,EAAM,cAAc,yBACpBhB,EAAK,YAAYgB,CAAK;AAAA,EACxB;AACE,eAAW9gB,KAAS6gB,GAAiB;AACnC,YAAMX,IAAO,SAAS,cAAc,KAAK;AACzC,MAAAA,EAAK,YAAY,kCACjBA,EAAK,cAAclgB,EAAM,QACzBkgB,EAAK,YAAY,IACjBA,EAAK,QAAQ,gBAAgBlgB,EAAM,KAAK,eAExCkgB,EAAK;AAAA,QACH;AAAA,QACA,CAACjY,MAAM;AACL,UAAAA,EAAE,cAAc,QAAQ,cAAcjI,EAAM,KAAK,GACjDkgB,EAAK,UAAU,IAAI,UAAU;AAAA,QAC/B;AAAA,QACA,EAAE,QAAAL,EAAA;AAAA,MAAO,GAGXK,EAAK;AAAA,QACH;AAAA,QACA,MAAM;AACJ,UAAAA,EAAK,UAAU,OAAO,UAAU;AAAA,QAClC;AAAA,QACA,EAAE,QAAAL,EAAA;AAAA,MAAO,GAGXC,EAAK,YAAYI,CAAI;AAAA,IACvB;AAGF,SAAOJ;AACT;AAKA,SAAST,GAAmBN,GAAmBG,GAAiC;AAC9E,QAAM,EAAE,QAAAhf,GAAQ,WAAA8e,GAAW,QAAAa,EAAA,IAAWX,GAChCzS,IAAQ,SAAS,cAAc,KAAK;AAC1C,SAAAA,EAAM,YAAY,qBAGlBA,EAAM;AAAA,IACJsU;AAAA,MACE;AAAA,MACAhC;AAAA,MACA,CAACiC,MAAY;AACX,QAAAhC,EAAU,cAAcgC,CAAO;AAAA,MACjC;AAAA,MACAnB;AAAA,IAAA;AAAA,EACF,GAIFpT,EAAM;AAAA,IACJsU;AAAA,MACE;AAAA,MACA7gB,EAAO,cAAc;AAAA,MACrB,CAAC8gB,MAAY;AACX,QAAAhC,EAAU,eAAe,cAAcgC,CAAO;AAAA,MAChD;AAAA,MACAnB;AAAA,IAAA;AAAA,EACF,GAIFpT,EAAM;AAAA,IACJsU;AAAA,MACE;AAAA,MACA7gB,EAAO,kBAAkB;AAAA,MACzB,CAAC8gB,MAAY;AACX,QAAAhC,EAAU,eAAe,kBAAkBgC,CAAO;AAAA,MACpD;AAAA,MACAnB;AAAA,IAAA;AAAA,EACF,GAGKpT;AACT;AAKA,SAASsU,EACPnZ,GACAoZ,GACAC,GACApB,GACa;AACb,QAAMV,IAAU,SAAS,cAAc,OAAO;AAC9C,EAAAA,EAAQ,YAAY;AAEpB,QAAM+B,IAAQ,SAAS,cAAc,OAAO;AAC5C,EAAAA,EAAM,OAAO,YACbA,EAAM,UAAUF,GAChBE,EAAM,iBAAiB,UAAU,MAAMD,EAASC,EAAM,OAAO,GAAG,EAAE,QAAArB,GAAQ;AAE1E,QAAMsB,IAAO,SAAS,cAAc,MAAM;AAC1C,SAAAA,EAAK,cAAcvZ,GAEnBuX,EAAQ,YAAY+B,CAAK,GACzB/B,EAAQ,YAAYgC,CAAI,GAEjBhC;AACT;AChaO,SAASiC,GAAoBnhB,GAAmBgT,GAAoBiM,GAAgC;AACzG,SAAAjM,EAAM,YAAY,mBAClBA,EAAM,aAAa,oBAAoB,OAAOhT,EAAI,gBAAgB,CAAC,CAAC,GACpEgT,EAAM,aAAa,kBAAkB,OAAOhT,EAAI,iBAAiB,EAAE,CAAC,GACpEgT,EAAM,aAAa,QAAQ,KAAK,GAGhCA,EAAM,YAAY,IAElBiM,EAAI,QAAQ,QAAQ,CAAC7d,GAAKwS,MAAW;AACnC,UAAMvQ,IAAO,SAAS,cAAc,KAAK;AAKzC,QAJAA,EAAK,YAAY,QACjBA,EAAK,aAAa,YAAY,OAAOuQ,CAAM,CAAC,GAC5CvQ,EAAK,aAAa,QAAQ,UAAU,GAEhCuQ,MAAW,GAAG;AAEhB,YAAMwN,IAAS,OAAOphB,EAAI,aAAa,KAAK;AAC5C,MAAAqD,EAAK,MAAM,cAAc,GAAG+d,CAAM;AAGlC,YAAMxD,IAAS,OAAO5d,EAAI,aAAa,GACjCsT,IAAM,SAAS,cAAc,QAAQ;AAC3C,MAAAA,EAAI,OAAO,UACXA,EAAI,YAAY,gBAChBA,EAAI,aAAa,cAActT,EAAI,kBAAkB,mBAAmB,cAAc,GACtFif,EAAI,QAAQ3L,GAAK2L,EAAI,YAAYjf,EAAI,kBAAkB,aAAa,QAAQ,CAAC,GAC7EsT,EAAI,iBAAiB,SAAS,CAACtL,MAAM;AACnC,QAAAA,EAAE,gBAAA,GACFiX,EAAI,SAASrB,CAAM;AAAA,MACrB,CAAC,GACDva,EAAK,YAAYiQ,CAAG;AAGpB,YAAM3L,IAAQ,SAAS,cAAc,MAAM;AAC3C,MAAAA,EAAM,YAAY,eAClBA,EAAM,cAAc,OAAO3H,EAAI,gBAAgB,EAAE,GACjDqD,EAAK,YAAYsE,CAAK;AAGtB,YAAM6L,IAAQ,SAAS,cAAc,MAAM;AAC3C,MAAAA,EAAM,YAAY,eAClBA,EAAM,cAAc,KAAK,OAAOxT,EAAI,eAAe,KAAK,CAAC,KACzDqD,EAAK,YAAYmQ,CAAK;AAAA,IACxB,OAAO;AAEL,YAAM1T,IAAQE,EAAIoB,EAAI,KAAK;AAC3B,MAAAiC,EAAK,cAAcvD,KAAS,OAAO,OAAOA,CAAK,IAAI;AAAA,IACrD;AAEA,IAAAkT,EAAM,YAAY3P,CAAI;AAAA,EACxB,CAAC,GAEM;AACT;AAKO,SAASge,GAAmBrhB,GAAmBgT,GAAoBxS,GAAkC;AAC1G,SAAAwS,EAAM,YAAY,kBAClBA,EAAM,aAAa,oBAAoB,OAAOhT,EAAI,gBAAgB,CAAC,CAAC,GACpEgT,EAAM,aAAa,kBAAkB,OAAOhT,EAAI,iBAAiB,EAAE,CAAC,GACpEgT,EAAM,YAAY,IAElBxS,EAAQ,QAAQ,CAACY,GAAKwS,MAAW;AAC/B,UAAMvQ,IAAO,SAAS,cAAc,KAAK;AAKzC,QAJAA,EAAK,YAAY,QACjBA,EAAK,aAAa,YAAY,OAAOuQ,CAAM,CAAC,GAC5CvQ,EAAK,aAAa,QAAQ,UAAU,GAEhCuQ,MAAW,GAAG;AAEhB,YAAMwN,IAAS,OAAOphB,EAAI,aAAa,KAAK;AAE5C,MAAAqD,EAAK,MAAM,cAAc,GAAG+d,IAAS,EAAE;AAEvC,YAAMzZ,IAAQ,SAAS,cAAc,MAAM;AAC3C,MAAAA,EAAM,YAAY,eAClBA,EAAM,cAAc,OAAO3H,EAAI,gBAAgB,EAAE,GACjDqD,EAAK,YAAYsE,CAAK;AAAA,IACxB,OAAO;AAEL,YAAM7H,IAAQE,EAAIoB,EAAI,KAAK;AAC3B,MAAAiC,EAAK,cAAcvD,KAAS,OAAO,OAAOA,CAAK,IAAI;AAAA,IACrD;AAEA,IAAAkT,EAAM,YAAY3P,CAAI;AAAA,EACxB,CAAC,GAEM;AACT;AAKO,SAASie,GAAyBthB,GAAmBgT,GAAoBxS,GAAkC;AAChH,SAAAwS,EAAM,YAAY,yBAElBA,EAAM,aAAa,QAAQ,cAAc,GACzCA,EAAM,YAAY,IAElBxS,EAAQ,QAAQ,CAACY,GAAKwS,MAAW;AAC/B,UAAMvQ,IAAO,SAAS,cAAc,KAAK;AAKzC,QAJAA,EAAK,YAAY,QACjBA,EAAK,aAAa,YAAY,OAAOuQ,CAAM,CAAC,GAGxCA,MAAW,GAAG;AAEhB,YAAMjM,IAAQ,SAAS,cAAc,MAAM;AAC3C,MAAAA,EAAM,YAAY,eAClBA,EAAM,cAAc,eACpBtE,EAAK,YAAYsE,CAAK;AAAA,IACxB,OAAO;AAEL,YAAM7H,IAAQE,EAAIoB,EAAI,KAAK;AAC3B,MAAAiC,EAAK,cAAcvD,KAAS,OAAO,OAAOA,CAAK,IAAI;AAAA,IACrD;AAEA,IAAAkT,EAAM,YAAY3P,CAAI;AAAA,EACxB,CAAC,GAEM;AACT;;AChHO,MAAMke,UAAoBrf,EAA4B;AAAA,EAClD,OAAO;AAAA,EACE,UAAU;AAAA;AAAA,EAG5B,OAAgB,WAAW;AAAA,EAE3B,IAAuB,gBAAsC;AAC3D,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,eAAe;AAAA,MACf,WAAW;AAAA,IAAA;AAAA,EAEf;AAAA;AAAA,EAGQ,WAAW;AAAA,EACX,iBAAiB;AAAA,EACjB,cAAkC;AAAA,EAClC,qCAA0C,IAAA;AAAA,EAC1C,mCAAgC,IAAA;AAAA,EAChC,kBAAkB;AAAA,EAClB,kBAA4D,CAAA;AAAA,EAC5D,iBAAqC;AAAA,EACrC,mBAAuC;AAAA,EACvC,0CAA0B,IAAA;AAAA,EAC1B,oCAAoB,IAAA;AAAA;AAAA;AAAA;AAAA,EAKpB,sBAA+B;AACrC,YAAQ,KAAK,OAAO,aAAa,UAAU,KAAK;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA,EAKA,IAAY,iBAA0C;AAEpD,UAAM0Q,IADS,KAAK,KACA,iBAAiB,WAAW,QAAQ;AAExD,QAAIA,MAAS,MAASA,MAAS,MAAO,QAAO;AAC7C,QAAIA,MAAS,MAAQA,MAAS,MAAM;AAClC,YAAMC,IAAO,KAAK,YAAY;AAC9B,UAAIA,KAAQ,iBAAiBA,CAAI,EAAE,iBAAiB,yBAAyB,EAAE,KAAA,MAAW;AACxF,eAAO;AAAA,IAEX;AACA,WAAO,KAAK,OAAO,aAAa;AAAA,EAClC;AAAA;AAAA;AAAA,EAMS,SAAe;AACtB,SAAK,WAAW,IAChB,KAAK,iBAAiB,IACtB,KAAK,cAAc,MACnB,KAAK,eAAe,MAAA,GACpB,KAAK,kBAAkB,CAAA,GACvB,KAAK,iBAAiB,MACtB,KAAK,wBAAA,GACL,KAAK,oBAAoB,MAAA,GACzB,KAAK,cAAc,MAAA;AAAA,EACrB;AAAA;AAAA;AAAA,EAMS,eAAgD;AAIvD,SADsB,KAAK,QAAQ,iBAAiB,KAAK,YAAY,iBAAiB,QAChE;AAItB,aAAO;AAAA,QACL,IAAI0O,EAAY;AAAA,QAChB,OAAO;AAAA,QACP,MAAM;AAAA,QACN,SAAS;AAAA,QACT,OAAO;AAAA,QACP,QAAQ,CAACxY,MAAc,KAAK,YAAYA,CAAS;AAAA,MAAA;AAAA,EAErD;AAAA;AAAA;AAAA,EAMS,YAAYxI,GAA0C;AAO7D,QALI,CAAC,KAAK,kBAAkB,KAAK,OAAO,WAAW,MAAS,KAAK,0BAC/D,KAAK,iBAAiB,IACtB,KAAK,WAAW,KAGd,CAAC,KAAK;AACR,aAAO,CAAC,GAAGA,CAAI;AAGjB,UAAM2b,IAASD,GAAoB,KAAK,MAAM;AAC9C,QAAIC,EAAO,SAAS;AAClB,kBAAK,KAAK,kBAAkBA,EAAO,KAAK,IAAI,CAAC,EAAE,GACxC,CAAC,GAAG3b,CAAI;AAOjB,QAJA,KAAK,oBAAA,GACL,KAAK,kBAAkB,KAAK,OAAO,mBAAmB,IAGlD,KAAK,aAAa,SAAS,KAAK,KAAK,mBAAmB,KAAK,aAAa;AAC5E,YAAMihB,IAAU9C,EAAgB,KAAK,YAAY,IAAI;AACrD,iBAAW3Q,KAAOyT;AAChB,aAAK,aAAa,IAAIzT,CAAG;AAAA,IAE7B;AAMA,QAHA,KAAK,cAAcuO,GAAW/b,GAAwB,KAAK,MAAM,GAG7D,KAAK,aAAa,SAAS,KAAK,KAAK,iBAAiB;AACxD,YAAMihB,IAAU9C,EAAgB,KAAK,YAAY,IAAI;AACrD,iBAAW3Q,KAAOyT;AAChB,aAAK,aAAa,IAAIzT,CAAG;AAAA,IAE7B;AAGA,UAAM0T,IAAc,KAAK,OAAO,eAAe,IACzCC,IAA2BpD;AAAA,MAC/B,KAAK,YAAY;AAAA,MACjB,KAAK;AAAA,MACL,KAAK;AAAA,IAAA,EACL,IAAI,CAACqD,OAAQ;AAAA,MACb,eAAeA,EAAG;AAAA,MAClB,cAAcA,EAAG;AAAA,MACjB,cAAcA,EAAG;AAAA,MACjB,gBAAgBA,EAAG;AAAA,MACnB,oBAAoB,EAAQA,EAAG,UAAU;AAAA,MACzC,iBAAiB,KAAK,aAAa,IAAIA,EAAG,MAAM;AAAA,MAChD,iBAAiBA,EAAG,YAAY;AAAA,MAChC,eAAeA,EAAG,QAAQF;AAAA,MAC1B,cAAcE,EAAG;AAAA,MACjB,GAAGA,EAAG;AAAA,IAAA,EACN;AAGF,SAAK,cAAc,MAAA;AACnB,UAAM5O,wBAAyB,IAAA;AAC/B,eAAW/S,KAAO0hB,GAAU;AAC1B,YAAM3T,IAAM/N,EAAI;AAChB,MAAA+S,EAAmB,IAAIhF,CAAG,GAEtB,CAAC,KAAK,oBAAoB,IAAIA,CAAG,KAAM/N,EAAI,eAA0B,KACvE,KAAK,cAAc,IAAI+N,CAAG;AAAA,IAE9B;AACA,gBAAK,sBAAsBgF,GAKpB2O;AAAA,EACT;AAAA,EAES,eAAelhB,GAAkD;AACxE,QAAI,CAAC,KAAK,YAAY,CAAC,KAAK;AAC1B,aAAO,CAAC,GAAGA,CAAO;AAGpB,UAAMohB,IAA+B,CAAA,GAG/BC,KAAmB,KAAK,OAAO,kBAAkB,CAAA,GAAI,IAAI,CAACjW,MAAM,KAAK,eAAe,IAAIA,CAAC,KAAKA,CAAC,EAAE,KAAK,KAAK;AACjH,IAAAgW,EAAa,KAAK;AAAA,MAChB,OAAO;AAAA,MACP,QAAQC,KAAmB;AAAA,MAC3B,OAAO;AAAA,IAAA,CACR;AAGD,eAAW/D,KAAU,KAAK,YAAY;AACpC,iBAAWC,KAAM,KAAK,OAAO,eAAe,CAAA,GAAI;AAC9C,cAAMI,IAAWhC,GAAe,CAAC2B,CAAM,GAAGC,EAAG,KAAK,GAC5C+D,IAAc/D,EAAG,UAAU,KAAK,eAAe,IAAIA,EAAG,KAAK,KAAKA,EAAG;AACzE,QAAA6D,EAAa,KAAK;AAAA,UAChB,OAAOzD;AAAA,UACP,QAAQ,GAAGL,CAAM,MAAMgE,CAAW,KAAK/D,EAAG,OAAO;AAAA,UACjD,OAAO;AAAA,UACP,MAAM;AAAA,QAAA,CACP;AAAA,MACH;AAIF,WAAI,KAAK,OAAO,cACd6D,EAAa,KAAK;AAAA,MAChB,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,MAAM;AAAA,IAAA,CACP,GAGIA;AAAA,EACT;AAAA,EAES,UAAU5hB,GAA8BgT,GAA6B;AAC5E,UAAM+O,IAAW/hB;AAGjB,WAAI+hB,EAAS,iBAAiBA,EAAS,qBAC9BZ,GAAoBY,GAAU/O,GAAO;AAAA,MAC1C,SAAS,KAAK;AAAA,MACd,UAAU,CAACjF,MAAQ,KAAK,OAAOA,CAAG;AAAA,MAClC,aAAa,CAACiU,MAAY,KAAK,YAAYA,CAAO;AAAA,MAClD,SAAS,CAAC3I,GAAI3R,MAAS,KAAK,QAAQ2R,GAAI3R,CAAI;AAAA,IAAA,CAC7C,IAICqa,EAAS,kBAAkB,UAAa,KAAK,WACxCV,GAAmBU,GAAU/O,GAAO,KAAK,WAAW,KAI7D,KAAK,oBAAoBA,CAAK,GAEvB;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,oBAAoBA,GAA0B;AAOpD,KAJEA,EAAM,UAAU,SAAS,iBAAiB,KAC1CA,EAAM,UAAU,SAAS,gBAAgB,KACzCA,EAAM,UAAU,SAAS,uBAAuB,OAIhDA,EAAM,UAAU,OAAO,mBAAmB,kBAAkB,uBAAuB,GACnFA,EAAM,UAAU,IAAI,eAAe,GAGnCA,EAAM,gBAAgB,kBAAkB,GAGxCA,EAAM,YAAY;AAAA,EAEtB;AAAA,EAES,cAAoB;AAE3B,IAAI,KAAK,YAAY,KAAK,OAAO,kBAAkB,KAAK,cACtD,KAAK,uBAAA,IAEL,KAAK,wBAAA;AAIP,UAAM3G,IAAQ,KAAK;AACnB,QAAIA,MAAU,MAAS,KAAK,cAAc,SAAS,EAAG;AAEtD,UAAM+G,IAAO,KAAK,YAAY,cAAc,OAAO;AACnD,QAAI,CAACA,EAAM;AAEX,UAAMC,IAAYhH,MAAU,SAAS,sBAAsB;AAC3D,eAAW2G,KAASI,EAAK,iBAAiB,mCAAmC,GAAG;AAC9E,YAAMrF,IAAOiF,EAAsB,QAAQ;AAC3C,MAAIjF,KAAO,KAAK,cAAc,IAAIA,CAAG,MACnCiF,EAAM,UAAU,IAAIK,CAAS,GAC7BL,EAAM,iBAAiB,gBAAgB,MAAMA,EAAM,UAAU,OAAOK,CAAS,GAAG,EAAE,MAAM,GAAA,CAAM;AAAA,IAElG;AACA,SAAK,cAAc,MAAA;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKQ,yBAA+B;AACrC,QAAI,CAAC,KAAK,YAAa;AAEvB,UAAM9M,IAAa,KAAK;AACxB,QAAI,CAACA,EAAY;AAGjB,UAAMwC,IACJxC,EAAW,cAAc,kBAAkB,KAC3CA,EAAW,cAAc,mBAAmB,KAC5CA,EAAW,SAAS,CAAC;AACvB,QAAI,CAACwC,EAAW;AAGhB,IAAK,KAAK,qBACR,KAAK,mBAAmB,SAAS,cAAc,KAAK,GACpD,KAAK,iBAAiB,YAAY,4BAClCA,EAAU,YAAY,KAAK,gBAAgB;AAI7C,UAAMkZ,IAA8B;AAAA,MAClC,eAAe;AAAA,MACf,cAAc;AAAA,MACd,qBAAqB;AAAA,MACrB,cAAc,KAAK,YAAY;AAAA,MAC/B,GAAG,KAAK,YAAY;AAAA,IAAA;AAItB,IAAAX,GAAyBW,GAAe,KAAK,kBAAkB,KAAK,WAAW;AAAA,EACjF;AAAA;AAAA;AAAA;AAAA,EAKQ,0BAAgC;AACtC,IAAI,KAAK,qBACP,KAAK,iBAAiB,OAAA,GACtB,KAAK,mBAAmB;AAAA,EAE5B;AAAA;AAAA;AAAA,EAMA,OAAOlU,GAAmB;AACxB,IAAI,KAAK,aAAa,IAAIA,CAAG,IAC3B,KAAK,aAAa,OAAOA,CAAG,IAE5B,KAAK,aAAa,IAAIA,CAAG,GAE3B,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,OAAOA,GAAmB;AACxB,SAAK,aAAa,IAAIA,CAAG,GACzB,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,SAASA,GAAmB;AAC1B,SAAK,aAAa,OAAOA,CAAG,GAC5B,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,YAAkB;AAChB,QAAI,KAAK,aAAa;AACpB,YAAMyT,IAAU9C,EAAgB,KAAK,YAAY,IAAI;AACrD,iBAAW3Q,KAAOyT;AAChB,aAAK,aAAa,IAAIzT,CAAG;AAE3B,WAAK,cAAA;AAAA,IACP;AAAA,EACF;AAAA,EAEA,cAAoB;AAClB,SAAK,aAAa,MAAA,GAClB,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,WAAWA,GAAsB;AAC/B,WAAO,KAAK,aAAa,IAAIA,CAAG;AAAA,EAClC;AAAA;AAAA;AAAA,EAMA,cAAoB;AAClB,IAAI,KAAK,gBAAgB,WAAW,KAClC,KAAK,uBAAA,GAEP,KAAK,WAAW,IAChB,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,eAAqB;AACnB,SAAK,WAAW,IAChB,KAAK,cAAc,MACnB,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,gBAAyB;AACvB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,iBAAqC;AACnC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,kBAAkBmU,GAAwB;AACxC,SAAK,OAAO,iBAAiBA,GAC7B,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,qBAAqBA,GAAwB;AAC3C,SAAK,OAAO,oBAAoBA,GAChC,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,eAAeA,GAAiC;AAC9C,SAAK,OAAO,cAAcA,GAC1B,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,UAAgB;AACd,SAAK,cAAc,MACnB,KAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA,EAMA,YAAkB;AAEhB,IADa,KAAK,KACb,cAAcX,EAAY,QAAQ;AAAA,EACzC;AAAA,EAEA,YAAkB;AAEhB,IADa,KAAK,KACb,eAAA;AAAA,EACP;AAAA,EAEA,cAAoB;AAElB,IADa,KAAK,KACb,gBAAgBA,EAAY,QAAQ;AAAA,EAC3C;AAAA,EAEA,iBAA0B;AAExB,WADa,KAAK,KACN,oBAAoBA,EAAY;AAAA,EAC9C;AAAA;AAAA;AAAA,EAMA,IAAY,cAA8B;AAExC,WADa,KAAK,KACL,WAAW,CAAA;AAAA,EAC1B;AAAA,EAEQ,sBAA4B;AAClC,UAAMX,IAAkB,KAAK,mBAAA;AAC7B,SAAK,eAAe,MAAA;AACpB,eAAW7gB,KAAS6gB;AAClB,WAAK,eAAe,IAAI7gB,EAAM,OAAOA,EAAM,MAAM;AAAA,EAErD;AAAA,EAEQ,qBAAkC;AACxC,WAAI,KAAK,gBAAgB,SAAS,IACzB,KAAK,kBAEP,KAAK,uBAAA;AAAA,EACd;AAAA,EAEQ,yBAAsC;AAC5C,UAAM0D,IAAO,KAAK;AAClB,QAAI;AACF,YAAMjD,IAAUiD,EAAK,gBAAA,KAAqBA,EAAK,WAAW,CAAA;AAC1D,kBAAK,kBAAkBjD,EACpB,OAAO,CAACY,MAA2B,CAACA,EAAI,MAAM,WAAW,SAAS,CAAC,EACnE,IAAI,CAACA,OAA6C;AAAA,QACjD,OAAOA,EAAI;AAAA,QACX,QAAQA,EAAI,UAAUA,EAAI;AAAA,MAAA,EAC1B,GACG,KAAK;AAAA,IACd,QAAQ;AACN,aAAO,CAAA;AAAA,IACT;AAAA,EACF;AAAA,EAEQ,YAAY2H,GAA6C;AAC/D,SAAK,iBAAiBA,GAElB,KAAK,gBAAgB,WAAW,KAClC,KAAK,uBAAA;AAGP,UAAMgW,IAA4B;AAAA,MAChC,eAAe,CAACoD,MAAY;AAC1B,QAAIA,IACF,KAAK,YAAA,IAEL,KAAK,aAAA,GAEP,KAAK,aAAA;AAAA,MACP;AAAA,MACA,kBAAkB,CAACpiB,GAAO8f,MAAS,KAAK,eAAe9f,GAAO8f,CAAI;AAAA,MAClE,uBAAuB,CAAC9f,GAAO8f,MAAS,KAAK,oBAAoB9f,GAAO8f,CAAI;AAAA,MAC5E,iBAAiB,CAAC9f,GAAOygB,MAAY,KAAK,cAAczgB,GAAOygB,CAAO;AAAA,MACtE,oBAAoB,CAACzgB,MAAU,KAAK,iBAAiBA,CAAK;AAAA,MAC1D,sBAAsB,CAACA,GAAOygB,MAAY,KAAK,mBAAmBzgB,GAAOygB,CAAO;AAAA,MAChF,gBAAgB,CAACC,GAAQ3gB,MAAU;AACjC,aAAK,OAAO2gB,CAAM,IAAI3gB,GAClB,KAAK,YAAU,KAAK,QAAA;AAAA,MAC1B;AAAA,MACA,oBAAoB,MAAM,KAAK,mBAAA;AAAA,IAAmB;AAGpD,WAAO+e,GAAiB9V,GAAW,KAAK,QAAQ,KAAK,UAAUgW,CAAS;AAAA,EAC1E;AAAA,EAEQ,eAAqB;AAC3B,IAAK,KAAK,mBACV,KAAK,eAAe,YAAY,IAChC,KAAK,YAAY,KAAK,cAAc;AAAA,EACtC;AAAA,EAEQ,eAAehf,GAAe4f,GAA8C;AAClF,QAAIA,MAAa,aAAa;AAC5B,YAAM5H,IAAU,KAAK,OAAO,kBAAkB,CAAA;AAC9C,MAAKA,EAAQ,SAAShY,CAAK,MACzB,KAAK,OAAO,iBAAiB,CAAC,GAAGgY,GAAShY,CAAK;AAAA,IAEnD,OAAO;AACL,YAAMgY,IAAU,KAAK,OAAO,qBAAqB,CAAA;AACjD,MAAKA,EAAQ,SAAShY,CAAK,MACzB,KAAK,OAAO,oBAAoB,CAAC,GAAGgY,GAAShY,CAAK;AAAA,IAEtD;AAEA,SAAK,qBAAqBA,GAAO4f,CAAQ,GACrC,KAAK,YAAU,KAAK,QAAA,GACxB,KAAK,aAAA;AAAA,EACP;AAAA,EAEQ,oBAAoB5f,GAAe4f,GAA8C;AACvF,IAAIA,MAAa,cACf,KAAK,OAAO,kBAAkB,KAAK,OAAO,kBAAkB,CAAA,GAAI,OAAO,CAAC/T,MAAMA,MAAM7L,CAAK,IAEzF,KAAK,OAAO,qBAAqB,KAAK,OAAO,qBAAqB,CAAA,GAAI,OAAO,CAAC6L,MAAMA,MAAM7L,CAAK,GAG7F,KAAK,YAAU,KAAK,QAAA,GACxB,KAAK,aAAA;AAAA,EACP;AAAA,EAEQ,qBAAqBA,GAAeqiB,GAA2D;AACrG,IAAIA,MAAe,gBACjB,KAAK,OAAO,kBAAkB,KAAK,OAAO,kBAAkB,CAAA,GAAI,OAAO,CAACxW,MAAMA,MAAM7L,CAAK,IAEvFqiB,MAAe,mBACjB,KAAK,OAAO,qBAAqB,KAAK,OAAO,qBAAqB,CAAA,GAAI,OAAO,CAACxW,MAAMA,MAAM7L,CAAK,IAE7FqiB,MAAe,aACjB,KAAK,OAAO,eAAe,KAAK,OAAO,eAAe,CAAA,GAAI,OAAO,CAACxU,MAAMA,EAAE,UAAU7N,CAAK;AAAA,EAE7F;AAAA,EAEQ,cAAcA,GAAeygB,GAAwB;AAC3D,UAAMzI,IAAU,KAAK,OAAO,eAAe,CAAA;AAC3C,IAAKA,EAAQ,KAAK,CAACnK,MAAMA,EAAE,UAAU7N,CAAK,MACxC,KAAK,OAAO,cAAc,CAAC,GAAGgY,GAAS,EAAE,OAAAhY,GAAO,SAAAygB,GAAS,IAG3D,KAAK,qBAAqBzgB,GAAO,QAAQ,GACrC,KAAK,YAAU,KAAK,QAAA,GACxB,KAAK,aAAA;AAAA,EACP;AAAA,EAEQ,iBAAiBA,GAAqB;AAC5C,SAAK,OAAO,eAAe,KAAK,OAAO,eAAe,CAAA,GAAI,OAAO,CAAC6N,MAAMA,EAAE,UAAU7N,CAAK,GACrF,KAAK,YAAU,KAAK,QAAA,GACxB,KAAK,aAAA;AAAA,EACP;AAAA,EAEQ,mBAAmBA,GAAeygB,GAAwB;AAChE,UAAM/D,IAAc,KAAK,OAAO,eAAe,CAAA,GACzC4F,IAAa5F,EAAY,UAAU,CAAC7O,MAAMA,EAAE,UAAU7N,CAAK;AACjE,IAAIsiB,KAAc,MAChB5F,EAAY4F,CAAU,IAAI,EAAE,GAAG5F,EAAY4F,CAAU,GAAG,SAAA7B,EAAA,GACxD,KAAK,OAAO,cAAc,CAAC,GAAG/D,CAAW,IAEvC,KAAK,YAAU,KAAK,QAAA;AAAA,EAC1B;AAAA;AAAA;AAAA,EAMkB,SAASjN;AAAAA;AAG7B;AClnBO,SAAS8S,GAA8Bxe,GAAqC;AAEjF,QAAMye,IAAOze,EAAO,QAAQ,CAAA;AAC5B,SAAOye,EAAK,iBAAiB,MAAQA,EAAK,oBAAoB;AAChE;AAUO,SAASC,GAAWhiB,GAAmBiiB,GAAmBC,GAA2B;AAG1F,MAFID,MAAcC,KACdD,IAAY,KAAKA,KAAajiB,EAAQ,UACtCkiB,IAAU,KAAKA,IAAUliB,EAAQ,OAAQ,QAAOA;AAEpD,QAAM2C,IAAS,CAAC,GAAG3C,CAAO,GACpB,CAACmiB,CAAO,IAAIxf,EAAO,OAAOsf,GAAW,CAAC;AAC5C,SAAAtf,EAAO,OAAOuf,GAAS,GAAGC,CAAO,GAC1Bxf;AACT;;ACNO,MAAMyf,WAAsB1gB,EAA8B;AAAA,EACtD,OAAO;AAAA,EACE,UAAU;AAAA,EAE5B,IAAuB,gBAAwC;AAC7D,WAAO;AAAA,MACL,WAAW;AAAA;AAAA,IAAA;AAAA,EAEf;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAY,gBAAyC;AAEnD,WAAK,KAAK,qBAGN,KAAK,OAAO,cAAc,SAAkB,KAAK,OAAO,YAGxD,KAAK,OAAO,mBAAmB,KAAc,MAC7C,KAAK,OAAO,mBAAmB,IAAa,UAPX;AAAA,EAUvC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAY,qBAA8B;AAExC,UAAM0Q,IADS,KAAK,KACA,iBAAiB,WAAW,QAAQ;AAGxD,QAAIA,MAAS,MAASA,MAAS,MAAO,QAAO;AAG7C,QAAIA,MAAS,MAAQA,MAAS,KAAM,QAAO;AAG3C,UAAMC,IAAO,KAAK,YAAY;AAC9B,WAAIA,IACc,iBAAiBA,CAAI,EAAE,iBAAiB,yBAAyB,EAAE,KAAA,MAChE,MAGd;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,IAAY,oBAA4B;AAEtC,QAAI,KAAK,OAAO,sBAAsB;AACpC,aAAO,KAAK,OAAO;AAIrB,UAAMA,IAAO,KAAK,YAAY;AAC9B,QAAIA,GAAM;AACR,YAAM8C,IAAc,iBAAiB9C,CAAI,EAAE,iBAAiB,0BAA0B,EAAE,KAAA,GAClFrP,IAAS,SAASmS,GAAa,EAAE;AACvC,UAAI,CAAC,MAAMnS,CAAM,EAAG,QAAOA;AAAA,IAC7B;AAEA,WAAO;AAAA,EACT;AAAA;AAAA,EAGQ,aAAa;AAAA,EACb,eAA8B;AAAA,EAC9B,eAA8B;AAAA,EAC9B,YAA2B;AAAA;AAAA;AAAA,EAK1B,OAAOC,GAAiE;AAC/E,UAAM,OAAOA,CAAI,GAIhBA,EAAgC;AAAA,MAC/B;AAAA,MACA,CAACuE,MAAa;AACZ,cAAM6a,IAAU7a,EAAkB;AAClC,QAAI6a,GAAQ,SAAS,OAAOA,EAAO,WAAY,YAC7C,KAAK,WAAWA,EAAO,OAAOA,EAAO,OAAO;AAAA,MAEhD;AAAA,MACA,EAAE,QAAQ,KAAK,iBAAA;AAAA,IAAiB;AAAA,EAEpC;AAAA,EAES,SAAe;AACtB,SAAK,aAAa,IAClB,KAAK,eAAe,MACpB,KAAK,eAAe,MACpB,KAAK,YAAY;AAAA,EACnB;AAAA;AAAA;AAAA,EAKS,cAAoB;AAC3B,UAAMtc,IAAa,KAAK;AACxB,QAAI,CAACA,EAAY;AAIjB,IAFgBA,EAAW,iBAAiB,qBAAqB,EAEzD,QAAQ,CAACzF,MAAW;AAC1B,YAAMgiB,IAAWhiB,GACXf,IAAQ+iB,EAAS,aAAa,YAAY;AAChD,UAAI,CAAC/iB,EAAO;AAEZ,YAAM+D,IAAS,KAAK,QAAQ,KAAK,CAAC,MAAM,EAAE,UAAU/D,CAAK,GAOnDgjB,IAAe,CALN,KAAK,KACW,aAAsB;AAAA,QACnD,MAAMrJ,EAAe;AAAA,QACrB,SAAS5V;AAAA,MAAA,CACV,EACqC,SAAS,EAAK;AACpD,UAAI,CAACA,KAAU,CAACwe,GAAcxe,CAAM,KAAK,CAACif,GAAc;AACtD,QAAAD,EAAS,YAAY;AACrB;AAAA,MACF;AAKA,MAHAA,EAAS,YAAY,IAGjB,CAAAA,EAAS,aAAa,sBAAsB,MAChDA,EAAS,aAAa,wBAAwB,MAAM,GAEpDA,EAAS,iBAAiB,aAAa,CAAC9a,MAAiB;AAEvD,cAAMgb,IADe,KAAK,eAAA,EACM,QAAQjjB,CAAK;AAC7C,aAAK,aAAa,IAClB,KAAK,eAAeA,GACpB,KAAK,eAAeijB,GAEhBhb,EAAE,iBACJA,EAAE,aAAa,gBAAgB,QAC/BA,EAAE,aAAa,QAAQ,cAAcjI,CAAK,IAG5C+iB,EAAS,UAAU,IAAI,UAAU;AAAA,MACnC,CAAC,GAEDA,EAAS,iBAAiB,WAAW,MAAM;AACzC,aAAK,aAAa,IAClB,KAAK,eAAe,MACpB,KAAK,eAAe,MACpB,KAAK,YAAY,MAEjBvc,EAAW,iBAAiB,qBAAqB,EAAE,QAAQ,CAAC0c,MAAM;AAChE,UAAAA,EAAE,UAAU,OAAO,YAAY,eAAe,eAAe,YAAY;AAAA,QAC3E,CAAC;AAAA,MACH,CAAC,GAEDH,EAAS,iBAAiB,YAAY,CAAC9a,MAAiB;AAEtD,YADAA,EAAE,eAAA,GACE,CAAC,KAAK,cAAc,KAAK,iBAAiBjI,EAAO;AAErD,cAAMiN,IAAO8V,EAAS,sBAAA,GAChBI,IAAOlW,EAAK,OAAOA,EAAK,QAAQ,GAGhCgW,IADe,KAAK,eAAA,EACM,QAAQjjB,CAAK;AAC7C,aAAK,YAAYiI,EAAE,UAAUkb,IAAOF,IAAaA,IAAa,GAE9DF,EAAS,UAAU,IAAI,aAAa,GACpCA,EAAS,UAAU,OAAO,eAAe9a,EAAE,UAAUkb,CAAI,GACzDJ,EAAS,UAAU,OAAO,cAAc9a,EAAE,WAAWkb,CAAI;AAAA,MAC3D,CAAC,GAEDJ,EAAS,iBAAiB,aAAa,MAAM;AAC3C,QAAAA,EAAS,UAAU,OAAO,eAAe,eAAe,YAAY;AAAA,MACtE,CAAC,GAEDA,EAAS,iBAAiB,QAAQ,CAAC9a,MAAiB;AAClD,QAAAA,EAAE,eAAA;AACF,cAAMmb,IAAe,KAAK,cACpBC,IAAe,KAAK,cACpBC,IAAY,KAAK;AAEvB,YAAI,CAAC,KAAK,cAAcF,MAAiB,QAAQC,MAAiB,QAAQC,MAAc;AACtF;AAGF,cAAMC,IAAmBD,IAAYD,IAAeC,IAAY,IAAIA,GAC9DE,IAAe,KAAK,eAAA,GACpBC,IAAWhB,GAAWe,GAAcH,GAAcE,CAAgB,GAElET,IAA2B;AAAA,UAC/B,OAAOM;AAAA,UACP,WAAWC;AAAA,UACX,SAASE;AAAA,UACT,aAAaE;AAAA,QAAA;AAIf,aAAK,kBAAkBA,CAAQ,GAE/B,KAAK,KAAK,eAAeX,CAAM;AAAA,MACjC,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKS,UAAU1gB,GAAsC;AACvD,QAAI,CAACA,EAAM,UAAWA,EAAM,QAAQ,eAAeA,EAAM,QAAQ;AAC/D;AAGF,UAAMsB,IAAO,KAAK,MACZggB,IAAWhgB,EAAK,WAChBjD,IAAUiD,EAAK;AAErB,QAAIggB,IAAW,KAAKA,KAAYjjB,EAAQ,OAAQ;AAEhD,UAAMsD,IAAStD,EAAQijB,CAAQ;AAC/B,QAAI,CAAC3f,KAAU,CAACwe,GAAcxe,CAAM,EAAG;AAGvC,UAAM+C,IAAS,KAAK;AAKpB,QAJwBA,EAAO,aAAsB;AAAA,MACnD,MAAM6S,EAAe;AAAA,MACrB,SAAS5V;AAAA,IAAA,CACV,EACmB,SAAS,EAAK,EAAG;AAErC,UAAMyf,IAAe,KAAK,eAAA,GACpBd,IAAYc,EAAa,QAAQzf,EAAO,KAAK;AACnD,QAAI2e,MAAc,GAAI;AAEtB,UAAMC,IAAUvgB,EAAM,QAAQ,cAAcsgB,IAAY,IAAIA,IAAY;AAGxE,QAAIC,IAAU,KAAKA,KAAWa,EAAa,OAAQ;AAGnD,UAAMG,IAAeljB,EAAQ,KAAK,CAACG,MAAMA,EAAE,UAAU4iB,EAAab,CAAO,CAAC;AAC1E,QAAI,EAAAgB,KACsB7c,EAAO,aAAsB;AAAA,MACnD,MAAM6S,EAAe;AAAA,MACrB,SAASgK;AAAA,IAAA,CACV,EACmB,SAAS,EAAK;AAGpC,kBAAK,WAAW5f,EAAO,OAAO4e,CAAO,GAGrCjf,EAAK,YAAYif,GACjBiB,GAAkB,KAAK,IAAW,GAElCxhB,EAAM,eAAA,GACNA,EAAM,gBAAA,GACC;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,iBAA2B;AACzB,WAAQ,KAAK,KAAwC,eAAA;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAAWpC,GAAe2iB,GAAuB;AAC/C,UAAMa,IAAe,KAAK,eAAA,GACpBd,IAAYc,EAAa,QAAQxjB,CAAK;AAC5C,QAAI0iB,MAAc,GAAI;AAEtB,UAAMe,IAAWhB,GAAWe,GAAcd,GAAWC,CAAO;AAG5D,SAAK,kBAAkBc,CAAQ,GAE/B,KAAK,KAAuB,eAAe;AAAA,MACzC,OAAAzjB;AAAA,MACA,WAAA0iB;AAAA,MACA,SAAAC;AAAA,MACA,aAAac;AAAA,IAAA,CACd;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,eAAeI,GAAuB;AACpC,SAAK,kBAAkBA,CAAK;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAyB;AACvB,UAAMC,IAAgB,KAAK,QAAQ,IAAI,CAACljB,MAAMA,EAAE,KAAK;AACrD,SAAK,kBAAkBkjB,CAAa;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,yBAA8C;AACpD,UAAMC,wBAAgB,IAAA;AACtB,gBAAK,YAAY,iBAAiB,iCAAiC,EAAE,QAAQ,CAACzgB,MAAS;AACrF,YAAMtD,IAAQsD,EAAK,aAAa,YAAY;AAC5C,MAAItD,KAAO+jB,EAAU,IAAI/jB,GAAOsD,EAAK,sBAAA,EAAwB,IAAI;AAAA,IACnE,CAAC,GACMygB;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,YAAYC,GAAyC;AAC3D,UAAMxd,IAAa,KAAK;AACxB,QAAI,CAACA,KAAcwd,EAAa,SAAS,EAAG;AAG5C,UAAMC,wBAAa,IAAA;AAUnB,QATAzd,EAAW,iBAAiB,iCAAiC,EAAE,QAAQ,CAAClD,MAAS;AAC/E,YAAMtD,IAAQsD,EAAK,aAAa,YAAY;AAC5C,UAAI,CAACtD,EAAO;AACZ,YAAMkkB,IAAUF,EAAa,IAAIhkB,CAAK;AACtC,UAAIkkB,MAAY,OAAW;AAC3B,YAAMC,IAASD,IAAU5gB,EAAK,sBAAA,EAAwB;AACtD,MAAI,KAAK,IAAI6gB,CAAM,IAAI,KAAGF,EAAO,IAAIjkB,GAAOmkB,CAAM;AAAA,IACpD,CAAC,GAEGF,EAAO,SAAS,EAAG;AAGvB,UAAM7iB,IAAuB,CAAA;AAU7B,QATAoF,EAAW,iBAAiB,mBAAmB,EAAE,QAAQ,CAAClD,MAAS;AACjE,YAAM6gB,IAASF,EAAO,IAAI3gB,EAAK,aAAa,YAAY,KAAK,EAAE;AAC/D,UAAI6gB,MAAW,QAAW;AACxB,cAAM7K,IAAKhW;AACX,QAAAgW,EAAG,MAAM,YAAY,cAAc6K,CAAM,OACzC/iB,EAAM,KAAKkY,CAAE;AAAA,MACf;AAAA,IACF,CAAC,GAEGlY,EAAM,WAAW,EAAG;AAGxB,IAAMoF,EAAW,KAAqB;AAEtC,UAAM4d,IAAW,KAAK;AAEtB,0BAAsB,MAAM;AAC1B,MAAAhjB,EAAM,QAAQ,CAACkY,MAAO;AACpB,QAAAA,EAAG,UAAU,IAAI,gBAAgB,GACjCA,EAAG,MAAM,YAAY;AAAA,MACvB,CAAC,GAGD,WAAW,MAAM;AACf,QAAAlY,EAAM,QAAQ,CAACkY,MAAO;AACpB,UAAAA,EAAG,MAAM,YAAY,IACrBA,EAAG,UAAU,OAAO,gBAAgB;AAAA,QACtC,CAAC;AAAA,MACH,GAAG8K,IAAW,EAAE;AAAA,IAClB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,YAAYC,GAA+B;AACjD,UAAM7d,IAAa,KAAK;AACxB,QAAI,CAACA,GAAY;AACf,MAAA6d,EAAA;AACA;AAAA,IACF;AAGA,UAAML,IAAe,KAAK,uBAAA;AAG1B,IAAAK,EAAA;AAGA,UAAMC,wBAAkB,IAAA;AAYxB,QAXA9d,EAAW,iBAAiB,iCAAiC,EAAE,QAAQ,CAAClD,MAAS;AAC/E,YAAMtD,IAAQsD,EAAK,aAAa,YAAY;AAC5C,UAAI,CAACtD,EAAO;AACZ,YAAMkkB,IAAUF,EAAa,IAAIhkB,CAAK;AACtC,UAAIkkB,MAAY,OAAW;AAC3B,YAAMK,IAAUjhB,EAAK,sBAAA,EAAwB;AAC7C,MAAI,KAAK,IAAI4gB,IAAUK,CAAO,IAAI,KAChCD,EAAY,IAAItkB,CAAK;AAAA,IAEzB,CAAC,GAEGskB,EAAY,SAAS,EAAG;AAG5B,UAAMljB,IAAuB,CAAA;AAU7B,QATAoF,EAAW,iBAAiB,mBAAmB,EAAE,QAAQ,CAAClD,MAAS;AACjE,YAAMtD,IAAQsD,EAAK,aAAa,YAAY;AAC5C,UAAItD,KAASskB,EAAY,IAAItkB,CAAK,GAAG;AACnC,cAAMsZ,IAAKhW;AACX,QAAAgW,EAAG,UAAU,IAAI,gBAAgB,GACjClY,EAAM,KAAKkY,CAAE;AAAA,MACf;AAAA,IACF,CAAC,GAEGlY,EAAM,WAAW,EAAG;AAGxB,UAAMgjB,IAAW,KAAK;AACtB,eAAW,MAAM;AACf,MAAAhjB,EAAM,QAAQ,CAACkY,MAAOA,EAAG,UAAU,OAAO,gBAAgB,CAAC;AAAA,IAC7D,GAAG8K,IAAW,EAAE;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKQ,kBAAkBX,GAA0B;AAClD,UAAM3c,IAAS,KAAK,MACdoO,IAAY,KAAK;AAEvB,QAAIA,MAAc,UAAU,KAAK,YAAY;AAC3C,YAAM8O,IAAe,KAAK,uBAAA;AAC1B,MAAAld,EAAO,eAAe2c,CAAQ,GACxB,KAAK,WAAW,KAAqB,cAC3C,KAAK,YAAYO,CAAY;AAAA,IAC/B,MAAA,CAAW9O,MAAc,SACvB,KAAK,YAAY,MAAMpO,EAAO,eAAe2c,CAAQ,CAAC,IAEtD3c,EAAO,eAAe2c,CAAQ;AAGhC,IAAA3c,EAAO,qBAAA;AAAA,EACT;AAAA;AAAA;AAAA,EAKkB,SAAS2I;AAAAA;AAE7B;ACxeO,SAAS+U,EAAerhB,GAA6C;AAC1E,SAAO;AAAA,IACL,UAAU,KAAK,IAAIA,EAAM,UAAUA,EAAM,MAAM;AAAA,IAC/C,UAAU,KAAK,IAAIA,EAAM,UAAUA,EAAM,MAAM;AAAA,IAC/C,QAAQ,KAAK,IAAIA,EAAM,UAAUA,EAAM,MAAM;AAAA,IAC7C,QAAQ,KAAK,IAAIA,EAAM,UAAUA,EAAM,MAAM;AAAA,EAAA;AAEjD;AAQO,SAASshB,GAActhB,GAAqC;AACjE,QAAMuhB,IAAaF,EAAerhB,CAAK;AACvC,SAAO;AAAA,IACL,MAAM,EAAE,KAAKuhB,EAAW,UAAU,KAAKA,EAAW,SAAA;AAAA,IAClD,IAAI,EAAE,KAAKA,EAAW,QAAQ,KAAKA,EAAW,OAAA;AAAA,EAAO;AAEzD;AAQO,SAASC,GAAe7hB,GAA0C;AACvE,SAAOA,EAAO,IAAI2hB,EAAa;AACjC;AAUO,SAASG,GAAc3kB,GAAaoB,GAAa8B,GAAmC;AACzF,QAAMuhB,IAAaF,EAAerhB,CAAK;AACvC,SACElD,KAAOykB,EAAW,YAAYzkB,KAAOykB,EAAW,UAAUrjB,KAAOqjB,EAAW,YAAYrjB,KAAOqjB,EAAW;AAE9G;AAUO,SAASG,GAAiB5kB,GAAaoB,GAAayB,GAAsC;AAC/F,SAAOA,EAAO,KAAK,CAACK,MAAUyhB,GAAc3kB,GAAKoB,GAAK8B,CAAK,CAAC;AAC9D;AAQO,SAAS2hB,GAAgB3hB,GAA+D;AAC7F,QAAM/B,IAA6C,CAAA,GAC7CsjB,IAAaF,EAAerhB,CAAK;AAEvC,WAASlD,IAAMykB,EAAW,UAAUzkB,KAAOykB,EAAW,QAAQzkB;AAC5D,aAASoB,IAAMqjB,EAAW,UAAUrjB,KAAOqjB,EAAW,QAAQrjB;AAC5D,MAAAD,EAAM,KAAK,EAAE,KAAAnB,GAAK,KAAAoB,EAAA,CAAK;AAI3B,SAAOD;AACT;AASO,SAAS2jB,GAAoBjiB,GAAkE;AACpG,QAAMkiB,wBAAc,IAAA;AAEpB,aAAW7hB,KAASL;AAClB,eAAWQ,KAAQwhB,GAAgB3hB,CAAK;AACtC,MAAA6hB,EAAQ,IAAI,GAAG1hB,EAAK,GAAG,IAAIA,EAAK,GAAG,IAAIA,CAAI;AAI/C,SAAO,CAAC,GAAG0hB,EAAQ,QAAQ;AAC7B;AAuBO,SAASC,EACdC,GACAlN,GACmB;AACnB,SAAO;AAAA,IACL,UAAUkN,EAAO;AAAA,IACjB,UAAUA,EAAO;AAAA,IACjB,QAAQlN,EAAQ;AAAA,IAChB,QAAQA,EAAQ;AAAA,EAAA;AAEpB;;ACvHA,SAASmN,GACPtS,GACArD,GAKA4V,GACuB;AACvB,MAAIvS,MAAS,UAAUrD,EAAM;AAC3B,WAAO;AAAA,MACL,MAAAqD;AAAA,MACA,QAAQ;AAAA,QACN;AAAA,UACE,MAAM,EAAE,KAAKrD,EAAM,aAAa,KAAK,KAAKA,EAAM,aAAa,IAAA;AAAA,UAC7D,IAAI,EAAE,KAAKA,EAAM,aAAa,KAAK,KAAKA,EAAM,aAAa,IAAA;AAAA,QAAI;AAAA,MACjE;AAAA,IACF;AAIJ,MAAIqD,MAAS,SAASrD,EAAM,SAAS,OAAO,GAAG;AAC7C,UAAM1M,IAAS,CAAC,GAAG0M,EAAM,QAAQ,EAAE,IAAI,CAAC5L,OAAc;AAAA,MACpD,MAAM,EAAE,KAAKA,GAAU,KAAK,EAAA;AAAA,MAC5B,IAAI,EAAE,KAAKA,GAAU,KAAKwhB,IAAW,EAAA;AAAA,IAAE,EACvC;AACF,WAAO,EAAE,MAAAvS,GAAM,QAAA/P,EAAA;AAAA,EACjB;AAEA,SAAI+P,MAAS,WAAWrD,EAAM,OAAO,SAAS,IACrC,EAAE,MAAAqD,GAAM,QAAQ8R,GAAenV,EAAM,MAAM,EAAA,IAG7C,EAAE,MAAAqD,GAAM,QAAQ,GAAC;AAC1B;AAUO,MAAMwS,WAAwBljB,EAAgC;AAAA,EAC1D,OAAO;AAAA,EACE,UAAU;AAAA,EAE5B,IAAuB,gBAA0C;AAC/D,WAAO;AAAA,MACL,MAAM;AAAA,IAAA;AAAA,EAEV;AAAA;AAAA;AAAA,EAIQ,+BAAe,IAAA;AAAA,EACf,eAA8B;AAAA,EAC9B,SAAwB;AAAA;AAAA,EAGxB,SAA8B,CAAA;AAAA,EAC9B,cAAwC;AAAA,EACxC,aAAkD;AAAA,EAClD,aAAa;AAAA;AAAA,EAGb,wBAAsD;AAAA;AAAA,EAGtD,eAAoD;AAAA;AAAA;AAAA,EAMnD,SAAe;AACtB,SAAK,SAAS,MAAA,GACd,KAAK,SAAS,CAAA,GACd,KAAK,cAAc,MACnB,KAAK,aAAa,MAClB,KAAK,aAAa,IAClB,KAAK,eAAe,MACpB,KAAK,wBAAwB;AAAA,EAC/B;AAAA;AAAA;AAAA,EAMS,YAAYC,GAAgC;AACnD,UAAM,EAAE,UAAAwB,GAAU,UAAAC,GAAU,eAAAyhB,EAAA,IAAkBljB,GACxC,EAAE,MAAAyQ,MAAS,KAAK;AAGtB,QAAIA,MAAS;AACX,kBAAK,eAAe,EAAE,KAAKjP,GAAU,KAAKC,EAAA,GAC1C,KAAK,KAA4B,oBAAoB,KAAK0hB,GAAA,CAAa,GACvE,KAAK,mBAAA,GACE;AAIT,QAAI1S,MAAS;AACX,kBAAK,SAAS,MAAA,GACd,KAAK,SAAS,IAAIjP,CAAQ,GAC1B,KAAK,eAAeA,GAEpB,KAAK,KAA4B,oBAAoB,KAAK2hB,GAAA,CAAa,GACvE,KAAK,mBAAA,GACE;AAIT,QAAI1S,MAAS,SAAS;AACpB,YAAMoF,IAAWqN,EAAc,UACzBE,IAAUF,EAAc,WAAWA,EAAc;AAEvD,UAAIrN,KAAY,KAAK,YAAY;AAE/B,cAAMwN,IAAWR,EAAsB,KAAK,YAAY,EAAE,KAAKrhB,GAAU,KAAKC,GAAU;AAExF,QAAI2hB,IACE,KAAK,OAAO,SAAS,IACvB,KAAK,OAAO,KAAK,OAAO,SAAS,CAAC,IAAIC,IAEtC,KAAK,OAAO,KAAKA,CAAQ,IAG3B,KAAK,SAAS,CAACA,CAAQ,GAEzB,KAAK,cAAcA;AAAA,MACrB,WAAWD,GAAS;AAClB,cAAMC,IAA8B;AAAA,UAClC,UAAU7hB;AAAA,UACV,UAAUC;AAAA,UACV,QAAQD;AAAA,UACR,QAAQC;AAAA,QAAA;AAEV,aAAK,OAAO,KAAK4hB,CAAQ,GACzB,KAAK,cAAcA,GACnB,KAAK,aAAa,EAAE,KAAK7hB,GAAU,KAAKC,EAAA;AAAA,MAC1C,OAAO;AACL,cAAM4hB,IAA8B;AAAA,UAClC,UAAU7hB;AAAA,UACV,UAAUC;AAAA,UACV,QAAQD;AAAA,UACR,QAAQC;AAAA,QAAA;AAEV,aAAK,SAAS,CAAC4hB,CAAQ,GACvB,KAAK,cAAcA,GACnB,KAAK,aAAa,EAAE,KAAK7hB,GAAU,KAAKC,EAAA;AAAA,MAC1C;AAEA,kBAAK,KAA4B,oBAAoB,KAAK0hB,GAAA,CAAa,GAEvE,KAAK,mBAAA,GACE;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA,EAES,UAAUnjB,GAA+B;AAChD,UAAM,EAAE,MAAAyQ,MAAS,KAAK,QAEhB6S,IADU,CAAC,WAAW,aAAa,aAAa,cAAc,OAAO,QAAQ,OAAO,UAAU,UAAU,EACrF,SAAStjB,EAAM,GAAG;AAG3C,QAAIA,EAAM,QAAQ;AAChB,aAAIyQ,MAAS,SACX,KAAK,eAAe,OACXA,MAAS,SAClB,KAAK,SAAS,MAAA,GACd,KAAK,SAAS,QACLA,MAAS,YAClB,KAAK,SAAS,CAAA,GACd,KAAK,cAAc,MACnB,KAAK,aAAa,OAEpB,KAAK,KAA4B,oBAAoB,KAAK0S,GAAA,CAAa,GACvE,KAAK,mBAAA,GACE;AAIT,QAAI1S,MAAS,UAAU6S;AAErB,4BAAe,MAAM;AACnB,aAAK,eAAe,EAAE,KAAK,KAAK,KAAK,WAAW,KAAK,KAAK,KAAK,UAAA,GAC/D,KAAK,KAA4B,oBAAoB,KAAKH,GAAA,CAAa,GACvE,KAAK,mBAAA;AAAA,MACP,CAAC,GACM;AAIT,QAAI1S,MAAS,UAAUzQ,EAAM,QAAQ,aAAaA,EAAM,QAAQ;AAE9D,4BAAe,MAAM;AACnB,aAAK,SAAS,MAAA,GACd,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS,GACrC,KAAK,eAAe,KAAK,KAAK,WAC9B,KAAK,KAA4B,oBAAoB,KAAKmjB,GAAA,CAAa,GACvE,KAAK,mBAAA;AAAA,MACP,CAAC,GACM;AAKT,QAAI1S,MAAS,WAAW6S,GAAU;AAEhC,YAAMC,IAAWvjB,EAAM,QAAQ,OACzBwjB,IAAexjB,EAAM,YAAY,CAACujB;AAIxC,aAAIC,KAAgB,CAAC,KAAK,eACxB,KAAK,aAAa,EAAE,KAAK,KAAK,KAAK,WAAW,KAAK,KAAK,KAAK,UAAA,IAI/D,KAAK,wBAAwB,EAAE,UAAUA,EAAA,GAKzC,eAAe,MAAM,KAAK,oBAAoB,GAEvC;AAAA,IACT;AAGA,QAAI/S,MAAS,WAAWzQ,EAAM,QAAQ,QAAQA,EAAM,WAAWA,EAAM,UAAU;AAC7E,YAAMa,IAAW,KAAK,KAAK,QACrBmiB,IAAW,KAAK,QAAQ;AAC9B,UAAIniB,IAAW,KAAKmiB,IAAW,GAAG;AAChC,cAAMS,IAA8B;AAAA,UAClC,UAAU;AAAA,UACV,UAAU;AAAA,UACV,QAAQ5iB,IAAW;AAAA,UACnB,QAAQmiB,IAAW;AAAA,QAAA;AAErB,oBAAK,SAAS,CAACS,CAAQ,GACvB,KAAK,cAAcA,GACnB,KAAK,KAA4B,oBAAoB,KAAKN,GAAA,CAAa,GACvE,KAAK,mBAAA,GACE;AAAA,MACT;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAES,gBAAgBnjB,GAAuC;AAM9D,QALI,KAAK,OAAO,SAAS,WACrBA,EAAM,aAAa,UAAaA,EAAM,aAAa,UACnDA,EAAM,WAAW,KAGjBA,EAAM,cAAc,YAAY,KAAK;AACvC;AAIF,SAAK,aAAa;AAClB,UAAMwB,IAAWxB,EAAM,UACjByB,IAAWzB,EAAM;AACvB,SAAK,aAAa,EAAE,KAAKwB,GAAU,KAAKC,EAAA,GAExBzB,EAAM,cAAc,WAAWA,EAAM,cAAc,YAEjE,KAAK,SAAS,CAAA;AAGhB,UAAMqjB,IAA8B;AAAA,MAClC,UAAU7hB;AAAA,MACV,UAAUC;AAAA,MACV,QAAQD;AAAA,MACR,QAAQC;AAAA,IAAA;AAEV,gBAAK,OAAO,KAAK4hB,CAAQ,GACzB,KAAK,cAAcA,GAEnB,KAAK,KAA4B,oBAAoB,KAAKF,GAAA,CAAa,GACvE,KAAK,mBAAA,GACE;AAAA,EACT;AAAA,EAES,gBAAgBnjB,GAAuC;AAI9D,QAHI,KAAK,OAAO,SAAS,WACrB,CAAC,KAAK,cAAc,CAAC,KAAK,cAC1BA,EAAM,aAAa,UAAaA,EAAM,aAAa,UACnDA,EAAM,WAAW,EAAG;AAExB,UAAMqjB,IAAWR,EAAsB,KAAK,YAAY,EAAE,KAAK7iB,EAAM,UAAU,KAAKA,EAAM,SAAA,CAAU;AAEpG,WAAI,KAAK,OAAO,SAAS,IACvB,KAAK,OAAO,KAAK,OAAO,SAAS,CAAC,IAAIqjB,IAEtC,KAAK,OAAO,KAAKA,CAAQ,GAE3B,KAAK,cAAcA,GAEnB,KAAK,KAA4B,oBAAoB,KAAKF,GAAA,CAAa,GACvE,KAAK,mBAAA,GACE;AAAA,EACT;AAAA,EAES,cAAcO,GAAwC;AAC7D,QAAI,KAAK,OAAO,SAAS,WACrB,KAAK;AACP,kBAAK,aAAa,IACX;AAAA,EAEX;AAAA;AAAA;AAAA;AAAA;AAAA,EAMAC,KAA+B;AAC7B,UAAMvf,IAAa,KAAK;AACxB,QAAI,CAACA,EAAY;AAEjB,UAAM,EAAE,MAAAqM,MAAS,KAAK;AAItB,IADiBrM,EAAW,iBAAiB,OAAO,EAC3C,QAAQ,CAAClD,MAAS;AACzB,MAAAA,EAAK,UAAU,OAAO,YAAY,OAAO,UAAU,SAAS,MAAM;AAAA,IACpE,CAAC;AAED,UAAM0iB,IAAUxf,EAAW,iBAAiB,gBAAgB;AAoB5D,QAnBAwf,EAAQ,QAAQ,CAAC/lB,MAAQ;AACvB,MAAAA,EAAI,UAAU,OAAO,YAAY,WAAW;AAAA,IAC9C,CAAC,GAGG4S,MAAS,UAEXoT,EAAezf,CAAU,GAEzBwf,EAAQ,QAAQ,CAAC/lB,MAAQ;AACvB,YAAMuW,IAAYvW,EAAI,cAAc,iBAAiB,GAC/C2D,IAAWsiB,GAAoB1P,CAAS;AAC9C,MAAI5S,KAAY,KAAK,KAAK,SAAS,IAAIA,CAAQ,KAC7C3D,EAAI,UAAU,IAAI,YAAY,WAAW;AAAA,IAE7C,CAAC,IAIC4S,MAAS,WAAW,KAAK,OAAO,SAAS,GAAG;AAE9C,MAAAoT,EAAezf,CAAU;AAEzB,YAAMke,IAAa,KAAK,cAAcF,EAAe,KAAK,WAAW,IAAI;AAGzE,MADche,EAAW,iBAAiB,2BAA2B,EAC/D,QAAQ,CAAClD,MAAS;AACtB,cAAMM,IAAW,SAASN,EAAK,aAAa,UAAU,KAAK,MAAM,EAAE,GAC7DO,IAAW,SAASP,EAAK,aAAa,UAAU,KAAK,MAAM,EAAE;AACnE,QAAIM,KAAY,KAAKC,KAAY,KACfghB,GAAiBjhB,GAAUC,GAAU,KAAK,MAAM,MAG9DP,EAAK,UAAU,IAAI,UAAU,GAEzBohB,MACE9gB,MAAa8gB,EAAW,YAAUphB,EAAK,UAAU,IAAI,KAAK,GAC1DM,MAAa8gB,EAAW,UAAQphB,EAAK,UAAU,IAAI,QAAQ,GAC3DO,MAAa6gB,EAAW,YAAUphB,EAAK,UAAU,IAAI,OAAO,GAC5DO,MAAa6gB,EAAW,UAAQphB,EAAK,UAAU,IAAI,MAAM;AAAA,MAIrE,CAAC;AAAA,IACH;AAGA,IAAIuP,MAAS,UAAU,KAAK,gBAE1BoT,EAAezf,CAAU;AAAA,EAE7B;AAAA,EAES,cAAoB;AAC3B,UAAMA,IAAa,KAAK;AACxB,QAAI,CAACA,EAAY;AAEjB,UAAMwC,IAAYxC,EAAW,SAAS,CAAC,GACjC,EAAE,MAAAqM,MAAS,KAAK;AAItB,QAAI,KAAK,yBAAyBA,MAAS,SAAS;AAClD,YAAM,EAAE,UAAAoF,MAAa,KAAK;AAC1B,WAAK,wBAAwB;AAE7B,YAAMrW,IAAa,KAAK,KAAK,WACvBukB,IAAa,KAAK,KAAK;AAE7B,UAAIlO,KAAY,KAAK,YAAY;AAE/B,cAAMwN,IAAWR,EAAsB,KAAK,YAAY,EAAE,KAAKrjB,GAAY,KAAKukB,GAAY;AAC5F,aAAK,SAAS,CAACV,CAAQ,GACvB,KAAK,cAAcA;AAAA,MACrB,MAAA,CAAYxN,MAEV,KAAK,SAAS,CAAA,GACd,KAAK,cAAc,MACnB,KAAK,aAAa,EAAE,KAAKrW,GAAY,KAAKukB,EAAA;AAG5C,WAAK,KAA4B,oBAAoB,KAAKZ,GAAA,CAAa;AAAA,IACzE;AAGC,SAAK,KAA4B,aAAa,uBAAuB1S,CAAI,GAGtE7J,KACFA,EAAU,UAAU,OAAO,aAAa,KAAK,UAAU,GAGzD,KAAK+c,GAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA,EAMS,iBAAuB;AAC9B,SAAKA,GAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,kBAAuD;AACrD,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,kBAA4B;AAC1B,WAAO,CAAC,GAAG,KAAK,QAAQ;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,YAAyB;AACvB,WAAOpB,GAAe,KAAK,MAAM;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAwD;AACtD,WAAOI,GAAoB,KAAK,MAAM;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA,EAKA,eAAe9kB,GAAaoB,GAAsB;AAChD,WAAOwjB,GAAiB5kB,GAAKoB,GAAK,KAAK,MAAM;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAuB;AACrB,SAAK,eAAe,MACpB,KAAK,SAAS,MAAA,GACd,KAAK,SAAS,MACd,KAAK,SAAS,CAAA,GACd,KAAK,cAAc,MACnB,KAAK,aAAa,MAClB,KAAK,KAA4B,oBAAoB,EAAE,MAAM,KAAK,OAAO,MAAM,QAAQ,CAAA,GAAI,GAC3F,KAAK,mBAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKA,UAAUyB,GAA2B;AACnC,SAAK,SAASA,EAAO,IAAI,CAAC4B,OAAO;AAAA,MAC/B,UAAUA,EAAE,KAAK;AAAA,MACjB,UAAUA,EAAE,KAAK;AAAA,MACjB,QAAQA,EAAE,GAAG;AAAA,MACb,QAAQA,EAAE,GAAG;AAAA,IAAA,EACb,GACF,KAAK,cAAc,KAAK,OAAO,SAAS,IAAI,KAAK,OAAO,KAAK,OAAO,SAAS,CAAC,IAAI,MAClF,KAAK,KAA4B,oBAAoB;AAAA,MACnD,MAAM,KAAK,OAAO;AAAA,MAClB,QAAQigB,GAAe,KAAK,MAAM;AAAA,IAAA,CACnC,GACD,KAAK,mBAAA;AAAA,EACP;AAAA;AAAA;AAAA,EAMAY,KAAqC;AACnC,WAAOJ;AAAA,MACL,KAAK,OAAO;AAAA,MACZ;AAAA,QACE,cAAc,KAAK;AAAA,QACnB,UAAU,KAAK;AAAA,QACf,QAAQ,KAAK;AAAA,MAAA;AAAA,MAEf,KAAK,QAAQ;AAAA,IAAA;AAAA,EAEjB;AAAA;AAAA;AAAA,EAMkB,SAAS1V;AAAAA;AAG7B;AC3iBO,SAAS2W,EAAexiB,GAAkByiB,GAA2B;AAC1E,SAAO,KAAK,MAAMziB,IAAWyiB,CAAS;AACxC;AAEO,SAASC,GAAcC,GAAqBF,GAAmD;AACpG,SAAO;AAAA,IACL,OAAOE,IAAcF;AAAA,IACrB,MAAME,IAAc,KAAKF;AAAA,EAAA;AAE7B;AAEO,SAASG,GAAkBviB,GAAkBE,GAAgBkiB,GAA6B;AAC/F,QAAMI,IAAaL,EAAeniB,GAAUoiB,CAAS,GAC/CK,IAAWN,EAAejiB,IAAS,GAAGkiB,CAAS,GAE/CM,IAAmB,CAAA;AACzB,WAAS5kB,IAAI0kB,GAAY1kB,KAAK2kB,GAAU3kB;AACtC,IAAA4kB,EAAO,KAAK5kB,CAAC;AAEf,SAAO4kB;AACT;AAEA,eAAsBC,GACpBC,GACAN,GACAF,GACA9lB,GACwB;AACxB,QAAM4C,IAAQmjB,GAAcC,GAAaF,CAAS;AAElD,SAAOQ,EAAW,QAAQ;AAAA,IACxB,UAAU1jB,EAAM;AAAA,IAChB,QAAQA,EAAM;AAAA,IACd,WAAW5C,EAAO;AAAA,IAClB,aAAaA,EAAO;AAAA,EAAA,CACrB;AACH;AAEO,SAASumB,GACdljB,GACAyiB,GACAU,GACiB;AACjB,QAAMR,IAAcH,EAAexiB,GAAUyiB,CAAS,GAChDW,IAAQD,EAAa,IAAIR,CAAW;AAC1C,MAAI,CAACS,EAAO;AAEZ,QAAMC,IAAerjB,IAAWyiB;AAChC,SAAOW,EAAMC,CAAY;AAC3B;ACxCA,MAAMC,KAAqB;AAWpB,MAAMC,WAAyBhlB,EAAiC;AAAA,EAC5D,OAAO;AAAA,EACE,UAAU;AAAA,EAE5B,IAAuB,gBAA2C;AAChE,WAAO;AAAA,MACL,UAAU;AAAA,MACV,gBAAgB;AAAA,MAChB,uBAAuB;AAAA,IAAA;AAAA,EAE3B;AAAA;AAAA,EAGQ,aAA0C;AAAA,EAC1C,gBAAgB;AAAA,EAChB,mCAAmB,IAAA;AAAA,EACnB,oCAAoB,IAAA;AAAA,EACpB,gBAAgB;AAAA,EAChB;AAAA;AAAA;AAAA,EAKC,SAAe;AACtB,SAAK,aAAa,MAClB,KAAK,gBAAgB,GACrB,KAAK,aAAa,MAAA,GAClB,KAAK,cAAc,MAAA,GACnB,KAAK,gBAAgB,GACjB,KAAK,wBACP,aAAa,KAAK,mBAAmB,GACrC,KAAK,sBAAsB;AAAA,EAE/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,qBAA2B;AACjC,QAAI,CAAC,KAAK,WAAY;AAGtB,UAAMilB,IAAU,KAAK,MACff,IAAY,KAAK,OAAO,kBAAkB,KAC1C9f,IAAW,EAAE,UAAU6gB,EAAQ,gBAAgB,OAAO,QAAQA,EAAQ,gBAAgB,IAAA,GAGtFC,IAAiBb,GAAkBjgB,EAAS,UAAUA,EAAS,QAAQ8f,CAAS;AAGtF,eAAWiB,KAAYD;AACrB,UAAI,OAAK,aAAa,IAAIC,CAAQ,KAAK,KAAK,cAAc,IAAIA,CAAQ,IAKtE;AAAA,YAAI,KAAK,cAAc,SAAS,KAAK,OAAO,yBAAyB;AACnE;AAGF,aAAK,cAAc,IAAIA,CAAQ,GAE/BV,GAAU,KAAK,YAAYU,GAAUjB,GAAW,EAAE,EAC/C,KAAK,CAACjjB,MAAW;AAChB,eAAK,aAAa,IAAIkkB,GAAUlkB,EAAO,IAAI,GAC3C,KAAK,gBAAgBA,EAAO,eAC5B,KAAK,cAAc,OAAOkkB,CAAQ,GAClC,KAAK,cAAA,GAEL,KAAK,mBAAA;AAAA,QACP,CAAC,EACA,MAAM,MAAM;AACX,eAAK,cAAc,OAAOA,CAAQ;AAAA,QACpC,CAAC;AAAA;AAAA,EAEP;AAAA;AAAA;AAAA,EAKS,YAAY9mB,GAAqC;AACxD,QAAI,CAAC,KAAK,WAAY,QAAO,CAAC,GAAGA,CAAI;AAGrC,UAAM4C,IAAoB,CAAA;AAC1B,aAASrB,IAAI,GAAGA,IAAI,KAAK,eAAeA,KAAK;AAC3C,YAAMwlB,IAAST,GAAgB/kB,GAAG,KAAK,OAAO,kBAAkB,KAAK,KAAK,YAAY;AACtF,MAAAqB,EAAO,KAAKmkB,KAAU,EAAE,WAAW,IAAM,SAASxlB,GAAG;AAAA,IACvD;AAEA,WAAOqB;AAAA,EACT;AAAA,EAES,SAAShB,GAA0B;AAC1C,IAAK,KAAK,eAGV,KAAK,mBAAA,GAGD,KAAK,uBACP,aAAa,KAAK,mBAAmB,GAEvC,KAAK,sBAAsB,WAAW,MAAM;AAC1C,WAAK,mBAAA;AAAA,IACP,GAAG8kB,EAAkB;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,cAAcL,GAAwC;AACpD,SAAK,aAAaA,GAClB,KAAK,aAAa,MAAA,GAClB,KAAK,cAAc,MAAA;AAGnB,UAAMR,IAAY,KAAK,OAAO,kBAAkB;AAChD,IAAAO,GAAUC,GAAY,GAAGR,GAAW,CAAA,CAAE,EAAE,KAAK,CAACjjB,MAAW;AACvD,WAAK,aAAa,IAAI,GAAGA,EAAO,IAAI,GACpC,KAAK,gBAAgBA,EAAO,eAC5B,KAAK,cAAA;AAAA,IACP,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,UAAgB;AACd,IAAK,KAAK,eACV,KAAK,aAAa,MAAA,GAClB,KAAK,cAAc,MAAA,GACnB,KAAK,cAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKA,aAAmB;AACjB,SAAK,aAAa,MAAA;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA,EAKA,mBAA2B;AACzB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAYQ,GAA2B;AACrC,UAAMyiB,IAAY,KAAK,OAAO,kBAAkB,KAC1CiB,IAAWlB,EAAexiB,GAAUyiB,CAAS;AACnD,WAAO,KAAK,aAAa,IAAIiB,CAAQ;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA,EAKA,sBAA8B;AAC5B,WAAO,KAAK,aAAa;AAAA,EAC3B;AAAA;AAEF;ACpLO,SAASE,GAAevnB,GAAUsO,GAAe8O,GAAkC;AACxF,SAAIpd,EAAI,OAAO,SAAkB,OAAOA,EAAI,EAAE,IACvCod,IAAY,GAAGA,CAAS,IAAI9O,CAAK,KAAK,OAAOA,CAAK;AAC3D;AA8CO,SAAS4E,GAAab,GAA2BtE,GAA0B;AAChF,QAAMsG,IAAc,IAAI,IAAIhC,CAAY;AACxC,SAAIgC,EAAY,IAAItG,CAAG,IACrBsG,EAAY,OAAOtG,CAAG,IAEtBsG,EAAY,IAAItG,CAAG,GAEdsG;AACT;AAMO,SAASmT,GAAUjnB,GAAaN,GAAoBmd,IAA2B,MAAMD,IAAQ,GAAgB;AAClH,QAAMsK,IAAgBxnB,EAAO,iBAAiB,YACxCuS,wBAAW,IAAA;AAEjB,WAAS1Q,IAAI,GAAGA,IAAIvB,EAAK,QAAQuB,KAAK;AACpC,UAAM9B,IAAMO,EAAKuB,CAAC,GACZiM,IAAMwZ,GAAevnB,GAAK8B,GAAGsb,CAAS,GACtCS,IAAW7d,EAAIynB,CAAa;AAElC,QAAI,MAAM,QAAQ5J,CAAQ,KAAKA,EAAS,SAAS,GAAG;AAClD,MAAArL,EAAK,IAAIzE,CAAG;AACZ,YAAM2Z,IAAYF,GAAU3J,GAAU5d,GAAQ8N,GAAKoP,IAAQ,CAAC;AAC5D,iBAAWwK,KAAKD,EAAW,CAAAlV,EAAK,IAAImV,CAAC;AAAA,IACvC;AAAA,EACF;AAEA,SAAOnV;AACT;AAMO,SAASoV,KAA2B;AACzC,6BAAW,IAAA;AACb;AAkCO,SAASC,GACdtnB,GACAunB,GACA7nB,GACAmd,IAA2B,MAC3BD,IAAQ,GACS;AACjB,QAAMsK,IAAgBxnB,EAAO,iBAAiB;AAE9C,WAAS6B,IAAI,GAAGA,IAAIvB,EAAK,QAAQuB,KAAK;AACpC,UAAM9B,IAAMO,EAAKuB,CAAC,GACZiM,IAAMwZ,GAAevnB,GAAK8B,GAAGsb,CAAS;AAE5C,QAAIrP,MAAQ+Z;AACV,aAAO,CAAC/Z,CAAG;AAGb,UAAM8P,IAAW7d,EAAIynB,CAAa;AAClC,QAAI,MAAM,QAAQ5J,CAAQ,KAAKA,EAAS,SAAS,GAAG;AAClD,YAAMkK,IAAYF,GAAahK,GAAUiK,GAAW7nB,GAAQ8N,GAAKoP,IAAQ,CAAC;AAC1E,UAAI4K;AACF,eAAO,CAACha,GAAK,GAAGga,CAAS;AAAA,IAE7B;AAAA,EACF;AAEA,SAAO;AACT;AAMO,SAASC,GACdznB,GACAunB,GACA7nB,GACAgoB,GACa;AACb,QAAMvW,IAAOmW,GAAatnB,GAAMunB,GAAW7nB,CAAM;AACjD,MAAI,CAACyR,EAAM,QAAOuW;AAElB,QAAM5T,IAAc,IAAI,IAAI4T,CAAgB;AAE5C,WAASnmB,IAAI,GAAGA,IAAI4P,EAAK,SAAS,GAAG5P;AACnC,IAAAuS,EAAY,IAAI3C,EAAK5P,CAAC,CAAC;AAEzB,SAAOuS;AACT;AC7KO,SAAS6T,GAAoB3nB,GAAaknB,IAAgB,YAAqB;AACpF,MAAI,CAAC,MAAM,QAAQlnB,CAAI,KAAKA,EAAK,WAAW,EAAG,QAAO;AAGtD,aAAWP,KAAOO;AAChB,QAAIP,KAAO,MAAM,QAAQA,EAAIynB,CAAa,CAAC,KAAKznB,EAAIynB,CAAa,EAAE,SAAS;AAC1E,aAAO;AAIX,SAAO;AACT;AAMO,SAASU,GAAmB5nB,GAA4B;AAC7D,MAAI,CAAC,MAAM,QAAQA,CAAI,KAAKA,EAAK,WAAW,EAAG,QAAO;AAEtD,QAAM6nB,IAAoB,CAAC,YAAY,SAAS,SAAS,WAAW,QAAQ;AAE5E,aAAWpoB,KAAOO;AAChB,QAAI,GAACP,KAAO,OAAOA,KAAQ;AAE3B,iBAAWD,KAASqoB;AAClB,YAAI,MAAM,QAAQpoB,EAAID,CAAK,CAAC,KAAKC,EAAID,CAAK,EAAE,SAAS;AACnD,iBAAOA;AAAA;AAKb,SAAO;AACT;;ACjBO,MAAMsoB,WAAmBnmB,EAA2B;AAAA,EAChD,OAAO;AAAA,EACE,UAAU;AAAA,EACV,SAASsN;AAAAA,EAE3B,IAAuB,gBAAqC;AAC1D,WAAO;AAAA,MACL,eAAe;AAAA,MACf,YAAY;AAAA,MACZ,iBAAiB;AAAA,MACjB,aAAa;AAAA,MACb,iBAAiB;AAAA,MACjB,WAAW;AAAA,IAAA;AAAA,EAEf;AAAA;AAAA,EAIQ,mCAAmB,IAAA;AAAA,EACnB,uBAAuB;AAAA,EACvB,gBAAoC,CAAA;AAAA,EACpC,gCAAgB,IAAA;AAAA,EAChB,0CAA0B,IAAA;AAAA,EAC1B,oCAAoB,IAAA;AAAA,EACpB,YAAyD;AAAA,EAExD,SAAe;AACtB,SAAK,aAAa,MAAA,GAClB,KAAK,uBAAuB,IAC5B,KAAK,gBAAgB,CAAA,GACrB,KAAK,UAAU,MAAA,GACf,KAAK,oBAAoB,MAAA,GACzB,KAAK,cAAc,MAAA,GACnB,KAAK,YAAY;AAAA,EACnB;AAAA;AAAA;AAAA,EAMA,IAAY,iBAA0C;AAEpD,UAAMoD,IADS,KAAK,KACA,iBAAiB,WAAW,QAAQ;AAExD,QAAIA,MAAS,MAASA,MAAS,MAAO,QAAO;AAC7C,QAAIA,MAAS,MAAQA,MAAS,MAAM;AAClC,YAAMC,IAAO,KAAK,YAAY;AAC9B,UAAIA,KAAQ,iBAAiBA,CAAI,EAAE,iBAAiB,yBAAyB,EAAE,KAAA,MAAW;AACxF,eAAO;AAAA,IAEX;AACA,WAAO,KAAK,OAAO,aAAa;AAAA,EAClC;AAAA;AAAA;AAAA,EAMA,OAAOtS,GAAmC;AACxC,QAAI,CAAC,KAAK,OAAO,WAAY,QAAO;AACpC,UAAMR,IAAQ,KAAK,OAAO,iBAAiBooB,GAAmB5nB,CAAa,KAAK;AAChF,WAAO2nB,GAAoB3nB,GAAeR,CAAK;AAAA,EACjD;AAAA;AAAA;AAAA,EAMS,YAAYQ,GAAiC;AACpD,UAAMknB,IAAgB,KAAK,OAAO,iBAAiB;AAEnD,QAAI,CAACS,GAAoB3nB,GAAeknB,CAAa;AACnD,kBAAK,gBAAgB,CAAA,GACrB,KAAK,UAAU,MAAA,GACf,KAAK,oBAAoB,MAAA,GAClB,CAAC,GAAGlnB,CAAI;AAIjB,QAAI+nB,IAAO,KAAK,eAAe/nB,CAAa;AAC5C,IAAI,KAAK,cACP+nB,IAAO,KAAK,SAASA,GAAM,KAAK,UAAU,OAAO,KAAK,UAAU,SAAS,IAIvE,KAAK,OAAO,mBAAmB,CAAC,KAAK,yBACvC,KAAK,eAAed,GAAUc,GAAM,KAAK,MAAM,GAC/C,KAAK,uBAAuB,KAI9B,KAAK,gBAAgB,KAAK,YAAYA,GAAM,KAAK,YAAY,GAC7D,KAAK,UAAU,MAAA,GACf,KAAK,cAAc,MAAA;AACnB,UAAMC,wBAAkB,IAAA;AAExB,eAAWvoB,KAAO,KAAK;AACrB,WAAK,UAAU,IAAIA,EAAI,KAAKA,CAAG,GAC/BuoB,EAAY,IAAIvoB,EAAI,GAAG,GACnB,CAAC,KAAK,oBAAoB,IAAIA,EAAI,GAAG,KAAKA,EAAI,QAAQ,KACxD,KAAK,cAAc,IAAIA,EAAI,GAAG;AAGlC,gBAAK,sBAAsBuoB,GAEpB,KAAK,cAAc,IAAI,CAAC9jB,OAAO;AAAA,MACpC,GAAGA,EAAE;AAAA,MACL,WAAWA,EAAE;AAAA,MACb,aAAaA,EAAE;AAAA,MACf,mBAAmBA,EAAE;AAAA,MACrB,gBAAgBA,EAAE;AAAA,IAAA,EAClB;AAAA,EACJ;AAAA;AAAA,EAGQ,eAAelE,GAAa6c,IAA2B,MAAa;AAC1E,UAAMqK,IAAgB,KAAK,OAAO,iBAAiB;AACnD,WAAOlnB,EAAK,IAAI,CAACP,GAAK,MAAM;AAC1B,YAAM+N,IACJ/N,EAAI,OAAO,SAAY,OAAOA,EAAI,EAAE,IAAKA,EAAI,gBAAgBod,IAAY,GAAGA,CAAS,IAAI,CAAC,KAAK,OAAO,CAAC,IACnGS,IAAW7d,EAAIynB,CAAa,GAC5B/J,IAAc,MAAM,QAAQG,CAAQ,KAAKA,EAAS,SAAS;AACjE,aAAO;AAAA,QACL,GAAG7d;AAAA,QACH,aAAa+N;AAAA,QACb,GAAI2P,IAAc,EAAE,CAAC+J,CAAa,GAAG,KAAK,eAAe5J,GAAU9P,CAAG,MAAM,CAAA;AAAA,MAAC;AAAA,IAEjF,CAAC;AAAA,EACH;AAAA;AAAA,EAGQ,YAAYxN,GAAagR,GAAuB4L,IAAQ,GAAuB;AACrF,UAAMsK,IAAgB,KAAK,OAAO,iBAAiB,YAC7CtkB,IAA6B,CAAA;AAEnC,eAAWnD,KAAOO,GAAM;AACtB,YAAMwN,IAAM/N,EAAI,eAAeA,EAAI,MAAM,KACnC6d,IAAW7d,EAAIynB,CAAa,GAC5B/J,IAAc,MAAM,QAAQG,CAAQ,KAAKA,EAAS,SAAS,GAC3D1L,IAAaZ,EAAS,IAAIxD,CAAG;AAEnC,MAAA5K,EAAO,KAAK;AAAA,QACV,KAAA4K;AAAA,QACA,MAAM/N;AAAA,QACN,OAAAmd;AAAA,QACA,aAAAO;AAAA,QACA,YAAAvL;AAAA,QACA,WAAWgL,IAAQ,KAAIpP,EAAI,UAAU,GAAGA,EAAI,YAAY,GAAG,CAAC,KAAK;AAAA,MAAO,CACzE,GAEG2P,KAAevL,KACjBhP,EAAO,KAAK,GAAG,KAAK,YAAY0a,GAAUtM,GAAU4L,IAAQ,CAAC,CAAC;AAAA,IAElE;AACA,WAAOha;AAAA,EACT;AAAA;AAAA,EAGQ,SAAS5C,GAAaR,GAAeyoB,GAAoB;AAC/D,UAAMf,IAAgB,KAAK,OAAO,iBAAiB;AASnD,WARe,CAAC,GAAGlnB,CAAI,EAAE,KAAK,CAACS,GAAGC,MAAM;AACtC,YAAM2W,IAAO5W,EAAEjB,CAAK,GAClB8X,IAAO5W,EAAElB,CAAK;AAChB,aAAI6X,KAAQ,QAAQC,KAAQ,OAAa,IACrCD,KAAQ,OAAa,KACrBC,KAAQ,OAAa,IAClBD,IAAOC,IAAO2Q,IAAM5Q,IAAOC,IAAO,CAAC2Q,IAAM;AAAA,IAClD,CAAC,EACa,IAAI,CAACxoB,MAAQ;AACzB,YAAM6d,IAAW7d,EAAIynB,CAAa;AAClC,aAAO,MAAM,QAAQ5J,CAAQ,KAAKA,EAAS,SAAS,IAChD,EAAE,GAAG7d,GAAK,CAACynB,CAAa,GAAG,KAAK,SAAS5J,GAAU9d,GAAOyoB,CAAG,MAC7DxoB;AAAA,IACN,CAAC;AAAA,EACH;AAAA,EAES,eAAeQ,GAAkD;AACxE,QAAI,KAAK,cAAc,WAAW,EAAG,QAAO,CAAC,GAAGA,CAAO;AAEvD,UAAMsP,IAAO,CAAC,GAAGtP,CAAO;AACxB,QAAIsP,EAAK,WAAW,EAAG,QAAOA;AAE9B,UAAMgG,IAAW,EAAE,GAAGhG,EAAK,CAAC,EAAA,GACtBX,IAAW2G,EAAS;AAC1B,QAAK3G,GAAkB,cAAe,QAAOW;AAE7C,UAAM2Y,IAAY,MAAM,KAAK,QACvBC,IAAU,KAAK,QAAQ,KAAK,IAAI,GAChCC,IAAc,KAAK,YAAY,KAAK,IAAI,GAExCC,IAAU,CAAC3J,MAAqD;AACpE,YAAM,EAAE,OAAAnf,GAAO,KAAAE,EAAA,IAAQif,GACjB,EAAE,aAAAwC,IAAc,IAAI,iBAAAoH,IAAkB,GAAA,IAASJ,EAAA,GAE/C1f,IAAY,SAAS,cAAc,MAAM;AAK/C,UAJAA,EAAU,YAAY,aACtBA,EAAU,MAAM,YAAY,gBAAgB,OAAO/I,EAAI,eAAe,CAAC,CAAC,GACxE+I,EAAU,MAAM,YAAY,qBAAqB,GAAG0Y,CAAW,IAAI,GAE/DzhB,EAAI,qBAAqB6oB,GAAiB;AAC5C,cAAMnhB,IAAO,SAAS,cAAc,MAAM;AAC1C,QAAAA,EAAK,YAAY,cAAc1H,EAAI,iBAAiB,cAAc,EAAE,IACpE0oB,EAAQhhB,GAAMihB,EAAY3oB,EAAI,iBAAiB,aAAa,QAAQ,CAAC,GACrE0H,EAAK,aAAa,iBAAiB1H,EAAI,SAAS,GAChD+I,EAAU,YAAYrB,CAAI;AAAA,MAC5B,WAAWmhB,GAAiB;AAC1B,cAAM3a,IAAS,SAAS,cAAc,MAAM;AAC5C,QAAAA,EAAO,YAAY,eACnBnF,EAAU,YAAYmF,CAAM;AAAA,MAC9B;AAEA,YAAMrE,IAAU,SAAS,cAAc,MAAM;AAC7C,UAAIsF,GAAU;AACZ,cAAMgH,IAAWhH,EAAS8P,CAAG;AAC7B,QAAI9I,aAAoB,OACtBtM,EAAQ,YAAYsM,CAAQ,IAE5BtM,EAAQ,cAAc,OAAOsM,KAAYrW,KAAS,EAAE;AAAA,MAExD;AACE,QAAA+J,EAAQ,cAAc,OAAO/J,KAAS,EAAE;AAE1C,aAAAiJ,EAAU,YAAYc,CAAO,GACtBd;AAAA,IACT;AAEC,WAAA6f,EAAgB,gBAAgB,IACjC9S,EAAS,eAAe8S,GACxB9Y,EAAK,CAAC,IAAIgG,GACHhG;AAAA,EACT;AAAA;AAAA;AAAA,EAMS,YAAY3N,GAAgC;AACnD,UAAMK,IAASL,EAAM,eAAe;AACpC,QAAI,CAACK,GAAQ,UAAU,SAAS,aAAa,EAAG,QAAO;AAEvD,UAAMuL,IAAMvL,EAAO,aAAa,eAAe,GACzCsmB,IAAU/a,IAAM,KAAK,UAAU,IAAIA,CAAG,IAAI;AAChD,WAAK+a,KAEL,KAAK,eAAe5V,GAAa,KAAK,cAAcnF,CAAI,GACxD,KAAK,KAAuB,eAAe;AAAA,MACzC,KAAAA;AAAA,MACA,KAAK+a,EAAQ;AAAA,MACb,UAAU,KAAK,aAAa,IAAI/a,CAAI;AAAA,MACpC,OAAO+a,EAAQ;AAAA,IAAA,CAChB,GACD,KAAK,cAAA,GACE,MAVc;AAAA,EAWvB;AAAA,EAES,cAAc3mB,GAAkC;AACvD,QAAI,KAAK,cAAc,WAAW,KAAK,CAACA,EAAM,OAAO,SAAU,QAAO;AAEtE,UAAM,EAAE,OAAApC,MAAUoC,EAAM;AACxB,IAAI,CAAC,KAAK,aAAa,KAAK,UAAU,UAAUpC,IAC9C,KAAK,YAAY,EAAE,OAAAA,GAAO,WAAW,EAAA,IAC5B,KAAK,UAAU,cAAc,IACtC,KAAK,YAAY,EAAE,OAAAA,GAAO,WAAW,GAAA,IAErC,KAAK,YAAY;AAInB,UAAM8G,IAAS,KAAK;AACpB,WAAIA,EAAO,eAAe,WACxBA,EAAO,aAAa,KAAK,YAAY,EAAE,GAAG,KAAK,cAAc,OAG/D,KAAK,KAAK,eAAe,EAAE,OAAA9G,GAAO,WAAW,KAAK,WAAW,aAAa,GAAG,GAC7E,KAAK,cAAA,GACE;AAAA,EACT;AAAA,EAES,cAAoB;AAC3B,UAAMsM,IAAQ,KAAK;AACnB,QAAIA,MAAU,MAAS,KAAK,cAAc,SAAS,EAAG;AAEtD,UAAM+G,IAAO,KAAK,YAAY,cAAc,OAAO;AACnD,QAAI,CAACA,EAAM;AAEX,UAAMC,IAAYhH,MAAU,SAAS,qBAAqB;AAC1D,eAAW2G,KAASI,EAAK,iBAAiB,gBAAgB,GAAG;AAC3D,YAAM/P,IAAO2P,EAAM,cAAc,iBAAiB,GAC5C9R,IAAMmC,IAAO,SAASA,EAAK,aAAa,UAAU,KAAK,MAAM,EAAE,IAAI,IACnE0K,IAAM,KAAK,cAAc7M,CAAG,GAAG;AAErC,MAAI6M,KAAO,KAAK,cAAc,IAAIA,CAAG,MACnCiF,EAAM,UAAU,IAAIK,CAAS,GAC7BL,EAAM,iBAAiB,gBAAgB,MAAMA,EAAM,UAAU,OAAOK,CAAS,GAAG,EAAE,MAAM,GAAA,CAAM;AAAA,IAElG;AACA,SAAK,cAAc,MAAA;AAAA,EACrB;AAAA;AAAA;AAAA,EAMA,OAAOtF,GAAmB;AACxB,SAAK,aAAa,IAAIA,CAAG,GACzB,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,SAASA,GAAmB;AAC1B,SAAK,aAAa,OAAOA,CAAG,GAC5B,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,OAAOA,GAAmB;AACxB,SAAK,eAAemF,GAAa,KAAK,cAAcnF,CAAG,GACvD,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,YAAkB;AAChB,SAAK,eAAeyZ,GAAU,KAAK,MAAe,KAAK,MAAM,GAC7D,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,cAAoB;AAClB,SAAK,eAAeI,GAAA,GACpB,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,WAAW7Z,GAAsB;AAC/B,WAAO,KAAK,aAAa,IAAIA,CAAG;AAAA,EAClC;AAAA,EAEA,kBAA4B;AAC1B,WAAO,CAAC,GAAG,KAAK,YAAY;AAAA,EAC9B;AAAA,EAEA,mBAAuC;AACrC,WAAO,CAAC,GAAG,KAAK,aAAa;AAAA,EAC/B;AAAA,EAEA,YAAYA,GAA8B;AACxC,WAAO,KAAK,UAAU,IAAIA,CAAG,GAAG;AAAA,EAClC;AAAA,EAEA,YAAYA,GAAmB;AAC7B,SAAK,eAAeia,GAAY,KAAK,MAAeja,GAAK,KAAK,QAAQ,KAAK,YAAY,GACvF,KAAK,cAAA;AAAA,EACP;AAAA;AAGF;ACxWO,SAASgb,GAAWxZ,GAAsByZ,GAAoBC,GAAgC;AACnG,QAAMC,IAAY,CAAC,GAAG3Z,EAAM,WAAWyZ,CAAM;AAG7C,SAAOE,EAAU,SAASD;AACxB,IAAAC,EAAU,MAAA;AAGZ,SAAO;AAAA,IACL,WAAAA;AAAA,IACA,WAAW,CAAA;AAAA;AAAA,EAAC;AAEhB;AASO,SAASC,GAAK5Z,GAGnB;AACA,MAAIA,EAAM,UAAU,WAAW;AAC7B,WAAO,EAAE,UAAUA,GAAO,QAAQ,KAAA;AAGpC,QAAM2Z,IAAY,CAAC,GAAG3Z,EAAM,SAAS,GAC/ByZ,IAASE,EAAU,IAAA;AAIzB,SAAKF,IAIE;AAAA,IACL,UAAU;AAAA,MACR,WAAAE;AAAA,MACA,WAAW,CAAC,GAAG3Z,EAAM,WAAWyZ,CAAM;AAAA,IAAA;AAAA,IAExC,QAAAA;AAAA,EAAA,IARO,EAAE,UAAUzZ,GAAO,QAAQ,KAAA;AAUtC;AASO,SAAS6Z,GAAK7Z,GAGnB;AACA,MAAIA,EAAM,UAAU,WAAW;AAC7B,WAAO,EAAE,UAAUA,GAAO,QAAQ,KAAA;AAGpC,QAAM8Z,IAAY,CAAC,GAAG9Z,EAAM,SAAS,GAC/ByZ,IAASK,EAAU,IAAA;AAIzB,SAAKL,IAIE;AAAA,IACL,UAAU;AAAA,MACR,WAAW,CAAC,GAAGzZ,EAAM,WAAWyZ,CAAM;AAAA,MACtC,WAAAK;AAAA,IAAA;AAAA,IAEF,QAAAL;AAAA,EAAA,IARO,EAAE,UAAUzZ,GAAO,QAAQ,KAAA;AAUtC;AAQO,SAAS+Z,GAAQ/Z,GAA+B;AACrD,SAAOA,EAAM,UAAU,SAAS;AAClC;AAQO,SAASga,GAAQha,GAA+B;AACrD,SAAOA,EAAM,UAAU,SAAS;AAClC;AAOO,SAASia,KAA8B;AAC5C,SAAO,EAAE,WAAW,IAAI,WAAW,CAAA,EAAC;AACtC;AAWO,SAASC,GAAiB9lB,GAAkB5D,GAAe2pB,GAAmBC,GAA+B;AAClH,SAAO;AAAA,IACL,MAAM;AAAA,IACN,UAAAhmB;AAAA,IACA,OAAA5D;AAAA,IACA,UAAA2pB;AAAA,IACA,UAAAC;AAAA,IACA,WAAW,KAAK,IAAA;AAAA,EAAI;AAExB;AChIO,MAAMC,WAAuB1nB,EAA+B;AAAA,EACxD,OAAO;AAAA,EACE,UAAU;AAAA,EAE5B,IAAuB,gBAAyC;AAC9D,WAAO;AAAA,MACL,gBAAgB;AAAA,IAAA;AAAA,EAEpB;AAAA;AAAA,EAGQ,YAA0B,CAAA;AAAA,EAC1B,YAA0B,CAAA;AAAA;AAAA;AAAA;AAAA,EAKzB,SAAe;AACtB,SAAK,YAAY,CAAA,GACjB,KAAK,YAAY,CAAA;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOS,UAAUC,GAA+B;AAChD,UAAM0nB,KAAU1nB,EAAM,WAAWA,EAAM,YAAYA,EAAM,QAAQ,OAAO,CAACA,EAAM,UACzE2nB,KAAU3nB,EAAM,WAAWA,EAAM,aAAaA,EAAM,QAAQ,OAAQA,EAAM,QAAQ,OAAOA,EAAM;AAErG,QAAI0nB,GAAQ;AACV,YAAM1mB,IAASgmB,GAAK,EAAE,WAAW,KAAK,WAAW,WAAW,KAAK,WAAW;AAC5E,UAAIhmB,EAAO,QAAQ;AAEjB,cAAM5C,IAAO,KAAK;AAClB,QAAIA,EAAK4C,EAAO,OAAO,QAAQ,MAC7B5C,EAAK4C,EAAO,OAAO,QAAQ,EAAEA,EAAO,OAAO,KAAK,IAAIA,EAAO,OAAO,WAIpE,KAAK,YAAYA,EAAO,SAAS,WACjC,KAAK,YAAYA,EAAO,SAAS,WAEjC,KAAK,KAAqB,QAAQ;AAAA,UAChC,QAAQA,EAAO;AAAA,UACf,MAAM;AAAA,QAAA,CACP,GAED,KAAK,cAAA;AAAA,MACP;AACA,aAAO;AAAA,IACT;AAEA,QAAI2mB,GAAQ;AACV,YAAM3mB,IAASimB,GAAK,EAAE,WAAW,KAAK,WAAW,WAAW,KAAK,WAAW;AAC5E,UAAIjmB,EAAO,QAAQ;AAEjB,cAAM5C,IAAO,KAAK;AAClB,QAAIA,EAAK4C,EAAO,OAAO,QAAQ,MAC7B5C,EAAK4C,EAAO,OAAO,QAAQ,EAAEA,EAAO,OAAO,KAAK,IAAIA,EAAO,OAAO,WAIpE,KAAK,YAAYA,EAAO,SAAS,WACjC,KAAK,YAAYA,EAAO,SAAS,WAEjC,KAAK,KAAqB,QAAQ;AAAA,UAChC,QAAQA,EAAO;AAAA,UACf,MAAM;AAAA,QAAA,CACP,GAED,KAAK,cAAA;AAAA,MACP;AACA,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,WAAWQ,GAAkB5D,GAAe2pB,GAAmBC,GAAyB;AACtF,UAAMX,IAASS,GAAiB9lB,GAAU5D,GAAO2pB,GAAUC,CAAQ,GAC7D7b,IAAWib;AAAA,MACf,EAAE,WAAW,KAAK,WAAW,WAAW,KAAK,UAAA;AAAA,MAC7CC;AAAA,MACA,KAAK,OAAO,kBAAkB;AAAA,IAAA;AAEhC,SAAK,YAAYlb,EAAS,WAC1B,KAAK,YAAYA,EAAS;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAA0B;AACxB,UAAM3K,IAASgmB,GAAK,EAAE,WAAW,KAAK,WAAW,WAAW,KAAK,WAAW;AAC5E,QAAIhmB,EAAO,QAAQ;AACjB,YAAM5C,IAAO,KAAK;AAClB,MAAIA,EAAK4C,EAAO,OAAO,QAAQ,MAC7B5C,EAAK4C,EAAO,OAAO,QAAQ,EAAEA,EAAO,OAAO,KAAK,IAAIA,EAAO,OAAO,WAEpE,KAAK,YAAYA,EAAO,SAAS,WACjC,KAAK,YAAYA,EAAO,SAAS,WACjC,KAAK,cAAA;AAAA,IACP;AACA,WAAOA,EAAO;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAA0B;AACxB,UAAMA,IAASimB,GAAK,EAAE,WAAW,KAAK,WAAW,WAAW,KAAK,WAAW;AAC5E,QAAIjmB,EAAO,QAAQ;AACjB,YAAM5C,IAAO,KAAK;AAClB,MAAIA,EAAK4C,EAAO,OAAO,QAAQ,MAC7B5C,EAAK4C,EAAO,OAAO,QAAQ,EAAEA,EAAO,OAAO,KAAK,IAAIA,EAAO,OAAO,WAEpE,KAAK,YAAYA,EAAO,SAAS,WACjC,KAAK,YAAYA,EAAO,SAAS,WACjC,KAAK,cAAA;AAAA,IACP;AACA,WAAOA,EAAO;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,UAAmB;AACjB,WAAOmmB,GAAQ,EAAE,WAAW,KAAK,WAAW,WAAW,KAAK,WAAW;AAAA,EACzE;AAAA;AAAA;AAAA;AAAA,EAKA,UAAmB;AACjB,WAAOC,GAAQ,EAAE,WAAW,KAAK,WAAW,WAAW,KAAK,WAAW;AAAA,EACzE;AAAA;AAAA;AAAA;AAAA,EAKA,eAAqB;AACnB,UAAMzb,IAAW0b,GAAA;AACjB,SAAK,YAAY1b,EAAS,WAC1B,KAAK,YAAYA,EAAS;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA,EAKA,eAA6B;AAC3B,WAAO,CAAC,GAAG,KAAK,SAAS;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKA,eAA6B;AAC3B,WAAO,CAAC,GAAG,KAAK,SAAS;AAAA,EAC3B;AAAA;AAEF;;AC9JA,SAASwU,GAAcxe,GAA+B;AACpD,QAAMye,IAAOze,EAAO,QAAQ,CAAA;AAC5B,SAAOye,EAAK,iBAAiB,MAAQA,EAAK,oBAAoB;AAChE;AAyBO,MAAMwH,UAAyB7nB,EAAiC;AAAA,EAC5D,OAAO;AAAA,EACE,UAAU;AAAA;AAAA,EAG5B,OAAgB,WAAW;AAAA,EAE3B,IAAuB,gBAA2C;AAChE,WAAO;AAAA,MACL,cAAc;AAAA,IAAA;AAAA,EAElB;AAAA;AAAA,EAGQ,oBAAwC;AAAA;AAAA,EAGxC,aAAa;AAAA,EACb,eAA8B;AAAA,EAC9B,eAA8B;AAAA,EAC9B,YAA2B;AAAA;AAAA;AAAA,EAK1B,SAAe;AACtB,SAAK,oBAAoB,MACzB,KAAK,aAAa,IAClB,KAAK,eAAe,MACpB,KAAK,eAAe,MACpB,KAAK,YAAY;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQS,eAAgD;AACvD,WAAO;AAAA,MACL,IAAI6nB,EAAiB;AAAA,MACrB,OAAO;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,OAAO;AAAA;AAAA,MACP,QAAQ,CAAChhB,MAAc,KAAK,mBAAmBA,CAAS;AAAA,IAAA;AAAA,EAE5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAa;AAEX,IADa,KAAK,KACb,cAAcghB,EAAiB,QAAQ;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA,EAKA,OAAa;AAEX,IADa,KAAK,KACb,eAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKA,SAAe;AAEb,IADa,KAAK,KACb,gBAAgBA,EAAiB,QAAQ;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,gBAAgBhqB,GAAwB;AAEtC,WADa,KAAK,KACN,gBAAgBA,CAAK;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,iBAAiBA,GAAeiqB,GAAwB;AAEtD,IADa,KAAK,KACb,iBAAiBjqB,GAAOiqB,CAAO;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,oBAA8B;AAE5B,WADa,KAAK,KAEf,cAAA,EACA,OAAO,CAACrpB,MAAMA,EAAE,OAAO,EACvB,IAAI,CAACA,MAAMA,EAAE,KAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,mBAA6B;AAE3B,WADa,KAAK,KAEf,cAAA,EACA,OAAO,CAACA,MAAM,CAACA,EAAE,OAAO,EACxB,IAAI,CAACA,MAAMA,EAAE,KAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAgB;AAEd,IADa,KAAK,KACb,eAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,aAAaZ,GAAqB;AAEhC,IADa,KAAK,KACb,uBAAuBA,CAAK;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAAWA,GAAqB;AAE9B,IADa,KAAK,KACb,iBAAiBA,GAAO,EAAI;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAAWA,GAAqB;AAE9B,IADa,KAAK,KACb,iBAAiBA,GAAO,EAAK;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,gBAAmG;AAEjG,WADa,KAAK,KACN,cAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,iBAA0B;AAExB,WADa,KAAK,KACN,oBAAoBgqB,EAAiB;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,mBAAmBhhB,GAA6C;AACtE,UAAMtF,IAAO,KAAK,MAGZyb,IAAU,SAAS,cAAc,KAAK;AAC5C,IAAAA,EAAQ,YAAY;AAGpB,UAAM+K,IAAa,SAAS,cAAc,KAAK;AAC/C,IAAAA,EAAW,YAAY,uBACvB/K,EAAQ,YAAY+K,CAAU;AAG9B,UAAMC,IAAa,SAAS,cAAc,QAAQ;AAClD,WAAAA,EAAW,YAAY,2BACvBA,EAAW,cAAc,YACzBA,EAAW,iBAAiB,SAAS,MAAM;AACzC,MAAAzmB,EAAK,eAAA,GACL,KAAK,eAAewmB,CAAU;AAAA,IAChC,CAAC,GACD/K,EAAQ,YAAYgL,CAAU,GAG9B,KAAK,oBAAoBD,GAGzB,KAAK,eAAeA,CAAU,GAG9BlhB,EAAU,YAAYmW,CAAO,GAGtB,MAAM;AACX,WAAK,oBAAoB,MACzBA,EAAQ,OAAA;AAAA,IACV;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,mBAA4B;AAClC,UAAMxb,IAAS,KAAK,MAAM,kBAAkB,SAAS;AAErD,WAAO,CAAC,EAAEA,KAAU,OAAQA,EAAoC,cAAe;AAAA,EACjF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,eAAeumB,GAA+B;AACpD,UAAMxmB,IAAO,KAAK,MACZ0mB,IAAiB,KAAK,iBAAA;AAE5B,IAAAF,EAAW,YAAY;AAGvB,UAAMG,IAAa3mB,EAAK,cAAA;AAExB,aAAS,IAAI,GAAG,IAAI2mB,EAAW,QAAQ,KAAK;AAC1C,YAAMhpB,IAAMgpB,EAAW,CAAC,GAClBziB,IAAQvG,EAAI,UAAUA,EAAI,OAE1BpB,IAAM,SAAS,cAAc,KAAK;AACxC,MAAAA,EAAI,YAAYoB,EAAI,cAAc,8BAA8B,sBAChEpB,EAAI,aAAa,cAAcoB,EAAI,KAAK,GACxCpB,EAAI,aAAa,cAAc,OAAO,CAAC,CAAC,GAGpCmqB,KAAkB7H,GAAclhB,CAA8B,MAChEpB,EAAI,YAAY,IAChBA,EAAI,UAAU,IAAI,aAAa,GAE/B,KAAK,mBAAmBA,GAAKoB,EAAI,OAAO,GAAG6oB,CAAU;AAGvD,YAAM3J,IAAe,SAAS,cAAc,OAAO;AACnD,MAAAA,EAAa,YAAY;AAEzB,YAAM9R,IAAW,SAAS,cAAc,OAAO;AAC/C,MAAAA,EAAS,OAAO,YAChBA,EAAS,UAAUpN,EAAI,SACvBoN,EAAS,WAAWpN,EAAI,eAAe,IACvCoN,EAAS,iBAAiB,UAAU,MAAM;AACxC,QAAA/K,EAAK,uBAAuBrC,EAAI,KAAK,GAErC,WAAW,MAAM,KAAK,eAAe6oB,CAAU,GAAG,CAAC;AAAA,MACrD,CAAC;AAED,YAAM3oB,IAAO,SAAS,cAAc,MAAM;AAO1C,UANAA,EAAK,cAAcqG,GAEnB2Y,EAAa,YAAY9R,CAAQ,GACjC8R,EAAa,YAAYhf,CAAI,GAGzB6oB,KAAkB7H,GAAclhB,CAA8B,GAAG;AACnE,cAAMipB,IAAS,SAAS,cAAc,MAAM;AAC5C,QAAAA,EAAO,YAAY,yBAEnB,KAAK,QAAQA,GAAQ,KAAK,YAAY,YAAY,CAAC,GACnDA,EAAO,QAAQ,mBACfrqB,EAAI,YAAYqqB,CAAM;AAAA,MACxB;AAEA,MAAArqB,EAAI,YAAYsgB,CAAY,GAC5B2J,EAAW,YAAYjqB,CAAG;AAAA,IAC5B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,mBAAmBA,GAAkBD,GAAeuO,GAAe2b,GAA+B;AACxG,IAAAjqB,EAAI,iBAAiB,aAAa,CAACgI,MAAiB;AAClD,WAAK,aAAa,IAClB,KAAK,eAAejI,GACpB,KAAK,eAAeuO,GAEhBtG,EAAE,iBACJA,EAAE,aAAa,gBAAgB,QAC/BA,EAAE,aAAa,QAAQ,cAAcjI,CAAK,IAG5CC,EAAI,UAAU,IAAI,UAAU;AAAA,IAC9B,CAAC,GAEDA,EAAI,iBAAiB,WAAW,MAAM;AACpC,WAAK,aAAa,IAClB,KAAK,eAAe,MACpB,KAAK,eAAe,MACpB,KAAK,YAAY,MAEjBiqB,EAAW,iBAAiB,qBAAqB,EAAE,QAAQ,CAACxlB,MAAM;AAChE,QAAAA,EAAE,UAAU,OAAO,YAAY,eAAe,eAAe,YAAY;AAAA,MAC3E,CAAC;AAAA,IACH,CAAC,GAEDzE,EAAI,iBAAiB,YAAY,CAACgI,MAAiB;AAEjD,UADAA,EAAE,eAAA,GACE,CAAC,KAAK,cAAc,KAAK,iBAAiBjI,EAAO;AAErD,YAAMiN,IAAOhN,EAAI,sBAAA,GACXsqB,IAAOtd,EAAK,MAAMA,EAAK,SAAS;AAEtC,WAAK,YAAYhF,EAAE,UAAUsiB,IAAOhc,IAAQA,IAAQ,GAGpD2b,EAAW,iBAAiB,qBAAqB,EAAE,QAAQ,CAACxlB,MAAM;AAChE,QAAIA,MAAMzE,KAAKyE,EAAE,UAAU,OAAO,eAAe,eAAe,YAAY;AAAA,MAC9E,CAAC,GAEDzE,EAAI,UAAU,IAAI,aAAa,GAC/BA,EAAI,UAAU,OAAO,eAAegI,EAAE,UAAUsiB,CAAI,GACpDtqB,EAAI,UAAU,OAAO,cAAcgI,EAAE,WAAWsiB,CAAI;AAAA,IACtD,CAAC,GAEDtqB,EAAI,iBAAiB,aAAa,MAAM;AACtC,MAAAA,EAAI,UAAU,OAAO,eAAe,eAAe,YAAY;AAAA,IACjE,CAAC,GAEDA,EAAI,iBAAiB,QAAQ,CAACgI,MAAiB;AAC7C,MAAAA,EAAE,eAAA;AACF,YAAMmb,IAAe,KAAK,cACpBC,IAAe,KAAK,cACpBC,IAAY,KAAK;AAEvB,UAAI,CAAC,KAAK,cAAcF,MAAiB,QAAQC,MAAiB,QAAQC,MAAc;AACtF;AAIF,YAAMC,IAAmBD,IAAYD,IAAeC,IAAY,IAAIA;AAEpE,UAAIC,MAAqBF,GAAc;AAErC,cAAMP,IAAqC;AAAA,UACzC,OAAOM;AAAA,UACP,WAAWC;AAAA,UACX,SAASE;AAAA,QAAA;AAEX,aAAK,KAAiC,0BAA0BT,CAAM,GAGtE,WAAW,MAAM;AACf,eAAK,eAAeoH,CAAU;AAAA,QAChC,GAAG,CAAC;AAAA,MACN;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA,EAKkB,SAASza;AAAA;AAE7B;"}
|