@juv/codego-react-ui 3.3.1 → 3.3.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/index.js CHANGED
@@ -822,7 +822,7 @@ var Input = React3.forwardRef(
822
822
  id: inputId,
823
823
  placeholder: placeholder ?? (inputType === "date" ? "MM/DD/YYYY" : inputType === "dateTime" ? "MM/DD/YYYY HH:mm" : inputType === "time" ? "HH:mm" : void 0),
824
824
  className: cn(
825
- "flex h-10 w-full rounded-xl border border-slate-900/30 bg-background/50 backdrop-blur-sm px-3 py-5 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 transition-colors hover:bg-background/80 dark:border-white/30 dark:bg-gray-400/5 dark:hover:bg-gray-400/50 dark:focus:bg-gray-400/20",
825
+ "flex h-10 w-full rounded-xl border bg-background/50 backdrop-blur-sm px-3 py-5 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 transition-colors hover:bg-background/80 dark:bg-gray-400/5 dark:hover:bg-gray-400/25 dark:focus:bg-gray-400/20",
826
826
  hasLeftAddon && "pl-10",
827
827
  (hasRightAddon || hasReveal) && "pr-10",
828
828
  (readOnly || isDateType) && "bg-muted cursor-pointer",
@@ -3065,7 +3065,7 @@ function Combobox({
3065
3065
  "aria-required": required,
3066
3066
  "aria-invalid": !!error,
3067
3067
  className: cn(
3068
- "flex w-full items-center justify-between gap-2 rounded-xl border border-border bg-background px-3 py-2 text-sm transition-colors dark:border-white/30 dark:bg-gray-400/5 dark:hover:bg-gray-400/50 dark:focus:bg-gray-400/20",
3068
+ "flex w-full items-center justify-between gap-2 rounded-xl border-2 border-border bg-background px-3 py-2 text-sm transition-colors dark:bg-gray-400/5 dark:hover:bg-gray-400/25 dark:focus:bg-gray-400/20",
3069
3069
  "hover:border-primary/40 focus:outline-none focus:ring-2 focus:ring-ring",
3070
3070
  open && "border-primary ring-2 ring-ring",
3071
3071
  disabled && "opacity-50 cursor-not-allowed pointer-events-none",
@@ -4608,7 +4608,7 @@ function TagInput({
4608
4608
  "div",
4609
4609
  {
4610
4610
  className: cn(
4611
- "flex flex-wrap gap-1.5 min-h-10 w-full rounded-xl border border-border bg-background px-3 py-2 text-sm transition-colors dark:border-white/30 dark:bg-gray-400/5 dark:focus:bg-gray-100/10",
4611
+ "flex flex-wrap gap-1.5 min-h-10 w-full rounded-xl border-2 border-border bg-background px-3 py-2 text-sm transition-colors dark:bg-gray-400/5 dark:focus:bg-gray-100/40",
4612
4612
  "focus-within:ring-2 focus-within:ring-ring focus-within:border-primary",
4613
4613
  disabled && "opacity-50 cursor-not-allowed pointer-events-none",
4614
4614
  error && "border-destructive focus-within:ring-destructive",
@@ -4714,7 +4714,7 @@ function OtpInput({
4714
4714
  "aria-required": required,
4715
4715
  "aria-invalid": !!(error || invalid),
4716
4716
  className: cn(
4717
- "h-12 w-10 rounded-xl border text-center text-lg font-semibold bg-background transition-all outline-none dark:border-white/30 dark:bg-gray-400/5 dark:hover:bg-gray-400/50 dark:focus:bg-gray-400/20",
4717
+ "h-12 w-10 rounded-xl border-2 border-border text-center text-lg font-semibold bg-background transition-all outline-none dark:bg-gray-400/5 dark:hover:bg-gray-400/25 dark:focus:bg-gray-400/20",
4718
4718
  "focus:ring-2 focus:ring-ring focus:border-primary",
4719
4719
  invalid ? "border-danger focus:ring-danger" : "border-border",
4720
4720
  disabled && "opacity-50 cursor-not-allowed",
@@ -4832,9 +4832,9 @@ function DateRangePicker({
4832
4832
  disabled,
4833
4833
  onClick: () => open ? setOpen(false) : openPicker(),
4834
4834
  className: cn(
4835
- "flex w-full items-center gap-2 rounded-xl border border-border bg-background px-3 py-2 text-sm transition-colors",
4835
+ "flex w-full items-center gap-2 rounded-xl border-2 border-border bg-background px-3 py-2 text-sm transition-colors",
4836
4836
  "hover:border-primary/40 focus:outline-none focus:ring-2 focus:ring-ring",
4837
- "dark:border-white/30 dark:bg-gray-400/5",
4837
+ "dark:bg-gray-400/5",
4838
4838
  open && "border-primary ring-2 ring-ring",
4839
4839
  disabled && "opacity-50 cursor-not-allowed pointer-events-none",
4840
4840
  !range2.from && "text-muted-foreground"
@@ -5895,7 +5895,7 @@ var Textarea = React26.forwardRef(
5895
5895
  onBlur?.(e);
5896
5896
  };
5897
5897
  const grammarly = disableGrammarly ? { "data-gramm": "false", "data-gramm_editor": "false", "data-enable-grammarly": "false" } : {};
5898
- return /* @__PURE__ */ jsxs28("div", { className: "relative w-full", children: [
5898
+ return /* @__PURE__ */ jsxs28("div", { className: "relative w-full", children: [
5899
5899
  label && /* @__PURE__ */ jsxs28("label", { className: "block text-sm font-medium text-foreground mb-2", children: [
5900
5900
  label,
5901
5901
  required && /* @__PURE__ */ jsx30("span", { className: "text-destructive ml-1", children: "*" })
@@ -5917,7 +5917,7 @@ var Textarea = React26.forwardRef(
5917
5917
  "aria-required": required,
5918
5918
  "aria-invalid": !!error,
5919
5919
  className: cn(
5920
- "w-full rounded-xl border border-slate-900/30 bg-background/50 backdrop-blur-sm px-4 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 transition-colors hover:bg-background/80 dark:border-white/30 dark:bg-gray-400/5 dark:hover:bg-gray-400/50 dark:focus:bg-gray-400/20",
5920
+ "w-full rounded-xl border-2 border-border bg-background/50 backdrop-blur-sm px-4 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 transition-colors hover:bg-background/80 dark:bg-gray-400/5 dark:hover:bg-gray-400/25 dark:focus:bg-gray-400/20",
5921
5921
  readOnly && "cursor-default bg-muted/40 focus-visible:ring-0",
5922
5922
  autosize && "resize-none overflow-hidden",
5923
5923
  error && "border-destructive focus-visible:ring-destructive",
@@ -6285,7 +6285,7 @@ import { createPortal as createPortal3 } from "react-dom";
6285
6285
  import axios3 from "axios";
6286
6286
  import { ChevronLeft as ChevronLeft6, ChevronRight as ChevronRight8, Search as Search5, Trash2 as Trash22, ChevronsUpDown, ChevronUp, ChevronDown as ChevronDown4, X as X9, Eye as Eye2, Pencil as Pencil2, Trash as Trash3, Loader2 as Loader22 } from "lucide-react";
6287
6287
  import { Fragment as Fragment11, jsx as jsx32, jsxs as jsxs30 } from "react/jsx-runtime";
6288
- function useServerTable({ url, params, encrypt, key, decryptPayloadLog, columnOverrides }) {
6288
+ function useServerTable({ url, params, encrypt, key, decryptPayloadLog, columnOverrides, debounce = 300, transform, manual = false, onSuccess, onError }) {
6289
6289
  const [data, setData] = React28.useState([]);
6290
6290
  const [columns, setColumns] = React28.useState([]);
6291
6291
  const [currentPage, setCurrentPage] = React28.useState(1);
@@ -6293,17 +6293,22 @@ function useServerTable({ url, params, encrypt, key, decryptPayloadLog, columnOv
6293
6293
  const [loading, setLoading] = React28.useState(false);
6294
6294
  const [error, setError] = React28.useState(null);
6295
6295
  const [tick, setTick] = React28.useState(0);
6296
+ const [searchValue, setSearchValue] = React28.useState("");
6297
+ const debounceTimer = React28.useRef(void 0);
6296
6298
  React28.useEffect(() => {
6299
+ if (manual && tick === 0) return;
6297
6300
  let cancelled = false;
6298
6301
  setLoading(true);
6299
6302
  setError(null);
6300
6303
  axios3.get(url, {
6301
- params: { ...params, page: currentPage }
6304
+ params: { ...params, page: currentPage, search: searchValue }
6302
6305
  }).then(({ data: res }) => {
6303
6306
  if (cancelled) return;
6304
6307
  const payload = encrypt ? decryptLaravelPayload(res, key) : res;
6305
6308
  if (encrypt && decryptPayloadLog) console.log("[useServerTable] decrypted payload:", payload);
6306
- setData(payload.data);
6309
+ const transformed = transform ? transform(payload) : payload.data;
6310
+ setData(transformed);
6311
+ onSuccess?.(transformed);
6307
6312
  const rawTotal = payload.total;
6308
6313
  const rawPerPage = payload.per_page;
6309
6314
  const rawLastPage = payload.last_page;
@@ -6319,9 +6324,9 @@ function useServerTable({ url, params, encrypt, key, decryptPayloadLog, columnOv
6319
6324
  links: payload.links ?? []
6320
6325
  };
6321
6326
  setPagination(pg);
6322
- if (payload.data.length > 0) {
6327
+ if (transformed.length > 0) {
6323
6328
  setColumns(
6324
- Object.keys(payload.data[0]).map((k) => {
6329
+ Object.keys(transformed[0]).map((k) => {
6325
6330
  const columnKey = k;
6326
6331
  return {
6327
6332
  key: columnKey,
@@ -6333,14 +6338,24 @@ function useServerTable({ url, params, encrypt, key, decryptPayloadLog, columnOv
6333
6338
  }
6334
6339
  }).catch((err) => {
6335
6340
  if (cancelled) return;
6336
- setError(err?.response?.data?.message ?? err.message ?? "Request failed");
6341
+ const errorMsg = err?.response?.data?.message ?? err.message ?? "Request failed";
6342
+ setError(errorMsg);
6343
+ onError?.(new Error(errorMsg));
6337
6344
  }).finally(() => {
6338
6345
  if (!cancelled) setLoading(false);
6339
6346
  });
6340
6347
  return () => {
6341
6348
  cancelled = true;
6342
6349
  };
6343
- }, [url, currentPage, tick, JSON.stringify(params), encrypt, decryptPayloadLog, JSON.stringify(columnOverrides)]);
6350
+ }, [url, currentPage, tick, JSON.stringify(params), encrypt, decryptPayloadLog, JSON.stringify(columnOverrides), searchValue]);
6351
+ const handleSearchChange = (value) => {
6352
+ setSearchValue(value);
6353
+ setCurrentPage(1);
6354
+ if (debounceTimer.current) clearTimeout(debounceTimer.current);
6355
+ debounceTimer.current = setTimeout(() => {
6356
+ setTick((t) => t + 1);
6357
+ }, debounce);
6358
+ };
6344
6359
  return {
6345
6360
  data,
6346
6361
  columns,
@@ -6350,7 +6365,9 @@ function useServerTable({ url, params, encrypt, key, decryptPayloadLog, columnOv
6350
6365
  loading,
6351
6366
  error,
6352
6367
  goToPage: (page) => setCurrentPage(page),
6353
- reload: () => setTick((t) => t + 1)
6368
+ reload: () => setTick((t) => t + 1),
6369
+ searchValue,
6370
+ onSearchChange: handleSearchChange
6354
6371
  };
6355
6372
  }
6356
6373
  var MODAL_WIDTH = {
@@ -10120,7 +10137,7 @@ function GroupNavigation({
10120
10137
  group.collapsible && "cursor-pointer hover:text-foreground"
10121
10138
  ),
10122
10139
  children: [
10123
- /* @__PURE__ */ jsx43("span", { className: "flex-1 text-xs font-semibold uppercase tracking-wider text-muted-foreground", children: group.label }),
10140
+ /* @__PURE__ */ jsx43("span", { className: "flex-1 text-xs font-semibold uppercase tracking-wider text-primary/50 text-left", children: group.label }),
10124
10141
  group.collapsible && (isOpen ? /* @__PURE__ */ jsx43(ChevronDown6, { className: "h-3 w-3 text-muted-foreground" }) : /* @__PURE__ */ jsx43(ChevronRight10, { className: "h-3 w-3 text-muted-foreground" }))
10125
10142
  ]
10126
10143
  }
@@ -10948,7 +10965,7 @@ function Panel({
10948
10965
  }
10949
10966
  ),
10950
10967
  /* @__PURE__ */ jsxs41("div", { className: "relative z-10 flex flex-1 min-w-0 flex-col", children: [
10951
- /* @__PURE__ */ jsxs41("header", { className: "flex h-14 shrink-0 items-center justify-between border-b glass px-4 gap-2", children: [
10968
+ /* @__PURE__ */ jsxs41("header", { className: "flex h-14 shrink-0 items-center justify-between border-b border-b-slate-300/50 px-4 gap-2", children: [
10952
10969
  /* @__PURE__ */ jsxs41("div", { className: "flex items-center gap-2", children: [
10953
10970
  collapsible && sidebar && /* @__PURE__ */ jsx46(
10954
10971
  Tooltip,
@@ -10981,7 +10998,7 @@ function Panel({
10981
10998
  ] })
10982
10999
  ] }),
10983
11000
  /* @__PURE__ */ jsxs41("main", { className: "flex-1 overflow-y-auto p-4", children: [
10984
- error && /* @__PURE__ */ jsx46("div", { className: "mb-4 p-3 rounded-md bg-destructive/10 text-destructive text-sm", children: error }),
11001
+ error && /* @__PURE__ */ jsx46("div", { className: "mb-4 p-3 rounded-md bg-destructive/50 text-destructive text-sm", children: error }),
10985
11002
  loading && /* @__PURE__ */ jsx46("div", { className: "flex items-center justify-center h-full", children: /* @__PURE__ */ jsx46(Loader24, { className: "h-6 w-6 animate-spin text-muted-foreground" }) }),
10986
11003
  showEmpty && /* @__PURE__ */ jsx46("div", { className: "flex items-center justify-center h-full text-muted-foreground", children: emptyState }),
10987
11004
  !loading && !showEmpty && children
@@ -12682,6 +12699,94 @@ function Wizard({
12682
12699
  className
12683
12700
  ), children: panel });
12684
12701
  }
12702
+
12703
+ // src/lib/codego/axiosInstance.ts
12704
+ import axios5 from "axios";
12705
+ var axiosInstance = axios5.create({
12706
+ baseURL: "/",
12707
+ timeout: 1e4,
12708
+ headers: {
12709
+ "Content-Type": "application/json",
12710
+ Accept: "application/json"
12711
+ }
12712
+ });
12713
+
12714
+ // src/lib/codego/request.ts
12715
+ var request = async (config) => {
12716
+ try {
12717
+ const response = await axiosInstance(config);
12718
+ return response.data;
12719
+ } catch (error) {
12720
+ throw error.response?.data || error;
12721
+ }
12722
+ };
12723
+
12724
+ // src/lib/codego/interceptors.ts
12725
+ var setupInterceptors = () => {
12726
+ axiosInstance.interceptors.request.use(
12727
+ (config) => {
12728
+ const token = localStorage.getItem("token");
12729
+ if (token && !config.skipAuth) {
12730
+ config.headers.Authorization = `Bearer ${token}`;
12731
+ }
12732
+ return config;
12733
+ },
12734
+ (error) => Promise.reject(error)
12735
+ );
12736
+ axiosInstance.interceptors.response.use(
12737
+ (response) => response,
12738
+ (error) => {
12739
+ if (error.response?.status === 401) {
12740
+ console.warn("Unauthorized - redirect login");
12741
+ }
12742
+ return Promise.reject(error);
12743
+ }
12744
+ );
12745
+ };
12746
+
12747
+ // src/lib/codego/index.ts
12748
+ setupInterceptors();
12749
+ var api = {
12750
+ get: (url, config) => request({ method: "GET", url, ...config }),
12751
+ post: (url, data, config) => request({ method: "POST", url, data, ...config }),
12752
+ put: (url, data, config) => request({ method: "PUT", url, data, ...config }),
12753
+ patch: (url, data, config) => request({ method: "PATCH", url, data, ...config }),
12754
+ delete: (url, config) => request({ method: "DELETE", url, ...config })
12755
+ };
12756
+
12757
+ // src/core/storage/store.ts
12758
+ import { create } from "zustand";
12759
+ import { persist, createJSONStorage } from "zustand/middleware";
12760
+ function createStore(initialValue, sessionName, expireInterval) {
12761
+ if (expireInterval) {
12762
+ const expireKey = `${sessionName}_expires`;
12763
+ const now = Date.now();
12764
+ const storedExpire = localStorage.getItem(expireKey);
12765
+ if (storedExpire && now > parseInt(storedExpire)) {
12766
+ localStorage.removeItem(sessionName);
12767
+ localStorage.removeItem(expireKey);
12768
+ }
12769
+ localStorage.setItem(expireKey, (now + expireInterval).toString());
12770
+ }
12771
+ const store = create()(
12772
+ persist(
12773
+ (set) => ({
12774
+ ...initialValue,
12775
+ set: (val) => set((prev) => ({ ...prev, ...val }))
12776
+ }),
12777
+ {
12778
+ name: sessionName,
12779
+ storage: createJSONStorage(() => localStorage)
12780
+ }
12781
+ )
12782
+ );
12783
+ const getStore = () => {
12784
+ const state = store.getState();
12785
+ const { set, ...rest } = state;
12786
+ return JSON.stringify(rest);
12787
+ };
12788
+ return { store, getStore };
12789
+ }
12685
12790
  export {
12686
12791
  Accordion,
12687
12792
  Authentication,
@@ -12778,6 +12883,8 @@ export {
12778
12883
  TreeView,
12779
12884
  Widget,
12780
12885
  Wizard,
12886
+ api,
12887
+ createStore,
12781
12888
  useServerBulletin,
12782
12889
  useServerDataGrid,
12783
12890
  useServerTable,
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "registry": "https://registry.npmjs.org/",
5
5
  "access": "public"
6
6
  },
7
- "version": "3.3.1",
7
+ "version": "3.3.5",
8
8
  "description": "Reusable React UI components",
9
9
  "license": "MIT",
10
10
  "main": "dist/index.js",
@@ -45,7 +45,8 @@
45
45
  "react-dom": ">=18",
46
46
  "react-leaflet": "^5.0.0",
47
47
  "react-router-dom": "^7.13.1",
48
- "tailwind-merge": "^3.5.0"
48
+ "tailwind-merge": "^3.5.0",
49
+ "zustand": "^5.0.12"
49
50
  },
50
51
  "devDependencies": {
51
52
  "@types/express": "^4.17.21",