diff --git a/src/Umbraco.Web.UI.Client/package-lock.json b/src/Umbraco.Web.UI.Client/package-lock.json index c3ae26382c..f16c285049 100644 --- a/src/Umbraco.Web.UI.Client/package-lock.json +++ b/src/Umbraco.Web.UI.Client/package-lock.json @@ -1,12 +1,12 @@ { "name": "@umbraco-cms/backoffice", - "version": "14.0.0-beta001", + "version": "14.0.0-beta002", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@umbraco-cms/backoffice", - "version": "14.0.0-beta001", + "version": "14.0.0-beta002", "license": "MIT", "dependencies": { "@openid/appauth": "^1.3.1", diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index 52dbc03297..83a2ff5f43 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -1,7 +1,7 @@ { "name": "@umbraco-cms/backoffice", "license": "MIT", - "version": "14.0.0-beta001", + "version": "14.0.0-beta002", "type": "module", "exports": { ".": null, diff --git a/src/Umbraco.Web.UI.Client/src/libs/element-api/element.test.ts b/src/Umbraco.Web.UI.Client/src/libs/element-api/element.test.ts index 4e363414c2..d4b35b075f 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/element-api/element.test.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/element-api/element.test.ts @@ -1,7 +1,7 @@ import { expect } from '@open-wc/testing'; import { UmbElementMixin } from './element.mixin.js'; import { customElement } from '@umbraco-cms/backoffice/external/lit'; -import { UmbStringState } from '@umbraco-cms/backoffice/observable-api'; +import { type UmbObserverController, UmbStringState } from '@umbraco-cms/backoffice/observable-api'; @customElement('test-my-umb-element') class UmbTestUmbElement extends UmbElementMixin(HTMLElement) {} @@ -206,7 +206,105 @@ describe('UmbElementMixin', () => { }); expect(callbackWasCalled).to.be.true; expect(ctrl).to.be.undefined; - expect(hostElement.hasController(ctrl)).to.be.false; + }); + }); + describe('Observe types', () => { + // Type helpers for TSC Type Checking: + type CheckType = T extends ExpectedType ? ExpectedType : never; + type ReverseCheckType = T extends ExpectedType ? never : T; + + it('observes Observable of String with corresponding callback method value type', () => { + const myState = new UmbStringState('hello'); + const myObservable = myState.asObservable(); + + const ctrl = hostElement.observe(myObservable, (value) => { + type A = typeof value; + const check: CheckType = value; + const check2: ReverseCheckType = value; + expect(check).to.be.equal('hello'); + expect(check2).to.be.equal('hello'); + }); + const check: CheckType> = ctrl; + const check2: ReverseCheckType> = ctrl; + + expect(hostElement.hasController(check)).to.be.true; + expect(check === check2).to.be.true; // Just to use the const for something. + }); + + it('observes Observable of String and Undefined with corresponding callback method value type', () => { + const myState = new UmbStringState(undefined); + const myObservable = myState.asObservable(); + + const ctrl = hostElement.observe(myObservable, (value) => { + type A = typeof value; + const check: CheckType = value; + expect(check).to.be.undefined; + }); + const check: CheckType> = ctrl; + const check2: ReverseCheckType> = ctrl; + const check3: ReverseCheckType> = ctrl; + + expect(hostElement.hasController(check)).to.be.true; + expect(check2 === check3).to.be.true; // Just to use the const for something. + }); + + it('observes potential undefined Observable of String with corresponding callback method value type', () => { + let myState: UmbStringState | undefined = undefined; + // eslint-disable-next-line no-constant-condition + if (1 === 1) { + myState = new UmbStringState('hello'); + } + const myObservable = myState?.asObservable(); + + const ctrl = hostElement.observe(myObservable, (value) => { + type A = typeof value; + const check: CheckType = value; + const check2: CheckType = value as string; + const check3: CheckType = value as undefined; + expect(check).to.be.equal('hello'); + expect(check2 === check3).to.be.true; // Just to use the const for something. + }); + const check: CheckType | undefined> = ctrl; + const check2: ReverseCheckType> = ctrl; + const check3: ReverseCheckType> = ctrl; + + if (ctrl) { + expect(hostElement.hasController(ctrl)).to.be.true; + } else { + expect(ctrl).to.be.undefined; + } + expect(check === check3 && check2 === check3).to.be.true; // Just to use the const for something. + }); + + it('observes potential undefined Observable of String and Null with corresponding callback method value type', () => { + let myState: UmbStringState | undefined = undefined; + // eslint-disable-next-line no-constant-condition + if (1 === 1) { + myState = new UmbStringState(null); + } + const myObservable = myState?.asObservable(); + + const ctrl = hostElement.observe(myObservable, (value) => { + type A = typeof value; + const check: CheckType = value; + const check2: CheckType = value as string; + const check3: CheckType = value as null; + const check4: CheckType = value as undefined; + expect(check).to.be.equal('hello'); + expect(check2 === check3 && check2 === check4).to.be.true; // Just to use the const for something. + }); + // Because the source is potentially undefined, the controller could be undefined and the value of the callback method could be undefined [NL] + const check: CheckType | undefined> = ctrl; + const check2: ReverseCheckType> = ctrl; + const check3: ReverseCheckType> = ctrl; + const check4: ReverseCheckType> = ctrl; + + if (ctrl) { + expect(hostElement.hasController(ctrl)).to.be.true; + } else { + expect(ctrl).to.be.undefined; + } + expect(check === check2 && check3 === check4).to.be.true; // Just to use the const for something. }); }); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/index.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/index.ts index dc76f38eaf..56c390dd50 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/index.ts @@ -5,6 +5,6 @@ export { UMB_DATA_TYPE_DETAIL_STORE_CONTEXT, } from './detail/index.js'; export { UmbDataTypeItemRepository, UMB_DATA_TYPE_ITEM_REPOSITORY_ALIAS } from './item/index.js'; -export { UmbMoveDataTypeRepository, MOVE_DATA_TYPE_REPOSITORY_ALIAS } from './move/index.js'; +export { UmbMoveDataTypeRepository, UMB_MOVE_DATA_TYPE_REPOSITORY_ALIAS } from './move/index.js'; export type { UmbDataTypeItemModel } from './item/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/move/index.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/move/index.ts index 01792b911d..dfc6dcb884 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/move/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/move/index.ts @@ -1,2 +1,2 @@ export { UmbMoveDataTypeRepository } from './data-type-move.repository.js'; -export { UMB_MOVE_DATA_TYPE_REPOSITORY_ALIAS as MOVE_DATA_TYPE_REPOSITORY_ALIAS } from './manifests.js'; +export { UMB_MOVE_DATA_TYPE_REPOSITORY_ALIAS } from './manifests.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/repository/member-collection.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/repository/member-collection.server.data-source.ts index c1bd0e153a..d9df07980f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/repository/member-collection.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/repository/member-collection.server.data-source.ts @@ -1,7 +1,7 @@ -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; import type { UmbMemberDetailModel, UmbMemberValueModel } from '../../types.js'; import { UMB_MEMBER_ENTITY_TYPE } from '../../entity.js'; import type { UmbMemberCollectionFilterModel } from '../types.js'; +import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; import type { UmbCollectionDataSource } from '@umbraco-cms/backoffice/collection'; import type { MemberResponseModel } from '@umbraco-cms/backoffice/external/backend-api'; import { MemberResource } from '@umbraco-cms/backoffice/external/backend-api'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/views/table/member-table-collection-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/views/table/member-table-collection-view.element.ts index ce68591370..6a7a71dff0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/views/table/member-table-collection-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/views/table/member-table-collection-view.element.ts @@ -1,5 +1,5 @@ -import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { UmbMemberCollectionModel } from '../../types.js'; +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { UmbDefaultCollectionContext } from '@umbraco-cms/backoffice/collection'; import { UMB_DEFAULT_COLLECTION_CONTEXT } from '@umbraco-cms/backoffice/collection'; import type { UmbTableColumn, UmbTableConfig, UmbTableItem } from '@umbraco-cms/backoffice/components'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/views/member/member-workspace-view-member-info.element.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/views/member/member-workspace-view-member-info.element.ts index 1c26c2fd29..bd1c6d3fde 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/views/member/member-workspace-view-member-info.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/views/member/member-workspace-view-member-info.element.ts @@ -1,6 +1,6 @@ // import { UMB_COMPOSITION_PICKER_MODAL, type UmbCompositionPickerModalData } from '../../../modals/index.js'; -import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { UmbMemberWorkspaceContext } from '../../member-workspace.context.js'; +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import type { UmbWorkspaceViewElement } from '@umbraco-cms/backoffice/extension-registry';