@simplysm/angular 14.0.8 → 14.0.9

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 (272) hide show
  1. package/README.md +234 -246
  2. package/dist/core/commons.d.ts.map +1 -1
  3. package/dist/core/directives/sd-events.directive.d.ts.map +1 -1
  4. package/dist/core/directives/sd-invalid.directive.d.ts.map +1 -1
  5. package/dist/core/directives/sd-item-of-template.directive.d.ts.map +1 -1
  6. package/dist/core/directives/sd-ripple.directive.d.ts.map +1 -1
  7. package/dist/core/directives/sd-router-link.directive.d.ts.map +1 -1
  8. package/dist/core/directives/sd-show-effect.directive.d.ts.map +1 -1
  9. package/dist/core/directives/sd-typed-template.directive.d.ts.map +1 -1
  10. package/dist/core/pipes/format.pipe.d.ts.map +1 -1
  11. package/dist/core/plugins/commands/findTopOpenModalEl.d.ts.map +1 -1
  12. package/dist/core/plugins/commands/sd-insert-command-event.plugin.d.ts.map +1 -1
  13. package/dist/core/plugins/commands/sd-refresh-command-event.plugin.d.ts.map +1 -1
  14. package/dist/core/plugins/commands/sd-save-command-event.plugin.d.ts.map +1 -1
  15. package/dist/core/plugins/events/sd-intersection-event.plugin.d.ts.map +1 -1
  16. package/dist/core/plugins/events/sd-option-event.plugin.d.ts.map +1 -1
  17. package/dist/core/plugins/events/sd-resize-event.plugin.d.ts.map +1 -1
  18. package/dist/core/plugins/sd-global-error-handler.plugin.d.ts.map +1 -1
  19. package/dist/core/provideSdAngular.d.ts.map +1 -1
  20. package/dist/core/providers/sd-angular-config.provider.d.ts.map +1 -1
  21. package/dist/core/providers/sd-app-structure.provider.d.ts.map +1 -1
  22. package/dist/core/providers/sd-file-dialog.provider.d.ts.map +1 -1
  23. package/dist/core/providers/sd-local-storage.provider.d.ts.map +1 -1
  24. package/dist/core/providers/sd-navigate-window.provider.d.ts.map +1 -1
  25. package/dist/core/providers/sd-print.provider.d.ts +7 -2
  26. package/dist/core/providers/sd-print.provider.d.ts.map +1 -1
  27. package/dist/core/providers/sd-service-client-factory.provider.d.ts.map +1 -1
  28. package/dist/core/providers/sd-shared-data.provider.d.ts +3 -0
  29. package/dist/core/providers/sd-shared-data.provider.d.ts.map +1 -1
  30. package/dist/core/providers/sd-system-config.provider.d.ts.map +1 -1
  31. package/dist/core/providers/sd-system-log.provider.d.ts.map +1 -1
  32. package/dist/core/providers/sd-theme-provider.d.ts.map +1 -1
  33. package/dist/core/utils/TDirectiveInputSignals.d.ts +4 -0
  34. package/dist/core/utils/TDirectiveInputSignals.d.ts.map +1 -1
  35. package/dist/core/utils/injectParent.d.ts.map +1 -1
  36. package/dist/core/utils/setSafeStyle.d.ts.map +1 -1
  37. package/dist/core/utils/setups/setupBgTheme.d.ts.map +1 -1
  38. package/dist/core/utils/setups/setupCanDeactivate.d.ts.map +1 -1
  39. package/dist/core/utils/setups/setupCloserWhenSingleSelectionChange.d.ts +9 -0
  40. package/dist/core/utils/setups/setupCloserWhenSingleSelectionChange.d.ts.map +1 -0
  41. package/dist/core/utils/setups/setupCloserWhenSingleSelectionChange.js +20 -0
  42. package/dist/core/utils/setups/setupCumulateSelectedKeys.d.ts +9 -0
  43. package/dist/core/utils/setups/setupCumulateSelectedKeys.d.ts.map +1 -0
  44. package/dist/core/utils/setups/setupCumulateSelectedKeys.js +27 -0
  45. package/dist/core/utils/setups/setupInvalid.d.ts.map +1 -1
  46. package/dist/core/utils/setups/setupModelHook.d.ts.map +1 -1
  47. package/dist/core/utils/setups/setupRevealOnShow.d.ts.map +1 -1
  48. package/dist/core/utils/setups/setupRipple.d.ts.map +1 -1
  49. package/dist/core/utils/useCurrentPageCodeSignal.d.ts.map +1 -1
  50. package/dist/core/utils/useExpandingManager.d.ts.map +1 -1
  51. package/dist/core/utils/useFullPageCodeSignal.d.ts.map +1 -1
  52. package/dist/core/utils/useSdSystemConfigResource.d.ts.map +1 -1
  53. package/dist/core/utils/useSelectionManager.d.ts.map +1 -1
  54. package/dist/core/utils/useSortingManager.d.ts.map +1 -1
  55. package/dist/core/utils/useViewTitleSignal.d.ts.map +1 -1
  56. package/dist/core/utils/useViewTypeSignal.d.ts.map +1 -1
  57. package/dist/features/address/sd-address-search.modal.d.ts +19 -0
  58. package/dist/features/address/sd-address-search.modal.d.ts.map +1 -0
  59. package/dist/features/address/sd-address-search.modal.js +88 -0
  60. package/dist/features/base/sd-base-container.control.d.ts.map +1 -1
  61. package/dist/features/base/sd-base-container.control.js +1 -1
  62. package/dist/features/data-view/sd-data-detail.control.d.ts +70 -0
  63. package/dist/features/data-view/sd-data-detail.control.d.ts.map +1 -0
  64. package/dist/features/data-view/sd-data-detail.control.js +606 -0
  65. package/dist/features/data-view/sd-data-select-button.control.d.ts +35 -0
  66. package/dist/features/data-view/sd-data-select-button.control.d.ts.map +1 -0
  67. package/dist/features/data-view/sd-data-select-button.control.js +219 -0
  68. package/dist/features/data-view/sd-data-sheet-column.directive.d.ts +8 -0
  69. package/dist/features/data-view/sd-data-sheet-column.directive.d.ts.map +1 -0
  70. package/dist/features/data-view/sd-data-sheet-column.directive.js +15 -0
  71. package/dist/features/data-view/sd-data-sheet.control.d.ts +131 -0
  72. package/dist/features/data-view/sd-data-sheet.control.d.ts.map +1 -0
  73. package/dist/features/data-view/sd-data-sheet.control.js +1152 -0
  74. package/dist/features/shared-data/sd-shared-data-select-button.control.d.ts +16 -0
  75. package/dist/features/shared-data/sd-shared-data-select-button.control.d.ts.map +1 -0
  76. package/dist/features/shared-data/sd-shared-data-select-button.control.js +66 -0
  77. package/dist/features/shared-data/sd-shared-data-select-list.control.d.ts +33 -0
  78. package/dist/features/shared-data/sd-shared-data-select-list.control.d.ts.map +1 -0
  79. package/dist/features/shared-data/sd-shared-data-select-list.control.js +346 -0
  80. package/dist/features/shared-data/sd-shared-data-select.control.d.ts +50 -0
  81. package/dist/features/shared-data/sd-shared-data-select.control.d.ts.map +1 -0
  82. package/dist/features/shared-data/sd-shared-data-select.control.js +425 -0
  83. package/dist/index.d.ts +11 -1
  84. package/dist/index.d.ts.map +1 -1
  85. package/dist/index.js +12 -0
  86. package/dist/ui/data/list/sd-list-item.control.d.ts +3 -1
  87. package/dist/ui/data/list/sd-list-item.control.d.ts.map +1 -1
  88. package/dist/ui/data/list/sd-list-item.control.js +8 -4
  89. package/dist/ui/data/list/sd-list.control.d.ts.map +1 -1
  90. package/dist/ui/data/list/sd-list.control.js +1 -1
  91. package/dist/ui/data/sheet/sd-sheet-column.directive.d.ts +8 -1
  92. package/dist/ui/data/sheet/sd-sheet-column.directive.d.ts.map +1 -1
  93. package/dist/ui/data/sheet/sd-sheet-config.modal.d.ts.map +1 -1
  94. package/dist/ui/data/sheet/sd-sheet-config.modal.js +1 -1
  95. package/dist/ui/data/sheet/sd-sheet.control.d.ts +4 -4
  96. package/dist/ui/data/sheet/sd-sheet.control.d.ts.map +1 -1
  97. package/dist/ui/data/sheet/sd-sheet.control.js +3 -4
  98. package/dist/ui/data/sheet/types.d.ts.map +1 -1
  99. package/dist/ui/data/sheet/useSheetCellAgent.d.ts.map +1 -1
  100. package/dist/ui/data/sheet/useSheetColumnFixing.d.ts.map +1 -1
  101. package/dist/ui/data/sheet/useSheetDomAccessor.d.ts.map +1 -1
  102. package/dist/ui/data/sheet/useSheetLayoutEngine.d.ts.map +1 -1
  103. package/dist/ui/form/button/sd-additional-button.control.d.ts.map +1 -1
  104. package/dist/ui/form/button/sd-additional-button.control.js +1 -1
  105. package/dist/ui/form/button/sd-anchor.control.d.ts.map +1 -1
  106. package/dist/ui/form/button/sd-anchor.control.js +1 -1
  107. package/dist/ui/form/button/sd-button.control.d.ts.map +1 -1
  108. package/dist/ui/form/button/sd-button.control.js +1 -1
  109. package/dist/ui/form/button/sd-modal-select-button.control.d.ts +16 -18
  110. package/dist/ui/form/button/sd-modal-select-button.control.d.ts.map +1 -1
  111. package/dist/ui/form/button/sd-modal-select-button.control.js +22 -39
  112. package/dist/ui/form/checkbox/sd-checkbox-group-item.control.d.ts.map +1 -1
  113. package/dist/ui/form/checkbox/sd-checkbox-group-item.control.js +1 -1
  114. package/dist/ui/form/checkbox/sd-checkbox-group.control.d.ts.map +1 -1
  115. package/dist/ui/form/checkbox/sd-checkbox-group.control.js +1 -1
  116. package/dist/ui/form/checkbox/sd-checkbox.control.d.ts.map +1 -1
  117. package/dist/ui/form/checkbox/sd-checkbox.control.js +1 -1
  118. package/dist/ui/form/checkbox/sd-switch.control.d.ts.map +1 -1
  119. package/dist/ui/form/checkbox/sd-switch.control.js +1 -1
  120. package/dist/ui/form/choice/sd-state-preset.control.d.ts.map +1 -1
  121. package/dist/ui/form/choice/sd-state-preset.control.js +1 -1
  122. package/dist/ui/form/editor/sd-tiptap-editor.control.d.ts +18 -1
  123. package/dist/ui/form/editor/sd-tiptap-editor.control.d.ts.map +1 -1
  124. package/dist/ui/form/editor/sd-tiptap-editor.control.js +18 -2
  125. package/dist/ui/form/input/sd-date-range.picker.d.ts.map +1 -1
  126. package/dist/ui/form/input/sd-date-range.picker.js +1 -1
  127. package/dist/ui/form/input/sd-numpad.control.d.ts.map +1 -1
  128. package/dist/ui/form/input/sd-numpad.control.js +1 -1
  129. package/dist/ui/form/input/sd-range.control.d.ts.map +1 -1
  130. package/dist/ui/form/input/sd-range.control.js +1 -1
  131. package/dist/ui/form/input/sd-textarea.control.d.ts.map +1 -1
  132. package/dist/ui/form/input/sd-textarea.control.js +1 -1
  133. package/dist/ui/form/input/sd-textfield-type-handlers.d.ts.map +1 -1
  134. package/dist/ui/form/input/sd-textfield.control.d.ts.map +1 -1
  135. package/dist/ui/form/input/sd-textfield.control.js +1 -1
  136. package/dist/ui/form/sd-form.control.d.ts.map +1 -1
  137. package/dist/ui/form/sd-form.control.js +1 -1
  138. package/dist/ui/form/select/sd-select-button.control.d.ts.map +1 -1
  139. package/dist/ui/form/select/sd-select-button.control.js +1 -1
  140. package/dist/ui/form/select/sd-select-item.control.d.ts +1 -1
  141. package/dist/ui/form/select/sd-select-item.control.d.ts.map +1 -1
  142. package/dist/ui/form/select/sd-select-item.control.js +1 -1
  143. package/dist/ui/form/select/sd-select.control.d.ts +9 -6
  144. package/dist/ui/form/select/sd-select.control.d.ts.map +1 -1
  145. package/dist/ui/form/select/sd-select.control.js +1 -1
  146. package/dist/ui/layout/dock/sd-dock-container.control.d.ts.map +1 -1
  147. package/dist/ui/layout/dock/sd-dock-container.control.js +1 -1
  148. package/dist/ui/layout/dock/sd-dock.control.d.ts.map +1 -1
  149. package/dist/ui/layout/dock/sd-dock.control.js +1 -1
  150. package/dist/ui/layout/kanban/sd-kanban-board.control.d.ts.map +1 -1
  151. package/dist/ui/layout/kanban/sd-kanban-board.control.js +1 -1
  152. package/dist/ui/layout/kanban/sd-kanban-lane.control.d.ts.map +1 -1
  153. package/dist/ui/layout/kanban/sd-kanban-lane.control.js +1 -1
  154. package/dist/ui/layout/kanban/sd-kanban.control.d.ts.map +1 -1
  155. package/dist/ui/layout/kanban/sd-kanban.control.js +1 -1
  156. package/dist/ui/layout/sd-card.directive.d.ts.map +1 -1
  157. package/dist/ui/layout/sd-gap.control.d.ts.map +1 -1
  158. package/dist/ui/layout/sd-gap.control.js +1 -1
  159. package/dist/ui/layout/sd-pane.directive.d.ts.map +1 -1
  160. package/dist/ui/layout/view/sd-view-item.control.d.ts.map +1 -1
  161. package/dist/ui/layout/view/sd-view-item.control.js +1 -1
  162. package/dist/ui/layout/view/sd-view.control.d.ts.map +1 -1
  163. package/dist/ui/layout/view/sd-view.control.js +1 -1
  164. package/dist/ui/navigation/collapse/sd-collapse-icon.control.d.ts.map +1 -1
  165. package/dist/ui/navigation/collapse/sd-collapse-icon.control.js +1 -1
  166. package/dist/ui/navigation/collapse/sd-collapse.control.d.ts.map +1 -1
  167. package/dist/ui/navigation/collapse/sd-collapse.control.js +1 -1
  168. package/dist/ui/navigation/menu-utils.d.ts.map +1 -1
  169. package/dist/ui/navigation/pagination/sd-pagination.control.d.ts.map +1 -1
  170. package/dist/ui/navigation/pagination/sd-pagination.control.js +1 -1
  171. package/dist/ui/navigation/sidebar/sd-sidebar-container.control.d.ts.map +1 -1
  172. package/dist/ui/navigation/sidebar/sd-sidebar-container.control.js +1 -1
  173. package/dist/ui/navigation/sidebar/sd-sidebar-menu.control.d.ts.map +1 -1
  174. package/dist/ui/navigation/sidebar/sd-sidebar-menu.control.js +1 -1
  175. package/dist/ui/navigation/sidebar/sd-sidebar-user.control.d.ts.map +1 -1
  176. package/dist/ui/navigation/sidebar/sd-sidebar-user.control.js +1 -1
  177. package/dist/ui/navigation/sidebar/sd-sidebar.control.d.ts.map +1 -1
  178. package/dist/ui/navigation/sidebar/sd-sidebar.control.js +1 -1
  179. package/dist/ui/navigation/tab/sd-tab-item.control.d.ts.map +1 -1
  180. package/dist/ui/navigation/tab/sd-tab-item.control.js +1 -1
  181. package/dist/ui/navigation/tab/sd-tab.control.d.ts.map +1 -1
  182. package/dist/ui/navigation/tab/sd-tab.control.js +1 -1
  183. package/dist/ui/navigation/tab/sd-tabview-item.control.d.ts.map +1 -1
  184. package/dist/ui/navigation/tab/sd-tabview-item.control.js +1 -1
  185. package/dist/ui/navigation/tab/sd-tabview.control.d.ts.map +1 -1
  186. package/dist/ui/navigation/tab/sd-tabview.control.js +1 -1
  187. package/dist/ui/navigation/topbar/sd-topbar-container.control.d.ts.map +1 -1
  188. package/dist/ui/navigation/topbar/sd-topbar-container.control.js +1 -1
  189. package/dist/ui/navigation/topbar/sd-topbar-menu.control.d.ts.map +1 -1
  190. package/dist/ui/navigation/topbar/sd-topbar-menu.control.js +1 -1
  191. package/dist/ui/navigation/topbar/sd-topbar-user.control.d.ts.map +1 -1
  192. package/dist/ui/navigation/topbar/sd-topbar-user.control.js +1 -1
  193. package/dist/ui/navigation/topbar/sd-topbar.control.d.ts.map +1 -1
  194. package/dist/ui/navigation/topbar/sd-topbar.control.js +1 -1
  195. package/dist/ui/overlay/busy/sd-busy-container.control.d.ts.map +1 -1
  196. package/dist/ui/overlay/busy/sd-busy-container.control.js +1 -1
  197. package/dist/ui/overlay/busy/sd-busy.provider.d.ts.map +1 -1
  198. package/dist/ui/overlay/dropdown/sd-dropdown-popup.control.d.ts.map +1 -1
  199. package/dist/ui/overlay/dropdown/sd-dropdown-popup.control.js +1 -1
  200. package/dist/ui/overlay/dropdown/sd-dropdown.control.d.ts.map +1 -1
  201. package/dist/ui/overlay/dropdown/sd-dropdown.control.js +1 -1
  202. package/dist/ui/overlay/modal/sd-confirm-modal.control.d.ts.map +1 -1
  203. package/dist/ui/overlay/modal/sd-confirm-modal.control.js +1 -1
  204. package/dist/ui/overlay/modal/sd-modal.control.d.ts.map +1 -1
  205. package/dist/ui/overlay/modal/sd-modal.control.js +1 -1
  206. package/dist/ui/overlay/modal/sd-modal.provider.d.ts +9 -3
  207. package/dist/ui/overlay/modal/sd-modal.provider.d.ts.map +1 -1
  208. package/dist/ui/overlay/modal/sd-prompt-modal.control.d.ts.map +1 -1
  209. package/dist/ui/overlay/modal/sd-prompt-modal.control.js +1 -1
  210. package/dist/ui/overlay/toast/sd-toast-container.control.d.ts.map +1 -1
  211. package/dist/ui/overlay/toast/sd-toast-container.control.js +1 -1
  212. package/dist/ui/overlay/toast/sd-toast.control.d.ts.map +1 -1
  213. package/dist/ui/overlay/toast/sd-toast.control.js +1 -1
  214. package/dist/ui/overlay/toast/sd-toast.provider.d.ts.map +1 -1
  215. package/dist/ui/visual/sd-barcode.control.d.ts.map +1 -1
  216. package/dist/ui/visual/sd-barcode.control.js +1 -1
  217. package/dist/ui/visual/sd-calendar.control.d.ts.map +1 -1
  218. package/dist/ui/visual/sd-calendar.control.js +1 -1
  219. package/dist/ui/visual/sd-echarts.control.d.ts.map +1 -1
  220. package/dist/ui/visual/sd-echarts.control.js +1 -1
  221. package/dist/ui/visual/sd-label.control.d.ts.map +1 -1
  222. package/dist/ui/visual/sd-label.control.js +1 -1
  223. package/dist/ui/visual/sd-note.control.d.ts.map +1 -1
  224. package/dist/ui/visual/sd-note.control.js +1 -1
  225. package/dist/ui/visual/sd-progress.control.d.ts.map +1 -1
  226. package/dist/ui/visual/sd-progress.control.js +1 -1
  227. package/docs/core.md +877 -0
  228. package/docs/features.md +377 -0
  229. package/docs/styling.md +309 -0
  230. package/docs/ui-data.md +233 -0
  231. package/docs/ui-form.md +421 -0
  232. package/docs/ui-layout.md +216 -0
  233. package/docs/ui-navigation.md +279 -0
  234. package/docs/ui-overlay.md +330 -0
  235. package/docs/ui-visual.md +131 -0
  236. package/package.json +5 -5
  237. package/src/core/providers/sd-print.provider.ts +10 -2
  238. package/src/core/providers/sd-shared-data.provider.ts +3 -0
  239. package/src/core/utils/TDirectiveInputSignals.ts +5 -0
  240. package/src/core/utils/setups/setupCloserWhenSingleSelectionChange.ts +29 -0
  241. package/src/core/utils/setups/setupCumulateSelectedKeys.ts +38 -0
  242. package/src/features/address/sd-address-search.modal.ts +119 -0
  243. package/src/features/data-view/sd-data-detail.control.ts +394 -0
  244. package/src/features/data-view/sd-data-select-button.control.ts +210 -0
  245. package/src/features/data-view/sd-data-sheet-column.directive.ts +10 -0
  246. package/src/features/data-view/sd-data-sheet.control.ts +850 -0
  247. package/src/features/shared-data/sd-shared-data-select-button.control.ts +64 -0
  248. package/src/features/shared-data/sd-shared-data-select-list.control.ts +245 -0
  249. package/src/features/shared-data/sd-shared-data-select.control.ts +364 -0
  250. package/src/index.ts +35 -1
  251. package/src/scss.d.ts +5 -0
  252. package/src/ui/data/list/sd-list-item.control.ts +3 -1
  253. package/src/ui/data/sheet/sd-sheet-column.directive.ts +9 -1
  254. package/src/ui/data/sheet/sd-sheet.control.ts +6 -6
  255. package/src/ui/form/button/sd-modal-select-button.control.ts +41 -59
  256. package/src/ui/form/editor/sd-tiptap-editor.control.ts +35 -1
  257. package/src/ui/form/select/sd-select-item.control.ts +1 -1
  258. package/src/ui/form/select/sd-select.control.ts +7 -4
  259. package/src/ui/overlay/modal/sd-modal.provider.ts +15 -3
  260. package/docs/commons-and-configuration.md +0 -34
  261. package/docs/data-display-components.md +0 -146
  262. package/docs/directives.md +0 -158
  263. package/docs/event-plugins.md +0 -109
  264. package/docs/form-components.md +0 -362
  265. package/docs/hooks-and-utilities.md +0 -175
  266. package/docs/layout-components.md +0 -140
  267. package/docs/navigation-components.md +0 -200
  268. package/docs/overlay-components.md +0 -193
  269. package/docs/pipes.md +0 -25
  270. package/docs/providers.md +0 -448
  271. package/docs/setup-functions.md +0 -66
  272. package/docs/visual-components.md +0 -89
@@ -0,0 +1,64 @@
1
+ import { NgTemplateOutlet } from "@angular/common";
2
+ import {
3
+ ChangeDetectionStrategy,
4
+ Component,
5
+ contentChild,
6
+ input,
7
+ TemplateRef,
8
+ ViewEncapsulation,
9
+ } from "@angular/core";
10
+ import type { ISharedDataBase } from "../../core/providers/sd-shared-data.provider";
11
+ import {
12
+ SdItemOfTemplateDirective,
13
+ type SdItemOfTemplateContext,
14
+ } from "../../core/directives/sd-item-of-template.directive";
15
+ import {
16
+ AbsSdDataSelectButton,
17
+ SdDataSelectButtonControl,
18
+ } from "../data-view/sd-data-select-button.control";
19
+ import type {
20
+ ISdSelectModal,
21
+ TSdSelectModalInfo,
22
+ } from "../../ui/form/button/sd-modal-select-button.control";
23
+ import type { TSelectModeValue } from "../../ui/form/select/sd-select.control";
24
+
25
+ @Component({
26
+ selector: "sd-shared-data-select-button",
27
+ changeDetection: ChangeDetectionStrategy.OnPush,
28
+ encapsulation: ViewEncapsulation.None,
29
+ standalone: true,
30
+ imports: [SdDataSelectButtonControl, NgTemplateOutlet, SdItemOfTemplateDirective],
31
+ template: `
32
+ <sd-data-select-button>
33
+ <ng-template [itemOf]="items()" let-item let-index="index">
34
+ <ng-template
35
+ [ngTemplateOutlet]="itemTplRef()"
36
+ [ngTemplateOutletContext]="{
37
+ $implicit: item,
38
+ item: item,
39
+ index: index,
40
+ depth: 0,
41
+ }"
42
+ />
43
+ </ng-template>
44
+ <ng-content />
45
+ </sd-data-select-button>
46
+ `,
47
+ })
48
+ export class SdSharedDataSelectButtonControl<
49
+ TItem extends ISharedDataBase<number>,
50
+ TMode extends keyof TSelectModeValue<number>,
51
+ TModal extends ISdSelectModal<any>,
52
+ > extends AbsSdDataSelectButton<TItem, number, TMode> {
53
+ items = input<TItem[]>([]);
54
+ modal = input.required<TSdSelectModalInfo<TModal>>();
55
+
56
+ itemTplRef = contentChild.required<any, TemplateRef<SdItemOfTemplateContext<TItem>>>(
57
+ SdItemOfTemplateDirective,
58
+ { read: TemplateRef },
59
+ );
60
+
61
+ override load(keys: number[]): TItem[] {
62
+ return this.items().filter((item) => keys.includes(item.__valueKey));
63
+ }
64
+ }
@@ -0,0 +1,245 @@
1
+ import { NgTemplateOutlet } from "@angular/common";
2
+ import {
3
+ booleanAttribute,
4
+ ChangeDetectionStrategy,
5
+ Component,
6
+ computed,
7
+ contentChild,
8
+ effect,
9
+ inject,
10
+ input,
11
+ model,
12
+ signal,
13
+ TemplateRef,
14
+ untracked,
15
+ ViewEncapsulation,
16
+ } from "@angular/core";
17
+ import { str } from "@simplysm/core-common";
18
+ import type { ISharedDataBase } from "../../core/providers/sd-shared-data.provider";
19
+ import {
20
+ SdItemOfTemplateDirective,
21
+ type SdItemOfTemplateContext,
22
+ } from "../../core/directives/sd-item-of-template.directive";
23
+ import { SdModalProvider } from "../../ui/overlay/modal/sd-modal.provider";
24
+ import type {
25
+ ISdSelectModal,
26
+ TSdSelectModalInfo,
27
+ } from "../../ui/form/button/sd-modal-select-button.control";
28
+ import { setupModelHook } from "../../core/utils/setups/setupModelHook";
29
+ import { SdPaginationControl } from "../../ui/navigation/pagination/sd-pagination.control";
30
+ import { SdTextfieldControl } from "../../ui/form/input/sd-textfield.control";
31
+ import { SdAnchorControl } from "../../ui/form/button/sd-anchor.control";
32
+ import { SdListControl } from "../../ui/data/list/sd-list.control";
33
+ import { SdListItemControl } from "../../ui/data/list/sd-list-item.control";
34
+ import { NgIcon } from "@ng-icons/core";
35
+ import { tablerExternalLink } from "@ng-icons/tabler-icons";
36
+
37
+ @Component({
38
+ selector: "sd-shared-data-select-list",
39
+ changeDetection: ChangeDetectionStrategy.OnPush,
40
+ encapsulation: ViewEncapsulation.None,
41
+ standalone: true,
42
+ imports: [
43
+ NgTemplateOutlet,
44
+ SdTextfieldControl,
45
+ SdPaginationControl,
46
+ SdAnchorControl,
47
+ SdListControl,
48
+ SdListItemControl,
49
+ NgIcon,
50
+ ],
51
+ host: {
52
+ class: "flex-column fill",
53
+ },
54
+ template: `
55
+ @if (header()) {
56
+ <div class="control-header p-default">
57
+ {{ header() }}
58
+ </div>
59
+ }
60
+
61
+ <div class="flex-column gap-sm p-default pt-0">
62
+ @if (headerTplRef() || modal()) {
63
+ <div class="flex-row">
64
+ <div class="flex-fill">
65
+ @if (headerTplRef()) {
66
+ <ng-template [ngTemplateOutlet]="headerTplRef()!"></ng-template>
67
+ }
68
+ </div>
69
+ @if (modal()) {
70
+ <sd-anchor (click)="onModalButtonClick()">
71
+ <ng-icon [svg]="tablerExternalLink" />
72
+ </sd-anchor>
73
+ }
74
+ </div>
75
+ }
76
+
77
+ @if (!filterTplRef()) {
78
+ <sd-textfield [type]="'text'" [placeholder]="'검색어'" [(value)]="searchText" />
79
+ } @else {
80
+ <div>
81
+ <ng-template [ngTemplateOutlet]="filterTplRef()!" />
82
+ </div>
83
+ }
84
+ </div>
85
+
86
+ <div class="flex-fill">
87
+ <div class="flex-column gap-default">
88
+ @if (pageItemCount()) {
89
+ <sd-pagination [(currentPage)]="page" [totalPageCount]="pageLength()" />
90
+ }
91
+
92
+ <sd-list [inset]="true" class="flex-fill">
93
+ @if (useUndefined()) {
94
+ <sd-list-item
95
+ [selected]="selectedItem() === undefined"
96
+ (click)="select(undefined)"
97
+ [selectedIcon]="selectedIcon()"
98
+ >
99
+ @if (undefinedTplRef()) {
100
+ <ng-template [ngTemplateOutlet]="undefinedTplRef()!" />
101
+ } @else {
102
+ <span class="tx-theme-gray-default">미지정</span>
103
+ }
104
+ </sd-list-item>
105
+ }
106
+ @for (item of displayItems(); let index = $index; track item.__valueKey) {
107
+ <sd-list-item
108
+ [selected]="selectedItem() === item"
109
+ (click)="toggle(item)"
110
+ [selectedIcon]="selectedIcon()"
111
+ >
112
+ <ng-template
113
+ [ngTemplateOutlet]="itemTplRef() ?? null"
114
+ [ngTemplateOutletContext]="{
115
+ $implicit: item,
116
+ item: item,
117
+ index: index,
118
+ depth: 0,
119
+ }"
120
+ ></ng-template>
121
+ </sd-list-item>
122
+ }
123
+ </sd-list>
124
+ </div>
125
+ </div>
126
+ `,
127
+ })
128
+ export class SdSharedDataSelectListControl<
129
+ TItem extends ISharedDataBase<string | number>,
130
+ TModal extends ISdSelectModal<any>,
131
+ > {
132
+ private readonly _sdModal = inject(SdModalProvider);
133
+
134
+ selectedItem = model<TItem>();
135
+ canChangeFn = input<(item: TItem | undefined) => boolean | Promise<boolean>>(
136
+ () => true,
137
+ );
138
+
139
+ items = input.required<TItem[]>();
140
+ selectedIcon = input<string>();
141
+ useUndefined = input(false, { transform: booleanAttribute });
142
+ filterFn = input<(item: TItem, index: number) => boolean>();
143
+
144
+ modal = input<TSdSelectModalInfo<TModal>>();
145
+
146
+ header = input<string>();
147
+
148
+ headerTplRef = contentChild<any, TemplateRef<void>>("headerTpl", {
149
+ read: TemplateRef,
150
+ });
151
+ filterTplRef = contentChild<any, TemplateRef<void>>("filterTpl", {
152
+ read: TemplateRef,
153
+ });
154
+ itemTplRef = contentChild<any, TemplateRef<SdItemOfTemplateContext<TItem>>>(
155
+ SdItemOfTemplateDirective,
156
+ { read: TemplateRef },
157
+ );
158
+ undefinedTplRef = contentChild<any, TemplateRef<void>>("undefinedTpl", {
159
+ read: TemplateRef,
160
+ });
161
+
162
+ searchText = signal<string | undefined>(undefined);
163
+
164
+ pageItemCount = input<number>();
165
+ page = signal(0);
166
+ pageLength = computed(() => {
167
+ const pic = this.pageItemCount();
168
+ if (pic != null && pic > 0) {
169
+ return Math.ceil(this.items().length / pic);
170
+ }
171
+ return 0;
172
+ });
173
+
174
+ displayItems = computed(() => {
175
+ let result = this.items().filter((item) => !item.__isHidden);
176
+
177
+ if (!str.isNullOrEmpty(this.searchText())) {
178
+ result = result.filter((item) =>
179
+ item.__searchText.includes(this.searchText()!),
180
+ );
181
+ }
182
+
183
+ if (this.filterFn() != null) {
184
+ result = result.filter((item, i) => this.filterFn()!(item, i));
185
+ }
186
+
187
+ const pic = this.pageItemCount();
188
+ if (pic != null && pic > 0) {
189
+ result = result.slice(pic * this.page(), pic * (this.page() + 1));
190
+ }
191
+
192
+ return result;
193
+ });
194
+
195
+ constructor() {
196
+ setupModelHook(this.selectedItem, this.canChangeFn);
197
+
198
+ // items 변경 시 selectedItem 동기화 (selectedItem은 추적하지 않음)
199
+ effect(() => {
200
+ const items = this.items();
201
+ const current = untracked(() => this.selectedItem());
202
+ if (current != null) {
203
+ const updated = items.find(
204
+ (item) => item.__valueKey === current.__valueKey,
205
+ );
206
+ if (updated !== current) {
207
+ this.selectedItem.set(updated);
208
+ }
209
+ }
210
+ });
211
+ }
212
+
213
+ select(item: TItem | undefined): void {
214
+ this.selectedItem.set(item);
215
+ }
216
+
217
+ toggle(item: TItem | undefined): void {
218
+ this.selectedItem.update((v) => (v === item ? undefined : item));
219
+ }
220
+
221
+ async onModalButtonClick(): Promise<void> {
222
+ const modalInfo = this.modal();
223
+ if (modalInfo == null) return;
224
+
225
+ const result = await this._sdModal.showAsync({
226
+ ...modalInfo,
227
+ inputs: {
228
+ selectMode: "single",
229
+ selectedItemKeys: [this.selectedItem()]
230
+ .filter((v): v is NonNullable<typeof v> => v != null)
231
+ .map((item) => item.__valueKey),
232
+ ...modalInfo.inputs,
233
+ } as any,
234
+ });
235
+
236
+ if (result != null) {
237
+ const newSelectedItem = this.items().find(
238
+ (item) => item.__valueKey === result.selectedItemKeys[0],
239
+ );
240
+ this.selectedItem.set(newSelectedItem);
241
+ }
242
+ }
243
+
244
+ protected readonly tablerExternalLink = tablerExternalLink;
245
+ }
@@ -0,0 +1,364 @@
1
+ import { NgTemplateOutlet } from "@angular/common";
2
+ import {
3
+ booleanAttribute,
4
+ ChangeDetectionStrategy,
5
+ Component,
6
+ computed,
7
+ contentChild,
8
+ effect,
9
+ inject,
10
+ input,
11
+ model,
12
+ signal,
13
+ TemplateRef,
14
+ untracked,
15
+ viewChild,
16
+ ViewEncapsulation,
17
+ } from "@angular/core";
18
+ import type { ISharedDataBase } from "../../core/providers/sd-shared-data.provider";
19
+ import { SdSelectControl, type TSelectModeValue } from "../../ui/form/select/sd-select.control";
20
+ import { SdSelectButtonControl } from "../../ui/form/select/sd-select-button.control";
21
+ import { SdSelectItemControl } from "../../ui/form/select/sd-select-item.control";
22
+ import { SdTextfieldControl } from "../../ui/form/input/sd-textfield.control";
23
+ import {
24
+ SdItemOfTemplateDirective,
25
+ type SdItemOfTemplateContext,
26
+ } from "../../core/directives/sd-item-of-template.directive";
27
+ import {
28
+ SdModalProvider,
29
+ type ISdModal,
30
+ type ISdModalInfo,
31
+ } from "../../ui/overlay/modal/sd-modal.provider";
32
+ import type {
33
+ ISdSelectModal,
34
+ TSdSelectModalInfo,
35
+ } from "../../ui/form/button/sd-modal-select-button.control";
36
+ import { NgIcon } from "@ng-icons/core";
37
+ import { tablerEdit, tablerSearch } from "@ng-icons/tabler-icons";
38
+
39
+ @Component({
40
+ selector: "sd-shared-data-select",
41
+ changeDetection: ChangeDetectionStrategy.OnPush,
42
+ encapsulation: ViewEncapsulation.None,
43
+ standalone: true,
44
+ imports: [
45
+ SdSelectControl,
46
+ SdTextfieldControl,
47
+ SdSelectItemControl,
48
+ SdItemOfTemplateDirective,
49
+ NgTemplateOutlet,
50
+ SdSelectButtonControl,
51
+ NgIcon,
52
+ ],
53
+ template: `
54
+ <sd-select
55
+ [value]="$any(value())"
56
+ (valueChange)="value.set($any($event))"
57
+ [disabled]="disabled()"
58
+ [required]="required()"
59
+ [inset]="inset()"
60
+ [inline]="inline()"
61
+ [size]="size()"
62
+ [items]="rootDisplayItems()"
63
+ [selectMode]="selectMode()"
64
+ [contentClass]="selectClass()"
65
+ [multiSelectionDisplayDirection]="multiSelectionDisplayDirection()"
66
+ [getChildrenFn]="hasParentKey() ? getChildren : undefined"
67
+ >
68
+ @if (modal()) {
69
+ <sd-select-button (click)="onModalButtonClick($event)">
70
+ <ng-icon [svg]="tablerSearch" />
71
+ </sd-select-button>
72
+ }
73
+ @if (editModal()) {
74
+ <sd-select-button (click)="onEditModalButtonClick($event)">
75
+ <ng-icon [svg]="tablerEdit" />
76
+ </sd-select-button>
77
+ }
78
+
79
+ <ng-template #headerTpl>
80
+ <div class="p-xs">
81
+ <sd-textfield
82
+ [type]="'text'"
83
+ [(value)]="searchText"
84
+ [placeholder]="'검색어'"
85
+ [size]="size()"
86
+ />
87
+ </div>
88
+ </ng-template>
89
+
90
+ <ng-template #beforeTpl>
91
+ @if (
92
+ (!required() && selectMode() === "single") ||
93
+ (useUndefined() && selectMode() === "multi")
94
+ ) {
95
+ <div
96
+ class="_sd-shared-data-select-undefined"
97
+ tabindex="0"
98
+ (click)="onUndefinedClick()"
99
+ (keydown.enter)="onUndefinedClick()"
100
+ (keydown.space)="onUndefinedClick(); $event.preventDefault()"
101
+ >
102
+ @if (undefinedTplRef()) {
103
+ <ng-template [ngTemplateOutlet]="undefinedTplRef()!" />
104
+ } @else {
105
+ <span class="tx-theme-gray-default">미지정</span>
106
+ }
107
+ </div>
108
+ }
109
+ </ng-template>
110
+
111
+ <ng-template
112
+ [itemOf]="rootDisplayItems()"
113
+ let-item="item"
114
+ let-index="index"
115
+ let-depth="depth"
116
+ >
117
+ @if (
118
+ getItemSelectable(item, index, depth) &&
119
+ (isDropdownOpen() || selectedKeys().includes(item.__valueKey))
120
+ ) {
121
+ <sd-select-item [value]="item.__valueKey" [hidden]="!getItemVisible(item, index)">
122
+ <span
123
+ [style.text-decoration]="
124
+ getIsHiddenFn()(item, index) ? 'line-through' : undefined
125
+ "
126
+ >
127
+ <ng-template
128
+ [ngTemplateOutlet]="itemTplRef() ?? null"
129
+ [ngTemplateOutletContext]="{
130
+ $implicit: item,
131
+ item: item,
132
+ index: index,
133
+ depth: depth,
134
+ }"
135
+ ></ng-template>
136
+ </span>
137
+ </sd-select-item>
138
+ }
139
+ </ng-template>
140
+ </sd-select>
141
+ `,
142
+ })
143
+ export class SdSharedDataSelectControl<
144
+ TItem extends ISharedDataBase<string | number>,
145
+ TMode extends keyof TSelectModeValue<TItem>,
146
+ TModal extends ISdSelectModal<any>,
147
+ > {
148
+ private readonly _sdModal = inject(SdModalProvider);
149
+ private readonly _selectCtrl = viewChild(SdSelectControl);
150
+
151
+ value = model<TSelectModeValue<TItem["__valueKey"] | undefined>[TMode]>();
152
+
153
+ items = input.required<TItem[]>();
154
+
155
+ disabled = input(false, { transform: booleanAttribute });
156
+ required = input(false, { transform: booleanAttribute });
157
+ useUndefined = input(false, { transform: booleanAttribute });
158
+ inset = input(false, { transform: booleanAttribute });
159
+ inline = input(false, { transform: booleanAttribute });
160
+
161
+ size = input<"sm" | "lg">();
162
+ selectMode = input("single" as TMode);
163
+ filterFn = input<(item: TItem, index: number, ...params: any[]) => boolean>();
164
+ filterFnParams = input<any[]>();
165
+
166
+ modal = input<TSdSelectModalInfo<TModal>>();
167
+ editModal = input<ISdModalInfo<ISdModal<boolean>>>();
168
+
169
+ selectClass = input<string>();
170
+ multiSelectionDisplayDirection = input<"vertical">();
171
+ getIsHiddenFn = input<(item: TItem, index: number) => boolean>(
172
+ (item) => item.__isHidden,
173
+ );
174
+ getSearchTextFn = input<(item: TItem, index: number) => string>(
175
+ (item) => item.__searchText,
176
+ );
177
+ displayOrderKeyProp = input<string>();
178
+
179
+ itemTplRef = contentChild<any, TemplateRef<SdItemOfTemplateContext<TItem>>>(
180
+ SdItemOfTemplateDirective,
181
+ { read: TemplateRef },
182
+ );
183
+ undefinedTplRef = contentChild<any, TemplateRef<void>>("undefinedTpl", {
184
+ read: TemplateRef,
185
+ });
186
+
187
+ searchText = signal<string | undefined>(undefined);
188
+
189
+ isDropdownOpen = computed(() => this._selectCtrl()?.dropdownOpen() ?? false);
190
+
191
+ hasParentKey = computed(() =>
192
+ this.items().some((item) => item.__parentKey != null),
193
+ );
194
+
195
+ itemByParentKeyMap = computed(() => {
196
+ if (!this.hasParentKey()) return undefined;
197
+
198
+ const map = new Map<TItem["__valueKey"] | undefined, TItem[]>();
199
+ for (const item of this.items()) {
200
+ const parentKey = item.__parentKey as TItem["__valueKey"] | undefined;
201
+ const existing = map.get(parentKey);
202
+ if (existing != null) {
203
+ existing.push(item);
204
+ } else {
205
+ map.set(parentKey, [item]);
206
+ }
207
+ }
208
+ return map;
209
+ });
210
+
211
+ rootDisplayItems = computed(() => {
212
+ let result = this.items().filter((item, index) => {
213
+ if (this.filterFn() != null) {
214
+ if (!this.filterFn()!(item, index, ...(this.filterFnParams() ?? []))) {
215
+ return false;
216
+ }
217
+ }
218
+ if (this.hasParentKey()) {
219
+ return item.__parentKey == null;
220
+ }
221
+ return true;
222
+ });
223
+
224
+ const orderProp = this.displayOrderKeyProp();
225
+ if (orderProp != null) {
226
+ result = [...result].sort((a, b) => {
227
+ const aVal = (a as any)[orderProp];
228
+ const bVal = (b as any)[orderProp];
229
+ if (aVal < bVal) return -1;
230
+ if (aVal > bVal) return 1;
231
+ return 0;
232
+ });
233
+ }
234
+
235
+ return result;
236
+ });
237
+
238
+ selectedKeys = computed((): any[] => {
239
+ const val = this.value();
240
+ if (val == null) return [];
241
+ if (Array.isArray(val)) return val;
242
+ return [val];
243
+ });
244
+
245
+ constructor() {
246
+ // 드롭다운 닫힘 시 검색어 초기화
247
+ effect(() => {
248
+ const ctrl = this._selectCtrl();
249
+ if (ctrl != null) {
250
+ ctrl.dropdownOpen();
251
+ }
252
+ untracked(() => this.searchText.set(undefined));
253
+ });
254
+ }
255
+
256
+ getItemSelectable(item: TItem, _index: number, depth: number): boolean {
257
+ if (!this.hasParentKey()) return true;
258
+ // depth가 0이면서 자식을 가진 항목(카테고리)은 선택 불가
259
+ return depth !== 0 || item.__parentKey == null;
260
+ }
261
+
262
+ getItemVisible(item: TItem, index: number): boolean {
263
+ if (
264
+ this.isIncludeSearchText(item, index) &&
265
+ !this.getIsHiddenFn()(item, index)
266
+ ) {
267
+ return true;
268
+ }
269
+ // 현재 선택된 항목은 항상 표시
270
+ const val = this.value();
271
+ if (val === item.__valueKey) return true;
272
+ if (Array.isArray(val) && val.includes(item.__valueKey)) return true;
273
+ return false;
274
+ }
275
+
276
+ isIncludeSearchText(item: TItem, index: number): boolean {
277
+ const splitSearchTexts =
278
+ this.searchText()
279
+ ?.trim()
280
+ .split(" ")
281
+ .map((t) => t.trim())
282
+ .filter((t) => t !== "") ?? [];
283
+
284
+ if (splitSearchTexts.length === 0) return true;
285
+
286
+ const itemText = this.getSearchTextFn()(item, index);
287
+ for (const term of splitSearchTexts) {
288
+ if (!itemText.toLowerCase().includes(term.toLowerCase())) {
289
+ // 트리 구조에서 자식 중 매칭 항목 확인
290
+ if (this.hasParentKey()) {
291
+ const children = this.getChildren(item);
292
+ for (let i = 0; i < children.length; i++) {
293
+ if (this.isIncludeSearchText(children[i], i)) {
294
+ return true;
295
+ }
296
+ }
297
+ }
298
+ return false;
299
+ }
300
+ }
301
+ return true;
302
+ }
303
+
304
+ getChildren = (item: ISharedDataBase<string | number>): TItem[] => {
305
+ let result =
306
+ this.itemByParentKeyMap()?.get(item.__valueKey as TItem["__valueKey"]) ??
307
+ [];
308
+
309
+ const orderProp = this.displayOrderKeyProp();
310
+ if (orderProp != null) {
311
+ result = [...result].sort((a, b) => {
312
+ const aVal = (a as any)[orderProp];
313
+ const bVal = (b as any)[orderProp];
314
+ if (aVal < bVal) return -1;
315
+ if (aVal > bVal) return 1;
316
+ return 0;
317
+ });
318
+ }
319
+
320
+ return result;
321
+ };
322
+
323
+ onUndefinedClick(): void {
324
+ this.value.set(undefined as any);
325
+ }
326
+
327
+ async onModalButtonClick(event: MouseEvent): Promise<void> {
328
+ event.preventDefault();
329
+ event.stopPropagation();
330
+
331
+ const modalInfo = this.modal();
332
+ if (modalInfo == null) return;
333
+
334
+ const result = await this._sdModal.showAsync({
335
+ ...modalInfo,
336
+ inputs: {
337
+ selectMode: this.selectMode(),
338
+ selectedItemKeys: this.selectedKeys(),
339
+ ...modalInfo.inputs,
340
+ } as any,
341
+ });
342
+
343
+ if (result != null) {
344
+ const newValue =
345
+ this.selectMode() === "multi"
346
+ ? result.selectedItemKeys
347
+ : result.selectedItemKeys[0];
348
+ this.value.set(newValue);
349
+ }
350
+ }
351
+
352
+ async onEditModalButtonClick(event: MouseEvent): Promise<void> {
353
+ event.preventDefault();
354
+ event.stopPropagation();
355
+
356
+ const modalInfo = this.editModal();
357
+ if (modalInfo == null) return;
358
+
359
+ await this._sdModal.showAsync(modalInfo);
360
+ }
361
+
362
+ protected readonly tablerSearch = tablerSearch;
363
+ protected readonly tablerEdit = tablerEdit;
364
+ }