@jmruthers/pace-core 0.6.4 → 0.6.5
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/{DataTable-E7YQZD7D.js → DataTable-AOVNCPTX.js} +8 -8
- package/dist/{PublicPageProvider-DEMpysFR.d.ts → PublicPageProvider-QTFVrL-Z.d.ts} +65 -83
- package/dist/{UnifiedAuthProvider-QPXO24B4.js → UnifiedAuthProvider-4SBX4LU5.js} +4 -4
- package/dist/{api-6LVZTHDS.js → api-O6HTBX5Y.js} +3 -3
- package/dist/{chunk-I6DAQMWX.js → chunk-6COVEUS7.js} +130 -106
- package/dist/chunk-6COVEUS7.js.map +1 -0
- package/dist/{chunk-36LVWXB2.js → chunk-AFVQODI2.js} +37 -1
- package/dist/{chunk-36LVWXB2.js.map → chunk-AFVQODI2.js.map} +1 -1
- package/dist/{chunk-3LPHPB62.js → chunk-EFN2EIMK.js} +2 -2
- package/dist/{chunk-ATKZM7RX.js → chunk-G7QEZTYQ.js} +31 -31
- package/dist/{chunk-ATKZM7RX.js.map → chunk-G7QEZTYQ.js.map} +1 -1
- package/dist/{chunk-NN6WWZ5U.js → chunk-HU2C6SSC.js} +29 -18
- package/dist/chunk-HU2C6SSC.js.map +1 -0
- package/dist/{chunk-AVMLPIM7.js → chunk-IHB5DR3H.js} +102 -51
- package/dist/chunk-IHB5DR3H.js.map +1 -0
- package/dist/{chunk-7JPAB3T5.js → chunk-IVOFDYWT.js} +364 -208
- package/dist/chunk-IVOFDYWT.js.map +1 -0
- package/dist/{chunk-6SOIHG6Z.js → chunk-JGRYX5UX.js} +120 -20
- package/dist/chunk-JGRYX5UX.js.map +1 -0
- package/dist/{chunk-OEWDTMG7.js → chunk-NTM7ZSB6.js} +4 -4
- package/dist/chunk-NTM7ZSB6.js.map +1 -0
- package/dist/{chunk-5EC5MEWX.js → chunk-RGAWHO7N.js} +4 -4
- package/dist/chunk-RGAWHO7N.js.map +1 -0
- package/dist/{chunk-YKRAFF5K.js → chunk-UPPMRMYG.js} +3 -3
- package/dist/{chunk-YKRAFF5K.js.map → chunk-UPPMRMYG.js.map} +1 -1
- package/dist/components.d.ts +2 -3
- package/dist/components.js +24 -28
- package/dist/components.js.map +1 -1
- package/dist/{contextValidator-OOPCLPZW.js → contextValidator-5OGXSPKS.js} +2 -2
- package/dist/hooks.d.ts +3 -3
- package/dist/hooks.js +41 -139
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +27 -18
- package/dist/index.js +41 -50
- package/dist/index.js.map +1 -1
- package/dist/providers.js +3 -3
- package/dist/rbac/index.d.ts +16 -9
- package/dist/rbac/index.js +6 -6
- package/dist/{usePublicRouteParams-i3qtoBgg.d.ts → usePublicRouteParams-ClnV4tnv.d.ts} +8 -8
- package/dist/utils.js +1 -1
- package/docs/api/modules.md +210 -100
- package/package.json +1 -2
- package/scripts/validate-master.js +1 -1
- package/src/components/DataTable/__tests__/keyboard.test.tsx +15 -2
- package/src/components/DataTable/components/ImportModal.tsx +4 -6
- package/src/components/DataTable/components/ViewRowModal.tsx +4 -4
- package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +455 -96
- package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +122 -58
- package/src/components/DataTable/core/DataTableContext.tsx +1 -1
- package/src/components/DateTimeField/DateTimeField.tsx +17 -19
- package/src/components/DateTimeField/README.md +5 -2
- package/src/components/Dialog/Dialog.test.tsx +248 -228
- package/src/components/Dialog/Dialog.tsx +455 -325
- package/src/components/Dialog/index.ts +3 -3
- package/src/components/FileDisplay/FileDisplay.test.tsx +41 -0
- package/src/components/FileDisplay/FileDisplay.tsx +5 -5
- package/src/components/Form/Form.test.tsx +3 -2
- package/src/components/Form/Form.tsx +4 -5
- package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +28 -28
- package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +40 -54
- package/src/components/LoginForm/LoginForm.tsx +2 -2
- package/src/components/NavigationMenu/NavigationMenu.tsx +2 -2
- package/src/components/PaceAppLayout/PaceAppLayout.tsx +32 -39
- package/src/components/PaceAppLayout/README.md +10 -9
- package/src/components/PaceAppLayout/test-setup.tsx +40 -31
- package/src/components/PasswordChange/PasswordChangeForm.test.tsx +61 -0
- package/src/components/PasswordChange/PasswordChangeForm.tsx +20 -13
- package/src/components/PublicLayout/PublicLayout.test.tsx +7 -3
- package/src/components/PublicLayout/PublicPageLayout.tsx +5 -8
- package/src/components/UserMenu/UserMenu.test.tsx +38 -6
- package/src/components/UserMenu/UserMenu.tsx +36 -34
- package/src/components/index.ts +3 -4
- package/src/hooks/useEventTheme.ts +4 -4
- package/src/hooks/useEvents.ts +11 -7
- package/src/hooks/useKeyboardShortcuts.ts +1 -1
- package/src/hooks/useOrganisationPermissions.ts +4 -4
- package/src/hooks/useOrganisations.ts +13 -7
- package/src/index.ts +11 -1
- package/src/rbac/README.md +20 -20
- package/src/rbac/hooks/useRBAC.test.ts +21 -3
- package/src/rbac/hooks/useRBAC.ts +4 -3
- package/src/rbac/hooks/useResourcePermissions.test.ts +125 -30
- package/src/rbac/hooks/useResourcePermissions.ts +57 -29
- package/src/rbac/permissions.ts +17 -17
- package/src/rbac/utils/contextValidator.ts +36 -0
- package/src/services/AuthService.ts +2 -5
- package/src/services/InactivityService.ts +139 -58
- package/src/styles/core.css +4 -0
- package/src/utils/formatting/formatTime.test.ts +3 -2
- package/dist/chunk-5EC5MEWX.js.map +0 -1
- package/dist/chunk-6SOIHG6Z.js.map +0 -1
- package/dist/chunk-7JPAB3T5.js.map +0 -1
- package/dist/chunk-AVMLPIM7.js.map +0 -1
- package/dist/chunk-I6DAQMWX.js.map +0 -1
- package/dist/chunk-NN6WWZ5U.js.map +0 -1
- package/dist/chunk-OEWDTMG7.js.map +0 -1
- /package/dist/{DataTable-E7YQZD7D.js.map → DataTable-AOVNCPTX.js.map} +0 -0
- /package/dist/{UnifiedAuthProvider-QPXO24B4.js.map → UnifiedAuthProvider-4SBX4LU5.js.map} +0 -0
- /package/dist/{api-6LVZTHDS.js.map → api-O6HTBX5Y.js.map} +0 -0
- /package/dist/{chunk-3LPHPB62.js.map → chunk-EFN2EIMK.js.map} +0 -0
- /package/dist/{contextValidator-OOPCLPZW.js.map → contextValidator-5OGXSPKS.js.map} +0 -0
package/dist/components.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { a as UnifiedAuthContextType, d as UnifiedAuthProvider, c as UnifiedAuthProviderProps, u as useUnifiedAuth } from './UnifiedAuthProvider-CKvHP1MK.js';
|
|
2
|
-
export { A as AddressField, k as AddressFieldProps, l as AddressFieldRef, o as Alert, q as AlertDescription, p as AlertTitle, r as Avatar, s as AvatarProps, t as Badge, u as BadgeProps, v as BadgeVariant, B as Button, a as ButtonProps,
|
|
2
|
+
export { A as AddressField, k as AddressFieldProps, l as AddressFieldRef, o as Alert, q as AlertDescription, p as AlertTitle, r as Avatar, s as AvatarProps, t as Badge, u as BadgeProps, v as BadgeVariant, B as Button, a as ButtonProps, am as Calendar, an as CalendarProps, C as Card, g as CardActions, i as CardActionsProps, f as CardContent, e as CardDescription, c as CardFooter, b as CardHeader, h as CardProps, d as CardTitle, w as Checkbox, aR as ContextSelector, aS as ContextSelectorProps, M as Dialog, V as DialogBody, a4 as DialogBodyProps, Q as DialogClose, a1 as DialogCloseProps, R as DialogContent, $ as DialogContentProps, Y as DialogDescription, W as DialogFooter, a3 as DialogFooterProps, U as DialogHeader, a2 as DialogHeaderProps, N as DialogPortal, a0 as DialogPortalProps, Z as DialogProps, a5 as DialogSize, X as DialogTitle, O as DialogTrigger, _ as DialogTriggerProps, aU as ErrorBoundary, aW as ErrorBoundaryProps, aV as ErrorBoundaryProvider, aY as ErrorBoundaryProviderProps, aX as ErrorBoundaryState, b3 as FileDisplay, b4 as FileDisplayProps, b1 as FileUpload, b2 as FileUploadProps, aK as Footer, aL as FooterProps, aD as Form, aE as FormField, aG as FormFieldProps, aF as FormProps, aZ as GlobalErrorHandler, aJ as Header, I as Input, j as InputProps, L as Label, m as LabelProps, a_ as LoadingSpinner, aH as LoginForm, aI as LoginFormProps, aQ as NavigationItem, aO as NavigationMenu, aP as NavigationMenuProps, bm as PaceAppLayout, bl as PaceAppLayoutProps, bo as PaceLoginPage, bn as PaceLoginPageProps, P as Progress, y as ProgressProps, aM as ProtectedRoute, aN as ProtectedRouteProps, be as PublicPageFooter, bk as PublicPageFooterProps, bd as PublicPageHeader, bj as PublicPageHeaderProps, bc as PublicPageLayout, bi as PublicPageLayoutProps, bf as PublicPageProvider, a6 as Select, aa as SelectContent, a7 as SelectGroup, ac as SelectItem, ab as SelectLabel, ad as SelectSeparator, a9 as SelectTrigger, a8 as SelectValue, a$ as SessionRestorationLoader, b0 as SessionRestorationLoaderProps, S as Switch, x as SwitchProps, z as Table, E as TableBody, F as TableCaption, G as TableCell, H as TableFooter, J as TableHead, D as TableHeader, K as TableRow, ae as Tabs, ah as TabsContent, al as TabsContentProps, af as TabsList, aj as TabsListProps, ai as TabsProps, ag as TabsTrigger, ak as TabsTriggerProps, T as Textarea, n as TextareaProps, ao as Toast, aq as ToastAction, aw as ToastActionElement, av as ToastClose, au as ToastDescription, ax as ToastProps, ar as ToastProvider, at as ToastTitle, as as ToastViewport, ap as Toaster, ay as Tooltip, aA as TooltipContent, aB as TooltipProvider, aC as TooltipRoot, az as TooltipTrigger, bb as UseFileReferenceForRecordReturn, b9 as UseFileReferenceOptions, ba as UseFileReferenceReturn, aT as UserMenu, b5 as useFileReference, b7 as useFileReferenceById, b6 as useFileReferenceForRecord, b8 as useFilesByCategory, bh as useIsPublicPage, bg as usePublicPageContext } from './PublicPageProvider-QTFVrL-Z.js';
|
|
3
3
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
4
|
export { u as useToast } from './useToast-AyaT-x7p.js';
|
|
5
5
|
export { D as DataTable, a as DataTableProps } from './DataTable-BMRU8a1j.js';
|
|
@@ -13,7 +13,6 @@ import './auth-BZOJqrdd.js';
|
|
|
13
13
|
import '@radix-ui/react-label';
|
|
14
14
|
import '@radix-ui/react-checkbox';
|
|
15
15
|
import '@radix-ui/react-switch';
|
|
16
|
-
import '@radix-ui/react-dialog';
|
|
17
16
|
import '@radix-ui/react-tabs';
|
|
18
17
|
import 'react-day-picker';
|
|
19
18
|
import '@radix-ui/react-toast';
|
|
@@ -35,7 +34,7 @@ import '@tanstack/react-table';
|
|
|
35
34
|
* Features:
|
|
36
35
|
* - Automatic UTC ↔ timezone conversion
|
|
37
36
|
* - Prevents unwanted conversions during user editing
|
|
38
|
-
* - Shows timezone information when not UTC
|
|
37
|
+
* - Shows timezone information below the input field when not UTC
|
|
39
38
|
* - Supports both ISO string and Date object values
|
|
40
39
|
* - Uses native datetime-local input type
|
|
41
40
|
* - Accessible form field with proper labels
|
package/dist/components.js
CHANGED
|
@@ -47,7 +47,7 @@ import {
|
|
|
47
47
|
useFileReferenceById,
|
|
48
48
|
useFileReferenceForRecord,
|
|
49
49
|
useFilesByCategory
|
|
50
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-6COVEUS7.js";
|
|
51
51
|
import {
|
|
52
52
|
Alert,
|
|
53
53
|
AlertDescription,
|
|
@@ -69,7 +69,6 @@ import {
|
|
|
69
69
|
DialogDescription,
|
|
70
70
|
DialogFooter,
|
|
71
71
|
DialogHeader,
|
|
72
|
-
DialogOverlay,
|
|
73
72
|
DialogPortal,
|
|
74
73
|
DialogTitle,
|
|
75
74
|
DialogTrigger,
|
|
@@ -88,27 +87,27 @@ import {
|
|
|
88
87
|
TooltipProvider,
|
|
89
88
|
TooltipRoot,
|
|
90
89
|
TooltipTrigger
|
|
91
|
-
} from "./chunk-
|
|
92
|
-
import "./chunk-
|
|
93
|
-
import "./chunk-
|
|
90
|
+
} from "./chunk-IVOFDYWT.js";
|
|
91
|
+
import "./chunk-HU2C6SSC.js";
|
|
92
|
+
import "./chunk-UPPMRMYG.js";
|
|
94
93
|
import {
|
|
95
94
|
useToast
|
|
96
|
-
} from "./chunk-
|
|
95
|
+
} from "./chunk-JGRYX5UX.js";
|
|
97
96
|
import {
|
|
98
97
|
ErrorBoundary,
|
|
99
98
|
ErrorBoundaryProvider,
|
|
100
99
|
PublicPageProvider,
|
|
101
100
|
useIsPublicPage,
|
|
102
101
|
usePublicPageContext
|
|
103
|
-
} from "./chunk-
|
|
102
|
+
} from "./chunk-NTM7ZSB6.js";
|
|
104
103
|
import "./chunk-KQCRWDSA.js";
|
|
105
104
|
import {
|
|
106
105
|
UnifiedAuthProvider,
|
|
107
106
|
useUnifiedAuth
|
|
108
|
-
} from "./chunk-
|
|
109
|
-
import "./chunk-
|
|
107
|
+
} from "./chunk-IHB5DR3H.js";
|
|
108
|
+
import "./chunk-EFN2EIMK.js";
|
|
110
109
|
import "./chunk-63FOKYGO.js";
|
|
111
|
-
import "./chunk-
|
|
110
|
+
import "./chunk-AFVQODI2.js";
|
|
112
111
|
import {
|
|
113
112
|
FileCategory
|
|
114
113
|
} from "./chunk-ZSAAAMVR.js";
|
|
@@ -209,23 +208,21 @@ function DateTimeField({
|
|
|
209
208
|
const timezoneDisplay = getTimezoneDisplay();
|
|
210
209
|
return /* @__PURE__ */ jsxs("div", { className: cn("space-y-2", className), children: [
|
|
211
210
|
/* @__PURE__ */ jsx(Label, { htmlFor: fieldId, required, helperText, error, children: label }),
|
|
212
|
-
/* @__PURE__ */
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
timezoneDisplay && /* @__PURE__ */ jsx("span", { className: "absolute right-3 top-1/2 -translate-y-1/2 text-sm text-muted-foreground pointer-events-none", children: timezoneDisplay })
|
|
228
|
-
] })
|
|
211
|
+
/* @__PURE__ */ jsx(
|
|
212
|
+
Input,
|
|
213
|
+
{
|
|
214
|
+
ref: inputRef,
|
|
215
|
+
id: fieldId,
|
|
216
|
+
type: "datetime-local",
|
|
217
|
+
value: displayValue,
|
|
218
|
+
onChange: handleChange,
|
|
219
|
+
onBlur: handleBlur,
|
|
220
|
+
required,
|
|
221
|
+
error: !!error,
|
|
222
|
+
className: "w-full"
|
|
223
|
+
}
|
|
224
|
+
),
|
|
225
|
+
timezoneDisplay && !error && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: timezoneDisplay })
|
|
229
226
|
] });
|
|
230
227
|
}
|
|
231
228
|
|
|
@@ -296,7 +293,6 @@ export {
|
|
|
296
293
|
DialogDescription,
|
|
297
294
|
DialogFooter,
|
|
298
295
|
DialogHeader,
|
|
299
|
-
DialogOverlay,
|
|
300
296
|
DialogPortal,
|
|
301
297
|
DialogTitle,
|
|
302
298
|
DialogTrigger,
|
package/dist/components.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/DateTimeField/DateTimeField.tsx","../src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx"],"sourcesContent":["/**\n * @file DateTimeField Component\n * @package @jmruthers/pace-core\n * @module Components/DateTimeField\n * @since 0.1.0\n *\n * Form input component for datetime values with timezone support.\n * Handles UTC ↔ timezone conversion automatically.\n *\n * Features:\n * - Automatic UTC ↔ timezone conversion\n * - Prevents unwanted conversions during user editing\n * - Shows timezone information when not UTC\n * - Supports both ISO string and Date object values\n * - Uses native datetime-local input type\n * - Accessible form field with proper labels\n *\n * @example\n * ```tsx\n * import { DateTimeField } from '@jmruthers/pace-core/components';\n * import { useState } from 'react';\n *\n * function EventForm() {\n * const [startTime, setStartTime] = useState<string>();\n *\n * return (\n * <DateTimeField\n * label=\"Start Time\"\n * value={startTime}\n * onChange={setStartTime}\n * timezone=\"America/New_York\"\n * required\n * />\n * );\n * }\n * ```\n *\n * @accessibility\n * - Proper label association with htmlFor\n * - Required field indicators\n * - Screen reader friendly\n * - Keyboard navigation support\n * - Focus management\n */\n\nimport * as React from 'react';\nimport { format, parse } from 'date-fns';\nimport { Label } from '../Label';\nimport { Input } from '../Input';\nimport { cn } from '../../utils/core/cn';\nimport { toZonedTime, fromZonedTime, getUserTimeZone } from '../../utils/timezone';\n\n/**\n * Props for the DateTimeField component\n */\nexport interface DateTimeFieldProps {\n /**\n * Field label\n */\n label: string;\n /**\n * UTC date value (ISO string, Date object, or undefined)\n */\n value: string | Date | undefined;\n /**\n * Change handler that receives UTC value (ISO string or Date object)\n */\n onChange: (value: string | Date | undefined) => void;\n /**\n * Target timezone for display (default: 'UTC')\n */\n timezone?: string;\n /**\n * Whether the field is required\n */\n required?: boolean;\n /**\n * Additional CSS classes\n */\n className?: string;\n /**\n * If true, onChange returns Date object instead of ISO string\n */\n returnAsDate?: boolean;\n /**\n * Input id (auto-generated if not provided)\n */\n id?: string;\n /**\n * Helper text to display below the label\n */\n helperText?: string;\n /**\n * Error message to display\n */\n error?: string;\n}\n\n/**\n * DateTimeField component\n * Form input for datetime values with automatic timezone conversion\n *\n * @param props - DateTimeField configuration\n * @returns JSX.Element - The rendered datetime field\n */\nexport function DateTimeField({\n label,\n value,\n onChange,\n timezone = 'UTC',\n required = false,\n className,\n returnAsDate = false,\n id,\n helperText,\n error\n}: DateTimeFieldProps) {\n const [isEditing, setIsEditing] = React.useState(false);\n const inputRef = React.useRef<HTMLInputElement>(null);\n const fieldId = id || `datetime-field-${React.useId()}`;\n\n // Convert UTC value to timezone for display\n const getDisplayValue = React.useCallback((): string => {\n if (!value) {\n return '';\n }\n\n try {\n let dateObj: Date;\n if (typeof value === 'string') {\n dateObj = new Date(value);\n } else {\n dateObj = value;\n }\n\n if (!dateObj || isNaN(dateObj.getTime())) {\n return '';\n }\n\n // Convert UTC to timezone\n const zonedDate = toZonedTime(dateObj, timezone);\n\n // Format for datetime-local input (YYYY-MM-DDTHH:mm)\n return format(zonedDate, \"yyyy-MM-dd'T'HH:mm\");\n } catch {\n return '';\n }\n }, [value, timezone]);\n\n const displayValue = isEditing ? undefined : getDisplayValue();\n\n // Handle input change\n const handleChange = React.useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n setIsEditing(true);\n const inputValue = e.target.value;\n\n if (!inputValue) {\n onChange(undefined);\n return;\n }\n\n try {\n // Parse the datetime-local value (in timezone)\n const localDate = parse(inputValue, \"yyyy-MM-dd'T'HH:mm\", new Date());\n\n if (isNaN(localDate.getTime())) {\n onChange(undefined);\n return;\n }\n\n // Convert from timezone to UTC\n const utcDate = fromZonedTime(localDate, timezone);\n\n // Return as ISO string or Date object\n if (returnAsDate) {\n onChange(utcDate);\n } else {\n onChange(utcDate.toISOString());\n }\n } catch {\n onChange(undefined);\n }\n }, [timezone, returnAsDate, onChange]);\n\n // Handle blur to stop editing mode\n const handleBlur = React.useCallback(() => {\n setIsEditing(false);\n }, []);\n\n // Get timezone display text\n const getTimezoneDisplay = React.useCallback((): string => {\n if (timezone === 'UTC') {\n return '';\n }\n\n const userTz = getUserTimeZone();\n if (timezone === userTz) {\n return 'Local';\n }\n\n return timezone;\n }, [timezone]);\n\n const timezoneDisplay = getTimezoneDisplay();\n\n return (\n <div className={cn('space-y-2', className)}>\n <Label htmlFor={fieldId} required={required} helperText={helperText} error={error}>\n {label}\n </Label>\n <div className=\"relative\">\n <Input\n ref={inputRef}\n id={fieldId}\n type=\"datetime-local\"\n value={displayValue}\n onChange={handleChange}\n onBlur={handleBlur}\n required={required}\n error={!!error}\n className=\"w-full\"\n />\n {timezoneDisplay && (\n <span className=\"absolute right-3 top-1/2 -translate-y-1/2 text-sm text-muted-foreground pointer-events-none\">\n {timezoneDisplay}\n </span>\n )}\n </div>\n </div>\n );\n}\n\n","/**\n * @file DatePickerWithTimezone Component\n * @package @jmruthers/pace-core\n * @module Components/DatePickerWithTimezone\n * @since 0.1.0\n *\n * Date picker component that displays timezone information alongside the calendar.\n * Provides a calendar interface with timezone context for date selection.\n *\n * Features:\n * - Calendar date selection\n * - Timezone display (shows \"Local\" when matches user timezone)\n * - Optional \"Done\" button\n * - Accessible date selection\n * - Keyboard navigation support\n *\n * @example\n * ```tsx\n * import { DatePickerWithTimezone } from '@jmruthers/pace-core/components';\n * import { useState } from 'react';\n *\n * function DateSelector() {\n * const [date, setDate] = useState<Date>();\n *\n * return (\n * <DatePickerWithTimezone\n * selected={date}\n * onSelect={setDate}\n * timezone=\"America/New_York\"\n * onDone={() => console.log('Date selected')}\n * />\n * );\n * }\n * ```\n *\n * @accessibility\n * - WCAG 2.1 AA compliant\n * - Keyboard navigation support\n * - Screen reader friendly\n * - Focus management\n * - Proper ARIA attributes\n */\n\nimport * as React from 'react';\nimport { Calendar } from '../Calendar';\nimport { Button } from '../Button';\nimport { Clock } from 'lucide-react';\nimport { getUserTimeZone } from '../../utils/timezone';\nimport { cn } from '../../utils/core/cn';\n\n/**\n * Props for the DatePickerWithTimezone component\n */\nexport interface DatePickerWithTimezoneProps {\n /**\n * Currently selected date\n */\n selected?: Date;\n /**\n * Date selection handler\n */\n onSelect: (date: Date | undefined) => void;\n /**\n * Optional callback when \"Done\" button is clicked\n */\n onDone?: () => void;\n /**\n * Timezone to display (defaults to user's timezone)\n */\n timezone?: string;\n /**\n * Additional CSS classes\n */\n className?: string;\n}\n\n/**\n * DatePickerWithTimezone component\n * Date picker with timezone information display\n *\n * @param props - DatePickerWithTimezone configuration\n * @returns JSX.Element - The rendered date picker with timezone\n */\nexport function DatePickerWithTimezone({\n selected,\n onSelect,\n onDone,\n timezone,\n className\n}: DatePickerWithTimezoneProps) {\n const userTimezone = getUserTimeZone();\n const displayTimezone = timezone || userTimezone;\n const timezoneDisplay = displayTimezone === userTimezone ? 'Local' : displayTimezone;\n\n return (\n <div className={cn('flex flex-col', className)}>\n <div className=\"p-3\">\n <Calendar\n mode=\"single\"\n selected={selected}\n onSelect={onSelect}\n initialFocus\n captionLayout=\"dropdown\"\n startMonth={new Date(1900, 0)}\n endMonth={new Date(2100, 11)}\n className=\"p-0\"\n />\n </div>\n\n <div className=\"flex items-center justify-between border-t border-border px-3 py-2\">\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <Clock className=\"size-4\" aria-hidden=\"true\" />\n <span>\n Timezone: <span aria-label={`Timezone ${timezoneDisplay}`}>{timezoneDisplay}</span>\n </span>\n </div>\n {onDone && (\n <Button onClick={onDone} size=\"sm\" className=\"h-8\">\n Done\n </Button>\n )}\n </div>\n </div>\n );\n}\n\n"],"mappings":"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","names":["jsx","jsxs"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/DateTimeField/DateTimeField.tsx","../src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx"],"sourcesContent":["/**\n * @file DateTimeField Component\n * @package @jmruthers/pace-core\n * @module Components/DateTimeField\n * @since 0.1.0\n *\n * Form input component for datetime values with timezone support.\n * Handles UTC ↔ timezone conversion automatically.\n *\n * Features:\n * - Automatic UTC ↔ timezone conversion\n * - Prevents unwanted conversions during user editing\n * - Shows timezone information below the input field when not UTC\n * - Supports both ISO string and Date object values\n * - Uses native datetime-local input type\n * - Accessible form field with proper labels\n *\n * @example\n * ```tsx\n * import { DateTimeField } from '@jmruthers/pace-core/components';\n * import { useState } from 'react';\n *\n * function EventForm() {\n * const [startTime, setStartTime] = useState<string>();\n *\n * return (\n * <DateTimeField\n * label=\"Start Time\"\n * value={startTime}\n * onChange={setStartTime}\n * timezone=\"America/New_York\"\n * required\n * />\n * );\n * }\n * ```\n *\n * @accessibility\n * - Proper label association with htmlFor\n * - Required field indicators\n * - Screen reader friendly\n * - Keyboard navigation support\n * - Focus management\n */\n\nimport * as React from 'react';\nimport { format, parse } from 'date-fns';\nimport { Label } from '../Label';\nimport { Input } from '../Input';\nimport { cn } from '../../utils/core/cn';\nimport { toZonedTime, fromZonedTime, getUserTimeZone } from '../../utils/timezone';\n\n/**\n * Props for the DateTimeField component\n */\nexport interface DateTimeFieldProps {\n /**\n * Field label\n */\n label: string;\n /**\n * UTC date value (ISO string, Date object, or undefined)\n */\n value: string | Date | undefined;\n /**\n * Change handler that receives UTC value (ISO string or Date object)\n */\n onChange: (value: string | Date | undefined) => void;\n /**\n * Target timezone for display (default: 'UTC')\n */\n timezone?: string;\n /**\n * Whether the field is required\n */\n required?: boolean;\n /**\n * Additional CSS classes\n */\n className?: string;\n /**\n * If true, onChange returns Date object instead of ISO string\n */\n returnAsDate?: boolean;\n /**\n * Input id (auto-generated if not provided)\n */\n id?: string;\n /**\n * Helper text to display below the label\n */\n helperText?: string;\n /**\n * Error message to display\n */\n error?: string;\n}\n\n/**\n * DateTimeField component\n * Form input for datetime values with automatic timezone conversion\n *\n * @param props - DateTimeField configuration\n * @returns JSX.Element - The rendered datetime field\n */\nexport function DateTimeField({\n label,\n value,\n onChange,\n timezone = 'UTC',\n required = false,\n className,\n returnAsDate = false,\n id,\n helperText,\n error\n}: DateTimeFieldProps) {\n const [isEditing, setIsEditing] = React.useState(false);\n const inputRef = React.useRef<HTMLInputElement>(null);\n const fieldId = id || `datetime-field-${React.useId()}`;\n\n // Convert UTC value to timezone for display\n const getDisplayValue = React.useCallback((): string => {\n if (!value) {\n return '';\n }\n\n try {\n let dateObj: Date;\n if (typeof value === 'string') {\n dateObj = new Date(value);\n } else {\n dateObj = value;\n }\n\n if (!dateObj || isNaN(dateObj.getTime())) {\n return '';\n }\n\n // Convert UTC to timezone\n const zonedDate = toZonedTime(dateObj, timezone);\n\n // Format for datetime-local input (YYYY-MM-DDTHH:mm)\n return format(zonedDate, \"yyyy-MM-dd'T'HH:mm\");\n } catch {\n return '';\n }\n }, [value, timezone]);\n\n const displayValue = isEditing ? undefined : getDisplayValue();\n\n // Handle input change\n const handleChange = React.useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n setIsEditing(true);\n const inputValue = e.target.value;\n\n if (!inputValue) {\n onChange(undefined);\n return;\n }\n\n try {\n // Parse the datetime-local value (in timezone)\n const localDate = parse(inputValue, \"yyyy-MM-dd'T'HH:mm\", new Date());\n\n if (isNaN(localDate.getTime())) {\n onChange(undefined);\n return;\n }\n\n // Convert from timezone to UTC\n const utcDate = fromZonedTime(localDate, timezone);\n\n // Return as ISO string or Date object\n if (returnAsDate) {\n onChange(utcDate);\n } else {\n onChange(utcDate.toISOString());\n }\n } catch {\n onChange(undefined);\n }\n }, [timezone, returnAsDate, onChange]);\n\n // Handle blur to stop editing mode\n const handleBlur = React.useCallback(() => {\n setIsEditing(false);\n }, []);\n\n // Get timezone display text\n const getTimezoneDisplay = React.useCallback((): string => {\n if (timezone === 'UTC') {\n return '';\n }\n\n const userTz = getUserTimeZone();\n if (timezone === userTz) {\n return 'Local';\n }\n\n return timezone;\n }, [timezone]);\n\n const timezoneDisplay = getTimezoneDisplay();\n\n return (\n <div className={cn('space-y-2', className)}>\n <Label htmlFor={fieldId} required={required} helperText={helperText} error={error}>\n {label}\n </Label>\n <Input\n ref={inputRef}\n id={fieldId}\n type=\"datetime-local\"\n value={displayValue}\n onChange={handleChange}\n onBlur={handleBlur}\n required={required}\n error={!!error}\n className=\"w-full\"\n />\n {timezoneDisplay && !error && (\n <p className=\"text-sm text-muted-foreground\">\n {timezoneDisplay}\n </p>\n )}\n </div>\n );\n}\n\n","/**\n * @file DatePickerWithTimezone Component\n * @package @jmruthers/pace-core\n * @module Components/DatePickerWithTimezone\n * @since 0.1.0\n *\n * Date picker component that displays timezone information alongside the calendar.\n * Provides a calendar interface with timezone context for date selection.\n *\n * Features:\n * - Calendar date selection\n * - Timezone display (shows \"Local\" when matches user timezone)\n * - Optional \"Done\" button\n * - Accessible date selection\n * - Keyboard navigation support\n *\n * @example\n * ```tsx\n * import { DatePickerWithTimezone } from '@jmruthers/pace-core/components';\n * import { useState } from 'react';\n *\n * function DateSelector() {\n * const [date, setDate] = useState<Date>();\n *\n * return (\n * <DatePickerWithTimezone\n * selected={date}\n * onSelect={setDate}\n * timezone=\"America/New_York\"\n * onDone={() => console.log('Date selected')}\n * />\n * );\n * }\n * ```\n *\n * @accessibility\n * - WCAG 2.1 AA compliant\n * - Keyboard navigation support\n * - Screen reader friendly\n * - Focus management\n * - Proper ARIA attributes\n */\n\nimport * as React from 'react';\nimport { Calendar } from '../Calendar';\nimport { Button } from '../Button';\nimport { Clock } from 'lucide-react';\nimport { getUserTimeZone } from '../../utils/timezone';\nimport { cn } from '../../utils/core/cn';\n\n/**\n * Props for the DatePickerWithTimezone component\n */\nexport interface DatePickerWithTimezoneProps {\n /**\n * Currently selected date\n */\n selected?: Date;\n /**\n * Date selection handler\n */\n onSelect: (date: Date | undefined) => void;\n /**\n * Optional callback when \"Done\" button is clicked\n */\n onDone?: () => void;\n /**\n * Timezone to display (defaults to user's timezone)\n */\n timezone?: string;\n /**\n * Additional CSS classes\n */\n className?: string;\n}\n\n/**\n * DatePickerWithTimezone component\n * Date picker with timezone information display\n *\n * @param props - DatePickerWithTimezone configuration\n * @returns JSX.Element - The rendered date picker with timezone\n */\nexport function DatePickerWithTimezone({\n selected,\n onSelect,\n onDone,\n timezone,\n className\n}: DatePickerWithTimezoneProps) {\n const userTimezone = getUserTimeZone();\n const displayTimezone = timezone || userTimezone;\n const timezoneDisplay = displayTimezone === userTimezone ? 'Local' : displayTimezone;\n\n return (\n <div className={cn('flex flex-col', className)}>\n <div className=\"p-3\">\n <Calendar\n mode=\"single\"\n selected={selected}\n onSelect={onSelect}\n initialFocus\n captionLayout=\"dropdown\"\n startMonth={new Date(1900, 0)}\n endMonth={new Date(2100, 11)}\n className=\"p-0\"\n />\n </div>\n\n <div className=\"flex items-center justify-between border-t border-border px-3 py-2\">\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <Clock className=\"size-4\" aria-hidden=\"true\" />\n <span>\n Timezone: <span aria-label={`Timezone ${timezoneDisplay}`}>{timezoneDisplay}</span>\n </span>\n </div>\n {onDone && (\n <Button onClick={onDone} size=\"sm\" className=\"h-8\">\n Done\n </Button>\n )}\n </div>\n </div>\n );\n}\n\n"],"mappings":"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","names":["jsx","jsxs"]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ContextValidator
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-AFVQODI2.js";
|
|
4
4
|
import "./chunk-PWLANIRT.js";
|
|
5
5
|
import "./chunk-DGUM43GV.js";
|
|
6
6
|
export {
|
|
7
7
|
ContextValidator
|
|
8
8
|
};
|
|
9
|
-
//# sourceMappingURL=contextValidator-
|
|
9
|
+
//# sourceMappingURL=contextValidator-5OGXSPKS.js.map
|
package/dist/hooks.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { u as useToast } from './useToast-AyaT-x7p.js';
|
|
2
|
-
import { S as StorageUploadOptions, a as StorageUploadResult, b as StorageListOptions, c as StorageListResult, d as StorageFileInfo } from './usePublicRouteParams-
|
|
3
|
-
export { O as OrganisationSecurityHook, l as UseAppConfigReturn, i as UseFormDialogOptions, j as UseFormDialogReturn, U as UseOrganisationPermissionsReturn, F as UsePublicEventLogoOptions, E as UsePublicEventLogoReturn, B as UsePublicEventOptions, A as UsePublicEventReturn, D as UsePublicFileDisplayOptions, C as UsePublicFileDisplayReturn, G as UsePublicRouteParamsReturn, n as clearPublicEventCache, q as clearPublicFileDisplayCache, t as clearPublicLogoCache, z as extractEventCodeFromPath, y as generatePublicRoutePath, o as getPublicEventCacheStats, r as getPublicFileDisplayCacheStats, v as getPublicLogoCacheStats, k as useAppConfig, u as useEventTheme, h as useFormDialog, e as useOrganisationPermissions, f as useOrganisationSecurity, m as usePublicEvent, x as usePublicEventCode, s as usePublicEventLogo, p as usePublicFileDisplay, w as usePublicRouteParams, g as useZodForm } from './usePublicRouteParams-
|
|
2
|
+
import { S as StorageUploadOptions, a as StorageUploadResult, b as StorageListOptions, c as StorageListResult, d as StorageFileInfo } from './usePublicRouteParams-ClnV4tnv.js';
|
|
3
|
+
export { O as OrganisationSecurityHook, l as UseAppConfigReturn, i as UseFormDialogOptions, j as UseFormDialogReturn, U as UseOrganisationPermissionsReturn, F as UsePublicEventLogoOptions, E as UsePublicEventLogoReturn, B as UsePublicEventOptions, A as UsePublicEventReturn, D as UsePublicFileDisplayOptions, C as UsePublicFileDisplayReturn, G as UsePublicRouteParamsReturn, n as clearPublicEventCache, q as clearPublicFileDisplayCache, t as clearPublicLogoCache, z as extractEventCodeFromPath, y as generatePublicRoutePath, o as getPublicEventCacheStats, r as getPublicFileDisplayCacheStats, v as getPublicLogoCacheStats, k as useAppConfig, u as useEventTheme, h as useFormDialog, e as useOrganisationPermissions, f as useOrganisationSecurity, m as usePublicEvent, x as usePublicEventCode, s as usePublicEventLogo, p as usePublicFileDisplay, w as usePublicRouteParams, g as useZodForm } from './usePublicRouteParams-ClnV4tnv.js';
|
|
4
4
|
import * as React$1 from 'react';
|
|
5
5
|
import { SortingState, ColumnFiltersState, ExpandedState } from '@tanstack/react-table';
|
|
6
6
|
import { d as DataRecord, g as PerformanceConfig, S as ServerSideConfig, C as ChunkingConfig, i as SearchIndexConfig, h as PaginationMode, k as ServerSideParams, l as ServerSideResponse, A as AutocompleteOptions, m as GooglePlaceAutocompletePrediction, P as ParsedAddress } from './types-CkbwOr4Y.js';
|
|
@@ -198,7 +198,7 @@ interface KeyboardShortcutsOptions {
|
|
|
198
198
|
*
|
|
199
199
|
* useKeyboardShortcuts(shortcuts);
|
|
200
200
|
*
|
|
201
|
-
* return <
|
|
201
|
+
* return <main>Content</main>;
|
|
202
202
|
* }
|
|
203
203
|
* ```
|
|
204
204
|
*/
|
package/dist/hooks.js
CHANGED
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
usePublicEventLogo,
|
|
13
13
|
usePublicRouteParams,
|
|
14
14
|
useZodForm
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-RGAWHO7N.js";
|
|
16
16
|
import {
|
|
17
17
|
archiveFile,
|
|
18
18
|
cleanupQueryCache,
|
|
@@ -34,20 +34,21 @@ import {
|
|
|
34
34
|
usePreventTabReload,
|
|
35
35
|
usePublicFileDisplay,
|
|
36
36
|
useQueryCache
|
|
37
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-UPPMRMYG.js";
|
|
38
38
|
import {
|
|
39
39
|
useDataTablePerformance,
|
|
40
|
+
useFocusTrap,
|
|
40
41
|
useToast
|
|
41
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-JGRYX5UX.js";
|
|
42
43
|
import {
|
|
43
44
|
useAppConfig,
|
|
44
45
|
useOrganisationSecurity
|
|
45
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-NTM7ZSB6.js";
|
|
46
47
|
import "./chunk-KQCRWDSA.js";
|
|
47
|
-
import "./chunk-
|
|
48
|
-
import "./chunk-
|
|
48
|
+
import "./chunk-IHB5DR3H.js";
|
|
49
|
+
import "./chunk-EFN2EIMK.js";
|
|
49
50
|
import "./chunk-63FOKYGO.js";
|
|
50
|
-
import "./chunk-
|
|
51
|
+
import "./chunk-AFVQODI2.js";
|
|
51
52
|
import "./chunk-ZSAAAMVR.js";
|
|
52
53
|
import "./chunk-QXHPKYJV.js";
|
|
53
54
|
import {
|
|
@@ -180,107 +181,8 @@ function useFocusManagement(options = {}) {
|
|
|
180
181
|
};
|
|
181
182
|
}
|
|
182
183
|
|
|
183
|
-
// src/hooks/useFocusTrap.ts
|
|
184
|
-
import { useRef as useRef2, useEffect as useEffect2, useCallback as useCallback2 } from "react";
|
|
185
|
-
var DEFAULT_FOCUSABLE_SELECTOR = [
|
|
186
|
-
"button:not([disabled])",
|
|
187
|
-
"[href]",
|
|
188
|
-
"input:not([disabled])",
|
|
189
|
-
"select:not([disabled])",
|
|
190
|
-
"textarea:not([disabled])",
|
|
191
|
-
'[tabindex]:not([tabindex="-1"])',
|
|
192
|
-
'[contenteditable="true"]'
|
|
193
|
-
].join(", ");
|
|
194
|
-
function useFocusTrap(options = {}) {
|
|
195
|
-
const {
|
|
196
|
-
isActive = false,
|
|
197
|
-
autoFocus = false,
|
|
198
|
-
restoreFocus = false,
|
|
199
|
-
onEscape,
|
|
200
|
-
focusableSelector = DEFAULT_FOCUSABLE_SELECTOR
|
|
201
|
-
} = options;
|
|
202
|
-
const containerRef = useRef2(null);
|
|
203
|
-
const previouslyFocusedElement = useRef2(null);
|
|
204
|
-
const getFocusableElements = useCallback2(() => {
|
|
205
|
-
if (!containerRef.current) return [];
|
|
206
|
-
return Array.from(
|
|
207
|
-
containerRef.current.querySelectorAll(focusableSelector)
|
|
208
|
-
).filter((element) => {
|
|
209
|
-
return (
|
|
210
|
-
// visible check
|
|
211
|
-
!element.hasAttribute("disabled") && !element.hasAttribute("hidden") && element.offsetParent !== null
|
|
212
|
-
);
|
|
213
|
-
});
|
|
214
|
-
}, [focusableSelector]);
|
|
215
|
-
const focusFirst = useCallback2(() => {
|
|
216
|
-
const elements = getFocusableElements();
|
|
217
|
-
if (elements.length > 0) {
|
|
218
|
-
elements[0].focus();
|
|
219
|
-
}
|
|
220
|
-
}, [getFocusableElements]);
|
|
221
|
-
const focusLast = useCallback2(() => {
|
|
222
|
-
const elements = getFocusableElements();
|
|
223
|
-
if (elements.length > 0) {
|
|
224
|
-
elements[elements.length - 1].focus();
|
|
225
|
-
}
|
|
226
|
-
}, [getFocusableElements]);
|
|
227
|
-
useEffect2(() => {
|
|
228
|
-
if (!isActive || !containerRef.current) return;
|
|
229
|
-
const handleKeyDown = (event) => {
|
|
230
|
-
if (event.key === "Escape" && onEscape) {
|
|
231
|
-
onEscape();
|
|
232
|
-
return;
|
|
233
|
-
}
|
|
234
|
-
if (event.key === "Tab") {
|
|
235
|
-
const focusableElements = getFocusableElements();
|
|
236
|
-
if (focusableElements.length === 0) return;
|
|
237
|
-
const firstElement = focusableElements[0];
|
|
238
|
-
const lastElement = focusableElements[focusableElements.length - 1];
|
|
239
|
-
if (event.shiftKey) {
|
|
240
|
-
if (document.activeElement === firstElement) {
|
|
241
|
-
event.preventDefault();
|
|
242
|
-
lastElement.focus();
|
|
243
|
-
}
|
|
244
|
-
} else {
|
|
245
|
-
if (document.activeElement === lastElement) {
|
|
246
|
-
event.preventDefault();
|
|
247
|
-
firstElement.focus();
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
};
|
|
252
|
-
const container = containerRef.current;
|
|
253
|
-
container.addEventListener("keydown", handleKeyDown);
|
|
254
|
-
return () => {
|
|
255
|
-
container.removeEventListener("keydown", handleKeyDown);
|
|
256
|
-
};
|
|
257
|
-
}, [isActive, onEscape, getFocusableElements]);
|
|
258
|
-
useEffect2(() => {
|
|
259
|
-
if (!isActive) return;
|
|
260
|
-
if (restoreFocus) {
|
|
261
|
-
previouslyFocusedElement.current = document.activeElement;
|
|
262
|
-
}
|
|
263
|
-
if (autoFocus) {
|
|
264
|
-
const timer = setTimeout(focusFirst, 0);
|
|
265
|
-
return () => clearTimeout(timer);
|
|
266
|
-
}
|
|
267
|
-
return () => {
|
|
268
|
-
if (restoreFocus && previouslyFocusedElement.current) {
|
|
269
|
-
previouslyFocusedElement.current.focus();
|
|
270
|
-
previouslyFocusedElement.current = null;
|
|
271
|
-
}
|
|
272
|
-
};
|
|
273
|
-
}, [isActive, autoFocus, restoreFocus, focusFirst]);
|
|
274
|
-
return {
|
|
275
|
-
containerRef,
|
|
276
|
-
focusFirst,
|
|
277
|
-
focusLast,
|
|
278
|
-
getFocusableElements
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
|
|
282
184
|
// src/hooks/useKeyboardShortcuts.ts
|
|
283
|
-
import { useEffect as
|
|
185
|
+
import { useEffect as useEffect2, useCallback as useCallback2 } from "react";
|
|
284
186
|
function parseKeyCombo(combo) {
|
|
285
187
|
const parts = combo.toLowerCase().split("+");
|
|
286
188
|
const key = parts.pop();
|
|
@@ -303,7 +205,7 @@ function matchesKeyCombo(event, combo) {
|
|
|
303
205
|
}
|
|
304
206
|
function useKeyboardShortcuts(shortcuts, options = {}) {
|
|
305
207
|
const { element = document, enabled = true } = options;
|
|
306
|
-
const handleKeyDown =
|
|
208
|
+
const handleKeyDown = useCallback2((event) => {
|
|
307
209
|
if (!enabled) return;
|
|
308
210
|
for (const shortcut of shortcuts) {
|
|
309
211
|
if (shortcut.enabled === false) continue;
|
|
@@ -319,7 +221,7 @@ function useKeyboardShortcuts(shortcuts, options = {}) {
|
|
|
319
221
|
}
|
|
320
222
|
}
|
|
321
223
|
}, [shortcuts, enabled]);
|
|
322
|
-
|
|
224
|
+
useEffect2(() => {
|
|
323
225
|
if (!enabled) return;
|
|
324
226
|
element.addEventListener("keydown", handleKeyDown);
|
|
325
227
|
return () => element.removeEventListener("keydown", handleKeyDown);
|
|
@@ -327,11 +229,11 @@ function useKeyboardShortcuts(shortcuts, options = {}) {
|
|
|
327
229
|
}
|
|
328
230
|
|
|
329
231
|
// src/hooks/useIsMobile.ts
|
|
330
|
-
import { useState, useEffect as
|
|
232
|
+
import { useState, useEffect as useEffect3 } from "react";
|
|
331
233
|
var MOBILE_BREAKPOINT = 768;
|
|
332
234
|
function useIsMobile() {
|
|
333
235
|
const [isMobile, setIsMobile] = useState(void 0);
|
|
334
|
-
|
|
236
|
+
useEffect3(() => {
|
|
335
237
|
if (typeof window === "undefined") {
|
|
336
238
|
setIsMobile(false);
|
|
337
239
|
return;
|
|
@@ -348,7 +250,7 @@ function useIsMobile() {
|
|
|
348
250
|
}
|
|
349
251
|
|
|
350
252
|
// src/hooks/useDataTableState.ts
|
|
351
|
-
import { useState as useState2, useCallback as
|
|
253
|
+
import { useState as useState2, useCallback as useCallback3 } from "react";
|
|
352
254
|
function useDataTableState(options) {
|
|
353
255
|
const { initialPageSize = 10, data } = options;
|
|
354
256
|
const [sorting, setSorting] = useState2([]);
|
|
@@ -357,7 +259,7 @@ function useDataTableState(options) {
|
|
|
357
259
|
const [pageSize, setPageSize] = useState2(initialPageSize);
|
|
358
260
|
const [pageIndex, setPageIndex] = useState2(0);
|
|
359
261
|
const [selectedRows, setSelectedRows] = useState2([]);
|
|
360
|
-
const resetState =
|
|
262
|
+
const resetState = useCallback3(() => {
|
|
361
263
|
setSorting([]);
|
|
362
264
|
setColumnFilters([]);
|
|
363
265
|
setExpanded({});
|
|
@@ -399,16 +301,16 @@ function useDataTableState(options) {
|
|
|
399
301
|
}
|
|
400
302
|
|
|
401
303
|
// src/hooks/usePerformanceMonitor.ts
|
|
402
|
-
import { useEffect as
|
|
304
|
+
import { useEffect as useEffect4, useRef as useRef2, useCallback as useCallback4 } from "react";
|
|
403
305
|
var log = createLogger("usePerformanceMonitor");
|
|
404
306
|
function usePerformanceMonitor(componentName, enabled = import.meta.env.MODE === "development", budgetName = "COMPONENT_RENDER") {
|
|
405
|
-
const renderStartTime =
|
|
406
|
-
const metrics =
|
|
407
|
-
const startMeasurement =
|
|
307
|
+
const renderStartTime = useRef2(0);
|
|
308
|
+
const metrics = useRef2([]);
|
|
309
|
+
const startMeasurement = useCallback4(() => {
|
|
408
310
|
if (!enabled) return;
|
|
409
311
|
renderStartTime.current = performance.now();
|
|
410
312
|
}, [enabled]);
|
|
411
|
-
const endMeasurement =
|
|
313
|
+
const endMeasurement = useCallback4(() => {
|
|
412
314
|
if (!enabled || renderStartTime.current === 0) return;
|
|
413
315
|
const renderTime = performance.now() - renderStartTime.current;
|
|
414
316
|
const metric = {
|
|
@@ -431,15 +333,15 @@ function usePerformanceMonitor(componentName, enabled = import.meta.env.MODE ===
|
|
|
431
333
|
}
|
|
432
334
|
renderStartTime.current = 0;
|
|
433
335
|
}, [enabled, componentName, budgetName]);
|
|
434
|
-
const getMetrics =
|
|
336
|
+
const getMetrics = useCallback4(() => {
|
|
435
337
|
return metrics.current.slice();
|
|
436
338
|
}, []);
|
|
437
|
-
const getAverageRenderTime =
|
|
339
|
+
const getAverageRenderTime = useCallback4(() => {
|
|
438
340
|
if (metrics.current.length === 0) return 0;
|
|
439
341
|
const total = metrics.current.reduce((sum, metric) => sum + metric.renderTime, 0);
|
|
440
342
|
return total / metrics.current.length;
|
|
441
343
|
}, []);
|
|
442
|
-
const getBudgetStatus =
|
|
344
|
+
const getBudgetStatus = useCallback4(() => {
|
|
443
345
|
const budget = PERFORMANCE_BUDGETS[budgetName];
|
|
444
346
|
if (!budget) return null;
|
|
445
347
|
const averageTime = getAverageRenderTime();
|
|
@@ -450,7 +352,7 @@ function usePerformanceMonitor(componentName, enabled = import.meta.env.MODE ===
|
|
|
450
352
|
efficiency: budget.threshold > 0 ? (budget.threshold - averageTime) / budget.threshold : 0
|
|
451
353
|
};
|
|
452
354
|
}, [budgetName, getAverageRenderTime]);
|
|
453
|
-
|
|
355
|
+
useEffect4(() => {
|
|
454
356
|
startMeasurement();
|
|
455
357
|
return endMeasurement;
|
|
456
358
|
});
|
|
@@ -464,7 +366,7 @@ function usePerformanceMonitor(componentName, enabled = import.meta.env.MODE ===
|
|
|
464
366
|
}
|
|
465
367
|
|
|
466
368
|
// src/hooks/useFileUrlCache.ts
|
|
467
|
-
import { useRef as
|
|
369
|
+
import { useRef as useRef3, useCallback as useCallback5 } from "react";
|
|
468
370
|
var globalUrlCache = /* @__PURE__ */ new Map();
|
|
469
371
|
var MAX_CACHE_SIZE = 500;
|
|
470
372
|
var DEFAULT_TTL_MS = 3600 * 1e3;
|
|
@@ -488,13 +390,13 @@ function cleanupCache() {
|
|
|
488
390
|
}
|
|
489
391
|
}
|
|
490
392
|
function useFileUrlCache() {
|
|
491
|
-
const cleanupIntervalRef =
|
|
393
|
+
const cleanupIntervalRef = useRef3(null);
|
|
492
394
|
if (cleanupIntervalRef.current === null && typeof window !== "undefined") {
|
|
493
395
|
cleanupIntervalRef.current = window.setInterval(() => {
|
|
494
396
|
cleanupCache();
|
|
495
397
|
}, 5 * 60 * 1e3);
|
|
496
398
|
}
|
|
497
|
-
const getUrl =
|
|
399
|
+
const getUrl = useCallback5(async (fileReference, supabase, organisationId, ttl = DEFAULT_TTL_MS) => {
|
|
498
400
|
const cacheKey = getCacheKey(fileReference);
|
|
499
401
|
const cached = globalUrlCache.get(cacheKey);
|
|
500
402
|
const now = Date.now();
|
|
@@ -527,7 +429,7 @@ function useFileUrlCache() {
|
|
|
527
429
|
return null;
|
|
528
430
|
}
|
|
529
431
|
}, []);
|
|
530
|
-
const setUrl =
|
|
432
|
+
const setUrl = useCallback5((fileReference, url, ttl = DEFAULT_TTL_MS) => {
|
|
531
433
|
const cacheKey = getCacheKey(fileReference);
|
|
532
434
|
globalUrlCache.set(cacheKey, {
|
|
533
435
|
url,
|
|
@@ -535,7 +437,7 @@ function useFileUrlCache() {
|
|
|
535
437
|
});
|
|
536
438
|
cleanupCache();
|
|
537
439
|
}, []);
|
|
538
|
-
const getCachedUrl =
|
|
440
|
+
const getCachedUrl = useCallback5((fileReference) => {
|
|
539
441
|
const cacheKey = getCacheKey(fileReference);
|
|
540
442
|
const cached = globalUrlCache.get(cacheKey);
|
|
541
443
|
const now = Date.now();
|
|
@@ -544,14 +446,14 @@ function useFileUrlCache() {
|
|
|
544
446
|
}
|
|
545
447
|
return null;
|
|
546
448
|
}, []);
|
|
547
|
-
const clearFile =
|
|
449
|
+
const clearFile = useCallback5((fileReference) => {
|
|
548
450
|
const cacheKey = getCacheKey(fileReference);
|
|
549
451
|
globalUrlCache.delete(cacheKey);
|
|
550
452
|
}, []);
|
|
551
|
-
const clearCache =
|
|
453
|
+
const clearCache = useCallback5(() => {
|
|
552
454
|
globalUrlCache.clear();
|
|
553
455
|
}, []);
|
|
554
|
-
const getCacheStats =
|
|
456
|
+
const getCacheStats = useCallback5(() => {
|
|
555
457
|
return {
|
|
556
458
|
size: globalUrlCache.size,
|
|
557
459
|
maxSize: MAX_CACHE_SIZE
|
|
@@ -568,7 +470,7 @@ function useFileUrlCache() {
|
|
|
568
470
|
}
|
|
569
471
|
|
|
570
472
|
// src/hooks/useStorage.ts
|
|
571
|
-
import { useState as useState3, useCallback as
|
|
473
|
+
import { useState as useState3, useCallback as useCallback6 } from "react";
|
|
572
474
|
var log2 = createLogger("useStorage");
|
|
573
475
|
function useStorage({ supabase, appName, orgId }) {
|
|
574
476
|
const [isUploading, setIsUploading] = useState3(false);
|
|
@@ -576,7 +478,7 @@ function useStorage({ supabase, appName, orgId }) {
|
|
|
576
478
|
const [isListing, setIsListing] = useState3(false);
|
|
577
479
|
const [listError, setListError] = useState3(null);
|
|
578
480
|
const [files, setFiles] = useState3([]);
|
|
579
|
-
const handleUploadFile =
|
|
481
|
+
const handleUploadFile = useCallback6(async (file, options = {}) => {
|
|
580
482
|
setIsUploading(true);
|
|
581
483
|
setUploadError(null);
|
|
582
484
|
try {
|
|
@@ -604,10 +506,10 @@ function useStorage({ supabase, appName, orgId }) {
|
|
|
604
506
|
setIsUploading(false);
|
|
605
507
|
}
|
|
606
508
|
}, [supabase, appName, orgId]);
|
|
607
|
-
const handleGetPublicUrl =
|
|
509
|
+
const handleGetPublicUrl = useCallback6((path) => {
|
|
608
510
|
return getPublicUrl(supabase, path);
|
|
609
511
|
}, [supabase]);
|
|
610
|
-
const handleGetSignedUrl =
|
|
512
|
+
const handleGetSignedUrl = useCallback6(async (path, expiresIn) => {
|
|
611
513
|
try {
|
|
612
514
|
const result = await getSignedUrl(supabase, path, {
|
|
613
515
|
appName,
|
|
@@ -620,7 +522,7 @@ function useStorage({ supabase, appName, orgId }) {
|
|
|
620
522
|
return null;
|
|
621
523
|
}
|
|
622
524
|
}, [supabase, appName, orgId]);
|
|
623
|
-
const handleDeleteFile =
|
|
525
|
+
const handleDeleteFile = useCallback6(async (path) => {
|
|
624
526
|
try {
|
|
625
527
|
const result = await deleteFile(supabase, path);
|
|
626
528
|
if (result.success) {
|
|
@@ -634,7 +536,7 @@ function useStorage({ supabase, appName, orgId }) {
|
|
|
634
536
|
};
|
|
635
537
|
}
|
|
636
538
|
}, [supabase]);
|
|
637
|
-
const handleArchiveFile =
|
|
539
|
+
const handleArchiveFile = useCallback6(async (path) => {
|
|
638
540
|
try {
|
|
639
541
|
const result = await archiveFile(supabase, path, { appName, orgId });
|
|
640
542
|
if (result.success) {
|
|
@@ -648,7 +550,7 @@ function useStorage({ supabase, appName, orgId }) {
|
|
|
648
550
|
};
|
|
649
551
|
}
|
|
650
552
|
}, [supabase, appName, orgId]);
|
|
651
|
-
const handleListFiles =
|
|
553
|
+
const handleListFiles = useCallback6(async (options = {}) => {
|
|
652
554
|
setIsListing(true);
|
|
653
555
|
setListError(null);
|
|
654
556
|
try {
|
|
@@ -668,7 +570,7 @@ function useStorage({ supabase, appName, orgId }) {
|
|
|
668
570
|
setIsListing(false);
|
|
669
571
|
}
|
|
670
572
|
}, [supabase, appName, orgId]);
|
|
671
|
-
const refreshFiles =
|
|
573
|
+
const refreshFiles = useCallback6(async () => {
|
|
672
574
|
await handleListFiles();
|
|
673
575
|
}, [handleListFiles]);
|
|
674
576
|
return {
|
|
@@ -701,7 +603,7 @@ function useFileUpload({ supabase, appName, orgId }) {
|
|
|
701
603
|
const [uploadProgress, setUploadProgress] = useState3(0);
|
|
702
604
|
const [isUploading, setIsUploading] = useState3(false);
|
|
703
605
|
const [uploadError, setUploadError] = useState3(null);
|
|
704
|
-
const uploadWithProgress =
|
|
606
|
+
const uploadWithProgress = useCallback6(async (file, options = {}) => {
|
|
705
607
|
setIsUploading(true);
|
|
706
608
|
setUploadProgress(0);
|
|
707
609
|
setUploadError(null);
|