@polymarbot/nuxt-layer-shadcn-ui 0.6.3 → 0.7.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.
- package/app/components/ui/DataTable/index.stories.ts +249 -154
- package/app/components/ui/DataTable/index.vue +94 -65
- package/app/components/ui/DataTable/types.ts +2 -0
- package/app/components/ui/DatePicker/index.stories.ts +1 -1
- package/app/components/ui/DatePicker/index.vue +1 -1
- package/app/components/ui/DateRangePicker/index.stories.ts +2 -2
- package/app/components/ui/DateRangePicker/index.vue +2 -2
- package/app/components/ui/InfiniteDataTable/en.json +6 -0
- package/app/components/ui/InfiniteDataTable/index.stories.ts +165 -0
- package/app/components/ui/InfiniteDataTable/index.vue +239 -0
- package/app/components/ui/InfiniteDataTable/types.ts +35 -0
- package/app/components/ui/InputRange/index.stories.ts +2 -2
- package/app/components/ui/InputRange/index.vue +2 -2
- package/app/components/ui/SearchSelect/index.vue +4 -4
- package/app/components/ui/Select/index.stories.ts +10 -0
- package/app/components/ui/Select/index.vue +10 -3
- package/app/components/ui/Select/types.ts +2 -0
- package/i18n/messages/ar.json +6 -0
- package/i18n/messages/de.json +6 -0
- package/i18n/messages/en.json +6 -0
- package/i18n/messages/es.json +6 -0
- package/i18n/messages/fr.json +6 -0
- package/i18n/messages/hi.json +6 -0
- package/i18n/messages/id.json +6 -0
- package/i18n/messages/it.json +6 -0
- package/i18n/messages/ja.json +6 -0
- package/i18n/messages/ko.json +6 -0
- package/i18n/messages/nl.json +6 -0
- package/i18n/messages/pl.json +6 -0
- package/i18n/messages/pt.json +6 -0
- package/i18n/messages/ru.json +6 -0
- package/i18n/messages/th.json +6 -0
- package/i18n/messages/tr.json +6 -0
- package/i18n/messages/vi.json +6 -0
- package/i18n/messages/zh-CN.json +6 -0
- package/i18n/messages/zh-TW.json +6 -0
- package/package.json +2 -2
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
<script setup lang="ts" generic="TData extends Record<string, any>">
|
|
2
|
+
import type { InfiniteDataTableFetchParams, InfiniteDataTableProps } from './types'
|
|
3
|
+
|
|
4
|
+
const props = withDefaults(defineProps<InfiniteDataTableProps<TData>>(), {
|
|
5
|
+
columns: () => [],
|
|
6
|
+
fetchMethod: undefined,
|
|
7
|
+
autoFetch: true,
|
|
8
|
+
filters: undefined,
|
|
9
|
+
pageSize: 30,
|
|
10
|
+
height: undefined,
|
|
11
|
+
clickable: false,
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
const emit = defineEmits<{
|
|
15
|
+
'update:filters': [filters: Record<string, any>]
|
|
16
|
+
'rowClick': [row: TData, index: number, event: MouseEvent]
|
|
17
|
+
}>()
|
|
18
|
+
|
|
19
|
+
const T = useTranslations('components.ui.InfiniteDataTable')
|
|
20
|
+
|
|
21
|
+
// -- Internal state --
|
|
22
|
+
|
|
23
|
+
const loading = ref(false)
|
|
24
|
+
const internalData = ref<TData[]>([]) as Ref<TData[]>
|
|
25
|
+
const next = ref<string | undefined>(undefined)
|
|
26
|
+
const hasMore = ref(true)
|
|
27
|
+
const total = ref<number | undefined>(undefined)
|
|
28
|
+
const requestVersion = ref(0)
|
|
29
|
+
|
|
30
|
+
const sortState = ref<{ sortBy: string | null, sortOrder: number | null }>({
|
|
31
|
+
sortBy: props.filters?.sortBy ? String(props.filters.sortBy) : null,
|
|
32
|
+
sortOrder: props.filters?.sortOrder ? Number(props.filters.sortOrder) : null,
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
const isInitialLoad = computed(() => loading.value && internalData.value.length === 0)
|
|
36
|
+
|
|
37
|
+
// -- IntersectionObserver root: only when internal scroll is active --
|
|
38
|
+
|
|
39
|
+
const dataTableRef = ref<{ scrollEl?: HTMLElement } | null>(null)
|
|
40
|
+
const intersectionOptions = computed<IntersectionObserverInit | undefined>(() => { // eslint-disable-line no-undef
|
|
41
|
+
if (!props.height) return undefined
|
|
42
|
+
const root = dataTableRef.value?.scrollEl
|
|
43
|
+
return root ? { root } : undefined
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
// -- Helpers --
|
|
47
|
+
|
|
48
|
+
function getFilters (): Record<string, any> {
|
|
49
|
+
return {
|
|
50
|
+
...(props.filters ?? {}),
|
|
51
|
+
sortBy: sortState.value.sortBy,
|
|
52
|
+
sortOrder: sortState.value.sortOrder,
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function buildFetchParams (): InfiniteDataTableFetchParams {
|
|
57
|
+
return {
|
|
58
|
+
...getFilters(),
|
|
59
|
+
next: next.value,
|
|
60
|
+
limit: props.pageSize,
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function resetState () {
|
|
65
|
+
internalData.value = []
|
|
66
|
+
next.value = undefined
|
|
67
|
+
hasMore.value = true
|
|
68
|
+
total.value = undefined
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// -- Loading --
|
|
72
|
+
|
|
73
|
+
async function loadMore () {
|
|
74
|
+
if (!props.fetchMethod) return
|
|
75
|
+
if (loading.value || !hasMore.value) return
|
|
76
|
+
|
|
77
|
+
const currentVersion = ++requestVersion.value
|
|
78
|
+
loading.value = true
|
|
79
|
+
try {
|
|
80
|
+
const result = await props.fetchMethod(buildFetchParams())
|
|
81
|
+
if (currentVersion !== requestVersion.value) return
|
|
82
|
+
|
|
83
|
+
internalData.value = [ ...internalData.value, ...result.items ]
|
|
84
|
+
if (result.total != null) total.value = result.total
|
|
85
|
+
next.value = result.next
|
|
86
|
+
hasMore.value = !!result.next
|
|
87
|
+
} catch (error) {
|
|
88
|
+
if (currentVersion !== requestVersion.value) return
|
|
89
|
+
console.error('InfiniteDataTable loadMore failed:', error)
|
|
90
|
+
} finally {
|
|
91
|
+
if (currentVersion === requestVersion.value) loading.value = false
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async function refresh () {
|
|
96
|
+
resetState()
|
|
97
|
+
emit('update:filters', getFilters())
|
|
98
|
+
await loadMore()
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function scrollToTop () {
|
|
102
|
+
const el = dataTableRef.value?.scrollEl
|
|
103
|
+
if (!el) return
|
|
104
|
+
if (el.scrollHeight > el.clientHeight) {
|
|
105
|
+
el.scrollTo({ top: 0, behavior: 'smooth' })
|
|
106
|
+
} else {
|
|
107
|
+
el.scrollIntoView({ behavior: 'smooth', block: 'start' })
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// -- Sort: incremental loading requires a full reset on sort change --
|
|
112
|
+
|
|
113
|
+
let sortUpdatePending = false
|
|
114
|
+
|
|
115
|
+
function onSortByUpdate (value: string | null) {
|
|
116
|
+
sortState.value.sortBy = value
|
|
117
|
+
scheduleAfterSort()
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function onSortOrderUpdate (value: number | null) {
|
|
121
|
+
sortState.value.sortOrder = value
|
|
122
|
+
scheduleAfterSort()
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function scheduleAfterSort () {
|
|
126
|
+
if (sortUpdatePending) return
|
|
127
|
+
sortUpdatePending = true
|
|
128
|
+
nextTick(() => {
|
|
129
|
+
sortUpdatePending = false
|
|
130
|
+
refresh()
|
|
131
|
+
})
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// -- External filters: any change resets and reloads --
|
|
135
|
+
|
|
136
|
+
watch(() => props.filters, (newVal, oldVal) => {
|
|
137
|
+
if (JSON.stringify(newVal) === JSON.stringify(oldVal)) return
|
|
138
|
+
refresh()
|
|
139
|
+
}, { deep: true })
|
|
140
|
+
|
|
141
|
+
// -- Expose --
|
|
142
|
+
|
|
143
|
+
defineExpose({
|
|
144
|
+
refresh,
|
|
145
|
+
loadMore,
|
|
146
|
+
scrollToTop,
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
// -- Lifecycle --
|
|
150
|
+
|
|
151
|
+
onMounted(() => {
|
|
152
|
+
emit('update:filters', getFilters())
|
|
153
|
+
if (props.autoFetch) loadMore()
|
|
154
|
+
})
|
|
155
|
+
</script>
|
|
156
|
+
|
|
157
|
+
<template>
|
|
158
|
+
<DataTable
|
|
159
|
+
ref="dataTableRef"
|
|
160
|
+
:data="internalData"
|
|
161
|
+
:columns
|
|
162
|
+
:height
|
|
163
|
+
:loading="isInitialLoad"
|
|
164
|
+
:clickable
|
|
165
|
+
:sortBy="sortState.sortBy"
|
|
166
|
+
:sortOrder="sortState.sortOrder"
|
|
167
|
+
@update:sortBy="onSortByUpdate"
|
|
168
|
+
@update:sortOrder="onSortOrderUpdate"
|
|
169
|
+
@rowClick="(row, i, e) => emit('rowClick', row as TData, i, e)"
|
|
170
|
+
>
|
|
171
|
+
<template
|
|
172
|
+
v-for="name in Object.keys($slots).filter(n => n !== 'bodyEnd' && n !== 'footer')"
|
|
173
|
+
:key="name"
|
|
174
|
+
#[name]="slotData"
|
|
175
|
+
>
|
|
176
|
+
<slot
|
|
177
|
+
:name="name"
|
|
178
|
+
v-bind="slotData ?? {}"
|
|
179
|
+
/>
|
|
180
|
+
</template>
|
|
181
|
+
|
|
182
|
+
<template
|
|
183
|
+
v-if="hasMore || internalData.length > 0"
|
|
184
|
+
#bodyEnd
|
|
185
|
+
>
|
|
186
|
+
<div
|
|
187
|
+
v-if="!hasMore"
|
|
188
|
+
class="py-2 text-xs text-muted-foreground text-center"
|
|
189
|
+
>
|
|
190
|
+
{{ T('allLoaded') }}
|
|
191
|
+
</div>
|
|
192
|
+
<EffectIntersectionChecker
|
|
193
|
+
v-else-if="!isInitialLoad"
|
|
194
|
+
:disabled="loading"
|
|
195
|
+
:options="intersectionOptions"
|
|
196
|
+
class="py-2 flex items-center justify-center"
|
|
197
|
+
@show="loadMore"
|
|
198
|
+
>
|
|
199
|
+
<Icon
|
|
200
|
+
name="loader-circle"
|
|
201
|
+
class="size-4 animate-spin text-muted-foreground"
|
|
202
|
+
/>
|
|
203
|
+
</EffectIntersectionChecker>
|
|
204
|
+
</template>
|
|
205
|
+
|
|
206
|
+
<template #footer>
|
|
207
|
+
<slot name="footer">
|
|
208
|
+
<div class="gap-2 text-xs flex items-center justify-between">
|
|
209
|
+
<div class="gap-2 flex items-center">
|
|
210
|
+
<Tooltip :text="T('scrollToTop')">
|
|
211
|
+
<Button
|
|
212
|
+
variant="ghost"
|
|
213
|
+
size="icon-sm"
|
|
214
|
+
icon="arrow-up-to-line"
|
|
215
|
+
:disabled="loading || internalData.length === 0"
|
|
216
|
+
@click="scrollToTop"
|
|
217
|
+
/>
|
|
218
|
+
</Tooltip>
|
|
219
|
+
<Tooltip :text="T('refresh')">
|
|
220
|
+
<Button
|
|
221
|
+
variant="ghost"
|
|
222
|
+
size="icon-sm"
|
|
223
|
+
icon="rotate-cw"
|
|
224
|
+
:disabled="loading"
|
|
225
|
+
@click="refresh"
|
|
226
|
+
/>
|
|
227
|
+
</Tooltip>
|
|
228
|
+
</div>
|
|
229
|
+
<span
|
|
230
|
+
v-if="total != null"
|
|
231
|
+
class="text-muted-foreground"
|
|
232
|
+
>
|
|
233
|
+
{{ T('count', { loaded: internalData.length, total }) }}
|
|
234
|
+
</span>
|
|
235
|
+
</div>
|
|
236
|
+
</slot>
|
|
237
|
+
</template>
|
|
238
|
+
</DataTable>
|
|
239
|
+
</template>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { DataTableColumn } from '../DataTable/types'
|
|
2
|
+
|
|
3
|
+
export interface InfiniteDataTableFetchParams {
|
|
4
|
+
/** Opaque token returned by the previous page; absent on the first page */
|
|
5
|
+
next?: string
|
|
6
|
+
/** Page size requested */
|
|
7
|
+
limit: number
|
|
8
|
+
/** Filter / sort fields are spread onto the params object */
|
|
9
|
+
[key: string]: any
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface InfiniteDataTableFetchResult<T = Record<string, any>> {
|
|
13
|
+
items: T[]
|
|
14
|
+
/** Token for the next page; absent signals "no more" */
|
|
15
|
+
next?: string
|
|
16
|
+
/** Optional total count */
|
|
17
|
+
total?: number
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface InfiniteDataTableProps<T = Record<string, any>> {
|
|
21
|
+
/** Column definitions */
|
|
22
|
+
columns?: DataTableColumn[]
|
|
23
|
+
/** Async function to fetch a page of rows */
|
|
24
|
+
fetchMethod?: (params: InfiniteDataTableFetchParams) => Promise<InfiniteDataTableFetchResult<T>>
|
|
25
|
+
/** Whether to fetch the first page on mount (default: true) */
|
|
26
|
+
autoFetch?: boolean
|
|
27
|
+
/** External filter state — changing this resets and reloads */
|
|
28
|
+
filters?: Record<string, any>
|
|
29
|
+
/** Number of rows per page (default: 30) */
|
|
30
|
+
pageSize?: number
|
|
31
|
+
/** Fixed height enabling internal vertical scroll (e.g. '400px') */
|
|
32
|
+
height?: string
|
|
33
|
+
/** Whether rows are clickable (shows pointer cursor and pairs with `@rowClick`) */
|
|
34
|
+
clickable?: boolean
|
|
35
|
+
}
|
|
@@ -38,7 +38,7 @@ const end = computed({
|
|
|
38
38
|
v-bind="$attrs"
|
|
39
39
|
:min="min"
|
|
40
40
|
:max="end ?? max"
|
|
41
|
-
:placeholder="startPlaceholder
|
|
41
|
+
:placeholder="startPlaceholder || T('startPlaceholder')"
|
|
42
42
|
fluid
|
|
43
43
|
/>
|
|
44
44
|
<span class="leading-0 text-muted-foreground">
|
|
@@ -49,7 +49,7 @@ const end = computed({
|
|
|
49
49
|
v-bind="$attrs"
|
|
50
50
|
:min="start ?? min"
|
|
51
51
|
:max="max"
|
|
52
|
-
:placeholder="endPlaceholder
|
|
52
|
+
:placeholder="endPlaceholder || T('endPlaceholder')"
|
|
53
53
|
fluid
|
|
54
54
|
/>
|
|
55
55
|
</div>
|
|
@@ -135,8 +135,8 @@ function handleSearch (value: string) {
|
|
|
135
135
|
// -- Empty text --
|
|
136
136
|
|
|
137
137
|
const computedEmptyText = computed(() => {
|
|
138
|
-
if (keyword.value) return props.searchEmptyText
|
|
139
|
-
return props.emptyText
|
|
138
|
+
if (keyword.value) return props.searchEmptyText || T('noSearchItems')
|
|
139
|
+
return props.emptyText || T('noItems')
|
|
140
140
|
})
|
|
141
141
|
|
|
142
142
|
// -- Popover open/close --
|
|
@@ -188,9 +188,10 @@ defineExpose({ refresh: resetAndLoad })
|
|
|
188
188
|
:options="displayedOptions"
|
|
189
189
|
:filter="filterFunction"
|
|
190
190
|
:placeholder="placeholder"
|
|
191
|
-
:disabled="disabled"
|
|
192
191
|
:searchPlaceholder="searchPlaceholder"
|
|
193
192
|
:emptyText="computedEmptyText"
|
|
193
|
+
:disabled="disabled"
|
|
194
|
+
:loading="isLoading"
|
|
194
195
|
@search="handleSearch"
|
|
195
196
|
@open="handleOpen"
|
|
196
197
|
@close="handleClose"
|
|
@@ -220,7 +221,6 @@ defineExpose({ refresh: resetAndLoad })
|
|
|
220
221
|
<EffectIntersectionChecker
|
|
221
222
|
v-if="hasMore"
|
|
222
223
|
:disabled="isLoading"
|
|
223
|
-
bao
|
|
224
224
|
class="py-2 flex items-center justify-center"
|
|
225
225
|
@show="loadMore"
|
|
226
226
|
>
|
|
@@ -36,6 +36,7 @@ const meta = {
|
|
|
36
36
|
argTypes: {
|
|
37
37
|
placeholder: { control: 'text' },
|
|
38
38
|
disabled: { control: 'boolean' },
|
|
39
|
+
loading: { control: 'boolean' },
|
|
39
40
|
filter: { control: 'boolean' },
|
|
40
41
|
multiple: { control: 'boolean' },
|
|
41
42
|
searchPlaceholder: { control: 'text' },
|
|
@@ -44,6 +45,7 @@ const meta = {
|
|
|
44
45
|
args: {
|
|
45
46
|
placeholder: 'Select an option',
|
|
46
47
|
disabled: false,
|
|
48
|
+
loading: false,
|
|
47
49
|
filter: false,
|
|
48
50
|
multiple: false,
|
|
49
51
|
searchPlaceholder: '',
|
|
@@ -277,6 +279,14 @@ export const Disabled: Story = {
|
|
|
277
279
|
}),
|
|
278
280
|
}
|
|
279
281
|
|
|
282
|
+
export const Loading: Story = {
|
|
283
|
+
parameters: noControls,
|
|
284
|
+
args: {
|
|
285
|
+
loading: true,
|
|
286
|
+
placeholder: 'Loading options',
|
|
287
|
+
},
|
|
288
|
+
}
|
|
289
|
+
|
|
280
290
|
export const EventHandling: Story = {
|
|
281
291
|
parameters: noControls,
|
|
282
292
|
render: () => ({
|
|
@@ -29,6 +29,7 @@ const props = withDefaults(defineProps<SelectProps<TValue, TMeta>>(), {
|
|
|
29
29
|
modelValue: undefined,
|
|
30
30
|
placeholder: undefined,
|
|
31
31
|
disabled: false,
|
|
32
|
+
loading: false,
|
|
32
33
|
filter: false,
|
|
33
34
|
searchPlaceholder: undefined,
|
|
34
35
|
emptyText: undefined,
|
|
@@ -188,7 +189,7 @@ function handleClear (event: MouseEvent) {
|
|
|
188
189
|
v-else
|
|
189
190
|
class="text-muted-foreground"
|
|
190
191
|
>
|
|
191
|
-
{{ placeholder
|
|
192
|
+
{{ placeholder || T('placeholder') }}
|
|
192
193
|
</span>
|
|
193
194
|
</span>
|
|
194
195
|
<InputGroupAddon
|
|
@@ -205,6 +206,12 @@ function handleClear (event: MouseEvent) {
|
|
|
205
206
|
</InputGroupAddon>
|
|
206
207
|
<InputGroupAddon align="inline-end">
|
|
207
208
|
<Icon
|
|
209
|
+
v-if="loading"
|
|
210
|
+
name="loader-circle"
|
|
211
|
+
class="size-4 animate-spin opacity-50"
|
|
212
|
+
/>
|
|
213
|
+
<Icon
|
|
214
|
+
v-else
|
|
208
215
|
name="chevron-down"
|
|
209
216
|
class="size-4 opacity-50"
|
|
210
217
|
/>
|
|
@@ -221,11 +228,11 @@ function handleClear (event: MouseEvent) {
|
|
|
221
228
|
>
|
|
222
229
|
<CommandInput
|
|
223
230
|
v-if="!!filter"
|
|
224
|
-
:placeholder="searchPlaceholder
|
|
231
|
+
:placeholder="searchPlaceholder || T('searchPlaceholder')"
|
|
225
232
|
/>
|
|
226
233
|
<CommandList>
|
|
227
234
|
<CommandEmpty>
|
|
228
|
-
{{ emptyText
|
|
235
|
+
{{ emptyText || T('noItems') }}
|
|
229
236
|
</CommandEmpty>
|
|
230
237
|
|
|
231
238
|
<template
|
|
@@ -13,6 +13,8 @@ export type SelectBaseProps<V extends string | number = string, M = unknown> = {
|
|
|
13
13
|
options?: SelectOption<V, M>[]
|
|
14
14
|
placeholder?: string
|
|
15
15
|
disabled?: boolean
|
|
16
|
+
/** Show a spinner in place of the chevron */
|
|
17
|
+
loading?: boolean
|
|
16
18
|
/** true: enable client-side label filter; function: custom filter (disables internal filter) */
|
|
17
19
|
filter?: boolean | SelectFilterFunction
|
|
18
20
|
/** Search input placeholder */
|
package/i18n/messages/ar.json
CHANGED
|
@@ -51,6 +51,12 @@
|
|
|
51
51
|
"Dropdown": {
|
|
52
52
|
"empty": "لا توجد عناصر"
|
|
53
53
|
},
|
|
54
|
+
"InfiniteDataTable": {
|
|
55
|
+
"allLoaded": "— تم تحميل الكل —",
|
|
56
|
+
"count": "{loaded} من {total} تم تحميله",
|
|
57
|
+
"refresh": "تحديث",
|
|
58
|
+
"scrollToTop": "الرجوع إلى الأعلى"
|
|
59
|
+
},
|
|
54
60
|
"InputRange": {
|
|
55
61
|
"endPlaceholder": "أقصى",
|
|
56
62
|
"startPlaceholder": "أدنى"
|
package/i18n/messages/de.json
CHANGED
|
@@ -51,6 +51,12 @@
|
|
|
51
51
|
"Dropdown": {
|
|
52
52
|
"empty": "Keine Elemente"
|
|
53
53
|
},
|
|
54
|
+
"InfiniteDataTable": {
|
|
55
|
+
"allLoaded": "— alle geladen —",
|
|
56
|
+
"count": "{loaded} von {total} geladen",
|
|
57
|
+
"refresh": "Aktualisieren",
|
|
58
|
+
"scrollToTop": "Nach oben scrollen"
|
|
59
|
+
},
|
|
54
60
|
"InputRange": {
|
|
55
61
|
"endPlaceholder": "Maximum",
|
|
56
62
|
"startPlaceholder": "Minimum"
|
package/i18n/messages/en.json
CHANGED
|
@@ -51,6 +51,12 @@
|
|
|
51
51
|
"Dropdown": {
|
|
52
52
|
"empty": "No items"
|
|
53
53
|
},
|
|
54
|
+
"InfiniteDataTable": {
|
|
55
|
+
"allLoaded": "— all loaded —",
|
|
56
|
+
"count": "{loaded} of {total} loaded",
|
|
57
|
+
"refresh": "Refresh",
|
|
58
|
+
"scrollToTop": "Scroll to top"
|
|
59
|
+
},
|
|
54
60
|
"InputRange": {
|
|
55
61
|
"endPlaceholder": "Max",
|
|
56
62
|
"startPlaceholder": "Min"
|
package/i18n/messages/es.json
CHANGED
|
@@ -51,6 +51,12 @@
|
|
|
51
51
|
"Dropdown": {
|
|
52
52
|
"empty": "Sin elementos"
|
|
53
53
|
},
|
|
54
|
+
"InfiniteDataTable": {
|
|
55
|
+
"allLoaded": "— todos cargados —",
|
|
56
|
+
"count": "{loaded} de {total} cargados",
|
|
57
|
+
"refresh": "Actualizar",
|
|
58
|
+
"scrollToTop": "Desplazarse hacia arriba"
|
|
59
|
+
},
|
|
54
60
|
"InputRange": {
|
|
55
61
|
"endPlaceholder": "Máximo",
|
|
56
62
|
"startPlaceholder": "Mínimo"
|
package/i18n/messages/fr.json
CHANGED
|
@@ -51,6 +51,12 @@
|
|
|
51
51
|
"Dropdown": {
|
|
52
52
|
"empty": "Aucun élément"
|
|
53
53
|
},
|
|
54
|
+
"InfiniteDataTable": {
|
|
55
|
+
"allLoaded": "— tout chargé —",
|
|
56
|
+
"count": "{loaded} sur {total} chargés",
|
|
57
|
+
"refresh": "Actualiser",
|
|
58
|
+
"scrollToTop": "Retour au haut"
|
|
59
|
+
},
|
|
54
60
|
"InputRange": {
|
|
55
61
|
"endPlaceholder": "Max",
|
|
56
62
|
"startPlaceholder": "Min"
|
package/i18n/messages/hi.json
CHANGED
|
@@ -51,6 +51,12 @@
|
|
|
51
51
|
"Dropdown": {
|
|
52
52
|
"empty": "कोई आइटम नहीं"
|
|
53
53
|
},
|
|
54
|
+
"InfiniteDataTable": {
|
|
55
|
+
"allLoaded": "— सभी लोड हो गए —",
|
|
56
|
+
"count": "{loaded} of {total} लोड हो गया",
|
|
57
|
+
"refresh": "ताज़ा करें",
|
|
58
|
+
"scrollToTop": "शीर्ष पर जाएं"
|
|
59
|
+
},
|
|
54
60
|
"InputRange": {
|
|
55
61
|
"endPlaceholder": "अधिकतम",
|
|
56
62
|
"startPlaceholder": "न्यूनतम"
|
package/i18n/messages/id.json
CHANGED
|
@@ -51,6 +51,12 @@
|
|
|
51
51
|
"Dropdown": {
|
|
52
52
|
"empty": "Tidak ada item"
|
|
53
53
|
},
|
|
54
|
+
"InfiniteDataTable": {
|
|
55
|
+
"allLoaded": "— semua dimuat —",
|
|
56
|
+
"count": "{loaded} dari {total} dimuat",
|
|
57
|
+
"refresh": "Segarkan",
|
|
58
|
+
"scrollToTop": "Gulir ke atas"
|
|
59
|
+
},
|
|
54
60
|
"InputRange": {
|
|
55
61
|
"endPlaceholder": "Maksimal",
|
|
56
62
|
"startPlaceholder": "Minimal"
|
package/i18n/messages/it.json
CHANGED
|
@@ -51,6 +51,12 @@
|
|
|
51
51
|
"Dropdown": {
|
|
52
52
|
"empty": "Nessun elemento"
|
|
53
53
|
},
|
|
54
|
+
"InfiniteDataTable": {
|
|
55
|
+
"allLoaded": "— completamente caricato —",
|
|
56
|
+
"count": "{loaded} di {total} caricati",
|
|
57
|
+
"refresh": "Aggiorna",
|
|
58
|
+
"scrollToTop": "Scorri verso l'alto"
|
|
59
|
+
},
|
|
54
60
|
"InputRange": {
|
|
55
61
|
"endPlaceholder": "Massimo",
|
|
56
62
|
"startPlaceholder": "Minimo"
|
package/i18n/messages/ja.json
CHANGED
|
@@ -51,6 +51,12 @@
|
|
|
51
51
|
"Dropdown": {
|
|
52
52
|
"empty": "アイテムなし"
|
|
53
53
|
},
|
|
54
|
+
"InfiniteDataTable": {
|
|
55
|
+
"allLoaded": "すべて読み込み完了",
|
|
56
|
+
"count": "{loaded}/{total} 読み込み済み",
|
|
57
|
+
"refresh": "更新",
|
|
58
|
+
"scrollToTop": "トップへスクロール"
|
|
59
|
+
},
|
|
54
60
|
"InputRange": {
|
|
55
61
|
"endPlaceholder": "最大値",
|
|
56
62
|
"startPlaceholder": "最小値"
|
package/i18n/messages/ko.json
CHANGED
|
@@ -51,6 +51,12 @@
|
|
|
51
51
|
"Dropdown": {
|
|
52
52
|
"empty": "항목 없음"
|
|
53
53
|
},
|
|
54
|
+
"InfiniteDataTable": {
|
|
55
|
+
"allLoaded": "— 모두 로드됨 —",
|
|
56
|
+
"count": "{loaded}개/{total}개 로드됨",
|
|
57
|
+
"refresh": "새로고침",
|
|
58
|
+
"scrollToTop": "상단으로 이동"
|
|
59
|
+
},
|
|
54
60
|
"InputRange": {
|
|
55
61
|
"endPlaceholder": "최대값",
|
|
56
62
|
"startPlaceholder": "최소값"
|
package/i18n/messages/nl.json
CHANGED
|
@@ -51,6 +51,12 @@
|
|
|
51
51
|
"Dropdown": {
|
|
52
52
|
"empty": "Geen items"
|
|
53
53
|
},
|
|
54
|
+
"InfiniteDataTable": {
|
|
55
|
+
"allLoaded": "— alles geladen —",
|
|
56
|
+
"count": "{loaded} van {total} geladen",
|
|
57
|
+
"refresh": "Vernieuwen",
|
|
58
|
+
"scrollToTop": "Naar boven schuiven"
|
|
59
|
+
},
|
|
54
60
|
"InputRange": {
|
|
55
61
|
"endPlaceholder": "Maximum",
|
|
56
62
|
"startPlaceholder": "Minimum"
|
package/i18n/messages/pl.json
CHANGED
|
@@ -51,6 +51,12 @@
|
|
|
51
51
|
"Dropdown": {
|
|
52
52
|
"empty": "Brak elementów"
|
|
53
53
|
},
|
|
54
|
+
"InfiniteDataTable": {
|
|
55
|
+
"allLoaded": "— wszystko załadowane —",
|
|
56
|
+
"count": "{loaded} z {total} załadowane",
|
|
57
|
+
"refresh": "Odśwież",
|
|
58
|
+
"scrollToTop": "Przewiń do góry"
|
|
59
|
+
},
|
|
54
60
|
"InputRange": {
|
|
55
61
|
"endPlaceholder": "Maksimum",
|
|
56
62
|
"startPlaceholder": "Minimum"
|
package/i18n/messages/pt.json
CHANGED
|
@@ -51,6 +51,12 @@
|
|
|
51
51
|
"Dropdown": {
|
|
52
52
|
"empty": "Sem itens"
|
|
53
53
|
},
|
|
54
|
+
"InfiniteDataTable": {
|
|
55
|
+
"allLoaded": "— Tudo carregado —",
|
|
56
|
+
"count": "{loaded} de {total} carregado(s)",
|
|
57
|
+
"refresh": "Atualizar",
|
|
58
|
+
"scrollToTop": "Voltar ao topo"
|
|
59
|
+
},
|
|
54
60
|
"InputRange": {
|
|
55
61
|
"endPlaceholder": "Máximo",
|
|
56
62
|
"startPlaceholder": "Mínimo"
|
package/i18n/messages/ru.json
CHANGED
|
@@ -51,6 +51,12 @@
|
|
|
51
51
|
"Dropdown": {
|
|
52
52
|
"empty": "Нет элементов"
|
|
53
53
|
},
|
|
54
|
+
"InfiniteDataTable": {
|
|
55
|
+
"allLoaded": "— все загружено —",
|
|
56
|
+
"count": "{loaded} из {total} загружено",
|
|
57
|
+
"refresh": "Обновить",
|
|
58
|
+
"scrollToTop": "Прокрутить вверх"
|
|
59
|
+
},
|
|
54
60
|
"InputRange": {
|
|
55
61
|
"endPlaceholder": "Максимум",
|
|
56
62
|
"startPlaceholder": "Минимум"
|
package/i18n/messages/th.json
CHANGED
|
@@ -51,6 +51,12 @@
|
|
|
51
51
|
"Dropdown": {
|
|
52
52
|
"empty": "ไม่มีรายการ"
|
|
53
53
|
},
|
|
54
|
+
"InfiniteDataTable": {
|
|
55
|
+
"allLoaded": "— โหลดเสร็จแล้วทั้งหมด —",
|
|
56
|
+
"count": "{loaded} จาก {total} โหลดแล้ว",
|
|
57
|
+
"refresh": "รีเฟรช",
|
|
58
|
+
"scrollToTop": "เลื่อนขึ้นด้านบน"
|
|
59
|
+
},
|
|
54
60
|
"InputRange": {
|
|
55
61
|
"endPlaceholder": "สูงสุด",
|
|
56
62
|
"startPlaceholder": "ต่ำสุด"
|
package/i18n/messages/tr.json
CHANGED
|
@@ -51,6 +51,12 @@
|
|
|
51
51
|
"Dropdown": {
|
|
52
52
|
"empty": "Öğe yok"
|
|
53
53
|
},
|
|
54
|
+
"InfiniteDataTable": {
|
|
55
|
+
"allLoaded": "— tümü yüklendi —",
|
|
56
|
+
"count": "{loaded} / {total} yüklendi",
|
|
57
|
+
"refresh": "Yenile",
|
|
58
|
+
"scrollToTop": "Başa dön"
|
|
59
|
+
},
|
|
54
60
|
"InputRange": {
|
|
55
61
|
"endPlaceholder": "Maks",
|
|
56
62
|
"startPlaceholder": "Min"
|
package/i18n/messages/vi.json
CHANGED
|
@@ -51,6 +51,12 @@
|
|
|
51
51
|
"Dropdown": {
|
|
52
52
|
"empty": "Không có mục"
|
|
53
53
|
},
|
|
54
|
+
"InfiniteDataTable": {
|
|
55
|
+
"allLoaded": "— tất cả đã tải —",
|
|
56
|
+
"count": "{loaded} của {total} đã tải",
|
|
57
|
+
"refresh": "Làm mới",
|
|
58
|
+
"scrollToTop": "Cuộn lên đầu"
|
|
59
|
+
},
|
|
54
60
|
"InputRange": {
|
|
55
61
|
"endPlaceholder": "Tối đa",
|
|
56
62
|
"startPlaceholder": "Tối thiểu"
|
package/i18n/messages/zh-CN.json
CHANGED
|
@@ -51,6 +51,12 @@
|
|
|
51
51
|
"Dropdown": {
|
|
52
52
|
"empty": "无项目"
|
|
53
53
|
},
|
|
54
|
+
"InfiniteDataTable": {
|
|
55
|
+
"allLoaded": "全部已加载",
|
|
56
|
+
"count": "{loaded} / {total} 已加载",
|
|
57
|
+
"refresh": "刷新",
|
|
58
|
+
"scrollToTop": "回到顶部"
|
|
59
|
+
},
|
|
54
60
|
"InputRange": {
|
|
55
61
|
"endPlaceholder": "最大值",
|
|
56
62
|
"startPlaceholder": "最小值"
|