@stimulus-library/mixins 1.0.0-alpha.7 → 1.0.1

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.
@@ -12,9 +12,10 @@ export interface LocalStorageProxy<T> {
12
12
  clear(): void;
13
13
  isEmpty(): boolean;
14
14
  }
15
- export declare const StorageSerializers: Record<'boolean' | 'object' | 'number' | 'any' | 'string' | 'map' | 'set', Serializer<any>> & {
15
+ export declare const StorageSerializers: Record<"boolean" | "object" | "number" | "any" | "string" | "map" | "set", Serializer<any>> & {
16
16
  [idx: string]: Serializer<any>;
17
17
  };
18
- export declare function useLocalStorage<T>(controller: Controller, key: string, defaultValue: T, opts?: {
19
- writeDefaults: boolean;
18
+ export declare function useLocalStorage<T>(controller: Controller, key: string, defaultValue?: any, opts?: {
19
+ onChange?: ((newValue: any, oldValue: any) => void) | null;
20
+ writeDefaults?: boolean;
20
21
  }): LocalStorageProxy<T>;
@@ -1,39 +1,48 @@
1
1
  import { reactive } from "@stimulus-library/utilities";
2
+ import { useEventListener } from "./use_event_listener";
2
3
  export const StorageSerializers = {
3
4
  boolean: {
4
- deserialize: (v) => v === 'true',
5
+ deserialize: (v) => v === "true",
5
6
  serialize: (v) => String(v),
6
- isEmpty: (v) => v === '' || v === null,
7
+ isEmpty: (v) => v === "" || v === null,
7
8
  },
8
9
  object: {
9
10
  deserialize: (v) => JSON.parse(v),
10
- serialize: (v) => JSON.stringify(v),
11
+ serialize: (v) => {
12
+ // Change events are triggered with a string value
13
+ if (typeof v === "string") {
14
+ return v;
15
+ }
16
+ else {
17
+ return JSON.stringify(v);
18
+ }
19
+ },
11
20
  isEmpty: (v) => {
12
21
  const values = Object.values(JSON.parse(v));
13
- return values.length === 0 || values.every(v => v === '' || v === null);
22
+ return values.length === 0 || values.every(v => v === "" || v === null);
14
23
  },
15
24
  },
16
25
  number: {
17
26
  deserialize: (v) => Number.parseFloat(v),
18
27
  serialize: (v) => String(v),
19
- isEmpty: (v) => v === '' || v === null,
28
+ isEmpty: (v) => v === "" || v === null,
20
29
  },
21
30
  any: {
22
31
  deserialize: (v) => v,
23
32
  serialize: (v) => String(v),
24
- isEmpty: (v) => v === '' || v === null,
33
+ isEmpty: (v) => v === "" || v === null,
25
34
  },
26
35
  string: {
27
36
  deserialize: (v) => v,
28
37
  serialize: (v) => String(v),
29
- isEmpty: (v) => v === '' || v === null,
38
+ isEmpty: (v) => v === "" || v === null,
30
39
  },
31
40
  map: {
32
41
  deserialize: (v) => new Map(JSON.parse(v)),
33
42
  serialize: (v) => JSON.stringify(Array.from(v.entries())),
34
43
  isEmpty: (v) => {
35
44
  const values = Array.from(v.values());
36
- return values.length === 0 || values.every(v => v === '' || v === null);
45
+ return values.length === 0 || values.every(v => v === "" || v === null);
37
46
  },
38
47
  },
39
48
  set: {
@@ -41,40 +50,46 @@ export const StorageSerializers = {
41
50
  serialize: (v) => JSON.stringify(Array.from(v.entries())),
42
51
  isEmpty: (v) => {
43
52
  const values = Array.from(v.values());
44
- return values.length === 0 || values.every(v => v === '' || v === null);
53
+ return values.length === 0 || values.every(v => v === "" || v === null);
45
54
  },
46
55
  },
47
56
  };
48
- export function useLocalStorage(controller, key, defaultValue, opts = { writeDefaults: true }) {
57
+ export function useLocalStorage(controller, key, defaultValue, opts) {
49
58
  let type;
50
- let { writeDefaults } = opts;
51
- if (defaultValue == null) {
52
- type = 'any';
59
+ let optsMergedWithDefaults = {
60
+ onChange: null,
61
+ writeDefaults: true,
62
+ ...opts,
63
+ };
64
+ let { writeDefaults } = optsMergedWithDefaults;
65
+ if (defaultValue === null || defaultValue === undefined) {
66
+ type = "any";
53
67
  }
54
68
  else if (defaultValue instanceof Set) {
55
- type = 'set';
69
+ type = "set";
56
70
  }
57
71
  else if (defaultValue instanceof Map) {
58
- type = 'map';
72
+ type = "map";
59
73
  }
60
- else if (typeof defaultValue === 'boolean') {
61
- type = 'boolean';
74
+ else if (typeof defaultValue === "boolean") {
75
+ type = "boolean";
62
76
  }
63
- else if (typeof defaultValue === 'string') {
64
- type = 'string';
77
+ else if (typeof defaultValue === "string") {
78
+ type = "string";
65
79
  }
66
- else if (typeof defaultValue === 'object') {
67
- type = 'object';
80
+ else if (typeof defaultValue === "object") {
81
+ type = "object";
68
82
  }
69
83
  else if (Array.isArray(defaultValue)) {
70
- type = 'object';
84
+ type = "object";
71
85
  }
72
86
  else if (!Number.isNaN(defaultValue)) {
73
- type = 'number';
87
+ type = "number";
74
88
  }
75
89
  else {
76
- type = 'any';
90
+ type = "any";
77
91
  }
92
+ let onChange = optsMergedWithDefaults.onChange?.bind(controller);
78
93
  let data = reactive({
79
94
  value: defaultValue,
80
95
  });
@@ -84,7 +99,7 @@ export function useLocalStorage(controller, key, defaultValue, opts = { writeDef
84
99
  const rawValue = storage.getItem(key);
85
100
  if (rawValue == null) {
86
101
  data.value = defaultValue;
87
- if (writeDefaults && defaultValue !== null) {
102
+ if (writeDefaults && defaultValue !== null && defaultValue !== undefined) {
88
103
  storage.setItem(key, serializer.serialize(defaultValue));
89
104
  }
90
105
  }
@@ -95,6 +110,9 @@ export function useLocalStorage(controller, key, defaultValue, opts = { writeDef
95
110
  };
96
111
  const write = (value) => {
97
112
  storage.setItem(key, serializer.serialize(value));
113
+ if (onChange) {
114
+ onChange(value, data.value);
115
+ }
98
116
  data.value = value;
99
117
  };
100
118
  const clear = () => {
@@ -107,6 +125,12 @@ export function useLocalStorage(controller, key, defaultValue, opts = { writeDef
107
125
  return serializer.isEmpty(rawValue);
108
126
  };
109
127
  read();
128
+ useEventListener(controller, window, "storage", (event) => {
129
+ if (event.key === key) {
130
+ console.log(event.newValue, event.oldValue);
131
+ write(event.newValue);
132
+ }
133
+ });
110
134
  return {
111
135
  get value() {
112
136
  return read();
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "ruby on rails",
10
10
  "ruby-on-rails"
11
11
  ],
12
- "version": "1.0.0-alpha.7",
12
+ "version": "1.0.1",
13
13
  "license": "MIT",
14
14
  "author": {
15
15
  "name": "Sub-Xaero",
@@ -35,7 +35,7 @@
35
35
  },
36
36
  "dependencies": {
37
37
  "@hotwired/stimulus": "^3.0.0",
38
- "@stimulus-library/utilities": "^1.0.0-alpha.3"
38
+ "@stimulus-library/utilities": "^1.0.1"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@types/chai": "^4.3.5",
@@ -55,5 +55,5 @@
55
55
  "typescript": "^5.1.3",
56
56
  "vite": "^4.1.1"
57
57
  },
58
- "gitHead": "0f37528aabf5fe7acc4dee070d0bf760bacc4dc1"
58
+ "gitHead": "26a7da01746a2bdf8a2a731b79d37256b789bdc0"
59
59
  }