sprintify-ui 0.0.93 → 0.0.95

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 (82) hide show
  1. package/dist/sprintify-ui.es.js +15422 -6148
  2. package/dist/style.css +1 -1
  3. package/dist/types/src/components/BaseActionItem.vue.d.ts +25 -102
  4. package/dist/types/src/components/BaseApp.vue.d.ts +8 -47
  5. package/dist/types/src/components/BaseAutocomplete.vue.d.ts +91 -327
  6. package/dist/types/src/components/BaseAutocompleteFetch.vue.d.ts +85 -290
  7. package/dist/types/src/components/BaseBadge.vue.d.ts +27 -110
  8. package/dist/types/src/components/BaseBelongsTo.vue.d.ts +89 -294
  9. package/dist/types/src/components/BaseButtonGroup.vue.d.ts +71 -254
  10. package/dist/types/src/components/BaseCard.vue.d.ts +15 -68
  11. package/dist/types/src/components/BaseClipboard.vue.d.ts +15 -68
  12. package/dist/types/src/components/BaseColor.vue.d.ts +63 -0
  13. package/dist/types/src/components/BaseDataIterator.vue.d.ts +82 -258
  14. package/dist/types/src/components/BaseDataTable.vue.d.ts +158 -509
  15. package/dist/types/src/components/BaseDescriptionList.vue.d.ts +8 -47
  16. package/dist/types/src/components/BaseDescriptionListItem.vue.d.ts +9 -48
  17. package/dist/types/src/components/BaseDialog.vue.d.ts +31 -131
  18. package/dist/types/src/components/BaseDropdown.vue.d.ts +30 -111
  19. package/dist/types/src/components/BaseField.vue.d.ts +31 -124
  20. package/dist/types/src/components/BaseFieldI18n.vue.d.ts +1 -1
  21. package/dist/types/src/components/BaseFileUploader.vue.d.ts +54 -192
  22. package/dist/types/src/components/BaseForm.vue.d.ts +62 -226
  23. package/dist/types/src/components/BaseHasMany.vue.d.ts +66 -219
  24. package/dist/types/src/components/BaseInput.vue.d.ts +10 -1
  25. package/dist/types/src/components/BaseInputError.vue.d.ts +8 -47
  26. package/dist/types/src/components/BaseInputPercent.vue.d.ts +1 -1
  27. package/dist/types/src/components/BaseLayoutSidebar.vue.d.ts +25 -98
  28. package/dist/types/src/components/BaseLayoutSidebarConfigurable.vue.d.ts +39 -155
  29. package/dist/types/src/components/BaseLayoutStacked.vue.d.ts +17 -70
  30. package/dist/types/src/components/BaseLayoutStackedConfigurable.vue.d.ts +39 -155
  31. package/dist/types/src/components/BaseLocaleForm.vue.d.ts +1 -1
  32. package/dist/types/src/components/BaseMediaLibrary.vue.d.ts +63 -234
  33. package/dist/types/src/components/BaseMenu.vue.d.ts +32 -105
  34. package/dist/types/src/components/BaseModalCenter.vue.d.ts +42 -132
  35. package/dist/types/src/components/BaseModalSide.vue.d.ts +29 -118
  36. package/dist/types/src/components/BaseNavbar.vue.d.ts +24 -87
  37. package/dist/types/src/components/BaseNavbarSideItem.vue.d.ts +3 -3
  38. package/dist/types/src/components/BaseRadioGroup.vue.d.ts +53 -194
  39. package/dist/types/src/components/BaseReadMore.vue.d.ts +15 -68
  40. package/dist/types/src/components/BaseRichText.vue.d.ts +92 -0
  41. package/dist/types/src/components/BaseSelect.vue.d.ts +35 -144
  42. package/dist/types/src/components/BaseSideNavigation.vue.d.ts +8 -47
  43. package/dist/types/src/components/BaseSideNavigationItem.vue.d.ts +23 -94
  44. package/dist/types/src/components/BaseSkeleton.vue.d.ts +19 -82
  45. package/dist/types/src/components/BaseSwitch.vue.d.ts +35 -144
  46. package/dist/types/src/components/BaseSystemAlert.vue.d.ts +27 -116
  47. package/dist/types/src/components/BaseTabItem.vue.d.ts +23 -94
  48. package/dist/types/src/components/BaseTable.vue.d.ts +101 -361
  49. package/dist/types/src/components/BaseTableColumn.vue.d.ts +1 -1
  50. package/dist/types/src/components/BaseTabs.vue.d.ts +8 -47
  51. package/dist/types/src/components/BaseTagAutocomplete.vue.d.ts +66 -236
  52. package/dist/types/src/components/BaseTagAutocompleteFetch.vue.d.ts +62 -212
  53. package/dist/types/src/components/index.d.ts +3 -1
  54. package/dist/types/src/composables/clickOutside.d.ts +8 -0
  55. package/dist/types/src/composables/modal.d.ts +1 -1
  56. package/dist/types/src/utils/scrollPreventer.d.ts +1 -2
  57. package/package.json +5 -1
  58. package/src/components/BaseAppDialogs.vue +1 -1
  59. package/src/components/BaseAutocomplete.vue +6 -25
  60. package/src/components/BaseButtonGroup.vue +2 -2
  61. package/src/components/BaseColor.stories.js +50 -0
  62. package/src/components/BaseColor.vue +91 -0
  63. package/src/components/BaseDropdown.stories.js +47 -9
  64. package/src/components/BaseDropdown.vue +27 -35
  65. package/src/components/BaseForm.vue +3 -3
  66. package/src/components/BaseInput.stories.js +52 -0
  67. package/src/components/BaseInput.vue +38 -1
  68. package/src/components/BaseLayoutSidebar.vue +4 -1
  69. package/src/components/BaseModalCenter.stories.js +5 -0
  70. package/src/components/BaseModalCenter.vue +14 -10
  71. package/src/components/BaseModalSide.vue +1 -4
  72. package/src/components/BaseRichText.stories.js +102 -0
  73. package/src/components/BaseRichText.vue +121 -0
  74. package/src/components/BaseSideNavigation.vue +4 -1
  75. package/src/components/BaseTable.vue +1 -0
  76. package/src/components/BaseTabs.vue +4 -1
  77. package/src/components/BaseTagAutocomplete.vue +1 -0
  78. package/src/components/BaseTextarea.vue +1 -1
  79. package/src/components/index.ts +4 -0
  80. package/src/composables/clickOutside.ts +57 -0
  81. package/src/composables/modal.ts +2 -6
  82. package/src/utils/scrollPreventer.ts +3 -13
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sprintify-ui",
3
- "version": "0.0.93",
3
+ "version": "0.0.95",
4
4
  "scripts": {
5
5
  "build": "rimraf dist && vue-tsc && vite build",
6
6
  "build-fast": "rimraf dist && vite build",
@@ -16,11 +16,13 @@
16
16
  "@tailwindcss/forms": "^0.5.3",
17
17
  "@tailwindcss/line-clamp": "^0.4.2",
18
18
  "@tailwindcss/typography": "^0.5.8",
19
+ "@vueup/vue-quill": "^1.0.0",
19
20
  "@vueuse/core": "^9.0.0",
20
21
  "axios": "^0.26.1",
21
22
  "humanize-duration": "^3.0.0",
22
23
  "lodash": "^4.17.21",
23
24
  "luxon": "^3.0.0",
25
+ "maska": "^2.1.1",
24
26
  "microtip": "^0.2.2",
25
27
  "object-to-formdata": "^4.4.2",
26
28
  "pikaday": "^1.8.2",
@@ -58,6 +60,7 @@
58
60
  "@typescript-eslint/parser": "^5.42.1",
59
61
  "@vitejs/plugin-vue": "^3.2.0",
60
62
  "@vue/eslint-config-typescript": "^11.0.2",
63
+ "@vueup/vue-quill": "^1.0.0",
61
64
  "@vueuse/core": "^9.5.0",
62
65
  "autoprefixer": "^10.4.13",
63
66
  "axios": "^0.26.1",
@@ -71,6 +74,7 @@
71
74
  "humanize-duration": "^3.27.3",
72
75
  "lodash": "^4.17.21",
73
76
  "luxon": "^3.1.0",
77
+ "maska": "^2.1.1",
74
78
  "microtip": "^0.2.2",
75
79
  "object-hash": "^3.0.0",
76
80
  "object-to-formdata": "^4.4.2",
@@ -28,7 +28,7 @@
28
28
  <div
29
29
  v-for="dialog in dialogs"
30
30
  :key="dialog.id"
31
- scroll-lock-target
31
+ data-scroll-lock-scrollable
32
32
  class="fixed inset-0 z-dialogs transform overflow-y-auto"
33
33
  >
34
34
  <div
@@ -24,6 +24,7 @@
24
24
  ]"
25
25
  autocomplete="off"
26
26
  :disabled="disabled"
27
+ @click="open"
27
28
  @input="onTextInput"
28
29
  @keydown="onTextKeydown"
29
30
  />
@@ -69,6 +70,7 @@
69
70
  >
70
71
  <div
71
72
  ref="dropdown"
73
+ data-scroll-lock-scrollable
72
74
  class="max-h-[214px] min-h-[75px] w-full overflow-y-auto"
73
75
  >
74
76
  <slot v-if="filteredNormalizedOptions.length == 0" name="empty">
@@ -159,6 +161,7 @@ import BaseSkeleton from '@/components/BaseSkeleton.vue';
159
161
  import { useHasOptions } from '@/composables/hasOptions';
160
162
  import { useField } from '@/composables/field';
161
163
  import { BaseIcon } from './index';
164
+ import { useClickOutside } from '@/composables/clickOutside';
162
165
 
163
166
  const props = defineProps({
164
167
  modelValue: {
@@ -314,33 +317,11 @@ watch(
314
317
  { immediate: true }
315
318
  );
316
319
 
317
- onMounted(() => {
318
- window.addEventListener('mousedown', onMouseDown);
319
- });
320
-
321
- onBeforeMount(() => {
322
- window.removeEventListener('mousedown', onMouseDown);
323
- });
324
-
325
- function onMouseDown(event: MouseEvent) {
326
- if (!autocomplete.value) {
327
- return;
328
- }
329
-
330
- // Get the element that was clicked
331
- const clickedElement = event.target as HTMLElement | null;
332
-
333
- if (!clickedElement) {
334
- return;
335
- }
336
-
337
- // `el` is the element you're detecting clicks outside of
338
- if (autocomplete.value.contains(clickedElement)) {
339
- open();
340
- } else {
320
+ useClickOutside(autocomplete, (outside: boolean) => {
321
+ if (outside) {
341
322
  close();
342
323
  }
343
- }
324
+ });
344
325
 
345
326
  function open() {
346
327
  clearInterval(timerId);
@@ -16,7 +16,7 @@
16
16
  >
17
17
  <slot
18
18
  name="option"
19
- :selected="isSelected(option)"
19
+ :selected="computed(() => isSelected(option))"
20
20
  :option="option"
21
21
  :disabled="disabled"
22
22
  >
@@ -28,7 +28,7 @@
28
28
  </template>
29
29
 
30
30
  <script lang="ts" setup>
31
- import { PropType } from 'vue';
31
+ import { PropType, computed } from 'vue';
32
32
  import { NormalizedOption, Option } from '@/types';
33
33
  import { cloneDeep, isArray } from 'lodash';
34
34
  import { useHasOptions } from '@/composables/hasOptions';
@@ -0,0 +1,50 @@
1
+ import { createFieldStory, colors } from '../../.storybook/utils';
2
+ import BaseColor from './BaseColor.vue';
3
+ import ShowValue from '../../.storybook/components/ShowValue.vue';
4
+
5
+ export default {
6
+ title: 'Form/BaseColor',
7
+ component: BaseColor,
8
+ argTypes: {},
9
+ args: {
10
+ colors: colors,
11
+ },
12
+ decorators: [() => ({ template: '<div class="mb-36"><story/></div>' })],
13
+ };
14
+
15
+ const Template = (args) => ({
16
+ components: { BaseColor, ShowValue },
17
+ setup() {
18
+ const value = ref(null);
19
+ return { args, value };
20
+ },
21
+ template: `
22
+ <BaseColor v-model="value" v-bind="args"></BaseColor>
23
+ <ShowValue :value="value"></ShowValue>
24
+ `,
25
+ });
26
+
27
+ export const Single = Template.bind({});
28
+ Single.args = {};
29
+
30
+ export const SingleRequired = Template.bind({});
31
+ SingleRequired.args = {
32
+ required: true,
33
+ };
34
+
35
+ export const Multiple = Template.bind({});
36
+ Multiple.args = {
37
+ multiple: true,
38
+ };
39
+
40
+ export const Disabled = Template.bind({});
41
+ Disabled.args = {
42
+ disabled: true,
43
+ modelValue: { label: '#16a34a', value: '#16a34a' },
44
+ };
45
+
46
+ export const Field = createFieldStory({
47
+ component: BaseColor,
48
+ componentName: 'BaseColor',
49
+ label: 'Choose your favorite color',
50
+ });
@@ -0,0 +1,91 @@
1
+ <template>
2
+ <div>
3
+ <BaseButtonGroup
4
+ :model-value="modelValue"
5
+ :disabled="disabled"
6
+ value-key="value"
7
+ label-key="label"
8
+ :required="required"
9
+ :options="colorOptions"
10
+ :multiple="multiple"
11
+ :button-type="buttonType"
12
+ :button-class="''"
13
+ :button-selected-class="''"
14
+ :button-unselected-class="''"
15
+ @update:model-value="$emit('update:modelValue', $event)"
16
+ >
17
+ <template #option="option">
18
+ <div
19
+ :style="{ background: option.option.value }"
20
+ class="p-3 border-none rounded-md"
21
+ :class="[
22
+ option.selected.value ? 'text-white' : 'text-transparent',
23
+ disabled ? ' cursor-not-allowed opacity-50' : '',
24
+ ]"
25
+ >
26
+ <BaseIcon icon="heroicons-solid:check-circle" class="w-5 h-5" />
27
+ </div>
28
+ </template>
29
+ </BaseButtonGroup>
30
+ </div>
31
+ </template>
32
+
33
+ <script lang="ts" setup>
34
+ import { PropType } from 'vue';
35
+ import { Option } from '@/types';
36
+ import { BaseButtonGroup } from '.';
37
+
38
+ const props = defineProps({
39
+ modelValue: {
40
+ default: undefined,
41
+ type: [Object, Array, null, undefined] as PropType<
42
+ Option[] | Option | null | undefined
43
+ >,
44
+ },
45
+ required: {
46
+ default: false,
47
+ type: Boolean,
48
+ },
49
+ disabled: {
50
+ default: false,
51
+ type: Boolean,
52
+ },
53
+ buttonType: {
54
+ default: 'button',
55
+ type: String as PropType<'button' | 'submit'>,
56
+ },
57
+ colors: {
58
+ type: [Array] as PropType<string[]>,
59
+ default() {
60
+ return [
61
+ '#0f172a',
62
+ '#dc2626',
63
+ '#ea580c',
64
+ '#eab308',
65
+ '#16a34a',
66
+ '#0d9488',
67
+ '#0891b2',
68
+ '#2563eb',
69
+ '#4f46e5',
70
+ '#9333ea',
71
+ '#db2777',
72
+ ];
73
+ },
74
+ },
75
+ multiple: {
76
+ default: false,
77
+ type: Boolean,
78
+ },
79
+ });
80
+
81
+ defineEmits(['update:modelValue']);
82
+
83
+ const colorOptions = computed(() => {
84
+ return props.colors.map((c) => {
85
+ return {
86
+ label: c,
87
+ value: c,
88
+ };
89
+ });
90
+ });
91
+ </script>
@@ -1,8 +1,17 @@
1
1
  import BaseBadge from './BaseBadge.vue';
2
2
  import BaseAutocomplete from './BaseAutocomplete.vue';
3
+ import BaseModalCenter from './BaseModalCenter.vue';
3
4
  import BaseDropdown from './BaseDropdown.vue';
4
5
  import { options } from '../../.storybook/utils';
5
6
 
7
+ const items = [];
8
+
9
+ for (let i = 0; i < 100; i++) {
10
+ items.push({
11
+ label: `Item ${i + 1}`,
12
+ });
13
+ }
14
+
6
15
  export default {
7
16
  title: 'Components/BaseDropdown',
8
17
  component: BaseDropdown,
@@ -23,7 +32,7 @@ export default {
23
32
  const Template = (args) => ({
24
33
  components: { BaseDropdown },
25
34
  setup() {
26
- return { args };
35
+ return { args, items };
27
36
  },
28
37
  template: `
29
38
  <div style="height: 1000px; margin-top: 300px;">
@@ -33,10 +42,11 @@ const Template = (args) => ({
33
42
  <div class="btn btn-primary">Click me</div>
34
43
  </template>
35
44
  <template #dropdown>
36
- <div class="bg-white shadow py-1 px-1 rounded">
37
- <button type="button" class="block text-sm px-4 py-1.5">Item 1</button>
38
- <button type="button" class="block text-sm px-4 py-1.5">Item 2</button>
39
- <button type="button" class="block text-sm px-4 py-1.5">Item 3</button>
45
+ <div
46
+ class="bg-white shadow py-1 px-1 rounded"
47
+ style="max-height: 200px; overflow: auto;"
48
+ data-scroll-lock-scrollable>
49
+ <button type="button" v-for="item in items" :key="item.label" class="block text-sm px-4 py-1.5">{{ item.label }}</button>
40
50
  </div>
41
51
  </template>
42
52
  </BaseDropdown>
@@ -67,11 +77,11 @@ export const WithAutocomplete = (args) => ({
67
77
  }
68
78
 
69
79
  function onClose() {
70
- if (autocomplete.value) {
71
- setTimeout(() => {
80
+ setTimeout(() => {
81
+ if (autocomplete.value) {
72
82
  autocomplete.value.setKeywords('');
73
- }, 10);
74
- }
83
+ }
84
+ }, 10);
75
85
  }
76
86
 
77
87
  function onUpdate(v, close) {
@@ -113,3 +123,31 @@ WithAutocomplete.args = {
113
123
  placement: 'bottom-start',
114
124
  padding: 3,
115
125
  };
126
+
127
+ export const ModalWithScroll = (args) => ({
128
+ components: { BaseDropdown, BaseModalCenter },
129
+ setup() {
130
+ return { args, items };
131
+ },
132
+ template: `
133
+ <BaseModalCenter :model-value="true">
134
+ <div class="p-10 bg-white">
135
+ <BaseDropdown v-bind="args">
136
+ <template #button>
137
+ <div class="btn btn-primary">Click me</div>
138
+ </template>
139
+ <template #dropdown>
140
+ <div
141
+ class="bg-white shadow py-1 px-1 rounded"
142
+ style="max-height: 200px; overflow: auto;"
143
+ data-scroll-lock-scrollable>
144
+ <button type="button" v-for="item in items" :key="item.label" class="block text-sm px-4 py-1.5">{{ item.label }}</button>
145
+ </div>
146
+ </template>
147
+ </BaseDropdown>
148
+
149
+ <div style="height: 3000px;"></div>
150
+ </div>
151
+ </BaseModalCenter>
152
+ `,
153
+ });
@@ -15,9 +15,10 @@
15
15
  leave-from-class="transform scale-100 opacity-100"
16
16
  leave-to-class="transform scale-90 opacity-0"
17
17
  >
18
- <div v-show="showDropdown" class="inline-block" scroll-lock-target>
18
+ <div v-show="showDropdown" class="inline-block">
19
19
  <slot
20
20
  name="dropdown"
21
+ :show-dropdown="showDropdown"
21
22
  :close="close"
22
23
  :open="open"
23
24
  :toggle="toggle"
@@ -30,6 +31,8 @@
30
31
  </template>
31
32
 
32
33
  <script lang="ts" setup>
34
+ import { useClickOutside } from '@/composables/clickOutside';
35
+ import { throttle } from 'lodash';
33
36
  import { PropType, StyleValue } from 'vue';
34
37
  import { disableScroll, enableScroll } from '../utils';
35
38
 
@@ -96,7 +99,7 @@ function open() {
96
99
  showDropdown.value = true;
97
100
  nextTick(() => {
98
101
  setBoundingBoxes();
99
- disableScroll(dropdown.value);
102
+ disableScroll();
100
103
  emit('open');
101
104
  });
102
105
  }
@@ -108,16 +111,6 @@ function close() {
108
111
  emit('close');
109
112
  }
110
113
 
111
- function activate() {
112
- window.addEventListener('keydown', onKeydown);
113
- window.addEventListener('mousedown', onMouseDown);
114
- }
115
-
116
- function deactivate() {
117
- window.removeEventListener('keydown', onKeydown);
118
- window.removeEventListener('mousedown', onMouseDown);
119
- }
120
-
121
114
  function onKeydown(event: KeyboardEvent) {
122
115
  if (event.code == 'Escape') {
123
116
  if (showDropdown.value) {
@@ -126,33 +119,32 @@ function onKeydown(event: KeyboardEvent) {
126
119
  }
127
120
  }
128
121
 
129
- function onMouseDown(event: MouseEvent) {
130
- if (!dropdown.value) {
131
- return;
132
- }
133
- // Get the element that was clicked
134
- const clickedElement = event.target as HTMLElement | null;
135
-
136
- if (!clickedElement) {
137
- return;
138
- }
122
+ const setBoundingBoxesDebounced = throttle(() => {
123
+ setBoundingBoxes();
124
+ }, 10);
139
125
 
140
- // Button is clicked
141
- if (
142
- button.value == clickedElement ||
143
- button.value?.contains(clickedElement)
144
- ) {
145
- return;
146
- }
126
+ function activate() {
127
+ window.addEventListener('keydown', onKeydown);
128
+ window.addEventListener('resize', setBoundingBoxesDebounced);
129
+ window.addEventListener('scroll', setBoundingBoxesDebounced, true);
130
+ }
147
131
 
148
- // `el` is the element you're detecting clicks outside of
149
- if (dropdown.value.contains(clickedElement)) {
150
- // do nothing..
151
- } else {
152
- close();
153
- }
132
+ function deactivate() {
133
+ window.removeEventListener('resize', setBoundingBoxesDebounced);
134
+ window.removeEventListener('scroll', setBoundingBoxesDebounced, true);
135
+ window.removeEventListener('keydown', onKeydown);
154
136
  }
155
137
 
138
+ useClickOutside(
139
+ dropdown,
140
+ (outside: boolean) => {
141
+ if (outside && showDropdown.value) {
142
+ close();
143
+ }
144
+ },
145
+ { includes: [button] }
146
+ );
147
+
156
148
  const placementInternal = computed(() => {
157
149
  const tooTallForTop =
158
150
  buttonY.value - dropdownHeight.value - props.padding < 0;
@@ -17,14 +17,14 @@
17
17
  >
18
18
  <slot v-if="loading" name="loading">
19
19
  <div
20
- class="absolute inset-0 flex h-full w-full items-center justify-center"
20
+ class="absolute inset-0 flex items-center justify-center w-full h-full"
21
21
  >
22
22
  <div
23
- class="absolute inset-0 h-full w-full opacity-80"
23
+ class="absolute inset-0 w-full h-full opacity-80"
24
24
  :class="loadingMaskClass"
25
25
  />
26
26
  <svg
27
- class="relative h-6 w-6 animate-spin text-blue-600"
27
+ class="relative w-6 h-6 text-blue-600 animate-spin"
28
28
  viewBox="0 0 24 24"
29
29
  >
30
30
  <path
@@ -18,6 +18,20 @@ export default {
18
18
  type: 'text',
19
19
  placeholder: 'Enter your name',
20
20
  },
21
+ argTypes: {
22
+ mask: {
23
+ control: { type: 'select' },
24
+ options: [
25
+ 'phone',
26
+ 'date',
27
+ 'time',
28
+ 'credit-card',
29
+ 'zip-code-canada',
30
+ 'dynamicMask',
31
+ 'customMask',
32
+ ],
33
+ },
34
+ },
21
35
  };
22
36
 
23
37
  const Template = (args) => ({
@@ -92,6 +106,44 @@ Error.args = {
92
106
  iconRight: 'heroicons:currency-dollar',
93
107
  };
94
108
 
109
+ export const PhoneMask = Template.bind({});
110
+ PhoneMask.args = {
111
+ mask: 'phone',
112
+ placeholder: '(250) 555-0199',
113
+ };
114
+
115
+ export const DateMask = Template.bind({});
116
+ DateMask.args = {
117
+ mask: 'date',
118
+ placeholder: 'yyyy-mm-dd',
119
+ };
120
+
121
+ export const TimeMask = Template.bind({});
122
+ TimeMask.args = {
123
+ mask: 'time',
124
+ placeholder: 'hh:mm:ss',
125
+ };
126
+
127
+ export const CreditCard = Template.bind({});
128
+ CreditCard.args = {
129
+ mask: 'credit-card', //4555 5666 6666 6634
130
+ };
131
+
132
+ export const CanadianZipCodeMask = Template.bind({});
133
+ CanadianZipCodeMask.args = {
134
+ mask: 'zip-code-canada', // M5M 4M4
135
+ };
136
+
137
+ export const DynamicMask = Template.bind({});
138
+ DynamicMask.args = {
139
+ mask: ['###.###.###-##', '##.###.###/####-##'],
140
+ };
141
+
142
+ export const CustomMask = Template.bind({});
143
+ CustomMask.args = {
144
+ mask: (value) => (value.startsWith('1') ? '#-#' : '##-##'),
145
+ };
146
+
95
147
  export const Field = createFieldStory({
96
148
  component: BaseInput,
97
149
  componentName: 'BaseInput',
@@ -21,6 +21,7 @@
21
21
  </div>
22
22
  <input
23
23
  ref="input"
24
+ v-maska:[maskOptions]
24
25
  :value="modelValue"
25
26
  :type="type"
26
27
  :name="nameInternal"
@@ -64,10 +65,11 @@
64
65
  </template>
65
66
 
66
67
  <script lang="ts" setup>
67
- import { get, isNumber, isString, trim } from 'lodash';
68
+ import { get, isString } from 'lodash';
68
69
  import { PropType } from 'vue';
69
70
  import { BaseIcon } from '@/index';
70
71
  import { useField } from '@/composables/field';
72
+ import { vMaska } from 'maska';
71
73
 
72
74
  const props = defineProps({
73
75
  modelValue: {
@@ -137,6 +139,41 @@ const props = defineProps({
137
139
  default: undefined,
138
140
  type: Number,
139
141
  },
142
+ mask: {
143
+ type: [String, Array, Function],
144
+ default() {
145
+ return null;
146
+ },
147
+ },
148
+ });
149
+
150
+ const maskOptions = computed(() => {
151
+ if (props.mask) {
152
+ return {
153
+ mask: maskInternal.value,
154
+ };
155
+ }
156
+ return undefined;
157
+ });
158
+
159
+ const maskInternal = computed(() => {
160
+ if (props.mask === 'phone') {
161
+ return '(###) ###-####';
162
+ }
163
+ if (props.mask === 'date') {
164
+ return '####-##-##';
165
+ }
166
+ if (props.mask === 'time') {
167
+ return '##:##:##';
168
+ }
169
+ if (props.mask === 'credit-card') {
170
+ return '#### #### #### ####';
171
+ }
172
+ if (props.mask === 'zip-code-canada') {
173
+ return '@#@ #@#';
174
+ }
175
+
176
+ return props.mask;
140
177
  });
141
178
 
142
179
  const emit = defineEmits(['update:modelValue', 'focus', 'blur']);
@@ -59,7 +59,10 @@
59
59
  <div class="flex flex-shrink-0 items-center px-4">
60
60
  <img class="block h-8 w-auto" :src="logoUrl" :alt="appName" />
61
61
  </div>
62
- <div class="mt-5 h-0 flex-1 overflow-y-auto">
62
+ <div
63
+ data-scroll-lock-scrollable
64
+ class="mt-5 h-0 flex-1 overflow-y-auto"
65
+ >
63
66
  <nav>
64
67
  <slot name="menu" />
65
68
  </nav>
@@ -52,6 +52,11 @@ VerticalAlignTop.args = {
52
52
  verticalAlign: 'top',
53
53
  };
54
54
 
55
+ export const NoCloseButton = Template.bind({});
56
+ NoCloseButton.args = {
57
+ showCloseButton: false,
58
+ };
59
+
55
60
  export const CustomBackdropClass = Template.bind({});
56
61
  CustomBackdropClass.args = {
57
62
  backdropClass: 'bg-red-500 bg-opacity-70',
@@ -7,16 +7,18 @@
7
7
  >
8
8
  <div v-show="modelValue">
9
9
  <div
10
- ref="allow"
10
+ data-scroll-lock-scrollable
11
11
  class="fixed inset-0 z-modal w-full overflow-y-auto overflow-x-hidden"
12
- scroll-lock-target
13
12
  >
14
13
  <div
15
- class="flex min-h-full w-full items-end justify-center overflow-hidden pt-20 sm:px-6 sm:pb-6 sm:pt-20"
16
- :class="{
17
- 'sm:items-center': verticalAlign == 'center',
18
- 'sm:items-start': verticalAlign == 'top',
19
- }"
14
+ class="flex min-h-full w-full items-end justify-center overflow-hidden sm:px-6 sm:pb-6"
15
+ :class="[
16
+ showCloseButton ? 'pt-20' : 'pt-6',
17
+ {
18
+ 'sm:items-center': verticalAlign == 'center',
19
+ 'sm:items-start': verticalAlign == 'top',
20
+ },
21
+ ]"
20
22
  >
21
23
  <div class="pt-safe grow">
22
24
  <transition
@@ -64,6 +66,7 @@
64
66
  </div>
65
67
 
66
68
  <button
69
+ v-if="showCloseButton"
67
70
  class="right fixed top-2 right-2 flex h-16 w-16 items-center justify-center rounded-full hover:bg-black hover:bg-opacity-20"
68
71
  type="button"
69
72
  @click="modal.close()"
@@ -100,15 +103,16 @@ const props = defineProps({
100
103
  default: '512px',
101
104
  type: String,
102
105
  },
106
+ showCloseButton: {
107
+ default: true,
108
+ type: Boolean,
109
+ },
103
110
  });
104
111
 
105
112
  const emit = defineEmits(['update:modelValue']);
106
113
 
107
- const allow = ref(null);
108
-
109
114
  const modal = useModal(
110
115
  computed(() => props.modelValue),
111
- allow,
112
116
  emit as any
113
117
  );
114
118
  </script>