@vuu-ui/vuu-table-extras 0.13.13 → 0.13.14

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.
@@ -5,12 +5,12 @@ var core = require('@salt-ds/core');
5
5
  var styles = require('@salt-ds/styles');
6
6
  var window = require('@salt-ds/window');
7
7
  var vuuUiControls = require('@vuu-ui/vuu-ui-controls');
8
- var TableProvider = require('../table-provider/TableProvider.js');
9
8
  var cx = require('clsx');
10
9
  var react = require('react');
11
- var ColumnMenu$1 = require('./ColumnMenu.css.js');
12
- var columnMenuUtils = require('./column-menu-utils.js');
13
10
  var TableSettingsPanel = require('../table-column-settings/TableSettingsPanel.js');
11
+ var TableProvider = require('../table-provider/TableProvider.js');
12
+ var columnMenuUtils = require('./column-menu-utils.js');
13
+ var ColumnMenu$1 = require('./ColumnMenu.css.js');
14
14
 
15
15
  const classBase = "vuuColumnMenu";
16
16
  const defaultColumnMenuPermissions = {
@@ -1 +1 @@
1
- {"version":3,"file":"ColumnMenu.js","sources":["../../src/column-menu/ColumnMenu.tsx"],"sourcesContent":["import { Menu, MenuPanel, MenuTrigger } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport {\n ColumnDescriptor,\n ColumnMenuPermissions,\n} from \"@vuu-ui/vuu-table-types\";\nimport { IconButton } from \"@vuu-ui/vuu-ui-controls\";\nimport { useTableContext } from \"../table-provider/TableProvider\";\nimport cx from \"clsx\";\nimport { HTMLAttributes, MouseEventHandler, useCallback } from \"react\";\n\nimport columnMenuCss from \"./ColumnMenu.css\";\nimport {\n buildAggregationMenuItems,\n buildPinMenuItems,\n buildGroupMenu,\n buildSortMenu,\n buildVisibilityMenuItems,\n ColumnMenuActionType,\n getColumnMenuActionType,\n type MenuItemClickHandler,\n buildSettingsMenuItems,\n} from \"./column-menu-utils\";\nimport { MenuActionHandler } from \"@vuu-ui/vuu-context-menu\";\nimport { defaultTableSettingsPermissions } from \"../table-column-settings/TableSettingsPanel\";\n\nconst classBase = \"vuuColumnMenu\";\n\nconst defaultColumnMenuPermissions: Readonly<ColumnMenuPermissions> = {\n allowSort: true,\n allowGroup: true,\n allowAggregation: true,\n allowHide: true,\n allowPin: true,\n allowColumnSettings: true,\n allowTableSettings: defaultTableSettingsPermissions,\n};\n\nexport interface ColumnMenuProps extends HTMLAttributes<HTMLSpanElement> {\n column: ColumnDescriptor;\n menuActionHandler?: MenuActionHandler<ColumnMenuActionType, ColumnDescriptor>;\n menuPermissions?: ColumnMenuPermissions;\n}\n\nexport const ColumnMenu = ({\n className,\n column,\n menuActionHandler: menuActionHandlerProp,\n menuPermissions: {\n allowSort,\n allowGroup,\n allowAggregation,\n allowHide,\n allowPin,\n allowColumnSettings,\n allowTableSettings,\n } = defaultColumnMenuPermissions,\n}: ColumnMenuProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-column-menu\",\n css: columnMenuCss,\n window: targetWindow,\n });\n\n const { dataSource, menuActionHandler } = useTableContext(true);\n\n const menuActionClickHandler = useCallback<MenuItemClickHandler>(\n (evt) => {\n const columnMenuActionType = getColumnMenuActionType(evt.target);\n if (menuActionHandlerProp?.(columnMenuActionType, column) !== true) {\n return menuActionHandler(columnMenuActionType, column);\n }\n },\n [column, menuActionHandler, menuActionHandlerProp],\n );\n\n const sortMenu = buildSortMenu(\n column,\n dataSource,\n menuActionClickHandler,\n allowSort,\n );\n const groupMenu = buildGroupMenu(\n column,\n dataSource,\n menuActionClickHandler,\n allowGroup,\n );\n const aggregationMenu = buildAggregationMenuItems(\n column,\n dataSource,\n menuActionClickHandler,\n allowAggregation,\n );\n const visibilityMenuItems = buildVisibilityMenuItems(\n column,\n menuActionClickHandler,\n allowHide,\n );\n const pinMenu = buildPinMenuItems(column, menuActionClickHandler, allowPin);\n const settingsMenuItems = buildSettingsMenuItems(\n column,\n menuActionClickHandler,\n allowColumnSettings,\n allowTableSettings,\n );\n\n const handleClick = useCallback<MouseEventHandler<HTMLButtonElement>>(\n (evt) => {\n // Prevent sort from triggering if the click were to bubble.\n evt.stopPropagation();\n },\n [],\n );\n\n return (\n <Menu>\n <MenuTrigger>\n <IconButton\n appearance=\"transparent\"\n className={cx(classBase, className)}\n data-embedded\n icon=\"more-vert\"\n sentiment=\"neutral\"\n aria-label=\"Open Column Menu\"\n onClick={handleClick}\n />\n </MenuTrigger>\n <MenuPanel>\n {sortMenu}\n {groupMenu}\n {aggregationMenu}\n {visibilityMenuItems}\n {pinMenu}\n {settingsMenuItems}\n </MenuPanel>\n </Menu>\n );\n};\n"],"names":["defaultTableSettingsPermissions","useWindow","useComponentCssInjection","columnMenuCss","useTableContext","useCallback","getColumnMenuActionType","buildSortMenu","buildGroupMenu","buildAggregationMenuItems","buildVisibilityMenuItems","buildPinMenuItems","buildSettingsMenuItems","Menu","jsx","MenuTrigger","IconButton","MenuPanel"],"mappings":"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"}
1
+ {"version":3,"file":"ColumnMenu.js","sources":["../../src/column-menu/ColumnMenu.tsx"],"sourcesContent":["import { Menu, MenuPanel, MenuTrigger } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { MenuActionHandler } from \"@vuu-ui/vuu-context-menu\";\nimport {\n ColumnDescriptor,\n ColumnMenuPermissions,\n} from \"@vuu-ui/vuu-table-types\";\nimport { IconButton } from \"@vuu-ui/vuu-ui-controls\";\nimport cx from \"clsx\";\nimport { HTMLAttributes, MouseEventHandler, useCallback } from \"react\";\nimport { defaultTableSettingsPermissions } from \"../table-column-settings/TableSettingsPanel\";\nimport { useTableContext } from \"../table-provider/TableProvider\";\nimport {\n buildAggregationMenuItems,\n buildGroupMenu,\n buildPinMenuItems,\n buildSettingsMenuItems,\n buildSortMenu,\n buildVisibilityMenuItems,\n ColumnMenuActionType,\n getColumnMenuActionType,\n type MenuItemClickHandler,\n} from \"./column-menu-utils\";\n\nimport columnMenuCss from \"./ColumnMenu.css\";\n\nconst classBase = \"vuuColumnMenu\";\n\nconst defaultColumnMenuPermissions: Readonly<ColumnMenuPermissions> = {\n allowSort: true,\n allowGroup: true,\n allowAggregation: true,\n allowHide: true,\n allowPin: true,\n allowColumnSettings: true,\n allowTableSettings: defaultTableSettingsPermissions,\n};\n\nexport interface ColumnMenuProps extends HTMLAttributes<HTMLSpanElement> {\n column: ColumnDescriptor;\n menuActionHandler?: MenuActionHandler<ColumnMenuActionType, ColumnDescriptor>;\n menuPermissions?: ColumnMenuPermissions;\n}\n\nexport const ColumnMenu = ({\n className,\n column,\n menuActionHandler: menuActionHandlerProp,\n menuPermissions: {\n allowSort,\n allowGroup,\n allowAggregation,\n allowHide,\n allowPin,\n allowColumnSettings,\n allowTableSettings,\n } = defaultColumnMenuPermissions,\n}: ColumnMenuProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-column-menu\",\n css: columnMenuCss,\n window: targetWindow,\n });\n\n const { dataSource, menuActionHandler } = useTableContext(true);\n\n const menuActionClickHandler = useCallback<MenuItemClickHandler>(\n (evt) => {\n const columnMenuActionType = getColumnMenuActionType(evt.target);\n if (menuActionHandlerProp?.(columnMenuActionType, column) !== true) {\n return menuActionHandler(columnMenuActionType, column);\n }\n },\n [column, menuActionHandler, menuActionHandlerProp],\n );\n\n const sortMenu = buildSortMenu(\n column,\n dataSource,\n menuActionClickHandler,\n allowSort,\n );\n const groupMenu = buildGroupMenu(\n column,\n dataSource,\n menuActionClickHandler,\n allowGroup,\n );\n const aggregationMenu = buildAggregationMenuItems(\n column,\n dataSource,\n menuActionClickHandler,\n allowAggregation,\n );\n const visibilityMenuItems = buildVisibilityMenuItems(\n column,\n menuActionClickHandler,\n allowHide,\n );\n const pinMenu = buildPinMenuItems(column, menuActionClickHandler, allowPin);\n const settingsMenuItems = buildSettingsMenuItems(\n column,\n menuActionClickHandler,\n allowColumnSettings,\n allowTableSettings,\n );\n\n const handleClick = useCallback<MouseEventHandler<HTMLButtonElement>>(\n (evt) => {\n // Prevent sort from triggering if the click were to bubble.\n evt.stopPropagation();\n },\n [],\n );\n\n return (\n <Menu>\n <MenuTrigger>\n <IconButton\n appearance=\"transparent\"\n className={cx(classBase, className)}\n data-embedded\n icon=\"more-vert\"\n sentiment=\"neutral\"\n aria-label=\"Open Column Menu\"\n onClick={handleClick}\n />\n </MenuTrigger>\n <MenuPanel>\n {sortMenu}\n {groupMenu}\n {aggregationMenu}\n {visibilityMenuItems}\n {pinMenu}\n {settingsMenuItems}\n </MenuPanel>\n </Menu>\n );\n};\n"],"names":["defaultTableSettingsPermissions","useWindow","useComponentCssInjection","columnMenuCss","useTableContext","useCallback","getColumnMenuActionType","buildSortMenu","buildGroupMenu","buildAggregationMenuItems","buildVisibilityMenuItems","buildPinMenuItems","buildSettingsMenuItems","Menu","jsx","MenuTrigger","IconButton","MenuPanel"],"mappings":"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"}
@@ -6,9 +6,18 @@ var styles = require('@salt-ds/styles');
6
6
  var window = require('@salt-ds/window');
7
7
  var react = require('react');
8
8
  var DatasourceStats = require('./DatasourceStats.css.js');
9
+ var vuuUtils = require('@vuu-ui/vuu-utils');
9
10
 
10
11
  const classBase = "vuuDatasourceStats";
11
12
  const numberFormatter = new Intl.NumberFormat();
13
+ const timeFormatter = vuuUtils.formatDate({ time: "hh:mm:ss" });
14
+ const formatTime = (ts) => {
15
+ if (typeof ts === "number") {
16
+ return timeFormatter(new Date(ts));
17
+ } else {
18
+ return void 0;
19
+ }
20
+ };
12
21
  const DataSourceStats = ({
13
22
  className: classNameProp,
14
23
  dataSource
@@ -21,19 +30,35 @@ const DataSourceStats = ({
21
30
  });
22
31
  const [range, setRange] = react.useState(dataSource.range);
23
32
  const [size, setSize] = react.useState(dataSource.size);
33
+ const [freezeTime, setFreezeTime] = react.useState(
34
+ formatTime(dataSource.freezeTimestamp)
35
+ );
36
+ const handleFreeze = react.useCallback(
37
+ (isFrozen, freezeTimestamp) => {
38
+ console.log(`DatasourceStats isFrozen ${isFrozen}`);
39
+ if (isFrozen) {
40
+ setFreezeTime(formatTime(freezeTimestamp));
41
+ } else {
42
+ setFreezeTime(void 0);
43
+ }
44
+ },
45
+ []
46
+ );
24
47
  react.useEffect(() => {
25
48
  setSize(dataSource.size);
26
49
  dataSource.on("resize", setSize);
27
50
  dataSource.on("range", setRange);
51
+ dataSource.on("freeze", handleFreeze);
28
52
  return () => {
29
53
  dataSource.removeListener("resize", setSize);
30
54
  dataSource.removeListener("range", setRange);
31
55
  };
32
- }, [dataSource]);
56
+ }, [dataSource, handleFreeze]);
33
57
  const className = cx(classBase, classNameProp);
34
58
  const from = numberFormatter.format(range.firstRowInViewport);
35
59
  const to = numberFormatter.format(range.lastRowInViewport);
36
60
  const value = numberFormatter.format(size);
61
+ console.log(`range = ${JSON.stringify(range)}`);
37
62
  if (size === 0) {
38
63
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${classBase}-label`, children: "No Rows to display" }) });
39
64
  } else {
@@ -43,7 +68,14 @@ const DataSourceStats = ({
43
68
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: "-" }),
44
69
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${classBase}-range`, children: to }),
45
70
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: "of" }),
46
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${classBase}-size`, children: value })
71
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${classBase}-size`, children: value }),
72
+ freezeTime !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(
73
+ "span",
74
+ {
75
+ className: `${classBase}-label`,
76
+ children: `(frozen at ${freezeTime})`
77
+ }
78
+ ) : null
47
79
  ] });
48
80
  }
49
81
  };
@@ -1 +1 @@
1
- {"version":3,"file":"DatasourceStats.js","sources":["../../src/datasource-stats/DatasourceStats.tsx"],"sourcesContent":["import { DataSource } from \"@vuu-ui/vuu-data-types\";\nimport cx from \"clsx\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { HTMLAttributes, useEffect, useState } from \"react\";\n\nimport dataSourceStats from \"./DatasourceStats.css\";\nimport { Range } from \"@vuu-ui/vuu-utils\";\n\ninterface DataSourceStatsProps extends HTMLAttributes<HTMLSpanElement> {\n dataSource: DataSource;\n}\n\nconst classBase = \"vuuDatasourceStats\";\n\nconst numberFormatter = new Intl.NumberFormat();\n\nexport const DataSourceStats = ({\n className: classNameProp,\n dataSource,\n}: DataSourceStatsProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-datasource-stats\",\n css: dataSourceStats,\n window: targetWindow,\n });\n\n const [range, setRange] = useState<Range>(dataSource.range);\n const [size, setSize] = useState(dataSource.size);\n useEffect(() => {\n setSize(dataSource.size);\n dataSource.on(\"resize\", setSize);\n dataSource.on(\"range\", setRange);\n return () => {\n dataSource.removeListener(\"resize\", setSize);\n dataSource.removeListener(\"range\", setRange);\n };\n }, [dataSource]);\n\n const className = cx(classBase, classNameProp);\n const from = numberFormatter.format(range.firstRowInViewport);\n const to = numberFormatter.format(range.lastRowInViewport);\n const value = numberFormatter.format(size);\n if (size === 0) {\n return (\n <div className={className}>\n <span className={`${classBase}-label`}>No Rows to display</span>\n </div>\n );\n } else {\n return (\n <div className={className}>\n <span className={`${classBase}-label`}>Rows</span>\n <span className={`${classBase}-range`}>{from}</span>\n <span>-</span>\n <span className={`${classBase}-range`}>{to}</span>\n <span>of</span>\n <span className={`${classBase}-size`}>{value}</span>\n </div>\n );\n }\n};\n"],"names":["useWindow","useComponentCssInjection","dataSourceStats","useState","useEffect","jsx","jsxs"],"mappings":";;;;;;;;;AAaA,MAAM,SAAY,GAAA,oBAAA;AAElB,MAAM,eAAA,GAAkB,IAAI,IAAA,CAAK,YAAa,EAAA;AAEvC,MAAM,kBAAkB,CAAC;AAAA,EAC9B,SAAW,EAAA,aAAA;AAAA,EACX;AACF,CAA4B,KAAA;AAC1B,EAAA,MAAM,eAAeA,gBAAU,EAAA;AAC/B,EAAyBC,+BAAA,CAAA;AAAA,IACvB,MAAQ,EAAA,sBAAA;AAAA,IACR,GAAK,EAAAC,eAAA;AAAA,IACL,MAAQ,EAAA;AAAA,GACT,CAAA;AAED,EAAA,MAAM,CAAC,KAAO,EAAA,QAAQ,CAAI,GAAAC,cAAA,CAAgB,WAAW,KAAK,CAAA;AAC1D,EAAA,MAAM,CAAC,IAAM,EAAA,OAAO,CAAI,GAAAA,cAAA,CAAS,WAAW,IAAI,CAAA;AAChD,EAAAC,eAAA,CAAU,MAAM;AACd,IAAA,OAAA,CAAQ,WAAW,IAAI,CAAA;AACvB,IAAW,UAAA,CAAA,EAAA,CAAG,UAAU,OAAO,CAAA;AAC/B,IAAW,UAAA,CAAA,EAAA,CAAG,SAAS,QAAQ,CAAA;AAC/B,IAAA,OAAO,MAAM;AACX,MAAW,UAAA,CAAA,cAAA,CAAe,UAAU,OAAO,CAAA;AAC3C,MAAW,UAAA,CAAA,cAAA,CAAe,SAAS,QAAQ,CAAA;AAAA,KAC7C;AAAA,GACF,EAAG,CAAC,UAAU,CAAC,CAAA;AAEf,EAAM,MAAA,SAAA,GAAY,EAAG,CAAA,SAAA,EAAW,aAAa,CAAA;AAC7C,EAAA,MAAM,IAAO,GAAA,eAAA,CAAgB,MAAO,CAAA,KAAA,CAAM,kBAAkB,CAAA;AAC5D,EAAA,MAAM,EAAK,GAAA,eAAA,CAAgB,MAAO,CAAA,KAAA,CAAM,iBAAiB,CAAA;AACzD,EAAM,MAAA,KAAA,GAAQ,eAAgB,CAAA,MAAA,CAAO,IAAI,CAAA;AACzC,EAAA,IAAI,SAAS,CAAG,EAAA;AACd,IACE,uBAAAC,cAAA,CAAC,KAAI,EAAA,EAAA,SAAA,EACH,QAAC,kBAAAA,cAAA,CAAA,MAAA,EAAA,EAAK,WAAW,CAAG,EAAA,SAAS,CAAU,MAAA,CAAA,EAAA,QAAA,EAAA,oBAAA,EAAkB,CAC3D,EAAA,CAAA;AAAA,GAEG,MAAA;AACL,IACE,uBAAAC,eAAA,CAAC,SAAI,SACH,EAAA,QAAA,EAAA;AAAA,sBAAAD,cAAA,CAAC,MAAK,EAAA,EAAA,SAAA,EAAW,CAAG,EAAA,SAAS,UAAU,QAAI,EAAA,MAAA,EAAA,CAAA;AAAA,qCAC1C,MAAK,EAAA,EAAA,SAAA,EAAW,CAAG,EAAA,SAAS,UAAW,QAAK,EAAA,IAAA,EAAA,CAAA;AAAA,sBAC7CA,cAAA,CAAC,UAAK,QAAC,EAAA,GAAA,EAAA,CAAA;AAAA,qCACN,MAAK,EAAA,EAAA,SAAA,EAAW,CAAG,EAAA,SAAS,UAAW,QAAG,EAAA,EAAA,EAAA,CAAA;AAAA,sBAC3CA,cAAA,CAAC,UAAK,QAAE,EAAA,IAAA,EAAA,CAAA;AAAA,qCACP,MAAK,EAAA,EAAA,SAAA,EAAW,CAAG,EAAA,SAAS,SAAU,QAAM,EAAA,KAAA,EAAA;AAAA,KAC/C,EAAA,CAAA;AAAA;AAGN;;;;"}
1
+ {"version":3,"file":"DatasourceStats.js","sources":["../../src/datasource-stats/DatasourceStats.tsx"],"sourcesContent":["import { DataSource } from \"@vuu-ui/vuu-data-types\";\nimport cx from \"clsx\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { HTMLAttributes, useCallback, useEffect, useState } from \"react\";\n\nimport dataSourceStats from \"./DatasourceStats.css\";\nimport { formatDate, Range } from \"@vuu-ui/vuu-utils\";\n\ninterface DataSourceStatsProps extends HTMLAttributes<HTMLSpanElement> {\n dataSource: DataSource;\n}\n\nconst classBase = \"vuuDatasourceStats\";\n\nconst numberFormatter = new Intl.NumberFormat();\nconst timeFormatter = formatDate({ time: \"hh:mm:ss\" });\n\nconst formatTime = (ts: number | undefined) => {\n if (typeof ts === \"number\") {\n return timeFormatter(new Date(ts));\n } else {\n return undefined;\n }\n};\n\nexport const DataSourceStats = ({\n className: classNameProp,\n dataSource,\n}: DataSourceStatsProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-datasource-stats\",\n css: dataSourceStats,\n window: targetWindow,\n });\n\n const [range, setRange] = useState<Range>(dataSource.range);\n const [size, setSize] = useState(dataSource.size);\n const [freezeTime, setFreezeTime] = useState(\n formatTime(dataSource.freezeTimestamp),\n );\n\n const handleFreeze = useCallback(\n (isFrozen: boolean, freezeTimestamp: number) => {\n console.log(`DatasourceStats isFrozen ${isFrozen}`);\n if (isFrozen) {\n setFreezeTime(formatTime(freezeTimestamp));\n } else {\n setFreezeTime(undefined);\n }\n },\n [],\n );\n\n useEffect(() => {\n setSize(dataSource.size);\n dataSource.on(\"resize\", setSize);\n dataSource.on(\"range\", setRange);\n dataSource.on(\"freeze\", handleFreeze);\n return () => {\n dataSource.removeListener(\"resize\", setSize);\n dataSource.removeListener(\"range\", setRange);\n };\n }, [dataSource, handleFreeze]);\n\n const className = cx(classBase, classNameProp);\n const from = numberFormatter.format(range.firstRowInViewport);\n const to = numberFormatter.format(range.lastRowInViewport);\n const value = numberFormatter.format(size);\n\n console.log(`range = ${JSON.stringify(range)}`);\n\n if (size === 0) {\n return (\n <div className={className}>\n <span className={`${classBase}-label`}>No Rows to display</span>\n </div>\n );\n } else {\n return (\n <div className={className}>\n <span className={`${classBase}-label`}>Rows</span>\n <span className={`${classBase}-range`}>{from}</span>\n <span>-</span>\n <span className={`${classBase}-range`}>{to}</span>\n <span>of</span>\n <span className={`${classBase}-size`}>{value}</span>\n {freezeTime !== undefined ? (\n <span\n className={`${classBase}-label`}\n >{`(frozen at ${freezeTime})`}</span>\n ) : null}\n </div>\n );\n }\n};\n"],"names":["formatDate","useWindow","useComponentCssInjection","dataSourceStats","useState","useCallback","useEffect","jsx","jsxs"],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ 'use strict';
2
+
3
+ var freezeControlCss = "\n\n.FreezeControl {\n align-items: center;\n background-color: var(--salt-container-secondary-background);\n border-radius: 6px;\n display: inline-grid;\n grid-template-columns: auto auto auto 1fr;\n grid-template-rows: var(--salt-size-base);\n column-gap: var(--salt-spacing-200);\n padding: 0 var(--salt-spacing-200);\n\n .saltSwitch {\n grid-area: 1/1/2/2;\n .saltSwitch-track {\n height: 24px;\n }\n }\n\n .FreezeControl-label {\n grid-area: 1/2/2/3;\n }\n\n .FreezeControl-lastUpdated {\n grid-area: 1/3/2/4;\n }\n\n & + .saltBadge-badge {\n cursor: default;\n display: none;\n }\n &.FreezeControl-showBadge + .saltBadge-badge {\n display: inline-block;\n }\n\n\n}\n\n";
4
+
5
+ module.exports = freezeControlCss;
6
+ //# sourceMappingURL=FreezeControl.css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FreezeControl.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
@@ -0,0 +1,48 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var styles = require('@salt-ds/styles');
5
+ var window = require('@salt-ds/window');
6
+ var core = require('@salt-ds/core');
7
+ var FreezeControl$1 = require('./FreezeControl.css.js');
8
+ var useFreezeControl = require('./useFreezeControl.js');
9
+ var cx = require('clsx');
10
+
11
+ const classBase = "FreezeControl";
12
+ const FreezeControl = ({
13
+ dataSource,
14
+ className,
15
+ ...htmlAttributes
16
+ }) => {
17
+ const targetWindow = window.useWindow();
18
+ styles.useComponentCssInjection({
19
+ testId: "vuu-freeze-control",
20
+ css: FreezeControl$1,
21
+ window: targetWindow
22
+ });
23
+ const { label, isFrozen, lastUpdateMessage, newRecordCount, onSwitchChange } = useFreezeControl.useFreezeControl({ dataSource });
24
+ return /* @__PURE__ */ jsxRuntime.jsx(core.Badge, { value: newRecordCount, max: 99, children: /* @__PURE__ */ jsxRuntime.jsxs(
25
+ "div",
26
+ {
27
+ ...htmlAttributes,
28
+ className: cx(classBase, className, {
29
+ [`${classBase}-showBadge`]: newRecordCount > 0
30
+ }),
31
+ children: [
32
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${classBase}-label`, children: label }),
33
+ /* @__PURE__ */ jsxRuntime.jsx(
34
+ core.Switch,
35
+ {
36
+ checked: isFrozen,
37
+ onChange: onSwitchChange,
38
+ className: "vuuLarge"
39
+ }
40
+ ),
41
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${classBase}-lastUpdated`, children: lastUpdateMessage })
42
+ ]
43
+ }
44
+ ) });
45
+ };
46
+
47
+ exports.FreezeControl = FreezeControl;
48
+ //# sourceMappingURL=FreezeControl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FreezeControl.js","sources":["../../src/freeze-control/FreezeControl.tsx"],"sourcesContent":["import { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { Badge, Switch } from \"@salt-ds/core\";\nimport freezeControlCss from \"./FreezeControl.css\";\nimport { useFreezeControl, type FreezeProps } from \"./useFreezeControl\";\nimport { HTMLAttributes } from \"react\";\nimport cx from \"clsx\";\n\nconst classBase = \"FreezeControl\";\n\nexport interface FreezeControlProps\n extends HTMLAttributes<HTMLDivElement>,\n FreezeProps {}\n\nexport const FreezeControl = ({\n dataSource,\n className,\n ...htmlAttributes\n}: FreezeControlProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-freeze-control\",\n css: freezeControlCss,\n window: targetWindow,\n });\n\n const { label, isFrozen, lastUpdateMessage, newRecordCount, onSwitchChange } =\n useFreezeControl({ dataSource });\n\n return (\n <Badge value={newRecordCount} max={99}>\n <div\n {...htmlAttributes}\n className={cx(classBase, className, {\n [`${classBase}-showBadge`]: newRecordCount > 0,\n })}\n >\n <span className={`${classBase}-label`}>{label}</span>\n <Switch\n checked={isFrozen}\n onChange={onSwitchChange}\n className=\"vuuLarge\"\n />\n <span className={`${classBase}-lastUpdated`}>{lastUpdateMessage}</span>\n </div>\n </Badge>\n );\n};\n"],"names":["useWindow","useComponentCssInjection","freezeControlCss","useFreezeControl","jsx","Badge","jsxs","Switch"],"mappings":";;;;;;;;;;AAQA,MAAM,SAAY,GAAA,eAAA;AAMX,MAAM,gBAAgB,CAAC;AAAA,EAC5B,UAAA;AAAA,EACA,SAAA;AAAA,EACA,GAAG;AACL,CAA0B,KAAA;AACxB,EAAA,MAAM,eAAeA,gBAAU,EAAA;AAC/B,EAAyBC,+BAAA,CAAA;AAAA,IACvB,MAAQ,EAAA,oBAAA;AAAA,IACR,GAAK,EAAAC,eAAA;AAAA,IACL,MAAQ,EAAA;AAAA,GACT,CAAA;AAED,EAAM,MAAA,EAAE,KAAO,EAAA,QAAA,EAAU,iBAAmB,EAAA,cAAA,EAAgB,gBAC1D,GAAAC,iCAAA,CAAiB,EAAE,UAAA,EAAY,CAAA;AAEjC,EAAA,uBACGC,cAAA,CAAAC,UAAA,EAAA,EAAM,KAAO,EAAA,cAAA,EAAgB,KAAK,EACjC,EAAA,QAAA,kBAAAC,eAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACE,GAAG,cAAA;AAAA,MACJ,SAAA,EAAW,EAAG,CAAA,SAAA,EAAW,SAAW,EAAA;AAAA,QAClC,CAAC,CAAA,EAAG,SAAS,CAAA,UAAA,CAAY,GAAG,cAAiB,GAAA;AAAA,OAC9C,CAAA;AAAA,MAED,QAAA,EAAA;AAAA,wBAAAF,cAAA,CAAC,MAAK,EAAA,EAAA,SAAA,EAAW,CAAG,EAAA,SAAS,UAAW,QAAM,EAAA,KAAA,EAAA,CAAA;AAAA,wBAC9CA,cAAA;AAAA,UAACG,WAAA;AAAA,UAAA;AAAA,YACC,OAAS,EAAA,QAAA;AAAA,YACT,QAAU,EAAA,cAAA;AAAA,YACV,SAAU,EAAA;AAAA;AAAA,SACZ;AAAA,uCACC,MAAK,EAAA,EAAA,SAAA,EAAW,CAAG,EAAA,SAAS,gBAAiB,QAAkB,EAAA,iBAAA,EAAA;AAAA;AAAA;AAAA,GAEpE,EAAA,CAAA;AAEJ;;;;"}
@@ -0,0 +1,73 @@
1
+ 'use strict';
2
+
3
+ var vuuUtils = require('@vuu-ui/vuu-utils');
4
+ var react = require('react');
5
+
6
+ const timeFormatter = vuuUtils.formatDate({ time: "hh:mm:ss" });
7
+ const formatFreezeTime = (ts) => {
8
+ if (ts === void 0) {
9
+ throw Error("[useFreezeControl] formatFreezeTime, freezeTime undefined");
10
+ }
11
+ return timeFormatter(new Date(ts));
12
+ };
13
+ const FreezeState = (dataSource, newRecordCount) => ({
14
+ isFrozen: dataSource.isFrozen ?? false,
15
+ label: dataSource.isFrozen ? "View Frozen" : "Freeze View",
16
+ lastUpdateMessage: dataSource.isFrozen ? `at ${formatFreezeTime(dataSource.freezeTimestamp)}` : "",
17
+ newRecordCount
18
+ });
19
+ const useFreezeControl = ({ dataSource }) => {
20
+ const { VuuDataSource } = vuuUtils.useData();
21
+ const table = react.useMemo(() => {
22
+ if (dataSource.table === void 0) {
23
+ throw Error(`[useFreezeControls] dataSource must have VuuTable`);
24
+ }
25
+ return dataSource.table;
26
+ }, [dataSource]);
27
+ const [freezeState, setFreezeState] = react.useState(
28
+ FreezeState(dataSource, 0)
29
+ );
30
+ const [startTrackingNewRows, stopTrackingNewRows] = react.useMemo(() => {
31
+ let ds = void 0;
32
+ const dataCallback = (message) => {
33
+ if (vuuUtils.messageHasSize(message)) {
34
+ setFreezeState(FreezeState(dataSource, message.size));
35
+ }
36
+ };
37
+ const start = (ts) => {
38
+ ds = new VuuDataSource({ table });
39
+ ds.subscribe(
40
+ {
41
+ filterSpec: {
42
+ filter: `created > ${ts}`
43
+ }
44
+ },
45
+ dataCallback
46
+ );
47
+ };
48
+ const stop = () => {
49
+ ds?.unsubscribe();
50
+ };
51
+ return [start, stop];
52
+ }, [VuuDataSource, dataSource, table]);
53
+ const handleSwitchChange = react.useCallback(
54
+ (evt) => {
55
+ if (evt.target.checked) {
56
+ dataSource.freeze?.();
57
+ startTrackingNewRows(dataSource.freezeTimestamp);
58
+ } else {
59
+ dataSource.unfreeze?.();
60
+ stopTrackingNewRows();
61
+ }
62
+ setFreezeState(FreezeState(dataSource, 0));
63
+ },
64
+ [dataSource, startTrackingNewRows, stopTrackingNewRows]
65
+ );
66
+ return {
67
+ ...freezeState,
68
+ onSwitchChange: handleSwitchChange
69
+ };
70
+ };
71
+
72
+ exports.useFreezeControl = useFreezeControl;
73
+ //# sourceMappingURL=useFreezeControl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useFreezeControl.js","sources":["../../src/freeze-control/useFreezeControl.ts"],"sourcesContent":["import {\n DataSource,\n DataSourceSubscribeCallback,\n} from \"@vuu-ui/vuu-data-types\";\nimport { VuuTable } from \"@vuu-ui/vuu-protocol-types\";\nimport { formatDate, messageHasSize, useData } from \"@vuu-ui/vuu-utils\";\nimport { ChangeEventHandler, useCallback, useMemo, useState } from \"react\";\n\nexport interface FreezeProps {\n dataSource: DataSource;\n}\n\ntype FreezeState = {\n isFrozen: boolean;\n label: string;\n lastUpdateMessage: string;\n newRecordCount: number;\n};\n\nconst timeFormatter = formatDate({ time: \"hh:mm:ss\" });\n\nconst formatFreezeTime = (ts?: number) => {\n if (ts === undefined) {\n throw Error(\"[useFreezeControl] formatFreezeTime, freezeTime undefined\");\n }\n return timeFormatter(new Date(ts));\n};\n\nconst FreezeState = (\n dataSource: DataSource,\n newRecordCount: number,\n): FreezeState => ({\n isFrozen: dataSource.isFrozen ?? false,\n label: dataSource.isFrozen ? \"View Frozen\" : \"Freeze View\",\n lastUpdateMessage: dataSource.isFrozen\n ? `at ${formatFreezeTime(dataSource.freezeTimestamp)}`\n : \"\",\n newRecordCount,\n});\n\nexport const useFreezeControl = ({ dataSource }: FreezeProps) => {\n const { VuuDataSource } = useData();\n const table = useMemo<VuuTable>(() => {\n if (dataSource.table === undefined) {\n throw Error(`[useFreezeControls] dataSource must have VuuTable`);\n }\n return dataSource.table;\n }, [dataSource]);\n const [freezeState, setFreezeState] = useState<FreezeState>(\n FreezeState(dataSource, 0),\n );\n\n const [startTrackingNewRows, stopTrackingNewRows] = useMemo(() => {\n let ds: DataSource | undefined = undefined;\n\n const dataCallback: DataSourceSubscribeCallback = (message) => {\n if (messageHasSize(message)) {\n setFreezeState(FreezeState(dataSource, message.size));\n }\n };\n\n const start = (ts: number) => {\n ds = new VuuDataSource({ table });\n ds.subscribe(\n {\n filterSpec: {\n filter: `created > ${ts}`,\n },\n },\n dataCallback,\n );\n };\n\n const stop = () => {\n ds?.unsubscribe();\n };\n\n return [start, stop];\n }, [VuuDataSource, dataSource, table]);\n\n const handleSwitchChange = useCallback<ChangeEventHandler<HTMLInputElement>>(\n (evt) => {\n if (evt.target.checked) {\n dataSource.freeze?.();\n startTrackingNewRows(dataSource.freezeTimestamp as number);\n } else {\n dataSource.unfreeze?.();\n stopTrackingNewRows();\n }\n setFreezeState(FreezeState(dataSource, 0));\n },\n [dataSource, startTrackingNewRows, stopTrackingNewRows],\n );\n\n return {\n ...freezeState,\n onSwitchChange: handleSwitchChange,\n };\n};\n"],"names":["formatDate","useData","useMemo","useState","messageHasSize","useCallback"],"mappings":"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"}
package/cjs/index.js CHANGED
@@ -28,6 +28,7 @@ var BaseNumericFormattingSettings = require('./column-formatting-settings/BaseNu
28
28
  var DateTimeFormattingSettings = require('./column-formatting-settings/DateTimeFormattingSettings.js');
29
29
  var DatasourceStats = require('./datasource-stats/DatasourceStats.js');
30
30
  var TableProvider = require('./table-provider/TableProvider.js');
31
+ var FreezeControl = require('./freeze-control/FreezeControl.js');
31
32
 
32
33
 
33
34
 
@@ -65,4 +66,5 @@ exports.DateTimeFormattingSettings = DateTimeFormattingSettings.DateTimeFormatti
65
66
  exports.DataSourceStats = DatasourceStats.DataSourceStats;
66
67
  exports.TableProvider = TableProvider.TableProvider;
67
68
  exports.useTableContext = TableProvider.useTableContext;
69
+ exports.FreezeControl = FreezeControl.FreezeControl;
68
70
  //# sourceMappingURL=index.js.map
package/cjs/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -3,12 +3,12 @@ import { Menu, MenuTrigger, MenuPanel } from '@salt-ds/core';
3
3
  import { useComponentCssInjection } from '@salt-ds/styles';
4
4
  import { useWindow } from '@salt-ds/window';
5
5
  import { IconButton } from '@vuu-ui/vuu-ui-controls';
6
- import { useTableContext } from '../table-provider/TableProvider.js';
7
6
  import cx from 'clsx';
8
7
  import { useCallback } from 'react';
9
- import columnMenuCss from './ColumnMenu.css.js';
10
- import { getColumnMenuActionType, buildSortMenu, buildGroupMenu, buildAggregationMenuItems, buildVisibilityMenuItems, buildPinMenuItems, buildSettingsMenuItems } from './column-menu-utils.js';
11
8
  import { defaultTableSettingsPermissions } from '../table-column-settings/TableSettingsPanel.js';
9
+ import { useTableContext } from '../table-provider/TableProvider.js';
10
+ import { getColumnMenuActionType, buildSortMenu, buildGroupMenu, buildAggregationMenuItems, buildVisibilityMenuItems, buildPinMenuItems, buildSettingsMenuItems } from './column-menu-utils.js';
11
+ import columnMenuCss from './ColumnMenu.css.js';
12
12
 
13
13
  const classBase = "vuuColumnMenu";
14
14
  const defaultColumnMenuPermissions = {
@@ -1 +1 @@
1
- {"version":3,"file":"ColumnMenu.js","sources":["../../src/column-menu/ColumnMenu.tsx"],"sourcesContent":["import { Menu, MenuPanel, MenuTrigger } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport {\n ColumnDescriptor,\n ColumnMenuPermissions,\n} from \"@vuu-ui/vuu-table-types\";\nimport { IconButton } from \"@vuu-ui/vuu-ui-controls\";\nimport { useTableContext } from \"../table-provider/TableProvider\";\nimport cx from \"clsx\";\nimport { HTMLAttributes, MouseEventHandler, useCallback } from \"react\";\n\nimport columnMenuCss from \"./ColumnMenu.css\";\nimport {\n buildAggregationMenuItems,\n buildPinMenuItems,\n buildGroupMenu,\n buildSortMenu,\n buildVisibilityMenuItems,\n ColumnMenuActionType,\n getColumnMenuActionType,\n type MenuItemClickHandler,\n buildSettingsMenuItems,\n} from \"./column-menu-utils\";\nimport { MenuActionHandler } from \"@vuu-ui/vuu-context-menu\";\nimport { defaultTableSettingsPermissions } from \"../table-column-settings/TableSettingsPanel\";\n\nconst classBase = \"vuuColumnMenu\";\n\nconst defaultColumnMenuPermissions: Readonly<ColumnMenuPermissions> = {\n allowSort: true,\n allowGroup: true,\n allowAggregation: true,\n allowHide: true,\n allowPin: true,\n allowColumnSettings: true,\n allowTableSettings: defaultTableSettingsPermissions,\n};\n\nexport interface ColumnMenuProps extends HTMLAttributes<HTMLSpanElement> {\n column: ColumnDescriptor;\n menuActionHandler?: MenuActionHandler<ColumnMenuActionType, ColumnDescriptor>;\n menuPermissions?: ColumnMenuPermissions;\n}\n\nexport const ColumnMenu = ({\n className,\n column,\n menuActionHandler: menuActionHandlerProp,\n menuPermissions: {\n allowSort,\n allowGroup,\n allowAggregation,\n allowHide,\n allowPin,\n allowColumnSettings,\n allowTableSettings,\n } = defaultColumnMenuPermissions,\n}: ColumnMenuProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-column-menu\",\n css: columnMenuCss,\n window: targetWindow,\n });\n\n const { dataSource, menuActionHandler } = useTableContext(true);\n\n const menuActionClickHandler = useCallback<MenuItemClickHandler>(\n (evt) => {\n const columnMenuActionType = getColumnMenuActionType(evt.target);\n if (menuActionHandlerProp?.(columnMenuActionType, column) !== true) {\n return menuActionHandler(columnMenuActionType, column);\n }\n },\n [column, menuActionHandler, menuActionHandlerProp],\n );\n\n const sortMenu = buildSortMenu(\n column,\n dataSource,\n menuActionClickHandler,\n allowSort,\n );\n const groupMenu = buildGroupMenu(\n column,\n dataSource,\n menuActionClickHandler,\n allowGroup,\n );\n const aggregationMenu = buildAggregationMenuItems(\n column,\n dataSource,\n menuActionClickHandler,\n allowAggregation,\n );\n const visibilityMenuItems = buildVisibilityMenuItems(\n column,\n menuActionClickHandler,\n allowHide,\n );\n const pinMenu = buildPinMenuItems(column, menuActionClickHandler, allowPin);\n const settingsMenuItems = buildSettingsMenuItems(\n column,\n menuActionClickHandler,\n allowColumnSettings,\n allowTableSettings,\n );\n\n const handleClick = useCallback<MouseEventHandler<HTMLButtonElement>>(\n (evt) => {\n // Prevent sort from triggering if the click were to bubble.\n evt.stopPropagation();\n },\n [],\n );\n\n return (\n <Menu>\n <MenuTrigger>\n <IconButton\n appearance=\"transparent\"\n className={cx(classBase, className)}\n data-embedded\n icon=\"more-vert\"\n sentiment=\"neutral\"\n aria-label=\"Open Column Menu\"\n onClick={handleClick}\n />\n </MenuTrigger>\n <MenuPanel>\n {sortMenu}\n {groupMenu}\n {aggregationMenu}\n {visibilityMenuItems}\n {pinMenu}\n {settingsMenuItems}\n </MenuPanel>\n </Menu>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ColumnMenu.js","sources":["../../src/column-menu/ColumnMenu.tsx"],"sourcesContent":["import { Menu, MenuPanel, MenuTrigger } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { MenuActionHandler } from \"@vuu-ui/vuu-context-menu\";\nimport {\n ColumnDescriptor,\n ColumnMenuPermissions,\n} from \"@vuu-ui/vuu-table-types\";\nimport { IconButton } from \"@vuu-ui/vuu-ui-controls\";\nimport cx from \"clsx\";\nimport { HTMLAttributes, MouseEventHandler, useCallback } from \"react\";\nimport { defaultTableSettingsPermissions } from \"../table-column-settings/TableSettingsPanel\";\nimport { useTableContext } from \"../table-provider/TableProvider\";\nimport {\n buildAggregationMenuItems,\n buildGroupMenu,\n buildPinMenuItems,\n buildSettingsMenuItems,\n buildSortMenu,\n buildVisibilityMenuItems,\n ColumnMenuActionType,\n getColumnMenuActionType,\n type MenuItemClickHandler,\n} from \"./column-menu-utils\";\n\nimport columnMenuCss from \"./ColumnMenu.css\";\n\nconst classBase = \"vuuColumnMenu\";\n\nconst defaultColumnMenuPermissions: Readonly<ColumnMenuPermissions> = {\n allowSort: true,\n allowGroup: true,\n allowAggregation: true,\n allowHide: true,\n allowPin: true,\n allowColumnSettings: true,\n allowTableSettings: defaultTableSettingsPermissions,\n};\n\nexport interface ColumnMenuProps extends HTMLAttributes<HTMLSpanElement> {\n column: ColumnDescriptor;\n menuActionHandler?: MenuActionHandler<ColumnMenuActionType, ColumnDescriptor>;\n menuPermissions?: ColumnMenuPermissions;\n}\n\nexport const ColumnMenu = ({\n className,\n column,\n menuActionHandler: menuActionHandlerProp,\n menuPermissions: {\n allowSort,\n allowGroup,\n allowAggregation,\n allowHide,\n allowPin,\n allowColumnSettings,\n allowTableSettings,\n } = defaultColumnMenuPermissions,\n}: ColumnMenuProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-column-menu\",\n css: columnMenuCss,\n window: targetWindow,\n });\n\n const { dataSource, menuActionHandler } = useTableContext(true);\n\n const menuActionClickHandler = useCallback<MenuItemClickHandler>(\n (evt) => {\n const columnMenuActionType = getColumnMenuActionType(evt.target);\n if (menuActionHandlerProp?.(columnMenuActionType, column) !== true) {\n return menuActionHandler(columnMenuActionType, column);\n }\n },\n [column, menuActionHandler, menuActionHandlerProp],\n );\n\n const sortMenu = buildSortMenu(\n column,\n dataSource,\n menuActionClickHandler,\n allowSort,\n );\n const groupMenu = buildGroupMenu(\n column,\n dataSource,\n menuActionClickHandler,\n allowGroup,\n );\n const aggregationMenu = buildAggregationMenuItems(\n column,\n dataSource,\n menuActionClickHandler,\n allowAggregation,\n );\n const visibilityMenuItems = buildVisibilityMenuItems(\n column,\n menuActionClickHandler,\n allowHide,\n );\n const pinMenu = buildPinMenuItems(column, menuActionClickHandler, allowPin);\n const settingsMenuItems = buildSettingsMenuItems(\n column,\n menuActionClickHandler,\n allowColumnSettings,\n allowTableSettings,\n );\n\n const handleClick = useCallback<MouseEventHandler<HTMLButtonElement>>(\n (evt) => {\n // Prevent sort from triggering if the click were to bubble.\n evt.stopPropagation();\n },\n [],\n );\n\n return (\n <Menu>\n <MenuTrigger>\n <IconButton\n appearance=\"transparent\"\n className={cx(classBase, className)}\n data-embedded\n icon=\"more-vert\"\n sentiment=\"neutral\"\n aria-label=\"Open Column Menu\"\n onClick={handleClick}\n />\n </MenuTrigger>\n <MenuPanel>\n {sortMenu}\n {groupMenu}\n {aggregationMenu}\n {visibilityMenuItems}\n {pinMenu}\n {settingsMenuItems}\n </MenuPanel>\n </Menu>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -2,11 +2,20 @@ import { jsx, jsxs } from 'react/jsx-runtime';
2
2
  import cx from 'clsx';
3
3
  import { useComponentCssInjection } from '@salt-ds/styles';
4
4
  import { useWindow } from '@salt-ds/window';
5
- import { useState, useEffect } from 'react';
5
+ import { useState, useCallback, useEffect } from 'react';
6
6
  import dataSourceStats from './DatasourceStats.css.js';
7
+ import { formatDate } from '@vuu-ui/vuu-utils';
7
8
 
8
9
  const classBase = "vuuDatasourceStats";
9
10
  const numberFormatter = new Intl.NumberFormat();
11
+ const timeFormatter = formatDate({ time: "hh:mm:ss" });
12
+ const formatTime = (ts) => {
13
+ if (typeof ts === "number") {
14
+ return timeFormatter(new Date(ts));
15
+ } else {
16
+ return void 0;
17
+ }
18
+ };
10
19
  const DataSourceStats = ({
11
20
  className: classNameProp,
12
21
  dataSource
@@ -19,19 +28,35 @@ const DataSourceStats = ({
19
28
  });
20
29
  const [range, setRange] = useState(dataSource.range);
21
30
  const [size, setSize] = useState(dataSource.size);
31
+ const [freezeTime, setFreezeTime] = useState(
32
+ formatTime(dataSource.freezeTimestamp)
33
+ );
34
+ const handleFreeze = useCallback(
35
+ (isFrozen, freezeTimestamp) => {
36
+ console.log(`DatasourceStats isFrozen ${isFrozen}`);
37
+ if (isFrozen) {
38
+ setFreezeTime(formatTime(freezeTimestamp));
39
+ } else {
40
+ setFreezeTime(void 0);
41
+ }
42
+ },
43
+ []
44
+ );
22
45
  useEffect(() => {
23
46
  setSize(dataSource.size);
24
47
  dataSource.on("resize", setSize);
25
48
  dataSource.on("range", setRange);
49
+ dataSource.on("freeze", handleFreeze);
26
50
  return () => {
27
51
  dataSource.removeListener("resize", setSize);
28
52
  dataSource.removeListener("range", setRange);
29
53
  };
30
- }, [dataSource]);
54
+ }, [dataSource, handleFreeze]);
31
55
  const className = cx(classBase, classNameProp);
32
56
  const from = numberFormatter.format(range.firstRowInViewport);
33
57
  const to = numberFormatter.format(range.lastRowInViewport);
34
58
  const value = numberFormatter.format(size);
59
+ console.log(`range = ${JSON.stringify(range)}`);
35
60
  if (size === 0) {
36
61
  return /* @__PURE__ */ jsx("div", { className, children: /* @__PURE__ */ jsx("span", { className: `${classBase}-label`, children: "No Rows to display" }) });
37
62
  } else {
@@ -41,7 +66,14 @@ const DataSourceStats = ({
41
66
  /* @__PURE__ */ jsx("span", { children: "-" }),
42
67
  /* @__PURE__ */ jsx("span", { className: `${classBase}-range`, children: to }),
43
68
  /* @__PURE__ */ jsx("span", { children: "of" }),
44
- /* @__PURE__ */ jsx("span", { className: `${classBase}-size`, children: value })
69
+ /* @__PURE__ */ jsx("span", { className: `${classBase}-size`, children: value }),
70
+ freezeTime !== void 0 ? /* @__PURE__ */ jsx(
71
+ "span",
72
+ {
73
+ className: `${classBase}-label`,
74
+ children: `(frozen at ${freezeTime})`
75
+ }
76
+ ) : null
45
77
  ] });
46
78
  }
47
79
  };
@@ -1 +1 @@
1
- {"version":3,"file":"DatasourceStats.js","sources":["../../src/datasource-stats/DatasourceStats.tsx"],"sourcesContent":["import { DataSource } from \"@vuu-ui/vuu-data-types\";\nimport cx from \"clsx\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { HTMLAttributes, useEffect, useState } from \"react\";\n\nimport dataSourceStats from \"./DatasourceStats.css\";\nimport { Range } from \"@vuu-ui/vuu-utils\";\n\ninterface DataSourceStatsProps extends HTMLAttributes<HTMLSpanElement> {\n dataSource: DataSource;\n}\n\nconst classBase = \"vuuDatasourceStats\";\n\nconst numberFormatter = new Intl.NumberFormat();\n\nexport const DataSourceStats = ({\n className: classNameProp,\n dataSource,\n}: DataSourceStatsProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-datasource-stats\",\n css: dataSourceStats,\n window: targetWindow,\n });\n\n const [range, setRange] = useState<Range>(dataSource.range);\n const [size, setSize] = useState(dataSource.size);\n useEffect(() => {\n setSize(dataSource.size);\n dataSource.on(\"resize\", setSize);\n dataSource.on(\"range\", setRange);\n return () => {\n dataSource.removeListener(\"resize\", setSize);\n dataSource.removeListener(\"range\", setRange);\n };\n }, [dataSource]);\n\n const className = cx(classBase, classNameProp);\n const from = numberFormatter.format(range.firstRowInViewport);\n const to = numberFormatter.format(range.lastRowInViewport);\n const value = numberFormatter.format(size);\n if (size === 0) {\n return (\n <div className={className}>\n <span className={`${classBase}-label`}>No Rows to display</span>\n </div>\n );\n } else {\n return (\n <div className={className}>\n <span className={`${classBase}-label`}>Rows</span>\n <span className={`${classBase}-range`}>{from}</span>\n <span>-</span>\n <span className={`${classBase}-range`}>{to}</span>\n <span>of</span>\n <span className={`${classBase}-size`}>{value}</span>\n </div>\n );\n }\n};\n"],"names":[],"mappings":";;;;;;;AAaA,MAAM,SAAY,GAAA,oBAAA;AAElB,MAAM,eAAA,GAAkB,IAAI,IAAA,CAAK,YAAa,EAAA;AAEvC,MAAM,kBAAkB,CAAC;AAAA,EAC9B,SAAW,EAAA,aAAA;AAAA,EACX;AACF,CAA4B,KAAA;AAC1B,EAAA,MAAM,eAAe,SAAU,EAAA;AAC/B,EAAyB,wBAAA,CAAA;AAAA,IACvB,MAAQ,EAAA,sBAAA;AAAA,IACR,GAAK,EAAA,eAAA;AAAA,IACL,MAAQ,EAAA;AAAA,GACT,CAAA;AAED,EAAA,MAAM,CAAC,KAAO,EAAA,QAAQ,CAAI,GAAA,QAAA,CAAgB,WAAW,KAAK,CAAA;AAC1D,EAAA,MAAM,CAAC,IAAM,EAAA,OAAO,CAAI,GAAA,QAAA,CAAS,WAAW,IAAI,CAAA;AAChD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,OAAA,CAAQ,WAAW,IAAI,CAAA;AACvB,IAAW,UAAA,CAAA,EAAA,CAAG,UAAU,OAAO,CAAA;AAC/B,IAAW,UAAA,CAAA,EAAA,CAAG,SAAS,QAAQ,CAAA;AAC/B,IAAA,OAAO,MAAM;AACX,MAAW,UAAA,CAAA,cAAA,CAAe,UAAU,OAAO,CAAA;AAC3C,MAAW,UAAA,CAAA,cAAA,CAAe,SAAS,QAAQ,CAAA;AAAA,KAC7C;AAAA,GACF,EAAG,CAAC,UAAU,CAAC,CAAA;AAEf,EAAM,MAAA,SAAA,GAAY,EAAG,CAAA,SAAA,EAAW,aAAa,CAAA;AAC7C,EAAA,MAAM,IAAO,GAAA,eAAA,CAAgB,MAAO,CAAA,KAAA,CAAM,kBAAkB,CAAA;AAC5D,EAAA,MAAM,EAAK,GAAA,eAAA,CAAgB,MAAO,CAAA,KAAA,CAAM,iBAAiB,CAAA;AACzD,EAAM,MAAA,KAAA,GAAQ,eAAgB,CAAA,MAAA,CAAO,IAAI,CAAA;AACzC,EAAA,IAAI,SAAS,CAAG,EAAA;AACd,IACE,uBAAA,GAAA,CAAC,KAAI,EAAA,EAAA,SAAA,EACH,QAAC,kBAAA,GAAA,CAAA,MAAA,EAAA,EAAK,WAAW,CAAG,EAAA,SAAS,CAAU,MAAA,CAAA,EAAA,QAAA,EAAA,oBAAA,EAAkB,CAC3D,EAAA,CAAA;AAAA,GAEG,MAAA;AACL,IACE,uBAAA,IAAA,CAAC,SAAI,SACH,EAAA,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,MAAK,EAAA,EAAA,SAAA,EAAW,CAAG,EAAA,SAAS,UAAU,QAAI,EAAA,MAAA,EAAA,CAAA;AAAA,0BAC1C,MAAK,EAAA,EAAA,SAAA,EAAW,CAAG,EAAA,SAAS,UAAW,QAAK,EAAA,IAAA,EAAA,CAAA;AAAA,sBAC7C,GAAA,CAAC,UAAK,QAAC,EAAA,GAAA,EAAA,CAAA;AAAA,0BACN,MAAK,EAAA,EAAA,SAAA,EAAW,CAAG,EAAA,SAAS,UAAW,QAAG,EAAA,EAAA,EAAA,CAAA;AAAA,sBAC3C,GAAA,CAAC,UAAK,QAAE,EAAA,IAAA,EAAA,CAAA;AAAA,0BACP,MAAK,EAAA,EAAA,SAAA,EAAW,CAAG,EAAA,SAAS,SAAU,QAAM,EAAA,KAAA,EAAA;AAAA,KAC/C,EAAA,CAAA;AAAA;AAGN;;;;"}
1
+ {"version":3,"file":"DatasourceStats.js","sources":["../../src/datasource-stats/DatasourceStats.tsx"],"sourcesContent":["import { DataSource } from \"@vuu-ui/vuu-data-types\";\nimport cx from \"clsx\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { HTMLAttributes, useCallback, useEffect, useState } from \"react\";\n\nimport dataSourceStats from \"./DatasourceStats.css\";\nimport { formatDate, Range } from \"@vuu-ui/vuu-utils\";\n\ninterface DataSourceStatsProps extends HTMLAttributes<HTMLSpanElement> {\n dataSource: DataSource;\n}\n\nconst classBase = \"vuuDatasourceStats\";\n\nconst numberFormatter = new Intl.NumberFormat();\nconst timeFormatter = formatDate({ time: \"hh:mm:ss\" });\n\nconst formatTime = (ts: number | undefined) => {\n if (typeof ts === \"number\") {\n return timeFormatter(new Date(ts));\n } else {\n return undefined;\n }\n};\n\nexport const DataSourceStats = ({\n className: classNameProp,\n dataSource,\n}: DataSourceStatsProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-datasource-stats\",\n css: dataSourceStats,\n window: targetWindow,\n });\n\n const [range, setRange] = useState<Range>(dataSource.range);\n const [size, setSize] = useState(dataSource.size);\n const [freezeTime, setFreezeTime] = useState(\n formatTime(dataSource.freezeTimestamp),\n );\n\n const handleFreeze = useCallback(\n (isFrozen: boolean, freezeTimestamp: number) => {\n console.log(`DatasourceStats isFrozen ${isFrozen}`);\n if (isFrozen) {\n setFreezeTime(formatTime(freezeTimestamp));\n } else {\n setFreezeTime(undefined);\n }\n },\n [],\n );\n\n useEffect(() => {\n setSize(dataSource.size);\n dataSource.on(\"resize\", setSize);\n dataSource.on(\"range\", setRange);\n dataSource.on(\"freeze\", handleFreeze);\n return () => {\n dataSource.removeListener(\"resize\", setSize);\n dataSource.removeListener(\"range\", setRange);\n };\n }, [dataSource, handleFreeze]);\n\n const className = cx(classBase, classNameProp);\n const from = numberFormatter.format(range.firstRowInViewport);\n const to = numberFormatter.format(range.lastRowInViewport);\n const value = numberFormatter.format(size);\n\n console.log(`range = ${JSON.stringify(range)}`);\n\n if (size === 0) {\n return (\n <div className={className}>\n <span className={`${classBase}-label`}>No Rows to display</span>\n </div>\n );\n } else {\n return (\n <div className={className}>\n <span className={`${classBase}-label`}>Rows</span>\n <span className={`${classBase}-range`}>{from}</span>\n <span>-</span>\n <span className={`${classBase}-range`}>{to}</span>\n <span>of</span>\n <span className={`${classBase}-size`}>{value}</span>\n {freezeTime !== undefined ? (\n <span\n className={`${classBase}-label`}\n >{`(frozen at ${freezeTime})`}</span>\n ) : null}\n </div>\n );\n }\n};\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ var freezeControlCss = "\n\n.FreezeControl {\n align-items: center;\n background-color: var(--salt-container-secondary-background);\n border-radius: 6px;\n display: inline-grid;\n grid-template-columns: auto auto auto 1fr;\n grid-template-rows: var(--salt-size-base);\n column-gap: var(--salt-spacing-200);\n padding: 0 var(--salt-spacing-200);\n\n .saltSwitch {\n grid-area: 1/1/2/2;\n .saltSwitch-track {\n height: 24px;\n }\n }\n\n .FreezeControl-label {\n grid-area: 1/2/2/3;\n }\n\n .FreezeControl-lastUpdated {\n grid-area: 1/3/2/4;\n }\n\n & + .saltBadge-badge {\n cursor: default;\n display: none;\n }\n &.FreezeControl-showBadge + .saltBadge-badge {\n display: inline-block;\n }\n\n\n}\n\n";
2
+
3
+ export { freezeControlCss as default };
4
+ //# sourceMappingURL=FreezeControl.css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FreezeControl.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
@@ -0,0 +1,46 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { useComponentCssInjection } from '@salt-ds/styles';
3
+ import { useWindow } from '@salt-ds/window';
4
+ import { Badge, Switch } from '@salt-ds/core';
5
+ import freezeControlCss from './FreezeControl.css.js';
6
+ import { useFreezeControl } from './useFreezeControl.js';
7
+ import cx from 'clsx';
8
+
9
+ const classBase = "FreezeControl";
10
+ const FreezeControl = ({
11
+ dataSource,
12
+ className,
13
+ ...htmlAttributes
14
+ }) => {
15
+ const targetWindow = useWindow();
16
+ useComponentCssInjection({
17
+ testId: "vuu-freeze-control",
18
+ css: freezeControlCss,
19
+ window: targetWindow
20
+ });
21
+ const { label, isFrozen, lastUpdateMessage, newRecordCount, onSwitchChange } = useFreezeControl({ dataSource });
22
+ return /* @__PURE__ */ jsx(Badge, { value: newRecordCount, max: 99, children: /* @__PURE__ */ jsxs(
23
+ "div",
24
+ {
25
+ ...htmlAttributes,
26
+ className: cx(classBase, className, {
27
+ [`${classBase}-showBadge`]: newRecordCount > 0
28
+ }),
29
+ children: [
30
+ /* @__PURE__ */ jsx("span", { className: `${classBase}-label`, children: label }),
31
+ /* @__PURE__ */ jsx(
32
+ Switch,
33
+ {
34
+ checked: isFrozen,
35
+ onChange: onSwitchChange,
36
+ className: "vuuLarge"
37
+ }
38
+ ),
39
+ /* @__PURE__ */ jsx("span", { className: `${classBase}-lastUpdated`, children: lastUpdateMessage })
40
+ ]
41
+ }
42
+ ) });
43
+ };
44
+
45
+ export { FreezeControl };
46
+ //# sourceMappingURL=FreezeControl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FreezeControl.js","sources":["../../src/freeze-control/FreezeControl.tsx"],"sourcesContent":["import { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { Badge, Switch } from \"@salt-ds/core\";\nimport freezeControlCss from \"./FreezeControl.css\";\nimport { useFreezeControl, type FreezeProps } from \"./useFreezeControl\";\nimport { HTMLAttributes } from \"react\";\nimport cx from \"clsx\";\n\nconst classBase = \"FreezeControl\";\n\nexport interface FreezeControlProps\n extends HTMLAttributes<HTMLDivElement>,\n FreezeProps {}\n\nexport const FreezeControl = ({\n dataSource,\n className,\n ...htmlAttributes\n}: FreezeControlProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-freeze-control\",\n css: freezeControlCss,\n window: targetWindow,\n });\n\n const { label, isFrozen, lastUpdateMessage, newRecordCount, onSwitchChange } =\n useFreezeControl({ dataSource });\n\n return (\n <Badge value={newRecordCount} max={99}>\n <div\n {...htmlAttributes}\n className={cx(classBase, className, {\n [`${classBase}-showBadge`]: newRecordCount > 0,\n })}\n >\n <span className={`${classBase}-label`}>{label}</span>\n <Switch\n checked={isFrozen}\n onChange={onSwitchChange}\n className=\"vuuLarge\"\n />\n <span className={`${classBase}-lastUpdated`}>{lastUpdateMessage}</span>\n </div>\n </Badge>\n );\n};\n"],"names":[],"mappings":";;;;;;;;AAQA,MAAM,SAAY,GAAA,eAAA;AAMX,MAAM,gBAAgB,CAAC;AAAA,EAC5B,UAAA;AAAA,EACA,SAAA;AAAA,EACA,GAAG;AACL,CAA0B,KAAA;AACxB,EAAA,MAAM,eAAe,SAAU,EAAA;AAC/B,EAAyB,wBAAA,CAAA;AAAA,IACvB,MAAQ,EAAA,oBAAA;AAAA,IACR,GAAK,EAAA,gBAAA;AAAA,IACL,MAAQ,EAAA;AAAA,GACT,CAAA;AAED,EAAM,MAAA,EAAE,KAAO,EAAA,QAAA,EAAU,iBAAmB,EAAA,cAAA,EAAgB,gBAC1D,GAAA,gBAAA,CAAiB,EAAE,UAAA,EAAY,CAAA;AAEjC,EAAA,uBACG,GAAA,CAAA,KAAA,EAAA,EAAM,KAAO,EAAA,cAAA,EAAgB,KAAK,EACjC,EAAA,QAAA,kBAAA,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACE,GAAG,cAAA;AAAA,MACJ,SAAA,EAAW,EAAG,CAAA,SAAA,EAAW,SAAW,EAAA;AAAA,QAClC,CAAC,CAAA,EAAG,SAAS,CAAA,UAAA,CAAY,GAAG,cAAiB,GAAA;AAAA,OAC9C,CAAA;AAAA,MAED,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,MAAK,EAAA,EAAA,SAAA,EAAW,CAAG,EAAA,SAAS,UAAW,QAAM,EAAA,KAAA,EAAA,CAAA;AAAA,wBAC9C,GAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YACC,OAAS,EAAA,QAAA;AAAA,YACT,QAAU,EAAA,cAAA;AAAA,YACV,SAAU,EAAA;AAAA;AAAA,SACZ;AAAA,4BACC,MAAK,EAAA,EAAA,SAAA,EAAW,CAAG,EAAA,SAAS,gBAAiB,QAAkB,EAAA,iBAAA,EAAA;AAAA;AAAA;AAAA,GAEpE,EAAA,CAAA;AAEJ;;;;"}
@@ -0,0 +1,71 @@
1
+ import { formatDate, useData, messageHasSize } from '@vuu-ui/vuu-utils';
2
+ import { useMemo, useState, useCallback } from 'react';
3
+
4
+ const timeFormatter = formatDate({ time: "hh:mm:ss" });
5
+ const formatFreezeTime = (ts) => {
6
+ if (ts === void 0) {
7
+ throw Error("[useFreezeControl] formatFreezeTime, freezeTime undefined");
8
+ }
9
+ return timeFormatter(new Date(ts));
10
+ };
11
+ const FreezeState = (dataSource, newRecordCount) => ({
12
+ isFrozen: dataSource.isFrozen ?? false,
13
+ label: dataSource.isFrozen ? "View Frozen" : "Freeze View",
14
+ lastUpdateMessage: dataSource.isFrozen ? `at ${formatFreezeTime(dataSource.freezeTimestamp)}` : "",
15
+ newRecordCount
16
+ });
17
+ const useFreezeControl = ({ dataSource }) => {
18
+ const { VuuDataSource } = useData();
19
+ const table = useMemo(() => {
20
+ if (dataSource.table === void 0) {
21
+ throw Error(`[useFreezeControls] dataSource must have VuuTable`);
22
+ }
23
+ return dataSource.table;
24
+ }, [dataSource]);
25
+ const [freezeState, setFreezeState] = useState(
26
+ FreezeState(dataSource, 0)
27
+ );
28
+ const [startTrackingNewRows, stopTrackingNewRows] = useMemo(() => {
29
+ let ds = void 0;
30
+ const dataCallback = (message) => {
31
+ if (messageHasSize(message)) {
32
+ setFreezeState(FreezeState(dataSource, message.size));
33
+ }
34
+ };
35
+ const start = (ts) => {
36
+ ds = new VuuDataSource({ table });
37
+ ds.subscribe(
38
+ {
39
+ filterSpec: {
40
+ filter: `created > ${ts}`
41
+ }
42
+ },
43
+ dataCallback
44
+ );
45
+ };
46
+ const stop = () => {
47
+ ds?.unsubscribe();
48
+ };
49
+ return [start, stop];
50
+ }, [VuuDataSource, dataSource, table]);
51
+ const handleSwitchChange = useCallback(
52
+ (evt) => {
53
+ if (evt.target.checked) {
54
+ dataSource.freeze?.();
55
+ startTrackingNewRows(dataSource.freezeTimestamp);
56
+ } else {
57
+ dataSource.unfreeze?.();
58
+ stopTrackingNewRows();
59
+ }
60
+ setFreezeState(FreezeState(dataSource, 0));
61
+ },
62
+ [dataSource, startTrackingNewRows, stopTrackingNewRows]
63
+ );
64
+ return {
65
+ ...freezeState,
66
+ onSwitchChange: handleSwitchChange
67
+ };
68
+ };
69
+
70
+ export { useFreezeControl };
71
+ //# sourceMappingURL=useFreezeControl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useFreezeControl.js","sources":["../../src/freeze-control/useFreezeControl.ts"],"sourcesContent":["import {\n DataSource,\n DataSourceSubscribeCallback,\n} from \"@vuu-ui/vuu-data-types\";\nimport { VuuTable } from \"@vuu-ui/vuu-protocol-types\";\nimport { formatDate, messageHasSize, useData } from \"@vuu-ui/vuu-utils\";\nimport { ChangeEventHandler, useCallback, useMemo, useState } from \"react\";\n\nexport interface FreezeProps {\n dataSource: DataSource;\n}\n\ntype FreezeState = {\n isFrozen: boolean;\n label: string;\n lastUpdateMessage: string;\n newRecordCount: number;\n};\n\nconst timeFormatter = formatDate({ time: \"hh:mm:ss\" });\n\nconst formatFreezeTime = (ts?: number) => {\n if (ts === undefined) {\n throw Error(\"[useFreezeControl] formatFreezeTime, freezeTime undefined\");\n }\n return timeFormatter(new Date(ts));\n};\n\nconst FreezeState = (\n dataSource: DataSource,\n newRecordCount: number,\n): FreezeState => ({\n isFrozen: dataSource.isFrozen ?? false,\n label: dataSource.isFrozen ? \"View Frozen\" : \"Freeze View\",\n lastUpdateMessage: dataSource.isFrozen\n ? `at ${formatFreezeTime(dataSource.freezeTimestamp)}`\n : \"\",\n newRecordCount,\n});\n\nexport const useFreezeControl = ({ dataSource }: FreezeProps) => {\n const { VuuDataSource } = useData();\n const table = useMemo<VuuTable>(() => {\n if (dataSource.table === undefined) {\n throw Error(`[useFreezeControls] dataSource must have VuuTable`);\n }\n return dataSource.table;\n }, [dataSource]);\n const [freezeState, setFreezeState] = useState<FreezeState>(\n FreezeState(dataSource, 0),\n );\n\n const [startTrackingNewRows, stopTrackingNewRows] = useMemo(() => {\n let ds: DataSource | undefined = undefined;\n\n const dataCallback: DataSourceSubscribeCallback = (message) => {\n if (messageHasSize(message)) {\n setFreezeState(FreezeState(dataSource, message.size));\n }\n };\n\n const start = (ts: number) => {\n ds = new VuuDataSource({ table });\n ds.subscribe(\n {\n filterSpec: {\n filter: `created > ${ts}`,\n },\n },\n dataCallback,\n );\n };\n\n const stop = () => {\n ds?.unsubscribe();\n };\n\n return [start, stop];\n }, [VuuDataSource, dataSource, table]);\n\n const handleSwitchChange = useCallback<ChangeEventHandler<HTMLInputElement>>(\n (evt) => {\n if (evt.target.checked) {\n dataSource.freeze?.();\n startTrackingNewRows(dataSource.freezeTimestamp as number);\n } else {\n dataSource.unfreeze?.();\n stopTrackingNewRows();\n }\n setFreezeState(FreezeState(dataSource, 0));\n },\n [dataSource, startTrackingNewRows, stopTrackingNewRows],\n );\n\n return {\n ...freezeState,\n onSwitchChange: handleSwitchChange,\n };\n};\n"],"names":[],"mappings":";;;AAmBA,MAAM,aAAgB,GAAA,UAAA,CAAW,EAAE,IAAA,EAAM,YAAY,CAAA;AAErD,MAAM,gBAAA,GAAmB,CAAC,EAAgB,KAAA;AACxC,EAAA,IAAI,OAAO,KAAW,CAAA,EAAA;AACpB,IAAA,MAAM,MAAM,2DAA2D,CAAA;AAAA;AAEzE,EAAA,OAAO,aAAc,CAAA,IAAI,IAAK,CAAA,EAAE,CAAC,CAAA;AACnC,CAAA;AAEA,MAAM,WAAA,GAAc,CAClB,UAAA,EACA,cACiB,MAAA;AAAA,EACjB,QAAA,EAAU,WAAW,QAAY,IAAA,KAAA;AAAA,EACjC,KAAA,EAAO,UAAW,CAAA,QAAA,GAAW,aAAgB,GAAA,aAAA;AAAA,EAC7C,iBAAA,EAAmB,WAAW,QAC1B,GAAA,CAAA,GAAA,EAAM,iBAAiB,UAAW,CAAA,eAAe,CAAC,CAClD,CAAA,GAAA,EAAA;AAAA,EACJ;AACF,CAAA,CAAA;AAEO,MAAM,gBAAmB,GAAA,CAAC,EAAE,UAAA,EAA8B,KAAA;AAC/D,EAAM,MAAA,EAAE,aAAc,EAAA,GAAI,OAAQ,EAAA;AAClC,EAAM,MAAA,KAAA,GAAQ,QAAkB,MAAM;AACpC,IAAI,IAAA,UAAA,CAAW,UAAU,KAAW,CAAA,EAAA;AAClC,MAAA,MAAM,MAAM,CAAmD,iDAAA,CAAA,CAAA;AAAA;AAEjE,IAAA,OAAO,UAAW,CAAA,KAAA;AAAA,GACpB,EAAG,CAAC,UAAU,CAAC,CAAA;AACf,EAAM,MAAA,CAAC,WAAa,EAAA,cAAc,CAAI,GAAA,QAAA;AAAA,IACpC,WAAA,CAAY,YAAY,CAAC;AAAA,GAC3B;AAEA,EAAA,MAAM,CAAC,oBAAA,EAAsB,mBAAmB,CAAA,GAAI,QAAQ,MAAM;AAChE,IAAA,IAAI,EAA6B,GAAA,KAAA,CAAA;AAEjC,IAAM,MAAA,YAAA,GAA4C,CAAC,OAAY,KAAA;AAC7D,MAAI,IAAA,cAAA,CAAe,OAAO,CAAG,EAAA;AAC3B,QAAA,cAAA,CAAe,WAAY,CAAA,UAAA,EAAY,OAAQ,CAAA,IAAI,CAAC,CAAA;AAAA;AACtD,KACF;AAEA,IAAM,MAAA,KAAA,GAAQ,CAAC,EAAe,KAAA;AAC5B,MAAA,EAAA,GAAK,IAAI,aAAA,CAAc,EAAE,KAAA,EAAO,CAAA;AAChC,MAAG,EAAA,CAAA,SAAA;AAAA,QACD;AAAA,UACE,UAAY,EAAA;AAAA,YACV,MAAA,EAAQ,aAAa,EAAE,CAAA;AAAA;AACzB,SACF;AAAA,QACA;AAAA,OACF;AAAA,KACF;AAEA,IAAA,MAAM,OAAO,MAAM;AACjB,MAAA,EAAA,EAAI,WAAY,EAAA;AAAA,KAClB;AAEA,IAAO,OAAA,CAAC,OAAO,IAAI,CAAA;AAAA,GAClB,EAAA,CAAC,aAAe,EAAA,UAAA,EAAY,KAAK,CAAC,CAAA;AAErC,EAAA,MAAM,kBAAqB,GAAA,WAAA;AAAA,IACzB,CAAC,GAAQ,KAAA;AACP,MAAI,IAAA,GAAA,CAAI,OAAO,OAAS,EAAA;AACtB,QAAA,UAAA,CAAW,MAAS,IAAA;AACpB,QAAA,oBAAA,CAAqB,WAAW,eAAyB,CAAA;AAAA,OACpD,MAAA;AACL,QAAA,UAAA,CAAW,QAAW,IAAA;AACtB,QAAoB,mBAAA,EAAA;AAAA;AAEtB,MAAe,cAAA,CAAA,WAAA,CAAY,UAAY,EAAA,CAAC,CAAC,CAAA;AAAA,KAC3C;AAAA,IACA,CAAC,UAAY,EAAA,oBAAA,EAAsB,mBAAmB;AAAA,GACxD;AAEA,EAAO,OAAA;AAAA,IACL,GAAG,WAAA;AAAA,IACH,cAAgB,EAAA;AAAA,GAClB;AACF;;;;"}
package/esm/index.js CHANGED
@@ -26,4 +26,5 @@ export { BaseNumericFormattingSettings } from './column-formatting-settings/Base
26
26
  export { DateTimeFormattingSettings } from './column-formatting-settings/DateTimeFormattingSettings.js';
27
27
  export { DataSourceStats } from './datasource-stats/DatasourceStats.js';
28
28
  export { TableProvider, useTableContext } from './table-provider/TableProvider.js';
29
+ export { FreezeControl } from './freeze-control/FreezeControl.js';
29
30
  //# sourceMappingURL=index.js.map
package/esm/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/package.json CHANGED
@@ -1,20 +1,20 @@
1
1
  {
2
- "version": "0.13.13",
2
+ "version": "0.13.14",
3
3
  "author": "heswell",
4
4
  "license": "Apache-2.0",
5
5
  "devDependencies": {
6
- "@vuu-ui/vuu-filter-types": "0.13.13",
7
- "@vuu-ui/vuu-protocol-types": "0.13.13"
6
+ "@vuu-ui/vuu-filter-types": "0.13.14",
7
+ "@vuu-ui/vuu-protocol-types": "0.13.14"
8
8
  },
9
9
  "dependencies": {
10
- "@vuu-ui/vuu-codemirror": "0.13.13",
11
- "@vuu-ui/vuu-data-react": "0.13.13",
12
- "@vuu-ui/vuu-data-types": "0.13.13",
13
- "@vuu-ui/vuu-table-types": "0.13.13",
14
- "@vuu-ui/vuu-popups": "0.13.13",
15
- "@vuu-ui/vuu-table": "0.13.13",
16
- "@vuu-ui/vuu-utils": "0.13.13",
17
- "@vuu-ui/vuu-ui-controls": "0.13.13",
10
+ "@vuu-ui/vuu-codemirror": "0.13.14",
11
+ "@vuu-ui/vuu-data-react": "0.13.14",
12
+ "@vuu-ui/vuu-data-types": "0.13.14",
13
+ "@vuu-ui/vuu-table-types": "0.13.14",
14
+ "@vuu-ui/vuu-popups": "0.13.14",
15
+ "@vuu-ui/vuu-table": "0.13.14",
16
+ "@vuu-ui/vuu-utils": "0.13.14",
17
+ "@vuu-ui/vuu-ui-controls": "0.13.14",
18
18
  "@lezer/lr": "1.4.2",
19
19
  "@salt-ds/core": "1.43.0",
20
20
  "@salt-ds/styles": "0.2.1",
@@ -1,7 +1,7 @@
1
+ import { MenuActionHandler } from "@vuu-ui/vuu-context-menu";
1
2
  import { ColumnDescriptor, ColumnMenuPermissions } from "@vuu-ui/vuu-table-types";
2
3
  import { HTMLAttributes } from "react";
3
4
  import { ColumnMenuActionType } from "./column-menu-utils";
4
- import { MenuActionHandler } from "@vuu-ui/vuu-context-menu";
5
5
  export interface ColumnMenuProps extends HTMLAttributes<HTMLSpanElement> {
6
6
  column: ColumnDescriptor;
7
7
  menuActionHandler?: MenuActionHandler<ColumnMenuActionType, ColumnDescriptor>;
@@ -0,0 +1,5 @@
1
+ import { type FreezeProps } from "./useFreezeControl";
2
+ import { HTMLAttributes } from "react";
3
+ export interface FreezeControlProps extends HTMLAttributes<HTMLDivElement>, FreezeProps {
4
+ }
5
+ export declare const FreezeControl: ({ dataSource, className, ...htmlAttributes }: FreezeControlProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,12 @@
1
+ import { DataSource } from "@vuu-ui/vuu-data-types";
2
+ import { ChangeEventHandler } from "react";
3
+ export interface FreezeProps {
4
+ dataSource: DataSource;
5
+ }
6
+ export declare const useFreezeControl: ({ dataSource }: FreezeProps) => {
7
+ onSwitchChange: ChangeEventHandler<HTMLInputElement>;
8
+ isFrozen: boolean;
9
+ label: string;
10
+ lastUpdateMessage: string;
11
+ newRecordCount: number;
12
+ };
package/types/index.d.ts CHANGED
@@ -14,3 +14,4 @@ export * from "./column-expression-panel";
14
14
  export * from "./column-formatting-settings";
15
15
  export * from "./datasource-stats";
16
16
  export { TableProvider, useTableContext } from "./table-provider/TableProvider";
17
+ export { FreezeControl } from "./freeze-control/FreezeControl";