@veams/status-quo 0.1.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/.github/workflows/pages.yml +46 -0
  2. package/.github/workflows/release.yml +33 -0
  3. package/CHANGELOG.md +30 -0
  4. package/README.md +260 -124
  5. package/assets/statusquo-logo.png +0 -0
  6. package/dist/hooks/state-subscription.d.ts +1 -2
  7. package/dist/hooks/state-subscription.js +8 -9
  8. package/dist/hooks/state-subscription.js.map +1 -1
  9. package/dist/index.d.ts +2 -2
  10. package/dist/index.js +2 -2
  11. package/dist/index.js.map +1 -1
  12. package/dist/store/__tests__/{state-handler.spec.js → observable-state-handler.spec.js} +14 -14
  13. package/dist/store/__tests__/observable-state-handler.spec.js.map +1 -0
  14. package/dist/store/__tests__/signal-state-handler.spec.js +78 -0
  15. package/dist/store/__tests__/signal-state-handler.spec.js.map +1 -0
  16. package/dist/store/base-state-handler.d.ts +30 -0
  17. package/dist/store/base-state-handler.js +84 -0
  18. package/dist/store/base-state-handler.js.map +1 -0
  19. package/dist/store/index.d.ts +3 -1
  20. package/dist/store/index.js +3 -1
  21. package/dist/store/index.js.map +1 -1
  22. package/dist/store/observable-state-handler.d.ts +26 -0
  23. package/dist/store/observable-state-handler.js +55 -0
  24. package/dist/store/observable-state-handler.js.map +1 -0
  25. package/dist/store/signal-state-handler.d.ts +25 -0
  26. package/dist/store/signal-state-handler.js +49 -0
  27. package/dist/store/signal-state-handler.js.map +1 -0
  28. package/dist/types/types.d.ts +2 -2
  29. package/package.json +22 -11
  30. package/playground/index.html +12 -0
  31. package/playground/src/App.tsx +478 -0
  32. package/playground/src/assets/philosophy-agnostic.svg +18 -0
  33. package/playground/src/assets/philosophy-separation.svg +13 -0
  34. package/playground/src/assets/philosophy-swap.svg +17 -0
  35. package/playground/src/assets/statusquo-logo.png +0 -0
  36. package/playground/src/main.tsx +19 -0
  37. package/playground/src/styles.css +411 -0
  38. package/playground/tsconfig.json +12 -0
  39. package/playground/vite.config.ts +18 -0
  40. package/src/hooks/state-subscription.tsx +21 -14
  41. package/src/index.ts +14 -2
  42. package/src/store/__tests__/{state-handler.spec.ts → observable-state-handler.spec.ts} +15 -15
  43. package/src/store/__tests__/signal-state-handler.spec.ts +97 -0
  44. package/src/store/base-state-handler.ts +119 -0
  45. package/src/store/index.ts +3 -1
  46. package/src/store/observable-state-handler.ts +87 -0
  47. package/src/store/signal-state-handler.ts +76 -0
  48. package/src/types/types.ts +2 -3
  49. package/dist/store/__tests__/state-handler.spec.js.map +0 -1
  50. package/dist/store/state-handler.d.ts +0 -36
  51. package/dist/store/state-handler.js +0 -122
  52. package/dist/store/state-handler.js.map +0 -1
  53. package/dist/types/hooks/index.d.ts +0 -2
  54. package/dist/types/hooks/state-factory.d.ts +0 -2
  55. package/dist/types/hooks/state-singleton.d.ts +0 -2
  56. package/dist/types/hooks/state-subscription.d.ts +0 -3
  57. package/dist/types/index.d.ts +0 -6
  58. package/dist/types/store/dev-tools.d.ts +0 -23
  59. package/dist/types/store/index.d.ts +0 -3
  60. package/dist/types/store/state-handler.d.ts +0 -36
  61. package/dist/types/store/state-singleton.d.ts +0 -5
  62. package/dist/types/types/types.d.ts +0 -7
  63. package/src/store/state-handler.ts +0 -181
  64. /package/dist/store/__tests__/{state-handler.spec.d.ts → observable-state-handler.spec.d.ts} +0 -0
  65. /package/dist/{types/store/__tests__/state-handler.spec.d.ts → store/__tests__/signal-state-handler.spec.d.ts} +0 -0
@@ -1,6 +1,6 @@
1
1
  import { lastValueFrom, Subject, take } from 'rxjs';
2
- import { StateHandler } from '../state-handler.js';
3
- class TestStateHandler extends StateHandler {
2
+ import { ObservableStateHandler } from '../observable-state-handler.js';
3
+ class TestObservableStateHandler extends ObservableStateHandler {
4
4
  constructor(withDevTools) {
5
5
  super({
6
6
  initialState: {
@@ -8,16 +8,15 @@ class TestStateHandler extends StateHandler {
8
8
  test2: 'testValue2',
9
9
  },
10
10
  ...(withDevTools && {
11
- devTools: {
12
- enabled: true,
13
- namespace: 'TestStateHandler',
11
+ options: {
12
+ devTools: {
13
+ enabled: true,
14
+ namespace: 'TestObservableStateHandler',
15
+ },
14
16
  },
15
17
  }),
16
18
  });
17
19
  }
18
- getObservable() {
19
- return this.getStateAsObservable();
20
- }
21
20
  getActions() {
22
21
  return {
23
22
  testAction: () => {
@@ -26,10 +25,10 @@ class TestStateHandler extends StateHandler {
26
25
  };
27
26
  }
28
27
  }
29
- describe('State Handler', () => {
28
+ describe('Observable State Handler', () => {
30
29
  let stateHandler;
31
30
  beforeEach(() => {
32
- stateHandler = new TestStateHandler();
31
+ stateHandler = new TestObservableStateHandler();
33
32
  });
34
33
  it('should provide initial state', () => {
35
34
  expect(stateHandler.getInitialState()).toStrictEqual({
@@ -49,7 +48,7 @@ describe('State Handler', () => {
49
48
  test2: 'testValue2',
50
49
  };
51
50
  stateHandler.setState(expected);
52
- const state = await lastValueFrom(stateHandler.getObservable().pipe(take(1)));
51
+ const state = await lastValueFrom(stateHandler.getStateAsObservable().pipe(take(1)));
53
52
  expect(state).toStrictEqual(expected);
54
53
  expect(stateHandler.getState()).toStrictEqual(expected);
55
54
  });
@@ -66,7 +65,7 @@ describe('State Handler', () => {
66
65
  });
67
66
  it('should only call subscriber when object state has changed', async () => {
68
67
  const spy = jest.fn();
69
- stateHandler.getObservable().subscribe(spy);
68
+ const unsubscribe = stateHandler.subscribe(spy);
70
69
  stateHandler.setState({
71
70
  test: 'test',
72
71
  });
@@ -79,7 +78,8 @@ describe('State Handler', () => {
79
78
  stateHandler.setState({
80
79
  test: 'test2',
81
80
  });
82
- expect(spy).toHaveBeenCalledTimes(3); // 1. testValue (Initial value), 2. test (first setter), 3. test2 (second setter)
81
+ unsubscribe();
82
+ expect(spy).toHaveBeenCalledTimes(2); // 1. test (first setter), 2. test2 (second setter)
83
83
  });
84
84
  });
85
- //# sourceMappingURL=state-handler.spec.js.map
85
+ //# sourceMappingURL=observable-state-handler.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observable-state-handler.spec.js","sourceRoot":"","sources":["../../../src/store/__tests__/observable-state-handler.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,78 @@
1
+ import { SignalStateHandler } from '../signal-state-handler.js';
2
+ class TestSignalStateHandler extends SignalStateHandler {
3
+ constructor(withDevTools) {
4
+ super({
5
+ initialState: {
6
+ test: 'testValue',
7
+ test2: 'testValue2',
8
+ },
9
+ ...(withDevTools && {
10
+ options: {
11
+ devTools: {
12
+ enabled: true,
13
+ namespace: 'TestSignalStateHandler',
14
+ },
15
+ },
16
+ }),
17
+ });
18
+ }
19
+ getActions() {
20
+ return {
21
+ testAction: () => {
22
+ this.setState({ test: 'newValue' });
23
+ },
24
+ };
25
+ }
26
+ }
27
+ describe('Signal State Handler', () => {
28
+ let stateHandler;
29
+ beforeEach(() => {
30
+ stateHandler = new TestSignalStateHandler();
31
+ });
32
+ it('should provide initial state', () => {
33
+ expect(stateHandler.getInitialState()).toStrictEqual({
34
+ test: 'testValue',
35
+ test2: 'testValue2',
36
+ });
37
+ });
38
+ it('should provide current state', () => {
39
+ expect(stateHandler.getState()).toStrictEqual({
40
+ test: 'testValue',
41
+ test2: 'testValue2',
42
+ });
43
+ });
44
+ it('should support state changing via setter and merge state object on first level', () => {
45
+ const expected = {
46
+ test: 'change',
47
+ test2: 'testValue2',
48
+ };
49
+ stateHandler.setState(expected);
50
+ expect(stateHandler.getState()).toStrictEqual(expected);
51
+ });
52
+ it('should support additional subscriptions handling', () => {
53
+ const spy = jest.fn();
54
+ const subscription = { unsubscribe: spy };
55
+ stateHandler.subscriptions = [subscription];
56
+ stateHandler.destroy();
57
+ expect(spy).toHaveBeenCalledTimes(1);
58
+ });
59
+ it('should only call subscriber when object state has changed', () => {
60
+ const spy = jest.fn();
61
+ const unsubscribe = stateHandler.subscribe(spy);
62
+ stateHandler.setState({
63
+ test: 'test',
64
+ });
65
+ stateHandler.setState({
66
+ test: 'test2',
67
+ });
68
+ stateHandler.setState({
69
+ test: 'test2',
70
+ });
71
+ stateHandler.setState({
72
+ test: 'test2',
73
+ });
74
+ unsubscribe();
75
+ expect(spy).toHaveBeenCalledTimes(2);
76
+ });
77
+ });
78
+ //# sourceMappingURL=signal-state-handler.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signal-state-handler.spec.js","sourceRoot":"","sources":["../../../src/store/__tests__/signal-state-handler.spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAEhE,MAAM,sBAAuB,SAAQ,kBAGpC;IACC,YAAY,YAAsB;QAChC,KAAK,CAAC;YACJ,YAAY,EAAE;gBACZ,IAAI,EAAE,WAAW;gBACjB,KAAK,EAAE,YAAY;aACpB;YACD,GAAG,CAAC,YAAY,IAAI;gBAClB,OAAO,EAAE;oBACP,QAAQ,EAAE;wBACR,OAAO,EAAE,IAAI;wBACb,SAAS,EAAE,wBAAwB;qBACpC;iBACF;aACF,CAAC;SACH,CAAC,CAAC;IACL,CAAC;IAED,UAAU;QACR,OAAO;YACL,UAAU,EAAE,GAAG,EAAE;gBACf,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;YACtC,CAAC;SACF,CAAC;IACJ,CAAC;CACF;AAED,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,IAAI,YAAoC,CAAC;IAEzC,UAAU,CAAC,GAAG,EAAE;QACd,YAAY,GAAG,IAAI,sBAAsB,EAAE,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,CAAC,YAAY,CAAC,eAAe,EAAE,CAAC,CAAC,aAAa,CAAC;YACnD,IAAI,EAAE,WAAW;YACjB,KAAK,EAAE,YAAY;SACpB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC,CAAC,aAAa,CAAC;YAC5C,IAAI,EAAE,WAAW;YACjB,KAAK,EAAE,YAAY;SACpB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gFAAgF,EAAE,GAAG,EAAE;QACxF,MAAM,QAAQ,GAAG;YACf,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,YAAY;SACpB,CAAC;QAEF,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAEhC,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;QACtB,MAAM,YAAY,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC;QAE1C,YAAY,CAAC,aAAa,GAAG,CAAC,YAAY,CAAC,CAAC;QAE5C,YAAY,CAAC,OAAO,EAAE,CAAC;QAEvB,MAAM,CAAC,GAAG,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACnE,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;QACtB,MAAM,WAAW,GAAG,YAAY,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAEhD,YAAY,CAAC,QAAQ,CAAC;YACpB,IAAI,EAAE,MAAM;SACb,CAAC,CAAC;QACH,YAAY,CAAC,QAAQ,CAAC;YACpB,IAAI,EAAE,OAAO;SACd,CAAC,CAAC;QACH,YAAY,CAAC,QAAQ,CAAC;YACpB,IAAI,EAAE,OAAO;SACd,CAAC,CAAC;QACH,YAAY,CAAC,QAAQ,CAAC;YACpB,IAAI,EAAE,OAAO;SACd,CAAC,CAAC;QAEH,WAAW,EAAE,CAAC;QAEd,MAAM,CAAC,GAAG,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,30 @@
1
+ import type { StateSubscriptionHandler } from '../types/types.js';
2
+ import type { DevTools } from './dev-tools.js';
3
+ type DevToolsOptions = {
4
+ enabled?: boolean;
5
+ namespace: string;
6
+ };
7
+ export declare abstract class BaseStateHandler<S, A> implements StateSubscriptionHandler<S, A> {
8
+ protected readonly initialState: S;
9
+ protected devTools: DevTools | null;
10
+ subscriptions: Array<{
11
+ unsubscribe: () => void;
12
+ }>;
13
+ protected constructor(initialState: S);
14
+ protected initDevTools(devToolsOptions?: DevToolsOptions): void;
15
+ getInitialState(): S;
16
+ getState(): S;
17
+ getSnapshot(): S;
18
+ setState(newState: Partial<S>, actionName?: string): void;
19
+ destroy(): void;
20
+ protected abstract getStateValue(): S;
21
+ protected abstract setStateValue(nextState: S): void;
22
+ protected bindSubscribable<T>(service: {
23
+ subscribe: (listener: (value: T) => void) => () => void;
24
+ getSnapshot?: () => T;
25
+ }, onChange: (value: T) => void): void;
26
+ abstract subscribe(listener: () => void): () => void;
27
+ abstract getActions(): A;
28
+ private handleDevToolsEvents;
29
+ }
30
+ export {};
@@ -0,0 +1,84 @@
1
+ import { withDevTools } from './dev-tools.js';
2
+ const defaultDevToolsOptions = { enabled: false, namespace: 'Store' };
3
+ const devToolsFeatures = {
4
+ pause: true,
5
+ lock: true,
6
+ persist: false,
7
+ export: true,
8
+ import: 'custom',
9
+ jump: true,
10
+ skip: true,
11
+ reorder: true,
12
+ dispatch: false,
13
+ test: false,
14
+ };
15
+ export class BaseStateHandler {
16
+ initialState;
17
+ devTools = null;
18
+ subscriptions = [];
19
+ constructor(initialState) {
20
+ this.initialState = initialState;
21
+ }
22
+ initDevTools(devToolsOptions) {
23
+ const mergedOptions = {
24
+ ...defaultDevToolsOptions,
25
+ ...devToolsOptions,
26
+ };
27
+ if (!mergedOptions.enabled) {
28
+ this.devTools = null;
29
+ return;
30
+ }
31
+ this.devTools = withDevTools(this.initialState, {
32
+ name: mergedOptions.namespace,
33
+ instanceId: mergedOptions.namespace.toLowerCase().replaceAll(' ', '-'),
34
+ actionCreators: this.getActions(),
35
+ features: devToolsFeatures,
36
+ });
37
+ this.devTools?.subscribe(this.handleDevToolsEvents);
38
+ }
39
+ getInitialState() {
40
+ return this.initialState;
41
+ }
42
+ getState() {
43
+ return this.getStateValue();
44
+ }
45
+ getSnapshot() {
46
+ return this.getState();
47
+ }
48
+ setState(newState, actionName = 'change') {
49
+ const nextState = { ...this.getState(), ...newState };
50
+ this.setStateValue(nextState);
51
+ this.devTools?.send(actionName, nextState);
52
+ }
53
+ destroy() {
54
+ this.subscriptions.forEach((subscription) => subscription.unsubscribe());
55
+ }
56
+ bindSubscribable(service, onChange) {
57
+ const unsubscribe = service.subscribe(onChange);
58
+ this.subscriptions = [...(this.subscriptions ?? []), { unsubscribe }];
59
+ if (service.getSnapshot)
60
+ onChange(service.getSnapshot());
61
+ }
62
+ handleDevToolsEvents = (message) => {
63
+ if (message.type !== 'DISPATCH') {
64
+ return;
65
+ }
66
+ switch (message.payload.type) {
67
+ case 'RESET':
68
+ this.setStateValue(this.getInitialState());
69
+ this.devTools?.init(this.getInitialState());
70
+ break;
71
+ case 'COMMIT':
72
+ this.setStateValue(this.getState());
73
+ this.devTools?.init(this.getState());
74
+ break;
75
+ case 'JUMP_TO_STATE':
76
+ case 'JUMP_TO_ACTION':
77
+ this.setStateValue(JSON.parse(message.state));
78
+ break;
79
+ default:
80
+ break;
81
+ }
82
+ };
83
+ }
84
+ //# sourceMappingURL=base-state-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-state-handler.js","sourceRoot":"","sources":["../../src/store/base-state-handler.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,5 @@
1
- export { StateHandler } from './state-handler.js';
1
+ export { BaseStateHandler } from './base-state-handler.js';
2
+ export { ObservableStateHandler } from './observable-state-handler.js';
3
+ export { SignalStateHandler } from './signal-state-handler.js';
2
4
  export type { StateSingleton } from './state-singleton.js';
3
5
  export { makeStateSingleton } from './state-singleton.js';
@@ -1,3 +1,5 @@
1
- export { StateHandler } from './state-handler.js';
1
+ export { BaseStateHandler } from './base-state-handler.js';
2
+ export { ObservableStateHandler } from './observable-state-handler.js';
3
+ export { SignalStateHandler } from './signal-state-handler.js';
2
4
  export { makeStateSingleton } from './state-singleton.js';
3
5
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/store/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/store/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAE/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,26 @@
1
+ import { BehaviorSubject } from 'rxjs';
2
+ import { BaseStateHandler } from './base-state-handler.js';
3
+ import type { Observable } from 'rxjs';
4
+ type ObservableStateHandlerProps<S> = {
5
+ initialState: S;
6
+ options?: {
7
+ devTools?: {
8
+ enabled?: boolean;
9
+ namespace: string;
10
+ };
11
+ };
12
+ };
13
+ type StateObservableOptions = {
14
+ useDistinctUntilChanged?: boolean;
15
+ };
16
+ export declare abstract class ObservableStateHandler<S, A> extends BaseStateHandler<S, A> {
17
+ private readonly state$;
18
+ protected constructor({ initialState, options }: ObservableStateHandlerProps<S>);
19
+ protected getStateValue(): S;
20
+ protected setStateValue(nextState: S): void;
21
+ getStateItemAsObservable(key: keyof S): Observable<S[keyof S]>;
22
+ getStateAsObservable(options?: StateObservableOptions): BehaviorSubject<S>;
23
+ getObservableItem(key: keyof S): Observable<S[keyof S]>;
24
+ subscribe(listener: () => void): () => void;
25
+ }
26
+ export {};
@@ -0,0 +1,55 @@
1
+ import { BehaviorSubject, distinctUntilKeyChanged, map, pipe, distinctUntilChanged } from 'rxjs';
2
+ import { BaseStateHandler } from './base-state-handler.js';
3
+ function distinctUntilChangedAsJson() {
4
+ return pipe(distinctUntilChanged((a, b) => {
5
+ return JSON.stringify(a) === JSON.stringify(b);
6
+ }));
7
+ }
8
+ const pipeMap = {
9
+ useDistinctUntilChanged: distinctUntilChangedAsJson(),
10
+ };
11
+ export class ObservableStateHandler extends BaseStateHandler {
12
+ state$;
13
+ constructor({ initialState, options }) {
14
+ super(initialState);
15
+ this.state$ = new BehaviorSubject(initialState);
16
+ this.initDevTools(options?.devTools);
17
+ }
18
+ getStateValue() {
19
+ return this.state$.getValue();
20
+ }
21
+ setStateValue(nextState) {
22
+ this.state$.next(nextState);
23
+ }
24
+ getStateItemAsObservable(key) {
25
+ return this.state$.pipe(distinctUntilKeyChanged(key), map((state) => state[key]));
26
+ }
27
+ getStateAsObservable(options = {
28
+ useDistinctUntilChanged: true,
29
+ }) {
30
+ // Unfortunately we cannot add pipe operators conditionally in an easy manner.
31
+ // That's why we use a simple object to attach operators to a new state observable via reduce().
32
+ // This way we can easily extend our default operators map.
33
+ return Object.keys(options)
34
+ .filter((optionKey) => options[optionKey] === true)
35
+ .map((enabledOptions) => pipeMap[enabledOptions])
36
+ .reduce((stateObservable$, operator) => {
37
+ return stateObservable$.pipe(operator);
38
+ }, this.state$);
39
+ }
40
+ getObservableItem(key) {
41
+ return this.getStateItemAsObservable(key);
42
+ }
43
+ subscribe(listener) {
44
+ let initialized = false;
45
+ const subscription = this.getStateAsObservable().subscribe(() => {
46
+ if (!initialized) {
47
+ initialized = true;
48
+ return;
49
+ }
50
+ listener();
51
+ });
52
+ return () => subscription.unsubscribe();
53
+ }
54
+ }
55
+ //# sourceMappingURL=observable-state-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observable-state-handler.js","sourceRoot":"","sources":["../../src/store/observable-state-handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,uBAAuB,EAAE,GAAG,EAAE,IAAI,EAAE,oBAAoB,EAAE,MAAM,MAAM,CAAC;AAEjG,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAgB3D,SAAS,0BAA0B;IACjC,OAAO,IAAI,CACT,oBAAoB,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QAC5B,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IACjD,CAAC,CAAC,CACH,CAAC;AACJ,CAAC;AAED,MAAM,OAAO,GAAG;IACd,uBAAuB,EAAE,0BAA0B,EAAE;CACtD,CAAC;AAEF,MAAM,OAAgB,sBAA6B,SAAQ,gBAAsB;IAC9D,MAAM,CAAqB;IAE5C,YAAsB,EAAE,YAAY,EAAE,OAAO,EAAkC;QAC7E,KAAK,CAAC,YAAY,CAAC,CAAC;QACpB,IAAI,CAAC,MAAM,GAAG,IAAI,eAAe,CAAI,YAAY,CAAC,CAAC;QACnD,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACvC,CAAC;IAES,aAAa;QACrB,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;IAChC,CAAC;IAES,aAAa,CAAC,SAAY;QAClC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC9B,CAAC;IAED,wBAAwB,CAAC,GAAY;QACnC,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CACrB,uBAAuB,CAAC,GAAG,CAAC,EAC5B,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAC3B,CAAC;IACJ,CAAC;IAED,oBAAoB,CAClB,UAAkC;QAChC,uBAAuB,EAAE,IAAI;KAC9B;QAED,8EAA8E;QAC9E,gGAAgG;QAChG,2DAA2D;QAC3D,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;aACxB,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,OAAO,CAAC,SAAyC,CAAC,KAAK,IAAI,CAAC;aAClF,GAAG,CAAC,CAAC,cAAc,EAAE,EAAE,CAAC,OAAO,CAAC,cAA8C,CAAC,CAAC;aAChF,MAAM,CAAC,CAAC,gBAAgB,EAAE,QAAQ,EAAE,EAAE;YACrC,OAAO,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAuB,CAAC;QAC/D,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IACpB,CAAC;IAED,iBAAiB,CAAC,GAAY;QAC5B,OAAO,IAAI,CAAC,wBAAwB,CAAC,GAAG,CAAC,CAAC;IAC5C,CAAC;IAED,SAAS,CAAC,QAAoB;QAC5B,IAAI,WAAW,GAAG,KAAK,CAAC;QACxB,MAAM,YAAY,GAAG,IAAI,CAAC,oBAAoB,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE;YAC9D,IAAI,CAAC,WAAW,EAAE,CAAC;gBACjB,WAAW,GAAG,IAAI,CAAC;gBACnB,OAAO;YACT,CAAC;YAED,QAAQ,EAAE,CAAC;QACb,CAAC,CAAC,CAAC;QACH,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,CAAC;IAC1C,CAAC;CACF"}
@@ -0,0 +1,25 @@
1
+ import { BaseStateHandler } from './base-state-handler.js';
2
+ import type { Signal } from '@preact/signals-core';
3
+ type SignalStateHandlerProps<S> = {
4
+ initialState: S;
5
+ options?: {
6
+ devTools?: {
7
+ enabled?: boolean;
8
+ namespace: string;
9
+ };
10
+ useDistinctUntilChanged?: boolean;
11
+ };
12
+ };
13
+ type Listener = () => void;
14
+ export declare abstract class SignalStateHandler<S, A> extends BaseStateHandler<S, A> {
15
+ private readonly state;
16
+ private readonly listeners;
17
+ private readonly useDistinctUntilChanged;
18
+ protected constructor({ initialState, options }: SignalStateHandlerProps<S>);
19
+ getSignal(): Signal<S>;
20
+ subscribe(listener: Listener): () => void;
21
+ protected getStateValue(): S;
22
+ protected setStateValue(nextState: S): void;
23
+ private notify;
24
+ }
25
+ export {};
@@ -0,0 +1,49 @@
1
+ import { signal } from '@preact/signals-core';
2
+ import { BaseStateHandler } from './base-state-handler.js';
3
+ const defaultOptions = {
4
+ useDistinctUntilChanged: true,
5
+ };
6
+ function isEqualAsJson(a, b) {
7
+ return JSON.stringify(a) === JSON.stringify(b);
8
+ }
9
+ export class SignalStateHandler extends BaseStateHandler {
10
+ state;
11
+ listeners = new Map();
12
+ useDistinctUntilChanged;
13
+ constructor({ initialState, options = defaultOptions }) {
14
+ super(initialState);
15
+ const mergedOptions = {
16
+ ...defaultOptions,
17
+ ...options,
18
+ };
19
+ this.state = signal(initialState);
20
+ this.useDistinctUntilChanged = mergedOptions.useDistinctUntilChanged ?? true;
21
+ this.initDevTools(options?.devTools);
22
+ }
23
+ getSignal() {
24
+ return this.state;
25
+ }
26
+ subscribe(listener) {
27
+ this.listeners.set(listener, this.state.value);
28
+ return () => {
29
+ this.listeners.delete(listener);
30
+ };
31
+ }
32
+ getStateValue() {
33
+ return this.state.value;
34
+ }
35
+ setStateValue(nextState) {
36
+ this.state.value = nextState;
37
+ this.notify(nextState);
38
+ }
39
+ notify(nextState) {
40
+ for (const [listener, lastSnapshot] of this.listeners.entries()) {
41
+ if (this.useDistinctUntilChanged && isEqualAsJson(nextState, lastSnapshot)) {
42
+ continue;
43
+ }
44
+ this.listeners.set(listener, nextState);
45
+ listener();
46
+ }
47
+ }
48
+ }
49
+ //# sourceMappingURL=signal-state-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signal-state-handler.js","sourceRoot":"","sources":["../../src/store/signal-state-handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAE9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAiB3D,MAAM,cAAc,GAAG;IACrB,uBAAuB,EAAE,IAAI;CAC9B,CAAC;AAEF,SAAS,aAAa,CAAC,CAAU,EAAE,CAAU;IAC3C,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,OAAgB,kBAAyB,SAAQ,gBAAsB;IAC1D,KAAK,CAAY;IACjB,SAAS,GAAG,IAAI,GAAG,EAAe,CAAC;IACnC,uBAAuB,CAAU;IAElD,YAAsB,EAAE,YAAY,EAAE,OAAO,GAAG,cAAc,EAA8B;QAC1F,KAAK,CAAC,YAAY,CAAC,CAAC;QACpB,MAAM,aAAa,GAAG;YACpB,GAAG,cAAc;YACjB,GAAG,OAAO;SACX,CAAC;QAEF,IAAI,CAAC,KAAK,GAAG,MAAM,CAAI,YAAY,CAAC,CAAC;QACrC,IAAI,CAAC,uBAAuB,GAAG,aAAa,CAAC,uBAAuB,IAAI,IAAI,CAAC;QAC7E,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACvC,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,SAAS,CAAC,QAAkB;QAC1B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAE/C,OAAO,GAAG,EAAE;YACV,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAClC,CAAC,CAAC;IACJ,CAAC;IAES,aAAa;QACrB,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;IAC1B,CAAC;IAES,aAAa,CAAC,SAAY;QAClC,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,SAAS,CAAC;QAC7B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACzB,CAAC;IAEO,MAAM,CAAC,SAAY;QACzB,KAAK,MAAM,CAAC,QAAQ,EAAE,YAAY,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,CAAC;YAChE,IAAI,IAAI,CAAC,uBAAuB,IAAI,aAAa,CAAC,SAAS,EAAE,YAAY,CAAC,EAAE,CAAC;gBAC3E,SAAS;YACX,CAAC;YAED,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;YACxC,QAAQ,EAAE,CAAC;QACb,CAAC;IACH,CAAC;CACF"}
@@ -1,6 +1,6 @@
1
- import type { Observable } from 'rxjs';
2
1
  export interface StateSubscriptionHandler<V, A> {
3
- getObservable: () => Observable<V>;
2
+ subscribe: (listener: () => void) => () => void;
3
+ getSnapshot: () => V;
4
4
  destroy: () => void;
5
5
  getInitialState: () => V;
6
6
  getActions: () => A;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@veams/status-quo",
3
- "version": "0.1.0",
3
+ "version": "1.1.0",
4
4
  "description": "The manager to rule states in frontend.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
@@ -40,6 +40,9 @@
40
40
  "lint": "pnpm run lint:ts",
41
41
  "lint:ts": "eslint --fix \"src/**/*.{tsx,ts}\" --config ./.eslintrc.cjs",
42
42
  "start": "npm-run-all --parallel watch:**",
43
+ "playground": "vite --config playground/vite.config.ts",
44
+ "docs:build": "vite build --config playground/vite.config.ts",
45
+ "docs:preview": "vite preview --config playground/vite.config.ts",
43
46
  "watch:bundle:ts": "npm run bundle:ts -- -w",
44
47
  "watch:generate:types": "npm run generate:types -- --watch",
45
48
  "test": "cross-env NODE_ENV=test jest --config jest.config.cjs",
@@ -47,26 +50,34 @@
47
50
  "release": "npm run build && release-it"
48
51
  },
49
52
  "peerDependencies": {
53
+ "@preact/signals-core": ">=1.0.0",
50
54
  "react": ">=18.0.0",
51
55
  "rxjs": ">=7.5.4"
52
56
  },
53
57
  "devDependencies": {
58
+ "@preact/signals-core": "^1.13.0",
59
+ "@types/prismjs": "^1.26.4",
60
+ "@types/react-dom": "^19.0.0",
54
61
  "@types/jest": "30.0.0",
55
- "@types/node": "24.0.13",
56
- "@types/react": "19.1.8",
57
- "cross-env": "7.0.3",
62
+ "@types/node": "25.2.3",
63
+ "@types/react": "19.2.14",
64
+ "@vitejs/plugin-react": "^5.0.0",
65
+ "cross-env": "10.1.0",
58
66
  "eslint": "8.55.0",
59
- "jest": "30.0.4",
60
- "jest-environment-jsdom": "30.0.4",
67
+ "jest": "30.2.0",
68
+ "jest-environment-jsdom": "30.2.0",
61
69
  "npm-run-all": "4.1.5",
62
- "prettier": "3.6.2",
63
- "react": "19.1.0",
70
+ "prettier": "3.8.1",
71
+ "prismjs": "^1.29.0",
72
+ "react": "19.2.4",
73
+ "react-dom": "19.2.4",
64
74
  "rxjs": "7.8.2",
65
75
  "tslib": "2.8.1",
66
- "typescript": "5.8.3",
76
+ "typescript": "5.9.3",
77
+ "vite": "^5.0.0",
67
78
  "@swc/jest": "0.2.39",
68
- "@swc/core": "1.12.11",
69
- "release-it": "19.0.3"
79
+ "@swc/core": "1.15.11",
80
+ "release-it": "19.2.4"
70
81
  },
71
82
  "keywords": [
72
83
  "State Management"
@@ -0,0 +1,12 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Status Quo Playground</title>
7
+ </head>
8
+ <body>
9
+ <div id="root"></div>
10
+ <script type="module" src="/src/main.tsx"></script>
11
+ </body>
12
+ </html>