@one-grid-core/angular 0.1.0-beta.6 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/README.md +49 -4
  2. package/esm2022/lib/components/one-grid/one-grid.component.mjs +67 -16
  3. package/esm2022/lib/components/one-grid-body/one-grid-body.component.mjs +282 -30
  4. package/esm2022/lib/components/one-grid-cell-group-renderer/one-grid-cell-group-renderer.component.mjs +10 -7
  5. package/esm2022/lib/components/one-grid-cell-option-menu/one-grid-cell-option-menu.component.mjs +60 -4
  6. package/esm2022/lib/components/one-grid-checkbox-header/one-grid-checkbox-header.component.mjs +14 -5
  7. package/esm2022/lib/components/one-grid-header/one-grid-header.component.mjs +50 -13
  8. package/esm2022/lib/components/one-grid-pagination/one-grid-pagination.component.mjs +39 -15
  9. package/esm2022/lib/components/one-grid-row-action/one-grid-row-action.component.mjs +54 -8
  10. package/esm2022/lib/components/one-grid-row-drag-handle/one-grid-row-drag-handle.component.mjs +110 -0
  11. package/esm2022/lib/core/directives/one-cell-renderer-component.directive.mjs +9 -2
  12. package/esm2022/lib/core/directives/one-cell-text-expand.directive.mjs +33 -51
  13. package/esm2022/lib/core/instants/one-grid-api.class.mjs +429 -166
  14. package/esm2022/lib/core/instants/one-row-node.class.mjs +103 -37
  15. package/esm2022/lib/core/models/one-column-def-types.model.mjs +1 -1
  16. package/esm2022/lib/core/models/one-event-types.model.mjs +1 -1
  17. package/esm2022/lib/core/models/one-grid-types.model.mjs +1 -1
  18. package/esm2022/lib/core/models/one-row-drag.model.mjs +2 -0
  19. package/esm2022/lib/core/models/one-row.model.mjs +1 -1
  20. package/esm2022/lib/core/models/one-tree-data.model.mjs +1 -1
  21. package/esm2022/lib/core/models/one-validation.model.mjs +1 -1
  22. package/esm2022/lib/core/pipes/cell-field-value-empty.pipe.mjs +8 -3
  23. package/esm2022/lib/core/pipes/column-sort-state.pipe.mjs +3 -1
  24. package/esm2022/lib/core/services/og-column.service.mjs +120 -13
  25. package/esm2022/lib/core/services/one-grid-cell.service.mjs +123 -20
  26. package/esm2022/lib/core/services/one-grid-row-drag.service.mjs +351 -0
  27. package/esm2022/lib/core/services/one-grid-selection.service.mjs +19 -6
  28. package/esm2022/lib/helpers/one-column-def.helper.mjs +27 -2
  29. package/esm2022/lib/helpers/one-filter.helper.mjs +71 -12
  30. package/esm2022/lib/helpers/one-validation.helper.mjs +7 -2
  31. package/esm2022/lib/index.mjs +6 -1
  32. package/esm2022/lib/one-grid.module.mjs +7 -16
  33. package/fesm2022/one-grid-core-angular.mjs +1964 -421
  34. package/fesm2022/one-grid-core-angular.mjs.map +1 -1
  35. package/lib/components/one-grid/one-grid.component.d.ts +16 -1
  36. package/lib/components/one-grid-body/one-grid-body.component.d.ts +132 -5
  37. package/lib/components/one-grid-cell-group-renderer/one-grid-cell-group-renderer.component.d.ts +6 -1
  38. package/lib/components/one-grid-cell-option-menu/one-grid-cell-option-menu.component.d.ts +19 -2
  39. package/lib/components/one-grid-checkbox-header/one-grid-checkbox-header.component.d.ts +5 -2
  40. package/lib/components/one-grid-header/one-grid-header.component.d.ts +15 -7
  41. package/lib/components/one-grid-pagination/one-grid-pagination.component.d.ts +24 -5
  42. package/lib/components/one-grid-row-action/one-grid-row-action.component.d.ts +44 -0
  43. package/lib/components/one-grid-row-drag-handle/one-grid-row-drag-handle.component.d.ts +39 -0
  44. package/lib/core/directives/one-cell-text-expand.directive.d.ts +21 -9
  45. package/lib/core/instants/one-grid-api.class.d.ts +212 -26
  46. package/lib/core/instants/one-row-node.class.d.ts +67 -14
  47. package/lib/core/models/one-column-def-types.model.d.ts +89 -15
  48. package/lib/core/models/one-event-types.model.d.ts +24 -1
  49. package/lib/core/models/one-grid-types.model.d.ts +36 -1
  50. package/lib/core/models/one-row-drag.model.d.ts +44 -0
  51. package/lib/core/models/one-row.model.d.ts +0 -5
  52. package/lib/core/models/one-tree-data.model.d.ts +13 -0
  53. package/lib/core/models/one-validation.model.d.ts +12 -2
  54. package/lib/core/pipes/column-sort-state.pipe.d.ts +1 -1
  55. package/lib/core/services/og-column.service.d.ts +44 -3
  56. package/lib/core/services/one-grid-cell.service.d.ts +52 -4
  57. package/lib/core/services/one-grid-row-drag.service.d.ts +113 -0
  58. package/lib/core/services/one-grid-selection.service.d.ts +9 -0
  59. package/lib/helpers/one-column-def.helper.d.ts +19 -1
  60. package/lib/helpers/one-filter.helper.d.ts +29 -4
  61. package/lib/index.d.ts +5 -0
  62. package/lib/one-grid.module.d.ts +17 -19
  63. package/package.json +1 -2
  64. package/scss/_one-grid.scss +389 -17
  65. package/esm2022/lib/core/pipes/cell-disable-resolver.pipe.mjs +0 -26
  66. package/lib/core/pipes/cell-disable-resolver.pipe.d.ts +0 -9
@@ -1,7 +1,42 @@
1
+ import type { Type } from "@angular/core";
1
2
  import type { OneGridApi } from "../instants/one-grid-api.class";
2
3
  import type { OneRowNode } from "../instants/one-row-node.class";
3
- import type { OneColumnDef } from "./one-column-def-types.model";
4
+ import type { OneColumnDef, OneGroupColumnDef } from "./one-column-def-types.model";
5
+ import type { RowSelectionMode } from "./one-event-types.model";
6
+ import type { OneDetailCellRendererParams } from "./one-master-detail.model";
7
+ import type { OneCellRendererComponent } from "./one-tree-data.model";
4
8
  export type OneGridType = 'simple' | 'master' | 'detail' | 'tree' | null;
9
+ /**
10
+ * Everything `OneGridApi.init` needs to stand a grid up.
11
+ *
12
+ * An options object rather than a positional list: the previous signature took
13
+ * ten positional arguments, four of them optional and two of them booleans, so
14
+ * a call site was unreadable and adding an option meant touching every caller.
15
+ *
16
+ * `OneGridComponent` calls this from `ngOnInit`. Applications should not.
17
+ */
18
+ export interface OneGridInitOptions<T = any> {
19
+ /** Which role this instance plays. `OneGridComponent` derives it from its inputs. */
20
+ gridType: OneGridType;
21
+ /** Column definitions, before `defaultColumnDef` is merged in. */
22
+ columnDefs: OneColumnDef<T>[];
23
+ /** Merged into every column definition. */
24
+ defaultColumnDef?: OneColumnDef<T>;
25
+ /** Header groups. Columns join one by `groupId`. */
26
+ groupColumnDefs?: OneGroupColumnDef[];
27
+ /** Passed to renderers, getters and predicates; `componentParent.getRowId` is read from it. */
28
+ context?: any;
29
+ /** `null` disables row selection entirely. Read once, here. */
30
+ rowSelection?: RowSelectionMode;
31
+ /** Turns on the nested detail grid. Mutually exclusive with `treeData`. */
32
+ masterDetail?: boolean;
33
+ /** Detail grid options plus `getDetailRowData`. Required when `masterDetail` is on. */
34
+ detailCellRendererParams?: OneDetailCellRendererParams;
35
+ /** Render a component in the detail area instead of a nested grid. */
36
+ detailRendererComponent?: Type<OneCellRendererComponent>;
37
+ /** Turns on hierarchical row building. Mutually exclusive with `masterDetail`. */
38
+ treeData?: boolean;
39
+ }
5
40
  export interface OneGridReadyEvent<T = any> {
6
41
  api: OneGridApi<T>;
7
42
  }
@@ -0,0 +1,44 @@
1
+ import { OneRowNode } from '../instants/one-row-node.class';
2
+ /**
3
+ * Why row reordering is unavailable right now.
4
+ *
5
+ * Reordering only means something when the order you see is the order the data
6
+ * is in. Each of these breaks that, so the handle is disabled rather than
7
+ * silently dropping the move:
8
+ *
9
+ * - `sorted` — the displayed order is derived from the sort model, and the
10
+ * next sort pass rebuilds it from scratch. A manual move would
11
+ * be discarded the moment anything re-sorted.
12
+ * - `filtered` — rows are hidden between the ones you can see, so "drop below
13
+ * this row" has no single answer.
14
+ * - `treeData` — moving a node between parents is a reparent, not a reorder.
15
+ * Not supported yet; see the docs.
16
+ */
17
+ export type OneRowDragSuppressedReason = 'sorted' | 'filtered' | 'treeData';
18
+ /** Where a drag would land, and where it started. */
19
+ export interface OneRowDragEvent<T = any> {
20
+ /** The row being moved. */
21
+ node: OneRowNode<T>;
22
+ /** Index it started at, in the grid's row order. */
23
+ fromIndex: number;
24
+ /** Index it would land at once removed from `fromIndex` and reinserted. */
25
+ toIndex: number;
26
+ /** How the move was driven. Keyboard moves are one step at a time. */
27
+ source: 'pointer' | 'keyboard';
28
+ }
29
+ /**
30
+ * The live state of a drag, published by the row-drag service so the body can
31
+ * render the handle and the drop indicator. `null` when no drag is in flight.
32
+ */
33
+ export interface OneRowDragState {
34
+ rowId: string;
35
+ fromIndex: number;
36
+ /**
37
+ * Insertion boundary, in row units: 0 is above the first row, `n` is below
38
+ * the last. This is a gap index, not a row index — the drop indicator is
39
+ * drawn at `insertAt * itemSize`, and the resulting row index differs by
40
+ * one depending on the direction of travel.
41
+ */
42
+ insertAt: number;
43
+ source: 'pointer' | 'keyboard';
44
+ }
@@ -29,10 +29,5 @@ export interface OneRowNodeEventMap<T> {
29
29
  node: OneRowNode<T>;
30
30
  expanded: boolean;
31
31
  };
32
- childrenChanged: {
33
- node: OneRowNode<T>;
34
- children: OneRowNode<T>[];
35
- source: 'masterDetail' | 'treeData';
36
- };
37
32
  }
38
33
  export type OneRowNodeListener<T, K extends keyof OneRowNodeEventMap<T>> = (event: OneRowNodeEventMap<T>[K]) => void;
@@ -4,6 +4,19 @@ export type TreeNode<T> = {
4
4
  children?: TreeNode<T>[];
5
5
  } & T;
6
6
  export interface OneCellRendererComponent {
7
+ /**
8
+ * Called when the cell is created and again whenever its params change.
9
+ *
10
+ * The params stay loosely typed here, unlike `cellRenderer`'s: the same
11
+ * directive also mounts a master/detail row's custom detail renderer, and a
12
+ * detail row has no column — so `field` and `columnDef` genuinely cannot be
13
+ * promised. For a cell renderer they are always supplied.
14
+ *
15
+ * A component that does not implement this gets the params assigned onto its
16
+ * own fields instead, so a renderer with plain public properties works too —
17
+ * but not both: the fallback only applies when `oneInit` is absent.
18
+ */
7
19
  oneInit(params: OneCellRendererParams): void;
20
+ /** Part of the interface, but the renderer directive never calls it. */
8
21
  refresh(params: OneCellRendererParams): boolean;
9
22
  }
@@ -1,7 +1,17 @@
1
- export interface OneValidationResult<T> {
1
+ /**
2
+ * Validation errors for a single row, keyed by column field.
3
+ *
4
+ * A field is absent when it passed, which is why the values are optional —
5
+ * `errors[field]` is `string | undefined`, not `string`. Keying on
6
+ * `keyof T & string` matches `OneColumnDef<T>.field`, so a typo in a field name
7
+ * is a compile error rather than a lookup that silently returns undefined.
8
+ */
9
+ export type OneRowValidationErrors<T = any> = Partial<Record<keyof T & string, string>>;
10
+ export interface OneValidationResult<T = any> {
2
11
  valid: boolean;
3
12
  invalid: boolean;
4
- errors: Record<string, string>[];
13
+ /** One entry per row, in the order the rows were given. */
14
+ errors: OneRowValidationErrors<T>[];
5
15
  }
6
16
  export type OneValidatorFn<T = any> = (value: any, row?: T) => string | null;
7
17
  export type OneValidationRules<T = any> = {
@@ -2,7 +2,7 @@ import { PipeTransform } from '@angular/core';
2
2
  import { OneSortModel } from '../models/one-grid-types.model';
3
3
  import * as i0 from "@angular/core";
4
4
  export declare class ColumnSortStatePipe implements PipeTransform {
5
- transform(field: string, sortModel: OneSortModel[]): 'asc' | 'desc' | null;
5
+ transform(field: string, sortModel: readonly OneSortModel[]): 'asc' | 'desc' | null;
6
6
  static ɵfac: i0.ɵɵFactoryDeclaration<ColumnSortStatePipe, never>;
7
7
  static ɵpipe: i0.ɵɵPipeDeclaration<ColumnSortStatePipe, "columnSortState", false>;
8
8
  }
@@ -1,14 +1,33 @@
1
- import { OneCellRendererParams, OneColumnDef, OneGroupColumnDef } from '../models/one-column-def-types.model';
1
+ import { OneCellPresentationParams, OneCellRendererParams, OneColumnDef, OneGroupColumnDef } from '../models/one-column-def-types.model';
2
2
  import { ColumnChangedEvent } from '../models/one-event-types.model';
3
3
  import * as i0 from "@angular/core";
4
4
  export declare class OgColumnService {
5
5
  private defaultColumnDef;
6
+ /**
7
+ * The grid's `context`, so header callbacks receive the same one cell
8
+ * callbacks do. Set during init; null in a bare service.
9
+ */
10
+ private context;
6
11
  private columnDefs$;
7
12
  private groupColumnDefs$;
8
- initColumnDefs(defaultColumnDef: OneColumnDef, columnDefs: OneColumnDef[], groupColumnDefs: OneGroupColumnDef[]): void;
13
+ initColumnDefs(defaultColumnDef: OneColumnDef, columnDefs: OneColumnDef[], groupColumnDefs: OneGroupColumnDef[], context?: unknown): void;
9
14
  getColumnState(): ColumnChangedEvent;
10
15
  setGroupColumnDefs(groupColumnDefs: OneGroupColumnDef[]): void;
11
16
  setColumnDefs(columnDefs: OneColumnDef[]): void;
17
+ /**
18
+ * Move pinned columns to their edge and measure how far in each one sits.
19
+ *
20
+ * Display order becomes left-pinned, unpinned, right-pinned, with declared
21
+ * order preserved inside each band. `_pinnedOffset` is the distance from that
22
+ * column's own edge — the sum of the widths of the pinned columns outside it
23
+ * — which is what the sticky `left` / `right` binding needs.
24
+ *
25
+ * With nothing pinned this returns the same array, in the same order, so a
26
+ * grid that does not use the feature is unaffected.
27
+ */
28
+ private applyPinning;
29
+ /** Total width of the columns frozen against the given edge. */
30
+ getPinnedWidth(side: 'left' | 'right'): number;
12
31
  updateColumnDef(id: string, changes: Partial<OneColumnDef>): void;
13
32
  reorderColumnDefs(fromIndex: number, toIndex: number): void;
14
33
  /**
@@ -16,7 +35,29 @@ export declare class OgColumnService {
16
35
  */
17
36
  private recalculateGroups;
18
37
  resolveGroupPresentation(col: OneGroupColumnDef, params?: OneCellRendererParams): OneGroupColumnDef;
19
- resolveCellPresentation(col: OneColumnDef, params?: OneCellRendererParams): OneColumnDef;
38
+ /**
39
+ * Resolve a column's header presentation. Once per column, when the columns
40
+ * are set — a header is one cell for the whole column, so there is no row to
41
+ * resolve it against and nothing to redo per render.
42
+ *
43
+ * This used to resolve the cell hooks too, from the same call, with no params
44
+ * at all. Two bugs came out of that: any callback touching `params` threw a
45
+ * TypeError at init, and the header's resolved value was then overwritten by
46
+ * every cell that rendered, since the body re-ran the same method per cell
47
+ * with row params. In dev mode the disagreement surfaced as NG0100.
48
+ */
49
+ resolveHeaderPresentation(col: OneColumnDef): OneColumnDef;
50
+ /**
51
+ * Resolve one cell's class, for one row.
52
+ *
53
+ * Pure: the result is returned rather than written back onto the column def,
54
+ * which every row of that column shares. Writing to it worked only because
55
+ * the template resolved and read in the same expression — one render order
56
+ * away from every row showing the last row's class.
57
+ */
58
+ resolveCellClass(col: OneColumnDef, params: OneCellPresentationParams): string | string[] | undefined;
59
+ /** Resolve one cell's inline style, for one row. Pure, as above. */
60
+ resolveCellStyle(col: OneColumnDef, params: OneCellPresentationParams): Record<string, string> | undefined;
20
61
  static ɵfac: i0.ɵɵFactoryDeclaration<OgColumnService, never>;
21
62
  static ɵprov: i0.ɵɵInjectableDeclaration<OgColumnService>;
22
63
  }
@@ -1,5 +1,6 @@
1
- import { OneCellState, OneCellStates, OneColumnDef } from '../models/one-column-def-types.model';
1
+ import { OneCellPresentationParams, OneCellState, OneCellStates, OneColumnDef } from '../models/one-column-def-types.model';
2
2
  import { OneRowNode } from '../instants/one-row-node.class';
3
+ import type { OneGridApi } from '../instants/one-grid-api.class';
3
4
  import * as i0 from "@angular/core";
4
5
  export declare class OneGridCellService {
5
6
  private _cellFieldValueEmpty;
@@ -7,22 +8,69 @@ export declare class OneGridCellService {
7
8
  private _cellFieldValue;
8
9
  private _columnDefs;
9
10
  private _context;
11
+ private _api;
10
12
  applyColumnDefs(columnDefs: OneColumnDef[], context: any): void;
13
+ /**
14
+ * Back-reference to the grid api, so predicate params can carry it.
15
+ *
16
+ * Pushed in rather than injected: `OneGridApi` already depends on this
17
+ * service, and injecting it back would close a DI cycle.
18
+ */
19
+ setGridApi(api: OneGridApi | null): void;
20
+ /**
21
+ * The params every row-scoped column callback receives.
22
+ *
23
+ * One builder, deliberately: `editable`, `updatable`, `disable`, `rowDrag`,
24
+ * `hideActionButton`, `cellClass`, `cellStyle`, `cellRenderer` and
25
+ * `valueFormatter` are all "decide something about this cell", and a consumer
26
+ * should not have to remember which of them happens to be handed `value` or
27
+ * `field`. Each used to be called with a slightly different subset.
28
+ */
29
+ cellParams(column: OneColumnDef, node: OneRowNode): OneCellPresentationParams;
11
30
  /**
12
31
  * Generate New Node States
13
32
  */
14
33
  generateCellStates(node: OneRowNode): OneCellStates | null;
34
+ /**
35
+ * The cell's value: the `valueGetter`'s output where the column declares one,
36
+ * the raw field otherwise. This is the value, not the display text — see
37
+ * {@link formatValue}.
38
+ */
39
+ private resolveValue;
40
+ /**
41
+ * Apply the column's `valueFormatter`.
42
+ *
43
+ * `valueFormatter` was declared on the column definition and called from
44
+ * nowhere — a consumer could write one, get no error, and see nothing happen.
45
+ * It runs on displayed text only, after the `valueGetter`, and is deliberately
46
+ * skipped for placeholders: an empty cell already has its own mechanism in
47
+ * `cellRendererParams.placeholder`, and two features competing to fill the
48
+ * same gap is worse than one.
49
+ *
50
+ * Note that sorting and filtering read the underlying row data, not this —
51
+ * which is exactly why formatting belongs here rather than in the getter.
52
+ */
53
+ private formatValue;
15
54
  /**
16
55
  * Generate New Node State Based on Column Field
17
56
  */
18
57
  generateCellState(node: OneRowNode, column: OneColumnDef): OneCellState;
58
+ /** Whether this cell may be edited at all. A capability: unset means no. */
59
+ editableFn: (column: OneColumnDef, node: OneRowNode) => boolean;
19
60
  /**
20
- * One Column Def Params Resolver
61
+ * The second edit gate, ANDed with `editable`.
62
+ *
63
+ * A restriction, so unset means "no restriction". It used to resolve through
64
+ * `!!undefined` to `false`, closing the gate on every column that did not name
65
+ * it — so `editable: true` on its own made nothing editable.
21
66
  */
22
- editableFn: (column: OneColumnDef, node: OneRowNode) => boolean;
23
67
  updatableFn: (column: OneColumnDef, node: OneRowNode) => boolean;
68
+ /** Disables this column's row action buttons. Not an edit gate. */
24
69
  disableFn: (column: OneColumnDef, node: OneRowNode) => boolean;
25
- dragableFn: (column: OneColumnDef, node: OneRowNode) => boolean;
70
+ /** Hides this column's row action buttons entirely. */
71
+ hideActionButtonFn: (column: OneColumnDef, node: OneRowNode) => boolean;
72
+ /** Whether this cell carries a row drag handle. */
73
+ rowDragFn: (column: OneColumnDef, node: OneRowNode) => boolean;
26
74
  valueGetterFn: (column: OneColumnDef, node: OneRowNode) => any;
27
75
  static ɵfac: i0.ɵɵFactoryDeclaration<OneGridCellService, never>;
28
76
  static ɵprov: i0.ɵɵInjectableDeclaration<OneGridCellService>;
@@ -0,0 +1,113 @@
1
+ import { OnDestroy } from '@angular/core';
2
+ import { BehaviorSubject } from 'rxjs';
3
+ import { OneRowDragEvent, OneRowDragState } from '../models/one-row-drag.model';
4
+ import { OneRowNode } from '../instants/one-row-node.class';
5
+ import * as i0 from "@angular/core";
6
+ /** What the body has to lend the service to run a drag. */
7
+ export interface OneRowDragContext<T = any> {
8
+ /** The scrolling element the rows live in. */
9
+ viewport: HTMLElement;
10
+ /** Fixed row height. The whole index calculation rests on rows being uniform. */
11
+ itemSize: number;
12
+ /** Current display order. Read fresh on every move — a drag mutates it. */
13
+ nodes: () => OneRowNode<T>[];
14
+ /** Apply the move. Returns false if the grid refused it. */
15
+ move: (fromIndex: number, toIndex: number) => boolean;
16
+ }
17
+ /**
18
+ * Owns one row-drag gesture at a time.
19
+ *
20
+ * Built on pointer events rather than HTML5 drag-and-drop or the CDK's
21
+ * drag-drop:
22
+ *
23
+ * - HTML5 DnD does not fire for touch at all, and its drag image cannot be
24
+ * styled to match the grid.
25
+ * - `cdkDropList` assumes every item it manages is in the DOM. Inside a virtual
26
+ * scroll viewport rows unmount as they leave the buffer, so the list it
27
+ * thinks it is sorting is only ever the visible window.
28
+ * - Pointer events cover mouse, touch and pen in one path, and pointer capture
29
+ * keeps the gesture alive when the finger leaves the row it started on.
30
+ *
31
+ * Because rows are a fixed `itemSize`, the drop target is arithmetic on the
32
+ * pointer's Y rather than a hit test against row elements — which is also why
33
+ * it stays correct for rows that are scrolled out and not rendered.
34
+ */
35
+ export declare class OneGridRowDragService<T = any> implements OnDestroy {
36
+ private readonly zone;
37
+ /** Live drag, for the body to render the handle state and the indicator. */
38
+ readonly state$: BehaviorSubject<OneRowDragState>;
39
+ /** Screen-reader narration for the keyboard path. */
40
+ readonly announcement$: BehaviorSubject<string>;
41
+ private context;
42
+ private pointerId;
43
+ private handle;
44
+ private startY;
45
+ private armed;
46
+ private lastClientY;
47
+ private scrollFrame;
48
+ /** A move already applied during this drag, so a cancel can undo it. */
49
+ private appliedFrom;
50
+ private onMove?;
51
+ private onEnd?;
52
+ attach(context: OneRowDragContext<T>): void;
53
+ get state(): OneRowDragState | null;
54
+ get dragging(): boolean;
55
+ /**
56
+ * Begin a pointer drag. Nothing visible happens until the pointer has moved
57
+ * {@link DRAG_THRESHOLD_PX}, so a click on the handle — which is also the
58
+ * keyboard affordance — is not swallowed by a zero-distance drag.
59
+ */
60
+ startPointerDrag(event: PointerEvent, node: OneRowNode<T>, handlers?: {
61
+ onEnd?: (event: OneRowDragEvent<T> | null) => void;
62
+ }): void;
63
+ private handlePointerMove;
64
+ private handlePointerUp;
65
+ private handlePointerCancel;
66
+ /** Escape aborts a pointer drag, the same as it does a keyboard one. */
67
+ private handlePointerKeydown;
68
+ /**
69
+ * Turn the pointer's Y into an insertion boundary.
70
+ *
71
+ * Boundaries, not rows: the value is where the row would be *inserted*, so
72
+ * 0 is above the first row and `length` is below the last. Rounding rather
73
+ * than flooring puts the split at the middle of each row, which is what
74
+ * makes the indicator flip when you cross the halfway point.
75
+ */
76
+ private updateFromPointer;
77
+ /**
78
+ * Scroll when the pointer sits near an edge, so rows outside the viewport
79
+ * are reachable without letting go. Runs on rAF while the pointer is parked
80
+ * in the zone, and re-derives the target each frame because the content
81
+ * moves while the pointer does not.
82
+ */
83
+ private updateAutoScroll;
84
+ private stopAutoScroll;
85
+ private teardownPointer;
86
+ /** Space/Enter on the handle: pick the row up, or put it down. */
87
+ toggleKeyboardDrag(node: OneRowNode<T>, handlers?: {
88
+ onEnd?: (event: OneRowDragEvent<T> | null) => void;
89
+ }): void;
90
+ /**
91
+ * Arrow keys move the row a position at a time, applying as they go.
92
+ *
93
+ * Applied rather than previewed because the row has to be seen to move: a
94
+ * keyboard user gets no drag image, and a preview line alone tells someone
95
+ * relying on a screen reader nothing about where the row now sits. Escape
96
+ * still restores the original position.
97
+ */
98
+ moveKeyboard(delta: number): boolean;
99
+ private commit;
100
+ /** Abort, restoring anything a keyboard drag already applied. */
101
+ cancel(): void;
102
+ private finish;
103
+ private reset;
104
+ private publish;
105
+ private announce;
106
+ private describe;
107
+ private indexOf;
108
+ private nodeAt;
109
+ private clamp;
110
+ ngOnDestroy(): void;
111
+ static ɵfac: i0.ɵɵFactoryDeclaration<OneGridRowDragService<any>, never>;
112
+ static ɵprov: i0.ɵɵInjectableDeclaration<OneGridRowDragService<any>>;
113
+ }
@@ -9,6 +9,15 @@ export declare class OneGridSelectionService {
9
9
  setSelectionMode(mode: RowSelectionMode): void;
10
10
  toggleSelection(rowId: string, selected: boolean): void;
11
11
  toggleAllSelection(allIds: string[], selected: boolean): void;
12
+ /**
13
+ * Tri-state for the header checkbox, over the rows currently present.
14
+ *
15
+ * This compared `_selectedIds.size` with `allIds.length` and never checked
16
+ * that the selected ids were among the present ones. Selecting two rows and
17
+ * then swapping in two different rows reported `checked` with nothing
18
+ * actually selected, because the two counts happened to match. Counting the
19
+ * intersection is the only thing that answers the question being asked.
20
+ */
12
21
  getSelectAllState(allIds: (string)[]): OneCheckboxState;
13
22
  selectAll(rowIds: string[]): void;
14
23
  deselectAll(): void;
@@ -1,4 +1,16 @@
1
1
  import { OneCellRendererParams, OneColumnDef, OneValueGetterParams } from "../core/models/one-column-def-types.model";
2
+ /** Width used when a column defines neither `width` nor `minWidth`. */
3
+ export declare const ONE_DEFAULT_COLUMN_WIDTH = 150;
4
+ /**
5
+ * The rendered width of a column, clamped to its bounds.
6
+ *
7
+ * `width`, `minWidth` and `maxWidth` are all optional, and the previous inline
8
+ * expression — repeated in two places — fell back to `minWidth` when `width`
9
+ * was absent. With neither set that produced `undefined`, and summing it gave
10
+ * a `NaN` row width, so the row collapsed. This is total: every combination of
11
+ * present and absent bounds resolves to a usable number.
12
+ */
13
+ export declare function resolveColumnWidth<T>(column: OneColumnDef<T>): number;
2
14
  /**
3
15
  * Apply Default Column Definitions
4
16
  */
@@ -6,7 +18,13 @@ export declare function applyDefaultColumnDef<T>(columnDefs: OneColumnDef<T>[],
6
18
  /**
7
19
  * One Column Params Resolver (Cell Renderer)
8
20
  */
9
- export declare function resolveOneCellRendererParams<T>(prop: boolean | ((params: any) => boolean), params: OneCellRendererParams<T>): boolean;
21
+ export declare function resolveOneCellRendererParams<T>(prop: boolean | ((params: any) => boolean), params: OneCellRendererParams<T>,
22
+ /**
23
+ * What an unset property means: `false` for a capability you opt into,
24
+ * `true` for a restriction you opt out of. `!!prop` could not tell the two
25
+ * apart, which left `updatable` — a restriction — defaulting to "deny".
26
+ */
27
+ whenUnset?: boolean): boolean;
10
28
  /**
11
29
  * One Column Params Resolver (Generics)
12
30
  */
@@ -5,16 +5,41 @@ import { OneFilterModel } from "../core/models/one-filter.model";
5
5
  *
6
6
  * Rules:
7
7
  * - A node is visible if it matches the filters or has a matching descendant.
8
- * - A node is expanded if it has a matching descendant.
8
+ * - While a filter is active, a node is expanded iff it has a matching
9
+ * descendant, so the hit is revealed.
10
+ *
11
+ * Overwriting `expanded` is only correct *while filtering*. This runs from
12
+ * `applyFilters`, which every `setRowData` / `updateRowData` calls, so doing it
13
+ * unconditionally force-expanded every parent on each data update: it made
14
+ * `groupDefaultExpanded` inert for tree data and collapsed expanded
15
+ * master-detail rows (they have no children, so `childMatch` is false).
9
16
  *
10
17
  * @returns True if the current node or any descendant matches.
11
18
  */
12
- export declare function filterTreeNode<T = any>(node: OneRowNode<T>, filters: OneFilterModel[] | null, quick: string): boolean;
19
+ export declare function filterTreeNode<T = any>(node: OneRowNode<T>, filters: OneFilterModel[] | null, quick: string, fields?: readonly string[]): boolean;
20
+ /**
21
+ * Whether anything is actually filtering right now. A model entry with no
22
+ * conditions matches everything, so it does not count as active.
23
+ */
24
+ export declare function isFilterActive(filters: OneFilterModel[] | null, quick: string): boolean;
13
25
  /**
14
26
  * Apply advanced per-column filters
15
27
  */
16
28
  export declare function matchesAdvancedFilters<T = any>(node: OneRowNode<T>, filters: OneFilterModel[] | null): boolean;
17
29
  /**
18
- * Apply quick filter across all fields
30
+ * Apply the quick filter to one row.
31
+ *
32
+ * Searches the fields the grid actually shows, when it is told what they are.
33
+ * It used to walk `Object.values(node.data)`, which had three consequences, all
34
+ * of them wrong:
35
+ *
36
+ * - a property with no column was searchable, so a user could match rows on
37
+ * data the grid never displayed;
38
+ * - a nested object stringified to `[object Object]`, so typing `object`
39
+ * matched every row holding one;
40
+ * - in a tree, `children` did the same, so most parents matched most queries.
41
+ *
42
+ * Non-primitive values are skipped regardless, so the `[object Object]` haystack
43
+ * cannot come back through a declared column either.
19
44
  */
20
- export declare function matchesQuickFilter<T = any>(node: OneRowNode<T>, quick: string): boolean;
45
+ export declare function matchesQuickFilter<T = any>(node: OneRowNode<T>, quick: string, fields?: readonly string[]): boolean;
package/lib/index.d.ts CHANGED
@@ -6,9 +6,14 @@ export * from './core/services/one-grid-event.service';
6
6
  export * from './core/services/one-grid-selection.service';
7
7
  export * from './core/services/one-grid-expansion.service';
8
8
  export * from './core/services/one-grid-cell.service';
9
+ export * from './core/services/one-grid-row-drag.service';
9
10
  export * from './core/services/one-grid-tree-data.service';
10
11
  export * from './core/models/constants/one-pagination.constant';
11
12
  export * from './core/models/one-column-def-types.model';
13
+ export * from './core/models/one-filter.model';
14
+ export * from './core/models/one-master-detail.model';
15
+ export * from './core/models/one-row.model';
16
+ export * from './core/models/one-row-drag.model';
12
17
  export * from './core/models/one-event-types.model';
13
18
  export * from './core/models/one-grid-types.model';
14
19
  export * from './core/models/one-pagination-types.model';
@@ -17,29 +17,27 @@ import * as i15 from "./core/pipes/cell-invalid.pipe";
17
17
  import * as i16 from "./core/pipes/cell-selected.pipe";
18
18
  import * as i17 from "./core/pipes/cell-action-button-enable.pipe";
19
19
  import * as i18 from "./core/pipes/cell-number-value.pipe";
20
- import * as i19 from "./core/pipes/cell-disable-resolver.pipe";
21
- import * as i20 from "./core/pipes/cell-field.pipe";
22
- import * as i21 from "./core/pipes/cell-key.pipe";
23
- import * as i22 from "./core/pipes/cell-level-padding.pipe";
24
- import * as i23 from "./core/pipes/column-sort-state.pipe";
25
- import * as i24 from "./core/pipes/header-checkbox-disabled.pipe";
26
- import * as i25 from "./core/pipes/header-checkbox-checked.pipe";
27
- import * as i26 from "./core/pipes/header-checkbox-indeterminate.pipe";
28
- import * as i27 from "./core/pipes/cell-state-renderer.pipe";
29
- import * as i28 from "./core/pipes/cell-state-group-renderer.pipe";
30
- import * as i29 from "./core/directives/one-cell-input-validator.directive";
31
- import * as i30 from "./core/directives/one-cell-renderer-component.directive";
32
- import * as i31 from "./core/directives/one-cell-text-expand.directive";
33
- import * as i32 from "./components/one-grid-cell-currency/one-grid-cell-currency.component";
34
- import * as i33 from "./components/one-grid-cell-option-menu/one-grid-cell-option-menu.component";
20
+ import * as i19 from "./core/pipes/cell-field.pipe";
21
+ import * as i20 from "./core/pipes/cell-key.pipe";
22
+ import * as i21 from "./core/pipes/cell-level-padding.pipe";
23
+ import * as i22 from "./core/pipes/column-sort-state.pipe";
24
+ import * as i23 from "./core/pipes/header-checkbox-disabled.pipe";
25
+ import * as i24 from "./core/pipes/header-checkbox-checked.pipe";
26
+ import * as i25 from "./core/pipes/header-checkbox-indeterminate.pipe";
27
+ import * as i26 from "./core/pipes/cell-state-renderer.pipe";
28
+ import * as i27 from "./core/pipes/cell-state-group-renderer.pipe";
29
+ import * as i28 from "./core/directives/one-cell-input-validator.directive";
30
+ import * as i29 from "./core/directives/one-cell-renderer-component.directive";
31
+ import * as i30 from "./core/directives/one-cell-text-expand.directive";
32
+ import * as i31 from "./components/one-grid-cell-currency/one-grid-cell-currency.component";
33
+ import * as i32 from "./components/one-grid-cell-option-menu/one-grid-cell-option-menu.component";
34
+ import * as i33 from "./components/one-grid-row-drag-handle/one-grid-row-drag-handle.component";
35
35
  import * as i34 from "@angular/common";
36
36
  import * as i35 from "@angular/forms";
37
37
  import * as i36 from "@angular/cdk/scrolling";
38
- import * as i37 from "@ng-bootstrap/ng-bootstrap";
39
- import * as i38 from "@angular/cdk/drag-drop";
40
- import * as i39 from "lucide-angular";
38
+ import * as i37 from "lucide-angular";
41
39
  export declare class OneGridModule {
42
40
  static ɵfac: i0.ɵɵFactoryDeclaration<OneGridModule, never>;
43
- static ɵmod: i0.ɵɵNgModuleDeclaration<OneGridModule, [typeof i1.OneGridComponent, typeof i2.OneGridHeaderComponent, typeof i3.OneGridBodyComponent, typeof i4.OneGridCheckboxComponent, typeof i5.OneGridCheckboxHeaderComponent, typeof i6.OneGridRowActionComponent, typeof i7.OneGridPaginationComponent, typeof i8.OneGridStatusComponent, typeof i9.OneGridCellGroupRendererComponent, typeof i10.CellFieldValueEmptyPipe, typeof i11.CellValueGetterPipe, typeof i12.CellFieldValuePipe, typeof i13.CellActionButtonVisiblePipe, typeof i14.CellEditablePipe, typeof i15.CellInvalidPipe, typeof i16.CellSelectedPipe, typeof i17.CellActionButtonEnablePipe, typeof i18.CellNumberValuePipe, typeof i19.CellDisableResolverPipe, typeof i20.CellFieldPipe, typeof i21.CellKeyPipe, typeof i22.CellLevelPaddingPipe, typeof i23.ColumnSortStatePipe, typeof i24.HeaderCheckboxDisabledPipe, typeof i25.HeaderCheckboxCheckedPipe, typeof i26.HeaderCheckboxIndeterminatePipe, typeof i27.CellStateRendererPipe, typeof i28.CellStateGroupRendererPipe, typeof i29.OneCellInputValidatorDirective, typeof i30.OneCellRendererComponentDirective, typeof i31.OneCellTextExpandDirective, typeof i32.OneGridCellCurrencyComponent, typeof i33.OneGridCellOptionMenuComponent], [typeof i34.CommonModule, typeof i35.FormsModule, typeof i36.ScrollingModule, typeof i37.NgbTypeahead, typeof i37.NgbHighlight, typeof i35.ReactiveFormsModule, typeof i38.CdkDragPlaceholder, typeof i39.LucideAngularModule], [typeof i1.OneGridComponent]>;
41
+ static ɵmod: i0.ɵɵNgModuleDeclaration<OneGridModule, [typeof i1.OneGridComponent, typeof i2.OneGridHeaderComponent, typeof i3.OneGridBodyComponent, typeof i4.OneGridCheckboxComponent, typeof i5.OneGridCheckboxHeaderComponent, typeof i6.OneGridRowActionComponent, typeof i7.OneGridPaginationComponent, typeof i8.OneGridStatusComponent, typeof i9.OneGridCellGroupRendererComponent, typeof i10.CellFieldValueEmptyPipe, typeof i11.CellValueGetterPipe, typeof i12.CellFieldValuePipe, typeof i13.CellActionButtonVisiblePipe, typeof i14.CellEditablePipe, typeof i15.CellInvalidPipe, typeof i16.CellSelectedPipe, typeof i17.CellActionButtonEnablePipe, typeof i18.CellNumberValuePipe, typeof i19.CellFieldPipe, typeof i20.CellKeyPipe, typeof i21.CellLevelPaddingPipe, typeof i22.ColumnSortStatePipe, typeof i23.HeaderCheckboxDisabledPipe, typeof i24.HeaderCheckboxCheckedPipe, typeof i25.HeaderCheckboxIndeterminatePipe, typeof i26.CellStateRendererPipe, typeof i27.CellStateGroupRendererPipe, typeof i28.OneCellInputValidatorDirective, typeof i29.OneCellRendererComponentDirective, typeof i30.OneCellTextExpandDirective, typeof i31.OneGridCellCurrencyComponent, typeof i32.OneGridCellOptionMenuComponent, typeof i33.OneGridRowDragHandleComponent], [typeof i34.CommonModule, typeof i35.FormsModule, typeof i36.ScrollingModule, typeof i35.ReactiveFormsModule, typeof i37.LucideAngularModule], [typeof i1.OneGridComponent]>;
44
42
  static ɵinj: i0.ɵɵInjectorDeclaration<OneGridModule>;
45
43
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@one-grid-core/angular",
3
- "version": "0.1.0-beta.6",
3
+ "version": "0.2.0",
4
4
  "description": "OneGrid — a feature-rich Angular data grid component with tree data, master/detail, editing, selection, pagination, and virtual scrolling.",
5
5
  "keywords": [
6
6
  "angular",
@@ -33,7 +33,6 @@
33
33
  "@angular/core": ">=17.0.0",
34
34
  "@angular/forms": ">=17.0.0",
35
35
  "@angular/cdk": ">=17.0.0",
36
- "@ng-bootstrap/ng-bootstrap": ">=16.0.0",
37
36
  "lucide-angular": ">=0.400.0",
38
37
  "rxjs": "^6.5.3 || ^7.4.0"
39
38
  },