@heymantle/litho 0.0.10 → 0.0.13
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/dist/cjs/components/Banner.js +6 -1
- package/dist/cjs/components/Button.js +33 -4
- package/dist/cjs/components/ButtonGroup.js +19 -4
- package/dist/cjs/components/Card.js +39 -3
- package/dist/cjs/components/ChoiceList.js +3 -2
- package/dist/cjs/components/Code.js +227 -0
- package/dist/cjs/components/Filters.js +1 -1
- package/dist/cjs/components/Frame.js +2 -2
- package/dist/cjs/components/Layout.js +16 -4
- package/dist/cjs/components/Link.js +35 -4
- package/dist/cjs/components/Modal.js +4 -0
- package/dist/cjs/components/Page.js +5 -2
- package/dist/cjs/components/Pane.js +669 -84
- package/dist/cjs/components/ResourceList.js +2 -2
- package/dist/cjs/components/TabNavigation.js +300 -0
- package/dist/cjs/components/TextField.js +3 -0
- package/dist/cjs/components/Tip.js +3 -0
- package/dist/cjs/components/Tooltip.js +12 -13
- package/dist/cjs/index.js +4 -0
- package/dist/cjs/stories/Pane.stories.js +352 -3
- package/dist/cjs/utilities/useBodyScrollLock.js +63 -0
- package/dist/cjs/utilities/useKeyboardAction.js +19 -0
- package/dist/cjs/utilities/useLocalStorage.js +126 -0
- package/dist/cjs/utilities/useMobile.js +92 -0
- package/dist/cjs/utilities/usePaneState.js +340 -0
- package/dist/cjs/utilities/useTabStorage.js +325 -0
- package/dist/esm/components/Banner.js +7 -2
- package/dist/esm/components/Button.js +33 -4
- package/dist/esm/components/ButtonGroup.js +19 -4
- package/dist/esm/components/Card.js +39 -3
- package/dist/esm/components/ChoiceList.js +3 -2
- package/dist/esm/components/Code.js +212 -0
- package/dist/esm/components/Filters.js +2 -2
- package/dist/esm/components/Frame.js +2 -2
- package/dist/esm/components/Layout.js +16 -4
- package/dist/esm/components/Link.js +31 -5
- package/dist/esm/components/Modal.js +4 -0
- package/dist/esm/components/Page.js +5 -2
- package/dist/esm/components/Pane.js +619 -83
- package/dist/esm/components/ResourceList.js +2 -2
- package/dist/esm/components/TabNavigation.js +285 -0
- package/dist/esm/components/TextField.js +4 -1
- package/dist/esm/components/Tip.js +4 -1
- package/dist/esm/components/Tooltip.js +12 -13
- package/dist/esm/index.js +1 -0
- package/dist/esm/stories/Pane.stories.js +346 -3
- package/dist/esm/utilities/useBodyScrollLock.js +53 -0
- package/dist/esm/utilities/useKeyboardAction.js +25 -0
- package/dist/esm/utilities/useLocalStorage.js +115 -0
- package/dist/esm/utilities/useMobile.js +79 -0
- package/dist/esm/utilities/usePaneState.js +334 -0
- package/dist/esm/utilities/useTabStorage.js +311 -0
- package/dist/types/components/Banner.d.ts.map +1 -1
- package/dist/types/components/Button.d.ts +2 -2
- package/dist/types/components/Button.d.ts.map +1 -1
- package/dist/types/components/ButtonGroup.d.ts.map +1 -1
- package/dist/types/components/Card.d.ts +34 -1
- package/dist/types/components/Card.d.ts.map +1 -1
- package/dist/types/components/Code.d.ts +28 -0
- package/dist/types/components/Code.d.ts.map +1 -0
- package/dist/types/components/Filters.d.ts.map +1 -1
- package/dist/types/components/Layout.d.ts +2 -0
- package/dist/types/components/Layout.d.ts.map +1 -1
- package/dist/types/components/Link.d.ts +4 -0
- package/dist/types/components/Link.d.ts.map +1 -1
- package/dist/types/components/Modal.d.ts +2 -0
- package/dist/types/components/Modal.d.ts.map +1 -1
- package/dist/types/components/Page.d.ts.map +1 -1
- package/dist/types/components/Pane.d.ts +2 -0
- package/dist/types/components/Pane.d.ts.map +1 -1
- package/dist/types/components/TabNavigation.d.ts +3 -0
- package/dist/types/components/TabNavigation.d.ts.map +1 -0
- package/dist/types/components/TextField.d.ts.map +1 -1
- package/dist/types/components/Tip.d.ts.map +1 -1
- package/dist/types/components/Tooltip.d.ts +2 -0
- package/dist/types/components/Tooltip.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/utilities/useBodyScrollLock.d.ts +12 -0
- package/dist/types/utilities/useBodyScrollLock.d.ts.map +1 -0
- package/dist/types/utilities/useKeyboardAction.d.ts +2 -0
- package/dist/types/utilities/useKeyboardAction.d.ts.map +1 -0
- package/dist/types/utilities/useLocalStorage.d.ts +13 -0
- package/dist/types/utilities/useLocalStorage.d.ts.map +1 -0
- package/dist/types/utilities/useMobile.d.ts +9 -0
- package/dist/types/utilities/useMobile.d.ts.map +1 -0
- package/dist/types/utilities/usePaneState.d.ts +2 -0
- package/dist/types/utilities/usePaneState.d.ts.map +1 -0
- package/dist/types/utilities/useTabStorage.d.ts +8 -0
- package/dist/types/utilities/useTabStorage.d.ts.map +1 -0
- package/index.css +77 -6
- package/package.json +2 -2
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
function _array_like_to_array(arr, len) {
|
|
3
|
+
if (len == null || len > arr.length) len = arr.length;
|
|
4
|
+
for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
|
|
5
|
+
return arr2;
|
|
6
|
+
}
|
|
7
|
+
function _array_with_holes(arr) {
|
|
8
|
+
if (Array.isArray(arr)) return arr;
|
|
9
|
+
}
|
|
10
|
+
function _iterable_to_array_limit(arr, i) {
|
|
11
|
+
var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
|
|
12
|
+
if (_i == null) return;
|
|
13
|
+
var _arr = [];
|
|
14
|
+
var _n = true;
|
|
15
|
+
var _d = false;
|
|
16
|
+
var _s, _e;
|
|
17
|
+
try {
|
|
18
|
+
for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
|
|
19
|
+
_arr.push(_s.value);
|
|
20
|
+
if (i && _arr.length === i) break;
|
|
21
|
+
}
|
|
22
|
+
} catch (err) {
|
|
23
|
+
_d = true;
|
|
24
|
+
_e = err;
|
|
25
|
+
} finally{
|
|
26
|
+
try {
|
|
27
|
+
if (!_n && _i["return"] != null) _i["return"]();
|
|
28
|
+
} finally{
|
|
29
|
+
if (_d) throw _e;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return _arr;
|
|
33
|
+
}
|
|
34
|
+
function _non_iterable_rest() {
|
|
35
|
+
throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
36
|
+
}
|
|
37
|
+
function _sliced_to_array(arr, i) {
|
|
38
|
+
return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
|
|
39
|
+
}
|
|
40
|
+
function _unsupported_iterable_to_array(o, minLen) {
|
|
41
|
+
if (!o) return;
|
|
42
|
+
if (typeof o === "string") return _array_like_to_array(o, minLen);
|
|
43
|
+
var n = Object.prototype.toString.call(o).slice(8, -1);
|
|
44
|
+
if (n === "Object" && o.constructor) n = o.constructor.name;
|
|
45
|
+
if (n === "Map" || n === "Set") return Array.from(n);
|
|
46
|
+
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
|
|
47
|
+
}
|
|
48
|
+
import { useState, useEffect, useCallback } from "react";
|
|
49
|
+
import { useDebouncedCallback } from "use-debounce";
|
|
50
|
+
/**
|
|
51
|
+
* Custom hook for detecting mobile viewport
|
|
52
|
+
* @param {number} breakpoint - The breakpoint width in pixels (default: 768)
|
|
53
|
+
* @param {number} debounceMs - Debounce delay for resize events in milliseconds (default: 150)
|
|
54
|
+
* @returns {boolean} - True if viewport width is below the breakpoint
|
|
55
|
+
*/ export function useMobile() {
|
|
56
|
+
var breakpoint = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : 768, debounceMs = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 150;
|
|
57
|
+
var _useState = _sliced_to_array(useState(function() {
|
|
58
|
+
if (typeof window === 'undefined') return false;
|
|
59
|
+
return window.innerWidth < breakpoint;
|
|
60
|
+
}), 2), isMobile = _useState[0], setIsMobile = _useState[1];
|
|
61
|
+
// Debounced resize handler
|
|
62
|
+
var handleResize = useDebouncedCallback(function() {
|
|
63
|
+
if (typeof window === 'undefined') return;
|
|
64
|
+
var mobile = window.innerWidth < breakpoint;
|
|
65
|
+
setIsMobile(mobile);
|
|
66
|
+
}, debounceMs);
|
|
67
|
+
useEffect(function() {
|
|
68
|
+
if (typeof window === 'undefined') return;
|
|
69
|
+
window.addEventListener('resize', handleResize);
|
|
70
|
+
return function() {
|
|
71
|
+
window.removeEventListener('resize', handleResize);
|
|
72
|
+
handleResize.cancel();
|
|
73
|
+
};
|
|
74
|
+
}, [
|
|
75
|
+
handleResize
|
|
76
|
+
]);
|
|
77
|
+
return isMobile;
|
|
78
|
+
}
|
|
79
|
+
export default useMobile;
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
function _array_like_to_array(arr, len) {
|
|
3
|
+
if (len == null || len > arr.length) len = arr.length;
|
|
4
|
+
for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
|
|
5
|
+
return arr2;
|
|
6
|
+
}
|
|
7
|
+
function _array_with_holes(arr) {
|
|
8
|
+
if (Array.isArray(arr)) return arr;
|
|
9
|
+
}
|
|
10
|
+
function _define_property(obj, key, value) {
|
|
11
|
+
if (key in obj) {
|
|
12
|
+
Object.defineProperty(obj, key, {
|
|
13
|
+
value: value,
|
|
14
|
+
enumerable: true,
|
|
15
|
+
configurable: true,
|
|
16
|
+
writable: true
|
|
17
|
+
});
|
|
18
|
+
} else {
|
|
19
|
+
obj[key] = value;
|
|
20
|
+
}
|
|
21
|
+
return obj;
|
|
22
|
+
}
|
|
23
|
+
function _iterable_to_array_limit(arr, i) {
|
|
24
|
+
var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
|
|
25
|
+
if (_i == null) return;
|
|
26
|
+
var _arr = [];
|
|
27
|
+
var _n = true;
|
|
28
|
+
var _d = false;
|
|
29
|
+
var _s, _e;
|
|
30
|
+
try {
|
|
31
|
+
for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
|
|
32
|
+
_arr.push(_s.value);
|
|
33
|
+
if (i && _arr.length === i) break;
|
|
34
|
+
}
|
|
35
|
+
} catch (err) {
|
|
36
|
+
_d = true;
|
|
37
|
+
_e = err;
|
|
38
|
+
} finally{
|
|
39
|
+
try {
|
|
40
|
+
if (!_n && _i["return"] != null) _i["return"]();
|
|
41
|
+
} finally{
|
|
42
|
+
if (_d) throw _e;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return _arr;
|
|
46
|
+
}
|
|
47
|
+
function _non_iterable_rest() {
|
|
48
|
+
throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
49
|
+
}
|
|
50
|
+
function _object_spread(target) {
|
|
51
|
+
for(var i = 1; i < arguments.length; i++){
|
|
52
|
+
var source = arguments[i] != null ? arguments[i] : {};
|
|
53
|
+
var ownKeys = Object.keys(source);
|
|
54
|
+
if (typeof Object.getOwnPropertySymbols === "function") {
|
|
55
|
+
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
|
|
56
|
+
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
59
|
+
ownKeys.forEach(function(key) {
|
|
60
|
+
_define_property(target, key, source[key]);
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
return target;
|
|
64
|
+
}
|
|
65
|
+
function ownKeys(object, enumerableOnly) {
|
|
66
|
+
var keys = Object.keys(object);
|
|
67
|
+
if (Object.getOwnPropertySymbols) {
|
|
68
|
+
var symbols = Object.getOwnPropertySymbols(object);
|
|
69
|
+
if (enumerableOnly) {
|
|
70
|
+
symbols = symbols.filter(function(sym) {
|
|
71
|
+
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
keys.push.apply(keys, symbols);
|
|
75
|
+
}
|
|
76
|
+
return keys;
|
|
77
|
+
}
|
|
78
|
+
function _object_spread_props(target, source) {
|
|
79
|
+
source = source != null ? source : {};
|
|
80
|
+
if (Object.getOwnPropertyDescriptors) {
|
|
81
|
+
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
|
|
82
|
+
} else {
|
|
83
|
+
ownKeys(Object(source)).forEach(function(key) {
|
|
84
|
+
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
return target;
|
|
88
|
+
}
|
|
89
|
+
function _sliced_to_array(arr, i) {
|
|
90
|
+
return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
|
|
91
|
+
}
|
|
92
|
+
function _type_of(obj) {
|
|
93
|
+
"@swc/helpers - typeof";
|
|
94
|
+
return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
|
|
95
|
+
}
|
|
96
|
+
function _unsupported_iterable_to_array(o, minLen) {
|
|
97
|
+
if (!o) return;
|
|
98
|
+
if (typeof o === "string") return _array_like_to_array(o, minLen);
|
|
99
|
+
var n = Object.prototype.toString.call(o).slice(8, -1);
|
|
100
|
+
if (n === "Object" && o.constructor) n = o.constructor.name;
|
|
101
|
+
if (n === "Map" || n === "Set") return Array.from(n);
|
|
102
|
+
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
|
|
103
|
+
}
|
|
104
|
+
import { useEffect, useRef, useMemo, useCallback } from "react";
|
|
105
|
+
import { useLocalStorage } from "./useLocalStorage.js";
|
|
106
|
+
var PANE_STATE_STORAGE_KEY = 'litho-pane-state';
|
|
107
|
+
var DEFAULT_ORG_STATE = {
|
|
108
|
+
activeTabId: null,
|
|
109
|
+
width: 400,
|
|
110
|
+
collapsed: false,
|
|
111
|
+
open: false,
|
|
112
|
+
tabs: []
|
|
113
|
+
};
|
|
114
|
+
// Module-level refs to track recent values across all hook instances
|
|
115
|
+
// This ensures we can track values even when multiple components use the hook
|
|
116
|
+
// Used to handle race conditions where updates are called in the same render cycle
|
|
117
|
+
var recentValuesRef = {}; // { [orgId]: { [key]: value } }
|
|
118
|
+
// Stable empty object reference to prevent unnecessary recalculations
|
|
119
|
+
var EMPTY_OBJECT = {};
|
|
120
|
+
// Helper to merge state with defaults (for reading)
|
|
121
|
+
// Preserves original array references when possible to prevent unnecessary re-renders
|
|
122
|
+
var mergeWithDefaults = function(state) {
|
|
123
|
+
if (!state || (typeof state === "undefined" ? "undefined" : _type_of(state)) !== 'object') {
|
|
124
|
+
return _object_spread({}, DEFAULT_ORG_STATE);
|
|
125
|
+
}
|
|
126
|
+
return _object_spread_props(_object_spread({}, DEFAULT_ORG_STATE, state), {
|
|
127
|
+
// Preserve original tabs array reference if it exists and is valid, otherwise use default
|
|
128
|
+
tabs: Array.isArray(state.tabs) ? state.tabs : DEFAULT_ORG_STATE.tabs
|
|
129
|
+
});
|
|
130
|
+
};
|
|
131
|
+
/**
|
|
132
|
+
* Hook to manage consolidated pane state in localStorage, scoped by orgId
|
|
133
|
+
* @param {string} [orgId] - Organization ID to scope the pane state (optional, but required for state operations)
|
|
134
|
+
* @returns {Object} { state, setState, setWidth, setCollapsed, setOpen, setTabs, setActiveTabId, refreshFromStorage }
|
|
135
|
+
*/ export var usePaneState = function(orgId) {
|
|
136
|
+
var currentOrgIdRef = useRef(orgId);
|
|
137
|
+
// Ref to track current React state so we can access it in setState callbacks
|
|
138
|
+
var currentStateRef = useRef(null);
|
|
139
|
+
// Update ref when orgId changes
|
|
140
|
+
useEffect(function() {
|
|
141
|
+
currentOrgIdRef.current = orgId;
|
|
142
|
+
}, [
|
|
143
|
+
orgId
|
|
144
|
+
]);
|
|
145
|
+
// Only initialize localStorage if there's existing data, otherwise use null
|
|
146
|
+
// This prevents saving empty objects on page load
|
|
147
|
+
var _useLocalStorage = _sliced_to_array(useLocalStorage(PANE_STATE_STORAGE_KEY, null, {
|
|
148
|
+
serialize: true
|
|
149
|
+
}), 2), allOrgsState = _useLocalStorage[0], setAllOrgsState = _useLocalStorage[1];
|
|
150
|
+
// Normalize null to empty object for internal use (memoize to prevent unnecessary recalculations)
|
|
151
|
+
// Use stable EMPTY_OBJECT reference when allOrgsState is null
|
|
152
|
+
var normalizedState = useMemo(function() {
|
|
153
|
+
return allOrgsState || EMPTY_OBJECT;
|
|
154
|
+
}, [
|
|
155
|
+
allOrgsState
|
|
156
|
+
]);
|
|
157
|
+
// Keep ref in sync with current React state
|
|
158
|
+
useEffect(function() {
|
|
159
|
+
currentStateRef.current = normalizedState;
|
|
160
|
+
}, [
|
|
161
|
+
normalizedState
|
|
162
|
+
]);
|
|
163
|
+
// Get current org's state (merge with defaults for reading)
|
|
164
|
+
var orgState = useMemo(function() {
|
|
165
|
+
if (!orgId) {
|
|
166
|
+
return _object_spread({}, DEFAULT_ORG_STATE);
|
|
167
|
+
}
|
|
168
|
+
var state = normalizedState === null || normalizedState === void 0 ? void 0 : normalizedState[orgId];
|
|
169
|
+
return mergeWithDefaults(state);
|
|
170
|
+
}, [
|
|
171
|
+
normalizedState,
|
|
172
|
+
orgId
|
|
173
|
+
]);
|
|
174
|
+
// Function to manually refresh state from localStorage
|
|
175
|
+
// Called on page load (via useState initializer) and when pane opens
|
|
176
|
+
var refreshFromStorage = useCallback(function() {
|
|
177
|
+
if (typeof window === 'undefined') return;
|
|
178
|
+
try {
|
|
179
|
+
var item = window.localStorage.getItem(PANE_STATE_STORAGE_KEY);
|
|
180
|
+
if (item !== null) {
|
|
181
|
+
var parsed = JSON.parse(item);
|
|
182
|
+
setAllOrgsState(parsed);
|
|
183
|
+
}
|
|
184
|
+
} catch (error) {
|
|
185
|
+
console.warn('Error refreshing pane state from localStorage:', error);
|
|
186
|
+
}
|
|
187
|
+
}, [
|
|
188
|
+
setAllOrgsState
|
|
189
|
+
]);
|
|
190
|
+
// Helper to ensure recentValuesRef exists for an orgId
|
|
191
|
+
var ensureRecentValuesRef = useCallback(function(orgId) {
|
|
192
|
+
if (!recentValuesRef[orgId]) {
|
|
193
|
+
recentValuesRef[orgId] = {};
|
|
194
|
+
}
|
|
195
|
+
}, []);
|
|
196
|
+
// Helper to create first-time state
|
|
197
|
+
var createFirstTimeState = useCallback(function(currentState, orgId, key, newValue) {
|
|
198
|
+
// Don't create state when setting 'open' to false on first time (pane was never opened)
|
|
199
|
+
if (key === 'open' && newValue === false) {
|
|
200
|
+
return currentState;
|
|
201
|
+
}
|
|
202
|
+
// Save the full default state on first open
|
|
203
|
+
return _object_spread_props(_object_spread({}, currentState), _define_property({}, orgId, _object_spread_props(_object_spread({}, DEFAULT_ORG_STATE), _define_property({}, key, newValue))));
|
|
204
|
+
}, []);
|
|
205
|
+
// Helper to apply recent values from snapshot to new state
|
|
206
|
+
var applyRecentValues = useCallback(function(newOrgState, snapshot, key) {
|
|
207
|
+
Object.keys(snapshot).forEach(function(recentKey) {
|
|
208
|
+
if (recentKey !== key) {
|
|
209
|
+
newOrgState[recentKey] = snapshot[recentKey];
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
}, []);
|
|
213
|
+
// Helper to cleanup snapshot values after update cycle
|
|
214
|
+
var cleanupSnapshotValues = useCallback(function(orgId, snapshot, snapshotKeys) {
|
|
215
|
+
if (typeof window === 'undefined' || snapshotKeys.length === 0) return;
|
|
216
|
+
requestAnimationFrame(function() {
|
|
217
|
+
var currentRecentValues = recentValuesRef[orgId];
|
|
218
|
+
if (!currentRecentValues) return;
|
|
219
|
+
// Clear only the keys that were in our snapshot and haven't changed
|
|
220
|
+
snapshotKeys.forEach(function(snapshotKey) {
|
|
221
|
+
if (currentRecentValues[snapshotKey] === snapshot[snapshotKey]) {
|
|
222
|
+
delete currentRecentValues[snapshotKey];
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
});
|
|
226
|
+
}, []);
|
|
227
|
+
// Generic helper function to update state for a given key
|
|
228
|
+
// Uses currentOrgIdRef internally to always get the latest orgId value
|
|
229
|
+
// Falls back to orgId prop if ref hasn't been updated yet
|
|
230
|
+
var updateStateForKey = useCallback(function(key, value, setState) {
|
|
231
|
+
var currentOrgId = currentOrgIdRef.current || orgId;
|
|
232
|
+
if (!currentOrgId) {
|
|
233
|
+
console.warn("Cannot set ".concat(key, ": orgId is required"));
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
ensureRecentValuesRef(currentOrgId);
|
|
237
|
+
// Capture a snapshot of recent values BEFORE entering setState callback
|
|
238
|
+
// This ensures we have the latest values even if React batches updates
|
|
239
|
+
var recentValuesSnapshot = _object_spread({}, recentValuesRef[currentOrgId]);
|
|
240
|
+
var snapshotKeys = Object.keys(recentValuesSnapshot);
|
|
241
|
+
setState(function(prev) {
|
|
242
|
+
var currentState = prev || {};
|
|
243
|
+
var currentOrgState = currentState[currentOrgId] || {};
|
|
244
|
+
var prevValue = currentOrgState[key];
|
|
245
|
+
var newValue = typeof value === 'function' ? value(prevValue) : value;
|
|
246
|
+
// Track the most recent value for this key (to handle race conditions)
|
|
247
|
+
recentValuesRef[currentOrgId][key] = newValue;
|
|
248
|
+
// Handle first-time state creation
|
|
249
|
+
var isFirstTime = !currentState[currentOrgId];
|
|
250
|
+
if (isFirstTime) {
|
|
251
|
+
return createFirstTimeState(currentState, currentOrgId, key, newValue);
|
|
252
|
+
}
|
|
253
|
+
// After first open, preserve existing state and update the specific key
|
|
254
|
+
var newOrgState = _object_spread_props(_object_spread({}, currentOrgState), _define_property({}, key, newValue));
|
|
255
|
+
// Apply recent values from snapshot (except the key being updated)
|
|
256
|
+
if (snapshotKeys.length > 0) {
|
|
257
|
+
applyRecentValues(newOrgState, recentValuesSnapshot, key);
|
|
258
|
+
}
|
|
259
|
+
return _object_spread_props(_object_spread({}, currentState), _define_property({}, currentOrgId, newOrgState));
|
|
260
|
+
});
|
|
261
|
+
// Cleanup snapshot values after update cycle completes
|
|
262
|
+
cleanupSnapshotValues(currentOrgId, recentValuesSnapshot, snapshotKeys);
|
|
263
|
+
}, [
|
|
264
|
+
orgId,
|
|
265
|
+
ensureRecentValuesRef,
|
|
266
|
+
createFirstTimeState,
|
|
267
|
+
applyRecentValues,
|
|
268
|
+
cleanupSnapshotValues
|
|
269
|
+
]);
|
|
270
|
+
// Helper setters for individual properties - memoized with useCallback
|
|
271
|
+
var setWidth = useCallback(function(value) {
|
|
272
|
+
updateStateForKey('width', value, setAllOrgsState);
|
|
273
|
+
}, [
|
|
274
|
+
updateStateForKey,
|
|
275
|
+
setAllOrgsState
|
|
276
|
+
]);
|
|
277
|
+
var setCollapsed = useCallback(function(value) {
|
|
278
|
+
updateStateForKey('collapsed', value, setAllOrgsState);
|
|
279
|
+
}, [
|
|
280
|
+
updateStateForKey,
|
|
281
|
+
setAllOrgsState
|
|
282
|
+
]);
|
|
283
|
+
var setOpen = useCallback(function(value) {
|
|
284
|
+
updateStateForKey('open', value, setAllOrgsState);
|
|
285
|
+
}, [
|
|
286
|
+
updateStateForKey,
|
|
287
|
+
setAllOrgsState
|
|
288
|
+
]);
|
|
289
|
+
var setTabs = useCallback(function(value) {
|
|
290
|
+
updateStateForKey('tabs', value, setAllOrgsState);
|
|
291
|
+
}, [
|
|
292
|
+
updateStateForKey,
|
|
293
|
+
setAllOrgsState
|
|
294
|
+
]);
|
|
295
|
+
var setActiveTabId = useCallback(function(value) {
|
|
296
|
+
updateStateForKey('activeTabId', value, setAllOrgsState);
|
|
297
|
+
}, [
|
|
298
|
+
updateStateForKey,
|
|
299
|
+
setAllOrgsState
|
|
300
|
+
]);
|
|
301
|
+
// Generic setState function for updating entire org state
|
|
302
|
+
var setState = useCallback(function(newState) {
|
|
303
|
+
if (!orgId) {
|
|
304
|
+
console.warn('Cannot set state: orgId is required');
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
setAllOrgsState(function(prev) {
|
|
308
|
+
var currentState = prev || {};
|
|
309
|
+
var currentOrgState = currentState[orgId] || {};
|
|
310
|
+
var isFirstTime = !currentState[orgId];
|
|
311
|
+
var mergedState = mergeWithDefaults(currentOrgState);
|
|
312
|
+
var updatedState = typeof newState === 'function' ? newState(mergedState) : _object_spread({}, mergedState, newState);
|
|
313
|
+
// On first open, save all default values to initialize the state
|
|
314
|
+
if (isFirstTime) {
|
|
315
|
+
return _object_spread_props(_object_spread({}, currentState), _define_property({}, orgId, _object_spread({}, DEFAULT_ORG_STATE, updatedState)));
|
|
316
|
+
}
|
|
317
|
+
// After first open, just save the updated state
|
|
318
|
+
return _object_spread_props(_object_spread({}, currentState), _define_property({}, orgId, updatedState));
|
|
319
|
+
});
|
|
320
|
+
}, [
|
|
321
|
+
orgId,
|
|
322
|
+
setAllOrgsState
|
|
323
|
+
]);
|
|
324
|
+
return {
|
|
325
|
+
state: orgState,
|
|
326
|
+
setState: setState,
|
|
327
|
+
setWidth: setWidth,
|
|
328
|
+
setCollapsed: setCollapsed,
|
|
329
|
+
setOpen: setOpen,
|
|
330
|
+
setTabs: setTabs,
|
|
331
|
+
setActiveTabId: setActiveTabId,
|
|
332
|
+
refreshFromStorage: refreshFromStorage
|
|
333
|
+
};
|
|
334
|
+
};
|