@kouji-ui/core 0.10.0 → 0.11.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.
@@ -8807,6 +8807,10 @@ function bindPresets(configToken) {
8807
8807
  provide: KJ_VARIANT_PRESET,
8808
8808
  useFactory: () => {
8809
8809
  const c = inject(configToken);
8810
+ // A config without a variant list (e.g. one that only sizes) keeps the
8811
+ // enclosing preset, so it never hands descendants `values: undefined`.
8812
+ if (!c.variants)
8813
+ return inject(KJ_VARIANT_PRESET, { skipSelf: true });
8810
8814
  return { values: c.variants, default: c.defaults.variant };
8811
8815
  },
8812
8816
  },
@@ -8814,6 +8818,10 @@ function bindPresets(configToken) {
8814
8818
  provide: KJ_SIZE_PRESET,
8815
8819
  useFactory: () => {
8816
8820
  const c = inject(configToken);
8821
+ // Same for sizes: `KjTabs` binds a variant-only config, and a `KjSize`
8822
+ // descendant (a `kj-kbd` in a tab panel) must see the enclosing preset.
8823
+ if (!c.sizes)
8824
+ return inject(KJ_SIZE_PRESET, { skipSelf: true });
8817
8825
  return { values: c.sizes, default: c.defaults.size };
8818
8826
  },
8819
8827
  },
@@ -22122,6 +22130,26 @@ class KjTable {
22122
22130
  */
22123
22131
  kjGetRowId = input(undefined, /* @ts-ignore */
22124
22132
  ...(ngDevMode ? [{ debugName: "kjGetRowId" }] : /* istanbul ignore next */ []));
22133
+ /**
22134
+ * Tree rows: returns a row's children (TanStack `getSubRows`). Children are
22135
+ * real table rows with the same columns, shown under their parent while it
22136
+ * is expanded. `undefined` (default) keeps the table flat.
22137
+ */
22138
+ kjGetSubRows = input(undefined, /* @ts-ignore */
22139
+ ...(ngDevMode ? [{ debugName: "kjGetSubRows" }] : /* istanbul ignore next */ []));
22140
+ /**
22141
+ * Tree rows: whether selecting a parent also selects its children
22142
+ * (TanStack `enableSubRowSelection`). Defaults to `false` — every row is
22143
+ * selected on its own.
22144
+ */
22145
+ kjSelectSubRows = input(false, { ...(ngDevMode ? { debugName: "kjSelectSubRows" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
22146
+ /**
22147
+ * Tree rows: whether parents start expanded. Applies to every parent with
22148
+ * no explicit expanded state — on first render, to rows loaded later, and
22149
+ * again after {@link resetExpansion} (an infinite table's request change).
22150
+ * Defaults to `false`.
22151
+ */
22152
+ kjDefaultExpanded = input(false, { ...(ngDevMode ? { debugName: "kjDefaultExpanded" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
22125
22153
  _state = signal(DEFAULT_STATE, /* @ts-ignore */
22126
22154
  ...(ngDevMode ? [{ debugName: "_state" }] : /* istanbul ignore next */ []));
22127
22155
  /**
@@ -22176,6 +22204,37 @@ class KjTable {
22176
22204
  setInfinite(on) {
22177
22205
  this._infinite.set(on);
22178
22206
  }
22207
+ /**
22208
+ * Whether a tree parent with no explicit entry in `state.expanded` is open.
22209
+ * Starts at `kjDefaultExpanded`; {@link expandAll} / {@link collapseAll}
22210
+ * flip it so rows loaded later follow the last bulk action.
22211
+ */
22212
+ _expandDefault = signal(false, /* @ts-ignore */
22213
+ ...(ngDevMode ? [{ debugName: "_expandDefault" }] : /* istanbul ignore next */ []));
22214
+ /**
22215
+ * `state.expanded` as TanStack sees it. Open-by-default with no exceptions
22216
+ * is handed over as `true`: TanStack skips expansion altogether for an
22217
+ * empty record, and `getIsRowExpanded` still keeps leaf rows closed.
22218
+ */
22219
+ tanstackExpanded = computed(() => {
22220
+ const expanded = this._state().expanded;
22221
+ if (expanded === true)
22222
+ return true;
22223
+ if (this._expandDefault() && Object.keys(expanded).length === 0)
22224
+ return true;
22225
+ return expanded;
22226
+ }, /* @ts-ignore */
22227
+ ...(ngDevMode ? [{ debugName: "tanstackExpanded" }] : /* istanbul ignore next */ []));
22228
+ /** Whether a row is expanded: its explicit state, else the tree default for parents. */
22229
+ isRowExpanded(row) {
22230
+ const expanded = this._state().expanded;
22231
+ if (expanded === true)
22232
+ return true;
22233
+ const own = expanded[row.id];
22234
+ if (own !== undefined)
22235
+ return own;
22236
+ return this._expandDefault() && (row.subRows?.length ?? 0) > 0;
22237
+ }
22179
22238
  /** Rows handed to TanStack plus, in infinite mode, their positions in the full result set. */
22180
22239
  compacted = computed(() => {
22181
22240
  const data = this.kjTableData();
@@ -22268,7 +22327,17 @@ class KjTable {
22268
22327
  manualSorting: this._infinite(),
22269
22328
  manualFiltering: this._infinite(),
22270
22329
  rowCount: this._rowCount() ?? undefined,
22271
- state: { ...this._state(), columnSizingInfo: this._columnSizingInfo() },
22330
+ getSubRows: this.kjGetSubRows(),
22331
+ getIsRowExpanded: row => this.isRowExpanded(row),
22332
+ enableSubRowSelection: this.kjSelectSubRows(),
22333
+ // Expansion is reset by the directive itself (see the constructor): an
22334
+ // infinite table's page loads must not wipe it.
22335
+ autoResetExpanded: false,
22336
+ state: {
22337
+ ...this._state(),
22338
+ expanded: this.tanstackExpanded(),
22339
+ columnSizingInfo: this._columnSizingInfo(),
22340
+ },
22272
22341
  onSortingChange: u => this.patch('sorting', u),
22273
22342
  onColumnFiltersChange: u => this.patch('columnFilters', u),
22274
22343
  onGlobalFilterChange: u => this.patch('globalFilter', u),
@@ -22293,6 +22362,91 @@ class KjTable {
22293
22362
  enableRowSelection: true,
22294
22363
  enableMultiRowSelection: true,
22295
22364
  }));
22365
+ constructor() {
22366
+ // New rows reset the expansion to `kjDefaultExpanded` (TanStack's own
22367
+ // auto-reset, kept), except in infinite mode where data changes are page
22368
+ // loads — the infinite wrapper calls `resetExpansion()` on a real reset.
22369
+ let seeded = false;
22370
+ effect(() => {
22371
+ this.kjTableData();
22372
+ if (!seeded) {
22373
+ seeded = true;
22374
+ return;
22375
+ }
22376
+ untracked(() => {
22377
+ if (!this._infinite())
22378
+ this.resetExpansion();
22379
+ });
22380
+ });
22381
+ // A new `kjDefaultExpanded` restarts the tree from that default.
22382
+ effect(() => {
22383
+ const open = this.kjDefaultExpanded();
22384
+ untracked(() => {
22385
+ if (this._expandDefault() === open)
22386
+ return;
22387
+ this._expandDefault.set(open);
22388
+ this.patch('expanded', {});
22389
+ });
22390
+ });
22391
+ }
22392
+ // ── Tree rows ───────────────────────────────────────────────────────────
22393
+ /**
22394
+ * Whether every loaded parent row is expanded (`false` when no row has
22395
+ * children). Rows of an infinite table that are not loaded yet do not count.
22396
+ */
22397
+ isAllExpanded = computed(() => {
22398
+ this._state();
22399
+ this._expandDefault();
22400
+ let parents = 0;
22401
+ for (const row of this.table().getCoreRowModel().flatRows) {
22402
+ if (!row.subRows?.length)
22403
+ continue;
22404
+ parents++;
22405
+ if (!this.isRowExpanded(row))
22406
+ return false;
22407
+ }
22408
+ return parents > 0;
22409
+ }, /* @ts-ignore */
22410
+ ...(ngDevMode ? [{ debugName: "isAllExpanded" }] : /* istanbul ignore next */ []));
22411
+ /**
22412
+ * Whether a row is expanded — its own choice, else `kjDefaultExpanded`
22413
+ * (or the last expand-all / collapse-all) for parents.
22414
+ * @param row The row.
22415
+ */
22416
+ getRowExpanded(row) {
22417
+ return this.isRowExpanded(row);
22418
+ }
22419
+ /**
22420
+ * Expand or collapse one row. Unlike TanStack's `row.toggleExpanded()`, the
22421
+ * choice is stored explicitly, so it holds against `kjDefaultExpanded`.
22422
+ * @param row The row.
22423
+ * @param expanded The new state; omitted, the current one flips.
22424
+ * @returns The row's new expanded state.
22425
+ */
22426
+ setRowExpanded(row, expanded) {
22427
+ const next = expanded ?? !this.isRowExpanded(row);
22428
+ const prev = this._state().expanded;
22429
+ // `true` ("every row") becomes "open by default" plus this exception.
22430
+ if (prev === true)
22431
+ this._expandDefault.set(true);
22432
+ this.patch('expanded', { ...(prev === true ? {} : prev), [row.id]: next });
22433
+ return next;
22434
+ }
22435
+ /** Expand every parent row, including the ones loaded later. */
22436
+ expandAll() {
22437
+ this._expandDefault.set(true);
22438
+ this.patch('expanded', {});
22439
+ }
22440
+ /** Collapse every parent row, including the ones loaded later. */
22441
+ collapseAll() {
22442
+ this._expandDefault.set(false);
22443
+ this.patch('expanded', {});
22444
+ }
22445
+ /** Forget per-row expansion and go back to `kjDefaultExpanded` — e.g. when the rows are replaced. */
22446
+ resetExpansion() {
22447
+ this._expandDefault.set(untracked(this.kjDefaultExpanded));
22448
+ this.patch('expanded', {});
22449
+ }
22296
22450
  /** Merge a partial state. Unspecified slices are left untouched. */
22297
22451
  setState(partial) {
22298
22452
  this._state.update(s => ({ ...s, ...partial }));
@@ -22327,7 +22481,7 @@ class KjTable {
22327
22481
  */
22328
22482
  get columnApi() { return this.buildApi().columnApi; }
22329
22483
  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 });
22484
+ 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
22485
  }
22332
22486
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjTable, decorators: [{
22333
22487
  type: Directive,
@@ -22337,7 +22491,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
22337
22491
  exportAs: 'kjTable',
22338
22492
  providers: [{ provide: KJ_TABLE, useExisting: KjTable }],
22339
22493
  }]
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 }] }] } });
22494
+ }], 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
22495
  /** Angular's NG0950 — a required input read before its first binding. */
22342
22496
  function isUnsetRequiredInput(error) {
22343
22497
  return typeof error === 'object' && error !== null && error.code === -950;
@@ -22566,9 +22720,19 @@ class KjTableRow {
22566
22720
  /** TanStack row instance — pass from getRowModel().rows. */
22567
22721
  kjRow = input.required(/* @ts-ignore */
22568
22722
  ...(ngDevMode ? [{ debugName: "kjRow" }] : /* istanbul ignore next */ []));
22723
+ /**
22724
+ * Overrides the 1-based `aria-rowindex` — for rows whose place in the grid
22725
+ * is not their `row.index`, like the children of a tree row. `null`
22726
+ * (default) derives it from the row.
22727
+ */
22728
+ kjAriaRowIndex = input(null, /* @ts-ignore */
22729
+ ...(ngDevMode ? [{ debugName: "kjAriaRowIndex" }] : /* istanbul ignore next */ []));
22569
22730
  table = injectParent(KJ_TABLE, { child: 'KjTableRow', parent: '[kjTable]' });
22570
22731
  /** 1-based ARIA index — accounts for header row(s). */
22571
22732
  ariaRowIndex = computed(() => {
22733
+ const override = this.kjAriaRowIndex();
22734
+ if (override != null)
22735
+ return override;
22572
22736
  const row = this.kjRow();
22573
22737
  // Infinite mode: the row's place in the whole result set, not in the loaded window.
22574
22738
  const source = row.depth === 0 ? this.table.sourceIndex()?.[row.index] : undefined;
@@ -22584,7 +22748,7 @@ class KjTableRow {
22584
22748
  }, /* @ts-ignore */
22585
22749
  ...(ngDevMode ? [{ debugName: "isSelected" }] : /* istanbul ignore next */ []));
22586
22750
  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 });
22751
+ 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
22752
  }
22589
22753
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjTableRow, decorators: [{
22590
22754
  type: Directive,
@@ -22598,7 +22762,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
22598
22762
  '[attr.data-selected]': 'isSelected() ? "" : null',
22599
22763
  },
22600
22764
  }]
22601
- }], propDecorators: { kjRow: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjRow", required: true }] }] } });
22765
+ }], propDecorators: { kjRow: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjRow", required: true }] }], kjAriaRowIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjAriaRowIndex", required: false }] }] } });
22602
22766
 
22603
22767
  /** Context token provided by `KjTableKeyboardNav` and injected by `KjTableCell`. */
22604
22768
  const KJ_TABLE_KEYBOARD_NAV = new InjectionToken('KjTableKeyboardNav');