design-system-next 2.20.1 → 2.20.5

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 (74) hide show
  1. package/dist/design-system-next.es.js +6863 -6804
  2. package/dist/design-system-next.es.js.gz +0 -0
  3. package/dist/design-system-next.umd.js +12 -12
  4. package/dist/design-system-next.umd.js.gz +0 -0
  5. package/dist/main.css +1 -1
  6. package/dist/main.css.gz +0 -0
  7. package/dist/package.json.d.ts +3 -2
  8. package/package.json +3 -2
  9. package/src/App.vue +51 -1
  10. package/src/assets/scripts/border-radius.ts +15 -15
  11. package/src/assets/scripts/colors.ts +134 -134
  12. package/src/assets/scripts/max-width.ts +11 -11
  13. package/src/assets/scripts/spacing.ts +23 -23
  14. package/src/assets/scripts/utilities.ts +15 -15
  15. package/src/components/accordion/accordion.ts +43 -43
  16. package/src/components/accordion/use-accordion.ts +43 -43
  17. package/src/components/banner/banner.ts +20 -20
  18. package/src/components/button/button.ts +72 -72
  19. package/src/components/button/button.vue +15 -15
  20. package/src/components/checkbox/checkbox.ts +45 -45
  21. package/src/components/collapsible/collapsible.ts +21 -21
  22. package/src/components/collapsible/collapsible.vue +27 -27
  23. package/src/components/dropdown/fix-multi-number.ts +92 -92
  24. package/src/components/empty-state/empty-state.ts +50 -50
  25. package/src/components/floating-action/floating-action.ts +12 -12
  26. package/src/components/input/input-email/input-email.vue +17 -17
  27. package/src/components/input/input-search/input-search.vue +13 -13
  28. package/src/components/input/input-url/input-url.vue +20 -20
  29. package/src/components/input/input-username/input-username.vue +17 -17
  30. package/src/components/list/ladderized-list/ladderized-list.ts +47 -39
  31. package/src/components/list/ladderized-list/ladderized-list.vue +2 -0
  32. package/src/components/list/list-item/list-item.ts +48 -0
  33. package/src/components/list/list-item/list-item.vue +108 -0
  34. package/src/components/list/list-item/use-list-item.ts +36 -0
  35. package/src/components/list/list.ts +4 -0
  36. package/src/components/list/list.vue +68 -254
  37. package/src/components/list/use-list.ts +19 -5
  38. package/src/components/logo/logo.ts +43 -43
  39. package/src/components/logo/logo.vue +14 -14
  40. package/src/components/logo/use-logo.ts +41 -41
  41. package/src/components/lozenge/lozenge.ts +4 -18
  42. package/src/components/lozenge/lozenge.vue +14 -4
  43. package/src/components/lozenge/use-lozenge.ts +6 -0
  44. package/src/components/radio/radio.ts +42 -42
  45. package/src/components/select/select-ladderized/select-ladderized.ts +13 -1
  46. package/src/components/select/select-ladderized/select-ladderized.vue +5 -5
  47. package/src/components/select/select-multiple/select-multiple.ts +16 -2
  48. package/src/components/select/select-multiple/select-multiple.vue +5 -6
  49. package/src/components/select/select.ts +12 -1
  50. package/src/components/select/select.vue +21 -11
  51. package/src/components/sidepanel/sidepanel.vue +55 -55
  52. package/src/components/sidepanel/stacking-sidepanel/stacking-sidepanel.ts +16 -16
  53. package/src/components/sidepanel/stacking-sidepanel/stacking-sidepanel.vue +39 -39
  54. package/src/components/slider/slider.ts +38 -38
  55. package/src/components/snackbar/snack/snack.ts +71 -71
  56. package/src/components/snackbar/use-snackbar.ts +34 -34
  57. package/src/components/status/status.ts +19 -19
  58. package/src/components/status/status.vue +13 -13
  59. package/src/components/stepper/step/step.ts +47 -47
  60. package/src/components/stepper/stepper.ts +47 -47
  61. package/src/components/stepper/stepper.vue +34 -34
  62. package/src/components/switch/switch.ts +42 -42
  63. package/src/components/table/table-actions/table-actions.ts +42 -42
  64. package/src/components/table/table-actions/table-actions.vue +40 -40
  65. package/src/components/table/table-chips-title/table-chips-title.ts +27 -27
  66. package/src/components/table/table-chips-title/table-chips-title.vue +32 -32
  67. package/src/components/table/table-chips-title/use-table-chips-title.ts +22 -22
  68. package/src/components/table/table-lozenge-title/table-lozenge-title.ts +23 -23
  69. package/src/components/table/table-lozenge-title/table-lozenge-title.vue +26 -26
  70. package/src/components/table/table-lozenge-title/use-table-lozenge-title.ts +21 -21
  71. package/src/components/tabs/tabs.ts +43 -43
  72. package/src/components/time-picker/time-picker.ts +69 -69
  73. package/src/components/tooltip/use-tooltip.ts +13 -13
  74. package/src/stores/useSnackbarStore.ts +44 -44
@@ -1,19 +1,8 @@
1
1
  <template>
2
2
  <div class="spr-font-main">
3
+ <!-- Header Section -->
3
4
  <template v-if="props.searchableMenu || props.displayListItemSelected">
4
- <div
5
- :class="[
6
- 'spr-sticky spr-z-20',
7
- 'spr-grid spr-gap-3 spr-bg-white-50 spr-px-size-spacing-3xs spr-py-size-spacing-2xs',
8
- 'spr-border-color-weak spr-border spr-border-x-0 spr-border-b spr-border-t-0 spr-border-solid',
9
- ]"
10
- :style="{
11
- top:
12
- typeof props.stickySearchOffset === 'number'
13
- ? props.stickySearchOffset + 'px'
14
- : String(props.stickySearchOffset),
15
- }"
16
- >
5
+ <div :class="listClasses.headerClasses" :style="stickyOffsetStyle">
17
6
  <spr-input-search
18
7
  v-if="props.searchableMenu"
19
8
  v-model="searchText"
@@ -24,254 +13,80 @@
24
13
  v-if="props.supportingDisplayText || props.displayListItemSelected"
25
14
  class="spr-label-sm-medium spr-text-color-base spr-block"
26
15
  >
27
- <template v-if="props.supportingDisplayText">
28
- {{ props.supportingDisplayText }}
29
- </template>
30
- <template v-else> {{ selectedItems.length }} Selected</template>
16
+ {{ props.supportingDisplayText || `${selectedItems.length} Selected` }}
31
17
  </span>
32
18
  </div>
33
19
  </template>
34
20
 
35
21
  <div class="spr-p-size-spacing-3xs">
36
- <template v-if="props.groupItemsBy">
37
- <template v-if="groupedMenuList && groupedMenuList.length > 0">
38
- <div class="spr-grid spr-gap-2">
39
- <div v-for="(list, listIndex) in groupedMenuList" :key="listIndex" class="spr-grid spr-gap-0.5">
40
- <div
41
- v-if="list.groupLabel !== 'no-group'"
42
- class="spr-label-xs-medium spr-text-color-base spr-px-size-spacing-4xs spr-py-size-spacing-3xs spr-uppercase"
43
- >
44
- <span>
45
- {{ list.groupLabel }}
46
- </span>
47
- </div>
48
- <div
49
- v-for="(item, itemIndex) in list.items"
50
- :key="itemIndex"
51
- :class="getListItemClasses(item)"
52
- @click="handleSelectedItem(item)"
53
- >
54
- <template v-if="props.lozenge">
55
- <div class="spr-flex spr-items-center spr-gap-1">
56
- <spr-checkbox
57
- v-if="props.multiSelect"
58
- :disabled="item.disabled || (props.disabledUnselectedItems && !isItemSelected(item))"
59
- :checked="isItemSelected(item)"
60
- />
61
- <spr-lozenge
62
- v-if="props.lozenge"
63
- :label="item.text || (item.lozengeProps?.label as string)"
64
- :tone="item.lozengeProps?.tone as string & (typeof LOZENGE_TONE)[number]"
65
- :fill="item.lozengeProps?.fill as boolean"
66
- :url="item.lozengeProps?.url as string"
67
- :icon="item.lozengeProps?.icon as string"
68
- :postfix-icon="item.lozengeProps?.postfixIcon as string"
69
- />
70
- </div>
71
- </template>
72
- <template v-else>
73
- <div class="spr-flex spr-items-center spr-gap-1">
74
- <spr-checkbox
75
- v-if="props.multiSelect"
76
- :disabled="item.disabled || (props.disabledUnselectedItems && !isItemSelected(item))"
77
- :checked="isItemSelected(item)"
78
- />
79
- <div :class="[item.textColor, 'spr-flex spr-flex-row spr-items-center spr-gap-size-spacing-3xs']">
80
- <span
81
- v-if="props.itemIcon || item.icon"
82
- :class="[
83
- item.iconColor,
84
- 'spr-mt-[2px]',
85
- {
86
- 'spr-text-color-disabled':
87
- item.disabled || (props.disabledUnselectedItems && !isItemSelected(item)),
88
- },
89
- ]"
90
- >
91
- <icon :icon="(props.itemIcon || item.icon) as string" width="20px" height="20px" />
92
- </span>
93
- <div
94
- :class="[
95
- 'spr-flex spr-flex-auto spr-flex-col spr-justify-start',
96
- {
97
- 'spr-text-color-disabled':
98
- item.disabled || (props.disabledUnselectedItems && !isItemSelected(item)),
99
- },
100
- ]"
101
- >
102
- <span class="spr-break-words spr-text-left spr-text-xs">
103
- {{ item.text }}
104
- </span>
105
- <span
106
- v-if="item.subtext"
107
- :class="[
108
- 'spr-body-xs-regular spr-text-color-base spr-break-words spr-text-left',
109
- {
110
- 'spr-text-color-disabled':
111
- item.disabled || (props.disabledUnselectedItems && !isItemSelected(item)),
112
- },
113
- ]"
114
- >
115
- {{ item.subtext }}
116
- </span>
117
- </div>
118
- </div>
119
- </div>
120
- <div class="spr-flex spr-items-center spr-gap-1">
121
- <template v-if="props.ladderized">
122
- <template v-if="item.sublevel && item.sublevel?.length > 0">
123
- <Icon class="spr-text-color-weak spr-size-4" icon="ph:caret-right" />
124
- </template>
125
- <template v-else>
126
- <Icon
127
- v-if="isItemSelected(item) && !props.noCheck"
128
- class="spr-text-color-brand-base spr-w-[1.39em]"
129
- icon="ph:check"
130
- />
131
- </template>
132
- </template>
133
- <template v-else>
134
- <spr-lozenge
135
- v-if="item.lozenge"
136
- :label="item.lozenge?.label as string"
137
- :tone="item.lozenge?.tone as string & (typeof LOZENGE_TONE)[number]"
138
- :fill="item.lozenge?.fill as boolean"
139
- :url="item.lozenge?.url as string"
140
- :icon="item.lozenge?.icon as string"
141
- :postfix-icon="item.lozenge?.postfixIcon as string"
142
- />
143
- <Icon
144
- v-if="isItemSelected(item) && !props.noCheck && !props.multiSelect"
145
- class="spr-text-color-brand-base spr-w-[1.39em]"
146
- icon="ph:check"
147
- />
148
- </template>
149
- </div>
150
- </template>
22
+ <!-- Grouped Items -->
23
+ <template v-if="props.groupItemsBy && groupedMenuList && groupedMenuList.length > 0">
24
+ <div class="spr-grid spr-gap-3">
25
+ <div v-for="(list, listIndex) in groupedMenuList" :key="listIndex" class="spr-grid spr-gap-0.5">
26
+ <div
27
+ v-if="list.groupLabel !== 'no-group'"
28
+ class="spr-label-xs-medium spr-text-color-base spr-px-size-spacing-4xs spr-py-size-spacing-3xs spr-uppercase"
29
+ >
30
+ {{ list.groupLabel }}
31
+ </div>
32
+ <div class="spr-grid spr-gap-[2px]">
33
+ <ListItem
34
+ v-for="item in list.items"
35
+ :key="item.value"
36
+ :item="item"
37
+ :is-selected="isItemSelected(item)"
38
+ :classes="getListItemClasses(item)"
39
+ :multi-select="props.multiSelect"
40
+ :lozenge="props.lozenge"
41
+ :ladderized="props.ladderized"
42
+ :no-check="props.noCheck"
43
+ :item-icon="props.itemIcon"
44
+ :disabled-unselected-items="props.disabledUnselectedItems"
45
+ @select="handleSelectedItem(item)"
46
+ />
47
+ <div v-if="props.infiniteScrollLoader" class="spr-flex spr-items-center spr-justify-center spr-p-2">
48
+ <Icon icon="svg-spinners:270-ring" />
151
49
  </div>
152
50
  </div>
153
51
  </div>
154
- </template>
155
- <template v-else>
156
- <div v-if="props.loading" class="spr-skeletal-loader spr-h-8 spr-w-full spr-rounded-md" />
157
- <div v-else class="spr-flex spr-items-center spr-justify-center spr-p-2 spr-text-center">
158
- <span class="spr-body-sm-regular spr-m-0">No results found</span>
52
+ </div>
53
+ </template>
54
+
55
+ <!-- Non-Grouped Items -->
56
+ <template v-else-if="localizedMenuList && localizedMenuList.length > 0">
57
+ <div class="spr-grid spr-gap-[2px]">
58
+ <ListItem
59
+ v-for="item in localizedMenuList"
60
+ :key="item.value"
61
+ :item="item"
62
+ :is-selected="isItemSelected(item)"
63
+ :classes="getListItemClasses(item)"
64
+ :multi-select="props.multiSelect"
65
+ :lozenge="props.lozenge"
66
+ :ladderized="props.ladderized"
67
+ :no-check="props.noCheck"
68
+ :item-icon="props.itemIcon"
69
+ :disabled-unselected-items="props.disabledUnselectedItems"
70
+ @select="handleSelectedItem(item)"
71
+ />
72
+ <div v-if="props.infiniteScrollLoader" class="spr-flex spr-items-center spr-justify-center spr-p-2">
73
+ <Icon icon="svg-spinners:270-ring" />
159
74
  </div>
160
- </template>
75
+ </div>
161
76
  </template>
77
+
78
+ <!-- Loading State -->
79
+ <template v-else-if="props.loading">
80
+ <div class="spr-grid spr-gap-[2px]">
81
+ <div v-for="i in 5" :key="i" class="spr-skeletal-loader spr-h-8 spr-w-full spr-rounded-md" />
82
+ </div>
83
+ </template>
84
+
85
+ <!-- Empty State -->
162
86
  <template v-else>
163
- <template v-if="localizedMenuList && localizedMenuList.length > 0">
164
- <div
165
- v-for="(item, index) in localizedMenuList"
166
- :key="index"
167
- :class="getListItemClasses(item)"
168
- @click="handleSelectedItem(item)"
169
- >
170
- <template v-if="props.lozenge">
171
- <div class="spr-flex spr-items-center spr-gap-1">
172
- <spr-checkbox
173
- v-if="props.multiSelect"
174
- :disabled="item.disabled || (props.disabledUnselectedItems && !isItemSelected(item))"
175
- :checked="isItemSelected(item)"
176
- />
177
- <spr-lozenge
178
- v-if="props.lozenge"
179
- :label="item.text || (item.lozengeProps?.label as string)"
180
- :tone="item.lozengeProps?.tone as string & (typeof LOZENGE_TONE)[number]"
181
- :fill="item.lozengeProps?.fill as boolean"
182
- :url="item.lozengeProps?.url as string"
183
- :icon="item.lozengeProps?.icon as string"
184
- :postfix-icon="item.lozengeProps?.postfixIcon as string"
185
- />
186
- </div>
187
- </template>
188
- <template v-else>
189
- <div class="spr-flex spr-items-center spr-gap-1">
190
- <spr-checkbox
191
- v-if="props.multiSelect"
192
- :disabled="item.disabled || (props.disabledUnselectedItems && !isItemSelected(item))"
193
- :checked="isItemSelected(item)"
194
- />
195
- <div :class="[item.textColor, 'spr-flex spr-flex-row spr-items-center spr-gap-size-spacing-3xs']">
196
- <span
197
- v-if="props.itemIcon || item.icon"
198
- :class="[
199
- item.iconColor,
200
- 'spr-mt-[2px]',
201
- {
202
- 'spr-text-color-disabled':
203
- item.disabled || (props.disabledUnselectedItems && !isItemSelected(item)),
204
- },
205
- ]"
206
- >
207
- <icon :icon="(props.itemIcon || item.icon) as string" width="20px" height="20px" />
208
- </span>
209
- <div
210
- :class="[
211
- 'spr-flex spr-flex-auto spr-flex-col spr-justify-start',
212
- {
213
- 'spr-text-color-disabled':
214
- item.disabled || (props.disabledUnselectedItems && !isItemSelected(item)),
215
- },
216
- ]"
217
- >
218
- <span class="spr-break-words spr-text-left spr-text-xs">
219
- {{ item.text }}
220
- </span>
221
- <span
222
- v-if="item.subtext"
223
- :class="[
224
- 'spr-body-xs-regular spr-text-color-base spr-break-words spr-text-left',
225
- {
226
- 'spr-text-color-disabled':
227
- item.disabled || (props.disabledUnselectedItems && !isItemSelected(item)),
228
- },
229
- ]"
230
- >
231
- {{ item.subtext }}
232
- </span>
233
- </div>
234
- </div>
235
- </div>
236
- <div class="spr-flex spr-items-center spr-gap-1">
237
- <template v-if="props.ladderized">
238
- <template v-if="item.sublevel && item.sublevel?.length > 0">
239
- <Icon class="spr-text-color-weak spr-size-4" icon="ph:caret-right" />
240
- </template>
241
- <template v-else>
242
- <Icon
243
- v-if="isItemSelected(item) && !props.noCheck"
244
- class="spr-text-color-brand-base spr-w-[1.39em]"
245
- icon="ph:check"
246
- />
247
- </template>
248
- </template>
249
- <template v-else>
250
- <spr-lozenge
251
- v-if="item.lozenge"
252
- :label="item.lozenge?.label as string"
253
- :tone="item.lozenge?.tone as string & (typeof LOZENGE_TONE)[number]"
254
- :fill="item.lozenge?.fill as boolean"
255
- :url="item.lozenge?.url as string"
256
- :icon="item.lozenge?.icon as string"
257
- :postfix-icon="item.lozenge?.postfixIcon as string"
258
- />
259
- <Icon
260
- v-if="isItemSelected(item) && !props.noCheck && !props.multiSelect"
261
- class="spr-text-color-brand-base spr-w-[1.39em]"
262
- icon="ph:check"
263
- />
264
- </template>
265
- </div>
266
- </template>
267
- </div>
268
- </template>
269
- <template v-else>
270
- <div v-if="props.loading" class="spr-skeletal-loader spr-h-8 spr-w-full spr-rounded-md" />
271
- <div v-else class="spr-flex spr-items-center spr-justify-center spr-p-2 spr-text-center">
272
- <span class="spr-body-sm-regular spr-m-0">No results found</span>
273
- </div>
274
- </template>
87
+ <div class="spr-flex spr-items-center spr-justify-center spr-p-2 spr-text-center">
88
+ <span class="spr-body-sm-regular spr-m-0">No results found</span>
89
+ </div>
275
90
  </template>
276
91
  </div>
277
92
  </div>
@@ -280,11 +95,8 @@
280
95
  <script lang="ts" setup>
281
96
  import { Icon } from '@iconify/vue';
282
97
 
283
- import SprCheckbox from '@/components/checkbox/checkbox.vue';
284
98
  import SprInputSearch from '@/components/input/input-search/input-search.vue';
285
- import SprLozenge from '@/components/lozenge/lozenge.vue';
286
-
287
- import { LOZENGE_TONE } from '@/components/lozenge/lozenge';
99
+ import ListItem from './list-item/list-item.vue';
288
100
 
289
101
  import { listPropTypes, listEmitTypes } from './list';
290
102
  import { useList } from './use-list';
@@ -293,6 +105,8 @@ const props = defineProps(listPropTypes);
293
105
  const emit = defineEmits(listEmitTypes);
294
106
 
295
107
  const {
108
+ listClasses,
109
+ stickyOffsetStyle,
296
110
  selectedItems,
297
111
  searchText,
298
112
  localizedMenuList,
@@ -7,13 +7,11 @@ import type { SetupContext } from 'vue';
7
7
  import type { ListPropTypes, ListEmitTypes, MenuListType, GroupedMenuListType } from './list';
8
8
 
9
9
  interface ListClasses {
10
+ headerClasses: string;
10
11
  listItemClasses: string;
11
12
  }
12
13
 
13
14
  export const useList = (props: ListPropTypes, emit: SetupContext<ListEmitTypes>['emit']) => {
14
- const selectedItems = useVModel(props, 'modelValue', emit);
15
- const searchString = useVModel(props, 'searchValue', emit);
16
-
17
15
  const {
18
16
  menuList,
19
17
  menuLevel,
@@ -23,9 +21,16 @@ export const useList = (props: ListPropTypes, emit: SetupContext<ListEmitTypes>[
23
21
  disabledLocalSearch,
24
22
  noCheck,
25
23
  disabledUnselectedItems,
24
+ stickySearchOffset,
26
25
  } = toRefs(props);
27
26
 
28
27
  const listClasses: ComputedRef<ListClasses> = computed(() => {
28
+ const headerClasses = classNames(
29
+ 'spr-sticky spr-z-20',
30
+ 'spr-grid spr-gap-3 spr-bg-white-50 spr-px-size-spacing-3xs spr-py-size-spacing-2xs',
31
+ 'spr-border-color-weak spr-border spr-border-x-0 spr-border-b spr-border-t-0 spr-border-solid',
32
+ );
33
+
29
34
  const listItemClasses = classNames(
30
35
  'spr-flex spr-cursor-pointer spr-items-center spr-justify-between spr-gap-1.5 spr-rounded-lg spr-p-2',
31
36
  'spr-transition spr-duration-150 spr-ease-in-out',
@@ -33,9 +38,17 @@ export const useList = (props: ListPropTypes, emit: SetupContext<ListEmitTypes>[
33
38
  'active:spr-background-color-single-active active:spr-scale-[.98]',
34
39
  );
35
40
 
36
- return { listItemClasses };
41
+ return { headerClasses, listItemClasses };
37
42
  });
38
43
 
44
+ const stickyOffsetStyle = computed(() => ({
45
+ top:
46
+ typeof stickySearchOffset.value === 'number' ? `${stickySearchOffset.value}px` : String(stickySearchOffset.value),
47
+ }));
48
+
49
+ const selectedItems = useVModel(props, 'modelValue', emit);
50
+ const searchString = useVModel(props, 'searchValue', emit);
51
+
39
52
  const searchText = ref<string>('');
40
53
 
41
54
  const localizedMenuList = ref<MenuListType[]>([]);
@@ -587,9 +600,10 @@ export const useList = (props: ListPropTypes, emit: SetupContext<ListEmitTypes>[
587
600
  });
588
601
 
589
602
  return {
603
+ listClasses,
604
+ stickyOffsetStyle,
590
605
  selectedItems,
591
606
  searchText,
592
- listClasses,
593
607
  localizedMenuList,
594
608
  groupedMenuList,
595
609
  apiSelectedList,
@@ -1,43 +1,43 @@
1
- import type { PropType, ExtractPropTypes } from 'vue';
2
-
3
- const LOGO_THEMES = ['white', 'dark', 'gray', 'green'] as const;
4
- const LOGO_NAMES = [
5
- 'benchmark',
6
- 'ecosystem',
7
- 'engage',
8
- 'finances',
9
- 'hr-mobile',
10
- 'hr',
11
- 'inbound',
12
- 'insight',
13
- 'readycash',
14
- 'readywage',
15
- 'payroll',
16
- 'performance-plus',
17
- 'procurement',
18
- 'professional-services',
19
- 'recruit',
20
- 'recruit-plus',
21
- 'sail',
22
- 'sidekick',
23
- 'wellness',
24
- ] as const;
25
-
26
- export const logoPropTypes = {
27
- name: {
28
- type: String as PropType<(typeof LOGO_NAMES)[number]>,
29
- validator: (value: (typeof LOGO_NAMES)[number]) => LOGO_NAMES.includes(value),
30
- default: 'hr',
31
- },
32
- theme: {
33
- type: String as PropType<(typeof LOGO_THEMES)[number]>,
34
- validator: (value: (typeof LOGO_THEMES)[number]) => LOGO_THEMES.includes(value),
35
- default: 'dark',
36
- },
37
- width: {
38
- type: [String, Number] as PropType<string | number>,
39
- default: '50', // If number, it will be treated as px
40
- },
41
- };
42
-
43
- export type LogoPropTypes = ExtractPropTypes<typeof logoPropTypes>;
1
+ import type { PropType, ExtractPropTypes } from 'vue';
2
+
3
+ const LOGO_THEMES = ['white', 'dark', 'gray', 'green'] as const;
4
+ const LOGO_NAMES = [
5
+ 'benchmark',
6
+ 'ecosystem',
7
+ 'engage',
8
+ 'finances',
9
+ 'hr-mobile',
10
+ 'hr',
11
+ 'inbound',
12
+ 'insight',
13
+ 'readycash',
14
+ 'readywage',
15
+ 'payroll',
16
+ 'performance-plus',
17
+ 'procurement',
18
+ 'professional-services',
19
+ 'recruit',
20
+ 'recruit-plus',
21
+ 'sail',
22
+ 'sidekick',
23
+ 'wellness',
24
+ ] as const;
25
+
26
+ export const logoPropTypes = {
27
+ name: {
28
+ type: String as PropType<(typeof LOGO_NAMES)[number]>,
29
+ validator: (value: (typeof LOGO_NAMES)[number]) => LOGO_NAMES.includes(value),
30
+ default: 'hr',
31
+ },
32
+ theme: {
33
+ type: String as PropType<(typeof LOGO_THEMES)[number]>,
34
+ validator: (value: (typeof LOGO_THEMES)[number]) => LOGO_THEMES.includes(value),
35
+ default: 'dark',
36
+ },
37
+ width: {
38
+ type: [String, Number] as PropType<string | number>,
39
+ default: '50', // If number, it will be treated as px
40
+ },
41
+ };
42
+
43
+ export type LogoPropTypes = ExtractPropTypes<typeof logoPropTypes>;
@@ -1,14 +1,14 @@
1
- <template>
2
- <div>
3
- <img v-bind="$attrs" :src="logoSrc" :alt="logoTitle" :title="logoTitle" :width="width" />
4
- </div>
5
- </template>
6
-
7
- <script lang="ts" setup>
8
- import { useLogo } from './use-logo';
9
- import { logoPropTypes } from './logo';
10
-
11
- const props = defineProps(logoPropTypes);
12
-
13
- const { logoSrc, logoTitle } = useLogo(props);
14
- </script>
1
+ <template>
2
+ <div>
3
+ <img v-bind="$attrs" :src="logoSrc" :alt="logoTitle" :title="logoTitle" :width="width" />
4
+ </div>
5
+ </template>
6
+
7
+ <script lang="ts" setup>
8
+ import { useLogo } from './use-logo';
9
+ import { logoPropTypes } from './logo';
10
+
11
+ const props = defineProps(logoPropTypes);
12
+
13
+ const { logoSrc, logoTitle } = useLogo(props);
14
+ </script>
@@ -1,41 +1,41 @@
1
- import { computed } from 'vue';
2
- import type { LogoPropTypes } from './logo';
3
- import { Cloudinary } from '@cloudinary/url-gen';
4
-
5
- const CLOUD_NAME = 'dfeykvudc';
6
-
7
- const NAME_MAP: Record<string, string> = {
8
- 'hr': 'Sprout HR',
9
- 'hr-mobile': 'Sprout HR Mobile',
10
- 'performance-plus': 'Sprout Performance+',
11
- 'recruit-plus': 'Sprout Recruit+',
12
- 'sail': 'Sprout SAIL',
13
- 'readycash': 'Sprout ReadyCash',
14
- 'readywage': 'Sprout ReadyWage',
15
- };
16
-
17
- export function useLogo(props: LogoPropTypes) {
18
- const cld = new Cloudinary({
19
- cloud: {
20
- cloudName: CLOUD_NAME,
21
- },
22
- });
23
-
24
- const logoSrc = computed(() => cld.image(`sprout-${props.name}-${props.theme}`).toURL());
25
-
26
- const logoTitle = computed(() => {
27
- if (props.name in NAME_MAP) {
28
- return NAME_MAP[props.name];
29
- }
30
-
31
- const firstChar = props.name.charAt(0).toUpperCase();
32
- const remainingChars = props.name.slice(1);
33
- const formattedName = `${firstChar}${remainingChars}`;
34
- return `Sprout ${formattedName}`;
35
- });
36
-
37
- return {
38
- logoSrc,
39
- logoTitle,
40
- };
41
- }
1
+ import { computed } from 'vue';
2
+ import type { LogoPropTypes } from './logo';
3
+ import { Cloudinary } from '@cloudinary/url-gen';
4
+
5
+ const CLOUD_NAME = 'dfeykvudc';
6
+
7
+ const NAME_MAP: Record<string, string> = {
8
+ 'hr': 'Sprout HR',
9
+ 'hr-mobile': 'Sprout HR Mobile',
10
+ 'performance-plus': 'Sprout Performance+',
11
+ 'recruit-plus': 'Sprout Recruit+',
12
+ 'sail': 'Sprout SAIL',
13
+ 'readycash': 'Sprout ReadyCash',
14
+ 'readywage': 'Sprout ReadyWage',
15
+ };
16
+
17
+ export function useLogo(props: LogoPropTypes) {
18
+ const cld = new Cloudinary({
19
+ cloud: {
20
+ cloudName: CLOUD_NAME,
21
+ },
22
+ });
23
+
24
+ const logoSrc = computed(() => cld.image(`sprout-${props.name}-${props.theme}`).toURL());
25
+
26
+ const logoTitle = computed(() => {
27
+ if (props.name in NAME_MAP) {
28
+ return NAME_MAP[props.name];
29
+ }
30
+
31
+ const firstChar = props.name.charAt(0).toUpperCase();
32
+ const remainingChars = props.name.slice(1);
33
+ const formattedName = `${firstChar}${remainingChars}`;
34
+ return `Sprout ${formattedName}`;
35
+ });
36
+
37
+ return {
38
+ logoSrc,
39
+ logoTitle,
40
+ };
41
+ }