twico-ui 1.3.1 → 1.4.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.
package/dist/index.cjs CHANGED
@@ -208,7 +208,9 @@ function initials(name) {
208
208
  function safeSrc(url) {
209
209
  if (url == null) return void 0;
210
210
  const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
211
- return s.startsWith("javascript:") || s.startsWith("vbscript:") ? void 0 : url;
211
+ if (s.startsWith("javascript:") || s.startsWith("vbscript:")) return void 0;
212
+ if (s.startsWith("data:") && !s.startsWith("data:image/")) return void 0;
213
+ return url;
212
214
  }
213
215
  function Avatar({
214
216
  src,
@@ -3801,6 +3803,7 @@ th.twc-dt__rownum .twc-dt__th-inner { padding-inline: 8px; gap: 2px; justify-con
3801
3803
  .twc-dt__sw[data-on="true"]::after { transform: translateX(14px); }
3802
3804
  .twc-dt__panel-head { display: flex; align-items: center; justify-content: space-between; padding: 6px 8px 8px; }
3803
3805
  .twc-dt__panel-title { font-size: var(--text-xs); font-weight: 700; letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--color-text-subtle); }
3806
+ .twc-dt__panel-count { font-weight: 600; color: var(--color-text-muted); text-transform: none; letter-spacing: 0; margin-inline-start: 6px; font-variant-numeric: tabular-nums; }
3804
3807
  .twc-dt__link { border: none; background: transparent; color: var(--color-primary); font-family: inherit; font-size: var(--text-xs); font-weight: 600; cursor: pointer; padding: 2px 4px; border-radius: var(--radius-sm); }
3805
3808
  .twc-dt__link:hover { background: var(--color-primary-subtle); }
3806
3809
 
@@ -4198,7 +4201,7 @@ function Datatable({
4198
4201
  loading = false,
4199
4202
  rowKey,
4200
4203
  checkboxSelection = false,
4201
- density: densityProp = "standard",
4204
+ density: densityProp = "comfortable",
4202
4205
  pageSize = 10,
4203
4206
  pageSizeOptions = [5, 10, 25, 50],
4204
4207
  height = 440,
@@ -4206,7 +4209,9 @@ function Datatable({
4206
4209
  rowCount,
4207
4210
  onServerChange,
4208
4211
  batchActions = [],
4209
- showExport = true,
4212
+ showExport = false,
4213
+ showDensity = false,
4214
+ showPivot = false,
4210
4215
  exportFilename = "export",
4211
4216
  aggregationValues = null,
4212
4217
  disableColumnReorder = false,
@@ -4745,7 +4750,7 @@ function Datatable({
4745
4750
  rowFocusRef.current = null;
4746
4751
  const root = gridRef.current;
4747
4752
  if (!root) return;
4748
- const sel = typeof CSS !== "undefined" && CSS.escape ? CSS.escape(String(key)) : String(key).replace(/"/g, '\\"');
4753
+ const sel = typeof CSS !== "undefined" && CSS.escape ? CSS.escape(String(key)) : String(key).replace(/[\\"]/g, "\\$&");
4749
4754
  const el = root.querySelector(`.twc-dt__row-handle[data-row-key="${sel}"]`);
4750
4755
  if (el) el.focus();
4751
4756
  });
@@ -5295,6 +5300,8 @@ function Datatable({
5295
5300
  };
5296
5301
  const shownColRows = cols.filter((c) => c.field !== "__pinactions__" && c.headerName.toLowerCase().includes(colQuery.trim().toLowerCase())).sort((a, b) => orderIdxOf(a.field) - orderIdxOf(b.field));
5297
5302
  const rowNumMatch = rowNumbers && "row number".includes(colQuery.trim().toLowerCase());
5303
+ const manageableCols = cols.filter((c) => c.field !== "__pinactions__");
5304
+ const visibleColCount = manageableCols.filter((c) => !hidden.has(c.field)).length;
5298
5305
  const rppOptions = Array.from(new Set([...pageSizeOptions || [], pageSize].filter((n) => n > 0))).sort((a, b) => a - b).map((n) => ({ value: String(n), label: String(n) }));
5299
5306
  const totalCols = ordered.length + (checkboxSelection ? 1 : 0) + (showRowNum ? 1 : 0);
5300
5307
  function renderGroupRow(item) {
@@ -5657,11 +5664,11 @@ function Datatable({
5657
5664
  ]
5658
5665
  }
5659
5666
  ),
5660
- /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: "twc-dt__tbtn", "data-tip": "Change row density", onClick: () => setDensity((d) => d === "compact" ? "standard" : d === "standard" ? "comfortable" : "compact"), children: [
5667
+ showDensity ? /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: "twc-dt__tbtn", "data-tip": "Change row density", onClick: () => setDensity((d) => d === "compact" ? "standard" : d === "standard" ? "comfortable" : "compact"), children: [
5661
5668
  /* @__PURE__ */ jsxRuntime.jsx(Svg, { d: I.density }),
5662
5669
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__tlabel", children: density[0].toUpperCase() + density.slice(1) })
5663
- ] }),
5664
- /* @__PURE__ */ jsxRuntime.jsxs(
5670
+ ] }) : null,
5671
+ showAggregation ? /* @__PURE__ */ jsxRuntime.jsxs(
5665
5672
  "button",
5666
5673
  {
5667
5674
  type: "button",
@@ -5686,8 +5693,8 @@ function Datatable({
5686
5693
  aggOn && hasAggregation ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__tbadge", children: ordered.filter((c) => aggOf(c)).length }) : null
5687
5694
  ]
5688
5695
  }
5689
- ),
5690
- /* @__PURE__ */ jsxRuntime.jsxs(
5696
+ ) : null,
5697
+ showPivot || pivotMode || pivot != null || pivotActive ? /* @__PURE__ */ jsxRuntime.jsxs(
5691
5698
  "button",
5692
5699
  {
5693
5700
  type: "button",
@@ -5712,7 +5719,7 @@ function Datatable({
5712
5719
  pivotActive ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__tdot", "aria-label": "on", role: "img" }) : null
5713
5720
  ]
5714
5721
  }
5715
- ),
5722
+ ) : null,
5716
5723
  showExport ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "twc-dt__export", children: [
5717
5724
  /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: "twc-dt__export-main", "data-tip": "Export to CSV", onClick: () => exportData("csv"), "aria-label": "Export to CSV", children: [
5718
5725
  /* @__PURE__ */ jsxRuntime.jsx(Svg, { d: I.download }),
@@ -6281,7 +6288,14 @@ function Datatable({
6281
6288
  ) : null,
6282
6289
  panel === "columns" && panelPos ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-dt__pop twc-dt__cols", style: { top: panelPos.top, left: panelPos.left }, role: "dialog", "aria-label": "Column settings", children: [
6283
6290
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-dt__panel-head", children: [
6284
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__panel-title", children: "Columns" }),
6291
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "twc-dt__panel-title", children: [
6292
+ "Columns ",
6293
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "twc-dt__panel-count", title: `${visibleColCount} of ${manageableCols.length} columns shown`, children: [
6294
+ visibleColCount,
6295
+ "/",
6296
+ manageableCols.length
6297
+ ] })
6298
+ ] }),
6285
6299
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
6286
6300
  /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-dt__link", onClick: () => setHidden(/* @__PURE__ */ new Set()), children: "Show all" }),
6287
6301
  /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-dt__link", onClick: () => setHidden(new Set(cols.filter((c) => c.hideable).map((c) => c.field))), children: "Hide all" })
@@ -8857,8 +8871,10 @@ var SIDEBAR_CSS = `
8857
8871
  .twc-sidebar__badge { flex: none; font-size: 11px; font-weight: var(--font-bold); padding: 1px 7px; border-radius: var(--radius-full); background: var(--color-primary); color: var(--color-primary-fg); opacity: 1; visibility: visible;
8858
8872
  transition: opacity var(--duration-fast) var(--ease-standard) var(--duration-fast), visibility 0s; }
8859
8873
  .twc-sidebar[data-collapsed="true"] .twc-sidebar__badge { opacity: 0; visibility: hidden; transition: opacity var(--duration-instant) var(--ease-standard), visibility 0s var(--duration-instant); }
8860
- /* Collapsed: pad the head so the brand mark lines up with the nav icon column (23px). */
8861
- .twc-sidebar[data-collapsed="true"] .twc-sidebar__head { padding: 0 calc(var(--space-3) + 11px); }
8874
+ /* Collapsed: centre the brand mark in the 68px rail (\u2248 the nav icon column) with no
8875
+ right padding, so a mark wider than the icons isn't clipped. flex-start (not
8876
+ justify-content) keeps it from jolting to centre while the rail is still wide. */
8877
+ .twc-sidebar[data-collapsed="true"] .twc-sidebar__head { padding-inline: 18px 0; }
8862
8878
  .twc-sidebar[data-collapsed="true"] .twc-sidebar__brand, .twc-sidebar[data-collapsed="true"] .twc-sidebar__foot-user { font-size: 0; gap: 0; }
8863
8879
  .twc-sidebar[data-collapsed="true"] .twc-sidebar__foot-user { justify-content: center; }
8864
8880
  .twc-sidebar__brand > :not(:first-child) { visibility: visible; transition: opacity var(--duration-fast) var(--ease-standard) var(--duration-fast), visibility 0s; }
@@ -9087,7 +9103,7 @@ function Slider({
9087
9103
  }
9088
9104
  function onKeyDown(e) {
9089
9105
  if (disabled) return;
9090
- let next = val;
9106
+ let next;
9091
9107
  if (e.key === "ArrowRight" || e.key === "ArrowUp") next = clampSnap(val + step);
9092
9108
  else if (e.key === "ArrowLeft" || e.key === "ArrowDown") next = clampSnap(val - step);
9093
9109
  else if (e.key === "Home") next = min;