@naptics/vue-collection 0.0.4 → 0.0.6
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/i18n/index.js +4 -4
- package/index.d.ts +0 -64
- package/index.js +1 -66
- package/package.json +1 -1
- package/utils/breakpoints.js +21 -21
- package/utils/component.js +9 -17
- package/utils/deferred.js +12 -12
- package/utils/identifiable.js +29 -27
- package/utils/stringMaxLength.js +13 -8
- package/utils/tailwind.js +1 -1
- package/utils/utils.js +5 -5
- package/utils/vModel.js +73 -82
- package/utils/validation.js +81 -55
- package/utils/vue.js +5 -7
- package/components/NAlert.jsx +0 -69
- package/components/NBadge.jsx +0 -58
- package/components/NBreadcrub.jsx +0 -64
- package/components/NButton.jsx +0 -58
- package/components/NCheckbox.jsx +0 -38
- package/components/NCheckboxLabel.jsx +0 -42
- package/components/NCrudModal.jsx +0 -89
- package/components/NDialog.jsx +0 -144
- package/components/NDropdown.jsx +0 -92
- package/components/NDropzone.jsx +0 -211
- package/components/NForm.jsx +0 -26
- package/components/NFormModal.jsx +0 -48
- package/components/NIconButton.jsx +0 -71
- package/components/NIconCircle.jsx +0 -67
- package/components/NInput.jsx +0 -97
- package/components/NInputPhone.jsx +0 -32
- package/components/NInputSelect.jsx +0 -89
- package/components/NInputSuggestion.jsx +0 -48
- package/components/NLink.jsx +0 -58
- package/components/NList.jsx +0 -24
- package/components/NLoadingIndicator.jsx +0 -42
- package/components/NModal.jsx +0 -170
- package/components/NPagination.jsx +0 -104
- package/components/NSearchbar.jsx +0 -58
- package/components/NSearchbarList.jsx +0 -20
- package/components/NSelect.jsx +0 -81
- package/components/NSuggestionList.jsx +0 -157
- package/components/NTable.jsx +0 -146
- package/components/NTableAction.jsx +0 -35
- package/components/NTextArea.jsx +0 -108
- package/components/NTooltip.jsx +0 -161
- package/components/NValInput.jsx +0 -101
package/components/NForm.jsx
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { createComponent, createProps } from '../utils/component';
|
|
2
|
-
export const nFormProps = createProps({
|
|
3
|
-
/**
|
|
4
|
-
* The {@link ValidatedForm} which will be used to validate the inputs.
|
|
5
|
-
* All inputs in this forms hierarchy should be added to the {@link ValidatedForm}.
|
|
6
|
-
*/
|
|
7
|
-
form: Object,
|
|
8
|
-
/**
|
|
9
|
-
* This is called, when a button of type `submit` in the hierarchy of this view is clicked
|
|
10
|
-
* and when the validation of the `form` was successful.
|
|
11
|
-
*/
|
|
12
|
-
onSubmit: Function,
|
|
13
|
-
});
|
|
14
|
-
/**
|
|
15
|
-
* The `NForm` should be used to wrap multiple inputs.
|
|
16
|
-
* If it contains a button of type `submit` in it's hierarchy,
|
|
17
|
-
* it catches the submit event and passes it to the {@link ValidatedForm} in its `form` prop.
|
|
18
|
-
*/
|
|
19
|
-
export default createComponent('NForm', nFormProps, (props, context) => {
|
|
20
|
-
const onSubmit = (event) => {
|
|
21
|
-
event.preventDefault();
|
|
22
|
-
if (!props.form || props.form.validate().isValid)
|
|
23
|
-
props.onSubmit?.();
|
|
24
|
-
};
|
|
25
|
-
return () => <form onSubmit={onSubmit}>{context.slots.default?.()}</form>;
|
|
26
|
-
});
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { createComponent, createProps } from '../utils/component';
|
|
2
|
-
import { reactive, toRefs } from 'vue';
|
|
3
|
-
import NForm from './NForm';
|
|
4
|
-
import NModal, { nModalProps } from './NModal';
|
|
5
|
-
export const nFormModalProps = createProps({
|
|
6
|
-
...nModalProps,
|
|
7
|
-
/**
|
|
8
|
-
* The maximum width of the modal. A regular tailwind class.
|
|
9
|
-
*/
|
|
10
|
-
maxWidth: {
|
|
11
|
-
type: String,
|
|
12
|
-
default: 'max-w-lg',
|
|
13
|
-
},
|
|
14
|
-
/**
|
|
15
|
-
* If set to `true` the modal closes when clicking on the background.
|
|
16
|
-
* Default is `false` as the accidental reseting of the whole form is very annoying.
|
|
17
|
-
*/
|
|
18
|
-
closeOnBackground: {
|
|
19
|
-
type: Boolean,
|
|
20
|
-
default: false,
|
|
21
|
-
},
|
|
22
|
-
/**
|
|
23
|
-
* The {@link ValidatedForm} to validate the inputs.
|
|
24
|
-
* All inputs should be added to the form.
|
|
25
|
-
*/
|
|
26
|
-
form: Object,
|
|
27
|
-
});
|
|
28
|
-
/**
|
|
29
|
-
* The `NFormModal` is a {@link NModal} with an integrated form.
|
|
30
|
-
* When submitting a `NFormModal` the form is first validated and
|
|
31
|
-
* only if the validation is succesful the `onOk` event is called.
|
|
32
|
-
*/
|
|
33
|
-
export default createComponent('NFormModal', nFormModalProps, (props, { slots }) => {
|
|
34
|
-
const childProps = reactive({
|
|
35
|
-
...toRefs(props),
|
|
36
|
-
onOk: () => {
|
|
37
|
-
if (!props.form || props.form.validate().isValid) {
|
|
38
|
-
props.onOk?.();
|
|
39
|
-
if (props.closeOnOk)
|
|
40
|
-
props.onUpdateValue?.(false);
|
|
41
|
-
}
|
|
42
|
-
},
|
|
43
|
-
closeOnOk: false,
|
|
44
|
-
});
|
|
45
|
-
return () => (<NModal {...childProps}>
|
|
46
|
-
<NForm form={props.form}>{slots.default?.()}</NForm>
|
|
47
|
-
</NModal>);
|
|
48
|
-
});
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { createComponent, createProps } from '../utils/component';
|
|
2
|
-
import { RouterLink } from 'vue-router';
|
|
3
|
-
import { nButtonProps } from './NButton';
|
|
4
|
-
import NTooltip, { mapTooltipProps, nToolTipPropsForImplementor } from './NTooltip';
|
|
5
|
-
export const nIconButtonProps = createProps({
|
|
6
|
-
/**
|
|
7
|
-
* The icon of the icon-button.
|
|
8
|
-
*/
|
|
9
|
-
icon: {
|
|
10
|
-
type: Function,
|
|
11
|
-
required: true,
|
|
12
|
-
},
|
|
13
|
-
/**
|
|
14
|
-
* The route of the icon-button. If this is set, the icon-button becomes a {@link RouterLink}.
|
|
15
|
-
*/
|
|
16
|
-
route: [String, Object],
|
|
17
|
-
/**
|
|
18
|
-
* The color of the icon-button.
|
|
19
|
-
*/
|
|
20
|
-
color: {
|
|
21
|
-
type: String,
|
|
22
|
-
default: 'default',
|
|
23
|
-
},
|
|
24
|
-
/**
|
|
25
|
-
* The shade of the icon-button.
|
|
26
|
-
*/
|
|
27
|
-
shade: {
|
|
28
|
-
type: Number,
|
|
29
|
-
default: 500,
|
|
30
|
-
},
|
|
31
|
-
/**
|
|
32
|
-
* The size of the icon in tailwind-units.
|
|
33
|
-
*/
|
|
34
|
-
size: {
|
|
35
|
-
type: Number,
|
|
36
|
-
default: 5,
|
|
37
|
-
},
|
|
38
|
-
/**
|
|
39
|
-
* The html attribute, which indicates the type of the button.
|
|
40
|
-
*/
|
|
41
|
-
type: nButtonProps.type,
|
|
42
|
-
/**
|
|
43
|
-
* If set to `true` the icon-button is disabled and no interaction is possible.
|
|
44
|
-
*/
|
|
45
|
-
disabled: Boolean,
|
|
46
|
-
/**
|
|
47
|
-
* This is called when the icon-button is clicked.
|
|
48
|
-
* It is only called when the `route` prop is not set on the icon-button.
|
|
49
|
-
*/
|
|
50
|
-
onClick: Function,
|
|
51
|
-
...nToolTipPropsForImplementor,
|
|
52
|
-
});
|
|
53
|
-
/**
|
|
54
|
-
* The `NIconButton` is a regular button which does not have any text but an icon instead.
|
|
55
|
-
*/
|
|
56
|
-
export default createComponent('NIconButton', nIconButtonProps, props => {
|
|
57
|
-
const classes = () => [
|
|
58
|
-
'block p-0.5 rounded-md focus:outline-none focus-visible:ring-2 -m-1',
|
|
59
|
-
props.disabled
|
|
60
|
-
? `text-${props.color}-200 cursor-default`
|
|
61
|
-
: `hover:bg-${props.color}-${props.shade} hover:bg-opacity-10 text-${props.color}-${props.shade} focus-visible:ring-${props.color}-${props.shade} cursor-pointer`,
|
|
62
|
-
];
|
|
63
|
-
const content = () => <props.icon class={`w-${props.size} h-${props.size}`}/>;
|
|
64
|
-
return () => (<NTooltip {...mapTooltipProps(props)}>
|
|
65
|
-
{props.route ? (<RouterLink to={props.route} class={classes()}>
|
|
66
|
-
{content()}
|
|
67
|
-
</RouterLink>) : (<button type={props.type} disabled={props.disabled} class={classes()} onClick={props.onClick}>
|
|
68
|
-
{content()}
|
|
69
|
-
</button>)}
|
|
70
|
-
</NTooltip>);
|
|
71
|
-
});
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { createComponent, createProps } from '../utils/component';
|
|
2
|
-
export const nIconCircleProps = createProps({
|
|
3
|
-
/**
|
|
4
|
-
* The icon of the icon-circle.
|
|
5
|
-
*/
|
|
6
|
-
icon: {
|
|
7
|
-
type: Function,
|
|
8
|
-
required: true,
|
|
9
|
-
},
|
|
10
|
-
/**
|
|
11
|
-
* The color of the icon-circle.
|
|
12
|
-
*/
|
|
13
|
-
color: {
|
|
14
|
-
type: String,
|
|
15
|
-
default: 'primary',
|
|
16
|
-
},
|
|
17
|
-
/**
|
|
18
|
-
* The size of the circle in "tailwind units" (4 px).
|
|
19
|
-
* Tailwind classes are used for the size, so any number can be passed.
|
|
20
|
-
* If the `iconSize` is not set, it will be adjusted automatically.
|
|
21
|
-
*/
|
|
22
|
-
circleSize: Number,
|
|
23
|
-
/**
|
|
24
|
-
* The size of the icon in "tailwind units" (4 px).
|
|
25
|
-
* No tailwind classes are used for the size, so any number can be passed.
|
|
26
|
-
* If the `circleSize` is not set, it will be adjusted automatically.
|
|
27
|
-
*/
|
|
28
|
-
iconSize: Number,
|
|
29
|
-
/**
|
|
30
|
-
* The shade of the icon.
|
|
31
|
-
*/
|
|
32
|
-
iconShade: {
|
|
33
|
-
type: Number,
|
|
34
|
-
default: 600,
|
|
35
|
-
},
|
|
36
|
-
/**
|
|
37
|
-
* The shade of the background.
|
|
38
|
-
*/
|
|
39
|
-
bgShade: {
|
|
40
|
-
type: Number,
|
|
41
|
-
default: 100,
|
|
42
|
-
},
|
|
43
|
-
});
|
|
44
|
-
const DEFAULT_CIRCLE_SIZE = 16;
|
|
45
|
-
const SCALING_FACTOR = 0.55;
|
|
46
|
-
/**
|
|
47
|
-
* The `NIconCircle` is an icon with a colored circle around it.
|
|
48
|
-
*/
|
|
49
|
-
export default createComponent('NIconCircle', nIconCircleProps, props => {
|
|
50
|
-
let circleSize = props.circleSize;
|
|
51
|
-
let iconSize = props.iconSize;
|
|
52
|
-
if (circleSize == null) {
|
|
53
|
-
if (iconSize == null)
|
|
54
|
-
circleSize = DEFAULT_CIRCLE_SIZE;
|
|
55
|
-
else
|
|
56
|
-
circleSize = iconSize / SCALING_FACTOR;
|
|
57
|
-
}
|
|
58
|
-
if (iconSize == null)
|
|
59
|
-
iconSize = circleSize * SCALING_FACTOR;
|
|
60
|
-
circleSize *= 4;
|
|
61
|
-
iconSize *= 4;
|
|
62
|
-
return () => (<div class={['flex items-center justify-center rounded-full', `bg-${props.color}-${props.bgShade}`]} style={`width: ${circleSize}px; height: ${circleSize}px`}>
|
|
63
|
-
<div class={`text-${props.color}-${props.iconShade}`} style={`width: ${iconSize}px; height: ${iconSize}px`}>
|
|
64
|
-
<props.icon />
|
|
65
|
-
</div>
|
|
66
|
-
</div>);
|
|
67
|
-
});
|
package/components/NInput.jsx
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import { createComponent, createProps } from '../utils/component';
|
|
2
|
-
import { ref } from 'vue';
|
|
3
|
-
import { ExclamationCircleIcon } from '@heroicons/vue/24/solid';
|
|
4
|
-
import NTooltip, { mapTooltipProps, nToolTipPropsForImplementor } from './NTooltip';
|
|
5
|
-
import './NInput.css';
|
|
6
|
-
import { vModelProps } from '../utils/vModel';
|
|
7
|
-
export const nInputProps = createProps({
|
|
8
|
-
...vModelProps(String),
|
|
9
|
-
/**
|
|
10
|
-
* The name of the input. Is displayed as a label above the input.
|
|
11
|
-
*/
|
|
12
|
-
name: String,
|
|
13
|
-
/**
|
|
14
|
-
* The placeholder of the input.
|
|
15
|
-
*/
|
|
16
|
-
placeholder: String,
|
|
17
|
-
/**
|
|
18
|
-
* The html autocomplete attribute of the input.
|
|
19
|
-
*/
|
|
20
|
-
autocomplete: {
|
|
21
|
-
type: String,
|
|
22
|
-
default: 'off',
|
|
23
|
-
},
|
|
24
|
-
/**
|
|
25
|
-
* The html type attribute of the input.
|
|
26
|
-
*/
|
|
27
|
-
type: {
|
|
28
|
-
type: String,
|
|
29
|
-
default: 'text',
|
|
30
|
-
},
|
|
31
|
-
/**
|
|
32
|
-
* The maximum value of the input.
|
|
33
|
-
*/
|
|
34
|
-
max: String,
|
|
35
|
-
/**
|
|
36
|
-
* The minimum value of the input.
|
|
37
|
-
*/
|
|
38
|
-
min: String,
|
|
39
|
-
/**
|
|
40
|
-
* If set to `true` the input is displayed with a red border.
|
|
41
|
-
*/
|
|
42
|
-
error: Boolean,
|
|
43
|
-
/**
|
|
44
|
-
* If set to `true` the input is disabled and no interaction is possible.
|
|
45
|
-
*/
|
|
46
|
-
disabled: Boolean,
|
|
47
|
-
/**
|
|
48
|
-
* If set to `true` the input is displayed smaller.
|
|
49
|
-
*/
|
|
50
|
-
small: Boolean,
|
|
51
|
-
/**
|
|
52
|
-
* If set to `true` the input's label is hidden.
|
|
53
|
-
*/
|
|
54
|
-
hideLabel: Boolean,
|
|
55
|
-
/**
|
|
56
|
-
* This is called when the input reveices focus.
|
|
57
|
-
*/
|
|
58
|
-
onFocus: Function,
|
|
59
|
-
/**
|
|
60
|
-
* This is called when the input looses focus.
|
|
61
|
-
*/
|
|
62
|
-
onBlur: Function,
|
|
63
|
-
...nToolTipPropsForImplementor,
|
|
64
|
-
});
|
|
65
|
-
/**
|
|
66
|
-
* The base class of inputs. A styled input with a lot of configuration possibilities but no validation.
|
|
67
|
-
*/
|
|
68
|
-
export default createComponent('NInput', nInputProps, (props, context) => {
|
|
69
|
-
const inputRef = ref();
|
|
70
|
-
const exposed = {
|
|
71
|
-
focus: () => inputRef.value?.focus(),
|
|
72
|
-
};
|
|
73
|
-
context.expose(exposed);
|
|
74
|
-
return () => (<div>
|
|
75
|
-
{props.name && !props.hideLabel && (<label for={props.name} class={['block text-sm font-medium mb-1', props.disabled ? 'text-default-300' : 'text-default-700']}>
|
|
76
|
-
{props.name}
|
|
77
|
-
</label>)}
|
|
78
|
-
<NTooltip block {...mapTooltipProps(props)}>
|
|
79
|
-
<div class="relative">
|
|
80
|
-
<input ref={inputRef} name={props.name} value={props.value} onInput={event => props.onUpdateValue?.(event.target.value)} placeholder={props.placeholder} autocomplete={props.autocomplete} type={props.type} min={props.min} max={props.max} disabled={props.disabled} onFocus={() => props.onFocus?.()} onBlur={() => props.onBlur?.()} onInvalid={event => event.preventDefault()} class={[
|
|
81
|
-
'block w-full rounded-md border focus:outline-none focus:ring-1 ',
|
|
82
|
-
props.small ? 'text-xs py-0.5 px-2' : 'py-2 px-4',
|
|
83
|
-
props.disabled
|
|
84
|
-
? 'text-default-500 placeholder-default-300 bg-default-50'
|
|
85
|
-
: 'text-default-900 placeholder-default-400 ',
|
|
86
|
-
props.error
|
|
87
|
-
? 'border-red-500 focus:border-red-500 focus:ring-red-500 pr-10'
|
|
88
|
-
: 'border-default-300 focus:border-primary-500 focus:ring-primary-500',
|
|
89
|
-
]}/>
|
|
90
|
-
|
|
91
|
-
<div class="absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none" v-show={props.error && !props.small}>
|
|
92
|
-
<ExclamationCircleIcon class="h-5 w-5 text-red-700" aria-hidden="true"/>
|
|
93
|
-
</div>
|
|
94
|
-
</div>
|
|
95
|
-
</NTooltip>
|
|
96
|
-
</div>);
|
|
97
|
-
});
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { createComponent, createProps } from '../utils/component';
|
|
2
|
-
import { external } from '../utils/validation';
|
|
3
|
-
import { computed, Suspense } from 'vue';
|
|
4
|
-
import NValInput, { nValInputProps } from './NValInput';
|
|
5
|
-
import { trsl } from '../i18n';
|
|
6
|
-
export const nInputPhoneProps = createProps(nValInputProps);
|
|
7
|
-
/**
|
|
8
|
-
* The `NInputPhone` autoformats phone numbers and checks if they are valid.
|
|
9
|
-
*/
|
|
10
|
-
export default createComponent('NInputPhoneSuspended', nInputPhoneProps, props => {
|
|
11
|
-
// Async components have to be wrapped in a suspense component.
|
|
12
|
-
return () => (<Suspense>
|
|
13
|
-
<NPhoneInput {...props}/>
|
|
14
|
-
</Suspense>);
|
|
15
|
-
});
|
|
16
|
-
const NPhoneInput = createComponent('NInputPhone', nInputPhoneProps, async (props) => {
|
|
17
|
-
// import dynamically for better codesplitting as the library is pretty large
|
|
18
|
-
const { parsePhoneNumber } = await import('awesome-phonenumber');
|
|
19
|
-
const DEFAULT_COUNTRY_CODE = 'CH';
|
|
20
|
-
const formattedToPlain = (number) => parsePhoneNumber(number, { regionCode: DEFAULT_COUNTRY_CODE }).number?.e164;
|
|
21
|
-
const plainToFormatted = (number) => parsePhoneNumber(number, { regionCode: DEFAULT_COUNTRY_CODE }).number?.international;
|
|
22
|
-
const onUpdateValue = (newValue) => {
|
|
23
|
-
const plain = formattedToPlain(newValue);
|
|
24
|
-
props.onUpdateValue?.(plain || newValue);
|
|
25
|
-
};
|
|
26
|
-
const value = computed(() => {
|
|
27
|
-
const formatted = plainToFormatted(props.value || '');
|
|
28
|
-
return formatted || props.value;
|
|
29
|
-
});
|
|
30
|
-
const isValid = computed(() => parsePhoneNumber(props.value || '').valid);
|
|
31
|
-
return () => (<NValInput {...{ ...props, onUpdateValue }} value={value.value} rules={external(isValid.value, trsl('vue-collection.validation.rules.phone'))} type="tel"/>);
|
|
32
|
-
});
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import { createComponent, createProps } from '../utils/component';
|
|
2
|
-
import { Id } from '../utils/identifiable';
|
|
3
|
-
import { option } from '../utils/validation';
|
|
4
|
-
import { vModelForRef } from '../utils/vModel';
|
|
5
|
-
import { watchRef } from '../utils/vue';
|
|
6
|
-
import { computed, ref, watch } from 'vue';
|
|
7
|
-
import { nInputProps } from './NInput';
|
|
8
|
-
import NSuggestionList, { nSuggestionListProps } from './NSuggestionList';
|
|
9
|
-
import NValInput, { nValInputProps } from './NValInput';
|
|
10
|
-
export const nInputSelectProps = createProps({
|
|
11
|
-
...nInputProps,
|
|
12
|
-
/**
|
|
13
|
-
* The id of the currently selected option of this input.
|
|
14
|
-
*/
|
|
15
|
-
value: String,
|
|
16
|
-
/**
|
|
17
|
-
* This is called with the newly selected id when the selection has changed.
|
|
18
|
-
* This happens, when an item from the suggestion list is selected or the
|
|
19
|
-
* input matches a selection option exactly.
|
|
20
|
-
* If no id is selected, the empty string is passed, in order to
|
|
21
|
-
* match the API of all other inputs who never pass `undefined`.
|
|
22
|
-
*/
|
|
23
|
-
onUpdateValue: Function,
|
|
24
|
-
/**
|
|
25
|
-
* The options which are allowed and suggested for this input.
|
|
26
|
-
* The options are filtered based on the user input.
|
|
27
|
-
*/
|
|
28
|
-
options: {
|
|
29
|
-
type: Array,
|
|
30
|
-
default: () => [],
|
|
31
|
-
},
|
|
32
|
-
/**
|
|
33
|
-
* @see {@link nValInputProps.optional}
|
|
34
|
-
*/
|
|
35
|
-
optional: nValInputProps.optional,
|
|
36
|
-
/**
|
|
37
|
-
* @see {@link nValInputProps.form}
|
|
38
|
-
*/
|
|
39
|
-
form: nValInputProps.form,
|
|
40
|
-
/**
|
|
41
|
-
* @see {@link nValInputProps.error}
|
|
42
|
-
*/
|
|
43
|
-
error: nValInputProps.error,
|
|
44
|
-
/**
|
|
45
|
-
* @see {@link nValInputProps.errorMessage}
|
|
46
|
-
*/
|
|
47
|
-
errorMessage: nValInputProps.errorMessage,
|
|
48
|
-
/**
|
|
49
|
-
* If set to `true` the list is hidden even if there are still matching items in the list.
|
|
50
|
-
*/
|
|
51
|
-
hideList: nSuggestionListProps.hideList,
|
|
52
|
-
/**
|
|
53
|
-
* @see {@link nSuggestionListProps.maxItems}
|
|
54
|
-
*/
|
|
55
|
-
maxItems: nSuggestionListProps.maxItems,
|
|
56
|
-
/**
|
|
57
|
-
* @see {@link nSuggestionListProps.listItem}
|
|
58
|
-
*/
|
|
59
|
-
listItem: nSuggestionListProps.listItem,
|
|
60
|
-
});
|
|
61
|
-
/**
|
|
62
|
-
* The `NInputSelect` is very similar to the {@link NSelect}, but instead of a select input it is a regular input.
|
|
63
|
-
* The user is forced to use a value from the specified options of the input.
|
|
64
|
-
* While they type, the list of options is shown to them and filtered based on their input.
|
|
65
|
-
*/
|
|
66
|
-
export default createComponent('NInputSelect', nInputSelectProps, props => {
|
|
67
|
-
const inputRef = ref();
|
|
68
|
-
const inputValue = ref('');
|
|
69
|
-
watch(() => props.value, newValue => {
|
|
70
|
-
if (newValue) {
|
|
71
|
-
const chosenOption = Id.find(props.options, newValue);
|
|
72
|
-
if (chosenOption)
|
|
73
|
-
inputValue.value = chosenOption.label;
|
|
74
|
-
}
|
|
75
|
-
}, { immediate: true });
|
|
76
|
-
const filteredOptions = computed(() => props.options.filter(option => option.label.includes(inputValue.value || '')));
|
|
77
|
-
const matchedOption = computed(() => {
|
|
78
|
-
const matches = props.options.filter(option => option.label === inputValue.value);
|
|
79
|
-
return matches.length > 0 ? matches[0] : null;
|
|
80
|
-
});
|
|
81
|
-
watchRef(matchedOption, newOption => props.onUpdateValue?.(newOption?.id || ''));
|
|
82
|
-
return () => (<NSuggestionList items={filteredOptions.value} onSelect={props.onUpdateValue} inputValue={inputValue.value} hideList={props.hideList || matchedOption.value != null || filteredOptions.value.length == 0} maxItems={props.maxItems} listItem={props.listItem} input={({ onFocus, onBlur }) => (<NValInput ref={inputRef} {...{ ...props, ...vModelForRef(inputValue) }} rules={option(props.options.map(opt => opt.label))} onFocus={() => {
|
|
83
|
-
onFocus();
|
|
84
|
-
props.onFocus?.();
|
|
85
|
-
}} onBlur={onBlur} disableBlurValidation/>)} onRequestInputFocus={() => inputRef.value?.focus()} onRealBlur={() => {
|
|
86
|
-
props.onBlur?.();
|
|
87
|
-
inputRef?.value?.validate();
|
|
88
|
-
}}/>);
|
|
89
|
-
});
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { createComponent, createProps } from '../utils/component';
|
|
2
|
-
import { Id } from '../utils/identifiable';
|
|
3
|
-
import { computed, ref } from 'vue';
|
|
4
|
-
import NSuggestionList, { nSuggestionListProps } from './NSuggestionList';
|
|
5
|
-
import NValInput, { nValInputProps } from './NValInput';
|
|
6
|
-
export const nInputSuggestionProps = createProps({
|
|
7
|
-
...nValInputProps,
|
|
8
|
-
/**
|
|
9
|
-
* If set to `true` the list is hidden even if there are still matching items in the list.
|
|
10
|
-
*/
|
|
11
|
-
hideList: nSuggestionListProps.hideList,
|
|
12
|
-
/**
|
|
13
|
-
* @see {@link nSuggestionListProps.maxItems}
|
|
14
|
-
*/
|
|
15
|
-
maxItems: nSuggestionListProps.maxItems,
|
|
16
|
-
/**
|
|
17
|
-
* The suggestions which are shown to the user for this input.
|
|
18
|
-
* The suggestions are filtered based on the user input.
|
|
19
|
-
*/
|
|
20
|
-
suggestions: {
|
|
21
|
-
type: Array,
|
|
22
|
-
default: () => [],
|
|
23
|
-
},
|
|
24
|
-
});
|
|
25
|
-
/**
|
|
26
|
-
* `NInputSuggestion` is an input, which shows a list of possible suggestions to the user
|
|
27
|
-
* which is filtered while typing. Contrary to {@link NInputSelect} the user is not required to choose any of the suggestions.
|
|
28
|
-
*/
|
|
29
|
-
export default createComponent('NInputSuggestion', nInputSuggestionProps, props => {
|
|
30
|
-
const suggestionItems = computed(() => props.suggestions
|
|
31
|
-
.filter(suggestion => suggestion.includes(props.value || ''))
|
|
32
|
-
.map((value, index) => ({
|
|
33
|
-
id: index.toString(),
|
|
34
|
-
label: value,
|
|
35
|
-
})));
|
|
36
|
-
const select = (id) => props.onUpdateValue?.(Id.find(suggestionItems.value, id)?.label || '');
|
|
37
|
-
const hideList = computed(() => props.hideList ||
|
|
38
|
-
suggestionItems.value.length == 0 ||
|
|
39
|
-
suggestionItems.value.filter(suggestion => suggestion.label !== props.value).length == 0);
|
|
40
|
-
const inputRef = ref();
|
|
41
|
-
return () => (<NSuggestionList items={suggestionItems.value} onSelect={id => select(id)} inputValue={props.value || ''} hideList={hideList.value} maxItems={props.maxItems} input={({ onFocus, onBlur }) => (<NValInput ref={inputRef} {...props} onFocus={() => {
|
|
42
|
-
onFocus();
|
|
43
|
-
props.onFocus?.();
|
|
44
|
-
}} onBlur={onBlur} disableBlurValidation/>)} onRequestInputFocus={() => inputRef.value?.focus()} onRealBlur={() => {
|
|
45
|
-
props.onBlur?.();
|
|
46
|
-
inputRef?.value?.validate();
|
|
47
|
-
}}/>);
|
|
48
|
-
});
|
package/components/NLink.jsx
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { createComponent, createProps } from '../utils/component';
|
|
2
|
-
import { computed } from 'vue';
|
|
3
|
-
import { RouterLink } from 'vue-router';
|
|
4
|
-
export const nLinkProps = createProps({
|
|
5
|
-
/**
|
|
6
|
-
* The text of the link. Can also be set in the default slot.
|
|
7
|
-
*/
|
|
8
|
-
text: String,
|
|
9
|
-
/**
|
|
10
|
-
* The route of the link. If this is set,
|
|
11
|
-
* the link becomes a {@link RouterLink} and does not emit the `onClick` event.
|
|
12
|
-
*/
|
|
13
|
-
route: [Object, String],
|
|
14
|
-
/**
|
|
15
|
-
* The color of the link.
|
|
16
|
-
*/
|
|
17
|
-
color: {
|
|
18
|
-
type: String,
|
|
19
|
-
default: 'primary',
|
|
20
|
-
},
|
|
21
|
-
/**
|
|
22
|
-
* The text size, a standard tailwind text-size class.
|
|
23
|
-
*/
|
|
24
|
-
textSize: String,
|
|
25
|
-
/**
|
|
26
|
-
* The shade of the link.
|
|
27
|
-
*/
|
|
28
|
-
shade: {
|
|
29
|
-
type: Number,
|
|
30
|
-
default: 500,
|
|
31
|
-
},
|
|
32
|
-
/**
|
|
33
|
-
* This is called when the link is clicked but only, if the `route` prop is not set.
|
|
34
|
-
* If the `route` prop is not set, the link will act as a regular button.
|
|
35
|
-
*/
|
|
36
|
-
onClick: Function,
|
|
37
|
-
});
|
|
38
|
-
/**
|
|
39
|
-
* The `NLink` is a styled text which can be used as a {@link RouterLink} or a regular button.
|
|
40
|
-
*/
|
|
41
|
-
export default createComponent('NLink', nLinkProps, (props, { slots }) => {
|
|
42
|
-
const hoverShade = computed(() => {
|
|
43
|
-
const shade = props.shade;
|
|
44
|
-
if (shade <= 500)
|
|
45
|
-
return shade + 100;
|
|
46
|
-
else
|
|
47
|
-
return shade - 200;
|
|
48
|
-
});
|
|
49
|
-
const classes = computed(() => [
|
|
50
|
-
'font-medium focus:outline-none focus-visible:ring-2 rounded-sm ring-offset-2 hover:underline text-left',
|
|
51
|
-
`${props.textSize} text-${props.color}-${props.shade} hover:text-${props.color}-${hoverShade.value} focus-visible:ring-${props.color}-${props.shade}`,
|
|
52
|
-
]);
|
|
53
|
-
return () => props.route ? (<RouterLink to={props.route} class={classes.value}>
|
|
54
|
-
{slots.default?.() || props.text}
|
|
55
|
-
</RouterLink>) : (<button onClick={props.onClick} class={classes.value}>
|
|
56
|
-
{slots.default?.() || props.text}
|
|
57
|
-
</button>);
|
|
58
|
-
});
|
package/components/NList.jsx
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { createComponent, createProps } from '../utils/component';
|
|
2
|
-
export const nListProps = createProps({
|
|
3
|
-
/**
|
|
4
|
-
* The items which are displayed in the list.
|
|
5
|
-
*/
|
|
6
|
-
items: {
|
|
7
|
-
type: Array,
|
|
8
|
-
default: () => [],
|
|
9
|
-
},
|
|
10
|
-
});
|
|
11
|
-
/**
|
|
12
|
-
* The `NList` displays key-value data in an appealing way.
|
|
13
|
-
*/
|
|
14
|
-
export default createComponent('NList', nListProps, props => {
|
|
15
|
-
return () => (<dl>
|
|
16
|
-
{props.items.map((item, index) => (<div key={index} class={[
|
|
17
|
-
'py-5 px-4 sm:grid sm:grid-cols-3 sm:gap-4',
|
|
18
|
-
index % 2 === 1 ? 'bg-white' : 'bg-default-50',
|
|
19
|
-
]}>
|
|
20
|
-
<dt class="text-sm font-medium text-default-500">{item.title}</dt>
|
|
21
|
-
<dd class="mt-1 text-sm sm:mt-0 sm:col-span-2">{item.text}</dd>
|
|
22
|
-
</div>))}
|
|
23
|
-
</dl>);
|
|
24
|
-
});
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { createComponent, createProps } from '../utils/component';
|
|
2
|
-
import { computed, useCssVars } from 'vue';
|
|
3
|
-
import './NLoadingIndicator.css';
|
|
4
|
-
export const nLoadingIndicator = createProps({
|
|
5
|
-
/**
|
|
6
|
-
* The color of the loading-indicator.
|
|
7
|
-
*/
|
|
8
|
-
color: {
|
|
9
|
-
type: String,
|
|
10
|
-
default: 'primary',
|
|
11
|
-
},
|
|
12
|
-
/**
|
|
13
|
-
* The shade of the loading-indicator.
|
|
14
|
-
*/
|
|
15
|
-
shade: {
|
|
16
|
-
type: Number,
|
|
17
|
-
default: 400,
|
|
18
|
-
},
|
|
19
|
-
/**
|
|
20
|
-
* The height of the loading-indicator in px.
|
|
21
|
-
*/
|
|
22
|
-
size: {
|
|
23
|
-
type: Number,
|
|
24
|
-
default: 10,
|
|
25
|
-
},
|
|
26
|
-
});
|
|
27
|
-
/**
|
|
28
|
-
* The `NLoadingIndicator` is a styled loading indicator.
|
|
29
|
-
*/
|
|
30
|
-
export default createComponent('NLoadingIndicator', nLoadingIndicator, props => {
|
|
31
|
-
const gap = computed(() => (props.size / 13) * 24);
|
|
32
|
-
const totalWidth = computed(() => gap.value * 2 + props.size);
|
|
33
|
-
useCssVars(() => ({
|
|
34
|
-
'n-loading-indicator-gap': `${gap.value}px`,
|
|
35
|
-
}));
|
|
36
|
-
return () => (<div class="lds-ellipsis" style={`height:${props.size}px;width:${totalWidth.value}px`}>
|
|
37
|
-
<div class={`bg-${props.color}-${props.shade}`} style={`height:${props.size}px;width:${props.size}px;left:0px`}/>
|
|
38
|
-
<div class={`bg-${props.color}-${props.shade}`} style={`height:${props.size}px;width:${props.size}px;left:0px`}/>
|
|
39
|
-
<div class={`bg-${props.color}-${props.shade}`} style={`height:${props.size}px;width:${props.size}px;left:${gap.value}px`}/>
|
|
40
|
-
<div class={`bg-${props.color}-${props.shade}`} style={`height:${props.size}px;width:${props.size}px;left:${2 * gap.value}px`}/>
|
|
41
|
-
</div>);
|
|
42
|
-
});
|