@pagamio/frontend-commons-lib 0.8.251 → 0.8.253

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.
@@ -71,6 +71,10 @@ export interface ApiQueryConfig<ResponseData> extends Omit<RequestConfig, 'metho
71
71
  * Callback when query errors
72
72
  */
73
73
  onError?: (error: ApiErrorResponse) => void;
74
+ /**
75
+ * Auto-refetch interval in milliseconds (e.g. 30_000 for 30 seconds)
76
+ */
77
+ refetchInterval?: number | false;
74
78
  }
75
79
  /**
76
80
  * Hook for GET requests using React Query
@@ -86,7 +90,7 @@ export interface ApiQueryConfig<ResponseData> extends Omit<RequestConfig, 'metho
86
90
  * });
87
91
  * ```
88
92
  */
89
- export declare function useApiQuery<ResponseData>({ queryKey, endpoint, enabled, staleTime, gcTime, select, onSuccess, onError, ...requestConfig }: ApiQueryConfig<ResponseData> & {
93
+ export declare function useApiQuery<ResponseData>({ queryKey, endpoint, enabled, staleTime, gcTime, select, onSuccess, onError, refetchInterval, ...requestConfig }: ApiQueryConfig<ResponseData> & {
90
94
  endpoint: string;
91
95
  }): UseQueryResult<ResponseData, ApiErrorResponse>;
92
96
  /**
@@ -62,7 +62,7 @@ export function QueryClientProvider({ children, queryClient, showDevTools }) {
62
62
  * });
63
63
  * ```
64
64
  */
65
- export function useApiQuery({ queryKey, endpoint, enabled = true, staleTime, gcTime, select, onSuccess, onError, ...requestConfig }) {
65
+ export function useApiQuery({ queryKey, endpoint, enabled = true, staleTime, gcTime, select, onSuccess, onError, refetchInterval, ...requestConfig }) {
66
66
  const api = useApi();
67
67
  return useQuery({
68
68
  queryKey,
@@ -73,6 +73,7 @@ export function useApiQuery({ queryKey, endpoint, enabled = true, staleTime, gcT
73
73
  staleTime,
74
74
  gcTime,
75
75
  select,
76
+ ...(refetchInterval !== undefined && { refetchInterval }),
76
77
  });
77
78
  }
78
79
  /**
@@ -9,14 +9,14 @@ const TOKEN_CONFIG = {
9
9
  defaultExpiry: 1 / 24,
10
10
  path: '/',
11
11
  secure: true,
12
- sameSite: 'strict',
12
+ sameSite: 'lax',
13
13
  },
14
14
  REFRESH_TOKEN: {
15
15
  name: 'refreshToken',
16
16
  defaultExpiry: 7,
17
17
  path: '/',
18
18
  secure: true,
19
- sameSite: 'strict',
19
+ sameSite: 'lax',
20
20
  },
21
21
  };
22
22
  export class TokenManager {
@@ -26,7 +26,7 @@ export class TokenManager {
26
26
  constructor(config) {
27
27
  this.cookieOptions = {
28
28
  secure: true,
29
- sameSite: 'strict',
29
+ sameSite: 'lax',
30
30
  path: '/',
31
31
  ...config.cookieOptions,
32
32
  };
@@ -1,6 +1,8 @@
1
1
  import React from 'react';
2
2
  interface EmptyStateProps {
3
3
  title: string;
4
+ description?: string;
5
+ icon?: React.ReactNode;
4
6
  }
5
7
  declare const EmptyState: React.FC<EmptyStateProps>;
6
8
  export default EmptyState;
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { MdOutlineFolder } from 'react-icons/md';
3
- const EmptyState = ({ title }) => {
4
- return (_jsxs("div", { className: "flex flex-col items-center justify-center rounded-lg border border-input bg-muted p-8 text-center", children: [_jsx("div", { className: "mb-4 flex h-32 w-32 items-center justify-center", children: _jsx(MdOutlineFolder, { className: "h-full w-full text-muted-foreground" }) }), _jsx("h2", { className: "mb-2 text-lg font-semibold text-foreground", children: title }), _jsx("p", { className: "text-muted-foreground", children: "We couldn't find any data at this moment. Please try again later or adjust your filters." })] }));
3
+ const EmptyState = ({ title, description, icon }) => {
4
+ return (_jsxs("div", { className: "flex flex-col items-center justify-center rounded-lg border border-input bg-muted p-8 text-center", children: [_jsx("div", { className: "mb-4 flex h-32 w-32 items-center justify-center", children: icon ?? _jsx(MdOutlineFolder, { className: "h-full w-full text-muted-foreground" }) }), _jsx("h2", { className: "mb-2 text-lg font-semibold text-foreground", children: title }), _jsx("p", { className: "text-muted-foreground", children: description ?? "We couldn't find any data at this moment. Please try again later or adjust your filters." })] }));
5
5
  };
6
6
  export default EmptyState;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @fileoverview TimerBadge - Elapsed time display with urgency-based color coding
3
+ *
4
+ * Self-updating badge that shows elapsed time from a given start time.
5
+ * Color transitions green → amber → red based on configurable thresholds.
6
+ * Designed for operational contexts where time-pressure matters (KDS, order boards).
7
+ *
8
+ * @example
9
+ * ```tsx
10
+ * <TimerBadge startTime={order.createdAt} warningMinutes={15} dangerMinutes={30} />
11
+ * ```
12
+ */
13
+ import * as React from 'react';
14
+ export interface TimerBadgeProps {
15
+ /** ISO date string or Date object marking when the timer started */
16
+ startTime: string | Date;
17
+ /** Minutes elapsed before turning amber (default: 15) */
18
+ warningMinutes?: number;
19
+ /** Minutes elapsed before turning red (default: 30) */
20
+ dangerMinutes?: number;
21
+ /** Size variant */
22
+ size?: 'sm' | 'md';
23
+ className?: string;
24
+ }
25
+ declare const TimerBadge: React.FC<TimerBadgeProps>;
26
+ export default TimerBadge;
@@ -0,0 +1,43 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * @fileoverview TimerBadge - Elapsed time display with urgency-based color coding
4
+ *
5
+ * Self-updating badge that shows elapsed time from a given start time.
6
+ * Color transitions green → amber → red based on configurable thresholds.
7
+ * Designed for operational contexts where time-pressure matters (KDS, order boards).
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * <TimerBadge startTime={order.createdAt} warningMinutes={15} dangerMinutes={30} />
12
+ * ```
13
+ */
14
+ import * as React from 'react';
15
+ import { cn } from '../../helpers/utils';
16
+ // =============================================================================
17
+ // HELPERS
18
+ // =============================================================================
19
+ function getElapsedSeconds(startTime) {
20
+ const start = typeof startTime === 'string' ? new Date(startTime) : startTime;
21
+ return Math.floor((Date.now() - start.getTime()) / 1000);
22
+ }
23
+ function formatElapsed(totalSeconds) {
24
+ const minutes = Math.floor(totalSeconds / 60);
25
+ const seconds = totalSeconds % 60;
26
+ return `${String(minutes).padStart(2, '0')}m ${String(seconds).padStart(2, '0')}s`;
27
+ }
28
+ // =============================================================================
29
+ // COMPONENT
30
+ // =============================================================================
31
+ const TimerBadge = ({ startTime, warningMinutes = 15, dangerMinutes = 30, size = 'sm', className, }) => {
32
+ const [elapsed, setElapsed] = React.useState(() => getElapsedSeconds(startTime));
33
+ React.useEffect(() => {
34
+ const interval = setInterval(() => {
35
+ setElapsed(getElapsedSeconds(startTime));
36
+ }, 1000);
37
+ return () => clearInterval(interval);
38
+ }, [startTime]);
39
+ const minutes = elapsed / 60;
40
+ const urgency = minutes >= dangerMinutes ? 'danger' : minutes >= warningMinutes ? 'warning' : 'safe';
41
+ return (_jsxs("span", { className: cn('inline-flex items-center gap-1 rounded-full font-mono font-medium tabular-nums', size === 'sm' ? 'px-2 py-0.5 text-xs' : 'px-2.5 py-1 text-sm', urgency === 'safe' && 'bg-emerald-500/15 text-emerald-600 dark:text-emerald-400', urgency === 'warning' && 'bg-amber-500/15 text-amber-600 dark:text-amber-400', urgency === 'danger' && 'bg-red-500/15 text-red-600 dark:text-red-400', className), children: [_jsxs("svg", { className: cn('h-3 w-3 flex-shrink-0', size === 'md' && 'h-3.5 w-3.5'), fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, "aria-hidden": "true", children: [_jsx("circle", { cx: "12", cy: "12", r: "10" }), _jsx("polyline", { points: "12 6 12 12 16 14" })] }), formatElapsed(elapsed)] }));
42
+ };
43
+ export default TimerBadge;
@@ -55,3 +55,5 @@ export type { ImageUploaderProps } from './ImageUploader';
55
55
  export { default as NotificationModal } from './NotificationModal';
56
56
  export type { NotificationModalProps } from './NotificationModal';
57
57
  export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from './Tooltip';
58
+ export { default as TimerBadge } from './TimerBadge';
59
+ export type { TimerBadgeProps } from './TimerBadge';
@@ -56,3 +56,5 @@ export { default as ImageUploader } from './ImageUploader';
56
56
  export { default as NotificationModal } from './NotificationModal';
57
57
  // Tooltip - v2 shadcn-style tooltip with Radix
58
58
  export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from './Tooltip';
59
+ // TimerBadge - elapsed time with urgency coloring (green → amber → red)
60
+ export { default as TimerBadge } from './TimerBadge';
package/lib/styles.css CHANGED
@@ -2184,6 +2184,9 @@ video {
2184
2184
  --tw-bg-opacity: 1;
2185
2185
  background-color: rgb(254 243 199 / var(--tw-bg-opacity, 1));
2186
2186
  }
2187
+ .bg-amber-500\/15 {
2188
+ background-color: rgb(245 158 11 / 0.15);
2189
+ }
2187
2190
  .bg-amber-600 {
2188
2191
  --tw-bg-opacity: 1;
2189
2192
  background-color: rgb(217 119 6 / var(--tw-bg-opacity, 1));
@@ -2248,6 +2251,9 @@ video {
2248
2251
  --tw-bg-opacity: 1;
2249
2252
  background-color: rgb(209 250 229 / var(--tw-bg-opacity, 1));
2250
2253
  }
2254
+ .bg-emerald-500\/15 {
2255
+ background-color: rgb(16 185 129 / 0.15);
2256
+ }
2251
2257
  .bg-gray-100 {
2252
2258
  --tw-bg-opacity: 1;
2253
2259
  background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));
@@ -2435,6 +2441,9 @@ video {
2435
2441
  --tw-bg-opacity: 1;
2436
2442
  background-color: rgb(240 82 82 / var(--tw-bg-opacity, 1));
2437
2443
  }
2444
+ .bg-red-500\/15 {
2445
+ background-color: rgb(240 82 82 / 0.15);
2446
+ }
2438
2447
  .bg-red-600 {
2439
2448
  --tw-bg-opacity: 1;
2440
2449
  background-color: rgb(224 36 36 / var(--tw-bg-opacity, 1));
@@ -2919,6 +2928,10 @@ video {
2919
2928
  .italic {
2920
2929
  font-style: italic;
2921
2930
  }
2931
+ .tabular-nums {
2932
+ --tw-numeric-spacing: tabular-nums;
2933
+ font-variant-numeric: var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction);
2934
+ }
2922
2935
  .leading-6 {
2923
2936
  line-height: 1.5rem;
2924
2937
  }
@@ -2955,6 +2968,10 @@ video {
2955
2968
  .text-accent-foreground {
2956
2969
  color: hsl(var(--accent-foreground));
2957
2970
  }
2971
+ .text-amber-600 {
2972
+ --tw-text-opacity: 1;
2973
+ color: rgb(217 119 6 / var(--tw-text-opacity, 1));
2974
+ }
2958
2975
  .text-amber-700 {
2959
2976
  --tw-text-opacity: 1;
2960
2977
  color: rgb(180 83 9 / var(--tw-text-opacity, 1));
@@ -5174,6 +5191,10 @@ video {
5174
5191
  --tw-text-opacity: 1;
5175
5192
  color: rgb(22 78 99 / var(--tw-text-opacity, 1));
5176
5193
  }
5194
+ .dark\:text-emerald-400:is(.dark *) {
5195
+ --tw-text-opacity: 1;
5196
+ color: rgb(52 211 153 / var(--tw-text-opacity, 1));
5197
+ }
5177
5198
  .dark\:text-foreground:is(.dark *) {
5178
5199
  color: hsl(var(--foreground));
5179
5200
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pagamio/frontend-commons-lib",
3
3
  "description": "Pagamio library for Frontend reusable components like the form engine and table container",
4
- "version": "0.8.251",
4
+ "version": "0.8.253",
5
5
  "publishConfig": {
6
6
  "access": "public",
7
7
  "provenance": false