Skip to content

Commit cff23cf

Browse files
committed
add last missing input fields
1 parent e61a73e commit cff23cf

File tree

15 files changed

+332
-20
lines changed

15 files changed

+332
-20
lines changed

exampleVault/Input Fields/Date and Time.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
2-
time: 14:12
2+
time: 21:03
33
date2: 2023-10-21
4-
date1: 2023-06-08
4+
date1: 2023-01-01
55
---
66

77
### Date
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
---
2-
progress1: -6
2+
progress1: -4
3+
progress2: 0.2
34
---
45

56
```meta-bind
67
INPUT[progressBar(showcase, minValue(-10), maxValue(3)):progress1]
78
```
89

910

11+
```meta-bind
12+
INPUT[progressBar(showcase, minValue(0), maxValue(1), stepSize(0.1)):progress2]
13+
```
14+
15+
1016

src/inputFields/_new/NewInputFieldFactory.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import { InlineSelectIPF } from './fields/InlineSelect/InlineSelectIPF';
1717
import { ImageSuggesterIPF } from './fields/ImageSuggester/ImageSuggesterIPF';
1818
import { ListIPF } from './fields/List/ListIPF';
1919
import { ListSuggesterIPF } from './fields/ListSuggester/ListSuggesterIPF';
20+
import { DateIPF } from './fields/Date/DateIPF';
21+
import { TimeIPF } from './fields/Time/TimeIPF';
2022

2123
export type NewInputField =
2224
| ToggleIPF
@@ -33,7 +35,9 @@ export type NewInputField =
3335
| InlineSelectIPF
3436
| ImageSuggesterIPF
3537
| ListIPF
36-
| ListSuggesterIPF;
38+
| ListSuggesterIPF
39+
| DateIPF
40+
| TimeIPF;
3741

3842
export class NewInputFieldFactory {
3943
plugin: IPlugin;
@@ -47,7 +51,7 @@ export class NewInputFieldFactory {
4751
this.checkRenderChildTypeAllowed(type, renderChildType);
4852
}
4953

50-
// Skipped: Date, Time, List Suggester
54+
// Skipped: Date, Time
5155

5256
if (type === InputFieldType.TOGGLE) {
5357
return new ToggleIPF(renderChild);
@@ -85,6 +89,10 @@ export class NewInputFieldFactory {
8589
return new ListIPF(renderChild);
8690
} else if (type === InputFieldType.LIST_SUGGESTER) {
8791
return new ListSuggesterIPF(renderChild);
92+
} else if (type === InputFieldType.DATE) {
93+
return new DateIPF(renderChild);
94+
} else if (type === InputFieldType.TIME) {
95+
return new TimeIPF(renderChild);
8896
}
8997

9098
return undefined;
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
<script lang="ts">
2+
import type { moment } from 'obsidian';
3+
import { onMount } from 'svelte';
4+
import { DateParser } from '../../../../parsers/DateParser';
5+
6+
export let value: moment.Moment;
7+
export let useUsInputOrder: boolean;
8+
export let onValueChange: (value: moment.Moment) => void;
9+
10+
let months: Record<string, string> = {};
11+
let days: Record<string, string> = {};
12+
13+
let year: string;
14+
let month: string;
15+
let day: string;
16+
17+
onMount(() => {
18+
months = {
19+
'0': 'January',
20+
'1': 'February',
21+
'2': 'March',
22+
'3': 'April',
23+
'4': 'May',
24+
'5': 'June',
25+
'6': 'July',
26+
'7': 'August',
27+
'8': 'September',
28+
'9': 'October',
29+
'10': 'November',
30+
'11': 'December',
31+
}
32+
33+
for (let i = 1; i <= 31; i++) {
34+
days[i.toString()] = i.toString();
35+
}
36+
37+
year = value.year().toString();
38+
month = value.month().toString();
39+
day = value.date().toString();
40+
})
41+
42+
export function setValue(v: moment.Moment): void {
43+
value = v;
44+
45+
year = value.year().toString();
46+
month = value.month().toString();
47+
day = value.date().toString();
48+
}
49+
50+
function onYearChange(): void {
51+
const parseRes = Number.parseInt(year);
52+
const yearNumber = Number.isNaN(parseRes) ? DateParser.getDefaultYear() : parseRes;
53+
54+
value.year(yearNumber);
55+
// year = yearNumber.toString();
56+
57+
onValueChange(value);
58+
}
59+
60+
function onMonthChange(): void {
61+
value.month(month);
62+
63+
const clampedDay = clampDay(value.date());
64+
65+
value.date(clampedDay);
66+
day = clampedDay.toString();
67+
68+
onValueChange(value);
69+
}
70+
71+
function onDayChange(): void {
72+
const parseRes = Number.parseInt(day);
73+
const clampedDay = clampDay(parseRes);
74+
75+
value.date(clampedDay);
76+
day = clampedDay.toString();
77+
78+
onValueChange(value);
79+
}
80+
81+
function clampDay(day: number): number {
82+
if (Number.isNaN(day)) {
83+
return DateParser.getDefaultDay();
84+
} else if (day < 1) {
85+
return 1;
86+
} else if (day > value.daysInMonth()) {
87+
return value.daysInMonth();
88+
}
89+
return day;
90+
}
91+
</script>
92+
93+
<div class='mb-input-element-group'>
94+
{#if useUsInputOrder}
95+
<select class='dropdown mb-input-element-group-element' bind:value={month} on:change={() => onMonthChange()}>
96+
{#each Object.entries(months) as [_month, _monthName]}
97+
<option value={_month}>{_monthName}</option>
98+
{/each}
99+
</select>
100+
101+
<select class='dropdown mb-input-element-group-element' bind:value={day} on:change={() => onDayChange()}>
102+
{#each Object.values(days) as _day}
103+
<option value={_day}>{_day}</option>
104+
{/each}
105+
</select>
106+
{:else}
107+
<select class='dropdown mb-input-element-group-element' bind:value={day} on:change={() => onDayChange()}>
108+
{#each Object.values(days) as _day}
109+
<option value={_day}>{_day}</option>
110+
{/each}
111+
</select>
112+
113+
<select class='dropdown mb-input-element-group-element' bind:value={month} on:change={() => onMonthChange()}>
114+
{#each Object.entries(months) as [_month, _monthName]}
115+
<option value={_month}>{_monthName}</option>
116+
{/each}
117+
</select>
118+
{/if}
119+
120+
<select class='dropdown mb-input-element-group-element' bind:value={day} on:change={() => onDayChange()}>
121+
{#each Object.values(days) as _day}
122+
<option value={_day}>{_day}</option>
123+
{/each}
124+
</select>
125+
126+
<select class='dropdown mb-input-element-group-element' bind:value={month} on:change={() => onMonthChange()}>
127+
{#each Object.entries(months) as [_month, _monthName]}
128+
<option value={_month}>{_monthName}</option>
129+
{/each}
130+
</select>
131+
132+
<input class='mb-date-input-year-input mb-input-element-group-element' type='number' tabindex='0' bind:value={year} on:input={() => onYearChange()} max=9999 min=0>
133+
</div>
134+
135+
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { NewAbstractInputField } from '../../NewAbstractInputField';
2+
import { type moment } from 'obsidian';
3+
import { type SvelteComponent } from 'svelte';
4+
import { type InputFieldMDRC } from '../../../../renderChildren/InputFieldMDRC';
5+
import { parseUnknownToString } from '../../../../utils/Utils';
6+
import { DateParser } from '../../../../parsers/DateParser';
7+
import DateComponent from './DateComponent.svelte';
8+
9+
export class DateIPF extends NewAbstractInputField<string, moment.Moment> {
10+
constructor(renderChild: InputFieldMDRC) {
11+
super(renderChild);
12+
}
13+
14+
protected filterValue(value: unknown): string | undefined {
15+
return parseUnknownToString(value);
16+
}
17+
18+
protected getFallbackDefaultValue(): moment.Moment {
19+
return DateParser.getDefaultDate();
20+
}
21+
22+
protected getSvelteComponent(): typeof SvelteComponent {
23+
return DateComponent;
24+
}
25+
26+
protected rawMapValue(value: moment.Moment): string {
27+
return DateParser.stringify(value);
28+
}
29+
30+
protected rawReverseMapValue(value: string): moment.Moment | undefined {
31+
return DateParser.parse(value);
32+
}
33+
34+
protected getMountArgs(): Record<string, unknown> {
35+
return {
36+
useUsInputOrder: this.renderChild.plugin.settings.useUsDateInputOrder,
37+
};
38+
}
39+
}

src/inputFields/_new/fields/DatePicker/DatePickerComponent.svelte

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
<script lang='ts'>
2-
import type { Moment } from 'moment';
2+
import type { moment } from 'obsidian';
33
import Icon from '../../../../utils/Icon.svelte';
44
5-
export let value: Moment | null;
5+
export let value: moment.Moment | null;
66
export let dateFormat: string;
77
export let showDatePicker: () => void;
8-
export let onValueChange: (value: Moment | null) => void;
8+
export let onValueChange: (value: moment.Moment | null) => void;
99
10-
export function setValue(v: Moment | null): void {
10+
export function setValue(v: moment.Moment | null): void {
1111
value = v;
1212
}
1313

src/inputFields/_new/fields/ProgressBar/ProgressBarComponent.svelte

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
export let value: number;
66
export let minValue: number;
77
export let maxValue: number;
8+
export let stepSize: number;
89
910
1011
let drag: boolean = false;
@@ -64,13 +65,21 @@
6465
clientX = clamp(clientX, boundingRect.left, boundingRect.right);
6566
6667
let value = remapRange(clientX, boundingRect.left, boundingRect.right, minValue, maxValue);
67-
value = Math.round(value);
68+
value = round(value, stepSize);
6869
6970
setValueInternal(value);
7071
}
7172
73+
function round(number: number, increment: number) {
74+
// the parsing is done to fix floating point errors
75+
return Number.parseFloat((Math.round(number / increment ) * increment).toFixed(15));
76+
}
77+
7278
function onKeyPress(e: KeyboardEvent) {
73-
if (keydownAcceleration < 50) keydownAcceleration++;
79+
if (keydownAcceleration < 50) {
80+
keydownAcceleration += 1;
81+
}
82+
7483
let throttled = Math.ceil(keydownAcceleration / 5);
7584
7685
if (e.key === 'ArrowUp' || e.key === 'ArrowRight') {

src/inputFields/_new/fields/ProgressBar/ProgressBarIPF.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,27 @@ import { InputFieldArgumentType } from '../../../../parsers/inputFieldParser/Inp
44
import { optClamp, parseUnknownToFloat } from '../../../../utils/Utils';
55
import { type SvelteComponent } from 'svelte';
66
import ProgressBarComponent from './ProgressBarComponent.svelte';
7+
import { ErrorLevel, MetaBindArgumentError } from '../../../../utils/errors/MetaBindErrors';
78

89
export class ProgressBarIPF extends NewAbstractInputField<number, number> {
910
minValue: number;
1011
maxValue: number;
12+
stepSize: number;
1113

1214
constructor(renderChild: InputFieldMDRC) {
1315
super(renderChild);
1416

1517
this.minValue = this.renderChild.getArgument(InputFieldArgumentType.MIN_VALUE)?.value ?? 0;
1618
this.maxValue = this.renderChild.getArgument(InputFieldArgumentType.MAX_VALUE)?.value ?? 100;
19+
this.stepSize = this.renderChild.getArgument(InputFieldArgumentType.STEP_SIZE)?.value ?? 1;
20+
21+
if (this.minValue >= this.maxValue) {
22+
throw new MetaBindArgumentError(
23+
ErrorLevel.ERROR,
24+
'can not create progress bar input field',
25+
`minValue (${this.maxValue}) must be less than maxValue (${this.maxValue})`,
26+
);
27+
}
1728
}
1829

1930
protected filterValue(value: unknown): number | undefined {
@@ -40,6 +51,7 @@ export class ProgressBarIPF extends NewAbstractInputField<number, number> {
4051
return {
4152
minValue: this.minValue,
4253
maxValue: this.maxValue,
54+
stepSize: this.stepSize,
4355
};
4456
}
4557
}

src/inputFields/_new/fields/Slider/SliderIPF.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { type InputFieldMDRC } from '../../../../renderChildren/InputFieldMDRC';
44
import { type SvelteComponent } from 'svelte';
55
import SliderComponent from './SliderComponent.svelte';
66
import { InputFieldArgumentType } from '../../../../parsers/inputFieldParser/InputFieldConfigs';
7+
import { ErrorLevel, MetaBindArgumentError } from '../../../../utils/errors/MetaBindErrors';
78

89
export class SliderIPF extends NewAbstractInputField<number, number> {
910
minValue: number;
@@ -17,6 +18,14 @@ export class SliderIPF extends NewAbstractInputField<number, number> {
1718
this.minValue = this.renderChild.getArgument(InputFieldArgumentType.MIN_VALUE)?.value ?? 0;
1819
this.maxValue = this.renderChild.getArgument(InputFieldArgumentType.MAX_VALUE)?.value ?? 100;
1920
this.stepSize = this.renderChild.getArgument(InputFieldArgumentType.STEP_SIZE)?.value ?? 1;
21+
22+
if (this.minValue >= this.maxValue) {
23+
throw new MetaBindArgumentError(
24+
ErrorLevel.ERROR,
25+
'can not create slider input field',
26+
`minValue (${this.maxValue}) must be less than maxValue (${this.maxValue})`,
27+
);
28+
}
2029
}
2130

2231
protected filterValue(value: unknown): number | undefined {

0 commit comments

Comments
 (0)