@juv/codego-react-ui 3.1.8 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1914,6 +1914,153 @@ function BulletinDeleteConfirm({
1914
1914
  document.body
1915
1915
  );
1916
1916
  }
1917
+ function BulletinEditModal({
1918
+ item,
1919
+ baseUrl,
1920
+ idKey,
1921
+ method,
1922
+ fields,
1923
+ onClose,
1924
+ onSuccess
1925
+ }) {
1926
+ const [loading, setLoading] = React8.useState(false);
1927
+ const [error, setError] = React8.useState(null);
1928
+ const [formData, setFormData] = React8.useState(() => {
1929
+ const initial = {};
1930
+ fields.forEach((f) => {
1931
+ initial[f.key] = item[f.key] ?? "";
1932
+ });
1933
+ return initial;
1934
+ });
1935
+ const id = item[idKey ?? "id"];
1936
+ const handleChange = (key, value) => {
1937
+ setFormData((prev) => ({ ...prev, [key]: value }));
1938
+ };
1939
+ const handleSubmit = async (e) => {
1940
+ e.preventDefault();
1941
+ setLoading(true);
1942
+ setError(null);
1943
+ try {
1944
+ const response = await (0, import_axios2.default)({
1945
+ method: method ?? "PUT",
1946
+ url: `${baseUrl}/${id}`,
1947
+ data: formData
1948
+ });
1949
+ onSuccess?.(response.data);
1950
+ onClose();
1951
+ } catch (err) {
1952
+ setError(err?.response?.data?.message ?? err.message ?? "Update failed");
1953
+ } finally {
1954
+ setLoading(false);
1955
+ }
1956
+ };
1957
+ return (0, import_react_dom.createPortal)(
1958
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1959
+ "div",
1960
+ {
1961
+ className: "fixed inset-0 z-50 flex items-center justify-center p-4",
1962
+ style: { background: "rgba(0,0,0,0.55)" },
1963
+ onMouseDown: (e) => {
1964
+ if (e.target === e.currentTarget) onClose();
1965
+ },
1966
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "w-full max-w-md rounded-2xl border border-border bg-card shadow-2xl p-6 space-y-4 max-h-[90vh] overflow-y-auto", children: [
1967
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center justify-between", children: [
1968
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h2", { className: "text-base font-semibold", children: "Edit Post" }),
1969
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1970
+ "button",
1971
+ {
1972
+ type: "button",
1973
+ onClick: onClose,
1974
+ className: "flex h-7 w-7 items-center justify-center rounded-lg text-muted-foreground hover:bg-accent hover:text-foreground transition-colors",
1975
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react4.X, { className: "h-4 w-4" })
1976
+ }
1977
+ )
1978
+ ] }),
1979
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
1980
+ fields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "space-y-1.5", children: [
1981
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { className: "text-xs font-medium text-muted-foreground", children: field.label }),
1982
+ field.type === "textarea" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1983
+ "textarea",
1984
+ {
1985
+ value: formData[field.key] ?? "",
1986
+ onChange: (e) => handleChange(field.key, e.target.value),
1987
+ placeholder: field.placeholder,
1988
+ className: "w-full px-3 py-2 text-sm rounded-lg border border-border bg-background outline-none focus:ring-1 focus:ring-ring resize-none",
1989
+ rows: 4
1990
+ }
1991
+ ) : field.type === "select" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1992
+ "select",
1993
+ {
1994
+ value: formData[field.key] ?? "",
1995
+ onChange: (e) => handleChange(field.key, e.target.value),
1996
+ className: "w-full px-3 py-2 text-sm rounded-lg border border-border bg-background outline-none focus:ring-1 focus:ring-ring",
1997
+ children: [
1998
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: "", children: "Select..." }),
1999
+ field.options?.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: opt, children: opt }, opt))
2000
+ ]
2001
+ }
2002
+ ) : field.type === "checkbox" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-2", children: [
2003
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2004
+ "input",
2005
+ {
2006
+ type: "checkbox",
2007
+ checked: formData[field.key] ?? false,
2008
+ onChange: (e) => handleChange(field.key, e.target.checked),
2009
+ className: "h-4 w-4 rounded border-border"
2010
+ }
2011
+ ),
2012
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-sm text-muted-foreground", children: field.placeholder })
2013
+ ] }) : field.type === "date" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2014
+ "input",
2015
+ {
2016
+ type: "date",
2017
+ value: formData[field.key] ?? "",
2018
+ onChange: (e) => handleChange(field.key, e.target.value),
2019
+ className: "w-full px-3 py-2 text-sm rounded-lg border border-border bg-background outline-none focus:ring-1 focus:ring-ring"
2020
+ }
2021
+ ) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2022
+ "input",
2023
+ {
2024
+ type: "text",
2025
+ value: formData[field.key] ?? "",
2026
+ onChange: (e) => handleChange(field.key, e.target.value),
2027
+ placeholder: field.placeholder,
2028
+ className: "w-full px-3 py-2 text-sm rounded-lg border border-border bg-background outline-none focus:ring-1 focus:ring-ring"
2029
+ }
2030
+ )
2031
+ ] }, field.key)),
2032
+ error && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "text-xs text-danger", children: error }),
2033
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex justify-end gap-2 pt-2", children: [
2034
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2035
+ "button",
2036
+ {
2037
+ type: "button",
2038
+ onClick: onClose,
2039
+ disabled: loading,
2040
+ className: "px-4 py-1.5 text-sm rounded-xl border border-border hover:bg-accent transition-colors",
2041
+ children: "Cancel"
2042
+ }
2043
+ ),
2044
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2045
+ "button",
2046
+ {
2047
+ type: "submit",
2048
+ disabled: loading,
2049
+ className: "px-4 py-1.5 text-sm rounded-xl bg-primary text-primary-foreground hover:bg-primary/90 transition-colors flex items-center gap-1.5",
2050
+ children: [
2051
+ loading && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react4.Loader2, { className: "h-3.5 w-3.5 animate-spin" }),
2052
+ loading ? "Saving\u2026" : "Save"
2053
+ ]
2054
+ }
2055
+ )
2056
+ ] })
2057
+ ] })
2058
+ ] })
2059
+ }
2060
+ ),
2061
+ document.body
2062
+ );
2063
+ }
1917
2064
  function ActionMenu({ item, actions }) {
1918
2065
  const [open, setOpen] = React8.useState(false);
1919
2066
  const ref = React8.useRef(null);
@@ -2063,12 +2210,17 @@ function BulletinBoard({
2063
2210
  onEdit,
2064
2211
  onDelete,
2065
2212
  preview = false,
2213
+ editBaseUrl,
2214
+ editMethod,
2215
+ editIdKey,
2216
+ editFields,
2066
2217
  deleteBaseUrl,
2067
2218
  deleteIdKey = "id",
2068
2219
  serverPagination,
2069
2220
  className
2070
2221
  }) {
2071
2222
  const [previewItem, setPreviewItem] = React8.useState(null);
2223
+ const [editItem, setEditItem] = React8.useState(null);
2072
2224
  const [deleteItem, setDeleteItem] = React8.useState(null);
2073
2225
  const [search, setSearch] = React8.useState("");
2074
2226
  const [category, setCategory] = React8.useState(null);
@@ -2214,7 +2366,10 @@ function BulletinBoard({
2214
2366
  onView: onView ? (item) => {
2215
2367
  onView(item);
2216
2368
  } : void 0,
2217
- onEdit: onEdit ? (item) => {
2369
+ onEdit: editBaseUrl && editFields ? (item) => {
2370
+ setPreviewItem(null);
2371
+ setEditItem(item);
2372
+ } : onEdit ? (item) => {
2218
2373
  onEdit(item);
2219
2374
  } : void 0,
2220
2375
  onDelete: deleteBaseUrl ? (item) => {
@@ -2225,6 +2380,20 @@ function BulletinBoard({
2225
2380
  } : void 0
2226
2381
  }
2227
2382
  ),
2383
+ editItem && editBaseUrl && editFields && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2384
+ BulletinEditModal,
2385
+ {
2386
+ item: editItem,
2387
+ baseUrl: editBaseUrl,
2388
+ idKey: editIdKey,
2389
+ method: editMethod,
2390
+ fields: editFields,
2391
+ onClose: () => setEditItem(null),
2392
+ onSuccess: (updated) => {
2393
+ onEdit?.(updated);
2394
+ }
2395
+ }
2396
+ ),
2228
2397
  deleteItem && deleteBaseUrl && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2229
2398
  BulletinDeleteConfirm,
2230
2399
  {
package/dist/index.d.cts CHANGED
@@ -468,6 +468,13 @@ interface BulletinPreviewProps {
468
468
  customActions?: BulletinAction[];
469
469
  }
470
470
  declare function BulletinPreview({ item, onClose, onEdit, onDelete, onView, customActions }: BulletinPreviewProps): React.ReactPortal;
471
+ interface BulletinEditField {
472
+ key: keyof BulletinItem | string;
473
+ label: string;
474
+ type: "text" | "textarea" | "select" | "checkbox" | "date";
475
+ options?: string[];
476
+ placeholder?: string;
477
+ }
471
478
  interface BulletinBoardProps {
472
479
  /** Array of bulletin post items. */
473
480
  items: BulletinItem[];
@@ -509,6 +516,8 @@ interface BulletinBoardProps {
509
516
  editMethod?: "PUT" | "PATCH" | "POST";
510
517
  /** Item key used as the id segment in the edit URL. */
511
518
  editIdKey?: string;
519
+ /** Edit form fields configuration. */
520
+ editFields?: BulletinEditField[];
512
521
  /** Base URL for built-in DELETE {baseUrl}/{id}/delete request. */
513
522
  deleteBaseUrl?: string;
514
523
  /** Item key used as the id segment in the delete URL. */
@@ -520,7 +529,7 @@ interface BulletinBoardProps {
520
529
  /** Additional CSS classes on the outer wrapper. */
521
530
  className?: string;
522
531
  }
523
- declare function BulletinBoard({ items, layout, columns, variant, searchable, filterable, categories: categoriesProp, title, headerAction, showHeader, emptyMessage, loading, loadingCount, onItemClick, onView, onEdit, onDelete, preview, deleteBaseUrl, deleteIdKey, serverPagination, className, }: BulletinBoardProps): react_jsx_runtime.JSX.Element;
532
+ 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;
524
533
 
525
534
  interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
526
535
  variant?: "primary" | "secondary" | "outline" | "ghost" | "link" | "danger" | "success" | "destructive";
@@ -2018,4 +2027,4 @@ interface WizardProps {
2018
2027
  }
2019
2028
  declare function Wizard({ steps, step: controlledStep, defaultStep, onStepChange, onFinish, onClose, layout, variant, size, isOpen, showClose, unchange, title, description, hideHeader, footer, renderActions, backLabel, nextLabel, finishLabel, cancelLabel, showCancel, showBackOnFirst, loading, clickableSteps, className, contentClassName, }: WizardProps): react_jsx_runtime.JSX.Element;
2020
2029
 
2021
- 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 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, 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, 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, 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 UseServerBulletinOptions, type UseServerBulletinReturn, type UseServerDataGridOptions, type UseServerDataGridReturn, type UseServerTableOptions, type UseServerTableReturn, Widget, type WidgetProps, Wizard, type WizardActionProps, type WizardLayout, type WizardProps, type WizardSize, type WizardStep, type WizardVariant, useServerBulletin, useServerDataGrid, useServerTable, useTheme, useToast, useToc };
2030
+ 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, 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, 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, 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 UseServerBulletinOptions, type UseServerBulletinReturn, type UseServerDataGridOptions, type UseServerDataGridReturn, type UseServerTableOptions, type UseServerTableReturn, Widget, type WidgetProps, Wizard, type WizardActionProps, type WizardLayout, type WizardProps, type WizardSize, type WizardStep, type WizardVariant, useServerBulletin, useServerDataGrid, useServerTable, useTheme, useToast, useToc };
package/dist/index.d.ts CHANGED
@@ -468,6 +468,13 @@ interface BulletinPreviewProps {
468
468
  customActions?: BulletinAction[];
469
469
  }
470
470
  declare function BulletinPreview({ item, onClose, onEdit, onDelete, onView, customActions }: BulletinPreviewProps): React.ReactPortal;
471
+ interface BulletinEditField {
472
+ key: keyof BulletinItem | string;
473
+ label: string;
474
+ type: "text" | "textarea" | "select" | "checkbox" | "date";
475
+ options?: string[];
476
+ placeholder?: string;
477
+ }
471
478
  interface BulletinBoardProps {
472
479
  /** Array of bulletin post items. */
473
480
  items: BulletinItem[];
@@ -509,6 +516,8 @@ interface BulletinBoardProps {
509
516
  editMethod?: "PUT" | "PATCH" | "POST";
510
517
  /** Item key used as the id segment in the edit URL. */
511
518
  editIdKey?: string;
519
+ /** Edit form fields configuration. */
520
+ editFields?: BulletinEditField[];
512
521
  /** Base URL for built-in DELETE {baseUrl}/{id}/delete request. */
513
522
  deleteBaseUrl?: string;
514
523
  /** Item key used as the id segment in the delete URL. */
@@ -520,7 +529,7 @@ interface BulletinBoardProps {
520
529
  /** Additional CSS classes on the outer wrapper. */
521
530
  className?: string;
522
531
  }
523
- declare function BulletinBoard({ items, layout, columns, variant, searchable, filterable, categories: categoriesProp, title, headerAction, showHeader, emptyMessage, loading, loadingCount, onItemClick, onView, onEdit, onDelete, preview, deleteBaseUrl, deleteIdKey, serverPagination, className, }: BulletinBoardProps): react_jsx_runtime.JSX.Element;
532
+ 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;
524
533
 
525
534
  interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
526
535
  variant?: "primary" | "secondary" | "outline" | "ghost" | "link" | "danger" | "success" | "destructive";
@@ -2018,4 +2027,4 @@ interface WizardProps {
2018
2027
  }
2019
2028
  declare function Wizard({ steps, step: controlledStep, defaultStep, onStepChange, onFinish, onClose, layout, variant, size, isOpen, showClose, unchange, title, description, hideHeader, footer, renderActions, backLabel, nextLabel, finishLabel, cancelLabel, showCancel, showBackOnFirst, loading, clickableSteps, className, contentClassName, }: WizardProps): react_jsx_runtime.JSX.Element;
2020
2029
 
2021
- 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 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, 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, 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, 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 UseServerBulletinOptions, type UseServerBulletinReturn, type UseServerDataGridOptions, type UseServerDataGridReturn, type UseServerTableOptions, type UseServerTableReturn, Widget, type WidgetProps, Wizard, type WizardActionProps, type WizardLayout, type WizardProps, type WizardSize, type WizardStep, type WizardVariant, useServerBulletin, useServerDataGrid, useServerTable, useTheme, useToast, useToc };
2030
+ 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, 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, 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, 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 UseServerBulletinOptions, type UseServerBulletinReturn, type UseServerDataGridOptions, type UseServerDataGridReturn, type UseServerTableOptions, type UseServerTableReturn, Widget, type WidgetProps, Wizard, type WizardActionProps, type WizardLayout, type WizardProps, type WizardSize, type WizardStep, type WizardVariant, useServerBulletin, useServerDataGrid, useServerTable, useTheme, useToast, useToc };
@@ -65076,6 +65076,153 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
65076
65076
  document.body
65077
65077
  );
65078
65078
  }
65079
+ function BulletinEditModal({
65080
+ item,
65081
+ baseUrl,
65082
+ idKey,
65083
+ method,
65084
+ fields,
65085
+ onClose,
65086
+ onSuccess
65087
+ }) {
65088
+ const [loading, setLoading] = React8.useState(false);
65089
+ const [error, setError] = React8.useState(null);
65090
+ const [formData, setFormData] = React8.useState(() => {
65091
+ const initial = {};
65092
+ fields.forEach((f) => {
65093
+ initial[f.key] = item[f.key] ?? "";
65094
+ });
65095
+ return initial;
65096
+ });
65097
+ const id = item[idKey ?? "id"];
65098
+ const handleChange = (key, value) => {
65099
+ setFormData((prev) => ({ ...prev, [key]: value }));
65100
+ };
65101
+ const handleSubmit = async (e) => {
65102
+ e.preventDefault();
65103
+ setLoading(true);
65104
+ setError(null);
65105
+ try {
65106
+ const response = await axios_default({
65107
+ method: method ?? "PUT",
65108
+ url: `${baseUrl}/${id}`,
65109
+ data: formData
65110
+ });
65111
+ onSuccess?.(response.data);
65112
+ onClose();
65113
+ } catch (err) {
65114
+ setError(err?.response?.data?.message ?? err.message ?? "Update failed");
65115
+ } finally {
65116
+ setLoading(false);
65117
+ }
65118
+ };
65119
+ return (0, import_react_dom.createPortal)(
65120
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
65121
+ "div",
65122
+ {
65123
+ className: "fixed inset-0 z-50 flex items-center justify-center p-4",
65124
+ style: { background: "rgba(0,0,0,0.55)" },
65125
+ onMouseDown: (e) => {
65126
+ if (e.target === e.currentTarget) onClose();
65127
+ },
65128
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "w-full max-w-md rounded-2xl border border-border bg-card shadow-2xl p-6 space-y-4 max-h-[90vh] overflow-y-auto", children: [
65129
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center justify-between", children: [
65130
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h2", { className: "text-base font-semibold", children: "Edit Post" }),
65131
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
65132
+ "button",
65133
+ {
65134
+ type: "button",
65135
+ onClick: onClose,
65136
+ className: "flex h-7 w-7 items-center justify-center rounded-lg text-muted-foreground hover:bg-accent hover:text-foreground transition-colors",
65137
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(X, { className: "h-4 w-4" })
65138
+ }
65139
+ )
65140
+ ] }),
65141
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
65142
+ fields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "space-y-1.5", children: [
65143
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { className: "text-xs font-medium text-muted-foreground", children: field.label }),
65144
+ field.type === "textarea" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
65145
+ "textarea",
65146
+ {
65147
+ value: formData[field.key] ?? "",
65148
+ onChange: (e) => handleChange(field.key, e.target.value),
65149
+ placeholder: field.placeholder,
65150
+ className: "w-full px-3 py-2 text-sm rounded-lg border border-border bg-background outline-none focus:ring-1 focus:ring-ring resize-none",
65151
+ rows: 4
65152
+ }
65153
+ ) : field.type === "select" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
65154
+ "select",
65155
+ {
65156
+ value: formData[field.key] ?? "",
65157
+ onChange: (e) => handleChange(field.key, e.target.value),
65158
+ className: "w-full px-3 py-2 text-sm rounded-lg border border-border bg-background outline-none focus:ring-1 focus:ring-ring",
65159
+ children: [
65160
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: "", children: "Select..." }),
65161
+ field.options?.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: opt, children: opt }, opt))
65162
+ ]
65163
+ }
65164
+ ) : field.type === "checkbox" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-2", children: [
65165
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
65166
+ "input",
65167
+ {
65168
+ type: "checkbox",
65169
+ checked: formData[field.key] ?? false,
65170
+ onChange: (e) => handleChange(field.key, e.target.checked),
65171
+ className: "h-4 w-4 rounded border-border"
65172
+ }
65173
+ ),
65174
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-sm text-muted-foreground", children: field.placeholder })
65175
+ ] }) : field.type === "date" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
65176
+ "input",
65177
+ {
65178
+ type: "date",
65179
+ value: formData[field.key] ?? "",
65180
+ onChange: (e) => handleChange(field.key, e.target.value),
65181
+ className: "w-full px-3 py-2 text-sm rounded-lg border border-border bg-background outline-none focus:ring-1 focus:ring-ring"
65182
+ }
65183
+ ) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
65184
+ "input",
65185
+ {
65186
+ type: "text",
65187
+ value: formData[field.key] ?? "",
65188
+ onChange: (e) => handleChange(field.key, e.target.value),
65189
+ placeholder: field.placeholder,
65190
+ className: "w-full px-3 py-2 text-sm rounded-lg border border-border bg-background outline-none focus:ring-1 focus:ring-ring"
65191
+ }
65192
+ )
65193
+ ] }, field.key)),
65194
+ error && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "text-xs text-danger", children: error }),
65195
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex justify-end gap-2 pt-2", children: [
65196
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
65197
+ "button",
65198
+ {
65199
+ type: "button",
65200
+ onClick: onClose,
65201
+ disabled: loading,
65202
+ className: "px-4 py-1.5 text-sm rounded-xl border border-border hover:bg-accent transition-colors",
65203
+ children: "Cancel"
65204
+ }
65205
+ ),
65206
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
65207
+ "button",
65208
+ {
65209
+ type: "submit",
65210
+ disabled: loading,
65211
+ className: "px-4 py-1.5 text-sm rounded-xl bg-primary text-primary-foreground hover:bg-primary/90 transition-colors flex items-center gap-1.5",
65212
+ children: [
65213
+ loading && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(LoaderCircle, { className: "h-3.5 w-3.5 animate-spin" }),
65214
+ loading ? "Saving\u2026" : "Save"
65215
+ ]
65216
+ }
65217
+ )
65218
+ ] })
65219
+ ] })
65220
+ ] })
65221
+ }
65222
+ ),
65223
+ document.body
65224
+ );
65225
+ }
65079
65226
  function ActionMenu({ item, actions }) {
65080
65227
  const [open, setOpen] = React8.useState(false);
65081
65228
  const ref = React8.useRef(null);
@@ -65225,12 +65372,17 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
65225
65372
  onEdit,
65226
65373
  onDelete,
65227
65374
  preview = false,
65375
+ editBaseUrl,
65376
+ editMethod,
65377
+ editIdKey,
65378
+ editFields,
65228
65379
  deleteBaseUrl,
65229
65380
  deleteIdKey = "id",
65230
65381
  serverPagination,
65231
65382
  className
65232
65383
  }) {
65233
65384
  const [previewItem, setPreviewItem] = React8.useState(null);
65385
+ const [editItem, setEditItem] = React8.useState(null);
65234
65386
  const [deleteItem, setDeleteItem] = React8.useState(null);
65235
65387
  const [search, setSearch] = React8.useState("");
65236
65388
  const [category, setCategory] = React8.useState(null);
@@ -65376,7 +65528,10 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
65376
65528
  onView: onView ? (item) => {
65377
65529
  onView(item);
65378
65530
  } : void 0,
65379
- onEdit: onEdit ? (item) => {
65531
+ onEdit: editBaseUrl && editFields ? (item) => {
65532
+ setPreviewItem(null);
65533
+ setEditItem(item);
65534
+ } : onEdit ? (item) => {
65380
65535
  onEdit(item);
65381
65536
  } : void 0,
65382
65537
  onDelete: deleteBaseUrl ? (item) => {
@@ -65387,6 +65542,20 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
65387
65542
  } : void 0
65388
65543
  }
65389
65544
  ),
65545
+ editItem && editBaseUrl && editFields && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
65546
+ BulletinEditModal,
65547
+ {
65548
+ item: editItem,
65549
+ baseUrl: editBaseUrl,
65550
+ idKey: editIdKey,
65551
+ method: editMethod,
65552
+ fields: editFields,
65553
+ onClose: () => setEditItem(null),
65554
+ onSuccess: (updated) => {
65555
+ onEdit?.(updated);
65556
+ }
65557
+ }
65558
+ ),
65390
65559
  deleteItem && deleteBaseUrl && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
65391
65560
  BulletinDeleteConfirm,
65392
65561
  {
package/dist/index.js CHANGED
@@ -1796,6 +1796,153 @@ function BulletinDeleteConfirm({
1796
1796
  document.body
1797
1797
  );
1798
1798
  }
1799
+ function BulletinEditModal({
1800
+ item,
1801
+ baseUrl,
1802
+ idKey,
1803
+ method,
1804
+ fields,
1805
+ onClose,
1806
+ onSuccess
1807
+ }) {
1808
+ const [loading, setLoading] = React8.useState(false);
1809
+ const [error, setError] = React8.useState(null);
1810
+ const [formData, setFormData] = React8.useState(() => {
1811
+ const initial = {};
1812
+ fields.forEach((f) => {
1813
+ initial[f.key] = item[f.key] ?? "";
1814
+ });
1815
+ return initial;
1816
+ });
1817
+ const id = item[idKey ?? "id"];
1818
+ const handleChange = (key, value) => {
1819
+ setFormData((prev) => ({ ...prev, [key]: value }));
1820
+ };
1821
+ const handleSubmit = async (e) => {
1822
+ e.preventDefault();
1823
+ setLoading(true);
1824
+ setError(null);
1825
+ try {
1826
+ const response = await axios2({
1827
+ method: method ?? "PUT",
1828
+ url: `${baseUrl}/${id}`,
1829
+ data: formData
1830
+ });
1831
+ onSuccess?.(response.data);
1832
+ onClose();
1833
+ } catch (err) {
1834
+ setError(err?.response?.data?.message ?? err.message ?? "Update failed");
1835
+ } finally {
1836
+ setLoading(false);
1837
+ }
1838
+ };
1839
+ return createPortal2(
1840
+ /* @__PURE__ */ jsx10(
1841
+ "div",
1842
+ {
1843
+ className: "fixed inset-0 z-50 flex items-center justify-center p-4",
1844
+ style: { background: "rgba(0,0,0,0.55)" },
1845
+ onMouseDown: (e) => {
1846
+ if (e.target === e.currentTarget) onClose();
1847
+ },
1848
+ children: /* @__PURE__ */ jsxs9("div", { className: "w-full max-w-md rounded-2xl border border-border bg-card shadow-2xl p-6 space-y-4 max-h-[90vh] overflow-y-auto", children: [
1849
+ /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between", children: [
1850
+ /* @__PURE__ */ jsx10("h2", { className: "text-base font-semibold", children: "Edit Post" }),
1851
+ /* @__PURE__ */ jsx10(
1852
+ "button",
1853
+ {
1854
+ type: "button",
1855
+ onClick: onClose,
1856
+ className: "flex h-7 w-7 items-center justify-center rounded-lg text-muted-foreground hover:bg-accent hover:text-foreground transition-colors",
1857
+ children: /* @__PURE__ */ jsx10(X, { className: "h-4 w-4" })
1858
+ }
1859
+ )
1860
+ ] }),
1861
+ /* @__PURE__ */ jsxs9("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
1862
+ fields.map((field) => /* @__PURE__ */ jsxs9("div", { className: "space-y-1.5", children: [
1863
+ /* @__PURE__ */ jsx10("label", { className: "text-xs font-medium text-muted-foreground", children: field.label }),
1864
+ field.type === "textarea" ? /* @__PURE__ */ jsx10(
1865
+ "textarea",
1866
+ {
1867
+ value: formData[field.key] ?? "",
1868
+ onChange: (e) => handleChange(field.key, e.target.value),
1869
+ placeholder: field.placeholder,
1870
+ className: "w-full px-3 py-2 text-sm rounded-lg border border-border bg-background outline-none focus:ring-1 focus:ring-ring resize-none",
1871
+ rows: 4
1872
+ }
1873
+ ) : field.type === "select" ? /* @__PURE__ */ jsxs9(
1874
+ "select",
1875
+ {
1876
+ value: formData[field.key] ?? "",
1877
+ onChange: (e) => handleChange(field.key, e.target.value),
1878
+ className: "w-full px-3 py-2 text-sm rounded-lg border border-border bg-background outline-none focus:ring-1 focus:ring-ring",
1879
+ children: [
1880
+ /* @__PURE__ */ jsx10("option", { value: "", children: "Select..." }),
1881
+ field.options?.map((opt) => /* @__PURE__ */ jsx10("option", { value: opt, children: opt }, opt))
1882
+ ]
1883
+ }
1884
+ ) : field.type === "checkbox" ? /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2", children: [
1885
+ /* @__PURE__ */ jsx10(
1886
+ "input",
1887
+ {
1888
+ type: "checkbox",
1889
+ checked: formData[field.key] ?? false,
1890
+ onChange: (e) => handleChange(field.key, e.target.checked),
1891
+ className: "h-4 w-4 rounded border-border"
1892
+ }
1893
+ ),
1894
+ /* @__PURE__ */ jsx10("span", { className: "text-sm text-muted-foreground", children: field.placeholder })
1895
+ ] }) : field.type === "date" ? /* @__PURE__ */ jsx10(
1896
+ "input",
1897
+ {
1898
+ type: "date",
1899
+ value: formData[field.key] ?? "",
1900
+ onChange: (e) => handleChange(field.key, e.target.value),
1901
+ className: "w-full px-3 py-2 text-sm rounded-lg border border-border bg-background outline-none focus:ring-1 focus:ring-ring"
1902
+ }
1903
+ ) : /* @__PURE__ */ jsx10(
1904
+ "input",
1905
+ {
1906
+ type: "text",
1907
+ value: formData[field.key] ?? "",
1908
+ onChange: (e) => handleChange(field.key, e.target.value),
1909
+ placeholder: field.placeholder,
1910
+ className: "w-full px-3 py-2 text-sm rounded-lg border border-border bg-background outline-none focus:ring-1 focus:ring-ring"
1911
+ }
1912
+ )
1913
+ ] }, field.key)),
1914
+ error && /* @__PURE__ */ jsx10("p", { className: "text-xs text-danger", children: error }),
1915
+ /* @__PURE__ */ jsxs9("div", { className: "flex justify-end gap-2 pt-2", children: [
1916
+ /* @__PURE__ */ jsx10(
1917
+ "button",
1918
+ {
1919
+ type: "button",
1920
+ onClick: onClose,
1921
+ disabled: loading,
1922
+ className: "px-4 py-1.5 text-sm rounded-xl border border-border hover:bg-accent transition-colors",
1923
+ children: "Cancel"
1924
+ }
1925
+ ),
1926
+ /* @__PURE__ */ jsxs9(
1927
+ "button",
1928
+ {
1929
+ type: "submit",
1930
+ disabled: loading,
1931
+ className: "px-4 py-1.5 text-sm rounded-xl bg-primary text-primary-foreground hover:bg-primary/90 transition-colors flex items-center gap-1.5",
1932
+ children: [
1933
+ loading && /* @__PURE__ */ jsx10(Loader2, { className: "h-3.5 w-3.5 animate-spin" }),
1934
+ loading ? "Saving\u2026" : "Save"
1935
+ ]
1936
+ }
1937
+ )
1938
+ ] })
1939
+ ] })
1940
+ ] })
1941
+ }
1942
+ ),
1943
+ document.body
1944
+ );
1945
+ }
1799
1946
  function ActionMenu({ item, actions }) {
1800
1947
  const [open, setOpen] = React8.useState(false);
1801
1948
  const ref = React8.useRef(null);
@@ -1945,12 +2092,17 @@ function BulletinBoard({
1945
2092
  onEdit,
1946
2093
  onDelete,
1947
2094
  preview = false,
2095
+ editBaseUrl,
2096
+ editMethod,
2097
+ editIdKey,
2098
+ editFields,
1948
2099
  deleteBaseUrl,
1949
2100
  deleteIdKey = "id",
1950
2101
  serverPagination,
1951
2102
  className
1952
2103
  }) {
1953
2104
  const [previewItem, setPreviewItem] = React8.useState(null);
2105
+ const [editItem, setEditItem] = React8.useState(null);
1954
2106
  const [deleteItem, setDeleteItem] = React8.useState(null);
1955
2107
  const [search, setSearch] = React8.useState("");
1956
2108
  const [category, setCategory] = React8.useState(null);
@@ -2096,7 +2248,10 @@ function BulletinBoard({
2096
2248
  onView: onView ? (item) => {
2097
2249
  onView(item);
2098
2250
  } : void 0,
2099
- onEdit: onEdit ? (item) => {
2251
+ onEdit: editBaseUrl && editFields ? (item) => {
2252
+ setPreviewItem(null);
2253
+ setEditItem(item);
2254
+ } : onEdit ? (item) => {
2100
2255
  onEdit(item);
2101
2256
  } : void 0,
2102
2257
  onDelete: deleteBaseUrl ? (item) => {
@@ -2107,6 +2262,20 @@ function BulletinBoard({
2107
2262
  } : void 0
2108
2263
  }
2109
2264
  ),
2265
+ editItem && editBaseUrl && editFields && /* @__PURE__ */ jsx10(
2266
+ BulletinEditModal,
2267
+ {
2268
+ item: editItem,
2269
+ baseUrl: editBaseUrl,
2270
+ idKey: editIdKey,
2271
+ method: editMethod,
2272
+ fields: editFields,
2273
+ onClose: () => setEditItem(null),
2274
+ onSuccess: (updated) => {
2275
+ onEdit?.(updated);
2276
+ }
2277
+ }
2278
+ ),
2110
2279
  deleteItem && deleteBaseUrl && /* @__PURE__ */ jsx10(
2111
2280
  BulletinDeleteConfirm,
2112
2281
  {
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "registry": "https://registry.npmjs.org/",
5
5
  "access": "public"
6
6
  },
7
- "version": "3.1.8",
7
+ "version": "3.2.0",
8
8
  "description": "Reusable React UI components",
9
9
  "license": "MIT",
10
10
  "main": "dist/index.js",