@nexxtmove/ui 0.1.36 → 0.1.38
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/package.json
CHANGED
|
@@ -140,14 +140,14 @@ const transitionClasses = computed(() => {
|
|
|
140
140
|
<div
|
|
141
141
|
v-if="isOpen"
|
|
142
142
|
role="menu"
|
|
143
|
-
class="absolute top-full z-10 mt-2.5 min-w-full rounded-md border border-gray-200 bg-white"
|
|
143
|
+
class="absolute top-full z-10 mt-2.5 min-w-full rounded-md border border-gray-200 bg-white whitespace-nowrap"
|
|
144
144
|
:class="placement === 'right' ? 'right-0' : 'left-0'"
|
|
145
145
|
>
|
|
146
146
|
<button
|
|
147
147
|
v-for="option in options"
|
|
148
148
|
:key="option.label"
|
|
149
149
|
role="menuitem"
|
|
150
|
-
class="flex w-full min-w-42 cursor-pointer items-center gap-2 px-4 py-2 text-left text-sm text-gray-700 transition-colors duration-200 hover:bg-gray-100 hover:text-purple-600 focus:bg-gray-100 focus:outline-none"
|
|
150
|
+
class="flex w-full min-w-42 cursor-pointer items-center gap-2 px-4 py-2 text-left text-sm whitespace-nowrap text-gray-700 transition-colors duration-200 hover:bg-gray-100 hover:text-purple-600 focus:bg-gray-100 focus:outline-none"
|
|
151
151
|
@click="handleOptionClick(option.action)"
|
|
152
152
|
>
|
|
153
153
|
<NexxtIcon v-if="option.icon" :name="option.icon" aria-hidden="true" />
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { ref, computed } from 'vue'
|
|
3
2
|
import Icon from '../Icon/Icon.vue'
|
|
4
3
|
|
|
5
4
|
const generateId = () => 'input-field-' + Math.random().toString(36).slice(2, 10)
|
|
6
|
-
const inputId =
|
|
5
|
+
const inputId = generateId()
|
|
7
6
|
|
|
8
7
|
defineOptions({
|
|
9
8
|
name: 'NexxtInputField',
|
|
@@ -14,71 +13,57 @@ interface NexxtInputFieldProps {
|
|
|
14
13
|
label?: string
|
|
15
14
|
error?: boolean
|
|
16
15
|
errorMessage?: string
|
|
17
|
-
focused?: boolean
|
|
18
16
|
leftIcon?: InstanceType<typeof Icon>['name']
|
|
19
17
|
rightIcon?: InstanceType<typeof Icon>['name']
|
|
20
18
|
}
|
|
21
19
|
|
|
22
|
-
|
|
20
|
+
defineProps<NexxtInputFieldProps>()
|
|
23
21
|
|
|
24
|
-
// ✅ Correct usage
|
|
25
22
|
const modelValue = defineModel<string>()
|
|
26
|
-
|
|
27
|
-
const isFocused = ref(false)
|
|
28
|
-
|
|
29
|
-
const wrapperClasses = computed(() => {
|
|
30
|
-
if (props.error) {
|
|
31
|
-
return 'border-brick-400'
|
|
32
|
-
}
|
|
33
|
-
if (props.focused || isFocused.value) {
|
|
34
|
-
return 'border-cornflower-blue-500'
|
|
35
|
-
}
|
|
36
|
-
return 'border-gray-200'
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
const onFocus = () => {
|
|
40
|
-
isFocused.value = true
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const onBlur = () => {
|
|
44
|
-
isFocused.value = false
|
|
45
|
-
}
|
|
46
23
|
</script>
|
|
47
24
|
|
|
48
25
|
<template>
|
|
49
|
-
<div class="flex
|
|
26
|
+
<div class="inline-flex flex-col gap-1">
|
|
50
27
|
<label
|
|
51
|
-
v-if="
|
|
28
|
+
v-if="label"
|
|
52
29
|
class="text-color-gray-700 justify-start body-normal text-sm"
|
|
53
30
|
:for="inputId"
|
|
54
31
|
>
|
|
55
|
-
{{
|
|
32
|
+
{{ label }}
|
|
56
33
|
</label>
|
|
57
34
|
|
|
58
35
|
<div
|
|
59
|
-
class="flex items-center gap-2 rounded-lg
|
|
60
|
-
:class="
|
|
36
|
+
class="flex items-center gap-2 rounded-lg px-3 ring transition-colors ease-out focus-within:ring-cornflower-blue-500"
|
|
37
|
+
:class="error ? 'ring-brick-400' : 'ring-gray-200'"
|
|
61
38
|
>
|
|
62
|
-
<span v-if="
|
|
63
|
-
<Icon :name="
|
|
39
|
+
<span v-if="leftIcon" class="flex items-center">
|
|
40
|
+
<Icon :name="leftIcon" />
|
|
64
41
|
</span>
|
|
65
42
|
|
|
66
43
|
<input
|
|
67
44
|
:id="inputId"
|
|
68
45
|
v-model="modelValue"
|
|
69
|
-
:placeholder="
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
class="w-full bg-transparent text-sm text-gray-900 placeholder-gray-400 focus:outline-none"
|
|
46
|
+
:placeholder="placeholder"
|
|
47
|
+
v-bind="$attrs"
|
|
48
|
+
class="h-10 min-w-60 bg-transparent text-sm text-gray-900 placeholder-gray-400 focus:outline-none"
|
|
73
49
|
/>
|
|
74
50
|
|
|
75
|
-
<span v-if="
|
|
76
|
-
<Icon :name="
|
|
51
|
+
<span v-if="rightIcon" class="flex items-center">
|
|
52
|
+
<Icon :name="rightIcon" />
|
|
77
53
|
</span>
|
|
78
54
|
</div>
|
|
79
55
|
|
|
80
|
-
<
|
|
81
|
-
|
|
82
|
-
|
|
56
|
+
<Transition
|
|
57
|
+
enter-active-class="transition-all duration-200 ease-out"
|
|
58
|
+
enter-from-class="opacity-0 -translate-y-1"
|
|
59
|
+
enter-to-class="opacity-100 translate-y-0"
|
|
60
|
+
leave-active-class="transition-all duration-150 ease-in"
|
|
61
|
+
leave-from-class="opacity-100 translate-y-0"
|
|
62
|
+
leave-to-class="opacity-0 -translate-y-1"
|
|
63
|
+
>
|
|
64
|
+
<p v-if="error && errorMessage" class="text-sm text-brick-400">
|
|
65
|
+
{{ errorMessage }}
|
|
66
|
+
</p>
|
|
67
|
+
</Transition>
|
|
83
68
|
</div>
|
|
84
69
|
</template>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<script lang="ts" setup generic="TKey extends string">
|
|
1
|
+
<script lang="ts" setup generic="TKey extends string, TRow extends Record<TKey, unknown>">
|
|
2
2
|
import { computed, ref } from 'vue'
|
|
3
3
|
import Icon from '../Icon/Icon.vue'
|
|
4
4
|
import Checkbox from '../Checkbox/Checkbox.vue'
|
|
@@ -10,9 +10,12 @@ export interface TableColumn<K extends string = string> {
|
|
|
10
10
|
width?: string
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
export interface NexxtTableProps<
|
|
13
|
+
export interface NexxtTableProps<
|
|
14
|
+
TKey extends string = string,
|
|
15
|
+
TRow extends Record<TKey, unknown> = Record<TKey, unknown>,
|
|
16
|
+
> {
|
|
14
17
|
columns: TableColumn<TKey>[]
|
|
15
|
-
rows:
|
|
18
|
+
rows: TRow[]
|
|
16
19
|
selectable?: boolean
|
|
17
20
|
}
|
|
18
21
|
|
|
@@ -20,12 +23,12 @@ const INTERACTIVE = ['a', 'button', 'input', 'select', 'textarea', 'label']
|
|
|
20
23
|
|
|
21
24
|
defineOptions({ name: 'NexxtTable' })
|
|
22
25
|
|
|
23
|
-
const props = defineProps<NexxtTableProps<TKey>>()
|
|
26
|
+
const props = defineProps<NexxtTableProps<TKey, TRow>>()
|
|
24
27
|
const emit = defineEmits<{
|
|
25
|
-
'row-click': [row:
|
|
28
|
+
'row-click': [row: TRow]
|
|
26
29
|
}>()
|
|
27
30
|
|
|
28
|
-
const selected = defineModel<
|
|
31
|
+
const selected = defineModel<TRow[]>({ default: () => [] })
|
|
29
32
|
const sortKey = defineModel<TKey>('sortKey')
|
|
30
33
|
const sortDirection = defineModel<'asc' | 'desc'>('sortDirection', { default: 'asc' })
|
|
31
34
|
|
|
@@ -38,13 +41,13 @@ const someSelected = computed(
|
|
|
38
41
|
() => selected.value.length > 0 && selected.value.length < props.rows.length,
|
|
39
42
|
)
|
|
40
43
|
|
|
41
|
-
const isRowSelected = (row:
|
|
44
|
+
const isRowSelected = (row: TRow) => selected.value.includes(row)
|
|
42
45
|
|
|
43
46
|
const toggleAll = () => {
|
|
44
47
|
selected.value = allSelected.value ? [] : [...props.rows]
|
|
45
48
|
}
|
|
46
49
|
|
|
47
|
-
const toggleRow = (row:
|
|
50
|
+
const toggleRow = (row: TRow) => {
|
|
48
51
|
selected.value = isRowSelected(row)
|
|
49
52
|
? selected.value.filter((r) => r !== row)
|
|
50
53
|
: [...selected.value, row]
|
|
@@ -84,6 +87,8 @@ const getRowRoundedClass = (rowIndex: number) => {
|
|
|
84
87
|
return ''
|
|
85
88
|
}
|
|
86
89
|
|
|
90
|
+
const rowValue = (row: TRow, key: TKey) => (row as Record<TKey, unknown>)[key]
|
|
91
|
+
|
|
87
92
|
const handleRowKeydown = (event: KeyboardEvent, rowIndex: number) => {
|
|
88
93
|
if (event.key === 'ArrowDown') {
|
|
89
94
|
event.preventDefault()
|
|
@@ -210,8 +215,8 @@ const handleRowKeydown = (event: KeyboardEvent, rowIndex: number) => {
|
|
|
210
215
|
role="gridcell"
|
|
211
216
|
:aria-colindex="colIndex + (selectable ? 2 : 1)"
|
|
212
217
|
>
|
|
213
|
-
<slot :name="`cell-${column.key}`" :row="row" :value="row
|
|
214
|
-
{{ row
|
|
218
|
+
<slot :name="`cell-${column.key}`" :row="row" :value="rowValue(row, column.key)">
|
|
219
|
+
{{ rowValue(row, column.key) }}
|
|
215
220
|
</slot>
|
|
216
221
|
</div>
|
|
217
222
|
</div>
|
package/src/components.json
CHANGED