Skip to content

Commit dc95fcf

Browse files
committed
fix #193
1 parent 6d0b680 commit dc95fcf

File tree

13 files changed

+192
-655
lines changed

13 files changed

+192
-655
lines changed

exampleVault/View Fields/View Field.md

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,13 @@ list:
1111
object:
1212
key: value
1313
file: Example Note with Embeds
14-
image: Other/Images/img_butterfly.webp
14+
image: Other/Images/subfolder/img_frozen_branch.jpg
1515
someInputValue: 1
1616
someComputedValue: 2
1717
images:
1818
- Other/Images/img_flower.webp
1919
- Other/Images/img_butterfly.webp
2020
- Other/Images/subfolder/img_frozen_branch.jpg
21-
- Other/Images/img_drops.jpg
2221
---
2322

2423
`INPUT[number:number1]`
@@ -62,20 +61,10 @@ Self Loop Error: `VIEW[**{computed}**][text():computed]`
6261
INPUT[imageSuggester(optionQuery("Other/Images")):image]
6362
```
6463

65-
`VIEW[!\[\[{image}\]\]][text(renderMarkdown)]`
6664
`VIEW[{image}][image]`
6765

6866
```meta-bind
69-
INPUT[imageSuggester(optionQuery("Other/Images")):images[0]]
70-
```
71-
```meta-bind
72-
INPUT[imageSuggester(optionQuery("Other/Images")):images[1]]
73-
```
74-
```meta-bind
75-
INPUT[imageSuggester(optionQuery("Other/Images")):images[2]]
76-
```
77-
```meta-bind
78-
INPUT[imageSuggester(optionQuery("Other/Images")):images[3]]
67+
INPUT[imageListSuggester(optionQuery("Other/Images")):images]
7968
```
8069

8170
`VIEW[{images}][image]`

packages/core/src/api/InternalAPI.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { type DatePickerIPF } from 'packages/core/src/fields/inputFields/fields/DatePicker/DatePickerIPF';
2-
import { type ImageSuggesterIPF } from 'packages/core/src/fields/inputFields/fields/ImageSuggester/ImageSuggesterIPF';
32
import {
3+
type ImageSuggesterLikeIPF,
44
type SuggesterLikeIFP,
55
type SuggesterOption,
66
} from 'packages/core/src/fields/inputFields/fields/Suggester/SuggesterHelper';
@@ -67,7 +67,7 @@ export abstract class InternalAPI<Plugin extends IPlugin> {
6767
*
6868
* @param inputField
6969
*/
70-
abstract getImageSuggesterOptions(inputField: ImageSuggesterIPF): SuggesterOption<string>[];
70+
abstract getImageSuggesterOptions(inputField: ImageSuggesterLikeIPF): SuggesterOption<string>[];
7171

7272
/**
7373
* Get the options for the suggester input field.
@@ -248,7 +248,7 @@ export abstract class InternalAPI<Plugin extends IPlugin> {
248248
this.createSearchModal(new SuggesterSelectModal(this.plugin, selectCallback, inputField)).open();
249249
}
250250

251-
openImageSuggesterModal(inputField: ImageSuggesterIPF, selectCallback: (selected: string) => void): void {
251+
openImageSuggesterModal(inputField: ImageSuggesterLikeIPF, selectCallback: (selected: string) => void): void {
252252
this.createModal(
253253
new SvelteModalContent((modal, targetEl) => {
254254
return new ImageSuggesterModalComponent({

packages/core/src/config/FieldConfigs.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export enum InputFieldType {
3434
LIST_SUGGESTER = 'listSuggester',
3535
INLINE_LIST_SUGGESTER = 'inlineListSuggester',
3636
INLINE_LIST = 'inlineList',
37+
IMAGE_LIST_SUGGESTER = 'imageListSuggester',
3738

3839
INVALID = 'invalid',
3940
}
@@ -162,6 +163,11 @@ export const InputFieldConfigs: Record<InputFieldType, InputFieldConfig> = {
162163
allowInBlock: true,
163164
allowInline: true,
164165
},
166+
[InputFieldType.IMAGE_LIST_SUGGESTER]: {
167+
type: InputFieldType.IMAGE_LIST_SUGGESTER,
168+
allowInBlock: true,
169+
allowInline: false,
170+
},
165171
[InputFieldType.INVALID]: {
166172
type: InputFieldType.INVALID,
167173
allowInBlock: false,
@@ -301,6 +307,7 @@ export const InputFieldArgumentConfigs: Record<InputFieldArgumentType, InputFiel
301307
InputFieldType.INLINE_SELECT,
302308
InputFieldType.LIST_SUGGESTER,
303309
InputFieldType.INLINE_LIST_SUGGESTER,
310+
InputFieldType.IMAGE_LIST_SUGGESTER,
304311
],
305312
values: [
306313
[
@@ -332,6 +339,7 @@ export const InputFieldArgumentConfigs: Record<InputFieldArgumentType, InputFiel
332339
InputFieldType.IMAGE_SUGGESTER,
333340
InputFieldType.LIST_SUGGESTER,
334341
InputFieldType.INLINE_LIST_SUGGESTER,
342+
InputFieldType.IMAGE_LIST_SUGGESTER,
335343
],
336344
values: [
337345
[

packages/core/src/fields/inputFields/InputFieldFactory.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ import { TimeIPF } from 'packages/core/src/fields/inputFields/fields/Time/TimeIP
2727
import { ToggleIPF } from 'packages/core/src/fields/inputFields/fields/Toggle/ToggleIPF';
2828
import { DocsUtils } from 'packages/core/src/utils/DocsUtils';
2929
import { ErrorLevel, MetaBindParsingError } from 'packages/core/src/utils/errors/MetaBindErrors';
30+
import { expectType } from 'packages/core/src/utils/Utils';
31+
import { ImageListSuggesterIPF } from 'packages/core/src/fields/inputFields/fields/ImageListSuggester/ImageListSuggesterIPF';
3032

3133
export type InputField =
3234
| ToggleIPF
@@ -47,7 +49,8 @@ export type InputField =
4749
| DateIPF
4850
| TimeIPF
4951
| InlineListSuggesterIPF
50-
| InlineListIPF;
52+
| InlineListIPF
53+
| ImageListSuggesterIPF;
5154

5255
export class InputFieldFactory {
5356
plugin: IPlugin;
@@ -104,8 +107,12 @@ export class InputFieldFactory {
104107
return new InlineListSuggesterIPF(base);
105108
} else if (type === InputFieldType.INLINE_LIST) {
106109
return new InlineListIPF(base);
110+
} else if (type === InputFieldType.IMAGE_LIST_SUGGESTER) {
111+
return new ImageListSuggesterIPF(base);
107112
}
108113

114+
expectType<InputFieldType.INVALID>(type);
115+
109116
return undefined;
110117
}
111118

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<script lang="ts">
2+
import Icon from '../../../../utils/components/Icon.svelte';
3+
import Button from '../../../../utils/components/Button.svelte';
4+
import { IPlugin } from '../../../../IPlugin';
5+
import { ContextMenuItemDefinition } from 'packages/core/src/utils/IContextMenu';
6+
import { ButtonStyleType } from 'packages/core/src/config/ButtonConfig';
7+
8+
export let plugin: IPlugin;
9+
export let value: string[];
10+
export let showSuggester: () => void;
11+
export let onValueChange: (value: string[]) => void;
12+
13+
export function setValue(v: string[]): void {
14+
value = v;
15+
}
16+
17+
export function addValue(v: string): void {
18+
value.push(v);
19+
20+
value = value;
21+
}
22+
23+
function remove(i: number) {
24+
value.splice(i, 1);
25+
// call with copy of array
26+
onValueChange(value);
27+
// tell svelte to update
28+
value = value;
29+
}
30+
31+
function suggestKey(event: KeyboardEvent): void {
32+
if (event.key === ' ') {
33+
showSuggester();
34+
}
35+
}
36+
37+
function openContextMenuForElement(e: MouseEvent, index: number) {
38+
const menuActions: ContextMenuItemDefinition[] = [];
39+
40+
if (index > 0) {
41+
menuActions.push({
42+
name: 'Move left',
43+
icon: 'arrow-left',
44+
onclick: () => {
45+
const temp = value[index - 1];
46+
value[index - 1] = value[index];
47+
value[index] = temp;
48+
onValueChange(value);
49+
},
50+
});
51+
}
52+
53+
if (index < value.length - 1) {
54+
menuActions.push({
55+
name: 'Move right',
56+
icon: 'arrow-right',
57+
onclick: () => {
58+
const temp = value[index + 1];
59+
value[index + 1] = value[index];
60+
value[index] = temp;
61+
onValueChange(value);
62+
},
63+
});
64+
}
65+
66+
menuActions.push({
67+
name: 'Remove',
68+
icon: 'x',
69+
warning: true,
70+
onclick: () => remove(index),
71+
});
72+
73+
plugin.internal.createContextMenu(menuActions).showWithEvent(e);
74+
}
75+
</script>
76+
77+
<div class="mb-image-card-grid">
78+
{#each value as image, i}
79+
<div class="mb-image-card">
80+
<img class="mb-image-card-image" src={plugin.internal.imagePathToUri(image)} alt={image} />
81+
<div class="mb-image-card-footer">
82+
<span>{image}</span>
83+
<Button variant={ButtonStyleType.PLAIN} on:click={e => openContextMenuForElement(e, i)}>
84+
<Icon iconName="more-vertical" plugin={plugin} />
85+
</Button>
86+
</div>
87+
</div>
88+
{/each}
89+
</div>
90+
<div class="mb-list-input">
91+
<Button variant={ButtonStyleType.DEFAULT} on:click={() => showSuggester()}>Add new image</Button>
92+
</div>
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { AbstractInputField } from 'packages/core/src/fields/inputFields/AbstractInputField';
2+
import ImageListSuggesterComponent from 'packages/core/src/fields/inputFields/fields/ImageListSuggester/ImageListSuggesterComponent.svelte';
3+
import { type MBLiteral, parseUnknownToLiteralArray, stringifyLiteral } from 'packages/core/src/utils/Literal';
4+
import { type SvelteComponent } from 'svelte';
5+
6+
export class ImageListSuggesterIPF extends AbstractInputField<MBLiteral[], string[]> {
7+
protected filterValue(value: unknown): MBLiteral[] | undefined {
8+
return parseUnknownToLiteralArray(value);
9+
}
10+
11+
protected getFallbackDefaultValue(): string[] {
12+
return [];
13+
}
14+
15+
protected getSvelteComponent(): typeof SvelteComponent {
16+
// @ts-ignore
17+
return ImageListSuggesterComponent;
18+
}
19+
20+
protected rawMapValue(value: string[]): MBLiteral[] {
21+
return value;
22+
}
23+
24+
protected rawReverseMapValue(value: MBLiteral[]): string[] | undefined {
25+
return value.map(v => stringifyLiteral(v)).filter(v => v !== undefined);
26+
}
27+
28+
protected getMountArgs(): Record<string, unknown> {
29+
return {
30+
showSuggester: () => this.openModal(),
31+
};
32+
}
33+
34+
openModal(): void {
35+
this.base.plugin.internal.openImageSuggesterModal(this, (selected: string) => {
36+
const value = this.getInternalValue();
37+
value.push(selected);
38+
this.setInternalValue(value);
39+
});
40+
}
41+
}
Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
<script lang="ts">
22
import { IPlugin } from 'packages/core/src/IPlugin';
3+
import Button from '../../../../utils/components/Button.svelte';
4+
import { ButtonStyleType } from '../../../../config/ButtonConfig';
5+
import Icon from 'packages/core/src/utils/components/Icon.svelte';
36
47
export let plugin: IPlugin;
58
@@ -14,20 +17,16 @@
1417
function openSuggester(event: MouseEvent) {
1518
showSuggester();
1619
}
17-
18-
function openSuggesterOnKey(event: KeyboardEvent) {
19-
if (event.key === ' ') {
20-
showSuggester();
21-
}
22-
}
2320
</script>
2421

25-
<div class="mb-image-suggest-input">
22+
<div class="mb-image-card">
2623
{#if value}
27-
<img class="mb-image-suggest-image" src={plugin.internal.imagePathToUri(value)} alt={value} />
24+
<img class="mb-image-card-image" src={plugin.internal.imagePathToUri(value)} alt={value} />
2825
{/if}
29-
<div class="mb-image-suggest-footer">
30-
<span class="mb-image-suggest-footer-text">{value || 'no image selected'}</span>
31-
<button class="btn btn-active" on:click={openSuggester} on:keydown={openSuggesterOnKey}> Change Image</button>
26+
<div class="mb-image-card-footer">
27+
<span>{value || 'no image selected'}</span>
28+
<Button variant={ButtonStyleType.PLAIN} on:click={openSuggester}>
29+
<Icon iconName="pencil" plugin={plugin} />
30+
</Button>
3231
</div>
3332
</div>

packages/core/src/fields/inputFields/fields/Suggester/SuggesterHelper.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
import { type InlineListSuggesterIPF } from 'packages/core/src/fields/inputFields/fields/InlineListSuggester/InlineListSuggesterIPF';
22
import { type ListSuggesterIPF } from 'packages/core/src/fields/inputFields/fields/ListSuggester/ListSuggesterIPF';
33
import { type SuggesterIPF } from 'packages/core/src/fields/inputFields/fields/Suggester/SuggesterIPF';
4+
import { type ImageSuggesterIPF } from 'packages/core/src/fields/inputFields/fields/ImageSuggester/ImageSuggesterIPF';
5+
import { type ImageListSuggesterIPF } from 'packages/core/src/fields/inputFields/fields/ImageListSuggester/ImageListSuggesterIPF';
46

57
export type SuggesterLikeIFP = SuggesterIPF | ListSuggesterIPF | InlineListSuggesterIPF;
68

9+
export type ImageSuggesterLikeIPF = ImageSuggesterIPF | ImageListSuggesterIPF;
10+
711
export class SuggesterOption<T> {
812
value: T;
913
displayValue: string;

0 commit comments

Comments
 (0)