@simplysm/angular 14.0.1 → 14.0.4

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 (442) hide show
  1. package/dist/core/commons.d.ts +2 -0
  2. package/dist/core/commons.d.ts.map +1 -0
  3. package/dist/core/commons.js +4 -0
  4. package/dist/core/directives/sd-events.directive.js +7 -7
  5. package/dist/core/directives/sd-item-of-template.directive.d.ts +14 -0
  6. package/dist/core/directives/sd-item-of-template.directive.d.ts.map +1 -0
  7. package/dist/core/directives/sd-item-of-template.directive.js +17 -0
  8. package/dist/core/directives/sd-router-link.directive.d.ts +19 -0
  9. package/dist/core/directives/sd-router-link.directive.d.ts.map +1 -0
  10. package/dist/core/directives/sd-router-link.directive.js +64 -0
  11. package/dist/core/directives/sd-typed-template.directive.d.ts +8 -0
  12. package/dist/core/directives/sd-typed-template.directive.d.ts.map +1 -0
  13. package/dist/core/directives/sd-typed-template.directive.js +17 -0
  14. package/dist/core/pipes/format.pipe.d.ts +9 -0
  15. package/dist/core/pipes/format.pipe.d.ts.map +1 -0
  16. package/dist/core/pipes/format.pipe.js +43 -0
  17. package/dist/core/plugins/commands/findTopOpenModalEl.d.ts +8 -0
  18. package/dist/core/plugins/commands/findTopOpenModalEl.d.ts.map +1 -0
  19. package/dist/core/plugins/commands/findTopOpenModalEl.js +21 -0
  20. package/dist/core/plugins/commands/sd-insert-command-event.plugin.d.ts.map +1 -1
  21. package/dist/core/plugins/commands/sd-insert-command-event.plugin.js +4 -0
  22. package/dist/core/plugins/commands/sd-refresh-command-event.plugin.d.ts.map +1 -1
  23. package/dist/core/plugins/commands/sd-refresh-command-event.plugin.js +4 -0
  24. package/dist/core/plugins/commands/sd-save-command-event.plugin.d.ts.map +1 -1
  25. package/dist/core/plugins/commands/sd-save-command-event.plugin.js +4 -0
  26. package/dist/core/plugins/events/sd-resize-event.plugin.d.ts.map +1 -1
  27. package/dist/core/plugins/events/sd-resize-event.plugin.js +0 -18
  28. package/dist/core/plugins/sd-global-error-handler.plugin.d.ts +1 -0
  29. package/dist/core/plugins/sd-global-error-handler.plugin.d.ts.map +1 -1
  30. package/dist/core/plugins/sd-global-error-handler.plugin.js +23 -13
  31. package/dist/core/provideSdAngular.d.ts +5 -0
  32. package/dist/core/provideSdAngular.d.ts.map +1 -0
  33. package/dist/core/provideSdAngular.js +127 -0
  34. package/dist/core/providers/sd-angular-config.provider.d.ts +7 -0
  35. package/dist/core/providers/sd-angular-config.provider.d.ts.map +1 -0
  36. package/dist/core/providers/sd-angular-config.provider.js +11 -0
  37. package/dist/core/providers/sd-app-structure.provider.d.ts +79 -0
  38. package/dist/core/providers/sd-app-structure.provider.d.ts.map +1 -0
  39. package/dist/core/providers/sd-app-structure.provider.js +278 -0
  40. package/dist/core/providers/sd-file-dialog.provider.d.ts +8 -0
  41. package/dist/core/providers/sd-file-dialog.provider.d.ts.map +1 -0
  42. package/dist/core/providers/sd-file-dialog.provider.js +49 -0
  43. package/dist/core/providers/sd-local-storage.provider.d.ts +10 -0
  44. package/dist/core/providers/sd-local-storage.provider.d.ts.map +1 -0
  45. package/dist/core/providers/sd-local-storage.provider.js +24 -0
  46. package/dist/core/providers/sd-navigate-window.provider.d.ts +9 -0
  47. package/dist/core/providers/sd-navigate-window.provider.d.ts.map +1 -0
  48. package/dist/core/providers/sd-navigate-window.provider.js +33 -0
  49. package/dist/core/providers/sd-print.provider.d.ts +26 -0
  50. package/dist/core/providers/sd-print.provider.d.ts.map +1 -0
  51. package/dist/core/providers/sd-print.provider.js +142 -0
  52. package/dist/core/providers/sd-service-client-factory.provider.d.ts +19 -0
  53. package/dist/core/providers/sd-service-client-factory.provider.d.ts.map +1 -0
  54. package/dist/core/providers/sd-service-client-factory.provider.js +86 -0
  55. package/dist/core/providers/sd-shared-data.provider.d.ts +36 -0
  56. package/dist/core/providers/sd-shared-data.provider.d.ts.map +1 -0
  57. package/dist/core/providers/sd-shared-data.provider.js +119 -0
  58. package/dist/core/providers/sd-system-config.provider.d.ts +13 -0
  59. package/dist/core/providers/sd-system-config.provider.d.ts.map +1 -0
  60. package/dist/core/providers/sd-system-config.provider.js +29 -0
  61. package/dist/core/providers/sd-system-log.provider.d.ts +8 -0
  62. package/dist/core/providers/sd-system-log.provider.d.ts.map +1 -0
  63. package/dist/core/providers/sd-system-log.provider.js +23 -0
  64. package/dist/core/providers/sd-theme-provider.js +1 -1
  65. package/dist/core/utils/TDirectiveInputSignals.d.ts +29 -0
  66. package/dist/core/utils/TDirectiveInputSignals.d.ts.map +1 -0
  67. package/dist/core/utils/TDirectiveInputSignals.js +1 -0
  68. package/dist/core/utils/setups/setupCanDeactivate.d.ts +2 -0
  69. package/dist/core/utils/setups/setupCanDeactivate.d.ts.map +1 -0
  70. package/dist/core/utils/setups/setupCanDeactivate.js +28 -0
  71. package/dist/core/utils/setups/setupModelHook.d.ts +3 -0
  72. package/dist/core/utils/setups/setupModelHook.d.ts.map +1 -0
  73. package/dist/core/utils/setups/setupModelHook.js +18 -0
  74. package/dist/core/utils/useCurrentPageCodeSignal.d.ts +3 -0
  75. package/dist/core/utils/useCurrentPageCodeSignal.d.ts.map +1 -0
  76. package/dist/core/utils/useCurrentPageCodeSignal.js +13 -0
  77. package/dist/core/utils/useExpandingManager.d.ts +23 -0
  78. package/dist/core/utils/useExpandingManager.d.ts.map +1 -0
  79. package/dist/core/utils/useExpandingManager.js +86 -0
  80. package/dist/core/utils/useFullPageCodeSignal.d.ts +3 -0
  81. package/dist/core/utils/useFullPageCodeSignal.d.ts.map +1 -0
  82. package/dist/core/utils/useFullPageCodeSignal.js +13 -0
  83. package/dist/core/utils/useSdSystemConfigResource.d.ts +13 -0
  84. package/dist/core/utils/useSdSystemConfigResource.d.ts.map +1 -0
  85. package/dist/core/utils/useSdSystemConfigResource.js +31 -0
  86. package/dist/core/utils/useSelectionManager.d.ts +18 -0
  87. package/dist/core/utils/useSelectionManager.d.ts.map +1 -0
  88. package/dist/core/utils/useSelectionManager.js +89 -0
  89. package/dist/core/utils/useSortingManager.d.ts +17 -0
  90. package/dist/core/utils/useSortingManager.d.ts.map +1 -0
  91. package/dist/core/utils/useSortingManager.js +81 -0
  92. package/dist/core/utils/useViewTitleSignal.d.ts +3 -0
  93. package/dist/core/utils/useViewTitleSignal.d.ts.map +1 -0
  94. package/dist/core/utils/useViewTitleSignal.js +17 -0
  95. package/dist/core/utils/useViewTypeSignal.d.ts +4 -0
  96. package/dist/core/utils/useViewTypeSignal.d.ts.map +1 -0
  97. package/dist/core/utils/useViewTypeSignal.js +23 -0
  98. package/dist/index.d.ts +95 -0
  99. package/dist/index.d.ts.map +1 -1
  100. package/dist/index.js +115 -0
  101. package/dist/styles.css +1462 -722
  102. package/dist/ui/data/list/sd-list-item.control.d.ts +18 -0
  103. package/dist/ui/data/list/sd-list-item.control.d.ts.map +1 -0
  104. package/dist/ui/data/list/sd-list-item.control.js +130 -0
  105. package/dist/ui/data/list/sd-list.control.d.ts +7 -0
  106. package/dist/ui/data/list/sd-list.control.d.ts.map +1 -0
  107. package/dist/ui/data/list/sd-list.control.js +22 -0
  108. package/dist/ui/data/sheet/sd-sheet-column.directive.d.ts +18 -0
  109. package/dist/ui/data/sheet/sd-sheet-column.directive.d.ts.map +1 -0
  110. package/dist/ui/data/sheet/sd-sheet-column.directive.js +30 -0
  111. package/dist/ui/data/sheet/sd-sheet-config.modal.d.ts +39 -0
  112. package/dist/ui/data/sheet/sd-sheet-config.modal.d.ts.map +1 -0
  113. package/dist/ui/data/sheet/sd-sheet-config.modal.js +258 -0
  114. package/dist/ui/data/sheet/sd-sheet.control.d.ts +154 -0
  115. package/dist/ui/data/sheet/sd-sheet.control.d.ts.map +1 -0
  116. package/dist/ui/data/sheet/sd-sheet.control.js +846 -0
  117. package/dist/ui/data/sheet/types.d.ts +32 -0
  118. package/dist/ui/data/sheet/types.d.ts.map +1 -0
  119. package/dist/ui/data/sheet/types.js +1 -0
  120. package/dist/ui/data/sheet/useSheetCellAgent.d.ts +21 -0
  121. package/dist/ui/data/sheet/useSheetCellAgent.d.ts.map +1 -0
  122. package/dist/ui/data/sheet/useSheetCellAgent.js +245 -0
  123. package/dist/ui/data/sheet/useSheetColumnFixing.d.ts +9 -0
  124. package/dist/ui/data/sheet/useSheetColumnFixing.d.ts.map +1 -0
  125. package/dist/ui/data/sheet/useSheetColumnFixing.js +29 -0
  126. package/dist/ui/data/sheet/useSheetDomAccessor.d.ts +11 -0
  127. package/dist/ui/data/sheet/useSheetDomAccessor.d.ts.map +1 -0
  128. package/dist/ui/data/sheet/useSheetDomAccessor.js +55 -0
  129. package/dist/ui/data/sheet/useSheetLayoutEngine.d.ts +14 -0
  130. package/dist/ui/data/sheet/useSheetLayoutEngine.d.ts.map +1 -0
  131. package/dist/ui/data/sheet/useSheetLayoutEngine.js +126 -0
  132. package/dist/ui/form/button/sd-additional-button.control.d.ts +8 -0
  133. package/dist/ui/form/button/sd-additional-button.control.d.ts.map +1 -0
  134. package/dist/ui/form/button/sd-additional-button.control.js +38 -0
  135. package/dist/ui/form/button/sd-anchor.control.d.ts +8 -0
  136. package/dist/ui/form/button/sd-anchor.control.d.ts.map +1 -0
  137. package/dist/ui/form/button/sd-anchor.control.js +25 -0
  138. package/dist/ui/form/button/sd-button.control.d.ts +14 -0
  139. package/dist/ui/form/button/sd-button.control.d.ts.map +1 -0
  140. package/dist/ui/form/button/sd-button.control.js +49 -0
  141. package/dist/ui/form/button/sd-modal-select-button.control.d.ts +46 -0
  142. package/dist/ui/form/button/sd-modal-select-button.control.d.ts.map +1 -0
  143. package/dist/ui/form/button/sd-modal-select-button.control.js +149 -0
  144. package/dist/ui/form/checkbox/sd-checkbox-group-item.control.d.ts +12 -0
  145. package/dist/ui/form/checkbox/sd-checkbox-group-item.control.d.ts.map +1 -0
  146. package/dist/ui/form/checkbox/sd-checkbox-group-item.control.js +53 -0
  147. package/dist/ui/form/checkbox/sd-checkbox-group.control.d.ts +8 -0
  148. package/dist/ui/form/checkbox/sd-checkbox-group.control.d.ts.map +1 -0
  149. package/dist/ui/form/checkbox/sd-checkbox-group.control.js +26 -0
  150. package/dist/ui/form/checkbox/sd-checkbox.control.d.ts +19 -0
  151. package/dist/ui/form/checkbox/sd-checkbox.control.d.ts.map +1 -0
  152. package/dist/ui/form/checkbox/sd-checkbox.control.js +103 -0
  153. package/dist/ui/form/checkbox/sd-switch.control.d.ts +14 -0
  154. package/dist/ui/form/checkbox/sd-switch.control.d.ts.map +1 -0
  155. package/dist/ui/form/checkbox/sd-switch.control.js +54 -0
  156. package/dist/ui/form/choice/sd-state-preset.control.d.ts +24 -0
  157. package/dist/ui/form/choice/sd-state-preset.control.d.ts.map +1 -0
  158. package/dist/ui/form/choice/sd-state-preset.control.js +134 -0
  159. package/dist/ui/form/editor/sd-tiptap-editor.control.d.ts +35 -0
  160. package/dist/ui/form/editor/sd-tiptap-editor.control.d.ts.map +1 -0
  161. package/dist/ui/form/editor/sd-tiptap-editor.control.js +480 -0
  162. package/dist/ui/form/input/sd-date-range.picker.d.ts +13 -0
  163. package/dist/ui/form/input/sd-date-range.picker.d.ts.map +1 -0
  164. package/dist/ui/form/input/sd-date-range.picker.js +125 -0
  165. package/dist/ui/form/input/sd-numpad.control.d.ts +18 -0
  166. package/dist/ui/form/input/sd-numpad.control.d.ts.map +1 -0
  167. package/dist/ui/form/input/sd-numpad.control.js +241 -0
  168. package/dist/ui/form/input/sd-range.control.d.ts +13 -0
  169. package/dist/ui/form/input/sd-range.control.d.ts.map +1 -0
  170. package/dist/ui/form/input/sd-range.control.js +53 -0
  171. package/dist/ui/form/input/sd-textarea.control.d.ts +23 -0
  172. package/dist/ui/form/input/sd-textarea.control.d.ts.map +1 -0
  173. package/dist/ui/form/input/sd-textarea.control.js +132 -0
  174. package/dist/ui/form/input/sd-textfield-type-handlers.d.ts +46 -0
  175. package/dist/ui/form/input/sd-textfield-type-handlers.d.ts.map +1 -0
  176. package/dist/ui/form/input/sd-textfield-type-handlers.js +336 -0
  177. package/dist/ui/form/input/sd-textfield.control.d.ts +39 -0
  178. package/dist/ui/form/input/sd-textfield.control.d.ts.map +1 -0
  179. package/dist/ui/form/input/sd-textfield.control.js +211 -0
  180. package/dist/ui/form/sd-form.control.d.ts +13 -0
  181. package/dist/ui/form/sd-form.control.d.ts.map +1 -0
  182. package/dist/ui/form/sd-form.control.js +60 -0
  183. package/dist/ui/form/select/sd-select-button.control.d.ts +7 -0
  184. package/dist/ui/form/select/sd-select-button.control.d.ts.map +1 -0
  185. package/dist/ui/form/select/sd-select-button.control.js +25 -0
  186. package/dist/ui/form/select/sd-select-item.control.d.ts +18 -0
  187. package/dist/ui/form/select/sd-select-item.control.d.ts.map +1 -0
  188. package/dist/ui/form/select/sd-select-item.control.js +103 -0
  189. package/dist/ui/form/select/sd-select.control.d.ts +45 -0
  190. package/dist/ui/form/select/sd-select.control.d.ts.map +1 -0
  191. package/dist/ui/form/select/sd-select.control.js +430 -0
  192. package/dist/ui/layout/dock/sd-dock-container.control.d.ts +12 -0
  193. package/dist/ui/layout/dock/sd-dock-container.control.d.ts.map +1 -0
  194. package/dist/ui/layout/dock/sd-dock-container.control.js +96 -0
  195. package/dist/ui/layout/dock/sd-dock.control.d.ts +17 -0
  196. package/dist/ui/layout/dock/sd-dock.control.d.ts.map +1 -0
  197. package/dist/ui/layout/dock/sd-dock.control.js +111 -0
  198. package/dist/ui/layout/kanban/sd-kanban-board.control.d.ts +24 -0
  199. package/dist/ui/layout/kanban/sd-kanban-board.control.d.ts.map +1 -0
  200. package/dist/ui/layout/kanban/sd-kanban-board.control.js +37 -0
  201. package/dist/ui/layout/kanban/sd-kanban-lane.control.d.ts +29 -0
  202. package/dist/ui/layout/kanban/sd-kanban-lane.control.d.ts.map +1 -0
  203. package/dist/ui/layout/kanban/sd-kanban-lane.control.js +223 -0
  204. package/dist/ui/layout/kanban/sd-kanban.control.d.ts +32 -0
  205. package/dist/ui/layout/kanban/sd-kanban.control.d.ts.map +1 -0
  206. package/dist/ui/layout/kanban/sd-kanban.control.js +147 -0
  207. package/dist/ui/layout/sd-card.directive.d.ts +6 -0
  208. package/dist/ui/layout/sd-card.directive.d.ts.map +1 -0
  209. package/dist/ui/layout/sd-card.directive.js +16 -0
  210. package/dist/ui/layout/sd-gap.control.d.ts +13 -0
  211. package/dist/ui/layout/sd-gap.control.d.ts.map +1 -0
  212. package/dist/ui/layout/sd-gap.control.js +44 -0
  213. package/dist/ui/layout/sd-pane.directive.d.ts +6 -0
  214. package/dist/ui/layout/sd-pane.directive.d.ts.map +1 -0
  215. package/dist/ui/layout/sd-pane.directive.js +17 -0
  216. package/dist/ui/layout/view/sd-view-item.control.d.ts +9 -0
  217. package/dist/ui/layout/view/sd-view-item.control.d.ts.map +1 -0
  218. package/dist/ui/layout/view/sd-view-item.control.js +25 -0
  219. package/dist/ui/layout/view/sd-view.control.d.ts +8 -0
  220. package/dist/ui/layout/view/sd-view.control.d.ts.map +1 -0
  221. package/dist/ui/layout/view/sd-view.control.js +23 -0
  222. package/dist/ui/navigation/collapse/sd-collapse-icon.control.d.ts +13 -0
  223. package/dist/ui/navigation/collapse/sd-collapse-icon.control.d.ts.map +1 -0
  224. package/dist/ui/navigation/collapse/sd-collapse-icon.control.js +33 -0
  225. package/dist/ui/navigation/collapse/sd-collapse.control.d.ts +14 -0
  226. package/dist/ui/navigation/collapse/sd-collapse.control.d.ts.map +1 -0
  227. package/dist/ui/navigation/collapse/sd-collapse.control.js +59 -0
  228. package/dist/ui/navigation/menu-utils.d.ts +13 -0
  229. package/dist/ui/navigation/menu-utils.d.ts.map +1 -0
  230. package/dist/ui/navigation/menu-utils.js +18 -0
  231. package/dist/ui/navigation/pagination/sd-pagination.control.d.ts +24 -0
  232. package/dist/ui/navigation/pagination/sd-pagination.control.d.ts.map +1 -0
  233. package/dist/ui/navigation/pagination/sd-pagination.control.js +137 -0
  234. package/dist/ui/navigation/sidebar/sd-sidebar-container.control.d.ts +11 -0
  235. package/dist/ui/navigation/sidebar/sd-sidebar-container.control.d.ts.map +1 -0
  236. package/dist/ui/navigation/sidebar/sd-sidebar-container.control.js +46 -0
  237. package/dist/ui/navigation/sidebar/sd-sidebar-menu.control.d.ts +28 -0
  238. package/dist/ui/navigation/sidebar/sd-sidebar-menu.control.d.ts.map +1 -0
  239. package/dist/ui/navigation/sidebar/sd-sidebar-menu.control.js +159 -0
  240. package/dist/ui/navigation/sidebar/sd-sidebar-user.control.d.ts +16 -0
  241. package/dist/ui/navigation/sidebar/sd-sidebar-user.control.d.ts.map +1 -0
  242. package/dist/ui/navigation/sidebar/sd-sidebar-user.control.js +109 -0
  243. package/dist/ui/navigation/sidebar/sd-sidebar.control.d.ts +8 -0
  244. package/dist/ui/navigation/sidebar/sd-sidebar.control.d.ts.map +1 -0
  245. package/dist/ui/navigation/sidebar/sd-sidebar.control.js +24 -0
  246. package/dist/ui/navigation/tab/sd-tab-item.control.d.ts +10 -0
  247. package/dist/ui/navigation/tab/sd-tab-item.control.d.ts.map +1 -0
  248. package/dist/ui/navigation/tab/sd-tab-item.control.js +31 -0
  249. package/dist/ui/navigation/tab/sd-tab.control.d.ts +7 -0
  250. package/dist/ui/navigation/tab/sd-tab.control.d.ts.map +1 -0
  251. package/dist/ui/navigation/tab/sd-tab.control.js +18 -0
  252. package/dist/ui/navigation/tab/sd-tabview-item.control.d.ts +10 -0
  253. package/dist/ui/navigation/tab/sd-tabview-item.control.d.ts.map +1 -0
  254. package/dist/ui/navigation/tab/sd-tabview-item.control.js +26 -0
  255. package/dist/ui/navigation/tab/sd-tabview.control.d.ts +9 -0
  256. package/dist/ui/navigation/tab/sd-tabview.control.d.ts.map +1 -0
  257. package/dist/ui/navigation/tab/sd-tabview.control.js +67 -0
  258. package/dist/ui/navigation/topbar/sd-topbar-container.control.d.ts +6 -0
  259. package/dist/ui/navigation/topbar/sd-topbar-container.control.d.ts.map +1 -0
  260. package/dist/ui/navigation/topbar/sd-topbar-container.control.js +17 -0
  261. package/dist/ui/navigation/topbar/sd-topbar-menu.control.d.ts +29 -0
  262. package/dist/ui/navigation/topbar/sd-topbar-menu.control.d.ts.map +1 -0
  263. package/dist/ui/navigation/topbar/sd-topbar-menu.control.js +245 -0
  264. package/dist/ui/navigation/topbar/sd-topbar-user.control.d.ts +13 -0
  265. package/dist/ui/navigation/topbar/sd-topbar-user.control.d.ts.map +1 -0
  266. package/dist/ui/navigation/topbar/sd-topbar-user.control.js +77 -0
  267. package/dist/ui/navigation/topbar/sd-topbar.control.d.ts +12 -0
  268. package/dist/ui/navigation/topbar/sd-topbar.control.d.ts.map +1 -0
  269. package/dist/ui/navigation/topbar/sd-topbar.control.js +59 -0
  270. package/dist/ui/overlay/busy/sd-busy-container.control.d.ts +14 -0
  271. package/dist/ui/overlay/busy/sd-busy-container.control.d.ts.map +1 -0
  272. package/dist/ui/overlay/busy/sd-busy-container.control.js +119 -0
  273. package/dist/ui/overlay/busy/sd-busy.provider.d.ts +16 -0
  274. package/dist/ui/overlay/busy/sd-busy.provider.d.ts.map +1 -0
  275. package/dist/ui/overlay/busy/sd-busy.provider.js +43 -0
  276. package/dist/ui/overlay/dropdown/sd-dropdown-popup.control.d.ts +11 -0
  277. package/dist/ui/overlay/dropdown/sd-dropdown-popup.control.d.ts.map +1 -0
  278. package/dist/ui/overlay/dropdown/sd-dropdown-popup.control.js +43 -0
  279. package/dist/ui/overlay/dropdown/sd-dropdown.control.d.ts +27 -0
  280. package/dist/ui/overlay/dropdown/sd-dropdown.control.d.ts.map +1 -0
  281. package/dist/ui/overlay/dropdown/sd-dropdown.control.js +284 -0
  282. package/dist/ui/overlay/modal/sd-confirm-modal.control.d.ts +17 -0
  283. package/dist/ui/overlay/modal/sd-confirm-modal.control.d.ts.map +1 -0
  284. package/dist/ui/overlay/modal/sd-confirm-modal.control.js +51 -0
  285. package/dist/ui/overlay/modal/sd-modal.control.d.ts +51 -0
  286. package/dist/ui/overlay/modal/sd-modal.control.d.ts.map +1 -0
  287. package/dist/ui/overlay/modal/sd-modal.control.js +411 -0
  288. package/dist/ui/overlay/modal/sd-modal.provider.d.ts +65 -0
  289. package/dist/ui/overlay/modal/sd-modal.provider.d.ts.map +1 -0
  290. package/dist/ui/overlay/modal/sd-modal.provider.js +146 -0
  291. package/dist/ui/overlay/modal/sd-prompt-modal.control.d.ts +19 -0
  292. package/dist/ui/overlay/modal/sd-prompt-modal.control.d.ts.map +1 -0
  293. package/dist/ui/overlay/modal/sd-prompt-modal.control.js +71 -0
  294. package/dist/ui/overlay/toast/sd-toast-container.control.d.ts +7 -0
  295. package/dist/ui/overlay/toast/sd-toast-container.control.d.ts.map +1 -0
  296. package/dist/ui/overlay/toast/sd-toast-container.control.js +20 -0
  297. package/dist/ui/overlay/toast/sd-toast.control.d.ts +14 -0
  298. package/dist/ui/overlay/toast/sd-toast.control.d.ts.map +1 -0
  299. package/dist/ui/overlay/toast/sd-toast.control.js +79 -0
  300. package/dist/ui/overlay/toast/sd-toast.provider.d.ts +45 -0
  301. package/dist/ui/overlay/toast/sd-toast.provider.d.ts.map +1 -0
  302. package/dist/ui/overlay/toast/sd-toast.provider.js +219 -0
  303. package/dist/ui/visual/sd-barcode.control.d.ts +11 -0
  304. package/dist/ui/visual/sd-barcode.control.d.ts.map +1 -0
  305. package/dist/ui/visual/sd-barcode.control.js +35 -0
  306. package/dist/ui/visual/sd-calendar.control.d.ts +20 -0
  307. package/dist/ui/visual/sd-calendar.control.d.ts.map +1 -0
  308. package/dist/ui/visual/sd-calendar.control.js +189 -0
  309. package/dist/ui/visual/sd-echarts.control.d.ts +13 -0
  310. package/dist/ui/visual/sd-echarts.control.d.ts.map +1 -0
  311. package/dist/ui/visual/sd-echarts.control.js +55 -0
  312. package/dist/ui/visual/sd-label.control.d.ts +9 -0
  313. package/dist/ui/visual/sd-label.control.d.ts.map +1 -0
  314. package/dist/ui/visual/sd-label.control.js +27 -0
  315. package/dist/ui/visual/sd-note.control.d.ts +9 -0
  316. package/dist/ui/visual/sd-note.control.d.ts.map +1 -0
  317. package/dist/ui/visual/sd-note.control.js +26 -0
  318. package/dist/ui/visual/sd-progress.control.d.ts +10 -0
  319. package/dist/ui/visual/sd-progress.control.d.ts.map +1 -0
  320. package/dist/ui/visual/sd-progress.control.js +38 -0
  321. package/package.json +35 -17
  322. package/scss/commons/_mixins.scss +34 -0
  323. package/scss/commons/_styles.scss +27 -68
  324. package/scss/commons/_variables.scss +7 -0
  325. package/scss/controls/_card.scss +29 -0
  326. package/scss/controls/_flex.scss +38 -0
  327. package/scss/controls/_form-box.scss +49 -0
  328. package/scss/controls/_form-table.scss +45 -0
  329. package/scss/controls/_grid.scss +36 -0
  330. package/scss/controls/_table.scss +99 -0
  331. package/scss/styles.scss +7 -0
  332. package/scss/themes/_variables-dark.scss +2 -0
  333. package/src/core/commons.ts +4 -0
  334. package/src/core/directives/sd-events.directive.ts +7 -7
  335. package/src/core/directives/sd-item-of-template.directive.ts +23 -0
  336. package/src/core/directives/sd-router-link.directive.ts +81 -0
  337. package/src/core/directives/sd-typed-template.directive.ts +16 -0
  338. package/src/core/pipes/format.pipe.ts +37 -0
  339. package/src/core/plugins/commands/findTopOpenModalEl.ts +23 -0
  340. package/src/core/plugins/commands/sd-insert-command-event.plugin.ts +4 -0
  341. package/src/core/plugins/commands/sd-refresh-command-event.plugin.ts +4 -0
  342. package/src/core/plugins/commands/sd-save-command-event.plugin.ts +4 -0
  343. package/src/core/plugins/events/sd-resize-event.plugin.ts +0 -22
  344. package/src/core/plugins/sd-global-error-handler.plugin.ts +22 -13
  345. package/src/core/provideSdAngular.ts +154 -0
  346. package/src/core/providers/sd-angular-config.provider.ts +6 -0
  347. package/src/core/providers/sd-app-structure.provider.ts +446 -0
  348. package/src/core/providers/sd-file-dialog.provider.ts +49 -0
  349. package/src/core/providers/sd-local-storage.provider.ts +21 -0
  350. package/src/core/providers/sd-navigate-window.provider.ts +44 -0
  351. package/src/core/providers/sd-print.provider.ts +189 -0
  352. package/src/core/providers/sd-service-client-factory.provider.ts +98 -0
  353. package/src/core/providers/sd-shared-data.provider.ts +179 -0
  354. package/src/core/providers/sd-system-config.provider.ts +28 -0
  355. package/src/core/providers/sd-system-log.provider.ts +19 -0
  356. package/src/core/providers/sd-theme-provider.ts +1 -1
  357. package/src/core/utils/TDirectiveInputSignals.ts +34 -0
  358. package/src/core/utils/setups/setupCanDeactivate.ts +34 -0
  359. package/src/core/utils/setups/setupModelHook.ts +26 -0
  360. package/src/core/utils/useCurrentPageCodeSignal.ts +16 -0
  361. package/src/core/utils/useExpandingManager.ts +117 -0
  362. package/src/core/utils/useFullPageCodeSignal.ts +24 -0
  363. package/src/core/utils/useSdSystemConfigResource.ts +36 -0
  364. package/src/core/utils/useSelectionManager.ts +104 -0
  365. package/src/core/utils/useSortingManager.ts +89 -0
  366. package/src/core/utils/useViewTitleSignal.ts +21 -0
  367. package/src/core/utils/useViewTypeSignal.ts +33 -0
  368. package/src/index.ts +209 -0
  369. package/src/scss.d.ts +1 -0
  370. package/src/ui/data/list/sd-list-item.control.ts +143 -0
  371. package/src/ui/data/list/sd-list.control.ts +41 -0
  372. package/src/ui/data/sheet/sd-sheet-column.directive.ts +26 -0
  373. package/src/ui/data/sheet/sd-sheet-config.modal.ts +252 -0
  374. package/src/ui/data/sheet/sd-sheet.control.ts +766 -0
  375. package/src/ui/data/sheet/types.ts +37 -0
  376. package/src/ui/data/sheet/useSheetCellAgent.ts +267 -0
  377. package/src/ui/data/sheet/useSheetColumnFixing.ts +37 -0
  378. package/src/ui/data/sheet/useSheetDomAccessor.ts +62 -0
  379. package/src/ui/data/sheet/useSheetLayoutEngine.ts +143 -0
  380. package/src/ui/form/button/sd-additional-button.control.ts +100 -0
  381. package/src/ui/form/button/sd-anchor.control.ts +67 -0
  382. package/src/ui/form/button/sd-button.control.ts +209 -0
  383. package/src/ui/form/button/sd-modal-select-button.control.ts +237 -0
  384. package/src/ui/form/checkbox/sd-checkbox-group-item.control.ts +51 -0
  385. package/src/ui/form/checkbox/sd-checkbox-group.control.ts +24 -0
  386. package/src/ui/form/checkbox/sd-checkbox.control.ts +305 -0
  387. package/src/ui/form/checkbox/sd-switch.control.ts +145 -0
  388. package/src/ui/form/choice/sd-state-preset.control.ts +173 -0
  389. package/src/ui/form/editor/sd-tiptap-editor.control.ts +474 -0
  390. package/src/ui/form/input/sd-date-range.picker.ts +98 -0
  391. package/src/ui/form/input/sd-numpad.control.ts +178 -0
  392. package/src/ui/form/input/sd-range.control.ts +59 -0
  393. package/src/ui/form/input/sd-textarea.control.ts +221 -0
  394. package/src/ui/form/input/sd-textfield-type-handlers.ts +445 -0
  395. package/src/ui/form/input/sd-textfield.control.ts +395 -0
  396. package/src/ui/form/sd-form.control.ts +52 -0
  397. package/src/ui/form/select/sd-select-button.control.ts +43 -0
  398. package/src/ui/form/select/sd-select-item.control.ts +143 -0
  399. package/src/ui/form/select/sd-select.control.ts +412 -0
  400. package/src/ui/layout/dock/sd-dock-container.control.ts +100 -0
  401. package/src/ui/layout/dock/sd-dock.control.ts +171 -0
  402. package/src/ui/layout/kanban/sd-kanban-board.control.ts +74 -0
  403. package/src/ui/layout/kanban/sd-kanban-lane.control.ts +210 -0
  404. package/src/ui/layout/kanban/sd-kanban.control.ts +227 -0
  405. package/src/ui/layout/sd-card.directive.ts +10 -0
  406. package/src/ui/layout/sd-gap.control.ts +63 -0
  407. package/src/ui/layout/sd-pane.directive.ts +11 -0
  408. package/src/ui/layout/view/sd-view-item.control.ts +45 -0
  409. package/src/ui/layout/view/sd-view.control.ts +31 -0
  410. package/src/ui/navigation/collapse/sd-collapse-icon.control.ts +51 -0
  411. package/src/ui/navigation/collapse/sd-collapse.control.ts +75 -0
  412. package/src/ui/navigation/menu-utils.ts +36 -0
  413. package/src/ui/navigation/pagination/sd-pagination.control.ts +125 -0
  414. package/src/ui/navigation/sidebar/sd-sidebar-container.control.ts +92 -0
  415. package/src/ui/navigation/sidebar/sd-sidebar-menu.control.ts +129 -0
  416. package/src/ui/navigation/sidebar/sd-sidebar-user.control.ts +84 -0
  417. package/src/ui/navigation/sidebar/sd-sidebar.control.ts +67 -0
  418. package/src/ui/navigation/tab/sd-tab-item.control.ts +55 -0
  419. package/src/ui/navigation/tab/sd-tab.control.ts +25 -0
  420. package/src/ui/navigation/tab/sd-tabview-item.control.ts +48 -0
  421. package/src/ui/navigation/tab/sd-tabview.control.ts +39 -0
  422. package/src/ui/navigation/topbar/sd-topbar-container.control.ts +22 -0
  423. package/src/ui/navigation/topbar/sd-topbar-menu.control.ts +165 -0
  424. package/src/ui/navigation/topbar/sd-topbar-user.control.ts +58 -0
  425. package/src/ui/navigation/topbar/sd-topbar.control.ts +94 -0
  426. package/src/ui/overlay/busy/sd-busy-container.control.ts +243 -0
  427. package/src/ui/overlay/busy/sd-busy.provider.ts +55 -0
  428. package/src/ui/overlay/dropdown/sd-dropdown-popup.control.ts +110 -0
  429. package/src/ui/overlay/dropdown/sd-dropdown.control.ts +310 -0
  430. package/src/ui/overlay/modal/sd-confirm-modal.control.ts +66 -0
  431. package/src/ui/overlay/modal/sd-modal.control.ts +362 -0
  432. package/src/ui/overlay/modal/sd-modal.provider.ts +216 -0
  433. package/src/ui/overlay/modal/sd-prompt-modal.control.ts +92 -0
  434. package/src/ui/overlay/toast/sd-toast-container.control.ts +58 -0
  435. package/src/ui/overlay/toast/sd-toast.control.ts +123 -0
  436. package/src/ui/overlay/toast/sd-toast.provider.ts +302 -0
  437. package/src/ui/visual/sd-barcode.control.ts +62 -0
  438. package/src/ui/visual/sd-calendar.control.ts +188 -0
  439. package/src/ui/visual/sd-echarts.control.ts +73 -0
  440. package/src/ui/visual/sd-label.control.ts +66 -0
  441. package/src/ui/visual/sd-note.control.ts +66 -0
  442. package/src/ui/visual/sd-progress.control.ts +88 -0
@@ -0,0 +1,66 @@
1
+ import {
2
+ ChangeDetectionStrategy,
3
+ Component,
4
+ input,
5
+ output,
6
+ signal,
7
+ ViewEncapsulation,
8
+ } from "@angular/core";
9
+ import type { ISdModal } from "./sd-modal.provider";
10
+ import { SdButtonControl } from "../../form/button/sd-button.control";
11
+
12
+ /**
13
+ * 범용 확인 모달.
14
+ * ISdModal<boolean> 구현. message를 표시하고, 확인/취소.
15
+ * 확인 시 true emit, 취소 시 undefined emit.
16
+ */
17
+ @Component({
18
+ selector: "sd-confirm-modal",
19
+ changeDetection: ChangeDetectionStrategy.OnPush,
20
+ encapsulation: ViewEncapsulation.None,
21
+ standalone: true,
22
+ imports: [SdButtonControl],
23
+ template: `
24
+ <div class="_sd-confirm-modal">
25
+ <p class="_message">{{ message() }}</p>
26
+ <div class="_actions">
27
+ <sd-button [theme]="'primary'" (click)="onConfirm()">확인</sd-button>
28
+ <sd-button (click)="onCancel()">취소</sd-button>
29
+ </div>
30
+ </div>
31
+ `,
32
+ styles: [
33
+ /* language=SCSS */ `
34
+ sd-confirm-modal {
35
+ display: block;
36
+ padding: var(--gap-default);
37
+
38
+ > ._sd-confirm-modal {
39
+ > ._message {
40
+ margin-bottom: var(--gap-default);
41
+ }
42
+
43
+ > ._actions {
44
+ display: flex;
45
+ justify-content: flex-end;
46
+ gap: var(--gap-sm);
47
+ }
48
+ }
49
+ }
50
+ `,
51
+ ],
52
+ })
53
+ export class SdConfirmModalControl implements ISdModal<boolean> {
54
+ initialized = signal(true);
55
+ close = output<boolean | undefined>();
56
+
57
+ message = input.required<string>();
58
+
59
+ onConfirm(): void {
60
+ this.close.emit(true);
61
+ }
62
+
63
+ onCancel(): void {
64
+ this.close.emit(undefined);
65
+ }
66
+ }
@@ -0,0 +1,362 @@
1
+ import {
2
+ ChangeDetectionStrategy,
3
+ Component,
4
+ effect,
5
+ ElementRef,
6
+ inject,
7
+ input,
8
+ model,
9
+ output,
10
+ type TemplateRef,
11
+ ViewEncapsulation,
12
+ } from "@angular/core";
13
+ import { isTabbable } from "tabbable";
14
+ import { NgTemplateOutlet } from "@angular/common";
15
+ import { SdActivatedModalProvider } from "./sd-modal.provider";
16
+ import { SdSystemConfigProvider } from "../../../core/providers/sd-system-config.provider";
17
+ import "@simplysm/core-browser";
18
+
19
+ @Component({
20
+ selector: "sd-modal",
21
+ changeDetection: ChangeDetectionStrategy.OnPush,
22
+ encapsulation: ViewEncapsulation.None,
23
+ standalone: true,
24
+ imports: [NgTemplateOutlet],
25
+ host: {
26
+ "[attr.data-sd-open]": "open() || undefined",
27
+ "[attr.data-sd-float]": "float() || undefined",
28
+ "[attr.data-sd-fill]": "fill() || undefined",
29
+ "[attr.data-sd-position]": "position() || undefined",
30
+ },
31
+ template: `
32
+ <div class="_backdrop" (mousedown)="onBackdropClick()"></div>
33
+ <div class="_dialog" tabindex="-1"
34
+ (keydown)="onDialogKeydown($event)"
35
+ (focus)="onDialogFocus()">
36
+ @if (!hideHeader()) {
37
+ <div class="_header" (mousedown)="onHeaderMouseDown($event)">
38
+ <span class="_title">{{ title() }}</span>
39
+ @if (actionTplRef()) {
40
+ <ng-container *ngTemplateOutlet="actionTplRef()!" />
41
+ }
42
+ @if (!hideCloseButton()) {
43
+ <button class="_close-btn" (click)="onCloseButtonClick()">×</button>
44
+ }
45
+ </div>
46
+ }
47
+ <div class="_content"><ng-content /></div>
48
+ @if (resizable()) {
49
+ <div class="_resize-handle _resize-top" data-resize-dir="top" (mousedown)="onResizeMouseDown($event, 'top')"></div>
50
+ <div class="_resize-handle _resize-bottom" data-resize-dir="bottom" (mousedown)="onResizeMouseDown($event, 'bottom')"></div>
51
+ <div class="_resize-handle _resize-left" data-resize-dir="left" (mousedown)="onResizeMouseDown($event, 'left')"></div>
52
+ <div class="_resize-handle _resize-right" data-resize-dir="right" (mousedown)="onResizeMouseDown($event, 'right')"></div>
53
+ <div class="_resize-handle _resize-top-left" data-resize-dir="top-left" (mousedown)="onResizeMouseDown($event, 'top-left')"></div>
54
+ <div class="_resize-handle _resize-top-right" data-resize-dir="top-right" (mousedown)="onResizeMouseDown($event, 'top-right')"></div>
55
+ <div class="_resize-handle _resize-bottom-left" data-resize-dir="bottom-left" (mousedown)="onResizeMouseDown($event, 'bottom-left')"></div>
56
+ <div class="_resize-handle _resize-bottom-right" data-resize-dir="bottom-right" (mousedown)="onResizeMouseDown($event, 'bottom-right')"></div>
57
+ }
58
+ </div>
59
+ `,
60
+ })
61
+ export class SdModalControl {
62
+ private readonly _elRef = inject(ElementRef<HTMLElement>);
63
+ private readonly _activatedModal = inject(SdActivatedModalProvider, { optional: true });
64
+ private readonly _systemConfig = inject(SdSystemConfigProvider, { optional: true });
65
+
66
+ open = model(false);
67
+ key = input<string | undefined>(undefined);
68
+ title = input("");
69
+ hideHeader = input(false);
70
+ hideCloseButton = input(false);
71
+ useCloseByBackdrop = input(true);
72
+ useCloseByEscapeKey = input(true);
73
+ float = input(false);
74
+ fill = input(false);
75
+ resizable = input(false);
76
+ movable = input(false);
77
+ position = input<"bottom-right" | "top-right" | undefined>(undefined);
78
+ minHeightPx = input<number | undefined>(undefined);
79
+ minWidthPx = input<number | undefined>(undefined);
80
+ heightPx = input<number | undefined>(undefined);
81
+ widthPx = input<number | undefined>(undefined);
82
+ headerStyle = input<string | undefined>(undefined);
83
+ noFirstControlFocusing = input(false);
84
+ actionTplRef = input<TemplateRef<any> | undefined>(undefined);
85
+
86
+ closeRequest = output<void>();
87
+
88
+ private _dragState:
89
+ | { startX: number; startY: number; startLeft: number; startTop: number }
90
+ | undefined;
91
+
92
+ private _resizeState:
93
+ | {
94
+ dir: string;
95
+ startX: number;
96
+ startY: number;
97
+ startWidth: number;
98
+ startHeight: number;
99
+ startLeft: number;
100
+ startTop: number;
101
+ }
102
+ | undefined;
103
+
104
+ private readonly _onDocumentMouseMove: (event: MouseEvent) => void;
105
+ private readonly _onDocumentMouseUp: () => void;
106
+
107
+ constructor() {
108
+ // widthPx/heightPx를 dialog 스타일에 적용
109
+ effect(() => {
110
+ const dialogEl = this._getDialogEl();
111
+ if (dialogEl === null) return;
112
+
113
+ const w = this.widthPx();
114
+ const h = this.heightPx();
115
+ if (w !== undefined) {
116
+ dialogEl.style.width = `${w}px`;
117
+ }
118
+ if (h !== undefined) {
119
+ dialogEl.style.height = `${h}px`;
120
+ }
121
+ });
122
+
123
+ // key 기반 설정 복원
124
+ effect(() => {
125
+ const k = this.key();
126
+ if (k === undefined || this._systemConfig == null) return;
127
+
128
+ void this._restoreConfig(k);
129
+ });
130
+
131
+ // mousemove/mouseup을 document에 등록 (리사이즈 & 드래그 공용)
132
+ this._onDocumentMouseMove = (event: MouseEvent) => {
133
+ if (this._resizeState !== undefined) {
134
+ this._applyResize(event);
135
+ }
136
+ if (this._dragState !== undefined) {
137
+ this._applyDrag(event);
138
+ }
139
+ };
140
+ this._onDocumentMouseUp = () => {
141
+ const hadState = this._resizeState !== undefined || this._dragState !== undefined;
142
+ this._resizeState = undefined;
143
+ this._dragState = undefined;
144
+ document.removeEventListener("mousemove", this._onDocumentMouseMove);
145
+ document.removeEventListener("mouseup", this._onDocumentMouseUp);
146
+ if (hadState) {
147
+ void this._saveConfig();
148
+ }
149
+ };
150
+ }
151
+
152
+ onResizeMouseDown(event: MouseEvent, dir: string): void {
153
+ event.preventDefault();
154
+ const dialogEl = this._getDialogEl();
155
+ if (dialogEl === null) return;
156
+
157
+ this._resizeState = {
158
+ dir,
159
+ startX: event.clientX,
160
+ startY: event.clientY,
161
+ startWidth: dialogEl.offsetWidth,
162
+ startHeight: dialogEl.offsetHeight,
163
+ startLeft: dialogEl.offsetLeft,
164
+ startTop: dialogEl.offsetTop,
165
+ };
166
+ document.addEventListener("mousemove", this._onDocumentMouseMove);
167
+ document.addEventListener("mouseup", this._onDocumentMouseUp);
168
+ }
169
+
170
+ onHeaderMouseDown(event: MouseEvent): void {
171
+ if (!this.movable()) return;
172
+ if ((event.target as HTMLElement).closest("button") !== null) return;
173
+
174
+ event.preventDefault();
175
+ const dialogEl = this._getDialogEl();
176
+ if (dialogEl === null) return;
177
+
178
+ this._dragState = {
179
+ startX: event.clientX,
180
+ startY: event.clientY,
181
+ startLeft: dialogEl.offsetLeft,
182
+ startTop: dialogEl.offsetTop,
183
+ };
184
+ document.addEventListener("mousemove", this._onDocumentMouseMove);
185
+ document.addEventListener("mouseup", this._onDocumentMouseUp);
186
+ }
187
+
188
+ onBackdropClick(): void {
189
+ if (!this.useCloseByBackdrop()) return;
190
+ this._requestClose();
191
+ }
192
+
193
+ onCloseButtonClick(): void {
194
+ this._requestClose();
195
+ }
196
+
197
+ onDialogKeydown(event: KeyboardEvent): void {
198
+ if (event.key === "Escape") {
199
+ if (!this.useCloseByEscapeKey()) return;
200
+ this._requestClose();
201
+ } else if (event.key === "Tab") {
202
+ this._handleTabTrap(event);
203
+ }
204
+ }
205
+
206
+ onDialogFocus(): void {
207
+ this._bringToFront();
208
+ }
209
+
210
+ private _requestClose(): void {
211
+ if (this._activatedModal !== null && !this._activatedModal.canDeactivefn()) {
212
+ return;
213
+ }
214
+ void this._saveConfig();
215
+ this.closeRequest.emit();
216
+ }
217
+
218
+ private _handleTabTrap(event: KeyboardEvent): void {
219
+ const hostEl = this._elRef.nativeElement;
220
+ const focusableElements = this._getTabbableElements(hostEl);
221
+ if (focusableElements.length === 0) return;
222
+
223
+ const first = focusableElements[0];
224
+ const last = focusableElements[focusableElements.length - 1];
225
+
226
+ if (event.shiftKey) {
227
+ // Shift+Tab: 첫 요소에서 → 마지막 요소로
228
+ if (document.activeElement === first) {
229
+ event.preventDefault();
230
+ last.focus();
231
+ }
232
+ } else {
233
+ // Tab: 마지막 요소에서 → 첫 요소로
234
+ if (document.activeElement === last) {
235
+ event.preventDefault();
236
+ first.focus();
237
+ }
238
+ }
239
+ }
240
+
241
+ private _getTabbableElements(container: HTMLElement): HTMLElement[] {
242
+ const result: HTMLElement[] = [];
243
+ const walker = document.createTreeWalker(container, NodeFilter.SHOW_ELEMENT);
244
+ let node = walker.nextNode();
245
+ while (node !== null) {
246
+ if (node instanceof HTMLElement && isTabbable(node)) {
247
+ result.push(node);
248
+ }
249
+ node = walker.nextNode();
250
+ }
251
+ return result;
252
+ }
253
+
254
+ private _bringToFront(): void {
255
+ const hostEl = this._elRef.nativeElement;
256
+ const allModals = document.body.findAll<HTMLElement>("sd-modal");
257
+ let maxZ = 4000;
258
+ for (const m of allModals) {
259
+ if (m === hostEl) continue;
260
+ const z = parseInt(m.style.zIndex || "0", 10);
261
+ if (z > maxZ) {
262
+ maxZ = z;
263
+ }
264
+ }
265
+ hostEl.style.zIndex = String(maxZ + 1);
266
+ }
267
+
268
+ private _getDialogEl(): HTMLElement | null {
269
+ return this._elRef.nativeElement.querySelector("._dialog");
270
+ }
271
+
272
+ private _applyResize(event: MouseEvent): void {
273
+ const state = this._resizeState;
274
+ if (state === undefined) return;
275
+
276
+ const dialogEl = this._getDialogEl();
277
+ if (dialogEl === null) return;
278
+
279
+ const dx = event.clientX - state.startX;
280
+ const dy = event.clientY - state.startY;
281
+ const minW = this.minWidthPx() ?? 0;
282
+ const minH = this.minHeightPx() ?? 0;
283
+
284
+ let newWidth = state.startWidth;
285
+ let newHeight = state.startHeight;
286
+ let newLeft = state.startLeft;
287
+ let newTop = state.startTop;
288
+
289
+ if (state.dir.includes("right")) {
290
+ newWidth = Math.max(state.startWidth + dx, minW);
291
+ }
292
+ if (state.dir.includes("left")) {
293
+ const proposed = state.startWidth - dx;
294
+ if (proposed >= minW) {
295
+ newWidth = proposed;
296
+ newLeft = state.startLeft + dx;
297
+ }
298
+ }
299
+ if (state.dir.includes("bottom")) {
300
+ newHeight = Math.max(state.startHeight + dy, minH);
301
+ }
302
+ if (state.dir.includes("top")) {
303
+ const proposed = state.startHeight - dy;
304
+ if (proposed >= minH) {
305
+ newHeight = proposed;
306
+ newTop = state.startTop + dy;
307
+ }
308
+ }
309
+
310
+ dialogEl.style.width = `${newWidth}px`;
311
+ dialogEl.style.height = `${newHeight}px`;
312
+ dialogEl.style.left = `${newLeft}px`;
313
+ dialogEl.style.top = `${newTop}px`;
314
+ }
315
+
316
+ private _applyDrag(event: MouseEvent): void {
317
+ const state = this._dragState;
318
+ if (state === undefined) return;
319
+
320
+ const dialogEl = this._getDialogEl();
321
+ if (dialogEl === null) return;
322
+
323
+ const dx = event.clientX - state.startX;
324
+ const dy = event.clientY - state.startY;
325
+
326
+ dialogEl.style.left = `${state.startLeft + dx}px`;
327
+ dialogEl.style.top = `${state.startTop + dy}px`;
328
+ }
329
+
330
+ private async _saveConfig(): Promise<void> {
331
+ const k = this.key();
332
+ if (k === undefined || this._systemConfig == null) return;
333
+
334
+ const dialogEl = this._getDialogEl();
335
+ if (dialogEl === null) return;
336
+
337
+ const config: Record<string, string> = {};
338
+ if (dialogEl.style.width !== "") config["width"] = dialogEl.style.width;
339
+ if (dialogEl.style.height !== "") config["height"] = dialogEl.style.height;
340
+ if (dialogEl.style.left !== "") config["left"] = dialogEl.style.left;
341
+ if (dialogEl.style.top !== "") config["top"] = dialogEl.style.top;
342
+
343
+ await this._systemConfig.setAsync(`sd-modal.${k}` as any, config as any);
344
+ }
345
+
346
+ private async _restoreConfig(k: string): Promise<void> {
347
+ if (this._systemConfig == null) return;
348
+
349
+ const config = (await this._systemConfig.getAsync(`sd-modal.${k}` as any)) as
350
+ | Record<string, string | undefined>
351
+ | undefined;
352
+ if (config == null) return;
353
+
354
+ const dialogEl = this._getDialogEl();
355
+ if (dialogEl === null) return;
356
+
357
+ if (config["width"] !== undefined) dialogEl.style.width = config["width"];
358
+ if (config["height"] !== undefined) dialogEl.style.height = config["height"];
359
+ if (config["left"] !== undefined) dialogEl.style.left = config["left"];
360
+ if (config["top"] !== undefined) dialogEl.style.top = config["top"];
361
+ }
362
+ }
@@ -0,0 +1,216 @@
1
+ import {
2
+ ApplicationRef,
3
+ createComponent,
4
+ EnvironmentInjector,
5
+ inject,
6
+ Injectable,
7
+ Injector,
8
+ signal,
9
+ type ComponentRef,
10
+ type OutputEmitterRef,
11
+ type Signal,
12
+ type TemplateRef,
13
+ type Type,
14
+ } from "@angular/core";
15
+ import { outputToObservable } from "@angular/core/rxjs-interop";
16
+ import { Subscription } from "rxjs";
17
+ import type { TDirectiveInputSignals } from "../../../core/utils/TDirectiveInputSignals";
18
+ import { SdModalControl } from "./sd-modal.control";
19
+ import "@simplysm/core-browser";
20
+
21
+ /**
22
+ * 모달 컴포넌트가 구현해야 하는 인터페이스
23
+ */
24
+ export interface ISdModal<O> {
25
+ initialized: Signal<boolean>;
26
+ close: OutputEmitterRef<O | undefined>;
27
+ actionTplRef?: TemplateRef<any>;
28
+ }
29
+
30
+ /**
31
+ * 모달 생성 시 전달하는 정보
32
+ */
33
+ export interface ISdModalInfo<T extends ISdModal<any>> {
34
+ title: string;
35
+ type: Type<T>;
36
+ inputs: Omit<TDirectiveInputSignals<T>, "initialized" | "close" | "actionTplRef">;
37
+ }
38
+
39
+ /**
40
+ * 모달 옵션
41
+ */
42
+ export interface ISdModalOptions {
43
+ key?: string;
44
+ hideHeader?: boolean;
45
+ hideCloseButton?: boolean;
46
+ useCloseByBackdrop?: boolean;
47
+ useCloseByEscapeKey?: boolean;
48
+ float?: boolean;
49
+ fill?: boolean;
50
+ resizable?: boolean;
51
+ movable?: boolean;
52
+ position?: "bottom-right" | "top-right";
53
+ minHeightPx?: number;
54
+ minWidthPx?: number;
55
+ heightPx?: number;
56
+ widthPx?: number;
57
+ headerStyle?: string;
58
+ noFirstControlFocusing?: boolean;
59
+ }
60
+
61
+ /**
62
+ * 모달 내부에서 inject하여 사용하는 프로바이더
63
+ */
64
+ @Injectable()
65
+ export class SdActivatedModalProvider<T extends ISdModal<any> = ISdModal<any>> {
66
+ modalComponent = signal<any>(undefined);
67
+ contentComponent = signal<T | undefined>(undefined);
68
+ canDeactivefn: () => boolean = () => true;
69
+ }
70
+
71
+ /**
72
+ * 모달을 프로그래밍 방식으로 생성하는 프로바이더
73
+ */
74
+ @Injectable({ providedIn: "root" })
75
+ export class SdModalProvider {
76
+ private readonly _appRef = inject(ApplicationRef);
77
+ private readonly _envInjector = inject(EnvironmentInjector);
78
+ private readonly _injector = inject(Injector);
79
+
80
+ modalCount = signal(0);
81
+
82
+ async showAsync<T extends ISdModal<any>>(
83
+ modal: ISdModalInfo<T>,
84
+ options?: ISdModalOptions,
85
+ ): Promise<Parameters<T["close"]["emit"]>[0] | undefined> {
86
+ return new Promise<Parameters<T["close"]["emit"]>[0] | undefined>((resolve) => {
87
+ // 1. modalCount 증가
88
+ this.modalCount.update((v) => v + 1);
89
+
90
+ // 2. SdActivatedModalProvider 인스턴스 생성
91
+ const activatedModal = new SdActivatedModalProvider<T>();
92
+
93
+ // 3. 컨텐츠 컴포넌트 생성 (elementInjector에 SdActivatedModalProvider 주입)
94
+ const contentInjector = Injector.create({
95
+ providers: [{ provide: SdActivatedModalProvider, useValue: activatedModal }],
96
+ parent: this._injector,
97
+ });
98
+
99
+ const contentRef: ComponentRef<T> = createComponent(modal.type, {
100
+ environmentInjector: this._envInjector,
101
+ elementInjector: contentInjector,
102
+ });
103
+
104
+ // 4. setInput으로 inputs 바인딩
105
+ for (const [key, value] of Object.entries(modal.inputs as Record<string, unknown>)) {
106
+ contentRef.setInput(key, value);
107
+ }
108
+
109
+ // 5. SdModalControl 생성 (projectableNodes로 컨텐츠 삽입)
110
+ const modalRef: ComponentRef<SdModalControl> = createComponent(SdModalControl, {
111
+ environmentInjector: this._envInjector,
112
+ elementInjector: contentInjector,
113
+ projectableNodes: [[contentRef.location.nativeElement]],
114
+ });
115
+
116
+ // 6. 옵션 바인딩
117
+ modalRef.setInput("title", modal.title);
118
+ if (options !== undefined) {
119
+ for (const [key, value] of Object.entries(options)) {
120
+ if (value !== undefined) {
121
+ modalRef.setInput(key, value);
122
+ }
123
+ }
124
+ }
125
+
126
+ // 7. SdActivatedModalProvider에 컴포넌트 참조 설정
127
+ activatedModal.modalComponent.set(modalRef.instance);
128
+ activatedModal.contentComponent.set(contentRef.instance);
129
+
130
+ // 8. appRef에 뷰 등록 + body에 삽입
131
+ this._appRef.attachView(contentRef.hostView);
132
+ this._appRef.attachView(modalRef.hostView);
133
+ document.body.appendChild(modalRef.location.nativeElement);
134
+
135
+ // 9. open 설정 + z-index
136
+ modalRef.instance.open.set(true);
137
+ this._assignZIndex(modalRef.location.nativeElement);
138
+
139
+ // 10. 포커스 저장 및 설정
140
+ const prevActiveEl = document.activeElement as HTMLElement | null;
141
+
142
+ // 지연된 포커스 설정 (DOM 삽입 후 렌더링 완료 대기)
143
+ queueMicrotask(() => {
144
+ const modalEl = modalRef.location.nativeElement as HTMLElement;
145
+ const dialogEl = modalEl.querySelector<HTMLElement>("._dialog");
146
+ if (dialogEl == null) return;
147
+
148
+ if (options?.noFirstControlFocusing === true) {
149
+ dialogEl.focus();
150
+ } else {
151
+ // 컨텐츠 영역에서 첫 포커스 가능 요소 검색
152
+ const contentEl = modalEl.querySelector("._content");
153
+ const firstFocusable = contentEl?.findFirstFocusableChild();
154
+ if (firstFocusable !== undefined) {
155
+ firstFocusable.focus();
156
+ } else {
157
+ dialogEl.focus();
158
+ }
159
+ }
160
+ });
161
+
162
+ // cleanup 함수
163
+ let closeSub: Subscription | undefined;
164
+ let closeRequestSub: Subscription | undefined;
165
+
166
+ const cleanup = (result: Parameters<T["close"]["emit"]>[0] | undefined) => {
167
+ closeSub?.unsubscribe();
168
+ closeRequestSub?.unsubscribe();
169
+
170
+ // DOM에서 제거
171
+ const modalEl = modalRef.location.nativeElement as HTMLElement;
172
+ if (modalEl.parentNode !== null) {
173
+ modalEl.parentNode.removeChild(modalEl);
174
+ }
175
+
176
+ // 뷰 분리 + 파괴
177
+ this._appRef.detachView(modalRef.hostView);
178
+ this._appRef.detachView(contentRef.hostView);
179
+ modalRef.destroy();
180
+ contentRef.destroy();
181
+
182
+ // modalCount 감소
183
+ this.modalCount.update((v) => v - 1);
184
+
185
+ // 포커스 복귀
186
+ if (prevActiveEl !== null && prevActiveEl.isConnected) {
187
+ prevActiveEl.focus();
188
+ }
189
+
190
+ resolve(result);
191
+ };
192
+
193
+ // 10. close output 구독 (컨텐츠 컴포넌트가 직접 close.emit 호출)
194
+ closeSub = outputToObservable(contentRef.instance.close).subscribe((result) => {
195
+ cleanup(result);
196
+ });
197
+
198
+ // 12. SdModalControl의 closeRequest 구독 (배경 클릭, ESC, 닫기 버튼)
199
+ closeRequestSub = outputToObservable(modalRef.instance.closeRequest).subscribe(() => {
200
+ cleanup(undefined);
201
+ });
202
+ });
203
+ }
204
+
205
+ private _assignZIndex(el: HTMLElement): void {
206
+ const allModals = document.body.findAll<HTMLElement>("sd-modal");
207
+ let maxZ = 4000;
208
+ for (const m of allModals) {
209
+ const z = parseInt(m.style.zIndex || "0", 10);
210
+ if (z > maxZ) {
211
+ maxZ = z;
212
+ }
213
+ }
214
+ el.style.zIndex = String(maxZ + 1);
215
+ }
216
+ }