akanjs 0.0.1 → 2.0.0-beta.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 (682) hide show
  1. package/CODE_OF_CONDUCT.md +54 -0
  2. package/CONTRIBUTING.md +83 -0
  3. package/LICENSE +21 -0
  4. package/README.ko.md +244 -0
  5. package/README.md +237 -6
  6. package/base/base.ts +194 -0
  7. package/base/baseEnv.ts +162 -0
  8. package/base/index.ts +6 -0
  9. package/base/primitiveRegistry.ts +342 -0
  10. package/base/symbols.ts +11 -0
  11. package/base/types.ts +137 -0
  12. package/base/utils.ts +30 -0
  13. package/cli/application/application.command.ts +213 -0
  14. package/cli/application/application.interface.tsx +225 -0
  15. package/cli/application/application.runner.ts +359 -0
  16. package/cli/application/application.script.ts +244 -0
  17. package/cli/build.ts +25 -0
  18. package/cli/cloud/cloud.command.ts +48 -0
  19. package/cli/cloud/cloud.runner.ts +158 -0
  20. package/cli/cloud/cloud.script.ts +40 -0
  21. package/cli/guideline/guideline.command.ts +31 -0
  22. package/cli/guideline/guideline.prompt.ts +212 -0
  23. package/cli/guideline/guideline.runner.ts +53 -0
  24. package/cli/guideline/guideline.script.ts +33 -0
  25. package/cli/guidelines/___library/sharedUiStructureDescription.en.md +767 -0
  26. package/cli/guidelines/___library/utilUiStructureDescription.en.md +395 -0
  27. package/cli/guidelines/___lint/lintRuleDescription.en.md +64 -0
  28. package/cli/guidelines/___module/moduleStructureDescription.en.md +80 -0
  29. package/cli/guidelines/componentRule/componentRule.generate.json +131 -0
  30. package/cli/guidelines/componentRule/componentRule.instruction.md +637 -0
  31. package/cli/guidelines/cssRule/cssRule.generate.json +93 -0
  32. package/cli/guidelines/cssRule/cssRule.instruction.md +435 -0
  33. package/cli/guidelines/databaseModule/databaseModule.generate.json +51 -0
  34. package/cli/guidelines/databaseModule/databaseModule.instruction.md +612 -0
  35. package/cli/guidelines/docPageRule/docPageRule.generate.json +72 -0
  36. package/cli/guidelines/docPageRule/docPageRule.instruction.md +389 -0
  37. package/cli/guidelines/enumConstant/enumConstant.generate.json +24 -0
  38. package/cli/guidelines/enumConstant/enumConstant.instruction.md +232 -0
  39. package/cli/guidelines/framework/framework.generate.json +119 -0
  40. package/cli/guidelines/framework/framework.instruction.md +1110 -0
  41. package/cli/guidelines/howToUseStore/howToUseStore.generate.json +0 -0
  42. package/cli/guidelines/modelConstant/modelConstant.generate.json +128 -0
  43. package/cli/guidelines/modelConstant/modelConstant.instruction.md +506 -0
  44. package/cli/guidelines/modelDictionary/modelDictionary.generate.json +108 -0
  45. package/cli/guidelines/modelDictionary/modelDictionary.instruction.md +547 -0
  46. package/cli/guidelines/modelDocument/modelDocument.generate.json +129 -0
  47. package/cli/guidelines/modelDocument/modelDocument.instruction.md +536 -0
  48. package/cli/guidelines/modelService/modelService.generate.json +135 -0
  49. package/cli/guidelines/modelService/modelService.instruction.md +708 -0
  50. package/cli/guidelines/modelSignal/modelSignal.generate.json +201 -0
  51. package/cli/guidelines/modelSignal/modelSignal.instruction.md +552 -0
  52. package/cli/guidelines/modelStore/modelStore.generate.json +130 -0
  53. package/cli/guidelines/modelStore/modelStore.instruction.md +585 -0
  54. package/cli/guidelines/modelTemplate/modelTemplate.generate.json +104 -0
  55. package/cli/guidelines/modelTemplate/modelTemplate.instruction.md +604 -0
  56. package/cli/guidelines/modelUnit/modelUnit.generate.json +92 -0
  57. package/cli/guidelines/modelUnit/modelUnit.instruction.md +541 -0
  58. package/cli/guidelines/modelUtil/modelUtil.generate.json +93 -0
  59. package/cli/guidelines/modelUtil/modelUtil.instruction.md +752 -0
  60. package/cli/guidelines/modelView/modelView.generate.json +80 -0
  61. package/cli/guidelines/modelView/modelView.instruction.md +1005 -0
  62. package/cli/guidelines/modelZone/modelZone.generate.json +126 -0
  63. package/cli/guidelines/modelZone/modelZone.instruction.md +528 -0
  64. package/cli/guidelines/scalarConstant/scalarConstant.generate.json +106 -0
  65. package/cli/guidelines/scalarConstant/scalarConstant.instruction.md +442 -0
  66. package/cli/guidelines/scalarDictionary/scalarDictionary.generate.json +83 -0
  67. package/cli/guidelines/scalarDictionary/scalarDictionary.instruction.md +273 -0
  68. package/cli/guidelines/scalarModule/scalarModule.generate.json +35 -0
  69. package/cli/guidelines/scalarModule/scalarModule.instruction.md +81 -0
  70. package/cli/guidelines/sharedUiUsage/sharedUiUsage.generate.json +108 -0
  71. package/cli/guidelines/sharedUiUsage/sharedUiUsage.instruction.md +310 -0
  72. package/cli/guidelines/utilUiUsage/utilUiUsage.generate.json +140 -0
  73. package/cli/guidelines/utilUiUsage/utilUiUsage.instruction.md +339 -0
  74. package/cli/index.js +11401 -0
  75. package/cli/index.ts +24 -0
  76. package/cli/library/library.command.ts +28 -0
  77. package/cli/library/library.runner.ts +69 -0
  78. package/cli/library/library.script.ts +39 -0
  79. package/cli/module/module.command.ts +35 -0
  80. package/cli/module/module.prompt.ts +18 -0
  81. package/cli/module/module.request.ts +319 -0
  82. package/cli/module/module.runner.ts +76 -0
  83. package/cli/module/module.script.ts +161 -0
  84. package/cli/package/package.command.ts +32 -0
  85. package/cli/package/package.runner.ts +64 -0
  86. package/cli/package/package.script.ts +35 -0
  87. package/cli/page/page.command.ts +14 -0
  88. package/cli/page/page.runner.ts +14 -0
  89. package/cli/page/page.script.ts +12 -0
  90. package/cli/scalar/scalar.command.ts +21 -0
  91. package/cli/scalar/scalar.prompt.ts +131 -0
  92. package/cli/scalar/scalar.runner.ts +38 -0
  93. package/cli/scalar/scalar.script.ts +16 -0
  94. package/cli/templates/__scalar/__model__/__model__.constant.ts +15 -0
  95. package/cli/templates/__scalar/__model__/__model__.dictionary.ts +19 -0
  96. package/cli/templates/__scalar/__model__/__model__.document.ts +15 -0
  97. package/cli/templates/app/akan.config.ts +14 -0
  98. package/cli/templates/app/capacitor.config.ts.template +8 -0
  99. package/cli/templates/app/common/commonLogic.ts +12 -0
  100. package/cli/templates/app/common/index.ts +10 -0
  101. package/cli/templates/app/env/env.client.debug.ts.template +7 -0
  102. package/cli/templates/app/env/env.client.develop.ts.template +7 -0
  103. package/cli/templates/app/env/env.client.local.ts.template +7 -0
  104. package/cli/templates/app/env/env.client.main.ts.template +7 -0
  105. package/cli/templates/app/env/env.client.testing.ts.template +7 -0
  106. package/cli/templates/app/env/env.client.ts +21 -0
  107. package/cli/templates/app/env/env.client.type.ts +16 -0
  108. package/cli/templates/app/env/env.server.debug.ts.template +7 -0
  109. package/cli/templates/app/env/env.server.develop.ts.template +9 -0
  110. package/cli/templates/app/env/env.server.local.ts.template +14 -0
  111. package/cli/templates/app/env/env.server.main.ts.template +9 -0
  112. package/cli/templates/app/env/env.server.testing.ts.template +6 -0
  113. package/cli/templates/app/env/env.server.ts +20 -0
  114. package/cli/templates/app/lib/___appName__/__appName__.dictionary.ts +17 -0
  115. package/cli/templates/app/lib/___appName__/__appName__.service.ts +13 -0
  116. package/cli/templates/app/lib/___appName__/__appName__.signal.ts +17 -0
  117. package/cli/templates/app/lib/___appName__/__appName__.store.ts +15 -0
  118. package/cli/templates/app/lib/option.ts +17 -0
  119. package/cli/templates/app/main.ts +16 -0
  120. package/cli/templates/app/package.json.template +5 -0
  121. package/cli/templates/app/page/_index.tsx +172 -0
  122. package/cli/templates/app/page/_layout.tsx +32 -0
  123. package/cli/templates/app/page/styles.css.template +53 -0
  124. package/cli/templates/app/public/favicon.ico +0 -0
  125. package/cli/templates/app/public/logo.png +0 -0
  126. package/cli/templates/app/srvkit/backendLogic.ts +12 -0
  127. package/cli/templates/app/srvkit/index.ts +10 -0
  128. package/cli/templates/app/tsconfig.json.template +21 -0
  129. package/cli/templates/app/ui/UiComponent.ts +16 -0
  130. package/cli/templates/app/ui/index.ts +10 -0
  131. package/cli/templates/app/webkit/frontendLogic.ts +12 -0
  132. package/cli/templates/app/webkit/index.ts +10 -0
  133. package/cli/templates/client.ts +46 -0
  134. package/cli/templates/crudPages/[__model__Id]/edit/page.tsx +47 -0
  135. package/cli/templates/crudPages/[__model__Id]/page.tsx +52 -0
  136. package/cli/templates/crudPages/new/page.tsx +42 -0
  137. package/cli/templates/crudPages/page.tsx +43 -0
  138. package/cli/templates/crudSinglePage/page.tsx +37 -0
  139. package/cli/templates/env/_env.server.type.ts +16 -0
  140. package/cli/templates/facetIndex/index.ts +32 -0
  141. package/cli/templates/index.ts +10 -0
  142. package/cli/templates/lib/__lib/lib.constant.ts +38 -0
  143. package/cli/templates/lib/__lib/lib.dictionary.ts +33 -0
  144. package/cli/templates/lib/__lib/lib.document.ts +35 -0
  145. package/cli/templates/lib/__lib/lib.service.ts +33 -0
  146. package/cli/templates/lib/__lib/lib.signal.ts +34 -0
  147. package/cli/templates/lib/__lib/lib.store.ts +33 -0
  148. package/cli/templates/lib/cnst.ts +29 -0
  149. package/cli/templates/lib/db.ts +32 -0
  150. package/cli/templates/lib/dict.ts +49 -0
  151. package/cli/templates/lib/sig.ts +60 -0
  152. package/cli/templates/lib/srv.ts +34 -0
  153. package/cli/templates/lib/st.ts +31 -0
  154. package/cli/templates/lib/useClient.ts +19 -0
  155. package/cli/templates/lib/useServer.ts +7 -0
  156. package/cli/templates/libRoot/.gitignore.template +16 -0
  157. package/cli/templates/libRoot/akan.config.ts +12 -0
  158. package/cli/templates/libRoot/base/baseLogic.ts +10 -0
  159. package/cli/templates/libRoot/base/index.ts +8 -0
  160. package/cli/templates/libRoot/common/commonLogic.ts +10 -0
  161. package/cli/templates/libRoot/common/index.ts +8 -0
  162. package/cli/templates/libRoot/env/env.server.example.ts.template +6 -0
  163. package/cli/templates/libRoot/env/env.server.testing.ts.template +6 -0
  164. package/cli/templates/libRoot/lib/___libName__/__libName__.dictionary.ts +15 -0
  165. package/cli/templates/libRoot/lib/___libName__/__libName__.service.ts +11 -0
  166. package/cli/templates/libRoot/lib/___libName__/__libName__.store.ts +13 -0
  167. package/cli/templates/libRoot/lib/option.ts +17 -0
  168. package/cli/templates/libRoot/package.json.template +5 -0
  169. package/cli/templates/libRoot/srvkit/backendLogic.ts +10 -0
  170. package/cli/templates/libRoot/srvkit/index.ts +8 -0
  171. package/cli/templates/libRoot/tsconfig.json.template +11 -0
  172. package/cli/templates/libRoot/ui/index.ts +7 -0
  173. package/cli/templates/libRoot/webkit/frontendLogic.ts +10 -0
  174. package/cli/templates/libRoot/webkit/index.ts +8 -0
  175. package/cli/templates/localDev/docker-compose.yaml.template +37 -0
  176. package/cli/templates/module/__Model__.Template.tsx +36 -0
  177. package/cli/templates/module/__Model__.Unit.tsx +26 -0
  178. package/cli/templates/module/__Model__.Util.tsx +30 -0
  179. package/cli/templates/module/__Model__.View.tsx +29 -0
  180. package/cli/templates/module/__Model__.Zone.tsx +43 -0
  181. package/cli/templates/module/__model__.constant.ts +24 -0
  182. package/cli/templates/module/__model__.dictionary.ts +30 -0
  183. package/cli/templates/module/__model__.document.ts +23 -0
  184. package/cli/templates/module/__model__.service.ts +16 -0
  185. package/cli/templates/module/__model__.signal.ts +27 -0
  186. package/cli/templates/module/__model__.store.ts +19 -0
  187. package/cli/templates/module/index.tsx +44 -0
  188. package/cli/templates/moduleRoot/index.tsx +31 -0
  189. package/cli/templates/pkgRoot/tsconfig.json.template +10 -0
  190. package/cli/templates/server.ts +45 -0
  191. package/cli/templates/workspaceRoot/.env.template +14 -0
  192. package/cli/templates/workspaceRoot/.gitignore.template +130 -0
  193. package/cli/templates/workspaceRoot/.vscode/settings.json.template +23 -0
  194. package/cli/templates/workspaceRoot/biome.json.template +175 -0
  195. package/cli/templates/workspaceRoot/bunfig.toml +4 -0
  196. package/cli/templates/workspaceRoot/infra/app/Chart.yaml.template +6 -0
  197. package/cli/templates/workspaceRoot/infra/app/templates/frontend.yaml.template +182 -0
  198. package/cli/templates/workspaceRoot/infra/app/values/_common-values.yaml.template +183 -0
  199. package/cli/templates/workspaceRoot/package.json.template +7 -0
  200. package/cli/templates/workspaceRoot/tsconfig.json.template +26 -0
  201. package/cli/testHelpers.ts +171 -0
  202. package/cli/workspace/workspace.command.ts +60 -0
  203. package/cli/workspace/workspace.runner.ts +57 -0
  204. package/cli/workspace/workspace.script.ts +68 -0
  205. package/client/capacitor.ts +68 -0
  206. package/client/clientRuntime.ts +141 -0
  207. package/client/cookie.ts +121 -0
  208. package/client/createFont.ts +8 -0
  209. package/client/csrTypes.ts +259 -0
  210. package/client/decorators.ts +25 -0
  211. package/client/device.ts +147 -0
  212. package/client/fetch.ts +1 -0
  213. package/client/index.ts +15 -0
  214. package/client/locale.ts +4 -0
  215. package/client/makePageProto.tsx +178 -0
  216. package/client/router.ts +286 -0
  217. package/client/rscNavigation.ts +19 -0
  218. package/client/storage.ts +33 -0
  219. package/client/translator.ts +43 -0
  220. package/client/types.ts +228 -0
  221. package/client/useClient.ts +1 -0
  222. package/common/Logger.ts +177 -0
  223. package/common/applyMixins.ts +14 -0
  224. package/common/capitalize.ts +4 -0
  225. package/common/deepObjectify.ts +27 -0
  226. package/common/formatNumber.ts +14 -0
  227. package/common/formatPhone.ts +7 -0
  228. package/common/getAllPropertyDescriptors.ts +13 -0
  229. package/common/hmrPhase.ts +17 -0
  230. package/common/httpClient.ts +101 -0
  231. package/common/index.ts +50 -0
  232. package/common/isDayjs.ts +3 -0
  233. package/common/isEmail.ts +2 -0
  234. package/common/isPhoneNumber.ts +8 -0
  235. package/common/isQueryEqual.ts +23 -0
  236. package/common/isValidDate.ts +14 -0
  237. package/common/localeConfig.ts +41 -0
  238. package/common/lowerlize.ts +4 -0
  239. package/common/mergeVersion.ts +10 -0
  240. package/common/objectify.ts +7 -0
  241. package/common/pathGet.ts +13 -0
  242. package/common/pathSet.ts +16 -0
  243. package/common/randomPick.ts +1 -0
  244. package/common/randomPicks.ts +12 -0
  245. package/common/routeConvention.ts +203 -0
  246. package/common/sleep.ts +8 -0
  247. package/common/splitVersion.ts +11 -0
  248. package/common/subRoute.ts +34 -0
  249. package/common/types.ts +15 -0
  250. package/constant/constantRegistry.ts +334 -0
  251. package/constant/crystalize.ts +45 -0
  252. package/constant/deserialize.ts +70 -0
  253. package/constant/fieldInfo.ts +415 -0
  254. package/constant/getDefault.ts +18 -0
  255. package/constant/immerify.ts +16 -0
  256. package/constant/index.ts +10 -0
  257. package/constant/purify.ts +118 -0
  258. package/constant/serialize.ts +87 -0
  259. package/constant/types.ts +105 -0
  260. package/constant/via.ts +360 -0
  261. package/devkit/aiEditor.ts +299 -0
  262. package/devkit/akanApp/akanApp.host.ts +356 -0
  263. package/devkit/akanApp/index.ts +1 -0
  264. package/devkit/akanConfig/akanConfig.ts +332 -0
  265. package/devkit/akanConfig/index.ts +2 -0
  266. package/devkit/akanConfig/types.ts +187 -0
  267. package/devkit/applicationBuildReporter.ts +69 -0
  268. package/devkit/applicationBuildRunner.ts +302 -0
  269. package/devkit/applicationReleasePackager.ts +205 -0
  270. package/devkit/artifact/implicitRootLayout.ts +155 -0
  271. package/devkit/artifact/index.ts +1 -0
  272. package/devkit/artifact/routeSeedIndex.ts +128 -0
  273. package/devkit/auth.ts +41 -0
  274. package/devkit/builder.ts +164 -0
  275. package/devkit/capacitor.base.config.ts +74 -0
  276. package/devkit/capacitorApp.ts +385 -0
  277. package/devkit/commandDecorators/argMeta.ts +88 -0
  278. package/devkit/commandDecorators/command.ts +314 -0
  279. package/devkit/commandDecorators/commandBuilder.ts +188 -0
  280. package/devkit/commandDecorators/commandMeta.ts +6 -0
  281. package/devkit/commandDecorators/dependencyBuilder.ts +100 -0
  282. package/devkit/commandDecorators/helpFormatter.ts +217 -0
  283. package/devkit/commandDecorators/index.ts +8 -0
  284. package/devkit/commandDecorators/targetMeta.ts +31 -0
  285. package/devkit/commandDecorators/types.ts +10 -0
  286. package/devkit/constants.ts +25 -0
  287. package/devkit/createTunnel.ts +36 -0
  288. package/devkit/dependencyScanner.ts +339 -0
  289. package/devkit/executors.ts +1326 -0
  290. package/devkit/extractDeps.ts +85 -0
  291. package/devkit/fileEditor.ts +106 -0
  292. package/devkit/fileSys.ts +39 -0
  293. package/devkit/frontendBuild/allRoutesBuilder.ts +103 -0
  294. package/devkit/frontendBuild/clientBuildTypes.ts +114 -0
  295. package/devkit/frontendBuild/clientEntriesBundler.ts +300 -0
  296. package/devkit/frontendBuild/clientEntryDiscovery.ts +196 -0
  297. package/devkit/frontendBuild/csrArtifactBuilder.ts +237 -0
  298. package/devkit/frontendBuild/cssCompiler.ts +279 -0
  299. package/devkit/frontendBuild/cssImportResolver.ts +116 -0
  300. package/devkit/frontendBuild/fontOptimizer.ts +427 -0
  301. package/devkit/frontendBuild/hmrChangeClassifier.ts +28 -0
  302. package/devkit/frontendBuild/hmrWatcher.ts +101 -0
  303. package/devkit/frontendBuild/index.ts +18 -0
  304. package/devkit/frontendBuild/pagesBundleBuilder.ts +137 -0
  305. package/devkit/frontendBuild/pagesEntrySourceGenerator.ts +37 -0
  306. package/devkit/frontendBuild/precompressArtifacts.ts +59 -0
  307. package/devkit/frontendBuild/routeClientBuilder.ts +290 -0
  308. package/devkit/frontendBuild/routesManifestArtifactSerializer.ts +62 -0
  309. package/devkit/frontendBuild/ssrBaseArtifactBuilder.ts +139 -0
  310. package/devkit/frontendBuild/vendorSpecifiers.ts +16 -0
  311. package/devkit/frontendBuild/watchRootResolver.ts +28 -0
  312. package/devkit/getCredentials.ts +19 -0
  313. package/devkit/getDirname.ts +3 -0
  314. package/devkit/getModelFileData.ts +59 -0
  315. package/devkit/getRelatedCnsts.ts +300 -0
  316. package/devkit/guideline.ts +19 -0
  317. package/devkit/incrementalBuilder/incrementalBuilder.host.ts +78 -0
  318. package/devkit/incrementalBuilder/incrementalBuilder.proc.ts +330 -0
  319. package/devkit/incrementalBuilder/index.ts +1 -0
  320. package/devkit/index.ts +36 -0
  321. package/devkit/lint/no-import-client-functions.grit +32 -0
  322. package/devkit/lint/no-import-external-library.grit +21 -0
  323. package/devkit/lint/no-js-private-class-method.grit +42 -0
  324. package/devkit/lint/no-use-client-in-server.grit +7 -0
  325. package/devkit/lint/non-scalar-props-restricted.grit +13 -0
  326. package/devkit/linter.ts +248 -0
  327. package/devkit/mobile/index.ts +1 -0
  328. package/devkit/mobile/mobileTarget.ts +47 -0
  329. package/devkit/prompter.ts +71 -0
  330. package/devkit/scanInfo.ts +605 -0
  331. package/devkit/selectModel.ts +11 -0
  332. package/devkit/spinner.ts +54 -0
  333. package/devkit/sshTunnel.ts +151 -0
  334. package/devkit/streamAi.ts +45 -0
  335. package/devkit/transforms/barrelAnalyzer.ts +249 -0
  336. package/devkit/transforms/barrelImportsPlugin.ts +451 -0
  337. package/devkit/transforms/externalizeFrameworkPlugin.ts +159 -0
  338. package/devkit/transforms/index.ts +5 -0
  339. package/devkit/transforms/rscUseClientTransform.ts +52 -0
  340. package/devkit/transforms/useClientBundlePlugin.ts +47 -0
  341. package/devkit/typeChecker.ts +260 -0
  342. package/devkit/types.ts +42 -0
  343. package/devkit/ui/MultiScrollList.tsx +228 -0
  344. package/devkit/ui/ScrollList.tsx +106 -0
  345. package/devkit/ui/index.ts +2 -0
  346. package/devkit/uploadRelease.ts +95 -0
  347. package/devkit/useStdoutDimensions.ts +20 -0
  348. package/dictionary/base.dictionary.ts +91 -0
  349. package/dictionary/dictInfo.ts +1079 -0
  350. package/dictionary/dictionary.ts +10 -0
  351. package/dictionary/index.ts +12 -0
  352. package/dictionary/locale.ts +230 -0
  353. package/dictionary/trans.ts +196 -0
  354. package/document/by.ts +39 -0
  355. package/document/dataLoader.ts +91 -0
  356. package/document/database.ts +168 -0
  357. package/document/databaseRegistry.ts +113 -0
  358. package/document/documentQuery.ts +143 -0
  359. package/document/documentSchema.ts +91 -0
  360. package/document/filterMeta.ts +210 -0
  361. package/document/index.ts +11 -0
  362. package/document/into.ts +169 -0
  363. package/document/loaderInfo.ts +50 -0
  364. package/document/schema.ts +24 -0
  365. package/document/types.ts +41 -0
  366. package/fetch/client/fetchClient.ts +600 -0
  367. package/fetch/client/httpClient.ts +157 -0
  368. package/fetch/client/index.ts +3 -0
  369. package/fetch/client/wsClient.ts +246 -0
  370. package/fetch/fetchType/appliedReturn.type.ts +108 -0
  371. package/fetch/fetchType/buildFetch.type.ts +24 -0
  372. package/fetch/fetchType/clientSignal.type.ts +22 -0
  373. package/fetch/fetchType/endpointFetch.type.ts +56 -0
  374. package/fetch/fetchType/index.ts +5 -0
  375. package/fetch/fetchType/sliceFetch.type.ts +173 -0
  376. package/fetch/index.ts +4 -0
  377. package/fetch/requestStorage.ts +127 -0
  378. package/fetch/serializer/fetch.serializer.ts +131 -0
  379. package/fetch/serializer/index.ts +1 -0
  380. package/fetch/types.ts +28 -0
  381. package/package.json +202 -5
  382. package/server/SSR_MEMORY_DIAGNOSIS.md +107 -0
  383. package/server/akanApp.ts +855 -0
  384. package/server/akanLib.ts +43 -0
  385. package/server/akanOption.ts +42 -0
  386. package/server/akanServer.ts +369 -0
  387. package/server/artifact/builderRpc.ts +124 -0
  388. package/server/artifact/index.ts +6 -0
  389. package/server/artifact/ipcTypes.ts +46 -0
  390. package/server/artifact/manifestTypes.ts +19 -0
  391. package/server/artifact/routeClientCache.ts +224 -0
  392. package/server/artifact/routeSeedIndexStore.ts +89 -0
  393. package/server/artifact/routesManifestStore.ts +120 -0
  394. package/server/decorators.ts +95 -0
  395. package/server/di/diLifecycle.ts +520 -0
  396. package/server/di/index.ts +4 -0
  397. package/server/di/predefinedAdaptor.ts +77 -0
  398. package/server/di/resolveAdaptorHierarchy.ts +82 -0
  399. package/server/di/resolveHierarchy.ts +89 -0
  400. package/server/di/resolveServiceHierarchy.ts +47 -0
  401. package/server/di/utils.ts +40 -0
  402. package/server/hmr/changeBatch.ts +14 -0
  403. package/server/hmr/clientScript.ts +310 -0
  404. package/server/hmr/devHmrController.ts +395 -0
  405. package/server/hmr/index.ts +4 -0
  406. package/server/hmr/wsHub.ts +56 -0
  407. package/server/imageOptimizer.ts +427 -0
  408. package/server/imageOptimizerError.ts +8 -0
  409. package/server/index.ts +14 -0
  410. package/server/lifecycle/shutdownManager.ts +52 -0
  411. package/server/logging/rotatingLogWriter.ts +190 -0
  412. package/server/processMetricsCollector.ts +78 -0
  413. package/server/proxy/akanResponse.ts +16 -0
  414. package/server/proxy/bunRequestFields.ts +12 -0
  415. package/server/proxy/hostBasePathWebProxy.ts +112 -0
  416. package/server/proxy/index.ts +15 -0
  417. package/server/proxy/localeWebProxy.ts +71 -0
  418. package/server/proxy/types.ts +41 -0
  419. package/server/proxy/webProxyRunner.ts +90 -0
  420. package/server/resolver/database.resolver.ts +340 -0
  421. package/server/resolver/index.ts +3 -0
  422. package/server/resolver/resolver.contract.fixture.ts +222 -0
  423. package/server/resolver/service.resolver.ts +176 -0
  424. package/server/resolver/signal.resolver.ts +386 -0
  425. package/server/robots.ts +32 -0
  426. package/server/routeElementComposer.tsx +91 -0
  427. package/server/routeTreeBuilder.ts +279 -0
  428. package/server/routing/apiRouter.ts +226 -0
  429. package/server/rscClient.tsx +140 -0
  430. package/server/rscWorker.tsx +625 -0
  431. package/server/rscWorkerHost.ts +616 -0
  432. package/server/sitemap.ts +90 -0
  433. package/server/ssrFromRscRenderer.tsx +285 -0
  434. package/server/ssrTypes.ts +48 -0
  435. package/server/types/react-server-dom-webpack.d.ts +91 -0
  436. package/server/types.tsx +109 -0
  437. package/server/vendor/akanjs-base.ts +1 -0
  438. package/server/vendor/akanjs-common.ts +1 -0
  439. package/server/vendor/akanjs-constant.ts +1 -0
  440. package/server/vendor/akanjs-store.ts +1 -0
  441. package/server/vendor/react-dom-client.ts +5 -0
  442. package/server/vendor/react-dom.ts +21 -0
  443. package/server/vendor/react-jsx-dev-runtime.ts +5 -0
  444. package/server/vendor/react-jsx-runtime.ts +5 -0
  445. package/server/vendor/react-refresh-runtime.ts +6 -0
  446. package/server/vendor/react-server-dom-webpack-client-browser.ts +12 -0
  447. package/server/vendor/react.ts +51 -0
  448. package/server/vendor/scheduler.ts +23 -0
  449. package/server/webRouter.ts +712 -0
  450. package/service/adapt.ts +47 -0
  451. package/service/base.service.ts +18 -0
  452. package/service/index.ts +10 -0
  453. package/service/injectInfo.ts +393 -0
  454. package/service/ipcTypes.ts +127 -0
  455. package/service/predefinedAdaptor/cache.adaptor.ts +105 -0
  456. package/service/predefinedAdaptor/compress.adaptor.ts +357 -0
  457. package/service/predefinedAdaptor/database.adaptor.ts +1310 -0
  458. package/service/predefinedAdaptor/index.ts +13 -0
  459. package/service/predefinedAdaptor/logging.adaptor.ts +36 -0
  460. package/service/predefinedAdaptor/queue.adaptor.ts +42 -0
  461. package/service/predefinedAdaptor/role.adaptor.ts +18 -0
  462. package/service/predefinedAdaptor/schedule.adaptor.ts +188 -0
  463. package/service/predefinedAdaptor/solidCache.adaptor.ts +143 -0
  464. package/service/predefinedAdaptor/solidPubsub.adaptor.ts +98 -0
  465. package/service/predefinedAdaptor/solidQueue.adaptor.ts +203 -0
  466. package/service/predefinedAdaptor/solidSqlite.ts +85 -0
  467. package/service/predefinedAdaptor/sqlitePath.ts +20 -0
  468. package/service/predefinedAdaptor/storage.adaptor.ts +121 -0
  469. package/service/predefinedAdaptor/websocket.adaptor.ts +313 -0
  470. package/service/serve.ts +223 -0
  471. package/service/serviceModule.ts +221 -0
  472. package/service/serviceRegistry.ts +26 -0
  473. package/service/types.ts +113 -0
  474. package/signal/base.signal.ts +46 -0
  475. package/signal/endpoint.ts +122 -0
  476. package/signal/endpointInfo.ts +374 -0
  477. package/signal/exception.ts +50 -0
  478. package/signal/guard.ts +18 -0
  479. package/signal/guards.ts +16 -0
  480. package/signal/index.ts +18 -0
  481. package/signal/intercept.ts +39 -0
  482. package/signal/internal.ts +56 -0
  483. package/signal/internalArg.ts +38 -0
  484. package/signal/internalInfo.ts +208 -0
  485. package/signal/middleware.ts +108 -0
  486. package/signal/serializer/fetch.serializer.ts +128 -0
  487. package/signal/serializer/index.ts +1 -0
  488. package/signal/serverSignal.ts +114 -0
  489. package/signal/signalContext.ts +446 -0
  490. package/signal/signalRegistry.ts +82 -0
  491. package/signal/slice.ts +158 -0
  492. package/signal/sliceInfo.ts +254 -0
  493. package/signal/types.ts +131 -0
  494. package/store/action.ts +1067 -0
  495. package/store/baseSt.ts +81 -0
  496. package/store/hooks.ts +2 -0
  497. package/store/index.ts +8 -0
  498. package/store/rootStore.ts +26 -0
  499. package/store/state.ts +226 -0
  500. package/store/stateBuilder.ts +429 -0
  501. package/store/stateInfo.ts +66 -0
  502. package/store/store.ts +194 -0
  503. package/store/storeInstance.ts +382 -0
  504. package/store/storeRegistry.ts +84 -0
  505. package/store/types.ts +69 -0
  506. package/store/withSelector.ts +62 -0
  507. package/test/index.ts +16 -0
  508. package/test/playwright.config.base.ts +48 -0
  509. package/test/playwright.pageAgent.ts +41 -0
  510. package/test/sample.ts +19 -0
  511. package/test/sampleOf.ts +70 -0
  512. package/test/signalTest.preload.ts +10 -0
  513. package/test/signalTestRuntime.ts +126 -0
  514. package/test/testServer.ts +187 -0
  515. package/ui/BottomSheet.tsx +103 -0
  516. package/ui/Button.tsx +70 -0
  517. package/ui/ClientSide.tsx +11 -0
  518. package/ui/Clipboard.tsx +49 -0
  519. package/ui/Constant/Doc.tsx +696 -0
  520. package/ui/Constant/Mermaid.tsx +149 -0
  521. package/ui/Constant/index.ts +6 -0
  522. package/ui/Constant/schemaDoc.ts +324 -0
  523. package/ui/Copy.tsx +27 -0
  524. package/ui/CsrImage.tsx +38 -0
  525. package/ui/Data/CardList.tsx +141 -0
  526. package/ui/Data/Dashboard.tsx +72 -0
  527. package/ui/Data/Insight.tsx +35 -0
  528. package/ui/Data/Item.tsx +285 -0
  529. package/ui/Data/ListContainer.tsx +320 -0
  530. package/ui/Data/Pagination.tsx +54 -0
  531. package/ui/Data/QueryMaker.tsx +21 -0
  532. package/ui/Data/TableList.tsx +161 -0
  533. package/ui/Data/index.ts +11 -0
  534. package/ui/Data/index_.tsx +11 -0
  535. package/ui/DatePicker.tsx +184 -0
  536. package/ui/Dialog/Action.tsx +15 -0
  537. package/ui/Dialog/Close.tsx +22 -0
  538. package/ui/Dialog/Content.tsx +11 -0
  539. package/ui/Dialog/Modal.tsx +137 -0
  540. package/ui/Dialog/Provider.tsx +33 -0
  541. package/ui/Dialog/Title.tsx +15 -0
  542. package/ui/Dialog/Trigger.tsx +22 -0
  543. package/ui/Dialog/context.ts +20 -0
  544. package/ui/Dialog/index.tsx +15 -0
  545. package/ui/DragAction.tsx +129 -0
  546. package/ui/DraggableList.tsx +230 -0
  547. package/ui/Dropdown.tsx +51 -0
  548. package/ui/Empty.tsx +32 -0
  549. package/ui/Field.tsx +1556 -0
  550. package/ui/FontFace.tsx +26 -0
  551. package/ui/Image.tsx +185 -0
  552. package/ui/InfiniteScroll.tsx +67 -0
  553. package/ui/Input.tsx +636 -0
  554. package/ui/KeyboardAvoiding.tsx +62 -0
  555. package/ui/Layout/BottomAction.tsx +15 -0
  556. package/ui/Layout/BottomInset.tsx +42 -0
  557. package/ui/Layout/BottomTab.tsx +71 -0
  558. package/ui/Layout/Header.tsx +38 -0
  559. package/ui/Layout/LeftSider.tsx +34 -0
  560. package/ui/Layout/Navbar.tsx +46 -0
  561. package/ui/Layout/RightSider.tsx +41 -0
  562. package/ui/Layout/Sider.tsx +69 -0
  563. package/ui/Layout/Template.tsx +11 -0
  564. package/ui/Layout/TopLeftAction.tsx +28 -0
  565. package/ui/Layout/Unit.tsx +19 -0
  566. package/ui/Layout/View.tsx +12 -0
  567. package/ui/Layout/Zone.tsx +10 -0
  568. package/ui/Layout/index.ts +27 -0
  569. package/ui/Link/Back.tsx +15 -0
  570. package/ui/Link/Close.tsx +20 -0
  571. package/ui/Link/CsrLink.tsx +41 -0
  572. package/ui/Link/Lang.tsx +16 -0
  573. package/ui/Link/SsrLink.tsx +68 -0
  574. package/ui/Link/index.tsx +32 -0
  575. package/ui/Link/types.ts +47 -0
  576. package/ui/Load/Edit.tsx +19 -0
  577. package/ui/Load/Edit_Client.tsx +120 -0
  578. package/ui/Load/Page.tsx +40 -0
  579. package/ui/Load/PageCSR.tsx +39 -0
  580. package/ui/Load/Pagination.tsx +89 -0
  581. package/ui/Load/Units.tsx +330 -0
  582. package/ui/Load/View.tsx +115 -0
  583. package/ui/Load/index.ts +11 -0
  584. package/ui/Load/index_.tsx +6 -0
  585. package/ui/Loading/Area.tsx +10 -0
  586. package/ui/Loading/Button.tsx +17 -0
  587. package/ui/Loading/Input.tsx +17 -0
  588. package/ui/Loading/ProgressBar.tsx +14 -0
  589. package/ui/Loading/Skeleton.tsx +22 -0
  590. package/ui/Loading/Spin.tsx +22 -0
  591. package/ui/Loading/index.tsx +8 -0
  592. package/ui/Menu.tsx +273 -0
  593. package/ui/Modal.tsx +87 -0
  594. package/ui/Model/AdminPanel.tsx +51 -0
  595. package/ui/Model/Edit.tsx +46 -0
  596. package/ui/Model/EditModal.tsx +301 -0
  597. package/ui/Model/EditWrapper.tsx +48 -0
  598. package/ui/Model/LoadInit.tsx +11 -0
  599. package/ui/Model/New.tsx +46 -0
  600. package/ui/Model/NewWrapper.tsx +20 -0
  601. package/ui/Model/NewWrapper_Client.tsx +57 -0
  602. package/ui/Model/Remove.tsx +75 -0
  603. package/ui/Model/RemoveWrapper.tsx +38 -0
  604. package/ui/Model/SureToRemove.tsx +108 -0
  605. package/ui/Model/View.tsx +65 -0
  606. package/ui/Model/ViewEditModal.tsx +125 -0
  607. package/ui/Model/ViewModal.tsx +71 -0
  608. package/ui/Model/ViewWrapper.tsx +38 -0
  609. package/ui/Model/index.ts +33 -0
  610. package/ui/Model/index_.tsx +16 -0
  611. package/ui/More.tsx +56 -0
  612. package/ui/ObjectId.tsx +29 -0
  613. package/ui/Pagination.tsx +120 -0
  614. package/ui/Popconfirm.tsx +135 -0
  615. package/ui/Portal.tsx +10 -0
  616. package/ui/Radio.tsx +53 -0
  617. package/ui/RecentTime.tsx +123 -0
  618. package/ui/Refresh.tsx +24 -0
  619. package/ui/ScreenNavigator.tsx +129 -0
  620. package/ui/Select.tsx +322 -0
  621. package/ui/Signal/Arg.tsx +352 -0
  622. package/ui/Signal/Doc.tsx +231 -0
  623. package/ui/Signal/Listener.tsx +74 -0
  624. package/ui/Signal/Message.tsx +267 -0
  625. package/ui/Signal/Object.tsx +131 -0
  626. package/ui/Signal/PubSub.tsx +247 -0
  627. package/ui/Signal/Request.tsx +30 -0
  628. package/ui/Signal/Response.tsx +76 -0
  629. package/ui/Signal/RestApi.tsx +390 -0
  630. package/ui/Signal/WebSocket.tsx +47 -0
  631. package/ui/Signal/index.ts +10 -0
  632. package/ui/Signal/makeExample.ts +75 -0
  633. package/ui/System/CSR.tsx +420 -0
  634. package/ui/System/Client.tsx +296 -0
  635. package/ui/System/Common.tsx +83 -0
  636. package/ui/System/DevModeToggle.tsx +21 -0
  637. package/ui/System/Gtag.tsx +69 -0
  638. package/ui/System/Messages.tsx +175 -0
  639. package/ui/System/Reconnect.tsx +156 -0
  640. package/ui/System/Root.tsx +10 -0
  641. package/ui/System/SSR.tsx +163 -0
  642. package/ui/System/SelectLanguage.tsx +47 -0
  643. package/ui/System/ThemeToggle.tsx +98 -0
  644. package/ui/System/index.tsx +23 -0
  645. package/ui/Tab/Menu.tsx +56 -0
  646. package/ui/Tab/Menus.tsx +10 -0
  647. package/ui/Tab/Panel.tsx +25 -0
  648. package/ui/Tab/Provider.tsx +25 -0
  649. package/ui/Tab/context.ts +16 -0
  650. package/ui/Tab/index.tsx +11 -0
  651. package/ui/Table.tsx +131 -0
  652. package/ui/ToggleSelect.tsx +144 -0
  653. package/ui/Unauthorized.tsx +29 -0
  654. package/ui/animated.tsx +8 -0
  655. package/ui/fontCss.ts +86 -0
  656. package/ui/index.ts +44 -0
  657. package/ui/styles.css +617 -0
  658. package/webkit/bootCsr.tsx +275 -0
  659. package/webkit/createRobotPage.ts +15 -0
  660. package/webkit/createSitemapPage.ts +4 -0
  661. package/webkit/index.ts +19 -0
  662. package/webkit/lazy.tsx +37 -0
  663. package/webkit/types.ts +7 -0
  664. package/webkit/useCamera.tsx +99 -0
  665. package/webkit/useCodepush.tsx +99 -0
  666. package/webkit/useContact.tsx +48 -0
  667. package/webkit/useCsrValues.ts +661 -0
  668. package/webkit/useDebounce.ts +24 -0
  669. package/webkit/useFetch.ts +48 -0
  670. package/webkit/useGeoLocation.tsx +24 -0
  671. package/webkit/useHistory.ts +76 -0
  672. package/webkit/useInterval.ts +21 -0
  673. package/webkit/useLocation.ts +69 -0
  674. package/webkit/usePurchase.tsx +156 -0
  675. package/webkit/usePushNoti.tsx +48 -0
  676. package/webkit/useThrottle.ts +22 -0
  677. package/src/index.js +0 -2
  678. package/src/index.js.map +0 -1
  679. package/src/lib/akan2.js +0 -4
  680. package/src/lib/akan2.js.map +0 -1
  681. package/src/run.js +0 -4
  682. package/src/run.js.map +0 -1
package/ui/Field.tsx ADDED
@@ -0,0 +1,1556 @@
1
+ "use client";
2
+ import { type DataList, type Dayjs, dayjs, type EnumInstance, isEnum } from "akanjs/base";
3
+ import { clsx, usePage } from "akanjs/client";
4
+ import { capitalize, formatPhone, isPhoneNumber, lowerlize } from "akanjs/common";
5
+ import type { SliceMeta } from "akanjs/fetch";
6
+ import { st } from "akanjs/store";
7
+ import { memo, type ReactNode, useState } from "react";
8
+ import { AiOutlinePlus } from "react-icons/ai";
9
+ import { BiHelpCircle, BiTrash, BiX } from "react-icons/bi";
10
+ import { MdDragIndicator } from "react-icons/md";
11
+
12
+ import { DraggableList } from "./DraggableList";
13
+ import { Input } from "./Input";
14
+ import { Select } from "./Select";
15
+ import { ToggleSelect as UtilToggleSelect } from "./ToggleSelect";
16
+
17
+ interface LabelProps {
18
+ className?: string;
19
+ label: string;
20
+ desc?: string;
21
+ unit?: string;
22
+ nullable?: boolean;
23
+ mode?: "view" | "edit";
24
+ }
25
+ const Label = ({ className, label, desc, unit, nullable, mode = "edit" }: LabelProps) => {
26
+ return (
27
+ <span className={clsx("flex shrink-0 items-center gap-1", className)}>
28
+ {/* {!nullable && mode === "edit" ? <span>* </span> : null} */}
29
+ {capitalize(label)}
30
+ {unit ? <span className="animate-fadeIn"> ({unit})</span> : null}
31
+ {desc ? (
32
+ <span className="tooltip tooltip-info tooltip-right" data-tip={desc}>
33
+ <BiHelpCircle />
34
+ </span>
35
+ ) : null}
36
+ {nullable ? <span className="text-gray-400 text-sm">{"(optional)"}</span> : null}
37
+ </span>
38
+ );
39
+ };
40
+
41
+ export interface FieldProps {
42
+ /** Additional classes for the outer field wrapper. */
43
+ className?: string;
44
+ /** Additional classes for the children container. */
45
+ containerClassName?: string;
46
+ /** Additional classes for the label row. */
47
+ labelClassName?: string;
48
+ /** Field label shown above the control. */
49
+ label?: string;
50
+ /** Optional help text shown in the label tooltip. */
51
+ desc?: string;
52
+ /** Marks the field as optional in the label. */
53
+ nullable?: boolean;
54
+ /** Field control content. */
55
+ children?: ReactNode;
56
+ }
57
+ export const Field = ({
58
+ className,
59
+ containerClassName,
60
+ labelClassName,
61
+ label,
62
+ desc,
63
+ nullable,
64
+ children,
65
+ }: FieldProps) => {
66
+ return (
67
+ <div className={clsx("w-full", className)}>
68
+ {label ? <Label className={labelClassName} nullable={nullable} label={label} desc={desc} /> : null}
69
+ <div className={clsx("mt-2 flex w-full flex-col gap-4 px-4", containerClassName)}>{children}</div>
70
+ </div>
71
+ );
72
+ };
73
+ Field.Label = Label;
74
+
75
+ interface ListProps<Item> {
76
+ className?: string;
77
+ labelClassName?: string;
78
+ label?: string;
79
+ desc?: string;
80
+ nullable?: boolean;
81
+ value: Item[];
82
+ onChange: (value: Item[]) => void;
83
+ onAdd: () => void;
84
+ renderItem: (item: Item, idx: number) => ReactNode;
85
+ }
86
+ const List = <Item,>({
87
+ className,
88
+ labelClassName,
89
+ label,
90
+ desc,
91
+ value,
92
+ onChange,
93
+ onAdd,
94
+ nullable,
95
+ renderItem,
96
+ }: ListProps<Item>) => {
97
+ const { l } = usePage();
98
+ return (
99
+ <div className={clsx("flex w-full flex-col", className)}>
100
+ {label ? <Label className={labelClassName} nullable={nullable} label={label} desc={desc} /> : null}
101
+ <div className="mb-2 flex w-full flex-col gap-2 rounded-md border border-gray-300 p-2">
102
+ {value.map((item, idx) => (
103
+ <>
104
+ <div key={idx} className="flex h-full w-full items-center justify-between gap-2">
105
+ {renderItem(item, idx)}
106
+ <div className="flex gap-2 border-gray-300 border-l pl-2">
107
+ <button
108
+ className="btn btn-xs btn-error btn-square btn-outline"
109
+ onClick={() => {
110
+ onChange(value.filter((_, i) => i !== idx));
111
+ }}
112
+ >
113
+ <BiTrash />
114
+ </button>
115
+ </div>
116
+ </div>
117
+ <div className="h-[0.5px] w-full bg-gray-300 px-2 last:h-0" />
118
+ </>
119
+ ))}
120
+ <button
121
+ className="btn btn-outline"
122
+ onClick={() => {
123
+ onAdd();
124
+ }}
125
+ >
126
+ +
127
+ </button>
128
+ </div>
129
+ </div>
130
+ );
131
+ };
132
+ Field.List = List;
133
+
134
+ interface TextProps {
135
+ label?: string;
136
+ desc?: string;
137
+ labelClassName?: string;
138
+ className?: string;
139
+ value: string | null;
140
+
141
+ onChange: (value: string) => void;
142
+ inputClassName?: string;
143
+ placeholder?: string;
144
+ nullable?: boolean;
145
+ cache?: boolean;
146
+ disabled?: boolean;
147
+ transform?: (value: string) => string;
148
+ validate?: (text: string) => boolean | string;
149
+ minlength?: number;
150
+ maxlength?: number;
151
+ onPressEnter?: () => void;
152
+ inputStyleType?: "bordered" | "borderless" | "underline";
153
+ }
154
+ const Text = ({
155
+ label,
156
+ desc,
157
+ labelClassName,
158
+ className,
159
+ value,
160
+ onChange,
161
+ placeholder,
162
+ nullable,
163
+ disabled,
164
+ minlength = nullable ? 0 : 2,
165
+ maxlength = 200,
166
+ transform = (v) => v,
167
+ validate,
168
+ onPressEnter,
169
+ cache,
170
+ inputClassName,
171
+ inputStyleType = "bordered",
172
+ }: TextProps) => {
173
+ const { l } = usePage();
174
+ return (
175
+ <div className={clsx("flex flex-col", className)}>
176
+ {label ? <Label className={labelClassName} nullable={nullable} label={label} desc={desc} /> : null}
177
+ <Input
178
+ cacheKey={cache ? `${label}-${desc}-text` : undefined}
179
+ inputStyleType={inputStyleType}
180
+ value={value ?? ""}
181
+ nullable={nullable}
182
+ placeholder={placeholder}
183
+ onChange={(value) => {
184
+ onChange(transform(value));
185
+ }}
186
+ disabled={disabled}
187
+ className={clsx("w-full", "")}
188
+ inputClassName={clsx("w-full focus:border-primary", inputClassName)}
189
+ validate={(text: string) => {
190
+ if (text.length < minlength) return l("base.textTooShortError", { minlength });
191
+ else if (text.length > maxlength) return l("base.textTooLongError", { maxlength });
192
+ else return validate?.(text) ?? true;
193
+ }}
194
+ onPressEnter={onPressEnter}
195
+ />
196
+ </div>
197
+ );
198
+ };
199
+ Field.Text = memo(Text);
200
+
201
+ interface PriceProps {
202
+ label?: string;
203
+ desc?: string;
204
+ labelClassName?: string;
205
+ className?: string;
206
+ value: string | null;
207
+ onChange: (value: string) => void;
208
+ inputClassName?: string;
209
+ placeholder?: string;
210
+ nullable?: boolean;
211
+ disabled?: boolean;
212
+ transform?: (value: string) => string;
213
+ validate?: (text: string) => boolean | string;
214
+ minlength?: number;
215
+ maxlength?: number;
216
+ onPressEnter?: () => void;
217
+ inputStyleType?: "bordered" | "borderless" | "underline";
218
+ }
219
+ const Price = ({
220
+ label,
221
+ desc,
222
+ labelClassName,
223
+ className,
224
+ value,
225
+ onChange,
226
+ placeholder,
227
+ nullable,
228
+ disabled,
229
+ minlength = nullable ? 0 : 2,
230
+ maxlength = 80,
231
+ transform = (v) => v,
232
+ validate,
233
+ onPressEnter,
234
+ inputClassName,
235
+ inputStyleType = "bordered",
236
+ }: PriceProps) => {
237
+ const { l } = usePage();
238
+ return (
239
+ <div className={clsx("flex flex-col", className)}>
240
+ {label ? <Label className={labelClassName} nullable={nullable} label={label} desc={desc} /> : null}
241
+ <Input
242
+ inputStyleType={inputStyleType}
243
+ value={value ?? ""}
244
+ nullable={nullable}
245
+ placeholder={placeholder ?? `~ ${l("base.priceUnit")}`}
246
+ onChange={(value) => {
247
+ const withoutComma = value.replace(/,/g, "").replace(/ /g, "");
248
+ onChange(transform(withoutComma));
249
+ }}
250
+ disabled={disabled}
251
+ className={clsx("w-full", "")}
252
+ inputClassName={clsx("w-full focus:border-primary", inputClassName)}
253
+ validate={(text: string) => {
254
+ if (text.length < minlength) return l("base.textTooShortError", { minlength });
255
+ else if (text.length > maxlength) return l("base.textTooLongError", { maxlength });
256
+ else return validate?.(text) ?? true;
257
+ }}
258
+ onPressEnter={onPressEnter}
259
+ />
260
+ </div>
261
+ );
262
+ };
263
+ Field.Price = memo(Price);
264
+
265
+ interface TextAreaProps {
266
+ label?: string;
267
+ desc?: string;
268
+ labelClassName?: string;
269
+ className?: string;
270
+ value: string | null;
271
+ onChange: (value: string) => void;
272
+ inputClassName?: string;
273
+ placeholder?: string;
274
+ nullable?: boolean;
275
+ disabled?: boolean;
276
+ transform?: (value: string) => string;
277
+ validate?: (text: string) => boolean | string;
278
+ rows?: number;
279
+ minlength?: number;
280
+ maxlength?: number;
281
+ cache?: boolean;
282
+ onPressEnter?: () => void;
283
+ }
284
+ const TextArea = ({
285
+ label,
286
+ desc,
287
+ labelClassName,
288
+ className,
289
+ value,
290
+ onChange,
291
+ placeholder,
292
+ nullable,
293
+ disabled,
294
+ rows = 3,
295
+ minlength = nullable ? 0 : 2,
296
+ maxlength = 1000,
297
+ transform = (v) => v,
298
+ validate,
299
+ onPressEnter,
300
+ cache,
301
+ inputClassName,
302
+ }: TextAreaProps) => {
303
+ const { l } = usePage();
304
+ return (
305
+ <div className={clsx("flex flex-col", className)}>
306
+ {label ? <Label className={labelClassName} nullable={nullable} label={label} desc={desc} /> : null}
307
+ <Input.TextArea
308
+ value={value ?? ""}
309
+ cacheKey={cache ? `${label}-${desc}-textArea` : undefined}
310
+ nullable={nullable}
311
+ placeholder={placeholder}
312
+ onChange={(value) => {
313
+ onChange(transform(value));
314
+ }}
315
+ disabled={disabled}
316
+ rows={rows}
317
+ className={clsx("h-full w-full")}
318
+ inputClassName={clsx("w-full focus:border-primary", inputClassName)}
319
+ validate={(text: string) => {
320
+ if (text.length < minlength) return l("base.textTooShortError", { minlength });
321
+ else if (text.length > maxlength) return l("base.textTooLongError", { maxlength });
322
+ else return validate?.(text) ?? true;
323
+ }}
324
+ onPressEnter={onPressEnter}
325
+ />
326
+ </div>
327
+ );
328
+ };
329
+ Field.TextArea = memo(TextArea);
330
+
331
+ interface SwitchProps {
332
+ label?: string;
333
+ desc?: string;
334
+ labelClassName?: string;
335
+ className?: string;
336
+ value: boolean;
337
+ onChange: (value: boolean) => void;
338
+ inputClassName?: string;
339
+ onDesc?: string;
340
+ offDesc?: string;
341
+ disabled?: boolean;
342
+ }
343
+ const Switch = ({
344
+ label,
345
+ desc,
346
+ labelClassName,
347
+ className,
348
+ value,
349
+ onChange,
350
+ disabled,
351
+ inputClassName,
352
+ onDesc,
353
+ offDesc,
354
+ }: SwitchProps) => {
355
+ return (
356
+ <div className={clsx("flex flex-col", className)}>
357
+ {label ? <Label className={labelClassName} nullable label={label} desc={desc} /> : null}
358
+ <div className="flex items-center gap-2">
359
+ <input
360
+ type="checkbox"
361
+ disabled={disabled}
362
+ className={clsx("toggle toggle-accent", inputClassName)}
363
+ checked={value}
364
+ onChange={(e) => {
365
+ onChange(e.target.checked);
366
+ }}
367
+ />
368
+ {(onDesc ?? offDesc) ? <div className="text-info text-sm">{value ? onDesc : offDesc}</div> : null}
369
+ </div>
370
+ </div>
371
+ );
372
+ };
373
+ Field.Switch = Switch;
374
+
375
+ interface ToggleSelectProps<I> {
376
+ className?: string;
377
+ labelClassName?: string;
378
+ label?: string;
379
+ desc?: string;
380
+ model?: string;
381
+ field?: string;
382
+ items: { label: string; value: I; disabled?: boolean }[] | readonly I[] | I[] | EnumInstance<string, I>;
383
+ value: I;
384
+ nullable?: boolean;
385
+ disabled?: boolean;
386
+ validate?: (value: I) => boolean | string;
387
+ onChange: (value: I) => void;
388
+ btnClassName?: string;
389
+ }
390
+ const ToggleSelect = <I extends string | number | boolean | null>({
391
+ className,
392
+ labelClassName,
393
+ label,
394
+ desc,
395
+ items,
396
+ value,
397
+ validate,
398
+ onChange,
399
+ nullable,
400
+ disabled,
401
+ btnClassName,
402
+ }: ToggleSelectProps<I>) => {
403
+ const { l } = usePage();
404
+ const isEnumValue = isEnum(items as EnumInstance<string, I>);
405
+ return (
406
+ <div className={clsx("flex flex-col", className)}>
407
+ {label ? <Label className={labelClassName} nullable={nullable} label={label} desc={desc} /> : null}
408
+ <UtilToggleSelect
409
+ className="mt-2"
410
+ nullable={!!nullable}
411
+ btnClassName={btnClassName}
412
+ items={
413
+ isEnumValue
414
+ ? ((items as EnumInstance<string, I>).values.map((item) => ({
415
+ label: l._(`${(items as unknown as EnumInstance).refName}.${item}`),
416
+ value: item,
417
+ })) as { label: string; value: I; disabled?: boolean }[])
418
+ : (items as { label: string; value: I; disabled?: boolean }[])
419
+ }
420
+ value={value}
421
+ onChange={(value: I, idx) => {
422
+ onChange(value);
423
+ }}
424
+ disabled={disabled}
425
+ validate={(value: I) => {
426
+ return validate?.(value) ?? true;
427
+ }}
428
+ />
429
+ </div>
430
+ );
431
+ };
432
+ Field.ToggleSelect = ToggleSelect;
433
+
434
+ interface MultiToggleSelectProps<I extends string | number | boolean> {
435
+ className?: string;
436
+ labelClassName?: string;
437
+ label?: string;
438
+ desc?: string;
439
+ items: EnumInstance<string, I> | { label: string; value: I; disabled?: boolean }[] | readonly I[] | I[];
440
+ value: I[];
441
+ disabled?: boolean;
442
+ minlength?: number;
443
+ maxlength?: number;
444
+ validate?: (value: I[]) => boolean | string;
445
+ onChange: (value: I[]) => void;
446
+ }
447
+ const MultiToggleSelect = <I extends string | number | boolean>({
448
+ className,
449
+ labelClassName,
450
+ label,
451
+ desc,
452
+ items,
453
+ value,
454
+ minlength,
455
+ maxlength,
456
+ validate,
457
+ onChange,
458
+ disabled,
459
+ }: MultiToggleSelectProps<I>) => {
460
+ const { l } = usePage();
461
+ const isEnumValue = isEnum(items as EnumInstance<string, I>);
462
+ return (
463
+ <div className={clsx("flex flex-col", className)}>
464
+ {label ? <Label className={labelClassName} nullable={!!minlength} label={label} desc={desc} /> : null}
465
+ <UtilToggleSelect.Multi
466
+ nullable={!minlength}
467
+ items={
468
+ isEnumValue
469
+ ? ((items as EnumInstance<string, I>).values.map((item) => ({
470
+ label: l._(`${(items as unknown as EnumInstance).refName}.${item}`),
471
+ value: item,
472
+ })) as { label: string; value: string; disabled?: boolean }[])
473
+ : (items as { label: string; value: string; disabled?: boolean }[])
474
+ }
475
+ value={value as string[]}
476
+ onChange={(values) => {
477
+ onChange(values as I[]);
478
+ }}
479
+ disabled={disabled}
480
+ validate={(value) => {
481
+ if (minlength && value.length < minlength) return l("base.selectTooShortError", { minlength });
482
+ else if (maxlength && value.length > maxlength) return l("base.selectTooLongError", { maxlength });
483
+ else return validate?.(value as I[]) ?? true;
484
+ }}
485
+ />
486
+ </div>
487
+ );
488
+ };
489
+ Field.MultiToggleSelect = MultiToggleSelect;
490
+
491
+ interface TextListProps {
492
+ label?: string;
493
+ desc?: string;
494
+ labelClassName?: string;
495
+ className?: string;
496
+ value: string[];
497
+ onChange: (value: string[]) => void;
498
+ inputClassName?: string;
499
+ placeholder?: string;
500
+ disabled?: boolean;
501
+ cache?: boolean;
502
+ transform?: (value: string) => string;
503
+ validate?: (text: string) => boolean | string;
504
+ minlength?: number;
505
+ maxlength?: number;
506
+ minTextlength?: number;
507
+ maxTextlength?: number;
508
+ }
509
+ const TextList = ({
510
+ label,
511
+ desc,
512
+ labelClassName,
513
+ className,
514
+ value,
515
+ onChange,
516
+ placeholder,
517
+ disabled,
518
+ transform = (v) => v,
519
+ minlength = 0,
520
+ maxlength = 50,
521
+ minTextlength = 2,
522
+ maxTextlength = 200,
523
+ cache,
524
+ validate,
525
+ inputClassName,
526
+ }: TextListProps) => {
527
+ const { l } = usePage();
528
+ return (
529
+ <div className={clsx("flex flex-col", className)}>
530
+ {label ? <Label className={labelClassName} nullable={!minlength} label={label} desc={desc} /> : null}
531
+ <div className="mb-5 h-full gap-2 rounded-md border border-gray-300 p-2">
532
+ <DraggableList
533
+ className="h-full gap-2"
534
+ onChange={onChange}
535
+ onRemove={(_, idx) => {
536
+ onChange(value.filter((_, i) => i !== idx));
537
+ }}
538
+ >
539
+ {value.map((text, idx) => (
540
+ <DraggableList.Item key={idx} value={text}>
541
+ <div className="flex w-full items-center">
542
+ <DraggableList.Cursor>
543
+ <MdDragIndicator className="text-xl" />
544
+ </DraggableList.Cursor>
545
+ <div className="flex w-full items-center justify-center gap-5">
546
+ <Input
547
+ value={text}
548
+ cacheKey={cache ? `${label}-${desc}-textList-[${idx}]` : undefined}
549
+ onChange={(text) => {
550
+ const newValue = [...value];
551
+ newValue[idx] = transform(text);
552
+ onChange(newValue);
553
+ }}
554
+ validate={(text: string) => {
555
+ if (text.length < minlength) return l("base.textTooShortError", { minlength: minTextlength });
556
+ else if (text.length > maxlength) return l("base.textTooLongError", { maxlength: maxTextlength });
557
+ else return validate?.(text) ?? true;
558
+ }}
559
+ className={clsx("w-full", inputClassName)}
560
+ inputClassName="w-full input-sm"
561
+ placeholder={placeholder}
562
+ disabled={disabled}
563
+ />
564
+ <button
565
+ className="btn btn-xs btn-error btn-square btn-outline"
566
+ onClick={() => {
567
+ onChange(value.filter((_, i) => i !== idx));
568
+ }}
569
+ >
570
+ <BiTrash />
571
+ </button>
572
+ </div>
573
+ </div>
574
+ </DraggableList.Item>
575
+ ))}
576
+ </DraggableList>
577
+ <div className="my-5 h-[0.5px] bg-base-content/20" />
578
+ {value.length <= maxTextlength ? (
579
+ <button
580
+ className="btn btn-outline w-full"
581
+ onClick={() => {
582
+ onChange([...value, ""]);
583
+ }}
584
+ >
585
+ + New
586
+ </button>
587
+ ) : null}
588
+ </div>
589
+ </div>
590
+ );
591
+ };
592
+ Field.TextList = TextList;
593
+
594
+ interface TagsProps {
595
+ label?: string;
596
+ desc?: string;
597
+ labelClassName?: string;
598
+ className?: string;
599
+ value: string[];
600
+ onChange: (value: string[]) => void;
601
+ inputClassName?: string;
602
+ placeholder?: string;
603
+ disabled?: boolean;
604
+ transform?: (value: string) => string;
605
+ validate?: (text: string) => boolean | string;
606
+ minlength?: number;
607
+ maxlength?: number;
608
+ minTextlength?: number;
609
+ maxTextlength?: number;
610
+ secret?: boolean;
611
+ }
612
+ const Tags = ({
613
+ label,
614
+ desc,
615
+ labelClassName,
616
+ className,
617
+ value,
618
+ onChange,
619
+ placeholder,
620
+ disabled,
621
+ transform = (v) => v,
622
+ minlength = 0,
623
+ maxlength = 50,
624
+ minTextlength = 2,
625
+ maxTextlength = 10,
626
+ validate,
627
+ inputClassName,
628
+ }: TagsProps) => {
629
+ const { l } = usePage();
630
+ const [inputVisible, setInputVisible] = useState(false);
631
+ const [tag, setTag] = useState("");
632
+ const addTag = () => {
633
+ if (!tag.length) return;
634
+ onChange([...value, tag]);
635
+ setInputVisible(false);
636
+ setTag("");
637
+ };
638
+
639
+ return (
640
+ <div className={clsx("flex flex-col", className)}>
641
+ {label ? <Label className={labelClassName} nullable={!minlength} label={label} desc={desc} /> : null}
642
+ <div className="flex w-full flex-wrap items-center gap-1 rounded-md border border-base-content/20 p-2">
643
+ {value.map((val, idx) => (
644
+ <span className="badge badge-outline items-center rounded-full text-xs" key={idx}>
645
+ <div className="text-xs italic">#</div>
646
+ {val}
647
+ <BiX
648
+ className="ml-1 cursor-pointer opacity-50 duration-200 hover:opacity-100"
649
+ onClick={() => {
650
+ if (!disabled) onChange(value.filter((v, i) => i !== idx));
651
+ }}
652
+ />
653
+ </span>
654
+ ))}
655
+ {inputVisible ? (
656
+ <Input
657
+ autoFocus
658
+ icon={<div className="text-xs italic">#</div>}
659
+ className="h-6 w-24 items-center justify-start rounded-full border px-4"
660
+ inputClassName="focus:border-0 border-0 bg-transparent text-xs h-full w-full"
661
+ placeholder={placeholder}
662
+ value={tag}
663
+ onChange={(value) => {
664
+ if (value.length > maxTextlength) return;
665
+ setTag(transform(value));
666
+ }}
667
+ onBlur={addTag}
668
+ onPressEnter={addTag}
669
+ onPressEscape={() => {
670
+ setInputVisible(false);
671
+ setTag("");
672
+ }}
673
+ validate={(text: string) => {
674
+ if (text.length < minTextlength) return l("base.textTooShortError", { minlength: minTextlength });
675
+ else if (text.length > maxTextlength) return l("base.textTooLongError", { maxlength: maxTextlength });
676
+ else return validate?.(text) ?? true;
677
+ }}
678
+ />
679
+ ) : !disabled ? (
680
+ <div
681
+
682
+ className="flex items-center gap-2 rounded-full bg-success px-2 py-1 text-success-content text-xs duration-200 hover:cursor-pointer hover:opacity-80"
683
+ onClick={() => {
684
+ setInputVisible(true);
685
+ }}
686
+ >
687
+ <AiOutlinePlus />
688
+ New Tag
689
+ </div>
690
+ ) : null}
691
+ </div>
692
+ </div>
693
+ );
694
+ };
695
+ Field.Tags = Tags;
696
+
697
+ interface DateProps<Nullable extends boolean> {
698
+ label?: string;
699
+ desc?: string;
700
+ labelClassName?: string;
701
+ nullable?: boolean;
702
+ className?: string;
703
+ min?: Dayjs;
704
+ max?: Dayjs;
705
+ value: Nullable extends true ? Dayjs | null : Dayjs;
706
+ showTime?: boolean;
707
+ onChange: (value: Dayjs) => void;
708
+ dateClassName?: string;
709
+ }
710
+ const Date = <Nullable extends boolean>({
711
+ className,
712
+ labelClassName,
713
+ nullable,
714
+ label,
715
+ desc,
716
+ value,
717
+ min,
718
+ max,
719
+ onChange,
720
+ showTime,
721
+ dateClassName,
722
+ }: DateProps<Nullable>) => {
723
+ return (
724
+ <div className={clsx("flex flex-col", className)}>
725
+ {label ? <Label className={labelClassName} nullable={nullable} label={label} desc={desc} /> : null}
726
+ {/* //! daysi UI datetime-local 컴포넌트에 max 값 넣으면 오른쪽 끝 짤리는 버그 있음.*/}
727
+ <input
728
+ type={showTime ? "datetime-local" : "date"}
729
+ className={clsx(
730
+ "input validator text-xs outline-none duration-200 focus-within:outline-none focus:outline-none",
731
+ dateClassName,
732
+ )}
733
+ min={min ? (showTime ? dayjs(min).format("YYYY-MM-DDTHH:mm") : dayjs(min).format("YYYY-MM-DD")) : undefined}
734
+ max={max ? (showTime ? dayjs(max).format("YYYY-MM-DDTHH:mm") : dayjs(max).format("YYYY-MM-DD")) : undefined}
735
+ value={value ? (showTime ? dayjs(value).format("YYYY-MM-DDTHH:mm") : dayjs(value).format("YYYY-MM-DD")) : ""}
736
+ onChange={(e) => {
737
+ onChange(dayjs(e.target.value));
738
+ }}
739
+ />
740
+ </div>
741
+ );
742
+ };
743
+ Field.Date = Date;
744
+
745
+ interface DateRangeProps<Nullable extends boolean> {
746
+ label?: string;
747
+ desc?: string;
748
+ labelClassName?: string;
749
+ nullable?: Nullable;
750
+ className?: string;
751
+ min?: Dayjs;
752
+ max?: Dayjs;
753
+ from: Nullable extends true ? Dayjs | null : Dayjs;
754
+ to: Nullable extends true ? Dayjs | null : Dayjs;
755
+ showTime?: boolean;
756
+ onChangeFrom: (value: Dayjs) => void;
757
+ onChangeTo: (value: Dayjs) => void;
758
+ onChange?: (from: Dayjs, to: Dayjs) => void;
759
+ }
760
+ const DateRange = <Nullable extends boolean>({
761
+ className,
762
+ labelClassName,
763
+ nullable,
764
+ label,
765
+ desc,
766
+ from,
767
+ to,
768
+ min,
769
+ max,
770
+ onChangeFrom,
771
+ onChangeTo,
772
+ onChange,
773
+ showTime,
774
+ }: DateRangeProps<Nullable>) => {
775
+ return (
776
+ <div className={clsx("flex flex-col", className)}>
777
+ {label ? <Label className={labelClassName} nullable={nullable} label={label} desc={desc} /> : null}
778
+
779
+ <div className="relative flex w-full flex-col items-start gap-2 pt-2 text-center md:flex-row md:items-center">
780
+ <div className="relative flex w-full flex-col items-start justify-start">
781
+ <div className="absolute -top-2 left-2 z-10 bg-base-100 px-2 font-light text-xs">From</div>
782
+ <Date
783
+ className="w-full"
784
+ dateClassName="w-full"
785
+ showTime={showTime}
786
+ value={from}
787
+ max={max}
788
+ min={min}
789
+ onChange={(value: Dayjs) => {
790
+ onChangeFrom(value);
791
+ }}
792
+ />
793
+ </div>
794
+ <div className="relative flex w-full flex-col items-start gap-2 text-center md:flex-row md:items-center">
795
+ <div className="absolute -top-2 left-2 z-10 bg-base-100 px-2 font-light text-xs">To</div>
796
+ <Date
797
+ className="w-full"
798
+ dateClassName="w-full"
799
+ showTime={showTime}
800
+ value={to}
801
+ max={max}
802
+ min={min}
803
+ onChange={(value: Dayjs) => {
804
+ onChangeTo(value);
805
+ }}
806
+ />
807
+ </div>
808
+ </div>
809
+ </div>
810
+ );
811
+ };
812
+ Field.DateRange = DateRange;
813
+
814
+ interface NumberProps {
815
+ label?: string;
816
+ desc?: string;
817
+ className?: string;
818
+ value: number | null;
819
+ placeholder?: string;
820
+ nullable?: boolean;
821
+ disabled?: boolean;
822
+ cache?: boolean;
823
+ min?: number;
824
+ max?: number;
825
+ unit?: string;
826
+ labelClassName?: string;
827
+ inputClassName?: string;
828
+ onChange: (value: number) => void;
829
+ transform?: (value: number) => number;
830
+ validate?: (text: number) => boolean | string;
831
+ onPressEnter?: () => void;
832
+ formatter?: (value: string) => string;
833
+ parser?: (value: string) => string;
834
+ }
835
+ const Number = ({
836
+ label,
837
+ desc,
838
+ labelClassName,
839
+ className,
840
+ value,
841
+ onChange,
842
+ placeholder,
843
+ nullable,
844
+ disabled,
845
+ min,
846
+ max,
847
+ cache,
848
+ transform = (v) => v,
849
+ validate,
850
+ onPressEnter,
851
+ inputClassName,
852
+ unit,
853
+ formatter,
854
+ parser,
855
+ }: NumberProps) => {
856
+ const { l } = usePage();
857
+ return (
858
+ <div className={clsx("flex flex-col", className)}>
859
+ {label ? <Label className={labelClassName} nullable={nullable} label={label} desc={desc} unit={unit} /> : null}
860
+ <Input.Number
861
+ min={min}
862
+ max={max}
863
+ cacheKey={cache ? `${label}-${desc}-number` : undefined}
864
+ value={value}
865
+ nullable={nullable}
866
+ formatter={formatter}
867
+ parser={parser}
868
+ placeholder={placeholder}
869
+ onChange={(value) => {
870
+ onChange(transform(value ?? 0));
871
+ }}
872
+ disabled={disabled}
873
+ className={clsx("w-full", "")}
874
+ inputClassName={clsx("w-full", inputClassName)}
875
+ validate={(value) => {
876
+
877
+ if (min !== undefined && (value as number) < min) return l("base.numberTooSmallError", { min });
878
+ else if (max !== undefined && (value as number) > max) return l("base.numberTooBigError", { max });
879
+ else return validate?.(value as number) ?? true;
880
+ }}
881
+ onPressEnter={onPressEnter}
882
+ />
883
+ </div>
884
+ );
885
+ };
886
+ Field.Number = Number;
887
+
888
+ interface DoubleNumberProps {
889
+ label?: string;
890
+ desc?: string;
891
+ labelClassName?: string;
892
+ className?: string;
893
+ value: [number, number] | null;
894
+ inputClassName?: string;
895
+ placeholder?: string;
896
+ nullable?: boolean;
897
+ disabled?: boolean;
898
+ min?: [number, number] | null;
899
+ max?: [number, number] | null;
900
+ separator?: ReactNode | string;
901
+ cache?: boolean;
902
+ onChange: (value: [number, number]) => void;
903
+ transform?: (value: number) => number;
904
+ validate?: (text: number) => boolean | string;
905
+ onPressEnter?: () => void;
906
+ }
907
+ const DoubleNumber = ({
908
+ label,
909
+ desc,
910
+ labelClassName,
911
+ className,
912
+ value,
913
+ placeholder,
914
+ nullable,
915
+ disabled,
916
+ min,
917
+ max,
918
+ inputClassName,
919
+ cache,
920
+ separator,
921
+ onChange,
922
+ transform = (v) => v,
923
+ validate,
924
+ onPressEnter,
925
+ }: DoubleNumberProps) => {
926
+ const { l } = usePage();
927
+ return (
928
+ <div className={clsx("flex flex-col", className)}>
929
+ {label ? <Label className={labelClassName} nullable={nullable} label={label} desc={desc} /> : null}
930
+ <div className="flex items-center gap-2">
931
+ <Input.Number
932
+ value={value ? value[0] : 0}
933
+ nullable={nullable}
934
+ cacheKey={cache ? `${label}-${desc}-number-[0]` : undefined}
935
+ placeholder={placeholder}
936
+ onChange={(num) => {
937
+ if (num === null) return;
938
+ onChange([transform(num), value ? value[1] : 0]);
939
+ }}
940
+ disabled={disabled}
941
+ className={clsx("w-full", "")}
942
+ inputClassName={clsx("w-full focus:border-primary", inputClassName)}
943
+ validate={(value) => {
944
+ if (min && (value as number) < min[0]) return l("base.numberTooSmallError", { min: min[0] });
945
+ else if (max && (value as number) > max[0]) return l("base.numberTooBigError", { max: max[0] });
946
+ else return validate?.(value as number) ?? true;
947
+ }}
948
+ onPressEnter={onPressEnter}
949
+ />
950
+ {separator}
951
+ <Input.Number
952
+ cacheKey={cache ? `${label}-${desc}-number-[1]` : undefined}
953
+ value={value ? value[1] : 0}
954
+ nullable={nullable}
955
+ placeholder={placeholder}
956
+ onChange={(num) => {
957
+ onChange([value ? value[0] : 0, transform(num ?? 0)]);
958
+ }}
959
+ disabled={disabled}
960
+ className={clsx("w-full", "")}
961
+ inputClassName={clsx("w-full focus:border-primary", inputClassName)}
962
+ validate={(value) => {
963
+ if (min && (value as number) < min[1]) return l("base.numberTooSmallError", { min: min[1] });
964
+ else if (max && (value as number) > max[1]) return l("base.numberTooBigError", { max: max[1] });
965
+ else return validate?.(value as number) ?? true;
966
+ }}
967
+ onPressEnter={onPressEnter}
968
+ />
969
+ </div>
970
+ </div>
971
+ );
972
+ };
973
+ Field.DoubleNumber = DoubleNumber;
974
+
975
+ interface EmailProps {
976
+ label?: string;
977
+ desc?: string;
978
+ labelClassName?: string;
979
+ className?: string;
980
+ value: string | null;
981
+ cache?: boolean;
982
+ onChange: (value: string) => void;
983
+ inputClassName?: string;
984
+ placeholder?: string;
985
+ nullable?: boolean;
986
+ disabled?: boolean;
987
+ transform?: (value: string) => string;
988
+ validate?: (text: string) => boolean | string;
989
+ minlength?: number;
990
+ maxlength?: number;
991
+ onPressEnter?: () => void;
992
+ inputStyleType?: "bordered" | "borderless" | "underline";
993
+ }
994
+ const Email = ({
995
+ label,
996
+ desc,
997
+ labelClassName,
998
+ className,
999
+ value,
1000
+ onChange,
1001
+ cache,
1002
+ placeholder = "example@email.com",
1003
+ nullable,
1004
+ disabled,
1005
+ minlength = nullable ? 0 : 2,
1006
+ maxlength = 80,
1007
+ transform = (v) => v,
1008
+ validate,
1009
+ onPressEnter,
1010
+ inputClassName,
1011
+ inputStyleType,
1012
+ }: EmailProps) => {
1013
+ const { l } = usePage();
1014
+ return (
1015
+ <div className={clsx("flex flex-col", className)}>
1016
+ {label ? <Label className={labelClassName} nullable={nullable} label={label} desc={desc} /> : null}
1017
+ <Input.Email
1018
+ value={value ?? ""}
1019
+ cacheKey={cache ? `${label}-${desc}-email` : undefined}
1020
+ nullable={nullable}
1021
+ placeholder={placeholder}
1022
+ onChange={(value) => {
1023
+ onChange(transform(value));
1024
+ }}
1025
+ disabled={disabled}
1026
+ className={clsx("w-full", "")}
1027
+ inputClassName={clsx("w-full focus:border-primary", inputClassName)}
1028
+ inputStyleType={inputStyleType}
1029
+ validate={(text: string) => {
1030
+ if (text.length < minlength) return l("base.textTooShortError", { minlength });
1031
+ else if (text.length > maxlength) return l("base.textTooLongError", { maxlength });
1032
+ else return validate?.(text) ?? true;
1033
+ }}
1034
+ onPressEnter={onPressEnter}
1035
+ />
1036
+ </div>
1037
+ );
1038
+ };
1039
+ Field.Email = Email;
1040
+
1041
+ interface PhoneProps {
1042
+ label?: string;
1043
+ desc?: string;
1044
+ labelClassName?: string;
1045
+ className?: string;
1046
+ value: string | null;
1047
+ onChange: (value: string) => void;
1048
+ inputClassName?: string;
1049
+ placeholder?: string;
1050
+ nullable?: boolean;
1051
+ disabled?: boolean;
1052
+ cache?: boolean;
1053
+ transform?: (value: string) => string;
1054
+ validate?: (text: string) => boolean | string;
1055
+ minlength?: number;
1056
+ maxlength?: number;
1057
+ onPressEnter?: () => void;
1058
+ }
1059
+ const Phone = ({
1060
+ label,
1061
+ desc,
1062
+ labelClassName,
1063
+ className,
1064
+ value,
1065
+ onChange,
1066
+ placeholder,
1067
+ nullable,
1068
+ disabled,
1069
+ maxlength = 13,
1070
+ cache,
1071
+ transform = (v) => formatPhone(v),
1072
+ validate,
1073
+ onPressEnter,
1074
+ inputClassName,
1075
+ }: PhoneProps) => {
1076
+ const { l } = usePage();
1077
+
1078
+ return (
1079
+ <div className={clsx("flex flex-col", className)}>
1080
+ {label ? <Label className={labelClassName} nullable={nullable} label={label} desc={desc} /> : null}
1081
+ <Input
1082
+ value={value ?? ""}
1083
+ cacheKey={cache ? `${label}-${desc}-phone` : undefined}
1084
+ nullable={nullable}
1085
+ placeholder={placeholder}
1086
+ onChange={(value) => {
1087
+ onChange(transform(value));
1088
+ }}
1089
+ disabled={disabled}
1090
+ maxLength={maxlength}
1091
+ className={clsx("w-full", "")}
1092
+ inputClassName={clsx("w-full focus:border-primary", inputClassName)}
1093
+ validate={(text: string) => {
1094
+ if (!isPhoneNumber(text)) return l("base.phoneInvalidError");
1095
+ else return validate?.(text) ?? true;
1096
+ }}
1097
+ onPressEnter={onPressEnter}
1098
+ />
1099
+ </div>
1100
+ );
1101
+ };
1102
+ Field.Phone = Phone;
1103
+
1104
+ interface PasswordProps {
1105
+ label?: string;
1106
+ desc?: string;
1107
+ labelClassName?: string;
1108
+ className?: string;
1109
+ value: string | null;
1110
+ onChange: (value: string) => void;
1111
+ confirmValue?: string | null;
1112
+ onChangeConfirm?: (value: string) => void;
1113
+ inputClassName?: string;
1114
+ placeholder?: string;
1115
+ nullable?: boolean;
1116
+ disabled?: boolean;
1117
+ cache?: boolean;
1118
+ transform?: (value: string) => string;
1119
+ validate?: (text: string) => boolean | string;
1120
+ minlength?: number;
1121
+ maxlength?: number;
1122
+ onPressEnter?: () => void;
1123
+ showConfirm?: boolean;
1124
+ }
1125
+ const Password = ({
1126
+ label,
1127
+ desc,
1128
+ labelClassName,
1129
+ className,
1130
+ value,
1131
+ onChange,
1132
+ cache,
1133
+ confirmValue,
1134
+ onChangeConfirm,
1135
+ placeholder,
1136
+ nullable,
1137
+ disabled,
1138
+ minlength = nullable ? 0 : 8,
1139
+ maxlength = 20,
1140
+ transform = (v) => v,
1141
+ validate,
1142
+ onPressEnter,
1143
+ inputClassName,
1144
+ showConfirm,
1145
+ }: PasswordProps) => {
1146
+ const { l } = usePage();
1147
+ return (
1148
+ <div className={clsx("flex flex-col", className)}>
1149
+ {label ? <Label className={labelClassName} nullable={nullable} label={label} desc={desc} /> : null}
1150
+ <div className="flex flex-col gap-2">
1151
+ <Input.Password
1152
+ cacheKey={cache ? `${label}-${desc}-password` : undefined}
1153
+ value={value ?? ""}
1154
+ nullable={nullable}
1155
+ placeholder={placeholder ?? l("base.password")}
1156
+ onChange={(value) => {
1157
+ onChange(transform(value));
1158
+ }}
1159
+ disabled={disabled}
1160
+ className={clsx("w-full", "")}
1161
+ inputClassName={clsx("w-full focus:border-primary", inputClassName)}
1162
+ validate={(text: string) => {
1163
+ if (text.length < minlength) return l("base.textTooShortError", { minlength });
1164
+ else if (text.length > maxlength) return l("base.textTooLongError", { maxlength });
1165
+ else return validate?.(text) ?? true;
1166
+ }}
1167
+ onPressEnter={onPressEnter}
1168
+ />
1169
+ {showConfirm ? (
1170
+ <Input.Password
1171
+ value={confirmValue ?? ""}
1172
+ nullable={nullable}
1173
+ placeholder={l("base.passwordConfirm")}
1174
+ onChange={(value) => onChangeConfirm?.(transform(value))}
1175
+ disabled={disabled}
1176
+ className={clsx("w-full", "")}
1177
+ inputClassName={clsx("w-full focus:border-primary", inputClassName)}
1178
+ validate={(text: string) => {
1179
+ if (value && text !== value) return l("base.passwordNotMatchError");
1180
+ else return true;
1181
+ }}
1182
+ onPressEnter={onPressEnter}
1183
+ />
1184
+ ) : null}
1185
+ </div>
1186
+ </div>
1187
+ );
1188
+ };
1189
+ Field.Password = Password;
1190
+
1191
+ interface ParentProps<T extends string, State, Input, Full, Light> {
1192
+ label?: string;
1193
+ desc?: string;
1194
+ labelClassName?: string;
1195
+ selectClassName?: string;
1196
+ className?: string;
1197
+ disabled?: boolean;
1198
+ nullable?: boolean;
1199
+ initArgs?: any[];
1200
+ value: Light | null;
1201
+ slice: SliceMeta;
1202
+ onChange: (value: Light | null) => void;
1203
+ onSearch?: (text: string) => void;
1204
+ sortOption?: (a: Light, b: Light) => number;
1205
+ renderOption: (model: Light) => ReactNode;
1206
+ renderSelected?: (value: Light) => ReactNode;
1207
+ }
1208
+ const Parent = <T extends string, State, Input, Full extends { id: string }, Light extends { id: string }>({
1209
+ label,
1210
+ desc,
1211
+ labelClassName,
1212
+ selectClassName,
1213
+ className,
1214
+ nullable,
1215
+ disabled,
1216
+ initArgs,
1217
+ slice,
1218
+ value,
1219
+ onChange,
1220
+ onSearch,
1221
+ sortOption,
1222
+ renderOption,
1223
+ renderSelected = renderOption,
1224
+ }: ParentProps<T, State, Input, Full, Light>) => {
1225
+ const { refName, sliceName } = slice;
1226
+ const [modelName, ModelName] = [lowerlize(refName), capitalize(refName)];
1227
+ const storeUse = st.use as { [key: string]: () => unknown };
1228
+ const storeDo = st.do as unknown as { [key: string]: (...args: any[]) => Promise<void> };
1229
+
1230
+ const names = {
1231
+ model: modelName,
1232
+ modelList: `${modelName}List`,
1233
+ modelListLoading: `${modelName}ListLoading`,
1234
+ refreshModel: `refresh${ModelName}`,
1235
+ };
1236
+
1237
+ const namesOfSlice = {
1238
+ modelList: sliceName.replace(names.model, names.modelList),
1239
+ modelListLoading: sliceName.replace(names.model, names.modelListLoading),
1240
+ refreshModel: sliceName.replace(names.model, names.refreshModel),
1241
+ };
1242
+
1243
+ const modelList = storeUse[namesOfSlice.modelList]() as DataList<Light>;
1244
+ const modelListLoading = storeUse[namesOfSlice.modelListLoading]() as string | boolean;
1245
+
1246
+ return (
1247
+ <div className={clsx("flex flex-col", className)}>
1248
+ {label ? <Label className={labelClassName} nullable={nullable} label={label} desc={desc} /> : null}
1249
+ <Select<string | null, false, true>
1250
+ label={label}
1251
+ desc={desc}
1252
+ labelClassName={labelClassName}
1253
+ selectClassName={selectClassName}
1254
+ value={value?.id ?? null}
1255
+ searchable
1256
+ options={modelList.map((model) => {
1257
+ const render = renderOption(model);
1258
+ return { label: typeof render === "string" ? render : model.id, value: model.id };
1259
+ })}
1260
+ renderOption={(modelId) => {
1261
+ if (!modelId) return null;
1262
+ const model = modelList.get(modelId);
1263
+ if (!model) return null;
1264
+ return renderOption(model);
1265
+ }}
1266
+ renderSelected={(modelId) => {
1267
+ if (!modelId) return null;
1268
+ const model = modelList.get(modelId);
1269
+ if (!model) return null;
1270
+ return renderSelected(model);
1271
+ }}
1272
+ onChange={(modelId) => {
1273
+ if (modelId) onChange(modelList.get(modelId) ?? null);
1274
+ else onChange(null);
1275
+ }}
1276
+ onOpen={() => {
1277
+ if (disabled) return;
1278
+ void storeDo[namesOfSlice.refreshModel]({ invalidate: true, queryArgs: initArgs });
1279
+ }}
1280
+ onSearch={onSearch}
1281
+ />
1282
+ </div>
1283
+ );
1284
+ };
1285
+ Field.Parent = Parent;
1286
+
1287
+ interface ParentIdProps<T extends string, State, Input, Full, Light> {
1288
+ label?: string;
1289
+ desc?: string;
1290
+ labelClassName?: string;
1291
+ className?: string;
1292
+ selectClassName?: string;
1293
+ disabled?: boolean;
1294
+ nullable?: boolean;
1295
+ initArgs?: any[];
1296
+ value: string | null;
1297
+ slice: SliceMeta;
1298
+ onChange: (id: string | null, model: Light | null) => void;
1299
+ onSearch?: (text: string) => void;
1300
+ sortOption?: (a: Light, b: Light) => number;
1301
+ renderOption?: (model: Light) => ReactNode;
1302
+ renderSelected?: (value: Light) => ReactNode;
1303
+ }
1304
+ const ParentId = <T extends string, State, Input, Full extends { id: string }, Light extends { id: string }>({
1305
+ label,
1306
+ desc,
1307
+ className,
1308
+ selectClassName,
1309
+ labelClassName,
1310
+ nullable,
1311
+ disabled,
1312
+ initArgs,
1313
+ slice,
1314
+ value,
1315
+ onChange,
1316
+ onSearch,
1317
+ sortOption,
1318
+ renderOption,
1319
+ renderSelected = renderOption,
1320
+ }: ParentIdProps<T, State, Input, Full, Light>) => {
1321
+ const { refName, sliceName } = slice;
1322
+ const [modelName, ModelName] = [lowerlize(refName), capitalize(refName)];
1323
+ const storeUse = st.use as { [key: string]: () => unknown };
1324
+ const storeDo = st.do as unknown as { [key: string]: (...args: any[]) => Promise<void> };
1325
+ const storeGet = st.get as unknown as <T>() => { [key: string]: T };
1326
+ const names = {
1327
+ model: modelName,
1328
+ modelList: `${modelName}List`,
1329
+ modelListLoading: `${modelName}ListLoading`,
1330
+ refreshModel: `refresh${ModelName}`,
1331
+ };
1332
+ const namesOfSlice = {
1333
+ modelList: sliceName.replace(names.model, names.modelList),
1334
+ modelListLoading: sliceName.replace(names.model, names.modelListLoading),
1335
+ refreshModel: sliceName.replace(names.model, names.refreshModel),
1336
+ };
1337
+ const modelList = storeUse[namesOfSlice.modelList]() as DataList<Light>;
1338
+ const modelListLoading = storeUse[namesOfSlice.modelListLoading]() as string | boolean;
1339
+
1340
+ return (
1341
+ <div className={clsx("flex flex-col", className)}>
1342
+ {label ? <Label className={labelClassName} nullable={nullable} label={label} desc={desc} /> : null}
1343
+ <Select<string | null, false, true>
1344
+ searchable
1345
+ desc={desc}
1346
+ label={label}
1347
+ labelClassName={labelClassName}
1348
+ selectClassName={selectClassName}
1349
+ value={value}
1350
+ options={modelList.map((model) => {
1351
+ const label = renderOption?.(model) ?? model.id;
1352
+ return { label: typeof label === "string" ? label : model.id, value: model.id };
1353
+ })}
1354
+ renderOption={(renderId) => {
1355
+ if (!renderId) return null;
1356
+ const model = modelList.get(renderId);
1357
+ if (!model) return null;
1358
+ return renderOption?.(model) ?? null;
1359
+ }}
1360
+ renderSelected={(renderId) => {
1361
+ if (!renderId) return null;
1362
+ const model = modelList.get(renderId);
1363
+ if (!model) return null;
1364
+ return renderSelected?.(model) ?? null;
1365
+ }}
1366
+ onOpen={() => {
1367
+ if (disabled) return;
1368
+ void storeDo[namesOfSlice.refreshModel]({ invalidate: true, queryArgs: initArgs });
1369
+ }}
1370
+ onChange={(modelId) => {
1371
+ if (modelId) onChange(modelId, modelList.get(modelId) ?? null);
1372
+ else onChange(null, null);
1373
+ }}
1374
+ onSearch={onSearch}
1375
+ />
1376
+ </div>
1377
+ );
1378
+ };
1379
+ Field.ParentId = ParentId;
1380
+
1381
+ interface ChildrenProps<T extends string, State, Input, Full, Light> {
1382
+ label?: string;
1383
+ desc?: string;
1384
+ labelClassName?: string;
1385
+ selectClassName?: string;
1386
+ className?: string;
1387
+ disabled?: boolean;
1388
+ nullable?: boolean;
1389
+ initArgs?: any[];
1390
+ value: Light[];
1391
+ onChange: (value: Light[]) => void;
1392
+ onSearch?: (text: string) => void;
1393
+ slice: SliceMeta;
1394
+ sortOption?: (a: Light, b: Light) => number;
1395
+ renderOption: (model: Light) => ReactNode;
1396
+ renderSelected?: (value: Light) => ReactNode;
1397
+ }
1398
+ const Children = <T extends string, State, Input, Full extends { id: string }, Light extends { id: string }>({
1399
+ label,
1400
+ desc,
1401
+ labelClassName,
1402
+ selectClassName,
1403
+ className,
1404
+ nullable,
1405
+ disabled,
1406
+ initArgs,
1407
+ slice,
1408
+ value,
1409
+ onChange,
1410
+ onSearch,
1411
+ sortOption,
1412
+ renderOption,
1413
+ renderSelected = renderOption,
1414
+ }: ChildrenProps<T, State, Input, Full, Light>) => {
1415
+ const { refName, sliceName } = slice;
1416
+ const [modelName, ModelName] = [lowerlize(refName), capitalize(refName)];
1417
+ const storeUse = st.use as { [key: string]: () => unknown };
1418
+ const storeDo = st.do as unknown as { [key: string]: (...args: any[]) => Promise<void> };
1419
+ const storeGet = st.get as unknown as <T>() => { [key: string]: T };
1420
+ const names = {
1421
+ model: modelName,
1422
+ modelList: `${modelName}List`,
1423
+ modelListLoading: `${modelName}ListLoading`,
1424
+ refreshModel: `refresh${ModelName}`,
1425
+ };
1426
+ const namesOfSlice = {
1427
+ modelList: sliceName.replace(names.model, names.modelList),
1428
+ modelListLoading: sliceName.replace(names.model, names.modelListLoading),
1429
+ refreshModel: sliceName.replace(names.model, names.refreshModel),
1430
+ };
1431
+ const modelList = storeUse[namesOfSlice.modelList]() as DataList<Light>;
1432
+ const modelListLoading = storeUse[namesOfSlice.modelListLoading]() as string | boolean;
1433
+
1434
+ return (
1435
+ <div className={clsx("flex flex-col", className)}>
1436
+ {label ? <Label className={labelClassName} nullable={nullable} label={label} desc={desc} /> : null}
1437
+ <Select
1438
+ searchable
1439
+ desc={desc}
1440
+ label={label}
1441
+ labelClassName={labelClassName}
1442
+ selectClassName={selectClassName}
1443
+ multiple
1444
+ value={value.map((model) => model.id)}
1445
+ options={modelList.map((model) => {
1446
+ const label = renderOption(model);
1447
+ return { label: typeof label === "string" ? label : model.id, value: model.id };
1448
+ })}
1449
+ onOpen={() => {
1450
+ if (disabled) return;
1451
+ void storeDo[namesOfSlice.refreshModel]({ invalidate: true, queryArgs: initArgs });
1452
+ }}
1453
+ renderOption={(modelId: string) => {
1454
+ const model = modelList.get(modelId);
1455
+ if (!model) return null;
1456
+ return renderOption(model);
1457
+ }}
1458
+ renderSelected={(modelId: string) => {
1459
+ const model = modelList.get(modelId);
1460
+ if (!model) return null;
1461
+ return renderSelected(model);
1462
+ }}
1463
+ onChange={(modelIds: string[]) => {
1464
+ onChange(
1465
+ modelIds.map((id) => modelList.get(id)).filter((model) => model !== undefined) as unknown as Light[],
1466
+ );
1467
+ }}
1468
+ onSearch={onSearch}
1469
+ />
1470
+ </div>
1471
+ );
1472
+ };
1473
+ Field.Children = Children;
1474
+
1475
+ interface ChildrenIdProps<T extends string, State, Input, Full, Light> {
1476
+ label?: string;
1477
+ desc?: string;
1478
+ labelClassName?: string;
1479
+ className?: string;
1480
+ disabled?: boolean;
1481
+ nullable?: boolean;
1482
+ initArgs?: any[];
1483
+ value: string[];
1484
+ slice: SliceMeta;
1485
+ onChange: (value: string[]) => void;
1486
+ onSearch?: (text: string) => void;
1487
+ sortOption?: (a: Light, b: Light) => number;
1488
+ renderOption: (model: Light) => ReactNode;
1489
+ }
1490
+ const ChildrenId = <T extends string, State, Input, Full extends { id: string }, Light extends { id: string }>({
1491
+ label,
1492
+ desc,
1493
+ labelClassName,
1494
+ className,
1495
+ nullable,
1496
+ disabled,
1497
+ initArgs,
1498
+ slice,
1499
+ value,
1500
+ onChange,
1501
+ onSearch,
1502
+ sortOption,
1503
+ renderOption,
1504
+ }: ChildrenIdProps<T, State, Input, Full, Light>) => {
1505
+ const { refName, sliceName } = slice;
1506
+ const [modelName, ModelName] = [lowerlize(refName), capitalize(refName)];
1507
+ const storeUse = st.use as { [key: string]: () => unknown };
1508
+ const storeDo = st.do as unknown as { [key: string]: (...args: any[]) => Promise<void> };
1509
+ const storeGet = st.get as unknown as <T>() => { [key: string]: T };
1510
+ const names = {
1511
+ model: modelName,
1512
+ modelList: `${modelName}List`,
1513
+ modelListLoading: `${modelName}ListLoading`,
1514
+ refreshModel: `refresh${ModelName}`,
1515
+ };
1516
+ const namesOfSlice = {
1517
+ modelList: sliceName.replace(names.model, names.modelList),
1518
+ modelListLoading: sliceName.replace(names.model, names.modelListLoading),
1519
+ refreshModel: sliceName.replace(names.model, names.refreshModel),
1520
+ };
1521
+ const modelList = storeUse[namesOfSlice.modelList]() as DataList<Light>;
1522
+ const modelListLoading = storeUse[namesOfSlice.modelListLoading]() as string | boolean;
1523
+
1524
+ return (
1525
+ <div className={clsx("flex flex-col", className)}>
1526
+ {label ? <Label className={labelClassName} nullable={nullable} label={label} desc={desc} /> : null}
1527
+ <Select
1528
+ searchable
1529
+ desc={desc}
1530
+ label={label}
1531
+ labelClassName={labelClassName}
1532
+ multiple
1533
+
1534
+ value={value}
1535
+ options={modelList.map((model) => {
1536
+ const label = renderOption(model);
1537
+ return { label: typeof label === "string" ? label : model.id, value: model.id };
1538
+ })}
1539
+ renderOption={(renderId) => {
1540
+ const model = modelList.get(renderId);
1541
+ if (!model) return null;
1542
+ return renderOption(model);
1543
+ }}
1544
+ onOpen={() => {
1545
+ if (disabled) return;
1546
+ void storeDo[namesOfSlice.refreshModel]({ invalidate: true, queryArgs: initArgs });
1547
+ }}
1548
+ onChange={(modelIds) => {
1549
+ onChange(modelIds);
1550
+ }}
1551
+ onSearch={onSearch}
1552
+ />
1553
+ </div>
1554
+ );
1555
+ };
1556
+ Field.ChildrenId = ChildrenId;