@togglely/sdk-react 1.0.0 → 1.1.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.
- package/dist/index.d.ts +138 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.esm.js +297 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.js +325 -0
- package/dist/index.js.map +1 -0
- package/package.json +1 -1
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Togglely React SDK
|
|
3
|
+
*
|
|
4
|
+
* Provides React hooks and context for feature toggles
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* ```tsx
|
|
8
|
+
* import { TogglelyProvider, useToggle, useToggles } from '@togglely/sdk-react';
|
|
9
|
+
*
|
|
10
|
+
* function App() {
|
|
11
|
+
* return (
|
|
12
|
+
* <TogglelyProvider
|
|
13
|
+
* apiKey="your-api-key"
|
|
14
|
+
* environment="production"
|
|
15
|
+
* baseUrl="https://your-togglely-instance.com"
|
|
16
|
+
* >
|
|
17
|
+
* <MyComponent />
|
|
18
|
+
* </TogglelyProvider>
|
|
19
|
+
* );
|
|
20
|
+
* }
|
|
21
|
+
*
|
|
22
|
+
* function MyComponent() {
|
|
23
|
+
* const isEnabled = useToggle('new-feature', false);
|
|
24
|
+
*
|
|
25
|
+
* return isEnabled ? <NewFeature /> : <OldFeature />;
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
import React, { ReactNode } from 'react';
|
|
30
|
+
import { TogglelyClient, TogglelyConfig, ToggleContext, TogglelyState } from '@togglely/sdk-core';
|
|
31
|
+
export interface TogglelyProviderProps extends Omit<TogglelyConfig, 'offlineFallback' | 'envPrefix'> {
|
|
32
|
+
children: ReactNode;
|
|
33
|
+
/** Initial toggles for SSR / offline mode */
|
|
34
|
+
initialToggles?: Record<string, any>;
|
|
35
|
+
/** Enable offline fallback (default: true) */
|
|
36
|
+
offlineFallback?: boolean;
|
|
37
|
+
}
|
|
38
|
+
export declare function TogglelyProvider({ children, initialToggles, offlineFallback, ...config }: TogglelyProviderProps): React.JSX.Element;
|
|
39
|
+
/**
|
|
40
|
+
* Get the Togglely client instance
|
|
41
|
+
*/
|
|
42
|
+
export declare function useTogglelyClient(): TogglelyClient;
|
|
43
|
+
/**
|
|
44
|
+
* Get the current Togglely state
|
|
45
|
+
*/
|
|
46
|
+
export declare function useTogglelyState(): TogglelyState;
|
|
47
|
+
/**
|
|
48
|
+
* Check if Togglely is ready (toggles have been fetched at least once)
|
|
49
|
+
*/
|
|
50
|
+
export declare function useTogglelyReady(): boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Check if Togglely is in offline mode
|
|
53
|
+
*/
|
|
54
|
+
export declare function useTogglelyOffline(): boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Hook to check if a boolean feature toggle is enabled
|
|
57
|
+
*/
|
|
58
|
+
export declare function useToggle(key: string, defaultValue?: boolean): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Hook to get a string toggle value
|
|
61
|
+
*/
|
|
62
|
+
export declare function useStringToggle(key: string, defaultValue?: string): string;
|
|
63
|
+
/**
|
|
64
|
+
* Hook to get a number toggle value
|
|
65
|
+
*/
|
|
66
|
+
export declare function useNumberToggle(key: string, defaultValue?: number): number;
|
|
67
|
+
/**
|
|
68
|
+
* Hook to get a JSON toggle value
|
|
69
|
+
*/
|
|
70
|
+
export declare function useJSONToggle<T = any>(key: string, defaultValue?: T): T;
|
|
71
|
+
/**
|
|
72
|
+
* Hook to get all toggles
|
|
73
|
+
*/
|
|
74
|
+
export declare function useToggles(): Record<string, {
|
|
75
|
+
value: any;
|
|
76
|
+
enabled: boolean;
|
|
77
|
+
}>;
|
|
78
|
+
/**
|
|
79
|
+
* Hook to set context for toggle evaluation
|
|
80
|
+
*/
|
|
81
|
+
export declare function useTogglelyContext(): {
|
|
82
|
+
setContext: (context: ToggleContext) => void;
|
|
83
|
+
clearContext: () => void;
|
|
84
|
+
context: ToggleContext;
|
|
85
|
+
};
|
|
86
|
+
export interface FeatureToggleProps {
|
|
87
|
+
/** Toggle key to check */
|
|
88
|
+
toggle: string;
|
|
89
|
+
/** Content to render when toggle is enabled */
|
|
90
|
+
children: ReactNode;
|
|
91
|
+
/** Content to render when toggle is disabled (optional) */
|
|
92
|
+
fallback?: ReactNode;
|
|
93
|
+
/** Default value if toggle is not found */
|
|
94
|
+
defaultValue?: boolean;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Component to conditionally render content based on a feature toggle
|
|
98
|
+
*/
|
|
99
|
+
export declare function FeatureToggle({ toggle, children, fallback, defaultValue }: FeatureToggleProps): React.JSX.Element;
|
|
100
|
+
export interface FeatureToggleSwitchProps {
|
|
101
|
+
/** Toggle key to check */
|
|
102
|
+
toggle: string;
|
|
103
|
+
/** Default value if toggle is not found */
|
|
104
|
+
defaultValue?: boolean;
|
|
105
|
+
/** Children should be FeatureToggleCase components */
|
|
106
|
+
children: ReactNode;
|
|
107
|
+
}
|
|
108
|
+
interface FeatureToggleCaseProps {
|
|
109
|
+
/** Render when toggle matches this value */
|
|
110
|
+
when: boolean;
|
|
111
|
+
/** Content to render */
|
|
112
|
+
children: ReactNode;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Case component for FeatureToggleSwitch
|
|
116
|
+
*/
|
|
117
|
+
export declare function FeatureToggleCase({ children }: FeatureToggleCaseProps): React.JSX.Element;
|
|
118
|
+
/**
|
|
119
|
+
* Switch component for feature toggles with multiple cases
|
|
120
|
+
*/
|
|
121
|
+
export declare function FeatureToggleSwitch({ toggle, defaultValue, children }: FeatureToggleSwitchProps): React.JSX.Element;
|
|
122
|
+
export interface WithFeatureToggleOptions {
|
|
123
|
+
toggle: string;
|
|
124
|
+
defaultValue?: boolean;
|
|
125
|
+
fallback?: React.ComponentType<any>;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Higher-order component to wrap a component with feature toggle check
|
|
129
|
+
*/
|
|
130
|
+
export declare function withFeatureToggle<P extends object>(Component: React.ComponentType<P>, options: WithFeatureToggleOptions): React.FC<P>;
|
|
131
|
+
/**
|
|
132
|
+
* Hook that suspends until toggles are ready
|
|
133
|
+
* Use with React.Suspense
|
|
134
|
+
*/
|
|
135
|
+
export declare function useTogglelySuspense(): TogglelyClient;
|
|
136
|
+
export type { TogglelyConfig, ToggleContext, TogglelyState, TogglelyEventType } from '@togglely/sdk-core';
|
|
137
|
+
export { TogglelyClient, createOfflineTogglesScript, togglesToEnvVars } from '@togglely/sdk-core';
|
|
138
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import React, { createContext, useState, useEffect, useContext, useCallback } from 'react';
|
|
2
|
+
import { TogglelyClient } from '@togglely/sdk-core';
|
|
3
|
+
export { TogglelyClient, createOfflineTogglesScript, togglesToEnvVars } from '@togglely/sdk-core';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Togglely React SDK
|
|
7
|
+
*
|
|
8
|
+
* Provides React hooks and context for feature toggles
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* ```tsx
|
|
12
|
+
* import { TogglelyProvider, useToggle, useToggles } from '@togglely/sdk-react';
|
|
13
|
+
*
|
|
14
|
+
* function App() {
|
|
15
|
+
* return (
|
|
16
|
+
* <TogglelyProvider
|
|
17
|
+
* apiKey="your-api-key"
|
|
18
|
+
* environment="production"
|
|
19
|
+
* baseUrl="https://your-togglely-instance.com"
|
|
20
|
+
* >
|
|
21
|
+
* <MyComponent />
|
|
22
|
+
* </TogglelyProvider>
|
|
23
|
+
* );
|
|
24
|
+
* }
|
|
25
|
+
*
|
|
26
|
+
* function MyComponent() {
|
|
27
|
+
* const isEnabled = useToggle('new-feature', false);
|
|
28
|
+
*
|
|
29
|
+
* return isEnabled ? <NewFeature /> : <OldFeature />;
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
const TogglelyContext = createContext({
|
|
34
|
+
client: null,
|
|
35
|
+
state: {
|
|
36
|
+
isReady: false,
|
|
37
|
+
isOffline: false,
|
|
38
|
+
lastError: null,
|
|
39
|
+
lastFetch: null
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
function TogglelyProvider({ children, initialToggles, offlineFallback = true, ...config }) {
|
|
43
|
+
const [client] = useState(() => new TogglelyClient({
|
|
44
|
+
...config,
|
|
45
|
+
offlineFallback
|
|
46
|
+
}));
|
|
47
|
+
const [state, setState] = useState(client.getState());
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
// Inject initial toggles for SSR if provided
|
|
50
|
+
if (initialToggles && typeof window !== 'undefined') {
|
|
51
|
+
window.__TOGGLELY_TOGGLES = initialToggles;
|
|
52
|
+
}
|
|
53
|
+
// Listen to all events
|
|
54
|
+
const unsubscribeReady = client.on('ready', (newState) => setState(newState));
|
|
55
|
+
const unsubscribeUpdate = client.on('update', (newState) => setState(newState));
|
|
56
|
+
const unsubscribeError = client.on('error', (newState) => setState(newState));
|
|
57
|
+
const unsubscribeOffline = client.on('offline', (newState) => setState(newState));
|
|
58
|
+
const unsubscribeOnline = client.on('online', (newState) => setState(newState));
|
|
59
|
+
return () => {
|
|
60
|
+
unsubscribeReady();
|
|
61
|
+
unsubscribeUpdate();
|
|
62
|
+
unsubscribeError();
|
|
63
|
+
unsubscribeOffline();
|
|
64
|
+
unsubscribeOnline();
|
|
65
|
+
client.destroy();
|
|
66
|
+
};
|
|
67
|
+
}, [client, initialToggles]);
|
|
68
|
+
return (React.createElement(TogglelyContext.Provider, { value: { client, state } }, children));
|
|
69
|
+
}
|
|
70
|
+
// ==================== Hooks ====================
|
|
71
|
+
/**
|
|
72
|
+
* Get the Togglely client instance
|
|
73
|
+
*/
|
|
74
|
+
function useTogglelyClient() {
|
|
75
|
+
const { client } = useContext(TogglelyContext);
|
|
76
|
+
if (!client) {
|
|
77
|
+
throw new Error('useTogglelyClient must be used within a TogglelyProvider');
|
|
78
|
+
}
|
|
79
|
+
return client;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Get the current Togglely state
|
|
83
|
+
*/
|
|
84
|
+
function useTogglelyState() {
|
|
85
|
+
const { state } = useContext(TogglelyContext);
|
|
86
|
+
return state;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Check if Togglely is ready (toggles have been fetched at least once)
|
|
90
|
+
*/
|
|
91
|
+
function useTogglelyReady() {
|
|
92
|
+
const { state } = useContext(TogglelyContext);
|
|
93
|
+
return state.isReady;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Check if Togglely is in offline mode
|
|
97
|
+
*/
|
|
98
|
+
function useTogglelyOffline() {
|
|
99
|
+
const { state } = useContext(TogglelyContext);
|
|
100
|
+
return state.isOffline;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Hook to check if a boolean feature toggle is enabled
|
|
104
|
+
*/
|
|
105
|
+
function useToggle(key, defaultValue = false) {
|
|
106
|
+
const client = useTogglelyClient();
|
|
107
|
+
const [value, setValue] = useState(defaultValue);
|
|
108
|
+
useEffect(() => {
|
|
109
|
+
let mounted = true;
|
|
110
|
+
const checkToggle = async () => {
|
|
111
|
+
const result = await client.isEnabled(key, defaultValue);
|
|
112
|
+
if (mounted) {
|
|
113
|
+
setValue(result);
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
checkToggle();
|
|
117
|
+
// Re-check when toggles are updated
|
|
118
|
+
const unsubscribe = client.on('update', checkToggle);
|
|
119
|
+
return () => {
|
|
120
|
+
mounted = false;
|
|
121
|
+
unsubscribe();
|
|
122
|
+
};
|
|
123
|
+
}, [client, key, defaultValue]);
|
|
124
|
+
return value;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Hook to get a string toggle value
|
|
128
|
+
*/
|
|
129
|
+
function useStringToggle(key, defaultValue = '') {
|
|
130
|
+
const client = useTogglelyClient();
|
|
131
|
+
const [value, setValue] = useState(defaultValue);
|
|
132
|
+
useEffect(() => {
|
|
133
|
+
let mounted = true;
|
|
134
|
+
const getValue = async () => {
|
|
135
|
+
const result = await client.getString(key, defaultValue);
|
|
136
|
+
if (mounted) {
|
|
137
|
+
setValue(result);
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
getValue();
|
|
141
|
+
const unsubscribe = client.on('update', getValue);
|
|
142
|
+
return () => {
|
|
143
|
+
mounted = false;
|
|
144
|
+
unsubscribe();
|
|
145
|
+
};
|
|
146
|
+
}, [client, key, defaultValue]);
|
|
147
|
+
return value;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Hook to get a number toggle value
|
|
151
|
+
*/
|
|
152
|
+
function useNumberToggle(key, defaultValue = 0) {
|
|
153
|
+
const client = useTogglelyClient();
|
|
154
|
+
const [value, setValue] = useState(defaultValue);
|
|
155
|
+
useEffect(() => {
|
|
156
|
+
let mounted = true;
|
|
157
|
+
const getValue = async () => {
|
|
158
|
+
const result = await client.getNumber(key, defaultValue);
|
|
159
|
+
if (mounted) {
|
|
160
|
+
setValue(result);
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
getValue();
|
|
164
|
+
const unsubscribe = client.on('update', getValue);
|
|
165
|
+
return () => {
|
|
166
|
+
mounted = false;
|
|
167
|
+
unsubscribe();
|
|
168
|
+
};
|
|
169
|
+
}, [client, key, defaultValue]);
|
|
170
|
+
return value;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Hook to get a JSON toggle value
|
|
174
|
+
*/
|
|
175
|
+
function useJSONToggle(key, defaultValue = {}) {
|
|
176
|
+
const client = useTogglelyClient();
|
|
177
|
+
const [value, setValue] = useState(defaultValue);
|
|
178
|
+
useEffect(() => {
|
|
179
|
+
let mounted = true;
|
|
180
|
+
const getValue = async () => {
|
|
181
|
+
const result = await client.getJSON(key, defaultValue);
|
|
182
|
+
if (mounted) {
|
|
183
|
+
setValue(result);
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
getValue();
|
|
187
|
+
const unsubscribe = client.on('update', getValue);
|
|
188
|
+
return () => {
|
|
189
|
+
mounted = false;
|
|
190
|
+
unsubscribe();
|
|
191
|
+
};
|
|
192
|
+
}, [client, key, defaultValue]);
|
|
193
|
+
return value;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Hook to get all toggles
|
|
197
|
+
*/
|
|
198
|
+
function useToggles() {
|
|
199
|
+
const client = useTogglelyClient();
|
|
200
|
+
const [toggles, setToggles] = useState({});
|
|
201
|
+
useEffect(() => {
|
|
202
|
+
const updateToggles = () => {
|
|
203
|
+
setToggles(client.getAllToggles());
|
|
204
|
+
};
|
|
205
|
+
updateToggles();
|
|
206
|
+
const unsubscribe = client.on('update', updateToggles);
|
|
207
|
+
return () => unsubscribe();
|
|
208
|
+
}, [client]);
|
|
209
|
+
return toggles;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Hook to set context for toggle evaluation
|
|
213
|
+
*/
|
|
214
|
+
function useTogglelyContext() {
|
|
215
|
+
const client = useTogglelyClient();
|
|
216
|
+
const [context, setContextState] = useState({});
|
|
217
|
+
const setContext = useCallback((newContext) => {
|
|
218
|
+
client.setContext(newContext);
|
|
219
|
+
setContextState(client.getContext());
|
|
220
|
+
}, [client]);
|
|
221
|
+
const clearContext = useCallback(() => {
|
|
222
|
+
client.clearContext();
|
|
223
|
+
setContextState({});
|
|
224
|
+
}, [client]);
|
|
225
|
+
return { setContext, clearContext, context };
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Component to conditionally render content based on a feature toggle
|
|
229
|
+
*/
|
|
230
|
+
function FeatureToggle({ toggle, children, fallback = null, defaultValue = false }) {
|
|
231
|
+
const isEnabled = useToggle(toggle, defaultValue);
|
|
232
|
+
return React.createElement(React.Fragment, null, isEnabled ? children : fallback);
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Case component for FeatureToggleSwitch
|
|
236
|
+
*/
|
|
237
|
+
function FeatureToggleCase({ children }) {
|
|
238
|
+
return React.createElement(React.Fragment, null, children);
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Switch component for feature toggles with multiple cases
|
|
242
|
+
*/
|
|
243
|
+
function FeatureToggleSwitch({ toggle, defaultValue = false, children }) {
|
|
244
|
+
const isEnabled = useToggle(toggle, defaultValue);
|
|
245
|
+
let match = null;
|
|
246
|
+
let defaultCase = null;
|
|
247
|
+
React.Children.forEach(children, (child) => {
|
|
248
|
+
if (!React.isValidElement(child))
|
|
249
|
+
return;
|
|
250
|
+
if (child.type === FeatureToggleCase) {
|
|
251
|
+
const { when, children: caseChildren } = child.props;
|
|
252
|
+
if (when === isEnabled) {
|
|
253
|
+
match = caseChildren;
|
|
254
|
+
}
|
|
255
|
+
if (when === undefined) {
|
|
256
|
+
defaultCase = caseChildren;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
return React.createElement(React.Fragment, null, match ?? defaultCase);
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Higher-order component to wrap a component with feature toggle check
|
|
264
|
+
*/
|
|
265
|
+
function withFeatureToggle(Component, options) {
|
|
266
|
+
return function WithFeatureToggleWrapper(props) {
|
|
267
|
+
const isEnabled = useToggle(options.toggle, options.defaultValue ?? false);
|
|
268
|
+
if (!isEnabled) {
|
|
269
|
+
if (options.fallback) {
|
|
270
|
+
return React.createElement(options.fallback, { ...props });
|
|
271
|
+
}
|
|
272
|
+
return null;
|
|
273
|
+
}
|
|
274
|
+
return React.createElement(Component, { ...props });
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
// ==================== Suspense Integration ====================
|
|
278
|
+
/**
|
|
279
|
+
* Hook that suspends until toggles are ready
|
|
280
|
+
* Use with React.Suspense
|
|
281
|
+
*/
|
|
282
|
+
function useTogglelySuspense() {
|
|
283
|
+
const client = useTogglelyClient();
|
|
284
|
+
const state = useTogglelyState();
|
|
285
|
+
if (!state.isReady) {
|
|
286
|
+
throw new Promise((resolve) => {
|
|
287
|
+
const unsubscribe = client.on('ready', () => {
|
|
288
|
+
unsubscribe();
|
|
289
|
+
resolve();
|
|
290
|
+
});
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
return client;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
export { FeatureToggle, FeatureToggleCase, FeatureToggleSwitch, TogglelyProvider, useJSONToggle, useNumberToggle, useStringToggle, useToggle, useTogglelyClient, useTogglelyContext, useTogglelyOffline, useTogglelyReady, useTogglelyState, useTogglelySuspense, useToggles, withFeatureToggle };
|
|
297
|
+
//# sourceMappingURL=index.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../src/index.tsx"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var React = require('react');
|
|
4
|
+
var sdkCore = require('@togglely/sdk-core');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Togglely React SDK
|
|
8
|
+
*
|
|
9
|
+
* Provides React hooks and context for feature toggles
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* ```tsx
|
|
13
|
+
* import { TogglelyProvider, useToggle, useToggles } from '@togglely/sdk-react';
|
|
14
|
+
*
|
|
15
|
+
* function App() {
|
|
16
|
+
* return (
|
|
17
|
+
* <TogglelyProvider
|
|
18
|
+
* apiKey="your-api-key"
|
|
19
|
+
* environment="production"
|
|
20
|
+
* baseUrl="https://your-togglely-instance.com"
|
|
21
|
+
* >
|
|
22
|
+
* <MyComponent />
|
|
23
|
+
* </TogglelyProvider>
|
|
24
|
+
* );
|
|
25
|
+
* }
|
|
26
|
+
*
|
|
27
|
+
* function MyComponent() {
|
|
28
|
+
* const isEnabled = useToggle('new-feature', false);
|
|
29
|
+
*
|
|
30
|
+
* return isEnabled ? <NewFeature /> : <OldFeature />;
|
|
31
|
+
* }
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
const TogglelyContext = React.createContext({
|
|
35
|
+
client: null,
|
|
36
|
+
state: {
|
|
37
|
+
isReady: false,
|
|
38
|
+
isOffline: false,
|
|
39
|
+
lastError: null,
|
|
40
|
+
lastFetch: null
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
function TogglelyProvider({ children, initialToggles, offlineFallback = true, ...config }) {
|
|
44
|
+
const [client] = React.useState(() => new sdkCore.TogglelyClient({
|
|
45
|
+
...config,
|
|
46
|
+
offlineFallback
|
|
47
|
+
}));
|
|
48
|
+
const [state, setState] = React.useState(client.getState());
|
|
49
|
+
React.useEffect(() => {
|
|
50
|
+
// Inject initial toggles for SSR if provided
|
|
51
|
+
if (initialToggles && typeof window !== 'undefined') {
|
|
52
|
+
window.__TOGGLELY_TOGGLES = initialToggles;
|
|
53
|
+
}
|
|
54
|
+
// Listen to all events
|
|
55
|
+
const unsubscribeReady = client.on('ready', (newState) => setState(newState));
|
|
56
|
+
const unsubscribeUpdate = client.on('update', (newState) => setState(newState));
|
|
57
|
+
const unsubscribeError = client.on('error', (newState) => setState(newState));
|
|
58
|
+
const unsubscribeOffline = client.on('offline', (newState) => setState(newState));
|
|
59
|
+
const unsubscribeOnline = client.on('online', (newState) => setState(newState));
|
|
60
|
+
return () => {
|
|
61
|
+
unsubscribeReady();
|
|
62
|
+
unsubscribeUpdate();
|
|
63
|
+
unsubscribeError();
|
|
64
|
+
unsubscribeOffline();
|
|
65
|
+
unsubscribeOnline();
|
|
66
|
+
client.destroy();
|
|
67
|
+
};
|
|
68
|
+
}, [client, initialToggles]);
|
|
69
|
+
return (React.createElement(TogglelyContext.Provider, { value: { client, state } }, children));
|
|
70
|
+
}
|
|
71
|
+
// ==================== Hooks ====================
|
|
72
|
+
/**
|
|
73
|
+
* Get the Togglely client instance
|
|
74
|
+
*/
|
|
75
|
+
function useTogglelyClient() {
|
|
76
|
+
const { client } = React.useContext(TogglelyContext);
|
|
77
|
+
if (!client) {
|
|
78
|
+
throw new Error('useTogglelyClient must be used within a TogglelyProvider');
|
|
79
|
+
}
|
|
80
|
+
return client;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Get the current Togglely state
|
|
84
|
+
*/
|
|
85
|
+
function useTogglelyState() {
|
|
86
|
+
const { state } = React.useContext(TogglelyContext);
|
|
87
|
+
return state;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Check if Togglely is ready (toggles have been fetched at least once)
|
|
91
|
+
*/
|
|
92
|
+
function useTogglelyReady() {
|
|
93
|
+
const { state } = React.useContext(TogglelyContext);
|
|
94
|
+
return state.isReady;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Check if Togglely is in offline mode
|
|
98
|
+
*/
|
|
99
|
+
function useTogglelyOffline() {
|
|
100
|
+
const { state } = React.useContext(TogglelyContext);
|
|
101
|
+
return state.isOffline;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Hook to check if a boolean feature toggle is enabled
|
|
105
|
+
*/
|
|
106
|
+
function useToggle(key, defaultValue = false) {
|
|
107
|
+
const client = useTogglelyClient();
|
|
108
|
+
const [value, setValue] = React.useState(defaultValue);
|
|
109
|
+
React.useEffect(() => {
|
|
110
|
+
let mounted = true;
|
|
111
|
+
const checkToggle = async () => {
|
|
112
|
+
const result = await client.isEnabled(key, defaultValue);
|
|
113
|
+
if (mounted) {
|
|
114
|
+
setValue(result);
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
checkToggle();
|
|
118
|
+
// Re-check when toggles are updated
|
|
119
|
+
const unsubscribe = client.on('update', checkToggle);
|
|
120
|
+
return () => {
|
|
121
|
+
mounted = false;
|
|
122
|
+
unsubscribe();
|
|
123
|
+
};
|
|
124
|
+
}, [client, key, defaultValue]);
|
|
125
|
+
return value;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Hook to get a string toggle value
|
|
129
|
+
*/
|
|
130
|
+
function useStringToggle(key, defaultValue = '') {
|
|
131
|
+
const client = useTogglelyClient();
|
|
132
|
+
const [value, setValue] = React.useState(defaultValue);
|
|
133
|
+
React.useEffect(() => {
|
|
134
|
+
let mounted = true;
|
|
135
|
+
const getValue = async () => {
|
|
136
|
+
const result = await client.getString(key, defaultValue);
|
|
137
|
+
if (mounted) {
|
|
138
|
+
setValue(result);
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
getValue();
|
|
142
|
+
const unsubscribe = client.on('update', getValue);
|
|
143
|
+
return () => {
|
|
144
|
+
mounted = false;
|
|
145
|
+
unsubscribe();
|
|
146
|
+
};
|
|
147
|
+
}, [client, key, defaultValue]);
|
|
148
|
+
return value;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Hook to get a number toggle value
|
|
152
|
+
*/
|
|
153
|
+
function useNumberToggle(key, defaultValue = 0) {
|
|
154
|
+
const client = useTogglelyClient();
|
|
155
|
+
const [value, setValue] = React.useState(defaultValue);
|
|
156
|
+
React.useEffect(() => {
|
|
157
|
+
let mounted = true;
|
|
158
|
+
const getValue = async () => {
|
|
159
|
+
const result = await client.getNumber(key, defaultValue);
|
|
160
|
+
if (mounted) {
|
|
161
|
+
setValue(result);
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
getValue();
|
|
165
|
+
const unsubscribe = client.on('update', getValue);
|
|
166
|
+
return () => {
|
|
167
|
+
mounted = false;
|
|
168
|
+
unsubscribe();
|
|
169
|
+
};
|
|
170
|
+
}, [client, key, defaultValue]);
|
|
171
|
+
return value;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Hook to get a JSON toggle value
|
|
175
|
+
*/
|
|
176
|
+
function useJSONToggle(key, defaultValue = {}) {
|
|
177
|
+
const client = useTogglelyClient();
|
|
178
|
+
const [value, setValue] = React.useState(defaultValue);
|
|
179
|
+
React.useEffect(() => {
|
|
180
|
+
let mounted = true;
|
|
181
|
+
const getValue = async () => {
|
|
182
|
+
const result = await client.getJSON(key, defaultValue);
|
|
183
|
+
if (mounted) {
|
|
184
|
+
setValue(result);
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
getValue();
|
|
188
|
+
const unsubscribe = client.on('update', getValue);
|
|
189
|
+
return () => {
|
|
190
|
+
mounted = false;
|
|
191
|
+
unsubscribe();
|
|
192
|
+
};
|
|
193
|
+
}, [client, key, defaultValue]);
|
|
194
|
+
return value;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Hook to get all toggles
|
|
198
|
+
*/
|
|
199
|
+
function useToggles() {
|
|
200
|
+
const client = useTogglelyClient();
|
|
201
|
+
const [toggles, setToggles] = React.useState({});
|
|
202
|
+
React.useEffect(() => {
|
|
203
|
+
const updateToggles = () => {
|
|
204
|
+
setToggles(client.getAllToggles());
|
|
205
|
+
};
|
|
206
|
+
updateToggles();
|
|
207
|
+
const unsubscribe = client.on('update', updateToggles);
|
|
208
|
+
return () => unsubscribe();
|
|
209
|
+
}, [client]);
|
|
210
|
+
return toggles;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Hook to set context for toggle evaluation
|
|
214
|
+
*/
|
|
215
|
+
function useTogglelyContext() {
|
|
216
|
+
const client = useTogglelyClient();
|
|
217
|
+
const [context, setContextState] = React.useState({});
|
|
218
|
+
const setContext = React.useCallback((newContext) => {
|
|
219
|
+
client.setContext(newContext);
|
|
220
|
+
setContextState(client.getContext());
|
|
221
|
+
}, [client]);
|
|
222
|
+
const clearContext = React.useCallback(() => {
|
|
223
|
+
client.clearContext();
|
|
224
|
+
setContextState({});
|
|
225
|
+
}, [client]);
|
|
226
|
+
return { setContext, clearContext, context };
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Component to conditionally render content based on a feature toggle
|
|
230
|
+
*/
|
|
231
|
+
function FeatureToggle({ toggle, children, fallback = null, defaultValue = false }) {
|
|
232
|
+
const isEnabled = useToggle(toggle, defaultValue);
|
|
233
|
+
return React.createElement(React.Fragment, null, isEnabled ? children : fallback);
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Case component for FeatureToggleSwitch
|
|
237
|
+
*/
|
|
238
|
+
function FeatureToggleCase({ children }) {
|
|
239
|
+
return React.createElement(React.Fragment, null, children);
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Switch component for feature toggles with multiple cases
|
|
243
|
+
*/
|
|
244
|
+
function FeatureToggleSwitch({ toggle, defaultValue = false, children }) {
|
|
245
|
+
const isEnabled = useToggle(toggle, defaultValue);
|
|
246
|
+
let match = null;
|
|
247
|
+
let defaultCase = null;
|
|
248
|
+
React.Children.forEach(children, (child) => {
|
|
249
|
+
if (!React.isValidElement(child))
|
|
250
|
+
return;
|
|
251
|
+
if (child.type === FeatureToggleCase) {
|
|
252
|
+
const { when, children: caseChildren } = child.props;
|
|
253
|
+
if (when === isEnabled) {
|
|
254
|
+
match = caseChildren;
|
|
255
|
+
}
|
|
256
|
+
if (when === undefined) {
|
|
257
|
+
defaultCase = caseChildren;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
return React.createElement(React.Fragment, null, match ?? defaultCase);
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Higher-order component to wrap a component with feature toggle check
|
|
265
|
+
*/
|
|
266
|
+
function withFeatureToggle(Component, options) {
|
|
267
|
+
return function WithFeatureToggleWrapper(props) {
|
|
268
|
+
const isEnabled = useToggle(options.toggle, options.defaultValue ?? false);
|
|
269
|
+
if (!isEnabled) {
|
|
270
|
+
if (options.fallback) {
|
|
271
|
+
return React.createElement(options.fallback, { ...props });
|
|
272
|
+
}
|
|
273
|
+
return null;
|
|
274
|
+
}
|
|
275
|
+
return React.createElement(Component, { ...props });
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
// ==================== Suspense Integration ====================
|
|
279
|
+
/**
|
|
280
|
+
* Hook that suspends until toggles are ready
|
|
281
|
+
* Use with React.Suspense
|
|
282
|
+
*/
|
|
283
|
+
function useTogglelySuspense() {
|
|
284
|
+
const client = useTogglelyClient();
|
|
285
|
+
const state = useTogglelyState();
|
|
286
|
+
if (!state.isReady) {
|
|
287
|
+
throw new Promise((resolve) => {
|
|
288
|
+
const unsubscribe = client.on('ready', () => {
|
|
289
|
+
unsubscribe();
|
|
290
|
+
resolve();
|
|
291
|
+
});
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
return client;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
Object.defineProperty(exports, "TogglelyClient", {
|
|
298
|
+
enumerable: true,
|
|
299
|
+
get: function () { return sdkCore.TogglelyClient; }
|
|
300
|
+
});
|
|
301
|
+
Object.defineProperty(exports, "createOfflineTogglesScript", {
|
|
302
|
+
enumerable: true,
|
|
303
|
+
get: function () { return sdkCore.createOfflineTogglesScript; }
|
|
304
|
+
});
|
|
305
|
+
Object.defineProperty(exports, "togglesToEnvVars", {
|
|
306
|
+
enumerable: true,
|
|
307
|
+
get: function () { return sdkCore.togglesToEnvVars; }
|
|
308
|
+
});
|
|
309
|
+
exports.FeatureToggle = FeatureToggle;
|
|
310
|
+
exports.FeatureToggleCase = FeatureToggleCase;
|
|
311
|
+
exports.FeatureToggleSwitch = FeatureToggleSwitch;
|
|
312
|
+
exports.TogglelyProvider = TogglelyProvider;
|
|
313
|
+
exports.useJSONToggle = useJSONToggle;
|
|
314
|
+
exports.useNumberToggle = useNumberToggle;
|
|
315
|
+
exports.useStringToggle = useStringToggle;
|
|
316
|
+
exports.useToggle = useToggle;
|
|
317
|
+
exports.useTogglelyClient = useTogglelyClient;
|
|
318
|
+
exports.useTogglelyContext = useTogglelyContext;
|
|
319
|
+
exports.useTogglelyOffline = useTogglelyOffline;
|
|
320
|
+
exports.useTogglelyReady = useTogglelyReady;
|
|
321
|
+
exports.useTogglelyState = useTogglelyState;
|
|
322
|
+
exports.useTogglelySuspense = useTogglelySuspense;
|
|
323
|
+
exports.useToggles = useToggles;
|
|
324
|
+
exports.withFeatureToggle = withFeatureToggle;
|
|
325
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/index.tsx"],"sourcesContent":[null],"names":["createContext","useState","TogglelyClient","useEffect","useContext","useCallback"],"mappings":";;;;;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BG;AA2BH,MAAM,eAAe,GAAGA,mBAAa,CAAuB;AAC1D,IAAA,MAAM,EAAE,IAAI;AACZ,IAAA,KAAK,EAAE;AACL,QAAA,OAAO,EAAE,KAAK;AACd,QAAA,SAAS,EAAE,KAAK;AAChB,QAAA,SAAS,EAAE,IAAI;AACf,QAAA,SAAS,EAAE;AACZ;AACF,CAAA,CAAC;AAYI,SAAU,gBAAgB,CAAC,EAC/B,QAAQ,EACR,cAAc,EACd,eAAe,GAAG,IAAI,EACtB,GAAG,MAAM,EACa,EAAA;IACtB,MAAM,CAAC,MAAM,CAAC,GAAGC,cAAQ,CAAC,MAAM,IAAIC,sBAAc,CAAC;AACjD,QAAA,GAAG,MAAM;QACT;AACD,KAAA,CAAC,CAAC;AAEH,IAAA,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAGD,cAAQ,CAAgB,MAAM,CAAC,QAAQ,EAAE,CAAC;IAEpEE,eAAS,CAAC,MAAK;;AAEb,QAAA,IAAI,cAAc,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;AAClD,YAAA,MAAc,CAAC,kBAAkB,GAAG,cAAc;QACrD;;AAGA,QAAA,MAAM,gBAAgB,GAAG,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,QAAQ,KAAK,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAC7E,QAAA,MAAM,iBAAiB,GAAG,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,KAAK,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAC/E,QAAA,MAAM,gBAAgB,GAAG,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,QAAQ,KAAK,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAC7E,QAAA,MAAM,kBAAkB,GAAG,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,QAAQ,KAAK,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACjF,QAAA,MAAM,iBAAiB,GAAG,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,KAAK,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAE/E,QAAA,OAAO,MAAK;AACV,YAAA,gBAAgB,EAAE;AAClB,YAAA,iBAAiB,EAAE;AACnB,YAAA,gBAAgB,EAAE;AAClB,YAAA,kBAAkB,EAAE;AACpB,YAAA,iBAAiB,EAAE;YACnB,MAAM,CAAC,OAAO,EAAE;AAClB,QAAA,CAAC;AACH,IAAA,CAAC,EAAE,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;AAE5B,IAAA,QACE,KAAA,CAAA,aAAA,CAAC,eAAe,CAAC,QAAQ,IAAC,KAAK,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,IAC/C,QAAQ,CACgB;AAE/B;AAEA;AAEA;;AAEG;SACa,iBAAiB,GAAA;IAC/B,MAAM,EAAE,MAAM,EAAE,GAAGC,gBAAU,CAAC,eAAe,CAAC;IAC9C,IAAI,CAAC,MAAM,EAAE;AACX,QAAA,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC;IAC7E;AACA,IAAA,OAAO,MAAM;AACf;AAEA;;AAEG;SACa,gBAAgB,GAAA;IAC9B,MAAM,EAAE,KAAK,EAAE,GAAGA,gBAAU,CAAC,eAAe,CAAC;AAC7C,IAAA,OAAO,KAAK;AACd;AAEA;;AAEG;SACa,gBAAgB,GAAA;IAC9B,MAAM,EAAE,KAAK,EAAE,GAAGA,gBAAU,CAAC,eAAe,CAAC;IAC7C,OAAO,KAAK,CAAC,OAAO;AACtB;AAEA;;AAEG;SACa,kBAAkB,GAAA;IAChC,MAAM,EAAE,KAAK,EAAE,GAAGA,gBAAU,CAAC,eAAe,CAAC;IAC7C,OAAO,KAAK,CAAC,SAAS;AACxB;AAEA;;AAEG;SACa,SAAS,CAAC,GAAW,EAAE,eAAwB,KAAK,EAAA;AAClE,IAAA,MAAM,MAAM,GAAG,iBAAiB,EAAE;IAClC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAGH,cAAQ,CAAC,YAAY,CAAC;IAEhDE,eAAS,CAAC,MAAK;QACb,IAAI,OAAO,GAAG,IAAI;AAElB,QAAA,MAAM,WAAW,GAAG,YAAW;YAC7B,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,YAAY,CAAC;YACxD,IAAI,OAAO,EAAE;gBACX,QAAQ,CAAC,MAAM,CAAC;YAClB;AACF,QAAA,CAAC;AAED,QAAA,WAAW,EAAE;;QAGb,MAAM,WAAW,GAAG,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,WAAW,CAAC;AAEpD,QAAA,OAAO,MAAK;YACV,OAAO,GAAG,KAAK;AACf,YAAA,WAAW,EAAE;AACf,QAAA,CAAC;IACH,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,YAAY,CAAC,CAAC;AAE/B,IAAA,OAAO,KAAK;AACd;AAEA;;AAEG;SACa,eAAe,CAAC,GAAW,EAAE,eAAuB,EAAE,EAAA;AACpE,IAAA,MAAM,MAAM,GAAG,iBAAiB,EAAE;IAClC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAGF,cAAQ,CAAC,YAAY,CAAC;IAEhDE,eAAS,CAAC,MAAK;QACb,IAAI,OAAO,GAAG,IAAI;AAElB,QAAA,MAAM,QAAQ,GAAG,YAAW;YAC1B,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,YAAY,CAAC;YACxD,IAAI,OAAO,EAAE;gBACX,QAAQ,CAAC,MAAM,CAAC;YAClB;AACF,QAAA,CAAC;AAED,QAAA,QAAQ,EAAE;QAEV,MAAM,WAAW,GAAG,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC;AAEjD,QAAA,OAAO,MAAK;YACV,OAAO,GAAG,KAAK;AACf,YAAA,WAAW,EAAE;AACf,QAAA,CAAC;IACH,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,YAAY,CAAC,CAAC;AAE/B,IAAA,OAAO,KAAK;AACd;AAEA;;AAEG;SACa,eAAe,CAAC,GAAW,EAAE,eAAuB,CAAC,EAAA;AACnE,IAAA,MAAM,MAAM,GAAG,iBAAiB,EAAE;IAClC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAGF,cAAQ,CAAC,YAAY,CAAC;IAEhDE,eAAS,CAAC,MAAK;QACb,IAAI,OAAO,GAAG,IAAI;AAElB,QAAA,MAAM,QAAQ,GAAG,YAAW;YAC1B,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,YAAY,CAAC;YACxD,IAAI,OAAO,EAAE;gBACX,QAAQ,CAAC,MAAM,CAAC;YAClB;AACF,QAAA,CAAC;AAED,QAAA,QAAQ,EAAE;QAEV,MAAM,WAAW,GAAG,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC;AAEjD,QAAA,OAAO,MAAK;YACV,OAAO,GAAG,KAAK;AACf,YAAA,WAAW,EAAE;AACf,QAAA,CAAC;IACH,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,YAAY,CAAC,CAAC;AAE/B,IAAA,OAAO,KAAK;AACd;AAEA;;AAEG;SACa,aAAa,CAAU,GAAW,EAAE,eAAkB,EAAO,EAAA;AAC3E,IAAA,MAAM,MAAM,GAAG,iBAAiB,EAAE;IAClC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAGF,cAAQ,CAAI,YAAY,CAAC;IAEnDE,eAAS,CAAC,MAAK;QACb,IAAI,OAAO,GAAG,IAAI;AAElB,QAAA,MAAM,QAAQ,GAAG,YAAW;YAC1B,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAAI,GAAG,EAAE,YAAY,CAAC;YACzD,IAAI,OAAO,EAAE;gBACX,QAAQ,CAAC,MAAM,CAAC;YAClB;AACF,QAAA,CAAC;AAED,QAAA,QAAQ,EAAE;QAEV,MAAM,WAAW,GAAG,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC;AAEjD,QAAA,OAAO,MAAK;YACV,OAAO,GAAG,KAAK;AACf,YAAA,WAAW,EAAE;AACf,QAAA,CAAC;IACH,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,YAAY,CAAC,CAAC;AAE/B,IAAA,OAAO,KAAK;AACd;AAEA;;AAEG;SACa,UAAU,GAAA;AACxB,IAAA,MAAM,MAAM,GAAG,iBAAiB,EAAE;IAClC,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAGF,cAAQ,CAAmD,EAAE,CAAC;IAE5FE,eAAS,CAAC,MAAK;QACb,MAAM,aAAa,GAAG,MAAK;AACzB,YAAA,UAAU,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;AACpC,QAAA,CAAC;AAED,QAAA,aAAa,EAAE;QAEf,MAAM,WAAW,GAAG,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC;AAEtD,QAAA,OAAO,MAAM,WAAW,EAAE;AAC5B,IAAA,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;AAEZ,IAAA,OAAO,OAAO;AAChB;AAEA;;AAEG;SACa,kBAAkB,GAAA;AAKhC,IAAA,MAAM,MAAM,GAAG,iBAAiB,EAAE;IAClC,MAAM,CAAC,OAAO,EAAE,eAAe,CAAC,GAAGF,cAAQ,CAAgB,EAAE,CAAC;AAE9D,IAAA,MAAM,UAAU,GAAGI,iBAAW,CAAC,CAAC,UAAyB,KAAI;AAC3D,QAAA,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC;AAC7B,QAAA,eAAe,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;AACtC,IAAA,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;AAEZ,IAAA,MAAM,YAAY,GAAGA,iBAAW,CAAC,MAAK;QACpC,MAAM,CAAC,YAAY,EAAE;QACrB,eAAe,CAAC,EAAE,CAAC;AACrB,IAAA,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;AAEZ,IAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,EAAE;AAC9C;AAeA;;AAEG;AACG,SAAU,aAAa,CAAC,EAC5B,MAAM,EACN,QAAQ,EACR,QAAQ,GAAG,IAAI,EACf,YAAY,GAAG,KAAK,EACD,EAAA;IACnB,MAAM,SAAS,GAAG,SAAS,CAAC,MAAM,EAAE,YAAY,CAAC;IACjD,OAAO,KAAA,CAAA,aAAA,CAAA,KAAA,CAAA,QAAA,EAAA,IAAA,EAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAI;AAC/C;AAkBA;;AAEG;AACG,SAAU,iBAAiB,CAAC,EAAE,QAAQ,EAA0B,EAAA;IACpE,OAAO,KAAA,CAAA,aAAA,CAAA,KAAA,CAAA,QAAA,EAAA,IAAA,EAAG,QAAQ,CAAI;AACxB;AAEA;;AAEG;AACG,SAAU,mBAAmB,CAAC,EAClC,MAAM,EACN,YAAY,GAAG,KAAK,EACpB,QAAQ,EACiB,EAAA;IACzB,MAAM,SAAS,GAAG,SAAS,CAAC,MAAM,EAAE,YAAY,CAAC;IAEjD,IAAI,KAAK,GAAc,IAAI;IAC3B,IAAI,WAAW,GAAc,IAAI;IAEjC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,KAAK,KAAI;AACzC,QAAA,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC;YAAE;AAElC,QAAA,IAAI,KAAK,CAAC,IAAI,KAAK,iBAAiB,EAAE;YACpC,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,KAAK,CAAC,KAAK;AACpD,YAAA,IAAI,IAAI,KAAK,SAAS,EAAE;gBACtB,KAAK,GAAG,YAAY;YACtB;AACA,YAAA,IAAI,IAAI,KAAK,SAAS,EAAE;gBACtB,WAAW,GAAG,YAAY;YAC5B;QACF;AACF,IAAA,CAAC,CAAC;AAEF,IAAA,OAAO,KAAA,CAAA,aAAA,CAAA,KAAA,CAAA,QAAA,EAAA,IAAA,EAAG,KAAK,IAAI,WAAW,CAAI;AACpC;AAUA;;AAEG;AACG,SAAU,iBAAiB,CAC/B,SAAiC,EACjC,OAAiC,EAAA;IAEjC,OAAO,SAAS,wBAAwB,CAAC,KAAQ,EAAA;AAC/C,QAAA,MAAM,SAAS,GAAG,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,YAAY,IAAI,KAAK,CAAC;QAE1E,IAAI,CAAC,SAAS,EAAE;AACd,YAAA,IAAI,OAAO,CAAC,QAAQ,EAAE;AACpB,gBAAA,OAAO,oBAAC,OAAO,CAAC,QAAQ,EAAA,EAAA,GAAK,KAAK,GAAI;YACxC;AACA,YAAA,OAAO,IAAI;QACb;AAEA,QAAA,OAAO,KAAA,CAAA,aAAA,CAAC,SAAS,EAAA,EAAA,GAAK,KAAK,GAAI;AACjC,IAAA,CAAC;AACH;AAEA;AAEA;;;AAGG;SACa,mBAAmB,GAAA;AACjC,IAAA,MAAM,MAAM,GAAG,iBAAiB,EAAE;AAClC,IAAA,MAAM,KAAK,GAAG,gBAAgB,EAAE;AAEhC,IAAA,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE;AAClB,QAAA,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,KAAI;YAClC,MAAM,WAAW,GAAG,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAK;AAC1C,gBAAA,WAAW,EAAE;AACb,gBAAA,OAAO,EAAE;AACX,YAAA,CAAC,CAAC;AACJ,QAAA,CAAC,CAAC;IACJ;AAEA,IAAA,OAAO,MAAM;AACf;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|