sprintify-ui 0.6.77 → 0.6.80

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.
@@ -28,6 +28,7 @@ import BaseCropperModal from './BaseCropperModal.vue';
28
28
  import BaseDataIterator from './BaseDataIterator.vue';
29
29
  import BaseDataTable from './BaseDataTable.vue';
30
30
  import BaseDatePicker from './BaseDatePicker.vue';
31
+ import BaseTimePicker from './BaseTimePicker.vue';
31
32
  import BaseDateSelect from './BaseDateSelect.vue';
32
33
  import BaseDescriptionList from './BaseDescriptionList.vue';
33
34
  import BaseDescriptionListItem from './BaseDescriptionListItem.vue';
@@ -100,4 +101,4 @@ import BaseLayoutStacked from './BaseLayoutStacked.vue';
100
101
  import BaseLayoutStackedConfigurable from './BaseLayoutStackedConfigurable.vue';
101
102
  import BaseLayoutSidebar from './BaseLayoutSidebar.vue';
102
103
  import BaseLayoutSidebarConfigurable from './BaseLayoutSidebarConfigurable.vue';
103
- export { BaseActionItem, BaseAddressForm, BaseAlert, BaseApp, BaseAppDialogs, BaseAppNotifications, BaseAutocomplete, BaseAutocompleteFetch, BaseAvatar, BaseAvatarGroup, BaseBadge, BaseBelongsTo, BaseBelongsToFetch, BaseBoolean, BaseBreadcrumbs, BaseButton, BaseButtonGroup, BaseCard, BaseCardRow, BaseCharacterCounter, BaseClipboard, BaseCalendar, BaseColor, BaseContainer, BaseCounter, BaseCropper, BaseCropperModal, BaseDataIterator, BaseDataTable, BaseDatePicker, BaseDateSelect, BaseDescriptionList, BaseDescriptionListItem, BaseDialog, BaseDisplayRelativeTime, BaseDropdown, BaseDropdownAutocomplete, BaseEmptyState, BaseField, BaseFieldI18n, BaseFilePicker, BaseFilePickerCrop, BaseFileUploader, BaseForm, BaseGantt, BaseHasMany, BaseHeader, BaseIcon, BaseIconPicker, BaseInput, BaseInputLabel, BaseInputPercent, BaseLoadingCover, BaseMediaItem, BaseMediaLibrary, BaseMediaPreview, BaseMenu, BaseMenuItem, BaseModalCenter, BaseModalSide, BaseNavbar, BaseNavbarItem, BaseNavbarItemContent, BaseNavbarSideItem, BasePagination, BasePanel, BasePassword, BaseProgressCircle, BaseRadioGroup, BaseReadMore, BaseRichText, BaseSelect, BaseShortcut, BaseSideNavigation, BaseSideNavigationItem, BaseSkeleton, BaseStatistic, BaseStepper, BaseStepperItem, BaseSwitch, BaseSystemAlert, BaseTable, BaseTableBody, BaseTableCell, BaseTableHead, BaseTableHeader, BaseTableRow, BaseTabs, BaseTabItem, BaseTagAutocomplete, BaseTagAutocompleteFetch, BaseTableColumn, BaseTextarea, BaseTextareaAutoresize, BaseTimeline, BaseTimelineItem, BaseTooltip, BaseUniqueCode, BaseLayoutStacked, BaseLayoutStackedConfigurable, BaseLayoutSidebar, BaseLayoutSidebarConfigurable, };
104
+ export { BaseActionItem, BaseAddressForm, BaseAlert, BaseApp, BaseAppDialogs, BaseAppNotifications, BaseAutocomplete, BaseAutocompleteFetch, BaseAvatar, BaseAvatarGroup, BaseBadge, BaseBelongsTo, BaseBelongsToFetch, BaseBoolean, BaseBreadcrumbs, BaseButton, BaseButtonGroup, BaseCard, BaseCardRow, BaseCharacterCounter, BaseClipboard, BaseCalendar, BaseColor, BaseContainer, BaseCounter, BaseCropper, BaseCropperModal, BaseDataIterator, BaseDataTable, BaseDatePicker, BaseTimePicker, BaseDateSelect, BaseDescriptionList, BaseDescriptionListItem, BaseDialog, BaseDisplayRelativeTime, BaseDropdown, BaseDropdownAutocomplete, BaseEmptyState, BaseField, BaseFieldI18n, BaseFilePicker, BaseFilePickerCrop, BaseFileUploader, BaseForm, BaseGantt, BaseHasMany, BaseHeader, BaseIcon, BaseIconPicker, BaseInput, BaseInputLabel, BaseInputPercent, BaseLoadingCover, BaseMediaItem, BaseMediaLibrary, BaseMediaPreview, BaseMenu, BaseMenuItem, BaseModalCenter, BaseModalSide, BaseNavbar, BaseNavbarItem, BaseNavbarItemContent, BaseNavbarSideItem, BasePagination, BasePanel, BasePassword, BaseProgressCircle, BaseRadioGroup, BaseReadMore, BaseRichText, BaseSelect, BaseShortcut, BaseSideNavigation, BaseSideNavigationItem, BaseSkeleton, BaseStatistic, BaseStepper, BaseStepperItem, BaseSwitch, BaseSystemAlert, BaseTable, BaseTableBody, BaseTableCell, BaseTableHead, BaseTableHeader, BaseTableRow, BaseTabs, BaseTabItem, BaseTagAutocomplete, BaseTagAutocompleteFetch, BaseTableColumn, BaseTextarea, BaseTextareaAutoresize, BaseTimeline, BaseTimelineItem, BaseTooltip, BaseUniqueCode, BaseLayoutStacked, BaseLayoutStackedConfigurable, BaseLayoutSidebar, BaseLayoutSidebarConfigurable, };
@@ -15,6 +15,7 @@ declare const messages: {
15
15
  month: string;
16
16
  save: string;
17
17
  sui: {
18
+ notes: string;
18
19
  address: string;
19
20
  address_1_placeholder: string;
20
21
  address_2_description: string;
@@ -28,6 +29,7 @@ declare const messages: {
28
29
  city: string;
29
30
  clear: string;
30
31
  click_or_select_date: string;
32
+ click_or_select_time: string;
31
33
  click_to_copy: string;
32
34
  columns: string;
33
35
  confirm: string;
@@ -58,7 +60,9 @@ declare const messages: {
58
60
  none: string;
59
61
  nothing_found: string;
60
62
  notifications_empty: string;
63
+ now: string;
61
64
  of: string;
65
+ ok: string;
62
66
  or: string;
63
67
  page: string;
64
68
  pagination_detail_1: string;
@@ -110,6 +114,7 @@ declare const messages: {
110
114
  month: string;
111
115
  save: string;
112
116
  sui: {
117
+ notes: string;
113
118
  address: string;
114
119
  address_1_placeholder: string;
115
120
  address_2_description: string;
@@ -123,6 +128,7 @@ declare const messages: {
123
128
  city: string;
124
129
  clear: string;
125
130
  click_or_select_date: string;
131
+ click_or_select_time: string;
126
132
  click_to_copy: string;
127
133
  columns: string;
128
134
  confirm: string;
@@ -153,7 +159,9 @@ declare const messages: {
153
159
  none: string;
154
160
  nothing_found: string;
155
161
  notifications_empty: string;
162
+ now: string;
156
163
  of: string;
164
+ ok: string;
157
165
  or: string;
158
166
  page: string;
159
167
  pagination_detail_1: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sprintify-ui",
3
- "version": "0.6.77",
3
+ "version": "0.6.80",
4
4
  "scripts": {
5
5
  "build": "rimraf dist && vue-tsc && vite build",
6
6
  "build-fast": "rimraf dist && vite build",
@@ -0,0 +1,10 @@
1
+ .base-time-picker {
2
+ .overflow-y-auto {
3
+ scrollbar-width: thin;
4
+ scrollbar-color: transparent transparent;
5
+ scroll-behavior: smooth;
6
+ }
7
+ .overflow-y-auto:hover {
8
+ scrollbar-color: #ccc white;
9
+ }
10
+ }
@@ -1,6 +1,7 @@
1
1
  @import "./base-calendar.css";
2
2
  @import "./base-cropper.css";
3
3
  @import "./base-date-picker.css";
4
+ @import "./base-time-picker.css";
4
5
  @import "./base-rich-text.css";
5
6
  @import "./base-table.css";
6
7
  @import "./base-tabs.css";
@@ -103,6 +103,21 @@
103
103
  @update:model-value="update('region', $event)"
104
104
  />
105
105
  </BaseField>
106
+
107
+ <BaseField
108
+ v-if="props.showNotes"
109
+ :label="t('sui.notes')"
110
+ :name="`${namePrefix}notes`"
111
+ :required="isRequired('notes')"
112
+ class="col-span-2"
113
+ :size="size"
114
+ >
115
+ <BaseTextarea
116
+ :model-value="normalizedModelValue.notes ?? ''"
117
+ class="w-full"
118
+ @update:model-value="update('notes', $event)"
119
+ />
120
+ </BaseField>
106
121
  </div>
107
122
  </template>
108
123
 
@@ -114,6 +129,7 @@ import { Region } from '@/types/Region';
114
129
  import BaseField from './BaseField.vue';
115
130
  import BaseInput from './BaseInput.vue';
116
131
  import BaseSelect from './BaseSelect.vue';
132
+ import BaseTextarea from './BaseTextarea.vue';
117
133
  import { t } from '@/i18n';
118
134
  import { config } from '..';
119
135
  import { Size } from '@/utils/sizes';
@@ -128,6 +144,7 @@ type Address = {
128
144
  city?: string | null;
129
145
  region?: string | null;
130
146
  country?: string | null;
147
+ notes?: string | null;
131
148
  };
132
149
 
133
150
  const props = withDefaults(
@@ -141,6 +158,7 @@ const props = withDefaults(
141
158
  size?: Size;
142
159
  hideRegion?: boolean;
143
160
  hideCountry?: boolean;
161
+ showNotes?: boolean;
144
162
  requiredFields?: (keyof Address)[];
145
163
  }>(),
146
164
  {
@@ -158,6 +176,7 @@ const props = withDefaults(
158
176
  size: undefined,
159
177
  hideRegion: false,
160
178
  hideCountry: false,
179
+ showNotes: false,
161
180
  requiredFields() {
162
181
  return ['address_1', 'city', 'postal_code', 'country', 'region'];
163
182
  }
@@ -176,6 +195,7 @@ const normalizedModelValue = computed((): Address => {
176
195
  form.postal_code = form.postal_code ?? '';
177
196
  form.country = form.country ?? '';
178
197
  form.region = form.region ?? '';
198
+ form.notes = form.notes ?? '';
179
199
  return form;
180
200
  });
181
201
 
@@ -57,6 +57,8 @@ import BaseActionItem from './BaseActionItem.vue';
57
57
  import BaseNavbarSideItemContent from './BaseNavbarSideItemContent.vue';
58
58
  import BaseCounter from './BaseCounter.vue';
59
59
 
60
+ const router = useRouter();
61
+
60
62
  const props = defineProps({
61
63
  item: {
62
64
  required: true,
@@ -83,9 +85,11 @@ const routeActive = computed((): boolean => {
83
85
  return false;
84
86
  }
85
87
 
86
- const link = useLink({ to: props.item.to });
88
+ const itemRoute = router.resolve(props.item.to);
87
89
 
88
- return link.isActive.value;
90
+ return router.currentRoute.value.matched.some((route) => {
91
+ return route.path.startsWith(itemRoute.path);
92
+ });
89
93
  });
90
94
 
91
95
  const showSubActions = computed((): boolean => {
@@ -0,0 +1,130 @@
1
+ <template>
2
+ <div
3
+ v-for="time in times"
4
+ :key="time"
5
+ :ref="element"
6
+ class="cursor-pointer py-1 text-center rounded content"
7
+ :class="{ 'bg-slate-100': hoveredIndex === `${type}-${time}`, 'bg-primary-100': selectedValue === `${type}-${time}` }"
8
+ @mouseenter="hoveredIndex = `${type}-${time}`"
9
+ @mouseleave="hoveredIndex = null"
10
+ @click="selectTime(`${type}-${time}`, type, time)"
11
+ >
12
+ {{ time }}
13
+ </div>
14
+ </template>
15
+
16
+ <script lang="ts" setup>
17
+ import { PropType } from 'vue';
18
+
19
+ const props = defineProps({
20
+ value: {
21
+ default: undefined,
22
+ type: [String, null, undefined] as PropType<string | null | undefined>,
23
+ },
24
+ type: {
25
+ default: 'hour',
26
+ type: String,
27
+ },
28
+ element: {
29
+ type: String,
30
+ required: true,
31
+ },
32
+ container: {
33
+ type: [HTMLElement, null] as PropType<HTMLElement | null>,
34
+ required: true,
35
+ },
36
+ times: {
37
+ default: () => Array.from({ length: 24 }, (_, i) => i.toString().padStart(2, '0')),
38
+ type: Array as PropType<string[]>,
39
+ },
40
+ });
41
+
42
+ const emit = defineEmits(['selectTime']);
43
+
44
+ const hoveredIndex = ref('' as string | null);
45
+ const selectedValue = ref('' as string | null);
46
+ const timeValue = ref('' as string | null);
47
+
48
+ const hourElements = ref<Array<HTMLElement | null>>([]);
49
+ const minuteElements = ref<Array<HTMLElement | null>>([]);
50
+ const secondElements = ref<Array<HTMLElement | null>>([]);
51
+
52
+ const selectTime = async (value: string, type: string, time: string) => {
53
+ selectedValue.value = value;
54
+
55
+ timeValue.value = time;
56
+
57
+ let element = [] as (HTMLElement | null)[];
58
+
59
+ if (props.type === 'hour') {
60
+ element = hourElements.value;
61
+ }
62
+ if (props.type === 'minute') {
63
+ element = minuteElements.value;
64
+ }
65
+ if (props.type === 'second') {
66
+ element = secondElements.value;
67
+ }
68
+
69
+ scrollToSelectedValue(props.container, element);
70
+
71
+ emit('selectTime', timeValue.value, type);
72
+ };
73
+
74
+ const scrollToSelectedValue = (
75
+ timeContainer: HTMLElement | null,
76
+ timeElement: (HTMLElement | null)[],
77
+ behavior: 'auto' | 'instant' | 'smooth' | undefined = 'smooth'
78
+ ) => {
79
+
80
+ console.log('timeContainer', timeContainer, 'timeValue', timeValue.value);
81
+
82
+ if (!timeContainer || !timeValue.value) {
83
+ return;
84
+ }
85
+
86
+ const selectedIndex = props.times.indexOf(timeValue.value);
87
+
88
+ const targetElement = timeElement[selectedIndex];
89
+
90
+ if (targetElement) {
91
+ const containerHeight = timeContainer.clientHeight;
92
+ const elementHeight = targetElement.clientHeight;
93
+ const offsetTop = targetElement.offsetTop;
94
+ const scrollTop = (offsetTop - (containerHeight - elementHeight) / 2);
95
+
96
+ timeContainer.scrollTo({ top: scrollTop, behavior: behavior as any });
97
+ }
98
+ };
99
+
100
+ watch(
101
+ () => props.container,
102
+ () => {
103
+ if (props.value) {
104
+ const [hour, minute, second] = props.value.split(':');
105
+
106
+ let element = [] as (HTMLElement | null)[];
107
+ if (props.type === 'hour') {
108
+ timeValue.value = hour;
109
+ selectedValue.value = `hour-${hour}`;
110
+ element = hourElements.value;
111
+ }
112
+ if (props.type === 'minute') {
113
+ timeValue.value = minute;
114
+ selectedValue.value = `minute-${minute}`;
115
+ element = minuteElements.value;
116
+ }
117
+ if (props.type === 'second') {
118
+ timeValue.value = second;
119
+ selectedValue.value = `second-${second}`;
120
+ element = secondElements.value;
121
+ }
122
+
123
+ scrollToSelectedValue(props.container, element, 'instant');
124
+ }
125
+
126
+ },
127
+ { immediate: true }
128
+ );
129
+
130
+ </script>
@@ -0,0 +1,71 @@
1
+ import { createFieldStory } from '../../.storybook/utils';
2
+ import BaseTimePicker from './BaseTimePicker.vue';
3
+ import ShowValue from '@/../.storybook/components/ShowValue.vue';
4
+
5
+ const sizes = ['xs', 'sm', 'md'];
6
+
7
+ export default {
8
+ title: 'Form/BaseTimePicker',
9
+ component: BaseTimePicker,
10
+ argTypes: {
11
+ size: {
12
+ control: { type: 'select' },
13
+ options: sizes,
14
+ }
15
+ },
16
+ };
17
+
18
+ const Template = (args) => ({
19
+ components: { BaseTimePicker, ShowValue },
20
+ setup() {
21
+ const value = ref(null);
22
+ return { value, args };
23
+ },
24
+ template: `
25
+ <BaseTimePicker v-model="value" v-bind="args">
26
+ </BaseTimePicker>
27
+ <ShowValue :value="value" />
28
+ `,
29
+ });
30
+
31
+ export const Demo = Template.bind({});
32
+
33
+ export const Disabled = Template.bind({});
34
+ Disabled.args = {
35
+ disabled: true,
36
+ };
37
+
38
+ export const DisabledSeconds = Template.bind({});
39
+ DisabledSeconds.args = {
40
+ disabledSeconds: true,
41
+ };
42
+
43
+ export const WithSteps = Template.bind({});
44
+ WithSteps.args = {
45
+ hourStep: 3,
46
+ minuteStep: 15,
47
+ secondStep: 10,
48
+ };
49
+
50
+ const TemplateSizes = (args) => ({
51
+ components: { BaseTimePicker },
52
+ setup() {
53
+ const value = ref(null);
54
+ const sizes = ['xs', 'sm', 'md'];
55
+ return { args, value, sizes };
56
+ },
57
+ template: `
58
+ <div v-for="size in sizes" :key="size" class="mb-4">
59
+ <p class="text-xs text-slate-600 leading-tight mb-1">{{ size }}</p>
60
+ <BaseTimePicker v-model="value" v-bind="args" :size="size" class="w-full"></BaseTimePicker>
61
+ </div>
62
+ `,
63
+ });
64
+
65
+ export const Sizes = TemplateSizes.bind({});
66
+
67
+ export const Field = createFieldStory({
68
+ component: BaseTimePicker,
69
+ componentName: 'BaseTimePicker',
70
+ label: 'Time',
71
+ });