dn-react-router-toolkit 0.4.4 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/dist/api/create_api_handler.d.mts +28 -0
  2. package/dist/api/create_api_handler.d.ts +28 -0
  3. package/dist/api/create_api_handler.js +148 -0
  4. package/dist/api/create_api_handler.mjs +132 -0
  5. package/dist/api/create_handler.d.mts +1 -1
  6. package/dist/api/create_handler.d.ts +1 -1
  7. package/dist/api/create_handler.js +27 -25
  8. package/dist/api/create_handler.mjs +27 -25
  9. package/dist/api/index.js +27 -25
  10. package/dist/api/index.mjs +27 -25
  11. package/dist/api/item_api_handler.d.mts +18 -0
  12. package/dist/api/item_api_handler.d.ts +18 -0
  13. package/dist/api/item_api_handler.js +55 -0
  14. package/dist/api/item_api_handler.mjs +30 -0
  15. package/dist/auth/index.d.mts +1 -2
  16. package/dist/auth/index.d.ts +1 -2
  17. package/dist/auth/index.js +13 -21
  18. package/dist/auth/index.mjs +12 -20
  19. package/dist/auth/with_auth.d.mts +3 -3
  20. package/dist/auth/with_auth.d.ts +3 -3
  21. package/dist/auth/with_auth.js +13 -21
  22. package/dist/auth/with_auth.mjs +12 -20
  23. package/dist/crud/crud_form.d.mts +13 -0
  24. package/dist/crud/crud_form.d.ts +13 -0
  25. package/dist/crud/crud_form.js +88 -0
  26. package/dist/crud/crud_form.mjs +55 -0
  27. package/dist/crud/crud_form_provider.d.mts +34 -0
  28. package/dist/crud/crud_form_provider.d.ts +34 -0
  29. package/dist/crud/crud_form_provider.js +160 -0
  30. package/dist/crud/crud_form_provider.mjs +124 -0
  31. package/dist/crud/crud_loader.d.mts +21 -0
  32. package/dist/crud/crud_loader.d.ts +21 -0
  33. package/dist/crud/crud_loader.js +288 -0
  34. package/dist/crud/crud_loader.mjs +273 -0
  35. package/dist/crud/crud_page.d.mts +25 -0
  36. package/dist/crud/crud_page.d.ts +25 -0
  37. package/dist/crud/crud_page.js +645 -0
  38. package/dist/crud/crud_page.mjs +616 -0
  39. package/dist/crud/generate_handlers.d.mts +15 -0
  40. package/dist/crud/generate_handlers.d.ts +15 -0
  41. package/dist/crud/generate_handlers.js +39 -0
  42. package/dist/crud/generate_handlers.mjs +14 -0
  43. package/dist/crud/generate_pages.d.mts +11 -0
  44. package/dist/crud/generate_pages.d.ts +11 -0
  45. package/dist/crud/generate_pages.js +52 -0
  46. package/dist/crud/generate_pages.mjs +17 -0
  47. package/dist/crud/generate_routes.d.mts +5 -0
  48. package/dist/crud/generate_routes.d.ts +5 -0
  49. package/dist/crud/generate_routes.js +62 -0
  50. package/dist/crud/generate_routes.mjs +27 -0
  51. package/dist/crud/index.d.mts +21 -0
  52. package/dist/crud/index.d.ts +21 -0
  53. package/dist/crud/index.js +970 -0
  54. package/dist/crud/index.mjs +945 -0
  55. package/dist/db/index.d.mts +4 -0
  56. package/dist/db/index.d.ts +4 -0
  57. package/dist/db/index.js +46 -0
  58. package/dist/db/index.mjs +8 -0
  59. package/dist/index.d.mts +3 -2
  60. package/dist/index.d.ts +3 -2
  61. package/dist/table/buttons.d.mts +10 -0
  62. package/dist/table/buttons.d.ts +10 -0
  63. package/dist/table/buttons.js +102 -0
  64. package/dist/table/buttons.mjs +71 -0
  65. package/dist/table/index.d.mts +9 -0
  66. package/dist/table/index.d.ts +9 -0
  67. package/dist/table/index.js +570 -0
  68. package/dist/table/index.mjs +543 -0
  69. package/dist/table/item_loader.d.mts +12 -0
  70. package/dist/table/item_loader.d.ts +12 -0
  71. package/dist/table/item_loader.js +51 -0
  72. package/dist/table/item_loader.mjs +26 -0
  73. package/dist/table/loader.d.mts +28 -0
  74. package/dist/table/loader.d.ts +28 -0
  75. package/dist/table/loader.js +70 -0
  76. package/dist/table/loader.mjs +48 -0
  77. package/dist/table/page.d.mts +27 -0
  78. package/dist/table/page.d.ts +27 -0
  79. package/dist/table/page.js +444 -0
  80. package/dist/table/page.mjs +415 -0
  81. package/dist/table/repository.d.mts +38 -0
  82. package/dist/table/repository.d.ts +38 -0
  83. package/dist/table/repository.js +76 -0
  84. package/dist/table/repository.mjs +56 -0
  85. package/dist/table/table.d.mts +27 -0
  86. package/dist/table/table.d.ts +27 -0
  87. package/dist/table/table.js +290 -0
  88. package/dist/table/table.mjs +255 -0
  89. package/package.json +21 -3
  90. package/dist/auth/temp_user.d.mts +0 -5
  91. package/dist/auth/temp_user.d.ts +0 -5
  92. package/dist/auth/temp_user.js +0 -18
  93. package/dist/auth/temp_user.mjs +0 -0
@@ -0,0 +1,616 @@
1
+ // src/crud/crud_page.tsx
2
+ import { useLoaderData as useLoaderData2, useLocation as useLocation3 } from "react-router";
3
+
4
+ // src/crud/crud_form_provider.tsx
5
+ import { useNavigate } from "react-router";
6
+ import { useStore } from "dn-react-toolkit/store";
7
+ import { createContext, useContext } from "react";
8
+ import React from "react";
9
+ var FormContext = createContext({});
10
+ function useFormContext() {
11
+ return useContext(FormContext);
12
+ }
13
+ function CrudFormProvider({
14
+ primaryKey = "id",
15
+ name,
16
+ prefix,
17
+ item,
18
+ columns = {},
19
+ children
20
+ }) {
21
+ const apiPrefix = `/api${prefix}`;
22
+ const store = useStore({
23
+ ...item || {}
24
+ });
25
+ const navigate = useNavigate();
26
+ const submit = async () => {
27
+ const res = await fetch(apiPrefix, {
28
+ method: "POST",
29
+ headers: {
30
+ "Content-Type": "application/json"
31
+ },
32
+ body: JSON.stringify(
33
+ Object.entries(store.state).reduce(
34
+ function reducer(acc, [key, value]) {
35
+ const converter = (value2) => {
36
+ if (value2 === void 0) {
37
+ return void 0;
38
+ }
39
+ if (value2 === null) {
40
+ return {
41
+ type: "null",
42
+ value: null
43
+ };
44
+ }
45
+ if (typeof value2 === "string") {
46
+ return {
47
+ type: "string",
48
+ value: value2
49
+ };
50
+ }
51
+ if (typeof value2 === "number") {
52
+ return {
53
+ type: "number",
54
+ value: value2
55
+ };
56
+ }
57
+ if (typeof value2 === "boolean") {
58
+ return {
59
+ type: "boolean",
60
+ value: value2
61
+ };
62
+ }
63
+ if (value2 instanceof Date) {
64
+ return {
65
+ type: "date",
66
+ value: value2.toISOString()
67
+ };
68
+ }
69
+ if (Array.isArray(value2)) {
70
+ return value2.map((v) => converter(v));
71
+ }
72
+ if (typeof value2 === "object") {
73
+ return Object.entries(
74
+ value2
75
+ ).reduce(reducer, {});
76
+ }
77
+ };
78
+ return {
79
+ ...acc,
80
+ [key]: converter(value)
81
+ };
82
+ },
83
+ {}
84
+ )
85
+ )
86
+ });
87
+ if (!res.ok) {
88
+ const { message } = await res.json();
89
+ alert(message);
90
+ return;
91
+ }
92
+ alert(`${name}\uB97C \uC800\uC7A5\uD588\uC2B5\uB2C8\uB2E4.`);
93
+ const { id } = await res.json();
94
+ navigate(`${prefix}/${id}`);
95
+ };
96
+ const deleteItem = async () => {
97
+ if (!item || !primaryKey) {
98
+ return;
99
+ }
100
+ const ok = confirm("\uC815\uB9D0\uB85C \uC0AD\uC81C\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?");
101
+ if (!ok) {
102
+ return;
103
+ }
104
+ const res = await fetch(`${apiPrefix}/${item[primaryKey]}`, {
105
+ method: "DELETE"
106
+ });
107
+ if (!res.ok) {
108
+ const { message } = await res.json();
109
+ alert(message);
110
+ return;
111
+ }
112
+ alert(`${name}\uB97C \uC0AD\uC81C\uD588\uC2B5\uB2C8\uB2E4.`);
113
+ navigate(`${prefix}`);
114
+ };
115
+ return /* @__PURE__ */ React.createElement(
116
+ FormContext.Provider,
117
+ {
118
+ value: { name, item, store, submit, delete: deleteItem, columns }
119
+ },
120
+ children
121
+ );
122
+ }
123
+
124
+ // src/table/page.tsx
125
+ import {
126
+ Link as Link3,
127
+ useLoaderData,
128
+ useLocation as useLocation2,
129
+ useNavigate as useNavigate2,
130
+ useSearchParams as useSearchParams3
131
+ } from "react-router";
132
+
133
+ // node_modules/react-icons/lib/iconBase.mjs
134
+ import React3 from "react";
135
+
136
+ // node_modules/react-icons/lib/iconContext.mjs
137
+ import React2 from "react";
138
+ var DefaultContext = {
139
+ color: void 0,
140
+ size: void 0,
141
+ className: void 0,
142
+ style: void 0,
143
+ attr: void 0
144
+ };
145
+ var IconContext = React2.createContext && /* @__PURE__ */ React2.createContext(DefaultContext);
146
+
147
+ // node_modules/react-icons/lib/iconBase.mjs
148
+ var _excluded = ["attr", "size", "title"];
149
+ function _objectWithoutProperties(source, excluded) {
150
+ if (source == null) return {};
151
+ var target = _objectWithoutPropertiesLoose(source, excluded);
152
+ var key, i;
153
+ if (Object.getOwnPropertySymbols) {
154
+ var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
155
+ for (i = 0; i < sourceSymbolKeys.length; i++) {
156
+ key = sourceSymbolKeys[i];
157
+ if (excluded.indexOf(key) >= 0) continue;
158
+ if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
159
+ target[key] = source[key];
160
+ }
161
+ }
162
+ return target;
163
+ }
164
+ function _objectWithoutPropertiesLoose(source, excluded) {
165
+ if (source == null) return {};
166
+ var target = {};
167
+ for (var key in source) {
168
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
169
+ if (excluded.indexOf(key) >= 0) continue;
170
+ target[key] = source[key];
171
+ }
172
+ }
173
+ return target;
174
+ }
175
+ function _extends() {
176
+ _extends = Object.assign ? Object.assign.bind() : function(target) {
177
+ for (var i = 1; i < arguments.length; i++) {
178
+ var source = arguments[i];
179
+ for (var key in source) {
180
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
181
+ target[key] = source[key];
182
+ }
183
+ }
184
+ }
185
+ return target;
186
+ };
187
+ return _extends.apply(this, arguments);
188
+ }
189
+ function ownKeys(e, r) {
190
+ var t = Object.keys(e);
191
+ if (Object.getOwnPropertySymbols) {
192
+ var o = Object.getOwnPropertySymbols(e);
193
+ r && (o = o.filter(function(r2) {
194
+ return Object.getOwnPropertyDescriptor(e, r2).enumerable;
195
+ })), t.push.apply(t, o);
196
+ }
197
+ return t;
198
+ }
199
+ function _objectSpread(e) {
200
+ for (var r = 1; r < arguments.length; r++) {
201
+ var t = null != arguments[r] ? arguments[r] : {};
202
+ r % 2 ? ownKeys(Object(t), true).forEach(function(r2) {
203
+ _defineProperty(e, r2, t[r2]);
204
+ }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function(r2) {
205
+ Object.defineProperty(e, r2, Object.getOwnPropertyDescriptor(t, r2));
206
+ });
207
+ }
208
+ return e;
209
+ }
210
+ function _defineProperty(obj, key, value) {
211
+ key = _toPropertyKey(key);
212
+ if (key in obj) {
213
+ Object.defineProperty(obj, key, { value, enumerable: true, configurable: true, writable: true });
214
+ } else {
215
+ obj[key] = value;
216
+ }
217
+ return obj;
218
+ }
219
+ function _toPropertyKey(t) {
220
+ var i = _toPrimitive(t, "string");
221
+ return "symbol" == typeof i ? i : i + "";
222
+ }
223
+ function _toPrimitive(t, r) {
224
+ if ("object" != typeof t || !t) return t;
225
+ var e = t[Symbol.toPrimitive];
226
+ if (void 0 !== e) {
227
+ var i = e.call(t, r || "default");
228
+ if ("object" != typeof i) return i;
229
+ throw new TypeError("@@toPrimitive must return a primitive value.");
230
+ }
231
+ return ("string" === r ? String : Number)(t);
232
+ }
233
+ function Tree2Element(tree) {
234
+ return tree && tree.map((node, i) => /* @__PURE__ */ React3.createElement(node.tag, _objectSpread({
235
+ key: i
236
+ }, node.attr), Tree2Element(node.child)));
237
+ }
238
+ function GenIcon(data) {
239
+ return (props) => /* @__PURE__ */ React3.createElement(IconBase, _extends({
240
+ attr: _objectSpread({}, data.attr)
241
+ }, props), Tree2Element(data.child));
242
+ }
243
+ function IconBase(props) {
244
+ var elem = (conf) => {
245
+ var {
246
+ attr,
247
+ size,
248
+ title
249
+ } = props, svgProps = _objectWithoutProperties(props, _excluded);
250
+ var computedSize = size || conf.size || "1em";
251
+ var className;
252
+ if (conf.className) className = conf.className;
253
+ if (props.className) className = (className ? className + " " : "") + props.className;
254
+ return /* @__PURE__ */ React3.createElement("svg", _extends({
255
+ stroke: "currentColor",
256
+ fill: "currentColor",
257
+ strokeWidth: "0"
258
+ }, conf.attr, attr, svgProps, {
259
+ className,
260
+ style: _objectSpread(_objectSpread({
261
+ color: props.color || conf.color
262
+ }, conf.style), props.style),
263
+ height: computedSize,
264
+ width: computedSize,
265
+ xmlns: "http://www.w3.org/2000/svg"
266
+ }), title && /* @__PURE__ */ React3.createElement("title", null, title), props.children);
267
+ };
268
+ return IconContext !== void 0 ? /* @__PURE__ */ React3.createElement(IconContext.Consumer, null, (conf) => elem(conf)) : elem(DefaultContext);
269
+ }
270
+
271
+ // node_modules/react-icons/go/index.mjs
272
+ function GoArrowDown(props) {
273
+ return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24" }, "child": [{ "tag": "path", "attr": { "d": "M4.97 13.22a.75.75 0 0 1 1.06 0L11 18.19V3.75a.75.75 0 0 1 1.5 0v14.44l4.97-4.97a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734l-6.25 6.25a.75.75 0 0 1-1.06 0l-6.25-6.25a.75.75 0 0 1 0-1.06Z" }, "child": [] }] })(props);
274
+ }
275
+ function GoArrowUp(props) {
276
+ return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24" }, "child": [{ "tag": "path", "attr": { "d": "M18.655 10.405a.75.75 0 0 1-1.06 0l-4.97-4.97v14.44a.75.75 0 0 1-1.5 0V5.435l-4.97 4.97a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734l6.25-6.25a.75.75 0 0 1 1.06 0l6.25 6.25a.75.75 0 0 1 0 1.06Z" }, "child": [] }] })(props);
277
+ }
278
+ function GoSearch(props) {
279
+ return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24" }, "child": [{ "tag": "path", "attr": { "d": "M10.25 2a8.25 8.25 0 0 1 6.34 13.53l5.69 5.69a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215l-5.69-5.69A8.25 8.25 0 1 1 10.25 2ZM3.5 10.25a6.75 6.75 0 1 0 13.5 0 6.75 6.75 0 0 0-13.5 0Z" }, "child": [] }] })(props);
280
+ }
281
+
282
+ // src/table/buttons.tsx
283
+ import { cn } from "dn-react-toolkit/utils";
284
+ import { Link, useLocation, useSearchParams } from "react-router";
285
+ import React4 from "react";
286
+ function TablePageButtons({
287
+ MAX_PAGES_TO_SHOW,
288
+ total,
289
+ limit,
290
+ offset
291
+ }) {
292
+ const pages = Math.ceil(total / limit);
293
+ const { pathname } = useLocation();
294
+ const [searchParams] = useSearchParams();
295
+ const currentPage = Math.floor(offset / limit) + 1;
296
+ const startButton = (Math.ceil(currentPage / MAX_PAGES_TO_SHOW) - 1) * MAX_PAGES_TO_SHOW;
297
+ const endButton = Math.min(startButton + MAX_PAGES_TO_SHOW - 1, pages);
298
+ return /* @__PURE__ */ React4.createElement(React4.Fragment, null, pages > 1 && /* @__PURE__ */ React4.createElement("div", { className: "flex justify-center items-center my-8 gap-4 text-neutral-400" }, startButton > 1 && /* @__PURE__ */ React4.createElement(
299
+ Link,
300
+ {
301
+ to: (() => {
302
+ searchParams.set(
303
+ "offset",
304
+ String((startButton - 1) * limit)
305
+ );
306
+ return `${pathname}?${searchParams.toString()}`;
307
+ })(),
308
+ className: "w-10 block text-center transition-colors hover:text-primary"
309
+ },
310
+ "\uC774\uC804"
311
+ ), Array.from({
312
+ length: Math.min(
313
+ MAX_PAGES_TO_SHOW,
314
+ pages - startButton
315
+ )
316
+ }).map((_, index) => {
317
+ return /* @__PURE__ */ React4.createElement(
318
+ Link,
319
+ {
320
+ key: index,
321
+ to: (() => {
322
+ searchParams.set(
323
+ "offset",
324
+ String((startButton + index) * limit)
325
+ );
326
+ return `${pathname}?${searchParams.toString()}`;
327
+ })(),
328
+ className: cn(
329
+ "w-6 block text-center transition-colors",
330
+ currentPage === startButton + index + 1 ? "font-bold text-primary" : "hover:text-primary"
331
+ )
332
+ },
333
+ startButton + index + 1
334
+ );
335
+ }), endButton < pages && /* @__PURE__ */ React4.createElement(
336
+ Link,
337
+ {
338
+ to: (() => {
339
+ searchParams.set(
340
+ "offset",
341
+ String((endButton + 1) * limit)
342
+ );
343
+ return `${pathname}?${searchParams.toString()}`;
344
+ })(),
345
+ className: "w-10 block text-center transition-colors hover:text-primary"
346
+ },
347
+ "\uB2E4\uC74C"
348
+ )));
349
+ }
350
+
351
+ // src/table/table.tsx
352
+ import { cn as cn2 } from "dn-react-toolkit/utils";
353
+ import { Link as Link2, useSearchParams as useSearchParams2 } from "react-router";
354
+ import React5 from "react";
355
+ function Table({
356
+ className = "min-w-full whitespace-nowrap",
357
+ data,
358
+ columns,
359
+ mapper: Mapper,
360
+ getLink,
361
+ limit,
362
+ offset,
363
+ orderBy,
364
+ direction
365
+ }) {
366
+ const keys = Object.entries(columns).filter((entry) => entry[1]).map(([key]) => key);
367
+ const sortedArray = [...data];
368
+ const [_, setSearchParams] = useSearchParams2();
369
+ return /* @__PURE__ */ React5.createElement(
370
+ "table",
371
+ {
372
+ className: cn2(
373
+ className,
374
+ "text-[15px] border-separate border-spacing-0"
375
+ )
376
+ },
377
+ /* @__PURE__ */ React5.createElement("thead", null, /* @__PURE__ */ React5.createElement("tr", null, keys.map((key) => {
378
+ const value = columns[key];
379
+ function getReactNode() {
380
+ if (value && typeof value === "object" && "label" in value) {
381
+ return value.label;
382
+ }
383
+ return value;
384
+ }
385
+ function Head() {
386
+ const reactNode = getReactNode();
387
+ if (typeof reactNode === "string") {
388
+ return /* @__PURE__ */ React5.createElement(
389
+ "button",
390
+ {
391
+ className: cn2(
392
+ orderBy === key ? "text-neutral-900 font-medium" : "text-neutral-500",
393
+ "px-4 h-14 flex items-center w-full"
394
+ ),
395
+ onClick: () => {
396
+ let newDirection = "asc";
397
+ if (orderBy === key) {
398
+ newDirection = direction === "asc" ? "desc" : "asc";
399
+ }
400
+ setSearchParams({
401
+ orderBy: key,
402
+ direction: newDirection
403
+ });
404
+ }
405
+ },
406
+ reactNode,
407
+ orderBy === key && /* @__PURE__ */ React5.createElement("div", { className: "ml-0.5" }, direction === "asc" ? /* @__PURE__ */ React5.createElement(GoArrowUp, null) : /* @__PURE__ */ React5.createElement(GoArrowDown, null))
408
+ );
409
+ }
410
+ return /* @__PURE__ */ React5.createElement(React5.Fragment, null, reactNode);
411
+ }
412
+ return /* @__PURE__ */ React5.createElement(
413
+ "th",
414
+ {
415
+ key,
416
+ className: cn2("border-y font-normal")
417
+ },
418
+ /* @__PURE__ */ React5.createElement(Head, null)
419
+ );
420
+ }))),
421
+ /* @__PURE__ */ React5.createElement("tbody", null, sortedArray.length === 0 && /* @__PURE__ */ React5.createElement("tr", null, /* @__PURE__ */ React5.createElement(
422
+ "td",
423
+ {
424
+ colSpan: keys.length,
425
+ className: "px-4 h-14 text-neutral-400 text-center"
426
+ },
427
+ "\uB370\uC774\uD130\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."
428
+ )), sortedArray.map((item, i) => /* @__PURE__ */ React5.createElement("tr", { key: i, className: "hover:bg-gray-50 transition-colors" }, keys.map((key, i2) => {
429
+ const value = item[key];
430
+ function Content() {
431
+ if (key in columns) {
432
+ const column = columns[key];
433
+ if (column && typeof column === "object" && "mapper" in column) {
434
+ const mapper = column.mapper;
435
+ if (mapper) {
436
+ return /* @__PURE__ */ React5.createElement(React5.Fragment, null, mapper(item));
437
+ }
438
+ }
439
+ }
440
+ return /* @__PURE__ */ React5.createElement(React5.Fragment, null, String(value));
441
+ }
442
+ const linkedContent = getLink ? /* @__PURE__ */ React5.createElement(
443
+ Link2,
444
+ {
445
+ to: getLink(item),
446
+ className: "block content-center px-4 w-full h-full"
447
+ },
448
+ /* @__PURE__ */ React5.createElement(Content, null)
449
+ ) : /* @__PURE__ */ React5.createElement(Content, null);
450
+ const cell = Mapper ? /* @__PURE__ */ React5.createElement(Mapper, { item, index: i2 }, linkedContent) : linkedContent;
451
+ return /* @__PURE__ */ React5.createElement("td", { key, className: "px-0 h-14 border-b" }, cell);
452
+ }))))
453
+ );
454
+ }
455
+
456
+ // src/table/page.tsx
457
+ import React6 from "react";
458
+ function createTablePage({
459
+ name,
460
+ columns,
461
+ primaryKey = "id"
462
+ }) {
463
+ return function TablePage({
464
+ AdminLayout
465
+ }) {
466
+ const { pathname } = useLocation2();
467
+ const { table } = useLoaderData();
468
+ const { items, total, limit, offset, orderBy, direction, searchKey } = table;
469
+ const navigate = useNavigate2();
470
+ const search = (query) => {
471
+ const searchParams2 = new URLSearchParams(window.location.search);
472
+ searchParams2.set("query", query);
473
+ searchParams2.set("offset", "0");
474
+ navigate(`${pathname}?${searchParams2.toString()}`);
475
+ };
476
+ const [searchParams] = useSearchParams3();
477
+ return /* @__PURE__ */ React6.createElement(
478
+ AdminLayout,
479
+ {
480
+ title: name,
481
+ actions: /* @__PURE__ */ React6.createElement(Link3, { to: `${pathname}/new`, className: "button-primary" }, name, " \uCD94\uAC00")
482
+ },
483
+ searchKey && /* @__PURE__ */ React6.createElement(
484
+ "form",
485
+ {
486
+ className: "h-18 px-4 flex items-center border-t",
487
+ onSubmit: (e) => {
488
+ e.preventDefault();
489
+ const formData = new FormData(e.currentTarget);
490
+ const query = formData.get("query");
491
+ search(query);
492
+ }
493
+ },
494
+ /* @__PURE__ */ React6.createElement(
495
+ "button",
496
+ {
497
+ type: "submit",
498
+ className: "w-10 h-10 flex justify-center items-center"
499
+ },
500
+ /* @__PURE__ */ React6.createElement(GoSearch, { className: "text-xl mr-4" })
501
+ ),
502
+ /* @__PURE__ */ React6.createElement(
503
+ "input",
504
+ {
505
+ className: "outline-none h-full flex-1",
506
+ placeholder: "\uC5EC\uAE30\uC5D0 \uAC80\uC0C9\uD558\uC138\uC694...",
507
+ name: "query",
508
+ defaultValue: searchParams.get("query") ?? ""
509
+ }
510
+ )
511
+ ),
512
+ /* @__PURE__ */ React6.createElement(
513
+ Table,
514
+ {
515
+ data: items,
516
+ columns,
517
+ getLink: primaryKey ? (item) => `${pathname}/${item[primaryKey]}` : void 0,
518
+ limit,
519
+ offset,
520
+ orderBy,
521
+ direction
522
+ }
523
+ ),
524
+ /* @__PURE__ */ React6.createElement(
525
+ TablePageButtons,
526
+ {
527
+ total,
528
+ limit,
529
+ offset,
530
+ MAX_PAGES_TO_SHOW: 10
531
+ }
532
+ )
533
+ );
534
+ };
535
+ }
536
+
537
+ // src/crud/crud_form.tsx
538
+ import { SyncInput } from "dn-react-toolkit/store";
539
+ import React7 from "react";
540
+ function CrudForm({ AdminLayout }) {
541
+ const form = useFormContext();
542
+ return /* @__PURE__ */ React7.createElement(
543
+ AdminLayout,
544
+ {
545
+ title: `${form.name} ${form.item ? "\uC218\uC815" : "\uCD94\uAC00"}`,
546
+ actions: /* @__PURE__ */ React7.createElement(
547
+ "button",
548
+ {
549
+ type: "button",
550
+ className: "button-primary",
551
+ onClick: form.submit
552
+ },
553
+ "\uC800\uC7A5\uD558\uAE30"
554
+ ),
555
+ className: "max-w-3xl mx-auto"
556
+ },
557
+ Object.keys(form.columns).length > 0 && /* @__PURE__ */ React7.createElement(React7.Fragment, null, Object.entries(form.columns).map(
558
+ ([key, value]) => /* @__PURE__ */ React7.createElement("label", { key }, value.label, value.component ? /* @__PURE__ */ React7.createElement(value.component, null) : /* @__PURE__ */ React7.createElement(
559
+ SyncInput,
560
+ {
561
+ store: form.store,
562
+ property: key,
563
+ className: "input-form"
564
+ }
565
+ ))
566
+ )),
567
+ form.item && /* @__PURE__ */ React7.createElement(
568
+ "button",
569
+ {
570
+ className: "button-dangerous mt-8",
571
+ onClick: () => {
572
+ form.delete();
573
+ }
574
+ },
575
+ "\uC0AD\uC81C\uD558\uAE30"
576
+ )
577
+ );
578
+ }
579
+
580
+ // src/crud/crud_page.tsx
581
+ import React8 from "react";
582
+ function crudPage({
583
+ name,
584
+ tablePageOptions,
585
+ formOptions,
586
+ AdminLayout
587
+ }) {
588
+ return (prefix) => {
589
+ return function Page() {
590
+ const data = useLoaderData2();
591
+ const { pathname } = useLocation3();
592
+ if (pathname === prefix) {
593
+ const Component = createTablePage({
594
+ ...tablePageOptions,
595
+ name
596
+ });
597
+ return /* @__PURE__ */ React8.createElement(Component, { AdminLayout });
598
+ }
599
+ if (pathname.startsWith(prefix)) {
600
+ return /* @__PURE__ */ React8.createElement(
601
+ CrudFormProvider,
602
+ {
603
+ item: data?.item,
604
+ prefix,
605
+ name,
606
+ columns: formOptions.columns
607
+ },
608
+ formOptions.form ? /* @__PURE__ */ React8.createElement(formOptions.form, null) : /* @__PURE__ */ React8.createElement(CrudForm, { AdminLayout })
609
+ );
610
+ }
611
+ };
612
+ };
613
+ }
614
+ export {
615
+ crudPage
616
+ };
@@ -0,0 +1,15 @@
1
+ import { LoaderFunctionArgs } from 'react-router';
2
+ import { CrudHandler } from './crud_loader.mjs';
3
+ import '../table/loader.mjs';
4
+ import '../table/repository.mjs';
5
+ import 'drizzle-orm';
6
+ import 'drizzle-orm/pg-core';
7
+ import '../table/item_loader.mjs';
8
+ import '../api/create_api_handler.mjs';
9
+ import '../auth/with_auth.mjs';
10
+ import 'dn-react-toolkit/auth';
11
+ import 'dn-react-toolkit/auth/server';
12
+
13
+ declare const generateHandlers: (handlers: Record<string, CrudHandler>) => (args: LoaderFunctionArgs) => Promise<any>;
14
+
15
+ export { generateHandlers };
@@ -0,0 +1,15 @@
1
+ import { LoaderFunctionArgs } from 'react-router';
2
+ import { CrudHandler } from './crud_loader.js';
3
+ import '../table/loader.js';
4
+ import '../table/repository.js';
5
+ import 'drizzle-orm';
6
+ import 'drizzle-orm/pg-core';
7
+ import '../table/item_loader.js';
8
+ import '../api/create_api_handler.js';
9
+ import '../auth/with_auth.js';
10
+ import 'dn-react-toolkit/auth';
11
+ import 'dn-react-toolkit/auth/server';
12
+
13
+ declare const generateHandlers: (handlers: Record<string, CrudHandler>) => (args: LoaderFunctionArgs) => Promise<any>;
14
+
15
+ export { generateHandlers };
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/crud/generate_handlers.ts
21
+ var generate_handlers_exports = {};
22
+ __export(generate_handlers_exports, {
23
+ generateHandlers: () => generateHandlers
24
+ });
25
+ module.exports = __toCommonJS(generate_handlers_exports);
26
+ var generateHandlers = (handlers) => {
27
+ return async (args) => {
28
+ const pattern = args.unstable_pattern;
29
+ for (const route of Object.keys(handlers)) {
30
+ if (pattern.startsWith(route) || pattern.startsWith(`/api${route}`)) {
31
+ return handlers[route](route)(args);
32
+ }
33
+ }
34
+ };
35
+ };
36
+ // Annotate the CommonJS export names for ESM import in node:
37
+ 0 && (module.exports = {
38
+ generateHandlers
39
+ });
@@ -0,0 +1,14 @@
1
+ // src/crud/generate_handlers.ts
2
+ var generateHandlers = (handlers) => {
3
+ return async (args) => {
4
+ const pattern = args.unstable_pattern;
5
+ for (const route of Object.keys(handlers)) {
6
+ if (pattern.startsWith(route) || pattern.startsWith(`/api${route}`)) {
7
+ return handlers[route](route)(args);
8
+ }
9
+ }
10
+ };
11
+ };
12
+ export {
13
+ generateHandlers
14
+ };