@kodaris/krubble-components 1.0.63 → 1.0.64

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.
@@ -4619,6 +4619,7 @@
4619
4619
  class KRTableModel {
4620
4620
  constructor() {
4621
4621
  this.title = '';
4622
+ this.description = '';
4622
4623
  this.actions = [];
4623
4624
  this.columns = [];
4624
4625
  this.displayedColumns = [];
@@ -4661,6 +4662,13 @@
4661
4662
  this._columnWidthsLocked = false;
4662
4663
  this._model = new KRTableModel();
4663
4664
  this.def = { columns: [] };
4665
+ /**
4666
+ * Table layout variant.
4667
+ * - 'default': Full-page table that fills parent height with centered search.
4668
+ * - 'card': Embedded table that sizes itself to content, left-aligns search, and
4669
+ * reserves space for pageSize rows to prevent layout shift.
4670
+ */
4671
+ this.variant = 'default';
4664
4672
  this._handleClickOutside = (e) => {
4665
4673
  const path = e.composedPath();
4666
4674
  if (this._columnPickerOpen) {
@@ -4719,6 +4727,9 @@
4719
4727
  if (this.def.title) {
4720
4728
  this._model.title = this.def.title;
4721
4729
  }
4730
+ if (this.def.description) {
4731
+ this._model.description = this.def.description;
4732
+ }
4722
4733
  if (this.def.actions) {
4723
4734
  this._model.actions = this.def.actions;
4724
4735
  }
@@ -4733,6 +4744,7 @@
4733
4744
  }
4734
4745
  if (typeof this.def.pageSize === 'number') {
4735
4746
  this._model.pageSize = this.def.pageSize;
4747
+ this._pageSize = this.def.pageSize;
4736
4748
  }
4737
4749
  if (this.def.rowClickable) {
4738
4750
  this._model.rowClickable = this.def.rowClickable;
@@ -4790,6 +4802,7 @@
4790
4802
  }
4791
4803
  }
4792
4804
  updated(changedProperties) {
4805
+ this.classList.toggle('kr-table--card', this.variant === 'card');
4793
4806
  this._updateScrollFlags();
4794
4807
  this._syncSlottedContent();
4795
4808
  }
@@ -5087,6 +5100,9 @@
5087
5100
  // Skip if already locked (prevents shifts on pagination changes)
5088
5101
  if (this._searchPositionLocked)
5089
5102
  return;
5103
+ // In card mode, search is left-aligned via CSS — no position locking needed
5104
+ if (this.variant === 'card')
5105
+ return;
5090
5106
  const search = this.shadowRoot?.querySelector('.search');
5091
5107
  const searchField = search?.querySelector('.search-field');
5092
5108
  if (!search || !searchField)
@@ -5559,12 +5575,25 @@
5559
5575
  <svg viewBox="0 0 24 24" fill="currentColor"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg>
5560
5576
  </span>
5561
5577
  </div>
5578
+ `;
5579
+ }
5580
+ /** Renders the card title block (title + description) above the toolbar in card mode. */
5581
+ _renderCardHeader() {
5582
+ if (this.variant !== 'card')
5583
+ return A;
5584
+ if (!this._model.title && !this._model.description)
5585
+ return A;
5586
+ return b `
5587
+ <div class="card-header">
5588
+ ${this._model.title ? b `<h2 class="card-header__title">${this._model.title}</h2>` : A}
5589
+ ${this._model.description ? b `<p class="card-header__description">${this._model.description}</p>` : A}
5590
+ </div>
5562
5591
  `;
5563
5592
  }
5564
5593
  /**
5565
5594
  * Renders the header toolbar containing:
5566
- * - Title (left)
5567
- * - Search bar with view selector dropdown (center)
5595
+ * - Title (left, default variant only)
5596
+ * - Search bar with view selector dropdown (center, or left-aligned in card variant)
5568
5597
  * - Tools (right): page navigation, refresh button, column visibility picker, actions dropdown
5569
5598
  *
5570
5599
  * Hidden when there's no title, no actions, and data fits on one page.
@@ -5575,7 +5604,7 @@
5575
5604
  }
5576
5605
  return b `
5577
5606
  <div class="header">
5578
- <div class="title">${this._model.title ?? ''}</div>
5607
+ ${this._model.title && this.variant !== 'card' ? b `<div class="title">${this._model.title}</div>` : A}
5579
5608
  ${this._model.dataSource?.mode === 'db' && !this._model.columns.some(col => col.searchable) ? b `<div class="search"></div>` : b `
5580
5609
  <div class="search">
5581
5610
  <!-- TODO: Saved views dropdown
@@ -5953,8 +5982,13 @@
5953
5982
  }
5954
5983
  /** Renders the scrollable data grid with column headers and rows. */
5955
5984
  _renderTable() {
5985
+ const wrapperStyle = {};
5986
+ if (this.variant === 'card') {
5987
+ // Reserve space for header row + pageSize data rows to prevent layout shift
5988
+ wrapperStyle['min-height'] = `${48 + (this._pageSize * 48)}px`;
5989
+ }
5956
5990
  return b `
5957
- <div class="wrapper">
5991
+ <div class="wrapper" style=${o$1(wrapperStyle)}>
5958
5992
  <div class="overlay-left"></div>
5959
5993
  <div class="overlay-right"></div>
5960
5994
  ${this._renderStatus()}
@@ -6022,6 +6056,7 @@
6022
6056
  return b `<slot></slot>`;
6023
6057
  }
6024
6058
  return b `
6059
+ ${this._renderCardHeader()}
6025
6060
  ${this._renderHeader()}
6026
6061
  ${this._renderTable()}
6027
6062
  ${this._renderFilterPanel()}
@@ -6060,7 +6095,7 @@
6060
6095
  }
6061
6096
 
6062
6097
  .title {
6063
- font-size: 20px;
6098
+ font-size: 18px;
6064
6099
  font-weight: 600;
6065
6100
  color: #000;
6066
6101
  }
@@ -6077,7 +6112,6 @@
6077
6112
  .content {
6078
6113
  height: 100%;
6079
6114
  overflow: auto;
6080
- padding-bottom: 24px;
6081
6115
  }
6082
6116
 
6083
6117
  /* -------------------------------------------------------------------------
@@ -6091,6 +6125,11 @@
6091
6125
  min-width: 0;
6092
6126
  }
6093
6127
 
6128
+ /* In card mode, align search left instead of center */
6129
+ :host(.kr-table--card) .search {
6130
+ justify-content: flex-start;
6131
+ }
6132
+
6094
6133
  .search-field {
6095
6134
  width: 100%;
6096
6135
  max-width: 400px;
@@ -6885,6 +6924,48 @@
6885
6924
  padding: 16px;
6886
6925
  }
6887
6926
 
6927
+ /* Card variant — self-contained card with border, auto height, left-aligned search */
6928
+ :host(.kr-table--card) {
6929
+ height: auto;
6930
+ /* overflow: visible; */
6931
+ overflow: hidden;
6932
+ /* border: 1px solid #e5e7eb; */
6933
+ /* border-radius: 8px; */
6934
+ border: 1px solid #c6c6cd;
6935
+ border-radius: 12px;
6936
+ background: #fff;
6937
+ }
6938
+
6939
+ .card-header {
6940
+ padding: 24px 24px 16px;
6941
+ }
6942
+
6943
+ .card-header__title {
6944
+ font-size: 18px;
6945
+ font-weight: 600;
6946
+ color: #1f2937;
6947
+ margin: 0;
6948
+ }
6949
+
6950
+ .card-header__description {
6951
+ font-size: 14px;
6952
+ color: #1f2937;
6953
+ margin: 12px 0 0;
6954
+ }
6955
+
6956
+ :host(.kr-table--card) .header {
6957
+ margin: 0 24px;
6958
+ }
6959
+
6960
+ :host(.kr-table--card) .wrapper {
6961
+ flex: none;
6962
+ overflow: visible;
6963
+ }
6964
+
6965
+ :host(.kr-table--card) .content {
6966
+ height: auto;
6967
+ }
6968
+
6888
6969
  `];
6889
6970
  __decorate$b([
6890
6971
  r$1()
@@ -6934,6 +7015,9 @@
6934
7015
  __decorate$b([
6935
7016
  n$1({ type: Object })
6936
7017
  ], exports.KRTable.prototype, "def", void 0);
7018
+ __decorate$b([
7019
+ n$1({ type: String, reflect: true })
7020
+ ], exports.KRTable.prototype, "variant", void 0);
6937
7021
  exports.KRTable = __decorate$b([
6938
7022
  t$1('kr-table')
6939
7023
  ], exports.KRTable);