From 1635e722672bde6d38f06ffabafa662c3b3ca1d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Tue, 10 Dec 2024 19:16:44 +0000 Subject: [PATCH 01/91] refactor(BooleanState): use the default state from the static property `state`, add stored `true` (#onTrueCallback) and `false`(#onFalseCallback) callback functions performed on state changes. Add `is()` `on()` `onFalse()` `onTrue()` `setOnFalse()` `setOnTrue()` methods. --- src/lib/boolean-state.abstract.ts | 139 ++++++++++++++++++++++++++---- 1 file changed, 123 insertions(+), 16 deletions(-) diff --git a/src/lib/boolean-state.abstract.ts b/src/lib/boolean-state.abstract.ts index c729f6f..efaf71d 100644 --- a/src/lib/boolean-state.abstract.ts +++ b/src/lib/boolean-state.abstract.ts @@ -9,60 +9,167 @@ import { State } from "./state.abstract"; * @extends {State} */ export abstract class BooleanState extends State { + /** + * @description Default state for the instance. + * @public + * @static + * @type {boolean} + */ + public static state = true; + + /** + * @description Privately stored callback function performed on state set to `false`. + * @type {*} + */ + #onFalseCallback; + + /** + * @description Privately stored callback function performed on state set to `true`. + * @type {*} + */ + #onTrueCallback; + /** * Creates an instance of parent class. * @constructor - * @param {?boolean} [state] Sets initially boolean state. + * @param {?boolean} [state] Sets initially `boolean` state. + * @param {?() => any} [onTrueCallback] Optional callback function performed on each state change to `true`. + * @param {?() => any} [onFalseCallback] Optional callback function performed on each state change to `false`. */ - constructor(state: boolean = true) { + constructor( + state: boolean = BooleanState.state, + onTrueCallback?: () => any, + onFalseCallback?: () => any, + ) { super(state); + this.#onTrueCallback = onTrueCallback; + this.#onFalseCallback = onFalseCallback; + if (state) { + onTrueCallback?.(); + } else { + onFalseCallback?.(); + } } /** * @description Sets boolean state to `false`. - * @protected + * @public + * @param {*} [callback=this.#onFalseCallback] Performs the callback function if provided. * @returns {this} */ - protected false(): this { + public false(callback = this.#onFalseCallback): this { super.set(false); + typeof callback === 'function' && callback(); return this; } /** - * @description Checks whether state is `false`. - * @protected + * @description Checks the active state and perform callback. + * @public + * @param {?boolean} [expected] Expected state of `boolean` type. + * @param {?(result: boolean) => void} [callback] The callback function with a expected `result`. + * @returns {boolean} + */ + public is(expected?: boolean, callback?: (result: boolean) => void): boolean { + const result = typeof expected === 'boolean' ? this.state === expected : this.state; + callback?.(result); + return result; + } + + /** + * @description Checks whether the state is `false`. + * @public * @returns {boolean} */ - protected isFalse() { + public isFalse() { return super.state === false; } /** - * @description Checks whether state is `true`. - * @protected + * @description Checks whether the state is `true`. + * @public * @returns {boolean} */ - protected isTrue() { - return super.state === true; + public isTrue() { + return super.state === true + } + + /** + * @description Performs the `callback` function on `state`. + * @public + * @param {(state: boolean) => void} stateCallback The callback function with a `state` to perform. + * @returns {this} + */ + public on(stateCallback: (state: boolean) => void): this { + stateCallback(this.state); + return this; + } + + /** + * @description Performs the `callback` function on state `false`. + * @public + * @param {() => void} callback The callback function to perform on state `false`. + * @returns {this} + */ + public onFalse(callback: () => void): this { + this.isFalse() && callback(); + return this; + } + + /** + * @description Performs the `callback` function on state `true`. + * @public + * @param {() => void} callback The callback function to perform on state `true`. + * @returns {this} + */ + public onTrue(callback: () => void): this { + this.isTrue() && callback(); + return this; + } + + /** + * @description Sets the callback function performed on state set to `false`. + * @public + * @param {() => void} onFalseCallback The callback function performed on state `false`. + * @returns {this} + */ + public setOnFalse(onFalseCallback: () => void): this { + typeof onFalseCallback === 'function' && (this.#onFalseCallback = onFalseCallback); + return this; + } + + /** + * @description Sets the callback function performed on state set to `true`. + * @public + * @param {() => void} onTrueCallback The callback function performed on state `true`. + * @returns {this} + */ + public setOnTrue(onTrueCallback: () => void): this { + typeof onTrueCallback === 'function' && (this.#onTrueCallback = onTrueCallback); + return this; } /** * @description Toggle boolean state. - * @protected + * @public * @returns {this} */ - protected toggle(): this { - super.set(!super.state) + public toggle(): this { + super.set(!super.state); + this.#onFalseCallback && this.onFalse(this.#onFalseCallback); + this.#onTrueCallback && this.onTrue(this.#onTrueCallback); return this; } /** * @description Sets boolean state to `true`. - * @protected + * @public + * @param {?() => void} [callback] Performs the callback function if provided. * @returns {this} */ - protected true(): this { + public true(callback = this.#onTrueCallback): this { super.set(true); + typeof callback === 'function' && callback(); return this; } } \ No newline at end of file From d6c4df78395535c06616a470f81c342d72d3cd84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Tue, 10 Dec 2024 19:36:25 +0000 Subject: [PATCH 02/91] refactor(ImmutableState): differ state by using `#locked` name. --- src/lib/immutable-state.abstract.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/immutable-state.abstract.ts b/src/lib/immutable-state.abstract.ts index 6a3f63c..2adfb4e 100644 --- a/src/lib/immutable-state.abstract.ts +++ b/src/lib/immutable-state.abstract.ts @@ -10,7 +10,7 @@ export abstract class ImmutableState { * @description Privately stored locked state as 'locked' if locked, otherwise `undefined`. * @type {?'locked'} */ - #state?: 'locked'; + #locked?: 'locked'; /** * @description "Prevents the modification of existing property attributes and values, and prevents the addition of new properties." @@ -40,7 +40,7 @@ export abstract class ImmutableState { * @returns {"locked"} */ public isLocked() { - return this.#state === 'locked'; + return this.#locked === 'locked'; } /** @@ -71,7 +71,7 @@ export abstract class ImmutableState { if (!this.isFrozen()) { this.freeze(); } - this.#state = 'locked'; + this.#locked = 'locked'; return this; } From 53dabfb06c40eaf2a2d493bfcf0566426a6340b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Tue, 10 Dec 2024 19:41:24 +0000 Subject: [PATCH 03/91] feat: Ability, Enabled, Disabled, Accessibility, Accessible, Inaccessible, Connection, Connected, Disconnected, Expendable, Expanded, Selectable, All, Selected, Visibility, Visible, Invisible, Activated, Active, Available, Deactivated, Edited, Restricted, --- src/lib/ability/ability.class.ts | 85 ++++++++++++++++++++ src/lib/ability/disabled.class.ts | 10 +++ src/lib/ability/enabled.class.ts | 10 +++ src/lib/ability/index.ts | 3 + src/lib/accessibility/accessibility.class.ts | 85 ++++++++++++++++++++ src/lib/accessibility/accessible.class.ts | 49 +++++++++++ src/lib/accessibility/inaccessible.class.ts | 10 +++ src/lib/accessibility/index.ts | 3 + src/lib/activated.class.ts | 10 +++ src/lib/active.class.ts | 10 +++ src/lib/available.class.ts | 10 +++ src/lib/connection/connected.class.ts | 10 +++ src/lib/connection/connection.class..ts | 62 ++++++++++++++ src/lib/connection/disconnected.class.ts | 10 +++ src/lib/connection/index.ts | 3 + src/lib/deactivated.class .ts | 10 +++ src/lib/edited.class.ts | 10 +++ src/lib/expendable/expanded.class.ts | 10 +++ src/lib/expendable/expendable.class.ts | 55 +++++++++++++ src/lib/expendable/index.ts | 2 + src/lib/index.ts | 37 +++++++++ src/lib/restricted.class.ts | 10 +++ src/lib/selectable/all.class.ts | 10 +++ src/lib/selectable/index.ts | 3 + src/lib/selectable/selectable.class.ts | 77 ++++++++++++++++++ src/lib/selectable/selected.class.ts | 38 +++++++++ src/lib/visibility/index.ts | 3 + src/lib/visibility/invisible.class.ts | 10 +++ src/lib/visibility/visibility.class.ts | 62 ++++++++++++++ src/lib/visibility/visible.class.ts | 10 +++ 30 files changed, 717 insertions(+) create mode 100644 src/lib/ability/ability.class.ts create mode 100644 src/lib/ability/disabled.class.ts create mode 100644 src/lib/ability/enabled.class.ts create mode 100644 src/lib/ability/index.ts create mode 100644 src/lib/accessibility/accessibility.class.ts create mode 100644 src/lib/accessibility/accessible.class.ts create mode 100644 src/lib/accessibility/inaccessible.class.ts create mode 100644 src/lib/accessibility/index.ts create mode 100644 src/lib/activated.class.ts create mode 100644 src/lib/active.class.ts create mode 100644 src/lib/available.class.ts create mode 100644 src/lib/connection/connected.class.ts create mode 100644 src/lib/connection/connection.class..ts create mode 100644 src/lib/connection/disconnected.class.ts create mode 100644 src/lib/connection/index.ts create mode 100644 src/lib/deactivated.class .ts create mode 100644 src/lib/edited.class.ts create mode 100644 src/lib/expendable/expanded.class.ts create mode 100644 src/lib/expendable/expendable.class.ts create mode 100644 src/lib/expendable/index.ts create mode 100644 src/lib/restricted.class.ts create mode 100644 src/lib/selectable/all.class.ts create mode 100644 src/lib/selectable/index.ts create mode 100644 src/lib/selectable/selectable.class.ts create mode 100644 src/lib/selectable/selected.class.ts create mode 100644 src/lib/visibility/index.ts create mode 100644 src/lib/visibility/invisible.class.ts create mode 100644 src/lib/visibility/visibility.class.ts create mode 100644 src/lib/visibility/visible.class.ts diff --git a/src/lib/ability/ability.class.ts b/src/lib/ability/ability.class.ts new file mode 100644 index 0000000..35794d0 --- /dev/null +++ b/src/lib/ability/ability.class.ts @@ -0,0 +1,85 @@ +// Class. +import { Disabled } from "./disabled.class"; +import { Enabled } from "./enabled.class"; +/** + * @description Ability as a `boolean` state (enabled/disabled) + * @export + * @class Ability + * @typedef {Ability} + */ +export class Ability { + /** + * @description Default state for the `Disabled` instance. + * @public + * @static + * @type {boolean} + */ + public static disabled = false; + + /** + * @description Default state for the `Enabled` instance. + * @public + * @static + * @type {boolean} + */ + public static enabled = true; + + /** + * @description Privately stored disabled state. + * @type {Disabled} + */ + #disabled = new Disabled(Ability.disabled); + + /** + * @description Privately stored enabled state. + * @type {Enabled} + */ + #enabled = new Enabled(Ability.enabled); + + /** + * Creates an instance of `Ability`. + * @constructor + * @param {?boolean} [enabled] + */ + constructor(enabled?: boolean) { + if (typeof enabled == 'boolean') { + enabled === true ? this.enable() : this.disable(); + } + } + + /** + * @description Disables the ability. + * @returns {this} + */ + public disable(): this { + this.#enabled.false(); + this.#disabled.true(); + return this; + } + + /** + * @description Enables the ability. + * @returns {this} + */ + public enable(): this { + this.#enabled.true(); + this.#disabled.false(); + return this; + } + + /** + * @description Gets the current disabled status of the ability. + * @returns {boolean} + */ + public isDisabled(): boolean { + return this.#disabled.is(); + } + + /** + * @description Gets the current status of the ability. + * @returns {boolean} + */ + public isEnabled(): boolean { + return this.#enabled.is(); + } +} diff --git a/src/lib/ability/disabled.class.ts b/src/lib/ability/disabled.class.ts new file mode 100644 index 0000000..f6519fd --- /dev/null +++ b/src/lib/ability/disabled.class.ts @@ -0,0 +1,10 @@ +// Abstract. +import { BooleanState } from "../boolean-state.abstract"; +/** + * @description Manages the disabled state of `boolean` type. + * @export + * @class Disabled + * @typedef {Disabled} + * @extends {BooleanState} + */ +export class Disabled extends BooleanState {} diff --git a/src/lib/ability/enabled.class.ts b/src/lib/ability/enabled.class.ts new file mode 100644 index 0000000..8d85b2a --- /dev/null +++ b/src/lib/ability/enabled.class.ts @@ -0,0 +1,10 @@ +// Abstract. +import { BooleanState } from "../boolean-state.abstract"; +/** + * @description Manages the enabled state of `boolean` type. + * @export + * @class Enabled + * @typedef {Enabled} + * @extends {BooleanState} + */ +export class Enabled extends BooleanState {} diff --git a/src/lib/ability/index.ts b/src/lib/ability/index.ts new file mode 100644 index 0000000..899e23b --- /dev/null +++ b/src/lib/ability/index.ts @@ -0,0 +1,3 @@ +export { Ability } from './ability.class'; +export { Disabled } from './disabled.class'; +export { Enabled } from './enabled.class'; diff --git a/src/lib/accessibility/accessibility.class.ts b/src/lib/accessibility/accessibility.class.ts new file mode 100644 index 0000000..5101be1 --- /dev/null +++ b/src/lib/accessibility/accessibility.class.ts @@ -0,0 +1,85 @@ +// Class. +import { Ability } from '../ability/ability.class'; +import { Restricted } from '../restricted.class'; +import { Accessible } from './accessible.class'; +import { Inaccessible } from './inaccessible.class'; +/** + * @description Manages the accessible/inaccessible state. + * @export + * @class Accessibility + * @typedef {Accessibility} + * @extends {Ability} + */ +export class Accessibility extends Ability { + /** + * @description Default state for the `Accessible` instance. + * @public + * @static + * @type {boolean} + */ + public static accessible = true; + + /** + * @description Default state for the `Inaccessible` instance. + * @public + * @static + * @type {boolean} + */ + public static inaccessible = true; + + /** + * @description + * @type {*} + */ + #accessible = new Accessible(); + + /** + * @description + * @type {*} + */ + #restricted = new Restricted(); + + /** + * @description + * @type {*} + */ + #inaccessible = new Inaccessible(); + + /** + * @description Sets the accessibility state to accessible if the ability is enabled. + * @public + * @returns {this} + */ + public accessible(): this { + super.isEnabled() && (this.#inaccessible.false(), this.#accessible.true()); + return this; + } + + /** + * @description Sets the accessibility state to inaccessible if the ability is enabled. + * @public + * @returns {this} + */ + public inaccessible(): this { + super.isEnabled() && (this.#inaccessible.true(), this.#accessible.false()); + return this; + } + + /** + * @description Checks whether the accessibility state is accessible. + * @public + * @returns {boolean} + */ + public isAccessible(): boolean { + return this.#accessible.is(); + } + + /** + * @description Checks whether the accessibility state is inaccessible. + * @public + * @returns {boolean} + */ + public isInaccessible(): boolean { + return this.#inaccessible.is(); + } +} diff --git a/src/lib/accessibility/accessible.class.ts b/src/lib/accessibility/accessible.class.ts new file mode 100644 index 0000000..8ead839 --- /dev/null +++ b/src/lib/accessibility/accessible.class.ts @@ -0,0 +1,49 @@ +// Abstract. +import { BooleanState } from "../boolean-state.abstract"; +/** + * @description Manages the accessible state as a `boolean` type . + * @export + * @class Accessible + * @typedef {Accessible} + * @extends {BooleanState} + */ +export class Accessible extends BooleanState { + /** + * Creates an instance of `Accessible`. + * @constructor + * @param {?boolean} [state] + */ + constructor(state?: boolean) { + super(state); + } + + /** + * @description Sets the state to `false`. + * @public + * @returns {this} + */ + public override false(): this { + super.false(); + return this; + } + + /** + * @inheritdoc Toggles `true` and `false` the accessible state. + * @public + * @returns {this} + */ + public override toggle(): this { + super.toggle(); + return this; + } + + /** + * @description Sets the state to `true`. + * @public + * @returns {this} + */ + public override true(): this { + super.true(); + return this; + } +} \ No newline at end of file diff --git a/src/lib/accessibility/inaccessible.class.ts b/src/lib/accessibility/inaccessible.class.ts new file mode 100644 index 0000000..fccea39 --- /dev/null +++ b/src/lib/accessibility/inaccessible.class.ts @@ -0,0 +1,10 @@ +// Abstract. +import { BooleanState } from "../boolean-state.abstract"; +/** + * @description Manages the inaccessible state as a `boolean` type . + * @export + * @class Inaccessible + * @typedef {Inaccessible} + * @extends {BooleanState} + */ +export class Inaccessible extends BooleanState {} \ No newline at end of file diff --git a/src/lib/accessibility/index.ts b/src/lib/accessibility/index.ts new file mode 100644 index 0000000..698176d --- /dev/null +++ b/src/lib/accessibility/index.ts @@ -0,0 +1,3 @@ +export { Accessibility } from "./accessibility.class"; +export { Accessible } from "./accessible.class"; +export { Inaccessible } from "./inaccessible.class"; diff --git a/src/lib/activated.class.ts b/src/lib/activated.class.ts new file mode 100644 index 0000000..03c715c --- /dev/null +++ b/src/lib/activated.class.ts @@ -0,0 +1,10 @@ +// Abstract. +import { BooleanState } from "./boolean-state.abstract"; +/** + * @description Manages the activated state as a `boolean` type . + * @export + * @class Activated + * @typedef {Activated} + * @extends {BooleanState} + */ +export class Activated extends BooleanState {} diff --git a/src/lib/active.class.ts b/src/lib/active.class.ts new file mode 100644 index 0000000..1d9b87f --- /dev/null +++ b/src/lib/active.class.ts @@ -0,0 +1,10 @@ +// Abstract. +import { BooleanState } from "./boolean-state.abstract"; +/** + * @description Manages the active state as a `boolean` type . + * @export + * @class Active + * @typedef {Active} + * @extends {BooleanState} + */ +export class Active extends BooleanState {} \ No newline at end of file diff --git a/src/lib/available.class.ts b/src/lib/available.class.ts new file mode 100644 index 0000000..4ff94f8 --- /dev/null +++ b/src/lib/available.class.ts @@ -0,0 +1,10 @@ +// Abstract. +import { BooleanState } from "./boolean-state.abstract"; +/** + * @description Manages the available state as a `boolean` type . + * @export + * @class Available + * @typedef {Available} + * @extends {BooleanState} + */ +export class Available extends BooleanState {} \ No newline at end of file diff --git a/src/lib/connection/connected.class.ts b/src/lib/connection/connected.class.ts new file mode 100644 index 0000000..b84362d --- /dev/null +++ b/src/lib/connection/connected.class.ts @@ -0,0 +1,10 @@ +// Abstract. +import { BooleanState } from "../boolean-state.abstract"; +/** + * @description Manages the connected state of `boolean` type. + * @export + * @class Connected + * @typedef {Connected} + * @extends {BooleanState} + */ +export class Connected extends BooleanState {} diff --git a/src/lib/connection/connection.class..ts b/src/lib/connection/connection.class..ts new file mode 100644 index 0000000..ca50107 --- /dev/null +++ b/src/lib/connection/connection.class..ts @@ -0,0 +1,62 @@ +// Class. +import { Ability } from '../ability/ability.class'; +import { Connected } from './connected.class'; +import { Disconnected } from './disconnected.class'; +/** + * @description Manages the connected/disconnected state. + * @export + * @class Connection + * @typedef {Connection} + * @extends {Ability} + */ +export class Connection extends Ability { + /** + * @description + * @type {*} + */ + #connected = new Connected(); + + /** + * @description + * @type {*} + */ + #disconnected = new Disconnected(); + + /** + * @description Sets the connection state to connected if the ability is enabled. + * @public + * @returns {this} + */ + public connect(): this { + super.isEnabled() && (this.#disconnected.false(), this.#connected.true()); + return this; + } + + /** + * @description Sets the connection state to disconnected if the ability is enabled. + * @public + * @returns {this} + */ + public disconnect(): this { + super.isEnabled() && (this.#disconnected.true(), this.#connected.false()); + return this; + } + + /** + * @description Checks whether the connection state is connected. + * @public + * @returns {boolean} + */ + public isConnected(): boolean { + return this.#connected.is(); + } + + /** + * @description Checks whether the connection state is disconnected. + * @public + * @returns {boolean} + */ + public isDisconnected(): boolean { + return this.#disconnected.is(); + } +} diff --git a/src/lib/connection/disconnected.class.ts b/src/lib/connection/disconnected.class.ts new file mode 100644 index 0000000..12f2c97 --- /dev/null +++ b/src/lib/connection/disconnected.class.ts @@ -0,0 +1,10 @@ +// Abstract. +import { BooleanState } from "../boolean-state.abstract"; +/** + * @description Manages the disconnected state of `boolean` type. + * @export + * @class Disconnected + * @typedef {Disconnected} + * @extends {BooleanState} + */ +export class Disconnected extends BooleanState {} diff --git a/src/lib/connection/index.ts b/src/lib/connection/index.ts new file mode 100644 index 0000000..b111a2c --- /dev/null +++ b/src/lib/connection/index.ts @@ -0,0 +1,3 @@ +export { Connected } from "./connected.class"; +export { Connection } from "./connection.class."; +export { Disconnected } from "./disconnected.class"; diff --git a/src/lib/deactivated.class .ts b/src/lib/deactivated.class .ts new file mode 100644 index 0000000..e7e9009 --- /dev/null +++ b/src/lib/deactivated.class .ts @@ -0,0 +1,10 @@ +// Abstract. +import { BooleanState } from "./boolean-state.abstract"; +/** + * @description Manages the deactivated state as a `boolean` type . + * @export + * @class Deactivated + * @typedef {Deactivated} + * @extends {BooleanState} + */ +export class Deactivated extends BooleanState {} \ No newline at end of file diff --git a/src/lib/edited.class.ts b/src/lib/edited.class.ts new file mode 100644 index 0000000..fafb193 --- /dev/null +++ b/src/lib/edited.class.ts @@ -0,0 +1,10 @@ +// Abstract. +import { BooleanState } from "./boolean-state.abstract"; +/** + * @description Manages the activated state as a `boolean` type . + * @export + * @class Activated + * @typedef {Edited} + * @extends {BooleanState} + */ +export class Edited extends BooleanState {} \ No newline at end of file diff --git a/src/lib/expendable/expanded.class.ts b/src/lib/expendable/expanded.class.ts new file mode 100644 index 0000000..abbf833 --- /dev/null +++ b/src/lib/expendable/expanded.class.ts @@ -0,0 +1,10 @@ +// Abstract. +import { BooleanState } from "../boolean-state.abstract"; +/** + * @description Manages the expanded state of `boolean` type. + * @export + * @class Expanded + * @typedef {Expanded} + * @extends {BooleanState} + */ +export class Expanded extends BooleanState {} diff --git a/src/lib/expendable/expendable.class.ts b/src/lib/expendable/expendable.class.ts new file mode 100644 index 0000000..4fe7d93 --- /dev/null +++ b/src/lib/expendable/expendable.class.ts @@ -0,0 +1,55 @@ +// Class. +import { Ability } from '../ability/ability.class'; +import { Expanded } from './expanded.class'; +/** + * @description Manages the ability state of `boolean` type. + * @export + * @class Expandable + * @typedef {Expandable} + * @extends {Ability} + */ +export class Expandable extends Ability { + /** + * @description + * @type {*} + */ + #expanded = new Expanded(false); + + /** + * @description Expand the expandable if the ability is enabled. + * @public + * @returns {this} + */ + public expand(): this { + super.isEnabled() && this.#expanded.true(); + return this; + } + + /** + * @description Fold the expandable. + * @public + * @returns {this} + */ + public fold(): this { + super.isEnabled() && this.#expanded.false(); + return this; + } + + /** + * @description Checks whether the expandable is expanded. + * @public + * @returns {boolean} + */ + public isExpanded(): boolean { + return this.#expanded.is(); + } + + /** + * @description Checks whether the expandable is folded. + * @public + * @returns {boolean} + */ + public isFolded(): boolean { + return this.#expanded.is() === false; + } +} diff --git a/src/lib/expendable/index.ts b/src/lib/expendable/index.ts new file mode 100644 index 0000000..e83fcb9 --- /dev/null +++ b/src/lib/expendable/index.ts @@ -0,0 +1,2 @@ +export { Expanded } from "./expanded.class"; +export { Expandable } from "./expendable.class"; diff --git a/src/lib/index.ts b/src/lib/index.ts index 1048a39..e8e86e3 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -1,3 +1,40 @@ +export { + Ability, + Disabled, + Enabled +} from './ability'; +export { + Accessibility, + Accessible, + Inaccessible +} from './accessibility'; +export { + Connected, + Connection, + Disconnected +} from './connection'; +export { + Expandable, + Expanded, +} from './expendable'; +export { + All, + Selectable, + Selected, +} from './selectable'; +export { + Invisible, + Visibility, + Visible, +} from './visibility'; +// Class state. +export { Activated } from './activated.class'; +export { Active } from './active.class'; +export { Available } from './available.class'; +export { Deactivated } from './deactivated.class '; +export { Edited } from './edited.class'; +export { Restricted } from './restricted.class'; +// Abstract state. export { BooleanState } from './boolean-state.abstract'; export { EnumState } from './enum-state.abstract'; export { ImmutableState } from './immutable-state.abstract'; diff --git a/src/lib/restricted.class.ts b/src/lib/restricted.class.ts new file mode 100644 index 0000000..2891733 --- /dev/null +++ b/src/lib/restricted.class.ts @@ -0,0 +1,10 @@ +// Abstract. +import { BooleanState } from "./boolean-state.abstract"; +/** + * @description Manages the restricted state of `boolean` type. + * @export + * @class Restricted + * @typedef {Restricted} + * @extends {BooleanState} + */ +export class Restricted extends BooleanState {} diff --git a/src/lib/selectable/all.class.ts b/src/lib/selectable/all.class.ts new file mode 100644 index 0000000..63999f7 --- /dev/null +++ b/src/lib/selectable/all.class.ts @@ -0,0 +1,10 @@ +// Abstract. +import { BooleanState } from "../boolean-state.abstract"; +/** + * @description Manages the all state of `boolean` type. + * @export + * @class All + * @typedef {All} + * @extends {BooleanState} + */ +export class All extends BooleanState {} diff --git a/src/lib/selectable/index.ts b/src/lib/selectable/index.ts new file mode 100644 index 0000000..dbec100 --- /dev/null +++ b/src/lib/selectable/index.ts @@ -0,0 +1,3 @@ +export { All } from "./all.class"; +export { Selectable } from "./selectable.class"; +export { Selected } from "./selected.class"; diff --git a/src/lib/selectable/selectable.class.ts b/src/lib/selectable/selectable.class.ts new file mode 100644 index 0000000..3a87854 --- /dev/null +++ b/src/lib/selectable/selectable.class.ts @@ -0,0 +1,77 @@ +// Class. +import { Ability } from '../ability/ability.class'; +import { Selected } from './selected.class'; +/** + * @description Manages the selected state. + * @export + * @class Selectable + * @typedef {Selectable} + * @extends {Ability} + */ +export class Selectable extends Ability { + /** + * @description Privately stored selected state. + * @type {*} + */ + #selected = new Selected(); + + /** + * @description Sets the selectable state to unselected if the ability is enabled. + * @public + * @returns {this} + */ + public deselect(): this { + super.isEnabled() && this.#selected.true(); + return this; + } + + /** + * @description Sets the selectable state to unselected if the ability is enabled. + * @public + * @returns {this} + */ + public deselectAll(): this { + super.isEnabled() && this.#selected.all.false(); + return this; + } + + /** + * @description Checks whether the selectable state is selected. + * @public + * @returns {boolean} + */ + public isSelected(): boolean { + return this.#selected.is(); + } + + /** + * @description Sets the selectable state to selected if the ability is enabled. + * @public + * @returns {this} + */ + public select(): this { + super.isEnabled() && this.#selected.true(); + return this; + } + + /** + * @description Sets the selectable state to selected if the ability is enabled. + * @public + * @returns {this} + */ + public selectAll(): this { + super.isEnabled() && this.#selected.all.true(); + return this; + } + + /** + * @description Toggles the selectable state between selected and unselected if the ability is enabled. + * @public + * @returns {this} + */ + public toggle(): this { + super.isEnabled() && this.#selected.toggle(); + return this; + } + +} diff --git a/src/lib/selectable/selected.class.ts b/src/lib/selectable/selected.class.ts new file mode 100644 index 0000000..4451f24 --- /dev/null +++ b/src/lib/selectable/selected.class.ts @@ -0,0 +1,38 @@ +// Class. +import { All } from "./all.class"; +// Abstract. +import { BooleanState } from "../boolean-state.abstract"; +/** + * @description Manages the selected state of `boolean` type. + * @export + * @class Selected + * @typedef {Selected} + * @extends {BooleanState} + */ +export class Selected extends BooleanState { + /** + * @description + * @public + * @returns {*} + */ + public get all() { + return this.#all; + } + + /** + * @description + * @type {boolean} + */ + #all + + /** + * Creates an instance of `Selected`. + * @constructor + * @param {?boolean} [selected] + */ + constructor(selected?: boolean, all = false) { + super(selected); + this.#all = new All(false, () => this.true(), () => this.false()); + typeof all === 'boolean' && all === true && this.#all.true(); + } +} diff --git a/src/lib/visibility/index.ts b/src/lib/visibility/index.ts new file mode 100644 index 0000000..75c79e4 --- /dev/null +++ b/src/lib/visibility/index.ts @@ -0,0 +1,3 @@ +export { Invisible } from "./invisible.class"; +export { Visibility } from "./visibility.class"; +export { Visible } from "./visible.class"; diff --git a/src/lib/visibility/invisible.class.ts b/src/lib/visibility/invisible.class.ts new file mode 100644 index 0000000..7a10571 --- /dev/null +++ b/src/lib/visibility/invisible.class.ts @@ -0,0 +1,10 @@ +// Abstract. +import { BooleanState } from "../boolean-state.abstract"; +/** + * @description Manages the invisible state as a `boolean` type . + * @export + * @class Invisible + * @typedef {Invisible} + * @extends {BooleanState} + */ +export class Invisible extends BooleanState {} \ No newline at end of file diff --git a/src/lib/visibility/visibility.class.ts b/src/lib/visibility/visibility.class.ts new file mode 100644 index 0000000..1ffe451 --- /dev/null +++ b/src/lib/visibility/visibility.class.ts @@ -0,0 +1,62 @@ +// Class. +import { Ability } from '../ability/ability.class'; +import { Invisible } from './invisible.class'; +import { Visible } from './visible.class'; +/** + * @description Manages the visibility state. + * @export + * @class Visibility + * @typedef {Visibility} + * @extends {Ability} + */ +export class Visibility extends Ability { + /** + * @description + * @type {*} + */ + #visible = new Visible(); + + /** + * @description + * @type {*} + */ + #invisible = new Invisible(); + + /** + * @description Sets the visibility to visible if the ability is enabled. + * @public + * @returns {this} + */ + public visible(): this { + super.isEnabled() && (this.#invisible.false(), this.#visible.true()); + return this; + } + + /** + * @description Sets the visibility to invisible if the ability is enabled. + * @public + * @returns {this} + */ + public invisible(): this { + super.isEnabled() && (this.#invisible.true(), this.#visible.false()); + return this; + } + + /** + * @description Checks whether the visibility is visible. + * @public + * @returns {boolean} + */ + public isVisible(): boolean { + return this.#visible.is(); + } + + /** + * @description Checks whether the visibility is invisible. + * @public + * @returns {boolean} + */ + public isInvisible(): boolean { + return this.#invisible.is(); + } +} diff --git a/src/lib/visibility/visible.class.ts b/src/lib/visibility/visible.class.ts new file mode 100644 index 0000000..b3b78c1 --- /dev/null +++ b/src/lib/visibility/visible.class.ts @@ -0,0 +1,10 @@ +// Abstract. +import { BooleanState } from "../boolean-state.abstract"; +/** + * @description Manages the visible state as a `boolean` type . + * @export + * @class Visible + * @typedef {Visible} + * @extends {BooleanState} + */ +export class Visible extends BooleanState {} \ No newline at end of file From cf260f7866c038eabee9122a041deb3c1c18c880 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Wed, 11 Dec 2024 22:07:05 +0000 Subject: [PATCH 04/91] refactor(Ability): use classes using the `as`. --- src/lib/{ability => }/ability.class.ts | 3 +-- src/lib/ability/disabled.class.ts | 10 ---------- src/lib/ability/enabled.class.ts | 10 ---------- src/lib/ability/index.ts | 3 --- 4 files changed, 1 insertion(+), 25 deletions(-) rename src/lib/{ability => }/ability.class.ts (94%) delete mode 100644 src/lib/ability/disabled.class.ts delete mode 100644 src/lib/ability/enabled.class.ts delete mode 100644 src/lib/ability/index.ts diff --git a/src/lib/ability/ability.class.ts b/src/lib/ability.class.ts similarity index 94% rename from src/lib/ability/ability.class.ts rename to src/lib/ability.class.ts index 35794d0..4ad0532 100644 --- a/src/lib/ability/ability.class.ts +++ b/src/lib/ability.class.ts @@ -1,6 +1,5 @@ // Class. -import { Disabled } from "./disabled.class"; -import { Enabled } from "./enabled.class"; +import { Boolean as Disabled, Boolean as Enabled } from "./boolean.class"; /** * @description Ability as a `boolean` state (enabled/disabled) * @export diff --git a/src/lib/ability/disabled.class.ts b/src/lib/ability/disabled.class.ts deleted file mode 100644 index f6519fd..0000000 --- a/src/lib/ability/disabled.class.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Abstract. -import { BooleanState } from "../boolean-state.abstract"; -/** - * @description Manages the disabled state of `boolean` type. - * @export - * @class Disabled - * @typedef {Disabled} - * @extends {BooleanState} - */ -export class Disabled extends BooleanState {} diff --git a/src/lib/ability/enabled.class.ts b/src/lib/ability/enabled.class.ts deleted file mode 100644 index 8d85b2a..0000000 --- a/src/lib/ability/enabled.class.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Abstract. -import { BooleanState } from "../boolean-state.abstract"; -/** - * @description Manages the enabled state of `boolean` type. - * @export - * @class Enabled - * @typedef {Enabled} - * @extends {BooleanState} - */ -export class Enabled extends BooleanState {} diff --git a/src/lib/ability/index.ts b/src/lib/ability/index.ts deleted file mode 100644 index 899e23b..0000000 --- a/src/lib/ability/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { Ability } from './ability.class'; -export { Disabled } from './disabled.class'; -export { Enabled } from './enabled.class'; From 05fc30ede526aba31d443fd8603f28e19b9b29b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Wed, 11 Dec 2024 22:08:03 +0000 Subject: [PATCH 05/91] refactor: remove in favor of using `as`. --- src/lib/accessibility/accessibility.class.ts | 85 -------------------- src/lib/accessibility/accessible.class.ts | 49 ----------- src/lib/accessibility/inaccessible.class.ts | 10 --- src/lib/accessibility/index.ts | 3 - src/lib/activated.class.ts | 10 --- src/lib/active.class.ts | 10 --- src/lib/available.class.ts | 10 --- src/lib/connection/connected.class.ts | 10 --- src/lib/connection/connection.class..ts | 62 -------------- src/lib/connection/disconnected.class.ts | 10 --- src/lib/connection/index.ts | 3 - src/lib/deactivated.class .ts | 10 --- src/lib/edited.class.ts | 10 --- src/lib/expendable/expanded.class.ts | 10 --- src/lib/expendable/expendable.class.ts | 55 ------------- src/lib/expendable/index.ts | 2 - src/lib/restricted.class.ts | 10 --- src/lib/selectable/all.class.ts | 10 --- src/lib/visibility/index.ts | 3 - src/lib/visibility/invisible.class.ts | 10 --- src/lib/visibility/visibility.class.ts | 62 -------------- src/lib/visibility/visible.class.ts | 10 --- 22 files changed, 454 deletions(-) delete mode 100644 src/lib/accessibility/accessibility.class.ts delete mode 100644 src/lib/accessibility/accessible.class.ts delete mode 100644 src/lib/accessibility/inaccessible.class.ts delete mode 100644 src/lib/accessibility/index.ts delete mode 100644 src/lib/activated.class.ts delete mode 100644 src/lib/active.class.ts delete mode 100644 src/lib/available.class.ts delete mode 100644 src/lib/connection/connected.class.ts delete mode 100644 src/lib/connection/connection.class..ts delete mode 100644 src/lib/connection/disconnected.class.ts delete mode 100644 src/lib/connection/index.ts delete mode 100644 src/lib/deactivated.class .ts delete mode 100644 src/lib/edited.class.ts delete mode 100644 src/lib/expendable/expanded.class.ts delete mode 100644 src/lib/expendable/expendable.class.ts delete mode 100644 src/lib/expendable/index.ts delete mode 100644 src/lib/restricted.class.ts delete mode 100644 src/lib/selectable/all.class.ts delete mode 100644 src/lib/visibility/index.ts delete mode 100644 src/lib/visibility/invisible.class.ts delete mode 100644 src/lib/visibility/visibility.class.ts delete mode 100644 src/lib/visibility/visible.class.ts diff --git a/src/lib/accessibility/accessibility.class.ts b/src/lib/accessibility/accessibility.class.ts deleted file mode 100644 index 5101be1..0000000 --- a/src/lib/accessibility/accessibility.class.ts +++ /dev/null @@ -1,85 +0,0 @@ -// Class. -import { Ability } from '../ability/ability.class'; -import { Restricted } from '../restricted.class'; -import { Accessible } from './accessible.class'; -import { Inaccessible } from './inaccessible.class'; -/** - * @description Manages the accessible/inaccessible state. - * @export - * @class Accessibility - * @typedef {Accessibility} - * @extends {Ability} - */ -export class Accessibility extends Ability { - /** - * @description Default state for the `Accessible` instance. - * @public - * @static - * @type {boolean} - */ - public static accessible = true; - - /** - * @description Default state for the `Inaccessible` instance. - * @public - * @static - * @type {boolean} - */ - public static inaccessible = true; - - /** - * @description - * @type {*} - */ - #accessible = new Accessible(); - - /** - * @description - * @type {*} - */ - #restricted = new Restricted(); - - /** - * @description - * @type {*} - */ - #inaccessible = new Inaccessible(); - - /** - * @description Sets the accessibility state to accessible if the ability is enabled. - * @public - * @returns {this} - */ - public accessible(): this { - super.isEnabled() && (this.#inaccessible.false(), this.#accessible.true()); - return this; - } - - /** - * @description Sets the accessibility state to inaccessible if the ability is enabled. - * @public - * @returns {this} - */ - public inaccessible(): this { - super.isEnabled() && (this.#inaccessible.true(), this.#accessible.false()); - return this; - } - - /** - * @description Checks whether the accessibility state is accessible. - * @public - * @returns {boolean} - */ - public isAccessible(): boolean { - return this.#accessible.is(); - } - - /** - * @description Checks whether the accessibility state is inaccessible. - * @public - * @returns {boolean} - */ - public isInaccessible(): boolean { - return this.#inaccessible.is(); - } -} diff --git a/src/lib/accessibility/accessible.class.ts b/src/lib/accessibility/accessible.class.ts deleted file mode 100644 index 8ead839..0000000 --- a/src/lib/accessibility/accessible.class.ts +++ /dev/null @@ -1,49 +0,0 @@ -// Abstract. -import { BooleanState } from "../boolean-state.abstract"; -/** - * @description Manages the accessible state as a `boolean` type . - * @export - * @class Accessible - * @typedef {Accessible} - * @extends {BooleanState} - */ -export class Accessible extends BooleanState { - /** - * Creates an instance of `Accessible`. - * @constructor - * @param {?boolean} [state] - */ - constructor(state?: boolean) { - super(state); - } - - /** - * @description Sets the state to `false`. - * @public - * @returns {this} - */ - public override false(): this { - super.false(); - return this; - } - - /** - * @inheritdoc Toggles `true` and `false` the accessible state. - * @public - * @returns {this} - */ - public override toggle(): this { - super.toggle(); - return this; - } - - /** - * @description Sets the state to `true`. - * @public - * @returns {this} - */ - public override true(): this { - super.true(); - return this; - } -} \ No newline at end of file diff --git a/src/lib/accessibility/inaccessible.class.ts b/src/lib/accessibility/inaccessible.class.ts deleted file mode 100644 index fccea39..0000000 --- a/src/lib/accessibility/inaccessible.class.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Abstract. -import { BooleanState } from "../boolean-state.abstract"; -/** - * @description Manages the inaccessible state as a `boolean` type . - * @export - * @class Inaccessible - * @typedef {Inaccessible} - * @extends {BooleanState} - */ -export class Inaccessible extends BooleanState {} \ No newline at end of file diff --git a/src/lib/accessibility/index.ts b/src/lib/accessibility/index.ts deleted file mode 100644 index 698176d..0000000 --- a/src/lib/accessibility/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { Accessibility } from "./accessibility.class"; -export { Accessible } from "./accessible.class"; -export { Inaccessible } from "./inaccessible.class"; diff --git a/src/lib/activated.class.ts b/src/lib/activated.class.ts deleted file mode 100644 index 03c715c..0000000 --- a/src/lib/activated.class.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Abstract. -import { BooleanState } from "./boolean-state.abstract"; -/** - * @description Manages the activated state as a `boolean` type . - * @export - * @class Activated - * @typedef {Activated} - * @extends {BooleanState} - */ -export class Activated extends BooleanState {} diff --git a/src/lib/active.class.ts b/src/lib/active.class.ts deleted file mode 100644 index 1d9b87f..0000000 --- a/src/lib/active.class.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Abstract. -import { BooleanState } from "./boolean-state.abstract"; -/** - * @description Manages the active state as a `boolean` type . - * @export - * @class Active - * @typedef {Active} - * @extends {BooleanState} - */ -export class Active extends BooleanState {} \ No newline at end of file diff --git a/src/lib/available.class.ts b/src/lib/available.class.ts deleted file mode 100644 index 4ff94f8..0000000 --- a/src/lib/available.class.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Abstract. -import { BooleanState } from "./boolean-state.abstract"; -/** - * @description Manages the available state as a `boolean` type . - * @export - * @class Available - * @typedef {Available} - * @extends {BooleanState} - */ -export class Available extends BooleanState {} \ No newline at end of file diff --git a/src/lib/connection/connected.class.ts b/src/lib/connection/connected.class.ts deleted file mode 100644 index b84362d..0000000 --- a/src/lib/connection/connected.class.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Abstract. -import { BooleanState } from "../boolean-state.abstract"; -/** - * @description Manages the connected state of `boolean` type. - * @export - * @class Connected - * @typedef {Connected} - * @extends {BooleanState} - */ -export class Connected extends BooleanState {} diff --git a/src/lib/connection/connection.class..ts b/src/lib/connection/connection.class..ts deleted file mode 100644 index ca50107..0000000 --- a/src/lib/connection/connection.class..ts +++ /dev/null @@ -1,62 +0,0 @@ -// Class. -import { Ability } from '../ability/ability.class'; -import { Connected } from './connected.class'; -import { Disconnected } from './disconnected.class'; -/** - * @description Manages the connected/disconnected state. - * @export - * @class Connection - * @typedef {Connection} - * @extends {Ability} - */ -export class Connection extends Ability { - /** - * @description - * @type {*} - */ - #connected = new Connected(); - - /** - * @description - * @type {*} - */ - #disconnected = new Disconnected(); - - /** - * @description Sets the connection state to connected if the ability is enabled. - * @public - * @returns {this} - */ - public connect(): this { - super.isEnabled() && (this.#disconnected.false(), this.#connected.true()); - return this; - } - - /** - * @description Sets the connection state to disconnected if the ability is enabled. - * @public - * @returns {this} - */ - public disconnect(): this { - super.isEnabled() && (this.#disconnected.true(), this.#connected.false()); - return this; - } - - /** - * @description Checks whether the connection state is connected. - * @public - * @returns {boolean} - */ - public isConnected(): boolean { - return this.#connected.is(); - } - - /** - * @description Checks whether the connection state is disconnected. - * @public - * @returns {boolean} - */ - public isDisconnected(): boolean { - return this.#disconnected.is(); - } -} diff --git a/src/lib/connection/disconnected.class.ts b/src/lib/connection/disconnected.class.ts deleted file mode 100644 index 12f2c97..0000000 --- a/src/lib/connection/disconnected.class.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Abstract. -import { BooleanState } from "../boolean-state.abstract"; -/** - * @description Manages the disconnected state of `boolean` type. - * @export - * @class Disconnected - * @typedef {Disconnected} - * @extends {BooleanState} - */ -export class Disconnected extends BooleanState {} diff --git a/src/lib/connection/index.ts b/src/lib/connection/index.ts deleted file mode 100644 index b111a2c..0000000 --- a/src/lib/connection/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { Connected } from "./connected.class"; -export { Connection } from "./connection.class."; -export { Disconnected } from "./disconnected.class"; diff --git a/src/lib/deactivated.class .ts b/src/lib/deactivated.class .ts deleted file mode 100644 index e7e9009..0000000 --- a/src/lib/deactivated.class .ts +++ /dev/null @@ -1,10 +0,0 @@ -// Abstract. -import { BooleanState } from "./boolean-state.abstract"; -/** - * @description Manages the deactivated state as a `boolean` type . - * @export - * @class Deactivated - * @typedef {Deactivated} - * @extends {BooleanState} - */ -export class Deactivated extends BooleanState {} \ No newline at end of file diff --git a/src/lib/edited.class.ts b/src/lib/edited.class.ts deleted file mode 100644 index fafb193..0000000 --- a/src/lib/edited.class.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Abstract. -import { BooleanState } from "./boolean-state.abstract"; -/** - * @description Manages the activated state as a `boolean` type . - * @export - * @class Activated - * @typedef {Edited} - * @extends {BooleanState} - */ -export class Edited extends BooleanState {} \ No newline at end of file diff --git a/src/lib/expendable/expanded.class.ts b/src/lib/expendable/expanded.class.ts deleted file mode 100644 index abbf833..0000000 --- a/src/lib/expendable/expanded.class.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Abstract. -import { BooleanState } from "../boolean-state.abstract"; -/** - * @description Manages the expanded state of `boolean` type. - * @export - * @class Expanded - * @typedef {Expanded} - * @extends {BooleanState} - */ -export class Expanded extends BooleanState {} diff --git a/src/lib/expendable/expendable.class.ts b/src/lib/expendable/expendable.class.ts deleted file mode 100644 index 4fe7d93..0000000 --- a/src/lib/expendable/expendable.class.ts +++ /dev/null @@ -1,55 +0,0 @@ -// Class. -import { Ability } from '../ability/ability.class'; -import { Expanded } from './expanded.class'; -/** - * @description Manages the ability state of `boolean` type. - * @export - * @class Expandable - * @typedef {Expandable} - * @extends {Ability} - */ -export class Expandable extends Ability { - /** - * @description - * @type {*} - */ - #expanded = new Expanded(false); - - /** - * @description Expand the expandable if the ability is enabled. - * @public - * @returns {this} - */ - public expand(): this { - super.isEnabled() && this.#expanded.true(); - return this; - } - - /** - * @description Fold the expandable. - * @public - * @returns {this} - */ - public fold(): this { - super.isEnabled() && this.#expanded.false(); - return this; - } - - /** - * @description Checks whether the expandable is expanded. - * @public - * @returns {boolean} - */ - public isExpanded(): boolean { - return this.#expanded.is(); - } - - /** - * @description Checks whether the expandable is folded. - * @public - * @returns {boolean} - */ - public isFolded(): boolean { - return this.#expanded.is() === false; - } -} diff --git a/src/lib/expendable/index.ts b/src/lib/expendable/index.ts deleted file mode 100644 index e83fcb9..0000000 --- a/src/lib/expendable/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { Expanded } from "./expanded.class"; -export { Expandable } from "./expendable.class"; diff --git a/src/lib/restricted.class.ts b/src/lib/restricted.class.ts deleted file mode 100644 index 2891733..0000000 --- a/src/lib/restricted.class.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Abstract. -import { BooleanState } from "./boolean-state.abstract"; -/** - * @description Manages the restricted state of `boolean` type. - * @export - * @class Restricted - * @typedef {Restricted} - * @extends {BooleanState} - */ -export class Restricted extends BooleanState {} diff --git a/src/lib/selectable/all.class.ts b/src/lib/selectable/all.class.ts deleted file mode 100644 index 63999f7..0000000 --- a/src/lib/selectable/all.class.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Abstract. -import { BooleanState } from "../boolean-state.abstract"; -/** - * @description Manages the all state of `boolean` type. - * @export - * @class All - * @typedef {All} - * @extends {BooleanState} - */ -export class All extends BooleanState {} diff --git a/src/lib/visibility/index.ts b/src/lib/visibility/index.ts deleted file mode 100644 index 75c79e4..0000000 --- a/src/lib/visibility/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { Invisible } from "./invisible.class"; -export { Visibility } from "./visibility.class"; -export { Visible } from "./visible.class"; diff --git a/src/lib/visibility/invisible.class.ts b/src/lib/visibility/invisible.class.ts deleted file mode 100644 index 7a10571..0000000 --- a/src/lib/visibility/invisible.class.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Abstract. -import { BooleanState } from "../boolean-state.abstract"; -/** - * @description Manages the invisible state as a `boolean` type . - * @export - * @class Invisible - * @typedef {Invisible} - * @extends {BooleanState} - */ -export class Invisible extends BooleanState {} \ No newline at end of file diff --git a/src/lib/visibility/visibility.class.ts b/src/lib/visibility/visibility.class.ts deleted file mode 100644 index 1ffe451..0000000 --- a/src/lib/visibility/visibility.class.ts +++ /dev/null @@ -1,62 +0,0 @@ -// Class. -import { Ability } from '../ability/ability.class'; -import { Invisible } from './invisible.class'; -import { Visible } from './visible.class'; -/** - * @description Manages the visibility state. - * @export - * @class Visibility - * @typedef {Visibility} - * @extends {Ability} - */ -export class Visibility extends Ability { - /** - * @description - * @type {*} - */ - #visible = new Visible(); - - /** - * @description - * @type {*} - */ - #invisible = new Invisible(); - - /** - * @description Sets the visibility to visible if the ability is enabled. - * @public - * @returns {this} - */ - public visible(): this { - super.isEnabled() && (this.#invisible.false(), this.#visible.true()); - return this; - } - - /** - * @description Sets the visibility to invisible if the ability is enabled. - * @public - * @returns {this} - */ - public invisible(): this { - super.isEnabled() && (this.#invisible.true(), this.#visible.false()); - return this; - } - - /** - * @description Checks whether the visibility is visible. - * @public - * @returns {boolean} - */ - public isVisible(): boolean { - return this.#visible.is(); - } - - /** - * @description Checks whether the visibility is invisible. - * @public - * @returns {boolean} - */ - public isInvisible(): boolean { - return this.#invisible.is(); - } -} diff --git a/src/lib/visibility/visible.class.ts b/src/lib/visibility/visible.class.ts deleted file mode 100644 index b3b78c1..0000000 --- a/src/lib/visibility/visible.class.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Abstract. -import { BooleanState } from "../boolean-state.abstract"; -/** - * @description Manages the visible state as a `boolean` type . - * @export - * @class Visible - * @typedef {Visible} - * @extends {BooleanState} - */ -export class Visible extends BooleanState {} \ No newline at end of file From a63027dfc6aa5e20966ea3f8523a9f349b1ac7ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Fri, 13 Dec 2024 20:14:26 +0000 Subject: [PATCH 06/91] refactor(BooleanState): add `canChange` feature, move `on()` method to `State`. --- src/lib/boolean-state.abstract.ts | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/src/lib/boolean-state.abstract.ts b/src/lib/boolean-state.abstract.ts index efaf71d..2f24227 100644 --- a/src/lib/boolean-state.abstract.ts +++ b/src/lib/boolean-state.abstract.ts @@ -32,23 +32,21 @@ export abstract class BooleanState extends State { /** * Creates an instance of parent class. * @constructor - * @param {?boolean} [state] Sets initially `boolean` state. + * @param {boolean} [state=BooleanState.state] Sets initially `boolean` state. + * @param {(boolean | ((newState: boolean, currentState: boolean) => boolean))} [canChange=true] * @param {?() => any} [onTrueCallback] Optional callback function performed on each state change to `true`. * @param {?() => any} [onFalseCallback] Optional callback function performed on each state change to `false`. */ constructor( state: boolean = BooleanState.state, + canChange: boolean | ((newState: boolean, currentState: boolean) => boolean) = true, onTrueCallback?: () => any, onFalseCallback?: () => any, ) { - super(state); + super(state, canChange); this.#onTrueCallback = onTrueCallback; this.#onFalseCallback = onFalseCallback; - if (state) { - onTrueCallback?.(); - } else { - onFalseCallback?.(); - } + state ? onTrueCallback?.() : onFalseCallback?.(); } /** @@ -94,17 +92,6 @@ export abstract class BooleanState extends State { return super.state === true } - /** - * @description Performs the `callback` function on `state`. - * @public - * @param {(state: boolean) => void} stateCallback The callback function with a `state` to perform. - * @returns {this} - */ - public on(stateCallback: (state: boolean) => void): this { - stateCallback(this.state); - return this; - } - /** * @description Performs the `callback` function on state `false`. * @public From e4cfa8808200330f4466856ecfd1eee3c11fb436 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Fri, 13 Dec 2024 20:16:33 +0000 Subject: [PATCH 07/91] refactor(State): add `canChange` feature to determine whether the `state` could be changed, and add `on()` method from `BooleanState`. --- src/lib/state.abstract.ts | 46 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/src/lib/state.abstract.ts b/src/lib/state.abstract.ts index a20bd18..1727d78 100644 --- a/src/lib/state.abstract.ts +++ b/src/lib/state.abstract.ts @@ -20,6 +20,12 @@ export abstract class State extends ImmutableState { return this.#state; } + /** + * @description + * @type {(boolean | ((newState: Type, currentState: Type) => boolean))} + */ + #canChange: boolean | ((newState: Type, currentState: Type) => boolean) = true; + /** * @description Privately stored state of `Type`. * @private @@ -30,11 +36,40 @@ export abstract class State extends ImmutableState { /** * Creates an instance of parent class. * @constructor - * @param {Type} [initialState] Initial state of `Type`. + * @param {Type} initialState Initial state of `Type`. + * @param {(boolean | ((newState: Type, currentState: Type) => boolean))} [canChange=true] */ - constructor(initialState: Type) { + constructor( + initialState: Type, + canChange: boolean | ((newState: Type, currentState: Type) => boolean) = true + ) { super(); this.set(initialState); + this.#canChange = canChange; + } + + /** + * @description + * @public + * @param {(boolean | ((newState: Type, currentState: Type) => boolean))} [canChange=true] + * @returns {this} + */ + public canChange( + canChange: boolean | ((newState: Type, currentState: Type) => boolean) = true, + ): this { + this.#canChange = canChange; + return this; + } + + /** + * @description Performs the `callback` function on `state`. + * @public + * @param {(state: Type) => void} stateCallback The callback function with a `state` to perform. + * @returns {this} + */ + public on(stateCallback: (state: Type) => void): this { + stateCallback(this.#state); + return this; } /** @@ -47,7 +82,12 @@ export abstract class State extends ImmutableState { if (super.isLocked()) { throw new Error('Cannot set when object is locked.'); } - this.#state = state; + + const canChange = typeof this.#canChange === 'boolean' + ? this.#canChange + : this.#canChange(state, this.#state); + + canChange === true && (this.#state = state); return this; } } From 234acbaad2f80e79602688a6bf12cb63e9138750 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sat, 14 Dec 2024 00:30:34 +0000 Subject: [PATCH 08/91] feat(Boolean): add non `abstract` class `Boolean` to import with the `as`. --- src/lib/boolean.class.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/lib/boolean.class.ts diff --git a/src/lib/boolean.class.ts b/src/lib/boolean.class.ts new file mode 100644 index 0000000..25e2c5d --- /dev/null +++ b/src/lib/boolean.class.ts @@ -0,0 +1,10 @@ +// Abstract. +import { BooleanState } from "./boolean-state.abstract"; +/** + * @description Handles the `boolean` type state. + * @export + * @class Boolean + * @typedef {Boolean} + * @extends {BooleanState} + */ +export class Boolean extends BooleanState {} From 6b1821be6d7c62926d66d1905ac410b34a9c15d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sat, 14 Dec 2024 00:31:04 +0000 Subject: [PATCH 09/91] feat(BooleanStates): add class to handle multiple `Boolean` states. --- src/lib/boolean-states.class.ts | 113 ++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 src/lib/boolean-states.class.ts diff --git a/src/lib/boolean-states.class.ts b/src/lib/boolean-states.class.ts new file mode 100644 index 0000000..7efd26f --- /dev/null +++ b/src/lib/boolean-states.class.ts @@ -0,0 +1,113 @@ +// Class. +import { Boolean } from "./boolean.class"; +/** + * @description The class to handle multiple `Boolean` states of the specified names. + * @export + * @class BooleanStates + * @typedef {BooleanStates} + * @template {string} [Names=string] + * @template {Boolean} [Object=Boolean] + */ +export class BooleanStates< + Names extends string = string, + Object extends Boolean = Boolean +> { + /** + * @description The state object of the specified `names`. + * @public + * @type {{ [K in Names]: Object }} + */ + public state: { [K in Names]: Object } = {} as any; + + /** + * Creates an instance of `BooleanStates`. + * @constructor + * @param {Names[]} names The names of `Object` states. + * @param {new (...args: any[]) => Object} [object=Boolean as unknown as new (...args: any[]) => Object] + */ + constructor( + names: Names[], + object: new (...args: any[]) => Object = Boolean as unknown as new (...args: any[]) => Object + ) { + names.forEach((name) => this.state[name] = new object()); + } + + /** + * @description Sets the `canChange` to the states of the specified `names`. + * @public + * @param {(boolean | ((newState: boolean, currentState: boolean) => boolean))} [canChange=true] + * @param {...Names[]} names The names of `Object` states to set the `canChange`. + * @returns {this} + */ + public canChange( + canChange: boolean | ((newState: boolean, currentState: boolean) => boolean) = true, + ...names: Names[] + ): this { + (names || Object.keys(this.state)).forEach(name => this.get(name).canChange(canChange)); + return this; + } + + /** + * @description Sets the state to `false in `Object` states of the specified `names`. + * @public + * @template {Names} Name + * @param {...Name[]} names The names to set the state to `false`. + * @returns {this} + */ + public false(...names: Name[]): this { + (names || Object.keys(this.state)).forEach(name => this.get(name).false()); + return this; + } + + /** + * @description Gets the `Object` state of the specified `name`. + * @public + * @template {Names} Name + * @param {Name} name The name of generic type variable `Name` to get. + * @returns {Object} + */ + public get(name: Name): Object { + if (this.state.hasOwnProperty(name)) { + return this.state[name]; + } else { + throw new Error(`State with name '${name}' does not exist.`); + } + } + + /** + * @description Picks the states of the specified `names` into the returned `object`. + * @public + * @template {Names} Name + * @param {...Name[]} names The names to pick to the returned `object`. + * @returns {{ [Key in Name]: Object }} + */ + public pick(...names: Name[]) { + const result = {} as { [Key in Name]: Object }; + ((names || Object.keys(this.state)) as Name[]).reduce((acc, name) => (Object.assign(acc, {[name]: this.get(name)}), acc), result); + return result; + } + + /** + * @description Toggles the state of the specified `names`. + * @public + * @template {Names} Name + * @param {...Name[]} names The `names` to toggle the state. + * @returns {this} + */ + public toggle(...names: Name[]): this { + (names || Object.keys(this.state)).forEach(name => this.get(name).toggle()); + return this; + } + + /** + * @description Sets the state to `true in `Object` states of the specified `names`. + * @public + * @template {Names} Name + * @param {...Name[]} names Arbitrary list of state `names` to sets to `true`. + * @returns {this} + */ + public true(...names: Name[]): this { + (names || Object.keys(this.state)).forEach(name => this.get(name).true()); + return this; + } +} From 3460bee3c7c4639d32da9eea89fbeb32a194ae21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 15 Dec 2024 14:42:18 +0000 Subject: [PATCH 10/91] refactor(State): simplify to use with the mixins or with a different approach of restricting state changes. --- src/lib/state.abstract.ts | 51 +++++++-------------------------------- 1 file changed, 9 insertions(+), 42 deletions(-) diff --git a/src/lib/state.abstract.ts b/src/lib/state.abstract.ts index 1727d78..f88b057 100644 --- a/src/lib/state.abstract.ts +++ b/src/lib/state.abstract.ts @@ -1,11 +1,10 @@ // Abstract. import { ImmutableState } from "./immutable-state.abstract"; /** - * @description Common class for setting the state of `Type`. + * @description Common `abstract class` for setting the state of the generic type variable `Type`. * @export * @abstract * @class State - * @typedef {State} * @template Type * @extends {ImmutableState} */ @@ -16,16 +15,10 @@ export abstract class State extends ImmutableState { * @readonly * @type {Type} */ - public get state() { + public get state(): Type { return this.#state; } - /** - * @description - * @type {(boolean | ((newState: Type, currentState: Type) => boolean))} - */ - #canChange: boolean | ((newState: Type, currentState: Type) => boolean) = true; - /** * @description Privately stored state of `Type`. * @private @@ -37,30 +30,12 @@ export abstract class State extends ImmutableState { * Creates an instance of parent class. * @constructor * @param {Type} initialState Initial state of `Type`. - * @param {(boolean | ((newState: Type, currentState: Type) => boolean))} [canChange=true] */ - constructor( - initialState: Type, - canChange: boolean | ((newState: Type, currentState: Type) => boolean) = true - ) { + constructor(initialState: Type) { super(); - this.set(initialState); - this.#canChange = canChange; + this.#state = initialState; } - - /** - * @description - * @public - * @param {(boolean | ((newState: Type, currentState: Type) => boolean))} [canChange=true] - * @returns {this} - */ - public canChange( - canChange: boolean | ((newState: Type, currentState: Type) => boolean) = true, - ): this { - this.#canChange = canChange; - return this; - } - + /** * @description Performs the `callback` function on `state`. * @public @@ -73,21 +48,13 @@ export abstract class State extends ImmutableState { } /** - * @description Sets the state if the object is not locked. + * @description Sets the state if the object is not locked and is allowed. * @public - * @param {Type} state + * @param {Type} state The state of `Type` to set. * @returns {this} */ - protected set(state: Type) { - if (super.isLocked()) { - throw new Error('Cannot set when object is locked.'); - } - - const canChange = typeof this.#canChange === 'boolean' - ? this.#canChange - : this.#canChange(state, this.#state); - - canChange === true && (this.#state = state); + protected set(state: Type): this { + this.#state = state; return this; } } From 2f450da38adc241d6d124b2812e065fc4f801cce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 15 Dec 2024 14:57:03 +0000 Subject: [PATCH 11/91] refactor(BooleanState): remove the `canChange` and set proper description. --- src/lib/boolean-state.abstract.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/lib/boolean-state.abstract.ts b/src/lib/boolean-state.abstract.ts index 2f24227..c2a81d9 100644 --- a/src/lib/boolean-state.abstract.ts +++ b/src/lib/boolean-state.abstract.ts @@ -5,7 +5,6 @@ import { State } from "./state.abstract"; * @export * @abstract * @class BooleanState - * @typedef {BooleanState} * @extends {State} */ export abstract class BooleanState extends State { @@ -30,20 +29,18 @@ export abstract class BooleanState extends State { #onTrueCallback; /** - * Creates an instance of parent class. + * Creates an instance of child class. * @constructor * @param {boolean} [state=BooleanState.state] Sets initially `boolean` state. - * @param {(boolean | ((newState: boolean, currentState: boolean) => boolean))} [canChange=true] * @param {?() => any} [onTrueCallback] Optional callback function performed on each state change to `true`. * @param {?() => any} [onFalseCallback] Optional callback function performed on each state change to `false`. */ constructor( state: boolean = BooleanState.state, - canChange: boolean | ((newState: boolean, currentState: boolean) => boolean) = true, onTrueCallback?: () => any, onFalseCallback?: () => any, ) { - super(state, canChange); + super(state); this.#onTrueCallback = onTrueCallback; this.#onFalseCallback = onFalseCallback; state ? onTrueCallback?.() : onFalseCallback?.(); From 5f2a76a3b088899e132e9739e9ab8ab759f5898c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 15 Dec 2024 14:57:31 +0000 Subject: [PATCH 12/91] refactor(BooleanStates): remove the `canChange` and update description. --- src/lib/boolean-states.class.ts | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/lib/boolean-states.class.ts b/src/lib/boolean-states.class.ts index 7efd26f..1712a24 100644 --- a/src/lib/boolean-states.class.ts +++ b/src/lib/boolean-states.class.ts @@ -4,7 +4,6 @@ import { Boolean } from "./boolean.class"; * @description The class to handle multiple `Boolean` states of the specified names. * @export * @class BooleanStates - * @typedef {BooleanStates} * @template {string} [Names=string] * @template {Boolean} [Object=Boolean] */ @@ -32,21 +31,6 @@ export class BooleanStates< names.forEach((name) => this.state[name] = new object()); } - /** - * @description Sets the `canChange` to the states of the specified `names`. - * @public - * @param {(boolean | ((newState: boolean, currentState: boolean) => boolean))} [canChange=true] - * @param {...Names[]} names The names of `Object` states to set the `canChange`. - * @returns {this} - */ - public canChange( - canChange: boolean | ((newState: boolean, currentState: boolean) => boolean) = true, - ...names: Names[] - ): this { - (names || Object.keys(this.state)).forEach(name => this.get(name).canChange(canChange)); - return this; - } - /** * @description Sets the state to `false in `Object` states of the specified `names`. * @public From 9ba0d2c63bb74fbd9eadd6ce2e4614b4d54522fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 15 Dec 2024 14:58:59 +0000 Subject: [PATCH 13/91] docs(NullState, NumberState, State): update. --- src/lib/null-state.abstract.ts | 2 +- src/lib/number-state.abstract.ts | 3 +-- src/lib/state.abstract.ts | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/lib/null-state.abstract.ts b/src/lib/null-state.abstract.ts index 87277d3..1969444 100644 --- a/src/lib/null-state.abstract.ts +++ b/src/lib/null-state.abstract.ts @@ -10,7 +10,7 @@ import { State } from "./state.abstract"; */ export abstract class NullState extends State { /** - * Creates an instance of parent class. + * Creates an instance of child class. * @constructor * @param {?null} [state] */ diff --git a/src/lib/number-state.abstract.ts b/src/lib/number-state.abstract.ts index c313474..aab4613 100644 --- a/src/lib/number-state.abstract.ts +++ b/src/lib/number-state.abstract.ts @@ -5,7 +5,6 @@ import { State } from "./state.abstract"; * @export * @abstract * @class NumberState - * @typedef {NumberState} * @extends {State} */ export abstract class NumberState extends State { @@ -52,7 +51,7 @@ export abstract class NumberState extends State { #resetValue; /** - * Creates an instance of `NumberState`. + * Creates an instance of child class. * @constructor * @param {?number} [state] Sets the initial, and reset state value(if not set). * @param {number} [increment=this.#incrementValue] Sets incremental size. diff --git a/src/lib/state.abstract.ts b/src/lib/state.abstract.ts index f88b057..761b64a 100644 --- a/src/lib/state.abstract.ts +++ b/src/lib/state.abstract.ts @@ -27,7 +27,7 @@ export abstract class State extends ImmutableState { #state!: Type; /** - * Creates an instance of parent class. + * Creates an instance of child class. * @constructor * @param {Type} initialState Initial state of `Type`. */ From e89ff46e61b9b7db56064869962ab279cf6120e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 15 Dec 2024 15:00:11 +0000 Subject: [PATCH 14/91] refactor(EnumState): change generic type variable from `T` to `Type` and update descriptions. --- src/lib/enum-state.abstract.ts | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/lib/enum-state.abstract.ts b/src/lib/enum-state.abstract.ts index 7dda06f..7ebfade 100644 --- a/src/lib/enum-state.abstract.ts +++ b/src/lib/enum-state.abstract.ts @@ -5,32 +5,31 @@ import { State } from "./state.abstract"; * @export * @abstract * @class EnumState - * @typedef {EnumState} * @template {object} EnumObject - * @template {EnumObject[keyof EnumObject]} T - * @extends {State} + * @template {EnumObject[keyof EnumObject]} Type + * @extends {State} */ export abstract class EnumState< EnumObject extends object, - T extends EnumObject[keyof EnumObject] -> extends State { + Type extends EnumObject[keyof EnumObject] +> extends State { /** - * Creates an instance of parent class. + * Creates an instance of child class. * @constructor - * @param {T} state + * @param {Type} state * @param {EnumObject} enumObject */ - constructor(state: T, enumObject: EnumObject) { + constructor(state: Type, enumObject: EnumObject) { super(state); } - + /** * @description Checks whether the state is of the specific enum. * @public - * @param {T} state The specific enum to check whether state is. + * @param {Type} state The specific enum to check whether state is. * @returns {boolean} */ - public is(state: T) { + public is(state: Type) { return super.state === state; } } From 2ea3d58b3f465264397e70e2a61d5eddb4f44aec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 15 Dec 2024 15:00:34 +0000 Subject: [PATCH 15/91] docs(Ability): remove `typedef`. --- src/lib/ability.class.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lib/ability.class.ts b/src/lib/ability.class.ts index 4ad0532..ebcfad0 100644 --- a/src/lib/ability.class.ts +++ b/src/lib/ability.class.ts @@ -4,7 +4,6 @@ import { Boolean as Disabled, Boolean as Enabled } from "./boolean.class"; * @description Ability as a `boolean` state (enabled/disabled) * @export * @class Ability - * @typedef {Ability} */ export class Ability { /** From 64bb501f13b215257d9210439a40ca41327266cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 15 Dec 2024 15:02:02 +0000 Subject: [PATCH 16/91] docs(Boolean): remove `typedef`. --- src/lib/boolean.class.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/lib/boolean.class.ts b/src/lib/boolean.class.ts index 25e2c5d..7be37ff 100644 --- a/src/lib/boolean.class.ts +++ b/src/lib/boolean.class.ts @@ -1,10 +1,9 @@ // Abstract. import { BooleanState } from "./boolean-state.abstract"; /** - * @description Handles the `boolean` type state. + * @description Handles the `boolean` type state. * @export * @class Boolean - * @typedef {Boolean} * @extends {BooleanState} */ export class Boolean extends BooleanState {} From 7fce13a963dc9e5b61993c963b2e2d7bd80d0cf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 15 Dec 2024 15:02:29 +0000 Subject: [PATCH 17/91] feat(Enum): add the `class`. --- src/lib/enum.class.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/lib/enum.class.ts diff --git a/src/lib/enum.class.ts b/src/lib/enum.class.ts new file mode 100644 index 0000000..05e11ea --- /dev/null +++ b/src/lib/enum.class.ts @@ -0,0 +1,15 @@ +// Abstract. +import { EnumState } from "./enum-state.abstract"; +/** + * @description + * @export + * @class Enum + * @typedef {Enum} + * @template {object} EnumObject + * @template {EnumObject[keyof EnumObject]} Type + * @extends {EnumState} + */ +export class Enum< + EnumObject extends object, + Type extends EnumObject[keyof EnumObject] +> extends EnumState {} From 934793ddddf6445c16b960d17cf5a3e6f6345a3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 15 Dec 2024 15:02:57 +0000 Subject: [PATCH 18/91] chore(index): update. --- src/lib/index.ts | 48 ++++++++++-------------------------------------- 1 file changed, 10 insertions(+), 38 deletions(-) diff --git a/src/lib/index.ts b/src/lib/index.ts index e8e86e3..8e7b760 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -1,43 +1,15 @@ -export { - Ability, - Disabled, - Enabled -} from './ability'; -export { - Accessibility, - Accessible, - Inaccessible -} from './accessibility'; -export { - Connected, - Connection, - Disconnected -} from './connection'; -export { - Expandable, - Expanded, -} from './expendable'; -export { - All, - Selectable, - Selected, -} from './selectable'; -export { - Invisible, - Visibility, - Visible, -} from './visibility'; -// Class state. -export { Activated } from './activated.class'; -export { Active } from './active.class'; -export { Available } from './available.class'; -export { Deactivated } from './deactivated.class '; -export { Edited } from './edited.class'; -export { Restricted } from './restricted.class'; -// Abstract state. +// Boolean state. +export { Ability } from './ability.class'; +export { Boolean } from './boolean.class'; +export { BooleanStates } from './boolean-states.class'; +// Enum state. +export { Enum } from './enum.class'; +// Object abstract state. +export { ImmutableState } from './immutable-state.abstract'; +// Data of type abstract state. export { BooleanState } from './boolean-state.abstract'; export { EnumState } from './enum-state.abstract'; -export { ImmutableState } from './immutable-state.abstract'; export { NullState } from './null-state.abstract'; export { NumberState } from './number-state.abstract'; +// Common abstract state. export { State } from './state.abstract'; \ No newline at end of file From 9feb8a4812ea190a354c802551abfc2614eb6764 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 15 Dec 2024 15:10:04 +0000 Subject: [PATCH 19/91] refactor(Ability): use as `abstract`. --- src/lib/{ability.class.ts => ability.abstract.ts} | 3 ++- src/lib/index.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) rename src/lib/{ability.class.ts => ability.abstract.ts} (97%) diff --git a/src/lib/ability.class.ts b/src/lib/ability.abstract.ts similarity index 97% rename from src/lib/ability.class.ts rename to src/lib/ability.abstract.ts index ebcfad0..3c4b71e 100644 --- a/src/lib/ability.class.ts +++ b/src/lib/ability.abstract.ts @@ -3,9 +3,10 @@ import { Boolean as Disabled, Boolean as Enabled } from "./boolean.class"; /** * @description Ability as a `boolean` state (enabled/disabled) * @export + * @abstract * @class Ability */ -export class Ability { +export abstract class Ability { /** * @description Default state for the `Disabled` instance. * @public diff --git a/src/lib/index.ts b/src/lib/index.ts index 8e7b760..c2f6da5 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -1,5 +1,4 @@ // Boolean state. -export { Ability } from './ability.class'; export { Boolean } from './boolean.class'; export { BooleanStates } from './boolean-states.class'; // Enum state. @@ -7,6 +6,7 @@ export { Enum } from './enum.class'; // Object abstract state. export { ImmutableState } from './immutable-state.abstract'; // Data of type abstract state. +export { Ability } from './ability.abstract'; export { BooleanState } from './boolean-state.abstract'; export { EnumState } from './enum-state.abstract'; export { NullState } from './null-state.abstract'; From cdc6ae591749fa33f3f674877a163d78c05bd3c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 15 Dec 2024 21:25:57 +0000 Subject: [PATCH 20/91] feat(ObjectState): add. --- src/lib/object-state.abstract.ts | 67 ++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 src/lib/object-state.abstract.ts diff --git a/src/lib/object-state.abstract.ts b/src/lib/object-state.abstract.ts new file mode 100644 index 0000000..c4402e0 --- /dev/null +++ b/src/lib/object-state.abstract.ts @@ -0,0 +1,67 @@ +// Abstract. +import { State } from "./state.abstract"; +/** + * @description The `abstract class` handles the state of Javascript Object. + * @export + * @abstract + * @class ObjectState + * @template {object} Type + * @extends {State} + */ +export abstract class ObjectState extends State { + /** + * @description Returns a newly created and frozen clone of the current state. + * @public + * @readonly + * @type {Type} + */ + public override get state(): Readonly { + return Object.freeze(Object.create(super.state)); + } + + /** + * @description + * @type {*} + */ + #initialState; + + /** + * Creates an instance of child class. + * @constructor + * @param {Type} initialState + */ + constructor(initialState: Type) { + super(initialState); + this.#initialState = initialState; + } + + /** + * @description + * @public + * @returns {this} + */ + public reset(): this { + super.set(this.#initialState); + return this; + } + + /** + * @description Converts the state to JSON. + * @public + * @returns {*} + */ + public toJSON() { + return JSON.stringify(super.state); + } + + /** + * @description Updates the state with `partial` value. + * @public + * @param {Partial} partial The partial object to merge into the state. + * @returns {this} + */ + public update(partial: Partial): this { + this.set({ ...super.state, ...partial }); + return this; + } +} From aade77b0c67b0e081051bc7bcf373e946065b34c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 15 Dec 2024 21:26:18 +0000 Subject: [PATCH 21/91] refactor(State): check the locked state before the `set()`. --- src/lib/state.abstract.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lib/state.abstract.ts b/src/lib/state.abstract.ts index 761b64a..08525c3 100644 --- a/src/lib/state.abstract.ts +++ b/src/lib/state.abstract.ts @@ -54,6 +54,9 @@ export abstract class State extends ImmutableState { * @returns {this} */ protected set(state: Type): this { + if (super.isLocked()) { + throw new Error('Cannot set when object is locked.'); + } this.#state = state; return this; } From 9b6b786d876bf5c19213764a97ac74e6503432a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Fri, 20 Dec 2024 01:25:39 +0000 Subject: [PATCH 22/91] feat(ArrayState): add. --- src/lib/array-state.abstract.ts | 156 ++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 src/lib/array-state.abstract.ts diff --git a/src/lib/array-state.abstract.ts b/src/lib/array-state.abstract.ts new file mode 100644 index 0000000..7586a89 --- /dev/null +++ b/src/lib/array-state.abstract.ts @@ -0,0 +1,156 @@ +// Abstract. +import { State } from "./state.abstract"; +/** + * @description The `abstract class` handles the state of `Array`. + * @export + * @abstract + * @class ArrayState + * @template Type + * @extends {State>} + */ +export abstract class ArrayState extends State> { + /** + * @inheritdoc Return the frozen readonly state. + * @public + * @readonly + * @type {Readonly} + */ + public override get state(): ReadonlyArray { + return Object.freeze(super.state); + } + + /** + * @description The initial state that used in resetting the state. + * @type {Type[]} + */ + #initialState: Type[]; + + /** + * Creates an instance of child class. + * @constructor + * @param {Type} state The initial state of `Type`. + */ + constructor(state: Type[]) { + super(state); + this.#initialState = state; + } + + /** + * @description Adds the `value` at the end of an `array` state. + * @public + * @param {Type} value The `value` of `Type` to append. + * @returns {this} + */ + public append(value: Type): this { + super.set([...super.state, value]); + return this; + } + + /** + * @description Clears the `array` state to empty. + * @public + * @returns {this} + */ + public clear(): this { + super.set([]); + return this; + } + + /** + * @description Finds the values in `array` state. + * @public + * @param {(value: Type) => boolean} predicate + * @returns {(Type | undefined)} + */ + public find(predicate: (value: Type) => boolean): Type | undefined { + return this.state.find(predicate); + } + + /** + * @description Filters the `array` state. + * @public + * @param {(value: Type) => boolean} predicate + * @returns {Type[]} + */ + public filter(predicate: (value: Type) => boolean): Type[] { + return this.state.filter(predicate); + } + + /** + * @description Returns the value of `Type` from the given `index`. + * @public + * @param {number} index + * @returns {Type} + */ + public get(index: number): Type { + return this.state[index]; + } + + /** + * @description Inserts the `value` at the specified `index` into the `array` state. + * @public + * @param {number} index The index of `number` type to insert the `value`. + * @param {Type} value The `value` to insert at the specified `index`. + * @returns {this} + */ + public insert(index: number, value: Type): this { + super.set([...[...super.state].slice(0, index), value, ...[...super.state].slice(index)]); + return this; + } + + /** + * @description Adds the `values` at the beginning of `array` state. + * @public + * @param {...Type[]} values The `values` to add at the beginning. + * @returns {this} + */ + public prepend(...values: Type[]): this { + super.set([...values, ...this.state]); + return this; + } + + /** + * @description Removes the values from the `array` state of the specified `indexes`. + * @public + * @param {...number[]} indexes Indexes to remove from the `array` state. + * @returns {this} + */ + public remove(...indexes: number[]): this { + super.set([...super.state].filter((value, index) => !indexes.includes(index))); + return this; + } + + /** + * @description Removes the values of specified `start` and `end` indexes from `array` state. + * @public + * @param {number} start The start `index` to begin removing. + * @param {number} end The end `index` to end removing. + * @returns {this} + */ + public removeRange(start: number, end: number): this { + super.set([...super.state].filter((value, index) => !(Array.from({ length: end -1 - start }, (value, i) => start + i)).includes(index))); + return this; + } + + /** + * @description Resets the state to the initial set in the `constructor`. + * @public + * @returns {this} + */ + public reset(): this { + super.set(this.#initialState); + return this; + } + + /** + * @description Updates the `value` at the `index` in the `array` state. + * @public + * @param {number} index The index of `array` state to be updated with the `value`. + * @param {Type} value The `value` of `Type` to update at the specified `index`. + * @returns {this} + */ + public update(index: number, value: Type): this { + super.set(this.state.map((v, i) => (i === index ? value : v))); + return this; + } +} From aaf1c746ea56e822c485898ccfd19e43439100fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Fri, 20 Dec 2024 01:25:55 +0000 Subject: [PATCH 23/91] feat(BooleanArrayState): add. --- src/lib/boolean-array-state.abstract.ts | 63 +++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 src/lib/boolean-array-state.abstract.ts diff --git a/src/lib/boolean-array-state.abstract.ts b/src/lib/boolean-array-state.abstract.ts new file mode 100644 index 0000000..40e0b4a --- /dev/null +++ b/src/lib/boolean-array-state.abstract.ts @@ -0,0 +1,63 @@ +// Abstract. +import { ArrayState } from "./array-state.abstract"; +/** + * @description Manages the `array` of `boolean` type state. + * @export + * @abstract + * @class BooleanArrayState + * @extends {ArrayState} + */ +export abstract class BooleanArrayState extends ArrayState { + /** + * Creates an instance of child class. + * @constructor + * @param {...boolean[]} states + */ + constructor(...states: boolean[]) { + super(states); + } + + /** + * @description Sets the specified `indexes` to `false` in the `array` state of `boolean` type. + * @public + * @param {...number[]} indexes Indexes to set to `false`. + * @returns {this} + */ + public false(...indexes: number[]): this { + super.set(this.updateState(indexes, () => false)); + return this; + } + + /** + * @description Toggles the specified `indexes` between `true` and `false` in the `array` state of `boolean` type. + * @public + * @param {...number[]} indexes Indexes to toggle. + * @returns {this} + */ + public toggle(...indexes: number[]): this { + super.set(this.updateState(indexes, (index) => !super.state[index])); + return this; + } + + /** + * @description Sets the specified `indexes` to `true` in the `array` state of `boolean` type. + * @public + * @param {...number[]} indexes Indexes to set to `true`. + * @returns {this} + */ + public true(...indexes: number[]): this { + super.set(this.updateState(indexes, () => true)); + return this; + } + + /** + * @description Updates the `boolean` states of the specified `indexes`. + * @private + * @param {number[]} indexes Indexes to update the state. + * @param {(index: number) => boolean} state The state of `function` type to update. + * @returns {boolean[]} + */ + private updateState(indexes: number[], state: (index: number) => boolean): boolean[] { + return super.state.map((value, index) => indexes.includes(index) ? state(index) : value); + } +} From 33b33a89df1882410afeb6e6e8796d476a805d02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Fri, 20 Dec 2024 01:26:14 +0000 Subject: [PATCH 24/91] refactor(State): set state as `Readonly`. --- src/lib/state.abstract.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/state.abstract.ts b/src/lib/state.abstract.ts index 08525c3..acdc91e 100644 --- a/src/lib/state.abstract.ts +++ b/src/lib/state.abstract.ts @@ -15,7 +15,7 @@ export abstract class State extends ImmutableState { * @readonly * @type {Type} */ - public get state(): Type { + public get state(): Readonly { return this.#state; } From 287aae02862cf89891c1205351345085b7a95984 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Fri, 20 Dec 2024 01:58:36 +0000 Subject: [PATCH 25/91] test(ArrayState): add. --- src/test/array-state.spec.ts | 44 ++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 src/test/array-state.spec.ts diff --git a/src/test/array-state.spec.ts b/src/test/array-state.spec.ts new file mode 100644 index 0000000..f4964e2 --- /dev/null +++ b/src/test/array-state.spec.ts @@ -0,0 +1,44 @@ +import { ArrayState } from '../lib/array-state.abstract'; + +export class NumberArrayState extends ArrayState {} + +let numberArrayState = new NumberArrayState([27, 37, 47]); + +describe(`ArrayState`, () => { + beforeEach(() => { + numberArrayState = new NumberArrayState([27, 37, 47]); + }); + it(`add()`, () => { + numberArrayState.append(34); + expect(numberArrayState.state[3]).toEqual(34); + }); + + it(`clear()`, () => { + expect(numberArrayState.clear().state).toEqual([]); + }); + + it(`get()`, () => { + expect(numberArrayState.get(0)).toEqual(27); + }); + + it(`insert()`, () => { + expect(numberArrayState.insert(1, 34).state[1]).toEqual(34); + }); + + it(`remove()`, () => { + expect(numberArrayState.remove(1).get(1)).toEqual(47); + }); + + it(`remove()`, () => { + expect(numberArrayState.remove(1, 2).get(0)).toEqual(27); + }); + + it(`reset()`, () => { + expect(numberArrayState.reset().state).toEqual([27, 37, 47]); + }); + + it(`update()`, () => { + expect(numberArrayState.update(1, 344).state[1]).toEqual(344); + }); +}); +console.log(`numberArrayState`, numberArrayState.state); From 302f5c4074c7a483492f506216bedeefe2f5c9aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Fri, 20 Dec 2024 23:37:10 +0000 Subject: [PATCH 26/91] refactor(ArrayState): add the `first()` and `last()` methods, and `get` accessor `length`. --- src/lib/array-state.abstract.ts | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/lib/array-state.abstract.ts b/src/lib/array-state.abstract.ts index 7586a89..6b6980b 100644 --- a/src/lib/array-state.abstract.ts +++ b/src/lib/array-state.abstract.ts @@ -9,6 +9,15 @@ import { State } from "./state.abstract"; * @extends {State>} */ export abstract class ArrayState extends State> { + /** + * @description Returns the `array` state length. + * @public + * @returns {number} + */ + public get length() { + return super.state.length; + } + /** * @inheritdoc Return the frozen readonly state. * @public @@ -35,6 +44,15 @@ export abstract class ArrayState extends State> { this.#initialState = state; } + /** + * @description Returns the first element of `array` state. + * @public + * @returns {Type} + */ + public first(): Type { + return this.state[0]; + } + /** * @description Adds the `value` at the end of an `array` state. * @public @@ -98,6 +116,15 @@ export abstract class ArrayState extends State> { return this; } + /** + * @description Returns the last element of `array` state. + * @public + * @returns {Type} + */ + public last(): Type { + return this.state[this.length]; + } + /** * @description Adds the `values` at the beginning of `array` state. * @public From 6b39acc9d99b856f1305c5e40dcc739834f6dea2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Fri, 20 Dec 2024 23:37:37 +0000 Subject: [PATCH 27/91] refactor(BooleanStates): remove. --- src/lib/boolean-states.class.ts | 97 --------------------------------- 1 file changed, 97 deletions(-) delete mode 100644 src/lib/boolean-states.class.ts diff --git a/src/lib/boolean-states.class.ts b/src/lib/boolean-states.class.ts deleted file mode 100644 index 1712a24..0000000 --- a/src/lib/boolean-states.class.ts +++ /dev/null @@ -1,97 +0,0 @@ -// Class. -import { Boolean } from "./boolean.class"; -/** - * @description The class to handle multiple `Boolean` states of the specified names. - * @export - * @class BooleanStates - * @template {string} [Names=string] - * @template {Boolean} [Object=Boolean] - */ -export class BooleanStates< - Names extends string = string, - Object extends Boolean = Boolean -> { - /** - * @description The state object of the specified `names`. - * @public - * @type {{ [K in Names]: Object }} - */ - public state: { [K in Names]: Object } = {} as any; - - /** - * Creates an instance of `BooleanStates`. - * @constructor - * @param {Names[]} names The names of `Object` states. - * @param {new (...args: any[]) => Object} [object=Boolean as unknown as new (...args: any[]) => Object] - */ - constructor( - names: Names[], - object: new (...args: any[]) => Object = Boolean as unknown as new (...args: any[]) => Object - ) { - names.forEach((name) => this.state[name] = new object()); - } - - /** - * @description Sets the state to `false in `Object` states of the specified `names`. - * @public - * @template {Names} Name - * @param {...Name[]} names The names to set the state to `false`. - * @returns {this} - */ - public false(...names: Name[]): this { - (names || Object.keys(this.state)).forEach(name => this.get(name).false()); - return this; - } - - /** - * @description Gets the `Object` state of the specified `name`. - * @public - * @template {Names} Name - * @param {Name} name The name of generic type variable `Name` to get. - * @returns {Object} - */ - public get(name: Name): Object { - if (this.state.hasOwnProperty(name)) { - return this.state[name]; - } else { - throw new Error(`State with name '${name}' does not exist.`); - } - } - - /** - * @description Picks the states of the specified `names` into the returned `object`. - * @public - * @template {Names} Name - * @param {...Name[]} names The names to pick to the returned `object`. - * @returns {{ [Key in Name]: Object }} - */ - public pick(...names: Name[]) { - const result = {} as { [Key in Name]: Object }; - ((names || Object.keys(this.state)) as Name[]).reduce((acc, name) => (Object.assign(acc, {[name]: this.get(name)}), acc), result); - return result; - } - - /** - * @description Toggles the state of the specified `names`. - * @public - * @template {Names} Name - * @param {...Name[]} names The `names` to toggle the state. - * @returns {this} - */ - public toggle(...names: Name[]): this { - (names || Object.keys(this.state)).forEach(name => this.get(name).toggle()); - return this; - } - - /** - * @description Sets the state to `true in `Object` states of the specified `names`. - * @public - * @template {Names} Name - * @param {...Name[]} names Arbitrary list of state `names` to sets to `true`. - * @returns {this} - */ - public true(...names: Name[]): this { - (names || Object.keys(this.state)).forEach(name => this.get(name).true()); - return this; - } -} From 9c06cea75e32c5e5f4b28258527ffbd6eeb1f8ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sat, 21 Dec 2024 19:10:19 +0000 Subject: [PATCH 28/91] refactor(ArrayState): add `merge()`, `set()`, and `swap()` methods, change `get()` to `at()` to use `get()` in child class. --- src/lib/array-state.abstract.ts | 82 +++++++++++++++++++++++++-------- 1 file changed, 63 insertions(+), 19 deletions(-) diff --git a/src/lib/array-state.abstract.ts b/src/lib/array-state.abstract.ts index 6b6980b..c696cfe 100644 --- a/src/lib/array-state.abstract.ts +++ b/src/lib/array-state.abstract.ts @@ -45,16 +45,7 @@ export abstract class ArrayState extends State> { } /** - * @description Returns the first element of `array` state. - * @public - * @returns {Type} - */ - public first(): Type { - return this.state[0]; - } - - /** - * @description Adds the `value` at the end of an `array` state. + * @description Appends the `value` at the end of an `array` state. * @public * @param {Type} value The `value` of `Type` to append. * @returns {this} @@ -64,6 +55,16 @@ export abstract class ArrayState extends State> { return this; } + /** + * @description Returns the value of `Type` from the given `index`. + * @public + * @param {number} index + * @returns {Type} + */ + public at(index: number): Type | undefined { + return this.state.at(index); + } + /** * @description Clears the `array` state to empty. * @public @@ -95,13 +96,12 @@ export abstract class ArrayState extends State> { } /** - * @description Returns the value of `Type` from the given `index`. + * @description Returns the first element of `array` state. * @public - * @param {number} index * @returns {Type} */ - public get(index: number): Type { - return this.state[index]; + public first(): Type { + return this.state[0]; } /** @@ -122,7 +122,26 @@ export abstract class ArrayState extends State> { * @returns {Type} */ public last(): Type { - return this.state[this.length]; + return this.state[this.length - 1]; + } + + /** + * @description Merges `values` into the `array` state starting at position. + * @public + * @param {Type[]} values Array of `Type` to merge with `array` state. + * @param {number} [startAt=this.length] The position to start merging `values` with an `array` state. + * @returns {this} + */ + public merge(values: Type[], startAt: number = this.length): this { + if (startAt < 0 || startAt > this.length) { + throw new Error("startAt index is out of bounds"); + } + super.set([ + ...super.state.slice(0, startAt), + ...values, + ...super.state.slice(startAt), + ]); + return this; } /** @@ -150,12 +169,12 @@ export abstract class ArrayState extends State> { /** * @description Removes the values of specified `start` and `end` indexes from `array` state. * @public - * @param {number} start The start `index` to begin removing. - * @param {number} end The end `index` to end removing. + * @param {number} startAt The start `index` to begin removing. + * @param {number} endAt The end `index` to end removing. * @returns {this} */ - public removeRange(start: number, end: number): this { - super.set([...super.state].filter((value, index) => !(Array.from({ length: end -1 - start }, (value, i) => start + i)).includes(index))); + public removeRange(startAt: number, endAt: number): this { + super.set([...super.state].filter((value, index) => !(Array.from({ length: endAt + 1 - startAt }, (value, i) => startAt + i)).includes(index))); return this; } @@ -169,6 +188,31 @@ export abstract class ArrayState extends State> { return this; } + /** + * @inheritdoc + * @public + * @param {ReadonlyArray} state + * @returns {this} + */ + public override set(state: ReadonlyArray): this { + super.set(state); + return this; + } + + /** + * @description + * @public + * @param {number} index + * @param {number} withIndex + * @returns {this} + */ + public swap(index: number, withIndex: number): this { + const state = [...this.state]; + [state[index], state[withIndex]] = [state[withIndex], state[index]]; + super.set(state); + return this; + } + /** * @description Updates the `value` at the `index` in the `array` state. * @public From 36e56a1e317fe47a58b05fa8dccb267a79a6534c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sat, 21 Dec 2024 20:59:25 +0000 Subject: [PATCH 29/91] test(ArrayState): update. --- src/test/array-state.spec.ts | 46 +++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/src/test/array-state.spec.ts b/src/test/array-state.spec.ts index f4964e2..6991954 100644 --- a/src/test/array-state.spec.ts +++ b/src/test/array-state.spec.ts @@ -8,35 +8,69 @@ describe(`ArrayState`, () => { beforeEach(() => { numberArrayState = new NumberArrayState([27, 37, 47]); }); - it(`add()`, () => { + it(`append()`, () => { numberArrayState.append(34); expect(numberArrayState.state[3]).toEqual(34); }); + it(`at()`, () => { + expect(numberArrayState.at(2)).toEqual(47); + }); + it(`clear()`, () => { expect(numberArrayState.clear().state).toEqual([]); }); - it(`get()`, () => { - expect(numberArrayState.get(0)).toEqual(27); + it(`find()`, () => { + expect(numberArrayState.find(value => value === 37)).toEqual(37); + }); + + it(`filter()`, () => { + expect(numberArrayState.filter(value => value === 37)).toEqual([37]); + }); + + it(`first()`, () => { + expect(numberArrayState.first()).toEqual(27); }); it(`insert()`, () => { expect(numberArrayState.insert(1, 34).state[1]).toEqual(34); }); - it(`remove()`, () => { - expect(numberArrayState.remove(1).get(1)).toEqual(47); + it(`last()`, () => { + expect(numberArrayState.last()).toEqual(47); + }); + + it(`merge()`, () => { + expect(numberArrayState.merge([34, 0], 1).state).toEqual([27, 34, 0, 37, 47]); + }); + + it(`prepend()`, () => { + expect(numberArrayState.prepend(34, 0).state).toEqual([34, 0, 27, 37, 47]); + }); + + it(`pick()`, () => { + expect(numberArrayState.pick(1, 2)).toEqual([37, 47]); }); it(`remove()`, () => { - expect(numberArrayState.remove(1, 2).get(0)).toEqual(27); + expect(numberArrayState.remove(1, 2).at(0)).toEqual(27); + }); + + it(`removeRange()`, () => { + numberArrayState.merge([34, 35, 36, 37, 38, 39, 40, 41, 42]); + expect(numberArrayState.removeRange(4, 7).state).toEqual([27, 37, 47, 34, 39, 40, 41, 42]); }); it(`reset()`, () => { expect(numberArrayState.reset().state).toEqual([27, 37, 47]); }); + it(`swap()`, () => { + expect(numberArrayState.swap(1, 2).state).toEqual([27, 47, 37]); + console.log(numberArrayState.state); + }); + it(`update()`, () => { expect(numberArrayState.update(1, 344).state[1]).toEqual(344); }); From 26ce21e8510604b59a95509cad7013e41ba4ab89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 22 Dec 2024 00:02:45 +0000 Subject: [PATCH 30/91] feat(NamedArrayState): add. --- src/lib/named-array-state.abstract.ts | 113 ++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 src/lib/named-array-state.abstract.ts diff --git a/src/lib/named-array-state.abstract.ts b/src/lib/named-array-state.abstract.ts new file mode 100644 index 0000000..373c72b --- /dev/null +++ b/src/lib/named-array-state.abstract.ts @@ -0,0 +1,113 @@ +// Abstract. +import { ArrayState } from "./array-state.abstract"; +/** + * @description Manages the `array` state of `Type` type with the specified names of generic type variable `Names`. + * @export + * @abstract + * @class NamedArrayState + * @template {string} Names + * @template Type + * @extends {ArrayState} + */ +export abstract class NamedArrayState< + Names extends string, + Type +> extends ArrayState { + /** + * @description Returns tuple an `array` where the first element contains an `array` of names and the second `array` contains their corresponding values. + * @public + * @returns {[Names[], Type[]]} + */ + public get stateAsTuple(): [Names[], Type[]] { + return [this.#names, [...super.state]]; + } + + /** + * @description Returns an `array` state of tuple pairs name-type. + * @public + * @readonly + * @type {[Names, Type][]} + */ + public get stateWithNames(): [Names, Type][] { + return this.#names.map((name, index) => [name, super.state[index]]); + } + + /** + * @description A private property, an `array` of generic type variable `Names`, used to associate `Type` values. + * @type {Names[]} + */ + #names: Names[]; + + /** + * Creates an instance of child `class`. + * @constructor + * @param {...Names[]} names Arbitrary parameter `names` of generic type variable `Names` to associate `Type` values. + */ + constructor(...names: Names[]) { + super([]); + this.#names = names; + } + + /** + * @description Returns the value from element of the specified `name`. + * @public + * @param {Names} name The name of generic type variable `Names` to get the value. + * @returns {Type} + */ + public get(name: Names): Type { + return this.state[this.#names.indexOf(name)]; + } + + /** + * @description Returns index of the specified `name`. + * @public + * @param {Names} name The name of generic type variable `Names` to get its index. + * @returns {number} + */ + public indexOf(name: Names): number { + return this.#names.indexOf(name); + } + + /** + * @description Selects values from the specified `names`. + * @public + * @param {...Names[]} names Arbitrary parameter of names to select the values from `array` state. + * @returns {Type[]} + */ + public select(...names: Names[]): Type[] { + return super.pick(...this.indexesOf(...names)); + } + + /** + * @description Returns the `object` of names with their `Type` values. + * @public + * @returns {{ [Name in Names]: Type }} + */ + public toObject() { + return this.#names.reduce( + (acc, name) => (acc[name] = super.state[this.indexOf(name)], acc), + {} as { [Name in Names]: Type } + ); + } + + /** + * @description Returns the indexes of the specified `names`. + * @protected + * @param {...Names[]} names Arbitrary parameter of generic type variable `Names` to get their indexes. + * @returns {number[]} + */ + protected indexesOf(...names: Names[]): number[] { + return names.map(name => this.#names.indexOf(name)); + } + + /** + * @description Private method to update the state of the specified `indexes` by using function `state`. + * @protected + * @param {number[]} indexes `Array` type indexes of `number` type to update the value. + * @param {(index: number) => Type} state The `function` to update the state under the specified `index`. + * @returns {Type[]} + */ + protected updateState(indexes: number[], state: (index: number) => Type): Type[] { + return super.state.map((value, index) => indexes.includes(index) ? state(index) : value); + } +} From 2fb7f2b614fb0d5546c16c6c9042e612fb0ed996 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 22 Dec 2024 00:37:20 +0000 Subject: [PATCH 31/91] refactor(ArrayState): add the `pick()` feature. --- src/lib/array-state.abstract.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/lib/array-state.abstract.ts b/src/lib/array-state.abstract.ts index c696cfe..3830d91 100644 --- a/src/lib/array-state.abstract.ts +++ b/src/lib/array-state.abstract.ts @@ -154,7 +154,17 @@ export abstract class ArrayState extends State> { super.set([...values, ...this.state]); return this; } - + + /** + * @description Picks the specified indexes. + * @public + * @param {...number[]} indexes Indexes to pick from the `array` state. + * @returns {Type[]} + */ + public pick(...indexes: number[]): Type[] { + return [...super.state].filter((element, index) => indexes.includes(index)); + } + /** * @description Removes the values from the `array` state of the specified `indexes`. * @public From 09f0285119c09f7f02f3e29acc755a8d4e8b285d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 22 Dec 2024 00:45:29 +0000 Subject: [PATCH 32/91] test(NamedArrayState): add. --- src/test/named-array-state.spec.ts | 49 ++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/test/named-array-state.spec.ts diff --git a/src/test/named-array-state.spec.ts b/src/test/named-array-state.spec.ts new file mode 100644 index 0000000..01eb5c8 --- /dev/null +++ b/src/test/named-array-state.spec.ts @@ -0,0 +1,49 @@ +import { NamedArrayState } from '../lib/named-array-state.abstract'; + +export class SomeoneState extends NamedArrayState {} + +let someoneState = new SomeoneState('Someone1', 'Someone2', 'Someone3').set([27, 34, 37, 47]); + +describe(`NamedArrayState`, () => { + beforeEach(() => { + someoneState = new SomeoneState('Someone1', 'Someone2', 'Someone3').set([27, 34, 37, 47]); + }); + + it(`someoneState.state`, () => { + expect(someoneState.state).toEqual([27, 34, 37, 47]); + }); + + it(`someoneState.stateAsTuple`, () => { + expect(someoneState.stateAsTuple).toEqual([['Someone1', 'Someone2', 'Someone3'], [27, 34, 37, 47]]); + }); + + it(`someoneState.stateWithNames`, () => { + expect(someoneState.stateWithNames).toEqual([['Someone1', 27], ['Someone2', 34], ['Someone3', 37]]); + }); + + it(`someoneState.state`, () => { + expect(someoneState.state).toEqual([27, 34, 37, 47]); + }); + + it(`someoneState.get()`, () => { + expect(someoneState.get('Someone2')).toEqual(34); + }); + + it(`someoneState.indexOf()`, () => { + expect(someoneState.indexOf('Someone2')).toEqual(1); + }); + + it(`someoneState.select()`, () => { + expect(someoneState.select('Someone2', 'Someone3')).toEqual([34, 37]); + }); + + it(`someoneState.toObject()`, () => { + expect(someoneState.toObject()).toEqual({ + 'Someone1': 27, + 'Someone2': 34, + 'Someone3': 37 + }); + }); + +}); +console.log(`someoneState`, someoneState); From 5be0ed056fb63368baf54cc47b7b57bb8a0f8cb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 22 Dec 2024 00:45:41 +0000 Subject: [PATCH 33/91] testL remove. --- src/test/immutability.spec.ts | 45 ----------------------------------- 1 file changed, 45 deletions(-) delete mode 100644 src/test/immutability.spec.ts diff --git a/src/test/immutability.spec.ts b/src/test/immutability.spec.ts deleted file mode 100644 index 0045411..0000000 --- a/src/test/immutability.spec.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { BooleanState } from "../lib"; - -export class ActiveState extends BooleanState { - public override get state() { - return super.state; - } - - public override false() { - super.false(); - return this; - } - - - public activate() { - super.true(); - return this; - } - - public deactivate() { - super.false(); - return this; - } -} - -const activeState = new ActiveState(); - -activeState.seal(); - -console.log(`--Sealed`); -console.log(activeState); -console.log(activeState.false()); -console.log(activeState.activate()); - -activeState.freeze(); - -console.log(`--Frozen`); -console.log(activeState.activate()); -console.log(activeState.false()); - -activeState.lock(); - -console.log(`--Locked`); -// console.log(activeState.activate()); -// console.log(activeState.false()); - From 6f8c1a36bfe85c7df226e750f6031eef8c1277dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 22 Dec 2024 00:49:20 +0000 Subject: [PATCH 34/91] feat(NamedBooleanArrayState): add. --- src/lib/named-boolean-array-state.abstract.ts | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/lib/named-boolean-array-state.abstract.ts diff --git a/src/lib/named-boolean-array-state.abstract.ts b/src/lib/named-boolean-array-state.abstract.ts new file mode 100644 index 0000000..55bec1c --- /dev/null +++ b/src/lib/named-boolean-array-state.abstract.ts @@ -0,0 +1,55 @@ +// Abstract. +import { NamedArrayState } from "./named-array-state.abstract"; +/** + * @description Manages the `array` state of `boolean` type with the specified names of generic type variable `Names`. + * @export + * @abstract + * @class NamedBooleanArrayState + * @template {string} Names + * @extends {ArrayState} + */ +export abstract class NamedBooleanArrayState< + Names extends string +> extends NamedArrayState { + /** + * Creates an instance of child `class`. + * @constructor + * @param {...Names[]} names Arbitrary parameter `names` of generic type variable `Names` to associate `boolean` values. + */ + constructor(...names: Names[]) { + super(...names); + } + + /** + * @description Sets to `false` elements of the specified `names`. + * @public + * @param {...Names[]} names Arbitrary parameter of generic type variable `Names` to set the elements to `false`. + * @returns {this} + */ + public false(...names: Names[]): this { + super.set(this.updateState(this.indexesOf(...names), () => false)); + return this; + } + + /** + * @description Toggles between `false` and `true` specified `names`. + * @public + * @param {...Names[]} names Arbitrary parameter of generic type variable `Names` to toggle their values. + * @returns {this} + */ + public toggle(...names: Names[]): this { + super.set(super.updateState(this.indexesOf(...names), index => !super.state[index])); + return this; + } + + /** + * @description Sets the `true` under the specified `names` in the `array` state. + * @public + * @param {...Names[]} names Arbitrary parameter of generic type variable `Names` to set the elements to `true`. + * @returns {this} + */ + public true(...names: Names[]): this { + super.set(super.updateState(this.indexesOf(...names), () => true)); + return this; + } +} From ea9dcaf0d33f46d3e8ae092f844636ed12ac0467 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 22 Dec 2024 01:07:00 +0000 Subject: [PATCH 35/91] refactor(NamedArrayState): add `values` to set initial state. --- src/lib/named-array-state.abstract.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/lib/named-array-state.abstract.ts b/src/lib/named-array-state.abstract.ts index 373c72b..4ff2ee3 100644 --- a/src/lib/named-array-state.abstract.ts +++ b/src/lib/named-array-state.abstract.ts @@ -41,10 +41,11 @@ export abstract class NamedArrayState< /** * Creates an instance of child `class`. * @constructor - * @param {...Names[]} names Arbitrary parameter `names` of generic type variable `Names` to associate `Type` values. + * @param {Names[]} names Arbitrary parameter `names` of generic type variable `Names` to associate `Type` values. + * @param {Type[]} [values=[]] The `values` to set to the respective `names`. */ - constructor(...names: Names[]) { - super([]); + constructor(names: Names[], values: Type[] = []) { + super(values); this.#names = names; } From 786560fef52ed1fa4dc62e8f362fa5dad4c78ee0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 22 Dec 2024 01:07:20 +0000 Subject: [PATCH 36/91] refactor(NamedBooleanArrayState): add `values` to set initial state. --- src/lib/named-boolean-array-state.abstract.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/lib/named-boolean-array-state.abstract.ts b/src/lib/named-boolean-array-state.abstract.ts index 55bec1c..415be13 100644 --- a/src/lib/named-boolean-array-state.abstract.ts +++ b/src/lib/named-boolean-array-state.abstract.ts @@ -4,9 +4,10 @@ import { NamedArrayState } from "./named-array-state.abstract"; * @description Manages the `array` state of `boolean` type with the specified names of generic type variable `Names`. * @export * @abstract - * @class NamedBooleanArrayState + * @class NamedBooleanArrayState + * @typedef {NamedBooleanArrayState} * @template {string} Names - * @extends {ArrayState} + * @extends {NamedArrayState} */ export abstract class NamedBooleanArrayState< Names extends string @@ -15,9 +16,10 @@ export abstract class NamedBooleanArrayState< * Creates an instance of child `class`. * @constructor * @param {...Names[]} names Arbitrary parameter `names` of generic type variable `Names` to associate `boolean` values. + * @param {boolean[]} [values=[]] The `values` of `boolean` type to set to the respective `names`. */ - constructor(...names: Names[]) { - super(...names); + constructor(names: Names[], values: boolean[] = []) { + super(names, values); } /** From e9d520f1cb05cbbc00fb4c8669ff08992ede26cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 22 Dec 2024 01:07:33 +0000 Subject: [PATCH 37/91] chore(index): update. --- src/lib/index.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/lib/index.ts b/src/lib/index.ts index c2f6da5..71ec2f0 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -1,6 +1,10 @@ // Boolean state. export { Boolean } from './boolean.class'; -export { BooleanStates } from './boolean-states.class'; +// Array state. +export { ArrayState } from './array-state.abstract'; +export { BooleanArrayState } from './boolean-array-state.abstract'; +export { NamedArrayState } from './named-array-state.abstract'; +export { NamedBooleanArrayState } from './named-boolean-array-state.abstract'; // Enum state. export { Enum } from './enum.class'; // Object abstract state. @@ -11,5 +15,6 @@ export { BooleanState } from './boolean-state.abstract'; export { EnumState } from './enum-state.abstract'; export { NullState } from './null-state.abstract'; export { NumberState } from './number-state.abstract'; +export { ObjectState } from './object-state.abstract'; // Common abstract state. export { State } from './state.abstract'; \ No newline at end of file From 292d2d328848debc7ea3d6dc6a0f7c1d85761572 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 22 Dec 2024 01:08:21 +0000 Subject: [PATCH 38/91] test(NamedArrayState): update with initial values. --- src/test/named-array-state.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/named-array-state.spec.ts b/src/test/named-array-state.spec.ts index 01eb5c8..7879fe7 100644 --- a/src/test/named-array-state.spec.ts +++ b/src/test/named-array-state.spec.ts @@ -2,11 +2,11 @@ import { NamedArrayState } from '../lib/named-array-state.abstract'; export class SomeoneState extends NamedArrayState {} -let someoneState = new SomeoneState('Someone1', 'Someone2', 'Someone3').set([27, 34, 37, 47]); +let someoneState = new SomeoneState(['Someone1', 'Someone2', 'Someone3'], [27, 34, 37, 47]); describe(`NamedArrayState`, () => { beforeEach(() => { - someoneState = new SomeoneState('Someone1', 'Someone2', 'Someone3').set([27, 34, 37, 47]); + someoneState = new SomeoneState(['Someone1', 'Someone2', 'Someone3'], [27, 34, 37, 47]); }); it(`someoneState.state`, () => { From feeed95c6b3d5a103bd9d85664eef68c4c93ae45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 22 Dec 2024 01:19:48 +0000 Subject: [PATCH 39/91] test(NamedBooleanArrayState): add. --- src/test/named-boolean-array-state.spec.ts | 32 ++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 src/test/named-boolean-array-state.spec.ts diff --git a/src/test/named-boolean-array-state.spec.ts b/src/test/named-boolean-array-state.spec.ts new file mode 100644 index 0000000..9c3baab --- /dev/null +++ b/src/test/named-boolean-array-state.spec.ts @@ -0,0 +1,32 @@ +import { NamedBooleanArrayState } from '../lib/named-boolean-array-state.abstract'; + + +export class Options extends NamedBooleanArrayState { + public get name() { + return this.toObject(); + } +} + +let options = new Options(['option1', 'option2', 'option3'], [false]); + + +describe(`ArrayState`, () => { + beforeEach(() => { + options = new Options(['option1', 'option2', 'option3'], [false]); + }); + + it(`false()`, () => { + expect(options.false('option2', 'option3').state).toEqual([false, false, false]); + }); + + it(`toggle()`, () => { + expect(options.toggle('option2', 'option3').state).toEqual([false, false, false]); + expect(options.toggle('option1', 'option2', 'option3').state).toEqual([true, true, true]); + }); + + it(`true()`, () => { + expect(options.true('option1').state).toEqual([true, true, true]); + }); +}); + +console.log(`NamedBooleanArrayState`, options); From f8b7a519ee0785bfa58c090e13af4999cc470412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 22 Dec 2024 01:19:59 +0000 Subject: [PATCH 40/91] refactor(NamedBooleanArrayState): initial default values. --- src/lib/named-boolean-array-state.abstract.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/named-boolean-array-state.abstract.ts b/src/lib/named-boolean-array-state.abstract.ts index 415be13..98e022e 100644 --- a/src/lib/named-boolean-array-state.abstract.ts +++ b/src/lib/named-boolean-array-state.abstract.ts @@ -19,7 +19,7 @@ export abstract class NamedBooleanArrayState< * @param {boolean[]} [values=[]] The `values` of `boolean` type to set to the respective `names`. */ constructor(names: Names[], values: boolean[] = []) { - super(names, values); + super(names, names.map((name, index) => values.length > -1 && index <= values.length - 1 ? values[index] : !!name)); } /** From 3f8ab49021ae50ed61705959baa4292969e4601d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 22 Dec 2024 01:21:13 +0000 Subject: [PATCH 41/91] refactor(ObjectState): do not create the object in returned state, add `get()` pick()` `set()`. --- src/lib/object-state.abstract.ts | 47 +++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/src/lib/object-state.abstract.ts b/src/lib/object-state.abstract.ts index c4402e0..aa71be1 100644 --- a/src/lib/object-state.abstract.ts +++ b/src/lib/object-state.abstract.ts @@ -16,11 +16,11 @@ export abstract class ObjectState extends State { * @type {Type} */ public override get state(): Readonly { - return Object.freeze(Object.create(super.state)); + return Object.freeze(super.state); } /** - * @description + * @description The initial state that used in resetting the state. * @type {*} */ #initialState; @@ -28,7 +28,7 @@ export abstract class ObjectState extends State { /** * Creates an instance of child class. * @constructor - * @param {Type} initialState + * @param {Type} initialState The initial state of `Type`. */ constructor(initialState: Type) { super(initialState); @@ -38,6 +38,28 @@ export abstract class ObjectState extends State { /** * @description * @public + * @template {keyof Type} Key + * @param {Key} key + * @returns {Type[Key]} + */ + public get(key: Key): Type[Key] { + return this.state[key]; + } + + /** + * @description + * @public + * @template {keyof Type} Keys + * @param {...Keys[]} keys + * @returns {Pick} + */ + public pick(...keys: Keys[]): Pick { + return keys.reduce((object, key) => (Object.assign(object, {[key]: this.state[key]}), object), {} as Type); + } + + /** + * @description Resets the state to the initial state set in the `constructor`. + * @public * @returns {this} */ public reset(): this { @@ -46,18 +68,29 @@ export abstract class ObjectState extends State { } /** - * @description Converts the state to JSON. + * @inheritdoc + * @public + * @param {Type} state + * @returns {this} + */ + public override set(state: Type): this { + super.set(state); + return this; + } + + /** + * @description Converts the state to JSON string. * @public - * @returns {*} + * @returns {string} */ - public toJSON() { + public toJSON(): string { return JSON.stringify(super.state); } /** * @description Updates the state with `partial` value. * @public - * @param {Partial} partial The partial object to merge into the state. + * @param {Partial} partial The partial `object` to merge into the state. * @returns {this} */ public update(partial: Partial): this { From d3dfd14c05cd982289f55ef760810e259988c46d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 22 Dec 2024 01:41:11 +0000 Subject: [PATCH 42/91] feat(BooleanObjectState): add. --- src/lib/boolean-object-state.abstract.ts | 90 ++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 src/lib/boolean-object-state.abstract.ts diff --git a/src/lib/boolean-object-state.abstract.ts b/src/lib/boolean-object-state.abstract.ts new file mode 100644 index 0000000..e709390 --- /dev/null +++ b/src/lib/boolean-object-state.abstract.ts @@ -0,0 +1,90 @@ +// Abstract. +import { ObjectState } from "./object-state.abstract"; +/** + * @description + * @export + * @abstract + * @class BooleanObjectState + * @typedef {BooleanObjectState} + * @template {PropertyKey} Names + * @extends {ObjectState<{[Name in Names]: boolean}>} + */ +export abstract class BooleanObjectState< + Names extends PropertyKey, +> extends ObjectState<{[Name in Names]: boolean}> { + /** + * Creates an instance of child class. + * @constructor + * @param {Names[]} names + */ + constructor(names: Names[]) { + super({} as {[Name in Names]: boolean}); + const partial: Partial<{[Name in Names]: boolean}> = {}; + names.forEach(name => Object.assign(partial, {[name]: true})); + this.update(partial); + } + + /** + * @description Sets the state to `false in `Object` states of the specified `names`. + * @public + * @template {Names} Name + * @param {...Name[]} names The names to set the state to `false`. + * @returns {this} + */ + public false(...names: Name[]): this { + this.updateState(names, () => false); + return this; + } + + /** + * @description + * @public + * @template {Names} Name + * @param {Name} name + * @param {?boolean} [expected] + * @returns {Object} + */ + public is(name: Name, expected?: boolean) { + return expected ? super.state[name] === expected : super.state[name]; + } + + /** + * @description Toggles the state of the specified `names`. + * @public + * @template {Names} Name + * @param {...Name[]} names The `names` to toggle the state. + * @returns {this} + */ + public toggle(...names: Name[]): this { + this.updateState(names, name => !this.state[name]); + return this; + } + + /** + * @description Sets the `boolean` value to `true in `object` state in the specified `names`. + * @public + * @template {Names} Name + * @param {...Name[]} names Arbitrary parameter of state `names` to sets to `true`. + * @returns {this} + */ + public true(...names: Name[]): this { + this.updateState(names, () => true); + return this; + } + + /** + * @description Updates the state of the specified `names` with the `valueFn`. + * @private + * @param {Names[]} [names=[]] + * @param {(name: Names) => boolean} valueFn + * @returns {this} + */ + private updateState(names: Names[] = [], valueFn: (name: Names) => boolean): this { + this.update( + (names.length > 0 ? names : Object.keys(this.state) as Names[]).reduce>( + (partial, name) => (Object.assign(partial, { [name]: valueFn(name) }), partial), {} + ) + ); + return this; + } +} From 1a08d765d9df03eba7a38dce982b9bd184727882 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 22 Dec 2024 01:48:06 +0000 Subject: [PATCH 43/91] chore(array): move array state to `array` directory. --- src/lib/{ => array}/array-state.abstract.ts | 2 +- src/lib/{ => array}/boolean-array-state.abstract.ts | 0 src/lib/array/index.ts | 4 ++++ src/lib/{ => array}/named-array-state.abstract.ts | 0 .../{ => array}/named-boolean-array-state.abstract.ts | 0 src/lib/index.ts | 10 ++++++---- 6 files changed, 11 insertions(+), 5 deletions(-) rename src/lib/{ => array}/array-state.abstract.ts (99%) rename src/lib/{ => array}/boolean-array-state.abstract.ts (100%) create mode 100644 src/lib/array/index.ts rename src/lib/{ => array}/named-array-state.abstract.ts (100%) rename src/lib/{ => array}/named-boolean-array-state.abstract.ts (100%) diff --git a/src/lib/array-state.abstract.ts b/src/lib/array/array-state.abstract.ts similarity index 99% rename from src/lib/array-state.abstract.ts rename to src/lib/array/array-state.abstract.ts index 3830d91..f85e3e7 100644 --- a/src/lib/array-state.abstract.ts +++ b/src/lib/array/array-state.abstract.ts @@ -1,5 +1,5 @@ // Abstract. -import { State } from "./state.abstract"; +import { State } from "../state.abstract"; /** * @description The `abstract class` handles the state of `Array`. * @export diff --git a/src/lib/boolean-array-state.abstract.ts b/src/lib/array/boolean-array-state.abstract.ts similarity index 100% rename from src/lib/boolean-array-state.abstract.ts rename to src/lib/array/boolean-array-state.abstract.ts diff --git a/src/lib/array/index.ts b/src/lib/array/index.ts new file mode 100644 index 0000000..2f70f10 --- /dev/null +++ b/src/lib/array/index.ts @@ -0,0 +1,4 @@ +export { ArrayState } from './array-state.abstract'; +export { BooleanArrayState } from './boolean-array-state.abstract'; +export { NamedArrayState } from './named-array-state.abstract'; +export { NamedBooleanArrayState } from './named-boolean-array-state.abstract'; \ No newline at end of file diff --git a/src/lib/named-array-state.abstract.ts b/src/lib/array/named-array-state.abstract.ts similarity index 100% rename from src/lib/named-array-state.abstract.ts rename to src/lib/array/named-array-state.abstract.ts diff --git a/src/lib/named-boolean-array-state.abstract.ts b/src/lib/array/named-boolean-array-state.abstract.ts similarity index 100% rename from src/lib/named-boolean-array-state.abstract.ts rename to src/lib/array/named-boolean-array-state.abstract.ts diff --git a/src/lib/index.ts b/src/lib/index.ts index 71ec2f0..f7cdc80 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -1,10 +1,12 @@ // Boolean state. export { Boolean } from './boolean.class'; // Array state. -export { ArrayState } from './array-state.abstract'; -export { BooleanArrayState } from './boolean-array-state.abstract'; -export { NamedArrayState } from './named-array-state.abstract'; -export { NamedBooleanArrayState } from './named-boolean-array-state.abstract'; +export { + ArrayState, + BooleanArrayState, + NamedArrayState, + NamedBooleanArrayState +} from './array'; // Enum state. export { Enum } from './enum.class'; // Object abstract state. From 39beeaa1ab5cb19ebbdc14ceaefa832708f8de49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 22 Dec 2024 01:49:04 +0000 Subject: [PATCH 44/91] chore(boolean): move boolean state to `boolean` directory. --- src/lib/{ => boolean}/boolean-state.abstract.ts | 2 +- src/lib/{ => boolean}/boolean.class.ts | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/lib/{ => boolean}/boolean-state.abstract.ts (99%) rename src/lib/{ => boolean}/boolean.class.ts (100%) diff --git a/src/lib/boolean-state.abstract.ts b/src/lib/boolean/boolean-state.abstract.ts similarity index 99% rename from src/lib/boolean-state.abstract.ts rename to src/lib/boolean/boolean-state.abstract.ts index c2a81d9..20b2e24 100644 --- a/src/lib/boolean-state.abstract.ts +++ b/src/lib/boolean/boolean-state.abstract.ts @@ -1,5 +1,5 @@ // Abstract. -import { State } from "./state.abstract"; +import { State } from "../state.abstract"; /** * @description Handles the `boolean` type state. * @export diff --git a/src/lib/boolean.class.ts b/src/lib/boolean/boolean.class.ts similarity index 100% rename from src/lib/boolean.class.ts rename to src/lib/boolean/boolean.class.ts From c91813e589928ab7b9668c008f121b783dc04dcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 22 Dec 2024 01:49:49 +0000 Subject: [PATCH 45/91] test: update. --- src/test/array-state.spec.ts | 2 +- src/test/named-array-state.spec.ts | 2 +- src/test/named-boolean-array-state.spec.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/array-state.spec.ts b/src/test/array-state.spec.ts index 6991954..f7cc2a0 100644 --- a/src/test/array-state.spec.ts +++ b/src/test/array-state.spec.ts @@ -1,4 +1,4 @@ -import { ArrayState } from '../lib/array-state.abstract'; +import { ArrayState } from '../lib/array'; export class NumberArrayState extends ArrayState {} diff --git a/src/test/named-array-state.spec.ts b/src/test/named-array-state.spec.ts index 7879fe7..2c3c426 100644 --- a/src/test/named-array-state.spec.ts +++ b/src/test/named-array-state.spec.ts @@ -1,4 +1,4 @@ -import { NamedArrayState } from '../lib/named-array-state.abstract'; +import { NamedArrayState } from '../lib/array'; export class SomeoneState extends NamedArrayState {} diff --git a/src/test/named-boolean-array-state.spec.ts b/src/test/named-boolean-array-state.spec.ts index 9c3baab..b4ff866 100644 --- a/src/test/named-boolean-array-state.spec.ts +++ b/src/test/named-boolean-array-state.spec.ts @@ -1,4 +1,4 @@ -import { NamedBooleanArrayState } from '../lib/named-boolean-array-state.abstract'; +import { NamedBooleanArrayState } from '../lib/array'; export class Options extends NamedBooleanArrayState { From 8087cfa982292fdc0b65ce2e29d0089935f49fd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 22 Dec 2024 01:50:37 +0000 Subject: [PATCH 46/91] chore(boolean/index): add. --- src/lib/boolean/index.ts | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 src/lib/boolean/index.ts diff --git a/src/lib/boolean/index.ts b/src/lib/boolean/index.ts new file mode 100644 index 0000000..c56e339 --- /dev/null +++ b/src/lib/boolean/index.ts @@ -0,0 +1,2 @@ +export { BooleanState } from './boolean-state.abstract'; +export { Boolean } from './boolean.class'; \ No newline at end of file From ffa22c4c29fc088c014f82b41149b23a84d27ad6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 22 Dec 2024 01:51:11 +0000 Subject: [PATCH 47/91] chore(index): update. --- src/lib/index.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/lib/index.ts b/src/lib/index.ts index f7cdc80..167c68b 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -1,5 +1,8 @@ // Boolean state. -export { Boolean } from './boolean.class'; +export { + Boolean, + BooleanState +} from './boolean'; // Array state. export { ArrayState, @@ -13,7 +16,6 @@ export { Enum } from './enum.class'; export { ImmutableState } from './immutable-state.abstract'; // Data of type abstract state. export { Ability } from './ability.abstract'; -export { BooleanState } from './boolean-state.abstract'; export { EnumState } from './enum-state.abstract'; export { NullState } from './null-state.abstract'; export { NumberState } from './number-state.abstract'; From d934907afbb22e535d52e3e3ccf0716e87ef8f5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 22 Dec 2024 01:53:27 +0000 Subject: [PATCH 48/91] chore(enum state): move to `enum` directory. --- src/lib/{ => enum}/enum-state.abstract.ts | 2 +- src/lib/{ => enum}/enum.class.ts | 0 src/lib/enum/index.ts | 2 ++ 3 files changed, 3 insertions(+), 1 deletion(-) rename src/lib/{ => enum}/enum-state.abstract.ts (94%) rename src/lib/{ => enum}/enum.class.ts (100%) create mode 100644 src/lib/enum/index.ts diff --git a/src/lib/enum-state.abstract.ts b/src/lib/enum/enum-state.abstract.ts similarity index 94% rename from src/lib/enum-state.abstract.ts rename to src/lib/enum/enum-state.abstract.ts index 7ebfade..a3cdf60 100644 --- a/src/lib/enum-state.abstract.ts +++ b/src/lib/enum/enum-state.abstract.ts @@ -1,5 +1,5 @@ // Abstract. -import { State } from "./state.abstract"; +import { State } from "../state.abstract"; /** * @description Handles the `enum` type state. * @export diff --git a/src/lib/enum.class.ts b/src/lib/enum/enum.class.ts similarity index 100% rename from src/lib/enum.class.ts rename to src/lib/enum/enum.class.ts diff --git a/src/lib/enum/index.ts b/src/lib/enum/index.ts new file mode 100644 index 0000000..f143a8d --- /dev/null +++ b/src/lib/enum/index.ts @@ -0,0 +1,2 @@ +export { EnumState } from './enum-state.abstract'; +export { Enum } from './enum.class'; \ No newline at end of file From d0a72d2e215f3579ae7add69a1517eae88d9553f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 22 Dec 2024 01:53:35 +0000 Subject: [PATCH 49/91] chore(index): update. --- src/lib/index.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/lib/index.ts b/src/lib/index.ts index 167c68b..aa05776 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -11,12 +11,14 @@ export { NamedBooleanArrayState } from './array'; // Enum state. -export { Enum } from './enum.class'; +export { + Enum, + EnumState +} from './enum'; // Object abstract state. export { ImmutableState } from './immutable-state.abstract'; // Data of type abstract state. export { Ability } from './ability.abstract'; -export { EnumState } from './enum-state.abstract'; export { NullState } from './null-state.abstract'; export { NumberState } from './number-state.abstract'; export { ObjectState } from './object-state.abstract'; From c55f388691a1650386b859f76d62196ff2130d48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 22 Dec 2024 01:56:37 +0000 Subject: [PATCH 50/91] test(BooleanArrayState): add. --- src/test/boolean-array-state.spec.ts | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/test/boolean-array-state.spec.ts diff --git a/src/test/boolean-array-state.spec.ts b/src/test/boolean-array-state.spec.ts new file mode 100644 index 0000000..bec40f5 --- /dev/null +++ b/src/test/boolean-array-state.spec.ts @@ -0,0 +1,21 @@ +import { BooleanArrayState } from "../lib/array"; + +export class Options extends BooleanArrayState {} + +let options = new Options(true, true, true, false); + +describe(`BooleanArrayState`, () => { + beforeEach(() => { + options = new Options(true, true, true, false); + }); + it(`false()`, () => { + expect(options.false(0, 1).state).toEqual([false, false, true, false]); + }); + it(`true()`, () => { + expect(options.true(options.length - 1).state).toEqual([true, true, true, true]); + }); + it(`true()`, () => { + expect(options.true(0, 1)); + }); +}); +console.log(`BooleanArrayState: `, options); From 2396f95248ec2ceda72a2e7bc0e4220d3bf00335 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 22 Dec 2024 01:57:00 +0000 Subject: [PATCH 51/91] test(EnumState): update the import. --- src/test/enum-state.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/enum-state.spec.ts b/src/test/enum-state.spec.ts index a62d8af..b700e6b 100644 --- a/src/test/enum-state.spec.ts +++ b/src/test/enum-state.spec.ts @@ -1,4 +1,4 @@ -import { EnumState } from "../lib/enum-state.abstract"; +import { EnumState } from "../lib/enum"; enum Active { Yes, From 918c25c6bfe02079d3f66aebd278c62b1391b046 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 22 Dec 2024 01:57:47 +0000 Subject: [PATCH 52/91] docs(ObjectState): update. --- src/lib/object-state.abstract.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/object-state.abstract.ts b/src/lib/object-state.abstract.ts index aa71be1..b4c0bee 100644 --- a/src/lib/object-state.abstract.ts +++ b/src/lib/object-state.abstract.ts @@ -10,7 +10,7 @@ import { State } from "./state.abstract"; */ export abstract class ObjectState extends State { /** - * @description Returns a newly created and frozen clone of the current state. + * @description Returns the frozen object of the current state. * @public * @readonly * @type {Type} From 0e1d04249ebc1ab778d0b961896227832ce5d477 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 22 Dec 2024 01:59:24 +0000 Subject: [PATCH 53/91] docs(BooleanObjectState): update. --- src/lib/boolean-object-state.abstract.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/lib/boolean-object-state.abstract.ts b/src/lib/boolean-object-state.abstract.ts index e709390..7ef71bd 100644 --- a/src/lib/boolean-object-state.abstract.ts +++ b/src/lib/boolean-object-state.abstract.ts @@ -1,11 +1,10 @@ // Abstract. import { ObjectState } from "./object-state.abstract"; /** - * @description + * @description Manages the `object` state of pairs name-boolean. * @export * @abstract * @class BooleanObjectState - * @typedef {BooleanObjectState} * @template {PropertyKey} Names * @extends {ObjectState<{[Name in Names]: boolean}>} */ From 4b1c62af50834faa4de9f6bd60e0ea15a55a16a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 22 Dec 2024 02:01:21 +0000 Subject: [PATCH 54/91] chore(object): move object state to the `object` directory. --- src/lib/index.ts | 6 +++++- src/lib/{ => object}/boolean-object-state.abstract.ts | 0 src/lib/object/index.ts | 2 ++ src/lib/{ => object}/object-state.abstract.ts | 2 +- 4 files changed, 8 insertions(+), 2 deletions(-) rename src/lib/{ => object}/boolean-object-state.abstract.ts (100%) create mode 100644 src/lib/object/index.ts rename src/lib/{ => object}/object-state.abstract.ts (98%) diff --git a/src/lib/index.ts b/src/lib/index.ts index aa05776..1ad65c2 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -15,12 +15,16 @@ export { Enum, EnumState } from './enum'; +// Object state. +export { + BooleanObjectState, + ObjectState +} from './object'; // Object abstract state. export { ImmutableState } from './immutable-state.abstract'; // Data of type abstract state. export { Ability } from './ability.abstract'; export { NullState } from './null-state.abstract'; export { NumberState } from './number-state.abstract'; -export { ObjectState } from './object-state.abstract'; // Common abstract state. export { State } from './state.abstract'; \ No newline at end of file diff --git a/src/lib/boolean-object-state.abstract.ts b/src/lib/object/boolean-object-state.abstract.ts similarity index 100% rename from src/lib/boolean-object-state.abstract.ts rename to src/lib/object/boolean-object-state.abstract.ts diff --git a/src/lib/object/index.ts b/src/lib/object/index.ts new file mode 100644 index 0000000..ed834c7 --- /dev/null +++ b/src/lib/object/index.ts @@ -0,0 +1,2 @@ +export { BooleanObjectState } from "./boolean-object-state.abstract"; +export { ObjectState } from "./object-state.abstract"; diff --git a/src/lib/object-state.abstract.ts b/src/lib/object/object-state.abstract.ts similarity index 98% rename from src/lib/object-state.abstract.ts rename to src/lib/object/object-state.abstract.ts index b4c0bee..3deb368 100644 --- a/src/lib/object-state.abstract.ts +++ b/src/lib/object/object-state.abstract.ts @@ -1,5 +1,5 @@ // Abstract. -import { State } from "./state.abstract"; +import { State } from "../state.abstract"; /** * @description The `abstract class` handles the state of Javascript Object. * @export From 7f3606984684e46747d146589b52c62e1d3a694c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 22 Dec 2024 02:02:10 +0000 Subject: [PATCH 55/91] chore(Ability): change import. --- src/lib/ability.abstract.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/ability.abstract.ts b/src/lib/ability.abstract.ts index 3c4b71e..bfd98cf 100644 --- a/src/lib/ability.abstract.ts +++ b/src/lib/ability.abstract.ts @@ -1,5 +1,5 @@ // Class. -import { Boolean as Disabled, Boolean as Enabled } from "./boolean.class"; +import { Boolean as Disabled, Boolean as Enabled } from "./boolean"; /** * @description Ability as a `boolean` state (enabled/disabled) * @export From 07229a93a0d5df7c1214166009dca6627442e590 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 22 Dec 2024 03:10:28 +0000 Subject: [PATCH 56/91] feat(BooleanActionObjectState): add. --- .../boolean-action-object-state.abstract.ts | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/lib/object/boolean-action-object-state.abstract.ts diff --git a/src/lib/object/boolean-action-object-state.abstract.ts b/src/lib/object/boolean-action-object-state.abstract.ts new file mode 100644 index 0000000..aabd667 --- /dev/null +++ b/src/lib/object/boolean-action-object-state.abstract.ts @@ -0,0 +1,55 @@ +// Class. +import { BooleanObjectState } from "./boolean-object-state.abstract"; +/** + * @description + * @export + * @abstract + * @class BooleanActionObjectState + * @template {string} [Names=string] + * @template {string} [Actions=string] + * @extends {BooleanObjectState} + */ +export abstract class BooleanActionObjectState< + Names extends PropertyKey = PropertyKey, + Actions extends string = string, +> extends BooleanObjectState { + /** + * @description + * @type {*} + */ + #actions = new Map(); + + /** + * Creates an instance of child `class`. + * @constructor + * @param {Names[]} names + * @param {?[Actions[], Names[]][]} [actions] + */ + constructor( + names: Names[], + actions?: [Actions[], Names[]][], + ) { + super(names); + actions?.forEach(([names, states]) => this.#actions.set(names, states)) + this.#actions.forEach(names => this.true(names[0]).false(...names.slice(1))); + } + + /** + * @description + * @public + * @template {Actions} Action + * @param {Action} action + */ + public dispatch(action: Action) { + for (const [actions, names] of this.#actions) { + if (actions.includes(action)) { + if (actions.indexOf(action) === 0) { + this.true(names[0]).false(...names.slice(1)); + } else { + this.false(names[0]).true(...names.slice(1)); + } + break; + } + } + } +} From 1764ddb8540be423b5cafa8de04144d68fb70dba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 22 Dec 2024 03:10:45 +0000 Subject: [PATCH 57/91] test(BooleanActionObjectState): add. --- src/test/boolean-action-object-state.spec.ts | 45 ++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 src/test/boolean-action-object-state.spec.ts diff --git a/src/test/boolean-action-object-state.spec.ts b/src/test/boolean-action-object-state.spec.ts new file mode 100644 index 0000000..6f7c74e --- /dev/null +++ b/src/test/boolean-action-object-state.spec.ts @@ -0,0 +1,45 @@ +import { BooleanActionObjectState } from "../lib/object"; + +export class Connection extends BooleanActionObjectState {} + +const connection1 = new Connection( + ['connected'], [ + [['connect', 'disconnect'], ['connected']] + ]); + + +console.group(`BooleanActionObjectState`); + +connection1.dispatch('connect'); + +console.log(`connection1`, connection1); + + +const connection2 = new Connection( + ['connected', 'disconnected'], [ + [['connect', 'disconnect'], ['connected', 'disconnected']] + ]); + +connection2.dispatch('connect'); + +console.log(`connection2 connected`, connection2.get('connected')); + +connection2.dispatch('disconnect'); + +console.log(`connection disconnected`, connection2.get('connected')); + + +console.groupEnd(); + + + + +// const selectable = new BooleanActionObjectState( +// ['selected', 'deselected', 'unselected'], [ +// [['select', 'deselect'], ['selected', 'deselected', 'unselected']] +// ]); + +// selectable.dispatch('deselect'); + +// console.log(`selectable`, selectable); + From 097dd981ff3db43fcebcbbf7ccd69c5350065409 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 22 Dec 2024 03:12:12 +0000 Subject: [PATCH 58/91] chore(object/index): add `BooleanActionObjectState`. --- src/lib/object/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lib/object/index.ts b/src/lib/object/index.ts index ed834c7..d588ad5 100644 --- a/src/lib/object/index.ts +++ b/src/lib/object/index.ts @@ -1,2 +1,3 @@ +export { BooleanActionObjectState } from "./boolean-action-object-state.abstract"; export { BooleanObjectState } from "./boolean-object-state.abstract"; -export { ObjectState } from "./object-state.abstract"; +export { ObjectState } from "./object-state.abstract"; \ No newline at end of file From 46a0ef60ad7d1c08aa4f9ec0782411538ee2efd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 22 Dec 2024 03:12:54 +0000 Subject: [PATCH 59/91] refactor(BooleanObjectState): check the `names` length in the `updateState()` method. --- src/lib/object/boolean-object-state.abstract.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/object/boolean-object-state.abstract.ts b/src/lib/object/boolean-object-state.abstract.ts index 7ef71bd..964c2fc 100644 --- a/src/lib/object/boolean-object-state.abstract.ts +++ b/src/lib/object/boolean-object-state.abstract.ts @@ -75,11 +75,11 @@ export abstract class BooleanObjectState< * @description Updates the state of the specified `names` with the `valueFn`. * @private * @param {Names[]} [names=[]] - * @param {(name: Names) => boolean} valueFn + * @param {(name: Names) => boolean} valueFn The function to update the value under the specified `name`. * @returns {this} */ private updateState(names: Names[] = [], valueFn: (name: Names) => boolean): this { - this.update( + names.length > 0 && this.update( (names.length > 0 ? names : Object.keys(this.state) as Names[]).reduce>( (partial, name) => (Object.assign(partial, { [name]: valueFn(name) }), partial), {} ) From 862d30dfc151b741ae84b53f5fccee16e21f0de7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 22 Dec 2024 03:13:39 +0000 Subject: [PATCH 60/91] test: update. --- src/test/boolean-array-state.spec.ts | 4 +++- src/test/enum-state.spec.ts | 2 ++ src/test/named-array-state.spec.ts | 2 ++ src/test/named-boolean-array-state.spec.ts | 2 ++ src/test/null-state.spec.ts | 3 ++- src/test/number-state.spec.ts | 3 ++- 6 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/test/boolean-array-state.spec.ts b/src/test/boolean-array-state.spec.ts index bec40f5..4ab8e58 100644 --- a/src/test/boolean-array-state.spec.ts +++ b/src/test/boolean-array-state.spec.ts @@ -18,4 +18,6 @@ describe(`BooleanArrayState`, () => { expect(options.true(0, 1)); }); }); -console.log(`BooleanArrayState: `, options); +console.group(`BooleanArrayState`); +console.log(`options: `, options); +console.groupEnd(); diff --git a/src/test/enum-state.spec.ts b/src/test/enum-state.spec.ts index b700e6b..7c2ef36 100644 --- a/src/test/enum-state.spec.ts +++ b/src/test/enum-state.spec.ts @@ -14,4 +14,6 @@ export class ActiveEnum extends EnumState { const activeEnum = new ActiveEnum(Active.No); +console.group('EnumState'); console.log(activeEnum.is(Active.No)); +console.groupEnd(); diff --git a/src/test/named-array-state.spec.ts b/src/test/named-array-state.spec.ts index 2c3c426..667e758 100644 --- a/src/test/named-array-state.spec.ts +++ b/src/test/named-array-state.spec.ts @@ -46,4 +46,6 @@ describe(`NamedArrayState`, () => { }); }); +console.group(`NamedArrayState`); console.log(`someoneState`, someoneState); +console.groupEnd(); diff --git a/src/test/named-boolean-array-state.spec.ts b/src/test/named-boolean-array-state.spec.ts index b4ff866..188c8f4 100644 --- a/src/test/named-boolean-array-state.spec.ts +++ b/src/test/named-boolean-array-state.spec.ts @@ -29,4 +29,6 @@ describe(`ArrayState`, () => { }); }); +console.group(`NamedBooleanArrayState`); console.log(`NamedBooleanArrayState`, options); +console.groupEnd(); diff --git a/src/test/null-state.spec.ts b/src/test/null-state.spec.ts index 5730341..44c1744 100644 --- a/src/test/null-state.spec.ts +++ b/src/test/null-state.spec.ts @@ -6,8 +6,9 @@ const nullified = new Nullified(); nullified.set(); -console.log(`NullState`); +console.group(`NullState`); console.log(nullified.state); nullified.unset(); console.log(nullified.state); +console.groupEnd(); diff --git a/src/test/number-state.spec.ts b/src/test/number-state.spec.ts index c9d129b..6c70e38 100644 --- a/src/test/number-state.spec.ts +++ b/src/test/number-state.spec.ts @@ -9,6 +9,7 @@ export class NumberedState extends NumberState { const numberedState = new NumberedState(); +console.group(`NumberState`); console.log(numberedState.state); numberedState.decrement(); console.log(numberedState.state); @@ -18,4 +19,4 @@ numberedState.increment(5); console.log(numberedState.state); numberedState.reset(); console.log(numberedState.state); - +console.groupEnd(); From 9c109f9f5084e634cb07a0cb7cb9d7875567d42d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 22 Dec 2024 03:14:15 +0000 Subject: [PATCH 61/91] chore(index): add `BooleanActionObjectState`. --- src/lib/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/index.ts b/src/lib/index.ts index 1ad65c2..b9ef046 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -17,6 +17,7 @@ export { } from './enum'; // Object state. export { + BooleanActionObjectState, BooleanObjectState, ObjectState } from './object'; From 0bb87ef197fefddeea7887e32f2e7a2b995d42e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 22 Dec 2024 21:12:54 +0000 Subject: [PATCH 62/91] chore(Ability): move to the `ability` directory. --- src/lib/{ => ability}/ability.abstract.ts | 2 +- src/lib/ability/index.ts | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) rename src/lib/{ => ability}/ability.abstract.ts (95%) create mode 100644 src/lib/ability/index.ts diff --git a/src/lib/ability.abstract.ts b/src/lib/ability/ability.abstract.ts similarity index 95% rename from src/lib/ability.abstract.ts rename to src/lib/ability/ability.abstract.ts index bfd98cf..1f365b9 100644 --- a/src/lib/ability.abstract.ts +++ b/src/lib/ability/ability.abstract.ts @@ -1,5 +1,5 @@ // Class. -import { Boolean as Disabled, Boolean as Enabled } from "./boolean"; +import { Boolean as Disabled, Boolean as Enabled } from "../boolean"; /** * @description Ability as a `boolean` state (enabled/disabled) * @export diff --git a/src/lib/ability/index.ts b/src/lib/ability/index.ts new file mode 100644 index 0000000..24024a1 --- /dev/null +++ b/src/lib/ability/index.ts @@ -0,0 +1,2 @@ +export { Ability } from './ability.abstract'; +export { ActionableAbility } from './actionable-ability.abstract'; \ No newline at end of file From 962a5f25af2513feb177e4f1d4a4422c33dabe36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sat, 28 Dec 2024 02:09:07 +0000 Subject: [PATCH 63/91] refactor(Selected): remove. --- src/lib/selectable/selected.class.ts | 38 ---------------------------- 1 file changed, 38 deletions(-) delete mode 100644 src/lib/selectable/selected.class.ts diff --git a/src/lib/selectable/selected.class.ts b/src/lib/selectable/selected.class.ts deleted file mode 100644 index 4451f24..0000000 --- a/src/lib/selectable/selected.class.ts +++ /dev/null @@ -1,38 +0,0 @@ -// Class. -import { All } from "./all.class"; -// Abstract. -import { BooleanState } from "../boolean-state.abstract"; -/** - * @description Manages the selected state of `boolean` type. - * @export - * @class Selected - * @typedef {Selected} - * @extends {BooleanState} - */ -export class Selected extends BooleanState { - /** - * @description - * @public - * @returns {*} - */ - public get all() { - return this.#all; - } - - /** - * @description - * @type {boolean} - */ - #all - - /** - * Creates an instance of `Selected`. - * @constructor - * @param {?boolean} [selected] - */ - constructor(selected?: boolean, all = false) { - super(selected); - this.#all = new All(false, () => this.true(), () => this.false()); - typeof all === 'boolean' && all === true && this.#all.true(); - } -} From dabbd30244204fef96c573d1893668c09037dad3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sat, 28 Dec 2024 02:09:59 +0000 Subject: [PATCH 64/91] refactor(Selectable): set as `abstract`, and use `Selected` of `Boolean`. --- ...ctable.class.ts => selectable.abstract.ts} | 30 +++---------------- 1 file changed, 4 insertions(+), 26 deletions(-) rename src/lib/selectable/{selectable.class.ts => selectable.abstract.ts} (62%) diff --git a/src/lib/selectable/selectable.class.ts b/src/lib/selectable/selectable.abstract.ts similarity index 62% rename from src/lib/selectable/selectable.class.ts rename to src/lib/selectable/selectable.abstract.ts index 3a87854..380a998 100644 --- a/src/lib/selectable/selectable.class.ts +++ b/src/lib/selectable/selectable.abstract.ts @@ -1,17 +1,16 @@ // Class. -import { Ability } from '../ability/ability.class'; -import { Selected } from './selected.class'; +import { Ability } from '../ability/ability.abstract'; +import { Boolean as Selected } from '../boolean'; /** * @description Manages the selected state. * @export * @class Selectable - * @typedef {Selectable} * @extends {Ability} */ -export class Selectable extends Ability { +export abstract class Selectable extends Ability { /** * @description Privately stored selected state. - * @type {*} + * @type {Selected} */ #selected = new Selected(); @@ -25,16 +24,6 @@ export class Selectable extends Ability { return this; } - /** - * @description Sets the selectable state to unselected if the ability is enabled. - * @public - * @returns {this} - */ - public deselectAll(): this { - super.isEnabled() && this.#selected.all.false(); - return this; - } - /** * @description Checks whether the selectable state is selected. * @public @@ -54,16 +43,6 @@ export class Selectable extends Ability { return this; } - /** - * @description Sets the selectable state to selected if the ability is enabled. - * @public - * @returns {this} - */ - public selectAll(): this { - super.isEnabled() && this.#selected.all.true(); - return this; - } - /** * @description Toggles the selectable state between selected and unselected if the ability is enabled. * @public @@ -73,5 +52,4 @@ export class Selectable extends Ability { super.isEnabled() && this.#selected.toggle(); return this; } - } From bce33d78f07b3949a446b456b21033322227ebee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sat, 28 Dec 2024 02:10:56 +0000 Subject: [PATCH 65/91] refactor(SelectableGroup): add to handle multiple selections. --- src/lib/selectable/index.ts | 5 +- .../selectable/selectable-group.abstract.ts | 62 +++++++++++++++++++ 2 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 src/lib/selectable/selectable-group.abstract.ts diff --git a/src/lib/selectable/index.ts b/src/lib/selectable/index.ts index dbec100..5acfead 100644 --- a/src/lib/selectable/index.ts +++ b/src/lib/selectable/index.ts @@ -1,3 +1,2 @@ -export { All } from "./all.class"; -export { Selectable } from "./selectable.class"; -export { Selected } from "./selected.class"; +export { Selectable } from './selectable.abstract'; +export { SelectableGroup } from './selectable-group.abstract'; \ No newline at end of file diff --git a/src/lib/selectable/selectable-group.abstract.ts b/src/lib/selectable/selectable-group.abstract.ts new file mode 100644 index 0000000..8229933 --- /dev/null +++ b/src/lib/selectable/selectable-group.abstract.ts @@ -0,0 +1,62 @@ +// Abstract. +import { Ability } from "../ability/ability.abstract"; +// Class. +import { Selectable } from "./selectable.abstract"; +/** + * @description + * @export + * @abstract + * @class SelectableGroup + * @template {Selectable} T + * @extends {Ability} + */ +export abstract class SelectableGroup extends Ability { + + /** + * @description + * @protected + * @type {T[]} + */ + protected selectable: T[]; + + /** + * Creates an instance of `SelectableGroup`. + * @constructor + * @param {T[]} selectable + * @param {boolean} [enabled=true] + */ + constructor(selectable: T[], enabled = true) { + super(enabled); + this.selectable = selectable; + } + + /** + * @description + * @public + * @returns {this} + */ + public selectAll(): this { + this.selectable.forEach(selectable => selectable.select()); + return this; + } + + /** + * @description + * @public + * @returns {this} + */ + public deselectAll(): this { + this.selectable.forEach(selectable => selectable.deselect()); + return this; + } + + /** + * @description + * @public + * @returns {this} + */ + public toggleSelection(): this { + this.selectable.forEach(selectable => selectable.toggle()); + return this; + } +} From b649ba25f0fd0cf9b83d2359b0f5fde451b87032 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sat, 28 Dec 2024 02:12:57 +0000 Subject: [PATCH 66/91] refactor(ObjectState): change `initialState` to `state` param in the `constructor`, and `pick()` method picks when the object has the key. --- src/lib/object/object-state.abstract.ts | 30 +++++++++++++++---------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/src/lib/object/object-state.abstract.ts b/src/lib/object/object-state.abstract.ts index 3deb368..fa701d3 100644 --- a/src/lib/object/object-state.abstract.ts +++ b/src/lib/object/object-state.abstract.ts @@ -21,40 +21,46 @@ export abstract class ObjectState extends State { /** * @description The initial state that used in resetting the state. - * @type {*} + * @type {Type} */ #initialState; /** * Creates an instance of child class. * @constructor - * @param {Type} initialState The initial state of `Type`. + * @param {Type} state The initial state of `Type`. */ - constructor(initialState: Type) { - super(initialState); - this.#initialState = initialState; + constructor(state: Type) { + super(state); + this.#initialState = state; } /** - * @description + * @description Returns the value from the specified `key`. * @public * @template {keyof Type} Key - * @param {Key} key - * @returns {Type[Key]} + * @param {Key} key The key of generic type variable `Key` to get from the `object` state. + * @returns {Type[Key]} The return value is the value from the specified `key` of the `object` state. */ public get(key: Key): Type[Key] { return this.state[key]; } /** - * @description + * @description Picks the specified `keys` to the returned `object`. * @public * @template {keyof Type} Keys - * @param {...Keys[]} keys - * @returns {Pick} + * @param {...Keys[]} keys Arbitrary parameter `keys` of generic type variable `Keys` to pick from `object` state. + * @returns {Pick} The returned value is an `object` of `Type` with the specified `keys`. */ public pick(...keys: Keys[]): Pick { - return keys.reduce((object, key) => (Object.assign(object, {[key]: this.state[key]}), object), {} as Type); + return keys.reduce( + (object, key) => ( + Object.hasOwn(this.state, key) && Object.assign(object, {[key]: this.state[key]}), + object + ), + {} as Type + ); } /** From 815f428c8dea5db0a9f16555a78724eee2fc902d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sat, 28 Dec 2024 02:14:20 +0000 Subject: [PATCH 67/91] feat(ActionableAbility): add. --- .../ability/actionable-ability.abstract.ts | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/lib/ability/actionable-ability.abstract.ts diff --git a/src/lib/ability/actionable-ability.abstract.ts b/src/lib/ability/actionable-ability.abstract.ts new file mode 100644 index 0000000..216516d --- /dev/null +++ b/src/lib/ability/actionable-ability.abstract.ts @@ -0,0 +1,49 @@ +// Abstract. +import { Ability } from "./ability.abstract"; +import { BooleanActionable } from "../actionable"; +/** + * @description + * @export + * @abstract + * @class ActionableAbility + * @template {PropertyKey} [Names=PropertyKey] + * @template {string} [Actions=string] + * @extends {Ability} + */ +export abstract class ActionableAbility< + Names extends PropertyKey = PropertyKey, + Actions extends string = string, +> extends Ability { + /** + * @description + * @type {*} + */ + #booleanActionable; + + /** + * Creates an instance of `ActionableAbility`. + * @constructor + * @param {Names[]} names + * @param {?{ + * boolean?: [Actions[], Names[]][] + * }} [actions] + */ + constructor( + names: Names[], + actions?: { + boolean?: [Actions[], Names[]][] + } + ) { + super(); + this.#booleanActionable = new BooleanActionable(names, actions?.boolean); + } + + /** + * @description + * @public + * @param {Actions} action + */ + public dispatch(action: Action) { + this.isEnabled() && this.#booleanActionable.dispatch(action); + } +} From 71d0230c02770ffa2751b31f4c023ffdc693b0de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sat, 28 Dec 2024 02:15:02 +0000 Subject: [PATCH 68/91] feat(NamedObjectState): add. --- src/lib/object/named-object-state.abstract.ts | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 src/lib/object/named-object-state.abstract.ts diff --git a/src/lib/object/named-object-state.abstract.ts b/src/lib/object/named-object-state.abstract.ts new file mode 100644 index 0000000..3a1518a --- /dev/null +++ b/src/lib/object/named-object-state.abstract.ts @@ -0,0 +1,63 @@ +// Abstract. +import { ObjectState } from "./object-state.abstract"; +/** + * @description The `abstract class` handles the `object` state with the specified `names`. + * @export + * @abstract + * @class NamedObjectState + * @template [Type=any] + * @template {PropertyKey} [Names=PropertyKey] + * @extends {ObjectState<{[Name in Names]: Type}>} + */ +export abstract class NamedObjectState< + Type = any, + Names extends PropertyKey = PropertyKey, +> extends ObjectState<{[Name in Names]: Type}> { + /** + * @description + * @public + * @readonly + * @type {Names[]} + */ + public get names(): Names[] { + return this.#names; + } + + /** + * @description + * @type {Names[]} + */ + #names: Names[]; + + /** + * Creates an instance of child class. + * @constructor + * @param {Names[]} names The names to + */ + constructor(names: Names[]) { + super({} as {[Name in Names]: Type}); + this.#names = names; + } + + /** + * @inheritdoc + * @public + * @template {Names} Name + * @param {Name} name + * @returns {Type} + */ + public override get(name: Name): Type { + return super.get(name); + } + + /** + * @inheritdoc + * @public + * @template {Names} Name + * @param {...Name[]} names + * @returns {Pick<{[Name in Names]: Type}, Name>} + */ + public override pick(...names: Name[]): Pick<{[Name in Names]: Type}, Name> { + return super.pick(...names); + } +} From 194a883bcd43b2045572cfa820539104a26237c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sat, 28 Dec 2024 02:16:27 +0000 Subject: [PATCH 69/91] refactor(BooleanObjectState): use `NamedObjectState` and pass `names` into `super`. --- src/lib/object/boolean-object-state.abstract.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/lib/object/boolean-object-state.abstract.ts b/src/lib/object/boolean-object-state.abstract.ts index 964c2fc..b75198c 100644 --- a/src/lib/object/boolean-object-state.abstract.ts +++ b/src/lib/object/boolean-object-state.abstract.ts @@ -1,23 +1,24 @@ // Abstract. -import { ObjectState } from "./object-state.abstract"; +import { NamedObjectState } from "./named-object-state.abstract"; /** * @description Manages the `object` state of pairs name-boolean. * @export * @abstract * @class BooleanObjectState + * @typedef {BooleanObjectState} * @template {PropertyKey} Names - * @extends {ObjectState<{[Name in Names]: boolean}>} + * @extends {NamedObjectState} */ export abstract class BooleanObjectState< Names extends PropertyKey, -> extends ObjectState<{[Name in Names]: boolean}> { +> extends NamedObjectState { /** * Creates an instance of child class. * @constructor * @param {Names[]} names */ constructor(names: Names[]) { - super({} as {[Name in Names]: boolean}); + super(names); const partial: Partial<{[Name in Names]: boolean}> = {}; names.forEach(name => Object.assign(partial, {[name]: true})); this.update(partial); From e1b07873b1954fb94ee209664ec4dfd5dd3d9d98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sat, 28 Dec 2024 02:16:43 +0000 Subject: [PATCH 70/91] chore(index): update. --- src/lib/object/index.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/lib/object/index.ts b/src/lib/object/index.ts index d588ad5..4e1737b 100644 --- a/src/lib/object/index.ts +++ b/src/lib/object/index.ts @@ -1,3 +1,4 @@ -export { BooleanActionObjectState } from "./boolean-action-object-state.abstract"; -export { BooleanObjectState } from "./boolean-object-state.abstract"; -export { ObjectState } from "./object-state.abstract"; \ No newline at end of file +export { BooleanActionObjectState } from './boolean-action-object-state.abstract'; +export { BooleanObjectState } from './boolean-object-state.abstract'; +export { NamedObjectState } from './named-object-state.abstract'; +export { ObjectState } from './object-state.abstract'; \ No newline at end of file From ee9e27d3ff9f463fef68bb2f39a973626cbca8c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 29 Dec 2024 04:18:31 +0000 Subject: [PATCH 71/91] test(Ability): add. --- src/test/ability.spec.ts | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/test/ability.spec.ts diff --git a/src/test/ability.spec.ts b/src/test/ability.spec.ts new file mode 100644 index 0000000..2e1ed5f --- /dev/null +++ b/src/test/ability.spec.ts @@ -0,0 +1,27 @@ +import { Ability } from "../lib"; + + +export class Connection extends Ability {} + +let connection = new Connection(); + +describe(`Ability`, () => { + beforeEach(() => { + connection = new Connection(true); + }); + + + it(`enable()`, () => { + expect(connection.isDisabled()).toBeFalse(); + connection.enable(); + expect(connection.isDisabled()).toBeFalse(); + expect(connection.isEnabled()).toBeTrue(); + }); + + it(`disable()`, () => { + connection.disable() + expect(connection.isDisabled()).toBeTrue(); + expect(connection.isEnabled()).toBeFalse(); + }); + +}); From 2a4955278433126dafd00f50cd186ce5d6496aba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 29 Dec 2024 05:57:38 +0000 Subject: [PATCH 72/91] refactor(Selectable): set to `false` in `deselect()` method. --- src/lib/selectable/selectable.abstract.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/selectable/selectable.abstract.ts b/src/lib/selectable/selectable.abstract.ts index 380a998..ef50bf4 100644 --- a/src/lib/selectable/selectable.abstract.ts +++ b/src/lib/selectable/selectable.abstract.ts @@ -20,7 +20,7 @@ export abstract class Selectable extends Ability { * @returns {this} */ public deselect(): this { - super.isEnabled() && this.#selected.true(); + super.isEnabled() && this.#selected.false(); return this; } From a756bd1cd8ea61003d074447541d79028024a797 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 29 Dec 2024 05:57:53 +0000 Subject: [PATCH 73/91] refactor(ActionableAbility): remove. --- .../ability/actionable-ability.abstract.ts | 49 ------------------- src/lib/ability/index.ts | 1 - 2 files changed, 50 deletions(-) delete mode 100644 src/lib/ability/actionable-ability.abstract.ts diff --git a/src/lib/ability/actionable-ability.abstract.ts b/src/lib/ability/actionable-ability.abstract.ts deleted file mode 100644 index 216516d..0000000 --- a/src/lib/ability/actionable-ability.abstract.ts +++ /dev/null @@ -1,49 +0,0 @@ -// Abstract. -import { Ability } from "./ability.abstract"; -import { BooleanActionable } from "../actionable"; -/** - * @description - * @export - * @abstract - * @class ActionableAbility - * @template {PropertyKey} [Names=PropertyKey] - * @template {string} [Actions=string] - * @extends {Ability} - */ -export abstract class ActionableAbility< - Names extends PropertyKey = PropertyKey, - Actions extends string = string, -> extends Ability { - /** - * @description - * @type {*} - */ - #booleanActionable; - - /** - * Creates an instance of `ActionableAbility`. - * @constructor - * @param {Names[]} names - * @param {?{ - * boolean?: [Actions[], Names[]][] - * }} [actions] - */ - constructor( - names: Names[], - actions?: { - boolean?: [Actions[], Names[]][] - } - ) { - super(); - this.#booleanActionable = new BooleanActionable(names, actions?.boolean); - } - - /** - * @description - * @public - * @param {Actions} action - */ - public dispatch(action: Action) { - this.isEnabled() && this.#booleanActionable.dispatch(action); - } -} diff --git a/src/lib/ability/index.ts b/src/lib/ability/index.ts index 24024a1..30f514d 100644 --- a/src/lib/ability/index.ts +++ b/src/lib/ability/index.ts @@ -1,2 +1 @@ export { Ability } from './ability.abstract'; -export { ActionableAbility } from './actionable-ability.abstract'; \ No newline at end of file From 922b1f0e3e8ecb91833b564b2d7aa8bef80d66c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 29 Dec 2024 08:13:05 +0000 Subject: [PATCH 74/91] refactor(array): move `updateState()` method to the `ArrayState` and change the name to `updateIndexes()`. --- src/lib/array/array-state.abstract.ts | 12 ++++++++++++ src/lib/array/boolean-array-state.abstract.ts | 17 +++-------------- src/lib/array/named-array-state.abstract.ts | 11 ----------- .../array/named-boolean-array-state.abstract.ts | 6 +++--- 4 files changed, 18 insertions(+), 28 deletions(-) diff --git a/src/lib/array/array-state.abstract.ts b/src/lib/array/array-state.abstract.ts index f85e3e7..273e7d4 100644 --- a/src/lib/array/array-state.abstract.ts +++ b/src/lib/array/array-state.abstract.ts @@ -234,4 +234,16 @@ export abstract class ArrayState extends State> { super.set(this.state.map((v, i) => (i === index ? value : v))); return this; } + + /** + * @description Protected method to update the state of the specified `indexes` by using callback function. + * @protected + * @param {number[]} indexes Indexes to update the state. + * @param {(value: Type, index: number) => Type} callbackFn The callback function to update the state at index. + * @returns {Type[]} + */ + protected updateIndexes(indexes: number[], callbackFn: (value: Type, index: number) => Type): Type[] { + indexes = (indexes.length > 0 ? indexes : Array.from({ length: super.state.length }, (_, i) => 0 + i)); + return super.state.map((value, index) => indexes.includes(index) ? callbackFn(super.state[index], index) : value); + } } diff --git a/src/lib/array/boolean-array-state.abstract.ts b/src/lib/array/boolean-array-state.abstract.ts index 40e0b4a..c57470d 100644 --- a/src/lib/array/boolean-array-state.abstract.ts +++ b/src/lib/array/boolean-array-state.abstract.ts @@ -24,7 +24,7 @@ export abstract class BooleanArrayState extends ArrayState { * @returns {this} */ public false(...indexes: number[]): this { - super.set(this.updateState(indexes, () => false)); + super.set(this.updateIndexes(indexes, () => false)); return this; } @@ -35,7 +35,7 @@ export abstract class BooleanArrayState extends ArrayState { * @returns {this} */ public toggle(...indexes: number[]): this { - super.set(this.updateState(indexes, (index) => !super.state[index])); + super.set(this.updateIndexes(indexes, value => !value)); return this; } @@ -46,18 +46,7 @@ export abstract class BooleanArrayState extends ArrayState { * @returns {this} */ public true(...indexes: number[]): this { - super.set(this.updateState(indexes, () => true)); + super.set(this.updateIndexes(indexes, () => true)); return this; } - - /** - * @description Updates the `boolean` states of the specified `indexes`. - * @private - * @param {number[]} indexes Indexes to update the state. - * @param {(index: number) => boolean} state The state of `function` type to update. - * @returns {boolean[]} - */ - private updateState(indexes: number[], state: (index: number) => boolean): boolean[] { - return super.state.map((value, index) => indexes.includes(index) ? state(index) : value); - } } diff --git a/src/lib/array/named-array-state.abstract.ts b/src/lib/array/named-array-state.abstract.ts index 4ff2ee3..67946ff 100644 --- a/src/lib/array/named-array-state.abstract.ts +++ b/src/lib/array/named-array-state.abstract.ts @@ -100,15 +100,4 @@ export abstract class NamedArrayState< protected indexesOf(...names: Names[]): number[] { return names.map(name => this.#names.indexOf(name)); } - - /** - * @description Private method to update the state of the specified `indexes` by using function `state`. - * @protected - * @param {number[]} indexes `Array` type indexes of `number` type to update the value. - * @param {(index: number) => Type} state The `function` to update the state under the specified `index`. - * @returns {Type[]} - */ - protected updateState(indexes: number[], state: (index: number) => Type): Type[] { - return super.state.map((value, index) => indexes.includes(index) ? state(index) : value); - } } diff --git a/src/lib/array/named-boolean-array-state.abstract.ts b/src/lib/array/named-boolean-array-state.abstract.ts index 98e022e..2b32054 100644 --- a/src/lib/array/named-boolean-array-state.abstract.ts +++ b/src/lib/array/named-boolean-array-state.abstract.ts @@ -29,7 +29,7 @@ export abstract class NamedBooleanArrayState< * @returns {this} */ public false(...names: Names[]): this { - super.set(this.updateState(this.indexesOf(...names), () => false)); + super.set(this.updateIndexes(this.indexesOf(...names), () => false)); return this; } @@ -40,7 +40,7 @@ export abstract class NamedBooleanArrayState< * @returns {this} */ public toggle(...names: Names[]): this { - super.set(super.updateState(this.indexesOf(...names), index => !super.state[index])); + super.set(super.updateIndexes(this.indexesOf(...names), value => !value)); return this; } @@ -51,7 +51,7 @@ export abstract class NamedBooleanArrayState< * @returns {this} */ public true(...names: Names[]): this { - super.set(super.updateState(this.indexesOf(...names), () => true)); + super.set(super.updateIndexes(this.indexesOf(...names), () => true)); return this; } } From ba882f2c5e281c6874ddface19cc5f0b0c732d35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 29 Dec 2024 08:13:20 +0000 Subject: [PATCH 75/91] test(array): add. --- src/test/array/array-state.spec.ts | 78 ++++++++++++++++ src/test/array/boolea-array-state.spec.ts | 106 ++++++++++++++++++++++ src/test/array/named-array-state.spec.ts | 13 +++ 3 files changed, 197 insertions(+) create mode 100644 src/test/array/array-state.spec.ts create mode 100644 src/test/array/boolea-array-state.spec.ts create mode 100644 src/test/array/named-array-state.spec.ts diff --git a/src/test/array/array-state.spec.ts b/src/test/array/array-state.spec.ts new file mode 100644 index 0000000..e9f9e5c --- /dev/null +++ b/src/test/array/array-state.spec.ts @@ -0,0 +1,78 @@ +import { ArrayState } from '../../lib/array'; + +export class NumberArrayState extends ArrayState {} + +let numberArrayState = new NumberArrayState([27, 37, 47]); + +describe(`ArrayState`, () => { + beforeEach(() => { + numberArrayState = new NumberArrayState([27, 37, 47]); + }); + it(`append()`, () => { + numberArrayState.append(34); + expect(numberArrayState.state[3]).toEqual(34); + }); + + it(`at()`, () => { + expect(numberArrayState.at(2)).toEqual(47); + }); + + it(`clear()`, () => { + expect(numberArrayState.clear().state).toEqual([]); + }); + + it(`find()`, () => { + expect(numberArrayState.find(value => value === 37)).toEqual(37); + }); + + it(`filter()`, () => { + expect(numberArrayState.filter(value => value === 37)).toEqual([37]); + }); + + it(`first()`, () => { + expect(numberArrayState.first()).toEqual(27); + }); + + it(`insert()`, () => { + expect(numberArrayState.insert(1, 34).state[1]).toEqual(34); + }); + + it(`last()`, () => { + expect(numberArrayState.last()).toEqual(47); + }); + + it(`merge()`, () => { + expect(numberArrayState.merge([34, 0], 1).state).toEqual([27, 34, 0, 37, 47]); + }); + + it(`prepend()`, () => { + expect(numberArrayState.prepend(34, 0).state).toEqual([34, 0, 27, 37, 47]); + }); + + it(`pick()`, () => { + expect(numberArrayState.pick(1, 2)).toEqual([37, 47]); + }); + + it(`remove()`, () => { + expect(numberArrayState.remove(1, 2).at(0)).toEqual(27); + }); + + it(`removeRange()`, () => { + numberArrayState.merge([34, 35, 36, 37, 38, 39, 40, 41, 42]); + expect(numberArrayState.removeRange(4, 7).state).toEqual([27, 37, 47, 34, 39, 40, 41, 42]); + }); + + it(`reset()`, () => { + expect(numberArrayState.reset().state).toEqual([27, 37, 47]); + }); + + it(`swap()`, () => { + expect(numberArrayState.swap(1, 2).state).toEqual([27, 47, 37]); + console.log(numberArrayState.state); + }); + + it(`update()`, () => { + expect(numberArrayState.update(1, 344).state[1]).toEqual(344); + }); +}); +console.log(`numberArrayState`, numberArrayState.state); diff --git a/src/test/array/boolea-array-state.spec.ts b/src/test/array/boolea-array-state.spec.ts new file mode 100644 index 0000000..8762b3f --- /dev/null +++ b/src/test/array/boolea-array-state.spec.ts @@ -0,0 +1,106 @@ +import { BooleanArrayState as AbstractBooleanArrayState } from '../../lib/array'; + +export class BooleanArrayState extends AbstractBooleanArrayState {} + +let booleanArrayState = new BooleanArrayState(false, false, true, true); + +describe(`BooleanArrayState`, () => { + beforeEach(() => { + booleanArrayState = new BooleanArrayState(false, false, true, true); + }); + + it(`false()`, () => { + booleanArrayState.false(3); + expect(booleanArrayState.state[3]).toBeFalse(); + expect(booleanArrayState.state[2]).toBeTrue(); + booleanArrayState.false(); + expect(booleanArrayState.state).toEqual([false, false, false, false]); + }); + + it(`true()`, () => { + booleanArrayState.true(0); + expect(booleanArrayState.state[0]).toBeTrue(); + expect(booleanArrayState.state[1]).toBeFalse(); + booleanArrayState.true(); + expect(booleanArrayState.state).toEqual([true, true, true, true]); + }); + + it(`toggle()`, () => { + booleanArrayState.toggle(); + console.log(booleanArrayState.state); + expect(booleanArrayState.state).toEqual([true, true, false, false]); + }); + + // Defaults. + it(`append()`, () => { + booleanArrayState.append(true); + expect(booleanArrayState.state[4]).toBeTrue(); + + booleanArrayState.append(false); + expect(booleanArrayState.state[5]).toBeFalse(); + }); + + it(`at()`, () => { + expect(booleanArrayState.at(0)).toBeFalse(); + }); + + it(`clear()`, () => { + expect(booleanArrayState.clear().state).toEqual([]); + }); + + it(`find()`, () => { + expect(booleanArrayState.find(value => value === false)).toEqual(false); + }); + + it(`filter()`, () => { + expect(booleanArrayState.filter(value => value === true)).toEqual([true, true]); + }); + + it(`first()`, () => { + expect(booleanArrayState.first()).toEqual(false); + }); + + it(`insert()`, () => { + expect(booleanArrayState.insert(1, true).state[1]).toEqual(true); + expect(booleanArrayState.insert(0, false).state[0]).toEqual(false); + }); + + it(`last()`, () => { + expect(booleanArrayState.last()).toEqual(true); + }); + + it(`merge()`, () => { + expect(booleanArrayState.merge([true, false], 1).state).toEqual([false, true, false, false, true, true]); + }); + + it(`prepend()`, () => { + expect(booleanArrayState.prepend(false, true).state).toEqual([false, true, false, false, true, true]); + }); + + it(`pick()`, () => { + expect(booleanArrayState.pick(1, 2)).toEqual([false, true]); + }); + + it(`remove()`, () => { + expect(booleanArrayState.remove(1, 2).state).toEqual([false, true]); + }); + + it(`removeRange()`, () => { + expect(booleanArrayState.merge([false, true, true, true, false, false, false, false]).removeRange(3, 10).state).toEqual([false, false, true, false]); + }); + + it(`reset()`, () => { + expect(booleanArrayState.merge([false, true, true, true, false, false, false, false]).reset().state).toEqual([false, false, true, true]); + }); + + it(`swap()`, () => { + expect(booleanArrayState.swap(0, 3).state).toEqual([true, false, true, false]); + }); + + it(`update()`, () => { + expect(booleanArrayState.update(1, true).state[1]).toEqual(true); + }); +}); +console.group(`BooleanArrayState`); +console.info(`booleanArrayState.state: `, booleanArrayState.state); +console.groupEnd(); diff --git a/src/test/array/named-array-state.spec.ts b/src/test/array/named-array-state.spec.ts new file mode 100644 index 0000000..d19f425 --- /dev/null +++ b/src/test/array/named-array-state.spec.ts @@ -0,0 +1,13 @@ +import { NamedArrayState as AbstractNamedArrayState } from "../../lib"; + + +export class Profile< + Names extends string, + Type +> extends AbstractNamedArrayState {} + + +let namedArrayState = new Profile(['firstname', 'surname', 'age'], ['Name', 'Valkovitz', 39]); + + +// namedArrayState. \ No newline at end of file From 3ce2ac5748406044d2b46c2a2c1e102d8843b21d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 29 Dec 2024 08:13:42 +0000 Subject: [PATCH 76/91] test(array): move to `array` directory. --- src/test/array-state.spec.ts | 78 ------------------------------------ 1 file changed, 78 deletions(-) delete mode 100644 src/test/array-state.spec.ts diff --git a/src/test/array-state.spec.ts b/src/test/array-state.spec.ts deleted file mode 100644 index f7cc2a0..0000000 --- a/src/test/array-state.spec.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { ArrayState } from '../lib/array'; - -export class NumberArrayState extends ArrayState {} - -let numberArrayState = new NumberArrayState([27, 37, 47]); - -describe(`ArrayState`, () => { - beforeEach(() => { - numberArrayState = new NumberArrayState([27, 37, 47]); - }); - it(`append()`, () => { - numberArrayState.append(34); - expect(numberArrayState.state[3]).toEqual(34); - }); - - it(`at()`, () => { - expect(numberArrayState.at(2)).toEqual(47); - }); - - it(`clear()`, () => { - expect(numberArrayState.clear().state).toEqual([]); - }); - - it(`find()`, () => { - expect(numberArrayState.find(value => value === 37)).toEqual(37); - }); - - it(`filter()`, () => { - expect(numberArrayState.filter(value => value === 37)).toEqual([37]); - }); - - it(`first()`, () => { - expect(numberArrayState.first()).toEqual(27); - }); - - it(`insert()`, () => { - expect(numberArrayState.insert(1, 34).state[1]).toEqual(34); - }); - - it(`last()`, () => { - expect(numberArrayState.last()).toEqual(47); - }); - - it(`merge()`, () => { - expect(numberArrayState.merge([34, 0], 1).state).toEqual([27, 34, 0, 37, 47]); - }); - - it(`prepend()`, () => { - expect(numberArrayState.prepend(34, 0).state).toEqual([34, 0, 27, 37, 47]); - }); - - it(`pick()`, () => { - expect(numberArrayState.pick(1, 2)).toEqual([37, 47]); - }); - - it(`remove()`, () => { - expect(numberArrayState.remove(1, 2).at(0)).toEqual(27); - }); - - it(`removeRange()`, () => { - numberArrayState.merge([34, 35, 36, 37, 38, 39, 40, 41, 42]); - expect(numberArrayState.removeRange(4, 7).state).toEqual([27, 37, 47, 34, 39, 40, 41, 42]); - }); - - it(`reset()`, () => { - expect(numberArrayState.reset().state).toEqual([27, 37, 47]); - }); - - it(`swap()`, () => { - expect(numberArrayState.swap(1, 2).state).toEqual([27, 47, 37]); - console.log(numberArrayState.state); - }); - - it(`update()`, () => { - expect(numberArrayState.update(1, 344).state[1]).toEqual(344); - }); -}); -console.log(`numberArrayState`, numberArrayState.state); From c9d3ff2f7ec375aaaa093035209c0bb9929076a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 29 Dec 2024 08:31:07 +0000 Subject: [PATCH 77/91] refactor(BooleanActionObjectState): use as state names to actions, instead of multiple. --- .../boolean-action-object-state.abstract.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/lib/object/boolean-action-object-state.abstract.ts b/src/lib/object/boolean-action-object-state.abstract.ts index aabd667..1ad9421 100644 --- a/src/lib/object/boolean-action-object-state.abstract.ts +++ b/src/lib/object/boolean-action-object-state.abstract.ts @@ -17,25 +17,25 @@ export abstract class BooleanActionObjectState< * @description * @type {*} */ - #actions = new Map(); + #actions = new Set(); /** * Creates an instance of child `class`. * @constructor * @param {Names[]} names - * @param {?[Actions[], Names[]][]} [actions] + * @param {?Actions[]} [actions] */ constructor( names: Names[], - actions?: [Actions[], Names[]][], + actions?: Actions[], ) { super(names); - actions?.forEach(([names, states]) => this.#actions.set(names, states)) - this.#actions.forEach(names => this.true(names[0]).false(...names.slice(1))); + actions?.forEach(action => this.#actions.add(action)); + this.#actions.size > 0 && this.true(super.names[0]).false(...super.names.slice(1)); } /** - * @description + * @description Dispatch the `action` to set the first value in * @public * @template {Actions} Action * @param {Action} action @@ -44,9 +44,9 @@ export abstract class BooleanActionObjectState< for (const [actions, names] of this.#actions) { if (actions.includes(action)) { if (actions.indexOf(action) === 0) { - this.true(names[0]).false(...names.slice(1)); + this.true(super.names[0]).false(...super.names.slice(1)); } else { - this.false(names[0]).true(...names.slice(1)); + this.false(super.names[0]).true(...super.names.slice(1)); } break; } From ec7cd7aca1013f0c1c46ec24612281a2d762edbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 29 Dec 2024 08:38:39 +0000 Subject: [PATCH 78/91] refactor(BooleanObjectState): change the method name from `updateState()` to `updateNames()`. --- src/lib/object/boolean-object-state.abstract.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/lib/object/boolean-object-state.abstract.ts b/src/lib/object/boolean-object-state.abstract.ts index b75198c..23e9a78 100644 --- a/src/lib/object/boolean-object-state.abstract.ts +++ b/src/lib/object/boolean-object-state.abstract.ts @@ -5,7 +5,6 @@ import { NamedObjectState } from "./named-object-state.abstract"; * @export * @abstract * @class BooleanObjectState - * @typedef {BooleanObjectState} * @template {PropertyKey} Names * @extends {NamedObjectState} */ @@ -32,7 +31,7 @@ export abstract class BooleanObjectState< * @returns {this} */ public false(...names: Name[]): this { - this.updateState(names, () => false); + this.updateNames(names, () => false); return this; } @@ -56,7 +55,7 @@ export abstract class BooleanObjectState< * @returns {this} */ public toggle(...names: Name[]): this { - this.updateState(names, name => !this.state[name]); + this.updateNames(names, name => !this.state[name]); return this; } @@ -68,7 +67,7 @@ export abstract class BooleanObjectState< * @returns {this} */ public true(...names: Name[]): this { - this.updateState(names, () => true); + this.updateNames(names, () => true); return this; } @@ -76,13 +75,13 @@ export abstract class BooleanObjectState< * @description Updates the state of the specified `names` with the `valueFn`. * @private * @param {Names[]} [names=[]] - * @param {(name: Names) => boolean} valueFn The function to update the value under the specified `name`. + * @param {(name: Names) => boolean} callbackFn The function to update the value under the specified `name`. * @returns {this} */ - private updateState(names: Names[] = [], valueFn: (name: Names) => boolean): this { + private updateNames(names: Names[] = [], callbackFn: (name: Names) => boolean): this { names.length > 0 && this.update( (names.length > 0 ? names : Object.keys(this.state) as Names[]).reduce>( - (partial, name) => (Object.assign(partial, { [name]: valueFn(name) }), partial), {} + (partial, name) => (Object.assign(partial, { [name]: callbackFn(name) }), partial), {} ) ); return this; From 2ff838d227e990e632be5f850e1376fe6c129b9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 29 Dec 2024 09:14:54 +0000 Subject: [PATCH 79/91] docs(README.md): update. --- README.md | 179 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 178 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4414983..f795839 100644 --- a/README.md +++ b/README.md @@ -22,10 +22,28 @@ Simple state management for TypeScript. * [Installation](#installation) * [Api](#api) + * [`Ability`](#ability) + + * [`ArrayState`](#arraystate) + * [`BooleanArrayState`](#booleanarraystate) + * [`NamedArrayState`](#namedarraystate) + * [`NamedBooleanArrayState`](#namedbooleanarraystate) + + * [`Boolean`](#boolean) * [`BooleanState`](#booleanstate) + + * [`Enum`](#enum) * [`EnumState`](#enumstate) + + * [`BooleanActionObjectState`](#booleanactionobjectstate) + * [`BooleanObjectState`](#booleanobjectstate) + * [`NamedObjectState`](#namedobjectstate) + * [`ObjectState`](#objectState) + + * [`ImmutableState`](#immutablestate) * [`NullState`](#nullstate) * [`NumberState`](#numberstate) + * [`State`](#state) * [Immutability](#immutability) * [Sealed](#sealed) * [Frozen](#frozen) @@ -45,8 +63,28 @@ npm install @typescript-package/state ```typescript import { + Ability, + + // Array. + ArrayState, + BooleanArrayState, + NamedArrayState, + NamedBooleanArrayState, + + // Boolean. + Boolean, BooleanState, + + // Enum. + Enum, EnumState, + + // Object. + BooleanActionObjectState, + BooleanObjectState, + NamedObjectState, + ObjectState, + NullState, NumberState, ImmutableState, @@ -54,6 +92,110 @@ import { } from '@typescript-package/state'; ``` +### `Ability` + +```typescript +import { Ability } from '@typescript-package/state'; + +// Extend the Ability class for a specific type +export class Connection extends Ability {} + +// Initialize the connection. +const connection = new Connection(); + +// Disables the connection. +connection.disable(); +connection.isDisabled(); + +// Enables the connection. +connection.enable(); +connection.isEnabled(); +``` + +### `ArrayState` + +```typescript +import { ArrayState } from '@typescript-package/state'; + +// Extend the ArrayState class for a specific type +export class Queue extends ArrayState { + // Additional custom methods specific to Queue can be added if needed +} + +const queue = new Queue([27, 28, 29]); + +// Append a number to the array state +queue.append(30); +console.log(queue.state); // Output: [27, 28, 29, 30] + +// Insert a number at a specific index +queue.insert(2, 99); +console.log(queue.state); // Output: [27, 28, 99, 29, 30] + +// Remove a number by index +queue.remove(1); +console.log(queue.state); // Output: [27, 99, 29, 30] + +// Pick specific indexes +const picked = queue.pick(0, 2); +console.log(picked); // Output: [27, 29] + +// Swap two elements +queue.swap(1, 3); +console.log(queue.state); // Output: [27, 30, 29, 99] + +// Reset the state to its initial state +queue.reset(); +console.log(queue.state); // Output: [27, 28, 29] +``` + +### `BooleanArrayState` + +```typescript +import { BooleanArrayState as AbstractBooleanArrayState } from '@typescript-package/state'; + +// Extend the AbstractBooleanArrayState class for a specific type +export class BooleanArrayState extends AbstractBooleanArrayState { + // Additional custom methods specific to BooleanArrayState can be added if needed +} + +let booleanArrayState = new BooleanArrayState(false, false, true, true); + +// Sets all values to `false`. +booleanArrayState.false(); +console.log(booleanArrayState.state); // Output: [false, false, false, false] + +// Toggles all values to `true`. +booleanArrayState.toggle(); +console.log(booleanArrayState.state); // Output: [true, true, true, true] + +// Toggles all values to `false`. +booleanArrayState.toggle(); +console.log(booleanArrayState.state); // Output: [false, false, false, false] + +// Sets all values to `true`. +booleanArrayState.true(); +console.log(booleanArrayState.state); // Output: [true, true, true, true] +``` + +### `NamedArrayState` + +```typescript +import { NamedArrayState } from '@typescript-package/state'; +``` + +### `NamedBooleanArrayState` + +```typescript +import { NamedBooleanArrayState } from '@typescript-package/state'; +``` + +### `Boolean` + +```typescript +import { Boolean } from '@typescript-package/state'; +``` + ### `BooleanState` ```typescript @@ -85,6 +227,12 @@ const activeState = new ActiveState(); activeState.deactivate(); ``` +### `Enum` + +```typescript +import { Enum } from '@typescript-package/state'; +``` + ### `EnumState` ```typescript @@ -101,7 +249,6 @@ export class ActiveEnum extends EnumState { constructor(state: Active) { super(state, Active); } - } // Initialize. @@ -111,6 +258,31 @@ const activeEnum = new ActiveEnum(Active.No); activeEnum.is(Active.No) ``` +### `BooleanActionObjectState` + +```typescript +``` + +### `BooleanObjectState` + +```typescript +``` + +### `NamedObjectState` + +```typescript +``` + +### `ObjectState` + +```typescript +``` + +### `ImmutableState` + +```typescript +``` + ### `NullState` ```typescript @@ -158,6 +330,11 @@ numberedState.increment(5); numberedState.reset(); ``` +### `State` + +```typescript +``` + ## Immutability ### Sealed From 5de0501ac68bc46498aad50507ca50b3d1a6ba13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 29 Dec 2024 09:15:41 +0000 Subject: [PATCH 80/91] docs(README.md): update. --- README.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/README.md b/README.md index f795839..aac1809 100644 --- a/README.md +++ b/README.md @@ -23,23 +23,18 @@ Simple state management for TypeScript. * [Installation](#installation) * [Api](#api) * [`Ability`](#ability) - * [`ArrayState`](#arraystate) * [`BooleanArrayState`](#booleanarraystate) * [`NamedArrayState`](#namedarraystate) * [`NamedBooleanArrayState`](#namedbooleanarraystate) - * [`Boolean`](#boolean) * [`BooleanState`](#booleanstate) - * [`Enum`](#enum) * [`EnumState`](#enumstate) - * [`BooleanActionObjectState`](#booleanactionobjectstate) * [`BooleanObjectState`](#booleanobjectstate) * [`NamedObjectState`](#namedobjectstate) * [`ObjectState`](#objectState) - * [`ImmutableState`](#immutablestate) * [`NullState`](#nullstate) * [`NumberState`](#numberstate) From bc983a2412121895bab8af58952a8f935c2195df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 29 Dec 2024 09:51:05 +0000 Subject: [PATCH 81/91] test(array): update. --- src/test/array/array-state.spec.ts | 100 +++++++++++++++++- ...te.spec.ts => boolean-array-state.spec.ts} | 19 ++++ 2 files changed, 118 insertions(+), 1 deletion(-) rename src/test/array/{boolea-array-state.spec.ts => boolean-array-state.spec.ts} (83%) diff --git a/src/test/array/array-state.spec.ts b/src/test/array/array-state.spec.ts index e9f9e5c..25401fd 100644 --- a/src/test/array/array-state.spec.ts +++ b/src/test/array/array-state.spec.ts @@ -75,4 +75,102 @@ describe(`ArrayState`, () => { expect(numberArrayState.update(1, 344).state[1]).toEqual(344); }); }); -console.log(`numberArrayState`, numberArrayState.state); +console.group(`ArrayState`); +console.info(`numberArrayState.state`, numberArrayState.state); + + +// Extend the ArrayState class for a specific type +export class Numbers extends ArrayState { + // Additional custom methods specific to Numbers can be added if needed +} + +// Initialize `Numbers`. +const numbers = new Numbers([27, 28, 29]); + +// Append a number to the array state +numbers.append(30); +console.log(numbers.state); // Output: [27, 28, 29, 30] + +// Insert a number at a specific index +numbers.insert(2, 99); +console.log(numbers.state); // Output: [27, 28, 99, 29, 30] + +// Remove a number by index +numbers.remove(1); +console.log(numbers.state); // Output: [27, 99, 29, 30] + +// Pick specific indexes +const picked = numbers.pick(0, 2); +console.log(picked); // Output: [27, 29] + +// Swap two elements +numbers.swap(1, 3); +console.log(numbers.state); // Output: [27, 30, 29, 99] + +// Reset the state to its initial state +numbers.reset(); +console.log(numbers.state); // Output: [27, 28, 29] + +export class Queue extends ArrayState { + /** + * Adds an item to the end of the queue (enqueue operation). + * @param {number} value - The number to add to the queue. + * @returns {this} + */ + public enqueue(value: number): this { + return this.append(value); + } + + /** + * Removes and returns the item at the front of the queue (dequeue operation). + * @returns {number | undefined} - The dequeued number or undefined if the queue is empty. + */ + public dequeue(): number | undefined { + const front = this.first(); + this.remove(0); // Remove the first element + return front; + } + + /** + * Returns the item at the front of the queue without removing it. + * @returns {number | undefined} - The number at the front of the queue. + */ + public peek(): number | undefined { + return this.first(); + } + + /** + * Checks if the queue is empty. + * @returns {boolean} - True if the queue is empty, false otherwise. + */ + public isEmpty(): boolean { + return this.length === 0; + } +} + +// Initialize `Queue`. +const queue = new Queue([27, 28, 29]); + +// Enqueue a number +queue.enqueue(30); +console.log(`queue.state`, queue.state); // Output: [27, 28, 29, 30] + +// Dequeue a number +const dequeued = queue.dequeue(); +console.log(dequeued); // Output: 27 +console.log(queue.state); // Output: [28, 29, 30] + +// Peek at the front of the queue +const front = queue.peek(); +console.log(front); // Output: 28 + +// Check if the queue is empty +console.log(queue.isEmpty()); // Output: false + +// Dequeue all items +queue.dequeue(); +queue.dequeue(); +queue.dequeue(); +console.log(queue.isEmpty()); // Output: true + +console.groupEnd(); diff --git a/src/test/array/boolea-array-state.spec.ts b/src/test/array/boolean-array-state.spec.ts similarity index 83% rename from src/test/array/boolea-array-state.spec.ts rename to src/test/array/boolean-array-state.spec.ts index 8762b3f..1acb190 100644 --- a/src/test/array/boolea-array-state.spec.ts +++ b/src/test/array/boolean-array-state.spec.ts @@ -103,4 +103,23 @@ describe(`BooleanArrayState`, () => { }); console.group(`BooleanArrayState`); console.info(`booleanArrayState.state: `, booleanArrayState.state); + +booleanArrayState = new BooleanArrayState(false, false, true, true); + +// Sets all values to `false`. +booleanArrayState.false(); +console.log(booleanArrayState.state); // Output: [false, false, false, false] + +// Toggles all values to `true`. +booleanArrayState.toggle(); +console.log(booleanArrayState.state); // Output: [true, true, true, true] + +// Toggles all values to `false`. +booleanArrayState.toggle(); +console.log(booleanArrayState.state); // Output: [false, false, false, false] + +// Sets all values to `true`. +booleanArrayState.true(); +console.log(booleanArrayState.state); // Output: [true, true, true, true] + console.groupEnd(); From 7e355189d0d7361e6fe74f978d104d46714fe59d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 29 Dec 2024 09:51:29 +0000 Subject: [PATCH 82/91] docs(README.md): update. --- README.md | 104 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 89 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index aac1809..d1b2db0 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Simple state management for TypeScript. * [`BooleanActionObjectState`](#booleanactionobjectstate) * [`BooleanObjectState`](#booleanobjectstate) * [`NamedObjectState`](#namedobjectstate) - * [`ObjectState`](#objectState) + * [`ObjectState`](#objectstate) * [`ImmutableState`](#immutablestate) * [`NullState`](#nullstate) * [`NumberState`](#numberstate) @@ -113,35 +113,103 @@ connection.isEnabled(); import { ArrayState } from '@typescript-package/state'; // Extend the ArrayState class for a specific type -export class Queue extends ArrayState { - // Additional custom methods specific to Queue can be added if needed +export class Numbers extends ArrayState { + // Additional custom methods specific to Numbers can be added if needed } -const queue = new Queue([27, 28, 29]); +// Initialize `Numbers`. +const numbers = new Numbers([27, 28, 29]); // Append a number to the array state -queue.append(30); -console.log(queue.state); // Output: [27, 28, 29, 30] +numbers.append(30); +console.log(numbers.state); // Output: [27, 28, 29, 30] // Insert a number at a specific index -queue.insert(2, 99); -console.log(queue.state); // Output: [27, 28, 99, 29, 30] +numbers.insert(2, 99); +console.log(numbers.state); // Output: [27, 28, 99, 29, 30] // Remove a number by index -queue.remove(1); -console.log(queue.state); // Output: [27, 99, 29, 30] +numbers.remove(1); +console.log(numbers.state); // Output: [27, 99, 29, 30] // Pick specific indexes -const picked = queue.pick(0, 2); +const picked = numbers.pick(0, 2); console.log(picked); // Output: [27, 29] // Swap two elements -queue.swap(1, 3); -console.log(queue.state); // Output: [27, 30, 29, 99] +numbers.swap(1, 3); +console.log(numbers.state); // Output: [27, 30, 29, 99] // Reset the state to its initial state -queue.reset(); -console.log(queue.state); // Output: [27, 28, 29] +numbers.reset(); +console.log(numbers.state); // Output: [27, 28, 29] +``` + +```typescript +import { ArrayState } from '@typescript-package/state'; + +// Extend the ArrayState class for a specific type +export class Queue extends ArrayState { + /** + * Adds an item to the end of the queue (enqueue operation). + * @param {number} value - The number to add to the queue. + * @returns {this} + */ + public enqueue(value: number): this { + return this.append(value); + } + + /** + * Removes and returns the item at the front of the queue (dequeue operation). + * @returns {number | undefined} - The dequeued number or undefined if the queue is empty. + */ + public dequeue(): number | undefined { + const front = this.first(); + this.remove(0); // Remove the first element + return front; + } + + /** + * Returns the item at the front of the queue without removing it. + * @returns {number | undefined} - The number at the front of the queue. + */ + public peek(): number | undefined { + return this.first(); + } + + /** + * Checks if the queue is empty. + * @returns {boolean} - True if the queue is empty, false otherwise. + */ + public isEmpty(): boolean { + return this.length === 0; + } +} + +// Initialize `Queue`. +const queue = new Queue([27, 28, 29]); + +// Enqueue a number +queue.enqueue(30); +console.log(queue.state); // Output: [27, 28, 29, 30] + +// Dequeue a number +const dequeued = queue.dequeue(); +console.log(dequeued); // Output: 27 +console.log(queue.state); // Output: [28, 29, 30] + +// Peek at the front of the queue +const front = queue.peek(); +console.log(front); // Output: 28 + +// Check if the queue is empty +console.log(queue.isEmpty()); // Output: false + +// Dequeue all items +queue.dequeue(); +queue.dequeue(); +queue.dequeue(); +console.log(queue.isEmpty()); // Output: true ``` ### `BooleanArrayState` @@ -256,26 +324,31 @@ activeEnum.is(Active.No) ### `BooleanActionObjectState` ```typescript +import { BooleanActionObjectState } from '@typescript-package/state'; ``` ### `BooleanObjectState` ```typescript +import { BooleanObjectState } from '@typescript-package/state'; ``` ### `NamedObjectState` ```typescript +import { NamedObjectState } from '@typescript-package/state'; ``` ### `ObjectState` ```typescript +import { ObjectState } from '@typescript-package/state'; ``` ### `ImmutableState` ```typescript +import { ImmutableState } from '@typescript-package/state'; ``` ### `NullState` @@ -328,6 +401,7 @@ numberedState.reset(); ### `State` ```typescript +import { State } from '@typescript-package/state'; ``` ## Immutability From 2c958c21cf2576a15c5cfdd9e8e4cd81b53394cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 29 Dec 2024 10:35:58 +0000 Subject: [PATCH 83/91] test: update. --- src/test/boolean-action-object-state.spec.ts | 53 +++++++++++--------- src/test/boolean-object-state.spec.ts | 20 ++++++++ src/test/experimentals.spec.ts | 16 ++++++ src/test/named-object-state.spec.ts | 12 +++++ src/test/object-state.spec.ts | 22 ++++++++ src/test/selectable-group.spec.ts | 36 +++++++++++++ src/test/selectable.spec.ts | 48 ++++++++++++++++++ 7 files changed, 184 insertions(+), 23 deletions(-) create mode 100644 src/test/boolean-object-state.spec.ts create mode 100644 src/test/experimentals.spec.ts create mode 100644 src/test/named-object-state.spec.ts create mode 100644 src/test/object-state.spec.ts create mode 100644 src/test/selectable-group.spec.ts create mode 100644 src/test/selectable.spec.ts diff --git a/src/test/boolean-action-object-state.spec.ts b/src/test/boolean-action-object-state.spec.ts index 6f7c74e..67417c9 100644 --- a/src/test/boolean-action-object-state.spec.ts +++ b/src/test/boolean-action-object-state.spec.ts @@ -1,12 +1,34 @@ import { BooleanActionObjectState } from "../lib/object"; -export class Connection extends BooleanActionObjectState {} - -const connection1 = new Connection( - ['connected'], [ - [['connect', 'disconnect'], ['connected']] - ]); - +export class Connection extends BooleanActionObjectState { + /** + * Checks whether connection is connected. + * @returns {boolean} + */ + public isConnected() { + return this.is("connected" as any, true); + } +} + +let connection1 = new Connection(['connected'], ['connect', 'disconnect']); + +describe(`BooleanActionObjectState`, () => { + beforeEach(() => { + connection1 = new Connection(['connected'], ['connect', 'disconnect']); + }); + + it(`dispatch('connect')`, () => { + connection1.dispatch('connect'); + expect(connection1.state.connected).toBeTrue(); + expect(connection1.isConnected()).toBeTrue(); + }); + + it(`dispatch('disconnect')`, () => { + connection1.dispatch('connect').dispatch('disconnect'); + expect(connection1.state.connected).toBeFalse(); + expect(connection1.isConnected()).toBeFalse(); + }); +}); console.group(`BooleanActionObjectState`); @@ -16,9 +38,7 @@ console.log(`connection1`, connection1); const connection2 = new Connection( - ['connected', 'disconnected'], [ - [['connect', 'disconnect'], ['connected', 'disconnected']] - ]); + ['connected', 'disconnected'], ['connect', 'disconnect']); connection2.dispatch('connect'); @@ -30,16 +50,3 @@ console.log(`connection disconnected`, connection2.get('connected')); console.groupEnd(); - - - - -// const selectable = new BooleanActionObjectState( -// ['selected', 'deselected', 'unselected'], [ -// [['select', 'deselect'], ['selected', 'deselected', 'unselected']] -// ]); - -// selectable.dispatch('deselect'); - -// console.log(`selectable`, selectable); - diff --git a/src/test/boolean-object-state.spec.ts b/src/test/boolean-object-state.spec.ts new file mode 100644 index 0000000..7d50c81 --- /dev/null +++ b/src/test/boolean-object-state.spec.ts @@ -0,0 +1,20 @@ +import { BooleanObjectState } from "../lib/object/boolean-object-state.abstract"; + +export class Options extends BooleanObjectState { + constructor(names: Names[]) { + super(names); + } +} + +const options = new Options(['option1', 'option2', 'option3', 'option4']); + +options.update({ 'option1': false }); +console.log(`options.state.option1: `, options.state.option1); + +console.log(`options.state: `, options.state); +options.toggle(); +console.log(`options.state: `, options.state); + +// const booleanStates = new Options(['option1', 'option2', 'option3', 'option4']); + + diff --git a/src/test/experimentals.spec.ts b/src/test/experimentals.spec.ts new file mode 100644 index 0000000..084b4b9 --- /dev/null +++ b/src/test/experimentals.spec.ts @@ -0,0 +1,16 @@ +import { Ability, Boolean as Checked, Boolean as Disabled } from "../lib"; + +export class Checkbox extends Ability { + private checked = new Checked(); + + constructor(checked: boolean, enabled: boolean = true) { + super(enabled); + + checked && this.checked.true(); + } +} + + +const checkbox = new Checkbox(false); + +console.log(`Checkbox`, checkbox.disable()); diff --git a/src/test/named-object-state.spec.ts b/src/test/named-object-state.spec.ts new file mode 100644 index 0000000..28e63b4 --- /dev/null +++ b/src/test/named-object-state.spec.ts @@ -0,0 +1,12 @@ +import { NamedObjectState as ANamedObjectState } from "../lib/object"; + +export class NamedObjectState< + Type = any, + Names extends PropertyKey = PropertyKey, +> extends ANamedObjectState {} + +const namedObjectState = new NamedObjectState(['a', 'b', 'c']); + +console.group(`NamedObjectState`); +console.log(`namedObjectState.pick('a')`, namedObjectState.pick('a')); +console.groupEnd(); diff --git a/src/test/object-state.spec.ts b/src/test/object-state.spec.ts new file mode 100644 index 0000000..fc8ae58 --- /dev/null +++ b/src/test/object-state.spec.ts @@ -0,0 +1,22 @@ +import { ObjectState as AbstractObjectState } from "../lib/object/object-state.abstract"; + +export interface UserInterface { + id: number, + firstName: string; + surname: string; +} + +export class User extends AbstractObjectState {} + +const user = new User({ + id: 27, + firstName: 'Firstname', + surname: 'Surname' +}); + +user.update({'surname': 'test'}); +// user.state.firstName = 'a'; + +console.log(user); + +export class FormState extends AbstractObjectState {} diff --git a/src/test/selectable-group.spec.ts b/src/test/selectable-group.spec.ts new file mode 100644 index 0000000..0642944 --- /dev/null +++ b/src/test/selectable-group.spec.ts @@ -0,0 +1,36 @@ +import { Selectable } from "../lib/selectable"; +import { SelectableGroup } from "../lib/selectable/selectable-group.abstract"; + + +// new SelectableGroup(); + +// Initialize individual Selectable elements +export class Checkbox extends Selectable { + public check() { + super.select(); + } + + public uncheck() { + super.select(); + } +} + +export class Checkboxes extends SelectableGroup { + constructor(selectable: Selectable[], enabled = true) { + super(selectable, enabled); + } + + // You can add additional functionality if needed, for example: + public countSelected(): number { + return this.selectable.filter(selectable => selectable.isSelected()).length; + } +} + +const item1 = new Checkbox(); +const item2 = new Checkbox(); +const item3 = new Checkbox(); + +// Create a ConcreteSelectableGroup with the created Selectable items +const group = new Checkboxes([item1, item2, item3]); + +console.log(`group`, group); diff --git a/src/test/selectable.spec.ts b/src/test/selectable.spec.ts new file mode 100644 index 0000000..7e2d6d8 --- /dev/null +++ b/src/test/selectable.spec.ts @@ -0,0 +1,48 @@ +import { Selectable } from '../lib/selectable/selectable.abstract'; + +export class Checkbox extends Selectable {} + +let checkbox = new Checkbox(true); + +describe(`Selectable`, () => { + beforeEach(() => { + checkbox = new Checkbox(true); + }); + + it(`enable()`, () => { + expect(checkbox.isDisabled()).toBeFalse(); + checkbox.enable(); + expect(checkbox.isDisabled()).toBeFalse(); + expect(checkbox.isEnabled()).toBeTrue(); + }); + + it(`disable()`, () => { + checkbox.disable() + expect(checkbox.isDisabled()).toBeTrue(); + expect(checkbox.isEnabled()).toBeFalse(); + }); + + it(`isSelected()`, () => { + expect(checkbox.isSelected()).toBeTrue(); + }); + + it(`deselect)`, () => { + checkbox.deselect(); + expect(checkbox.isSelected()).toBeFalse(); + }); + + it(`select()`, () => { + checkbox.deselect(); + expect(checkbox.isSelected()).toBeFalse(); + checkbox.select(); + expect(checkbox.isSelected()).toBeTrue(); + }); + + it(`toggle()`, () => { + expect(checkbox.isSelected()).toBeTrue(); + checkbox.toggle(); + expect(checkbox.isSelected()).toBeFalse(); + checkbox.toggle(); + expect(checkbox.isSelected()).toBeTrue(); + }); +}); From 2c61eaaa19fdde798d0e3f62260dd81cf41c5999 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 29 Dec 2024 10:36:29 +0000 Subject: [PATCH 84/91] refactor(BooleanActionObjectState): update the `dispatch()` method . --- .../boolean-action-object-state.abstract.ts | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/lib/object/boolean-action-object-state.abstract.ts b/src/lib/object/boolean-action-object-state.abstract.ts index 1ad9421..7cea8a6 100644 --- a/src/lib/object/boolean-action-object-state.abstract.ts +++ b/src/lib/object/boolean-action-object-state.abstract.ts @@ -35,21 +35,22 @@ export abstract class BooleanActionObjectState< } /** - * @description Dispatch the `action` to set the first value in + * @description Dispatches the action where first action sets the first state to `true`. * @public - * @template {Actions} Action - * @param {Action} action + * @template {Actions} Action + * @param {Action} action The action name to dispatch. + * @returns {this} */ - public dispatch(action: Action) { - for (const [actions, names] of this.#actions) { - if (actions.includes(action)) { - if (actions.indexOf(action) === 0) { - this.true(super.names[0]).false(...super.names.slice(1)); - } else { - this.false(super.names[0]).true(...super.names.slice(1)); - } - break; - } + public dispatch(action: Action): this { + const [firstValue] = [...this.#actions]; + const restNames = super.names.slice(1); + if (firstValue === action) { + this.true(super.names[0]); + restNames.length > 0 && this.false(...restNames); + } else { + this.false(super.names[0]); + restNames.length > 0 && this.true(...restNames); } + return this; } } From 8536835ccc0dd9651992751ef676cef276862763 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 29 Dec 2024 10:36:46 +0000 Subject: [PATCH 85/91] chore: update public api. --- src/lib/index.ts | 22 +++++++++++++--------- src/public-api.ts | 19 +++++++++++++++++-- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/src/lib/index.ts b/src/lib/index.ts index b9ef046..f0a8ce5 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -1,8 +1,6 @@ -// Boolean state. -export { - Boolean, - BooleanState -} from './boolean'; +// Ability. +export { Ability } from './ability'; + // Array state. export { ArrayState, @@ -10,22 +8,28 @@ export { NamedArrayState, NamedBooleanArrayState } from './array'; + +// Boolean state. +export { + Boolean, + BooleanState +} from './boolean'; + // Enum state. export { Enum, EnumState } from './enum'; + // Object state. export { BooleanActionObjectState, BooleanObjectState, + NamedObjectState, ObjectState } from './object'; -// Object abstract state. + export { ImmutableState } from './immutable-state.abstract'; -// Data of type abstract state. -export { Ability } from './ability.abstract'; export { NullState } from './null-state.abstract'; export { NumberState } from './number-state.abstract'; -// Common abstract state. export { State } from './state.abstract'; \ No newline at end of file diff --git a/src/public-api.ts b/src/public-api.ts index 2eba120..ec1af55 100644 --- a/src/public-api.ts +++ b/src/public-api.ts @@ -2,11 +2,26 @@ * Public API Surface of state */ export { + Ability, + + ArrayState, + BooleanArrayState, + NamedArrayState, + NamedBooleanArrayState, + + Boolean, BooleanState, + + Enum, EnumState, + + BooleanActionObjectState, + BooleanObjectState, + NamedObjectState, + ObjectState, + + ImmutableState, NullState, NumberState, - ImmutableState, State } from './lib'; - \ No newline at end of file From 6b43ca8e730b70cdc036ac91aaaf17c14ab93fae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 29 Dec 2024 10:37:03 +0000 Subject: [PATCH 86/91] docs(README.md): update. --- README.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/README.md b/README.md index d1b2db0..ce17f2e 100644 --- a/README.md +++ b/README.md @@ -145,6 +145,8 @@ numbers.reset(); console.log(numbers.state); // Output: [27, 28, 29] ``` +A simple queue implementation. + ```typescript import { ArrayState } from '@typescript-package/state'; @@ -325,6 +327,31 @@ activeEnum.is(Active.No) ```typescript import { BooleanActionObjectState } from '@typescript-package/state'; + +// Extend the BooleanActionObjectState class for a specific type +export class Connection extends BooleanActionObjectState { + /** + * Checks whether connection is connected. + * @returns {boolean} + */ + public isConnected() { + return this.is("connected" as any, true); + } +} +// Initialize the `Connection` with state `connected` and actions `connect` and `disconnect`. +const connection = new Connection(['connected'], ['connect', 'disconnect']); + +// Dispatches the `connect` action. +connection.dispatch('connect'); +console.log(connection.isConnected()); // Output: true + +// Dispatches the `disconnect` action. +connection.dispatch('disconnect'); +console.log(connection.isConnected()); // Output: false + +// Dispatches the `connect` action. +connection.dispatch('connect'); +console.log(connection.isConnected()); // Output: true ``` ### `BooleanObjectState` From 7d8475774157c0dd3b434d6e14378d509fc66625 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 29 Dec 2024 10:46:52 +0000 Subject: [PATCH 87/91] docs(README.md): update. --- README.md | 91 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 46 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index ce17f2e..7c04f3f 100644 --- a/README.md +++ b/README.md @@ -26,16 +26,16 @@ Simple state management for TypeScript. * [`ArrayState`](#arraystate) * [`BooleanArrayState`](#booleanarraystate) * [`NamedArrayState`](#namedarraystate) - * [`NamedBooleanArrayState`](#namedbooleanarraystate) - * [`Boolean`](#boolean) + * `NamedBooleanArrayState` + * `Boolean` * [`BooleanState`](#booleanstate) - * [`Enum`](#enum) + * `Enum` * [`EnumState`](#enumstate) * [`BooleanActionObjectState`](#booleanactionobjectstate) - * [`BooleanObjectState`](#booleanobjectstate) - * [`NamedObjectState`](#namedobjectstate) - * [`ObjectState`](#objectstate) - * [`ImmutableState`](#immutablestate) + * `BooleanObjectState` + * `NamedObjectState` + * `ObjectState` + * `ImmutableState` * [`NullState`](#nullstate) * [`NumberState`](#numberstate) * [`State`](#state) @@ -247,18 +247,49 @@ console.log(booleanArrayState.state); // Output: [true, true, true, true] ```typescript import { NamedArrayState } from '@typescript-package/state'; -``` -### `NamedBooleanArrayState` +// Extend the NamedArrayState class for a specific type +export class AppConfiguration extends NamedArrayState<'theme' | 'language' | 'notifications', string | boolean> { + constructor() { + super( + ['theme', 'language', 'notifications'], // Names of the configuration settings + ['dark', 'en', true] // Default values + ); + } -```typescript -import { NamedBooleanArrayState } from '@typescript-package/state'; -``` + /** + * Updates the value of a specific configuration by name. + * @param {string} name - The name of the configuration to update. + * @param {string | boolean} value - The new value to set. + */ + public updateConfiguration(name: 'theme' | 'language' | 'notifications', value: string | boolean) { + this.update(this.indexOf(name), value); + } +} + +// Initialize. +const config = new AppConfiguration(); -### `Boolean` +// View the current state as an object +console.log(config.toObject()); // Output: { theme: 'dark', language: 'en', notifications: true } -```typescript -import { Boolean } from '@typescript-package/state'; +// Get the value of a specific setting +console.log(config.get('theme')); // Output: 'dark' + +// Update a specific configuration setting +config.updateConfiguration('theme', 'light'); +console.log(config.get('theme')); // Output: 'light' + +// Selecting multiple configuration options +const selectedValues = config.select('theme', 'language'); +console.log(selectedValues); // Output: ['light', 'en'] + +// Retrieve state with names as tuples +console.log(config.stateWithNames); // Output: [['theme', 'light'], ['language', 'en'], ['notifications', true]] + +// Reset the configuration state to its initial value +config.reset(); +console.log(config.toObject()); // Output: { theme: 'dark', language: 'en', notifications: true } ``` ### `BooleanState` @@ -292,12 +323,6 @@ const activeState = new ActiveState(); activeState.deactivate(); ``` -### `Enum` - -```typescript -import { Enum } from '@typescript-package/state'; -``` - ### `EnumState` ```typescript @@ -354,30 +379,6 @@ connection.dispatch('connect'); console.log(connection.isConnected()); // Output: true ``` -### `BooleanObjectState` - -```typescript -import { BooleanObjectState } from '@typescript-package/state'; -``` - -### `NamedObjectState` - -```typescript -import { NamedObjectState } from '@typescript-package/state'; -``` - -### `ObjectState` - -```typescript -import { ObjectState } from '@typescript-package/state'; -``` - -### `ImmutableState` - -```typescript -import { ImmutableState } from '@typescript-package/state'; -``` - ### `NullState` ```typescript From 40e99530ddd9bc0daeb8bfb1115c379af3556916 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 29 Dec 2024 10:49:46 +0000 Subject: [PATCH 88/91] test: update. --- src/test/experimentals.spec.ts | 50 +++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/src/test/experimentals.spec.ts b/src/test/experimentals.spec.ts index 084b4b9..6814cff 100644 --- a/src/test/experimentals.spec.ts +++ b/src/test/experimentals.spec.ts @@ -1,4 +1,4 @@ -import { Ability, Boolean as Checked, Boolean as Disabled } from "../lib"; +import { Ability, Boolean as Checked, Boolean as Disabled, NamedArrayState } from "../lib"; export class Checkbox extends Ability { private checked = new Checked(); @@ -14,3 +14,51 @@ export class Checkbox extends Ability { const checkbox = new Checkbox(false); console.log(`Checkbox`, checkbox.disable()); + + +// NamedArrayState + +class AppConfiguration extends NamedArrayState<'theme' | 'language' | 'notifications', string | boolean> { + constructor() { + super( + ['theme', 'language', 'notifications'], // Names of the configuration settings + ['dark', 'en', true] // Default values + ); + } + + /** + * Updates the value of a specific configuration by name. + * @param {string} name - The name of the configuration to update. + * @param {string | boolean} value - The new value to set. + */ + public updateConfiguration(name: 'theme' | 'language' | 'notifications', value: string | boolean) { + this.update(this.indexOf(name), value); + } +} + +const config = new AppConfiguration(); + +console.group(`NamedArrayState`); + +// View the current state as an object +console.log(config.toObject()); // Output: { theme: 'dark', language: 'en', notifications: true } + +// Get the value of a specific setting +console.log(config.get('theme')); // Output: 'dark' + +// Update a specific configuration setting +config.updateConfiguration('theme', 'light'); +console.log(config.get('theme')); // Output: 'light' + +// Selecting multiple configuration options +const selectedValues = config.select('theme', 'language'); +console.log(selectedValues); // Output: ['light', 'en'] + +// Retrieve state with names as tuples +console.log(config.stateWithNames); // Output: [['theme', 'light'], ['language', 'en'], ['notifications', true]] + +// Reset the configuration state to its initial values +config.reset(); +console.log(config.toObject()); // Output: { theme: 'dark', language: 'en', notifications: true } + +console.groupEnd(); From 7ee54d4c76c049ac824ad9327033b7e6d02e5ffc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 29 Dec 2024 10:49:52 +0000 Subject: [PATCH 89/91] docs(README.md): update. --- README.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/README.md b/README.md index 7c04f3f..28e4d00 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Simple state management for TypeScript. * `ImmutableState` * [`NullState`](#nullstate) * [`NumberState`](#numberstate) - * [`State`](#state) + * `State` * [Immutability](#immutability) * [Sealed](#sealed) * [Frozen](#frozen) @@ -426,12 +426,6 @@ numberedState.increment(5); numberedState.reset(); ``` -### `State` - -```typescript -import { State } from '@typescript-package/state'; -``` - ## Immutability ### Sealed From 3e38f35f21b58d3436178f71cc26f83ca8352354 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 29 Dec 2024 10:55:20 +0000 Subject: [PATCH 90/91] 2.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b3e452a..efea00e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-package/state", - "version": "1.0.0", + "version": "2.0.0", "author": "wwwdev.io ", "description": "State management for TypeScript.", "license": "MIT", From 8721fa5dd00b2abf5e39a806fbd360a5c8b728e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Acibor=20Rudnicki?= Date: Sun, 29 Dec 2024 11:26:09 +0000 Subject: [PATCH 91/91] docs(README.md): update. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 28e4d00..24e22d7 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ ## typescript-package/state -Simple state management for TypeScript. +Simple state management for different types in TypeScript. [![npm version][typescript-package-npm-badge-svg]][typescript-package-npm-badge]