@ogidor/dashboard 1.0.11 → 1.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,2 @@
1
1
  export {};
2
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kZWxzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2FwcC9tb2RlbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQSBzaW5nbGUgd2lkZ2V0IG9uIHRoZSBncmlkLlxuICogVGhlIGxpYiBpcyBjb250ZW50LWFnbm9zdGljIOKAlCBgZGF0YWAgY2FuIGhvbGQgYW55dGhpbmcgdGhlIGNvbnN1bWVyIG5lZWRzLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFdpZGdldCB7XG4gIGlkOiBzdHJpbmc7XG4gIC8qKiBHcmlkIGNvbHVtbiAoMC1iYXNlZCkgKi9cbiAgeDogbnVtYmVyO1xuICAvKiogR3JpZCByb3cgKDAtYmFzZWQpICovXG4gIHk6IG51bWJlcjtcbiAgLyoqIE51bWJlciBvZiBjb2x1bW5zIHRoaXMgd2lkZ2V0IHNwYW5zICovXG4gIGNvbHM6IG51bWJlcjtcbiAgLyoqIE51bWJlciBvZiByb3dzIHRoaXMgd2lkZ2V0IHNwYW5zICovXG4gIHJvd3M6IG51bWJlcjtcbiAgLyoqIERpc3BsYXkgdGl0bGUgc2hvd24gaW4gdGhlIGNhcmQgaGVhZGVyICovXG4gIHRpdGxlOiBzdHJpbmc7XG4gIC8qKiBPcHRpb25hbCBwZXItd2lkZ2V0IGNhcmQgYmFja2dyb3VuZCBjb2xvci4gT3ZlcnJpZGVzIHRoZSBnbG9iYWwgdGhlbWUgd2lkZ2V0Q2FyZENvbG9yLiAqL1xuICBjYXJkQ29sb3I/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBBcmJpdHJhcnkgY29uc3VtZXIgZGF0YS5cbiAgICogVGhlIGxpYiBzdG9yZXMgYW5kIHN5bmNzIHRoaXMgYnV0IG5ldmVyIGluc3BlY3RzIGl0LlxuICAgKi9cbiAgZGF0YT86IGFueTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQYWdlIHtcbiAgaWQ6IHN0cmluZztcbiAgbmFtZTogc3RyaW5nO1xuICB3aWRnZXRzOiBXaWRnZXRbXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBEYXNoYm9hcmRDb25maWcge1xuICBwYWdlczogUGFnZVtdO1xuICBhY3RpdmVQYWdlSWQ6IHN0cmluZztcbn1cblxuLyoqXG4gKiBUaGVtZSBjb25maWd1cmF0aW9uIGZvciB0aGUgZGFzaGJvYXJkLlxuICogQWxsIHByb3BlcnRpZXMgYXJlIG9wdGlvbmFsIOKAlCBhbnkgdmFsdWVzIG5vdCBwcm92aWRlZCB3aWxsIGZhbGwgYmFjayB0byBkZWZhdWx0cy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEYXNoYm9hcmRUaGVtZSB7XG4gIC8qKiBCYWNrZ3JvdW5kIGNvbG9yIG9mIHRoZSBvdmVyYWxsIGRhc2hib2FyZCB3cmFwcGVyLiBEZWZhdWx0OiBgIzAwMDAwMGAgKi9cbiAgYmFja2dyb3VuZENvbG9yPzogc3RyaW5nO1xuICAvKiogQmFja2dyb3VuZCBjb2xvciBvZiB0aGUgbWFpbiBjb250ZW50IHBhbmVsLiBEZWZhdWx0OiBgIzFjMWMxZWAgKi9cbiAgcGFuZWxDb2xvcj86IHN0cmluZztcbiAgLyoqIEJhY2tncm91bmQgY29sb3Igb2YgaW5kaXZpZHVhbCB3aWRnZXQgY2FyZHMuIERlZmF1bHQ6IGAjMmMyYzJlYCAqL1xuICB3aWRnZXRDYXJkQ29sb3I/OiBzdHJpbmc7XG4gIC8qKiBQcmltYXJ5IGZvcmVncm91bmQvdGV4dCBjb2xvci4gRGVmYXVsdDogYCM4ZThlOTNgICovXG4gIGZvcmVDb2xvcj86IHN0cmluZztcbiAgLyoqIFByaW1hcnkgYWNjZW50IGNvbG9yIChhY3RpdmUgdGFicywgYnV0dG9ucywgZXRjLikuIERlZmF1bHQ6IGAjMGE4NGZmYCAqL1xuICBhY2NlbnRDb2xvcj86IHN0cmluZztcbiAgLyoqIERhbmdlciBjb2xvciB1c2VkIG9uIHJlbW92ZS13aWRnZXQgYnV0dG9uIGhvdmVyLiBEZWZhdWx0OiBgI2ZmNDUzYWAgKi9cbiAgZGFuZ2VyQ29sb3I/OiBzdHJpbmc7XG4gIC8qKiBGb250IGZhbWlseSBhcHBsaWVkIHRvIHRoZSB3aG9sZSBkYXNoYm9hcmQuIERlZmF1bHQ6IHN5c3RlbS11aSBzdGFjayAqL1xuICBmb250RmFtaWx5Pzogc3RyaW5nO1xuXG4gIC8vIOKUgOKUgCBIZWFkZXIgLyBUYWJzIOKUgOKUgFxuICAvKiogQmFja2dyb3VuZCBvZiB0aGUgdGFicyBwaWxsIGNvbnRhaW5lci4gRGVmYXVsdDogYHJnYmEoNDQsNDQsNDYsMC42KWAgKi9cbiAgdGFic0NvbnRhaW5lckNvbG9yPzogc3RyaW5nO1xuICAvKiogQmFja2dyb3VuZCBvZiB0aGUgYWN0aXZlL3NlbGVjdGVkIHRhYi4gRGVmYXVsdDogYCMzYTNhM2NgICovXG4gIHRhYkFjdGl2ZUNvbG9yPzogc3RyaW5nO1xuICAvKiogVGV4dCBjb2xvciBvZiB0aGUgYWN0aXZlIHRhYi4gRGVmYXVsdDogYCNmZmZmZmZgICovXG4gIHRhYkFjdGl2ZVRleHRDb2xvcj86IHN0cmluZztcbiAgLyoqIFRleHQgY29sb3Igb2YgaG92ZXJlZCAoaW5hY3RpdmUpIHRhYnMuIERlZmF1bHQ6IGAjZTVlNWVhYCAqL1xuICB0YWJIb3ZlclRleHRDb2xvcj86IHN0cmluZztcbiAgLyoqIFRleHQgY29sb3Igb2YgdGhlIFwiQWRkIFdpZGdldFwiIGJ1dHRvbi4gRGVmYXVsdDogYCNmZmZmZmZgICovXG4gIGFkZFdpZGdldEJ1dHRvblRleHRDb2xvcj86IHN0cmluZztcblxuICAvLyDilIDilIAgUG9wLW91dCB3aW5kb3cg4pSA4pSAXG4gIC8qKiBUZXh0IGNvbG9yIG9mIHRoZSBwb3Atb3V0IHBhZ2UgdGl0bGUuIERlZmF1bHQ6IGAjZmZmZmZmYCAqL1xuICBwb3BvdXRUaXRsZUNvbG9yPzogc3RyaW5nO1xuXG4gIC8vIOKUgOKUgCBXaWRnZXQgY2FyZCDilIDilIBcbiAgLyoqIFRleHQgY29sb3Igb2YgdGhlIHdpZGdldCBjYXJkIHRpdGxlLiBEZWZhdWx0OiBgI2ZmZmZmZmAgKi9cbiAgd2lkZ2V0VGl0bGVDb2xvcj86IHN0cmluZztcbiAgLyoqIENvbG9yIG9mIHRoZSBkcmFnLWhhbmRsZSBkb3RzIG9uIGEgd2lkZ2V0IGNhcmQuIERlZmF1bHQ6IGByZ2JhKDI1NSwyNTUsMjU1LDAuMilgICovXG4gIGRyYWdIYW5kbGVDb2xvcj86IHN0cmluZztcbiAgLyoqIEJvcmRlciBjb2xvciBvZiB3aWRnZXQgY2FyZHMuIERlZmF1bHQ6IGByZ2JhKDI1NSwyNTUsMjU1LDAuMDcpYCAqL1xuICB3aWRnZXRCb3JkZXJDb2xvcj86IHN0cmluZztcbiAgLyoqIEJhY2tncm91bmQgb2YgdGhlIGljb24gYnV0dG9ucyAoZWRpdC9yZW1vdmUpIG9uIHdpZGdldCBob3Zlci4gRGVmYXVsdDogYHJnYmEoMjU1LDI1NSwyNTUsMC4wNylgICovXG4gIHdpZGdldEJ1dHRvbkJnQ29sb3I/OiBzdHJpbmc7XG4gIC8qKiBEZWZhdWx0IHRleHQgY29sb3Igb2YgaWNvbiBidXR0b25zLiBEZWZhdWx0OiBgcmdiYSgyNTUsMjU1LDI1NSwwLjUpYCAqL1xuICB3aWRnZXRCdXR0b25Db2xvcj86IHN0cmluZztcblxuICAvLyDilIDilIAgR3JpZCDilIDilIBcbiAgLyoqIENvbG9yIG9mIHRoZSBkcmFnL3Jlc2l6ZSBwbGFjZWhvbGRlciBvdmVybGF5LiBEZWZhdWx0OiBzYW1lIGFzIGFjY2VudENvbG9yICovXG4gIHBsYWNlaG9sZGVyQ29sb3I/OiBzdHJpbmc7XG4gIC8qKiBDb2xvciBvZiB0aGUgcmVzaXplIGhhbmRsZSBpY29uLiBEZWZhdWx0OiBgcmdiYSgyNTUsMjU1LDI1NSwwLjI1KWAgKi9cbiAgcmVzaXplSGFuZGxlQ29sb3I/OiBzdHJpbmc7XG59XG4iXX0=
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kZWxzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2FwcC9tb2RlbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQSBzaW5nbGUgd2lkZ2V0IG9uIHRoZSBncmlkLlxuICogVGhlIGxpYiBpcyBjb250ZW50LWFnbm9zdGljIOKAlCBgZGF0YWAgY2FuIGhvbGQgYW55dGhpbmcgdGhlIGNvbnN1bWVyIG5lZWRzLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFdpZGdldCB7XG4gIGlkOiBzdHJpbmc7XG4gIC8qKiBHcmlkIGNvbHVtbiAoMC1iYXNlZCkgKi9cbiAgeDogbnVtYmVyO1xuICAvKiogR3JpZCByb3cgKDAtYmFzZWQpICovXG4gIHk6IG51bWJlcjtcbiAgLyoqIE51bWJlciBvZiBjb2x1bW5zIHRoaXMgd2lkZ2V0IHNwYW5zICovXG4gIGNvbHM6IG51bWJlcjtcbiAgLyoqIE51bWJlciBvZiByb3dzIHRoaXMgd2lkZ2V0IHNwYW5zICovXG4gIHJvd3M6IG51bWJlcjtcbiAgLyoqIERpc3BsYXkgdGl0bGUgc2hvd24gaW4gdGhlIGNhcmQgaGVhZGVyICovXG4gIHRpdGxlOiBzdHJpbmc7XG4gIC8qKiBPcHRpb25hbCBwZXItd2lkZ2V0IGNhcmQgYmFja2dyb3VuZCBjb2xvci4gT3ZlcnJpZGVzIHRoZSBnbG9iYWwgdGhlbWUgd2lkZ2V0Q2FyZENvbG9yLiAqL1xuICBjYXJkQ29sb3I/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBBcmJpdHJhcnkgY29uc3VtZXIgZGF0YS5cbiAgICogVGhlIGxpYiBzdG9yZXMgYW5kIHN5bmNzIHRoaXMgYnV0IG5ldmVyIGluc3BlY3RzIGl0LlxuICAgKi9cbiAgZGF0YT86IGFueTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQYWdlIHtcbiAgaWQ6IHN0cmluZztcbiAgbmFtZTogc3RyaW5nO1xuICB3aWRnZXRzOiBXaWRnZXRbXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBEYXNoYm9hcmRDb25maWcge1xuICBwYWdlczogUGFnZVtdO1xuICBhY3RpdmVQYWdlSWQ6IHN0cmluZztcbn1cblxuLyoqXG4gKiBUaGVtZSBjb25maWd1cmF0aW9uIGZvciB0aGUgZGFzaGJvYXJkLlxuICogQWxsIHByb3BlcnRpZXMgYXJlIG9wdGlvbmFsIOKAlCBhbnkgdmFsdWVzIG5vdCBwcm92aWRlZCB3aWxsIGZhbGwgYmFjayB0byBkZWZhdWx0cy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEYXNoYm9hcmRUaGVtZSB7XG4gIC8qKiBCYWNrZ3JvdW5kIGNvbG9yIG9mIHRoZSBvdmVyYWxsIGRhc2hib2FyZCB3cmFwcGVyLiBEZWZhdWx0OiBgIzAwMDAwMGAgKi9cbiAgYmFja2dyb3VuZENvbG9yPzogc3RyaW5nO1xuICAvKiogQmFja2dyb3VuZCBjb2xvciBvZiB0aGUgbWFpbiBjb250ZW50IHBhbmVsLiBEZWZhdWx0OiBgIzFjMWMxZWAgKi9cbiAgcGFuZWxDb2xvcj86IHN0cmluZztcbiAgLyoqIFN1YnRsZSBib3JkZXIgb24gdGhlIG1haW4gcGFuZWwgYW5kIHBvcC1vdXQgaGVhZGVyLiBEZWZhdWx0OiBgcmdiYSgyNTUsMjU1LDI1NSwwLjA1KWAgKi9cbiAgcGFuZWxCb3JkZXJDb2xvcj86IHN0cmluZztcbiAgLyoqIEJhY2tncm91bmQgY29sb3Igb2YgaW5kaXZpZHVhbCB3aWRnZXQgY2FyZHMuIERlZmF1bHQ6IGAjMmMyYzJlYCAqL1xuICB3aWRnZXRDYXJkQ29sb3I/OiBzdHJpbmc7XG4gIC8qKiBQcmltYXJ5IGZvcmVncm91bmQvdGV4dCBjb2xvci4gRGVmYXVsdDogYCM4ZThlOTNgICovXG4gIGZvcmVDb2xvcj86IHN0cmluZztcbiAgLyoqIFByaW1hcnkgYWNjZW50IGNvbG9yIChhY3RpdmUgdGFicywgYnV0dG9ucywgZXRjLikuIERlZmF1bHQ6IGAjMGE4NGZmYCAqL1xuICBhY2NlbnRDb2xvcj86IHN0cmluZztcbiAgLyoqIExpZ2h0IHRpbnQgb2YgdGhlIGFjY2VudCBjb2xvciB1c2VkIGZvciBob3ZlciBiYWNrZ3JvdW5kcy4gRGVmYXVsdDogYHJnYmEoMTAsMTMyLDI1NSwwLjE1KWAgKi9cbiAgYWNjZW50VGludENvbG9yPzogc3RyaW5nO1xuICAvKiogU3Ryb25nZXIgdGludCBvZiB0aGUgYWNjZW50IGNvbG9yIHVzZWQgZm9yIGFjdGl2ZSBjYXJkIGJhY2tncm91bmRzLiBEZWZhdWx0OiBgcmdiYSgxMCwxMzIsMjU1LDAuMjUpYCAqL1xuICBhY2NlbnRUaW50U3Ryb25nQ29sb3I/OiBzdHJpbmc7XG4gIC8qKiBEYW5nZXIgY29sb3IgdXNlZCBvbiByZW1vdmUtd2lkZ2V0IGJ1dHRvbiBob3Zlci4gRGVmYXVsdDogYCNmZjQ1M2FgICovXG4gIGRhbmdlckNvbG9yPzogc3RyaW5nO1xuICAvKiogTGlnaHQgdGludCBvZiB0aGUgZGFuZ2VyIGNvbG9yIHVzZWQgZm9yIGhvdmVyIGJhY2tncm91bmRzLiBEZWZhdWx0OiBgcmdiYSgyNTUsNjksNTgsMC4yMilgICovXG4gIGRhbmdlclRpbnRDb2xvcj86IHN0cmluZztcbiAgLyoqIEZvbnQgZmFtaWx5IGFwcGxpZWQgdG8gdGhlIHdob2xlIGRhc2hib2FyZC4gRGVmYXVsdDogc3lzdGVtLXVpIHN0YWNrICovXG4gIGZvbnRGYW1pbHk/OiBzdHJpbmc7XG5cbiAgLy8g4pSA4pSAIEhlYWRlciAvIFRhYnMg4pSA4pSAXG4gIC8qKiBCYWNrZ3JvdW5kIG9mIHRoZSB0YWJzIHBpbGwgY29udGFpbmVyLiBEZWZhdWx0OiBgcmdiYSg0NCw0NCw0NiwwLjYpYCAqL1xuICB0YWJzQ29udGFpbmVyQ29sb3I/OiBzdHJpbmc7XG4gIC8qKiBCYWNrZ3JvdW5kIG9mIHRoZSBhY3RpdmUvc2VsZWN0ZWQgdGFiLiBEZWZhdWx0OiBgIzNhM2EzY2AgKi9cbiAgdGFiQWN0aXZlQ29sb3I/OiBzdHJpbmc7XG4gIC8qKiBUZXh0IGNvbG9yIG9mIHRoZSBhY3RpdmUgdGFiLiBEZWZhdWx0OiBgI2ZmZmZmZmAgKi9cbiAgdGFiQWN0aXZlVGV4dENvbG9yPzogc3RyaW5nO1xuICAvKiogVGV4dCBjb2xvciBvZiBob3ZlcmVkIChpbmFjdGl2ZSkgdGFicy4gRGVmYXVsdDogYCNlNWU1ZWFgICovXG4gIHRhYkhvdmVyVGV4dENvbG9yPzogc3RyaW5nO1xuICAvKiogQmFja2dyb3VuZCBvZiBhIGhvdmVyZWQgKGluYWN0aXZlKSB0YWIuIERlZmF1bHQ6IGByZ2JhKDI1NSwyNTUsMjU1LDAuMDUpYCAqL1xuICB0YWJIb3ZlckJnQ29sb3I/OiBzdHJpbmc7XG4gIC8qKiBUZXh0IGNvbG9yIG9mIHRoZSBcIkFkZCBXaWRnZXRcIiBidXR0b24uIERlZmF1bHQ6IGAjZmZmZmZmYCAqL1xuICBhZGRXaWRnZXRCdXR0b25UZXh0Q29sb3I/OiBzdHJpbmc7XG4gIC8qKiBCYWNrZ3JvdW5kIG9mIHRoZSBvdmVyZmxvdyBcIitOXCIgYnV0dG9uLiBEZWZhdWx0OiBgcmdiYSgyNTUsMjU1LDI1NSwwLjA4KWAgKi9cbiAgb3ZlcmZsb3dCdG5CZ0NvbG9yPzogc3RyaW5nO1xuICAvKiogQm9yZGVyIG9mIHRoZSBvdmVyZmxvdyBcIitOXCIgYnV0dG9uLiBEZWZhdWx0OiBgcmdiYSgyNTUsMjU1LDI1NSwwLjEyKWAgKi9cbiAgb3ZlcmZsb3dCdG5Cb3JkZXJDb2xvcj86IHN0cmluZztcblxuICAvLyDilIDilIAgVGFiLXN3aXRjaGVyIG92ZXJsYXkg4pSA4pSAXG4gIC8qKiBCYWNrZ3JvdW5kIG9mIHRoZSBmdWxsLXNjcmVlbiBvdmVybGF5IGJlaGluZCB0aGUgdGFiLXN3aXRjaGVyIHNoZWV0LiBEZWZhdWx0OiBgcmdiYSgwLDAsMCwwLjU1KWAgKi9cbiAgb3ZlcmxheUJnQ29sb3I/OiBzdHJpbmc7XG4gIC8qKiBCb3JkZXIgY29sb3Igb2YgdGhlIHRhYi1zd2l0Y2hlciBzaGVldCBhbmQgaXRzIGlubmVyIGRpdmlkZXJzLiBEZWZhdWx0OiBgcmdiYSgyNTUsMjU1LDI1NSwwLjA4KWAgKi9cbiAgc2hlZXRCb3JkZXJDb2xvcj86IHN0cmluZztcbiAgLyoqIFNjcm9sbGJhciB0aHVtYiBjb2xvciBpbnNpZGUgdGhlIHRhYi1zd2l0Y2hlciBncmlkLiBEZWZhdWx0OiBgcmdiYSgyNTUsMjU1LDI1NSwwLjE1KWAgKi9cbiAgc2Nyb2xsYmFyQ29sb3I/OiBzdHJpbmc7XG5cbiAgLy8g4pSA4pSAIFBvcC1vdXQgd2luZG93IOKUgOKUgFxuICAvKiogVGV4dCBjb2xvciBvZiB0aGUgcG9wLW91dCBwYWdlIHRpdGxlLiBEZWZhdWx0OiBgI2ZmZmZmZmAgKi9cbiAgcG9wb3V0VGl0bGVDb2xvcj86IHN0cmluZztcblxuICAvLyDilIDilIAgV2lkZ2V0IGNhcmQg4pSA4pSAXG4gIC8qKiBUZXh0IGNvbG9yIG9mIHRoZSB3aWRnZXQgY2FyZCB0aXRsZS4gRGVmYXVsdDogYCNmZmZmZmZgICovXG4gIHdpZGdldFRpdGxlQ29sb3I/OiBzdHJpbmc7XG4gIC8qKiBDb2xvciBvZiB0aGUgZHJhZy1oYW5kbGUgZG90cyBvbiBhIHdpZGdldCBjYXJkLiBEZWZhdWx0OiBgcmdiYSgyNTUsMjU1LDI1NSwwLjIpYCAqL1xuICBkcmFnSGFuZGxlQ29sb3I/OiBzdHJpbmc7XG4gIC8qKiBCb3JkZXIgY29sb3Igb2Ygd2lkZ2V0IGNhcmRzLiBEZWZhdWx0OiBgcmdiYSgyNTUsMjU1LDI1NSwwLjA3KWAgKi9cbiAgd2lkZ2V0Qm9yZGVyQ29sb3I/OiBzdHJpbmc7XG4gIC8qKiBCYWNrZ3JvdW5kIG9mIHRoZSBpY29uIGJ1dHRvbnMgKGVkaXQvcmVtb3ZlKSBvbiB3aWRnZXQgaG92ZXIuIERlZmF1bHQ6IGByZ2JhKDI1NSwyNTUsMjU1LDAuMDcpYCAqL1xuICB3aWRnZXRCdXR0b25CZ0NvbG9yPzogc3RyaW5nO1xuICAvKiogRGVmYXVsdCB0ZXh0IGNvbG9yIG9mIGljb24gYnV0dG9ucy4gRGVmYXVsdDogYHJnYmEoMjU1LDI1NSwyNTUsMC41KWAgKi9cbiAgd2lkZ2V0QnV0dG9uQ29sb3I/OiBzdHJpbmc7XG5cbiAgLy8g4pSA4pSAIEdyaWQg4pSA4pSAXG4gIC8qKiBDb2xvciBvZiB0aGUgZHJhZy9yZXNpemUgcGxhY2Vob2xkZXIgb3ZlcmxheS4gRGVmYXVsdDogc2FtZSBhcyBhY2NlbnRDb2xvciAqL1xuICBwbGFjZWhvbGRlckNvbG9yPzogc3RyaW5nO1xuICAvKiogQ29sb3Igb2YgdGhlIHJlc2l6ZSBoYW5kbGUgaWNvbi4gRGVmYXVsdDogYHJnYmEoMjU1LDI1NSwyNTUsMC4yNSlgICovXG4gIHJlc2l6ZUhhbmRsZUNvbG9yPzogc3RyaW5nO1xufVxuIl19
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Directive, EventEmitter, TemplateRef, Component, ChangeDetectionStrategy, Input, Output, ViewChild, ContentChild, Injectable, Pipe, NgModule } from '@angular/core';
2
+ import { Directive, EventEmitter, TemplateRef, Component, ChangeDetectionStrategy, Input, Output, ViewChild, ContentChild, Injectable, Pipe, HostListener, NgModule } from '@angular/core';
3
3
  import { BrowserModule } from '@angular/platform-browser';
4
4
  import * as i2 from '@angular/common';
5
5
  import { CommonModule } from '@angular/common';
@@ -882,16 +882,26 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImpo
882
882
  const DEFAULT_THEME = {
883
883
  backgroundColor: '#000000',
884
884
  panelColor: '#1c1c1e',
885
+ panelBorderColor: 'rgba(255,255,255,0.05)',
885
886
  widgetCardColor: '#2c2c2e',
886
887
  foreColor: '#8e8e93',
887
888
  accentColor: '#0a84ff',
889
+ accentTintColor: 'rgba(10,132,255,0.15)',
890
+ accentTintStrongColor: 'rgba(10,132,255,0.25)',
888
891
  dangerColor: '#ff453a',
892
+ dangerTintColor: 'rgba(255,69,58,0.22)',
889
893
  fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif',
890
894
  tabsContainerColor: 'rgba(44,44,46,0.6)',
891
895
  tabActiveColor: '#3a3a3c',
892
896
  tabActiveTextColor: '#ffffff',
893
897
  tabHoverTextColor: '#e5e5ea',
898
+ tabHoverBgColor: 'rgba(255,255,255,0.05)',
894
899
  addWidgetButtonTextColor: '#ffffff',
900
+ overflowBtnBgColor: 'rgba(255,255,255,0.08)',
901
+ overflowBtnBorderColor: 'rgba(255,255,255,0.12)',
902
+ overlayBgColor: 'rgba(0,0,0,0.55)',
903
+ sheetBorderColor: 'rgba(255,255,255,0.08)',
904
+ scrollbarColor: 'rgba(255,255,255,0.15)',
895
905
  popoutTitleColor: '#ffffff',
896
906
  widgetTitleColor: '#ffffff',
897
907
  dragHandleColor: 'rgba(255,255,255,0.2)',
@@ -922,10 +932,19 @@ class DashboardComponent {
922
932
  this.resolvedTheme = Object.assign({}, DEFAULT_THEME);
923
933
  this.wrapperStyles = {};
924
934
  this.pages = [];
935
+ this.visiblePages = [];
936
+ this.hiddenCount = 0;
925
937
  this.activePageId = '';
926
938
  this.isPoppedOut = false;
927
- this.tabsOverflow = false;
939
+ this.tabSwitcherOpen = false;
928
940
  this.subs = new Subscription();
941
+ // Reserved space for the overflow "+N" button and the add "+" button (px)
942
+ this.OVERFLOW_BTN_W = 80;
943
+ this.ADD_BTN_W = 52;
944
+ this.GAP = 6;
945
+ this.PADDING = 12; // 6px each side
946
+ // Cache of measured tab widths (including gap) indexed by page position
947
+ this._tabWidthCache = [];
929
948
  }
930
949
  ngOnChanges(changes) {
931
950
  if (changes['theme'] || changes['initialLayout'])
@@ -947,11 +966,15 @@ class DashboardComponent {
947
966
  this.isPoppedOut = true;
948
967
  this.subs.add(this.stateService.pages$.subscribe(pages => {
949
968
  this.pages = pages;
969
+ this._tabWidthCache = []; // invalidate cache — page list changed
950
970
  if (this.isPoppedOut && hash) {
951
971
  if (pages.find(p => p.id === hash))
952
972
  this.stateService.setActivePage(hash);
953
973
  }
954
974
  this.updateActivePage();
975
+ this.recalcVisibleTabs();
976
+ // Second pass after Angular has rendered the updated tab elements
977
+ setTimeout(() => this.recalcVisibleTabs());
955
978
  }));
956
979
  this.subs.add(this.stateService.activePageId$.subscribe(id => {
957
980
  this.activePageId = id;
@@ -959,18 +982,16 @@ class DashboardComponent {
959
982
  }));
960
983
  }
961
984
  ngAfterViewInit() {
962
- if (!this.tabsContainerRef)
985
+ if (!this.tabsTrackRef)
963
986
  return;
964
987
  this.zone.runOutsideAngular(() => {
965
988
  this.resizeObserver = new ResizeObserver(() => {
966
- this.zone.run(() => this.checkOverflow());
989
+ this.zone.run(() => this.recalcVisibleTabs());
967
990
  });
968
- this.resizeObserver.observe(this.tabsContainerRef.nativeElement);
969
- });
970
- // Also detect scroll so fade hides when scrolled to end
971
- this.tabsContainerRef.nativeElement.addEventListener('scroll', () => {
972
- this.zone.run(() => this.checkOverflow());
991
+ this.resizeObserver.observe(this.tabsTrackRef.nativeElement);
973
992
  });
993
+ // Initial measurement pass now that the DOM is ready
994
+ setTimeout(() => this.recalcVisibleTabs());
974
995
  }
975
996
  ngOnDestroy() {
976
997
  var _a;
@@ -997,13 +1018,83 @@ class DashboardComponent {
997
1018
  this.stateService.popOutPage(pageId);
998
1019
  }
999
1020
  serializeLayout() { return this.stateService.serializeLayout(); }
1000
- checkOverflow() {
1001
- var _a;
1002
- const el = (_a = this.tabsContainerRef) === null || _a === void 0 ? void 0 : _a.nativeElement;
1003
- if (!el)
1021
+ openTabSwitcher() { this.tabSwitcherOpen = true; }
1022
+ closeTabSwitcher() { this.tabSwitcherOpen = false; }
1023
+ onEscapeKey() { this.closeTabSwitcher(); }
1024
+ onSwitcherSelect(pageId) {
1025
+ this.stateService.setActivePage(pageId);
1026
+ this.closeTabSwitcher();
1027
+ }
1028
+ onSwitcherPopOut(event, pageId) {
1029
+ event.stopPropagation();
1030
+ this.stateService.popOutPage(pageId);
1031
+ this.closeTabSwitcher();
1032
+ }
1033
+ onSwitcherRemove(event, pageId) {
1034
+ event.stopPropagation();
1035
+ if (confirm('Remove this workspace?')) {
1036
+ this.stateService.removePage(pageId);
1037
+ if (this.pages.length <= 1)
1038
+ this.closeTabSwitcher();
1039
+ }
1040
+ }
1041
+ onSwitcherAdd() {
1042
+ const name = prompt('Workspace name:', `Workspace ${this.pages.length + 1}`);
1043
+ if (name)
1044
+ this.stateService.addPage(name);
1045
+ }
1046
+ recalcVisibleTabs() {
1047
+ if (!this.tabsTrackRef || !this.pages.length) {
1048
+ this.visiblePages = this.pages;
1049
+ this.hiddenCount = 0;
1050
+ this.cdr.markForCheck();
1004
1051
  return;
1005
- const atEnd = el.scrollLeft + el.clientWidth >= el.scrollWidth - 4;
1006
- this.tabsOverflow = !atEnd && el.scrollWidth > el.clientWidth;
1052
+ }
1053
+ const track = this.tabsTrackRef.nativeElement;
1054
+ const trackW = track.clientWidth;
1055
+ // Space always consumed by the add "+" button + padding
1056
+ const baseReserved = this.ADD_BTN_W + this.GAP + this.PADDING;
1057
+ // Space needed for the overflow "+N" button when shown
1058
+ const overflowSlot = this.OVERFLOW_BTN_W + this.GAP;
1059
+ // Measure each real tab element currently in the DOM.
1060
+ // The DOM always renders all visiblePages tabs, so we may not have all tabs
1061
+ // measured yet — fall back to the previous measured cache or a generous estimate.
1062
+ const tabEls = Array.from(track.querySelectorAll('.tab'));
1063
+ // Build a width map by index (only covers currently visible tabs)
1064
+ const measuredWidths = this.pages.map((_, i) => {
1065
+ var _a;
1066
+ const el = tabEls[i];
1067
+ return el ? el.getBoundingClientRect().width + this.GAP : (_a = this._tabWidthCache[i]) !== null && _a !== void 0 ? _a : 150 + this.GAP;
1068
+ });
1069
+ // Update cache for next call
1070
+ tabEls.forEach((el, i) => {
1071
+ this._tabWidthCache[i] = el.getBoundingClientRect().width + this.GAP;
1072
+ });
1073
+ // How much space the tabs need in total (no overflow button)
1074
+ const totalNeeded = measuredWidths.reduce((s, w) => s + w, 0) - this.GAP; // remove trailing gap
1075
+ if (totalNeeded <= trackW - baseReserved) {
1076
+ // Everything fits — show all
1077
+ this.visiblePages = this.pages;
1078
+ this.hiddenCount = 0;
1079
+ }
1080
+ else {
1081
+ // Not everything fits — fill as many as possible while always leaving room for overflow btn
1082
+ const budget = trackW - baseReserved - overflowSlot;
1083
+ let used = 0;
1084
+ let count = 0;
1085
+ for (let i = 0; i < this.pages.length; i++) {
1086
+ used += measuredWidths[i];
1087
+ if (used - this.GAP <= budget) { // -GAP: last item has no trailing gap
1088
+ count++;
1089
+ }
1090
+ else {
1091
+ break;
1092
+ }
1093
+ }
1094
+ count = Math.max(1, count);
1095
+ this.visiblePages = this.pages.slice(0, count);
1096
+ this.hiddenCount = this.pages.length - count;
1097
+ }
1007
1098
  this.cdr.markForCheck();
1008
1099
  }
1009
1100
  applyTheme() {
@@ -1013,16 +1104,26 @@ class DashboardComponent {
1013
1104
  this.wrapperStyles = {
1014
1105
  '--dash-bg': t.backgroundColor,
1015
1106
  '--dash-panel-bg': t.panelColor,
1107
+ '--dash-panel-border': t.panelBorderColor,
1016
1108
  '--dash-card-bg': t.widgetCardColor,
1017
1109
  '--dash-fore-color': t.foreColor,
1018
1110
  '--dash-accent-color': t.accentColor,
1111
+ '--dash-accent-tint': t.accentTintColor,
1112
+ '--dash-accent-tint-strong': t.accentTintStrongColor,
1019
1113
  '--dash-danger-color': t.dangerColor,
1114
+ '--dash-danger-tint': t.dangerTintColor,
1020
1115
  '--dash-font-family': t.fontFamily,
1021
1116
  '--dash-tabs-container-color': t.tabsContainerColor,
1022
1117
  '--dash-tab-active-color': t.tabActiveColor,
1023
1118
  '--dash-tab-active-text': t.tabActiveTextColor,
1024
1119
  '--dash-tab-hover-text': t.tabHoverTextColor,
1120
+ '--dash-tab-hover-bg': t.tabHoverBgColor,
1025
1121
  '--dash-add-widget-text': t.addWidgetButtonTextColor,
1122
+ '--dash-overflow-btn-bg': t.overflowBtnBgColor,
1123
+ '--dash-overflow-btn-border': t.overflowBtnBorderColor,
1124
+ '--dash-overlay-bg': t.overlayBgColor,
1125
+ '--dash-sheet-border': t.sheetBorderColor,
1126
+ '--dash-scrollbar-color': t.scrollbarColor,
1026
1127
  '--dash-popout-title-color': t.popoutTitleColor,
1027
1128
  '--dash-widget-title-color': t.widgetTitleColor,
1028
1129
  '--dash-drag-handle-color': t.dragHandleColor,
@@ -1035,18 +1136,10 @@ class DashboardComponent {
1035
1136
  }
1036
1137
  updateActivePage() {
1037
1138
  this.activePage = this.pages.find(p => p.id === this.activePageId);
1038
- // scroll active tab into view
1039
- setTimeout(() => {
1040
- if (!this.tabsContainerRef)
1041
- return;
1042
- const active = this.tabsContainerRef.nativeElement.querySelector('.tab.active');
1043
- active === null || active === void 0 ? void 0 : active.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'nearest' });
1044
- this.checkOverflow();
1045
- });
1046
1139
  }
1047
1140
  }
1048
1141
  DashboardComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: DashboardComponent, deps: [{ token: DashboardStateService }, { token: i0.ChangeDetectorRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
1049
- DashboardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: DashboardComponent, selector: "app-dashboard", inputs: { initialLayout: "initialLayout", theme: "theme" }, outputs: { addWidgetRequested: "addWidgetRequested", editWidgetRequested: "editWidgetRequested" }, queries: [{ propertyName: "cellTemplate", first: true, predicate: GridCellDirective, descendants: true, read: TemplateRef }], viewQueries: [{ propertyName: "tabsContainerRef", first: true, predicate: ["tabsContainer"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
1142
+ DashboardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: DashboardComponent, selector: "app-dashboard", inputs: { initialLayout: "initialLayout", theme: "theme" }, outputs: { addWidgetRequested: "addWidgetRequested", editWidgetRequested: "editWidgetRequested" }, host: { listeners: { "document:keydown.escape": "onEscapeKey()" } }, queries: [{ propertyName: "cellTemplate", first: true, predicate: GridCellDirective, descendants: true, read: TemplateRef }], viewQueries: [{ propertyName: "tabsTrackRef", first: true, predicate: ["tabsTrack"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
1050
1143
  <!-- POPPED-OUT MODE -->
1051
1144
  <ng-container *ngIf="isPoppedOut; else normalMode">
1052
1145
  <div class="popout-wrapper" [ngStyle]="wrapperStyles">
@@ -1075,29 +1168,39 @@ DashboardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", ver
1075
1168
 
1076
1169
  <header class="dashboard-header">
1077
1170
 
1078
- <!-- Tabs pill — scrollable, fades when overflowing -->
1079
- <div class="tabs-scroll-track">
1080
- <div class="tabs-container" #tabsContainer>
1081
- <div
1082
- *ngFor="let page of pages"
1083
- class="tab"
1084
- [class.active]="page.id === activePageId"
1085
- (click)="onSelectPage(page.id)"
1086
- >
1087
- <span class="tab-name">{{ page.name }}</span>
1088
- <button class="tab-action tab-popout" (click)="onPopOut($event, page.id)" title="Open in new window">
1089
- <i class="la la-external-link-alt"></i>
1090
- </button>
1091
- <button class="tab-action tab-close" *ngIf="pages.length > 1" (click)="onRemovePage($event, page.id)" title="Close">
1092
- <i class="la la-times"></i>
1093
- </button>
1094
- </div>
1095
- <button class="btn-add-page" (click)="onAddPage()" title="New workspace">
1096
- <i class="la la-plus"></i>
1171
+ <!-- Tab bar -->
1172
+ <div class="tabs-track" #tabsTrack>
1173
+ <!-- Visible tabs -->
1174
+ <div
1175
+ *ngFor="let page of visiblePages"
1176
+ class="tab"
1177
+ [class.active]="page.id === activePageId"
1178
+ (click)="onSelectPage(page.id)"
1179
+ >
1180
+ <span class="tab-name">{{ page.name }}</span>
1181
+ <button class="tab-action tab-popout" (click)="onPopOut($event, page.id)" title="Open in new window">
1182
+ <i class="la la-external-link-alt"></i>
1183
+ </button>
1184
+ <button class="tab-action tab-close" *ngIf="pages.length > 1" (click)="onRemovePage($event, page.id)" title="Close">
1185
+ <i class="la la-times"></i>
1097
1186
  </button>
1098
1187
  </div>
1099
- <!-- fade hint shown when scrollable -->
1100
- <div class="tabs-fade-right" *ngIf="tabsOverflow"></div>
1188
+
1189
+ <!-- Overflow button — shown only when there are hidden tabs -->
1190
+ <button
1191
+ *ngIf="hiddenCount > 0"
1192
+ class="btn-overflow"
1193
+ (click)="openTabSwitcher()"
1194
+ title="Show all workspaces"
1195
+ >
1196
+ <span>+{{ hiddenCount }}</span>
1197
+ <i class="la la-th-large"></i>
1198
+ </button>
1199
+
1200
+ <!-- Add page button -->
1201
+ <button class="btn-add-page" (click)="onAddPage()" title="New workspace">
1202
+ <i class="la la-plus"></i>
1203
+ </button>
1101
1204
  </div>
1102
1205
 
1103
1206
  <button class="btn-add-widget" (click)="addWidgetRequested.emit()" title="Add widget">
@@ -1107,6 +1210,49 @@ DashboardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", ver
1107
1210
 
1108
1211
  </header>
1109
1212
 
1213
+ <!-- ── Tab-switcher overlay (Chrome mobile style) ── -->
1214
+ <div class="tab-switcher-overlay" *ngIf="tabSwitcherOpen" (click)="closeTabSwitcher()">
1215
+ <div class="tab-switcher-sheet" (click)="$event.stopPropagation()">
1216
+
1217
+ <div class="tab-switcher-header">
1218
+ <span class="tab-switcher-title">{{ pages.length }} Workspace{{ pages.length !== 1 ? 's' : '' }}</span>
1219
+ <button class="tab-switcher-close-btn" (click)="closeTabSwitcher()" title="Close">
1220
+ <i class="la la-times"></i>
1221
+ </button>
1222
+ </div>
1223
+
1224
+ <div class="tab-switcher-grid">
1225
+ <div
1226
+ *ngFor="let page of pages"
1227
+ class="tab-card"
1228
+ [class.active]="page.id === activePageId"
1229
+ (click)="onSwitcherSelect(page.id)"
1230
+ >
1231
+ <div class="tab-card-icon">
1232
+ <i class="la la-th-large"></i>
1233
+ </div>
1234
+ <span class="tab-card-name">{{ page.name }}</span>
1235
+ <div class="tab-card-actions">
1236
+ <button class="tab-card-btn tab-card-popout" (click)="onSwitcherPopOut($event, page.id)" title="Open in new window">
1237
+ <i class="la la-external-link-alt"></i>
1238
+ </button>
1239
+ <button class="tab-card-btn tab-card-remove" *ngIf="pages.length > 1" (click)="onSwitcherRemove($event, page.id)" title="Close">
1240
+ <i class="la la-times"></i>
1241
+ </button>
1242
+ </div>
1243
+ </div>
1244
+ </div>
1245
+
1246
+ <div class="tab-switcher-footer">
1247
+ <button class="tab-switcher-add-btn" (click)="onSwitcherAdd()">
1248
+ <i class="la la-plus"></i>
1249
+ <span>New Workspace</span>
1250
+ </button>
1251
+ </div>
1252
+
1253
+ </div>
1254
+ </div>
1255
+
1110
1256
  <div class="grid-container">
1111
1257
  <app-grid [widgets]="activePage?.widgets || []" (itemChanged)="onItemChanged($event)">
1112
1258
  <ng-template gridCell let-widget="widget">
@@ -1125,7 +1271,7 @@ DashboardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", ver
1125
1271
  </main>
1126
1272
  </div>
1127
1273
  </ng-template>
1128
- `, isInline: true, styles: [":host{display:flex;flex-direction:column;width:100%;height:100%;min-height:0;--dash-bg: #000000;--dash-panel-bg: #1c1c1e;--dash-card-bg: #2c2c2e;--dash-fore-color: #8e8e93;--dash-accent-color: #0a84ff;--dash-danger-color: #ff453a;--dash-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif;--dash-tabs-container-color: rgba(44,44,46,.6);--dash-tab-active-color: #3a3a3c;--dash-tab-active-text: #ffffff;--dash-tab-hover-text: #e5e5ea;--dash-add-widget-text: #ffffff;--dash-popout-title-color: #ffffff;--dash-widget-title-color: #ffffff;--dash-drag-handle-color: rgba(255,255,255,.2);--dash-widget-border-color: rgba(255,255,255,.07);--dash-widget-btn-bg: rgba(255,255,255,.07);--dash-widget-btn-color: rgba(255,255,255,.5);--dash-placeholder-color: #0a84ff;--dash-resize-handle-color: rgba(255,255,255,.25)}.dashboard-wrapper{display:flex;flex:1;min-height:0;overflow:hidden;padding:16px;box-sizing:border-box;background:var(--dash-bg);color:var(--dash-fore-color);font-family:var(--dash-font-family)}.main-content{flex:1;display:flex;flex-direction:column;overflow:hidden;border-radius:40px;padding:20px;background:var(--dash-panel-bg);border:1px solid rgba(255,255,255,.05)}.popout-wrapper{display:flex;flex:1;flex-direction:column;min-height:0;overflow:hidden;padding:16px;box-sizing:border-box;background:var(--dash-bg);color:var(--dash-fore-color);font-family:var(--dash-font-family)}.popout-header{display:flex;align-items:center;margin-bottom:16px;padding:10px 18px;background:var(--dash-panel-bg);border-radius:20px;border:1px solid rgba(255,255,255,.06);flex-shrink:0}.popout-title{font-size:16px;font-weight:700;color:var(--dash-popout-title-color)}.popout-wrapper app-grid{flex:1;min-height:0;overflow:auto}.dashboard-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:20px;gap:12px;flex-shrink:0}.tabs-scroll-track{position:relative;flex:1;min-width:0}.tabs-container{display:flex;align-items:center;gap:8px;background:var(--dash-tabs-container-color);backdrop-filter:blur(10px);border-radius:25px;padding:6px;overflow-x:auto;overflow-y:hidden;scrollbar-width:none}.tabs-container::-webkit-scrollbar{display:none}.tabs-fade-right{position:absolute;top:0;right:0;width:60px;height:100%;border-radius:0 25px 25px 0;pointer-events:none;background:linear-gradient(to right,transparent,var(--dash-panel-bg))}.tab{display:flex;align-items:center;gap:4px;padding:8px 14px 8px 18px;border-radius:20px;cursor:pointer;font-size:14px;font-weight:500;color:var(--dash-fore-color);white-space:nowrap;flex-shrink:0;transition:all .2s}.tab.active{background:var(--dash-tab-active-color);color:var(--dash-tab-active-text)}.tab:hover:not(.active){color:var(--dash-tab-hover-text);background:rgba(255,255,255,.05)}.tab-name{flex:1;white-space:nowrap}.tab-action{background:transparent;border:none;color:var(--dash-fore-color);padding:2px;font-size:11px;cursor:pointer;opacity:0;border-radius:50%;width:20px;height:20px;display:flex;align-items:center;justify-content:center;transition:all .2s;flex-shrink:0}.tab:hover .tab-action{opacity:1}.tab-popout:hover{color:var(--dash-accent-color);background:rgba(10,132,255,.18)}.tab-close:hover{color:var(--dash-danger-color);background:rgba(255,69,58,.2)}.btn-add-page{background:transparent;border:none;color:var(--dash-fore-color);padding:8px 16px;cursor:pointer;border-radius:20px;flex-shrink:0;transition:all .2s}.btn-add-page:hover{color:var(--dash-accent-color);background:rgba(10,132,255,.1)}.btn-add-widget{display:flex;align-items:center;gap:6px;background:var(--dash-accent-color);border:none;color:var(--dash-add-widget-text);font-size:14px;font-weight:600;padding:10px 20px;border-radius:22px;cursor:pointer;white-space:nowrap;flex-shrink:0;transition:opacity .2s,transform .15s}.btn-add-widget:hover{opacity:.9;transform:translateY(-1px)}.btn-add-widget:active{transform:translateY(0)}.main-content .grid-container{flex:1;overflow:auto;border-radius:24px;min-height:0}app-grid{background:transparent;display:block;height:100%;width:100%}\n"], dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: WidgetRendererComponent, selector: "app-widget-renderer", inputs: ["widget", "theme"], outputs: ["editRequested", "removeRequested"] }, { kind: "component", type: CustomGridComponent, selector: "app-grid", inputs: ["widgets", "columns", "gap", "rowHeight", "minItemCols", "minItemRows"], outputs: ["itemChanged", "layoutChanged"] }, { kind: "directive", type: GridCellDirective, selector: "[gridCell]" }] });
1274
+ `, isInline: true, styles: [":host{display:flex;flex-direction:column;width:100%;height:100%;min-height:0;--dash-bg: #000000;--dash-panel-bg: #1c1c1e;--dash-panel-border: rgba(255,255,255,.05);--dash-card-bg: #2c2c2e;--dash-fore-color: #8e8e93;--dash-accent-color: #0a84ff;--dash-accent-tint: rgba(10,132,255,.15);--dash-accent-tint-strong: rgba(10,132,255,.25);--dash-danger-color: #ff453a;--dash-danger-tint: rgba(255,69,58,.22);--dash-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif;--dash-tabs-container-color: rgba(44,44,46,.6);--dash-tab-active-color: #3a3a3c;--dash-tab-active-text: #ffffff;--dash-tab-hover-text: #e5e5ea;--dash-tab-hover-bg: rgba(255,255,255,.05);--dash-add-widget-text: #ffffff;--dash-overflow-btn-bg: rgba(255,255,255,.08);--dash-overflow-btn-border: rgba(255,255,255,.12);--dash-overlay-bg: rgba(0,0,0,.55);--dash-sheet-border: rgba(255,255,255,.08);--dash-scrollbar-color: rgba(255,255,255,.15);--dash-popout-title-color: #ffffff;--dash-widget-title-color: #ffffff;--dash-drag-handle-color: rgba(255,255,255,.2);--dash-widget-border-color: rgba(255,255,255,.07);--dash-widget-btn-bg: rgba(255,255,255,.07);--dash-widget-btn-color: rgba(255,255,255,.5);--dash-placeholder-color: #0a84ff;--dash-resize-handle-color: rgba(255,255,255,.25)}.dashboard-wrapper{display:flex;flex:1;min-height:0;overflow:hidden;padding:16px;box-sizing:border-box;background:var(--dash-bg);color:var(--dash-fore-color);font-family:var(--dash-font-family)}.main-content{flex:1;display:flex;flex-direction:column;overflow:hidden;border-radius:40px;padding:20px;background:var(--dash-panel-bg);border:1px solid var(--dash-panel-border);position:relative}.popout-wrapper{display:flex;flex:1;flex-direction:column;min-height:0;overflow:hidden;padding:16px;box-sizing:border-box;background:var(--dash-bg);color:var(--dash-fore-color);font-family:var(--dash-font-family)}.popout-header{display:flex;align-items:center;margin-bottom:16px;padding:10px 18px;background:var(--dash-panel-bg);border-radius:20px;border:1px solid var(--dash-panel-border);flex-shrink:0}.popout-title{font-size:16px;font-weight:700;color:var(--dash-popout-title-color)}.popout-wrapper app-grid{flex:1;min-height:0;overflow:auto}.dashboard-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:20px;gap:12px;flex-shrink:0}.tabs-track{display:flex;align-items:center;gap:6px;flex:1;min-width:0;background:var(--dash-tabs-container-color);backdrop-filter:blur(10px);border-radius:25px;padding:6px;overflow:hidden}.tab{display:flex;align-items:center;gap:4px;padding:8px 14px 8px 18px;border-radius:20px;cursor:pointer;font-size:14px;font-weight:500;color:var(--dash-fore-color);white-space:nowrap;flex-shrink:0;transition:background .2s,color .2s}.tab.active{background:var(--dash-tab-active-color);color:var(--dash-tab-active-text)}.tab:hover:not(.active){color:var(--dash-tab-hover-text);background:var(--dash-tab-hover-bg)}.tab-name{white-space:nowrap}.tab-action{background:transparent;border:none;color:var(--dash-fore-color);padding:2px;font-size:11px;cursor:pointer;opacity:0;border-radius:50%;width:20px;height:20px;display:flex;align-items:center;justify-content:center;transition:all .2s;flex-shrink:0}.tab:hover .tab-action{opacity:1}.tab-popout:hover{color:var(--dash-accent-color);background:var(--dash-accent-tint)}.tab-close:hover{color:var(--dash-danger-color);background:var(--dash-danger-tint)}.btn-overflow{display:inline-flex;align-items:center;gap:5px;background:var(--dash-overflow-btn-bg);border:1px solid var(--dash-overflow-btn-border);border-radius:20px;padding:7px 13px;cursor:pointer;font-size:13px;font-weight:600;color:var(--dash-tab-active-text);white-space:nowrap;flex-shrink:0;transition:background .2s,border-color .2s,color .2s}.btn-overflow:hover{background:var(--dash-accent-tint);border-color:var(--dash-accent-color);color:var(--dash-accent-color)}.btn-add-page{background:transparent;border:none;color:var(--dash-fore-color);padding:8px 14px;cursor:pointer;border-radius:20px;flex-shrink:0;transition:all .2s}.btn-add-page:hover{color:var(--dash-accent-color);background:var(--dash-accent-tint)}.tab-switcher-overlay{position:absolute;inset:0;z-index:1000;background:var(--dash-overlay-bg);backdrop-filter:blur(4px);display:flex;align-items:flex-start;justify-content:center;padding-top:60px;animation:overlay-in .18s ease}@keyframes overlay-in{0%{opacity:0}to{opacity:1}}.tab-switcher-sheet{background:var(--dash-panel-bg);border:1px solid var(--dash-sheet-border);border-radius:24px;width:min(520px,calc(100% - 32px));max-height:calc(100% - 80px);display:flex;flex-direction:column;overflow:hidden;animation:sheet-in .22s cubic-bezier(.32,1.2,.5,1)}@keyframes sheet-in{0%{transform:translateY(-16px) scale(.97);opacity:0}to{transform:translateY(0) scale(1);opacity:1}}.tab-switcher-header{display:flex;align-items:center;justify-content:space-between;padding:16px 20px 12px;border-bottom:1px solid var(--dash-sheet-border);flex-shrink:0}.tab-switcher-title{font-size:15px;font-weight:700;color:var(--dash-tab-active-text)}.tab-switcher-close-btn{background:var(--dash-widget-btn-bg);border:none;color:var(--dash-fore-color);width:28px;height:28px;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;font-size:14px;transition:background .15s,color .15s}.tab-switcher-close-btn:hover{background:var(--dash-danger-tint);color:var(--dash-danger-color)}.tab-switcher-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:10px;padding:16px;overflow-y:auto;scrollbar-width:thin;scrollbar-color:var(--dash-scrollbar-color) transparent}.tab-card{display:flex;flex-direction:column;align-items:center;gap:8px;padding:16px 12px 12px;border-radius:16px;background:var(--dash-card-bg);border:1.5px solid transparent;cursor:pointer;transition:border-color .15s,background .15s,transform .12s;position:relative}.tab-card:hover{background:var(--dash-tab-hover-bg);transform:translateY(-2px)}.tab-card.active{border-color:var(--dash-accent-color);background:var(--dash-accent-tint)}.tab-card-icon{width:44px;height:44px;border-radius:12px;background:var(--dash-widget-btn-bg);display:flex;align-items:center;justify-content:center;font-size:20px;color:var(--dash-fore-color)}.tab-card.active .tab-card-icon{background:var(--dash-accent-tint-strong);color:var(--dash-accent-color)}.tab-card-name{font-size:13px;font-weight:500;color:var(--dash-tab-active-text);text-align:center;word-break:break-word;line-height:1.3}.tab-card-actions{display:flex;gap:4px;opacity:0;transition:opacity .15s}.tab-card:hover .tab-card-actions{opacity:1}.tab-card-btn{background:var(--dash-widget-btn-bg);border:none;width:26px;height:26px;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;font-size:12px;color:var(--dash-fore-color);transition:background .15s,color .15s}.tab-card-popout:hover{background:var(--dash-accent-tint-strong);color:var(--dash-accent-color)}.tab-card-remove:hover{background:var(--dash-danger-tint);color:var(--dash-danger-color)}.tab-switcher-footer{padding:12px 16px 16px;border-top:1px solid var(--dash-sheet-border);flex-shrink:0}.tab-switcher-add-btn{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;padding:11px 20px;border-radius:16px;background:var(--dash-accent-tint);border:1.5px dashed var(--dash-accent-tint-strong);color:var(--dash-accent-color);font-size:14px;font-weight:600;cursor:pointer;transition:background .15s,border-color .15s}.tab-switcher-add-btn:hover{background:var(--dash-accent-tint-strong);border-color:var(--dash-accent-color)}.btn-add-widget{display:flex;align-items:center;gap:6px;background:var(--dash-accent-color);border:none;color:var(--dash-add-widget-text);font-size:14px;font-weight:600;padding:10px 20px;border-radius:22px;cursor:pointer;white-space:nowrap;flex-shrink:0;transition:opacity .2s,transform .15s}.btn-add-widget:hover{opacity:.9;transform:translateY(-1px)}.btn-add-widget:active{transform:translateY(0)}.main-content .grid-container{flex:1;overflow:auto;border-radius:24px;min-height:0}app-grid{background:transparent;display:block;height:100%;width:100%}\n"], dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: WidgetRendererComponent, selector: "app-widget-renderer", inputs: ["widget", "theme"], outputs: ["editRequested", "removeRequested"] }, { kind: "component", type: CustomGridComponent, selector: "app-grid", inputs: ["widgets", "columns", "gap", "rowHeight", "minItemCols", "minItemRows"], outputs: ["itemChanged", "layoutChanged"] }, { kind: "directive", type: GridCellDirective, selector: "[gridCell]" }] });
1129
1275
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: DashboardComponent, decorators: [{
1130
1276
  type: Component,
1131
1277
  args: [{ selector: 'app-dashboard', template: `
@@ -1157,29 +1303,39 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImpo
1157
1303
 
1158
1304
  <header class="dashboard-header">
1159
1305
 
1160
- <!-- Tabs pill — scrollable, fades when overflowing -->
1161
- <div class="tabs-scroll-track">
1162
- <div class="tabs-container" #tabsContainer>
1163
- <div
1164
- *ngFor="let page of pages"
1165
- class="tab"
1166
- [class.active]="page.id === activePageId"
1167
- (click)="onSelectPage(page.id)"
1168
- >
1169
- <span class="tab-name">{{ page.name }}</span>
1170
- <button class="tab-action tab-popout" (click)="onPopOut($event, page.id)" title="Open in new window">
1171
- <i class="la la-external-link-alt"></i>
1172
- </button>
1173
- <button class="tab-action tab-close" *ngIf="pages.length > 1" (click)="onRemovePage($event, page.id)" title="Close">
1174
- <i class="la la-times"></i>
1175
- </button>
1176
- </div>
1177
- <button class="btn-add-page" (click)="onAddPage()" title="New workspace">
1178
- <i class="la la-plus"></i>
1306
+ <!-- Tab bar -->
1307
+ <div class="tabs-track" #tabsTrack>
1308
+ <!-- Visible tabs -->
1309
+ <div
1310
+ *ngFor="let page of visiblePages"
1311
+ class="tab"
1312
+ [class.active]="page.id === activePageId"
1313
+ (click)="onSelectPage(page.id)"
1314
+ >
1315
+ <span class="tab-name">{{ page.name }}</span>
1316
+ <button class="tab-action tab-popout" (click)="onPopOut($event, page.id)" title="Open in new window">
1317
+ <i class="la la-external-link-alt"></i>
1318
+ </button>
1319
+ <button class="tab-action tab-close" *ngIf="pages.length > 1" (click)="onRemovePage($event, page.id)" title="Close">
1320
+ <i class="la la-times"></i>
1179
1321
  </button>
1180
1322
  </div>
1181
- <!-- fade hint shown when scrollable -->
1182
- <div class="tabs-fade-right" *ngIf="tabsOverflow"></div>
1323
+
1324
+ <!-- Overflow button — shown only when there are hidden tabs -->
1325
+ <button
1326
+ *ngIf="hiddenCount > 0"
1327
+ class="btn-overflow"
1328
+ (click)="openTabSwitcher()"
1329
+ title="Show all workspaces"
1330
+ >
1331
+ <span>+{{ hiddenCount }}</span>
1332
+ <i class="la la-th-large"></i>
1333
+ </button>
1334
+
1335
+ <!-- Add page button -->
1336
+ <button class="btn-add-page" (click)="onAddPage()" title="New workspace">
1337
+ <i class="la la-plus"></i>
1338
+ </button>
1183
1339
  </div>
1184
1340
 
1185
1341
  <button class="btn-add-widget" (click)="addWidgetRequested.emit()" title="Add widget">
@@ -1189,6 +1345,49 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImpo
1189
1345
 
1190
1346
  </header>
1191
1347
 
1348
+ <!-- ── Tab-switcher overlay (Chrome mobile style) ── -->
1349
+ <div class="tab-switcher-overlay" *ngIf="tabSwitcherOpen" (click)="closeTabSwitcher()">
1350
+ <div class="tab-switcher-sheet" (click)="$event.stopPropagation()">
1351
+
1352
+ <div class="tab-switcher-header">
1353
+ <span class="tab-switcher-title">{{ pages.length }} Workspace{{ pages.length !== 1 ? 's' : '' }}</span>
1354
+ <button class="tab-switcher-close-btn" (click)="closeTabSwitcher()" title="Close">
1355
+ <i class="la la-times"></i>
1356
+ </button>
1357
+ </div>
1358
+
1359
+ <div class="tab-switcher-grid">
1360
+ <div
1361
+ *ngFor="let page of pages"
1362
+ class="tab-card"
1363
+ [class.active]="page.id === activePageId"
1364
+ (click)="onSwitcherSelect(page.id)"
1365
+ >
1366
+ <div class="tab-card-icon">
1367
+ <i class="la la-th-large"></i>
1368
+ </div>
1369
+ <span class="tab-card-name">{{ page.name }}</span>
1370
+ <div class="tab-card-actions">
1371
+ <button class="tab-card-btn tab-card-popout" (click)="onSwitcherPopOut($event, page.id)" title="Open in new window">
1372
+ <i class="la la-external-link-alt"></i>
1373
+ </button>
1374
+ <button class="tab-card-btn tab-card-remove" *ngIf="pages.length > 1" (click)="onSwitcherRemove($event, page.id)" title="Close">
1375
+ <i class="la la-times"></i>
1376
+ </button>
1377
+ </div>
1378
+ </div>
1379
+ </div>
1380
+
1381
+ <div class="tab-switcher-footer">
1382
+ <button class="tab-switcher-add-btn" (click)="onSwitcherAdd()">
1383
+ <i class="la la-plus"></i>
1384
+ <span>New Workspace</span>
1385
+ </button>
1386
+ </div>
1387
+
1388
+ </div>
1389
+ </div>
1390
+
1192
1391
  <div class="grid-container">
1193
1392
  <app-grid [widgets]="activePage?.widgets || []" (itemChanged)="onItemChanged($event)">
1194
1393
  <ng-template gridCell let-widget="widget">
@@ -1207,7 +1406,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImpo
1207
1406
  </main>
1208
1407
  </div>
1209
1408
  </ng-template>
1210
- `, styles: [":host{display:flex;flex-direction:column;width:100%;height:100%;min-height:0;--dash-bg: #000000;--dash-panel-bg: #1c1c1e;--dash-card-bg: #2c2c2e;--dash-fore-color: #8e8e93;--dash-accent-color: #0a84ff;--dash-danger-color: #ff453a;--dash-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif;--dash-tabs-container-color: rgba(44,44,46,.6);--dash-tab-active-color: #3a3a3c;--dash-tab-active-text: #ffffff;--dash-tab-hover-text: #e5e5ea;--dash-add-widget-text: #ffffff;--dash-popout-title-color: #ffffff;--dash-widget-title-color: #ffffff;--dash-drag-handle-color: rgba(255,255,255,.2);--dash-widget-border-color: rgba(255,255,255,.07);--dash-widget-btn-bg: rgba(255,255,255,.07);--dash-widget-btn-color: rgba(255,255,255,.5);--dash-placeholder-color: #0a84ff;--dash-resize-handle-color: rgba(255,255,255,.25)}.dashboard-wrapper{display:flex;flex:1;min-height:0;overflow:hidden;padding:16px;box-sizing:border-box;background:var(--dash-bg);color:var(--dash-fore-color);font-family:var(--dash-font-family)}.main-content{flex:1;display:flex;flex-direction:column;overflow:hidden;border-radius:40px;padding:20px;background:var(--dash-panel-bg);border:1px solid rgba(255,255,255,.05)}.popout-wrapper{display:flex;flex:1;flex-direction:column;min-height:0;overflow:hidden;padding:16px;box-sizing:border-box;background:var(--dash-bg);color:var(--dash-fore-color);font-family:var(--dash-font-family)}.popout-header{display:flex;align-items:center;margin-bottom:16px;padding:10px 18px;background:var(--dash-panel-bg);border-radius:20px;border:1px solid rgba(255,255,255,.06);flex-shrink:0}.popout-title{font-size:16px;font-weight:700;color:var(--dash-popout-title-color)}.popout-wrapper app-grid{flex:1;min-height:0;overflow:auto}.dashboard-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:20px;gap:12px;flex-shrink:0}.tabs-scroll-track{position:relative;flex:1;min-width:0}.tabs-container{display:flex;align-items:center;gap:8px;background:var(--dash-tabs-container-color);backdrop-filter:blur(10px);border-radius:25px;padding:6px;overflow-x:auto;overflow-y:hidden;scrollbar-width:none}.tabs-container::-webkit-scrollbar{display:none}.tabs-fade-right{position:absolute;top:0;right:0;width:60px;height:100%;border-radius:0 25px 25px 0;pointer-events:none;background:linear-gradient(to right,transparent,var(--dash-panel-bg))}.tab{display:flex;align-items:center;gap:4px;padding:8px 14px 8px 18px;border-radius:20px;cursor:pointer;font-size:14px;font-weight:500;color:var(--dash-fore-color);white-space:nowrap;flex-shrink:0;transition:all .2s}.tab.active{background:var(--dash-tab-active-color);color:var(--dash-tab-active-text)}.tab:hover:not(.active){color:var(--dash-tab-hover-text);background:rgba(255,255,255,.05)}.tab-name{flex:1;white-space:nowrap}.tab-action{background:transparent;border:none;color:var(--dash-fore-color);padding:2px;font-size:11px;cursor:pointer;opacity:0;border-radius:50%;width:20px;height:20px;display:flex;align-items:center;justify-content:center;transition:all .2s;flex-shrink:0}.tab:hover .tab-action{opacity:1}.tab-popout:hover{color:var(--dash-accent-color);background:rgba(10,132,255,.18)}.tab-close:hover{color:var(--dash-danger-color);background:rgba(255,69,58,.2)}.btn-add-page{background:transparent;border:none;color:var(--dash-fore-color);padding:8px 16px;cursor:pointer;border-radius:20px;flex-shrink:0;transition:all .2s}.btn-add-page:hover{color:var(--dash-accent-color);background:rgba(10,132,255,.1)}.btn-add-widget{display:flex;align-items:center;gap:6px;background:var(--dash-accent-color);border:none;color:var(--dash-add-widget-text);font-size:14px;font-weight:600;padding:10px 20px;border-radius:22px;cursor:pointer;white-space:nowrap;flex-shrink:0;transition:opacity .2s,transform .15s}.btn-add-widget:hover{opacity:.9;transform:translateY(-1px)}.btn-add-widget:active{transform:translateY(0)}.main-content .grid-container{flex:1;overflow:auto;border-radius:24px;min-height:0}app-grid{background:transparent;display:block;height:100%;width:100%}\n"] }]
1409
+ `, styles: [":host{display:flex;flex-direction:column;width:100%;height:100%;min-height:0;--dash-bg: #000000;--dash-panel-bg: #1c1c1e;--dash-panel-border: rgba(255,255,255,.05);--dash-card-bg: #2c2c2e;--dash-fore-color: #8e8e93;--dash-accent-color: #0a84ff;--dash-accent-tint: rgba(10,132,255,.15);--dash-accent-tint-strong: rgba(10,132,255,.25);--dash-danger-color: #ff453a;--dash-danger-tint: rgba(255,69,58,.22);--dash-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif;--dash-tabs-container-color: rgba(44,44,46,.6);--dash-tab-active-color: #3a3a3c;--dash-tab-active-text: #ffffff;--dash-tab-hover-text: #e5e5ea;--dash-tab-hover-bg: rgba(255,255,255,.05);--dash-add-widget-text: #ffffff;--dash-overflow-btn-bg: rgba(255,255,255,.08);--dash-overflow-btn-border: rgba(255,255,255,.12);--dash-overlay-bg: rgba(0,0,0,.55);--dash-sheet-border: rgba(255,255,255,.08);--dash-scrollbar-color: rgba(255,255,255,.15);--dash-popout-title-color: #ffffff;--dash-widget-title-color: #ffffff;--dash-drag-handle-color: rgba(255,255,255,.2);--dash-widget-border-color: rgba(255,255,255,.07);--dash-widget-btn-bg: rgba(255,255,255,.07);--dash-widget-btn-color: rgba(255,255,255,.5);--dash-placeholder-color: #0a84ff;--dash-resize-handle-color: rgba(255,255,255,.25)}.dashboard-wrapper{display:flex;flex:1;min-height:0;overflow:hidden;padding:16px;box-sizing:border-box;background:var(--dash-bg);color:var(--dash-fore-color);font-family:var(--dash-font-family)}.main-content{flex:1;display:flex;flex-direction:column;overflow:hidden;border-radius:40px;padding:20px;background:var(--dash-panel-bg);border:1px solid var(--dash-panel-border);position:relative}.popout-wrapper{display:flex;flex:1;flex-direction:column;min-height:0;overflow:hidden;padding:16px;box-sizing:border-box;background:var(--dash-bg);color:var(--dash-fore-color);font-family:var(--dash-font-family)}.popout-header{display:flex;align-items:center;margin-bottom:16px;padding:10px 18px;background:var(--dash-panel-bg);border-radius:20px;border:1px solid var(--dash-panel-border);flex-shrink:0}.popout-title{font-size:16px;font-weight:700;color:var(--dash-popout-title-color)}.popout-wrapper app-grid{flex:1;min-height:0;overflow:auto}.dashboard-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:20px;gap:12px;flex-shrink:0}.tabs-track{display:flex;align-items:center;gap:6px;flex:1;min-width:0;background:var(--dash-tabs-container-color);backdrop-filter:blur(10px);border-radius:25px;padding:6px;overflow:hidden}.tab{display:flex;align-items:center;gap:4px;padding:8px 14px 8px 18px;border-radius:20px;cursor:pointer;font-size:14px;font-weight:500;color:var(--dash-fore-color);white-space:nowrap;flex-shrink:0;transition:background .2s,color .2s}.tab.active{background:var(--dash-tab-active-color);color:var(--dash-tab-active-text)}.tab:hover:not(.active){color:var(--dash-tab-hover-text);background:var(--dash-tab-hover-bg)}.tab-name{white-space:nowrap}.tab-action{background:transparent;border:none;color:var(--dash-fore-color);padding:2px;font-size:11px;cursor:pointer;opacity:0;border-radius:50%;width:20px;height:20px;display:flex;align-items:center;justify-content:center;transition:all .2s;flex-shrink:0}.tab:hover .tab-action{opacity:1}.tab-popout:hover{color:var(--dash-accent-color);background:var(--dash-accent-tint)}.tab-close:hover{color:var(--dash-danger-color);background:var(--dash-danger-tint)}.btn-overflow{display:inline-flex;align-items:center;gap:5px;background:var(--dash-overflow-btn-bg);border:1px solid var(--dash-overflow-btn-border);border-radius:20px;padding:7px 13px;cursor:pointer;font-size:13px;font-weight:600;color:var(--dash-tab-active-text);white-space:nowrap;flex-shrink:0;transition:background .2s,border-color .2s,color .2s}.btn-overflow:hover{background:var(--dash-accent-tint);border-color:var(--dash-accent-color);color:var(--dash-accent-color)}.btn-add-page{background:transparent;border:none;color:var(--dash-fore-color);padding:8px 14px;cursor:pointer;border-radius:20px;flex-shrink:0;transition:all .2s}.btn-add-page:hover{color:var(--dash-accent-color);background:var(--dash-accent-tint)}.tab-switcher-overlay{position:absolute;inset:0;z-index:1000;background:var(--dash-overlay-bg);backdrop-filter:blur(4px);display:flex;align-items:flex-start;justify-content:center;padding-top:60px;animation:overlay-in .18s ease}@keyframes overlay-in{0%{opacity:0}to{opacity:1}}.tab-switcher-sheet{background:var(--dash-panel-bg);border:1px solid var(--dash-sheet-border);border-radius:24px;width:min(520px,calc(100% - 32px));max-height:calc(100% - 80px);display:flex;flex-direction:column;overflow:hidden;animation:sheet-in .22s cubic-bezier(.32,1.2,.5,1)}@keyframes sheet-in{0%{transform:translateY(-16px) scale(.97);opacity:0}to{transform:translateY(0) scale(1);opacity:1}}.tab-switcher-header{display:flex;align-items:center;justify-content:space-between;padding:16px 20px 12px;border-bottom:1px solid var(--dash-sheet-border);flex-shrink:0}.tab-switcher-title{font-size:15px;font-weight:700;color:var(--dash-tab-active-text)}.tab-switcher-close-btn{background:var(--dash-widget-btn-bg);border:none;color:var(--dash-fore-color);width:28px;height:28px;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;font-size:14px;transition:background .15s,color .15s}.tab-switcher-close-btn:hover{background:var(--dash-danger-tint);color:var(--dash-danger-color)}.tab-switcher-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:10px;padding:16px;overflow-y:auto;scrollbar-width:thin;scrollbar-color:var(--dash-scrollbar-color) transparent}.tab-card{display:flex;flex-direction:column;align-items:center;gap:8px;padding:16px 12px 12px;border-radius:16px;background:var(--dash-card-bg);border:1.5px solid transparent;cursor:pointer;transition:border-color .15s,background .15s,transform .12s;position:relative}.tab-card:hover{background:var(--dash-tab-hover-bg);transform:translateY(-2px)}.tab-card.active{border-color:var(--dash-accent-color);background:var(--dash-accent-tint)}.tab-card-icon{width:44px;height:44px;border-radius:12px;background:var(--dash-widget-btn-bg);display:flex;align-items:center;justify-content:center;font-size:20px;color:var(--dash-fore-color)}.tab-card.active .tab-card-icon{background:var(--dash-accent-tint-strong);color:var(--dash-accent-color)}.tab-card-name{font-size:13px;font-weight:500;color:var(--dash-tab-active-text);text-align:center;word-break:break-word;line-height:1.3}.tab-card-actions{display:flex;gap:4px;opacity:0;transition:opacity .15s}.tab-card:hover .tab-card-actions{opacity:1}.tab-card-btn{background:var(--dash-widget-btn-bg);border:none;width:26px;height:26px;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;font-size:12px;color:var(--dash-fore-color);transition:background .15s,color .15s}.tab-card-popout:hover{background:var(--dash-accent-tint-strong);color:var(--dash-accent-color)}.tab-card-remove:hover{background:var(--dash-danger-tint);color:var(--dash-danger-color)}.tab-switcher-footer{padding:12px 16px 16px;border-top:1px solid var(--dash-sheet-border);flex-shrink:0}.tab-switcher-add-btn{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;padding:11px 20px;border-radius:16px;background:var(--dash-accent-tint);border:1.5px dashed var(--dash-accent-tint-strong);color:var(--dash-accent-color);font-size:14px;font-weight:600;cursor:pointer;transition:background .15s,border-color .15s}.tab-switcher-add-btn:hover{background:var(--dash-accent-tint-strong);border-color:var(--dash-accent-color)}.btn-add-widget{display:flex;align-items:center;gap:6px;background:var(--dash-accent-color);border:none;color:var(--dash-add-widget-text);font-size:14px;font-weight:600;padding:10px 20px;border-radius:22px;cursor:pointer;white-space:nowrap;flex-shrink:0;transition:opacity .2s,transform .15s}.btn-add-widget:hover{opacity:.9;transform:translateY(-1px)}.btn-add-widget:active{transform:translateY(0)}.main-content .grid-container{flex:1;overflow:auto;border-radius:24px;min-height:0}app-grid{background:transparent;display:block;height:100%;width:100%}\n"] }]
1211
1410
  }], ctorParameters: function () { return [{ type: DashboardStateService }, { type: i0.ChangeDetectorRef }, { type: i0.NgZone }]; }, propDecorators: { initialLayout: [{
1212
1411
  type: Input
1213
1412
  }], theme: [{
@@ -1219,9 +1418,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImpo
1219
1418
  }], cellTemplate: [{
1220
1419
  type: ContentChild,
1221
1420
  args: [GridCellDirective, { read: TemplateRef }]
1222
- }], tabsContainerRef: [{
1421
+ }], tabsTrackRef: [{
1223
1422
  type: ViewChild,
1224
- args: ['tabsContainer']
1423
+ args: ['tabsTrack']
1424
+ }], onEscapeKey: [{
1425
+ type: HostListener,
1426
+ args: ['document:keydown.escape']
1225
1427
  }] } });
1226
1428
 
1227
1429
  class DashboardModule {