@simplysm/angular 14.0.42 → 14.0.43

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 (241) hide show
  1. package/dist/controls/button/sd-additional-button.js +1 -1
  2. package/dist/controls/button/sd-anchor.js +1 -1
  3. package/dist/controls/button/sd-button.js +1 -1
  4. package/dist/controls/button/sd-modal-select-button.d.ts +1 -1
  5. package/dist/controls/button/sd-modal-select-button.d.ts.map +1 -1
  6. package/dist/controls/button/sd-modal-select-button.js +8 -6
  7. package/dist/controls/checkbox/sd-checkbox-group-item.js +1 -1
  8. package/dist/controls/checkbox/sd-checkbox-group.js +1 -1
  9. package/dist/controls/checkbox/sd-checkbox.js +1 -1
  10. package/dist/controls/checkbox/sd-switch.js +1 -1
  11. package/dist/controls/collapse/sd-collapse-icon.d.ts.map +1 -1
  12. package/dist/controls/collapse/sd-collapse-icon.js +3 -3
  13. package/dist/controls/collapse/sd-collapse.d.ts +1 -1
  14. package/dist/controls/collapse/sd-collapse.d.ts.map +1 -1
  15. package/dist/controls/collapse/sd-collapse.js +8 -7
  16. package/dist/controls/dropdown/sd-dropdown-popup.d.ts +2 -0
  17. package/dist/controls/dropdown/sd-dropdown-popup.d.ts.map +1 -1
  18. package/dist/controls/dropdown/sd-dropdown-popup.js +21 -8
  19. package/dist/controls/dropdown/sd-dropdown.d.ts.map +1 -1
  20. package/dist/controls/dropdown/sd-dropdown.js +5 -16
  21. package/dist/controls/form/sd-form.js +1 -1
  22. package/dist/controls/gap/sd-gap.js +5 -5
  23. package/dist/controls/input/sd-date-range-picker.d.ts +1 -0
  24. package/dist/controls/input/sd-date-range-picker.d.ts.map +1 -1
  25. package/dist/controls/input/sd-date-range-picker.js +14 -19
  26. package/dist/controls/input/sd-numpad.js +3 -3
  27. package/dist/controls/input/sd-range.js +1 -1
  28. package/dist/controls/input/sd-textarea.js +2 -2
  29. package/dist/controls/input/sd-textfield-type-handlers.js +2 -2
  30. package/dist/controls/input/sd-textfield.js +9 -9
  31. package/dist/controls/list/sd-list-item.d.ts +0 -1
  32. package/dist/controls/list/sd-list-item.d.ts.map +1 -1
  33. package/dist/controls/list/sd-list-item.js +38 -38
  34. package/dist/controls/list/sd-list.d.ts.map +1 -1
  35. package/dist/controls/list/sd-list.js +3 -3
  36. package/dist/controls/pagination/sd-pagination.js +1 -1
  37. package/dist/controls/select/sd-select-button.d.ts.map +1 -1
  38. package/dist/controls/select/sd-select-button.js +4 -8
  39. package/dist/controls/select/sd-select-item.d.ts +3 -3
  40. package/dist/controls/select/sd-select-item.d.ts.map +1 -1
  41. package/dist/controls/select/sd-select-item.js +27 -20
  42. package/dist/controls/select/sd-select.d.ts +5 -4
  43. package/dist/controls/select/sd-select.d.ts.map +1 -1
  44. package/dist/controls/select/sd-select.js +20 -17
  45. package/dist/controls/tab/sd-tab-item.js +1 -1
  46. package/dist/controls/tab/sd-tab.js +1 -1
  47. package/dist/core/app-structure/sd-app-structure.utils.js +1 -1
  48. package/dist/core/busy/sd-busy-container.d.ts.map +1 -1
  49. package/dist/core/busy/sd-busy-container.js +62 -68
  50. package/dist/core/busy/sd-busy.provider.js +1 -1
  51. package/dist/core/commands/sd-command.d.ts +13 -0
  52. package/dist/core/commands/sd-command.d.ts.map +1 -0
  53. package/dist/core/commands/sd-command.js +52 -0
  54. package/dist/core/error-handler/sd-global-error-handler.plugin.js +1 -1
  55. package/dist/core/events/sd-events.d.ts +1 -6
  56. package/dist/core/events/sd-events.d.ts.map +1 -1
  57. package/dist/core/events/sd-events.js +3 -11
  58. package/dist/core/events/sd-intersection.d.ts +13 -0
  59. package/dist/core/events/sd-intersection.d.ts.map +1 -0
  60. package/dist/core/events/sd-intersection.js +27 -0
  61. package/dist/core/events/sd-resize.d.ts +16 -0
  62. package/dist/core/events/sd-resize.d.ts.map +1 -0
  63. package/dist/core/events/{sd-resize-event.plugin.js → sd-resize.js} +18 -20
  64. package/dist/core/file-dialog/sd-file-dialog.provider.js +1 -1
  65. package/dist/core/modal/injectDragResize.js +9 -9
  66. package/dist/core/modal/injectFocusTrap.js +1 -1
  67. package/dist/core/modal/sd-confirm-modal.js +1 -1
  68. package/dist/core/modal/sd-modal.d.ts +8 -1
  69. package/dist/core/modal/sd-modal.d.ts.map +1 -1
  70. package/dist/core/modal/sd-modal.js +135 -39
  71. package/dist/core/modal/sd-modal.provider.js +5 -5
  72. package/dist/core/modal/sd-prompt-modal.js +1 -1
  73. package/dist/core/provideSdAngular.d.ts.map +1 -1
  74. package/dist/core/provideSdAngular.js +0 -10
  75. package/dist/core/ripple/setupRipple.js +5 -5
  76. package/dist/core/routing/menu-utils.js +1 -1
  77. package/dist/core/routing/sd-navigate-window.provider.js +1 -1
  78. package/dist/core/routing/sd-router-link.js +1 -1
  79. package/dist/core/selection/setupCumulateSelectedKeys.js +3 -3
  80. package/dist/core/setupModelHook.js +1 -1
  81. package/dist/core/toast/sd-toast-container.d.ts +1 -1
  82. package/dist/core/toast/sd-toast-container.js +3 -7
  83. package/dist/core/toast/sd-toast.d.ts.map +1 -1
  84. package/dist/core/toast/sd-toast.js +27 -24
  85. package/dist/core/toast/sd-toast.provider.js +6 -6
  86. package/dist/core/validation/setupInvalid.js +2 -1
  87. package/dist/data/data-detail/sd-data-detail.d.ts +2 -1
  88. package/dist/data/data-detail/sd-data-detail.d.ts.map +1 -1
  89. package/dist/data/data-detail/sd-data-detail.js +37 -33
  90. package/dist/data/data-select-button/sd-data-select-button.js +1 -1
  91. package/dist/data/data-sheet/sd-data-sheet.d.ts +2 -1
  92. package/dist/data/data-sheet/sd-data-sheet.d.ts.map +1 -1
  93. package/dist/data/data-sheet/sd-data-sheet.js +30 -22
  94. package/dist/data/kanban/sd-kanban-board.js +1 -1
  95. package/dist/data/kanban/sd-kanban-lane.js +1 -1
  96. package/dist/data/kanban/sd-kanban.d.ts +1 -1
  97. package/dist/data/kanban/sd-kanban.d.ts.map +1 -1
  98. package/dist/data/kanban/sd-kanban.js +4 -4
  99. package/dist/data/permission-table/sd-permission-table.js +6 -6
  100. package/dist/data/shared-data/sd-shared-data-select-button.js +1 -1
  101. package/dist/data/shared-data/sd-shared-data-select-list.js +3 -3
  102. package/dist/data/shared-data/sd-shared-data-select.d.ts +1 -1
  103. package/dist/data/shared-data/sd-shared-data-select.d.ts.map +1 -1
  104. package/dist/data/shared-data/sd-shared-data-select.js +29 -54
  105. package/dist/data/sheet/injectSheetDomAccessor.d.ts +6 -2
  106. package/dist/data/sheet/injectSheetDomAccessor.d.ts.map +1 -1
  107. package/dist/data/sheet/injectSheetDomAccessor.js +27 -22
  108. package/dist/data/sheet/injectSheetSelectRowIndicator.d.ts +10 -0
  109. package/dist/data/sheet/injectSheetSelectRowIndicator.d.ts.map +1 -0
  110. package/dist/data/sheet/injectSheetSelectRowIndicator.js +55 -0
  111. package/dist/data/sheet/sd-sheet-config.modal.d.ts +18 -19
  112. package/dist/data/sheet/sd-sheet-config.modal.d.ts.map +1 -1
  113. package/dist/data/sheet/sd-sheet-config.modal.js +357 -217
  114. package/dist/data/sheet/sd-sheet.d.ts +27 -13
  115. package/dist/data/sheet/sd-sheet.d.ts.map +1 -1
  116. package/dist/data/sheet/sd-sheet.js +609 -291
  117. package/dist/data/sheet/useSheetCellAgent.js +6 -6
  118. package/dist/data/sheet/useSheetCellStyling.d.ts.map +1 -1
  119. package/dist/data/sheet/useSheetCellStyling.js +4 -4
  120. package/dist/data/sheet/useSheetFocusIndicator.d.ts +7 -0
  121. package/dist/data/sheet/useSheetFocusIndicator.d.ts.map +1 -0
  122. package/dist/data/sheet/useSheetFocusIndicator.js +53 -0
  123. package/dist/data/sheet/useSheetLayoutEngine.js +1 -1
  124. package/dist/data/state-preset/sd-state-preset.d.ts.map +1 -1
  125. package/dist/data/state-preset/sd-state-preset.js +14 -14
  126. package/dist/features/address/sd-address-search.modal.js +3 -3
  127. package/dist/features/editor/sd-tiptap-editor.js +6 -6
  128. package/dist/features/editor/useTiptapToolbar.js +2 -2
  129. package/dist/features/theme/sd-theme-selector.js +1 -1
  130. package/dist/features/visual/sd-barcode.js +1 -1
  131. package/dist/features/visual/sd-calendar.js +2 -2
  132. package/dist/features/visual/sd-echarts.d.ts +2 -1
  133. package/dist/features/visual/sd-echarts.d.ts.map +1 -1
  134. package/dist/features/visual/sd-echarts.js +5 -3
  135. package/dist/features/visual/sd-label.js +1 -1
  136. package/dist/features/visual/sd-note.js +1 -1
  137. package/dist/features/visual/sd-progress.js +1 -1
  138. package/dist/index.d.ts +3 -5
  139. package/dist/index.d.ts.map +1 -1
  140. package/dist/index.js +3 -5
  141. package/dist/layout/base-container/sd-base-container.js +3 -3
  142. package/dist/layout/dock/sd-dock-container.js +1 -1
  143. package/dist/layout/dock/sd-dock.d.ts +3 -2
  144. package/dist/layout/dock/sd-dock.d.ts.map +1 -1
  145. package/dist/layout/dock/sd-dock.js +6 -4
  146. package/dist/layout/sidebar/sd-sidebar-container.js +5 -5
  147. package/dist/layout/sidebar/sd-sidebar-menu.d.ts.map +1 -1
  148. package/dist/layout/sidebar/sd-sidebar-menu.js +7 -6
  149. package/dist/layout/sidebar/sd-sidebar-user.js +1 -1
  150. package/dist/layout/sidebar/sd-sidebar.js +1 -1
  151. package/dist/layout/topbar/sd-topbar-container.js +1 -1
  152. package/dist/layout/topbar/sd-topbar-menu.d.ts.map +1 -1
  153. package/dist/layout/topbar/sd-topbar-menu.js +7 -7
  154. package/dist/layout/topbar/sd-topbar-user.js +1 -1
  155. package/dist/layout/topbar/sd-topbar.js +3 -3
  156. package/package.json +5 -5
  157. package/src/controls/button/sd-modal-select-button.ts +7 -2
  158. package/src/controls/collapse/sd-collapse-icon.ts +2 -2
  159. package/src/controls/collapse/sd-collapse.ts +4 -5
  160. package/src/controls/dropdown/sd-dropdown-popup.ts +15 -2
  161. package/src/controls/dropdown/sd-dropdown.ts +4 -16
  162. package/src/controls/gap/sd-gap.ts +4 -4
  163. package/src/controls/input/sd-date-range-picker.ts +13 -16
  164. package/src/controls/input/sd-numpad.ts +1 -1
  165. package/src/controls/input/sd-textarea.ts +1 -1
  166. package/src/controls/input/sd-textfield-type-handlers.ts +2 -2
  167. package/src/controls/input/sd-textfield.ts +6 -6
  168. package/src/controls/list/sd-list-item.ts +40 -26
  169. package/src/controls/list/sd-list.ts +2 -1
  170. package/src/controls/select/sd-select-button.ts +8 -11
  171. package/src/controls/select/sd-select-item.ts +35 -27
  172. package/src/controls/select/sd-select.ts +111 -41
  173. package/src/core/app-structure/sd-app-structure.utils.ts +1 -1
  174. package/src/core/busy/sd-busy-container.ts +235 -123
  175. package/src/core/busy/sd-busy.provider.ts +1 -1
  176. package/src/core/commands/sd-command.ts +46 -0
  177. package/src/core/error-handler/sd-global-error-handler.plugin.ts +1 -1
  178. package/src/core/events/sd-events.ts +1 -12
  179. package/src/core/events/sd-intersection.ts +29 -0
  180. package/src/core/events/{sd-resize-event.plugin.ts → sd-resize.ts} +17 -24
  181. package/src/core/file-dialog/sd-file-dialog.provider.ts +1 -1
  182. package/src/core/modal/injectDragResize.ts +9 -9
  183. package/src/core/modal/injectFocusTrap.ts +1 -1
  184. package/src/core/modal/sd-modal.provider.ts +5 -5
  185. package/src/core/modal/sd-modal.ts +119 -41
  186. package/src/core/provideSdAngular.ts +0 -10
  187. package/src/core/ripple/setupRipple.ts +5 -5
  188. package/src/core/routing/menu-utils.ts +1 -1
  189. package/src/core/routing/sd-navigate-window.provider.ts +1 -1
  190. package/src/core/routing/sd-router-link.ts +1 -1
  191. package/src/core/selection/setupCumulateSelectedKeys.ts +3 -3
  192. package/src/core/setupModelHook.ts +1 -1
  193. package/src/core/toast/sd-toast-container.ts +1 -1
  194. package/src/core/toast/sd-toast.provider.ts +6 -6
  195. package/src/core/toast/sd-toast.ts +25 -22
  196. package/src/core/validation/setupInvalid.ts +2 -1
  197. package/src/data/data-detail/sd-data-detail.ts +15 -11
  198. package/src/data/data-sheet/sd-data-sheet.ts +13 -15
  199. package/src/data/kanban/sd-kanban.ts +4 -5
  200. package/src/data/permission-table/sd-permission-table.ts +4 -4
  201. package/src/data/shared-data/sd-shared-data-select-list.ts +1 -1
  202. package/src/data/shared-data/sd-shared-data-select.ts +8 -27
  203. package/src/data/sheet/injectSheetDomAccessor.ts +37 -25
  204. package/src/data/sheet/injectSheetSelectRowIndicator.ts +69 -0
  205. package/src/data/sheet/sd-sheet-config.modal.ts +215 -191
  206. package/src/data/sheet/sd-sheet.ts +529 -209
  207. package/src/data/sheet/useSheetCellAgent.ts +8 -8
  208. package/src/data/sheet/useSheetCellStyling.ts +4 -8
  209. package/src/data/sheet/useSheetFocusIndicator.ts +66 -0
  210. package/src/data/sheet/useSheetLayoutEngine.ts +1 -1
  211. package/src/data/state-preset/sd-state-preset.ts +26 -13
  212. package/src/features/address/sd-address-search.modal.ts +1 -1
  213. package/src/features/editor/sd-tiptap-editor.ts +4 -4
  214. package/src/features/editor/useTiptapToolbar.ts +2 -2
  215. package/src/features/visual/sd-calendar.ts +1 -1
  216. package/src/features/visual/sd-echarts.ts +2 -0
  217. package/src/index.ts +4 -6
  218. package/src/layout/base-container/sd-base-container.ts +1 -1
  219. package/src/layout/dock/sd-dock.ts +3 -2
  220. package/src/layout/sidebar/sd-sidebar-container.ts +2 -2
  221. package/src/layout/sidebar/sd-sidebar-menu.ts +1 -3
  222. package/src/layout/topbar/sd-topbar-menu.ts +11 -15
  223. package/src/layout/topbar/sd-topbar.ts +1 -1
  224. package/dist/core/commands/sd-insert-command-event.plugin.d.ts +0 -11
  225. package/dist/core/commands/sd-insert-command-event.plugin.d.ts.map +0 -1
  226. package/dist/core/commands/sd-insert-command-event.plugin.js +0 -35
  227. package/dist/core/commands/sd-refresh-command-event.plugin.d.ts +0 -11
  228. package/dist/core/commands/sd-refresh-command-event.plugin.d.ts.map +0 -1
  229. package/dist/core/commands/sd-refresh-command-event.plugin.js +0 -38
  230. package/dist/core/commands/sd-save-command-event.plugin.d.ts +0 -11
  231. package/dist/core/commands/sd-save-command-event.plugin.d.ts.map +0 -1
  232. package/dist/core/commands/sd-save-command-event.plugin.js +0 -38
  233. package/dist/core/events/sd-intersection-event.plugin.d.ts +0 -13
  234. package/dist/core/events/sd-intersection-event.plugin.d.ts.map +0 -1
  235. package/dist/core/events/sd-intersection-event.plugin.js +0 -29
  236. package/dist/core/events/sd-resize-event.plugin.d.ts +0 -16
  237. package/dist/core/events/sd-resize-event.plugin.d.ts.map +0 -1
  238. package/src/core/commands/sd-insert-command-event.plugin.ts +0 -39
  239. package/src/core/commands/sd-refresh-command-event.plugin.ts +0 -44
  240. package/src/core/commands/sd-save-command-event.plugin.ts +0 -44
  241. package/src/core/events/sd-intersection-event.plugin.ts +0 -35
@@ -30,7 +30,7 @@ import {
30
30
  <span class="tx-trans-light">****</span>
31
31
  } @else {
32
32
  @if (controlValue()) {
33
- <pre>{{ controlValueText() ?? controlValue() }} </pre>
33
+ <pre>{{ controlValueText() ? controlValueText() : " " }}</pre>
34
34
  } @else if (placeholder()) {
35
35
  <span class="tx-trans-lighter">{{ placeholder() }}</span>
36
36
  } @else {
@@ -274,7 +274,7 @@ import {
274
274
  `,
275
275
  ],
276
276
  host: {
277
- "[attr.data-sd-type]": "controlType()",
277
+ "[attr.data-sd-type]": "type()",
278
278
  "[attr.data-sd-disabled]": "disabled()",
279
279
  "[attr.data-sd-readonly]": "readonly()",
280
280
  "[attr.data-sd-inline]": "inline()",
@@ -336,7 +336,7 @@ export class SdTextfield<K extends keyof SdTextfieldTypes> {
336
336
  if (value == null) return undefined;
337
337
  return this._handler().toDisplayText(value, {
338
338
  minDigits: this.minDigits(),
339
- });
339
+ }) ?? this.controlValue();
340
340
  });
341
341
 
342
342
  constructor() {
@@ -356,7 +356,7 @@ export class SdTextfield<K extends keyof SdTextfieldTypes> {
356
356
 
357
357
  if (this.validatorFn()) {
358
358
  const message = this.validatorFn()!(value);
359
- if (message !== undefined) {
359
+ if (message != null) {
360
360
  errorMessages.push(message);
361
361
  }
362
362
  }
@@ -372,7 +372,7 @@ export class SdTextfield<K extends keyof SdTextfieldTypes> {
372
372
  return;
373
373
  }
374
374
  const parsed = this._handler().parse(inputEl.value, { format: this.format() });
375
- if (parsed === undefined) {
375
+ if (parsed == null) {
376
376
  inputEl.value = this.controlValue();
377
377
  return;
378
378
  }
@@ -387,7 +387,7 @@ export class SdTextfield<K extends keyof SdTextfieldTypes> {
387
387
  return;
388
388
  }
389
389
  const parsed = this._handler().parse(text, { format: this.format() });
390
- if (parsed === undefined) {
390
+ if (parsed == null) {
391
391
  const inputEl = event.target as HTMLInputElement;
392
392
  inputEl.value = this.controlValue();
393
393
  return;
@@ -15,20 +15,17 @@ import { NgIcon } from "@ng-icons/core";
15
15
  import { SdCollapse } from "../collapse/sd-collapse";
16
16
  import { SdCollapseIcon } from "../collapse/sd-collapse-icon";
17
17
  import { SdList } from "./sd-list";
18
- import { setupRipple } from "../../core/ripple/setupRipple";
18
+ import { SdRipple } from "../../core/ripple/sd-ripple";
19
19
 
20
20
  @Component({
21
21
  selector: "sd-list-item",
22
22
  changeDetection: ChangeDetectionStrategy.OnPush,
23
23
  encapsulation: ViewEncapsulation.None,
24
24
  standalone: true,
25
- imports: [SdCollapse, SdCollapseIcon, NgTemplateOutlet, NgIcon],
25
+ imports: [SdCollapse, SdCollapseIcon, NgTemplateOutlet, NgIcon, SdRipple],
26
26
  template: `
27
- <div class="_content" [style]="contentStyle()" [class]="contentClass()" tabindex="0" (click)="onContentClick()" (keydown.enter)="onContentClick()">
28
- @if (layout() === "accordion" && hasChildren()) {
29
- <sd-collapse-icon [open]="open()" />
30
- }
31
- @if (selectedIcon() !== undefined && !hasChildren()) {
27
+ <div class="_content" [style]="contentStyle()" [class]="contentClass()" tabindex="0" (click)="onContentClick()" (keydown.enter)="onContentClick()" [sdRipple]="!readonly() && !(layout() === 'flat' && hasChildren())">
28
+ @if (selectedIcon() != null && !hasChildren()) {
32
29
  <ng-icon
33
30
  [class.tx-theme-primary-default]="selected()"
34
31
  [class.tx-trans-lightest]="!selected()"
@@ -43,6 +40,9 @@ import { setupRipple } from "../../core/ripple/setupRipple";
43
40
  <ng-template [ngTemplateOutlet]="toolTpl()!" />
44
41
  </div>
45
42
  }
43
+ @if (layout() === "accordion" && hasChildren()) {
44
+ <sd-collapse-icon [open]="open()" />
45
+ }
46
46
  </div>
47
47
  @if (hasChildren()) {
48
48
  <sd-collapse [open]="childrenOpen()">
@@ -57,54 +57,72 @@ import { setupRipple } from "../../core/ripple/setupRipple";
57
57
 
58
58
  > ._content {
59
59
  display: flex;
60
- align-items: center;
61
60
  padding: var(--gap-sm) var(--gap-default);
62
61
  cursor: pointer;
63
- gap: var(--gap-sm);
62
+ gap: var(--gap-xs);
64
63
 
65
64
  > ._label {
66
- flex: 1;
65
+ flex: 1 1 auto;
66
+ overflow: auto;
67
67
  }
68
68
  }
69
69
 
70
- &:hover > ._content {
71
- background: var(--trans-lighter);
72
- }
73
-
74
70
  &[data-sd-selected="true"] > ._content {
75
71
  background: var(--trans-lighter);
76
72
  font-weight: bold;
77
73
  }
78
74
 
75
+ &[data-sd-has-selected-icon="true"][data-sd-selected="true"] > ._content {
76
+ color: var(--text-trans-default);
77
+
78
+ &:hover {
79
+ background: var(--trans-lighter);
80
+ }
81
+ }
82
+
79
83
  &[data-sd-readonly="true"] {
80
84
  > ._content {
81
85
  cursor: default;
82
86
  }
87
+ }
83
88
 
84
- &:hover > ._content {
85
- background: transparent;
89
+ &[data-sd-layout="accordion"] {
90
+ &:not([data-sd-readonly="true"]) {
91
+ > ._content:hover {
92
+ background: var(--trans-lighter);
93
+ }
94
+ }
95
+
96
+ > sd-collapse > ._content > sd-list {
97
+ padding: var(--gap-xs) 0;
86
98
  }
87
99
  }
88
100
 
89
- &[data-sd-layout="flat"] {
101
+ &[data-sd-layout="flat"][data-sd-has-children="true"] {
90
102
  > ._content {
91
- font-size: 0.85em;
92
- opacity: 0.7;
103
+ display: block;
104
+ background: transparent;
93
105
  cursor: default;
106
+ font-size: var(--font-size-sm);
107
+ opacity: 0.7;
94
108
  }
109
+ }
110
+ }
95
111
 
96
- &:hover > ._content {
97
- background: transparent;
98
- }
112
+ .sd-theme-mobile > sd-list-item {
113
+ > ._content:hover {
114
+ background: transparent;
99
115
  }
100
116
  }
101
117
  `,
102
118
  ],
103
119
  host: {
104
120
  "[attr.data-sd-layout]": "layout()",
121
+ "[attr.data-sd-open]": "open()",
105
122
  "[attr.data-sd-selected]": "selected()",
106
123
  "[attr.data-sd-readonly]": "readonly()",
107
124
  "[attr.data-sd-has-children]": "hasChildren()",
125
+ "[attr.data-sd-has-selected-icon]": "selectedIcon() != null",
108
126
  },
109
127
  })
110
128
  export class SdListItem {
@@ -126,10 +144,6 @@ export class SdListItem {
126
144
  return this.layout() === "flat" ? true : this.open();
127
145
  });
128
146
 
129
- constructor() {
130
- setupRipple(() => !this.readonly() && this.layout() !== "flat");
131
- }
132
-
133
147
  onContentClick(): void {
134
148
  if (this.readonly()) return;
135
149
  if (this.layout() === "accordion" && this.hasChildren()) {
@@ -18,7 +18,8 @@ import {
18
18
  styles: [
19
19
  /* language=SCSS */ `
20
20
  sd-list {
21
- display: block;
21
+ display: flex;
22
+ flex-direction: column;
22
23
  user-select: none;
23
24
  background: var(--control-color);
24
25
 
@@ -17,24 +17,21 @@ import { setupRipple } from "../../core/ripple/setupRipple";
17
17
  styles: [
18
18
  /* language=SCSS */ `
19
19
  sd-select-button {
20
- display: inline-flex;
21
- align-items: center;
22
- justify-content: center;
23
- padding: var(--gap-sm) var(--gap-default);
20
+ display: block;
21
+ background: var(--control-color);
22
+ font-weight: bold;
24
23
  cursor: pointer;
25
- border-left: 1px solid var(--trans-lighter);
26
- position: relative;
27
- overflow: hidden;
24
+ color: var(--theme-primary-default);
25
+ transition: background 0.1s linear;
28
26
 
29
27
  &:hover {
30
- background: var(--trans-lighter);
28
+ color: var(--theme-primary-darker);
29
+ background: var(--theme-gray-lightest);
31
30
  }
32
31
  }
33
32
  `,
34
33
  ],
35
- host: {
36
- "[attr.tabindex]": "0",
37
- },
34
+ host: {},
38
35
  })
39
36
  export class SdSelectButton {
40
37
  constructor() {
@@ -23,11 +23,12 @@ import { SdGap } from "../gap/sd-gap";
23
23
  standalone: true,
24
24
  imports: [SdCheckbox, SdGap],
25
25
  template: `
26
- <div class="_content" tabindex="0" (click)="onClick()" (keydown)="onKeydown($event)">
27
- @if (_parentControl.selectMode() === "multi") {
28
- <sd-checkbox [value]="isSelected()" [inline]="true" />
29
- <sd-gap [width]="'sm'" />
30
- }
26
+ @if (_parentControl.selectMode() === "multi") {
27
+ <sd-checkbox [value]="isSelected()" [inline]="true" />
28
+ <sd-gap [width]="'sm'" />
29
+ }
30
+
31
+ <div class="_content" style="display: inline-block;">
31
32
  <ng-content />
32
33
  </div>
33
34
  `,
@@ -37,32 +38,33 @@ import { SdGap } from "../gap/sd-gap";
37
38
 
38
39
  sd-select-item {
39
40
  display: block;
41
+ padding: var(--gap-sm) var(--gap-default);
42
+ cursor: pointer;
43
+ transition: background 0.1s ease-in;
44
+ background: var(--control-color);
45
+
46
+ &:hover {
47
+ transition: background 0.1s ease-out;
48
+ background: rgba(0, 0, 0, 0.07);
49
+ }
40
50
 
41
- > ._content {
42
- padding: var(--gap-sm) var(--gap-default);
43
- cursor: pointer;
44
-
45
- &:hover {
46
- background: var(--trans-lighter);
47
- }
48
-
49
- &:focus {
50
- outline: none;
51
- background: var(--trans-lighter);
52
- }
51
+ &:focus {
52
+ outline: none;
53
+ transition: background 0.1s ease-out;
54
+ background: rgba(0, 0, 0, 0.07);
53
55
  }
54
56
 
55
- &[data-sd-selected="true"] > ._content {
56
- background: var(--trans-lighter);
57
+ &[data-sd-selected="true"] {
58
+ color: var(--theme-primary-default);
57
59
  font-weight: bold;
60
+ background: rgba(0, 0, 0, 0.07);
58
61
  }
59
62
 
60
63
  &[data-sd-disabled="true"] {
61
- > ._content {
62
- opacity: 0.3;
63
- cursor: default;
64
- pointer-events: none;
65
- }
64
+ background: var(--theme-gray-default);
65
+ opacity: 0.3;
66
+ cursor: default;
67
+ pointer-events: none;
66
68
  }
67
69
 
68
70
  &[data-sd-hidden="true"] {
@@ -72,9 +74,13 @@ import { SdGap } from "../gap/sd-gap";
72
74
  `,
73
75
  ],
74
76
  host: {
77
+ "[attr.tabindex]": "'0'",
78
+ "[attr.data-sd-select-mode]": "_parentControl.selectMode()",
75
79
  "[attr.data-sd-selected]": "isSelected()",
76
80
  "[attr.data-sd-disabled]": "disabled()",
77
81
  "[attr.data-sd-hidden]": "hidden()",
82
+ "(click)": "onClick($event)",
83
+ "(keydown)": "onKeydown($event)",
78
84
  },
79
85
  })
80
86
  export class SdSelectItem<T> {
@@ -84,7 +90,7 @@ export class SdSelectItem<T> {
84
90
  private readonly _elRef = inject(ElementRef<HTMLElement>);
85
91
  private readonly _destroyRef = inject(DestroyRef);
86
92
 
87
- value = input.required<T>();
93
+ value = input<T | undefined>(undefined);
88
94
  disabled = input(false, { transform: booleanAttribute });
89
95
  hidden = input(false, { transform: booleanAttribute });
90
96
 
@@ -95,7 +101,7 @@ export class SdSelectItem<T> {
95
101
  const itemValue = this.value();
96
102
  if (this._parentControl.selectMode() === "multi") {
97
103
  const arr = parentValue as T[] | undefined;
98
- return arr != null && arr.includes(itemValue);
104
+ return arr != null && arr.includes(itemValue as T);
99
105
  }
100
106
  return parentValue === itemValue;
101
107
  });
@@ -116,7 +122,9 @@ export class SdSelectItem<T> {
116
122
  });
117
123
  }
118
124
 
119
- onClick(): void {
125
+ onClick(event: MouseEvent): void {
126
+ event.preventDefault();
127
+ event.stopPropagation();
120
128
  if (this.disabled()) return;
121
129
  this._parentControl.selectItem(this.value());
122
130
  }
@@ -51,10 +51,10 @@ export type SelectModeValue<T> = {
51
51
  <sd-dropdown [disabled]="disabled()" [(open)]="dropdownOpen">
52
52
  <div class="_sd-select-control" [sdRipple]="!disabled()">
53
53
  <div class="_sd-select-control-content" #contentEl>
54
- @if (_selectedItemContentHTML() !== undefined) {
54
+ @if (_selectedItemContentHTML() != null) {
55
55
  <div [innerHTML]="_selectedItemContentHTML()"></div>
56
56
  } @else if (placeholder()) {
57
- <span class="tx-trans-lighter">{{ placeholder() }}</span>
57
+ <span class="sd-text-color-gray-default">{{ placeholder() }}</span>
58
58
  } @else {
59
59
  <span>&nbsp;</span>
60
60
  }
@@ -83,7 +83,7 @@ export type SelectModeValue<T> = {
83
83
  <ng-template [ngTemplateOutlet]="_beforeTpl()!" />
84
84
  }
85
85
  @if (_itemOfTpl(); as tpl) {
86
- @for (item of _flatItems(); track item) {
86
+ @for (item of _flatItems(); track trackByFn()(item.data, item.index)) {
87
87
  <ng-template
88
88
  [ngTemplateOutlet]="tpl"
89
89
  [ngTemplateOutletContext]="{ $implicit: item.data, item: item.data, index: item.index, depth: item.depth }"
@@ -97,23 +97,33 @@ export type SelectModeValue<T> = {
97
97
  `,
98
98
  styles: [
99
99
  /* language=SCSS */ `
100
- @use "../../../scss/commons/mixins";
101
-
102
100
  sd-select {
103
101
  display: block;
104
102
  position: relative;
103
+ width: 100%;
104
+ min-width: 10em;
105
105
 
106
106
  > sd-dropdown {
107
+ display: flex;
108
+ overflow: hidden;
109
+
110
+ border: 1px solid var(--trans-lighter);
111
+ border-radius: var(--border-radius-default);
112
+ background: var(--theme-secondary-lightest);
113
+
114
+ &:focus,
115
+ &:focus-within {
116
+ border-color: var(--theme-primary-default);
117
+ }
118
+
107
119
  > ._sd-select-control {
108
- @include mixins.form-control-base();
109
120
  display: flex;
110
- align-items: center;
121
+ position: relative;
122
+ gap: var(--gap-default);
123
+ flex-grow: 1;
124
+ padding: var(--gap-sm) var(--gap-default);
111
125
  cursor: pointer;
112
126
 
113
- border: 1px solid var(--trans-lighter);
114
- border-radius: var(--border-radius-default);
115
- background: var(--theme-secondary-lightest);
116
-
117
127
  > ._sd-select-control-content {
118
128
  flex: 1;
119
129
  overflow: hidden;
@@ -122,45 +132,103 @@ export type SelectModeValue<T> = {
122
132
  }
123
133
 
124
134
  > ._sd-select-control-icon {
125
- margin-left: var(--gap-sm);
126
135
  opacity: 0.3;
127
136
  }
137
+
138
+ &:hover > ._sd-select-control-icon,
139
+ &:focus > ._sd-select-control-icon,
140
+ &:active > ._sd-select-control-icon {
141
+ opacity: 1;
142
+ }
128
143
  }
129
144
 
130
- &:focus-within > ._sd-select-control {
131
- border-color: var(--theme-secondary-default);
145
+ > sd-select-button {
146
+ padding: var(--gap-sm);
147
+ border-left: 1px solid var(--theme-gray-lightest);
148
+
149
+ &:last-of-type {
150
+ border-top-right-radius: var(--border-radius-default);
151
+ border-bottom-right-radius: var(--border-radius-default);
152
+ }
132
153
  }
133
154
  }
134
155
 
135
- &[data-sd-size="sm"] > sd-dropdown > ._sd-select-control {
136
- padding: var(--gap-xs) var(--gap-sm);
137
- }
156
+ &[data-sd-disabled="true"] {
157
+ > sd-dropdown {
158
+ background: var(--theme-gray-lightest);
138
159
 
139
- &[data-sd-size="lg"] > sd-dropdown > ._sd-select-control {
140
- padding: var(--gap-default) var(--gap-lg);
160
+ > ._sd-select-control {
161
+ color: var(--text-trans-light);
162
+ cursor: default;
163
+
164
+ > ._sd-select-control-icon {
165
+ display: none;
166
+ }
167
+ }
168
+ }
141
169
  }
142
170
 
143
171
  &[data-sd-inline="true"] {
144
172
  display: inline-block;
145
173
  width: auto;
174
+ vertical-align: top;
146
175
  }
147
176
 
148
- &[data-sd-inset="true"] > sd-dropdown > ._sd-select-control {
149
- border: none;
150
- border-radius: 0;
177
+ &[data-sd-size="sm"] {
178
+ > sd-dropdown {
179
+ > ._sd-select-control {
180
+ padding: var(--gap-xs) var(--gap-sm);
181
+ gap: var(--gap-sm);
182
+ }
151
183
 
152
- &:focus-within {
153
- outline: 1px solid var(--theme-primary-default);
184
+ > sd-select-button {
185
+ padding: var(--gap-xs);
186
+ }
154
187
  }
155
188
  }
156
189
 
157
- &[data-sd-disabled="true"] {
158
- > sd-dropdown > ._sd-select-control {
159
- background: var(--trans-lighter);
160
- cursor: default;
190
+ &[data-sd-size="lg"] {
191
+ > sd-dropdown {
192
+ > ._sd-select-control {
193
+ padding: var(--gap-default) var(--gap-lg);
194
+ gap: var(--gap-lg);
195
+ }
161
196
 
162
- > ._sd-select-control-icon {
163
- display: none;
197
+ > sd-select-button {
198
+ padding: var(--gap-default);
199
+ }
200
+ }
201
+ }
202
+
203
+ &[data-sd-inset="true"] {
204
+ min-width: auto;
205
+ border-radius: 0;
206
+
207
+ > sd-dropdown {
208
+ border: none;
209
+ border-radius: 0;
210
+
211
+ > sd-select-button {
212
+ border-radius: 0;
213
+ }
214
+
215
+ &:focus,
216
+ &:focus-within {
217
+ outline: 1px solid var(--theme-primary-default);
218
+ outline-offset: -1px;
219
+
220
+ > sd-select-button {
221
+ outline: 1px solid var(--theme-primary-default);
222
+ outline-offset: -1px;
223
+ }
224
+ }
225
+ }
226
+
227
+ &[data-sd-disabled="true"] > sd-dropdown {
228
+ background: var(--control-color);
229
+
230
+ > ._sd-select-control {
231
+ color: var(--text-trans-default);
164
232
  }
165
233
  }
166
234
  }
@@ -194,12 +262,13 @@ export class SdSelect<M extends "single" | "multi", T> {
194
262
  multiSelectionDisplayDirection = input<"vertical">();
195
263
 
196
264
  items = input<T[]>();
265
+ trackByFn = input<(item: T, index: number) => unknown>((item) => item);
197
266
  getChildrenFn = input<(item: T) => T[] | undefined>();
198
267
 
199
268
  contentClass = input<string>();
200
269
  contentStyle = input<string>();
201
270
 
202
- dropdownOpen = signal(false);
271
+ dropdownOpen = model(false);
203
272
 
204
273
  protected readonly tablerCaretDown = tablerCaretDown;
205
274
 
@@ -225,9 +294,9 @@ export class SdSelect<M extends "single" | "multi", T> {
225
294
  const walk = (list: T[], depth: number) => {
226
295
  for (const item of list) {
227
296
  flat.push({ data: item, index: index++, depth });
228
- if (getChildren !== undefined) {
297
+ if (getChildren != null) {
229
298
  const children = getChildren(item);
230
- if (children !== undefined) {
299
+ if (children != null) {
231
300
  walk(children, depth + 1);
232
301
  }
233
302
  }
@@ -254,7 +323,7 @@ export class SdSelect<M extends "single" | "multi", T> {
254
323
  const popupEl = this._dropdownControl().popupElRef().nativeElement;
255
324
  const cls = this.contentClass();
256
325
  const addedClasses: string[] = [];
257
- if (cls !== undefined) {
326
+ if (cls != null) {
258
327
  for (const c of cls.split(" ").filter(Boolean)) {
259
328
  popupEl.classList.add(c);
260
329
  addedClasses.push(c);
@@ -262,7 +331,7 @@ export class SdSelect<M extends "single" | "multi", T> {
262
331
  }
263
332
  const style = this.contentStyle();
264
333
  const addedStyleProps: string[] = [];
265
- if (style !== undefined) {
334
+ if (style != null) {
266
335
  const tempEl = document.createElement("div");
267
336
  tempEl.style.cssText = style;
268
337
  for (let i = 0; i < tempEl.style.length; i++) {
@@ -330,12 +399,13 @@ export class SdSelect<M extends "single" | "multi", T> {
330
399
 
331
400
  const selectedItems = untracked(() => items.filter((item) => arr.includes(item.value())));
332
401
 
333
- const separator = this.multiSelectionDisplayDirection() === "vertical" ? "<br>" : ", ";
402
+ const isVertical = this.multiSelectionDisplayDirection() === "vertical";
403
+ const separator = isVertical ? "<div class='p-sm-0'></div>" : ", ";
334
404
  const htmlParts: string[] = [];
335
405
  for (const item of selectedItems) {
336
406
  const html = item.contentHTML();
337
407
  if (html !== "") {
338
- htmlParts.push(html);
408
+ htmlParts.push(`<span style="display: inline">${html}</span>`);
339
409
  }
340
410
  }
341
411
  if (htmlParts.length > 0) {
@@ -360,24 +430,24 @@ export class SdSelect<M extends "single" | "multi", T> {
360
430
  });
361
431
  }
362
432
 
363
- selectItem(itemValue: T): void {
433
+ selectItem(itemValue: T | undefined): void {
364
434
  this._setOrToggle(itemValue);
365
435
  if (this.selectMode() === "single") {
366
436
  this.closeDropdown();
367
437
  }
368
438
  }
369
439
 
370
- toggleItem(itemValue: T): void {
440
+ toggleItem(itemValue: T | undefined): void {
371
441
  this._setOrToggle(itemValue);
372
442
  }
373
443
 
374
- private _setOrToggle(itemValue: T): void {
444
+ private _setOrToggle(itemValue: T | undefined): void {
375
445
  if (this.selectMode() === "single") {
376
446
  this.value.set(itemValue);
377
447
  } else {
378
448
  this.value.update((v) => {
379
449
  const arr = (v as T[] | undefined) ?? [];
380
- if (arr.includes(itemValue)) {
450
+ if (arr.includes(itemValue as T)) {
381
451
  return arr.filter((item) => item !== itemValue);
382
452
  } else {
383
453
  return [...arr, itemValue];
@@ -28,7 +28,7 @@ export abstract class SdAppStructureUtils {
28
28
  permKeys: K[],
29
29
  permRecord: Record<string, boolean> | undefined,
30
30
  ): K[] {
31
- if (permRecord === undefined) return [] as K[];
31
+ if (permRecord == null) return [] as K[];
32
32
 
33
33
  const result = [] as K[];
34
34
  for (const permKey of permKeys) {