@pallasoft/ps-core-components 2.44.2 → 2.46.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 +7 -2
- package/dist/components/ps-data-boundary.js +13 -1
- package/dist/components/ps-drag-overlay.js +4 -4
- package/dist/components/ps-draggable-grid.js +3 -1
- package/dist/components/ps-sortable-list.js +5 -5
- package/dist/constants/ps-data-boundary-config.d.ts +4 -0
- package/dist/constants/ps-data-boundary-config.js +7 -0
- package/dist/constants/ps-data-boundary-variant.d.ts +4 -0
- package/dist/constants/ps-data-boundary-variant.js +8 -0
- package/dist/constants/ps-drag-config.d.ts +3 -0
- package/dist/constants/ps-drag-config.js +10 -4
- package/dist/constants/ps-draggable-grid.d.ts +2 -0
- package/dist/constants/ps-optimistic-config.d.ts +1 -0
- package/dist/constants/ps-optimistic-config.js +1 -0
- package/dist/constants/ps-skeleton-config.d.ts +1 -0
- package/dist/constants/ps-skeleton-config.js +1 -0
- package/dist/esm/components/ps-data-boundary.js +14 -2
- package/dist/esm/components/ps-drag-overlay.js +5 -5
- package/dist/esm/components/ps-draggable-grid.js +3 -1
- package/dist/esm/components/ps-sortable-list.js +6 -6
- package/dist/esm/constants/ps-data-boundary-config.js +4 -0
- package/dist/esm/constants/ps-data-boundary-variant.js +5 -0
- package/dist/esm/constants/ps-drag-config.js +9 -3
- package/dist/esm/constants/ps-optimistic-config.js +1 -0
- package/dist/esm/constants/ps-skeleton-config.js +1 -0
- package/dist/esm/hooks/use-ps-drag-sensors.js +2 -2
- package/dist/esm/hooks/use-ps-drag-transition.js +10 -0
- package/dist/esm/hooks/use-ps-optimistic-rows.js +23 -12
- package/dist/esm/hooks/use-ps-promise-value.js +15 -0
- package/dist/esm/hooks/use-ps-retained-promise.js +21 -0
- package/dist/esm/index.js +8 -0
- package/dist/esm/interfaces/ps-retained-promise-data.js +1 -0
- package/dist/esm/models/ps-drag-transition.js +1 -0
- package/dist/esm/services/ps-deep-equal-service.js +31 -0
- package/dist/esm/services/ps-optimistic-release-service.js +32 -0
- package/dist/esm/services/ps-skeleton-class-service.js +11 -1
- package/dist/hooks/use-ps-drag-sensors.d.ts +2 -2
- package/dist/hooks/use-ps-drag-sensors.js +2 -2
- package/dist/hooks/use-ps-drag-transition.d.ts +2 -0
- package/dist/hooks/use-ps-drag-transition.js +14 -0
- package/dist/hooks/use-ps-optimistic-rows.js +22 -11
- package/dist/hooks/use-ps-promise-value.d.ts +1 -0
- package/dist/hooks/use-ps-promise-value.js +19 -0
- package/dist/hooks/use-ps-retained-promise.d.ts +2 -0
- package/dist/hooks/use-ps-retained-promise.js +25 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +8 -0
- package/dist/interfaces/ps-optimistic-changes.d.ts +2 -0
- package/dist/interfaces/ps-retained-promise-data.d.ts +4 -0
- package/dist/interfaces/ps-retained-promise-data.js +2 -0
- package/dist/models/ps-drag-transition.d.ts +4 -0
- package/dist/models/ps-drag-transition.js +2 -0
- package/dist/services/ps-deep-equal-service.d.ts +5 -0
- package/dist/services/ps-deep-equal-service.js +35 -0
- package/dist/services/ps-optimistic-release-service.d.ts +5 -0
- package/dist/services/ps-optimistic-release-service.js +36 -0
- package/dist/services/ps-skeleton-class-service.d.ts +1 -0
- package/dist/services/ps-skeleton-class-service.js +11 -1
- package/package.json +1 -1
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { type ElementType, type ReactNode } from 'react';
|
|
2
|
+
import { PsDataBoundaryVariant } from '../constants/ps-data-boundary-variant';
|
|
2
3
|
export interface PsDataBoundaryProps<Data> {
|
|
3
4
|
AwaitComponent: ElementType;
|
|
4
|
-
children: (data: Data) => ReactNode;
|
|
5
|
+
children: (data: Data, isPending: boolean) => ReactNode;
|
|
6
|
+
className?: string;
|
|
5
7
|
errorElement: ReactNode;
|
|
6
8
|
fallback: ReactNode;
|
|
7
9
|
resolve: Promise<Data>;
|
|
10
|
+
retain?: boolean;
|
|
11
|
+
retainKey?: string;
|
|
12
|
+
variant?: PsDataBoundaryVariant;
|
|
8
13
|
}
|
|
9
|
-
export declare const PsDataBoundary: <Data>({ AwaitComponent, children, errorElement, fallback, resolve, }: PsDataBoundaryProps<Data>) => import("react").JSX.Element;
|
|
14
|
+
export declare const PsDataBoundary: <Data>({ AwaitComponent, children, className, errorElement, fallback, resolve, retain, retainKey, variant, }: PsDataBoundaryProps<Data>) => import("react").JSX.Element;
|
|
@@ -3,5 +3,17 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.PsDataBoundary = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const react_1 = require("react");
|
|
6
|
-
const
|
|
6
|
+
const ps_design_system_1 = require("@pallasoft/ps-design-system");
|
|
7
|
+
const ps_data_boundary_config_1 = require("../constants/ps-data-boundary-config");
|
|
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, }) => {
|
|
10
|
+
const deferred = (0, react_1.useDeferredValue)({ key: retainKey, resolve });
|
|
11
|
+
const isRetaining = retain && deferred.key === retainKey;
|
|
12
|
+
const shown = isRetaining ? deferred.resolve : resolve;
|
|
13
|
+
const isPending = shown !== resolve;
|
|
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
|
+
if (variant === ps_data_boundary_variant_1.PsDataBoundaryVariant.Page)
|
|
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 }));
|
|
18
|
+
};
|
|
7
19
|
exports.PsDataBoundary = PsDataBoundary;
|
|
@@ -21,9 +21,7 @@ const PsDragOverlay = ({ children, className, frames, isDropAnimated, }) => {
|
|
|
21
21
|
const isReduced = (0, use_ps_reduced_motion_1.usePsReducedMotion)();
|
|
22
22
|
const zIndex = (0, use_ps_layer_z_index_1.usePsLayerZIndex)(ps_design_system_1.PallasoftZIndex.Popover);
|
|
23
23
|
(0, react_1.useEffect)(() => setIsMounted(true), []);
|
|
24
|
-
|
|
25
|
-
return null;
|
|
26
|
-
const lift = (element) => {
|
|
24
|
+
const lift = (0, react_1.useCallback)((element) => {
|
|
27
25
|
if (element === null || isReduced || typeof element.animate !== 'function')
|
|
28
26
|
return;
|
|
29
27
|
element.animate(frames, {
|
|
@@ -31,7 +29,9 @@ const PsDragOverlay = ({ children, className, frames, isDropAnimated, }) => {
|
|
|
31
29
|
easing: ps_drag_config_1.PsDragConfig.liftEasing,
|
|
32
30
|
fill: 'forwards',
|
|
33
31
|
});
|
|
34
|
-
};
|
|
32
|
+
}, [frames, isReduced]);
|
|
33
|
+
if (!isMounted)
|
|
34
|
+
return null;
|
|
35
35
|
return (0, react_dom_1.createPortal)((0, jsx_runtime_1.jsx)(core_1.DragOverlay, { dropAnimation: isReduced || isDropAnimated === false ? null : dropAnimation, zIndex: zIndex, children: children === null ? null : ((0, jsx_runtime_1.jsx)("div", { className: className, ref: lift, children: children })) }), document.body);
|
|
36
36
|
};
|
|
37
37
|
exports.PsDragOverlay = PsDragOverlay;
|
|
@@ -9,11 +9,13 @@ const utilities_1 = require("@dnd-kit/utilities");
|
|
|
9
9
|
const ps_drag_config_1 = require("../constants/ps-drag-config");
|
|
10
10
|
const ps_draggable_grid_1 = require("../constants/ps-draggable-grid");
|
|
11
11
|
const use_ps_drag_sensors_1 = require("../hooks/use-ps-drag-sensors");
|
|
12
|
+
const use_ps_drag_transition_1 = require("../hooks/use-ps-drag-transition");
|
|
12
13
|
const ps_drag_grip_1 = require("./ps-drag-grip");
|
|
13
14
|
const ps_drag_overlay_1 = require("./ps-drag-overlay");
|
|
14
15
|
const PsDraggableGridHandle = ({ attributes, label, listeners, setActivatorNodeRef, }) => ((0, jsx_runtime_1.jsx)("button", { ...attributes, ...listeners, "aria-label": `Move ${label}`, className: ps_draggable_grid_1.PsDraggableGridClasses.handle, ref: setActivatorNodeRef, title: `Move ${label}`, type: 'button', children: (0, jsx_runtime_1.jsx)(ps_drag_grip_1.PsDragGrip, {}) }));
|
|
15
16
|
const PsSortableGridItem = ({ className, index, item, renderItem, }) => {
|
|
16
|
-
const
|
|
17
|
+
const dragTransition = (0, use_ps_drag_transition_1.usePsDragTransition)();
|
|
18
|
+
const { attributes, isDragging, listeners, setActivatorNodeRef, setNodeRef, transform, transition, } = (0, sortable_1.useSortable)({ id: item.id, transition: dragTransition });
|
|
17
19
|
const rendered = renderItem({
|
|
18
20
|
handle: ((0, jsx_runtime_1.jsx)(PsDraggableGridHandle, { attributes: attributes, label: item.label, listeners: listeners, setActivatorNodeRef: setActivatorNodeRef })),
|
|
19
21
|
index,
|
|
@@ -8,13 +8,13 @@ const sortable_1 = require("@dnd-kit/sortable");
|
|
|
8
8
|
const utilities_1 = require("@dnd-kit/utilities");
|
|
9
9
|
const ps_drag_config_1 = require("../constants/ps-drag-config");
|
|
10
10
|
const use_ps_drag_sensors_1 = require("../hooks/use-ps-drag-sensors");
|
|
11
|
-
const
|
|
11
|
+
const use_ps_drag_transition_1 = require("../hooks/use-ps-drag-transition");
|
|
12
12
|
const ps_drag_grip_1 = require("./ps-drag-grip");
|
|
13
13
|
const ps_drag_overlay_1 = require("./ps-drag-overlay");
|
|
14
14
|
const PsSortableListHandle = ({ attributes, className, icon, label, listeners, setActivatorNodeRef, }) => ((0, jsx_runtime_1.jsx)("button", { ...attributes, ...listeners, "aria-label": label, className: className === undefined ? ps_drag_config_1.PsDragClasses.handle : className, ref: setActivatorNodeRef, title: label, type: 'button', children: icon === undefined ? (0, jsx_runtime_1.jsx)(ps_drag_grip_1.PsDragGrip, {}) : icon }));
|
|
15
15
|
const PsSortableListRow = ({ className, handleClassName, handleIcon, getHandleLabel, index, isDisabled, item, renderItem, }) => {
|
|
16
|
-
const
|
|
17
|
-
const { attributes, isDragging, listeners, setActivatorNodeRef, setNodeRef, transform, transition, } = (0, sortable_1.useSortable)({ disabled: isDisabled, id: item.id });
|
|
16
|
+
const dragTransition = (0, use_ps_drag_transition_1.usePsDragTransition)();
|
|
17
|
+
const { attributes, isDragging, listeners, setActivatorNodeRef, setNodeRef, transform, transition, } = (0, sortable_1.useSortable)({ disabled: isDisabled, id: item.id, transition: dragTransition });
|
|
18
18
|
const rendered = renderItem({
|
|
19
19
|
handle: ((0, jsx_runtime_1.jsx)(PsSortableListHandle, { attributes: attributes, className: handleClassName, icon: handleIcon, label: getHandleLabel(item.label), listeners: listeners, setActivatorNodeRef: setActivatorNodeRef })),
|
|
20
20
|
index,
|
|
@@ -27,7 +27,7 @@ const PsSortableListRow = ({ className, handleClassName, handleIcon, getHandleLa
|
|
|
27
27
|
return ((0, jsx_runtime_1.jsx)("div", { className: `${ps_drag_config_1.PsDragClasses.listItem} ${className} ${isDragging ? ps_drag_config_1.PsDragClasses.placeholder : ''}`, ref: setNodeRef, style: {
|
|
28
28
|
opacity: isDragging ? ps_drag_config_1.PsDragConfig.placeholderOpacity : undefined,
|
|
29
29
|
transform: utilities_1.CSS.Translate.toString(transform),
|
|
30
|
-
transition
|
|
30
|
+
transition,
|
|
31
31
|
}, children: rendered }));
|
|
32
32
|
};
|
|
33
33
|
const PsSortableList = ({ announcements: texts, className, getHandleLabel, getItemClassName, handleClassName, handleIcon, instructions, isHorizontal = false, role, items, onMove, renderItem, }) => {
|
|
@@ -66,7 +66,7 @@ const PsSortableList = ({ announcements: texts, className, getHandleLabel, getIt
|
|
|
66
66
|
onMove(String(active.id), from, to);
|
|
67
67
|
};
|
|
68
68
|
const activeGroup = activeItem === null ? undefined : activeItem.groupKey;
|
|
69
|
-
return ((0, jsx_runtime_1.jsxs)(core_1.DndContext, { accessibility: { announcements, screenReaderInstructions: { draggable: instructions } }, collisionDetection: core_1.closestCenter, onDragCancel: () => setActiveId(null), onDragEnd: handleDragEnd, onDragStart: ({ active }) => setActiveId(String(active.id)), sensors: sensors, children: [(0, jsx_runtime_1.jsx)(sortable_1.SortableContext, { items: items.map((item) => item.id), strategy: isHorizontal ? sortable_1.horizontalListSortingStrategy : sortable_1.verticalListSortingStrategy, children: (0, jsx_runtime_1.jsx)("div", { className: className, role: role, children: items.map((item, index) => ((0, jsx_runtime_1.jsx)(PsSortableListRow, { className: itemClassName(item), getHandleLabel: getHandleLabel, handleClassName: handleClassName, handleIcon: handleIcon, index: index, isDisabled: activeItem !== null && item.groupKey !== activeGroup, item: item, renderItem: renderItem }, item.id))) }) }), (0, jsx_runtime_1.jsx)(ps_drag_overlay_1.PsDragOverlay, { className: ps_drag_config_1.PsDragClasses.lifted, frames: ps_drag_config_1.
|
|
69
|
+
return ((0, jsx_runtime_1.jsxs)(core_1.DndContext, { accessibility: { announcements, screenReaderInstructions: { draggable: instructions } }, collisionDetection: core_1.closestCenter, onDragCancel: () => setActiveId(null), onDragEnd: handleDragEnd, onDragStart: ({ active }) => setActiveId(String(active.id)), sensors: sensors, children: [(0, jsx_runtime_1.jsx)(sortable_1.SortableContext, { items: items.map((item) => item.id), strategy: isHorizontal ? sortable_1.horizontalListSortingStrategy : sortable_1.verticalListSortingStrategy, children: (0, jsx_runtime_1.jsx)("div", { className: className, role: role, children: items.map((item, index) => ((0, jsx_runtime_1.jsx)(PsSortableListRow, { className: itemClassName(item), getHandleLabel: getHandleLabel, handleClassName: handleClassName, handleIcon: handleIcon, index: index, isDisabled: activeItem !== null && item.groupKey !== activeGroup, item: item, renderItem: renderItem }, item.id))) }) }), (0, jsx_runtime_1.jsx)(ps_drag_overlay_1.PsDragOverlay, { className: ps_drag_config_1.PsDragClasses.lifted, frames: ps_drag_config_1.PsDragRowLiftFrames, children: activeItem !== null
|
|
70
70
|
? renderItem({
|
|
71
71
|
handle: ((0, jsx_runtime_1.jsx)(PsSortableListHandle, { className: handleClassName, icon: handleIcon, label: getHandleLabel(activeItem.label) })),
|
|
72
72
|
index: activeIndex,
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PsDataBoundaryVariant = void 0;
|
|
4
|
+
var PsDataBoundaryVariant;
|
|
5
|
+
(function (PsDataBoundaryVariant) {
|
|
6
|
+
PsDataBoundaryVariant["Page"] = "page";
|
|
7
|
+
PsDataBoundaryVariant["Section"] = "section";
|
|
8
|
+
})(PsDataBoundaryVariant || (exports.PsDataBoundaryVariant = PsDataBoundaryVariant = {}));
|
|
@@ -5,6 +5,8 @@ export declare const PsDragConfig: {
|
|
|
5
5
|
readonly liftDuration: 200;
|
|
6
6
|
readonly liftEasing: "cubic-bezier(0.2, 0.9, 0.3, 1.2)";
|
|
7
7
|
readonly placeholderOpacity: "0.4";
|
|
8
|
+
readonly sortDuration: 250;
|
|
9
|
+
readonly sortEasing: "ease";
|
|
8
10
|
readonly touchDelay: 180;
|
|
9
11
|
readonly touchTolerance: 6;
|
|
10
12
|
};
|
|
@@ -15,4 +17,5 @@ export declare const PsDragClasses: {
|
|
|
15
17
|
readonly placeholder: "outline-dashed outline-2 outline-offset-[-2px] outline-primary/35";
|
|
16
18
|
};
|
|
17
19
|
export declare const PsDragLiftFrames: Keyframe[];
|
|
20
|
+
export declare const PsDragRowLiftFrames: Keyframe[];
|
|
18
21
|
export declare const PsDragListLiftFrames: Keyframe[];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.PsDragListLiftFrames = exports.PsDragLiftFrames = exports.PsDragClasses = exports.PsDragConfig = void 0;
|
|
3
|
+
exports.PsDragListLiftFrames = exports.PsDragRowLiftFrames = exports.PsDragLiftFrames = exports.PsDragClasses = exports.PsDragConfig = void 0;
|
|
4
4
|
exports.PsDragConfig = {
|
|
5
5
|
activationDistance: 6,
|
|
6
6
|
dropDuration: 220,
|
|
@@ -8,6 +8,8 @@ exports.PsDragConfig = {
|
|
|
8
8
|
liftDuration: 200,
|
|
9
9
|
liftEasing: 'cubic-bezier(0.2, 0.9, 0.3, 1.2)',
|
|
10
10
|
placeholderOpacity: '0.4',
|
|
11
|
+
sortDuration: 250,
|
|
12
|
+
sortEasing: 'ease',
|
|
11
13
|
touchDelay: 180,
|
|
12
14
|
touchTolerance: 6,
|
|
13
15
|
};
|
|
@@ -24,7 +26,11 @@ exports.PsDragLiftFrames = [
|
|
|
24
26
|
transform: 'scale(1.035) rotate(-1.2deg)',
|
|
25
27
|
},
|
|
26
28
|
];
|
|
27
|
-
exports.
|
|
28
|
-
{ boxShadow: '0 0 0 0 rgb(15 23 42 / 0)', transform: 'scale(1)' },
|
|
29
|
-
{
|
|
29
|
+
exports.PsDragRowLiftFrames = [
|
|
30
|
+
{ boxShadow: '0 0 0 0 rgb(15 23 42 / 0)', transform: 'scale(1) rotate(0deg)' },
|
|
31
|
+
{
|
|
32
|
+
boxShadow: '0 28px 64px -18px rgb(15 23 42 / 0.5)',
|
|
33
|
+
transform: 'scale(1.035) rotate(-0.25deg)',
|
|
34
|
+
},
|
|
30
35
|
];
|
|
36
|
+
exports.PsDragListLiftFrames = exports.PsDragRowLiftFrames;
|
|
@@ -5,6 +5,8 @@ export declare const PsDraggableGridConfig: {
|
|
|
5
5
|
readonly liftDuration: 200;
|
|
6
6
|
readonly liftEasing: "cubic-bezier(0.2, 0.9, 0.3, 1.2)";
|
|
7
7
|
readonly placeholderOpacity: "0.4";
|
|
8
|
+
readonly sortDuration: 250;
|
|
9
|
+
readonly sortEasing: "ease";
|
|
8
10
|
readonly touchDelay: 180;
|
|
9
11
|
readonly touchTolerance: 6;
|
|
10
12
|
};
|
|
@@ -10,6 +10,7 @@ export declare const PsSkeletonConfig: {
|
|
|
10
10
|
readonly importantPrefix: "!";
|
|
11
11
|
readonly widthUtilityPattern: RegExp;
|
|
12
12
|
readonly heightUtilityPattern: RegExp;
|
|
13
|
+
readonly radiusUtilityPattern: RegExp;
|
|
13
14
|
readonly compactControlHeightClassName: "h-ps-control-compact";
|
|
14
15
|
readonly tabWidthClassName: "w-24";
|
|
15
16
|
readonly tabCount: 4;
|
|
@@ -16,6 +16,7 @@ exports.PsSkeletonConfig = {
|
|
|
16
16
|
importantPrefix: '!',
|
|
17
17
|
widthUtilityPattern: /^(w|size)-/,
|
|
18
18
|
heightUtilityPattern: /^(h|size)-/,
|
|
19
|
+
radiusUtilityPattern: /^rounded(-|$)/,
|
|
19
20
|
compactControlHeightClassName: 'h-ps-control-compact',
|
|
20
21
|
tabWidthClassName: 'w-24',
|
|
21
22
|
tabCount: 4,
|
|
@@ -1,3 +1,15 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { Suspense } from 'react';
|
|
3
|
-
|
|
2
|
+
import { Suspense, useDeferredValue } from 'react';
|
|
3
|
+
import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
|
|
4
|
+
import { PsDataBoundaryConfig } from '../constants/ps-data-boundary-config.js';
|
|
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, }) => {
|
|
7
|
+
const deferred = useDeferredValue({ key: retainKey, resolve });
|
|
8
|
+
const isRetaining = retain && deferred.key === retainKey;
|
|
9
|
+
const shown = isRetaining ? deferred.resolve : resolve;
|
|
10
|
+
const isPending = shown !== resolve;
|
|
11
|
+
const content = (_jsx(Suspense, { fallback: fallback, children: _jsx(AwaitComponent, { errorElement: errorElement, resolve: shown, children: (data) => children(data, isPending) }) }));
|
|
12
|
+
if (variant === PsDataBoundaryVariant.Page)
|
|
13
|
+
return content;
|
|
14
|
+
return (_jsx("div", { "aria-busy": isPending, className: PallasoftClassNameService.merge(PsDataBoundaryConfig.sectionClassName, isPending ? PsDataBoundaryConfig.pendingClassName : null, className), children: content }));
|
|
15
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect, useState } from 'react';
|
|
2
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
3
3
|
import { DragOverlay, defaultDropAnimationSideEffects } from '@dnd-kit/core';
|
|
4
4
|
import { PallasoftZIndex } from '@pallasoft/ps-design-system';
|
|
5
5
|
import { createPortal } from 'react-dom';
|
|
@@ -18,9 +18,7 @@ export const PsDragOverlay = ({ children, className, frames, isDropAnimated, })
|
|
|
18
18
|
const isReduced = usePsReducedMotion();
|
|
19
19
|
const zIndex = usePsLayerZIndex(PallasoftZIndex.Popover);
|
|
20
20
|
useEffect(() => setIsMounted(true), []);
|
|
21
|
-
|
|
22
|
-
return null;
|
|
23
|
-
const lift = (element) => {
|
|
21
|
+
const lift = useCallback((element) => {
|
|
24
22
|
if (element === null || isReduced || typeof element.animate !== 'function')
|
|
25
23
|
return;
|
|
26
24
|
element.animate(frames, {
|
|
@@ -28,6 +26,8 @@ export const PsDragOverlay = ({ children, className, frames, isDropAnimated, })
|
|
|
28
26
|
easing: PsDragConfig.liftEasing,
|
|
29
27
|
fill: 'forwards',
|
|
30
28
|
});
|
|
31
|
-
};
|
|
29
|
+
}, [frames, isReduced]);
|
|
30
|
+
if (!isMounted)
|
|
31
|
+
return null;
|
|
32
32
|
return createPortal(_jsx(DragOverlay, { dropAnimation: isReduced || isDropAnimated === false ? null : dropAnimation, zIndex: zIndex, children: children === null ? null : (_jsx("div", { className: className, ref: lift, children: children })) }), document.body);
|
|
33
33
|
};
|
|
@@ -6,11 +6,13 @@ import { CSS } from '@dnd-kit/utilities';
|
|
|
6
6
|
import { PsDragConfig } from '../constants/ps-drag-config.js';
|
|
7
7
|
import { PsDraggableGridClasses, PsDraggableGridLiftFrames } from '../constants/ps-draggable-grid.js';
|
|
8
8
|
import { usePsDragSensors } from '../hooks/use-ps-drag-sensors.js';
|
|
9
|
+
import { usePsDragTransition } from '../hooks/use-ps-drag-transition.js';
|
|
9
10
|
import { PsDragGrip } from './ps-drag-grip.js';
|
|
10
11
|
import { PsDragOverlay } from './ps-drag-overlay.js';
|
|
11
12
|
const PsDraggableGridHandle = ({ attributes, label, listeners, setActivatorNodeRef, }) => (_jsx("button", { ...attributes, ...listeners, "aria-label": `Move ${label}`, className: PsDraggableGridClasses.handle, ref: setActivatorNodeRef, title: `Move ${label}`, type: 'button', children: _jsx(PsDragGrip, {}) }));
|
|
12
13
|
const PsSortableGridItem = ({ className, index, item, renderItem, }) => {
|
|
13
|
-
const
|
|
14
|
+
const dragTransition = usePsDragTransition();
|
|
15
|
+
const { attributes, isDragging, listeners, setActivatorNodeRef, setNodeRef, transform, transition, } = useSortable({ id: item.id, transition: dragTransition });
|
|
14
16
|
const rendered = renderItem({
|
|
15
17
|
handle: (_jsx(PsDraggableGridHandle, { attributes: attributes, label: item.label, listeners: listeners, setActivatorNodeRef: setActivatorNodeRef })),
|
|
16
18
|
index,
|
|
@@ -3,15 +3,15 @@ import { useState } from 'react';
|
|
|
3
3
|
import { DndContext, closestCenter, } from '@dnd-kit/core';
|
|
4
4
|
import { SortableContext, horizontalListSortingStrategy, useSortable, verticalListSortingStrategy, } from '@dnd-kit/sortable';
|
|
5
5
|
import { CSS } from '@dnd-kit/utilities';
|
|
6
|
-
import { PsDragClasses, PsDragConfig,
|
|
6
|
+
import { PsDragClasses, PsDragConfig, PsDragRowLiftFrames } from '../constants/ps-drag-config.js';
|
|
7
7
|
import { usePsDragSensors } from '../hooks/use-ps-drag-sensors.js';
|
|
8
|
-
import {
|
|
8
|
+
import { usePsDragTransition } from '../hooks/use-ps-drag-transition.js';
|
|
9
9
|
import { PsDragGrip } from './ps-drag-grip.js';
|
|
10
10
|
import { PsDragOverlay } from './ps-drag-overlay.js';
|
|
11
11
|
const PsSortableListHandle = ({ attributes, className, icon, label, listeners, setActivatorNodeRef, }) => (_jsx("button", { ...attributes, ...listeners, "aria-label": label, className: className === undefined ? PsDragClasses.handle : className, ref: setActivatorNodeRef, title: label, type: 'button', children: icon === undefined ? _jsx(PsDragGrip, {}) : icon }));
|
|
12
12
|
const PsSortableListRow = ({ className, handleClassName, handleIcon, getHandleLabel, index, isDisabled, item, renderItem, }) => {
|
|
13
|
-
const
|
|
14
|
-
const { attributes, isDragging, listeners, setActivatorNodeRef, setNodeRef, transform, transition, } = useSortable({ disabled: isDisabled, id: item.id });
|
|
13
|
+
const dragTransition = usePsDragTransition();
|
|
14
|
+
const { attributes, isDragging, listeners, setActivatorNodeRef, setNodeRef, transform, transition, } = useSortable({ disabled: isDisabled, id: item.id, transition: dragTransition });
|
|
15
15
|
const rendered = renderItem({
|
|
16
16
|
handle: (_jsx(PsSortableListHandle, { attributes: attributes, className: handleClassName, icon: handleIcon, label: getHandleLabel(item.label), listeners: listeners, setActivatorNodeRef: setActivatorNodeRef })),
|
|
17
17
|
index,
|
|
@@ -24,7 +24,7 @@ const PsSortableListRow = ({ className, handleClassName, handleIcon, getHandleLa
|
|
|
24
24
|
return (_jsx("div", { className: `${PsDragClasses.listItem} ${className} ${isDragging ? PsDragClasses.placeholder : ''}`, ref: setNodeRef, style: {
|
|
25
25
|
opacity: isDragging ? PsDragConfig.placeholderOpacity : undefined,
|
|
26
26
|
transform: CSS.Translate.toString(transform),
|
|
27
|
-
transition
|
|
27
|
+
transition,
|
|
28
28
|
}, children: rendered }));
|
|
29
29
|
};
|
|
30
30
|
export const PsSortableList = ({ announcements: texts, className, getHandleLabel, getItemClassName, handleClassName, handleIcon, instructions, isHorizontal = false, role, items, onMove, renderItem, }) => {
|
|
@@ -63,7 +63,7 @@ export const PsSortableList = ({ announcements: texts, className, getHandleLabel
|
|
|
63
63
|
onMove(String(active.id), from, to);
|
|
64
64
|
};
|
|
65
65
|
const activeGroup = activeItem === null ? undefined : activeItem.groupKey;
|
|
66
|
-
return (_jsxs(DndContext, { accessibility: { announcements, screenReaderInstructions: { draggable: instructions } }, collisionDetection: closestCenter, onDragCancel: () => setActiveId(null), onDragEnd: handleDragEnd, onDragStart: ({ active }) => setActiveId(String(active.id)), sensors: sensors, children: [_jsx(SortableContext, { items: items.map((item) => item.id), strategy: isHorizontal ? horizontalListSortingStrategy : verticalListSortingStrategy, children: _jsx("div", { className: className, role: role, children: items.map((item, index) => (_jsx(PsSortableListRow, { className: itemClassName(item), getHandleLabel: getHandleLabel, handleClassName: handleClassName, handleIcon: handleIcon, index: index, isDisabled: activeItem !== null && item.groupKey !== activeGroup, item: item, renderItem: renderItem }, item.id))) }) }), _jsx(PsDragOverlay, { className: PsDragClasses.lifted, frames:
|
|
66
|
+
return (_jsxs(DndContext, { accessibility: { announcements, screenReaderInstructions: { draggable: instructions } }, collisionDetection: closestCenter, onDragCancel: () => setActiveId(null), onDragEnd: handleDragEnd, onDragStart: ({ active }) => setActiveId(String(active.id)), sensors: sensors, children: [_jsx(SortableContext, { items: items.map((item) => item.id), strategy: isHorizontal ? horizontalListSortingStrategy : verticalListSortingStrategy, children: _jsx("div", { className: className, role: role, children: items.map((item, index) => (_jsx(PsSortableListRow, { className: itemClassName(item), getHandleLabel: getHandleLabel, handleClassName: handleClassName, handleIcon: handleIcon, index: index, isDisabled: activeItem !== null && item.groupKey !== activeGroup, item: item, renderItem: renderItem }, item.id))) }) }), _jsx(PsDragOverlay, { className: PsDragClasses.lifted, frames: PsDragRowLiftFrames, children: activeItem !== null
|
|
67
67
|
? renderItem({
|
|
68
68
|
handle: (_jsx(PsSortableListHandle, { className: handleClassName, icon: handleIcon, label: getHandleLabel(activeItem.label) })),
|
|
69
69
|
index: activeIndex,
|
|
@@ -5,6 +5,8 @@ export const PsDragConfig = {
|
|
|
5
5
|
liftDuration: 200,
|
|
6
6
|
liftEasing: 'cubic-bezier(0.2, 0.9, 0.3, 1.2)',
|
|
7
7
|
placeholderOpacity: '0.4',
|
|
8
|
+
sortDuration: 250,
|
|
9
|
+
sortEasing: 'ease',
|
|
8
10
|
touchDelay: 180,
|
|
9
11
|
touchTolerance: 6,
|
|
10
12
|
};
|
|
@@ -21,7 +23,11 @@ export const PsDragLiftFrames = [
|
|
|
21
23
|
transform: 'scale(1.035) rotate(-1.2deg)',
|
|
22
24
|
},
|
|
23
25
|
];
|
|
24
|
-
export const
|
|
25
|
-
{ boxShadow: '0 0 0 0 rgb(15 23 42 / 0)', transform: 'scale(1)' },
|
|
26
|
-
{
|
|
26
|
+
export const PsDragRowLiftFrames = [
|
|
27
|
+
{ boxShadow: '0 0 0 0 rgb(15 23 42 / 0)', transform: 'scale(1) rotate(0deg)' },
|
|
28
|
+
{
|
|
29
|
+
boxShadow: '0 28px 64px -18px rgb(15 23 42 / 0.5)',
|
|
30
|
+
transform: 'scale(1.035) rotate(-0.25deg)',
|
|
31
|
+
},
|
|
27
32
|
];
|
|
33
|
+
export const PsDragListLiftFrames = PsDragRowLiftFrames;
|
|
@@ -13,6 +13,7 @@ export const PsSkeletonConfig = {
|
|
|
13
13
|
importantPrefix: '!',
|
|
14
14
|
widthUtilityPattern: /^(w|size)-/,
|
|
15
15
|
heightUtilityPattern: /^(h|size)-/,
|
|
16
|
+
radiusUtilityPattern: /^rounded(-|$)/,
|
|
16
17
|
compactControlHeightClassName: 'h-ps-control-compact',
|
|
17
18
|
tabWidthClassName: 'w-24',
|
|
18
19
|
tabCount: 4,
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { KeyboardSensor, MouseSensor, TouchSensor, useSensor, useSensors, } from '@dnd-kit/core';
|
|
2
2
|
import { sortableKeyboardCoordinates } from '@dnd-kit/sortable';
|
|
3
3
|
import { PsDragConfig } from '../constants/ps-drag-config.js';
|
|
4
|
-
export const usePsDragSensors = () => useSensors(useSensor(MouseSensor, {
|
|
4
|
+
export const usePsDragSensors = (coordinateGetter = sortableKeyboardCoordinates) => useSensors(useSensor(MouseSensor, {
|
|
5
5
|
activationConstraint: { distance: PsDragConfig.activationDistance },
|
|
6
6
|
}), useSensor(TouchSensor, {
|
|
7
7
|
activationConstraint: {
|
|
8
8
|
delay: PsDragConfig.touchDelay,
|
|
9
9
|
tolerance: PsDragConfig.touchTolerance,
|
|
10
10
|
},
|
|
11
|
-
}), useSensor(KeyboardSensor, { coordinateGetter
|
|
11
|
+
}), useSensor(KeyboardSensor, { coordinateGetter }));
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { PsDragConfig } from '../constants/ps-drag-config.js';
|
|
2
|
+
import { usePsReducedMotion } from './use-ps-reduced-motion.js';
|
|
3
|
+
const transition = {
|
|
4
|
+
duration: PsDragConfig.sortDuration,
|
|
5
|
+
easing: PsDragConfig.sortEasing,
|
|
6
|
+
};
|
|
7
|
+
export const usePsDragTransition = () => {
|
|
8
|
+
const isReduced = usePsReducedMotion();
|
|
9
|
+
return isReduced ? null : transition;
|
|
10
|
+
};
|
|
@@ -1,17 +1,28 @@
|
|
|
1
|
-
import { useCallback, useMemo, useState } from 'react';
|
|
1
|
+
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
2
|
+
import { PsOptimisticConfig } from '../constants/ps-optimistic-config.js';
|
|
3
|
+
import { PsOptimisticReleaseService } from '../services/ps-optimistic-release-service.js';
|
|
2
4
|
export const usePsOptimisticRows = ({ apply, isHolding = false, isSaving, rows, }) => {
|
|
3
|
-
const [remembered, setRemembered] = useState(
|
|
4
|
-
base: rows,
|
|
5
|
-
changes: [],
|
|
6
|
-
});
|
|
5
|
+
const [remembered, setRemembered] = useState(() => PsOptimisticReleaseService.empty(rows));
|
|
7
6
|
const isActive = isSaving || isHolding;
|
|
8
|
-
const
|
|
9
|
-
if (
|
|
10
|
-
setRemembered(
|
|
11
|
-
const changes =
|
|
7
|
+
const current = PsOptimisticReleaseService.next(remembered, rows, isActive, apply);
|
|
8
|
+
if (current !== remembered)
|
|
9
|
+
setRemembered(current);
|
|
10
|
+
const { changes } = current;
|
|
11
|
+
const isHeld = changes.length > 0 && !isActive;
|
|
12
12
|
const shown = useMemo(() => (changes.length === 0 ? rows : apply(rows, changes)), [apply, changes, rows]);
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
if (!isHeld)
|
|
15
|
+
return undefined;
|
|
16
|
+
const timer = setTimeout(() => setRemembered(PsOptimisticReleaseService.empty(rows)), PsOptimisticConfig.releaseTimeoutMs);
|
|
17
|
+
return () => clearTimeout(timer);
|
|
18
|
+
}, [isHeld, changes, rows]);
|
|
19
|
+
const remember = useCallback((change) => setRemembered((previous) => ({
|
|
20
|
+
base: rows,
|
|
21
|
+
changes: [...previous.changes, change],
|
|
22
|
+
drainBase: null,
|
|
23
|
+
wasActive: previous.wasActive,
|
|
24
|
+
})), [rows]);
|
|
25
|
+
const forgetLast = useCallback(() => setRemembered((previous) => ({ ...previous, changes: previous.changes.slice(0, -1) })), []);
|
|
26
|
+
const rollback = useCallback(() => setRemembered(PsOptimisticReleaseService.empty(rows)), [rows]);
|
|
16
27
|
return { forgetLast, remember, rollback, rows: shown };
|
|
17
28
|
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
export const usePsPromiseValue = (promise, initial) => {
|
|
3
|
+
const [value, setValue] = useState(initial);
|
|
4
|
+
useEffect(() => {
|
|
5
|
+
let isCurrent = true;
|
|
6
|
+
void promise.then((resolved) => {
|
|
7
|
+
if (isCurrent)
|
|
8
|
+
setValue(resolved);
|
|
9
|
+
}, () => undefined);
|
|
10
|
+
return () => {
|
|
11
|
+
isCurrent = false;
|
|
12
|
+
};
|
|
13
|
+
}, [promise]);
|
|
14
|
+
return value;
|
|
15
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
export const usePsRetainedPromise = (promise) => {
|
|
3
|
+
const [state, setState] = useState({
|
|
4
|
+
hasFailed: false,
|
|
5
|
+
value: null,
|
|
6
|
+
});
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
let isCurrent = true;
|
|
9
|
+
void promise.then((value) => {
|
|
10
|
+
if (isCurrent)
|
|
11
|
+
setState({ hasFailed: false, value });
|
|
12
|
+
}, () => {
|
|
13
|
+
if (isCurrent)
|
|
14
|
+
setState((previous) => ({ ...previous, hasFailed: true }));
|
|
15
|
+
});
|
|
16
|
+
return () => {
|
|
17
|
+
isCurrent = false;
|
|
18
|
+
};
|
|
19
|
+
}, [promise]);
|
|
20
|
+
return state;
|
|
21
|
+
};
|
package/dist/esm/index.js
CHANGED
|
@@ -127,6 +127,12 @@ export * from './components/ps-active-filter-chip.js';
|
|
|
127
127
|
export * from './components/ps-back-link.js';
|
|
128
128
|
export * from './components/ps-card-block-skeleton.js';
|
|
129
129
|
export * from './components/ps-data-boundary.js';
|
|
130
|
+
export * from './constants/ps-data-boundary-config.js';
|
|
131
|
+
export * from './constants/ps-data-boundary-variant.js';
|
|
132
|
+
export * from './hooks/use-ps-retained-promise.js';
|
|
133
|
+
export * from './hooks/use-ps-promise-value.js';
|
|
134
|
+
export * from './interfaces/ps-retained-promise-data.js';
|
|
135
|
+
export * from './services/ps-deep-equal-service.js';
|
|
130
136
|
export * from './components/ps-faq-answer.js';
|
|
131
137
|
export * from './components/ps-feature-grid.js';
|
|
132
138
|
export * from './components/ps-feature-card.js';
|
|
@@ -188,6 +194,8 @@ export * from './models/ps-summary-item.js';
|
|
|
188
194
|
export * from './components/ps-drag-grip.js';
|
|
189
195
|
export * from './components/ps-drag-overlay.js';
|
|
190
196
|
export * from './hooks/use-ps-drag-sensors.js';
|
|
197
|
+
export * from './hooks/use-ps-drag-transition.js';
|
|
198
|
+
export * from './models/ps-drag-transition.js';
|
|
191
199
|
export * from './hooks/use-ps-list-keys.js';
|
|
192
200
|
export * from './interfaces/ps-list-keys-result.js';
|
|
193
201
|
export * from './services/ps-list-key-service.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export class PsDeepEqualService {
|
|
2
|
+
static isEqual(left, right) {
|
|
3
|
+
if (Object.is(left, right))
|
|
4
|
+
return true;
|
|
5
|
+
if (typeof left !== 'object' || typeof right !== 'object')
|
|
6
|
+
return false;
|
|
7
|
+
if (left === null || right === null)
|
|
8
|
+
return false;
|
|
9
|
+
if (Array.isArray(left) || Array.isArray(right))
|
|
10
|
+
return PsDeepEqualService.isArrayEqual(left, right);
|
|
11
|
+
if (left instanceof Date || right instanceof Date) {
|
|
12
|
+
return left instanceof Date && right instanceof Date && left.getTime() === right.getTime();
|
|
13
|
+
}
|
|
14
|
+
return PsDeepEqualService.isRecordEqual(left, right);
|
|
15
|
+
}
|
|
16
|
+
static isArrayEqual(left, right) {
|
|
17
|
+
if (!Array.isArray(left) || !Array.isArray(right))
|
|
18
|
+
return false;
|
|
19
|
+
if (left.length !== right.length)
|
|
20
|
+
return false;
|
|
21
|
+
return left.every((item, index) => PsDeepEqualService.isEqual(item, right[index]));
|
|
22
|
+
}
|
|
23
|
+
static isRecordEqual(left, right) {
|
|
24
|
+
const leftEntries = Object.entries(left);
|
|
25
|
+
const rightRecord = { ...right };
|
|
26
|
+
if (leftEntries.length !== Object.keys(rightRecord).length)
|
|
27
|
+
return false;
|
|
28
|
+
return leftEntries.every(([key, value]) => Object.prototype.hasOwnProperty.call(rightRecord, key) &&
|
|
29
|
+
PsDeepEqualService.isEqual(value, rightRecord[key]));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { PsDeepEqualService } from './ps-deep-equal-service.js';
|
|
2
|
+
export class PsOptimisticReleaseService {
|
|
3
|
+
static empty(rows) {
|
|
4
|
+
return { base: rows, changes: [], drainBase: null, wasActive: false };
|
|
5
|
+
}
|
|
6
|
+
static next(remembered, rows, isActive, apply) {
|
|
7
|
+
if (isActive) {
|
|
8
|
+
if (remembered.wasActive && remembered.drainBase === null)
|
|
9
|
+
return remembered;
|
|
10
|
+
return { ...remembered, drainBase: null, wasActive: true };
|
|
11
|
+
}
|
|
12
|
+
if (remembered.changes.length === 0) {
|
|
13
|
+
if (remembered.base === rows && !remembered.wasActive)
|
|
14
|
+
return remembered;
|
|
15
|
+
return PsOptimisticReleaseService.empty(rows);
|
|
16
|
+
}
|
|
17
|
+
if (remembered.wasActive) {
|
|
18
|
+
if (!PsDeepEqualService.isEqual(rows, remembered.base)) {
|
|
19
|
+
return PsOptimisticReleaseService.empty(rows);
|
|
20
|
+
}
|
|
21
|
+
return { ...remembered, drainBase: rows, wasActive: false };
|
|
22
|
+
}
|
|
23
|
+
const reference = remembered.drainBase === null ? remembered.base : remembered.drainBase;
|
|
24
|
+
if (!PsDeepEqualService.isEqual(rows, reference)) {
|
|
25
|
+
return PsOptimisticReleaseService.empty(rows);
|
|
26
|
+
}
|
|
27
|
+
if (PsDeepEqualService.isEqual(apply(rows, remembered.changes), rows)) {
|
|
28
|
+
return PsOptimisticReleaseService.empty(rows);
|
|
29
|
+
}
|
|
30
|
+
return remembered;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -10,8 +10,18 @@ export class PsSkeletonClassService {
|
|
|
10
10
|
: [];
|
|
11
11
|
const hasWidth = utilities.some((utility) => PsSkeletonConfig.widthUtilityPattern.test(utility));
|
|
12
12
|
const hasHeight = utilities.some((utility) => PsSkeletonConfig.heightUtilityPattern.test(utility));
|
|
13
|
+
const hasRadius = utilities.some((utility) => PsSkeletonConfig.radiusUtilityPattern.test(utility));
|
|
13
14
|
const size = PsSkeletonConfig.shapeSizes[shape];
|
|
14
|
-
|
|
15
|
+
const shapeClassName = hasRadius
|
|
16
|
+
? PsSkeletonClassService.withoutRadius(PsSkeletonConfig.shapeClassNames[shape])
|
|
17
|
+
: PsSkeletonConfig.shapeClassNames[shape];
|
|
18
|
+
return PallasoftClassNameService.merge(PsSkeletonConfig.baseClassName, shapeClassName, hasHeight ? null : size.height, hasWidth ? null : size.width, className);
|
|
19
|
+
}
|
|
20
|
+
static withoutRadius(className) {
|
|
21
|
+
return className
|
|
22
|
+
.split(PsSkeletonConfig.classSeparator)
|
|
23
|
+
.filter((token) => !PsSkeletonConfig.radiusUtilityPattern.test(token))
|
|
24
|
+
.join(' ');
|
|
15
25
|
}
|
|
16
26
|
static withoutImportant(token) {
|
|
17
27
|
return token.startsWith(PsSkeletonConfig.importantPrefix) ? token.slice(1) : token;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { type SensorDescriptor, type SensorOptions } from '@dnd-kit/core';
|
|
2
|
-
export declare const usePsDragSensors: () => SensorDescriptor<SensorOptions>[];
|
|
1
|
+
import { type KeyboardCoordinateGetter, type SensorDescriptor, type SensorOptions } from '@dnd-kit/core';
|
|
2
|
+
export declare const usePsDragSensors: (coordinateGetter?: KeyboardCoordinateGetter) => SensorDescriptor<SensorOptions>[];
|
|
@@ -4,12 +4,12 @@ exports.usePsDragSensors = void 0;
|
|
|
4
4
|
const core_1 = require("@dnd-kit/core");
|
|
5
5
|
const sortable_1 = require("@dnd-kit/sortable");
|
|
6
6
|
const ps_drag_config_1 = require("../constants/ps-drag-config");
|
|
7
|
-
const usePsDragSensors = () => (0, core_1.useSensors)((0, core_1.useSensor)(core_1.MouseSensor, {
|
|
7
|
+
const usePsDragSensors = (coordinateGetter = sortable_1.sortableKeyboardCoordinates) => (0, core_1.useSensors)((0, core_1.useSensor)(core_1.MouseSensor, {
|
|
8
8
|
activationConstraint: { distance: ps_drag_config_1.PsDragConfig.activationDistance },
|
|
9
9
|
}), (0, core_1.useSensor)(core_1.TouchSensor, {
|
|
10
10
|
activationConstraint: {
|
|
11
11
|
delay: ps_drag_config_1.PsDragConfig.touchDelay,
|
|
12
12
|
tolerance: ps_drag_config_1.PsDragConfig.touchTolerance,
|
|
13
13
|
},
|
|
14
|
-
}), (0, core_1.useSensor)(core_1.KeyboardSensor, { coordinateGetter
|
|
14
|
+
}), (0, core_1.useSensor)(core_1.KeyboardSensor, { coordinateGetter }));
|
|
15
15
|
exports.usePsDragSensors = usePsDragSensors;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.usePsDragTransition = void 0;
|
|
4
|
+
const ps_drag_config_1 = require("../constants/ps-drag-config");
|
|
5
|
+
const use_ps_reduced_motion_1 = require("./use-ps-reduced-motion");
|
|
6
|
+
const transition = {
|
|
7
|
+
duration: ps_drag_config_1.PsDragConfig.sortDuration,
|
|
8
|
+
easing: ps_drag_config_1.PsDragConfig.sortEasing,
|
|
9
|
+
};
|
|
10
|
+
const usePsDragTransition = () => {
|
|
11
|
+
const isReduced = (0, use_ps_reduced_motion_1.usePsReducedMotion)();
|
|
12
|
+
return isReduced ? null : transition;
|
|
13
|
+
};
|
|
14
|
+
exports.usePsDragTransition = usePsDragTransition;
|
|
@@ -2,20 +2,31 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.usePsOptimisticRows = void 0;
|
|
4
4
|
const react_1 = require("react");
|
|
5
|
+
const ps_optimistic_config_1 = require("../constants/ps-optimistic-config");
|
|
6
|
+
const ps_optimistic_release_service_1 = require("../services/ps-optimistic-release-service");
|
|
5
7
|
const usePsOptimisticRows = ({ apply, isHolding = false, isSaving, rows, }) => {
|
|
6
|
-
const [remembered, setRemembered] = (0, react_1.useState)(
|
|
7
|
-
base: rows,
|
|
8
|
-
changes: [],
|
|
9
|
-
});
|
|
8
|
+
const [remembered, setRemembered] = (0, react_1.useState)(() => ps_optimistic_release_service_1.PsOptimisticReleaseService.empty(rows));
|
|
10
9
|
const isActive = isSaving || isHolding;
|
|
11
|
-
const
|
|
12
|
-
if (
|
|
13
|
-
setRemembered(
|
|
14
|
-
const changes =
|
|
10
|
+
const current = ps_optimistic_release_service_1.PsOptimisticReleaseService.next(remembered, rows, isActive, apply);
|
|
11
|
+
if (current !== remembered)
|
|
12
|
+
setRemembered(current);
|
|
13
|
+
const { changes } = current;
|
|
14
|
+
const isHeld = changes.length > 0 && !isActive;
|
|
15
15
|
const shown = (0, react_1.useMemo)(() => (changes.length === 0 ? rows : apply(rows, changes)), [apply, changes, rows]);
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
(0, react_1.useEffect)(() => {
|
|
17
|
+
if (!isHeld)
|
|
18
|
+
return undefined;
|
|
19
|
+
const timer = setTimeout(() => setRemembered(ps_optimistic_release_service_1.PsOptimisticReleaseService.empty(rows)), ps_optimistic_config_1.PsOptimisticConfig.releaseTimeoutMs);
|
|
20
|
+
return () => clearTimeout(timer);
|
|
21
|
+
}, [isHeld, changes, rows]);
|
|
22
|
+
const remember = (0, react_1.useCallback)((change) => setRemembered((previous) => ({
|
|
23
|
+
base: rows,
|
|
24
|
+
changes: [...previous.changes, change],
|
|
25
|
+
drainBase: null,
|
|
26
|
+
wasActive: previous.wasActive,
|
|
27
|
+
})), [rows]);
|
|
28
|
+
const forgetLast = (0, react_1.useCallback)(() => setRemembered((previous) => ({ ...previous, changes: previous.changes.slice(0, -1) })), []);
|
|
29
|
+
const rollback = (0, react_1.useCallback)(() => setRemembered(ps_optimistic_release_service_1.PsOptimisticReleaseService.empty(rows)), [rows]);
|
|
19
30
|
return { forgetLast, remember, rollback, rows: shown };
|
|
20
31
|
};
|
|
21
32
|
exports.usePsOptimisticRows = usePsOptimisticRows;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const usePsPromiseValue: <Value>(promise: Promise<Value>, initial: Value) => Value;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.usePsPromiseValue = void 0;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const usePsPromiseValue = (promise, initial) => {
|
|
6
|
+
const [value, setValue] = (0, react_1.useState)(initial);
|
|
7
|
+
(0, react_1.useEffect)(() => {
|
|
8
|
+
let isCurrent = true;
|
|
9
|
+
void promise.then((resolved) => {
|
|
10
|
+
if (isCurrent)
|
|
11
|
+
setValue(resolved);
|
|
12
|
+
}, () => undefined);
|
|
13
|
+
return () => {
|
|
14
|
+
isCurrent = false;
|
|
15
|
+
};
|
|
16
|
+
}, [promise]);
|
|
17
|
+
return value;
|
|
18
|
+
};
|
|
19
|
+
exports.usePsPromiseValue = usePsPromiseValue;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.usePsRetainedPromise = void 0;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const usePsRetainedPromise = (promise) => {
|
|
6
|
+
const [state, setState] = (0, react_1.useState)({
|
|
7
|
+
hasFailed: false,
|
|
8
|
+
value: null,
|
|
9
|
+
});
|
|
10
|
+
(0, react_1.useEffect)(() => {
|
|
11
|
+
let isCurrent = true;
|
|
12
|
+
void promise.then((value) => {
|
|
13
|
+
if (isCurrent)
|
|
14
|
+
setState({ hasFailed: false, value });
|
|
15
|
+
}, () => {
|
|
16
|
+
if (isCurrent)
|
|
17
|
+
setState((previous) => ({ ...previous, hasFailed: true }));
|
|
18
|
+
});
|
|
19
|
+
return () => {
|
|
20
|
+
isCurrent = false;
|
|
21
|
+
};
|
|
22
|
+
}, [promise]);
|
|
23
|
+
return state;
|
|
24
|
+
};
|
|
25
|
+
exports.usePsRetainedPromise = usePsRetainedPromise;
|
package/dist/index.d.ts
CHANGED
|
@@ -127,6 +127,12 @@ export * from './components/ps-active-filter-chip';
|
|
|
127
127
|
export * from './components/ps-back-link';
|
|
128
128
|
export * from './components/ps-card-block-skeleton';
|
|
129
129
|
export * from './components/ps-data-boundary';
|
|
130
|
+
export * from './constants/ps-data-boundary-config';
|
|
131
|
+
export * from './constants/ps-data-boundary-variant';
|
|
132
|
+
export * from './hooks/use-ps-retained-promise';
|
|
133
|
+
export * from './hooks/use-ps-promise-value';
|
|
134
|
+
export * from './interfaces/ps-retained-promise-data';
|
|
135
|
+
export * from './services/ps-deep-equal-service';
|
|
130
136
|
export * from './components/ps-faq-answer';
|
|
131
137
|
export * from './components/ps-feature-grid';
|
|
132
138
|
export * from './components/ps-feature-card';
|
|
@@ -188,6 +194,8 @@ export * from './models/ps-summary-item';
|
|
|
188
194
|
export * from './components/ps-drag-grip';
|
|
189
195
|
export * from './components/ps-drag-overlay';
|
|
190
196
|
export * from './hooks/use-ps-drag-sensors';
|
|
197
|
+
export * from './hooks/use-ps-drag-transition';
|
|
198
|
+
export * from './models/ps-drag-transition';
|
|
191
199
|
export * from './hooks/use-ps-list-keys';
|
|
192
200
|
export * from './interfaces/ps-list-keys-result';
|
|
193
201
|
export * from './services/ps-list-key-service';
|
package/dist/index.js
CHANGED
|
@@ -143,6 +143,12 @@ __exportStar(require("./components/ps-active-filter-chip"), exports);
|
|
|
143
143
|
__exportStar(require("./components/ps-back-link"), exports);
|
|
144
144
|
__exportStar(require("./components/ps-card-block-skeleton"), exports);
|
|
145
145
|
__exportStar(require("./components/ps-data-boundary"), exports);
|
|
146
|
+
__exportStar(require("./constants/ps-data-boundary-config"), exports);
|
|
147
|
+
__exportStar(require("./constants/ps-data-boundary-variant"), exports);
|
|
148
|
+
__exportStar(require("./hooks/use-ps-retained-promise"), exports);
|
|
149
|
+
__exportStar(require("./hooks/use-ps-promise-value"), exports);
|
|
150
|
+
__exportStar(require("./interfaces/ps-retained-promise-data"), exports);
|
|
151
|
+
__exportStar(require("./services/ps-deep-equal-service"), exports);
|
|
146
152
|
__exportStar(require("./components/ps-faq-answer"), exports);
|
|
147
153
|
__exportStar(require("./components/ps-feature-grid"), exports);
|
|
148
154
|
__exportStar(require("./components/ps-feature-card"), exports);
|
|
@@ -204,6 +210,8 @@ __exportStar(require("./models/ps-summary-item"), exports);
|
|
|
204
210
|
__exportStar(require("./components/ps-drag-grip"), exports);
|
|
205
211
|
__exportStar(require("./components/ps-drag-overlay"), exports);
|
|
206
212
|
__exportStar(require("./hooks/use-ps-drag-sensors"), exports);
|
|
213
|
+
__exportStar(require("./hooks/use-ps-drag-transition"), exports);
|
|
214
|
+
__exportStar(require("./models/ps-drag-transition"), exports);
|
|
207
215
|
__exportStar(require("./hooks/use-ps-list-keys"), exports);
|
|
208
216
|
__exportStar(require("./interfaces/ps-list-keys-result"), exports);
|
|
209
217
|
__exportStar(require("./services/ps-list-key-service"), exports);
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PsDeepEqualService = void 0;
|
|
4
|
+
class PsDeepEqualService {
|
|
5
|
+
static isEqual(left, right) {
|
|
6
|
+
if (Object.is(left, right))
|
|
7
|
+
return true;
|
|
8
|
+
if (typeof left !== 'object' || typeof right !== 'object')
|
|
9
|
+
return false;
|
|
10
|
+
if (left === null || right === null)
|
|
11
|
+
return false;
|
|
12
|
+
if (Array.isArray(left) || Array.isArray(right))
|
|
13
|
+
return PsDeepEqualService.isArrayEqual(left, right);
|
|
14
|
+
if (left instanceof Date || right instanceof Date) {
|
|
15
|
+
return left instanceof Date && right instanceof Date && left.getTime() === right.getTime();
|
|
16
|
+
}
|
|
17
|
+
return PsDeepEqualService.isRecordEqual(left, right);
|
|
18
|
+
}
|
|
19
|
+
static isArrayEqual(left, right) {
|
|
20
|
+
if (!Array.isArray(left) || !Array.isArray(right))
|
|
21
|
+
return false;
|
|
22
|
+
if (left.length !== right.length)
|
|
23
|
+
return false;
|
|
24
|
+
return left.every((item, index) => PsDeepEqualService.isEqual(item, right[index]));
|
|
25
|
+
}
|
|
26
|
+
static isRecordEqual(left, right) {
|
|
27
|
+
const leftEntries = Object.entries(left);
|
|
28
|
+
const rightRecord = { ...right };
|
|
29
|
+
if (leftEntries.length !== Object.keys(rightRecord).length)
|
|
30
|
+
return false;
|
|
31
|
+
return leftEntries.every(([key, value]) => Object.prototype.hasOwnProperty.call(rightRecord, key) &&
|
|
32
|
+
PsDeepEqualService.isEqual(value, rightRecord[key]));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
exports.PsDeepEqualService = PsDeepEqualService;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { PsOptimisticChanges } from '../interfaces/ps-optimistic-changes';
|
|
2
|
+
export declare class PsOptimisticReleaseService {
|
|
3
|
+
static empty<Row, Change>(rows: Row[]): PsOptimisticChanges<Row, Change>;
|
|
4
|
+
static next<Row, Change>(remembered: PsOptimisticChanges<Row, Change>, rows: Row[], isActive: boolean, apply: (rows: Row[], changes: Change[]) => Row[]): PsOptimisticChanges<Row, Change>;
|
|
5
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PsOptimisticReleaseService = void 0;
|
|
4
|
+
const ps_deep_equal_service_1 = require("./ps-deep-equal-service");
|
|
5
|
+
class PsOptimisticReleaseService {
|
|
6
|
+
static empty(rows) {
|
|
7
|
+
return { base: rows, changes: [], drainBase: null, wasActive: false };
|
|
8
|
+
}
|
|
9
|
+
static next(remembered, rows, isActive, apply) {
|
|
10
|
+
if (isActive) {
|
|
11
|
+
if (remembered.wasActive && remembered.drainBase === null)
|
|
12
|
+
return remembered;
|
|
13
|
+
return { ...remembered, drainBase: null, wasActive: true };
|
|
14
|
+
}
|
|
15
|
+
if (remembered.changes.length === 0) {
|
|
16
|
+
if (remembered.base === rows && !remembered.wasActive)
|
|
17
|
+
return remembered;
|
|
18
|
+
return PsOptimisticReleaseService.empty(rows);
|
|
19
|
+
}
|
|
20
|
+
if (remembered.wasActive) {
|
|
21
|
+
if (!ps_deep_equal_service_1.PsDeepEqualService.isEqual(rows, remembered.base)) {
|
|
22
|
+
return PsOptimisticReleaseService.empty(rows);
|
|
23
|
+
}
|
|
24
|
+
return { ...remembered, drainBase: rows, wasActive: false };
|
|
25
|
+
}
|
|
26
|
+
const reference = remembered.drainBase === null ? remembered.base : remembered.drainBase;
|
|
27
|
+
if (!ps_deep_equal_service_1.PsDeepEqualService.isEqual(rows, reference)) {
|
|
28
|
+
return PsOptimisticReleaseService.empty(rows);
|
|
29
|
+
}
|
|
30
|
+
if (ps_deep_equal_service_1.PsDeepEqualService.isEqual(apply(rows, remembered.changes), rows)) {
|
|
31
|
+
return PsOptimisticReleaseService.empty(rows);
|
|
32
|
+
}
|
|
33
|
+
return remembered;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
exports.PsOptimisticReleaseService = PsOptimisticReleaseService;
|
|
@@ -13,8 +13,18 @@ class PsSkeletonClassService {
|
|
|
13
13
|
: [];
|
|
14
14
|
const hasWidth = utilities.some((utility) => ps_skeleton_config_1.PsSkeletonConfig.widthUtilityPattern.test(utility));
|
|
15
15
|
const hasHeight = utilities.some((utility) => ps_skeleton_config_1.PsSkeletonConfig.heightUtilityPattern.test(utility));
|
|
16
|
+
const hasRadius = utilities.some((utility) => ps_skeleton_config_1.PsSkeletonConfig.radiusUtilityPattern.test(utility));
|
|
16
17
|
const size = ps_skeleton_config_1.PsSkeletonConfig.shapeSizes[shape];
|
|
17
|
-
|
|
18
|
+
const shapeClassName = hasRadius
|
|
19
|
+
? PsSkeletonClassService.withoutRadius(ps_skeleton_config_1.PsSkeletonConfig.shapeClassNames[shape])
|
|
20
|
+
: ps_skeleton_config_1.PsSkeletonConfig.shapeClassNames[shape];
|
|
21
|
+
return ps_design_system_1.PallasoftClassNameService.merge(ps_skeleton_config_1.PsSkeletonConfig.baseClassName, shapeClassName, hasHeight ? null : size.height, hasWidth ? null : size.width, className);
|
|
22
|
+
}
|
|
23
|
+
static withoutRadius(className) {
|
|
24
|
+
return className
|
|
25
|
+
.split(ps_skeleton_config_1.PsSkeletonConfig.classSeparator)
|
|
26
|
+
.filter((token) => !ps_skeleton_config_1.PsSkeletonConfig.radiusUtilityPattern.test(token))
|
|
27
|
+
.join(' ');
|
|
18
28
|
}
|
|
19
29
|
static withoutImportant(token) {
|
|
20
30
|
return token.startsWith(ps_skeleton_config_1.PsSkeletonConfig.importantPrefix) ? token.slice(1) : token;
|