playbook_ui 16.7.0.pre.alpha.play2924tooltipmisalignment16298 → 16.7.0.pre.alpha.tablewidths16407

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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_advanced_table/Components/RegularTableView.tsx +2 -0
  3. data/app/pb_kits/playbook/pb_advanced_table/Components/TableHeaderCell.tsx +2 -0
  4. data/app/pb_kits/playbook/pb_advanced_table/Components/VirtualizedTableView.tsx +5 -1
  5. data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableState.ts +24 -0
  6. data/app/pb_kits/playbook/pb_advanced_table/Utilities/ColumnLayoutHelper.ts +123 -0
  7. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.test.jsx +76 -0
  8. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_styling.jsx +2 -0
  9. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_styling.md +10 -0
  10. data/app/pb_kits/playbook/pb_advanced_table/docs/_playground.json +182 -5839
  11. data/app/pb_kits/playbook/pb_advanced_table/docs/_playground.overrides.json +5 -30
  12. data/app/pb_kits/playbook/pb_advanced_table/docs/advanced_table_column_definitions_styling.json +6 -1
  13. data/app/pb_kits/playbook/pb_date_picker/_date_picker.tsx +1 -19
  14. data/app/pb_kits/playbook/pb_date_picker/date_picker.html.erb +5 -8
  15. data/app/pb_kits/playbook/pb_date_picker/date_picker.rb +0 -12
  16. data/app/pb_kits/playbook/pb_date_picker/date_picker.test.js +0 -26
  17. data/app/pb_kits/playbook/pb_date_range_stacked/docs/_playground.json +1 -1
  18. data/app/pb_kits/playbook/pb_dropdown/_dropdown.tsx +0 -58
  19. data/app/pb_kits/playbook/pb_dropdown/dropdown.html.erb +0 -2
  20. data/app/pb_kits/playbook/pb_dropdown/dropdown.test.jsx +1 -7
  21. data/app/pb_kits/playbook/pb_rich_text_editor/_rich_text_editor.tsx +1 -1
  22. data/app/pb_kits/playbook/pb_rich_text_editor/_tiptap_styles.scss +262 -43
  23. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_rails_default.html.erb +1 -0
  24. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_rails_default.md +12 -0
  25. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_rails_simple.html.erb +9 -0
  26. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_rails_simple.md +8 -0
  27. data/app/pb_kits/playbook/pb_rich_text_editor/docs/example.yml +2 -0
  28. data/app/pb_kits/playbook/pb_rich_text_editor/kit.schema.json +18 -9
  29. data/app/pb_kits/playbook/pb_rich_text_editor/rich_text_editor.html.erb +162 -0
  30. data/app/pb_kits/playbook/pb_rich_text_editor/rich_text_editor.rb +71 -0
  31. data/app/pb_kits/playbook/pb_rich_text_editor/rich_text_editor_rails.js +202 -0
  32. data/app/pb_kits/playbook/pb_select/select.rb +0 -9
  33. data/app/pb_kits/playbook/pb_text_input/text_input.rb +0 -9
  34. data/dist/chunks/vendor.js +2 -2
  35. data/dist/menu.yml +1 -2
  36. data/dist/playbook.css +1 -1
  37. data/lib/playbook/version.rb +1 -1
  38. metadata +10 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3e33b44c25c0ba6a0d5fd1892e0472a1386b6be151356b70c1e4216ba2822267
4
- data.tar.gz: b8a0e8f1f004f86029489370a42f1b76015103e98e09a98284cfa3a5e9e56c4e
3
+ metadata.gz: 8da495f79107327990243768d12d0c686b02cd3c9139be2021b1a2502ac1091b
4
+ data.tar.gz: b87d04b9c001d89e1f25889e19ec812d5e882eb04b06df284bcb3feb963567ce
5
5
  SHA512:
6
- metadata.gz: 6e8ae8b9fec0dd0c10a0a9a64e8d9a39a7b0fb705f89ddddbb575c90b7c18b4024b43a470e23a537581f2688e5c03b7fd281d94a25dc2ca9978501e447b81d50
7
- data.tar.gz: 6005ef5a5e9d4466efbab580803cbc4b1f025321d87b1997dee9a3b8aab073f92c27580f0fdbc68e3e5dce8f244db748b3f40ef443f1fa3a8fb96b54c6ad6757
6
+ metadata.gz: 6b65bd11a250d2eb7de7f99b7e9c1209ef8d425244886afb6dfc744866172989ba223a981d78b92621f880c46fdb2ee3a3167776204754a430a847f1198ea71f
7
+ data.tar.gz: 91f38760a01e16eaaf16db868791168edbe57581cd05057e443ac3eeaffef513ebbc37451c716d65bb0591bfa0ebd022dc019c88d9cc15f62c74f5e5a78dfb25
@@ -5,6 +5,7 @@ import { flexRender, Row, Cell } from "@tanstack/react-table"
5
5
  import { GenericObject } from "../../types"
6
6
  import { isChrome } from "../Utilities/BrowserCheck"
7
7
  import { findColumnDefByAccessor } from "../Utilities/ColumnStylingHelper"
8
+ import { playbookColumnLayoutStylesFromMeta } from "../Utilities/ColumnLayoutHelper"
8
9
  import { getRowColorClass, shouldShowLoadingIndicator } from "../Utilities/RowUtils"
9
10
 
10
11
  import LoadingInline from "../../pb_loading_inline/_loading_inline"
@@ -94,6 +95,7 @@ const TableCellRenderer = ({
94
95
  )}
95
96
  key={`${cell.id}-data`}
96
97
  style={{
98
+ ...playbookColumnLayoutStylesFromMeta(column.columnDef),
97
99
  left: isPinnedLeft
98
100
  ? i === 1 // Accounting for set min-width for first column
99
101
  ? '180px'
@@ -16,6 +16,7 @@ import { SortIconButton } from "./SortIconButton"
16
16
  import { ToggleIconButton } from "./ToggleIconButton"
17
17
  import { displayIcon } from "../Utilities/IconHelpers"
18
18
  import { findColumnDefByAccessor } from "../Utilities/ColumnStylingHelper"
19
+ import { playbookColumnLayoutStylesFromMeta } from "../Utilities/ColumnLayoutHelper"
19
20
  import { updateExpandAndCollapseState } from "../Utilities/ExpansionControlHelpers"
20
21
 
21
22
  import { isChrome } from "../Utilities/BrowserCheck"
@@ -198,6 +199,7 @@ const isToggleExpansionEnabled =
198
199
  id={cellId}
199
200
  key={`${header?.id}-header`}
200
201
  style={{
202
+ ...playbookColumnLayoutStylesFromMeta(header?.column?.columnDef),
201
203
  backgroundColor: headerBackgroundColor,
202
204
  color: headerFontColor,
203
205
  left: isPinnedLeft
@@ -19,6 +19,7 @@ import { LoadingCell } from "../Components/LoadingCell"
19
19
  import { renderCollapsibleTrail } from "../Components/CollapsibleTrail"
20
20
 
21
21
  import AdvancedTableContext from "../Context/AdvancedTableContext"
22
+ import { playbookColumnLayoutStylesFromMeta } from "../Utilities/ColumnLayoutHelper"
22
23
 
23
24
  type VirtualizedTableViewProps = {
24
25
  collapsibleTrail?: boolean
@@ -224,7 +225,10 @@ export const VirtualizedTableView = ({
224
225
  isLastCell && 'last-cell',
225
226
  )}
226
227
  key={`${cell.id}-data`}
227
- style={{ width: cellWidth }}
228
+ style={{
229
+ ...playbookColumnLayoutStylesFromMeta(cell.column.columnDef),
230
+ width: cellWidth,
231
+ }}
228
232
  >
229
233
  {collapsibleTrail && i === 0 && row.depth > 0 && renderCollapsibleTrail(row.depth)}
230
234
  <span id={`${cell.id}-span`}>
@@ -12,6 +12,10 @@ import {
12
12
  import { GenericObject } from "../../types";
13
13
  import { createColumnHelper } from "@tanstack/react-table";
14
14
  import { createCellFunction } from "../Utilities/CellRendererUtils";
15
+ import {
16
+ buildPlaybookColumnLayoutStyles,
17
+ buildTanStackSizingFromColumn,
18
+ } from "../Utilities/ColumnLayoutHelper";
15
19
  import { getParentOnlySortedRowModel } from "../Utilities/RowModelUtils";
16
20
 
17
21
  interface UseTableStateProps {
@@ -105,11 +109,31 @@ export function useTableState({
105
109
  columns: buildColumns(column.columns, false),
106
110
  };
107
111
  }
112
+ const tanStackSizing = buildTanStackSizingFromColumn(column);
113
+ const layoutStyles = buildPlaybookColumnLayoutStyles(column, tanStackSizing);
114
+ const userMeta =
115
+ column.meta &&
116
+ typeof column.meta === "object" &&
117
+ !Array.isArray(column.meta)
118
+ ? column.meta
119
+ : {};
120
+ const hasLayoutStyles =
121
+ layoutStyles.width !== undefined ||
122
+ layoutStyles.minWidth !== undefined ||
123
+ layoutStyles.maxWidth !== undefined;
124
+
108
125
  // Define the base column structure
109
126
  const columnStructure = {
110
127
  ...columnHelper.accessor(column.accessor, {
111
128
  header: column.header ?? column.label ?? "",
112
129
  enableSorting: isFirstColumn || column.enableSort === true,
130
+ ...tanStackSizing,
131
+ meta: {
132
+ ...userMeta,
133
+ ...(hasLayoutStyles
134
+ ? { playbookColumnLayoutStyles: layoutStyles }
135
+ : {}),
136
+ },
113
137
  }),
114
138
  };
115
139
 
@@ -0,0 +1,123 @@
1
+ import type { CSSProperties } from "react"
2
+
3
+ import { GenericObject } from "../../types"
4
+
5
+ /**
6
+ * Converts a Playbook column width value to a CSS length string.
7
+ * Numbers are treated as pixels; strings are passed through (e.g. `"12rem"`, `"200px"`).
8
+ */
9
+ export function cssLength(
10
+ value: number | string | undefined | null
11
+ ): string | undefined {
12
+ if (value === undefined || value === null || value === "") return undefined
13
+ if (typeof value === "number" && Number.isFinite(value)) return `${value}px`
14
+ return String(value)
15
+ }
16
+
17
+ const columnStylingKeys = (column: GenericObject) =>
18
+ (column.columnStyling || column.column_styling || {}) as GenericObject
19
+
20
+ function readStylingLength(
21
+ styling: GenericObject,
22
+ camel: string,
23
+ snake?: string
24
+ ): string | number | undefined {
25
+ if (snake) return styling[camel] ?? styling[snake]
26
+ return styling[camel] as string | number | undefined
27
+ }
28
+
29
+ /**
30
+ * TanStack Table v8 `ColumnDef` sizing fields we forward from each `columnDefinitions` entry.
31
+ * See AdvancedTable kit docs for precedence with `columnStyling` width keys.
32
+ */
33
+ export const PLAYBOOK_FORWARDED_COLUMN_DEF_SIZING_KEYS = [
34
+ "size",
35
+ "minSize",
36
+ "maxSize",
37
+ ] as const
38
+
39
+ export type PlaybookForwardedColumnSizing = Partial<
40
+ Record<(typeof PLAYBOOK_FORWARDED_COLUMN_DEF_SIZING_KEYS)[number], number>
41
+ >
42
+
43
+ export function buildTanStackSizingFromColumn(
44
+ column: GenericObject
45
+ ): PlaybookForwardedColumnSizing {
46
+ const out: PlaybookForwardedColumnSizing = {}
47
+ PLAYBOOK_FORWARDED_COLUMN_DEF_SIZING_KEYS.forEach((key) => {
48
+ const v = column[key]
49
+ if (typeof v === "number" && Number.isFinite(v)) out[key] = v
50
+ })
51
+
52
+ const styling = columnStylingKeys(column)
53
+
54
+ if (out.size === undefined && readStylingLength(styling, "width") !== undefined) {
55
+ const w = readStylingLength(styling, "width")
56
+ if (typeof w === "number" && Number.isFinite(w)) out.size = w
57
+ }
58
+ if (out.minSize === undefined && readStylingLength(styling, "minWidth", "min_width") !== undefined) {
59
+ const w = readStylingLength(styling, "minWidth", "min_width")
60
+ if (typeof w === "number" && Number.isFinite(w)) out.minSize = w
61
+ }
62
+ if (out.maxSize === undefined && readStylingLength(styling, "maxWidth", "max_width") !== undefined) {
63
+ const w = readStylingLength(styling, "maxWidth", "max_width")
64
+ if (typeof w === "number" && Number.isFinite(w)) out.maxSize = w
65
+ }
66
+
67
+ return out
68
+ }
69
+
70
+ /**
71
+ * Inline width styles for `<th>` / `<td>` so `table-layout: fixed` tables keep stable
72
+ * columns when row content changes (e.g. expand/collapse). Values mirror TanStack sizing
73
+ * and/or `columnStyling` width keys; string values in `columnStyling` win over numeric
74
+ * TanStack fields when both describe the same axis.
75
+ */
76
+ export function buildPlaybookColumnLayoutStyles(
77
+ column: GenericObject,
78
+ tanStackSizing: PlaybookForwardedColumnSizing
79
+ ): CSSProperties {
80
+ const styling = columnStylingKeys(column)
81
+ const styles: CSSProperties = {}
82
+
83
+ const widthFromStyling = cssLength(
84
+ readStylingLength(styling, "width") as string | number | undefined
85
+ )
86
+ const minFromStyling = cssLength(
87
+ readStylingLength(styling, "minWidth", "min_width") as string | number | undefined
88
+ )
89
+ const maxFromStyling = cssLength(
90
+ readStylingLength(styling, "maxWidth", "max_width") as string | number | undefined
91
+ )
92
+
93
+ const widthFromTanStack =
94
+ tanStackSizing.size !== undefined
95
+ ? cssLength(tanStackSizing.size)
96
+ : undefined
97
+ const minFromTanStack =
98
+ tanStackSizing.minSize !== undefined
99
+ ? cssLength(tanStackSizing.minSize)
100
+ : undefined
101
+ const maxFromTanStack =
102
+ tanStackSizing.maxSize !== undefined
103
+ ? cssLength(tanStackSizing.maxSize)
104
+ : undefined
105
+
106
+ if (widthFromStyling !== undefined) styles.width = widthFromStyling
107
+ else if (widthFromTanStack !== undefined) styles.width = widthFromTanStack
108
+
109
+ if (minFromStyling !== undefined) styles.minWidth = minFromStyling
110
+ else if (minFromTanStack !== undefined) styles.minWidth = minFromTanStack
111
+
112
+ if (maxFromStyling !== undefined) styles.maxWidth = maxFromStyling
113
+ else if (maxFromTanStack !== undefined) styles.maxWidth = maxFromTanStack
114
+
115
+ return styles
116
+ }
117
+
118
+ export function playbookColumnLayoutStylesFromMeta(
119
+ columnDef: GenericObject | undefined
120
+ ): CSSProperties {
121
+ const meta = columnDef?.meta as GenericObject | undefined
122
+ return (meta?.playbookColumnLayoutStyles || {}) as CSSProperties
123
+ }
@@ -774,6 +774,82 @@ test("columnStyling.cellPadding sets cell padding", () => {
774
774
  expect(firstEnrollmentCell).toHaveClass('p_none')
775
775
  });
776
776
 
777
+ test("columnStyling minWidth, width, and maxWidth apply to header and body cells", () => {
778
+ const styledColumnDefs = [
779
+ {
780
+ accessor: "year",
781
+ label: "Year",
782
+ cellAccessors: ["quarter", "month", "day"],
783
+ columnStyling: { minWidth: 240, width: 260, maxWidth: 400 },
784
+ },
785
+ {
786
+ accessor: "newEnrollments",
787
+ label: "New Enrollments",
788
+ },
789
+ {
790
+ accessor: "scheduledMeetings",
791
+ label: "Scheduled Meetings",
792
+ },
793
+ ];
794
+
795
+ render(
796
+ <AdvancedTable
797
+ columnDefinitions={styledColumnDefs}
798
+ data={{ testid: testId }}
799
+ tableData={MOCK_DATA}
800
+ />
801
+ );
802
+
803
+ const yearHeader = screen.getByText("Year").closest("th");
804
+ expect(yearHeader).toHaveStyle({ minWidth: "240px", width: "260px", maxWidth: "400px" });
805
+
806
+ const yearCell = screen.getAllByText("2021")[0].closest("td");
807
+ expect(yearCell).toHaveStyle({ minWidth: "240px", width: "260px", maxWidth: "400px" });
808
+ });
809
+
810
+ test("columnDefinitions size, minSize, and maxSize apply layout styles", () => {
811
+ const styledColumnDefs = [
812
+ {
813
+ accessor: "year",
814
+ label: "Year",
815
+ cellAccessors: ["quarter", "month", "day"],
816
+ },
817
+ {
818
+ accessor: "newEnrollments",
819
+ label: "New Enrollments",
820
+ size: 180,
821
+ minSize: 160,
822
+ maxSize: 320,
823
+ },
824
+ {
825
+ accessor: "scheduledMeetings",
826
+ label: "Scheduled Meetings",
827
+ },
828
+ ];
829
+
830
+ render(
831
+ <AdvancedTable
832
+ columnDefinitions={styledColumnDefs}
833
+ data={{ testid: testId }}
834
+ tableData={MOCK_DATA}
835
+ />
836
+ );
837
+
838
+ const enrollmentsHeader = screen.getByText("New Enrollments").closest("th");
839
+ expect(enrollmentsHeader).toHaveStyle({
840
+ width: "180px",
841
+ minWidth: "160px",
842
+ maxWidth: "320px",
843
+ });
844
+
845
+ const enrollmentsCell = screen.getAllByText("20")[0].closest("td");
846
+ expect(enrollmentsCell).toHaveStyle({
847
+ width: "180px",
848
+ minWidth: "160px",
849
+ maxWidth: "320px",
850
+ });
851
+ });
852
+
777
853
  test("columnStyling.fontColor sets cell font color", () => {
778
854
  const styledColumnDefs = [
779
855
  {
@@ -10,6 +10,8 @@ const AdvancedTableColumnStyling = (props) => {
10
10
  accessor: "year",
11
11
  label: "Year",
12
12
  cellAccessors: ["quarter", "month", "day"],
13
+ // Keeps the hierarchy column narrow and stable when rows expand (see kit docs).
14
+ columnStyling: { minWidth: 108, width: 124, maxWidth: 168 },
13
15
  },
14
16
  {
15
17
  accessor: "newEnrollments",
@@ -6,4 +6,14 @@ The `columnStyling` prop is an optional item that can be used within `columnDefi
6
6
 
7
7
  3) `fontColor`: This will allow you to control the font color for a given column.
8
8
 
9
+ 4) **Column width (layout stability)** — optional keys on `columnStyling` (numbers are treated as **pixels**; you may also use CSS length strings such as `"12rem"` or `"200px"`):
10
+
11
+ - `minWidth`: minimum width for the column’s header and body cells (helps prevent horizontal “jump” when row content or expansion depth changes on tables using fixed layout).
12
+ - `width`: preferred column width.
13
+ - `maxWidth`: maximum column width.
14
+
15
+ The live example below narrows the **Year** column (`minWidth` / `width` / `maxWidth`) so the first column stays compact while leaving room for expand and sort controls.
16
+
17
+ The same sizing can be expressed with TanStack `ColumnDef` fields on each column definition object (merged into the underlying table model): `size` (width), `minSize`, and `maxSize` (numbers, pixels). If both are present for the same axis, **`columnStyling` string values take precedence**; otherwise `columnStyling` numeric/string values override TanStack numbers when only one source sets that axis. **Grouped columns:** apply width controls on **leaf** column definitions (the columns that have an `accessor`).
18
+
9
19
  `columnStyling` can be used within the columnDefinition of all the columns or some of them, as shown. Each column has its own individual control in this way.