🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@unleash/toolbar

Package Overview
Dependencies
Maintainers
9
Versions
3
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@unleash/toolbar - npm Package Compare versions

Comparing version
1.0.0
to
1.1.0
+12
-3
package.json
{
"name": "@unleash/toolbar",
"version": "1.0.0",
"version": "1.1.0",
"description": "Client-side override toolbar for Unleash JavaScript SDKs",

@@ -60,2 +60,6 @@ "type": "module",

"author": "Unleash",
"repository": {
"type": "git",
"url": "https://github.com/Unleash/toolbar"
},
"bugs": {

@@ -93,3 +97,3 @@ "url": "https://github.com/Unleash/toolbar/issues"

"jsdom": "^27.3.0",
"postcss": "^8.5.6",
"postcss": "^8.5.12",
"react": "^18.3.1 || ^19.2.3",

@@ -102,3 +106,3 @@ "react-dom": "^18.3.1 || ^19.2.3",

"unleash-proxy-client": "^3.4.1",
"vite": "^7.2.7",
"vite": "^8.0.16",
"vite-plugin-dts": "^4.5.4",

@@ -109,3 +113,8 @@ "vitest": "^4.0.15"

"lit": "^3.3.1"
},
"overrides": {
"next": {
"postcss": "^8.5.12"
}
}
}
+28
-6

@@ -5,2 +5,4 @@ # Unleash Toolbar

![Unleash Toolbar Screenshot](toolbar.png)
## Features

@@ -14,2 +16,4 @@

- **Customizable UI**: Theming support and positioning options
- **Draggable & Dismissible**: Drag the floating icon to any window edge, minimize to the icon, or hide it entirely until the next page refresh
- **Custom Banner**: Optional message in the toolbar to clarify its scope for your team
- **SDK Compatible**: Works with Unleash JavaScript SDK

@@ -21,6 +25,6 @@

- **Core**: ~8 KB gzipped
- **React**: ~0.2 KB gzipped (thin wrapper)
- **Next.js**: ~0.6 KB gzipped (server utilities)
- **CSS**: ~2.4 KB gzipped
- **Core**: ~9.5 KB gzipped
- **React**: ~0.6 KB gzipped (thin wrapper)
- **Next.js**: ~0.7 KB gzipped (server utilities)
- **CSS**: ~2.7 KB gzipped

@@ -153,4 +157,4 @@ ## Installation

```
```
### Next.js App Router (Client & Server Components)

@@ -240,2 +244,3 @@

**Environment Variables for Next.js:**
```env

@@ -304,7 +309,24 @@ # Used by @unleash/nextjs SDK

// Side positions (vertically centered): 'left' | 'right'
// Used as the starting position; overridden once the user drags the toolbar.
position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'left' | 'right';
// Allow dragging the floating icon to reposition the toolbar along any
// window edge. The chosen position is persisted. (default: true)
draggable?: boolean;
// Initial visibility (default: false, but respects persisted state if available)
initiallyVisible?: boolean;
// Optional informational message shown as a banner below the header.
// Useful for clarifying the toolbar's scope to your team, e.g.
// "Only client-side flags are overridable here". Empty by default.
banner?: string;
// Optional URL shown as a link next to the banner message (opens in a new
// tab). Only rendered when `banner` is also set.
bannerLink?: string;
// Text for the banner link (default: "Read more"). Only used with bannerLink.
bannerLinkText?: string;
// Sort flags alphabetically instead of by evaluation order (default: false)

@@ -595,3 +617,3 @@ sortAlphabetically?: boolean;

- [Unleash Documentation](https://docs.getunleash.io/)
- [Unleash Toolbar Documentation](https://docs.getunleash.io/integrate/toolbar)
- [Unleash JavaScript SDK](https://github.com/Unleash/unleash-proxy-client-js)

@@ -598,0 +620,0 @@ - [Unleash React SDK](https://github.com/Unleash/proxy-client-react)

interface GlobalWithLit {
litIssuedWarnings?: Set<string>;
}
declare const g: GlobalWithLit;
//# sourceMappingURL=setup.d.ts.map
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/__tests__/setup.ts"],"names":[],"mappings":"AAGA,UAAU,aAAa;IACrB,iBAAiB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACjC;AAED,QAAA,MAAM,CAAC,EAA4B,aAAa,CAAC"}
import { UnleashClient } from 'unleash-proxy-client';
import { ToolbarStateManager } from './state';
import { FlagOverride, InitToolbarOptions, ToolbarState, UnleashContext, UnleashToolbarInstance, WrappedUnleashClient } from './types';
/**
* Main toolbar instance implementation
*/
export declare class UnleashToolbar implements UnleashToolbarInstance {
private stateManager;
private ui;
readonly client: WrappedUnleashClient;
constructor(stateManager: ToolbarStateManager, wrappedClient: WrappedUnleashClient, options: InitToolbarOptions);
private initUI;
show(): void;
hide(): void;
destroy(): void;
getState(): ToolbarState;
getFlagNames(): string[];
setFlagOverride(name: string, override: FlagOverride | null): void;
setContextOverride(context: Partial<UnleashContext>): void;
removeContextOverride(fieldName: keyof UnleashContext): void;
resetOverrides(): void;
resetContextOverrides(): void;
}
/**
* Initialize the Unleash Toolbar with a client
* This is the main entry point - handles both toolbar creation and client wrapping
* Returns the wrapped client directly for immediate use
*
* @param client - The Unleash client to wrap
* @param options - Toolbar configuration options
*/
export declare function initUnleashToolbar(client: UnleashClient, options?: InitToolbarOptions): WrappedUnleashClient;
export { ToolbarStateManager } from './state';
export * from './types';
export { wrapUnleashClient } from './wrapper';
//# sourceMappingURL=index.d.ts.map
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,KAAK,EACV,YAAY,EACZ,kBAAkB,EAElB,YAAY,EACZ,cAAc,EACd,sBAAsB,EACtB,oBAAoB,EACrB,MAAM,SAAS,CAAC;AAGjB;;GAEG;AACH,qBAAa,cAAe,YAAW,sBAAsB;IAC3D,OAAO,CAAC,YAAY,CAAsB;IAC1C,OAAO,CAAC,EAAE,CAAoB;IAC9B,SAAgB,MAAM,EAAE,oBAAoB,CAAC;gBAG3C,YAAY,EAAE,mBAAmB,EACjC,aAAa,EAAE,oBAAoB,EACnC,OAAO,EAAE,kBAAkB;YAUf,MAAM;IASpB,IAAI,IAAI,IAAI;IAIZ,IAAI,IAAI,IAAI;IAIZ,OAAO,IAAI,IAAI;IAKf,QAAQ,IAAI,YAAY;IAIxB,YAAY,IAAI,MAAM,EAAE;IAIxB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,GAAG,IAAI,GAAG,IAAI;IAIlE,kBAAkB,CAAC,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI;IAI1D,qBAAqB,CAAC,SAAS,EAAE,MAAM,cAAc,GAAG,IAAI;IAI5D,cAAc,IAAI,IAAI;IAItB,qBAAqB,IAAI,IAAI;CAG9B;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,aAAa,EACrB,OAAO,GAAE,kBAAuB,GAC/B,oBAAoB,CAuBtB;AAUD,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAE9C,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC"}
class e{listeners=/* @__PURE__ */new Set;subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}emit(e){this.listeners.forEach(t=>{try{t(e)}catch(a){console.error("[Unleash Toolbar] Error in event listener:",a)}})}}class t{constructor(e,t){this.mode=e,this.key=t}enableCookieSync=!1;setCookieSyncEnabled(e){this.enableCookieSync=e}getStorage(){if("undefined"==typeof window)return null;switch(this.mode){case"local":return window.localStorage;case"session":return window.sessionStorage;default:return null}}syncToCookies(e){if(this.enableCookieSync&&"undefined"!=typeof document)try{!async function(e,t){if("undefined"==typeof document)return;const a=encodeURIComponent(t);if("cookieStore"in window)try{return void(await window.cookieStore.set({name:e,value:a,path:"/",sameSite:"lax",expires:Date.now()+6048e5}))}catch{}document.cookie=[`${e}=${a}`,"path=/","max-age=604800","SameSite=Lax"].join("; ")}("unleash-toolbar-state",JSON.stringify(e))}catch(t){console.error("[Unleash Toolbar] Failed to sync state to cookies:",t)}}load(){const e=this.getStorage();if(!e)return null;try{const t=e.getItem(this.key);return t?JSON.parse(t):null}catch(t){return console.error("[Unleash Toolbar] Failed to load state from storage:",t),null}}save(e){const t=this.getStorage();if(t)try{t.setItem(this.key,JSON.stringify(e)),this.syncToCookies(e)}catch(a){console.error("[Unleash Toolbar] Failed to save state to storage:",a)}}clear(){const e=this.getStorage();if(e)try{e.removeItem(this.key),this.enableCookieSync&&async function(e){if("undefined"!=typeof document){if("cookieStore"in window)try{return void(await window.cookieStore.delete(e))}catch{}document.cookie=`${e}=; path=/; max-age=0`}}("unleash-toolbar-state")}catch(t){console.error("[Unleash Toolbar] Failed to clear storage:",t)}}}class a{state;eventEmitter;storage;sortAlphabetically;constructor(a="local",s="unleash-toolbar-state",r=!1){this.eventEmitter=new e,this.storage=new t(a,s),this.sortAlphabetically=r;const i=this.storage.load();this.state=i||this.getInitialState()}getInitialState(){return{flags:{},contextOverrides:{}}}persist(){this.storage.save(this.state)}applyOverride(e,t){return t?"flag"===t.type?t.value:"variant"===t.type?"object"==typeof e&&null!==e&&"name"in e?{...e,name:t.variantKey,enabled:!0}:{name:t.variantKey,enabled:!0}:t:e}reEvaluateAllFlags(e){Object.keys(this.state.flags).forEach(t=>{const a=this.state.flags[t];if(a)try{const{defaultValue:s,effectiveValue:r}=e(t);this.state.flags[t]={...a,lastDefaultValue:s,lastEffectiveValue:r}}catch(s){console.error(`[Unleash Toolbar] Failed to re-evaluate flag ${t}:`,s)}}),this.persist(),this.eventEmitter.emit({type:"sdk_updated",timestamp:Date.now()})}getState(){return JSON.parse(JSON.stringify(this.state))}subscribe(e){return this.eventEmitter.subscribe(e)}recordEvaluation(e,t,a,s,r){const i=this.state.flags[e],n=!i;this.state.flags[e]={flagType:t,lastDefaultValue:a,lastEffectiveValue:s,lastContext:r,override:i?.override||null},this.persist(),n&&this.eventEmitter.emit({type:"sdk_updated",timestamp:Date.now()})}setFlagOverride(e,t){this.state.flags[e]?(this.state.flags[e].override=t,this.state.flags[e].lastEffectiveValue=this.applyOverride(this.state.flags[e].lastDefaultValue,t)):this.state.flags[e]={flagType:"variant"===t?.type?"variant":"flag",lastDefaultValue:null,lastEffectiveValue:this.applyOverride(null,t),lastContext:null,override:t},this.persist(),this.eventEmitter.emit({type:"flag_override_changed",name:e,override:t,timestamp:Date.now()})}getFlagOverride(e){return this.state.flags[e]?.override||null}setContextOverride(e){this.state.contextOverrides={...this.state.contextOverrides,...e},this.persist(),this.eventEmitter.emit({type:"context_override_changed",contextOverrides:this.state.contextOverrides})}removeContextOverride(e){const t={...this.state.contextOverrides};delete t[e],this.state.contextOverrides=t,this.persist(),this.eventEmitter.emit({type:"context_override_changed",contextOverrides:this.state.contextOverrides})}getMergedContext(e={}){return{...e,...this.state.contextOverrides,properties:{...e.properties||{},...this.state.contextOverrides.properties||{}}}}resetOverrides(){Object.keys(this.state.flags).forEach(e=>{this.state.flags[e].override=null,this.state.flags[e].lastEffectiveValue=this.state.flags[e].lastDefaultValue,this.eventEmitter.emit({type:"flag_override_changed",name:e,override:null,timestamp:Date.now()})}),this.persist()}resetContextOverrides(){this.state.contextOverrides={},this.persist(),this.eventEmitter.emit({type:"context_override_changed",contextOverrides:{}})}setVisibility(e){this.state.isVisible=e,this.persist()}getVisibility(){return this.state.isVisible}clearPersistence(){this.storage.clear()}getFlagNames(){const e=Object.keys(this.state.flags);return this.sortAlphabetically?e.sort():e}getFlagMetadata(e){return this.state.flags[e]||null}enableCookieSync(){this.storage.setCookieSyncEnabled(!0)}}function s(e,t){if("__original"in e)return e;const a=e.getContext(),s=/* @__PURE__ */new Set;let i;const n={__original:e,isEnabled:function(a){const s=e.getContext(),i=t.getMergedContext(s),n=e.isEnabled(a),o=r(n,t.getFlagOverride(a));return t.recordEvaluation(a,"flag",n,o,i),o},getVariant:function(a){const s=e.getContext(),i=t.getMergedContext(s),n=e.getVariant(a),o=r(n,t.getFlagOverride(a));return t.recordEvaluation(a,"variant",n,o,i),o},getContext:function(){const a=e.getContext();return{appName:"",...t.getMergedContext(a)}},on:function(t,a){return"update"===t&&s.add(a),e.on(t,a),i}};function o(){s.forEach(e=>{try{e()}catch(t){console.error("[Unleash Toolbar] Error in update listener:",t)}})}return e.on("update",()=>{t.reEvaluateAllFlags(a=>{const s=t.getFlagMetadata(a),i="variant"===s?.flagType?e.getVariant(a):e.isEnabled(a);return{defaultValue:i,effectiveValue:r(i,t.getFlagOverride(a))}})}),t.subscribe(s=>{if("context_override_changed"===s.type){const s=t.getMergedContext(a),{appName:i,environment:n,...l}=s;e.updateContext(l).then(()=>{t.reEvaluateAllFlags(a=>{const s=t.getFlagMetadata(a),i="variant"===s?.flagType?e.getVariant(a):e.isEnabled(a);return{defaultValue:i,effectiveValue:r(i,t.getFlagOverride(a))}}),o()}).catch(e=>{console.error("[Unleash Toolbar] Failed to update context:",e)})}"flag_override_changed"===s.type&&o()}),i=new Proxy(n,{get(t,a){if(a in t)return Reflect.get(t,a);const s=Reflect.get(e,a);return"function"==typeof s?s.bind(e):s},set:(t,a,s)=>a in t?(Reflect.set(t,a,s),!0):(Reflect.set(e,a,s),!0)}),i}function r(e,t){return t?"flag"===t.type?t.value:"variant"===t.type?"object"==typeof e&&null!==e&&"name"in e?{...e,name:t.variantKey,enabled:!0}:{name:t.variantKey,enabled:!0}:e:e}class i{stateManager;ui;client;constructor(e,t,a){this.stateManager=e,this.client=t,this.ui=null,this.initUI(e,t,a)}async initUI(e,t,a){const{ToolbarUI:s}=await import("./ui-LKEosjLO.js");this.ui=new s(e,t,a)}show(){this.ui&&this.ui.show()}hide(){this.ui&&this.ui.hide()}destroy(){this.ui&&this.ui.destroy(),this.stateManager.clearPersistence()}getState(){return this.stateManager.getState()}getFlagNames(){return this.stateManager.getFlagNames()}setFlagOverride(e,t){this.stateManager.setFlagOverride(e,t)}setContextOverride(e){this.stateManager.setContextOverride(e)}removeContextOverride(e){this.stateManager.removeContextOverride(e)}resetOverrides(){this.stateManager.resetOverrides()}resetContextOverrides(){this.stateManager.resetContextOverrides()}}function n(e,t={}){const r=t.enableCookieSync||!1,n=new a(t.storageMode||"local",t.storageKey||"unleash-toolbar-state",t.sortAlphabetically||!1);r&&n.enableCookieSync();const o=s(e,n),l=new i(n,o,t);return"undefined"!=typeof window&&(window.unleashToolbar=l),o}"undefined"!=typeof window&&(window.UnleashToolbar={init:n});export{a as ToolbarStateManager,i as UnleashToolbar,n as initUnleashToolbar,s as wrapUnleashClient};
//# sourceMappingURL=index.es.js.map
{"version":3,"file":"index.es.js","sources":["../src/state.ts","../src/wrapper.ts","../src/index.ts"],"sourcesContent":["import type {\n FlagMetadata,\n FlagOverride,\n FlagValue,\n StorageMode,\n ToolbarEvent,\n ToolbarEventListener,\n ToolbarState,\n UnleashContext,\n UnleashVariant,\n} from './types';\n\n/**\n * Helper to set a cookie with proper encoding\n */\nasync function setCookie(name: string, value: string, maxAgeSeconds: number): Promise<void> {\n if (typeof document === 'undefined') return;\n\n const encodedValue = encodeURIComponent(value);\n\n // Use Cookie Store API if available, fallback to document.cookie\n if ('cookieStore' in window) {\n try {\n await window.cookieStore.set({\n name,\n value: encodedValue,\n path: '/',\n sameSite: 'lax',\n expires: Date.now() + maxAgeSeconds * 1000,\n });\n return;\n } catch {\n // Fallback to document.cookie if Cookie Store API fails\n }\n }\n\n // Fallback for browsers without Cookie Store API\n const cookieParts = [\n `${name}=${encodedValue}`,\n 'path=/',\n `max-age=${maxAgeSeconds}`,\n 'SameSite=Lax',\n ];\n\n // biome-ignore lint/suspicious/noDocumentCookie: Fallback for browsers without Cookie Store API\n document.cookie = cookieParts.join('; ');\n}\n\n/**\n * Helper to delete a cookie\n */\nasync function deleteCookie(name: string): Promise<void> {\n if (typeof document === 'undefined') return;\n\n // Use Cookie Store API if available, fallback to document.cookie\n if ('cookieStore' in window) {\n try {\n await window.cookieStore.delete(name);\n return;\n } catch {\n // Fallback to document.cookie if Cookie Store API fails\n }\n }\n\n // Fallback for browsers without Cookie Store API\n // biome-ignore lint/suspicious/noDocumentCookie: Fallback for browsers without Cookie Store API\n document.cookie = `${name}=; path=/; max-age=0`;\n}\n\n/**\n * Event emitter for toolbar state changes\n */\nclass EventEmitter {\n private listeners: Set<ToolbarEventListener> = new Set();\n\n subscribe(listener: ToolbarEventListener): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n emit(event: ToolbarEvent): void {\n this.listeners.forEach((listener) => {\n try {\n listener(event);\n } catch (error) {\n console.error('[Unleash Toolbar] Error in event listener:', error);\n }\n });\n }\n}\n\n/**\n * Storage abstraction for different persistence modes\n */\nclass StorageAdapter {\n private enableCookieSync: boolean = false;\n\n constructor(\n private mode: StorageMode,\n private key: string,\n ) {}\n\n /**\n * Enable or disable cookie synchronization for SSR support\n * Should be enabled by Next.js integration\n */\n setCookieSyncEnabled(enabled: boolean): void {\n this.enableCookieSync = enabled;\n }\n\n private getStorage(): Storage | null {\n if (typeof window === 'undefined') return null;\n\n switch (this.mode) {\n case 'local':\n return window.localStorage;\n case 'session':\n return window.sessionStorage;\n default:\n return null;\n }\n }\n\n /**\n * Syncs state to cookies for server-side access (Next.js SSR)\n * Only runs when explicitly enabled via setCookieSyncEnabled()\n */\n private syncToCookies(state: ToolbarState): void {\n if (!this.enableCookieSync) return;\n if (typeof document === 'undefined') return;\n\n try {\n const value = JSON.stringify(state);\n // Set cookie with 7 day expiration, accessible from same origin\n setCookie('unleash-toolbar-state', value, 7 * 24 * 60 * 60);\n } catch (error) {\n console.error('[Unleash Toolbar] Failed to sync state to cookies:', error);\n }\n }\n\n load(): ToolbarState | null {\n const storage = this.getStorage();\n if (!storage) return null;\n\n try {\n const data = storage.getItem(this.key);\n return data ? JSON.parse(data) : null;\n } catch (error) {\n console.error('[Unleash Toolbar] Failed to load state from storage:', error);\n return null;\n }\n }\n\n save(state: ToolbarState): void {\n const storage = this.getStorage();\n if (!storage) return;\n\n try {\n storage.setItem(this.key, JSON.stringify(state));\n this.syncToCookies(state);\n } catch (error) {\n console.error('[Unleash Toolbar] Failed to save state to storage:', error);\n }\n }\n\n clear(): void {\n const storage = this.getStorage();\n if (!storage) return;\n\n try {\n storage.removeItem(this.key);\n // Also clear the cookie if sync was enabled\n if (this.enableCookieSync) {\n deleteCookie('unleash-toolbar-state');\n }\n } catch (error) {\n console.error('[Unleash Toolbar] Failed to clear storage:', error);\n }\n }\n}\n\n/**\n * Core state manager for the toolbar\n */\nexport class ToolbarStateManager {\n private state: ToolbarState;\n private eventEmitter: EventEmitter;\n private storage: StorageAdapter;\n private sortAlphabetically: boolean;\n\n constructor(\n storageMode: StorageMode = 'local',\n storageKey: string = 'unleash-toolbar-state',\n sortAlphabetically: boolean = false,\n ) {\n this.eventEmitter = new EventEmitter();\n this.storage = new StorageAdapter(storageMode, storageKey);\n this.sortAlphabetically = sortAlphabetically;\n\n // Try to load persisted state\n const persistedState = this.storage.load();\n this.state = persistedState || this.getInitialState();\n }\n\n private getInitialState(): ToolbarState {\n return {\n flags: {},\n contextOverrides: {},\n };\n }\n\n private persist(): void {\n this.storage.save(this.state);\n }\n\n /**\n * Apply override to a default value (same logic as wrapper)\n */\n private applyOverride(\n defaultValue: boolean | UnleashVariant | null,\n override: FlagOverride | null,\n ): boolean | UnleashVariant | null {\n if (!override) return defaultValue;\n\n if (override.type === 'flag') {\n return override.value;\n }\n\n if (override.type === 'variant') {\n // For variant overrides, create a variant object\n if (typeof defaultValue === 'object' && defaultValue !== null && 'name' in defaultValue) {\n return {\n ...defaultValue,\n name: override.variantKey,\n enabled: true,\n };\n }\n // If default was not a variant, create a new one\n return {\n name: override.variantKey,\n enabled: true,\n };\n }\n\n // Exhaustiveness check (for future-proofing)\n const _exhaustive: never = override;\n return _exhaustive;\n }\n\n /**\n * Re-evaluate all known flags (used when SDK configuration updates)\n */\n reEvaluateAllFlags(\n evaluator: (flagName: string) => { defaultValue: FlagValue; effectiveValue: FlagValue },\n ): void {\n const flagNames = Object.keys(this.state.flags);\n\n flagNames.forEach((flagName) => {\n const existing = this.state.flags[flagName];\n if (!existing) return;\n\n try {\n const { defaultValue, effectiveValue } = evaluator(flagName);\n\n // Update flag metadata with new default value\n this.state.flags[flagName] = {\n ...existing,\n lastDefaultValue: defaultValue,\n lastEffectiveValue: effectiveValue,\n };\n } catch (error) {\n // If evaluation fails, keep existing data\n console.error(`[Unleash Toolbar] Failed to re-evaluate flag ${flagName}:`, error);\n }\n });\n\n this.persist();\n\n this.eventEmitter.emit({\n type: 'sdk_updated',\n timestamp: Date.now(),\n });\n }\n\n /**\n * Get the current state (immutable copy)\n */\n getState(): ToolbarState {\n return JSON.parse(JSON.stringify(this.state));\n }\n\n /**\n * Subscribe to state change events\n */\n subscribe(listener: ToolbarEventListener): () => void {\n return this.eventEmitter.subscribe(listener);\n }\n\n /**\n * Record a flag evaluation (updates state without emitting events)\n */\n recordEvaluation(\n name: string,\n flagType: 'flag' | 'variant',\n defaultValue: boolean | UnleashVariant | null,\n effectiveValue: boolean | UnleashVariant | null,\n context: UnleashContext,\n ): void {\n const existing = this.state.flags[name];\n const isNewFlag = !existing;\n\n this.state.flags[name] = {\n flagType,\n lastDefaultValue: defaultValue,\n lastEffectiveValue: effectiveValue,\n lastContext: context,\n override: existing?.override || null,\n };\n\n this.persist();\n\n // Emit event only for new flags to trigger UI update\n if (isNewFlag) {\n this.eventEmitter.emit({\n type: 'sdk_updated',\n timestamp: Date.now(),\n });\n }\n }\n\n /**\n * Set or clear a flag override\n */\n setFlagOverride(name: string, override: FlagOverride | null): void {\n if (!this.state.flags[name]) {\n // Infer flag type from override type (shouldn't happen in normal flow)\n const flagType = override?.type === 'variant' ? 'variant' : 'flag';\n this.state.flags[name] = {\n flagType,\n lastDefaultValue: null,\n lastEffectiveValue: this.applyOverride(null, override),\n lastContext: null,\n override,\n };\n } else {\n this.state.flags[name].override = override;\n\n // Recalculate effective value based on new override\n const defaultValue = this.state.flags[name].lastDefaultValue;\n this.state.flags[name].lastEffectiveValue = this.applyOverride(defaultValue, override);\n }\n\n this.persist();\n\n this.eventEmitter.emit({\n type: 'flag_override_changed',\n name,\n override,\n timestamp: Date.now(),\n });\n }\n\n /**\n * Get flag override\n */\n getFlagOverride(name: string): FlagOverride | null {\n return this.state.flags[name]?.override || null;\n }\n\n /**\n * Set context overrides\n */\n setContextOverride(context: Partial<UnleashContext>): void {\n this.state.contextOverrides = {\n ...this.state.contextOverrides,\n ...context,\n };\n\n this.persist();\n\n this.eventEmitter.emit({\n type: 'context_override_changed',\n contextOverrides: this.state.contextOverrides,\n });\n }\n\n /**\n * Remove a specific context override field\n */\n removeContextOverride(fieldName: keyof UnleashContext): void {\n const newOverrides = { ...this.state.contextOverrides };\n delete newOverrides[fieldName];\n\n // Replace entire context overrides object\n this.state.contextOverrides = newOverrides;\n this.persist();\n\n this.eventEmitter.emit({\n type: 'context_override_changed',\n contextOverrides: this.state.contextOverrides,\n });\n }\n\n /**\n * Get merged context (original + overrides)\n */\n getMergedContext(baseContext: UnleashContext = {}): UnleashContext {\n return {\n ...baseContext,\n ...this.state.contextOverrides,\n properties: {\n ...(baseContext.properties || {}),\n ...(this.state.contextOverrides.properties || {}),\n },\n };\n }\n\n /**\n * Reset all flag overrides\n */\n resetOverrides(): void {\n Object.keys(this.state.flags).forEach((name) => {\n this.state.flags[name].override = null;\n\n // Recalculate effective value (will match default)\n const defaultValue = this.state.flags[name].lastDefaultValue;\n this.state.flags[name].lastEffectiveValue = defaultValue;\n\n // Emit event for each flag override removal\n this.eventEmitter.emit({\n type: 'flag_override_changed',\n name,\n override: null,\n timestamp: Date.now(),\n });\n });\n\n this.persist();\n }\n\n /**\n * Reset context overrides\n */\n resetContextOverrides(): void {\n this.state.contextOverrides = {};\n\n this.persist();\n\n this.eventEmitter.emit({\n type: 'context_override_changed',\n contextOverrides: {},\n });\n }\n\n /**\n * Set toolbar visibility state\n */\n setVisibility(isVisible: boolean): void {\n this.state.isVisible = isVisible;\n this.persist();\n }\n\n /**\n * Get toolbar visibility state\n */\n getVisibility(): boolean | undefined {\n return this.state.isVisible;\n }\n\n /**\n * Clear all persisted data\n */\n clearPersistence(): void {\n this.storage.clear();\n }\n\n /**\n * Get all flag names in evaluation order (insertion order) or alphabetically\n */\n getFlagNames(): string[] {\n const names = Object.keys(this.state.flags);\n return this.sortAlphabetically ? names.sort() : names;\n }\n\n /**\n * Get metadata for a specific flag\n */\n getFlagMetadata(name: string): FlagMetadata | null {\n return this.state.flags[name] || null;\n }\n\n /**\n * Enable cookie synchronization for server-side rendering support\n * Should be called by Next.js integration when SSR is needed\n */\n enableCookieSync(): void {\n this.storage.setCookieSyncEnabled(true);\n }\n}\n","import type { UnleashClient } from 'unleash-proxy-client';\nimport type { ToolbarStateManager } from './state';\nimport type { FlagOverride, UnleashVariant, WrappedUnleashClient } from './types';\n\n/**\n * Wrap an Unleash client to intercept evaluations and apply overrides\n */\nexport function wrapUnleashClient(\n baseClient: UnleashClient,\n stateManager: ToolbarStateManager,\n): WrappedUnleashClient {\n // If already wrapped, return as-is\n if (isWrappedClient(baseClient)) {\n return baseClient as WrappedUnleashClient;\n }\n\n // Capture original base context before any updates\n const originalBaseContext = baseClient.getContext();\n\n // Track user-registered 'update' listeners so we can trigger them on toolbar changes\n const updateListeners = new Set<() => void>();\n\n // Reference to the final proxy (will be assigned below)\n let proxyClient: WrappedUnleashClient;\n\n // Create a partial object with only the methods we're intercepting.\n // The Proxy will handle all other methods by forwarding to baseClient.\n const wrappedClient: Partial<WrappedUnleashClient> = {\n __original: baseClient,\n isEnabled,\n getVariant,\n getContext,\n on: onHandler,\n };\n\n function isEnabled(toggleName: string): boolean {\n // Get merged context (toolbar overrides are applied via updateContext)\n const currentContext = baseClient.getContext();\n const mergedContext = stateManager.getMergedContext(currentContext);\n\n // Get default evaluation from base client (uses client's global context)\n const defaultValue = baseClient.isEnabled(toggleName);\n\n // Apply override if exists\n const override = stateManager.getFlagOverride(toggleName);\n const effectiveValue = applyFlagOverride(defaultValue, override);\n\n // Record evaluation with explicit flag type\n stateManager.recordEvaluation(toggleName, 'flag', defaultValue, effectiveValue, mergedContext);\n\n return effectiveValue as boolean;\n }\n\n function getVariant(toggleName: string): UnleashVariant {\n // Get merged context (toolbar overrides are applied via updateContext)\n const currentContext = baseClient.getContext();\n const mergedContext = stateManager.getMergedContext(currentContext);\n\n // Get default evaluation from base client (uses client's global context)\n const defaultValue = baseClient.getVariant(toggleName);\n\n // Apply override if exists\n const override = stateManager.getFlagOverride(toggleName);\n const effectiveValue = applyFlagOverride(defaultValue, override);\n\n // Record evaluation with explicit flag type\n stateManager.recordEvaluation(\n toggleName,\n 'variant',\n defaultValue,\n effectiveValue,\n mergedContext,\n );\n\n return effectiveValue as UnleashVariant;\n }\n\n function getContext() {\n const baseContext = baseClient.getContext();\n const merged = stateManager.getMergedContext(baseContext);\n // Ensure appName exists (required by SDK type)\n return {\n appName: '',\n ...merged,\n };\n }\n\n // Intercept on() method to capture 'update' listeners\n function onHandler(event: string, callback: () => void): WrappedUnleashClient {\n if (event === 'update') {\n updateListeners.add(callback);\n }\n // Forward to base client\n baseClient.on(event, callback);\n // Return the proxy for method chaining\n return proxyClient;\n }\n\n // Helper to trigger all registered 'update' listeners\n function triggerUpdateListeners() {\n updateListeners.forEach((callback) => {\n try {\n callback();\n } catch (error) {\n console.error('[Unleash Toolbar] Error in update listener:', error);\n }\n });\n }\n\n // Listen to SDK 'update' event to re-evaluate flags when config changes\n baseClient.on('update', () => {\n // Re-evaluate all known flags with the new SDK configuration\n stateManager.reEvaluateAllFlags((flagName) => {\n // Get flag metadata to determine type\n const metadata = stateManager.getFlagMetadata(flagName);\n const isVariant = metadata?.flagType === 'variant';\n\n // Get new default value from SDK using correct method\n const defaultValue = isVariant\n ? baseClient.getVariant(flagName)\n : baseClient.isEnabled(flagName);\n\n // Apply override if exists\n const override = stateManager.getFlagOverride(flagName);\n const effectiveValue = applyFlagOverride(defaultValue, override);\n\n return { defaultValue, effectiveValue };\n });\n // Trigger user's 'update' listeners (already called by SDK, but for consistency)\n });\n\n // Listen to toolbar state changes to update client context and trigger re-renders\n stateManager.subscribe((event) => {\n if (event.type === 'context_override_changed') {\n // Update the base client's context with merged context\n // Use original base context (not current client context which includes previous overrides)\n const mergedContext = stateManager.getMergedContext(originalBaseContext);\n\n // Remove appName and environment - they are static and can't be updated\n const { appName: _appName, environment: _environment, ...updatableContext } = mergedContext;\n\n // Update context on the client (this triggers SDK re-evaluation)\n baseClient\n .updateContext(updatableContext)\n .then(() => {\n // Re-evaluate all known flags after context update\n stateManager.reEvaluateAllFlags((flagName) => {\n // Get flag metadata to determine type\n const metadata = stateManager.getFlagMetadata(flagName);\n const isVariant = metadata?.flagType === 'variant';\n\n // Get new default value from SDK with updated context using correct method\n const defaultValue = isVariant\n ? baseClient.getVariant(flagName)\n : baseClient.isEnabled(flagName);\n\n // Apply override if exists\n const override = stateManager.getFlagOverride(flagName);\n const effectiveValue = applyFlagOverride(defaultValue, override);\n\n return { defaultValue, effectiveValue };\n });\n // Trigger user's 'update' listeners after context change\n triggerUpdateListeners();\n })\n .catch((err) => {\n console.error('[Unleash Toolbar] Failed to update context:', err);\n });\n }\n\n // Trigger user's 'update' listeners for flag override changes\n // (flag_override_changed is emitted when override is set or removed, including bulk resets)\n if (event.type === 'flag_override_changed') {\n triggerUpdateListeners();\n }\n });\n\n // Proxy all other methods and properties to the base client\n proxyClient = new Proxy(wrappedClient, {\n get(target, prop) {\n if (prop in target) {\n return Reflect.get(target, prop);\n }\n const value = Reflect.get(baseClient, prop);\n return typeof value === 'function' ? value.bind(baseClient) : value;\n },\n set(target, prop, value) {\n if (prop in target) {\n Reflect.set(target, prop, value);\n return true;\n }\n Reflect.set(baseClient, prop, value);\n return true;\n },\n }) as WrappedUnleashClient;\n\n return proxyClient;\n}\n\n/**\n * Apply flag override to evaluation result\n */\nfunction applyFlagOverride(\n defaultValue: boolean | UnleashVariant | null,\n override: FlagOverride | null,\n): boolean | UnleashVariant | null {\n if (!override) return defaultValue;\n\n if (override.type === 'flag') {\n return override.value;\n }\n\n if (override.type === 'variant') {\n // For variant overrides, create a variant object\n if (typeof defaultValue === 'object' && defaultValue !== null && 'name' in defaultValue) {\n return {\n ...defaultValue,\n name: override.variantKey,\n enabled: true,\n };\n }\n // If default was not a variant, create a new one\n return {\n name: override.variantKey,\n enabled: true,\n };\n }\n\n return defaultValue;\n}\n\n/**\n * Unwrap a client to get the original\n */\nexport function unwrapUnleashClient(client: UnleashClient): UnleashClient {\n if (isWrappedClient(client)) {\n return (client as WrappedUnleashClient).__original;\n }\n return client;\n}\n\n/**\n * Check if a client is wrapped\n */\nexport function isWrappedClient(client: UnleashClient): client is WrappedUnleashClient {\n return '__original' in client;\n}\n","import type { UnleashClient } from 'unleash-proxy-client';\nimport { ToolbarStateManager } from './state';\nimport type {\n FlagOverride,\n InitToolbarOptions,\n IToolbarUI,\n ToolbarState,\n UnleashContext,\n UnleashToolbarInstance,\n WrappedUnleashClient,\n} from './types';\nimport { wrapUnleashClient } from './wrapper';\n\n/**\n * Main toolbar instance implementation\n */\nexport class UnleashToolbar implements UnleashToolbarInstance {\n private stateManager: ToolbarStateManager;\n private ui: IToolbarUI | null;\n public readonly client: WrappedUnleashClient;\n\n constructor(\n stateManager: ToolbarStateManager,\n wrappedClient: WrappedUnleashClient,\n options: InitToolbarOptions,\n ) {\n this.stateManager = stateManager;\n this.client = wrappedClient;\n this.ui = null;\n\n // Initialize UI asynchronously to avoid SSR issues\n this.initUI(stateManager, wrappedClient, options);\n }\n\n private async initUI(\n stateManager: ToolbarStateManager,\n wrappedClient: WrappedUnleashClient,\n options: InitToolbarOptions,\n ) {\n const { ToolbarUI } = await import('./ui');\n this.ui = new ToolbarUI(stateManager, wrappedClient, options);\n }\n\n show(): void {\n if (this.ui) this.ui.show();\n }\n\n hide(): void {\n if (this.ui) this.ui.hide();\n }\n\n destroy(): void {\n if (this.ui) this.ui.destroy();\n this.stateManager.clearPersistence();\n }\n\n getState(): ToolbarState {\n return this.stateManager.getState();\n }\n\n getFlagNames(): string[] {\n return this.stateManager.getFlagNames();\n }\n\n setFlagOverride(name: string, override: FlagOverride | null): void {\n this.stateManager.setFlagOverride(name, override);\n }\n\n setContextOverride(context: Partial<UnleashContext>): void {\n this.stateManager.setContextOverride(context);\n }\n\n removeContextOverride(fieldName: keyof UnleashContext): void {\n this.stateManager.removeContextOverride(fieldName);\n }\n\n resetOverrides(): void {\n this.stateManager.resetOverrides();\n }\n\n resetContextOverrides(): void {\n this.stateManager.resetContextOverrides();\n }\n}\n\n/**\n * Initialize the Unleash Toolbar with a client\n * This is the main entry point - handles both toolbar creation and client wrapping\n * Returns the wrapped client directly for immediate use\n *\n * @param client - The Unleash client to wrap\n * @param options - Toolbar configuration options\n */\nexport function initUnleashToolbar(\n client: UnleashClient,\n options: InitToolbarOptions = {},\n): WrappedUnleashClient {\n const storageMode = options.storageMode || 'local';\n const storageKey = options.storageKey || 'unleash-toolbar-state';\n const sortAlphabetically = options.sortAlphabetically || false;\n const enableCookieSync = options.enableCookieSync || false;\n\n const stateManager = new ToolbarStateManager(storageMode, storageKey, sortAlphabetically);\n\n // Enable cookie sync if requested (for Next.js SSR)\n if (enableCookieSync) {\n stateManager.enableCookieSync();\n }\n\n const wrappedClient = wrapUnleashClient(client, stateManager);\n const toolbar = new UnleashToolbar(stateManager, wrappedClient, options);\n\n // Expose toolbar instance globally for debugging/advanced use\n if (typeof window !== 'undefined') {\n // biome-ignore lint/suspicious/noExplicitAny: no type for window\n (window as any).unleashToolbar = toolbar;\n }\n\n return wrappedClient;\n}\n\n// UMD global export\nif (typeof window !== 'undefined') {\n // biome-ignore lint/suspicious/noExplicitAny: no type for window\n (window as any).UnleashToolbar = {\n init: initUnleashToolbar,\n };\n}\n\nexport { ToolbarStateManager } from './state';\n// Export types\nexport * from './types';\nexport { wrapUnleashClient } from './wrapper';\n"],"names":["EventEmitter","listeners","Set","subscribe","listener","this","add","delete","emit","event","forEach","error","console","StorageAdapter","constructor","mode","key","enableCookieSync","setCookieSyncEnabled","enabled","getStorage","window","localStorage","sessionStorage","syncToCookies","state","document","async","name","value","encodedValue","encodeURIComponent","cookieStore","set","path","sameSite","expires","Date","now","maxAgeSeconds","cookie","join","setCookie","JSON","stringify","load","storage","data","getItem","parse","save","setItem","clear","removeItem","deleteCookie","ToolbarStateManager","eventEmitter","sortAlphabetically","storageMode","storageKey","persistedState","getInitialState","flags","contextOverrides","persist","applyOverride","defaultValue","override","type","variantKey","reEvaluateAllFlags","evaluator","Object","keys","flagName","existing","effectiveValue","lastDefaultValue","lastEffectiveValue","timestamp","getState","recordEvaluation","flagType","context","isNewFlag","lastContext","setFlagOverride","getFlagOverride","setContextOverride","removeContextOverride","fieldName","newOverrides","getMergedContext","baseContext","properties","resetOverrides","resetContextOverrides","setVisibility","isVisible","getVisibility","clearPersistence","getFlagNames","names","sort","getFlagMetadata","wrapUnleashClient","baseClient","stateManager","originalBaseContext","getContext","updateListeners","proxyClient","wrappedClient","__original","isEnabled","toggleName","currentContext","mergedContext","applyFlagOverride","getVariant","appName","on","callback","triggerUpdateListeners","metadata","_appName","environment","_environment","updatableContext","updateContext","then","catch","err","Proxy","get","target","prop","Reflect","bind","UnleashToolbar","ui","client","options","initUI","ToolbarUI","import","show","hide","destroy","initUnleashToolbar","toolbar","unleashToolbar","init"],"mappings":"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"}
const e="unleash-toolbar-state";function a(e){if(!e)return null;try{return JSON.parse(decodeURIComponent(e))}catch{return null}}function t(t){const n=t.get(e);return a(n?.value)}function n(e,a){const n=t(a);if(!n||!e)return e;const r=JSON.parse(JSON.stringify(e));r.features||(r.features=[]);const s=new Set(r.features.map(e=>e.name));r.features=r.features.map(e=>{const a=n.flags[e.name]?.override;return a?"flag"===a.type?{...e,enabled:a.value,strategies:a.value?e.strategies&&e.strategies.length>0?e.strategies:[{name:"default",parameters:{},constraints:[]}]:[]}:"variant"===a.type&&e.variants?{...e,enabled:!0,strategies:e.strategies&&e.strategies.length>0?e.strategies:[{name:"default",parameters:{},constraints:[]}],variants:e.variants.map(e=>({...e,weight:e.name===a.variantKey?1e3:0}))}:e:e});for(const[t,i]of Object.entries(n.flags))if(!s.has(t)&&i.override){const e=i.override;"flag"===e.type?r.features.push({name:t,enabled:e.value,strategies:e.value?[{name:"default",parameters:{},constraints:[]}]:[]}):"variant"===e.type&&r.features.push({name:t,enabled:!0,strategies:[{name:"default",parameters:{},constraints:[]}],variants:[{name:e.variantKey,weight:1e3}]})}return r}function r(e,a){const n=t(a);return n&&e?e.map(e=>{const a=n.flags[e.name]?.override;return a?"flag"===a.type?{...e,enabled:a.value,variant:a.value?e.variant:{name:"disabled",enabled:!1}}:"variant"===a.type?{...e,enabled:!0,variant:{name:a.variantKey,enabled:!0,payload:e.variant?.payload}}:e:e}):e}export{e as UNLEASH_TOOLBAR_COOKIE,n as applyToolbarOverrides,r as applyToolbarOverridesToToggles,t as getToolbarStateFromCookies,a as parseToolbarState};
//# sourceMappingURL=next-server.es.js.map
{"version":3,"file":"next-server.es.js","sources":["../src/next/server.ts"],"sourcesContent":["/**\n * Server-side Next.js integration for Unleash Toolbar\n *\n * This module provides utilities for applying toolbar overrides in server components,\n * SSR, SSG, and App Router scenarios. It reads overrides from cookies to ensure\n * server-side flag evaluations respect client-side toolbar changes.\n *\n * @example App Router Server Component\n * ```tsx\n * import { cookies } from 'next/headers';\n * import { getDefinitions, evaluateFlags, flagsClient } from '@unleash/nextjs';\n * import { applyToolbarOverrides } from '@unleash/toolbar/next/server';\n *\n * export default async function ServerPage() {\n * const cookieStore = await cookies();\n * const definitions = await getDefinitions();\n * const modifiedDefinitions = applyToolbarOverrides(definitions, cookieStore);\n *\n * const { toggles } = evaluateFlags(modifiedDefinitions, {\n * sessionId: 'session-123'\n * });\n *\n * const flags = flagsClient(toggles);\n * const isEnabled = flags.isEnabled('my-flag');\n *\n * return <div>{isEnabled ? 'ON' : 'OFF'}</div>;\n * }\n * ```\n */\n\nimport type { IToggle } from '@unleash/nextjs';\nimport type { ClientFeaturesResponse } from 'unleash-client';\nimport type { VariantDefinition } from 'unleash-client/lib/variant';\nimport type { ToolbarState } from '../types';\n\nexport const UNLEASH_TOOLBAR_COOKIE = 'unleash-toolbar-state';\n\n/**\n * Cookie store interface compatible with Next.js cookies()\n */\ninterface CookieStore {\n get(name: string): { value: string } | undefined;\n}\n\n/**\n * Parses toolbar state from cookie value\n */\nexport function parseToolbarState(cookieValue: string | undefined): ToolbarState | null {\n if (!cookieValue) return null;\n\n try {\n return JSON.parse(decodeURIComponent(cookieValue));\n } catch {\n return null;\n }\n}\n\n/**\n * Reads toolbar state from Next.js cookie store\n */\nexport function getToolbarStateFromCookies(cookieStore: CookieStore): ToolbarState | null {\n const cookie = cookieStore.get(UNLEASH_TOOLBAR_COOKIE);\n return parseToolbarState(cookie?.value);\n}\n\n/**\n * Applies toolbar overrides to Unleash feature flag definitions.\n *\n * Use this with getDefinitions() from @unleash/nextjs before evaluating flags\n * to ensure server-side evaluations respect toolbar overrides.\n *\n * @param definitions - Feature flag definitions from getDefinitions()\n * @param cookieStore - Next.js cookie store from cookies()\n * @returns Modified definitions with overrides applied\n *\n * @example\n * ```tsx\n * import { getDefinitions, evaluateFlags } from '@unleash/nextjs';\n * import { cookies } from 'next/headers';\n * import { applyToolbarOverrides } from '@unleash/toolbar/next/server';\n *\n * const cookieStore = await cookies();\n * const definitions = await getDefinitions();\n * const modified = applyToolbarOverrides(definitions, cookieStore);\n * const { toggles } = evaluateFlags(modified, context);\n * ```\n */\nexport function applyToolbarOverrides(\n definitions: ClientFeaturesResponse,\n cookieStore: CookieStore,\n): ClientFeaturesResponse {\n const state = getToolbarStateFromCookies(cookieStore);\n\n if (!state || !definitions) return definitions;\n\n // Clone definitions to avoid mutation\n const modified = JSON.parse(JSON.stringify(definitions)) as ClientFeaturesResponse;\n\n if (!modified.features) {\n modified.features = [];\n }\n\n // Track which features we've seen\n const existingFeatureNames = new Set(modified.features.map((f) => f.name));\n\n // Apply overrides to existing features\n modified.features = modified.features.map((feature) => {\n const override = state.flags[feature.name]?.override;\n\n if (!override) return feature;\n\n if (override.type === 'flag') {\n // Force flag to enabled/disabled\n return {\n ...feature,\n enabled: override.value,\n // Override strategies to force the value\n // When enabling, ensure we have at least a default strategy\n strategies: override.value\n ? feature.strategies && feature.strategies.length > 0\n ? feature.strategies\n : [{ name: 'default', parameters: {}, constraints: [] }]\n : [],\n };\n }\n\n if (override.type === 'variant' && feature.variants) {\n // Force specific variant\n return {\n ...feature,\n enabled: true,\n strategies:\n feature.strategies && feature.strategies.length > 0\n ? feature.strategies\n : [{ name: 'default', parameters: {}, constraints: [] }],\n variants: feature.variants.map((v: VariantDefinition) => ({\n ...v,\n weight: v.name === override.variantKey ? 1000 : 0,\n })),\n };\n }\n\n return feature;\n });\n\n // Add features that don't exist in the API but have overrides\n for (const [flagName, metadata] of Object.entries(state.flags)) {\n if (!existingFeatureNames.has(flagName) && metadata.override) {\n const override = metadata.override;\n\n if (override.type === 'flag') {\n // Add a new feature for the override\n modified.features.push({\n name: flagName,\n enabled: override.value,\n strategies: override.value ? [{ name: 'default', parameters: {}, constraints: [] }] : [],\n });\n } else if (override.type === 'variant') {\n // Add a new feature with a variant\n modified.features.push({\n name: flagName,\n enabled: true,\n strategies: [{ name: 'default', parameters: {}, constraints: [] }],\n variants: [\n {\n name: override.variantKey,\n weight: 1000,\n },\n ],\n });\n }\n }\n }\n\n return modified;\n}\n\n/**\n * Applies toolbar overrides to evaluated toggles.\n *\n * Alternative to applyToolbarOverrides() - use this if you already have\n * evaluated toggles and want to apply overrides post-evaluation.\n *\n * @param toggles - Evaluated toggles array from evaluateFlags()\n * @param cookieStore - Next.js cookie store from cookies()\n * @returns Modified toggles with overrides applied\n *\n * @example\n * ```tsx\n * import { getDefinitions, evaluateFlags, flagsClient } from '@unleash/nextjs';\n * import { cookies } from 'next/headers';\n * import { applyToolbarOverridesToToggles } from '@unleash/toolbar/next/server';\n *\n * const definitions = await getDefinitions();\n * const { toggles } = evaluateFlags(definitions, context);\n * const modified = applyToolbarOverridesToToggles(toggles, await cookies());\n * const flags = flagsClient(modified);\n * ```\n */\nexport function applyToolbarOverridesToToggles(\n toggles: IToggle[],\n cookieStore: CookieStore,\n): IToggle[] {\n const state = getToolbarStateFromCookies(cookieStore);\n\n if (!state || !toggles) return toggles;\n\n return toggles.map((toggle) => {\n const override = state.flags[toggle.name]?.override;\n\n if (!override) return toggle;\n\n if (override.type === 'flag') {\n return {\n ...toggle,\n enabled: override.value,\n variant: override.value ? toggle.variant : { name: 'disabled', enabled: false },\n };\n }\n\n if (override.type === 'variant') {\n return {\n ...toggle,\n enabled: true,\n variant: {\n name: override.variantKey,\n enabled: true,\n payload: toggle.variant?.payload,\n },\n };\n }\n\n return toggle;\n });\n}\n"],"names":["UNLEASH_TOOLBAR_COOKIE","parseToolbarState","cookieValue","JSON","parse","decodeURIComponent","getToolbarStateFromCookies","cookieStore","cookie","get","value","applyToolbarOverrides","definitions","state","modified","stringify","features","existingFeatureNames","Set","map","f","name","feature","override","flags","type","enabled","strategies","length","parameters","constraints","variants","v","weight","variantKey","flagName","metadata","Object","entries","has","push","applyToolbarOverridesToToggles","toggles","toggle","variant","payload"],"mappings":"AAmCO,MAAMA,EAAyB,wBAY/B,SAASC,EAAkBC,GAChC,IAAKA,EAAa,OAAO,KAEzB,IACE,OAAOC,KAAKC,MAAMC,mBAAmBH,GACvC,CAAA,MACE,OAAO,IACT,CACF,CAKO,SAASI,EAA2BC,GACzC,MAAMC,EAASD,EAAYE,IAAIT,GAC/B,OAAOC,EAAkBO,GAAQE,MACnC,CAwBO,SAASC,EACdC,EACAL,GAEA,MAAMM,EAAQP,EAA2BC,GAEzC,IAAKM,IAAUD,EAAa,OAAOA,EAGnC,MAAME,EAAWX,KAAKC,MAAMD,KAAKY,UAAUH,IAEtCE,EAASE,WACZF,EAASE,SAAW,IAItB,MAAMC,EAAuB,IAAIC,IAAIJ,EAASE,SAASG,IAAKC,GAAMA,EAAEC,OAGpEP,EAASE,SAAWF,EAASE,SAASG,IAAKG,IACzC,MAAMC,EAAWV,EAAMW,MAAMF,EAAQD,OAAOE,SAE5C,OAAKA,EAEiB,SAAlBA,EAASE,KAEJ,IACFH,EACHI,QAASH,EAASb,MAGlBiB,WAAYJ,EAASb,MACjBY,EAAQK,YAAcL,EAAQK,WAAWC,OAAS,EAChDN,EAAQK,WACR,CAAC,CAAEN,KAAM,UAAWQ,WAAY,GAAIC,YAAa,KACnD,IAIc,YAAlBP,EAASE,MAAsBH,EAAQS,SAElC,IACFT,EACHI,SAAS,EACTC,WACEL,EAAQK,YAAcL,EAAQK,WAAWC,OAAS,EAC9CN,EAAQK,WACR,CAAC,CAAEN,KAAM,UAAWQ,WAAY,CAAA,EAAIC,YAAa,KACvDC,SAAUT,EAAQS,SAASZ,IAAKa,IAAA,IAC3BA,EACHC,OAAQD,EAAEX,OAASE,EAASW,WAAa,IAAO,MAK/CZ,EAjCeA,IAqCxB,IAAA,MAAYa,EAAUC,KAAaC,OAAOC,QAAQzB,EAAMW,OACtD,IAAKP,EAAqBsB,IAAIJ,IAAaC,EAASb,SAAU,CAC5D,MAAMA,EAAWa,EAASb,SAEJ,SAAlBA,EAASE,KAEXX,EAASE,SAASwB,KAAK,CACrBnB,KAAMc,EACNT,QAASH,EAASb,MAClBiB,WAAYJ,EAASb,MAAQ,CAAC,CAAEW,KAAM,UAAWQ,WAAY,CAAA,EAAIC,YAAa,KAAQ,KAE7D,YAAlBP,EAASE,MAElBX,EAASE,SAASwB,KAAK,CACrBnB,KAAMc,EACNT,SAAS,EACTC,WAAY,CAAC,CAAEN,KAAM,UAAWQ,WAAY,GAAIC,YAAa,KAC7DC,SAAU,CACR,CACEV,KAAME,EAASW,WACfD,OAAQ,OAKlB,CAGF,OAAOnB,CACT,CAwBO,SAAS2B,EACdC,EACAnC,GAEA,MAAMM,EAAQP,EAA2BC,GAEzC,OAAKM,GAAU6B,EAERA,EAAQvB,IAAKwB,IAClB,MAAMpB,EAAWV,EAAMW,MAAMmB,EAAOtB,OAAOE,SAE3C,OAAKA,EAEiB,SAAlBA,EAASE,KACJ,IACFkB,EACHjB,QAASH,EAASb,MAClBkC,QAASrB,EAASb,MAAQiC,EAAOC,QAAU,CAAEvB,KAAM,WAAYK,SAAS,IAItD,YAAlBH,EAASE,KACJ,IACFkB,EACHjB,SAAS,EACTkB,QAAS,CACPvB,KAAME,EAASW,WACfR,SAAS,EACTmB,QAASF,EAAOC,SAASC,UAKxBF,EAtBeA,IALOD,CA6BjC"}
"use client";
export{useFlag,useFlags,useFlagsStatus,useUnleashClient,useUnleashContext,useVariant}from"@unleash/proxy-client-react";import{jsx as e}from"react/jsx-runtime";import{UnleashToolbarProvider as o}from"./react.es.js";function t(t){const r={...t.toolbarOptions,enableCookieSync:!0};/* @__PURE__ */
return e(o,{...t,toolbarOptions:r})}export{t as UnleashToolbarProvider};
//# sourceMappingURL=next.es.js.map
{"version":3,"file":"next.es.js","sources":["../src/next/client.tsx"],"sourcesContent":["/**\n * Client-side Next.js integration for Unleash Toolbar\n * \n * This module provides the client-side provider for Next.js applications.\n * Use this in client components marked with \"use client\" directive.\n * Automatically enables cookie synchronization for server-side rendering support.\n */\n'use client';\n\nimport { UnleashToolbarProvider as BaseUnleashToolbarProvider } from '../react/index';\nimport type { InitToolbarOptions } from '../types';\nimport React from 'react';\n\n/**\n * Next.js-specific provider that wraps the official Unleash React SDK's FlagProvider\n * and automatically enables cookie synchronization for server-side rendering support.\n * \n * This ensures toolbar state is available in server components via getToolbarStateFromCookies().\n */\nexport function UnleashToolbarProvider(props: React.ComponentProps<typeof BaseUnleashToolbarProvider>) {\n // Automatically enable cookie sync for Next.js SSR support\n const toolbarOptions: InitToolbarOptions = {\n ...props.toolbarOptions,\n enableCookieSync: true,\n };\n\n return <BaseUnleashToolbarProvider {...props} toolbarOptions={toolbarOptions} />;\n}\n\nexport * from '../react/hooks';\n\n"],"names":["UnleashToolbarProvider","props","toolbarOptions","enableCookieSync","jsx","BaseUnleashToolbarProvider"],"mappings":"sNAmBO,SAASA,EAAuBC,GAErC,MAAMC,EAAqC,IACtCD,EAAMC,eACTC,kBAAkB;AAGpB,OAAOC,EAACC,EAAA,IAA+BJ,EAAOC,kBAChD"}
import { UnleashToolbarProvider as BaseUnleashToolbarProvider } from '../react/index';
import { default as React } from 'react';
/**
* Next.js-specific provider that wraps the official Unleash React SDK's FlagProvider
* and automatically enables cookie synchronization for server-side rendering support.
*
* This ensures toolbar state is available in server components via getToolbarStateFromCookies().
*/
export declare function UnleashToolbarProvider(props: React.ComponentProps<typeof BaseUnleashToolbarProvider>): import("react/jsx-runtime").JSX.Element;
export * from '../react/hooks';
//# sourceMappingURL=client.d.ts.map
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/next/client.tsx"],"names":[],"mappings":"AASA,OAAO,EAAE,sBAAsB,IAAI,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AAEtF,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,0BAA0B,CAAC,2CAQpG;AAED,cAAc,gBAAgB,CAAC"}
/**
* Next.js integration for Unleash Toolbar
*
* This package provides both client-side and server-side integration for Next.js:
*
* - Client-side: `@unleash/toolbar/next` (same as React integration)
* - Server-side: `@unleash/toolbar/next/server` (for App Router server components)
*
* @example Client Component
* ```tsx
* 'use client';
* import { UnleashToolbarProvider, useFlag } from '@unleash/toolbar/next';
*
* export function MyComponent() {
* return (
* <UnleashToolbarProvider config={{ ... }}>
* <App />
* </UnleashToolbarProvider>
* );
* }
* ```
*
* @example Server Component
* ```tsx
* import { cookies } from 'next/headers';
* import { getDefinitions, evaluateFlags, flagsClient } from '@unleash/nextjs';
* import { applyToolbarOverrides } from '@unleash/toolbar/next/server';
*
* export default async function Page() {
* const definitions = await getDefinitions();
* const modified = applyToolbarOverrides(definitions, await cookies());
* const { toggles } = evaluateFlags(modified, { sessionId: '123' });
* const flags = flagsClient(toggles);
*
* return <div>{flags.isEnabled('my-flag') ? 'ON' : 'OFF'}</div>;
* }
* ```
*/
export * from '../react/hooks';
export { UnleashToolbarProvider } from './client';
//# sourceMappingURL=index.d.ts.map
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/next/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,cAAc,gBAAgB,CAAC;AAE/B,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC"}
import { IToggle } from '@unleash/nextjs';
import { ClientFeaturesResponse } from 'unleash-client';
import { ToolbarState } from '../types';
export declare const UNLEASH_TOOLBAR_COOKIE = "unleash-toolbar-state";
/**
* Cookie store interface compatible with Next.js cookies()
*/
interface CookieStore {
get(name: string): {
value: string;
} | undefined;
}
/**
* Parses toolbar state from cookie value
*/
export declare function parseToolbarState(cookieValue: string | undefined): ToolbarState | null;
/**
* Reads toolbar state from Next.js cookie store
*/
export declare function getToolbarStateFromCookies(cookieStore: CookieStore): ToolbarState | null;
/**
* Applies toolbar overrides to Unleash feature flag definitions.
*
* Use this with getDefinitions() from @unleash/nextjs before evaluating flags
* to ensure server-side evaluations respect toolbar overrides.
*
* @param definitions - Feature flag definitions from getDefinitions()
* @param cookieStore - Next.js cookie store from cookies()
* @returns Modified definitions with overrides applied
*
* @example
* ```tsx
* import { getDefinitions, evaluateFlags } from '@unleash/nextjs';
* import { cookies } from 'next/headers';
* import { applyToolbarOverrides } from '@unleash/toolbar/next/server';
*
* const cookieStore = await cookies();
* const definitions = await getDefinitions();
* const modified = applyToolbarOverrides(definitions, cookieStore);
* const { toggles } = evaluateFlags(modified, context);
* ```
*/
export declare function applyToolbarOverrides(definitions: ClientFeaturesResponse, cookieStore: CookieStore): ClientFeaturesResponse;
/**
* Applies toolbar overrides to evaluated toggles.
*
* Alternative to applyToolbarOverrides() - use this if you already have
* evaluated toggles and want to apply overrides post-evaluation.
*
* @param toggles - Evaluated toggles array from evaluateFlags()
* @param cookieStore - Next.js cookie store from cookies()
* @returns Modified toggles with overrides applied
*
* @example
* ```tsx
* import { getDefinitions, evaluateFlags, flagsClient } from '@unleash/nextjs';
* import { cookies } from 'next/headers';
* import { applyToolbarOverridesToToggles } from '@unleash/toolbar/next/server';
*
* const definitions = await getDefinitions();
* const { toggles } = evaluateFlags(definitions, context);
* const modified = applyToolbarOverridesToToggles(toggles, await cookies());
* const flags = flagsClient(modified);
* ```
*/
export declare function applyToolbarOverridesToToggles(toggles: IToggle[], cookieStore: CookieStore): IToggle[];
export {};
//# sourceMappingURL=server.d.ts.map
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/next/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAE7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7C,eAAO,MAAM,sBAAsB,0BAA0B,CAAC;AAE9D;;GAEG;AACH,UAAU,WAAW;IACnB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;CAClD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,YAAY,GAAG,IAAI,CAQtF;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,WAAW,GAAG,YAAY,GAAG,IAAI,CAGxF;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,sBAAsB,EACnC,WAAW,EAAE,WAAW,GACvB,sBAAsB,CAqFxB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,8BAA8B,CAC5C,OAAO,EAAE,OAAO,EAAE,EAClB,WAAW,EAAE,WAAW,GACvB,OAAO,EAAE,CAgCX"}
import{jsx as r}from"react/jsx-runtime";import{UnleashClient as e}from"unleash-proxy-client";import{FlagProvider as o}from"@unleash/proxy-client-react";import{ToolbarStateManager as n,wrapUnleashClient as t,UnleashToolbar as i}from"./index.es.js";import{useRef as l,useEffect as c}from"react";function u({FlagProvider:u=o,config:a,client:s,toolbarOptions:d={},startClient:f=!0,children:p,...h}){if(!a&&!s)throw new Error('UnleashToolbarProvider: Either "config" or "client" prop must be provided');if(a&&s)throw new Error('UnleashToolbarProvider: Provide either "config" or "client" prop, not both');const b=l(null),m=l(null),w=l(null);if(null===w.current){const r=s||new e(a);if(void 0!==d){const e=new n(d.storageMode||"local",d.storageKey||"unleash-toolbar-state",d.sortAlphabetically||!1);m.current=e,d.enableCookieSync&&e.enableCookieSync(),w.current=t(r,e)}else w.current=r}return c(()=>{if(void 0!==d&&!b.current&&m.current&&!w.current?.__toolbar){const r=new i(m.current,w.current,d);w.current.__toolbar=r,b.current=r,"undefined"!=typeof window&&(window.unleashToolbar=r)}return()=>{b.current&&"function"==typeof b.current.destroy&&(b.current.destroy(),b.current=null)}},[]),/* @__PURE__ */r(u,{unleashClient:w.current,startClient:f,...h,children:p})}export{u as UnleashToolbarProvider};
//# sourceMappingURL=react.es.js.map
{"version":3,"file":"react.es.js","sources":["../src/react/index.tsx"],"sourcesContent":["import { UnleashClient, type IConfig } from 'unleash-proxy-client';\nimport { FlagProvider as DefaultFlagProvider } from '@unleash/proxy-client-react';\nimport { wrapUnleashClient, ToolbarStateManager, UnleashToolbar } from '../index';\nimport type { InitToolbarOptions } from '../types';\nimport React, { useRef, useEffect } from 'react';\n\n/**\n * Base props shared by both config and client variants\n */\ninterface BaseToolbarProviderProps {\n /**\n * The official FlagProvider component from @unleash/proxy-client-react\n * Optional - defaults to the standard FlagProvider\n */\n FlagProvider?: React.ComponentType<any>;\n \n /**\n * Optional toolbar configuration\n * Set to undefined to disable toolbar in production\n */\n toolbarOptions?: InitToolbarOptions;\n \n /**\n * Whether to automatically start the client\n * Defaults to true\n */\n startClient?: boolean;\n \n /**\n * Children components\n */\n children: React.ReactNode;\n \n /**\n * Any additional props to pass to the official FlagProvider\n */\n [key: string]: any;\n}\n\n/**\n * Props when using config-based initialization\n */\ninterface ConfigBasedProps extends BaseToolbarProviderProps {\n /**\n * Unleash SDK configuration object (same as official React SDK)\n */\n config: IConfig;\n client?: never;\n}\n\n/**\n * Props when using pre-instantiated client\n */\ninterface ClientBasedProps extends BaseToolbarProviderProps {\n /**\n * Pre-instantiated Unleash client (will be wrapped with toolbar)\n */\n client: UnleashClient;\n config?: never;\n}\n\n/**\n * Props for the UnleashToolbarProvider - either config OR client must be provided\n */\ntype UnleashToolbarProviderProps = ConfigBasedProps | ClientBasedProps;\n\n/**\n * Higher-order provider that wraps the official Unleash React SDK's FlagProvider\n * and initializes the toolbar with a wrapped client.\n * \n * Simple usage (no imports needed):\n * ```tsx\n * import { UnleashToolbarProvider } from '@unleash/toolbar/react';\n * \n * function App() {\n * return (\n * <UnleashToolbarProvider\n * config={{\n * url: 'https://your-unleash-instance.com/api/frontend',\n * clientKey: 'your-client-key',\n * appName: 'my-app'\n * }}\n * toolbarOptions={{ themePreset: 'dark' }}\n * >\n * <YourApp />\n * </UnleashToolbarProvider>\n * );\n * }\n * ```\n * \n * Advanced usage with custom FlagProvider:\n * ```tsx\n * import { FlagProvider } from '@unleash/proxy-client-react';\n * \n * <UnleashToolbarProvider\n * FlagProvider={FlagProvider}\n * config={{ ... }}\n * >\n * <YourApp />\n * </UnleashToolbarProvider>\n * ```\n */\nexport function UnleashToolbarProvider({\n FlagProvider = DefaultFlagProvider,\n config,\n client,\n toolbarOptions = {},\n startClient = true,\n children,\n ...flagProviderProps\n}: UnleashToolbarProviderProps) {\n // Validate that either config or client is provided, not both\n if (!config && !client) {\n throw new Error(\n 'UnleashToolbarProvider: Either \"config\" or \"client\" prop must be provided'\n );\n }\n if (config && client) {\n throw new Error(\n 'UnleashToolbarProvider: Provide either \"config\" or \"client\" prop, not both'\n );\n }\n\n const toolbarRef = useRef<any>(null);\n const stateManagerRef = useRef<any>(null);\n \n // Wrap client synchronously (idempotent, captures flag evaluations)\n // This ensures the wrapper intercepts all flag evaluations from the first render\n const wrappedClientRef = useRef<UnleashClient | null>(null);\n \n if (wrappedClientRef.current === null) {\n const unleashClient = client || new UnleashClient(config!);\n \n if (toolbarOptions !== undefined) {\n // Create state manager that will be shared between wrapper and toolbar\n const storageMode = toolbarOptions.storageMode || 'local';\n const storageKey = toolbarOptions.storageKey || 'unleash-toolbar-state';\n const sortAlphabetically = toolbarOptions.sortAlphabetically || false;\n const stateManager = new ToolbarStateManager(storageMode, storageKey, sortAlphabetically);\n stateManagerRef.current = stateManager;\n\n if (toolbarOptions.enableCookieSync) {\n stateManager.enableCookieSync();\n }\n \n // Wrap client synchronously with shared state manager\n wrappedClientRef.current = wrapUnleashClient(unleashClient, stateManager);\n } else {\n // no toolbar - just use original client\n wrappedClientRef.current = unleashClient;\n }\n }\n \n // Create toolbar UI in useEffect (StrictMode-safe)\n useEffect(() => {\n // Only create toolbar if:\n // 1. toolbarOptions is defined\n // 2. No toolbar ref yet\n // 3. State manager exists\n // 4. Wrapped client doesn't already have a toolbar (prevents StrictMode duplicates)\n if (toolbarOptions !== undefined && \n !toolbarRef.current && \n stateManagerRef.current &&\n !(wrappedClientRef.current as any)?.__toolbar) {\n // Create toolbar with the same state manager used for wrapping\n const toolbar = new UnleashToolbar(stateManagerRef.current, wrappedClientRef.current as any, toolbarOptions);\n (wrappedClientRef.current as any).__toolbar = toolbar;\n toolbarRef.current = toolbar;\n \n // Expose globally\n if (typeof window !== 'undefined') {\n (window as any).unleashToolbar = toolbar;\n }\n }\n \n // Cleanup toolbar on unmount\n return () => {\n if (toolbarRef.current && typeof toolbarRef.current.destroy === 'function') {\n toolbarRef.current.destroy();\n toolbarRef.current = null;\n }\n };\n }, []);\n\n return (\n <FlagProvider\n unleashClient={wrappedClientRef.current}\n startClient={startClient}\n {...flagProviderProps}\n >\n {children}\n </FlagProvider>\n );\n}\n"],"names":["UnleashToolbarProvider","FlagProvider","DefaultFlagProvider","config","client","toolbarOptions","startClient","children","flagProviderProps","Error","toolbarRef","useRef","stateManagerRef","wrappedClientRef","current","unleashClient","UnleashClient","stateManager","ToolbarStateManager","storageMode","storageKey","sortAlphabetically","enableCookieSync","wrapUnleashClient","useEffect","__toolbar","toolbar","UnleashToolbar","window","unleashToolbar","destroy","jsx"],"mappings":"qSAsGO,SAASA,GAAuBC,aACrCA,EAAeC,EAAAC,OACfA,EAAAC,OACAA,EAAAC,eACAA,EAAiB,CAAA,EAACC,YAClBA,GAAc,EAAAC,SACdA,KACGC,IAGH,IAAKL,IAAWC,EACd,MAAM,IAAIK,MACR,6EAGJ,GAAIN,GAAUC,EACZ,MAAM,IAAIK,MACR,8EAIJ,MAAMC,EAAaC,EAAY,MACzBC,EAAkBD,EAAY,MAI9BE,EAAmBF,EAA6B,MAEtD,GAAiC,OAA7BE,EAAiBC,QAAkB,CACrC,MAAMC,EAAgBX,GAAU,IAAIY,EAAcb,GAElD,QAAuB,IAAnBE,EAA8B,CAEhC,MAGMY,EAAe,IAAIC,EAHLb,EAAec,aAAe,QAC/Bd,EAAee,YAAc,wBACrBf,EAAegB,qBAAsB,GAEhET,EAAgBE,QAAUG,EAEtBZ,EAAeiB,kBACjBL,EAAaK,mBAIfT,EAAiBC,QAAUS,EAAkBR,EAAeE,EAC9D,MAEEJ,EAAiBC,QAAUC,CAE/B,CAiCA,OA9BAS,EAAU,KAMR,QAAuB,IAAnBnB,IACCK,EAAWI,SACZF,EAAgBE,UACdD,EAAiBC,SAAiBW,UAAW,CAEjD,MAAMC,EAAU,IAAIC,EAAef,EAAgBE,QAASD,EAAiBC,QAAgBT,GAC5FQ,EAAiBC,QAAgBW,UAAYC,EAC9ChB,EAAWI,QAAUY,EAGC,oBAAXE,SACRA,OAAeC,eAAiBH,EAErC,CAGA,MAAO,KACDhB,EAAWI,SAAiD,mBAA/BJ,EAAWI,QAAQgB,UAClDpB,EAAWI,QAAQgB,UACnBpB,EAAWI,QAAU,QAGxB,mBAGDiB,EAAC9B,EAAA,CACCc,cAAeF,EAAiBC,QAChCR,iBACIE,EAEHD,YAGP"}
export {};
//# sourceMappingURL=index.test.d.ts.map
{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../../src/react/__tests__/index.test.tsx"],"names":[],"mappings":""}
/**
* Re-export hooks from the official Unleash React SDK
* This allows users to import all React hooks from the toolbar package:
*
* import { useFlag, useVariant } from '@unleash/toolbar/react';
*/
export { useFlag, useFlags, useFlagsStatus, useUnleashClient, useUnleashContext, useVariant, } from '@unleash/proxy-client-react';
//# sourceMappingURL=hooks.d.ts.map
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/react/hooks.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACL,OAAO,EACP,QAAQ,EACR,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,UAAU,GACX,MAAM,6BAA6B,CAAC"}
import { UnleashClient, IConfig } from 'unleash-proxy-client';
import { InitToolbarOptions } from '../types';
import { default as React } from 'react';
/**
* Base props shared by both config and client variants
*/
interface BaseToolbarProviderProps {
/**
* The official FlagProvider component from @unleash/proxy-client-react
* Optional - defaults to the standard FlagProvider
*/
FlagProvider?: React.ComponentType<any>;
/**
* Optional toolbar configuration
* Set to undefined to disable toolbar in production
*/
toolbarOptions?: InitToolbarOptions;
/**
* Whether to automatically start the client
* Defaults to true
*/
startClient?: boolean;
/**
* Children components
*/
children: React.ReactNode;
/**
* Any additional props to pass to the official FlagProvider
*/
[key: string]: any;
}
/**
* Props when using config-based initialization
*/
interface ConfigBasedProps extends BaseToolbarProviderProps {
/**
* Unleash SDK configuration object (same as official React SDK)
*/
config: IConfig;
client?: never;
}
/**
* Props when using pre-instantiated client
*/
interface ClientBasedProps extends BaseToolbarProviderProps {
/**
* Pre-instantiated Unleash client (will be wrapped with toolbar)
*/
client: UnleashClient;
config?: never;
}
/**
* Props for the UnleashToolbarProvider - either config OR client must be provided
*/
type UnleashToolbarProviderProps = ConfigBasedProps | ClientBasedProps;
/**
* Higher-order provider that wraps the official Unleash React SDK's FlagProvider
* and initializes the toolbar with a wrapped client.
*
* Simple usage (no imports needed):
* ```tsx
* import { UnleashToolbarProvider } from '@unleash/toolbar/react';
*
* function App() {
* return (
* <UnleashToolbarProvider
* config={{
* url: 'https://your-unleash-instance.com/api/frontend',
* clientKey: 'your-client-key',
* appName: 'my-app'
* }}
* toolbarOptions={{ themePreset: 'dark' }}
* >
* <YourApp />
* </UnleashToolbarProvider>
* );
* }
* ```
*
* Advanced usage with custom FlagProvider:
* ```tsx
* import { FlagProvider } from '@unleash/proxy-client-react';
*
* <UnleashToolbarProvider
* FlagProvider={FlagProvider}
* config={{ ... }}
* >
* <YourApp />
* </UnleashToolbarProvider>
* ```
*/
export declare function UnleashToolbarProvider({ FlagProvider, config, client, toolbarOptions, startClient, children, ...flagProviderProps }: UnleashToolbarProviderProps): import("react/jsx-runtime").JSX.Element;
export {};
//# sourceMappingURL=index.d.ts.map
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,KAAK,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAGnE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AACnD,OAAO,KAA4B,MAAM,OAAO,CAAC;AAEjD;;GAEG;AACH,UAAU,wBAAwB;IAChC;;;OAGG;IACH,YAAY,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IAExC;;;OAGG;IACH,cAAc,CAAC,EAAE,kBAAkB,CAAC;IAEpC;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;OAEG;IACH,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAE1B;;OAEG;IACH,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED;;GAEG;AACH,UAAU,gBAAiB,SAAQ,wBAAwB;IACzD;;OAEG;IACH,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,KAAK,CAAC;CAChB;AAED;;GAEG;AACH,UAAU,gBAAiB,SAAQ,wBAAwB;IACzD;;OAEG;IACH,MAAM,EAAE,aAAa,CAAC;IACtB,MAAM,CAAC,EAAE,KAAK,CAAC;CAChB;AAED;;GAEG;AACH,KAAK,2BAA2B,GAAG,gBAAgB,GAAG,gBAAgB,CAAC;AAEvE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,YAAkC,EAClC,MAAM,EACN,MAAM,EACN,cAAmB,EACnB,WAAkB,EAClB,QAAQ,EACR,GAAG,iBAAiB,EACrB,EAAE,2BAA2B,2CAmF7B"}
import { FlagMetadata, FlagOverride, FlagValue, StorageMode, ToolbarEventListener, ToolbarState, UnleashContext, UnleashVariant } from './types';
/**
* Core state manager for the toolbar
*/
export declare class ToolbarStateManager {
private state;
private eventEmitter;
private storage;
private sortAlphabetically;
constructor(storageMode?: StorageMode, storageKey?: string, sortAlphabetically?: boolean);
private getInitialState;
private persist;
/**
* Apply override to a default value (same logic as wrapper)
*/
private applyOverride;
/**
* Re-evaluate all known flags (used when SDK configuration updates)
*/
reEvaluateAllFlags(evaluator: (flagName: string) => {
defaultValue: FlagValue;
effectiveValue: FlagValue;
}): void;
/**
* Get the current state (immutable copy)
*/
getState(): ToolbarState;
/**
* Subscribe to state change events
*/
subscribe(listener: ToolbarEventListener): () => void;
/**
* Record a flag evaluation (updates state without emitting events)
*/
recordEvaluation(name: string, flagType: 'flag' | 'variant', defaultValue: boolean | UnleashVariant | null, effectiveValue: boolean | UnleashVariant | null, context: UnleashContext): void;
/**
* Set or clear a flag override
*/
setFlagOverride(name: string, override: FlagOverride | null): void;
/**
* Get flag override
*/
getFlagOverride(name: string): FlagOverride | null;
/**
* Set context overrides
*/
setContextOverride(context: Partial<UnleashContext>): void;
/**
* Remove a specific context override field
*/
removeContextOverride(fieldName: keyof UnleashContext): void;
/**
* Get merged context (original + overrides)
*/
getMergedContext(baseContext?: UnleashContext): UnleashContext;
/**
* Reset all flag overrides
*/
resetOverrides(): void;
/**
* Reset context overrides
*/
resetContextOverrides(): void;
/**
* Set toolbar visibility state
*/
setVisibility(isVisible: boolean): void;
/**
* Get toolbar visibility state
*/
getVisibility(): boolean | undefined;
/**
* Clear all persisted data
*/
clearPersistence(): void;
/**
* Get all flag names in evaluation order (insertion order) or alphabetically
*/
getFlagNames(): string[];
/**
* Get metadata for a specific flag
*/
getFlagMetadata(name: string): FlagMetadata | null;
/**
* Enable cookie synchronization for server-side rendering support
* Should be called by Next.js integration when SSR is needed
*/
enableCookieSync(): void;
}
//# sourceMappingURL=state.d.ts.map
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,WAAW,EAEX,oBAAoB,EACpB,YAAY,EACZ,cAAc,EACd,cAAc,EACf,MAAM,SAAS,CAAC;AA2KjB;;GAEG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,kBAAkB,CAAU;gBAGlC,WAAW,GAAE,WAAqB,EAClC,UAAU,GAAE,MAAgC,EAC5C,kBAAkB,GAAE,OAAe;IAWrC,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,OAAO;IAIf;;OAEG;IACH,OAAO,CAAC,aAAa;IA+BrB;;OAEG;IACH,kBAAkB,CAChB,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK;QAAE,YAAY,EAAE,SAAS,CAAC;QAAC,cAAc,EAAE,SAAS,CAAA;KAAE,GACtF,IAAI;IA8BP;;OAEG;IACH,QAAQ,IAAI,YAAY;IAIxB;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,oBAAoB,GAAG,MAAM,IAAI;IAIrD;;OAEG;IACH,gBAAgB,CACd,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,YAAY,EAAE,OAAO,GAAG,cAAc,GAAG,IAAI,EAC7C,cAAc,EAAE,OAAO,GAAG,cAAc,GAAG,IAAI,EAC/C,OAAO,EAAE,cAAc,GACtB,IAAI;IAuBP;;OAEG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,GAAG,IAAI,GAAG,IAAI;IA6BlE;;OAEG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI;IAIlD;;OAEG;IACH,kBAAkB,CAAC,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI;IAc1D;;OAEG;IACH,qBAAqB,CAAC,SAAS,EAAE,MAAM,cAAc,GAAG,IAAI;IAc5D;;OAEG;IACH,gBAAgB,CAAC,WAAW,GAAE,cAAmB,GAAG,cAAc;IAWlE;;OAEG;IACH,cAAc,IAAI,IAAI;IAoBtB;;OAEG;IACH,qBAAqB,IAAI,IAAI;IAW7B;;OAEG;IACH,aAAa,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI;IAKvC;;OAEG;IACH,aAAa,IAAI,OAAO,GAAG,SAAS;IAIpC;;OAEG;IACH,gBAAgB,IAAI,IAAI;IAIxB;;OAEG;IACH,YAAY,IAAI,MAAM,EAAE;IAKxB;;OAEG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI;IAIlD;;;OAGG;IACH,gBAAgB,IAAI,IAAI;CAGzB"}
.unleash-toolbar-container{--ut-primary:#6c65e5;--ut-bg:#fff;--ut-text:#1f2021;--ut-border:#e1e1e3;--ut-hover:#f5f6fa;--ut-success:#00b894;--ut-danger:#d63031;--ut-warning:#fdcb6e;--ut-shadow:rgba(0,0,0,.1);--ut-font:-apple-system,BlinkMacSystemFont,"Segoe UI","Roboto","Oxygen","Ubuntu",sans-serif;all:initial;position:fixed;z-index:999998}.unleash-toolbar-container.ut-theme-dark{--ut-primary:#4c4992;--ut-bg:#1a1923;--ut-text:#eeeefc;--ut-border:#39384c;--ut-hover:#3d4446;--ut-success:#00b894;--ut-danger:#ff7675;--ut-warning:#fdcb6e;--ut-shadow:rgba(0,0,0,.3)}.unleash-toolbar button,.unleash-toolbar input,.unleash-toolbar-container{box-sizing:border-box;font-family:inherit;letter-spacing:normal;line-height:inherit;margin:0;text-transform:none;word-spacing:normal}.unleash-toolbar input{background:var(--ut-bg);color:var(--ut-text);margin:0}.unleash-toolbar img{border:none;max-width:none;vertical-align:middle}.unleash-toolbar img,.unleash-toolbar svg{display:inline-block;height:auto;max-width:none}.unleash-toolbar-container.position-top-left{left:20px;top:20px}.unleash-toolbar-container.position-top-right{right:20px;top:20px}.unleash-toolbar-container.position-bottom-left{bottom:20px;left:20px}.unleash-toolbar-container.position-bottom-right{bottom:20px;right:20px}.unleash-toolbar-container.position-left{left:20px;top:50%;transform:translateY(-50%)}.unleash-toolbar-container.position-right{right:20px;top:50%;transform:translateY(-50%)}.unleash-toolbar-container .ut-toggle{all:initial;align-items:center;background:var(--ut-primary);border:none;border-radius:50%;box-shadow:0 4px 12px var(--ut-shadow);cursor:pointer;display:flex;height:48px;justify-content:center;padding:0;position:relative;transition:all .3s ease;width:48px}.unleash-toolbar-container .ut-toggle:hover{box-shadow:0 6px 16px rgba(0,0,0,.2);transform:scale(1.1)}.unleash-toolbar-container .ut-toggle img{height:28px;object-fit:contain;width:28px}.unleash-toolbar-container .unleash-toolbar{all:initial;background:var(--ut-bg);border:1px solid var(--ut-border);border-radius:8px;box-shadow:0 4px 12px var(--ut-shadow);box-sizing:border-box;color:var(--ut-text);display:flex;flex-direction:column;font-family:var(--ut-font);font-size:14px;height:700px;line-height:1.5;max-height:85vh;min-height:400px;overflow:hidden;position:relative;width:400px}.unleash-toolbar-container .unleash-toolbar *{box-sizing:border-box}.unleash-toolbar .ut-header{align-items:center;background:var(--ut-primary);border-bottom:1px solid var(--ut-border);color:#fff;display:flex;flex-shrink:0;gap:12px;justify-content:space-between;padding:12px 20px 12px 12px;position:relative}.unleash-toolbar .ut-title{align-items:center;display:flex;flex:1;gap:10px;min-width:0}.unleash-toolbar .ut-title img{flex-shrink:0;height:28px;object-fit:contain;width:28px}.unleash-toolbar .ut-title-main{font-size:14px;font-weight:600;line-height:1.3}.unleash-toolbar .ut-title-sub{font-size:11px;margin-top:1px;opacity:.9}.unleash-toolbar .ut-actions{align-items:center;display:flex;gap:4px}.unleash-toolbar .ut-btn-icon{align-items:center;background:hsla(0,0%,100%,.1);border:1px solid hsla(0,0%,100%,.15);border-radius:4px;color:#fff;cursor:pointer;display:flex;flex-shrink:0;font-size:16px;height:24px;justify-content:center;line-height:1;padding:0;transition:all .2s;width:24px}.unleash-toolbar .ut-btn-icon:hover{background:hsla(0,0%,100%,.2);border-color:hsla(0,0%,100%,.25)}.unleash-toolbar .ut-btn-small{background:hsla(0,0%,100%,.15);border:1px solid hsla(0,0%,100%,.2);color:#fff;white-space:nowrap}.unleash-toolbar .ut-btn-small:hover{background:hsla(0,0%,100%,.25);border-color:hsla(0,0%,100%,.3)}.unleash-toolbar .ut-btn{background:hsla(0,0%,100%,.2);border:none;border-radius:4px;color:#fff;cursor:pointer;font-family:inherit;font-size:12px;padding:6px 12px;transition:background .2s}.unleash-toolbar .ut-btn:hover{background:hsla(0,0%,100%,.3)}.unleash-toolbar .ut-btn-close{align-items:center;background-color:var(--ut-primary);border:none;color:#fff;cursor:pointer;display:flex;flex-shrink:0;font-size:18px;height:24px;justify-content:center;line-height:1;padding:0;transition:all .2s;width:24px}.unleash-toolbar .ut-btn-close:hover{background:rgba(0,0,0,.3);border-color:hsla(0,0%,100%,.2)}.unleash-toolbar .ut-tabs{background:var(--ut-bg);display:flex;flex-shrink:0}.unleash-toolbar .ut-tab{background:none;border:none;border-bottom:2px solid transparent;color:var(--ut-text);cursor:pointer;flex:1;font-family:inherit;font-size:13px;padding:12px;transition:all .2s}.unleash-toolbar .ut-tab:hover{background:var(--ut-hover)}.unleash-toolbar .ut-tab.active{border-bottom-color:var(--ut-primary);font-weight:600}.unleash-toolbar .ut-content{display:flex;flex:1;flex-direction:column;overflow-y:auto}.unleash-toolbar .ut-tab-header{align-items:center;background:var(--ut-bg);display:flex;flex-shrink:0;gap:12px;padding:12px 16px}.unleash-toolbar .ut-search-container{flex:1;min-width:0}.unleash-toolbar .ut-search-input{border:1px solid var(--ut-border);border-radius:6px;font-family:inherit;font-size:13px;padding:8px 12px;transition:border-color .2s;width:100%}.unleash-toolbar .ut-search-input:focus{border-color:var(--ut-primary);outline:none}.unleash-toolbar .ut-search-input::placeholder{color:var(--ut-text);opacity:.5}.unleash-toolbar .ut-tab-header .ut-btn{background:var(--ut-primary);border:none;border-radius:6px;color:#fff;cursor:pointer;flex-shrink:0;font-family:inherit;font-size:13px;font-weight:500;padding:8px 16px;transition:all .2s;white-space:nowrap}.unleash-toolbar .ut-tab-header .ut-btn:hover{box-shadow:0 2px 4px rgba(0,0,0,.1);opacity:.9;transform:translateY(-1px)}.unleash-toolbar .ut-flag-list{display:flex;flex:1;flex-direction:column;gap:8px;overflow-y:auto;padding:16px}.unleash-toolbar .ut-flag-item{align-items:center;background:var(--ut-bg);border:1px solid var(--ut-border);border-radius:6px;display:flex;gap:12px;min-height:48px;padding:10px 12px}.unleash-toolbar .ut-flag-main{flex:1;min-width:0}.unleash-toolbar .ut-flag-header{align-items:flex-start;display:flex;flex-direction:column;gap:6px}.unleash-toolbar .ut-flag-title-row{align-items:center;display:flex;flex-wrap:wrap;gap:6px}.unleash-toolbar .ut-flag-name{flex-shrink:0;font-size:13px;font-weight:600;word-break:break-word}.unleash-toolbar .ut-flag-meta{align-items:center;display:flex;flex-wrap:wrap;font-size:11px;gap:8px}.unleash-toolbar .ut-flag-default-value{align-items:center;color:#636e72;display:flex;font-size:11px;gap:4px}.unleash-toolbar .ut-override-indicator{align-items:center;color:var(--ut-primary);display:flex;font-weight:500;gap:4px}.unleash-toolbar .ut-eval-count{font-size:10px;opacity:.6}.unleash-toolbar .ut-flag-control{flex-shrink:0}.unleash-toolbar .ut-badge{border-radius:3px;font-size:10px;font-weight:600;padding:2px 6px}.unleash-toolbar .ut-badge-success{background:#d4edda;color:#155724}.unleash-toolbar .ut-badge-danger{background:#f8d7da;color:#721c24}.unleash-toolbar .ut-badge-default{background:#e2e3e5;color:#383d41}.unleash-toolbar .ut-toggle-group{background:var(--ut-hover);border:1px solid var(--ut-border);border-radius:5px;display:flex;gap:3px;padding:2px}.unleash-toolbar .ut-toggle-btn{background:transparent;border:none;border-radius:4px;color:var(--ut-text);cursor:pointer;font-family:inherit;font-size:11px;font-weight:500;min-width:36px;padding:4px 10px;transition:all .15s ease;white-space:nowrap}.unleash-toolbar .ut-toggle-btn:hover:not(.active){background:hsla(0,0%,100%,.5)}.unleash-toolbar .ut-toggle-btn.active{background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.1);color:var(--ut-primary);font-weight:600}.unleash-toolbar .ut-variant-control{display:flex;flex-direction:column;gap:6px;min-width:120px}.unleash-toolbar .ut-variant-override-toggle{align-items:center;border-radius:4px;cursor:pointer;display:flex;font-size:12px;gap:6px;padding:6px 10px;transition:background .15s}.unleash-toolbar .ut-variant-override-toggle:hover{background:var(--ut-hover)}.unleash-toolbar .ut-variant-override-toggle input[type=checkbox]{cursor:pointer}.unleash-toolbar .ut-input-small{border:1px solid var(--ut-border);border-radius:4px;font-family:inherit;font-size:11px;padding:4px 8px;width:100%}.unleash-toolbar .ut-input-small:focus{border-color:var(--ut-primary);outline:none}.unleash-toolbar .ut-btn-small{font-weight:500;padding:4px 10px;transition:all .15s}.unleash-toolbar .ut-btn-small.active{background:var(--ut-primary);border-color:var(--ut-primary);color:#fff}.unleash-toolbar .ut-override-control{display:flex;gap:8px;margin-top:8px}.unleash-toolbar .ut-btn-small{background:var(--ut-hover);border:1px solid var(--ut-border);border-radius:4px;color:var(--ut-text);cursor:pointer;font-family:inherit;font-size:11px;padding:6px 10px;transition:all .2s}.unleash-toolbar .ut-btn-small:hover{background:var(--ut-border)}.unleash-toolbar .ut-context-form{display:flex;flex:1;flex-direction:column;gap:12px;overflow-y:auto;padding:16px}.unleash-toolbar .ut-form-group{display:flex;flex-direction:column;gap:4px;position:relative}.unleash-toolbar .ut-label{align-items:center;color:var(--ut-text);display:flex;font-size:12px;font-weight:600;gap:6px}.unleash-toolbar .ut-readonly-label{font-size:11px;opacity:.6}.unleash-toolbar .ut-input-with-reset{display:block;position:relative;width:100%}.unleash-toolbar .ut-input-with-reset .ut-input{padding-right:32px;width:100%}.unleash-toolbar .ut-reset-field{align-items:center;background:var(--ut-hover);border:1px solid var(--ut-border);border-radius:4px;bottom:4px;color:var(--ut-text);cursor:pointer;display:flex;font-size:14px;justify-content:center;line-height:1;margin:auto 0;padding:0;position:absolute;right:4px;top:4px;transition:all .15s;width:24px}.unleash-toolbar .ut-reset-field:hover{background:var(--ut-border);border-color:var(--ut-primary);color:var(--ut-primary)}.unleash-toolbar .ut-property-actions{display:flex;flex-shrink:0;gap:4px}.unleash-toolbar .ut-btn-remove{background:var(--ut-hover);border:1px solid var(--ut-border);border-radius:4px;color:#d63031;cursor:pointer;flex-shrink:0;font-size:16px;font-weight:700;height:32px;line-height:1;padding:0;transition:all .15s;width:24px}.unleash-toolbar .ut-btn-remove:hover{background:#fee;border-color:#d63031;color:#d63031}.unleash-toolbar .ut-input{border:1px solid var(--ut-border);border-radius:4px;font-family:inherit;font-size:13px;padding:8px 12px}.unleash-toolbar .ut-input:focus{border-color:var(--ut-primary);outline:none}.unleash-toolbar .ut-input-readonly{cursor:not-allowed;opacity:.7}.unleash-toolbar .ut-properties{display:flex;flex-direction:column;gap:8px}.unleash-toolbar .ut-property-row{align-items:center;display:flex;gap:8px;min-width:0}.unleash-toolbar .ut-property-key{background:var(--ut-bg-secondary);border-radius:4px;color:var(--ut-text);flex:0 0 auto;font-size:13px;max-width:200px;min-width:120px;opacity:.8;overflow:hidden;padding:8px 12px;text-overflow:ellipsis;white-space:nowrap}.unleash-toolbar .ut-property-row .ut-input-with-reset{flex:1;min-width:0}.unleash-toolbar .ut-empty{color:#636e72;font-size:13px;padding:40px 20px;text-align:center}.unleash-toolbar .ut-empty-properties{color:var(--ut-text);font-size:12px;margin-bottom:8px}.unleash-toolbar .ut-stats{display:grid;gap:8px;grid-template-columns:repeat(2,1fr);margin-bottom:16px}.unleash-toolbar .ut-stat-card{background:var(--ut-hover);border-radius:6px;padding:12px;text-align:center}.unleash-toolbar .ut-stat-value{color:var(--ut-primary);font-size:24px;font-weight:700}.unleash-toolbar .ut-stat-label{color:#636e72;font-size:11px;margin-top:4px}.unleash-toolbar .ut-content::-webkit-scrollbar{width:10px}.unleash-toolbar .ut-content::-webkit-scrollbar-track{background:var(--ut-hover);border-radius:5px}.unleash-toolbar .ut-content::-webkit-scrollbar-thumb{background:var(--ut-primary);border:2px solid var(--ut-bg);border-radius:5px}.unleash-toolbar .ut-content::-webkit-scrollbar-thumb:hover{background:var(--ut-primary);opacity:.8}.unleash-toolbar .ut-flag-list::-webkit-scrollbar{width:10px}.unleash-toolbar .ut-flag-list::-webkit-scrollbar-track{background:var(--ut-hover);border-radius:5px}.unleash-toolbar .ut-flag-list::-webkit-scrollbar-thumb{background:var(--ut-primary);border:2px solid var(--ut-bg);border-radius:5px}.unleash-toolbar .ut-flag-list::-webkit-scrollbar-thumb:hover{background:var(--ut-primary);opacity:.8}
import { UnleashClient } from 'unleash-proxy-client';
/**
* Unleash context used for feature flag evaluation
*/
export interface UnleashContext {
userId?: string;
sessionId?: string;
remoteAddress?: string;
environment?: string;
appName?: string;
properties?: Record<string, string>;
}
/**
* Unleash variant structure
*/
export interface UnleashVariant {
name: string;
enabled: boolean;
payload?: {
type: string;
value: string;
};
}
/**
* Flag override types
*/
export type FlagOverride = {
type: 'flag';
value: boolean;
} | {
type: 'variant';
variantKey: string;
};
/**
* Metadata for a single flag evaluation
*/
export interface FlagMetadata {
flagType: 'flag' | 'variant';
lastDefaultValue: FlagValue;
lastEffectiveValue: FlagValue;
lastContext: UnleashContext | null;
override: FlagOverride | null;
}
export type FlagValue = boolean | UnleashVariant | null;
/**
* Complete toolbar state
*/
export interface ToolbarState {
flags: {
[featureName: string]: FlagMetadata;
};
contextOverrides: Partial<UnleashContext>;
isVisible?: boolean;
}
/**
* Storage mode options
*
* - **local**: Persists across browser tabs and page reloads. Best for development
* as overrides remain active across the entire browser session and even after
* closing/reopening the browser. (DEFAULT)
*
* - **session**: Persists only within the current browser tab. Overrides survive
* page reloads but are lost when the tab is closed. Useful when testing different
* configurations in different tabs without interference.
*
* - **memory**: No persistence - overrides lost on page reload. Useful for
* quick temporary testing or when you need complete isolation between page loads.
* Also appropriate for strict security/privacy requirements where no data should
* be written to disk.
*/
export type StorageMode = 'memory' | 'session' | 'local';
/**
* Theme customization options
*/
export interface ToolbarThemeOptions {
primaryColor?: string;
backgroundColor?: string;
textColor?: string;
borderColor?: string;
fontFamily?: string;
}
/**
* Built-in theme presets
*/
export type ThemePreset = 'light' | 'dark';
/**
* Initialization options for the toolbar
*/
export interface InitToolbarOptions {
/** Storage persistence mode (default: 'local') */
storageMode?: StorageMode;
/** Storage key for persisted state (default: 'unleash-toolbar-state') */
storageKey?: string;
/** Built-in theme preset (default: 'light') */
themePreset?: ThemePreset;
/** Custom theme colors (overrides themePreset if provided) */
theme?: ToolbarThemeOptions;
/** Container element (default: document.body) */
container?: HTMLElement | null;
/** Toolbar position (default: 'bottom-right') */
position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'left' | 'right';
/** Whether toolbar is visible on initialization (default: true, but respects persisted state if available) */
initiallyVisible?: boolean;
/** Sort flags alphabetically instead of by evaluation order (default: false) */
sortAlphabetically?: boolean;
/** Enable cookie synchronization for server-side rendering (Next.js) (default: false) */
enableCookieSync?: boolean;
}
/**
* Toolbar event types (internal use only - not part of public API)
* @internal
*/
export type ToolbarEvent = {
type: 'flag_override_changed';
name: string;
override: FlagOverride | null;
timestamp: number;
} | {
type: 'context_override_changed';
contextOverrides: Partial<UnleashContext>;
} | {
type: 'sdk_updated';
timestamp: number;
};
/**
* Event listener function (internal use only - not part of public API)
* @internal
*/
export type ToolbarEventListener = (event: ToolbarEvent) => void;
/**
* Toolbar UI interface (implemented by UI modules)
*/
export interface IToolbarUI {
show(): void;
hide(): void;
destroy(): void;
}
/**
* Main toolbar instance API
*/
export interface UnleashToolbarInstance {
readonly client: WrappedUnleashClient;
show(): void;
hide(): void;
destroy(): void;
getState(): ToolbarState;
getFlagNames(): string[];
setFlagOverride(name: string, override: FlagOverride | null): void;
setContextOverride(context: Partial<UnleashContext>): void;
removeContextOverride(fieldName: keyof UnleashContext): void;
resetOverrides(): void;
resetContextOverrides(): void;
}
/**
* Wrapped Unleash client with override support.
* Extends the SDK client type and adds the __original property.
*/
export interface WrappedUnleashClient extends UnleashClient {
__original: UnleashClient;
__toolbar?: UnleashToolbarInstance;
}
//# sourceMappingURL=types.d.ts.map
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
const t=globalThis,e=t=>t,s=t.trustedTypes,i=s?s.createPolicy("lit-html",{createHTML:t=>t}):void 0,r="$lit$",n=`lit$${Math.random().toFixed(9).slice(2)}$`,a="?"+n,o=`<${a}>`,l=document,d=()=>l.createComment(""),h=t=>null===t||"object"!=typeof t&&"function"!=typeof t,u=Array.isArray,c="[ \t\n\f\r]",v=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,p=/-->/g,g=/>/g,$=RegExp(`>|${c}(?:([^\\s"'>=/]+)(${c}*=${c}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),m=/'/g,f=/"/g,b=/^(?:script|style|textarea|title)$/i,A=(t,...e)=>({_$litType$:1,strings:t,values:e}),y=Symbol.for("lit-noChange"),_=Symbol.for("lit-nothing"),x=new WeakMap,C=l.createTreeWalker(l,129);function T(t,e){if(!u(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==i?i.createHTML(e):e}const O=(t,e)=>{const s=t.length-1,i=[];let a,l=2===e?"<svg>":3===e?"<math>":"",d=v;for(let h=0;h<s;h++){const e=t[h];let s,u,c=-1,A=0;for(;A<e.length&&(d.lastIndex=A,u=d.exec(e),null!==u);)A=d.lastIndex,d===v?"!--"===u[1]?d=p:void 0!==u[1]?d=g:void 0!==u[2]?(b.test(u[2])&&(a=RegExp("</"+u[2],"g")),d=$):void 0!==u[3]&&(d=$):d===$?">"===u[0]?(d=a??v,c=-1):void 0===u[1]?c=-2:(c=d.lastIndex-u[2].length,s=u[1],d=void 0===u[3]?$:'"'===u[3]?f:m):d===f||d===m?d=$:d===p||d===g?d=v:(d=$,a=void 0);const y=d===$&&t[h+1].startsWith("/>")?" ":"";l+=d===v?e+o:c>=0?(i.push(s),e.slice(0,c)+r+e.slice(c)+n+y):e+n+(-2===c?h:y)}return[T(t,l+(t[s]||"<?>")+(2===e?"</svg>":3===e?"</math>":"")),i]};class F{constructor({strings:t,_$litType$:e},i){let o;this.parts=[];let l=0,h=0;const u=t.length-1,c=this.parts,[v,p]=O(t,e);if(this.el=F.createElement(v,i),C.currentNode=this.el.content,2===e||3===e){const t=this.el.content.firstChild;t.replaceWith(...t.childNodes)}for(;null!==(o=C.nextNode())&&c.length<u;){if(1===o.nodeType){if(o.hasAttributes())for(const t of o.getAttributeNames())if(t.endsWith(r)){const e=p[h++],s=o.getAttribute(t).split(n),i=/([.?@])?(.*)/.exec(e);c.push({type:1,index:l,name:i[2],strings:s,ctor:"."===i[1]?V:"?"===i[1]?k:"@"===i[1]?E:w}),o.removeAttribute(t)}else t.startsWith(n)&&(c.push({type:6,index:l}),o.removeAttribute(t));if(b.test(o.tagName)){const t=o.textContent.split(n),e=t.length-1;if(e>0){o.textContent=s?s.emptyScript:"";for(let s=0;s<e;s++)o.append(t[s],d()),C.nextNode(),c.push({type:2,index:++l});o.append(t[e],d())}}}else if(8===o.nodeType)if(o.data===a)c.push({type:2,index:l});else{let t=-1;for(;-1!==(t=o.data.indexOf(n,t+1));)c.push({type:7,index:l}),t+=n.length-1}l++}}static createElement(t,e){const s=l.createElement("template");return s.innerHTML=t,s}}function M(t,e,s=t,i){if(e===y)return e;let r=void 0!==i?s._$Co?.[i]:s._$Cl;const n=h(e)?void 0:e._$litDirective$;return r?.constructor!==n&&(r?._$AO?.(!1),void 0===n?r=void 0:(r=new n(t),r._$AT(t,s,i)),void 0!==i?(s._$Co??=[])[i]=r:s._$Cl=r),void 0!==r&&(e=M(t,r._$AS(t,e.values),r,i)),e}class N{constructor(t,e){this._$AV=[],this._$AN=void 0,this._$AD=t,this._$AM=e}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}u(t){const{el:{content:e},parts:s}=this._$AD,i=(t?.creationScope??l).importNode(e,!0);C.currentNode=i;let r=C.nextNode(),n=0,a=0,o=s[0];for(;void 0!==o;){if(n===o.index){let e;2===o.type?e=new H(r,r.nextSibling,this,t):1===o.type?e=new o.ctor(r,o.name,o.strings,this,t):6===o.type&&(e=new P(r,this,t)),this._$AV.push(e),o=s[++a]}n!==o?.index&&(r=C.nextNode(),n++)}return C.currentNode=l,i}p(t){let e=0;for(const s of this._$AV)void 0!==s&&(void 0!==s.strings?(s._$AI(t,s,e),e+=s.strings.length-2):s._$AI(t[e])),e++}}class H{get _$AU(){return this._$AM?._$AU??this._$Cv}constructor(t,e,s,i){this.type=2,this._$AH=_,this._$AN=void 0,this._$AA=t,this._$AB=e,this._$AM=s,this.options=i,this._$Cv=i?.isConnected??!0}get parentNode(){let t=this._$AA.parentNode;const e=this._$AM;return void 0!==e&&11===t?.nodeType&&(t=e.parentNode),t}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(t,e=this){t=M(this,t,e),h(t)?t===_||null==t||""===t?(this._$AH!==_&&this._$AR(),this._$AH=_):t!==this._$AH&&t!==y&&this._(t):void 0!==t._$litType$?this.$(t):void 0!==t.nodeType?this.T(t):(t=>u(t)||"function"==typeof t?.[Symbol.iterator])(t)?this.k(t):this._(t)}O(t){return this._$AA.parentNode.insertBefore(t,this._$AB)}T(t){this._$AH!==t&&(this._$AR(),this._$AH=this.O(t))}_(t){this._$AH!==_&&h(this._$AH)?this._$AA.nextSibling.data=t:this.T(l.createTextNode(t)),this._$AH=t}$(t){const{values:e,_$litType$:s}=t,i="number"==typeof s?this._$AC(t):(void 0===s.el&&(s.el=F.createElement(T(s.h,s.h[0]),this.options)),s);if(this._$AH?._$AD===i)this._$AH.p(e);else{const t=new N(i,this),s=t.u(this.options);t.p(e),this.T(s),this._$AH=t}}_$AC(t){let e=x.get(t.strings);return void 0===e&&x.set(t.strings,e=new F(t)),e}k(t){u(this._$AH)||(this._$AH=[],this._$AR());const e=this._$AH;let s,i=0;for(const r of t)i===e.length?e.push(s=new H(this.O(d()),this.O(d()),this,this.options)):s=e[i],s._$AI(r),i++;i<e.length&&(this._$AR(s&&s._$AB.nextSibling,i),e.length=i)}_$AR(t=this._$AA.nextSibling,s){for(this._$AP?.(!1,!0,s);t!==this._$AB;){const s=e(t).nextSibling;e(t).remove(),t=s}}setConnected(t){void 0===this._$AM&&(this._$Cv=t,this._$AP?.(t))}}class w{get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}constructor(t,e,s,i,r){this.type=1,this._$AH=_,this._$AN=void 0,this.element=t,this.name=e,this._$AM=i,this.options=r,s.length>2||""!==s[0]||""!==s[1]?(this._$AH=Array(s.length-1).fill(new String),this.strings=s):this._$AH=_}_$AI(t,e=this,s,i){const r=this.strings;let n=!1;if(void 0===r)t=M(this,t,e,0),n=!h(t)||t!==this._$AH&&t!==y,n&&(this._$AH=t);else{const i=t;let a,o;for(t=r[0],a=0;a<r.length-1;a++)o=M(this,i[s+a],e,a),o===y&&(o=this._$AH[a]),n||=!h(o)||o!==this._$AH[a],o===_?t=_:t!==_&&(t+=(o??"")+r[a+1]),this._$AH[a]=o}n&&!i&&this.j(t)}j(t){t===_?this.element.removeAttribute(this.name):this.element.setAttribute(this.name,t??"")}}class V extends w{constructor(){super(...arguments),this.type=3}j(t){this.element[this.name]=t===_?void 0:t}}class k extends w{constructor(){super(...arguments),this.type=4}j(t){this.element.toggleAttribute(this.name,!!t&&t!==_)}}class E extends w{constructor(t,e,s,i,r){super(t,e,s,i,r),this.type=5}_$AI(t,e=this){if((t=M(this,t,e,0)??_)===y)return;const s=this._$AH,i=t===_&&s!==_||t.capture!==s.capture||t.once!==s.once||t.passive!==s.passive,r=t!==_&&(s===_||i);i&&this.element.removeEventListener(this.name,this,s),r&&this.element.addEventListener(this.name,this,t),this._$AH=t}handleEvent(t){"function"==typeof this._$AH?this._$AH.call(this.options?.host??this.element,t):this._$AH.handleEvent(t)}}class P{constructor(t,e,s){this.element=t,this.type=6,this._$AN=void 0,this._$AM=e,this.options=s}get _$AU(){return this._$AM._$AU}_$AI(t){M(this,t)}}const I=t.litHtmlPolyfillSupport;I?.(F,H),(t.litHtmlVersions??=[]).push("3.3.2");const S="https://cdn.getunleash.io/docs-assets/unleash_logo_icon.svg";class U{container;rootElement;stateManager;currentTab="flags";position;themePreset;customTheme;originalBaseContext;searchQuery="";constructor(t,e,s={}){this.stateManager=t,this.position=s.position||"bottom-right",this.themePreset=s.themePreset||"light",this.customTheme=s.theme,this.originalBaseContext=e.__original.getContext();const i=this.stateManager.getVisibility();void 0===i&&this.stateManager.setVisibility(void 0!==i?i:s.initiallyVisible??!1),this.rootElement=document.createElement("div"),this.rootElement.className=`unleash-toolbar-container position-${this.position}`,"dark"===this.themePreset&&this.rootElement.classList.add("ut-theme-dark"),this.applyCustomTheme(this.rootElement),this.container=s.container||document.body,this.container.appendChild(this.rootElement),this.stateManager.subscribe(()=>{this.render()}),this.render()}applyCustomTheme(t){if(!this.customTheme)return;const e=t.style;this.customTheme.primaryColor&&e.setProperty("--ut-primary",this.customTheme.primaryColor),this.customTheme.backgroundColor&&e.setProperty("--ut-bg",this.customTheme.backgroundColor),this.customTheme.textColor&&e.setProperty("--ut-text",this.customTheme.textColor),this.customTheme.borderColor&&e.setProperty("--ut-border",this.customTheme.borderColor),this.customTheme.fontFamily&&e.setProperty("--ut-font",this.customTheme.fontFamily)}show(){this.stateManager.setVisibility(!0),this.render()}hide(){this.stateManager.setVisibility(!1),this.render()}destroy(){this.rootElement.remove()}render(){const t=this.stateManager.getState(),e=this.stateManager.getFlagNames(),s=this.stateManager.getVisibility();((t,e)=>{let s=e._$litPart$;if(void 0===s){const t=null;e._$litPart$=s=new H(e.insertBefore(d(),t),t,void 0,{})}s._$AI(t)})(A`
<button
class="ut-toggle"
style=${s?"display: none;":"display: flex;"}
@click=${()=>this.show()}
title="Open Unleash Toolbar"
>
<img src="${S}" alt="Unleash" />
</button>
<div
class="unleash-toolbar"
style=${s?"display: flex;":"display: none;"}
>
${this.renderHeader(t)}
${this.renderTabsNavigation()}
<div class="ut-content">
<div style=${"flags"===this.currentTab?"":"display: none;"}>
${this.renderFlagsTab(e)}
</div>
<div style=${"context"===this.currentTab?"":"display: none;"}>
${this.renderContextTab(t.contextOverrides)}
</div>
</div>
</div>
`,this.rootElement)}renderHeader(t){const e=Object.keys(t.flags).length,s=Object.values(t.flags).filter(t=>null!==t.override).length;return A`
<div class="ut-header">
<div class="ut-title">
<img src="${S}" alt="Unleash" />
<div>
<div class="ut-title-main">Unleash Toolbar</div>
<div class="ut-title-sub">${e} flags • ${s} overrides</div>
</div>
</div>
<button class="ut-btn-close" @click=${()=>this.hide()} title="Close toolbar">×</button>
</div>
`}renderTabsNavigation(){return A`
<div class="ut-tabs">
<button
class=${"ut-tab "+("flags"===this.currentTab?"active":"")}
@click=${()=>this.switchTab("flags")}
>
Feature Flags
</button>
<button
class=${"ut-tab "+("context"===this.currentTab?"active":"")}
@click=${()=>this.switchTab("context")}
>
Context
</button>
</div>
`}switchTab(t){this.currentTab=t,this.render()}renderFlagsTab(t){if(0===t.length)return A`
<div class="ut-empty">
No flags evaluated yet. Use feature flags in your app to see them here.
</div>
`;const e=this.searchQuery?t.filter(t=>t.toLowerCase().includes(this.searchQuery.toLowerCase())):t;return A`
<div class="ut-tab-header">
<div class="ut-search-container">
<input
type="text"
class="ut-search-input"
placeholder="Search flags..."
.value=${this.searchQuery}
@input=${t=>this.updateSearch(t.target.value)}
/>
</div>
<button class="ut-btn" @click=${()=>this.stateManager.resetOverrides()}>
Reset All Overrides
</button>
</div>
<div class="ut-flag-list">
${e.length>0?e.map(t=>this.renderFlagItem(t)):A`<div class="ut-empty">No flags match "${this.searchQuery}"</div>`}
</div>
`}updateSearch(t){this.searchQuery=t,this.render()}renderFlagItem(t){const e=this.stateManager.getFlagMetadata(t);if(!e)return null;const s="variant"===e.flagType,i=null!==e.override;let r="default";return i&&"flag"===e.override?.type&&(r=e.override.value?"on":"off"),A`
<div class="ut-flag-item">
<div class="ut-flag-main">
<div class="ut-flag-header">
<div class="ut-flag-title-row">
<div class="ut-flag-name">${t}</div>
</div>
<div class="ut-flag-meta">
<div class="ut-flag-default-value" title="Default value from Unleash">
${this.renderValueBadge(e.lastDefaultValue)}
</div>
${i?A`
<span class="ut-override-indicator" title="Override value (overriding the default)">
→ ${this.renderValueBadge(e.lastEffectiveValue)}
</span>
`:null}
</div>
</div>
</div>
<div class="ut-flag-control">
${s?A`
<div class="ut-variant-control">
${i&&"variant"===e.override?.type?A`
<input
type="text"
class="ut-input-small"
placeholder="Variant name"
.value=${e.override.variantKey}
@input=${e=>this.setVariant(t,e.target.value)}
title="Enter variant name to override with"
/>
<button
class="ut-btn-small active"
@click=${()=>this.toggleVariantOverride(t)}
title="Clear variant override"
>Clear Override</button>
`:A`
<button
class="ut-btn-small"
@click=${()=>this.toggleVariantOverride(t)}
title="Set a variant override"
>Override Variant</button>
`}
</div>
`:A`
<div class="ut-toggle-group">
<button
class=${"ut-toggle-btn "+("off"===r?"active":"")}
@click=${()=>this.setFlagOverride(t,"off")}
title="Force this flag to OFF"
>OFF</button>
<button
class=${"ut-toggle-btn "+("default"===r?"active":"")}
@click=${()=>this.setFlagOverride(t,"default")}
title="Use default value from Unleash (no override)"
>—</button>
<button
class=${"ut-toggle-btn "+("on"===r?"active":"")}
@click=${()=>this.setFlagOverride(t,"on")}
title="Force this flag to ON"
>ON</button>
</div>
`}
</div>
</div>
`}renderValueBadge(t){return"boolean"==typeof t?A`<span class=${"ut-badge ut-badge-"+(t?"success":"danger")}>${t?"ON":"OFF"}</span>`:t&&"object"==typeof t&&"name"in t?A`<span class="ut-badge ut-badge-default">${t.name}</span>`:A`<span class="ut-badge ut-badge-default">null</span>`}setFlagOverride(t,e){"default"===e?this.stateManager.setFlagOverride(t,null):"on"===e?this.stateManager.setFlagOverride(t,{type:"flag",value:!0}):"off"===e&&this.stateManager.setFlagOverride(t,{type:"flag",value:!1})}toggleVariantOverride(t){const e=this.stateManager.getFlagMetadata(t);this.stateManager.setFlagOverride(t,e?.override?null:{type:"variant",variantKey:"default"})}setVariant(t,e){this.stateManager.setFlagOverride(t,{type:"variant",variantKey:e})}isFieldOverridden(t,e,s){if("properties"===t)return!1;const i=s[t];return void 0!==i&&i!==e[t]}renderContextField(t,e,s,i,r,n=!1){return A`
<div class="ut-form-group">
<label class="ut-label">
${t}${n?A` <span class="ut-readonly-label">(read-only)</span>`:null}
</label>
<div class="ut-input-with-reset">
<input
type="text"
class=${n?"ut-input ut-input-readonly":"ut-input"}
placeholder=${s}
.value=${i}
@input=${n?null:t=>this.updateContextField(e,t.target.value)}
?readonly=${n}
title=${n?"This context field is static and cannot be modified.":""}
/>
${r&&!n?A`
<button
class="ut-reset-field"
@click=${()=>this.resetContextField(e)}
title="Reset to original value"
>↻</button>
`:null}
</div>
</div>
`}updateContextField(t,e){this.stateManager.setContextOverride({[t]:e||void 0})}resetContextField(t){this.stateManager.removeContextOverride(t)}renderContextTab(t){const e=this.originalBaseContext,s={...e,...t},i=["userId","sessionId","remoteAddress","environment","appName","properties"],r=e.properties||{},n=t.properties||{},a={...r,...n},o=Object.entries(a).filter(([t,e])=>!i.includes(t)&&""!==e),l=Object.fromEntries(o);return A`
<div class="ut-tab-header">
<button class="ut-btn" @click=${()=>this.stateManager.resetContextOverrides()}>
Reset All Context
</button>
</div>
<div class="ut-context-form">
${this.renderContextField("User ID","userId","user-123",s.userId||"",this.isFieldOverridden("userId",e,t))}
${this.renderContextField("Session ID","sessionId","session-456",s.sessionId||"",this.isFieldOverridden("sessionId",e,t))}
${this.renderContextField("Remote Address","remoteAddress","192.168.1.1",s.remoteAddress||"",this.isFieldOverridden("remoteAddress",e,t))}
${this.renderContextField("Environment","environment","development",s.environment||"",!1,!0)}
${this.renderContextField("App Name","appName","my-app",s.appName||"",!1,!0)}
<div class="ut-form-group">
<div class="ut-label">Custom Properties</div>
<div class="ut-properties">
${this.renderProperties(l||{},r)}
</div>
</div>
</div>
`}renderProperties(t,e={}){const s=Object.entries(t);return 0===s.length?A`
<div class="ut-empty-properties">
No custom properties defined in base context
</div>
`:A`
${s.map(([t,s])=>{const i=e[t],r=void 0!==i&&i!==s;return A`
<div class="ut-property-row">
<div class="ut-property-key" title="Property key (read-only)">${t}</div>
<div class="ut-input-with-reset">
<input
type="text"
class="ut-input"
placeholder="Value"
.value=${s}
@input=${e=>this.updatePropertyValue(t,e.target.value)}
title=${r?`Original: ${i}`:""}
/>
${r?A`
<button
class="ut-reset-field"
@click=${()=>this.resetProperty(t)}
title="Reset to original value"
>↻</button>
`:null}
</div>
</div>
`})}
`}updatePropertyValue(t,e){const s={...this.stateManager.getState().contextOverrides.properties||{},[t]:e};this.stateManager.setContextOverride({properties:s})}resetProperty(t){const e=this.originalBaseContext.properties||{},s={...this.stateManager.getState().contextOverrides.properties||{}};void 0!==e[t]?s[t]=e[t]:delete s[t],this.stateManager.setContextOverride({properties:s})}}export{U as ToolbarUI};
//# sourceMappingURL=ui-LKEosjLO.js.map
{"version":3,"file":"ui-LKEosjLO.js","sources":["../node_modules/lit-html/lit-html.js","../src/ui.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2017 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\nconst t=globalThis,i=t=>t,s=t.trustedTypes,e=s?s.createPolicy(\"lit-html\",{createHTML:t=>t}):void 0,h=\"$lit$\",o=`lit$${Math.random().toFixed(9).slice(2)}$`,n=\"?\"+o,r=`<${n}>`,l=document,c=()=>l.createComment(\"\"),a=t=>null===t||\"object\"!=typeof t&&\"function\"!=typeof t,u=Array.isArray,d=t=>u(t)||\"function\"==typeof t?.[Symbol.iterator],f=\"[ \\t\\n\\f\\r]\",v=/<(?:(!--|\\/[^a-zA-Z])|(\\/?[a-zA-Z][^>\\s]*)|(\\/?$))/g,_=/-->/g,m=/>/g,p=RegExp(`>|${f}(?:([^\\\\s\"'>=/]+)(${f}*=${f}*(?:[^ \\t\\n\\f\\r\"'\\`<>=]|(\"|')|))|$)`,\"g\"),g=/'/g,$=/\"/g,y=/^(?:script|style|textarea|title)$/i,x=t=>(i,...s)=>({_$litType$:t,strings:i,values:s}),b=x(1),w=x(2),T=x(3),E=Symbol.for(\"lit-noChange\"),A=Symbol.for(\"lit-nothing\"),C=new WeakMap,P=l.createTreeWalker(l,129);function V(t,i){if(!u(t)||!t.hasOwnProperty(\"raw\"))throw Error(\"invalid template strings array\");return void 0!==e?e.createHTML(i):i}const N=(t,i)=>{const s=t.length-1,e=[];let n,l=2===i?\"<svg>\":3===i?\"<math>\":\"\",c=v;for(let i=0;i<s;i++){const s=t[i];let a,u,d=-1,f=0;for(;f<s.length&&(c.lastIndex=f,u=c.exec(s),null!==u);)f=c.lastIndex,c===v?\"!--\"===u[1]?c=_:void 0!==u[1]?c=m:void 0!==u[2]?(y.test(u[2])&&(n=RegExp(\"</\"+u[2],\"g\")),c=p):void 0!==u[3]&&(c=p):c===p?\">\"===u[0]?(c=n??v,d=-1):void 0===u[1]?d=-2:(d=c.lastIndex-u[2].length,a=u[1],c=void 0===u[3]?p:'\"'===u[3]?$:g):c===$||c===g?c=p:c===_||c===m?c=v:(c=p,n=void 0);const x=c===p&&t[i+1].startsWith(\"/>\")?\" \":\"\";l+=c===v?s+r:d>=0?(e.push(a),s.slice(0,d)+h+s.slice(d)+o+x):s+o+(-2===d?i:x)}return[V(t,l+(t[s]||\"<?>\")+(2===i?\"</svg>\":3===i?\"</math>\":\"\")),e]};class S{constructor({strings:t,_$litType$:i},e){let r;this.parts=[];let l=0,a=0;const u=t.length-1,d=this.parts,[f,v]=N(t,i);if(this.el=S.createElement(f,e),P.currentNode=this.el.content,2===i||3===i){const t=this.el.content.firstChild;t.replaceWith(...t.childNodes)}for(;null!==(r=P.nextNode())&&d.length<u;){if(1===r.nodeType){if(r.hasAttributes())for(const t of r.getAttributeNames())if(t.endsWith(h)){const i=v[a++],s=r.getAttribute(t).split(o),e=/([.?@])?(.*)/.exec(i);d.push({type:1,index:l,name:e[2],strings:s,ctor:\".\"===e[1]?I:\"?\"===e[1]?L:\"@\"===e[1]?z:H}),r.removeAttribute(t)}else t.startsWith(o)&&(d.push({type:6,index:l}),r.removeAttribute(t));if(y.test(r.tagName)){const t=r.textContent.split(o),i=t.length-1;if(i>0){r.textContent=s?s.emptyScript:\"\";for(let s=0;s<i;s++)r.append(t[s],c()),P.nextNode(),d.push({type:2,index:++l});r.append(t[i],c())}}}else if(8===r.nodeType)if(r.data===n)d.push({type:2,index:l});else{let t=-1;for(;-1!==(t=r.data.indexOf(o,t+1));)d.push({type:7,index:l}),t+=o.length-1}l++}}static createElement(t,i){const s=l.createElement(\"template\");return s.innerHTML=t,s}}function M(t,i,s=t,e){if(i===E)return i;let h=void 0!==e?s._$Co?.[e]:s._$Cl;const o=a(i)?void 0:i._$litDirective$;return h?.constructor!==o&&(h?._$AO?.(!1),void 0===o?h=void 0:(h=new o(t),h._$AT(t,s,e)),void 0!==e?(s._$Co??=[])[e]=h:s._$Cl=h),void 0!==h&&(i=M(t,h._$AS(t,i.values),h,e)),i}class R{constructor(t,i){this._$AV=[],this._$AN=void 0,this._$AD=t,this._$AM=i}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}u(t){const{el:{content:i},parts:s}=this._$AD,e=(t?.creationScope??l).importNode(i,!0);P.currentNode=e;let h=P.nextNode(),o=0,n=0,r=s[0];for(;void 0!==r;){if(o===r.index){let i;2===r.type?i=new k(h,h.nextSibling,this,t):1===r.type?i=new r.ctor(h,r.name,r.strings,this,t):6===r.type&&(i=new Z(h,this,t)),this._$AV.push(i),r=s[++n]}o!==r?.index&&(h=P.nextNode(),o++)}return P.currentNode=l,e}p(t){let i=0;for(const s of this._$AV)void 0!==s&&(void 0!==s.strings?(s._$AI(t,s,i),i+=s.strings.length-2):s._$AI(t[i])),i++}}class k{get _$AU(){return this._$AM?._$AU??this._$Cv}constructor(t,i,s,e){this.type=2,this._$AH=A,this._$AN=void 0,this._$AA=t,this._$AB=i,this._$AM=s,this.options=e,this._$Cv=e?.isConnected??!0}get parentNode(){let t=this._$AA.parentNode;const i=this._$AM;return void 0!==i&&11===t?.nodeType&&(t=i.parentNode),t}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(t,i=this){t=M(this,t,i),a(t)?t===A||null==t||\"\"===t?(this._$AH!==A&&this._$AR(),this._$AH=A):t!==this._$AH&&t!==E&&this._(t):void 0!==t._$litType$?this.$(t):void 0!==t.nodeType?this.T(t):d(t)?this.k(t):this._(t)}O(t){return this._$AA.parentNode.insertBefore(t,this._$AB)}T(t){this._$AH!==t&&(this._$AR(),this._$AH=this.O(t))}_(t){this._$AH!==A&&a(this._$AH)?this._$AA.nextSibling.data=t:this.T(l.createTextNode(t)),this._$AH=t}$(t){const{values:i,_$litType$:s}=t,e=\"number\"==typeof s?this._$AC(t):(void 0===s.el&&(s.el=S.createElement(V(s.h,s.h[0]),this.options)),s);if(this._$AH?._$AD===e)this._$AH.p(i);else{const t=new R(e,this),s=t.u(this.options);t.p(i),this.T(s),this._$AH=t}}_$AC(t){let i=C.get(t.strings);return void 0===i&&C.set(t.strings,i=new S(t)),i}k(t){u(this._$AH)||(this._$AH=[],this._$AR());const i=this._$AH;let s,e=0;for(const h of t)e===i.length?i.push(s=new k(this.O(c()),this.O(c()),this,this.options)):s=i[e],s._$AI(h),e++;e<i.length&&(this._$AR(s&&s._$AB.nextSibling,e),i.length=e)}_$AR(t=this._$AA.nextSibling,s){for(this._$AP?.(!1,!0,s);t!==this._$AB;){const s=i(t).nextSibling;i(t).remove(),t=s}}setConnected(t){void 0===this._$AM&&(this._$Cv=t,this._$AP?.(t))}}class H{get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}constructor(t,i,s,e,h){this.type=1,this._$AH=A,this._$AN=void 0,this.element=t,this.name=i,this._$AM=e,this.options=h,s.length>2||\"\"!==s[0]||\"\"!==s[1]?(this._$AH=Array(s.length-1).fill(new String),this.strings=s):this._$AH=A}_$AI(t,i=this,s,e){const h=this.strings;let o=!1;if(void 0===h)t=M(this,t,i,0),o=!a(t)||t!==this._$AH&&t!==E,o&&(this._$AH=t);else{const e=t;let n,r;for(t=h[0],n=0;n<h.length-1;n++)r=M(this,e[s+n],i,n),r===E&&(r=this._$AH[n]),o||=!a(r)||r!==this._$AH[n],r===A?t=A:t!==A&&(t+=(r??\"\")+h[n+1]),this._$AH[n]=r}o&&!e&&this.j(t)}j(t){t===A?this.element.removeAttribute(this.name):this.element.setAttribute(this.name,t??\"\")}}class I extends H{constructor(){super(...arguments),this.type=3}j(t){this.element[this.name]=t===A?void 0:t}}class L extends H{constructor(){super(...arguments),this.type=4}j(t){this.element.toggleAttribute(this.name,!!t&&t!==A)}}class z extends H{constructor(t,i,s,e,h){super(t,i,s,e,h),this.type=5}_$AI(t,i=this){if((t=M(this,t,i,0)??A)===E)return;const s=this._$AH,e=t===A&&s!==A||t.capture!==s.capture||t.once!==s.once||t.passive!==s.passive,h=t!==A&&(s===A||e);e&&this.element.removeEventListener(this.name,this,s),h&&this.element.addEventListener(this.name,this,t),this._$AH=t}handleEvent(t){\"function\"==typeof this._$AH?this._$AH.call(this.options?.host??this.element,t):this._$AH.handleEvent(t)}}class Z{constructor(t,i,s){this.element=t,this.type=6,this._$AN=void 0,this._$AM=i,this.options=s}get _$AU(){return this._$AM._$AU}_$AI(t){M(this,t)}}const j={M:h,P:o,A:n,C:1,L:N,R,D:d,V:M,I:k,H,N:L,U:z,B:I,F:Z},B=t.litHtmlPolyfillSupport;B?.(S,k),(t.litHtmlVersions??=[]).push(\"3.3.2\");const D=(t,i,s)=>{const e=s?.renderBefore??i;let h=e._$litPart$;if(void 0===h){const t=s?.renderBefore??null;e._$litPart$=h=new k(i.insertBefore(c(),t),t,void 0,s??{})}return h._$AI(t),h};export{j as _$LH,b as html,T as mathml,E as noChange,A as nothing,D as render,w as svg};\n//# sourceMappingURL=lit-html.js.map\n","import { html, render } from 'lit-html';\nimport type { ToolbarStateManager } from './state';\nimport type {\n FlagValue,\n InitToolbarOptions,\n IToolbarUI,\n ToolbarState,\n UnleashContext,\n WrappedUnleashClient,\n} from './types';\n\n// Unleash logo from CDN\nconst UNLEASH_LOGO = 'https://cdn.getunleash.io/docs-assets/unleash_logo_icon.svg';\n\n/**\n * Create the toolbar UI component using Lit\n */\nexport class ToolbarUI implements IToolbarUI {\n private container: HTMLElement;\n private rootElement: HTMLElement;\n private stateManager: ToolbarStateManager;\n private currentTab: 'flags' | 'context' = 'flags';\n private position: string;\n private themePreset: 'light' | 'dark';\n private customTheme?: InitToolbarOptions['theme'];\n private originalBaseContext: Partial<UnleashContext>;\n private searchQuery: string = '';\n\n constructor(\n stateManager: ToolbarStateManager,\n wrappedClient: WrappedUnleashClient,\n options: InitToolbarOptions = {},\n ) {\n this.stateManager = stateManager;\n this.position = options.position || 'bottom-right';\n this.themePreset = options.themePreset || 'light';\n this.customTheme = options.theme;\n\n // Capture original base context before any overrides are applied\n this.originalBaseContext = wrappedClient.__original.getContext();\n\n // Initialize visibility from persisted state, or use initiallyVisible option\n const persistedVisibility = this.stateManager.getVisibility();\n const isVisible =\n persistedVisibility !== undefined ? persistedVisibility : (options.initiallyVisible ?? false);\n\n // Persist the initial visibility if not already set\n if (persistedVisibility === undefined) {\n this.stateManager.setVisibility(isVisible);\n }\n\n // Create single root container\n this.rootElement = document.createElement('div');\n this.rootElement.className = `unleash-toolbar-container position-${this.position}`;\n if (this.themePreset === 'dark') {\n this.rootElement.classList.add('ut-theme-dark');\n }\n this.applyCustomTheme(this.rootElement);\n\n // Attach to container or body\n this.container = options.container || document.body;\n this.container.appendChild(this.rootElement);\n\n // Subscribe to state changes\n this.stateManager.subscribe(() => {\n this.render();\n });\n\n // Initial render\n this.render();\n }\n\n private applyCustomTheme(element: HTMLElement): void {\n if (!this.customTheme) return;\n\n const style = element.style;\n if (this.customTheme.primaryColor)\n style.setProperty('--ut-primary', this.customTheme.primaryColor);\n if (this.customTheme.backgroundColor)\n style.setProperty('--ut-bg', this.customTheme.backgroundColor);\n if (this.customTheme.textColor) style.setProperty('--ut-text', this.customTheme.textColor);\n if (this.customTheme.borderColor)\n style.setProperty('--ut-border', this.customTheme.borderColor);\n if (this.customTheme.fontFamily) style.setProperty('--ut-font', this.customTheme.fontFamily);\n }\n\n show(): void {\n this.stateManager.setVisibility(true);\n this.render();\n }\n\n hide(): void {\n this.stateManager.setVisibility(false);\n this.render();\n }\n\n destroy(): void {\n this.rootElement.remove();\n }\n\n private render(): void {\n const state = this.stateManager.getState();\n const flagNames = this.stateManager.getFlagNames();\n const isVisible = this.stateManager.getVisibility();\n\n // Single unified template for everything\n const template = html`\n <button \n class=\"ut-toggle\" \n style=${isVisible ? 'display: none;' : 'display: flex;'}\n @click=${() => this.show()}\n title=\"Open Unleash Toolbar\"\n >\n <img src=\"${UNLEASH_LOGO}\" alt=\"Unleash\" />\n </button>\n\n <div \n class=\"unleash-toolbar\" \n style=${isVisible ? 'display: flex;' : 'display: none;'}\n >\n ${this.renderHeader(state)}\n ${this.renderTabsNavigation()}\n <div class=\"ut-content\">\n <div style=${this.currentTab === 'flags' ? '' : 'display: none;'}>\n ${this.renderFlagsTab(flagNames)}\n </div>\n <div style=${this.currentTab === 'context' ? '' : 'display: none;'}>\n ${this.renderContextTab(state.contextOverrides)}\n </div>\n </div>\n </div>\n `;\n\n render(template, this.rootElement);\n }\n\n private renderHeader(state: ToolbarState) {\n const flagCount = Object.keys(state.flags).length;\n const overrideCount = Object.values(state.flags).filter((f) => f.override !== null).length;\n\n return html`\n <div class=\"ut-header\">\n <div class=\"ut-title\">\n <img src=\"${UNLEASH_LOGO}\" alt=\"Unleash\" />\n <div>\n <div class=\"ut-title-main\">Unleash Toolbar</div>\n <div class=\"ut-title-sub\">${flagCount} flags • ${overrideCount} overrides</div>\n </div>\n </div>\n <button class=\"ut-btn-close\" @click=${() => this.hide()} title=\"Close toolbar\">×</button>\n </div>\n `;\n }\n\n private renderTabsNavigation() {\n return html`\n <div class=\"ut-tabs\">\n <button \n class=${`ut-tab ${this.currentTab === 'flags' ? 'active' : ''}`}\n @click=${() => this.switchTab('flags')}\n >\n Feature Flags\n </button>\n <button \n class=${`ut-tab ${this.currentTab === 'context' ? 'active' : ''}`}\n @click=${() => this.switchTab('context')}\n >\n Context\n </button>\n </div>\n `;\n }\n\n private switchTab(tab: 'flags' | 'context'): void {\n this.currentTab = tab;\n this.render();\n }\n\n private renderFlagsTab(flagNames: string[]) {\n if (flagNames.length === 0) {\n return html`\n <div class=\"ut-empty\">\n No flags evaluated yet. Use feature flags in your app to see them here.\n </div>\n `;\n }\n\n // Filter flags based on search query\n const filteredFlags = this.searchQuery\n ? flagNames.filter((name) => name.toLowerCase().includes(this.searchQuery.toLowerCase()))\n : flagNames;\n\n return html`\n <div class=\"ut-tab-header\">\n <div class=\"ut-search-container\">\n <input\n type=\"text\"\n class=\"ut-search-input\"\n placeholder=\"Search flags...\"\n .value=${this.searchQuery}\n @input=${(e: Event) => this.updateSearch((e.target as HTMLInputElement).value)}\n />\n </div>\n <button class=\"ut-btn\" @click=${() => this.stateManager.resetOverrides()}>\n Reset All Overrides\n </button>\n </div>\n <div class=\"ut-flag-list\">\n ${\n filteredFlags.length > 0\n ? filteredFlags.map((name) => this.renderFlagItem(name))\n : html`<div class=\"ut-empty\">No flags match \"${this.searchQuery}\"</div>`\n }\n </div>\n `;\n }\n\n private updateSearch(query: string): void {\n this.searchQuery = query;\n this.render();\n }\n\n private renderFlagItem(name: string) {\n const metadata = this.stateManager.getFlagMetadata(name);\n if (!metadata) return null;\n\n // Use the explicitly stored flag type\n const isVariant = metadata.flagType === 'variant';\n const hasOverride = metadata.override !== null;\n\n // Determine current state for toggle\n let toggleState = 'default';\n if (hasOverride && metadata.override?.type === 'flag') {\n toggleState = metadata.override.value ? 'on' : 'off';\n }\n\n return html`\n <div class=\"ut-flag-item\">\n <div class=\"ut-flag-main\">\n <div class=\"ut-flag-header\">\n <div class=\"ut-flag-title-row\">\n <div class=\"ut-flag-name\">${name}</div>\n </div>\n <div class=\"ut-flag-meta\">\n <div class=\"ut-flag-default-value\" title=\"Default value from Unleash\">\n ${this.renderValueBadge(metadata.lastDefaultValue)}\n </div>\n ${\n hasOverride\n ? html`\n <span class=\"ut-override-indicator\" title=\"Override value (overriding the default)\">\n → ${this.renderValueBadge(metadata.lastEffectiveValue)}\n </span>\n `\n : null\n }\n </div>\n </div>\n </div>\n \n <div class=\"ut-flag-control\">\n ${\n !isVariant\n ? html`\n <div class=\"ut-toggle-group\">\n <button \n class=${`ut-toggle-btn ${toggleState === 'off' ? 'active' : ''}`}\n @click=${() => this.setFlagOverride(name, 'off')}\n title=\"Force this flag to OFF\"\n >OFF</button>\n <button \n class=${`ut-toggle-btn ${toggleState === 'default' ? 'active' : ''}`}\n @click=${() => this.setFlagOverride(name, 'default')}\n title=\"Use default value from Unleash (no override)\"\n >—</button>\n <button \n class=${`ut-toggle-btn ${toggleState === 'on' ? 'active' : ''}`}\n @click=${() => this.setFlagOverride(name, 'on')}\n title=\"Force this flag to ON\"\n >ON</button>\n </div>\n `\n : html`\n <div class=\"ut-variant-control\">\n ${\n hasOverride && metadata.override?.type === 'variant'\n ? html`\n <input \n type=\"text\" \n class=\"ut-input-small\" \n placeholder=\"Variant name\" \n .value=${metadata.override.variantKey}\n @input=${(e: Event) => this.setVariant(name, (e.target as HTMLInputElement).value)}\n title=\"Enter variant name to override with\"\n />\n <button \n class=\"ut-btn-small active\" \n @click=${() => this.toggleVariantOverride(name)}\n title=\"Clear variant override\"\n >Clear Override</button>\n `\n : html`\n <button \n class=\"ut-btn-small\" \n @click=${() => this.toggleVariantOverride(name)}\n title=\"Set a variant override\"\n >Override Variant</button>\n `\n }\n </div>\n `\n }\n </div>\n </div>\n `;\n }\n\n private renderValueBadge(value: FlagValue) {\n if (typeof value === 'boolean') {\n return html`<span class=${`ut-badge ut-badge-${value ? 'success' : 'danger'}`}>${value ? 'ON' : 'OFF'}</span>`;\n }\n if (value && typeof value === 'object' && 'name' in value) {\n return html`<span class=\"ut-badge ut-badge-default\">${value.name}</span>`;\n }\n return html`<span class=\"ut-badge ut-badge-default\">null</span>`;\n }\n\n private setFlagOverride(flagName: string, value: 'on' | 'off' | 'default'): void {\n if (value === 'default') {\n this.stateManager.setFlagOverride(flagName, null);\n } else if (value === 'on') {\n this.stateManager.setFlagOverride(flagName, { type: 'flag', value: true });\n } else if (value === 'off') {\n this.stateManager.setFlagOverride(flagName, { type: 'flag', value: false });\n }\n }\n\n private toggleVariantOverride(flagName: string): void {\n const metadata = this.stateManager.getFlagMetadata(flagName);\n\n if (metadata?.override) {\n // Clear override\n this.stateManager.setFlagOverride(flagName, null);\n } else {\n // Set default variant override\n this.stateManager.setFlagOverride(flagName, { type: 'variant', variantKey: 'default' });\n }\n }\n\n private setVariant(flagName: string, variantKey: string): void {\n this.stateManager.setFlagOverride(flagName, { type: 'variant', variantKey });\n }\n\n private isFieldOverridden(\n fieldName: string,\n baseContext: Partial<UnleashContext>,\n contextOverrides: Partial<UnleashContext>,\n ): boolean {\n if (fieldName === 'properties') {\n return false; // Handle properties separately\n }\n const baseValue = baseContext[fieldName as keyof UnleashContext];\n const overrideValue = contextOverrides[fieldName as keyof UnleashContext];\n\n // Only consider it overridden if there's an override AND it differs from base\n return overrideValue !== undefined && overrideValue !== baseValue;\n }\n\n private renderContextField(\n label: string,\n fieldName: string,\n placeholder: string,\n value: string,\n isOverridden: boolean,\n readonly = false,\n ) {\n return html`\n <div class=\"ut-form-group\">\n <label class=\"ut-label\">\n ${label}${readonly ? html` <span class=\"ut-readonly-label\">(read-only)</span>` : null}\n </label>\n <div class=\"ut-input-with-reset\">\n <input \n type=\"text\" \n class=${readonly ? 'ut-input ut-input-readonly' : 'ut-input'}\n placeholder=${placeholder}\n .value=${value}\n @input=${readonly ? null : (e: Event) => this.updateContextField(fieldName, (e.target as HTMLInputElement).value)}\n ?readonly=${readonly}\n title=${readonly ? 'This context field is static and cannot be modified.' : ''}\n />\n ${\n isOverridden && !readonly\n ? html`\n <button \n class=\"ut-reset-field\" \n @click=${() => this.resetContextField(fieldName)}\n title=\"Reset to original value\"\n >↻</button>\n `\n : null\n }\n </div>\n </div>\n `;\n }\n\n private updateContextField(field: string, value: string): void {\n this.stateManager.setContextOverride({ [field]: value || undefined });\n }\n\n private resetContextField(field: string): void {\n this.stateManager.removeContextOverride(field as keyof UnleashContext);\n }\n\n private renderContextTab(contextOverrides: Partial<UnleashContext>) {\n // Use original base context (not current client context which includes overrides)\n const baseContext = this.originalBaseContext;\n const mergedContext = { ...baseContext, ...contextOverrides };\n\n // Standard context fields that should not appear in custom properties\n const standardFields = [\n 'userId',\n 'sessionId',\n 'remoteAddress',\n 'environment',\n 'appName',\n 'properties',\n ];\n\n // Merge properties and exclude any that are standard fields\n const baseProperties = baseContext.properties || {};\n const overrideProperties = contextOverrides.properties || {};\n const mergedProperties = { ...baseProperties, ...overrideProperties };\n\n // Filter out standard fields and show only non-empty properties\n const customPropertiesArray = Object.entries(mergedProperties).filter(([key, value]) => {\n if (standardFields.includes(key)) return false;\n // Only show properties that have a non-empty value\n return value !== '';\n });\n\n const customProperties = Object.fromEntries(customPropertiesArray);\n\n return html`\n <div class=\"ut-tab-header\">\n <button class=\"ut-btn\" @click=${() => this.stateManager.resetContextOverrides()}>\n Reset All Context\n </button>\n </div>\n <div class=\"ut-context-form\">\n ${this.renderContextField('User ID', 'userId', 'user-123', mergedContext.userId || '', this.isFieldOverridden('userId', baseContext, contextOverrides))}\n ${this.renderContextField('Session ID', 'sessionId', 'session-456', mergedContext.sessionId || '', this.isFieldOverridden('sessionId', baseContext, contextOverrides))}\n ${this.renderContextField('Remote Address', 'remoteAddress', '192.168.1.1', mergedContext.remoteAddress || '', this.isFieldOverridden('remoteAddress', baseContext, contextOverrides))}\n ${this.renderContextField('Environment', 'environment', 'development', mergedContext.environment || '', false, true)}\n ${this.renderContextField('App Name', 'appName', 'my-app', mergedContext.appName || '', false, true)}\n\n <div class=\"ut-form-group\">\n <div class=\"ut-label\">Custom Properties</div>\n <div class=\"ut-properties\">\n ${this.renderProperties(customProperties || {}, baseProperties)}\n </div>\n </div>\n </div>\n `;\n }\n\n private renderProperties(\n properties: Record<string, string>,\n baseProperties: Record<string, string> = {},\n ) {\n const entries = Object.entries(properties);\n\n if (entries.length === 0) {\n return html`\n <div class=\"ut-empty-properties\">\n No custom properties defined in base context\n </div>\n `;\n }\n\n return html`\n ${entries.map(([key, value]) => {\n const baseValue = baseProperties[key];\n const isOverridden = baseValue !== undefined && baseValue !== value;\n return html`\n <div class=\"ut-property-row\">\n <div class=\"ut-property-key\" title=\"Property key (read-only)\">${key}</div>\n <div class=\"ut-input-with-reset\">\n <input \n type=\"text\" \n class=\"ut-input\" \n placeholder=\"Value\"\n .value=${value}\n @input=${(e: Event) => this.updatePropertyValue(key, (e.target as HTMLInputElement).value)}\n title=${isOverridden ? `Original: ${baseValue}` : ''}\n />\n ${\n isOverridden\n ? html`\n <button \n class=\"ut-reset-field\" \n @click=${() => this.resetProperty(key)}\n title=\"Reset to original value\"\n >↻</button>\n `\n : null\n }\n </div>\n </div>\n `;\n })}\n `;\n }\n\n private updatePropertyValue(key: string, value: string): void {\n const state = this.stateManager.getState();\n const properties = { ...(state.contextOverrides.properties || {}), [key]: value };\n this.stateManager.setContextOverride({ properties });\n }\n\n private resetProperty(key: string): void {\n const baseProperties = this.originalBaseContext.properties || {};\n const state = this.stateManager.getState();\n const properties = { ...(state.contextOverrides.properties || {}) };\n\n // Restore to base value\n if (baseProperties[key] !== undefined) {\n properties[key] = baseProperties[key];\n } else {\n delete properties[key];\n }\n\n this.stateManager.setContextOverride({ properties });\n }\n}\n"],"names":["t","globalThis","i","s","trustedTypes","e","createPolicy","createHTML","h","o","Math","random","toFixed","slice","n","r","l","document","c","createComment","a","u","Array","isArray","f","v","_","m","p","RegExp","g","$","y","b","_$litType$","strings","values","E","Symbol","for","A","C","WeakMap","P","createTreeWalker","V","hasOwnProperty","Error","N","length","d","lastIndex","exec","test","x","startsWith","push","S","constructor","this","parts","el","createElement","currentNode","content","firstChild","replaceWith","childNodes","nextNode","nodeType","hasAttributes","getAttributeNames","endsWith","getAttribute","split","type","index","name","ctor","I","L","z","H","removeAttribute","tagName","textContent","emptyScript","append","data","indexOf","innerHTML","M","_$Co","_$Cl","_$litDirective$","_$AO","_$AT","_$AS","R","_$AV","_$AN","_$AD","_$AM","parentNode","_$AU","creationScope","importNode","k","nextSibling","Z","_$AI","_$Cv","_$AH","_$AA","_$AB","options","isConnected","startNode","endNode","_$AR","T","iterator","O","insertBefore","createTextNode","_$AC","get","set","_$AP","remove","setConnected","element","fill","String","j","setAttribute","super","arguments","toggleAttribute","capture","once","passive","removeEventListener","addEventListener","handleEvent","call","host","B","litHtmlPolyfillSupport","litHtmlVersions","UNLEASH_LOGO","ToolbarUI","container","rootElement","stateManager","currentTab","position","themePreset","customTheme","originalBaseContext","searchQuery","wrappedClient","theme","__original","getContext","persistedVisibility","getVisibility","setVisibility","initiallyVisible","className","classList","add","applyCustomTheme","body","appendChild","subscribe","render","style","primaryColor","setProperty","backgroundColor","textColor","borderColor","fontFamily","show","hide","destroy","state","getState","flagNames","getFlagNames","isVisible","_$litPart$","html","renderHeader","renderTabsNavigation","renderFlagsTab","renderContextTab","contextOverrides","flagCount","Object","keys","flags","overrideCount","filter","override","switchTab","tab","filteredFlags","toLowerCase","includes","updateSearch","target","value","resetOverrides","map","renderFlagItem","query","metadata","getFlagMetadata","isVariant","flagType","hasOverride","toggleState","renderValueBadge","lastDefaultValue","lastEffectiveValue","variantKey","setVariant","toggleVariantOverride","setFlagOverride","flagName","isFieldOverridden","fieldName","baseContext","overrideValue","renderContextField","label","placeholder","isOverridden","readonly","updateContextField","resetContextField","field","setContextOverride","removeContextOverride","mergedContext","standardFields","baseProperties","properties","overrideProperties","mergedProperties","customPropertiesArray","entries","key","customProperties","fromEntries","resetContextOverrides","userId","sessionId","remoteAddress","environment","appName","renderProperties","baseValue","updatePropertyValue","resetProperty"],"mappings":"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","x_google_ignoreList":[0]}
import { ToolbarStateManager } from './state';
import { InitToolbarOptions, IToolbarUI, WrappedUnleashClient } from './types';
/**
* Create the toolbar UI component using Lit
*/
export declare class ToolbarUI implements IToolbarUI {
private container;
private rootElement;
private stateManager;
private currentTab;
private position;
private themePreset;
private customTheme?;
private originalBaseContext;
private searchQuery;
constructor(stateManager: ToolbarStateManager, wrappedClient: WrappedUnleashClient, options?: InitToolbarOptions);
private applyCustomTheme;
show(): void;
hide(): void;
destroy(): void;
private render;
private renderHeader;
private renderTabsNavigation;
private switchTab;
private renderFlagsTab;
private updateSearch;
private renderFlagItem;
private renderValueBadge;
private setFlagOverride;
private toggleVariantOverride;
private setVariant;
private isFieldOverridden;
private renderContextField;
private updateContextField;
private resetContextField;
private renderContextTab;
private renderProperties;
private updatePropertyValue;
private resetProperty;
}
//# sourceMappingURL=ui.d.ts.map
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,KAAK,EAEV,kBAAkB,EAClB,UAAU,EAGV,oBAAoB,EACrB,MAAM,SAAS,CAAC;AAKjB;;GAEG;AACH,qBAAa,SAAU,YAAW,UAAU;IAC1C,OAAO,CAAC,SAAS,CAAc;IAC/B,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,YAAY,CAAsB;IAC1C,OAAO,CAAC,UAAU,CAAgC;IAClD,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,WAAW,CAAmB;IACtC,OAAO,CAAC,WAAW,CAAC,CAA8B;IAClD,OAAO,CAAC,mBAAmB,CAA0B;IACrD,OAAO,CAAC,WAAW,CAAc;gBAG/B,YAAY,EAAE,mBAAmB,EACjC,aAAa,EAAE,oBAAoB,EACnC,OAAO,GAAE,kBAAuB;IAyClC,OAAO,CAAC,gBAAgB;IAcxB,IAAI,IAAI,IAAI;IAKZ,IAAI,IAAI,IAAI;IAKZ,OAAO,IAAI,IAAI;IAIf,OAAO,CAAC,MAAM;IAoCd,OAAO,CAAC,YAAY;IAkBpB,OAAO,CAAC,oBAAoB;IAmB5B,OAAO,CAAC,SAAS;IAKjB,OAAO,CAAC,cAAc;IAuCtB,OAAO,CAAC,YAAY;IAKpB,OAAO,CAAC,cAAc;IA+FtB,OAAO,CAAC,gBAAgB;IAUxB,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,qBAAqB;IAY7B,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,iBAAiB;IAezB,OAAO,CAAC,kBAAkB;IAuC1B,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,gBAAgB;IAoDxB,OAAO,CAAC,gBAAgB;IAgDxB,OAAO,CAAC,mBAAmB;IAM3B,OAAO,CAAC,aAAa;CActB"}
import { UnleashClient } from 'unleash-proxy-client';
import { ToolbarStateManager } from './state';
import { WrappedUnleashClient } from './types';
/**
* Wrap an Unleash client to intercept evaluations and apply overrides
*/
export declare function wrapUnleashClient(baseClient: UnleashClient, stateManager: ToolbarStateManager): WrappedUnleashClient;
/**
* Unwrap a client to get the original
*/
export declare function unwrapUnleashClient(client: UnleashClient): UnleashClient;
/**
* Check if a client is wrapped
*/
export declare function isWrappedClient(client: UnleashClient): client is WrappedUnleashClient;
//# sourceMappingURL=wrapper.d.ts.map
{"version":3,"file":"wrapper.d.ts","sourceRoot":"","sources":["../src/wrapper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,KAAK,EAAgC,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAElF;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,aAAa,EACzB,YAAY,EAAE,mBAAmB,GAChC,oBAAoB,CA2LtB;AAkCD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,GAAG,aAAa,CAKxE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,IAAI,oBAAoB,CAErF"}