@indielayer/ui 1.7.5 → 1.8.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 (73) hide show
  1. package/README.md +0 -1
  2. package/docs/components/common/CodePreview.vue +1 -1
  3. package/docs/components/common/CopyButton.vue +1 -1
  4. package/docs/components/toolbar/ToolbarColorToggle.vue +4 -4
  5. package/docs/components/toolbar/ToolbarSearch.vue +1 -1
  6. package/docs/layouts/default.vue +2 -2
  7. package/docs/pages/colors.vue +1 -1
  8. package/docs/pages/component/alert/usage.vue +1 -1
  9. package/docs/pages/component/breadcrumbs/usage.vue +1 -1
  10. package/docs/pages/component/button/button-group.vue +1 -1
  11. package/docs/pages/component/button/variants.vue +1 -1
  12. package/docs/pages/component/drawer/usage.vue +1 -1
  13. package/docs/pages/component/form/usage.vue +2 -1
  14. package/docs/pages/component/formGroup/usage.vue +1 -1
  15. package/docs/pages/component/modal/composed.vue +12 -3
  16. package/docs/pages/component/modal/usage.vue +5 -12
  17. package/docs/pages/component/notifications/usage.vue +9 -9
  18. package/docs/pages/component/pagination/usage.vue +2 -1
  19. package/docs/pages/component/progress/variants.vue +8 -8
  20. package/docs/pages/component/radio/states.vue +6 -6
  21. package/docs/pages/component/radio/variants.vue +6 -6
  22. package/docs/pages/component/select/index.vue +5 -5
  23. package/docs/pages/component/select/{variants.vue → size.vue} +11 -15
  24. package/docs/pages/component/select/states.vue +11 -15
  25. package/docs/pages/component/select/usage.vue +19 -22
  26. package/docs/pages/component/spinner/variants.vue +1 -1
  27. package/docs/pages/component/table/usage.vue +1 -1
  28. package/docs/pages/component/tag/usage.vue +10 -18
  29. package/docs/pages/component/toggle/states.vue +6 -6
  30. package/docs/pages/component/toggle/variants.vue +6 -6
  31. package/docs/pages/icons.vue +36 -39
  32. package/docs/router/index.ts +1 -5
  33. package/lib/components/checkbox/Checkbox.vue.d.ts +4 -0
  34. package/lib/components/datepicker/Datepicker.vue.d.ts +4 -0
  35. package/lib/components/datepicker/Datepicker.vue.js +3 -3
  36. package/lib/components/drawer/Drawer.vue.js +1 -1
  37. package/lib/components/formGroup/FormGroup.vue.d.ts +4 -0
  38. package/lib/components/input/Input.vue.d.ts +7 -0
  39. package/lib/components/input/Input.vue.js +26 -24
  40. package/lib/components/menu/MenuItem.vue2.js +1 -1
  41. package/lib/components/modal/Modal.vue.js +74 -70
  42. package/lib/components/popover/Popover.vue.js +1 -1
  43. package/lib/components/radio/Radio.vue.d.ts +4 -0
  44. package/lib/components/scroll/Scroll.vue2.js +1 -1
  45. package/lib/components/select/Select.vue.d.ts +24 -1
  46. package/lib/components/select/Select.vue.js +302 -264
  47. package/lib/components/select/theme/Select.base.theme.js +3 -1
  48. package/lib/components/select/theme/Select.carbon.theme.js +3 -1
  49. package/lib/components/slider/Slider.vue.d.ts +4 -0
  50. package/lib/components/tab/Tab.vue.js +1 -1
  51. package/lib/components/tab/TabGroup.vue.js +2 -2
  52. package/lib/components/textarea/Textarea.vue.d.ts +4 -0
  53. package/lib/components/textarea/Textarea.vue.js +1 -1
  54. package/lib/components/toggle/Toggle.vue.d.ts +4 -0
  55. package/lib/components/tooltip/Tooltip.vue.js +1 -1
  56. package/lib/composables/useInputtable.d.ts +1 -0
  57. package/lib/composables/useInputtable.js +31 -30
  58. package/lib/index.umd.js +4 -4
  59. package/lib/node_modules/.pnpm/{@vueuse_core@10.2.0_vue@3.3.9 → @vueuse_core@10.2.0_vue@3.3.9_typescript@5.2.2_}/node_modules/@vueuse/core/index.js +2 -2
  60. package/lib/version.d.ts +1 -1
  61. package/lib/version.js +1 -1
  62. package/package.json +1 -1
  63. package/src/components/input/Input.vue +3 -1
  64. package/src/components/modal/Modal.vue +11 -2
  65. package/src/components/select/Select.vue +70 -25
  66. package/src/components/select/theme/Select.base.theme.ts +5 -1
  67. package/src/components/select/theme/Select.carbon.theme.ts +5 -1
  68. package/src/composables/useInputtable.ts +6 -3
  69. package/src/version.ts +1 -1
  70. /package/lib/node_modules/.pnpm/{@vuepic_vue-datepicker@8.3.2_vue@3.3.9 → @vuepic_vue-datepicker@8.3.2_vue@3.3.9_typescript@5.2.2_}/node_modules/@vuepic/vue-datepicker/dist/main.css.js +0 -0
  71. /package/lib/node_modules/.pnpm/{@vuepic_vue-datepicker@8.3.2_vue@3.3.9 → @vuepic_vue-datepicker@8.3.2_vue@3.3.9_typescript@5.2.2_}/node_modules/@vuepic/vue-datepicker/dist/vue-datepicker.js +0 -0
  72. /package/lib/node_modules/.pnpm/{@vueuse_shared@10.2.0_vue@3.3.9 → @vueuse_shared@10.2.0_vue@3.3.9_typescript@5.2.2_}/node_modules/@vueuse/shared/index.js +0 -0
  73. /package/lib/node_modules/.pnpm/{floating-vue@5.2.2_vue@3.3.9 → floating-vue@5.2.2_@nuxt_kit@3.10.1_rollup@3.29.4__vue@3.3.9_typescript@5.2.2_}/node_modules/floating-vue/dist/floating-vue.js +0 -0
@@ -1,5 +1,5 @@
1
- import { noop as j, toValue as L, tryOnScopeDispose as k, isIOS as G, useThrottleFn as Q, isClient as N, increaseWithUnit as U, toRef as J, useDebounceFn as K } from "../../../../@vueuse_shared@10.2.0_vue@3.3.9/node_modules/@vueuse/shared/index.js";
2
- import { createFilterWrapper as Oe, debounceFilter as ge, throttleFilter as Se } from "../../../../@vueuse_shared@10.2.0_vue@3.3.9/node_modules/@vueuse/shared/index.js";
1
+ import { noop as j, toValue as L, tryOnScopeDispose as k, isIOS as G, useThrottleFn as Q, isClient as N, increaseWithUnit as U, toRef as J, useDebounceFn as K } from "../../../../@vueuse_shared@10.2.0_vue@3.3.9_typescript@5.2.2_/node_modules/@vueuse/shared/index.js";
2
+ import { createFilterWrapper as Oe, debounceFilter as ge, throttleFilter as Se } from "../../../../@vueuse_shared@10.2.0_vue@3.3.9_typescript@5.2.2_/node_modules/@vueuse/shared/index.js";
3
3
  import { watch as F, computed as g, ref as T, reactive as D, watchEffect as Z, getCurrentInstance as ee, onMounted as te } from "vue";
4
4
  function _(e) {
5
5
  var o;
package/lib/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- declare const _default: "1.7.5";
1
+ declare const _default: "1.8.1";
2
2
  export default _default;
package/lib/version.js CHANGED
@@ -1,4 +1,4 @@
1
- const e = "1.7.5";
1
+ const e = "1.8.1";
2
2
  export {
3
3
  e as default
4
4
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indielayer/ui",
3
- "version": "1.7.5",
3
+ "version": "1.8.1",
4
4
  "description": "Indielayer UI Components with Tailwind CSS build for Vue 3",
5
5
  "author": {
6
6
  "name": "João Teixeira",
@@ -24,6 +24,7 @@ const inputProps = {
24
24
  type: String,
25
25
  default: 'text',
26
26
  },
27
+ step: [Number, String],
27
28
  block: Boolean,
28
29
  }
29
30
 
@@ -147,7 +148,7 @@ defineExpose({ focus, blur, reset, validate, setError })
147
148
  ? 'border-error-500 dark:border-error-400 focus:outline-error-500'
148
149
  : 'focus:outline-[color:var(--x-input-border)]',
149
150
  {
150
- '!pl-10': iconLeft,
151
+ '!pl-10': iconLeft || icon,
151
152
  '!pr-10': iconRight,
152
153
  },
153
154
  ]"
@@ -156,6 +157,7 @@ defineExpose({ focus, blur, reset, validate, setError })
156
157
  :max="max"
157
158
  :minlength="minlength"
158
159
  :maxlength="maxlength"
160
+ :step="step"
159
161
  :dir="dir"
160
162
  :name="name"
161
163
  :placeholder="placeholder"
@@ -67,7 +67,7 @@ export default {
67
67
  </script>
68
68
 
69
69
  <script setup lang="ts">
70
- import { ref, watch, type PropType, type ExtractPublicPropTypes, computed, nextTick, onMounted } from 'vue'
70
+ import { ref, watch, type PropType, type ExtractPublicPropTypes, computed, nextTick } from 'vue'
71
71
  import { onClickOutside, useEventListener } from '@vueuse/core'
72
72
  import { useTheme, type ThemeComponent } from '../../composables/useTheme'
73
73
  import { useFocusTrap } from '../../composables/useFocusTrap'
@@ -132,8 +132,17 @@ async function checkVisibiliy() {
132
132
 
133
133
  if (typeof window !== 'undefined') useEventListener(document, 'keydown', onKeyDown)
134
134
 
135
+ const shouldIgnoreEvent = (event: KeyboardEvent) => {
136
+ return ['.v-popper__popper', '.x-datepicker'].some((target) => {
137
+ if (typeof target === 'string') {
138
+ return Array.from(window.document.querySelectorAll(target))
139
+ .some((el) => el === event.target || event.composedPath().includes(el))
140
+ }
141
+ })
142
+ }
143
+
135
144
  function onKeyDown(event: KeyboardEvent) {
136
- if (event.key === 'Escape' && value.value && !props.persistent) close()
145
+ if (event.key === 'Escape' && !shouldIgnoreEvent(event) && value.value && !props.persistent) close()
137
146
  }
138
147
 
139
148
  function clickOutsideCallback() {
@@ -9,6 +9,11 @@ const selectProps = {
9
9
  multiple: Boolean,
10
10
  flat: Boolean,
11
11
  native: Boolean,
12
+ filterable: Boolean,
13
+ filterPlaceholder: {
14
+ type: String,
15
+ default: 'Filter by...',
16
+ },
12
17
  }
13
18
 
14
19
  export type SelectOption = {
@@ -19,7 +24,7 @@ export type SelectOption = {
19
24
 
20
25
  export type SelectProps = ExtractPublicPropTypes<typeof selectProps>
21
26
 
22
- type InternalClasses = 'wrapper' | 'box' | 'content' | 'iconWrapper' | 'icon'
27
+ type InternalClasses = 'wrapper' | 'box' | 'content' | 'search' | 'contentBody' | 'iconWrapper' | 'icon'
23
28
  type InternalExtraData = { errorInternal: Ref<boolean>; }
24
29
  export interface SelectTheme extends ThemeComponent<SelectProps, InternalClasses, InternalExtraData> {}
25
30
 
@@ -49,6 +54,7 @@ import XSpinner from '../spinner/Spinner.vue'
49
54
  import XPopover from '../popover/Popover.vue'
50
55
  import XPopoverContainer from '../popover/PopoverContainer.vue'
51
56
  import XInputFooter from '../inputFooter/InputFooter.vue'
57
+ import type { XInput } from '../input'
52
58
 
53
59
  const props = defineProps(selectProps)
54
60
 
@@ -60,6 +66,9 @@ const itemsRef = ref<InstanceType<typeof XMenuItem>[] | null>(null)
60
66
  const popoverRef = ref<InstanceType<typeof XPopover> | null>(null)
61
67
  const selectedIndex = ref<number | undefined>()
62
68
 
69
+ const filter = ref('')
70
+ const filterRef = ref<InstanceType<typeof XInput> | null>(null)
71
+
63
72
  const selected = computed<any | any[]>({
64
73
  get() {
65
74
  if (props.multiple) {
@@ -78,40 +87,57 @@ const selected = computed<any | any[]>({
78
87
  const internalOptions = computed(() => {
79
88
  if (!props.options || props.options.length === 0) return []
80
89
 
81
- return props.options.map((option) => {
82
- let isActive = false
90
+ return props.options
91
+ .filter((option) => filter.value === '' || option.label.toLowerCase().includes(filter.value.toLowerCase()))
92
+ .map((option) => {
93
+ let isActive = false
83
94
 
84
- if (props.multiple && Array.isArray(selected.value)) {
85
- isActive = selected.value.includes(option.value)
86
- } else {
87
- isActive = option.value === selected.value
88
- }
95
+ if (props.multiple && Array.isArray(selected.value)) {
96
+ isActive = selected.value.includes(option.value)
97
+ } else {
98
+ isActive = option.value === selected.value
99
+ }
89
100
 
90
- return {
91
- value: option.value,
92
- label: option.label,
93
- active: isActive,
94
- disabled: option.disabled,
95
- iconRight: isActive ? checkIcon : undefined,
96
- onClick: () => handleOptionClick(option.value),
97
- }
98
- })
101
+ return {
102
+ value: option.value,
103
+ label: option.label,
104
+ active: isActive,
105
+ disabled: option.disabled,
106
+ iconRight: isActive ? checkIcon : undefined,
107
+ onClick: () => handleOptionClick(option.value),
108
+ }
109
+ })
99
110
  })
100
111
 
101
- const availableOptions = computed(() => props.options?.filter((option) => !option.disabled))
112
+ const availableOptions = computed(() => internalOptions.value.filter((option) => !option.disabled))
102
113
 
103
114
  const isOpen = computed(() => popoverRef.value?.isOpen)
104
115
 
116
+ watch(filter, (val) => {
117
+ if (val) {
118
+ selectedIndex.value = undefined
119
+ findSelectableIndex(-1)
120
+ }
121
+ })
122
+
105
123
  watch(isOpen, (isOpenValue) => {
106
124
  if (isOpenValue) {
107
125
  findSelectedIndex()
108
- setTimeout(() => {
109
- scrollToIndex(selectedIndex.value || 0)
110
- }, 50)
111
126
 
112
127
  if (props.multiple || typeof selectedIndex.value === 'undefined') {
113
128
  findSelectableIndex(-1)
114
129
  }
130
+
131
+ setTimeout(() => {
132
+ requestAnimationFrame(() => {
133
+ scrollToIndex(selectedIndex.value || 0)
134
+
135
+ if (props.filterable) filterRef.value?.focus()
136
+ })
137
+ }, 50)
138
+
139
+ } else {
140
+ if (props.filterable) filter.value = ''
115
141
  }
116
142
  })
117
143
 
@@ -184,6 +210,11 @@ function handleOptionClick(value: string | number) {
184
210
  } else {
185
211
  selected.value = [value]
186
212
  }
213
+
214
+ if (props.filterable)
215
+ setTimeout(() => {
216
+ filterRef.value?.focus()
217
+ })
187
218
  } else {
188
219
  selected.value = value
189
220
  }
@@ -285,7 +316,9 @@ function handleKeyNavigation(e: KeyboardEvent) {
285
316
  return
286
317
  }
287
318
  findSelectableIndex(selectedIndex.value, 'up')
288
- } else if (e.code === 'Enter' || e.code === 'Space') {
319
+ } else if (e.code === 'Enter' || (e.code === 'Space')) {
320
+ if (e.code === 'Space' && props.filterable) return
321
+
289
322
  e.preventDefault()
290
323
  e.stopPropagation()
291
324
  if (!isOpen.value) {
@@ -293,7 +326,7 @@ function handleKeyNavigation(e: KeyboardEvent) {
293
326
 
294
327
  return
295
328
  }
296
- if (typeof selectedIndex.value !== 'undefined') {
329
+ if (typeof selectedIndex.value !== 'undefined' && internalOptions.value[selectedIndex.value]) {
297
330
  handleOptionClick(internalOptions.value[selectedIndex.value].value)
298
331
  if (!props.multiple) popoverRef.value?.hide()
299
332
  }
@@ -397,7 +430,18 @@ defineExpose({ focus, blur, reset, validate, setError })
397
430
 
398
431
  <template #content>
399
432
  <x-popover-container :class="classes.content">
400
- <template v-if="internalOptions.length > 0">
433
+ <slot name="content-header">
434
+ <div v-if="filterable" :class="classes.search">
435
+ <x-input
436
+ ref="filterRef"
437
+ v-model="filter"
438
+ :placeholder="filterPlaceholder"
439
+ skip-form-registry
440
+ size="sm"
441
+ />
442
+ </div>
443
+ </slot>
444
+ <div v-if="internalOptions.length > 0" :class="classes.contentBody">
401
445
  <x-menu-item
402
446
  v-for="(item, index) in internalOptions"
403
447
  :key="index"
@@ -410,10 +454,11 @@ defineExpose({ focus, blur, reset, validate, setError })
410
454
  filled
411
455
  @click="() => !multiple && popoverRef?.hide()"
412
456
  />
413
- </template>
457
+ </div>
414
458
  <div v-else class="px-2 text-center text-secondary-400">
415
459
  No options
416
460
  </div>
461
+ <slot name="content-footer"></slot>
417
462
  </x-popover-container>
418
463
  </template>
419
464
  </x-popover>
@@ -27,7 +27,11 @@ const theme: SelectTheme = {
27
27
  return classes
28
28
  },
29
29
 
30
- content: 'p-1 max-h-72 overflow-y-auto',
30
+ content: 'p-1',
31
+
32
+ search: 'p-1 mb-0.5',
33
+
34
+ contentBody: 'overflow-y-auto max-h-64',
31
35
 
32
36
  iconWrapper: 'pointer-events-none absolute inset-y-0 right-0 flex items-center px-2',
33
37
 
@@ -30,7 +30,11 @@ const theme: SelectTheme = {
30
30
  return classes
31
31
  },
32
32
 
33
- content: 'py-1 max-h-72 overflow-y-auto',
33
+ content: 'p-1',
34
+
35
+ search: 'p-1 mb-0.5',
36
+
37
+ contentBody: 'overflow-y-auto max-h-64',
34
38
 
35
39
  iconWrapper: 'pointer-events-none absolute inset-y-0 right-0 flex items-center px-2',
36
40
 
@@ -118,7 +118,8 @@ export const useInputtable = (props: any, { focus, emit, withListeners = true }:
118
118
  if (formGroup.isInsideFormGroup) {
119
119
  formGroup.registerInputGroup(nameInternal.value, focus)
120
120
  } else {
121
- form.registerInput(nameInternal.value, focus, validate, setError)
121
+ if (!props.skipFormRegistry)
122
+ form.registerInput(nameInternal.value, focus, validate, setError)
122
123
  }
123
124
  })
124
125
 
@@ -126,7 +127,8 @@ export const useInputtable = (props: any, { focus, emit, withListeners = true }:
126
127
  if (formGroup.isInsideFormGroup) {
127
128
  formGroup.unregisterInputGroup(nameInternal.value)
128
129
  } else {
129
- form.unregisterInput(nameInternal.value)
130
+ if (!props.skipFormRegistry)
131
+ form.unregisterInput(nameInternal.value)
130
132
  }
131
133
 
132
134
  })
@@ -136,7 +138,7 @@ export const useInputtable = (props: any, { focus, emit, withListeners = true }:
136
138
  errorInternal,
137
139
  hideFooterInternal,
138
140
  isFocused,
139
- isInsideForm: form.isInsideForm,
141
+ isInsideForm: props.skipFormRegistry ? false : form.isInsideForm,
140
142
  isInsideFormGroup: formGroup.isInsideFormGroup,
141
143
  inputListeners,
142
144
  formGroup,
@@ -174,4 +176,5 @@ useInputtable.props = () => ({
174
176
  default: () => [],
175
177
  },
176
178
  tooltip: String,
179
+ skipFormRegistry: Boolean,
177
180
  } as const)
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export default '1.7.5'
1
+ export default '1.8.1'