diff --git a/app/javascript/packages/assets/README.md b/app/javascript/packages/assets/README.md new file mode 100644 index 00000000000..1ceefbb9399 --- /dev/null +++ b/app/javascript/packages/assets/README.md @@ -0,0 +1,35 @@ +# `@18f/identity-assets` + +Utilities for resolving asset URLs from [Ruby on Rails' Asset Pipeline](https://guides.rubyonrails.org/asset_pipeline.html). + +## Usage + +Within your code, use `getAssetPath` and provide a raw asset path, where the expected return value is the URL resolved by the Ruby on Rails Asset pipeline: + +```ts +const spriteURL = getAssetPath('sprite.svg'); +``` + +The included Webpack plugin will scan for references to `getAssetPath` and add those as assets of the associated Webpack entrypoint. + +```ts +// webpack.config.js + +module.exports = { + // ... + plugins: [ + // ... + new RailsAssetsWebpackPlugin(), + ], +}; +``` + +The expectation is that this can be used in combination with a tool like [`WebpackManifestPlugin`](https://github.com/shellscape/webpack-manifest-plugin) to generate a JSON manifest of all assets expected to be loaded with a given Webpack entrypoint, so that the backend can ensure those asset paths are populated into a ` +``` diff --git a/app/javascript/packages/config/README.md b/app/javascript/packages/config/README.md new file mode 100644 index 00000000000..cbd08991cfe --- /dev/null +++ b/app/javascript/packages/config/README.md @@ -0,0 +1,21 @@ +# `@18f/identity-config` + +Utilities for retrieving global application configuration values. + +## Usage + +From your JavaScript code, retrieve a configuration value using the `getConfigValue` export: + +```ts +const appName = getConfigValue('appName'); +``` + +The configuration is expected to be bootstrapped in page markup within a ` +``` diff --git a/app/javascript/packages/device/README.md b/app/javascript/packages/device/README.md new file mode 100644 index 00000000000..4eddb5570db --- /dev/null +++ b/app/javascript/packages/device/README.md @@ -0,0 +1,34 @@ +# `@18f/identity-device` + +Utilities for detecting details about the user's device. + +## Usage + +Import the desired utility function from the package: + +```ts +import { isLikelyMobile } from '@18f/identity-device'; + +isLikelyMobile(); +// true +``` + +## API + +### `isIPad` + +Returns true if the device is an iPad, or false otherwise. + +iPadOS devices no longer list the correct user agent. As a proxy, we check for the incorrect one (Macintosh) then test the number of touchpoints, which for iPads will be 5. + +### `isLikelyMobile` + +Returns true if the device is likely a mobile device, or false otherwise. This is a rough approximation, using device user agent sniffing. + +### `hasMediaAccess` + +Returns true if the current device allows access to camera device APIs. + +### `isCameraCapableMobile` + +Returns true if the current device is assumed to be a mobile device where a camera is available, or false otherwise. This is a rough approximation, using device user agent sniffing and availability of camera device APIs. diff --git a/app/javascript/packages/document-capture-polling/README.md b/app/javascript/packages/document-capture-polling/README.md new file mode 100644 index 00000000000..18f42cb180a --- /dev/null +++ b/app/javascript/packages/document-capture-polling/README.md @@ -0,0 +1,20 @@ +# `@18f/identity-document-capture-polling` + +Package implementing behaviors associated with the hybrid handoff document capture flow, where document capture is initiated on a desktop computer and completed on a mobile device. The behaviors of this package are responsible for polling for the result of a document capture happening on another device, and redirecting the user upon completion or failure. + +## Usage + +Initialize the package's binding with the polling endpoint and required elements: + +```ts +import { DocumentCapturePolling } from '@18f/identity-document-capture-polling'; + +new DocumentCapturePolling({ + statusEndpoint: '/path/to/endpoint', + elements: { + backLink: document.querySelector('.link-sent-back-link'), + form: document.querySelector('.link-sent-continue-button-form'), + }, +}).bind(); +``` + diff --git a/app/javascript/packages/document-capture/README.md b/app/javascript/packages/document-capture/README.md new file mode 100644 index 00000000000..7083f63bbcc --- /dev/null +++ b/app/javascript/packages/document-capture/README.md @@ -0,0 +1,22 @@ +# `@18f/identity-document-capture` + +React components for displaying a user interface for a user to upload or capture photos of their state-issued identification. + +## Usage + +Render the included `` React component. Most settings are expected to be configured by wrapping the component with one or more of the included context provider components. + +```tsx +import { render } from 'react-dom'; +import { DocumentCapture, AnalyticsContextProvider } from '@18f/identity-document-capture'; + +const appRoot = document.getElementById('app-root'); + +render( + + {/* ... */} + + , + appRoot +); +``` diff --git a/app/javascript/packages/form-steps/README.md b/app/javascript/packages/form-steps/README.md new file mode 100644 index 00000000000..4435bfac638 --- /dev/null +++ b/app/javascript/packages/form-steps/README.md @@ -0,0 +1,21 @@ +# `@18f/identity-form-steps` + +React components for managing a user's progression through a series of steps in a form. + +## Usage + +At a minimum, render the `` React component with an array of step configurations. Each step must include a `name` and `form`, where the `form` is a React component that will be rendered once the user reaches the step. + +```tsx +import { render } from 'react-dom'; +import { FormSteps } from '@18f/identity-form-steps'; + +const STEPS = [ + { name: 'First Step', form: () =>

Welcome to the first step!

}, + { name: 'Second Step', form: () =>

Welcome to the second step!

}, +]; + +const appRoot = document.getElementById('app-root'); + +render(, appRoot); +``` diff --git a/app/javascript/packages/masked-text-toggle/README.md b/app/javascript/packages/masked-text-toggle/README.md new file mode 100644 index 00000000000..d346c20fa18 --- /dev/null +++ b/app/javascript/packages/masked-text-toggle/README.md @@ -0,0 +1,32 @@ +# `@18f/identity-masked-text-toggle` + +Package implementing behaviors associated with toggling the visibility of text which is masked by default due to its sensitivity. + +For example, a Social Security number may be masked to show only `6**-**-***4` by default, and allow a user to toggle the visibility of the full number if desired. + +## Usage + +Initialize the package's binding with the polling endpoint and required elements: + +```ts +import MaskedTextToggle from '@18f/identity-masked-text-toggle'; + +const toggle = document.querySelector('.masked-text-toggle'); +new MaskedTextToggle(toggle).bind(); +``` + +The given toggle element is expected to be a checkbox, associated with the masked text wrapper by an `aria-controls` attribute. + +The masked text wrapper is expected to contain two variations of the text: a masked form (with a `data-masked="true"` attribute) and a revealed form (with a `data-masked="false"` attribute). The package will toggle visibility using the `display-none` utility class from the U.S. Web Design System. + +```html + + + 6**-**-***4 + + + + +``` diff --git a/app/javascript/packages/memorable-date/README.md b/app/javascript/packages/memorable-date/README.md new file mode 100644 index 00000000000..9865cc45843 --- /dev/null +++ b/app/javascript/packages/memorable-date/README.md @@ -0,0 +1,22 @@ +# `@18f/identity-memorable-date` + +Custom element implementing behaviors associated with Login.gov's adaptation of the U.S. Web Design System [Memorable Date component](https://designsystem.digital.gov/components/memorable-date/). + +## Usage + +Importing the element will register the `` custom element: + +```ts +import '@18f/identity-memorable-date/memorable-date-element'; +``` + +The custom element will implement modal behavior, but all markup must already exist. + +```html + + + + + + +``` diff --git a/app/javascript/packages/password-confirmation/README.md b/app/javascript/packages/password-confirmation/README.md index 5a5ae306cc8..97ad4545006 100644 --- a/app/javascript/packages/password-confirmation/README.md +++ b/app/javascript/packages/password-confirmation/README.md @@ -1,4 +1,4 @@ -# `@18f/password-confirmation` +# `@18f/identity-password-confirmation` Custom element implementation that adds password inputs with validation for confirmation. @@ -7,7 +7,7 @@ Custom element implementation that adds password inputs with validation for conf Importing the element will register the `` custom element: ```ts -import '@18f/password-confirmation/password-confirmation-element'; +import '@18f/identity-password-confirmation/password-confirmation-element'; ``` The custom element will implement the behavior for validation, but all markup must already exist. diff --git a/app/javascript/packages/password-toggle/README.md b/app/javascript/packages/password-toggle/README.md new file mode 100644 index 00000000000..84d23f0e595 --- /dev/null +++ b/app/javascript/packages/password-toggle/README.md @@ -0,0 +1,22 @@ +# `@18f/identity-password-toggle` + +Custom element implementation that toggles the visibility of a password field text in response to clicking a checkbox. + +## Usage + +Importing the element will register the `` custom element: + +```ts +import '@18f/identity-password-toggle/password-toggle-element'; +``` + +The custom element will implement associatd behaviors, but all markup must already exist. + +```html + + + + + + +``` diff --git a/app/javascript/packages/phone-input/README.md b/app/javascript/packages/phone-input/README.md new file mode 100644 index 00000000000..fa14a63cace --- /dev/null +++ b/app/javascript/packages/phone-input/README.md @@ -0,0 +1,31 @@ +# `@18f/identity-phone-input` + +Custom element implementation initializes an interactive phone input, using [`intl-tel-input`](https://github.com/jackocnr/intl-tel-input). + +## Usage + +Importing the element will register the `` custom element: + +```ts +import '@18f/identity-phone-input'; +``` + +The custom element will implement associatd behaviors, but all markup must already exist. + +```html + + +
+ + +
+ + +
+``` diff --git a/app/javascript/packages/spinner-button/README.md b/app/javascript/packages/spinner-button/README.md new file mode 100644 index 00000000000..54702984562 --- /dev/null +++ b/app/javascript/packages/spinner-button/README.md @@ -0,0 +1,38 @@ +# `@18f/identity-spinner-button` + +Custom element and React component for displaying a spinner effect on a button when clicked. + +## Usage + +### Custom Element + +Importing the element will register the `` custom element: + +```ts +import '@18f/identity-spinner-button/spinner-button-element'; +``` + +The custom element will implement associated behaviors, but all markup must already exist, rendered server-side or by the included React component. + +When clicked, the a `spinner-button--spinner-active` class will be added to the root element, which can be used to control the visibility of associated elements using custom CSS styles. + +```html + + + +``` + +### React + +The package exports a `` component. + +```tsx +import { render } from 'react-dom'; +import { SpinnerButton } from '@18f/identity-spinner-button'; + +const appRoot = document.getElementById('app-root'); + +render(Spin!, appRoot) +``` diff --git a/app/javascript/packages/time-element/README.md b/app/javascript/packages/time-element/README.md new file mode 100644 index 00000000000..49e7c385778 --- /dev/null +++ b/app/javascript/packages/time-element/README.md @@ -0,0 +1,21 @@ +# `@18f/identity-time-element` + +Custom element which converts a time string rendered by the server into the user's local time. + +## Usage + +The package exports a `TimeElement` custom element, which can be registered using the browser's custom element registry: + +```ts +import { TimeElement } from '@18f/identity-time-element'; + +customElements.define('lg-time', TimeElement); +``` + +The custom element will implement associated behaviors, but all markup must already exist. + +```html + + September 26, 2023 at 4:20 PM + +``` diff --git a/app/javascript/packages/validated-field/README.md b/app/javascript/packages/validated-field/README.md new file mode 100644 index 00000000000..e8fc974b5ab --- /dev/null +++ b/app/javascript/packages/validated-field/README.md @@ -0,0 +1,45 @@ +# `@18f/identity-validated-field` + +Custom element and React component for controlling validation behavior associated with a form input. + +It enhances the behavior of an input by: + +- Displaying an error message on the page when form submission results in a validation error +- Moving focus to the first invalid field when form submission results in a validation error +- Providing default error messages for common validation constraints (e.g. required field missing) +- Allowing you to customize error messages associated with default field validation +- Resetting the error state when an input value changes + +## Usage + +### Custom Element + +Importing the element will register the `` custom element: + +```ts +import '@18f/identity-validated-field/validated-field-element'; +``` + +The custom element will implement associated behaviors, but all markup must already exist, rendered server-side or by the included React component. + +```html + + +
+ +
+
+``` + +### React + +The package exports a `` component. If rendered without a child, it will render a text input by default. + +```tsx +import { render } from 'react-dom'; +import { ValidatedField } from '@18f/identity-validated-field'; + +const appRoot = document.getElementById('app-root'); + +render(, appRoot); +``` diff --git a/scripts/validate-workspaces.js b/scripts/validate-workspaces.js index 8b90e52ed60..a9a75bc42d1 100755 --- a/scripts/validate-workspaces.js +++ b/scripts/validate-workspaces.js @@ -135,22 +135,6 @@ const EXCEPTIONS = { // Reason: ESLint plugins must follow a specific format for their package names, which conflicts // with our standard "identity-" prefix. checkHaveCorrectPackageName: ['app/javascript/packages/eslint-plugin/package.json'], - // Reason: There is no reason aside from legacy prior to enforcement. Please write documentation! - checkHaveDocumentation: [ - 'app/javascript/packages/assets/package.json', - 'app/javascript/packages/config/package.json', - 'app/javascript/packages/device/package.json', - 'app/javascript/packages/document-capture/package.json', - 'app/javascript/packages/document-capture-polling/package.json', - 'app/javascript/packages/form-steps/package.json', - 'app/javascript/packages/masked-text-toggle/package.json', - 'app/javascript/packages/memorable-date/package.json', - 'app/javascript/packages/password-toggle/package.json', - 'app/javascript/packages/phone-input/package.json', - 'app/javascript/packages/spinner-button/package.json', - 'app/javascript/packages/time-element/package.json', - 'app/javascript/packages/validated-field/package.json', - ], }; const manifestPaths = glob('app/javascript/packages/*/package.json');