@sqrzro/admin 2.1.0-bz.9 → 2.1.0-r19.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 (126) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +8 -5
  3. package/assets/images/check-white.svg +3 -0
  4. package/assets/images/chevron.svg +3 -0
  5. package/assets/images/close.svg +3 -0
  6. package/assets/images/danger.svg +3 -0
  7. package/assets/images/eye.svg +12 -0
  8. package/assets/images/info.svg +3 -0
  9. package/assets/images/success.svg +3 -0
  10. package/assets/images/warning.svg +3 -0
  11. package/dist/components/AppLayout/index.d.ts +2 -2
  12. package/dist/components/AppLayout/index.js +7 -5
  13. package/dist/components/AppNavigation/index.d.ts +4 -2
  14. package/dist/components/AppNavigation/index.js +4 -13
  15. package/dist/components/AppNavigationComponent/index.d.ts +11 -0
  16. package/dist/components/AppNavigationComponent/index.js +19 -0
  17. package/dist/components/AppNavigationSub/index.d.ts +11 -0
  18. package/dist/components/AppNavigationSub/index.js +12 -0
  19. package/dist/components/Auth/index.d.ts +10 -0
  20. package/dist/components/Auth/index.js +10 -0
  21. package/dist/components/Badge/index.d.ts +1 -2
  22. package/dist/components/Badge/index.js +16 -7
  23. package/dist/components/BooleanFilter/index.d.ts +0 -1
  24. package/dist/components/Dashboard/index.d.ts +0 -1
  25. package/dist/components/Dashboard/index.js +1 -1
  26. package/dist/components/DataTable/index.d.ts +5 -0
  27. package/dist/components/DataTable/index.js +5 -0
  28. package/dist/components/DateFilter/index.d.ts +0 -1
  29. package/dist/components/DateFilter/index.js +24 -1
  30. package/dist/components/DropdownFilter/index.d.ts +0 -1
  31. package/dist/components/FilterBar/index.d.ts +4 -3
  32. package/dist/components/FilterBar/index.js +30 -3
  33. package/dist/components/FilterBarClearButton/index.d.ts +5 -0
  34. package/dist/components/FilterBarClearButton/index.js +5 -0
  35. package/dist/components/FilterBarItem/index.d.ts +4 -3
  36. package/dist/components/FilterBarItem/index.js +6 -5
  37. package/dist/components/GridList/index.d.ts +2 -3
  38. package/dist/components/GridListItem/index.d.ts +1 -2
  39. package/dist/components/GridListItem/index.js +3 -2
  40. package/dist/components/InfoPanel/index.d.ts +2 -2
  41. package/dist/components/InfoPanel/index.js +18 -6
  42. package/dist/components/List/index.d.ts +4 -20
  43. package/dist/components/List/index.js +13 -17
  44. package/dist/components/ListActions/index.d.ts +6 -4
  45. package/dist/components/ListActions/index.js +16 -3
  46. package/dist/components/ListClientComponent/index.d.ts +13 -0
  47. package/dist/components/ListClientComponent/index.js +14 -0
  48. package/dist/components/ListComponent/index.d.ts +13 -0
  49. package/dist/components/ListComponent/index.js +21 -0
  50. package/dist/components/ListItem/index.d.ts +19 -10
  51. package/dist/components/ListItem/index.js +18 -5
  52. package/dist/components/ListSkeleton/index.d.ts +4 -0
  53. package/dist/components/ListSkeleton/index.js +5 -0
  54. package/dist/components/MeActions/index.d.ts +4 -2
  55. package/dist/components/MeActions/index.js +4 -11
  56. package/dist/components/MePanel/index.d.ts +3 -2
  57. package/dist/components/MePanel/index.js +3 -2
  58. package/dist/components/Menu/index.d.ts +7 -0
  59. package/dist/components/Menu/index.js +7 -0
  60. package/dist/components/MenuItem/index.d.ts +4 -0
  61. package/dist/components/MenuItem/index.js +20 -0
  62. package/dist/components/Page/index.d.ts +4 -3
  63. package/dist/components/Page/index.js +6 -3
  64. package/dist/components/PageActions/index.d.ts +0 -1
  65. package/dist/components/PaginatedList/index.d.ts +8 -0
  66. package/dist/components/PaginatedList/index.js +18 -0
  67. package/dist/components/PaginatedListComponent/index.d.ts +13 -0
  68. package/dist/components/PaginatedListComponent/index.js +20 -0
  69. package/dist/components/Pagination/index.d.ts +7 -0
  70. package/dist/components/Pagination/index.js +40 -0
  71. package/dist/components/PaginationItem/index.d.ts +9 -0
  72. package/dist/components/PaginationItem/index.js +16 -0
  73. package/dist/components/Panel/index.d.ts +3 -2
  74. package/dist/components/Panel/index.js +13 -2
  75. package/dist/components/RootLayout/index.d.ts +2 -2
  76. package/dist/components/RootLayout/index.js +6 -12
  77. package/dist/components/SettingsForm/index.d.ts +6 -0
  78. package/dist/components/SettingsForm/index.js +14 -0
  79. package/dist/components/SettingsPage/index.d.ts +2 -0
  80. package/dist/components/SettingsPage/index.js +9 -0
  81. package/dist/components/Table/index.d.ts +6 -7
  82. package/dist/components/Table/index.js +16 -14
  83. package/dist/components/TableClientComponent/index.d.ts +0 -1
  84. package/dist/components/TableClientComponent/index.js +2 -11
  85. package/dist/components/TableComponent/index.d.ts +11 -0
  86. package/dist/components/TableComponent/index.js +17 -0
  87. package/dist/components/Tabs/index.d.ts +2 -7
  88. package/dist/components/Tabs/index.js +5 -22
  89. package/dist/components/TabsComponent/index.d.ts +7 -0
  90. package/dist/components/TabsComponent/index.js +9 -0
  91. package/dist/components/index.d.ts +12 -5
  92. package/dist/components/index.js +5 -2
  93. package/dist/hooks/useNavigation.d.ts +11 -0
  94. package/dist/hooks/useNavigation.js +27 -0
  95. package/dist/index.cjs +1266 -0
  96. package/dist/index.cjs.map +1 -0
  97. package/dist/index.js.map +1 -0
  98. package/dist/interfaces.d.ts +8 -2
  99. package/dist/services/ConfigService.d.ts +8 -3
  100. package/dist/services/ConfigService.js +6 -6
  101. package/dist/services/PermissionService.d.ts +3 -0
  102. package/dist/services/PermissionService.js +30 -0
  103. package/dist/services/SettingsService.d.ts +8 -0
  104. package/dist/services/SettingsService.js +9 -0
  105. package/dist/styles/config.js +119 -47
  106. package/dist/styles/tailwind.d.ts +9 -1
  107. package/dist/styles/tailwind.js +16 -3
  108. package/package.json +46 -45
  109. package/dist/components/Icon/index.d.ts +0 -8
  110. package/dist/components/Icon/index.js +0 -22
  111. package/dist/components/LoginForm/index.d.ts +0 -8
  112. package/dist/components/LoginForm/index.js +0 -7
  113. package/dist/icons/ErrorIcon/index.d.ts +0 -3
  114. package/dist/icons/ErrorIcon/index.js +0 -5
  115. package/dist/icons/InfoIcon/index.d.ts +0 -3
  116. package/dist/icons/InfoIcon/index.js +0 -5
  117. package/dist/icons/SuccessIcon/index.d.ts +0 -3
  118. package/dist/icons/SuccessIcon/index.js +0 -5
  119. package/dist/icons/WarningIcon/index.d.ts +0 -3
  120. package/dist/icons/WarningIcon/index.js +0 -5
  121. package/dist/services/AuthService.d.ts +0 -1
  122. package/dist/services/AuthService.js +0 -5
  123. package/dist/utility/formatters.d.ts +0 -1
  124. package/dist/utility/formatters.js +0 -8
  125. /package/{postcss.js → postcss.cjs} +0 -0
  126. /package/{tailwind.js → tailwind.cjs} +0 -0
package/dist/index.cjs ADDED
@@ -0,0 +1,1266 @@
1
+ 'use strict';
2
+
3
+ var components = require('@sqrzro/components');
4
+ var headers = require('next/headers');
5
+ var react = require('react');
6
+ var utility = require('@sqrzro/utility');
7
+ var navigation = require('next/navigation');
8
+ var jsxRuntime = require('react/jsx-runtime');
9
+ var hooks = require('@sqrzro/hooks');
10
+ var reactDom = require('react-dom');
11
+ var google = require('next/font/google');
12
+
13
+ // src/components/index.ts
14
+
15
+ // src/services/ConfigService.ts
16
+ var config = {
17
+ app: {
18
+ name: "Square Zero",
19
+ url: "http://localhost:8080"
20
+ },
21
+ navigation: []
22
+ };
23
+ function setConfig(cfg, logo) {
24
+ config = { ...cfg, logo };
25
+ return config;
26
+ }
27
+ function getConfig() {
28
+ return config;
29
+ }
30
+ async function getLayout() {
31
+ return Promise.resolve(headers.cookies().get("layout")?.value || "topbar");
32
+ }
33
+ async function submitSettingsForm(formData) {
34
+ headers.cookies().set("layout", formData.layout);
35
+ return Promise.resolve([true, null]);
36
+ }
37
+ async function filterList(list) {
38
+ if (process.env.APP_ENV !== "production" && process.env.DANGEROUSLY_DISABLE_PERMISSIONS) {
39
+ return Promise.resolve(list);
40
+ }
41
+ const cookie = headers.cookies().get("permissions")?.value;
42
+ if (!cookie) {
43
+ return Promise.resolve([]);
44
+ }
45
+ let value = [];
46
+ try {
47
+ value = JSON.parse(cookie);
48
+ } catch (err) {
49
+ return Promise.resolve([]);
50
+ }
51
+ return Promise.resolve(
52
+ list.filter(({ permission }) => {
53
+ if (!permission) {
54
+ return true;
55
+ }
56
+ const permissions = Array.isArray(permission) ? permission : [permission];
57
+ return permissions.every((item) => value.includes(item));
58
+ })
59
+ );
60
+ }
61
+ function getActiveHref(pathname, hrefs) {
62
+ return hrefs.filter((href) => href && pathname.startsWith(`/${href.replace(/^\//u, "")}`)).sort((first, second) => {
63
+ if (!first || !second) {
64
+ return 0;
65
+ }
66
+ return second.length - first.length;
67
+ })[0] || "";
68
+ }
69
+ function useNavigation(data2, options2) {
70
+ const [activeHref, setActiveHref] = react.useState("");
71
+ const pathname = navigation.usePathname();
72
+ const hrefs = data2.map(({ href }) => utility.joinUrl(options2?.basePath, href));
73
+ react.useEffect(() => {
74
+ setActiveHref(getActiveHref(pathname, hrefs));
75
+ }, [pathname]);
76
+ return data2.map(({ href, label }) => ({
77
+ href: utility.joinUrl(options2?.basePath, href),
78
+ isActive: utility.joinUrl(options2?.basePath, href) === activeHref,
79
+ label
80
+ }));
81
+ }
82
+ var useNavigation_default = useNavigation;
83
+ function AppNavigationComponent({
84
+ data: data2,
85
+ layout
86
+ }) {
87
+ const navigation = useNavigation_default(data2);
88
+ return /* @__PURE__ */ jsxRuntime.jsx("nav", { className: components.tw("h-full", layout === "sidebar" ? "w-full" : "pl-6"), children: /* @__PURE__ */ jsxRuntime.jsx(
89
+ "ul",
90
+ {
91
+ className: components.tw(
92
+ "flex h-full gap-2",
93
+ layout === "sidebar" ? "flex-col items-start" : "items-center"
94
+ ),
95
+ children: navigation.map(({ href, isActive, label }) => /* @__PURE__ */ jsxRuntime.jsx("li", { className: components.tw(layout === "sidebar" ? null : "h-full"), children: /* @__PURE__ */ jsxRuntime.jsx(
96
+ components.Link,
97
+ {
98
+ className: components.tw(
99
+ "relative flex h-full items-center px-1 font-semibold",
100
+ isActive ? "before:bg-primary text-white before:absolute before:bottom-0 before:left-0 before:right-0 before:h-1" : "text-white/80 hover:text-white"
101
+ ),
102
+ href,
103
+ children: label
104
+ }
105
+ ) }, href))
106
+ }
107
+ ) });
108
+ }
109
+ var AppNavigationComponent_default = AppNavigationComponent;
110
+ async function AppNavigation({
111
+ layout
112
+ }) {
113
+ return /* @__PURE__ */ jsxRuntime.jsx(AppNavigationComponent_default, { data: await filterList(getConfig().navigation), layout });
114
+ }
115
+ var AppNavigation_default = AppNavigation;
116
+ function MeActions() {
117
+ return /* @__PURE__ */ jsxRuntime.jsxs("ul", { className: "flex gap-2 text-xs text-slate-300", children: [
118
+ /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(components.Link, { href: "/settings", children: "Settings" }) }),
119
+ /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(components.LogoutButton, {}) })
120
+ ] });
121
+ }
122
+ var MeActions_default = MeActions;
123
+ function MePanel({ layout, user }) {
124
+ return /* @__PURE__ */ jsxRuntime.jsxs(
125
+ "div",
126
+ {
127
+ className: components.tw(
128
+ "ml-auto flex items-center gap-3",
129
+ layout === "sidebar" ? "flex-row-reverse" : null
130
+ ),
131
+ children: [
132
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-end gap-0.5 text-white", children: [
133
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: user?.name }),
134
+ /* @__PURE__ */ jsxRuntime.jsx(MeActions_default, {})
135
+ ] }),
136
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-9 w-9 flex-none rounded-full border-4 border-slate-500" })
137
+ ]
138
+ }
139
+ );
140
+ }
141
+ var MePanel_default = MePanel;
142
+ async function AppLayout({ children, user }) {
143
+ const config2 = getConfig();
144
+ const layout = await getLayout();
145
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: components.tw("", layout === "sidebar" ? "grid grid-cols-[12rem_1fr]" : null), children: [
146
+ /* @__PURE__ */ jsxRuntime.jsx("header", { className: "bg-slate-800", children: /* @__PURE__ */ jsxRuntime.jsx(components.Container, { isFullWidth: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
147
+ "div",
148
+ {
149
+ className: components.tw(
150
+ "flex items-center",
151
+ layout === "sidebar" ? "-mx-4 h-screen flex-col py-4" : "h-16 border-b border-slate-700"
152
+ ),
153
+ children: [
154
+ /* @__PURE__ */ jsxRuntime.jsxs(
155
+ components.Link,
156
+ {
157
+ className: components.tw(layout === "sidebar" ? "h-12 w-12" : "h-9 w-9"),
158
+ href: "/",
159
+ children: [
160
+ config2.logo?.(),
161
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: config2.app.name })
162
+ ]
163
+ }
164
+ ),
165
+ /* @__PURE__ */ jsxRuntime.jsx(AppNavigation_default, { layout }),
166
+ /* @__PURE__ */ jsxRuntime.jsx(MePanel_default, { layout, user })
167
+ ]
168
+ }
169
+ ) }) }),
170
+ /* @__PURE__ */ jsxRuntime.jsx("main", { className: "mb-10 block", children })
171
+ ] });
172
+ }
173
+ var AppLayout_default = AppLayout;
174
+ var classNames = {
175
+ root: "bg-slate-800 gap-8",
176
+ logo: "mx-auto flex h-12 w-32 items-end",
177
+ panel: "rounded bg-white p-8 shadow-lg pb-10",
178
+ title: "text-lg font-semibold mb-6 leading-none",
179
+ link: "font-semibold text-link",
180
+ actions: "pt-2 w-full",
181
+ footer: "-mb-2"
182
+ };
183
+ function Auth(props) {
184
+ return /* @__PURE__ */ jsxRuntime.jsx(components.Auth, { ...props, classNames });
185
+ }
186
+ var Auth_default = Auth;
187
+ var classMap = {
188
+ danger: "bg-red-100 text-red-700",
189
+ error: "bg-red-100 text-red-700",
190
+ info: "bg-sky-100 text-sky-700",
191
+ warning: "bg-yellow-100 text-yellow-700",
192
+ success: "bg-green-100 text-green-700"
193
+ };
194
+ var dotMap = {
195
+ danger: "fill-red-400",
196
+ error: "fill-red-400",
197
+ info: "fill-sky-400",
198
+ warning: "fill-yellow-400",
199
+ success: "fill-green-400"
200
+ };
201
+ function Badge({ children, variant }) {
202
+ return /* @__PURE__ */ jsxRuntime.jsxs(
203
+ "strong",
204
+ {
205
+ className: components.tw(
206
+ "inline-flex items-center gap-1.5 rounded-full bg-slate-100 px-2 py-1 text-xs font-medium text-slate-600",
207
+ variant ? classMap[variant] : null
208
+ ),
209
+ children: [
210
+ /* @__PURE__ */ jsxRuntime.jsx(
211
+ "svg",
212
+ {
213
+ "aria-hidden": "true",
214
+ className: components.tw("h-1.5 w-1.5 fill-slate-400", variant ? dotMap[variant] : null),
215
+ viewBox: "0 0 6 6",
216
+ children: /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "3", cy: "3", r: "3" })
217
+ }
218
+ ),
219
+ children
220
+ ]
221
+ }
222
+ );
223
+ }
224
+ var Badge_default = Badge;
225
+ function Dashboard({ children, title }) {
226
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "py-8", children: [
227
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "mx-auto text-center text-4xl font-semibold", children: title }),
228
+ children
229
+ ] });
230
+ }
231
+ var Dashboard_default = Dashboard;
232
+ function FilterBarClearButton({
233
+ onClick
234
+ }) {
235
+ return /* @__PURE__ */ jsxRuntime.jsxs(
236
+ "button",
237
+ {
238
+ className: "absolute right-0 top-0 flex h-full w-10 select-none items-center justify-center",
239
+ onClick,
240
+ type: "button",
241
+ children: [
242
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Remove" }),
243
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex h-4 w-4 items-center justify-center rounded-full bg-white leading-none text-slate-800", children: "\xD7" })
244
+ ]
245
+ }
246
+ );
247
+ }
248
+ var FilterBarClearButton_default = FilterBarClearButton;
249
+ var data = [
250
+ {
251
+ id: "0",
252
+ name: "No"
253
+ },
254
+ {
255
+ id: "1",
256
+ name: "Yes"
257
+ }
258
+ ];
259
+ function BooleanFilter({
260
+ name,
261
+ onChange,
262
+ value
263
+ }) {
264
+ return /* @__PURE__ */ jsxRuntime.jsx(components.Dropdown, { data, name, onChange, value, isPanelOnly: true });
265
+ }
266
+ function renderBooleanValue(value) {
267
+ return data.find((item) => item.id === value)?.name || "";
268
+ }
269
+ var BooleanFilter_default = BooleanFilter;
270
+ function DateFilter({ name, onChange, value }) {
271
+ return /* @__PURE__ */ jsxRuntime.jsx(components.CalendarInput, { name, onChange, value, isPanelOnly: true, isRange: true });
272
+ }
273
+ function transformDateValue(value) {
274
+ return value || "";
275
+ }
276
+ var LENGTH_OF_YEAR = 4;
277
+ function renderDateString(value, noYear) {
278
+ const date = new Date(value);
279
+ if (Number.isNaN(date.getTime())) {
280
+ return "";
281
+ }
282
+ const day = date.getDate().toString().padStart(2, "0");
283
+ const month = (date.getMonth() + 1).toString().padStart(2, "0");
284
+ const year = date.getFullYear();
285
+ return `${day}/${month}${noYear ? "" : `/${year}`}`;
286
+ }
287
+ function renderDateValue(value) {
288
+ if (value.includes(",")) {
289
+ const values = value.split(",");
290
+ const years = values.map((item) => parseInt(item.substring(0, LENGTH_OF_YEAR), 10));
291
+ return value.split(",").map(
292
+ (item) => renderDateString(
293
+ item,
294
+ years[0] === years[1] && years[0] === (/* @__PURE__ */ new Date()).getFullYear()
295
+ )
296
+ ).join(" - ");
297
+ }
298
+ return renderDateString(value);
299
+ }
300
+ var DateFilter_default = DateFilter;
301
+ function DropdownFilter({
302
+ data: data2,
303
+ name,
304
+ onChange,
305
+ value
306
+ }) {
307
+ return /* @__PURE__ */ jsxRuntime.jsx(components.Dropdown, { data: data2, name, onChange, value, isPanelOnly: true });
308
+ }
309
+ function renderDropdownValue(value, data2) {
310
+ return data2?.find((item) => item.id === value)?.name || "";
311
+ }
312
+ var DropdownFilter_default = DropdownFilter;
313
+ var map = {
314
+ boolean: { component: BooleanFilter_default, renderValue: renderBooleanValue },
315
+ date: {
316
+ component: DateFilter_default,
317
+ renderValue: renderDateValue,
318
+ size: "w-96",
319
+ transformValue: transformDateValue
320
+ },
321
+ dropdown: { component: DropdownFilter_default, renderValue: renderDropdownValue }
322
+ };
323
+ var DEFAULT_SIZE = "w-56";
324
+ function FilterBarItem({
325
+ data: data2,
326
+ label,
327
+ name,
328
+ onChange,
329
+ type,
330
+ value
331
+ }) {
332
+ const panel = react.useRef(null);
333
+ function handleChange(event) {
334
+ onChange(name, event.target.value);
335
+ panel.current?.hidePopover();
336
+ }
337
+ function handleClear() {
338
+ onChange(name, "");
339
+ }
340
+ const { component: FilterComponent, renderValue, size, transformValue } = map[type];
341
+ return /* @__PURE__ */ jsxRuntime.jsxs(
342
+ "li",
343
+ {
344
+ className: components.tw(
345
+ "relative inline-flex h-8 items-center gap-2 rounded-full border px-5 text-xs text-white",
346
+ value ? "border-solid border-slate-400" : "border-dashed border-slate-400",
347
+ value ? "bg-slate-700 pr-10" : "text-slate-300"
348
+ ),
349
+ children: [
350
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "", children: label }),
351
+ value ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "border-l border-l-slate-300 pl-2 font-semibold", children: renderValue(value, data2) }) : null,
352
+ /* @__PURE__ */ jsxRuntime.jsx(
353
+ "button",
354
+ {
355
+ className: components.tw(
356
+ "absolute left-0 top-0 h-full select-none text-transparent",
357
+ value ? "right-10" : "right-0"
358
+ ),
359
+ id: `${name}-control`,
360
+ popovertarget: `${name}-target`,
361
+ type: "button",
362
+ children: "Edit"
363
+ }
364
+ ),
365
+ value ? /* @__PURE__ */ jsxRuntime.jsx(FilterBarClearButton_default, { onClick: handleClear }) : null,
366
+ /* @__PURE__ */ jsxRuntime.jsx(
367
+ "div",
368
+ {
369
+ ref: panel,
370
+ anchor: `${name}-control`,
371
+ className: components.tw(
372
+ "show left-[anchor(left)] top-[anchor(bottom)] -ml-px mt-2 origin-top-left origin-top-left rounded bg-white shadow-lg",
373
+ size || DEFAULT_SIZE
374
+ ),
375
+ id: `${name}-target`,
376
+ popover: "auto",
377
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-1", role: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
378
+ FilterComponent,
379
+ {
380
+ data: data2,
381
+ name,
382
+ onChange: handleChange,
383
+ value: transformValue ? transformValue(value) : value
384
+ }
385
+ ) })
386
+ }
387
+ )
388
+ ]
389
+ }
390
+ );
391
+ }
392
+ var FilterBarItem_default = FilterBarItem;
393
+ function FilterBar({ hasSearch, map: map2 }) {
394
+ const router = navigation.useRouter();
395
+ const [filters, setFilter] = hooks.useFilters();
396
+ const [search, setSearch] = react.useState(filters.get("search") || "");
397
+ function handleChange(name, value) {
398
+ setFilter(name, value);
399
+ router.refresh();
400
+ }
401
+ function handleSearchChange(event) {
402
+ setSearch(event.target.value || "");
403
+ }
404
+ function handleSearchClear() {
405
+ setSearch("");
406
+ setFilter("search", "");
407
+ }
408
+ function handleSearchKeyDown(event) {
409
+ if (event.key === "Enter") {
410
+ setFilter("search", event.currentTarget.value);
411
+ }
412
+ }
413
+ return /* @__PURE__ */ jsxRuntime.jsxs("ul", { className: "relative flex gap-2 before:absolute before:left-[calc(50%-50vw)] before:top-full before:h-24 before:w-screen before:bg-slate-800", children: [
414
+ hasSearch ? /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "relative", children: [
415
+ /* @__PURE__ */ jsxRuntime.jsx(
416
+ components.TextInput,
417
+ {
418
+ classNames: {
419
+ root: {
420
+ default: components.tw(
421
+ "h-8 w-56 rounded-full border border-slate-400 px-3 text-xs text-white placeholder:text-slate-300",
422
+ filters.get("search") ? "bg-slate-700" : "bg-transparent focus:bg-slate-700"
423
+ )
424
+ }
425
+ },
426
+ name: "search",
427
+ onChange: handleSearchChange,
428
+ onKeyDown: handleSearchKeyDown,
429
+ placeholder: "Search...",
430
+ value: search
431
+ }
432
+ ),
433
+ filters.get("search") ? /* @__PURE__ */ jsxRuntime.jsx(FilterBarClearButton_default, { onClick: handleSearchClear }) : null
434
+ ] }) : null,
435
+ (map2 || []).map((filter) => /* @__PURE__ */ jsxRuntime.jsx(
436
+ FilterBarItem_default,
437
+ {
438
+ onChange: handleChange,
439
+ value: filters.get(filter.name) || "",
440
+ ...filter
441
+ },
442
+ filter.name
443
+ ))
444
+ ] });
445
+ }
446
+ var FilterBar_default = FilterBar;
447
+ function renderMeta(meta) {
448
+ if (!meta) {
449
+ return null;
450
+ }
451
+ if (Array.isArray(meta)) {
452
+ return /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex items-center gap-4 text-xs text-slate-600", children: meta.map((item) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: item }, String(item))) });
453
+ }
454
+ return /* @__PURE__ */ jsxRuntime.jsx("table", { className: "w-full text-xs", children: /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: Object.entries(meta).map(([key, value]) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "odd:bg-slate-100", children: [
455
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-2 font-semibold", children: key }),
456
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "p-2 text-right", children: value || "-" })
457
+ ] }, key)) }) });
458
+ }
459
+ function ListItem({
460
+ actions: Actions,
461
+ // eslint-disable-line @typescript-eslint/naming-convention
462
+ description,
463
+ href,
464
+ id,
465
+ meta,
466
+ title
467
+ }) {
468
+ return /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsxs("article", { className: "bg-panel overflow-hidden rounded p-4 shadow-[0px_0px_0px_1px_rgba(9,9,11,0.07),0px_2px_2px_0px_rgba(9,9,11,0.05)]", children: [
469
+ title ? /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-lg font-semibold", children: href ? /* @__PURE__ */ jsxRuntime.jsx(components.Link, { href, children: title }) : title }) : null,
470
+ description ? /* @__PURE__ */ jsxRuntime.jsx("div", { children: description }) : null,
471
+ meta || Actions ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4 flex items-center justify-between border-t border-slate-200 pt-3", children: [
472
+ meta ? renderMeta(meta) : null,
473
+ Actions ? /* @__PURE__ */ jsxRuntime.jsx(Actions, { id }) : null
474
+ ] }) : null
475
+ ] }) });
476
+ }
477
+ var ListItem_default = ListItem;
478
+ function GridListItem({
479
+ href,
480
+ image,
481
+ imageHref,
482
+ meta,
483
+ subtitle,
484
+ title
485
+ }) {
486
+ return /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsxs("article", { className: "bg-panel overflow-hidden rounded p-4 shadow", children: [
487
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative mb-4 h-64 rounded border border border-slate-300 bg-slate-50 p-4", children: image ? /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
488
+ /* @__PURE__ */ jsxRuntime.jsx("img", { alt: "", className: "h-full w-full object-contain", src: image }),
489
+ imageHref ? /* @__PURE__ */ jsxRuntime.jsx(components.Link, { className: "absolute inset-0", href: imageHref, scroll: false, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Edit Image" }) }) : null
490
+ ] }) : imageHref ? /* @__PURE__ */ jsxRuntime.jsxs(
491
+ components.Link,
492
+ {
493
+ className: "absolute inset-0 flex flex-col items-center justify-center gap-3 font-semibold text-slate-500",
494
+ href: imageHref,
495
+ scroll: false,
496
+ children: [
497
+ /* @__PURE__ */ jsxRuntime.jsx("i", { className: "block h-12 w-12 rounded-full border-2 border-slate-300" }),
498
+ "Add Image"
499
+ ]
500
+ }
501
+ ) : null }),
502
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-base font-semibold", children: href ? /* @__PURE__ */ jsxRuntime.jsx(components.Link, { href, children: title }) : title }),
503
+ subtitle ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-slate-500", children: subtitle }) : null,
504
+ meta ? /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
505
+ /* @__PURE__ */ jsxRuntime.jsx("hr", { className: "my-4" }),
506
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-between", children: meta ? renderMeta(meta) : null })
507
+ ] }) : null,
508
+ href ? /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
509
+ /* @__PURE__ */ jsxRuntime.jsx("hr", { className: "my-4" }),
510
+ /* @__PURE__ */ jsxRuntime.jsx(components.Link, { href, scroll: false, children: "Edit" })
511
+ ] }) : null
512
+ ] }) });
513
+ }
514
+ var GridListItem_default = GridListItem;
515
+ function defaultTransformer() {
516
+ return {
517
+ id: 0,
518
+ title: ""
519
+ };
520
+ }
521
+ var reservedSearchParams = ["action"];
522
+ function checkHasFilters(searchParams) {
523
+ return Array.from(searchParams.entries()).some(
524
+ ([key, value]) => !reservedSearchParams.includes(key) && Boolean(value)
525
+ );
526
+ }
527
+ async function List({
528
+ actions,
529
+ columns,
530
+ emptyMessageProps,
531
+ filters,
532
+ fn,
533
+ hasSearch,
534
+ isMinimal,
535
+ params,
536
+ renderItem = ListItem_default,
537
+ transformer
538
+ }) {
539
+ let searchParams;
540
+ try {
541
+ const { headers } = await import('next/headers');
542
+ searchParams = new URLSearchParams(headers().get("x-search-params") || "");
543
+ } catch (err) {
544
+ searchParams = new URLSearchParams();
545
+ }
546
+ const [response, error] = await fn(params, searchParams);
547
+ if (!Array.isArray(response)) {
548
+ throw new Error(
549
+ "Response is not an array. Did you forget to return an Errorable object in the function?"
550
+ );
551
+ }
552
+ if (error) {
553
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { children: "Error" });
554
+ }
555
+ const data2 = await filterList(response.map(transformer || defaultTransformer));
556
+ const hasFilters = checkHasFilters(searchParams);
557
+ const componentEmptyMessageProps = hasFilters ? {
558
+ children: "Try adjusting the filters above. If you think this is a mistake, please contact your site administrator.",
559
+ title: "No results match the current filters"
560
+ } : emptyMessageProps;
561
+ return /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
562
+ (filters || hasSearch) && (data2.length || hasFilters) ? /* @__PURE__ */ jsxRuntime.jsx(FilterBar_default, { hasSearch, map: filters }) : null,
563
+ data2.length ? /* @__PURE__ */ jsxRuntime.jsx(
564
+ "ul",
565
+ {
566
+ className: components.tw(
567
+ "relative",
568
+ columns ? "grid grid-cols-3 gap-6" : "flex flex-col gap-4"
569
+ ),
570
+ children: data2.map((item) => /* @__PURE__ */ jsxRuntime.jsx(react.Fragment, { children: renderItem({ actions, ...item }) }, item.id))
571
+ }
572
+ ) : /* @__PURE__ */ jsxRuntime.jsx(components.EmptyMessage, { ...componentEmptyMessageProps, classNameProps: { isMinimal } })
573
+ ] });
574
+ }
575
+ var List_default = List;
576
+ function GridList(props) {
577
+ return /* @__PURE__ */ jsxRuntime.jsx(List_default, { ...props, columns: 3, renderItem: GridListItem_default });
578
+ }
579
+ var GridList_default = GridList;
580
+ var iconClassMap = {
581
+ danger: "bg-[url(/admin/images/danger.svg)]",
582
+ info: "bg-[url(/admin/images/info.svg)]",
583
+ success: "bg-[url(/admin/images/success.svg)]",
584
+ warning: "bg-[url(/admin/images/warning.svg)]"
585
+ };
586
+ var classMap2 = {
587
+ danger: "bg-red-50 text-red-700",
588
+ info: "bg-sky-50 text-sky-700",
589
+ success: "bg-green-50 text-green-700",
590
+ warning: "bg-yellow-50 text-yellow-700"
591
+ };
592
+ function InfoPanel({ children, variant = "info" }) {
593
+ return /* @__PURE__ */ jsxRuntime.jsxs("aside", { className: components.tw("grid grid-cols-[1rem_auto] gap-4 rounded p-4", classMap2[variant]), children: [
594
+ /* @__PURE__ */ jsxRuntime.jsx("i", { className: components.tw("aspect-square bg-contain bg-no-repeat", iconClassMap[variant]) }),
595
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children })
596
+ ] });
597
+ }
598
+ var InfoPanel_default = InfoPanel;
599
+ function ListAction({
600
+ id,
601
+ onClick,
602
+ label,
603
+ variant
604
+ }) {
605
+ function handleClick() {
606
+ onClick(id);
607
+ }
608
+ return /* @__PURE__ */ jsxRuntime.jsx(components.ConfirmableButton, { onClick: handleClick, variant, isText: true, children: label });
609
+ }
610
+ var ListAction_default = ListAction;
611
+ function ListActions({ actions, id }) {
612
+ const [isOpen, setIsOpen, ref] = hooks.useClickOutside();
613
+ function toggleIsOpen() {
614
+ setIsOpen(!isOpen);
615
+ }
616
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, className: "flex flex-row-reverse items-center gap-4", children: [
617
+ /* @__PURE__ */ jsxRuntime.jsxs(
618
+ "button",
619
+ {
620
+ className: "h-4 rotate-90 text-xs leading-[1em] tracking-tighter text-slate-500",
621
+ onClick: toggleIsOpen,
622
+ type: "button",
623
+ children: [
624
+ "\u2022\u2022\u2022",
625
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "sr-only", children: [
626
+ isOpen ? "Close" : "Open",
627
+ " Actions"
628
+ ] })
629
+ ]
630
+ }
631
+ ),
632
+ isOpen ? /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "show relative flex origin-right gap-4 bg-white before:absolute before:-bottom-2 before:-top-2 before:left-[-999em] before:right-full before:bg-white/80", children: actions.map(({ label, onClick, variant }) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(ListAction_default, { id, label, onClick, variant }) }, label)) }) : null
633
+ ] });
634
+ }
635
+ var ListActions_default = ListActions;
636
+ function TabsComponent({ basePath = "", data: data2 }) {
637
+ const navigation = useNavigation_default(data2, { basePath });
638
+ return /* @__PURE__ */ jsxRuntime.jsx("nav", { children: /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex gap-4", children: navigation.map(({ href, isActive, label }) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(
639
+ components.Link,
640
+ {
641
+ className: components.tw(
642
+ "block border-b-4 border-transparent px-1 pb-2 font-semibold",
643
+ isActive ? "border-primary" : "opacity-80 hover:opacity-100"
644
+ ),
645
+ href,
646
+ children: label
647
+ }
648
+ ) }, href)) }) });
649
+ }
650
+ var TabsComponent_default = TabsComponent;
651
+ async function Tabs({ basePath, data: data2 }) {
652
+ return /* @__PURE__ */ jsxRuntime.jsx(TabsComponent_default, { basePath, data: await filterList(utility.filterNull(data2)) });
653
+ }
654
+ var Tabs_default = Tabs;
655
+ async function Page({
656
+ basePath,
657
+ children,
658
+ isFullWidth,
659
+ tabs,
660
+ title
661
+ }) {
662
+ const layout = await getLayout();
663
+ return /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
664
+ /* @__PURE__ */ jsxRuntime.jsx(
665
+ "header",
666
+ {
667
+ className: components.tw(
668
+ "",
669
+ layout === "sidebar" ? "bg-slate-200" : "bg-slate-800 pb-16 text-white"
670
+ ),
671
+ children: /* @__PURE__ */ jsxRuntime.jsxs(components.Container, { isFullWidth: layout === "sidebar" || isFullWidth, children: [
672
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between py-10", children: [
673
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "min-h-10 text-3xl font-semibold", children: title }),
674
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-2", id: "page-actions" })
675
+ ] }),
676
+ tabs ? /* @__PURE__ */ jsxRuntime.jsx(
677
+ "div",
678
+ {
679
+ className: components.tw(
680
+ "-mt-4",
681
+ layout === "sidebar" ? "" : "mb-8 border-b border-slate-700"
682
+ ),
683
+ children: /* @__PURE__ */ jsxRuntime.jsx(Tabs_default, { basePath, data: utility.filterNull(tabs) })
684
+ }
685
+ ) : null
686
+ ] })
687
+ }
688
+ ),
689
+ /* @__PURE__ */ jsxRuntime.jsx(components.Container, { isFullWidth: layout === "sidebar" || isFullWidth, children: /* @__PURE__ */ jsxRuntime.jsx(
690
+ "div",
691
+ {
692
+ className: components.tw("flex flex-col gap-8", layout === "sidebar" ? "mt-8" : "-mt-16"),
693
+ children
694
+ }
695
+ ) })
696
+ ] });
697
+ }
698
+ var Page_default = Page;
699
+ function Panel({ action, children, title }) {
700
+ return /* @__PURE__ */ jsxRuntime.jsxs("article", { className: "bg-panel relative overflow-hidden rounded p-6 shadow-[0px_0px_0px_1px_rgba(9,9,11,0.07),0px_2px_2px_0px_rgba(9,9,11,0.05)]", children: [
701
+ title ? /* @__PURE__ */ jsxRuntime.jsxs("header", { children: [
702
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "mb-4 border-b border-slate-200 pb-3 text-lg font-semibold leading-none", children: title }),
703
+ action ? /* @__PURE__ */ jsxRuntime.jsx(components.Button, { href: action.href, children: action.label }) : null
704
+ ] }) : null,
705
+ children
706
+ ] });
707
+ }
708
+ var Panel_default = Panel;
709
+ function PageActions({ children }) {
710
+ const ref = react.useRef(null);
711
+ const [mounted, setMounted] = react.useState(false);
712
+ react.useEffect(() => {
713
+ ref.current = document.getElementById("page-actions");
714
+ setMounted(true);
715
+ }, []);
716
+ return mounted && ref.current ? reactDom.createPortal(children, ref.current) : null;
717
+ }
718
+ var PageActions_default = PageActions;
719
+ var classNames2 = components.twx({
720
+ actionList: () => ({
721
+ root: "flex gap-2"
722
+ }),
723
+ button: (props) => ({
724
+ root: {
725
+ danger: "border-red-500 bg-red-500 text-white",
726
+ default: components.tw(
727
+ "text-md h-10 rounded border border-slate-300 bg-white px-5 text-slate-600",
728
+ props?.isFullWidth ? "w-full" : null
729
+ ),
730
+ primary: "bg-button-bg text-button-text border-none font-semibold"
731
+ }
732
+ }),
733
+ calendar: () => ({
734
+ root: "p-4 pb-3 text-sm text-slate-600",
735
+ head: "pb-2 text-center text-xs text-slate-400",
736
+ month: "w-full table-fixed",
737
+ day: {
738
+ default: "h-10 border border-slate-200",
739
+ highlighted: "bg-slate-100",
740
+ selected: "bg-slate-200"
741
+ }
742
+ }),
743
+ calendarNavigation: () => ({
744
+ root: "mb-6 flex items-center justify-between",
745
+ title: "text-base font-semibold",
746
+ control: "h-6 w-6 rounded-full border border-slate-300",
747
+ previous: "-order-1"
748
+ }),
749
+ checkboxInput: (props) => ({
750
+ root: components.tw("flex", props?.isInline ? "gap-6" : "flex-col gap-2"),
751
+ icon: {
752
+ default: "h-6 w-6 rounded border border-slate-300",
753
+ checked: "bg-green-500"
754
+ },
755
+ label: "pl-2 font-semibold"
756
+ }),
757
+ codeInput: () => ({
758
+ input: {
759
+ default: "focus:border-primary h-10 rounded border border-slate-300 text-center",
760
+ error: "border-red-500"
761
+ }
762
+ }),
763
+ definitionList: () => ({
764
+ root: "flex flex-col gap-4",
765
+ row: "border-b border-slate-200 pb-4",
766
+ term: "pb-1 text-slate-500"
767
+ }),
768
+ dropdown: () => ({
769
+ list: "overflow-hidden rounded",
770
+ item: { default: "block p-3 text-sm text-slate-700", selected: "bg-slate-100" },
771
+ title: "block leading-none",
772
+ meta: "mt-1 block text-xs leading-none text-slate-500",
773
+ icon: "mr-2 h-5 w-5 bg-[url(/admin/images/chevron.svg)] bg-contain bg-center bg-no-repeat",
774
+ clear: "mr-2 h-4 w-4 bg-[url(/admin/images/close.svg)] bg-contain bg-center bg-no-repeat"
775
+ }),
776
+ editableFieldset: () => ({
777
+ root: "bg-panel grid grid-cols-[30%_1fr] gap-8 rounded p-8 shadow",
778
+ title: "mb-8 text-lg font-semibold leading-none text-slate-700",
779
+ description: "text-slate-600",
780
+ actions: "flex justify-end gap-2 border-t border-slate-200 pt-4"
781
+ }),
782
+ editableFormField: () => ({
783
+ root: "grid grid-cols-[25%_1fr] border-t border-slate-200 py-4",
784
+ label: "flex items-center font-semibold leading-none",
785
+ field: "flex min-h-10 items-center"
786
+ }),
787
+ emptyMessage: (props) => ({
788
+ root: components.tw(
789
+ "relative mx-auto mt-4 w-full max-w-2xl p-16 text-center text-slate-500",
790
+ props?.isMinimal ? null : "rounded bg-white shadow before:pointer-events-none before:absolute before:inset-2 before:border-2 before:border-dashed"
791
+ ),
792
+ title: "mb-2 text-pretty text-xl font-semibold leading-tight",
793
+ description: "text-pretty",
794
+ action: "mt-6 flex justify-center"
795
+ }),
796
+ fieldset: () => ({
797
+ root: "rounded bg-white p-8 shadow",
798
+ title: "mb-8 text-lg font-semibold leading-none text-slate-700"
799
+ }),
800
+ form: () => ({
801
+ root: "flex flex-col gap-6"
802
+ }),
803
+ formField: (props) => ({
804
+ root: {
805
+ default: props?.isEditable ? "grid grid-cols-[25%_1fr] border-t border-slate-200 py-4" : ""
806
+ },
807
+ label: components.tw(
808
+ "flex font-semibold leading-none",
809
+ props?.isEditable ? "items-center" : "mb-2 justify-between"
810
+ ),
811
+ details: "mb-2 text-xs font-normal leading-none text-slate-500",
812
+ optional: "pl-2 text-xs font-normal leading-none text-slate-500",
813
+ error: components.tw(
814
+ "mt-2 flex items-center gap-1.5 text-red-600 before:h-4 before:w-4 before:rounded-full before:bg-[url(/admin/images/danger.svg)] before:bg-contain",
815
+ props?.isEditable ? "col-start-2" : ""
816
+ )
817
+ }),
818
+ imageInput: () => ({
819
+ root: "h-64 rounded border border-slate-300 bg-slate-50 p-8",
820
+ icon: "mx-auto mb-2 block h-12 w-12 rounded-full border-2 border-slate-300",
821
+ title: "mb-1 font-semibold",
822
+ description: "text-xs italic text-slate-700"
823
+ }),
824
+ inputPanel: () => ({
825
+ root: "show my-1 origin-top rounded border border-slate-300 bg-white shadow-md"
826
+ }),
827
+ loadingModal: () => ({
828
+ root: "open:backdrop:fade py-16 backdrop:bg-slate-700/50 backdrop:backdrop-blur-sm",
829
+ panel: "text-center text-lg font-semibold text-white"
830
+ }),
831
+ modal: () => ({
832
+ root: "open:backdrop:fade py-16 backdrop:bg-slate-700/50 backdrop:backdrop-blur-sm",
833
+ panel: "show bg-panel row-start-2 mx-auto w-full max-w-lg rounded p-6 text-left shadow-xl",
834
+ title: "mb-6 text-lg font-semibold",
835
+ actions: "flex justify-end"
836
+ }),
837
+ multiInput: () => ({
838
+ root: "flex flex-col gap-2 pt-2",
839
+ row: "grid grid-cols-[1fr_auto] has-[>_button]:gap-2"
840
+ }),
841
+ objectInput: () => ({
842
+ root: "flex flex-col gap-2"
843
+ }),
844
+ passwordInput: () => ({
845
+ action: {
846
+ default: "mr-2 h-6 w-6 overflow-hidden bg-[url(/admin/images/eye.svg)] bg-no-repeat indent-12",
847
+ selected: "bg-bottom"
848
+ }
849
+ }),
850
+ staticTextInput: () => ({
851
+ root: {
852
+ default: "text-md flex min-h-10 flex-col justify-center rounded border border-slate-300 bg-white p-3",
853
+ error: "border-red-500"
854
+ },
855
+ label: "block leading-none",
856
+ meta: "mt-1 block text-xs leading-none text-slate-500",
857
+ placeholder: "block leading-none text-slate-500"
858
+ }),
859
+ switch: () => ({
860
+ root: "flex gap-4",
861
+ input: {
862
+ default: "h-6 w-10 flex-none cursor-pointer rounded-full bg-slate-300 p-1 transition-colors",
863
+ checked: "bg-green-500"
864
+ },
865
+ control: {
866
+ default: "h-4 w-4 translate-x-0 transform rounded-full bg-white shadow-md transition-transform",
867
+ checked: "translate-x-full"
868
+ },
869
+ label: "font-semibold",
870
+ details: "block text-xs text-slate-500"
871
+ }),
872
+ textArea: () => ({
873
+ root: {
874
+ default: "text-md focus:border-primary rounded border border-slate-300 px-3 py-2",
875
+ error: "border-red-500"
876
+ }
877
+ }),
878
+ textButton: () => ({
879
+ root: { danger: "text-red-600" }
880
+ }),
881
+ textInput: () => ({
882
+ root: {
883
+ default: "text-md focus:border-primary h-10 rounded border border-slate-300 px-3",
884
+ error: "border-red-500"
885
+ },
886
+ prefix: {
887
+ default: "peer-focus:border-primary relative -mr-1 rounded-l border border-slate-300 bg-white px-3 text-sm text-slate-600"
888
+ }
889
+ }),
890
+ toast: () => ({
891
+ root: {
892
+ default: "rounded border px-4 py-2",
893
+ success: "border-green-300 bg-green-100 text-green-700",
894
+ error: "border-red-300 bg-red-100 text-red-700"
895
+ }
896
+ })
897
+ });
898
+ var config_default = classNames2;
899
+
900
+ // src/components/Config/index.tsx
901
+ function Config({ data: data2 }) {
902
+ if (data2) {
903
+ setConfig(data2);
904
+ }
905
+ return null;
906
+ }
907
+ var Config_default = Config;
908
+ var inter = google.Inter({
909
+ subsets: ["latin"],
910
+ variable: "--font-inter"
911
+ });
912
+ function RootLayout({ children, config: config2, logo }) {
913
+ if (config2) {
914
+ setConfig(config2, logo);
915
+ }
916
+ return /* @__PURE__ */ jsxRuntime.jsxs("html", { lang: "en", children: [
917
+ /* @__PURE__ */ jsxRuntime.jsx("head", {}),
918
+ /* @__PURE__ */ jsxRuntime.jsxs(
919
+ "body",
920
+ {
921
+ className: components.tw(
922
+ inter.variable,
923
+ "overflow-x-hidden overflow-y-scroll bg-slate-50 font-sans text-sm text-slate-800 has-[[data-modal][open]]:overflow-hidden"
924
+ ),
925
+ children: [
926
+ /* @__PURE__ */ jsxRuntime.jsx(
927
+ "script",
928
+ {
929
+ dangerouslySetInnerHTML: {
930
+ __html: "(function(d){var v=d.createElement('div'),t=d.createElement('style'),s=v.style;s.overflowY='scroll';s.width='50';s.height='50';d.body.append(v);t.innerHTML='body:has([data-modal][open]){padding-right:'+(v.offsetWidth-v.clientWidth)+'px}';d.body.append(t);v.remove()}(document))"
931
+ }
932
+ }
933
+ ),
934
+ /* @__PURE__ */ jsxRuntime.jsx(Config_default, { data: config2 }),
935
+ /* @__PURE__ */ jsxRuntime.jsx(components.ClassNames, { data: config_default }),
936
+ children,
937
+ /* @__PURE__ */ jsxRuntime.jsx(components.Toaster, {})
938
+ ]
939
+ }
940
+ )
941
+ ] });
942
+ }
943
+ var RootLayout_default = RootLayout;
944
+ var options = { sidebar: "Side bar", topbar: "Top bar" };
945
+ function SettingsForm({ defaults }) {
946
+ const { fieldProps, formProps } = hooks.useEditableForm({
947
+ defaults,
948
+ onSubmit: submitSettingsForm
949
+ });
950
+ return /* @__PURE__ */ jsxRuntime.jsxs(components.EditableForm, { title: "Appearance", ...formProps, children: [
951
+ /* @__PURE__ */ jsxRuntime.jsx(
952
+ components.EditableRadioFormField,
953
+ {
954
+ ...fieldProps("layout"),
955
+ options,
956
+ renderValue: (value) => value ? options[value] || "-" : "-"
957
+ }
958
+ ),
959
+ /* @__PURE__ */ jsxRuntime.jsx(components.EditableSwitchFormField, { ...fieldProps("isDark"), label: "Dark mode" })
960
+ ] });
961
+ }
962
+ var SettingsForm_default = SettingsForm;
963
+ async function SettingsPage({
964
+ children
965
+ }) {
966
+ const layout = await getLayout();
967
+ return /* @__PURE__ */ jsxRuntime.jsx(Page_default, { title: "Settings", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
968
+ /* @__PURE__ */ jsxRuntime.jsx(SettingsForm_default, { defaults: { layout } }),
969
+ children
970
+ ] }) });
971
+ }
972
+ var SettingsPage_default = SettingsPage;
973
+ function createFilterLink(pathname, searchParams, filters) {
974
+ const updatedSearchParams = new URLSearchParams({
975
+ ...Object.fromEntries(searchParams),
976
+ ...filters
977
+ });
978
+ return `${pathname}?${updatedSearchParams.toString()}`;
979
+ }
980
+ function getDir(currentDir, isSortActive) {
981
+ if (isSortActive) {
982
+ return currentDir === "asc" ? "desc" : "asc";
983
+ }
984
+ return "asc";
985
+ }
986
+ function createSortLink(pathname, searchParams, sort) {
987
+ const dir = getDir(searchParams.get("dir"), searchParams.get("sort") === sort);
988
+ return createFilterLink(pathname, searchParams, { sort, dir });
989
+ }
990
+ function getSortIconProps(searchParams, sort) {
991
+ if (searchParams.get("sort") === sort) {
992
+ return { dir: searchParams.get("dir") };
993
+ }
994
+ return { dir: null };
995
+ }
996
+ function isStringArray(array) {
997
+ return array.every((item) => typeof item === "string");
998
+ }
999
+ function parseColumns(columns) {
1000
+ if (columns.length === 0) {
1001
+ return [];
1002
+ }
1003
+ if (isStringArray(columns)) {
1004
+ return columns.map((key) => ({ key }));
1005
+ }
1006
+ return columns;
1007
+ }
1008
+ function TableClientComponent({
1009
+ columns,
1010
+ data: data2
1011
+ }) {
1012
+ const pathname = navigation.usePathname();
1013
+ const searchParams = navigation.useSearchParams();
1014
+ const parsedColumns = parseColumns(columns);
1015
+ const hasTitles = parsedColumns.some((column) => column.title);
1016
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-white shadow-sm", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full", children: [
1017
+ hasTitles ? /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsx("tr", { children: parsedColumns.map((column) => /* @__PURE__ */ jsxRuntime.jsx(
1018
+ "th",
1019
+ {
1020
+ className: components.tw(
1021
+ "p-4",
1022
+ column.type === "number" ? "text-right" : "text-left"
1023
+ ),
1024
+ children: column.title ? /* @__PURE__ */ jsxRuntime.jsxs(
1025
+ components.Link,
1026
+ {
1027
+ href: createSortLink(
1028
+ pathname,
1029
+ searchParams,
1030
+ column.key
1031
+ ),
1032
+ children: [
1033
+ column.title,
1034
+ " "
1035
+ ]
1036
+ }
1037
+ ) : null
1038
+ },
1039
+ column.key
1040
+ )) }) }) : null,
1041
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: data2.map((item) => /* @__PURE__ */ jsxRuntime.jsx("tr", { className: "odd:bg-slate-100", children: parsedColumns.map((column) => /* @__PURE__ */ jsxRuntime.jsx(
1042
+ "td",
1043
+ {
1044
+ className: components.tw(
1045
+ "border-x border-transparent p-4",
1046
+ getSortIconProps(searchParams, column.key).dir ? "border-sky-300 bg-sky-300/10" : "",
1047
+ column.type === "number" ? "text-right" : "text-left"
1048
+ ),
1049
+ children: item[column.key]
1050
+ },
1051
+ column.key
1052
+ )) }, item.id)) })
1053
+ ] }) });
1054
+ }
1055
+ var TableClientComponent_default = TableClientComponent;
1056
+ function defaultTransformer2(item) {
1057
+ return {
1058
+ id: item.id,
1059
+ ...item
1060
+ };
1061
+ }
1062
+ async function Table({
1063
+ columns,
1064
+ fn,
1065
+ searchParams
1066
+ }) {
1067
+ const [response, error] = await fn(searchParams);
1068
+ if (error) {
1069
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { children: "Error" });
1070
+ }
1071
+ const data2 = response.map(defaultTransformer2);
1072
+ return /* @__PURE__ */ jsxRuntime.jsx(TableClientComponent_default, { columns, data: data2 });
1073
+ }
1074
+ var Table_default = Table;
1075
+
1076
+ Object.defineProperty(exports, "Autocomplete", {
1077
+ enumerable: true,
1078
+ get: function () { return components.Autocomplete; }
1079
+ });
1080
+ Object.defineProperty(exports, "AutocompleteFormField", {
1081
+ enumerable: true,
1082
+ get: function () { return components.AutocompleteFormField; }
1083
+ });
1084
+ Object.defineProperty(exports, "Button", {
1085
+ enumerable: true,
1086
+ get: function () { return components.Button; }
1087
+ });
1088
+ Object.defineProperty(exports, "CalendarInput", {
1089
+ enumerable: true,
1090
+ get: function () { return components.CalendarInput; }
1091
+ });
1092
+ Object.defineProperty(exports, "CheckboxInput", {
1093
+ enumerable: true,
1094
+ get: function () { return components.CheckboxInput; }
1095
+ });
1096
+ Object.defineProperty(exports, "ConfirmableButton", {
1097
+ enumerable: true,
1098
+ get: function () { return components.ConfirmableButton; }
1099
+ });
1100
+ Object.defineProperty(exports, "ConnectedDropdown", {
1101
+ enumerable: true,
1102
+ get: function () { return components.ConnectedDropdown; }
1103
+ });
1104
+ Object.defineProperty(exports, "ContentFormField", {
1105
+ enumerable: true,
1106
+ get: function () { return components.ContentFormField; }
1107
+ });
1108
+ Object.defineProperty(exports, "DateFormField", {
1109
+ enumerable: true,
1110
+ get: function () { return components.DateFormField; }
1111
+ });
1112
+ Object.defineProperty(exports, "DateInput", {
1113
+ enumerable: true,
1114
+ get: function () { return components.DateInput; }
1115
+ });
1116
+ Object.defineProperty(exports, "DefinitionList", {
1117
+ enumerable: true,
1118
+ get: function () { return components.DefinitionList; }
1119
+ });
1120
+ Object.defineProperty(exports, "Dropdown", {
1121
+ enumerable: true,
1122
+ get: function () { return components.Dropdown; }
1123
+ });
1124
+ Object.defineProperty(exports, "DropdownFormField", {
1125
+ enumerable: true,
1126
+ get: function () { return components.DropdownFormField; }
1127
+ });
1128
+ Object.defineProperty(exports, "EditableDateFormField", {
1129
+ enumerable: true,
1130
+ get: function () { return components.EditableDateFormField; }
1131
+ });
1132
+ Object.defineProperty(exports, "EditableDropdownFormField", {
1133
+ enumerable: true,
1134
+ get: function () { return components.EditableDropdownFormField; }
1135
+ });
1136
+ Object.defineProperty(exports, "EditableForm", {
1137
+ enumerable: true,
1138
+ get: function () { return components.EditableForm; }
1139
+ });
1140
+ Object.defineProperty(exports, "EditableFormField", {
1141
+ enumerable: true,
1142
+ get: function () { return components.EditableFormField; }
1143
+ });
1144
+ Object.defineProperty(exports, "EditableMultiFormField", {
1145
+ enumerable: true,
1146
+ get: function () { return components.EditableMultiFormField; }
1147
+ });
1148
+ Object.defineProperty(exports, "EditableNumberFormField", {
1149
+ enumerable: true,
1150
+ get: function () { return components.EditableNumberFormField; }
1151
+ });
1152
+ Object.defineProperty(exports, "EditableSwitchFormField", {
1153
+ enumerable: true,
1154
+ get: function () { return components.EditableSwitchFormField; }
1155
+ });
1156
+ Object.defineProperty(exports, "EditableTextAreaFormField", {
1157
+ enumerable: true,
1158
+ get: function () { return components.EditableTextAreaFormField; }
1159
+ });
1160
+ Object.defineProperty(exports, "EditableTextFormField", {
1161
+ enumerable: true,
1162
+ get: function () { return components.EditableTextFormField; }
1163
+ });
1164
+ Object.defineProperty(exports, "EmptyMessage", {
1165
+ enumerable: true,
1166
+ get: function () { return components.EmptyMessage; }
1167
+ });
1168
+ Object.defineProperty(exports, "Fieldset", {
1169
+ enumerable: true,
1170
+ get: function () { return components.Fieldset; }
1171
+ });
1172
+ Object.defineProperty(exports, "Form", {
1173
+ enumerable: true,
1174
+ get: function () { return components.Form; }
1175
+ });
1176
+ Object.defineProperty(exports, "FormField", {
1177
+ enumerable: true,
1178
+ get: function () { return components.FormField; }
1179
+ });
1180
+ Object.defineProperty(exports, "FormSubmit", {
1181
+ enumerable: true,
1182
+ get: function () { return components.FormSubmit; }
1183
+ });
1184
+ Object.defineProperty(exports, "ImageFormField", {
1185
+ enumerable: true,
1186
+ get: function () { return components.ImageFormField; }
1187
+ });
1188
+ Object.defineProperty(exports, "ImageInput", {
1189
+ enumerable: true,
1190
+ get: function () { return components.ImageInput; }
1191
+ });
1192
+ Object.defineProperty(exports, "Link", {
1193
+ enumerable: true,
1194
+ get: function () { return components.Link; }
1195
+ });
1196
+ Object.defineProperty(exports, "LoadingModal", {
1197
+ enumerable: true,
1198
+ get: function () { return components.LoadingModal; }
1199
+ });
1200
+ Object.defineProperty(exports, "ModalForm", {
1201
+ enumerable: true,
1202
+ get: function () { return components.ModalForm; }
1203
+ });
1204
+ Object.defineProperty(exports, "MultiFormField", {
1205
+ enumerable: true,
1206
+ get: function () { return components.MultiFormField; }
1207
+ });
1208
+ Object.defineProperty(exports, "NumberFormField", {
1209
+ enumerable: true,
1210
+ get: function () { return components.NumberFormField; }
1211
+ });
1212
+ Object.defineProperty(exports, "NumberInput", {
1213
+ enumerable: true,
1214
+ get: function () { return components.NumberInput; }
1215
+ });
1216
+ Object.defineProperty(exports, "RadioInput", {
1217
+ enumerable: true,
1218
+ get: function () { return components.RadioInput; }
1219
+ });
1220
+ Object.defineProperty(exports, "Switch", {
1221
+ enumerable: true,
1222
+ get: function () { return components.Switch; }
1223
+ });
1224
+ Object.defineProperty(exports, "SwitchFormField", {
1225
+ enumerable: true,
1226
+ get: function () { return components.SwitchFormField; }
1227
+ });
1228
+ Object.defineProperty(exports, "TextArea", {
1229
+ enumerable: true,
1230
+ get: function () { return components.TextArea; }
1231
+ });
1232
+ Object.defineProperty(exports, "TextAreaFormField", {
1233
+ enumerable: true,
1234
+ get: function () { return components.TextAreaFormField; }
1235
+ });
1236
+ Object.defineProperty(exports, "TextFormField", {
1237
+ enumerable: true,
1238
+ get: function () { return components.TextFormField; }
1239
+ });
1240
+ Object.defineProperty(exports, "TextInput", {
1241
+ enumerable: true,
1242
+ get: function () { return components.TextInput; }
1243
+ });
1244
+ Object.defineProperty(exports, "Toaster", {
1245
+ enumerable: true,
1246
+ get: function () { return components.Toaster; }
1247
+ });
1248
+ exports.AppLayout = AppLayout_default;
1249
+ exports.Auth = Auth_default;
1250
+ exports.Badge = Badge_default;
1251
+ exports.Dashboard = Dashboard_default;
1252
+ exports.FilterBar = FilterBar_default;
1253
+ exports.GridList = GridList_default;
1254
+ exports.InfoPanel = InfoPanel_default;
1255
+ exports.List = List_default;
1256
+ exports.ListActions = ListActions_default;
1257
+ exports.Page = Page_default;
1258
+ exports.PageActions = PageActions_default;
1259
+ exports.Panel = Panel_default;
1260
+ exports.RootLayout = RootLayout_default;
1261
+ exports.SettingsPage = SettingsPage_default;
1262
+ exports.Table = Table_default;
1263
+ exports.getConfig = getConfig;
1264
+ exports.setConfig = setConfig;
1265
+ //# sourceMappingURL=out.js.map
1266
+ //# sourceMappingURL=index.cjs.map