Skip to content

Commit f0fa538

Browse files
committed
feat: number field
1 parent 1a9c575 commit f0fa538

6 files changed

Lines changed: 90 additions & 6 deletions

File tree

resources/js/components/inputs/FormInputNumber.vue renamed to resources/js/components-archive/inputs/FormInputNumber.vue

File renamed without changes.
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<script setup lang="ts">
2+
import type { FormFieldValue, FormNumberFieldProps } from '@aminnausin/cedar-ui';
3+
4+
import { LucideChevronDown, LucideChevronUp } from '../icons';
5+
import { ButtonIcon } from '../button';
6+
import { InputShell } from '../input';
7+
8+
const props = withDefaults(defineProps<FormNumberFieldProps>(), { increment: 1 });
9+
const model = defineModel<FormFieldValue>();
10+
11+
const normalise = (): number | null => {
12+
if (typeof model.value !== 'number') {
13+
model.value = 0;
14+
}
15+
return model.value;
16+
};
17+
18+
const clampValue = (value: number) => {
19+
const { min, max } = props.field;
20+
21+
if (min != undefined && value < min) return min;
22+
if (max != undefined && value > max) return max;
23+
24+
return value;
25+
};
26+
27+
const step = (delta: 1 | -1) => {
28+
const current = normalise();
29+
if (current == null) return;
30+
31+
const next = current + delta * props.increment;
32+
model.value = clampValue(next);
33+
};
34+
35+
const clamp = () => {
36+
if (typeof model.value !== 'number') return;
37+
model.value = clampValue(model.value);
38+
};
39+
</script>
40+
41+
<template>
42+
<span class="relative mt-1 inline-flex w-full text-sm">
43+
<InputShell>
44+
<template #input="{ class: inputClass }">
45+
<input
46+
@change="clamp"
47+
@blur="clamp"
48+
v-model="model"
49+
type="number"
50+
:id="field.name"
51+
:name="field.name"
52+
:title="field.text ?? field.name"
53+
:required="field.required"
54+
:disabled="field.disabled"
55+
:placeholder="field.placeholder"
56+
:aria-autocomplete="field.autocomplete ? 'list' : 'none'"
57+
:class="['pe-12', inputClass]"
58+
:min="field.min"
59+
:max="field.max"
60+
/>
61+
</template>
62+
</InputShell>
63+
64+
<span class="absolute top-0 right-0 flex h-full w-12 flex-col">
65+
<ButtonIcon
66+
@click.prevent.stop="step(1)"
67+
class="focus:ring-primary hover:bg-overlay-border/50 h-1/2 rounded-none rounded-tr-md ring-inset focus:ring-2"
68+
:title="`Increment ${field.name}`"
69+
:variant="'ghost'"
70+
>
71+
<LucideChevronUp width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" class="size-4" />
72+
</ButtonIcon>
73+
<ButtonIcon
74+
@click.prevent.stop="step(-1)"
75+
class="focus:ring-primary hover:bg-overlay-border/50 h-1/2 rounded-none rounded-br-md ring-inset focus:ring-2"
76+
:title="`Decrement ${field.name}`"
77+
:variant="'ghost'"
78+
>
79+
<LucideChevronDown width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" class="size-4" />
80+
</ButtonIcon>
81+
</span>
82+
</span>
83+
</template>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default as FormNumberField } from './FormNumberField.vue';

resources/js/components/forms/EditFolder.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ import type { SeriesUpdateRequest } from '@/types/requests';
66
import { handleStorageURL, toCalendarFormattedDate } from '@/service/util';
77
import { FormInput, FormLabel, FormErrorList } from '@/components/cedar-ui/form';
88
import { computed, reactive, ref, watch } from 'vue';
9+
import { FormNumberField } from '@/components/cedar-ui/number-field';
910
import { useGetAllTags } from '@/service/queries';
1011
import { FormTextArea } from '@/components/cedar-ui/textarea';
1112
import { UseCreateTag } from '@/service/mutations';
1213
import { toast } from '@aminnausin/cedar-ui';
1314
14-
import FormInputNumber from '@/components/inputs/FormInputNumber.vue';
1515
import InputMultiChip from '@/components/pinesUI/InputMultiChip.vue';
1616
import DatePicker from '@/components/pinesUI/DatePicker.vue';
1717
import mediaAPI from '@/service/mediaAPI.ts';
@@ -206,7 +206,7 @@ watch(tagsQuery, () => {
206206

207207
<FormTextArea v-if="field.type === 'textArea'" v-model="form.fields[field.name]" :field="field" />
208208
<DatePicker v-else-if="field.type === 'date'" v-model="form.fields[field.name]" :field="field" />
209-
<FormInputNumber v-else-if="field.type === 'number'" v-model="form.fields[field.name]" :field="field" />
209+
<FormNumberField v-else-if="field.type === 'number'" v-model="form.fields[field.name]" :field="field" />
210210
<InputMultiChip
211211
v-else-if="field.name === 'tags'"
212212
:placeholder="'Add tags'"

resources/js/components/forms/EditLyrics.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ import { FormInput, FormLabel, FormErrorList } from '@/components/cedar-ui/form'
99
import { ButtonForm, ButtonText } from '@/components/cedar-ui/button';
1010
import { TableLoadingSpinner } from '@/components/cedar-ui/table';
1111
import { toFormattedDuration } from '@/service/util';
12+
import { FormNumberField } from '@/components/cedar-ui/number-field';
1213
import { useLyricStore } from '@/stores/LyricStore';
1314
import { FormTextArea } from '@/components/cedar-ui/textarea';
1415
import { storeToRefs } from 'pinia';
1516
import { toast } from '@aminnausin/cedar-ui';
1617
17-
import FormInputNumber from '@/components/inputs/FormInputNumber.vue';
1818
import LrcLibCard from '@/components/cards/data/LrcLibCard.vue';
1919
import DatePicker from '@/components/pinesUI/DatePicker.vue';
2020
import useForm from '@/composables/useForm';
@@ -140,7 +140,7 @@ watch(
140140
<FormInput v-if="field.name === 'duration'" :field="field" v-model="field.value" disabled title="Song Duration" />
141141
<FormTextArea v-else-if="field.type === 'textArea'" v-model="form.fields[field.name]" :field="field" />
142142
<DatePicker v-else-if="field.type === 'date'" v-model="form.fields[field.name]" :field="field" />
143-
<FormInputNumber v-else-if="field.type === 'number'" v-model="form.fields[field.name]" :field="field" />
143+
<FormNumberField v-else-if="field.type === 'number'" v-model="form.fields[field.name]" :field="field" />
144144
<FormInput v-else v-model="form.fields[field.name]" :field="field" />
145145
<FormErrorList :errors="form.errors" :field-name="field.name" />
146146
</div>

resources/js/components/forms/EditVideo.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type { MetadataUpdateRequest } from '@/types/requests';
66
import { FormInput, FormLabel, FormErrorList } from '@/components/cedar-ui/form';
77
import { computed, reactive, ref, watch } from 'vue';
88
import { toCalendarFormattedDate } from '@/service/util';
9+
import { FormNumberField } from '@/components/cedar-ui/number-field';
910
import { useContentStore } from '@/stores/ContentStore';
1011
import { useGetAllTags } from '@/service/queries';
1112
import { FormTextArea } from '@/components/cedar-ui/textarea';
@@ -14,7 +15,6 @@ import { storeToRefs } from 'pinia';
1415
import { MediaType } from '@/types/types';
1516
import { toast } from '@aminnausin/cedar-ui';
1617
17-
import FormInputNumber from '@/components/inputs/FormInputNumber.vue';
1818
import InputMultiChip from '@/components/pinesUI/InputMultiChip.vue';
1919
import DatePicker from '@/components/pinesUI/DatePicker.vue';
2020
import mediaAPI from '@/service/mediaAPI.ts';
@@ -221,7 +221,7 @@ watch(tagsQuery, () => {
221221

222222
<FormTextArea v-if="field.type === 'textArea'" v-model="form.fields[field.name]" :field="field" />
223223
<DatePicker v-else-if="field.type === 'date'" v-model="form.fields[field.name]" :field="field" />
224-
<FormInputNumber v-else-if="field.type === 'number'" v-model="form.fields[field.name]" :field="field" />
224+
<FormNumberField v-else-if="field.type === 'number'" v-model="form.fields[field.name]" :field="field" />
225225
<InputMultiChip
226226
v-else-if="field.name === 'video_tags'"
227227
:placeholder="'Add tags'"

0 commit comments

Comments
 (0)