@pattern-stack/frontend-patterns 0.2.0-alpha.0 → 0.2.0-alpha.3

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.
Files changed (56) hide show
  1. package/cli/commands/generate-hooks.ts +13 -4
  2. package/cli/src/codegen/openapi/__tests__/naming-utils.test.js +367 -0
  3. package/cli/src/codegen/openapi/client-generator.js +87 -19
  4. package/cli/src/codegen/openapi/confidence-scorer.js +93 -0
  5. package/cli/src/codegen/openapi/hook-config.js +48 -0
  6. package/cli/src/codegen/openapi/hook-generator.js +100 -62
  7. package/cli/src/codegen/openapi/naming-constants.js +98 -0
  8. package/cli/src/codegen/openapi/naming-utils.js +149 -0
  9. package/dist/atoms/components/core/Badge/Badge.d.ts +1 -1
  10. package/dist/atoms/components/data/DataTable/DataTable.d.ts.map +1 -1
  11. package/dist/atoms/components/data/DataTable/DataTable.types.d.ts +15 -3
  12. package/dist/atoms/components/data/DataTable/DataTable.types.d.ts.map +1 -1
  13. package/dist/atoms/hooks/index.d.ts +2 -0
  14. package/dist/atoms/hooks/index.d.ts.map +1 -1
  15. package/dist/atoms/hooks/useFieldMetadata.d.ts +18 -0
  16. package/dist/atoms/hooks/useFieldMetadata.d.ts.map +1 -0
  17. package/dist/atoms/hooks/useResponsiveTable.d.ts +103 -0
  18. package/dist/atoms/hooks/useResponsiveTable.d.ts.map +1 -0
  19. package/dist/atoms/primitives/sheet.d.ts +23 -0
  20. package/dist/atoms/primitives/sheet.d.ts.map +1 -0
  21. package/dist/atoms/services/auth-service.d.ts.map +1 -1
  22. package/dist/atoms/types/auth.d.ts +51 -0
  23. package/dist/atoms/types/auth.d.ts.map +1 -1
  24. package/dist/atoms/types/index.d.ts +1 -0
  25. package/dist/atoms/types/index.d.ts.map +1 -1
  26. package/dist/atoms/types/ui-config.d.ts +25 -8
  27. package/dist/atoms/types/ui-config.d.ts.map +1 -1
  28. package/dist/atoms/types/ui-metadata.d.ts +112 -0
  29. package/dist/atoms/types/ui-metadata.d.ts.map +1 -0
  30. package/dist/atoms/utils/ui-mapping.d.ts +9 -3
  31. package/dist/atoms/utils/ui-mapping.d.ts.map +1 -1
  32. package/dist/features/auth/hooks/useAuth.d.ts.map +1 -1
  33. package/dist/frontend-patterns.css +82 -0
  34. package/dist/index.d.ts +4 -1
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.es.js +1030 -248
  37. package/dist/index.es.js.map +1 -1
  38. package/dist/index.js +1031 -248
  39. package/dist/index.js.map +1 -1
  40. package/dist/molecules/layout/ListToolbar/ListToolbar.d.ts +37 -0
  41. package/dist/molecules/layout/ListToolbar/ListToolbar.d.ts.map +1 -0
  42. package/dist/molecules/layout/ListToolbar/index.d.ts +2 -0
  43. package/dist/molecules/layout/ListToolbar/index.d.ts.map +1 -0
  44. package/dist/molecules/layout/PageTitle/PageTitle.d.ts +17 -0
  45. package/dist/molecules/layout/PageTitle/PageTitle.d.ts.map +1 -0
  46. package/dist/molecules/layout/PageTitle/index.d.ts +2 -0
  47. package/dist/molecules/layout/PageTitle/index.d.ts.map +1 -0
  48. package/dist/molecules/layout/index.d.ts +2 -0
  49. package/dist/molecules/layout/index.d.ts.map +1 -1
  50. package/dist/templates/ListPageTemplate.d.ts +21 -0
  51. package/dist/templates/ListPageTemplate.d.ts.map +1 -0
  52. package/dist/templates/admin/AdminCRUDTemplate.d.ts.map +1 -1
  53. package/dist/templates/factory.d.ts.map +1 -1
  54. package/dist/templates/index.d.ts +1 -0
  55. package/dist/templates/index.d.ts.map +1 -1
  56. package/package.json +4 -3
package/dist/index.js CHANGED
@@ -30,9 +30,10 @@ const tailwindMerge = require("tailwind-merge");
30
30
  const axios = require("axios");
31
31
  const jsxDevRuntime = require("react/jsx-dev-runtime");
32
32
  const React = require("react");
33
+ const SheetPrimitive = require("@radix-ui/react-dialog");
34
+ const lucideReact = require("lucide-react");
33
35
  const LabelPrimitive = require("@radix-ui/react-label");
34
36
  const classVarianceAuthority = require("class-variance-authority");
35
- const lucideReact = require("lucide-react");
36
37
  const AvatarPrimitive = require("@radix-ui/react-avatar");
37
38
  const reactQuery = require("@tanstack/react-query");
38
39
  const reactSlot = require("@radix-ui/react-slot");
@@ -57,6 +58,7 @@ function _interopNamespaceDefault(e) {
57
58
  return Object.freeze(n);
58
59
  }
59
60
  const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
61
+ const SheetPrimitive__namespace = /* @__PURE__ */ _interopNamespaceDefault(SheetPrimitive);
60
62
  const LabelPrimitive__namespace = /* @__PURE__ */ _interopNamespaceDefault(LabelPrimitive);
61
63
  const AvatarPrimitive__namespace = /* @__PURE__ */ _interopNamespaceDefault(AvatarPrimitive);
62
64
  const DropdownMenuPrimitive__namespace = /* @__PURE__ */ _interopNamespaceDefault(DropdownMenuPrimitive);
@@ -695,11 +697,11 @@ const DEFAULT_FIELD_MAPPINGS = {
695
697
  state: "status",
696
698
  orderStatus: "status",
697
699
  paymentStatus: "status",
698
- // Category fields
699
- category: "category",
700
- type: "category",
701
- tag: "category",
702
- label: "category",
700
+ // Badge fields (categories, tags, labels)
701
+ category: "badge",
702
+ type: "badge",
703
+ tag: "badge",
704
+ label: "badge",
703
705
  // Money fields
704
706
  amount: "money",
705
707
  price: "money",
@@ -775,7 +777,7 @@ const FIELD_PATTERNS = [
775
777
  // discount_rate, tax_percent
776
778
  { pattern: /status|state/, type: "status" },
777
779
  // order_status, state
778
- { pattern: /category|type|tag|label/, type: "category" },
780
+ { pattern: /category|type|tag|label/, type: "badge" },
779
781
  // product_category
780
782
  { pattern: /email/i, type: "email" },
781
783
  // user_email, emailAddress
@@ -1988,18 +1990,46 @@ const globalColorManager = new CategoryColorManager("sequential");
1988
1990
  function useCategoryColors(strategy) {
1989
1991
  return strategy ? new CategoryColorManager(strategy) : globalColorManager;
1990
1992
  }
1991
- function formatMoney(value, currency = "USD") {
1992
- return new Intl.NumberFormat("en-US", {
1993
+ const LEGACY_TYPE_MAP = {
1994
+ // Old frontend names
1995
+ category: "badge",
1996
+ // Backend names that differ
1997
+ currency: "money",
1998
+ percentage: "percent",
1999
+ // Input-focused types (deprecated)
2000
+ select: "badge",
2001
+ multiselect: "badge",
2002
+ textarea: "text",
2003
+ reference: "entity",
2004
+ enum: "badge"
2005
+ };
2006
+ function normalizeFieldType(type) {
2007
+ return LEGACY_TYPE_MAP[type] ?? type ?? "text";
2008
+ }
2009
+ function formatMoney(value, currency = "USD", decimals = 2, locale = "en-US") {
2010
+ return new Intl.NumberFormat(locale, {
1993
2011
  style: "currency",
1994
2012
  currency,
1995
- minimumFractionDigits: 2,
1996
- maximumFractionDigits: 2
2013
+ minimumFractionDigits: decimals,
2014
+ maximumFractionDigits: decimals
1997
2015
  }).format(value);
1998
2016
  }
1999
- function formatPercent(value, decimals = 1) {
2000
- return `${value.toFixed(decimals)}%`;
2017
+ function formatPercent(value, decimals = 1, locale = "en-US") {
2018
+ return new Intl.NumberFormat(locale, {
2019
+ style: "percent",
2020
+ minimumFractionDigits: decimals,
2021
+ maximumFractionDigits: decimals
2022
+ }).format(value / 100);
2023
+ }
2024
+ function formatNumber(value, decimals, locale = "en-US") {
2025
+ const options = {};
2026
+ if (decimals !== void 0) {
2027
+ options.minimumFractionDigits = decimals;
2028
+ options.maximumFractionDigits = decimals;
2029
+ }
2030
+ return new Intl.NumberFormat(locale, options).format(value);
2001
2031
  }
2002
- function formatDate(value, includeTime = false) {
2032
+ function formatDate(value, includeTime = false, locale = "en-US") {
2003
2033
  const date = typeof value === "string" ? new Date(value) : value;
2004
2034
  if (isNaN(date.getTime())) return String(value);
2005
2035
  const options = {
@@ -2012,7 +2042,7 @@ function formatDate(value, includeTime = false) {
2012
2042
  options.minute = "2-digit";
2013
2043
  options.hour12 = true;
2014
2044
  }
2015
- return date.toLocaleDateString("en-US", options);
2045
+ return date.toLocaleDateString(locale, options);
2016
2046
  }
2017
2047
  function getSizeForBreakpoint(breakpoint) {
2018
2048
  switch (breakpoint) {
@@ -2040,35 +2070,36 @@ function getDisplayForBreakpoint(breakpoint) {
2040
2070
  return "full";
2041
2071
  }
2042
2072
  }
2073
+ const DEFAULT_STATUS_COLORS = {
2074
+ active: "success",
2075
+ completed: "success",
2076
+ approved: "success",
2077
+ published: "success",
2078
+ pending: "warning",
2079
+ processing: "warning",
2080
+ scheduled: "warning",
2081
+ draft: "warning",
2082
+ failed: "error",
2083
+ rejected: "error",
2084
+ cancelled: "error",
2085
+ deleted: "error",
2086
+ inactive: "neutral",
2087
+ archived: "neutral",
2088
+ closed: "neutral"
2089
+ };
2043
2090
  const defaultFieldRenderers = {
2044
- status: (value, _fieldName, breakpoint) => {
2091
+ status: (value, _fieldName, breakpoint, _item, format) => {
2045
2092
  const size = getSizeForBreakpoint(breakpoint);
2046
2093
  const display = getDisplayForBreakpoint(breakpoint);
2047
- const statusColorMap = {
2048
- active: "success",
2049
- completed: "success",
2050
- approved: "success",
2051
- published: "success",
2052
- pending: "warning",
2053
- processing: "warning",
2054
- scheduled: "warning",
2055
- draft: "warning",
2056
- failed: "error",
2057
- rejected: "error",
2058
- cancelled: "error",
2059
- deleted: "error",
2060
- inactive: "neutral",
2061
- archived: "neutral",
2062
- closed: "neutral"
2063
- };
2064
- const status = statusColorMap[String(value).toLowerCase()] || "info";
2094
+ const colorMap = (format == null ? void 0 : format.statusColors) ?? DEFAULT_STATUS_COLORS;
2095
+ const status = colorMap[String(value).toLowerCase()] ?? "info";
2065
2096
  return /* @__PURE__ */ jsxDevRuntime.jsxDEV(DataBadge, { variant: "status", status, size, display, children: String(value) }, void 0, false, {
2066
2097
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/utils/ui-mapping.tsx",
2067
- lineNumber: 134,
2098
+ lineNumber: 209,
2068
2099
  columnNumber: 7
2069
2100
  }, void 0);
2070
2101
  },
2071
- category: (value, _fieldName, breakpoint) => {
2102
+ badge: (value, _fieldName, breakpoint) => {
2072
2103
  const size = getSizeForBreakpoint(breakpoint);
2073
2104
  const display = getDisplayForBreakpoint(breakpoint);
2074
2105
  const color = globalColorManager.getColor(String(value));
@@ -2085,45 +2116,62 @@ const defaultFieldRenderers = {
2085
2116
  false,
2086
2117
  {
2087
2118
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/utils/ui-mapping.tsx",
2088
- lineNumber: 146,
2119
+ lineNumber: 221,
2089
2120
  columnNumber: 7
2090
2121
  },
2091
2122
  void 0
2092
2123
  );
2093
2124
  },
2094
- money: (value) => {
2095
- const formatted = formatMoney(Number(value));
2125
+ money: (value, _fieldName, _breakpoint, _item, format) => {
2126
+ const formatted = formatMoney(
2127
+ Number(value),
2128
+ (format == null ? void 0 : format.currency) ?? "USD",
2129
+ (format == null ? void 0 : format.decimals) ?? 2,
2130
+ (format == null ? void 0 : format.locale) ?? "en-US"
2131
+ );
2096
2132
  return /* @__PURE__ */ jsxDevRuntime.jsxDEV("span", { className: "font-mono tabular-nums", children: formatted }, void 0, false, {
2097
2133
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/utils/ui-mapping.tsx",
2098
- lineNumber: 159,
2134
+ lineNumber: 239,
2099
2135
  columnNumber: 12
2100
2136
  }, void 0);
2101
2137
  },
2102
- percent: (value) => {
2103
- const formatted = formatPercent(Number(value));
2138
+ percent: (value, _fieldName, _breakpoint, _item, format) => {
2139
+ const formatted = formatPercent(
2140
+ Number(value),
2141
+ (format == null ? void 0 : format.decimals) ?? 1,
2142
+ (format == null ? void 0 : format.locale) ?? "en-US"
2143
+ );
2104
2144
  return /* @__PURE__ */ jsxDevRuntime.jsxDEV("span", { className: "font-mono tabular-nums", children: formatted }, void 0, false, {
2105
2145
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/utils/ui-mapping.tsx",
2106
- lineNumber: 164,
2146
+ lineNumber: 248,
2107
2147
  columnNumber: 12
2108
2148
  }, void 0);
2109
2149
  },
2110
- date: (value) => {
2111
- const formatted = formatDate(value, false);
2150
+ date: (value, _fieldName, _breakpoint, _item, format) => {
2151
+ const formatted = formatDate(
2152
+ value,
2153
+ false,
2154
+ (format == null ? void 0 : format.locale) ?? "en-US"
2155
+ );
2112
2156
  return /* @__PURE__ */ jsxDevRuntime.jsxDEV("span", { className: "text-muted-foreground", children: formatted }, void 0, false, {
2113
2157
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/utils/ui-mapping.tsx",
2114
- lineNumber: 169,
2158
+ lineNumber: 257,
2115
2159
  columnNumber: 12
2116
2160
  }, void 0);
2117
2161
  },
2118
- datetime: (value) => {
2119
- const formatted = formatDate(value, true);
2162
+ datetime: (value, _fieldName, _breakpoint, _item, format) => {
2163
+ const formatted = formatDate(
2164
+ value,
2165
+ true,
2166
+ (format == null ? void 0 : format.locale) ?? "en-US"
2167
+ );
2120
2168
  return /* @__PURE__ */ jsxDevRuntime.jsxDEV("span", { className: "text-muted-foreground text-sm", children: formatted }, void 0, false, {
2121
2169
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/utils/ui-mapping.tsx",
2122
- lineNumber: 174,
2170
+ lineNumber: 266,
2123
2171
  columnNumber: 12
2124
2172
  }, void 0);
2125
2173
  },
2126
- user: (value, _fieldName, breakpoint, _item) => {
2174
+ user: (value, _fieldName, breakpoint) => {
2127
2175
  const sizeMap2 = {
2128
2176
  xs: "xs",
2129
2177
  sm: "sm",
@@ -2135,31 +2183,31 @@ const defaultFieldRenderers = {
2135
2183
  if (breakpoint === "xs" || breakpoint === "2xs") {
2136
2184
  return /* @__PURE__ */ jsxDevRuntime.jsxDEV(Avatar, { size, fallback: initials }, void 0, false, {
2137
2185
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/utils/ui-mapping.tsx",
2138
- lineNumber: 196,
2186
+ lineNumber: 288,
2139
2187
  columnNumber: 14
2140
2188
  }, void 0);
2141
2189
  }
2142
2190
  return /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "flex items-center gap-2", children: [
2143
2191
  /* @__PURE__ */ jsxDevRuntime.jsxDEV(Avatar, { size, fallback: initials }, void 0, false, {
2144
2192
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/utils/ui-mapping.tsx",
2145
- lineNumber: 202,
2193
+ lineNumber: 294,
2146
2194
  columnNumber: 9
2147
2195
  }, void 0),
2148
2196
  /* @__PURE__ */ jsxDevRuntime.jsxDEV("span", { className: "text-sm", children: String(value) }, void 0, false, {
2149
2197
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/utils/ui-mapping.tsx",
2150
- lineNumber: 203,
2198
+ lineNumber: 295,
2151
2199
  columnNumber: 9
2152
2200
  }, void 0)
2153
2201
  ] }, void 0, true, {
2154
2202
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/utils/ui-mapping.tsx",
2155
- lineNumber: 201,
2203
+ lineNumber: 293,
2156
2204
  columnNumber: 7
2157
2205
  }, void 0);
2158
2206
  },
2159
- entity: (value, fieldName, breakpoint, _item) => {
2207
+ entity: (value, fieldName, breakpoint, _item, format) => {
2160
2208
  const size = getSizeForBreakpoint(breakpoint);
2161
2209
  const showName = breakpoint !== "xs" && breakpoint !== "2xs";
2162
- const type = fieldName.includes("vendor") || fieldName.includes("supplier") ? "vendor" : fieldName.includes("partner") ? "partner" : fieldName.includes("company") || fieldName.includes("organization") ? "company" : "customer";
2210
+ const type = (format == null ? void 0 : format.entityType) ?? (fieldName.includes("vendor") || fieldName.includes("supplier") ? "vendor" : fieldName.includes("partner") ? "partner" : fieldName.includes("company") || fieldName.includes("organization") ? "company" : "customer");
2163
2211
  return /* @__PURE__ */ jsxDevRuntime.jsxDEV(
2164
2212
  EntityIcon,
2165
2213
  {
@@ -2173,20 +2221,20 @@ const defaultFieldRenderers = {
2173
2221
  false,
2174
2222
  {
2175
2223
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/utils/ui-mapping.tsx",
2176
- lineNumber: 223,
2224
+ lineNumber: 316,
2177
2225
  columnNumber: 7
2178
2226
  },
2179
2227
  void 0
2180
2228
  );
2181
2229
  },
2182
- boolean: (value, _fieldName, _breakpoint) => {
2230
+ boolean: (value) => {
2183
2231
  return /* @__PURE__ */ jsxDevRuntime.jsxDEV(Checkbox, { checked: Boolean(value), disabled: true }, void 0, false, {
2184
2232
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/utils/ui-mapping.tsx",
2185
- lineNumber: 234,
2233
+ lineNumber: 327,
2186
2234
  columnNumber: 12
2187
2235
  }, void 0);
2188
2236
  },
2189
- email: (value, _fieldName, _breakpoint) => {
2237
+ email: (value) => {
2190
2238
  return /* @__PURE__ */ jsxDevRuntime.jsxDEV(
2191
2239
  "a",
2192
2240
  {
@@ -2198,13 +2246,13 @@ const defaultFieldRenderers = {
2198
2246
  false,
2199
2247
  {
2200
2248
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/utils/ui-mapping.tsx",
2201
- lineNumber: 239,
2249
+ lineNumber: 332,
2202
2250
  columnNumber: 7
2203
2251
  },
2204
2252
  void 0
2205
2253
  );
2206
2254
  },
2207
- url: (value, _fieldName, _breakpoint) => {
2255
+ url: (value) => {
2208
2256
  const url = String(value);
2209
2257
  const display = url.replace(/^https?:\/\/(www\.)?/, "").split("/")[0];
2210
2258
  return /* @__PURE__ */ jsxDevRuntime.jsxDEV(
@@ -2220,13 +2268,13 @@ const defaultFieldRenderers = {
2220
2268
  false,
2221
2269
  {
2222
2270
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/utils/ui-mapping.tsx",
2223
- lineNumber: 253,
2271
+ lineNumber: 346,
2224
2272
  columnNumber: 7
2225
2273
  },
2226
2274
  void 0
2227
2275
  );
2228
2276
  },
2229
- phone: (value, _fieldName, _breakpoint) => {
2277
+ phone: (value) => {
2230
2278
  const phone = String(value);
2231
2279
  const cleaned = phone.replace(/\D/g, "");
2232
2280
  return /* @__PURE__ */ jsxDevRuntime.jsxDEV(
@@ -2240,40 +2288,111 @@ const defaultFieldRenderers = {
2240
2288
  false,
2241
2289
  {
2242
2290
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/utils/ui-mapping.tsx",
2243
- lineNumber: 269,
2291
+ lineNumber: 362,
2244
2292
  columnNumber: 7
2245
2293
  },
2246
2294
  void 0
2247
2295
  );
2248
2296
  },
2249
- text: (value, _fieldName, _breakpoint) => {
2297
+ text: (value) => {
2250
2298
  return /* @__PURE__ */ jsxDevRuntime.jsxDEV("span", { children: String(value) }, void 0, false, {
2251
2299
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/utils/ui-mapping.tsx",
2252
- lineNumber: 279,
2300
+ lineNumber: 372,
2253
2301
  columnNumber: 12
2254
2302
  }, void 0);
2255
2303
  },
2256
- number: (value, _fieldName, _breakpoint) => {
2257
- const num = Number(value);
2258
- const formatted = num.toLocaleString();
2304
+ number: (value, _fieldName, _breakpoint, _item, format) => {
2305
+ const formatted = formatNumber(
2306
+ Number(value),
2307
+ format == null ? void 0 : format.decimals,
2308
+ (format == null ? void 0 : format.locale) ?? "en-US"
2309
+ );
2259
2310
  return /* @__PURE__ */ jsxDevRuntime.jsxDEV("span", { className: "font-mono tabular-nums", children: formatted }, void 0, false, {
2260
2311
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/utils/ui-mapping.tsx",
2261
- lineNumber: 285,
2312
+ lineNumber: 381,
2313
+ columnNumber: 12
2314
+ }, void 0);
2315
+ },
2316
+ json: (value) => {
2317
+ const str = typeof value === "object" ? JSON.stringify(value, null, 2) : String(value);
2318
+ return /* @__PURE__ */ jsxDevRuntime.jsxDEV("code", { className: "text-xs bg-muted px-1 py-0.5 rounded font-mono", children: str.length > 50 ? str.slice(0, 50) + "..." : str }, void 0, false, {
2319
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/utils/ui-mapping.tsx",
2320
+ lineNumber: 386,
2321
+ columnNumber: 12
2322
+ }, void 0);
2323
+ },
2324
+ image: (value) => {
2325
+ return /* @__PURE__ */ jsxDevRuntime.jsxDEV("img", { src: String(value), alt: "", className: "w-8 h-8 rounded object-cover" }, void 0, false, {
2326
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/utils/ui-mapping.tsx",
2327
+ lineNumber: 390,
2262
2328
  columnNumber: 12
2263
2329
  }, void 0);
2330
+ },
2331
+ rating: (value, _fieldName, _breakpoint, _item, format) => {
2332
+ const max = (format == null ? void 0 : format.max) ?? 5;
2333
+ const filled = Math.round(Number(value));
2334
+ return (
2335
+ // eslint-disable-next-line design-system/no-hardcoded-colors -- amber is standard for star ratings
2336
+ /* @__PURE__ */ jsxDevRuntime.jsxDEV("span", { className: "text-amber-500", children: [
2337
+ "★".repeat(Math.min(filled, max)),
2338
+ "☆".repeat(Math.max(0, max - filled))
2339
+ ] }, void 0, true, {
2340
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/utils/ui-mapping.tsx",
2341
+ lineNumber: 398,
2342
+ columnNumber: 7
2343
+ }, void 0)
2344
+ );
2345
+ },
2346
+ color: (value) => {
2347
+ return /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "flex items-center gap-2", children: [
2348
+ /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "w-4 h-4 rounded border", style: { backgroundColor: String(value) } }, void 0, false, {
2349
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/utils/ui-mapping.tsx",
2350
+ lineNumber: 407,
2351
+ columnNumber: 9
2352
+ }, void 0),
2353
+ /* @__PURE__ */ jsxDevRuntime.jsxDEV("span", { className: "text-xs font-mono", children: String(value) }, void 0, false, {
2354
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/utils/ui-mapping.tsx",
2355
+ lineNumber: 408,
2356
+ columnNumber: 9
2357
+ }, void 0)
2358
+ ] }, void 0, true, {
2359
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/utils/ui-mapping.tsx",
2360
+ lineNumber: 406,
2361
+ columnNumber: 7
2362
+ }, void 0);
2363
+ },
2364
+ file: (value, _fieldName, _breakpoint, item) => {
2365
+ const filename = (item == null ? void 0 : item.filename) ?? String(value).split("/").pop() ?? "file";
2366
+ return /* @__PURE__ */ jsxDevRuntime.jsxDEV("a", { href: String(value), className: "flex items-center gap-1 text-primary hover:underline", children: [
2367
+ /* @__PURE__ */ jsxDevRuntime.jsxDEV(lucideReact.File, { className: "w-4 h-4" }, void 0, false, {
2368
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/utils/ui-mapping.tsx",
2369
+ lineNumber: 417,
2370
+ columnNumber: 9
2371
+ }, void 0),
2372
+ /* @__PURE__ */ jsxDevRuntime.jsxDEV("span", { className: "text-sm truncate max-w-[150px]", children: filename }, void 0, false, {
2373
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/utils/ui-mapping.tsx",
2374
+ lineNumber: 418,
2375
+ columnNumber: 9
2376
+ }, void 0)
2377
+ ] }, void 0, true, {
2378
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/utils/ui-mapping.tsx",
2379
+ lineNumber: 416,
2380
+ columnNumber: 7
2381
+ }, void 0);
2264
2382
  }
2265
2383
  };
2266
- function renderField(value, fieldName, fieldType, breakpoint, item, customRenderers) {
2267
- const renderer = (customRenderers == null ? void 0 : customRenderers[fieldType]) || defaultFieldRenderers[fieldType];
2384
+ function renderField(value, fieldName, fieldType, breakpoint, item, customRenderers, format) {
2385
+ const normalizedType = normalizeFieldType(fieldType);
2386
+ const renderer = (customRenderers == null ? void 0 : customRenderers[normalizedType]) || defaultFieldRenderers[normalizedType];
2268
2387
  if (!renderer) {
2269
- console.warn(`No renderer found for field type: ${fieldType}`);
2388
+ console.warn(`No renderer found for field type: ${fieldType} (normalized: ${normalizedType})`);
2270
2389
  return /* @__PURE__ */ jsxDevRuntime.jsxDEV("span", { children: String(value) }, void 0, false, {
2271
2390
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/utils/ui-mapping.tsx",
2272
- lineNumber: 306,
2391
+ lineNumber: 443,
2273
2392
  columnNumber: 12
2274
2393
  }, this);
2275
2394
  }
2276
- return renderer(value, fieldName, breakpoint, item);
2395
+ return renderer(value, fieldName, breakpoint, item, format);
2277
2396
  }
2278
2397
  function cn(...inputs) {
2279
2398
  return tailwindMerge.twMerge(clsx.clsx(inputs));
@@ -2490,6 +2609,149 @@ function useHealth() {
2490
2609
  retry: 2
2491
2610
  });
2492
2611
  }
2612
+ function useFieldMetadata({
2613
+ entity,
2614
+ view = "list",
2615
+ enabled = true
2616
+ }) {
2617
+ return reactQuery.useQuery({
2618
+ queryKey: ["metadata", entity, view],
2619
+ queryFn: async () => {
2620
+ const response = await fetch(`/api/v1/${entity}/metadata?view=${view}`);
2621
+ if (!response.ok) {
2622
+ throw new Error(`Failed to fetch metadata for ${entity}`);
2623
+ }
2624
+ return response.json();
2625
+ },
2626
+ enabled,
2627
+ staleTime: 1e3 * 60 * 30
2628
+ // 30 minutes - metadata rarely changes
2629
+ });
2630
+ }
2631
+ function useResponsiveTable(options = {}) {
2632
+ const {
2633
+ initialView = "full",
2634
+ autoSwitch = true,
2635
+ minWidthForCompact = 400,
2636
+ debounceMs = 100,
2637
+ onViewChange
2638
+ } = options;
2639
+ const [viewMode, setViewModeState] = React.useState(initialView);
2640
+ const [isAutoSwitching, setIsAutoSwitching] = React.useState(autoSwitch);
2641
+ const [overflowState, setOverflowState] = React.useState({
2642
+ fullOverflows: false,
2643
+ compactOverflows: false
2644
+ });
2645
+ const fullTableRef = React.useRef(null);
2646
+ const compactTableRef = React.useRef(null);
2647
+ const debounceTimerRef = React.useRef(null);
2648
+ const isTransitioningRef = React.useRef(false);
2649
+ const hasOverflow = React.useCallback((element) => {
2650
+ if (!element) return false;
2651
+ return element.scrollWidth > element.clientWidth + 2;
2652
+ }, []);
2653
+ const determineView = React.useCallback(() => {
2654
+ var _a, _b, _c, _d;
2655
+ const containerWidth = ((_b = (_a = fullTableRef.current) == null ? void 0 : _a.parentElement) == null ? void 0 : _b.clientWidth) || ((_d = (_c = compactTableRef.current) == null ? void 0 : _c.parentElement) == null ? void 0 : _d.clientWidth) || window.innerWidth;
2656
+ if (containerWidth < minWidthForCompact) {
2657
+ return "cards";
2658
+ }
2659
+ const fullOverflows = hasOverflow(fullTableRef.current);
2660
+ const compactOverflows = hasOverflow(compactTableRef.current);
2661
+ setOverflowState({ fullOverflows, compactOverflows });
2662
+ if (!fullOverflows) {
2663
+ return "full";
2664
+ }
2665
+ if (!compactOverflows) {
2666
+ return "compact";
2667
+ }
2668
+ return "cards";
2669
+ }, [hasOverflow, minWidthForCompact]);
2670
+ const checkAndUpdate = React.useCallback(() => {
2671
+ if (!isAutoSwitching || isTransitioningRef.current) return;
2672
+ if (debounceTimerRef.current) {
2673
+ clearTimeout(debounceTimerRef.current);
2674
+ }
2675
+ debounceTimerRef.current = setTimeout(() => {
2676
+ const newView = determineView();
2677
+ if (newView !== viewMode) {
2678
+ isTransitioningRef.current = true;
2679
+ setViewModeState(newView);
2680
+ onViewChange == null ? void 0 : onViewChange(newView);
2681
+ setTimeout(() => {
2682
+ isTransitioningRef.current = false;
2683
+ }, 50);
2684
+ }
2685
+ }, debounceMs);
2686
+ }, [isAutoSwitching, determineView, viewMode, debounceMs, onViewChange]);
2687
+ const setViewMode = React.useCallback(
2688
+ (mode) => {
2689
+ setIsAutoSwitching(false);
2690
+ setViewModeState(mode);
2691
+ onViewChange == null ? void 0 : onViewChange(mode);
2692
+ },
2693
+ [onViewChange]
2694
+ );
2695
+ const enableAutoSwitch = React.useCallback(() => {
2696
+ setIsAutoSwitching(true);
2697
+ }, []);
2698
+ React.useEffect(() => {
2699
+ var _a, _b;
2700
+ if (!isAutoSwitching) return;
2701
+ const initialCheckTimer = setTimeout(checkAndUpdate, 50);
2702
+ const resizeObserver = new ResizeObserver(() => {
2703
+ checkAndUpdate();
2704
+ });
2705
+ if (fullTableRef.current) {
2706
+ resizeObserver.observe(fullTableRef.current);
2707
+ }
2708
+ if (compactTableRef.current) {
2709
+ resizeObserver.observe(compactTableRef.current);
2710
+ }
2711
+ const parent = ((_a = fullTableRef.current) == null ? void 0 : _a.parentElement) || ((_b = compactTableRef.current) == null ? void 0 : _b.parentElement);
2712
+ if (parent) {
2713
+ resizeObserver.observe(parent);
2714
+ }
2715
+ window.addEventListener("resize", checkAndUpdate);
2716
+ return () => {
2717
+ clearTimeout(initialCheckTimer);
2718
+ if (debounceTimerRef.current) {
2719
+ clearTimeout(debounceTimerRef.current);
2720
+ }
2721
+ resizeObserver.disconnect();
2722
+ window.removeEventListener("resize", checkAndUpdate);
2723
+ };
2724
+ }, [isAutoSwitching, checkAndUpdate]);
2725
+ React.useEffect(() => {
2726
+ if (!isAutoSwitching) return;
2727
+ const timer = setTimeout(checkAndUpdate, 100);
2728
+ return () => clearTimeout(timer);
2729
+ }, [viewMode, isAutoSwitching, checkAndUpdate]);
2730
+ return {
2731
+ viewMode,
2732
+ setViewMode,
2733
+ enableAutoSwitch,
2734
+ isAutoSwitching,
2735
+ fullTableRef,
2736
+ compactTableRef,
2737
+ overflowState
2738
+ };
2739
+ }
2740
+ function useOverflowDetection(ref) {
2741
+ const [hasOverflow, setHasOverflow] = React.useState(false);
2742
+ React.useEffect(() => {
2743
+ const element = ref.current;
2744
+ if (!element) return;
2745
+ const checkOverflow = () => {
2746
+ setHasOverflow(element.scrollWidth > element.clientWidth + 2);
2747
+ };
2748
+ checkOverflow();
2749
+ const observer = new ResizeObserver(checkOverflow);
2750
+ observer.observe(element);
2751
+ return () => observer.disconnect();
2752
+ }, [ref]);
2753
+ return hasOverflow;
2754
+ }
2493
2755
  const buttonVariants = classVarianceAuthority.cva(
2494
2756
  "inline-flex items-center justify-center whitespace-nowrap rounded-lg text-sm font-medium ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/20 focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-50 active:scale-[0.98]",
2495
2757
  {
@@ -5362,6 +5624,25 @@ function DataTable({
5362
5624
  }
5363
5625
  const value = item[column.key];
5364
5626
  const fieldName = column.key;
5627
+ if (value === null || value === void 0) {
5628
+ return /* @__PURE__ */ jsxDevRuntime.jsxDEV("span", { className: "text-muted-foreground", children: "—" }, void 0, false, {
5629
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5630
+ lineNumber: 179,
5631
+ columnNumber: 14
5632
+ }, this);
5633
+ }
5634
+ if (column.type) {
5635
+ return renderField(
5636
+ value,
5637
+ fieldName,
5638
+ column.type,
5639
+ currentBreakpoint,
5640
+ item,
5641
+ void 0,
5642
+ // customRenderers
5643
+ column.format
5644
+ );
5645
+ }
5365
5646
  const fieldType = getFieldType(fieldName, value, effectiveUI);
5366
5647
  return renderField(value, fieldName, fieldType, currentBreakpoint, item);
5367
5648
  };
@@ -5374,99 +5655,99 @@ function DataTable({
5374
5655
  children: [
5375
5656
  showSearch && /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "relative flex-1 max-w-sm", children: /* @__PURE__ */ jsxDevRuntime.jsxDEV(Skeleton$1, { className: "h-10 w-full" }, void 0, false, {
5376
5657
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5377
- lineNumber: 195,
5658
+ lineNumber: 213,
5378
5659
  columnNumber: 15
5379
5660
  }, this) }, void 0, false, {
5380
5661
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5381
- lineNumber: 194,
5662
+ lineNumber: 212,
5382
5663
  columnNumber: 13
5383
5664
  }, this) }, void 0, false, {
5384
5665
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5385
- lineNumber: 193,
5666
+ lineNumber: 211,
5386
5667
  columnNumber: 11
5387
5668
  }, this),
5388
5669
  /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "rounded border overflow-hidden", children: /* @__PURE__ */ jsxDevRuntime.jsxDEV(Table$1, { children: [
5389
5670
  /* @__PURE__ */ jsxDevRuntime.jsxDEV(TableHeader$1, { children: /* @__PURE__ */ jsxDevRuntime.jsxDEV(TableRow$1, { children: visibleColumns.map((column) => /* @__PURE__ */ jsxDevRuntime.jsxDEV(TableHead$1, { style: { width: column.width }, children: /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxDevRuntime.jsxDEV(Skeleton$1, { className: "h-4 w-20" }, void 0, false, {
5390
5671
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5391
- lineNumber: 208,
5672
+ lineNumber: 226,
5392
5673
  columnNumber: 23
5393
5674
  }, this) }, void 0, false, {
5394
5675
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5395
- lineNumber: 207,
5676
+ lineNumber: 225,
5396
5677
  columnNumber: 21
5397
5678
  }, this) }, column.key, false, {
5398
5679
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5399
- lineNumber: 206,
5680
+ lineNumber: 224,
5400
5681
  columnNumber: 19
5401
5682
  }, this)) }, void 0, false, {
5402
5683
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5403
- lineNumber: 204,
5684
+ lineNumber: 222,
5404
5685
  columnNumber: 15
5405
5686
  }, this) }, void 0, false, {
5406
5687
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5407
- lineNumber: 203,
5688
+ lineNumber: 221,
5408
5689
  columnNumber: 13
5409
5690
  }, this),
5410
5691
  /* @__PURE__ */ jsxDevRuntime.jsxDEV(TableBody$1, { children: Array.from({ length: loadingItemCount }, (_, index) => /* @__PURE__ */ jsxDevRuntime.jsxDEV(TableRow$1, { children: visibleColumns.map((column) => /* @__PURE__ */ jsxDevRuntime.jsxDEV(TableCell$1, { children: /* @__PURE__ */ jsxDevRuntime.jsxDEV(Skeleton$1, { className: "h-4 w-full max-w-32" }, void 0, false, {
5411
5692
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5412
- lineNumber: 219,
5693
+ lineNumber: 237,
5413
5694
  columnNumber: 23
5414
5695
  }, this) }, column.key, false, {
5415
5696
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5416
- lineNumber: 218,
5697
+ lineNumber: 236,
5417
5698
  columnNumber: 21
5418
5699
  }, this)) }, index, false, {
5419
5700
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5420
- lineNumber: 216,
5701
+ lineNumber: 234,
5421
5702
  columnNumber: 17
5422
5703
  }, this)) }, void 0, false, {
5423
5704
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5424
- lineNumber: 214,
5705
+ lineNumber: 232,
5425
5706
  columnNumber: 13
5426
5707
  }, this)
5427
5708
  ] }, void 0, true, {
5428
5709
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5429
- lineNumber: 202,
5710
+ lineNumber: 220,
5430
5711
  columnNumber: 11
5431
5712
  }, this) }, void 0, false, {
5432
5713
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5433
- lineNumber: 201,
5714
+ lineNumber: 219,
5434
5715
  columnNumber: 9
5435
5716
  }, this),
5436
5717
  showPagination && /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "flex items-center justify-between", children: [
5437
5718
  /* @__PURE__ */ jsxDevRuntime.jsxDEV(Skeleton$1, { className: "h-4 w-48" }, void 0, false, {
5438
5719
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5439
- lineNumber: 231,
5720
+ lineNumber: 249,
5440
5721
  columnNumber: 13
5441
5722
  }, this),
5442
5723
  /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "flex items-center gap-2", children: [
5443
5724
  /* @__PURE__ */ jsxDevRuntime.jsxDEV(Skeleton$1, { className: "h-8 w-20" }, void 0, false, {
5444
5725
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5445
- lineNumber: 233,
5726
+ lineNumber: 251,
5446
5727
  columnNumber: 15
5447
5728
  }, this),
5448
5729
  /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "flex items-center gap-1", children: Array.from({ length: 3 }, (_, i) => /* @__PURE__ */ jsxDevRuntime.jsxDEV(Skeleton$1, { className: "h-8 w-8" }, i, false, {
5449
5730
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5450
- lineNumber: 236,
5731
+ lineNumber: 254,
5451
5732
  columnNumber: 19
5452
5733
  }, this)) }, void 0, false, {
5453
5734
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5454
- lineNumber: 234,
5735
+ lineNumber: 252,
5455
5736
  columnNumber: 15
5456
5737
  }, this),
5457
5738
  /* @__PURE__ */ jsxDevRuntime.jsxDEV(Skeleton$1, { className: "h-8 w-16" }, void 0, false, {
5458
5739
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5459
- lineNumber: 239,
5740
+ lineNumber: 257,
5460
5741
  columnNumber: 15
5461
5742
  }, this)
5462
5743
  ] }, void 0, true, {
5463
5744
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5464
- lineNumber: 232,
5745
+ lineNumber: 250,
5465
5746
  columnNumber: 13
5466
5747
  }, this)
5467
5748
  ] }, void 0, true, {
5468
5749
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5469
- lineNumber: 230,
5750
+ lineNumber: 248,
5470
5751
  columnNumber: 11
5471
5752
  }, this)
5472
5753
  ]
@@ -5475,7 +5756,7 @@ function DataTable({
5475
5756
  true,
5476
5757
  {
5477
5758
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5478
- lineNumber: 187,
5759
+ lineNumber: 205,
5479
5760
  columnNumber: 7
5480
5761
  },
5481
5762
  this
@@ -5494,7 +5775,7 @@ function DataTable({
5494
5775
  false,
5495
5776
  {
5496
5777
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5497
- lineNumber: 253,
5778
+ lineNumber: 271,
5498
5779
  columnNumber: 13
5499
5780
  },
5500
5781
  this
@@ -5515,7 +5796,7 @@ function DataTable({
5515
5796
  false,
5516
5797
  {
5517
5798
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5518
- lineNumber: 257,
5799
+ lineNumber: 275,
5519
5800
  columnNumber: 13
5520
5801
  },
5521
5802
  this
@@ -5533,7 +5814,7 @@ function DataTable({
5533
5814
  "aria-label": tooltipContent.clearSearch,
5534
5815
  children: /* @__PURE__ */ jsxDevRuntime.jsxDEV(lucideReact.X, { className: "w-4 h-4", "data-component-name": "DataTableClear" }, void 0, false, {
5535
5816
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5536
- lineNumber: 278,
5817
+ lineNumber: 296,
5537
5818
  columnNumber: 17
5538
5819
  }, this)
5539
5820
  },
@@ -5541,14 +5822,14 @@ function DataTable({
5541
5822
  false,
5542
5823
  {
5543
5824
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5544
- lineNumber: 268,
5825
+ lineNumber: 286,
5545
5826
  columnNumber: 15
5546
5827
  },
5547
5828
  this
5548
5829
  )
5549
5830
  ] }, void 0, true, {
5550
5831
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5551
- lineNumber: 252,
5832
+ lineNumber: 270,
5552
5833
  columnNumber: 11
5553
5834
  }, this),
5554
5835
  searchTerm && /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "text-muted-foreground text-sm", children: [
@@ -5557,12 +5838,12 @@ function DataTable({
5557
5838
  sortedData.length !== 1 ? "s" : ""
5558
5839
  ] }, void 0, true, {
5559
5840
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5560
- lineNumber: 283,
5841
+ lineNumber: 301,
5561
5842
  columnNumber: 13
5562
5843
  }, this)
5563
5844
  ] }, void 0, true, {
5564
5845
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5565
- lineNumber: 251,
5846
+ lineNumber: 269,
5566
5847
  columnNumber: 9
5567
5848
  }, this),
5568
5849
  renderMobileCard && isMobile ? /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { children: renderMobileCard({
@@ -5570,7 +5851,7 @@ function DataTable({
5570
5851
  onItemClick: onRowClick
5571
5852
  }) }, void 0, false, {
5572
5853
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5573
- lineNumber: 292,
5854
+ lineNumber: 310,
5574
5855
  columnNumber: 9
5575
5856
  }, this) : /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "rounded border overflow-hidden", children: /* @__PURE__ */ jsxDevRuntime.jsxDEV(Table$1, { children: [
5576
5857
  /* @__PURE__ */ jsxDevRuntime.jsxDEV(TableHeader$1, { children: /* @__PURE__ */ jsxDevRuntime.jsxDEV(TableRow$1, { children: visibleColumns.map((column) => {
@@ -5588,17 +5869,17 @@ function DataTable({
5588
5869
  children: /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "flex items-center gap-1 xs:gap-2", children: typeof column.header === "string" ? /* @__PURE__ */ jsxDevRuntime.jsxDEV(jsxDevRuntime.Fragment, { children: [
5589
5870
  /* @__PURE__ */ jsxDevRuntime.jsxDEV("span", { className: "truncate", children: column.header }, void 0, false, {
5590
5871
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5591
- lineNumber: 328,
5872
+ lineNumber: 346,
5592
5873
  columnNumber: 29
5593
5874
  }, this),
5594
5875
  column.sortable !== false && getSortIcon(column.key)
5595
5876
  ] }, void 0, true, {
5596
5877
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5597
- lineNumber: 327,
5878
+ lineNumber: 345,
5598
5879
  columnNumber: 27
5599
5880
  }, this) : column.header }, void 0, false, {
5600
5881
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5601
- lineNumber: 325,
5882
+ lineNumber: 343,
5602
5883
  columnNumber: 23
5603
5884
  }, this)
5604
5885
  },
@@ -5606,18 +5887,18 @@ function DataTable({
5606
5887
  false,
5607
5888
  {
5608
5889
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5609
- lineNumber: 308,
5890
+ lineNumber: 326,
5610
5891
  columnNumber: 21
5611
5892
  },
5612
5893
  this
5613
5894
  );
5614
5895
  }) }, void 0, false, {
5615
5896
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5616
- lineNumber: 302,
5897
+ lineNumber: 320,
5617
5898
  columnNumber: 15
5618
5899
  }, this) }, void 0, false, {
5619
5900
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5620
- lineNumber: 301,
5901
+ lineNumber: 319,
5621
5902
  columnNumber: 13
5622
5903
  }, this),
5623
5904
  /* @__PURE__ */ jsxDevRuntime.jsxDEV(TableBody$1, { children: paginatedData.length === 0 ? /* @__PURE__ */ jsxDevRuntime.jsxDEV(TableRow$1, { children: /* @__PURE__ */ jsxDevRuntime.jsxDEV(
@@ -5631,13 +5912,13 @@ function DataTable({
5631
5912
  false,
5632
5913
  {
5633
5914
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5634
- lineNumber: 344,
5915
+ lineNumber: 362,
5635
5916
  columnNumber: 19
5636
5917
  },
5637
5918
  this
5638
5919
  ) }, void 0, false, {
5639
5920
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5640
- lineNumber: 343,
5921
+ lineNumber: 361,
5641
5922
  columnNumber: 17
5642
5923
  }, this) : paginatedData.map((item, index) => /* @__PURE__ */ jsxDevRuntime.jsxDEV(
5643
5924
  TableRow$1,
@@ -5649,7 +5930,7 @@ function DataTable({
5649
5930
  onClick: () => onRowClick == null ? void 0 : onRowClick(item),
5650
5931
  children: visibleColumns.map((column) => /* @__PURE__ */ jsxDevRuntime.jsxDEV(TableCell$1, { children: renderCell(column, item) }, column.key, false, {
5651
5932
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5652
- lineNumber: 362,
5933
+ lineNumber: 380,
5653
5934
  columnNumber: 23
5654
5935
  }, this))
5655
5936
  },
@@ -5657,22 +5938,22 @@ function DataTable({
5657
5938
  false,
5658
5939
  {
5659
5940
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5660
- lineNumber: 353,
5941
+ lineNumber: 371,
5661
5942
  columnNumber: 19
5662
5943
  },
5663
5944
  this
5664
5945
  )) }, void 0, false, {
5665
5946
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5666
- lineNumber: 341,
5947
+ lineNumber: 359,
5667
5948
  columnNumber: 13
5668
5949
  }, this)
5669
5950
  ] }, void 0, true, {
5670
5951
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5671
- lineNumber: 300,
5952
+ lineNumber: 318,
5672
5953
  columnNumber: 11
5673
5954
  }, this) }, void 0, false, {
5674
5955
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5675
- lineNumber: 299,
5956
+ lineNumber: 317,
5676
5957
  columnNumber: 9
5677
5958
  }, this),
5678
5959
  showPagination && totalPages > 1 && /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "flex items-center justify-between", children: [
@@ -5688,7 +5969,7 @@ function DataTable({
5688
5969
  " entries"
5689
5970
  ] }, void 0, true, {
5690
5971
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5691
- lineNumber: 377,
5972
+ lineNumber: 395,
5692
5973
  columnNumber: 11
5693
5974
  }, this),
5694
5975
  /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "flex items-center gap-2", children: [
@@ -5706,7 +5987,7 @@ function DataTable({
5706
5987
  false,
5707
5988
  {
5708
5989
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5709
- lineNumber: 383,
5990
+ lineNumber: 401,
5710
5991
  columnNumber: 13
5711
5992
  },
5712
5993
  this
@@ -5735,14 +6016,14 @@ function DataTable({
5735
6016
  false,
5736
6017
  {
5737
6018
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5738
- lineNumber: 406,
6019
+ lineNumber: 424,
5739
6020
  columnNumber: 19
5740
6021
  },
5741
6022
  this
5742
6023
  );
5743
6024
  }) }, void 0, false, {
5744
6025
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5745
- lineNumber: 392,
6026
+ lineNumber: 410,
5746
6027
  columnNumber: 13
5747
6028
  }, this),
5748
6029
  /* @__PURE__ */ jsxDevRuntime.jsxDEV(
@@ -5759,24 +6040,24 @@ function DataTable({
5759
6040
  false,
5760
6041
  {
5761
6042
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5762
- lineNumber: 418,
6043
+ lineNumber: 436,
5763
6044
  columnNumber: 13
5764
6045
  },
5765
6046
  this
5766
6047
  )
5767
6048
  ] }, void 0, true, {
5768
6049
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5769
- lineNumber: 382,
6050
+ lineNumber: 400,
5770
6051
  columnNumber: 11
5771
6052
  }, this)
5772
6053
  ] }, void 0, true, {
5773
6054
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5774
- lineNumber: 376,
6055
+ lineNumber: 394,
5775
6056
  columnNumber: 9
5776
6057
  }, this)
5777
6058
  ] }, void 0, true, {
5778
6059
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/components/data/DataTable/DataTable.tsx",
5779
- lineNumber: 248,
6060
+ lineNumber: 266,
5780
6061
  columnNumber: 5
5781
6062
  }, this);
5782
6063
  }
@@ -13984,6 +14265,98 @@ const SectionHeader = ({
13984
14265
  void 0
13985
14266
  );
13986
14267
  };
14268
+ const PageTitle = ({
14269
+ children,
14270
+ icon,
14271
+ actions,
14272
+ size = "lg",
14273
+ className,
14274
+ as: Component = "h1"
14275
+ }) => {
14276
+ const titleSizes = {
14277
+ sm: "text-xl",
14278
+ md: "text-2xl",
14279
+ lg: "text-3xl",
14280
+ xl: "text-4xl"
14281
+ };
14282
+ const iconSizes = {
14283
+ sm: "h-5 w-5",
14284
+ md: "h-6 w-6",
14285
+ lg: "h-7 w-7",
14286
+ xl: "h-8 w-8"
14287
+ };
14288
+ const gapSizes = {
14289
+ sm: "gap-2",
14290
+ md: "gap-2.5",
14291
+ lg: "gap-3",
14292
+ xl: "gap-4"
14293
+ };
14294
+ return /* @__PURE__ */ jsxDevRuntime.jsxDEV(
14295
+ "div",
14296
+ {
14297
+ className: cn(
14298
+ "flex items-center justify-between",
14299
+ gapSizes[size],
14300
+ className
14301
+ ),
14302
+ "data-component-name": "PageTitle",
14303
+ children: [
14304
+ /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: cn("flex items-center", gapSizes[size]), children: [
14305
+ icon && /* @__PURE__ */ jsxDevRuntime.jsxDEV(
14306
+ "div",
14307
+ {
14308
+ className: cn(
14309
+ "flex items-center justify-center text-foreground",
14310
+ iconSizes[size]
14311
+ ),
14312
+ children: icon
14313
+ },
14314
+ void 0,
14315
+ false,
14316
+ {
14317
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/molecules/layout/PageTitle/PageTitle.tsx",
14318
+ lineNumber: 59,
14319
+ columnNumber: 11
14320
+ },
14321
+ void 0
14322
+ ),
14323
+ /* @__PURE__ */ jsxDevRuntime.jsxDEV(
14324
+ Component,
14325
+ {
14326
+ className: cn("font-semibold text-foreground", titleSizes[size]),
14327
+ children
14328
+ },
14329
+ void 0,
14330
+ false,
14331
+ {
14332
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/molecules/layout/PageTitle/PageTitle.tsx",
14333
+ lineNumber: 68,
14334
+ columnNumber: 9
14335
+ },
14336
+ void 0
14337
+ )
14338
+ ] }, void 0, true, {
14339
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/molecules/layout/PageTitle/PageTitle.tsx",
14340
+ lineNumber: 57,
14341
+ columnNumber: 7
14342
+ }, void 0),
14343
+ actions && /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "flex items-center gap-2", children: actions }, void 0, false, {
14344
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/molecules/layout/PageTitle/PageTitle.tsx",
14345
+ lineNumber: 75,
14346
+ columnNumber: 19
14347
+ }, void 0)
14348
+ ]
14349
+ },
14350
+ void 0,
14351
+ true,
14352
+ {
14353
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/molecules/layout/PageTitle/PageTitle.tsx",
14354
+ lineNumber: 49,
14355
+ columnNumber: 5
14356
+ },
14357
+ void 0
14358
+ );
14359
+ };
13987
14360
  const SidebarProvider = ({
13988
14361
  children
13989
14362
  }) => {
@@ -14192,6 +14565,56 @@ const BulkSelectionBar = ({
14192
14565
  void 0
14193
14566
  );
14194
14567
  };
14568
+ const ListToolbar = ({
14569
+ search,
14570
+ buttons,
14571
+ primaryAction,
14572
+ className,
14573
+ gap = "md"
14574
+ }) => {
14575
+ const gapSizes = {
14576
+ sm: "gap-2",
14577
+ md: "gap-4",
14578
+ lg: "gap-6"
14579
+ };
14580
+ return /* @__PURE__ */ jsxDevRuntime.jsxDEV(
14581
+ "div",
14582
+ {
14583
+ className: cn("flex items-center", gapSizes[gap], className),
14584
+ "data-component-name": "ListToolbar",
14585
+ children: [
14586
+ search && /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "flex-shrink-0", children: search }, void 0, false, {
14587
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/molecules/layout/ListToolbar/ListToolbar.tsx",
14588
+ lineNumber: 58,
14589
+ columnNumber: 18
14590
+ }, void 0),
14591
+ buttons && /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: cn("flex items-center", gapSizes[gap === "lg" ? "md" : "sm"]), children: buttons }, void 0, false, {
14592
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/molecules/layout/ListToolbar/ListToolbar.tsx",
14593
+ lineNumber: 62,
14594
+ columnNumber: 9
14595
+ }, void 0),
14596
+ primaryAction && /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "flex-grow" }, void 0, false, {
14597
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/molecules/layout/ListToolbar/ListToolbar.tsx",
14598
+ lineNumber: 68,
14599
+ columnNumber: 25
14600
+ }, void 0),
14601
+ primaryAction && /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "flex-shrink-0", children: primaryAction }, void 0, false, {
14602
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/molecules/layout/ListToolbar/ListToolbar.tsx",
14603
+ lineNumber: 71,
14604
+ columnNumber: 25
14605
+ }, void 0)
14606
+ ]
14607
+ },
14608
+ void 0,
14609
+ true,
14610
+ {
14611
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/molecules/layout/ListToolbar/ListToolbar.tsx",
14612
+ lineNumber: 53,
14613
+ columnNumber: 5
14614
+ },
14615
+ void 0
14616
+ );
14617
+ };
14195
14618
  const Pagination = ({
14196
14619
  currentPage,
14197
14620
  totalPages,
@@ -15578,11 +16001,21 @@ class AuthService {
15578
16001
  this.removeItem("user");
15579
16002
  }
15580
16003
  async login(credentials) {
15581
- const response = await apiClient.post(
15582
- `${this.config.apiUrl}${this.config.endpoints.login}`,
15583
- credentials
15584
- );
15585
- const { token, refreshToken, user, expiresIn } = response;
16004
+ const response = await apiClient.post(`${this.config.apiUrl}${this.config.endpoints.login}`, credentials);
16005
+ let token;
16006
+ let refreshToken;
16007
+ let expiresIn;
16008
+ if ("access_token" in response) {
16009
+ const backendResponse = response;
16010
+ token = backendResponse.access_token;
16011
+ refreshToken = backendResponse.refresh_token;
16012
+ } else {
16013
+ const oldResponse = response;
16014
+ token = oldResponse.token;
16015
+ refreshToken = oldResponse.refreshToken;
16016
+ expiresIn = oldResponse.expiresIn;
16017
+ }
16018
+ const user = response.user;
15586
16019
  const expiresAt = expiresIn ? Date.now() + expiresIn * 1e3 : void 0;
15587
16020
  this.setTokenData({ token, refreshToken, expiresAt });
15588
16021
  this.setStoredUser(user);
@@ -15606,17 +16039,28 @@ class AuthService {
15606
16039
  this.refreshPromise = null;
15607
16040
  }
15608
16041
  }
15609
- async performTokenRefresh(refreshToken) {
16042
+ async performTokenRefresh(currentRefreshToken) {
15610
16043
  try {
15611
- const response = await apiClient.post(
15612
- `${this.config.apiUrl}${this.config.endpoints.refresh}`,
15613
- { refreshToken }
15614
- );
15615
- const { token, refreshToken: newRefreshToken, expiresIn } = response;
16044
+ const response = await apiClient.post(`${this.config.apiUrl}${this.config.endpoints.refresh}`, {
16045
+ refresh_token: currentRefreshToken
16046
+ });
16047
+ let token;
16048
+ let newRefreshToken;
16049
+ let expiresIn;
16050
+ if ("access_token" in response) {
16051
+ const backendResponse = response;
16052
+ token = backendResponse.access_token;
16053
+ newRefreshToken = currentRefreshToken;
16054
+ } else {
16055
+ const oldResponse = response;
16056
+ token = oldResponse.token;
16057
+ newRefreshToken = oldResponse.refreshToken;
16058
+ expiresIn = oldResponse.expiresIn;
16059
+ }
15616
16060
  const expiresAt = expiresIn ? Date.now() + expiresIn * 1e3 : void 0;
15617
16061
  this.setTokenData({
15618
16062
  token,
15619
- refreshToken: newRefreshToken || refreshToken,
16063
+ refreshToken: newRefreshToken || currentRefreshToken,
15620
16064
  expiresAt
15621
16065
  });
15622
16066
  if (this.config.autoRefresh && expiresAt) {
@@ -15814,7 +16258,7 @@ function AuthProvider({
15814
16258
  };
15815
16259
  return /* @__PURE__ */ jsxDevRuntime.jsxDEV(AuthContext.Provider, { value, children }, void 0, false, {
15816
16260
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/features/auth/hooks/useAuth.tsx",
15817
- lineNumber: 201,
16261
+ lineNumber: 205,
15818
16262
  columnNumber: 10
15819
16263
  }, this);
15820
16264
  }
@@ -16406,7 +16850,7 @@ const DashboardCard = ({
16406
16850
  category,
16407
16851
  padding = "md"
16408
16852
  }) => {
16409
- const paddingClasses = {
16853
+ const paddingClasses2 = {
16410
16854
  sm: "p-4",
16411
16855
  md: "p-6",
16412
16856
  lg: "p-8"
@@ -16414,7 +16858,7 @@ const DashboardCard = ({
16414
16858
  return /* @__PURE__ */ jsxDevRuntime.jsxDEV(
16415
16859
  Card,
16416
16860
  {
16417
- className: cn(paddingClasses[padding], className),
16861
+ className: cn(paddingClasses2[padding], className),
16418
16862
  category,
16419
16863
  children: [
16420
16864
  (title || description || actions) && /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "mb-4", children: /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "flex items-start justify-between", children: [
@@ -17090,6 +17534,130 @@ const DataDetailTemplate = ({
17090
17534
  columnNumber: 5
17091
17535
  }, void 0);
17092
17536
  };
17537
+ const maxWidthClasses = {
17538
+ sm: "max-w-screen-sm",
17539
+ md: "max-w-screen-md",
17540
+ lg: "max-w-screen-lg",
17541
+ xl: "max-w-screen-xl",
17542
+ "2xl": "max-w-screen-2xl",
17543
+ full: "max-w-full",
17544
+ none: ""
17545
+ };
17546
+ const paddingClasses = {
17547
+ none: "p-0",
17548
+ sm: "p-4",
17549
+ md: "p-6",
17550
+ lg: "p-8"
17551
+ };
17552
+ const ListPageTemplate = ({
17553
+ title,
17554
+ toolbar,
17555
+ children,
17556
+ footer,
17557
+ className,
17558
+ contentClassName,
17559
+ maxWidth = "full",
17560
+ padding = "md"
17561
+ }) => {
17562
+ return /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: cn("flex flex-col min-h-0 flex-1", className), children: [
17563
+ /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "flex-shrink-0 border-b border-border bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60", children: /* @__PURE__ */ jsxDevRuntime.jsxDEV(
17564
+ "div",
17565
+ {
17566
+ className: cn(
17567
+ "mx-auto",
17568
+ maxWidthClasses[maxWidth],
17569
+ paddingClasses[padding]
17570
+ ),
17571
+ children: title
17572
+ },
17573
+ void 0,
17574
+ false,
17575
+ {
17576
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/ListPageTemplate.tsx",
17577
+ lineNumber: 54,
17578
+ columnNumber: 9
17579
+ },
17580
+ void 0
17581
+ ) }, void 0, false, {
17582
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/ListPageTemplate.tsx",
17583
+ lineNumber: 53,
17584
+ columnNumber: 7
17585
+ }, void 0),
17586
+ toolbar && /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "flex-shrink-0 border-b border-border bg-muted/30", children: /* @__PURE__ */ jsxDevRuntime.jsxDEV(
17587
+ "div",
17588
+ {
17589
+ className: cn(
17590
+ "mx-auto",
17591
+ maxWidthClasses[maxWidth],
17592
+ paddingClasses[padding]
17593
+ ),
17594
+ children: toolbar
17595
+ },
17596
+ void 0,
17597
+ false,
17598
+ {
17599
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/ListPageTemplate.tsx",
17600
+ lineNumber: 68,
17601
+ columnNumber: 11
17602
+ },
17603
+ void 0
17604
+ ) }, void 0, false, {
17605
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/ListPageTemplate.tsx",
17606
+ lineNumber: 67,
17607
+ columnNumber: 9
17608
+ }, void 0),
17609
+ /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: cn("flex-1 min-h-0 overflow-auto", contentClassName), children: /* @__PURE__ */ jsxDevRuntime.jsxDEV(
17610
+ "div",
17611
+ {
17612
+ className: cn(
17613
+ "mx-auto h-full",
17614
+ maxWidthClasses[maxWidth],
17615
+ paddingClasses[padding]
17616
+ ),
17617
+ children
17618
+ },
17619
+ void 0,
17620
+ false,
17621
+ {
17622
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/ListPageTemplate.tsx",
17623
+ lineNumber: 82,
17624
+ columnNumber: 9
17625
+ },
17626
+ void 0
17627
+ ) }, void 0, false, {
17628
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/ListPageTemplate.tsx",
17629
+ lineNumber: 81,
17630
+ columnNumber: 7
17631
+ }, void 0),
17632
+ footer && /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "flex-shrink-0 border-t border-border bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60", children: /* @__PURE__ */ jsxDevRuntime.jsxDEV(
17633
+ "div",
17634
+ {
17635
+ className: cn(
17636
+ "mx-auto",
17637
+ maxWidthClasses[maxWidth],
17638
+ paddingClasses[padding]
17639
+ ),
17640
+ children: footer
17641
+ },
17642
+ void 0,
17643
+ false,
17644
+ {
17645
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/ListPageTemplate.tsx",
17646
+ lineNumber: 96,
17647
+ columnNumber: 11
17648
+ },
17649
+ void 0
17650
+ ) }, void 0, false, {
17651
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/ListPageTemplate.tsx",
17652
+ lineNumber: 95,
17653
+ columnNumber: 9
17654
+ }, void 0)
17655
+ ] }, void 0, true, {
17656
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/ListPageTemplate.tsx",
17657
+ lineNumber: 51,
17658
+ columnNumber: 5
17659
+ }, void 0);
17660
+ };
17093
17661
  function debounce(func, wait) {
17094
17662
  let timeout = null;
17095
17663
  return function debounced(...args) {
@@ -19411,16 +19979,16 @@ const AdminCRUDTemplate = ({
19411
19979
  },
19412
19980
  // Data columns
19413
19981
  ...schema.fields.filter((field) => field.showInTable !== false).map((field) => {
19414
- let columnType = "default";
19982
+ let columnType = void 0;
19415
19983
  if (field.type === "boolean" || field.name.toLowerCase().includes("status")) {
19416
19984
  columnType = "status";
19417
19985
  } else if (field.name.toLowerCase().includes("category")) {
19418
- columnType = "category";
19986
+ columnType = "badge";
19419
19987
  }
19420
19988
  return {
19421
19989
  key: field.name,
19422
19990
  header: field.label,
19423
- type: columnType,
19991
+ ...columnType && { type: columnType },
19424
19992
  cell: field.render ? (item) => field.render(item[field.name], item) : void 0,
19425
19993
  sortable: true,
19426
19994
  width: field.width ? `${field.width}px` : void 0
@@ -19443,7 +20011,7 @@ const AdminCRUDTemplate = ({
19443
20011
  tooltip: "View details",
19444
20012
  children: /* @__PURE__ */ jsxDevRuntime.jsxDEV(lucideReact.Eye, { className: "w-4 h-4" }, void 0, false, {
19445
20013
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19446
- lineNumber: 241,
20014
+ lineNumber: 242,
19447
20015
  columnNumber: 13
19448
20016
  }, void 0)
19449
20017
  },
@@ -19451,7 +20019,7 @@ const AdminCRUDTemplate = ({
19451
20019
  false,
19452
20020
  {
19453
20021
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19454
- lineNumber: 232,
20022
+ lineNumber: 233,
19455
20023
  columnNumber: 11
19456
20024
  },
19457
20025
  void 0
@@ -19468,7 +20036,7 @@ const AdminCRUDTemplate = ({
19468
20036
  tooltip: "Edit",
19469
20037
  children: /* @__PURE__ */ jsxDevRuntime.jsxDEV(lucideReact.Edit, { className: "w-4 h-4" }, void 0, false, {
19470
20038
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19471
- lineNumber: 253,
20039
+ lineNumber: 254,
19472
20040
  columnNumber: 15
19473
20041
  }, void 0)
19474
20042
  },
@@ -19476,7 +20044,7 @@ const AdminCRUDTemplate = ({
19476
20044
  false,
19477
20045
  {
19478
20046
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19479
- lineNumber: 244,
20047
+ lineNumber: 245,
19480
20048
  columnNumber: 13
19481
20049
  },
19482
20050
  void 0
@@ -19493,7 +20061,7 @@ const AdminCRUDTemplate = ({
19493
20061
  tooltip: "Delete",
19494
20062
  children: /* @__PURE__ */ jsxDevRuntime.jsxDEV(lucideReact.Trash2, { className: "w-4 h-4" }, void 0, false, {
19495
20063
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19496
- lineNumber: 266,
20064
+ lineNumber: 267,
19497
20065
  columnNumber: 15
19498
20066
  }, void 0)
19499
20067
  },
@@ -19501,14 +20069,14 @@ const AdminCRUDTemplate = ({
19501
20069
  false,
19502
20070
  {
19503
20071
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19504
- lineNumber: 257,
20072
+ lineNumber: 258,
19505
20073
  columnNumber: 13
19506
20074
  },
19507
20075
  void 0
19508
20076
  )
19509
20077
  ] }, void 0, true, {
19510
20078
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19511
- lineNumber: 231,
20079
+ lineNumber: 232,
19512
20080
  columnNumber: 9
19513
20081
  }, void 0),
19514
20082
  sortable: false,
@@ -19583,12 +20151,12 @@ const AdminCRUDTemplate = ({
19583
20151
  field.label
19584
20152
  ] }, void 0, true, {
19585
20153
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19586
- lineNumber: 349,
20154
+ lineNumber: 350,
19587
20155
  columnNumber: 13
19588
20156
  }, void 0),
19589
20157
  (_a2 = field.options) == null ? void 0 : _a2.map((option) => /* @__PURE__ */ jsxDevRuntime.jsxDEV("option", { value: option.value, children: option.label }, option.value, false, {
19590
20158
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19591
- lineNumber: 351,
20159
+ lineNumber: 352,
19592
20160
  columnNumber: 15
19593
20161
  }, void 0))
19594
20162
  ]
@@ -19597,7 +20165,7 @@ const AdminCRUDTemplate = ({
19597
20165
  true,
19598
20166
  {
19599
20167
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19600
- lineNumber: 342,
20168
+ lineNumber: 343,
19601
20169
  columnNumber: 11
19602
20170
  },
19603
20171
  void 0
@@ -19613,7 +20181,7 @@ const AdminCRUDTemplate = ({
19613
20181
  false,
19614
20182
  {
19615
20183
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19616
- lineNumber: 357,
20184
+ lineNumber: 358,
19617
20185
  columnNumber: 11
19618
20186
  },
19619
20187
  void 0
@@ -19632,7 +20200,7 @@ const AdminCRUDTemplate = ({
19632
20200
  false,
19633
20201
  {
19634
20202
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19635
- lineNumber: 366,
20203
+ lineNumber: 367,
19636
20204
  columnNumber: 11
19637
20205
  },
19638
20206
  void 0
@@ -19648,7 +20216,7 @@ const AdminCRUDTemplate = ({
19648
20216
  false,
19649
20217
  {
19650
20218
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19651
- lineNumber: 378,
20219
+ lineNumber: 379,
19652
20220
  columnNumber: 11
19653
20221
  },
19654
20222
  void 0
@@ -19658,7 +20226,7 @@ const AdminCRUDTemplate = ({
19658
20226
  false,
19659
20227
  {
19660
20228
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19661
- lineNumber: 335,
20229
+ lineNumber: 336,
19662
20230
  columnNumber: 7
19663
20231
  },
19664
20232
  void 0
@@ -19675,7 +20243,7 @@ const AdminCRUDTemplate = ({
19675
20243
  size: "lg",
19676
20244
  icon: /* @__PURE__ */ jsxDevRuntime.jsxDEV(lucideReact.Plus, { className: "w-5 h-5" }, void 0, false, {
19677
20245
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19678
- lineNumber: 410,
20246
+ lineNumber: 411,
19679
20247
  columnNumber: 23
19680
20248
  }, void 0)
19681
20249
  },
@@ -19683,7 +20251,7 @@ const AdminCRUDTemplate = ({
19683
20251
  false,
19684
20252
  {
19685
20253
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19686
- lineNumber: 406,
20254
+ lineNumber: 407,
19687
20255
  columnNumber: 15
19688
20256
  },
19689
20257
  void 0
@@ -19691,7 +20259,7 @@ const AdminCRUDTemplate = ({
19691
20259
  /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { children: [
19692
20260
  /* @__PURE__ */ jsxDevRuntime.jsxDEV("h1", { className: "text-4xl font-bold text-foreground", children: schema.displayNamePlural }, void 0, false, {
19693
20261
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19694
- lineNumber: 413,
20262
+ lineNumber: 414,
19695
20263
  columnNumber: 17
19696
20264
  }, void 0),
19697
20265
  /* @__PURE__ */ jsxDevRuntime.jsxDEV("p", { className: "text-lg text-muted-foreground mt-2", children: [
@@ -19700,17 +20268,17 @@ const AdminCRUDTemplate = ({
19700
20268
  " with comprehensive CRUD operations"
19701
20269
  ] }, void 0, true, {
19702
20270
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19703
- lineNumber: 416,
20271
+ lineNumber: 417,
19704
20272
  columnNumber: 17
19705
20273
  }, void 0)
19706
20274
  ] }, void 0, true, {
19707
20275
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19708
- lineNumber: 412,
20276
+ lineNumber: 413,
19709
20277
  columnNumber: 15
19710
20278
  }, void 0)
19711
20279
  ] }, void 0, true, {
19712
20280
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19713
- lineNumber: 405,
20281
+ lineNumber: 406,
19714
20282
  columnNumber: 13
19715
20283
  }, void 0),
19716
20284
  /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "flex items-center gap-2", children: [
@@ -19730,7 +20298,7 @@ const AdminCRUDTemplate = ({
19730
20298
  false,
19731
20299
  {
19732
20300
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19733
- lineNumber: 430,
20301
+ lineNumber: 431,
19734
20302
  columnNumber: 19
19735
20303
  },
19736
20304
  void 0
@@ -19742,7 +20310,7 @@ const AdminCRUDTemplate = ({
19742
20310
  true,
19743
20311
  {
19744
20312
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19745
- lineNumber: 425,
20313
+ lineNumber: 426,
19746
20314
  columnNumber: 17
19747
20315
  },
19748
20316
  void 0
@@ -19750,32 +20318,32 @@ const AdminCRUDTemplate = ({
19750
20318
  permissions.create && /* @__PURE__ */ jsxDevRuntime.jsxDEV(Button, { onClick: handleCreate, variant: "default", children: [
19751
20319
  /* @__PURE__ */ jsxDevRuntime.jsxDEV(lucideReact.Plus, { className: "w-4 h-4 mr-2" }, void 0, false, {
19752
20320
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19753
- lineNumber: 439,
20321
+ lineNumber: 440,
19754
20322
  columnNumber: 19
19755
20323
  }, void 0),
19756
20324
  "Create ",
19757
20325
  schema.displayName
19758
20326
  ] }, void 0, true, {
19759
20327
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19760
- lineNumber: 438,
20328
+ lineNumber: 439,
19761
20329
  columnNumber: 17
19762
20330
  }, void 0)
19763
20331
  ] }, void 0, true, {
19764
20332
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19765
- lineNumber: 423,
20333
+ lineNumber: 424,
19766
20334
  columnNumber: 13
19767
20335
  }, void 0)
19768
20336
  ] }, void 0, true, {
19769
20337
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19770
- lineNumber: 404,
20338
+ lineNumber: 405,
19771
20339
  columnNumber: 11
19772
20340
  }, void 0) }, void 0, false, {
19773
20341
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19774
- lineNumber: 403,
20342
+ lineNumber: 404,
19775
20343
  columnNumber: 9
19776
20344
  }, void 0) }, void 0, false, {
19777
20345
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19778
- lineNumber: 402,
20346
+ lineNumber: 403,
19779
20347
  columnNumber: 7
19780
20348
  }, void 0),
19781
20349
  /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "flex-shrink-0 border-b border-border bg-muted/30", children: /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-4", children: /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "flex items-center justify-between", children: [
@@ -19789,13 +20357,13 @@ const AdminCRUDTemplate = ({
19789
20357
  children: [
19790
20358
  /* @__PURE__ */ jsxDevRuntime.jsxDEV(lucideReact.Filter, { className: "w-4 h-4 mr-2" }, void 0, false, {
19791
20359
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19792
- lineNumber: 460,
20360
+ lineNumber: 461,
19793
20361
  columnNumber: 19
19794
20362
  }, void 0),
19795
20363
  "Filters",
19796
20364
  activeFilterCount > 0 && /* @__PURE__ */ jsxDevRuntime.jsxDEV("span", { className: "absolute -top-2 -right-2 min-w-5 h-5 rounded-full text-xs bg-destructive text-destructive-foreground flex items-center justify-center", children: activeFilterCount }, void 0, false, {
19797
20365
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19798
- lineNumber: 463,
20366
+ lineNumber: 464,
19799
20367
  columnNumber: 21
19800
20368
  }, void 0)
19801
20369
  ]
@@ -19804,7 +20372,7 @@ const AdminCRUDTemplate = ({
19804
20372
  true,
19805
20373
  {
19806
20374
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19807
- lineNumber: 455,
20375
+ lineNumber: 456,
19808
20376
  columnNumber: 17
19809
20377
  },
19810
20378
  void 0
@@ -19826,7 +20394,7 @@ const AdminCRUDTemplate = ({
19826
20394
  true,
19827
20395
  {
19828
20396
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19829
- lineNumber: 475,
20397
+ lineNumber: 476,
19830
20398
  columnNumber: 23
19831
20399
  },
19832
20400
  void 0
@@ -19843,19 +20411,19 @@ const AdminCRUDTemplate = ({
19843
20411
  false,
19844
20412
  {
19845
20413
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19846
- lineNumber: 484,
20414
+ lineNumber: 485,
19847
20415
  columnNumber: 21
19848
20416
  },
19849
20417
  void 0
19850
20418
  )
19851
20419
  ] }, void 0, true, {
19852
20420
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19853
- lineNumber: 473,
20421
+ lineNumber: 474,
19854
20422
  columnNumber: 19
19855
20423
  }, void 0)
19856
20424
  ] }, void 0, true, {
19857
20425
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19858
- lineNumber: 453,
20426
+ lineNumber: 454,
19859
20427
  columnNumber: 13
19860
20428
  }, void 0),
19861
20429
  /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "flex items-center gap-2", children: [
@@ -19865,7 +20433,7 @@ const AdminCRUDTemplate = ({
19865
20433
  " selected"
19866
20434
  ] }, void 0, true, {
19867
20435
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19868
- lineNumber: 500,
20436
+ lineNumber: 501,
19869
20437
  columnNumber: 19
19870
20438
  }, void 0),
19871
20439
  permissions.delete && /* @__PURE__ */ jsxDevRuntime.jsxDEV(
@@ -19877,7 +20445,7 @@ const AdminCRUDTemplate = ({
19877
20445
  children: [
19878
20446
  /* @__PURE__ */ jsxDevRuntime.jsxDEV(lucideReact.Trash2, { className: "w-4 h-4 mr-2" }, void 0, false, {
19879
20447
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19880
- lineNumber: 509,
20448
+ lineNumber: 510,
19881
20449
  columnNumber: 23
19882
20450
  }, void 0),
19883
20451
  "Delete"
@@ -19887,14 +20455,14 @@ const AdminCRUDTemplate = ({
19887
20455
  true,
19888
20456
  {
19889
20457
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19890
- lineNumber: 504,
20458
+ lineNumber: 505,
19891
20459
  columnNumber: 21
19892
20460
  },
19893
20461
  void 0
19894
20462
  )
19895
20463
  ] }, void 0, true, {
19896
20464
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19897
- lineNumber: 499,
20465
+ lineNumber: 500,
19898
20466
  columnNumber: 17
19899
20467
  }, void 0),
19900
20468
  permissions.export && /* @__PURE__ */ jsxDevRuntime.jsxDEV(
@@ -19908,7 +20476,7 @@ const AdminCRUDTemplate = ({
19908
20476
  children: [
19909
20477
  /* @__PURE__ */ jsxDevRuntime.jsxDEV(lucideReact.Download, { className: "w-4 h-4 mr-2" }, void 0, false, {
19910
20478
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19911
- lineNumber: 522,
20479
+ lineNumber: 523,
19912
20480
  columnNumber: 19
19913
20481
  }, void 0),
19914
20482
  "Export"
@@ -19918,7 +20486,7 @@ const AdminCRUDTemplate = ({
19918
20486
  true,
19919
20487
  {
19920
20488
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19921
- lineNumber: 518,
20489
+ lineNumber: 519,
19922
20490
  columnNumber: 17
19923
20491
  },
19924
20492
  void 0
@@ -19943,7 +20511,7 @@ const AdminCRUDTemplate = ({
19943
20511
  children: [
19944
20512
  /* @__PURE__ */ jsxDevRuntime.jsxDEV(lucideReact.Upload, { className: "w-4 h-4 mr-2" }, void 0, false, {
19945
20513
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19946
- lineNumber: 543,
20514
+ lineNumber: 544,
19947
20515
  columnNumber: 19
19948
20516
  }, void 0),
19949
20517
  "Import"
@@ -19953,7 +20521,7 @@ const AdminCRUDTemplate = ({
19953
20521
  true,
19954
20522
  {
19955
20523
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19956
- lineNumber: 528,
20524
+ lineNumber: 529,
19957
20525
  columnNumber: 17
19958
20526
  },
19959
20527
  void 0
@@ -19972,27 +20540,27 @@ const AdminCRUDTemplate = ({
19972
20540
  true,
19973
20541
  {
19974
20542
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19975
- lineNumber: 550,
20543
+ lineNumber: 551,
19976
20544
  columnNumber: 17
19977
20545
  },
19978
20546
  void 0
19979
20547
  ))
19980
20548
  ] }, void 0, true, {
19981
20549
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19982
- lineNumber: 496,
20550
+ lineNumber: 497,
19983
20551
  columnNumber: 13
19984
20552
  }, void 0)
19985
20553
  ] }, void 0, true, {
19986
20554
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19987
- lineNumber: 451,
20555
+ lineNumber: 452,
19988
20556
  columnNumber: 11
19989
20557
  }, void 0) }, void 0, false, {
19990
20558
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19991
- lineNumber: 450,
20559
+ lineNumber: 451,
19992
20560
  columnNumber: 9
19993
20561
  }, void 0) }, void 0, false, {
19994
20562
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
19995
- lineNumber: 449,
20563
+ lineNumber: 450,
19996
20564
  columnNumber: 7
19997
20565
  }, void 0),
19998
20566
  /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "flex-1 min-h-0 overflow-auto", children: /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-8", children: hasData ? /* @__PURE__ */ jsxDevRuntime.jsxDEV(Card, { className: "p-6", category, children: /* @__PURE__ */ jsxDevRuntime.jsxDEV(
@@ -20012,13 +20580,13 @@ const AdminCRUDTemplate = ({
20012
20580
  false,
20013
20581
  {
20014
20582
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
20015
- lineNumber: 569,
20583
+ lineNumber: 570,
20016
20584
  columnNumber: 15
20017
20585
  },
20018
20586
  void 0
20019
20587
  ) }, void 0, false, {
20020
20588
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
20021
- lineNumber: 568,
20589
+ lineNumber: 569,
20022
20590
  columnNumber: 13
20023
20591
  }, void 0) : /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "flex items-center justify-center min-h-96", children: emptyState || /* @__PURE__ */ jsxDevRuntime.jsxDEV(
20024
20592
  EmptyState,
@@ -20034,21 +20602,21 @@ const AdminCRUDTemplate = ({
20034
20602
  false,
20035
20603
  {
20036
20604
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
20037
- lineNumber: 584,
20605
+ lineNumber: 585,
20038
20606
  columnNumber: 17
20039
20607
  },
20040
20608
  void 0
20041
20609
  ) }, void 0, false, {
20042
20610
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
20043
- lineNumber: 582,
20611
+ lineNumber: 583,
20044
20612
  columnNumber: 13
20045
20613
  }, void 0) }, void 0, false, {
20046
20614
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
20047
- lineNumber: 566,
20615
+ lineNumber: 567,
20048
20616
  columnNumber: 9
20049
20617
  }, void 0) }, void 0, false, {
20050
20618
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
20051
- lineNumber: 565,
20619
+ lineNumber: 566,
20052
20620
  columnNumber: 7
20053
20621
  }, void 0),
20054
20622
  /* @__PURE__ */ jsxDevRuntime.jsxDEV(
@@ -20063,22 +20631,22 @@ const AdminCRUDTemplate = ({
20063
20631
  /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "flex justify-end gap-2 pt-4", children: [
20064
20632
  /* @__PURE__ */ jsxDevRuntime.jsxDEV(Button, { variant: "outline", onClick: () => setShowCreateModal(false), children: "Cancel" }, void 0, false, {
20065
20633
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
20066
- lineNumber: 613,
20634
+ lineNumber: 614,
20067
20635
  columnNumber: 13
20068
20636
  }, void 0),
20069
20637
  /* @__PURE__ */ jsxDevRuntime.jsxDEV(Button, { onClick: () => handleSubmit(false), variant: "default", children: "Create" }, void 0, false, {
20070
20638
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
20071
- lineNumber: 616,
20639
+ lineNumber: 617,
20072
20640
  columnNumber: 13
20073
20641
  }, void 0)
20074
20642
  ] }, void 0, true, {
20075
20643
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
20076
- lineNumber: 612,
20644
+ lineNumber: 613,
20077
20645
  columnNumber: 11
20078
20646
  }, void 0)
20079
20647
  ] }, void 0, true, {
20080
20648
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
20081
- lineNumber: 609,
20649
+ lineNumber: 610,
20082
20650
  columnNumber: 9
20083
20651
  }, void 0)
20084
20652
  },
@@ -20086,7 +20654,7 @@ const AdminCRUDTemplate = ({
20086
20654
  false,
20087
20655
  {
20088
20656
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
20089
- lineNumber: 603,
20657
+ lineNumber: 604,
20090
20658
  columnNumber: 7
20091
20659
  },
20092
20660
  void 0
@@ -20103,22 +20671,22 @@ const AdminCRUDTemplate = ({
20103
20671
  /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "flex justify-end gap-2 pt-4", children: [
20104
20672
  /* @__PURE__ */ jsxDevRuntime.jsxDEV(Button, { variant: "outline", onClick: () => setShowEditModal(false), children: "Cancel" }, void 0, false, {
20105
20673
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
20106
- lineNumber: 634,
20674
+ lineNumber: 635,
20107
20675
  columnNumber: 13
20108
20676
  }, void 0),
20109
20677
  /* @__PURE__ */ jsxDevRuntime.jsxDEV(Button, { onClick: () => handleSubmit(true), variant: "default", children: "Update" }, void 0, false, {
20110
20678
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
20111
- lineNumber: 637,
20679
+ lineNumber: 638,
20112
20680
  columnNumber: 13
20113
20681
  }, void 0)
20114
20682
  ] }, void 0, true, {
20115
20683
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
20116
- lineNumber: 633,
20684
+ lineNumber: 634,
20117
20685
  columnNumber: 11
20118
20686
  }, void 0)
20119
20687
  ] }, void 0, true, {
20120
20688
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
20121
- lineNumber: 630,
20689
+ lineNumber: 631,
20122
20690
  columnNumber: 9
20123
20691
  }, void 0)
20124
20692
  },
@@ -20126,7 +20694,7 @@ const AdminCRUDTemplate = ({
20126
20694
  false,
20127
20695
  {
20128
20696
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
20129
- lineNumber: 624,
20697
+ lineNumber: 625,
20130
20698
  columnNumber: 7
20131
20699
  },
20132
20700
  void 0
@@ -20146,7 +20714,7 @@ const AdminCRUDTemplate = ({
20146
20714
  "? This action cannot be undone."
20147
20715
  ] }, void 0, true, {
20148
20716
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
20149
- lineNumber: 652,
20717
+ lineNumber: 653,
20150
20718
  columnNumber: 11
20151
20719
  }, void 0),
20152
20720
  /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "flex justify-end gap-2", children: [
@@ -20161,24 +20729,24 @@ const AdminCRUDTemplate = ({
20161
20729
  false,
20162
20730
  {
20163
20731
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
20164
- lineNumber: 658,
20732
+ lineNumber: 659,
20165
20733
  columnNumber: 13
20166
20734
  },
20167
20735
  void 0
20168
20736
  ),
20169
20737
  /* @__PURE__ */ jsxDevRuntime.jsxDEV(Button, { variant: "destructive", onClick: confirmDelete, children: "Delete" }, void 0, false, {
20170
20738
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
20171
- lineNumber: 664,
20739
+ lineNumber: 665,
20172
20740
  columnNumber: 13
20173
20741
  }, void 0)
20174
20742
  ] }, void 0, true, {
20175
20743
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
20176
- lineNumber: 657,
20744
+ lineNumber: 658,
20177
20745
  columnNumber: 11
20178
20746
  }, void 0)
20179
20747
  ] }, void 0, true, {
20180
20748
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
20181
- lineNumber: 651,
20749
+ lineNumber: 652,
20182
20750
  columnNumber: 9
20183
20751
  }, void 0)
20184
20752
  },
@@ -20186,14 +20754,14 @@ const AdminCRUDTemplate = ({
20186
20754
  false,
20187
20755
  {
20188
20756
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
20189
- lineNumber: 645,
20757
+ lineNumber: 646,
20190
20758
  columnNumber: 7
20191
20759
  },
20192
20760
  void 0
20193
20761
  )
20194
20762
  ] }, void 0, true, {
20195
20763
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/admin/AdminCRUDTemplate.tsx",
20196
- lineNumber: 400,
20764
+ lineNumber: 401,
20197
20765
  columnNumber: 5
20198
20766
  }, void 0);
20199
20767
  };
@@ -21309,6 +21877,26 @@ const ReactQueryDevtools = React.lazy(
21309
21877
  default: mod.ReactQueryDevtools
21310
21878
  }))
21311
21879
  );
21880
+ class DevtoolsErrorBoundary extends React.Component {
21881
+ constructor(props) {
21882
+ super(props);
21883
+ this.state = { hasError: false };
21884
+ }
21885
+ static getDerivedStateFromError() {
21886
+ return { hasError: true };
21887
+ }
21888
+ componentDidCatch(error) {
21889
+ {
21890
+ console.debug("[DevTools] Failed to initialize:", error.message);
21891
+ }
21892
+ }
21893
+ render() {
21894
+ if (this.state.hasError) {
21895
+ return null;
21896
+ }
21897
+ return this.props.children;
21898
+ }
21899
+ }
21312
21900
  function createReactApp(config) {
21313
21901
  const appConfig = typeof config === "string" ? { title: config } : config;
21314
21902
  const {
@@ -21339,18 +21927,18 @@ function createReactApp(config) {
21339
21927
  title
21340
21928
  ] }, void 0, true, {
21341
21929
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/factory.tsx",
21342
- lineNumber: 81,
21930
+ lineNumber: 110,
21343
21931
  columnNumber: 9
21344
21932
  }, this),
21345
21933
  /* @__PURE__ */ jsxDevRuntime.jsxDEV("p", { className: "text-lg text-muted-foreground mb-6", children: description }, void 0, false, {
21346
21934
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/factory.tsx",
21347
- lineNumber: 82,
21935
+ lineNumber: 111,
21348
21936
  columnNumber: 9
21349
21937
  }, this),
21350
21938
  /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "space-y-2 text-sm text-muted-foreground", children: [
21351
21939
  /* @__PURE__ */ jsxDevRuntime.jsxDEV("p", { children: "✅ Template integration successful" }, void 0, false, {
21352
21940
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/factory.tsx",
21353
- lineNumber: 84,
21941
+ lineNumber: 113,
21354
21942
  columnNumber: 11
21355
21943
  }, this),
21356
21944
  /* @__PURE__ */ jsxDevRuntime.jsxDEV("p", { children: [
@@ -21358,26 +21946,26 @@ function createReactApp(config) {
21358
21946
  version
21359
21947
  ] }, void 0, true, {
21360
21948
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/factory.tsx",
21361
- lineNumber: 85,
21949
+ lineNumber: 114,
21362
21950
  columnNumber: 11
21363
21951
  }, this),
21364
21952
  /* @__PURE__ */ jsxDevRuntime.jsxDEV("p", { children: "🚀 Ready for development" }, void 0, false, {
21365
21953
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/factory.tsx",
21366
- lineNumber: 86,
21954
+ lineNumber: 115,
21367
21955
  columnNumber: 11
21368
21956
  }, this)
21369
21957
  ] }, void 0, true, {
21370
21958
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/factory.tsx",
21371
- lineNumber: 83,
21959
+ lineNumber: 112,
21372
21960
  columnNumber: 9
21373
21961
  }, this)
21374
21962
  ] }, void 0, true, {
21375
21963
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/factory.tsx",
21376
- lineNumber: 80,
21964
+ lineNumber: 109,
21377
21965
  columnNumber: 7
21378
21966
  }, this) }, void 0, false, {
21379
21967
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/factory.tsx",
21380
- lineNumber: 79,
21968
+ lineNumber: 108,
21381
21969
  columnNumber: 5
21382
21970
  }, this);
21383
21971
  const createProviderTree = (children) => {
@@ -21385,50 +21973,54 @@ function createReactApp(config) {
21385
21973
  customProviders.reverse().forEach((Provider) => {
21386
21974
  tree = /* @__PURE__ */ jsxDevRuntime.jsxDEV(Provider, { children: tree }, Provider.name, false, {
21387
21975
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/factory.tsx",
21388
- lineNumber: 98,
21976
+ lineNumber: 127,
21389
21977
  columnNumber: 14
21390
21978
  }, this);
21391
21979
  });
21392
21980
  if (enableRouting) {
21393
21981
  tree = /* @__PURE__ */ jsxDevRuntime.jsxDEV(NavigationProvider, { initialNavigation: navigation, children: /* @__PURE__ */ jsxDevRuntime.jsxDEV(SidebarProvider, { children: tree }, void 0, false, {
21394
21982
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/factory.tsx",
21395
- lineNumber: 105,
21983
+ lineNumber: 134,
21396
21984
  columnNumber: 11
21397
21985
  }, this) }, void 0, false, {
21398
21986
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/factory.tsx",
21399
- lineNumber: 104,
21987
+ lineNumber: 133,
21400
21988
  columnNumber: 9
21401
21989
  }, this);
21402
21990
  }
21403
21991
  if (enableAuth) {
21404
21992
  tree = /* @__PURE__ */ jsxDevRuntime.jsxDEV(AuthProvider, { config: auth, children: tree }, void 0, false, {
21405
21993
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/factory.tsx",
21406
- lineNumber: 112,
21994
+ lineNumber: 141,
21407
21995
  columnNumber: 14
21408
21996
  }, this);
21409
21997
  }
21410
21998
  if (enableQuery) {
21411
21999
  tree = /* @__PURE__ */ jsxDevRuntime.jsxDEV(reactQuery.QueryClientProvider, { client: queryClient, children: [
21412
22000
  tree,
21413
- /* @__PURE__ */ jsxDevRuntime.jsxDEV(React.Suspense, { fallback: null, children: /* @__PURE__ */ jsxDevRuntime.jsxDEV(ReactQueryDevtools, { initialIsOpen: false }, void 0, false, {
22001
+ /* @__PURE__ */ jsxDevRuntime.jsxDEV(DevtoolsErrorBoundary, { children: /* @__PURE__ */ jsxDevRuntime.jsxDEV(React.Suspense, { fallback: null, children: /* @__PURE__ */ jsxDevRuntime.jsxDEV(ReactQueryDevtools, { initialIsOpen: false }, void 0, false, {
22002
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/factory.tsx",
22003
+ lineNumber: 152,
22004
+ columnNumber: 17
22005
+ }, this) }, void 0, false, {
21414
22006
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/factory.tsx",
21415
- lineNumber: 122,
22007
+ lineNumber: 151,
21416
22008
  columnNumber: 15
21417
22009
  }, this) }, void 0, false, {
21418
22010
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/factory.tsx",
21419
- lineNumber: 121,
22011
+ lineNumber: 150,
21420
22012
  columnNumber: 13
21421
22013
  }, this)
21422
22014
  ] }, void 0, true, {
21423
22015
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/factory.tsx",
21424
- lineNumber: 118,
22016
+ lineNumber: 147,
21425
22017
  columnNumber: 9
21426
22018
  }, this);
21427
22019
  }
21428
22020
  if (enableRouting) {
21429
22021
  tree = /* @__PURE__ */ jsxDevRuntime.jsxDEV(reactRouterDom.BrowserRouter, { children: tree }, void 0, false, {
21430
22022
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/factory.tsx",
21431
- lineNumber: 131,
22023
+ lineNumber: 162,
21432
22024
  columnNumber: 14
21433
22025
  }, this);
21434
22026
  }
@@ -21439,37 +22031,52 @@ function createReactApp(config) {
21439
22031
  routes.push({ path, component });
21440
22032
  },
21441
22033
  render() {
22034
+ const shouldProtect = enableAuth && (auth == null ? void 0 : auth.requireAuth) !== false;
22035
+ const publicPaths = (auth == null ? void 0 : auth.publicPaths) ?? ["/login", "/register", "/forgot-password"];
22036
+ const isPublicPath = (path) => {
22037
+ return publicPaths.some((p) => path === p || path.startsWith(p + "/"));
22038
+ };
22039
+ const wrapWithProtection = (path, component) => {
22040
+ if (shouldProtect && !isPublicPath(path)) {
22041
+ return /* @__PURE__ */ jsxDevRuntime.jsxDEV(ProtectedRoute, { children: component }, void 0, false, {
22042
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/factory.tsx",
22043
+ lineNumber: 187,
22044
+ columnNumber: 18
22045
+ }, this);
22046
+ }
22047
+ return component;
22048
+ };
21442
22049
  const AppContent = () => /* @__PURE__ */ jsxDevRuntime.jsxDEV(reactRouterDom.Routes, { children: /* @__PURE__ */ jsxDevRuntime.jsxDEV(reactRouterDom.Route, { path: "/", element: /* @__PURE__ */ jsxDevRuntime.jsxDEV(AppLayout, {}, void 0, false, {
21443
22050
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/factory.tsx",
21444
- lineNumber: 146,
22051
+ lineNumber: 194,
21445
22052
  columnNumber: 36
21446
22053
  }, this), children: [
21447
- /* @__PURE__ */ jsxDevRuntime.jsxDEV(reactRouterDom.Route, { index: true, element: /* @__PURE__ */ jsxDevRuntime.jsxDEV(DefaultHome, {}, void 0, false, {
22054
+ /* @__PURE__ */ jsxDevRuntime.jsxDEV(reactRouterDom.Route, { index: true, element: wrapWithProtection("/", /* @__PURE__ */ jsxDevRuntime.jsxDEV(DefaultHome, {}, void 0, false, {
21448
22055
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/factory.tsx",
21449
- lineNumber: 147,
21450
- columnNumber: 35
21451
- }, this) }, void 0, false, {
22056
+ lineNumber: 195,
22057
+ columnNumber: 59
22058
+ }, this)) }, void 0, false, {
21452
22059
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/factory.tsx",
21453
- lineNumber: 147,
22060
+ lineNumber: 195,
21454
22061
  columnNumber: 13
21455
22062
  }, this),
21456
- routes.map(({ path, component }, index) => /* @__PURE__ */ jsxDevRuntime.jsxDEV(reactRouterDom.Route, { path, element: component }, index, false, {
22063
+ routes.map(({ path, component }, index) => /* @__PURE__ */ jsxDevRuntime.jsxDEV(reactRouterDom.Route, { path, element: wrapWithProtection(path, component) }, index, false, {
21457
22064
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/factory.tsx",
21458
- lineNumber: 149,
22065
+ lineNumber: 197,
21459
22066
  columnNumber: 15
21460
22067
  }, this))
21461
22068
  ] }, void 0, true, {
21462
22069
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/factory.tsx",
21463
- lineNumber: 146,
22070
+ lineNumber: 194,
21464
22071
  columnNumber: 11
21465
22072
  }, this) }, void 0, false, {
21466
22073
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/factory.tsx",
21467
- lineNumber: 145,
22074
+ lineNumber: 193,
21468
22075
  columnNumber: 9
21469
22076
  }, this);
21470
22077
  return createProviderTree(/* @__PURE__ */ jsxDevRuntime.jsxDEV(AppContent, {}, void 0, false, {
21471
22078
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/factory.tsx",
21472
- lineNumber: 155,
22079
+ lineNumber: 203,
21473
22080
  columnNumber: 33
21474
22081
  }, this));
21475
22082
  },
@@ -21481,7 +22088,7 @@ function createReactApp(config) {
21481
22088
  const root = client.createRoot(element);
21482
22089
  root.render(/* @__PURE__ */ jsxDevRuntime.jsxDEV(React.StrictMode, { children: this.render() }, void 0, false, {
21483
22090
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/templates/factory.tsx",
21484
- lineNumber: 165,
22091
+ lineNumber: 213,
21485
22092
  columnNumber: 19
21486
22093
  }, this));
21487
22094
  }
@@ -21581,7 +22188,7 @@ const ResponsiveShowcaseContent = () => {
21581
22188
  {
21582
22189
  key: "category",
21583
22190
  header: "Category",
21584
- type: "category",
22191
+ type: "badge",
21585
22192
  icon: /* @__PURE__ */ jsxDevRuntime.jsxDEV(lucideReact.Briefcase, { className: "w-3 h-3" }, void 0, false, {
21586
22193
  fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/organisms/showcase/ComponentShowcasePage.tsx",
21587
22194
  lineNumber: 168,
@@ -22155,7 +22762,7 @@ const ComponentShowcasePage = () => {
22155
22762
  const tableColumns = [
22156
22763
  { key: "name", header: "Model Name" },
22157
22764
  { key: "status", header: "Status", type: "status" },
22158
- { key: "category", header: "Category", type: "category" },
22765
+ { key: "category", header: "Category", type: "badge" },
22159
22766
  { key: "runs", header: "Runs" }
22160
22767
  ];
22161
22768
  return /* @__PURE__ */ jsxDevRuntime.jsxDEV("div", { className: "min-h-screen bg-background", children: [
@@ -23588,7 +24195,7 @@ const ComponentShowcasePage = () => {
23588
24195
  columns={[
23589
24196
  { key: 'name', header: 'Model Name' },
23590
24197
  { key: 'status', header: 'Status', type: 'status' },
23591
- { key: 'category', header: 'Category', type: 'category' }
24198
+ { key: 'category', header: 'Category', type: 'badge' }
23592
24199
  ]}
23593
24200
  searchPlaceholder="Search models..."
23594
24201
  onRowClick={(item) => alert(item.name)}
@@ -28553,6 +29160,165 @@ const ComponentShowcasePage = () => {
28553
29160
  columnNumber: 5
28554
29161
  }, void 0);
28555
29162
  };
29163
+ const Sheet = SheetPrimitive__namespace.Root;
29164
+ const SheetTrigger = SheetPrimitive__namespace.Trigger;
29165
+ const SheetClose = SheetPrimitive__namespace.Close;
29166
+ const SheetPortal = SheetPrimitive__namespace.Portal;
29167
+ const SheetOverlay = React__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxDevRuntime.jsxDEV(
29168
+ SheetPrimitive__namespace.Overlay,
29169
+ {
29170
+ className: cn(
29171
+ "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
29172
+ className
29173
+ ),
29174
+ ...props,
29175
+ ref
29176
+ },
29177
+ void 0,
29178
+ false,
29179
+ {
29180
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/primitives/sheet.tsx",
29181
+ lineNumber: 15,
29182
+ columnNumber: 3
29183
+ },
29184
+ void 0
29185
+ ));
29186
+ SheetOverlay.displayName = SheetPrimitive__namespace.Overlay.displayName;
29187
+ const sheetVariants = {
29188
+ top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
29189
+ bottom: "inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
29190
+ left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
29191
+ right: "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm"
29192
+ };
29193
+ const SheetContent = React__namespace.forwardRef(({ side = "right", className, children, ...props }, ref) => /* @__PURE__ */ jsxDevRuntime.jsxDEV(SheetPortal, { children: [
29194
+ /* @__PURE__ */ jsxDevRuntime.jsxDEV(SheetOverlay, {}, void 0, false, {
29195
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/primitives/sheet.tsx",
29196
+ lineNumber: 43,
29197
+ columnNumber: 5
29198
+ }, void 0),
29199
+ /* @__PURE__ */ jsxDevRuntime.jsxDEV(
29200
+ SheetPrimitive__namespace.Content,
29201
+ {
29202
+ ref,
29203
+ className: cn(
29204
+ "fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500",
29205
+ sheetVariants[side],
29206
+ className
29207
+ ),
29208
+ ...props,
29209
+ children: [
29210
+ children,
29211
+ /* @__PURE__ */ jsxDevRuntime.jsxDEV(SheetPrimitive__namespace.Close, { className: "absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary", children: [
29212
+ /* @__PURE__ */ jsxDevRuntime.jsxDEV(lucideReact.X, { className: "h-4 w-4" }, void 0, false, {
29213
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/primitives/sheet.tsx",
29214
+ lineNumber: 55,
29215
+ columnNumber: 9
29216
+ }, void 0),
29217
+ /* @__PURE__ */ jsxDevRuntime.jsxDEV("span", { className: "sr-only", children: "Close" }, void 0, false, {
29218
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/primitives/sheet.tsx",
29219
+ lineNumber: 56,
29220
+ columnNumber: 9
29221
+ }, void 0)
29222
+ ] }, void 0, true, {
29223
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/primitives/sheet.tsx",
29224
+ lineNumber: 54,
29225
+ columnNumber: 7
29226
+ }, void 0)
29227
+ ]
29228
+ },
29229
+ void 0,
29230
+ true,
29231
+ {
29232
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/primitives/sheet.tsx",
29233
+ lineNumber: 44,
29234
+ columnNumber: 5
29235
+ },
29236
+ void 0
29237
+ )
29238
+ ] }, void 0, true, {
29239
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/primitives/sheet.tsx",
29240
+ lineNumber: 42,
29241
+ columnNumber: 3
29242
+ }, void 0));
29243
+ SheetContent.displayName = SheetPrimitive__namespace.Content.displayName;
29244
+ const SheetHeader = ({
29245
+ className,
29246
+ ...props
29247
+ }) => /* @__PURE__ */ jsxDevRuntime.jsxDEV(
29248
+ "div",
29249
+ {
29250
+ className: cn(
29251
+ "flex flex-col space-y-2 text-center sm:text-left",
29252
+ className
29253
+ ),
29254
+ ...props
29255
+ },
29256
+ void 0,
29257
+ false,
29258
+ {
29259
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/primitives/sheet.tsx",
29260
+ lineNumber: 67,
29261
+ columnNumber: 3
29262
+ },
29263
+ void 0
29264
+ );
29265
+ SheetHeader.displayName = "SheetHeader";
29266
+ const SheetFooter = ({
29267
+ className,
29268
+ ...props
29269
+ }) => /* @__PURE__ */ jsxDevRuntime.jsxDEV(
29270
+ "div",
29271
+ {
29272
+ className: cn(
29273
+ "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
29274
+ className
29275
+ ),
29276
+ ...props
29277
+ },
29278
+ void 0,
29279
+ false,
29280
+ {
29281
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/primitives/sheet.tsx",
29282
+ lineNumber: 81,
29283
+ columnNumber: 3
29284
+ },
29285
+ void 0
29286
+ );
29287
+ SheetFooter.displayName = "SheetFooter";
29288
+ const SheetTitle = React__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxDevRuntime.jsxDEV(
29289
+ SheetPrimitive__namespace.Title,
29290
+ {
29291
+ ref,
29292
+ className: cn("text-lg font-semibold text-foreground", className),
29293
+ ...props
29294
+ },
29295
+ void 0,
29296
+ false,
29297
+ {
29298
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/primitives/sheet.tsx",
29299
+ lineNumber: 95,
29300
+ columnNumber: 3
29301
+ },
29302
+ void 0
29303
+ ));
29304
+ SheetTitle.displayName = SheetPrimitive__namespace.Title.displayName;
29305
+ const SheetDescription = React__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxDevRuntime.jsxDEV(
29306
+ SheetPrimitive__namespace.Description,
29307
+ {
29308
+ ref,
29309
+ className: cn("text-sm text-muted-foreground", className),
29310
+ ...props
29311
+ },
29312
+ void 0,
29313
+ false,
29314
+ {
29315
+ fileName: "/Users/dug/Projects/pattern-stack/frontend-patterns/src/atoms/primitives/sheet.tsx",
29316
+ lineNumber: 107,
29317
+ columnNumber: 3
29318
+ },
29319
+ void 0
29320
+ ));
29321
+ SheetDescription.displayName = SheetPrimitive__namespace.Description.displayName;
28556
29322
  function isBulkOperation(path, _method, requestBody) {
28557
29323
  const bulkPatterns = [
28558
29324
  /\/bulk[-_]?delete$/i,
@@ -28707,6 +29473,8 @@ exports.IconBadge = IconBadge;
28707
29473
  exports.Input = Input;
28708
29474
  exports.Label = Label;
28709
29475
  exports.ListCard = ListCard;
29476
+ exports.ListPageTemplate = ListPageTemplate;
29477
+ exports.ListToolbar = ListToolbar;
28710
29478
  exports.Loading = Loading;
28711
29479
  exports.LoginForm = LoginForm;
28712
29480
  exports.LogoutButton = LogoutButton;
@@ -28716,6 +29484,7 @@ exports.Modal = Modal;
28716
29484
  exports.NavMenu = NavMenu;
28717
29485
  exports.NavigationProvider = NavigationProvider;
28718
29486
  exports.PageTemplate = PageTemplate;
29487
+ exports.PageTitle = PageTitle;
28719
29488
  exports.Pagination = Pagination;
28720
29489
  exports.PaletteSwitcher = PaletteSwitcher;
28721
29490
  exports.ProgressBar = ProgressBar;
@@ -28730,6 +29499,16 @@ exports.SelectContent = SelectContent;
28730
29499
  exports.SelectItem = SelectItem;
28731
29500
  exports.SelectTrigger = SelectTrigger;
28732
29501
  exports.SelectValue = SelectValue;
29502
+ exports.Sheet = Sheet;
29503
+ exports.SheetClose = SheetClose;
29504
+ exports.SheetContent = SheetContent;
29505
+ exports.SheetDescription = SheetDescription;
29506
+ exports.SheetFooter = SheetFooter;
29507
+ exports.SheetHeader = SheetHeader;
29508
+ exports.SheetOverlay = SheetOverlay;
29509
+ exports.SheetPortal = SheetPortal;
29510
+ exports.SheetTitle = SheetTitle;
29511
+ exports.SheetTrigger = SheetTrigger;
28733
29512
  exports.ShowcaseSection = ShowcaseSection;
28734
29513
  exports.Sidebar = Sidebar;
28735
29514
  exports.SidebarButton = SidebarButton;
@@ -28789,6 +29568,7 @@ exports.interactionVariants = interactionVariants;
28789
29568
  exports.isBulkOperation = isBulkOperation;
28790
29569
  exports.isValidIcon = isValidIcon;
28791
29570
  exports.legacyPatterns = legacyPatterns;
29571
+ exports.normalizeFieldType = normalizeFieldType;
28792
29572
  exports.renderField = renderField;
28793
29573
  exports.responsiveScales = responsiveScales;
28794
29574
  exports.setGlobalAuthService = setGlobalAuthService;
@@ -28802,6 +29582,7 @@ exports.useCategoryColors = useCategoryColors;
28802
29582
  exports.useCreateExample = useCreateExample;
28803
29583
  exports.useDeleteExample = useDeleteExample;
28804
29584
  exports.useErrorBoundary = useErrorBoundary;
29585
+ exports.useFieldMetadata = useFieldMetadata;
28805
29586
  exports.useGetExample = useGetExample;
28806
29587
  exports.useHealth = useHealth;
28807
29588
  exports.useIsDesktop = useIsDesktop;
@@ -28811,8 +29592,10 @@ exports.useMaxMediaQuery = useMaxMediaQuery;
28811
29592
  exports.useMediaQuery = useMediaQuery;
28812
29593
  exports.useMockAuth = useMockAuth;
28813
29594
  exports.useNavigation = useNavigation;
29595
+ exports.useOverflowDetection = useOverflowDetection;
28814
29596
  exports.usePermissions = usePermissions;
28815
29597
  exports.useResponsiveClasses = useResponsiveClasses;
29598
+ exports.useResponsiveTable = useResponsiveTable;
28816
29599
  exports.useResponsiveValue = useResponsiveValue;
28817
29600
  exports.useSidebar = useSidebar;
28818
29601
  exports.useTextOverflow = useTextOverflow;