@contember/echo 0.0.21 → 0.0.22

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.
Files changed (60) hide show
  1. package/README.md +2 -2
  2. package/dist/components/Echo.d.ts +2 -2
  3. package/dist/components/atoms/Button.d.ts +0 -2
  4. package/dist/components/icons/index.d.ts +0 -1
  5. package/dist/components/molecules/LauncherButton.d.ts +2 -0
  6. package/dist/components/molecules/StoredFeedback.d.ts +2 -0
  7. package/dist/{features/feedback/components → components/organisms}/FeedbackForm.d.ts +1 -1
  8. package/dist/config/drawingConfig.d.ts +5 -10
  9. package/dist/contexts/EchoContext.d.ts +5 -8
  10. package/dist/echo.es.js +5076 -6212
  11. package/dist/echo.umd.js +11 -1095
  12. package/dist/index.d.ts +4 -3
  13. package/dist/stores/drawingStore.d.ts +6 -7
  14. package/dist/stores/echoStore.d.ts +4 -11
  15. package/dist/stores/feedbackStore.d.ts +6 -6
  16. package/dist/stores/widgetStore.d.ts +9 -8
  17. package/dist/style.css +1 -0
  18. package/dist/types.d.ts +24 -30
  19. package/dist/utils/common.d.ts +1 -0
  20. package/dist/utils/format.d.ts +1 -0
  21. package/dist/utils/index.d.ts +10 -1
  22. package/dist/utils/listeners.d.ts +22 -0
  23. package/dist/utils/screenshot.d.ts +2 -6
  24. package/dist/utils/storage.d.ts +2 -2
  25. package/dist/utils/validators.d.ts +2 -0
  26. package/package.json +4 -6
  27. package/dist/components/EchoLayout.d.ts +0 -7
  28. package/dist/components/Launcher.d.ts +0 -6
  29. package/dist/components/Overlay.d.ts +0 -4
  30. package/dist/components/icons/MessageIcon.d.ts +0 -3
  31. package/dist/features/drawing/components/index.d.ts +0 -5
  32. package/dist/features/drawing/index.d.ts +0 -2
  33. package/dist/features/drawing/styles/ColorSelector.styles.d.ts +0 -2
  34. package/dist/features/drawing/styles/DrawingLayer.styles.d.ts +0 -2
  35. package/dist/features/drawing/styles/DrawingToolbar.styles.d.ts +0 -2
  36. package/dist/features/drawing/styles/DrawingTooltip.styles.d.ts +0 -2
  37. package/dist/features/drawing/styles/ShapeActions.styles.d.ts +0 -2
  38. package/dist/features/drawing/styles/index.d.ts +0 -6
  39. package/dist/features/feedback/components/index.d.ts +0 -1
  40. package/dist/features/feedback/index.d.ts +0 -2
  41. package/dist/features/feedback/styles/FeedbackForm.styles.d.ts +0 -2
  42. package/dist/features/feedback/styles/index.d.ts +0 -1
  43. package/dist/features/launcher/components/EchoLauncherButton.d.ts +0 -2
  44. package/dist/features/launcher/components/SavedPagesDropdown.d.ts +0 -2
  45. package/dist/features/launcher/styles/EchoLauncherButton.styles.d.ts +0 -2
  46. package/dist/features/launcher/styles/Notification.styles.d.ts +0 -2
  47. package/dist/features/launcher/styles/SavedPagesDropdown.styles.d.ts +0 -2
  48. package/dist/features/launcher/styles/WelcomeMessage.styles.d.ts +0 -2
  49. package/dist/features/launcher/styles/index.d.ts +0 -4
  50. package/dist/styles/Echo.styles.d.ts +0 -2
  51. package/dist/styles/index.d.ts +0 -2
  52. package/dist/styles/zIndex.d.ts +0 -13
  53. /package/dist/{features/drawing/components → components/atoms}/Shape.d.ts +0 -0
  54. /package/dist/{features/drawing/components → components/molecules}/ColorSelector.d.ts +0 -0
  55. /package/dist/{features/drawing/components → components/molecules}/DrawingToolbar.d.ts +0 -0
  56. /package/dist/{features/drawing/components → components/molecules}/DrawingTooltip.d.ts +0 -0
  57. /package/dist/{features/launcher/components → components/molecules}/Notification.d.ts +0 -0
  58. /package/dist/{features/drawing/components → components/molecules}/ShapeActions.d.ts +0 -0
  59. /package/dist/{features/launcher/components → components/molecules}/WelcomeMessage.d.ts +0 -0
  60. /package/dist/{features/drawing/components → components/organisms}/DrawingLayer.d.ts +0 -0
package/dist/index.d.ts CHANGED
@@ -1,8 +1,9 @@
1
- import { type EchoOptions, type FeedbackData, type Position } from './types';
1
+ import { type EchoConfig, type FeedbackPayload } from './types';
2
+ import './styles.css';
2
3
  /**
3
4
  * Initialize the Echo feedback widget.
4
5
  * @throws {Error} If initialization fails or invalid options are provided
5
6
  * @returns {() => void} Cleanup function to remove the widget
6
7
  */
7
- export declare function initEcho(options: EchoOptions): () => void;
8
- export type { FeedbackData, EchoOptions, Position };
8
+ export declare function initEcho(options: EchoConfig): () => void;
9
+ export type { FeedbackPayload, EchoConfig };
@@ -1,12 +1,11 @@
1
- import type { DrawingTool, Point, Shape } from '~/types';
2
- export interface DrawingState {
1
+ import type { DrawingTool, FullEchoConfig, Point, Shape } from '~/types';
2
+ export type DrawingState = {
3
3
  isDrawing: boolean;
4
4
  selectedShapeId: string | null;
5
5
  selectedTool: DrawingTool;
6
6
  selectedColor: string;
7
7
  shapes: Shape[];
8
8
  currentPoints: Point[];
9
- currentPath: string;
10
9
  showTooltip: boolean;
11
10
  mousePosition: Point;
12
11
  hasDrawn: boolean;
@@ -15,8 +14,8 @@ export interface DrawingState {
15
14
  initialClickPos: Point | null;
16
15
  dragOffset: Point | null;
17
16
  cursor: string;
18
- }
19
- export interface DrawingStore {
17
+ };
18
+ export type DrawingStore = {
20
19
  state: DrawingState;
21
20
  setState: (state: Partial<DrawingState>, isClearing?: boolean) => void;
22
21
  methods: {
@@ -36,5 +35,5 @@ export interface DrawingStore {
36
35
  points: Point[];
37
36
  }, point: Point) => void;
38
37
  };
39
- }
40
- export declare const createDrawingStore: (primaryColor: string, onStateChange?: (state: Partial<DrawingState>, isClearing?: boolean) => void) => DrawingStore;
38
+ };
39
+ export declare const createDrawingStore: (config: FullEchoConfig, currentPageKey: string, onStateChange?: (state: Partial<DrawingState>, isClearing?: boolean) => void) => DrawingStore;
@@ -1,20 +1,13 @@
1
- import type { FeedbackData, TextConfig } from '~/types';
1
+ import type { FullEchoConfig } from '~/types';
2
2
  import { type DrawingStore } from './drawingStore';
3
3
  import { type FeedbackStore } from './feedbackStore';
4
4
  import { type WidgetStore } from './widgetStore';
5
- export interface EchoStore {
5
+ export type EchoStore = {
6
6
  feedback: FeedbackStore;
7
7
  drawing: DrawingStore;
8
8
  widget: WidgetStore;
9
- text: TextConfig;
10
9
  methods: {
11
10
  reset: () => void;
12
11
  };
13
- }
14
- interface EchoStoreConfig {
15
- primaryColor: string;
16
- onSubmit: (data: FeedbackData) => Promise<void>;
17
- text: TextConfig;
18
- }
19
- export declare const createEchoStore: (config: EchoStoreConfig) => EchoStore;
20
- export {};
12
+ };
13
+ export declare const createEchoStore: (config: FullEchoConfig) => EchoStore;
@@ -1,12 +1,12 @@
1
- import type { Screenshot } from '~/types';
2
- export interface FeedbackState {
1
+ import type { FullEchoConfig, Screenshot } from '~/types';
2
+ export type FeedbackState = {
3
3
  comment: string;
4
4
  screenshot?: Screenshot;
5
5
  isCapturing: boolean;
6
6
  isMinimized: boolean;
7
- }
8
- export interface FeedbackStore {
7
+ };
8
+ export type FeedbackStore = {
9
9
  state: FeedbackState;
10
10
  setState: (state: Partial<FeedbackState>, isClearing?: boolean) => void;
11
- }
12
- export declare const createFeedbackStore: (initialComment?: string, onStateChange?: (state: Partial<FeedbackState>, isClearing?: boolean) => void) => FeedbackStore;
11
+ };
12
+ export declare const createFeedbackStore: (config: FullEchoConfig, currentPageKey: string, onStateChange?: (state: Partial<FeedbackState>, isClearing?: boolean) => void) => FeedbackStore;
@@ -1,5 +1,6 @@
1
- import type { FeedbackData, Notification } from '~/types';
2
- export interface WidgetState {
1
+ import type { FeedbackPayload, FullEchoConfig, Notification, TextConfig } from '~/types';
2
+ export type WidgetState = {
3
+ text: TextConfig;
3
4
  isOpen: boolean;
4
5
  primaryColor: string;
5
6
  notification: Notification;
@@ -7,16 +8,16 @@ export interface WidgetState {
7
8
  width: number;
8
9
  height: number;
9
10
  };
10
- isPagesDropdownOpen: boolean;
11
+ isStoredFeedbackOpen: boolean;
11
12
  pagesCount: number;
12
13
  welcomeMessageIsClosing: boolean;
13
- }
14
- export interface WidgetStore {
14
+ };
15
+ export type WidgetStore = {
15
16
  state: WidgetState;
16
17
  setState: (state: Partial<WidgetState>) => void;
17
18
  methods: {
18
19
  postSubmit: (result: Notification) => void;
19
- onSubmit: (data: FeedbackData) => Promise<void>;
20
+ onSubmit: (data: FeedbackPayload) => Promise<void>;
20
21
  };
21
- }
22
- export declare const createWidgetStore: (primaryColor: string, onSubmit: (data: FeedbackData) => Promise<void>) => WidgetStore;
22
+ };
23
+ export declare const createWidgetStore: (config: FullEchoConfig, currentPageKey: string) => WidgetStore;
package/dist/style.css ADDED
@@ -0,0 +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}}
package/dist/types.d.ts CHANGED
@@ -1,29 +1,29 @@
1
- export type Screenshot = `data:image/webp;base64,${string}` | `data:image/png;base64,${string}`;
2
- export interface BrowserInfo {
1
+ export type Screenshot = `data:image/png;base64,${string}`;
2
+ export type BrowserInfo = {
3
3
  width: number;
4
4
  height: number;
5
5
  screenWidth: number;
6
6
  screenHeight: number;
7
- }
8
- export interface Metadata {
7
+ };
8
+ export type Metadata = {
9
9
  url: string;
10
10
  userAgent: string;
11
11
  timestamp: string;
12
12
  browserInfo: BrowserInfo;
13
- }
14
- export interface ConsoleEntry {
13
+ };
14
+ export type ConsoleEntry = {
15
15
  type: 'log' | 'warn' | 'error';
16
16
  message: string;
17
17
  timestamp: string;
18
- }
19
- export interface FeedbackData {
18
+ };
19
+ export type FeedbackPayload = {
20
20
  comment: string;
21
21
  screenshot?: Screenshot;
22
22
  metadata: Metadata;
23
23
  console: ConsoleEntry[];
24
- }
24
+ };
25
25
  export type Position = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
26
- export interface TextConfig {
26
+ export type TextConfig = {
27
27
  welcomeMessage: {
28
28
  text: string;
29
29
  closeAriaLabel: string;
@@ -47,47 +47,41 @@ export interface TextConfig {
47
47
  drawingTooltip: {
48
48
  text: string;
49
49
  };
50
- }
51
- export type EchoOptions = {
52
- onSubmit: (data: FeedbackData) => Promise<void>;
50
+ };
51
+ export type EchoConfig = {
52
+ onSubmit: (data: FeedbackPayload) => Promise<void>;
53
53
  position?: Position;
54
54
  primaryColor?: `#${string}`;
55
55
  textConfig?: Partial<TextConfig>;
56
- children?: any;
56
+ };
57
+ export type FullEchoConfig = Required<EchoConfig> & {
58
+ textConfig: TextConfig;
57
59
  };
58
60
  export declare const POSITIONS: Record<Position, {
59
61
  [key: string]: string;
60
62
  }>;
61
- export interface Point {
63
+ export type Point = {
62
64
  x: number;
63
65
  y: number;
64
- }
66
+ };
65
67
  export type ShapeType = 'rectangle' | 'path';
66
68
  export type DrawingTool = 'rectangle' | 'path';
67
- export interface Shape {
69
+ export type Shape = {
68
70
  id: string;
69
71
  type: ShapeType;
70
72
  color: string;
71
73
  points: Point[];
72
- }
73
- export interface IconProps {
74
+ };
75
+ export type IconProps = {
74
76
  size?: number;
75
77
  stroke?: string;
76
78
  strokeWidth?: number;
77
79
  class?: string;
78
80
  style?: any;
79
81
  fill?: string;
80
- }
81
- export interface StylesConfig {
82
- primaryColor: string;
83
- }
84
- export interface EnrichedStylesConfig extends StylesConfig {
85
- primaryTextColor: string;
86
- primaryColorLighter: string;
87
- primaryColorLightest: string;
88
- }
89
- export interface Notification {
82
+ };
83
+ export type Notification = {
90
84
  show: boolean;
91
85
  type: 'success' | 'error' | null;
92
86
  message: string | null;
93
- }
87
+ };
@@ -0,0 +1 @@
1
+ export declare const deepMerge: (target: any, source: any) => any;
@@ -0,0 +1 @@
1
+ export declare const formatPath: (path: string) => string;
@@ -1,4 +1,13 @@
1
+ export * from './color';
2
+ export * from './common';
3
+ export * from './console';
4
+ export * from './debounce';
1
5
  export * from './device';
2
- export * from './screenshot';
6
+ export * from './events';
7
+ export * from './format';
3
8
  export * from './geometry';
9
+ export * from './listeners';
10
+ export * from './screenshot';
4
11
  export * from './storage';
12
+ export * from './svg';
13
+ export * from './validators';
@@ -0,0 +1,22 @@
1
+ export declare const registerKeyListener: (key: string, callback: () => void) => void;
2
+ export declare const registerWindowEventListener: {
3
+ <K extends keyof WindowEventMap>(props: {
4
+ event: K;
5
+ callback: (e: WindowEventMap[K]) => void;
6
+ onMount?: () => void;
7
+ onCleanup?: () => void;
8
+ }): void;
9
+ (props: {
10
+ event: string;
11
+ callback: (e: Event) => void;
12
+ onMount?: () => void;
13
+ onCleanup?: () => void;
14
+ }): void;
15
+ };
16
+ export declare const registerMutationObserver: (props: {
17
+ target: Node;
18
+ options?: MutationObserverInit;
19
+ callback: (mutations: MutationRecord[]) => void;
20
+ onMount?: () => void;
21
+ onCleanup?: () => void;
22
+ }) => void;
@@ -1,6 +1,2 @@
1
- import type { Screenshot, Shape } from '~/types';
2
- interface CaptureScreenshotConfig {
3
- annotations: Shape[];
4
- }
5
- export declare const captureScreenshot: ({ annotations }: CaptureScreenshotConfig) => Promise<Screenshot | undefined>;
6
- export {};
1
+ import type { Screenshot } from '~/types';
2
+ export declare const captureScreenshot: () => Promise<Screenshot | undefined>;
@@ -1,6 +1,6 @@
1
1
  import { DrawingState, FeedbackState } from '~/stores';
2
2
  import type { Shape } from '~/types';
3
- interface StoredPageState {
3
+ type StoredPageState = {
4
4
  feedback: {
5
5
  comment: string;
6
6
  };
@@ -8,7 +8,7 @@ interface StoredPageState {
8
8
  shapes: Shape[];
9
9
  };
10
10
  latestQuery?: string;
11
- }
11
+ };
12
12
  export declare const dispatchStorageChange: () => void;
13
13
  export declare const getStorageKey: (key: string) => string;
14
14
  export declare const getFromStorage: <T>(key: string, defaultValue: T) => T;
@@ -0,0 +1,2 @@
1
+ import type { EchoConfig } from '~/types';
2
+ export declare const validateOptions: (options: EchoConfig) => void;
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.21",
4
+ "version": "0.0.22",
5
5
  "type": "module",
6
6
  "author": "neumie@neumie.dev",
7
7
  "keywords": [
@@ -16,10 +16,9 @@
16
16
  "dist"
17
17
  ],
18
18
  "scripts": {
19
- "dev": "vite",
20
- "build": "tsc && vite build && tsc --emitDeclarationOnly ",
21
- "preview": "vite preview",
22
- "watch": "concurrently \"tsc --watch\" \"vite build --watch\""
19
+ "dev": "vite build --watch",
20
+ "build": "tsc && vite build && tsc --emitDeclarationOnly",
21
+ "ts:watch": "tsc --watch"
23
22
  },
24
23
  "dependencies": {
25
24
  "html2canvas": "^1.4.1",
@@ -27,7 +26,6 @@
27
26
  },
28
27
  "devDependencies": {
29
28
  "@types/node": "^20.17.12",
30
- "concurrently": "^9.1.2",
31
29
  "typescript": "^5.0.0",
32
30
  "vite": "^5.0.0",
33
31
  "vite-plugin-solid": "^2.10.1",
@@ -1,7 +0,0 @@
1
- import type { Component } from 'solid-js';
2
- import type { Position } from '~/types';
3
- interface EchoLayoutProps {
4
- position?: Position;
5
- }
6
- export declare const EchoLayout: Component<EchoLayoutProps>;
7
- export {};
@@ -1,6 +0,0 @@
1
- import type { Component, JSXElement } from 'solid-js';
2
- interface LauncherProps {
3
- children: JSXElement;
4
- }
5
- export declare const Launcher: Component<LauncherProps>;
6
- export {};
@@ -1,4 +0,0 @@
1
- import type { Component, JSX } from 'solid-js';
2
- export declare const Overlay: Component<{
3
- children: JSX.Element;
4
- }>;
@@ -1,3 +0,0 @@
1
- import type { Component } from 'solid-js';
2
- import type { IconProps } from '~/types';
3
- export declare const MessageIcon: Component<IconProps>;
@@ -1,5 +0,0 @@
1
- export * from './DrawingLayer';
2
- export * from './DrawingTooltip';
3
- export * from './Shape';
4
- export * from './ShapeActions';
5
- export * from './DrawingToolbar';
@@ -1,2 +0,0 @@
1
- export * from './components';
2
- export * from './styles';
@@ -1,2 +0,0 @@
1
- import type { StylesConfig } from '~/types';
2
- export declare const colorSelectorStyles: (config: StylesConfig) => string;
@@ -1,2 +0,0 @@
1
- import type { EnrichedStylesConfig } from '~/types';
2
- export declare const drawingLayerStyles: (config: EnrichedStylesConfig) => string;
@@ -1,2 +0,0 @@
1
- import type { EnrichedStylesConfig } from '~/types';
2
- export declare const drawingToolbarStyles: (config: EnrichedStylesConfig) => string;
@@ -1,2 +0,0 @@
1
- import type { EnrichedStylesConfig } from '~/types';
2
- export declare const tooltipStyles: (config: EnrichedStylesConfig) => string;
@@ -1,2 +0,0 @@
1
- import type { EnrichedStylesConfig } from '~/types';
2
- export declare const shapeActionsStyles: (config: EnrichedStylesConfig) => string;
@@ -1,6 +0,0 @@
1
- export * from './DrawingLayer.styles';
2
- export * from './ShapeActions.styles';
3
- export * from './ColorSelector.styles';
4
- export * from './DrawingLayer.styles';
5
- export * from './DrawingToolbar.styles';
6
- export * from './DrawingTooltip.styles';
@@ -1 +0,0 @@
1
- export * from './FeedbackForm';
@@ -1,2 +0,0 @@
1
- export * from './components';
2
- export * from './styles';
@@ -1,2 +0,0 @@
1
- import type { EnrichedStylesConfig } from '~/types';
2
- export declare const feedbackFormStyles: (config: EnrichedStylesConfig) => string;
@@ -1 +0,0 @@
1
- export * from './FeedbackForm.styles';
@@ -1,2 +0,0 @@
1
- import type { Component } from 'solid-js';
2
- export declare const EchoLauncherButton: Component;
@@ -1,2 +0,0 @@
1
- import { type Component } from 'solid-js';
2
- export declare const SavedPagesDropdown: Component;
@@ -1,2 +0,0 @@
1
- import type { EnrichedStylesConfig } from '~/types';
2
- export declare const echoLauncherButtonStyles: (config: EnrichedStylesConfig) => string;
@@ -1,2 +0,0 @@
1
- import type { EnrichedStylesConfig } from '~/types';
2
- export declare const notificationStyles: (config: EnrichedStylesConfig) => string;
@@ -1,2 +0,0 @@
1
- import type { EnrichedStylesConfig } from '~/types';
2
- export declare const savedPagesDropdownStyles: (config: EnrichedStylesConfig) => string;
@@ -1,2 +0,0 @@
1
- import type { EnrichedStylesConfig } from '~/types';
2
- export declare const welcomeMessageStyles: (config: EnrichedStylesConfig) => string;
@@ -1,4 +0,0 @@
1
- export * from './EchoLauncherButton.styles';
2
- export * from './SavedPagesDropdown.styles';
3
- export * from './WelcomeMessage.styles';
4
- export * from './Notification.styles';
@@ -1,2 +0,0 @@
1
- import type { EnrichedStylesConfig } from '~/types';
2
- export declare const echoStyles: (config: EnrichedStylesConfig) => string;
@@ -1,2 +0,0 @@
1
- export * from './Echo.styles';
2
- export * from './zIndex';
@@ -1,13 +0,0 @@
1
- declare const zIndex: {
2
- readonly root: 999999;
3
- readonly overlay: 1;
4
- readonly launcher: 2;
5
- readonly widgetButton: 2;
6
- readonly notification: 2;
7
- readonly welcomeMessage: 2;
8
- readonly feedbackForm: 4;
9
- readonly drawingToolbar: 3;
10
- readonly shapeActions: 3;
11
- readonly drawingTooltip: 3;
12
- };
13
- export { zIndex };