Skip to content

Commit b0ad160

Browse files
committed
add #131 and #137
1 parent 186c508 commit b0ad160

File tree

16 files changed

+449
-29
lines changed

16 files changed

+449
-29
lines changed

exampleVault/Input Fields/List.md

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ list3:
1111
- Example Note with Image
1212
- Example Note with Callouts
1313
- something
14+
list4:
15+
- Example Note with Callouts
16+
- Example Note with Embeds
17+
- Example Note with Embeds
18+
list5:
19+
- this is an element
1420
---
1521

1622

@@ -26,7 +32,12 @@ INPUT[listSuggester(optionQuery(#example-note), option(something, other), showca
2632
INPUT[listSuggester(optionQuery(#example-note), option(something, other), useLinks(false), showcase):list3]
2733
```
2834

29-
3035
```meta-bind
31-
INPUT[listsuggester(optionQuery(#example-note), option(something, other), useLinks(false), showcase):list3]
32-
```
36+
INPUT[inlineListSuggester(optionQuery(#example-note), option(something, other), useLinks(false), showcase):list4]
37+
```
38+
39+
40+
Some text: `INPUT[inlineListSuggester(optionQuery(#example-note), option(something, other), useLinks(false)):list4]` some more text
41+
42+
43+
Some text: `INPUT[inlineList:list5]` some more text
2.54 MB
Loading

src/inputFields/InputFieldFactory.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import { DateIPF } from './fields/Date/DateIPF';
2020
import { TimeIPF } from './fields/Time/TimeIPF';
2121
import { type InputFieldConfig, InputFieldConfigs, InputFieldType } from '../parsers/GeneralConfigs';
2222
import { DocsHelper } from '../utils/DocsHelper';
23+
import { InlineListSuggesterIPF } from './fields/InlineListSuggester/InlineListSuggesterIPF';
24+
import { InlineListIPF } from './fields/InlineList/InlineListIPF';
2325

2426
export type NewInputField =
2527
| ToggleIPF
@@ -38,7 +40,9 @@ export type NewInputField =
3840
| ListIPF
3941
| ListSuggesterIPF
4042
| DateIPF
41-
| TimeIPF;
43+
| TimeIPF
44+
| InlineListSuggesterIPF
45+
| InlineListIPF;
4246

4347
export class InputFieldFactory {
4448
plugin: IPlugin;
@@ -94,6 +98,10 @@ export class InputFieldFactory {
9498
return new DateIPF(renderChild);
9599
} else if (type === InputFieldType.TIME) {
96100
return new TimeIPF(renderChild);
101+
} else if (type === InputFieldType.INLINE_LIST_SUGGESTER) {
102+
return new InlineListSuggesterIPF(renderChild);
103+
} else if (type === InputFieldType.INLINE_LIST) {
104+
return new InlineListIPF(renderChild);
97105
}
98106

99107
return undefined;
Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,45 @@
11
<script lang="ts">
22
import ImageSuggesterCard from './ImageSuggesterCard.svelte';
33
import { SuggesterOption } from '../Suggester/SuggesterHelper';
4+
import {TextInput} from 'obsidian-svelte';
5+
import {prepareFuzzySearch} from 'obsidian';
46
57
export let options: SuggesterOption<string>[];
68
export let onSelect: (item: string) => void;
9+
10+
let search = '';
11+
let filteredOptions: SuggesterOption<string>[];
12+
13+
$: runSearch(search);
14+
15+
function runSearch(search: string): void {
16+
if (!search) {
17+
filteredOptions = options;
18+
return;
19+
}
20+
21+
const searchFn = prepareFuzzySearch(search);
22+
23+
let x: SuggesterOption<string>[] = []
24+
for (const option of options) {
25+
if (searchFn(option.value)?.score !== undefined) {
26+
x.push(option);
27+
}
28+
}
29+
30+
filteredOptions = x;
31+
}
732
</script>
833

34+
<div class="mb-image-search-container">
35+
<TextInput bind:value={search} placeholder="Search Images..."></TextInput>
36+
</div>
937
<div class="mb-image-card-grid">
10-
{#each options as option}
38+
{#each filteredOptions as option}
1139
<ImageSuggesterCard image={option.value} onSelect={onSelect}></ImageSuggesterCard>
1240
{/each}
1341
</div>
1442

1543
<style>
16-
.mb-image-card-grid {
17-
display: grid;
18-
grid-template-columns: repeat(auto-fit, minmax(min(500px, 100%), 1fr));
19-
gap: var(--size-4-4);
20-
}
44+
2145
</style>

src/inputFields/fields/ImageSuggester/ImageSuggesterCard.svelte

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
2323
.image-card-image {
2424
width: 100%;
25+
height: fit-content;
26+
max-height: 500px;
27+
object-fit: contain;
2528
}
2629
2730
.image-card-text {

src/inputFields/fields/ImageSuggester/ImageSuggesterComponent.svelte

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@
4141
4242
.mb-image-suggest-image {
4343
width: 100%;
44+
height: fit-content;
45+
max-height: 500px;
46+
object-fit: contain;
4447
}
4548
4649
.mb-image-suggest-footer {

src/inputFields/fields/ImageSuggester/ImageSuggesterHelper.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,19 @@ import { type ImageSuggesterIPF } from './ImageSuggesterIPF';
99
import { InputFieldArgumentType } from '../../../parsers/GeneralConfigs';
1010
import { stringifyLiteral } from '../../../utils/Literal';
1111

12+
function recSearchFolder(folder: TFolder): SuggesterOption<string>[] {
13+
const ret = [];
14+
for (const child of folder.children) {
15+
if (child instanceof TFile && isImageExtension(child.extension)) {
16+
ret.push(new SuggesterOption(child.path, child.name));
17+
}
18+
if (child instanceof TFolder) {
19+
ret.push(...recSearchFolder(child));
20+
}
21+
}
22+
return ret;
23+
}
24+
1225
export function getImageSuggesterOptions(
1326
optionArgs: OptionInputFieldArgument[],
1427
optionQueryArgs: OptionQueryInputFieldArgument[],
@@ -54,11 +67,7 @@ export function getImageSuggesterOptions(
5467
continue;
5568
}
5669

57-
for (const child of folder.children) {
58-
if (child instanceof TFile && isImageExtension(child.extension)) {
59-
options.push(new SuggesterOption(child.path, child.name));
60-
}
61-
}
70+
options.push(...recSearchFolder(folder));
6271
}
6372

6473
for (const optionArg of optionArgs) {
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<script lang="ts">
2+
import Icon from '../../../utils/Icon.svelte';
3+
import { isMdLink, parseMdLink } from '../../../parsers/MarkdownLinkParser';
4+
import LinkComponent from '../../../utils/LinkComponent.svelte';
5+
import { MBLiteral } from '../../../utils/Literal';
6+
7+
export let value: MBLiteral[];
8+
export let showInput: () => void;
9+
export let onValueChange: (value: MBLiteral[]) => void;
10+
11+
export function setValue(v: MBLiteral[]): void {
12+
value = v;
13+
}
14+
15+
export function addValue(v: MBLiteral): void {
16+
value.push(v);
17+
18+
value = value;
19+
}
20+
21+
function remove(i: number) {
22+
value.splice(i, 1);
23+
// call with copy of array
24+
onValueChange(value);
25+
// tell svelte to update
26+
value = value;
27+
}
28+
29+
function input(event: MouseEvent): void {
30+
// don't fire the event if user clicked on the link
31+
if (!(event.target instanceof HTMLAnchorElement)) {
32+
showInput();
33+
}
34+
}
35+
36+
function inputKey(event: KeyboardEvent): void {
37+
if (event.key === ' ') {
38+
showInput();
39+
}
40+
}
41+
</script>
42+
43+
<div class="mb-inline-list">
44+
{#each value as entry, i}
45+
<div class="mb-inline-list-item">
46+
{#if isMdLink(`${entry}`)}
47+
<span>
48+
<LinkComponent mdLink={parseMdLink(`${entry}`)}></LinkComponent>
49+
</span>
50+
{:else}
51+
<span>{entry}</span>
52+
{/if}
53+
<button class="mb-inline-list-item-button" on:click={() => remove(i)}>
54+
<Icon iconName="x" />
55+
</button>
56+
</div>
57+
{/each}
58+
<div class="mb-inline-list-add" on:click={input} on:keydown={inputKey} role="button" tabindex="0">
59+
<!-- Alignment hack with zero width space -->
60+
<span>&#x200B;</span>
61+
<Icon iconName="plus" />
62+
</div>
63+
</div>
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { AbstractInputField } from '../../AbstractInputField';
2+
import { MBLiteral, parseUnknownToLiteralArray } from '../../../utils/Literal';
3+
import { InputFieldMDRC } from '../../../renderChildren/InputFieldMDRC';
4+
import { SvelteComponent } from 'svelte';
5+
import InlineListComponent from './InlineListComponent.svelte';
6+
import { TextPromptModal } from '../../../utils/TextPromptModal';
7+
8+
export class InlineListIPF extends AbstractInputField<MBLiteral[], MBLiteral[]> {
9+
constructor(renderChild: InputFieldMDRC) {
10+
super(renderChild);
11+
}
12+
13+
protected filterValue(value: unknown): MBLiteral[] | undefined {
14+
return parseUnknownToLiteralArray(value);
15+
}
16+
17+
protected getFallbackDefaultValue(): MBLiteral[] {
18+
return [];
19+
}
20+
21+
protected getSvelteComponent(): typeof SvelteComponent {
22+
return InlineListComponent;
23+
}
24+
25+
protected rawMapValue(value: MBLiteral[]): MBLiteral[] {
26+
return value;
27+
}
28+
29+
protected rawReverseMapValue(value: MBLiteral[]): MBLiteral[] | undefined {
30+
return value;
31+
}
32+
33+
protected getMountArgs(): Record<string, unknown> {
34+
return {
35+
showInput: () => this.openModal(),
36+
};
37+
}
38+
39+
openModal(): void {
40+
new TextPromptModal(
41+
this.renderChild.plugin.app,
42+
'',
43+
'Meta Bind List',
44+
'New List Element',
45+
'',
46+
newElement => {
47+
const value = this.getInternalValue();
48+
value.push(newElement);
49+
this.setInternalValue(value);
50+
},
51+
() => {},
52+
).open();
53+
}
54+
}

0 commit comments

Comments
 (0)