@kouji-ui/core 0.10.0 → 0.11.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.
@@ -22122,6 +22122,26 @@ class KjTable {
22122
22122
  */
22123
22123
  kjGetRowId = input(undefined, /* @ts-ignore */
22124
22124
  ...(ngDevMode ? [{ debugName: "kjGetRowId" }] : /* istanbul ignore next */ []));
22125
+ /**
22126
+ * Tree rows: returns a row's children (TanStack `getSubRows`). Children are
22127
+ * real table rows with the same columns, shown under their parent while it
22128
+ * is expanded. `undefined` (default) keeps the table flat.
22129
+ */
22130
+ kjGetSubRows = input(undefined, /* @ts-ignore */
22131
+ ...(ngDevMode ? [{ debugName: "kjGetSubRows" }] : /* istanbul ignore next */ []));
22132
+ /**
22133
+ * Tree rows: whether selecting a parent also selects its children
22134
+ * (TanStack `enableSubRowSelection`). Defaults to `false` — every row is
22135
+ * selected on its own.
22136
+ */
22137
+ kjSelectSubRows = input(false, { ...(ngDevMode ? { debugName: "kjSelectSubRows" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
22138
+ /**
22139
+ * Tree rows: whether parents start expanded. Applies to every parent with
22140
+ * no explicit expanded state — on first render, to rows loaded later, and
22141
+ * again after {@link resetExpansion} (an infinite table's request change).
22142
+ * Defaults to `false`.
22143
+ */
22144
+ kjDefaultExpanded = input(false, { ...(ngDevMode ? { debugName: "kjDefaultExpanded" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
22125
22145
  _state = signal(DEFAULT_STATE, /* @ts-ignore */
22126
22146
  ...(ngDevMode ? [{ debugName: "_state" }] : /* istanbul ignore next */ []));
22127
22147
  /**
@@ -22176,6 +22196,37 @@ class KjTable {
22176
22196
  setInfinite(on) {
22177
22197
  this._infinite.set(on);
22178
22198
  }
22199
+ /**
22200
+ * Whether a tree parent with no explicit entry in `state.expanded` is open.
22201
+ * Starts at `kjDefaultExpanded`; {@link expandAll} / {@link collapseAll}
22202
+ * flip it so rows loaded later follow the last bulk action.
22203
+ */
22204
+ _expandDefault = signal(false, /* @ts-ignore */
22205
+ ...(ngDevMode ? [{ debugName: "_expandDefault" }] : /* istanbul ignore next */ []));
22206
+ /**
22207
+ * `state.expanded` as TanStack sees it. Open-by-default with no exceptions
22208
+ * is handed over as `true`: TanStack skips expansion altogether for an
22209
+ * empty record, and `getIsRowExpanded` still keeps leaf rows closed.
22210
+ */
22211
+ tanstackExpanded = computed(() => {
22212
+ const expanded = this._state().expanded;
22213
+ if (expanded === true)
22214
+ return true;
22215
+ if (this._expandDefault() && Object.keys(expanded).length === 0)
22216
+ return true;
22217
+ return expanded;
22218
+ }, /* @ts-ignore */
22219
+ ...(ngDevMode ? [{ debugName: "tanstackExpanded" }] : /* istanbul ignore next */ []));
22220
+ /** Whether a row is expanded: its explicit state, else the tree default for parents. */
22221
+ isRowExpanded(row) {
22222
+ const expanded = this._state().expanded;
22223
+ if (expanded === true)
22224
+ return true;
22225
+ const own = expanded[row.id];
22226
+ if (own !== undefined)
22227
+ return own;
22228
+ return this._expandDefault() && (row.subRows?.length ?? 0) > 0;
22229
+ }
22179
22230
  /** Rows handed to TanStack plus, in infinite mode, their positions in the full result set. */
22180
22231
  compacted = computed(() => {
22181
22232
  const data = this.kjTableData();
@@ -22268,7 +22319,17 @@ class KjTable {
22268
22319
  manualSorting: this._infinite(),
22269
22320
  manualFiltering: this._infinite(),
22270
22321
  rowCount: this._rowCount() ?? undefined,
22271
- state: { ...this._state(), columnSizingInfo: this._columnSizingInfo() },
22322
+ getSubRows: this.kjGetSubRows(),
22323
+ getIsRowExpanded: row => this.isRowExpanded(row),
22324
+ enableSubRowSelection: this.kjSelectSubRows(),
22325
+ // Expansion is reset by the directive itself (see the constructor): an
22326
+ // infinite table's page loads must not wipe it.
22327
+ autoResetExpanded: false,
22328
+ state: {
22329
+ ...this._state(),
22330
+ expanded: this.tanstackExpanded(),
22331
+ columnSizingInfo: this._columnSizingInfo(),
22332
+ },
22272
22333
  onSortingChange: u => this.patch('sorting', u),
22273
22334
  onColumnFiltersChange: u => this.patch('columnFilters', u),
22274
22335
  onGlobalFilterChange: u => this.patch('globalFilter', u),
@@ -22293,6 +22354,91 @@ class KjTable {
22293
22354
  enableRowSelection: true,
22294
22355
  enableMultiRowSelection: true,
22295
22356
  }));
22357
+ constructor() {
22358
+ // New rows reset the expansion to `kjDefaultExpanded` (TanStack's own
22359
+ // auto-reset, kept), except in infinite mode where data changes are page
22360
+ // loads — the infinite wrapper calls `resetExpansion()` on a real reset.
22361
+ let seeded = false;
22362
+ effect(() => {
22363
+ this.kjTableData();
22364
+ if (!seeded) {
22365
+ seeded = true;
22366
+ return;
22367
+ }
22368
+ untracked(() => {
22369
+ if (!this._infinite())
22370
+ this.resetExpansion();
22371
+ });
22372
+ });
22373
+ // A new `kjDefaultExpanded` restarts the tree from that default.
22374
+ effect(() => {
22375
+ const open = this.kjDefaultExpanded();
22376
+ untracked(() => {
22377
+ if (this._expandDefault() === open)
22378
+ return;
22379
+ this._expandDefault.set(open);
22380
+ this.patch('expanded', {});
22381
+ });
22382
+ });
22383
+ }
22384
+ // ── Tree rows ───────────────────────────────────────────────────────────
22385
+ /**
22386
+ * Whether every loaded parent row is expanded (`false` when no row has
22387
+ * children). Rows of an infinite table that are not loaded yet do not count.
22388
+ */
22389
+ isAllExpanded = computed(() => {
22390
+ this._state();
22391
+ this._expandDefault();
22392
+ let parents = 0;
22393
+ for (const row of this.table().getCoreRowModel().flatRows) {
22394
+ if (!row.subRows?.length)
22395
+ continue;
22396
+ parents++;
22397
+ if (!this.isRowExpanded(row))
22398
+ return false;
22399
+ }
22400
+ return parents > 0;
22401
+ }, /* @ts-ignore */
22402
+ ...(ngDevMode ? [{ debugName: "isAllExpanded" }] : /* istanbul ignore next */ []));
22403
+ /**
22404
+ * Whether a row is expanded — its own choice, else `kjDefaultExpanded`
22405
+ * (or the last expand-all / collapse-all) for parents.
22406
+ * @param row The row.
22407
+ */
22408
+ getRowExpanded(row) {
22409
+ return this.isRowExpanded(row);
22410
+ }
22411
+ /**
22412
+ * Expand or collapse one row. Unlike TanStack's `row.toggleExpanded()`, the
22413
+ * choice is stored explicitly, so it holds against `kjDefaultExpanded`.
22414
+ * @param row The row.
22415
+ * @param expanded The new state; omitted, the current one flips.
22416
+ * @returns The row's new expanded state.
22417
+ */
22418
+ setRowExpanded(row, expanded) {
22419
+ const next = expanded ?? !this.isRowExpanded(row);
22420
+ const prev = this._state().expanded;
22421
+ // `true` ("every row") becomes "open by default" plus this exception.
22422
+ if (prev === true)
22423
+ this._expandDefault.set(true);
22424
+ this.patch('expanded', { ...(prev === true ? {} : prev), [row.id]: next });
22425
+ return next;
22426
+ }
22427
+ /** Expand every parent row, including the ones loaded later. */
22428
+ expandAll() {
22429
+ this._expandDefault.set(true);
22430
+ this.patch('expanded', {});
22431
+ }
22432
+ /** Collapse every parent row, including the ones loaded later. */
22433
+ collapseAll() {
22434
+ this._expandDefault.set(false);
22435
+ this.patch('expanded', {});
22436
+ }
22437
+ /** Forget per-row expansion and go back to `kjDefaultExpanded` — e.g. when the rows are replaced. */
22438
+ resetExpansion() {
22439
+ this._expandDefault.set(untracked(this.kjDefaultExpanded));
22440
+ this.patch('expanded', {});
22441
+ }
22296
22442
  /** Merge a partial state. Unspecified slices are left untouched. */
22297
22443
  setState(partial) {
22298
22444
  this._state.update(s => ({ ...s, ...partial }));
@@ -22327,7 +22473,7 @@ class KjTable {
22327
22473
  */
22328
22474
  get columnApi() { return this.buildApi().columnApi; }
22329
22475
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjTable, deps: [], target: i0.ɵɵFactoryTarget.Directive });
22330
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.5", type: KjTable, isStandalone: true, selector: "[kjTable]", inputs: { kjTable: { classPropertyName: "kjTable", publicName: "kjTable", isSignal: true, isRequired: true, transformFunction: null }, kjTableData: { classPropertyName: "kjTableData", publicName: "kjTableData", isSignal: true, isRequired: false, transformFunction: null }, kjGetRowId: { classPropertyName: "kjGetRowId", publicName: "kjGetRowId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { kjTableData: "kjTableDataChange" }, providers: [{ provide: KJ_TABLE, useExisting: KjTable }], exportAs: ["kjTable"], ngImport: i0 });
22476
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.5", type: KjTable, isStandalone: true, selector: "[kjTable]", inputs: { kjTable: { classPropertyName: "kjTable", publicName: "kjTable", isSignal: true, isRequired: true, transformFunction: null }, kjTableData: { classPropertyName: "kjTableData", publicName: "kjTableData", isSignal: true, isRequired: false, transformFunction: null }, kjGetRowId: { classPropertyName: "kjGetRowId", publicName: "kjGetRowId", isSignal: true, isRequired: false, transformFunction: null }, kjGetSubRows: { classPropertyName: "kjGetSubRows", publicName: "kjGetSubRows", isSignal: true, isRequired: false, transformFunction: null }, kjSelectSubRows: { classPropertyName: "kjSelectSubRows", publicName: "kjSelectSubRows", isSignal: true, isRequired: false, transformFunction: null }, kjDefaultExpanded: { classPropertyName: "kjDefaultExpanded", publicName: "kjDefaultExpanded", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { kjTableData: "kjTableDataChange" }, providers: [{ provide: KJ_TABLE, useExisting: KjTable }], exportAs: ["kjTable"], ngImport: i0 });
22331
22477
  }
22332
22478
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjTable, decorators: [{
22333
22479
  type: Directive,
@@ -22337,7 +22483,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
22337
22483
  exportAs: 'kjTable',
22338
22484
  providers: [{ provide: KJ_TABLE, useExisting: KjTable }],
22339
22485
  }]
22340
- }], propDecorators: { kjTable: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjTable", required: true }] }], kjTableData: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjTableData", required: false }] }, { type: i0.Output, args: ["kjTableDataChange"] }], kjGetRowId: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjGetRowId", required: false }] }] } });
22486
+ }], ctorParameters: () => [], propDecorators: { kjTable: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjTable", required: true }] }], kjTableData: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjTableData", required: false }] }, { type: i0.Output, args: ["kjTableDataChange"] }], kjGetRowId: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjGetRowId", required: false }] }], kjGetSubRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjGetSubRows", required: false }] }], kjSelectSubRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjSelectSubRows", required: false }] }], kjDefaultExpanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjDefaultExpanded", required: false }] }] } });
22341
22487
  /** Angular's NG0950 — a required input read before its first binding. */
22342
22488
  function isUnsetRequiredInput(error) {
22343
22489
  return typeof error === 'object' && error !== null && error.code === -950;
@@ -22566,9 +22712,19 @@ class KjTableRow {
22566
22712
  /** TanStack row instance — pass from getRowModel().rows. */
22567
22713
  kjRow = input.required(/* @ts-ignore */
22568
22714
  ...(ngDevMode ? [{ debugName: "kjRow" }] : /* istanbul ignore next */ []));
22715
+ /**
22716
+ * Overrides the 1-based `aria-rowindex` — for rows whose place in the grid
22717
+ * is not their `row.index`, like the children of a tree row. `null`
22718
+ * (default) derives it from the row.
22719
+ */
22720
+ kjAriaRowIndex = input(null, /* @ts-ignore */
22721
+ ...(ngDevMode ? [{ debugName: "kjAriaRowIndex" }] : /* istanbul ignore next */ []));
22569
22722
  table = injectParent(KJ_TABLE, { child: 'KjTableRow', parent: '[kjTable]' });
22570
22723
  /** 1-based ARIA index — accounts for header row(s). */
22571
22724
  ariaRowIndex = computed(() => {
22725
+ const override = this.kjAriaRowIndex();
22726
+ if (override != null)
22727
+ return override;
22572
22728
  const row = this.kjRow();
22573
22729
  // Infinite mode: the row's place in the whole result set, not in the loaded window.
22574
22730
  const source = row.depth === 0 ? this.table.sourceIndex()?.[row.index] : undefined;
@@ -22584,7 +22740,7 @@ class KjTableRow {
22584
22740
  }, /* @ts-ignore */
22585
22741
  ...(ngDevMode ? [{ debugName: "isSelected" }] : /* istanbul ignore next */ []));
22586
22742
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjTableRow, deps: [], target: i0.ɵɵFactoryTarget.Directive });
22587
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.5", type: KjTableRow, isStandalone: true, selector: "[kjTableRow]", inputs: { kjRow: { classPropertyName: "kjRow", publicName: "kjRow", isSignal: true, isRequired: true, transformFunction: null } }, host: { attributes: { "role": "row" }, properties: { "attr.aria-rowindex": "ariaRowIndex()", "attr.aria-selected": "isSelectable() ? isSelected() : null", "attr.data-selected": "isSelected() ? \"\" : null" } }, ngImport: i0 });
22743
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.5", type: KjTableRow, isStandalone: true, selector: "[kjTableRow]", inputs: { kjRow: { classPropertyName: "kjRow", publicName: "kjRow", isSignal: true, isRequired: true, transformFunction: null }, kjAriaRowIndex: { classPropertyName: "kjAriaRowIndex", publicName: "kjAriaRowIndex", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "row" }, properties: { "attr.aria-rowindex": "ariaRowIndex()", "attr.aria-selected": "isSelectable() ? isSelected() : null", "attr.data-selected": "isSelected() ? \"\" : null" } }, ngImport: i0 });
22588
22744
  }
22589
22745
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjTableRow, decorators: [{
22590
22746
  type: Directive,
@@ -22598,7 +22754,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
22598
22754
  '[attr.data-selected]': 'isSelected() ? "" : null',
22599
22755
  },
22600
22756
  }]
22601
- }], propDecorators: { kjRow: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjRow", required: true }] }] } });
22757
+ }], propDecorators: { kjRow: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjRow", required: true }] }], kjAriaRowIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjAriaRowIndex", required: false }] }] } });
22602
22758
 
22603
22759
  /** Context token provided by `KjTableKeyboardNav` and injected by `KjTableCell`. */
22604
22760
  const KJ_TABLE_KEYBOARD_NAV = new InjectionToken('KjTableKeyboardNav');