@bl33dz/fa814698dcde12f86a37ac31dd3aedf9 1.0.20 → 1.0.21
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/perisai-ui.es.js +2690 -2059
- package/dist/perisai-ui.umd.js +20 -1
- package/package.json +3 -3
- package/src/index.ts +2 -5
- package/src/shadcn/input-otp/InputOTP.vue +28 -0
- package/src/shadcn/input-otp/InputOTPGroup.vue +22 -0
- package/src/shadcn/input-otp/InputOTPSeparator.vue +21 -0
- package/src/shadcn/input-otp/InputOTPSlot.vue +32 -0
- package/src/shadcn/input-otp/index.ts +4 -0
- package/src/shadcn/navigation-menu/NavigationMenuTrigger.vue +17 -12
- package/src/ui/select.vue +2 -1
- package/vite.config.ts +0 -1
- package/src/ui/InputOTP.vue +0 -69
- package/src/ui/InputOTPGroup.vue +0 -7
- package/src/ui/InputOTPSeparator.vue +0 -8
- package/src/ui/InputOTPSlot.vue +0 -61
- package/src/ui/input-otp.vue +0 -52
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "1.0.
|
|
6
|
+
"version": "1.0.21",
|
|
7
7
|
"main": "dist/perisai-ui.umd.js",
|
|
8
8
|
"module": "dist/perisai-ui.es.js",
|
|
9
9
|
"scripts": {
|
|
@@ -28,7 +28,6 @@
|
|
|
28
28
|
"esbuild": "^0.25.12",
|
|
29
29
|
"estree-walker": "^2.0.2",
|
|
30
30
|
"fdir": "^6.5.0",
|
|
31
|
-
"input-otp": "^1.4.2",
|
|
32
31
|
"lucide-vue-next": "^0.554.0",
|
|
33
32
|
"magic-string": "^0.30.21",
|
|
34
33
|
"nanoid": "^3.3.11",
|
|
@@ -39,7 +38,8 @@
|
|
|
39
38
|
"source-map-js": "^1.2.1",
|
|
40
39
|
"tailwind-merge": "^3.4.0",
|
|
41
40
|
"tinyglobby": "^0.2.15",
|
|
42
|
-
"vaul-vue": "^0.4.1"
|
|
41
|
+
"vaul-vue": "^0.4.1",
|
|
42
|
+
"vue-input-otp": "^0.3.2"
|
|
43
43
|
},
|
|
44
44
|
"description": ""
|
|
45
45
|
}
|
package/src/index.ts
CHANGED
|
@@ -10,12 +10,10 @@ export * from './shadcn/tooltip';
|
|
|
10
10
|
export * from './shadcn/command';
|
|
11
11
|
export * from './shadcn/switch';
|
|
12
12
|
export * from './shadcn/collapsible';
|
|
13
|
+
export * from './shadcn/navigation-menu';
|
|
14
|
+
export * from './shadcn/input-otp';
|
|
13
15
|
|
|
14
16
|
export * from './ui/tree';
|
|
15
|
-
export { default as InputOTP } from './ui/InputOTP.vue';
|
|
16
|
-
export { default as InputOTPGroup } from './ui/InputOTPGroup.vue';
|
|
17
|
-
export { default as InputOTPSeparator } from './ui/InputOTPSeparator.vue';
|
|
18
|
-
export { default as InputOTPSlot } from './ui/InputOTPSlot.vue';
|
|
19
17
|
export { default as PopoverContent } from './ui/PopoverContent.vue';
|
|
20
18
|
export { default as PopoverTrigger } from './ui/PopoverTrigger.vue';
|
|
21
19
|
export { default as SelectContent } from './ui/SelectContent.vue';
|
|
@@ -112,7 +110,6 @@ export { default as Slash } from './ui/icons/Slash.vue';
|
|
|
112
110
|
export { default as Trash2 } from './ui/icons/Trash2.vue';
|
|
113
111
|
export { default as Type } from './ui/icons/Type.vue';
|
|
114
112
|
export { default as User } from './ui/icons/User.vue';
|
|
115
|
-
export { default as InputOtp } from './ui/input-otp.vue';
|
|
116
113
|
export { default as Input } from './ui/input.vue';
|
|
117
114
|
export { default as Label } from './ui/label.vue';
|
|
118
115
|
export { default as Pagination } from './ui/pagination.vue';
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { HTMLAttributes } from "vue"
|
|
3
|
+
import type { OTPInputEmits, OTPInputProps } from "vue-input-otp"
|
|
4
|
+
import { reactiveOmit } from "@vueuse/core"
|
|
5
|
+
import { useForwardPropsEmits } from "reka-ui"
|
|
6
|
+
import { OTPInput } from "vue-input-otp"
|
|
7
|
+
import { cn } from "../../lib/utils"
|
|
8
|
+
|
|
9
|
+
const props = defineProps<OTPInputProps & { class?: HTMLAttributes["class"] }>()
|
|
10
|
+
|
|
11
|
+
const emits = defineEmits<OTPInputEmits>()
|
|
12
|
+
|
|
13
|
+
const delegatedProps = reactiveOmit(props, "class")
|
|
14
|
+
|
|
15
|
+
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<template>
|
|
19
|
+
<OTPInput
|
|
20
|
+
v-slot="slotProps"
|
|
21
|
+
v-bind="forwarded"
|
|
22
|
+
:container-class="cn('flex items-center gap-2 has-disabled:opacity-50', props.class)"
|
|
23
|
+
data-slot="input-otp"
|
|
24
|
+
class="disabled:cursor-not-allowed"
|
|
25
|
+
>
|
|
26
|
+
<slot v-bind="slotProps" />
|
|
27
|
+
</OTPInput>
|
|
28
|
+
</template>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { HTMLAttributes } from "vue"
|
|
3
|
+
import { reactiveOmit } from "@vueuse/core"
|
|
4
|
+
import { useForwardProps } from "reka-ui"
|
|
5
|
+
import { cn } from "../../lib/utils"
|
|
6
|
+
|
|
7
|
+
const props = defineProps<{ class?: HTMLAttributes["class"] }>()
|
|
8
|
+
|
|
9
|
+
const delegatedProps = reactiveOmit(props, "class")
|
|
10
|
+
|
|
11
|
+
const forwarded = useForwardProps(delegatedProps)
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<template>
|
|
15
|
+
<div
|
|
16
|
+
data-slot="input-otp-group"
|
|
17
|
+
v-bind="forwarded"
|
|
18
|
+
:class="cn('flex items-center', props.class)"
|
|
19
|
+
>
|
|
20
|
+
<slot />
|
|
21
|
+
</div>
|
|
22
|
+
</template>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { HTMLAttributes } from "vue"
|
|
3
|
+
import { MinusIcon } from "lucide-vue-next"
|
|
4
|
+
import { useForwardProps } from "reka-ui"
|
|
5
|
+
|
|
6
|
+
const props = defineProps<{ class?: HTMLAttributes["class"] }>()
|
|
7
|
+
|
|
8
|
+
const forwarded = useForwardProps(props)
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<template>
|
|
12
|
+
<div
|
|
13
|
+
data-slot="input-otp-separator"
|
|
14
|
+
role="separator"
|
|
15
|
+
v-bind="forwarded"
|
|
16
|
+
>
|
|
17
|
+
<slot>
|
|
18
|
+
<MinusIcon />
|
|
19
|
+
</slot>
|
|
20
|
+
</div>
|
|
21
|
+
</template>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { HTMLAttributes } from "vue"
|
|
3
|
+
import { reactiveOmit } from "@vueuse/core"
|
|
4
|
+
import { useForwardProps } from "reka-ui"
|
|
5
|
+
import { computed } from "vue"
|
|
6
|
+
import { useVueOTPContext } from "vue-input-otp"
|
|
7
|
+
import { cn } from "../../lib/utils"
|
|
8
|
+
|
|
9
|
+
const props = defineProps<{ index: number, class?: HTMLAttributes["class"] }>()
|
|
10
|
+
|
|
11
|
+
const delegatedProps = reactiveOmit(props, "class")
|
|
12
|
+
|
|
13
|
+
const forwarded = useForwardProps(delegatedProps)
|
|
14
|
+
|
|
15
|
+
const context = useVueOTPContext()
|
|
16
|
+
|
|
17
|
+
const slot = computed(() => context?.value.slots[props.index])
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<template>
|
|
21
|
+
<div
|
|
22
|
+
v-bind="forwarded"
|
|
23
|
+
data-slot="input-otp-slot"
|
|
24
|
+
:data-active="slot?.isActive"
|
|
25
|
+
:class="cn('data-[active=true]:border-ring data-[active=true]:ring-ring/50 data-[active=true]:aria-invalid:ring-destructive/20 dark:data-[active=true]:aria-invalid:ring-destructive/40 aria-invalid:border-destructive data-[active=true]:aria-invalid:border-destructive border-input relative flex h-9 w-9 items-center justify-center border-y border-r text-sm bg-input-background transition-all outline-none first:rounded-l-md first:border-l last:rounded-r-md data-[active=true]:z-10 data-[active=true]:ring-[3px]', props.class)"
|
|
26
|
+
>
|
|
27
|
+
{{ slot?.char }}
|
|
28
|
+
<div v-if="slot?.hasFakeCaret" class="pointer-events-none absolute inset-0 flex items-center justify-center">
|
|
29
|
+
<div class="animate-caret-blink bg-foreground h-4 w-px duration-1000" />
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
</template>
|
|
@@ -1,24 +1,29 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import type { NavigationMenuTriggerProps } from "reka-ui"
|
|
3
|
+
import type { HTMLAttributes } from "vue"
|
|
4
|
+
import { reactiveOmit } from "@vueuse/core"
|
|
5
|
+
import { NavigationMenuTrigger, useForwardProps } from "reka-ui"
|
|
2
6
|
import { cn } from '@/lib/utils';
|
|
3
7
|
import { ChevronDown } from 'lucide-vue-next';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
+
|
|
9
|
+
const props = defineProps<NavigationMenuTriggerProps & { class?: HTMLAttributes["class"] }>()
|
|
10
|
+
|
|
11
|
+
const delegatedProps = reactiveOmit(props, "class")
|
|
12
|
+
const forwardedProps = useForwardProps(delegatedProps)
|
|
8
13
|
</script>
|
|
9
14
|
<template>
|
|
10
|
-
<
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
<NavigationMenuTrigger
|
|
16
|
+
data-slot="navigation-menu-trigger"
|
|
17
|
+
v-bind="forwardedProps"
|
|
18
|
+
:class="cn(
|
|
19
|
+
'group inline-flex h-9 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground disabled:pointer-events-none disabled:opacity-50 transition-[color,box-shadow] outline-none focus-visible:ring-ring/50 focus-visible:ring-[3px] focus-visible:outline-1',
|
|
20
|
+
props.class
|
|
21
|
+
)"
|
|
16
22
|
>
|
|
17
23
|
<slot />
|
|
18
24
|
<ChevronDown
|
|
19
25
|
class="relative top-[1px] ml-1 size-3 transition duration-300 group-data-[state=open]:rotate-180"
|
|
20
26
|
aria-hidden="true"
|
|
21
|
-
:class="{ 'rotate-180': props.open }"
|
|
22
27
|
/>
|
|
23
|
-
</
|
|
28
|
+
</NavigationMenuTrigger>
|
|
24
29
|
</template>
|
package/src/ui/select.vue
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
:disabled="disabled"
|
|
21
21
|
:class="mergedClass"
|
|
22
22
|
>
|
|
23
|
-
<SelectTrigger class="w-full">
|
|
23
|
+
<SelectTrigger :class="cn('w-full', triggerClass)">
|
|
24
24
|
<slot name="trigger">
|
|
25
25
|
<SelectValue :placeholder="placeholder" />
|
|
26
26
|
</slot>
|
|
@@ -59,6 +59,7 @@ const props = defineProps({
|
|
|
59
59
|
disabled: Boolean,
|
|
60
60
|
customClass: String,
|
|
61
61
|
contentClass: String,
|
|
62
|
+
triggerClass: String,
|
|
62
63
|
title: String,
|
|
63
64
|
maxDisplay: { type: Number, default: 3 },
|
|
64
65
|
size: { type: String, default: 'default' },
|
package/vite.config.ts
CHANGED
package/src/ui/InputOTP.vue
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import { computed, provide, h, defineAsyncComponent, useSlots } from 'vue';
|
|
3
|
-
import { cn } from './utils';
|
|
4
|
-
import { InputOTPContext, InputOTPMaskContext } from './InputOTPContext';
|
|
5
|
-
|
|
6
|
-
const props = defineProps({
|
|
7
|
-
modelValue: { type: String, default: '' },
|
|
8
|
-
maxLength: { type: Number, required: true },
|
|
9
|
-
disabled: { type: Boolean, default: false },
|
|
10
|
-
masked: { type: Boolean, default: false },
|
|
11
|
-
class: String,
|
|
12
|
-
containerClass: String,
|
|
13
|
-
});
|
|
14
|
-
const emit = defineEmits(['update:modelValue']);
|
|
15
|
-
const slots = useSlots();
|
|
16
|
-
|
|
17
|
-
const handleChange = (newValue: string) => {
|
|
18
|
-
if (newValue.length <= props.maxLength) {
|
|
19
|
-
emit('update:modelValue', newValue);
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
// Try to use external input-otp package if available
|
|
24
|
-
let OTPInput: any = null;
|
|
25
|
-
try {
|
|
26
|
-
OTPInput = defineAsyncComponent(() => import('input-otp'));
|
|
27
|
-
} catch (e) {
|
|
28
|
-
OTPInput = null;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
if (OTPInput) {
|
|
32
|
-
provide(InputOTPMaskContext, { masked: props.masked });
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const contextValue = computed(() => ({
|
|
36
|
-
value: props.modelValue,
|
|
37
|
-
onChange: handleChange,
|
|
38
|
-
maxLength: props.maxLength,
|
|
39
|
-
disabled: props.disabled,
|
|
40
|
-
masked: props.masked,
|
|
41
|
-
}));
|
|
42
|
-
|
|
43
|
-
if (!OTPInput) {
|
|
44
|
-
provide(InputOTPContext, contextValue.value);
|
|
45
|
-
provide(InputOTPMaskContext, { masked: props.masked });
|
|
46
|
-
}
|
|
47
|
-
</script>
|
|
48
|
-
<template>
|
|
49
|
-
<component
|
|
50
|
-
v-if="OTPInput"
|
|
51
|
-
:is="OTPInput"
|
|
52
|
-
data-slot="input-otp"
|
|
53
|
-
:container-class="cn('flex items-center gap-2 has-disabled:opacity-50', props.containerClass)"
|
|
54
|
-
:class="cn('disabled:cursor-not-allowed', props.class)"
|
|
55
|
-
:max-length="props.maxLength"
|
|
56
|
-
:value="props.modelValue"
|
|
57
|
-
:onChange="(val: string) => emit('update:modelValue', val)"
|
|
58
|
-
:disabled="props.disabled"
|
|
59
|
-
>
|
|
60
|
-
<slot />
|
|
61
|
-
</component>
|
|
62
|
-
<div
|
|
63
|
-
v-else
|
|
64
|
-
data-slot="input-otp"
|
|
65
|
-
:class="cn('flex items-center gap-2 has-disabled:opacity-50', props.containerClass)"
|
|
66
|
-
>
|
|
67
|
-
<slot />
|
|
68
|
-
</div>
|
|
69
|
-
</template>
|
package/src/ui/InputOTPGroup.vue
DELETED
package/src/ui/InputOTPSlot.vue
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
<script setup>
|
|
2
|
-
import { computed } from 'vue';
|
|
3
|
-
import { cn } from '@/lib/utils';
|
|
4
|
-
|
|
5
|
-
const props = defineProps({
|
|
6
|
-
index: Number,
|
|
7
|
-
char: String,
|
|
8
|
-
class: String,
|
|
9
|
-
disabled: Boolean,
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
const extDisplayChar = computed(() => {
|
|
13
|
-
return '';
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
const extIsActive = computed(() => {
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
const isActive = computed(() => {
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
const handleClick = () => {
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
const handleInput = (e) => {
|
|
26
|
-
const value = e.target.value;
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
</script>
|
|
30
|
-
|
|
31
|
-
<template>
|
|
32
|
-
<!-- Fallback context: input field mode -->
|
|
33
|
-
<div
|
|
34
|
-
data-slot="input-otp-slot"
|
|
35
|
-
:data-index="props.index"
|
|
36
|
-
:data-active="isActive"
|
|
37
|
-
:class="cn('data-[active=true]:border-ring data-[active=true]:ring-ring/50 border-input relative flex h-9 w-9 items-center justify-center border-y border-r text-sm bg-input-background transition-all outline-none first:rounded-l-md first:border-l last:rounded-r-md data-[active=true]:z-10 data-[active=true]:ring-[3px] cursor-text', props.class)"
|
|
38
|
-
@click="handleClick"
|
|
39
|
-
>
|
|
40
|
-
<input
|
|
41
|
-
ref="inputRef"
|
|
42
|
-
type="text"
|
|
43
|
-
inputmode="numeric"
|
|
44
|
-
pattern="[0-9]*"
|
|
45
|
-
maxlength="1"
|
|
46
|
-
:value="char"
|
|
47
|
-
@input="handleInput"
|
|
48
|
-
@keydown="handleKeydown"
|
|
49
|
-
@focus="isFocused = true"
|
|
50
|
-
@blur="isFocused = false"
|
|
51
|
-
class="absolute inset-0 w-full h-full bg-transparent border-0 outline-none text-center opacity-0 caret-transparent"
|
|
52
|
-
style="caret-color: transparent;"
|
|
53
|
-
/>
|
|
54
|
-
<div class="pointer-events-none select-none relative z-10 flex items-center justify-center">
|
|
55
|
-
<span v-if="char" class="text-foreground">{{ displayChar }}</span>
|
|
56
|
-
</div>
|
|
57
|
-
<div v-if="isActive && !char" class="pointer-events-none absolute inset-0 flex items-center justify-center z-20">
|
|
58
|
-
<div class="animate-caret-blink bg-foreground h-4 w-px duration-1000" />
|
|
59
|
-
</div>
|
|
60
|
-
</div>
|
|
61
|
-
</template>
|
package/src/ui/input-otp.vue
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import { computed, provide, defineAsyncComponent, useSlots } from 'vue';
|
|
3
|
-
import { cn } from '@/lib/utils';
|
|
4
|
-
// These would be your context keys (provide/inject)
|
|
5
|
-
const InputOTPMaskContext = Symbol('InputOTPMaskContext');
|
|
6
|
-
const FallbackInputOTPContext = Symbol('FallbackInputOTPContext');
|
|
7
|
-
|
|
8
|
-
const props = defineProps({
|
|
9
|
-
class: String,
|
|
10
|
-
containerClass: String,
|
|
11
|
-
maxLength: { type: Number, required: true },
|
|
12
|
-
modelValue: { type: String, default: '' },
|
|
13
|
-
disabled: { type: Boolean, default: false },
|
|
14
|
-
masked: { type: Boolean, default: false },
|
|
15
|
-
});
|
|
16
|
-
const emit = defineEmits(['update:modelValue']);
|
|
17
|
-
const slots = useSlots();
|
|
18
|
-
|
|
19
|
-
const handleChange = (newValue: string) => {
|
|
20
|
-
if (newValue.length <= props.maxLength) {
|
|
21
|
-
emit('update:modelValue', newValue);
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
import { OTPInput } from "input-otp";
|
|
26
|
-
|
|
27
|
-
const contextValue = computed(() => ({
|
|
28
|
-
value: props.modelValue,
|
|
29
|
-
onChange: handleChange,
|
|
30
|
-
maxLength: props.maxLength,
|
|
31
|
-
disabled: props.disabled,
|
|
32
|
-
masked: props.masked,
|
|
33
|
-
}));
|
|
34
|
-
|
|
35
|
-
</script>
|
|
36
|
-
<template>
|
|
37
|
-
<OTPInput
|
|
38
|
-
data-slot="input-otp"
|
|
39
|
-
:container-class="cn('flex items-center gap-2 has-disabled:opacity-50', props.containerClass)"
|
|
40
|
-
:class-name="cn('disabled:cursor-not-allowed', props.class)"
|
|
41
|
-
:maxlength="props.maxLength"
|
|
42
|
-
:value="props.modelValue"
|
|
43
|
-
:on-change="(val) => emit('update:modelValue', val)"
|
|
44
|
-
:disabled="props.disabled"
|
|
45
|
-
v-bind="props"
|
|
46
|
-
style="display: flex;"
|
|
47
|
-
>
|
|
48
|
-
<div class="flex items-center gap-2">
|
|
49
|
-
<slot />
|
|
50
|
-
</div>
|
|
51
|
-
</OTPInput>
|
|
52
|
-
</template>
|