dn-react-router-toolkit 0.8.1 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/dist/api/create_api_handler.d.mts +2 -2
  2. package/dist/api/create_api_handler.d.ts +2 -2
  3. package/dist/api/create_api_handler.js +55 -52
  4. package/dist/api/create_api_handler.mjs +61 -59
  5. package/dist/api/create_handler.d.mts +5 -5
  6. package/dist/api/create_handler.d.ts +5 -5
  7. package/dist/api/create_handler.js +41 -44
  8. package/dist/api/create_handler.mjs +41 -44
  9. package/dist/api/index.d.mts +4 -3
  10. package/dist/api/index.d.ts +4 -3
  11. package/dist/api/index.js +118 -102
  12. package/dist/api/index.mjs +130 -109
  13. package/dist/api/item_api_handler.d.mts +4 -3
  14. package/dist/api/item_api_handler.d.ts +4 -3
  15. package/dist/api/item_api_handler.js +22 -6
  16. package/dist/api/item_api_handler.mjs +28 -6
  17. package/dist/auth/cookie_manager.d.mts +1 -1
  18. package/dist/auth/cookie_manager.d.ts +1 -1
  19. package/dist/auth/index.d.mts +2 -2
  20. package/dist/auth/index.d.ts +2 -2
  21. package/dist/auth/index.js +18 -18
  22. package/dist/auth/index.mjs +18 -18
  23. package/dist/auth/with_auth.d.mts +2 -2
  24. package/dist/auth/with_auth.d.ts +2 -2
  25. package/dist/auth/with_auth.js +18 -18
  26. package/dist/auth/with_auth.mjs +18 -18
  27. package/dist/client/editor.d.mts +2 -2
  28. package/dist/client/editor.d.ts +2 -2
  29. package/dist/client/editor.js +9 -3
  30. package/dist/client/editor.mjs +9 -3
  31. package/dist/client/index.d.mts +2 -2
  32. package/dist/client/index.d.ts +2 -2
  33. package/dist/client/index.js +9 -3
  34. package/dist/client/index.mjs +9 -3
  35. package/dist/crud/crud_form.js +22 -4
  36. package/dist/crud/crud_form.mjs +11 -3
  37. package/dist/crud/crud_form_provider.js +16 -3
  38. package/dist/crud/crud_form_provider.mjs +14 -1
  39. package/dist/crud/index.d.mts +0 -20
  40. package/dist/crud/index.d.ts +0 -20
  41. package/dist/crud/index.js +32 -8589
  42. package/dist/crud/index.mjs +11 -8599
  43. package/dist/db/backup/index.d.mts +1 -1
  44. package/dist/db/backup/index.d.ts +1 -1
  45. package/dist/form/create_form_component.js +21 -2
  46. package/dist/form/create_form_component.mjs +10 -1
  47. package/dist/form/form_components.js +21 -2
  48. package/dist/form/form_components.mjs +10 -1
  49. package/dist/form/index.js +21 -2
  50. package/dist/form/index.mjs +10 -1
  51. package/dist/post/editor_toolbar.js +20 -3
  52. package/dist/post/editor_toolbar.mjs +9 -2
  53. package/dist/post/index.js +93 -7711
  54. package/dist/post/index.mjs +69 -7723
  55. package/dist/post/post_form_page.js +91 -7711
  56. package/dist/post/post_form_page.mjs +69 -7725
  57. package/dist/post/thumbnail_picker.js +21 -2
  58. package/dist/post/thumbnail_picker.mjs +10 -1
  59. package/dist/table/buttons.js +11 -14
  60. package/dist/table/buttons.mjs +10 -13
  61. package/dist/table/index.d.mts +0 -2
  62. package/dist/table/index.d.ts +0 -2
  63. package/dist/table/index.js +24 -95
  64. package/dist/table/index.mjs +23 -92
  65. package/dist/table/load_table.d.mts +1 -1
  66. package/dist/table/load_table.d.ts +1 -1
  67. package/dist/table/load_table.js +2 -2
  68. package/dist/table/load_table.mjs +2 -2
  69. package/dist/table/loader.js +2 -2
  70. package/dist/table/loader.mjs +2 -2
  71. package/dist/table/table.d.mts +2 -2
  72. package/dist/table/table.d.ts +2 -2
  73. package/dist/table/table.js +14 -25
  74. package/dist/table/table.mjs +11 -24
  75. package/dist/table/table_form.js +16 -39
  76. package/dist/table/table_form.mjs +15 -38
  77. package/dist/utils/cn.d.mts +3 -0
  78. package/dist/utils/cn.d.ts +3 -0
  79. package/dist/utils/cn.js +32 -0
  80. package/dist/utils/cn.mjs +7 -0
  81. package/dist/utils/date.d.mts +5 -0
  82. package/dist/utils/date.d.ts +5 -0
  83. package/dist/utils/date.js +65 -0
  84. package/dist/utils/date.mjs +29 -0
  85. package/dist/utils/index.d.mts +7 -0
  86. package/dist/utils/index.d.ts +7 -0
  87. package/dist/utils/index.js +116 -0
  88. package/dist/utils/index.mjs +73 -0
  89. package/dist/utils/korean.d.mts +6 -0
  90. package/dist/utils/korean.d.ts +6 -0
  91. package/dist/{crud/generate_pages.js → utils/korean.js} +16 -30
  92. package/dist/utils/korean.mjs +16 -0
  93. package/dist/utils/singleton.d.mts +3 -0
  94. package/dist/utils/singleton.d.ts +3 -0
  95. package/dist/utils/singleton.js +37 -0
  96. package/dist/utils/singleton.mjs +12 -0
  97. package/dist/utils/sleep.d.mts +3 -0
  98. package/dist/utils/sleep.d.ts +3 -0
  99. package/dist/{table/item_loader.js → utils/sleep.js} +8 -19
  100. package/dist/utils/sleep.mjs +7 -0
  101. package/dist/utils/slug.d.mts +3 -0
  102. package/dist/utils/slug.d.ts +3 -0
  103. package/dist/{crud/generate_handlers.js → utils/slug.js} +8 -15
  104. package/dist/utils/slug.mjs +7 -0
  105. package/package.json +7 -3
  106. package/dist/crud/crud_loader.d.mts +0 -26
  107. package/dist/crud/crud_loader.d.ts +0 -26
  108. package/dist/crud/crud_loader.js +0 -351
  109. package/dist/crud/crud_loader.mjs +0 -337
  110. package/dist/crud/crud_page.d.mts +0 -32
  111. package/dist/crud/crud_page.d.ts +0 -32
  112. package/dist/crud/crud_page.js +0 -776
  113. package/dist/crud/crud_page.mjs +0 -758
  114. package/dist/crud/generate_handlers.d.mts +0 -16
  115. package/dist/crud/generate_handlers.d.ts +0 -16
  116. package/dist/crud/generate_handlers.mjs +0 -14
  117. package/dist/crud/generate_pages.d.mts +0 -19
  118. package/dist/crud/generate_pages.d.ts +0 -19
  119. package/dist/crud/generate_pages.mjs +0 -30
  120. package/dist/crud/generate_routes.d.mts +0 -5
  121. package/dist/crud/generate_routes.d.ts +0 -5
  122. package/dist/crud/generate_routes.js +0 -7639
  123. package/dist/crud/generate_routes.mjs +0 -7627
  124. package/dist/table/item_loader.d.mts +0 -14
  125. package/dist/table/item_loader.d.ts +0 -14
  126. package/dist/table/item_loader.mjs +0 -18
  127. package/dist/table/page.d.mts +0 -16
  128. package/dist/table/page.d.ts +0 -16
  129. package/dist/table/page.js +0 -375
  130. package/dist/table/page.mjs +0 -350
@@ -1,758 +0,0 @@
1
- // src/crud/crud_page.tsx
2
- import { useLoaderData as useLoaderData2, useLocation as useLocation4 } from "react-router";
3
-
4
- // src/crud/crud_form_provider.tsx
5
- import { useNavigate } from "react-router";
6
- import { useStore } from "react-store-input";
7
- import {
8
- createContext,
9
- useContext
10
- } from "react";
11
-
12
- // src/crud/serialize.ts
13
- function serialize(value) {
14
- if (value === void 0) {
15
- return void 0;
16
- }
17
- if (value === null) {
18
- return {
19
- type: "null",
20
- value: null
21
- };
22
- }
23
- if (typeof value === "string") {
24
- return {
25
- type: "string",
26
- value
27
- };
28
- }
29
- if (typeof value === "number") {
30
- return {
31
- type: "number",
32
- value
33
- };
34
- }
35
- if (typeof value === "boolean") {
36
- return {
37
- type: "boolean",
38
- value
39
- };
40
- }
41
- if (value instanceof Date) {
42
- return {
43
- type: "date",
44
- value: value.toISOString()
45
- };
46
- }
47
- if (Array.isArray(value)) {
48
- return {
49
- type: "array",
50
- value: value.map((item) => serialize(item))
51
- };
52
- }
53
- if (typeof value === "object") {
54
- return {
55
- type: "object",
56
- value: Object.entries(value).reduce(
57
- (acc, [key, value2]) => {
58
- return {
59
- ...acc,
60
- [key]: serialize(value2)
61
- };
62
- },
63
- {}
64
- )
65
- };
66
- }
67
- return void 0;
68
- }
69
-
70
- // src/crud/crud_form_provider.tsx
71
- import { Korean } from "dn-react-toolkit/utils";
72
- import { jsx } from "react/jsx-runtime";
73
- var FormContext = createContext({});
74
- function useFormContext() {
75
- return useContext(FormContext);
76
- }
77
- function CrudFormProvider({
78
- primaryKey,
79
- name,
80
- prefix,
81
- item,
82
- columns = {},
83
- children
84
- }) {
85
- const apiPrefix = `/api${prefix}`;
86
- const createInitialState = () => {
87
- return Object.keys(item || columns).reduce((acc, key) => {
88
- const value2 = item ? item[key] : void 0;
89
- if (columns[key]?.defaultValue !== void 0) {
90
- if (typeof value2 === "number") {
91
- return {
92
- ...acc,
93
- [key]: value2 ?? columns[key]?.defaultValue
94
- };
95
- }
96
- return {
97
- ...acc,
98
- [key]: value2 || columns[key]?.defaultValue
99
- };
100
- }
101
- return {
102
- ...acc,
103
- [key]: value2
104
- };
105
- }, {});
106
- };
107
- const store = useStore(createInitialState());
108
- const navigate = useNavigate();
109
- const submit = async () => {
110
- const res = await fetch(apiPrefix, {
111
- method: "POST",
112
- headers: {
113
- "Content-Type": "application/json"
114
- },
115
- body: JSON.stringify(serialize(store.state))
116
- });
117
- if (!res.ok) {
118
- const { message } = await res.json();
119
- alert(message);
120
- return;
121
- }
122
- alert(`${Korean.with(name, ["\uC744", "\uB97C"])} \uC800\uC7A5\uD588\uC2B5\uB2C8\uB2E4.`);
123
- const { id } = await res.json();
124
- navigate(`${prefix}/${id}`);
125
- };
126
- const deleteItem = async () => {
127
- if (!item || !primaryKey) {
128
- return;
129
- }
130
- const ok = confirm("\uC815\uB9D0\uB85C \uC0AD\uC81C\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?");
131
- if (!ok) {
132
- return;
133
- }
134
- const res = await fetch(`${apiPrefix}/${item[primaryKey]}`, {
135
- method: "DELETE"
136
- });
137
- if (!res.ok) {
138
- const { message } = await res.json();
139
- alert(message);
140
- return;
141
- }
142
- alert(`${Korean.with(name, ["\uC744", "\uB97C"])} \uC0AD\uC81C\uD588\uC2B5\uB2C8\uB2E4.`);
143
- navigate(`${prefix}`);
144
- };
145
- const value = {
146
- name,
147
- item,
148
- store,
149
- submit,
150
- delete: deleteItem,
151
- columns
152
- };
153
- return /* @__PURE__ */ jsx(FormContext.Provider, { value, children });
154
- }
155
-
156
- // src/table/page.tsx
157
- import { Link as Link3, useLocation as useLocation3 } from "react-router";
158
-
159
- // src/table/table_form.tsx
160
- import { useLocation as useLocation2, useNavigate as useNavigate2, useSearchParams as useSearchParams3 } from "react-router";
161
- import { GoSearch } from "react-icons/go";
162
-
163
- // src/table/table.tsx
164
- import { cn } from "dn-react-toolkit/utils";
165
- import { GoArrowDown, GoArrowUp } from "react-icons/go";
166
- import { Link, useSearchParams } from "react-router";
167
- import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
168
- function Table({
169
- className = "min-w-full whitespace-nowrap",
170
- data,
171
- columns,
172
- mapper: Mapper,
173
- getLink,
174
- limit,
175
- offset,
176
- orderBy,
177
- direction,
178
- filters
179
- }) {
180
- const keys = Object.entries(columns).filter((entry) => entry[1]).map(([key]) => key);
181
- const sortedArray = [...data];
182
- const [_, setSearchParams] = useSearchParams();
183
- return /* @__PURE__ */ jsxs(
184
- "table",
185
- {
186
- className: cn(
187
- className,
188
- "text-[15px] border-separate border-spacing-0"
189
- ),
190
- children: [
191
- /* @__PURE__ */ jsx2("thead", { children: /* @__PURE__ */ jsx2("tr", { children: keys.map((key) => {
192
- const value = columns[key];
193
- function getReactNode() {
194
- if (value && typeof value === "object" && "label" in value) {
195
- return value.label;
196
- }
197
- return value;
198
- }
199
- function Head() {
200
- const reactNode = getReactNode();
201
- if (typeof reactNode === "string") {
202
- return /* @__PURE__ */ jsxs(
203
- "button",
204
- {
205
- className: cn(
206
- orderBy === key ? "text-gray-900 font-medium" : "text-gray-500 font-medium",
207
- "px-4 flex items-center w-full"
208
- ),
209
- onClick: () => {
210
- let newDirection = "asc";
211
- if (orderBy === key) {
212
- newDirection = direction === "asc" ? "desc" : "asc";
213
- }
214
- setSearchParams({
215
- orderBy: key,
216
- direction: newDirection
217
- });
218
- },
219
- children: [
220
- reactNode,
221
- orderBy === key && /* @__PURE__ */ jsx2("div", { className: "ml-0.5", children: direction === "asc" ? /* @__PURE__ */ jsx2(GoArrowUp, {}) : /* @__PURE__ */ jsx2(GoArrowDown, {}) })
222
- ]
223
- }
224
- );
225
- }
226
- return /* @__PURE__ */ jsx2(Fragment, { children: reactNode });
227
- }
228
- const filter = filters[key];
229
- return /* @__PURE__ */ jsxs(
230
- "th",
231
- {
232
- className: cn(
233
- "py-4 border-y font-normal align-top"
234
- ),
235
- children: [
236
- /* @__PURE__ */ jsx2(Head, {}),
237
- filter && /* @__PURE__ */ jsx2("div", { className: "px-3 mt-4", children: /* @__PURE__ */ jsxs(
238
- "select",
239
- {
240
- className: "w-full h-10 px-1.5 border rounded-full outline-none",
241
- onChange: (e) => {
242
- const value2 = e.target.value;
243
- setSearchParams((prev) => {
244
- if (value2) {
245
- prev.set(
246
- key,
247
- encodeURIComponent(
248
- value2
249
- )
250
- );
251
- } else {
252
- prev.delete(key);
253
- }
254
- return prev;
255
- });
256
- },
257
- children: [
258
- /* @__PURE__ */ jsx2("option", { value: "", children: "\uC804\uCCB4" }),
259
- filter.map((option) => /* @__PURE__ */ jsx2(
260
- "option",
261
- {
262
- value: option,
263
- children: option
264
- },
265
- option
266
- ))
267
- ]
268
- }
269
- ) })
270
- ]
271
- },
272
- key
273
- );
274
- }) }) }),
275
- /* @__PURE__ */ jsxs("tbody", { children: [
276
- sortedArray.length === 0 && /* @__PURE__ */ jsx2("tr", { children: /* @__PURE__ */ jsx2(
277
- "td",
278
- {
279
- colSpan: keys.length,
280
- className: "px-4 h-20 text-gray-400 text-center",
281
- children: "\uB370\uC774\uD130\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."
282
- }
283
- ) }),
284
- sortedArray.map((item, i) => /* @__PURE__ */ jsx2("tr", { className: "hover:bg-gray-50 transition-colors", children: keys.map((key, i2) => {
285
- const value = item[key];
286
- function Content() {
287
- if (key in columns) {
288
- const column = columns[key];
289
- if (column && typeof column === "object" && "mapper" in column) {
290
- const mapper = column.mapper;
291
- if (mapper) {
292
- return /* @__PURE__ */ jsx2(Fragment, { children: mapper(item) });
293
- }
294
- }
295
- }
296
- return /* @__PURE__ */ jsx2(Fragment, { children: String(value) });
297
- }
298
- const linkedContent = getLink ? /* @__PURE__ */ jsx2(
299
- Link,
300
- {
301
- to: getLink(item),
302
- className: "block content-center px-4 w-full h-full",
303
- children: /* @__PURE__ */ jsx2(Content, {})
304
- }
305
- ) : /* @__PURE__ */ jsx2(Content, {});
306
- const cell = Mapper ? /* @__PURE__ */ jsx2(Mapper, { item, index: i2, children: linkedContent }) : linkedContent;
307
- return /* @__PURE__ */ jsx2("td", { className: "px-0 h-14 border-b", children: cell }, key);
308
- }) }, i))
309
- ] })
310
- ]
311
- }
312
- );
313
- }
314
-
315
- // src/table/use_table.tsx
316
- import { useLoaderData } from "react-router";
317
- function useTable() {
318
- const { table } = useLoaderData();
319
- return table;
320
- }
321
-
322
- // src/table/buttons.tsx
323
- import { cn as cn2 } from "dn-react-toolkit/utils";
324
- import { Link as Link2, useLocation, useSearchParams as useSearchParams2 } from "react-router";
325
- import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
326
- function TablePageButtons({
327
- MAX_PAGES_TO_SHOW,
328
- total,
329
- limit,
330
- offset
331
- }) {
332
- const pages = Math.ceil(total / limit);
333
- const { pathname } = useLocation();
334
- const [searchParams] = useSearchParams2();
335
- const currentPage = Math.floor(offset / limit) + 1;
336
- const startButton = (Math.ceil(currentPage / MAX_PAGES_TO_SHOW) - 1) * MAX_PAGES_TO_SHOW;
337
- const endButton = Math.min(startButton + MAX_PAGES_TO_SHOW - 1, pages);
338
- return /* @__PURE__ */ jsx3(Fragment2, { children: pages > 1 && /* @__PURE__ */ jsxs2("div", { className: "flex justify-center items-center my-8 gap-4 text-neutral-400", children: [
339
- startButton > 1 && /* @__PURE__ */ jsx3(
340
- Link2,
341
- {
342
- to: (() => {
343
- searchParams.set(
344
- "offset",
345
- String((startButton - 1) * limit)
346
- );
347
- return `${pathname}?${searchParams.toString()}`;
348
- })(),
349
- className: "w-10 block text-center transition-colors hover:text-primary",
350
- children: "\uC774\uC804"
351
- }
352
- ),
353
- Array.from({
354
- length: Math.min(
355
- MAX_PAGES_TO_SHOW,
356
- pages - startButton
357
- )
358
- }).map((_, index) => {
359
- return /* @__PURE__ */ jsx3(
360
- Link2,
361
- {
362
- to: (() => {
363
- searchParams.set(
364
- "offset",
365
- String((startButton + index) * limit)
366
- );
367
- return `${pathname}?${searchParams.toString()}`;
368
- })(),
369
- className: cn2(
370
- "w-6 block text-center transition-colors",
371
- currentPage === startButton + index + 1 ? "font-bold text-primary" : "hover:text-primary"
372
- ),
373
- children: startButton + index + 1
374
- },
375
- index
376
- );
377
- }),
378
- endButton < pages && /* @__PURE__ */ jsx3(
379
- Link2,
380
- {
381
- to: (() => {
382
- searchParams.set(
383
- "offset",
384
- String((endButton + 1) * limit)
385
- );
386
- return `${pathname}?${searchParams.toString()}`;
387
- })(),
388
- className: "w-10 block text-center transition-colors hover:text-primary",
389
- children: "\uB2E4\uC74C"
390
- }
391
- )
392
- ] }) });
393
- }
394
-
395
- // src/table/table_form.tsx
396
- import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
397
- function TableForm({
398
- columns,
399
- primaryKey = "id"
400
- }) {
401
- const { pathname } = useLocation2();
402
- const {
403
- items,
404
- total,
405
- limit,
406
- offset,
407
- orderBy,
408
- direction,
409
- searchKey,
410
- filters
411
- } = useTable();
412
- const navigate = useNavigate2();
413
- const search = (query) => {
414
- const searchParams2 = new URLSearchParams(window.location.search);
415
- searchParams2.set("query", query);
416
- searchParams2.set("offset", "0");
417
- navigate(`${pathname}?${searchParams2.toString()}`);
418
- };
419
- const [searchParams] = useSearchParams3();
420
- return /* @__PURE__ */ jsxs3(Fragment3, { children: [
421
- searchKey && /* @__PURE__ */ jsxs3(
422
- "form",
423
- {
424
- className: "h-20 px-4 flex items-center border-t",
425
- onSubmit: (e) => {
426
- e.preventDefault();
427
- const formData = new FormData(e.currentTarget);
428
- const query = formData.get("query");
429
- search(query);
430
- },
431
- children: [
432
- /* @__PURE__ */ jsx4(
433
- "button",
434
- {
435
- type: "submit",
436
- className: "w-10 h-10 flex justify-center items-center",
437
- children: /* @__PURE__ */ jsx4(GoSearch, { className: "text-xl mr-4" })
438
- }
439
- ),
440
- /* @__PURE__ */ jsx4(
441
- "input",
442
- {
443
- className: "outline-none h-full flex-1",
444
- placeholder: "\uC5EC\uAE30\uC5D0 \uAC80\uC0C9\uD558\uC138\uC694...",
445
- name: "query",
446
- defaultValue: searchParams.get("query") ?? ""
447
- }
448
- )
449
- ]
450
- }
451
- ),
452
- /* @__PURE__ */ jsx4(
453
- Table,
454
- {
455
- data: items,
456
- columns,
457
- getLink: primaryKey ? (item) => `${pathname}/${item[primaryKey]}` : void 0,
458
- limit,
459
- offset,
460
- orderBy,
461
- direction,
462
- filters
463
- }
464
- ),
465
- /* @__PURE__ */ jsx4(
466
- TablePageButtons,
467
- {
468
- total,
469
- limit,
470
- offset,
471
- MAX_PAGES_TO_SHOW: 10
472
- }
473
- )
474
- ] });
475
- }
476
-
477
- // src/table/page.tsx
478
- import { Fragment as Fragment4, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
479
- function createTablePage({
480
- name,
481
- columns,
482
- primaryKey = "id"
483
- }) {
484
- return function TablePage({
485
- header: Header
486
- }) {
487
- const { pathname } = useLocation3();
488
- return /* @__PURE__ */ jsxs4(Fragment4, { children: [
489
- /* @__PURE__ */ jsx5(
490
- Header,
491
- {
492
- title: name,
493
- actions: /* @__PURE__ */ jsxs4(Link3, { to: `${pathname}/new`, className: "button-primary", children: [
494
- name,
495
- " \uCD94\uAC00"
496
- ] })
497
- }
498
- ),
499
- /* @__PURE__ */ jsx5("div", { className: "max-w-7xl mx-auto w-full overflow-auto", children: /* @__PURE__ */ jsx5(TableForm, { columns, primaryKey }) })
500
- ] });
501
- };
502
- }
503
-
504
- // src/form/create_form_component.tsx
505
- import { cn as cn3 } from "dn-react-toolkit/utils";
506
- import "react";
507
- import { jsx as jsx6 } from "react/jsx-runtime";
508
- function createComponent(tag, options) {
509
- return function FormComponent({ className, ...props }) {
510
- const Tag = tag;
511
- return /* @__PURE__ */ jsx6(Tag, { ...props, className: cn3(options.className, className) });
512
- };
513
- }
514
-
515
- // src/form/form_components.tsx
516
- var FormEntry = createComponent("div", {
517
- className: "flex-1"
518
- });
519
- var FormRow = createComponent("div", {
520
- className: "flex-1 flex gap-4 mb-6"
521
- });
522
- var FormLabel = createComponent("label", {
523
- className: "flex-1 font-semibold mb-2.5 block"
524
- });
525
-
526
- // src/crud/crud_form.tsx
527
- import { useStoreComponent } from "react-store-input";
528
-
529
- // src/client/env_loader.tsx
530
- import { useRouteLoaderData } from "react-router";
531
- import { jsx as jsx7 } from "react/jsx-runtime";
532
-
533
- // src/client/file_input.tsx
534
- import {
535
- useRef
536
- } from "react";
537
- import { Fragment as Fragment5, jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
538
-
539
- // src/client/use_user_agent.tsx
540
- import { useRouteLoaderData as useRouteLoaderData2 } from "react-router";
541
-
542
- // src/client/store_text_editor.tsx
543
- import {
544
- TextEditor
545
- } from "dn-react-text-editor";
546
- import { useStoreController } from "react-store-input";
547
- import { useImperativeHandle, useRef as useRef2 } from "react";
548
- import { jsx as jsx9 } from "react/jsx-runtime";
549
- function StoreTextEditor({
550
- store,
551
- name,
552
- getter,
553
- setter,
554
- defaultValue,
555
- ref,
556
- ...props
557
- }) {
558
- const controllerRef = useRef2(null);
559
- useImperativeHandle(
560
- ref,
561
- () => controllerRef.current,
562
- []
563
- );
564
- const { dispatch } = useStoreController(store, {
565
- onSubscribe: (state) => {
566
- const controller = controllerRef.current;
567
- if (!controller) {
568
- return;
569
- }
570
- const getResult = () => {
571
- if (getter) {
572
- return getter(state) || "";
573
- }
574
- if (name) {
575
- return state[name] || "";
576
- }
577
- return "";
578
- };
579
- const result = getResult();
580
- if (controller.value !== result) {
581
- controller.value = result;
582
- }
583
- },
584
- onDispatch: (state) => {
585
- const controller = controllerRef.current;
586
- if (!controller) {
587
- return;
588
- }
589
- if (setter) {
590
- setter(state, controller.value);
591
- return;
592
- }
593
- if (name) {
594
- state[name] = controller.value;
595
- }
596
- }
597
- });
598
- const getDefaultValue = () => {
599
- if (getter) {
600
- return getter(store.state);
601
- }
602
- if (name) {
603
- return store.state[name];
604
- }
605
- return void 0;
606
- };
607
- return /* @__PURE__ */ jsx9(
608
- TextEditor,
609
- {
610
- ...props,
611
- ref: controllerRef,
612
- defaultValue: defaultValue ?? getDefaultValue(),
613
- onChange: (e) => {
614
- dispatch();
615
- props.onChange?.(e);
616
- }
617
- }
618
- );
619
- }
620
-
621
- // src/client/editor.tsx
622
- import { generateMetadata } from "dn-react-toolkit/file/client";
623
-
624
- // src/crud/crud_form.tsx
625
- import { Fragment as Fragment6, jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
626
- function CrudForm({
627
- AdminHeader
628
- }) {
629
- const form = useFormContext();
630
- const component = useStoreComponent(form.store);
631
- return /* @__PURE__ */ jsxs6(Fragment6, { children: [
632
- /* @__PURE__ */ jsx10(
633
- AdminHeader,
634
- {
635
- title: `${form.name} ${form.item ? "\uC218\uC815" : "\uCD94\uAC00"}`,
636
- actions: /* @__PURE__ */ jsxs6(Fragment6, { children: [
637
- form.item && /* @__PURE__ */ jsx10(
638
- "button",
639
- {
640
- type: "button",
641
- className: "button-outline",
642
- onClick: () => {
643
- form.delete();
644
- },
645
- children: "\uC0AD\uC81C\uD558\uAE30"
646
- }
647
- ),
648
- /* @__PURE__ */ jsx10(
649
- "button",
650
- {
651
- type: "button",
652
- className: "button-primary",
653
- onClick: form.submit,
654
- children: "\uC800\uC7A5\uD558\uAE30"
655
- }
656
- )
657
- ] })
658
- }
659
- ),
660
- /* @__PURE__ */ jsx10("div", { className: "max-w-2xl mx-auto", children: Object.keys(form.columns).length > 0 && /* @__PURE__ */ jsx10(Fragment6, { children: Object.entries(form.columns).map(
661
- ([name, value]) => {
662
- function InputComponent() {
663
- if (value.component) {
664
- const Component = value.component;
665
- return /* @__PURE__ */ jsx10(Component, { store: form.store, name });
666
- }
667
- if (value.type === "textarea") {
668
- return /* @__PURE__ */ jsx10(
669
- StoreTextEditor,
670
- {
671
- store: form.store,
672
- name,
673
- editor: {
674
- attributes: {
675
- class: "text-editor-form"
676
- }
677
- }
678
- }
679
- );
680
- }
681
- if (value.options) {
682
- const Component = value.options;
683
- return /* @__PURE__ */ jsx10(component.select, { name, className: "select-form", children: /* @__PURE__ */ jsx10(Component, {}) });
684
- }
685
- return /* @__PURE__ */ jsx10(
686
- component.input,
687
- {
688
- name,
689
- type: value.type,
690
- className: "input-form"
691
- }
692
- );
693
- }
694
- const v = form.store.state[name];
695
- if (typeof v === "boolean") {
696
- return /* @__PURE__ */ jsxs6("div", { className: "flex", children: [
697
- value.label,
698
- /* @__PURE__ */ jsx10("div", { className: "ml-auto", children: /* @__PURE__ */ jsx10(InputComponent, {}) })
699
- ] });
700
- }
701
- return /* @__PURE__ */ jsx10(FormRow, { children: /* @__PURE__ */ jsxs6(FormEntry, { children: [
702
- /* @__PURE__ */ jsx10(FormLabel, { children: value.label }, name),
703
- /* @__PURE__ */ jsx10(InputComponent, {})
704
- ] }) }, name);
705
- }
706
- ) }) })
707
- ] });
708
- }
709
-
710
- // src/crud/crud_page.tsx
711
- import { jsx as jsx11 } from "react/jsx-runtime";
712
- function crudPage({
713
- name,
714
- primaryKey,
715
- tablePageOptions,
716
- formOptions,
717
- header
718
- }) {
719
- const create = (prefix) => {
720
- return function Page() {
721
- const data = useLoaderData2();
722
- const { pathname } = useLocation4();
723
- if (pathname === prefix) {
724
- const Component = createTablePage({
725
- ...tablePageOptions,
726
- name
727
- });
728
- return /* @__PURE__ */ jsx11(Component, { header });
729
- }
730
- if (pathname.startsWith(prefix)) {
731
- return /* @__PURE__ */ jsx11(
732
- CrudFormProvider,
733
- {
734
- item: data?.item,
735
- prefix,
736
- name,
737
- columns: formOptions.columns,
738
- primaryKey,
739
- children: formOptions.form ? /* @__PURE__ */ jsx11(FormDelegate, { component: formOptions.form }) : /* @__PURE__ */ jsx11(CrudForm, { AdminHeader: header })
740
- }
741
- );
742
- }
743
- };
744
- };
745
- return {
746
- name,
747
- create
748
- };
749
- }
750
- function FormDelegate({
751
- component: Component
752
- }) {
753
- const form = useFormContext();
754
- return /* @__PURE__ */ jsx11(Component, { form });
755
- }
756
- export {
757
- crudPage
758
- };