@contember/echo 0.0.28 → 0.0.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/style.css CHANGED
@@ -1 +1 @@
1
- *,*:before,*:after{box-sizing:border-box}.echo-root{position:absolute;top:0;left:0;z-index:var(--z-root);isolation:isolate;pointer-events:none;--z-root: 999999;--z-launcher: 2;--z-overlay: 1;--z-drawing-toolbar: 3;--z-drawing-tooltip: 3;--z-shape-actions: 3;--z-notification: 2;--z-welcome-message: 2;--z-widget-button: 2;--z-feedback-form: 4;--primary-color: #000;--primary-text-color: #fff;--error-color: #f44336;--success-color: var(--primary-color);--text-dark: #1a1a1a;--text-medium: #333;--text-light: #666;--text-lighter: #999;--border-color: rgba(0, 0, 0, .1);--border-color-light: rgba(0, 0, 0, .05);--border-color-medium: rgba(0, 0, 0, .08);--primary-color-lighter: color-mix(in srgb, var(--primary-color) 100%, white 40%);--primary-color-lightest: color-mix(in srgb, var(--primary-color) 7%, white 100%);--hover-color: color-mix(in srgb, var(--primary-color) 80%, #fff);--shadow-color-dark: rgba(0, 0, 0, .6);--shadow-color-light: rgba(255, 255, 255, .1);--shadow-color-medium: rgba(0, 0, 0, .2);--shadow-sm: 0 1px 3px;--shadow-md: 0 4px 10px;--shadow-lg: 0 10px 20px;--shadow-black-sm: var(--shadow-sm) rgba(0, 0, 0, .5);--shadow-black-md: var(--shadow-md) rgba(0, 0, 0, .5);--shadow-black-lg: var(--shadow-lg) rgba(0, 0, 0, .5);--shadow-black-lightened-sm: var(--shadow-sm) var(--shadow-color-medium);--shadow-black-lightened-md: var(--shadow-md) var(--shadow-color-medium);--shadow-black-lightened-lg: var(--shadow-lg) var(--shadow-color-medium);--shadow-primary-sm: var(--shadow-sm) color-mix(in srgb, var(--primary-color) 60%, transparent 80%);--shadow-primary-md: var(--shadow-md) color-mix(in srgb, var(--primary-color) 50%, transparent 80%);--shadow-primary-lg: var(--shadow-lg) color-mix(in srgb, var(--primary-color) 40%, transparent 80%);--shadow-primary-lighter-sm: var(--shadow-sm) color-mix(in srgb, var(--primary-color-lighter) 70%, transparent 80%);--shadow-primary-lighter-md: var(--shadow-md) color-mix(in srgb, var(--primary-color-lighter) 60%, transparent 80%);--shadow-primary-lighter-lg: var(--shadow-lg) color-mix(in srgb, var(--primary-color-lighter) 50%, transparent 80%);--shadow-primary-lightest-sm: var(--shadow-sm) color-mix(in srgb, var(--primary-color-lightest) 70%, transparent 80%);--shadow-primary-lightest-md: var(--shadow-md) color-mix(in srgb, var(--primary-color-lightest) 60%, transparent 80%);--shadow-primary-lightest-lg: var(--shadow-lg) color-mix(in srgb, var(--primary-color-lightest) 50%, transparent 80%);--shadow-combined-sm: var(--shadow-primary-sm), var(--shadow-black-lightened-sm);--shadow-combined-md: var(--shadow-primary-md), var(--shadow-black-lightened-md);--shadow-combined-lg: var(--shadow-primary-lg), var(--shadow-black-lightened-lg);--spacing-xs: 4px;--spacing-sm: 8px;--spacing-md: 12px;--spacing-lg: 16px;--spacing-xl: 20px;--spacing-2xl: 24px;--spacing-3xl: 32px;--radius-sm: 4px;--radius-md: 8px;--radius-lg: 12px;--radius-xl: 16px;--radius-full: 9999px;--font-xs: .8125rem;--font-sm: .875rem;--font-base: .9375rem;--font-md: 1rem;--font-lg: 1.125rem;--duration-fast: .1s;--duration-base: .2s;--duration-slow: .3s;--duration-slower: .4s;--duration-slowest: .6s;--ease-default: ease;--ease-in-out: ease-in-out;--ease-bounce: cubic-bezier(.34, 1.56, .64, 1);--ease-smooth: cubic-bezier(.4, 0, .2, 1);--ease-spring: cubic-bezier(.16, 1, .3, 1)}.echo-stored-feedback{position:absolute;display:flex;flex-direction:column;bottom:calc(100% + var(--spacing-lg));right:0;width:320px;background:#fff;border-radius:var(--radius-lg);box-shadow:var(--shadow-black-lightened-lg);animation:slideUpFade var(--duration-base) var(--ease-smooth);z-index:calc(var(--z-widget-button) + 1);transform-origin:bottom right;transition:all var(--duration-base) var(--ease-smooth)}.echo-stored-feedback-header{display:flex;align-items:center;justify-content:space-between;padding:var(--spacing-md) var(--spacing-lg)}.echo-stored-feedback-header h3{margin:0;font-size:var(--font-md);font-weight:600}.echo-stored-feedback-list{max-height:400px;overflow-y:auto;border-bottom-left-radius:var(--radius-lg);border-bottom-right-radius:var(--radius-lg)}.echo-stored-feedback-item{display:flex;align-items:center;justify-content:space-between;padding:var(--spacing-md) var(--spacing-lg);border-bottom:1px solid var(--border-color-light);transition:all var(--duration-base) var(--ease-smooth);background:#fff;position:relative}.echo-stored-feedback-item:hover{background:var(--primary-color-lightest)}.echo-stored-feedback-item-current{background:var(--primary-color-lightest);padding-left:calc(var(--spacing-lg) - 3px)}.echo-stored-feedback-item-current:before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--primary-color);border-top-left-radius:var(--radius-lg);border-bottom-left-radius:var(--radius-lg)}.echo-stored-feedback-item:last-child{border-bottom:none;border-bottom-left-radius:var(--radius-lg);border-bottom-right-radius:var(--radius-lg)}.echo-stored-feedback-item:last-child.echo-stored-feedback-item-current:before{border-bottom-left-radius:var(--radius-lg)}.echo-stored-feedback-content{flex:1;min-width:0;margin-right:var(--spacing-md)}.echo-stored-feedback-path{font-size:var(--font-sm);font-weight:500;color:var(--text-medium);margin-bottom:var(--spacing-xs);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.echo-stored-feedback-preview{font-size:var(--font-xs);color:var(--text-light);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.echo-stored-feedback-actions{display:flex;align-items:center;gap:var(--spacing-sm)}.echo-stored-feedback-link{color:var(--text-light)}.echo-stored-feedback-link:hover{color:var(--primary-color)}.echo-stored-feedback-delete{color:var(--text-light);font-size:var(--font-xs);padding:var(--spacing-xs) var(--spacing-md)}.echo-stored-feedback-delete:hover{color:var(--error-color);background:color-mix(in srgb,var(--error-color) 10%,transparent)}.echo-stored-feedback-empty{padding:var(--spacing-3xl) var(--spacing-lg);text-align:center;color:var(--text-light);font-size:var(--font-sm);border-bottom-left-radius:var(--radius-lg);border-bottom-right-radius:var(--radius-lg)}.echo-launcher{position:fixed;z-index:var(--z-launcher);bottom:var(--spacing-xl);right:var(--spacing-xl)}.echo-overlay{position:absolute;z-index:var(--z-overlay);top:0;left:0;right:0;bottom:0;border:3px solid var(--primary-color)}[data-hidden=true],[data-hidden=false]{transition:opacity var(--duration-slow) var(--ease-in-out),visibility var(--duration-slow) var(--ease-in-out)}[data-hidden=true]{opacity:0;visibility:hidden;pointer-events:none}[data-hidden=false]{opacity:1;visibility:visible;pointer-events:auto;user-select:none;-webkit-user-select:none}.echo-launcher-button{z-index:var(--z-widget-button);position:relative;display:flex;align-items:center;justify-content:center;cursor:pointer;background:radial-gradient(circle at 40% 40%,var(--primary-color) 0%,var(--primary-color-lighter) 65%,var(--primary-color-lighter) 100%);border:none;border-radius:var(--radius-full);width:48px;height:48px;box-shadow:var(--shadow-black-md);transition:all var(--duration-slow) var(--ease-default),left var(--duration-slower) var(--ease-smooth),opacity var(--duration-slow) var(--ease-in-out)}.echo-launcher-button:hover{box-shadow:var(--shadow-black-lg);transform:translateY(-2px)}.echo-launcher-button:active{transform:scale(.95)}.echo-launcher-button-count{position:absolute;top:calc(-1 * var(--spacing-xs));right:calc(-1 * var(--spacing-xs));background:var(--primary-color-lightest);color:var(--primary-color-lighter);border-radius:var(--radius-md);min-width:20px;height:20px;display:flex;align-items:center;justify-content:center;box-shadow:var(--shadow-black-sm);padding:0 var(--spacing-xs);font-weight:600;pointer-events:auto;cursor:pointer;transform-origin:center center;animation:popIn var(--duration-slow) var(--ease-bounce);transition:transform var(--duration-base) var(--ease-default)}.echo-launcher-button-count:hover{transform:scale(1.1)}.echo-feedback{position:fixed;bottom:var(--spacing-xl);right:var(--spacing-xl);width:min(calc(100vw - var(--spacing-2xl)),24rem);z-index:var(--z-feedback-form);box-shadow:var(--shadow-black-lightened-lg);display:flex;flex-direction:column;gap:var(--spacing-lg);background:#fff;border-radius:var(--radius-lg);will-change:transform;padding:var(--spacing-lg)}.echo-feedback[data-minimized=true]{transition:transform .4s var(--ease-default),box-shadow .4s var(--ease-default);transform:translate(calc(100% - 48px),calc(100% - 48px));box-shadow:0 8px 16px #0003}.echo-feedback[data-minimized=true]:hover{cursor:pointer;transform:translate(calc(100% - 48px),calc(100% - 48px)) rotate(-2deg) scale(1.1);box-shadow:0 12px 24px #00000040}.echo-feedback[data-minimized=false]{transition:transform .4s var(--ease-smooth),box-shadow .4s var(--ease-smooth);transform:translate(0)}.echo-feedback[style*=transition]{pointer-events:none}.echo-feedback-content{display:flex;flex-direction:column;gap:var(--spacing-lg)}.echo-feedback-header{display:flex;justify-content:space-between;align-items:center}.echo-feedback-title{font-size:var(--font-lg);font-weight:600;color:var(--text-dark);margin:0}.echo-feedback-header-actions{display:flex;gap:var(--spacing-xs);margin:calc(-1 * var(--spacing-sm)) calc(-1 * var(--spacing-sm)) calc(-1 * var(--spacing-sm)) 0}.echo-feedback-form-textarea{width:100%;min-height:120px;border-radius:var(--radius-md);border:1px solid var(--border-color);padding:var(--spacing-md);font-size:var(--font-base);resize:vertical;background:#fffc;font-family:inherit}.echo-feedback-form-textarea:focus{outline:none;border-color:var(--primary-color);background:#fff;box-shadow:0 0 0 3px color-mix(in srgb,var(--primary-color) 15%,transparent)}.echo-feedback-form-textarea::placeholder{color:var(--text-lighter)}[data-hide-when-drawing=true]{opacity:1;visibility:visible;transition:opacity .3s ease-in-out,visibility .3s ease-in-out}[data-drawing=true] [data-hide-when-drawing=true]{opacity:0;visibility:hidden;pointer-events:none;user-select:none;-webkit-user-select:none}.echo-drawing-layer,.echo-drawing-layer-container{position:absolute;top:0;left:0;right:0;bottom:0;pointer-events:none;user-select:none;-webkit-user-select:none}.echo-drawing-layer-container svg{pointer-events:auto}.echo-drawing-toolbar{position:fixed;top:var(--spacing-xl);left:var(--spacing-xl);display:flex;flex-direction:column;gap:var(--spacing-sm);z-index:var(--z-drawing-toolbar);opacity:1;transition:opacity var(--duration-base) var(--ease-default)}.echo-drawing-toolbar-button{width:50px;height:50px;border-radius:var(--radius-full);border:2px solid #ddd;background:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;padding:0;transition:all var(--duration-base) var(--ease-default);box-shadow:var(--shadow-black-sm);position:relative}.echo-drawing-toolbar-icon{width:25px;height:25px;color:var(--primary-color);transition:color var(--duration-base) var(--ease-default)}.echo-drawing-toolbar-button:hover{transform:scale(1.05);border-color:var(--hover-color)}.echo-drawing-toolbar-button[data-selected=true]{background:var(--primary-color-lightest);border-color:var(--primary-color)}.echo-color-selector{position:relative}.echo-color-selector:hover .echo-drawing-toolbar-button{border-top-right-radius:0;border-bottom-right-radius:0;transform:scale(1.05);border-right-color:transparent;background:rgba(var(--primary-color),.9);border-color:var(--hover-color)}.echo-color-swatch-wrapper{position:absolute;left:calc(100% - 2px);top:50%;transform:translateY(-50%);height:52.5px;padding-right:var(--spacing-sm);display:none}.echo-color-selector:hover .echo-color-swatch-wrapper{display:block}.echo-color-swatch{height:100%;background:#fff;border-radius:var(--radius-md);border-top-left-radius:0;border-bottom-left-radius:0;padding:var(--spacing-sm);padding-left:var(--spacing-md);box-shadow:var(--shadow-black-sm);display:flex;align-items:center;gap:var(--spacing-sm);border:2px solid #ddd;border-left:none}.echo-color-selector:hover .echo-color-swatch{border-color:var(--hover-color)}.echo-color-swatch-button{width:24px;height:24px;border-radius:var(--radius-full);border:2px solid transparent;cursor:pointer;padding:0;transition:transform var(--duration-base) var(--ease-default)}.echo-color-swatch-button:hover{transform:scale(1.1)}.echo-color-swatch-button[data-selected=true]{border-color:var(--primary-color)}.echo-drawing-tooltip{display:flex;text-wrap:nowrap;position:fixed;background:#fff;padding:var(--spacing-sm) var(--spacing-lg);border-radius:var(--radius-lg);box-shadow:var(--shadow-combined-sm);font-size:var(--font-sm);color:var(--primary-color);z-index:var(--z-drawing-tooltip);pointer-events:none;animation:slideDownFade var(--duration-slow) var(--ease-default);border:1px solid var(--primary-color);background:var(--primary-color-lightest)}.echo-shape-actions{position:fixed;z-index:var(--z-shape-actions);display:flex;gap:var(--spacing-xs);background:#fff;border-radius:var(--radius-lg);box-shadow:var(--shadow-combined-md);transform:translate(-50%,-100%) translateY(calc(-1 * var(--spacing-sm)));animation:popInSlideDown var(--duration-fast) var(--ease-default);cursor:default;pointer-events:auto;padding:var(--spacing-xs);border:1px solid var(--primary-color)}.echo-shape-actions-divider{width:1px;margin:var(--spacing-sm) 0;background:var(--border-color);pointer-events:none}.echo-shape-actions[hidden]{display:none}.echo-notification{position:absolute;z-index:var(--z-notification);bottom:70px;right:0;width:300px;padding:var(--spacing-2xl);border-radius:var(--radius-lg);font-size:var(--font-md);font-weight:500;box-shadow:var(--shadow-combined-md);background:#fff;border:1px solid var(--primary-color);transform-origin:bottom right;display:flex;flex-direction:column;align-items:center;gap:var(--spacing-xl);opacity:1;pointer-events:auto;transition:all var(--duration-base) var(--ease-smooth)}.echo-notification:not([data-empty=true]){animation:popInSlideUp var(--duration-slower) var(--ease-spring)}.echo-notification[data-empty=true]{opacity:0;pointer-events:none;transform:translateY(var(--spacing-sm)) scale(.95);transition:none}.echo-notification-hide{position:absolute;top:var(--spacing-lg);right:var(--spacing-lg);width:24px;height:24px;padding:var(--spacing-xs);border:none;background:transparent;color:var(--text-light);opacity:.7;cursor:pointer;border-radius:var(--radius-full);display:flex;align-items:center;justify-content:center;transition:all var(--duration-base) var(--ease-bounce);flex-shrink:0}.echo-notification-hide:hover{opacity:1;background:var(--primary-color-lightest);transform:scale(1.1);color:var(--primary-color)}.echo-notification-icon{display:flex;align-items:center;justify-content:center;flex-shrink:0;transform:scale(1.5);background:var(--primary-color-lightest);padding:var(--spacing-md);border-radius:var(--radius-full);margin-top:var(--spacing-md);transition:all var(--duration-base) var(--ease-bounce)}.echo-notification[data-type=success]{border-color:var(--success-color)}.echo-notification[data-type=success] .echo-notification-icon{color:var(--success-color)}.echo-notification[data-type=error]{border-color:var(--error-color)}.echo-notification[data-type=error] .echo-notification-icon{color:var(--error-color);background:color-mix(in srgb,var(--error-color) 10%,white)}.echo-notification-content{display:flex;flex-direction:column;align-items:center;gap:12px;text-align:center;padding:0 12px}.echo-notification-title{font-size:1rem;font-weight:600;color:#1a1a1a}.echo-notification-message{font-size:.875rem;font-weight:400;color:#666;line-height:1.4;max-width:100%}@media (max-width: 768px){.echo-notification{right:0;width:calc(100vw - 40px);height:auto;min-height:180px;-webkit-backdrop-filter:none;backdrop-filter:none;font-size:.9375rem;padding:20px;gap:16px;bottom:calc(100% + 20px)}.echo-notification-icon{transform:scale(1.3);padding:10px;margin-top:8px}.echo-notification-title{font-size:.9375rem}.echo-notification-message{font-size:.8125rem}}.echo-welcome-message{display:flex;align-items:center;gap:var(--spacing-xs);position:fixed;z-index:var(--z-welcome-message);background:var(--primary-color-lightest);border:1px solid var(--primary-color);color:var(--primary-color);padding:var(--spacing-md) var(--spacing-lg);border-radius:var(--radius-lg);font-size:var(--font-sm);font-weight:500;box-shadow:var(--shadow-combined-md);opacity:1;transform:translateY(0) scale(1);transition:all var(--duration-slow) var(--ease-smooth);animation:bounceIn var(--duration-slowest) var(--ease-bounce);user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;cursor:pointer;text-align:left}.echo-welcome-message:hover{transform:translateY(-2px) scale(1.02);background:var(--primary-color-lightest);box-shadow:var(--shadow-combined-lg)}.echo-welcome-message:active{transform:translateY(0) scale(.98)}.echo-welcome-message-close{width:20px;height:20px;padding:2px;margin-left:var(--spacing-xs);border:none;background:transparent;opacity:.7;cursor:pointer;border-radius:var(--radius-full);display:flex;align-items:center;justify-content:center;transition:all var(--duration-base) var(--ease-default)}.echo-welcome-message-close:hover{opacity:1;background:var(--shadow-color-light);transform:scale(1.1)}.echo-welcome-message-close:active{transform:scale(.95)}.echo-welcome-message:after{content:"";position:absolute;bottom:-4px;right:17px;width:16px;height:16px;background:inherit;transform:rotate(45deg);border-radius:var(--radius-xs);border:1px solid var(--primary-color);z-index:-2}.echo-welcome-message:before{content:"";position:absolute;top:0;left:0;width:100%;height:100%;background:var(--primary-color-lightest);z-index:-1;border-radius:var(--radius-lg)}.echo-welcome-message-pulsar{content:"";display:inline-block;width:6px;height:6px;background:var(--primary-color);border-radius:50%;margin-right:8px;animation:pulse 1.5s var(--ease-in-out) infinite}.echo-button{display:inline-flex;align-items:center;justify-content:center;border:none;border-radius:var(--radius-md);font-weight:500;cursor:pointer;transition:all var(--duration-base) var(--ease-default);line-height:1}.echo-button:focus-visible{outline:2px solid var(--primary-color);outline-offset:2px}.echo-button-primary{background:var(--primary-color);color:#fff}.echo-button-primary:hover{background:var(--hover-color);transform:translateY(-1px)}.echo-button-primary:active{transform:translateY(0)}.echo-button-secondary{background:transparent;color:var(--text-light)}.echo-button-secondary:hover{background-color:var(--primary-color-lightest);color:var(--primary-color)}.echo-button-xs{padding:var(--spacing-xs);font-size:var(--font-xs)}.echo-button-sm{padding:var(--spacing-xs);font-size:var(--font-sm)}.echo-button-md{padding:var(--spacing-md) var(--spacing-2xl);font-size:var(--font-base)}.echo-button-lg{padding:var(--spacing-md) var(--spacing-3xl);font-size:var(--font-md)}@keyframes slideUpFade{0%{opacity:0;transform:translateY(var(--spacing-sm))}to{opacity:1;transform:translateY(0)}}@keyframes slideDownFade{0%{opacity:0;transform:translateY(calc(-1 * var(--spacing-sm)))}to{opacity:1;transform:translateY(0)}}@keyframes popIn{0%{transform:scale(0);opacity:0}to{transform:scale(1);opacity:1}}@keyframes popInSlideUp{0%{opacity:0;transform:translateY(var(--spacing-sm)) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes popInSlideDown{0%{opacity:0;transform:translate(-50%,-100%) translateY(calc(-1 * var(--spacing-xs))) scale(.95)}to{opacity:1;transform:translate(-50%,-100%) translateY(calc(-1 * var(--spacing-sm))) scale(1)}}@keyframes bounceIn{0%{opacity:0;transform:translateY(var(--spacing-xl)) scale(.9)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes pulse{0%{transform:scale(1);opacity:1}50%{transform:scale(1.5);opacity:.5}to{transform:scale(1);opacity:1}}
1
+ *,*:before,*:after{box-sizing:border-box}.echo-root{position:absolute;top:0;left:0;z-index:var(--z-root);isolation:isolate;pointer-events:none;--z-root: 999999;--z-launcher: 2;--z-overlay: 1;--z-drawing-toolbar: 3;--z-drawing-tooltip: 3;--z-shape-actions: 3;--z-notification: 2;--z-welcome-message: 2;--z-widget-button: 2;--z-feedback-form: 4;--primary-color: #000;--primary-text-color: #fff;--error-color: #f44336;--success-color: var(--primary-color);--text-dark: #1a1a1a;--text-medium: #333;--text-light: #666;--text-lighter: #999;--border-color: rgba(0, 0, 0, .1);--border-color-light: rgba(0, 0, 0, .05);--border-color-medium: rgba(0, 0, 0, .08);--primary-color-lighter: color-mix(in srgb, var(--primary-color) 100%, white 40%);--primary-color-lightest: color-mix(in srgb, var(--primary-color) 7%, white 100%);--hover-color: color-mix(in srgb, var(--primary-color) 80%, #fff);--shadow-color-dark: rgba(0, 0, 0, .6);--shadow-color-light: rgba(255, 255, 255, .1);--shadow-color-medium: rgba(0, 0, 0, .2);--shadow-sm: 0 1px 3px;--shadow-md: 0 4px 10px;--shadow-lg: 0 10px 20px;--shadow-black-sm: var(--shadow-sm) rgba(0, 0, 0, .5);--shadow-black-md: var(--shadow-md) rgba(0, 0, 0, .5);--shadow-black-lg: var(--shadow-lg) rgba(0, 0, 0, .5);--shadow-black-lightened-sm: var(--shadow-sm) var(--shadow-color-medium);--shadow-black-lightened-md: var(--shadow-md) var(--shadow-color-medium);--shadow-black-lightened-lg: var(--shadow-lg) var(--shadow-color-medium);--shadow-primary-sm: var(--shadow-sm) color-mix(in srgb, var(--primary-color) 60%, transparent 80%);--shadow-primary-md: var(--shadow-md) color-mix(in srgb, var(--primary-color) 50%, transparent 80%);--shadow-primary-lg: var(--shadow-lg) color-mix(in srgb, var(--primary-color) 40%, transparent 80%);--shadow-primary-lighter-sm: var(--shadow-sm) color-mix(in srgb, var(--primary-color-lighter) 70%, transparent 80%);--shadow-primary-lighter-md: var(--shadow-md) color-mix(in srgb, var(--primary-color-lighter) 60%, transparent 80%);--shadow-primary-lighter-lg: var(--shadow-lg) color-mix(in srgb, var(--primary-color-lighter) 50%, transparent 80%);--shadow-primary-lightest-sm: var(--shadow-sm) color-mix(in srgb, var(--primary-color-lightest) 70%, transparent 80%);--shadow-primary-lightest-md: var(--shadow-md) color-mix(in srgb, var(--primary-color-lightest) 60%, transparent 80%);--shadow-primary-lightest-lg: var(--shadow-lg) color-mix(in srgb, var(--primary-color-lightest) 50%, transparent 80%);--shadow-combined-sm: var(--shadow-primary-sm), var(--shadow-black-lightened-sm);--shadow-combined-md: var(--shadow-primary-md), var(--shadow-black-lightened-md);--shadow-combined-lg: var(--shadow-primary-lg), var(--shadow-black-lightened-lg);--spacing-xs: 4px;--spacing-sm: 8px;--spacing-md: 12px;--spacing-lg: 16px;--spacing-xl: 20px;--spacing-2xl: 24px;--spacing-3xl: 32px;--radius-sm: 4px;--radius-md: 8px;--radius-lg: 12px;--radius-xl: 16px;--radius-full: 9999px;--font-xs: .8125rem;--font-sm: .875rem;--font-base: .9375rem;--font-md: 1rem;--font-lg: 1.125rem;--duration-fast: .1s;--duration-base: .2s;--duration-slow: .3s;--duration-slower: .4s;--duration-slowest: .6s;--ease-default: ease;--ease-in-out: ease-in-out;--ease-bounce: cubic-bezier(.34, 1.56, .64, 1);--ease-smooth: cubic-bezier(.4, 0, .2, 1);--ease-spring: cubic-bezier(.16, 1, .3, 1)}.echo-stored-feedback{position:absolute;display:flex;flex-direction:column;bottom:calc(100% + var(--spacing-lg));right:0;width:320px;background:#fff;border-radius:var(--radius-lg);box-shadow:var(--shadow-black-lightened-lg);animation:slideUpFade var(--duration-base) var(--ease-smooth);z-index:calc(var(--z-widget-button) + 1);transform-origin:bottom right;transition:all var(--duration-base) var(--ease-smooth)}.echo-stored-feedback-header{display:flex;align-items:center;justify-content:space-between;padding:var(--spacing-md) var(--spacing-lg)}.echo-stored-feedback-header h3{margin:0;font-size:var(--font-md);font-weight:600}.echo-stored-feedback-list{max-height:400px;overflow-y:auto;border-bottom-left-radius:var(--radius-lg);border-bottom-right-radius:var(--radius-lg)}.echo-stored-feedback-item{display:flex;align-items:center;justify-content:space-between;padding:var(--spacing-md) var(--spacing-lg);border-bottom:1px solid var(--border-color-light);transition:all var(--duration-base) var(--ease-smooth);background:#fff;position:relative}.echo-stored-feedback-item:hover{background:var(--primary-color-lightest)}.echo-stored-feedback-item-current{background:var(--primary-color-lightest);padding-left:calc(var(--spacing-lg) - 3px)}.echo-stored-feedback-item-current:before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--primary-color);border-top-left-radius:var(--radius-lg);border-bottom-left-radius:var(--radius-lg)}.echo-stored-feedback-item:last-child{border-bottom:none;border-bottom-left-radius:var(--radius-lg);border-bottom-right-radius:var(--radius-lg)}.echo-stored-feedback-item:last-child.echo-stored-feedback-item-current:before{border-bottom-left-radius:var(--radius-lg)}.echo-stored-feedback-content{flex:1;min-width:0;margin-right:var(--spacing-md)}.echo-stored-feedback-path{font-size:var(--font-sm);font-weight:500;color:var(--text-medium);margin-bottom:var(--spacing-xs);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.echo-stored-feedback-preview{font-size:var(--font-xs);color:var(--text-light);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.echo-stored-feedback-actions{display:flex;align-items:center;gap:var(--spacing-sm)}.echo-stored-feedback-link{color:var(--text-light)}.echo-stored-feedback-link:hover{color:var(--primary-color)}.echo-stored-feedback-delete{color:var(--text-light);font-size:var(--font-xs);padding:var(--spacing-xs) var(--spacing-md)}.echo-stored-feedback-delete:hover{color:var(--error-color);background:color-mix(in srgb,var(--error-color) 10%,transparent)}.echo-stored-feedback-empty{padding:var(--spacing-3xl) var(--spacing-lg);text-align:center;color:var(--text-light);font-size:var(--font-sm);border-bottom-left-radius:var(--radius-lg);border-bottom-right-radius:var(--radius-lg)}.echo-launcher{position:fixed;z-index:var(--z-launcher);bottom:var(--spacing-xl);right:var(--spacing-xl)}.echo-overlay{position:absolute;top:0;left:0;margin:0;padding:0;max-width:none;max-height:none;border:3px solid var(--primary-color);background:transparent}.echo-overlay::backdrop{background:transparent}[data-hidden=true],[data-hidden=false]{transition:opacity var(--duration-slow) var(--ease-in-out),visibility var(--duration-slow) var(--ease-in-out)}[data-hidden=true]{opacity:0;visibility:hidden;pointer-events:none}[data-hidden=false]{opacity:1;visibility:visible;pointer-events:auto;user-select:none;-webkit-user-select:none}.echo-launcher-button{z-index:var(--z-widget-button);position:relative;display:flex;align-items:center;justify-content:center;cursor:pointer;background:radial-gradient(circle at 40% 40%,var(--primary-color) 0%,var(--primary-color-lighter) 65%,var(--primary-color-lighter) 100%);border:none;border-radius:var(--radius-full);width:48px;height:48px;box-shadow:var(--shadow-black-md);transition:all var(--duration-slow) var(--ease-default),left var(--duration-slower) var(--ease-smooth),opacity var(--duration-slow) var(--ease-in-out)}.echo-launcher-button:hover{box-shadow:var(--shadow-black-lg);transform:translateY(-2px)}.echo-launcher-button:active{transform:scale(.95)}.echo-launcher-button-count{position:absolute;top:calc(-1 * var(--spacing-xs));right:calc(-1 * var(--spacing-xs));background:var(--primary-color-lightest);color:var(--primary-color-lighter);border-radius:var(--radius-md);min-width:20px;height:20px;display:flex;align-items:center;justify-content:center;box-shadow:var(--shadow-black-sm);padding:0 var(--spacing-xs);font-weight:600;pointer-events:auto;cursor:pointer;transform-origin:center center;animation:popIn var(--duration-slow) var(--ease-bounce);transition:transform var(--duration-base) var(--ease-default)}.echo-launcher-button-count:hover{transform:scale(1.1)}.echo-feedback{position:fixed;bottom:var(--spacing-xl);right:var(--spacing-xl);width:min(calc(100vw - var(--spacing-2xl)),24rem);z-index:var(--z-feedback-form);box-shadow:var(--shadow-black-lightened-lg);display:flex;flex-direction:column;gap:var(--spacing-lg);background:#fff;border-radius:var(--radius-lg);will-change:transform;padding:var(--spacing-lg)}.echo-feedback[data-minimized=true]{transition:transform .4s var(--ease-default),box-shadow .4s var(--ease-default);transform:translate(calc(100% - 48px),calc(100% - 48px));box-shadow:0 8px 16px #0003}.echo-feedback[data-minimized=true]:hover{cursor:pointer;transform:translate(calc(100% - 48px),calc(100% - 48px)) rotate(-2deg) scale(1.1);box-shadow:0 12px 24px #00000040}.echo-feedback[data-minimized=false]{transition:transform .4s var(--ease-smooth),box-shadow .4s var(--ease-smooth);transform:translate(0)}.echo-feedback[style*=transition]{pointer-events:none}.echo-feedback-content{display:flex;flex-direction:column;gap:var(--spacing-lg)}.echo-feedback-header{display:flex;justify-content:space-between;align-items:center}.echo-feedback-title{font-size:var(--font-lg);font-weight:600;color:var(--text-dark);margin:0}.echo-feedback-header-actions{display:flex;gap:var(--spacing-xs);margin:calc(-1 * var(--spacing-sm)) calc(-1 * var(--spacing-sm)) calc(-1 * var(--spacing-sm)) 0}.echo-feedback-form-textarea{width:100%;padding:.5rem;border:1px solid var(--border-color);border-radius:var(--radius-md);background-color:#fff;color:var(--text-medium);font-size:var(--font-sm);transition:all var(--duration-base) var(--ease-default);min-height:120px;resize:vertical;font-family:inherit}.echo-feedback-form-textarea:focus{outline:none;border-color:var(--primary-color);box-shadow:0 0 0 3px color-mix(in srgb,var(--primary-color) 15%,transparent)}.echo-feedback-form-textarea::placeholder{color:var(--text-lighter)}[data-hide-when-drawing=true]{opacity:1;visibility:visible;transition:opacity .3s ease-in-out,visibility .3s ease-in-out}[data-drawing=true] [data-hide-when-drawing=true]{opacity:0;visibility:hidden;pointer-events:none;user-select:none;-webkit-user-select:none}.echo-drawing-layer,.echo-drawing-layer-container{position:absolute;top:0;left:0;right:0;bottom:0;pointer-events:none;user-select:none;-webkit-user-select:none}.echo-drawing-layer-container svg{pointer-events:auto}.echo-drawing-toolbar{position:fixed;top:var(--spacing-xl);left:var(--spacing-xl);display:flex;flex-direction:column;gap:var(--spacing-sm);z-index:var(--z-drawing-toolbar);opacity:1;transition:opacity var(--duration-base) var(--ease-default)}.echo-drawing-toolbar-button{width:50px;height:50px;border-radius:var(--radius-full);border:2px solid #ddd;background:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;padding:0;transition:all var(--duration-base) var(--ease-default);box-shadow:var(--shadow-black-sm);position:relative}.echo-drawing-toolbar-icon{width:25px;height:25px;color:var(--primary-color);transition:color var(--duration-base) var(--ease-default)}.echo-drawing-toolbar-button:hover{transform:scale(1.05);border-color:var(--hover-color)}.echo-drawing-toolbar-button[data-selected=true]{background:var(--primary-color-lightest);border-color:var(--primary-color)}.echo-color-selector{position:relative}.echo-color-selector:hover .echo-drawing-toolbar-button{border-top-right-radius:0;border-bottom-right-radius:0;transform:scale(1.05);border-right-color:transparent;background:rgba(var(--primary-color),.9);border-color:var(--hover-color)}.echo-color-swatch-wrapper{position:absolute;left:calc(100% - 2px);top:50%;transform:translateY(-50%);height:52.5px;padding-right:var(--spacing-sm);display:none}.echo-color-selector:hover .echo-color-swatch-wrapper{display:block}.echo-color-swatch{height:100%;background:#fff;border-radius:var(--radius-md);border-top-left-radius:0;border-bottom-left-radius:0;padding:var(--spacing-sm);padding-left:var(--spacing-md);box-shadow:var(--shadow-black-sm);display:flex;align-items:center;gap:var(--spacing-sm);border:2px solid #ddd;border-left:none}.echo-color-selector:hover .echo-color-swatch{border-color:var(--hover-color)}.echo-color-swatch-button{width:24px;height:24px;border-radius:var(--radius-full);border:2px solid transparent;cursor:pointer;padding:0;transition:transform var(--duration-base) var(--ease-default)}.echo-color-swatch-button:hover{transform:scale(1.1)}.echo-color-swatch-button[data-selected=true]{border-color:var(--primary-color)}.echo-drawing-tooltip{display:flex;text-wrap:nowrap;position:fixed;background:#fff;padding:var(--spacing-sm) var(--spacing-lg);border-radius:var(--radius-lg);box-shadow:var(--shadow-combined-sm);font-size:var(--font-sm);color:var(--primary-color);z-index:var(--z-drawing-tooltip);pointer-events:none;animation:slideDownFade var(--duration-slow) var(--ease-default);border:1px solid var(--primary-color);background:var(--primary-color-lightest)}.echo-shape-actions{position:fixed;z-index:var(--z-shape-actions);display:flex;gap:var(--spacing-xs);background:#fff;border-radius:var(--radius-lg);box-shadow:var(--shadow-combined-md);transform:translate(-50%,-100%) translateY(calc(-1 * var(--spacing-sm)));animation:popInSlideDown var(--duration-fast) var(--ease-default);cursor:default;pointer-events:auto;padding:var(--spacing-xs);border:1px solid var(--primary-color)}.echo-shape-actions-divider{width:1px;margin:var(--spacing-sm) 0;background:var(--border-color);pointer-events:none}.echo-shape-actions[hidden]{display:none}.echo-notification{position:absolute;z-index:var(--z-notification);bottom:70px;right:0;width:300px;padding:var(--spacing-2xl);border-radius:var(--radius-lg);font-size:var(--font-md);font-weight:500;box-shadow:var(--shadow-combined-md);background:#fff;border:1px solid var(--primary-color);transform-origin:bottom right;display:flex;flex-direction:column;align-items:center;gap:var(--spacing-xl);opacity:1;pointer-events:auto;transition:all var(--duration-base) var(--ease-smooth)}.echo-notification:not([data-empty=true]){animation:popInSlideUp var(--duration-slower) var(--ease-spring)}.echo-notification[data-empty=true]{opacity:0;pointer-events:none;transform:translateY(var(--spacing-sm)) scale(.95);transition:none}.echo-notification-hide{position:absolute;top:var(--spacing-lg);right:var(--spacing-lg);width:24px;height:24px;padding:var(--spacing-xs);border:none;background:transparent;color:var(--text-light);opacity:.7;cursor:pointer;border-radius:var(--radius-full);display:flex;align-items:center;justify-content:center;transition:all var(--duration-base) var(--ease-bounce);flex-shrink:0}.echo-notification-hide:hover{opacity:1;background:var(--primary-color-lightest);transform:scale(1.1);color:var(--primary-color)}.echo-notification-icon{display:flex;align-items:center;justify-content:center;flex-shrink:0;transform:scale(1.5);background:var(--primary-color-lightest);padding:var(--spacing-md);border-radius:var(--radius-full);margin-top:var(--spacing-md);transition:all var(--duration-base) var(--ease-bounce)}.echo-notification[data-type=success]{border-color:var(--success-color)}.echo-notification[data-type=success] .echo-notification-icon{color:var(--success-color)}.echo-notification[data-type=error]{border-color:var(--error-color)}.echo-notification[data-type=error] .echo-notification-icon{color:var(--error-color);background:color-mix(in srgb,var(--error-color) 10%,white)}.echo-notification-content{display:flex;flex-direction:column;align-items:center;gap:12px;text-align:center;padding:0 12px}.echo-notification-title{font-size:1rem;font-weight:600;color:#1a1a1a}.echo-notification-message{font-size:.875rem;font-weight:400;color:#666;line-height:1.4;max-width:100%}@media (max-width: 768px){.echo-notification{right:0;width:calc(100vw - 40px);height:auto;min-height:180px;-webkit-backdrop-filter:none;backdrop-filter:none;font-size:.9375rem;padding:20px;gap:16px;bottom:calc(100% + 20px)}.echo-notification-icon{transform:scale(1.3);padding:10px;margin-top:8px}.echo-notification-title{font-size:.9375rem}.echo-notification-message{font-size:.8125rem}}.echo-welcome-message{display:flex;align-items:center;gap:var(--spacing-xs);position:fixed;z-index:var(--z-welcome-message);background:var(--primary-color-lightest);border:1px solid var(--primary-color);color:var(--primary-color);padding:var(--spacing-md) var(--spacing-lg);border-radius:var(--radius-lg);font-size:var(--font-sm);font-weight:500;box-shadow:var(--shadow-combined-md);opacity:1;transform:translateY(0) scale(1);transition:all var(--duration-slow) var(--ease-smooth);animation:bounceIn var(--duration-slowest) var(--ease-bounce);user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;cursor:pointer;text-align:left}.echo-welcome-message:hover{transform:translateY(-2px) scale(1.02);background:var(--primary-color-lightest);box-shadow:var(--shadow-combined-lg)}.echo-welcome-message:active{transform:translateY(0) scale(.98)}.echo-welcome-message-close{width:20px;height:20px;padding:2px;margin-left:var(--spacing-xs);border:none;background:transparent;opacity:.7;cursor:pointer;border-radius:var(--radius-full);display:flex;align-items:center;justify-content:center;transition:all var(--duration-base) var(--ease-default)}.echo-welcome-message-close:hover{opacity:1;background:var(--shadow-color-light);transform:scale(1.1)}.echo-welcome-message-close:active{transform:scale(.95)}.echo-welcome-message:after{content:"";position:absolute;bottom:-4px;right:17px;width:16px;height:16px;background:inherit;transform:rotate(45deg);border-radius:var(--radius-xs);border:1px solid var(--primary-color);z-index:-2}.echo-welcome-message:before{content:"";position:absolute;top:0;left:0;width:100%;height:100%;background:var(--primary-color-lightest);z-index:-1;border-radius:var(--radius-lg)}.echo-welcome-message-pulsar{content:"";display:inline-block;width:6px;height:6px;background:var(--primary-color);border-radius:50%;margin-right:8px;animation:pulse 1.5s var(--ease-in-out) infinite}.echo-button{display:inline-flex;align-items:center;justify-content:center;border:none;border-radius:var(--radius-md);font-weight:500;cursor:pointer;transition:all var(--duration-base) var(--ease-default);line-height:1}.echo-button:focus-visible{outline:2px solid var(--primary-color);outline-offset:2px}.echo-button-primary{background:var(--primary-color);color:#fff}.echo-button-primary:hover{background:var(--hover-color);transform:translateY(-1px)}.echo-button-primary:active{transform:translateY(0)}.echo-button-secondary{background:transparent;color:var(--text-light)}.echo-button-secondary:hover{background-color:var(--primary-color-lightest);color:var(--primary-color)}.echo-button-xs{padding:var(--spacing-xs);font-size:var(--font-xs)}.echo-button-sm{padding:var(--spacing-xs);font-size:var(--font-sm)}.echo-button-md{padding:var(--spacing-md) var(--spacing-2xl);font-size:var(--font-base)}.echo-button-lg{padding:var(--spacing-md) var(--spacing-3xl);font-size:var(--font-md)}@keyframes slideUpFade{0%{opacity:0;transform:translateY(var(--spacing-sm))}to{opacity:1;transform:translateY(0)}}@keyframes slideDownFade{0%{opacity:0;transform:translateY(calc(-1 * var(--spacing-sm)))}to{opacity:1;transform:translateY(0)}}@keyframes popIn{0%{transform:scale(0);opacity:0}to{transform:scale(1);opacity:1}}@keyframes popInSlideUp{0%{opacity:0;transform:translateY(var(--spacing-sm)) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes popInSlideDown{0%{opacity:0;transform:translate(-50%,-100%) translateY(calc(-1 * var(--spacing-xs))) scale(.95)}to{opacity:1;transform:translate(-50%,-100%) translateY(calc(-1 * var(--spacing-sm))) scale(1)}}@keyframes bounceIn{0%{opacity:0;transform:translateY(var(--spacing-xl)) scale(.9)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes pulse{0%{transform:scale(1);opacity:1}50%{transform:scale(1.5);opacity:.5}to{transform:scale(1);opacity:1}}.echo-inputs{display:flex;flex-direction:column;gap:1rem;margin-bottom:1rem}.echo-input{display:flex;flex-direction:column;gap:.5rem}.echo-input-label{font-size:.875rem;font-weight:500;color:var(--text-color)}.echo-input-required{color:#dc2626;margin-left:.25rem}.echo-input-field{width:100%;padding:.5rem;border:1px solid var(--border-color);border-radius:var(--radius-md);background-color:#fff;color:var(--text-medium);font-size:var(--font-sm);transition:all var(--duration-base) var(--ease-default)}.echo-input-field:focus{outline:none;border-color:var(--primary-color);box-shadow:0 0 0 3px color-mix(in srgb,var(--primary-color) 15%,transparent)}.echo-input-field::placeholder{color:var(--text-lighter)}select.echo-input-field{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23666' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right .5rem center;padding-right:2.5rem;cursor:pointer}.echo-input-options{display:flex;flex-direction:column;gap:var(--spacing-sm);border:none;margin:0;padding:0}.echo-input-option{display:flex;align-items:center;gap:.5rem;cursor:pointer;padding:var(--spacing-xs);border-radius:var(--radius-sm);transition:all var(--duration-base) var(--ease-default)}.echo-input-option:hover{background:var(--primary-color-lightest)}.echo-input-option input[type=radio],.echo-input-option input[type=checkbox]{-webkit-appearance:none;-moz-appearance:none;appearance:none;margin:0;width:18px;height:18px;border:1px solid var(--border-color);background-color:#fff;display:grid;place-content:center;cursor:pointer;transition:all var(--duration-base) var(--ease-default)}.echo-input-option input[type=radio]{border-radius:50%}.echo-input-option input[type=radio]:before{content:"";width:10px;height:10px;border-radius:50%;transform:scale(0);transition:transform var(--duration-base) var(--ease-default);background-color:var(--primary-color)}.echo-input-option input[type=radio]:checked:before{transform:scale(1)}.echo-input-option input[type=checkbox]{border-radius:var(--radius-sm)}.echo-input-option input[type=checkbox]:before{content:"";width:12px;height:12px;transform:scale(0);transition:all var(--duration-base) var(--ease-default);background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");background-size:contain;background-repeat:no-repeat;background-position:center}.echo-input-option input[type=checkbox]:checked{background-color:var(--primary-color-lighter);border-color:var(--primary-color-lighter)}.echo-input-option input[type=checkbox]:checked:before{transform:scale(1)}.echo-input-option input[type=radio]:hover,.echo-input-option input[type=checkbox]:hover{border-color:var(--primary-color-lighter)}.echo-input-option input[type=radio]:focus,.echo-input-option input[type=checkbox]:focus{outline:none;border-color:var(--primary-color-lighter);box-shadow:0 0 0 3px color-mix(in srgb,var(--primary-color) 15%,transparent)}.echo-input-option input[type=radio]:checked,.echo-input-option input[type=checkbox]:checked{border-color:var(--primary-color-lighter)}.echo-input-option span{font-size:var(--font-sm);color:var(--text-medium);-webkit-user-select:none;user-select:none}.echo-select{position:relative;width:100%}.echo-select-trigger{width:100%;padding:.5rem;border:1px solid var(--border-color);border-radius:var(--radius-md);background-color:#fff;color:var(--text-medium);font-size:var(--font-sm);transition:all var(--duration-base) var(--ease-default);cursor:pointer;text-align:left;display:flex;align-items:center;justify-content:space-between;gap:.5rem;outline:none}.echo-select-trigger[data-placeholder=true]{color:var(--text-lighter)}.echo-select-trigger:hover{border-color:var(--border-color-medium)}.echo-select-trigger:focus,.echo-select-trigger[data-open=true]{border-color:var(--primary-color);box-shadow:0 0 0 3px color-mix(in srgb,var(--primary-color) 15%,transparent)}.echo-select-arrow{flex-shrink:0;transition:transform var(--duration-base) var(--ease-default)}.echo-select-trigger[data-open=true] .echo-select-arrow{transform:rotate(180deg)}.echo-select-dropdown{position:absolute;top:calc(100% + .25rem);left:0;right:0;background:#fff;border:1px solid var(--border-color-medium);border-radius:var(--radius-md);box-shadow:var(--shadow-black-lightened-md);max-height:15rem;overflow-y:auto;z-index:10;animation:slideDownFade var(--duration-base) var(--ease-default);padding:var(--spacing-xs)}.echo-select-option{width:100%;padding:.5rem .75rem;background:none;border:none;text-align:left;color:var(--text-medium);font-size:var(--font-sm);cursor:pointer;transition:all var(--duration-base) var(--ease-default);outline:none;border-radius:var(--radius-sm)}.echo-select-option:hover{background:var(--primary-color-lightest)}.echo-select-option:focus{background:var(--primary-color-lightest);box-shadow:0 0 0 1px var(--primary-color) inset}.echo-select-option[data-selected=true]{background:var(--primary-color-lightest);color:var(--primary-color);font-weight:500}select.echo-input-field{display:none}.visually-hidden{position:absolute;left:50%;bottom:0;transform:translate(-50%);width:1px;height:1px;padding:0;margin:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
package/dist/types.d.ts CHANGED
@@ -4,12 +4,42 @@ export type BrowserInfo = {
4
4
  height: number;
5
5
  screenWidth: number;
6
6
  screenHeight: number;
7
+ language: string;
8
+ languages: readonly string[];
9
+ doNotTrack: string | null;
10
+ cookiesEnabled: boolean;
11
+ hardwareConcurrency: number;
12
+ deviceMemory?: number;
13
+ maxTouchPoints: number;
14
+ colorDepth: number;
15
+ pixelRatio: number;
16
+ availableWidth: number;
17
+ availableHeight: number;
7
18
  };
8
- export type Metadata = {
19
+ export type NetworkInfo = {
20
+ effectiveType?: string;
21
+ downlink?: number;
22
+ rtt?: number;
23
+ saveData?: boolean;
24
+ };
25
+ export type LocationInfo = {
9
26
  url: string;
27
+ origin: string;
28
+ pathname: string;
29
+ searchParams: Record<string, string>;
30
+ referrer: string;
31
+ };
32
+ export type TimeInfo = {
33
+ timezone: string;
34
+ localDateTime: string;
35
+ };
36
+ export type Metadata = {
10
37
  userAgent: string;
11
- timestamp: string;
12
38
  browserInfo: BrowserInfo;
39
+ networkInfo: NetworkInfo;
40
+ locationInfo: LocationInfo;
41
+ timeInfo: TimeInfo;
42
+ console: ConsoleEntry[];
13
43
  };
14
44
  export type ConsoleEntry = {
15
45
  type: 'log' | 'warn' | 'error';
@@ -17,10 +47,10 @@ export type ConsoleEntry = {
17
47
  timestamp: string;
18
48
  };
19
49
  export type FeedbackPayload = {
20
- comment: string;
50
+ message: string;
21
51
  screenshot?: Screenshot;
22
52
  metadata: Metadata;
23
- console: ConsoleEntry[];
53
+ customInputs?: Record<string, CustomInputValue>;
24
54
  };
25
55
  export type Position = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
26
56
  export type TextConfig = {
@@ -48,11 +78,45 @@ export type TextConfig = {
48
78
  text: string;
49
79
  };
50
80
  };
81
+ export type CustomInputValue = string | string[];
82
+ export type CustomInputBase = {
83
+ id: string;
84
+ label?: string;
85
+ required?: boolean;
86
+ defaultValue?: CustomInputValue;
87
+ };
88
+ export type TextInputConfig = CustomInputBase & {
89
+ type: 'text';
90
+ placeholder?: string;
91
+ };
92
+ export type TextAreaConfig = CustomInputBase & {
93
+ type: 'textarea';
94
+ placeholder?: string;
95
+ };
96
+ export type SelectOption = {
97
+ value: string;
98
+ label: string;
99
+ };
100
+ export type SelectInputConfig = CustomInputBase & {
101
+ type: 'select';
102
+ options: SelectOption[];
103
+ placeholder?: string;
104
+ };
105
+ export type RadioInputConfig = CustomInputBase & {
106
+ type: 'radio';
107
+ options: SelectOption[];
108
+ };
109
+ export type CheckboxInputConfig = CustomInputBase & {
110
+ type: 'checkbox';
111
+ options: SelectOption[];
112
+ };
113
+ export type CustomInputConfig = TextInputConfig | TextAreaConfig | SelectInputConfig | RadioInputConfig | CheckboxInputConfig;
51
114
  export type EchoConfig = {
52
115
  onSubmit: (data: FeedbackPayload) => Promise<Response | void>;
53
116
  position?: Position;
54
117
  primaryColor?: `#${string}`;
55
118
  textConfig?: Partial<TextConfig>;
119
+ customInputs?: CustomInputConfig[];
56
120
  };
57
121
  export type FullEchoConfig = Required<EchoConfig> & {
58
122
  textConfig: TextConfig;
@@ -1 +1,2 @@
1
1
  export declare const deepMerge: (target: any, source: any) => any;
2
+ export declare const debounce: <T extends (...args: any[]) => void>(func: T, wait: number) => (...args: Parameters<T>) => void;
@@ -1,7 +1,6 @@
1
1
  export * from './color';
2
2
  export * from './common';
3
3
  export * from './console';
4
- export * from './debounce';
5
4
  export * from './device';
6
5
  export * from './events';
7
6
  export * from './format';
@@ -1,16 +1,17 @@
1
- export declare const registerKeyListener: (key: string, callback: (e: KeyboardEvent) => void) => void;
2
1
  export declare const registerWindowEventListener: {
3
2
  <K extends keyof WindowEventMap>(props: {
4
3
  event: K;
5
4
  callback: (e: WindowEventMap[K]) => void;
6
5
  onMount?: () => void;
7
6
  onCleanup?: () => void;
7
+ useOriginal?: boolean;
8
8
  }): void;
9
9
  (props: {
10
10
  event: string;
11
11
  callback: (e: Event) => void;
12
12
  onMount?: () => void;
13
13
  onCleanup?: () => void;
14
+ useOriginal?: boolean;
14
15
  }): void;
15
16
  };
16
17
  export declare const registerMutationObserver: (props: {
@@ -20,3 +21,4 @@ export declare const registerMutationObserver: (props: {
20
21
  onMount?: () => void;
21
22
  onCleanup?: () => void;
22
23
  }) => void;
24
+ export declare const createWrappedListener: (originalListener: EventListenerOrEventListenerObject, callback: (event: Event) => void) => (this: EventTarget, event: Event) => void;
@@ -0,0 +1,2 @@
1
+ import type { Metadata } from '~/types';
2
+ export declare const collectMetadata: () => Metadata;
@@ -0,0 +1,4 @@
1
+ export declare const registerOriginalListener: (target: EventTarget, type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions) => void;
2
+ export declare const removeOriginalListener: (target: EventTarget, type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions) => void;
3
+ export declare const patchEventTarget: (callback: (event: Event) => void) => void;
4
+ export declare const unpatchEventTarget: () => void;
@@ -0,0 +1,6 @@
1
+ import type { WidgetStore } from '~/stores/widgetStore';
2
+ import type { Notification } from '~/types';
3
+ export declare const createNotificationManager: (widget: WidgetStore) => {
4
+ show: (notification: Omit<Notification, "show">) => void;
5
+ clear: () => void;
6
+ };
@@ -0,0 +1,8 @@
1
+ import type { DrawingState } from '~/stores/drawingStore';
2
+ import type { FeedbackState } from '~/stores/feedbackStore';
3
+ import type { WidgetStore } from '~/stores/widgetStore';
4
+ export type PageState = {
5
+ feedback: FeedbackState;
6
+ drawing: DrawingState;
7
+ };
8
+ export declare const createDebouncedStateSaver: (widget: WidgetStore) => (pageKey: string, state: PageState, isClearing?: any) => void;
@@ -1,14 +1,16 @@
1
1
  import { DrawingState, FeedbackState } from '~/stores';
2
- import type { Shape } from '~/types';
2
+ import type { CustomInputValue, Shape } from '~/types';
3
3
  type StoredPageState = {
4
4
  feedback: {
5
- comment: string;
5
+ message: string;
6
+ customInputValues?: Record<string, CustomInputValue>;
6
7
  };
7
8
  drawing: {
8
9
  shapes: Shape[];
9
10
  };
10
11
  latestQuery?: string;
11
12
  };
13
+ export declare const formatPagePath: (path: string | undefined) => string;
12
14
  export declare const dispatchStorageChange: () => void;
13
15
  export declare const getStorageKey: (key: string) => string;
14
16
  export declare const getFromStorage: <T>(key: string, defaultValue: T) => T;
@@ -18,7 +20,7 @@ export declare const savePageState: (pageKey: string, state: {
18
20
  feedback: FeedbackState;
19
21
  drawing: DrawingState;
20
22
  }) => void;
21
- export declare const loadPageState: (pageKey: string) => StoredPageState | null;
23
+ export declare const loadPageState: (pageKey: string) => StoredPageState | undefined;
22
24
  export declare const clearPageState: (pageKey: string) => void;
23
25
  export declare const getStoredPagesCount: () => number;
24
26
  export declare const getStoredPages: () => {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@contember/echo",
3
3
  "license": "Apache-2.0",
4
- "version": "0.0.28",
4
+ "version": "0.0.29",
5
5
  "type": "module",
6
6
  "author": "neumie@neumie.dev",
7
7
  "keywords": [
@@ -1 +0,0 @@
1
- export declare const debounce: <T extends (...args: any[]) => void>(func: T, wait: number) => (...args: Parameters<T>) => void;