@citruslime/ui 2.0.0-beta.5 → 2.0.0-beta.9
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/.eslintrc.js +2 -0
- package/dist/citrus-lime-ui.es.js +3960 -0
- package/dist/citrus-lime-ui.umd.js +1 -0
- package/dist/src/components/accordion/cl-ui-accordion.vue.d.ts +47 -0
- package/dist/src/components/accordion/index.d.ts +2 -0
- package/dist/{@types/components/accordion/item.d.ts → src/components/accordion/types.d.ts} +0 -0
- package/dist/src/components/app/cl-ui-app.vue.d.ts +44 -0
- package/dist/src/components/app/index.d.ts +1 -0
- package/dist/src/components/button/cl-ui-button.vue.d.ts +40 -0
- package/dist/src/components/button/index.d.ts +2 -0
- package/dist/src/components/button/types.d.ts +4 -0
- package/dist/src/components/calendar/cl-ui-calendar.vue.d.ts +2 -0
- package/dist/src/components/calendar/index.d.ts +2 -0
- package/dist/src/components/calendar/types.d.ts +2 -0
- package/dist/src/components/calendar/utils.d.ts +23 -0
- package/dist/src/components/card/cl-ui-card.vue.d.ts +22 -0
- package/dist/src/components/card/index.d.ts +2 -0
- package/dist/src/components/card/types.d.ts +2 -0
- package/dist/src/components/combo-box/cl-ui-combo-box.vue.d.ts +506 -0
- package/dist/src/components/combo-box/index.d.ts +2 -0
- package/dist/src/components/combo-box/search-container/cl-ui-combo-box-search.vue.d.ts +230 -0
- package/dist/src/components/combo-box/search-container/header/cl-ui-combo-box-header.vue.d.ts +34 -0
- package/dist/src/components/combo-box/search-container/selectable/cl-ui-combo-box-selectable.vue.d.ts +68 -0
- package/dist/{@types/components/combo-box/item.d.ts → src/components/combo-box/types.d.ts} +0 -0
- package/dist/src/components/footer/index.d.ts +1 -0
- package/dist/src/components/grid/cell/cl-ui-grid-cell.vue.d.ts +65 -0
- package/dist/src/components/grid/cl-ui-grid.vue.d.ts +478 -0
- package/dist/src/components/grid/filter/cl-ui-grid-filter.vue.d.ts +64 -0
- package/dist/src/components/grid/footer/cl-ui-grid-footer.vue.d.ts +57 -0
- package/dist/src/components/grid/header/cl-ui-grid-header.vue.d.ts +175 -0
- package/dist/src/components/grid/index.d.ts +2 -0
- package/dist/src/components/grid/types.d.ts +92 -0
- package/dist/src/components/grid/view-manager/cl-ui-grid-view-manager.vue.d.ts +75 -0
- package/dist/src/components/header/index.d.ts +2 -0
- package/dist/src/components/header/menu/cl-ui-header-menu.vue.d.ts +16 -0
- package/dist/src/components/header/menu/index.d.ts +2 -0
- package/dist/src/components/header/menu/types.d.ts +5 -0
- package/dist/src/components/index.d.ts +16 -0
- package/dist/src/components/language-switcher/cl-ui-language-switcher.vue.d.ts +33 -0
- package/dist/src/components/language-switcher/index.d.ts +2 -0
- package/dist/{@types/language.d.ts → src/components/language-switcher/types.d.ts} +1 -1
- package/dist/src/components/loading-spinner/index.d.ts +1 -0
- package/dist/src/components/login/cl-ui-login.vue.d.ts +92 -0
- package/dist/src/components/login/index.d.ts +2 -0
- package/dist/{@types/components/login/authentication.d.ts → src/components/login/types.d.ts} +0 -0
- package/dist/src/components/modal/cl-ui-modal.vue.d.ts +107 -0
- package/dist/src/components/modal/index.d.ts +1 -0
- package/dist/src/components/modal/types.d.ts +2 -0
- package/dist/src/components/navigation/cl-ui-navigation.vue.d.ts +669 -0
- package/dist/src/components/navigation/index.d.ts +2 -0
- package/dist/{@types/components/navigation/index.d.ts → src/components/navigation/types.d.ts} +2 -2
- package/dist/src/components/notification/cl-ui-notification.vue.d.ts +31 -0
- package/dist/src/components/notification/index.d.ts +1 -0
- package/dist/src/components/notification/types.d.ts +9 -0
- package/dist/src/components/slider/cl-ui-slider.vue.d.ts +87 -0
- package/dist/src/components/slider/index.d.ts +1 -0
- package/dist/{composables → src/composables}/index.d.ts +0 -0
- package/dist/{composables → src/composables}/notification.d.ts +1 -1
- package/dist/src/main.d.ts +6 -0
- package/dist/{utils → src/utils}/copy.d.ts +1 -1
- package/dist/{utils → src/utils}/debouncer.d.ts +6 -1
- package/dist/src/utils/extensions/string/index.d.ts +2 -0
- package/dist/{utils/extensions/string-utilities.d.ts → src/utils/extensions/string/utils.d.ts} +0 -0
- package/dist/src/utils/filter-methods.d.ts +5 -0
- package/dist/src/utils/i18n/config.d.ts +33 -0
- package/dist/src/utils/i18n/defaults.d.ts +4 -0
- package/dist/src/utils/i18n/index.d.ts +3 -0
- package/dist/src/utils/i18n/types.d.ts +94 -0
- package/dist/{utils → src/utils}/id.d.ts +0 -0
- package/dist/{utils → src/utils}/index.d.ts +2 -0
- package/dist/{utils → src/utils}/name-of.d.ts +0 -0
- package/dist/{utils → src/utils}/sort.d.ts +0 -0
- package/dist/{utils → src/utils}/url-params.d.ts +0 -0
- package/dist/style.css +1 -1
- package/package.json +23 -12
- package/dist/@types/appUser.d.ts +0 -11
- package/dist/@types/components/accordion/index.d.ts +0 -1
- package/dist/@types/components/combo-box/index.d.ts +0 -2
- package/dist/@types/components/combo-box/localisations.d.ts +0 -19
- package/dist/@types/components/grid/column.d.ts +0 -46
- package/dist/@types/components/grid/index.d.ts +0 -4
- package/dist/@types/components/grid/localisations.d.ts +0 -47
- package/dist/@types/components/grid/request.d.ts +0 -49
- package/dist/@types/components/grid/update.d.ts +0 -4
- package/dist/@types/components/header/index.d.ts +0 -1
- package/dist/@types/components/header/localisations.d.ts +0 -8
- package/dist/@types/components/login/index.d.ts +0 -2
- package/dist/@types/components/login/localisations.d.ts +0 -7
- package/dist/@types/components/notification/index.d.ts +0 -1
- package/dist/@types/components/notification/item.d.ts +0 -7
- package/dist/@types/components/slider/index.d.ts +0 -1
- package/dist/@types/components/slider/localisations.d.ts +0 -3
- package/dist/@types/date-format.d.ts +0 -8
- package/dist/@types/debouncer.d.ts +0 -6
- package/dist/@types/index.d.ts +0 -16
- package/dist/@types/locale.d.ts +0 -10
- package/dist/@types/number-format.d.ts +0 -7
- package/dist/@types/string-format.d.ts +0 -3
- package/dist/@types/string.d.ts +0 -47
- package/dist/components/index.d.ts +0 -17
- package/dist/main.d.ts +0 -8
- package/dist/ui.es.js +0 -1
- package/dist/ui.umd.js +0 -1
- package/dist/utils/extensions/string.d.ts +0 -1
- package/dist/utils/i18n/datetime-formats.d.ts +0 -3
- package/dist/utils/i18n/number-formats.d.ts +0 -3
- package/src/components/accordion/cl-ui-accordion.vue +0 -89
- package/src/components/app/cl-ui-app.vue +0 -29
- package/src/components/button/cl-ui-button.vue +0 -48
- package/src/components/calendar/cl-ui-calendar.vue +0 -277
- package/src/components/card/cl-ui-card.vue +0 -70
- package/src/components/combo-box/cl-ui-combo-box.vue +0 -357
- package/src/components/combo-box/search-container/cl-ui-combo-box-search.vue +0 -279
- package/src/components/combo-box/search-container/header/cl-ui-combo-box-header.vue +0 -36
- package/src/components/combo-box/search-container/selectable/cl-ui-combo-box-selectable.vue +0 -99
- package/src/components/footer/cl-ui-footer.vue +0 -31
- package/src/components/grid/cell/cl-ui-grid-cell.vue +0 -158
- package/src/components/grid/cl-ui-grid.vue +0 -482
- package/src/components/grid/filter/cl-ui-grid-filter.vue +0 -270
- package/src/components/grid/footer/cl-ui-grid-footer.vue +0 -186
- package/src/components/grid/header/cl-ui-grid-header.vue +0 -78
- package/src/components/grid/view-manager/cl-ui-grid-view-manager.vue +0 -145
- package/src/components/header/cl-ui-header.vue +0 -11
- package/src/components/header-helper/cl-ui-header-helper.vue +0 -55
- package/src/components/language-switcher/cl-ui-language-switcher.vue +0 -82
- package/src/components/loading-spinner/cl-ui-loading-spinner.vue +0 -16
- package/src/components/login/cl-ui-login.vue +0 -183
- package/src/components/modal/cl-ui-modal.vue +0 -120
- package/src/components/navigation/cl-ui-navigation.vue +0 -124
- package/src/components/notification/cl-ui-notification.vue +0 -55
- package/src/components/slider/cl-ui-slider.vue +0 -145
|
@@ -1,279 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue';
|
|
3
|
-
|
|
4
|
-
import { ComboBoxItem, ComboBoxSearchContainerLocalisations } from '../../../@types';
|
|
5
|
-
|
|
6
|
-
import ClUiComboBoxHeader from './header/cl-ui-combo-box-header.vue';
|
|
7
|
-
import ClUiComboBoxSelectable from './selectable/cl-ui-combo-box-selectable.vue';
|
|
8
|
-
|
|
9
|
-
const props = withDefaults(defineProps<{
|
|
10
|
-
localisations: ComboBoxSearchContainerLocalisations;
|
|
11
|
-
loading?: boolean;
|
|
12
|
-
objectType: string;
|
|
13
|
-
objectParentType?: string;
|
|
14
|
-
errorMessage?: string;
|
|
15
|
-
canCreateNewObject?: boolean;
|
|
16
|
-
canClearSelectedObject?: boolean;
|
|
17
|
-
currentObjectName?: string;
|
|
18
|
-
results?: ComboBoxItem[];
|
|
19
|
-
isVisible?: boolean;
|
|
20
|
-
}>(), {
|
|
21
|
-
loading: false,
|
|
22
|
-
objectParentType: '',
|
|
23
|
-
errorMessage: '',
|
|
24
|
-
canCreateNewObject: false,
|
|
25
|
-
canClearSelectedObject: true,
|
|
26
|
-
currentObjectName: '',
|
|
27
|
-
results: () => [],
|
|
28
|
-
isVisible: false
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
const emit = defineEmits({
|
|
32
|
-
'clear-object': null,
|
|
33
|
-
'create-object': null,
|
|
34
|
-
'select-object': null,
|
|
35
|
-
search: null,
|
|
36
|
-
'hide-dropdown': null
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
const searchText = ref<string>('');
|
|
40
|
-
const showAddNewOption = ref<boolean>(false);
|
|
41
|
-
const currentSelection = ref<number>(-1);
|
|
42
|
-
const firstIndexInResults = computed<number>(() => showAddNewOption.value ? -1 : 0);
|
|
43
|
-
|
|
44
|
-
const combinedErrorMessage = computed<string>(() => props.localisations.errorMessage.replacePlaceholders(props.errorMessage));
|
|
45
|
-
const searchHint = computed<string>(() => props.localisations.searchHintText.replacePlaceholders(props.objectType));
|
|
46
|
-
const addPrompt = computed<string>(() => props.localisations.addPrompt.replacePlaceholders(searchText.value, props.objectType));
|
|
47
|
-
const noResults = computed<string>(() => props.localisations.noResults.replacePlaceholders(searchText.value));
|
|
48
|
-
|
|
49
|
-
const container = ref<HTMLElement>();
|
|
50
|
-
const searchBox = ref<HTMLInputElement>();
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Event when the text in the search box is updated that will trigger
|
|
54
|
-
* the search call.
|
|
55
|
-
*
|
|
56
|
-
* @param {KeyboardEvent} keyboardEvent - The keyboard event on the input.
|
|
57
|
-
*/
|
|
58
|
-
function search (keyboardEvent?: KeyboardEvent) : void {
|
|
59
|
-
if (keyboardEvent === undefined || (
|
|
60
|
-
keyboardEvent?.code.startsWith('Arrow') === false
|
|
61
|
-
&& keyboardEvent?.code.startsWith('Control') === false
|
|
62
|
-
&& keyboardEvent?.code.startsWith('Shift') === false
|
|
63
|
-
&& keyboardEvent?.code.startsWith('Tab') === false
|
|
64
|
-
&& keyboardEvent?.code !== 'Enter')) {
|
|
65
|
-
emit('search', searchText.value);
|
|
66
|
-
|
|
67
|
-
currentSelection.value = -2;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Emits up to the combo box to select the object with the given id.
|
|
73
|
-
*
|
|
74
|
-
* @param {number} id - The object's id.
|
|
75
|
-
*/
|
|
76
|
-
function selectObject (id: number) : void {
|
|
77
|
-
emit('select-object', id);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Emits up to the combo box to create a new object.
|
|
82
|
-
*/
|
|
83
|
-
function createObject () : void {
|
|
84
|
-
emit('create-object', searchText.value);
|
|
85
|
-
hideDropdown();
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Emits up to the combo box to hide the dropdown.
|
|
90
|
-
*/
|
|
91
|
-
function hideDropdown () : void {
|
|
92
|
-
emit('hide-dropdown');
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Update the current selection when the Down arrow on the keyboard is pressed.
|
|
97
|
-
*
|
|
98
|
-
* @param {number} firstIndex - The index of the first item that can be selected.
|
|
99
|
-
*/
|
|
100
|
-
function onKeyboardArrowDown (firstIndex: number): void {
|
|
101
|
-
if (currentSelection.value < props.results.length - 1) {
|
|
102
|
-
|
|
103
|
-
if (currentSelection.value === -2 && searchText.value === '') {
|
|
104
|
-
currentSelection.value++;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
currentSelection.value++;
|
|
108
|
-
}
|
|
109
|
-
else {
|
|
110
|
-
currentSelection.value = firstIndex;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
scroll();
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Update the current selection when the Up arrow on the keyboard is pressed.
|
|
118
|
-
*
|
|
119
|
-
* @param {number} firstIndex - The index of the first item that can be selected.
|
|
120
|
-
*/
|
|
121
|
-
function onKeyboardArrowUp (firstIndex: number): void {
|
|
122
|
-
if (currentSelection.value > firstIndex) {
|
|
123
|
-
currentSelection.value--;
|
|
124
|
-
}
|
|
125
|
-
else {
|
|
126
|
-
currentSelection.value = props.results.length - 1;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
scroll();
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Select the currently highlighted object in the list when the Enter button on the keyboard is pressed.
|
|
134
|
-
*/
|
|
135
|
-
function onKeyboardEnter (): void {
|
|
136
|
-
if (currentSelection.value >= 0 && props.results !== undefined) {
|
|
137
|
-
selectObject(props.results[currentSelection.value].id);
|
|
138
|
-
}
|
|
139
|
-
else if (currentSelection.value === -1) {
|
|
140
|
-
createObject();
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* Ensure the focus leaves the control when pressing Shift+Tab by forcing focus on
|
|
146
|
-
* the previously selectable input.
|
|
147
|
-
*
|
|
148
|
-
* @param {KeyboardEvent} keyboardEvent - The keyboard event.
|
|
149
|
-
*/
|
|
150
|
-
function onKeyboardShiftTab (keyboardEvent: KeyboardEvent) : void {
|
|
151
|
-
if (keyboardEvent.key === 'Tab' && keyboardEvent.shiftKey === true) {
|
|
152
|
-
const selectableElements = document.getElementsByTagName('input');
|
|
153
|
-
let indexOfPreviouslySelectableItem = -1;
|
|
154
|
-
|
|
155
|
-
for (let i = 0; i < selectableElements.length; i++) {
|
|
156
|
-
if (selectableElements[i] === keyboardEvent.target) {
|
|
157
|
-
indexOfPreviouslySelectableItem = i - 1;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
if (indexOfPreviouslySelectableItem >= 0) {
|
|
162
|
-
selectableElements[indexOfPreviouslySelectableItem].focus();
|
|
163
|
-
hideDropdown();
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Scroll the results to the highlighted object.
|
|
170
|
-
*/
|
|
171
|
-
function scroll () : void {
|
|
172
|
-
if (props.results && props.results.length > 1) {
|
|
173
|
-
const heightOffset = 34;
|
|
174
|
-
container.value?.scrollTo(0, ((currentSelection.value + 1) * heightOffset) - (heightOffset * 2));
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* Update the add new option to determine whether it should be displayed.
|
|
180
|
-
*/
|
|
181
|
-
function updateAddNewOption () : void {
|
|
182
|
-
let finalResultMatches = false;
|
|
183
|
-
|
|
184
|
-
if (props.results !== null && props.results.length === 1) {
|
|
185
|
-
finalResultMatches = searchText.value.toUpperCase().trim() === props.results[0].name.toUpperCase().trim();
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
showAddNewOption.value = props.canCreateNewObject === true
|
|
189
|
-
&& props.errorMessage === ''
|
|
190
|
-
&& searchText.value.trim() !== ''
|
|
191
|
-
&& finalResultMatches === false;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* Update the index of the selected object.
|
|
196
|
-
*
|
|
197
|
-
* @param {number} index - The index.
|
|
198
|
-
*/
|
|
199
|
-
function updateSelectedObjectIndex (index: number) : void {
|
|
200
|
-
currentSelection.value = index;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* Event when visibility of the search container changes. If visible,
|
|
205
|
-
* makes a call to get the data and then sets the focus on the search box.
|
|
206
|
-
*/
|
|
207
|
-
function onVisibilityChanged () : void {
|
|
208
|
-
if (props.isVisible === true) {
|
|
209
|
-
searchText.value = '';
|
|
210
|
-
search();
|
|
211
|
-
|
|
212
|
-
nextTick(() => searchBox.value?.focus());
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
watch(() => props.results, () => updateAddNewOption());
|
|
217
|
-
watch(() => props.errorMessage, () => updateAddNewOption());
|
|
218
|
-
watch(() => props.isVisible, () => onVisibilityChanged());
|
|
219
|
-
|
|
220
|
-
onMounted(() => container.value?.addEventListener('keydown', onKeyboardShiftTab));
|
|
221
|
-
|
|
222
|
-
onUnmounted(() => container.value?.removeEventListener('keydown', onKeyboardShiftTab));
|
|
223
|
-
</script>
|
|
224
|
-
|
|
225
|
-
<template>
|
|
226
|
-
<div ref="container"
|
|
227
|
-
class="bg-white border border-collapse border-grey-0 h-52 overflow-y-auto p-2 text-sm"
|
|
228
|
-
@keydown.up.prevent.stop="onKeyboardArrowUp(firstIndexInResults)"
|
|
229
|
-
@keydown.down.prevent.stop="onKeyboardArrowDown(firstIndexInResults)"
|
|
230
|
-
@keyup.enter.prevent.stop="onKeyboardEnter">
|
|
231
|
-
<div class="flex">
|
|
232
|
-
<input ref="searchBox"
|
|
233
|
-
v-model="searchText"
|
|
234
|
-
type="text"
|
|
235
|
-
:placeholder="searchHint"
|
|
236
|
-
@keyup="search"
|
|
237
|
-
@blur="hideDropdown">
|
|
238
|
-
|
|
239
|
-
<cl-ui-loading-spinner v-if="loading"
|
|
240
|
-
class="absolute ml-2 mt-11" />
|
|
241
|
-
</div>
|
|
242
|
-
|
|
243
|
-
<cl-ui-combo-box-header v-if="currentObjectName !== ''"
|
|
244
|
-
:show-clear-button="canClearSelectedObject"
|
|
245
|
-
:text="currentObjectName"
|
|
246
|
-
@clear-object="$emit('clear-object')" />
|
|
247
|
-
|
|
248
|
-
<cl-ui-combo-box-header v-if="objectParentType !== '' && results !== null && results.length > 0 && errorMessage === ''"
|
|
249
|
-
:text="objectType"
|
|
250
|
-
:additional-text="objectParentType" />
|
|
251
|
-
|
|
252
|
-
<cl-ui-combo-box-header v-if="results !== null && results.length === 0 && searchText.trim() !== '' && canCreateNewObject === false && errorMessage === ''"
|
|
253
|
-
:text="noResults" />
|
|
254
|
-
|
|
255
|
-
<cl-ui-combo-box-header v-if="errorMessage !== ''"
|
|
256
|
-
class="!bg-danger-light text-danger-dark"
|
|
257
|
-
:text="combinedErrorMessage" />
|
|
258
|
-
|
|
259
|
-
<cl-ui-combo-box-selectable v-if="showAddNewOption"
|
|
260
|
-
:is-create-new-option="true"
|
|
261
|
-
:text="addPrompt"
|
|
262
|
-
:index="-1"
|
|
263
|
-
:localisations="localisations"
|
|
264
|
-
:selected-index="currentSelection"
|
|
265
|
-
@create-object="createObject"
|
|
266
|
-
@option-highlighted="updateSelectedObjectIndex" />
|
|
267
|
-
|
|
268
|
-
<div v-if="errorMessage === '' && results !== null">
|
|
269
|
-
<cl-ui-combo-box-selectable v-for="(result, index) in results"
|
|
270
|
-
:key="index"
|
|
271
|
-
:localisations="localisations"
|
|
272
|
-
:option="result"
|
|
273
|
-
:index="index"
|
|
274
|
-
:selected-index="currentSelection"
|
|
275
|
-
@select-object="selectObject"
|
|
276
|
-
@option-highlighted="updateSelectedObjectIndex" />
|
|
277
|
-
</div>
|
|
278
|
-
</div>
|
|
279
|
-
</template>
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
withDefaults(defineProps<{
|
|
3
|
-
showClearButton?: boolean;
|
|
4
|
-
text?: string;
|
|
5
|
-
additionalText?: string;
|
|
6
|
-
}>(), {
|
|
7
|
-
showClearButton: false,
|
|
8
|
-
text: '',
|
|
9
|
-
additionalText: ''
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
defineEmits({
|
|
13
|
-
'clear-object': null
|
|
14
|
-
});
|
|
15
|
-
</script>
|
|
16
|
-
|
|
17
|
-
<template>
|
|
18
|
-
<div class="bg-grey-2 border-b border-grey-2 border-t flex p-1">
|
|
19
|
-
<div v-if="additionalText !== ''"
|
|
20
|
-
class="w-1/2">
|
|
21
|
-
{{ additionalText }}
|
|
22
|
-
</div>
|
|
23
|
-
<div :class="{
|
|
24
|
-
'w-1/2': additionalText !== '',
|
|
25
|
-
'w-full': additionalText === ''
|
|
26
|
-
}">
|
|
27
|
-
{{ text }}
|
|
28
|
-
</div>
|
|
29
|
-
<div v-show="showClearButton"
|
|
30
|
-
class="cursor-pointer float-right"
|
|
31
|
-
@mousedown="$emit('clear-object')">
|
|
32
|
-
<icon class="hover:text-link-default mt-0.5 rounded-full"
|
|
33
|
-
icon="ph:x-circle" />
|
|
34
|
-
</div>
|
|
35
|
-
</div>
|
|
36
|
-
</template>
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import { computed, ref, watch } from 'vue';
|
|
3
|
-
|
|
4
|
-
import { ComboBoxItem } from '../../../../@types';
|
|
5
|
-
|
|
6
|
-
const props = withDefaults(defineProps<{
|
|
7
|
-
isCreateNewOption?: boolean;
|
|
8
|
-
selectedIndex?: number;
|
|
9
|
-
text?: string;
|
|
10
|
-
option?: ComboBoxItem | null;
|
|
11
|
-
index: number;
|
|
12
|
-
}>(), {
|
|
13
|
-
isCreateNewOption: false,
|
|
14
|
-
selectedIndex: -1,
|
|
15
|
-
text: '',
|
|
16
|
-
option: () => null
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
const emit = defineEmits({
|
|
20
|
-
'create-object': null,
|
|
21
|
-
'select-object': null,
|
|
22
|
-
'option-highlighted': null
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
const displayedText = computed<string>(() => props.option?.name ?? props.text);
|
|
26
|
-
const displayedParent = computed<string>(() => props.option?.parentName ?? '');
|
|
27
|
-
const isHighlighted = ref<boolean>(false);
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Event when the option is selected - triggers to either select
|
|
31
|
-
* the highlight object, or prompt to create a new one.
|
|
32
|
-
*/
|
|
33
|
-
function optionSelected () : void {
|
|
34
|
-
if (props.isCreateNewOption === true) {
|
|
35
|
-
emit('create-object');
|
|
36
|
-
}
|
|
37
|
-
else {
|
|
38
|
-
emit('select-object', props.option?.id);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Event when the mouse hovers over the component.
|
|
44
|
-
*
|
|
45
|
-
* @param {boolean} hovered - Whether the mouse has hovered over or out of the component.
|
|
46
|
-
*/
|
|
47
|
-
function onHover (hovered: boolean) : void {
|
|
48
|
-
if (hovered === true) {
|
|
49
|
-
isHighlighted.value = true;
|
|
50
|
-
emit('option-highlighted', props.index);
|
|
51
|
-
}
|
|
52
|
-
else {
|
|
53
|
-
if (props.index !== props.selectedIndex) {
|
|
54
|
-
isHighlighted.value = false;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Update the highlight on the component.
|
|
61
|
-
*/
|
|
62
|
-
function updateHighlight () : void {
|
|
63
|
-
if (props.selectedIndex === props.index) {
|
|
64
|
-
isHighlighted.value = true;
|
|
65
|
-
}
|
|
66
|
-
else {
|
|
67
|
-
isHighlighted.value = false;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
watch(() => props.selectedIndex, () => updateHighlight());
|
|
72
|
-
</script>
|
|
73
|
-
|
|
74
|
-
<template>
|
|
75
|
-
<div class="border-b border-grey-0 border-t cursor-pointer flex p-1"
|
|
76
|
-
:class="{
|
|
77
|
-
'bg-grey-0': isHighlighted === false,
|
|
78
|
-
'bg-primary-default text-white': isHighlighted
|
|
79
|
-
}"
|
|
80
|
-
@mousedown="optionSelected"
|
|
81
|
-
@mousemove="onHover(true)"
|
|
82
|
-
@mouseleave="onHover(false)">
|
|
83
|
-
<div v-if="option !== null && option.parentId !== 0 && option.parentId !== undefined"
|
|
84
|
-
class="w-1/2">
|
|
85
|
-
{{ displayedParent }}
|
|
86
|
-
</div>
|
|
87
|
-
<div :class="{
|
|
88
|
-
'w-1/2': displayedParent !== '',
|
|
89
|
-
'w-full': displayedParent === ''
|
|
90
|
-
}">
|
|
91
|
-
{{ displayedText }}
|
|
92
|
-
</div>
|
|
93
|
-
<div v-show="isCreateNewOption"
|
|
94
|
-
class="float-right py-1.5">
|
|
95
|
-
<icon class="bg-primary-default rounded-full text-white"
|
|
96
|
-
icon="ph:plus-circle" />
|
|
97
|
-
</div>
|
|
98
|
-
</div>
|
|
99
|
-
</template>
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
withDefaults(defineProps<{
|
|
3
|
-
leftText?: string;
|
|
4
|
-
rightText?: string;
|
|
5
|
-
}>(), {
|
|
6
|
-
leftText: '',
|
|
7
|
-
rightText: ''
|
|
8
|
-
});
|
|
9
|
-
</script>
|
|
10
|
-
|
|
11
|
-
<template>
|
|
12
|
-
<div class="flex flex-wrap left-0 w-full">
|
|
13
|
-
<div v-if="$slots.default"
|
|
14
|
-
class="w-full">
|
|
15
|
-
<slot></slot>
|
|
16
|
-
</div>
|
|
17
|
-
|
|
18
|
-
<div v-show="leftText !== '' || rightText !== ''"
|
|
19
|
-
class="leading-10 text-sm w-full">
|
|
20
|
-
<strong v-show="leftText !== ''"
|
|
21
|
-
class="float-left">
|
|
22
|
-
{{ leftText }}
|
|
23
|
-
</strong>
|
|
24
|
-
|
|
25
|
-
<strong v-show="rightText !== ''"
|
|
26
|
-
class="float-right">
|
|
27
|
-
{{ rightText }}
|
|
28
|
-
</strong>
|
|
29
|
-
</div>
|
|
30
|
-
</div>
|
|
31
|
-
</template>
|
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
export default {
|
|
3
|
-
inheritAttrs: false
|
|
4
|
-
};
|
|
5
|
-
</script>
|
|
6
|
-
|
|
7
|
-
<script setup lang="ts">
|
|
8
|
-
import { computed, ref, watch, watchEffect } from 'vue';
|
|
9
|
-
import { useI18n } from 'vue-i18n';
|
|
10
|
-
|
|
11
|
-
import { DateFormat, GridColumn, GridColumnType, NumberFormat, StringFormat } from '../../../@types';
|
|
12
|
-
import { copy } from '../../../utils';
|
|
13
|
-
|
|
14
|
-
const props = withDefaults(defineProps<{
|
|
15
|
-
currentLocale?: string;
|
|
16
|
-
column: GridColumn;
|
|
17
|
-
record: Record<string, unknown>;
|
|
18
|
-
editMode?: boolean;
|
|
19
|
-
}>(), {
|
|
20
|
-
currentLocale: 'en-GB',
|
|
21
|
-
editMode: false
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
const emit = defineEmits({
|
|
25
|
-
edit: null,
|
|
26
|
-
focus: null,
|
|
27
|
-
'undo-edit': null
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
const { d, n } = useI18n();
|
|
31
|
-
|
|
32
|
-
const currentRecord = ref<Record<string, unknown>>(copy(props.record));
|
|
33
|
-
|
|
34
|
-
const edited = computed<boolean>(() => currentRecord.value[props.column.field ?? ''] !== props.record[props.column.field ?? '']);
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Retrieve a string value, from the provided record.
|
|
38
|
-
*
|
|
39
|
-
* @param record The record to get the value from.
|
|
40
|
-
* @param key The property to get the value of.
|
|
41
|
-
* @returns The record value, as a string.
|
|
42
|
-
*/
|
|
43
|
-
function getStringValue (record: Record<string, unknown>, key: string): string {
|
|
44
|
-
return record[key] as string;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Retrieve a numeric value, from the provided record.
|
|
49
|
-
*
|
|
50
|
-
* @param record The record to get the value from.
|
|
51
|
-
* @param key The property to get the value of.
|
|
52
|
-
* @returns The record value, as a number.
|
|
53
|
-
*/
|
|
54
|
-
function getNumericValue (record: Record<string, unknown>, key: string): number {
|
|
55
|
-
return record[key] as number;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Retrieve a boolean value, from the provided record.
|
|
60
|
-
*
|
|
61
|
-
* @param record The record to get the value from.
|
|
62
|
-
* @param key The property to get the value of.
|
|
63
|
-
* @returns The record value, as a boolean.
|
|
64
|
-
*/
|
|
65
|
-
function getBooleanValue (record: Record<string, unknown>, key: string): boolean {
|
|
66
|
-
return record[key] as boolean;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Emits an event to indicate that the cell was focused.
|
|
71
|
-
*/
|
|
72
|
-
function cellFocused (): void {
|
|
73
|
-
emit('focus');
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
watchEffect(() => currentRecord.value = copy(props.record));
|
|
77
|
-
|
|
78
|
-
watch(currentRecord, (newValue) => {
|
|
79
|
-
const property: string = props.column.field ?? '';
|
|
80
|
-
|
|
81
|
-
if (property !== '') {
|
|
82
|
-
if (newValue[property] !== props.record[property]) {
|
|
83
|
-
emit('edit', newValue[property]);
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
emit('undo-edit');
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}, {
|
|
90
|
-
deep: true
|
|
91
|
-
});
|
|
92
|
-
</script>
|
|
93
|
-
|
|
94
|
-
<template>
|
|
95
|
-
<td v-if="editMode && column.field && column.editable"
|
|
96
|
-
v-bind="$attrs"
|
|
97
|
-
:class="{
|
|
98
|
-
'bg-link-lighter': edited
|
|
99
|
-
}">
|
|
100
|
-
<strong class="lg:hidden mr-2">
|
|
101
|
-
{{ column.caption }}
|
|
102
|
-
</strong>
|
|
103
|
-
|
|
104
|
-
<slot :name="`${column.name}Edit`"
|
|
105
|
-
v-bind="{ cellFocused, column, edited, record: currentRecord }"></slot>
|
|
106
|
-
</td>
|
|
107
|
-
<td v-else
|
|
108
|
-
v-bind="$attrs">
|
|
109
|
-
<strong class="lg:hidden mr-2">
|
|
110
|
-
{{ column.caption }}
|
|
111
|
-
</strong>
|
|
112
|
-
|
|
113
|
-
<!-- Slot contents -->
|
|
114
|
-
<slot v-if="column.type === GridColumnType.SLOT"
|
|
115
|
-
:name="column.name"
|
|
116
|
-
v-bind="{ column, record }"></slot>
|
|
117
|
-
<!-- Booleans -->
|
|
118
|
-
<input v-else-if="column.type === GridColumnType.BOOLEAN && column.field !== undefined"
|
|
119
|
-
type="checkbox"
|
|
120
|
-
:checked="getBooleanValue(record, column.field)"
|
|
121
|
-
disabled>
|
|
122
|
-
<!-- Dates and datetimes -->
|
|
123
|
-
<template v-else-if="(column.type === GridColumnType.DATE || column.type === GridColumnType.DATETIME) && column.field !== undefined">
|
|
124
|
-
<template v-if="column.format !== undefined">
|
|
125
|
-
{{ d(new Date(getStringValue(record, column.field)), column.format, currentLocale) }}
|
|
126
|
-
</template>
|
|
127
|
-
<template v-else-if="column.type === GridColumnType.DATE">
|
|
128
|
-
{{ d(new Date(getStringValue(record, column.field)), DateFormat.DATE, currentLocale) }}
|
|
129
|
-
</template>
|
|
130
|
-
<template v-else>
|
|
131
|
-
{{ d(new Date(getStringValue(record, column.field)), DateFormat.DATETIME, currentLocale) }}
|
|
132
|
-
</template>
|
|
133
|
-
</template>
|
|
134
|
-
<!-- Numbers -->
|
|
135
|
-
<template v-else-if="column.type === GridColumnType.NUMBER && column.field">
|
|
136
|
-
<template v-if="column.format === NumberFormat.MULTIPLIER">
|
|
137
|
-
×{{ getNumericValue(record, column.field) }}
|
|
138
|
-
</template>
|
|
139
|
-
<template v-else-if="column.format !== undefined">
|
|
140
|
-
{{ n(getNumericValue(record, column.field), column.format, currentLocale) }}
|
|
141
|
-
</template>
|
|
142
|
-
<template v-else>
|
|
143
|
-
{{ getNumericValue(record, column.field) }}
|
|
144
|
-
</template>
|
|
145
|
-
</template>
|
|
146
|
-
<!-- Strings -->
|
|
147
|
-
<template v-else-if="column.field !== undefined">
|
|
148
|
-
<span v-if="column.maxLength !== undefined"
|
|
149
|
-
class="inline-block whitespace-nowrap">
|
|
150
|
-
{{ getStringValue(record, column.field).trimToLength(column.maxLength, column.format !== undefined ? column.format === StringFormat.ELLIPSIS : false) }}
|
|
151
|
-
</span>
|
|
152
|
-
<span v-else
|
|
153
|
-
class="inline-block whitespace-nowrap">
|
|
154
|
-
{{ getStringValue(record, column.field) }}
|
|
155
|
-
</span>
|
|
156
|
-
</template>
|
|
157
|
-
</td>
|
|
158
|
-
</template>
|