Merge branches 'dev' and 'dev' of github.com:estruyf/vscode-front-matter into dev

This commit is contained in:
Elio Struyf
2023-03-06 10:19:03 +01:00
13 changed files with 277 additions and 209 deletions
+5
View File
@@ -15,11 +15,16 @@
### 🎨 Enhancements
- [#522](https://github.com/estruyf/vscode-front-matter/issues/522): Configuration support added for [Astro](https://astro.build)
- [#523](https://github.com/estruyf/vscode-front-matter/issues/523): Added support for `floating`/`decimal` numbers with a new number field property called `numberOptions`
- [#524](https://github.com/estruyf/vscode-front-matter/issues/524): Removed the **Global settings** view from the panel. You can still get it back by configuring a [custom view mode](https://frontmatter.codes/docs/panel#view-modes).
### ⚡️ Optimizations
### 🐞 Fixes
- [#518](https://github.com/estruyf/vscode-front-matter/issues/518): Fix an issue where the `YAML` parser adds line breaks to long strings
- [#520](https://github.com/estruyf/vscode-front-matter/issues/520): Add the URL protocol to the host on opening the preview if it's missing
## [8.3.0] - 2023-02-14 - [Release notes](https://beta.frontmatter.codes/updates/v8.3.0)
+41 -35
View File
@@ -33,8 +33,12 @@
position: inherit !important;
}
.z-10 { z-index: 10 !important; }
.z-20 { z-index: 10 !important; }
.z-10 {
z-index: 10 !important;
}
.z-20 {
z-index: 10 !important;
}
.w-full {
width: 100% !important;
@@ -44,11 +48,12 @@
.ext_settings,
.git_actions,
.initialize_actions {
padding: 1rem 1.25rem;
padding: 1rem 1.25rem;
box-sizing: border-box;
}
#app, .frontmatter {
#app,
.frontmatter {
height: 100%;
}
@@ -58,7 +63,7 @@
align-items: center;
opacity: 0.8;
text-align: center;
padding: 1rem 1.25rem;
padding: 1rem 1.25rem;
}
.spinner,
@@ -103,7 +108,7 @@
padding-bottom: var(--input-margin-vertical);
display: flex;
flex-direction: column;
justify-content: space-between;
justify-content: start;
}
.frontmatter h3 {
@@ -113,7 +118,7 @@
.frontmatter p,
.frontmatter h4,
.frontmatter ul {
margin-bottom: .5rem;
margin-bottom: 0.5rem;
}
.article__tags h3,
@@ -131,7 +136,8 @@
margin-right: 0.5rem;
}
.seo__status__details, .seo__status__keywords {
.seo__status__details,
.seo__status__keywords {
margin-bottom: 1rem;
}
@@ -162,11 +168,11 @@
}
.article__tags__dropbox.open {
border: 1px solid rgba(0, 0, 0, .9);
border: 1px solid rgba(0, 0, 0, 0.9);
}
.article__tags ul {
color: var(--vscode-dropdown-foreground);
color: var(--vscode-dropdown-foreground);
background-color: var(--vscode-dropdown-background);
}
@@ -176,16 +182,16 @@
}
.article__tags li:active {
color: var(--vscode-button-foreground);
color: var(--vscode-button-foreground);
background-color: var(--vscode-button-background);
}
.article__tags li[aria-selected="true"] {
.article__tags li[aria-selected='true'] {
color: var(--vscode-button-foreground);
background-color: var(--vscode-button-hoverBackground);
}
.article__tags li[aria-disabled="true"] {
.article__tags li[aria-disabled='true'] {
display: none;
}
@@ -224,7 +230,7 @@
}
.ext_link_block svg {
margin-right: .5rem;
margin-right: 0.5rem;
display: block;
width: 16px;
height: 16px;
@@ -258,16 +264,16 @@
}
.ext_link_block button.active {
color: var(--vscode-button-foreground);
background: var(--vscode-button-background);
color: var(--vscode-button-foreground);
background: var(--vscode-button-background);
}
.ext_link_block button.active:hover {
cursor: pointer;
background: var(--vscode-button-hoverBackground);
cursor: pointer;
background: var(--vscode-button-hoverBackground);
}
.ext_link_block a:hover,
.ext_link_block a:active,
.ext_link_block a:hover,
.ext_link_block a:active,
.ext_link_block a:focus,
.ext_link_block a:visited {
color: var(--vscode-button-secondaryForeground);
@@ -301,15 +307,15 @@
}
.table__cell__validation .valid {
color: #46EC86;
color: #46ec86;
}
.table__cell__validation .warning {
color: #E6AF2E;
color: #e6af2e;
}
.table__cell__validation div span + span {
margin-left: .5rem;
margin-left: 0.5rem;
}
.seo__status__note {
@@ -325,7 +331,7 @@
height: 24px;
}
.field__toggle input {
.field__toggle input {
opacity: 0;
width: 0;
height: 0;
@@ -339,21 +345,21 @@
right: 0;
bottom: 0;
background-color: var(--vscode-button-secondaryBackground);
-webkit-transition: .4s;
transition: .4s;
-webkit-transition: 0.4s;
transition: 0.4s;
border-radius: 34px;
}
.field__toggle__slider:before {
position: absolute;
content: "";
content: '';
height: 16px;
width: 16px;
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
-webkit-transition: 0.4s;
transition: 0.4s;
border-radius: 50%;
}
@@ -405,7 +411,7 @@ input:checked + .field__toggle__slider:before {
}
.file_list__items__item {
color: var(--vscode-foreground);
color: var(--vscode-foreground);
font-size: var(--vscode-font-size);
font-weight: var(--vscode-font-weight);
cursor: pointer;
@@ -419,7 +425,7 @@ input:checked + .field__toggle__slider:before {
}
.file_list__items__item:hover {
background-color: var(--vscode-list-hoverBackground);
background-color: var(--vscode-list-hoverBackground);
color: var(--vscode-list-hoverForeground);
cursor: pointer;
}
@@ -429,7 +435,7 @@ input:checked + .field__toggle__slider:before {
flex-shrink: 0;
height: 20px;
width: 20px;
margin-right: .25rem;
margin-right: 0.25rem;
}
.file_list__items__item span {
@@ -454,7 +460,7 @@ input:checked + .field__toggle__slider:before {
.sponsor svg {
height: 20px;
width: 20px;
margin-right: .25rem;
margin-right: 0.25rem;
}
.sponsor a {
@@ -471,7 +477,7 @@ input:checked + .field__toggle__slider:before {
}
.sponsor a > span {
margin-right: .25rem;
margin-right: 0.25rem;
}
/* Timepicker */
@@ -494,4 +500,4 @@ input:checked + .field__toggle__slider:before {
.react-datepicker-time__input input {
border: 1px solid #aeaeae !important;
}
}
+148 -153
View File
@@ -10,8 +10,7 @@
"color": "#0e131f",
"theme": "dark"
},
"badges": [
{
"badges": [{
"description": "version",
"url": "https://img.shields.io/github/package-json/v/estruyf/vscode-front-matter?color=green&label=vscode-front-matter&style=flat-square",
"href": "https://github.com/estruyf/vscode-front-matter"
@@ -55,8 +54,7 @@
],
"main": "./dist/extension.js",
"contributes": {
"keybindings": [
{
"keybindings": [{
"command": "frontMatter.dashboard",
"key": "alt+d"
},
@@ -74,24 +72,20 @@
}
],
"viewsContainers": {
"activitybar": [
{
"id": "frontmatter-explorer",
"title": "Front Matter",
"icon": "assets/frontmatter-short-min.svg"
}
]
"activitybar": [{
"id": "frontmatter-explorer",
"title": "Front Matter",
"icon": "assets/frontmatter-short-min.svg"
}]
},
"views": {
"frontmatter-explorer": [
{
"id": "frontMatter.explorer",
"name": "Front Matter",
"icon": "assets/frontmatter-short-min.svg",
"contextualTitle": "Front Matter",
"type": "webview"
}
]
"frontmatter-explorer": [{
"id": "frontMatter.explorer",
"name": "Front Matter",
"icon": "assets/frontmatter-short-min.svg",
"contextualTitle": "Front Matter",
"type": "webview"
}]
},
"configuration": {
"title": "Front Matter: use frontmatter.json for shared team settings",
@@ -126,8 +120,7 @@
"frontMatter.content.defaultFileType": {
"type": "string",
"default": "md",
"oneOf": [
{
"oneOf": [{
"enum": [
"md",
"mdx"
@@ -143,8 +136,7 @@
"frontMatter.content.defaultSorting": {
"type": "string",
"default": "",
"oneOf": [
{
"oneOf": [{
"enum": [
"LastModifiedAsc",
"LastModifiedDesc",
@@ -471,8 +463,7 @@
"command": {
"$id": "#scriptCommand",
"type": "string",
"oneOf": [
{
"oneOf": [{
"enum": [
"node",
"bash",
@@ -646,8 +637,7 @@
"title",
"file"
],
"anyOf": [
{
"anyOf": [{
"required": [
"schema"
]
@@ -701,8 +691,7 @@
"id",
"path"
],
"anyOf": [
{
"anyOf": [{
"required": [
"schema"
]
@@ -1048,8 +1037,7 @@
"default": "",
"description": "The ID of your taxonomy field. It cannot contain the \"tags\" or \"categories\" value.",
"not": {
"anyOf": [
{
"anyOf": [{
"const": ""
},
{
@@ -1093,6 +1081,32 @@
"type": "string"
}
},
"numberOptions": {
"type": "object",
"description": "Specify the options for the number field",
"properties": {
"isDecimal": {
"type": "boolean",
"default": false,
"description": "Specify if the number is a decimal"
},
"min": {
"type": "number",
"default": 0,
"description": "The minimum value"
},
"max": {
"type": "number",
"default": 0,
"description": "The maximum value"
},
"step": {
"type": "number",
"default": 1,
"description": "The step value"
}
}
},
"taxonomyLimit": {
"type": "number",
"default": 0,
@@ -1183,8 +1197,7 @@
"type",
"name"
],
"allOf": [
{
"allOf": [{
"if": {
"properties": {
"type": {
@@ -1342,51 +1355,48 @@
"fields"
]
},
"default": [
{
"name": "default",
"pageBundle": false,
"fields": [
{
"title": "Title",
"name": "title",
"type": "string"
},
{
"title": "Description",
"name": "description",
"type": "string"
},
{
"title": "Publishing date",
"name": "date",
"type": "datetime",
"default": "{{now}}",
"isPublishDate": true
},
{
"title": "Content preview",
"name": "preview",
"type": "image"
},
{
"title": "Is in draft",
"name": "draft",
"type": "boolean"
},
{
"title": "Tags",
"name": "tags",
"type": "tags"
},
{
"title": "Categories",
"name": "categories",
"type": "categories"
}
]
}
],
"default": [{
"name": "default",
"pageBundle": false,
"fields": [{
"title": "Title",
"name": "title",
"type": "string"
},
{
"title": "Description",
"name": "description",
"type": "string"
},
{
"title": "Publishing date",
"name": "date",
"type": "datetime",
"default": "{{now}}",
"isPublishDate": true
},
{
"title": "Content preview",
"name": "preview",
"type": "image"
},
{
"title": "Is in draft",
"name": "draft",
"type": "boolean"
},
{
"title": "Tags",
"name": "tags",
"type": "tags"
},
{
"title": "Categories",
"name": "categories",
"type": "categories"
}
]
}],
"scope": "Taxonomy"
},
"frontMatter.taxonomy.customTaxonomy": {
@@ -1399,8 +1409,7 @@
"type": "string",
"description": "ID for your taxonomy field. It cannot contain the \"tags\" or \"categories\" value.",
"not": {
"anyOf": [
{
"anyOf": [{
"const": ""
},
{
@@ -1582,8 +1591,7 @@
}
}
},
"commands": [
{
"commands": [{
"command": "frontMatter.config.reload",
"title": "Reload config",
"category": "Front Matter"
@@ -1897,15 +1905,12 @@
"category": "Front Matter"
}
],
"submenus": [
{
"id": "frontmatter.submenu",
"label": "Front Matter"
}
],
"submenus": [{
"id": "frontmatter.submenu",
"label": "Front Matter"
}],
"menus": {
"editor/title": [
{
"editor/title": [{
"command": "frontMatter.markup.heading",
"group": "navigation@-133",
"when": "frontMatter:file:isValid == true && frontMatter:markdown:wysiwyg"
@@ -1981,14 +1986,11 @@
"when": "frontMatter:enabled == true && frontMatter:dashboard:open == true"
}
],
"explorer/context": [
{
"submenu": "frontmatter.submenu",
"group": "frontmatter@1"
}
],
"frontmatter.submenu": [
{
"explorer/context": [{
"submenu": "frontmatter.submenu",
"group": "frontmatter@1"
}],
"frontmatter.submenu": [{
"command": "frontMatter.createFromTemplate",
"when": "explorerResourceIsFolder",
"group": "frontmatter@1"
@@ -2004,8 +2006,7 @@
"group": "frontmatter@3"
}
],
"commandPalette": [
{
"commandPalette": [{
"command": "frontMatter.init",
"when": "frontMatterCanInit"
},
@@ -2146,8 +2147,7 @@
"when": "frontMatter:file:isValid == true"
}
],
"view/title": [
{
"view/title": [{
"command": "frontMatter.collapseSections",
"group": "navigation@0",
"when": "view == frontMatter.explorer"
@@ -2164,57 +2164,52 @@
}
]
},
"grammars": [
{
"path": "./syntaxes/hugo.tmLanguage.json",
"scopeName": "frontmatter.markdown.hugo",
"injectTo": [
"text.html.markdown"
]
}
],
"walkthroughs": [
{
"id": "frontmatter.welcome",
"title": "Get started with Front Matter",
"description": "Discover the features of Front Matter and learn how to use the CMS for your SSG or static site.",
"steps": [
{
"id": "frontmatter.welcome.init",
"title": "Get started",
"description": "Initial steps to get started.\n[Open dashboard](command:frontMatter.dashboard)",
"media": {
"markdown": "assets/walkthrough/get-started.md"
},
"completionEvents": [
"onContext:frontMatterInitialized"
]
"grammars": [{
"path": "./syntaxes/hugo.tmLanguage.json",
"scopeName": "frontmatter.markdown.hugo",
"injectTo": [
"text.html.markdown"
]
}],
"walkthroughs": [{
"id": "frontmatter.welcome",
"title": "Get started with Front Matter",
"description": "Discover the features of Front Matter and learn how to use the CMS for your SSG or static site.",
"steps": [{
"id": "frontmatter.welcome.init",
"title": "Get started",
"description": "Initial steps to get started.\n[Open dashboard](command:frontMatter.dashboard)",
"media": {
"markdown": "assets/walkthrough/get-started.md"
},
{
"id": "frontmatter.welcome.documentation",
"title": "Documentation",
"description": "Check out the documentation for Front Matter.\n[View our documentation](https://frontmatter.codes/docs)",
"media": {
"markdown": "assets/walkthrough/documentation.md"
},
"completionEvents": [
"onLink:https://frontmatter.codes/docs"
]
"completionEvents": [
"onContext:frontMatterInitialized"
]
},
{
"id": "frontmatter.welcome.documentation",
"title": "Documentation",
"description": "Check out the documentation for Front Matter.\n[View our documentation](https://frontmatter.codes/docs)",
"media": {
"markdown": "assets/walkthrough/documentation.md"
},
{
"id": "frontmatter.welcome.supporter",
"title": "Support the project",
"description": "Become a supporter.\n[Support the project](https://github.com/sponsors/estruyf)",
"media": {
"markdown": "assets/walkthrough/support-the-project.md"
},
"completionEvents": [
"onLink:https://github.com/sponsors/estruyf"
]
}
]
}
]
"completionEvents": [
"onLink:https://frontmatter.codes/docs"
]
},
{
"id": "frontmatter.welcome.supporter",
"title": "Support the project",
"description": "Become a supporter.\n[Support the project](https://github.com/sponsors/estruyf)",
"media": {
"markdown": "assets/walkthrough/support-the-project.md"
},
"completionEvents": [
"onLink:https://github.com/sponsors/estruyf"
]
}
]
}]
},
"scripts": {
"dev:ext": "npm run clean && npm-run-all --parallel watch:*",
@@ -2339,4 +2334,4 @@
"vsce": {
"dependencies": false
}
}
}
+2 -1
View File
@@ -161,7 +161,8 @@ export class Preview {
light: Uri.file(join(extensionPath, 'assets/icons/frontmatter-short-light.svg'))
};
const localhostUrl = await env.asExternalUri(Uri.parse(settings.host));
const crntUrl = settings.host.startsWith('http') ? settings.host : `http://${settings.host}`;
const localhostUrl = await env.asExternalUri(Uri.parse(crntUrl));
const cspSource = webView.webview.cspSource;
+30 -8
View File
@@ -1,10 +1,25 @@
export const FrameworkDetectors = [
{
framework: {
name: 'astro',
dist: 'dist',
static: 'public',
build: 'npm run build',
server: 'http://localhost:3000'
},
requiredFiles: ['astro.config.mjs'],
requiredDependencies: ['astro'],
commands: {
start: 'npm run dev'
}
},
{
framework: {
name: 'gatsby',
dist: 'public',
static: 'static',
build: 'gatsby build'
build: 'gatsby build',
server: 'http://localhost:8000'
},
requiredFiles: ['gatsby-config.js'],
requiredDependencies: ['gatsby'],
@@ -17,7 +32,8 @@ export const FrameworkDetectors = [
name: 'hugo',
dist: 'public',
static: 'static',
build: 'hugo'
build: 'hugo',
server: 'http://localhost:1313'
},
requiredFiles: ['config.toml', 'config.yaml', 'config.yml'],
commands: {
@@ -29,7 +45,8 @@ export const FrameworkDetectors = [
name: 'next',
dist: '.next',
static: 'public',
build: 'next build'
build: 'next build',
server: 'http://localhost:3000'
},
requiredFiles: ['next.config.js'],
requiredDependencies: ['next'],
@@ -42,7 +59,8 @@ export const FrameworkDetectors = [
name: 'nuxt',
dist: 'dist',
static: 'static',
build: 'nuxt'
build: 'nuxt',
server: 'http://localhost:3000'
},
requiredFiles: ['nuxt.config.js'],
requiredDependencies: ['nuxt'],
@@ -55,7 +73,8 @@ export const FrameworkDetectors = [
name: 'jekyll',
dist: '_site',
static: 'assets',
build: 'bundle exec jekyll build'
build: 'bundle exec jekyll build',
server: 'http://localhost:4000'
},
requiredFiles: ['Gemfile'],
requiredDependencies: ['jekyll'],
@@ -68,7 +87,8 @@ export const FrameworkDetectors = [
name: 'docusaurus',
dist: 'build',
static: 'static',
build: 'npx docusaurus build'
build: 'npx docusaurus build',
server: 'http://localhost:3000'
},
requiredFiles: ['docusaurus.config.js'],
requiredDependencies: ['@docusaurus/core'],
@@ -80,7 +100,8 @@ export const FrameworkDetectors = [
framework: {
name: '11ty',
dist: '_site',
build: 'npx @11ty/eleventy'
build: 'npx @11ty/eleventy',
server: 'http://localhost:8080'
},
requiredDependencies: ['@11ty/eleventy'],
commands: {
@@ -91,7 +112,8 @@ export const FrameworkDetectors = [
framework: {
name: 'hexo',
dist: 'public',
build: 'npx hexo-cli generate'
build: 'npx hexo-cli generate',
server: 'http://localhost:4000'
},
requiredFiles: ['_config.js'],
requiredDependencies: ['hexo'],
+1 -1
View File
@@ -238,7 +238,7 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
return `
<!DOCTYPE html>
<html lang="en">
<html lang="en-US">
<head>
<meta http-equiv="Content-Security-Policy" content="${csp.join('; ')}">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
+13 -2
View File
@@ -1,7 +1,12 @@
import { join } from 'path';
import { commands, Uri } from 'vscode';
import { Folders } from '../../commands/Folders';
import { COMMAND_NAME, SETTING_CONTENT_STATIC_FOLDER, SETTING_FRAMEWORK_ID } from '../../constants';
import {
COMMAND_NAME,
SETTING_CONTENT_STATIC_FOLDER,
SETTING_FRAMEWORK_ID,
SETTING_PREVIEW_HOST
} from '../../constants';
import { DashboardCommand } from '../../dashboardWebView/DashboardCommand';
import { DashboardMessage } from '../../dashboardWebView/DashboardMessage';
import { DashboardSettings, Settings } from '../../helpers';
@@ -62,12 +67,18 @@ export class SettingsListener extends BaseListener {
if (frameworkId) {
const allFrameworks = FrameworkDetector.getAll();
const framework = allFrameworks.find((f: Framework) => f.name === frameworkId);
const framework: Framework | undefined = allFrameworks.find(
(f: Framework) => f.name === frameworkId
);
if (framework) {
if (framework.static) {
await Settings.update(SETTING_CONTENT_STATIC_FOLDER, framework.static, true);
}
if (framework.server) {
await Settings.update(SETTING_PREVIEW_HOST, framework.server, true);
}
await FrameworkDetector.checkDefaultSettings(framework);
} else {
await Settings.update(SETTING_CONTENT_STATIC_FOLDER, '', true);
+1
View File
@@ -3,4 +3,5 @@ export interface Framework {
dist: string;
static: string;
build: string;
server?: string;
}
+10
View File
@@ -104,10 +104,20 @@ export interface Field {
dataFileKey?: string;
dataFileValue?: string;
// Number field options
numberOptions?: NumberOptions;
// When clause
when?: WhenClause;
}
export interface NumberOptions {
isDecimal?: boolean;
min?: number;
max?: number;
step?: number;
}
export enum WhenOperator {
equals = 'eq',
notEquals = 'neq',
+6 -2
View File
@@ -13,7 +13,7 @@ import { FeatureFlag } from '../components/features/FeatureFlag';
import { FEATURE_FLAG } from '../constants/Features';
import { GitAction } from './components/Git/GitAction';
import { CustomView } from './components/CustomView';
import { useEffect, useState } from 'react';
import { useEffect, useMemo, useState } from 'react';
export interface IViewPanelProps { }
@@ -32,6 +32,10 @@ export const ViewPanel: React.FunctionComponent<IViewPanelProps> = (
mode
} = useMessages();
const allPanelValues = useMemo(() => {
return Object.values(FEATURE_FLAG.panel).filter(v => v !== FEATURE_FLAG.panel.globalSettings)
}, [FEATURE_FLAG.panel]);
useEffect(() => {
if (window.fmExternal && window.fmExternal.isDevelopment) {
setIsDevMode(true);
@@ -80,7 +84,7 @@ export const ViewPanel: React.FunctionComponent<IViewPanelProps> = (
<CustomView metadata={metadata} />
<FeatureFlag features={mode?.features || []} flag={FEATURE_FLAG.panel.globalSettings}>
<FeatureFlag features={mode?.features || [...allPanelValues]} flag={FEATURE_FLAG.panel.globalSettings}>
<GlobalSettings settings={settings} />
</FeatureFlag>
+6 -1
View File
@@ -11,6 +11,7 @@ import { FeatureFlag } from '../../components/features/FeatureFlag';
import { FEATURE_FLAG } from '../../constants/Features';
import { Messenger } from '@estruyf/vscode/dist/client';
import { GitAction } from './Git/GitAction';
import { useMemo } from 'react';
export interface IBaseViewProps {
settings: PanelSettings | undefined;
@@ -50,6 +51,10 @@ const BaseView: React.FunctionComponent<IBaseViewProps> = ({
(s) => s.bulk && (s.type === 'content' || !s.type)
);
const allPanelValues = useMemo(() => {
return Object.values(FEATURE_FLAG.panel).filter(v => v !== FEATURE_FLAG.panel.globalSettings)
}, [FEATURE_FLAG.panel]);
return (
<div className="frontmatter">
<div className={`ext_actions`}>
@@ -63,7 +68,7 @@ const BaseView: React.FunctionComponent<IBaseViewProps> = ({
<>
<GitAction settings={settings} />
<FeatureFlag features={mode?.features || []} flag={FEATURE_FLAG.panel.globalSettings}>
<FeatureFlag features={mode?.features || [...allPanelValues]} flag={FEATURE_FLAG.panel.globalSettings}>
<GlobalSettings settings={settings} isBase />
</FeatureFlag>
@@ -1,32 +1,34 @@
import { CalculatorIcon } from '@heroicons/react/outline';
import * as React from 'react';
import { useEffect, useMemo } from 'react';
import { BaseFieldProps } from '../../../models';
import { useCallback, useEffect, useMemo } from 'react';
import { BaseFieldProps, NumberOptions } from '../../../models';
import { FieldTitle } from './FieldTitle';
import { FieldMessage } from './FieldMessage';
export interface INumberFieldProps extends BaseFieldProps<number | null> {
options?: NumberOptions;
onChange: (nrValue: number | null) => void;
}
export const NumberField: React.FunctionComponent<INumberFieldProps> = ({
label,
description,
options,
value,
required,
onChange
}: React.PropsWithChildren<INumberFieldProps>) => {
const [nrValue, setNrValue] = React.useState<number | null>(value);
const onValueChange = (txtValue: string) => {
let newValue: number | null = parseInt(txtValue);
const onValueChange = useCallback((txtValue: string) => {
let newValue: number | null = options?.isDecimal ? parseFloat(txtValue) : parseInt(txtValue);
if (isNaN(newValue)) {
newValue = null;
}
setNrValue(newValue);
onChange(newValue);
};
}, [options?.isDecimal]);
const showRequiredState = useMemo(() => {
return required && (nrValue === null || nrValue === undefined);
@@ -38,6 +40,8 @@ export const NumberField: React.FunctionComponent<INumberFieldProps> = ({
}
}, [value]);
console.log(`NumberField: ${label} - ${value} - ${JSON.stringify(options)}`)
return (
<div className={`metadata_field ${showRequiredState ? 'required' : ''}`}>
<FieldTitle label={label} icon={<CalculatorIcon />} required={required} />
@@ -46,6 +50,9 @@ export const NumberField: React.FunctionComponent<INumberFieldProps> = ({
type={`number`}
className={`metadata_field__number`}
value={`${nrValue}`}
min={options?.min ?? undefined}
max={options?.max ?? undefined}
step={options?.step ?? undefined}
onChange={(e) => onValueChange(e.target.value)}
/>
@@ -217,7 +217,7 @@ export const WrapperField: React.FunctionComponent<IWrapperFieldProps> = ({
</FieldBoundary>
);
} else if (field.type === 'number') {
let nrValue: number | null = parseInt(fieldValue as string);
let nrValue: number | null = field.numberOptions?.isDecimal ? parseFloat(fieldValue as string) : parseInt(fieldValue as string);
if (isNaN(nrValue)) {
nrValue = null;
}
@@ -228,6 +228,7 @@ export const WrapperField: React.FunctionComponent<IWrapperFieldProps> = ({
key={field.name}
label={field.title || field.name}
description={field.description}
options={field.numberOptions}
onChange={(value) => onSendUpdate(field.name, value, parentFields)}
value={nrValue}
required={!!field.required}