@pallasoft/ps-core-components 2.26.0 → 2.28.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.
Files changed (37) hide show
  1. package/dist/components/ps-divider.d.ts +7 -0
  2. package/dist/components/ps-divider.js +12 -0
  3. package/dist/components/ps-overview-card.d.ts +12 -0
  4. package/dist/components/ps-overview-card.js +7 -0
  5. package/dist/components/ps-store-badge.js +3 -8
  6. package/dist/constants/ps-store-badge-config.d.ts +13 -17
  7. package/dist/constants/ps-store-badge-config.js +15 -31
  8. package/dist/esm/components/ps-divider.js +8 -0
  9. package/dist/esm/components/ps-overview-card.js +3 -0
  10. package/dist/esm/components/ps-store-badge.js +3 -8
  11. package/dist/esm/constants/ps-store-badge-config.js +15 -31
  12. package/dist/esm/hooks/use-ps-optimistic-fetcher.js +68 -0
  13. package/dist/esm/index.js +9 -0
  14. package/dist/esm/interfaces/ps-fetcher-like.js +1 -0
  15. package/dist/esm/interfaces/ps-fetcher-submit-options.js +1 -0
  16. package/dist/esm/interfaces/ps-optimistic-fetcher-input.js +1 -0
  17. package/dist/esm/interfaces/ps-optimistic-fetcher-result.js +1 -0
  18. package/dist/esm/interfaces/ps-revalidator-like.js +1 -0
  19. package/dist/esm/models/ps-divider-orientation.js +1 -0
  20. package/dist/hooks/use-ps-optimistic-fetcher.d.ts +3 -0
  21. package/dist/hooks/use-ps-optimistic-fetcher.js +72 -0
  22. package/dist/index.d.ts +9 -0
  23. package/dist/index.js +9 -0
  24. package/dist/interfaces/ps-fetcher-like.d.ts +6 -0
  25. package/dist/interfaces/ps-fetcher-like.js +2 -0
  26. package/dist/interfaces/ps-fetcher-submit-options.d.ts +3 -0
  27. package/dist/interfaces/ps-fetcher-submit-options.js +2 -0
  28. package/dist/interfaces/ps-optimistic-fetcher-input.d.ts +11 -0
  29. package/dist/interfaces/ps-optimistic-fetcher-input.js +2 -0
  30. package/dist/interfaces/ps-optimistic-fetcher-result.d.ts +4 -0
  31. package/dist/interfaces/ps-optimistic-fetcher-result.js +2 -0
  32. package/dist/interfaces/ps-revalidator-like.d.ts +4 -0
  33. package/dist/interfaces/ps-revalidator-like.js +2 -0
  34. package/dist/models/ps-divider-orientation.d.ts +1 -0
  35. package/dist/models/ps-divider-orientation.js +2 -0
  36. package/dist/models/ps-store-badge-logo-path.d.ts +0 -1
  37. package/package.json +1 -1
@@ -0,0 +1,7 @@
1
+ import type { PsDividerOrientation } from '../models/ps-divider-orientation';
2
+ export interface PsDividerProps {
3
+ className?: string;
4
+ label?: string;
5
+ orientation?: PsDividerOrientation;
6
+ }
7
+ export declare const PsDivider: ({ className, label, orientation, }: PsDividerProps) => import("react").JSX.Element;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PsDivider = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const PsDivider = ({ className = '', label, orientation = 'horizontal', }) => {
6
+ if (orientation === 'vertical')
7
+ return ((0, jsx_runtime_1.jsx)("div", { "aria-orientation": 'vertical', className: `w-px shrink-0 self-stretch bg-line ${className}`, role: 'separator' }));
8
+ if (!label)
9
+ return ((0, jsx_runtime_1.jsx)("div", { "aria-orientation": 'horizontal', className: `h-px w-full shrink-0 bg-line ${className}`, role: 'separator' }));
10
+ return ((0, jsx_runtime_1.jsxs)("div", { "aria-label": label, "aria-orientation": 'horizontal', className: `flex w-full items-center gap-3 ${className}`, role: 'separator', children: [(0, jsx_runtime_1.jsx)("span", { "aria-hidden": 'true', className: 'h-px flex-1 bg-line' }), (0, jsx_runtime_1.jsx)("span", { "aria-hidden": 'true', className: 'text-xs text-ink/55', children: label }), (0, jsx_runtime_1.jsx)("span", { "aria-hidden": 'true', className: 'h-px flex-1 bg-line' })] }));
11
+ };
12
+ exports.PsDivider = PsDivider;
@@ -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;
@@ -9,15 +9,10 @@ const PsStoreBadge = ({ className, href, labels, onPress, platform, size = 'defa
9
9
  const shownLabels = labels === undefined ? platformData.labels : labels;
10
10
  const sizeClasses = ps_store_badge_config_1.PsStoreBadgeClasses.sizes[size];
11
11
  const badgeClassName = ps_design_system_1.PallasoftClassNameService.merge(ps_store_badge_config_1.PsStoreBadgeClasses.base, sizeClasses.badge, className);
12
- const badgeStyle = {
13
- backgroundColor: ps_store_badge_config_1.PsStoreBadgeConfig.colors.background,
14
- borderColor: ps_store_badge_config_1.PsStoreBadgeConfig.colors.border,
15
- color: ps_store_badge_config_1.PsStoreBadgeConfig.colors.text,
16
- };
17
12
  const ariaLabel = `${shownLabels.caption} ${shownLabels.name}`;
18
- const content = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("svg", { "aria-hidden": 'true', className: ps_design_system_1.PallasoftClassNameService.merge('shrink-0', sizeClasses.logo), viewBox: ps_store_badge_config_1.PsStoreBadgeConfig.logoViewBox, xmlns: 'http://www.w3.org/2000/svg', children: platformData.logoPaths.map((path) => ((0, jsx_runtime_1.jsx)("path", { d: path.d, fill: path.fill }, path.d))) }), (0, jsx_runtime_1.jsxs)("span", { "aria-hidden": 'true', className: 'flex min-w-0 flex-col items-start gap-0.5', children: [(0, jsx_runtime_1.jsx)("span", { className: ps_design_system_1.PallasoftClassNameService.merge('whitespace-nowrap', sizeClasses.caption), children: shownLabels.caption }), (0, jsx_runtime_1.jsx)("span", { className: ps_design_system_1.PallasoftClassNameService.merge('whitespace-nowrap', sizeClasses.name), children: shownLabels.name })] })] }));
13
+ const content = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("span", { "aria-hidden": 'true', className: ps_design_system_1.PallasoftClassNameService.merge(ps_store_badge_config_1.PsStoreBadgeClasses.tile, sizeClasses.tile), children: (0, jsx_runtime_1.jsx)("svg", { className: sizeClasses.logo, fill: 'currentColor', viewBox: ps_store_badge_config_1.PsStoreBadgeConfig.logoViewBox, xmlns: 'http://www.w3.org/2000/svg', children: platformData.logoPaths.map((path) => ((0, jsx_runtime_1.jsx)("path", { d: path.d }, path.d))) }) }), (0, jsx_runtime_1.jsxs)("span", { "aria-hidden": 'true', className: 'flex min-w-0 flex-col items-start', children: [(0, jsx_runtime_1.jsx)("span", { className: ps_design_system_1.PallasoftClassNameService.merge('truncate max-w-full', sizeClasses.caption), children: shownLabels.caption }), (0, jsx_runtime_1.jsx)("span", { className: ps_design_system_1.PallasoftClassNameService.merge('truncate max-w-full', sizeClasses.name), children: shownLabels.name })] })] }));
19
14
  if (href === undefined)
20
- return ((0, jsx_runtime_1.jsx)("button", { "aria-label": ariaLabel, className: badgeClassName, "data-platform": platform, onClick: onPress, style: badgeStyle, type: 'button', children: content }));
21
- return ((0, jsx_runtime_1.jsx)("a", { "aria-label": ariaLabel, className: badgeClassName, "data-platform": platform, href: href, rel: 'noopener noreferrer', style: badgeStyle, target: '_blank', children: content }));
15
+ return ((0, jsx_runtime_1.jsx)("button", { "aria-label": ariaLabel, className: badgeClassName, "data-platform": platform, onClick: onPress, type: 'button', children: content }));
16
+ return ((0, jsx_runtime_1.jsx)("a", { "aria-label": ariaLabel, className: badgeClassName, "data-platform": platform, href: href, rel: 'noopener noreferrer', target: '_blank', children: content }));
22
17
  };
23
18
  exports.PsStoreBadge = PsStoreBadge;
@@ -1,9 +1,4 @@
1
1
  export declare const PsStoreBadgeConfig: {
2
- readonly colors: {
3
- readonly background: "#000000";
4
- readonly border: "#A6A6A6";
5
- readonly text: "#FFFFFF";
6
- };
7
2
  readonly logoViewBox: "0 0 24 24";
8
3
  readonly platforms: {
9
4
  "app-store": {
@@ -13,7 +8,6 @@ export declare const PsStoreBadgeConfig: {
13
8
  };
14
9
  logoPaths: {
15
10
  d: string;
16
- fill: string;
17
11
  }[];
18
12
  };
19
13
  "google-play": {
@@ -23,28 +17,30 @@ export declare const PsStoreBadgeConfig: {
23
17
  };
24
18
  logoPaths: {
25
19
  d: string;
26
- fill: string;
27
20
  }[];
28
21
  };
29
22
  };
30
23
  };
31
24
  export declare const PsStoreBadgeClasses: {
32
- readonly base: "ps-focus-ring inline-flex shrink-0 items-center rounded-lg border font-sans leading-none transition-opacity hover:opacity-85 motion-reduce:transition-none";
33
- readonly group: "flex flex-wrap items-center";
25
+ readonly base: "ps-focus-ring ps-liquid ps-liquid-control ps-pressable group/store inline-flex w-full min-w-0 items-center bg-white/72 font-sans text-left text-ink hover:border-primary/30 dark:border-white/16 dark:bg-white/12 motion-reduce:transition-none motion-reduce:hover:transform-none";
26
+ readonly group: "grid w-full grid-cols-1 sm:grid-cols-2";
34
27
  readonly sizes: {
35
28
  readonly default: {
36
- readonly badge: "h-11 min-w-[8.25rem] gap-2 px-3";
37
- readonly caption: "text-[0.625rem]";
29
+ readonly badge: "min-h-12 gap-3 px-2.5 py-1.5";
30
+ readonly caption: "text-xs leading-4";
38
31
  readonly gap: "gap-3";
39
- readonly logo: "size-6";
40
- readonly name: "text-lg font-semibold tracking-tight";
32
+ readonly logo: "size-5";
33
+ readonly name: "text-sm font-semibold leading-5";
34
+ readonly tile: "size-9";
41
35
  };
42
36
  readonly large: {
43
- readonly badge: "h-14 min-w-[10.5rem] gap-2.5 px-4";
44
- readonly caption: "text-xs";
37
+ readonly badge: "min-h-14 gap-3.5 px-3 py-2";
38
+ readonly caption: "text-xs leading-4";
45
39
  readonly gap: "gap-4";
46
- readonly logo: "size-8";
47
- readonly name: "text-2xl font-semibold tracking-tight";
40
+ readonly logo: "size-6";
41
+ readonly name: "text-base font-semibold leading-6";
42
+ readonly tile: "size-10";
48
43
  };
49
44
  };
45
+ readonly tile: "ps-icon-surface transition-colors group-hover/store:bg-primary/15 motion-reduce:transition-none";
50
46
  };
@@ -3,11 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PsStoreBadgeClasses = exports.PsStoreBadgeConfig = void 0;
4
4
  const ps_store_platform_1 = require("./ps-store-platform");
5
5
  exports.PsStoreBadgeConfig = {
6
- colors: {
7
- background: '#000000',
8
- border: '#A6A6A6',
9
- text: '#FFFFFF',
10
- },
11
6
  logoViewBox: '0 0 24 24',
12
7
  platforms: {
13
8
  [ps_store_platform_1.PsStorePlatform.appStore]: {
@@ -15,50 +10,39 @@ exports.PsStoreBadgeConfig = {
15
10
  logoPaths: [
16
11
  {
17
12
  d: 'M12.152 6.896c-.948 0-2.415-1.078-3.96-1.04-2.04.027-3.91 1.183-4.961 3.014-2.117 3.675-.546 9.103 1.519 12.09 1.013 1.454 2.208 3.09 3.792 3.039 1.52-.065 2.09-.987 3.935-.987 1.831 0 2.35.987 3.96.948 1.637-.026 2.676-1.48 3.676-2.948 1.156-1.688 1.636-3.325 1.662-3.415-.039-.013-3.182-1.221-3.22-4.857-.026-3.04 2.48-4.494 2.597-4.559-1.429-2.09-3.623-2.324-4.39-2.376-2-.156-3.675 1.09-4.61 1.09zM15.53 3.83c.843-1.012 1.4-2.427 1.245-3.83-1.207.052-2.662.805-3.532 1.818-.78.896-1.454 2.338-1.273 3.714 1.338.104 2.715-.688 3.559-1.701',
18
- fill: '#FFFFFF',
19
13
  },
20
14
  ],
21
15
  },
22
16
  [ps_store_platform_1.PsStorePlatform.googlePlay]: {
23
- labels: { caption: 'GET IT ON', name: 'Google Play' },
17
+ labels: { caption: 'Get it on', name: 'Google Play' },
24
18
  logoPaths: [
25
19
  {
26
- d: 'M1.337.924a1.486 1.486 0 0 0-.112.568v21.017c0 .217.045.419.124.6l11.155-11.087L1.337.924z',
27
- fill: '#4285F4',
28
- },
29
- {
30
- d: 'M13.544 10.989l3.258-3.238L3.45.195a1.466 1.466 0 0 0-.946-.179l11.04 10.973z',
31
- fill: '#34A853',
32
- },
33
- {
34
- d: 'M22.018 13.298l-3.919 2.218-3.515-3.493 3.543-3.521 3.891 2.202a1.49 1.49 0 0 1 0 2.594z',
35
- fill: '#FBBC04',
36
- },
37
- {
38
- d: 'M13.544 13.056l-11 10.933c.298.036.612-.016.906-.183l13.324-7.54-3.23-3.21z',
39
- fill: '#EA4335',
20
+ d: 'M6.2 2.9c-.5-.3-1.2.1-1.2.7v16.8c0 .6.7 1 1.2.7l14-8.4c.5-.3.5-1.1 0-1.4L6.2 2.9z',
40
21
  },
41
22
  ],
42
23
  },
43
24
  },
44
25
  };
45
26
  exports.PsStoreBadgeClasses = {
46
- base: 'ps-focus-ring inline-flex shrink-0 items-center rounded-lg border font-sans leading-none transition-opacity hover:opacity-85 motion-reduce:transition-none',
47
- group: 'flex flex-wrap items-center',
27
+ base: 'ps-focus-ring ps-liquid ps-liquid-control ps-pressable group/store inline-flex w-full min-w-0 items-center bg-white/72 font-sans text-left text-ink hover:border-primary/30 dark:border-white/16 dark:bg-white/12 motion-reduce:transition-none motion-reduce:hover:transform-none',
28
+ group: 'grid w-full grid-cols-1 sm:grid-cols-2',
48
29
  sizes: {
49
30
  default: {
50
- badge: 'h-11 min-w-[8.25rem] gap-2 px-3',
51
- caption: 'text-[0.625rem]',
31
+ badge: 'min-h-12 gap-3 px-2.5 py-1.5',
32
+ caption: 'text-xs leading-4',
52
33
  gap: 'gap-3',
53
- logo: 'size-6',
54
- name: 'text-lg font-semibold tracking-tight',
34
+ logo: 'size-5',
35
+ name: 'text-sm font-semibold leading-5',
36
+ tile: 'size-9',
55
37
  },
56
38
  large: {
57
- badge: 'h-14 min-w-[10.5rem] gap-2.5 px-4',
58
- caption: 'text-xs',
39
+ badge: 'min-h-14 gap-3.5 px-3 py-2',
40
+ caption: 'text-xs leading-4',
59
41
  gap: 'gap-4',
60
- logo: 'size-8',
61
- name: 'text-2xl font-semibold tracking-tight',
42
+ logo: 'size-6',
43
+ name: 'text-base font-semibold leading-6',
44
+ tile: 'size-10',
62
45
  },
63
46
  },
47
+ tile: 'ps-icon-surface transition-colors group-hover/store:bg-primary/15 motion-reduce:transition-none',
64
48
  };
@@ -0,0 +1,8 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ export const PsDivider = ({ className = '', label, orientation = 'horizontal', }) => {
3
+ if (orientation === 'vertical')
4
+ return (_jsx("div", { "aria-orientation": 'vertical', className: `w-px shrink-0 self-stretch bg-line ${className}`, role: 'separator' }));
5
+ if (!label)
6
+ return (_jsx("div", { "aria-orientation": 'horizontal', className: `h-px w-full shrink-0 bg-line ${className}`, role: 'separator' }));
7
+ return (_jsxs("div", { "aria-label": label, "aria-orientation": 'horizontal', className: `flex w-full items-center gap-3 ${className}`, role: 'separator', children: [_jsx("span", { "aria-hidden": 'true', className: 'h-px flex-1 bg-line' }), _jsx("span", { "aria-hidden": 'true', className: 'text-xs text-ink/55', children: label }), _jsx("span", { "aria-hidden": 'true', className: 'h-px flex-1 bg-line' })] }));
8
+ };
@@ -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] }));
@@ -6,14 +6,9 @@ export const PsStoreBadge = ({ className, href, labels, onPress, platform, size
6
6
  const shownLabels = labels === undefined ? platformData.labels : labels;
7
7
  const sizeClasses = PsStoreBadgeClasses.sizes[size];
8
8
  const badgeClassName = PallasoftClassNameService.merge(PsStoreBadgeClasses.base, sizeClasses.badge, className);
9
- const badgeStyle = {
10
- backgroundColor: PsStoreBadgeConfig.colors.background,
11
- borderColor: PsStoreBadgeConfig.colors.border,
12
- color: PsStoreBadgeConfig.colors.text,
13
- };
14
9
  const ariaLabel = `${shownLabels.caption} ${shownLabels.name}`;
15
- const content = (_jsxs(_Fragment, { children: [_jsx("svg", { "aria-hidden": 'true', className: PallasoftClassNameService.merge('shrink-0', sizeClasses.logo), viewBox: PsStoreBadgeConfig.logoViewBox, xmlns: 'http://www.w3.org/2000/svg', children: platformData.logoPaths.map((path) => (_jsx("path", { d: path.d, fill: path.fill }, path.d))) }), _jsxs("span", { "aria-hidden": 'true', className: 'flex min-w-0 flex-col items-start gap-0.5', children: [_jsx("span", { className: PallasoftClassNameService.merge('whitespace-nowrap', sizeClasses.caption), children: shownLabels.caption }), _jsx("span", { className: PallasoftClassNameService.merge('whitespace-nowrap', sizeClasses.name), children: shownLabels.name })] })] }));
10
+ const content = (_jsxs(_Fragment, { children: [_jsx("span", { "aria-hidden": 'true', className: PallasoftClassNameService.merge(PsStoreBadgeClasses.tile, sizeClasses.tile), children: _jsx("svg", { className: sizeClasses.logo, fill: 'currentColor', viewBox: PsStoreBadgeConfig.logoViewBox, xmlns: 'http://www.w3.org/2000/svg', children: platformData.logoPaths.map((path) => (_jsx("path", { d: path.d }, path.d))) }) }), _jsxs("span", { "aria-hidden": 'true', className: 'flex min-w-0 flex-col items-start', children: [_jsx("span", { className: PallasoftClassNameService.merge('truncate max-w-full', sizeClasses.caption), children: shownLabels.caption }), _jsx("span", { className: PallasoftClassNameService.merge('truncate max-w-full', sizeClasses.name), children: shownLabels.name })] })] }));
16
11
  if (href === undefined)
17
- return (_jsx("button", { "aria-label": ariaLabel, className: badgeClassName, "data-platform": platform, onClick: onPress, style: badgeStyle, type: 'button', children: content }));
18
- return (_jsx("a", { "aria-label": ariaLabel, className: badgeClassName, "data-platform": platform, href: href, rel: 'noopener noreferrer', style: badgeStyle, target: '_blank', children: content }));
12
+ return (_jsx("button", { "aria-label": ariaLabel, className: badgeClassName, "data-platform": platform, onClick: onPress, type: 'button', children: content }));
13
+ return (_jsx("a", { "aria-label": ariaLabel, className: badgeClassName, "data-platform": platform, href: href, rel: 'noopener noreferrer', target: '_blank', children: content }));
19
14
  };
@@ -1,10 +1,5 @@
1
1
  import { PsStorePlatform } from './ps-store-platform';
2
2
  export const PsStoreBadgeConfig = {
3
- colors: {
4
- background: '#000000',
5
- border: '#A6A6A6',
6
- text: '#FFFFFF',
7
- },
8
3
  logoViewBox: '0 0 24 24',
9
4
  platforms: {
10
5
  [PsStorePlatform.appStore]: {
@@ -12,50 +7,39 @@ export const PsStoreBadgeConfig = {
12
7
  logoPaths: [
13
8
  {
14
9
  d: 'M12.152 6.896c-.948 0-2.415-1.078-3.96-1.04-2.04.027-3.91 1.183-4.961 3.014-2.117 3.675-.546 9.103 1.519 12.09 1.013 1.454 2.208 3.09 3.792 3.039 1.52-.065 2.09-.987 3.935-.987 1.831 0 2.35.987 3.96.948 1.637-.026 2.676-1.48 3.676-2.948 1.156-1.688 1.636-3.325 1.662-3.415-.039-.013-3.182-1.221-3.22-4.857-.026-3.04 2.48-4.494 2.597-4.559-1.429-2.09-3.623-2.324-4.39-2.376-2-.156-3.675 1.09-4.61 1.09zM15.53 3.83c.843-1.012 1.4-2.427 1.245-3.83-1.207.052-2.662.805-3.532 1.818-.78.896-1.454 2.338-1.273 3.714 1.338.104 2.715-.688 3.559-1.701',
15
- fill: '#FFFFFF',
16
10
  },
17
11
  ],
18
12
  },
19
13
  [PsStorePlatform.googlePlay]: {
20
- labels: { caption: 'GET IT ON', name: 'Google Play' },
14
+ labels: { caption: 'Get it on', name: 'Google Play' },
21
15
  logoPaths: [
22
16
  {
23
- d: 'M1.337.924a1.486 1.486 0 0 0-.112.568v21.017c0 .217.045.419.124.6l11.155-11.087L1.337.924z',
24
- fill: '#4285F4',
25
- },
26
- {
27
- d: 'M13.544 10.989l3.258-3.238L3.45.195a1.466 1.466 0 0 0-.946-.179l11.04 10.973z',
28
- fill: '#34A853',
29
- },
30
- {
31
- d: 'M22.018 13.298l-3.919 2.218-3.515-3.493 3.543-3.521 3.891 2.202a1.49 1.49 0 0 1 0 2.594z',
32
- fill: '#FBBC04',
33
- },
34
- {
35
- d: 'M13.544 13.056l-11 10.933c.298.036.612-.016.906-.183l13.324-7.54-3.23-3.21z',
36
- fill: '#EA4335',
17
+ d: 'M6.2 2.9c-.5-.3-1.2.1-1.2.7v16.8c0 .6.7 1 1.2.7l14-8.4c.5-.3.5-1.1 0-1.4L6.2 2.9z',
37
18
  },
38
19
  ],
39
20
  },
40
21
  },
41
22
  };
42
23
  export const PsStoreBadgeClasses = {
43
- base: 'ps-focus-ring inline-flex shrink-0 items-center rounded-lg border font-sans leading-none transition-opacity hover:opacity-85 motion-reduce:transition-none',
44
- group: 'flex flex-wrap items-center',
24
+ base: 'ps-focus-ring ps-liquid ps-liquid-control ps-pressable group/store inline-flex w-full min-w-0 items-center bg-white/72 font-sans text-left text-ink hover:border-primary/30 dark:border-white/16 dark:bg-white/12 motion-reduce:transition-none motion-reduce:hover:transform-none',
25
+ group: 'grid w-full grid-cols-1 sm:grid-cols-2',
45
26
  sizes: {
46
27
  default: {
47
- badge: 'h-11 min-w-[8.25rem] gap-2 px-3',
48
- caption: 'text-[0.625rem]',
28
+ badge: 'min-h-12 gap-3 px-2.5 py-1.5',
29
+ caption: 'text-xs leading-4',
49
30
  gap: 'gap-3',
50
- logo: 'size-6',
51
- name: 'text-lg font-semibold tracking-tight',
31
+ logo: 'size-5',
32
+ name: 'text-sm font-semibold leading-5',
33
+ tile: 'size-9',
52
34
  },
53
35
  large: {
54
- badge: 'h-14 min-w-[10.5rem] gap-2.5 px-4',
55
- caption: 'text-xs',
36
+ badge: 'min-h-14 gap-3.5 px-3 py-2',
37
+ caption: 'text-xs leading-4',
56
38
  gap: 'gap-4',
57
- logo: 'size-8',
58
- name: 'text-2xl font-semibold tracking-tight',
39
+ logo: 'size-6',
40
+ name: 'text-base font-semibold leading-6',
41
+ tile: 'size-10',
59
42
  },
60
43
  },
44
+ tile: 'ps-icon-surface transition-colors group-hover/store:bg-primary/15 motion-reduce:transition-none',
61
45
  };
@@ -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';
@@ -145,3 +152,5 @@ export * from './components/ps-drag-grip';
145
152
  export * from './components/ps-drag-overlay';
146
153
  export * from './hooks/use-ps-drag-sensors';
147
154
  export * from './hooks/use-ps-reduced-motion';
155
+ export * from './components/ps-divider';
156
+ export * from './models/ps-divider-orientation';
@@ -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';
@@ -145,3 +152,5 @@ export * from './components/ps-drag-grip';
145
152
  export * from './components/ps-drag-overlay';
146
153
  export * from './hooks/use-ps-drag-sensors';
147
154
  export * from './hooks/use-ps-reduced-motion';
155
+ export * from './components/ps-divider';
156
+ export * from './models/ps-divider-orientation';
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);
@@ -161,3 +168,5 @@ __exportStar(require("./components/ps-drag-grip"), exports);
161
168
  __exportStar(require("./components/ps-drag-overlay"), exports);
162
169
  __exportStar(require("./hooks/use-ps-drag-sensors"), exports);
163
170
  __exportStar(require("./hooks/use-ps-reduced-motion"), exports);
171
+ __exportStar(require("./components/ps-divider"), exports);
172
+ __exportStar(require("./models/ps-divider-orientation"), exports);
@@ -0,0 +1,6 @@
1
+ import type { PsFetcherSubmitOptions } from './ps-fetcher-submit-options';
2
+ export interface PsFetcherLike<Data> {
3
+ data: Data | undefined;
4
+ state: string;
5
+ submit: (values: Record<string, string>, options: PsFetcherSubmitOptions) => unknown;
6
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,3 @@
1
+ export interface PsFetcherSubmitOptions {
2
+ method: 'post';
3
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -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
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,4 @@
1
+ export interface PsOptimisticFetcherResult<Row> {
2
+ rows: Row[];
3
+ submit: (values: Record<string, string>) => void;
4
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,4 @@
1
+ export interface PsRevalidatorLike {
2
+ revalidate: () => Promise<void> | void;
3
+ state: string;
4
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1 @@
1
+ export type PsDividerOrientation = 'horizontal' | 'vertical';
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,4 +1,3 @@
1
1
  export interface PsStoreBadgeLogoPath {
2
2
  d: string;
3
- fill: string;
4
3
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pallasoft/ps-core-components",
3
- "version": "2.26.0",
3
+ "version": "2.28.0",
4
4
  "private": false,
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/esm/index.js",