@toolbox-web/grid-angular 1.4.0 → 1.5.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.
@@ -82,6 +82,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
82
82
  // `adapter.createDetailRenderer(grid)` and `adapter.parseDetailElement(el)`
83
83
  // delegate to. Without this import, both methods return undefined.
84
84
  registerDetailRendererBridge((gridElement, adapter) => {
85
+ // Type inferred from `getDetailTemplate` (same package instance as `adapter`),
86
+ // not from a local `import type { TemplateRef } from '@angular/core'` — the
87
+ // latter resolves through Bun's `.bun/` cache during ng-packagr build and
88
+ // produces a brand-incompatible TemplateRef vs the built adapter `.d.ts`.
85
89
  const template = getDetailTemplate(gridElement);
86
90
  if (!template)
87
91
  return undefined;
@@ -103,18 +107,20 @@ registerTemplateBridge(({ grid }) => {
103
107
  const detailElement = grid.querySelector('tbw-grid-detail');
104
108
  if (!detailElement)
105
109
  return;
106
- // The plugin must already have been added to the grid (via [masterDetail] input
107
- // or manual gridConfig.plugins). Find it by name to avoid importing the class.
110
+ // The plugin must already have been attached (via [masterDetail] input,
111
+ // gridConfig.features.masterDetail, or gridConfig.plugins). Use the runtime
112
+ // lookup so we don't miss plugins instantiated from `gridConfig.features`,
113
+ // which never appear in `gridConfig.plugins`.
108
114
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
109
- const existingPlugin = grid.gridConfig?.plugins?.find((p) => p.name === 'masterDetail');
115
+ const existingPlugin = grid.getPluginByName?.('masterDetail');
110
116
  if (!existingPlugin) {
111
117
  // eslint-disable-next-line no-console
112
118
  console.warn('[tbw-grid-angular] <tbw-grid-detail> found but MasterDetailPlugin is not configured.\n' +
113
- 'Add the [masterDetail] input or include MasterDetailPlugin in gridConfig.plugins:\n\n' +
119
+ 'Add the [masterDetail] input, set gridConfig.features.masterDetail, or include\n' +
120
+ 'MasterDetailPlugin in gridConfig.plugins:\n\n' +
114
121
  ' <tbw-grid [masterDetail]="{ showExpandColumn: true }">...</tbw-grid>\n\n' +
115
122
  'or:\n\n' +
116
- ' import { MasterDetailPlugin } from "@toolbox-web/grid/plugins/master-detail";\n' +
117
- ' gridConfig = { plugins: [new MasterDetailPlugin({ ... })] };');
123
+ ' gridConfig = { features: { masterDetail: { showExpandColumn: true } } };');
118
124
  return;
119
125
  }
120
126
  existingPlugin.refreshDetailRenderer?.();
@@ -1 +1 @@
1
- {"version":3,"file":"toolbox-web-grid-angular-features-master-detail.mjs","sources":["../../../../libs/grid-angular/features/master-detail/src/grid-master-detail.directive.ts","../../../../libs/grid-angular/features/master-detail/src/index.ts","../../../../libs/grid-angular/features/master-detail/src/toolbox-web-grid-angular-features-master-detail.ts"],"sourcesContent":["/**\n * `GridMasterDetailDirective` — owns `[masterDetail]` and `(detailExpand)`\n * on `<tbw-grid>`. See `GridFilteringDirective` for the full rationale.\n *\n * Note: this directive is independent of the higher-level\n * `<tbw-grid-detail>` template element + `GridDetailView` wrapper, which\n * uses a different bridging mechanism (template registration). Apps using\n * the template form do not need this directive.\n *\n * @category Directive\n */\nimport { Directive, ElementRef, inject, input, OnDestroy, OnInit, output } from '@angular/core';\nimport type { DataGridElement } from '@toolbox-web/grid';\nimport { claimEvent, registerFeatureClaim, unclaimEvent, unregisterFeatureClaim } from '@toolbox-web/grid-angular';\nimport type { DetailExpandDetail, MasterDetailConfig } from '@toolbox-web/grid/plugins/master-detail';\n\n/**\n * Owns the binding(s) `[masterDetail], [detailExpand]` on `<tbw-grid>` for the matching feature plugin. See {@link GridFilteringDirective} for the full rationale.\n *\n * @category Directive\n */\n@Directive({\n selector: 'tbw-grid[masterDetail], tbw-grid[detailExpand]',\n standalone: true,\n})\nexport class GridMasterDetailDirective implements OnInit, OnDestroy {\n private readonly elementRef = inject(ElementRef<DataGridElement>);\n\n readonly masterDetail = input<MasterDetailConfig>();\n readonly detailExpand = output<DetailExpandDetail>();\n\n private listener?: (e: Event) => void;\n\n constructor() {\n const grid = this.elementRef.nativeElement;\n registerFeatureClaim(grid, 'masterDetail', () => this.masterDetail());\n claimEvent(grid, 'detail-expand');\n }\n\n ngOnInit(): void {\n const grid = this.elementRef.nativeElement;\n this.listener = (e: Event): void => this.detailExpand.emit((e as CustomEvent<DetailExpandDetail>).detail);\n grid.addEventListener('detail-expand', this.listener);\n }\n\n ngOnDestroy(): void {\n const grid = this.elementRef.nativeElement;\n if (this.listener) {\n grid.removeEventListener('detail-expand', this.listener);\n this.listener = undefined;\n }\n unregisterFeatureClaim(grid, 'masterDetail');\n unclaimEvent(grid, 'detail-expand');\n }\n}\n","/**\n * Master-detail feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `[masterDetail]` input on the `Grid`\n * directive AND to wire `<tbw-grid-detail>` Angular templates into the\n * MasterDetailPlugin's `detailRenderer`.\n *\n * @example\n * ```typescript\n * // In your bootstrap (e.g. main.ts or app.component.ts):\n * import '@toolbox-web/grid-angular/features/master-detail';\n * ```\n *\n * ```html\n * <tbw-grid [masterDetail]=\"{ showExpandColumn: true }\">\n * <tbw-grid-detail>\n * <ng-template let-row>...</ng-template>\n * </tbw-grid-detail>\n * </tbw-grid>\n * ```\n *\n * @packageDocumentation\n */\n\nimport type { TemplateRef } from '@angular/core';\nimport {\n getDetailTemplate,\n registerDetailRendererBridge,\n registerTemplateBridge,\n type GridAdapter,\n type GridDetailContext,\n} from '@toolbox-web/grid-angular';\nimport '@toolbox-web/grid/features/master-detail';\nexport { GridMasterDetailDirective } from './grid-master-detail.directive';\nexport type { _Augmentation as _MasterDetailAugmentation } from '@toolbox-web/grid/features/master-detail';\n\n// ---------------------------------------------------------------------------\n// Re-exports from `@toolbox-web/grid-angular` (main entry).\n//\n// `GridDetailView` (and its `getDetailTemplate` helper / `GridDetailContext`\n// type) still physically live in the main entry today but are master-detail\n// specific. They are re-exported here so consumers can import them from the\n// feature entry that owns the runtime behaviour. The same symbols are\n// `@deprecated` on the main entry; in v2.0.0 the source will physically move\n// into this secondary entry and the deprecated re-exports on the main entry\n// will be removed.\n// ---------------------------------------------------------------------------\nexport { getDetailTemplate, GridDetailView } from '@toolbox-web/grid-angular';\nexport type { GridDetailContext } from '@toolbox-web/grid-angular';\n\n/**\n * Subset of `MasterDetailPlugin` we touch from the bridge. Avoids importing\n * the plugin class itself (would defeat tree-shaking and re-introduce the\n * coupling we just removed from the core directive).\n */\ninterface MasterDetailPluginLike {\n refreshDetailRenderer?: () => void;\n}\n\n// Install the row renderer bridge on the adapter. This is what\n// `adapter.createDetailRenderer(grid)` and `adapter.parseDetailElement(el)`\n// delegate to. Without this import, both methods return undefined.\nregisterDetailRendererBridge(<TRow = unknown>(gridElement: HTMLElement, adapter: GridAdapter) => {\n const template = getDetailTemplate(gridElement) as TemplateRef<GridDetailContext<TRow>> | undefined;\n if (!template) return undefined;\n\n return (row: TRow) => {\n const context: GridDetailContext<TRow> = { $implicit: row, row };\n const viewRef = adapter.createTrackedEmbeddedView(template, context);\n const container = document.createElement('div');\n viewRef.rootNodes.forEach((node: Node) => container.appendChild(node));\n return container;\n };\n});\n\n// Wire <tbw-grid-detail> Angular templates into the MasterDetailPlugin once\n// content templates are registered. The plugin's `parseLightDomDetail()`\n// already calls back into the adapter via `grid.__frameworkAdapter.parseDetailElement`\n// (which the `Grid` directive set in `ngOnInit`), so all we need to do here\n// is trigger a refresh once Angular's content templates are available.\nregisterTemplateBridge(({ grid }) => {\n // Only act when the user actually placed a <tbw-grid-detail> in light DOM.\n const detailElement = grid.querySelector('tbw-grid-detail');\n if (!detailElement) return;\n\n // The plugin must already have been added to the grid (via [masterDetail] input\n // or manual gridConfig.plugins). Find it by name to avoid importing the class.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const existingPlugin = (grid as any).gridConfig?.plugins?.find(\n (p: { name?: string }) => p.name === 'masterDetail',\n ) as MasterDetailPluginLike | undefined;\n\n if (!existingPlugin) {\n // eslint-disable-next-line no-console\n console.warn(\n '[tbw-grid-angular] <tbw-grid-detail> found but MasterDetailPlugin is not configured.\\n' +\n 'Add the [masterDetail] input or include MasterDetailPlugin in gridConfig.plugins:\\n\\n' +\n ' <tbw-grid [masterDetail]=\"{ showExpandColumn: true }\">...</tbw-grid>\\n\\n' +\n 'or:\\n\\n' +\n ' import { MasterDetailPlugin } from \"@toolbox-web/grid/plugins/master-detail\";\\n' +\n ' gridConfig = { plugins: [new MasterDetailPlugin({ ... })] };',\n );\n return;\n }\n\n existingPlugin.refreshDetailRenderer?.();\n});\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"toolbox-web-grid-angular-features-master-detail.mjs","sources":["../../../../libs/grid-angular/features/master-detail/src/grid-master-detail.directive.ts","../../../../libs/grid-angular/features/master-detail/src/index.ts","../../../../libs/grid-angular/features/master-detail/src/toolbox-web-grid-angular-features-master-detail.ts"],"sourcesContent":["/**\n * `GridMasterDetailDirective` — owns `[masterDetail]` and `(detailExpand)`\n * on `<tbw-grid>`. See `GridFilteringDirective` for the full rationale.\n *\n * Note: this directive is independent of the higher-level\n * `<tbw-grid-detail>` template element + `GridDetailView` wrapper, which\n * uses a different bridging mechanism (template registration). Apps using\n * the template form do not need this directive.\n *\n * @category Directive\n */\nimport { Directive, ElementRef, inject, input, OnDestroy, OnInit, output } from '@angular/core';\nimport type { DataGridElement } from '@toolbox-web/grid';\nimport { claimEvent, registerFeatureClaim, unclaimEvent, unregisterFeatureClaim } from '@toolbox-web/grid-angular';\nimport type { DetailExpandDetail, MasterDetailConfig } from '@toolbox-web/grid/plugins/master-detail';\n\n/**\n * Owns the binding(s) `[masterDetail], [detailExpand]` on `<tbw-grid>` for the matching feature plugin. See {@link GridFilteringDirective} for the full rationale.\n *\n * @category Directive\n */\n@Directive({\n selector: 'tbw-grid[masterDetail], tbw-grid[detailExpand]',\n standalone: true,\n})\nexport class GridMasterDetailDirective implements OnInit, OnDestroy {\n private readonly elementRef = inject(ElementRef<DataGridElement>);\n\n readonly masterDetail = input<MasterDetailConfig>();\n readonly detailExpand = output<DetailExpandDetail>();\n\n private listener?: (e: Event) => void;\n\n constructor() {\n const grid = this.elementRef.nativeElement;\n registerFeatureClaim(grid, 'masterDetail', () => this.masterDetail());\n claimEvent(grid, 'detail-expand');\n }\n\n ngOnInit(): void {\n const grid = this.elementRef.nativeElement;\n this.listener = (e: Event): void => this.detailExpand.emit((e as CustomEvent<DetailExpandDetail>).detail);\n grid.addEventListener('detail-expand', this.listener);\n }\n\n ngOnDestroy(): void {\n const grid = this.elementRef.nativeElement;\n if (this.listener) {\n grid.removeEventListener('detail-expand', this.listener);\n this.listener = undefined;\n }\n unregisterFeatureClaim(grid, 'masterDetail');\n unclaimEvent(grid, 'detail-expand');\n }\n}\n","/**\n * Master-detail feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `[masterDetail]` input on the `Grid`\n * directive AND to wire `<tbw-grid-detail>` Angular templates into the\n * MasterDetailPlugin's `detailRenderer`.\n *\n * @example\n * ```typescript\n * // In your bootstrap (e.g. main.ts or app.component.ts):\n * import '@toolbox-web/grid-angular/features/master-detail';\n * ```\n *\n * ```html\n * <tbw-grid [masterDetail]=\"{ showExpandColumn: true }\">\n * <tbw-grid-detail>\n * <ng-template let-row>...</ng-template>\n * </tbw-grid-detail>\n * </tbw-grid>\n * ```\n *\n * @packageDocumentation\n */\n\nimport {\n getDetailTemplate,\n registerDetailRendererBridge,\n registerTemplateBridge,\n type GridAdapter,\n type GridDetailContext,\n} from '@toolbox-web/grid-angular';\nimport '@toolbox-web/grid/features/master-detail';\nexport { GridMasterDetailDirective } from './grid-master-detail.directive';\nexport type { _Augmentation as _MasterDetailAugmentation } from '@toolbox-web/grid/features/master-detail';\n\n// ---------------------------------------------------------------------------\n// Re-exports from `@toolbox-web/grid-angular` (main entry).\n//\n// `GridDetailView` (and its `getDetailTemplate` helper / `GridDetailContext`\n// type) still physically live in the main entry today but are master-detail\n// specific. They are re-exported here so consumers can import them from the\n// feature entry that owns the runtime behaviour. The same symbols are\n// `@deprecated` on the main entry; in v2.0.0 the source will physically move\n// into this secondary entry and the deprecated re-exports on the main entry\n// will be removed.\n// ---------------------------------------------------------------------------\nexport { getDetailTemplate, GridDetailView } from '@toolbox-web/grid-angular';\nexport type { GridDetailContext } from '@toolbox-web/grid-angular';\n\n/**\n * Subset of `MasterDetailPlugin` we touch from the bridge. Avoids importing\n * the plugin class itself (would defeat tree-shaking and re-introduce the\n * coupling we just removed from the core directive).\n */\ninterface MasterDetailPluginLike {\n refreshDetailRenderer?: () => void;\n}\n\n// Install the row renderer bridge on the adapter. This is what\n// `adapter.createDetailRenderer(grid)` and `adapter.parseDetailElement(el)`\n// delegate to. Without this import, both methods return undefined.\nregisterDetailRendererBridge(<TRow = unknown>(gridElement: HTMLElement, adapter: GridAdapter) => {\n // Type inferred from `getDetailTemplate` (same package instance as `adapter`),\n // not from a local `import type { TemplateRef } from '@angular/core'` — the\n // latter resolves through Bun's `.bun/` cache during ng-packagr build and\n // produces a brand-incompatible TemplateRef vs the built adapter `.d.ts`.\n const template = getDetailTemplate(gridElement);\n if (!template) return undefined;\n\n return (row: TRow) => {\n const context: GridDetailContext<TRow> = { $implicit: row, row };\n const viewRef = adapter.createTrackedEmbeddedView(template, context);\n const container = document.createElement('div');\n viewRef.rootNodes.forEach((node: Node) => container.appendChild(node));\n return container;\n };\n});\n\n// Wire <tbw-grid-detail> Angular templates into the MasterDetailPlugin once\n// content templates are registered. The plugin's `parseLightDomDetail()`\n// already calls back into the adapter via `grid.__frameworkAdapter.parseDetailElement`\n// (which the `Grid` directive set in `ngOnInit`), so all we need to do here\n// is trigger a refresh once Angular's content templates are available.\nregisterTemplateBridge(({ grid }) => {\n // Only act when the user actually placed a <tbw-grid-detail> in light DOM.\n const detailElement = grid.querySelector('tbw-grid-detail');\n if (!detailElement) return;\n\n // The plugin must already have been attached (via [masterDetail] input,\n // gridConfig.features.masterDetail, or gridConfig.plugins). Use the runtime\n // lookup so we don't miss plugins instantiated from `gridConfig.features`,\n // which never appear in `gridConfig.plugins`.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const existingPlugin = (grid as any).getPluginByName?.('masterDetail') as MasterDetailPluginLike | undefined;\n\n if (!existingPlugin) {\n // eslint-disable-next-line no-console\n console.warn(\n '[tbw-grid-angular] <tbw-grid-detail> found but MasterDetailPlugin is not configured.\\n' +\n 'Add the [masterDetail] input, set gridConfig.features.masterDetail, or include\\n' +\n 'MasterDetailPlugin in gridConfig.plugins:\\n\\n' +\n ' <tbw-grid [masterDetail]=\"{ showExpandColumn: true }\">...</tbw-grid>\\n\\n' +\n 'or:\\n\\n' +\n ' gridConfig = { features: { masterDetail: { showExpandColumn: true } } };',\n );\n return;\n }\n\n existingPlugin.refreshDetailRenderer?.();\n});\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -77,6 +77,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
77
77
  // `adapter.parseResponsiveCardElement(el)` delegate to. Without this import,
78
78
  // both methods return undefined.
79
79
  registerResponsiveCardRendererBridge((gridElement, adapter) => {
80
+ // Type inferred from `getResponsiveCardTemplate` (same package instance as
81
+ // `adapter`), not from a local `import type { TemplateRef } from '@angular/core'`
82
+ // — the latter resolves through Bun's `.bun/` cache during ng-packagr build
83
+ // and produces a brand-incompatible TemplateRef vs the built adapter `.d.ts`.
80
84
  const template = getResponsiveCardTemplate(gridElement);
81
85
  if (!template)
82
86
  return undefined;
@@ -100,17 +104,20 @@ registerTemplateBridge(({ grid, adapter }) => {
100
104
  const cardRenderer = adapter.createResponsiveCardRenderer(grid);
101
105
  if (!cardRenderer)
102
106
  return;
103
- // Find the plugin by name to avoid importing the class.
107
+ // The plugin must already have been attached (via [responsive] input,
108
+ // gridConfig.features.responsive, or gridConfig.plugins). Use the runtime
109
+ // lookup so we don't miss plugins instantiated from `gridConfig.features`,
110
+ // which never appear in `gridConfig.plugins`.
104
111
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
105
- const existingPlugin = grid.gridConfig?.plugins?.find((p) => p.name === 'responsive');
112
+ const existingPlugin = grid.getPluginByName?.('responsive');
106
113
  if (!existingPlugin) {
107
114
  // eslint-disable-next-line no-console
108
115
  console.warn('[tbw-grid-angular] <tbw-grid-responsive-card> found but ResponsivePlugin is not configured.\n' +
109
- 'Add the [responsive] input or include ResponsivePlugin in gridConfig.plugins:\n\n' +
116
+ 'Add the [responsive] input, set gridConfig.features.responsive, or include\n' +
117
+ 'ResponsivePlugin in gridConfig.plugins:\n\n' +
110
118
  ' <tbw-grid [responsive]="{ breakpoint: 600 }">...</tbw-grid>\n\n' +
111
119
  'or:\n\n' +
112
- ' import { ResponsivePlugin } from "@toolbox-web/grid/plugins/responsive";\n' +
113
- ' gridConfig = { plugins: [new ResponsivePlugin({ breakpoint: 600 })] };');
120
+ ' gridConfig = { features: { responsive: { breakpoint: 600 } } };');
114
121
  return;
115
122
  }
116
123
  existingPlugin.setCardRenderer?.(cardRenderer);
@@ -1 +1 @@
1
- {"version":3,"file":"toolbox-web-grid-angular-features-responsive.mjs","sources":["../../../../libs/grid-angular/features/responsive/src/grid-responsive.directive.ts","../../../../libs/grid-angular/features/responsive/src/index.ts","../../../../libs/grid-angular/features/responsive/src/toolbox-web-grid-angular-features-responsive.ts"],"sourcesContent":["/**\n * `GridResponsiveDirective` — owns `[responsive]` and `(responsiveChange)`\n * on `<tbw-grid>`. See `GridFilteringDirective` for the full rationale.\n *\n * @category Directive\n */\nimport { Directive, ElementRef, inject, input, OnDestroy, OnInit, output } from '@angular/core';\nimport type { DataGridElement } from '@toolbox-web/grid';\nimport { claimEvent, registerFeatureClaim, unclaimEvent, unregisterFeatureClaim } from '@toolbox-web/grid-angular';\nimport type { ResponsiveChangeDetail, ResponsivePluginConfig } from '@toolbox-web/grid/plugins/responsive';\n\n/**\n * Owns the binding(s) `[responsive], [responsiveChange]` on `<tbw-grid>` for the matching feature plugin. See {@link GridFilteringDirective} for the full rationale.\n *\n * @category Directive\n */\n@Directive({\n selector: 'tbw-grid[responsive], tbw-grid[responsiveChange]',\n standalone: true,\n})\nexport class GridResponsiveDirective implements OnInit, OnDestroy {\n private readonly elementRef = inject(ElementRef<DataGridElement>);\n\n readonly responsive = input<boolean | ResponsivePluginConfig>();\n readonly responsiveChange = output<ResponsiveChangeDetail>();\n\n private listener?: (e: Event) => void;\n\n constructor() {\n const grid = this.elementRef.nativeElement;\n registerFeatureClaim(grid, 'responsive', () => this.responsive());\n claimEvent(grid, 'responsive-change');\n }\n\n ngOnInit(): void {\n const grid = this.elementRef.nativeElement;\n this.listener = (e: Event): void => this.responsiveChange.emit((e as CustomEvent<ResponsiveChangeDetail>).detail);\n grid.addEventListener('responsive-change', this.listener);\n }\n\n ngOnDestroy(): void {\n const grid = this.elementRef.nativeElement;\n if (this.listener) {\n grid.removeEventListener('responsive-change', this.listener);\n this.listener = undefined;\n }\n unregisterFeatureClaim(grid, 'responsive');\n unclaimEvent(grid, 'responsive-change');\n }\n}\n","/**\n * Responsive feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `[responsive]` input on the `Grid`\n * directive AND to wire `<tbw-grid-responsive-card>` Angular templates into\n * the ResponsivePlugin's `cardRenderer`.\n *\n * @example\n * ```typescript\n * // In your bootstrap (e.g. main.ts or app.component.ts):\n * import '@toolbox-web/grid-angular/features/responsive';\n * ```\n *\n * ```html\n * <tbw-grid [responsive]=\"{ breakpoint: 768 }\">\n * <tbw-grid-responsive-card>\n * <ng-template let-row>...</ng-template>\n * </tbw-grid-responsive-card>\n * </tbw-grid>\n * ```\n *\n * @packageDocumentation\n */\n\nimport type { TemplateRef } from '@angular/core';\nimport {\n getResponsiveCardTemplate,\n registerResponsiveCardRendererBridge,\n registerTemplateBridge,\n type GridAdapter,\n type GridResponsiveCardContext,\n} from '@toolbox-web/grid-angular';\nimport '@toolbox-web/grid/features/responsive';\nexport { GridResponsiveDirective } from './grid-responsive.directive';\nexport type { _Augmentation as _ResponsiveAugmentation } from '@toolbox-web/grid/features/responsive';\n\n/**\n * Subset of `ResponsivePlugin` we touch from the bridge. Avoids importing\n * the plugin class itself.\n */\ninterface ResponsivePluginLike {\n setCardRenderer?: (renderer: (row: unknown, rowIndex: number) => HTMLElement) => void;\n}\n\n// Install the row renderer bridge on the adapter. This is what\n// `adapter.createResponsiveCardRenderer(grid)` and\n// `adapter.parseResponsiveCardElement(el)` delegate to. Without this import,\n// both methods return undefined.\nregisterResponsiveCardRendererBridge(<TRow = unknown>(gridElement: HTMLElement, adapter: GridAdapter) => {\n const template = getResponsiveCardTemplate(gridElement) as TemplateRef<GridResponsiveCardContext<TRow>> | undefined;\n if (!template) return undefined;\n\n return (row: TRow, rowIndex: number) => {\n const context: GridResponsiveCardContext<TRow> = { $implicit: row, row, index: rowIndex };\n const viewRef = adapter.createTrackedEmbeddedView(template, context);\n const container = document.createElement('div');\n viewRef.rootNodes.forEach((node: Node) => container.appendChild(node));\n return container;\n };\n});\n\n// Wire <tbw-grid-responsive-card> Angular templates into the ResponsivePlugin\n// once content templates are registered. Runs from `Grid.ngAfterContentInit`\n// via the template-bridge registry.\nregisterTemplateBridge(({ grid, adapter }) => {\n // Only act when the user actually placed a <tbw-grid-responsive-card> in light DOM.\n const cardElement = grid.querySelector('tbw-grid-responsive-card');\n if (!cardElement) return;\n\n // Build a card renderer from the Angular template.\n const cardRenderer = adapter.createResponsiveCardRenderer(grid);\n if (!cardRenderer) return;\n\n // Find the plugin by name to avoid importing the class.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const existingPlugin = (grid as any).gridConfig?.plugins?.find((p: { name?: string }) => p.name === 'responsive') as\n | ResponsivePluginLike\n | undefined;\n\n if (!existingPlugin) {\n // eslint-disable-next-line no-console\n console.warn(\n '[tbw-grid-angular] <tbw-grid-responsive-card> found but ResponsivePlugin is not configured.\\n' +\n 'Add the [responsive] input or include ResponsivePlugin in gridConfig.plugins:\\n\\n' +\n ' <tbw-grid [responsive]=\"{ breakpoint: 600 }\">...</tbw-grid>\\n\\n' +\n 'or:\\n\\n' +\n ' import { ResponsivePlugin } from \"@toolbox-web/grid/plugins/responsive\";\\n' +\n ' gridConfig = { plugins: [new ResponsivePlugin({ breakpoint: 600 })] };',\n );\n return;\n }\n\n existingPlugin.setCardRenderer?.(cardRenderer as (row: unknown, rowIndex: number) => HTMLElement);\n});\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"toolbox-web-grid-angular-features-responsive.mjs","sources":["../../../../libs/grid-angular/features/responsive/src/grid-responsive.directive.ts","../../../../libs/grid-angular/features/responsive/src/index.ts","../../../../libs/grid-angular/features/responsive/src/toolbox-web-grid-angular-features-responsive.ts"],"sourcesContent":["/**\n * `GridResponsiveDirective` — owns `[responsive]` and `(responsiveChange)`\n * on `<tbw-grid>`. See `GridFilteringDirective` for the full rationale.\n *\n * @category Directive\n */\nimport { Directive, ElementRef, inject, input, OnDestroy, OnInit, output } from '@angular/core';\nimport type { DataGridElement } from '@toolbox-web/grid';\nimport { claimEvent, registerFeatureClaim, unclaimEvent, unregisterFeatureClaim } from '@toolbox-web/grid-angular';\nimport type { ResponsiveChangeDetail, ResponsivePluginConfig } from '@toolbox-web/grid/plugins/responsive';\n\n/**\n * Owns the binding(s) `[responsive], [responsiveChange]` on `<tbw-grid>` for the matching feature plugin. See {@link GridFilteringDirective} for the full rationale.\n *\n * @category Directive\n */\n@Directive({\n selector: 'tbw-grid[responsive], tbw-grid[responsiveChange]',\n standalone: true,\n})\nexport class GridResponsiveDirective implements OnInit, OnDestroy {\n private readonly elementRef = inject(ElementRef<DataGridElement>);\n\n readonly responsive = input<boolean | ResponsivePluginConfig>();\n readonly responsiveChange = output<ResponsiveChangeDetail>();\n\n private listener?: (e: Event) => void;\n\n constructor() {\n const grid = this.elementRef.nativeElement;\n registerFeatureClaim(grid, 'responsive', () => this.responsive());\n claimEvent(grid, 'responsive-change');\n }\n\n ngOnInit(): void {\n const grid = this.elementRef.nativeElement;\n this.listener = (e: Event): void => this.responsiveChange.emit((e as CustomEvent<ResponsiveChangeDetail>).detail);\n grid.addEventListener('responsive-change', this.listener);\n }\n\n ngOnDestroy(): void {\n const grid = this.elementRef.nativeElement;\n if (this.listener) {\n grid.removeEventListener('responsive-change', this.listener);\n this.listener = undefined;\n }\n unregisterFeatureClaim(grid, 'responsive');\n unclaimEvent(grid, 'responsive-change');\n }\n}\n","/**\n * Responsive feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `[responsive]` input on the `Grid`\n * directive AND to wire `<tbw-grid-responsive-card>` Angular templates into\n * the ResponsivePlugin's `cardRenderer`.\n *\n * @example\n * ```typescript\n * // In your bootstrap (e.g. main.ts or app.component.ts):\n * import '@toolbox-web/grid-angular/features/responsive';\n * ```\n *\n * ```html\n * <tbw-grid [responsive]=\"{ breakpoint: 768 }\">\n * <tbw-grid-responsive-card>\n * <ng-template let-row>...</ng-template>\n * </tbw-grid-responsive-card>\n * </tbw-grid>\n * ```\n *\n * @packageDocumentation\n */\n\nimport {\n getResponsiveCardTemplate,\n registerResponsiveCardRendererBridge,\n registerTemplateBridge,\n type GridAdapter,\n type GridResponsiveCardContext,\n} from '@toolbox-web/grid-angular';\nimport '@toolbox-web/grid/features/responsive';\nexport { GridResponsiveDirective } from './grid-responsive.directive';\nexport type { _Augmentation as _ResponsiveAugmentation } from '@toolbox-web/grid/features/responsive';\n\n/**\n * Subset of `ResponsivePlugin` we touch from the bridge. Avoids importing\n * the plugin class itself.\n */\ninterface ResponsivePluginLike {\n setCardRenderer?: (renderer: (row: unknown, rowIndex: number) => HTMLElement) => void;\n}\n\n// Install the row renderer bridge on the adapter. This is what\n// `adapter.createResponsiveCardRenderer(grid)` and\n// `adapter.parseResponsiveCardElement(el)` delegate to. Without this import,\n// both methods return undefined.\nregisterResponsiveCardRendererBridge(<TRow = unknown>(gridElement: HTMLElement, adapter: GridAdapter) => {\n // Type inferred from `getResponsiveCardTemplate` (same package instance as\n // `adapter`), not from a local `import type { TemplateRef } from '@angular/core'`\n // — the latter resolves through Bun's `.bun/` cache during ng-packagr build\n // and produces a brand-incompatible TemplateRef vs the built adapter `.d.ts`.\n const template = getResponsiveCardTemplate(gridElement);\n if (!template) return undefined;\n\n return (row: TRow, rowIndex: number) => {\n const context: GridResponsiveCardContext<TRow> = { $implicit: row, row, index: rowIndex };\n const viewRef = adapter.createTrackedEmbeddedView(template, context);\n const container = document.createElement('div');\n viewRef.rootNodes.forEach((node: Node) => container.appendChild(node));\n return container;\n };\n});\n\n// Wire <tbw-grid-responsive-card> Angular templates into the ResponsivePlugin\n// once content templates are registered. Runs from `Grid.ngAfterContentInit`\n// via the template-bridge registry.\nregisterTemplateBridge(({ grid, adapter }) => {\n // Only act when the user actually placed a <tbw-grid-responsive-card> in light DOM.\n const cardElement = grid.querySelector('tbw-grid-responsive-card');\n if (!cardElement) return;\n\n // Build a card renderer from the Angular template.\n const cardRenderer = adapter.createResponsiveCardRenderer(grid);\n if (!cardRenderer) return;\n\n // The plugin must already have been attached (via [responsive] input,\n // gridConfig.features.responsive, or gridConfig.plugins). Use the runtime\n // lookup so we don't miss plugins instantiated from `gridConfig.features`,\n // which never appear in `gridConfig.plugins`.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const existingPlugin = (grid as any).getPluginByName?.('responsive') as ResponsivePluginLike | undefined;\n\n if (!existingPlugin) {\n // eslint-disable-next-line no-console\n console.warn(\n '[tbw-grid-angular] <tbw-grid-responsive-card> found but ResponsivePlugin is not configured.\\n' +\n 'Add the [responsive] input, set gridConfig.features.responsive, or include\\n' +\n 'ResponsivePlugin in gridConfig.plugins:\\n\\n' +\n ' <tbw-grid [responsive]=\"{ breakpoint: 600 }\">...</tbw-grid>\\n\\n' +\n 'or:\\n\\n' +\n ' gridConfig = { features: { responsive: { breakpoint: 600 } } };',\n );\n return;\n }\n\n existingPlugin.setCardRenderer?.(cardRenderer as (row: unknown, rowIndex: number) => HTMLElement);\n});\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -18,6 +18,7 @@ import { DataGridElement } from '@toolbox-web/grid';
18
18
  *
19
19
  * Also checks if it's an ES6 class (vs function) by inspecting the
20
20
  * string representation.
21
+ * @since 0.3.0
21
22
  */
22
23
  function isComponentClass(value) {
23
24
  if (typeof value !== 'function' || value.prototype === undefined) {
@@ -92,6 +93,7 @@ function getEditorTemplate(element) {
92
93
  * re-exports from the main `@toolbox-web/grid-angular` entry will be removed
93
94
  * at the same time. Consumers should already be importing from the feature
94
95
  * entry.
96
+ * @since 0.1.0
95
97
  */
96
98
  class GridColumnEditor {
97
99
  elementRef = inject((ElementRef));
@@ -166,6 +168,7 @@ function getViewTemplate(element) {
166
168
  * ```
167
169
  *
168
170
  * @category Directive
171
+ * @since 0.1.0
169
172
  */
170
173
  class GridColumnView {
171
174
  elementRef = inject((ElementRef));
@@ -201,6 +204,7 @@ const FORM_ARRAY_CONTEXT$1 = Symbol('formArrayContext');
201
204
  /**
202
205
  * Gets the FormArrayContext from a grid element, if present.
203
206
  * @internal
207
+ * @since 0.5.0
204
208
  */
205
209
  function getFormArrayContext(gridElement) {
206
210
  return gridElement[FORM_ARRAY_CONTEXT$1];
@@ -271,6 +275,7 @@ function getFormArrayContext(gridElement) {
271
275
  * re-exports from the main `@toolbox-web/grid-angular` entry will be removed
272
276
  * at the same time. Consumers should already be importing from the feature
273
277
  * entry.
278
+ * @since 0.5.0
274
279
  */
275
280
  class GridFormArray {
276
281
  destroyRef = inject(DestroyRef);
@@ -760,6 +765,7 @@ function getToolPanelElements(gridElement) {
760
765
  * ```
761
766
  *
762
767
  * @category Directive
768
+ * @since 0.1.0
763
769
  */
764
770
  class GridToolPanel {
765
771
  elementRef = inject((ElementRef));
@@ -896,6 +902,7 @@ function getStructuralEditorTemplate(columnElement) {
896
902
  * ```
897
903
  *
898
904
  * @category Directive
905
+ * @since 0.1.1
899
906
  */
900
907
  class TbwRenderer {
901
908
  template = inject((TemplateRef));
@@ -999,6 +1006,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
999
1006
  * will be removed at the same time. Consumers should already be importing
1000
1007
  * from the feature entry. (`TbwRenderer` stays in the main entry — it is
1001
1008
  * editor-agnostic.)
1009
+ * @since 0.1.1
1002
1010
  */
1003
1011
  class TbwEditor {
1004
1012
  template = inject((TemplateRef));
@@ -1060,6 +1068,7 @@ const editorMountHooks = [];
1060
1068
  * (e.g. `features/editing`) on import.
1061
1069
  *
1062
1070
  * @internal Plugin API
1071
+ * @since 1.4.0
1063
1072
  */
1064
1073
  function registerEditorMountHook(hook) {
1065
1074
  editorMountHooks.push(hook);
@@ -1090,6 +1099,7 @@ function notifyEditorMounted(container, gridEl) {
1090
1099
  * `(blur)` flush their pending value before the cell DOM is torn down by Tab /
1091
1100
  * programmatic row exit.
1092
1101
  * @internal
1102
+ * @since 1.4.0
1093
1103
  */
1094
1104
  function makeFlushFocusedInput(host) {
1095
1105
  return () => {
@@ -1194,6 +1204,7 @@ function wireEditorCallbacks(hostElement, instance, commit, cancel) {
1194
1204
  */
1195
1205
  /**
1196
1206
  * Injection token for providing type defaults at app level.
1207
+ * @since 0.3.0
1197
1208
  */
1198
1209
  const GRID_TYPE_DEFAULTS = new InjectionToken('GRID_TYPE_DEFAULTS');
1199
1210
  /**
@@ -1231,6 +1242,7 @@ const GRID_TYPE_DEFAULTS = new InjectionToken('GRID_TYPE_DEFAULTS');
1231
1242
  * }
1232
1243
  * }
1233
1244
  * ```
1245
+ * @since 0.3.0
1234
1246
  */
1235
1247
  class GridTypeRegistry {
1236
1248
  defaults = new Map();
@@ -1320,6 +1332,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
1320
1332
  * ]
1321
1333
  * };
1322
1334
  * ```
1335
+ * @since 0.3.0
1323
1336
  */
1324
1337
  function provideGridTypeDefaults(defaults) {
1325
1338
  return makeEnvironmentProviders([{ provide: GRID_TYPE_DEFAULTS, useValue: defaults }]);
@@ -1348,6 +1361,7 @@ let filterPanelTypeDefaultBridge = null;
1348
1361
  * Install the master-detail row-renderer bridge. Called once on import by
1349
1362
  * `@toolbox-web/grid-angular/features/master-detail`.
1350
1363
  * @internal Plugin API
1364
+ * @since 1.4.0
1351
1365
  */
1352
1366
  function registerDetailRendererBridge(bridge) {
1353
1367
  detailRendererBridge = bridge;
@@ -1356,6 +1370,7 @@ function registerDetailRendererBridge(bridge) {
1356
1370
  * Install the responsive-card row-renderer bridge. Called once on import by
1357
1371
  * `@toolbox-web/grid-angular/features/responsive`.
1358
1372
  * @internal Plugin API
1373
+ * @since 1.4.0
1359
1374
  */
1360
1375
  function registerResponsiveCardRendererBridge(bridge) {
1361
1376
  responsiveCardRendererBridge = bridge;
@@ -1366,6 +1381,7 @@ function registerResponsiveCardRendererBridge(bridge) {
1366
1381
  * type-default and grid-config-level component-class filterPanelRenderers are
1367
1382
  * silently dropped — same precondition as the FilteringPlugin (TBW031).
1368
1383
  * @internal Plugin API
1384
+ * @since 1.4.0
1369
1385
  */
1370
1386
  function registerFilterPanelTypeDefaultBridge(bridge) {
1371
1387
  filterPanelTypeDefaultBridge = bridge;
@@ -1415,6 +1431,7 @@ const templateBridges = [];
1415
1431
  * by the JS loader.
1416
1432
  *
1417
1433
  * @internal
1434
+ * @since 1.4.0
1418
1435
  */
1419
1436
  function registerTemplateBridge(bridge) {
1420
1437
  templateBridges.push(bridge);
@@ -1425,6 +1442,7 @@ function registerTemplateBridge(bridge) {
1425
1442
  * errors thrown by one bridge do not stop the others.
1426
1443
  *
1427
1444
  * @internal
1445
+ * @since 1.4.0
1428
1446
  */
1429
1447
  function runTemplateBridges(ctx) {
1430
1448
  for (const bridge of templateBridges) {
@@ -1450,6 +1468,7 @@ const featureConfigPreprocessors = new Map();
1450
1468
  * a no-op).
1451
1469
  *
1452
1470
  * @internal
1471
+ * @since 1.4.0
1453
1472
  */
1454
1473
  function registerFeatureConfigPreprocessor(name, fn) {
1455
1474
  featureConfigPreprocessors.set(name, fn);
@@ -1458,6 +1477,7 @@ function registerFeatureConfigPreprocessor(name, fn) {
1458
1477
  * Look up the preprocessor for a feature, if any.
1459
1478
  *
1460
1479
  * @internal
1480
+ * @since 1.4.0
1461
1481
  */
1462
1482
  function getFeatureConfigPreprocessor(name) {
1463
1483
  return featureConfigPreprocessors.get(name);
@@ -1577,6 +1597,7 @@ function syncRootNodes(viewRef, container) {
1577
1597
  container.replaceChildren(...rootNodes);
1578
1598
  }
1579
1599
  }
1600
+ /** @since 0.11.0 */
1580
1601
  class GridAdapter {
1581
1602
  injector;
1582
1603
  appRef;
@@ -1664,6 +1685,12 @@ class GridAdapter {
1664
1685
  if (angularConfig.loadingRenderer && isComponentClass(angularConfig.loadingRenderer)) {
1665
1686
  result.loadingRenderer = this.createComponentLoadingRenderer(angularConfig.loadingRenderer);
1666
1687
  }
1688
+ // Process emptyRenderer - convert Angular component class to function.
1689
+ // `null` is a valid opt-out value (suppresses the built-in default message);
1690
+ // non-component values (vanilla functions, null) are forwarded unchanged.
1691
+ if (angularConfig.emptyRenderer && isComponentClass(angularConfig.emptyRenderer)) {
1692
+ result.emptyRenderer = this.createComponentEmptyRenderer(angularConfig.emptyRenderer);
1693
+ }
1667
1694
  return result;
1668
1695
  }
1669
1696
  /**
@@ -2168,6 +2195,19 @@ class GridAdapter {
2168
2195
  const mount = this.mountComponentRenderer(componentClass, (ctx) => ({ size: ctx.size }));
2169
2196
  return (ctx) => mount(ctx).hostElement;
2170
2197
  }
2198
+ /**
2199
+ * Creates an empty-state renderer function from an Angular component class.
2200
+ *
2201
+ * The component receives `sourceRowCount` and `filteredOut` inputs.
2202
+ * @internal
2203
+ */
2204
+ createComponentEmptyRenderer(componentClass) {
2205
+ const mount = this.mountComponentRenderer(componentClass, (ctx) => ({
2206
+ sourceRowCount: ctx.sourceRowCount,
2207
+ filteredOut: ctx.filteredOut,
2208
+ }));
2209
+ return (ctx) => mount(ctx).hostElement;
2210
+ }
2171
2211
  /**
2172
2212
  * Create an embedded view from a `TemplateRef` and append-track it on the
2173
2213
  * adapter's view-ref pool so it is cleaned up on `destroy()` / `unmount()`.
@@ -2337,6 +2377,7 @@ class GridAdapter {
2337
2377
  */
2338
2378
  /**
2339
2379
  * Injection token for providing icon overrides at app level.
2380
+ * @since 0.8.0
2340
2381
  */
2341
2382
  const GRID_ICONS = new InjectionToken('GRID_ICONS');
2342
2383
  /**
@@ -2369,6 +2410,7 @@ const GRID_ICONS = new InjectionToken('GRID_ICONS');
2369
2410
  * }
2370
2411
  * }
2371
2412
  * ```
2413
+ * @since 0.8.0
2372
2414
  */
2373
2415
  class GridIconRegistry {
2374
2416
  icons = new Map();
@@ -2467,6 +2509,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
2467
2509
  * ]
2468
2510
  * };
2469
2511
  * ```
2512
+ * @since 0.8.0
2470
2513
  */
2471
2514
  function provideGridIcons(icons) {
2472
2515
  return makeEnvironmentProviders([{ provide: GRID_ICONS, useValue: icons }]);
@@ -2511,6 +2554,7 @@ function provideGridIcons(icons) {
2511
2554
  * Defaults to `'tbw-grid'` (first grid in the component). Use when the
2512
2555
  * component contains multiple grids, e.g. `'tbw-grid.primary'` or `'#my-grid'`.
2513
2556
  * @returns Object with grid access methods and state signals
2557
+ * @since 0.6.0
2514
2558
  */
2515
2559
  function injectGrid(selector = 'tbw-grid') {
2516
2560
  const elementRef = inject(ElementRef);
@@ -2675,6 +2719,7 @@ function injectGrid(selector = 'tbw-grid') {
2675
2719
  * `@toolbox-web/grid-angular/features/filtering` in v2.0.0; the deprecated
2676
2720
  * re-export from the main `@toolbox-web/grid-angular` entry will be removed at
2677
2721
  * the same time. Consumers should already be importing from the feature entry.
2722
+ * @since 0.13.0
2678
2723
  */
2679
2724
  class BaseFilterPanel {
2680
2725
  /**
@@ -2783,6 +2828,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
2783
2828
  * `@toolbox-web/grid-angular/features/editing` in v2.0.0; the deprecated
2784
2829
  * re-export from the main `@toolbox-web/grid-angular` entry will be removed at
2785
2830
  * the same time. Consumers should already be importing from the feature entry.
2831
+ * @since 0.5.0
2786
2832
  */
2787
2833
  class BaseGridEditor {
2788
2834
  elementRef = inject(ElementRef);
@@ -3090,6 +3136,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
3090
3136
  * `@toolbox-web/grid-angular/features/editing` in v2.0.0; the deprecated
3091
3137
  * re-export from the main `@toolbox-web/grid-angular` entry will be removed at
3092
3138
  * the same time. Consumers should already be importing from the feature entry.
3139
+ * @since 0.13.0
3093
3140
  */
3094
3141
  class BaseGridEditorCVA extends BaseGridEditor {
3095
3142
  // ============================================================================
@@ -3359,6 +3406,7 @@ let anchorCounter = 0;
3359
3406
  * the deprecated re-export from the main `@toolbox-web/grid-angular` entry
3360
3407
  * will be removed at the same time. Consumers should already be importing
3361
3408
  * from the feature entry.
3409
+ * @since 0.13.0
3362
3410
  */
3363
3411
  class BaseOverlayEditor extends BaseGridEditor {
3364
3412
  _elementRef = inject(ElementRef);
@@ -3825,6 +3873,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
3825
3873
  * ```
3826
3874
  *
3827
3875
  * @category Directive
3876
+ * @since 0.13.0
3828
3877
  */
3829
3878
  class TbwGridColumn {
3830
3879
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: TbwGridColumn, deps: [], target: i0.ɵɵFactoryTarget.Directive });
@@ -3842,6 +3891,7 @@ const detailTemplateRegistry = new Map();
3842
3891
  /**
3843
3892
  * Gets the detail template registered for a given grid element.
3844
3893
  * Used by AngularGridAdapter to retrieve templates at render time.
3894
+ * @since 0.1.0
3845
3895
  */
3846
3896
  function getDetailTemplate(gridElement) {
3847
3897
  // Look for tbw-grid-detail child and get its template
@@ -3899,6 +3949,7 @@ function getDetailTemplate(gridElement) {
3899
3949
  * ```
3900
3950
  *
3901
3951
  * @category Directive
3952
+ * @since 0.1.0
3902
3953
  */
3903
3954
  class GridDetailView {
3904
3955
  elementRef = inject((ElementRef));
@@ -3959,6 +4010,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
3959
4010
  * ```
3960
4011
  *
3961
4012
  * @category Directive
4013
+ * @since 0.13.0
3962
4014
  */
3963
4015
  class TbwGridHeader {
3964
4016
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: TbwGridHeader, deps: [], target: i0.ɵɵFactoryTarget.Directive });
@@ -3976,6 +4028,7 @@ const FORM_ARRAY_CONTEXT = Symbol('formArrayContext');
3976
4028
  /**
3977
4029
  * Gets the FormArrayContext from a grid element, if present.
3978
4030
  * @internal
4031
+ * @since 0.11.0
3979
4032
  */
3980
4033
  function getLazyFormContext(gridElement) {
3981
4034
  return gridElement[FORM_ARRAY_CONTEXT];
@@ -4062,6 +4115,7 @@ function getLazyFormContext(gridElement) {
4062
4115
  * re-exports from the main `@toolbox-web/grid-angular` entry will be removed
4063
4116
  * at the same time. Consumers should already be importing from the feature
4064
4117
  * entry.
4118
+ * @since 0.11.0
4065
4119
  */
4066
4120
  class GridLazyForm {
4067
4121
  elementRef = inject((ElementRef));
@@ -4467,6 +4521,7 @@ const responsiveCardTemplateRegistry = new Map();
4467
4521
  *
4468
4522
  * @param gridElement - The grid element to look up
4469
4523
  * @returns The template reference or undefined if not found
4524
+ * @since 0.4.0
4470
4525
  */
4471
4526
  function getResponsiveCardTemplate(gridElement) {
4472
4527
  // Find the tbw-grid-responsive-card element inside the grid
@@ -4507,6 +4562,7 @@ function getResponsiveCardTemplate(gridElement) {
4507
4562
  *
4508
4563
  * @see ResponsivePlugin
4509
4564
  * @category Directive
4565
+ * @since 0.4.0
4510
4566
  */
4511
4567
  class GridResponsiveCard {
4512
4568
  elementRef = inject((ElementRef));
@@ -4588,6 +4644,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
4588
4644
  * ```
4589
4645
  *
4590
4646
  * @category Directive
4647
+ * @since 0.13.0
4591
4648
  */
4592
4649
  class TbwGridToolButtons {
4593
4650
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: TbwGridToolButtons, deps: [], target: i0.ɵɵFactoryTarget.Directive });
@@ -4636,6 +4693,7 @@ const VALID_TYPES = new Set(['string', 'number', 'boolean', 'date', 'datetime',
4636
4693
  *
4637
4694
  * @param shorthand - The shorthand string (e.g., 'name', 'salary:number')
4638
4695
  * @returns A ColumnConfig object
4696
+ * @since 1.4.0
4639
4697
  */
4640
4698
  function parseColumnShorthand(shorthand) {
4641
4699
  const colonIndex = shorthand.lastIndexOf(':');
@@ -4660,6 +4718,7 @@ function parseColumnShorthand(shorthand) {
4660
4718
  *
4661
4719
  * @param columns - Array of column shorthands (strings or ColumnConfig objects)
4662
4720
  * @returns Array of ColumnConfig objects
4721
+ * @since 1.4.0
4663
4722
  */
4664
4723
  function normalizeColumns(columns) {
4665
4724
  return columns.map((col) => (typeof col === 'string' ? parseColumnShorthand(col) : col));
@@ -4667,13 +4726,15 @@ function normalizeColumns(columns) {
4667
4726
  /**
4668
4727
  * Apply column defaults to a list of columns. Individual column properties
4669
4728
  * override defaults.
4729
+ * @since 1.4.0
4670
4730
  */
4671
4731
  function applyColumnDefaults(columns, defaults) {
4672
4732
  if (!defaults)
4673
4733
  return columns;
4674
4734
  return columns.map((col) => ({ ...defaults, ...col }));
4675
4735
  }
4676
- /** Check if an array of columns contains any shorthand strings. */
4736
+ /** Check if an array of columns contains any shorthand strings. * @since 1.4.0
4737
+ */
4677
4738
  function hasColumnShorthands(columns) {
4678
4739
  return columns.some((col) => typeof col === 'string');
4679
4740
  }
@@ -4687,6 +4748,7 @@ const eventClaims = new WeakMap();
4687
4748
  * the {@link Grid} directive will then use {@link getFeatureClaim} during
4688
4749
  * plugin creation instead of reading its own deprecated input.
4689
4750
  * @internal
4751
+ * @since 1.4.0
4690
4752
  */
4691
4753
  function registerFeatureClaim(grid, name, getConfig) {
4692
4754
  let map = featureClaims.get(grid);
@@ -4700,6 +4762,7 @@ function registerFeatureClaim(grid, name, getConfig) {
4700
4762
  * Look up a feature claim. Returns the registered config getter, or
4701
4763
  * `undefined` if no directive owns this feature on this element.
4702
4764
  * @internal
4765
+ * @since 1.4.0
4703
4766
  */
4704
4767
  function getFeatureClaim(grid, name) {
4705
4768
  return featureClaims.get(grid)?.get(name);
@@ -4709,6 +4772,7 @@ function getFeatureClaim(grid, name) {
4709
4772
  * that, if the directive is removed (e.g. via `*ngIf`) but the host
4710
4773
  * `<tbw-grid>` survives, {@link Grid}'s deprecated input takes back over.
4711
4774
  * @internal
4775
+ * @since 1.4.0
4712
4776
  */
4713
4777
  function unregisterFeatureClaim(grid, name) {
4714
4778
  featureClaims.get(grid)?.delete(name);
@@ -4718,6 +4782,7 @@ function unregisterFeatureClaim(grid, name) {
4718
4782
  * `setupEventListeners` skips wiring its own deprecated `output()` for any
4719
4783
  * claimed event — the directive owns the listener and the emit.
4720
4784
  * @internal
4785
+ * @since 1.4.0
4721
4786
  */
4722
4787
  function claimEvent(grid, eventName) {
4723
4788
  let set = eventClaims.get(grid);
@@ -4730,6 +4795,7 @@ function claimEvent(grid, eventName) {
4730
4795
  /**
4731
4796
  * Returns true if a directive has claimed this event on this grid element.
4732
4797
  * @internal
4798
+ * @since 1.4.0
4733
4799
  */
4734
4800
  function isEventClaimed(grid, eventName) {
4735
4801
  return eventClaims.get(grid)?.has(eventName) ?? false;
@@ -4738,6 +4804,7 @@ function isEventClaimed(grid, eventName) {
4738
4804
  * Drop an event claim. Pair with {@link claimEvent} in a directive's
4739
4805
  * `ngOnDestroy`.
4740
4806
  * @internal
4807
+ * @since 1.4.0
4741
4808
  */
4742
4809
  function unclaimEvent(grid, eventName) {
4743
4810
  eventClaims.get(grid)?.delete(eventName);
@@ -4778,6 +4845,7 @@ function unclaimEvent(grid, eventName) {
4778
4845
  * - Handles cleanup on destruction
4779
4846
  *
4780
4847
  * @category Directive
4848
+ * @since 0.1.0
4781
4849
  */
4782
4850
  class Grid {
4783
4851
  elementRef = inject((ElementRef));
@@ -6298,6 +6366,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
6298
6366
  *
6299
6367
  * Equivalent to calling `provideGridTypeDefaults(options.typeDefaults)` and
6300
6368
  * `provideGridIcons(options.icons)` separately.
6369
+ * @since 1.4.0
6301
6370
  */
6302
6371
  function provideGrid(options = {}) {
6303
6372
  const providers = [];