@juv/codego-react-ui 3.5.21 → 3.6.1
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/README.md +55 -0
- package/dist/index.cjs +139 -178
- package/dist/index.d.cts +41 -23
- package/dist/index.d.ts +41 -23
- package/dist/index.global.js +132 -177
- package/dist/index.js +143 -186
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import * as React from 'react';
|
|
|
3
3
|
import React__default from 'react';
|
|
4
4
|
import { AxiosRequestConfig } from 'axios';
|
|
5
5
|
import { UseBoundStore, StoreApi } from 'zustand';
|
|
6
|
+
import CryptoJS from 'crypto-js';
|
|
6
7
|
|
|
7
8
|
type AuthView = "login" | "register" | "resetPassword";
|
|
8
9
|
interface AuthField {
|
|
@@ -810,26 +811,6 @@ interface BulletinServerPaginationProp {
|
|
|
810
811
|
currentPage: number;
|
|
811
812
|
goToPage: (page: number) => void;
|
|
812
813
|
}
|
|
813
|
-
interface UseServerBulletinOptions {
|
|
814
|
-
url: string;
|
|
815
|
-
params?: Record<string, string | number>;
|
|
816
|
-
encrypt?: boolean;
|
|
817
|
-
key?: string;
|
|
818
|
-
decryptPayloadLog?: boolean;
|
|
819
|
-
/** Map raw API row → BulletinItem */
|
|
820
|
-
transform?: (row: any) => BulletinItem;
|
|
821
|
-
}
|
|
822
|
-
interface UseServerBulletinReturn {
|
|
823
|
-
items: BulletinItem[];
|
|
824
|
-
currentPage: number;
|
|
825
|
-
pagination: ServerPagination | null;
|
|
826
|
-
serverPagination: BulletinServerPaginationProp | null;
|
|
827
|
-
loading: boolean;
|
|
828
|
-
error: string | null;
|
|
829
|
-
goToPage: (page: number) => void;
|
|
830
|
-
reload: () => void;
|
|
831
|
-
}
|
|
832
|
-
declare function useServerBulletin({ url, params, encrypt, key, decryptPayloadLog, transform, }: UseServerBulletinOptions): UseServerBulletinReturn;
|
|
833
814
|
interface BulletinPreviewProps {
|
|
834
815
|
item: BulletinItem;
|
|
835
816
|
onClose: () => void;
|
|
@@ -838,8 +819,12 @@ interface BulletinPreviewProps {
|
|
|
838
819
|
onView?: (item: BulletinItem) => void;
|
|
839
820
|
/** Custom actions to add to the preview header */
|
|
840
821
|
customActions?: BulletinAction[];
|
|
822
|
+
/** Extra React elements rendered in the preview modal header's left area */
|
|
823
|
+
headerAction?: React.ReactNode;
|
|
824
|
+
/** Extra React elements rendered in the preview modal footer's action area */
|
|
825
|
+
footerAction?: React.ReactNode;
|
|
841
826
|
}
|
|
842
|
-
declare function BulletinPreview({ item, onClose, onEdit, onDelete, onView, customActions }: BulletinPreviewProps): React.ReactPortal;
|
|
827
|
+
declare function BulletinPreview({ item, onClose, onEdit, onDelete, onView, customActions, headerAction, footerAction }: BulletinPreviewProps): React.ReactPortal;
|
|
843
828
|
interface BulletinEditField {
|
|
844
829
|
key: keyof BulletinItem | string;
|
|
845
830
|
label: string;
|
|
@@ -898,10 +883,16 @@ interface BulletinBoardProps {
|
|
|
898
883
|
serverPagination?: BulletinServerPaginationProp | null;
|
|
899
884
|
/** Fired when a post card is clicked (ignored when preview=true). */
|
|
900
885
|
onItemClick?: (item: BulletinItem) => void;
|
|
886
|
+
/** Extra React elements rendered below the board content (above pagination). */
|
|
887
|
+
footerAction?: React.ReactNode;
|
|
888
|
+
/** Extra React elements rendered in the preview modal header's left area. */
|
|
889
|
+
headerPreviewAction?: React.ReactNode;
|
|
890
|
+
/** Extra React elements rendered in the preview modal footer's action area. */
|
|
891
|
+
footerPreviewAction?: (item: BulletinItem) => React.ReactNode;
|
|
901
892
|
/** Additional CSS classes on the outer wrapper. */
|
|
902
893
|
className?: string;
|
|
903
894
|
}
|
|
904
|
-
declare function BulletinBoard({ items, layout, columns, variant, searchable, filterable, categories: categoriesProp, title, headerAction, showHeader, emptyMessage, loading, loadingCount, onItemClick, onView, onEdit, onDelete, preview, editBaseUrl, editMethod, editIdKey, editFields, deleteBaseUrl, deleteIdKey, serverPagination, className, }: BulletinBoardProps): react_jsx_runtime.JSX.Element;
|
|
895
|
+
declare function BulletinBoard({ items, layout, columns, variant, searchable, filterable, categories: categoriesProp, title, headerAction, showHeader, emptyMessage, loading, loadingCount, onItemClick, onView, onEdit, onDelete, preview, editBaseUrl, editMethod, editIdKey, editFields, deleteBaseUrl, deleteIdKey, serverPagination, footerAction, headerPreviewAction, footerPreviewAction, className, }: BulletinBoardProps): react_jsx_runtime.JSX.Element;
|
|
905
896
|
|
|
906
897
|
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
907
898
|
variant?: "primary" | "secondary" | "outline" | "ghost" | "link" | "danger" | "success" | "destructive";
|
|
@@ -978,6 +969,8 @@ interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
|
978
969
|
confirmBeforeClickModalTitle?: string;
|
|
979
970
|
confirmBeforeClickModalContent?: React.ReactNode;
|
|
980
971
|
confirmBeforeClickFooterAction?: React.ReactNode;
|
|
972
|
+
onConfirm?: () => void;
|
|
973
|
+
onCancel?: () => void;
|
|
981
974
|
href?: string;
|
|
982
975
|
target?: "_blank" | "_self";
|
|
983
976
|
as?: "button" | "a" | "div";
|
|
@@ -2561,4 +2554,29 @@ type StoreWrapper<T extends object> = {
|
|
|
2561
2554
|
*/
|
|
2562
2555
|
declare function createStore<T extends object>(initialValue: T, sessionName: string, expireInterval?: number): StoreWrapper<T>;
|
|
2563
2556
|
|
|
2564
|
-
|
|
2557
|
+
type LaravelEncryptedPayload = {
|
|
2558
|
+
iv: string;
|
|
2559
|
+
value: string;
|
|
2560
|
+
mac: string;
|
|
2561
|
+
tag?: string;
|
|
2562
|
+
};
|
|
2563
|
+
declare function getLaravelSecretKey(): string;
|
|
2564
|
+
declare function parseLaravelKey(secretKey: string): CryptoJS.lib.WordArray;
|
|
2565
|
+
declare function parseLaravelEncryptedPayload(payload: string): LaravelEncryptedPayload;
|
|
2566
|
+
declare function decryptLaravelPayload<T>(payload: string, secretKey?: string): T;
|
|
2567
|
+
|
|
2568
|
+
/**
|
|
2569
|
+
* Decrypt a Laravel-encrypted API response.
|
|
2570
|
+
*
|
|
2571
|
+
* Accepts either:
|
|
2572
|
+
* - a raw encrypted string (the full response body)
|
|
2573
|
+
* - an object with an `data` key holding the encrypted string
|
|
2574
|
+
*
|
|
2575
|
+
* @param response Raw encrypted string or `{ data: string }` object
|
|
2576
|
+
* @param key Optional Laravel APP_KEY (base64:… or raw). Falls back to VITE_LARAVEL_KEY.
|
|
2577
|
+
*/
|
|
2578
|
+
declare function decryptResponse<T = unknown>(response: string | {
|
|
2579
|
+
data: string;
|
|
2580
|
+
}, key?: string): T;
|
|
2581
|
+
|
|
2582
|
+
export { Accordion, type AccordionItem, type AccordionProps, type AccordionVariant, type ActionField, type ActionFieldType, type AuthField, type AuthVariant, type AuthView, Authentication, type AuthenticationProps, AvatarStack, type AvatarStackProps, Badge, type BadgeProps, type BadgeSize, type BadgeVariant, Breadcrumb, type BreadcrumbItem, type BreadcrumbProps, type BulletinAction, BulletinBoard, type BulletinBoardProps, type BulletinColumns, type BulletinEditField, type BulletinItem, type BulletinLayout, BulletinPreview, type BulletinPreviewProps, type BulletinPriority, type BulletinServerPaginationProp, type BulletinVariant, Button, type ButtonProps, COLOR_PALETTE, Calendar, CalendarDateRangePicker, type CalendarDateRangePickerProps, type CalendarDateRangeVariant, type CalendarEvent, type CalendarProps, type CalendarView, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, type ChartDataPoint, ChartWidget, type ChartWidgetProps, Checkbox, type CheckboxProps, CircularProgress, type CircularProgressProps, type ClusterVariant, CodegoApiProvider, ColorPicker, type ColorPickerProps, type Column, Combobox, type ComboboxOption, type ComboboxProps, type CommandItem, CommandPalette, type CommandPaletteProps, ComposableWidget, type ComposableWidgetProps, type ConfirmVariant, ContextMenu, type ContextMenuItem, type ContextMenuProps, DataGrid, type DataGridColumn, type DataGridProps, DatePickerPopup, type DateRange, DateRangePicker, type DateRangePickerProps, type DefaultActionsConfig, DocsLayout, Drawer, type DrawerProps, type DrawerSide, Dropdown, DropdownItem, DropdownLabel, type DropdownProps, DropdownSeparator, EVENT_COLORS, type FileTypeValidation, FileUpload, type FileUploadProps, type FlexAlign, type FlexDirection, type FlexGap, FlexItem, type FlexItemProps, type FlexJustify, FlexLayout, type FlexLayoutProps, type FlexWrap, type FlyToOptions, type FormField, type FormFieldType, type GridAlign, type GridCols, type GridGap, GridItem, type GridItemProps, GridLayout, type GridLayoutProps, GroupNavigation, type GroupNavigationProps, type ImageEditorMode, type ImageEditorOptions, Input, type InputProps, KanbanBoard, type KanbanBoardProps, type KanbanCard, type KanbanColumn, Label, type LaravelEncryptedPayload, LeafletMap, type LeafletMapProps, LeftSidebar, type LeftSidebarProps, type MapLibreClusterVariant, MapLibreMap, type MapLibreMarker, type MapLibreProps, type MapLibreRoute, type MapLibreRouteType, type MapLibreStyle, type MapMarker, type MapRoute, type MarkerColor, type MetricItem, MetricRow, type MetricRowProps, Modal, ModalConfirmation, type ModalConfirmationProps, type ModalProps, ModalUnchange, type ModalUnchangeProps, ModalWithForms, type ModalWithFormsProps, type NavGroup, type NavItem, Navigation, type NavigationProps, NotificationBanner, type NotificationBannerProps, type NotificationItem, NotificationPanel, type NotificationPanelProps, type NotificationVariant, OtpInput, type OtpInputProps, Pagination, type PaginationProps, Panel, type PanelProps, PanelSettings, type PanelSettingsProps, type PanelSettingsTab, PanelSidebarGroup, PanelSidebarItem, Popover, type PopoverPlacement, type PopoverProps, Progress, type ProgressProps, type ProgressSize, type ProgressVariant, type PropRow, PropsTable, RadioGroup, type RadioGroupProps, type RadioOption, type RadioSize, type RadioVariant, RangeSlider, type RangeSliderProps, Repeater, type RepeaterProps, type RequestConfig, ResizablePanels, type ResizablePanelsProps, RichTextEditor, type RichTextEditorProps, RightSidebar, type RightSidebarProps, type RouteType, ScrollArea, type ScrollAreaProps, Section, SectionBlock, type SectionProps, type SectionVariant, Select, type SelectOption, type SelectProps, type SemanticColor, type ServerDataGridProp, type ServerPagination, type ServerPaginationLink, type ServerPaginationProp, type ServerTableResponse, Skeleton, Slider, type SliderProps, type SortDir, StatCard, type StatCardProps, type StatTrend, StatsWidget, type StatsWidgetProps, type Step, type StepStatus, Stepper, type StepperProps, type TabItem, type TabSize, type TabVariant, Table, TableOfContents, type TableProps, TableWidget, type TableWidgetProps, Tabs, type TabsProps, TagInput, type TagInputProps, Textarea, type TextareaProps, type ThemeColors, ThemeProvider, type ThemeSettings, Timeline, type TimelineItem, type TimelineProps, type TimelineVariant, type ToastItem, type ToastPosition, ToastProvider, type ToastProviderProps, type ToastVariant, type TocItem, TocProvider, ToggleSwitch, type ToggleSwitchProps, Tooltip, type TooltipProps, Topbar, type TopbarProps, type TreeNode, TreeView, type TreeViewProps, type TrendDir, type UseServerDataGridOptions, type UseServerDataGridReturn, type UseServerTableOptions, type UseServerTableReturn, Widget, type WidgetProps, Wizard, type WizardActionProps, type WizardLayout, type WizardProps, type WizardSize, type WizardStep, type WizardVariant, api, createStore, decryptLaravelPayload, decryptResponse, getLaravelSecretKey, parseLaravelEncryptedPayload, parseLaravelKey, useServerDataGrid, useServerTable, useTheme, useToast, useToc };
|
package/dist/index.global.js
CHANGED
|
@@ -53730,7 +53730,11 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
|
|
|
53730
53730
|
Wizard: () => Wizard,
|
|
53731
53731
|
api: () => api,
|
|
53732
53732
|
createStore: () => createStore2,
|
|
53733
|
-
|
|
53733
|
+
decryptLaravelPayload: () => decryptLaravelPayload,
|
|
53734
|
+
decryptResponse: () => decryptResponse,
|
|
53735
|
+
getLaravelSecretKey: () => getLaravelSecretKey,
|
|
53736
|
+
parseLaravelEncryptedPayload: () => parseLaravelEncryptedPayload,
|
|
53737
|
+
parseLaravelKey: () => parseLaravelKey,
|
|
53734
53738
|
useServerDataGrid: () => useServerDataGrid,
|
|
53735
53739
|
useServerTable: () => useServerTable,
|
|
53736
53740
|
useTheme: () => useTheme,
|
|
@@ -60730,6 +60734,7 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
|
|
|
60730
60734
|
|
|
60731
60735
|
// src/components/ui/button.tsx
|
|
60732
60736
|
var React = __toESM(require_react(), 1);
|
|
60737
|
+
var ReactDOM2 = __toESM(require_react_dom(), 1);
|
|
60733
60738
|
var import_jsx_runtime = __toESM(require_jsx_runtime(), 1);
|
|
60734
60739
|
var Button = React.forwardRef(
|
|
60735
60740
|
({
|
|
@@ -60808,6 +60813,8 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
|
|
|
60808
60813
|
confirmBeforeClickModalTitle,
|
|
60809
60814
|
confirmBeforeClickModalContent,
|
|
60810
60815
|
confirmBeforeClickFooterAction,
|
|
60816
|
+
onConfirm,
|
|
60817
|
+
onCancel,
|
|
60811
60818
|
href,
|
|
60812
60819
|
target,
|
|
60813
60820
|
as = "button",
|
|
@@ -60903,11 +60910,13 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
|
|
|
60903
60910
|
};
|
|
60904
60911
|
function handleConfirmProceed() {
|
|
60905
60912
|
setConfirmOpen(false);
|
|
60913
|
+
onConfirm?.();
|
|
60906
60914
|
onClick?.(pendingEvent.current ?? void 0);
|
|
60907
60915
|
pendingEvent.current = null;
|
|
60908
60916
|
}
|
|
60909
60917
|
function handleConfirmCancel() {
|
|
60910
60918
|
setConfirmOpen(false);
|
|
60919
|
+
onCancel?.();
|
|
60911
60920
|
pendingEvent.current = null;
|
|
60912
60921
|
}
|
|
60913
60922
|
const buttonContent = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
@@ -60935,46 +60944,49 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
|
|
|
60935
60944
|
tabIndex,
|
|
60936
60945
|
"data-testid": testID
|
|
60937
60946
|
};
|
|
60938
|
-
const confirmModal = confirmBeforeClick && confirmOpen ?
|
|
60939
|
-
|
|
60940
|
-
|
|
60941
|
-
|
|
60942
|
-
|
|
60943
|
-
|
|
60944
|
-
|
|
60945
|
-
|
|
60946
|
-
|
|
60947
|
-
|
|
60948
|
-
|
|
60949
|
-
|
|
60950
|
-
|
|
60951
|
-
|
|
60952
|
-
|
|
60953
|
-
|
|
60954
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
60955
|
-
|
|
60956
|
-
|
|
60957
|
-
|
|
60958
|
-
|
|
60959
|
-
|
|
60960
|
-
|
|
60961
|
-
|
|
60962
|
-
|
|
60963
|
-
|
|
60964
|
-
|
|
60965
|
-
|
|
60966
|
-
|
|
60967
|
-
|
|
60968
|
-
|
|
60969
|
-
|
|
60970
|
-
|
|
60971
|
-
|
|
60972
|
-
|
|
60973
|
-
|
|
60974
|
-
|
|
60975
|
-
|
|
60976
|
-
|
|
60977
|
-
|
|
60947
|
+
const confirmModal = confirmBeforeClick && confirmOpen ? ReactDOM2.createPortal(
|
|
60948
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
60949
|
+
"div",
|
|
60950
|
+
{
|
|
60951
|
+
className: "fixed inset-0 z-[9999] flex items-center justify-center",
|
|
60952
|
+
onClick: handleConfirmCancel,
|
|
60953
|
+
children: [
|
|
60954
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "absolute inset-0 bg-black/50 backdrop-blur-sm" }),
|
|
60955
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
60956
|
+
"div",
|
|
60957
|
+
{
|
|
60958
|
+
className: "relative z-10 w-full max-w-sm rounded-2xl border border-border bg-card p-6 shadow-2xl",
|
|
60959
|
+
onClick: (e) => e.stopPropagation(),
|
|
60960
|
+
children: [
|
|
60961
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-base font-semibold text-foreground mb-2", children: confirmBeforeClickModalTitle ?? "Are you sure?" }),
|
|
60962
|
+
confirmBeforeClickModalContent && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "text-sm text-muted-foreground mb-5", children: confirmBeforeClickModalContent }),
|
|
60963
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex justify-end gap-2 mt-4", children: confirmBeforeClickFooterAction ?? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
60964
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
60965
|
+
"button",
|
|
60966
|
+
{
|
|
60967
|
+
type: "button",
|
|
60968
|
+
onClick: handleConfirmCancel,
|
|
60969
|
+
className: "inline-flex items-center justify-center rounded-md border border-border bg-background px-4 py-2 text-sm font-medium text-foreground hover:bg-accent transition-colors",
|
|
60970
|
+
children: "Cancel"
|
|
60971
|
+
}
|
|
60972
|
+
),
|
|
60973
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
60974
|
+
"button",
|
|
60975
|
+
{
|
|
60976
|
+
type: "button",
|
|
60977
|
+
onClick: handleConfirmProceed,
|
|
60978
|
+
className: "inline-flex items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary-hover transition-colors",
|
|
60979
|
+
children: "Proceed"
|
|
60980
|
+
}
|
|
60981
|
+
)
|
|
60982
|
+
] }) })
|
|
60983
|
+
]
|
|
60984
|
+
}
|
|
60985
|
+
)
|
|
60986
|
+
]
|
|
60987
|
+
}
|
|
60988
|
+
),
|
|
60989
|
+
document.body
|
|
60978
60990
|
) : null;
|
|
60979
60991
|
if (Element2 === "a") {
|
|
60980
60992
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
@@ -64733,66 +64745,6 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
|
|
|
64733
64745
|
// src/components/ui/bulletin-board.tsx
|
|
64734
64746
|
var React8 = __toESM(require_react(), 1);
|
|
64735
64747
|
var import_react_dom = __toESM(require_react_dom(), 1);
|
|
64736
|
-
|
|
64737
|
-
// src/components/tools/decryptPayload.ts
|
|
64738
|
-
var import_crypto_js = __toESM(require_crypto_js(), 1);
|
|
64739
|
-
function getLaravelSecretKey() {
|
|
64740
|
-
const viteKey = (() => {
|
|
64741
|
-
try {
|
|
64742
|
-
return new Function("return import.meta.env")();
|
|
64743
|
-
} catch {
|
|
64744
|
-
return void 0;
|
|
64745
|
-
}
|
|
64746
|
-
})()?.VITE_LARAVEL_KEY;
|
|
64747
|
-
const legacyKey = globalThis?.process?.env?.REACT_APP_LARAVEL_KEY;
|
|
64748
|
-
const windowKey = globalThis?.__LARAVEL_KEY__;
|
|
64749
|
-
const key = viteKey || legacyKey || windowKey;
|
|
64750
|
-
if (!key) {
|
|
64751
|
-
throw new Error("Missing Laravel decryption key. Set VITE_LARAVEL_KEY in your .env or inject window.__LARAVEL_KEY__ via Blade.");
|
|
64752
|
-
}
|
|
64753
|
-
return key;
|
|
64754
|
-
}
|
|
64755
|
-
function parseLaravelKey(secretKey) {
|
|
64756
|
-
if (secretKey.startsWith("base64:")) {
|
|
64757
|
-
return import_crypto_js.default.enc.Base64.parse(secretKey.slice("base64:".length));
|
|
64758
|
-
}
|
|
64759
|
-
return import_crypto_js.default.enc.Utf8.parse(secretKey);
|
|
64760
|
-
}
|
|
64761
|
-
function parseLaravelEncryptedPayload(payload) {
|
|
64762
|
-
let jsonStr = payload;
|
|
64763
|
-
try {
|
|
64764
|
-
jsonStr = atob(payload);
|
|
64765
|
-
} catch {
|
|
64766
|
-
}
|
|
64767
|
-
return JSON.parse(jsonStr);
|
|
64768
|
-
}
|
|
64769
|
-
function decryptLaravelPayload(payload, secretKey) {
|
|
64770
|
-
const resolvedKey = secretKey ?? getLaravelSecretKey();
|
|
64771
|
-
const parsed = parseLaravelEncryptedPayload(payload);
|
|
64772
|
-
if (parsed.tag) {
|
|
64773
|
-
throw new Error("Unsupported Laravel cipher (AEAD tag present). Expected AES-*-CBC payload.");
|
|
64774
|
-
}
|
|
64775
|
-
const key = parseLaravelKey(resolvedKey);
|
|
64776
|
-
const expectedMac = import_crypto_js.default.HmacSHA256(parsed.iv + parsed.value, key).toString(import_crypto_js.default.enc.Hex);
|
|
64777
|
-
if (expectedMac !== parsed.mac) {
|
|
64778
|
-
throw new Error("Invalid payload MAC (wrong key or tampered payload).");
|
|
64779
|
-
}
|
|
64780
|
-
const iv = import_crypto_js.default.enc.Base64.parse(parsed.iv);
|
|
64781
|
-
const ciphertext = import_crypto_js.default.enc.Base64.parse(parsed.value);
|
|
64782
|
-
const cipherParams = import_crypto_js.default.lib.CipherParams.create({ ciphertext });
|
|
64783
|
-
const decrypted = import_crypto_js.default.AES.decrypt(cipherParams, key, {
|
|
64784
|
-
iv,
|
|
64785
|
-
mode: import_crypto_js.default.mode.CBC,
|
|
64786
|
-
padding: import_crypto_js.default.pad.Pkcs7
|
|
64787
|
-
});
|
|
64788
|
-
const plaintext = decrypted.toString(import_crypto_js.default.enc.Utf8);
|
|
64789
|
-
if (!plaintext) {
|
|
64790
|
-
throw new Error("Decryption produced empty plaintext (wrong key/cipher).");
|
|
64791
|
-
}
|
|
64792
|
-
return JSON.parse(plaintext);
|
|
64793
|
-
}
|
|
64794
|
-
|
|
64795
|
-
// src/components/ui/bulletin-board.tsx
|
|
64796
64748
|
var import_jsx_runtime10 = __toESM(require_jsx_runtime(), 1);
|
|
64797
64749
|
var PRIORITY_CONFIG = {
|
|
64798
64750
|
urgent: { label: "Urgent", icon: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(CircleAlert, { className: "h-3 w-3" }), badge: "error" },
|
|
@@ -64822,82 +64774,13 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
|
|
|
64822
64774
|
}
|
|
64823
64775
|
return null;
|
|
64824
64776
|
}
|
|
64825
|
-
function
|
|
64826
|
-
url: url2,
|
|
64827
|
-
params,
|
|
64828
|
-
encrypt,
|
|
64829
|
-
key,
|
|
64830
|
-
decryptPayloadLog,
|
|
64831
|
-
transform
|
|
64832
|
-
}) {
|
|
64833
|
-
const [items, setItems] = React8.useState([]);
|
|
64834
|
-
const [currentPage, setCurrentPage] = React8.useState(1);
|
|
64835
|
-
const [pagination, setPagination] = React8.useState(null);
|
|
64836
|
-
const [loading, setLoading] = React8.useState(false);
|
|
64837
|
-
const [error, setError] = React8.useState(null);
|
|
64838
|
-
const [tick, setTick] = React8.useState(0);
|
|
64839
|
-
React8.useEffect(() => {
|
|
64840
|
-
let cancelled = false;
|
|
64841
|
-
setLoading(true);
|
|
64842
|
-
setError(null);
|
|
64843
|
-
axios_default.get(url2, { params: { ...params, page: currentPage } }).then(({ data: res }) => {
|
|
64844
|
-
if (cancelled) return;
|
|
64845
|
-
let payload;
|
|
64846
|
-
try {
|
|
64847
|
-
payload = encrypt ? decryptLaravelPayload(res, key) : res;
|
|
64848
|
-
} catch (decryptErr) {
|
|
64849
|
-
console.error("[useServerBulletin] decryption failed:", decryptErr?.message ?? decryptErr);
|
|
64850
|
-
if (!cancelled) setError(decryptErr?.message ?? "Decryption failed");
|
|
64851
|
-
return;
|
|
64852
|
-
}
|
|
64853
|
-
if (encrypt && decryptPayloadLog) console.log("[useServerBulletin] decrypted:", payload);
|
|
64854
|
-
const rows = Array.isArray(payload) ? payload : payload.data ?? [];
|
|
64855
|
-
setItems(transform ? rows.map(transform) : rows);
|
|
64856
|
-
if (!Array.isArray(payload)) {
|
|
64857
|
-
const rawTotal = payload.total;
|
|
64858
|
-
const rawPerPage = payload.per_page;
|
|
64859
|
-
const rawLastPage = payload.last_page;
|
|
64860
|
-
const lastPage = rawLastPage ?? Math.ceil(rawTotal / rawPerPage);
|
|
64861
|
-
const pg = payload.pagination ?? {
|
|
64862
|
-
first_page_url: payload.first_page_url ?? `${url2}?page=1`,
|
|
64863
|
-
last_page_url: payload.last_page_url ?? `${url2}?page=${lastPage}`,
|
|
64864
|
-
last_page: lastPage,
|
|
64865
|
-
next_page_url: payload.next_page_url !== void 0 ? payload.next_page_url : currentPage < lastPage ? `${url2}?page=${currentPage + 1}` : null,
|
|
64866
|
-
prev_page_url: payload.prev_page_url !== void 0 ? payload.prev_page_url : currentPage > 1 ? `${url2}?page=${currentPage - 1}` : null,
|
|
64867
|
-
per_page: rawPerPage,
|
|
64868
|
-
total: rawTotal,
|
|
64869
|
-
links: payload.links ?? []
|
|
64870
|
-
};
|
|
64871
|
-
setPagination(pg);
|
|
64872
|
-
}
|
|
64873
|
-
}).catch((err) => {
|
|
64874
|
-
if (cancelled) return;
|
|
64875
|
-
setError(err?.response?.data?.message ?? err.message ?? "Request failed");
|
|
64876
|
-
}).finally(() => {
|
|
64877
|
-
if (!cancelled) setLoading(false);
|
|
64878
|
-
});
|
|
64879
|
-
return () => {
|
|
64880
|
-
cancelled = true;
|
|
64881
|
-
};
|
|
64882
|
-
}, [url2, currentPage, tick, JSON.stringify(params), encrypt, decryptPayloadLog]);
|
|
64883
|
-
return {
|
|
64884
|
-
items,
|
|
64885
|
-
currentPage,
|
|
64886
|
-
pagination,
|
|
64887
|
-
serverPagination: pagination ? { pagination, currentPage, goToPage: (p) => setCurrentPage(p) } : null,
|
|
64888
|
-
loading,
|
|
64889
|
-
error,
|
|
64890
|
-
goToPage: (p) => setCurrentPage(p),
|
|
64891
|
-
reload: () => setTick((t) => t + 1)
|
|
64892
|
-
};
|
|
64893
|
-
}
|
|
64894
|
-
function BulletinPreview({ item, onClose, onEdit, onDelete, onView, customActions }) {
|
|
64777
|
+
function BulletinPreview({ item, onClose, onEdit, onDelete, onView, customActions, headerAction, footerAction }) {
|
|
64895
64778
|
const priority = item.priority ? PRIORITY_CONFIG[item.priority] : null;
|
|
64896
64779
|
return (0, import_react_dom.createPortal)(
|
|
64897
64780
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
64898
64781
|
"div",
|
|
64899
64782
|
{
|
|
64900
|
-
className: "fixed inset-0 z-50 flex items-center justify-center p-4",
|
|
64783
|
+
className: "fixed inset-0 z-50 flex glass items-center justify-center p-4",
|
|
64901
64784
|
style: { background: "rgba(0,0,0,0.55)" },
|
|
64902
64785
|
onMouseDown: (e) => {
|
|
64903
64786
|
if (e.target === e.currentTarget) onClose();
|
|
@@ -64910,7 +64793,8 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
|
|
|
64910
64793
|
" Pinned"
|
|
64911
64794
|
] }),
|
|
64912
64795
|
priority && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Badge, { variant: priority.badge, size: "sm", icon: priority.icon ?? void 0, children: priority.label }),
|
|
64913
|
-
item.category && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Badge, { variant: "outline", size: "sm", children: item.category })
|
|
64796
|
+
item.category && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Badge, { variant: "outline", size: "sm", children: item.category }),
|
|
64797
|
+
headerAction
|
|
64914
64798
|
] }),
|
|
64915
64799
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-1 shrink-0", children: [
|
|
64916
64800
|
onEdit && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
@@ -65009,6 +64893,7 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
|
|
|
65009
64893
|
] })
|
|
65010
64894
|
] }) }),
|
|
65011
64895
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
64896
|
+
footerAction,
|
|
65012
64897
|
onEdit && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
65013
64898
|
"button",
|
|
65014
64899
|
{
|
|
@@ -65403,6 +65288,9 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
|
|
|
65403
65288
|
deleteBaseUrl,
|
|
65404
65289
|
deleteIdKey = "id",
|
|
65405
65290
|
serverPagination,
|
|
65291
|
+
footerAction,
|
|
65292
|
+
headerPreviewAction,
|
|
65293
|
+
footerPreviewAction,
|
|
65406
65294
|
className
|
|
65407
65295
|
}) {
|
|
65408
65296
|
const [previewItem, setPreviewItem] = React8.useState(null);
|
|
@@ -65487,6 +65375,7 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
|
|
|
65487
65375
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Pin, { className: "h-8 w-8 opacity-20" }),
|
|
65488
65376
|
emptyMessage
|
|
65489
65377
|
] }) : layout === "list" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "flex flex-col gap-3", children: filtered.map((item) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(BulletinCard, { item, variant, layout: "list", onClick: handleCardClick }, item.id)) }) : layout === "masonry" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: cn("gap-4", COLS_CLASS[columns]), style: { display: "grid", gridTemplateRows: "masonry" }, children: filtered.map((item) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(BulletinCard, { item, variant, layout: "masonry", onClick: handleCardClick }, item.id)) }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: cn("grid gap-4", COLS_CLASS[columns]), children: filtered.map((item) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(BulletinCard, { item, variant, layout: "grid", onClick: handleCardClick }, item.id)) }),
|
|
65378
|
+
footerAction && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { children: footerAction }),
|
|
65490
65379
|
serverPagination && (() => {
|
|
65491
65380
|
const { pagination, currentPage: cp, goToPage } = serverPagination;
|
|
65492
65381
|
const totalPages = pagination.last_page ?? Math.ceil(pagination.total / pagination.per_page);
|
|
@@ -65563,7 +65452,9 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
|
|
|
65563
65452
|
setDeleteItem(item);
|
|
65564
65453
|
} : onDelete ? (item) => {
|
|
65565
65454
|
onDelete(item);
|
|
65566
|
-
} : void 0
|
|
65455
|
+
} : void 0,
|
|
65456
|
+
footerAction: footerPreviewAction ? footerPreviewAction(previewItem) : void 0,
|
|
65457
|
+
headerAction: headerPreviewAction
|
|
65567
65458
|
}
|
|
65568
65459
|
),
|
|
65569
65460
|
editItem && editBaseUrl && editFields && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
@@ -67033,6 +66924,64 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
|
|
|
67033
66924
|
var React29 = __toESM(require_react(), 1);
|
|
67034
66925
|
var import_react_dom3 = __toESM(require_react_dom(), 1);
|
|
67035
66926
|
|
|
66927
|
+
// src/components/tools/decryptPayload.ts
|
|
66928
|
+
var import_crypto_js = __toESM(require_crypto_js(), 1);
|
|
66929
|
+
function getLaravelSecretKey() {
|
|
66930
|
+
const viteKey = (() => {
|
|
66931
|
+
try {
|
|
66932
|
+
return new Function("return import.meta.env")();
|
|
66933
|
+
} catch {
|
|
66934
|
+
return void 0;
|
|
66935
|
+
}
|
|
66936
|
+
})()?.VITE_LARAVEL_KEY;
|
|
66937
|
+
const legacyKey = globalThis?.process?.env?.REACT_APP_LARAVEL_KEY;
|
|
66938
|
+
const windowKey = globalThis?.__LARAVEL_KEY__;
|
|
66939
|
+
const key = viteKey || legacyKey || windowKey;
|
|
66940
|
+
if (!key) {
|
|
66941
|
+
throw new Error("Missing Laravel decryption key. Set VITE_LARAVEL_KEY in your .env or inject window.__LARAVEL_KEY__ via Blade.");
|
|
66942
|
+
}
|
|
66943
|
+
return key;
|
|
66944
|
+
}
|
|
66945
|
+
function parseLaravelKey(secretKey) {
|
|
66946
|
+
if (secretKey.startsWith("base64:")) {
|
|
66947
|
+
return import_crypto_js.default.enc.Base64.parse(secretKey.slice("base64:".length));
|
|
66948
|
+
}
|
|
66949
|
+
return import_crypto_js.default.enc.Utf8.parse(secretKey);
|
|
66950
|
+
}
|
|
66951
|
+
function parseLaravelEncryptedPayload(payload) {
|
|
66952
|
+
let jsonStr = payload;
|
|
66953
|
+
try {
|
|
66954
|
+
jsonStr = atob(payload);
|
|
66955
|
+
} catch {
|
|
66956
|
+
}
|
|
66957
|
+
return JSON.parse(jsonStr);
|
|
66958
|
+
}
|
|
66959
|
+
function decryptLaravelPayload(payload, secretKey) {
|
|
66960
|
+
const resolvedKey = secretKey ?? getLaravelSecretKey();
|
|
66961
|
+
const parsed = parseLaravelEncryptedPayload(payload);
|
|
66962
|
+
if (parsed.tag) {
|
|
66963
|
+
throw new Error("Unsupported Laravel cipher (AEAD tag present). Expected AES-*-CBC payload.");
|
|
66964
|
+
}
|
|
66965
|
+
const key = parseLaravelKey(resolvedKey);
|
|
66966
|
+
const expectedMac = import_crypto_js.default.HmacSHA256(parsed.iv + parsed.value, key).toString(import_crypto_js.default.enc.Hex);
|
|
66967
|
+
if (expectedMac !== parsed.mac) {
|
|
66968
|
+
throw new Error("Invalid payload MAC (wrong key or tampered payload).");
|
|
66969
|
+
}
|
|
66970
|
+
const iv = import_crypto_js.default.enc.Base64.parse(parsed.iv);
|
|
66971
|
+
const ciphertext = import_crypto_js.default.enc.Base64.parse(parsed.value);
|
|
66972
|
+
const cipherParams = import_crypto_js.default.lib.CipherParams.create({ ciphertext });
|
|
66973
|
+
const decrypted = import_crypto_js.default.AES.decrypt(cipherParams, key, {
|
|
66974
|
+
iv,
|
|
66975
|
+
mode: import_crypto_js.default.mode.CBC,
|
|
66976
|
+
padding: import_crypto_js.default.pad.Pkcs7
|
|
66977
|
+
});
|
|
66978
|
+
const plaintext = decrypted.toString(import_crypto_js.default.enc.Utf8);
|
|
66979
|
+
if (!plaintext) {
|
|
66980
|
+
throw new Error("Decryption produced empty plaintext (wrong key/cipher).");
|
|
66981
|
+
}
|
|
66982
|
+
return JSON.parse(plaintext);
|
|
66983
|
+
}
|
|
66984
|
+
|
|
67036
66985
|
// src/components/ui/pagination.tsx
|
|
67037
66986
|
var import_jsx_runtime19 = __toESM(require_jsx_runtime(), 1);
|
|
67038
66987
|
function range(start, end) {
|
|
@@ -69964,7 +69913,7 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
|
|
|
69964
69913
|
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
69965
69914
|
"div",
|
|
69966
69915
|
{
|
|
69967
|
-
className: "fixed inset-0 z-50 flex items-center justify-center p-4",
|
|
69916
|
+
className: "fixed inset-0 z-50 flex glass items-center justify-center p-4",
|
|
69968
69917
|
style: { background: "rgba(0,0,0,0.5)" },
|
|
69969
69918
|
onMouseDown: (e) => {
|
|
69970
69919
|
if (e.target === e.currentTarget) onClose();
|
|
@@ -74739,7 +74688,7 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
|
|
|
74739
74688
|
|
|
74740
74689
|
// src/components/ui/tooltip.tsx
|
|
74741
74690
|
var React40 = __toESM(require_react(), 1);
|
|
74742
|
-
var
|
|
74691
|
+
var ReactDOM3 = __toESM(require_react_dom(), 1);
|
|
74743
74692
|
var import_jsx_runtime44 = __toESM(require_jsx_runtime(), 1);
|
|
74744
74693
|
function Tooltip({
|
|
74745
74694
|
content,
|
|
@@ -74794,7 +74743,7 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
|
|
|
74794
74743
|
onBlur: () => setVisible(false),
|
|
74795
74744
|
children: [
|
|
74796
74745
|
children,
|
|
74797
|
-
visible &&
|
|
74746
|
+
visible && ReactDOM3.createPortal(
|
|
74798
74747
|
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
74799
74748
|
"div",
|
|
74800
74749
|
{
|
|
@@ -77626,6 +77575,12 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
|
|
|
77626
77575
|
};
|
|
77627
77576
|
return { store, getStore };
|
|
77628
77577
|
}
|
|
77578
|
+
|
|
77579
|
+
// src/core/decryption/decode.ts
|
|
77580
|
+
function decryptResponse(response, key) {
|
|
77581
|
+
const payload = typeof response === "string" ? response : response.data;
|
|
77582
|
+
return decryptLaravelPayload(payload, key);
|
|
77583
|
+
}
|
|
77629
77584
|
return __toCommonJS(index_exports);
|
|
77630
77585
|
})();
|
|
77631
77586
|
/*! Bundled license information:
|