@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
@@ -46,56 +46,148 @@ const DEFAULT_EXTENSIONS: AnyExtension[] = [
46
46
  @if (!disabled()) {
47
47
  <div class="_toolbar">
48
48
  <div class="_btn-group">
49
- <button type="button" data-cmd="h1" [class._active]="activeStates().h1"
50
- (click)="execCmd('h1')">H1</button>
51
- <button type="button" data-cmd="h2" [class._active]="activeStates().h2"
52
- (click)="execCmd('h2')">H2</button>
49
+ <button
50
+ type="button"
51
+ data-cmd="h1"
52
+ [class._active]="activeStates().h1"
53
+ (click)="execCmd('h1')"
54
+ >
55
+ H1
56
+ </button>
57
+ <button
58
+ type="button"
59
+ data-cmd="h2"
60
+ [class._active]="activeStates().h2"
61
+ (click)="execCmd('h2')"
62
+ >
63
+ H2
64
+ </button>
53
65
  </div>
54
66
  <div class="_btn-group">
55
- <button type="button" data-cmd="bold" [class._active]="activeStates().bold"
56
- (click)="execCmd('bold')">B</button>
57
- <button type="button" data-cmd="italic" [class._active]="activeStates().italic"
58
- (click)="execCmd('italic')">I</button>
59
- <button type="button" data-cmd="underline" [class._active]="activeStates().underline"
60
- (click)="execCmd('underline')">U</button>
61
- <button type="button" data-cmd="strike" [class._active]="activeStates().strike"
62
- (click)="execCmd('strike')">S</button>
67
+ <button
68
+ type="button"
69
+ data-cmd="bold"
70
+ [class._active]="activeStates().bold"
71
+ (click)="execCmd('bold')"
72
+ >
73
+ B
74
+ </button>
75
+ <button
76
+ type="button"
77
+ data-cmd="italic"
78
+ [class._active]="activeStates().italic"
79
+ (click)="execCmd('italic')"
80
+ >
81
+ I
82
+ </button>
83
+ <button
84
+ type="button"
85
+ data-cmd="underline"
86
+ [class._active]="activeStates().underline"
87
+ (click)="execCmd('underline')"
88
+ >
89
+ U
90
+ </button>
91
+ <button
92
+ type="button"
93
+ data-cmd="strike"
94
+ [class._active]="activeStates().strike"
95
+ (click)="execCmd('strike')"
96
+ >
97
+ S
98
+ </button>
63
99
  </div>
64
100
  <div class="_btn-group">
65
- <button type="button" data-cmd="textColor" class="_color-btn"
66
- (click)="toggleColorPicker('text')">
101
+ <button
102
+ type="button"
103
+ data-cmd="textColor"
104
+ class="_color-btn"
105
+ (click)="toggleColorPicker('text')"
106
+ >
67
107
  <span class="_color-indicator" [style.background-color]="activeColor()"></span>
68
108
  A
69
109
  </button>
70
- <button type="button" data-cmd="bgColor" class="_color-btn"
71
- (click)="toggleColorPicker('bg')">
110
+ <button
111
+ type="button"
112
+ data-cmd="bgColor"
113
+ class="_color-btn"
114
+ (click)="toggleColorPicker('bg')"
115
+ >
72
116
  <span class="_color-indicator" [style.background-color]="activeBgColor()"></span>
73
117
  BG
74
118
  </button>
75
119
  </div>
76
120
  <div class="_btn-group">
77
- <button type="button" data-cmd="bulletList" [class._active]="activeStates().bulletList"
78
- (click)="execCmd('bulletList')">UL</button>
79
- <button type="button" data-cmd="orderedList" [class._active]="activeStates().orderedList"
80
- (click)="execCmd('orderedList')">OL</button>
121
+ <button
122
+ type="button"
123
+ data-cmd="bulletList"
124
+ [class._active]="activeStates().bulletList"
125
+ (click)="execCmd('bulletList')"
126
+ >
127
+ UL
128
+ </button>
129
+ <button
130
+ type="button"
131
+ data-cmd="orderedList"
132
+ [class._active]="activeStates().orderedList"
133
+ (click)="execCmd('orderedList')"
134
+ >
135
+ OL
136
+ </button>
81
137
  <button type="button" data-cmd="indent" (click)="execCmd('indent')">→</button>
82
138
  <button type="button" data-cmd="outdent" (click)="execCmd('outdent')">←</button>
83
139
  </div>
84
140
  <div class="_btn-group">
85
- <button type="button" data-cmd="blockquote" [class._active]="activeStates().blockquote"
86
- (click)="execCmd('blockquote')">❝</button>
87
- <button type="button" data-cmd="codeBlock" [class._active]="activeStates().codeBlock"
88
- (click)="execCmd('codeBlock')">&lt;/&gt;</button>
141
+ <button
142
+ type="button"
143
+ data-cmd="blockquote"
144
+ [class._active]="activeStates().blockquote"
145
+ (click)="execCmd('blockquote')"
146
+ >
147
+
148
+ </button>
149
+ <button
150
+ type="button"
151
+ data-cmd="codeBlock"
152
+ [class._active]="activeStates().codeBlock"
153
+ (click)="execCmd('codeBlock')"
154
+ >
155
+ &lt;/&gt;
156
+ </button>
89
157
  </div>
90
158
  <div class="_btn-group">
91
- <button type="button" data-cmd="alignLeft" [class._active]="activeStates().alignLeft"
92
- (click)="execCmd('alignLeft')">≡L</button>
93
- <button type="button" data-cmd="alignCenter" [class._active]="activeStates().alignCenter"
94
- (click)="execCmd('alignCenter')">≡C</button>
95
- <button type="button" data-cmd="alignRight" [class._active]="activeStates().alignRight"
96
- (click)="execCmd('alignRight')">≡R</button>
97
- <button type="button" data-cmd="alignJustify" [class._active]="activeStates().alignJustify"
98
- (click)="execCmd('alignJustify')">≡J</button>
159
+ <button
160
+ type="button"
161
+ data-cmd="alignLeft"
162
+ [class._active]="activeStates().alignLeft"
163
+ (click)="execCmd('alignLeft')"
164
+ >
165
+ ≡L
166
+ </button>
167
+ <button
168
+ type="button"
169
+ data-cmd="alignCenter"
170
+ [class._active]="activeStates().alignCenter"
171
+ (click)="execCmd('alignCenter')"
172
+ >
173
+ ≡C
174
+ </button>
175
+ <button
176
+ type="button"
177
+ data-cmd="alignRight"
178
+ [class._active]="activeStates().alignRight"
179
+ (click)="execCmd('alignRight')"
180
+ >
181
+ ≡R
182
+ </button>
183
+ <button
184
+ type="button"
185
+ data-cmd="alignJustify"
186
+ [class._active]="activeStates().alignJustify"
187
+ (click)="execCmd('alignJustify')"
188
+ >
189
+ ≡J
190
+ </button>
99
191
  </div>
100
192
  <div class="_btn-group">
101
193
  <button type="button" data-cmd="clean" (click)="execCmd('clean')">Tx</button>
@@ -104,13 +196,17 @@ const DEFAULT_EXTENSIONS: AnyExtension[] = [
104
196
  @if (colorPickerMode() != undefined) {
105
197
  <div class="_color-picker">
106
198
  @for (color of colorPresets; track color) {
107
- <button type="button" class="_color-swatch"
108
- [style.background-color]="color"
109
- [attr.aria-label]="color"
110
- (click)="applyColor(color)"></button>
199
+ <button
200
+ type="button"
201
+ class="_color-swatch"
202
+ [style.background-color]="color"
203
+ [attr.aria-label]="color"
204
+ (click)="applyColor(color)"
205
+ ></button>
111
206
  }
112
- <button type="button" class="_color-swatch _no-color"
113
- (click)="applyColor(undefined)">✕</button>
207
+ <button type="button" class="_color-swatch _no-color" (click)="applyColor(undefined)">
208
+
209
+ </button>
114
210
  </div>
115
211
  }
116
212
  }
@@ -121,41 +217,41 @@ const DEFAULT_EXTENSIONS: AnyExtension[] = [
121
217
  sd-tiptap-editor {
122
218
  display: block;
123
219
  position: relative;
124
- border: 1px solid var(--trans-lighter);
125
- border-radius: var(--border-radius-default);
126
- background: var(--theme-secondary-lightest);
220
+ border: 1px solid var(--sd-bd-field);
221
+ border-radius: var(--sd-radius-default);
222
+ background-color: var(--sd-bg-field);
127
223
 
128
224
  > ._toolbar {
129
225
  display: flex;
130
226
  flex-wrap: wrap;
131
- gap: var(--gap-xs);
132
- padding: var(--gap-xs);
133
- border-bottom: 1px solid var(--trans-lighter);
227
+ gap: var(--sd-gap-xs);
228
+ padding: var(--sd-gap-xs);
229
+ border-bottom: 1px solid var(--sd-bd-hairline);
134
230
 
135
231
  > ._btn-group {
136
232
  display: flex;
137
233
  gap: 1px;
138
234
 
139
235
  > button {
140
- padding: var(--gap-xs) var(--gap-sm);
141
- border: 1px solid var(--trans-lighter);
142
- border-radius: var(--border-radius-default);
143
- background: transparent;
236
+ padding: var(--sd-gap-xs) var(--sd-gap-sm);
237
+ border: 1px solid var(--sd-bd-hairline);
238
+ border-radius: var(--sd-radius-default);
239
+ background-color: transparent;
144
240
  cursor: pointer;
145
- font-size: var(--font-size-default);
241
+ font-size: var(--sd-font-size-default);
146
242
  line-height: 1;
147
243
 
148
244
  &._active {
149
- background: var(--theme-primary-default);
150
- color: var(--text-trans-rev-default);
245
+ background-color: var(--sd-bg-primary-solid);
246
+ color: var(--sd-tx-primary-solid);
151
247
  }
152
248
 
153
249
  &:hover {
154
- background: var(--trans-lighter);
250
+ background-color: var(--sd-bg-state-hover);
155
251
  }
156
252
 
157
253
  &._active:hover {
158
- background: var(--theme-primary-default);
254
+ background-color: var(--sd-bg-primary-solid);
159
255
  }
160
256
  }
161
257
  }
@@ -165,13 +261,13 @@ const DEFAULT_EXTENSIONS: AnyExtension[] = [
165
261
  display: flex;
166
262
  flex-wrap: wrap;
167
263
  gap: 2px;
168
- padding: var(--gap-xs);
169
- border-bottom: 1px solid var(--trans-lighter);
264
+ padding: var(--sd-gap-xs);
265
+ border-bottom: 1px solid var(--sd-bd-hairline);
170
266
 
171
267
  > ._color-swatch {
172
268
  width: 1.25rem;
173
269
  height: 1.25rem;
174
- border: 1px solid var(--trans-lighter);
270
+ border: 1px solid var(--sd-bd-hairline);
175
271
  border-radius: 2px;
176
272
  cursor: pointer;
177
273
  padding: 0;
@@ -180,16 +276,16 @@ const DEFAULT_EXTENSIONS: AnyExtension[] = [
180
276
  display: flex;
181
277
  align-items: center;
182
278
  justify-content: center;
183
- background: var(--control-color);
279
+ background-color: var(--sd-bg-control);
184
280
  font-size: 0.625rem;
185
281
  }
186
282
  }
187
283
  }
188
284
 
189
285
  > ._editor-container {
190
- padding: var(--gap-sm);
286
+ padding: var(--sd-gap-sm);
191
287
  min-height: 6.25rem;
192
- font-family: var(--font-family-field);
288
+ font-family: var(--sd-font-family-field);
193
289
 
194
290
  > .tiptap {
195
291
  outline: none;
@@ -200,9 +296,10 @@ const DEFAULT_EXTENSIONS: AnyExtension[] = [
200
296
  }
201
297
  }
202
298
 
299
+ // disabled 는 색 치환 단일 규약 (DEC-009)
203
300
  &[data-sd-disabled="true"] {
204
- background: var(--theme-gray-lightest);
205
- color: var(--text-trans-light);
301
+ background-color: var(--sd-bg-disabled);
302
+ color: var(--sd-tx-disabled);
206
303
 
207
304
  > ._editor-container > .tiptap {
208
305
  cursor: not-allowed;
@@ -248,11 +345,46 @@ export class SdTiptapEditor {
248
345
  private readonly _destroyRef = inject(DestroyRef);
249
346
 
250
347
  readonly colorPresets = [
251
- "#000000", "#434343", "#666666", "#999999", "#b7b7b7", "#cccccc", "#d9d9d9", "#efefef",
252
- "#f3f3f3", "#ffffff", "#980000", "#ff0000", "#ff9900", "#ffff00", "#00ff00", "#00ffff",
253
- "#4a86e8", "#0000ff", "#9900ff", "#ff00ff", "#e6b8af", "#f4cccc", "#fce5cd", "#fff2cc",
254
- "#d9ead3", "#d0e0e3", "#c9daf8", "#cfe2f3", "#d9d2e9", "#ead1dc", "#dd7e6b", "#ea9999",
255
- "#f9cb9c", "#ffe599", "#b6d7a8", "#a2c4c9", "#a4c2f4", "#9fc5e8", "#b4a7d6", "#d5a6bd",
348
+ "#000000",
349
+ "#434343",
350
+ "#666666",
351
+ "#999999",
352
+ "#b7b7b7",
353
+ "#cccccc",
354
+ "#d9d9d9",
355
+ "#efefef",
356
+ "#f3f3f3",
357
+ "#ffffff",
358
+ "#980000",
359
+ "#ff0000",
360
+ "#ff9900",
361
+ "#ffff00",
362
+ "#00ff00",
363
+ "#00ffff",
364
+ "#4a86e8",
365
+ "#0000ff",
366
+ "#9900ff",
367
+ "#ff00ff",
368
+ "#e6b8af",
369
+ "#f4cccc",
370
+ "#fce5cd",
371
+ "#fff2cc",
372
+ "#d9ead3",
373
+ "#d0e0e3",
374
+ "#c9daf8",
375
+ "#cfe2f3",
376
+ "#d9d2e9",
377
+ "#ead1dc",
378
+ "#dd7e6b",
379
+ "#ea9999",
380
+ "#f9cb9c",
381
+ "#ffe599",
382
+ "#b6d7a8",
383
+ "#a2c4c9",
384
+ "#a4c2f4",
385
+ "#9fc5e8",
386
+ "#b4a7d6",
387
+ "#d5a6bd",
256
388
  ];
257
389
 
258
390
  /** @internal -- TipTap Editor 인스턴스. 테스트 및 고급 사용자용 */
@@ -344,20 +476,22 @@ export class SdTiptapEditor {
344
476
  const container = this._elRef.nativeElement.querySelector("._editor-container");
345
477
  if (container == null) return;
346
478
 
347
- this.editor.set(new Editor({
348
- element: container,
349
- extensions,
350
- content: initialContent ?? "",
351
- editable: untracked(() => !this.disabled() && !this.readonly()),
352
- onUpdate: ({ editor }) => {
353
- const html = this._getEditorHtmlFrom(editor);
354
- this._lastEditorHtml = html;
355
- this.value.set(html);
356
- },
357
- onTransaction: () => {
358
- this._toolbar.refreshActiveStates();
359
- },
360
- }));
479
+ this.editor.set(
480
+ new Editor({
481
+ element: container,
482
+ extensions,
483
+ content: initialContent ?? "",
484
+ editable: untracked(() => !this.disabled() && !this.readonly()),
485
+ onUpdate: ({ editor }) => {
486
+ const html = this._getEditorHtmlFrom(editor);
487
+ this._lastEditorHtml = html;
488
+ this.value.set(html);
489
+ },
490
+ onTransaction: () => {
491
+ this._toolbar.refreshActiveStates();
492
+ },
493
+ }),
494
+ );
361
495
  }
362
496
 
363
497
  private _destroyEditor(): void {
@@ -374,5 +508,4 @@ export class SdTiptapEditor {
374
508
  if (editor.isEmpty) return undefined;
375
509
  return html;
376
510
  }
377
-
378
511
  }
@@ -1,10 +1,28 @@
1
1
  import { effect, inject, Injectable, PLATFORM_ID, signal } from "@angular/core";
2
2
  import { isPlatformBrowser } from "@angular/common";
3
3
 
4
+ // 내장 테마 단일 정의 — 새 테마 추가 시 여기 항목 1줄 +
5
+ // scss/themes 값 맵 + _theme-variables 의 .sd-theme-{value} writeVars 블록만 추가하면 된다.
6
+ // light 는 :root 기본값이라 값 맵/블록이 없어도 동작한다(클래스가 붙어도 규칙이 없어 무효).
7
+ export const SD_THEMES = [
8
+ { value: "light", label: "라이트" },
9
+ { value: "blueprint", label: "블루프린트" },
10
+ { value: "ide-dark", label: "IDE 다크" },
11
+ ] as const;
12
+
13
+ export type SdThemeName = (typeof SD_THEMES)[number]["value"];
14
+
15
+ // 밀도 축 — 테마와 직교(DEC-007). compact 는 치수 토큰 그룹(sd-density-compact)만 덮는다.
16
+ export type SdDensity = "normal" | "compact";
17
+
4
18
  @Injectable({ providedIn: "root" })
5
19
  export class SdThemeProvider {
6
- // 블루프린트(엔지니어링 도면) 테마
7
- blueprint = signal<boolean>(false);
20
+ readonly themes: readonly { value: SdThemeName; label: string }[] = SD_THEMES;
21
+
22
+ // 라이트(기본) / 블루프린트(도면) / IDE 다크
23
+ theme = signal<SdThemeName>("light");
24
+
25
+ density = signal<SdDensity>("normal");
8
26
 
9
27
  readonly fontSizePresets: readonly number[] = [12, 14, 16, 20, 24, 28];
10
28
 
@@ -15,7 +33,14 @@ export class SdThemeProvider {
15
33
  if (!isPlatformBrowser(inject(PLATFORM_ID))) return;
16
34
 
17
35
  effect(() => {
18
- document.body.classList.toggle("sd-theme-blueprint", this.blueprint());
36
+ const theme = this.theme();
37
+ for (const def of this.themes) {
38
+ document.body.classList.toggle(`sd-theme-${def.value}`, def.value === theme);
39
+ }
40
+ });
41
+
42
+ effect(() => {
43
+ document.body.classList.toggle("sd-density-compact", this.density() === "compact");
19
44
  });
20
45
 
21
46
  effect(() => {
@@ -51,8 +51,27 @@ import { tablerMinus, tablerPalette, tablerPlus } from "@ng-icons/tabler-icons";
51
51
  </div>
52
52
  </div>
53
53
  <div class="flex-row gap-sm cross-align-center">
54
- <span>블루프린트</span>
55
- <sd-switch [(value)]="_sdTheme.blueprint" />
54
+ <span>테마</span>
55
+ <div class="flex-row gap-xs cross-align-center">
56
+ @for (item of _sdTheme.themes; track item.value) {
57
+ <sd-button
58
+ [inline]="true"
59
+ [size]="'sm'"
60
+ [theme]="_sdTheme.theme() === item.value ? 'primary' : 'link-gray'"
61
+ (click)="_sdTheme.theme.set(item.value)"
62
+ >
63
+ {{ item.label }}
64
+ </sd-button>
65
+ }
66
+ </div>
67
+ </div>
68
+ <div class="flex-row gap-sm cross-align-center">
69
+ <span>compact</span>
70
+ <sd-switch
71
+ [inline]="true"
72
+ [value]="_sdTheme.density() === 'compact'"
73
+ (valueChange)="_sdTheme.density.set($event ? 'compact' : 'normal')"
74
+ />
56
75
  </div>
57
76
  </div>
58
77
  </sd-dropdown-popup>
@@ -0,0 +1,103 @@
1
+ // WCAG 2.x 대비율 계산 (DEC-012) — 테마(커스텀 테마 포함) 핵심 fg/bg 쌍 검증용.
2
+ // 알파 색은 배경 표면에 합성 후 계산한다.
3
+
4
+ interface RgbaColor {
5
+ r: number;
6
+ g: number;
7
+ b: number;
8
+ a: number;
9
+ }
10
+
11
+ function parseCssColor(colorText: string): RgbaColor {
12
+ const trimmed = colorText.trim().toLowerCase();
13
+
14
+ if (trimmed === "white") return { r: 255, g: 255, b: 255, a: 1 };
15
+ if (trimmed === "black") return { r: 0, g: 0, b: 0, a: 1 };
16
+ if (trimmed === "transparent") return { r: 0, g: 0, b: 0, a: 0 };
17
+
18
+ const hexMatch = /^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/.exec(trimmed);
19
+ if (hexMatch) {
20
+ const hex = hexMatch[1];
21
+ if (hex.length === 3) {
22
+ return {
23
+ r: parseInt(hex[0] + hex[0], 16),
24
+ g: parseInt(hex[1] + hex[1], 16),
25
+ b: parseInt(hex[2] + hex[2], 16),
26
+ a: 1,
27
+ };
28
+ }
29
+ return {
30
+ r: parseInt(hex.slice(0, 2), 16),
31
+ g: parseInt(hex.slice(2, 4), 16),
32
+ b: parseInt(hex.slice(4, 6), 16),
33
+ a: hex.length === 8 ? parseInt(hex.slice(6, 8), 16) / 255 : 1,
34
+ };
35
+ }
36
+
37
+ const rgbMatch =
38
+ /^rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)\s*(?:,\s*([\d.]+)\s*)?\)$/.exec(trimmed);
39
+ if (rgbMatch) {
40
+ // 알파 캡처 그룹은 미매치 시 런타임에 undefined (exec 타입은 string 으로 나옴)
41
+ const alphaText = rgbMatch[4] as string | undefined;
42
+ return {
43
+ r: Number(rgbMatch[1]),
44
+ g: Number(rgbMatch[2]),
45
+ b: Number(rgbMatch[3]),
46
+ a: alphaText != null ? Number(alphaText) : 1,
47
+ };
48
+ }
49
+
50
+ throw new Error(`WCAG 대비 계산: 색상을 해석할 수 없습니다: "${colorText}"`);
51
+ }
52
+
53
+ function composite(fg: RgbaColor, bg: RgbaColor): RgbaColor {
54
+ const a = fg.a + bg.a * (1 - fg.a);
55
+ if (a === 0) return { r: 0, g: 0, b: 0, a: 0 };
56
+ return {
57
+ r: (fg.r * fg.a + bg.r * bg.a * (1 - fg.a)) / a,
58
+ g: (fg.g * fg.a + bg.g * bg.a * (1 - fg.a)) / a,
59
+ b: (fg.b * fg.a + bg.b * bg.a * (1 - fg.a)) / a,
60
+ a,
61
+ };
62
+ }
63
+
64
+ function getRelativeLuminance(color: RgbaColor): number {
65
+ const [r, g, b] = [color.r, color.g, color.b].map((v) => {
66
+ const srgb = v / 255;
67
+ return srgb <= 0.03928 ? srgb / 12.92 : Math.pow((srgb + 0.055) / 1.055, 2.4);
68
+ });
69
+ return 0.2126 * r + 0.7152 * g + 0.0722 * b;
70
+ }
71
+
72
+ /**
73
+ * WCAG 2.x 대비율 (1-21).
74
+ *
75
+ * @param foregroundColor 전경색(텍스트 등). 알파면 배경 위에 합성 후 계산.
76
+ * @param backgroundColor 배경색. 알파면 `baseColor` 위에 합성(불투명 배경이면 불필요).
77
+ * @param baseColor 반투명 배경 아래의 최종 불투명 표면색.
78
+ */
79
+ export function getWcagContrastRatio(
80
+ foregroundColor: string,
81
+ backgroundColor: string,
82
+ baseColor?: string,
83
+ ): number {
84
+ let bg = parseCssColor(backgroundColor);
85
+ if (bg.a < 1) {
86
+ if (baseColor == null) {
87
+ throw new Error(
88
+ `WCAG 대비 계산: 반투명 배경("${backgroundColor}")은 base 표면색이 필요합니다`,
89
+ );
90
+ }
91
+ const base = parseCssColor(baseColor);
92
+ if (base.a < 1) {
93
+ throw new Error(`WCAG 대비 계산: base 표면색("${baseColor}")은 불투명해야 합니다`);
94
+ }
95
+ bg = composite(bg, base);
96
+ }
97
+
98
+ const fg = composite(parseCssColor(foregroundColor), bg);
99
+
100
+ const l1 = getRelativeLuminance(fg);
101
+ const l2 = getRelativeLuminance(bg);
102
+ return (Math.max(l1, l2) + 0.05) / (Math.min(l1, l2) + 0.05);
103
+ }
@@ -85,18 +85,18 @@ import { NgTemplateOutlet } from "@angular/common";
85
85
  border-collapse: collapse;
86
86
  width: 100%;
87
87
  height: 100%;
88
- border-radius: var(--border-radius-default);
88
+ border-radius: var(--sd-radius-default);
89
89
  overflow: hidden;
90
90
 
91
91
  > * > tr > * {
92
- padding: var(--gap-sm) var(--gap-default);
93
- border: 1px solid var(--theme-gray-light);
92
+ padding: var(--sd-gap-sm) var(--sd-gap-default);
93
+ border: 1px solid var(--sd-bd-default);
94
94
 
95
95
  width: calc(100% / 7);
96
96
  }
97
97
 
98
98
  > thead > tr > th {
99
- background: var(--theme-gray-lighter);
99
+ background-color: var(--sd-bg-gray-subtle);
100
100
  height: 10%;
101
101
  }
102
102
 
@@ -105,14 +105,14 @@ import { NgTemplateOutlet } from "@angular/common";
105
105
  height: 15%;
106
106
 
107
107
  > .day {
108
- margin-bottom: var(--gap-sm);
108
+ margin-bottom: var(--sd-gap-sm);
109
109
  }
110
110
 
111
111
  &.not-current {
112
- background: var(--theme-gray-lightest);
112
+ background-color: var(--sd-bg-canvas);
113
113
 
114
114
  > .day {
115
- color: var(--theme-gray-default);
115
+ color: var(--sd-tx-gray);
116
116
  }
117
117
  }
118
118
 
@@ -120,7 +120,7 @@ import { NgTemplateOutlet } from "@angular/common";
120
120
  display: flex;
121
121
  flex-wrap: nowrap;
122
122
 
123
- @include mixins.flex-direction(column, var(--gap-sm));
123
+ @include mixins.flex-direction(column, var(--sd-gap-sm));
124
124
  }
125
125
  }
126
126
  }