From f44331cfe6b1049807d1ee1cc76b2dfa1c4fc445 Mon Sep 17 00:00:00 2001 From: Aagash Raaj Date: Mon, 28 Aug 2023 18:19:47 +0530 Subject: [PATCH 01/19] Add label provider for rich-text-editor --- packages/nimble-components/CONTRIBUTING.md | 3 +- .../label-provider/rich-text-editor/index.ts | 52 +++++++ .../rich-text-editor/label-token-defaults.ts | 10 ++ .../rich-text-editor/label-tokens.ts | 22 +++ .../rich-text-editor/name-utils.ts | 12 ++ .../label-provider-rich-text-editor.spec.ts | 137 ++++++++++++++++++ ...label-provider-rich-text-editor.stories.ts | 23 +++ .../src/rich-text-editor/template.ts | 17 ++- .../testing/rich-text-editor.pageobject.ts | 18 +-- .../tests/rich-text-editor-labels.spec.ts | 72 +++++++++ .../tests/rich-text-editor.stories.ts | 6 +- 11 files changed, 353 insertions(+), 19 deletions(-) create mode 100644 packages/nimble-components/src/label-provider/rich-text-editor/index.ts create mode 100644 packages/nimble-components/src/label-provider/rich-text-editor/label-token-defaults.ts create mode 100644 packages/nimble-components/src/label-provider/rich-text-editor/label-tokens.ts create mode 100644 packages/nimble-components/src/label-provider/rich-text-editor/name-utils.ts create mode 100644 packages/nimble-components/src/label-provider/rich-text-editor/tests/label-provider-rich-text-editor.spec.ts create mode 100644 packages/nimble-components/src/label-provider/rich-text-editor/tests/label-provider-rich-text-editor.stories.ts create mode 100644 packages/nimble-components/src/rich-text-editor/tests/rich-text-editor-labels.spec.ts diff --git a/packages/nimble-components/CONTRIBUTING.md b/packages/nimble-components/CONTRIBUTING.md index 1173124182..71aee951ba 100644 --- a/packages/nimble-components/CONTRIBUTING.md +++ b/packages/nimble-components/CONTRIBUTING.md @@ -445,10 +445,11 @@ When creating a new component, create a `*-matrix.stories.ts` Storybook file to Most user-visible strings displayed by Nimble components are provided by the client application and are expected to be localized by the application if necessary. However, some strings are built into Nimble components and are provided only in English. An application can provide localized versions of these strings by using design tokens set on label provider elements. -There are currently 2 label providers: +There are currently 3 label providers: - `nimble-label-provider-core`: Used for labels for all components besides the table - `nimble-label-provider-table`: Used for labels for the table (and table sub-components / column types) +- `nimble-label-provider-rich-text-editor`: Used for labels for the rich text editor The expected format for label token names is: diff --git a/packages/nimble-components/src/label-provider/rich-text-editor/index.ts b/packages/nimble-components/src/label-provider/rich-text-editor/index.ts new file mode 100644 index 0000000000..8c29be5cba --- /dev/null +++ b/packages/nimble-components/src/label-provider/rich-text-editor/index.ts @@ -0,0 +1,52 @@ +import { attr } from '@microsoft/fast-element'; +import { DesignSystem } from '@microsoft/fast-foundation'; +import { DesignTokensFor, LabelProviderBase } from '../base'; +import { + richTextEditorToggleBoldLabel, + richTextEditorToggleItalicsLabel, + richTextEditorToggleBulletListLabel, + richTextEditorToggleNumberedListLabel +} from './label-tokens'; + +declare global { + interface HTMLElementTagNameMap { + 'nimble-label-provider-rich-text-editor': LabelProviderRichTextEditor; + } +} + +const supportedLabels = { + toggleBold: richTextEditorToggleBoldLabel, + toggleItalics: richTextEditorToggleItalicsLabel, + toggleBulletList: richTextEditorToggleBulletListLabel, + toggleNumberedList: richTextEditorToggleNumberedListLabel, +} as const; + +/** + * Label provider for the Nimble rich text editor + */ +export class LabelProviderRichTextEditor + extends LabelProviderBase + implements DesignTokensFor { + @attr({ attribute: 'toggle-bold' }) + public toggleBold: string | undefined; + + @attr({ attribute: 'toggle-italics' }) + public toggleItalics: string | undefined; + + @attr({ attribute: 'toggle-bullet-list' }) + public toggleBulletList: string | undefined; + + @attr({ attribute: 'toggle-numbered-list' }) + public toggleNumberedList: string | undefined; + + protected override readonly supportedLabels = supportedLabels; +} + +const nimbleLabelProviderRichTextEditor = LabelProviderRichTextEditor.compose({ + baseName: 'label-provider-rich-text-editor' +}); + +DesignSystem.getOrCreate() + .withPrefix('nimble') + .register(nimbleLabelProviderRichTextEditor()); +export const labelProviderRichTextEditorTag = DesignSystem.tagFor(LabelProviderRichTextEditor); diff --git a/packages/nimble-components/src/label-provider/rich-text-editor/label-token-defaults.ts b/packages/nimble-components/src/label-provider/rich-text-editor/label-token-defaults.ts new file mode 100644 index 0000000000..15db6967bb --- /dev/null +++ b/packages/nimble-components/src/label-provider/rich-text-editor/label-token-defaults.ts @@ -0,0 +1,10 @@ +import type * as TokensNamespace from './label-tokens'; + +type TokenName = keyof typeof TokensNamespace; + +export const richTextEditorLabelDefaults: { readonly [key in TokenName]: string } = { + richTextEditorToggleBoldLabel: 'Bold', + richTextEditorToggleItalicsLabel: 'Italics', + richTextEditorToggleBulletListLabel: 'Bullet List', + richTextEditorToggleNumberedListLabel: 'Numbered List', +}; diff --git a/packages/nimble-components/src/label-provider/rich-text-editor/label-tokens.ts b/packages/nimble-components/src/label-provider/rich-text-editor/label-tokens.ts new file mode 100644 index 0000000000..2327dd1569 --- /dev/null +++ b/packages/nimble-components/src/label-provider/rich-text-editor/label-tokens.ts @@ -0,0 +1,22 @@ +import { DesignToken } from '@microsoft/fast-foundation'; +import { richTextEditorLabelDefaults } from './label-token-defaults'; + +export const richTextEditorToggleBoldLabel = DesignToken.create({ + name: 'rich-text-editor-toggle-bold-label', + cssCustomPropertyName: null +}).withDefault(richTextEditorLabelDefaults.richTextEditorToggleBoldLabel); + +export const richTextEditorToggleItalicsLabel = DesignToken.create({ + name: 'rich-text-editor-toggle-italics-label', + cssCustomPropertyName: null +}).withDefault(richTextEditorLabelDefaults.richTextEditorToggleItalicsLabel); + +export const richTextEditorToggleBulletListLabel = DesignToken.create({ + name: 'rich-text-editor-toggle-bullet-list-label', + cssCustomPropertyName: null +}).withDefault(richTextEditorLabelDefaults.richTextEditorToggleBulletListLabel); + +export const richTextEditorToggleNumberedListLabel = DesignToken.create({ + name: 'rich-text-editor-toggle-numbered-list-label', + cssCustomPropertyName: null +}).withDefault(richTextEditorLabelDefaults.richTextEditorToggleNumberedListLabel); diff --git a/packages/nimble-components/src/label-provider/rich-text-editor/name-utils.ts b/packages/nimble-components/src/label-provider/rich-text-editor/name-utils.ts new file mode 100644 index 0000000000..234e31b151 --- /dev/null +++ b/packages/nimble-components/src/label-provider/rich-text-editor/name-utils.ts @@ -0,0 +1,12 @@ +/** + * Removes the richTextEditor prefix and camelCases the input token name. + * (The design token name has the richTextEditor prefix, but the properties on the LabelProviderRichTextEditor do not, as they're already + * scoped to the rich-text-editor only) + */ +export function removeRichTextEditorPrefixAndCamelCase(jsTokenName: string): string { + // Example: 'richTextEditorToggleBulletListLabel' => 'toggleBulletListLabel' + return jsTokenName.replace( + /^richTextEditor(\w)(\w+)/, + (_match: string, firstChar: string, restOfString: string) => `${firstChar.toLowerCase()}${restOfString}` + ); +} diff --git a/packages/nimble-components/src/label-provider/rich-text-editor/tests/label-provider-rich-text-editor.spec.ts b/packages/nimble-components/src/label-provider/rich-text-editor/tests/label-provider-rich-text-editor.spec.ts new file mode 100644 index 0000000000..65426273ae --- /dev/null +++ b/packages/nimble-components/src/label-provider/rich-text-editor/tests/label-provider-rich-text-editor.spec.ts @@ -0,0 +1,137 @@ +import { spinalCase } from '@microsoft/fast-web-utilities'; +import { html } from '@microsoft/fast-element'; +import * as labelTokensNamespace from '../label-tokens'; +import { LabelProviderRichTextEditor, labelProviderRichTextEditorTag } from '..'; +import { getSpecTypeByNamedList } from '../../../utilities/tests/parameterized'; +import { + getAttributeName, + getPropertyName +} from '../../base/tests/label-name-utils'; +import { ThemeProvider, themeProviderTag } from '../../../theme-provider'; +import { Fixture, fixture } from '../../../utilities/tests/fixture'; +import { removeRichTextEditorPrefixAndCamelCase } from '../name-utils'; + +type DesignTokenPropertyName = keyof typeof labelTokensNamespace; +const designTokenPropertyNames = Object.keys( + labelTokensNamespace +) as DesignTokenPropertyName[]; + +async function setup(): Promise> { + return fixture(html` + <${themeProviderTag}> + <${labelProviderRichTextEditorTag}> + + `); +} + +describe('Label Provider Rich Text Editor', () => { + let element: LabelProviderRichTextEditor; + let themeProvider: ThemeProvider; + let connect: () => Promise; + let disconnect: () => Promise; + + beforeEach(async () => { + ({ element: themeProvider, connect, disconnect } = await setup()); + element = themeProvider.querySelector(labelProviderRichTextEditorTag)!; + await connect(); + }); + + afterEach(async () => { + await disconnect(); + }); + + it('can construct an element instance', () => { + expect( + document.createElement('nimble-label-provider-rich-text-editor') + ).toBeInstanceOf(LabelProviderRichTextEditor); + }); + + describe('token JS key should match DesignToken.name', () => { + const tokenEntries = designTokenPropertyNames.map( + (name: DesignTokenPropertyName) => ({ + name, + labelToken: labelTokensNamespace[name] + }) + ); + + for (const tokenEntry of tokenEntries) { + const focused: DesignTokenPropertyName[] = []; + const disabled: DesignTokenPropertyName[] = []; + const specType = getSpecTypeByNamedList( + tokenEntry, + focused, + disabled + ); + specType(`for token name ${tokenEntry.name}`, () => { + const convertedTokenValue = spinalCase(tokenEntry.name); + expect(tokenEntry.labelToken.name).toBe(convertedTokenValue); + }); + } + }); + + describe('token JS key should match a LabelProvider property/attribute', () => { + const tokenEntries = designTokenPropertyNames.map( + (name: DesignTokenPropertyName) => ({ + name, + labelToken: labelTokensNamespace[name] + }) + ); + + for (const tokenEntry of tokenEntries) { + const focused: DesignTokenPropertyName[] = []; + const disabled: DesignTokenPropertyName[] = []; + const specType = getSpecTypeByNamedList( + tokenEntry, + focused, + disabled + ); + // eslint-disable-next-line @typescript-eslint/no-loop-func + specType(`for token name ${tokenEntry.name}`, () => { + const tokenName = removeRichTextEditorPrefixAndCamelCase( + tokenEntry.name + ); + const expectedPropertyName = getPropertyName(tokenName); + const expectedAttributeName = getAttributeName(tokenName); + const attributeDefinition = element.$fastController.definition.attributes.find( + a => a.name === expectedPropertyName + ); + expect(attributeDefinition).toBeDefined(); + expect(expectedAttributeName).toEqual( + attributeDefinition!.attribute + ); + }); + } + }); + + describe('token value is updated after setting corresponding LabelProvider attribute', () => { + const tokenEntries = designTokenPropertyNames.map( + (name: DesignTokenPropertyName) => ({ + name, + labelToken: labelTokensNamespace[name] + }) + ); + + for (const tokenEntry of tokenEntries) { + const focused: DesignTokenPropertyName[] = []; + const disabled: DesignTokenPropertyName[] = []; + const specType = getSpecTypeByNamedList( + tokenEntry, + focused, + disabled + ); + // eslint-disable-next-line @typescript-eslint/no-loop-func + specType(`for token name ${tokenEntry.name}`, () => { + const tokenName = removeRichTextEditorPrefixAndCamelCase( + tokenEntry.name + ); + const attributeName = getAttributeName(tokenName); + const updatedValue = `NewString-${tokenName}`; + element.setAttribute(attributeName, updatedValue); + + expect(tokenEntry.labelToken.getValueFor(themeProvider)).toBe( + updatedValue + ); + }); + } + }); +}); diff --git a/packages/nimble-components/src/label-provider/rich-text-editor/tests/label-provider-rich-text-editor.stories.ts b/packages/nimble-components/src/label-provider/rich-text-editor/tests/label-provider-rich-text-editor.stories.ts new file mode 100644 index 0000000000..c03ac632a5 --- /dev/null +++ b/packages/nimble-components/src/label-provider/rich-text-editor/tests/label-provider-rich-text-editor.stories.ts @@ -0,0 +1,23 @@ +import type { StoryObj } from '@storybook/html'; +import { + LabelProviderArgs, + labelProviderMetadata +} from '../../base/tests/label-provider-stories-utils'; +import { labelProviderRichTextEditorTag } from '..'; +import * as labelTokensNamespace from '../label-tokens'; +import { removeRichTextEditorPrefixAndCamelCase } from '../name-utils'; + +const metadata = { + ...labelProviderMetadata, + title: 'Tokens/Label Providers' +}; + +export default metadata; + +export const richTextEditorLabelProvider: StoryObj = { + args: { + labelProviderTag: labelProviderRichTextEditorTag, + labelTokens: Object.entries(labelTokensNamespace), + removeNamePrefix: removeRichTextEditorPrefixAndCamelCase + } +}; diff --git a/packages/nimble-components/src/rich-text-editor/template.ts b/packages/nimble-components/src/rich-text-editor/template.ts index e8db67808a..3ef3852f82 100644 --- a/packages/nimble-components/src/rich-text-editor/template.ts +++ b/packages/nimble-components/src/rich-text-editor/template.ts @@ -6,6 +6,7 @@ import { iconBoldBTag } from '../icons/bold-b'; import { iconItalicITag } from '../icons/italic-i'; import { iconListTag } from '../icons/list'; import { iconNumberListTag } from '../icons/number-list'; +import { richTextEditorToggleBoldLabel, richTextEditorToggleItalicsLabel, richTextEditorToggleBulletListLabel, richTextEditorToggleNumberedListLabel } from '../label-provider/rich-text-editor/label-tokens'; // prettier-ignore export const template = html` @@ -20,12 +21,12 @@ export const template = html` appearance="ghost" content-hidden slot="start" - title="Bold" + title=${x => richTextEditorToggleBoldLabel.getValueFor(x)} @click=${x => x.boldButtonClick()} @change=${(x, c) => x.stopEventPropagation(c.event)} @keydown=${(x, c) => x.boldButtonKeyDown(c.event as KeyboardEvent)} > - Bold + ${x => richTextEditorToggleBoldLabel.getValueFor(x)} <${iconBoldBTag} slot="start"> <${toggleButtonTag} @@ -33,12 +34,12 @@ export const template = html` appearance="ghost" content-hidden slot="start" - title="Italics" + title=${x => richTextEditorToggleItalicsLabel.getValueFor(x)} @click=${x => x.italicsButtonClick()} @change=${(x, c) => x.stopEventPropagation(c.event)} @keydown=${(x, c) => x.italicsButtonKeyDown(c.event as KeyboardEvent)} > - Italics + ${x => richTextEditorToggleItalicsLabel.getValueFor(x)} <${iconItalicITag} slot="start"> <${toggleButtonTag} @@ -46,12 +47,12 @@ export const template = html` appearance="ghost" content-hidden slot="start" - title="Bullet List" + title=${x => richTextEditorToggleBulletListLabel.getValueFor(x)} @click=${x => x.bulletListButtonClick()} @change=${(x, c) => x.stopEventPropagation(c.event)} @keydown=${(x, c) => x.bulletListButtonKeyDown(c.event as KeyboardEvent)} > - Bullet List + ${x => richTextEditorToggleBulletListLabel.getValueFor(x)} <${iconListTag} slot="start"> <${toggleButtonTag} @@ -59,12 +60,12 @@ export const template = html` appearance="ghost" content-hidden slot="start" - title="Numbered List" + title=${x => richTextEditorToggleNumberedListLabel.getValueFor(x)} @click=${x => x.numberedListButtonClick()} @change=${(x, c) => x.stopEventPropagation(c.event)} @keydown=${(x, c) => x.numberedListButtonKeyDown(c.event as KeyboardEvent)} > - Numbered List + ${x => richTextEditorToggleNumberedListLabel.getValueFor(x)} <${iconNumberListTag} slot="start"> diff --git a/packages/nimble-components/src/rich-text-editor/testing/rich-text-editor.pageobject.ts b/packages/nimble-components/src/rich-text-editor/testing/rich-text-editor.pageobject.ts index 2ad02b8ee3..38050ed6b4 100644 --- a/packages/nimble-components/src/rich-text-editor/testing/rich-text-editor.pageobject.ts +++ b/packages/nimble-components/src/rich-text-editor/testing/rich-text-editor.pageobject.ts @@ -156,6 +156,15 @@ export class RichTextEditorPageObject { .map(el => el.textContent || ''); } + public getFormattingButton( + index: ToolbarButton + ): ToggleButton | null | undefined { + const buttons: NodeListOf = this.richTextEditorElement.shadowRoot!.querySelectorAll( + 'nimble-toggle-button' + ); + return buttons[index]; + } + private getEditorSection(): Element | null | undefined { return this.richTextEditorElement.shadowRoot?.querySelector('.editor'); } @@ -165,13 +174,4 @@ export class RichTextEditorPageObject { '.ProseMirror' ); } - - private getFormattingButton( - index: ToolbarButton - ): ToggleButton | null | undefined { - const buttons: NodeListOf = this.richTextEditorElement.shadowRoot!.querySelectorAll( - 'nimble-toggle-button' - ); - return buttons[index]; - } } diff --git a/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor-labels.spec.ts b/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor-labels.spec.ts new file mode 100644 index 0000000000..2d3962b4c0 --- /dev/null +++ b/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor-labels.spec.ts @@ -0,0 +1,72 @@ +import { html } from '@microsoft/fast-element'; +import { richTextEditorTag, type RichTextEditor } from '..'; +import { type Fixture, fixture } from '../../utilities/tests/fixture'; +import { themeProviderTag, type ThemeProvider } from '../../theme-provider'; +import { + LabelProviderRichTextEditor, + labelProviderRichTextEditorTag +} from '../../label-provider/rich-text-editor'; +import { RichTextEditorPageObject } from '../testing/rich-text-editor.pageobject'; +import { ToolbarButton } from '../testing/types'; + +async function setup(): Promise> { + return fixture( + html` + <${themeProviderTag}> + <${labelProviderRichTextEditorTag}> + <${richTextEditorTag}> + <${themeProviderTag}>` + ); +} + +describe('Rich Text Editor with LabelProviderRichTextEditor', () => { + let element: RichTextEditor; + let labelProvider: LabelProviderRichTextEditor; + let connect: () => Promise; + let disconnect: () => Promise; + let pageObject: RichTextEditorPageObject; + + beforeEach(async () => { + let themeProvider: ThemeProvider; + ({ element: themeProvider, connect, disconnect } = await setup()); + element = themeProvider.querySelector(richTextEditorTag)!; + labelProvider = themeProvider.querySelector(labelProviderRichTextEditorTag)!; + pageObject = new RichTextEditorPageObject(element); + }); + + afterEach(async () => { + await disconnect(); + }); + + it('uses correct labels for bold button', async () => { + await connect(); + labelProvider.toggleBold = 'Bold'; + const boldButton = pageObject.getFormattingButton(ToolbarButton.bold); + expect(boldButton!.textContent!.trim()).toBe('Bold'); + expect(boldButton!.title).toBe('Bold'); + }); + + it('uses correct labels for Italics button', async () => { + await connect(); + labelProvider.toggleItalics = 'Italics'; + const italicButton = pageObject.getFormattingButton(ToolbarButton.italics); + expect(italicButton!.textContent!.trim()).toBe('Italics'); + expect(italicButton!.title).toBe('Italics'); + }); + + it('uses correct labels for bullet list button', async () => { + await connect(); + labelProvider.toggleBulletList = 'Bullet List'; + const bulletListButton = pageObject.getFormattingButton(ToolbarButton.bulletList); + expect(bulletListButton!.textContent!.trim()).toBe('Bullet List'); + expect(bulletListButton!.title).toBe('Bullet List'); + }); + + it('uses correct labels for numbered list button', async () => { + await connect(); + labelProvider.toggleNumberedList = 'Numbered List'; + const numberedListButton = pageObject.getFormattingButton(ToolbarButton.numberedList); + expect(numberedListButton!.textContent!.trim()).toBe('Numbered List'); + expect(numberedListButton!.title).toBe('Numbered List'); + }); +}); \ No newline at end of file diff --git a/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor.stories.ts b/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor.stories.ts index ff2adc95cf..8c36addde8 100644 --- a/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor.stories.ts +++ b/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor.stories.ts @@ -6,9 +6,11 @@ import { } from '../../utilities/tests/storybook'; import { RichTextEditor, richTextEditorTag } from '..'; import { buttonTag } from '../../button'; +import { addLabelUseMetadata, type LabelUserArgs } from '../../label-provider/base/tests/label-user-stories-utils'; +import { labelProviderRichTextEditorTag } from '../../label-provider/rich-text-editor'; // eslint-disable-next-line @typescript-eslint/no-empty-interface -interface RichTextEditorArgs { +interface RichTextEditorArgs extends LabelUserArgs { data: ExampleDataType; footerActionButtons: boolean; getMarkdown: undefined; @@ -120,6 +122,8 @@ const metadata: Meta = { } }; +addLabelUseMetadata(metadata, labelProviderRichTextEditorTag); + export default metadata; export const richTextEditor: StoryObj = {}; From c741e17e17890ea29eb57f3b746b55aacb03f3ab Mon Sep 17 00:00:00 2001 From: Aagash Raaj Date: Mon, 28 Aug 2023 18:26:02 +0530 Subject: [PATCH 02/19] Fix lint --- .../label-provider/rich-text-editor/index.ts | 6 ++++-- .../rich-text-editor/label-token-defaults.ts | 6 ++++-- .../rich-text-editor/label-tokens.ts | 12 ++++++++---- .../rich-text-editor/name-utils.ts | 4 +++- .../label-provider-rich-text-editor.spec.ts | 5 ++++- .../src/rich-text-editor/template.ts | 7 ++++++- .../tests/rich-text-editor-labels.spec.ts | 18 +++++++++++++----- .../tests/rich-text-editor.stories.ts | 5 ++++- 8 files changed, 46 insertions(+), 17 deletions(-) diff --git a/packages/nimble-components/src/label-provider/rich-text-editor/index.ts b/packages/nimble-components/src/label-provider/rich-text-editor/index.ts index 8c29be5cba..11f349a5f0 100644 --- a/packages/nimble-components/src/label-provider/rich-text-editor/index.ts +++ b/packages/nimble-components/src/label-provider/rich-text-editor/index.ts @@ -18,7 +18,7 @@ const supportedLabels = { toggleBold: richTextEditorToggleBoldLabel, toggleItalics: richTextEditorToggleItalicsLabel, toggleBulletList: richTextEditorToggleBulletListLabel, - toggleNumberedList: richTextEditorToggleNumberedListLabel, + toggleNumberedList: richTextEditorToggleNumberedListLabel } as const; /** @@ -49,4 +49,6 @@ const nimbleLabelProviderRichTextEditor = LabelProviderRichTextEditor.compose({ DesignSystem.getOrCreate() .withPrefix('nimble') .register(nimbleLabelProviderRichTextEditor()); -export const labelProviderRichTextEditorTag = DesignSystem.tagFor(LabelProviderRichTextEditor); +export const labelProviderRichTextEditorTag = DesignSystem.tagFor( + LabelProviderRichTextEditor +); diff --git a/packages/nimble-components/src/label-provider/rich-text-editor/label-token-defaults.ts b/packages/nimble-components/src/label-provider/rich-text-editor/label-token-defaults.ts index 15db6967bb..42dbe410e9 100644 --- a/packages/nimble-components/src/label-provider/rich-text-editor/label-token-defaults.ts +++ b/packages/nimble-components/src/label-provider/rich-text-editor/label-token-defaults.ts @@ -2,9 +2,11 @@ import type * as TokensNamespace from './label-tokens'; type TokenName = keyof typeof TokensNamespace; -export const richTextEditorLabelDefaults: { readonly [key in TokenName]: string } = { +export const richTextEditorLabelDefaults: { + readonly [key in TokenName]: string; +} = { richTextEditorToggleBoldLabel: 'Bold', richTextEditorToggleItalicsLabel: 'Italics', richTextEditorToggleBulletListLabel: 'Bullet List', - richTextEditorToggleNumberedListLabel: 'Numbered List', + richTextEditorToggleNumberedListLabel: 'Numbered List' }; diff --git a/packages/nimble-components/src/label-provider/rich-text-editor/label-tokens.ts b/packages/nimble-components/src/label-provider/rich-text-editor/label-tokens.ts index 2327dd1569..d013f8ed8f 100644 --- a/packages/nimble-components/src/label-provider/rich-text-editor/label-tokens.ts +++ b/packages/nimble-components/src/label-provider/rich-text-editor/label-tokens.ts @@ -16,7 +16,11 @@ export const richTextEditorToggleBulletListLabel = DesignToken.create({ cssCustomPropertyName: null }).withDefault(richTextEditorLabelDefaults.richTextEditorToggleBulletListLabel); -export const richTextEditorToggleNumberedListLabel = DesignToken.create({ - name: 'rich-text-editor-toggle-numbered-list-label', - cssCustomPropertyName: null -}).withDefault(richTextEditorLabelDefaults.richTextEditorToggleNumberedListLabel); +export const richTextEditorToggleNumberedListLabel = DesignToken.create( + { + name: 'rich-text-editor-toggle-numbered-list-label', + cssCustomPropertyName: null + } +).withDefault( + richTextEditorLabelDefaults.richTextEditorToggleNumberedListLabel +); diff --git a/packages/nimble-components/src/label-provider/rich-text-editor/name-utils.ts b/packages/nimble-components/src/label-provider/rich-text-editor/name-utils.ts index 234e31b151..7ff6a8b4d9 100644 --- a/packages/nimble-components/src/label-provider/rich-text-editor/name-utils.ts +++ b/packages/nimble-components/src/label-provider/rich-text-editor/name-utils.ts @@ -3,7 +3,9 @@ * (The design token name has the richTextEditor prefix, but the properties on the LabelProviderRichTextEditor do not, as they're already * scoped to the rich-text-editor only) */ -export function removeRichTextEditorPrefixAndCamelCase(jsTokenName: string): string { +export function removeRichTextEditorPrefixAndCamelCase( + jsTokenName: string +): string { // Example: 'richTextEditorToggleBulletListLabel' => 'toggleBulletListLabel' return jsTokenName.replace( /^richTextEditor(\w)(\w+)/, diff --git a/packages/nimble-components/src/label-provider/rich-text-editor/tests/label-provider-rich-text-editor.spec.ts b/packages/nimble-components/src/label-provider/rich-text-editor/tests/label-provider-rich-text-editor.spec.ts index 65426273ae..9a618e8462 100644 --- a/packages/nimble-components/src/label-provider/rich-text-editor/tests/label-provider-rich-text-editor.spec.ts +++ b/packages/nimble-components/src/label-provider/rich-text-editor/tests/label-provider-rich-text-editor.spec.ts @@ -1,7 +1,10 @@ import { spinalCase } from '@microsoft/fast-web-utilities'; import { html } from '@microsoft/fast-element'; import * as labelTokensNamespace from '../label-tokens'; -import { LabelProviderRichTextEditor, labelProviderRichTextEditorTag } from '..'; +import { + LabelProviderRichTextEditor, + labelProviderRichTextEditorTag +} from '..'; import { getSpecTypeByNamedList } from '../../../utilities/tests/parameterized'; import { getAttributeName, diff --git a/packages/nimble-components/src/rich-text-editor/template.ts b/packages/nimble-components/src/rich-text-editor/template.ts index 3ef3852f82..5cc01a789b 100644 --- a/packages/nimble-components/src/rich-text-editor/template.ts +++ b/packages/nimble-components/src/rich-text-editor/template.ts @@ -6,7 +6,12 @@ import { iconBoldBTag } from '../icons/bold-b'; import { iconItalicITag } from '../icons/italic-i'; import { iconListTag } from '../icons/list'; import { iconNumberListTag } from '../icons/number-list'; -import { richTextEditorToggleBoldLabel, richTextEditorToggleItalicsLabel, richTextEditorToggleBulletListLabel, richTextEditorToggleNumberedListLabel } from '../label-provider/rich-text-editor/label-tokens'; +import { + richTextEditorToggleBoldLabel, + richTextEditorToggleItalicsLabel, + richTextEditorToggleBulletListLabel, + richTextEditorToggleNumberedListLabel +} from '../label-provider/rich-text-editor/label-tokens'; // prettier-ignore export const template = html` diff --git a/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor-labels.spec.ts b/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor-labels.spec.ts index 2d3962b4c0..8d835f86ad 100644 --- a/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor-labels.spec.ts +++ b/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor-labels.spec.ts @@ -30,7 +30,9 @@ describe('Rich Text Editor with LabelProviderRichTextEditor', () => { let themeProvider: ThemeProvider; ({ element: themeProvider, connect, disconnect } = await setup()); element = themeProvider.querySelector(richTextEditorTag)!; - labelProvider = themeProvider.querySelector(labelProviderRichTextEditorTag)!; + labelProvider = themeProvider.querySelector( + labelProviderRichTextEditorTag + )!; pageObject = new RichTextEditorPageObject(element); }); @@ -49,7 +51,9 @@ describe('Rich Text Editor with LabelProviderRichTextEditor', () => { it('uses correct labels for Italics button', async () => { await connect(); labelProvider.toggleItalics = 'Italics'; - const italicButton = pageObject.getFormattingButton(ToolbarButton.italics); + const italicButton = pageObject.getFormattingButton( + ToolbarButton.italics + ); expect(italicButton!.textContent!.trim()).toBe('Italics'); expect(italicButton!.title).toBe('Italics'); }); @@ -57,7 +61,9 @@ describe('Rich Text Editor with LabelProviderRichTextEditor', () => { it('uses correct labels for bullet list button', async () => { await connect(); labelProvider.toggleBulletList = 'Bullet List'; - const bulletListButton = pageObject.getFormattingButton(ToolbarButton.bulletList); + const bulletListButton = pageObject.getFormattingButton( + ToolbarButton.bulletList + ); expect(bulletListButton!.textContent!.trim()).toBe('Bullet List'); expect(bulletListButton!.title).toBe('Bullet List'); }); @@ -65,8 +71,10 @@ describe('Rich Text Editor with LabelProviderRichTextEditor', () => { it('uses correct labels for numbered list button', async () => { await connect(); labelProvider.toggleNumberedList = 'Numbered List'; - const numberedListButton = pageObject.getFormattingButton(ToolbarButton.numberedList); + const numberedListButton = pageObject.getFormattingButton( + ToolbarButton.numberedList + ); expect(numberedListButton!.textContent!.trim()).toBe('Numbered List'); expect(numberedListButton!.title).toBe('Numbered List'); }); -}); \ No newline at end of file +}); diff --git a/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor.stories.ts b/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor.stories.ts index 8c36addde8..7cafa89e44 100644 --- a/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor.stories.ts +++ b/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor.stories.ts @@ -6,7 +6,10 @@ import { } from '../../utilities/tests/storybook'; import { RichTextEditor, richTextEditorTag } from '..'; import { buttonTag } from '../../button'; -import { addLabelUseMetadata, type LabelUserArgs } from '../../label-provider/base/tests/label-user-stories-utils'; +import { + addLabelUseMetadata, + type LabelUserArgs +} from '../../label-provider/base/tests/label-user-stories-utils'; import { labelProviderRichTextEditorTag } from '../../label-provider/rich-text-editor'; // eslint-disable-next-line @typescript-eslint/no-empty-interface From a81799ead936ed77d66c239bc14a446c5d08b38f Mon Sep 17 00:00:00 2001 From: Aagash Raaj <123377167+aagash-ni@users.noreply.github.com> Date: Mon, 28 Aug 2023 19:13:14 +0530 Subject: [PATCH 03/19] Change files --- ...le-components-68c4b395-98d1-4e9b-bda3-ba58ff53d17c.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 change/@ni-nimble-components-68c4b395-98d1-4e9b-bda3-ba58ff53d17c.json diff --git a/change/@ni-nimble-components-68c4b395-98d1-4e9b-bda3-ba58ff53d17c.json b/change/@ni-nimble-components-68c4b395-98d1-4e9b-bda3-ba58ff53d17c.json new file mode 100644 index 0000000000..614f055950 --- /dev/null +++ b/change/@ni-nimble-components-68c4b395-98d1-4e9b-bda3-ba58ff53d17c.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "Add label provider for rich-text-editor", + "packageName": "@ni/nimble-components", + "email": "123377167+aagash-ni@users.noreply.github.com", + "dependentChangeType": "patch" +} From 6c05da245c7d9bccb230aa7920c77a0f07e62073 Mon Sep 17 00:00:00 2001 From: Aagash Raaj <123377167+aagash-ni@users.noreply.github.com> Date: Tue, 29 Aug 2023 15:51:54 +0530 Subject: [PATCH 04/19] Update testcase with getSpecTypeByNamedList --- .../tests/rich-text-editor-labels.spec.ts | 89 +++++++++++-------- 1 file changed, 53 insertions(+), 36 deletions(-) diff --git a/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor-labels.spec.ts b/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor-labels.spec.ts index 8d835f86ad..70c29e9a2e 100644 --- a/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor-labels.spec.ts +++ b/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor-labels.spec.ts @@ -8,6 +8,10 @@ import { } from '../../label-provider/rich-text-editor'; import { RichTextEditorPageObject } from '../testing/rich-text-editor.pageobject'; import { ToolbarButton } from '../testing/types'; +import { getSpecTypeByNamedList } from '../../utilities/tests/parameterized'; +import { waitForUpdatesAsync } from '../../testing/async-helpers'; + +type LabelProvider = 'toggleBold' | 'toggleItalics' | 'toggleBulletList' | 'toggleNumberedList'; async function setup(): Promise> { return fixture( @@ -19,16 +23,51 @@ async function setup(): Promise> { ); } +const formattingButtons: { + name: string, + property: LabelProvider, + label: string, + toolbarButtonIndex: ToolbarButton +}[] = [ + { + name: 'Bold', + property: 'toggleBold', + label: 'Customized Bold Label', + toolbarButtonIndex: ToolbarButton.bold, + }, + { + name: 'Italics', + property: 'toggleItalics', + label: 'Customized Italics Label', + toolbarButtonIndex: ToolbarButton.italics, + }, + { + name: 'BulletList', + property: 'toggleBulletList', + label: 'Customized Bullet List Label', + toolbarButtonIndex: ToolbarButton.bulletList, + }, + { + name: 'NumberedList', + property: 'toggleNumberedList', + label: 'Customized Numbered List Label', + toolbarButtonIndex: ToolbarButton.numberedList, + } +]; + describe('Rich Text Editor with LabelProviderRichTextEditor', () => { let element: RichTextEditor; let labelProvider: LabelProviderRichTextEditor; let connect: () => Promise; let disconnect: () => Promise; let pageObject: RichTextEditorPageObject; + const focused: string[] = []; + const disabled: string[] = []; beforeEach(async () => { let themeProvider: ThemeProvider; ({ element: themeProvider, connect, disconnect } = await setup()); + await connect(); element = themeProvider.querySelector(richTextEditorTag)!; labelProvider = themeProvider.querySelector( labelProviderRichTextEditorTag @@ -40,41 +79,19 @@ describe('Rich Text Editor with LabelProviderRichTextEditor', () => { await disconnect(); }); - it('uses correct labels for bold button', async () => { - await connect(); - labelProvider.toggleBold = 'Bold'; - const boldButton = pageObject.getFormattingButton(ToolbarButton.bold); - expect(boldButton!.textContent!.trim()).toBe('Bold'); - expect(boldButton!.title).toBe('Bold'); - }); - - it('uses correct labels for Italics button', async () => { - await connect(); - labelProvider.toggleItalics = 'Italics'; - const italicButton = pageObject.getFormattingButton( - ToolbarButton.italics - ); - expect(italicButton!.textContent!.trim()).toBe('Italics'); - expect(italicButton!.title).toBe('Italics'); - }); - - it('uses correct labels for bullet list button', async () => { - await connect(); - labelProvider.toggleBulletList = 'Bullet List'; - const bulletListButton = pageObject.getFormattingButton( - ToolbarButton.bulletList - ); - expect(bulletListButton!.textContent!.trim()).toBe('Bullet List'); - expect(bulletListButton!.title).toBe('Bullet List'); - }); - - it('uses correct labels for numbered list button', async () => { - await connect(); - labelProvider.toggleNumberedList = 'Numbered List'; - const numberedListButton = pageObject.getFormattingButton( - ToolbarButton.numberedList + for (const value of formattingButtons) { + const specType = getSpecTypeByNamedList(value, focused, disabled); + // eslint-disable-next-line @typescript-eslint/no-loop-func + specType( + `uses correct labels '${value.label}' for ${value.name} button`, + // eslint-disable-next-line @typescript-eslint/no-loop-func + async () => { + labelProvider[value.property] = value.label; + await waitForUpdatesAsync(); + const formatButton = pageObject.getFormattingButton(value.toolbarButtonIndex); + expect(formatButton!.textContent!.trim()).toBe(value.label); + expect(formatButton!.title).toBe(value.label); + } ); - expect(numberedListButton!.textContent!.trim()).toBe('Numbered List'); - expect(numberedListButton!.title).toBe('Numbered List'); - }); + } }); From 3a7e724bea1cc0265bb14859af5b26f72b74688e Mon Sep 17 00:00:00 2001 From: Aagash Raaj <123377167+aagash-ni@users.noreply.github.com> Date: Tue, 29 Aug 2023 15:54:59 +0530 Subject: [PATCH 05/19] Fix Lint --- .../tests/rich-text-editor-labels.spec.ts | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor-labels.spec.ts b/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor-labels.spec.ts index 70c29e9a2e..0b85a00cdf 100644 --- a/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor-labels.spec.ts +++ b/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor-labels.spec.ts @@ -11,7 +11,11 @@ import { ToolbarButton } from '../testing/types'; import { getSpecTypeByNamedList } from '../../utilities/tests/parameterized'; import { waitForUpdatesAsync } from '../../testing/async-helpers'; -type LabelProvider = 'toggleBold' | 'toggleItalics' | 'toggleBulletList' | 'toggleNumberedList'; +type LabelProvider = + | 'toggleBold' + | 'toggleItalics' + | 'toggleBulletList' + | 'toggleNumberedList'; async function setup(): Promise> { return fixture( @@ -33,25 +37,25 @@ const formattingButtons: { name: 'Bold', property: 'toggleBold', label: 'Customized Bold Label', - toolbarButtonIndex: ToolbarButton.bold, + toolbarButtonIndex: ToolbarButton.bold }, { name: 'Italics', property: 'toggleItalics', label: 'Customized Italics Label', - toolbarButtonIndex: ToolbarButton.italics, + toolbarButtonIndex: ToolbarButton.italics }, { name: 'BulletList', property: 'toggleBulletList', label: 'Customized Bullet List Label', - toolbarButtonIndex: ToolbarButton.bulletList, + toolbarButtonIndex: ToolbarButton.bulletList }, { name: 'NumberedList', property: 'toggleNumberedList', label: 'Customized Numbered List Label', - toolbarButtonIndex: ToolbarButton.numberedList, + toolbarButtonIndex: ToolbarButton.numberedList } ]; @@ -88,7 +92,9 @@ describe('Rich Text Editor with LabelProviderRichTextEditor', () => { async () => { labelProvider[value.property] = value.label; await waitForUpdatesAsync(); - const formatButton = pageObject.getFormattingButton(value.toolbarButtonIndex); + const formatButton = pageObject.getFormattingButton( + value.toolbarButtonIndex + ); expect(formatButton!.textContent!.trim()).toBe(value.label); expect(formatButton!.title).toBe(value.label); } From 395a5aa19ab72d63699b44753c4c65ec41f4237e Mon Sep 17 00:00:00 2001 From: Aagash Raaj <123377167+aagash-ni@users.noreply.github.com> Date: Tue, 29 Aug 2023 15:56:02 +0530 Subject: [PATCH 06/19] Minor fix --- .../src/rich-text-editor/tests/rich-text-editor-labels.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor-labels.spec.ts b/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor-labels.spec.ts index 0b85a00cdf..f6f0a908da 100644 --- a/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor-labels.spec.ts +++ b/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor-labels.spec.ts @@ -87,7 +87,7 @@ describe('Rich Text Editor with LabelProviderRichTextEditor', () => { const specType = getSpecTypeByNamedList(value, focused, disabled); // eslint-disable-next-line @typescript-eslint/no-loop-func specType( - `uses correct labels '${value.label}' for ${value.name} button`, + `uses correct label '${value.label}' for ${value.name} button`, // eslint-disable-next-line @typescript-eslint/no-loop-func async () => { labelProvider[value.property] = value.label; From eafefaad24c89f0a1a1284b9e3198c22221d6a29 Mon Sep 17 00:00:00 2001 From: Aagash Raaj <123377167+aagash-ni@users.noreply.github.com> Date: Tue, 29 Aug 2023 16:55:42 +0530 Subject: [PATCH 07/19] Address PR comments --- .../src/label-provider/base/tests/label-providers.mdx | 9 ++++++++- .../src/rich-text-editor/testing/types.ts | 2 ++ .../tests/rich-text-editor-labels.spec.ts | 8 +------- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/packages/nimble-components/src/label-provider/base/tests/label-providers.mdx b/packages/nimble-components/src/label-provider/base/tests/label-providers.mdx index 5ff9a04358..d002a4eef9 100644 --- a/packages/nimble-components/src/label-provider/base/tests/label-providers.mdx +++ b/packages/nimble-components/src/label-provider/base/tests/label-providers.mdx @@ -1,6 +1,7 @@ import { Canvas, Meta, Title } from '@storybook/blocks'; import { coreLabelProvider } from '../../core/tests/label-provider-core.stories'; import { tableLabelProvider } from '../../table/tests/label-provider-table.stories'; +import { richTextEditorLabelProvider } from '../../rich-text-editor/tests/label-provider-rich-text-editor.stories' Label Providers @@ -20,7 +21,7 @@ See the [Localization section of the nimble-blazor readme](https://github.com/ni ## Core Label Provider -Provides labels for all Nimble components besides the table component. +Provides labels for all Nimble components besides the table and the rich text editor component. @@ -29,3 +30,9 @@ Provides labels for all Nimble components besides the table component. Provides labels for the `nimble-table` and all associated table sub-components / column types. + +## Rich Text Editor Label Provider + +Provides labels for the `nimble-rich-text-editor`. + + diff --git a/packages/nimble-components/src/rich-text-editor/testing/types.ts b/packages/nimble-components/src/rich-text-editor/testing/types.ts index 4060a4ed4b..00c2826b79 100644 --- a/packages/nimble-components/src/rich-text-editor/testing/types.ts +++ b/packages/nimble-components/src/rich-text-editor/testing/types.ts @@ -5,3 +5,5 @@ export const ToolbarButton = { numberedList: 3 } as const; export type ToolbarButton = (typeof ToolbarButton)[keyof typeof ToolbarButton]; + +export type LabelProvider = 'toggleBold' | 'toggleItalics' | 'toggleBulletList' | 'toggleNumberedList'; diff --git a/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor-labels.spec.ts b/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor-labels.spec.ts index f6f0a908da..09e786f2bd 100644 --- a/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor-labels.spec.ts +++ b/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor-labels.spec.ts @@ -7,16 +7,10 @@ import { labelProviderRichTextEditorTag } from '../../label-provider/rich-text-editor'; import { RichTextEditorPageObject } from '../testing/rich-text-editor.pageobject'; -import { ToolbarButton } from '../testing/types'; +import { LabelProvider, ToolbarButton } from '../testing/types'; import { getSpecTypeByNamedList } from '../../utilities/tests/parameterized'; import { waitForUpdatesAsync } from '../../testing/async-helpers'; -type LabelProvider = - | 'toggleBold' - | 'toggleItalics' - | 'toggleBulletList' - | 'toggleNumberedList'; - async function setup(): Promise> { return fixture( html` From dee5c597f31d74e4f87ef813cc0bf285d79de3bd Mon Sep 17 00:00:00 2001 From: Aagash Raaj <123377167+aagash-ni@users.noreply.github.com> Date: Tue, 29 Aug 2023 17:11:30 +0530 Subject: [PATCH 08/19] Fix lint --- .../src/label-provider/base/tests/label-providers.mdx | 2 +- .../nimble-components/src/rich-text-editor/testing/types.ts | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/nimble-components/src/label-provider/base/tests/label-providers.mdx b/packages/nimble-components/src/label-provider/base/tests/label-providers.mdx index d002a4eef9..1421139a45 100644 --- a/packages/nimble-components/src/label-provider/base/tests/label-providers.mdx +++ b/packages/nimble-components/src/label-provider/base/tests/label-providers.mdx @@ -1,7 +1,7 @@ import { Canvas, Meta, Title } from '@storybook/blocks'; import { coreLabelProvider } from '../../core/tests/label-provider-core.stories'; import { tableLabelProvider } from '../../table/tests/label-provider-table.stories'; -import { richTextEditorLabelProvider } from '../../rich-text-editor/tests/label-provider-rich-text-editor.stories' +import { richTextEditorLabelProvider } from '../../rich-text-editor/tests/label-provider-rich-text-editor.stories'; Label Providers diff --git a/packages/nimble-components/src/rich-text-editor/testing/types.ts b/packages/nimble-components/src/rich-text-editor/testing/types.ts index 00c2826b79..42e3846653 100644 --- a/packages/nimble-components/src/rich-text-editor/testing/types.ts +++ b/packages/nimble-components/src/rich-text-editor/testing/types.ts @@ -6,4 +6,8 @@ export const ToolbarButton = { } as const; export type ToolbarButton = (typeof ToolbarButton)[keyof typeof ToolbarButton]; -export type LabelProvider = 'toggleBold' | 'toggleItalics' | 'toggleBulletList' | 'toggleNumberedList'; +export type LabelProvider = + | 'toggleBold' + | 'toggleItalics' + | 'toggleBulletList' + | 'toggleNumberedList'; From 31afcf40d43efbbc25acf11a7a1dd8f0ec67778b Mon Sep 17 00:00:00 2001 From: Aagash Raaj <123377167+aagash-ni@users.noreply.github.com> Date: Wed, 30 Aug 2023 23:36:34 +0530 Subject: [PATCH 09/19] Address PR Comments --- .../label-provider/base/tests/label-providers.mdx | 12 ++++++------ .../tests/rich-text-editor-labels.spec.ts | 1 - 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/nimble-components/src/label-provider/base/tests/label-providers.mdx b/packages/nimble-components/src/label-provider/base/tests/label-providers.mdx index 1421139a45..454d810576 100644 --- a/packages/nimble-components/src/label-provider/base/tests/label-providers.mdx +++ b/packages/nimble-components/src/label-provider/base/tests/label-providers.mdx @@ -25,14 +25,14 @@ Provides labels for all Nimble components besides the table and the rich text ed -## Table Label Provider - -Provides labels for the `nimble-table` and all associated table sub-components / column types. - - - ## Rich Text Editor Label Provider Provides labels for the `nimble-rich-text-editor`. + +## Table Label Provider + +Provides labels for the `nimble-table` and all associated table sub-components / column types. + + diff --git a/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor-labels.spec.ts b/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor-labels.spec.ts index 09e786f2bd..c516f86baa 100644 --- a/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor-labels.spec.ts +++ b/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor-labels.spec.ts @@ -79,7 +79,6 @@ describe('Rich Text Editor with LabelProviderRichTextEditor', () => { for (const value of formattingButtons) { const specType = getSpecTypeByNamedList(value, focused, disabled); - // eslint-disable-next-line @typescript-eslint/no-loop-func specType( `uses correct label '${value.label}' for ${value.name} button`, // eslint-disable-next-line @typescript-eslint/no-loop-func From 3a5c86c35e34a8faf22632a1f04cd57f76bf73f4 Mon Sep 17 00:00:00 2001 From: Aagash Raaj <123377167+aagash-ni@users.noreply.github.com> Date: Thu, 31 Aug 2023 17:30:43 +0530 Subject: [PATCH 10/19] Address PR Comments --- packages/nimble-components/CONTRIBUTING.md | 6 +-- packages/nimble-components/README.md | 5 +- .../base/tests/label-name-utils.ts | 12 +++++ .../tests/label-provider-stories-utils.ts | 13 +++-- .../base/tests/label-providers.mdx | 10 ++-- .../label-provider/rich-text-editor/index.ts | 54 ------------------- .../rich-text-editor/label-token-defaults.ts | 12 ----- .../rich-text-editor/label-tokens.ts | 26 --------- .../rich-text-editor/name-utils.ts | 14 ----- .../src/label-provider/rich-text/index.ts | 54 +++++++++++++++++++ .../rich-text/label-token-defaults.ts | 12 +++++ .../label-provider/rich-text/label-tokens.ts | 26 +++++++++ .../tests/label-provider-rich-text.spec.ts} | 34 ++++++------ .../label-provider-rich-text.stories.ts} | 11 ++-- .../src/label-provider/table/name-utils.ts | 12 ----- .../table/tests/label-provider-table.spec.ts | 14 ++--- .../tests/label-provider-table.stories.ts | 5 +- .../src/rich-text-editor/template.ts | 26 ++++----- .../testing/rich-text-editor.pageobject.ts | 20 +++++-- .../src/rich-text-editor/testing/types.ts | 2 +- .../tests/rich-text-editor-labels.spec.ts | 35 ++++++------ .../tests/rich-text-editor.stories.ts | 4 +- 22 files changed, 208 insertions(+), 199 deletions(-) delete mode 100644 packages/nimble-components/src/label-provider/rich-text-editor/index.ts delete mode 100644 packages/nimble-components/src/label-provider/rich-text-editor/label-token-defaults.ts delete mode 100644 packages/nimble-components/src/label-provider/rich-text-editor/label-tokens.ts delete mode 100644 packages/nimble-components/src/label-provider/rich-text-editor/name-utils.ts create mode 100644 packages/nimble-components/src/label-provider/rich-text/index.ts create mode 100644 packages/nimble-components/src/label-provider/rich-text/label-token-defaults.ts create mode 100644 packages/nimble-components/src/label-provider/rich-text/label-tokens.ts rename packages/nimble-components/src/label-provider/{rich-text-editor/tests/label-provider-rich-text-editor.spec.ts => rich-text/tests/label-provider-rich-text.spec.ts} (86%) rename packages/nimble-components/src/label-provider/{rich-text-editor/tests/label-provider-rich-text-editor.stories.ts => rich-text/tests/label-provider-rich-text.stories.ts} (55%) delete mode 100644 packages/nimble-components/src/label-provider/table/name-utils.ts diff --git a/packages/nimble-components/CONTRIBUTING.md b/packages/nimble-components/CONTRIBUTING.md index 71aee951ba..75b242b113 100644 --- a/packages/nimble-components/CONTRIBUTING.md +++ b/packages/nimble-components/CONTRIBUTING.md @@ -445,11 +445,11 @@ When creating a new component, create a `*-matrix.stories.ts` Storybook file to Most user-visible strings displayed by Nimble components are provided by the client application and are expected to be localized by the application if necessary. However, some strings are built into Nimble components and are provided only in English. An application can provide localized versions of these strings by using design tokens set on label provider elements. -There are currently 3 label providers: +The current label providers: -- `nimble-label-provider-core`: Used for labels for all components besides the table +- `nimble-label-provider-core`: Used for labels for all components without a dedicated label provider +- `nimble-label-provider-rich-text`: Used for labels for the rich text components - `nimble-label-provider-table`: Used for labels for the table (and table sub-components / column types) -- `nimble-label-provider-rich-text-editor`: Used for labels for the rich text editor The expected format for label token names is: diff --git a/packages/nimble-components/README.md b/packages/nimble-components/README.md index 3529674cfa..867509e020 100644 --- a/packages/nimble-components/README.md +++ b/packages/nimble-components/README.md @@ -100,9 +100,10 @@ The goal of the Nimble design system is to provide a consistent style for applic Most user-visible strings displayed by Nimble components are provided by the client application and are expected to be localized by the application if necessary. However, some strings are built into Nimble components and are provided only in English. An application can provide localized versions of these strings by using design tokens set on label provider elements. -There are currently 2 label providers: +The current label providers: -- `nimble-label-provider-core`: Used for labels for all components besides the table +- `nimble-label-provider-core`: Used for labels for all components without a dedicated label provider +- `nimble-label-provider-rich-text`: Used for labels for the rich text components - `nimble-label-provider-table`: Used for labels for the table (and table sub-components / column types) If a client is localized, it should: diff --git a/packages/nimble-components/src/label-provider/base/tests/label-name-utils.ts b/packages/nimble-components/src/label-provider/base/tests/label-name-utils.ts index 420a6c35f0..0045dddc66 100644 --- a/packages/nimble-components/src/label-provider/base/tests/label-name-utils.ts +++ b/packages/nimble-components/src/label-provider/base/tests/label-name-utils.ts @@ -7,3 +7,15 @@ export function getPropertyName(jsKey: string): string { export function getAttributeName(jsKey: string): string { return spinalCase(getPropertyName(jsKey)); } + +/** + * Removes the prefix and camelCases the input token name. + * (The design token name has the element/types prefix, but the properties do not, as they're already + * scoped to the respective element) + */ +export function removePrefixAndCamelCase(jsTokenName: string, prefix: string): string { + return jsTokenName.replace( + new RegExp(`^${prefix}(\\w)(\\w+)`), + (_match: string, firstChar: string, restOfString: string) => `${firstChar.toLowerCase()}${restOfString}` + ); +} diff --git a/packages/nimble-components/src/label-provider/base/tests/label-provider-stories-utils.ts b/packages/nimble-components/src/label-provider/base/tests/label-provider-stories-utils.ts index 658f244ba9..96f904859b 100644 --- a/packages/nimble-components/src/label-provider/base/tests/label-provider-stories-utils.ts +++ b/packages/nimble-components/src/label-provider/base/tests/label-provider-stories-utils.ts @@ -11,7 +11,8 @@ export interface LabelProviderArgs { tableRef: Table; labelProviderTag: string; labelTokens: [string, DesignToken][]; - removeNamePrefix(tokenName: string): string; + prefixSubstring: string; + removeNamePrefix(tokenName: string, elementName?: string,): string; updateData(args: LabelProviderArgs): void; } @@ -89,11 +90,17 @@ export const labelProviderMetadata: Meta = { table: { disable: true } + }, + prefixSubstring: { + table: { + disable: true + } } }, args: { removeNamePrefix: jsTokenName => jsTokenName, tableRef: undefined, + prefixSubstring: undefined, updateData: x => { void (async () => { // Safari workaround: the table element instance is made at this point @@ -104,10 +111,10 @@ export const labelProviderMetadata: Meta = { return { tokenName: token[0], htmlAttributeName: getAttributeName( - x.removeNamePrefix(token[0]) + x.removeNamePrefix(token[0], x.prefixSubstring) ), jsPropertyName: getPropertyName( - x.removeNamePrefix(token[0]) + x.removeNamePrefix(token[0], x.prefixSubstring) ), defaultValue: token[1].getValueFor(document.body) }; diff --git a/packages/nimble-components/src/label-provider/base/tests/label-providers.mdx b/packages/nimble-components/src/label-provider/base/tests/label-providers.mdx index 454d810576..dd1a059003 100644 --- a/packages/nimble-components/src/label-provider/base/tests/label-providers.mdx +++ b/packages/nimble-components/src/label-provider/base/tests/label-providers.mdx @@ -1,7 +1,7 @@ import { Canvas, Meta, Title } from '@storybook/blocks'; import { coreLabelProvider } from '../../core/tests/label-provider-core.stories'; import { tableLabelProvider } from '../../table/tests/label-provider-table.stories'; -import { richTextEditorLabelProvider } from '../../rich-text-editor/tests/label-provider-rich-text-editor.stories'; +import { richTextLabelProvider } from '../../rich-text/tests/label-provider-rich-text.stories'; Label Providers @@ -21,15 +21,15 @@ See the [Localization section of the nimble-blazor readme](https://github.com/ni ## Core Label Provider -Provides labels for all Nimble components besides the table and the rich text editor component. +Provides labels for all Nimble components that do not have a dedicated label provider. -## Rich Text Editor Label Provider +## Rich Text Label Provider -Provides labels for the `nimble-rich-text-editor`. +Provides labels for the the rich text components. - + ## Table Label Provider diff --git a/packages/nimble-components/src/label-provider/rich-text-editor/index.ts b/packages/nimble-components/src/label-provider/rich-text-editor/index.ts deleted file mode 100644 index 11f349a5f0..0000000000 --- a/packages/nimble-components/src/label-provider/rich-text-editor/index.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { attr } from '@microsoft/fast-element'; -import { DesignSystem } from '@microsoft/fast-foundation'; -import { DesignTokensFor, LabelProviderBase } from '../base'; -import { - richTextEditorToggleBoldLabel, - richTextEditorToggleItalicsLabel, - richTextEditorToggleBulletListLabel, - richTextEditorToggleNumberedListLabel -} from './label-tokens'; - -declare global { - interface HTMLElementTagNameMap { - 'nimble-label-provider-rich-text-editor': LabelProviderRichTextEditor; - } -} - -const supportedLabels = { - toggleBold: richTextEditorToggleBoldLabel, - toggleItalics: richTextEditorToggleItalicsLabel, - toggleBulletList: richTextEditorToggleBulletListLabel, - toggleNumberedList: richTextEditorToggleNumberedListLabel -} as const; - -/** - * Label provider for the Nimble rich text editor - */ -export class LabelProviderRichTextEditor - extends LabelProviderBase - implements DesignTokensFor { - @attr({ attribute: 'toggle-bold' }) - public toggleBold: string | undefined; - - @attr({ attribute: 'toggle-italics' }) - public toggleItalics: string | undefined; - - @attr({ attribute: 'toggle-bullet-list' }) - public toggleBulletList: string | undefined; - - @attr({ attribute: 'toggle-numbered-list' }) - public toggleNumberedList: string | undefined; - - protected override readonly supportedLabels = supportedLabels; -} - -const nimbleLabelProviderRichTextEditor = LabelProviderRichTextEditor.compose({ - baseName: 'label-provider-rich-text-editor' -}); - -DesignSystem.getOrCreate() - .withPrefix('nimble') - .register(nimbleLabelProviderRichTextEditor()); -export const labelProviderRichTextEditorTag = DesignSystem.tagFor( - LabelProviderRichTextEditor -); diff --git a/packages/nimble-components/src/label-provider/rich-text-editor/label-token-defaults.ts b/packages/nimble-components/src/label-provider/rich-text-editor/label-token-defaults.ts deleted file mode 100644 index 42dbe410e9..0000000000 --- a/packages/nimble-components/src/label-provider/rich-text-editor/label-token-defaults.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type * as TokensNamespace from './label-tokens'; - -type TokenName = keyof typeof TokensNamespace; - -export const richTextEditorLabelDefaults: { - readonly [key in TokenName]: string; -} = { - richTextEditorToggleBoldLabel: 'Bold', - richTextEditorToggleItalicsLabel: 'Italics', - richTextEditorToggleBulletListLabel: 'Bullet List', - richTextEditorToggleNumberedListLabel: 'Numbered List' -}; diff --git a/packages/nimble-components/src/label-provider/rich-text-editor/label-tokens.ts b/packages/nimble-components/src/label-provider/rich-text-editor/label-tokens.ts deleted file mode 100644 index d013f8ed8f..0000000000 --- a/packages/nimble-components/src/label-provider/rich-text-editor/label-tokens.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { DesignToken } from '@microsoft/fast-foundation'; -import { richTextEditorLabelDefaults } from './label-token-defaults'; - -export const richTextEditorToggleBoldLabel = DesignToken.create({ - name: 'rich-text-editor-toggle-bold-label', - cssCustomPropertyName: null -}).withDefault(richTextEditorLabelDefaults.richTextEditorToggleBoldLabel); - -export const richTextEditorToggleItalicsLabel = DesignToken.create({ - name: 'rich-text-editor-toggle-italics-label', - cssCustomPropertyName: null -}).withDefault(richTextEditorLabelDefaults.richTextEditorToggleItalicsLabel); - -export const richTextEditorToggleBulletListLabel = DesignToken.create({ - name: 'rich-text-editor-toggle-bullet-list-label', - cssCustomPropertyName: null -}).withDefault(richTextEditorLabelDefaults.richTextEditorToggleBulletListLabel); - -export const richTextEditorToggleNumberedListLabel = DesignToken.create( - { - name: 'rich-text-editor-toggle-numbered-list-label', - cssCustomPropertyName: null - } -).withDefault( - richTextEditorLabelDefaults.richTextEditorToggleNumberedListLabel -); diff --git a/packages/nimble-components/src/label-provider/rich-text-editor/name-utils.ts b/packages/nimble-components/src/label-provider/rich-text-editor/name-utils.ts deleted file mode 100644 index 7ff6a8b4d9..0000000000 --- a/packages/nimble-components/src/label-provider/rich-text-editor/name-utils.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Removes the richTextEditor prefix and camelCases the input token name. - * (The design token name has the richTextEditor prefix, but the properties on the LabelProviderRichTextEditor do not, as they're already - * scoped to the rich-text-editor only) - */ -export function removeRichTextEditorPrefixAndCamelCase( - jsTokenName: string -): string { - // Example: 'richTextEditorToggleBulletListLabel' => 'toggleBulletListLabel' - return jsTokenName.replace( - /^richTextEditor(\w)(\w+)/, - (_match: string, firstChar: string, restOfString: string) => `${firstChar.toLowerCase()}${restOfString}` - ); -} diff --git a/packages/nimble-components/src/label-provider/rich-text/index.ts b/packages/nimble-components/src/label-provider/rich-text/index.ts new file mode 100644 index 0000000000..404e52a981 --- /dev/null +++ b/packages/nimble-components/src/label-provider/rich-text/index.ts @@ -0,0 +1,54 @@ +import { attr } from '@microsoft/fast-element'; +import { DesignSystem } from '@microsoft/fast-foundation'; +import { DesignTokensFor, LabelProviderBase } from '../base'; +import { + richTextToggleBoldLabel, + richTextToggleItalicsLabel, + richTextToggleBulletedListLabel, + richTextToggleNumberedListLabel +} from './label-tokens'; + +declare global { + interface HTMLElementTagNameMap { + 'nimble-label-provider-rich-text': LabelProviderRichText; + } +} + +const supportedLabels = { + toggleBold: richTextToggleBoldLabel, + toggleItalics: richTextToggleItalicsLabel, + toggleBulletedList: richTextToggleBulletedListLabel, + toggleNumberedList: richTextToggleNumberedListLabel +} as const; + +/** + * Label provider for the Nimble rich text component + */ +export class LabelProviderRichText + extends LabelProviderBase + implements DesignTokensFor { + @attr({ attribute: 'toggle-bold' }) + public toggleBold: string | undefined; + + @attr({ attribute: 'toggle-italics' }) + public toggleItalics: string | undefined; + + @attr({ attribute: 'toggle-bulleted-list' }) + public toggleBulletedList: string | undefined; + + @attr({ attribute: 'toggle-numbered-list' }) + public toggleNumberedList: string | undefined; + + protected override readonly supportedLabels = supportedLabels; +} + +const nimbleLabelProviderRichText = LabelProviderRichText.compose({ + baseName: 'label-provider-rich-text' +}); + +DesignSystem.getOrCreate() + .withPrefix('nimble') + .register(nimbleLabelProviderRichText()); +export const labelProviderRichTextTag = DesignSystem.tagFor( + LabelProviderRichText +); diff --git a/packages/nimble-components/src/label-provider/rich-text/label-token-defaults.ts b/packages/nimble-components/src/label-provider/rich-text/label-token-defaults.ts new file mode 100644 index 0000000000..fa56ca8875 --- /dev/null +++ b/packages/nimble-components/src/label-provider/rich-text/label-token-defaults.ts @@ -0,0 +1,12 @@ +import type * as TokensNamespace from './label-tokens'; + +type TokenName = keyof typeof TokensNamespace; + +export const richTextLabelDefaults: { + readonly [key in TokenName]: string; +} = { + richTextToggleBoldLabel: 'Bold', + richTextToggleItalicsLabel: 'Italics', + richTextToggleBulletedListLabel: 'Bulleted List', + richTextToggleNumberedListLabel: 'Numbered List' +}; diff --git a/packages/nimble-components/src/label-provider/rich-text/label-tokens.ts b/packages/nimble-components/src/label-provider/rich-text/label-tokens.ts new file mode 100644 index 0000000000..04f9d9ac31 --- /dev/null +++ b/packages/nimble-components/src/label-provider/rich-text/label-tokens.ts @@ -0,0 +1,26 @@ +import { DesignToken } from '@microsoft/fast-foundation'; +import { richTextLabelDefaults } from './label-token-defaults'; + +export const richTextToggleBoldLabel = DesignToken.create({ + name: 'rich-text-toggle-bold-label', + cssCustomPropertyName: null +}).withDefault(richTextLabelDefaults.richTextToggleBoldLabel); + +export const richTextToggleItalicsLabel = DesignToken.create({ + name: 'rich-text-toggle-italics-label', + cssCustomPropertyName: null +}).withDefault(richTextLabelDefaults.richTextToggleItalicsLabel); + +export const richTextToggleBulletedListLabel = DesignToken.create({ + name: 'rich-text-toggle-bulleted-list-label', + cssCustomPropertyName: null +}).withDefault(richTextLabelDefaults.richTextToggleBulletedListLabel); + +export const richTextToggleNumberedListLabel = DesignToken.create( + { + name: 'rich-text-toggle-numbered-list-label', + cssCustomPropertyName: null + } +).withDefault( + richTextLabelDefaults.richTextToggleNumberedListLabel +); diff --git a/packages/nimble-components/src/label-provider/rich-text-editor/tests/label-provider-rich-text-editor.spec.ts b/packages/nimble-components/src/label-provider/rich-text/tests/label-provider-rich-text.spec.ts similarity index 86% rename from packages/nimble-components/src/label-provider/rich-text-editor/tests/label-provider-rich-text-editor.spec.ts rename to packages/nimble-components/src/label-provider/rich-text/tests/label-provider-rich-text.spec.ts index 9a618e8462..230d039099 100644 --- a/packages/nimble-components/src/label-provider/rich-text-editor/tests/label-provider-rich-text-editor.spec.ts +++ b/packages/nimble-components/src/label-provider/rich-text/tests/label-provider-rich-text.spec.ts @@ -2,17 +2,15 @@ import { spinalCase } from '@microsoft/fast-web-utilities'; import { html } from '@microsoft/fast-element'; import * as labelTokensNamespace from '../label-tokens'; import { - LabelProviderRichTextEditor, - labelProviderRichTextEditorTag + LabelProviderRichText, + labelProviderRichTextTag } from '..'; import { getSpecTypeByNamedList } from '../../../utilities/tests/parameterized'; -import { - getAttributeName, - getPropertyName -} from '../../base/tests/label-name-utils'; +import { getAttributeName, + getPropertyName, + removePrefixAndCamelCase } from '../../base/tests/label-name-utils'; import { ThemeProvider, themeProviderTag } from '../../../theme-provider'; import { Fixture, fixture } from '../../../utilities/tests/fixture'; -import { removeRichTextEditorPrefixAndCamelCase } from '../name-utils'; type DesignTokenPropertyName = keyof typeof labelTokensNamespace; const designTokenPropertyNames = Object.keys( @@ -22,20 +20,20 @@ const designTokenPropertyNames = Object.keys( async function setup(): Promise> { return fixture(html` <${themeProviderTag}> - <${labelProviderRichTextEditorTag}> + <${labelProviderRichTextTag}> `); } -describe('Label Provider Rich Text Editor', () => { - let element: LabelProviderRichTextEditor; +describe('Label Provider Rich Text', () => { + let element: LabelProviderRichText; let themeProvider: ThemeProvider; let connect: () => Promise; let disconnect: () => Promise; beforeEach(async () => { ({ element: themeProvider, connect, disconnect } = await setup()); - element = themeProvider.querySelector(labelProviderRichTextEditorTag)!; + element = themeProvider.querySelector(labelProviderRichTextTag)!; await connect(); }); @@ -45,8 +43,8 @@ describe('Label Provider Rich Text Editor', () => { it('can construct an element instance', () => { expect( - document.createElement('nimble-label-provider-rich-text-editor') - ).toBeInstanceOf(LabelProviderRichTextEditor); + document.createElement('nimble-label-provider-rich-text') + ).toBeInstanceOf(LabelProviderRichText); }); describe('token JS key should match DesignToken.name', () => { @@ -90,8 +88,9 @@ describe('Label Provider Rich Text Editor', () => { ); // eslint-disable-next-line @typescript-eslint/no-loop-func specType(`for token name ${tokenEntry.name}`, () => { - const tokenName = removeRichTextEditorPrefixAndCamelCase( - tokenEntry.name + const tokenName = removePrefixAndCamelCase( + tokenEntry.name, + 'richText', ); const expectedPropertyName = getPropertyName(tokenName); const expectedAttributeName = getAttributeName(tokenName); @@ -124,8 +123,9 @@ describe('Label Provider Rich Text Editor', () => { ); // eslint-disable-next-line @typescript-eslint/no-loop-func specType(`for token name ${tokenEntry.name}`, () => { - const tokenName = removeRichTextEditorPrefixAndCamelCase( - tokenEntry.name + const tokenName = removePrefixAndCamelCase( + tokenEntry.name, + 'richText' ); const attributeName = getAttributeName(tokenName); const updatedValue = `NewString-${tokenName}`; diff --git a/packages/nimble-components/src/label-provider/rich-text-editor/tests/label-provider-rich-text-editor.stories.ts b/packages/nimble-components/src/label-provider/rich-text/tests/label-provider-rich-text.stories.ts similarity index 55% rename from packages/nimble-components/src/label-provider/rich-text-editor/tests/label-provider-rich-text-editor.stories.ts rename to packages/nimble-components/src/label-provider/rich-text/tests/label-provider-rich-text.stories.ts index c03ac632a5..a240fd73ab 100644 --- a/packages/nimble-components/src/label-provider/rich-text-editor/tests/label-provider-rich-text-editor.stories.ts +++ b/packages/nimble-components/src/label-provider/rich-text/tests/label-provider-rich-text.stories.ts @@ -3,9 +3,9 @@ import { LabelProviderArgs, labelProviderMetadata } from '../../base/tests/label-provider-stories-utils'; -import { labelProviderRichTextEditorTag } from '..'; +import { labelProviderRichTextTag } from '..'; import * as labelTokensNamespace from '../label-tokens'; -import { removeRichTextEditorPrefixAndCamelCase } from '../name-utils'; +import { removePrefixAndCamelCase } from '../../base/tests/label-name-utils'; const metadata = { ...labelProviderMetadata, @@ -14,10 +14,11 @@ const metadata = { export default metadata; -export const richTextEditorLabelProvider: StoryObj = { +export const richTextLabelProvider: StoryObj = { args: { - labelProviderTag: labelProviderRichTextEditorTag, + labelProviderTag: labelProviderRichTextTag, labelTokens: Object.entries(labelTokensNamespace), - removeNamePrefix: removeRichTextEditorPrefixAndCamelCase + prefixSubstring: 'richText', + removeNamePrefix: removePrefixAndCamelCase } }; diff --git a/packages/nimble-components/src/label-provider/table/name-utils.ts b/packages/nimble-components/src/label-provider/table/name-utils.ts deleted file mode 100644 index 27fa0784ca..0000000000 --- a/packages/nimble-components/src/label-provider/table/name-utils.ts +++ /dev/null @@ -1,12 +0,0 @@ -/** - * Removes the table prefix and camelCases the input token name. - * (The design token name has the table prefix, but the properties on the LabelProviderTable do not, as they're already - * scoped to the table only) - */ -export function removeTablePrefixAndCamelCase(jsTokenName: string): string { - // Example: 'tableGroupExpandLabel' => 'groupExpandLabel' - return jsTokenName.replace( - /^table(\w)(\w+)/, - (_match: string, firstChar: string, restOfString: string) => `${firstChar.toLowerCase()}${restOfString}` - ); -} diff --git a/packages/nimble-components/src/label-provider/table/tests/label-provider-table.spec.ts b/packages/nimble-components/src/label-provider/table/tests/label-provider-table.spec.ts index 1659d7e4db..a21adc72f8 100644 --- a/packages/nimble-components/src/label-provider/table/tests/label-provider-table.spec.ts +++ b/packages/nimble-components/src/label-provider/table/tests/label-provider-table.spec.ts @@ -5,11 +5,11 @@ import { LabelProviderTable, labelProviderTableTag } from '..'; import { getSpecTypeByNamedList } from '../../../utilities/tests/parameterized'; import { getAttributeName, - getPropertyName + getPropertyName, + removePrefixAndCamelCase } from '../../base/tests/label-name-utils'; import { ThemeProvider, themeProviderTag } from '../../../theme-provider'; import { Fixture, fixture } from '../../../utilities/tests/fixture'; -import { removeTablePrefixAndCamelCase } from '../name-utils'; type DesignTokenPropertyName = keyof typeof labelTokensNamespace; const designTokenPropertyNames = Object.keys( @@ -87,8 +87,9 @@ describe('Label Provider Table', () => { ); // eslint-disable-next-line @typescript-eslint/no-loop-func specType(`for token name ${tokenEntry.name}`, () => { - const tokenName = removeTablePrefixAndCamelCase( - tokenEntry.name + const tokenName = removePrefixAndCamelCase( + tokenEntry.name, + 'table' ); const expectedPropertyName = getPropertyName(tokenName); const expectedAttributeName = getAttributeName(tokenName); @@ -121,8 +122,9 @@ describe('Label Provider Table', () => { ); // eslint-disable-next-line @typescript-eslint/no-loop-func specType(`for token name ${tokenEntry.name}`, () => { - const tokenName = removeTablePrefixAndCamelCase( - tokenEntry.name + const tokenName = removePrefixAndCamelCase( + tokenEntry.name, + 'table' ); const attributeName = getAttributeName(tokenName); const updatedValue = `NewString-${tokenName}`; diff --git a/packages/nimble-components/src/label-provider/table/tests/label-provider-table.stories.ts b/packages/nimble-components/src/label-provider/table/tests/label-provider-table.stories.ts index 4904d06b56..7eb3611c8b 100644 --- a/packages/nimble-components/src/label-provider/table/tests/label-provider-table.stories.ts +++ b/packages/nimble-components/src/label-provider/table/tests/label-provider-table.stories.ts @@ -4,8 +4,8 @@ import { labelProviderMetadata } from '../../base/tests/label-provider-stories-utils'; import { labelProviderTableTag } from '..'; -import { removeTablePrefixAndCamelCase } from '../name-utils'; import * as labelTokensNamespace from '../label-tokens'; +import { removePrefixAndCamelCase } from '../../base/tests/label-name-utils'; const metadata = { ...labelProviderMetadata, @@ -18,6 +18,7 @@ export const tableLabelProvider: StoryObj = { args: { labelProviderTag: labelProviderTableTag, labelTokens: Object.entries(labelTokensNamespace), - removeNamePrefix: removeTablePrefixAndCamelCase + prefixSubstring: 'table', + removeNamePrefix: removePrefixAndCamelCase } }; diff --git a/packages/nimble-components/src/rich-text-editor/template.ts b/packages/nimble-components/src/rich-text-editor/template.ts index 5cc01a789b..fc24fe92e9 100644 --- a/packages/nimble-components/src/rich-text-editor/template.ts +++ b/packages/nimble-components/src/rich-text-editor/template.ts @@ -7,11 +7,11 @@ import { iconItalicITag } from '../icons/italic-i'; import { iconListTag } from '../icons/list'; import { iconNumberListTag } from '../icons/number-list'; import { - richTextEditorToggleBoldLabel, - richTextEditorToggleItalicsLabel, - richTextEditorToggleBulletListLabel, - richTextEditorToggleNumberedListLabel -} from '../label-provider/rich-text-editor/label-tokens'; + richTextToggleBoldLabel, + richTextToggleItalicsLabel, + richTextToggleBulletedListLabel, + richTextToggleNumberedListLabel +} from '../label-provider/rich-text/label-tokens'; // prettier-ignore export const template = html` @@ -26,12 +26,12 @@ export const template = html` appearance="ghost" content-hidden slot="start" - title=${x => richTextEditorToggleBoldLabel.getValueFor(x)} + title=${x => richTextToggleBoldLabel.getValueFor(x)} @click=${x => x.boldButtonClick()} @change=${(x, c) => x.stopEventPropagation(c.event)} @keydown=${(x, c) => x.boldButtonKeyDown(c.event as KeyboardEvent)} > - ${x => richTextEditorToggleBoldLabel.getValueFor(x)} + ${x => richTextToggleBoldLabel.getValueFor(x)} <${iconBoldBTag} slot="start"> <${toggleButtonTag} @@ -39,12 +39,12 @@ export const template = html` appearance="ghost" content-hidden slot="start" - title=${x => richTextEditorToggleItalicsLabel.getValueFor(x)} + title=${x => richTextToggleItalicsLabel.getValueFor(x)} @click=${x => x.italicsButtonClick()} @change=${(x, c) => x.stopEventPropagation(c.event)} @keydown=${(x, c) => x.italicsButtonKeyDown(c.event as KeyboardEvent)} > - ${x => richTextEditorToggleItalicsLabel.getValueFor(x)} + ${x => richTextToggleItalicsLabel.getValueFor(x)} <${iconItalicITag} slot="start"> <${toggleButtonTag} @@ -52,12 +52,12 @@ export const template = html` appearance="ghost" content-hidden slot="start" - title=${x => richTextEditorToggleBulletListLabel.getValueFor(x)} + title=${x => richTextToggleBulletedListLabel.getValueFor(x)} @click=${x => x.bulletListButtonClick()} @change=${(x, c) => x.stopEventPropagation(c.event)} @keydown=${(x, c) => x.bulletListButtonKeyDown(c.event as KeyboardEvent)} > - ${x => richTextEditorToggleBulletListLabel.getValueFor(x)} + ${x => richTextToggleBulletedListLabel.getValueFor(x)} <${iconListTag} slot="start"> <${toggleButtonTag} @@ -65,12 +65,12 @@ export const template = html` appearance="ghost" content-hidden slot="start" - title=${x => richTextEditorToggleNumberedListLabel.getValueFor(x)} + title=${x => richTextToggleNumberedListLabel.getValueFor(x)} @click=${x => x.numberedListButtonClick()} @change=${(x, c) => x.stopEventPropagation(c.event)} @keydown=${(x, c) => x.numberedListButtonKeyDown(c.event as KeyboardEvent)} > - ${x => richTextEditorToggleNumberedListLabel.getValueFor(x)} + ${x => richTextToggleNumberedListLabel.getValueFor(x)} <${iconNumberListTag} slot="start"> diff --git a/packages/nimble-components/src/rich-text-editor/testing/rich-text-editor.pageobject.ts b/packages/nimble-components/src/rich-text-editor/testing/rich-text-editor.pageobject.ts index 38050ed6b4..eae32bd59c 100644 --- a/packages/nimble-components/src/rich-text-editor/testing/rich-text-editor.pageobject.ts +++ b/packages/nimble-components/src/rich-text-editor/testing/rich-text-editor.pageobject.ts @@ -156,13 +156,27 @@ export class RichTextEditorPageObject { .map(el => el.textContent || ''); } - public getFormattingButton( - index: ToolbarButton + public getFormattingButtonTextContent( + toolbarButton: ToolbarButton + ): string { + const button = this.getFormattingButton(toolbarButton); + return button!.textContent!.trim(); + } + + public getFormattingButtonTitle( + toolbarButton: ToolbarButton + ): string { + const button = this.getFormattingButton(toolbarButton); + return button!.title; + } + + private getFormattingButton( + toolbarButton: ToolbarButton ): ToggleButton | null | undefined { const buttons: NodeListOf = this.richTextEditorElement.shadowRoot!.querySelectorAll( 'nimble-toggle-button' ); - return buttons[index]; + return buttons[toolbarButton]; } private getEditorSection(): Element | null | undefined { diff --git a/packages/nimble-components/src/rich-text-editor/testing/types.ts b/packages/nimble-components/src/rich-text-editor/testing/types.ts index 42e3846653..0cde20f188 100644 --- a/packages/nimble-components/src/rich-text-editor/testing/types.ts +++ b/packages/nimble-components/src/rich-text-editor/testing/types.ts @@ -9,5 +9,5 @@ export type ToolbarButton = (typeof ToolbarButton)[keyof typeof ToolbarButton]; export type LabelProvider = | 'toggleBold' | 'toggleItalics' - | 'toggleBulletList' + | 'toggleBulletedList' | 'toggleNumberedList'; diff --git a/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor-labels.spec.ts b/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor-labels.spec.ts index c516f86baa..a0029cd9b5 100644 --- a/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor-labels.spec.ts +++ b/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor-labels.spec.ts @@ -3,9 +3,9 @@ import { richTextEditorTag, type RichTextEditor } from '..'; import { type Fixture, fixture } from '../../utilities/tests/fixture'; import { themeProviderTag, type ThemeProvider } from '../../theme-provider'; import { - LabelProviderRichTextEditor, - labelProviderRichTextEditorTag -} from '../../label-provider/rich-text-editor'; + LabelProviderRichText, + labelProviderRichTextTag +} from '../../label-provider/rich-text'; import { RichTextEditorPageObject } from '../testing/rich-text-editor.pageobject'; import { LabelProvider, ToolbarButton } from '../testing/types'; import { getSpecTypeByNamedList } from '../../utilities/tests/parameterized'; @@ -15,7 +15,7 @@ async function setup(): Promise> { return fixture( html` <${themeProviderTag}> - <${labelProviderRichTextEditorTag}> + <${labelProviderRichTextTag}> <${richTextEditorTag}> <${themeProviderTag}>` ); @@ -25,37 +25,37 @@ const formattingButtons: { name: string, property: LabelProvider, label: string, - toolbarButtonIndex: ToolbarButton + toolbarButton: ToolbarButton }[] = [ { name: 'Bold', property: 'toggleBold', label: 'Customized Bold Label', - toolbarButtonIndex: ToolbarButton.bold + toolbarButton: ToolbarButton.bold }, { name: 'Italics', property: 'toggleItalics', label: 'Customized Italics Label', - toolbarButtonIndex: ToolbarButton.italics + toolbarButton: ToolbarButton.italics }, { name: 'BulletList', - property: 'toggleBulletList', - label: 'Customized Bullet List Label', - toolbarButtonIndex: ToolbarButton.bulletList + property: 'toggleBulletedList', + label: 'Customized Bulleted List Label', + toolbarButton: ToolbarButton.bulletList }, { name: 'NumberedList', property: 'toggleNumberedList', label: 'Customized Numbered List Label', - toolbarButtonIndex: ToolbarButton.numberedList + toolbarButton: ToolbarButton.numberedList } ]; -describe('Rich Text Editor with LabelProviderRichTextEditor', () => { +describe('Rich Text Editor with LabelProviderRichText', () => { let element: RichTextEditor; - let labelProvider: LabelProviderRichTextEditor; + let labelProvider: LabelProviderRichText; let connect: () => Promise; let disconnect: () => Promise; let pageObject: RichTextEditorPageObject; @@ -68,7 +68,7 @@ describe('Rich Text Editor with LabelProviderRichTextEditor', () => { await connect(); element = themeProvider.querySelector(richTextEditorTag)!; labelProvider = themeProvider.querySelector( - labelProviderRichTextEditorTag + labelProviderRichTextTag )!; pageObject = new RichTextEditorPageObject(element); }); @@ -85,11 +85,8 @@ describe('Rich Text Editor with LabelProviderRichTextEditor', () => { async () => { labelProvider[value.property] = value.label; await waitForUpdatesAsync(); - const formatButton = pageObject.getFormattingButton( - value.toolbarButtonIndex - ); - expect(formatButton!.textContent!.trim()).toBe(value.label); - expect(formatButton!.title).toBe(value.label); + expect(pageObject.getFormattingButtonTextContent(value.toolbarButton)).toBe(value.label); + expect(pageObject.getFormattingButtonTitle(value.toolbarButton)).toBe(value.label); } ); } diff --git a/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor.stories.ts b/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor.stories.ts index 7cafa89e44..4ac113abd2 100644 --- a/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor.stories.ts +++ b/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor.stories.ts @@ -10,7 +10,7 @@ import { addLabelUseMetadata, type LabelUserArgs } from '../../label-provider/base/tests/label-user-stories-utils'; -import { labelProviderRichTextEditorTag } from '../../label-provider/rich-text-editor'; +import { labelProviderRichTextTag } from '../../label-provider/rich-text'; // eslint-disable-next-line @typescript-eslint/no-empty-interface interface RichTextEditorArgs extends LabelUserArgs { @@ -125,7 +125,7 @@ const metadata: Meta = { } }; -addLabelUseMetadata(metadata, labelProviderRichTextEditorTag); +addLabelUseMetadata(metadata, labelProviderRichTextTag); export default metadata; From 0671f0b910893f7d1cf8660fed275eb140d10cd9 Mon Sep 17 00:00:00 2001 From: Aagash Raaj <123377167+aagash-ni@users.noreply.github.com> Date: Thu, 31 Aug 2023 23:02:22 +0530 Subject: [PATCH 11/19] Fix Lint --- .../label-provider/base/tests/label-name-utils.ts | 5 ++++- .../base/tests/label-provider-stories-utils.ts | 2 +- .../label-provider/base/tests/label-providers.mdx | 2 +- .../src/label-provider/rich-text/label-tokens.ts | 12 ++++-------- .../tests/label-provider-rich-text.spec.ts | 13 ++++++------- .../testing/rich-text-editor.pageobject.ts | 4 +--- .../tests/rich-text-editor-labels.spec.ts | 14 +++++++++----- 7 files changed, 26 insertions(+), 26 deletions(-) diff --git a/packages/nimble-components/src/label-provider/base/tests/label-name-utils.ts b/packages/nimble-components/src/label-provider/base/tests/label-name-utils.ts index 0045dddc66..86e158b254 100644 --- a/packages/nimble-components/src/label-provider/base/tests/label-name-utils.ts +++ b/packages/nimble-components/src/label-provider/base/tests/label-name-utils.ts @@ -13,7 +13,10 @@ export function getAttributeName(jsKey: string): string { * (The design token name has the element/types prefix, but the properties do not, as they're already * scoped to the respective element) */ -export function removePrefixAndCamelCase(jsTokenName: string, prefix: string): string { +export function removePrefixAndCamelCase( + jsTokenName: string, + prefix: string +): string { return jsTokenName.replace( new RegExp(`^${prefix}(\\w)(\\w+)`), (_match: string, firstChar: string, restOfString: string) => `${firstChar.toLowerCase()}${restOfString}` diff --git a/packages/nimble-components/src/label-provider/base/tests/label-provider-stories-utils.ts b/packages/nimble-components/src/label-provider/base/tests/label-provider-stories-utils.ts index 96f904859b..e7e0f9fd74 100644 --- a/packages/nimble-components/src/label-provider/base/tests/label-provider-stories-utils.ts +++ b/packages/nimble-components/src/label-provider/base/tests/label-provider-stories-utils.ts @@ -12,7 +12,7 @@ export interface LabelProviderArgs { labelProviderTag: string; labelTokens: [string, DesignToken][]; prefixSubstring: string; - removeNamePrefix(tokenName: string, elementName?: string,): string; + removeNamePrefix(tokenName: string, elementName?: string): string; updateData(args: LabelProviderArgs): void; } diff --git a/packages/nimble-components/src/label-provider/base/tests/label-providers.mdx b/packages/nimble-components/src/label-provider/base/tests/label-providers.mdx index dd1a059003..cf2a80441b 100644 --- a/packages/nimble-components/src/label-provider/base/tests/label-providers.mdx +++ b/packages/nimble-components/src/label-provider/base/tests/label-providers.mdx @@ -27,7 +27,7 @@ Provides labels for all Nimble components that do not have a dedicated label pro ## Rich Text Label Provider -Provides labels for the the rich text components. +Provides labels for the the rich text components. diff --git a/packages/nimble-components/src/label-provider/rich-text/label-tokens.ts b/packages/nimble-components/src/label-provider/rich-text/label-tokens.ts index 04f9d9ac31..5cf31633b9 100644 --- a/packages/nimble-components/src/label-provider/rich-text/label-tokens.ts +++ b/packages/nimble-components/src/label-provider/rich-text/label-tokens.ts @@ -16,11 +16,7 @@ export const richTextToggleBulletedListLabel = DesignToken.create({ cssCustomPropertyName: null }).withDefault(richTextLabelDefaults.richTextToggleBulletedListLabel); -export const richTextToggleNumberedListLabel = DesignToken.create( - { - name: 'rich-text-toggle-numbered-list-label', - cssCustomPropertyName: null - } -).withDefault( - richTextLabelDefaults.richTextToggleNumberedListLabel -); +export const richTextToggleNumberedListLabel = DesignToken.create({ + name: 'rich-text-toggle-numbered-list-label', + cssCustomPropertyName: null +}).withDefault(richTextLabelDefaults.richTextToggleNumberedListLabel); diff --git a/packages/nimble-components/src/label-provider/rich-text/tests/label-provider-rich-text.spec.ts b/packages/nimble-components/src/label-provider/rich-text/tests/label-provider-rich-text.spec.ts index 230d039099..74e951223d 100644 --- a/packages/nimble-components/src/label-provider/rich-text/tests/label-provider-rich-text.spec.ts +++ b/packages/nimble-components/src/label-provider/rich-text/tests/label-provider-rich-text.spec.ts @@ -1,14 +1,13 @@ import { spinalCase } from '@microsoft/fast-web-utilities'; import { html } from '@microsoft/fast-element'; import * as labelTokensNamespace from '../label-tokens'; -import { - LabelProviderRichText, - labelProviderRichTextTag -} from '..'; +import { LabelProviderRichText, labelProviderRichTextTag } from '..'; import { getSpecTypeByNamedList } from '../../../utilities/tests/parameterized'; -import { getAttributeName, +import { + getAttributeName, getPropertyName, - removePrefixAndCamelCase } from '../../base/tests/label-name-utils'; + removePrefixAndCamelCase +} from '../../base/tests/label-name-utils'; import { ThemeProvider, themeProviderTag } from '../../../theme-provider'; import { Fixture, fixture } from '../../../utilities/tests/fixture'; @@ -90,7 +89,7 @@ describe('Label Provider Rich Text', () => { specType(`for token name ${tokenEntry.name}`, () => { const tokenName = removePrefixAndCamelCase( tokenEntry.name, - 'richText', + 'richText' ); const expectedPropertyName = getPropertyName(tokenName); const expectedAttributeName = getAttributeName(tokenName); diff --git a/packages/nimble-components/src/rich-text-editor/testing/rich-text-editor.pageobject.ts b/packages/nimble-components/src/rich-text-editor/testing/rich-text-editor.pageobject.ts index eae32bd59c..a1734adc4e 100644 --- a/packages/nimble-components/src/rich-text-editor/testing/rich-text-editor.pageobject.ts +++ b/packages/nimble-components/src/rich-text-editor/testing/rich-text-editor.pageobject.ts @@ -163,9 +163,7 @@ export class RichTextEditorPageObject { return button!.textContent!.trim(); } - public getFormattingButtonTitle( - toolbarButton: ToolbarButton - ): string { + public getFormattingButtonTitle(toolbarButton: ToolbarButton): string { const button = this.getFormattingButton(toolbarButton); return button!.title; } diff --git a/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor-labels.spec.ts b/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor-labels.spec.ts index a0029cd9b5..8bcd734c6b 100644 --- a/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor-labels.spec.ts +++ b/packages/nimble-components/src/rich-text-editor/tests/rich-text-editor-labels.spec.ts @@ -67,9 +67,7 @@ describe('Rich Text Editor with LabelProviderRichText', () => { ({ element: themeProvider, connect, disconnect } = await setup()); await connect(); element = themeProvider.querySelector(richTextEditorTag)!; - labelProvider = themeProvider.querySelector( - labelProviderRichTextTag - )!; + labelProvider = themeProvider.querySelector(labelProviderRichTextTag)!; pageObject = new RichTextEditorPageObject(element); }); @@ -85,8 +83,14 @@ describe('Rich Text Editor with LabelProviderRichText', () => { async () => { labelProvider[value.property] = value.label; await waitForUpdatesAsync(); - expect(pageObject.getFormattingButtonTextContent(value.toolbarButton)).toBe(value.label); - expect(pageObject.getFormattingButtonTitle(value.toolbarButton)).toBe(value.label); + expect( + pageObject.getFormattingButtonTextContent( + value.toolbarButton + ) + ).toBe(value.label); + expect( + pageObject.getFormattingButtonTitle(value.toolbarButton) + ).toBe(value.label); } ); } From 7191d23eeec920a2bb05ce8671082e3e0b603569 Mon Sep 17 00:00:00 2001 From: Aagash Raaj <123377167+aagash-ni@users.noreply.github.com> Date: Fri, 1 Sep 2023 11:50:46 +0530 Subject: [PATCH 12/19] Angulation integration for rich text label provider --- .../src/app/app.component.html | 1 + .../example-client-app/src/app/app.module.ts | 2 + .../projects/ni/nimble-angular/README.md | 3 + .../rich-text-editor/ng-package.json | 6 + ...vider-rich-text-with-defaults.directive.ts | 20 ++ ...mble-label-provider-rich-text.directive.ts | 56 ++++ .../nimble-label-provider-rich-text.module.ts | 15 + .../rich-text-editor/public-api.ts | 3 + ...-rich-text-with-defaults.directive.spec.ts | 48 +++ ...label-provider-rich-text.directive.spec.ts | 283 ++++++++++++++++++ 10 files changed, 437 insertions(+) create mode 100644 angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/ng-package.json create mode 100644 angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/nimble-label-provider-rich-text-with-defaults.directive.ts create mode 100644 angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/nimble-label-provider-rich-text.directive.ts create mode 100644 angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/nimble-label-provider-rich-text.module.ts create mode 100644 angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/public-api.ts create mode 100644 angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/tests/nimble-label-provider-rich-text-with-defaults.directive.spec.ts create mode 100644 angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/tests/nimble-label-provider-rich-text.directive.spec.ts diff --git a/angular-workspace/projects/example-client-app/src/app/app.component.html b/angular-workspace/projects/example-client-app/src/app/app.component.html index 303015226f..eacfdfabb3 100644 --- a/angular-workspace/projects/example-client-app/src/app/app.component.html +++ b/angular-workspace/projects/example-client-app/src/app/app.component.html @@ -1,5 +1,6 @@ +
diff --git a/angular-workspace/projects/example-client-app/src/app/app.module.ts b/angular-workspace/projects/example-client-app/src/app/app.module.ts index b47de93b03..ef04893163 100644 --- a/angular-workspace/projects/example-client-app/src/app/app.module.ts +++ b/angular-workspace/projects/example-client-app/src/app/app.module.ts @@ -11,6 +11,7 @@ import { NimbleTextAreaModule, NimbleTextFieldModule, NimbleNumberFieldModule, N NimbleAnchorModule, NimbleAnchorButtonModule, NimbleAnchorTabModule, NimbleAnchorTabsModule, NimbleIconCheckModule, NimbleBannerModule, NimbleAnchorMenuItemModule, NimbleAnchorTreeItemModule } from '@ni/nimble-angular'; import { NimbleLabelProviderCoreModule } from '@ni/nimble-angular/label-provider/core'; +import { NimbleLabelProviderRichTextModule } from '@ni/nimble-angular/label-provider/rich-text-editor'; import { NimbleLabelProviderTableModule } from '@ni/nimble-angular/label-provider/table'; import { NimbleMappingTextModule } from '@ni/nimble-angular/mapping/text'; import { NimbleMappingIconModule } from '@ni/nimble-angular/mapping/icon'; @@ -39,6 +40,7 @@ import { HeaderComponent } from './header/header.component'; ReactiveFormsModule, NimbleThemeProviderModule, NimbleLabelProviderCoreModule, + NimbleLabelProviderRichTextModule, NimbleLabelProviderTableModule, NimbleTextAreaModule, NimbleTextFieldModule, diff --git a/angular-workspace/projects/ni/nimble-angular/README.md b/angular-workspace/projects/ni/nimble-angular/README.md index 3aa2b2a247..e19d481990 100644 --- a/angular-workspace/projects/ni/nimble-angular/README.md +++ b/angular-workspace/projects/ni/nimble-angular/README.md @@ -93,11 +93,14 @@ Most user-visible strings displayed by Nimble components are provided by the cli The standard way to use these in Angular (for localized apps using `@angular/localize`) is: 1. Import the label provider module(s) from your app module: - `NimbleLabelProviderCoreModule` from `@ni/nimble-angular/label-provider/core`: Used for labels for all components besides the table + - `NimbleLabelProviderRichTextModule` from `@ni/nimble-angular/label-provider/rich-text`: Used for labels for the rich text components - `NimbleLabelProviderTableModule` from `@ni/nimble-angular/label-provider/table`: Used for labels for the table (and table sub-components / column types) 2. To use the Nimble-provided strings (which are already declared with `$localize`), use the `NimbleLabelProvider[Core/Table]WithDefaultsDirective`: ```html + + diff --git a/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/ng-package.json b/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/ng-package.json new file mode 100644 index 0000000000..e5440110fb --- /dev/null +++ b/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/ng-package.json @@ -0,0 +1,6 @@ +{ + "$schema": "../../../../../../node_modules/ng-packagr/ng-package.schema.json", + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/nimble-label-provider-rich-text-with-defaults.directive.ts b/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/nimble-label-provider-rich-text-with-defaults.directive.ts new file mode 100644 index 0000000000..248005216a --- /dev/null +++ b/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/nimble-label-provider-rich-text-with-defaults.directive.ts @@ -0,0 +1,20 @@ +import { Directive, ElementRef, Renderer2 } from '@angular/core'; +import type { LabelProviderRichText } from '@ni/nimble-components/dist/esm/label-provider/rich-text'; + +import '@angular/localize/init'; + +/** + * Directive for nimble-label-provider-rich-text which will initialize all of the labels with $localize-tagged strings, for apps + * using @angular/localize. + */ +@Directive({ + selector: 'nimble-label-provider-rich-text[withDefaults]' +}) +export class NimbleLabelProviderRichTextWithDefaultsDirective { + public constructor(protected readonly renderer: Renderer2, protected readonly elementRef: ElementRef) { + this.elementRef.nativeElement.toggleBold = $localize`:Nimble rich text - toggle bold|:Bold`; + this.elementRef.nativeElement.toggleItalics = $localize`:Nimble rich text - toggle italics|:Italics`; + this.elementRef.nativeElement.toggleBulletedList = $localize`:Nimble rich text - toggle bulleted list|:Bulleted List`; + this.elementRef.nativeElement.toggleNumberedList = $localize`:Nimble rich text - toggle numbered list|:Numbered List`; + } +} \ No newline at end of file diff --git a/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/nimble-label-provider-rich-text.directive.ts b/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/nimble-label-provider-rich-text.directive.ts new file mode 100644 index 0000000000..d230fe361f --- /dev/null +++ b/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/nimble-label-provider-rich-text.directive.ts @@ -0,0 +1,56 @@ +import { Directive, ElementRef, Input, Renderer2 } from '@angular/core'; +import type { LabelProviderRichText } from '@ni/nimble-components/dist/esm/label-provider/rich-text'; + +export type { LabelProviderRichText }; + +/** + * Directive to provide Angular integration for the nimble-rich-text label provider. + * To use the Nimble-provided strings declared via $localize, instead use NimbleLabelProviderRichTextWithDefaultsDirective. + */ +@Directive({ + selector: 'nimble-label-provider-rich-text' +}) +export class NimbleLabelProviderRichTextDirective { + public constructor(protected readonly renderer: Renderer2, protected readonly elementRef: ElementRef) { + } + + public get toggleBold(): string | undefined { + return this.elementRef.nativeElement.toggleBold; + } + + // Renaming because property should have camel casing, but attribute should not + // eslint-disable-next-line @angular-eslint/no-input-rename + @Input('toggle-bold') public set toggleBold(value: string | undefined) { + this.renderer.setProperty(this.elementRef.nativeElement, 'toggleBold', value); + } + + public get toggleItalics(): string | undefined { + return this.elementRef.nativeElement.toggleItalics; + } + + // Renaming because property should have camel casing, but attribute should not + // eslint-disable-next-line @angular-eslint/no-input-rename + @Input('toggle-italics') public set toggleItalics(value: string | undefined) { + this.renderer.setProperty(this.elementRef.nativeElement, 'toggleItalics', value); + } + + public get toggleBulletedList(): string | undefined { + return this.elementRef.nativeElement.toggleBulletedList; + } + + // Renaming because property should have camel casing, but attribute should not + // eslint-disable-next-line @angular-eslint/no-input-rename + @Input('toggle-bulleted-list') public set toggleBulletedList(value: string | undefined) { + this.renderer.setProperty(this.elementRef.nativeElement, 'toggleBulletedList', value); + } + + public get toggleNumberedList(): string | undefined { + return this.elementRef.nativeElement.toggleNumberedList; + } + + // Renaming because property should have camel casing, but attribute should not + // eslint-disable-next-line @angular-eslint/no-input-rename + @Input('toggle-numbered-list') public set toggleNumberedList(value: string | undefined) { + this.renderer.setProperty(this.elementRef.nativeElement, 'toggleNumberedList', value); + } +} \ No newline at end of file diff --git a/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/nimble-label-provider-rich-text.module.ts b/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/nimble-label-provider-rich-text.module.ts new file mode 100644 index 0000000000..08c3cef9f4 --- /dev/null +++ b/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/nimble-label-provider-rich-text.module.ts @@ -0,0 +1,15 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { NimbleLabelProviderRichTextDirective } from './nimble-label-provider-rich-text.directive'; +import { NimbleLabelProviderRichTextWithDefaultsDirective } from './nimble-label-provider-rich-text-with-defaults.directive'; + +import '@ni/nimble-components/dist/esm/label-provider/rich-text'; + +@NgModule({ + declarations: [NimbleLabelProviderRichTextDirective, NimbleLabelProviderRichTextWithDefaultsDirective], + imports: [ + CommonModule + ], + exports: [NimbleLabelProviderRichTextDirective, NimbleLabelProviderRichTextWithDefaultsDirective] +}) +export class NimbleLabelProviderRichTextModule { } diff --git a/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/public-api.ts b/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/public-api.ts new file mode 100644 index 0000000000..23f0305680 --- /dev/null +++ b/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/public-api.ts @@ -0,0 +1,3 @@ +export * from './nimble-label-provider-rich-text.directive'; +export * from './nimble-label-provider-rich-text-with-defaults.directive'; +export * from './nimble-label-provider-rich-text.module'; \ No newline at end of file diff --git a/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/tests/nimble-label-provider-rich-text-with-defaults.directive.spec.ts b/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/tests/nimble-label-provider-rich-text-with-defaults.directive.spec.ts new file mode 100644 index 0000000000..a7017543e8 --- /dev/null +++ b/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/tests/nimble-label-provider-rich-text-with-defaults.directive.spec.ts @@ -0,0 +1,48 @@ +import { Component, ElementRef, ViewChild } from '@angular/core'; +import { TestBed } from '@angular/core/testing'; +import { CommonModule } from '@angular/common'; +import { computeMsgId } from '@angular/compiler'; +import { loadTranslations } from '@angular/localize'; +import type { LabelProviderRichText } from '../nimble-label-provider-rich-text.directive'; +import { NimbleLabelProviderRichTextModule } from '../nimble-label-provider-rich-text.module'; + +describe('Nimble LabelProviderRichText withDefaults directive', () => { + @Component({ + template: ` + + + ` + }) + class TestHostComponent { + @ViewChild('labelProvider', { static: true }) public labelProvider: ElementRef; + } + + let labelProvider: LabelProviderRichText; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [TestHostComponent], + imports: [NimbleLabelProviderRichTextModule, CommonModule] + }); + }); + + beforeEach(() => { + loadTranslations({ + [computeMsgId('Bold', 'Nimble rich text - toggle bold')]: 'Translated Bold', + [computeMsgId('Italics', 'Nimble rich text - toggle italics')]: 'Translated Italics', + [computeMsgId('Bulleted List', 'Nimble rich text - toggle bulleted list')]: 'Translated Bulleted List', + [computeMsgId('Numbered List', 'Nimble rich text - toggle numbered list')]: 'Translated Numbered List', + }); + const fixture = TestBed.createComponent(TestHostComponent); + const testHostComponent = fixture.componentInstance; + labelProvider = testHostComponent.labelProvider.nativeElement; + fixture.detectChanges(); + }); + + it('applies translated values for each label', () => { + expect(labelProvider.toggleBold).toBe('Translated Bold'); + expect(labelProvider.toggleItalics).toBe('Translated Italics'); + expect(labelProvider.toggleBulletedList).toBe('Translated Bulleted List'); + expect(labelProvider.toggleNumberedList).toBe('Translated Numbered List'); + }); +}); diff --git a/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/tests/nimble-label-provider-rich-text.directive.spec.ts b/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/tests/nimble-label-provider-rich-text.directive.spec.ts new file mode 100644 index 0000000000..759041008f --- /dev/null +++ b/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/tests/nimble-label-provider-rich-text.directive.spec.ts @@ -0,0 +1,283 @@ +import { Component, ElementRef, ViewChild } from '@angular/core'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { LabelProviderRichText, NimbleLabelProviderRichTextDirective } from '../nimble-label-provider-rich-text.directive'; +import { NimbleLabelProviderRichTextModule } from '../nimble-label-provider-rich-text.module'; + +describe('Nimble Label Provider Rich text', () => { + const label1 = 'String 1'; + const label2 = 'String 2'; + const label3 = 'String 3'; + const label4 = 'String 4'; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [NimbleLabelProviderRichTextModule] + }); + }); + + it('custom element is defined', () => { + expect(customElements.get('nimble-label-provider-rich-text')).not.toBeUndefined(); + }); + + describe('with no values in template', () => { + @Component({ + template: ` + + ` + }) + class TestHostComponent { + @ViewChild('labelProvider', { read: NimbleLabelProviderRichTextDirective }) public directive: NimbleLabelProviderRichTextDirective; + @ViewChild('labelProvider', { read: ElementRef }) public elementRef: ElementRef; + } + + let fixture: ComponentFixture; + let directive: NimbleLabelProviderRichTextDirective; + let nativeElement: LabelProviderRichText; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [TestHostComponent], + imports: [NimbleLabelProviderRichTextModule] + }); + fixture = TestBed.createComponent(TestHostComponent); + fixture.detectChanges(); + directive = fixture.componentInstance.directive; + nativeElement = fixture.componentInstance.elementRef.nativeElement; + }); + + it('has expected defaults for toggleBold', () => { + expect(directive.toggleBold).toBeUndefined(); + expect(nativeElement.toggleBold).toBeUndefined(); + }); + + it('has expected defaults for toggleItalics', () => { + expect(directive.toggleItalics).toBeUndefined(); + expect(nativeElement.toggleItalics).toBeUndefined(); + }); + + it('has expected defaults for toggleBulletedList', () => { + expect(directive.toggleBulletedList).toBeUndefined(); + expect(nativeElement.toggleBulletedList).toBeUndefined(); + }); + + it('has expected defaults for toggleNumberedList', () => { + expect(directive.toggleNumberedList).toBeUndefined(); + expect(nativeElement.toggleNumberedList).toBeUndefined(); + }); + }); + + describe('with template string values', () => { + @Component({ + template: ` + + + ` + }) + class TestHostComponent { + @ViewChild('labelProvider', { read: NimbleLabelProviderRichTextDirective }) public directive: NimbleLabelProviderRichTextDirective; + @ViewChild('labelProvider', { read: ElementRef }) public elementRef: ElementRef; + } + + let fixture: ComponentFixture; + let directive: NimbleLabelProviderRichTextDirective; + let nativeElement: LabelProviderRichText; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [TestHostComponent], + imports: [NimbleLabelProviderRichTextModule] + }); + fixture = TestBed.createComponent(TestHostComponent); + fixture.detectChanges(); + directive = fixture.componentInstance.directive; + nativeElement = fixture.componentInstance.elementRef.nativeElement; + }); + + it('will use template string values for toggleBold', () => { + expect(directive.toggleBold).toBe(label1); + expect(nativeElement.toggleBold).toBe(label1); + }); + + it('will use template string values for toggleItalics', () => { + expect(directive.toggleItalics).toBe(label2); + expect(nativeElement.toggleItalics).toBe(label2); + }); + + it('will use template string values for toggleBulletedList', () => { + expect(directive.toggleBulletedList).toBe(label3); + expect(nativeElement.toggleBulletedList).toBe(label3); + }); + + it('will use template string values for toggleNumberedList', () => { + expect(directive.toggleNumberedList).toBe(label4); + expect(nativeElement.toggleNumberedList).toBe(label4); + }); + }); + + describe('with property bound values', () => { + @Component({ + template: ` + + + ` + }) + class TestHostComponent { + @ViewChild('labelProvider', { read: NimbleLabelProviderRichTextDirective }) public directive: NimbleLabelProviderRichTextDirective; + @ViewChild('labelProvider', { read: ElementRef }) public elementRef: ElementRef; + public toggleBold = label1; + public toggleItalics = label1; + public toggleBulletedList = label1; + public toggleNumberedList = label1; + } + + let fixture: ComponentFixture; + let directive: NimbleLabelProviderRichTextDirective; + let nativeElement: LabelProviderRichText; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [TestHostComponent], + imports: [NimbleLabelProviderRichTextModule] + }); + fixture = TestBed.createComponent(TestHostComponent); + fixture.detectChanges(); + directive = fixture.componentInstance.directive; + nativeElement = fixture.componentInstance.elementRef.nativeElement; + }); + + it('can be configured with property binding for toggleBold', () => { + expect(directive.toggleBold).toBe(label1); + expect(nativeElement.toggleBold).toBe(label1); + + fixture.componentInstance.toggleBold = label2; + fixture.detectChanges(); + + expect(directive.toggleBold).toBe(label2); + expect(nativeElement.toggleBold).toBe(label2); + }); + + it('can be configured with property binding for toggleItalics', () => { + expect(directive.toggleItalics).toBe(label1); + expect(nativeElement.toggleItalics).toBe(label1); + + fixture.componentInstance.toggleItalics = label2; + fixture.detectChanges(); + + expect(directive.toggleItalics).toBe(label2); + expect(nativeElement.toggleItalics).toBe(label2); + }); + + it('can be configured with property binding for toggleBulletedList', () => { + expect(directive.toggleBulletedList).toBe(label1); + expect(nativeElement.toggleBulletedList).toBe(label1); + + fixture.componentInstance.toggleBulletedList = label2; + fixture.detectChanges(); + + expect(directive.toggleBulletedList).toBe(label2); + expect(nativeElement.toggleBulletedList).toBe(label2); + }); + + it('can be configured with property binding for toggleNumberedList', () => { + expect(directive.toggleNumberedList).toBe(label1); + expect(nativeElement.toggleNumberedList).toBe(label1); + + fixture.componentInstance.toggleNumberedList = label2; + fixture.detectChanges(); + + expect(directive.toggleNumberedList).toBe(label2); + expect(nativeElement.toggleNumberedList).toBe(label2); + }); + }); + + describe('with attribute bound values', () => { + @Component({ + template: ` + + + ` + }) + class TestHostComponent { + @ViewChild('labelProvider', { read: NimbleLabelProviderRichTextDirective }) public directive: NimbleLabelProviderRichTextDirective; + @ViewChild('labelProvider', { read: ElementRef }) public elementRef: ElementRef; + public toggleBold = label1; + public toggleItalics = label1; + public toggleBulletedList = label1; + public toggleNumberedList = label1; + } + + let fixture: ComponentFixture; + let directive: NimbleLabelProviderRichTextDirective; + let nativeElement: LabelProviderRichText; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [TestHostComponent], + imports: [NimbleLabelProviderRichTextModule] + }); + fixture = TestBed.createComponent(TestHostComponent); + fixture.detectChanges(); + directive = fixture.componentInstance.directive; + nativeElement = fixture.componentInstance.elementRef.nativeElement; + }); + + it('can be configured with attribute binding for toggleBold', () => { + expect(directive.toggleBold).toBe(label1); + expect(nativeElement.toggleBold).toBe(label1); + + fixture.componentInstance.toggleBold = label2; + fixture.detectChanges(); + + expect(directive.toggleBold).toBe(label2); + expect(nativeElement.toggleBold).toBe(label2); + }); + + it('can be configured with attribute binding for toggleItalics', () => { + expect(directive.toggleItalics).toBe(label1); + expect(nativeElement.toggleItalics).toBe(label1); + + fixture.componentInstance.toggleItalics = label2; + fixture.detectChanges(); + + expect(directive.toggleItalics).toBe(label2); + expect(nativeElement.toggleItalics).toBe(label2); + }); + + it('can be configured with attribute binding for toggleBulletedList', () => { + expect(directive.toggleBulletedList).toBe(label1); + expect(nativeElement.toggleBulletedList).toBe(label1); + + fixture.componentInstance.toggleBulletedList = label2; + fixture.detectChanges(); + + expect(directive.toggleBulletedList).toBe(label2); + expect(nativeElement.toggleBulletedList).toBe(label2); + }); + + it('can be configured with attribute binding for toggleNumberedList', () => { + expect(directive.toggleNumberedList).toBe(label1); + expect(nativeElement.toggleNumberedList).toBe(label1); + + fixture.componentInstance.toggleNumberedList = label2; + fixture.detectChanges(); + + expect(directive.toggleNumberedList).toBe(label2); + expect(nativeElement.toggleNumberedList).toBe(label2); + }); + }); +}); From 742eadd9fa5f4039581b59090be654d0459ada00 Mon Sep 17 00:00:00 2001 From: Aagash Raaj <123377167+aagash-ni@users.noreply.github.com> Date: Fri, 1 Sep 2023 11:52:13 +0530 Subject: [PATCH 13/19] Rename folder --- .../{rich-text-editor => rich-text}/ng-package.json | 0 .../nimble-label-provider-rich-text-with-defaults.directive.ts | 0 .../nimble-label-provider-rich-text.directive.ts | 0 .../nimble-label-provider-rich-text.module.ts | 0 .../label-provider/{rich-text-editor => rich-text}/public-api.ts | 0 ...imble-label-provider-rich-text-with-defaults.directive.spec.ts | 0 .../tests/nimble-label-provider-rich-text.directive.spec.ts | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename angular-workspace/projects/ni/nimble-angular/label-provider/{rich-text-editor => rich-text}/ng-package.json (100%) rename angular-workspace/projects/ni/nimble-angular/label-provider/{rich-text-editor => rich-text}/nimble-label-provider-rich-text-with-defaults.directive.ts (100%) rename angular-workspace/projects/ni/nimble-angular/label-provider/{rich-text-editor => rich-text}/nimble-label-provider-rich-text.directive.ts (100%) rename angular-workspace/projects/ni/nimble-angular/label-provider/{rich-text-editor => rich-text}/nimble-label-provider-rich-text.module.ts (100%) rename angular-workspace/projects/ni/nimble-angular/label-provider/{rich-text-editor => rich-text}/public-api.ts (100%) rename angular-workspace/projects/ni/nimble-angular/label-provider/{rich-text-editor => rich-text}/tests/nimble-label-provider-rich-text-with-defaults.directive.spec.ts (100%) rename angular-workspace/projects/ni/nimble-angular/label-provider/{rich-text-editor => rich-text}/tests/nimble-label-provider-rich-text.directive.spec.ts (100%) diff --git a/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/ng-package.json b/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text/ng-package.json similarity index 100% rename from angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/ng-package.json rename to angular-workspace/projects/ni/nimble-angular/label-provider/rich-text/ng-package.json diff --git a/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/nimble-label-provider-rich-text-with-defaults.directive.ts b/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text/nimble-label-provider-rich-text-with-defaults.directive.ts similarity index 100% rename from angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/nimble-label-provider-rich-text-with-defaults.directive.ts rename to angular-workspace/projects/ni/nimble-angular/label-provider/rich-text/nimble-label-provider-rich-text-with-defaults.directive.ts diff --git a/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/nimble-label-provider-rich-text.directive.ts b/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text/nimble-label-provider-rich-text.directive.ts similarity index 100% rename from angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/nimble-label-provider-rich-text.directive.ts rename to angular-workspace/projects/ni/nimble-angular/label-provider/rich-text/nimble-label-provider-rich-text.directive.ts diff --git a/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/nimble-label-provider-rich-text.module.ts b/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text/nimble-label-provider-rich-text.module.ts similarity index 100% rename from angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/nimble-label-provider-rich-text.module.ts rename to angular-workspace/projects/ni/nimble-angular/label-provider/rich-text/nimble-label-provider-rich-text.module.ts diff --git a/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/public-api.ts b/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text/public-api.ts similarity index 100% rename from angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/public-api.ts rename to angular-workspace/projects/ni/nimble-angular/label-provider/rich-text/public-api.ts diff --git a/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/tests/nimble-label-provider-rich-text-with-defaults.directive.spec.ts b/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text/tests/nimble-label-provider-rich-text-with-defaults.directive.spec.ts similarity index 100% rename from angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/tests/nimble-label-provider-rich-text-with-defaults.directive.spec.ts rename to angular-workspace/projects/ni/nimble-angular/label-provider/rich-text/tests/nimble-label-provider-rich-text-with-defaults.directive.spec.ts diff --git a/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/tests/nimble-label-provider-rich-text.directive.spec.ts b/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text/tests/nimble-label-provider-rich-text.directive.spec.ts similarity index 100% rename from angular-workspace/projects/ni/nimble-angular/label-provider/rich-text-editor/tests/nimble-label-provider-rich-text.directive.spec.ts rename to angular-workspace/projects/ni/nimble-angular/label-provider/rich-text/tests/nimble-label-provider-rich-text.directive.spec.ts From a1b4409faa9f2dda4bd5fee49d433fc3968bab4b Mon Sep 17 00:00:00 2001 From: Aagash Raaj <123377167+aagash-ni@users.noreply.github.com> Date: Fri, 1 Sep 2023 12:01:40 +0530 Subject: [PATCH 14/19] Update import in app module --- .../projects/example-client-app/src/app/app.module.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/angular-workspace/projects/example-client-app/src/app/app.module.ts b/angular-workspace/projects/example-client-app/src/app/app.module.ts index ef04893163..bca2cc7d80 100644 --- a/angular-workspace/projects/example-client-app/src/app/app.module.ts +++ b/angular-workspace/projects/example-client-app/src/app/app.module.ts @@ -11,7 +11,7 @@ import { NimbleTextAreaModule, NimbleTextFieldModule, NimbleNumberFieldModule, N NimbleAnchorModule, NimbleAnchorButtonModule, NimbleAnchorTabModule, NimbleAnchorTabsModule, NimbleIconCheckModule, NimbleBannerModule, NimbleAnchorMenuItemModule, NimbleAnchorTreeItemModule } from '@ni/nimble-angular'; import { NimbleLabelProviderCoreModule } from '@ni/nimble-angular/label-provider/core'; -import { NimbleLabelProviderRichTextModule } from '@ni/nimble-angular/label-provider/rich-text-editor'; +import { NimbleLabelProviderRichTextModule } from '@ni/nimble-angular/label-provider/rich-text'; import { NimbleLabelProviderTableModule } from '@ni/nimble-angular/label-provider/table'; import { NimbleMappingTextModule } from '@ni/nimble-angular/mapping/text'; import { NimbleMappingIconModule } from '@ni/nimble-angular/mapping/icon'; From 68a02fabf1e4599916ac78cd8f83e4e9400db4b6 Mon Sep 17 00:00:00 2001 From: Aagash Raaj <123377167+aagash-ni@users.noreply.github.com> Date: Fri, 1 Sep 2023 12:04:33 +0530 Subject: [PATCH 15/19] Change files --- ...imble-angular-1c21fd5b-5570-420d-908a-574c88d5db06.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 change/@ni-nimble-angular-1c21fd5b-5570-420d-908a-574c88d5db06.json diff --git a/change/@ni-nimble-angular-1c21fd5b-5570-420d-908a-574c88d5db06.json b/change/@ni-nimble-angular-1c21fd5b-5570-420d-908a-574c88d5db06.json new file mode 100644 index 0000000000..b926f2f473 --- /dev/null +++ b/change/@ni-nimble-angular-1c21fd5b-5570-420d-908a-574c88d5db06.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "Angular Integration for rich text label provider", + "packageName": "@ni/nimble-angular", + "email": "123377167+aagash-ni@users.noreply.github.com", + "dependentChangeType": "patch" +} From a7d29659dadd2395471c560aecf3b848b6a942d6 Mon Sep 17 00:00:00 2001 From: Aagash Raaj <123377167+aagash-ni@users.noreply.github.com> Date: Fri, 1 Sep 2023 14:32:57 +0530 Subject: [PATCH 16/19] Minor Fix --- angular-workspace/projects/ni/nimble-angular/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/angular-workspace/projects/ni/nimble-angular/README.md b/angular-workspace/projects/ni/nimble-angular/README.md index e19d481990..044a00995c 100644 --- a/angular-workspace/projects/ni/nimble-angular/README.md +++ b/angular-workspace/projects/ni/nimble-angular/README.md @@ -95,7 +95,7 @@ The standard way to use these in Angular (for localized apps using `@angular/loc - `NimbleLabelProviderCoreModule` from `@ni/nimble-angular/label-provider/core`: Used for labels for all components besides the table - `NimbleLabelProviderRichTextModule` from `@ni/nimble-angular/label-provider/rich-text`: Used for labels for the rich text components - `NimbleLabelProviderTableModule` from `@ni/nimble-angular/label-provider/table`: Used for labels for the table (and table sub-components / column types) -2. To use the Nimble-provided strings (which are already declared with `$localize`), use the `NimbleLabelProvider[Core/Table]WithDefaultsDirective`: +2. To use the Nimble-provided strings (which are already declared with `$localize`), use the `NimbleLabelProvider[Core/Table/RichText]WithDefaultsDirective`: ```html From 90c792cdcb84b8281a84fde365a7d77659d496fc Mon Sep 17 00:00:00 2001 From: Aagash Raaj <123377167+aagash-ni@users.noreply.github.com> Date: Mon, 4 Sep 2023 19:04:57 +0530 Subject: [PATCH 17/19] Address PR comments --- angular-workspace/projects/ni/nimble-angular/README.md | 2 +- ...le-label-provider-rich-text-with-defaults.directive.spec.ts | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/angular-workspace/projects/ni/nimble-angular/README.md b/angular-workspace/projects/ni/nimble-angular/README.md index 044a00995c..310577cb71 100644 --- a/angular-workspace/projects/ni/nimble-angular/README.md +++ b/angular-workspace/projects/ni/nimble-angular/README.md @@ -92,7 +92,7 @@ Most user-visible strings displayed by Nimble components are provided by the cli The standard way to use these in Angular (for localized apps using `@angular/localize`) is: 1. Import the label provider module(s) from your app module: - - `NimbleLabelProviderCoreModule` from `@ni/nimble-angular/label-provider/core`: Used for labels for all components besides the table + - `NimbleLabelProviderCoreModule` from `@ni/nimble-angular/label-provider/core`: Used for labels for all components that do not have a dedicated label provider - `NimbleLabelProviderRichTextModule` from `@ni/nimble-angular/label-provider/rich-text`: Used for labels for the rich text components - `NimbleLabelProviderTableModule` from `@ni/nimble-angular/label-provider/table`: Used for labels for the table (and table sub-components / column types) 2. To use the Nimble-provided strings (which are already declared with `$localize`), use the `NimbleLabelProvider[Core/Table/RichText]WithDefaultsDirective`: diff --git a/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text/tests/nimble-label-provider-rich-text-with-defaults.directive.spec.ts b/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text/tests/nimble-label-provider-rich-text-with-defaults.directive.spec.ts index a7017543e8..b773a4babb 100644 --- a/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text/tests/nimble-label-provider-rich-text-with-defaults.directive.spec.ts +++ b/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text/tests/nimble-label-provider-rich-text-with-defaults.directive.spec.ts @@ -24,9 +24,6 @@ describe('Nimble LabelProviderRichText withDefaults directive', () => { declarations: [TestHostComponent], imports: [NimbleLabelProviderRichTextModule, CommonModule] }); - }); - - beforeEach(() => { loadTranslations({ [computeMsgId('Bold', 'Nimble rich text - toggle bold')]: 'Translated Bold', [computeMsgId('Italics', 'Nimble rich text - toggle italics')]: 'Translated Italics', From 7d98432800ddb59eeba480da66c37d3037d779bb Mon Sep 17 00:00:00 2001 From: Aagash Raaj <123377167+aagash-ni@users.noreply.github.com> Date: Tue, 5 Sep 2023 10:30:39 +0530 Subject: [PATCH 18/19] Address PR comments --- ...label-provider-rich-text.directive.spec.ts | 128 +++++++++--------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text/tests/nimble-label-provider-rich-text.directive.spec.ts b/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text/tests/nimble-label-provider-rich-text.directive.spec.ts index 759041008f..9f95feae2b 100644 --- a/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text/tests/nimble-label-provider-rich-text.directive.spec.ts +++ b/angular-workspace/projects/ni/nimble-angular/label-provider/rich-text/tests/nimble-label-provider-rich-text.directive.spec.ts @@ -4,10 +4,10 @@ import { LabelProviderRichText, NimbleLabelProviderRichTextDirective } from '../ import { NimbleLabelProviderRichTextModule } from '../nimble-label-provider-rich-text.module'; describe('Nimble Label Provider Rich text', () => { - const label1 = 'String 1'; - const label2 = 'String 2'; - const label3 = 'String 3'; - const label4 = 'String 4'; + const boldLabel = 'Bold'; + const italicsLabel = 'Italics'; + const numberedListLabel = 'Numbered List'; + const bulletedListLabel = 'Bulleted List'; beforeEach(() => { TestBed.configureTestingModule({ @@ -70,10 +70,10 @@ describe('Nimble Label Provider Rich text', () => { @Component({ template: ` ` @@ -99,23 +99,23 @@ describe('Nimble Label Provider Rich text', () => { }); it('will use template string values for toggleBold', () => { - expect(directive.toggleBold).toBe(label1); - expect(nativeElement.toggleBold).toBe(label1); + expect(directive.toggleBold).toBe(boldLabel); + expect(nativeElement.toggleBold).toBe(boldLabel); }); it('will use template string values for toggleItalics', () => { - expect(directive.toggleItalics).toBe(label2); - expect(nativeElement.toggleItalics).toBe(label2); + expect(directive.toggleItalics).toBe(italicsLabel); + expect(nativeElement.toggleItalics).toBe(italicsLabel); }); it('will use template string values for toggleBulletedList', () => { - expect(directive.toggleBulletedList).toBe(label3); - expect(nativeElement.toggleBulletedList).toBe(label3); + expect(directive.toggleBulletedList).toBe(bulletedListLabel); + expect(nativeElement.toggleBulletedList).toBe(bulletedListLabel); }); it('will use template string values for toggleNumberedList', () => { - expect(directive.toggleNumberedList).toBe(label4); - expect(nativeElement.toggleNumberedList).toBe(label4); + expect(directive.toggleNumberedList).toBe(numberedListLabel); + expect(nativeElement.toggleNumberedList).toBe(numberedListLabel); }); }); @@ -134,10 +134,10 @@ describe('Nimble Label Provider Rich text', () => { class TestHostComponent { @ViewChild('labelProvider', { read: NimbleLabelProviderRichTextDirective }) public directive: NimbleLabelProviderRichTextDirective; @ViewChild('labelProvider', { read: ElementRef }) public elementRef: ElementRef; - public toggleBold = label1; - public toggleItalics = label1; - public toggleBulletedList = label1; - public toggleNumberedList = label1; + public toggleBold = boldLabel; + public toggleItalics = italicsLabel; + public toggleBulletedList = bulletedListLabel; + public toggleNumberedList = numberedListLabel; } let fixture: ComponentFixture; @@ -156,47 +156,47 @@ describe('Nimble Label Provider Rich text', () => { }); it('can be configured with property binding for toggleBold', () => { - expect(directive.toggleBold).toBe(label1); - expect(nativeElement.toggleBold).toBe(label1); + expect(directive.toggleBold).toBe(boldLabel); + expect(nativeElement.toggleBold).toBe(boldLabel); - fixture.componentInstance.toggleBold = label2; + fixture.componentInstance.toggleBold = 'newBoldLabel'; fixture.detectChanges(); - expect(directive.toggleBold).toBe(label2); - expect(nativeElement.toggleBold).toBe(label2); + expect(directive.toggleBold).toBe('newBoldLabel'); + expect(nativeElement.toggleBold).toBe('newBoldLabel'); }); it('can be configured with property binding for toggleItalics', () => { - expect(directive.toggleItalics).toBe(label1); - expect(nativeElement.toggleItalics).toBe(label1); + expect(directive.toggleItalics).toBe(italicsLabel); + expect(nativeElement.toggleItalics).toBe(italicsLabel); - fixture.componentInstance.toggleItalics = label2; + fixture.componentInstance.toggleItalics = 'newItalicsLabel'; fixture.detectChanges(); - expect(directive.toggleItalics).toBe(label2); - expect(nativeElement.toggleItalics).toBe(label2); + expect(directive.toggleItalics).toBe('newItalicsLabel'); + expect(nativeElement.toggleItalics).toBe('newItalicsLabel'); }); it('can be configured with property binding for toggleBulletedList', () => { - expect(directive.toggleBulletedList).toBe(label1); - expect(nativeElement.toggleBulletedList).toBe(label1); + expect(directive.toggleBulletedList).toBe(bulletedListLabel); + expect(nativeElement.toggleBulletedList).toBe(bulletedListLabel); - fixture.componentInstance.toggleBulletedList = label2; + fixture.componentInstance.toggleBulletedList = 'newBulletedListLabel'; fixture.detectChanges(); - expect(directive.toggleBulletedList).toBe(label2); - expect(nativeElement.toggleBulletedList).toBe(label2); + expect(directive.toggleBulletedList).toBe('newBulletedListLabel'); + expect(nativeElement.toggleBulletedList).toBe('newBulletedListLabel'); }); it('can be configured with property binding for toggleNumberedList', () => { - expect(directive.toggleNumberedList).toBe(label1); - expect(nativeElement.toggleNumberedList).toBe(label1); + expect(directive.toggleNumberedList).toBe(numberedListLabel); + expect(nativeElement.toggleNumberedList).toBe(numberedListLabel); - fixture.componentInstance.toggleNumberedList = label2; + fixture.componentInstance.toggleNumberedList = 'newNumberedListLabel'; fixture.detectChanges(); - expect(directive.toggleNumberedList).toBe(label2); - expect(nativeElement.toggleNumberedList).toBe(label2); + expect(directive.toggleNumberedList).toBe('newNumberedListLabel'); + expect(nativeElement.toggleNumberedList).toBe('newNumberedListLabel'); }); }); @@ -215,10 +215,10 @@ describe('Nimble Label Provider Rich text', () => { class TestHostComponent { @ViewChild('labelProvider', { read: NimbleLabelProviderRichTextDirective }) public directive: NimbleLabelProviderRichTextDirective; @ViewChild('labelProvider', { read: ElementRef }) public elementRef: ElementRef; - public toggleBold = label1; - public toggleItalics = label1; - public toggleBulletedList = label1; - public toggleNumberedList = label1; + public toggleBold = boldLabel; + public toggleItalics = italicsLabel; + public toggleBulletedList = bulletedListLabel; + public toggleNumberedList = numberedListLabel; } let fixture: ComponentFixture; @@ -237,47 +237,47 @@ describe('Nimble Label Provider Rich text', () => { }); it('can be configured with attribute binding for toggleBold', () => { - expect(directive.toggleBold).toBe(label1); - expect(nativeElement.toggleBold).toBe(label1); + expect(directive.toggleBold).toBe(boldLabel); + expect(nativeElement.toggleBold).toBe(boldLabel); - fixture.componentInstance.toggleBold = label2; + fixture.componentInstance.toggleBold = 'newBoldLabel'; fixture.detectChanges(); - expect(directive.toggleBold).toBe(label2); - expect(nativeElement.toggleBold).toBe(label2); + expect(directive.toggleBold).toBe('newBoldLabel'); + expect(nativeElement.toggleBold).toBe('newBoldLabel'); }); it('can be configured with attribute binding for toggleItalics', () => { - expect(directive.toggleItalics).toBe(label1); - expect(nativeElement.toggleItalics).toBe(label1); + expect(directive.toggleItalics).toBe(italicsLabel); + expect(nativeElement.toggleItalics).toBe(italicsLabel); - fixture.componentInstance.toggleItalics = label2; + fixture.componentInstance.toggleItalics = 'newItalicsLabel'; fixture.detectChanges(); - expect(directive.toggleItalics).toBe(label2); - expect(nativeElement.toggleItalics).toBe(label2); + expect(directive.toggleItalics).toBe('newItalicsLabel'); + expect(nativeElement.toggleItalics).toBe('newItalicsLabel'); }); it('can be configured with attribute binding for toggleBulletedList', () => { - expect(directive.toggleBulletedList).toBe(label1); - expect(nativeElement.toggleBulletedList).toBe(label1); + expect(directive.toggleBulletedList).toBe(bulletedListLabel); + expect(nativeElement.toggleBulletedList).toBe(bulletedListLabel); - fixture.componentInstance.toggleBulletedList = label2; + fixture.componentInstance.toggleBulletedList = 'newBulletedListLabel'; fixture.detectChanges(); - expect(directive.toggleBulletedList).toBe(label2); - expect(nativeElement.toggleBulletedList).toBe(label2); + expect(directive.toggleBulletedList).toBe('newBulletedListLabel'); + expect(nativeElement.toggleBulletedList).toBe('newBulletedListLabel'); }); it('can be configured with attribute binding for toggleNumberedList', () => { - expect(directive.toggleNumberedList).toBe(label1); - expect(nativeElement.toggleNumberedList).toBe(label1); + expect(directive.toggleNumberedList).toBe(numberedListLabel); + expect(nativeElement.toggleNumberedList).toBe(numberedListLabel); - fixture.componentInstance.toggleNumberedList = label2; + fixture.componentInstance.toggleNumberedList = 'newNumberedListLabel'; fixture.detectChanges(); - expect(directive.toggleNumberedList).toBe(label2); - expect(nativeElement.toggleNumberedList).toBe(label2); + expect(directive.toggleNumberedList).toBe('newNumberedListLabel'); + expect(nativeElement.toggleNumberedList).toBe('newNumberedListLabel'); }); }); }); From 80d5f150c9d70c22d221f2af5862e511d51838c7 Mon Sep 17 00:00:00 2001 From: Aagash Raaj <123377167+aagash-ni@users.noreply.github.com> Date: Wed, 6 Sep 2023 19:25:32 +0530 Subject: [PATCH 19/19] Remove chnage file --- ...le-components-68c4b395-98d1-4e9b-bda3-ba58ff53d17c.json | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 change/@ni-nimble-components-68c4b395-98d1-4e9b-bda3-ba58ff53d17c.json diff --git a/change/@ni-nimble-components-68c4b395-98d1-4e9b-bda3-ba58ff53d17c.json b/change/@ni-nimble-components-68c4b395-98d1-4e9b-bda3-ba58ff53d17c.json deleted file mode 100644 index 614f055950..0000000000 --- a/change/@ni-nimble-components-68c4b395-98d1-4e9b-bda3-ba58ff53d17c.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "type": "patch", - "comment": "Add label provider for rich-text-editor", - "packageName": "@ni/nimble-components", - "email": "123377167+aagash-ni@users.noreply.github.com", - "dependentChangeType": "patch" -}