@tcn/ui-table 2.3.15 → 2.4.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.
@@ -1,55 +1,55 @@
1
- import { jsx as e, jsxs as c } from "react/jsx-runtime";
2
- import { useCallback as x } from "react";
3
- import { Box as r, HStack as h } from "@tcn/ui/stacks";
1
+ import { jsx as e, jsxs as p } from "react/jsx-runtime";
2
+ import { useCallback as h } from "react";
3
+ import { Box as i, HStack as x } from "@tcn/ui/stacks";
4
4
  import { TH as f } from "@tcn/ui/layouts";
5
5
  import { c as u } from "../../cell.module-WpHnQBVu.js";
6
- import { SortControl as C } from "./sort_control.js";
7
- function H({
8
- heading: n,
6
+ import { SortControl as b } from "./sort_control.js";
7
+ function N({
8
+ heading: r,
9
9
  sticky: l,
10
- onResize: i,
10
+ onResize: n,
11
11
  width: o,
12
12
  sortMode: a,
13
13
  onSortModeChange: s,
14
- canSort: d
14
+ canSort: c
15
15
  }) {
16
- const m = l != null ? 2 : 1, p = x(
16
+ const m = l != null ? 2 : 1, d = h(
17
17
  ({ width: t }) => {
18
- i?.(Math.max(t, 20));
18
+ n?.(Math.max(t, 20));
19
19
  },
20
- [i]
20
+ [n]
21
21
  );
22
22
  return /* @__PURE__ */ e(
23
23
  f,
24
24
  {
25
- className: u["table-cell"],
25
+ className: `tcn-header-cell ${u["table-cell"]}`,
26
26
  "data-stick-to": l,
27
27
  style: { width: `${o}px`, zIndex: m },
28
28
  children: /* @__PURE__ */ e(
29
- r,
29
+ i,
30
30
  {
31
- padding: "0px 8px",
31
+ className: "tcn-table-cell-content",
32
32
  overflow: "hidden",
33
33
  minWidth: "24px",
34
34
  maxWidth: "unset",
35
35
  width: o,
36
36
  enableResizeOnEnd: !0,
37
- onWidthResize: p,
37
+ onWidthResize: d,
38
38
  onClick: (t) => t.stopPropagation(),
39
- children: /* @__PURE__ */ c(h, { children: [
39
+ children: /* @__PURE__ */ p(x, { children: [
40
40
  /* @__PURE__ */ e(
41
- r,
41
+ i,
42
42
  {
43
43
  minWidth: "24px",
44
44
  className: "ellipsis",
45
45
  style: { alignItems: "center", display: "flex" },
46
- children: n
46
+ children: r
47
47
  }
48
48
  ),
49
49
  /* @__PURE__ */ e(
50
- C,
50
+ b,
51
51
  {
52
- canSort: d,
52
+ canSort: c,
53
53
  onSortModeChange: s,
54
54
  sortMode: a
55
55
  }
@@ -61,6 +61,6 @@ function H({
61
61
  );
62
62
  }
63
63
  export {
64
- H as HeaderCell
64
+ N as HeaderCell
65
65
  };
66
66
  //# sourceMappingURL=header_cell.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"header_cell.js","sources":["../../../src/components/cells/header_cell.tsx"],"sourcesContent":["import React, { useCallback } from 'react';\n\nimport { Box, HStack, type OnWidthResizePayload } from '@tcn/ui/stacks';\n\nimport { TH } from '@tcn/ui/layouts';\nimport cellStyles from './cell.module.css';\nimport { SortControl, type SortControlProps } from './sort_control.js';\n\nexport interface HeaderCellProps extends SortControlProps {\n heading: React.ReactNode;\n index: number;\n sticky?: 'start' | 'end';\n onResize?: (width: number) => void;\n width?: number;\n}\n\nexport function HeaderCell({\n heading,\n sticky,\n onResize,\n width,\n sortMode,\n onSortModeChange,\n canSort,\n}: HeaderCellProps) {\n const zIndex = sticky != null ? 2 : 1;\n\n const handleResize = useCallback(\n ({ width }: OnWidthResizePayload) => {\n onResize?.(Math.max(width, 20));\n },\n [onResize]\n );\n\n return (\n <TH\n className={cellStyles['table-cell']}\n data-stick-to={sticky}\n style={{ width: `${width}px`, zIndex }}\n >\n <Box\n padding=\"0px 8px\" // FIXME: should be on theme ideally.\n overflow=\"hidden\"\n minWidth=\"24px\"\n maxWidth=\"unset\"\n width={width}\n enableResizeOnEnd\n onWidthResize={handleResize}\n onClick={e => e.stopPropagation()}\n >\n <HStack>\n <Box\n minWidth=\"24px\"\n className=\"ellipsis\"\n style={{ alignItems: 'center', display: 'flex' }}\n >\n {heading}\n </Box>\n\n <SortControl\n canSort={canSort}\n onSortModeChange={onSortModeChange}\n sortMode={sortMode}\n />\n </HStack>\n </Box>\n </TH>\n );\n}\n"],"names":["HeaderCell","heading","sticky","onResize","width","sortMode","onSortModeChange","canSort","zIndex","handleResize","useCallback","jsx","TH","cellStyles","Box","e","HStack","SortControl"],"mappings":";;;;;;AAgBO,SAASA,EAAW;AAAA,EACzB,SAAAC;AAAA,EACA,QAAAC;AAAA,EACA,UAAAC;AAAA,EACA,OAAAC;AAAA,EACA,UAAAC;AAAA,EACA,kBAAAC;AAAA,EACA,SAAAC;AACF,GAAoB;AAClB,QAAMC,IAASN,KAAU,OAAO,IAAI,GAE9BO,IAAeC;AAAA,IACnB,CAAC,EAAE,OAAAN,QAAkC;AACnC,MAAAD,IAAW,KAAK,IAAIC,GAAO,EAAE,CAAC;AAAA,IAChC;AAAA,IACA,CAACD,CAAQ;AAAA,EAAA;AAGX,SACE,gBAAAQ;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,WAAWC,EAAW,YAAY;AAAA,MAClC,iBAAeX;AAAA,MACf,OAAO,EAAE,OAAO,GAAGE,CAAK,MAAM,QAAAI,EAAA;AAAA,MAE9B,UAAA,gBAAAG;AAAA,QAACG;AAAA,QAAA;AAAA,UACC,SAAQ;AAAA,UACR,UAAS;AAAA,UACT,UAAS;AAAA,UACT,UAAS;AAAA,UACT,OAAAV;AAAA,UACA,mBAAiB;AAAA,UACjB,eAAeK;AAAA,UACf,SAAS,CAAAM,MAAKA,EAAE,gBAAA;AAAA,UAEhB,4BAACC,GAAA,EACC,UAAA;AAAA,YAAA,gBAAAL;AAAA,cAACG;AAAA,cAAA;AAAA,gBACC,UAAS;AAAA,gBACT,WAAU;AAAA,gBACV,OAAO,EAAE,YAAY,UAAU,SAAS,OAAA;AAAA,gBAEvC,UAAAb;AAAA,cAAA;AAAA,YAAA;AAAA,YAGH,gBAAAU;AAAA,cAACM;AAAA,cAAA;AAAA,gBACC,SAAAV;AAAA,gBACA,kBAAAD;AAAA,gBACA,UAAAD;AAAA,cAAA;AAAA,YAAA;AAAA,UACF,EAAA,CACF;AAAA,QAAA;AAAA,MAAA;AAAA,IACF;AAAA,EAAA;AAGN;"}
1
+ {"version":3,"file":"header_cell.js","sources":["../../../src/components/cells/header_cell.tsx"],"sourcesContent":["import React, { useCallback } from 'react';\n\nimport { Box, HStack, type OnWidthResizePayload } from '@tcn/ui/stacks';\n\nimport { TH } from '@tcn/ui/layouts';\nimport cellStyles from './cell.module.css';\nimport { SortControl, type SortControlProps } from './sort_control.js';\n\nexport interface HeaderCellProps extends SortControlProps {\n heading: React.ReactNode;\n index: number;\n sticky?: 'start' | 'end';\n onResize?: (width: number) => void;\n width?: number;\n}\n\nexport function HeaderCell({\n heading,\n sticky,\n onResize,\n width,\n sortMode,\n onSortModeChange,\n canSort,\n}: HeaderCellProps) {\n const zIndex = sticky != null ? 2 : 1;\n\n const handleResize = useCallback(\n ({ width }: OnWidthResizePayload) => {\n onResize?.(Math.max(width, 20));\n },\n [onResize]\n );\n\n return (\n <TH\n className={`tcn-header-cell ${cellStyles['table-cell']}`}\n data-stick-to={sticky}\n style={{ width: `${width}px`, zIndex }}\n >\n <Box\n className=\"tcn-table-cell-content\"\n overflow=\"hidden\"\n minWidth=\"24px\"\n maxWidth=\"unset\"\n width={width}\n enableResizeOnEnd\n onWidthResize={handleResize}\n onClick={e => e.stopPropagation()}\n >\n <HStack>\n <Box\n minWidth=\"24px\"\n className=\"ellipsis\"\n style={{ alignItems: 'center', display: 'flex' }}\n >\n {heading}\n </Box>\n\n <SortControl\n canSort={canSort}\n onSortModeChange={onSortModeChange}\n sortMode={sortMode}\n />\n </HStack>\n </Box>\n </TH>\n );\n}\n"],"names":["HeaderCell","heading","sticky","onResize","width","sortMode","onSortModeChange","canSort","zIndex","handleResize","useCallback","jsx","TH","cellStyles","Box","e","HStack","SortControl"],"mappings":";;;;;;AAgBO,SAASA,EAAW;AAAA,EACzB,SAAAC;AAAA,EACA,QAAAC;AAAA,EACA,UAAAC;AAAA,EACA,OAAAC;AAAA,EACA,UAAAC;AAAA,EACA,kBAAAC;AAAA,EACA,SAAAC;AACF,GAAoB;AAClB,QAAMC,IAASN,KAAU,OAAO,IAAI,GAE9BO,IAAeC;AAAA,IACnB,CAAC,EAAE,OAAAN,QAAkC;AACnC,MAAAD,IAAW,KAAK,IAAIC,GAAO,EAAE,CAAC;AAAA,IAChC;AAAA,IACA,CAACD,CAAQ;AAAA,EAAA;AAGX,SACE,gBAAAQ;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,WAAW,mBAAmBC,EAAW,YAAY,CAAC;AAAA,MACtD,iBAAeX;AAAA,MACf,OAAO,EAAE,OAAO,GAAGE,CAAK,MAAM,QAAAI,EAAA;AAAA,MAE9B,UAAA,gBAAAG;AAAA,QAACG;AAAA,QAAA;AAAA,UACC,WAAU;AAAA,UACV,UAAS;AAAA,UACT,UAAS;AAAA,UACT,UAAS;AAAA,UACT,OAAAV;AAAA,UACA,mBAAiB;AAAA,UACjB,eAAeK;AAAA,UACf,SAAS,CAAAM,MAAKA,EAAE,gBAAA;AAAA,UAEhB,4BAACC,GAAA,EACC,UAAA;AAAA,YAAA,gBAAAL;AAAA,cAACG;AAAA,cAAA;AAAA,gBACC,UAAS;AAAA,gBACT,WAAU;AAAA,gBACV,OAAO,EAAE,YAAY,UAAU,SAAS,OAAA;AAAA,gBAEvC,UAAAb;AAAA,cAAA;AAAA,YAAA;AAAA,YAGH,gBAAAU;AAAA,cAACM;AAAA,cAAA;AAAA,gBACC,SAAAV;AAAA,gBACA,kBAAAD;AAAA,gBACA,UAAAD;AAAA,cAAA;AAAA,YAAA;AAAA,UACF,EAAA,CACF;AAAA,QAAA;AAAA,MAAA;AAAA,IACF;AAAA,EAAA;AAGN;"}
@@ -7,7 +7,8 @@ export interface TableFilterPanelProps extends Omit<PanelProps, 'children'> {
7
7
  children: ReactElement<FieldFilterProps>[] | ReactElement<FieldFilterProps>;
8
8
  dataSource: DataSource<any>;
9
9
  onClose?: () => void;
10
+ title?: string;
10
11
  }
11
- export declare function TableFilterPanel({ children, dataSource, className, onClose, ...props }: TableFilterPanelProps): import("react/jsx-runtime").JSX.Element;
12
+ export declare function TableFilterPanel({ children, dataSource, className, onClose, title, ...props }: TableFilterPanelProps): import("react/jsx-runtime").JSX.Element;
12
13
  export declare const TableFilterPanelContext: import('react').Context<TableFilterPanelPresenter<unknown> | null>;
13
14
  //# sourceMappingURL=table_filter_panel.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"table_filter_panel.d.ts","sourceRoot":"","sources":["../../../src/components/table_filter_panel/table_filter_panel.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,YAAY,EAA2B,MAAM,OAAO,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AACzE,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,EAAS,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAO1D,MAAM,WAAW,qBAAsB,SAAQ,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC;IACzE,QAAQ,EAAE,YAAY,CAAC,gBAAgB,CAAC,EAAE,GAAG,YAAY,CAAC,gBAAgB,CAAC,CAAC;IAC5E,UAAU,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,QAAQ,EACR,UAAU,EACV,SAAS,EACT,OAAO,EACP,GAAG,KAAK,EACT,EAAE,qBAAqB,2CAgCvB;AAED,eAAO,MAAM,uBAAuB,oEAEnC,CAAC"}
1
+ {"version":3,"file":"table_filter_panel.d.ts","sourceRoot":"","sources":["../../../src/components/table_filter_panel/table_filter_panel.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,YAAY,EAA2B,MAAM,OAAO,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AACzE,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,EAAS,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAQ1D,MAAM,WAAW,qBAAsB,SAAQ,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC;IACzE,QAAQ,EAAE,YAAY,CAAC,gBAAgB,CAAC,EAAE,GAAG,YAAY,CAAC,gBAAgB,CAAC,CAAC;IAC5E,UAAU,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,QAAQ,EACR,UAAU,EACV,SAAS,EACT,OAAO,EACP,KAAuB,EACvB,GAAG,KAAK,EACT,EAAE,qBAAqB,2CA+BvB;AAED,eAAO,MAAM,uBAAuB,oEAEnC,CAAC"}
@@ -1,53 +1,48 @@
1
- import { jsx as e, jsxs as r } from "react/jsx-runtime";
2
- import { createContext as s, useState as b } from "react";
3
- import { TableFilterPanelPresenter as p } from "./table_filter_panel_presenter.js";
4
- import { Panel as f } from "@tcn/ui/surfaces";
5
- import { Header as m, VBody as d, Section as y } from "@tcn/ui/layouts";
6
- import { Spacer as u } from "@tcn/ui/stacks";
7
- import { Button as P } from "@tcn/ui/actions";
8
- import { CrossIcon as h } from "@tcn/icons/cross_icon.js";
9
- import '../../table_filter_panel.css';const F = "_table-filter-panel_124e30e", _ = "_table-filter-panel-body_c016eb0", x = "_table-filter-panel-section_cfd2eb9", t = { "table-filter-panel": F, "table-filter-panel-body": _, "table-filter-panel-section": x };
10
- function w({
11
- children: a,
12
- dataSource: n,
13
- className: i,
14
- onClose: l,
15
- ...o
1
+ import { jsx as e, jsxs as l } from "react/jsx-runtime";
2
+ import { createContext as f, useState as b } from "react";
3
+ import { TableFilterPanelPresenter as m } from "./table_filter_panel_presenter.js";
4
+ import { Aside as p } from "@tcn/ui/surfaces";
5
+ import { Header as d, Body as y, Scaffold as h, Section as u } from "@tcn/ui/layouts";
6
+ import { Spacer as P } from "@tcn/ui/stacks";
7
+ import { Button as F } from "@tcn/ui/actions";
8
+ import { CrossIcon as x } from "@tcn/icons/cross_icon.js";
9
+ import { Title as S } from "@tcn/ui/typography";
10
+ import '../../table_filter_panel.css';const T = "_table-filter-panel-body_c016eb0", _ = "_table-filter-panel-section_cfd2eb9", r = { "table-filter-panel-body": T, "table-filter-panel-section": _ };
11
+ function I({
12
+ children: n,
13
+ dataSource: i,
14
+ className: a,
15
+ onClose: t,
16
+ title: o = "Table Filters",
17
+ ...c
16
18
  }) {
17
- const [c] = b(() => new p(n));
18
- return /* @__PURE__ */ e(S.Provider, { value: c, children: /* @__PURE__ */ r(
19
- f,
20
- {
21
- className: `${t["table-filter-panel"]} tcn-table-filter-panel ${i}`,
22
- ...o,
23
- children: [
24
- /* @__PURE__ */ r(m, { children: [
25
- "Table Filters",
26
- /* @__PURE__ */ e(u, {}),
27
- l && /* @__PURE__ */ e(P, { utility: !0, hierarchy: "tertiary", onClick: l, children: /* @__PURE__ */ e(h, {}) })
28
- ] }),
29
- /* @__PURE__ */ e(
30
- d,
19
+ const [s] = b(() => new m(i));
20
+ return /* @__PURE__ */ e(B.Provider, { value: s, children: /* @__PURE__ */ l(p, { className: `tcn-table-filter-panel ${a}`, ...c, children: [
21
+ /* @__PURE__ */ l(d, { children: [
22
+ /* @__PURE__ */ e(S, { children: o }),
23
+ /* @__PURE__ */ e(P, {}),
24
+ t && /* @__PURE__ */ e(F, { utility: !0, hierarchy: "tertiary", onClick: t, children: /* @__PURE__ */ e(x, {}) })
25
+ ] }),
26
+ /* @__PURE__ */ e(
27
+ y,
28
+ {
29
+ className: `${r["table-filter-panel-body"]} tcn-table-filter-panel-body`,
30
+ children: /* @__PURE__ */ e(h, { children: /* @__PURE__ */ e(
31
+ u,
31
32
  {
32
- className: `${t["table-filter-panel-body"]} tcn-table-filter-panel-body`,
33
- children: /* @__PURE__ */ e(
34
- y,
35
- {
36
- className: `${t["table-filter-panel-section"]} tcn-table-filter-panel-section`,
37
- children: a
38
- }
39
- )
33
+ className: `${r["table-filter-panel-section"]} tcn-table-filter-panel-section`,
34
+ children: n
40
35
  }
41
- )
42
- ]
43
- }
44
- ) });
36
+ ) })
37
+ }
38
+ )
39
+ ] }) });
45
40
  }
46
- const S = s(
41
+ const B = f(
47
42
  null
48
43
  );
49
44
  export {
50
- w as TableFilterPanel,
51
- S as TableFilterPanelContext
45
+ I as TableFilterPanel,
46
+ B as TableFilterPanelContext
52
47
  };
53
48
  //# sourceMappingURL=table_filter_panel.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"table_filter_panel.js","sources":["../../../src/components/table_filter_panel/table_filter_panel.tsx"],"sourcesContent":["import { DataSource } from '@tcn/resource-store';\nimport { ReactElement, useState, createContext } from 'react';\nimport { FieldFilterProps } from './field_filters/field_filter_props.js';\nimport { TableFilterPanelPresenter } from './table_filter_panel_presenter.js';\nimport { Panel, type PanelProps } from '@tcn/ui/surfaces';\nimport { Header, Section, VBody } from '@tcn/ui/layouts';\nimport styles from './table_filter_panel.module.css';\nimport { Spacer } from '@tcn/ui/stacks';\nimport { Button } from '@tcn/ui/actions';\nimport { CrossIcon } from '@tcn/icons/cross_icon.js';\n\nexport interface TableFilterPanelProps extends Omit<PanelProps, 'children'> {\n children: ReactElement<FieldFilterProps>[] | ReactElement<FieldFilterProps>;\n dataSource: DataSource<any>;\n onClose?: () => void;\n}\n\nexport function TableFilterPanel({\n children,\n dataSource,\n className,\n onClose,\n ...props\n}: TableFilterPanelProps) {\n const [presenter] = useState(() => {\n return new TableFilterPanelPresenter(dataSource);\n });\n\n return (\n <TableFilterPanelContext.Provider value={presenter}>\n <Panel\n className={`${styles['table-filter-panel']} tcn-table-filter-panel ${className}`}\n {...props}\n >\n <Header>\n Table Filters\n <Spacer />\n {onClose && (\n <Button utility hierarchy=\"tertiary\" onClick={onClose}>\n <CrossIcon />\n </Button>\n )}\n </Header>\n <VBody\n className={`${styles['table-filter-panel-body']} tcn-table-filter-panel-body`}\n >\n <Section\n className={`${styles['table-filter-panel-section']} tcn-table-filter-panel-section`}\n >\n {children}\n </Section>\n </VBody>\n </Panel>\n </TableFilterPanelContext.Provider>\n );\n}\n\nexport const TableFilterPanelContext = createContext<TableFilterPanelPresenter | null>(\n null\n);\n"],"names":["TableFilterPanel","children","dataSource","className","onClose","props","presenter","useState","TableFilterPanelPresenter","jsx","TableFilterPanelContext","jsxs","Panel","styles","Header","Spacer","Button","CrossIcon","VBody","Section","createContext"],"mappings":";;;;;;;;;AAiBO,SAASA,EAAiB;AAAA,EAC/B,UAAAC;AAAA,EACA,YAAAC;AAAA,EACA,WAAAC;AAAA,EACA,SAAAC;AAAA,EACA,GAAGC;AACL,GAA0B;AACxB,QAAM,CAACC,CAAS,IAAIC,EAAS,MACpB,IAAIC,EAA0BN,CAAU,CAChD;AAED,SACE,gBAAAO,EAACC,EAAwB,UAAxB,EAAiC,OAAOJ,GACvC,UAAA,gBAAAK;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,WAAW,GAAGC,EAAO,oBAAoB,CAAC,2BAA2BV,CAAS;AAAA,MAC7E,GAAGE;AAAA,MAEJ,UAAA;AAAA,QAAA,gBAAAM,EAACG,GAAA,EAAO,UAAA;AAAA,UAAA;AAAA,4BAELC,GAAA,EAAO;AAAA,UACPX,KACC,gBAAAK,EAACO,GAAA,EAAO,SAAO,IAAC,WAAU,YAAW,SAASZ,GAC5C,UAAA,gBAAAK,EAACQ,GAAA,CAAA,CAAU,EAAA,CACb;AAAA,QAAA,GAEJ;AAAA,QACA,gBAAAR;AAAA,UAACS;AAAA,UAAA;AAAA,YACC,WAAW,GAAGL,EAAO,yBAAyB,CAAC;AAAA,YAE/C,UAAA,gBAAAJ;AAAA,cAACU;AAAA,cAAA;AAAA,gBACC,WAAW,GAAGN,EAAO,4BAA4B,CAAC;AAAA,gBAEjD,UAAAZ;AAAA,cAAA;AAAA,YAAA;AAAA,UACH;AAAA,QAAA;AAAA,MACF;AAAA,IAAA;AAAA,EAAA,GAEJ;AAEJ;AAEO,MAAMS,IAA0BU;AAAA,EACrC;AACF;"}
1
+ {"version":3,"file":"table_filter_panel.js","sources":["../../../src/components/table_filter_panel/table_filter_panel.tsx"],"sourcesContent":["import { DataSource } from '@tcn/resource-store';\nimport { ReactElement, useState, createContext } from 'react';\nimport { FieldFilterProps } from './field_filters/field_filter_props.js';\nimport { TableFilterPanelPresenter } from './table_filter_panel_presenter.js';\nimport { Aside, type PanelProps } from '@tcn/ui/surfaces';\nimport { Body, Header, Scaffold, Section } from '@tcn/ui/layouts';\nimport styles from './table_filter_panel.module.css';\nimport { Spacer } from '@tcn/ui/stacks';\nimport { Button } from '@tcn/ui/actions';\nimport { CrossIcon } from '@tcn/icons/cross_icon.js';\nimport { Title } from '@tcn/ui/typography';\n\nexport interface TableFilterPanelProps extends Omit<PanelProps, 'children'> {\n children: ReactElement<FieldFilterProps>[] | ReactElement<FieldFilterProps>;\n dataSource: DataSource<any>;\n onClose?: () => void;\n title?: string;\n}\n\nexport function TableFilterPanel({\n children,\n dataSource,\n className,\n onClose,\n title = 'Table Filters',\n ...props\n}: TableFilterPanelProps) {\n const [presenter] = useState(() => {\n return new TableFilterPanelPresenter(dataSource);\n });\n\n return (\n <TableFilterPanelContext.Provider value={presenter}>\n <Aside className={`tcn-table-filter-panel ${className}`} {...props}>\n <Header>\n <Title>{title}</Title>\n <Spacer />\n {onClose && (\n <Button utility hierarchy=\"tertiary\" onClick={onClose}>\n <CrossIcon />\n </Button>\n )}\n </Header>\n <Body\n className={`${styles['table-filter-panel-body']} tcn-table-filter-panel-body`}\n >\n <Scaffold>\n <Section\n className={`${styles['table-filter-panel-section']} tcn-table-filter-panel-section`}\n >\n {children}\n </Section>\n </Scaffold>\n </Body>\n </Aside>\n </TableFilterPanelContext.Provider>\n );\n}\n\nexport const TableFilterPanelContext = createContext<TableFilterPanelPresenter | null>(\n null\n);\n"],"names":["TableFilterPanel","children","dataSource","className","onClose","title","props","presenter","useState","TableFilterPanelPresenter","jsx","TableFilterPanelContext","jsxs","Aside","Header","Title","Spacer","Button","CrossIcon","Body","styles","Scaffold","Section","createContext"],"mappings":";;;;;;;;;;AAmBO,SAASA,EAAiB;AAAA,EAC/B,UAAAC;AAAA,EACA,YAAAC;AAAA,EACA,WAAAC;AAAA,EACA,SAAAC;AAAA,EACA,OAAAC,IAAQ;AAAA,EACR,GAAGC;AACL,GAA0B;AACxB,QAAM,CAACC,CAAS,IAAIC,EAAS,MACpB,IAAIC,EAA0BP,CAAU,CAChD;AAED,SACE,gBAAAQ,EAACC,EAAwB,UAAxB,EAAiC,OAAOJ,GACvC,UAAA,gBAAAK,EAACC,GAAA,EAAM,WAAW,0BAA0BV,CAAS,IAAK,GAAGG,GAC3D,UAAA;AAAA,IAAA,gBAAAM,EAACE,GAAA,EACC,UAAA;AAAA,MAAA,gBAAAJ,EAACK,KAAO,UAAAV,EAAA,CAAM;AAAA,wBACbW,GAAA,EAAO;AAAA,MACPZ,KACC,gBAAAM,EAACO,GAAA,EAAO,SAAO,IAAC,WAAU,YAAW,SAASb,GAC5C,UAAA,gBAAAM,EAACQ,GAAA,CAAA,CAAU,EAAA,CACb;AAAA,IAAA,GAEJ;AAAA,IACA,gBAAAR;AAAA,MAACS;AAAA,MAAA;AAAA,QACC,WAAW,GAAGC,EAAO,yBAAyB,CAAC;AAAA,QAE/C,4BAACC,GAAA,EACC,UAAA,gBAAAX;AAAA,UAACY;AAAA,UAAA;AAAA,YACC,WAAW,GAAGF,EAAO,4BAA4B,CAAC;AAAA,YAEjD,UAAAnB;AAAA,UAAA;AAAA,QAAA,EACH,CACF;AAAA,MAAA;AAAA,IAAA;AAAA,EACF,EAAA,CACF,EAAA,CACF;AAEJ;AAEO,MAAMU,IAA0BY;AAAA,EACrC;AACF;"}
package/dist/table.css CHANGED
@@ -1 +1 @@
1
- ._table-body_b8c928c{border-spacing:0;width:auto;min-width:100%;height:auto;min-height:100%;table-layout:fixed;display:table}._table-body_b8c928c thead th,._table-body_b8c928c thead td{padding:0}:is(._table-body_b8c928c thead tr,._table-body_b8c928c tbody tr) th[data-stick-to=start],:is(._table-body_b8c928c thead tr,._table-body_b8c928c tbody tr) td[data-stick-to=start]{border-inline-end:1px solid #ccc}:is(._table-body_b8c928c thead tr,._table-body_b8c928c tbody tr) th[data-stick-to=end],:is(._table-body_b8c928c thead tr,._table-body_b8c928c tbody tr) td[data-stick-to=end]{border-inline-start:1px solid #ccc}._table-body_b8c928c tr[data-clickable=true]{cursor:pointer}._table-body_b8c928c thead tr th{position:sticky;top:0;z-index:1;box-sizing:border-box}._table-body_b8c928c thead{position:sticky;top:0;z-index:3}._table-body_b8c928c tbody{position:relative;z-index:1}._table-body_b8c928c tfoot{position:relative;z-index:2}._table-body_b8c928c th>div{display:flex;align-items:center}._table-body_b8c928c td>div{height:100%;display:flex;align-items:center}._table-body_b8c928c tfoot{position:sticky;bottom:0}._table-body_b8c928c td,._table-body_b8c928c th{vertical-align:middle}._table-body_b8c928c[data-is-clickable=true] td{cursor:pointer}
1
+ ._table-body_b8c928c{border-spacing:0;width:auto;min-width:100%;height:auto;min-height:100%;table-layout:fixed;display:table}:is(._table-body_b8c928c thead tr,._table-body_b8c928c tbody tr) th[data-stick-to=start],:is(._table-body_b8c928c thead tr,._table-body_b8c928c tbody tr) td[data-stick-to=start]{border-inline-end:1px solid #ccc}:is(._table-body_b8c928c thead tr,._table-body_b8c928c tbody tr) th[data-stick-to=end],:is(._table-body_b8c928c thead tr,._table-body_b8c928c tbody tr) td[data-stick-to=end]{border-inline-start:1px solid #ccc}._table-body_b8c928c tr[data-clickable=true]{cursor:pointer}._table-body_b8c928c thead tr th{position:sticky;top:0;z-index:1;box-sizing:border-box}._table-body_b8c928c thead{position:sticky;top:0;z-index:3}._table-body_b8c928c tbody{position:relative;z-index:1}._table-body_b8c928c tfoot{position:relative;z-index:2}._table-body_b8c928c th>div{display:flex;align-items:center}._table-body_b8c928c td>div{height:100%;display:flex;align-items:center}._table-body_b8c928c tfoot{position:sticky;bottom:0}._table-body_b8c928c td,._table-body_b8c928c th{vertical-align:middle}._table-body_b8c928c[data-is-clickable=true] td{cursor:pointer}
@@ -1 +1 @@
1
- ._table-filter-panel_124e30e{--material: #fafafa;background:var(--material)}._table-filter-panel-body_c016eb0{padding-block:8px}._table-filter-panel-body_c016eb0 ._table-filter-panel-section_cfd2eb9{gap:8px}
1
+ ._table-filter-panel-body_c016eb0{padding-block:8px}._table-filter-panel-body_c016eb0 ._table-filter-panel-section_cfd2eb9{gap:8px}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tcn/ui-table",
3
- "version": "2.3.15",
3
+ "version": "2.4.1",
4
4
  "type": "module",
5
5
  "description": "React table component library",
6
6
  "author": "TCN",
@@ -39,11 +39,11 @@
39
39
  ],
40
40
  "dependencies": {
41
41
  "clarity-pattern-parser": "^11.5.4",
42
- "@tcn/icons": "2.3.0",
43
42
  "@tcn/aip-160": "1.2.5",
44
- "@tcn/resource-store": "2.5.4",
45
- "@tcn/state": "1.3.1",
46
- "@tcn/ui": "0.12.6"
43
+ "@tcn/state": "1.3.2",
44
+ "@tcn/resource-store": "2.5.6",
45
+ "@tcn/icons": "2.3.0",
46
+ "@tcn/ui": "0.13.1"
47
47
  },
48
48
  "peerDependencies": {
49
49
  "react": "^18.2.0",
@@ -3,14 +3,16 @@ import React, { useCallback, useState } from 'react';
3
3
 
4
4
  import { CrossIcon } from '@tcn/icons/cross_icon.js';
5
5
  import {
6
+ type DataSource,
6
7
  StaticDataSource,
7
8
  StaticDateField,
8
9
  StaticNumberField,
9
10
  StaticStringField,
10
11
  } from '@tcn/resource-store';
11
- import { useSignalValue } from '@tcn/state';
12
+ import { Signal, useSignalValue } from '@tcn/state';
12
13
  import { Button } from '@tcn/ui/actions';
13
- import { Footer, Header, HBody, Rail, Side, VBody } from '@tcn/ui/layouts';
14
+ import { Checkbox } from '@tcn/ui/inputs';
15
+ import { Footer, Header, Rail, Side, Body } from '@tcn/ui/layouts';
14
16
  import { Box, HStack, Spacer, VStack, ZStack } from '@tcn/ui/stacks';
15
17
  import { Panel } from '@tcn/ui/surfaces';
16
18
  import { Title } from '@tcn/ui/typography';
@@ -308,7 +310,7 @@ export function WithTableHeaderAndTableFooter() {
308
310
  <Spacer />
309
311
  <GlobalSearch dataSource={source} />
310
312
  </Header>
311
- <VBody height="flex">
313
+ <Body height="flex">
312
314
  <Table
313
315
  dataSource={source}
314
316
  onRowClick={item => {
@@ -323,7 +325,7 @@ export function WithTableHeaderAndTableFooter() {
323
325
  <TableColumn heading="Occupation" fieldName="occupation" />
324
326
  <TableColumn heading="Active" fieldName="isActive" />
325
327
  </Table>
326
- </VBody>
328
+ </Body>
327
329
  <Footer>
328
330
  <TablePager dataSource={source} />
329
331
  </Footer>
@@ -411,21 +413,14 @@ export function WithFilterPanel() {
411
413
  <StoryWrapper>
412
414
  <Panel height="100%">
413
415
  <Header>The Table</Header>
414
- <VBody>
416
+ <Body>
415
417
  <Rail>
418
+ {/* TODO: Refactor to remove duplicate column logic (outer Side and inner Aside - in TableFilterPanel ) */}
416
419
  <Side padding="0px">
417
- <Box
418
- minWidth="300px"
419
- enableResizeOnEnd
420
- overflowY="auto"
421
- height="100%"
422
- style={{
423
- scrollbarGutter: 'stable', // Not sure if there is a better way to prevent the scrollbar appearing causing a horizontal scroll - to to resizing, we fix the width of the content, so adding a vertical scrollbar causing a horizontal overflow.
424
- }}
425
- >
420
+ <Box minWidth="300px" enableResizeOnEnd height="100%" maxHeight="100%">
426
421
  <TableFilterPanel
427
422
  dataSource={source}
428
- onClose={() => window.alert('Closed')}
423
+ onClose={() => window.alert('onClose callback called.')}
429
424
  >
430
425
  <StringFieldFilter fieldName="name" label="Name (string)" />
431
426
  <NumberFieldFilter fieldName="age" label="Age (number)" />
@@ -434,8 +429,8 @@ export function WithFilterPanel() {
434
429
  </TableFilterPanel>
435
430
  </Box>
436
431
  </Side>
437
- <HBody>
438
- <Table dataSource={source} height="100%" width="flex">
432
+ <Body>
433
+ <Table dataSource={source} height="100%">
439
434
  <TableColumn heading="Name" fieldName="name" sticky="start" />
440
435
  <TableColumn heading="Age" fieldName="age" width={150} canSort />
441
436
  <TableColumn heading="Email" fieldName="email" width={300} />
@@ -449,9 +444,9 @@ export function WithFilterPanel() {
449
444
  <TableColumn heading="Occupation" fieldName="occupation" width={200} />
450
445
  <TableColumn heading="Active" fieldName="isActive" />
451
446
  </Table>
452
- </HBody>
447
+ </Body>
453
448
  </Rail>
454
- </VBody>
449
+ </Body>
455
450
  <Footer>
456
451
  <TablePager dataSource={source} />
457
452
  </Footer>
@@ -460,4 +455,139 @@ export function WithFilterPanel() {
460
455
  );
461
456
  }
462
457
 
458
+ // Selection Table
459
+
460
+ type SelectionStatus = 'none' | 'some' | 'all';
461
+
462
+ class SelectionPresenter<T extends { id: string }> {
463
+ private _selected = new Signal<Set<string>>(new Set());
464
+ private _status = new Signal<SelectionStatus>('none');
465
+ private _dataSource: DataSource<T>;
466
+
467
+ constructor(dataSource: DataSource<T>) {
468
+ this._dataSource = dataSource;
469
+ }
470
+
471
+ get broadcasts() {
472
+ return {
473
+ selected: this._selected.broadcast,
474
+ status: this._status.broadcast,
475
+ };
476
+ }
477
+
478
+ private getTotalRowCount(): number {
479
+ return this._dataSource.broadcasts.currentResults.get().length;
480
+ }
481
+
482
+ private getSelectedCount(): number {
483
+ return this._selected.get().size;
484
+ }
485
+
486
+ private getNextStatus() {
487
+ const selectedCount = this.getSelectedCount();
488
+ const totalCount = this.getTotalRowCount();
489
+ if (selectedCount === totalCount) return 'all';
490
+ if (selectedCount === 0) return 'none';
491
+ if (selectedCount < totalCount) return 'some';
492
+ return 'none';
493
+ }
494
+
495
+ private setStatus() {
496
+ const status = this.getNextStatus();
497
+ this._status.set(status);
498
+ }
499
+
500
+ toggleRow(row: T) {
501
+ this._selected.transform(selected => {
502
+ if (selected.has(row.id)) selected.delete(row.id);
503
+ else selected.add(row.id);
504
+ return selected;
505
+ });
506
+ this.setStatus();
507
+ }
508
+
509
+ private getAllIds(): string[] {
510
+ return this._dataSource.broadcasts.currentResults.get().map((r: T) => r.id);
511
+ }
512
+
513
+ toggleAllRows() {
514
+ const status = this._status.get();
515
+ if (status === 'all') {
516
+ this._selected.set(new Set());
517
+ } else {
518
+ this._selected.set(new Set(this.getAllIds()));
519
+ }
520
+ this.setStatus();
521
+ }
522
+ }
523
+
524
+ const RowCheck = ({
525
+ item,
526
+ presenter,
527
+ }: {
528
+ item: DataItem;
529
+ presenter: SelectionPresenter<DataItem>;
530
+ }) => {
531
+ const selected = useSignalValue(presenter.broadcasts.selected);
532
+ const status = useSignalValue(presenter.broadcasts.status);
533
+ const isChecked = selected.has(item.id) || status === 'all';
534
+ return <Checkbox checked={isChecked} onChange={() => presenter.toggleRow(item)} />;
535
+ };
536
+
537
+ const ColumnCheck = ({ presenter }: { presenter: SelectionPresenter<DataItem> }) => {
538
+ const status = useSignalValue(presenter.broadcasts.status);
539
+ const isChecked = status === 'all';
540
+
541
+ return (
542
+ <Checkbox
543
+ checked={isChecked}
544
+ data-indeterminate={status === 'some'}
545
+ onChange={() => presenter.toggleAllRows()}
546
+ onClick={e => e.stopPropagation()}
547
+ />
548
+ );
549
+ };
550
+
551
+ export function SelectionTable() {
552
+ const [source] = useState(() => {
553
+ return new StaticDataSource<DataItem>(items, [
554
+ new StaticStringField('id', i => i.id),
555
+ new StaticStringField('name', i => i.name),
556
+ new StaticNumberField('age', i => i.age),
557
+ new StaticStringField('email', i => i.email),
558
+ new StaticStringField('city', i => i.city),
559
+ new StaticStringField('country', i => i.country),
560
+ new StaticStringField('occupation', i => i.occupation),
561
+ new StaticStringField('isActive', i => (i.isActive ? 'Yes' : 'No')),
562
+ ]);
563
+ });
564
+
565
+ const [presenter] = useState(() => new SelectionPresenter<DataItem>(source));
566
+
567
+ return (
568
+ <StoryWrapper>
569
+ <Panel>
570
+ <Header>Selection Table</Header>
571
+ <Body>
572
+ <Table dataSource={source}>
573
+ <TableColumn
574
+ heading={<ColumnCheck presenter={presenter} />}
575
+ sticky="start"
576
+ width={48}
577
+ render={(item: DataItem) => <RowCheck item={item} presenter={presenter} />}
578
+ />
579
+ <TableColumn heading="Name" fieldName="name" />
580
+ <TableColumn heading="Age" fieldName="age" />
581
+ <TableColumn heading="Email" fieldName="email" />
582
+ <TableColumn heading="City" fieldName="city" />
583
+ <TableColumn heading="Country" fieldName="country" />
584
+ <TableColumn heading="Occupation" fieldName="occupation" />
585
+ <TableColumn heading="Active" fieldName="isActive" />
586
+ </Table>
587
+ </Body>
588
+ </Panel>
589
+ </StoryWrapper>
590
+ );
591
+ }
592
+
463
593
  export default meta;
@@ -34,12 +34,12 @@ export function HeaderCell({
34
34
 
35
35
  return (
36
36
  <TH
37
- className={cellStyles['table-cell']}
37
+ className={`tcn-header-cell ${cellStyles['table-cell']}`}
38
38
  data-stick-to={sticky}
39
39
  style={{ width: `${width}px`, zIndex }}
40
40
  >
41
41
  <Box
42
- padding="0px 8px" // FIXME: should be on theme ideally.
42
+ className="tcn-table-cell-content"
43
43
  overflow="hidden"
44
44
  minWidth="24px"
45
45
  maxWidth="unset"
@@ -8,16 +8,6 @@
8
8
  display: table;
9
9
  }
10
10
 
11
- /* FIXME: These styles should be handled at the theme level
12
- but tcn ui does not handle resizing or sticky logic. */
13
- /* Reset padding for header - due to resize logic */
14
- .table-body thead {
15
- th,
16
- td {
17
- padding: 0;
18
- }
19
- }
20
-
21
11
  .table-body thead tr,
22
12
  .table-body tbody tr {
23
13
  th[data-stick-to="start"],
@@ -1,8 +1,3 @@
1
- .table-filter-panel {
2
- --material: #fafafa;
3
- background: var(--material);
4
- }
5
-
6
1
  .table-filter-panel-body {
7
2
  padding-block: 8px;
8
3
  .table-filter-panel-section {
@@ -3,10 +3,11 @@ import {
3
3
  StaticNumberField,
4
4
  StaticStringField,
5
5
  } from '@tcn/resource-store';
6
- import React, { useState } from 'react';
6
+ import { useState } from 'react';
7
7
  import { items } from '../../__stories__/sample_data.js';
8
8
  import { NumberFieldFilter } from './field_filters/number_field_filter.js';
9
9
  import { TableFilterPanel } from './table_filter_panel.js';
10
+ import { VStack } from '@tcn/ui/stacks';
10
11
 
11
12
  type DataItem = {
12
13
  id: string;
@@ -37,10 +38,10 @@ export const Demo = () => {
37
38
  });
38
39
 
39
40
  return (
40
- <div style={{ width: '300px' }}>
41
+ <VStack width="300px" height="100%">
41
42
  <TableFilterPanel dataSource={source}>
42
43
  <NumberFieldFilter fieldName="age" label="Age" />
43
44
  </TableFilterPanel>
44
- </div>
45
+ </VStack>
45
46
  );
46
47
  };
@@ -2,17 +2,19 @@ import { DataSource } from '@tcn/resource-store';
2
2
  import { ReactElement, useState, createContext } from 'react';
3
3
  import { FieldFilterProps } from './field_filters/field_filter_props.js';
4
4
  import { TableFilterPanelPresenter } from './table_filter_panel_presenter.js';
5
- import { Panel, type PanelProps } from '@tcn/ui/surfaces';
6
- import { Header, Section, VBody } from '@tcn/ui/layouts';
5
+ import { Aside, type PanelProps } from '@tcn/ui/surfaces';
6
+ import { Body, Header, Scaffold, Section } from '@tcn/ui/layouts';
7
7
  import styles from './table_filter_panel.module.css';
8
8
  import { Spacer } from '@tcn/ui/stacks';
9
9
  import { Button } from '@tcn/ui/actions';
10
10
  import { CrossIcon } from '@tcn/icons/cross_icon.js';
11
+ import { Title } from '@tcn/ui/typography';
11
12
 
12
13
  export interface TableFilterPanelProps extends Omit<PanelProps, 'children'> {
13
14
  children: ReactElement<FieldFilterProps>[] | ReactElement<FieldFilterProps>;
14
15
  dataSource: DataSource<any>;
15
16
  onClose?: () => void;
17
+ title?: string;
16
18
  }
17
19
 
18
20
  export function TableFilterPanel({
@@ -20,6 +22,7 @@ export function TableFilterPanel({
20
22
  dataSource,
21
23
  className,
22
24
  onClose,
25
+ title = 'Table Filters',
23
26
  ...props
24
27
  }: TableFilterPanelProps) {
25
28
  const [presenter] = useState(() => {
@@ -28,12 +31,9 @@ export function TableFilterPanel({
28
31
 
29
32
  return (
30
33
  <TableFilterPanelContext.Provider value={presenter}>
31
- <Panel
32
- className={`${styles['table-filter-panel']} tcn-table-filter-panel ${className}`}
33
- {...props}
34
- >
34
+ <Aside className={`tcn-table-filter-panel ${className}`} {...props}>
35
35
  <Header>
36
- Table Filters
36
+ <Title>{title}</Title>
37
37
  <Spacer />
38
38
  {onClose && (
39
39
  <Button utility hierarchy="tertiary" onClick={onClose}>
@@ -41,16 +41,18 @@ export function TableFilterPanel({
41
41
  </Button>
42
42
  )}
43
43
  </Header>
44
- <VBody
44
+ <Body
45
45
  className={`${styles['table-filter-panel-body']} tcn-table-filter-panel-body`}
46
46
  >
47
- <Section
48
- className={`${styles['table-filter-panel-section']} tcn-table-filter-panel-section`}
49
- >
50
- {children}
51
- </Section>
52
- </VBody>
53
- </Panel>
47
+ <Scaffold>
48
+ <Section
49
+ className={`${styles['table-filter-panel-section']} tcn-table-filter-panel-section`}
50
+ >
51
+ {children}
52
+ </Section>
53
+ </Scaffold>
54
+ </Body>
55
+ </Aside>
54
56
  </TableFilterPanelContext.Provider>
55
57
  );
56
58
  }