@pallasoft/ps-core-components 2.27.0 → 2.29.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-overview-card.d.ts +12 -0
- package/dist/components/ps-overview-card.js +7 -0
- package/dist/components/ps-rating-display.d.ts +9 -0
- package/dist/components/ps-rating-display.js +12 -0
- package/dist/components/ps-sortable-list.d.ts +1 -1
- package/dist/components/ps-sortable-list.js +2 -2
- package/dist/constants/ps-rating-display-config.d.ts +10 -0
- package/dist/constants/ps-rating-display-config.js +14 -0
- package/dist/constants/ps-rating-display-size.d.ts +5 -0
- package/dist/constants/ps-rating-display-size.js +9 -0
- package/dist/esm/components/ps-overview-card.js +3 -0
- package/dist/esm/components/ps-rating-display.js +8 -0
- package/dist/esm/components/ps-sortable-list.js +3 -3
- package/dist/esm/constants/ps-rating-display-config.js +11 -0
- package/dist/esm/constants/ps-rating-display-size.js +6 -0
- package/dist/esm/hooks/use-ps-optimistic-fetcher.js +68 -0
- package/dist/esm/index.js +9 -0
- package/dist/esm/interfaces/ps-fetcher-like.js +1 -0
- package/dist/esm/interfaces/ps-fetcher-submit-options.js +1 -0
- package/dist/esm/interfaces/ps-optimistic-fetcher-input.js +1 -0
- package/dist/esm/interfaces/ps-optimistic-fetcher-result.js +1 -0
- package/dist/esm/interfaces/ps-revalidator-like.js +1 -0
- package/dist/hooks/use-ps-optimistic-fetcher.d.ts +3 -0
- package/dist/hooks/use-ps-optimistic-fetcher.js +72 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +9 -0
- package/dist/interfaces/ps-fetcher-like.d.ts +6 -0
- package/dist/interfaces/ps-fetcher-like.js +2 -0
- package/dist/interfaces/ps-fetcher-submit-options.d.ts +3 -0
- package/dist/interfaces/ps-fetcher-submit-options.js +2 -0
- package/dist/interfaces/ps-optimistic-fetcher-input.d.ts +11 -0
- package/dist/interfaces/ps-optimistic-fetcher-input.js +2 -0
- package/dist/interfaces/ps-optimistic-fetcher-result.d.ts +4 -0
- package/dist/interfaces/ps-optimistic-fetcher-result.js +2 -0
- package/dist/interfaces/ps-revalidator-like.d.ts +4 -0
- package/dist/interfaces/ps-revalidator-like.js +2 -0
- package/dist/models/ps-sortable-list.d.ts +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
export interface PsOverviewCardProps {
|
|
3
|
+
action?: ReactNode;
|
|
4
|
+
badge?: ReactNode;
|
|
5
|
+
children?: ReactNode;
|
|
6
|
+
className?: string;
|
|
7
|
+
footer?: ReactNode;
|
|
8
|
+
icon?: ReactNode;
|
|
9
|
+
summary?: string;
|
|
10
|
+
title: string;
|
|
11
|
+
}
|
|
12
|
+
export declare const PsOverviewCard: ({ action, badge, children, className, footer, icon, summary, title, }: PsOverviewCardProps) => import("react").JSX.Element;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PsOverviewCard = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const ps_design_system_1 = require("@pallasoft/ps-design-system");
|
|
6
|
+
const PsOverviewCard = ({ action, badge, children, className, footer, icon, summary, title, }) => ((0, jsx_runtime_1.jsxs)("section", { className: ps_design_system_1.PallasoftClassNameService.merge('flex min-w-0 flex-col gap-4 rounded-ps-panel border border-line bg-surface p-5', className), children: [(0, jsx_runtime_1.jsxs)("header", { className: 'flex min-w-0 items-start gap-3', children: [icon ? (0, jsx_runtime_1.jsx)("span", { className: 'ps-icon-surface h-10 w-10 shrink-0', children: icon }) : null, (0, jsx_runtime_1.jsxs)("div", { className: 'flex min-w-0 flex-1 flex-col gap-1', children: [(0, jsx_runtime_1.jsxs)("div", { className: 'flex flex-wrap items-center gap-2', children: [(0, jsx_runtime_1.jsx)("h2", { className: 'text-base font-semibold text-ink', children: title }), badge] }), summary ? (0, jsx_runtime_1.jsx)("p", { className: 'break-words text-sm leading-6 text-ink/60', children: summary }) : null] }), action ? (0, jsx_runtime_1.jsx)("div", { className: 'flex shrink-0 items-center gap-2', children: action }) : null] }), children ? (0, jsx_runtime_1.jsx)("div", { className: 'flex min-w-0 flex-col gap-1', children: children }) : null, footer ? (0, jsx_runtime_1.jsx)("div", { className: 'flex flex-wrap items-center gap-2', children: footer }) : null] }));
|
|
7
|
+
exports.PsOverviewCard = PsOverviewCard;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { PsRatingDisplaySize } from '../constants/ps-rating-display-size';
|
|
2
|
+
export interface PsRatingDisplayProps {
|
|
3
|
+
className?: string;
|
|
4
|
+
label: string;
|
|
5
|
+
max?: number;
|
|
6
|
+
score: number;
|
|
7
|
+
size?: PsRatingDisplaySize;
|
|
8
|
+
}
|
|
9
|
+
export declare const PsRatingDisplay: ({ className, label, max, score, size, }: PsRatingDisplayProps) => import("react").JSX.Element;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PsRatingDisplay = 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_icons_1 = require("@pallasoft/ps-icons");
|
|
7
|
+
const ps_rating_display_config_1 = require("../constants/ps-rating-display-config");
|
|
8
|
+
const ps_rating_display_size_1 = require("../constants/ps-rating-display-size");
|
|
9
|
+
const PsRatingDisplay = ({ className, label, max = ps_rating_display_config_1.PsRatingDisplayConfig.defaultMax, score, size = ps_rating_display_size_1.PsRatingDisplaySize.Medium, }) => ((0, jsx_runtime_1.jsx)("div", { "aria-label": label, className: ps_design_system_1.PallasoftClassNameService.merge('flex items-center gap-1', className), role: 'img', children: Array.from({ length: max }, (_, index) => index + 1).map((value) => ((0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { className: ps_design_system_1.PallasoftClassNameService.merge(ps_rating_display_config_1.PsRatingDisplayConfig.iconClassNames[size], value <= score
|
|
10
|
+
? ps_rating_display_config_1.PsRatingDisplayConfig.filledClassName
|
|
11
|
+
: ps_rating_display_config_1.PsRatingDisplayConfig.emptyClassName), iconKey: ps_icons_1.PsIconKey.Star }, value))) }));
|
|
12
|
+
exports.PsRatingDisplay = PsRatingDisplay;
|
|
@@ -19,4 +19,4 @@ export interface PsSortableListRowProps<TItem extends PsSortableListItem> {
|
|
|
19
19
|
item: TItem;
|
|
20
20
|
renderItem: (options: PsSortableListRenderOptions<TItem>) => JSX.Element | null;
|
|
21
21
|
}
|
|
22
|
-
export declare const PsSortableList: <TItem extends PsSortableListItem>({ announcements: texts, className, getHandleLabel, getItemClassName, handleClassName, handleIcon, instructions, role, items, onMove, renderItem, }: PsSortableListProps<TItem>) => JSX.Element;
|
|
22
|
+
export declare const PsSortableList: <TItem extends PsSortableListItem>({ announcements: texts, className, getHandleLabel, getItemClassName, handleClassName, handleIcon, instructions, isHorizontal, role, items, onMove, renderItem, }: PsSortableListProps<TItem>) => JSX.Element;
|
|
@@ -30,7 +30,7 @@ const PsSortableListRow = ({ className, handleClassName, handleIcon, getHandleLa
|
|
|
30
30
|
transition: isReduced ? undefined : transition,
|
|
31
31
|
}, children: rendered }));
|
|
32
32
|
};
|
|
33
|
-
const PsSortableList = ({ announcements: texts, className, getHandleLabel, getItemClassName, handleClassName, handleIcon, instructions, role, items, onMove, renderItem, }) => {
|
|
33
|
+
const PsSortableList = ({ announcements: texts, className, getHandleLabel, getItemClassName, handleClassName, handleIcon, instructions, isHorizontal = false, role, items, onMove, renderItem, }) => {
|
|
34
34
|
const [activeId, setActiveId] = (0, react_1.useState)(null);
|
|
35
35
|
const sensors = (0, use_ps_drag_sensors_1.usePsDragSensors)();
|
|
36
36
|
const activeIndex = items.findIndex((item) => item.id === activeId);
|
|
@@ -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: 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.PsDragListLiftFrames, children: activeItem !== null
|
|
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.PsDragListLiftFrames, 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,10 @@
|
|
|
1
|
+
export declare const PsRatingDisplayConfig: {
|
|
2
|
+
readonly defaultMax: 5;
|
|
3
|
+
readonly filledClassName: "fill-current text-primary";
|
|
4
|
+
readonly emptyClassName: "text-ink/30 dark:text-white/30";
|
|
5
|
+
readonly iconClassNames: {
|
|
6
|
+
readonly large: "h-8 w-8";
|
|
7
|
+
readonly medium: "h-6 w-6";
|
|
8
|
+
readonly small: "h-4 w-4";
|
|
9
|
+
};
|
|
10
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PsRatingDisplayConfig = void 0;
|
|
4
|
+
const ps_rating_display_size_1 = require("./ps-rating-display-size");
|
|
5
|
+
exports.PsRatingDisplayConfig = {
|
|
6
|
+
defaultMax: 5,
|
|
7
|
+
filledClassName: 'fill-current text-primary',
|
|
8
|
+
emptyClassName: 'text-ink/30 dark:text-white/30',
|
|
9
|
+
iconClassNames: {
|
|
10
|
+
[ps_rating_display_size_1.PsRatingDisplaySize.Large]: 'h-8 w-8',
|
|
11
|
+
[ps_rating_display_size_1.PsRatingDisplaySize.Medium]: 'h-6 w-6',
|
|
12
|
+
[ps_rating_display_size_1.PsRatingDisplaySize.Small]: 'h-4 w-4',
|
|
13
|
+
},
|
|
14
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PsRatingDisplaySize = void 0;
|
|
4
|
+
var PsRatingDisplaySize;
|
|
5
|
+
(function (PsRatingDisplaySize) {
|
|
6
|
+
PsRatingDisplaySize["Large"] = "large";
|
|
7
|
+
PsRatingDisplaySize["Medium"] = "medium";
|
|
8
|
+
PsRatingDisplaySize["Small"] = "small";
|
|
9
|
+
})(PsRatingDisplaySize || (exports.PsRatingDisplaySize = PsRatingDisplaySize = {}));
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
|
|
3
|
+
export const PsOverviewCard = ({ action, badge, children, className, footer, icon, summary, title, }) => (_jsxs("section", { className: PallasoftClassNameService.merge('flex min-w-0 flex-col gap-4 rounded-ps-panel border border-line bg-surface p-5', className), children: [_jsxs("header", { className: 'flex min-w-0 items-start gap-3', children: [icon ? _jsx("span", { className: 'ps-icon-surface h-10 w-10 shrink-0', children: icon }) : null, _jsxs("div", { className: 'flex min-w-0 flex-1 flex-col gap-1', children: [_jsxs("div", { className: 'flex flex-wrap items-center gap-2', children: [_jsx("h2", { className: 'text-base font-semibold text-ink', children: title }), badge] }), summary ? _jsx("p", { className: 'break-words text-sm leading-6 text-ink/60', children: summary }) : null] }), action ? _jsx("div", { className: 'flex shrink-0 items-center gap-2', children: action }) : null] }), children ? _jsx("div", { className: 'flex min-w-0 flex-col gap-1', children: children }) : null, footer ? _jsx("div", { className: 'flex flex-wrap items-center gap-2', children: footer }) : null] }));
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
|
|
3
|
+
import { PsIcon, PsIconKey } from '@pallasoft/ps-icons';
|
|
4
|
+
import { PsRatingDisplayConfig } from '../constants/ps-rating-display-config';
|
|
5
|
+
import { PsRatingDisplaySize } from '../constants/ps-rating-display-size';
|
|
6
|
+
export const PsRatingDisplay = ({ className, label, max = PsRatingDisplayConfig.defaultMax, score, size = PsRatingDisplaySize.Medium, }) => (_jsx("div", { "aria-label": label, className: PallasoftClassNameService.merge('flex items-center gap-1', className), role: 'img', children: Array.from({ length: max }, (_, index) => index + 1).map((value) => (_jsx(PsIcon, { className: PallasoftClassNameService.merge(PsRatingDisplayConfig.iconClassNames[size], value <= score
|
|
7
|
+
? PsRatingDisplayConfig.filledClassName
|
|
8
|
+
: PsRatingDisplayConfig.emptyClassName), iconKey: PsIconKey.Star }, value))) }));
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useState } from 'react';
|
|
3
3
|
import { DndContext, closestCenter, } from '@dnd-kit/core';
|
|
4
|
-
import { SortableContext, useSortable, verticalListSortingStrategy } from '@dnd-kit/sortable';
|
|
4
|
+
import { SortableContext, horizontalListSortingStrategy, useSortable, verticalListSortingStrategy, } from '@dnd-kit/sortable';
|
|
5
5
|
import { CSS } from '@dnd-kit/utilities';
|
|
6
6
|
import { PsDragClasses, PsDragConfig, PsDragListLiftFrames } from '../constants/ps-drag-config';
|
|
7
7
|
import { usePsDragSensors } from '../hooks/use-ps-drag-sensors';
|
|
@@ -27,7 +27,7 @@ const PsSortableListRow = ({ className, handleClassName, handleIcon, getHandleLa
|
|
|
27
27
|
transition: isReduced ? undefined : transition,
|
|
28
28
|
}, children: rendered }));
|
|
29
29
|
};
|
|
30
|
-
export const PsSortableList = ({ announcements: texts, className, getHandleLabel, getItemClassName, handleClassName, handleIcon, instructions, role, items, onMove, renderItem, }) => {
|
|
30
|
+
export const PsSortableList = ({ announcements: texts, className, getHandleLabel, getItemClassName, handleClassName, handleIcon, instructions, isHorizontal = false, role, items, onMove, renderItem, }) => {
|
|
31
31
|
const [activeId, setActiveId] = useState(null);
|
|
32
32
|
const sensors = usePsDragSensors();
|
|
33
33
|
const activeIndex = items.findIndex((item) => item.id === activeId);
|
|
@@ -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: 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: PsDragListLiftFrames, children: activeItem !== null
|
|
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: PsDragListLiftFrames, children: activeItem !== null
|
|
67
67
|
? renderItem({
|
|
68
68
|
handle: (_jsx(PsSortableListHandle, { className: handleClassName, icon: handleIcon, label: getHandleLabel(activeItem.label) })),
|
|
69
69
|
index: activeIndex,
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { PsRatingDisplaySize } from './ps-rating-display-size';
|
|
2
|
+
export const PsRatingDisplayConfig = {
|
|
3
|
+
defaultMax: 5,
|
|
4
|
+
filledClassName: 'fill-current text-primary',
|
|
5
|
+
emptyClassName: 'text-ink/30 dark:text-white/30',
|
|
6
|
+
iconClassNames: {
|
|
7
|
+
[PsRatingDisplaySize.Large]: 'h-8 w-8',
|
|
8
|
+
[PsRatingDisplaySize.Medium]: 'h-6 w-6',
|
|
9
|
+
[PsRatingDisplaySize.Small]: 'h-4 w-4',
|
|
10
|
+
},
|
|
11
|
+
};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
|
+
import { usePsChangeQueue } from './use-ps-change-queue';
|
|
3
|
+
import { usePsOptimisticRows } from './use-ps-optimistic-rows';
|
|
4
|
+
export const usePsOptimisticFetcher = ({ apply, fetcher, isHolding = false, isSuccess, merge, revalidator, rows, }) => {
|
|
5
|
+
const [isUnsettled, setIsUnsettled] = useState(false);
|
|
6
|
+
const submitted = useRef(0);
|
|
7
|
+
const settle = useRef(null);
|
|
8
|
+
const sawBusy = useRef(false);
|
|
9
|
+
const dataBefore = useRef(fetcher.data);
|
|
10
|
+
const dataSeen = useRef(fetcher.data);
|
|
11
|
+
const { forgetLast, remember, rows: shown, } = usePsOptimisticRows({
|
|
12
|
+
apply,
|
|
13
|
+
isHolding,
|
|
14
|
+
isSaving: isUnsettled || fetcher.state !== 'idle' || revalidator.state !== 'idle',
|
|
15
|
+
rows,
|
|
16
|
+
});
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
dataSeen.current = fetcher.data;
|
|
19
|
+
if (settle.current === null)
|
|
20
|
+
return;
|
|
21
|
+
if (fetcher.state !== 'idle') {
|
|
22
|
+
sawBusy.current = true;
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
if (!sawBusy.current && fetcher.data === dataBefore.current)
|
|
26
|
+
return;
|
|
27
|
+
const done = settle.current;
|
|
28
|
+
settle.current = null;
|
|
29
|
+
sawBusy.current = false;
|
|
30
|
+
done(fetcher.data);
|
|
31
|
+
}, [fetcher.data, fetcher.state]);
|
|
32
|
+
const submitOne = useCallback((values) => new Promise((resolve) => {
|
|
33
|
+
settle.current = resolve;
|
|
34
|
+
sawBusy.current = false;
|
|
35
|
+
dataBefore.current = dataSeen.current;
|
|
36
|
+
void fetcher.submit(values, { method: 'post' });
|
|
37
|
+
}), [fetcher]);
|
|
38
|
+
const send = useCallback(async (queued) => {
|
|
39
|
+
for (const submission of merge === undefined ? queued : merge(queued)) {
|
|
40
|
+
const result = await submitOne(submission);
|
|
41
|
+
if (!isSuccess(result))
|
|
42
|
+
throw result;
|
|
43
|
+
}
|
|
44
|
+
}, [isSuccess, merge, submitOne]);
|
|
45
|
+
const revalidate = useCallback(() => {
|
|
46
|
+
const through = submitted.current;
|
|
47
|
+
void Promise.resolve(revalidator.revalidate()).finally(() => {
|
|
48
|
+
if (submitted.current === through)
|
|
49
|
+
setIsUnsettled(false);
|
|
50
|
+
});
|
|
51
|
+
}, [revalidator]);
|
|
52
|
+
const forgetFailed = useCallback((failed, dropped) => {
|
|
53
|
+
for (let index = 0; index < failed.length + dropped.length; index += 1)
|
|
54
|
+
forgetLast();
|
|
55
|
+
}, [forgetLast]);
|
|
56
|
+
const queue = usePsChangeQueue({
|
|
57
|
+
onDrained: revalidate,
|
|
58
|
+
onFailed: forgetFailed,
|
|
59
|
+
send,
|
|
60
|
+
});
|
|
61
|
+
const submit = useCallback((values) => {
|
|
62
|
+
submitted.current += 1;
|
|
63
|
+
setIsUnsettled(true);
|
|
64
|
+
remember(values);
|
|
65
|
+
queue.enqueue(values);
|
|
66
|
+
}, [queue, remember]);
|
|
67
|
+
return { rows: shown, submit };
|
|
68
|
+
};
|
package/dist/esm/index.js
CHANGED
|
@@ -75,6 +75,12 @@ export * from './hooks/use-ps-change-queue';
|
|
|
75
75
|
export * from './interfaces/ps-change-queue-input';
|
|
76
76
|
export * from './interfaces/ps-change-queue-result';
|
|
77
77
|
export * from './hooks/use-ps-optimistic-rows';
|
|
78
|
+
export * from './hooks/use-ps-optimistic-fetcher';
|
|
79
|
+
export * from './interfaces/ps-fetcher-like';
|
|
80
|
+
export * from './interfaces/ps-fetcher-submit-options';
|
|
81
|
+
export * from './interfaces/ps-optimistic-fetcher-input';
|
|
82
|
+
export * from './interfaces/ps-optimistic-fetcher-result';
|
|
83
|
+
export * from './interfaces/ps-revalidator-like';
|
|
78
84
|
export * from './interfaces/ps-optimistic-rows-input';
|
|
79
85
|
export * from './interfaces/ps-optimistic-rows-result';
|
|
80
86
|
export * from './hooks/use-ps-navigation-progress';
|
|
@@ -129,6 +135,7 @@ export * from './models/ps-theme-mode-state';
|
|
|
129
135
|
export * from './models/ps-tool-card-data';
|
|
130
136
|
export * from './components/ps-capped-list';
|
|
131
137
|
export * from './components/ps-detail-list';
|
|
138
|
+
export * from './components/ps-overview-card';
|
|
132
139
|
export * from './components/ps-form-footer';
|
|
133
140
|
export * from './components/ps-start-highlight';
|
|
134
141
|
export * from './components/ps-start-panel';
|
|
@@ -147,3 +154,5 @@ export * from './hooks/use-ps-drag-sensors';
|
|
|
147
154
|
export * from './hooks/use-ps-reduced-motion';
|
|
148
155
|
export * from './components/ps-divider';
|
|
149
156
|
export * from './models/ps-divider-orientation';
|
|
157
|
+
export * from './components/ps-rating-display';
|
|
158
|
+
export * from './constants/ps-rating-display-size';
|
|
@@ -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,3 @@
|
|
|
1
|
+
import type { PsOptimisticFetcherInput } from '../interfaces/ps-optimistic-fetcher-input';
|
|
2
|
+
import type { PsOptimisticFetcherResult } from '../interfaces/ps-optimistic-fetcher-result';
|
|
3
|
+
export declare const usePsOptimisticFetcher: <Row, Data>({ apply, fetcher, isHolding, isSuccess, merge, revalidator, rows, }: PsOptimisticFetcherInput<Row, Data>) => PsOptimisticFetcherResult<Row>;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.usePsOptimisticFetcher = void 0;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const use_ps_change_queue_1 = require("./use-ps-change-queue");
|
|
6
|
+
const use_ps_optimistic_rows_1 = require("./use-ps-optimistic-rows");
|
|
7
|
+
const usePsOptimisticFetcher = ({ apply, fetcher, isHolding = false, isSuccess, merge, revalidator, rows, }) => {
|
|
8
|
+
const [isUnsettled, setIsUnsettled] = (0, react_1.useState)(false);
|
|
9
|
+
const submitted = (0, react_1.useRef)(0);
|
|
10
|
+
const settle = (0, react_1.useRef)(null);
|
|
11
|
+
const sawBusy = (0, react_1.useRef)(false);
|
|
12
|
+
const dataBefore = (0, react_1.useRef)(fetcher.data);
|
|
13
|
+
const dataSeen = (0, react_1.useRef)(fetcher.data);
|
|
14
|
+
const { forgetLast, remember, rows: shown, } = (0, use_ps_optimistic_rows_1.usePsOptimisticRows)({
|
|
15
|
+
apply,
|
|
16
|
+
isHolding,
|
|
17
|
+
isSaving: isUnsettled || fetcher.state !== 'idle' || revalidator.state !== 'idle',
|
|
18
|
+
rows,
|
|
19
|
+
});
|
|
20
|
+
(0, react_1.useEffect)(() => {
|
|
21
|
+
dataSeen.current = fetcher.data;
|
|
22
|
+
if (settle.current === null)
|
|
23
|
+
return;
|
|
24
|
+
if (fetcher.state !== 'idle') {
|
|
25
|
+
sawBusy.current = true;
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (!sawBusy.current && fetcher.data === dataBefore.current)
|
|
29
|
+
return;
|
|
30
|
+
const done = settle.current;
|
|
31
|
+
settle.current = null;
|
|
32
|
+
sawBusy.current = false;
|
|
33
|
+
done(fetcher.data);
|
|
34
|
+
}, [fetcher.data, fetcher.state]);
|
|
35
|
+
const submitOne = (0, react_1.useCallback)((values) => new Promise((resolve) => {
|
|
36
|
+
settle.current = resolve;
|
|
37
|
+
sawBusy.current = false;
|
|
38
|
+
dataBefore.current = dataSeen.current;
|
|
39
|
+
void fetcher.submit(values, { method: 'post' });
|
|
40
|
+
}), [fetcher]);
|
|
41
|
+
const send = (0, react_1.useCallback)(async (queued) => {
|
|
42
|
+
for (const submission of merge === undefined ? queued : merge(queued)) {
|
|
43
|
+
const result = await submitOne(submission);
|
|
44
|
+
if (!isSuccess(result))
|
|
45
|
+
throw result;
|
|
46
|
+
}
|
|
47
|
+
}, [isSuccess, merge, submitOne]);
|
|
48
|
+
const revalidate = (0, react_1.useCallback)(() => {
|
|
49
|
+
const through = submitted.current;
|
|
50
|
+
void Promise.resolve(revalidator.revalidate()).finally(() => {
|
|
51
|
+
if (submitted.current === through)
|
|
52
|
+
setIsUnsettled(false);
|
|
53
|
+
});
|
|
54
|
+
}, [revalidator]);
|
|
55
|
+
const forgetFailed = (0, react_1.useCallback)((failed, dropped) => {
|
|
56
|
+
for (let index = 0; index < failed.length + dropped.length; index += 1)
|
|
57
|
+
forgetLast();
|
|
58
|
+
}, [forgetLast]);
|
|
59
|
+
const queue = (0, use_ps_change_queue_1.usePsChangeQueue)({
|
|
60
|
+
onDrained: revalidate,
|
|
61
|
+
onFailed: forgetFailed,
|
|
62
|
+
send,
|
|
63
|
+
});
|
|
64
|
+
const submit = (0, react_1.useCallback)((values) => {
|
|
65
|
+
submitted.current += 1;
|
|
66
|
+
setIsUnsettled(true);
|
|
67
|
+
remember(values);
|
|
68
|
+
queue.enqueue(values);
|
|
69
|
+
}, [queue, remember]);
|
|
70
|
+
return { rows: shown, submit };
|
|
71
|
+
};
|
|
72
|
+
exports.usePsOptimisticFetcher = usePsOptimisticFetcher;
|
package/dist/index.d.ts
CHANGED
|
@@ -75,6 +75,12 @@ export * from './hooks/use-ps-change-queue';
|
|
|
75
75
|
export * from './interfaces/ps-change-queue-input';
|
|
76
76
|
export * from './interfaces/ps-change-queue-result';
|
|
77
77
|
export * from './hooks/use-ps-optimistic-rows';
|
|
78
|
+
export * from './hooks/use-ps-optimistic-fetcher';
|
|
79
|
+
export * from './interfaces/ps-fetcher-like';
|
|
80
|
+
export * from './interfaces/ps-fetcher-submit-options';
|
|
81
|
+
export * from './interfaces/ps-optimistic-fetcher-input';
|
|
82
|
+
export * from './interfaces/ps-optimistic-fetcher-result';
|
|
83
|
+
export * from './interfaces/ps-revalidator-like';
|
|
78
84
|
export * from './interfaces/ps-optimistic-rows-input';
|
|
79
85
|
export * from './interfaces/ps-optimistic-rows-result';
|
|
80
86
|
export * from './hooks/use-ps-navigation-progress';
|
|
@@ -129,6 +135,7 @@ export * from './models/ps-theme-mode-state';
|
|
|
129
135
|
export * from './models/ps-tool-card-data';
|
|
130
136
|
export * from './components/ps-capped-list';
|
|
131
137
|
export * from './components/ps-detail-list';
|
|
138
|
+
export * from './components/ps-overview-card';
|
|
132
139
|
export * from './components/ps-form-footer';
|
|
133
140
|
export * from './components/ps-start-highlight';
|
|
134
141
|
export * from './components/ps-start-panel';
|
|
@@ -147,3 +154,5 @@ export * from './hooks/use-ps-drag-sensors';
|
|
|
147
154
|
export * from './hooks/use-ps-reduced-motion';
|
|
148
155
|
export * from './components/ps-divider';
|
|
149
156
|
export * from './models/ps-divider-orientation';
|
|
157
|
+
export * from './components/ps-rating-display';
|
|
158
|
+
export * from './constants/ps-rating-display-size';
|
package/dist/index.js
CHANGED
|
@@ -91,6 +91,12 @@ __exportStar(require("./hooks/use-ps-change-queue"), exports);
|
|
|
91
91
|
__exportStar(require("./interfaces/ps-change-queue-input"), exports);
|
|
92
92
|
__exportStar(require("./interfaces/ps-change-queue-result"), exports);
|
|
93
93
|
__exportStar(require("./hooks/use-ps-optimistic-rows"), exports);
|
|
94
|
+
__exportStar(require("./hooks/use-ps-optimistic-fetcher"), exports);
|
|
95
|
+
__exportStar(require("./interfaces/ps-fetcher-like"), exports);
|
|
96
|
+
__exportStar(require("./interfaces/ps-fetcher-submit-options"), exports);
|
|
97
|
+
__exportStar(require("./interfaces/ps-optimistic-fetcher-input"), exports);
|
|
98
|
+
__exportStar(require("./interfaces/ps-optimistic-fetcher-result"), exports);
|
|
99
|
+
__exportStar(require("./interfaces/ps-revalidator-like"), exports);
|
|
94
100
|
__exportStar(require("./interfaces/ps-optimistic-rows-input"), exports);
|
|
95
101
|
__exportStar(require("./interfaces/ps-optimistic-rows-result"), exports);
|
|
96
102
|
__exportStar(require("./hooks/use-ps-navigation-progress"), exports);
|
|
@@ -145,6 +151,7 @@ __exportStar(require("./models/ps-theme-mode-state"), exports);
|
|
|
145
151
|
__exportStar(require("./models/ps-tool-card-data"), exports);
|
|
146
152
|
__exportStar(require("./components/ps-capped-list"), exports);
|
|
147
153
|
__exportStar(require("./components/ps-detail-list"), exports);
|
|
154
|
+
__exportStar(require("./components/ps-overview-card"), exports);
|
|
148
155
|
__exportStar(require("./components/ps-form-footer"), exports);
|
|
149
156
|
__exportStar(require("./components/ps-start-highlight"), exports);
|
|
150
157
|
__exportStar(require("./components/ps-start-panel"), exports);
|
|
@@ -163,3 +170,5 @@ __exportStar(require("./hooks/use-ps-drag-sensors"), exports);
|
|
|
163
170
|
__exportStar(require("./hooks/use-ps-reduced-motion"), exports);
|
|
164
171
|
__exportStar(require("./components/ps-divider"), exports);
|
|
165
172
|
__exportStar(require("./models/ps-divider-orientation"), exports);
|
|
173
|
+
__exportStar(require("./components/ps-rating-display"), exports);
|
|
174
|
+
__exportStar(require("./constants/ps-rating-display-size"), exports);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { PsFetcherLike } from './ps-fetcher-like';
|
|
2
|
+
import type { PsRevalidatorLike } from './ps-revalidator-like';
|
|
3
|
+
export interface PsOptimisticFetcherInput<Row, Data> {
|
|
4
|
+
apply: (rows: Row[], changes: Record<string, string>[]) => Row[];
|
|
5
|
+
fetcher: PsFetcherLike<Data>;
|
|
6
|
+
isHolding?: boolean;
|
|
7
|
+
isSuccess: (data: Data | undefined) => boolean;
|
|
8
|
+
merge?: (changes: Record<string, string>[]) => Record<string, string>[];
|
|
9
|
+
revalidator: PsRevalidatorLike;
|
|
10
|
+
rows: Row[];
|
|
11
|
+
}
|
|
@@ -27,6 +27,7 @@ export interface PsSortableListProps<TItem extends PsSortableListItem> {
|
|
|
27
27
|
handleIcon?: JSX.Element;
|
|
28
28
|
instructions: string;
|
|
29
29
|
items: TItem[];
|
|
30
|
+
isHorizontal?: boolean;
|
|
30
31
|
onMove: (itemId: string, fromIndex: number, toIndex: number) => void;
|
|
31
32
|
renderItem: (options: PsSortableListRenderOptions<TItem>) => JSX.Element | null;
|
|
32
33
|
}
|