@dataloop-ai/components 0.20.202 → 0.20.204

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dataloop-ai/components",
3
- "version": "0.20.202",
3
+ "version": "0.20.204",
4
4
  "exports": {
5
5
  ".": "./index.ts",
6
6
  "./models": "./models.ts",
@@ -38,6 +38,8 @@ body {
38
38
  --dl-font-size-h6: 10px;
39
39
  --dl-font-size-body: 12px;
40
40
  --dl-font-size-small: 10px;
41
+ --dl-font-size-alert: 14px;
42
+ --dl-font-size-alert-title: 16px;
41
43
 
42
44
  /* shadows */
43
45
  --dl-menu-shadow: rgba(0, 0, 0, 0.14); /* replace to --dell-shadow: rgba(0, 0, 0, 0.14); */
@@ -23,6 +23,13 @@
23
23
  </span>
24
24
  </span>
25
25
  </div>
26
+ <div
27
+ v-if="$slots.actions"
28
+ class="actions"
29
+ data-test="actions"
30
+ >
31
+ <slot name="actions" />
32
+ </div>
26
33
  <div
27
34
  v-if="closable"
28
35
  class="close-button"
@@ -100,21 +107,32 @@ const typeToIconMap: Record<DlAlertType, string> = {
100
107
  info: 'icon-dl-info-filled',
101
108
  success: 'icon-dl-approve-filled',
102
109
  warning: 'icon-dl-alert-filled',
103
- error: 'icon-dl-error-filled'
110
+ error: 'icon-dl-error-filled',
111
+ discovery: 'icon-dl-error-filled'
104
112
  }
105
113
 
106
114
  const typeToIconColorMap: Record<DlAlertType, string> = {
107
115
  info: 'dell-blue-500',
108
116
  success: 'dell-green-500',
109
117
  warning: 'dell-yellow-600',
110
- error: 'dell-red-500'
118
+ error: 'dell-red-500',
119
+ discovery: 'dl-color-discovery'
120
+ }
121
+
122
+ const typeToIndicatorColorMap: Record<DlAlertType, string> = {
123
+ info: 'dell-blue-500',
124
+ success: 'dell-green-500',
125
+ warning: 'dell-yellow-800',
126
+ error: 'dell-red-500',
127
+ discovery: 'dl-color-discovery'
111
128
  }
112
129
 
113
130
  const typeToBackgroundMap: Record<DlAlertType, string> = {
114
131
  info: 'dell-blue-200',
115
132
  success: 'dell-green-200',
116
133
  warning: 'dell-yellow-200',
117
- error: 'dell-red-200'
134
+ error: 'dell-red-200',
135
+ discovery: 'dl-color-discovery-bg'
118
136
  }
119
137
 
120
138
  export default defineComponent({
@@ -139,7 +157,7 @@ export default defineComponent({
139
157
  type: String,
140
158
  required: true,
141
159
  validator: (value: string) =>
142
- includes(['info', 'success', 'warning', 'error'], value)
160
+ includes(['info', 'success', 'warning', 'error', 'discovery'], value)
143
161
  },
144
162
  textColor: {
145
163
  type: String,
@@ -230,18 +248,26 @@ export default defineComponent({
230
248
 
231
249
  const { height } = rootElement.getBoundingClientRect()
232
250
  const iconS: Record<string, any> = {
233
- display: 'flex'
251
+ display: 'flex',
252
+ alignSelf: 'flex-start',
253
+ paddingTop: '2px'
254
+ }
255
+ const closeS: Record<string, any> = {
256
+ display: 'flex',
257
+ alignSelf: 'flex-start'
234
258
  }
235
259
  const rootS: Record<string, any> = {
236
260
  backgroundColor: getColor(
237
261
  typeToBackgroundMap[type.value as DlAlertType]
238
262
  )
239
263
  }
240
- if (height > 46) {
241
- iconS.alignSelf = 'flex-start'
242
- } else {
243
- iconS.alignSelf = 'center'
244
- }
264
+ rootS['--dl-alert-indicator-color'] = getColor(
265
+ typeToIndicatorColorMap[type.value as DlAlertType]
266
+ )
267
+ rootS['--dl-alert-border-color'] = getColor(
268
+ typeToIndicatorColorMap[type.value as DlAlertType]
269
+ )
270
+
245
271
  if (fluid === true) {
246
272
  rootS.width = '100%'
247
273
  } else {
@@ -250,11 +276,13 @@ export default defineComponent({
250
276
 
251
277
  if (padding.value) {
252
278
  rootS['--dl-alert-padding'] = padding.value
279
+ } else {
280
+ rootS['--dl-alert-padding'] = '8px 16px'
253
281
  }
254
282
 
255
283
  iconStyle.value = iconS
256
284
  rootStyle.value = rootS
257
- closeButtonStyle.value = iconS
285
+ closeButtonStyle.value = closeS
258
286
  })
259
287
  }
260
288
 
@@ -308,9 +336,33 @@ export default defineComponent({
308
336
  flex-direction: row;
309
337
  justify-content: space-between;
310
338
  min-height: 36px;
311
- border-radius: 2px;
339
+ border-left: 4px solid var(--dl-alert-indicator-color, transparent);
340
+ border-top: 1px solid var(--dl-alert-border-color, transparent);
341
+ border-right: 1px solid var(--dl-alert-border-color, transparent);
342
+ border-bottom: 1px solid var(--dl-alert-border-color, transparent);
343
+ border-radius: 0px;
312
344
  box-sizing: border-box;
313
345
 
346
+ ::v-deep a {
347
+ color: var(--dell-blue-600);
348
+ text-decoration: none;
349
+ }
350
+
351
+ ::v-deep a:visited {
352
+ color: var(--dell-blue-600);
353
+ text-decoration: none;
354
+ }
355
+
356
+ ::v-deep a:hover {
357
+ color: var(--dell-blue-700);
358
+ text-decoration: underline;
359
+ }
360
+
361
+ ::v-deep a:active {
362
+ color: var(--dell-blue-800);
363
+ text-decoration: underline;
364
+ }
365
+
314
366
  > div {
315
367
  display: flex;
316
368
  flex-direction: row;
@@ -318,17 +370,32 @@ export default defineComponent({
318
370
  }
319
371
 
320
372
  .text {
321
- padding-left: 10px;
373
+ padding-left: 8px;
374
+ padding-top: 2px;
322
375
  font-size: var(--dl-font-size-body);
323
376
  line-height: normal;
324
- align-self: center;
377
+ align-self: flex-start;
378
+ font-size: 14px;
379
+ line-height: 16px;
380
+ font-weight: 400;
325
381
  word-break: break-word;
326
382
  }
327
383
 
328
384
  .close-button {
329
- padding-right: 10px;
330
- padding-left: 10px;
331
- align-items: var(--dl-alert-align-button, start);
385
+ display: flex;
386
+ padding: 12px;
387
+ align-items: flex-start;
388
+ }
389
+
390
+ .actions {
391
+ display: flex;
392
+ align-items: center;
393
+ gap: 8px;
394
+ padding: 8px 12px;
395
+ height: 40px;
396
+ max-height: 40px;
397
+ box-sizing: border-box;
398
+ align-self: flex-start;
332
399
  }
333
400
 
334
401
  .icon-dl-close:hover {
@@ -1 +1 @@
1
- export type DlAlertType = 'info' | 'success' | 'warning' | 'error'
1
+ export type DlAlertType = 'info' | 'success' | 'warning' | 'error' | 'discovery'
@@ -264,7 +264,7 @@ export default defineComponent({
264
264
  color: this.color,
265
265
  filled: this.filled,
266
266
  shaded: this.shaded,
267
- textColor: this.iconColor ?? this.textColor
267
+ textColor: this.iconColor || this.textColor
268
268
  })
269
269
  }
270
270
 
@@ -278,7 +278,7 @@ export default defineComponent({
278
278
  return setTextOnPressed({
279
279
  disabled: this.disabled,
280
280
  flat: this.flat,
281
- textColor: this.iconColor ?? this.textColor
281
+ textColor: this.iconColor || this.textColor
282
282
  })
283
283
  }
284
284
 
@@ -290,7 +290,7 @@ export default defineComponent({
290
290
  outlined: this.outlined,
291
291
  shaded: this.shaded,
292
292
  flat: this.flat,
293
- color: this.iconColor ?? this.textColor
293
+ color: this.iconColor || this.textColor
294
294
  })
295
295
  )
296
296
  }
@@ -81,29 +81,29 @@ export const setTextColor = ({
81
81
  textColor
82
82
  }: DlButtonProps): string => {
83
83
  if (disabled) {
84
- return getColor('', 'dl-color-disabled')
84
+ return getColor('', 'dell-gray-500')
85
85
  }
86
86
  if (shaded && outlined) {
87
- return getColor(textColor, 'dl-color-text-darker-buttons')
87
+ return getColor(textColor, 'dell-gray-800')
88
88
  }
89
89
  if (outlined) {
90
- return getColor(textColor, 'dl-color-secondary')
90
+ return getColor(textColor, 'dell-blue-500')
91
91
  }
92
92
  if (flat) {
93
93
  if (color === 'secondary') {
94
- return getColor(textColor, 'dl-color-darker')
94
+ return getColor(textColor, 'dell-gray-800')
95
95
  }
96
96
 
97
- return getColor(textColor, 'dl-color-secondary')
97
+ return getColor(textColor, 'dell-blue-500')
98
98
  }
99
99
  if (shaded) {
100
- return getColor(textColor, 'dl-color-darker')
100
+ return getColor(textColor, 'dell-gray-800')
101
101
  }
102
102
  if (filled) {
103
- return getColor(textColor, 'dl-color-text-buttons')
103
+ return getColor(textColor, 'dell-white')
104
104
  }
105
105
 
106
- return getColor(textColor, 'dl-color-text-buttons')
106
+ return getColor(textColor, 'dell-white')
107
107
  }
108
108
 
109
109
  export const setBgColor = ({
@@ -15,18 +15,66 @@
15
15
  class="alert"
16
16
  :type="type"
17
17
  :closable="closable"
18
- icon-size="24px"
18
+ icon-size="16px"
19
19
  :dark-mode="false"
20
20
  close-button-position="center"
21
21
  style="position: relative"
22
22
  @update:model-value="closeToast"
23
23
  >
24
24
  <slot name="message">
25
- <span
26
- class="toast-message"
27
- data-test="message-text"
28
- />
25
+ <div
26
+ class="toast-text"
27
+ :class="{
28
+ 'toast-text--single': !multiLine,
29
+ 'toast-text--with-title': !!title
30
+ }"
31
+ >
32
+ <div v-if="title" class="toast-title">
33
+ {{ title }}
34
+ </div>
35
+ <div
36
+ v-if="html"
37
+ class="toast-message"
38
+ data-test="message-text"
39
+ v-html="message"
40
+ />
41
+ <div
42
+ v-else
43
+ class="toast-message"
44
+ :class="{ 'toast-message--pre-line': multiLine }"
45
+ data-test="message-text"
46
+ >
47
+ {{ message }}
48
+ </div>
49
+
50
+ <div v-if="caption" class="toast-caption">
51
+ <div v-if="html" v-html="caption" />
52
+ <div v-else>
53
+ {{ caption }}
54
+ </div>
55
+ </div>
56
+ </div>
29
57
  </slot>
58
+ <template v-if="actions && actions.length" #actions>
59
+ <dl-button
60
+ v-for="(action, idx) in actions"
61
+ :key="idx"
62
+ :label="action.label"
63
+ :icon="action.icon"
64
+ :color="action.textColor || 'dl-alert-border-color'"
65
+ :text-color="action.textColor || 'dl-alert-border-color'"
66
+ :hover-border-color="action.textColor || 'dl-alert-border-color'"
67
+ :hover-text-color="action.textColor || 'dl-alert-border-color'"
68
+ :hover-bg-color="'transparent'"
69
+ :pressed-bg-color="'transparent'"
70
+ :styles="action.styles || defaultActionButtonStyles"
71
+ :filled="false"
72
+ outlined
73
+ no-wrap
74
+ overflow
75
+ @click="onActionClick(action)"
76
+ />
77
+ </template>
30
78
  <dl-badge
31
79
  v-if="count"
32
80
  with-border
@@ -61,22 +109,46 @@ import {
61
109
  getCurrentInstance,
62
110
  onBeforeMount,
63
111
  onMounted,
112
+ PropType,
64
113
  ref
65
114
  } from 'vue-demi'
66
- import { DlAlert, DlBadge } from '../../../'
67
- import { DlToastTypes, DlToastPositions } from '../types'
115
+ import { DlAlert, DlBadge, DlButton } from '../../../'
116
+ import { DlToastAction, DlToastTypes, DlToastPositions } from '../types'
68
117
  import { removeElement } from '../utils/render'
69
118
  import { Animation } from '../types'
70
119
  import { v4 } from 'uuid'
71
120
 
121
+ const DEFAULT_ACTION_BUTTON_STYLES =
122
+ 'min-width:73px; max-width:100px; height:24px; max-height:24px; padding:0 8px; border-radius:2px;'
123
+
72
124
  export default defineComponent({
73
125
  name: 'ToastComponent',
74
- components: { DlAlert, DlBadge },
126
+ components: { DlAlert, DlBadge, DlButton },
75
127
  props: {
128
+ title: {
129
+ type: String,
130
+ default: ''
131
+ },
76
132
  message: {
77
133
  type: String,
78
134
  required: true
79
135
  },
136
+ caption: {
137
+ type: String,
138
+ default: ''
139
+ },
140
+ html: {
141
+ type: Boolean,
142
+ default: false
143
+ },
144
+ multiLine: {
145
+ type: Boolean,
146
+ default: true
147
+ },
148
+ actions: {
149
+ type: Array as PropType<DlToastAction[]>,
150
+ default: (): DlToastAction[] => []
151
+ },
80
152
  type: {
81
153
  type: String,
82
154
  required: true,
@@ -203,7 +275,7 @@ export default defineComponent({
203
275
  '.dl-toast-container--pending'
204
276
  )
205
277
  const messageContainer = root.value?.querySelector('.toast-message')
206
- if (messageContainer) {
278
+ if (messageContainer && slots?.message) {
207
279
  messageContainer.innerHTML = message
208
280
  }
209
281
  parent.insertAdjacentElement('afterbegin', root.value)
@@ -227,6 +299,13 @@ export default defineComponent({
227
299
  setHideTimeout()
228
300
  }
229
301
 
302
+ const onActionClick = (action: DlToastAction) => {
303
+ action?.handler?.()
304
+ if (action?.closeOnClick) {
305
+ closeToastMessage()
306
+ }
307
+ }
308
+
230
309
  const badgeColor = computed(() => {
231
310
  switch (props.type) {
232
311
  case DlToastTypes.SUCCESS:
@@ -237,6 +316,8 @@ export default defineComponent({
237
316
  return 'var(--dl-color-alert-error)'
238
317
  case DlToastTypes.INFO:
239
318
  return 'var(--dl-color-alert-info)'
319
+ case DlToastTypes.DISCOVERY:
320
+ return 'var(--dl-color-discovery)'
240
321
  }
241
322
  })
242
323
 
@@ -249,6 +330,8 @@ export default defineComponent({
249
330
  correctParent,
250
331
  updateCount,
251
332
  count,
333
+ onActionClick,
334
+ defaultActionButtonStyles: DEFAULT_ACTION_BUTTON_STYLES,
252
335
  badgeColor
253
336
  }
254
337
  }
@@ -256,6 +339,32 @@ export default defineComponent({
256
339
  </script>
257
340
 
258
341
  <style lang="scss" scoped>
342
+ .toast-text {
343
+ min-width: 0;
344
+ flex: 1 1 auto;
345
+ }
346
+
347
+ .toast-title {
348
+ font-size: var(--dl-font-size-alert-title, 16px);
349
+ line-height: 150%;
350
+ margin-bottom: 2px;
351
+ }
352
+
353
+ .toast-text--single {
354
+ white-space: nowrap;
355
+ overflow: hidden;
356
+ text-overflow: ellipsis;
357
+ }
358
+
359
+ .toast-caption {
360
+ margin-top: 2px;
361
+ opacity: 0.8;
362
+ }
363
+
364
+ .toast-message--pre-line {
365
+ white-space: pre-line;
366
+ }
367
+
259
368
  .toast-item {
260
369
  display: inline-flex;
261
370
  align-items: center;
@@ -263,7 +372,7 @@ export default defineComponent({
263
372
  min-width: 400px;
264
373
  max-width: 900px;
265
374
  margin: 5px;
266
- cursor: pointer;
375
+ cursor: default;
267
376
  animation-duration: 150ms;
268
377
 
269
378
  &.toast-item--top,
@@ -373,13 +482,13 @@ export default defineComponent({
373
482
 
374
483
  .DlToastContainer {
375
484
  --dl-color-negative: var(--dl-color-alert-error);
376
- --dl-color-negative-background: var(--dl-color-alert-error-background);
485
+ --dl-color-negative-background: var(--dell-red-200);
377
486
  --dl-color-warning: var(--dl-color-alert-warn);
378
- --dl-color-warning-background: var(--dl-color-alert-warn-background);
487
+ --dl-color-warning-background: var(--dell-yellow-200);
379
488
  --dl-color-positive: var(--dl-color-alert-success);
380
- --dl-color-positive-background: var(--dl-color-alert-success-background);
489
+ --dl-color-positive-background: var(--dell-green-200);
381
490
  --dl-color-info: var(--dl-color-alert-info);
382
- --dl-color-info-background: var(--dl-color-alert-info-background);
491
+ --dl-color-info-background: var(--dell-blue-200);
383
492
  --dl-color-darker: var(--dl-color-alert-text);
384
493
  --dl-alert-align-button: center;
385
494
  }
@@ -16,14 +16,67 @@ export enum DlToastTypes {
16
16
  SUCCESS = 'success',
17
17
  WARNING = 'warning',
18
18
  ERROR = 'error',
19
- INFO = 'info'
19
+ INFO = 'info',
20
+ DISCOVERY = 'discovery'
21
+ }
22
+
23
+ export interface DlToastAction {
24
+ /**
25
+ * The label displayed on the action button
26
+ */
27
+ label?: string
28
+ /**
29
+ * The icon displayed on the action button
30
+ */
31
+ icon?: string
32
+ /**
33
+ * The text color of the action button
34
+ */
35
+ textColor?: string
36
+ /**
37
+ * Inline styles passed to DlButton `styles` prop
38
+ */
39
+ styles?: string | Record<string, string>
40
+ /**
41
+ * Called when the action button is clicked
42
+ */
43
+ handler: () => unknown
44
+ /**
45
+ * Close toast after the action is clicked
46
+ * @default false
47
+ */
48
+ closeOnClick?: boolean
20
49
  }
21
50
 
22
51
  export interface DlToastProps {
52
+ /**
53
+ * Optional title displayed above the message
54
+ */
55
+ title?: string
23
56
  /**
24
57
  * The message to display in the toast
25
58
  */
26
59
  message: string
60
+ /**
61
+ * Optional caption displayed under the message
62
+ */
63
+ caption?: string
64
+ /**
65
+ * When false, message/caption should be treated as plain text (escaped).
66
+ * When true, message/caption can be rendered as HTML.
67
+ * @default false
68
+ */
69
+ html?: boolean
70
+ /**
71
+ * When true, allow wrapping into multiple lines.
72
+ * When false, keep message in a single line (ellipsis).
73
+ * @default true
74
+ */
75
+ multiLine?: boolean
76
+ /**
77
+ * Optional action buttons displayed inside the toast
78
+ */
79
+ actions?: DlToastAction[]
27
80
  /**
28
81
  * The type of the toast
29
82
  */
@@ -92,6 +92,18 @@
92
92
  <dl-button @click="showToastMessageCustom">
93
93
  Show Toast Message
94
94
  </dl-button>
95
+ <dl-button @click="showToastMultiLine">
96
+ Multi Line
97
+ </dl-button>
98
+ <div class="flex-row" style="margin-top: 8px">
99
+ <dl-button @click="showToastWithLink">
100
+ Toast with link
101
+ </dl-button>
102
+ <dl-switch
103
+ v-model="htmlEnabled"
104
+ :left-label="htmlEnabled ? 'HTML true' : 'HTML false'"
105
+ />
106
+ </div>
95
107
  </div>
96
108
  </template>
97
109
 
@@ -126,6 +138,7 @@ export default defineComponent({
126
138
  const closable = ref(true)
127
139
  const width = ref('auto')
128
140
  const collapseCount = ref(null)
141
+ const htmlEnabled = ref(false)
129
142
  function showToastMessage() {
130
143
  DlToast.open({
131
144
  message: message.value,
@@ -160,16 +173,48 @@ export default defineComponent({
160
173
  }
161
174
  )
162
175
  }
176
+ function showToastMultiLine() {
177
+ DlToast.open({
178
+ message:
179
+ 'This is an page-level alert that communicates an\ninformational message.',
180
+ position: position.value as DlToastPositions,
181
+ type: DlToastTypes.SUCCESS,
182
+ duration: Number(duration.value) || 1000,
183
+ closable: closable.value,
184
+ width: width.value,
185
+ collapseCount: collapseCount.value,
186
+ html: false,
187
+ multiLine: true
188
+ } as any)
189
+ }
190
+ function showToastWithLink() {
191
+ const linkHtml =
192
+ '<a href="https://docs.dataloop.ai/" target="_blank" rel="noopener noreferrer">Link to another page.</a>'
193
+ DlToast.open({
194
+ message: `This is an page-level alert that communicates an informational message.\n${linkHtml}`,
195
+ position: position.value as DlToastPositions,
196
+ type: DlToastTypes.SUCCESS,
197
+ duration: Number(duration.value) || 1000,
198
+ closable: closable.value,
199
+ width: width.value,
200
+ collapseCount: collapseCount.value,
201
+ html: htmlEnabled.value,
202
+ multiLine: true
203
+ } as any)
204
+ }
163
205
  return {
164
206
  showToastMessageCustom,
165
207
  showToastMessage,
208
+ showToastMultiLine,
209
+ showToastWithLink,
166
210
  message,
167
211
  duration,
168
212
  type,
169
213
  position,
170
214
  closable,
171
215
  width,
172
- collapseCount
216
+ collapseCount,
217
+ htmlEnabled
173
218
  }
174
219
  }
175
220
  })
@@ -179,4 +224,10 @@ export default defineComponent({
179
224
  .flex {
180
225
  display: flex;
181
226
  }
227
+
228
+ .flex-row {
229
+ display: flex;
230
+ align-items: center;
231
+ gap: 12px;
232
+ }
182
233
  </style>
@@ -8,13 +8,32 @@ const allColorNames = {
8
8
  }
9
9
 
10
10
  const getLighterGradient = (color: string, magnitude = MAGNITUDE) => {
11
- color = color.replace('dl', '--dl')
11
+ if (color.startsWith('dl-') || color.startsWith('dell-')) {
12
+ color = `--${color}`
13
+ }
14
+ if (color.startsWith('--dell-')) {
15
+ const colorMatch = color.match(/--dell-(\w+)-(\d+)/)
16
+ if (colorMatch) {
17
+ try {
18
+ const colorName = colorMatch[1]
19
+ const colorValue = parseInt(colorMatch[2])
20
+ const nextColorValue = colorValue + 100
21
+ const colorToReplace = `--dell-${colorName}-${nextColorValue}`
22
+ if (colorToReplace in allColorNames) {
23
+ return allColorNames[
24
+ colorToReplace as keyof typeof allColorNames
25
+ ]
26
+ }
27
+ } catch (error) {
28
+ // skip error
29
+ }
30
+ }
31
+ }
12
32
  let newColor =
13
33
  color in allColorNames
14
34
  ? allColorNames[color as keyof typeof allColorNames]
15
35
  : color
16
36
  newColor = newColor.replace(`#`, ``).trim()
17
-
18
37
  if (newColor.length === 6) {
19
38
  const decimalColor = parseInt(newColor, 16)
20
39