@homebound/beam 4.40.1 → 4.42.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.d.cts CHANGED
@@ -5974,6 +5974,8 @@ type RowProps<R extends Kinded> = {
5974
5974
  setResizedWidth: (columnId: string, width: number, columnIndex: number) => void;
5975
5975
  disableColumnResizing: boolean;
5976
5976
  calculatePreviewWidth: (columnId: string, newWidth: number, columnIndex: number) => number;
5977
+ /** Column ids that take `columnStriping`. Stable until the visible columns change. */
5978
+ stripedColumnIds?: ReadonlySet<string>;
5977
5979
  onDragStart?: (row: GridDataRow<R>, event: React__default.DragEvent<HTMLElement>) => void;
5978
5980
  onDragEnd?: (row: GridDataRow<R>, event: React__default.DragEvent<HTMLElement>) => void;
5979
5981
  onDrop?: (row: GridDataRow<R>, event: React__default.DragEvent<HTMLElement>) => void;
@@ -6324,6 +6326,8 @@ type GridStyle = {
6324
6326
  });
6325
6327
  /** Allows for customization of the background color used to denote an "active" row */
6326
6328
  activeBgColor?: BeamColor;
6329
+ /** Resolved `columnStriping` color. */
6330
+ columnStripeColor?: BeamColor;
6327
6331
  /** Defines styles for the group row which holds the selected rows that have been filtered out */
6328
6332
  keptGroupRowCss?: Properties;
6329
6333
  /** Defines styles for the last row `keptGroup` to provide separation from the rest of the table */
@@ -6356,6 +6360,11 @@ type GridStyleDef = {
6356
6360
  highlightOnHover?: boolean;
6357
6361
  /** Rounds the top corners of the first head-row cells. Defaults to true */
6358
6362
  roundedHeader?: boolean;
6363
+ /**
6364
+ * Zebra on the 2nd, 4th, 6th… content column. A leading group is striped only when a content column precedes it.
6365
+ * Select, collapse, and gutter columns are skipped. A column `bgColor` wins.
6366
+ */
6367
+ columnStriping?: BeamColor;
6359
6368
  };
6360
6369
  declare const getTableStyles: (props?: GridStyleDef) => GridStyle;
6361
6370
  /** Defines row-specific styling for each given row `kind` in `R` */
@@ -9533,6 +9542,8 @@ type GridTableLayoutProps<F extends Record<string, unknown>, R extends Kinded, X
9533
9542
  /** Shows "N Rows Selected · Clear" before the columns selector; Clear deselects every row. */
9534
9543
  selectionSummary?: boolean;
9535
9544
  hideEditColumns?: boolean;
9545
+ /** When set, columns that share a name use one Edit Columns switch. */
9546
+ shareColumnVisibility?: boolean;
9536
9547
  totalCount?: number;
9537
9548
  /** When true, shows a view toggle button and renders the table with `as="card"` when in card view. */
9538
9549
  withCardView?: boolean;
@@ -10334,8 +10345,6 @@ declare function useSetupColumnSizes<R extends Kinded>(style: GridStyle, columns
10334
10345
  declare function groupColumns<T extends Kinded>(opts: {
10335
10346
  id: string;
10336
10347
  header: string;
10337
- /** Paints every cell in the group. A leaf's own `bgColor` wins. */
10338
- bgColor?: BeamColor;
10339
10348
  columns: Array<Omit<GridColumn<T>, "groupHeader">>;
10340
10349
  }): GridColumn<T>[];
10341
10350
  /** Provides default styling for a GridColumn representing a Date. */
@@ -11030,6 +11039,8 @@ interface TriggerNoticeProps extends Omit<SnackbarNoticeProps, "id" | "onClose">
11030
11039
  type EditColumnsButtonProps<R extends Kinded> = {
11031
11040
  columns: GridColumn<R>[];
11032
11041
  api: GridTableApi<R>;
11042
+ /** When set, columns that share a name use one Edit Columns switch. */
11043
+ shareColumnVisibility?: boolean;
11033
11044
  defaultOpen?: boolean;
11034
11045
  } & Pick<OverlayTriggerProps, "placement" | "disabled" | "tooltip">;
11035
11046
  declare function EditColumnsButton<R extends Kinded>(props: EditColumnsButtonProps<R>): React$1.JSX.Element;
package/dist/index.d.ts CHANGED
@@ -5974,6 +5974,8 @@ type RowProps<R extends Kinded> = {
5974
5974
  setResizedWidth: (columnId: string, width: number, columnIndex: number) => void;
5975
5975
  disableColumnResizing: boolean;
5976
5976
  calculatePreviewWidth: (columnId: string, newWidth: number, columnIndex: number) => number;
5977
+ /** Column ids that take `columnStriping`. Stable until the visible columns change. */
5978
+ stripedColumnIds?: ReadonlySet<string>;
5977
5979
  onDragStart?: (row: GridDataRow<R>, event: React__default.DragEvent<HTMLElement>) => void;
5978
5980
  onDragEnd?: (row: GridDataRow<R>, event: React__default.DragEvent<HTMLElement>) => void;
5979
5981
  onDrop?: (row: GridDataRow<R>, event: React__default.DragEvent<HTMLElement>) => void;
@@ -6324,6 +6326,8 @@ type GridStyle = {
6324
6326
  });
6325
6327
  /** Allows for customization of the background color used to denote an "active" row */
6326
6328
  activeBgColor?: BeamColor;
6329
+ /** Resolved `columnStriping` color. */
6330
+ columnStripeColor?: BeamColor;
6327
6331
  /** Defines styles for the group row which holds the selected rows that have been filtered out */
6328
6332
  keptGroupRowCss?: Properties;
6329
6333
  /** Defines styles for the last row `keptGroup` to provide separation from the rest of the table */
@@ -6356,6 +6360,11 @@ type GridStyleDef = {
6356
6360
  highlightOnHover?: boolean;
6357
6361
  /** Rounds the top corners of the first head-row cells. Defaults to true */
6358
6362
  roundedHeader?: boolean;
6363
+ /**
6364
+ * Zebra on the 2nd, 4th, 6th… content column. A leading group is striped only when a content column precedes it.
6365
+ * Select, collapse, and gutter columns are skipped. A column `bgColor` wins.
6366
+ */
6367
+ columnStriping?: BeamColor;
6359
6368
  };
6360
6369
  declare const getTableStyles: (props?: GridStyleDef) => GridStyle;
6361
6370
  /** Defines row-specific styling for each given row `kind` in `R` */
@@ -9533,6 +9542,8 @@ type GridTableLayoutProps<F extends Record<string, unknown>, R extends Kinded, X
9533
9542
  /** Shows "N Rows Selected · Clear" before the columns selector; Clear deselects every row. */
9534
9543
  selectionSummary?: boolean;
9535
9544
  hideEditColumns?: boolean;
9545
+ /** When set, columns that share a name use one Edit Columns switch. */
9546
+ shareColumnVisibility?: boolean;
9536
9547
  totalCount?: number;
9537
9548
  /** When true, shows a view toggle button and renders the table with `as="card"` when in card view. */
9538
9549
  withCardView?: boolean;
@@ -10334,8 +10345,6 @@ declare function useSetupColumnSizes<R extends Kinded>(style: GridStyle, columns
10334
10345
  declare function groupColumns<T extends Kinded>(opts: {
10335
10346
  id: string;
10336
10347
  header: string;
10337
- /** Paints every cell in the group. A leaf's own `bgColor` wins. */
10338
- bgColor?: BeamColor;
10339
10348
  columns: Array<Omit<GridColumn<T>, "groupHeader">>;
10340
10349
  }): GridColumn<T>[];
10341
10350
  /** Provides default styling for a GridColumn representing a Date. */
@@ -11030,6 +11039,8 @@ interface TriggerNoticeProps extends Omit<SnackbarNoticeProps, "id" | "onClose">
11030
11039
  type EditColumnsButtonProps<R extends Kinded> = {
11031
11040
  columns: GridColumn<R>[];
11032
11041
  api: GridTableApi<R>;
11042
+ /** When set, columns that share a name use one Edit Columns switch. */
11043
+ shareColumnVisibility?: boolean;
11033
11044
  defaultOpen?: boolean;
11034
11045
  } & Pick<OverlayTriggerProps, "placement" | "disabled" | "tooltip">;
11035
11046
  declare function EditColumnsButton<R extends Kinded>(props: EditColumnsButtonProps<R>): React$1.JSX.Element;
package/dist/index.js CHANGED
@@ -6440,7 +6440,8 @@ function memoizedTableStyles() {
6440
6440
  vAlign = rowHeight === "fixed" ? "center" : "top",
6441
6441
  cellTypography = "xs",
6442
6442
  highlightOnHover = true,
6443
- roundedHeader = true
6443
+ roundedHeader = true,
6444
+ columnStriping
6444
6445
  } = props;
6445
6446
  const key = safeKeys(props).sort().map((k) => `${k}_${props[k]}`).join("|");
6446
6447
  if (!cache[key]) {
@@ -6749,6 +6750,9 @@ function memoizedTableStyles() {
6749
6750
  paddingTop: "pt_4px",
6750
6751
  paddingBottom: "pb_4px"
6751
6752
  }
6753
+ } : {},
6754
+ ...columnStriping ? {
6755
+ columnStripeColor: columnStriping
6752
6756
  } : {}
6753
6757
  };
6754
6758
  }
@@ -6857,7 +6861,8 @@ var gridStyleDefKeysRecord = {
6857
6861
  vAlign: true,
6858
6862
  cellTypography: true,
6859
6863
  highlightOnHover: true,
6860
- roundedHeader: true
6864
+ roundedHeader: true,
6865
+ columnStriping: true
6861
6866
  };
6862
6867
  function isGridStyleDef(style) {
6863
6868
  const keys = safeKeys(style);
@@ -9102,7 +9107,6 @@ function groupColumns(opts) {
9102
9107
  const {
9103
9108
  id,
9104
9109
  header,
9105
- bgColor,
9106
9110
  columns
9107
9111
  } = opts;
9108
9112
  return columns.map((column2) => ({
@@ -9112,7 +9116,6 @@ function groupColumns(opts) {
9112
9116
  groupId: id,
9113
9117
  groupLabel: header,
9114
9118
  groupHeader: header,
9115
- bgColor: column2.bgColor ?? bgColor,
9116
9119
  name: prefixGroupColumnName(header, column2.name)
9117
9120
  }));
9118
9121
  }
@@ -10463,6 +10466,7 @@ function RowImpl(props) {
10463
10466
  setResizedWidth,
10464
10467
  disableColumnResizing = true,
10465
10468
  calculatePreviewWidth,
10469
+ stripedColumnIds,
10466
10470
  onDragStart,
10467
10471
  onDragEnd,
10468
10472
  onDrop,
@@ -10477,6 +10481,7 @@ function RowImpl(props) {
10477
10481
  api,
10478
10482
  visibleColumns: columns
10479
10483
  } = tableState;
10484
+ const columnStripeColor = style.columnStripeColor;
10480
10485
  const {
10481
10486
  row,
10482
10487
  api: rowApi,
@@ -10674,6 +10679,12 @@ function RowImpl(props) {
10674
10679
  // Add right border on expandable header cells except the last column
10675
10680
  ...isExpandableHeader && columnIndex + currentColspan < columns.length && style.expandableHeaderNonLastColumnCss,
10676
10681
  ...isGroupHeader && style.groupHeaderCss,
10682
+ ...columnStripeColor && stripedColumnIds?.has(column2.id) && {
10683
+ backgroundColor: ["bgColor_var", {
10684
+ "--backgroundColor": maybeCssVar_12(maybeCssVar(columnStripeColor))
10685
+ }]
10686
+ },
10687
+ // A leaf background is explicit and wins over the stripe.
10677
10688
  ...column2.bgColor && {
10678
10689
  backgroundColor: ["bgColor_var", {
10679
10690
  "--backgroundColor": maybeCssVar_12(column2.bgColor)
@@ -14127,6 +14138,7 @@ function GridTable(props) {
14127
14138
  const columns = useComputed(() => {
14128
14139
  return tableState.visibleColumns;
14129
14140
  }, [tableState]);
14141
+ const stripedColumnIds = useMemo16(() => style.columnStripeColor ? getStripedColumnIds(columns) : void 0, [columns, style.columnStripeColor]);
14130
14142
  tableState.initSortState(props.sorting, columns);
14131
14143
  const {
14132
14144
  getCount
@@ -14256,7 +14268,8 @@ function GridTable(props) {
14256
14268
  resizedWidths,
14257
14269
  setResizedWidth: handleColumnResize,
14258
14270
  disableColumnResizing,
14259
- calculatePreviewWidth
14271
+ calculatePreviewWidth,
14272
+ stripedColumnIds
14260
14273
  } }, rs.key);
14261
14274
  const makeCompanionRow = (rs, resolved, isFirstBodyRow, isLastBodyRow) => {
14262
14275
  const levelStyle = style.levels && (typeof style.levels === "function" ? style.levels(rs.level) : style.levels[rs.level]);
@@ -14307,7 +14320,7 @@ function GridTable(props) {
14307
14320
  visibleDataRows2 = visibleDataRows2.slice(0, filterMaxRows);
14308
14321
  }
14309
14322
  return [tableHeadRows2, visibleDataRows2, keptSelectedRows2, pinnedRows2, tooManyClientSideRows2];
14310
- }, [as, api, style, rowStyles, maybeStyle, columnSizes, columns.length, getCount, filterMaxRows, cardHeight, cardImageFit]);
14323
+ }, [as, api, style, rowStyles, maybeStyle, columnSizes, columns.length, stripedColumnIds, getCount, filterMaxRows, cardHeight, cardImageFit]);
14311
14324
  if (props.rowLookup) props.rowLookup.current = api.lookup;
14312
14325
  const noData = visibleDataRows.length === 0 && pinnedRows.length === 0;
14313
14326
  const firstRowMessage = noData && !emptyState && fallbackMessage || tooManyClientSideRows && "Hiding some rows, use filter..." || infoMessage;
@@ -14716,6 +14729,32 @@ function useColumnMeasureWidth() {
14716
14729
  return void 0;
14717
14730
  }
14718
14731
  var CARD_MIN_WIDTH_PX = 330;
14732
+ function getStripedColumnIds(columns) {
14733
+ const ids = /* @__PURE__ */ new Set();
14734
+ const contentColumns = columns.filter(isContentColumn);
14735
+ if (contentColumns.some((column2) => column2.groupId)) {
14736
+ const firstGroupStripes = contentColumns.findIndex((column2) => column2.groupId) > 0;
14737
+ const ordinals = /* @__PURE__ */ new Map();
14738
+ for (const column2 of contentColumns) {
14739
+ const {
14740
+ groupId
14741
+ } = column2;
14742
+ if (!groupId) continue;
14743
+ let ordinal = ordinals.get(groupId);
14744
+ if (ordinal === void 0) {
14745
+ ordinal = ordinals.size;
14746
+ ordinals.set(groupId, ordinal);
14747
+ }
14748
+ const stripes = firstGroupStripes ? ordinal % 2 === 0 : ordinal % 2 === 1;
14749
+ if (stripes) ids.add(column2.id);
14750
+ }
14751
+ return ids;
14752
+ }
14753
+ contentColumns.forEach((column2, ordinal) => {
14754
+ if (ordinal % 2 === 1) ids.add(column2.id);
14755
+ });
14756
+ return ids;
14757
+ }
14719
14758
 
14720
14759
  // src/components/ToggleChip.tsx
14721
14760
  import { trussProps as trussProps34 } from "@homebound/truss/runtime";
@@ -25139,7 +25178,8 @@ function EditColumnsButton(props) {
25139
25178
  defaultOpen,
25140
25179
  disabled,
25141
25180
  columns,
25142
- api
25181
+ api,
25182
+ shareColumnVisibility = false
25143
25183
  } = props;
25144
25184
  const state = useMenuTriggerState4({
25145
25185
  defaultOpen
@@ -25154,26 +25194,13 @@ function EditColumnsButton(props) {
25154
25194
  const {
25155
25195
  sm
25156
25196
  } = useBreakpoint();
25157
- const options = useMemo42(() => columns.filter((column2) => column2.canHide).filter((column2) => {
25158
- if (!column2.name || column2.name.length === 0 || !column2.id || column2.id.length === 0) {
25159
- console.warn("Column is missing 'name' and/or 'id' property required by the Edit Columns button", column2);
25160
- return false;
25161
- }
25162
- return true;
25163
- }).map((column2) => ({
25164
- label: column2.name,
25165
- value: column2.id,
25166
- tooltip: column2.tooltip
25167
- })), [columns]);
25197
+ const options = useMemo42(() => buildColumnOptions(columns, shareColumnVisibility), [columns, shareColumnVisibility]);
25168
25198
  const selectedValues = useComputed(() => api.getVisibleColumnIds(), [api]);
25169
25199
  const setSelectedValues = useCallback27((ids) => {
25170
25200
  api.resetColumnWidths();
25171
25201
  api.setVisibleColumns(columns.filter((column2) => column2.canHide ? ids.includes(column2.id) : true).map((c) => c.id));
25172
25202
  }, [columns, api]);
25173
- const hasHiddenColumn = useMemo42(() => {
25174
- const selectableOptionValues = options.map((option) => option.value);
25175
- return selectableOptionValues.some((option) => !selectedValues.includes(option));
25176
- }, [options, selectedValues]);
25203
+ const hasHiddenColumn = useMemo42(() => options.some((option) => option.ids.some((id) => !selectedValues.includes(id))), [options, selectedValues]);
25177
25204
  return /* @__PURE__ */ jsx179(OverlayTrigger, { ...props, trigger: sm ? {
25178
25205
  icon: hasHiddenColumn ? "columnsBadged" : "columns",
25179
25206
  variant: "outline"
@@ -25201,7 +25228,7 @@ function EditColumnsButton(props) {
25201
25228
  /* @__PURE__ */ jsx179("span", { className: "fw4 fz_14px lh_20px mw0", children: option.label }),
25202
25229
  option.tooltip ? /* @__PURE__ */ jsx179(ColumnTooltipIcon, { ...tid[`tooltip_${option.value}`], tooltip: closeMenuOnClickTooltip(option.tooltip, state.close), color: "--b-text-link-default" /* TextLinkDefault */, label: option.label }) : null
25203
25230
  ] }),
25204
- /* @__PURE__ */ jsx179(Switch, { compact: true, selected: selectedValues.includes(option.value), onChange: (value) => setSelectedValues(value ? [...selectedValues, option.value] : selectedValues.filter((v) => v !== option.value)), labelStyle: "hidden", label: option.label, ...tid[`option${option.value}`] })
25231
+ /* @__PURE__ */ jsx179(Switch, { compact: true, selected: option.ids.every((id) => selectedValues.includes(id)), onChange: (value) => setSelectedValues(value ? [...selectedValues, ...option.ids] : selectedValues.filter((id) => !option.ids.includes(id))), labelStyle: "hidden", label: option.label, ...tid[`option${option.value}`] })
25205
25232
  ] }, option.value)) }),
25206
25233
  /* @__PURE__ */ jsx179("div", { ...trussProps105({
25207
25234
  display: "df",
@@ -25218,6 +25245,54 @@ function EditColumnsButton(props) {
25218
25245
  }), children: /* @__PURE__ */ jsx179(Button, { variant: "tertiary", label: "Reset Column Widths", onClick: () => api.resetColumnWidths() }) })
25219
25246
  ] }) });
25220
25247
  }
25248
+ function buildColumnOptions(columns, shareColumnVisibility) {
25249
+ const hideable = columns.filter((column2) => {
25250
+ if (!column2.canHide) return false;
25251
+ if (!column2.name || column2.name.length === 0 || !column2.id || column2.id.length === 0) {
25252
+ console.warn("Column is missing 'name' and/or 'id' property required by the Edit Columns button", column2);
25253
+ return false;
25254
+ }
25255
+ return true;
25256
+ });
25257
+ if (!shareColumnVisibility) {
25258
+ return hideable.map((column2) => ({
25259
+ label: column2.name,
25260
+ value: column2.id,
25261
+ ids: [column2.id],
25262
+ tooltip: column2.tooltip
25263
+ }));
25264
+ }
25265
+ const byLabel = /* @__PURE__ */ new Map();
25266
+ const warnedLabels = /* @__PURE__ */ new Set();
25267
+ for (const column2 of hideable) {
25268
+ const label = leafColumnName(column2);
25269
+ const existing = byLabel.get(label);
25270
+ if (!existing) {
25271
+ byLabel.set(label, {
25272
+ label,
25273
+ value: column2.id,
25274
+ ids: [column2.id],
25275
+ tooltip: column2.tooltip
25276
+ });
25277
+ continue;
25278
+ }
25279
+ existing.ids.push(column2.id);
25280
+ if (existing.tooltip !== column2.tooltip && !warnedLabels.has(label)) {
25281
+ warnedLabels.add(label);
25282
+ console.warn(`Edit Columns columns labeled "${label}" have different tooltips. Using the first.`);
25283
+ }
25284
+ }
25285
+ return [...byLabel.values()];
25286
+ }
25287
+ function leafColumnName(column2) {
25288
+ const {
25289
+ name,
25290
+ groupLabel
25291
+ } = column2;
25292
+ const prefix = groupLabel ? `${groupLabel}: ` : void 0;
25293
+ if (name && prefix && name.startsWith(prefix)) return name.slice(prefix.length);
25294
+ return name;
25295
+ }
25221
25296
  function closeMenuOnClickTooltip(tooltip, closeMenu) {
25222
25297
  if (typeof tooltip !== "function") return tooltip;
25223
25298
  return () => {
@@ -25442,6 +25517,7 @@ function GridTableLayoutActionsComponent(props) {
25442
25517
  searchProps,
25443
25518
  hasHideableColumns,
25444
25519
  columns,
25520
+ shareColumnVisibility,
25445
25521
  api,
25446
25522
  withCardView,
25447
25523
  view,
@@ -25535,7 +25611,7 @@ function GridTableLayoutActionsComponent(props) {
25535
25611
  ] }),
25536
25612
  (hasHideableColumns || withCardView || !!actions?.length || selectionSummary) && /* @__PURE__ */ jsxs96("div", { className: "df aic g_12px", children: [
25537
25613
  selectionSummary && api && /* @__PURE__ */ jsx184(SelectionSummaryAction, { api, numberOnly: sm }),
25538
- hasHideableColumns && view === "list" && columns && api && /* @__PURE__ */ jsx184(EditColumnsButton, { columns, api, tooltip: "Display columns" }),
25614
+ hasHideableColumns && view === "list" && columns && api && /* @__PURE__ */ jsx184(EditColumnsButton, { columns, api, shareColumnVisibility, tooltip: "Display columns" }),
25539
25615
  withCardView && view !== void 0 && setView && /* @__PURE__ */ jsx184(ViewToggleButton, { view, onChange: setView }),
25540
25616
  !!actions?.length && /* @__PURE__ */ jsx184(HeaderActions, { actions, ...testId.actions })
25541
25617
  ] })
@@ -26414,6 +26490,7 @@ function GridTableLayoutComponent(props) {
26414
26490
  actions,
26415
26491
  selectionSummary = false,
26416
26492
  hideEditColumns = false,
26493
+ shareColumnVisibility = false,
26417
26494
  withCardView,
26418
26495
  defaultView = "list",
26419
26496
  emptyFallback: layoutEmptyFallback,
@@ -26468,6 +26545,7 @@ function GridTableLayoutComponent(props) {
26468
26545
  searchProps: filterSearchProps,
26469
26546
  hasHideableColumns,
26470
26547
  columns,
26548
+ shareColumnVisibility,
26471
26549
  api,
26472
26550
  withCardView,
26473
26551
  view,