@trackunit/react-components 2.5.2-alpha-3b19e5fe058.0 → 2.5.4

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.
package/index.cjs.js CHANGED
@@ -28,7 +28,6 @@ var dequal = require('dequal');
28
28
  var defaultTranslations = {
29
29
  "breadcrumb.backButton": "back",
30
30
  "breadcrumb.expandButton": "expand",
31
- "cardHeader.closeButton": "Close",
32
31
  "moreMenu.buttonLabel": "Show more"
33
32
  };
34
33
 
@@ -11948,6 +11947,19 @@ const useStorageKey = (key, userId) => {
11948
11947
  return react.useMemo(() => (userId ? `${key}-${userId}` : key), [key, userId]);
11949
11948
  };
11950
11949
 
11950
+ /**
11951
+ * Raw localStorage access, kept in one place so this file's exemption from the
11952
+ * no-direct-storage-access rule is centralised rather than repeated at each call site.
11953
+ *
11954
+ * TODO: migrate to the useLocalStorage hook — this file was exempted when the
11955
+ * no-direct-storage-access rule was introduced.
11956
+ */
11957
+ /* eslint-disable no-restricted-globals */
11958
+ const rawLocalStorage = {
11959
+ read: (key) => localStorage.getItem(key),
11960
+ write: (key, value) => localStorage.setItem(key, value),
11961
+ remove: (key) => localStorage.removeItem(key),
11962
+ };
11951
11963
  /**
11952
11964
  * Generic persistence hook that loads state from a URL slot (search param
11953
11965
  * or hash fragment, depending on `urlLocation`) with localStorage fallback,
@@ -11971,6 +11983,11 @@ const useStorageKey = (key, userId) => {
11971
11983
  * `toUrlValue` + encoding). Duplicate writes where the state has not
11972
11984
  * changed (deep equality) are skipped.
11973
11985
  *
11986
+ * `clearState` removes the entry from localStorage and from the URL slot,
11987
+ * rather than writing an empty value. Use it when the state a consumer
11988
+ * derives has become empty, so no leftover entry is stored for a value the
11989
+ * user has reset. It is idempotent — clearing an absent entry is a no-op.
11990
+ *
11974
11991
  * @param options - Configuration for the persisted state.
11975
11992
  * @param options.key - Unique identifier used for both the URL slot and the localStorage key.
11976
11993
  * @param options.validate - Called with the decoded/parsed value; must return `TState` or `undefined`.
@@ -12085,9 +12102,7 @@ const usePersistedState = ({ key, validate, serialize, toUrlValue, fromUrlValue,
12085
12102
  let storageState;
12086
12103
  if (localStorageEnabled) {
12087
12104
  try {
12088
- // TODO: migrate to useLocalStorage hook — this file was exempted when the no-direct-storage-access rule was introduced
12089
- // eslint-disable-next-line no-restricted-globals
12090
- const raw = localStorage.getItem(storageKey);
12105
+ const raw = rawLocalStorage.read(storageKey);
12091
12106
  if (raw) {
12092
12107
  const parsed = storageSerializer.deserialize(raw);
12093
12108
  storageState = validateState(parsed);
@@ -12222,8 +12237,7 @@ const usePersistedState = ({ key, validate, serialize, toUrlValue, fromUrlValue,
12222
12237
  const serialized = serializeRef.current
12223
12238
  ? serializeRef.current(migrated)
12224
12239
  : storageSerializer.serialize(migrated);
12225
- // eslint-disable-next-line no-restricted-globals
12226
- localStorage.setItem(storageKey, serialized);
12240
+ rawLocalStorage.write(storageKey, serialized);
12227
12241
  }
12228
12242
  const urlValue = toUrlValueRef.current ? toUrlValueRef.current(migrated) : migrated;
12229
12243
  const encoded = encode(urlValue);
@@ -12237,14 +12251,20 @@ const usePersistedState = ({ key, validate, serialize, toUrlValue, fromUrlValue,
12237
12251
  lastPersistedRef.current = state;
12238
12252
  if (localStorageEnabled) {
12239
12253
  const serialized = serializeRef.current ? serializeRef.current(state) : storageSerializer.serialize(state);
12240
- // eslint-disable-next-line no-restricted-globals
12241
- localStorage.setItem(storageKey, serialized);
12254
+ rawLocalStorage.write(storageKey, serialized);
12242
12255
  }
12243
12256
  const urlValue = toUrlValueRef.current ? toUrlValueRef.current(state) : state;
12244
12257
  const encoded = encode(urlValue);
12245
12258
  updateSearchParam(encoded);
12246
12259
  }, [storageKey, encode, localStorageEnabled, updateSearchParam]);
12247
- return react.useMemo(() => ({ initialState, persistState }), [initialState, persistState]);
12260
+ const clearState = react.useCallback(() => {
12261
+ lastPersistedRef.current = undefined;
12262
+ if (localStorageEnabled) {
12263
+ rawLocalStorage.remove(storageKey);
12264
+ }
12265
+ updateSearchParam(undefined);
12266
+ }, [localStorageEnabled, storageKey, updateSearchParam]);
12267
+ return react.useMemo(() => ({ initialState, persistState, clearState }), [initialState, persistState, clearState]);
12248
12268
  };
12249
12269
 
12250
12270
  const OVERSCAN = 10;
package/index.esm.js CHANGED
@@ -26,7 +26,6 @@ import { dequal } from 'dequal';
26
26
  var defaultTranslations = {
27
27
  "breadcrumb.backButton": "back",
28
28
  "breadcrumb.expandButton": "expand",
29
- "cardHeader.closeButton": "Close",
30
29
  "moreMenu.buttonLabel": "Show more"
31
30
  };
32
31
 
@@ -11946,6 +11945,19 @@ const useStorageKey = (key, userId) => {
11946
11945
  return useMemo(() => (userId ? `${key}-${userId}` : key), [key, userId]);
11947
11946
  };
11948
11947
 
11948
+ /**
11949
+ * Raw localStorage access, kept in one place so this file's exemption from the
11950
+ * no-direct-storage-access rule is centralised rather than repeated at each call site.
11951
+ *
11952
+ * TODO: migrate to the useLocalStorage hook — this file was exempted when the
11953
+ * no-direct-storage-access rule was introduced.
11954
+ */
11955
+ /* eslint-disable no-restricted-globals */
11956
+ const rawLocalStorage = {
11957
+ read: (key) => localStorage.getItem(key),
11958
+ write: (key, value) => localStorage.setItem(key, value),
11959
+ remove: (key) => localStorage.removeItem(key),
11960
+ };
11949
11961
  /**
11950
11962
  * Generic persistence hook that loads state from a URL slot (search param
11951
11963
  * or hash fragment, depending on `urlLocation`) with localStorage fallback,
@@ -11969,6 +11981,11 @@ const useStorageKey = (key, userId) => {
11969
11981
  * `toUrlValue` + encoding). Duplicate writes where the state has not
11970
11982
  * changed (deep equality) are skipped.
11971
11983
  *
11984
+ * `clearState` removes the entry from localStorage and from the URL slot,
11985
+ * rather than writing an empty value. Use it when the state a consumer
11986
+ * derives has become empty, so no leftover entry is stored for a value the
11987
+ * user has reset. It is idempotent — clearing an absent entry is a no-op.
11988
+ *
11972
11989
  * @param options - Configuration for the persisted state.
11973
11990
  * @param options.key - Unique identifier used for both the URL slot and the localStorage key.
11974
11991
  * @param options.validate - Called with the decoded/parsed value; must return `TState` or `undefined`.
@@ -12083,9 +12100,7 @@ const usePersistedState = ({ key, validate, serialize, toUrlValue, fromUrlValue,
12083
12100
  let storageState;
12084
12101
  if (localStorageEnabled) {
12085
12102
  try {
12086
- // TODO: migrate to useLocalStorage hook — this file was exempted when the no-direct-storage-access rule was introduced
12087
- // eslint-disable-next-line no-restricted-globals
12088
- const raw = localStorage.getItem(storageKey);
12103
+ const raw = rawLocalStorage.read(storageKey);
12089
12104
  if (raw) {
12090
12105
  const parsed = storageSerializer.deserialize(raw);
12091
12106
  storageState = validateState(parsed);
@@ -12220,8 +12235,7 @@ const usePersistedState = ({ key, validate, serialize, toUrlValue, fromUrlValue,
12220
12235
  const serialized = serializeRef.current
12221
12236
  ? serializeRef.current(migrated)
12222
12237
  : storageSerializer.serialize(migrated);
12223
- // eslint-disable-next-line no-restricted-globals
12224
- localStorage.setItem(storageKey, serialized);
12238
+ rawLocalStorage.write(storageKey, serialized);
12225
12239
  }
12226
12240
  const urlValue = toUrlValueRef.current ? toUrlValueRef.current(migrated) : migrated;
12227
12241
  const encoded = encode(urlValue);
@@ -12235,14 +12249,20 @@ const usePersistedState = ({ key, validate, serialize, toUrlValue, fromUrlValue,
12235
12249
  lastPersistedRef.current = state;
12236
12250
  if (localStorageEnabled) {
12237
12251
  const serialized = serializeRef.current ? serializeRef.current(state) : storageSerializer.serialize(state);
12238
- // eslint-disable-next-line no-restricted-globals
12239
- localStorage.setItem(storageKey, serialized);
12252
+ rawLocalStorage.write(storageKey, serialized);
12240
12253
  }
12241
12254
  const urlValue = toUrlValueRef.current ? toUrlValueRef.current(state) : state;
12242
12255
  const encoded = encode(urlValue);
12243
12256
  updateSearchParam(encoded);
12244
12257
  }, [storageKey, encode, localStorageEnabled, updateSearchParam]);
12245
- return useMemo(() => ({ initialState, persistState }), [initialState, persistState]);
12258
+ const clearState = useCallback(() => {
12259
+ lastPersistedRef.current = undefined;
12260
+ if (localStorageEnabled) {
12261
+ rawLocalStorage.remove(storageKey);
12262
+ }
12263
+ updateSearchParam(undefined);
12264
+ }, [localStorageEnabled, storageKey, updateSearchParam]);
12265
+ return useMemo(() => ({ initialState, persistState, clearState }), [initialState, persistState, clearState]);
12246
12266
  };
12247
12267
 
12248
12268
  const OVERSCAN = 10;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/react-components",
3
- "version": "2.5.2-alpha-3b19e5fe058.0",
3
+ "version": "2.5.4",
4
4
  "repository": "https://github.com/Trackunit/manager",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "migrations": "./migrations.json",
@@ -14,17 +14,17 @@
14
14
  "@floating-ui/react": "^0.26.25",
15
15
  "string-ts": "^2.0.0",
16
16
  "tailwind-merge": "^2.0.0",
17
- "@trackunit/ui-design-tokens": "1.14.1-alpha-3b19e5fe058.0",
18
- "@trackunit/css-class-variance-utilities": "1.14.1-alpha-3b19e5fe058.0",
19
- "@trackunit/shared-utils": "1.16.1-alpha-3b19e5fe058.0",
20
- "@trackunit/ui-icons": "1.14.1-alpha-3b19e5fe058.0",
17
+ "@trackunit/ui-design-tokens": "1.14.1",
18
+ "@trackunit/css-class-variance-utilities": "1.14.1",
19
+ "@trackunit/shared-utils": "1.16.1",
20
+ "@trackunit/ui-icons": "1.14.1",
21
21
  "es-toolkit": "^1.39.10",
22
22
  "@tanstack/react-virtual": "^3.14.3",
23
23
  "dequal": "^2.0.3",
24
24
  "fflate": "^0.8.2",
25
25
  "superjson": "^2.2.6",
26
26
  "zod": "^3.25.76",
27
- "@trackunit/i18n-library-translation": "2.3.1-alpha-3b19e5fe058.0"
27
+ "@trackunit/i18n-library-translation": "2.3.1"
28
28
  },
29
29
  "peerDependencies": {
30
30
  "react": "^19.0.0",
@@ -43,6 +43,7 @@ type UsePersistedStateOptions<TState> = {
43
43
  type UsePersistedStateReturn<TState> = {
44
44
  readonly initialState: TState | undefined;
45
45
  readonly persistState: (state: TState) => void;
46
+ readonly clearState: () => void;
46
47
  };
47
48
  /**
48
49
  * Generic persistence hook that loads state from a URL slot (search param
@@ -67,6 +68,11 @@ type UsePersistedStateReturn<TState> = {
67
68
  * `toUrlValue` + encoding). Duplicate writes where the state has not
68
69
  * changed (deep equality) are skipped.
69
70
  *
71
+ * `clearState` removes the entry from localStorage and from the URL slot,
72
+ * rather than writing an empty value. Use it when the state a consumer
73
+ * derives has become empty, so no leftover entry is stored for a value the
74
+ * user has reset. It is idempotent — clearing an absent entry is a no-op.
75
+ *
70
76
  * @param options - Configuration for the persisted state.
71
77
  * @param options.key - Unique identifier used for both the URL slot and the localStorage key.
72
78
  * @param options.validate - Called with the decoded/parsed value; must return `TState` or `undefined`.
@@ -3,7 +3,6 @@
3
3
  var translation = {
4
4
  "breadcrumb.backButton": "zurück",
5
5
  "breadcrumb.expandButton": "ausklappen",
6
- "cardHeader.closeButton": "Schließen",
7
6
  "moreMenu.buttonLabel": "Mehr anzeigen"
8
7
  };
9
8
 
@@ -1,7 +1,6 @@
1
1
  var translation = {
2
2
  "breadcrumb.backButton": "zurück",
3
3
  "breadcrumb.expandButton": "ausklappen",
4
- "cardHeader.closeButton": "Schließen",
5
4
  "moreMenu.buttonLabel": "Mehr anzeigen"
6
5
  };
7
6
 
@@ -3,7 +3,6 @@
3
3
  var translation = {
4
4
  "breadcrumb.backButton": "powrót",
5
5
  "breadcrumb.expandButton": "rozwiń",
6
- "cardHeader.closeButton": "Zamknij",
7
6
  "moreMenu.buttonLabel": "Pokaż więcej"
8
7
  };
9
8
 
@@ -1,7 +1,6 @@
1
1
  var translation = {
2
2
  "breadcrumb.backButton": "powrót",
3
3
  "breadcrumb.expandButton": "rozwiń",
4
- "cardHeader.closeButton": "Zamknij",
5
4
  "moreMenu.buttonLabel": "Pokaż więcej"
6
5
  };
7
6
 
@@ -3,7 +3,6 @@
3
3
  var translation = {
4
4
  "breadcrumb.backButton": "voltar",
5
5
  "breadcrumb.expandButton": "expandir",
6
- "cardHeader.closeButton": "Fechar",
7
6
  "moreMenu.buttonLabel": "Mostrar mais"
8
7
  };
9
8
 
@@ -1,7 +1,6 @@
1
1
  var translation = {
2
2
  "breadcrumb.backButton": "voltar",
3
3
  "breadcrumb.expandButton": "expandir",
4
- "cardHeader.closeButton": "Fechar",
5
4
  "moreMenu.buttonLabel": "Mostrar mais"
6
5
  };
7
6
 
@@ -3,7 +3,6 @@
3
3
  var translation = {
4
4
  "breadcrumb.backButton": "назад",
5
5
  "breadcrumb.expandButton": "развернуть",
6
- "cardHeader.closeButton": "Закрыть",
7
6
  "moreMenu.buttonLabel": "Показать больше"
8
7
  };
9
8
 
@@ -1,7 +1,6 @@
1
1
  var translation = {
2
2
  "breadcrumb.backButton": "назад",
3
3
  "breadcrumb.expandButton": "развернуть",
4
- "cardHeader.closeButton": "Закрыть",
5
4
  "moreMenu.buttonLabel": "Показать больше"
6
5
  };
7
6
 
@@ -3,7 +3,6 @@
3
3
  var translation = {
4
4
  "breadcrumb.backButton": "înapoi",
5
5
  "breadcrumb.expandButton": "extindere",
6
- "cardHeader.closeButton": "Închidere",
7
6
  "moreMenu.buttonLabel": "Afișare mai mult"
8
7
  };
9
8
 
@@ -1,7 +1,6 @@
1
1
  var translation = {
2
2
  "breadcrumb.backButton": "înapoi",
3
3
  "breadcrumb.expandButton": "extindere",
4
- "cardHeader.closeButton": "Închidere",
5
4
  "moreMenu.buttonLabel": "Afișare mai mult"
6
5
  };
7
6
 
@@ -3,7 +3,6 @@
3
3
  var translation = {
4
4
  "breadcrumb.backButton": "atrás",
5
5
  "breadcrumb.expandButton": "expandir",
6
- "cardHeader.closeButton": "Cerrar",
7
6
  "moreMenu.buttonLabel": "Mostrar más"
8
7
  };
9
8
 
@@ -1,7 +1,6 @@
1
1
  var translation = {
2
2
  "breadcrumb.backButton": "atrás",
3
3
  "breadcrumb.expandButton": "expandir",
4
- "cardHeader.closeButton": "Cerrar",
5
4
  "moreMenu.buttonLabel": "Mostrar más"
6
5
  };
7
6
 
@@ -3,7 +3,6 @@
3
3
  var translation = {
4
4
  "breadcrumb.backButton": "tillbaka",
5
5
  "breadcrumb.expandButton": "expandera",
6
- "cardHeader.closeButton": "Stäng",
7
6
  "moreMenu.buttonLabel": "Visa mer"
8
7
  };
9
8
 
@@ -1,7 +1,6 @@
1
1
  var translation = {
2
2
  "breadcrumb.backButton": "tillbaka",
3
3
  "breadcrumb.expandButton": "expandera",
4
- "cardHeader.closeButton": "Stäng",
5
4
  "moreMenu.buttonLabel": "Visa mer"
6
5
  };
7
6
 
@@ -3,7 +3,6 @@
3
3
  var translation = {
4
4
  "breadcrumb.backButton": "戻る",
5
5
  "breadcrumb.expandButton": "展開",
6
- "cardHeader.closeButton": "閉じる",
7
6
  "moreMenu.buttonLabel": "さらに表示"
8
7
  };
9
8
 
@@ -1,7 +1,6 @@
1
1
  var translation = {
2
2
  "breadcrumb.backButton": "戻る",
3
3
  "breadcrumb.expandButton": "展開",
4
- "cardHeader.closeButton": "閉じる",
5
4
  "moreMenu.buttonLabel": "さらに表示"
6
5
  };
7
6
 
@@ -3,7 +3,6 @@
3
3
  var translation = {
4
4
  "breadcrumb.backButton": "ย้อนกลับ",
5
5
  "breadcrumb.expandButton": "ขยาย",
6
- "cardHeader.closeButton": "ปิด",
7
6
  "moreMenu.buttonLabel": "แสดงเพิ่มเติม"
8
7
  };
9
8
 
@@ -1,7 +1,6 @@
1
1
  var translation = {
2
2
  "breadcrumb.backButton": "ย้อนกลับ",
3
3
  "breadcrumb.expandButton": "ขยาย",
4
- "cardHeader.closeButton": "ปิด",
5
4
  "moreMenu.buttonLabel": "แสดงเพิ่มเติม"
6
5
  };
7
6
 
@@ -3,7 +3,6 @@
3
3
  var translation = {
4
4
  "breadcrumb.backButton": "tilbage",
5
5
  "breadcrumb.expandButton": "udvid",
6
- "cardHeader.closeButton": "Luk",
7
6
  "moreMenu.buttonLabel": "Vis mere"
8
7
  };
9
8
 
@@ -1,7 +1,6 @@
1
1
  var translation = {
2
2
  "breadcrumb.backButton": "tilbage",
3
3
  "breadcrumb.expandButton": "udvid",
4
- "cardHeader.closeButton": "Luk",
5
4
  "moreMenu.buttonLabel": "Vis mere"
6
5
  };
7
6
 
@@ -3,7 +3,6 @@
3
3
  var translation = {
4
4
  "breadcrumb.backButton": "zpět",
5
5
  "breadcrumb.expandButton": "rozbalit",
6
- "cardHeader.closeButton": "Zavřít",
7
6
  "moreMenu.buttonLabel": "Zobrazit více"
8
7
  };
9
8
 
@@ -1,7 +1,6 @@
1
1
  var translation = {
2
2
  "breadcrumb.backButton": "zpět",
3
3
  "breadcrumb.expandButton": "rozbalit",
4
- "cardHeader.closeButton": "Zavřít",
5
4
  "moreMenu.buttonLabel": "Zobrazit více"
6
5
  };
7
6
 
@@ -3,7 +3,6 @@
3
3
  var translation = {
4
4
  "breadcrumb.backButton": "terug",
5
5
  "breadcrumb.expandButton": "uitklappen",
6
- "cardHeader.closeButton": "Afsluiten",
7
6
  "moreMenu.buttonLabel": "Meer weergeven"
8
7
  };
9
8
 
@@ -1,7 +1,6 @@
1
1
  var translation = {
2
2
  "breadcrumb.backButton": "terug",
3
3
  "breadcrumb.expandButton": "uitklappen",
4
- "cardHeader.closeButton": "Afsluiten",
5
4
  "moreMenu.buttonLabel": "Meer weergeven"
6
5
  };
7
6
 
@@ -3,7 +3,6 @@
3
3
  var translation = {
4
4
  "breadcrumb.backButton": "retour",
5
5
  "breadcrumb.expandButton": "développer",
6
- "cardHeader.closeButton": "Fermer",
7
6
  "moreMenu.buttonLabel": "Afficher plus"
8
7
  };
9
8
 
@@ -1,7 +1,6 @@
1
1
  var translation = {
2
2
  "breadcrumb.backButton": "retour",
3
3
  "breadcrumb.expandButton": "développer",
4
- "cardHeader.closeButton": "Fermer",
5
4
  "moreMenu.buttonLabel": "Afficher plus"
6
5
  };
7
6
 
@@ -3,7 +3,6 @@
3
3
  var translation = {
4
4
  "breadcrumb.backButton": "takaisin",
5
5
  "breadcrumb.expandButton": "laajenna",
6
- "cardHeader.closeButton": "Sulje",
7
6
  "moreMenu.buttonLabel": "Näytä lisää"
8
7
  };
9
8
 
@@ -1,7 +1,6 @@
1
1
  var translation = {
2
2
  "breadcrumb.backButton": "takaisin",
3
3
  "breadcrumb.expandButton": "laajenna",
4
- "cardHeader.closeButton": "Sulje",
5
4
  "moreMenu.buttonLabel": "Näytä lisää"
6
5
  };
7
6
 
@@ -3,7 +3,6 @@
3
3
  var translation = {
4
4
  "breadcrumb.backButton": "vissza",
5
5
  "breadcrumb.expandButton": "kibontás",
6
- "cardHeader.closeButton": "Bezárás",
7
6
  "moreMenu.buttonLabel": "Több megjelenítése"
8
7
  };
9
8
 
@@ -1,7 +1,6 @@
1
1
  var translation = {
2
2
  "breadcrumb.backButton": "vissza",
3
3
  "breadcrumb.expandButton": "kibontás",
4
- "cardHeader.closeButton": "Bezárás",
5
4
  "moreMenu.buttonLabel": "Több megjelenítése"
6
5
  };
7
6
 
@@ -3,7 +3,6 @@
3
3
  var translation = {
4
4
  "breadcrumb.backButton": "indietro",
5
5
  "breadcrumb.expandButton": "espandi",
6
- "cardHeader.closeButton": "Chiudi",
7
6
  "moreMenu.buttonLabel": "Mostra di più"
8
7
  };
9
8
 
@@ -1,7 +1,6 @@
1
1
  var translation = {
2
2
  "breadcrumb.backButton": "indietro",
3
3
  "breadcrumb.expandButton": "espandi",
4
- "cardHeader.closeButton": "Chiudi",
5
4
  "moreMenu.buttonLabel": "Mostra di più"
6
5
  };
7
6
 
@@ -3,7 +3,6 @@
3
3
  var translation = {
4
4
  "breadcrumb.backButton": "tilbake",
5
5
  "breadcrumb.expandButton": "utvid",
6
- "cardHeader.closeButton": "Lukk",
7
6
  "moreMenu.buttonLabel": "Vis mer"
8
7
  };
9
8
 
@@ -1,7 +1,6 @@
1
1
  var translation = {
2
2
  "breadcrumb.backButton": "tilbake",
3
3
  "breadcrumb.expandButton": "utvid",
4
- "cardHeader.closeButton": "Lukk",
5
4
  "moreMenu.buttonLabel": "Vis mer"
6
5
  };
7
6