@pallasoft/ps-core-components 2.46.1 → 2.47.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/ps-data-boundary.d.ts +2 -1
- package/dist/components/ps-data-boundary.js +2 -2
- package/dist/components/ps-empty-value.d.ts +5 -0
- package/dist/components/ps-empty-value.js +8 -0
- package/dist/components/ps-image.d.ts +14 -0
- package/dist/components/ps-image.js +29 -0
- package/dist/components/ps-signed-value.d.ts +6 -0
- package/dist/components/ps-signed-value.js +9 -0
- package/dist/constants/ps-empty-value-config.d.ts +4 -0
- package/dist/constants/ps-empty-value-config.js +7 -0
- package/dist/constants/ps-image-config.d.ts +7 -0
- package/dist/constants/ps-image-config.js +10 -0
- package/dist/constants/ps-image-fit.d.ts +7 -0
- package/dist/constants/ps-image-fit.js +11 -0
- package/dist/constants/ps-image-status.d.ts +5 -0
- package/dist/constants/ps-image-status.js +9 -0
- package/dist/constants/ps-signed-value-classes.d.ts +2 -0
- package/dist/constants/ps-signed-value-classes.js +9 -0
- package/dist/esm/components/ps-data-boundary.js +2 -2
- package/dist/esm/components/ps-empty-value.js +4 -0
- package/dist/esm/components/ps-image.js +25 -0
- package/dist/esm/components/ps-signed-value.js +5 -0
- package/dist/esm/constants/ps-empty-value-config.js +4 -0
- package/dist/esm/constants/ps-image-config.js +7 -0
- package/dist/esm/constants/ps-image-fit.js +8 -0
- package/dist/esm/constants/ps-image-status.js +6 -0
- package/dist/esm/constants/ps-signed-value-classes.js +6 -0
- package/dist/esm/hooks/use-ps-cursor-pages.js +82 -0
- package/dist/esm/hooks/use-ps-draft-state.js +18 -0
- package/dist/esm/hooks/use-ps-remote-read.js +31 -0
- package/dist/esm/hooks/use-ps-text-param.js +16 -0
- package/dist/esm/index.js +30 -0
- package/dist/esm/interfaces/ps-cursor-pages-input.js +1 -0
- package/dist/esm/interfaces/ps-cursor-pages-result.js +1 -0
- package/dist/esm/interfaces/ps-draft-state-options.js +1 -0
- package/dist/esm/interfaces/ps-draft-state-result.js +1 -0
- package/dist/esm/interfaces/ps-remote-read-input.js +1 -0
- package/dist/esm/interfaces/ps-remote-read-result.js +1 -0
- package/dist/esm/models/ps-cursor-pages-state.js +1 -0
- package/dist/esm/models/ps-draft-state-data.js +1 -0
- package/dist/esm/models/ps-image-state-data.js +1 -0
- package/dist/esm/models/ps-remote-read-state.js +1 -0
- package/dist/esm/models/ps-remote-settled-data.js +1 -0
- package/dist/esm/models/ps-text-param-data.js +1 -0
- package/dist/esm/models/ps-text-param-options.js +1 -0
- package/dist/esm/services/ps-cursor-pages-service.js +14 -0
- package/dist/esm/services/ps-draft-state-service.js +11 -0
- package/dist/esm/services/ps-image-service.js +11 -0
- package/dist/esm/services/ps-remote-read-service.js +19 -0
- package/dist/esm/services/ps-signed-value-service.js +13 -0
- package/dist/hooks/use-ps-cursor-pages.d.ts +3 -0
- package/dist/hooks/use-ps-cursor-pages.js +86 -0
- package/dist/hooks/use-ps-draft-state.d.ts +3 -0
- package/dist/hooks/use-ps-draft-state.js +22 -0
- package/dist/hooks/use-ps-remote-read.d.ts +3 -0
- package/dist/hooks/use-ps-remote-read.js +35 -0
- package/dist/hooks/use-ps-text-param.d.ts +4 -0
- package/dist/hooks/use-ps-text-param.js +20 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.js +30 -0
- package/dist/interfaces/ps-cursor-pages-input.d.ts +8 -0
- package/dist/interfaces/ps-cursor-pages-input.js +2 -0
- package/dist/interfaces/ps-cursor-pages-result.d.ts +7 -0
- package/dist/interfaces/ps-cursor-pages-result.js +2 -0
- package/dist/interfaces/ps-draft-state-options.d.ts +3 -0
- package/dist/interfaces/ps-draft-state-options.js +2 -0
- package/dist/interfaces/ps-draft-state-result.d.ts +7 -0
- package/dist/interfaces/ps-draft-state-result.js +2 -0
- package/dist/interfaces/ps-remote-read-input.d.ts +5 -0
- package/dist/interfaces/ps-remote-read-input.js +2 -0
- package/dist/interfaces/ps-remote-read-result.d.ts +5 -0
- package/dist/interfaces/ps-remote-read-result.js +2 -0
- package/dist/models/ps-cursor-pages-state.d.ts +8 -0
- package/dist/models/ps-cursor-pages-state.js +2 -0
- package/dist/models/ps-draft-state-data.d.ts +4 -0
- package/dist/models/ps-draft-state-data.js +2 -0
- package/dist/models/ps-image-state-data.d.ts +5 -0
- package/dist/models/ps-image-state-data.js +2 -0
- package/dist/models/ps-remote-read-state.d.ts +6 -0
- package/dist/models/ps-remote-read-state.js +2 -0
- package/dist/models/ps-remote-settled-data.d.ts +4 -0
- package/dist/models/ps-remote-settled-data.js +2 -0
- package/dist/models/ps-text-param-data.d.ts +5 -0
- package/dist/models/ps-text-param-data.js +2 -0
- package/dist/models/ps-text-param-options.d.ts +5 -0
- package/dist/models/ps-text-param-options.js +2 -0
- package/dist/services/ps-cursor-pages-service.d.ts +6 -0
- package/dist/services/ps-cursor-pages-service.js +18 -0
- package/dist/services/ps-draft-state-service.d.ts +6 -0
- package/dist/services/ps-draft-state-service.js +15 -0
- package/dist/services/ps-image-service.d.ts +6 -0
- package/dist/services/ps-image-service.js +15 -0
- package/dist/services/ps-remote-read-service.d.ts +8 -0
- package/dist/services/ps-remote-read-service.js +23 -0
- package/dist/services/ps-signed-value-service.d.ts +5 -0
- package/dist/services/ps-signed-value-service.js +17 -0
- package/package.json +2 -2
|
@@ -4,6 +4,7 @@ export interface PsDataBoundaryProps<Data> {
|
|
|
4
4
|
AwaitComponent: ElementType;
|
|
5
5
|
children: (data: Data, isPending: boolean) => ReactNode;
|
|
6
6
|
className?: string;
|
|
7
|
+
dimWhenPending?: boolean;
|
|
7
8
|
errorElement: ReactNode;
|
|
8
9
|
fallback: ReactNode;
|
|
9
10
|
resolve: Promise<Data>;
|
|
@@ -11,4 +12,4 @@ export interface PsDataBoundaryProps<Data> {
|
|
|
11
12
|
retainKey?: string;
|
|
12
13
|
variant?: PsDataBoundaryVariant;
|
|
13
14
|
}
|
|
14
|
-
export declare const PsDataBoundary: <Data>({ AwaitComponent, children, className, errorElement, fallback, resolve, retain, retainKey, variant, }: PsDataBoundaryProps<Data>) => import("react").JSX.Element;
|
|
15
|
+
export declare const PsDataBoundary: <Data>({ AwaitComponent, children, className, dimWhenPending, errorElement, fallback, resolve, retain, retainKey, variant, }: PsDataBoundaryProps<Data>) => import("react").JSX.Element;
|
|
@@ -6,7 +6,7 @@ const react_1 = require("react");
|
|
|
6
6
|
const ps_design_system_1 = require("@pallasoft/ps-design-system");
|
|
7
7
|
const ps_data_boundary_config_1 = require("../constants/ps-data-boundary-config");
|
|
8
8
|
const ps_data_boundary_variant_1 = require("../constants/ps-data-boundary-variant");
|
|
9
|
-
const PsDataBoundary = ({ AwaitComponent, children, className, errorElement, fallback, resolve, retain = false, retainKey, variant = ps_data_boundary_variant_1.PsDataBoundaryVariant.Page, }) => {
|
|
9
|
+
const PsDataBoundary = ({ AwaitComponent, children, className, dimWhenPending = false, errorElement, fallback, resolve, retain = false, retainKey, variant = ps_data_boundary_variant_1.PsDataBoundaryVariant.Page, }) => {
|
|
10
10
|
const deferred = (0, react_1.useDeferredValue)({ key: retainKey, resolve });
|
|
11
11
|
const isRetaining = retain && deferred.key === retainKey;
|
|
12
12
|
const shown = isRetaining ? deferred.resolve : resolve;
|
|
@@ -14,6 +14,6 @@ const PsDataBoundary = ({ AwaitComponent, children, className, errorElement, fal
|
|
|
14
14
|
const content = ((0, jsx_runtime_1.jsx)(react_1.Suspense, { fallback: fallback, children: (0, jsx_runtime_1.jsx)(AwaitComponent, { errorElement: errorElement, resolve: shown, children: (data) => children(data, isPending) }) }));
|
|
15
15
|
if (variant === ps_data_boundary_variant_1.PsDataBoundaryVariant.Page)
|
|
16
16
|
return content;
|
|
17
|
-
return ((0, jsx_runtime_1.jsx)("div", { "aria-busy": isPending, className: ps_design_system_1.PallasoftClassNameService.merge(ps_data_boundary_config_1.PsDataBoundaryConfig.sectionClassName, isPending ? ps_data_boundary_config_1.PsDataBoundaryConfig.pendingClassName : null, className), children: content }));
|
|
17
|
+
return ((0, jsx_runtime_1.jsx)("div", { "aria-busy": isPending, className: ps_design_system_1.PallasoftClassNameService.merge(ps_data_boundary_config_1.PsDataBoundaryConfig.sectionClassName, isPending && dimWhenPending ? ps_data_boundary_config_1.PsDataBoundaryConfig.pendingClassName : null, className), children: content }));
|
|
18
18
|
};
|
|
19
19
|
exports.PsDataBoundary = PsDataBoundary;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PsEmptyValue = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const ps_design_system_1 = require("@pallasoft/ps-design-system");
|
|
6
|
+
const ps_empty_value_config_1 = require("../constants/ps-empty-value-config");
|
|
7
|
+
const PsEmptyValue = ({ className, label }) => ((0, jsx_runtime_1.jsxs)("span", { className: ps_design_system_1.PallasoftClassNameService.merge(ps_empty_value_config_1.PsEmptyValueConfig.className, className), children: [(0, jsx_runtime_1.jsx)("span", { "aria-hidden": 'true', children: ps_empty_value_config_1.PsEmptyValueConfig.symbol }), (0, jsx_runtime_1.jsx)("span", { className: 'sr-only', children: label })] }));
|
|
8
|
+
exports.PsEmptyValue = PsEmptyValue;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type ImgHTMLAttributes, type ReactNode } from 'react';
|
|
2
|
+
import type { PsImageFit } from '../constants/ps-image-fit';
|
|
3
|
+
export interface PsImageProps {
|
|
4
|
+
alt: string;
|
|
5
|
+
className?: string;
|
|
6
|
+
errorFallback?: ReactNode;
|
|
7
|
+
fit?: PsImageFit;
|
|
8
|
+
height?: number | string;
|
|
9
|
+
loading?: ImgHTMLAttributes<HTMLImageElement>['loading'];
|
|
10
|
+
radius?: string;
|
|
11
|
+
src: string;
|
|
12
|
+
width?: number | string;
|
|
13
|
+
}
|
|
14
|
+
export declare const PsImage: ({ alt, className, errorFallback, fit, height, loading, radius, src, width, }: PsImageProps) => import("react").JSX.Element | null;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PsImage = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const ps_design_system_1 = require("@pallasoft/ps-design-system");
|
|
7
|
+
const ps_image_config_1 = require("../constants/ps-image-config");
|
|
8
|
+
const ps_image_status_1 = require("../constants/ps-image-status");
|
|
9
|
+
const ps_skeleton_shape_1 = require("../constants/ps-skeleton-shape");
|
|
10
|
+
const use_ps_browser_layout_effect_1 = require("../hooks/use-ps-browser-layout-effect");
|
|
11
|
+
const ps_image_service_1 = require("../services/ps-image-service");
|
|
12
|
+
const ps_skeleton_1 = require("./ps-skeleton");
|
|
13
|
+
const PsImage = ({ alt, className, errorFallback, fit, height, loading, radius, src, width, }) => {
|
|
14
|
+
const element = (0, react_1.useRef)(null);
|
|
15
|
+
const [state, setState] = (0, react_1.useState)({ src, status: ps_image_status_1.PsImageStatus.Loading });
|
|
16
|
+
const status = ps_image_service_1.PsImageService.resolve(state, src);
|
|
17
|
+
(0, use_ps_browser_layout_effect_1.usePsBrowserLayoutEffect)(() => {
|
|
18
|
+
if (element.current === null)
|
|
19
|
+
return;
|
|
20
|
+
const found = ps_image_service_1.PsImageService.statusOf(element.current);
|
|
21
|
+
if (found !== ps_image_status_1.PsImageStatus.Loading)
|
|
22
|
+
setState({ src, status: found });
|
|
23
|
+
}, [src]);
|
|
24
|
+
if (status === ps_image_status_1.PsImageStatus.Error)
|
|
25
|
+
return errorFallback === undefined ? null : (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: errorFallback });
|
|
26
|
+
const isLoaded = status === ps_image_status_1.PsImageStatus.Loaded;
|
|
27
|
+
return ((0, jsx_runtime_1.jsxs)("span", { className: ps_image_config_1.PsImageConfig.rootClassName, style: { borderRadius: radius }, children: [isLoaded ? null : ((0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: ps_image_config_1.PsImageConfig.skeletonClassName, shape: ps_skeleton_shape_1.PsSkeletonShape.Block })), (0, jsx_runtime_1.jsx)("img", { alt: alt, className: ps_design_system_1.PallasoftClassNameService.merge(ps_image_config_1.PsImageConfig.imageClassName, isLoaded ? ps_image_config_1.PsImageConfig.loadedClassName : ps_image_config_1.PsImageConfig.hiddenClassName, className), decoding: 'async', height: height, loading: loading, onError: () => setState({ src, status: ps_image_status_1.PsImageStatus.Error }), onLoad: () => setState({ src, status: ps_image_status_1.PsImageStatus.Loaded }), ref: element, src: src, style: fit === undefined ? undefined : { objectFit: fit }, width: width })] }));
|
|
28
|
+
};
|
|
29
|
+
exports.PsImage = PsImage;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PsSignedValue = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const ps_design_system_1 = require("@pallasoft/ps-design-system");
|
|
6
|
+
const ps_signed_value_classes_1 = require("../constants/ps-signed-value-classes");
|
|
7
|
+
const ps_signed_value_service_1 = require("../services/ps-signed-value-service");
|
|
8
|
+
const PsSignedValue = ({ className, format, value }) => ((0, jsx_runtime_1.jsx)("span", { className: ps_design_system_1.PallasoftClassNameService.merge(ps_signed_value_classes_1.PsSignedValueClasses[ps_signed_value_service_1.PsSignedValueService.direction(value)], className), children: ps_signed_value_service_1.PsSignedValueService.text(value, format) }));
|
|
9
|
+
exports.PsSignedValue = PsSignedValue;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const PsImageConfig: {
|
|
2
|
+
readonly hiddenClassName: "opacity-0";
|
|
3
|
+
readonly imageClassName: "col-start-1 row-start-1";
|
|
4
|
+
readonly loadedClassName: "opacity-100 animate-ps-fade-in motion-reduce:animate-none";
|
|
5
|
+
readonly rootClassName: "inline-grid shrink-0 max-w-full overflow-hidden align-middle";
|
|
6
|
+
readonly skeletonClassName: "col-start-1 row-start-1 h-full w-full rounded-[inherit]";
|
|
7
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PsImageConfig = void 0;
|
|
4
|
+
exports.PsImageConfig = {
|
|
5
|
+
hiddenClassName: 'opacity-0',
|
|
6
|
+
imageClassName: 'col-start-1 row-start-1',
|
|
7
|
+
loadedClassName: 'opacity-100 animate-ps-fade-in motion-reduce:animate-none',
|
|
8
|
+
rootClassName: 'inline-grid shrink-0 max-w-full overflow-hidden align-middle',
|
|
9
|
+
skeletonClassName: 'col-start-1 row-start-1 h-full w-full rounded-[inherit]',
|
|
10
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PsImageFit = void 0;
|
|
4
|
+
var PsImageFit;
|
|
5
|
+
(function (PsImageFit) {
|
|
6
|
+
PsImageFit["Contain"] = "contain";
|
|
7
|
+
PsImageFit["Cover"] = "cover";
|
|
8
|
+
PsImageFit["Fill"] = "fill";
|
|
9
|
+
PsImageFit["None"] = "none";
|
|
10
|
+
PsImageFit["ScaleDown"] = "scale-down";
|
|
11
|
+
})(PsImageFit || (exports.PsImageFit = PsImageFit = {}));
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PsImageStatus = void 0;
|
|
4
|
+
var PsImageStatus;
|
|
5
|
+
(function (PsImageStatus) {
|
|
6
|
+
PsImageStatus["Error"] = "error";
|
|
7
|
+
PsImageStatus["Loaded"] = "loaded";
|
|
8
|
+
PsImageStatus["Loading"] = "loading";
|
|
9
|
+
})(PsImageStatus || (exports.PsImageStatus = PsImageStatus = {}));
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PsSignedValueClasses = void 0;
|
|
4
|
+
const ps_utilities_1 = require("@pallasoft/ps-utilities");
|
|
5
|
+
exports.PsSignedValueClasses = {
|
|
6
|
+
[ps_utilities_1.AmountDirection.In]: 'tabular-nums text-success',
|
|
7
|
+
[ps_utilities_1.AmountDirection.Neutral]: 'tabular-nums text-ink',
|
|
8
|
+
[ps_utilities_1.AmountDirection.Out]: 'tabular-nums text-danger',
|
|
9
|
+
};
|
|
@@ -3,7 +3,7 @@ import { Suspense, useDeferredValue } from 'react';
|
|
|
3
3
|
import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
|
|
4
4
|
import { PsDataBoundaryConfig } from '../constants/ps-data-boundary-config.js';
|
|
5
5
|
import { PsDataBoundaryVariant } from '../constants/ps-data-boundary-variant.js';
|
|
6
|
-
export const PsDataBoundary = ({ AwaitComponent, children, className, errorElement, fallback, resolve, retain = false, retainKey, variant = PsDataBoundaryVariant.Page, }) => {
|
|
6
|
+
export const PsDataBoundary = ({ AwaitComponent, children, className, dimWhenPending = false, errorElement, fallback, resolve, retain = false, retainKey, variant = PsDataBoundaryVariant.Page, }) => {
|
|
7
7
|
const deferred = useDeferredValue({ key: retainKey, resolve });
|
|
8
8
|
const isRetaining = retain && deferred.key === retainKey;
|
|
9
9
|
const shown = isRetaining ? deferred.resolve : resolve;
|
|
@@ -11,5 +11,5 @@ export const PsDataBoundary = ({ AwaitComponent, children, className, errorEleme
|
|
|
11
11
|
const content = (_jsx(Suspense, { fallback: fallback, children: _jsx(AwaitComponent, { errorElement: errorElement, resolve: shown, children: (data) => children(data, isPending) }) }));
|
|
12
12
|
if (variant === PsDataBoundaryVariant.Page)
|
|
13
13
|
return content;
|
|
14
|
-
return (_jsx("div", { "aria-busy": isPending, className: PallasoftClassNameService.merge(PsDataBoundaryConfig.sectionClassName, isPending ? PsDataBoundaryConfig.pendingClassName : null, className), children: content }));
|
|
14
|
+
return (_jsx("div", { "aria-busy": isPending, className: PallasoftClassNameService.merge(PsDataBoundaryConfig.sectionClassName, isPending && dimWhenPending ? PsDataBoundaryConfig.pendingClassName : null, className), children: content }));
|
|
15
15
|
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
|
|
3
|
+
import { PsEmptyValueConfig } from '../constants/ps-empty-value-config.js';
|
|
4
|
+
export const PsEmptyValue = ({ className, label }) => (_jsxs("span", { className: PallasoftClassNameService.merge(PsEmptyValueConfig.className, className), children: [_jsx("span", { "aria-hidden": 'true', children: PsEmptyValueConfig.symbol }), _jsx("span", { className: 'sr-only', children: label })] }));
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useRef, useState } from 'react';
|
|
3
|
+
import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
|
|
4
|
+
import { PsImageConfig } from '../constants/ps-image-config.js';
|
|
5
|
+
import { PsImageStatus } from '../constants/ps-image-status.js';
|
|
6
|
+
import { PsSkeletonShape } from '../constants/ps-skeleton-shape.js';
|
|
7
|
+
import { usePsBrowserLayoutEffect } from '../hooks/use-ps-browser-layout-effect.js';
|
|
8
|
+
import { PsImageService } from '../services/ps-image-service.js';
|
|
9
|
+
import { PsSkeleton } from './ps-skeleton.js';
|
|
10
|
+
export const PsImage = ({ alt, className, errorFallback, fit, height, loading, radius, src, width, }) => {
|
|
11
|
+
const element = useRef(null);
|
|
12
|
+
const [state, setState] = useState({ src, status: PsImageStatus.Loading });
|
|
13
|
+
const status = PsImageService.resolve(state, src);
|
|
14
|
+
usePsBrowserLayoutEffect(() => {
|
|
15
|
+
if (element.current === null)
|
|
16
|
+
return;
|
|
17
|
+
const found = PsImageService.statusOf(element.current);
|
|
18
|
+
if (found !== PsImageStatus.Loading)
|
|
19
|
+
setState({ src, status: found });
|
|
20
|
+
}, [src]);
|
|
21
|
+
if (status === PsImageStatus.Error)
|
|
22
|
+
return errorFallback === undefined ? null : _jsx(_Fragment, { children: errorFallback });
|
|
23
|
+
const isLoaded = status === PsImageStatus.Loaded;
|
|
24
|
+
return (_jsxs("span", { className: PsImageConfig.rootClassName, style: { borderRadius: radius }, children: [isLoaded ? null : (_jsx(PsSkeleton, { className: PsImageConfig.skeletonClassName, shape: PsSkeletonShape.Block })), _jsx("img", { alt: alt, className: PallasoftClassNameService.merge(PsImageConfig.imageClassName, isLoaded ? PsImageConfig.loadedClassName : PsImageConfig.hiddenClassName, className), decoding: 'async', height: height, loading: loading, onError: () => setState({ src, status: PsImageStatus.Error }), onLoad: () => setState({ src, status: PsImageStatus.Loaded }), ref: element, src: src, style: fit === undefined ? undefined : { objectFit: fit }, width: width })] }));
|
|
25
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
|
|
3
|
+
import { PsSignedValueClasses } from '../constants/ps-signed-value-classes.js';
|
|
4
|
+
import { PsSignedValueService } from '../services/ps-signed-value-service.js';
|
|
5
|
+
export const PsSignedValue = ({ className, format, value }) => (_jsx("span", { className: PallasoftClassNameService.merge(PsSignedValueClasses[PsSignedValueService.direction(value)], className), children: PsSignedValueService.text(value, format) }));
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export const PsImageConfig = {
|
|
2
|
+
hiddenClassName: 'opacity-0',
|
|
3
|
+
imageClassName: 'col-start-1 row-start-1',
|
|
4
|
+
loadedClassName: 'opacity-100 animate-ps-fade-in motion-reduce:animate-none',
|
|
5
|
+
rootClassName: 'inline-grid shrink-0 max-w-full overflow-hidden align-middle',
|
|
6
|
+
skeletonClassName: 'col-start-1 row-start-1 h-full w-full rounded-[inherit]',
|
|
7
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
|
+
import { PsCursorPagesService } from '../services/ps-cursor-pages-service.js';
|
|
3
|
+
import { PsRemoteReadService } from '../services/ps-remote-read-service.js';
|
|
4
|
+
export const usePsCursorPages = (input) => {
|
|
5
|
+
const { reloadKey } = input;
|
|
6
|
+
const firstUrl = input.url(null);
|
|
7
|
+
const [state, setState] = useState(() => PsCursorPagesService.initialState());
|
|
8
|
+
const inputRef = useRef(input);
|
|
9
|
+
const stateRef = useRef(state);
|
|
10
|
+
const inflight = useRef(null);
|
|
11
|
+
inputRef.current = input;
|
|
12
|
+
stateRef.current = state;
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
setState((current) => (current.isLoadingMore ? { ...current, isLoadingMore: false } : current));
|
|
15
|
+
if (firstUrl === null)
|
|
16
|
+
return;
|
|
17
|
+
const controller = new AbortController();
|
|
18
|
+
inflight.current = controller;
|
|
19
|
+
PsRemoteReadService.read(firstUrl, inputRef.current.parse, controller.signal).then((page) => {
|
|
20
|
+
if (controller.signal.aborted)
|
|
21
|
+
return;
|
|
22
|
+
inflight.current = null;
|
|
23
|
+
setState({
|
|
24
|
+
error: null,
|
|
25
|
+
hasMore: PsCursorPagesService.hasMore(page.length, inputRef.current.pageSize),
|
|
26
|
+
isLoadingMore: false,
|
|
27
|
+
rows: page,
|
|
28
|
+
settled: { reloadKey, url: firstUrl },
|
|
29
|
+
});
|
|
30
|
+
}, (failure) => {
|
|
31
|
+
if (controller.signal.aborted)
|
|
32
|
+
return;
|
|
33
|
+
inflight.current = null;
|
|
34
|
+
setState({
|
|
35
|
+
error: failure,
|
|
36
|
+
hasMore: false,
|
|
37
|
+
isLoadingMore: false,
|
|
38
|
+
rows: [],
|
|
39
|
+
settled: { reloadKey, url: firstUrl },
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
return () => {
|
|
43
|
+
controller.abort();
|
|
44
|
+
inflight.current = null;
|
|
45
|
+
};
|
|
46
|
+
}, [firstUrl, reloadKey]);
|
|
47
|
+
const loadMore = useCallback(() => {
|
|
48
|
+
const current = stateRef.current;
|
|
49
|
+
const latest = inputRef.current;
|
|
50
|
+
if (!current.hasMore || inflight.current !== null)
|
|
51
|
+
return;
|
|
52
|
+
const nextUrl = latest.url(latest.cursorOf(current.rows));
|
|
53
|
+
if (nextUrl === null)
|
|
54
|
+
return;
|
|
55
|
+
const controller = new AbortController();
|
|
56
|
+
inflight.current = controller;
|
|
57
|
+
setState((existing) => ({ ...existing, error: null, isLoadingMore: true }));
|
|
58
|
+
PsRemoteReadService.read(nextUrl, latest.parse, controller.signal).then((page) => {
|
|
59
|
+
if (controller.signal.aborted)
|
|
60
|
+
return;
|
|
61
|
+
inflight.current = null;
|
|
62
|
+
setState((existing) => ({
|
|
63
|
+
...existing,
|
|
64
|
+
hasMore: PsCursorPagesService.hasMore(page.length, inputRef.current.pageSize),
|
|
65
|
+
isLoadingMore: false,
|
|
66
|
+
rows: PsCursorPagesService.append(existing.rows, page, inputRef.current.keyOf),
|
|
67
|
+
}));
|
|
68
|
+
}, (failure) => {
|
|
69
|
+
if (controller.signal.aborted)
|
|
70
|
+
return;
|
|
71
|
+
inflight.current = null;
|
|
72
|
+
setState((existing) => ({ ...existing, error: failure, isLoadingMore: false }));
|
|
73
|
+
});
|
|
74
|
+
}, []);
|
|
75
|
+
return {
|
|
76
|
+
error: state.error,
|
|
77
|
+
hasMore: state.hasMore,
|
|
78
|
+
isLoading: PsRemoteReadService.isPending(state.settled, firstUrl, reloadKey) || state.isLoadingMore,
|
|
79
|
+
loadMore,
|
|
80
|
+
rows: state.rows,
|
|
81
|
+
};
|
|
82
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { useCallback, useState } from 'react';
|
|
2
|
+
import { PsDraftStateService } from '../services/ps-draft-state-service.js';
|
|
3
|
+
export const usePsDraftState = (initial, options) => {
|
|
4
|
+
const [state, setState] = useState(() => PsDraftStateService.fresh(initial));
|
|
5
|
+
const isCurrent = PsDraftStateService.isEqual(initial, state.baseline, options);
|
|
6
|
+
if (!isCurrent)
|
|
7
|
+
setState(PsDraftStateService.fresh(initial));
|
|
8
|
+
const setValue = useCallback((next) => setState((current) => ({ ...current, value: next })), []);
|
|
9
|
+
const update = useCallback((updater) => setState((current) => ({ ...current, value: updater(current.value) })), []);
|
|
10
|
+
const reset = useCallback(() => setState((current) => ({ ...current, value: structuredClone(current.baseline) })), []);
|
|
11
|
+
return {
|
|
12
|
+
isDirty: !PsDraftStateService.isEqual(state.value, state.baseline, options),
|
|
13
|
+
reset,
|
|
14
|
+
setValue,
|
|
15
|
+
update,
|
|
16
|
+
value: state.value,
|
|
17
|
+
};
|
|
18
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { useEffect, useRef, useState } from 'react';
|
|
2
|
+
import { PsRemoteReadService } from '../services/ps-remote-read-service.js';
|
|
3
|
+
export const usePsRemoteRead = ({ parse, reloadKey, url, }) => {
|
|
4
|
+
const [state, setState] = useState(() => PsRemoteReadService.initialState());
|
|
5
|
+
const parseRef = useRef(parse);
|
|
6
|
+
parseRef.current = parse;
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
if (url === null)
|
|
9
|
+
return;
|
|
10
|
+
const controller = new AbortController();
|
|
11
|
+
PsRemoteReadService.read(url, parseRef.current, controller.signal).then((data) => {
|
|
12
|
+
if (controller.signal.aborted)
|
|
13
|
+
return;
|
|
14
|
+
setState({ data, error: null, settled: { reloadKey, url } });
|
|
15
|
+
}, (failure) => {
|
|
16
|
+
if (controller.signal.aborted)
|
|
17
|
+
return;
|
|
18
|
+
setState((current) => ({
|
|
19
|
+
data: current.data,
|
|
20
|
+
error: failure,
|
|
21
|
+
settled: { reloadKey, url },
|
|
22
|
+
}));
|
|
23
|
+
});
|
|
24
|
+
return () => controller.abort();
|
|
25
|
+
}, [reloadKey, url]);
|
|
26
|
+
return {
|
|
27
|
+
data: state.data,
|
|
28
|
+
error: state.error,
|
|
29
|
+
isLoading: PsRemoteReadService.isPending(state.settled, url, reloadKey),
|
|
30
|
+
};
|
|
31
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
import { PsQueryParamConfig } from '../constants/ps-query-param-config.js';
|
|
3
|
+
import { PsQueryParamService } from '../services/ps-query-param-service.js';
|
|
4
|
+
import { usePsDebouncedValue } from './use-ps-debounced-value.js';
|
|
5
|
+
export const usePsTextParam = ([searchParams, setSearchParams], { debounceMs, name, resetParams }) => {
|
|
6
|
+
const raw = searchParams.get(name);
|
|
7
|
+
const committed = raw === null ? '' : raw;
|
|
8
|
+
const [value, setValue] = useState(committed);
|
|
9
|
+
const settled = usePsDebouncedValue(value, debounceMs);
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
if (settled === committed)
|
|
12
|
+
return;
|
|
13
|
+
setSearchParams((current) => PsQueryParamService.withChoice(current, name, settled, '', resetParams), PsQueryParamConfig.setOptions);
|
|
14
|
+
}, [settled]);
|
|
15
|
+
return { committed, onChange: setValue, value };
|
|
16
|
+
};
|
package/dist/esm/index.js
CHANGED
|
@@ -228,3 +228,33 @@ export * from './hooks/use-ps-choice-param.js';
|
|
|
228
228
|
export * from './hooks/use-ps-flag-param.js';
|
|
229
229
|
export * from './constants/ps-rerender-config.js';
|
|
230
230
|
export * from './hooks/use-ps-rerender-at.js';
|
|
231
|
+
export * from './models/ps-remote-settled-data.js';
|
|
232
|
+
export * from './models/ps-remote-read-state.js';
|
|
233
|
+
export * from './interfaces/ps-remote-read-input.js';
|
|
234
|
+
export * from './interfaces/ps-remote-read-result.js';
|
|
235
|
+
export * from './services/ps-remote-read-service.js';
|
|
236
|
+
export * from './hooks/use-ps-remote-read.js';
|
|
237
|
+
export * from './interfaces/ps-cursor-pages-input.js';
|
|
238
|
+
export * from './interfaces/ps-cursor-pages-result.js';
|
|
239
|
+
export * from './models/ps-cursor-pages-state.js';
|
|
240
|
+
export * from './services/ps-cursor-pages-service.js';
|
|
241
|
+
export * from './hooks/use-ps-cursor-pages.js';
|
|
242
|
+
export * from './models/ps-text-param-options.js';
|
|
243
|
+
export * from './models/ps-text-param-data.js';
|
|
244
|
+
export * from './hooks/use-ps-text-param.js';
|
|
245
|
+
export * from './interfaces/ps-draft-state-options.js';
|
|
246
|
+
export * from './interfaces/ps-draft-state-result.js';
|
|
247
|
+
export * from './models/ps-draft-state-data.js';
|
|
248
|
+
export * from './services/ps-draft-state-service.js';
|
|
249
|
+
export * from './hooks/use-ps-draft-state.js';
|
|
250
|
+
export * from './constants/ps-empty-value-config.js';
|
|
251
|
+
export * from './components/ps-empty-value.js';
|
|
252
|
+
export * from './constants/ps-signed-value-classes.js';
|
|
253
|
+
export * from './services/ps-signed-value-service.js';
|
|
254
|
+
export * from './components/ps-signed-value.js';
|
|
255
|
+
export * from './constants/ps-image-status.js';
|
|
256
|
+
export * from './constants/ps-image-fit.js';
|
|
257
|
+
export * from './constants/ps-image-config.js';
|
|
258
|
+
export * from './models/ps-image-state-data.js';
|
|
259
|
+
export * from './services/ps-image-service.js';
|
|
260
|
+
export * from './components/ps-image.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export class PsCursorPagesService {
|
|
2
|
+
static append(existing, page, keyOf) {
|
|
3
|
+
if (keyOf === undefined)
|
|
4
|
+
return [...existing, ...page];
|
|
5
|
+
const known = new Set(existing.map(keyOf));
|
|
6
|
+
return [...existing, ...page.filter((row) => !known.has(keyOf(row)))];
|
|
7
|
+
}
|
|
8
|
+
static hasMore(pageLength, pageSize) {
|
|
9
|
+
return pageLength >= pageSize;
|
|
10
|
+
}
|
|
11
|
+
static initialState() {
|
|
12
|
+
return { error: null, hasMore: false, isLoadingMore: false, rows: [], settled: null };
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { PsDeepEqualService } from './ps-deep-equal-service.js';
|
|
2
|
+
export class PsDraftStateService {
|
|
3
|
+
static fresh(initial) {
|
|
4
|
+
return { baseline: initial, value: structuredClone(initial) };
|
|
5
|
+
}
|
|
6
|
+
static isEqual(left, right, options) {
|
|
7
|
+
if (options !== undefined && options.isEqual !== undefined)
|
|
8
|
+
return options.isEqual(left, right);
|
|
9
|
+
return PsDeepEqualService.isEqual(left, right);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { PsImageStatus } from '../constants/ps-image-status.js';
|
|
2
|
+
export class PsImageService {
|
|
3
|
+
static resolve(state, src) {
|
|
4
|
+
return state.src === src ? state.status : PsImageStatus.Loading;
|
|
5
|
+
}
|
|
6
|
+
static statusOf(element) {
|
|
7
|
+
if (!element.complete)
|
|
8
|
+
return PsImageStatus.Loading;
|
|
9
|
+
return element.naturalWidth > 0 ? PsImageStatus.Loaded : PsImageStatus.Error;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Client } from '@pallasoft/ps-utilities';
|
|
2
|
+
export class PsRemoteReadService {
|
|
3
|
+
static initialState() {
|
|
4
|
+
return { data: null, error: null, settled: null };
|
|
5
|
+
}
|
|
6
|
+
static isPending(settled, url, reloadKey) {
|
|
7
|
+
if (url === null)
|
|
8
|
+
return false;
|
|
9
|
+
return settled === null || settled.url !== url || !Object.is(settled.reloadKey, reloadKey);
|
|
10
|
+
}
|
|
11
|
+
static async read(url, parse, signal) {
|
|
12
|
+
const response = await PsRemoteReadService.client.get(url, {
|
|
13
|
+
responseType: 'json',
|
|
14
|
+
signal,
|
|
15
|
+
});
|
|
16
|
+
return parse(response.data);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
PsRemoteReadService.client = Client.HttpService.createApiClient();
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { AmountDirection, Common } from '@pallasoft/ps-utilities';
|
|
2
|
+
export class PsSignedValueService {
|
|
3
|
+
static direction(value) {
|
|
4
|
+
const sign = Common.DecimalStringService.sign(value);
|
|
5
|
+
if (sign > 0)
|
|
6
|
+
return AmountDirection.In;
|
|
7
|
+
return sign < 0 ? AmountDirection.Out : AmountDirection.Neutral;
|
|
8
|
+
}
|
|
9
|
+
static text(value, format) {
|
|
10
|
+
const body = format === undefined ? value : format(value);
|
|
11
|
+
return Common.DecimalStringService.sign(value) > 0 ? `+${body}` : body;
|
|
12
|
+
}
|
|
13
|
+
}
|