qstd 0.2.4 → 0.2.6

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/CHANGELOG.md CHANGED
@@ -7,6 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.2.6] - 2025-11-25
11
+
12
+ ### Fixed
13
+
14
+ - Improved `useTheme` hook reliability with refs to prevent stale closures
15
+ - Added `storeRef` to always access current state
16
+ - Added `isInternalUpdateRef` to distinguish internal vs external updates
17
+ - Fixed localStorage parsing to use correct `parsed.value` property
18
+ - Prevents duplicate state updates from custom events
19
+
20
+ ## [0.2.5] - 2025-11-25
21
+
22
+ ### Fixed
23
+
24
+ - Fixed `useTheme` hook toggle function not updating `data-theme` attribute
25
+ - Moved localStorage save logic to effect to avoid race condition with event listeners
26
+ - State updates now properly trigger theme changes on HTML element
27
+
10
28
  ## [0.2.4] - 2025-11-24
11
29
 
12
30
  ### Changed
@@ -3563,7 +3563,7 @@ var getInitialStore = () => {
3563
3563
  if (stored) {
3564
3564
  const parsed = JSON.parse(stored);
3565
3565
  return {
3566
- value: parsed.theme ?? getInitialTheme(),
3566
+ value: parsed.value ?? getInitialTheme(),
3567
3567
  isManual: parsed.isManual ?? false
3568
3568
  };
3569
3569
  }
@@ -3588,6 +3588,11 @@ var saveStore = (store) => {
3588
3588
  // src/react/use-theme/index.ts
3589
3589
  function useTheme() {
3590
3590
  const [store, setStore] = React11__namespace.default.useState(getInitialStore);
3591
+ const storeRef = React11__namespace.default.useRef(store);
3592
+ const isInternalUpdateRef = React11__namespace.default.useRef(false);
3593
+ React11__namespace.default.useEffect(() => {
3594
+ storeRef.current = store;
3595
+ }, [store]);
3591
3596
  React11__namespace.default.useEffect(() => {
3592
3597
  document.documentElement.setAttribute("data-theme", store.value);
3593
3598
  }, [store.value]);
@@ -3598,6 +3603,10 @@ function useTheme() {
3598
3603
  }
3599
3604
  };
3600
3605
  const handleThemeChange = (e) => {
3606
+ if (isInternalUpdateRef.current) {
3607
+ isInternalUpdateRef.current = false;
3608
+ return;
3609
+ }
3601
3610
  const customEvent = e;
3602
3611
  if (customEvent.detail) {
3603
3612
  setStore(customEvent.detail);
@@ -3611,21 +3620,19 @@ function useTheme() {
3611
3620
  };
3612
3621
  }, []);
3613
3622
  const update = (updates) => {
3614
- setStore((prev) => {
3615
- const next = { ...prev, ...updates };
3616
- saveStore(next);
3617
- return next;
3618
- });
3623
+ const newStore = { ...storeRef.current, ...updates };
3624
+ setStore(newStore);
3625
+ isInternalUpdateRef.current = true;
3626
+ saveStore(newStore);
3619
3627
  };
3620
3628
  const toggle = (theme) => {
3621
- setStore((prev) => {
3622
- const next = {
3623
- value: theme ?? (prev.value === "light" ? "dark" : "light"),
3624
- isManual: true
3625
- };
3626
- saveStore(next);
3627
- return next;
3628
- });
3629
+ const newStore = {
3630
+ value: theme ?? (storeRef.current.value === "light" ? "dark" : "light"),
3631
+ isManual: true
3632
+ };
3633
+ setStore(newStore);
3634
+ isInternalUpdateRef.current = true;
3635
+ saveStore(newStore);
3629
3636
  };
3630
3637
  return { ...store, update, toggle };
3631
3638
  }
@@ -3540,7 +3540,7 @@ var getInitialStore = () => {
3540
3540
  if (stored) {
3541
3541
  const parsed = JSON.parse(stored);
3542
3542
  return {
3543
- value: parsed.theme ?? getInitialTheme(),
3543
+ value: parsed.value ?? getInitialTheme(),
3544
3544
  isManual: parsed.isManual ?? false
3545
3545
  };
3546
3546
  }
@@ -3565,6 +3565,11 @@ var saveStore = (store) => {
3565
3565
  // src/react/use-theme/index.ts
3566
3566
  function useTheme() {
3567
3567
  const [store, setStore] = React11__default.useState(getInitialStore);
3568
+ const storeRef = React11__default.useRef(store);
3569
+ const isInternalUpdateRef = React11__default.useRef(false);
3570
+ React11__default.useEffect(() => {
3571
+ storeRef.current = store;
3572
+ }, [store]);
3568
3573
  React11__default.useEffect(() => {
3569
3574
  document.documentElement.setAttribute("data-theme", store.value);
3570
3575
  }, [store.value]);
@@ -3575,6 +3580,10 @@ function useTheme() {
3575
3580
  }
3576
3581
  };
3577
3582
  const handleThemeChange = (e) => {
3583
+ if (isInternalUpdateRef.current) {
3584
+ isInternalUpdateRef.current = false;
3585
+ return;
3586
+ }
3578
3587
  const customEvent = e;
3579
3588
  if (customEvent.detail) {
3580
3589
  setStore(customEvent.detail);
@@ -3588,21 +3597,19 @@ function useTheme() {
3588
3597
  };
3589
3598
  }, []);
3590
3599
  const update = (updates) => {
3591
- setStore((prev) => {
3592
- const next = { ...prev, ...updates };
3593
- saveStore(next);
3594
- return next;
3595
- });
3600
+ const newStore = { ...storeRef.current, ...updates };
3601
+ setStore(newStore);
3602
+ isInternalUpdateRef.current = true;
3603
+ saveStore(newStore);
3596
3604
  };
3597
3605
  const toggle = (theme) => {
3598
- setStore((prev) => {
3599
- const next = {
3600
- value: theme ?? (prev.value === "light" ? "dark" : "light"),
3601
- isManual: true
3602
- };
3603
- saveStore(next);
3604
- return next;
3605
- });
3606
+ const newStore = {
3607
+ value: theme ?? (storeRef.current.value === "light" ? "dark" : "light"),
3608
+ isManual: true
3609
+ };
3610
+ setStore(newStore);
3611
+ isInternalUpdateRef.current = true;
3612
+ saveStore(newStore);
3606
3613
  };
3607
3614
  return { ...store, update, toggle };
3608
3615
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qstd",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "description": "Standard Block component and utilities library with Panda CSS",
5
5
  "author": "malin1",
6
6
  "license": "MIT",