dn-react-router-toolkit 0.4.4 → 0.5.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 (95) 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.js +27 -25
  6. package/dist/api/create_handler.mjs +27 -25
  7. package/dist/api/index.js +27 -25
  8. package/dist/api/index.mjs +27 -25
  9. package/dist/api/item_api_handler.d.mts +18 -0
  10. package/dist/api/item_api_handler.d.ts +18 -0
  11. package/dist/api/item_api_handler.js +55 -0
  12. package/dist/api/item_api_handler.mjs +30 -0
  13. package/dist/auth/index.d.mts +1 -2
  14. package/dist/auth/index.d.ts +1 -2
  15. package/dist/auth/index.js +13 -21
  16. package/dist/auth/index.mjs +12 -20
  17. package/dist/auth/with_auth.d.mts +3 -3
  18. package/dist/auth/with_auth.d.ts +3 -3
  19. package/dist/auth/with_auth.js +13 -21
  20. package/dist/auth/with_auth.mjs +12 -20
  21. package/dist/crud/crud_form.d.mts +13 -0
  22. package/dist/crud/crud_form.d.ts +13 -0
  23. package/dist/crud/crud_form.js +88 -0
  24. package/dist/crud/crud_form.mjs +55 -0
  25. package/dist/crud/crud_form_provider.d.mts +34 -0
  26. package/dist/crud/crud_form_provider.d.ts +34 -0
  27. package/dist/crud/crud_form_provider.js +160 -0
  28. package/dist/crud/crud_form_provider.mjs +124 -0
  29. package/dist/crud/crud_loader.d.mts +21 -0
  30. package/dist/crud/crud_loader.d.ts +21 -0
  31. package/dist/crud/crud_loader.js +288 -0
  32. package/dist/crud/crud_loader.mjs +273 -0
  33. package/dist/crud/crud_page.d.mts +25 -0
  34. package/dist/crud/crud_page.d.ts +25 -0
  35. package/dist/crud/crud_page.js +645 -0
  36. package/dist/crud/crud_page.mjs +616 -0
  37. package/dist/crud/generate_handlers.d.mts +15 -0
  38. package/dist/crud/generate_handlers.d.ts +15 -0
  39. package/dist/crud/generate_handlers.js +39 -0
  40. package/dist/crud/generate_handlers.mjs +14 -0
  41. package/dist/crud/generate_pages.d.mts +11 -0
  42. package/dist/crud/generate_pages.d.ts +11 -0
  43. package/dist/crud/generate_pages.js +52 -0
  44. package/dist/crud/generate_pages.mjs +17 -0
  45. package/dist/crud/generate_routes.d.mts +5 -0
  46. package/dist/crud/generate_routes.d.ts +5 -0
  47. package/dist/crud/generate_routes.js +62 -0
  48. package/dist/crud/generate_routes.mjs +27 -0
  49. package/dist/crud/index.d.mts +21 -0
  50. package/dist/crud/index.d.ts +21 -0
  51. package/dist/crud/index.js +970 -0
  52. package/dist/crud/index.mjs +945 -0
  53. package/dist/db/index.d.mts +4 -0
  54. package/dist/db/index.d.ts +4 -0
  55. package/dist/db/index.js +46 -0
  56. package/dist/db/index.mjs +8 -0
  57. package/dist/index.d.mts +3 -2
  58. package/dist/index.d.ts +3 -2
  59. package/dist/seo/index.js +26 -25
  60. package/dist/seo/index.mjs +27 -26
  61. package/dist/seo/seo.js +26 -25
  62. package/dist/seo/seo.mjs +27 -26
  63. package/dist/table/buttons.d.mts +10 -0
  64. package/dist/table/buttons.d.ts +10 -0
  65. package/dist/table/buttons.js +102 -0
  66. package/dist/table/buttons.mjs +71 -0
  67. package/dist/table/index.d.mts +9 -0
  68. package/dist/table/index.d.ts +9 -0
  69. package/dist/table/index.js +570 -0
  70. package/dist/table/index.mjs +543 -0
  71. package/dist/table/item_loader.d.mts +12 -0
  72. package/dist/table/item_loader.d.ts +12 -0
  73. package/dist/table/item_loader.js +51 -0
  74. package/dist/table/item_loader.mjs +26 -0
  75. package/dist/table/loader.d.mts +28 -0
  76. package/dist/table/loader.d.ts +28 -0
  77. package/dist/table/loader.js +70 -0
  78. package/dist/table/loader.mjs +48 -0
  79. package/dist/table/page.d.mts +27 -0
  80. package/dist/table/page.d.ts +27 -0
  81. package/dist/table/page.js +444 -0
  82. package/dist/table/page.mjs +415 -0
  83. package/dist/table/repository.d.mts +38 -0
  84. package/dist/table/repository.d.ts +38 -0
  85. package/dist/table/repository.js +76 -0
  86. package/dist/table/repository.mjs +56 -0
  87. package/dist/table/table.d.mts +27 -0
  88. package/dist/table/table.d.ts +27 -0
  89. package/dist/table/table.js +290 -0
  90. package/dist/table/table.mjs +255 -0
  91. package/package.json +21 -3
  92. package/dist/auth/temp_user.d.mts +0 -5
  93. package/dist/auth/temp_user.d.ts +0 -5
  94. package/dist/auth/temp_user.js +0 -18
  95. package/dist/auth/temp_user.mjs +0 -0
@@ -0,0 +1,28 @@
1
+ import { LoaderFunctionArgs } from 'react-router';
2
+ import { TableRepository, ColumnOf } from './repository.js';
3
+ import { Table, SQLWrapper, InferSelectModel } from 'drizzle-orm';
4
+ import 'drizzle-orm/pg-core';
5
+
6
+ type TableOptions<T extends Table> = {
7
+ where?: SQLWrapper[];
8
+ searchKey?: ColumnOf<T>;
9
+ defaultOrderBy: keyof InferSelectModel<T>;
10
+ defaultDirection: "asc" | "desc";
11
+ };
12
+ type TableLoaderOptions<T extends Table, TSelect> = {
13
+ repository: TableRepository<T, TSelect>;
14
+ tableOptions: TableOptions<T>;
15
+ };
16
+ declare function tableLoader<T extends Table, TSelect>({ repository, tableOptions, }: TableLoaderOptions<T, TSelect>): ({ request }: LoaderFunctionArgs) => Promise<{
17
+ table: {
18
+ items: TSelect[];
19
+ total: number;
20
+ limit: number;
21
+ offset: number;
22
+ orderBy: keyof T["_"]["columns"] & string;
23
+ direction: "desc" | "asc";
24
+ searchKey: ColumnOf<T> | undefined;
25
+ };
26
+ }>;
27
+
28
+ export { type TableLoaderOptions, tableLoader };
@@ -0,0 +1,70 @@
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/table/loader.tsx
21
+ var loader_exports = {};
22
+ __export(loader_exports, {
23
+ tableLoader: () => tableLoader
24
+ });
25
+ module.exports = __toCommonJS(loader_exports);
26
+ var import_drizzle_orm = require("drizzle-orm");
27
+ function tableLoader({
28
+ repository,
29
+ tableOptions
30
+ }) {
31
+ return async ({ request }) => {
32
+ const searchParams = new URL(request.url).searchParams;
33
+ const { where, searchKey, defaultOrderBy, defaultDirection } = tableOptions;
34
+ const query = searchParams.get("query") ?? void 0;
35
+ const limit = Number(searchParams.get("limit") ?? "10");
36
+ const offset = Number(searchParams.get("offset") ?? "0");
37
+ const orderBy = searchParams.get("orderBy") ?? defaultOrderBy;
38
+ const direction = searchParams.get("direction") ?? defaultDirection;
39
+ const whereClauses = (0, import_drizzle_orm.and)(
40
+ searchKey && query ? (0, import_drizzle_orm.ilike)(
41
+ repository.schema[searchKey],
42
+ `%${query}%`
43
+ ) : void 0,
44
+ ...where ?? []
45
+ );
46
+ const total = await repository.countTotal({ where: whereClauses });
47
+ const items = await repository.findAll({
48
+ orderBy,
49
+ direction,
50
+ limit,
51
+ offset,
52
+ where: whereClauses
53
+ });
54
+ return {
55
+ table: {
56
+ items,
57
+ total,
58
+ limit,
59
+ offset,
60
+ orderBy,
61
+ direction,
62
+ searchKey
63
+ }
64
+ };
65
+ };
66
+ }
67
+ // Annotate the CommonJS export names for ESM import in node:
68
+ 0 && (module.exports = {
69
+ tableLoader
70
+ });
@@ -0,0 +1,48 @@
1
+ // src/table/loader.tsx
2
+ import {
3
+ and,
4
+ ilike
5
+ } from "drizzle-orm";
6
+ function tableLoader({
7
+ repository,
8
+ tableOptions
9
+ }) {
10
+ return async ({ request }) => {
11
+ const searchParams = new URL(request.url).searchParams;
12
+ const { where, searchKey, defaultOrderBy, defaultDirection } = tableOptions;
13
+ const query = searchParams.get("query") ?? void 0;
14
+ const limit = Number(searchParams.get("limit") ?? "10");
15
+ const offset = Number(searchParams.get("offset") ?? "0");
16
+ const orderBy = searchParams.get("orderBy") ?? defaultOrderBy;
17
+ const direction = searchParams.get("direction") ?? defaultDirection;
18
+ const whereClauses = and(
19
+ searchKey && query ? ilike(
20
+ repository.schema[searchKey],
21
+ `%${query}%`
22
+ ) : void 0,
23
+ ...where ?? []
24
+ );
25
+ const total = await repository.countTotal({ where: whereClauses });
26
+ const items = await repository.findAll({
27
+ orderBy,
28
+ direction,
29
+ limit,
30
+ offset,
31
+ where: whereClauses
32
+ });
33
+ return {
34
+ table: {
35
+ items,
36
+ total,
37
+ limit,
38
+ offset,
39
+ orderBy,
40
+ direction,
41
+ searchKey
42
+ }
43
+ };
44
+ };
45
+ }
46
+ export {
47
+ tableLoader
48
+ };
@@ -0,0 +1,27 @@
1
+ import { TableColumnOptions } from './table.mjs';
2
+ import React from 'react';
3
+
4
+ type TableProps<TModel> = {
5
+ items: TModel[];
6
+ total: number;
7
+ limit: number;
8
+ offset: number;
9
+ orderBy: string;
10
+ direction: string;
11
+ searchKey?: string;
12
+ };
13
+ type TablePageOptions<TModel> = {
14
+ name: string;
15
+ columns: TableColumnOptions<TModel>;
16
+ primaryKey?: keyof TModel;
17
+ };
18
+ declare function createTablePage<TModel>({ name, columns, primaryKey, }: TablePageOptions<TModel>): ({ AdminLayout, }: {
19
+ AdminLayout: React.FC<{
20
+ title: string;
21
+ actions?: React.ReactNode;
22
+ className?: string;
23
+ children?: React.ReactNode;
24
+ }>;
25
+ }) => React.JSX.Element;
26
+
27
+ export { type TablePageOptions, type TableProps, createTablePage };
@@ -0,0 +1,27 @@
1
+ import { TableColumnOptions } from './table.js';
2
+ import React from 'react';
3
+
4
+ type TableProps<TModel> = {
5
+ items: TModel[];
6
+ total: number;
7
+ limit: number;
8
+ offset: number;
9
+ orderBy: string;
10
+ direction: string;
11
+ searchKey?: string;
12
+ };
13
+ type TablePageOptions<TModel> = {
14
+ name: string;
15
+ columns: TableColumnOptions<TModel>;
16
+ primaryKey?: keyof TModel;
17
+ };
18
+ declare function createTablePage<TModel>({ name, columns, primaryKey, }: TablePageOptions<TModel>): ({ AdminLayout, }: {
19
+ AdminLayout: React.FC<{
20
+ title: string;
21
+ actions?: React.ReactNode;
22
+ className?: string;
23
+ children?: React.ReactNode;
24
+ }>;
25
+ }) => React.JSX.Element;
26
+
27
+ export { type TablePageOptions, type TableProps, createTablePage };
@@ -0,0 +1,444 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/table/page.tsx
31
+ var page_exports = {};
32
+ __export(page_exports, {
33
+ createTablePage: () => createTablePage
34
+ });
35
+ module.exports = __toCommonJS(page_exports);
36
+ var import_react_router3 = require("react-router");
37
+
38
+ // node_modules/react-icons/lib/iconBase.mjs
39
+ var import_react2 = __toESM(require("react"), 1);
40
+
41
+ // node_modules/react-icons/lib/iconContext.mjs
42
+ var import_react = __toESM(require("react"), 1);
43
+ var DefaultContext = {
44
+ color: void 0,
45
+ size: void 0,
46
+ className: void 0,
47
+ style: void 0,
48
+ attr: void 0
49
+ };
50
+ var IconContext = import_react.default.createContext && /* @__PURE__ */ import_react.default.createContext(DefaultContext);
51
+
52
+ // node_modules/react-icons/lib/iconBase.mjs
53
+ var _excluded = ["attr", "size", "title"];
54
+ function _objectWithoutProperties(source, excluded) {
55
+ if (source == null) return {};
56
+ var target = _objectWithoutPropertiesLoose(source, excluded);
57
+ var key, i;
58
+ if (Object.getOwnPropertySymbols) {
59
+ var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
60
+ for (i = 0; i < sourceSymbolKeys.length; i++) {
61
+ key = sourceSymbolKeys[i];
62
+ if (excluded.indexOf(key) >= 0) continue;
63
+ if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
64
+ target[key] = source[key];
65
+ }
66
+ }
67
+ return target;
68
+ }
69
+ function _objectWithoutPropertiesLoose(source, excluded) {
70
+ if (source == null) return {};
71
+ var target = {};
72
+ for (var key in source) {
73
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
74
+ if (excluded.indexOf(key) >= 0) continue;
75
+ target[key] = source[key];
76
+ }
77
+ }
78
+ return target;
79
+ }
80
+ function _extends() {
81
+ _extends = Object.assign ? Object.assign.bind() : function(target) {
82
+ for (var i = 1; i < arguments.length; i++) {
83
+ var source = arguments[i];
84
+ for (var key in source) {
85
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
86
+ target[key] = source[key];
87
+ }
88
+ }
89
+ }
90
+ return target;
91
+ };
92
+ return _extends.apply(this, arguments);
93
+ }
94
+ function ownKeys(e, r) {
95
+ var t = Object.keys(e);
96
+ if (Object.getOwnPropertySymbols) {
97
+ var o = Object.getOwnPropertySymbols(e);
98
+ r && (o = o.filter(function(r2) {
99
+ return Object.getOwnPropertyDescriptor(e, r2).enumerable;
100
+ })), t.push.apply(t, o);
101
+ }
102
+ return t;
103
+ }
104
+ function _objectSpread(e) {
105
+ for (var r = 1; r < arguments.length; r++) {
106
+ var t = null != arguments[r] ? arguments[r] : {};
107
+ r % 2 ? ownKeys(Object(t), true).forEach(function(r2) {
108
+ _defineProperty(e, r2, t[r2]);
109
+ }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function(r2) {
110
+ Object.defineProperty(e, r2, Object.getOwnPropertyDescriptor(t, r2));
111
+ });
112
+ }
113
+ return e;
114
+ }
115
+ function _defineProperty(obj, key, value) {
116
+ key = _toPropertyKey(key);
117
+ if (key in obj) {
118
+ Object.defineProperty(obj, key, { value, enumerable: true, configurable: true, writable: true });
119
+ } else {
120
+ obj[key] = value;
121
+ }
122
+ return obj;
123
+ }
124
+ function _toPropertyKey(t) {
125
+ var i = _toPrimitive(t, "string");
126
+ return "symbol" == typeof i ? i : i + "";
127
+ }
128
+ function _toPrimitive(t, r) {
129
+ if ("object" != typeof t || !t) return t;
130
+ var e = t[Symbol.toPrimitive];
131
+ if (void 0 !== e) {
132
+ var i = e.call(t, r || "default");
133
+ if ("object" != typeof i) return i;
134
+ throw new TypeError("@@toPrimitive must return a primitive value.");
135
+ }
136
+ return ("string" === r ? String : Number)(t);
137
+ }
138
+ function Tree2Element(tree) {
139
+ return tree && tree.map((node, i) => /* @__PURE__ */ import_react2.default.createElement(node.tag, _objectSpread({
140
+ key: i
141
+ }, node.attr), Tree2Element(node.child)));
142
+ }
143
+ function GenIcon(data) {
144
+ return (props) => /* @__PURE__ */ import_react2.default.createElement(IconBase, _extends({
145
+ attr: _objectSpread({}, data.attr)
146
+ }, props), Tree2Element(data.child));
147
+ }
148
+ function IconBase(props) {
149
+ var elem = (conf) => {
150
+ var {
151
+ attr,
152
+ size,
153
+ title
154
+ } = props, svgProps = _objectWithoutProperties(props, _excluded);
155
+ var computedSize = size || conf.size || "1em";
156
+ var className;
157
+ if (conf.className) className = conf.className;
158
+ if (props.className) className = (className ? className + " " : "") + props.className;
159
+ return /* @__PURE__ */ import_react2.default.createElement("svg", _extends({
160
+ stroke: "currentColor",
161
+ fill: "currentColor",
162
+ strokeWidth: "0"
163
+ }, conf.attr, attr, svgProps, {
164
+ className,
165
+ style: _objectSpread(_objectSpread({
166
+ color: props.color || conf.color
167
+ }, conf.style), props.style),
168
+ height: computedSize,
169
+ width: computedSize,
170
+ xmlns: "http://www.w3.org/2000/svg"
171
+ }), title && /* @__PURE__ */ import_react2.default.createElement("title", null, title), props.children);
172
+ };
173
+ return IconContext !== void 0 ? /* @__PURE__ */ import_react2.default.createElement(IconContext.Consumer, null, (conf) => elem(conf)) : elem(DefaultContext);
174
+ }
175
+
176
+ // node_modules/react-icons/go/index.mjs
177
+ function GoArrowDown(props) {
178
+ 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);
179
+ }
180
+ function GoArrowUp(props) {
181
+ 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);
182
+ }
183
+ function GoSearch(props) {
184
+ 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);
185
+ }
186
+
187
+ // src/table/buttons.tsx
188
+ var import_utils = require("dn-react-toolkit/utils");
189
+ var import_react_router = require("react-router");
190
+ var import_react3 = __toESM(require("react"));
191
+ function TablePageButtons({
192
+ MAX_PAGES_TO_SHOW,
193
+ total,
194
+ limit,
195
+ offset
196
+ }) {
197
+ const pages = Math.ceil(total / limit);
198
+ const { pathname } = (0, import_react_router.useLocation)();
199
+ const [searchParams] = (0, import_react_router.useSearchParams)();
200
+ const currentPage = Math.floor(offset / limit) + 1;
201
+ const startButton = (Math.ceil(currentPage / MAX_PAGES_TO_SHOW) - 1) * MAX_PAGES_TO_SHOW;
202
+ const endButton = Math.min(startButton + MAX_PAGES_TO_SHOW - 1, pages);
203
+ return /* @__PURE__ */ import_react3.default.createElement(import_react3.default.Fragment, null, pages > 1 && /* @__PURE__ */ import_react3.default.createElement("div", { className: "flex justify-center items-center my-8 gap-4 text-neutral-400" }, startButton > 1 && /* @__PURE__ */ import_react3.default.createElement(
204
+ import_react_router.Link,
205
+ {
206
+ to: (() => {
207
+ searchParams.set(
208
+ "offset",
209
+ String((startButton - 1) * limit)
210
+ );
211
+ return `${pathname}?${searchParams.toString()}`;
212
+ })(),
213
+ className: "w-10 block text-center transition-colors hover:text-primary"
214
+ },
215
+ "\uC774\uC804"
216
+ ), Array.from({
217
+ length: Math.min(
218
+ MAX_PAGES_TO_SHOW,
219
+ pages - startButton
220
+ )
221
+ }).map((_, index) => {
222
+ return /* @__PURE__ */ import_react3.default.createElement(
223
+ import_react_router.Link,
224
+ {
225
+ key: index,
226
+ to: (() => {
227
+ searchParams.set(
228
+ "offset",
229
+ String((startButton + index) * limit)
230
+ );
231
+ return `${pathname}?${searchParams.toString()}`;
232
+ })(),
233
+ className: (0, import_utils.cn)(
234
+ "w-6 block text-center transition-colors",
235
+ currentPage === startButton + index + 1 ? "font-bold text-primary" : "hover:text-primary"
236
+ )
237
+ },
238
+ startButton + index + 1
239
+ );
240
+ }), endButton < pages && /* @__PURE__ */ import_react3.default.createElement(
241
+ import_react_router.Link,
242
+ {
243
+ to: (() => {
244
+ searchParams.set(
245
+ "offset",
246
+ String((endButton + 1) * limit)
247
+ );
248
+ return `${pathname}?${searchParams.toString()}`;
249
+ })(),
250
+ className: "w-10 block text-center transition-colors hover:text-primary"
251
+ },
252
+ "\uB2E4\uC74C"
253
+ )));
254
+ }
255
+
256
+ // src/table/table.tsx
257
+ var import_utils2 = require("dn-react-toolkit/utils");
258
+ var import_react_router2 = require("react-router");
259
+ var import_react4 = __toESM(require("react"));
260
+ function Table({
261
+ className = "min-w-full whitespace-nowrap",
262
+ data,
263
+ columns,
264
+ mapper: Mapper,
265
+ getLink,
266
+ limit,
267
+ offset,
268
+ orderBy,
269
+ direction
270
+ }) {
271
+ const keys = Object.entries(columns).filter((entry) => entry[1]).map(([key]) => key);
272
+ const sortedArray = [...data];
273
+ const [_, setSearchParams] = (0, import_react_router2.useSearchParams)();
274
+ return /* @__PURE__ */ import_react4.default.createElement(
275
+ "table",
276
+ {
277
+ className: (0, import_utils2.cn)(
278
+ className,
279
+ "text-[15px] border-separate border-spacing-0"
280
+ )
281
+ },
282
+ /* @__PURE__ */ import_react4.default.createElement("thead", null, /* @__PURE__ */ import_react4.default.createElement("tr", null, keys.map((key) => {
283
+ const value = columns[key];
284
+ function getReactNode() {
285
+ if (value && typeof value === "object" && "label" in value) {
286
+ return value.label;
287
+ }
288
+ return value;
289
+ }
290
+ function Head() {
291
+ const reactNode = getReactNode();
292
+ if (typeof reactNode === "string") {
293
+ return /* @__PURE__ */ import_react4.default.createElement(
294
+ "button",
295
+ {
296
+ className: (0, import_utils2.cn)(
297
+ orderBy === key ? "text-neutral-900 font-medium" : "text-neutral-500",
298
+ "px-4 h-14 flex items-center w-full"
299
+ ),
300
+ onClick: () => {
301
+ let newDirection = "asc";
302
+ if (orderBy === key) {
303
+ newDirection = direction === "asc" ? "desc" : "asc";
304
+ }
305
+ setSearchParams({
306
+ orderBy: key,
307
+ direction: newDirection
308
+ });
309
+ }
310
+ },
311
+ reactNode,
312
+ orderBy === key && /* @__PURE__ */ import_react4.default.createElement("div", { className: "ml-0.5" }, direction === "asc" ? /* @__PURE__ */ import_react4.default.createElement(GoArrowUp, null) : /* @__PURE__ */ import_react4.default.createElement(GoArrowDown, null))
313
+ );
314
+ }
315
+ return /* @__PURE__ */ import_react4.default.createElement(import_react4.default.Fragment, null, reactNode);
316
+ }
317
+ return /* @__PURE__ */ import_react4.default.createElement(
318
+ "th",
319
+ {
320
+ key,
321
+ className: (0, import_utils2.cn)("border-y font-normal")
322
+ },
323
+ /* @__PURE__ */ import_react4.default.createElement(Head, null)
324
+ );
325
+ }))),
326
+ /* @__PURE__ */ import_react4.default.createElement("tbody", null, sortedArray.length === 0 && /* @__PURE__ */ import_react4.default.createElement("tr", null, /* @__PURE__ */ import_react4.default.createElement(
327
+ "td",
328
+ {
329
+ colSpan: keys.length,
330
+ className: "px-4 h-14 text-neutral-400 text-center"
331
+ },
332
+ "\uB370\uC774\uD130\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."
333
+ )), sortedArray.map((item, i) => /* @__PURE__ */ import_react4.default.createElement("tr", { key: i, className: "hover:bg-gray-50 transition-colors" }, keys.map((key, i2) => {
334
+ const value = item[key];
335
+ function Content() {
336
+ if (key in columns) {
337
+ const column = columns[key];
338
+ if (column && typeof column === "object" && "mapper" in column) {
339
+ const mapper = column.mapper;
340
+ if (mapper) {
341
+ return /* @__PURE__ */ import_react4.default.createElement(import_react4.default.Fragment, null, mapper(item));
342
+ }
343
+ }
344
+ }
345
+ return /* @__PURE__ */ import_react4.default.createElement(import_react4.default.Fragment, null, String(value));
346
+ }
347
+ const linkedContent = getLink ? /* @__PURE__ */ import_react4.default.createElement(
348
+ import_react_router2.Link,
349
+ {
350
+ to: getLink(item),
351
+ className: "block content-center px-4 w-full h-full"
352
+ },
353
+ /* @__PURE__ */ import_react4.default.createElement(Content, null)
354
+ ) : /* @__PURE__ */ import_react4.default.createElement(Content, null);
355
+ const cell = Mapper ? /* @__PURE__ */ import_react4.default.createElement(Mapper, { item, index: i2 }, linkedContent) : linkedContent;
356
+ return /* @__PURE__ */ import_react4.default.createElement("td", { key, className: "px-0 h-14 border-b" }, cell);
357
+ }))))
358
+ );
359
+ }
360
+
361
+ // src/table/page.tsx
362
+ var import_react5 = __toESM(require("react"));
363
+ function createTablePage({
364
+ name,
365
+ columns,
366
+ primaryKey = "id"
367
+ }) {
368
+ return function TablePage({
369
+ AdminLayout
370
+ }) {
371
+ const { pathname } = (0, import_react_router3.useLocation)();
372
+ const { table } = (0, import_react_router3.useLoaderData)();
373
+ const { items, total, limit, offset, orderBy, direction, searchKey } = table;
374
+ const navigate = (0, import_react_router3.useNavigate)();
375
+ const search = (query) => {
376
+ const searchParams2 = new URLSearchParams(window.location.search);
377
+ searchParams2.set("query", query);
378
+ searchParams2.set("offset", "0");
379
+ navigate(`${pathname}?${searchParams2.toString()}`);
380
+ };
381
+ const [searchParams] = (0, import_react_router3.useSearchParams)();
382
+ return /* @__PURE__ */ import_react5.default.createElement(
383
+ AdminLayout,
384
+ {
385
+ title: name,
386
+ actions: /* @__PURE__ */ import_react5.default.createElement(import_react_router3.Link, { to: `${pathname}/new`, className: "button-primary" }, name, " \uCD94\uAC00")
387
+ },
388
+ searchKey && /* @__PURE__ */ import_react5.default.createElement(
389
+ "form",
390
+ {
391
+ className: "h-18 px-4 flex items-center border-t",
392
+ onSubmit: (e) => {
393
+ e.preventDefault();
394
+ const formData = new FormData(e.currentTarget);
395
+ const query = formData.get("query");
396
+ search(query);
397
+ }
398
+ },
399
+ /* @__PURE__ */ import_react5.default.createElement(
400
+ "button",
401
+ {
402
+ type: "submit",
403
+ className: "w-10 h-10 flex justify-center items-center"
404
+ },
405
+ /* @__PURE__ */ import_react5.default.createElement(GoSearch, { className: "text-xl mr-4" })
406
+ ),
407
+ /* @__PURE__ */ import_react5.default.createElement(
408
+ "input",
409
+ {
410
+ className: "outline-none h-full flex-1",
411
+ placeholder: "\uC5EC\uAE30\uC5D0 \uAC80\uC0C9\uD558\uC138\uC694...",
412
+ name: "query",
413
+ defaultValue: searchParams.get("query") ?? ""
414
+ }
415
+ )
416
+ ),
417
+ /* @__PURE__ */ import_react5.default.createElement(
418
+ Table,
419
+ {
420
+ data: items,
421
+ columns,
422
+ getLink: primaryKey ? (item) => `${pathname}/${item[primaryKey]}` : void 0,
423
+ limit,
424
+ offset,
425
+ orderBy,
426
+ direction
427
+ }
428
+ ),
429
+ /* @__PURE__ */ import_react5.default.createElement(
430
+ TablePageButtons,
431
+ {
432
+ total,
433
+ limit,
434
+ offset,
435
+ MAX_PAGES_TO_SHOW: 10
436
+ }
437
+ )
438
+ );
439
+ };
440
+ }
441
+ // Annotate the CommonJS export names for ESM import in node:
442
+ 0 && (module.exports = {
443
+ createTablePage
444
+ });