@toolbox-web/grid 3.9.2 → 3.10.1

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.
Files changed (123) hide show
  1. package/all.js +1 -1
  2. package/all.js.map +1 -1
  3. package/index.js +1 -1
  4. package/index.js.map +1 -1
  5. package/lib/core/types.d.ts +6 -3
  6. package/lib/features/clipboard.js.map +1 -1
  7. package/lib/features/column-virtualization.js.map +1 -1
  8. package/lib/features/context-menu.js.map +1 -1
  9. package/lib/features/editing.js.map +1 -1
  10. package/lib/features/export.js.map +1 -1
  11. package/lib/features/filtering.js.map +1 -1
  12. package/lib/features/grouping-columns.js.map +1 -1
  13. package/lib/features/grouping-rows.js.map +1 -1
  14. package/lib/features/master-detail.js.map +1 -1
  15. package/lib/features/multi-sort.js.map +1 -1
  16. package/lib/features/pinned-columns.js.map +1 -1
  17. package/lib/features/pinned-rows.js.map +1 -1
  18. package/lib/features/pivot.js.map +1 -1
  19. package/lib/features/print.js.map +1 -1
  20. package/lib/features/registry.js +1 -1
  21. package/lib/features/registry.js.map +1 -1
  22. package/lib/features/reorder-columns.js.map +1 -1
  23. package/lib/features/responsive.js.map +1 -1
  24. package/lib/features/row-drag-drop.js.map +1 -1
  25. package/lib/features/selection.js.map +1 -1
  26. package/lib/features/server-side.js.map +1 -1
  27. package/lib/features/shell.js.map +1 -1
  28. package/lib/features/sticky-rows.js.map +1 -1
  29. package/lib/features/tooltip.js.map +1 -1
  30. package/lib/features/tree.js.map +1 -1
  31. package/lib/features/undo-redo.js.map +1 -1
  32. package/lib/features/visibility.js.map +1 -1
  33. package/lib/plugins/clipboard/index.js.map +1 -1
  34. package/lib/plugins/column-virtualization/index.js.map +1 -1
  35. package/lib/plugins/context-menu/index.js.map +1 -1
  36. package/lib/plugins/editing/editors.d.ts +15 -0
  37. package/lib/plugins/editing/index.js +1 -1
  38. package/lib/plugins/editing/index.js.map +1 -1
  39. package/lib/plugins/editing/internal/helpers.d.ts +23 -0
  40. package/lib/plugins/editing/types.d.ts +16 -1
  41. package/lib/plugins/export/index.js +1 -1
  42. package/lib/plugins/export/index.js.map +1 -1
  43. package/lib/plugins/filtering/filter-model.d.ts +20 -1
  44. package/lib/plugins/filtering/filter-panel-default.d.ts +15 -1
  45. package/lib/plugins/filtering/index.d.ts +1 -1
  46. package/lib/plugins/filtering/index.js +1 -1
  47. package/lib/plugins/filtering/index.js.map +1 -1
  48. package/lib/plugins/filtering/types.d.ts +58 -3
  49. package/lib/plugins/grouping-columns/index.js.map +1 -1
  50. package/lib/plugins/grouping-rows/index.js +1 -1
  51. package/lib/plugins/grouping-rows/index.js.map +1 -1
  52. package/lib/plugins/hierarchy/index.js.map +1 -1
  53. package/lib/plugins/master-detail/index.js +1 -1
  54. package/lib/plugins/master-detail/index.js.map +1 -1
  55. package/lib/plugins/master-detail/master-detail-plugin.d.ts +6 -1
  56. package/lib/plugins/multi-sort/index.js.map +1 -1
  57. package/lib/plugins/pinned-columns/index.js.map +1 -1
  58. package/lib/plugins/pinned-rows/index.js.map +1 -1
  59. package/lib/plugins/pivot/index.js +1 -1
  60. package/lib/plugins/pivot/index.js.map +1 -1
  61. package/lib/plugins/pivot/pivot-plugin.d.ts +2 -0
  62. package/lib/plugins/pivot/types.d.ts +2 -0
  63. package/lib/plugins/print/index.js.map +1 -1
  64. package/lib/plugins/reorder-columns/index.js.map +1 -1
  65. package/lib/plugins/responsive/index.js.map +1 -1
  66. package/lib/plugins/row-drag-drop/index.js.map +1 -1
  67. package/lib/plugins/selection/index.js +1 -1
  68. package/lib/plugins/selection/index.js.map +1 -1
  69. package/lib/plugins/server-side/index.js.map +1 -1
  70. package/lib/plugins/shared/form-field-target.d.ts +10 -0
  71. package/lib/plugins/shared/format-value.d.ts +12 -0
  72. package/lib/plugins/shared/structural-toggle.d.ts +14 -0
  73. package/lib/plugins/shell/index.js.map +1 -1
  74. package/lib/plugins/sticky-rows/index.js.map +1 -1
  75. package/lib/plugins/tooltip/index.js.map +1 -1
  76. package/lib/plugins/tree/index.js +1 -1
  77. package/lib/plugins/tree/index.js.map +1 -1
  78. package/lib/plugins/undo-redo/index.d.ts +1 -1
  79. package/lib/plugins/undo-redo/index.js +1 -1
  80. package/lib/plugins/undo-redo/index.js.map +1 -1
  81. package/lib/plugins/undo-redo/types.d.ts +20 -2
  82. package/lib/plugins/undo-redo/undo-redo-plugin.d.ts +8 -0
  83. package/lib/plugins/visibility/index.js.map +1 -1
  84. package/package.json +1 -1
  85. package/umd/grid.all.umd.js +1 -1
  86. package/umd/grid.all.umd.js.map +1 -1
  87. package/umd/grid.umd.js +1 -1
  88. package/umd/grid.umd.js.map +1 -1
  89. package/umd/plugins/clipboard.umd.js.map +1 -1
  90. package/umd/plugins/column-virtualization.umd.js.map +1 -1
  91. package/umd/plugins/context-menu.umd.js.map +1 -1
  92. package/umd/plugins/editing.umd.js +1 -1
  93. package/umd/plugins/editing.umd.js.map +1 -1
  94. package/umd/plugins/export.umd.js +1 -1
  95. package/umd/plugins/export.umd.js.map +1 -1
  96. package/umd/plugins/filtering.umd.js +1 -1
  97. package/umd/plugins/filtering.umd.js.map +1 -1
  98. package/umd/plugins/grouping-columns.umd.js.map +1 -1
  99. package/umd/plugins/grouping-rows.umd.js +1 -1
  100. package/umd/plugins/grouping-rows.umd.js.map +1 -1
  101. package/umd/plugins/hierarchy.umd.js.map +1 -1
  102. package/umd/plugins/master-detail.umd.js +1 -1
  103. package/umd/plugins/master-detail.umd.js.map +1 -1
  104. package/umd/plugins/multi-sort.umd.js.map +1 -1
  105. package/umd/plugins/pinned-columns.umd.js.map +1 -1
  106. package/umd/plugins/pinned-rows.umd.js.map +1 -1
  107. package/umd/plugins/pivot.umd.js +1 -1
  108. package/umd/plugins/pivot.umd.js.map +1 -1
  109. package/umd/plugins/print.umd.js.map +1 -1
  110. package/umd/plugins/reorder-columns.umd.js.map +1 -1
  111. package/umd/plugins/responsive.umd.js.map +1 -1
  112. package/umd/plugins/row-drag-drop.umd.js.map +1 -1
  113. package/umd/plugins/selection.umd.js +1 -1
  114. package/umd/plugins/selection.umd.js.map +1 -1
  115. package/umd/plugins/server-side.umd.js.map +1 -1
  116. package/umd/plugins/shell.umd.js.map +1 -1
  117. package/umd/plugins/sticky-rows.umd.js.map +1 -1
  118. package/umd/plugins/tooltip.umd.js.map +1 -1
  119. package/umd/plugins/tree.umd.js +1 -1
  120. package/umd/plugins/tree.umd.js.map +1 -1
  121. package/umd/plugins/undo-redo.umd.js +1 -1
  122. package/umd/plugins/undo-redo.umd.js.map +1 -1
  123. package/umd/plugins/visibility.umd.js.map +1 -1
@@ -101,6 +101,8 @@ export declare class PivotPlugin extends BaseGridPlugin<PivotConfig> {
101
101
  private keysToAnimate;
102
102
  /** Cached value formatters keyed by value field name */
103
103
  private valueFormatters;
104
+ /** Value fields whose column `format` already logged TBW062 (warn once per field, not per rebuild) */
105
+ private formatErrorFields;
104
106
  /** Column totals for percentage mode */
105
107
  private columnTotals;
106
108
  /** Current interactive sort state for pivot columns (managed by onHeaderClick) */
@@ -174,6 +174,8 @@ export interface PivotValueField {
174
174
  /**
175
175
  * Format function for display values. Receives the aggregated number and returns a string.
176
176
  * When omitted, the original column's `format` is used if available, otherwise raw `String(value)`.
177
+ * Aggregates have no source row, so the column's `format` is called with `row` undefined; if it
178
+ * throws (e.g. it reads the row), the raw number is shown. Set this when the column's `format` needs the row.
177
179
  *
178
180
  * @example
179
181
  * ```typescript
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../../../libs/grid/src/lib/core/internal/diagnostics.ts","../../../../../../libs/grid/src/lib/plugins/print/print-isolated.ts","../../../../../../libs/grid/src/lib/plugins/print/print.css?inline","../../../../../../libs/grid/src/lib/plugins/print/print-plugin.ts"],"sourcesContent":["/**\n * Centralized diagnostic messages for @toolbox-web/grid.\n *\n * Every user-facing warning, error, or info message in the grid has a unique\n * diagnostic code (e.g. `TBW001`). Each code maps to a section on the online\n * troubleshooting page, giving developers a direct link to resolution steps.\n *\n * ## Usage\n *\n * ```ts\n * import { MISSING_BREAKPOINT, warnDiagnostic, throwDiagnostic } from './diagnostics';\n *\n * // Warn with a code\n * warnDiagnostic(MISSING_BREAKPOINT, 'Set a breakpoint...', gridId);\n *\n * // Throw with a code\n * throwDiagnostic(MISSING_ROW_ID, 'Configure getRowId...', gridId);\n * ```\n *\n * Plugins should prefer `this.warn(MISSING_BREAKPOINT, message)` via BaseGridPlugin\n * instead of importing this module directly.\n *\n * @internal\n */\n\n// #region Grid Prefix\n\n/**\n * Build the `[tbw-grid]` or `[tbw-grid#my-id]` log prefix.\n * Pass `pluginName` for a scoped prefix like `[tbw-grid:SelectionPlugin]`.\n */\nexport function gridPrefix(gridId?: string, pluginName?: string): string {\n const id = gridId ? `#${gridId}` : '';\n const plugin = pluginName ? `:${pluginName}` : '';\n return `[tbw-grid${id}${plugin}]`;\n}\n\n// #endregion\n\n// #region Diagnostic Codes\n\n/**\n * Diagnostic codes used across the grid library.\n *\n * Each code is an individual export so that unused codes are tree-shaken\n * from bundles that don't reference them (esbuild can't tree-shake\n * properties from a single object).\n *\n * Naming: TBW + 3-digit number.\n * Ranges:\n * 001–019 Configuration validation (missing plugins, bad config)\n * 020–029 Plugin lifecycle (dependencies, incompatibilities, alias collapse)\n * 030–039 Feature registry\n * 040–049 Row operations (row ID, row mutations)\n * 050–059 Column operations (width, template)\n * 060–069 Rendering (callbacks, formatters, external views)\n * 070–079 Shell (tool panels, header/toolbar content)\n * 080–089 Editing & editors\n * 090–099 Print\n * 100–109 Clipboard\n * 110–119 Plugin-specific (responsive, undo-redo, grouping-columns)\n * 120–129 Style injection\n * 130–139 Attribute parsing\n * 140–149 DataSource / ServerSide\n */\n\n// --- Config validation (001–019) ---\n/** Column uses a plugin-owned property but the plugin is not loaded. */\nexport const MISSING_PLUGIN = 'TBW001' as const;\n/** Grid config uses a plugin-owned property but the plugin is not loaded. */\nexport const MISSING_PLUGIN_CONFIG = 'TBW002' as const;\n/** Plugin config rule violation (error severity). */\nexport const CONFIG_RULE_ERROR = 'TBW003' as const;\n/** Plugin config rule violation (warning severity). */\nexport const CONFIG_RULE_WARN = 'TBW004' as const;\n\n// --- Plugin lifecycle (020–029) ---\n/** Required plugin dependency is missing. */\nexport const MISSING_DEPENDENCY = 'TBW020' as const;\n/** Optional plugin dependency is missing. */\nexport const OPTIONAL_DEPENDENCY = 'TBW021' as const;\n/** Two loaded plugins are incompatible. */\nexport const INCOMPATIBLE_PLUGINS = 'TBW022' as const;\n/** Two plugin instances resolve to the same canonical name (alias collapse). */\nexport const PLUGIN_ALIAS_COLLAPSE = 'TBW023' as const;\n/** Error thrown inside a plugin event handler. */\nexport const PLUGIN_EVENT_ERROR = 'TBW024' as const;\n/** Conflicting config values found while merging alias-collapsed plugin instances. */\nexport const PLUGIN_ALIAS_CONFIG_CONFLICT = 'TBW025' as const;\n\n// --- Feature registry (030–039) ---\n/** Feature was re-registered (overwritten). */\nexport const FEATURE_REREGISTERED = 'TBW030' as const;\n/** Feature configured but not imported. */\nexport const FEATURE_NOT_IMPORTED = 'TBW031' as const;\n/** Feature depends on another feature that is not enabled. */\nexport const FEATURE_MISSING_DEP = 'TBW032' as const;\n\n// --- Row operations (040–049) ---\n/** Cannot determine row ID (no getRowId and no id property). */\nexport const MISSING_ROW_ID = 'TBW040' as const;\n/** Row with given ID not found. */\nexport const ROW_NOT_FOUND = 'TBW041' as const;\n\n// --- Column operations (050–059) ---\n/** Column has an invalid CSS width value. */\nexport const INVALID_COLUMN_WIDTH = 'TBW050' as const;\n\n// --- Rendering callbacks (060–069) ---\n/** rowClass callback threw an error. */\nexport const ROW_CLASS_ERROR = 'TBW060' as const;\n/** cellClass callback threw an error. */\nexport const CELL_CLASS_ERROR = 'TBW061' as const;\n/** Column format function threw an error. */\nexport const FORMAT_ERROR = 'TBW062' as const;\n/** External view mount() threw an error. */\nexport const VIEW_MOUNT_ERROR = 'TBW063' as const;\n/** External view event dispatch error. */\nexport const VIEW_DISPATCH_ERROR = 'TBW064' as const;\n\n// --- Shell (070–079) ---\n/** Tool panel missing required id. */\nexport const TOOL_PANEL_MISSING_ATTR = 'TBW070' as const;\n/** No tool panels registered. */\nexport const NO_TOOL_PANELS = 'TBW071' as const;\n/** Tool panel section not found. */\nexport const TOOL_PANEL_NOT_FOUND = 'TBW072' as const;\n/** Tool panel already registered. */\nexport const TOOL_PANEL_DUPLICATE = 'TBW073' as const;\n/** Header content already registered. */\nexport const HEADER_CONTENT_DUPLICATE = 'TBW074' as const;\n/** Toolbar content already registered. */\nexport const TOOLBAR_CONTENT_DUPLICATE = 'TBW075' as const;\n\n// --- Editing & editors (080–089) ---\n/** External editor mount() threw an error. */\nexport const EDITOR_MOUNT_ERROR = 'TBW080' as const;\n\n// --- Print (090–099) ---\n/** Print already in progress. */\nexport const PRINT_IN_PROGRESS = 'TBW090' as const;\n/** Grid not available for printing. */\nexport const PRINT_NO_GRID = 'TBW091' as const;\n/** Print operation failed. */\nexport const PRINT_FAILED = 'TBW092' as const;\n/** Multiple elements share the same grid ID (print isolation issue). */\nexport const PRINT_DUPLICATE_ID = 'TBW093' as const;\n\n// --- Clipboard (100–109) ---\n/** Clipboard API write failed. */\nexport const CLIPBOARD_FAILED = 'TBW100' as const;\n\n// --- Plugin-specific (110–119) ---\n/** ResponsivePlugin: no breakpoint configured. */\nexport const MISSING_BREAKPOINT = 'TBW110' as const;\n/** UndoRedoPlugin: transaction already in progress. */\nexport const TRANSACTION_IN_PROGRESS = 'TBW111' as const;\n/** UndoRedoPlugin: no transaction in progress. */\nexport const NO_TRANSACTION = 'TBW112' as const;\n/** GroupingColumnsPlugin: missing id or header on column group definition. */\nexport const COLUMN_GROUP_NO_ID = 'TBW113' as const;\n/** GroupingColumnsPlugin: conflicting columnGroups sources. */\nexport const COLUMN_GROUPS_CONFLICT = 'TBW114' as const;\n\n// --- Style injection (120–129) ---\n/** Failed to extract grid.css from document stylesheets. */\nexport const STYLE_EXTRACT_FAILED = 'TBW120' as const;\n/** Could not find grid.css in document.styleSheets. */\nexport const STYLE_NOT_FOUND = 'TBW121' as const;\n\n// --- Attribute parsing (130–139) ---\n/** Invalid JSON in an HTML attribute. */\nexport const INVALID_ATTRIBUTE_JSON = 'TBW130' as const;\n\n// --- DataSource / ServerSide (140–149) ---\n/** ServerSidePlugin: getRows() rejected. */\nexport const DATASOURCE_FETCH_ERROR = 'TBW140' as const;\n/** ServerSidePlugin: getChildRows() rejected. */\nexport const DATASOURCE_CHILD_FETCH_ERROR = 'TBW141' as const;\n/** ServerSidePlugin: getChildRows() not implemented but a plugin queried for children. */\nexport const DATASOURCE_NO_CHILD_HANDLER = 'TBW142' as const;\n/** ServerSidePlugin: concurrent request limit reached, request deferred. */\nexport const DATASOURCE_THROTTLED = 'TBW143' as const;\n\nexport type DiagnosticCode =\n | typeof MISSING_PLUGIN\n | typeof MISSING_PLUGIN_CONFIG\n | typeof CONFIG_RULE_ERROR\n | typeof CONFIG_RULE_WARN\n | typeof MISSING_DEPENDENCY\n | typeof OPTIONAL_DEPENDENCY\n | typeof INCOMPATIBLE_PLUGINS\n | typeof PLUGIN_ALIAS_COLLAPSE\n | typeof PLUGIN_EVENT_ERROR\n | typeof PLUGIN_ALIAS_CONFIG_CONFLICT\n | typeof FEATURE_REREGISTERED\n | typeof FEATURE_NOT_IMPORTED\n | typeof FEATURE_MISSING_DEP\n | typeof MISSING_ROW_ID\n | typeof ROW_NOT_FOUND\n | typeof INVALID_COLUMN_WIDTH\n | typeof ROW_CLASS_ERROR\n | typeof CELL_CLASS_ERROR\n | typeof FORMAT_ERROR\n | typeof VIEW_MOUNT_ERROR\n | typeof VIEW_DISPATCH_ERROR\n | typeof TOOL_PANEL_MISSING_ATTR\n | typeof NO_TOOL_PANELS\n | typeof TOOL_PANEL_NOT_FOUND\n | typeof TOOL_PANEL_DUPLICATE\n | typeof HEADER_CONTENT_DUPLICATE\n | typeof TOOLBAR_CONTENT_DUPLICATE\n | typeof EDITOR_MOUNT_ERROR\n | typeof PRINT_IN_PROGRESS\n | typeof PRINT_NO_GRID\n | typeof PRINT_FAILED\n | typeof PRINT_DUPLICATE_ID\n | typeof CLIPBOARD_FAILED\n | typeof MISSING_BREAKPOINT\n | typeof TRANSACTION_IN_PROGRESS\n | typeof NO_TRANSACTION\n | typeof COLUMN_GROUP_NO_ID\n | typeof COLUMN_GROUPS_CONFLICT\n | typeof STYLE_EXTRACT_FAILED\n | typeof STYLE_NOT_FOUND\n | typeof INVALID_ATTRIBUTE_JSON\n | typeof DATASOURCE_FETCH_ERROR\n | typeof DATASOURCE_CHILD_FETCH_ERROR\n | typeof DATASOURCE_NO_CHILD_HANDLER\n | typeof DATASOURCE_THROTTLED;\n\n// #endregion\n\n// #region Docs URL\n\nconst DOCS_BASE = 'https://toolboxjs.com/grid/errors';\n\n/** Build a direct link to the troubleshooting section for a code. */\nfunction docsUrl(code: DiagnosticCode): string {\n return `${DOCS_BASE}#${code.toLowerCase()}`;\n}\n\n// #endregion\n\n// #region Formatting\n\n/**\n * Format a diagnostic message with prefix, code, and docs link.\n *\n * Output format:\n * ```\n * [tbw-grid#my-id] TBW001: Your message here.\n *\n * → More info: https://toolboxjs.com/grid/errors#tbw001\n * ```\n */\nexport function formatDiagnostic(code: DiagnosticCode, message: string, gridId?: string, pluginName?: string): string {\n const prefix = gridPrefix(gridId, pluginName);\n return `${prefix} ${code}: ${message}\\n\\n → More info: ${docsUrl(code)}`;\n}\n\n// #endregion\n\n// #region Public API\n\n/**\n * Throw an error with a diagnostic code and docs link.\n * Use for configuration errors and API misuse that should halt execution.\n */\nexport function throwDiagnostic(code: DiagnosticCode, message: string, gridId?: string, pluginName?: string): never {\n throw new Error(formatDiagnostic(code, message, gridId, pluginName));\n}\n\n/**\n * Log a warning with a diagnostic code and docs link.\n * Use for recoverable issues the developer should fix.\n */\nexport function warnDiagnostic(code: DiagnosticCode, message: string, gridId?: string, pluginName?: string): void {\n console.warn(formatDiagnostic(code, message, gridId, pluginName));\n}\n\n/**\n * Log a debug message with a diagnostic code and docs link.\n * Use for optional/soft dependency notifications — visible only when\n * the browser DevTools \"Verbose\" log level is enabled.\n */\nexport function debugDiagnostic(code: DiagnosticCode, message: string, gridId?: string, pluginName?: string): void {\n console.debug(formatDiagnostic(code, message, gridId, pluginName));\n}\n\n/**\n * Log an error with a diagnostic code and docs link.\n * Use for non-throwing errors (e.g., failed async operations).\n */\nexport function errorDiagnostic(code: DiagnosticCode, message: string, gridId?: string, pluginName?: string): void {\n console.error(formatDiagnostic(code, message, gridId, pluginName));\n}\n\n// #endregion\n","/**\n * Utility for printing a grid in isolation by hiding all other page content.\n *\n * This approach keeps the grid in place (with virtualization disabled by PrintPlugin)\n * and uses CSS to hide everything else on the page during printing.\n */\n\nimport { PRINT_DUPLICATE_ID, warnDiagnostic } from '../../core/internal/diagnostics';\nimport type { PrintOrientation } from './types';\n\n/** @since 1.4.0 */\nexport interface PrintIsolatedOptions {\n /** Page orientation hint */\n orientation?: PrintOrientation;\n}\n\n/** ID for the isolation stylesheet */\nconst ISOLATION_STYLE_ID = 'tbw-print-isolation-style';\n\n/**\n * Create a stylesheet that hides everything except the target grid.\n * Uses the grid's ID to target it specifically.\n */\nfunction createIsolationStylesheet(gridId: string, orientation: PrintOrientation): HTMLStyleElement {\n const style = document.createElement('style');\n style.id = ISOLATION_STYLE_ID;\n style.textContent = `\n /* Print isolation: hide everything except the target grid */\n @media print {\n /* Hide all body children by default */\n body > *:not(#${gridId}) {\n display: none !important;\n }\n\n /* But show the grid and ensure it's not hidden by ancestor rules */\n #${gridId} {\n display: block !important;\n position: static !important;\n visibility: visible !important;\n opacity: 1 !important;\n overflow: visible !important;\n height: auto !important;\n width: 100% !important;\n max-height: none !important;\n margin: 0 !important;\n padding: 0 !important;\n transform: none !important;\n }\n\n /* If grid is nested, we need to show its ancestors too */\n #${gridId},\n #${gridId} * {\n visibility: visible !important;\n }\n\n /* Walk up the DOM and show all ancestors of the grid */\n body *:has(> #${gridId}),\n body *:has(#${gridId}) {\n display: block !important;\n visibility: visible !important;\n opacity: 1 !important;\n overflow: visible !important;\n height: auto !important;\n position: static !important;\n transform: none !important;\n background: transparent !important;\n border: none !important;\n padding: 0 !important;\n margin: 0 !important;\n }\n\n /* Hide siblings of ancestors (everything that's not in the path to the grid) */\n body *:has(#${gridId}) > *:not(:has(#${gridId})):not(#${gridId}) {\n display: none !important;\n }\n\n /* Page settings */\n @page {\n size: ${orientation};\n margin: 1cm;\n }\n\n /* Ensure proper print styling */\n body {\n margin: 0 !important;\n padding: 0 !important;\n background: white !important;\n color-scheme: light !important;\n }\n }\n\n /* Screen: also apply isolation for print preview */\n @media screen {\n /* When this stylesheet is active, we're about to print */\n /* No screen-specific rules needed - isolation only applies to print */\n }\n `;\n return style;\n}\n\n/**\n * Print a grid in isolation by hiding all other page content.\n *\n * This function adds a temporary stylesheet that uses CSS to hide everything\n * on the page except the target grid during printing. The grid stays in place\n * with all its data (virtualization should be disabled separately).\n *\n * @param gridElement - The tbw-grid element to print (must have an ID)\n * @param options - Optional configuration\n * @returns Promise that resolves when the print dialog closes\n *\n * @example\n * ```typescript\n * import { queryGrid } from '@toolbox-web/grid';\n * import { printGridIsolated } from '@toolbox-web/grid/plugins/print';\n *\n * const grid = queryGrid('tbw-grid');\n * await printGridIsolated(grid, { orientation: 'landscape' });\n * ```\n * @since 1.4.0\n */\nexport async function printGridIsolated(gridElement: HTMLElement, options: PrintIsolatedOptions = {}): Promise<void> {\n const { orientation = 'landscape' } = options;\n\n const gridId = gridElement.id;\n\n // Warn if multiple elements share this ID (user-set IDs could collide)\n const elementsWithId = document.querySelectorAll(`#${CSS.escape(gridId)}`);\n if (elementsWithId.length > 1) {\n warnDiagnostic(\n PRINT_DUPLICATE_ID,\n `Multiple elements found with id=\"${gridId}\". ` +\n `Print isolation may not work correctly. Ensure each grid has a unique ID.`,\n gridId,\n 'print',\n );\n }\n\n // Remove any existing isolation stylesheet\n document.getElementById(ISOLATION_STYLE_ID)?.remove();\n\n // Add the isolation stylesheet\n const isolationStyle = createIsolationStylesheet(gridId, orientation);\n document.head.appendChild(isolationStyle);\n\n return new Promise((resolve) => {\n // Listen for afterprint event to cleanup\n const onAfterPrint = () => {\n window.removeEventListener('afterprint', onAfterPrint);\n // Remove isolation stylesheet\n document.getElementById(ISOLATION_STYLE_ID)?.remove();\n resolve();\n };\n window.addEventListener('afterprint', onAfterPrint);\n\n // Trigger print\n window.print();\n\n // Fallback timeout in case afterprint doesn't fire (some browsers)\n setTimeout(() => {\n window.removeEventListener('afterprint', onAfterPrint);\n document.getElementById(ISOLATION_STYLE_ID)?.remove();\n resolve();\n }, 5000);\n });\n}\n","/**\n * Print Plugin CSS\n *\n * Styles for print-optimized grid rendering.\n * Uses @media print for automatic print detection.\n */\n\n/* Print header/footer - hidden on screen, shown in print */\n.tbw-print-header,\n.tbw-print-footer {\n display: none;\n}\n\n/* ========================================\n @media print rules - all print styles\n ======================================== */\n\n@media print {\n tbw-grid {\n /* Force visible overflow to render all rows */\n overflow: visible !important;\n height: auto !important;\n\n /* Remove outer border - keep only cell borders */\n border: none !important;\n border-radius: 0 !important;\n\n /* Force light mode for printing */\n color-scheme: light only;\n\n /* Ensure colors print */\n -webkit-print-color-adjust: exact;\n print-color-adjust: exact;\n }\n\n tbw-grid .tbw-grid-content {\n overflow: visible !important;\n height: auto !important;\n max-height: none !important;\n }\n\n tbw-grid .tbw-scroll-area {\n overflow: visible !important;\n height: auto !important;\n max-height: none !important;\n }\n\n tbw-grid .rows-body {\n overflow: visible !important;\n height: auto !important;\n max-height: none !important;\n }\n\n /* Ensure virtualized rows container expands to show all rows */\n tbw-grid .rows-container,\n tbw-grid .rows-viewport,\n tbw-grid .rows {\n overflow: visible !important;\n height: auto !important;\n max-height: none !important;\n transform: none !important; /* Remove virtual scroll offset */\n }\n\n tbw-grid .rows-viewport .rows {\n position: static !important; /* Reset from absolute positioning */\n }\n\n /* Hide interactive elements, shell chrome, and header icons */\n tbw-grid .resize-handle,\n tbw-grid [part='sort-indicator'],\n tbw-grid .tbw-filter-btn,\n tbw-grid .tool-panel,\n tbw-grid .tool-panel-content,\n tbw-grid .tbw-shell-header,\n tbw-grid .shell-toolbar,\n tbw-grid .tool-panel-toggle,\n tbw-grid [data-print-hide],\n tbw-grid .expander-cell,\n tbw-grid .tree-toggle,\n tbw-grid .context-menu,\n tbw-grid .faux-vscroll {\n display: none !important;\n }\n\n /* Print header with title and timestamp */\n tbw-grid .tbw-print-header {\n display: flex;\n justify-content: space-between;\n align-items: baseline;\n padding: var(--tbw-spacing-md, 0.5em) 0;\n margin-bottom: var(--tbw-spacing-md, 0.5em);\n border-bottom: 2px solid var(--tbw-print-border, var(--tbw-color-border-strong));\n font-family: inherit;\n }\n\n .tbw-print-header-title {\n font-size: 1.25em;\n font-weight: bold;\n }\n\n .tbw-print-header-timestamp {\n font-size: var(--tbw-font-size-sm, 0.875em);\n color: var(--tbw-print-muted, var(--tbw-color-fg-muted));\n }\n\n /* Print footer */\n tbw-grid .tbw-print-footer {\n display: block;\n margin-top: var(--tbw-spacing-md, 0.5em);\n padding-top: var(--tbw-spacing-md, 0.5em);\n border-top: 1px solid var(--tbw-print-border, var(--tbw-color-border));\n font-size: var(--tbw-font-size-xs, 0.75em);\n color: var(--tbw-print-muted, var(--tbw-color-fg-muted));\n text-align: end;\n }\n\n /* Row styling */\n tbw-grid .data-grid-row {\n break-inside: avoid;\n page-break-inside: avoid;\n }\n\n /* Cell styling - use theme variables with print-safe fallbacks */\n tbw-grid .cell {\n border: 1px solid var(--tbw-print-cell-border, var(--tbw-color-border)) !important;\n }\n\n /* Ensure the last column's end border is visible */\n tbw-grid .header-row,\n tbw-grid .data-grid-row {\n padding-inline-end: 1px; /* Prevent end border from being clipped */\n }\n\n /* Remove hover effects */\n tbw-grid .data-grid-row:hover,\n tbw-grid .cell:hover {\n background: inherit !important;\n }\n\n /* Page setup */\n @page {\n margin: 1cm;\n }\n}\n","/**\n * Print Plugin (Class-based)\n *\n * Provides print layout functionality for tbw-grid.\n * Temporarily disables virtualization to render all rows and uses\n * @media print CSS for print-optimized styling.\n */\n\nimport { PRINT_FAILED, PRINT_IN_PROGRESS, PRINT_NO_GRID, errorDiagnostic } from '../../core/internal/diagnostics';\nimport { BaseGridPlugin, type GridElement } from '../../core/plugin/base-plugin';\nimport type { ToolbarContentDefinition } from '../shell/types';\nimport { printGridIsolated } from './print-isolated';\nimport styles from './print.css?inline';\nimport type { PrintCompleteDetail, PrintConfig, PrintParams, PrintStartDetail } from './types';\n\n/**\n * Extended grid interface for PrintPlugin internal access.\n * Includes registerToolbarContent which is available on the grid class\n * but not exposed in the standard plugin API.\n */\ninterface PrintGridRef extends GridElement {\n registerToolbarContent?(content: ToolbarContentDefinition): void;\n unregisterToolbarContent?(contentId: string): void;\n}\n\n/** Default configuration */\nconst DEFAULT_CONFIG: Required<PrintConfig> = {\n button: false,\n orientation: 'landscape',\n warnThreshold: 500,\n maxRows: 0,\n includeTitle: true,\n includeTimestamp: true,\n title: '',\n isolate: false,\n};\n\n/**\n * Print Plugin for tbw-grid\n *\n * Enables printing the full grid content by temporarily disabling virtualization\n * and applying print-optimized styles. Handles large datasets gracefully with\n * configurable row limits.\n *\n * ## Installation\n *\n * ```ts\n * import { PrintPlugin } from '@toolbox-web/grid/plugins/print';\n * ```\n *\n * ## Events\n *\n * | Event | Detail | Description |\n * |-------|--------|-------------|\n * | `print-start` | {@link PrintStartDetail} | Fired when print begins |\n * | `print-complete` | {@link PrintCompleteDetail} | Fired when print completes |\n *\n * @example Basic Print\n * ```ts\n * import { queryGrid } from '@toolbox-web/grid';\n * import { PrintPlugin } from '@toolbox-web/grid/plugins/print';\n *\n * const grid = queryGrid('tbw-grid');\n * grid.gridConfig = {\n * plugins: [new PrintPlugin()],\n * };\n *\n * // Trigger print\n * const printPlugin = grid.getPluginByName('print');\n * await printPlugin.print();\n * ```\n *\n * @example With Toolbar Button\n * ```ts\n * grid.gridConfig = {\n * plugins: [new PrintPlugin({ button: true, orientation: 'landscape' })],\n * };\n * ```\n *\n * @see {@link PrintConfig} for all configuration options\n * @since 1.4.0\n */\nexport class PrintPlugin extends BaseGridPlugin<PrintConfig> {\n /** @internal */\n readonly name = 'print';\n\n /** @internal */\n override readonly version = '1.0.0';\n\n /** CSS styles for print mode */\n override readonly styles = styles;\n\n /** Current print state */\n #printing = false;\n\n /** Saved column visibility state */\n #savedHiddenColumns: Map<string, boolean> | null = null;\n\n /** Saved virtualization state */\n #savedVirtualization: { bypassThreshold: number } | null = null;\n\n /** Saved rows when maxRows limit is applied */\n #savedRows: unknown[] | null = null;\n\n /** Print header element */\n #printHeader: HTMLElement | null = null;\n\n /** Print footer element */\n #printFooter: HTMLElement | null = null;\n\n /** Applied scale factor (legacy, used for cleanup) */\n #appliedScale: number | null = null;\n\n /**\n * Get the grid typed as PrintGridRef for internal access.\n */\n get #internalGrid(): PrintGridRef {\n return this.grid;\n }\n\n /**\n * Check if print is currently in progress\n */\n isPrinting(): boolean {\n return this.#printing;\n }\n\n /**\n * Trigger the browser print dialog\n *\n * This method:\n * 1. Validates row count against maxRows limit\n * 2. Disables virtualization to render all rows\n * 3. Applies print-specific CSS classes\n * 4. Opens the browser print dialog (or isolated window if `isolate: true`)\n * 5. Restores normal state after printing\n *\n * @param params - Optional parameters to override config for this print\n * @param params.isolate - If true, prints in an isolated window containing only the grid\n * @returns Promise that resolves when print dialog closes\n */\n async print(params?: PrintParams): Promise<void> {\n if (this.#printing) {\n this.warn(PRINT_IN_PROGRESS, 'Print already in progress');\n return;\n }\n\n const grid = this.gridElement;\n if (!grid) {\n this.warn(PRINT_NO_GRID, 'Grid not available');\n return;\n }\n\n const config = { ...DEFAULT_CONFIG, ...this.config, ...params };\n const rows = this.rows;\n const originalRowCount = rows.length;\n let rowCount = originalRowCount;\n let limitApplied = false;\n\n // Check if we should warn about large datasets\n if (config.warnThreshold > 0 && originalRowCount > config.warnThreshold) {\n const limitInfo =\n config.maxRows > 0 ? `\\n\\nNote: Output will be limited to ${config.maxRows.toLocaleString()} rows.` : '';\n const proceed = confirm(\n `This grid has ${originalRowCount.toLocaleString()} rows. ` +\n `Printing large datasets may cause performance issues or browser slowdowns.${limitInfo}\\n\\n` +\n `Click OK to continue, or Cancel to abort.`,\n );\n if (!proceed) {\n return;\n }\n }\n\n // Apply hard row limit if configured\n if (config.maxRows > 0 && originalRowCount > config.maxRows) {\n rowCount = config.maxRows;\n limitApplied = true;\n }\n\n this.#printing = true;\n\n // Track timing for duration reporting\n const startTime = performance.now();\n\n // Emit print-start event\n this.emit<PrintStartDetail>('print-start', {\n rowCount,\n limitApplied,\n originalRowCount,\n });\n\n try {\n // Save current virtualization state\n const internalGrid = this.#internalGrid;\n this.#savedVirtualization = {\n bypassThreshold: internalGrid._virtualization?.bypassThreshold ?? 24,\n };\n\n // Hide columns marked with printHidden\n this.#hidePrintColumns();\n\n // Apply row limit if configured\n if (limitApplied) {\n this.#savedRows = this.sourceRows;\n // Set limited rows on the grid\n this.grid.rows = this.sourceRows.slice(0, rowCount);\n // Wait for grid to process new rows\n await new Promise((resolve) => setTimeout(resolve, 50));\n }\n\n // Add print header if configured\n if (config.includeTitle || config.includeTimestamp) {\n this.#addPrintHeader(config);\n }\n\n // Disable virtualization to render all rows\n // This forces the grid to render all rows in the DOM\n await this.#disableVirtualization();\n\n // Wait for next frame to ensure DOM is updated\n await new Promise((resolve) => requestAnimationFrame(resolve));\n await new Promise((resolve) => requestAnimationFrame(resolve));\n\n // Add orientation class for @page rules\n grid.classList.add(`print-${config.orientation}`);\n\n // Wait for next frame to ensure DOM is updated\n await new Promise((resolve) => requestAnimationFrame(resolve));\n await new Promise((resolve) => requestAnimationFrame(resolve));\n\n // Trigger browser print dialog (isolated or inline)\n if (config.isolate) {\n await this.#printInIsolatedWindow(config);\n } else {\n await this.#triggerPrint();\n }\n\n // Emit print-complete event\n this.emit<PrintCompleteDetail>('print-complete', {\n success: true,\n rowCount,\n duration: Math.round(performance.now() - startTime),\n });\n } catch (error) {\n errorDiagnostic(PRINT_FAILED, `Print failed: ${error}`, this.gridElement?.id, this.name);\n this.emit<PrintCompleteDetail>('print-complete', {\n success: false,\n rowCount: 0,\n duration: Math.round(performance.now() - startTime),\n });\n } finally {\n // Restore normal state\n this.#cleanup();\n this.#printing = false;\n }\n }\n\n /**\n * Add print header with title and timestamp\n */\n #addPrintHeader(config: Required<PrintConfig>): void {\n const grid = this.gridElement;\n if (!grid) return;\n\n // Create print header\n this.#printHeader = document.createElement('div');\n this.#printHeader.className = 'tbw-print-header';\n\n // Title\n if (config.includeTitle) {\n const title = config.title || this.grid.effectiveConfig?.shell?.header?.title || 'Grid Data';\n const titleEl = document.createElement('div');\n titleEl.className = 'tbw-print-header-title';\n titleEl.textContent = title;\n this.#printHeader.appendChild(titleEl);\n }\n\n // Timestamp\n if (config.includeTimestamp) {\n const timestampEl = document.createElement('div');\n timestampEl.className = 'tbw-print-header-timestamp';\n timestampEl.textContent = `Printed: ${new Date().toLocaleString()}`;\n this.#printHeader.appendChild(timestampEl);\n }\n\n // Insert at the beginning of the grid\n grid.insertBefore(this.#printHeader, grid.firstChild);\n\n // Create print footer\n this.#printFooter = document.createElement('div');\n this.#printFooter.className = 'tbw-print-footer';\n this.#printFooter.textContent = `Page generated from ${window.location.hostname}`;\n grid.appendChild(this.#printFooter);\n }\n\n /**\n * Disable virtualization to render all rows\n */\n async #disableVirtualization(): Promise<void> {\n const internalGrid = this.#internalGrid;\n if (!internalGrid._virtualization) return;\n\n // Set bypass threshold higher than total row count to disable virtualization\n // This makes the grid render all rows (up to maxRows) instead of just visible ones\n const totalRows = this.rows.length;\n internalGrid._virtualization.bypassThreshold = totalRows + 100;\n\n // Force a full refresh to re-render with virtualization disabled\n internalGrid.refreshVirtualWindow(true);\n\n // Wait for render to complete\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n\n /**\n * Trigger the browser print dialog\n */\n async #triggerPrint(): Promise<void> {\n return new Promise((resolve) => {\n // Listen for afterprint event\n const onAfterPrint = () => {\n window.removeEventListener('afterprint', onAfterPrint);\n resolve();\n };\n window.addEventListener('afterprint', onAfterPrint);\n\n // Trigger print\n window.print();\n\n // Fallback timeout in case afterprint doesn't fire (some browsers)\n setTimeout(() => {\n // Guard against test environment teardown where window may be undefined\n if (typeof window !== 'undefined') {\n window.removeEventListener('afterprint', onAfterPrint);\n }\n resolve();\n }, 1000);\n });\n }\n\n /**\n * Print in isolation by hiding all other page content.\n * This excludes navigation, sidebars, etc. while keeping the grid in place.\n */\n async #printInIsolatedWindow(config: Required<PrintConfig>): Promise<void> {\n const grid = this.gridElement;\n if (!grid) return;\n\n await printGridIsolated(grid, {\n orientation: config.orientation,\n });\n }\n\n /**\n * Hide columns marked with printHidden: true OR utility: true.\n *\n * Utility (system) columns — selection checkbox, expander, drag handle, custom\n * action menus, etc. — are excluded from print by default. Set `printHidden: false`\n * explicitly on a utility column if you need it to appear in the printout.\n */\n #hidePrintColumns(): void {\n const columns = this.columns;\n if (!columns) return;\n\n // Save current hidden state and hide print columns\n this.#savedHiddenColumns = new Map();\n\n for (const col of columns) {\n if (!col.field) continue;\n // Default: hide if printHidden === true OR utility === true.\n // Allow explicit opt-in for utility columns via `printHidden: false`.\n const shouldHide = col.printHidden === true || (col.utility === true && col.printHidden !== false);\n if (!shouldHide) continue;\n // Save current visibility state (true = visible, false = hidden)\n this.#savedHiddenColumns.set(col.field, !col.hidden);\n // Hide the column for printing\n this.grid.setColumnVisible(col.field, false);\n }\n }\n\n /**\n * Restore columns that were hidden for printing\n */\n #restorePrintColumns(): void {\n if (!this.#savedHiddenColumns) return;\n\n for (const [field, wasVisible] of this.#savedHiddenColumns) {\n // Restore original visibility\n this.grid.setColumnVisible(field, wasVisible);\n }\n\n this.#savedHiddenColumns = null;\n }\n\n /**\n * Cleanup after printing\n */\n #cleanup(): void {\n const grid = this.gridElement;\n if (!grid) return;\n\n // Restore columns that were hidden for printing\n this.#restorePrintColumns();\n\n // Remove orientation classes (both original and possibly switched)\n grid.classList.remove('print-portrait', 'print-landscape');\n\n // Remove scaling transform if applied (legacy)\n if (this.#appliedScale !== null) {\n grid.style.transform = '';\n grid.style.transformOrigin = '';\n grid.style.width = '';\n this.#appliedScale = null;\n }\n\n // Remove print header/footer\n if (this.#printHeader) {\n this.#printHeader.remove();\n this.#printHeader = null;\n }\n if (this.#printFooter) {\n this.#printFooter.remove();\n this.#printFooter = null;\n }\n\n // Restore virtualization\n const internalGrid = this.#internalGrid;\n if (this.#savedVirtualization && internalGrid._virtualization) {\n internalGrid._virtualization.bypassThreshold = this.#savedVirtualization.bypassThreshold;\n internalGrid.refreshVirtualWindow(true);\n this.#savedVirtualization = null;\n }\n\n // Restore original rows if they were limited\n if (this.#savedRows !== null) {\n this.grid.rows = this.#savedRows;\n this.#savedRows = null;\n }\n }\n\n /**\n * Register toolbar button if configured\n * @internal\n */\n override afterRender(): void {\n // Register toolbar on first render when button is enabled\n if (this.config?.button && !this.#toolbarRegistered) {\n this.#registerToolbarButton();\n this.#toolbarRegistered = true;\n }\n }\n\n /** Track if toolbar button is registered */\n #toolbarRegistered = false;\n\n /**\n * Register print button in toolbar\n */\n #registerToolbarButton(): void {\n const grid = this.#internalGrid;\n\n // Register toolbar content\n grid.registerToolbarContent?.({\n id: 'print-button',\n order: 900, // High order to appear at the end\n render: (container: HTMLElement) => {\n const button = document.createElement('button');\n button.className = 'tbw-toolbar-btn tbw-print-btn';\n button.title = this.t('print.buttonTitle', 'Print grid');\n button.type = 'button';\n\n // Use print icon\n this.setIcon(button, 'print');\n\n button.addEventListener(\n 'click',\n () => {\n this.print();\n },\n { signal: this.disconnectSignal },\n );\n\n container.appendChild(button);\n },\n });\n }\n}\n"],"mappings":"mDAgQA,SAAgB,EAAiB,EAAsB,EAAiB,EAAiB,GAEvF,MAAO,GAnOT,SAA2B,EAAiB,GAG1C,MAAO,YAFI,EAAS,IAAI,IAAW,KACpB,EAAa,IAAI,IAAe,KAEjD,CA8NiB,CAAW,EAAQ,MACd,MAAS,uBApB/B,SAAiB,GACf,MAAO,qCAAgB,EAAK,eAC9B,CAkB4D,CAAQ,IACpE,CClPA,IAAM,EAAqB,4BAwG3B,eAAsB,EAAkB,EAA0B,EAAgC,CAAC,GACjG,MAAM,YAAE,EAAc,aAAgB,EAEhC,EAAS,EAAY,GAGJ,SAAS,iBAAiB,IAAI,IAAI,OAAO,MAC7C,OAAS,GDqJ9B,SAA+B,EAAsB,EAAiB,EAAiB,GACrF,QAAQ,KAAK,EAAiB,EAAM,EAAS,EAAQ,GACvD,CCtJI,CDiB8B,SCf5B,oCAAoC,gFAEpC,EACA,SAKJ,SAAS,eAAe,IAAqB,SAG7C,MAAM,EAvHR,SAAmC,EAAgB,GACjD,MAAM,EAAQ,SAAS,cAAc,SAyErC,OAxEA,EAAM,GAAK,EACX,EAAM,YAAc,+JAIA,0IAKb,meAeA,cACA,kJAKa,0BACF,6gBAeA,oBAAyB,YAAiB,+GAM9C,yeAmBP,CACT,CA4CyB,CAA0B,EAAQ,GAGzD,OAFA,SAAS,KAAK,YAAY,GAEnB,IAAI,QAAS,IAElB,MAAM,EAAA,KACJ,OAAO,oBAAoB,aAAc,GAEzC,SAAS,eAAe,IAAqB,SAC7C,KAEF,OAAO,iBAAiB,aAAc,GAGtC,OAAO,QAGP,WAAA,KACE,OAAO,oBAAoB,aAAc,GACzC,SAAS,eAAe,IAAqB,SAC7C,KACC,MAEP,KE3IM,EAAwC,CAC5C,QAAQ,EACR,YAAa,YACb,cAAe,IACf,QAAS,EACT,cAAc,EACd,kBAAkB,EAClB,MAAO,GACP,SAAS,GAgDE,EAAb,cAAiC,EAE/B,KAAgB,QAGhB,QAA4B,QAG5B,qgEAGA,IAAY,EAGZ,GAAmD,KAGnD,GAA2D,KAG3D,GAA+B,KAG/B,GAAmC,KAGnC,GAAmC,KAGnC,GAA+B,KAK/B,KAAI,GACF,OAAO,KAAK,IACd,CAKA,UAAA,GACE,OAAO,MAAK,CACd,CAgBA,WAAM,CAAM,GACV,GAAI,MAAK,EAEP,YADA,KAAK,KHHsB,SGGE,6BAI/B,MAAM,EAAO,KAAK,YAClB,IAAK,EAEH,YADA,KAAK,KHPkB,SGOE,sBAI3B,MAAM,EAAS,IAAK,KAAmB,KAAK,UAAW,GAEjD,EADO,KAAK,KACY,OAC9B,IAAI,EAAW,EACX,GAAe,EAGnB,GAAI,EAAO,cAAgB,GAAK,EAAmB,EAAO,cAAe,CACvE,MAAM,EACJ,EAAO,QAAU,EAAI,uCAAuC,EAAO,QAAQ,yBAA2B,GAMxG,IALgB,QACd,iBAAiB,EAAiB,oGAC6C,kDAI/E,MAEJ,CAGI,EAAO,QAAU,GAAK,EAAmB,EAAO,UAClD,EAAW,EAAO,QAClB,GAAe,GAGjB,MAAK,GAAY,EAGjB,MAAM,EAAY,YAAY,MAG9B,KAAK,KAAuB,cAAe,CACzC,WACA,eACA,qBAGF,IAEE,MAAM,EAAe,MAAK,EAC1B,MAAK,EAAuB,CAC1B,gBAAiB,EAAa,iBAAiB,iBAAmB,IAIpE,MAAK,IAGD,IACF,MAAK,EAAa,KAAK,WAEvB,KAAK,KAAK,KAAO,KAAK,WAAW,MAAM,EAAG,SAEpC,IAAI,QAAS,GAAY,WAAW,EAAS,OAIjD,EAAO,cAAgB,EAAO,mBAChC,MAAK,EAAgB,SAKjB,MAAK,UAGL,IAAI,QAAS,GAAY,sBAAsB,UAC/C,IAAI,QAAS,GAAY,sBAAsB,IAGrD,EAAK,UAAU,IAAI,SAAS,EAAO,qBAG7B,IAAI,QAAS,GAAY,sBAAsB,UAC/C,IAAI,QAAS,GAAY,sBAAsB,IAGjD,EAAO,cACH,MAAK,EAAuB,SAE5B,MAAK,IAIb,KAAK,KAA0B,iBAAkB,CAC/C,SAAS,EACT,WACA,SAAU,KAAK,MAAM,YAAY,MAAQ,IAE7C,CAAA,MAAS,GHmDmB,EAtJJ,SAsJ0B,EGlDlB,iBAAiB,IHkDkB,EGlDT,KAAK,aAAa,GHkDQ,EGlDJ,KAAK,KHmDvF,QAAQ,MAAM,EAAiB,EAAM,EAAS,EAAQ,IGlDlD,KAAK,KAA0B,iBAAkB,CAC/C,SAAS,EACT,SAAU,EACV,SAAU,KAAK,MAAM,YAAY,MAAQ,IAE7C,CAAA,QAEE,MAAK,IACL,MAAK,GAAY,CACnB,CHwCJ,IAAgC,EAAsB,EAAiB,EAAiB,CGvCtF,CAKA,EAAA,CAAgB,GACd,MAAM,EAAO,KAAK,YAClB,GAAK,EAAL,CAOA,GAJA,MAAK,EAAe,SAAS,cAAc,OAC3C,MAAK,EAAa,UAAY,mBAG1B,EAAO,aAAc,CACvB,MAAM,EAAQ,EAAO,OAAS,KAAK,KAAK,iBAAiB,OAAO,QAAQ,OAAS,YAC3E,EAAU,SAAS,cAAc,OACvC,EAAQ,UAAY,yBACpB,EAAQ,YAAc,EACtB,MAAK,EAAa,YAAY,EAChC,CAGA,GAAI,EAAO,iBAAkB,CAC3B,MAAM,EAAc,SAAS,cAAc,OAC3C,EAAY,UAAY,6BACxB,EAAY,YAAc,4BAAA,IAAgB,MAAO,mBACjD,MAAK,EAAa,YAAY,EAChC,CAGA,EAAK,aAAa,MAAK,EAAc,EAAK,YAG1C,MAAK,EAAe,SAAS,cAAc,OAC3C,MAAK,EAAa,UAAY,mBAC9B,MAAK,EAAa,YAAc,uBAAuB,OAAO,SAAS,WACvE,EAAK,YAAY,MAAK,EA9BX,CA+Bb,CAKA,OAAM,GACJ,MAAM,EAAe,MAAK,EAC1B,IAAK,EAAa,gBAAiB,OAInC,MAAM,EAAY,KAAK,KAAK,OAC5B,EAAa,gBAAgB,gBAAkB,EAAY,IAG3D,EAAa,sBAAqB,SAG5B,IAAI,QAAS,GAAY,WAAW,EAAS,KACrD,CAKA,OAAM,GACJ,OAAO,IAAI,QAAS,IAElB,MAAM,EAAA,KACJ,OAAO,oBAAoB,aAAc,GACzC,KAEF,OAAO,iBAAiB,aAAc,GAGtC,OAAO,QAGP,WAAA,KAEwB,oBAAX,QACT,OAAO,oBAAoB,aAAc,GAE3C,KACC,MAEP,CAMA,OAAM,CAAuB,GAC3B,MAAM,EAAO,KAAK,YACb,SAEC,EAAkB,EAAM,CAC5B,YAAa,EAAO,aAExB,CASA,EAAA,GACE,MAAM,EAAU,KAAK,QACrB,GAAK,EAAL,CAGA,MAAK,iBAAsB,IAAI,IAE/B,IAAK,MAAM,KAAO,EACX,EAAI,SAG8B,IAApB,EAAI,cAAyC,IAAhB,EAAI,UAAwC,IAApB,EAAI,eAG5E,MAAK,EAAoB,IAAI,EAAI,OAAQ,EAAI,QAE7C,KAAK,KAAK,iBAAiB,EAAI,OAAO,GAd1B,CAgBhB,CAKA,EAAA,GACE,GAAK,MAAK,EAAV,CAEA,IAAK,MAAO,EAAO,KAAe,MAAK,EAErC,KAAK,KAAK,iBAAiB,EAAO,GAGpC,MAAK,EAAsB,IAPI,CAQjC,CAKA,EAAA,GACE,MAAM,EAAO,KAAK,YAClB,IAAK,EAAM,OAGX,MAAK,IAGL,EAAK,UAAU,OAAO,iBAAkB,mBAGb,OAAvB,MAAK,IACP,EAAK,MAAM,UAAY,GACvB,EAAK,MAAM,gBAAkB,GAC7B,EAAK,MAAM,MAAQ,GACnB,MAAK,EAAgB,MAInB,MAAK,IACP,MAAK,EAAa,SAClB,MAAK,EAAe,MAElB,MAAK,IACP,MAAK,EAAa,SAClB,MAAK,EAAe,MAItB,MAAM,EAAe,MAAK,EACtB,MAAK,GAAwB,EAAa,kBAC5C,EAAa,gBAAgB,gBAAkB,MAAK,EAAqB,gBACzE,EAAa,sBAAqB,GAClC,MAAK,EAAuB,MAIN,OAApB,MAAK,IACP,KAAK,KAAK,KAAO,MAAK,EACtB,MAAK,EAAa,KAEtB,CAMA,WAAA,GAEM,KAAK,QAAQ,SAAW,MAAK,IAC/B,MAAK,IACL,MAAK,GAAqB,EAE9B,CAGA,IAAqB,EAKrB,EAAA,GAIE,MAHkB,EAGb,yBAAyB,CAC5B,GAAI,eACJ,MAAO,IACP,OAAS,IACP,MAAM,EAAS,SAAS,cAAc,UACtC,EAAO,UAAY,gCACnB,EAAO,MAAQ,KAAK,EAAE,oBAAqB,cAC3C,EAAO,KAAO,SAGd,KAAK,QAAQ,EAAQ,SAErB,EAAO,iBACL,QAAA,KAEE,KAAK,SAEP,CAAE,OAAQ,KAAK,mBAGjB,EAAU,YAAY,KAG5B"}
1
+ {"version":3,"file":"index.js","names":["styles","BaseGridPlugin","formatDiagnostic","code","message","gridId","pluginName","gridPrefix","toLowerCase","docsUrl","ISOLATION_STYLE_ID","async","printGridIsolated","gridElement","options","orientation","id","document","querySelectorAll","CSS","escape","length","console","warn","warnDiagnostic","getElementById","remove","isolationStyle","style","createElement","textContent","createIsolationStylesheet","head","appendChild","Promise","resolve","onAfterPrint","window","removeEventListener","addEventListener","print","setTimeout","DEFAULT_CONFIG","button","warnThreshold","maxRows","includeTitle","includeTimestamp","title","isolate","PrintPlugin","name","version","styles","printing","savedHiddenColumns","savedVirtualization","savedRows","printHeader","printFooter","appliedScale","internalGrid","this","grid","isPrinting","params","config","originalRowCount","rows","rowCount","limitApplied","limitInfo","toLocaleString","confirm","startTime","performance","now","emit","bypassThreshold","_virtualization","hidePrintColumns","sourceRows","slice","addPrintHeader","disableVirtualization","requestAnimationFrame","classList","add","printInIsolatedWindow","triggerPrint","success","duration","Math","round","error","cleanup","className","effectiveConfig","shell","header","titleEl","timestampEl","Date","insertBefore","firstChild","location","hostname","totalRows","refreshVirtualWindow","columns","Map","col","field","printHidden","utility","set","hidden","setColumnVisible","restorePrintColumns","wasVisible","transform","transformOrigin","width","afterRender","toolbarRegistered","registerToolbarButton","registerToolbarContent","order","render","container","t","type","setIcon","signal","disconnectSignal"],"sources":["../../../../../../libs/grid/src/lib/core/internal/diagnostics.ts","../../../../../../libs/grid/src/lib/plugins/print/print-isolated.ts","../../../../../../libs/grid/src/lib/plugins/print/print.css?inline","../../../../../../libs/grid/src/lib/plugins/print/print-plugin.ts"],"sourcesContent":["/**\n * Centralized diagnostic messages for @toolbox-web/grid.\n *\n * Every user-facing warning, error, or info message in the grid has a unique\n * diagnostic code (e.g. `TBW001`). Each code maps to a section on the online\n * troubleshooting page, giving developers a direct link to resolution steps.\n *\n * ## Usage\n *\n * ```ts\n * import { MISSING_BREAKPOINT, warnDiagnostic, throwDiagnostic } from './diagnostics';\n *\n * // Warn with a code\n * warnDiagnostic(MISSING_BREAKPOINT, 'Set a breakpoint...', gridId);\n *\n * // Throw with a code\n * throwDiagnostic(MISSING_ROW_ID, 'Configure getRowId...', gridId);\n * ```\n *\n * Plugins should prefer `this.warn(MISSING_BREAKPOINT, message)` via BaseGridPlugin\n * instead of importing this module directly.\n *\n * @internal\n */\n\n// #region Grid Prefix\n\n/**\n * Build the `[tbw-grid]` or `[tbw-grid#my-id]` log prefix.\n * Pass `pluginName` for a scoped prefix like `[tbw-grid:SelectionPlugin]`.\n */\nexport function gridPrefix(gridId?: string, pluginName?: string): string {\n const id = gridId ? `#${gridId}` : '';\n const plugin = pluginName ? `:${pluginName}` : '';\n return `[tbw-grid${id}${plugin}]`;\n}\n\n// #endregion\n\n// #region Diagnostic Codes\n\n/**\n * Diagnostic codes used across the grid library.\n *\n * Each code is an individual export so that unused codes are tree-shaken\n * from bundles that don't reference them (esbuild can't tree-shake\n * properties from a single object).\n *\n * Naming: TBW + 3-digit number.\n * Ranges:\n * 001–019 Configuration validation (missing plugins, bad config)\n * 020–029 Plugin lifecycle (dependencies, incompatibilities, alias collapse)\n * 030–039 Feature registry\n * 040–049 Row operations (row ID, row mutations)\n * 050–059 Column operations (width, template)\n * 060–069 Rendering (callbacks, formatters, external views)\n * 070–079 Shell (tool panels, header/toolbar content)\n * 080–089 Editing & editors\n * 090–099 Print\n * 100–109 Clipboard\n * 110–119 Plugin-specific (responsive, undo-redo, grouping-columns)\n * 120–129 Style injection\n * 130–139 Attribute parsing\n * 140–149 DataSource / ServerSide\n */\n\n// --- Config validation (001–019) ---\n/** Column uses a plugin-owned property but the plugin is not loaded. */\nexport const MISSING_PLUGIN = 'TBW001' as const;\n/** Grid config uses a plugin-owned property but the plugin is not loaded. */\nexport const MISSING_PLUGIN_CONFIG = 'TBW002' as const;\n/** Plugin config rule violation (error severity). */\nexport const CONFIG_RULE_ERROR = 'TBW003' as const;\n/** Plugin config rule violation (warning severity). */\nexport const CONFIG_RULE_WARN = 'TBW004' as const;\n\n// --- Plugin lifecycle (020–029) ---\n/** Required plugin dependency is missing. */\nexport const MISSING_DEPENDENCY = 'TBW020' as const;\n/** Optional plugin dependency is missing. */\nexport const OPTIONAL_DEPENDENCY = 'TBW021' as const;\n/** Two loaded plugins are incompatible. */\nexport const INCOMPATIBLE_PLUGINS = 'TBW022' as const;\n/** Two plugin instances resolve to the same canonical name (alias collapse). */\nexport const PLUGIN_ALIAS_COLLAPSE = 'TBW023' as const;\n/** Error thrown inside a plugin event handler. */\nexport const PLUGIN_EVENT_ERROR = 'TBW024' as const;\n/** Conflicting config values found while merging alias-collapsed plugin instances. */\nexport const PLUGIN_ALIAS_CONFIG_CONFLICT = 'TBW025' as const;\n\n// --- Feature registry (030–039) ---\n/** Feature was re-registered (overwritten). */\nexport const FEATURE_REREGISTERED = 'TBW030' as const;\n/** Feature configured but not imported. */\nexport const FEATURE_NOT_IMPORTED = 'TBW031' as const;\n/** Feature depends on another feature that is not enabled. */\nexport const FEATURE_MISSING_DEP = 'TBW032' as const;\n\n// --- Row operations (040–049) ---\n/** Cannot determine row ID (no getRowId and no id property). */\nexport const MISSING_ROW_ID = 'TBW040' as const;\n/** Row with given ID not found. */\nexport const ROW_NOT_FOUND = 'TBW041' as const;\n\n// --- Column operations (050–059) ---\n/** Column has an invalid CSS width value. */\nexport const INVALID_COLUMN_WIDTH = 'TBW050' as const;\n\n// --- Rendering callbacks (060–069) ---\n/** rowClass callback threw an error. */\nexport const ROW_CLASS_ERROR = 'TBW060' as const;\n/** cellClass callback threw an error. */\nexport const CELL_CLASS_ERROR = 'TBW061' as const;\n/** Column format function threw an error. */\nexport const FORMAT_ERROR = 'TBW062' as const;\n/** External view mount() threw an error. */\nexport const VIEW_MOUNT_ERROR = 'TBW063' as const;\n/** External view event dispatch error. */\nexport const VIEW_DISPATCH_ERROR = 'TBW064' as const;\n\n// --- Shell (070–079) ---\n/** Tool panel missing required id. */\nexport const TOOL_PANEL_MISSING_ATTR = 'TBW070' as const;\n/** No tool panels registered. */\nexport const NO_TOOL_PANELS = 'TBW071' as const;\n/** Tool panel section not found. */\nexport const TOOL_PANEL_NOT_FOUND = 'TBW072' as const;\n/** Tool panel already registered. */\nexport const TOOL_PANEL_DUPLICATE = 'TBW073' as const;\n/** Header content already registered. */\nexport const HEADER_CONTENT_DUPLICATE = 'TBW074' as const;\n/** Toolbar content already registered. */\nexport const TOOLBAR_CONTENT_DUPLICATE = 'TBW075' as const;\n\n// --- Editing & editors (080–089) ---\n/** External editor mount() threw an error. */\nexport const EDITOR_MOUNT_ERROR = 'TBW080' as const;\n\n// --- Print (090–099) ---\n/** Print already in progress. */\nexport const PRINT_IN_PROGRESS = 'TBW090' as const;\n/** Grid not available for printing. */\nexport const PRINT_NO_GRID = 'TBW091' as const;\n/** Print operation failed. */\nexport const PRINT_FAILED = 'TBW092' as const;\n/** Multiple elements share the same grid ID (print isolation issue). */\nexport const PRINT_DUPLICATE_ID = 'TBW093' as const;\n\n// --- Clipboard (100–109) ---\n/** Clipboard API write failed. */\nexport const CLIPBOARD_FAILED = 'TBW100' as const;\n\n// --- Plugin-specific (110–119) ---\n/** ResponsivePlugin: no breakpoint configured. */\nexport const MISSING_BREAKPOINT = 'TBW110' as const;\n/** UndoRedoPlugin: transaction already in progress. */\nexport const TRANSACTION_IN_PROGRESS = 'TBW111' as const;\n/** UndoRedoPlugin: no transaction in progress. */\nexport const NO_TRANSACTION = 'TBW112' as const;\n/** GroupingColumnsPlugin: missing id or header on column group definition. */\nexport const COLUMN_GROUP_NO_ID = 'TBW113' as const;\n/** GroupingColumnsPlugin: conflicting columnGroups sources. */\nexport const COLUMN_GROUPS_CONFLICT = 'TBW114' as const;\n\n// --- Style injection (120–129) ---\n/** Failed to extract grid.css from document stylesheets. */\nexport const STYLE_EXTRACT_FAILED = 'TBW120' as const;\n/** Could not find grid.css in document.styleSheets. */\nexport const STYLE_NOT_FOUND = 'TBW121' as const;\n\n// --- Attribute parsing (130–139) ---\n/** Invalid JSON in an HTML attribute. */\nexport const INVALID_ATTRIBUTE_JSON = 'TBW130' as const;\n\n// --- DataSource / ServerSide (140–149) ---\n/** ServerSidePlugin: getRows() rejected. */\nexport const DATASOURCE_FETCH_ERROR = 'TBW140' as const;\n/** ServerSidePlugin: getChildRows() rejected. */\nexport const DATASOURCE_CHILD_FETCH_ERROR = 'TBW141' as const;\n/** ServerSidePlugin: getChildRows() not implemented but a plugin queried for children. */\nexport const DATASOURCE_NO_CHILD_HANDLER = 'TBW142' as const;\n/** ServerSidePlugin: concurrent request limit reached, request deferred. */\nexport const DATASOURCE_THROTTLED = 'TBW143' as const;\n\nexport type DiagnosticCode =\n | typeof MISSING_PLUGIN\n | typeof MISSING_PLUGIN_CONFIG\n | typeof CONFIG_RULE_ERROR\n | typeof CONFIG_RULE_WARN\n | typeof MISSING_DEPENDENCY\n | typeof OPTIONAL_DEPENDENCY\n | typeof INCOMPATIBLE_PLUGINS\n | typeof PLUGIN_ALIAS_COLLAPSE\n | typeof PLUGIN_EVENT_ERROR\n | typeof PLUGIN_ALIAS_CONFIG_CONFLICT\n | typeof FEATURE_REREGISTERED\n | typeof FEATURE_NOT_IMPORTED\n | typeof FEATURE_MISSING_DEP\n | typeof MISSING_ROW_ID\n | typeof ROW_NOT_FOUND\n | typeof INVALID_COLUMN_WIDTH\n | typeof ROW_CLASS_ERROR\n | typeof CELL_CLASS_ERROR\n | typeof FORMAT_ERROR\n | typeof VIEW_MOUNT_ERROR\n | typeof VIEW_DISPATCH_ERROR\n | typeof TOOL_PANEL_MISSING_ATTR\n | typeof NO_TOOL_PANELS\n | typeof TOOL_PANEL_NOT_FOUND\n | typeof TOOL_PANEL_DUPLICATE\n | typeof HEADER_CONTENT_DUPLICATE\n | typeof TOOLBAR_CONTENT_DUPLICATE\n | typeof EDITOR_MOUNT_ERROR\n | typeof PRINT_IN_PROGRESS\n | typeof PRINT_NO_GRID\n | typeof PRINT_FAILED\n | typeof PRINT_DUPLICATE_ID\n | typeof CLIPBOARD_FAILED\n | typeof MISSING_BREAKPOINT\n | typeof TRANSACTION_IN_PROGRESS\n | typeof NO_TRANSACTION\n | typeof COLUMN_GROUP_NO_ID\n | typeof COLUMN_GROUPS_CONFLICT\n | typeof STYLE_EXTRACT_FAILED\n | typeof STYLE_NOT_FOUND\n | typeof INVALID_ATTRIBUTE_JSON\n | typeof DATASOURCE_FETCH_ERROR\n | typeof DATASOURCE_CHILD_FETCH_ERROR\n | typeof DATASOURCE_NO_CHILD_HANDLER\n | typeof DATASOURCE_THROTTLED;\n\n// #endregion\n\n// #region Docs URL\n\nconst DOCS_BASE = 'https://toolboxjs.com/grid/errors';\n\n/** Build a direct link to the troubleshooting section for a code. */\nfunction docsUrl(code: DiagnosticCode): string {\n return `${DOCS_BASE}#${code.toLowerCase()}`;\n}\n\n// #endregion\n\n// #region Formatting\n\n/**\n * Format a diagnostic message with prefix, code, and docs link.\n *\n * Output format:\n * ```\n * [tbw-grid#my-id] TBW001: Your message here.\n *\n * → More info: https://toolboxjs.com/grid/errors#tbw001\n * ```\n */\nexport function formatDiagnostic(code: DiagnosticCode, message: string, gridId?: string, pluginName?: string): string {\n const prefix = gridPrefix(gridId, pluginName);\n return `${prefix} ${code}: ${message}\\n\\n → More info: ${docsUrl(code)}`;\n}\n\n// #endregion\n\n// #region Public API\n\n/**\n * Throw an error with a diagnostic code and docs link.\n * Use for configuration errors and API misuse that should halt execution.\n */\nexport function throwDiagnostic(code: DiagnosticCode, message: string, gridId?: string, pluginName?: string): never {\n throw new Error(formatDiagnostic(code, message, gridId, pluginName));\n}\n\n/**\n * Log a warning with a diagnostic code and docs link.\n * Use for recoverable issues the developer should fix.\n */\nexport function warnDiagnostic(code: DiagnosticCode, message: string, gridId?: string, pluginName?: string): void {\n console.warn(formatDiagnostic(code, message, gridId, pluginName));\n}\n\n/**\n * Log a debug message with a diagnostic code and docs link.\n * Use for optional/soft dependency notifications — visible only when\n * the browser DevTools \"Verbose\" log level is enabled.\n */\nexport function debugDiagnostic(code: DiagnosticCode, message: string, gridId?: string, pluginName?: string): void {\n console.debug(formatDiagnostic(code, message, gridId, pluginName));\n}\n\n/**\n * Log an error with a diagnostic code and docs link.\n * Use for non-throwing errors (e.g., failed async operations).\n */\nexport function errorDiagnostic(code: DiagnosticCode, message: string, gridId?: string, pluginName?: string): void {\n console.error(formatDiagnostic(code, message, gridId, pluginName));\n}\n\n// #endregion\n","/**\n * Utility for printing a grid in isolation by hiding all other page content.\n *\n * This approach keeps the grid in place (with virtualization disabled by PrintPlugin)\n * and uses CSS to hide everything else on the page during printing.\n */\n\nimport { PRINT_DUPLICATE_ID, warnDiagnostic } from '../../core/internal/diagnostics';\nimport type { PrintOrientation } from './types';\n\n/** @since 1.4.0 */\nexport interface PrintIsolatedOptions {\n /** Page orientation hint */\n orientation?: PrintOrientation;\n}\n\n/** ID for the isolation stylesheet */\nconst ISOLATION_STYLE_ID = 'tbw-print-isolation-style';\n\n/**\n * Create a stylesheet that hides everything except the target grid.\n * Uses the grid's ID to target it specifically.\n */\nfunction createIsolationStylesheet(gridId: string, orientation: PrintOrientation): HTMLStyleElement {\n const style = document.createElement('style');\n style.id = ISOLATION_STYLE_ID;\n style.textContent = `\n /* Print isolation: hide everything except the target grid */\n @media print {\n /* Hide all body children by default */\n body > *:not(#${gridId}) {\n display: none !important;\n }\n\n /* But show the grid and ensure it's not hidden by ancestor rules */\n #${gridId} {\n display: block !important;\n position: static !important;\n visibility: visible !important;\n opacity: 1 !important;\n overflow: visible !important;\n height: auto !important;\n width: 100% !important;\n max-height: none !important;\n margin: 0 !important;\n padding: 0 !important;\n transform: none !important;\n }\n\n /* If grid is nested, we need to show its ancestors too */\n #${gridId},\n #${gridId} * {\n visibility: visible !important;\n }\n\n /* Walk up the DOM and show all ancestors of the grid */\n body *:has(> #${gridId}),\n body *:has(#${gridId}) {\n display: block !important;\n visibility: visible !important;\n opacity: 1 !important;\n overflow: visible !important;\n height: auto !important;\n position: static !important;\n transform: none !important;\n background: transparent !important;\n border: none !important;\n padding: 0 !important;\n margin: 0 !important;\n }\n\n /* Hide siblings of ancestors (everything that's not in the path to the grid) */\n body *:has(#${gridId}) > *:not(:has(#${gridId})):not(#${gridId}) {\n display: none !important;\n }\n\n /* Page settings */\n @page {\n size: ${orientation};\n margin: 1cm;\n }\n\n /* Ensure proper print styling */\n body {\n margin: 0 !important;\n padding: 0 !important;\n background: white !important;\n color-scheme: light !important;\n }\n }\n\n /* Screen: also apply isolation for print preview */\n @media screen {\n /* When this stylesheet is active, we're about to print */\n /* No screen-specific rules needed - isolation only applies to print */\n }\n `;\n return style;\n}\n\n/**\n * Print a grid in isolation by hiding all other page content.\n *\n * This function adds a temporary stylesheet that uses CSS to hide everything\n * on the page except the target grid during printing. The grid stays in place\n * with all its data (virtualization should be disabled separately).\n *\n * @param gridElement - The tbw-grid element to print (must have an ID)\n * @param options - Optional configuration\n * @returns Promise that resolves when the print dialog closes\n *\n * @example\n * ```typescript\n * import { queryGrid } from '@toolbox-web/grid';\n * import { printGridIsolated } from '@toolbox-web/grid/plugins/print';\n *\n * const grid = queryGrid('tbw-grid');\n * await printGridIsolated(grid, { orientation: 'landscape' });\n * ```\n * @since 1.4.0\n */\nexport async function printGridIsolated(gridElement: HTMLElement, options: PrintIsolatedOptions = {}): Promise<void> {\n const { orientation = 'landscape' } = options;\n\n const gridId = gridElement.id;\n\n // Warn if multiple elements share this ID (user-set IDs could collide)\n const elementsWithId = document.querySelectorAll(`#${CSS.escape(gridId)}`);\n if (elementsWithId.length > 1) {\n warnDiagnostic(\n PRINT_DUPLICATE_ID,\n `Multiple elements found with id=\"${gridId}\". ` +\n `Print isolation may not work correctly. Ensure each grid has a unique ID.`,\n gridId,\n 'print',\n );\n }\n\n // Remove any existing isolation stylesheet\n document.getElementById(ISOLATION_STYLE_ID)?.remove();\n\n // Add the isolation stylesheet\n const isolationStyle = createIsolationStylesheet(gridId, orientation);\n document.head.appendChild(isolationStyle);\n\n return new Promise((resolve) => {\n // Listen for afterprint event to cleanup\n const onAfterPrint = () => {\n window.removeEventListener('afterprint', onAfterPrint);\n // Remove isolation stylesheet\n document.getElementById(ISOLATION_STYLE_ID)?.remove();\n resolve();\n };\n window.addEventListener('afterprint', onAfterPrint);\n\n // Trigger print\n window.print();\n\n // Fallback timeout in case afterprint doesn't fire (some browsers)\n setTimeout(() => {\n window.removeEventListener('afterprint', onAfterPrint);\n document.getElementById(ISOLATION_STYLE_ID)?.remove();\n resolve();\n }, 5000);\n });\n}\n","/**\n * Print Plugin CSS\n *\n * Styles for print-optimized grid rendering.\n * Uses @media print for automatic print detection.\n */\n\n/* Print header/footer - hidden on screen, shown in print */\n.tbw-print-header,\n.tbw-print-footer {\n display: none;\n}\n\n/* ========================================\n @media print rules - all print styles\n ======================================== */\n\n@media print {\n tbw-grid {\n /* Force visible overflow to render all rows */\n overflow: visible !important;\n height: auto !important;\n\n /* Remove outer border - keep only cell borders */\n border: none !important;\n border-radius: 0 !important;\n\n /* Force light mode for printing */\n color-scheme: light only;\n\n /* Ensure colors print */\n -webkit-print-color-adjust: exact;\n print-color-adjust: exact;\n }\n\n tbw-grid .tbw-grid-content {\n overflow: visible !important;\n height: auto !important;\n max-height: none !important;\n }\n\n tbw-grid .tbw-scroll-area {\n overflow: visible !important;\n height: auto !important;\n max-height: none !important;\n }\n\n tbw-grid .rows-body {\n overflow: visible !important;\n height: auto !important;\n max-height: none !important;\n }\n\n /* Ensure virtualized rows container expands to show all rows */\n tbw-grid .rows-container,\n tbw-grid .rows-viewport,\n tbw-grid .rows {\n overflow: visible !important;\n height: auto !important;\n max-height: none !important;\n transform: none !important; /* Remove virtual scroll offset */\n }\n\n tbw-grid .rows-viewport .rows {\n position: static !important; /* Reset from absolute positioning */\n }\n\n /* Hide interactive elements, shell chrome, and header icons */\n tbw-grid .resize-handle,\n tbw-grid [part='sort-indicator'],\n tbw-grid .tbw-filter-btn,\n tbw-grid .tool-panel,\n tbw-grid .tool-panel-content,\n tbw-grid .tbw-shell-header,\n tbw-grid .shell-toolbar,\n tbw-grid .tool-panel-toggle,\n tbw-grid [data-print-hide],\n tbw-grid .expander-cell,\n tbw-grid .tree-toggle,\n tbw-grid .context-menu,\n tbw-grid .faux-vscroll {\n display: none !important;\n }\n\n /* Print header with title and timestamp */\n tbw-grid .tbw-print-header {\n display: flex;\n justify-content: space-between;\n align-items: baseline;\n padding: var(--tbw-spacing-md, 0.5em) 0;\n margin-bottom: var(--tbw-spacing-md, 0.5em);\n border-bottom: 2px solid var(--tbw-print-border, var(--tbw-color-border-strong));\n font-family: inherit;\n }\n\n .tbw-print-header-title {\n font-size: 1.25em;\n font-weight: bold;\n }\n\n .tbw-print-header-timestamp {\n font-size: var(--tbw-font-size-sm, 0.875em);\n color: var(--tbw-print-muted, var(--tbw-color-fg-muted));\n }\n\n /* Print footer */\n tbw-grid .tbw-print-footer {\n display: block;\n margin-top: var(--tbw-spacing-md, 0.5em);\n padding-top: var(--tbw-spacing-md, 0.5em);\n border-top: 1px solid var(--tbw-print-border, var(--tbw-color-border));\n font-size: var(--tbw-font-size-xs, 0.75em);\n color: var(--tbw-print-muted, var(--tbw-color-fg-muted));\n text-align: end;\n }\n\n /* Row styling */\n tbw-grid .data-grid-row {\n break-inside: avoid;\n page-break-inside: avoid;\n }\n\n /* Cell styling - use theme variables with print-safe fallbacks */\n tbw-grid .cell {\n border: 1px solid var(--tbw-print-cell-border, var(--tbw-color-border)) !important;\n }\n\n /* Ensure the last column's end border is visible */\n tbw-grid .header-row,\n tbw-grid .data-grid-row {\n padding-inline-end: 1px; /* Prevent end border from being clipped */\n }\n\n /* Remove hover effects */\n tbw-grid .data-grid-row:hover,\n tbw-grid .cell:hover {\n background: inherit !important;\n }\n\n /* Page setup */\n @page {\n margin: 1cm;\n }\n}\n","/**\n * Print Plugin (Class-based)\n *\n * Provides print layout functionality for tbw-grid.\n * Temporarily disables virtualization to render all rows and uses\n * @media print CSS for print-optimized styling.\n */\n\nimport { PRINT_FAILED, PRINT_IN_PROGRESS, PRINT_NO_GRID, errorDiagnostic } from '../../core/internal/diagnostics';\nimport { BaseGridPlugin, type GridElement } from '../../core/plugin/base-plugin';\nimport type { ToolbarContentDefinition } from '../shell/types';\nimport { printGridIsolated } from './print-isolated';\nimport styles from './print.css?inline';\nimport type { PrintCompleteDetail, PrintConfig, PrintParams, PrintStartDetail } from './types';\n\n/**\n * Extended grid interface for PrintPlugin internal access.\n * Includes registerToolbarContent which is available on the grid class\n * but not exposed in the standard plugin API.\n */\ninterface PrintGridRef extends GridElement {\n registerToolbarContent?(content: ToolbarContentDefinition): void;\n unregisterToolbarContent?(contentId: string): void;\n}\n\n/** Default configuration */\nconst DEFAULT_CONFIG: Required<PrintConfig> = {\n button: false,\n orientation: 'landscape',\n warnThreshold: 500,\n maxRows: 0,\n includeTitle: true,\n includeTimestamp: true,\n title: '',\n isolate: false,\n};\n\n/**\n * Print Plugin for tbw-grid\n *\n * Enables printing the full grid content by temporarily disabling virtualization\n * and applying print-optimized styles. Handles large datasets gracefully with\n * configurable row limits.\n *\n * ## Installation\n *\n * ```ts\n * import { PrintPlugin } from '@toolbox-web/grid/plugins/print';\n * ```\n *\n * ## Events\n *\n * | Event | Detail | Description |\n * |-------|--------|-------------|\n * | `print-start` | {@link PrintStartDetail} | Fired when print begins |\n * | `print-complete` | {@link PrintCompleteDetail} | Fired when print completes |\n *\n * @example Basic Print\n * ```ts\n * import { queryGrid } from '@toolbox-web/grid';\n * import { PrintPlugin } from '@toolbox-web/grid/plugins/print';\n *\n * const grid = queryGrid('tbw-grid');\n * grid.gridConfig = {\n * plugins: [new PrintPlugin()],\n * };\n *\n * // Trigger print\n * const printPlugin = grid.getPluginByName('print');\n * await printPlugin.print();\n * ```\n *\n * @example With Toolbar Button\n * ```ts\n * grid.gridConfig = {\n * plugins: [new PrintPlugin({ button: true, orientation: 'landscape' })],\n * };\n * ```\n *\n * @see {@link PrintConfig} for all configuration options\n * @since 1.4.0\n */\nexport class PrintPlugin extends BaseGridPlugin<PrintConfig> {\n /** @internal */\n readonly name = 'print';\n\n /** @internal */\n override readonly version = '1.0.0';\n\n /** CSS styles for print mode */\n override readonly styles = styles;\n\n /** Current print state */\n #printing = false;\n\n /** Saved column visibility state */\n #savedHiddenColumns: Map<string, boolean> | null = null;\n\n /** Saved virtualization state */\n #savedVirtualization: { bypassThreshold: number } | null = null;\n\n /** Saved rows when maxRows limit is applied */\n #savedRows: unknown[] | null = null;\n\n /** Print header element */\n #printHeader: HTMLElement | null = null;\n\n /** Print footer element */\n #printFooter: HTMLElement | null = null;\n\n /** Applied scale factor (legacy, used for cleanup) */\n #appliedScale: number | null = null;\n\n /**\n * Get the grid typed as PrintGridRef for internal access.\n */\n get #internalGrid(): PrintGridRef {\n return this.grid;\n }\n\n /**\n * Check if print is currently in progress\n */\n isPrinting(): boolean {\n return this.#printing;\n }\n\n /**\n * Trigger the browser print dialog\n *\n * This method:\n * 1. Validates row count against maxRows limit\n * 2. Disables virtualization to render all rows\n * 3. Applies print-specific CSS classes\n * 4. Opens the browser print dialog (or isolated window if `isolate: true`)\n * 5. Restores normal state after printing\n *\n * @param params - Optional parameters to override config for this print\n * @param params.isolate - If true, prints in an isolated window containing only the grid\n * @returns Promise that resolves when print dialog closes\n */\n async print(params?: PrintParams): Promise<void> {\n if (this.#printing) {\n this.warn(PRINT_IN_PROGRESS, 'Print already in progress');\n return;\n }\n\n const grid = this.gridElement;\n if (!grid) {\n this.warn(PRINT_NO_GRID, 'Grid not available');\n return;\n }\n\n const config = { ...DEFAULT_CONFIG, ...this.config, ...params };\n const rows = this.rows;\n const originalRowCount = rows.length;\n let rowCount = originalRowCount;\n let limitApplied = false;\n\n // Check if we should warn about large datasets\n if (config.warnThreshold > 0 && originalRowCount > config.warnThreshold) {\n const limitInfo =\n config.maxRows > 0 ? `\\n\\nNote: Output will be limited to ${config.maxRows.toLocaleString()} rows.` : '';\n const proceed = confirm(\n `This grid has ${originalRowCount.toLocaleString()} rows. ` +\n `Printing large datasets may cause performance issues or browser slowdowns.${limitInfo}\\n\\n` +\n `Click OK to continue, or Cancel to abort.`,\n );\n if (!proceed) {\n return;\n }\n }\n\n // Apply hard row limit if configured\n if (config.maxRows > 0 && originalRowCount > config.maxRows) {\n rowCount = config.maxRows;\n limitApplied = true;\n }\n\n this.#printing = true;\n\n // Track timing for duration reporting\n const startTime = performance.now();\n\n // Emit print-start event\n this.emit<PrintStartDetail>('print-start', {\n rowCount,\n limitApplied,\n originalRowCount,\n });\n\n try {\n // Save current virtualization state\n const internalGrid = this.#internalGrid;\n this.#savedVirtualization = {\n bypassThreshold: internalGrid._virtualization?.bypassThreshold ?? 24,\n };\n\n // Hide columns marked with printHidden\n this.#hidePrintColumns();\n\n // Apply row limit if configured\n if (limitApplied) {\n this.#savedRows = this.sourceRows;\n // Set limited rows on the grid\n this.grid.rows = this.sourceRows.slice(0, rowCount);\n // Wait for grid to process new rows\n await new Promise((resolve) => setTimeout(resolve, 50));\n }\n\n // Add print header if configured\n if (config.includeTitle || config.includeTimestamp) {\n this.#addPrintHeader(config);\n }\n\n // Disable virtualization to render all rows\n // This forces the grid to render all rows in the DOM\n await this.#disableVirtualization();\n\n // Wait for next frame to ensure DOM is updated\n await new Promise((resolve) => requestAnimationFrame(resolve));\n await new Promise((resolve) => requestAnimationFrame(resolve));\n\n // Add orientation class for @page rules\n grid.classList.add(`print-${config.orientation}`);\n\n // Wait for next frame to ensure DOM is updated\n await new Promise((resolve) => requestAnimationFrame(resolve));\n await new Promise((resolve) => requestAnimationFrame(resolve));\n\n // Trigger browser print dialog (isolated or inline)\n if (config.isolate) {\n await this.#printInIsolatedWindow(config);\n } else {\n await this.#triggerPrint();\n }\n\n // Emit print-complete event\n this.emit<PrintCompleteDetail>('print-complete', {\n success: true,\n rowCount,\n duration: Math.round(performance.now() - startTime),\n });\n } catch (error) {\n errorDiagnostic(PRINT_FAILED, `Print failed: ${error}`, this.gridElement?.id, this.name);\n this.emit<PrintCompleteDetail>('print-complete', {\n success: false,\n rowCount: 0,\n duration: Math.round(performance.now() - startTime),\n });\n } finally {\n // Restore normal state\n this.#cleanup();\n this.#printing = false;\n }\n }\n\n /**\n * Add print header with title and timestamp\n */\n #addPrintHeader(config: Required<PrintConfig>): void {\n const grid = this.gridElement;\n if (!grid) return;\n\n // Create print header\n this.#printHeader = document.createElement('div');\n this.#printHeader.className = 'tbw-print-header';\n\n // Title\n if (config.includeTitle) {\n const title = config.title || this.grid.effectiveConfig?.shell?.header?.title || 'Grid Data';\n const titleEl = document.createElement('div');\n titleEl.className = 'tbw-print-header-title';\n titleEl.textContent = title;\n this.#printHeader.appendChild(titleEl);\n }\n\n // Timestamp\n if (config.includeTimestamp) {\n const timestampEl = document.createElement('div');\n timestampEl.className = 'tbw-print-header-timestamp';\n timestampEl.textContent = `Printed: ${new Date().toLocaleString()}`;\n this.#printHeader.appendChild(timestampEl);\n }\n\n // Insert at the beginning of the grid\n grid.insertBefore(this.#printHeader, grid.firstChild);\n\n // Create print footer\n this.#printFooter = document.createElement('div');\n this.#printFooter.className = 'tbw-print-footer';\n this.#printFooter.textContent = `Page generated from ${window.location.hostname}`;\n grid.appendChild(this.#printFooter);\n }\n\n /**\n * Disable virtualization to render all rows\n */\n async #disableVirtualization(): Promise<void> {\n const internalGrid = this.#internalGrid;\n if (!internalGrid._virtualization) return;\n\n // Set bypass threshold higher than total row count to disable virtualization\n // This makes the grid render all rows (up to maxRows) instead of just visible ones\n const totalRows = this.rows.length;\n internalGrid._virtualization.bypassThreshold = totalRows + 100;\n\n // Force a full refresh to re-render with virtualization disabled\n internalGrid.refreshVirtualWindow(true);\n\n // Wait for render to complete\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n\n /**\n * Trigger the browser print dialog\n */\n async #triggerPrint(): Promise<void> {\n return new Promise((resolve) => {\n // Listen for afterprint event\n const onAfterPrint = () => {\n window.removeEventListener('afterprint', onAfterPrint);\n resolve();\n };\n window.addEventListener('afterprint', onAfterPrint);\n\n // Trigger print\n window.print();\n\n // Fallback timeout in case afterprint doesn't fire (some browsers)\n setTimeout(() => {\n // Guard against test environment teardown where window may be undefined\n if (typeof window !== 'undefined') {\n window.removeEventListener('afterprint', onAfterPrint);\n }\n resolve();\n }, 1000);\n });\n }\n\n /**\n * Print in isolation by hiding all other page content.\n * This excludes navigation, sidebars, etc. while keeping the grid in place.\n */\n async #printInIsolatedWindow(config: Required<PrintConfig>): Promise<void> {\n const grid = this.gridElement;\n if (!grid) return;\n\n await printGridIsolated(grid, {\n orientation: config.orientation,\n });\n }\n\n /**\n * Hide columns marked with printHidden: true OR utility: true.\n *\n * Utility (system) columns — selection checkbox, expander, drag handle, custom\n * action menus, etc. — are excluded from print by default. Set `printHidden: false`\n * explicitly on a utility column if you need it to appear in the printout.\n */\n #hidePrintColumns(): void {\n const columns = this.columns;\n if (!columns) return;\n\n // Save current hidden state and hide print columns\n this.#savedHiddenColumns = new Map();\n\n for (const col of columns) {\n if (!col.field) continue;\n // Default: hide if printHidden === true OR utility === true.\n // Allow explicit opt-in for utility columns via `printHidden: false`.\n const shouldHide = col.printHidden === true || (col.utility === true && col.printHidden !== false);\n if (!shouldHide) continue;\n // Save current visibility state (true = visible, false = hidden)\n this.#savedHiddenColumns.set(col.field, !col.hidden);\n // Hide the column for printing\n this.grid.setColumnVisible(col.field, false);\n }\n }\n\n /**\n * Restore columns that were hidden for printing\n */\n #restorePrintColumns(): void {\n if (!this.#savedHiddenColumns) return;\n\n for (const [field, wasVisible] of this.#savedHiddenColumns) {\n // Restore original visibility\n this.grid.setColumnVisible(field, wasVisible);\n }\n\n this.#savedHiddenColumns = null;\n }\n\n /**\n * Cleanup after printing\n */\n #cleanup(): void {\n const grid = this.gridElement;\n if (!grid) return;\n\n // Restore columns that were hidden for printing\n this.#restorePrintColumns();\n\n // Remove orientation classes (both original and possibly switched)\n grid.classList.remove('print-portrait', 'print-landscape');\n\n // Remove scaling transform if applied (legacy)\n if (this.#appliedScale !== null) {\n grid.style.transform = '';\n grid.style.transformOrigin = '';\n grid.style.width = '';\n this.#appliedScale = null;\n }\n\n // Remove print header/footer\n if (this.#printHeader) {\n this.#printHeader.remove();\n this.#printHeader = null;\n }\n if (this.#printFooter) {\n this.#printFooter.remove();\n this.#printFooter = null;\n }\n\n // Restore virtualization\n const internalGrid = this.#internalGrid;\n if (this.#savedVirtualization && internalGrid._virtualization) {\n internalGrid._virtualization.bypassThreshold = this.#savedVirtualization.bypassThreshold;\n internalGrid.refreshVirtualWindow(true);\n this.#savedVirtualization = null;\n }\n\n // Restore original rows if they were limited\n if (this.#savedRows !== null) {\n this.grid.rows = this.#savedRows;\n this.#savedRows = null;\n }\n }\n\n /**\n * Register toolbar button if configured\n * @internal\n */\n override afterRender(): void {\n // Register toolbar on first render when button is enabled\n if (this.config?.button && !this.#toolbarRegistered) {\n this.#registerToolbarButton();\n this.#toolbarRegistered = true;\n }\n }\n\n /** Track if toolbar button is registered */\n #toolbarRegistered = false;\n\n /**\n * Register print button in toolbar\n */\n #registerToolbarButton(): void {\n const grid = this.#internalGrid;\n\n // Register toolbar content\n grid.registerToolbarContent?.({\n id: 'print-button',\n order: 900, // High order to appear at the end\n render: (container: HTMLElement) => {\n const button = document.createElement('button');\n button.className = 'tbw-toolbar-btn tbw-print-btn';\n button.title = this.t('print.buttonTitle', 'Print grid');\n button.type = 'button';\n\n // Use print icon\n this.setIcon(button, 'print');\n\n button.addEventListener(\n 'click',\n () => {\n this.print();\n },\n { signal: this.disconnectSignal },\n );\n\n container.appendChild(button);\n },\n });\n }\n}\n"],"mappings":"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"}