@toolbox-web/grid-angular 1.7.0 → 1.7.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.
- package/fesm2022/toolbox-web-grid-angular-features-filtering.mjs +26 -1
- package/fesm2022/toolbox-web-grid-angular-features-filtering.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-grouping-columns.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-grouping-rows.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-master-detail.mjs +33 -1
- package/fesm2022/toolbox-web-grid-angular-features-master-detail.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-pinned-rows.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-responsive.mjs +30 -1
- package/fesm2022/toolbox-web-grid-angular-features-responsive.mjs.map +1 -1
- package/package.json +1 -1
- package/types/toolbox-web-grid-angular-features-filtering.d.ts +22 -3
- package/types/toolbox-web-grid-angular-features-filtering.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-grouping-columns.d.ts +16 -12
- package/types/toolbox-web-grid-angular-features-grouping-columns.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-grouping-rows.d.ts +9 -7
- package/types/toolbox-web-grid-angular-features-grouping-rows.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-master-detail.d.ts +22 -2
- package/types/toolbox-web-grid-angular-features-master-detail.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-pinned-rows.d.ts +71 -2
- package/types/toolbox-web-grid-angular-features-pinned-rows.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-responsive.d.ts +22 -2
- package/types/toolbox-web-grid-angular-features-responsive.d.ts.map +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { inject, ElementRef, input, output, Directive, DestroyRef, signal, afterNextRender } from '@angular/core';
|
|
3
|
-
import { registerFeatureClaim, claimEvent, unregisterFeatureClaim, unclaimEvent, registerFilterPanelTypeDefaultBridge } from '@toolbox-web/grid-angular';
|
|
3
|
+
import { registerFeatureClaim, claimEvent, unregisterFeatureClaim, unclaimEvent, registerFilterPanelTypeDefaultBridge, registerFeatureConfigPreprocessor, isComponentClass } from '@toolbox-web/grid-angular';
|
|
4
4
|
export { BaseFilterPanel } from '@toolbox-web/grid-angular';
|
|
5
5
|
import '@toolbox-web/grid/features/filtering';
|
|
6
6
|
|
|
@@ -185,6 +185,31 @@ registerFilterPanelTypeDefaultBridge((rendererValue, adapter) => {
|
|
|
185
185
|
container.appendChild(mount(params).hostElement);
|
|
186
186
|
};
|
|
187
187
|
});
|
|
188
|
+
/**
|
|
189
|
+
* Bridge an Angular component class used as the plugin-level
|
|
190
|
+
* `filterPanelRenderer` (in `FilterConfig`) to the `(container, params) => void`
|
|
191
|
+
* form required by FilteringPlugin. Mirrors `registerFilterPanelTypeDefaultBridge`
|
|
192
|
+
* above, but for the plugin-wide renderer rather than per-type defaults.
|
|
193
|
+
*
|
|
194
|
+
* Without this preprocessor, passing a component class as
|
|
195
|
+
* `filtering.filterPanelRenderer` would be invoked as a function at render
|
|
196
|
+
* time and crash.
|
|
197
|
+
*
|
|
198
|
+
* @since 1.7.1
|
|
199
|
+
*/
|
|
200
|
+
registerFeatureConfigPreprocessor('filtering', (config, adapter) => {
|
|
201
|
+
if (!config || typeof config === 'boolean' || typeof config !== 'object')
|
|
202
|
+
return config;
|
|
203
|
+
const cfg = config;
|
|
204
|
+
if (!isComponentClass(cfg.filterPanelRenderer))
|
|
205
|
+
return config;
|
|
206
|
+
const componentClass = cfg.filterPanelRenderer;
|
|
207
|
+
const mount = adapter.mountComponentRenderer(componentClass, (params) => ({ params }));
|
|
208
|
+
const filterPanelRenderer = (container, params) => {
|
|
209
|
+
container.appendChild(mount(params).hostElement);
|
|
210
|
+
};
|
|
211
|
+
return { ...cfg, filterPanelRenderer };
|
|
212
|
+
});
|
|
188
213
|
/**
|
|
189
214
|
* Angular inject function for programmatic filter control.
|
|
190
215
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toolbox-web-grid-angular-features-filtering.mjs","sources":["../../../../libs/grid-angular/features/filtering/src/grid-filtering.directive.ts","../../../../libs/grid-angular/features/filtering/src/index.ts","../../../../libs/grid-angular/features/filtering/src/toolbox-web-grid-angular-features-filtering.ts"],"sourcesContent":["/**\n * `GridFilteringDirective` — attribute-selector directive that owns the\n * `filtering` input and the `filterChange` output on `<tbw-grid>`.\n *\n * ## Why this exists\n *\n * Historically these bindings lived on the central `Grid` directive in\n * `@toolbox-web/grid-angular`. That meant the typed surface for the\n * filtering plugin shipped in the core bundle of every consumer, even those\n * that never imported the filtering feature. Moving them here lets the\n * surface tree-shake away with the rest of the feature when it is not\n * imported, matching the philosophy of the React / Vue adapters and the\n * web-component core (where unloaded plugins simply don't exist on the\n * element).\n *\n * ## Usage\n *\n * ```typescript\n * import { Component } from '@angular/core';\n * import { Grid } from '@toolbox-web/grid-angular';\n * import { GridFilteringDirective } from '@toolbox-web/grid-angular/features/filtering';\n *\n * @Component({\n * selector: 'app-grid',\n * imports: [Grid, GridFilteringDirective],\n * template: `\n * <tbw-grid [rows]=\"rows\" [filtering]=\"true\" (filterChange)=\"onFilter($event)\" />\n * `,\n * })\n * export class AppGridComponent {}\n * ```\n *\n * ## Backward compatibility (v1.x)\n *\n * The matching `filtering` input and `filterChange` output also still exist\n * on `Grid` (marked `@deprecated`) so existing apps that bind them without\n * importing `GridFilteringDirective` continue to work — those will be\n * removed in v2.0.0. When both this directive and the deprecated bindings\n * are present, the directive wins via the per-grid claims registry in\n * `internal/feature-claims.ts`: `Grid` consults the registry and skips its\n * own plugin creation + event wiring for any claimed feature.\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 { FilterChangeDetail, FilterConfig } from '@toolbox-web/grid/plugins/filtering';\n\n/**\n * Owns the `[filtering]` input and `(filterChange)` output on `<tbw-grid>`.\n *\n * Selector matches when *either* binding is present so users can pick the\n * style that suits their template — both go through the same claim and the\n * same wiring.\n * @category Directive\n */\n@Directive({\n selector: 'tbw-grid[filtering], tbw-grid[filterChange]',\n standalone: true,\n})\nexport class GridFilteringDirective implements OnInit, OnDestroy {\n private readonly elementRef = inject(ElementRef<DataGridElement>);\n\n /**\n * Enable column filtering. Identical semantics to the deprecated input on\n * `Grid` — this directive owns the binding when both are present.\n *\n * @example\n * ```html\n * <tbw-grid [filtering]=\"true\" />\n * <tbw-grid [filtering]=\"{ debounceMs: 200 }\" />\n * ```\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n readonly filtering = input<boolean | FilterConfig<any>>();\n\n /**\n * Emitted when filter values change.\n *\n * @example\n * ```html\n * <tbw-grid (filterChange)=\"onFilterChange($event)\" />\n * ```\n */\n readonly filterChange = output<FilterChangeDetail>();\n\n // Listener kept so we can detach in `ngOnDestroy`.\n private listener?: (e: Event) => void;\n\n constructor() {\n const grid = this.elementRef.nativeElement;\n // Tell `Grid` we own this feature's input. Reading `this.filtering()`\n // inside the getter establishes a reactive dependency in `Grid`'s\n // `createFeaturePlugins` effect — when our input changes, that effect\n // re-runs and the plugin config is updated.\n registerFeatureClaim(grid, 'filtering', () => this.filtering());\n // Tell `Grid` we own the matching event so it doesn't double-emit on\n // its own deprecated `filterChange` output.\n claimEvent(grid, 'filter-change');\n }\n\n ngOnInit(): void {\n const grid = this.elementRef.nativeElement;\n this.listener = (e: Event) => {\n this.filterChange.emit((e as CustomEvent<FilterChangeDetail>).detail);\n };\n grid.addEventListener('filter-change', this.listener);\n }\n\n ngOnDestroy(): void {\n const grid = this.elementRef.nativeElement;\n if (this.listener) {\n grid.removeEventListener('filter-change', this.listener);\n this.listener = undefined;\n }\n // Drop the claims so that, if the directive is removed via *ngIf but\n // the host `<tbw-grid>` survives, `Grid`'s deprecated bindings take\n // back over without leaving stale ownership behind.\n unregisterFeatureClaim(grid, 'filtering');\n unclaimEvent(grid, 'filter-change');\n }\n}\n","/**\n * Filtering feature for @toolbox-web/grid-angular\n *\n * Two ways to use:\n *\n * 1. **Recommended (tree-shakeable surface):** add `GridFilteringDirective`\n * to your component's `imports`. The directive owns the `[filtering]`\n * input and `(filterChange)` output, so the typed surface tree-shakes\n * away when the feature is not imported.\n * 2. **Legacy (non-breaking, deprecated):** side-effect import the feature\n * entry; the matching `[filtering]` / `(filterChange)` bindings on the\n * central `Grid` directive will work as in v1.x. These bindings on `Grid`\n * are marked `@deprecated` and will be removed in v2.0.0.\n *\n * Either way `injectGridFiltering()` is available for programmatic control.\n *\n * @example Recommended (directive-owned binding)\n * ```typescript\n * import { Grid } from '@toolbox-web/grid-angular';\n * import { GridFilteringDirective } from '@toolbox-web/grid-angular/features/filtering';\n *\n * @Component({\n * imports: [Grid, GridFilteringDirective],\n * template: `<tbw-grid [filtering]=\"true\" (filterChange)=\"onChange($event)\" />`,\n * })\n * ```\n *\n * @example Legacy (deprecated; works without importing the directive)\n * ```typescript\n * import '@toolbox-web/grid-angular/features/filtering';\n *\n * <tbw-grid [filtering]=\"true\" />\n * <tbw-grid [filtering]=\"{ debounceMs: 200 }\" />\n * ```\n *\n * @example Using injectGridFiltering\n * ```typescript\n * import { injectGridFiltering } from '@toolbox-web/grid-angular/features/filtering';\n *\n * @Component({...})\n * export class MyComponent {\n * private filtering = injectGridFiltering();\n *\n * filterByStatus(status: string) {\n * this.filtering.setFilter('status', { operator: 'equals', value: status });\n * }\n * }\n * ```\n *\n * @packageDocumentation\n */\n\nimport { afterNextRender, DestroyRef, ElementRef, inject, signal, type Signal, type Type } from '@angular/core';\nimport type { DataGridElement } from '@toolbox-web/grid';\nimport { registerFilterPanelTypeDefaultBridge, type GridAdapter } from '@toolbox-web/grid-angular';\nimport '@toolbox-web/grid/features/filtering';\nimport {\n FilteringPlugin,\n type BlankMode,\n type FilterModel,\n type FilterPanelParams,\n} from '@toolbox-web/grid/plugins/filtering';\nexport type { _Augmentation as _FilteringAugmentation } from '@toolbox-web/grid/features/filtering';\n\n// Attribute-selector directive that owns the `[filtering]` input and\n// `(filterChange)` output on `<tbw-grid>`. Add to your component's `imports`\n// alongside `Grid` to opt into the feature directly via the binding. The\n// matching deprecated bindings on `Grid` remain as a v1.x compatibility\n// shim and will be removed in v2.0.0.\nexport { GridFilteringDirective } from './grid-filtering.directive';\n\n// ---------------------------------------------------------------------------\n// Re-exports from `@toolbox-web/grid-angular` (main entry).\n//\n// `BaseFilterPanel` is filtering-specific (implements `FilterPanel` from the\n// filtering plugin). It still physically lives in the main entry today, but\n// is re-exported here so consumers can import it from the feature entry that\n// owns the runtime behaviour. The same symbol is `@deprecated` on the main\n// entry; in v2.0.0 the source will physically move into this secondary entry\n// and the deprecated re-export on the main entry will be removed.\n// ---------------------------------------------------------------------------\nexport { BaseFilterPanel } from '@toolbox-web/grid-angular';\n\n// Bridge any Angular component classes used as `filterPanelRenderer` (in\n// `gridConfig.typeDefaults` or via `provideGridTypeDefaults`) to the\n// `(container, params) => void` form required by FilteringPlugin. Without\n// this import, component-class filterPanelRenderers are silently dropped \\u2014\n// the same precondition as the FilteringPlugin itself (TBW031).\nregisterFilterPanelTypeDefaultBridge((rendererValue: unknown, adapter: GridAdapter) => {\n const componentClass = rendererValue as Type<unknown>;\n const mount = adapter.mountComponentRenderer<FilterPanelParams>(componentClass, (params) => ({ params }));\n return (container: HTMLElement, params: FilterPanelParams) => {\n container.appendChild(mount(params).hostElement);\n };\n});\n\n/**\n * Filtering methods returned from injectGridFiltering.\n *\n * Uses lazy discovery - the grid is found on first method call, not during initialization.\n */\nexport interface FilteringMethods {\n /**\n * Set a filter on a specific field.\n * @param field - The field name to filter\n * @param filter - Filter configuration, or null to remove\n * @param options - `{ silent: true }` applies the filter without emitting `filter-change`\n */\n setFilter: (field: string, filter: Omit<FilterModel, 'field'> | null, options?: { silent?: boolean }) => void;\n\n /**\n * Get the current filter for a field.\n */\n getFilter: (field: string) => FilterModel | undefined;\n\n /**\n * Get all active filters.\n */\n getFilters: () => FilterModel[];\n\n /**\n * Set all filters at once (replaces existing).\n * @param options - `{ silent: true }` applies filters without emitting `filter-change`\n */\n setFilterModel: (filters: FilterModel[], options?: { silent?: boolean }) => void;\n\n /**\n * Clear all active filters.\n * @param options - `{ silent: true }` clears filters without emitting `filter-change`\n */\n clearAllFilters: (options?: { silent?: boolean }) => void;\n\n /**\n * Clear filter for a specific field.\n * @param options - `{ silent: true }` clears filter without emitting `filter-change`\n */\n clearFieldFilter: (field: string, options?: { silent?: boolean }) => void;\n\n /**\n * Check if a field has an active filter.\n */\n isFieldFiltered: (field: string) => boolean;\n\n /**\n * Get the count of rows after filtering.\n */\n getFilteredRowCount: () => number;\n\n /**\n * Get unique values for a field (for building filter dropdowns).\n */\n getUniqueValues: (field: string) => unknown[];\n\n /**\n * Get set filters whose values no longer match any rows in the current data.\n */\n getStaleFilters: () => FilterModel[];\n\n /**\n * Get the current blank mode for a field.\n */\n getBlankMode: (field: string) => BlankMode;\n\n /**\n * Toggle blank filter mode for a field.\n */\n toggleBlankFilter: (field: string, mode: BlankMode) => void;\n\n /**\n * Signal indicating if grid is ready.\n */\n isReady: Signal<boolean>;\n}\n\n/**\n * Angular inject function for programmatic filter control.\n *\n * Uses **lazy grid discovery** - the grid element is found when methods are called,\n * not during initialization.\n *\n * @example\n * ```typescript\n * import { Component } from '@angular/core';\n * import { Grid } from '@toolbox-web/grid-angular';\n * import '@toolbox-web/grid-angular/features/filtering';\n * import { injectGridFiltering } from '@toolbox-web/grid-angular/features/filtering';\n *\n * @Component({\n * selector: 'app-my-grid',\n * imports: [Grid],\n * template: `\n * <input (input)=\"applyFilter($event)\" placeholder=\"Filter by name...\" />\n * <span>{{ filtering.getFilteredRowCount() }} results</span>\n * <button (click)=\"filtering.clearAllFilters()\">Clear</button>\n * <tbw-grid [rows]=\"rows\" [filtering]=\"true\"></tbw-grid>\n * `\n * })\n * export class MyGridComponent {\n * filtering = injectGridFiltering();\n *\n * applyFilter(event: Event) {\n * const value = (event.target as HTMLInputElement).value;\n * this.filtering.setFilter('name', value ? { operator: 'contains', value } : null);\n * }\n * }\n * ```\n *\n * @param selector - Optional CSS selector to target a specific grid element.\n * Defaults to `'tbw-grid'` (first grid in the component). Use when the\n * component contains multiple grids, e.g. `'tbw-grid.primary'` or `'#my-grid'`.\n */\nexport function injectGridFiltering(selector = 'tbw-grid'): FilteringMethods {\n const elementRef = inject(ElementRef);\n const destroyRef = inject(DestroyRef);\n const isReady = signal(false);\n\n let cachedGrid: DataGridElement | null = null;\n let readyPromiseStarted = false;\n\n const getGrid = (): DataGridElement | null => {\n if (cachedGrid) return cachedGrid;\n\n const grid = elementRef.nativeElement.querySelector(selector) as DataGridElement | null;\n if (grid) {\n cachedGrid = grid;\n if (!readyPromiseStarted) {\n readyPromiseStarted = true;\n grid.ready?.().then(() => {\n // If the plugin is already attached, signal readiness immediately.\n // Otherwise, Angular's Grid directive may not have applied gridConfig\n // yet (it uses effect + queueMicrotask). Defer to let pending\n // microtasks flush before signaling readiness.\n if (grid.getPluginByName('filtering')) {\n isReady.set(true);\n } else {\n setTimeout(() => isReady.set(true), 0);\n }\n });\n }\n }\n return grid;\n };\n\n const getPlugin = (): FilteringPlugin | undefined => {\n return getGrid()?.getPluginByName('filtering') as FilteringPlugin | undefined;\n };\n\n // Eagerly discover the grid after the first render so isReady updates\n // without requiring a programmatic method call. Falls back to a\n // MutationObserver for lazy-rendered tabs, *ngIf, @defer, etc.\n afterNextRender(() => {\n if (getGrid()) return;\n\n const host = elementRef.nativeElement as HTMLElement;\n const observer = new MutationObserver(() => {\n if (getGrid()) observer.disconnect();\n });\n observer.observe(host, { childList: true, subtree: true });\n\n destroyRef.onDestroy(() => observer.disconnect());\n });\n\n return {\n isReady: isReady.asReadonly(),\n\n setFilter: (field: string, filter: Omit<FilterModel, 'field'> | null, options?: { silent?: boolean }) => {\n const plugin = getPlugin();\n if (!plugin) {\n console.warn(\n `[tbw-grid:filtering] FilteringPlugin not found.\\n\\n` +\n ` → Enable filtering on the grid:\\n` +\n ` <tbw-grid [filtering]=\"true\" />`,\n );\n return;\n }\n plugin.setFilter(field, filter, options);\n },\n\n getFilter: (field: string) => getPlugin()?.getFilter(field),\n\n getFilters: () => getPlugin()?.getFilters() ?? [],\n\n setFilterModel: (filters: FilterModel[], options?: { silent?: boolean }) => {\n const plugin = getPlugin();\n if (!plugin) {\n console.warn(\n `[tbw-grid:filtering] FilteringPlugin not found.\\n\\n` +\n ` → Enable filtering on the grid:\\n` +\n ` <tbw-grid [filtering]=\"true\" />`,\n );\n return;\n }\n plugin.setFilterModel(filters, options);\n },\n\n clearAllFilters: (options?: { silent?: boolean }) => {\n const plugin = getPlugin();\n if (!plugin) {\n console.warn(\n `[tbw-grid:filtering] FilteringPlugin not found.\\n\\n` +\n ` → Enable filtering on the grid:\\n` +\n ` <tbw-grid [filtering]=\"true\" />`,\n );\n return;\n }\n plugin.clearAllFilters(options);\n },\n\n clearFieldFilter: (field: string, options?: { silent?: boolean }) => {\n const plugin = getPlugin();\n if (!plugin) {\n console.warn(\n `[tbw-grid:filtering] FilteringPlugin not found.\\n\\n` +\n ` → Enable filtering on the grid:\\n` +\n ` <tbw-grid [filtering]=\"true\" />`,\n );\n return;\n }\n plugin.clearFieldFilter(field, options);\n },\n\n isFieldFiltered: (field: string) => getPlugin()?.isFieldFiltered(field) ?? false,\n\n getFilteredRowCount: () => getPlugin()?.getFilteredRowCount() ?? 0,\n\n getUniqueValues: (field: string) => getPlugin()?.getUniqueValues(field) ?? [],\n\n getStaleFilters: () => getPlugin()?.getStaleFilters() ?? [],\n\n getBlankMode: (field: string) => getPlugin()?.getBlankMode(field) ?? 'all',\n\n toggleBlankFilter: (field: string, mode: BlankMode) => {\n const plugin = getPlugin();\n if (!plugin) {\n console.warn(\n `[tbw-grid:filtering] FilteringPlugin not found.\\n\\n` +\n ` → Enable filtering on the grid:\\n` +\n ` <tbw-grid [filtering]=\"true\" />`,\n );\n return;\n }\n plugin.toggleBlankFilter(field, mode);\n },\n };\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-filtering.mjs","sources":["../../../../libs/grid-angular/features/filtering/src/grid-filtering.directive.ts","../../../../libs/grid-angular/features/filtering/src/index.ts","../../../../libs/grid-angular/features/filtering/src/toolbox-web-grid-angular-features-filtering.ts"],"sourcesContent":["/**\n * `GridFilteringDirective` — attribute-selector directive that owns the\n * `filtering` input and the `filterChange` output on `<tbw-grid>`.\n *\n * ## Why this exists\n *\n * Historically these bindings lived on the central `Grid` directive in\n * `@toolbox-web/grid-angular`. That meant the typed surface for the\n * filtering plugin shipped in the core bundle of every consumer, even those\n * that never imported the filtering feature. Moving them here lets the\n * surface tree-shake away with the rest of the feature when it is not\n * imported, matching the philosophy of the React / Vue adapters and the\n * web-component core (where unloaded plugins simply don't exist on the\n * element).\n *\n * ## Usage\n *\n * ```typescript\n * import { Component } from '@angular/core';\n * import { Grid } from '@toolbox-web/grid-angular';\n * import { GridFilteringDirective } from '@toolbox-web/grid-angular/features/filtering';\n *\n * @Component({\n * selector: 'app-grid',\n * imports: [Grid, GridFilteringDirective],\n * template: `\n * <tbw-grid [rows]=\"rows\" [filtering]=\"true\" (filterChange)=\"onFilter($event)\" />\n * `,\n * })\n * export class AppGridComponent {}\n * ```\n *\n * ## Backward compatibility (v1.x)\n *\n * The matching `filtering` input and `filterChange` output also still exist\n * on `Grid` (marked `@deprecated`) so existing apps that bind them without\n * importing `GridFilteringDirective` continue to work — those will be\n * removed in v2.0.0. When both this directive and the deprecated bindings\n * are present, the directive wins via the per-grid claims registry in\n * `internal/feature-claims.ts`: `Grid` consults the registry and skips its\n * own plugin creation + event wiring for any claimed feature.\n *\n * @category Directive\n */\nimport { Directive, ElementRef, inject, input, OnDestroy, OnInit, output, type Type } from '@angular/core';\nimport type { DataGridElement } from '@toolbox-web/grid';\nimport {\n claimEvent,\n registerFeatureClaim,\n unclaimEvent,\n unregisterFeatureClaim,\n type FilterPanel,\n} from '@toolbox-web/grid-angular';\nimport type { FilterConfig as CoreFilterConfig, FilterChangeDetail } from '@toolbox-web/grid/plugins/filtering';\n\n/**\n * Angular-specific filter config that allows an Angular component class as\n * the plugin-level `filterPanelRenderer`.\n *\n * Extends the core `FilterConfig` to accept a `Type<FilterPanel>` for\n * `filterPanelRenderer` in addition to the vanilla\n * `(container, params) => void` signature. Bridging to vanilla DOM is handled\n * by the side-effect import `@toolbox-web/grid-angular/features/filtering`.\n *\n * Re-exported from the feature entry under the same name as the core type\n * so Angular consumers see a single canonical `FilterConfig` from\n * `@toolbox-web/grid-angular/features/filtering`.\n *\n * @since 1.7.1\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type FilterConfig<TRow = any> = Omit<CoreFilterConfig<TRow>, 'filterPanelRenderer'> & {\n filterPanelRenderer?: CoreFilterConfig<TRow>['filterPanelRenderer'] | Type<FilterPanel>;\n};\n\n/**\n * Owns the `[filtering]` input and `(filterChange)` output on `<tbw-grid>`.\n *\n * Selector matches when *either* binding is present so users can pick the\n * style that suits their template — both go through the same claim and the\n * same wiring.\n * @category Directive\n */\n@Directive({\n selector: 'tbw-grid[filtering], tbw-grid[filterChange]',\n standalone: true,\n})\nexport class GridFilteringDirective implements OnInit, OnDestroy {\n private readonly elementRef = inject(ElementRef<DataGridElement>);\n\n /**\n * Enable column filtering. Identical semantics to the deprecated input on\n * `Grid` — this directive owns the binding when both are present.\n *\n * @example\n * ```html\n * <tbw-grid [filtering]=\"true\" />\n * <tbw-grid [filtering]=\"{ debounceMs: 200 }\" />\n * ```\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n readonly filtering = input<boolean | FilterConfig<any>>();\n\n /**\n * Emitted when filter values change.\n *\n * @example\n * ```html\n * <tbw-grid (filterChange)=\"onFilterChange($event)\" />\n * ```\n */\n readonly filterChange = output<FilterChangeDetail>();\n\n // Listener kept so we can detach in `ngOnDestroy`.\n private listener?: (e: Event) => void;\n\n constructor() {\n const grid = this.elementRef.nativeElement;\n // Tell `Grid` we own this feature's input. Reading `this.filtering()`\n // inside the getter establishes a reactive dependency in `Grid`'s\n // `createFeaturePlugins` effect — when our input changes, that effect\n // re-runs and the plugin config is updated.\n registerFeatureClaim(grid, 'filtering', () => this.filtering());\n // Tell `Grid` we own the matching event so it doesn't double-emit on\n // its own deprecated `filterChange` output.\n claimEvent(grid, 'filter-change');\n }\n\n ngOnInit(): void {\n const grid = this.elementRef.nativeElement;\n this.listener = (e: Event) => {\n this.filterChange.emit((e as CustomEvent<FilterChangeDetail>).detail);\n };\n grid.addEventListener('filter-change', this.listener);\n }\n\n ngOnDestroy(): void {\n const grid = this.elementRef.nativeElement;\n if (this.listener) {\n grid.removeEventListener('filter-change', this.listener);\n this.listener = undefined;\n }\n // Drop the claims so that, if the directive is removed via *ngIf but\n // the host `<tbw-grid>` survives, `Grid`'s deprecated bindings take\n // back over without leaving stale ownership behind.\n unregisterFeatureClaim(grid, 'filtering');\n unclaimEvent(grid, 'filter-change');\n }\n}\n","/**\n * Filtering feature for @toolbox-web/grid-angular\n *\n * Two ways to use:\n *\n * 1. **Recommended (tree-shakeable surface):** add `GridFilteringDirective`\n * to your component's `imports`. The directive owns the `[filtering]`\n * input and `(filterChange)` output, so the typed surface tree-shakes\n * away when the feature is not imported.\n * 2. **Legacy (non-breaking, deprecated):** side-effect import the feature\n * entry; the matching `[filtering]` / `(filterChange)` bindings on the\n * central `Grid` directive will work as in v1.x. These bindings on `Grid`\n * are marked `@deprecated` and will be removed in v2.0.0.\n *\n * Either way `injectGridFiltering()` is available for programmatic control.\n *\n * @example Recommended (directive-owned binding)\n * ```typescript\n * import { Grid } from '@toolbox-web/grid-angular';\n * import { GridFilteringDirective } from '@toolbox-web/grid-angular/features/filtering';\n *\n * @Component({\n * imports: [Grid, GridFilteringDirective],\n * template: `<tbw-grid [filtering]=\"true\" (filterChange)=\"onChange($event)\" />`,\n * })\n * ```\n *\n * @example Legacy (deprecated; works without importing the directive)\n * ```typescript\n * import '@toolbox-web/grid-angular/features/filtering';\n *\n * <tbw-grid [filtering]=\"true\" />\n * <tbw-grid [filtering]=\"{ debounceMs: 200 }\" />\n * ```\n *\n * @example Using injectGridFiltering\n * ```typescript\n * import { injectGridFiltering } from '@toolbox-web/grid-angular/features/filtering';\n *\n * @Component({...})\n * export class MyComponent {\n * private filtering = injectGridFiltering();\n *\n * filterByStatus(status: string) {\n * this.filtering.setFilter('status', { operator: 'equals', value: status });\n * }\n * }\n * ```\n *\n * @packageDocumentation\n */\n\nimport { afterNextRender, DestroyRef, ElementRef, inject, signal, type Signal, type Type } from '@angular/core';\nimport type { DataGridElement } from '@toolbox-web/grid';\nimport {\n isComponentClass,\n registerFeatureConfigPreprocessor,\n registerFilterPanelTypeDefaultBridge,\n type GridAdapter,\n} from '@toolbox-web/grid-angular';\nimport '@toolbox-web/grid/features/filtering';\nimport {\n FilteringPlugin,\n type BlankMode,\n type FilterConfig as CoreFilterConfig,\n type FilterModel,\n type FilterPanelParams,\n} from '@toolbox-web/grid/plugins/filtering';\nexport type { _Augmentation as _FilteringAugmentation } from '@toolbox-web/grid/features/filtering';\n\n// Attribute-selector directive that owns the `[filtering]` input and\n// `(filterChange)` output on `<tbw-grid>`. Add to your component's `imports`\n// alongside `Grid` to opt into the feature directly via the binding. The\n// matching deprecated bindings on `Grid` remain as a v1.x compatibility\n// shim and will be removed in v2.0.0.\nexport { GridFilteringDirective } from './grid-filtering.directive';\nexport type { FilterConfig } from './grid-filtering.directive';\n\n// ---------------------------------------------------------------------------\n// Re-exports from `@toolbox-web/grid-angular` (main entry).\n//\n// `BaseFilterPanel` is filtering-specific (implements `FilterPanel` from the\n// filtering plugin). It still physically lives in the main entry today, but\n// is re-exported here so consumers can import it from the feature entry that\n// owns the runtime behaviour. The same symbol is `@deprecated` on the main\n// entry; in v2.0.0 the source will physically move into this secondary entry\n// and the deprecated re-export on the main entry will be removed.\n// ---------------------------------------------------------------------------\nexport { BaseFilterPanel } from '@toolbox-web/grid-angular';\n\n// Bridge any Angular component classes used as `filterPanelRenderer` (in\n// `gridConfig.typeDefaults` or via `provideGridTypeDefaults`) to the\n// `(container, params) => void` form required by FilteringPlugin. Without\n// this import, component-class filterPanelRenderers are silently dropped \\u2014\n// the same precondition as the FilteringPlugin itself (TBW031).\nregisterFilterPanelTypeDefaultBridge((rendererValue: unknown, adapter: GridAdapter) => {\n const componentClass = rendererValue as Type<unknown>;\n const mount = adapter.mountComponentRenderer<FilterPanelParams>(componentClass, (params) => ({ params }));\n return (container: HTMLElement, params: FilterPanelParams) => {\n container.appendChild(mount(params).hostElement);\n };\n});\n\n/**\n * Bridge an Angular component class used as the plugin-level\n * `filterPanelRenderer` (in `FilterConfig`) to the `(container, params) => void`\n * form required by FilteringPlugin. Mirrors `registerFilterPanelTypeDefaultBridge`\n * above, but for the plugin-wide renderer rather than per-type defaults.\n *\n * Without this preprocessor, passing a component class as\n * `filtering.filterPanelRenderer` would be invoked as a function at render\n * time and crash.\n *\n * @since 1.7.1\n */\nregisterFeatureConfigPreprocessor('filtering', (config, adapter) => {\n if (!config || typeof config === 'boolean' || typeof config !== 'object') return config;\n const cfg = config as CoreFilterConfig;\n if (!isComponentClass(cfg.filterPanelRenderer)) return config;\n\n const componentClass = cfg.filterPanelRenderer as Type<unknown>;\n const mount = adapter.mountComponentRenderer<FilterPanelParams>(componentClass, (params) => ({ params }));\n const filterPanelRenderer: CoreFilterConfig['filterPanelRenderer'] = (container, params) => {\n container.appendChild(mount(params).hostElement);\n };\n return { ...cfg, filterPanelRenderer };\n});\n\n/**\n * Filtering methods returned from injectGridFiltering.\n *\n * Uses lazy discovery - the grid is found on first method call, not during initialization.\n */\nexport interface FilteringMethods {\n /**\n * Set a filter on a specific field.\n * @param field - The field name to filter\n * @param filter - Filter configuration, or null to remove\n * @param options - `{ silent: true }` applies the filter without emitting `filter-change`\n */\n setFilter: (field: string, filter: Omit<FilterModel, 'field'> | null, options?: { silent?: boolean }) => void;\n\n /**\n * Get the current filter for a field.\n */\n getFilter: (field: string) => FilterModel | undefined;\n\n /**\n * Get all active filters.\n */\n getFilters: () => FilterModel[];\n\n /**\n * Set all filters at once (replaces existing).\n * @param options - `{ silent: true }` applies filters without emitting `filter-change`\n */\n setFilterModel: (filters: FilterModel[], options?: { silent?: boolean }) => void;\n\n /**\n * Clear all active filters.\n * @param options - `{ silent: true }` clears filters without emitting `filter-change`\n */\n clearAllFilters: (options?: { silent?: boolean }) => void;\n\n /**\n * Clear filter for a specific field.\n * @param options - `{ silent: true }` clears filter without emitting `filter-change`\n */\n clearFieldFilter: (field: string, options?: { silent?: boolean }) => void;\n\n /**\n * Check if a field has an active filter.\n */\n isFieldFiltered: (field: string) => boolean;\n\n /**\n * Get the count of rows after filtering.\n */\n getFilteredRowCount: () => number;\n\n /**\n * Get unique values for a field (for building filter dropdowns).\n */\n getUniqueValues: (field: string) => unknown[];\n\n /**\n * Get set filters whose values no longer match any rows in the current data.\n */\n getStaleFilters: () => FilterModel[];\n\n /**\n * Get the current blank mode for a field.\n */\n getBlankMode: (field: string) => BlankMode;\n\n /**\n * Toggle blank filter mode for a field.\n */\n toggleBlankFilter: (field: string, mode: BlankMode) => void;\n\n /**\n * Signal indicating if grid is ready.\n */\n isReady: Signal<boolean>;\n}\n\n/**\n * Angular inject function for programmatic filter control.\n *\n * Uses **lazy grid discovery** - the grid element is found when methods are called,\n * not during initialization.\n *\n * @example\n * ```typescript\n * import { Component } from '@angular/core';\n * import { Grid } from '@toolbox-web/grid-angular';\n * import '@toolbox-web/grid-angular/features/filtering';\n * import { injectGridFiltering } from '@toolbox-web/grid-angular/features/filtering';\n *\n * @Component({\n * selector: 'app-my-grid',\n * imports: [Grid],\n * template: `\n * <input (input)=\"applyFilter($event)\" placeholder=\"Filter by name...\" />\n * <span>{{ filtering.getFilteredRowCount() }} results</span>\n * <button (click)=\"filtering.clearAllFilters()\">Clear</button>\n * <tbw-grid [rows]=\"rows\" [filtering]=\"true\"></tbw-grid>\n * `\n * })\n * export class MyGridComponent {\n * filtering = injectGridFiltering();\n *\n * applyFilter(event: Event) {\n * const value = (event.target as HTMLInputElement).value;\n * this.filtering.setFilter('name', value ? { operator: 'contains', value } : null);\n * }\n * }\n * ```\n *\n * @param selector - Optional CSS selector to target a specific grid element.\n * Defaults to `'tbw-grid'` (first grid in the component). Use when the\n * component contains multiple grids, e.g. `'tbw-grid.primary'` or `'#my-grid'`.\n */\nexport function injectGridFiltering(selector = 'tbw-grid'): FilteringMethods {\n const elementRef = inject(ElementRef);\n const destroyRef = inject(DestroyRef);\n const isReady = signal(false);\n\n let cachedGrid: DataGridElement | null = null;\n let readyPromiseStarted = false;\n\n const getGrid = (): DataGridElement | null => {\n if (cachedGrid) return cachedGrid;\n\n const grid = elementRef.nativeElement.querySelector(selector) as DataGridElement | null;\n if (grid) {\n cachedGrid = grid;\n if (!readyPromiseStarted) {\n readyPromiseStarted = true;\n grid.ready?.().then(() => {\n // If the plugin is already attached, signal readiness immediately.\n // Otherwise, Angular's Grid directive may not have applied gridConfig\n // yet (it uses effect + queueMicrotask). Defer to let pending\n // microtasks flush before signaling readiness.\n if (grid.getPluginByName('filtering')) {\n isReady.set(true);\n } else {\n setTimeout(() => isReady.set(true), 0);\n }\n });\n }\n }\n return grid;\n };\n\n const getPlugin = (): FilteringPlugin | undefined => {\n return getGrid()?.getPluginByName('filtering') as FilteringPlugin | undefined;\n };\n\n // Eagerly discover the grid after the first render so isReady updates\n // without requiring a programmatic method call. Falls back to a\n // MutationObserver for lazy-rendered tabs, *ngIf, @defer, etc.\n afterNextRender(() => {\n if (getGrid()) return;\n\n const host = elementRef.nativeElement as HTMLElement;\n const observer = new MutationObserver(() => {\n if (getGrid()) observer.disconnect();\n });\n observer.observe(host, { childList: true, subtree: true });\n\n destroyRef.onDestroy(() => observer.disconnect());\n });\n\n return {\n isReady: isReady.asReadonly(),\n\n setFilter: (field: string, filter: Omit<FilterModel, 'field'> | null, options?: { silent?: boolean }) => {\n const plugin = getPlugin();\n if (!plugin) {\n console.warn(\n `[tbw-grid:filtering] FilteringPlugin not found.\\n\\n` +\n ` → Enable filtering on the grid:\\n` +\n ` <tbw-grid [filtering]=\"true\" />`,\n );\n return;\n }\n plugin.setFilter(field, filter, options);\n },\n\n getFilter: (field: string) => getPlugin()?.getFilter(field),\n\n getFilters: () => getPlugin()?.getFilters() ?? [],\n\n setFilterModel: (filters: FilterModel[], options?: { silent?: boolean }) => {\n const plugin = getPlugin();\n if (!plugin) {\n console.warn(\n `[tbw-grid:filtering] FilteringPlugin not found.\\n\\n` +\n ` → Enable filtering on the grid:\\n` +\n ` <tbw-grid [filtering]=\"true\" />`,\n );\n return;\n }\n plugin.setFilterModel(filters, options);\n },\n\n clearAllFilters: (options?: { silent?: boolean }) => {\n const plugin = getPlugin();\n if (!plugin) {\n console.warn(\n `[tbw-grid:filtering] FilteringPlugin not found.\\n\\n` +\n ` → Enable filtering on the grid:\\n` +\n ` <tbw-grid [filtering]=\"true\" />`,\n );\n return;\n }\n plugin.clearAllFilters(options);\n },\n\n clearFieldFilter: (field: string, options?: { silent?: boolean }) => {\n const plugin = getPlugin();\n if (!plugin) {\n console.warn(\n `[tbw-grid:filtering] FilteringPlugin not found.\\n\\n` +\n ` → Enable filtering on the grid:\\n` +\n ` <tbw-grid [filtering]=\"true\" />`,\n );\n return;\n }\n plugin.clearFieldFilter(field, options);\n },\n\n isFieldFiltered: (field: string) => getPlugin()?.isFieldFiltered(field) ?? false,\n\n getFilteredRowCount: () => getPlugin()?.getFilteredRowCount() ?? 0,\n\n getUniqueValues: (field: string) => getPlugin()?.getUniqueValues(field) ?? [],\n\n getStaleFilters: () => getPlugin()?.getStaleFilters() ?? [],\n\n getBlankMode: (field: string) => getPlugin()?.getBlankMode(field) ?? 'all',\n\n toggleBlankFilter: (field: string, mode: BlankMode) => {\n const plugin = getPlugin();\n if (!plugin) {\n console.warn(\n `[tbw-grid:filtering] FilteringPlugin not found.\\n\\n` +\n ` → Enable filtering on the grid:\\n` +\n ` <tbw-grid [filtering]=\"true\" />`,\n );\n return;\n }\n plugin.toggleBlankFilter(field, mode);\n },\n };\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toolbox-web-grid-angular-features-grouping-columns.mjs","sources":["../../../../libs/grid-angular/features/grouping-columns/src/grid-grouping-columns.directive.ts","../../../../libs/grid-angular/features/grouping-columns/src/index.ts","../../../../libs/grid-angular/features/grouping-columns/src/toolbox-web-grid-angular-features-grouping-columns.ts"],"sourcesContent":["/**\n * `GridGroupingColumnsDirective` — owns `[groupingColumns]` on\n * `<tbw-grid>`. No event outputs. See `GridFilteringDirective` for the\n * full rationale.\n *\n * @category Directive\n */\nimport { Directive, ElementRef, inject, input, OnDestroy, type Type } from '@angular/core';\nimport type { DataGridElement } from '@toolbox-web/grid';\nimport { registerFeatureClaim, unregisterFeatureClaim } from '@toolbox-web/grid-angular';\nimport type {\n ColumnGroupDefinition,\n
|
|
1
|
+
{"version":3,"file":"toolbox-web-grid-angular-features-grouping-columns.mjs","sources":["../../../../libs/grid-angular/features/grouping-columns/src/grid-grouping-columns.directive.ts","../../../../libs/grid-angular/features/grouping-columns/src/index.ts","../../../../libs/grid-angular/features/grouping-columns/src/toolbox-web-grid-angular-features-grouping-columns.ts"],"sourcesContent":["/**\n * `GridGroupingColumnsDirective` — owns `[groupingColumns]` on\n * `<tbw-grid>`. No event outputs. See `GridFilteringDirective` for the\n * full rationale.\n *\n * @category Directive\n */\nimport { Directive, ElementRef, inject, input, OnDestroy, type Type } from '@angular/core';\nimport type { DataGridElement } from '@toolbox-web/grid';\nimport { registerFeatureClaim, unregisterFeatureClaim } from '@toolbox-web/grid-angular';\nimport type {\n ColumnGroupDefinition as CoreColumnGroupDefinition,\n GroupingColumnsConfig as CoreGroupingColumnsConfig,\n GroupHeaderRenderParams,\n} from '@toolbox-web/grid/plugins/grouping-columns';\n\n/**\n * Column group definition widened to accept an Angular component class as\n * the per-group `renderer`.\n *\n * @since 1.7.0\n */\nexport type ColumnGroupDefinition = Omit<CoreColumnGroupDefinition, 'renderer'> & {\n renderer?: CoreColumnGroupDefinition['renderer'] | Type<unknown>;\n};\n\n/**\n * Grouping-columns config widened to accept Angular component classes for\n * `groupHeaderRenderer` and per-group `renderer` inside `columnGroups`.\n *\n * Component instances receive the {@link GroupHeaderRenderParams} fields as\n * inputs (`id`, `label`, `columns`, `firstIndex`, `isImplicit`).\n *\n * @since 1.7.0\n */\nexport type GroupingColumnsConfig = Omit<CoreGroupingColumnsConfig, 'groupHeaderRenderer' | 'columnGroups'> & {\n columnGroups?: ColumnGroupDefinition[];\n groupHeaderRenderer?: CoreGroupingColumnsConfig['groupHeaderRenderer'] | Type<unknown>;\n};\n\n// ── Deprecated framework-prefixed aliases ────────────────────────────────\n// Retained for backwards compatibility. New code should use the canonical\n// (unprefixed) names above.\n\n/** @deprecated Use {@link ColumnGroupDefinition} instead. */\nexport type AngularColumnGroupDefinition = ColumnGroupDefinition;\n/** @deprecated Use {@link GroupingColumnsConfig} instead. */\nexport type AngularGroupingColumnsConfig = GroupingColumnsConfig;\n\n/**\n * Owns the binding(s) `[groupingColumns]` on `<tbw-grid>` for the matching feature plugin. See `GridFilteringDirective` for the full rationale.\n *\n * @category Directive\n */\n@Directive({\n selector: 'tbw-grid[groupingColumns]',\n standalone: true,\n})\nexport class GridGroupingColumnsDirective implements OnDestroy {\n private readonly elementRef = inject(ElementRef<DataGridElement>);\n\n readonly groupingColumns = input<boolean | GroupingColumnsConfig>();\n\n constructor() {\n registerFeatureClaim(this.elementRef.nativeElement, 'groupingColumns', () => this.groupingColumns());\n }\n\n ngOnDestroy(): void {\n unregisterFeatureClaim(this.elementRef.nativeElement, 'groupingColumns');\n }\n}\n","/**\n * Column grouping feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `groupingColumns` input on Grid directive.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/grouping-columns';\n *\n * <tbw-grid [groupingColumns]=\"{ columnGroups: [...] }\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport type { Type } from '@angular/core';\nimport { isComponentClass, registerFeatureConfigPreprocessor, type GridAdapter } from '@toolbox-web/grid-angular';\nimport '@toolbox-web/grid/features/grouping-columns';\nimport type {\n GroupingColumnsConfig as CoreGroupingColumnsConfig,\n GroupHeaderRenderParams,\n} from '@toolbox-web/grid/plugins/grouping-columns';\nexport {\n GridGroupingColumnsDirective,\n // Deprecated framework-prefixed aliases.\n type AngularColumnGroupDefinition,\n type AngularGroupingColumnsConfig,\n // Canonical (unprefixed) widening types.\n type ColumnGroupDefinition,\n type GroupingColumnsConfig,\n} from './grid-grouping-columns.directive';\nexport type { _Augmentation as _GroupingColumnsAugmentation } from '@toolbox-web/grid/features/grouping-columns';\n\n/**\n * Build a group-header renderer function from an Angular component class.\n * The component should accept group header inputs (id, label, columns, firstIndex, isImplicit).\n */\nfunction buildGroupHeaderRenderer(\n adapter: GridAdapter,\n componentClass: Type<unknown>,\n): (params: GroupHeaderRenderParams) => HTMLElement {\n const mount = adapter.mountComponentRenderer<GroupHeaderRenderParams>(componentClass, (p) => ({\n id: p.id,\n label: p.label,\n columns: p.columns,\n firstIndex: p.firstIndex,\n isImplicit: p.isImplicit,\n }));\n return (params) => mount(params).hostElement;\n}\n\n// Bridge any Angular component classes embedded in the user-supplied config\n// (e.g. group-header renderers) to plain renderer functions before the core\n// plugin factory consumes the config. Without this, raw component classes\n// would be invoked without `new`, causing runtime errors.\nregisterFeatureConfigPreprocessor('groupingColumns', (config, adapter) => {\n if (!config || typeof config !== 'object') return config;\n const cfg = config as CoreGroupingColumnsConfig;\n const processed = { ...cfg };\n let changed = false;\n\n // Bridge top-level groupHeaderRenderer component class\n if (cfg.groupHeaderRenderer && isComponentClass(cfg.groupHeaderRenderer)) {\n processed.groupHeaderRenderer = buildGroupHeaderRenderer(adapter, cfg.groupHeaderRenderer);\n changed = true;\n }\n\n // Bridge per-group renderer component classes inside columnGroups\n if (Array.isArray(cfg.columnGroups)) {\n let groupChanged = false;\n const mappedGroups = cfg.columnGroups.map((def) => {\n if (def.renderer && isComponentClass(def.renderer)) {\n groupChanged = true;\n return { ...def, renderer: buildGroupHeaderRenderer(adapter, def.renderer) };\n }\n return def;\n });\n if (groupChanged) {\n processed.columnGroups = mappedGroups;\n changed = true;\n }\n }\n\n return changed ? processed : cfg;\n});\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;AAAA;;;;;;AAMG;AA2CH;;;;AAIG;MAKU,4BAA4B,CAAA;AACtB,IAAA,UAAU,GAAG,MAAM,EAAC,UAA2B,EAAC;IAExD,eAAe,GAAG,KAAK,CAAA,IAAA,SAAA,GAAA,CAAA,SAAA,EAAA,EAAA,SAAA,EAAA,iBAAA,EAAA,CAAA,8BAAA,EAAA,CAAA,CAAmC;AAEnE,IAAA,WAAA,GAAA;AACE,QAAA,oBAAoB,CAAC,IAAI,CAAC,UAAU,CAAC,aAAa,EAAE,iBAAiB,EAAE,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;IACtG;IAEA,WAAW,GAAA;QACT,sBAAsB,CAAC,IAAI,CAAC,UAAU,CAAC,aAAa,EAAE,iBAAiB,CAAC;IAC1E;uGAXW,4BAA4B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;2FAA5B,4BAA4B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,2BAAA,EAAA,MAAA,EAAA,EAAA,eAAA,EAAA,EAAA,iBAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,iBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA;;2FAA5B,4BAA4B,EAAA,UAAA,EAAA,CAAA;kBAJxC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,2BAA2B;AACrC,oBAAA,UAAU,EAAE,IAAI;AACjB,iBAAA;;;ACzDD;;;;;;;;;;;;;AAaG;AAoBH;;;AAGG;AACH,SAAS,wBAAwB,CAC/B,OAAoB,EACpB,cAA6B,EAAA;AAE7B,IAAA,MAAM,KAAK,GAAG,OAAO,CAAC,sBAAsB,CAA0B,cAAc,EAAE,CAAC,CAAC,MAAM;QAC5F,EAAE,EAAE,CAAC,CAAC,EAAE;QACR,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,OAAO,EAAE,CAAC,CAAC,OAAO;QAClB,UAAU,EAAE,CAAC,CAAC,UAAU;QACxB,UAAU,EAAE,CAAC,CAAC,UAAU;AACzB,KAAA,CAAC,CAAC;IACH,OAAO,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,CAAC,CAAC,WAAW;AAC9C;AAEA;AACA;AACA;AACA;AACA,iCAAiC,CAAC,iBAAiB,EAAE,CAAC,MAAM,EAAE,OAAO,KAAI;AACvE,IAAA,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;AAAE,QAAA,OAAO,MAAM;IACxD,MAAM,GAAG,GAAG,MAAmC;AAC/C,IAAA,MAAM,SAAS,GAAG,EAAE,GAAG,GAAG,EAAE;IAC5B,IAAI,OAAO,GAAG,KAAK;;IAGnB,IAAI,GAAG,CAAC,mBAAmB,IAAI,gBAAgB,CAAC,GAAG,CAAC,mBAAmB,CAAC,EAAE;QACxE,SAAS,CAAC,mBAAmB,GAAG,wBAAwB,CAAC,OAAO,EAAE,GAAG,CAAC,mBAAmB,CAAC;QAC1F,OAAO,GAAG,IAAI;IAChB;;IAGA,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE;QACnC,IAAI,YAAY,GAAG,KAAK;QACxB,MAAM,YAAY,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,GAAG,KAAI;YAChD,IAAI,GAAG,CAAC,QAAQ,IAAI,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;gBAClD,YAAY,GAAG,IAAI;AACnB,gBAAA,OAAO,EAAE,GAAG,GAAG,EAAE,QAAQ,EAAE,wBAAwB,CAAC,OAAO,EAAE,GAAG,CAAC,QAAQ,CAAC,EAAE;YAC9E;AACA,YAAA,OAAO,GAAG;AACZ,QAAA,CAAC,CAAC;QACF,IAAI,YAAY,EAAE;AAChB,YAAA,SAAS,CAAC,YAAY,GAAG,YAAY;YACrC,OAAO,GAAG,IAAI;QAChB;IACF;IAEA,OAAO,OAAO,GAAG,SAAS,GAAG,GAAG;AAClC,CAAC,CAAC;;ACpFF;;AAEG;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toolbox-web-grid-angular-features-grouping-rows.mjs","sources":["../../../../libs/grid-angular/features/grouping-rows/src/grid-grouping-rows.directive.ts","../../../../libs/grid-angular/features/grouping-rows/src/index.ts","../../../../libs/grid-angular/features/grouping-rows/src/toolbox-web-grid-angular-features-grouping-rows.ts"],"sourcesContent":["/**\n * `GridGroupingRowsDirective` — owns `[groupingRows]` and the group\n * toggle/expand/collapse outputs on `<tbw-grid>`. See\n * `GridFilteringDirective` for the full rationale.\n *\n * @category Directive\n */\nimport { Directive, ElementRef, inject, input, OnDestroy, OnInit, output, type Type } from '@angular/core';\nimport type { DataGridElement } from '@toolbox-web/grid';\nimport { claimEvent, registerFeatureClaim, unclaimEvent, unregisterFeatureClaim } from '@toolbox-web/grid-angular';\nimport type {\n
|
|
1
|
+
{"version":3,"file":"toolbox-web-grid-angular-features-grouping-rows.mjs","sources":["../../../../libs/grid-angular/features/grouping-rows/src/grid-grouping-rows.directive.ts","../../../../libs/grid-angular/features/grouping-rows/src/index.ts","../../../../libs/grid-angular/features/grouping-rows/src/toolbox-web-grid-angular-features-grouping-rows.ts"],"sourcesContent":["/**\n * `GridGroupingRowsDirective` — owns `[groupingRows]` and the group\n * toggle/expand/collapse outputs on `<tbw-grid>`. See\n * `GridFilteringDirective` for the full rationale.\n *\n * @category Directive\n */\nimport { Directive, ElementRef, inject, input, OnDestroy, OnInit, output, type Type } from '@angular/core';\nimport type { DataGridElement } from '@toolbox-web/grid';\nimport { claimEvent, registerFeatureClaim, unclaimEvent, unregisterFeatureClaim } from '@toolbox-web/grid-angular';\nimport type {\n GroupingRowsConfig as CoreGroupingRowsConfig,\n GroupCollapseDetail,\n GroupExpandDetail,\n GroupRowRenderParams,\n GroupToggleDetail,\n} from '@toolbox-web/grid/plugins/grouping-rows';\n\n/**\n * Grouping-rows config widened to accept an Angular component class as\n * `groupRowRenderer`.\n *\n * Component instances receive the {@link GroupRowRenderParams} fields as\n * inputs (`key`, `value`, `depth`, `rows`, `expanded`, `toggleExpand`).\n *\n * @since 1.7.0\n */\nexport type GroupingRowsConfig = Omit<CoreGroupingRowsConfig, 'groupRowRenderer'> & {\n groupRowRenderer?: CoreGroupingRowsConfig['groupRowRenderer'] | Type<unknown>;\n};\n\n// ── Deprecated framework-prefixed alias ─────────────────────────────────\n/** @deprecated Use {@link GroupingRowsConfig} instead. */\nexport type AngularGroupingRowsConfig = GroupingRowsConfig;\n\n/**\n * Owns the binding(s) `[groupingRows], [groupToggle], [groupExpand], [groupCollapse]` on `<tbw-grid>` for the matching feature plugin. See `GridFilteringDirective` for the full rationale.\n *\n * @category Directive\n */\n@Directive({\n selector: 'tbw-grid[groupingRows], tbw-grid[groupToggle], tbw-grid[groupExpand], tbw-grid[groupCollapse]',\n standalone: true,\n})\nexport class GridGroupingRowsDirective implements OnInit, OnDestroy {\n private readonly elementRef = inject(ElementRef<DataGridElement>);\n\n readonly groupingRows = input<GroupingRowsConfig>();\n readonly groupToggle = output<GroupToggleDetail>();\n readonly groupExpand = output<GroupExpandDetail>();\n readonly groupCollapse = output<GroupCollapseDetail>();\n\n private readonly listeners = new Map<string, (e: Event) => void>();\n private static readonly EVENTS = ['group-toggle', 'group-expand', 'group-collapse'] as const;\n\n constructor() {\n const grid = this.elementRef.nativeElement;\n registerFeatureClaim(grid, 'groupingRows', () => this.groupingRows());\n for (const ev of GridGroupingRowsDirective.EVENTS) claimEvent(grid, ev);\n }\n\n ngOnInit(): void {\n const grid = this.elementRef.nativeElement;\n const wire = <T>(name: string, out: { emit: (v: T) => void }): void => {\n const l = (e: Event): void => out.emit((e as CustomEvent<T>).detail);\n grid.addEventListener(name, l);\n this.listeners.set(name, l);\n };\n wire<GroupToggleDetail>('group-toggle', this.groupToggle);\n wire<GroupExpandDetail>('group-expand', this.groupExpand);\n wire<GroupCollapseDetail>('group-collapse', this.groupCollapse);\n }\n\n ngOnDestroy(): void {\n const grid = this.elementRef.nativeElement;\n for (const [name, l] of this.listeners) grid.removeEventListener(name, l);\n this.listeners.clear();\n unregisterFeatureClaim(grid, 'groupingRows');\n for (const ev of GridGroupingRowsDirective.EVENTS) unclaimEvent(grid, ev);\n }\n}\n","/**\n * Row grouping feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `groupingRows` input on Grid directive.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/grouping-rows';\n *\n * <tbw-grid [groupingRows]=\"{ groupBy: ['department'] }\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport { isComponentClass, registerFeatureConfigPreprocessor } from '@toolbox-web/grid-angular';\nimport '@toolbox-web/grid/features/grouping-rows';\nimport type {\n GroupingRowsConfig as CoreGroupingRowsConfig,\n GroupRowRenderParams,\n} from '@toolbox-web/grid/plugins/grouping-rows';\nexport {\n GridGroupingRowsDirective,\n type AngularGroupingRowsConfig,\n type GroupingRowsConfig,\n} from './grid-grouping-rows.directive';\nexport type { _Augmentation as _GroupingRowsAugmentation } from '@toolbox-web/grid/features/grouping-rows';\n\n// Bridge any Angular component classes embedded in the user-supplied config\n// (e.g. group-row renderer) to plain renderer functions before the core\n// plugin factory consumes the config.\nregisterFeatureConfigPreprocessor('groupingRows', (config, adapter) => {\n if (!config || typeof config !== 'object') return config;\n const cfg = config as CoreGroupingRowsConfig;\n if (cfg.groupRowRenderer && isComponentClass(cfg.groupRowRenderer)) {\n const mount = adapter.mountComponentRenderer<GroupRowRenderParams>(cfg.groupRowRenderer, (p) => ({\n key: p.key,\n value: p.value,\n depth: p.depth,\n rows: p.rows,\n expanded: p.expanded,\n toggleExpand: p.toggleExpand,\n }));\n return { ...cfg, groupRowRenderer: (params: GroupRowRenderParams) => mount(params).hostElement };\n }\n return cfg;\n});\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { registerFeatureClaim, claimEvent, unregisterFeatureClaim, unclaimEvent, registerDetailRendererBridge, getDetailTemplate, registerTemplateBridge } from '@toolbox-web/grid-angular';
|
|
1
|
+
import { registerFeatureClaim, claimEvent, unregisterFeatureClaim, unclaimEvent, registerDetailRendererBridge, getDetailTemplate, registerTemplateBridge, registerFeatureConfigPreprocessor, isComponentClass } from '@toolbox-web/grid-angular';
|
|
2
2
|
export { GridDetailView, getDetailTemplate } from '@toolbox-web/grid-angular';
|
|
3
3
|
import '@toolbox-web/grid/features/master-detail';
|
|
4
4
|
import * as i0 from '@angular/core';
|
|
@@ -124,6 +124,38 @@ registerTemplateBridge(({ grid }) => {
|
|
|
124
124
|
}
|
|
125
125
|
existingPlugin.refreshDetailRenderer?.();
|
|
126
126
|
});
|
|
127
|
+
/**
|
|
128
|
+
* Bridge any Angular component class used as `masterDetail.detailRenderer` to
|
|
129
|
+
* a plain `(row, rowIndex) => HTMLElement` function before the core plugin
|
|
130
|
+
* factory consumes the config. Without this preprocessor, a component class
|
|
131
|
+
* passed as `detailRenderer` would be invoked as a function at render time
|
|
132
|
+
* and crash. Light-DOM `<tbw-grid-detail>` templates continue to win via
|
|
133
|
+
* `parseLightDomDetail` inside the plugin.
|
|
134
|
+
*
|
|
135
|
+
* @since 1.7.1
|
|
136
|
+
*/
|
|
137
|
+
registerFeatureConfigPreprocessor('masterDetail', (config, adapter) => {
|
|
138
|
+
if (!config || typeof config !== 'object')
|
|
139
|
+
return config;
|
|
140
|
+
const cfg = config;
|
|
141
|
+
if (!isComponentClass(cfg.detailRenderer))
|
|
142
|
+
return config;
|
|
143
|
+
const componentClass = cfg.detailRenderer;
|
|
144
|
+
const mount = adapter.mountComponentRenderer(componentClass, (ctx) => ({
|
|
145
|
+
row: ctx.row,
|
|
146
|
+
rowIndex: ctx.rowIndex,
|
|
147
|
+
}));
|
|
148
|
+
const cached = new Map();
|
|
149
|
+
const detailRenderer = (row, rowIndex) => {
|
|
150
|
+
const existing = cached.get(row);
|
|
151
|
+
if (existing)
|
|
152
|
+
return existing;
|
|
153
|
+
const { hostElement } = mount({ row, rowIndex });
|
|
154
|
+
cached.set(row, hostElement);
|
|
155
|
+
return hostElement;
|
|
156
|
+
};
|
|
157
|
+
return { ...cfg, detailRenderer };
|
|
158
|
+
});
|
|
127
159
|
|
|
128
160
|
/**
|
|
129
161
|
* Generated bundle index. Do not edit.
|
|
@@ -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 `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 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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"}
|
|
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, type Type } from '@angular/core';\nimport type { DataGridElement } from '@toolbox-web/grid';\nimport { claimEvent, registerFeatureClaim, unclaimEvent, unregisterFeatureClaim } from '@toolbox-web/grid-angular';\nimport type {\n MasterDetailConfig as CoreMasterDetailConfig,\n DetailExpandDetail,\n} from '@toolbox-web/grid/plugins/master-detail';\n\n/**\n * Angular-specific master-detail config that allows an Angular component class\n * as `detailRenderer`.\n *\n * Extends the core `MasterDetailConfig` to accept a `Type<unknown>` for\n * `detailRenderer` in addition to the vanilla\n * `(row, rowIndex) => HTMLElement | string` signature. Bridging to vanilla\n * DOM is handled by the side-effect import\n * `@toolbox-web/grid-angular/features/master-detail`.\n *\n * Re-exported from the feature entry under the same name as the core type\n * so Angular consumers see a single canonical `MasterDetailConfig` from\n * `@toolbox-web/grid-angular/features/master-detail`.\n *\n * @since 1.7.1\n */\nexport type MasterDetailConfig = Omit<CoreMasterDetailConfig, 'detailRenderer'> & {\n detailRenderer?: CoreMasterDetailConfig['detailRenderer'] | Type<unknown>;\n};\n\n/**\n * Owns the binding(s) `[masterDetail], [detailExpand]` on `<tbw-grid>` for the matching feature plugin. See `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 { Type } from '@angular/core';\nimport {\n getDetailTemplate,\n isComponentClass,\n registerDetailRendererBridge,\n registerFeatureConfigPreprocessor,\n registerTemplateBridge,\n type GridAdapter,\n type GridDetailContext,\n} from '@toolbox-web/grid-angular';\nimport '@toolbox-web/grid/features/master-detail';\nimport type { MasterDetailConfig } from './grid-master-detail.directive';\nexport { GridMasterDetailDirective } from './grid-master-detail.directive';\nexport type { MasterDetailConfig } 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 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/**\n * Bridge any Angular component class used as `masterDetail.detailRenderer` to\n * a plain `(row, rowIndex) => HTMLElement` function before the core plugin\n * factory consumes the config. Without this preprocessor, a component class\n * passed as `detailRenderer` would be invoked as a function at render time\n * and crash. Light-DOM `<tbw-grid-detail>` templates continue to win via\n * `parseLightDomDetail` inside the plugin.\n *\n * @since 1.7.1\n */\nregisterFeatureConfigPreprocessor('masterDetail', (config, adapter) => {\n if (!config || typeof config !== 'object') return config;\n const cfg = config as MasterDetailConfig;\n if (!isComponentClass(cfg.detailRenderer)) return config;\n\n const componentClass = cfg.detailRenderer as Type<unknown>;\n const mount = adapter.mountComponentRenderer<{ row: unknown; rowIndex: number }>(componentClass, (ctx) => ({\n row: ctx.row,\n rowIndex: ctx.rowIndex,\n }));\n const cached = new Map<unknown, HTMLElement>();\n const detailRenderer: MasterDetailConfig['detailRenderer'] = (row, rowIndex) => {\n const existing = cached.get(row);\n if (existing) return existing;\n const { hostElement } = mount({ row, rowIndex });\n cached.set(row, hostElement);\n return hostElement;\n };\n return { ...cfg, detailRenderer };\n});\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toolbox-web-grid-angular-features-pinned-rows.mjs","sources":["../../../../libs/grid-angular/features/pinned-rows/src/cached-panel-renderer.ts","../../../../libs/grid-angular/features/pinned-rows/src/grid-pinned-rows.directive.ts","../../../../libs/grid-angular/features/pinned-rows/src/index.ts","../../../../libs/grid-angular/features/pinned-rows/src/toolbox-web-grid-angular-features-pinned-rows.ts"],"sourcesContent":["/**\n * @internal\n *\n * Cached panel-renderer factory for the Angular pinned-rows adapter (#354).\n *\n * Extracted into its own module so the pure caching logic can be unit-tested\n * without depending on the heavy `@toolbox-web/grid-angular` barrel (which\n * pulls in every directive at module-load and requires substantial Angular\n * DI mocking).\n *\n * @since 1.7.0\n */\nimport type { ComponentRef, Type } from '@angular/core';\nimport type { PinnedRowsContext } from '@toolbox-web/grid/plugins/pinned-rows';\n\n/**\n * Minimal structural shape of the adapter API used by {@link buildCachedPanelRenderer}.\n * Mirrors `GridAdapter.mountComponentRenderer` without the rest of the surface\n * so tests can pass a stub.\n *\n * @internal\n */\nexport interface PanelRendererAdapter {\n mountComponentRenderer<TCtx>(\n componentClass: Type<unknown>,\n mapInputs: (ctx: TCtx) => Record<string, unknown>,\n ): (ctx: TCtx) => { hostElement: HTMLElement; componentRef: ComponentRef<unknown> };\n}\n\n/**\n * Map a {@link PinnedRowsContext} to the Angular component input bag.\n * Centralized so both the initial `mountComponentRenderer` call and the\n * per-call input-refresh path stay in sync.\n *\n * @internal\n */\nexport function mapPinnedRowsInputs(ctx: PinnedRowsContext): Record<string, unknown> {\n return {\n totalRows: ctx.totalRows,\n filteredRows: ctx.filteredRows,\n selectedRows: ctx.selectedRows,\n columns: ctx.columns,\n rows: ctx.rows,\n grid: ctx.grid,\n };\n}\n\n/**\n * Build a pinned-rows panel renderer function from an Angular component class.\n * The component should accept inputs from {@link PinnedRowsContext}.\n *\n * Caches the mounted component across renders — the pinned-rows plugin\n * (`renderPanelSlot`) reference-checks renderer outputs to skip DOM mutation\n * when nothing changed. On subsequent calls inputs are refreshed via\n * `componentRef.setInput()` instead of mounting a fresh component.\n *\n * The cached `ComponentRef` is tracked in the adapter's render pool, so it is\n * destroyed automatically when the grid is disposed.\n *\n * @internal\n */\nexport function buildCachedPanelRenderer(\n adapter: PanelRendererAdapter,\n componentClass: Type<unknown>,\n): (ctx: PinnedRowsContext) => HTMLElement {\n const mount = adapter.mountComponentRenderer<PinnedRowsContext>(componentClass, mapPinnedRowsInputs);\n let cached: { hostElement: HTMLElement; componentRef: ComponentRef<unknown> } | null = null;\n return (ctx) => {\n if (!cached) {\n cached = mount(ctx);\n return cached.hostElement;\n }\n const inputs = mapPinnedRowsInputs(ctx);\n for (const name of Object.keys(inputs)) {\n cached.componentRef.setInput(name, inputs[name]);\n }\n cached.componentRef.changeDetectorRef.detectChanges();\n return cached.hostElement;\n };\n}\n","/**\n * `GridPinnedRowsDirective` — owns `[pinnedRows]` on `<tbw-grid>`. No\n * event outputs. See `GridFilteringDirective` for the full rationale.\n *\n * @category Directive\n */\nimport { Directive, ElementRef, inject, input, OnDestroy } from '@angular/core';\nimport type { DataGridElement } from '@toolbox-web/grid';\nimport { registerFeatureClaim, unregisterFeatureClaim } from '@toolbox-web/grid-angular';\nimport type { PinnedRowsConfig } from '@toolbox-web/grid/plugins/pinned-rows';\n\n/**\n * Owns the binding(s) `[pinnedRows]` on `<tbw-grid>` for the matching feature plugin. See `GridFilteringDirective` for the full rationale.\n *\n * @category Directive\n */\n@Directive({\n selector: 'tbw-grid[pinnedRows]',\n standalone: true,\n})\nexport class GridPinnedRowsDirective implements OnDestroy {\n private readonly elementRef = inject(ElementRef<DataGridElement>);\n\n readonly pinnedRows = input<boolean | PinnedRowsConfig>();\n\n constructor() {\n registerFeatureClaim(this.elementRef.nativeElement, 'pinnedRows', () => this.pinnedRows());\n }\n\n ngOnDestroy(): void {\n unregisterFeatureClaim(this.elementRef.nativeElement, 'pinnedRows');\n }\n}\n","/**\n * Pinned rows feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `pinnedRows` input on Grid directive.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/pinned-rows';\n *\n * <tbw-grid [pinnedRows]=\"{ bottom: [{ type: 'aggregation' }] }\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport type { Type } from '@angular/core';\nimport { isComponentClass, registerFeatureConfigPreprocessor, type GridAdapter } from '@toolbox-web/grid-angular';\nimport '@toolbox-web/grid/features/pinned-rows';\nimport type {\n PinnedRowsConfig,\n PinnedRowsContext,\n PinnedRowSlot,\n ZonedPanelRender,\n} from '@toolbox-web/grid/plugins/pinned-rows';\nimport { buildCachedPanelRenderer } from './cached-panel-renderer';\nexport { GridPinnedRowsDirective } from './grid-pinned-rows.directive';\nexport type { _Augmentation as _PinnedRowsAugmentation } from '@toolbox-web/grid/features/pinned-rows';\n\n/**\n * Build a pinned-rows panel renderer function from an Angular component class.\n * Thin wrapper around {@link buildCachedPanelRenderer} that fixes the adapter\n * type to the concrete `GridAdapter`.\n */\nfunction buildPanelRenderer(\n adapter: GridAdapter,\n componentClass: Type<unknown>,\n): (ctx: PinnedRowsContext) => HTMLElement {\n return buildCachedPanelRenderer(adapter, componentClass);\n}\n\n/**\n * Bridge a single pinned-row slot. Aggregation slots (no `render`) pass through.\n * For panel slots, wrap any component-class `render` (or array entry's `render`)\n * with the Angular component renderer.\n */\nfunction bridgeSlot(adapter: GridAdapter, slot: PinnedRowSlot): PinnedRowSlot {\n if (!('render' in slot) || slot.render == null) return slot;\n\n if (Array.isArray(slot.render)) {\n const zoned: ZonedPanelRender[] = slot.render.map((entry) => {\n if (entry?.render == null) return entry;\n if (isComponentClass(entry.render)) {\n return { zone: entry.zone, render: buildPanelRenderer(adapter, entry.render as Type<unknown>) };\n }\n return entry;\n });\n return { ...slot, render: zoned };\n }\n\n if (isComponentClass(slot.render)) {\n return { ...slot, render: buildPanelRenderer(adapter, slot.render as Type<unknown>) };\n }\n return slot;\n}\n\n// Bridge any Angular component classes embedded in `customPanels` and `slots`\n// to plain renderer functions before the core plugin factory consumes the config.\nregisterFeatureConfigPreprocessor('pinnedRows', (config, adapter) => {\n if (!config || typeof config !== 'object') return config;\n const cfg = config as PinnedRowsConfig;\n let next: PinnedRowsConfig = cfg;\n\n // Legacy customPanels bridging.\n if (Array.isArray(cfg.customPanels)) {\n const hasComponentRender = cfg.customPanels.some((panel) => isComponentClass(panel.render));\n if (hasComponentRender) {\n next = {\n ...next,\n customPanels: cfg.customPanels.map((panel) => {\n if (!isComponentClass(panel.render)) return panel;\n return { ...panel, render: buildPanelRenderer(adapter, panel.render) };\n }),\n };\n }\n }\n\n // Slots[] bridging \\u2014 each PanelSlot.render may be a component class, or an\n // array of { zone?, render } where each render may be a component class.\n if (Array.isArray(cfg.slots)) {\n next = { ...next, slots: cfg.slots.map((slot) => bridgeSlot(adapter, slot)) };\n }\n\n return next;\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-pinned-rows.mjs","sources":["../../../../libs/grid-angular/features/pinned-rows/src/cached-panel-renderer.ts","../../../../libs/grid-angular/features/pinned-rows/src/grid-pinned-rows.directive.ts","../../../../libs/grid-angular/features/pinned-rows/src/index.ts","../../../../libs/grid-angular/features/pinned-rows/src/toolbox-web-grid-angular-features-pinned-rows.ts"],"sourcesContent":["/**\n * @internal\n *\n * Cached panel-renderer factory for the Angular pinned-rows adapter (#354).\n *\n * Extracted into its own module so the pure caching logic can be unit-tested\n * without depending on the heavy `@toolbox-web/grid-angular` barrel (which\n * pulls in every directive at module-load and requires substantial Angular\n * DI mocking).\n *\n * @since 1.7.0\n */\nimport type { ComponentRef, Type } from '@angular/core';\nimport type { PinnedRowsContext } from '@toolbox-web/grid/plugins/pinned-rows';\n\n/**\n * Minimal structural shape of the adapter API used by {@link buildCachedPanelRenderer}.\n * Mirrors `GridAdapter.mountComponentRenderer` without the rest of the surface\n * so tests can pass a stub.\n *\n * @internal\n */\nexport interface PanelRendererAdapter {\n mountComponentRenderer<TCtx>(\n componentClass: Type<unknown>,\n mapInputs: (ctx: TCtx) => Record<string, unknown>,\n ): (ctx: TCtx) => { hostElement: HTMLElement; componentRef: ComponentRef<unknown> };\n}\n\n/**\n * Map a {@link PinnedRowsContext} to the Angular component input bag.\n * Centralized so both the initial `mountComponentRenderer` call and the\n * per-call input-refresh path stay in sync.\n *\n * @internal\n */\nexport function mapPinnedRowsInputs(ctx: PinnedRowsContext): Record<string, unknown> {\n return {\n totalRows: ctx.totalRows,\n filteredRows: ctx.filteredRows,\n selectedRows: ctx.selectedRows,\n columns: ctx.columns,\n rows: ctx.rows,\n grid: ctx.grid,\n };\n}\n\n/**\n * Build a pinned-rows panel renderer function from an Angular component class.\n * The component should accept inputs from {@link PinnedRowsContext}.\n *\n * Caches the mounted component across renders — the pinned-rows plugin\n * (`renderPanelSlot`) reference-checks renderer outputs to skip DOM mutation\n * when nothing changed. On subsequent calls inputs are refreshed via\n * `componentRef.setInput()` instead of mounting a fresh component.\n *\n * The cached `ComponentRef` is tracked in the adapter's render pool, so it is\n * destroyed automatically when the grid is disposed.\n *\n * @internal\n */\nexport function buildCachedPanelRenderer(\n adapter: PanelRendererAdapter,\n componentClass: Type<unknown>,\n): (ctx: PinnedRowsContext) => HTMLElement {\n const mount = adapter.mountComponentRenderer<PinnedRowsContext>(componentClass, mapPinnedRowsInputs);\n let cached: { hostElement: HTMLElement; componentRef: ComponentRef<unknown> } | null = null;\n return (ctx) => {\n if (!cached) {\n cached = mount(ctx);\n return cached.hostElement;\n }\n const inputs = mapPinnedRowsInputs(ctx);\n for (const name of Object.keys(inputs)) {\n cached.componentRef.setInput(name, inputs[name]);\n }\n cached.componentRef.changeDetectorRef.detectChanges();\n return cached.hostElement;\n };\n}\n","/**\n * `GridPinnedRowsDirective` — owns `[pinnedRows]` on `<tbw-grid>`. No\n * event outputs. See `GridFilteringDirective` for the full rationale.\n *\n * @category Directive\n */\nimport { Directive, ElementRef, inject, input, OnDestroy, type Type } from '@angular/core';\nimport type { DataGridElement } from '@toolbox-web/grid';\nimport { registerFeatureClaim, unregisterFeatureClaim } from '@toolbox-web/grid-angular';\nimport type {\n PinnedRowsConfig as CorePinnedRowsConfig,\n PanelZone,\n PinnedRowsContext,\n} from '@toolbox-web/grid/plugins/pinned-rows';\n\n/**\n * Angular-shaped panel-slot render: a renderer function (vanilla), an Angular\n * component class, or an array of zoned entries that each accept the same.\n *\n * Component instances receive the {@link PinnedRowsContext} fields as inputs.\n *\n * @since 1.7.1\n */\nexport type PanelRender = ((ctx: PinnedRowsContext) => HTMLElement | null) | Type<unknown>;\n\n/**\n * Angular-shaped zoned panel render entry.\n *\n * @since 1.7.1\n */\nexport interface ZonedPanelRender {\n zone?: PanelZone;\n render: PanelRender;\n}\n\n/**\n * Angular-shaped pinned-rows panel slot.\n *\n * @since 1.7.1\n */\nexport interface PanelSlot {\n id?: string;\n position?: 'top' | 'bottom';\n render: PanelRender | ZonedPanelRender[];\n}\n\ntype CoreSlot = NonNullable<CorePinnedRowsConfig['slots']>[number];\ntype CoreAggregationSlot = Exclude<CoreSlot, { render: unknown }>;\n\n/**\n * Angular-shaped pinned-rows slot \\u2014 either an aggregation slot (passthrough)\n * or a panel slot accepting Angular component classes as `render`.\n *\n * @since 1.7.1\n */\nexport type PinnedRowSlot = CoreAggregationSlot | PanelSlot;\n\n/**\n * Pinned-rows config widened to accept Angular component classes as `render`\n * inside `slots[]` and `customPanels[]`. Bridging to vanilla DOM is handled\n * by the side-effect import `@toolbox-web/grid-angular/features/pinned-rows`.\n *\n * Re-exported under the same name as the core type so Angular users see a\n * single canonical `PinnedRowsConfig` from\n * `@toolbox-web/grid-angular/features/pinned-rows`.\n *\n * @since 1.7.1\n */\nexport type PinnedRowsConfig = Omit<CorePinnedRowsConfig, 'slots' | 'customPanels'> & {\n slots?: PinnedRowSlot[];\n customPanels?: Array<{\n id: string;\n position: PanelZone;\n render: ((ctx: PinnedRowsContext) => HTMLElement) | Type<unknown>;\n }>;\n};\n\n// ── Deprecated framework-prefixed aliases ──────────────────────────────────\n// Retained for backwards compatibility. New code should use the canonical\n// (unprefixed) names above.\n\n/** @deprecated Use {@link PanelRender} instead. */\nexport type AngularPanelRender = PanelRender;\n/** @deprecated Use {@link ZonedPanelRender} instead. */\nexport type AngularZonedPanelRender = ZonedPanelRender;\n/** @deprecated Use {@link PanelSlot} instead. */\nexport type AngularPanelSlot = PanelSlot;\n/** @deprecated Use {@link PinnedRowSlot} instead. */\nexport type AngularPinnedRowSlot = PinnedRowSlot;\n/** @deprecated Use {@link PinnedRowsConfig} instead. */\nexport type AngularPinnedRowsConfig = PinnedRowsConfig;\n\n/**\n * Owns the binding(s) `[pinnedRows]` on `<tbw-grid>` for the matching feature plugin. See `GridFilteringDirective` for the full rationale.\n *\n * @category Directive\n */\n@Directive({\n selector: 'tbw-grid[pinnedRows]',\n standalone: true,\n})\nexport class GridPinnedRowsDirective implements OnDestroy {\n private readonly elementRef = inject(ElementRef<DataGridElement>);\n\n readonly pinnedRows = input<boolean | PinnedRowsConfig>();\n\n constructor() {\n registerFeatureClaim(this.elementRef.nativeElement, 'pinnedRows', () => this.pinnedRows());\n }\n\n ngOnDestroy(): void {\n unregisterFeatureClaim(this.elementRef.nativeElement, 'pinnedRows');\n }\n}\n","/**\n * Pinned rows feature for @toolbox-web/grid-angular\n *\n * Import this module to enable the `pinnedRows` input on Grid directive.\n *\n * @example\n * ```typescript\n * import '@toolbox-web/grid-angular/features/pinned-rows';\n *\n * <tbw-grid [pinnedRows]=\"{ bottom: [{ type: 'aggregation' }] }\" />\n * ```\n *\n * @packageDocumentation\n */\n\nimport type { Type } from '@angular/core';\nimport { isComponentClass, registerFeatureConfigPreprocessor, type GridAdapter } from '@toolbox-web/grid-angular';\nimport '@toolbox-web/grid/features/pinned-rows';\nimport type {\n PinnedRowsConfig as CorePinnedRowsConfig,\n PinnedRowSlot as CorePinnedRowSlot,\n ZonedPanelRender as CoreZonedPanelRender,\n PinnedRowsContext,\n} from '@toolbox-web/grid/plugins/pinned-rows';\nimport { buildCachedPanelRenderer } from './cached-panel-renderer';\nexport { GridPinnedRowsDirective } from './grid-pinned-rows.directive';\nexport type {\n // Deprecated framework-prefixed aliases \\u2014 kept for backwards compatibility.\n AngularPanelRender,\n AngularPanelSlot,\n AngularPinnedRowsConfig,\n AngularPinnedRowSlot,\n AngularZonedPanelRender,\n // Canonical (unprefixed) widening types. Same names as the core types\n // from `@toolbox-web/grid` \\u2014 these accept Angular component classes in\n // addition to the vanilla `HTMLElement`-returning renderer functions.\n PanelRender,\n PanelSlot,\n PinnedRowsConfig,\n PinnedRowSlot,\n ZonedPanelRender,\n} from './grid-pinned-rows.directive';\nexport type { _Augmentation as _PinnedRowsAugmentation } from '@toolbox-web/grid/features/pinned-rows';\n\n/**\n * Build a pinned-rows panel renderer function from an Angular component class.\n * Thin wrapper around {@link buildCachedPanelRenderer} that fixes the adapter\n * type to the concrete `GridAdapter`.\n */\nfunction buildPanelRenderer(\n adapter: GridAdapter,\n componentClass: Type<unknown>,\n): (ctx: PinnedRowsContext) => HTMLElement {\n return buildCachedPanelRenderer(adapter, componentClass);\n}\n\n/**\n * Bridge a single pinned-row slot. Aggregation slots (no `render`) pass through.\n * For panel slots, wrap any component-class `render` (or array entry's `render`)\n * with the Angular component renderer.\n */\nfunction bridgeSlot(adapter: GridAdapter, slot: CorePinnedRowSlot): CorePinnedRowSlot {\n if (!('render' in slot) || slot.render == null) return slot;\n\n if (Array.isArray(slot.render)) {\n const zoned: CoreZonedPanelRender[] = slot.render.map((entry) => {\n if (entry?.render == null) return entry;\n if (isComponentClass(entry.render)) {\n return { zone: entry.zone, render: buildPanelRenderer(adapter, entry.render as Type<unknown>) };\n }\n return entry;\n });\n return { ...slot, render: zoned };\n }\n\n if (isComponentClass(slot.render)) {\n return { ...slot, render: buildPanelRenderer(adapter, slot.render as Type<unknown>) };\n }\n return slot;\n}\n\n// Bridge any Angular component classes embedded in `customPanels` and `slots`\n// to plain renderer functions before the core plugin factory consumes the config.\nregisterFeatureConfigPreprocessor('pinnedRows', (config, adapter) => {\n if (!config || typeof config !== 'object') return config;\n const cfg = config as CorePinnedRowsConfig;\n let next: CorePinnedRowsConfig = cfg;\n\n // Legacy customPanels bridging.\n if (Array.isArray(cfg.customPanels)) {\n const hasComponentRender = cfg.customPanels.some((panel) => isComponentClass(panel.render));\n if (hasComponentRender) {\n next = {\n ...next,\n customPanels: cfg.customPanels.map((panel) => {\n if (!isComponentClass(panel.render)) return panel;\n return { ...panel, render: buildPanelRenderer(adapter, panel.render) };\n }),\n };\n }\n }\n\n // Slots[] bridging \\u2014 each PanelSlot.render may be a component class, or an\n // array of { zone?, render } where each render may be a component class.\n if (Array.isArray(cfg.slots)) {\n next = { ...next, slots: cfg.slots.map((slot) => bridgeSlot(adapter, slot)) };\n }\n\n return next;\n});\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { registerFeatureClaim, claimEvent, unregisterFeatureClaim, unclaimEvent, registerResponsiveCardRendererBridge, getResponsiveCardTemplate, registerTemplateBridge } from '@toolbox-web/grid-angular';
|
|
1
|
+
import { registerFeatureClaim, claimEvent, unregisterFeatureClaim, unclaimEvent, registerResponsiveCardRendererBridge, getResponsiveCardTemplate, registerTemplateBridge, registerFeatureConfigPreprocessor, isComponentClass } from '@toolbox-web/grid-angular';
|
|
2
2
|
import '@toolbox-web/grid/features/responsive';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
4
|
import { inject, ElementRef, input, output, Directive } from '@angular/core';
|
|
@@ -121,6 +121,35 @@ registerTemplateBridge(({ grid, adapter }) => {
|
|
|
121
121
|
}
|
|
122
122
|
existingPlugin.setCardRenderer?.(cardRenderer);
|
|
123
123
|
});
|
|
124
|
+
/**
|
|
125
|
+
* Bridge any Angular component class used as `responsive.cardRenderer` to a
|
|
126
|
+
* plain `(row, rowIndex, column?) => HTMLElement` function before the core
|
|
127
|
+
* plugin factory consumes the config. Without this preprocessor, a component
|
|
128
|
+
* class passed as `cardRenderer` would be invoked as a function at render
|
|
129
|
+
* time and crash. Light-DOM `<tbw-grid-responsive-card>` templates continue
|
|
130
|
+
* to win via the post-mount template bridge above.
|
|
131
|
+
*
|
|
132
|
+
* @since 1.7.1
|
|
133
|
+
*/
|
|
134
|
+
registerFeatureConfigPreprocessor('responsive', (config, adapter) => {
|
|
135
|
+
if (!config || typeof config !== 'object')
|
|
136
|
+
return config;
|
|
137
|
+
const cfg = config;
|
|
138
|
+
if (!isComponentClass(cfg.cardRenderer))
|
|
139
|
+
return config;
|
|
140
|
+
const componentClass = cfg.cardRenderer;
|
|
141
|
+
const mount = adapter.mountComponentRenderer(componentClass, (ctx) => ({ row: ctx.row, rowIndex: ctx.rowIndex, column: ctx.column }));
|
|
142
|
+
const cached = new Map();
|
|
143
|
+
const cardRenderer = (row, rowIndex, column) => {
|
|
144
|
+
const existing = cached.get(row);
|
|
145
|
+
if (existing)
|
|
146
|
+
return existing;
|
|
147
|
+
const { hostElement } = mount({ row, rowIndex, column });
|
|
148
|
+
cached.set(row, hostElement);
|
|
149
|
+
return hostElement;
|
|
150
|
+
};
|
|
151
|
+
return { ...cfg, cardRenderer };
|
|
152
|
+
});
|
|
124
153
|
|
|
125
154
|
/**
|
|
126
155
|
* Generated bundle index. Do not edit.
|
|
@@ -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 `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 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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"}
|
|
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, type Type } from '@angular/core';\nimport type { DataGridElement } from '@toolbox-web/grid';\nimport { claimEvent, registerFeatureClaim, unclaimEvent, unregisterFeatureClaim } from '@toolbox-web/grid-angular';\nimport type {\n ResponsivePluginConfig as CoreResponsivePluginConfig,\n ResponsiveChangeDetail,\n} from '@toolbox-web/grid/plugins/responsive';\n\n/**\n * Angular-specific responsive config that allows an Angular component class\n * as `cardRenderer`.\n *\n * Extends the core `ResponsivePluginConfig` to accept a `Type<unknown>` for\n * `cardRenderer` in addition to the vanilla\n * `(row, rowIndex, column?) => HTMLElement` signature. Bridging to vanilla\n * DOM is handled by the side-effect import\n * `@toolbox-web/grid-angular/features/responsive`.\n *\n * Re-exported from the feature entry under the same name as the core type\n * so Angular consumers see a single canonical `ResponsivePluginConfig` from\n * `@toolbox-web/grid-angular/features/responsive`.\n *\n * @since 1.7.1\n */\nexport type ResponsivePluginConfig<TRow = unknown> = Omit<CoreResponsivePluginConfig<TRow>, 'cardRenderer'> & {\n cardRenderer?: CoreResponsivePluginConfig<TRow>['cardRenderer'] | Type<unknown>;\n};\n\n/**\n * Owns the binding(s) `[responsive], [responsiveChange]` on `<tbw-grid>` for the matching feature plugin. See `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 { Type } from '@angular/core';\nimport {\n getResponsiveCardTemplate,\n isComponentClass,\n registerFeatureConfigPreprocessor,\n registerResponsiveCardRendererBridge,\n registerTemplateBridge,\n type GridAdapter,\n type GridResponsiveCardContext,\n} from '@toolbox-web/grid-angular';\nimport '@toolbox-web/grid/features/responsive';\nimport type { ResponsivePluginConfig } from './grid-responsive.directive';\nexport { GridResponsiveDirective } from './grid-responsive.directive';\nexport type { ResponsivePluginConfig } 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 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/**\n * Bridge any Angular component class used as `responsive.cardRenderer` to a\n * plain `(row, rowIndex, column?) => HTMLElement` function before the core\n * plugin factory consumes the config. Without this preprocessor, a component\n * class passed as `cardRenderer` would be invoked as a function at render\n * time and crash. Light-DOM `<tbw-grid-responsive-card>` templates continue\n * to win via the post-mount template bridge above.\n *\n * @since 1.7.1\n */\nregisterFeatureConfigPreprocessor('responsive', (config, adapter) => {\n if (!config || typeof config !== 'object') return config;\n const cfg = config as ResponsivePluginConfig;\n if (!isComponentClass(cfg.cardRenderer)) return config;\n\n const componentClass = cfg.cardRenderer as Type<unknown>;\n const mount = adapter.mountComponentRenderer<{ row: unknown; rowIndex: number; column?: unknown }>(\n componentClass,\n (ctx) => ({ row: ctx.row, rowIndex: ctx.rowIndex, column: ctx.column }),\n );\n const cached = new Map<unknown, HTMLElement>();\n const cardRenderer: NonNullable<ResponsivePluginConfig['cardRenderer']> = (row, rowIndex, column) => {\n const existing = cached.get(row);\n if (existing) return existing;\n const { hostElement } = mount({ row, rowIndex, column });\n cached.set(row, hostElement);\n return hostElement;\n };\n return { ...cfg, cardRenderer };\n});\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,28 @@
|
|
|
1
1
|
import * as _angular_core from '@angular/core';
|
|
2
|
-
import { OnInit, OnDestroy, Signal } from '@angular/core';
|
|
3
|
-
import { FilterConfig, FilterChangeDetail, FilterModel, BlankMode } from '@toolbox-web/grid/plugins/filtering';
|
|
2
|
+
import { OnInit, OnDestroy, Type, Signal } from '@angular/core';
|
|
3
|
+
import { FilterConfig as FilterConfig$1, FilterChangeDetail, FilterModel, BlankMode } from '@toolbox-web/grid/plugins/filtering';
|
|
4
4
|
export { _Augmentation as _FilteringAugmentation } from '@toolbox-web/grid/features/filtering';
|
|
5
|
+
import { FilterPanel } from '@toolbox-web/grid-angular';
|
|
5
6
|
export { BaseFilterPanel } from '@toolbox-web/grid-angular';
|
|
6
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Angular-specific filter config that allows an Angular component class as
|
|
10
|
+
* the plugin-level `filterPanelRenderer`.
|
|
11
|
+
*
|
|
12
|
+
* Extends the core `FilterConfig` to accept a `Type<FilterPanel>` for
|
|
13
|
+
* `filterPanelRenderer` in addition to the vanilla
|
|
14
|
+
* `(container, params) => void` signature. Bridging to vanilla DOM is handled
|
|
15
|
+
* by the side-effect import `@toolbox-web/grid-angular/features/filtering`.
|
|
16
|
+
*
|
|
17
|
+
* Re-exported from the feature entry under the same name as the core type
|
|
18
|
+
* so Angular consumers see a single canonical `FilterConfig` from
|
|
19
|
+
* `@toolbox-web/grid-angular/features/filtering`.
|
|
20
|
+
*
|
|
21
|
+
* @since 1.7.1
|
|
22
|
+
*/
|
|
23
|
+
type FilterConfig<TRow = any> = Omit<FilterConfig$1<TRow>, 'filterPanelRenderer'> & {
|
|
24
|
+
filterPanelRenderer?: FilterConfig$1<TRow>['filterPanelRenderer'] | Type<FilterPanel>;
|
|
25
|
+
};
|
|
7
26
|
/**
|
|
8
27
|
* Owns the `[filtering]` input and `(filterChange)` output on `<tbw-grid>`.
|
|
9
28
|
*
|
|
@@ -207,5 +226,5 @@ interface FilteringMethods {
|
|
|
207
226
|
declare function injectGridFiltering(selector?: string): FilteringMethods;
|
|
208
227
|
|
|
209
228
|
export { GridFilteringDirective, injectGridFiltering };
|
|
210
|
-
export type { FilteringMethods };
|
|
229
|
+
export type { FilterConfig, FilteringMethods };
|
|
211
230
|
//# sourceMappingURL=toolbox-web-grid-angular-features-filtering.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toolbox-web-grid-angular-features-filtering.d.ts","sources":["../../../../libs/grid-angular/features/filtering/src/grid-filtering.directive.ts","../../../../libs/grid-angular/features/filtering/src/index.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"toolbox-web-grid-angular-features-filtering.d.ts","sources":["../../../../libs/grid-angular/features/filtering/src/grid-filtering.directive.ts","../../../../libs/grid-angular/features/filtering/src/index.ts"],"mappings":";;;;;;;AAuDA;;;;;;;;;;;;;;AAcG;KAES,YAAY,eAAe,IAAI,CAACA,cAAgB;AAC1D,0BAAsBA,cAAgB,gCAAgC,IAAI,CAAC,WAAW;;AAGxF;;;;;;;AAOG;AACH,cAIa,sBAAuB,YAAW,MAAM,EAAE,SAAS;AAC9D;AAEA;;;;;;;;;AASG;wBAEe,aAAA,CAAA,WAAA,WAAA,YAAA;AAElB;;;;;;;AAOG;2BACkB,aAAA,CAAA,gBAAA,CAAA,kBAAA;;;AAiBrB;AAQA;oDAjDW,sBAAsB;sDAAtB,sBAAsB;AA6DlC;;ACpJD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkDG;;AA8EH;;;;AAIG;UACc,gBAAgB;AAC/B;;;;;AAKG;AACH,uCAAmC,IAAI,CAAC,WAAW;;AAAiD;AAEpG;;AAEG;kCAC2B,WAAW;AAEzC;;AAEG;AACH,sBAAkB,WAAW;AAE7B;;;AAGG;8BACuB,WAAW;;AAAkC;AAEvE;;;AAGG;AACH;;AAAgD;AAEhD;;;AAGG;;;AAC6D;AAEhE;;AAEG;AACH;AAEA;;AAEG;;AAGH;;AAEG;;AAGH;;AAEG;AACH,2BAAuB,WAAW;AAElC;;AAEG;AACH,qCAAiC,SAAS;AAE1C;;AAEG;6CACsC,SAAS;AAElD;;AAEG;AACH,aAAS,MAAM;AAChB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCG;AACH,iBAAgB,mBAAmB,qBAAyB,gBAAgB;;;;","names":["CoreFilterConfig"]}
|
|
@@ -1,30 +1,34 @@
|
|
|
1
1
|
export { _Augmentation as _GroupingColumnsAugmentation } from '@toolbox-web/grid/features/grouping-columns';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
3
|
import { OnDestroy, Type } from '@angular/core';
|
|
4
|
-
import { GroupingColumnsConfig, ColumnGroupDefinition } from '@toolbox-web/grid/plugins/grouping-columns';
|
|
4
|
+
import { GroupingColumnsConfig as GroupingColumnsConfig$1, ColumnGroupDefinition as ColumnGroupDefinition$1 } from '@toolbox-web/grid/plugins/grouping-columns';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* Column group definition widened to accept an Angular component class as
|
|
8
|
+
* the per-group `renderer`.
|
|
9
9
|
*
|
|
10
10
|
* @since 1.7.0
|
|
11
11
|
*/
|
|
12
|
-
type
|
|
13
|
-
renderer?: ColumnGroupDefinition['renderer'] | Type<unknown>;
|
|
12
|
+
type ColumnGroupDefinition = Omit<ColumnGroupDefinition$1, 'renderer'> & {
|
|
13
|
+
renderer?: ColumnGroupDefinition$1['renderer'] | Type<unknown>;
|
|
14
14
|
};
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
16
|
+
* Grouping-columns config widened to accept Angular component classes for
|
|
17
|
+
* `groupHeaderRenderer` and per-group `renderer` inside `columnGroups`.
|
|
18
18
|
*
|
|
19
19
|
* Component instances receive the {@link GroupHeaderRenderParams} fields as
|
|
20
20
|
* inputs (`id`, `label`, `columns`, `firstIndex`, `isImplicit`).
|
|
21
21
|
*
|
|
22
22
|
* @since 1.7.0
|
|
23
23
|
*/
|
|
24
|
-
type
|
|
25
|
-
columnGroups?:
|
|
26
|
-
groupHeaderRenderer?: GroupingColumnsConfig['groupHeaderRenderer'] | Type<unknown>;
|
|
24
|
+
type GroupingColumnsConfig = Omit<GroupingColumnsConfig$1, 'groupHeaderRenderer' | 'columnGroups'> & {
|
|
25
|
+
columnGroups?: ColumnGroupDefinition[];
|
|
26
|
+
groupHeaderRenderer?: GroupingColumnsConfig$1['groupHeaderRenderer'] | Type<unknown>;
|
|
27
27
|
};
|
|
28
|
+
/** @deprecated Use {@link ColumnGroupDefinition} instead. */
|
|
29
|
+
type AngularColumnGroupDefinition = ColumnGroupDefinition;
|
|
30
|
+
/** @deprecated Use {@link GroupingColumnsConfig} instead. */
|
|
31
|
+
type AngularGroupingColumnsConfig = GroupingColumnsConfig;
|
|
28
32
|
/**
|
|
29
33
|
* Owns the binding(s) `[groupingColumns]` on `<tbw-grid>` for the matching feature plugin. See `GridFilteringDirective` for the full rationale.
|
|
30
34
|
*
|
|
@@ -32,7 +36,7 @@ type AngularGroupingColumnsConfig = Omit<GroupingColumnsConfig, 'groupHeaderRend
|
|
|
32
36
|
*/
|
|
33
37
|
declare class GridGroupingColumnsDirective implements OnDestroy {
|
|
34
38
|
private readonly elementRef;
|
|
35
|
-
readonly groupingColumns: i0.InputSignal<boolean |
|
|
39
|
+
readonly groupingColumns: i0.InputSignal<boolean | GroupingColumnsConfig | undefined>;
|
|
36
40
|
constructor();
|
|
37
41
|
ngOnDestroy(): void;
|
|
38
42
|
static ɵfac: i0.ɵɵFactoryDeclaration<GridGroupingColumnsDirective, never>;
|
|
@@ -40,5 +44,5 @@ declare class GridGroupingColumnsDirective implements OnDestroy {
|
|
|
40
44
|
}
|
|
41
45
|
|
|
42
46
|
export { GridGroupingColumnsDirective };
|
|
43
|
-
export type { AngularColumnGroupDefinition, AngularGroupingColumnsConfig };
|
|
47
|
+
export type { AngularColumnGroupDefinition, AngularGroupingColumnsConfig, ColumnGroupDefinition, GroupingColumnsConfig };
|
|
44
48
|
//# sourceMappingURL=toolbox-web-grid-angular-features-grouping-columns.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toolbox-web-grid-angular-features-grouping-columns.d.ts","sources":["../../../../libs/grid-angular/features/grouping-columns/src/grid-grouping-columns.directive.ts"],"mappings":";;;;;AAgBA;;;;;AAKG;AACG,KAAM,
|
|
1
|
+
{"version":3,"file":"toolbox-web-grid-angular-features-grouping-columns.d.ts","sources":["../../../../libs/grid-angular/features/grouping-columns/src/grid-grouping-columns.directive.ts"],"mappings":";;;;;AAgBA;;;;;AAKG;AACG,KAAM,qBAAqB,GAAG,IAAI,CAACA,uBAAyB;eACrDA,uBAAyB,eAAe,IAAI;;AAGzD;;;;;;;;AAQG;AACG,KAAM,qBAAqB,GAAG,IAAI,CAACC,uBAAyB;AAChE,mBAAe,qBAAqB;0BACdA,uBAAyB,0BAA0B,IAAI;;AAO/E;AACM,KAAM,4BAA4B,GAAG,qBAAqB;AAChE;AACM,KAAM,4BAA4B,GAAG,qBAAqB;AAEhE;;;;AAIG;AACH,cAIa,4BAA6B,YAAW,SAAS;AAC5D;8BAEwBC,EAAA,CAAA,WAAA,WAAA,qBAAA;;AAMxB;yCATW,4BAA4B;2CAA5B,4BAA4B;AAYxC;;;;","names":["CoreColumnGroupDefinition","CoreGroupingColumnsConfig","_angular_core"]}
|
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
export { _Augmentation as _GroupingRowsAugmentation } from '@toolbox-web/grid/features/grouping-rows';
|
|
2
2
|
import * as _angular_core from '@angular/core';
|
|
3
3
|
import { OnInit, OnDestroy, Type } from '@angular/core';
|
|
4
|
-
import { GroupingRowsConfig, GroupToggleDetail, GroupExpandDetail, GroupCollapseDetail } from '@toolbox-web/grid/plugins/grouping-rows';
|
|
4
|
+
import { GroupingRowsConfig as GroupingRowsConfig$1, GroupToggleDetail, GroupExpandDetail, GroupCollapseDetail } from '@toolbox-web/grid/plugins/grouping-rows';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* Grouping-rows config widened to accept an Angular component class as
|
|
8
|
+
* `groupRowRenderer`.
|
|
9
9
|
*
|
|
10
10
|
* Component instances receive the {@link GroupRowRenderParams} fields as
|
|
11
11
|
* inputs (`key`, `value`, `depth`, `rows`, `expanded`, `toggleExpand`).
|
|
12
12
|
*
|
|
13
13
|
* @since 1.7.0
|
|
14
14
|
*/
|
|
15
|
-
type
|
|
16
|
-
groupRowRenderer?: GroupingRowsConfig['groupRowRenderer'] | Type<unknown>;
|
|
15
|
+
type GroupingRowsConfig = Omit<GroupingRowsConfig$1, 'groupRowRenderer'> & {
|
|
16
|
+
groupRowRenderer?: GroupingRowsConfig$1['groupRowRenderer'] | Type<unknown>;
|
|
17
17
|
};
|
|
18
|
+
/** @deprecated Use {@link GroupingRowsConfig} instead. */
|
|
19
|
+
type AngularGroupingRowsConfig = GroupingRowsConfig;
|
|
18
20
|
/**
|
|
19
21
|
* Owns the binding(s) `[groupingRows], [groupToggle], [groupExpand], [groupCollapse]` on `<tbw-grid>` for the matching feature plugin. See `GridFilteringDirective` for the full rationale.
|
|
20
22
|
*
|
|
@@ -22,7 +24,7 @@ type AngularGroupingRowsConfig = Omit<GroupingRowsConfig, 'groupRowRenderer'> &
|
|
|
22
24
|
*/
|
|
23
25
|
declare class GridGroupingRowsDirective implements OnInit, OnDestroy {
|
|
24
26
|
private readonly elementRef;
|
|
25
|
-
readonly groupingRows: _angular_core.InputSignal<
|
|
27
|
+
readonly groupingRows: _angular_core.InputSignal<GroupingRowsConfig | undefined>;
|
|
26
28
|
readonly groupToggle: _angular_core.OutputEmitterRef<GroupToggleDetail>;
|
|
27
29
|
readonly groupExpand: _angular_core.OutputEmitterRef<GroupExpandDetail>;
|
|
28
30
|
readonly groupCollapse: _angular_core.OutputEmitterRef<GroupCollapseDetail>;
|
|
@@ -36,5 +38,5 @@ declare class GridGroupingRowsDirective implements OnInit, OnDestroy {
|
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
export { GridGroupingRowsDirective };
|
|
39
|
-
export type { AngularGroupingRowsConfig };
|
|
41
|
+
export type { AngularGroupingRowsConfig, GroupingRowsConfig };
|
|
40
42
|
//# sourceMappingURL=toolbox-web-grid-angular-features-grouping-rows.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toolbox-web-grid-angular-features-grouping-rows.d.ts","sources":["../../../../libs/grid-angular/features/grouping-rows/src/grid-grouping-rows.directive.ts"],"mappings":";;;;;AAkBA;;;;;;;;AAQG;AACG,KAAM,
|
|
1
|
+
{"version":3,"file":"toolbox-web-grid-angular-features-grouping-rows.d.ts","sources":["../../../../libs/grid-angular/features/grouping-rows/src/grid-grouping-rows.directive.ts"],"mappings":";;;;;AAkBA;;;;;;;;AAQG;AACG,KAAM,kBAAkB,GAAG,IAAI,CAACA,oBAAsB;uBACvCA,oBAAsB,uBAAuB,IAAI;;AAItE;AACM,KAAM,yBAAyB,GAAG,kBAAkB;AAE1D;;;;AAIG;AACH,cAIa,yBAA0B,YAAW,MAAM,EAAE,SAAS;AACjE;2BAEqB,aAAA,CAAA,WAAA,CAAA,kBAAA;0BACD,aAAA,CAAA,gBAAA,CAAA,iBAAA;0BACA,aAAA,CAAA,gBAAA,CAAA,iBAAA;4BACE,aAAA,CAAA,gBAAA,CAAA,mBAAA;AAEtB;AACA;;AAQA;AAYA;oDA7BW,yBAAyB;sDAAzB,yBAAyB;AAoCrC;;;;","names":["CoreGroupingRowsConfig"]}
|
|
@@ -1,9 +1,28 @@
|
|
|
1
1
|
export { _Augmentation as _MasterDetailAugmentation } from '@toolbox-web/grid/features/master-detail';
|
|
2
2
|
import * as _angular_core from '@angular/core';
|
|
3
|
-
import { OnInit, OnDestroy } from '@angular/core';
|
|
4
|
-
import { MasterDetailConfig, DetailExpandDetail } from '@toolbox-web/grid/plugins/master-detail';
|
|
3
|
+
import { OnInit, OnDestroy, Type } from '@angular/core';
|
|
4
|
+
import { MasterDetailConfig as MasterDetailConfig$1, DetailExpandDetail } from '@toolbox-web/grid/plugins/master-detail';
|
|
5
5
|
export { GridDetailContext, GridDetailView, getDetailTemplate } from '@toolbox-web/grid-angular';
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Angular-specific master-detail config that allows an Angular component class
|
|
9
|
+
* as `detailRenderer`.
|
|
10
|
+
*
|
|
11
|
+
* Extends the core `MasterDetailConfig` to accept a `Type<unknown>` for
|
|
12
|
+
* `detailRenderer` in addition to the vanilla
|
|
13
|
+
* `(row, rowIndex) => HTMLElement | string` signature. Bridging to vanilla
|
|
14
|
+
* DOM is handled by the side-effect import
|
|
15
|
+
* `@toolbox-web/grid-angular/features/master-detail`.
|
|
16
|
+
*
|
|
17
|
+
* Re-exported from the feature entry under the same name as the core type
|
|
18
|
+
* so Angular consumers see a single canonical `MasterDetailConfig` from
|
|
19
|
+
* `@toolbox-web/grid-angular/features/master-detail`.
|
|
20
|
+
*
|
|
21
|
+
* @since 1.7.1
|
|
22
|
+
*/
|
|
23
|
+
type MasterDetailConfig = Omit<MasterDetailConfig$1, 'detailRenderer'> & {
|
|
24
|
+
detailRenderer?: MasterDetailConfig$1['detailRenderer'] | Type<unknown>;
|
|
25
|
+
};
|
|
7
26
|
/**
|
|
8
27
|
* Owns the binding(s) `[masterDetail], [detailExpand]` on `<tbw-grid>` for the matching feature plugin. See `GridFilteringDirective` for the full rationale.
|
|
9
28
|
*
|
|
@@ -22,4 +41,5 @@ declare class GridMasterDetailDirective implements OnInit, OnDestroy {
|
|
|
22
41
|
}
|
|
23
42
|
|
|
24
43
|
export { GridMasterDetailDirective };
|
|
44
|
+
export type { MasterDetailConfig };
|
|
25
45
|
//# sourceMappingURL=toolbox-web-grid-angular-features-master-detail.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toolbox-web-grid-angular-features-master-detail.d.ts","sources":["../../../../libs/grid-angular/features/master-detail/src/grid-master-detail.directive.ts"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"toolbox-web-grid-angular-features-master-detail.d.ts","sources":["../../../../libs/grid-angular/features/master-detail/src/grid-master-detail.directive.ts"],"mappings":";;;;;;AAmBA;;;;;;;;;;;;;;;AAeG;AACG,KAAM,kBAAkB,GAAG,IAAI,CAACA,oBAAsB;qBACzCA,oBAAsB,qBAAqB,IAAI;;AAGlE;;;;AAIG;AACH,cAIa,yBAA0B,YAAW,MAAM,EAAE,SAAS;AACjE;2BAEqB,aAAA,CAAA,WAAA,CAAA,kBAAA;2BACA,aAAA,CAAA,gBAAA,CAAA,kBAAA;;;AAUrB;AAMA;oDApBW,yBAAyB;sDAAzB,yBAAyB;AA6BrC;;;;","names":["CoreMasterDetailConfig"]}
|
|
@@ -1,8 +1,76 @@
|
|
|
1
1
|
export { _Augmentation as _PinnedRowsAugmentation } from '@toolbox-web/grid/features/pinned-rows';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
|
-
import { OnDestroy } from '@angular/core';
|
|
4
|
-
import { PinnedRowsConfig } from '@toolbox-web/grid/plugins/pinned-rows';
|
|
3
|
+
import { OnDestroy, Type } from '@angular/core';
|
|
4
|
+
import { PinnedRowsConfig as PinnedRowsConfig$1, PinnedRowsContext, PanelZone } from '@toolbox-web/grid/plugins/pinned-rows';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Angular-shaped panel-slot render: a renderer function (vanilla), an Angular
|
|
8
|
+
* component class, or an array of zoned entries that each accept the same.
|
|
9
|
+
*
|
|
10
|
+
* Component instances receive the {@link PinnedRowsContext} fields as inputs.
|
|
11
|
+
*
|
|
12
|
+
* @since 1.7.1
|
|
13
|
+
*/
|
|
14
|
+
type PanelRender = ((ctx: PinnedRowsContext) => HTMLElement | null) | Type<unknown>;
|
|
15
|
+
/**
|
|
16
|
+
* Angular-shaped zoned panel render entry.
|
|
17
|
+
*
|
|
18
|
+
* @since 1.7.1
|
|
19
|
+
*/
|
|
20
|
+
interface ZonedPanelRender {
|
|
21
|
+
zone?: PanelZone;
|
|
22
|
+
render: PanelRender;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Angular-shaped pinned-rows panel slot.
|
|
26
|
+
*
|
|
27
|
+
* @since 1.7.1
|
|
28
|
+
*/
|
|
29
|
+
interface PanelSlot {
|
|
30
|
+
id?: string;
|
|
31
|
+
position?: 'top' | 'bottom';
|
|
32
|
+
render: PanelRender | ZonedPanelRender[];
|
|
33
|
+
}
|
|
34
|
+
type CoreSlot = NonNullable<PinnedRowsConfig$1['slots']>[number];
|
|
35
|
+
type CoreAggregationSlot = Exclude<CoreSlot, {
|
|
36
|
+
render: unknown;
|
|
37
|
+
}>;
|
|
38
|
+
/**
|
|
39
|
+
* Angular-shaped pinned-rows slot \u2014 either an aggregation slot (passthrough)
|
|
40
|
+
* or a panel slot accepting Angular component classes as `render`.
|
|
41
|
+
*
|
|
42
|
+
* @since 1.7.1
|
|
43
|
+
*/
|
|
44
|
+
type PinnedRowSlot = CoreAggregationSlot | PanelSlot;
|
|
45
|
+
/**
|
|
46
|
+
* Pinned-rows config widened to accept Angular component classes as `render`
|
|
47
|
+
* inside `slots[]` and `customPanels[]`. Bridging to vanilla DOM is handled
|
|
48
|
+
* by the side-effect import `@toolbox-web/grid-angular/features/pinned-rows`.
|
|
49
|
+
*
|
|
50
|
+
* Re-exported under the same name as the core type so Angular users see a
|
|
51
|
+
* single canonical `PinnedRowsConfig` from
|
|
52
|
+
* `@toolbox-web/grid-angular/features/pinned-rows`.
|
|
53
|
+
*
|
|
54
|
+
* @since 1.7.1
|
|
55
|
+
*/
|
|
56
|
+
type PinnedRowsConfig = Omit<PinnedRowsConfig$1, 'slots' | 'customPanels'> & {
|
|
57
|
+
slots?: PinnedRowSlot[];
|
|
58
|
+
customPanels?: Array<{
|
|
59
|
+
id: string;
|
|
60
|
+
position: PanelZone;
|
|
61
|
+
render: ((ctx: PinnedRowsContext) => HTMLElement) | Type<unknown>;
|
|
62
|
+
}>;
|
|
63
|
+
};
|
|
64
|
+
/** @deprecated Use {@link PanelRender} instead. */
|
|
65
|
+
type AngularPanelRender = PanelRender;
|
|
66
|
+
/** @deprecated Use {@link ZonedPanelRender} instead. */
|
|
67
|
+
type AngularZonedPanelRender = ZonedPanelRender;
|
|
68
|
+
/** @deprecated Use {@link PanelSlot} instead. */
|
|
69
|
+
type AngularPanelSlot = PanelSlot;
|
|
70
|
+
/** @deprecated Use {@link PinnedRowSlot} instead. */
|
|
71
|
+
type AngularPinnedRowSlot = PinnedRowSlot;
|
|
72
|
+
/** @deprecated Use {@link PinnedRowsConfig} instead. */
|
|
73
|
+
type AngularPinnedRowsConfig = PinnedRowsConfig;
|
|
6
74
|
/**
|
|
7
75
|
* Owns the binding(s) `[pinnedRows]` on `<tbw-grid>` for the matching feature plugin. See `GridFilteringDirective` for the full rationale.
|
|
8
76
|
*
|
|
@@ -18,4 +86,5 @@ declare class GridPinnedRowsDirective implements OnDestroy {
|
|
|
18
86
|
}
|
|
19
87
|
|
|
20
88
|
export { GridPinnedRowsDirective };
|
|
89
|
+
export type { AngularPanelRender, AngularPanelSlot, AngularPinnedRowSlot, AngularPinnedRowsConfig, AngularZonedPanelRender, PanelRender, PanelSlot, PinnedRowSlot, PinnedRowsConfig, ZonedPanelRender };
|
|
21
90
|
//# sourceMappingURL=toolbox-web-grid-angular-features-pinned-rows.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toolbox-web-grid-angular-features-pinned-rows.d.ts","sources":["../../../../libs/grid-angular/features/pinned-rows/src/grid-pinned-rows.directive.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"toolbox-web-grid-angular-features-pinned-rows.d.ts","sources":["../../../../libs/grid-angular/features/pinned-rows/src/grid-pinned-rows.directive.ts"],"mappings":";;;;;AAeA;;;;;;;AAOG;KACS,WAAW,UAAU,iBAAiB,KAAK,WAAW,WAAW,IAAI;AAEjF;;;;AAIG;UACc,gBAAgB;WACxB,SAAS;YACR,WAAW;AACpB;AAED;;;;AAIG;UACc,SAAS;;AAExB;AACA,YAAQ,WAAW,GAAG,gBAAgB;AACvC;AAED,KAAK,QAAQ,GAAG,WAAW,CAACA,kBAAoB;AAChD,KAAK,mBAAmB,GAAG,OAAO,CAAC,QAAQ;;AAAqB;AAEhE;;;;;AAKG;KACS,aAAa,GAAG,mBAAmB,GAAG,SAAS;AAE3D;;;;;;;;;;AAUG;AACG,KAAM,gBAAgB,GAAG,IAAI,CAACA,kBAAoB;AACtD,YAAQ,aAAa;mBACN,KAAK;;kBAER,SAAS;AACnB,uBAAe,iBAAiB,KAAK,WAAW,IAAI,IAAI;AACzD;;AAOH;AACM,KAAM,kBAAkB,GAAG,WAAW;AAC5C;AACM,KAAM,uBAAuB,GAAG,gBAAgB;AACtD;AACM,KAAM,gBAAgB,GAAG,SAAS;AACxC;AACM,KAAM,oBAAoB,GAAG,aAAa;AAChD;AACM,KAAM,uBAAuB,GAAG,gBAAgB;AAEtD;;;;AAIG;AACH,cAIa,uBAAwB,YAAW,SAAS;AACvD;yBAEmBC,EAAA,CAAA,WAAA,WAAA,gBAAA;;AAMnB;yCATW,uBAAuB;2CAAvB,uBAAuB;AAYnC;;;;","names":["CorePinnedRowsConfig","_angular_core"]}
|
|
@@ -1,8 +1,27 @@
|
|
|
1
1
|
export { _Augmentation as _ResponsiveAugmentation } from '@toolbox-web/grid/features/responsive';
|
|
2
2
|
import * as _angular_core from '@angular/core';
|
|
3
|
-
import { OnInit, OnDestroy } from '@angular/core';
|
|
4
|
-
import { ResponsivePluginConfig, ResponsiveChangeDetail } from '@toolbox-web/grid/plugins/responsive';
|
|
3
|
+
import { OnInit, OnDestroy, Type } from '@angular/core';
|
|
4
|
+
import { ResponsivePluginConfig as ResponsivePluginConfig$1, ResponsiveChangeDetail } from '@toolbox-web/grid/plugins/responsive';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Angular-specific responsive config that allows an Angular component class
|
|
8
|
+
* as `cardRenderer`.
|
|
9
|
+
*
|
|
10
|
+
* Extends the core `ResponsivePluginConfig` to accept a `Type<unknown>` for
|
|
11
|
+
* `cardRenderer` in addition to the vanilla
|
|
12
|
+
* `(row, rowIndex, column?) => HTMLElement` signature. Bridging to vanilla
|
|
13
|
+
* DOM is handled by the side-effect import
|
|
14
|
+
* `@toolbox-web/grid-angular/features/responsive`.
|
|
15
|
+
*
|
|
16
|
+
* Re-exported from the feature entry under the same name as the core type
|
|
17
|
+
* so Angular consumers see a single canonical `ResponsivePluginConfig` from
|
|
18
|
+
* `@toolbox-web/grid-angular/features/responsive`.
|
|
19
|
+
*
|
|
20
|
+
* @since 1.7.1
|
|
21
|
+
*/
|
|
22
|
+
type ResponsivePluginConfig<TRow = unknown> = Omit<ResponsivePluginConfig$1<TRow>, 'cardRenderer'> & {
|
|
23
|
+
cardRenderer?: ResponsivePluginConfig$1<TRow>['cardRenderer'] | Type<unknown>;
|
|
24
|
+
};
|
|
6
25
|
/**
|
|
7
26
|
* Owns the binding(s) `[responsive], [responsiveChange]` on `<tbw-grid>` for the matching feature plugin. See `GridFilteringDirective` for the full rationale.
|
|
8
27
|
*
|
|
@@ -21,4 +40,5 @@ declare class GridResponsiveDirective implements OnInit, OnDestroy {
|
|
|
21
40
|
}
|
|
22
41
|
|
|
23
42
|
export { GridResponsiveDirective };
|
|
43
|
+
export type { ResponsivePluginConfig };
|
|
24
44
|
//# sourceMappingURL=toolbox-web-grid-angular-features-responsive.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toolbox-web-grid-angular-features-responsive.d.ts","sources":["../../../../libs/grid-angular/features/responsive/src/grid-responsive.directive.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"toolbox-web-grid-angular-features-responsive.d.ts","sources":["../../../../libs/grid-angular/features/responsive/src/grid-responsive.directive.ts"],"mappings":";;;;;AAcA;;;;;;;;;;;;;;;AAeG;KACS,sBAAsB,mBAAmB,IAAI,CAACA,wBAA0B;AAClF,mBAAeA,wBAA0B,yBAAyB,IAAI;;AAGxE;;;;AAIG;AACH,cAIa,uBAAwB,YAAW,MAAM,EAAE,SAAS;AAC/D;yBAEmB,aAAA,CAAA,WAAA,WAAA,sBAAA;+BACM,aAAA,CAAA,gBAAA,CAAA,sBAAA;;;AAUzB;AAMA;oDApBW,uBAAuB;sDAAvB,uBAAuB;AA6BnC;;;;","names":["CoreResponsivePluginConfig"]}
|