aetherx-dt-ui 0.1.0

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 (33) hide show
  1. package/dist/cli/index.mjs +440 -0
  2. package/package.json +56 -0
  3. package/src/registry/components/badge/DtBadge.vue +94 -0
  4. package/src/registry/components/badge/index.ts +2 -0
  5. package/src/registry/components/button/DtButton.vue +176 -0
  6. package/src/registry/components/button/index.ts +2 -0
  7. package/src/registry/components/card/DtCard.vue +46 -0
  8. package/src/registry/components/card/DtCardContent.vue +15 -0
  9. package/src/registry/components/card/DtCardFooter.vue +17 -0
  10. package/src/registry/components/card/DtCardHeader.vue +31 -0
  11. package/src/registry/components/card/index.ts +4 -0
  12. package/src/registry/components/dialog/DtDialog.vue +41 -0
  13. package/src/registry/components/dialog/DtDialogContent.vue +140 -0
  14. package/src/registry/components/dialog/DtDialogFooter.vue +18 -0
  15. package/src/registry/components/dialog/DtDialogHeader.vue +32 -0
  16. package/src/registry/components/dialog/DtDialogTrigger.vue +20 -0
  17. package/src/registry/components/dialog/index.ts +5 -0
  18. package/src/registry/components/input/DtInput.vue +140 -0
  19. package/src/registry/components/input/index.ts +2 -0
  20. package/src/registry/components/select/DtSelect.vue +102 -0
  21. package/src/registry/components/select/DtSelectContent.vue +103 -0
  22. package/src/registry/components/select/DtSelectItem.vue +123 -0
  23. package/src/registry/components/select/DtSelectTrigger.vue +128 -0
  24. package/src/registry/components/select/index.ts +4 -0
  25. package/src/registry/docs/badge.md +171 -0
  26. package/src/registry/docs/button.md +184 -0
  27. package/src/registry/docs/card.md +199 -0
  28. package/src/registry/docs/dialog.md +282 -0
  29. package/src/registry/docs/input.md +168 -0
  30. package/src/registry/docs/select.md +346 -0
  31. package/src/registry/lib/utils.ts +4 -0
  32. package/src/registry/registry.json +52 -0
  33. package/src/registry/styles/base.css +143 -0
@@ -0,0 +1,176 @@
1
+ <script setup lang="ts">
2
+ import { computed } from 'vue'
3
+
4
+ export type ButtonVariant = 'default' | 'secondary' | 'outline' | 'ghost' | 'destructive' | 'link'
5
+ export type ButtonSize = 'sm' | 'default' | 'lg' | 'icon'
6
+
7
+ const props = withDefaults(defineProps<{
8
+ variant?: ButtonVariant
9
+ size?: ButtonSize
10
+ disabled?: boolean
11
+ loading?: boolean
12
+ }>(), {
13
+ variant: 'default',
14
+ size: 'default',
15
+ })
16
+
17
+ const classes = computed(() => [
18
+ 'dt-button',
19
+ `dt-button--${props.variant}`,
20
+ `dt-button--${props.size}`,
21
+ props.disabled && 'dt-button--disabled',
22
+ props.loading && 'dt-button--loading',
23
+ ].filter(Boolean))
24
+ </script>
25
+
26
+ <template>
27
+ <button
28
+ :class="classes"
29
+ :disabled="disabled || loading"
30
+ v-bind="$attrs"
31
+ >
32
+ <span v-if="loading" class="dt-button__spinner" aria-hidden="true" />
33
+ <span v-if="$slots['icon-left']" class="dt-button__icon dt-button__icon--left">
34
+ <slot name="icon-left" />
35
+ </span>
36
+ <slot />
37
+ <span v-if="$slots['icon-right']" class="dt-button__icon dt-button__icon--right">
38
+ <slot name="icon-right" />
39
+ </span>
40
+ </button>
41
+ </template>
42
+
43
+ <style scoped>
44
+ .dt-button {
45
+ display: inline-flex;
46
+ align-items: center;
47
+ justify-content: center;
48
+ gap: var(--dt-space-2);
49
+ font-weight: 500;
50
+ border-radius: var(--dt-radius-md);
51
+ transition: background-color var(--dt-transition-base),
52
+ border-color var(--dt-transition-base),
53
+ color var(--dt-transition-base),
54
+ box-shadow var(--dt-transition-base);
55
+ cursor: pointer;
56
+ border: 1px solid transparent;
57
+ font-family: inherit;
58
+ line-height: 1;
59
+ white-space: nowrap;
60
+ user-select: none;
61
+ }
62
+
63
+ /* Variants */
64
+ .dt-button--default {
65
+ background-color: var(--dt-primary);
66
+ color: var(--dt-primary-foreground);
67
+ }
68
+ .dt-button--default:hover {
69
+ background-color: var(--dt-primary-hover);
70
+ }
71
+
72
+ .dt-button--secondary {
73
+ background-color: var(--dt-secondary);
74
+ color: var(--dt-secondary-foreground);
75
+ }
76
+ .dt-button--secondary:hover {
77
+ background-color: var(--dt-secondary-hover);
78
+ }
79
+
80
+ .dt-button--outline {
81
+ border-color: var(--dt-border);
82
+ background-color: transparent;
83
+ color: var(--dt-foreground);
84
+ }
85
+ .dt-button--outline:hover {
86
+ background-color: var(--dt-accent);
87
+ border-color: var(--dt-border-hover);
88
+ }
89
+
90
+ .dt-button--ghost {
91
+ background-color: transparent;
92
+ color: var(--dt-foreground);
93
+ }
94
+ .dt-button--ghost:hover {
95
+ background-color: var(--dt-accent);
96
+ }
97
+
98
+ .dt-button--destructive {
99
+ background-color: var(--dt-destructive);
100
+ color: var(--dt-destructive-foreground);
101
+ }
102
+ .dt-button--destructive:hover {
103
+ background-color: var(--dt-destructive-hover);
104
+ }
105
+
106
+ .dt-button--link {
107
+ background-color: transparent;
108
+ color: var(--dt-primary);
109
+ text-decoration: underline;
110
+ text-underline-offset: 4px;
111
+ }
112
+ .dt-button--link:hover {
113
+ color: var(--dt-primary-hover);
114
+ }
115
+
116
+ /* Sizes */
117
+ .dt-button--sm {
118
+ height: 2rem;
119
+ padding: 0 0.75rem;
120
+ font-size: var(--dt-font-size-sm);
121
+ }
122
+ .dt-button--default {
123
+ height: 2.5rem;
124
+ padding: 0 1rem;
125
+ font-size: var(--dt-font-size-base);
126
+ }
127
+ .dt-button--lg {
128
+ height: 2.75rem;
129
+ padding: 0 1.5rem;
130
+ font-size: var(--dt-font-size-lg);
131
+ }
132
+ .dt-button--icon {
133
+ height: 2.5rem;
134
+ width: 2.5rem;
135
+ padding: 0;
136
+ }
137
+
138
+ /* States */
139
+ .dt-button--disabled {
140
+ opacity: 0.5;
141
+ pointer-events: none;
142
+ }
143
+
144
+ .dt-button--loading {
145
+ position: relative;
146
+ pointer-events: none;
147
+ }
148
+
149
+ .dt-button:focus-visible {
150
+ outline: 2px solid var(--dt-ring);
151
+ outline-offset: 2px;
152
+ }
153
+
154
+ /* Spinner */
155
+ .dt-button__spinner {
156
+ width: 1em;
157
+ height: 1em;
158
+ border: 2px solid currentColor;
159
+ border-right-color: transparent;
160
+ border-radius: var(--dt-radius-full);
161
+ animation: dt-spin 0.6s linear infinite;
162
+ }
163
+
164
+ .dt-button__icon {
165
+ display: inline-flex;
166
+ align-items: center;
167
+ justify-content: center;
168
+ flex-shrink: 0;
169
+ }
170
+
171
+ @keyframes dt-spin {
172
+ to {
173
+ transform: rotate(360deg);
174
+ }
175
+ }
176
+ </style>
@@ -0,0 +1,2 @@
1
+ export { default as DtButton } from './DtButton.vue'
2
+ export type { ButtonVariant, ButtonSize } from './DtButton.vue'
@@ -0,0 +1,46 @@
1
+ <script setup lang="ts">
2
+ import { computed } from 'vue'
3
+
4
+ const props = withDefaults(defineProps<{
5
+ bordered?: boolean
6
+ shadow?: boolean
7
+ padding?: boolean
8
+ }>(), {
9
+ bordered: true,
10
+ shadow: false,
11
+ padding: true,
12
+ })
13
+
14
+ const classes = computed(() => [
15
+ 'dt-card',
16
+ props.bordered && 'dt-card--bordered',
17
+ props.shadow && 'dt-card--shadow',
18
+ props.padding && 'dt-card--padding',
19
+ ].filter(Boolean))
20
+ </script>
21
+
22
+ <template>
23
+ <div :class="classes" v-bind="$attrs">
24
+ <slot />
25
+ </div>
26
+ </template>
27
+
28
+ <style scoped>
29
+ .dt-card {
30
+ background-color: var(--dt-background);
31
+ border-radius: var(--dt-radius-lg);
32
+ overflow: hidden;
33
+ }
34
+
35
+ .dt-card--bordered {
36
+ border: 1px solid var(--dt-border);
37
+ }
38
+
39
+ .dt-card--shadow {
40
+ box-shadow: var(--dt-shadow-md);
41
+ }
42
+
43
+ .dt-card--padding {
44
+ padding: var(--dt-space-6);
45
+ }
46
+ </style>
@@ -0,0 +1,15 @@
1
+ <script setup lang="ts">
2
+ </script>
3
+
4
+ <template>
5
+ <div class="dt-card-content" v-bind="$attrs">
6
+ <slot />
7
+ </div>
8
+ </template>
9
+
10
+ <style scoped>
11
+ .dt-card-content {
12
+ font-size: var(--dt-font-size-base);
13
+ color: var(--dt-foreground);
14
+ }
15
+ </style>
@@ -0,0 +1,17 @@
1
+ <script setup lang="ts">
2
+ </script>
3
+
4
+ <template>
5
+ <div class="dt-card-footer" v-bind="$attrs">
6
+ <slot />
7
+ </div>
8
+ </template>
9
+
10
+ <style scoped>
11
+ .dt-card-footer {
12
+ display: flex;
13
+ align-items: center;
14
+ gap: var(--dt-space-2);
15
+ padding-top: var(--dt-space-4);
16
+ }
17
+ </style>
@@ -0,0 +1,31 @@
1
+ <script setup lang="ts">
2
+ </script>
3
+
4
+ <template>
5
+ <div class="dt-card-header" v-bind="$attrs">
6
+ <slot />
7
+ </div>
8
+ </template>
9
+
10
+ <style scoped>
11
+ .dt-card-header {
12
+ display: flex;
13
+ flex-direction: column;
14
+ gap: var(--dt-space-1);
15
+ padding-bottom: var(--dt-space-4);
16
+ }
17
+
18
+ .dt-card-header :deep(h1),
19
+ .dt-card-header :deep(h2),
20
+ .dt-card-header :deep(h3),
21
+ .dt-card-header :deep(h4) {
22
+ font-weight: 600;
23
+ line-height: 1.25;
24
+ color: var(--dt-foreground);
25
+ }
26
+
27
+ .dt-card-header :deep(p) {
28
+ font-size: var(--dt-font-size-sm);
29
+ color: var(--dt-muted-foreground);
30
+ }
31
+ </style>
@@ -0,0 +1,4 @@
1
+ export { default as DtCard } from './DtCard.vue'
2
+ export { default as DtCardHeader } from './DtCardHeader.vue'
3
+ export { default as DtCardContent } from './DtCardContent.vue'
4
+ export { default as DtCardFooter } from './DtCardFooter.vue'
@@ -0,0 +1,41 @@
1
+ <script setup lang="ts">
2
+ import { provide, ref, computed, watch } from 'vue'
3
+
4
+ const props = withDefaults(defineProps<{
5
+ modelValue?: boolean
6
+ }>(), {
7
+ modelValue: undefined,
8
+ })
9
+
10
+ const emit = defineEmits<{
11
+ 'update:modelValue': [value: boolean]
12
+ }>()
13
+
14
+ const internalOpen = ref(false)
15
+
16
+ const isOpen = computed({
17
+ get: () => props.modelValue !== undefined ? props.modelValue : internalOpen.value,
18
+ set: (val: boolean) => {
19
+ internalOpen.value = val
20
+ emit('update:modelValue', val)
21
+ },
22
+ })
23
+
24
+ function open() {
25
+ isOpen.value = true
26
+ }
27
+
28
+ function close() {
29
+ isOpen.value = false
30
+ }
31
+
32
+ function toggle() {
33
+ isOpen.value = !isOpen.value
34
+ }
35
+
36
+ provide('dt-dialog', { isOpen, open, close, toggle })
37
+ </script>
38
+
39
+ <template>
40
+ <slot :open="isOpen" :toggle="toggle" :close="close" />
41
+ </template>
@@ -0,0 +1,140 @@
1
+ <script setup lang="ts">
2
+ import { inject, ref, watch, onMounted, onBeforeUnmount, nextTick, type Ref, type ComputedRef } from 'vue'
3
+
4
+ const dialog = inject<{
5
+ isOpen: ComputedRef<boolean>
6
+ close: () => void
7
+ }>('dt-dialog')!
8
+
9
+ const contentRef = ref<HTMLElement | null>(null)
10
+ const visible = ref(false)
11
+ const animating = ref(false)
12
+
13
+ // Focus trap
14
+ const previousActiveElement = ref<HTMLElement | null>(null)
15
+
16
+ function focusTrap(event: KeyboardEvent) {
17
+ if (event.key !== 'Tab' || !contentRef.value) return
18
+
19
+ const focusableElements = contentRef.value.querySelectorAll<HTMLElement>(
20
+ 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])'
21
+ )
22
+
23
+ if (focusableElements.length === 0) return
24
+
25
+ const first = focusableElements[0]
26
+ const last = focusableElements[focusableElements.length - 1]
27
+
28
+ if (event.shiftKey && document.activeElement === first) {
29
+ event.preventDefault()
30
+ last.focus()
31
+ } else if (!event.shiftKey && document.activeElement === last) {
32
+ event.preventDefault()
33
+ first.focus()
34
+ }
35
+ }
36
+
37
+ function onKeydown(event: KeyboardEvent) {
38
+ if (event.key === 'Escape') {
39
+ dialog.close()
40
+ }
41
+ focusTrap(event)
42
+ }
43
+
44
+ function onOverlayClick(event: MouseEvent) {
45
+ if (event.target === event.currentTarget) {
46
+ dialog.close()
47
+ }
48
+ }
49
+
50
+ watch(() => dialog.isOpen.value, async (open) => {
51
+ if (open) {
52
+ previousActiveElement.value = document.activeElement as HTMLElement
53
+ visible.value = true
54
+ document.body.style.overflow = 'hidden'
55
+ await nextTick()
56
+ animating.value = true
57
+ // Focus the first focusable element
58
+ const firstFocusable = contentRef.value?.querySelector<HTMLElement>(
59
+ 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])'
60
+ )
61
+ firstFocusable?.focus()
62
+ } else {
63
+ animating.value = false
64
+ document.body.style.overflow = ''
65
+ // Wait for exit animation
66
+ setTimeout(() => {
67
+ visible.value = false
68
+ previousActiveElement.value?.focus()
69
+ }, 200)
70
+ }
71
+ })
72
+
73
+ onBeforeUnmount(() => {
74
+ document.body.style.overflow = ''
75
+ })
76
+ </script>
77
+
78
+ <template>
79
+ <Teleport to="body">
80
+ <div
81
+ v-if="visible"
82
+ class="dt-dialog-overlay"
83
+ :class="{ 'dt-dialog-overlay--open': animating }"
84
+ @click="onOverlayClick"
85
+ @keydown="onKeydown"
86
+ >
87
+ <div
88
+ ref="contentRef"
89
+ class="dt-dialog-content"
90
+ :class="{ 'dt-dialog-content--open': animating }"
91
+ role="dialog"
92
+ aria-modal="true"
93
+ v-bind="$attrs"
94
+ >
95
+ <slot />
96
+ </div>
97
+ </div>
98
+ </Teleport>
99
+ </template>
100
+
101
+ <style scoped>
102
+ .dt-dialog-overlay {
103
+ position: fixed;
104
+ inset: 0;
105
+ z-index: var(--dt-z-overlay);
106
+ display: flex;
107
+ align-items: center;
108
+ justify-content: center;
109
+ padding: var(--dt-space-4);
110
+ background-color: rgb(0 0 0 / 0.4);
111
+ opacity: 0;
112
+ transition: opacity 0.2s ease;
113
+ }
114
+
115
+ .dt-dialog-overlay--open {
116
+ opacity: 1;
117
+ }
118
+
119
+ .dt-dialog-content {
120
+ position: relative;
121
+ z-index: var(--dt-z-modal);
122
+ width: 100%;
123
+ max-width: 28rem;
124
+ max-height: calc(100vh - 2rem);
125
+ overflow-y: auto;
126
+ background-color: var(--dt-background);
127
+ border: 1px solid var(--dt-border);
128
+ border-radius: var(--dt-radius-lg);
129
+ box-shadow: var(--dt-shadow-lg);
130
+ padding: var(--dt-space-6);
131
+ transform: scale(0.95) translateY(0.5rem);
132
+ opacity: 0;
133
+ transition: transform 0.2s ease, opacity 0.2s ease;
134
+ }
135
+
136
+ .dt-dialog-content--open {
137
+ transform: scale(1) translateY(0);
138
+ opacity: 1;
139
+ }
140
+ </style>
@@ -0,0 +1,18 @@
1
+ <script setup lang="ts">
2
+ </script>
3
+
4
+ <template>
5
+ <div class="dt-dialog-footer" v-bind="$attrs">
6
+ <slot />
7
+ </div>
8
+ </template>
9
+
10
+ <style scoped>
11
+ .dt-dialog-footer {
12
+ display: flex;
13
+ align-items: center;
14
+ justify-content: flex-end;
15
+ gap: var(--dt-space-2);
16
+ padding-top: var(--dt-space-4);
17
+ }
18
+ </style>
@@ -0,0 +1,32 @@
1
+ <script setup lang="ts">
2
+ </script>
3
+
4
+ <template>
5
+ <div class="dt-dialog-header" v-bind="$attrs">
6
+ <slot />
7
+ </div>
8
+ </template>
9
+
10
+ <style scoped>
11
+ .dt-dialog-header {
12
+ display: flex;
13
+ flex-direction: column;
14
+ gap: var(--dt-space-1);
15
+ padding-bottom: var(--dt-space-4);
16
+ }
17
+
18
+ .dt-dialog-header :deep(h1),
19
+ .dt-dialog-header :deep(h2),
20
+ .dt-dialog-header :deep(h3),
21
+ .dt-dialog-header :deep(h4) {
22
+ font-size: var(--dt-font-size-lg);
23
+ font-weight: 600;
24
+ line-height: 1.25;
25
+ color: var(--dt-foreground);
26
+ }
27
+
28
+ .dt-dialog-header :deep(p) {
29
+ font-size: var(--dt-font-size-sm);
30
+ color: var(--dt-muted-foreground);
31
+ }
32
+ </style>
@@ -0,0 +1,20 @@
1
+ <script setup lang="ts">
2
+ import { inject } from 'vue'
3
+
4
+ const dialog = inject<{
5
+ toggle: () => void
6
+ }>('dt-dialog')!
7
+ </script>
8
+
9
+ <template>
10
+ <span class="dt-dialog-trigger" @click="dialog.toggle()" v-bind="$attrs">
11
+ <slot />
12
+ </span>
13
+ </template>
14
+
15
+ <style scoped>
16
+ .dt-dialog-trigger {
17
+ display: inline-flex;
18
+ cursor: pointer;
19
+ }
20
+ </style>
@@ -0,0 +1,5 @@
1
+ export { default as DtDialog } from './DtDialog.vue'
2
+ export { default as DtDialogTrigger } from './DtDialogTrigger.vue'
3
+ export { default as DtDialogContent } from './DtDialogContent.vue'
4
+ export { default as DtDialogHeader } from './DtDialogHeader.vue'
5
+ export { default as DtDialogFooter } from './DtDialogFooter.vue'
@@ -0,0 +1,140 @@
1
+ <script setup lang="ts">
2
+ import { computed, useAttrs } from 'vue'
3
+
4
+ export type InputType = 'text' | 'email' | 'password' | 'number' | 'search' | 'tel' | 'url'
5
+
6
+ const props = withDefaults(defineProps<{
7
+ modelValue?: string | number
8
+ type?: InputType
9
+ placeholder?: string
10
+ disabled?: boolean
11
+ error?: string
12
+ hint?: string
13
+ id?: string
14
+ }>(), {
15
+ type: 'text',
16
+ })
17
+
18
+ const emit = defineEmits<{
19
+ 'update:modelValue': [value: string | number]
20
+ }>()
21
+
22
+ const attrs = useAttrs()
23
+
24
+ const inputId = computed(() => props.id || `dt-input-${Math.random().toString(36).slice(2, 9)}`)
25
+
26
+ const wrapperClasses = computed(() => [
27
+ 'dt-input-wrapper',
28
+ props.error && 'dt-input-wrapper--error',
29
+ props.disabled && 'dt-input-wrapper--disabled',
30
+ ].filter(Boolean))
31
+
32
+ const inputClasses = computed(() => [
33
+ 'dt-input',
34
+ props.error && 'dt-input--error',
35
+ ].filter(Boolean))
36
+
37
+ function onInput(event: Event) {
38
+ const target = event.target as HTMLInputElement
39
+ const value = props.type === 'number' ? Number(target.value) : target.value
40
+ emit('update:modelValue', value)
41
+ }
42
+ </script>
43
+
44
+ <template>
45
+ <div :class="wrapperClasses">
46
+ <label v-if="$slots.label" :for="inputId" class="dt-input__label">
47
+ <slot name="label" />
48
+ </label>
49
+ <input
50
+ :id="inputId"
51
+ :class="inputClasses"
52
+ :type="type"
53
+ :value="modelValue"
54
+ :placeholder="placeholder"
55
+ :disabled="disabled"
56
+ :aria-invalid="!!error"
57
+ :aria-describedby="error ? `${inputId}-error` : hint ? `${inputId}-hint` : undefined"
58
+ v-bind="attrs"
59
+ @input="onInput"
60
+ />
61
+ <p v-if="error" :id="`${inputId}-error`" class="dt-input__error" role="alert">
62
+ {{ error }}
63
+ </p>
64
+ <p v-else-if="hint" :id="`${inputId}-hint`" class="dt-input__hint">
65
+ {{ hint }}
66
+ </p>
67
+ </div>
68
+ </template>
69
+
70
+ <style scoped>
71
+ .dt-input-wrapper {
72
+ display: flex;
73
+ flex-direction: column;
74
+ gap: var(--dt-space-1);
75
+ width: 100%;
76
+ }
77
+
78
+ .dt-input__label {
79
+ font-size: var(--dt-font-size-sm);
80
+ font-weight: 500;
81
+ color: var(--dt-foreground);
82
+ }
83
+
84
+ .dt-input {
85
+ height: 2.5rem;
86
+ width: 100%;
87
+ padding: 0 0.75rem;
88
+ font-size: var(--dt-font-size-base);
89
+ font-family: inherit;
90
+ color: var(--dt-foreground);
91
+ background-color: var(--dt-background);
92
+ border: 1px solid var(--dt-border);
93
+ border-radius: var(--dt-radius-md);
94
+ transition: border-color var(--dt-transition-base),
95
+ box-shadow var(--dt-transition-base);
96
+ outline: none;
97
+ }
98
+
99
+ .dt-input::placeholder {
100
+ color: var(--dt-muted-foreground);
101
+ }
102
+
103
+ .dt-input:hover:not(:disabled) {
104
+ border-color: var(--dt-border-hover);
105
+ }
106
+
107
+ .dt-input:focus {
108
+ border-color: var(--dt-ring);
109
+ box-shadow: 0 0 0 2px color-mix(in srgb, var(--dt-ring) 25%, transparent);
110
+ }
111
+
112
+ .dt-input--error {
113
+ border-color: var(--dt-destructive);
114
+ }
115
+ .dt-input--error:focus {
116
+ border-color: var(--dt-destructive);
117
+ box-shadow: 0 0 0 2px color-mix(in srgb, var(--dt-destructive) 25%, transparent);
118
+ }
119
+
120
+ .dt-input:disabled {
121
+ opacity: 0.5;
122
+ cursor: not-allowed;
123
+ background-color: var(--dt-muted);
124
+ }
125
+
126
+ .dt-input__error {
127
+ font-size: var(--dt-font-size-xs);
128
+ color: var(--dt-destructive);
129
+ }
130
+
131
+ .dt-input__hint {
132
+ font-size: var(--dt-font-size-xs);
133
+ color: var(--dt-muted-foreground);
134
+ }
135
+
136
+ .dt-input-wrapper--disabled {
137
+ opacity: 0.5;
138
+ pointer-events: none;
139
+ }
140
+ </style>
@@ -0,0 +1,2 @@
1
+ export { default as DtInput } from './DtInput.vue'
2
+ export type { InputType } from './DtInput.vue'