Skip to content

Commit

Permalink
Merge pull request #5499 from alphagov/export-configurable-class
Browse files Browse the repository at this point in the history
Rename `GOVUKFrontendComponentConfigurable`, export `ConfigurableComponent`
  • Loading branch information
patrickpatrickpatrick authored Nov 22, 2024
2 parents 0496828 + 81b8df2 commit 19bea6b
Show file tree
Hide file tree
Showing 12 changed files with 55 additions and 41 deletions.
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,21 @@ For advice on how to use these release notes see [our guidance on staying up to

## Unreleased

### Use our base configurable component to build your own configurable component

We've added a `ConfigurableComponent` class to help you build your own configurable components. It extends our base component class and so it allows you to focus on your components' specific features by handling these shared behaviours across components:

- checking that GOV.UK Frontend is supported
- checking that the component is not already initialised on its root element
- checking the type of the root element and storing it for access within the component as this.$root
- taking a configuration object as a parameter and then storing it for access within the component as this.config
- merging a passed configuration object with configuration options specified on the data attributes of the root element

We introduced this change in:

- [#5499: Rename GOVUKFrontendComponentConfigurable, export ConfigurableComponent](https://github.com/alphagov/govuk-frontend/pull/5499)
- [#5456: Refactor Accordion to extend from a GOVUKFrontendConfigurableComponent](https://github.com/alphagov/govuk-frontend/issues/5456)

## v5.7.1 (Fix release)

To install this version with npm, run `npm install [email protected]`. You can also find more information about [how to stay up to date](https://frontend.design-system.service.gov.uk/staying-up-to-date/#updating-to-the-latest-version) in our documentation.
Expand Down
1 change: 1 addition & 0 deletions packages/govuk-frontend/src/govuk/all.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export { Tabs } from './components/tabs/tabs.mjs'
export { initAll, createAll } from './init.mjs'
export { isSupported } from './common/index.mjs'
export { GOVUKFrontendComponent as Component } from './govuk-frontend-component.mjs'
export { ConfigurableComponent } from './common/configuration.mjs'

/**
* @typedef {import('./init.mjs').Config} Config
Expand Down
1 change: 1 addition & 0 deletions packages/govuk-frontend/src/govuk/all.puppeteer.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ describe('GOV.UK Frontend', () => {
'CharacterCount',
'Checkboxes',
'Component',
'ConfigurableComponent',
'ErrorSummary',
'ExitThisPage',
'Header',
Expand Down
2 changes: 1 addition & 1 deletion packages/govuk-frontend/src/govuk/common/configuration.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const configOverride = Symbol.for('configOverride')
* @template {Element & { dataset: DOMStringMap }} [RootElementType=HTMLElement]
* @augments GOVUKFrontendComponent<RootElementType>
*/
export class GOVUKFrontendComponentConfigurable extends GOVUKFrontendComponent {
export class ConfigurableComponent extends GOVUKFrontendComponent {
/**
* configOverride
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import { ConfigError } from '../../errors/index.mjs'
import {
GOVUKFrontendComponentConfigurable,
configOverride
} from '../configuration.mjs'
import { ConfigurableComponent, configOverride } from '../configuration.mjs'

describe('GOVUKFrontendComponentConfigurable', () => {
describe('ConfigurableComponent', () => {
beforeEach(() => {
// Jest does not tidy the JSDOM document between tests
// so we need to take care of that ourselves
Expand All @@ -18,23 +15,23 @@ describe('GOVUKFrontendComponentConfigurable', () => {

describe('throws error', () => {
it('if no schema defined', () => {
class ConfigurableComponent extends GOVUKFrontendComponentConfigurable {
class MockConfigurableComponent extends ConfigurableComponent {
static moduleName = 'config-component'

static defaults = {
randomAttribute: 0
}
}

expect(() => new ConfigurableComponent(document.body)).toThrow(
expect(() => new MockConfigurableComponent(document.body)).toThrow(
new ConfigError(
'config-component: Config passed as parameter into constructor but no schema defined'
)
)
})

it('if no defaults defined', () => {
class ConfigurableComponent extends GOVUKFrontendComponentConfigurable {
class MockConfigurableComponent extends ConfigurableComponent {
static moduleName = 'config-component'

static schema = {
Expand All @@ -44,7 +41,7 @@ describe('GOVUKFrontendComponentConfigurable', () => {
}
}

expect(() => new ConfigurableComponent(document.body)).toThrow(
expect(() => new MockConfigurableComponent(document.body)).toThrow(
new ConfigError(
'config-component: Config passed as parameter into constructor but no defaults defined'
)
Expand All @@ -58,7 +55,7 @@ describe('GOVUKFrontendComponentConfigurable', () => {
<div id="test-component"></div>
`

class ConfigurableComponent extends GOVUKFrontendComponentConfigurable {
class MockConfigurableComponent extends ConfigurableComponent {
static moduleName = 'config-component'

static schema = {
Expand All @@ -74,7 +71,7 @@ describe('GOVUKFrontendComponentConfigurable', () => {

const testComponent = document.querySelector('#test-component')

const configComponent = new ConfigurableComponent(testComponent)
const configComponent = new MockConfigurableComponent(testComponent)

expect(configComponent._config).toMatchObject({ randomAttribute: 0 })
})
Expand All @@ -84,7 +81,7 @@ describe('GOVUKFrontendComponentConfigurable', () => {
<div id="test-component" data-random-attribute="42"></div>
`

class ConfigurableComponent extends GOVUKFrontendComponentConfigurable {
class MockConfigurableComponent extends ConfigurableComponent {
static moduleName = 'config-component'

static schema = {
Expand All @@ -100,7 +97,7 @@ describe('GOVUKFrontendComponentConfigurable', () => {

const testComponent = document.querySelector('#test-component')

const configComponent = new ConfigurableComponent(testComponent)
const configComponent = new MockConfigurableComponent(testComponent)

expect(configComponent._config).toMatchObject({ randomAttribute: 42 })
})
Expand All @@ -110,7 +107,7 @@ describe('GOVUKFrontendComponentConfigurable', () => {
<div id="test-component"></div>
`

class ConfigurableComponent extends GOVUKFrontendComponentConfigurable {
class MockConfigurableComponent extends ConfigurableComponent {
static moduleName = 'config-component'

static schema = {
Expand All @@ -126,7 +123,7 @@ describe('GOVUKFrontendComponentConfigurable', () => {

const testComponent = document.querySelector('#test-component')

const configComponent = new ConfigurableComponent(testComponent, {
const configComponent = new MockConfigurableComponent(testComponent, {
randomAttribute: 100
})

Expand All @@ -138,7 +135,7 @@ describe('GOVUKFrontendComponentConfigurable', () => {
<div id="test-component" data-random-attribute="12"></div>
`

class ConfigurableComponent extends GOVUKFrontendComponentConfigurable {
class MockConfigurableComponent extends ConfigurableComponent {
static moduleName = 'config-component'

static schema = {
Expand All @@ -154,7 +151,7 @@ describe('GOVUKFrontendComponentConfigurable', () => {

const testComponent = document.querySelector('#test-component')

const configComponent = new ConfigurableComponent(testComponent, {
const configComponent = new MockConfigurableComponent(testComponent, {
randomAttribute: 100
})

Expand All @@ -170,7 +167,7 @@ describe('GOVUKFrontendComponentConfigurable', () => {
<div id="test-component" data-random-attribute="13"></div>
`

class ConfigurableComponent extends GOVUKFrontendComponentConfigurable {
class MockConfigurableComponent extends ConfigurableComponent {
[configOverride](config) {
return configOverrideFunction(config)
}
Expand All @@ -190,7 +187,7 @@ describe('GOVUKFrontendComponentConfigurable', () => {

const testComponent = document.querySelector('#test-component')

const configComponent = new ConfigurableComponent(testComponent, {
const configComponent = new MockConfigurableComponent(testComponent, {
randomAttribute: '14'
})

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { GOVUKFrontendComponentConfigurable } from '../../common/configuration.mjs'
import { ConfigurableComponent } from '../../common/configuration.mjs'
import { ElementError } from '../../errors/index.mjs'
import { I18n } from '../../i18n.mjs'

Expand All @@ -15,9 +15,9 @@ import { I18n } from '../../i18n.mjs'
* attribute, which also provides accessibility.
*
* @preserve
* @augments GOVUKFrontendComponentConfigurable<AccordionConfig>
* @augments ConfigurableComponent<AccordionConfig>
*/
export class Accordion extends GOVUKFrontendComponentConfigurable {
export class Accordion extends ConfigurableComponent {
/** @private */
i18n

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { GOVUKFrontendComponentConfigurable } from '../../common/configuration.mjs'
import { ConfigurableComponent } from '../../common/configuration.mjs'

const DEBOUNCE_TIMEOUT_IN_SECONDS = 1

/**
* JavaScript enhancements for the Button component
*
* @preserve
* @augments GOVUKFrontendComponentConfigurable<ButtonConfig>
* @augments ConfigurableComponent<ButtonConfig>
*/
export class Button extends GOVUKFrontendComponentConfigurable {
export class Button extends ConfigurableComponent {
/**
* @private
* @type {number | null}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { closestAttributeValue } from '../../common/closest-attribute-value.mjs'
import {
validateConfig,
GOVUKFrontendComponentConfigurable,
ConfigurableComponent,
configOverride
} from '../../common/configuration.mjs'
import { formatErrorMessage } from '../../common/index.mjs'
Expand All @@ -19,9 +19,9 @@ import { I18n } from '../../i18n.mjs'
* of the available characters/words has been entered.
*
* @preserve
* @augments GOVUKFrontendComponentConfigurable<CharacterCountConfig>
* @augments ConfigurableComponent<CharacterCountConfig>
*/
export class CharacterCount extends GOVUKFrontendComponentConfigurable {
export class CharacterCount extends ConfigurableComponent {
/** @private */
$textarea

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { GOVUKFrontendComponentConfigurable } from '../../common/configuration.mjs'
import { ConfigurableComponent } from '../../common/configuration.mjs'
import { getFragmentFromUrl, setFocus } from '../../common/index.mjs'

/**
Expand All @@ -8,9 +8,9 @@ import { getFragmentFromUrl, setFocus } from '../../common/index.mjs'
* configuration.
*
* @preserve
* @augments GOVUKFrontendComponentConfigurable<ErrorSummaryConfig>
* @augments ConfigurableComponent<ErrorSummaryConfig>
*/
export class ErrorSummary extends GOVUKFrontendComponentConfigurable {
export class ErrorSummary extends ConfigurableComponent {
/**
* @param {Element | null} $root - HTML element to use for error summary
* @param {ErrorSummaryConfig} [config] - Error summary config
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { GOVUKFrontendComponentConfigurable } from '../../common/configuration.mjs'
import { ConfigurableComponent } from '../../common/configuration.mjs'
import { ElementError } from '../../errors/index.mjs'
import { I18n } from '../../i18n.mjs'

/**
* Exit this page component
*
* @preserve
* @augments GOVUKFrontendComponentConfigurable<ExitThisPageConfig>
* @augments ConfigurableComponent<ExitThisPageConfig>
*/
export class ExitThisPage extends GOVUKFrontendComponentConfigurable {
export class ExitThisPage extends ConfigurableComponent {
/** @private */
i18n

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { GOVUKFrontendComponentConfigurable } from '../../common/configuration.mjs'
import { ConfigurableComponent } from '../../common/configuration.mjs'
import { setFocus } from '../../common/index.mjs'

/**
* Notification Banner component
*
* @preserve
* @augments GOVUKFrontendComponentConfigurable<NotificationBannerConfig>
* @augments ConfigurableComponent<NotificationBannerConfig>
*/
export class NotificationBanner extends GOVUKFrontendComponentConfigurable {
export class NotificationBanner extends ConfigurableComponent {
/**
* @param {Element | null} $root - HTML element to use for notification banner
* @param {NotificationBannerConfig} [config] - Notification banner config
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { closestAttributeValue } from '../../common/closest-attribute-value.mjs'
import { GOVUKFrontendComponentConfigurable } from '../../common/configuration.mjs'
import { ConfigurableComponent } from '../../common/configuration.mjs'
import { ElementError } from '../../errors/index.mjs'
import { I18n } from '../../i18n.mjs'

/**
* Password input component
*
* @preserve
* @augments GOVUKFrontendComponentConfigurable<PasswordInputConfig>
* @augments ConfigurableComponent<PasswordInputConfig>
*/
export class PasswordInput extends GOVUKFrontendComponentConfigurable {
export class PasswordInput extends ConfigurableComponent {
/** @private */
i18n

Expand Down

0 comments on commit 19bea6b

Please sign in to comment.