diff --git a/docs b/docs index 4cb684c4..bcc98483 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 4cb684c450d1c8e076252d7dbcab70291eff7fe8 +Subproject commit bcc98483c3c385dd062b5ce5b63459e6f1b8d115 diff --git a/packages/angular b/packages/angular index b32d5e64..e0faf8df 160000 --- a/packages/angular +++ b/packages/angular @@ -1 +1 @@ -Subproject commit b32d5e64e7fac3078a9c79fba320493a2d6b67d8 +Subproject commit e0faf8dfcc39ddf2e5d03e594166fd553134be33 diff --git a/packages/svelte b/packages/svelte index 3eab2a65..898f7071 160000 --- a/packages/svelte +++ b/packages/svelte @@ -1 +1 @@ -Subproject commit 3eab2a65b7ab9eb28f5ee8be1f09659c4f59215d +Subproject commit 898f70718465e8ccdb202a864a085d0c6164f5b0 diff --git a/packages/vue3 b/packages/vue3 index dd9b9554..7334976a 160000 --- a/packages/vue3 +++ b/packages/vue3 @@ -1 +1 @@ -Subproject commit dd9b95545e6dd30266810372fdc83363988365e4 +Subproject commit 7334976afc28bf540da7b27fd14d67b1d566a9e3 diff --git a/src/components.d.ts b/src/components.d.ts index cd85ec05..52919a17 100644 --- a/src/components.d.ts +++ b/src/components.d.ts @@ -5,7 +5,7 @@ * It contains typing information for all components that exist in this project. */ import { HTMLStencilElement, JSXBase } from "@stencil/core/internal"; -import { AfterEditEvent, AllDimensionType, ApplyFocusEvent, BeforeCellRenderEvent, BeforeEdit, BeforeRangeSaveDataDetails, BeforeRowRenderEvent, BeforeSaveDataDetails, Cell, CellTemplateProp, ChangedRange, ColumnDataSchemaModel, ColumnGrouping, ColumnProp, ColumnRegular, ColumnType, DataFormat, DataType, DimensionCols, DimensionRows, DimensionSettingsState, DimensionType, DimensionTypeCol, DragStartEvent, EditCell, EditorCtr, Editors, ElementScroll, ExtraNodeFuncConfig, FocusAfterRenderEvent, FocusRenderEvent, FocusTemplateFunc, HyperFunc, InitialHeaderClick, MultiDimensionType, Nullable, PluginBaseComponent, PositionItem, Providers, RangeArea, RangeClipboardCopyEventProps, RangeClipboardPasteEvent, RowDefinition, RowHeaders, SaveDataDetails, SelectionStoreState, TempRange, Theme, ViewportData, ViewPortResizeEvent, ViewPortScrollEvent, ViewportState, ViewSettingSizeProp } from "./types/index"; +import { AfterEditEvent, AllDimensionType, ApplyFocusEvent, BeforeCellRenderEvent, BeforeEdit, BeforeRangeSaveDataDetails, BeforeRowRenderEvent, BeforeSaveDataDetails, Cell, CellTemplateProp, ChangedRange, ColumnDataSchemaModel, ColumnGrouping, ColumnProp, ColumnRegular, ColumnType, DataFormat, DataType, DimensionCols, DimensionRows, DimensionSettingsState, DimensionType, DimensionTypeCol, DragStartEvent, EditCell, EditorCtr, Editors, ElementScroll, ExtraNodeFuncConfig, FocusAfterRenderEvent, FocusRenderEvent, FocusTemplateFunc, InitialHeaderClick, MultiDimensionType, Nullable, PluginBaseComponent, PositionItem, Providers, RangeArea, RangeClipboardCopyEventProps, RangeClipboardPasteEvent, RowDefinition, RowHeaders, SaveDataDetails, SelectionStoreState, TempRange, Theme, ViewportData, ViewPortResizeEvent, ViewPortScrollEvent, ViewportState, ViewSettingSizeProp } from "./types/index"; import { GridPlugin } from "./plugins/base.plugin"; import { AutoSizeColumnConfig } from "./plugins/column.auto-size.plugin"; import { ColumnFilterConfig, FilterCaptions, FilterCollection, LogicFunction, MultiFilterItem, ShowData } from "./plugins/filter/filter.types"; @@ -19,7 +19,7 @@ import { DSourceState, Groups } from "./store/index"; import { ResizeProps } from "./components/header/resizable.directive"; import { HeaderRenderProps } from "./components/header/header-renderer"; import { EventData } from "./components/overlay/selection.utils"; -export { AfterEditEvent, AllDimensionType, ApplyFocusEvent, BeforeCellRenderEvent, BeforeEdit, BeforeRangeSaveDataDetails, BeforeRowRenderEvent, BeforeSaveDataDetails, Cell, CellTemplateProp, ChangedRange, ColumnDataSchemaModel, ColumnGrouping, ColumnProp, ColumnRegular, ColumnType, DataFormat, DataType, DimensionCols, DimensionRows, DimensionSettingsState, DimensionType, DimensionTypeCol, DragStartEvent, EditCell, EditorCtr, Editors, ElementScroll, ExtraNodeFuncConfig, FocusAfterRenderEvent, FocusRenderEvent, FocusTemplateFunc, HyperFunc, InitialHeaderClick, MultiDimensionType, Nullable, PluginBaseComponent, PositionItem, Providers, RangeArea, RangeClipboardCopyEventProps, RangeClipboardPasteEvent, RowDefinition, RowHeaders, SaveDataDetails, SelectionStoreState, TempRange, Theme, ViewportData, ViewPortResizeEvent, ViewPortScrollEvent, ViewportState, ViewSettingSizeProp } from "./types/index"; +export { AfterEditEvent, AllDimensionType, ApplyFocusEvent, BeforeCellRenderEvent, BeforeEdit, BeforeRangeSaveDataDetails, BeforeRowRenderEvent, BeforeSaveDataDetails, Cell, CellTemplateProp, ChangedRange, ColumnDataSchemaModel, ColumnGrouping, ColumnProp, ColumnRegular, ColumnType, DataFormat, DataType, DimensionCols, DimensionRows, DimensionSettingsState, DimensionType, DimensionTypeCol, DragStartEvent, EditCell, EditorCtr, Editors, ElementScroll, ExtraNodeFuncConfig, FocusAfterRenderEvent, FocusRenderEvent, FocusTemplateFunc, InitialHeaderClick, MultiDimensionType, Nullable, PluginBaseComponent, PositionItem, Providers, RangeArea, RangeClipboardCopyEventProps, RangeClipboardPasteEvent, RowDefinition, RowHeaders, SaveDataDetails, SelectionStoreState, TempRange, Theme, ViewportData, ViewPortResizeEvent, ViewPortScrollEvent, ViewportState, ViewSettingSizeProp } from "./types/index"; export { GridPlugin } from "./plugins/base.plugin"; export { AutoSizeColumnConfig } from "./plugins/column.auto-size.plugin"; export { ColumnFilterConfig, FilterCaptions, FilterCollection, LogicFunction, MultiFilterItem, ShowData } from "./plugins/filter/filter.types"; @@ -434,7 +434,6 @@ export namespace Components { * Disables dynamic filtering. A way to apply filters on Save only */ "disableDynamicFiltering": boolean; - "extraContent"?: (h: HyperFunc, data: ShowData) => VNode | VNode[]; "filterCaptions": FilterCaptions | undefined; "filterEntities": Record; "filterNames": Record; @@ -1813,7 +1812,6 @@ declare namespace LocalJSX { * Disables dynamic filtering. A way to apply filters on Save only */ "disableDynamicFiltering"?: boolean; - "extraContent"?: (h: HyperFunc, data: ShowData) => VNode | VNode[]; "filterCaptions"?: FilterCaptions | undefined; "filterEntities"?: Record; "filterNames"?: Record; diff --git a/src/components/revoGrid/plugin.service.ts b/src/components/revoGrid/plugin.service.ts index b18e0dec..aae62ccd 100644 --- a/src/components/revoGrid/plugin.service.ts +++ b/src/components/revoGrid/plugin.service.ts @@ -1,11 +1,11 @@ -import { PluginBaseComponent, PluginProviders } from '@type'; -import { BasePlugin, GridPlugin } from 'src/plugins'; +import { PluginBaseComponent, PluginProviders, PluginServiceBase } from '@type'; +import { GridPlugin } from 'src/plugins'; /** * Plugin service * Manages plugins */ -export class PluginService { +export class PluginService implements PluginServiceBase { /** * Plugins * Define plugins collection @@ -72,7 +72,7 @@ export class PluginService { /** * Get plugin by class */ - getByClass( + getByClass( pluginClass: new (...args: any[]) => T, ): T | undefined { return this.internalPlugins.find(p => p instanceof pluginClass) as diff --git a/src/components/revoGrid/revo-grid.tsx b/src/components/revoGrid/revo-grid.tsx index 77577465..f7b884a1 100644 --- a/src/components/revoGrid/revo-grid.tsx +++ b/src/components/revoGrid/revo-grid.tsx @@ -1394,6 +1394,7 @@ export class RevoGridComponent { dimension: this.dimensionProvider, viewport: this.viewportProvider, selection: this.selectionStoreConnector, + plugins: this.pluginService, }; return pluginData; diff --git a/src/index.ts b/src/index.ts index 88c4b3a2..e2df64d0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,4 +4,4 @@ export * from './plugins'; export * from './components'; export * from './utils'; export { TextEditor } from './components/editors/text-editor'; -export { h } from '@stencil/core'; +export { h, type FunctionalComponent } from '@stencil/core'; diff --git a/src/plugins/filter/filter.panel.tsx b/src/plugins/filter/filter.panel.tsx index 16508954..6ee98fd4 100644 --- a/src/plugins/filter/filter.panel.tsx +++ b/src/plugins/filter/filter.panel.tsx @@ -21,7 +21,7 @@ import { MultiFilterItem, ShowData, } from './filter.types'; -import { ColumnProp, HyperFunc } from '@type'; +import type { ColumnProp } from '@type'; import { FilterType } from './filter.indexed'; const defaultType: FilterType = 'none'; @@ -48,7 +48,7 @@ export class FilterPanel { // drops the filter reset: 'Reset', cancel: 'Cancel', - add: 'Add more condition...', + add: 'Add condition', placeholder: 'Enter value...', and: 'and', or: 'or', @@ -68,9 +68,6 @@ export class FilterPanel { * Disables dynamic filtering. A way to apply filters on Save only */ @Prop() disableDynamicFiltering = false; - - @Prop() extraContent?: (h: HyperFunc, data: ShowData) => VNode | VNode[]; - @Event() filterChange: EventEmitter; @Event() resetChange: EventEmitter; @@ -132,7 +129,7 @@ export class FilterPanel { const prop = this.changes?.prop; if (typeof prop === 'undefined') return ''; - const propFilters = this.filterItems[prop]?.filter(f => !f.hidden) || []; + const propFilters = this.filterItems[prop]; const capts = Object.assign( this.filterCaptionsInternal, this.filterCaptions, @@ -141,6 +138,9 @@ export class FilterPanel {
{propFilters.map((filter, index) => { let andOrButton; + if (filter.hidden) { + return; + } // hide toggle button if there is only one filter and the last one if (index !== this.filterItems[prop].length - 1) { @@ -175,7 +175,7 @@ export class FilterPanel { ); })} - {propFilters.length > 0 ?
: ''} + {propFilters.filter(f => !f.hidden).length > 0 ?
: ''}
); } @@ -365,6 +365,15 @@ export class FilterPanel { const options: VNode[] = []; const prop = this.changes.prop; + const hidden = new Set(); + Object.entries(this.filterItems).forEach(([_, values]) => { + values.forEach((filter) => { + if (filter.hidden) { + hidden.add(filter.type); + } + }) + }); + if (!isDefaultTypeRemoved) { const capts = Object.assign( this.filterCaptionsInternal, @@ -384,14 +393,17 @@ export class FilterPanel { } for (let gIndex in this.changes.filterTypes) { - options.push( - ...this.changes.filterTypes[gIndex].map(k => ( - - )), - ); - options.push(); + const group = this.changes.filterTypes[gIndex].filter(k => !hidden.has(k)); + if (group.length) { + options.push( + ...group.map(k => ( + + )), + ); + options.push(); + } } return options; } @@ -444,7 +456,7 @@ export class FilterPanel { }} > - { this.extraContent?.(h, this.changes) } + { this.changes.extraContent?.(this.changes) || '' }
{this.getFilterItemsList()}
diff --git a/src/plugins/filter/filter.plugin.tsx b/src/plugins/filter/filter.plugin.tsx index a0596c1a..b7e4d3ca 100644 --- a/src/plugins/filter/filter.plugin.tsx +++ b/src/plugins/filter/filter.plugin.tsx @@ -1,6 +1,6 @@ import { h, type VNode } from '@stencil/core'; -import type { ColumnProp, ColumnRegular, DataType, HyperFunc, PluginProviders } from '@type'; +import type { ColumnProp, ColumnRegular, DataType, PluginProviders } from '@type'; import { BasePlugin } from '../base.plugin'; import { FILTER_PROP, isFilterBtn } from './filter.button'; import { @@ -47,6 +47,14 @@ export class FilterPlugin extends BasePlugin { filterCollection: FilterCollection = {}; multiFilterItems: MultiFilterItem = {}; + /** + * Filter types + * @example + * { + * string: ['contains', 'beginswith'], + * number: ['eqN', 'neqN', 'gt'] + * } + */ filterByType: Record = { ...filterTypes }; filterNameIndexByType: Record = { @@ -58,12 +66,12 @@ export class FilterPlugin extends BasePlugin { filterProp = FILTER_PROP; - extraHyperContent?: (h: HyperFunc, data: ShowData) => VNode | VNode[]; + extraHyperContent?: (data: ShowData) => VNode | VNode[]; constructor( public revogrid: HTMLRevoGridElement, providers: PluginProviders, - config?: ColumnFilterConfig, + public config?: ColumnFilterConfig, ) { super(revogrid, providers); if (config) { @@ -82,7 +90,6 @@ export class FilterPlugin extends BasePlugin { onFilterChange={e => this.onFilterChange(e.detail)} onResetChange={e => this.onFilterReset(e.detail)} disableDynamicFiltering={config?.disableDynamicFiltering} - extraContent={this.extraHyperContent} ref={e => (this.pop = e)} > { this.extraContent() }, ]; @@ -111,7 +118,7 @@ export class FilterPlugin extends BasePlugin { }; this.addEventListener( 'headerclick', - (e: CustomEvent) => + (e) => this.headerclick(e), ); this.addEventListener( @@ -220,14 +227,18 @@ export class FilterPlugin extends BasePlugin { const buttonPos = el.getBoundingClientRect(); const prop = e.detail.prop; - this.pop.show({ + const data: ShowData = { + ...e.detail, ...this.filterCollection[prop], x: buttonPos.x - gridPos.x, y: buttonPos.y - gridPos.y + buttonPos.height, autoCorrect: true, - prop, filterTypes: this.getColumnFilter(e.detail.filter), filterItems: this.multiFilterItems, + }; + this.pop.show({ + ...data, + extraContent: this.extraHyperContent, }); } diff --git a/src/plugins/filter/filter.types.ts b/src/plugins/filter/filter.types.ts index f4ee9877..26bbaa3e 100644 --- a/src/plugins/filter/filter.types.ts +++ b/src/plugins/filter/filter.types.ts @@ -1,5 +1,5 @@ -import { ColumnProp } from '@type'; -import { FilterType } from './filter.indexed'; +import type { ColumnProp, ColumnRegular } from '@type'; +import type { FilterType } from './filter.indexed'; export type DateEnum = | 'today' @@ -143,4 +143,6 @@ export type ShowData = { autoCorrect?: boolean; filterTypes?: Record; filterItems?: MultiFilterItem; -} & FilterItem; + // pass vnodes from plugins + extraContent?: (data: ShowData) => any; +} & FilterItem & Omit; diff --git a/src/types/plugin.types.ts b/src/types/plugin.types.ts index 1f92ec39..8564d052 100644 --- a/src/types/plugin.types.ts +++ b/src/types/plugin.types.ts @@ -1,9 +1,19 @@ +import { PluginBaseComponent } from '@type'; import ColumnDataProvider from '../services/column.data.provider'; import { DataProvider } from '../services/data.provider'; import DimensionProvider from '../services/dimension.provider'; import type { SelectionStoreConnector } from '../services/selection.store.connector'; import ViewportProvider from '../services/viewport.provider'; +export interface PluginServiceBase { + get(): PluginBaseComponent[]; + add(plugin: PluginBaseComponent): void; + remove(plugin: PluginBaseComponent): void; + getByClass( + pluginClass: new (...args: any[]) => T, + ): T | undefined; +} + /** * Services that are provided by the various plugins for use by the grid. Each plugin * is responsible for providing a specific service, and the `PluginProviders` type collects all the services provided @@ -30,6 +40,12 @@ export type PluginProviders = { * The viewport service provides access to the grid's viewport state. */ viewport: ViewportProvider; + + /** + * Plugin services + */ + + plugins: PluginServiceBase; };