@privyid/persona 1.0.0-rc.1 → 1.0.0-rc.2
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.
- package/dist/components/datepicker/Datepicker.vue +36 -13
- package/dist/components/dropdown/Dropdown.vue +6 -1
- package/dist/components/filterbar/pinned/PinnedSelect.vue.d.ts +2 -2
- package/dist/components/filterbar/pinned/PinnedToggle.vue.d.ts +7 -7
- package/dist/components/meta.json +7 -4
- package/dist/components/select/Select.vue +21 -1
- package/dist/components/time/Time.vue +257 -0
- package/dist/components/time/TimeItem.vue +117 -0
- package/dist/components/time/index.d.ts +19 -0
- package/dist/components/time/index.mjs +53 -0
- package/dist/components/time/utils/index.d.ts +9 -0
- package/dist/components/time/utils/index.mjs +82 -0
- package/dist/components/timepicker/Timepicker.vue +230 -0
- package/dist/module.json +1 -1
- package/package.json +12 -12
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
:disabled="disabled">
|
|
9
9
|
<template #activator>
|
|
10
10
|
<Input
|
|
11
|
+
v-bind="$attrs"
|
|
11
12
|
:value="value"
|
|
12
13
|
:model-value="value"
|
|
13
14
|
data-testid="datepicker-input"
|
|
@@ -16,7 +17,10 @@
|
|
|
16
17
|
:disabled="disabled"
|
|
17
18
|
:error="error"
|
|
18
19
|
:size="size"
|
|
20
|
+
:clearable="clearable"
|
|
21
|
+
:container-class="containerClass"
|
|
19
22
|
readonly
|
|
23
|
+
@clear="onClear"
|
|
20
24
|
@focus="onFocus">
|
|
21
25
|
<template #append>
|
|
22
26
|
<IconCalendar
|
|
@@ -27,6 +31,7 @@
|
|
|
27
31
|
|
|
28
32
|
<Calendar
|
|
29
33
|
v-model="model"
|
|
34
|
+
class="datepicker__calendar"
|
|
30
35
|
:start="start"
|
|
31
36
|
:end="end"
|
|
32
37
|
:disabled="disabled"
|
|
@@ -37,7 +42,6 @@
|
|
|
37
42
|
:range="range"
|
|
38
43
|
:min-range="minRange"
|
|
39
44
|
:max-range="maxRange"
|
|
40
|
-
class="datepicker__calendar"
|
|
41
45
|
@change="onSelected"
|
|
42
46
|
@update:start="$emit('update:start', $event)"
|
|
43
47
|
@update:end="$emit('update:end', $event)" />
|
|
@@ -60,6 +64,8 @@ import { useVModel } from '../input'
|
|
|
60
64
|
import IconCalendar from '@privyid/persona-icon/vue/calendar/16.vue'
|
|
61
65
|
import type { SizeVariant } from '../button'
|
|
62
66
|
|
|
67
|
+
defineOptions({ inheritAttrs: false })
|
|
68
|
+
|
|
63
69
|
const props = defineProps({
|
|
64
70
|
modelValue: {
|
|
65
71
|
type : [Date, Array] as PropType<Date | [Date, Date]>,
|
|
@@ -69,6 +75,30 @@ const props = defineProps({
|
|
|
69
75
|
type : String as PropType<SizeVariant>,
|
|
70
76
|
default: 'md',
|
|
71
77
|
},
|
|
78
|
+
disabled: {
|
|
79
|
+
type : Boolean,
|
|
80
|
+
default: false,
|
|
81
|
+
},
|
|
82
|
+
readonly: {
|
|
83
|
+
type : Boolean,
|
|
84
|
+
default: false,
|
|
85
|
+
},
|
|
86
|
+
error: {
|
|
87
|
+
type : Boolean,
|
|
88
|
+
default: false,
|
|
89
|
+
},
|
|
90
|
+
clearable: {
|
|
91
|
+
type : Boolean,
|
|
92
|
+
default: false,
|
|
93
|
+
},
|
|
94
|
+
containerClass: {
|
|
95
|
+
type: [
|
|
96
|
+
String,
|
|
97
|
+
Array,
|
|
98
|
+
Object,
|
|
99
|
+
],
|
|
100
|
+
default: undefined,
|
|
101
|
+
},
|
|
72
102
|
start: {
|
|
73
103
|
type : Date,
|
|
74
104
|
default: undefined,
|
|
@@ -85,18 +115,6 @@ const props = defineProps({
|
|
|
85
115
|
type : String,
|
|
86
116
|
default: 'dd/MM/yyyy',
|
|
87
117
|
},
|
|
88
|
-
disabled: {
|
|
89
|
-
type : Boolean,
|
|
90
|
-
default: undefined,
|
|
91
|
-
},
|
|
92
|
-
readonly: {
|
|
93
|
-
type : Boolean,
|
|
94
|
-
default: undefined,
|
|
95
|
-
},
|
|
96
|
-
error: {
|
|
97
|
-
type : Boolean,
|
|
98
|
-
default: undefined,
|
|
99
|
-
},
|
|
100
118
|
max: {
|
|
101
119
|
type : Date,
|
|
102
120
|
default: undefined,
|
|
@@ -178,6 +196,11 @@ function onFocus () {
|
|
|
178
196
|
isOpen.value = true
|
|
179
197
|
}
|
|
180
198
|
|
|
199
|
+
function onClear () {
|
|
200
|
+
if (!props.disabled && !props.readonly)
|
|
201
|
+
model.value = undefined
|
|
202
|
+
}
|
|
203
|
+
|
|
181
204
|
function onSelected (event: Event) {
|
|
182
205
|
isOpen.value = false
|
|
183
206
|
|
|
@@ -197,7 +197,12 @@ defineEmits<{
|
|
|
197
197
|
}>()
|
|
198
198
|
|
|
199
199
|
const slots = defineSlots<{
|
|
200
|
-
'activator'(props: {
|
|
200
|
+
'activator'(props: {
|
|
201
|
+
isOpen: boolean,
|
|
202
|
+
open: () => void,
|
|
203
|
+
close: () => void,
|
|
204
|
+
toggle: () => void,
|
|
205
|
+
}): VNode[],
|
|
201
206
|
'button-content'(): VNode[],
|
|
202
207
|
'prepend'(): VNode[],
|
|
203
208
|
'append'(): VNode[],
|
|
@@ -11,7 +11,7 @@ declare const _default: import("vue-demi").DefineComponent<{
|
|
|
11
11
|
default: () => never[];
|
|
12
12
|
};
|
|
13
13
|
modelValue: {
|
|
14
|
-
type: (
|
|
14
|
+
type: (NumberConstructor | BooleanConstructor | ArrayConstructor | ObjectConstructor | DateConstructor | StringConstructor)[];
|
|
15
15
|
default: undefined;
|
|
16
16
|
};
|
|
17
17
|
}, {
|
|
@@ -30,7 +30,7 @@ declare const _default: import("vue-demi").DefineComponent<{
|
|
|
30
30
|
default: () => never[];
|
|
31
31
|
};
|
|
32
32
|
modelValue: {
|
|
33
|
-
type: (
|
|
33
|
+
type: (NumberConstructor | BooleanConstructor | ArrayConstructor | ObjectConstructor | DateConstructor | StringConstructor)[];
|
|
34
34
|
default: undefined;
|
|
35
35
|
};
|
|
36
36
|
}>> & {
|
|
@@ -6,15 +6,15 @@ declare const _default: import("vue-demi").DefineComponent<{
|
|
|
6
6
|
required: true;
|
|
7
7
|
};
|
|
8
8
|
modelValue: {
|
|
9
|
-
type: (
|
|
9
|
+
type: (NumberConstructor | BooleanConstructor | ArrayConstructor | ObjectConstructor | DateConstructor | StringConstructor)[];
|
|
10
10
|
default: boolean;
|
|
11
11
|
};
|
|
12
12
|
value: {
|
|
13
|
-
type: (
|
|
13
|
+
type: (NumberConstructor | BooleanConstructor | ArrayConstructor | ObjectConstructor | DateConstructor | StringConstructor)[];
|
|
14
14
|
default: boolean;
|
|
15
15
|
};
|
|
16
16
|
uncheckedValue: {
|
|
17
|
-
type: (
|
|
17
|
+
type: (NumberConstructor | BooleanConstructor | ArrayConstructor | ObjectConstructor | DateConstructor | StringConstructor)[];
|
|
18
18
|
default: boolean;
|
|
19
19
|
};
|
|
20
20
|
checked: {
|
|
@@ -30,15 +30,15 @@ declare const _default: import("vue-demi").DefineComponent<{
|
|
|
30
30
|
required: true;
|
|
31
31
|
};
|
|
32
32
|
modelValue: {
|
|
33
|
-
type: (
|
|
33
|
+
type: (NumberConstructor | BooleanConstructor | ArrayConstructor | ObjectConstructor | DateConstructor | StringConstructor)[];
|
|
34
34
|
default: boolean;
|
|
35
35
|
};
|
|
36
36
|
value: {
|
|
37
|
-
type: (
|
|
37
|
+
type: (NumberConstructor | BooleanConstructor | ArrayConstructor | ObjectConstructor | DateConstructor | StringConstructor)[];
|
|
38
38
|
default: boolean;
|
|
39
39
|
};
|
|
40
40
|
uncheckedValue: {
|
|
41
|
-
type: (
|
|
41
|
+
type: (NumberConstructor | BooleanConstructor | ArrayConstructor | ObjectConstructor | DateConstructor | StringConstructor)[];
|
|
42
42
|
default: boolean;
|
|
43
43
|
};
|
|
44
44
|
checked: {
|
|
@@ -49,8 +49,8 @@ declare const _default: import("vue-demi").DefineComponent<{
|
|
|
49
49
|
"onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
|
|
50
50
|
onChange?: ((...args: any[]) => any) | undefined;
|
|
51
51
|
}, {
|
|
52
|
-
modelValue: string | number | boolean | Record<string, any> | unknown[] | Date;
|
|
53
52
|
value: string | number | boolean | Record<string, any> | unknown[] | Date;
|
|
53
|
+
modelValue: string | number | boolean | Record<string, any> | unknown[] | Date;
|
|
54
54
|
checked: boolean;
|
|
55
55
|
uncheckedValue: string | number | boolean | Record<string, any> | unknown[] | Date;
|
|
56
56
|
}, {}>;
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
"PCollapse": "components/collapse/Collapse.vue",
|
|
26
26
|
"PContextualBar": "components/contextual-bar/ContextualBar.vue",
|
|
27
27
|
"PCropper": "components/cropper/Cropper.vue",
|
|
28
|
+
"PDatepicker": "components/datepicker/Datepicker.vue",
|
|
28
29
|
"PDialog": "components/dialog/Dialog.vue",
|
|
29
30
|
"PDialogFooter": "components/dialog/DialogFooter.vue",
|
|
30
|
-
"PDatepicker": "components/datepicker/Datepicker.vue",
|
|
31
31
|
"PDivider": "components/divider/Divider.vue",
|
|
32
32
|
"PDot": "components/dot/Dot.vue",
|
|
33
33
|
"PDropdown": "components/dropdown/Dropdown.vue",
|
|
@@ -74,16 +74,16 @@
|
|
|
74
74
|
"PPdfObjectAddon": "components/pdf-object/PdfObjectAddon.vue",
|
|
75
75
|
"PPdfObjectDebugger": "components/pdf-object/PdfObjectDebugger.vue",
|
|
76
76
|
"PPdfObjects": "components/pdf-object/PdfObjects.vue",
|
|
77
|
+
"PPdfText": "components/pdf-text/PdfText.vue",
|
|
77
78
|
"PPdfError": "components/pdf-viewer/PdfError.vue",
|
|
78
79
|
"PPdfLoading": "components/pdf-viewer/PdfLoading.vue",
|
|
79
80
|
"PPdfNavigation": "components/pdf-viewer/PdfNavigation.vue",
|
|
80
81
|
"PPdfViewer": "components/pdf-viewer/PdfViewer.vue",
|
|
81
|
-
"PPdfText": "components/pdf-text/PdfText.vue",
|
|
82
82
|
"PPopover": "components/popover/Popover.vue",
|
|
83
83
|
"PPopup": "components/popup/Popup.vue",
|
|
84
|
-
"PProgressIndicator": "components/progress-indicator/ProgressIndicator.vue",
|
|
85
84
|
"PProgress": "components/progress/Progress.vue",
|
|
86
85
|
"PProgressItem": "components/progress/ProgressItem.vue",
|
|
86
|
+
"PProgressIndicator": "components/progress-indicator/ProgressIndicator.vue",
|
|
87
87
|
"PProgressbar": "components/progressbar/Progressbar.vue",
|
|
88
88
|
"PRadio": "components/radio/Radio.vue",
|
|
89
89
|
"PRingbar": "components/ringbar/Ringbar.vue",
|
|
@@ -118,8 +118,11 @@
|
|
|
118
118
|
"PTab": "components/tabs/Tab.vue",
|
|
119
119
|
"PTabContent": "components/tabs/TabContent.vue",
|
|
120
120
|
"PTabs": "components/tabs/Tabs.vue",
|
|
121
|
-
"PTextarea": "components/textarea/Textarea.vue",
|
|
122
121
|
"PText": "components/text/Text.vue",
|
|
122
|
+
"PTextarea": "components/textarea/Textarea.vue",
|
|
123
|
+
"PTime": "components/time/Time.vue",
|
|
124
|
+
"PTimeItem": "components/time/TimeItem.vue",
|
|
125
|
+
"PTimepicker": "components/timepicker/Timepicker.vue",
|
|
123
126
|
"PToast": "components/toast/Toast.vue",
|
|
124
127
|
"PToggle": "components/toggle/Toggle.vue",
|
|
125
128
|
"PTooltip": "components/tooltip/Tooltip.vue",
|
|
@@ -89,7 +89,9 @@
|
|
|
89
89
|
<div
|
|
90
90
|
data-testid="select-no-data"
|
|
91
91
|
class="select__empty">
|
|
92
|
-
<slot
|
|
92
|
+
<slot
|
|
93
|
+
name="empty"
|
|
94
|
+
:keyword="keyword">
|
|
93
95
|
{{ emptyText }}
|
|
94
96
|
</slot>
|
|
95
97
|
</div>
|
|
@@ -168,6 +170,7 @@ import IconLoading from '../spinner/SpinnerRing.vue'
|
|
|
168
170
|
import type {
|
|
169
171
|
PropType,
|
|
170
172
|
HTMLAttributes,
|
|
173
|
+
VNode,
|
|
171
174
|
} from 'vue-demi'
|
|
172
175
|
import {
|
|
173
176
|
computed,
|
|
@@ -459,6 +462,23 @@ defineExpose({
|
|
|
459
462
|
menuEl,
|
|
460
463
|
toggle,
|
|
461
464
|
})
|
|
465
|
+
|
|
466
|
+
defineSlots<{
|
|
467
|
+
'activator'(props: {
|
|
468
|
+
isOpen: boolean,
|
|
469
|
+
open: () => void,
|
|
470
|
+
close: () => void,
|
|
471
|
+
toggle: () => void,
|
|
472
|
+
}): VNode[],
|
|
473
|
+
'selected'(props: { item: unknown, multiple: boolean }): VNode[],
|
|
474
|
+
'placeholder'(): VNode[],
|
|
475
|
+
'empty'(props: { keyword: string }): VNode[],
|
|
476
|
+
'option'(props: {
|
|
477
|
+
item: SelectItem,
|
|
478
|
+
isSelected: boolean,
|
|
479
|
+
}): VNode[],
|
|
480
|
+
'loading'(): VNode[],
|
|
481
|
+
}>()
|
|
462
482
|
</script>
|
|
463
483
|
|
|
464
484
|
<style lang="postcss">
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<p-card
|
|
3
|
+
data-testid="time"
|
|
4
|
+
class="time"
|
|
5
|
+
element="div">
|
|
6
|
+
<div class="time__container">
|
|
7
|
+
<TimeItem
|
|
8
|
+
v-model="hour"
|
|
9
|
+
:options="hourOptions"
|
|
10
|
+
time-type="hour"
|
|
11
|
+
class="time__items--hour" />
|
|
12
|
+
|
|
13
|
+
<div class="time__separator">
|
|
14
|
+
{{ timeSeparator }}
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
<TimeItem
|
|
18
|
+
v-model="minute"
|
|
19
|
+
:options="minuteOptions"
|
|
20
|
+
time-type="minute"
|
|
21
|
+
class="time__items--minute" />
|
|
22
|
+
|
|
23
|
+
<TimeItem
|
|
24
|
+
v-if="is12Hour"
|
|
25
|
+
v-model="ampm"
|
|
26
|
+
:options="periodOptions"
|
|
27
|
+
time-type="ampm"
|
|
28
|
+
class="time__items--ampm" />
|
|
29
|
+
</div>
|
|
30
|
+
<template
|
|
31
|
+
v-if="$slots.default"
|
|
32
|
+
#footer>
|
|
33
|
+
<div class="time__action">
|
|
34
|
+
<slot :confirm="confirm" />
|
|
35
|
+
</div>
|
|
36
|
+
</template>
|
|
37
|
+
</p-card>
|
|
38
|
+
</template>
|
|
39
|
+
|
|
40
|
+
<script setup lang="ts">
|
|
41
|
+
import pCard from '../card/Card.vue'
|
|
42
|
+
import TimeItem from './TimeItem.vue'
|
|
43
|
+
import type { PropType } from 'vue-demi'
|
|
44
|
+
import {
|
|
45
|
+
watch,
|
|
46
|
+
computed,
|
|
47
|
+
nextTick,
|
|
48
|
+
onBeforeMount,
|
|
49
|
+
ref,
|
|
50
|
+
} from 'vue-demi'
|
|
51
|
+
import { watchDebounced } from '@vueuse/core'
|
|
52
|
+
import { useVModel } from '../input'
|
|
53
|
+
import {
|
|
54
|
+
format,
|
|
55
|
+
formatISO,
|
|
56
|
+
isDate,
|
|
57
|
+
parse,
|
|
58
|
+
startOfDay,
|
|
59
|
+
} from 'date-fns'
|
|
60
|
+
import type { TimeModel, TimeContext } from './index'
|
|
61
|
+
import {
|
|
62
|
+
getHourUnits,
|
|
63
|
+
getMinuteUnits,
|
|
64
|
+
parseTime,
|
|
65
|
+
validateInterval,
|
|
66
|
+
} from './utils'
|
|
67
|
+
|
|
68
|
+
const props = defineProps({
|
|
69
|
+
modelValue: {
|
|
70
|
+
type : [Date, Object] as PropType<Date | TimeModel>,
|
|
71
|
+
default: undefined,
|
|
72
|
+
},
|
|
73
|
+
timeSeparator: {
|
|
74
|
+
type : String,
|
|
75
|
+
default: ':',
|
|
76
|
+
},
|
|
77
|
+
is12Hour: {
|
|
78
|
+
type : Boolean,
|
|
79
|
+
default: false,
|
|
80
|
+
},
|
|
81
|
+
hourInterval: {
|
|
82
|
+
type : Number,
|
|
83
|
+
default : 1,
|
|
84
|
+
validator: (value: number, prop) => {
|
|
85
|
+
return validateInterval('hour', value, prop.is12Hour as boolean)
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
minuteInterval: {
|
|
89
|
+
type : Number,
|
|
90
|
+
default : 1,
|
|
91
|
+
validator: (value: number) => {
|
|
92
|
+
return validateInterval('minute', value)
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
min: {
|
|
96
|
+
type : Date,
|
|
97
|
+
default: undefined,
|
|
98
|
+
},
|
|
99
|
+
max: {
|
|
100
|
+
type : Date,
|
|
101
|
+
default: undefined,
|
|
102
|
+
},
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
const emit = defineEmits<{
|
|
106
|
+
'update:modelValue': [unknown],
|
|
107
|
+
'context': [TimeContext],
|
|
108
|
+
'change': [TimeContext],
|
|
109
|
+
}>()
|
|
110
|
+
|
|
111
|
+
const model = useVModel(props)
|
|
112
|
+
const localModel = ref<Date>(startOfDay(new Date()))
|
|
113
|
+
|
|
114
|
+
const hour = ref('00')
|
|
115
|
+
const minute = ref('00')
|
|
116
|
+
const ampm = ref<'AM' | 'PM' | '-'>('AM')
|
|
117
|
+
|
|
118
|
+
const timeLabel = computed(() => {
|
|
119
|
+
const time = `${hour.value}:${minute.value}`
|
|
120
|
+
|
|
121
|
+
return props.is12Hour ? `${time} ${ampm.value}` : time
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
const timeFormat = computed(() => props.is12Hour ? 'hh:mm a' : 'HH:mm')
|
|
125
|
+
|
|
126
|
+
const hourOptions = computed(() => {
|
|
127
|
+
return getHourUnits(localModel.value, props.is12Hour, props.hourInterval, props.min, props.max)
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
const minuteOptions = computed(() => {
|
|
131
|
+
return getMinuteUnits(localModel.value, Number(hour.value), props.minuteInterval, props.min, props.max)
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
const periodOptions = computed(() => {
|
|
135
|
+
return ['AM', 'PM'] // TODO: should handle for period within time range
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
watchDebounced([
|
|
139
|
+
hour,
|
|
140
|
+
minute,
|
|
141
|
+
ampm,
|
|
142
|
+
], () => {
|
|
143
|
+
const date = parse(timeLabel.value, timeFormat.value, localModel.value)
|
|
144
|
+
|
|
145
|
+
emit('change', getContext(date))
|
|
146
|
+
}, { flush: 'post', debounce: 300 })
|
|
147
|
+
|
|
148
|
+
watch(model, init)
|
|
149
|
+
|
|
150
|
+
onBeforeMount(init)
|
|
151
|
+
|
|
152
|
+
function init () {
|
|
153
|
+
try {
|
|
154
|
+
if (!model.value)
|
|
155
|
+
return
|
|
156
|
+
|
|
157
|
+
if (isDate(model.value)) {
|
|
158
|
+
localModel.value = new Date(model.value as Date)
|
|
159
|
+
|
|
160
|
+
const { hh, mm, a } = parseTime(localModel.value, timeFormat.value)
|
|
161
|
+
|
|
162
|
+
assignTime(hh, mm, a)
|
|
163
|
+
} else {
|
|
164
|
+
const { hh, mm, a } = (model.value as TimeModel)
|
|
165
|
+
|
|
166
|
+
assignTime(hh, mm, a)
|
|
167
|
+
|
|
168
|
+
localModel.value = parse(timeLabel.value, timeFormat.value, new Date())
|
|
169
|
+
|
|
170
|
+
!props.is12Hour && a && console.warn('Please provide is12Hour props to parse time to 12 Hour Format')
|
|
171
|
+
}
|
|
172
|
+
} catch (error) {
|
|
173
|
+
console.warn(error)
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function confirm (): void {
|
|
178
|
+
try {
|
|
179
|
+
localModel.value = parse(timeLabel.value, timeFormat.value, localModel.value)
|
|
180
|
+
|
|
181
|
+
model.value = isDate(model.value)
|
|
182
|
+
? new Date(localModel.value)
|
|
183
|
+
: {
|
|
184
|
+
hh: hour.value,
|
|
185
|
+
mm: minute.value,
|
|
186
|
+
a : props.is12Hour ? ampm.value : undefined,
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
emit('context', getContext(localModel.value))
|
|
190
|
+
} catch (error) {
|
|
191
|
+
console.warn(error)
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
async function assignTime (hh: string, mm: string, a?: 'AM' | 'PM' | '-') {
|
|
196
|
+
hour.value = hh ?? '00'
|
|
197
|
+
minute.value = mm ?? '00'
|
|
198
|
+
ampm.value = a ?? 'AM'
|
|
199
|
+
|
|
200
|
+
await nextTick()
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function getContext (date: Date): TimeContext {
|
|
204
|
+
return {
|
|
205
|
+
time : format(date, timeFormat.value),
|
|
206
|
+
date : date,
|
|
207
|
+
dateISO: formatISO(date),
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
</script>
|
|
211
|
+
|
|
212
|
+
<style lang="postcss">
|
|
213
|
+
.time {
|
|
214
|
+
--p-card-padding-x: 2rem;
|
|
215
|
+
--p-card-padding-y: 2rem;
|
|
216
|
+
|
|
217
|
+
@apply flex flex-col shadow-xl;
|
|
218
|
+
@apply max-w-[320px] overflow-hidden;
|
|
219
|
+
|
|
220
|
+
&.card {
|
|
221
|
+
@apply border-transparent dark:border-transparent;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
&__container {
|
|
225
|
+
@apply flex items-center justify-center w-full min-h-[144px] space-x-2;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
&__separator {
|
|
229
|
+
@apply px-2.5 py-3;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
&__action {
|
|
233
|
+
@apply grid grid-flow-col auto-cols-fr;
|
|
234
|
+
|
|
235
|
+
&--cancel,
|
|
236
|
+
&--confirm {
|
|
237
|
+
@apply mx-2;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
.card__body {
|
|
242
|
+
@apply pb-6;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
.card__footer {
|
|
246
|
+
@apply pt-0;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
.splide__track {
|
|
250
|
+
@apply px-2;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
.dropdown__subitem & {
|
|
254
|
+
@apply shadow-none;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
</style>
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
ref="container"
|
|
4
|
+
class="time__items splide"
|
|
5
|
+
:class="`time__times--${timeType}`">
|
|
6
|
+
<div class="splide__track">
|
|
7
|
+
<div class="splide__list">
|
|
8
|
+
<div
|
|
9
|
+
v-for="option in options"
|
|
10
|
+
:key="option"
|
|
11
|
+
class="time__item splide__slide">
|
|
12
|
+
{{ option }}
|
|
13
|
+
</div>
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
</div>
|
|
17
|
+
</template>
|
|
18
|
+
|
|
19
|
+
<script setup lang="ts">
|
|
20
|
+
import {
|
|
21
|
+
ref,
|
|
22
|
+
onMounted,
|
|
23
|
+
watch,
|
|
24
|
+
computed,
|
|
25
|
+
} from 'vue-demi'
|
|
26
|
+
import { watchDebounced } from '@vueuse/core'
|
|
27
|
+
import type {
|
|
28
|
+
PropType,
|
|
29
|
+
Ref,
|
|
30
|
+
} from 'vue-demi'
|
|
31
|
+
import { useTime } from './index'
|
|
32
|
+
import { useVModel } from '../input'
|
|
33
|
+
import type { Options } from '@splidejs/splide'
|
|
34
|
+
import '@splidejs/splide/css/core'
|
|
35
|
+
|
|
36
|
+
type TimeType = 'hour' | 'minute' | 'ampm'
|
|
37
|
+
|
|
38
|
+
const props = defineProps({
|
|
39
|
+
modelValue: {
|
|
40
|
+
type : String,
|
|
41
|
+
default: '00',
|
|
42
|
+
},
|
|
43
|
+
timeType: {
|
|
44
|
+
type : String as PropType<TimeType>,
|
|
45
|
+
default: 'hour',
|
|
46
|
+
},
|
|
47
|
+
options: {
|
|
48
|
+
type : Array<string>,
|
|
49
|
+
default: () => [],
|
|
50
|
+
},
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
const { splide, activeSplide, initSplide } = useTime()
|
|
54
|
+
|
|
55
|
+
const model = useVModel(props)
|
|
56
|
+
const container = ref<HTMLDivElement>()
|
|
57
|
+
|
|
58
|
+
const timeOptions = computed(() => props.options)
|
|
59
|
+
|
|
60
|
+
watch(activeSplide, (value) => {
|
|
61
|
+
model.value = props.options[value]
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
watchDebounced(timeOptions, (value) => {
|
|
65
|
+
if (!splide.value)
|
|
66
|
+
return
|
|
67
|
+
|
|
68
|
+
const splideOptions: Options = {
|
|
69
|
+
...splide.value.options,
|
|
70
|
+
clones: value.length === 1 ? 0 : undefined,
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
splide.value.options = splideOptions
|
|
74
|
+
splide.value.refresh()
|
|
75
|
+
|
|
76
|
+
if (!value.includes(model.value))
|
|
77
|
+
model.value = value[0]
|
|
78
|
+
}, { flush: 'post', debounce: 50 })
|
|
79
|
+
|
|
80
|
+
onMounted(async () => {
|
|
81
|
+
if (container.value) {
|
|
82
|
+
const splideOptions: Options = {
|
|
83
|
+
start: timeOptions.value.indexOf(model.value),
|
|
84
|
+
type : props.timeType === 'ampm' ? 'slide' : 'loop',
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
await initSplide(container as Ref<HTMLDivElement>, splideOptions)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
splide.value?.on('refresh', () => {
|
|
91
|
+
const index = timeOptions.value.indexOf(model.value)
|
|
92
|
+
|
|
93
|
+
splide.value?.go(index === -1 ? 0 : index)
|
|
94
|
+
})
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
</script>
|
|
98
|
+
|
|
99
|
+
<style lang="postcss">
|
|
100
|
+
.time {
|
|
101
|
+
&__items {
|
|
102
|
+
&:before {
|
|
103
|
+
@apply absolute content-[''] w-[42px] h-12 border-default dark:border-dark-default border-y;
|
|
104
|
+
@apply top-[50%] left-[50%] translate-x-[-50%] translate-y-[-50%];
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
&__item {
|
|
109
|
+
@apply text-center px-2.5 py-3 text-subtle dark:text-dark-subtle cursor-pointer;
|
|
110
|
+
@apply transition-[color] duration-[50ms];
|
|
111
|
+
|
|
112
|
+
&.is-active {
|
|
113
|
+
@apply text-default dark:text-dark-default font-medium cursor-default;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
</style>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { MaybeRef } from '@vueuse/core';
|
|
2
|
+
import type { Options, Splide } from '@splidejs/splide';
|
|
3
|
+
export type TimeLimitation = Date | TimeModel | undefined;
|
|
4
|
+
export interface TimeModel {
|
|
5
|
+
hh: string;
|
|
6
|
+
mm: string;
|
|
7
|
+
a?: 'AM' | 'PM' | '-';
|
|
8
|
+
}
|
|
9
|
+
export interface TimeContext {
|
|
10
|
+
time: string;
|
|
11
|
+
date: Date;
|
|
12
|
+
dateISO: string;
|
|
13
|
+
}
|
|
14
|
+
export declare function useTime(): {
|
|
15
|
+
splide: import("vue-demi").Ref<Splide | undefined>;
|
|
16
|
+
activeSplide: import("vue-demi").Ref<number>;
|
|
17
|
+
initSplide: (element: MaybeRef<HTMLDivElement>, options?: Options) => Promise<void>;
|
|
18
|
+
initSplideEvent: () => void;
|
|
19
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import {
|
|
2
|
+
onBeforeUnmount,
|
|
3
|
+
ref,
|
|
4
|
+
unref
|
|
5
|
+
} from "vue-demi";
|
|
6
|
+
import defu from "defu";
|
|
7
|
+
export function useTime() {
|
|
8
|
+
const splide = ref();
|
|
9
|
+
const activeSplide = ref(1);
|
|
10
|
+
async function initSplide(element, options) {
|
|
11
|
+
const { Splide } = await import("@splidejs/splide");
|
|
12
|
+
const container = unref(element);
|
|
13
|
+
const splideOptions = defu(options, {
|
|
14
|
+
direction: "ttb",
|
|
15
|
+
height: "9rem",
|
|
16
|
+
width: "100%",
|
|
17
|
+
focus: "center",
|
|
18
|
+
perPage: 3,
|
|
19
|
+
perMove: 1,
|
|
20
|
+
arrows: false,
|
|
21
|
+
wheel: true,
|
|
22
|
+
wheelSleep: 150,
|
|
23
|
+
isNavigation: true,
|
|
24
|
+
pagination: false
|
|
25
|
+
});
|
|
26
|
+
splide.value = new Splide(container, splideOptions);
|
|
27
|
+
initSplideEvent();
|
|
28
|
+
}
|
|
29
|
+
function initSplideEvent() {
|
|
30
|
+
if (!splide.value)
|
|
31
|
+
return;
|
|
32
|
+
splide.value.on("mounted", onTimeLoad);
|
|
33
|
+
splide.value.on("move", onTimeChange);
|
|
34
|
+
splide.value.mount();
|
|
35
|
+
}
|
|
36
|
+
function onTimeLoad() {
|
|
37
|
+
if (!splide.value)
|
|
38
|
+
return;
|
|
39
|
+
activeSplide.value = splide.value.index;
|
|
40
|
+
}
|
|
41
|
+
function onTimeChange(index) {
|
|
42
|
+
activeSplide.value = index;
|
|
43
|
+
}
|
|
44
|
+
onBeforeUnmount(() => {
|
|
45
|
+
splide.value?.destroy();
|
|
46
|
+
});
|
|
47
|
+
return {
|
|
48
|
+
splide,
|
|
49
|
+
activeSplide,
|
|
50
|
+
initSplide,
|
|
51
|
+
initSplideEvent
|
|
52
|
+
};
|
|
53
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function getHourUnits(model: Date, is12Hour: boolean, step?: number, min?: Date, max?: Date): string[];
|
|
2
|
+
export declare function getMinuteUnits(model: Date, currentHour: number, step?: number, min?: Date, max?: Date): string[];
|
|
3
|
+
export declare function getFormat(is12Hour: boolean): "hh:mm a" | "HH:mm";
|
|
4
|
+
export declare function parseTime(date: Date, timeFormat: string): {
|
|
5
|
+
hh: string;
|
|
6
|
+
mm: string;
|
|
7
|
+
a: "AM" | "PM";
|
|
8
|
+
};
|
|
9
|
+
export declare function validateInterval(type: 'hour' | 'minute', value: number, is12Hour?: boolean): boolean;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import {
|
|
2
|
+
set,
|
|
3
|
+
eachHourOfInterval,
|
|
4
|
+
eachMinuteOfInterval,
|
|
5
|
+
endOfDay,
|
|
6
|
+
format,
|
|
7
|
+
isBefore,
|
|
8
|
+
min as minDate,
|
|
9
|
+
max as maxDate,
|
|
10
|
+
startOfDay,
|
|
11
|
+
isSameHour,
|
|
12
|
+
endOfHour,
|
|
13
|
+
startOfHour
|
|
14
|
+
} from "date-fns";
|
|
15
|
+
import { uniq } from "lodash-es";
|
|
16
|
+
export function getHourUnits(model, is12Hour, step = 1, min, max) {
|
|
17
|
+
if (isBefore(max, min)) {
|
|
18
|
+
console.warn("`max` value should greater than `min` value and vice versa");
|
|
19
|
+
return [];
|
|
20
|
+
}
|
|
21
|
+
let start = startOfDay(/* @__PURE__ */ new Date());
|
|
22
|
+
let end = endOfDay(/* @__PURE__ */ new Date());
|
|
23
|
+
if (min)
|
|
24
|
+
start = maxDate([model, min]);
|
|
25
|
+
if (max)
|
|
26
|
+
end = minDate([endOfDay(start), max]);
|
|
27
|
+
const hourUnits = eachHourOfInterval({
|
|
28
|
+
start,
|
|
29
|
+
end
|
|
30
|
+
}, { step });
|
|
31
|
+
const units = hourUnits.map((date) => {
|
|
32
|
+
if (is12Hour)
|
|
33
|
+
return format(date, "hh");
|
|
34
|
+
return format(date, "HH");
|
|
35
|
+
});
|
|
36
|
+
return uniq(units);
|
|
37
|
+
}
|
|
38
|
+
export function getMinuteUnits(model, currentHour, step = 1, min, max) {
|
|
39
|
+
if (isBefore(max, min)) {
|
|
40
|
+
console.warn("`max` value should greater than `min` value and vice versa");
|
|
41
|
+
return [];
|
|
42
|
+
}
|
|
43
|
+
let start = startOfDay(/* @__PURE__ */ new Date());
|
|
44
|
+
let end = endOfDay(/* @__PURE__ */ new Date());
|
|
45
|
+
if (min)
|
|
46
|
+
start = maxDate([model, min]);
|
|
47
|
+
if (max)
|
|
48
|
+
end = minDate([endOfDay(start), max]);
|
|
49
|
+
const currentTime = set(start, { hours: currentHour });
|
|
50
|
+
const minuteUnits = eachMinuteOfInterval({
|
|
51
|
+
start: isSameHour(currentTime, start) ? currentTime : startOfHour(currentTime),
|
|
52
|
+
end: isSameHour(currentTime, end) ? end : endOfHour(currentTime)
|
|
53
|
+
}, { step });
|
|
54
|
+
const units = minuteUnits.map((date) => {
|
|
55
|
+
return format(date, "mm");
|
|
56
|
+
});
|
|
57
|
+
return uniq(units);
|
|
58
|
+
}
|
|
59
|
+
export function getFormat(is12Hour) {
|
|
60
|
+
return is12Hour ? "hh:mm a" : "HH:mm";
|
|
61
|
+
}
|
|
62
|
+
export function parseTime(date, timeFormat) {
|
|
63
|
+
const [hh, mm] = format(date, timeFormat).split(":");
|
|
64
|
+
const a = format(date, "a");
|
|
65
|
+
return {
|
|
66
|
+
hh,
|
|
67
|
+
mm: mm.slice(0, 2),
|
|
68
|
+
a
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
export function validateInterval(type, value, is12Hour = false) {
|
|
72
|
+
let min = 0;
|
|
73
|
+
let max = 0;
|
|
74
|
+
if (type === "hour") {
|
|
75
|
+
min = 1;
|
|
76
|
+
max = is12Hour ? 12 : 24;
|
|
77
|
+
} else if (type === "minute") {
|
|
78
|
+
min = 1;
|
|
79
|
+
max = 60;
|
|
80
|
+
}
|
|
81
|
+
return value >= min && value < max;
|
|
82
|
+
}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<Dropdown
|
|
3
|
+
v-model="isOpen"
|
|
4
|
+
class="timepicker"
|
|
5
|
+
data-testid="timepicker"
|
|
6
|
+
aria-label="timepicker"
|
|
7
|
+
:class="classNames"
|
|
8
|
+
:disabled="disabled">
|
|
9
|
+
<template #activator>
|
|
10
|
+
<Input
|
|
11
|
+
:value="value"
|
|
12
|
+
:model-value="value"
|
|
13
|
+
data-testid="timepicker-input"
|
|
14
|
+
class="timepicker__input"
|
|
15
|
+
:placeholder="placeholder"
|
|
16
|
+
:disabled="disabled"
|
|
17
|
+
:error="error"
|
|
18
|
+
:size="size"
|
|
19
|
+
readonly
|
|
20
|
+
@focus="onFocus">
|
|
21
|
+
<template #append>
|
|
22
|
+
<IconTime
|
|
23
|
+
class="timepicker__icon" />
|
|
24
|
+
</template>
|
|
25
|
+
</Input>
|
|
26
|
+
</template>
|
|
27
|
+
|
|
28
|
+
<Time
|
|
29
|
+
v-if="isOpen"
|
|
30
|
+
v-slot="{ confirm }"
|
|
31
|
+
v-model="model"
|
|
32
|
+
:time-separator="timeSeparator"
|
|
33
|
+
:is12-hour="is12Hour"
|
|
34
|
+
:hour-interval="hourInterval"
|
|
35
|
+
:minute-interval="minuteInterval"
|
|
36
|
+
:min="min"
|
|
37
|
+
:max="max"
|
|
38
|
+
@context="onTimeContext"
|
|
39
|
+
@change="(context) => emit('change', context)">
|
|
40
|
+
<slot
|
|
41
|
+
name="footer"
|
|
42
|
+
:confirm="confirm"
|
|
43
|
+
:close="onClose">
|
|
44
|
+
<Button
|
|
45
|
+
v-if="dismissable"
|
|
46
|
+
variant="ghost"
|
|
47
|
+
class="time__action--cancel"
|
|
48
|
+
@click="onClose">
|
|
49
|
+
{{ dimissLabel }}
|
|
50
|
+
</Button>
|
|
51
|
+
<Button
|
|
52
|
+
variant="solid"
|
|
53
|
+
color="info"
|
|
54
|
+
@click="confirm">
|
|
55
|
+
{{ confirmLabel }}
|
|
56
|
+
</Button>
|
|
57
|
+
</slot>
|
|
58
|
+
</Time>
|
|
59
|
+
</Dropdown>
|
|
60
|
+
</template>
|
|
61
|
+
|
|
62
|
+
<script setup lang="ts">
|
|
63
|
+
import Dropdown from '../dropdown/Dropdown.vue'
|
|
64
|
+
import Input from '../input/Input.vue'
|
|
65
|
+
import Button from '../button/Button.vue'
|
|
66
|
+
import IconTime from '@privyid/persona-icon/vue/time/16.vue'
|
|
67
|
+
import Time from '../time/Time.vue'
|
|
68
|
+
import type { SizeVariant } from '../button'
|
|
69
|
+
import { useVModel } from '../input'
|
|
70
|
+
import type { TimeContext, TimeModel } from '../time'
|
|
71
|
+
import { validateInterval } from '../time/utils'
|
|
72
|
+
import type { PropType, VNode } from 'vue-demi'
|
|
73
|
+
import {
|
|
74
|
+
ref, computed, onMounted,
|
|
75
|
+
} from 'vue-demi'
|
|
76
|
+
import { format, isDate } from 'date-fns'
|
|
77
|
+
|
|
78
|
+
const props = defineProps({
|
|
79
|
+
modelValue: {
|
|
80
|
+
type : [Date, Object] as PropType<Date | TimeModel>,
|
|
81
|
+
default: undefined,
|
|
82
|
+
},
|
|
83
|
+
size: {
|
|
84
|
+
type : String as PropType<SizeVariant>,
|
|
85
|
+
default: 'md',
|
|
86
|
+
},
|
|
87
|
+
placeholder: {
|
|
88
|
+
type : String,
|
|
89
|
+
default: '',
|
|
90
|
+
},
|
|
91
|
+
disabled: {
|
|
92
|
+
type : Boolean,
|
|
93
|
+
default: undefined,
|
|
94
|
+
},
|
|
95
|
+
readonly: {
|
|
96
|
+
type : Boolean,
|
|
97
|
+
default: undefined,
|
|
98
|
+
},
|
|
99
|
+
error: {
|
|
100
|
+
type : Boolean,
|
|
101
|
+
default: undefined,
|
|
102
|
+
},
|
|
103
|
+
dismissable: {
|
|
104
|
+
type : Boolean,
|
|
105
|
+
default: false,
|
|
106
|
+
},
|
|
107
|
+
dimissLabel: {
|
|
108
|
+
type : String,
|
|
109
|
+
default: 'Cancel',
|
|
110
|
+
},
|
|
111
|
+
confirmLabel: {
|
|
112
|
+
type : String,
|
|
113
|
+
default: 'Set',
|
|
114
|
+
},
|
|
115
|
+
timeSeparator: {
|
|
116
|
+
type : String,
|
|
117
|
+
default: ':',
|
|
118
|
+
},
|
|
119
|
+
is12Hour: {
|
|
120
|
+
type : Boolean,
|
|
121
|
+
default: false,
|
|
122
|
+
},
|
|
123
|
+
hourInterval: {
|
|
124
|
+
type : Number,
|
|
125
|
+
default : 1,
|
|
126
|
+
validator: (value: number, prop) => {
|
|
127
|
+
return validateInterval('hour', value, prop.is12Hour as boolean)
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
minuteInterval: {
|
|
131
|
+
type : Number,
|
|
132
|
+
default : 1,
|
|
133
|
+
validator: (value: number) => {
|
|
134
|
+
return validateInterval('minute', value)
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
min: {
|
|
138
|
+
type : Date,
|
|
139
|
+
default: undefined,
|
|
140
|
+
},
|
|
141
|
+
max: {
|
|
142
|
+
type : Date,
|
|
143
|
+
default: undefined,
|
|
144
|
+
},
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
const emit = defineEmits<{
|
|
148
|
+
'update:modelValue': [unknown],
|
|
149
|
+
'context': [TimeContext],
|
|
150
|
+
'change': [TimeContext],
|
|
151
|
+
}>()
|
|
152
|
+
|
|
153
|
+
const model = useVModel(props)
|
|
154
|
+
const isOpen = ref(false)
|
|
155
|
+
const value = ref('')
|
|
156
|
+
|
|
157
|
+
const classNames = computed(() => {
|
|
158
|
+
const result: string[] = []
|
|
159
|
+
|
|
160
|
+
if (isOpen.value)
|
|
161
|
+
result.push('timepicker--open')
|
|
162
|
+
|
|
163
|
+
if (props.disabled)
|
|
164
|
+
result.push('timepicker--disabled')
|
|
165
|
+
|
|
166
|
+
if (props.readonly)
|
|
167
|
+
result.push('timepicker--readonly')
|
|
168
|
+
|
|
169
|
+
if (props.error)
|
|
170
|
+
result.push('timepicker--error', 'state--error')
|
|
171
|
+
|
|
172
|
+
return result
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
onMounted(() => {
|
|
176
|
+
if (!model.value)
|
|
177
|
+
return
|
|
178
|
+
|
|
179
|
+
if (isDate(model.value))
|
|
180
|
+
value.value = format(model.value as Date, props.is12Hour ? 'hh:mm a' : 'HH:mm')
|
|
181
|
+
else {
|
|
182
|
+
const { hh, mm, a } = model.value as TimeModel
|
|
183
|
+
const time = `${hh}:${mm}`
|
|
184
|
+
|
|
185
|
+
value.value = props.is12Hour ? `${time} ${a || ''}` : time
|
|
186
|
+
}
|
|
187
|
+
})
|
|
188
|
+
|
|
189
|
+
function onFocus () {
|
|
190
|
+
if (!props.disabled && !props.readonly)
|
|
191
|
+
isOpen.value = true
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function onTimeContext (context: TimeContext) {
|
|
195
|
+
onClose()
|
|
196
|
+
|
|
197
|
+
value.value = context.time
|
|
198
|
+
emit('context', context)
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function onClose () {
|
|
202
|
+
isOpen.value = false
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
defineSlots<{
|
|
206
|
+
'footer'(props: {
|
|
207
|
+
confirm: () => void,
|
|
208
|
+
close: () => void,
|
|
209
|
+
}): VNode[], }>()
|
|
210
|
+
</script>
|
|
211
|
+
|
|
212
|
+
<style lang="postcss">
|
|
213
|
+
.timepicker {
|
|
214
|
+
&__input {
|
|
215
|
+
@apply pr-8 truncate;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
&__icon {
|
|
219
|
+
@apply transition-transform duration-150 text-muted pointer-events-none;
|
|
220
|
+
@apply dark:text-dark-muted;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
> .dropdown__menu {
|
|
224
|
+
--p-dropdown-size: auto;
|
|
225
|
+
--p-dropdown-max-height: 100%;
|
|
226
|
+
|
|
227
|
+
@apply min-w-max max-h-min;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
</style>
|
package/dist/module.json
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@privyid/persona",
|
|
3
3
|
"description": "Persona core package",
|
|
4
|
-
"version": "1.0.0-rc.
|
|
4
|
+
"version": "1.0.0-rc.2",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"url": "https://github.com/privy-open-source/design-system.git",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"import": "./dist/directive/index.mjs",
|
|
29
29
|
"types": "./dist/directive/index.d.ts"
|
|
30
30
|
},
|
|
31
|
-
"./components
|
|
31
|
+
"./components/*": "./dist/components/*"
|
|
32
32
|
},
|
|
33
33
|
"typesVersions": {
|
|
34
34
|
"*": {
|
|
@@ -58,15 +58,15 @@
|
|
|
58
58
|
"dev:prepare": "nuxt-module-build --stub && nuxi prepare playground"
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
|
-
"@floating-ui/dom": "1.6.
|
|
61
|
+
"@floating-ui/dom": "1.6.3",
|
|
62
62
|
"@jill64/universal-sanitizer": "^1.0.2",
|
|
63
63
|
"@juggle/resize-observer": "3.4.0",
|
|
64
|
-
"@nuxt/kit": "3.
|
|
64
|
+
"@nuxt/kit": "3.10.2",
|
|
65
65
|
"@splidejs/splide": "4.1.4",
|
|
66
66
|
"@testing-library/dom": "9.3.4",
|
|
67
67
|
"@testing-library/user-event": "14.5.2",
|
|
68
68
|
"@vueuse/core": "10.7.2",
|
|
69
|
-
"@vueuse/math": "10.
|
|
69
|
+
"@vueuse/math": "10.8.0",
|
|
70
70
|
"@zxing/browser": "0.1.4",
|
|
71
71
|
"@zxing/library": "0.20.0",
|
|
72
72
|
"chart.js": "4.4.1",
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"scroll-into-view": "1.16.2",
|
|
84
84
|
"tabbable": "6.2.0",
|
|
85
85
|
"vue-collapsed": "1.3.0",
|
|
86
|
-
"vue-demi": "0.14.
|
|
86
|
+
"vue-demi": "0.14.7",
|
|
87
87
|
"vuedraggable": "next",
|
|
88
88
|
"webfontloader": "1.6.28",
|
|
89
89
|
"zxcvbn": "4.4.2"
|
|
@@ -92,8 +92,8 @@
|
|
|
92
92
|
"extends @privyid/browserslist-config"
|
|
93
93
|
],
|
|
94
94
|
"peerDependencies": {
|
|
95
|
-
"@privyid/browserslist-config": "^1.0.0-rc.
|
|
96
|
-
"@privyid/tailwind-preset": "^1.0.0-rc.
|
|
95
|
+
"@privyid/browserslist-config": "^1.0.0-rc.2",
|
|
96
|
+
"@privyid/tailwind-preset": "^1.0.0-rc.2",
|
|
97
97
|
"postcss-custom-properties": "^12.1.11 || ^13.0.0",
|
|
98
98
|
"postcss-hexrgba": "^2.1.0",
|
|
99
99
|
"postcss-lighten-darken": "^0.9.0",
|
|
@@ -102,13 +102,13 @@
|
|
|
102
102
|
},
|
|
103
103
|
"devDependencies": {
|
|
104
104
|
"@nuxt/module-builder": "^0.5.0",
|
|
105
|
-
"@nuxt/schema": "3.
|
|
105
|
+
"@nuxt/schema": "3.10.2",
|
|
106
106
|
"@nuxtjs/tailwindcss": "^6.2.0",
|
|
107
|
-
"@privyid/browserslist-config": "^1.0.0-rc.
|
|
108
|
-
"@privyid/tailwind-preset": "^1.0.0-rc.
|
|
107
|
+
"@privyid/browserslist-config": "^1.0.0-rc.2",
|
|
108
|
+
"@privyid/tailwind-preset": "^1.0.0-rc.2",
|
|
109
109
|
"@types/sanitize-html": "^2",
|
|
110
110
|
"browserslist-to-esbuild": "^2.0.0",
|
|
111
|
-
"nuxt": "3.
|
|
111
|
+
"nuxt": "3.10.2",
|
|
112
112
|
"postcss-custom-properties": "^13.0.0",
|
|
113
113
|
"postcss-hexrgba": "^2.1.0",
|
|
114
114
|
"postcss-lighten-darken": "^0.9.0",
|