@vuu-ui/vuu-utils 2.1.14 → 2.1.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/node_modules/@dnd-kit/react/hooks.js +17 -17
- package/cjs/node_modules/@dnd-kit/react/hooks.js.map +1 -1
- package/cjs/node_modules/@dnd-kit/react/index.js +24 -24
- package/cjs/node_modules/@dnd-kit/react/index.js.map +1 -1
- package/cjs/node_modules/@dnd-kit/react/sortable.js +5 -5
- package/cjs/node_modules/@dnd-kit/react/sortable.js.map +1 -1
- package/cjs/packages/vuu-utils/src/ShellContext.js +3 -3
- package/cjs/packages/vuu-utils/src/ShellContext.js.map +1 -1
- package/cjs/packages/vuu-utils/src/ThemeProvider.js +10 -10
- package/cjs/packages/vuu-utils/src/ThemeProvider.js.map +1 -1
- package/cjs/packages/vuu-utils/src/context-definitions/DataContext.js +2 -2
- package/cjs/packages/vuu-utils/src/context-definitions/DataContext.js.map +1 -1
- package/cjs/packages/vuu-utils/src/context-definitions/DataProvider.js +4 -4
- package/cjs/packages/vuu-utils/src/context-definitions/DataProvider.js.map +1 -1
- package/cjs/packages/vuu-utils/src/context-definitions/DataSourceProvider.js +5 -5
- package/cjs/packages/vuu-utils/src/context-definitions/DataSourceProvider.js.map +1 -1
- package/cjs/packages/vuu-utils/src/context-definitions/WorkspaceContext.js +3 -3
- package/cjs/packages/vuu-utils/src/context-definitions/WorkspaceContext.js.map +1 -1
- package/cjs/packages/vuu-utils/src/data-editing/DataEditingProvider.js +5 -5
- package/cjs/packages/vuu-utils/src/data-editing/DataEditingProvider.js.map +1 -1
- package/cjs/packages/vuu-utils/src/data-editing/EditButtons.js +10 -10
- package/cjs/packages/vuu-utils/src/data-editing/EditButtons.js.map +1 -1
- package/cjs/packages/vuu-utils/src/data-editing/EditSession.js +57 -62
- package/cjs/packages/vuu-utils/src/data-editing/EditSession.js.map +1 -1
- package/cjs/packages/vuu-utils/src/data-editing/edit-utils.js +5 -5
- package/cjs/packages/vuu-utils/src/data-editing/edit-utils.js.map +1 -1
- package/cjs/packages/vuu-utils/src/data-editing/useEditableTable.js +7 -7
- package/cjs/packages/vuu-utils/src/data-editing/useEditableTable.js.map +1 -1
- package/cjs/packages/vuu-utils/src/datasource/BaseDataSource.js +2 -2
- package/cjs/packages/vuu-utils/src/datasource/BaseDataSource.js.map +1 -1
- package/cjs/packages/vuu-utils/src/datasource/datasource-filter-utils.js +3 -3
- package/cjs/packages/vuu-utils/src/datasource/datasource-filter-utils.js.map +1 -1
- package/cjs/packages/vuu-utils/src/date/date-utils.js +2 -2
- package/cjs/packages/vuu-utils/src/date/date-utils.js.map +1 -1
- package/cjs/packages/vuu-utils/src/date/formatter.js +2 -2
- package/cjs/packages/vuu-utils/src/date/formatter.js.map +1 -1
- package/cjs/packages/vuu-utils/src/feature-utils.js +2 -2
- package/cjs/packages/vuu-utils/src/feature-utils.js.map +1 -1
- package/cjs/packages/vuu-utils/src/react-utils.js +8 -8
- package/cjs/packages/vuu-utils/src/react-utils.js.map +1 -1
- package/cjs/packages/vuu-utils/src/theme-utils.js +3 -3
- package/cjs/packages/vuu-utils/src/theme-utils.js.map +1 -1
- package/cjs/packages/vuu-utils/src/useId.js +2 -2
- package/cjs/packages/vuu-utils/src/useId.js.map +1 -1
- package/cjs/packages/vuu-utils/src/useLayoutEffectSkipFirst.js +3 -3
- package/cjs/packages/vuu-utils/src/useLayoutEffectSkipFirst.js.map +1 -1
- package/cjs/packages/vuu-utils/src/useResizeObserver.js +5 -5
- package/cjs/packages/vuu-utils/src/useResizeObserver.js.map +1 -1
- package/cjs/packages/vuu-utils/src/useStateRef.js +4 -4
- package/cjs/packages/vuu-utils/src/useStateRef.js.map +1 -1
- package/esm/packages/vuu-utils/src/ThemeProvider.js +2 -2
- package/esm/packages/vuu-utils/src/ThemeProvider.js.map +1 -1
- package/esm/packages/vuu-utils/src/context-definitions/WorkspaceContext.js +2 -2
- package/esm/packages/vuu-utils/src/context-definitions/WorkspaceContext.js.map +1 -1
- package/esm/packages/vuu-utils/src/data-editing/EditSession.js +57 -62
- package/esm/packages/vuu-utils/src/data-editing/EditSession.js.map +1 -1
- package/esm/packages/vuu-utils/src/feature-utils.js +2 -2
- package/esm/packages/vuu-utils/src/feature-utils.js.map +1 -1
- package/package.json +6 -6
- package/types/data-editing/EditSession.d.ts +8 -15
- package/cjs/packages/vuu-utils/dist/index.js +0 -6004
- package/cjs/packages/vuu-utils/dist/index.js.map +0 -1
- package/esm/packages/vuu-utils/dist/index.js +0 -5979
- package/esm/packages/vuu-utils/dist/index.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var React = require('react');
|
|
4
4
|
|
|
5
5
|
const WidthHeight = ["height", "width"];
|
|
6
6
|
const WidthOnly = ["width"];
|
|
@@ -54,8 +54,8 @@ const resizeObserver = new ResizeObserver((entries) => {
|
|
|
54
54
|
}
|
|
55
55
|
});
|
|
56
56
|
function useResizeObserver(ref, dimensions, onResize, reportInitialSize = false) {
|
|
57
|
-
const dimensionsRef =
|
|
58
|
-
const measure =
|
|
57
|
+
const dimensionsRef = React.useRef(dimensions);
|
|
58
|
+
const measure = React.useCallback((target) => {
|
|
59
59
|
const { width, height } = target.getBoundingClientRect();
|
|
60
60
|
const { clientWidth: contentWidth, clientHeight: contentHeight } = target;
|
|
61
61
|
const flooredHeight = Math.floor(height);
|
|
@@ -77,7 +77,7 @@ function useResizeObserver(ref, dimensions, onResize, reportInitialSize = false)
|
|
|
77
77
|
{}
|
|
78
78
|
);
|
|
79
79
|
}, []);
|
|
80
|
-
|
|
80
|
+
React.useEffect(() => {
|
|
81
81
|
const target = ref.current;
|
|
82
82
|
async function registerObserver() {
|
|
83
83
|
observedMap.set(target, { measurements: {} });
|
|
@@ -114,7 +114,7 @@ function useResizeObserver(ref, dimensions, onResize, reportInitialSize = false)
|
|
|
114
114
|
}
|
|
115
115
|
};
|
|
116
116
|
}, [measure, ref]);
|
|
117
|
-
|
|
117
|
+
React.useEffect(() => {
|
|
118
118
|
const target = ref.current;
|
|
119
119
|
const record = observedMap.get(target);
|
|
120
120
|
if (record) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useResizeObserver.js","sources":["../../../../../../packages/vuu-utils/src/useResizeObserver.ts"],"sourcesContent":["import { RefObject, useCallback, useEffect, useRef } from \"react\";\n\nexport const WidthHeight = [\"height\", \"width\"];\nexport const WidthOnly = [\"width\"];\n\nexport type measurements<T = string | number> = {\n height?: T;\n clientHeight?: number;\n clientWidth?: number;\n contentHeight?: number;\n contentWidth?: number;\n scrollHeight?: number;\n scrollWidth?: number;\n width?: T;\n};\ntype measuredDimension = keyof measurements<number>;\n\nexport type ResizeHandler = (measurements: measurements<number>) => void;\n\ntype observedDetails = {\n onResize?: ResizeHandler;\n measurements: measurements<number>;\n};\nconst observedMap = new Map<HTMLElement, observedDetails>();\n\nconst getTargetSize = (\n element: HTMLElement,\n size: {\n height: number;\n width: number;\n contentHeight: number;\n contentWidth: number;\n },\n dimension: measuredDimension,\n): number => {\n switch (dimension) {\n case \"height\":\n return size.height;\n case \"clientHeight\":\n return Math.floor(element.clientHeight);\n case \"clientWidth\":\n return Math.floor(element.clientWidth);\n case \"contentHeight\":\n return size.contentHeight;\n case \"contentWidth\":\n return size.contentWidth;\n case \"scrollHeight\":\n return Math.ceil(Math.floor(element.scrollHeight));\n case \"scrollWidth\":\n return Math.ceil(Math.floor(element.scrollWidth));\n case \"width\":\n return size.width;\n default:\n return 0;\n }\n};\n\n// TODO should we make this create-on-demand\nconst resizeObserver = new ResizeObserver((entries: ResizeObserverEntry[]) => {\n for (const entry of entries) {\n const { target, borderBoxSize, contentBoxSize } = entry;\n const observedTarget = observedMap.get(target as HTMLElement);\n if (observedTarget) {\n const [{ blockSize: height, inlineSize: width }] = borderBoxSize;\n const [{ blockSize: contentHeight, inlineSize: contentWidth }] =\n contentBoxSize;\n const { onResize, measurements } = observedTarget;\n let sizeChanged = false;\n for (const [dimension, size] of Object.entries(measurements)) {\n const newSize = getTargetSize(\n target as HTMLElement,\n { height, width, contentHeight, contentWidth },\n dimension as measuredDimension,\n );\n\n if (newSize !== size) {\n sizeChanged = true;\n measurements[dimension as measuredDimension] = newSize;\n }\n }\n if (sizeChanged) {\n // TODO only return measured sizes\n onResize && onResize(measurements);\n }\n }\n }\n});\n\n// TODO use an optional lag (default to false) to ask to fire onResize\n// with initial size\nexport function useResizeObserver(\n ref: RefObject<Element | HTMLElement | null>,\n dimensions: readonly string[],\n onResize: ResizeHandler,\n reportInitialSize = false,\n) {\n const dimensionsRef = useRef(dimensions);\n\n const measure = useCallback((target: HTMLElement): measurements<number> => {\n const { width, height } = target.getBoundingClientRect();\n const { clientWidth: contentWidth, clientHeight: contentHeight } = target;\n const flooredHeight = Math.floor(height);\n const flooredWidth = Math.floor(width);\n\n return dimensionsRef.current.reduce(\n (map: { [key: string]: number }, dim) => {\n map[dim] = getTargetSize(\n target,\n {\n width: flooredWidth,\n height: flooredHeight,\n contentHeight,\n contentWidth,\n },\n dim as measuredDimension,\n );\n return map;\n },\n {},\n );\n }, []);\n\n // TODO use ref to store resizeHandler here\n // resize handler registered with REsizeObserver will never change\n // use ref to store user onResize callback here\n // resizeHandler will call user callback.current\n\n // Keep this effect separate in case user inadvertently passes different\n // dimensions or callback instance each time - we only ever want to\n // initiate new observation when ref changes.\n useEffect(() => {\n const target = ref.current as HTMLElement;\n async function registerObserver() {\n // Create the map entry immediately. useEffect may fire below\n // before fonts are ready and attempt to update entry\n observedMap.set(target, { measurements: {} as measurements<number> });\n // await document.fonts.ready;\n const observedTarget = observedMap.get(target);\n if (observedTarget) {\n const measurements = measure(target);\n observedTarget.measurements = measurements;\n resizeObserver.observe(target);\n if (reportInitialSize) {\n onResize(measurements);\n }\n } else {\n console.log(\n `%cuseResizeObserver an target expected to be under observation wa snot found. This warrants investigation`,\n \"font-weight:bold; color:red;\",\n );\n }\n }\n\n if (target) {\n // TODO might we want multiple callers to attach a listener to the same element ?\n if (observedMap.has(target)) {\n console.log(\n `useResizeObserver attemping to observe same element twice`,\n {\n target,\n },\n );\n // throw Error(\n // \"useResizeObserver attemping to observe same element twice\"\n // );\n }\n // TODO set a pending entry on map\n registerObserver();\n }\n return () => {\n if (target && observedMap.has(target)) {\n resizeObserver.unobserve(target);\n observedMap.delete(target);\n }\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [measure, ref]);\n\n useEffect(() => {\n const target = ref.current as HTMLElement;\n const record = observedMap.get(target);\n if (record) {\n if (dimensionsRef.current !== dimensions) {\n dimensionsRef.current = dimensions;\n const measurements = measure(target);\n record.measurements = measurements;\n }\n // Might not have changed, but no harm ...\n record.onResize = onResize;\n }\n }, [dimensions, measure, ref, onResize]);\n}\n"],"names":["useRef","useCallback","useEffect"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useResizeObserver.js","sources":["../../../../../../packages/vuu-utils/src/useResizeObserver.ts"],"sourcesContent":["import { RefObject, useCallback, useEffect, useRef } from \"react\";\n\nexport const WidthHeight = [\"height\", \"width\"];\nexport const WidthOnly = [\"width\"];\n\nexport type measurements<T = string | number> = {\n height?: T;\n clientHeight?: number;\n clientWidth?: number;\n contentHeight?: number;\n contentWidth?: number;\n scrollHeight?: number;\n scrollWidth?: number;\n width?: T;\n};\ntype measuredDimension = keyof measurements<number>;\n\nexport type ResizeHandler = (measurements: measurements<number>) => void;\n\ntype observedDetails = {\n onResize?: ResizeHandler;\n measurements: measurements<number>;\n};\nconst observedMap = new Map<HTMLElement, observedDetails>();\n\nconst getTargetSize = (\n element: HTMLElement,\n size: {\n height: number;\n width: number;\n contentHeight: number;\n contentWidth: number;\n },\n dimension: measuredDimension,\n): number => {\n switch (dimension) {\n case \"height\":\n return size.height;\n case \"clientHeight\":\n return Math.floor(element.clientHeight);\n case \"clientWidth\":\n return Math.floor(element.clientWidth);\n case \"contentHeight\":\n return size.contentHeight;\n case \"contentWidth\":\n return size.contentWidth;\n case \"scrollHeight\":\n return Math.ceil(Math.floor(element.scrollHeight));\n case \"scrollWidth\":\n return Math.ceil(Math.floor(element.scrollWidth));\n case \"width\":\n return size.width;\n default:\n return 0;\n }\n};\n\n// TODO should we make this create-on-demand\nconst resizeObserver = new ResizeObserver((entries: ResizeObserverEntry[]) => {\n for (const entry of entries) {\n const { target, borderBoxSize, contentBoxSize } = entry;\n const observedTarget = observedMap.get(target as HTMLElement);\n if (observedTarget) {\n const [{ blockSize: height, inlineSize: width }] = borderBoxSize;\n const [{ blockSize: contentHeight, inlineSize: contentWidth }] =\n contentBoxSize;\n const { onResize, measurements } = observedTarget;\n let sizeChanged = false;\n for (const [dimension, size] of Object.entries(measurements)) {\n const newSize = getTargetSize(\n target as HTMLElement,\n { height, width, contentHeight, contentWidth },\n dimension as measuredDimension,\n );\n\n if (newSize !== size) {\n sizeChanged = true;\n measurements[dimension as measuredDimension] = newSize;\n }\n }\n if (sizeChanged) {\n // TODO only return measured sizes\n onResize && onResize(measurements);\n }\n }\n }\n});\n\n// TODO use an optional lag (default to false) to ask to fire onResize\n// with initial size\nexport function useResizeObserver(\n ref: RefObject<Element | HTMLElement | null>,\n dimensions: readonly string[],\n onResize: ResizeHandler,\n reportInitialSize = false,\n) {\n const dimensionsRef = useRef(dimensions);\n\n const measure = useCallback((target: HTMLElement): measurements<number> => {\n const { width, height } = target.getBoundingClientRect();\n const { clientWidth: contentWidth, clientHeight: contentHeight } = target;\n const flooredHeight = Math.floor(height);\n const flooredWidth = Math.floor(width);\n\n return dimensionsRef.current.reduce(\n (map: { [key: string]: number }, dim) => {\n map[dim] = getTargetSize(\n target,\n {\n width: flooredWidth,\n height: flooredHeight,\n contentHeight,\n contentWidth,\n },\n dim as measuredDimension,\n );\n return map;\n },\n {},\n );\n }, []);\n\n // TODO use ref to store resizeHandler here\n // resize handler registered with REsizeObserver will never change\n // use ref to store user onResize callback here\n // resizeHandler will call user callback.current\n\n // Keep this effect separate in case user inadvertently passes different\n // dimensions or callback instance each time - we only ever want to\n // initiate new observation when ref changes.\n useEffect(() => {\n const target = ref.current as HTMLElement;\n async function registerObserver() {\n // Create the map entry immediately. useEffect may fire below\n // before fonts are ready and attempt to update entry\n observedMap.set(target, { measurements: {} as measurements<number> });\n // await document.fonts.ready;\n const observedTarget = observedMap.get(target);\n if (observedTarget) {\n const measurements = measure(target);\n observedTarget.measurements = measurements;\n resizeObserver.observe(target);\n if (reportInitialSize) {\n onResize(measurements);\n }\n } else {\n console.log(\n `%cuseResizeObserver an target expected to be under observation wa snot found. This warrants investigation`,\n \"font-weight:bold; color:red;\",\n );\n }\n }\n\n if (target) {\n // TODO might we want multiple callers to attach a listener to the same element ?\n if (observedMap.has(target)) {\n console.log(\n `useResizeObserver attemping to observe same element twice`,\n {\n target,\n },\n );\n // throw Error(\n // \"useResizeObserver attemping to observe same element twice\"\n // );\n }\n // TODO set a pending entry on map\n registerObserver();\n }\n return () => {\n if (target && observedMap.has(target)) {\n resizeObserver.unobserve(target);\n observedMap.delete(target);\n }\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [measure, ref]);\n\n useEffect(() => {\n const target = ref.current as HTMLElement;\n const record = observedMap.get(target);\n if (record) {\n if (dimensionsRef.current !== dimensions) {\n dimensionsRef.current = dimensions;\n const measurements = measure(target);\n record.measurements = measurements;\n }\n // Might not have changed, but no harm ...\n record.onResize = onResize;\n }\n }, [dimensions, measure, ref, onResize]);\n}\n"],"names":["useRef","useCallback","useEffect"],"mappings":"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"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var React = require('react');
|
|
4
4
|
|
|
5
5
|
const isSimpleStateValue = (arg) => typeof arg !== "function";
|
|
6
6
|
const useStateRef = (initialValue) => {
|
|
7
|
-
const [value, _setValue] =
|
|
8
|
-
const ref =
|
|
9
|
-
const setValue =
|
|
7
|
+
const [value, _setValue] = React.useState(initialValue);
|
|
8
|
+
const ref = React.useRef(value);
|
|
9
|
+
const setValue = React.useCallback((arg) => {
|
|
10
10
|
if (isSimpleStateValue(arg)) {
|
|
11
11
|
ref.current = arg;
|
|
12
12
|
_setValue(arg);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useStateRef.js","sources":["../../../../../../packages/vuu-utils/src/useStateRef.ts"],"sourcesContent":["import {\n Dispatch,\n RefObject,\n SetStateAction,\n useCallback,\n useRef,\n useState,\n} from \"react\";\n\n/**\n * Extension to useState that maintains a ref for the\n * current state value. Useful where use of the ref can\n * avoid referencing the state vale in a dependency array\n * eg on a native event handler.\n *\n * @param value the initial value to store\n */\n\nconst isSimpleStateValue = <T>(arg: SetStateAction<T>): arg is T =>\n typeof arg !== \"function\";\n\n// Keeps a ref value in sync with a state value\nexport const useStateRef = <T = string>(\n initialValue: T,\n): [RefObject<T>, Dispatch<SetStateAction<T>>] => {\n const [value, _setValue] = useState<T>(initialValue);\n const ref = useRef<T>(value);\n\n const setValue = useCallback<Dispatch<SetStateAction<T>>>((arg) => {\n if (isSimpleStateValue(arg)) {\n ref.current = arg;\n _setValue(arg);\n } else {\n const { current: prev } = ref;\n ref.current = arg(prev);\n _setValue(ref.current);\n }\n }, []);\n return [ref, setValue];\n};\n"],"names":["useState","useRef","useCallback"],"mappings":";;;;AAkBA,MAAM,kBAAqB,GAAA,CAAI,GAC7B,KAAA,OAAO,GAAQ,KAAA,UAAA;AAGJ,MAAA,WAAA,GAAc,CACzB,YACgD,KAAA;AAChD,EAAA,MAAM,CAAC,KAAA,EAAO,SAAS,CAAA,GAAIA,
|
|
1
|
+
{"version":3,"file":"useStateRef.js","sources":["../../../../../../packages/vuu-utils/src/useStateRef.ts"],"sourcesContent":["import {\n Dispatch,\n RefObject,\n SetStateAction,\n useCallback,\n useRef,\n useState,\n} from \"react\";\n\n/**\n * Extension to useState that maintains a ref for the\n * current state value. Useful where use of the ref can\n * avoid referencing the state vale in a dependency array\n * eg on a native event handler.\n *\n * @param value the initial value to store\n */\n\nconst isSimpleStateValue = <T>(arg: SetStateAction<T>): arg is T =>\n typeof arg !== \"function\";\n\n// Keeps a ref value in sync with a state value\nexport const useStateRef = <T = string>(\n initialValue: T,\n): [RefObject<T>, Dispatch<SetStateAction<T>>] => {\n const [value, _setValue] = useState<T>(initialValue);\n const ref = useRef<T>(value);\n\n const setValue = useCallback<Dispatch<SetStateAction<T>>>((arg) => {\n if (isSimpleStateValue(arg)) {\n ref.current = arg;\n _setValue(arg);\n } else {\n const { current: prev } = ref;\n ref.current = arg(prev);\n _setValue(ref.current);\n }\n }, []);\n return [ref, setValue];\n};\n"],"names":["useState","useRef","useCallback"],"mappings":";;;;AAkBA,MAAM,kBAAqB,GAAA,CAAI,GAC7B,KAAA,OAAO,GAAQ,KAAA,UAAA;AAGJ,MAAA,WAAA,GAAc,CACzB,YACgD,KAAA;AAChD,EAAA,MAAM,CAAC,KAAA,EAAO,SAAS,CAAA,GAAIA,eAAY,YAAY,CAAA;AACnD,EAAM,MAAA,GAAA,GAAMC,aAAU,KAAK,CAAA;AAE3B,EAAM,MAAA,QAAA,GAAWC,iBAAyC,CAAA,CAAC,GAAQ,KAAA;AACjE,IAAI,IAAA,kBAAA,CAAmB,GAAG,CAAG,EAAA;AAC3B,MAAA,GAAA,CAAI,OAAU,GAAA,GAAA;AACd,MAAA,SAAA,CAAU,GAAG,CAAA;AAAA,KACR,MAAA;AACL,MAAM,MAAA,EAAE,OAAS,EAAA,IAAA,EAAS,GAAA,GAAA;AAC1B,MAAI,GAAA,CAAA,OAAA,GAAU,IAAI,IAAI,CAAA;AACtB,MAAA,SAAA,CAAU,IAAI,OAAO,CAAA;AAAA;AACvB,GACF,EAAG,EAAE,CAAA;AACL,EAAO,OAAA,CAAC,KAAK,QAAQ,CAAA;AACvB;;;;"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
2
|
import { createContext, useContext, isValidElement, cloneElement } from 'react';
|
|
3
|
-
import
|
|
3
|
+
import cx from 'clsx';
|
|
4
4
|
|
|
5
5
|
const DEFAULT_DENSITY = "medium";
|
|
6
6
|
const DEFAULT_THEME = "salt-theme";
|
|
@@ -35,7 +35,7 @@ const useThemeAttributes = (themeAttributes) => {
|
|
|
35
35
|
const createThemedChildren = (children, theme, themeMode, density) => {
|
|
36
36
|
if (isValidElement(children)) {
|
|
37
37
|
return cloneElement(children, {
|
|
38
|
-
className:
|
|
38
|
+
className: cx(
|
|
39
39
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
40
40
|
children.props?.className,
|
|
41
41
|
`${theme}-theme`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThemeProvider.js","sources":["../../../../../../packages/vuu-utils/src/ThemeProvider.tsx"],"sourcesContent":["import React, {\n createContext,\n HTMLAttributes,\n ReactNode,\n isValidElement,\n cloneElement,\n useContext,\n} from \"react\";\nimport cx from \"clsx\";\n\nexport const DEFAULT_DENSITY: Density = \"medium\";\nexport const DEFAULT_THEME = \"salt-theme\";\nexport const DEFAULT_THEME_MODE: ThemeMode = \"light\";\n\nexport type Density = \"high\" | \"medium\" | \"low\" | \"touch\";\nexport type ThemeMode = \"light\" | \"dark\";\nexport type TargetElement = \"root\" | \"scope\" | \"child\";\n\nexport interface ThemeContextProps {\n density: Density;\n theme: string;\n themeMode: ThemeMode;\n}\n\nexport const ThemeContext = createContext<ThemeContextProps>({\n density: \"high\",\n theme: \"vuu\",\n themeMode: \"light\",\n});\n\nexport type ThemeClasses = [string, string, ThemeMode];\n\nconst DEFAULT_THEME_ATTRIBUTES: ThemeClasses = [\n \"vuu\",\n \"salt-density-high\",\n \"light\" as ThemeMode,\n];\n\nexport type ThemeAttributes = {\n themeClass: string;\n densityClass: string;\n dataMode: ThemeMode;\n};\n\nexport const useThemeAttributes = (\n themeAttributes?: ThemeAttributes\n): [string, string, ThemeMode] => {\n const context = useContext(ThemeContext);\n if (themeAttributes) {\n return [\n themeAttributes.themeClass,\n themeAttributes.densityClass,\n themeAttributes.dataMode,\n ];\n } else if (context) {\n return [\n `${context.theme}-theme`,\n `salt-density-${context.density}`,\n context.themeMode,\n ];\n }\n return DEFAULT_THEME_ATTRIBUTES;\n};\n\nconst createThemedChildren = (\n children: ReactNode,\n theme: string,\n themeMode: ThemeMode,\n density: Density\n) => {\n if (isValidElement<HTMLAttributes<HTMLElement>>(children)) {\n return cloneElement(children, {\n className: cx(\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n children.props?.className,\n `${theme}-theme`,\n `salt-density-${density}`\n ),\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n \"data-mode\": themeMode,\n });\n } else {\n console.warn(\n `\\nThemeProvider can only apply CSS classes for theming to a single nested child element of the ThemeProvider.\n Wrap elements with a single container`\n );\n return children;\n }\n};\n\ninterface ThemeProviderProps {\n applyThemeClasses?: boolean;\n children: ReactNode;\n density?: Density;\n theme?: string;\n themeMode?: ThemeMode;\n}\n\nexport const ThemeProvider = ({\n applyThemeClasses = false,\n children,\n theme: themeProp,\n themeMode: themeModeProp,\n density: densityProp,\n}: ThemeProviderProps) => {\n const {\n density: inheritedDensity,\n themeMode: inheritedThemeMode,\n theme: inheritedTheme,\n } = useContext(ThemeContext);\n const density = densityProp ?? inheritedDensity ?? DEFAULT_DENSITY;\n const themeMode = themeModeProp ?? inheritedThemeMode ?? DEFAULT_THEME_MODE;\n const theme = themeProp ?? inheritedTheme ?? DEFAULT_THEME;\n const themedChildren = applyThemeClasses\n ? createThemedChildren(children, theme, themeMode, density)\n : children;\n\n return (\n <ThemeContext.Provider value={{ themeMode, density, theme }}>\n {themedChildren}\n </ThemeContext.Provider>\n );\n};\n\nThemeProvider.displayName = \"ThemeProvider\";\n"],"names":[
|
|
1
|
+
{"version":3,"file":"ThemeProvider.js","sources":["../../../../../../packages/vuu-utils/src/ThemeProvider.tsx"],"sourcesContent":["import React, {\n createContext,\n HTMLAttributes,\n ReactNode,\n isValidElement,\n cloneElement,\n useContext,\n} from \"react\";\nimport cx from \"clsx\";\n\nexport const DEFAULT_DENSITY: Density = \"medium\";\nexport const DEFAULT_THEME = \"salt-theme\";\nexport const DEFAULT_THEME_MODE: ThemeMode = \"light\";\n\nexport type Density = \"high\" | \"medium\" | \"low\" | \"touch\";\nexport type ThemeMode = \"light\" | \"dark\";\nexport type TargetElement = \"root\" | \"scope\" | \"child\";\n\nexport interface ThemeContextProps {\n density: Density;\n theme: string;\n themeMode: ThemeMode;\n}\n\nexport const ThemeContext = createContext<ThemeContextProps>({\n density: \"high\",\n theme: \"vuu\",\n themeMode: \"light\",\n});\n\nexport type ThemeClasses = [string, string, ThemeMode];\n\nconst DEFAULT_THEME_ATTRIBUTES: ThemeClasses = [\n \"vuu\",\n \"salt-density-high\",\n \"light\" as ThemeMode,\n];\n\nexport type ThemeAttributes = {\n themeClass: string;\n densityClass: string;\n dataMode: ThemeMode;\n};\n\nexport const useThemeAttributes = (\n themeAttributes?: ThemeAttributes\n): [string, string, ThemeMode] => {\n const context = useContext(ThemeContext);\n if (themeAttributes) {\n return [\n themeAttributes.themeClass,\n themeAttributes.densityClass,\n themeAttributes.dataMode,\n ];\n } else if (context) {\n return [\n `${context.theme}-theme`,\n `salt-density-${context.density}`,\n context.themeMode,\n ];\n }\n return DEFAULT_THEME_ATTRIBUTES;\n};\n\nconst createThemedChildren = (\n children: ReactNode,\n theme: string,\n themeMode: ThemeMode,\n density: Density\n) => {\n if (isValidElement<HTMLAttributes<HTMLElement>>(children)) {\n return cloneElement(children, {\n className: cx(\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n children.props?.className,\n `${theme}-theme`,\n `salt-density-${density}`\n ),\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n \"data-mode\": themeMode,\n });\n } else {\n console.warn(\n `\\nThemeProvider can only apply CSS classes for theming to a single nested child element of the ThemeProvider.\n Wrap elements with a single container`\n );\n return children;\n }\n};\n\ninterface ThemeProviderProps {\n applyThemeClasses?: boolean;\n children: ReactNode;\n density?: Density;\n theme?: string;\n themeMode?: ThemeMode;\n}\n\nexport const ThemeProvider = ({\n applyThemeClasses = false,\n children,\n theme: themeProp,\n themeMode: themeModeProp,\n density: densityProp,\n}: ThemeProviderProps) => {\n const {\n density: inheritedDensity,\n themeMode: inheritedThemeMode,\n theme: inheritedTheme,\n } = useContext(ThemeContext);\n const density = densityProp ?? inheritedDensity ?? DEFAULT_DENSITY;\n const themeMode = themeModeProp ?? inheritedThemeMode ?? DEFAULT_THEME_MODE;\n const theme = themeProp ?? inheritedTheme ?? DEFAULT_THEME;\n const themedChildren = applyThemeClasses\n ? createThemedChildren(children, theme, themeMode, density)\n : children;\n\n return (\n <ThemeContext.Provider value={{ themeMode, density, theme }}>\n {themedChildren}\n </ThemeContext.Provider>\n );\n};\n\nThemeProvider.displayName = \"ThemeProvider\";\n"],"names":[],"mappings":";;;;AAUO,MAAM,eAA2B,GAAA;AACjC,MAAM,aAAgB,GAAA;AACtB,MAAM,kBAAgC,GAAA;AAYtC,MAAM,eAAe,aAAiC,CAAA;AAAA,EAC3D,OAAS,EAAA,MAAA;AAAA,EACT,KAAO,EAAA,KAAA;AAAA,EACP,SAAW,EAAA;AACb,CAAC;AAID,MAAM,wBAAyC,GAAA;AAAA,EAC7C,KAAA;AAAA,EACA,mBAAA;AAAA,EACA;AACF,CAAA;AAQa,MAAA,kBAAA,GAAqB,CAChC,eACgC,KAAA;AAChC,EAAM,MAAA,OAAA,GAAU,WAAW,YAAY,CAAA;AACvC,EAAA,IAAI,eAAiB,EAAA;AACnB,IAAO,OAAA;AAAA,MACL,eAAgB,CAAA,UAAA;AAAA,MAChB,eAAgB,CAAA,YAAA;AAAA,MAChB,eAAgB,CAAA;AAAA,KAClB;AAAA,aACS,OAAS,EAAA;AAClB,IAAO,OAAA;AAAA,MACL,CAAA,EAAG,QAAQ,KAAK,CAAA,MAAA,CAAA;AAAA,MAChB,CAAA,aAAA,EAAgB,QAAQ,OAAO,CAAA,CAAA;AAAA,MAC/B,OAAQ,CAAA;AAAA,KACV;AAAA;AAEF,EAAO,OAAA,wBAAA;AACT;AAEA,MAAM,oBAAuB,GAAA,CAC3B,QACA,EAAA,KAAA,EACA,WACA,OACG,KAAA;AACH,EAAI,IAAA,cAAA,CAA4C,QAAQ,CAAG,EAAA;AACzD,IAAA,OAAO,aAAa,QAAU,EAAA;AAAA,MAC5B,SAAW,EAAA,EAAA;AAAA;AAAA,QAET,SAAS,KAAO,EAAA,SAAA;AAAA,QAChB,GAAG,KAAK,CAAA,MAAA,CAAA;AAAA,QACR,gBAAgB,OAAO,CAAA;AAAA,OACzB;AAAA;AAAA;AAAA,MAGA,WAAa,EAAA;AAAA,KACd,CAAA;AAAA,GACI,MAAA;AACL,IAAQ,OAAA,CAAA,IAAA;AAAA,MACN;AAAA;AAAA,iDAAA;AAAA,KAEF;AACA,IAAO,OAAA,QAAA;AAAA;AAEX,CAAA;AAUO,MAAM,gBAAgB,CAAC;AAAA,EAC5B,iBAAoB,GAAA,KAAA;AAAA,EACpB,QAAA;AAAA,EACA,KAAO,EAAA,SAAA;AAAA,EACP,SAAW,EAAA,aAAA;AAAA,EACX,OAAS,EAAA;AACX,CAA0B,KAAA;AACxB,EAAM,MAAA;AAAA,IACJ,OAAS,EAAA,gBAAA;AAAA,IACT,SAAW,EAAA,kBAAA;AAAA,IACX,KAAO,EAAA;AAAA,GACT,GAAI,WAAW,YAAY,CAAA;AAC3B,EAAM,MAAA,OAAA,GAAU,eAAe,gBAAoB,IAAA,eAAA;AACnD,EAAM,MAAA,SAAA,GAAY,iBAAiB,kBAAsB,IAAA,kBAAA;AACzD,EAAM,MAAA,KAAA,GAAQ,aAAa,cAAkB,IAAA,aAAA;AAC7C,EAAA,MAAM,iBAAiB,iBACnB,GAAA,oBAAA,CAAqB,UAAU,KAAO,EAAA,SAAA,EAAW,OAAO,CACxD,GAAA,QAAA;AAEJ,EACE,uBAAA,GAAA,CAAC,YAAa,CAAA,QAAA,EAAb,EAAsB,KAAA,EAAO,EAAE,SAAW,EAAA,OAAA,EAAS,KAAM,EAAA,EACvD,QACH,EAAA,cAAA,EAAA,CAAA;AAEJ;AAEA,aAAA,CAAc,WAAc,GAAA,eAAA;;;;"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
import React, { useContext } from 'react';
|
|
2
2
|
|
|
3
|
-
const WorkspaceContext =
|
|
3
|
+
const WorkspaceContext = React.createContext({
|
|
4
4
|
getApplicationSettings: () => void 0,
|
|
5
5
|
layoutMetadata: [],
|
|
6
6
|
saveLayout: () => void 0,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkspaceContext.js","sources":["../../../../../../../packages/vuu-utils/src/context-definitions/WorkspaceContext.tsx"],"sourcesContent":["import React, { useContext } from \"react\";\nimport {\n ApplicationSetting,\n ApplicationSettings,\n LayoutJSON\n} from \"../json-types\";\nimport { LayoutMetadata, LayoutMetadataDto } from \"../layout-types\";\n\nexport interface WorkspaceContextProps {\n layoutMetadata: LayoutMetadata[];\n layoutPlaceholderJSON?: LayoutJSON;\n getApplicationSettings: (\n key?: keyof ApplicationSettings\n ) => ApplicationSettings | ApplicationSetting | undefined;\n loadLayoutById: (id: string) => void;\n saveApplicationSettings: (\n settings: ApplicationSettings | ApplicationSetting,\n key?: keyof ApplicationSettings\n ) => void;\n saveLayout: (n: LayoutMetadataDto) => void;\n saveApplicationLayout: (layout: LayoutJSON) => void;\n workspaceJSON?: LayoutJSON | LayoutJSON[];\n}\n\nexport const WorkspaceContext = React.createContext<WorkspaceContextProps>({\n getApplicationSettings: () => undefined,\n layoutMetadata: [],\n saveLayout: () => undefined,\n saveApplicationLayout: () => undefined,\n saveApplicationSettings: () => undefined,\n loadLayoutById: () => undefined\n});\n\nexport const usePlaceholderJSON = () => {\n const { layoutPlaceholderJSON } = useContext(WorkspaceContext);\n return layoutPlaceholderJSON;\n};\n"],"names":[
|
|
1
|
+
{"version":3,"file":"WorkspaceContext.js","sources":["../../../../../../../packages/vuu-utils/src/context-definitions/WorkspaceContext.tsx"],"sourcesContent":["import React, { useContext } from \"react\";\nimport {\n ApplicationSetting,\n ApplicationSettings,\n LayoutJSON\n} from \"../json-types\";\nimport { LayoutMetadata, LayoutMetadataDto } from \"../layout-types\";\n\nexport interface WorkspaceContextProps {\n layoutMetadata: LayoutMetadata[];\n layoutPlaceholderJSON?: LayoutJSON;\n getApplicationSettings: (\n key?: keyof ApplicationSettings\n ) => ApplicationSettings | ApplicationSetting | undefined;\n loadLayoutById: (id: string) => void;\n saveApplicationSettings: (\n settings: ApplicationSettings | ApplicationSetting,\n key?: keyof ApplicationSettings\n ) => void;\n saveLayout: (n: LayoutMetadataDto) => void;\n saveApplicationLayout: (layout: LayoutJSON) => void;\n workspaceJSON?: LayoutJSON | LayoutJSON[];\n}\n\nexport const WorkspaceContext = React.createContext<WorkspaceContextProps>({\n getApplicationSettings: () => undefined,\n layoutMetadata: [],\n saveLayout: () => undefined,\n saveApplicationLayout: () => undefined,\n saveApplicationSettings: () => undefined,\n loadLayoutById: () => undefined\n});\n\nexport const usePlaceholderJSON = () => {\n const { layoutPlaceholderJSON } = useContext(WorkspaceContext);\n return layoutPlaceholderJSON;\n};\n"],"names":[],"mappings":";;AAwBa,MAAA,gBAAA,GAAmB,MAAM,aAAqC,CAAA;AAAA,EACzE,wBAAwB,MAAM,KAAA,CAAA;AAAA,EAC9B,gBAAgB,EAAC;AAAA,EACjB,YAAY,MAAM,KAAA,CAAA;AAAA,EAClB,uBAAuB,MAAM,KAAA,CAAA;AAAA,EAC7B,yBAAyB,MAAM,KAAA,CAAA;AAAA,EAC/B,gBAAgB,MAAM,KAAA;AACxB,CAAC;AAEM,MAAM,qBAAqB,MAAM;AACtC,EAAA,MAAM,EAAE,qBAAA,EAA0B,GAAA,UAAA,CAAW,gBAAgB,CAAA;AAC7D,EAAO,OAAA,qBAAA;AACT;;;;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { EventEmitter } from '../event-emitter.js';
|
|
2
|
-
import { isRpcError } from '
|
|
2
|
+
import { isRpcError } from '../protocol-message-utils.js';
|
|
3
3
|
|
|
4
4
|
var __typeError = (msg) => {
|
|
5
5
|
throw TypeError(msg);
|
|
@@ -24,12 +24,6 @@ class EditSession extends EventEmitter {
|
|
|
24
24
|
__privateAdd(this, _sessionDataSource);
|
|
25
25
|
__privateAdd(this, _inEditMode, false);
|
|
26
26
|
__privateSet(this, _sourceTableDataSource, dataSource);
|
|
27
|
-
dataSource.on("remote-update-during-local-edit", (rows) => {
|
|
28
|
-
console.log(
|
|
29
|
-
`source table updated via another channel, whilst we have an inline edit session in progress`,
|
|
30
|
-
{ rows }
|
|
31
|
-
);
|
|
32
|
-
});
|
|
33
27
|
}
|
|
34
28
|
get editCount() {
|
|
35
29
|
return __privateGet(this, _editCount);
|
|
@@ -97,7 +91,7 @@ class EditSession extends EventEmitter {
|
|
|
97
91
|
get editState() {
|
|
98
92
|
return this.editCount === 0 ? "clean" : "dirty";
|
|
99
93
|
}
|
|
100
|
-
|
|
94
|
+
getOrCreateRowEdits(key) {
|
|
101
95
|
const rowEditDetails = __privateGet(this, _rowEdits).get(key);
|
|
102
96
|
if (rowEditDetails) {
|
|
103
97
|
return rowEditDetails;
|
|
@@ -112,9 +106,21 @@ class EditSession extends EventEmitter {
|
|
|
112
106
|
storeCellEdit(cellEdits, column, originalValue, editedValue, isValid) {
|
|
113
107
|
const cellEdit = cellEdits.get(column);
|
|
114
108
|
if (cellEdit) {
|
|
115
|
-
if (
|
|
116
|
-
|
|
117
|
-
|
|
109
|
+
if (cellEdit.originalValue === editedValue) {
|
|
110
|
+
cellEdits.delete(column);
|
|
111
|
+
cellEdit.isDeleted = true;
|
|
112
|
+
if (cellEdit.isValid) {
|
|
113
|
+
this.editCount -= 1;
|
|
114
|
+
} else {
|
|
115
|
+
this.invalidCount -= 1;
|
|
116
|
+
}
|
|
117
|
+
} else {
|
|
118
|
+
if (isValid && cellEdit.isValid === false) {
|
|
119
|
+
cellEdit.isValid = true;
|
|
120
|
+
cellEdit.editedValue = editedValue;
|
|
121
|
+
__privateSet(this, _invalidCount, __privateGet(this, _invalidCount) - 1);
|
|
122
|
+
this.editCount += 1;
|
|
123
|
+
}
|
|
118
124
|
}
|
|
119
125
|
return cellEdit;
|
|
120
126
|
} else {
|
|
@@ -124,43 +130,17 @@ class EditSession extends EventEmitter {
|
|
|
124
130
|
isValid
|
|
125
131
|
};
|
|
126
132
|
cellEdits.set(column, cellEdit2);
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* Apply incremental edit(s) to edit control value. Used for TextInput, where multiple
|
|
133
|
-
* edits may follow in sequence before value finally committed.
|
|
134
|
-
*
|
|
135
|
-
* @param key value for edited Row
|
|
136
|
-
* @param columnName
|
|
137
|
-
* @param originalValue
|
|
138
|
-
* @param newValue
|
|
139
|
-
*/
|
|
140
|
-
edit(key, columnName, originalValue, newValue) {
|
|
141
|
-
const { cellEdits } = this.getRowEdits(key);
|
|
142
|
-
const cellEdit = cellEdits.get(columnName);
|
|
143
|
-
if (cellEdit) {
|
|
144
|
-
if (newValue === cellEdit.originalValue) {
|
|
145
|
-
if (cellEdits.size === 1) {
|
|
146
|
-
__privateGet(this, _rowEdits).delete(key);
|
|
147
|
-
} else {
|
|
148
|
-
cellEdits.delete(columnName);
|
|
149
|
-
}
|
|
150
|
-
this.editCount = __privateGet(this, _editCount) - 1;
|
|
151
|
-
} else {
|
|
152
|
-
cellEdit.editedValue = newValue;
|
|
133
|
+
if (isValid) {
|
|
134
|
+
this.editCount += 1;
|
|
153
135
|
}
|
|
154
|
-
|
|
155
|
-
cellEdits.set(columnName, {
|
|
156
|
-
originalValue,
|
|
157
|
-
editedValue: newValue
|
|
158
|
-
});
|
|
159
|
-
this.editCount = __privateGet(this, _editCount) + 1;
|
|
136
|
+
return cellEdit2;
|
|
160
137
|
}
|
|
161
138
|
}
|
|
162
139
|
async commit(key, columnName, originalValue, typedValue, isValid) {
|
|
163
|
-
|
|
140
|
+
if (!__privateGet(this, _inEditMode)) {
|
|
141
|
+
throw new Error("No edit session in progress");
|
|
142
|
+
}
|
|
143
|
+
const rowEditDetails = this.getOrCreateRowEdits(key);
|
|
164
144
|
if (isValid) {
|
|
165
145
|
const { cellEdits } = rowEditDetails;
|
|
166
146
|
const cellEdit = this.storeCellEdit(
|
|
@@ -170,28 +150,43 @@ class EditSession extends EventEmitter {
|
|
|
170
150
|
typedValue,
|
|
171
151
|
isValid
|
|
172
152
|
);
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
);
|
|
178
|
-
if (isRpcError(response)) {
|
|
179
|
-
cellEdit.isValid = false;
|
|
180
|
-
this.invalidCount += 1;
|
|
153
|
+
if (cellEdit.isDeleted) {
|
|
154
|
+
if (rowEditDetails.cellEdits.size === 0) {
|
|
155
|
+
__privateGet(this, _rowEdits).delete(key);
|
|
156
|
+
}
|
|
181
157
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
158
|
+
if (this.dataSource?.editCell) {
|
|
159
|
+
const response = await this.dataSource.editCell(
|
|
160
|
+
key,
|
|
161
|
+
columnName,
|
|
162
|
+
typedValue
|
|
163
|
+
);
|
|
164
|
+
if (isRpcError(response)) {
|
|
165
|
+
cellEdit.isValid = false;
|
|
189
166
|
this.invalidCount += 1;
|
|
190
167
|
}
|
|
168
|
+
return {
|
|
169
|
+
editedDuringCurrentSession: cellEdit.originalValue !== typedValue,
|
|
170
|
+
...response
|
|
171
|
+
};
|
|
191
172
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
);
|
|
173
|
+
} else {
|
|
174
|
+
const { cellEdits } = rowEditDetails;
|
|
175
|
+
let cellEdit = cellEdits.get(columnName);
|
|
176
|
+
if (cellEdit && cellEdit.isValid !== false) {
|
|
177
|
+
cellEdit.isValid = false;
|
|
178
|
+
this.invalidCount += 1;
|
|
179
|
+
} else if (cellEdit === void 0) {
|
|
180
|
+
cellEdit = this.storeCellEdit(
|
|
181
|
+
cellEdits,
|
|
182
|
+
columnName,
|
|
183
|
+
originalValue,
|
|
184
|
+
typedValue,
|
|
185
|
+
isValid
|
|
186
|
+
);
|
|
187
|
+
this.invalidCount += 1;
|
|
188
|
+
}
|
|
189
|
+
return { editedDuringCurrentSession: false };
|
|
195
190
|
}
|
|
196
191
|
}
|
|
197
192
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EditSession.js","sources":["../../../../../../../packages/vuu-utils/src/data-editing/EditSession.tsx"],"sourcesContent":["import { DataSource, EditSessionMode } from \"@vuu-ui/vuu-data-types\";\nimport type { VuuRowDataItemType } from \"@vuu-ui/vuu-protocol-types\";\nimport { EventEmitter } from \"../event-emitter\";\nimport { isRpcError } from \"../../dist/index.mjs\";\n\nexport type EditState = \"clean\" | \"dirty\" | \"invalid\" | \"stale\";\n\ntype CellEdit = {\n originalValue: VuuRowDataItemType;\n editedValue: VuuRowDataItemType;\n isValid?: boolean;\n};\n\n// TODO can add more when when we know what the server implementation of error columns will look like\nexport class StaleUpdateError extends Error {}\n\ntype RowEditDetails = {\n /**\n * Column name => cell edit details\n */\n cellEdits: Map<string, CellEdit>;\n};\n\ntype EditSessionEvents = {\n editState: (editState: EditState) => void;\n};\n\nexport class EditSession extends EventEmitter<EditSessionEvents> {\n /**\n * Row key => row edits\n */\n #rowEdits = new Map<string, RowEditDetails>();\n #editCount = 0;\n #invalidCount = 0;\n #sourceTableDataSource?: DataSource;\n #sessionDataSource?: DataSource;\n #inEditMode = false;\n\n constructor(dataSource: DataSource) {\n super();\n this.#sourceTableDataSource = dataSource;\n\n dataSource.on(\"remote-update-during-local-edit\", (rows) => {\n console.log(\n `source table updated via another channel, whilst we have an inline edit session in progress`,\n { rows },\n );\n });\n }\n\n get editCount() {\n return this.#editCount;\n }\n\n set editCount(val: number) {\n if (val !== this.#editCount) {\n const oldCount = this.#editCount;\n this.#editCount = val;\n if (val === 0) {\n this.emit(\"editState\", \"clean\");\n } else if (oldCount === 0) {\n this.emit(\"editState\", \"dirty\");\n }\n }\n }\n\n get invalidCount() {\n return this.#invalidCount;\n }\n\n set invalidCount(val: number) {\n if (val !== this.#invalidCount) {\n const oldCount = this.#invalidCount;\n this.#invalidCount = val;\n if (val === 0) {\n this.emit(\"editState\", this.#editCount === 0 ? \"clean\" : \"dirty\");\n } else if (oldCount === 0) {\n this.emit(\"editState\", \"invalid\");\n }\n }\n }\n\n clear() {\n this.#rowEdits.clear();\n this.#editCount = 0;\n this.#inEditMode = false;\n }\n\n async begin(editSessionMode?: EditSessionMode) {\n try {\n this.#inEditMode = true;\n const sessionDataSource =\n await this.#sourceTableDataSource?.beginEditSession?.(editSessionMode);\n\n this.#sessionDataSource = sessionDataSource;\n\n return sessionDataSource;\n } catch (e) {\n this.#inEditMode = false;\n }\n }\n\n get dataSource() {\n return this.#sessionDataSource ?? this.#sourceTableDataSource;\n }\n\n async end(saveChanges = false, force = false) {\n try {\n if (this.#inEditMode) {\n await this.dataSource?.endEditSession?.(saveChanges, force);\n this.clear();\n }\n } catch (e) {\n if (e instanceof StaleUpdateError) {\n this.emit(\"editState\", \"stale\");\n } else {\n console.error(`[EditSession] ${(e as Error).message}`);\n }\n }\n }\n\n get inEditMode() {\n return this.#inEditMode;\n }\n\n get editState(): EditState {\n return this.editCount === 0 ? \"clean\" : \"dirty\";\n }\n\n getRowEdits(key: string): RowEditDetails {\n const rowEditDetails = this.#rowEdits.get(key);\n if (rowEditDetails) {\n return rowEditDetails;\n } else {\n const rowEditDetails = {\n cellEdits: new Map(),\n };\n this.#rowEdits.set(key, rowEditDetails);\n return rowEditDetails;\n }\n }\n\n storeCellEdit(\n cellEdits: Map<string, CellEdit>,\n column: string,\n originalValue: VuuRowDataItemType,\n editedValue: VuuRowDataItemType,\n isValid: boolean,\n ) {\n const cellEdit = cellEdits.get(column);\n if (cellEdit) {\n if (isValid && cellEdit.isValid === false) {\n cellEdit.isValid = true;\n this.invalidCount -= 1;\n }\n return cellEdit;\n } else {\n const cellEdit = {\n originalValue,\n editedValue,\n isValid,\n };\n cellEdits.set(column, cellEdit);\n this.editCount = this.#editCount + 1;\n return cellEdit;\n }\n }\n\n /**\n * Apply incremental edit(s) to edit control value. Used for TextInput, where multiple\n * edits may follow in sequence before value finally committed.\n *\n * @param key value for edited Row\n * @param columnName\n * @param originalValue\n * @param newValue\n */\n edit(\n key: string,\n columnName: string,\n originalValue: VuuRowDataItemType,\n newValue: VuuRowDataItemType,\n ) {\n const { cellEdits } = this.getRowEdits(key);\n const cellEdit = cellEdits.get(columnName);\n if (cellEdit) {\n if (newValue === cellEdit.originalValue) {\n if (cellEdits.size === 1) {\n this.#rowEdits.delete(key);\n } else {\n // re-editing a cell had removed the edit\n cellEdits.delete(columnName);\n }\n this.editCount = this.#editCount - 1;\n } else {\n cellEdit.editedValue = newValue;\n }\n } else {\n cellEdits.set(columnName, {\n originalValue,\n editedValue: newValue,\n });\n this.editCount = this.#editCount + 1;\n }\n }\n\n async commit(\n key: string,\n columnName: string,\n originalValue: VuuRowDataItemType,\n typedValue: string | number | boolean,\n isValid: boolean,\n ) {\n const rowEditDetails = this.getRowEdits(key);\n\n if (isValid) {\n const { cellEdits } = rowEditDetails;\n const cellEdit = this.storeCellEdit(\n cellEdits,\n columnName,\n originalValue,\n typedValue,\n isValid,\n );\n\n const response = await this.dataSource?.editCell?.(\n key,\n columnName,\n typedValue,\n );\n if (isRpcError(response)) {\n cellEdit.isValid = false;\n this.invalidCount += 1;\n }\n\n return response;\n } else {\n if (rowEditDetails) {\n const { cellEdits } = rowEditDetails;\n const cellEditValues = cellEdits.get(columnName);\n if (cellEditValues && cellEditValues.isValid !== false) {\n cellEditValues.isValid = false;\n this.invalidCount += 1;\n }\n }\n console.log(\n `[EditSession] key ${key}, column ${columnName} is valid ? ${isValid} `,\n );\n }\n }\n}\n"],"names":["rowEditDetails","cellEdit"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"EditSession.js","sources":["../../../../../../../packages/vuu-utils/src/data-editing/EditSession.tsx"],"sourcesContent":["import { EditApi, EditSessionMode } from \"@vuu-ui/vuu-data-types\";\nimport type { VuuRowDataItemType } from \"@vuu-ui/vuu-protocol-types\";\nimport { EventEmitter } from \"../event-emitter\";\nimport { isRpcError } from \"../protocol-message-utils\";\n\nexport type EditState = \"clean\" | \"dirty\" | \"invalid\" | \"stale\";\n\nexport class EditError extends Error {}\n\ntype CellEdit = {\n originalValue: VuuRowDataItemType;\n editedValue: VuuRowDataItemType;\n isValid?: boolean;\n isDeleted?: boolean;\n};\n\n// TODO can add more when when we know what the server implementation of error columns will look like\nexport class StaleUpdateError extends Error {}\n\ntype RowEditDetails = {\n /**\n * Column name => cell edit details\n */\n cellEdits: Map<string, CellEdit>;\n};\n\ntype EditSessionEvents = {\n editState: (editState: EditState) => void;\n};\n\nexport class EditSession extends EventEmitter<EditSessionEvents> {\n /**\n * Row key => row edits\n */\n #rowEdits = new Map<string, RowEditDetails>();\n #editCount = 0;\n #invalidCount = 0;\n #sourceTableDataSource?: EditApi;\n #sessionDataSource?: EditApi;\n #inEditMode = false;\n\n constructor(dataSource: EditApi) {\n super();\n this.#sourceTableDataSource = dataSource;\n }\n\n get editCount() {\n return this.#editCount;\n }\n\n set editCount(val: number) {\n if (val !== this.#editCount) {\n const oldCount = this.#editCount;\n this.#editCount = val;\n if (val === 0) {\n this.emit(\"editState\", \"clean\");\n } else if (oldCount === 0) {\n this.emit(\"editState\", \"dirty\");\n }\n }\n }\n\n get invalidCount() {\n return this.#invalidCount;\n }\n\n set invalidCount(val: number) {\n if (val !== this.#invalidCount) {\n const oldCount = this.#invalidCount;\n this.#invalidCount = val;\n if (val === 0) {\n this.emit(\"editState\", this.#editCount === 0 ? \"clean\" : \"dirty\");\n } else if (oldCount === 0) {\n this.emit(\"editState\", \"invalid\");\n }\n }\n }\n\n clear() {\n this.#rowEdits.clear();\n this.#editCount = 0;\n this.#inEditMode = false;\n }\n\n async begin(editSessionMode?: EditSessionMode) {\n try {\n this.#inEditMode = true;\n const sessionDataSource =\n await this.#sourceTableDataSource?.beginEditSession?.(editSessionMode);\n\n this.#sessionDataSource = sessionDataSource;\n\n return sessionDataSource;\n } catch (e) {\n this.#inEditMode = false;\n }\n }\n\n get dataSource() {\n return this.#sessionDataSource ?? this.#sourceTableDataSource;\n }\n\n async end(saveChanges = false, force = false) {\n try {\n if (this.#inEditMode) {\n await this.dataSource?.endEditSession?.(saveChanges, force);\n this.clear();\n }\n } catch (e) {\n if (e instanceof StaleUpdateError) {\n this.emit(\"editState\", \"stale\");\n } else {\n console.error(`[EditSession] ${(e as Error).message}`);\n }\n }\n }\n\n get inEditMode() {\n return this.#inEditMode;\n }\n\n get editState(): EditState {\n return this.editCount === 0 ? \"clean\" : \"dirty\";\n }\n\n getOrCreateRowEdits(key: string): RowEditDetails {\n const rowEditDetails = this.#rowEdits.get(key);\n if (rowEditDetails) {\n return rowEditDetails;\n } else {\n const rowEditDetails = {\n cellEdits: new Map(),\n };\n this.#rowEdits.set(key, rowEditDetails);\n return rowEditDetails;\n }\n }\n\n storeCellEdit(\n cellEdits: Map<string, CellEdit>,\n column: string,\n originalValue: VuuRowDataItemType,\n editedValue: VuuRowDataItemType,\n isValid: boolean,\n ) {\n const cellEdit = cellEdits.get(column);\n if (cellEdit) {\n if (cellEdit.originalValue === editedValue) {\n cellEdits.delete(column);\n cellEdit.isDeleted = true;\n if (cellEdit.isValid) {\n this.editCount -= 1;\n } else {\n this.invalidCount -= 1;\n }\n } else {\n if (isValid && cellEdit.isValid === false) {\n cellEdit.isValid = true;\n cellEdit.editedValue = editedValue;\n // do not trigger the event, save it for the editCount\n this.#invalidCount -= 1;\n this.editCount += 1;\n }\n }\n return cellEdit;\n } else {\n const cellEdit: CellEdit = {\n originalValue,\n editedValue,\n isValid,\n };\n cellEdits.set(column, cellEdit);\n if (isValid) {\n this.editCount += 1;\n }\n return cellEdit;\n }\n }\n\n async commit(\n key: string,\n columnName: string,\n originalValue: VuuRowDataItemType,\n typedValue: string | number | boolean,\n isValid: boolean,\n ) {\n if (!this.#inEditMode) {\n throw new Error(\"No edit session in progress\");\n }\n const rowEditDetails = this.getOrCreateRowEdits(key);\n\n if (isValid) {\n const { cellEdits } = rowEditDetails;\n\n const cellEdit = this.storeCellEdit(\n cellEdits,\n columnName,\n originalValue,\n typedValue,\n isValid,\n );\n\n if (cellEdit.isDeleted) {\n if (rowEditDetails.cellEdits.size === 0) {\n this.#rowEdits.delete(key);\n }\n }\n\n if (this.dataSource?.editCell) {\n const response = await this.dataSource.editCell(\n key,\n columnName,\n typedValue,\n );\n if (isRpcError(response)) {\n cellEdit.isValid = false;\n this.invalidCount += 1;\n }\n\n return {\n editedDuringCurrentSession: cellEdit.originalValue !== typedValue,\n ...response,\n };\n }\n } else {\n const { cellEdits } = rowEditDetails;\n let cellEdit = cellEdits.get(columnName);\n if (cellEdit && cellEdit.isValid !== false) {\n cellEdit.isValid = false;\n this.invalidCount += 1;\n } else if (cellEdit === undefined) {\n cellEdit = this.storeCellEdit(\n cellEdits,\n columnName,\n originalValue,\n typedValue,\n isValid,\n );\n this.invalidCount += 1;\n }\n return { editedDuringCurrentSession: false };\n }\n }\n}\n"],"names":["rowEditDetails","cellEdit"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { partition } from './array-utils.js';
|
|
2
2
|
import { wordify } from './text-utils.js';
|
|
3
|
-
import
|
|
3
|
+
import React from 'react';
|
|
4
4
|
import { getLayoutComponent } from './component-registry.js';
|
|
5
5
|
|
|
6
6
|
const env = process.env.NODE_ENV;
|
|
@@ -13,7 +13,7 @@ function featureFromJson({ type }) {
|
|
|
13
13
|
`layoutUtils unable to create feature component from JSON, unknown type ${type}`
|
|
14
14
|
);
|
|
15
15
|
}
|
|
16
|
-
return
|
|
16
|
+
return React.createElement(componentType);
|
|
17
17
|
}
|
|
18
18
|
const isCustomFeature = (feature) => feature.leftNavLocation === "vuu-features";
|
|
19
19
|
const isWildcardSchema = (vuuTables) => vuuTables === "*";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-utils.js","sources":["../../../../../../packages/vuu-utils/src/feature-utils.ts"],"sourcesContent":["import type { TableSchema } from \"@vuu-ui/vuu-data-types\";\nimport type { VuuTable } from \"@vuu-ui/vuu-protocol-types\";\nimport { ListOption } from \"@vuu-ui/vuu-table-types\";\nimport { partition } from \"./array-utils\";\nimport { wordify } from \"./text-utils\";\nimport React, { ReactElement } from \"react\";\nimport { getLayoutComponent } from \"./component-registry\";\n\nexport type PathMap = {\n [key: string]: Pick<DynamicFeatureDescriptor, \"css\" | \"url\">;\n};\nexport type Environment = \"development\" | \"production\";\nexport const env = process.env.NODE_ENV as Environment;\n\nexport type LookupTableProvider = (table: VuuTable) => ListOption[];\n\nexport interface ViewConfig {\n allowRename?: boolean;\n closeable?: boolean;\n header?: boolean;\n}\n\nexport interface DynamicFeatureProps<P extends object | undefined = object> {\n /**\n props that will be passed to the lazily loaded component.\n */\n ComponentProps?: P;\n ViewProps?: ViewConfig;\n css?: string;\n height?: number;\n title?: string;\n /** \n The url of javascript bundle to lazily load. Bundle must provide a default export\n and that export must be a React component.\n */\n url: string;\n width?: number;\n}\n\ndeclare global {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n const vuuConfig: Promise<VuuConfig>;\n}\n\nexport interface DynamicFeatureDescriptor {\n /**\n * url for css file for feature\n */\n css?: string;\n featureProps?: {\n vuuTables?: \"*\" | VuuTable[];\n };\n leftNavLocation: \"vuu-features\" | \"vuu-tables\";\n name: string;\n title: string;\n /**\n * url for javascript bundle to load feature\n */\n url: string;\n viewProps?: ViewConfig;\n}\n\nexport interface StaticFeatureDescriptor {\n group?: string;\n label: string;\n type: string;\n}\n\nconst isStaticFeature = (\n feature: unknown,\n): feature is StaticFeatureDescriptor =>\n feature !== null && typeof feature === \"object\" && \"type\" in feature;\n\nexport const isStaticFeatures = (\n features: unknown,\n): features is StaticFeatureDescriptor[] =>\n Array.isArray(features) && features.every(isStaticFeature);\n\nexport interface FilterTableFeatureProps {\n tableSchema: TableSchema;\n}\n\nexport type DynamicFeatures = {\n [key: string]: DynamicFeatureDescriptor;\n};\n\nexport function featureFromJson({ type }: { type: string }): ReactElement {\n const componentType = type.match(/^[a-z]/) ? type : getLayoutComponent(type);\n if (componentType === undefined) {\n throw Error(\n `layoutUtils unable to create feature component from JSON, unknown type ${type}`,\n );\n }\n return React.createElement(componentType);\n}\n\nexport interface VuuConfig {\n features: DynamicFeatures;\n authUrl?: string;\n websocketUrl: string;\n ssl: boolean;\n}\n\n/**\n * We currently categorize 'features' simply by the leftNavLocation\n * @param feature\n * @returns\n */\nexport const isCustomFeature = (feature: DynamicFeatureDescriptor) =>\n feature.leftNavLocation === \"vuu-features\";\n\nexport const isWildcardSchema = (\n vuuTables?: \"*\" | VuuTable[],\n): vuuTables is \"*\" => vuuTables === \"*\";\nexport const isVuuTables = (\n vuuTables?: \"*\" | VuuTable[],\n): vuuTables is VuuTable[] => Array.isArray(vuuTables);\n\nexport interface FeaturePropsWithFilterTableFeature\n extends Omit<DynamicFeatureProps, \"ComponentProps\"> {\n ComponentProps: FilterTableFeatureProps;\n}\n\nexport const hasFilterTableFeatureProps = (\n props: DynamicFeatureProps,\n): props is FeaturePropsWithFilterTableFeature =>\n typeof props.ComponentProps === \"object\" &&\n props.ComponentProps !== null &&\n \"tableSchema\" in props.ComponentProps;\n\nexport const isSameTable = (t1: VuuTable, t2: VuuTable) => {\n t1.module === t2.module && t1.table == t2.table;\n};\n\n// Sort TableScheas by module\nexport const byModule = (schema1: TableSchema, schema2: TableSchema) => {\n const m1 = schema1.table.module.toLowerCase();\n const m2 = schema2.table.module.toLowerCase();\n if (m1 < m2) {\n return -1;\n } else if (m1 > m2) {\n return 1;\n } else if (schema1.table.table < schema2.table.table) {\n return -1;\n } else if (schema1.table.table > schema2.table.table) {\n return 1;\n } else {\n return 0;\n }\n};\n\nexport type GetFeaturePaths = (params: {\n env: Environment;\n fileName: string;\n withCss?: boolean;\n}) => DynamicFeatureProps;\n\nexport const getFilterTableFeatures = (\n schemas: TableSchema[],\n getFeaturePath: GetFeaturePaths,\n) =>\n schemas\n .sort(byModule)\n .map<DynamicFeatureProps<FilterTableFeatureProps>>((schema) => ({\n ...getFeaturePath({ env, fileName: \"FilterTable\" }),\n ComponentProps: {\n tableSchema: schema,\n },\n ViewProps: {\n allowRename: true,\n },\n title: `${schema.table.module} ${schema.table.table}`,\n }));\n\nexport type Component = {\n componentName: string;\n component: unknown;\n};\n\nexport const assertComponentRegistered = (\n componentName: string,\n component: unknown,\n) => {\n if (typeof component !== \"function\") {\n console.warn(\n `${componentName} module not loaded, will be unabale to deserialize from layout JSON`,\n );\n }\n};\n\nexport const assertComponentsRegistered = (componentList: Component[]) => {\n for (const { componentName, component } of componentList) {\n assertComponentRegistered(componentName, component);\n }\n};\n/**\n * Process the DynamicFeature descriptors. Identify\n * the vuu tables required and inject the appropriate TableSchemas\n *\n * @param dynamicFeatures\n * @param tableSchemas\n * @returns\n */\nexport const getCustomAndTableFeatures = (\n dynamicFeatures: DynamicFeatureDescriptor[],\n tableSchemas: TableSchema[],\n): {\n dynamicFeatures: DynamicFeatureProps[];\n tableFeatures: DynamicFeatureProps<FilterTableFeatureProps>[];\n} => {\n // Split features into simple tables and 'custom' features\n const [customFeatureConfig, tableFeaturesConfig] = partition(\n dynamicFeatures,\n isCustomFeature,\n );\n\n const customFeatures: DynamicFeatureProps[] = [];\n const tableFeatures: DynamicFeatureProps<FilterTableFeatureProps>[] = [];\n\n for (const {\n featureProps = {},\n viewProps,\n ...feature\n } of tableFeaturesConfig) {\n const { vuuTables } = featureProps;\n // Currently FilterTable is the only 'tableFeature' and it uses the wildcard\n if (isWildcardSchema(vuuTables)) {\n if (tableSchemas) {\n for (const tableSchema of tableSchemas) {\n tableFeatures.push({\n ...feature,\n ComponentProps: {\n tableSchema,\n },\n title: `${tableSchema.table.module} ${wordify(\n tableSchema.table.table,\n )}`,\n ViewProps: {\n ...viewProps,\n allowRename: true,\n },\n });\n }\n }\n }\n }\n\n for (const {\n featureProps = {},\n viewProps,\n ...feature\n } of customFeatureConfig) {\n const { vuuTables } = featureProps;\n if (isVuuTables(vuuTables)) {\n if (tableSchemas) {\n customFeatures.push({\n ...feature,\n ComponentProps: vuuTables.reduce<Record<string, TableSchema>>(\n (map, vuuTable) => {\n map[`${vuuTable.table}Schema`] = tableSchemas.find(\n (tableSchema) => isSameTable(vuuTable, tableSchema.table),\n ) as TableSchema;\n return map;\n },\n {},\n ),\n ViewProps: viewProps,\n });\n }\n } else {\n customFeatures.push(feature);\n }\n }\n return { dynamicFeatures: customFeatures, tableFeatures: tableFeatures };\n};\n"],"names":["React"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"feature-utils.js","sources":["../../../../../../packages/vuu-utils/src/feature-utils.ts"],"sourcesContent":["import type { TableSchema } from \"@vuu-ui/vuu-data-types\";\nimport type { VuuTable } from \"@vuu-ui/vuu-protocol-types\";\nimport { ListOption } from \"@vuu-ui/vuu-table-types\";\nimport { partition } from \"./array-utils\";\nimport { wordify } from \"./text-utils\";\nimport React, { ReactElement } from \"react\";\nimport { getLayoutComponent } from \"./component-registry\";\n\nexport type PathMap = {\n [key: string]: Pick<DynamicFeatureDescriptor, \"css\" | \"url\">;\n};\nexport type Environment = \"development\" | \"production\";\nexport const env = process.env.NODE_ENV as Environment;\n\nexport type LookupTableProvider = (table: VuuTable) => ListOption[];\n\nexport interface ViewConfig {\n allowRename?: boolean;\n closeable?: boolean;\n header?: boolean;\n}\n\nexport interface DynamicFeatureProps<P extends object | undefined = object> {\n /**\n props that will be passed to the lazily loaded component.\n */\n ComponentProps?: P;\n ViewProps?: ViewConfig;\n css?: string;\n height?: number;\n title?: string;\n /** \n The url of javascript bundle to lazily load. Bundle must provide a default export\n and that export must be a React component.\n */\n url: string;\n width?: number;\n}\n\ndeclare global {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n const vuuConfig: Promise<VuuConfig>;\n}\n\nexport interface DynamicFeatureDescriptor {\n /**\n * url for css file for feature\n */\n css?: string;\n featureProps?: {\n vuuTables?: \"*\" | VuuTable[];\n };\n leftNavLocation: \"vuu-features\" | \"vuu-tables\";\n name: string;\n title: string;\n /**\n * url for javascript bundle to load feature\n */\n url: string;\n viewProps?: ViewConfig;\n}\n\nexport interface StaticFeatureDescriptor {\n group?: string;\n label: string;\n type: string;\n}\n\nconst isStaticFeature = (\n feature: unknown,\n): feature is StaticFeatureDescriptor =>\n feature !== null && typeof feature === \"object\" && \"type\" in feature;\n\nexport const isStaticFeatures = (\n features: unknown,\n): features is StaticFeatureDescriptor[] =>\n Array.isArray(features) && features.every(isStaticFeature);\n\nexport interface FilterTableFeatureProps {\n tableSchema: TableSchema;\n}\n\nexport type DynamicFeatures = {\n [key: string]: DynamicFeatureDescriptor;\n};\n\nexport function featureFromJson({ type }: { type: string }): ReactElement {\n const componentType = type.match(/^[a-z]/) ? type : getLayoutComponent(type);\n if (componentType === undefined) {\n throw Error(\n `layoutUtils unable to create feature component from JSON, unknown type ${type}`,\n );\n }\n return React.createElement(componentType);\n}\n\nexport interface VuuConfig {\n features: DynamicFeatures;\n authUrl?: string;\n websocketUrl: string;\n ssl: boolean;\n}\n\n/**\n * We currently categorize 'features' simply by the leftNavLocation\n * @param feature\n * @returns\n */\nexport const isCustomFeature = (feature: DynamicFeatureDescriptor) =>\n feature.leftNavLocation === \"vuu-features\";\n\nexport const isWildcardSchema = (\n vuuTables?: \"*\" | VuuTable[],\n): vuuTables is \"*\" => vuuTables === \"*\";\nexport const isVuuTables = (\n vuuTables?: \"*\" | VuuTable[],\n): vuuTables is VuuTable[] => Array.isArray(vuuTables);\n\nexport interface FeaturePropsWithFilterTableFeature\n extends Omit<DynamicFeatureProps, \"ComponentProps\"> {\n ComponentProps: FilterTableFeatureProps;\n}\n\nexport const hasFilterTableFeatureProps = (\n props: DynamicFeatureProps,\n): props is FeaturePropsWithFilterTableFeature =>\n typeof props.ComponentProps === \"object\" &&\n props.ComponentProps !== null &&\n \"tableSchema\" in props.ComponentProps;\n\nexport const isSameTable = (t1: VuuTable, t2: VuuTable) => {\n t1.module === t2.module && t1.table == t2.table;\n};\n\n// Sort TableScheas by module\nexport const byModule = (schema1: TableSchema, schema2: TableSchema) => {\n const m1 = schema1.table.module.toLowerCase();\n const m2 = schema2.table.module.toLowerCase();\n if (m1 < m2) {\n return -1;\n } else if (m1 > m2) {\n return 1;\n } else if (schema1.table.table < schema2.table.table) {\n return -1;\n } else if (schema1.table.table > schema2.table.table) {\n return 1;\n } else {\n return 0;\n }\n};\n\nexport type GetFeaturePaths = (params: {\n env: Environment;\n fileName: string;\n withCss?: boolean;\n}) => DynamicFeatureProps;\n\nexport const getFilterTableFeatures = (\n schemas: TableSchema[],\n getFeaturePath: GetFeaturePaths,\n) =>\n schemas\n .sort(byModule)\n .map<DynamicFeatureProps<FilterTableFeatureProps>>((schema) => ({\n ...getFeaturePath({ env, fileName: \"FilterTable\" }),\n ComponentProps: {\n tableSchema: schema,\n },\n ViewProps: {\n allowRename: true,\n },\n title: `${schema.table.module} ${schema.table.table}`,\n }));\n\nexport type Component = {\n componentName: string;\n component: unknown;\n};\n\nexport const assertComponentRegistered = (\n componentName: string,\n component: unknown,\n) => {\n if (typeof component !== \"function\") {\n console.warn(\n `${componentName} module not loaded, will be unabale to deserialize from layout JSON`,\n );\n }\n};\n\nexport const assertComponentsRegistered = (componentList: Component[]) => {\n for (const { componentName, component } of componentList) {\n assertComponentRegistered(componentName, component);\n }\n};\n/**\n * Process the DynamicFeature descriptors. Identify\n * the vuu tables required and inject the appropriate TableSchemas\n *\n * @param dynamicFeatures\n * @param tableSchemas\n * @returns\n */\nexport const getCustomAndTableFeatures = (\n dynamicFeatures: DynamicFeatureDescriptor[],\n tableSchemas: TableSchema[],\n): {\n dynamicFeatures: DynamicFeatureProps[];\n tableFeatures: DynamicFeatureProps<FilterTableFeatureProps>[];\n} => {\n // Split features into simple tables and 'custom' features\n const [customFeatureConfig, tableFeaturesConfig] = partition(\n dynamicFeatures,\n isCustomFeature,\n );\n\n const customFeatures: DynamicFeatureProps[] = [];\n const tableFeatures: DynamicFeatureProps<FilterTableFeatureProps>[] = [];\n\n for (const {\n featureProps = {},\n viewProps,\n ...feature\n } of tableFeaturesConfig) {\n const { vuuTables } = featureProps;\n // Currently FilterTable is the only 'tableFeature' and it uses the wildcard\n if (isWildcardSchema(vuuTables)) {\n if (tableSchemas) {\n for (const tableSchema of tableSchemas) {\n tableFeatures.push({\n ...feature,\n ComponentProps: {\n tableSchema,\n },\n title: `${tableSchema.table.module} ${wordify(\n tableSchema.table.table,\n )}`,\n ViewProps: {\n ...viewProps,\n allowRename: true,\n },\n });\n }\n }\n }\n }\n\n for (const {\n featureProps = {},\n viewProps,\n ...feature\n } of customFeatureConfig) {\n const { vuuTables } = featureProps;\n if (isVuuTables(vuuTables)) {\n if (tableSchemas) {\n customFeatures.push({\n ...feature,\n ComponentProps: vuuTables.reduce<Record<string, TableSchema>>(\n (map, vuuTable) => {\n map[`${vuuTable.table}Schema`] = tableSchemas.find(\n (tableSchema) => isSameTable(vuuTable, tableSchema.table),\n ) as TableSchema;\n return map;\n },\n {},\n ),\n ViewProps: viewProps,\n });\n }\n } else {\n customFeatures.push(feature);\n }\n }\n return { dynamicFeatures: customFeatures, tableFeatures: tableFeatures };\n};\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2.1.
|
|
2
|
+
"version": "2.1.16",
|
|
3
3
|
"author": "heswell",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"types": "types/index.d.ts",
|
|
@@ -7,14 +7,14 @@
|
|
|
7
7
|
"@salt-ds/core": "1.54.1"
|
|
8
8
|
},
|
|
9
9
|
"devDependencies": {
|
|
10
|
-
"@vuu-ui/vuu-data-types": "2.1.
|
|
11
|
-
"@vuu-ui/vuu-table-types": "2.1.
|
|
12
|
-
"@vuu-ui/vuu-filter-types": "2.1.
|
|
13
|
-
"@vuu-ui/vuu-protocol-types": "2.1.
|
|
10
|
+
"@vuu-ui/vuu-data-types": "2.1.16",
|
|
11
|
+
"@vuu-ui/vuu-table-types": "2.1.16",
|
|
12
|
+
"@vuu-ui/vuu-filter-types": "2.1.16",
|
|
13
|
+
"@vuu-ui/vuu-protocol-types": "2.1.16"
|
|
14
14
|
},
|
|
15
15
|
"peerDependencies": {
|
|
16
16
|
"@internationalized/date": "^3.0.0",
|
|
17
|
-
"@vuu-ui/vuu-filter-parser": "2.1.
|
|
17
|
+
"@vuu-ui/vuu-filter-parser": "2.1.16",
|
|
18
18
|
"clsx": "^2.0.0",
|
|
19
19
|
"react": "^19.2.3",
|
|
20
20
|
"react-dom": "^19.2.3"
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { EditApi, EditSessionMode } from "@vuu-ui/vuu-data-types";
|
|
2
2
|
import type { VuuRowDataItemType } from "@vuu-ui/vuu-protocol-types";
|
|
3
3
|
import { EventEmitter } from "../event-emitter";
|
|
4
4
|
export type EditState = "clean" | "dirty" | "invalid" | "stale";
|
|
5
|
+
export declare class EditError extends Error {
|
|
6
|
+
}
|
|
5
7
|
type CellEdit = {
|
|
6
8
|
originalValue: VuuRowDataItemType;
|
|
7
9
|
editedValue: VuuRowDataItemType;
|
|
8
10
|
isValid?: boolean;
|
|
11
|
+
isDeleted?: boolean;
|
|
9
12
|
};
|
|
10
13
|
export declare class StaleUpdateError extends Error {
|
|
11
14
|
}
|
|
@@ -20,29 +23,19 @@ type EditSessionEvents = {
|
|
|
20
23
|
};
|
|
21
24
|
export declare class EditSession extends EventEmitter<EditSessionEvents> {
|
|
22
25
|
#private;
|
|
23
|
-
constructor(dataSource:
|
|
26
|
+
constructor(dataSource: EditApi);
|
|
24
27
|
get editCount(): number;
|
|
25
28
|
set editCount(val: number);
|
|
26
29
|
get invalidCount(): number;
|
|
27
30
|
set invalidCount(val: number);
|
|
28
31
|
clear(): void;
|
|
29
|
-
begin(editSessionMode?: EditSessionMode): Promise<DataSource | undefined>;
|
|
30
|
-
get dataSource():
|
|
32
|
+
begin(editSessionMode?: EditSessionMode): Promise<import("@vuu-ui/vuu-data-types").DataSource | undefined>;
|
|
33
|
+
get dataSource(): EditApi | undefined;
|
|
31
34
|
end(saveChanges?: boolean, force?: boolean): Promise<void>;
|
|
32
35
|
get inEditMode(): boolean;
|
|
33
36
|
get editState(): EditState;
|
|
34
|
-
|
|
37
|
+
getOrCreateRowEdits(key: string): RowEditDetails;
|
|
35
38
|
storeCellEdit(cellEdits: Map<string, CellEdit>, column: string, originalValue: VuuRowDataItemType, editedValue: VuuRowDataItemType, isValid: boolean): CellEdit;
|
|
36
|
-
/**
|
|
37
|
-
* Apply incremental edit(s) to edit control value. Used for TextInput, where multiple
|
|
38
|
-
* edits may follow in sequence before value finally committed.
|
|
39
|
-
*
|
|
40
|
-
* @param key value for edited Row
|
|
41
|
-
* @param columnName
|
|
42
|
-
* @param originalValue
|
|
43
|
-
* @param newValue
|
|
44
|
-
*/
|
|
45
|
-
edit(key: string, columnName: string, originalValue: VuuRowDataItemType, newValue: VuuRowDataItemType): void;
|
|
46
39
|
commit(key: string, columnName: string, originalValue: VuuRowDataItemType, typedValue: string | number | boolean, isValid: boolean): Promise<any>;
|
|
47
40
|
}
|
|
48
41
|
export {};
|