@indielayer/ui 1.6.1 → 1.6.3

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 (66) hide show
  1. package/docs/components/toolbar/Toolbar.vue +4 -2
  2. package/docs/components/toolbar/ToolbarSearch.vue +256 -0
  3. package/docs/pages/component/button/usage.vue +1 -1
  4. package/docs/pages/component/checkbox/states.vue +1 -1
  5. package/docs/pages/component/checkbox/usage.vue +1 -8
  6. package/docs/pages/component/input/size.vue +3 -2
  7. package/docs/pages/component/input/states.vue +3 -3
  8. package/docs/pages/component/input/usage.vue +1 -1
  9. package/docs/pages/component/input/variants.vue +2 -2
  10. package/docs/pages/component/radio/usage.vue +6 -7
  11. package/docs/pages/component/table/usage.vue +35 -40
  12. package/docs/pages/component/textarea/states.vue +8 -9
  13. package/docs/pages/component/textarea/variants.vue +7 -8
  14. package/docs/search/components.json +1 -0
  15. package/lib/components/button/theme/Button.base.theme.js +1 -1
  16. package/lib/components/card/theme/Card.base.theme.js +3 -3
  17. package/lib/components/checkbox/Checkbox.vue.d.ts +13 -3
  18. package/lib/components/form/Form.vue.js +8 -8
  19. package/lib/components/formGroup/FormGroup.vue.d.ts +13 -3
  20. package/lib/components/input/Input.vue.d.ts +13 -3
  21. package/lib/components/input/Input.vue.js +15 -15
  22. package/lib/components/input/theme/Input.base.theme.js +1 -1
  23. package/lib/components/modal/Modal.vue.d.ts +30 -4
  24. package/lib/components/modal/Modal.vue.js +82 -68
  25. package/lib/components/modal/theme/Modal.base.theme.js +12 -8
  26. package/lib/components/notifications/theme/Notifications.base.theme.js +1 -1
  27. package/lib/components/radio/Radio.vue.d.ts +13 -3
  28. package/lib/components/select/Select.vue.d.ts +13 -3
  29. package/lib/components/select/theme/Select.base.theme.js +1 -1
  30. package/lib/components/slider/Slider.vue.d.ts +13 -3
  31. package/lib/components/table/Table.vue.js +101 -98
  32. package/lib/components/table/theme/TableCell.base.theme.js +1 -1
  33. package/lib/components/table/theme/TableHead.base.theme.js +5 -5
  34. package/lib/components/table/theme/TableHeader.base.theme.js +2 -2
  35. package/lib/components/table/theme/TableRow.base.theme.js +1 -1
  36. package/lib/components/textarea/Textarea.vue.d.ts +13 -3
  37. package/lib/components/textarea/Textarea.vue.js +9 -9
  38. package/lib/components/textarea/theme/Textarea.base.theme.js +1 -1
  39. package/lib/components/toggle/Toggle.vue.d.ts +13 -3
  40. package/lib/composables/useFocusTrap.js +23 -31
  41. package/lib/composables/useInputtable.d.ts +4 -1
  42. package/lib/composables/useInputtable.js +22 -19
  43. package/lib/index.js +1 -1
  44. package/lib/index.umd.js +4 -4
  45. package/lib/version.d.ts +1 -1
  46. package/lib/version.js +1 -1
  47. package/package.json +7 -5
  48. package/src/components/button/theme/Button.base.theme.ts +2 -2
  49. package/src/components/card/theme/Card.base.theme.ts +1 -1
  50. package/src/components/form/Form.vue +1 -1
  51. package/src/components/input/Input.vue +3 -4
  52. package/src/components/input/theme/Input.base.theme.ts +1 -1
  53. package/src/components/modal/Modal.vue +33 -18
  54. package/src/components/modal/theme/Modal.base.theme.ts +10 -0
  55. package/src/components/notifications/theme/Notifications.base.theme.ts +1 -1
  56. package/src/components/select/theme/Select.base.theme.ts +1 -1
  57. package/src/components/table/Table.vue +1 -1
  58. package/src/components/table/theme/TableCell.base.theme.ts +1 -1
  59. package/src/components/table/theme/TableHead.base.theme.ts +2 -2
  60. package/src/components/table/theme/TableHeader.base.theme.ts +2 -2
  61. package/src/components/table/theme/TableRow.base.theme.ts +1 -1
  62. package/src/components/textarea/Textarea.vue +1 -1
  63. package/src/components/textarea/theme/Textarea.base.theme.ts +1 -1
  64. package/src/composables/useFocusTrap.ts +0 -23
  65. package/src/composables/useInputtable.ts +5 -1
  66. package/src/version.ts +1 -1
package/lib/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- declare const _default: "1.6.1";
1
+ declare const _default: "1.6.3";
2
2
  export default _default;
package/lib/version.js CHANGED
@@ -1,4 +1,4 @@
1
- const e = "1.6.1";
1
+ const e = "1.6.3";
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.6.1",
3
+ "version": "1.6.3",
4
4
  "description": "Indielayer UI Components with Tailwind CSS build for Vue 3",
5
5
  "author": {
6
6
  "name": "João Teixeira",
@@ -64,6 +64,7 @@
64
64
  "clean-css": "^5.3.0",
65
65
  "eslint": "^8.43.0",
66
66
  "floating-vue": "^5.2.2",
67
+ "fuse.js": "^7.0.0",
67
68
  "jsdom": "^22.1.0",
68
69
  "postcss": "^8.4.4",
69
70
  "rollup-plugin-visualizer": "^5.9.2",
@@ -98,13 +99,14 @@
98
99
  "dev": "vite dev --mode docs",
99
100
  "build": "pnpm generate && vite build",
100
101
  "build:docs": "pnpm build --mode docs",
101
- "build:prod": "pnpm build && pnpm gen-types",
102
+ "build:prod": "pnpm build && pnpm gen:types",
102
103
  "build:watch": "pnpm generate && vite build --watch",
103
104
  "build:only": "vite build",
104
105
  "build:stats": "VITE_VISUALIZER=Y npm run build",
105
- "generate": "pnpm gen-version",
106
- "gen-types": "vue-tsc --declaration --emitDeclarationOnly -p tsconfig.vitest.json --composite false",
107
- "gen-version": "node .scripts/gen-version.cjs",
106
+ "generate": "pnpm gen:version",
107
+ "gen:types": "vue-tsc --declaration --emitDeclarationOnly -p tsconfig.vitest.json --composite false",
108
+ "gen:version": "node .scripts/gen-version.cjs",
109
+ "gen:search": "node .scripts/gen-search.cjs",
108
110
  "test": "pnpm test:unit",
109
111
  "test:unit": "vitest --environment jsdom",
110
112
  "typecheck": "vue-tsc --noEmit -p tsconfig.vitest.json --composite false",
@@ -12,8 +12,8 @@ const theme: ButtonTheme = {
12
12
  if (!props.flat && !props.light && !props.ghost && !props.disabled && !props.loading) classes.push('shadow-sm')
13
13
 
14
14
  // size
15
- if (props.size === 'xs') classes.push(slots.default ? `py-1 text-xs ${props.icon ? 'px-2' : 'px-3'}` : 'leading-none p-1')
16
- else if (props.size === 'sm') classes.push(slots.default ? `py-2 text-sm ${props.icon ? 'px-3' : 'px-4'}` : 'leading-none p-2')
15
+ if (props.size === 'xs') classes.push(slots.default ? `py-1 text-xs ${props.icon ? 'px-2' : 'px-2'}` : 'leading-none p-1')
16
+ else if (props.size === 'sm') classes.push(slots.default ? `py-1.5 text-sm ${props.icon ? 'px-3' : 'px-3'}` : 'leading-none p-1.5')
17
17
  else if (props.size === 'lg') classes.push(slots.default ? `py-3 text-lg ${props.icon ? 'px-4' : 'px-6'}` : 'leading-none p-3')
18
18
  else if (props.size === 'xl') classes.push(slots.default ? `py-4 text-xl ${props.icon ? 'px-6' : 'px-6'}` : 'leading-none p-4')
19
19
  else classes.push(slots.default ? `py-2 ${props.icon ? 'px-4' : 'px-5'}` : 'leading-none p-2')
@@ -2,7 +2,7 @@ import type { CardTheme } from '../Card.vue'
2
2
 
3
3
  const theme: CardTheme = {
4
4
  classes: {
5
- wrapper: ({ props }) => `bg-slate-50 dark:bg-slate-800 rounded-md ${props.flat ? '' : 'shadow'}`,
5
+ wrapper: ({ props }) => `bg-white dark:bg-secondary-800 overflow-hidden rounded-md ${props.flat ? '' : 'shadow'}`,
6
6
  },
7
7
  }
8
8
 
@@ -145,7 +145,7 @@ const { styles, classes, className } = useTheme('Form', {}, props)
145
145
  </div>
146
146
  </slot>
147
147
 
148
- <fieldset :disabled="disabled" :class="classes.content">
148
+ <fieldset :disabled="disabled" :class="classes.content" class="contents">
149
149
  <slot></slot>
150
150
  </fieldset>
151
151
 
@@ -119,9 +119,9 @@ defineExpose({ focus, blur, reset, validate, setError })
119
119
  <div class="relative">
120
120
  <slot name="prefix">
121
121
  <x-icon
122
- v-if="iconLeft"
122
+ v-if="iconLeft || icon"
123
123
  :size="size"
124
- :icon="iconLeft"
124
+ :icon="iconLeft || icon"
125
125
  class="ml-2 left-1"
126
126
  :class="classes.icon"
127
127
  />
@@ -152,8 +152,7 @@ defineExpose({ focus, blur, reset, validate, setError })
152
152
  :placeholder="placeholder"
153
153
  :readonly="readonly"
154
154
  :type="currentType"
155
- :value="modelValue || ''"
156
- v-bind="$attrs"
155
+ :value="typeof modelValue !== 'undefined' ? modelValue : ''"
157
156
  v-on="inputListeners"
158
157
  @change="onChange"
159
158
  />
@@ -10,7 +10,7 @@ const theme: InputTheme = {
10
10
  if (!data.errorInternal && !props.disabled) classes.push('hover:border-secondary-400 dark:hover:border-secondary-500')
11
11
 
12
12
  if (props.size === 'xs') classes.push('px-2 py-1 text-xs')
13
- else if (props.size === 'sm') classes.push('px-2 py-2 text-sm')
13
+ else if (props.size === 'sm') classes.push('px-2 py-1.5 text-sm')
14
14
  else if (props.size === 'lg') classes.push('px-4 py-3 text-lg')
15
15
  else if (props.size === 'xl') classes.push('px-5 py-4 text-xl')
16
16
  else classes.push('px-3 py-2')
@@ -1,13 +1,21 @@
1
1
  <script lang="ts">
2
2
  const modalSize = ['xs', 'sm', 'md', 'lg', 'xl', 'full'] as const
3
+ const modalPosition = ['top', 'center', 'bottom'] as const
3
4
  const modalProps = {
4
5
  size: {
5
6
  type: String as PropType<ModalSize>,
6
7
  default: 'xl',
7
8
  },
9
+ position: {
10
+ type: String as PropType<ModalPosition>,
11
+ default: 'center',
12
+ },
8
13
  modelValue: Boolean,
9
14
  showClose: Boolean,
10
- backdrop: Boolean,
15
+ backdrop: {
16
+ type: Boolean,
17
+ default: true,
18
+ },
11
19
  hasActions: {
12
20
  type: Boolean,
13
21
  default: true,
@@ -40,9 +48,10 @@ const modalProps = {
40
48
  }
41
49
 
42
50
  export type ModalSize = typeof modalSize[number]
51
+ export type ModalPosition = typeof modalPosition[number]
43
52
  export type ModalProps = ExtractPublicPropTypes<typeof modalProps>
44
53
 
45
- type InternalClasses = 'wrapper' | 'backdrop' | 'modal' | 'closeIcon' | 'header' | 'content' | 'actions' | 'title' | 'description' | 'label'
54
+ type InternalClasses = 'wrapper' | 'backdrop' | 'modal' | 'modalWrapper' | 'closeIcon' | 'header' | 'content' | 'actions' | 'title' | 'description' | 'label'
46
55
  type InternaData = {
47
56
  visible: boolean;
48
57
  }
@@ -52,6 +61,7 @@ export default {
52
61
  name: 'XModal',
53
62
  validators: {
54
63
  size: modalSize,
64
+ position: modalPosition,
55
65
  },
56
66
  }
57
67
  </script>
@@ -174,10 +184,11 @@ defineExpose({ open, close })
174
184
  :class="classes.backdrop"
175
185
  ></div>
176
186
 
177
- <div class="flex items-end sm:items-center justify-center p-4 sm:p-6 h-screen">
187
+ <div :class="classes.modalWrapper">
178
188
  <component
179
189
  :is="isForm ? XForm : 'div'"
180
190
  ref="modalRef"
191
+ class="max-h-full"
181
192
  :disabled="formDisabled"
182
193
  :auto-validate="formAutoValidate"
183
194
  :title="formTitle"
@@ -192,12 +203,14 @@ defineExpose({ open, close })
192
203
  @submit="(isValid: boolean) => $emit('submit', isValid)"
193
204
  >
194
205
  <slot name="image"></slot>
195
- <div v-if="hasHeader" :class="classes.header">
196
- <slot name="header">
197
- <div v-if="label" :class="classes.label">{{ label }}</div>
198
- <div v-if="title" :class="classes.title">{{ title }}</div>
199
- </slot>
200
- </div>
206
+ <slot name="header">
207
+ <div v-if="hasHeader" :class="classes.header">
208
+ <slot name="header-content">
209
+ <div v-if="label" :class="classes.label">{{ label }}</div>
210
+ <div v-if="title" :class="classes.title">{{ title }}</div>
211
+ </slot>
212
+ </div>
213
+ </slot>
201
214
  <x-scroll
202
215
  v-if="$slots.default"
203
216
  :scrollbar="false"
@@ -217,15 +230,17 @@ defineExpose({ open, close })
217
230
  :class="classes.closeIcon"
218
231
  @click="close"
219
232
  />
220
- <div v-if="hasActions" :class="classes.actions">
221
- <slot name="actions">
222
- <slot name="cancel-action"></slot>
223
- <div v-if="hasPlaceholder"></div>
224
- <slot name="tertiary-action"></slot>
225
- <slot name="secondary-action"></slot>
226
- <slot name="primary-action"></slot>
227
- </slot>
228
- </div>
233
+ <slot name="footer">
234
+ <div v-if="hasActions" :class="classes.actions">
235
+ <slot name="actions">
236
+ <slot name="cancel-action"></slot>
237
+ <div v-if="hasPlaceholder"></div>
238
+ <slot name="tertiary-action"></slot>
239
+ <slot name="secondary-action"></slot>
240
+ <slot name="primary-action"></slot>
241
+ </slot>
242
+ </div>
243
+ </slot>
229
244
  </component>
230
245
  </div>
231
246
  </div>
@@ -13,6 +13,16 @@ const theme: ModalTheme = {
13
13
  return classes
14
14
  },
15
15
 
16
+ modalWrapper: ({ props }) => {
17
+ const classes = ['flex justify-center p-4 sm:p-8 md:py-20 h-screen']
18
+
19
+ if (props.position === 'top') classes.push('items-start')
20
+ else if (props.position === 'bottom') classes.push('items-end')
21
+ else classes.push('items-end sm:items-center')
22
+
23
+ return classes
24
+ },
25
+
16
26
  modal: ({ props, data }) => {
17
27
  const classes = ['relative flex flex-col z-10 bg-white dark:bg-secondary-900 rounded-md shadow-lg transform transition-all overflow-hidden max-h-full w-full']
18
28
 
@@ -2,7 +2,7 @@ import type { NotificationsTheme } from '../Notifications.vue'
2
2
 
3
3
  const theme: NotificationsTheme = {
4
4
  classes: {
5
- wrapper: 'fixed z-50 w-full sm:w-auto overflow-y-auto max-h-screen',
5
+ wrapper: 'fixed z-50 w-full sm:w-auto max-h-screen',
6
6
 
7
7
  list: 'flex flex-col items-end w-full sm:w-[520px] px-4',
8
8
 
@@ -10,7 +10,7 @@ const theme: SelectTheme = {
10
10
  if (!data.errorInternal && !props.disabled) classes.push('hover:border-secondary-400 dark:hover:border-secondary-500')
11
11
 
12
12
  if (props.size === 'xs') classes.push('px-2 py-1 text-xs')
13
- else if (props.size === 'sm') classes.push('px-2 py-2 text-sm')
13
+ else if (props.size === 'sm') classes.push('px-2 py-1.5 text-sm')
14
14
  else if (props.size === 'lg') classes.push('px-4 py-3 text-lg')
15
15
  else if (props.size === 'xl') classes.push('px-5 py-4 text-xl')
16
16
  else classes.push('px-3 py-2')
@@ -252,7 +252,7 @@ const { styles, classes, className } = useTheme('Table', {}, props)
252
252
  </slot>
253
253
  </x-table-cell>
254
254
  </x-table-row>
255
- <tr v-if="expandable">
255
+ <tr v-if="expandable" :class="{ 'hidden': !internalItems[index]?.__expanded }">
256
256
  <td colspan="999">
257
257
  <div class="overflow-hidden transition-opacity" :class="[internalItems[index]?.__expanded ? '' : 'opacity-0 max-h-0']">
258
258
  <slot name="expanded-row" :item="item"></slot>
@@ -3,7 +3,7 @@ import type { TableCellTheme } from '../TableCell.vue'
3
3
  const theme: TableCellTheme = {
4
4
  classes: {
5
5
  wrapper: ({ props }) => {
6
- const c = ['last:pr-0 px-3']
6
+ const c = ['px-3']
7
7
 
8
8
  c.push(props.dense ? 'py-2' : 'py-4')
9
9
 
@@ -2,8 +2,8 @@ import type { TableHeadTheme } from '../TableHead.vue'
2
2
 
3
3
  const theme: TableHeadTheme = {
4
4
  classes: {
5
- thead: 'align-bottom',
6
- row: 'text-sm text-secondary-600 dark:text-secondary-400 border-b',
5
+ thead: 'align-bottom bg-secondary-50 dark:bg-secondary-700',
6
+ row: 'text-sm text-secondary-600 dark:text-secondary-200 border-b',
7
7
  },
8
8
  }
9
9
 
@@ -3,7 +3,7 @@ import type { TableHeaderTheme } from '../TableHeader.vue'
3
3
  const theme: TableHeaderTheme = {
4
4
  classes: {
5
5
  th: ({ props }) => {
6
- const classes = ['relative py-2 font-semibold tracking-widest uppercase text-xs px-3']
6
+ const classes = ['relative py-3 font-semibold text-xs px-3']
7
7
 
8
8
  if (props.sortable) classes.push('cursor-pointer hover:text-secondary-800 dark:hover:text-secondary-300 transition-colors duration-150 ease-in-out')
9
9
 
@@ -18,7 +18,7 @@ const theme: TableHeaderTheme = {
18
18
  },
19
19
 
20
20
  sortIcon: ({ props }) => {
21
- const classes = ['absolute stroke-2 w-3 h-3 top-2.5 right-0.5']
21
+ const classes = ['absolute stroke-2 w-3 h-3 top-3.5 right-0.5']
22
22
 
23
23
  return classes
24
24
  },
@@ -6,7 +6,7 @@ const theme: TableRowTheme = {
6
6
  const classes = []
7
7
 
8
8
  if (props.striped) {
9
- classes.push('odd:bg-secondary-50 dark:odd:bg-secondary-800')
9
+ classes.push('even:bg-secondary-50 dark:even:bg-secondary-700')
10
10
  } else {
11
11
  classes.push('border-b border-secondary-200 dark:border-secondary-700')
12
12
  }
@@ -138,7 +138,7 @@ defineExpose({ focus, blur, reset, validate, setError })
138
138
  :name="name"
139
139
  :placeholder="placeholder"
140
140
  :readonly="readonly"
141
- :value="modelValue ? String(modelValue) : ''"
141
+ :value="typeof modelValue !== 'undefined' ? String(modelValue) : ''"
142
142
  v-on="inputListeners"
143
143
  @keydown.enter="onEnter"
144
144
  @input="onInput"
@@ -11,7 +11,7 @@ const theme: TextareaTheme = {
11
11
  if (!data.errorInternal && !props.disabled) classes.push('hover:border-secondary-400 dark:hover:border-secondary-500')
12
12
 
13
13
  if (props.size === 'xs') classes.push('px-2 py-1 text-xs')
14
- else if (props.size === 'sm') classes.push('px-2 py-2 text-sm')
14
+ else if (props.size === 'sm') classes.push('px-2 py-1.5 text-sm')
15
15
  else if (props.size === 'lg') classes.push('px-4 py-3 text-lg')
16
16
  else if (props.size === 'xl') classes.push('px-5 py-4 text-xl')
17
17
  else classes.push('px-3 py-2')
@@ -64,29 +64,6 @@ export function useFocusTrap() {
64
64
  lastEl?.focus()
65
65
  }
66
66
 
67
- } else if (event.key === 'ArrowUp' || event.key === 'ArrowLeft') {
68
- event.preventDefault()
69
- const currentEl = document.activeElement as HTMLElement
70
- const index = focusable.indexOf(currentEl)
71
- const previousEl = focusable[index - 1]
72
-
73
- if (previousEl) {
74
- previousEl.focus()
75
- } else if (lastFocusableEl) {
76
- lastFocusableEl.focus()
77
- }
78
-
79
- } else if (event.key === 'ArrowDown' || event.key === 'ArrowRight') {
80
- event.preventDefault()
81
- const currentEl = document.activeElement as HTMLElement
82
- const index = focusable.indexOf(currentEl)
83
- const nextElement = focusable[index + 1]
84
-
85
- if (nextElement) {
86
- nextElement.focus()
87
- } else if (firstFocusableEl) {
88
- firstFocusableEl.focus()
89
- }
90
67
  }
91
68
  }
92
69
 
@@ -103,6 +103,7 @@ export const useInputtable = (props: any, { focus, emit, withListeners = true }:
103
103
  input: (event: Event) => {
104
104
  if (props.validateOnInput && !isFirstValidation.value) validate((event.target as HTMLInputElement).value)
105
105
  emit('update:modelValue', (event.target as HTMLInputElement).value)
106
+ emit('input', event)
106
107
  },
107
108
  change: (event: Event) => emit('change', event),
108
109
  }
@@ -152,7 +153,10 @@ useInputtable.emits = (withListeners = true): string[] => {
152
153
  }
153
154
 
154
155
  useInputtable.props = () => ({
155
- modelValue: [String, Number, Boolean, Object, Array] as PropType<string | number | boolean | object | any[] | undefined>,
156
+ modelValue: {
157
+ type: [String, Number, Boolean, Object, Array] as PropType<string | number | boolean | object | any[] | undefined>,
158
+ default: undefined,
159
+ },
156
160
  id: String,
157
161
  name: String,
158
162
  readonly: Boolean,
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export default '1.6.1'
1
+ export default '1.6.3'