Skip to content

Commit

Permalink
Added the number-field component (#48)
Browse files Browse the repository at this point in the history
# Pull Request

## 📖 Description

<!--- Provide some background and a description of your work. -->
Adds the number-field foundation component.

Also applied a small cleanup to some of the component testing.

### 🎫 Issues

<!---
List and link relevant issues here using the keyword "closes"
if this PR will close an issue, eg. closes #411
-->
Continues work on #31

## ✅ Checklist

### General

<!--- Review the list and put an x in the boxes that apply. -->

- [x] I have added tests for my changes.
- [x] I have tested my changes.
- [x] I have updated the project documentation to reflect my changes.

## ⏭ Next Steps

<!---
If there is relevant follow-up work to this PR, please list any existing issues or provide brief descriptions of what you would like to do next.
-->
- Continue adding foundation components
  • Loading branch information
janechu committed May 18, 2022
1 parent 90bea9e commit 0535d57
Show file tree
Hide file tree
Showing 15 changed files with 509 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "none",
"comment": "Added the number-field component",
"packageName": "@microsoft/fast-cli",
"email": "7559015+janechu@users.noreply.github.com",
"dependentChangeType": "none"
}
56 changes: 50 additions & 6 deletions packages/fast-cli/src/cli.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { expect, test } from "@playwright/test";
import { execSync } from "child_process";
import path from "path";
import fs from "fs-extra";
import { requiredComponentTemplateFiles } from "./components/files.js";
import { availableTemplates } from "./components/options.js";

const dirname = path.resolve(process.cwd());
const tempDirRelativeLocation = "../temp";
Expand Down Expand Up @@ -59,11 +59,12 @@ function setup() {
"fast:config": `fast config -p ./src/components`,
"fast:add-design-system": `fast add-design-system -p test -s open`,
"fast:add-component:template": `fast add-component -n test-component -t ${path.resolve(dirname, "../temp-component")}`,
"fast:add-foundation-component:blank": `fast add-foundation-component -n test-component -t blank`,
"fast:add-foundation-component:badge": `fast add-foundation-component -n test-component -t badge`,
"fast:add-foundation-component:card": `fast add-foundation-component -n test-component -t card`,
"fast:add-foundation-component:dialog": `fast add-foundation-component -n test-component -t dialog`,
"fast:add-foundation-component:disclosure": `fast add-foundation-component -n test-component -t disclosure`,
...availableTemplates.reduce((prevValue, currValue: string) => {
return {
...prevValue,
[`fast:add-foundation-component:${currValue}`]: `fast add-foundation-component -n test-component -t ${currValue}`
}
}, {}),
};
fs.writeFileSync(path.resolve(tempDir, "package.json"), JSON.stringify(packageJson, null, 2));
}
Expand Down Expand Up @@ -467,5 +468,48 @@ test.describe("CLI", () => {
).not.toThrow();
});
});
test.describe("number-field", () => {
test.beforeAll(() => {
setup();
execSync(`cd ${tempDir} && npm run fast:init`);
setup();
execSync(`cd ${tempDir} && npm run fast:add-foundation-component:number-field`);
});
test.afterAll(() => {
teardown();
});
test("should copy files from the template", () => {
let files: Array<string> = [];

function testGeneratedFiles(folderName: string) {
const tempDirContents = fs.readdirSync(path.resolve(tempDir, "src/components/test-component", folderName));
const tempDirContentsWithFileTypes = fs.readdirSync(path.resolve(tempDir, "src/components/test-component", folderName), {
withFileTypes: true
});

for (let i = 0, contentLength = tempDirContents.length; i < contentLength; i++) {
if (tempDirContentsWithFileTypes[i].isDirectory()) {
testGeneratedFiles(tempDirContents[i]);
} else {
files.push(
folderName
? `${folderName}/${tempDirContents[i]}`
: tempDirContents[i]
);
}
}
}

testGeneratedFiles("");
expect(files).toEqual(expectedGeneratedComponentTemplateFiles);
});
test("should be able to run the build", () => {
expect(
() => {
execSync(`cd ${tempDir} && npm run build`);
}
).not.toThrow();
});
});
});
});
3 changes: 3 additions & 0 deletions packages/fast-cli/src/components/number-field/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Description

This template is used as a number-field component template from which a user can modify without having to do the initial scaffolding.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type { ComponentTemplateConfig } from "../../../utilities/template";

export default (config: ComponentTemplateConfig): string => `
# ${config.className}
An implementation of a [text field](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Input/text) as a form-connected web-component.
For more information on the building blocks used to create this component, please refer to https://www.fast.design/docs/components/number-field`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type { ComponentTemplateConfig } from "../../../utilities/template";

export default (config: ComponentTemplateConfig): string =>
`import { template } from "./${config.tagName}.template.js";
import { styles } from "./${config.tagName}.styles.js";
export const definition = {
baseName: "${config.tagName}",
template,
styles,
}`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type { ComponentTemplateConfig } from "../../../utilities/template";

export default (config: ComponentTemplateConfig): string => `
import { expect, test } from "@playwright/test";
import { fixtureURL } from "@microsoft/fast-cli/dist/esm/utilities/playwright.js";
test.describe("${config.tagName}", () => {
const fixture = fixtureURL("${config.tagName}");
test.beforeEach(async ({ page }) => {
await page.goto(fixture);
});
test("should load the fixture URL", async ({ page }) => {
const pageUrl = page.url();
expect(pageUrl).toBe(\`http://localhost:3000/\${fixture}\`);
});
test("should contain the component in the URL", async ({ page }) => {
const element = page.locator("${config.tagName}");
await expect(element).not.toBeNull();
});
});
`
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type { ComponentTemplateConfig } from "../../../utilities/template";

export default (config: ComponentTemplateConfig): string => `
import Template from "./fixtures/base.html";
import "./define.js";
export default {
title: "${config.tagName}",
};
export const ${config.className} = () => Template;
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
import type { ComponentTemplateConfig } from "../../../utilities/template";

export default (config: ComponentTemplateConfig): string =>
`import { css, ElementStyles } from "@microsoft/fast-element";
import {
disabledCursor,
display,
focusVisible,
forcedColorsStylesheetBehavior,
FoundationElementTemplate,
NumberFieldOptions,
} from "@microsoft/fast-foundation";
import { SystemColors } from "@microsoft/fast-web-utilities";
import {
accentFillActive,
accentFillHover,
accentFillRest,
bodyFont,
controlCornerRadius,
designUnit,
disabledOpacity,
focusStrokeOuter,
focusStrokeWidth,
heightNumber,
neutralFillHover,
neutralFillInputHover,
neutralFillInputRest,
neutralFillRest,
neutralForegroundRest,
neutralStrokeRest,
strokeWidth,
typeRampBaseFontSize,
typeRampBaseLineHeight,
} from "@microsoft/adaptive-ui";
/**
* Styles for ${config.className}
* @public
*/
export const styles: FoundationElementTemplate<ElementStyles> = (
context,
definition
) =>
css\`
\${display("inline-block")} :host {
font-family: \${bodyFont};
outline: none;
user-select: none;
}
.root {
box-sizing: border-box;
position: relative;
display: flex;
flex-direction: row;
color: \${neutralForegroundRest};
background: \${neutralFillInputRest};
border-radius: calc(\${controlCornerRadius} * 1px);
border: calc(\${strokeWidth} * 1px) solid \${accentFillRest};
height: calc(\${heightNumber} * 1px);
align-items: baseline;
}
.control {
-webkit-appearance: none;
font: inherit;
background: transparent;
border: 0;
color: inherit;
height: calc(100% - 4px);
width: 100%;
margin-top: auto;
margin-bottom: auto;
border: none;
padding: 0 calc(\${designUnit} * 2px + 1px);
font-size: \${typeRampBaseFontSize};
line-height: \${typeRampBaseLineHeight};
}
.control:hover,
.control:\${focusVisible},
.control:disabled,
.control:active {
outline: none;
}
.controls {
opacity: 0;
}
.label {
display: block;
color: \${neutralForegroundRest};
cursor: pointer;
font-size: \${typeRampBaseFontSize};
line-height: \${typeRampBaseLineHeight};
margin-bottom: 4px;
}
.label__hidden {
display: none;
visibility: hidden;
}
.start,
.control,
.controls,
.end {
align-self: center;
}
.start,
.end {
margin: auto;
fill: currentcolor;
}
.step-up-glyph,
.step-down-glyph {
display: block;
padding: 4px 10px;
cursor: pointer;
}
.step-up-glyph:before,
.step-down-glyph:before {
content: '';
display: block;
border: solid transparent 6px;
}
.step-up-glyph:before {
border-bottom-color: \${neutralForegroundRest};
}
.step-down-glyph:before {
border-top-color: \${neutralForegroundRest};
}
::slotted(svg) {
/* TODO: adaptive typography https://github.com/microsoft/fast/issues/2432 */
width: 16px;
height: 16px;
}
.start {
margin-inline-start: 11px;
}
.end {
margin-inline-end: 11px;
}
:host(:hover:not([disabled])) .root {
background: \${neutralFillInputHover};
border-color: \${accentFillHover};
}
:host(:active:not([disabled])) .root {
background: \${neutralFillInputHover};
border-color: \${accentFillActive};
}
:host(:focus-within:not([disabled])) .root {
border-color: \${focusStrokeOuter};
box-shadow: 0 0 0 calc(\${focusStrokeWidth} * 1px) \${focusStrokeOuter} inset;
}
:host(:hover:not([disabled])) .controls,
:host(:focus-within:not([disabled])) .controls {
opacity: 1;
}
:host([appearance="filled"]) .root {
background: \${neutralFillRest};
}
:host([appearance="filled"]:hover:not([disabled])) .root {
background: \${neutralFillHover};
}
:host([disabled]) .label,
:host([readonly]) .label,
:host([readonly]) .control,
:host([disabled]) .control {
cursor: \${disabledCursor};
}
:host([disabled]) {
opacity: \${disabledOpacity};
}
:host([disabled]) .control {
border-color: \${neutralStrokeRest};
}
\`.withBehaviors(
forcedColorsStylesheetBehavior(
css\`
.root,
:host([appearance="filled"]) .root {
forced-color-adjust: none;
background: \${SystemColors.Field};
border-color: \${SystemColors.FieldText};
}
:host(:hover:not([disabled])) .root,
:host([appearance="filled"]:hover:not([disabled])) .root,
:host([appearance="filled"]:hover) .root {
background: \${SystemColors.Field};
border-color: \${SystemColors.Highlight};
}
.start,
.end {
fill: currentcolor;
}
:host([disabled]) {
opacity: 1;
}
:host([disabled]) .root,
:host([appearance="filled"]:hover[disabled]) .root {
border-color: \${SystemColors.GrayText};
background: \${SystemColors.Field};
}
:host(:focus-within:enabled) .root {
border-color: \${SystemColors.Highlight};
box-shadow: 0 0 0 1px \${SystemColors.Highlight} inset;
}
input::placeholder {
color: \${SystemColors.GrayText};
}
\`
)
);`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { ComponentTemplateConfig } from "../../../utilities/template";

export default (config: ComponentTemplateConfig): string => `
import { NumberField, numberFieldTemplate, FoundationElementTemplate } from "@microsoft/fast-foundation";
import type { ViewTemplate } from "@microsoft/fast-element";
/**
* The template for ${config.className} component.
* @public
*/
export const template: FoundationElementTemplate<ViewTemplate<NumberField>> = numberFieldTemplate;
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import type { ComponentTemplateConfig } from "../../../utilities/template";

export default (config: ComponentTemplateConfig): string =>
`import { NumberField } from "@microsoft/fast-foundation";
/**
* A class derived from the NumberField foundation component
*/
export class ${config.className} extends NumberField {};`
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type { ComponentTemplateConfig } from "../../../utilities/template";

export default (config: ComponentTemplateConfig): string =>
`import { ${config.className} } from "./${config.tagName}.js";
import { definition } from "./${config.tagName}.definition.js";
${config.className}.compose(definition);`;

0 comments on commit 0535d57

Please sign in to comment.