diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c0385b3..ad4d3d53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,8 @@ - [#103](https://github.com/estruyf/vscode-front-matter/issues/103): Added title and description field to the metadata section - [#104](https://github.com/estruyf/vscode-front-matter/issues/104): Allow to set images in front matter from the metadata panel section - [#105](https://github.com/estruyf/vscode-front-matter/issues/105): Content Type support with backwards compatibility -- [#107](https://github.com/estruyf/vscode-front-matter/issues/107): Number field support added in content types fields +- [#107](https://github.com/estruyf/vscode-front-matter/issues/107): Number field support added in content type fields +- [#108](https://github.com/estruyf/vscode-front-matter/issues/108): Choice field support added in content type fields ## [3.1.0] - 2021-09-10 diff --git a/assets/media/styles.css b/assets/media/styles.css index 7c29ff73..38ee991b 100644 --- a/assets/media/styles.css +++ b/assets/media/styles.css @@ -451,6 +451,19 @@ input:checked + .field__toggle__slider:before { outline: none !important; } +.metadata_field__choice { + border: 1px solid var(--vscode-inputValidation-infoBorder) !important; + outline: none !important; + width: 100%; + padding: var(--input-padding-vertical) var(--input-padding-horizontal); + color: var(--vscode-input-foreground); + background-color: var(--vscode-input-background); +} + +.metadata_field__choice::placeholde { + color: var(--vscode-input-placeholderForeground); +} + .metadata_field__datetime { display: flex; justify-content: space-between; diff --git a/docs/content/docs/content-types.md b/docs/content/docs/content-types.md index 324019be..27394cd4 100644 --- a/docs/content/docs/content-types.md +++ b/docs/content/docs/content-types.md @@ -175,9 +175,19 @@ Front Matter its metadata section supports the following fields: - `datetime` - `boolean` - `image` +- `choice` - `tags`: mapped to the tags defined in your settings. - `categories`: mapped to the categories defined in your settings. +### Field properties + +A field consists out of the following properties: + +- `title`: The title to show in the metadata section (optional); +- `name`: The name of your field, will be used to set in the front matter of your Markdown file; +- `type`: One of the above supported types; +- `choices`: When you picked the `choice` field type, you need to return an array of choices: `["Choice 1", "Choice 2", "Choice 3"]`. + ## Creating a template To make sure that your type of content is already defined when creating a new Markdown file. It will be easier to set the type of content within a template. diff --git a/package.json b/package.json index 0e2587c3..e8099007 100644 --- a/package.json +++ b/package.json @@ -337,6 +337,7 @@ "datetime", "boolean", "image", + "choice", "tags", "categories" ], @@ -349,6 +350,13 @@ "title": { "type": "string", "description": "Title to show in the UI" + }, + "choices": { + "type": "array", + "description": "Define your choices", + "items": { + "type": "string" + } } }, "additionalProperties": false, diff --git a/src/models/PanelSettings.ts b/src/models/PanelSettings.ts index 87c217d5..51043dfb 100644 --- a/src/models/PanelSettings.ts +++ b/src/models/PanelSettings.ts @@ -26,7 +26,8 @@ export interface ContentType { export interface Field { title?: string; name: string; - type: "string" | "number" | "datetime" | "boolean" | "image" | "tags" | "categories"; + type: "string" | "number" | "datetime" | "boolean" | "image" | "choice" | "tags" | "categories"; + choices?: string[]; } export interface DateInfo { diff --git a/src/panelWebView/components/Fields/ChoiceField.tsx b/src/panelWebView/components/Fields/ChoiceField.tsx new file mode 100644 index 00000000..d25bf011 --- /dev/null +++ b/src/panelWebView/components/Fields/ChoiceField.tsx @@ -0,0 +1,42 @@ +import { CheckIcon } from '@heroicons/react/outline'; +import * as React from 'react'; +import { VsLabel } from '../VscodeComponents'; + +export interface IChoiceFieldProps { + label: string; + selected: string; + choices: string[]; + onChange: (value: string) => void; +} + +export const ChoiceField: React.FunctionComponent = ({label, selected, choices, onChange}: React.PropsWithChildren) => { + const [ crntSelected, setCrntSelected ] = React.useState(selected); + + const onValueChange = (txtValue: string) => { + setCrntSelected(txtValue); + onChange(txtValue); + }; + + const containsSelected = selected && choices.indexOf(selected) !== -1; + + return ( +
+ +
+ {label} +
+
+ + +
+ ); +}; \ No newline at end of file diff --git a/src/panelWebView/components/Metadata.tsx b/src/panelWebView/components/Metadata.tsx index fe708a1d..5bfdc4f7 100644 --- a/src/panelWebView/components/Metadata.tsx +++ b/src/panelWebView/components/Metadata.tsx @@ -11,12 +11,13 @@ import { TagPicker } from './TagPicker'; import { parseJSON } from 'date-fns'; import { DateTimeField } from './Fields/DateTimeField'; import { TextField } from './Fields/TextField'; - import "react-datepicker/dist/react-datepicker.css"; import { PreviewImageField } from './Fields/PreviewImageField'; import { DEFAULT_CONTENT_TYPE, DEFAULT_CONTENT_TYPE_NAME } from '../../constants/ContentType'; import { ListUnorderedIcon } from './Icons/ListUnorderedIcon'; import { NumberField } from './Fields/NumberField'; +import { ChoiceField } from './Fields/ChoiceField'; + export interface IMetadataProps { settings: PanelSettings | undefined; metadata: { [prop: string]: string[] | string | null }; @@ -127,6 +128,18 @@ export const Metadata: React.FunctionComponent = ({settings, met value={metadata[field.name] as string} onChange={(value => sendUpdate(field.name, value))} /> ); + } else if (field.type === 'choice') { + const choices = field.choices || []; + const choiceValue = metadata[field.name]; + + return ( + sendUpdate(field.name, value))} /> + ); } else if (field.type === 'tags') { return (