@juv/codego-react-ui 3.0.8 → 3.1.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/dist/index.cjs CHANGED
@@ -2127,6 +2127,62 @@ function MetricRow({ items, divided = true, className }) {
2127
2127
 
2128
2128
  // src/components/ui/data-grid.tsx
2129
2129
  var React24 = __toESM(require("react"), 1);
2130
+ var import_react_dom = require("react-dom");
2131
+
2132
+ // src/components/tools/decryptPayload.ts
2133
+ var import_crypto_js = __toESM(require("crypto-js"), 1);
2134
+ var import_meta = {};
2135
+ function getLaravelSecretKey() {
2136
+ const viteKey = import_meta.env["VITE_LARAVEL_KEY"];
2137
+ const legacyKey = globalThis?.process?.env?.REACT_APP_LARAVEL_KEY;
2138
+ const key = viteKey || legacyKey;
2139
+ if (!key) {
2140
+ throw new Error("Missing Laravel decryption key. Set VITE_LARAVEL_KEY in your .env.");
2141
+ }
2142
+ return key;
2143
+ }
2144
+ function parseLaravelKey(secretKey) {
2145
+ if (secretKey.startsWith("base64:")) {
2146
+ return import_crypto_js.default.enc.Base64.parse(secretKey.slice("base64:".length));
2147
+ }
2148
+ return import_crypto_js.default.enc.Utf8.parse(secretKey);
2149
+ }
2150
+ function parseLaravelEncryptedPayload(payload) {
2151
+ let jsonStr = payload;
2152
+ try {
2153
+ jsonStr = atob(payload);
2154
+ } catch {
2155
+ }
2156
+ return JSON.parse(jsonStr);
2157
+ }
2158
+ function decryptLaravelPayload(payload) {
2159
+ const secretKey = getLaravelSecretKey();
2160
+ const parsed = parseLaravelEncryptedPayload(payload);
2161
+ if (parsed.tag) {
2162
+ throw new Error("Unsupported Laravel cipher (AEAD tag present). Expected AES-*-CBC payload.");
2163
+ }
2164
+ const key = parseLaravelKey(secretKey);
2165
+ const expectedMac = import_crypto_js.default.HmacSHA256(parsed.iv + parsed.value, key).toString();
2166
+ if (expectedMac !== parsed.mac) {
2167
+ throw new Error("Invalid payload MAC (wrong key or tampered payload).");
2168
+ }
2169
+ const iv = import_crypto_js.default.enc.Base64.parse(parsed.iv);
2170
+ const ciphertext = import_crypto_js.default.enc.Base64.parse(parsed.value);
2171
+ const cipherParams = import_crypto_js.default.lib.CipherParams.create({ ciphertext });
2172
+ const decrypted = import_crypto_js.default.AES.decrypt(cipherParams, key, {
2173
+ iv,
2174
+ mode: import_crypto_js.default.mode.CBC,
2175
+ padding: import_crypto_js.default.pad.Pkcs7
2176
+ });
2177
+ const plaintext = decrypted.toString(import_crypto_js.default.enc.Utf8);
2178
+ if (!plaintext) {
2179
+ throw new Error("Decryption produced empty plaintext (wrong key/cipher).");
2180
+ }
2181
+ console.log("Decrypted payload:", plaintext);
2182
+ return JSON.parse(plaintext);
2183
+ }
2184
+
2185
+ // src/components/ui/data-grid.tsx
2130
2186
  var import_axios = __toESM(require("axios"), 1);
2131
2187
  var import_lucide_react15 = require("lucide-react");
2132
2188
 
@@ -4843,7 +4899,7 @@ Input.displayName = "Input";
4843
4899
 
4844
4900
  // src/components/ui/data-grid.tsx
4845
4901
  var import_jsx_runtime28 = require("react/jsx-runtime");
4846
- function useServerDataGrid({ url, params }) {
4902
+ function useServerDataGrid({ url, params, encrypt }) {
4847
4903
  const [data, setData] = React24.useState([]);
4848
4904
  const [columns, setColumns] = React24.useState([]);
4849
4905
  const [currentPage, setCurrentPage] = React24.useState(1);
@@ -4857,23 +4913,26 @@ function useServerDataGrid({ url, params }) {
4857
4913
  setError(null);
4858
4914
  import_axios.default.get(url, { params: { ...params, page: currentPage } }).then(({ data: res }) => {
4859
4915
  if (cancelled) return;
4860
- setData(res.data);
4861
- const rawTotal = res.total;
4862
- const rawPerPage = res.per_page;
4863
- const lastPage = Math.ceil(rawTotal / rawPerPage);
4864
- const pg = res.pagination ?? {
4865
- first_page_url: res.first_page_url ?? `${url}?page=1`,
4866
- last_page_url: res.last_page_url ?? `${url}?page=${lastPage}`,
4867
- next_page_url: res.next_page_url !== void 0 ? res.next_page_url : currentPage < lastPage ? `${url}?page=${currentPage + 1}` : null,
4868
- prev_page_url: res.prev_page_url !== void 0 ? res.prev_page_url : currentPage > 1 ? `${url}?page=${currentPage - 1}` : null,
4916
+ const payload = encrypt ? decryptLaravelPayload(res) : res;
4917
+ setData(payload.data);
4918
+ const rawTotal = payload.total;
4919
+ const rawPerPage = payload.per_page;
4920
+ const rawLastPage = payload.last_page;
4921
+ const lastPage = rawLastPage ?? Math.ceil(rawTotal / rawPerPage);
4922
+ const pg = payload.pagination ?? {
4923
+ first_page_url: payload.first_page_url ?? `${url}?page=1`,
4924
+ last_page_url: payload.last_page_url ?? `${url}?page=${lastPage}`,
4925
+ last_page: lastPage,
4926
+ next_page_url: payload.next_page_url !== void 0 ? payload.next_page_url : currentPage < lastPage ? `${url}?page=${currentPage + 1}` : null,
4927
+ prev_page_url: payload.prev_page_url !== void 0 ? payload.prev_page_url : currentPage > 1 ? `${url}?page=${currentPage - 1}` : null,
4869
4928
  per_page: rawPerPage,
4870
4929
  total: rawTotal,
4871
- links: res.links ?? []
4930
+ links: payload.links ?? []
4872
4931
  };
4873
4932
  setPagination(pg);
4874
- if (res.data.length > 0) {
4933
+ if (payload.data.length > 0) {
4875
4934
  setColumns(
4876
- Object.keys(res.data[0]).map((key) => ({
4935
+ Object.keys(payload.data[0]).map((key) => ({
4877
4936
  key,
4878
4937
  header: key.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase())
4879
4938
  }))
@@ -4902,23 +4961,26 @@ function useServerDataGrid({ url, params }) {
4902
4961
  };
4903
4962
  }
4904
4963
  function DGModalShell({ title, onClose, children, footer }) {
4905
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
4906
- "div",
4907
- {
4908
- className: "fixed inset-0 z-50 flex items-center justify-center p-4",
4909
- style: { background: "rgba(0,0,0,0.5)" },
4910
- onMouseDown: (e) => {
4911
- if (e.target === e.currentTarget) onClose();
4912
- },
4913
- children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "relative w-full max-w-lg rounded-2xl border border-border bg-card shadow-2xl flex flex-col max-h-[90vh]", children: [
4914
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex items-center justify-between px-6 py-4 border-b border-border shrink-0", children: [
4915
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("h2", { className: "text-base font-semibold", children: title }),
4916
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("button", { onClick: onClose, className: "text-muted-foreground hover:text-foreground transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react15.X, { className: "h-4 w-4" }) })
4917
- ] }),
4918
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "overflow-y-auto px-6 py-4 flex-1", children }),
4919
- footer && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "px-6 py-4 border-t border-border shrink-0 flex justify-end gap-2", children: footer })
4920
- ] })
4921
- }
4964
+ return (0, import_react_dom.createPortal)(
4965
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
4966
+ "div",
4967
+ {
4968
+ className: "fixed inset-0 z-50 flex items-center justify-center p-4",
4969
+ style: { background: "rgba(0,0,0,0.5)" },
4970
+ onMouseDown: (e) => {
4971
+ if (e.target === e.currentTarget) onClose();
4972
+ },
4973
+ children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "relative w-full max-w-lg rounded-2xl border border-border bg-card shadow-2xl flex flex-col max-h-[90vh]", children: [
4974
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex items-center justify-between px-6 py-4 border-b border-border shrink-0", children: [
4975
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("h2", { className: "text-base font-semibold", children: title }),
4976
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("button", { onClick: onClose, className: "text-muted-foreground hover:text-foreground transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react15.X, { className: "h-4 w-4" }) })
4977
+ ] }),
4978
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "overflow-y-auto px-6 py-4 flex-1", children }),
4979
+ footer && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "px-6 py-4 border-t border-border shrink-0 flex justify-end gap-2", children: footer })
4980
+ ] })
4981
+ }
4982
+ ),
4983
+ document.body
4922
4984
  );
4923
4985
  }
4924
4986
  function DGFieldRenderer({ field, value, onChange }) {
@@ -5232,7 +5294,10 @@ function DataGrid({
5232
5294
  )
5233
5295
  ] })
5234
5296
  } : null;
5235
- const visibleCols = [
5297
+ const visibleCols = defaultActions?.position === "first" ? [
5298
+ ...actionsCol ? [actionsCol] : [],
5299
+ ...columns.filter((c) => !hiddenCols.includes(String(c.key)))
5300
+ ] : [
5236
5301
  ...columns.filter((c) => !hiddenCols.includes(String(c.key))),
5237
5302
  ...actionsCol ? [actionsCol] : []
5238
5303
  ];
@@ -5372,7 +5437,7 @@ function DataGrid({
5372
5437
  ),
5373
5438
  serverPagination && (() => {
5374
5439
  const { pagination, currentPage: cp, goToPage } = serverPagination;
5375
- const totalServerPages = Math.ceil(pagination.total / pagination.per_page);
5440
+ const totalServerPages = pagination.last_page ?? Math.ceil(pagination.total / pagination.per_page);
5376
5441
  const pageLinks = Array.from({ length: totalServerPages }, (_, i) => i + 1);
5377
5442
  return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex items-center justify-between gap-2 flex-wrap", children: [
5378
5443
  /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { className: "text-xs text-muted-foreground", children: [
@@ -9483,10 +9548,11 @@ function Stepper({
9483
9548
 
9484
9549
  // src/components/ui/table.tsx
9485
9550
  var React44 = __toESM(require("react"), 1);
9551
+ var import_react_dom2 = require("react-dom");
9486
9552
  var import_axios2 = __toESM(require("axios"), 1);
9487
9553
  var import_lucide_react28 = require("lucide-react");
9488
9554
  var import_jsx_runtime55 = require("react/jsx-runtime");
9489
- function useServerTable({ url, params }) {
9555
+ function useServerTable({ url, params, encrypt }) {
9490
9556
  const [data, setData] = React44.useState([]);
9491
9557
  const [columns, setColumns] = React44.useState([]);
9492
9558
  const [currentPage, setCurrentPage] = React44.useState(1);
@@ -9502,23 +9568,26 @@ function useServerTable({ url, params }) {
9502
9568
  params: { ...params, page: currentPage }
9503
9569
  }).then(({ data: res }) => {
9504
9570
  if (cancelled) return;
9505
- setData(res.data);
9506
- const rawTotal = res.total;
9507
- const rawPerPage = res.per_page;
9508
- const lastPage = Math.ceil(rawTotal / rawPerPage);
9509
- const pg = res.pagination ?? {
9510
- first_page_url: res.first_page_url ?? `${url}?page=1`,
9511
- last_page_url: res.last_page_url ?? `${url}?page=${lastPage}`,
9512
- next_page_url: res.next_page_url !== void 0 ? res.next_page_url : currentPage < lastPage ? `${url}?page=${currentPage + 1}` : null,
9513
- prev_page_url: res.prev_page_url !== void 0 ? res.prev_page_url : currentPage > 1 ? `${url}?page=${currentPage - 1}` : null,
9571
+ const payload = encrypt ? decryptLaravelPayload(res) : res;
9572
+ setData(payload.data);
9573
+ const rawTotal = payload.total;
9574
+ const rawPerPage = payload.per_page;
9575
+ const rawLastPage = payload.last_page;
9576
+ const lastPage = rawLastPage ?? Math.ceil(rawTotal / rawPerPage);
9577
+ const pg = payload.pagination ?? {
9578
+ first_page_url: payload.first_page_url ?? `${url}?page=1`,
9579
+ last_page_url: payload.last_page_url ?? `${url}?page=${lastPage}`,
9580
+ last_page: lastPage,
9581
+ next_page_url: payload.next_page_url !== void 0 ? payload.next_page_url : currentPage < lastPage ? `${url}?page=${currentPage + 1}` : null,
9582
+ prev_page_url: payload.prev_page_url !== void 0 ? payload.prev_page_url : currentPage > 1 ? `${url}?page=${currentPage - 1}` : null,
9514
9583
  per_page: rawPerPage,
9515
9584
  total: rawTotal,
9516
- links: res.links ?? []
9585
+ links: payload.links ?? []
9517
9586
  };
9518
9587
  setPagination(pg);
9519
- if (res.data.length > 0) {
9588
+ if (payload.data.length > 0) {
9520
9589
  setColumns(
9521
- Object.keys(res.data[0]).map((key) => ({
9590
+ Object.keys(payload.data[0]).map((key) => ({
9522
9591
  key,
9523
9592
  title: key.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase())
9524
9593
  }))
@@ -9547,23 +9616,26 @@ function useServerTable({ url, params }) {
9547
9616
  };
9548
9617
  }
9549
9618
  function ModalShell({ title, onClose, children, footer }) {
9550
- return /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
9551
- "div",
9552
- {
9553
- className: "fixed inset-0 z-50 flex items-center justify-center p-4",
9554
- style: { background: "rgba(0,0,0,0.5)" },
9555
- onMouseDown: (e) => {
9556
- if (e.target === e.currentTarget) onClose();
9557
- },
9558
- children: /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "relative w-full max-w-lg rounded-2xl border border-border bg-card shadow-2xl flex flex-col max-h-[90vh]", children: [
9559
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "flex items-center justify-between px-6 py-4 border-b border-border shrink-0", children: [
9560
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("h2", { className: "text-base font-semibold", children: title }),
9561
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("button", { onClick: onClose, className: "text-muted-foreground hover:text-foreground transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(import_lucide_react28.X, { className: "h-4 w-4" }) })
9562
- ] }),
9563
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "overflow-y-auto px-6 py-4 flex-1", children }),
9564
- footer && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "px-6 py-4 border-t border-border shrink-0 flex justify-end gap-2", children: footer })
9565
- ] })
9566
- }
9619
+ return (0, import_react_dom2.createPortal)(
9620
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
9621
+ "div",
9622
+ {
9623
+ className: "fixed inset-0 z-50 flex items-center justify-center p-4",
9624
+ style: { background: "rgba(0,0,0,0.5)" },
9625
+ onMouseDown: (e) => {
9626
+ if (e.target === e.currentTarget) onClose();
9627
+ },
9628
+ children: /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "relative w-full max-w-lg rounded-2xl border border-border bg-card shadow-2xl flex flex-col max-h-[90vh]", children: [
9629
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "flex items-center justify-between px-6 py-4 border-b border-border shrink-0", children: [
9630
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("h2", { className: "text-base font-semibold", children: title }),
9631
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("button", { onClick: onClose, className: "text-muted-foreground hover:text-foreground transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(import_lucide_react28.X, { className: "h-4 w-4" }) })
9632
+ ] }),
9633
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "overflow-y-auto px-6 py-4 flex-1", children }),
9634
+ footer && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "px-6 py-4 border-t border-border shrink-0 flex justify-end gap-2", children: footer })
9635
+ ] })
9636
+ }
9637
+ ),
9638
+ document.body
9567
9639
  );
9568
9640
  }
9569
9641
  function FieldRenderer({ field, value, onChange }) {
@@ -9906,7 +9978,7 @@ function Table({
9906
9978
  )
9907
9979
  ] })
9908
9980
  };
9909
- return [...columns, actionsCol];
9981
+ return defaultActions.position === "first" ? [actionsCol, ...columns] : [...columns, actionsCol];
9910
9982
  }, [columns, defaultActions]);
9911
9983
  const handleSort = (key) => {
9912
9984
  if (sortKey !== key) {
@@ -10002,9 +10074,9 @@ function Table({
10002
10074
  }
10003
10075
  ),
10004
10076
  /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("span", { className: "text-xs text-muted-foreground", children: [
10005
- filteredData.length,
10077
+ serverPagination ? serverPagination.pagination.total : filteredData.length,
10006
10078
  " ",
10007
- filteredData.length === 1 ? "row" : "rows",
10079
+ (serverPagination ? serverPagination.pagination.total : filteredData.length) === 1 ? "row" : "rows",
10008
10080
  search && ` \xB7 filtered from ${tableData.length}`
10009
10081
  ] })
10010
10082
  ] })
@@ -10178,7 +10250,7 @@ function Table({
10178
10250
  ] }),
10179
10251
  serverPagination && (() => {
10180
10252
  const { pagination: pagination2, currentPage: cp, goToPage } = serverPagination;
10181
- const totalServerPages = Math.ceil(pagination2.total / pagination2.per_page);
10253
+ const totalServerPages = pagination2.last_page ?? Math.ceil(pagination2.total / pagination2.per_page);
10182
10254
  const pageLinks = Array.from({ length: totalServerPages }, (_, i) => i + 1);
10183
10255
  return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "flex items-center justify-between gap-2 flex-wrap", children: [
10184
10256
  /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("span", { className: "text-xs text-muted-foreground", children: [
package/dist/index.d.cts CHANGED
@@ -344,6 +344,7 @@ interface ServerPaginationLink {
344
344
  interface ServerPagination {
345
345
  first_page_url: string;
346
346
  last_page_url: string;
347
+ last_page: number;
347
348
  next_page_url: string | null;
348
349
  prev_page_url: string | null;
349
350
  per_page: number;
@@ -360,6 +361,8 @@ interface UseServerTableOptions {
360
361
  url: string;
361
362
  /** Extra query params merged on every request */
362
363
  params?: Record<string, string | number>;
364
+ /** If true, the response is expected to be a Laravel-encrypted payload and will be decrypted using VITE_LARAVEL_KEY */
365
+ encrypt?: boolean;
363
366
  }
364
367
  interface UseServerTableReturn<T> {
365
368
  data: T[];
@@ -377,7 +380,7 @@ interface ServerPaginationProp {
377
380
  currentPage: number;
378
381
  goToPage: (page: number) => void;
379
382
  }
380
- declare function useServerTable<T extends Record<string, any>>({ url, params }: UseServerTableOptions): UseServerTableReturn<T>;
383
+ declare function useServerTable<T extends Record<string, any>>({ url, params, encrypt }: UseServerTableOptions): UseServerTableReturn<T>;
381
384
  type ActionFieldType = "input" | "password" | "textarea" | "checkbox" | "toggle" | "select" | "radio" | "slider" | "tag-input" | "otp" | "combobox" | "color-picker" | "date-range" | "rich-text" | "file-upload" | "repeater";
382
385
  interface ActionField {
383
386
  key: string;
@@ -412,6 +415,8 @@ interface DefaultActionsConfig<T> {
412
415
  baseUrl: string;
413
416
  /** Row key used as the URL id segment. Defaults to "id". */
414
417
  idKey?: keyof T;
418
+ /** Position of the Actions column. Default "last". */
419
+ position?: "first" | "last";
415
420
  /** Fields rendered in the Edit modal form. Auto-derived from row keys when omitted. */
416
421
  editForm?: ActionField[];
417
422
  /** Fields rendered in the View modal. Auto-derived from row keys when omitted. */
@@ -462,6 +467,8 @@ interface ServerDataGridProp {
462
467
  interface UseServerDataGridOptions {
463
468
  url: string;
464
469
  params?: Record<string, string | number>;
470
+ /** If true, the response is expected to be a Laravel-encrypted payload and will be decrypted using VITE_LARAVEL_KEY */
471
+ encrypt?: boolean;
465
472
  }
466
473
  interface UseServerDataGridReturn<T> {
467
474
  data: T[];
@@ -474,7 +481,7 @@ interface UseServerDataGridReturn<T> {
474
481
  goToPage: (page: number) => void;
475
482
  reload: () => void;
476
483
  }
477
- declare function useServerDataGrid<T extends Record<string, any>>({ url, params }: UseServerDataGridOptions): UseServerDataGridReturn<T>;
484
+ declare function useServerDataGrid<T extends Record<string, any>>({ url, params, encrypt }: UseServerDataGridOptions): UseServerDataGridReturn<T>;
478
485
  type SortDir = "asc" | "desc" | null;
479
486
  interface DataGridColumn<T> {
480
487
  key: keyof T | string;
package/dist/index.d.ts CHANGED
@@ -344,6 +344,7 @@ interface ServerPaginationLink {
344
344
  interface ServerPagination {
345
345
  first_page_url: string;
346
346
  last_page_url: string;
347
+ last_page: number;
347
348
  next_page_url: string | null;
348
349
  prev_page_url: string | null;
349
350
  per_page: number;
@@ -360,6 +361,8 @@ interface UseServerTableOptions {
360
361
  url: string;
361
362
  /** Extra query params merged on every request */
362
363
  params?: Record<string, string | number>;
364
+ /** If true, the response is expected to be a Laravel-encrypted payload and will be decrypted using VITE_LARAVEL_KEY */
365
+ encrypt?: boolean;
363
366
  }
364
367
  interface UseServerTableReturn<T> {
365
368
  data: T[];
@@ -377,7 +380,7 @@ interface ServerPaginationProp {
377
380
  currentPage: number;
378
381
  goToPage: (page: number) => void;
379
382
  }
380
- declare function useServerTable<T extends Record<string, any>>({ url, params }: UseServerTableOptions): UseServerTableReturn<T>;
383
+ declare function useServerTable<T extends Record<string, any>>({ url, params, encrypt }: UseServerTableOptions): UseServerTableReturn<T>;
381
384
  type ActionFieldType = "input" | "password" | "textarea" | "checkbox" | "toggle" | "select" | "radio" | "slider" | "tag-input" | "otp" | "combobox" | "color-picker" | "date-range" | "rich-text" | "file-upload" | "repeater";
382
385
  interface ActionField {
383
386
  key: string;
@@ -412,6 +415,8 @@ interface DefaultActionsConfig<T> {
412
415
  baseUrl: string;
413
416
  /** Row key used as the URL id segment. Defaults to "id". */
414
417
  idKey?: keyof T;
418
+ /** Position of the Actions column. Default "last". */
419
+ position?: "first" | "last";
415
420
  /** Fields rendered in the Edit modal form. Auto-derived from row keys when omitted. */
416
421
  editForm?: ActionField[];
417
422
  /** Fields rendered in the View modal. Auto-derived from row keys when omitted. */
@@ -462,6 +467,8 @@ interface ServerDataGridProp {
462
467
  interface UseServerDataGridOptions {
463
468
  url: string;
464
469
  params?: Record<string, string | number>;
470
+ /** If true, the response is expected to be a Laravel-encrypted payload and will be decrypted using VITE_LARAVEL_KEY */
471
+ encrypt?: boolean;
465
472
  }
466
473
  interface UseServerDataGridReturn<T> {
467
474
  data: T[];
@@ -474,7 +481,7 @@ interface UseServerDataGridReturn<T> {
474
481
  goToPage: (page: number) => void;
475
482
  reload: () => void;
476
483
  }
477
- declare function useServerDataGrid<T extends Record<string, any>>({ url, params }: UseServerDataGridOptions): UseServerDataGridReturn<T>;
484
+ declare function useServerDataGrid<T extends Record<string, any>>({ url, params, encrypt }: UseServerDataGridOptions): UseServerDataGridReturn<T>;
478
485
  type SortDir = "asc" | "desc" | null;
479
486
  interface DataGridColumn<T> {
480
487
  key: keyof T | string;