@simplysm/angular 14.1.20 → 14.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. package/dist/controls/button/sd-additional-button.js +2 -2
  2. package/dist/controls/button/sd-anchor.d.ts.map +1 -1
  3. package/dist/controls/button/sd-anchor.js +3 -3
  4. package/dist/controls/button/sd-button.d.ts.map +1 -1
  5. package/dist/controls/button/sd-button.js +3 -3
  6. package/dist/controls/button/sd-modal-select-button.d.ts.map +1 -1
  7. package/dist/controls/button/sd-modal-select-button.js +2 -2
  8. package/dist/controls/checkbox/sd-checkbox.d.ts.map +1 -1
  9. package/dist/controls/checkbox/sd-checkbox.js +3 -3
  10. package/dist/controls/checkbox/sd-switch.d.ts.map +1 -1
  11. package/dist/controls/checkbox/sd-switch.js +3 -3
  12. package/dist/controls/collapse/sd-collapse-icon.d.ts +1 -1
  13. package/dist/controls/collapse/sd-collapse-icon.d.ts.map +1 -1
  14. package/dist/controls/collapse/sd-collapse-icon.js +2 -2
  15. package/dist/controls/collapse/sd-collapse.d.ts +1 -1
  16. package/dist/controls/collapse/sd-collapse.d.ts.map +1 -1
  17. package/dist/controls/collapse/sd-collapse.js +2 -2
  18. package/dist/controls/dropdown/sd-dropdown-popup.d.ts.map +1 -1
  19. package/dist/controls/dropdown/sd-dropdown-popup.js +2 -2
  20. package/dist/controls/dropdown/sd-dropdown.js +1 -1
  21. package/dist/controls/gap/sd-gap.d.ts.map +1 -1
  22. package/dist/controls/gap/sd-gap.js +5 -7
  23. package/dist/controls/input/sd-date-range-picker.js +2 -2
  24. package/dist/controls/input/sd-numpad.d.ts.map +1 -1
  25. package/dist/controls/input/sd-numpad.js +7 -15
  26. package/dist/controls/input/sd-range.js +2 -2
  27. package/dist/controls/input/sd-textarea.js +4 -4
  28. package/dist/controls/input/sd-textfield.d.ts.map +1 -1
  29. package/dist/controls/input/sd-textfield.js +10 -10
  30. package/dist/controls/list/sd-list-item.js +43 -43
  31. package/dist/controls/list/sd-list.js +2 -2
  32. package/dist/controls/pagination/sd-pagination.d.ts.map +1 -1
  33. package/dist/controls/pagination/sd-pagination.js +7 -5
  34. package/dist/controls/select/sd-select-button.d.ts.map +1 -1
  35. package/dist/controls/select/sd-select-button.js +4 -4
  36. package/dist/controls/select/sd-select-item.d.ts.map +1 -1
  37. package/dist/controls/select/sd-select-item.js +3 -3
  38. package/dist/controls/select/sd-select.d.ts.map +1 -1
  39. package/dist/controls/select/sd-select.js +10 -19
  40. package/dist/controls/tab/sd-tab-item.js +2 -2
  41. package/dist/controls/tab/sd-tab.js +2 -2
  42. package/dist/core/busy/sd-busy-container.d.ts.map +1 -1
  43. package/dist/core/busy/sd-busy-container.js +3 -3
  44. package/dist/core/modal/sd-modal.d.ts.map +1 -1
  45. package/dist/core/modal/sd-modal.js +3 -3
  46. package/dist/core/provideSdAngular.d.ts.map +1 -1
  47. package/dist/core/provideSdAngular.js +31 -10
  48. package/dist/core/ripple/setupRipple.js +2 -2
  49. package/dist/core/setupBgTheme.d.ts +0 -1
  50. package/dist/core/setupBgTheme.d.ts.map +1 -1
  51. package/dist/core/setupBgTheme.js +3 -4
  52. package/dist/core/show-effect/setupRevealOnShow.js +1 -1
  53. package/dist/core/toast/sd-toast-container.js +2 -2
  54. package/dist/core/toast/sd-toast.d.ts.map +1 -1
  55. package/dist/core/toast/sd-toast.js +3 -3
  56. package/dist/core/validation/setupInvalid.js +5 -5
  57. package/dist/data/crud/sd-base-container.d.ts.map +1 -1
  58. package/dist/data/crud/sd-base-container.js +50 -52
  59. package/dist/data/kanban/sd-kanban-board.js +2 -2
  60. package/dist/data/kanban/sd-kanban-lane.d.ts.map +1 -1
  61. package/dist/data/kanban/sd-kanban-lane.js +4 -4
  62. package/dist/data/kanban/sd-kanban.d.ts.map +1 -1
  63. package/dist/data/kanban/sd-kanban.js +4 -4
  64. package/dist/data/permission-table/sd-permission-table.d.ts.map +1 -1
  65. package/dist/data/permission-table/sd-permission-table.js +5 -17
  66. package/dist/data/shared-data/sd-shared-data-select-list.d.ts.map +1 -1
  67. package/dist/data/shared-data/sd-shared-data-select-list.js +5 -19
  68. package/dist/data/shared-data/sd-shared-data-select.d.ts.map +1 -1
  69. package/dist/data/shared-data/sd-shared-data-select.js +8 -15
  70. package/dist/data/sheet/sd-sheet-config.modal.d.ts.map +1 -1
  71. package/dist/data/sheet/sd-sheet-config.modal.js +7 -9
  72. package/dist/data/sheet/sd-sheet.d.ts.map +1 -1
  73. package/dist/data/sheet/sd-sheet.js +10 -12
  74. package/dist/data/sheet/useSheetCellStyling.d.ts.map +1 -1
  75. package/dist/data/sheet/useSheetCellStyling.js +1 -1
  76. package/dist/data/state-preset/sd-state-preset.js +5 -5
  77. package/dist/features/editor/sd-markdown-editor.d.ts.map +1 -1
  78. package/dist/features/editor/sd-markdown-editor.js +85 -34
  79. package/dist/features/editor/sd-tiptap-editor.d.ts.map +1 -1
  80. package/dist/features/editor/sd-tiptap-editor.js +192 -61
  81. package/dist/features/theme/sd-theme-provider.d.ts +18 -1
  82. package/dist/features/theme/sd-theme-provider.d.ts.map +1 -1
  83. package/dist/features/theme/sd-theme-provider.js +21 -4
  84. package/dist/features/theme/sd-theme-selector.d.ts.map +1 -1
  85. package/dist/features/theme/sd-theme-selector.js +50 -9
  86. package/dist/features/theme/wcag-contrast.d.ts +9 -0
  87. package/dist/features/theme/wcag-contrast.d.ts.map +1 -0
  88. package/dist/features/theme/wcag-contrast.js +83 -0
  89. package/dist/features/visual/sd-calendar.js +2 -2
  90. package/dist/features/visual/sd-label.d.ts.map +1 -1
  91. package/dist/features/visual/sd-label.js +5 -5
  92. package/dist/features/visual/sd-note.d.ts.map +1 -1
  93. package/dist/features/visual/sd-note.js +3 -3
  94. package/dist/features/visual/sd-progress.d.ts.map +1 -1
  95. package/dist/features/visual/sd-progress.js +3 -3
  96. package/dist/index.d.ts +12 -11
  97. package/dist/index.d.ts.map +1 -1
  98. package/dist/index.js +10 -9
  99. package/dist/layout/sidebar/sd-sidebar-container.d.ts.map +1 -1
  100. package/dist/layout/sidebar/sd-sidebar-container.js +11 -5
  101. package/dist/layout/sidebar/sd-sidebar-menu.d.ts.map +1 -1
  102. package/dist/layout/sidebar/sd-sidebar-menu.js +5 -17
  103. package/dist/layout/sidebar/sd-sidebar-user.js +32 -32
  104. package/dist/layout/sidebar/sd-sidebar.d.ts.map +1 -1
  105. package/dist/layout/sidebar/sd-sidebar.js +3 -3
  106. package/dist/layout/topbar/sd-topbar-menu.js +5 -5
  107. package/dist/layout/topbar/sd-topbar.d.ts.map +1 -1
  108. package/dist/layout/topbar/sd-topbar.js +5 -5
  109. package/package.json +5 -5
  110. package/scss/commons/_colors.scss +296 -242
  111. package/scss/commons/_density.scss +23 -0
  112. package/scss/commons/_mixins.scss +142 -129
  113. package/scss/commons/_styles.scss +78 -103
  114. package/scss/commons/_theme-variables.scss +16 -2
  115. package/scss/commons/_variables.scss +277 -149
  116. package/scss/controls/_card.scss +12 -8
  117. package/scss/controls/_form-box.scss +7 -7
  118. package/scss/controls/_form-table.scss +7 -7
  119. package/scss/controls/_table.scss +5 -5
  120. package/scss/sd-tokens.md +132 -0
  121. package/scss/styles.scss +3 -4
  122. package/scss/themes/_variables-blueprint.scss +127 -81
  123. package/scss/themes/_variables-ide-dark.scss +215 -0
  124. package/src/controls/button/sd-additional-button.ts +12 -12
  125. package/src/controls/button/sd-anchor.ts +7 -8
  126. package/src/controls/button/sd-button.ts +42 -44
  127. package/src/controls/button/sd-modal-select-button.ts +15 -19
  128. package/src/controls/checkbox/sd-checkbox.ts +55 -43
  129. package/src/controls/checkbox/sd-switch.ts +18 -19
  130. package/src/controls/collapse/sd-collapse-icon.ts +2 -2
  131. package/src/controls/collapse/sd-collapse.ts +2 -2
  132. package/src/controls/dropdown/sd-dropdown-popup.ts +10 -12
  133. package/src/controls/dropdown/sd-dropdown.ts +1 -1
  134. package/src/controls/gap/sd-gap.ts +11 -9
  135. package/src/controls/input/sd-date-range-picker.ts +1 -1
  136. package/src/controls/input/sd-numpad.ts +3 -11
  137. package/src/controls/input/sd-range.ts +1 -1
  138. package/src/controls/input/sd-textarea.ts +18 -18
  139. package/src/controls/input/sd-textfield.ts +39 -37
  140. package/src/controls/list/sd-list-item.ts +195 -195
  141. package/src/controls/list/sd-list.ts +8 -8
  142. package/src/controls/pagination/sd-pagination.ts +4 -2
  143. package/src/controls/select/sd-select-button.ts +6 -10
  144. package/src/controls/select/sd-select-item.ts +14 -15
  145. package/src/controls/select/sd-select.ts +34 -35
  146. package/src/controls/tab/sd-tab-item.ts +4 -4
  147. package/src/controls/tab/sd-tab.ts +2 -2
  148. package/src/core/busy/sd-busy-container.ts +17 -16
  149. package/src/core/modal/sd-modal.ts +38 -32
  150. package/src/core/provideSdAngular.ts +34 -10
  151. package/src/core/ripple/setupRipple.ts +2 -2
  152. package/src/core/setupBgTheme.ts +5 -14
  153. package/src/core/show-effect/setupRevealOnShow.ts +1 -1
  154. package/src/core/toast/sd-toast-container.ts +5 -5
  155. package/src/core/toast/sd-toast.ts +16 -17
  156. package/src/core/validation/setupInvalid.ts +5 -5
  157. package/src/data/crud/sd-base-container.ts +120 -122
  158. package/src/data/kanban/sd-kanban-board.ts +1 -1
  159. package/src/data/kanban/sd-kanban-lane.ts +9 -14
  160. package/src/data/kanban/sd-kanban.ts +9 -19
  161. package/src/data/permission-table/sd-permission-table.ts +12 -20
  162. package/src/data/shared-data/sd-shared-data-select-list.ts +5 -19
  163. package/src/data/shared-data/sd-shared-data-select.ts +11 -28
  164. package/src/data/sheet/sd-sheet-config.modal.ts +5 -7
  165. package/src/data/sheet/sd-sheet.ts +29 -28
  166. package/src/data/sheet/useSheetCellStyling.ts +12 -3
  167. package/src/data/state-preset/sd-state-preset.ts +16 -16
  168. package/src/features/editor/sd-markdown-editor.ts +110 -56
  169. package/src/features/editor/sd-tiptap-editor.ts +214 -81
  170. package/src/features/theme/sd-theme-provider.ts +28 -3
  171. package/src/features/theme/sd-theme-selector.ts +21 -2
  172. package/src/features/theme/wcag-contrast.ts +103 -0
  173. package/src/features/visual/sd-calendar.ts +8 -8
  174. package/src/features/visual/sd-label.ts +11 -12
  175. package/src/features/visual/sd-note.ts +10 -11
  176. package/src/features/visual/sd-progress.ts +9 -11
  177. package/src/index.ts +15 -40
  178. package/src/layout/sidebar/sd-sidebar-container.ts +21 -8
  179. package/src/layout/sidebar/sd-sidebar-menu.ts +15 -17
  180. package/src/layout/sidebar/sd-sidebar-user.ts +100 -100
  181. package/src/layout/sidebar/sd-sidebar.ts +7 -9
  182. package/src/layout/topbar/sd-topbar-menu.ts +3 -3
  183. package/src/layout/topbar/sd-topbar.ts +12 -14
  184. package/styles.css +1641 -2462
  185. package/scss/themes/_blueprint-surfaces.scss +0 -87
@@ -39,15 +39,7 @@ export type SelectModeValue<T> = {
39
39
  changeDetection: ChangeDetectionStrategy.OnPush,
40
40
  encapsulation: ViewEncapsulation.None,
41
41
  standalone: true,
42
- imports: [
43
- SdDropdown,
44
- SdDropdownPopup,
45
- SdAnchor,
46
- SdGap,
47
- NgTemplateOutlet,
48
- SdRipple,
49
- NgIcon,
50
- ],
42
+ imports: [SdDropdown, SdDropdownPopup, SdAnchor, SdGap, NgTemplateOutlet, SdRipple, NgIcon],
51
43
  template: `
52
44
  <sd-dropdown [disabled]="disabled()" [(open)]="dropdownOpen">
53
45
  <div
@@ -92,7 +84,12 @@ export type SelectModeValue<T> = {
92
84
  @for (item of _flatItems(); track trackByFn()(item.data, item.index)) {
93
85
  <ng-template
94
86
  [ngTemplateOutlet]="tpl"
95
- [ngTemplateOutletContext]="{ $implicit: item.data, item: item.data, index: item.index, depth: item.depth }"
87
+ [ngTemplateOutletContext]="{
88
+ $implicit: item.data,
89
+ item: item.data,
90
+ index: item.index,
91
+ depth: item.depth,
92
+ }"
96
93
  />
97
94
  }
98
95
  } @else {
@@ -113,23 +110,23 @@ export type SelectModeValue<T> = {
113
110
  display: flex;
114
111
  overflow: hidden;
115
112
 
116
- border: 1px solid var(--border-color-light);
117
- border-radius: var(--border-radius-default);
118
- background: var(--theme-secondary-lightest);
113
+ border: 1px solid var(--sd-bd-field);
114
+ border-radius: var(--sd-radius-default);
115
+ background-color: var(--sd-bg-field);
119
116
 
120
117
  &:focus,
121
118
  &:focus-within {
122
- border-color: var(--theme-primary-default);
119
+ border-color: var(--sd-focus-ring-color);
123
120
  }
124
121
 
125
122
  > ._sd-select-control {
126
123
  display: flex;
127
124
  position: relative;
128
- gap: var(--gap-default);
125
+ gap: var(--sd-gap-default);
129
126
  flex-grow: 1;
130
- padding: var(--gap-sm) var(--gap-default);
127
+ padding: var(--sd-gap-sm) var(--sd-gap-default);
131
128
  cursor: pointer;
132
- font-family: var(--font-family-field);
129
+ font-family: var(--sd-font-family-field);
133
130
 
134
131
  > ._sd-select-control-content {
135
132
  flex: 1;
@@ -150,22 +147,23 @@ export type SelectModeValue<T> = {
150
147
  }
151
148
 
152
149
  > sd-select-button {
153
- padding: var(--gap-sm);
154
- border-left: 1px solid var(--theme-gray-lightest);
150
+ padding: var(--sd-gap-sm);
151
+ border-left: 1px solid var(--sd-bd-hairline);
155
152
 
156
153
  &:last-of-type {
157
- border-top-right-radius: var(--border-radius-default);
158
- border-bottom-right-radius: var(--border-radius-default);
154
+ border-top-right-radius: var(--sd-radius-default);
155
+ border-bottom-right-radius: var(--sd-radius-default);
159
156
  }
160
157
  }
161
158
  }
162
159
 
160
+ // disabled 는 색 치환 단일 규약 (DEC-009)
163
161
  &[data-sd-disabled="true"] {
164
162
  > sd-dropdown {
165
- background: var(--theme-gray-lightest);
163
+ background-color: var(--sd-bg-disabled);
166
164
 
167
165
  > ._sd-select-control {
168
- color: var(--text-trans-light);
166
+ color: var(--sd-tx-disabled);
169
167
  cursor: default;
170
168
 
171
169
  > ._sd-select-control-icon {
@@ -184,12 +182,12 @@ export type SelectModeValue<T> = {
184
182
  &[data-sd-size="sm"] {
185
183
  > sd-dropdown {
186
184
  > ._sd-select-control {
187
- padding: var(--gap-xs) var(--gap-sm);
188
- gap: var(--gap-sm);
185
+ padding: var(--sd-gap-xs) var(--sd-gap-sm);
186
+ gap: var(--sd-gap-sm);
189
187
  }
190
188
 
191
189
  > sd-select-button {
192
- padding: var(--gap-xs);
190
+ padding: var(--sd-gap-xs);
193
191
  }
194
192
  }
195
193
  }
@@ -197,12 +195,12 @@ export type SelectModeValue<T> = {
197
195
  &[data-sd-size="lg"] {
198
196
  > sd-dropdown {
199
197
  > ._sd-select-control {
200
- padding: var(--gap-default) var(--gap-lg);
201
- gap: var(--gap-lg);
198
+ padding: var(--sd-gap-default) var(--sd-gap-lg);
199
+ gap: var(--sd-gap-lg);
202
200
  }
203
201
 
204
202
  > sd-select-button {
205
- padding: var(--gap-default);
203
+ padding: var(--sd-gap-default);
206
204
  }
207
205
  }
208
206
  }
@@ -221,21 +219,22 @@ export type SelectModeValue<T> = {
221
219
 
222
220
  &:focus,
223
221
  &:focus-within {
224
- outline: 1px solid var(--theme-primary-default);
222
+ outline: 1px solid var(--sd-focus-ring-color);
225
223
  outline-offset: -1px;
226
224
 
227
225
  > sd-select-button {
228
- outline: 1px solid var(--theme-primary-default);
226
+ outline: 1px solid var(--sd-focus-ring-color);
229
227
  outline-offset: -1px;
230
228
  }
231
229
  }
232
230
  }
233
231
 
232
+ // inset(시트 셀 등)의 disabled 는 일반 콘텐츠처럼 표시(현행 유지)
234
233
  &[data-sd-disabled="true"] > sd-dropdown {
235
- background: var(--control-color);
234
+ background-color: var(--sd-bg-control);
236
235
 
237
236
  > ._sd-select-control {
238
- color: var(--text-trans-default);
237
+ color: var(--sd-tx-default);
239
238
  }
240
239
  }
241
240
  }
@@ -243,8 +242,8 @@ export type SelectModeValue<T> = {
243
242
 
244
243
  ._sd-select-all-bar {
245
244
  display: flex;
246
- padding: var(--gap-sm) var(--gap-default);
247
- border-bottom: 1px solid var(--border-color-light);
245
+ padding: var(--sd-gap-sm) var(--sd-gap-default);
246
+ border-bottom: 1px solid var(--sd-bd-default);
248
247
  }
249
248
  `,
250
249
  ],
@@ -26,17 +26,17 @@ import { SdTab } from "./sd-tab";
26
26
  /* language=SCSS */ `
27
27
  sd-tab-item {
28
28
  display: inline-block;
29
- padding: var(--gap-sm) var(--gap-default);
29
+ padding: var(--sd-gap-sm) var(--sd-gap-default);
30
30
  cursor: pointer;
31
31
  margin-bottom: -2px;
32
32
 
33
33
  border-bottom: 2px solid transparent !important;
34
34
  font-weight: bold;
35
- color: var(--theme-gray-default);
35
+ color: var(--sd-tx-gray);
36
36
 
37
37
  &[data-sd-selected="true"] {
38
- border-bottom: 3px solid var(--theme-primary-default) !important;
39
- color: var(--theme-primary-default);
38
+ border-bottom: 3px solid var(--sd-bd-primary-solid) !important;
39
+ color: var(--sd-tx-primary);
40
40
  }
41
41
  }
42
42
  `,
@@ -10,9 +10,9 @@ import { ChangeDetectionStrategy, Component, model, ViewEncapsulation } from "@a
10
10
  /* language=SCSS */ `
11
11
  sd-tab {
12
12
  display: block;
13
- border-bottom: 2px solid var(--theme-gray-lighter);
13
+ border-bottom: 2px solid var(--sd-bd-hairline);
14
14
 
15
- padding: 0 calc(var(--gap-default) + 1px) 0 calc(var(--gap-default) - 1px);
15
+ padding: 0 calc(var(--sd-gap-default) + 1px) 0 calc(var(--sd-gap-default) - 1px);
16
16
  }
17
17
  `,
18
18
  ],
@@ -77,13 +77,13 @@ import { SdBusyProvider, type SdBusyType } from "./sd-busy.provider";
77
77
  left: 0;
78
78
  width: 100%;
79
79
  height: 100%;
80
- z-index: map.get(variables.$vars, z-index, busy);
80
+ z-index: map.get(variables.$sd, z, busy);
81
81
 
82
82
  visibility: hidden;
83
83
  pointer-events: none;
84
84
 
85
85
  opacity: 0;
86
- transition: opacity var(--animation-duration);
86
+ transition: opacity var(--sd-animation-duration);
87
87
  transition-timing-function: linear;
88
88
 
89
89
  > ._progress {
@@ -93,7 +93,7 @@ import { SdBusyProvider, type SdBusyType } from "./sd-busy.provider";
93
93
  left: 0;
94
94
  height: 4px;
95
95
  width: 100%;
96
- background-color: var(--background-color);
96
+ background-color: var(--sd-bg-canvas);
97
97
 
98
98
  > ._progress-bar {
99
99
  position: absolute;
@@ -103,11 +103,11 @@ import { SdBusyProvider, type SdBusyType } from "./sd-busy.provider";
103
103
  content: "";
104
104
  height: 4px;
105
105
  width: 100%;
106
- transition: var(--animation-duration) ease-in;
106
+ transition: var(--sd-animation-duration) ease-in;
107
107
  transition-property: transform;
108
108
  transform-origin: left;
109
109
  transform: scaleX(0);
110
- background-color: var(--theme-primary-default);
110
+ background-color: var(--sd-bg-primary-solid);
111
111
  }
112
112
  }
113
113
  }
@@ -124,7 +124,7 @@ import { SdBusyProvider, type SdBusyType } from "./sd-busy.provider";
124
124
  &[data-sd-type="spinner"] {
125
125
  > ._screen > ._rect {
126
126
  transform: translateY(-100%);
127
- transition: var(--animation-duration) ease-in;
127
+ transition: var(--sd-animation-duration) ease-in;
128
128
  transition-property: transform;
129
129
 
130
130
  > ._indicator {
@@ -132,11 +132,12 @@ import { SdBusyProvider, type SdBusyType } from "./sd-busy.provider";
132
132
  width: 30px;
133
133
  height: 30px;
134
134
  margin: 20px auto 0 auto;
135
- border: 6px solid var(--background-color);
135
+ // 링은 캔버스색, 하단 호는 primary 면색을 그대로 사용하는 그래픽
136
+ border: 6px solid var(--sd-bg-canvas);
136
137
  border-radius: 100%;
137
- border-bottom-color: var(--theme-primary-default);
138
+ border-bottom-color: var(--sd-bg-primary-solid);
138
139
  animation: sd-busy-spin 1s linear infinite;
139
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
140
+ box-shadow: 0 2px 4px var(--sd-shadow-color);
140
141
 
141
142
  > div {
142
143
  display: none;
@@ -147,17 +148,17 @@ import { SdBusyProvider, type SdBusyType } from "./sd-busy.provider";
147
148
  position: absolute;
148
149
  top: 55px;
149
150
  width: 100%;
150
- color: var(--background-color);
151
+ color: var(--sd-bg-canvas);
151
152
  font-weight: bold;
152
153
  text-align: center;
153
- text-shadow: 0 0 2px var(--background-rev-color);
154
+ text-shadow: 0 0 2px var(--sd-bg-inverse);
154
155
  }
155
156
  }
156
157
 
157
158
  &[data-sd-busy="true"] {
158
159
  > ._screen > ._rect {
159
160
  transform: none;
160
- transition: var(--animation-duration) ease-out;
161
+ transition: var(--sd-animation-duration) ease-out;
161
162
  }
162
163
  }
163
164
  }
@@ -173,7 +174,7 @@ import { SdBusyProvider, type SdBusyType } from "./sd-busy.provider";
173
174
  left: 0;
174
175
  height: 4px;
175
176
  width: 100%;
176
- background-color: var(--background-color);
177
+ background-color: var(--sd-bg-canvas);
177
178
 
178
179
  &:before,
179
180
  &:after {
@@ -189,12 +190,12 @@ import { SdBusyProvider, type SdBusyType } from "./sd-busy.provider";
189
190
  }
190
191
 
191
192
  &:before {
192
- background-color: var(--theme-primary-default);
193
+ background-color: var(--sd-bg-primary-solid);
193
194
  animation: sd-busy-bar-indicator-before 2s infinite ease-in;
194
195
  }
195
196
 
196
197
  &:after {
197
- background-color: var(--background-color);
198
+ background-color: var(--sd-bg-canvas);
198
199
  animation: sd-busy-bar-indicator-after 2s infinite ease-out;
199
200
  }
200
201
 
@@ -239,7 +240,7 @@ import { SdBusyProvider, type SdBusyType } from "./sd-busy.provider";
239
240
  left: 0;
240
241
  width: 100%;
241
242
  height: 100%;
242
- background-color: var(--trans-light);
243
+ background-color: var(--sd-bg-busy-indicator);
243
244
  animation: sd-busy-cube 2.4s infinite linear both;
244
245
  transform-origin: 100% 100%;
245
246
  }
@@ -118,14 +118,14 @@ import "@simplysm/core-browser";
118
118
  sd-modal {
119
119
  display: block;
120
120
  position: fixed;
121
- z-index: var(--z-index-modal);
121
+ z-index: var(--sd-z-modal);
122
122
  top: 0;
123
123
  left: 0;
124
124
  width: 100%;
125
125
  height: 100%;
126
- padding-top: calc(var(--topbar-height) + var(--gap-sm));
126
+ padding-top: calc(var(--sd-topbar-height) + var(--sd-gap-sm));
127
127
  opacity: 0;
128
- transition: opacity var(--animation-duration) ease-in-out;
128
+ transition: opacity var(--sd-animation-duration) ease-in-out;
129
129
  pointer-events: none;
130
130
 
131
131
  > ._backdrop {
@@ -134,7 +134,7 @@ import "@simplysm/core-browser";
134
134
  left: 0;
135
135
  width: 100%;
136
136
  height: 100%;
137
- background: var(--trans-default);
137
+ background-color: var(--sd-bg-backdrop);
138
138
  }
139
139
 
140
140
  > ._dialog {
@@ -144,12 +144,13 @@ import "@simplysm/core-browser";
144
144
  margin: 0 auto;
145
145
  width: fit-content;
146
146
  min-width: 200px;
147
- background: var(--control-color);
147
+ background-color: var(--sd-bg-elevated);
148
+ border: 1px solid var(--sd-modal-bd);
148
149
  overflow: hidden;
149
150
  @include mixins.elevation(16);
150
- border-radius: var(--border-radius-default);
151
+ border-radius: var(--sd-radius-default);
151
152
  transform: translateY(-25px);
152
- transition: transform var(--animation-duration) ease-in-out;
153
+ transition: transform var(--sd-animation-duration) ease-in-out;
153
154
 
154
155
  &:focus {
155
156
  outline: none;
@@ -159,16 +160,22 @@ import "@simplysm/core-browser";
159
160
  display: flex;
160
161
  align-items: center;
161
162
  user-select: none;
162
- border-bottom: 1px solid var(--theme-gray-lighter);
163
- background: var(--theme-gray-lightest);
163
+ border-bottom: 1px solid var(--sd-bd-hairline);
164
+ background-color: var(--sd-modal-header-bg);
165
+ color: var(--sd-modal-header-tx);
164
166
 
165
167
  > ._title {
166
168
  flex: 1;
167
- padding: var(--gap-sm) var(--gap-default);
169
+ padding: var(--sd-gap-sm) var(--sd-gap-default);
168
170
  }
169
171
 
170
172
  > ._close-btn {
171
- padding: var(--gap-sm) var(--gap-default);
173
+ padding: var(--sd-gap-sm) var(--sd-gap-default);
174
+ color: var(--sd-modal-header-tx-muted);
175
+
176
+ &:hover {
177
+ color: var(--sd-modal-header-tx);
178
+ }
172
179
  }
173
180
  }
174
181
 
@@ -183,7 +190,7 @@ import "@simplysm/core-browser";
183
190
  &._resize-left {
184
191
  top: 0;
185
192
  left: 0;
186
- width: var(--gap-sm);
193
+ width: var(--sd-gap-sm);
187
194
  height: 100%;
188
195
  cursor: ew-resize;
189
196
  }
@@ -191,7 +198,7 @@ import "@simplysm/core-browser";
191
198
  &._resize-right {
192
199
  top: 0;
193
200
  right: 0;
194
- width: var(--gap-sm);
201
+ width: var(--sd-gap-sm);
195
202
  height: 100%;
196
203
  cursor: ew-resize;
197
204
  }
@@ -200,15 +207,15 @@ import "@simplysm/core-browser";
200
207
  top: 0;
201
208
  left: 0;
202
209
  width: 100%;
203
- height: var(--gap-sm);
210
+ height: var(--sd-gap-sm);
204
211
  cursor: ns-resize;
205
212
  }
206
213
 
207
214
  &._resize-top-right {
208
215
  right: 0;
209
216
  top: 0;
210
- width: var(--gap-sm);
211
- height: var(--gap-sm);
217
+ width: var(--sd-gap-sm);
218
+ height: var(--sd-gap-sm);
212
219
  z-index: 1;
213
220
  cursor: nesw-resize;
214
221
  }
@@ -216,8 +223,8 @@ import "@simplysm/core-browser";
216
223
  &._resize-top-left {
217
224
  left: 0;
218
225
  top: 0;
219
- width: var(--gap-sm);
220
- height: var(--gap-sm);
226
+ width: var(--sd-gap-sm);
227
+ height: var(--sd-gap-sm);
221
228
  cursor: nwse-resize;
222
229
  z-index: 1;
223
230
  }
@@ -226,15 +233,15 @@ import "@simplysm/core-browser";
226
233
  bottom: 0;
227
234
  left: 0;
228
235
  width: 100%;
229
- height: var(--gap-sm);
236
+ height: var(--sd-gap-sm);
230
237
  cursor: ns-resize;
231
238
  }
232
239
 
233
240
  &._resize-bottom-right {
234
241
  right: 0;
235
242
  bottom: 0;
236
- width: var(--gap-sm);
237
- height: var(--gap-sm);
243
+ width: var(--sd-gap-sm);
244
+ height: var(--sd-gap-sm);
238
245
  z-index: 1;
239
246
  cursor: nwse-resize;
240
247
  }
@@ -242,8 +249,8 @@ import "@simplysm/core-browser";
242
249
  &._resize-bottom-left {
243
250
  left: 0;
244
251
  bottom: 0;
245
- width: var(--gap-sm);
246
- height: var(--gap-sm);
252
+ width: var(--sd-gap-sm);
253
+ height: var(--sd-gap-sm);
247
254
  cursor: nesw-resize;
248
255
  z-index: 1;
249
256
  }
@@ -270,7 +277,7 @@ import "@simplysm/core-browser";
270
277
  pointer-events: auto;
271
278
  opacity: 0;
272
279
  @include mixins.elevation(4);
273
- border: 1px solid var(--theme-gray-lighter);
280
+ border: 1px solid var(--sd-bd-hairline);
274
281
 
275
282
  &:focus {
276
283
  @include mixins.elevation(16);
@@ -290,16 +297,16 @@ import "@simplysm/core-browser";
290
297
  &[data-sd-position="bottom-right"] {
291
298
  > ._dialog {
292
299
  position: absolute;
293
- right: calc(var(--gap-xxl) * 2);
294
- bottom: var(--gap-xxl);
300
+ right: calc(var(--sd-gap-xxl) * 2);
301
+ bottom: var(--sd-gap-xxl);
295
302
  }
296
303
  }
297
304
 
298
305
  &[data-sd-position="top-right"] {
299
306
  > ._dialog {
300
307
  position: absolute;
301
- right: var(--gap-xxl);
302
- top: var(--gap-xxl);
308
+ right: var(--sd-gap-xxl);
309
+ top: var(--sd-gap-xxl);
303
310
  }
304
311
  }
305
312
 
@@ -313,8 +320,8 @@ import "@simplysm/core-browser";
313
320
  border-radius: 0;
314
321
 
315
322
  > ._header {
316
- background: transparent;
317
- color: var(--text-trans-lighter);
323
+ background-color: transparent;
324
+ color: var(--sd-tx-faint);
318
325
  }
319
326
  }
320
327
  }
@@ -519,8 +526,7 @@ export class SdModal {
519
526
  if (this._sdSystemConfig == null) return;
520
527
 
521
528
  const config = (await this._sdSystemConfig.getAsync(`sd-modal.${k}`)) as
522
- | Record<string, string | undefined>
523
- | undefined;
529
+ Record<string, string | undefined> | undefined;
524
530
  if (config == null) return;
525
531
 
526
532
  const dialogEl = this._getDialogEl();
@@ -25,13 +25,14 @@ import { SwUpdate } from "@angular/service-worker";
25
25
  import { provideNgIconsConfig } from "@ng-icons/core";
26
26
  import { SdBusyProvider } from "./busy/sd-busy.provider";
27
27
  import { SdAngularConfigProvider } from "./config/sd-angular-config.provider";
28
- import { SdThemeProvider } from "../features/theme/sd-theme-provider";
28
+ import { SD_THEMES, SdThemeProvider } from "../features/theme/sd-theme-provider";
29
29
  import { SdLocalStorageProvider } from "./config/sd-local-storage.provider";
30
30
  import { SdGlobalErrorHandlerPlugin } from "./error-handler/sd-global-error-handler.plugin";
31
31
  import { SdOptionEventPlugin } from "./events/sd-option-event.plugin";
32
32
  import { createLogger } from "@simplysm/core-common";
33
33
 
34
34
  const logger = createLogger("angular:sw-update");
35
+ const themeLogger = createLogger("angular:theme");
35
36
 
36
37
  export function provideSdAngular(opt: { clientName: string }): EnvironmentProviders {
37
38
  return makeEnvironmentProviders([
@@ -42,9 +43,10 @@ export function provideSdAngular(opt: { clientName: string }): EnvironmentProvid
42
43
  disableImageLazyLoadWarning: true,
43
44
  },
44
45
  },
46
+ // size 는 지정하지 않음 — 인라인 스타일로 박혀 styles.scss 의
47
+ // line-height 연동 calc(--ng-icon__size)를 덮어버림.
45
48
  provideNgIconsConfig({
46
49
  strokeWidth: 1.5,
47
- size: "1.33em",
48
50
  }),
49
51
  provideEnvironmentInitializer(() => {
50
52
  // SSR(프리렌더) 가드: 테마 저장·복원은 브라우저 전용
@@ -53,17 +55,39 @@ export function provideSdAngular(opt: { clientName: string }): EnvironmentProvid
53
55
  const sdTheme = inject(SdThemeProvider);
54
56
  const sdLocalStorage = inject(SdLocalStorageProvider);
55
57
 
56
- const savedBlueprint = sdLocalStorage.get("sd-theme-blueprint");
57
- if (savedBlueprint != null) {
58
- sdTheme.blueprint.set(savedBlueprint);
58
+ const savedTheme = sdLocalStorage.get("sd-theme");
59
+ if (savedTheme != null) {
60
+ const matched = SD_THEMES.find((def) => def.value === savedTheme);
61
+ if (matched != null) {
62
+ sdTheme.theme.set(matched.value);
63
+ } else {
64
+ // 저장된 테마가 내장 목록에 없음(구버전 제거 등) — 기본 테마 유지 + 사용자 인지용 경고
65
+ themeLogger.warn(
66
+ `저장된 테마 '${String(savedTheme)}' 가 내장 테마 목록에 없어 기본 테마로 표시합니다.`,
67
+ );
68
+ }
69
+ }
70
+
71
+ let prevTheme = sdTheme.theme();
72
+ effect(() => {
73
+ const theme = sdTheme.theme();
74
+ if (theme !== prevTheme) {
75
+ sdLocalStorage.set("sd-theme", theme);
76
+ prevTheme = theme;
77
+ }
78
+ });
79
+
80
+ const savedDensity = sdLocalStorage.get("sd-theme-density");
81
+ if (savedDensity === "compact" || savedDensity === "normal") {
82
+ sdTheme.density.set(savedDensity);
59
83
  }
60
84
 
61
- let prevBlueprint = sdTheme.blueprint();
85
+ let prevDensity = sdTheme.density();
62
86
  effect(() => {
63
- const blueprint = sdTheme.blueprint();
64
- if (blueprint !== prevBlueprint) {
65
- sdLocalStorage.set("sd-theme-blueprint", blueprint);
66
- prevBlueprint = blueprint;
87
+ const density = sdTheme.density();
88
+ if (density !== prevDensity) {
89
+ sdLocalStorage.set("sd-theme-density", density);
90
+ prevDensity = density;
67
91
  }
68
92
  });
69
93
 
@@ -35,14 +35,14 @@ export function setupRipple(enableFn?: () => boolean): void {
35
35
  position: "absolute",
36
36
  pointerEvents: "none",
37
37
  borderRadius: "100%",
38
- background: "var(--trans-light)",
38
+ backgroundColor: "var(--sd-bg-state-active)",
39
39
 
40
40
  width: size * 2 + "px",
41
41
  height: size * 2 + "px",
42
42
  top: y - size + "px",
43
43
  left: x - size + "px",
44
44
 
45
- transition: "calc(2 * var(--animation-duration)) linear",
45
+ transition: "calc(2 * var(--sd-animation-duration)) linear",
46
46
  transitionProperty: "transform, opacity",
47
47
  transform: "scale(0.1)",
48
48
  });
@@ -3,29 +3,20 @@ import { isPlatformBrowser } from "@angular/common";
3
3
 
4
4
  export function setupBgTheme(options?: {
5
5
  theme?:
6
- | "primary"
7
- | "secondary"
8
- | "info"
9
- | "success"
10
- | "warning"
11
- | "danger"
12
- | "gray"
13
- | "blue-gray";
14
- lightness?: "lightest" | "lighter";
6
+ "primary" | "secondary" | "info" | "success" | "warning" | "danger" | "gray" | "blue-gray";
15
7
  }): void {
16
8
  // SSR(프리렌더) 가드: document 반영은 브라우저 전용
17
9
  if (!isPlatformBrowser(inject(PLATFORM_ID))) return;
18
10
 
19
11
  effect((onCleanup) => {
12
+ // 앱 배경(body 가 소비하는 --sd-bg-canvas)을 시맨틱 subtle 면으로 덮는다.
20
13
  document.body.style.setProperty(
21
- "--background-color",
22
- options?.theme
23
- ? `var(--theme-${options.theme}-${options.lightness ?? "lightest"})`
24
- : "",
14
+ "--sd-bg-canvas",
15
+ options?.theme ? `var(--sd-bg-${options.theme}-subtle)` : "",
25
16
  );
26
17
 
27
18
  onCleanup(() => {
28
- document.body.style.setProperty("--background-color", "");
19
+ document.body.style.setProperty("--sd-bg-canvas", "");
29
20
  });
30
21
  });
31
22
  }
@@ -28,7 +28,7 @@ export function setupRevealOnShow(
28
28
  Object.assign(el.style, {
29
29
  opacity: "1",
30
30
  transform: "none",
31
- transitionDuration: "var(--animation-duration)",
31
+ transitionDuration: "var(--sd-animation-duration)",
32
32
  transitionTimingFunction: "ease-out",
33
33
  transitionProperty: "opacity, transform",
34
34
  });
@@ -29,8 +29,8 @@ import {
29
29
  height: 100%;
30
30
  width: 100%;
31
31
  pointer-events: none;
32
- padding: var(--gap-xxl);
33
- z-index: map.get(variables.$vars, z-index, toast);
32
+ padding: var(--sd-gap-xxl);
33
+ z-index: map.get(variables.$sd, z, toast);
34
34
 
35
35
  @include mixins.flex-direction(column);
36
36
 
@@ -43,9 +43,9 @@ import {
43
43
 
44
44
  > sd-toast {
45
45
  position: absolute;
46
- bottom: var(--gap-xxl);
47
- left: var(--gap-xxl);
48
- right: var(--gap-xxl);
46
+ bottom: var(--sd-gap-xxl);
47
+ left: var(--sd-gap-xxl);
48
+ right: var(--sd-gap-xxl);
49
49
  width: auto;
50
50
  }
51
51
  }