Skip to content

Commit

Permalink
Merge pull request #531 from revolist/506-wcag-accessibility-plugin
Browse files Browse the repository at this point in the history
#506 wcag accessibility plugin added
  • Loading branch information
revolist authored Aug 17, 2024
2 parents 4f661fb + c66cd10 commit 3fee827
Show file tree
Hide file tree
Showing 18 changed files with 258 additions and 102 deletions.
2 changes: 1 addition & 1 deletion docs
Submodule docs updated 248 files
26 changes: 15 additions & 11 deletions src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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, ChangedRange, ColumnDataSchemaModel, ColumnGrouping, ColumnProp, ColumnRegular, ColumnType, DataFormat, DataType, DimensionCols, DimensionRows, DimensionSettingsState, DimensionType, DimensionTypeCol, DragStartEvent, EditCell, EditorCtr, Editors, ElementScroll, FocusRenderEvent, FocusTemplateFunc, InitialHeaderClick, MultiDimensionType, Nullable, PluginBaseComponent, PositionItem, 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, ChangedRange, ColumnDataSchemaModel, ColumnGrouping, ColumnProp, ColumnRegular, ColumnType, DataFormat, DataType, DimensionCols, DimensionRows, DimensionSettingsState, DimensionType, DimensionTypeCol, DragStartEvent, EditCell, EditorCtr, Editors, ElementScroll, FocusAfterRenderEvent, FocusRenderEvent, FocusTemplateFunc, InitialHeaderClick, MultiDimensionType, Nullable, PluginBaseComponent, PositionItem, 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 } from "./plugins/filter/filter.plugin";
Expand All @@ -21,7 +21,7 @@ import { LogicFunction } from "./plugins/filter/filter.types";
import { ResizeProps } from "./components/header/resizable.directive";
import { Cell as Cell1, ColumnRegular as ColumnRegular1, DataType as DataType1, DimensionCols as DimensionCols1, DimensionRows as DimensionRows1, DimensionSettingsState as DimensionSettingsState1, Observable as Observable1, SelectionStoreState as SelectionStoreState1 } from "./components";
import { EventData } from "./components/overlay/selection.utils";
export { AfterEditEvent, AllDimensionType, ApplyFocusEvent, BeforeCellRenderEvent, BeforeEdit, BeforeRangeSaveDataDetails, BeforeRowRenderEvent, BeforeSaveDataDetails, Cell, ChangedRange, ColumnDataSchemaModel, ColumnGrouping, ColumnProp, ColumnRegular, ColumnType, DataFormat, DataType, DimensionCols, DimensionRows, DimensionSettingsState, DimensionType, DimensionTypeCol, DragStartEvent, EditCell, EditorCtr, Editors, ElementScroll, FocusRenderEvent, FocusTemplateFunc, InitialHeaderClick, MultiDimensionType, Nullable, PluginBaseComponent, PositionItem, 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, ChangedRange, ColumnDataSchemaModel, ColumnGrouping, ColumnProp, ColumnRegular, ColumnType, DataFormat, DataType, DimensionCols, DimensionRows, DimensionSettingsState, DimensionType, DimensionTypeCol, DragStartEvent, EditCell, EditorCtr, Editors, ElementScroll, FocusAfterRenderEvent, FocusRenderEvent, FocusTemplateFunc, InitialHeaderClick, MultiDimensionType, Nullable, PluginBaseComponent, PositionItem, 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 } from "./plugins/filter/filter.plugin";
Expand Down Expand Up @@ -52,6 +52,11 @@ export namespace Components {
* @example focus-rgCol-rgRow - focus layer for main data. Applies extra elements in <revogr-focus />.
*/
interface RevoGrid {
/**
* Enable accessibility. If disabled, the grid will not be accessible.
* @default true
*/
"accessible": boolean;
/**
* Add trimmed by type
*/
Expand Down Expand Up @@ -962,10 +967,7 @@ declare global {
interface HTMLRevogrFocusElementEventMap {
"beforefocusrender": FocusRenderEvent;
"beforescrollintoview": { el: HTMLElement };
"afterfocus": {
model: any;
column: ColumnRegular;
};
"afterfocus": FocusAfterRenderEvent;
}
/**
* Focus component. Shows focus layer around the cell that is currently in focus.
Expand Down Expand Up @@ -1207,6 +1209,11 @@ declare namespace LocalJSX {
* @example focus-rgCol-rgRow - focus layer for main data. Applies extra elements in <revogr-focus />.
*/
interface RevoGrid {
/**
* Enable accessibility. If disabled, the grid will not be accessible.
* @default true
*/
"accessible"?: boolean;
/**
* Additional data to be passed to plugins, renders or editors. For example if you need to pass Vue component instance.
*/
Expand Down Expand Up @@ -1308,7 +1315,7 @@ declare namespace LocalJSX {
*/
"onAfteredit"?: (event: RevoGridCustomEvent<AfterEditEvent>) => void;
/**
* Triggered after focus render finished. Can be used to access a focus element through `event.target`
* Triggered after focus render finished. Can be used to access a focus element through `event.target`. This is just a duplicate of `afterfocus` from `revogr-focus.tsx`.
*/
"onAfterfocus"?: (event: RevoGridCustomEvent<{
model: any;
Expand Down Expand Up @@ -1746,10 +1753,7 @@ declare namespace LocalJSX {
/**
* Used to setup properties after focus was rendered
*/
"onAfterfocus"?: (event: RevogrFocusCustomEvent<{
model: any;
column: ColumnRegular;
}>) => void;
"onAfterfocus"?: (event: RevogrFocusCustomEvent<FocusAfterRenderEvent>) => void;
/**
* Before focus render event. Can be prevented by event.preventDefault(). If preventDefault used slot will be rendered.
*/
Expand Down
2 changes: 1 addition & 1 deletion src/components/data/column.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ export default class ColumnService {
prop: ColumnProp;
rowIndex: number;
colIndex: number;
model: DataType;
model?: DataType;
colType: DimensionCols;
type: DimensionRows;
}[] = [];
Expand Down
1 change: 1 addition & 0 deletions src/components/data/revogr-data-style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ revogr-data {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
outline: none;

&.align-center {
text-align: center;
Expand Down
3 changes: 2 additions & 1 deletion src/components/overlay/keyboard.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
isEnterKeyValue,
isLetterKey,
isPaste,
isTab,
} from '../../utils/key.utils';
import { timeout } from '../../utils';
import {
Expand Down Expand Up @@ -80,7 +81,7 @@ export class KeyboardService {
}

// tab key means same as arrow right
if (codesLetter.TAB === e.code) {
if (isTab(e.code)) {
this.keyChangeSelection(e, canRange);
return;
}
Expand Down
1 change: 1 addition & 0 deletions src/components/overlay/revogr-overlay-selection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,7 @@ export class OverlaySelection {
range,
...this.types,
});

if (canPaste) {
return;
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/overlay/selection.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export type EventData = {
};

export function collectModelsOfRange(data: DataLookup, store: Observable<DSourceState<DataType, DimensionRows>>) {
const models: DataLookup = {};
const models: Partial<DataLookup> = {};
for (let i in data) {
const rowIndex = parseInt(i, 10);
models[rowIndex] = getSourceItem(
Expand Down
82 changes: 47 additions & 35 deletions src/components/revoGrid/revo-grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,38 @@ import {
Host,
} from '@stencil/core';

import type {
MultiDimensionType,
DimensionRows,
DimensionCols,
DimensionType,
DimensionTypeCol,
RowHeaders,
ColumnRegular,
ColumnGrouping,
DataType,
RowDefinition,
ColumnType,
FocusTemplateFunc,
PositionItem,
ColumnProp,
ViewPortScrollEvent,
InitialHeaderClick,
AllDimensionType,
Editors,
BeforeSaveDataDetails,
BeforeRangeSaveDataDetails,
Cell,
ChangedRange,
RangeArea,
AfterEditEvent,
Theme,
PluginBaseComponent,
HeaderProperties,
PluginProviders,
FocusAfterRenderEvent,
} from '@type';

import ColumnDataProvider from '../../services/column.data.provider';
import { DataProvider } from '../../services/data.provider';
import { DSourceState, getVisibleSourceItem } from '@store';
Expand Down Expand Up @@ -45,39 +77,10 @@ import { rowDefinitionByType, rowDefinitionRemoveByType } from './grid.helpers';
import ColumnPlugin from '../../plugins/moveColumn/column.drag.plugin';
import { getPropertyFromEvent } from '../../utils/events';
import { isMobileDevice } from '../../utils/mobile';
import {
MultiDimensionType,
DimensionRows,
DimensionCols,
DimensionType,
DimensionTypeCol,
RowHeaders,
ColumnRegular,
ColumnGrouping,
DataType,
RowDefinition,
ColumnType,
FocusTemplateFunc,
PositionItem,
ColumnProp,
ViewPortScrollEvent,
InitialHeaderClick,
AllDimensionType,
Editors,
BeforeSaveDataDetails,
BeforeRangeSaveDataDetails,
Cell,
ChangedRange,
RangeArea,
AfterEditEvent,
Theme,
PluginBaseComponent,
HeaderProperties,
PluginProviders,
} from '@type';
import type { Observable } from '../../utils/store.utils';
import type { GridPlugin } from '../../plugins/base.plugin';
import { ColumnCollection, getColumnByProp, getColumns } from '../../utils/column.utils';
import { WCAGPlugin } from '../../plugins/wcag';


/**
Expand Down Expand Up @@ -285,6 +288,13 @@ export class RevoGridComponent {
*/
@Prop() registerVNode: VNode[] = [];


/**
* Enable accessibility. If disabled, the grid will not be accessible.
* @default true
*/
@Prop() accessible = true;

// #endregion

// #region Events
Expand Down Expand Up @@ -327,12 +337,10 @@ export class RevoGridComponent {

/**
* Triggered after focus render finished.
* Can be used to access a focus element through `event.target`
* Can be used to access a focus element through `event.target`.
* This is just a duplicate of `afterfocus` from `revogr-focus.tsx`.
*/
@Event() afterfocus: EventEmitter<{
model: any;
column: ColumnRegular;
}>;
@Event() afterfocus: EventEmitter<FocusAfterRenderEvent>;

/**
* This event is triggered before the order of `rgRow` is applied.
Expand Down Expand Up @@ -1215,6 +1223,10 @@ export class RevoGridComponent {
selection: this.selectionStoreConnector,
};

if (this.accessible) {
this.internalPlugins.push(new WCAGPlugin(this.element, pluginData));
}

// register auto size plugin
if (this.autoSizeColumn) {
this.internalPlugins.push(
Expand Down
1 change: 1 addition & 0 deletions src/components/scroll/revogr-viewport-scroll-style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ revogr-viewport-scroll {
position: relative;
width: 100%;
flex-grow: 1;
outline: none; // avoid accessibility focus issue
@include noScroll;

revogr-data,
Expand Down
39 changes: 19 additions & 20 deletions src/components/selectionFocus/revogr-focus.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
FocusTemplateFunc,
DimensionCols,
DimensionRows,
FocusAfterRenderEvent,
} from '@type';
import { Observable } from '../../utils/store.utils';

Expand Down Expand Up @@ -78,29 +79,11 @@ export class RevogrFocus {
/**
* Used to setup properties after focus was rendered
*/
@Event({ eventName: 'afterfocus' }) afterFocus: EventEmitter<{
model: any;
column: ColumnRegular;
}>;
@Event({ eventName: 'afterfocus' }) afterFocus: EventEmitter<FocusAfterRenderEvent>;

@Element() el: HTMLElement;
private activeFocus: Cell | null = null;

private changed(e: HTMLElement, focus: Cell) {
const beforeScrollIn = this.beforeScrollIntoView.emit({ el: e });
if (!beforeScrollIn.defaultPrevented) {
e.scrollIntoView({
block: 'nearest',
inline: 'nearest',
});
}
const model = getSourceItem(this.dataStore, focus.y);
const column = getSourceItem(this.colData, focus.x);
this.afterFocus.emit({
model,
column,
});
}

componentDidRender() {
const currentFocus = this.selectionStore.get('focus');
Expand All @@ -112,7 +95,23 @@ export class RevogrFocus {
}
this.activeFocus = currentFocus;
if (currentFocus && this.el) {
this.changed(this.el, currentFocus);
const beforeScrollIn = this.beforeScrollIntoView.emit({ el: this.el });
if (!beforeScrollIn.defaultPrevented) {
this.el.scrollIntoView({
block: 'nearest',
inline: 'nearest',
});
}
const model = getSourceItem(this.dataStore, currentFocus.y);
const column = getSourceItem(this.colData, currentFocus.x);
this.afterFocus.emit({
model,
column,
rowType: this.rowType,
colType: this.colType,
rowIndex: currentFocus.y,
colIndex: currentFocus.x,
});
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/plugins/column.auto-size.plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ export default class AutoSizeColumnPlugin extends BasePlugin {
s.store.get('items'),
(prev, _row, i) => {
const item = getSourceItem(s.store, i);
return Math.max(prev || 0, this.getLength(item[rgCol.prop]));
return Math.max(prev || 0, this.getLength(item?.[rgCol.prop]));
},
0,
);
Expand Down
10 changes: 5 additions & 5 deletions src/plugins/groupingRow/grouping.row.plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,14 @@ export default class GroupingRowPlugin extends BasePlugin {
}

// grouping filter
if (!isGrouping(model)) {
result.source.push(model);
result.oldNewIndexes[i] = index;
index++;
} else {
if (isGrouping(model)) {
if (model[GROUP_EXPANDED]) {
result.prevExpanded[model[PSEUDO_GROUP_ITEM_VALUE]] = true;
}
} else {
result.source.push(model);
result.oldNewIndexes[i] = index;
index++;
}
return result;
},
Expand Down
Loading

0 comments on commit 3fee827

Please sign in to comment.