edvoyui-component-library-test-flight 0.0.243 → 0.0.245

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.
@@ -26,7 +26,7 @@ declare const __VLS_component: import('../../../node_modules/vue').DefineCompone
26
26
  default: string;
27
27
  };
28
28
  alertType: {
29
- type: PropType<"Default" | "Warning" | "Success" | "Error">;
29
+ type: PropType<"Default" | "Info" | "Warning" | "Success" | "Error">;
30
30
  default: string;
31
31
  };
32
32
  alertIcon: {
@@ -53,7 +53,7 @@ declare const __VLS_component: import('../../../node_modules/vue').DefineCompone
53
53
  default: string;
54
54
  };
55
55
  alertType: {
56
- type: PropType<"Default" | "Warning" | "Success" | "Error">;
56
+ type: PropType<"Default" | "Info" | "Warning" | "Success" | "Error">;
57
57
  default: string;
58
58
  };
59
59
  alertIcon: {
@@ -71,7 +71,7 @@ declare const __VLS_component: import('../../../node_modules/vue').DefineCompone
71
71
  showAlert: boolean;
72
72
  heading: string;
73
73
  textMessage: string;
74
- alertType: "Success" | "Error" | "Default" | "Warning";
74
+ alertType: "Success" | "Error" | "Default" | "Info" | "Warning";
75
75
  alertIcon: string | Function | Record<string, any>;
76
76
  actionItems: boolean;
77
77
  }, {}, {}, {}, string, import('../../../node_modules/vue').ComponentProvideOptions, true, {}, any>;
@@ -7,7 +7,7 @@
7
7
  leave-from-class="opacity-100"
8
8
  leave-to-class="opacity-0"
9
9
  >
10
- <div v-if="showAlert" :class="['p-4 rounded-md', alertsClass.bgColor]">
10
+ <div v-if="showAlert" :class="['px-4 py-4 rounded-lg border border-solid', alertsClass.bgColor]">
11
11
  <div
12
12
  :class="[closeIcon && !textMessage ? 'items-center pr-2 flex' : 'flex items-start']"
13
13
  >
@@ -87,8 +87,10 @@ import {
87
87
  CheckCircleIcon,
88
88
  XCircleIcon,
89
89
  XMarkIcon,
90
+ InformationCircleIcon
90
91
  } from "@heroicons/vue/24/solid";
91
92
 
93
+
92
94
  const props = defineProps({
93
95
  showAlert: {
94
96
  type: Boolean,
@@ -103,7 +105,7 @@ const props = defineProps({
103
105
  default: "",
104
106
  },
105
107
  alertType: {
106
- type: String as PropType<"Default" | "Warning" | "Success" | "Error">,
108
+ type: String as PropType<"Default" | "Info" | "Warning" | "Success" | "Error">,
107
109
  default: "Default",
108
110
  },
109
111
  alertIcon: {
@@ -127,7 +129,22 @@ const onClose = () => {
127
129
  const alertsClass = computed(() => {
128
130
  const iconClasses = {
129
131
  Default: {
130
- bgColor: "bg-blue-50",
132
+ bgColor: "bg-gray-100 border-gray-200",
133
+ leftIcon: {
134
+ icon: InformationCircleIcon,
135
+ color: "text-gray-600",
136
+ },
137
+ titleColor: "text-gray-800",
138
+ textColor: "text-gray-700",
139
+ btnPrimary:
140
+ "bg-gray-700 hover:bg-gray-800 focus:ring-gray-600 focus:ring-offset-gray-50",
141
+ btnTertiary:
142
+ "text-gray-500 bg-gray-50 hover:bg-gray-100 focus:ring-gray-600 focus:ring-offset-gray-50",
143
+ btnClose:
144
+ "bg-gray-50 text-gray-500 hover:bg-gray-100 focus:ring-gray-600 focus:ring-offset-gray-50",
145
+ },
146
+ Info: {
147
+ bgColor: "bg-blue-50 border-blue-200",
131
148
  leftIcon: {
132
149
  icon: CheckCircleIcon,
133
150
  color: "text-blue-400",
@@ -142,7 +159,7 @@ const alertsClass = computed(() => {
142
159
  "bg-blue-50 text-blue-500 hover:bg-blue-100 focus:ring-blue-600 focus:ring-offset-blue-50",
143
160
  },
144
161
  Warning: {
145
- bgColor: "bg-yellow-50",
162
+ bgColor: "bg-yellow-50 border-orange-200",
146
163
  leftIcon: {
147
164
  icon: ExclamationTriangleIcon,
148
165
  color: "text-yellow-400",
@@ -157,7 +174,7 @@ const alertsClass = computed(() => {
157
174
  "bg-yellow-50 text-yellow-500 hover:bg-yellow-100 focus:ring-yellow-600 focus:ring-offset-yellow-50",
158
175
  },
159
176
  Success: {
160
- bgColor: "bg-green-50",
177
+ bgColor: "bg-green-50 border-green-200",
161
178
  leftIcon: {
162
179
  icon: CheckCircleIcon,
163
180
  color: "text-green-400",
@@ -172,7 +189,7 @@ const alertsClass = computed(() => {
172
189
  "bg-green-50 text-green-500 hover:bg-green-100 focus:ring-green-600 focus:ring-offset-green-50",
173
190
  },
174
191
  Error: {
175
- bgColor: "bg-red-50",
192
+ bgColor: "bg-red-50 border-red-200",
176
193
  leftIcon: {
177
194
  icon: XCircleIcon,
178
195
  color: "text-red-400",
@@ -28,6 +28,10 @@ declare const __VLS_component: import('../../../node_modules/vue').DefineCompone
28
28
  type: BooleanConstructor;
29
29
  default: boolean;
30
30
  };
31
+ indeterminate: {
32
+ type: BooleanConstructor;
33
+ default: boolean;
34
+ };
31
35
  label: {
32
36
  type: PropType<string>;
33
37
  required: false;
@@ -56,6 +60,10 @@ declare const __VLS_component: import('../../../node_modules/vue').DefineCompone
56
60
  type: BooleanConstructor;
57
61
  default: boolean;
58
62
  };
63
+ indeterminate: {
64
+ type: BooleanConstructor;
65
+ default: boolean;
66
+ };
59
67
  label: {
60
68
  type: PropType<string>;
61
69
  required: false;
@@ -70,6 +78,7 @@ declare const __VLS_component: import('../../../node_modules/vue').DefineCompone
70
78
  name: string;
71
79
  errors: Record<string, any>;
72
80
  modelValue: boolean;
81
+ indeterminate: boolean;
73
82
  }, {}, {}, {}, string, import('../../../node_modules/vue').ComponentProvideOptions, true, {}, HTMLDivElement>;
74
83
  declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
75
84
  export default _default;
@@ -1,8 +1,16 @@
1
1
  <template>
2
2
  <div>
3
3
  <label class="flex flex-row items-center scale-100 translate-x-0 translate-y-0 eui-checkbox">
4
- <input v-model="isChecked" type="checkbox" id="checkbox" class="appearance-none sr-only input-checkbox" :disabled="disabled"
5
- @change="toggle($event)" />
4
+ <input
5
+ v-model="isChecked"
6
+ type="checkbox"
7
+ id="checkbox"
8
+ class="appearance-none sr-only input-checkbox"
9
+ :disabled="disabled"
10
+ :indeterminate.prop="indeterminate"
11
+ :aria-checked="indeterminate ? 'mixed' : isChecked"
12
+ @change="toggle($event)"
13
+ />
6
14
  <div class="cbx-icon" for="checkbox">
7
15
  <span>
8
16
  <svg width="14px" height="14px">
@@ -45,6 +53,10 @@ const props = defineProps({
45
53
  type: Boolean,
46
54
  default: false,
47
55
  },
56
+ indeterminate: {
57
+ type: Boolean,
58
+ default: false,
59
+ },
48
60
  label: { type: String as PropType<string>, required: false, default: "" },
49
61
  });
50
62
 
@@ -56,9 +68,7 @@ watch(isChecked, (newValue) => {
56
68
  });
57
69
 
58
70
  const toggle = ($event: Event) => {
59
- if($event) {
60
- emit("toggle", isChecked.value);
61
- }
71
+ emit("toggle", ($event.target as HTMLInputElement).checked);
62
72
  };
63
73
 
64
74
  watch(props, (newValue) => {
@@ -97,6 +107,15 @@ watch(props, (newValue) => {
97
107
  @apply bg-purple-700 border-purple-700;
98
108
  }
99
109
 
110
+ .eui-checkbox .input-checkbox:indeterminate + .cbx-icon > span {
111
+ @apply bg-purple-700 border-purple-700;
112
+ }
113
+
114
+ .eui-checkbox .input-checkbox:indeterminate + .cbx-icon > span::after {
115
+ content: '';
116
+ @apply absolute left-1/2 top-1/2 h-0.5 w-2.5 -translate-x-1/2 -translate-y-1/2 rounded bg-white;
117
+ }
118
+
100
119
  .eui-checkbox .input-checkbox:checked + .cbx-icon span > svg {
101
120
  stroke-dashoffset: 0;
102
121
  transition: rotate(8deg);
@@ -17,7 +17,7 @@
17
17
  'is-open': isDatepickerOpen,
18
18
  },
19
19
  inputFilled
20
- ? 'overflow-hidden border border-gray-100 cursor-pointer group h-14 rounded-xl eui-datepicker'
20
+ ? 'overflow-hidden border border-gray-200 cursor-pointer group h-14 rounded-xl eui-datepicker'
21
21
  : 'h-10 eui-datepicker normal',
22
22
  'relative w-full mb-2',
23
23
  ]"
@@ -283,7 +283,7 @@ const clearIconRight = computed(() =>
283
283
  @apply min-w-44;
284
284
  .dp__main {
285
285
  .dp__input {
286
- @apply pb-2 pt-6 border-0 transition-colors duration-100 ease-in-out text-sm font-medium leading-6 placeholder:text-gray-400 placeholder:font-normal;
286
+ @apply pb-2 pt-6 border-0 transition-colors duration-100 ease-in-out text-sm font-medium leading-6 placeholder:text-gray-600 placeholder:font-normal;
287
287
  padding-left: v-bind(iconshowLeft);
288
288
  padding-right: v-bind(iconshowRight);
289
289
  }
@@ -300,7 +300,7 @@ const clearIconRight = computed(() =>
300
300
  &.normal {
301
301
  .dp__main {
302
302
  .dp__input {
303
- @apply py-2 ring-1 ring-gray-100;
303
+ @apply py-2 ring-1 ring-gray-200;
304
304
  }
305
305
  .dp__input.dp__input_focus {
306
306
  @apply ring-2 h-10 rounded-md ring-purple-600;
@@ -26,6 +26,12 @@ interface Props {
26
26
  ignoreDeselect?: boolean;
27
27
  popperClasses?: string;
28
28
  showCount?: boolean;
29
+ /** Include an All row for every item in `items` (independent of search). */
30
+ showSelectAll?: boolean;
31
+ selectAllLabel?: string;
32
+ /** Maximum selected tags shown before the More/Less control; 0 shows all. */
33
+ maxVisibleTags?: number;
34
+ tagSize?: "sm" | "md" | "lg";
29
35
  }
30
36
  export type SelectItemKey = string | (string | number)[] | ((item: object, fallback?: any) => any);
31
37
  declare function __VLS_template(): {
@@ -199,6 +205,10 @@ declare const __VLS_component: import('../../../node_modules/vue').DefineCompone
199
205
  ignoreDeselect: boolean;
200
206
  popperClasses: string;
201
207
  showCount: boolean;
208
+ showSelectAll: boolean;
209
+ selectAllLabel: string;
210
+ maxVisibleTags: number;
211
+ tagSize: "sm" | "md" | "lg";
202
212
  }, {}, {}, {}, string, import('../../../node_modules/vue').ComponentProvideOptions, false, {
203
213
  componentRef: HTMLDivElement;
204
214
  searchInputRef: import('../../../node_modules/vue').CreateComponentPublicInstanceWithMixins<Readonly<import('../../../node_modules/vue').ExtractPropTypes<{
@@ -38,6 +38,7 @@
38
38
  <button
39
39
  v-else-if="!showDropDown && selectedValues.length > 0"
40
40
  type="button"
41
+ :disabled="disabled"
41
42
  class="flex items-center justify-between w-full h-10 gap-2 px-4 py-2 text-left bg-white border border-gray-200 border-solid cursor-pointer search-textstyle rounded-3xl"
42
43
  @click="handleOpen"
43
44
  >
@@ -100,6 +101,30 @@
100
101
  aria-activedescendant="listbox-option-3"
101
102
  class="space-y-0.5"
102
103
  >
104
+ <li
105
+ v-if="selectType === 'multiple' && showSelectAll && items.length"
106
+ role="option"
107
+ :aria-selected="allItemsSelected"
108
+ class="mb-2 border-b border-gray-100 pb-2"
109
+ @click.stop
110
+ >
111
+ <EUICheckbox
112
+ :model-value="allItemsSelected"
113
+ :indeterminate="someItemsSelected && !allItemsSelected"
114
+ :disabled="disabled"
115
+ :class="[
116
+ 'relative flex items-center text-sm transition-colors duration-75 w-full multiple-select rounded-md font-medium [&_label]:w-full [&_label]:p-2.5',
117
+ allItemsSelected || someItemsSelected
118
+ ? 'text-gray-800 hover:bg-purple-50 hover:text-purple-600'
119
+ : 'text-gray-600 hover:bg-gray-50 hover:text-gray-800',
120
+ ]"
121
+ @toggle="handleSelectAll"
122
+ >
123
+ <template #label>
124
+ <span class="ms-2">{{ selectAllLabel }}</span>
125
+ </template>
126
+ </EUICheckbox>
127
+ </li>
103
128
  <li v-if="filteredItems.length === 0 && !hideNoData">
104
129
  <slot name="no-items">
105
130
  <div
@@ -173,7 +198,7 @@
173
198
  : 'text-gray-600 hover:bg-gray-50 hover:text-gray-800',
174
199
  'relative flex items-center capitalize text-sm transition-colors duration-75 w-full multiple-select rounded-md font-medium [&_label]:w-full [&_label]:p-2.5',
175
200
  ]"
176
- @update:model-value="
201
+ @toggle="
177
202
  (checked) => handleCheckboxChange(item, checked)
178
203
  "
179
204
  >
@@ -197,26 +222,50 @@
197
222
  <slot v-if="$slots.labelhint" name="labelhint"></slot>
198
223
  <div
199
224
  v-if="selectType === 'multiple' && selectedValues.length > 0 && showTags"
200
- class="px-0.5 my-2 inline-flex gap-x-3 gap-y-2 items-center flex-wrap"
225
+ class="my-2 space-y-2"
201
226
  >
202
- <slot
203
- v-for="(item, index) in selectedValues"
204
- name="selection"
205
- :item="item"
206
- :clear="() => handleDeselect(item)"
207
- :key="`selected-values-${index}`"
227
+ <div
228
+ class="px-0.5 gap-x-3 gap-y-2 items-center flex-wrap"
229
+ :class="[
230
+ effectiveTagLimit ? 'flex w-full' : 'inline-flex',
231
+ tagsExpanded && effectiveTagLimit ? 'max-h-32 overflow-y-auto' : '',
232
+ ]"
208
233
  >
209
- <EUITag
210
- class="capitalize"
211
- :disabled="disabled"
212
- closeIcon
213
- size="md"
214
- color="secondary"
215
- @remove="handleTagRemove(item)"
234
+ <slot
235
+ v-for="(item, index) in visibleSelectedValues"
236
+ name="selection"
237
+ :item="item"
238
+ :clear="() => handleDeselect(item)"
239
+ :key="`selected-values-${index}`"
240
+ >
241
+ <EUITag
242
+ class="capitalize"
243
+ :disabled="disabled"
244
+ :closeIcon="!disabled"
245
+ :size="tagSize"
246
+ color="secondary"
247
+ @remove="handleTagRemove(item)"
248
+ >
249
+ {{ startCase(item[itemText] || item) }}
250
+ </EUITag>
251
+ </slot>
252
+ <button
253
+ v-if="canExpandTags && !tagsExpanded"
254
+ type="button"
255
+ class="text-xs font-medium text-violet-600 hover:text-violet-700"
256
+ @click="tagsExpanded = true"
216
257
  >
217
- {{ startCase(item[itemText] || item) }}
218
- </EUITag>
219
- </slot>
258
+ +{{ selectedValues.length - effectiveTagLimit }} more
259
+ </button>
260
+ </div>
261
+ <button
262
+ v-if="canExpandTags && tagsExpanded"
263
+ type="button"
264
+ class="text-xs font-medium text-violet-600 hover:text-violet-700"
265
+ @click="tagsExpanded = false"
266
+ >
267
+ Show less
268
+ </button>
220
269
  </div>
221
270
  <div
222
271
  class="absolute top-0 px-2 text-xs text-white rounded right-6"
@@ -289,6 +338,12 @@ interface Props {
289
338
  ignoreDeselect?: boolean;
290
339
  popperClasses?: string;
291
340
  showCount?: boolean;
341
+ /** Include an All row for every item in `items` (independent of search). */
342
+ showSelectAll?: boolean;
343
+ selectAllLabel?: string;
344
+ /** Maximum selected tags shown before the More/Less control; 0 shows all. */
345
+ maxVisibleTags?: number;
346
+ tagSize?: "sm" | "md" | "lg";
292
347
  }
293
348
  const props = withDefaults(defineProps<Props>(), {
294
349
  items: () => [],
@@ -314,6 +369,10 @@ const props = withDefaults(defineProps<Props>(), {
314
369
  ignoreDeselect: false,
315
370
  popperClasses: "",
316
371
  showCount: false,
372
+ showSelectAll: false,
373
+ selectAllLabel: "All",
374
+ maxVisibleTags: 0,
375
+ tagSize: "md",
317
376
  });
318
377
 
319
378
 
@@ -337,6 +396,7 @@ const options = ref<HTMLElement>();
337
396
  const searchInputRef = ref<any>();
338
397
  const componentRef = ref<HTMLElement>();
339
398
  const isOpening = ref(false);
399
+ const tagsExpanded = ref(false);
340
400
 
341
401
  // Computed properties
342
402
  const selectedValues = computed({
@@ -362,6 +422,37 @@ const selected = computed(() => {
362
422
  };
363
423
  });
364
424
 
425
+ const sameItem = (a: any, b: any) =>
426
+ a != null &&
427
+ b != null &&
428
+ getPropertyFromItem(a, props.itemText) ===
429
+ getPropertyFromItem(b, props.itemText);
430
+
431
+ const allItemsSelected = computed(
432
+ () => props.items.length > 0 && props.items.every((item) => selected.value(item))
433
+ );
434
+ const someItemsSelected = computed(() =>
435
+ props.items.some((item) => selected.value(item))
436
+ );
437
+
438
+ const effectiveTagLimit = computed(() =>
439
+ Number.isFinite(props.maxVisibleTags) && props.maxVisibleTags > 0
440
+ ? Math.floor(props.maxVisibleTags)
441
+ : 0
442
+ );
443
+ const canExpandTags = computed(
444
+ () => effectiveTagLimit.value > 0 && selectedValues.value.length > effectiveTagLimit.value
445
+ );
446
+ const visibleSelectedValues = computed(() =>
447
+ canExpandTags.value && !tagsExpanded.value
448
+ ? selectedValues.value.slice(0, effectiveTagLimit.value)
449
+ : selectedValues.value
450
+ );
451
+
452
+ watch(canExpandTags, (canExpand) => {
453
+ if (!canExpand) tagsExpanded.value = false;
454
+ });
455
+
365
456
  export type SelectItemKey =
366
457
  | string
367
458
  | (string | number)[]
@@ -434,8 +525,7 @@ const filteredItems = computed(() => {
434
525
  });
435
526
 
436
527
  const handleDeselect = (item: any) => {
437
- // console.log("called with:", item, selectedValues.value);
438
- if (props.ignoreDeselect) return;
528
+ if (props.ignoreDeselect || props.disabled) return;
439
529
  let index = -1;
440
530
  if (typeof item === "object" && item[props.itemText]) {
441
531
  index = selectedValues.value.findIndex(
@@ -464,10 +554,26 @@ const handleDeselect = (item: any) => {
464
554
  };
465
555
 
466
556
  const handleClearAll = () => {
557
+ if (props.disabled) return;
467
558
  emit("update:modelValue", []);
468
559
  emit("toggle");
469
560
  };
470
561
 
562
+ const handleSelectAll = (checked: boolean) => {
563
+ if (props.disabled || props.selectType !== "multiple") return;
564
+ const next = checked
565
+ ? [
566
+ ...selectedValues.value,
567
+ ...props.items.filter((item) => !selected.value(item)),
568
+ ]
569
+ : selectedValues.value.filter(
570
+ (value: any) => !props.items.some((item) => sameItem(value, item))
571
+ );
572
+ emit("update:modelValue", next);
573
+ emit("on-change", next);
574
+ emit("toggle", next);
575
+ };
576
+
471
577
  const handleTagRemove = (item: any) => {
472
578
  handleDeselect(item);
473
579
  };
@@ -499,6 +605,7 @@ const handleUpdate = (items: any) => {
499
605
  };
500
606
 
501
607
  const handleSelect = (item: any) => {
608
+ if (props.disabled) return;
502
609
  let newSelection: any;
503
610
 
504
611
  if (props.selectType === "multiple" && typeof item === "object") {
@@ -537,6 +644,7 @@ const handleSelect = (item: any) => {
537
644
  };
538
645
 
539
646
  const handleOpen = () => {
647
+ if (props.disabled) return;
540
648
  isOpening.value = true;
541
649
 
542
650
  // Only clear search for single select, preserve it for multiple select
@@ -619,13 +727,6 @@ watch(internalSearch, (value: string) => {
619
727
  emit("search", value);
620
728
  });
621
729
 
622
- watch(
623
- () => props.modelValue,
624
- (newValue, oldValue) => {
625
- console.log("changed from:", oldValue, "to:", newValue);
626
- },
627
- { deep: true }
628
- );
629
730
  </script>
630
731
 
631
732
  <style lang="scss">
@@ -22,6 +22,7 @@
22
22
  :class="['search-input', hasError ? 'error-state' : '']"
23
23
  :placeholder="placeholder"
24
24
  :value="modelValue"
25
+ :disabled="disabled"
25
26
  @input="emitInput"
26
27
  @focus="onFocus"
27
28
  @blur="onBlur"