diff --git a/apps/docs/_data/components.json b/apps/docs/_data/components.json index 629f0dd02d..5b6f4be56a 100644 --- a/apps/docs/_data/components.json +++ b/apps/docs/_data/components.json @@ -281,9 +281,9 @@ }, { "title": "option", - "markdown": "./libs/components/src/lib/listbox-option/README.md", + "markdown": "./libs/components/src/lib/option/README.md", "modules": [ - "/assets/modules/components/listbox-option/index.js", + "/assets/modules/components/option/index.js", "/assets/modules/components/listbox/index.js" ] }, @@ -292,7 +292,7 @@ "status": "alpha", "markdown": "./libs/components/src/lib/listbox/README.md", "modules": [ - "/assets/modules/components/listbox-option/index.js", + "/assets/modules/components/option/index.js", "/assets/modules/components/listbox/index.js" ] }, diff --git a/change/@vonage-nx-vivid-138899ae-8f78-49cb-8e9b-c1e17817ea91.json b/change/@vonage-nx-vivid-138899ae-8f78-49cb-8e9b-c1e17817ea91.json new file mode 100644 index 0000000000..e04de9fe19 --- /dev/null +++ b/change/@vonage-nx-vivid-138899ae-8f78-49cb-8e9b-c1e17817ea91.json @@ -0,0 +1,7 @@ +{ + "comment": "align with custom prefix for custom-elements support", + "type": "none", + "packageName": "@vonage/nx-vivid", + "email": "yinon@hotmail.com", + "dependentChangeType": "none" +} diff --git a/change/@vonage-vivid-dcd48901-44d8-4cd1-82fb-dca16b03db6f.json b/change/@vonage-vivid-dcd48901-44d8-4cd1-82fb-dca16b03db6f.json new file mode 100644 index 0000000000..1ba5d49096 --- /dev/null +++ b/change/@vonage-vivid-dcd48901-44d8-4cd1-82fb-dca16b03db6f.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "enable custom prefix for custom-elements", + "packageName": "@vonage/vivid", + "email": "yinon@hotmail.com", + "dependentChangeType": "patch" +} diff --git a/libs/components/README.md b/libs/components/README.md index 512357669a..48d89ba076 100644 --- a/libs/components/README.md +++ b/libs/components/README.md @@ -75,6 +75,30 @@ Note: scss users can simply [forward](https://sass-lang.com/documentation/at-rul @forward 'node_modules/@vonage/vivid/styles/[path to file].css'; ``` +## Advanced Usage + +### Scoped Elements + +Custom elements, by browsers limitations, are registered globally, and thus may conflict when multiple versions of the library are used in the same application as all custom elements register under the same namespace. + +This burdens micro frontend architecture and updates to outdated versions of the Vivid, enforcing a single version of the library to be used. Meaning, any update to the library will require a full application update. + +To avoid this bottleneck, Vivid provides a way for authors' to scope each custom element namespace by setting a `prefix` query parameter to their import call. + +The following example will register *badge* custom element as `dashboard-badge`: + +```js +import '/node_modules/@vonage/vivid/badge/index.js?prefix=dashboard'; +``` + +then use it as: + +```html + +``` + +Even though the custom elements are registered under different namespaces, [npm packages version range handling](https://docs.npmjs.com/cli/v7/configuring-npm/package-json#dependencies) can still be used for multiple versions saving. + ## Support This library is open source, developed and maintained by the [Vonage Vivid team](Vonage/vivid). diff --git a/libs/components/jest.config.cjs b/libs/components/jest.config.cjs index e697f26f69..92089ca5c5 100644 --- a/libs/components/jest.config.cjs +++ b/libs/components/jest.config.cjs @@ -2,19 +2,32 @@ module.exports = { displayName: 'components', preset: '../../jest.preset.js', testEnvironment: 'jsdom', + extensionsToTreatAsEsm: ['.ts',], globals: { 'ts-jest': { + useESM: true, tsconfig: '/tsconfig.spec.json', + diagnostics: { + ignoreCodes: [1343] + }, + astTransformers: { + before: [ + { + path: 'node_modules/ts-jest-mock-import-meta', + options: { metaObjectReplacement: { url: 'https://www.url.com' } } + } + ], + } }, }, transform: { '^.+\\.[tj]s?$': 'ts-jest', }, transformIgnorePatterns: [ - "/node_modules/(?!(@microsoft|exenv-es6)/)" + '/node_modules/(?!(@microsoft|exenv-es6|@vivid-nx)/)' ], moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], coverageDirectory: '../../coverage/libs/components', - testMatch: [ "**/__tests__/**/*.[jt]s?(x)", "**/?(*.)+(spec).[jt]s?(x)", "!**/?(*.)+(config.spec).[jt]s?(x)" ], - setupFilesAfterEnv: ["/setupJestTests.js"] + testMatch: ['**/__tests__/**/*.[jt]s?(x)', '**/?(*.)+(spec).[jt]s?(x)', '!**/?(*.)+(config.spec).[jt]s?(x)'], + setupFilesAfterEnv: ['/setupJestTests.js'] }; diff --git a/libs/components/package.json b/libs/components/package.json index 9b83ead011..9b77923510 100644 --- a/libs/components/package.json +++ b/libs/components/package.json @@ -43,7 +43,7 @@ "./nav-item": "./nav-item", "./number-field": "./number-field", "./note": "./note", - "./option": "./listbox-option", + "./option": "./option", "./popup": "./popup", "./progress": "./progress", "./progress-ring": "./progress-ring", diff --git a/libs/components/setupJestTests.js b/libs/components/setupJestTests.js index 4cb0306f3b..2a992da150 100644 --- a/libs/components/setupJestTests.js +++ b/libs/components/setupJestTests.js @@ -1,10 +1,14 @@ -import * as jestFetchMock from 'jest-fetch-mock'; +// import * as jestFetchMock from 'jest-fetch-mock'; +// import { enableFetchMocks } from 'jest-fetch-mock'; +import { jest } from '@jest/globals'; +import fetchMock from 'jest-fetch-mock'; +import './src/shared/utils'; -jestFetchMock.enableFetchMocks(); +fetchMock.enableMocks(); Object.defineProperty(window, 'matchMedia', { writable: true, - value: jest.fn().mockImplementation((query: any) => ({ + value: jest.fn().mockImplementation((query) => ({ matches: false, media: query, onchange: null, @@ -15,3 +19,21 @@ Object.defineProperty(window, 'matchMedia', { dispatchEvent: jest.fn(), })), }); + +jest.mock('./src/shared/utils', () => { + const originalModule = jest.requireActual('./src/shared/utils'); + + //Mock the default export and named export 'foo' + return { + ...originalModule, + loadComponentsModules: jest.fn((components) => { + components.forEach((component) => import(`./src/lib/${component}/index.ts`)); + + return Promise.all( + components.map(component => + customElements.whenDefined(`vwc-${component}`) + ) + ); + }), + }; +}); diff --git a/libs/components/src/lib/accordion-item/accordion-item.spec.ts b/libs/components/src/lib/accordion-item/accordion-item.spec.ts index 3cf334550b..2a2704b21a 100644 --- a/libs/components/src/lib/accordion-item/accordion-item.spec.ts +++ b/libs/components/src/lib/accordion-item/accordion-item.spec.ts @@ -7,6 +7,10 @@ const COMPONENT_TAG = 'vwc-accordion-item'; describe('vwc-accordion-item', () => { let element: AccordionItem; + beforeAll(async () => { + await customElements.whenDefined(COMPONENT_TAG); + }); + beforeEach(async () => { element = (await fixture( `<${COMPONENT_TAG}>` diff --git a/libs/components/src/lib/accordion-item/index.ts b/libs/components/src/lib/accordion-item/index.ts index e4cdd8dbb7..2e9fbf97a2 100644 --- a/libs/components/src/lib/accordion-item/index.ts +++ b/libs/components/src/lib/accordion-item/index.ts @@ -1,13 +1,14 @@ -import '../icon'; -import '../focus'; - import type { FoundationElementDefinition } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; +import { loadComponentsModules } from '../../shared/utils'; import styles from './accordion-item.scss'; import { AccordionItem } from './accordion-item'; import { AccordionItemTemplate as template } from './accordion-item.template'; +const prefix = getPrefix(import.meta.url); +const dependencies = ['icon', 'focus']; + export const vividAccordionItem = AccordionItem.compose({ baseName: 'accordion-item', @@ -18,4 +19,8 @@ export const vividAccordionItem = }, }); -designSystem.register(vividAccordionItem()); +(async () => { + await loadComponentsModules(dependencies, prefix); + designSystem.withPrefix(prefix).register(vividAccordionItem()); +})(); + diff --git a/libs/components/src/lib/accordion/accordion.spec.ts b/libs/components/src/lib/accordion/accordion.spec.ts index f16fd310bc..fd1927cace 100644 --- a/libs/components/src/lib/accordion/accordion.spec.ts +++ b/libs/components/src/lib/accordion/accordion.spec.ts @@ -11,6 +11,10 @@ describe('vwc-accordion', () => { let accordionItem1: AccordionItem; let accordionItem2: AccordionItem; + beforeAll(async () => { + await customElements.whenDefined(COMPONENT_TAG); + }); + beforeEach(async () => { element = (await fixture( `<${COMPONENT_TAG}> diff --git a/libs/components/src/lib/accordion/index.ts b/libs/components/src/lib/accordion/index.ts index deb9ed4003..ea84548212 100644 --- a/libs/components/src/lib/accordion/index.ts +++ b/libs/components/src/lib/accordion/index.ts @@ -1,5 +1,5 @@ import type { FoundationElementDefinition } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; import styles from './accordion.scss'; import { Accordion } from './accordion'; @@ -11,4 +11,4 @@ export const vividAccordion = Accordion.compose({ styles, }); -designSystem.register(vividAccordion()); +designSystem.withPrefix(getPrefix(import.meta.url)).register(vividAccordion()); diff --git a/libs/components/src/lib/action-group/index.ts b/libs/components/src/lib/action-group/index.ts index c3a8c2c07c..784c690d7b 100644 --- a/libs/components/src/lib/action-group/index.ts +++ b/libs/components/src/lib/action-group/index.ts @@ -1,5 +1,5 @@ import type { FoundationElementDefinition } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; import styles from './action-group.scss'; import { ActionGroup } from './action-group'; @@ -11,4 +11,4 @@ export const vividActionGroup = ActionGroup.compose styles, }); -designSystem.register(vividActionGroup()); +designSystem.withPrefix(getPrefix(import.meta.url)).register(vividActionGroup()); diff --git a/libs/components/src/lib/avatar/avatar.spec.ts b/libs/components/src/lib/avatar/avatar.spec.ts index 35042b3d79..a43ed13dc6 100644 --- a/libs/components/src/lib/avatar/avatar.spec.ts +++ b/libs/components/src/lib/avatar/avatar.spec.ts @@ -9,6 +9,10 @@ describe('vwc-avatar', () => { let baseElement: Element; let element: Avatar; + beforeAll(async () => { + await customElements.whenDefined(COMPONENT_TAG); + }); + beforeEach(async () => { element = (await fixture( `<${COMPONENT_TAG}>` diff --git a/libs/components/src/lib/avatar/index.ts b/libs/components/src/lib/avatar/index.ts index a766f6dbf8..f9014e90f1 100644 --- a/libs/components/src/lib/avatar/index.ts +++ b/libs/components/src/lib/avatar/index.ts @@ -1,16 +1,21 @@ -import '../icon'; - import type { FoundationElementDefinition } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; +import { loadComponentsModules } from '../../shared/utils'; import styles from './avatar.scss'; import { Avatar } from './avatar'; import { AvatarTemplate as template } from './avatar.template'; +const prefix = getPrefix(import.meta.url); +const dependencies = ['icon']; + export const vividAvatar = Avatar.compose({ baseName: 'avatar', template: template as any, styles, }); -designSystem.register(vividAvatar()); +(async () => { + await loadComponentsModules(dependencies, prefix); + designSystem.withPrefix(prefix).register(vividAvatar()); +})(); diff --git a/libs/components/src/lib/badge/badge.spec.ts b/libs/components/src/lib/badge/badge.spec.ts index 9ed570bf33..1b8c264801 100644 --- a/libs/components/src/lib/badge/badge.spec.ts +++ b/libs/components/src/lib/badge/badge.spec.ts @@ -9,6 +9,10 @@ const ICON_SELECTOR = 'vwc-icon'; describe('vwc-badge', () => { let element: Badge; + beforeAll(async () => { + await customElements.whenDefined(COMPONENT_TAG); + }); + beforeEach(async () => { element = await fixture(`<${COMPONENT_TAG}>`) as Badge; }); diff --git a/libs/components/src/lib/badge/index.ts b/libs/components/src/lib/badge/index.ts index bfdcd44df9..617c007b09 100644 --- a/libs/components/src/lib/badge/index.ts +++ b/libs/components/src/lib/badge/index.ts @@ -1,11 +1,11 @@ -import '../icon'; - import type { FoundationElementDefinition } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; +import { loadComponentsModules } from '../../shared/utils'; import { Badge } from './badge'; import styles from './badge.scss'; import { badgeTemplate as template } from './badge.template'; +const prefix = getPrefix(import.meta.url); /** * Represents a badge custom element. @@ -20,4 +20,7 @@ export const vividBadge = Badge.compose({ styles, }); -designSystem.register(vividBadge()); +(async () => { + await loadComponentsModules(['icon'], prefix); + designSystem.withPrefix(prefix).register(vividBadge()); +})(); diff --git a/libs/components/src/lib/banner/banner.spec.ts b/libs/components/src/lib/banner/banner.spec.ts index 56a81dea66..aef60424fc 100644 --- a/libs/components/src/lib/banner/banner.spec.ts +++ b/libs/components/src/lib/banner/banner.spec.ts @@ -29,6 +29,10 @@ describe('vwc-banner', () => { let element: Banner; + beforeAll(async () => { + await customElements.whenDefined(COMPONENT_TAG); + }); + beforeEach(async () => { element = (await fixture( `<${COMPONENT_TAG}>` diff --git a/libs/components/src/lib/banner/index.ts b/libs/components/src/lib/banner/index.ts index 42a7c5da1e..344e6d16a0 100644 --- a/libs/components/src/lib/banner/index.ts +++ b/libs/components/src/lib/banner/index.ts @@ -1,16 +1,20 @@ -import '../button'; - import type { FoundationElementDefinition } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; +import { loadComponentsModules } from '../../shared/utils'; import styles from './banner.scss'; import { Banner } from './banner'; import { BannerTemplate as template } from './banner.template'; +const prefix = getPrefix(import.meta.url); + export const vividBanner = Banner.compose({ baseName: 'banner', template: template as any, styles, }); -designSystem.register(vividBanner()); +(async () => { + await loadComponentsModules(['button'], prefix); + designSystem.withPrefix(prefix).register(vividBanner()); +})(); diff --git a/libs/components/src/lib/breadcrumb-item/index.ts b/libs/components/src/lib/breadcrumb-item/index.ts index fa92785ff3..fff99bd571 100644 --- a/libs/components/src/lib/breadcrumb-item/index.ts +++ b/libs/components/src/lib/breadcrumb-item/index.ts @@ -1,13 +1,13 @@ -import '../icon'; -import '../focus'; - import type { FoundationElementDefinition } from '@microsoft/fast-foundation'; -import {designSystem} from '../../shared/design-system'; +import {designSystem, getPrefix} from '../../shared/design-system'; +import { loadComponentsModules } from '../../shared/utils'; import styles from './breadcrumb-item.scss'; import {BreadcrumbItem} from './breadcrumb-item'; import {BreadcrumbItemTemplate as template} from './breadcrumb-item.template'; +const prefix = getPrefix(import.meta.url); + export const vividBreadcrumbItem = BreadcrumbItem.compose({ baseName: 'breadcrumb-item', template: template as any, @@ -17,4 +17,7 @@ export const vividBreadcrumbItem = BreadcrumbItem.compose { + await loadComponentsModules(['icon', 'focus'], prefix); + designSystem.withPrefix(prefix).register(vividBreadcrumbItem()); +})(); diff --git a/libs/components/src/lib/breadcrumb/index.ts b/libs/components/src/lib/breadcrumb/index.ts index 1076c6f8a9..ae78d4fad0 100644 --- a/libs/components/src/lib/breadcrumb/index.ts +++ b/libs/components/src/lib/breadcrumb/index.ts @@ -1,5 +1,5 @@ import type { FoundationElementDefinition } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; import { breadcrumbTemplate as template } from './breadcrumb.template'; import styles from './breadcrumb.scss'; import { Breadcrumb } from './breadcrumb'; @@ -10,4 +10,5 @@ export const vividBreadcrumb = Breadcrumb.compose({ styles, }); -designSystem.register(vividBreadcrumb()); +designSystem.withPrefix(getPrefix(import.meta.url)).register(vividBreadcrumb()); + diff --git a/libs/components/src/lib/button/button.spec.ts b/libs/components/src/lib/button/button.spec.ts index 2a87db0b6e..226b01f80f 100644 --- a/libs/components/src/lib/button/button.spec.ts +++ b/libs/components/src/lib/button/button.spec.ts @@ -1,7 +1,7 @@ import { elementUpdated, fixture } from '@vivid-nx/shared'; import type { Icon } from '../icon/icon'; import { Button } from './button'; -import '.'; +import '.'; const COMPONENT_TAG = 'vwc-button'; const ICON_SELECTOR = 'vwc-icon'; @@ -9,6 +9,10 @@ const ICON_SELECTOR = 'vwc-icon'; describe('vwc-button', () => { let element: Button; + beforeAll(async () => { + await customElements.whenDefined(COMPONENT_TAG); + }); + beforeEach(async () => { element = await fixture(`<${COMPONENT_TAG}>`) as Button; }); diff --git a/libs/components/src/lib/button/index.ts b/libs/components/src/lib/button/index.ts index ebfb86334e..f15e425293 100644 --- a/libs/components/src/lib/button/index.ts +++ b/libs/components/src/lib/button/index.ts @@ -1,18 +1,15 @@ -import '../icon'; -import '../focus'; - - -import { Button as FastButton, type FoundationElementDefinition } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { + Button as FastButton, + type FoundationElementDefinition, +} from '@microsoft/fast-foundation'; +import { designSystem, getPrefix } from '../../shared/design-system'; +import { loadComponentsModules } from '../../shared/utils'; import { Button } from './button'; import styles from './button.scss'; import { buttonTemplate as template } from './button.template'; -/** - * Represents a button custom element. - */ -export const vividButton = Button.compose({ +const vividButton = Button.compose({ baseName: 'button', baseClass: FastButton, template: template as any, @@ -22,4 +19,9 @@ export const vividButton = Button.compose({ }, }); -designSystem.register(vividButton()); +const prefix = getPrefix(import.meta.url); + +(async () => { + await loadComponentsModules(['icon', 'focus'], prefix); + designSystem.withPrefix(prefix).register(vividButton()); +})(); diff --git a/libs/components/src/lib/calendar-event/index.ts b/libs/components/src/lib/calendar-event/index.ts index ef71ea7eb7..fa94ee8947 100644 --- a/libs/components/src/lib/calendar-event/index.ts +++ b/libs/components/src/lib/calendar-event/index.ts @@ -1,5 +1,5 @@ import type { FoundationElementDefinition } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; import styles from './calendar-event.scss'; import { CalendarEvent } from './calendar-event'; @@ -15,4 +15,4 @@ export const vividCalendarEvent = } }); -designSystem.register(vividCalendarEvent()); +designSystem.withPrefix(getPrefix(import.meta.url)).register(vividCalendarEvent()); diff --git a/libs/components/src/lib/calendar/index.ts b/libs/components/src/lib/calendar/index.ts index cbdbeb8d50..b5ad92f454 100644 --- a/libs/components/src/lib/calendar/index.ts +++ b/libs/components/src/lib/calendar/index.ts @@ -1,5 +1,5 @@ import type { FoundationElementDefinition } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; import styles from './calendar.scss'; import { Calendar } from './calendar'; @@ -14,4 +14,4 @@ export const vividCalendar = Calendar.compose({ } }); -designSystem.register(vividCalendar()); +designSystem.withPrefix(getPrefix(import.meta.url)).register(vividCalendar()); diff --git a/libs/components/src/lib/card/index.ts b/libs/components/src/lib/card/index.ts index 7bc8db4cbc..0903915acc 100644 --- a/libs/components/src/lib/card/index.ts +++ b/libs/components/src/lib/card/index.ts @@ -1,17 +1,20 @@ -import '../elevation'; -import '../icon'; - import type { FoundationElementDefinition } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; +import { loadComponentsModules } from '../../shared/utils'; import styles from './card.scss'; import { Card } from './card'; import { CardTemplate as template } from './card.template'; +const prefix = getPrefix(import.meta.url); + export const vividCard = Card.compose({ baseName: 'card', template: template as any, styles, }); -designSystem.register(vividCard()); +(async () => { + await loadComponentsModules(['icon', 'elevation'], prefix); + designSystem.withPrefix(prefix).register(vividCard()); +})(); diff --git a/libs/components/src/lib/checkbox/index.ts b/libs/components/src/lib/checkbox/index.ts index 51325b1776..4665ebd15c 100644 --- a/libs/components/src/lib/checkbox/index.ts +++ b/libs/components/src/lib/checkbox/index.ts @@ -1,13 +1,13 @@ -import '../icon'; -import '../focus'; - import type { CheckboxOptions } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; +import { loadComponentsModules } from '../../shared/utils'; import styles from './checkbox.scss'; import { Checkbox } from './checkbox'; import { CheckboxTemplate as template } from './checkbox.template'; +const prefix = getPrefix(import.meta.url); + export const vividCheckbox = Checkbox.compose({ baseName: 'checkbox', template: template as any, @@ -17,4 +17,7 @@ export const vividCheckbox = Checkbox.compose({ }, }); -designSystem.register(vividCheckbox()); +(async () => { + await loadComponentsModules(['icon', 'focus'], prefix); + designSystem.withPrefix(prefix).register(vividCheckbox()); +})(); diff --git a/libs/components/src/lib/components.ts b/libs/components/src/lib/components.ts index 661ef11851..248a1cee5e 100644 --- a/libs/components/src/lib/components.ts +++ b/libs/components/src/lib/components.ts @@ -18,7 +18,7 @@ export * from './fab'; export * from './icon'; export * from './layout'; export * from './listbox'; -export * from './listbox-option'; +export * from './option'; export * from './menu'; export * from './menu-item'; export * from './nav'; diff --git a/libs/components/src/lib/dialog/index.ts b/libs/components/src/lib/dialog/index.ts index 2230ec4f9e..38f3016d84 100644 --- a/libs/components/src/lib/dialog/index.ts +++ b/libs/components/src/lib/dialog/index.ts @@ -1,19 +1,21 @@ -import '../icon'; -import '../button'; -import '../elevation'; - import type { FoundationElementDefinition } from '@microsoft/fast-foundation'; //TODO::remove next line when removing the dialog polyfill import dialogPolyfillStyles from 'dialog-polyfill/dist/dialog-polyfill.css'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; +import { loadComponentsModules } from '../../shared/utils'; import styles from './dialog.scss'; import { Dialog } from './dialog'; import { DialogTemplate as template } from './dialog.template'; +const prefix = getPrefix(import.meta.url); + export const vividDialog = Dialog.compose({ baseName: 'dialog', template: template as any, styles: [styles, dialogPolyfillStyles], }); -designSystem.register(vividDialog()); +(async () => { + await loadComponentsModules(['icon', 'button', 'elevation'], prefix); + designSystem.withPrefix(prefix).register(vividDialog()); +})(); diff --git a/libs/components/src/lib/divider/index.ts b/libs/components/src/lib/divider/index.ts index 70ce021760..bc3ebe8bc8 100644 --- a/libs/components/src/lib/divider/index.ts +++ b/libs/components/src/lib/divider/index.ts @@ -1,5 +1,5 @@ import type { FoundationElementDefinition } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; import styles from './divider.scss'; import { Divider } from './divider'; @@ -11,4 +11,4 @@ export const vividDivider = Divider.compose({ styles, }); -designSystem.register(vividDivider()); +designSystem.withPrefix(getPrefix(import.meta.url)).register(vividDivider()); diff --git a/libs/components/src/lib/elevation/index.ts b/libs/components/src/lib/elevation/index.ts index 12b9c0be9a..54a1f05265 100644 --- a/libs/components/src/lib/elevation/index.ts +++ b/libs/components/src/lib/elevation/index.ts @@ -1,5 +1,5 @@ import type { FoundationElementDefinition } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; import { Elevation } from './elevation'; import styles from './elevation.scss'; import { elevationTemplate as template } from './elevation.template'; @@ -14,4 +14,4 @@ export const vividElevation = Elevation.compose({ styles, }); -designSystem.register(vividElevation()); +designSystem.withPrefix(getPrefix(import.meta.url)).register(vividElevation()); diff --git a/libs/components/src/lib/fab/index.ts b/libs/components/src/lib/fab/index.ts index 95e24a7f7d..6c8df757cb 100644 --- a/libs/components/src/lib/fab/index.ts +++ b/libs/components/src/lib/fab/index.ts @@ -1,13 +1,13 @@ -import '../icon'; -import '../focus'; - import type { FoundationElementDefinition } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; +import { loadComponentsModules } from '../../shared/utils'; import styles from './fab.scss'; import { Fab } from './fab'; import { FabTemplate as template } from './fab.template'; +const prefix = getPrefix(import.meta.url); + export const vividFab = Fab.compose({ baseName: 'fab', template: template as any, @@ -17,4 +17,7 @@ export const vividFab = Fab.compose({ }, }); -designSystem.register(vividFab()); +( async () => { + await loadComponentsModules(['icon', 'focus'], prefix); + designSystem.withPrefix(prefix).register(vividFab()); +})(); diff --git a/libs/components/src/lib/focus/index.ts b/libs/components/src/lib/focus/index.ts index 908342dded..edfdbec09f 100644 --- a/libs/components/src/lib/focus/index.ts +++ b/libs/components/src/lib/focus/index.ts @@ -1,5 +1,5 @@ import type { FoundationElementDefinition } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; import { Focus } from './focus'; import styles from './focus.scss'; import { focusTemplate as template } from './focus.template'; @@ -18,4 +18,4 @@ export const vividFocus = Focus.compose({ styles, }); -designSystem.register(vividFocus()); +designSystem.withPrefix(getPrefix(import.meta.url)).register(vividFocus()); diff --git a/libs/components/src/lib/header/index.ts b/libs/components/src/lib/header/index.ts index f9e98a5ec5..944378119d 100644 --- a/libs/components/src/lib/header/index.ts +++ b/libs/components/src/lib/header/index.ts @@ -1,16 +1,20 @@ -import '../elevation'; - import type { FoundationElementDefinition } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; +import { loadComponentsModules } from '../../shared/utils'; import styles from './header.scss'; - import { Header } from './header'; import { headerTemplate as template } from './header.template'; + +const prefix = getPrefix(import.meta.url); + export const vividHeader = Header.compose({ baseName: 'header', template: template as any, styles, }); -designSystem.register(vividHeader()); +(async () => { + await loadComponentsModules(['elevation'], prefix); + designSystem.withPrefix(prefix).register(vividHeader()); +})(); diff --git a/libs/components/src/lib/icon/index.ts b/libs/components/src/lib/icon/index.ts index 15865d7b47..40b825dd90 100644 --- a/libs/components/src/lib/icon/index.ts +++ b/libs/components/src/lib/icon/index.ts @@ -1,5 +1,5 @@ import type { FoundationElementDefinition } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; import styles from './icon.scss'; import { Icon } from './icon'; import { iconTemplate as template } from './icon.template'; @@ -11,4 +11,4 @@ export const vividIcon = Icon.compose({ styles, }); -designSystem.register(vividIcon()); +designSystem.withPrefix(getPrefix(import.meta.url)).register(vividIcon()); diff --git a/libs/components/src/lib/layout/index.ts b/libs/components/src/lib/layout/index.ts index 6215d5accb..0a466088e1 100644 --- a/libs/components/src/lib/layout/index.ts +++ b/libs/components/src/lib/layout/index.ts @@ -1,5 +1,5 @@ import type { FoundationElementDefinition } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; import { Layout } from './layout'; import styles from './layout.scss'; import { layoutTemplate as template } from './layout.template'; @@ -15,4 +15,4 @@ export const vividLayout = Layout.compose({ styles, }); -designSystem.register(vividLayout()); +designSystem.withPrefix(getPrefix(import.meta.url)).register(vividLayout()); diff --git a/libs/components/src/lib/listbox-option/index.ts b/libs/components/src/lib/listbox-option/index.ts deleted file mode 100644 index ebe775f2c1..0000000000 --- a/libs/components/src/lib/listbox-option/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -import '../icon'; -import '../focus'; - -import type { FoundationElementDefinition } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; -import { ListboxOption } from './listbox-option'; -import { ListboxOptionTemplate as template } from './listbox-option.template'; -import styles from './listbox-option.scss'; - -export const vividListboxOption = ListboxOption.compose({ - baseName: 'option', - template: template as any, - styles -}); - -designSystem.register(vividListboxOption()); diff --git a/libs/components/src/lib/listbox/index.ts b/libs/components/src/lib/listbox/index.ts index 996d80b92c..8a03223f49 100644 --- a/libs/components/src/lib/listbox/index.ts +++ b/libs/components/src/lib/listbox/index.ts @@ -1,16 +1,24 @@ -import '../focus'; -import '../listbox-option'; - import type { FoundationElementDefinition } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; +import { loadComponentsModules } from '../../shared/utils'; import { Listbox } from './listbox'; import { ListboxTemplate as template } from './listbox.template'; import styles from './listbox.scss'; -export const vividListbox = Listbox.compose({ + +const prefix = getPrefix(import.meta.url); + +const vividListbox = Listbox.compose({ baseName: 'listbox', template: template as any, styles }); -designSystem.register(vividListbox()); +(async () => { + // by convention, option isn't required to be imported + // in listbox as it is not used directly in its template rather by user's authoring. + // but, due to the race condition and way listbox needs children to + // connect before setting/checking their props/attributes, it is required + await loadComponentsModules(['option', 'focus'], prefix); + designSystem.withPrefix(prefix).register(vividListbox()); +})(); diff --git a/libs/components/src/lib/listbox/listbox.spec.ts b/libs/components/src/lib/listbox/listbox.spec.ts index 1599d83412..0f79ade1a7 100644 --- a/libs/components/src/lib/listbox/listbox.spec.ts +++ b/libs/components/src/lib/listbox/listbox.spec.ts @@ -1,7 +1,7 @@ import { elementUpdated, fixture, getBaseElement } from '@vivid-nx/shared'; -import type { ListboxOption } from '../listbox-option/listbox-option'; +import type { ListboxOption } from '../option/option'; import { Listbox } from './listbox'; -import '../listbox-option'; +import '../option'; import '.'; const COMPONENT_TAG = 'vwc-listbox'; diff --git a/libs/components/src/lib/listbox/ui.test.ts b/libs/components/src/lib/listbox/ui.test.ts index f34329015a..7e97c37314 100644 --- a/libs/components/src/lib/listbox/ui.test.ts +++ b/libs/components/src/lib/listbox/ui.test.ts @@ -7,7 +7,7 @@ import { loadTemplate } from '../../visual-tests/visual-tests-utils.js'; -const components = ['listbox', 'listbox-option']; +const components = ['listbox', 'option']; test('should show the component', async ({ page }: { page: Page }) => { const template = extractHTMLBlocksFromReadme(path.join(new URL('.', import.meta.url).pathname, 'README.md')) .reduce((htmlString: string, block: string) => `${htmlString}
${block}
`, ''); diff --git a/libs/components/src/lib/menu-item/index.ts b/libs/components/src/lib/menu-item/index.ts index 3432a92cec..38bd10dbeb 100644 --- a/libs/components/src/lib/menu-item/index.ts +++ b/libs/components/src/lib/menu-item/index.ts @@ -1,16 +1,20 @@ -import '../icon'; - import type { MenuItemOptions } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; +import { loadComponentsModules } from '../../shared/utils'; import styles from './menu-item.scss'; import { MenuItem } from './menu-item'; import { MenuItemTemplate as template } from './menu-item.template'; +const prefix = getPrefix(import.meta.url); + export const vividMenuItem = MenuItem.compose({ baseName: 'menu-item', template: template as any, styles }); -designSystem.register(vividMenuItem()); +(async () => { + await loadComponentsModules(['icon', 'focus'], prefix); + designSystem.withPrefix(prefix).register(vividMenuItem()); +})(); diff --git a/libs/components/src/lib/menu-item/menu-item.spec.ts b/libs/components/src/lib/menu-item/menu-item.spec.ts index 7fb7d4faff..69bbbdf470 100644 --- a/libs/components/src/lib/menu-item/menu-item.spec.ts +++ b/libs/components/src/lib/menu-item/menu-item.spec.ts @@ -13,6 +13,10 @@ const ICON_SELECTOR = 'vwc-icon'; describe('vwc-menu-item', () => { let element: MenuItem; + beforeAll(async () => { + await customElements.whenDefined(COMPONENT_TAG); + }); + beforeEach(async () => { element = (await fixture( `<${COMPONENT_TAG}>` diff --git a/libs/components/src/lib/menu/index.ts b/libs/components/src/lib/menu/index.ts index 9dc330a8c8..095d950367 100644 --- a/libs/components/src/lib/menu/index.ts +++ b/libs/components/src/lib/menu/index.ts @@ -1,15 +1,10 @@ -import '../popup'; -// by convention, menu-item isn't required to be imported -// in menu as it is not used directly rather by authoring. -// but, due to the race condition and way menu needs children to -// connect before setting/checking their props/attributes, it is required -import '../menu-item'; - -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; +import { loadComponentsModules } from '../../shared/utils'; import styles from './menu.scss'; import { Menu } from './menu'; import { MenuTemplate as template } from './menu.template'; +const prefix = getPrefix(import.meta.url); export const vividMenu = Menu.compose({ baseName: 'menu', @@ -17,4 +12,11 @@ export const vividMenu = Menu.compose({ styles, }); -designSystem.register(vividMenu()); +(async () => { + // by convention, menu-item isn't required to be imported + // in menu as it is not used directly in template, rather by user's authoring. + // but, due to the race condition and way menu needs children to + // connect before setting/checking their props/attributes, it is required + await loadComponentsModules(['popup', 'menu-item'], prefix); + designSystem.withPrefix(prefix).register(vividMenu()); +})(); diff --git a/libs/components/src/lib/menu/menu.spec.ts b/libs/components/src/lib/menu/menu.spec.ts index 017cba3a67..7966966d24 100644 --- a/libs/components/src/lib/menu/menu.spec.ts +++ b/libs/components/src/lib/menu/menu.spec.ts @@ -3,7 +3,6 @@ import type { Button } from '@microsoft/fast-foundation'; import { keyArrowDown, keyArrowUp } from '@microsoft/fast-web-utilities'; import { Popup } from '../popup/popup'; import { Menu } from './menu'; -import '../menu-item'; import '.'; const COMPONENT_TAG = 'vwc-menu'; @@ -18,6 +17,10 @@ describe('vwc-menu', () => { disconnect: jest.fn() })); + beforeAll(async () => { + await customElements.whenDefined(COMPONENT_TAG); + }); + beforeEach(async () => { element = (await fixture(`<${COMPONENT_TAG}>`)) as Menu; }); diff --git a/libs/components/src/lib/nav-disclosure/index.ts b/libs/components/src/lib/nav-disclosure/index.ts index 1c131b42ef..7202ae5724 100644 --- a/libs/components/src/lib/nav-disclosure/index.ts +++ b/libs/components/src/lib/nav-disclosure/index.ts @@ -1,13 +1,13 @@ -import '../icon'; -import '../focus'; - import type { FoundationElementDefinition } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; +import { loadComponentsModules } from '../../shared/utils'; import styles from './nav-disclosure.scss'; import { NavDisclosure } from './nav-disclosure'; import { NavDisclosureTemplate as template } from './nav-disclosure.template'; +const prefix = getPrefix(import.meta.url); + export const vividNavDisclosure = NavDisclosure.compose({ baseName: 'nav-disclosure', @@ -15,4 +15,7 @@ export const vividNavDisclosure = styles, }); -designSystem.register(vividNavDisclosure()); +(async () => { + await loadComponentsModules(['icon', 'focus'], prefix); + designSystem.withPrefix(prefix).register(vividNavDisclosure()); +})(); diff --git a/libs/components/src/lib/nav-item/index.ts b/libs/components/src/lib/nav-item/index.ts index 627d6128bc..1565451041 100644 --- a/libs/components/src/lib/nav-item/index.ts +++ b/libs/components/src/lib/nav-item/index.ts @@ -1,13 +1,13 @@ -import '../icon'; -import '../focus'; - import type { FoundationElementDefinition } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; +import { loadComponentsModules } from '../../shared/utils'; import styles from './nav-item.scss'; import { NavItem } from './nav-item'; import { NavItemTemplate as template } from './nav-item.template'; +const prefix = getPrefix(import.meta.url); + export const vividNavItem = NavItem.compose({ baseName: 'nav-item', @@ -18,4 +18,7 @@ export const vividNavItem = }, }); -designSystem.register(vividNavItem()); +( async () => { + await loadComponentsModules(['icon', 'focus'], prefix); + designSystem.withPrefix(prefix).register(vividNavItem()); +})(); diff --git a/libs/components/src/lib/nav/index.ts b/libs/components/src/lib/nav/index.ts index c454f52d44..37589441eb 100644 --- a/libs/components/src/lib/nav/index.ts +++ b/libs/components/src/lib/nav/index.ts @@ -1,5 +1,5 @@ import type { FoundationElementDefinition } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; import { Nav } from './nav'; import { NavTemplate as template } from './nav.template'; @@ -10,4 +10,4 @@ export const vividNav = template: template as any, }); -designSystem.register(vividNav()); +designSystem.withPrefix(getPrefix(import.meta.url)).register(vividNav()); diff --git a/libs/components/src/lib/note/index.ts b/libs/components/src/lib/note/index.ts index ecb2d32a61..10a9babcb0 100644 --- a/libs/components/src/lib/note/index.ts +++ b/libs/components/src/lib/note/index.ts @@ -1,14 +1,20 @@ import type { FoundationElementDefinition } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; +import { loadComponentsModules } from '../../shared/utils'; import styles from './note.scss'; import { Note } from './note'; import { NoteTemplate as template } from './note.template'; +const prefix = getPrefix(import.meta.url); + export const vividNote = Note.compose({ baseName: 'note', template: template as any, styles, }); -designSystem.register(vividNote()); +(async () => { + await loadComponentsModules(['icon'], prefix); + designSystem.withPrefix(prefix).register(vividNote()); +})(); diff --git a/libs/components/src/lib/note/note.template.ts b/libs/components/src/lib/note/note.template.ts index 3afd60609b..2b9da79b44 100644 --- a/libs/components/src/lib/note/note.template.ts +++ b/libs/components/src/lib/note/note.template.ts @@ -5,7 +5,6 @@ import type { FoundationElementDefinition, } from '@microsoft/fast-foundation'; import { classNames } from '@microsoft/fast-web-utilities'; -import '../icon/index'; import {Connotation} from '../enums'; import type { Note } from './note'; diff --git a/libs/components/src/lib/number-field/index.ts b/libs/components/src/lib/number-field/index.ts index 6be791784b..9e8401503f 100644 --- a/libs/components/src/lib/number-field/index.ts +++ b/libs/components/src/lib/number-field/index.ts @@ -1,12 +1,13 @@ import type { FoundationElementDefinition } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; +import { loadComponentsModules } from '../../shared/utils'; import styles from './number-field.scss'; -import '../button'; -import '../divider'; - import { NumberField } from './number-field'; import { NumberFieldTemplate as template } from './number-field.template'; + +const prefix = getPrefix(import.meta.url); + export const vividNumberField = NumberField.compose({ baseName: 'number-field', @@ -17,7 +18,7 @@ export const vividNumberField = }, }); -designSystem.register(vividNumberField()); - - - +(async () => { + await loadComponentsModules(['button', 'divider'], prefix); + designSystem.withPrefix(prefix).register(vividNumberField()); +})(); diff --git a/libs/components/src/lib/listbox-option/README.md b/libs/components/src/lib/option/README.md similarity index 100% rename from libs/components/src/lib/listbox-option/README.md rename to libs/components/src/lib/option/README.md diff --git a/libs/components/src/lib/option/index.ts b/libs/components/src/lib/option/index.ts new file mode 100644 index 0000000000..e159b92280 --- /dev/null +++ b/libs/components/src/lib/option/index.ts @@ -0,0 +1,19 @@ +import type { FoundationElementDefinition } from '@microsoft/fast-foundation'; +import { designSystem, getPrefix } from '../../shared/design-system'; +import { loadComponentsModules } from '../../shared/utils'; +import { ListboxOption } from './option'; +import { ListboxOptionTemplate as template } from './option.template'; +import styles from './option.scss'; + +const prefix = getPrefix(import.meta.url); + +export const vividListboxOption = ListboxOption.compose({ + baseName: 'option', + template: template as any, + styles +}); + +(async () => { + await loadComponentsModules(['icon', 'focus'], prefix); + designSystem.withPrefix(prefix).register(vividListboxOption()); +})(); diff --git a/libs/components/src/lib/listbox-option/listbox-option.scss b/libs/components/src/lib/option/option.scss similarity index 100% rename from libs/components/src/lib/listbox-option/listbox-option.scss rename to libs/components/src/lib/option/option.scss diff --git a/libs/components/src/lib/listbox-option/listbox-option.spec.ts b/libs/components/src/lib/option/option.spec.ts similarity index 95% rename from libs/components/src/lib/listbox-option/listbox-option.spec.ts rename to libs/components/src/lib/option/option.spec.ts index a8b229096e..85a1b7fa1e 100644 --- a/libs/components/src/lib/listbox-option/listbox-option.spec.ts +++ b/libs/components/src/lib/option/option.spec.ts @@ -1,6 +1,6 @@ import { elementUpdated, fixture } from '@vivid-nx/shared'; import { Icon } from '../icon/icon'; -import { ListboxOption } from './listbox-option'; +import { ListboxOption } from './option'; import '.'; const COMPONENT_TAG = 'vwc-option'; @@ -20,6 +20,7 @@ describe('vwc-option', () => { expect(element).toBeInstanceOf(ListboxOption); expect(element.text).toEqual(''); expect(element.icon).toBeUndefined(); + expect(element.iconTrailing).toBeFalsy(); expect(element.selected).toBeFalsy(); expect(element.checked).toBeUndefined(); expect(element.disabled).toBeUndefined(); diff --git a/libs/components/src/lib/listbox-option/listbox-option.template.ts b/libs/components/src/lib/option/option.template.ts similarity index 96% rename from libs/components/src/lib/listbox-option/listbox-option.template.ts rename to libs/components/src/lib/option/option.template.ts index 8afbda676e..3896fa2987 100644 --- a/libs/components/src/lib/listbox-option/listbox-option.template.ts +++ b/libs/components/src/lib/option/option.template.ts @@ -7,7 +7,7 @@ import type { import { classNames } from '@microsoft/fast-web-utilities'; import { affixIconTemplateFactory } from '../../shared/patterns/affix'; import { focusTemplateFactory } from '../../shared/patterns'; -import type { ListboxOption } from './listbox-option'; +import type { ListboxOption } from './option'; const getClasses = ({ icon, disabled, selected, checked diff --git a/libs/components/src/lib/listbox-option/listbox-option.ts b/libs/components/src/lib/option/option.ts similarity index 100% rename from libs/components/src/lib/listbox-option/listbox-option.ts rename to libs/components/src/lib/option/option.ts diff --git a/libs/components/src/lib/listbox-option/ui.test.ts b/libs/components/src/lib/option/ui.test.ts similarity index 90% rename from libs/components/src/lib/listbox-option/ui.test.ts rename to libs/components/src/lib/option/ui.test.ts index 71d706c45a..ccba529689 100644 --- a/libs/components/src/lib/listbox-option/ui.test.ts +++ b/libs/components/src/lib/option/ui.test.ts @@ -7,7 +7,7 @@ import { loadTemplate } from '../../visual-tests/visual-tests-utils.js'; -const components = ['listbox-option', 'listbox']; +const components = ['option', 'listbox']; test('should show the component', async ({ page }: { page: Page }) => { const template = extractHTMLBlocksFromReadme(path.join(new URL('.', import.meta.url).pathname, 'README.md')) .reduce((htmlString: string, block: string) => `${htmlString}
${block}
`, ''); @@ -29,6 +29,6 @@ test('should show the component', async ({ page }: { page: Page }) => { expect(await testWrapper?.screenshot()) .toMatchSnapshot( - './snapshots/listbox-option.png', + './snapshots/option.png', ); }); diff --git a/libs/components/src/lib/listbox-option/ui.test.ts-snapshots/snapshots-listbox-option-Desktop-Chromium-linux.png b/libs/components/src/lib/option/ui.test.ts-snapshots/snapshots-option-Desktop-Chromium-linux.png similarity index 100% rename from libs/components/src/lib/listbox-option/ui.test.ts-snapshots/snapshots-listbox-option-Desktop-Chromium-linux.png rename to libs/components/src/lib/option/ui.test.ts-snapshots/snapshots-option-Desktop-Chromium-linux.png diff --git a/libs/components/src/lib/listbox-option/ui.test.ts-snapshots/snapshots-listbox-option-Desktop-Firefox-linux.png b/libs/components/src/lib/option/ui.test.ts-snapshots/snapshots-option-Desktop-Firefox-linux.png similarity index 100% rename from libs/components/src/lib/listbox-option/ui.test.ts-snapshots/snapshots-listbox-option-Desktop-Firefox-linux.png rename to libs/components/src/lib/option/ui.test.ts-snapshots/snapshots-option-Desktop-Firefox-linux.png diff --git a/libs/components/src/lib/listbox-option/ui.test.ts-snapshots/snapshots-listbox-option-Desktop-Safari-linux.png b/libs/components/src/lib/option/ui.test.ts-snapshots/snapshots-option-Desktop-Safari-linux.png similarity index 100% rename from libs/components/src/lib/listbox-option/ui.test.ts-snapshots/snapshots-listbox-option-Desktop-Safari-linux.png rename to libs/components/src/lib/option/ui.test.ts-snapshots/snapshots-option-Desktop-Safari-linux.png diff --git a/libs/components/src/lib/popup/index.ts b/libs/components/src/lib/popup/index.ts index f631da1614..3dc8a1d97e 100644 --- a/libs/components/src/lib/popup/index.ts +++ b/libs/components/src/lib/popup/index.ts @@ -1,13 +1,13 @@ -import '../elevation'; -import '../button'; - import type { FoundationElementDefinition } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; +import { loadComponentsModules } from '../../shared/utils'; import { Popup } from './popup'; import styles from './popup.scss'; import { popupTemplate as template } from './popup.template'; +const prefix = getPrefix(import.meta.url); + /** * Represents a popup custom element. * popup is... @@ -18,4 +18,7 @@ export const vividPopup = Popup.compose({ styles, }); -designSystem.register(vividPopup()); +(async () => { + await loadComponentsModules(['elevation', 'button'], prefix); + designSystem.withPrefix(prefix).register(vividPopup()); +})(); diff --git a/libs/components/src/lib/popup/popup.template.ts b/libs/components/src/lib/popup/popup.template.ts index 0c9723a749..0888b7ee71 100644 --- a/libs/components/src/lib/popup/popup.template.ts +++ b/libs/components/src/lib/popup/popup.template.ts @@ -2,6 +2,8 @@ import { html, ref, when } from '@microsoft/fast-element'; import { classNames } from '@microsoft/fast-web-utilities'; import type { ViewTemplate } from '@microsoft/fast-element'; import type { ElementDefinitionContext, FoundationElementDefinition } from '@microsoft/fast-foundation'; +import { Elevation } from '../elevation/elevation'; +import { Button } from '../button/button'; import type { Popup } from './popup'; const getClasses = ({ @@ -16,14 +18,19 @@ const getClasses = ({ /** * The template for the {@link @vonage/vivid#Popup} component. * + * @param context * @returns {ViewTemplate} A template capable of creating HTMLView instances or rendering directly to DOM. * @public */ export const popupTemplate: ( context: ElementDefinitionContext, definition: FoundationElementDefinition -) => ViewTemplate = () => html` - +) => ViewTemplate = (context: ElementDefinitionContext) => { + const elevationTag = context.tagFor(Elevation); + const buttonTag = context.tagFor(Button); + + return html` + <${elevationTag}> - `; + `; +}; diff --git a/libs/components/src/lib/progress-ring/index.ts b/libs/components/src/lib/progress-ring/index.ts index 0fd1ce8bd8..aaaad68233 100644 --- a/libs/components/src/lib/progress-ring/index.ts +++ b/libs/components/src/lib/progress-ring/index.ts @@ -1,5 +1,5 @@ import type {FoundationElementDefinition} from '@microsoft/fast-foundation'; -import {designSystem} from '../../shared/design-system'; +import {designSystem, getPrefix} from '../../shared/design-system'; import styles from './progress-ring.scss'; import {ProgressRing} from './progress-ring'; @@ -12,5 +12,5 @@ export const vividProgressRing = styles, }); -designSystem.register(vividProgressRing()); +designSystem.withPrefix(getPrefix(import.meta.url)).register(vividProgressRing()); diff --git a/libs/components/src/lib/progress/index.ts b/libs/components/src/lib/progress/index.ts index 73f85a2b22..2eb64760eb 100644 --- a/libs/components/src/lib/progress/index.ts +++ b/libs/components/src/lib/progress/index.ts @@ -1,5 +1,5 @@ import type { FoundationElementDefinition } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; import styles from './progress.scss'; import { Progress } from './progress'; @@ -11,4 +11,4 @@ export const vividProgress = Progress.compose({ styles, }); -designSystem.register(vividProgress()); +designSystem.withPrefix(getPrefix(import.meta.url)).register(vividProgress()); diff --git a/libs/components/src/lib/radio-group/index.ts b/libs/components/src/lib/radio-group/index.ts index ff81272819..b4e4207e31 100644 --- a/libs/components/src/lib/radio-group/index.ts +++ b/libs/components/src/lib/radio-group/index.ts @@ -1,4 +1,4 @@ -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; import styles from './radio-group.scss'; import { RadioGroup } from './radio-group'; @@ -10,4 +10,4 @@ export const vividRadioGroup = RadioGroup.compose({ styles, }); -designSystem.register(vividRadioGroup()); +designSystem.withPrefix(getPrefix(import.meta.url)).register(vividRadioGroup()); diff --git a/libs/components/src/lib/radio/index.ts b/libs/components/src/lib/radio/index.ts index ae15ba066d..98451934ec 100644 --- a/libs/components/src/lib/radio/index.ts +++ b/libs/components/src/lib/radio/index.ts @@ -1,16 +1,20 @@ -import '../focus'; - import type { RadioOptions } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; +import { loadComponentsModules } from '../../shared/utils'; import styles from './radio.scss'; import { Radio } from './radio'; import { RadioTemplate as template } from './radio.template'; +const prefix = getPrefix(import.meta.url); + export const vividRadio = Radio.compose({ baseName: 'radio', template: template as any, styles }); -designSystem.register(vividRadio()); +(async () => { + await loadComponentsModules(['focus'], prefix); + designSystem.withPrefix(prefix).register(vividRadio()); +})(); diff --git a/libs/components/src/lib/side-drawer/index.ts b/libs/components/src/lib/side-drawer/index.ts index 51ee175aea..a489736596 100644 --- a/libs/components/src/lib/side-drawer/index.ts +++ b/libs/components/src/lib/side-drawer/index.ts @@ -1,5 +1,5 @@ import type { FoundationElementDefinition } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; import { SideDrawer } from './side-drawer'; import styles from './side-drawer.scss'; import { sideDrawerTemplate as template } from './side-drawer.template'; @@ -13,4 +13,4 @@ export const vividSideDrawer = SideDrawer.compose({ styles, }); -designSystem.register(vividSideDrawer()); +designSystem.withPrefix(getPrefix(import.meta.url)).register(vividSideDrawer()); diff --git a/libs/components/src/lib/slider/index.ts b/libs/components/src/lib/slider/index.ts index 28ce417353..4381e99d24 100644 --- a/libs/components/src/lib/slider/index.ts +++ b/libs/components/src/lib/slider/index.ts @@ -1,16 +1,20 @@ -import '../focus'; - import type { SliderOptions } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; +import { loadComponentsModules } from '../../shared/utils'; import styles from './slider.scss'; import { Slider } from './slider'; import { SliderTemplate as template } from './slider.template'; +const prefix = getPrefix(import.meta.url); + export const vividSlider = Slider.compose({ baseName: 'slider', template: template as any, styles, }); -designSystem.register(vividSlider()); +(async () => { + await loadComponentsModules(['focus'], prefix); + designSystem.withPrefix(prefix).register(vividSlider()); +})(); diff --git a/libs/components/src/lib/switch/index.ts b/libs/components/src/lib/switch/index.ts index 4db486a6e7..a6fa3bc94a 100644 --- a/libs/components/src/lib/switch/index.ts +++ b/libs/components/src/lib/switch/index.ts @@ -1,13 +1,12 @@ -import '../focus'; - import type { FoundationElementDefinition } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; +import { loadComponentsModules } from '../../shared/utils'; import styles from './switch.scss'; -import '../focus'; - import { Switch } from './switch'; import { SwitchTemplate as template } from './switch.template'; +const prefix = getPrefix(import.meta.url); + export const vividSwitch = Switch.compose({ baseName: 'switch', template: template as any, @@ -17,4 +16,7 @@ export const vividSwitch = Switch.compose({ } }); -designSystem.register(vividSwitch()); +(async () => { + await loadComponentsModules(['icon', 'focus'], prefix); + designSystem.withPrefix(prefix).register(vividSwitch()); +})(); diff --git a/libs/components/src/lib/text-anchor/index.ts b/libs/components/src/lib/text-anchor/index.ts index 18007adb49..2766191d47 100644 --- a/libs/components/src/lib/text-anchor/index.ts +++ b/libs/components/src/lib/text-anchor/index.ts @@ -1,5 +1,5 @@ import type { FoundationElementDefinition } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; import { TextAnchor } from './text-anchor'; import { textAnchorTemplate as template } from './text-anchor.template'; @@ -9,4 +9,4 @@ export const vividTextAnchor = TextAnchor.compose({ template: template as any, }); -designSystem.register(vividTextAnchor()); +designSystem.withPrefix(getPrefix(import.meta.url)).register(vividTextAnchor()); diff --git a/libs/components/src/lib/text-area/index.ts b/libs/components/src/lib/text-area/index.ts index 8a14b94cd5..76a744a38b 100644 --- a/libs/components/src/lib/text-area/index.ts +++ b/libs/components/src/lib/text-area/index.ts @@ -1,13 +1,13 @@ -import '../focus'; -import '../icon'; - import type { FoundationElementDefinition } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; +import { loadComponentsModules } from '../../shared/utils'; import styles from './text-area.scss'; import { TextArea } from './text-area'; import { TextAreaTemplate as template } from './text-area.template'; +const prefix = getPrefix(import.meta.url); + export const vividTextArea = TextArea.compose({ baseName: 'text-area', template: template as any, @@ -17,4 +17,7 @@ export const vividTextArea = TextArea.compose({ }, }); -designSystem.register(vividTextArea()); +(async () => { + await loadComponentsModules(['icon', 'focus'], prefix); + designSystem.withPrefix(prefix).register(vividTextArea()); +})(); diff --git a/libs/components/src/lib/text-field/index.ts b/libs/components/src/lib/text-field/index.ts index e84cbe715e..5da6889e5b 100644 --- a/libs/components/src/lib/text-field/index.ts +++ b/libs/components/src/lib/text-field/index.ts @@ -1,12 +1,12 @@ -import '../icon'; -import '../focus'; - import type { FoundationElementDefinition } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; +import { loadComponentsModules } from '../../shared/utils'; import { TextField } from './text-field'; import styles from './text-field.scss'; import { TextfieldTemplate as template } from './text-field.template'; +const prefix = getPrefix(import.meta.url); + export const vividTextfield = TextField.compose({ baseName: 'text-field', template: template as any, @@ -16,5 +16,7 @@ export const vividTextfield = TextField.compose({ }, }); -designSystem.register(vividTextfield()); - +( async () => { + await loadComponentsModules(['icon', 'focus'], prefix); + designSystem.withPrefix(prefix).register(vividTextfield()); +})(); diff --git a/libs/components/src/lib/text-field/text-field.template.ts b/libs/components/src/lib/text-field/text-field.template.ts index a3dfed77f0..22e2417f25 100644 --- a/libs/components/src/lib/text-field/text-field.template.ts +++ b/libs/components/src/lib/text-field/text-field.template.ts @@ -7,7 +7,6 @@ import type { import {classNames} from '@microsoft/fast-web-utilities'; import { affixIconTemplateFactory } from '../../shared/patterns/affix'; import { focusTemplateFactory } from '../../shared/patterns/focus'; -import '../icon/index'; import {getFeedbackTemplate} from '../../shared/patterns'; import type {TextField} from './text-field'; diff --git a/libs/components/src/lib/tooltip/index.ts b/libs/components/src/lib/tooltip/index.ts index e96fded125..60449ffb4b 100644 --- a/libs/components/src/lib/tooltip/index.ts +++ b/libs/components/src/lib/tooltip/index.ts @@ -1,16 +1,20 @@ -import '../popup'; - import type { FoundationElementDefinition } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; +import { loadComponentsModules } from '../../shared/utils'; import styles from './tooltip.scss'; import { Tooltip } from './tooltip'; import { TooltipTemplate as template } from './tooltip.template'; +const prefix = getPrefix(import.meta.url); + export const vividTooltip = Tooltip.compose({ baseName: 'tooltip', template: template as any, styles, }); -designSystem.register(vividTooltip()); +(async () => { + await loadComponentsModules(['popup'], prefix); + designSystem.withPrefix(prefix).register(vividTooltip()); +})(); diff --git a/libs/components/src/shared/design-system/index.ts b/libs/components/src/shared/design-system/index.ts index bf9803ed83..276dbff976 100644 --- a/libs/components/src/shared/design-system/index.ts +++ b/libs/components/src/shared/design-system/index.ts @@ -1,12 +1,12 @@ import { DesignSystem } from '@microsoft/fast-foundation'; + +export const getPrefix = (url:string) => new URL(url).searchParams.get('prefix') || 'vwc'; + // common components dependency /** * @param {HTMLElement} element - The element to get or create a design system for. + * @param prefix * @returns {DesignSystem} - Represents a configurable design system. An API gateway to design system features. */ -export function provideVividDesignSystem(element?: HTMLElement): DesignSystem { - return DesignSystem.getOrCreate(element).withPrefix('vwc'); -} - -export const designSystem = provideVividDesignSystem(); +export const designSystem = DesignSystem.getOrCreate(); diff --git a/libs/components/src/shared/utils/index.spec.ts b/libs/components/src/shared/utils/index.spec.ts new file mode 100644 index 0000000000..c9e80e1f88 --- /dev/null +++ b/libs/components/src/shared/utils/index.spec.ts @@ -0,0 +1,41 @@ +import '.'; + +describe('loadComponentsModules', () => { + function mockCallWithPrefix(prefix: string) { + jest.mock(`../${components[0]}/index.js?prefix=${prefix}`, async () => { + return import(`../../lib/${components[0]}/index`); + }, { virtual: true }); + } + + function getNonMockedLoadComponentsModules(): { loadComponentsModules: any; } { + return jest.requireActual('.'); + } + + const components = ['button']; + const prefix = 'vivid'; + let whenDefinedMock: any; + const whenDefinedResolveValue = {}; + const { loadComponentsModules } = getNonMockedLoadComponentsModules(); + + beforeEach(() => { + whenDefinedMock = jest.spyOn(customElements, 'whenDefined') + .mockReturnValue(Promise.resolve(whenDefinedResolveValue as CustomElementConstructor)); + mockCallWithPrefix(prefix); + }); + + afterEach(() => { + whenDefinedMock.mockRestore(); + }); + + it('should import "../${component}/index.js?prefix=${prefix}', async () => { + await loadComponentsModules(components, prefix); + + expect(customElements.whenDefined).toHaveBeenCalledWith('vivid-button'); + }); + + it('should wait for whenDefined of all components', async () => { + const [whenDefinedRActualesolveValue] = await loadComponentsModules(components, prefix); + + expect(whenDefinedResolveValue).toEqual(whenDefinedRActualesolveValue); + }); +}); diff --git a/libs/components/src/shared/utils/index.ts b/libs/components/src/shared/utils/index.ts new file mode 100644 index 0000000000..e2d8cb6033 --- /dev/null +++ b/libs/components/src/shared/utils/index.ts @@ -0,0 +1,9 @@ +export const loadComponentsModules = (components: string[], prefix: string) => { + components.forEach((component) => import(`../${component}/index.js?prefix=${prefix}`)); + + return Promise.all( + components.map(component => + customElements.whenDefined(`${prefix}-${component}`) + ) + ); +}; diff --git a/libs/components/tsconfig.spec.json b/libs/components/tsconfig.spec.json index e03a280d4d..b8af15efb4 100644 --- a/libs/components/tsconfig.spec.json +++ b/libs/components/tsconfig.spec.json @@ -2,9 +2,9 @@ "extends": "./tsconfig.json", "compilerOptions": { "outDir": "../../dist/out-tsc", - "module": "commonjs", "types": ["jest", "node"], "allowJs": true, + "noEmit": false }, "exclude": [ "**/*.config.spec.ts", diff --git a/libs/nx-vivid/src/generators/component/files/index.ts__tmpl__ b/libs/nx-vivid/src/generators/component/files/index.ts__tmpl__ index 5e2a11b942..bfc6ab4f3b 100644 --- a/libs/nx-vivid/src/generators/component/files/index.ts__tmpl__ +++ b/libs/nx-vivid/src/generators/component/files/index.ts__tmpl__ @@ -1,5 +1,5 @@ import type { FoundationElementDefinition } from '@microsoft/fast-foundation'; -import { designSystem } from '../../shared/design-system'; +import { designSystem, getPrefix } from '../../shared/design-system'; import styles from './<%= fileName %>.scss'; import { <%= className %> } from './<%= fileName %>'; @@ -11,4 +11,4 @@ export const vivid<%= className %> = <%= className %>.compose()); +designSystem.withPrefix(getPrefix(import.meta.url)).register(vivid<%= className %>()); diff --git a/package-lock.json b/package-lock.json index 6de3319a36..36135e7c7f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -95,6 +95,7 @@ "stylelint-config-standard-scss": "^3.0.0", "stylelint-no-unsupported-browser-features": "^5.0.3", "ts-jest": "28.0.8", + "ts-jest-mock-import-meta": "^0.12.0", "ts-node": "10.9.1", "typescript": "4.8.4" } @@ -18171,6 +18172,15 @@ } } }, + "node_modules/ts-jest-mock-import-meta": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/ts-jest-mock-import-meta/-/ts-jest-mock-import-meta-0.12.0.tgz", + "integrity": "sha512-LfuetNsQ6CDEAPekFOtMpCPRBBAgoA322IQ95eCa3x0mR++GwhZddlsmjOUhxRPLF3utbXUZpCEZiW+HP8jkiA==", + "dev": true, + "peerDependencies": { + "ts-jest": ">=20.0.0" + } + }, "node_modules/ts-loader": { "version": "9.4.1", "dev": true, @@ -31254,6 +31264,13 @@ "yargs-parser": "^21.0.1" } }, + "ts-jest-mock-import-meta": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/ts-jest-mock-import-meta/-/ts-jest-mock-import-meta-0.12.0.tgz", + "integrity": "sha512-LfuetNsQ6CDEAPekFOtMpCPRBBAgoA322IQ95eCa3x0mR++GwhZddlsmjOUhxRPLF3utbXUZpCEZiW+HP8jkiA==", + "dev": true, + "requires": {} + }, "ts-loader": { "version": "9.4.1", "dev": true, diff --git a/package.json b/package.json index 22966d011d..7fd8bccebe 100644 --- a/package.json +++ b/package.json @@ -100,6 +100,7 @@ "stylelint-config-standard-scss": "^3.0.0", "stylelint-no-unsupported-browser-features": "^5.0.3", "ts-jest": "28.0.8", + "ts-jest-mock-import-meta": "^0.12.0", "ts-node": "10.9.1", "typescript": "4.8.4" }