@syntrologie/adapt-nav 2.5.1 → 2.6.0-canary.2

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 (76) hide show
  1. package/node_modules/@syntrologie/shared-editor-ui/dist/hooks/useTriggerWhenStatus.d.ts.map +1 -1
  2. package/node_modules/@syntrologie/shared-editor-ui/dist/hooks/useTriggerWhenStatus.js +22 -153
  3. package/node_modules/@syntrologie/shared-editor-ui/package.json +2 -2
  4. package/package.json +1 -1
  5. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/AnchorPicker.test.d.ts +0 -2
  6. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/AnchorPicker.test.d.ts.map +0 -1
  7. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/AnchorPicker.test.js +0 -224
  8. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/BeforeAfterToggle.test.d.ts +0 -2
  9. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/BeforeAfterToggle.test.d.ts.map +0 -1
  10. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/BeforeAfterToggle.test.js +0 -29
  11. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/ConditionStatusLine.test.d.ts +0 -2
  12. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/ConditionStatusLine.test.d.ts.map +0 -1
  13. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/ConditionStatusLine.test.js +0 -260
  14. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/DetectionBadge.test.d.ts +0 -2
  15. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/DetectionBadge.test.d.ts.map +0 -1
  16. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/DetectionBadge.test.js +0 -70
  17. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/DismissedSection.test.d.ts +0 -2
  18. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/DismissedSection.test.d.ts.map +0 -1
  19. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/DismissedSection.test.js +0 -46
  20. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditBackButton.test.d.ts +0 -2
  21. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditBackButton.test.d.ts.map +0 -1
  22. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditBackButton.test.js +0 -20
  23. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorBody.test.d.ts +0 -2
  24. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorBody.test.d.ts.map +0 -1
  25. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorBody.test.js +0 -12
  26. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorCard.test.d.ts +0 -2
  27. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorCard.test.d.ts.map +0 -1
  28. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorCard.test.js +0 -84
  29. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorFooter.test.d.ts +0 -2
  30. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorFooter.test.d.ts.map +0 -1
  31. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorFooter.test.js +0 -23
  32. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorHeader.test.d.ts +0 -2
  33. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorHeader.test.d.ts.map +0 -1
  34. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorHeader.test.js +0 -23
  35. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorInput.test.d.ts +0 -2
  36. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorInput.test.d.ts.map +0 -1
  37. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorInput.test.js +0 -26
  38. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorLayout.test.d.ts +0 -2
  39. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorLayout.test.d.ts.map +0 -1
  40. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorLayout.test.js +0 -13
  41. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorPanelShell.test.d.ts +0 -2
  42. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorPanelShell.test.d.ts.map +0 -1
  43. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorPanelShell.test.js +0 -496
  44. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorSelect.test.d.ts +0 -2
  45. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorSelect.test.d.ts.map +0 -1
  46. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorSelect.test.js +0 -22
  47. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorTextarea.test.d.ts +0 -2
  48. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorTextarea.test.d.ts.map +0 -1
  49. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EditorTextarea.test.js +0 -20
  50. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/ElementHighlight.test.d.ts +0 -2
  51. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/ElementHighlight.test.d.ts.map +0 -1
  52. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/ElementHighlight.test.js +0 -176
  53. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EmptyState.test.d.ts +0 -2
  54. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EmptyState.test.d.ts.map +0 -1
  55. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/EmptyState.test.js +0 -10
  56. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/GroupHeader.test.d.ts +0 -2
  57. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/GroupHeader.test.d.ts.map +0 -1
  58. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/GroupHeader.test.js +0 -14
  59. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/TriggerJourney.test.d.ts +0 -2
  60. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/TriggerJourney.test.d.ts.map +0 -1
  61. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/TriggerJourney.test.js +0 -189
  62. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/cn.test.d.ts +0 -2
  63. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/cn.test.d.ts.map +0 -1
  64. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/cn.test.js +0 -16
  65. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/formatConditionLabel.test.d.ts +0 -2
  66. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/formatConditionLabel.test.d.ts.map +0 -1
  67. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/formatConditionLabel.test.js +0 -329
  68. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/selectorGenerator.test.d.ts +0 -2
  69. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/selectorGenerator.test.d.ts.map +0 -1
  70. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/selectorGenerator.test.js +0 -257
  71. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/useElementRect.test.d.ts +0 -2
  72. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/useElementRect.test.d.ts.map +0 -1
  73. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/useElementRect.test.js +0 -112
  74. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/useTriggerWhenStatus.test.d.ts +0 -2
  75. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/useTriggerWhenStatus.test.d.ts.map +0 -1
  76. package/node_modules/@syntrologie/shared-editor-ui/dist/__tests__/useTriggerWhenStatus.test.js +0 -1015
@@ -1,13 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { render } from '@testing-library/react';
3
- import { describe, expect, it } from 'vitest';
4
- import { EditorLayout } from '../components/EditorLayout';
5
- describe('EditorLayout', () => {
6
- it('renders children in a flex column container', () => {
7
- const { getByText, container } = render(_jsx(EditorLayout, { children: _jsx("span", { children: "child" }) }));
8
- expect(getByText('child')).toBeTruthy();
9
- const wrapper = container.firstElementChild;
10
- expect(wrapper.className).toContain('se-flex');
11
- expect(wrapper.className).toContain('se-flex-col');
12
- });
13
- });
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=EditorPanelShell.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"EditorPanelShell.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/EditorPanelShell.test.tsx"],"names":[],"mappings":""}
@@ -1,496 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { act, fireEvent, render } from '@testing-library/react';
3
- import { beforeEach, describe, expect, it, vi } from 'vitest';
4
- import { EditorPanelShell } from '../components/EditorPanelShell';
5
- // jsdom does not support PointerEvent; polyfill it so fireEvent creates events
6
- // with clientX/clientY/pointerId correctly.
7
- if (typeof globalThis.PointerEvent === 'undefined') {
8
- class PointerEventPolyfill extends MouseEvent {
9
- constructor(type, init = {}) {
10
- super(type, init);
11
- this.pointerId = init.pointerId ?? 0;
12
- this.pointerType = init.pointerType ?? '';
13
- }
14
- }
15
- vi.stubGlobal('PointerEvent', PointerEventPolyfill);
16
- }
17
- vi.stubGlobal('ResizeObserver', class {
18
- observe() { }
19
- unobserve() { }
20
- disconnect() { }
21
- });
22
- Element.prototype.setPointerCapture = vi.fn();
23
- Element.prototype.releasePointerCapture = vi.fn();
24
- // Node 25+ exposes a native `localStorage` that shadows jsdom's when
25
- // `--localstorage-file` is absent. Stub with a proper in-memory Storage.
26
- const storageMap = new Map();
27
- vi.stubGlobal('localStorage', {
28
- getItem: (key) => storageMap.get(key) ?? null,
29
- setItem: (key, value) => storageMap.set(key, value),
30
- removeItem: (key) => storageMap.delete(key),
31
- clear: () => storageMap.clear(),
32
- get length() {
33
- return storageMap.size;
34
- },
35
- key: (index) => [...storageMap.keys()][index] ?? null,
36
- });
37
- describe('EditorPanelShell', () => {
38
- beforeEach(() => {
39
- localStorage.clear();
40
- // Set default viewport dimensions
41
- Object.defineProperty(window, 'innerWidth', { value: 1280, writable: true });
42
- Object.defineProperty(window, 'innerHeight', { value: 800, writable: true });
43
- });
44
- it('renders panel docked left by default', () => {
45
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
46
- const panel = container.querySelector('[data-syntro-editor-panel]');
47
- expect(panel).toBeTruthy();
48
- expect(panel.style.left).toBe('0px');
49
- expect(panel.style.top).toBe('0px');
50
- });
51
- it('renders panel with minimum width of 480px', () => {
52
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
53
- const panel = container.querySelector('[data-syntro-editor-panel]');
54
- expect(panel.style.width).toBe('480px');
55
- });
56
- it('renders FAB when panel is open', () => {
57
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
58
- const fab = container.querySelector('[data-syntro-fab]');
59
- expect(fab).toBeTruthy();
60
- });
61
- it('renders FAB when panel is closed (minimized)', () => {
62
- const { container } = render(_jsx(EditorPanelShell, { isOpen: false, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
63
- const fab = container.querySelector('[data-syntro-fab]');
64
- expect(fab).toBeTruthy();
65
- const panel = container.querySelector('[data-syntro-editor-panel]');
66
- expect(panel).toBeNull();
67
- });
68
- it('renders 8 resize handles when panel is open', () => {
69
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
70
- const handles = container.querySelectorAll('[data-syntro-editor-ui^="resize-"]');
71
- expect(handles.length).toBe(8);
72
- });
73
- it('does not render resize handles when closed', () => {
74
- const { container } = render(_jsx(EditorPanelShell, { isOpen: false, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
75
- const handles = container.querySelectorAll('[data-syntro-editor-ui^="resize-"]');
76
- expect(handles.length).toBe(0);
77
- });
78
- it('saves geometry to localStorage on mount', () => {
79
- render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
80
- const stored = localStorage.getItem('syntro:editor-panel');
81
- expect(stored).toBeTruthy();
82
- const geo = JSON.parse(stored);
83
- expect(geo.width).toBe(480);
84
- expect(geo.docked).toBe('left');
85
- });
86
- it('loads geometry from localStorage', () => {
87
- localStorage.setItem('syntro:editor-panel', JSON.stringify({ x: 100, y: 50, width: 600, height: 500, docked: null }));
88
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
89
- const panel = container.querySelector('[data-syntro-editor-panel]');
90
- expect(panel.style.left).toBe('100px');
91
- expect(panel.style.top).toBe('50px');
92
- expect(panel.style.width).toBe('600px');
93
- });
94
- it('applies antialiased font smoothing', () => {
95
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
96
- const panel = container.querySelector('[data-syntro-editor-panel]');
97
- expect(panel.className).toContain('se-antialiased');
98
- });
99
- it('applies rounded corners when undocked', () => {
100
- localStorage.setItem('syntro:editor-panel', JSON.stringify({ x: 100, y: 50, width: 600, height: 500, docked: null }));
101
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
102
- const panel = container.querySelector('[data-syntro-editor-panel]');
103
- expect(panel.className).toContain('se-rounded-lg');
104
- });
105
- it('applies edge border when docked left', () => {
106
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
107
- const panel = container.querySelector('[data-syntro-editor-panel]');
108
- expect(panel.className).toContain('se-border-r');
109
- });
110
- it('uses namespaced localStorage key when panelId is provided', () => {
111
- render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, panelId: "my-panel", children: _jsx("div", { children: "Content" }) }));
112
- const stored = localStorage.getItem('syntro:editor-panel:my-panel');
113
- expect(stored).toBeTruthy();
114
- const geo = JSON.parse(stored);
115
- expect(geo.width).toBe(480);
116
- expect(geo.docked).toBe('left');
117
- });
118
- it('loads geometry from namespaced localStorage key when panelId is provided', () => {
119
- localStorage.setItem('syntro:editor-panel:my-panel', JSON.stringify({ x: 200, y: 75, width: 700, height: 550, docked: null }));
120
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, panelId: "my-panel", children: _jsx("div", { children: "Content" }) }));
121
- const panel = container.querySelector('[data-syntro-editor-panel]');
122
- expect(panel.style.left).toBe('200px');
123
- expect(panel.style.top).toBe('75px');
124
- expect(panel.style.width).toBe('700px');
125
- });
126
- it('does not use default key when panelId is provided', () => {
127
- render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, panelId: "my-panel", children: _jsx("div", { children: "Content" }) }));
128
- const defaultStored = localStorage.getItem('syntro:editor-panel');
129
- expect(defaultStored).toBeNull();
130
- });
131
- it('FAB zIndex matches panel zIndex prop', () => {
132
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, zIndex: 10000, children: _jsx("div", { children: "Content" }) }));
133
- const fab = container.querySelector('[data-syntro-fab]');
134
- const panel = container.querySelector('[data-syntro-editor-panel]');
135
- expect(fab.style.zIndex).toBe('10000');
136
- expect(panel.style.zIndex).toBe('10000');
137
- });
138
- it('resize handles have data-resize-dir attributes', () => {
139
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
140
- const handles = container.querySelectorAll('[data-resize-dir]');
141
- expect(handles.length).toBe(8);
142
- const dirs = Array.from(handles).map((h) => h.dataset.resizeDir);
143
- expect(dirs).toContain('n');
144
- expect(dirs).toContain('se');
145
- expect(dirs).toContain('nw');
146
- });
147
- it('renders docked right with left border and correct position', () => {
148
- localStorage.setItem('syntro:editor-panel', JSON.stringify({ x: 0, y: 0, width: 500, height: 800, docked: 'right' }));
149
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
150
- const panel = container.querySelector('[data-syntro-editor-panel]');
151
- expect(panel.className).toContain('se-border-l');
152
- expect(panel.style.right).toBe('0px');
153
- });
154
- it('gracefully handles corrupt localStorage data', () => {
155
- localStorage.setItem('syntro:editor-panel', 'not-valid-json');
156
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
157
- const panel = container.querySelector('[data-syntro-editor-panel]');
158
- // Falls back to default geometry
159
- expect(panel).toBeTruthy();
160
- expect(panel.style.width).toBe('480px');
161
- });
162
- it('enforces minimum width when localStorage has smaller value', () => {
163
- localStorage.setItem('syntro:editor-panel', JSON.stringify({ x: 0, y: 0, width: 100, height: 200, docked: null }));
164
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
165
- const panel = container.querySelector('[data-syntro-editor-panel]');
166
- // Width should be clamped to MIN_WIDTH (480)
167
- expect(panel.style.width).toBe('480px');
168
- });
169
- it('enforces minimum height when localStorage has smaller value', () => {
170
- localStorage.setItem('syntro:editor-panel', JSON.stringify({ x: 0, y: 0, width: 600, height: 100, docked: null }));
171
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
172
- const panel = container.querySelector('[data-syntro-editor-panel]');
173
- // Height should be clamped to MIN_HEIGHT (400)
174
- expect(panel.style.height).toBe('400px');
175
- });
176
- it('handles localStorage data with missing fields by using defaults', () => {
177
- localStorage.setItem('syntro:editor-panel', JSON.stringify({ docked: null }));
178
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
179
- const panel = container.querySelector('[data-syntro-editor-panel]');
180
- expect(panel).toBeTruthy();
181
- // x/y should default to 0, width to MIN_WIDTH, height to max(MIN_HEIGHT, innerHeight)
182
- expect(panel.style.left).toBe('0px');
183
- expect(panel.style.top).toBe('0px');
184
- expect(panel.style.width).toBe('480px');
185
- });
186
- describe('FAB drag handlers', () => {
187
- it('calls onToggle on FAB click (pointerDown + pointerUp without move)', () => {
188
- const onToggle = vi.fn();
189
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: onToggle, children: _jsx("div", { children: "Content" }) }));
190
- const fab = container.querySelector('[data-syntro-fab]');
191
- fireEvent.pointerDown(fab, { clientX: 100, clientY: 100, pointerId: 1 });
192
- fireEvent.pointerUp(fab, { clientX: 100, clientY: 100, pointerId: 1 });
193
- expect(onToggle).toHaveBeenCalledTimes(1);
194
- });
195
- it('does not call onToggle when FAB is dragged beyond threshold', () => {
196
- const onToggle = vi.fn();
197
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: onToggle, children: _jsx("div", { children: "Content" }) }));
198
- const fab = container.querySelector('[data-syntro-fab]');
199
- fireEvent.pointerDown(fab, { clientX: 100, clientY: 100, pointerId: 1 });
200
- // Move beyond DRAG_THRESHOLD (5px)
201
- fireEvent.pointerMove(fab, { clientX: 200, clientY: 200, pointerId: 1 });
202
- fireEvent.pointerUp(fab, { clientX: 200, clientY: 200, pointerId: 1 });
203
- expect(onToggle).not.toHaveBeenCalled();
204
- });
205
- it('does not count as drag when movement is below threshold', () => {
206
- const onToggle = vi.fn();
207
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: onToggle, children: _jsx("div", { children: "Content" }) }));
208
- const fab = container.querySelector('[data-syntro-fab]');
209
- fireEvent.pointerDown(fab, { clientX: 100, clientY: 100, pointerId: 1 });
210
- // Move less than DRAG_THRESHOLD (5px)
211
- fireEvent.pointerMove(fab, { clientX: 102, clientY: 102, pointerId: 1 });
212
- fireEvent.pointerUp(fab, { clientX: 102, clientY: 102, pointerId: 1 });
213
- // Still treated as click
214
- expect(onToggle).toHaveBeenCalledTimes(1);
215
- });
216
- it('ignores pointerMove when not dragging', () => {
217
- const onToggle = vi.fn();
218
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: onToggle, children: _jsx("div", { children: "Content" }) }));
219
- const fab = container.querySelector('[data-syntro-fab]');
220
- // Move without pointerDown should be ignored
221
- fireEvent.pointerMove(fab, { clientX: 200, clientY: 200, pointerId: 1 });
222
- // Panel should not have moved
223
- const panel = container.querySelector('[data-syntro-editor-panel]');
224
- expect(panel.style.left).toBe('0px');
225
- });
226
- it('moves panel DOM directly during drag for performance', () => {
227
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
228
- const fab = container.querySelector('[data-syntro-fab]');
229
- const panel = container.querySelector('[data-syntro-editor-panel]');
230
- fireEvent.pointerDown(fab, { clientX: 12, clientY: 12, pointerId: 1 });
231
- // Move beyond threshold
232
- fireEvent.pointerMove(fab, { clientX: 112, clientY: 112, pointerId: 1 });
233
- // Panel DOM should be updated directly
234
- expect(panel.style.left).toBe('100px');
235
- expect(panel.style.top).toBe('100px');
236
- expect(panel.style.right).toBe('auto');
237
- });
238
- it('updates FAB position during drag', () => {
239
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
240
- const fab = container.querySelector('[data-syntro-fab]');
241
- fireEvent.pointerDown(fab, { clientX: 12, clientY: 12, pointerId: 1 });
242
- fireEvent.pointerMove(fab, { clientX: 112, clientY: 112, pointerId: 1 });
243
- // FAB should be positioned with FAB_INSET (12px) offset from panel top-left
244
- expect(fab.style.left).toBe('112px'); // 100 + 12
245
- expect(fab.style.top).toBe('112px'); // 100 + 12
246
- });
247
- it('snaps to left edge when dragged close to left boundary', () => {
248
- localStorage.setItem('syntro:editor-panel', JSON.stringify({ x: 200, y: 100, width: 500, height: 600, docked: null }));
249
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
250
- const fab = container.querySelector('[data-syntro-fab]');
251
- // Start drag from the panel's position
252
- fireEvent.pointerDown(fab, { clientX: 212, clientY: 112, pointerId: 1 });
253
- // Move to near left edge (x < SNAP_THRESHOLD=20)
254
- fireEvent.pointerMove(fab, { clientX: 22, clientY: 112, pointerId: 1 });
255
- fireEvent.pointerUp(fab, { clientX: 22, clientY: 112, pointerId: 1 });
256
- // After snap, should be docked left
257
- const stored = JSON.parse(localStorage.getItem('syntro:editor-panel'));
258
- expect(stored.docked).toBe('left');
259
- });
260
- it('snaps to right edge when dragged close to right boundary', () => {
261
- localStorage.setItem('syntro:editor-panel', JSON.stringify({ x: 200, y: 100, width: 500, height: 600, docked: null }));
262
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
263
- const fab = container.querySelector('[data-syntro-fab]');
264
- // Start drag
265
- fireEvent.pointerDown(fab, { clientX: 212, clientY: 112, pointerId: 1 });
266
- // Move to near right edge (x + width >= innerWidth - SNAP_THRESHOLD)
267
- // Panel width is 500, innerWidth is 1280: need x >= 1280 - 20 - 500 = 760
268
- fireEvent.pointerMove(fab, { clientX: 982, clientY: 112, pointerId: 1 });
269
- fireEvent.pointerUp(fab, { clientX: 982, clientY: 112, pointerId: 1 });
270
- const stored = JSON.parse(localStorage.getItem('syntro:editor-panel'));
271
- expect(stored.docked).toBe('right');
272
- });
273
- it('sets undocked geometry when dragged to middle of screen', () => {
274
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
275
- const fab = container.querySelector('[data-syntro-fab]');
276
- fireEvent.pointerDown(fab, { clientX: 12, clientY: 12, pointerId: 1 });
277
- // Move to center area (not near edges)
278
- fireEvent.pointerMove(fab, { clientX: 312, clientY: 112, pointerId: 1 });
279
- fireEvent.pointerUp(fab, { clientX: 312, clientY: 112, pointerId: 1 });
280
- const stored = JSON.parse(localStorage.getItem('syntro:editor-panel'));
281
- expect(stored.docked).toBeNull();
282
- expect(stored.x).toBe(300);
283
- expect(stored.y).toBe(100);
284
- });
285
- });
286
- describe('resize handlers', () => {
287
- it('resizes panel east (wider)', () => {
288
- localStorage.setItem('syntro:editor-panel', JSON.stringify({ x: 100, y: 50, width: 500, height: 600, docked: null }));
289
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
290
- const handle = container.querySelector('[data-resize-dir="e"]');
291
- const panel = container.querySelector('[data-syntro-editor-panel]');
292
- fireEvent.pointerDown(handle, { clientX: 600, clientY: 300, pointerId: 1 });
293
- fireEvent.pointerMove(handle, { clientX: 700, clientY: 300, pointerId: 1 });
294
- // Width should increase by 100
295
- expect(panel.style.width).toBe('600px');
296
- fireEvent.pointerUp(handle, { clientX: 700, clientY: 300, pointerId: 1 });
297
- const stored = JSON.parse(localStorage.getItem('syntro:editor-panel'));
298
- expect(stored.width).toBe(600);
299
- });
300
- it('resizes panel south (taller)', () => {
301
- localStorage.setItem('syntro:editor-panel', JSON.stringify({ x: 100, y: 50, width: 500, height: 600, docked: null }));
302
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
303
- const handle = container.querySelector('[data-resize-dir="s"]');
304
- const panel = container.querySelector('[data-syntro-editor-panel]');
305
- fireEvent.pointerDown(handle, { clientX: 300, clientY: 650, pointerId: 1 });
306
- fireEvent.pointerMove(handle, { clientX: 300, clientY: 750, pointerId: 1 });
307
- expect(panel.style.height).toBe('700px');
308
- fireEvent.pointerUp(handle, { clientX: 300, clientY: 750, pointerId: 1 });
309
- });
310
- it('resizes panel west (moves left edge)', () => {
311
- localStorage.setItem('syntro:editor-panel', JSON.stringify({ x: 200, y: 50, width: 500, height: 600, docked: null }));
312
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
313
- const handle = container.querySelector('[data-resize-dir="w"]');
314
- const panel = container.querySelector('[data-syntro-editor-panel]');
315
- fireEvent.pointerDown(handle, { clientX: 200, clientY: 300, pointerId: 1 });
316
- fireEvent.pointerMove(handle, { clientX: 100, clientY: 300, pointerId: 1 });
317
- // Width increases by 100, x decreases by 100
318
- expect(panel.style.width).toBe('600px');
319
- expect(panel.style.left).toBe('100px');
320
- fireEvent.pointerUp(handle, { clientX: 100, clientY: 300, pointerId: 1 });
321
- });
322
- it('resizes panel north (moves top edge)', () => {
323
- localStorage.setItem('syntro:editor-panel', JSON.stringify({ x: 100, y: 200, width: 500, height: 600, docked: null }));
324
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
325
- const handle = container.querySelector('[data-resize-dir="n"]');
326
- const panel = container.querySelector('[data-syntro-editor-panel]');
327
- fireEvent.pointerDown(handle, { clientX: 300, clientY: 200, pointerId: 1 });
328
- fireEvent.pointerMove(handle, { clientX: 300, clientY: 100, pointerId: 1 });
329
- expect(panel.style.height).toBe('700px');
330
- expect(panel.style.top).toBe('100px');
331
- fireEvent.pointerUp(handle, { clientX: 300, clientY: 100, pointerId: 1 });
332
- });
333
- it('resizes panel southeast (corner)', () => {
334
- localStorage.setItem('syntro:editor-panel', JSON.stringify({ x: 100, y: 50, width: 500, height: 600, docked: null }));
335
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
336
- const handle = container.querySelector('[data-resize-dir="se"]');
337
- const panel = container.querySelector('[data-syntro-editor-panel]');
338
- fireEvent.pointerDown(handle, { clientX: 600, clientY: 650, pointerId: 1 });
339
- fireEvent.pointerMove(handle, { clientX: 700, clientY: 750, pointerId: 1 });
340
- expect(panel.style.width).toBe('600px');
341
- expect(panel.style.height).toBe('700px');
342
- fireEvent.pointerUp(handle, { clientX: 700, clientY: 750, pointerId: 1 });
343
- });
344
- it('resizes panel northwest (corner, moves both edges)', () => {
345
- localStorage.setItem('syntro:editor-panel', JSON.stringify({ x: 200, y: 200, width: 500, height: 600, docked: null }));
346
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
347
- const handle = container.querySelector('[data-resize-dir="nw"]');
348
- const panel = container.querySelector('[data-syntro-editor-panel]');
349
- fireEvent.pointerDown(handle, { clientX: 200, clientY: 200, pointerId: 1 });
350
- fireEvent.pointerMove(handle, { clientX: 100, clientY: 100, pointerId: 1 });
351
- expect(panel.style.width).toBe('600px');
352
- expect(panel.style.height).toBe('700px');
353
- expect(panel.style.left).toBe('100px');
354
- expect(panel.style.top).toBe('100px');
355
- fireEvent.pointerUp(handle, { clientX: 100, clientY: 100, pointerId: 1 });
356
- });
357
- it('enforces minimum width during resize', () => {
358
- localStorage.setItem('syntro:editor-panel', JSON.stringify({ x: 100, y: 50, width: 500, height: 600, docked: null }));
359
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
360
- const handle = container.querySelector('[data-resize-dir="e"]');
361
- const panel = container.querySelector('[data-syntro-editor-panel]');
362
- fireEvent.pointerDown(handle, { clientX: 600, clientY: 300, pointerId: 1 });
363
- // Try to shrink below MIN_WIDTH (480)
364
- fireEvent.pointerMove(handle, { clientX: 200, clientY: 300, pointerId: 1 });
365
- expect(panel.style.width).toBe('480px');
366
- fireEvent.pointerUp(handle, { clientX: 200, clientY: 300, pointerId: 1 });
367
- });
368
- it('enforces minimum height during resize', () => {
369
- localStorage.setItem('syntro:editor-panel', JSON.stringify({ x: 100, y: 50, width: 500, height: 600, docked: null }));
370
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
371
- const handle = container.querySelector('[data-resize-dir="s"]');
372
- const panel = container.querySelector('[data-syntro-editor-panel]');
373
- fireEvent.pointerDown(handle, { clientX: 300, clientY: 650, pointerId: 1 });
374
- // Try to shrink below MIN_HEIGHT (400)
375
- fireEvent.pointerMove(handle, { clientX: 300, clientY: 100, pointerId: 1 });
376
- expect(panel.style.height).toBe('400px');
377
- fireEvent.pointerUp(handle, { clientX: 300, clientY: 100, pointerId: 1 });
378
- });
379
- it('undocks panel when resize is started on a docked panel', () => {
380
- // Start with docked left
381
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
382
- const handle = container.querySelector('[data-resize-dir="e"]');
383
- fireEvent.pointerDown(handle, { clientX: 480, clientY: 300, pointerId: 1 });
384
- // After starting resize on docked panel, it should undock
385
- const stored = JSON.parse(localStorage.getItem('syntro:editor-panel'));
386
- expect(stored.docked).toBeNull();
387
- });
388
- it('ignores pointerMove when no resize is active', () => {
389
- localStorage.setItem('syntro:editor-panel', JSON.stringify({ x: 100, y: 50, width: 500, height: 600, docked: null }));
390
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
391
- const handle = container.querySelector('[data-resize-dir="e"]');
392
- const panel = container.querySelector('[data-syntro-editor-panel]');
393
- // Move without pointerDown
394
- fireEvent.pointerMove(handle, { clientX: 700, clientY: 300, pointerId: 1 });
395
- // Width should not change
396
- expect(panel.style.width).toBe('500px');
397
- });
398
- it('updates FAB position during resize', () => {
399
- localStorage.setItem('syntro:editor-panel', JSON.stringify({ x: 100, y: 50, width: 500, height: 600, docked: null }));
400
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
401
- const handle = container.querySelector('[data-resize-dir="s"]');
402
- const fab = container.querySelector('[data-syntro-fab]');
403
- fireEvent.pointerDown(handle, { clientX: 300, clientY: 650, pointerId: 1 });
404
- fireEvent.pointerMove(handle, { clientX: 300, clientY: 750, pointerId: 1 });
405
- // FAB top should stay at top-left of panel during resize
406
- // FAB top = y + FAB_INSET = 50 + 12 = 62
407
- expect(fab.style.top).toBe('62px');
408
- // FAB left = x + FAB_INSET = 100 + 12 = 112
409
- expect(fab.style.left).toBe('112px');
410
- fireEvent.pointerUp(handle, { clientX: 300, clientY: 750, pointerId: 1 });
411
- });
412
- it('does not commit geometry on pointerUp when no pending geo exists', () => {
413
- localStorage.setItem('syntro:editor-panel', JSON.stringify({ x: 100, y: 50, width: 500, height: 600, docked: null }));
414
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
415
- const handle = container.querySelector('[data-resize-dir="e"]');
416
- // pointerDown then immediate pointerUp without pointerMove
417
- fireEvent.pointerDown(handle, { clientX: 600, clientY: 300, pointerId: 1 });
418
- fireEvent.pointerUp(handle, { clientX: 600, clientY: 300, pointerId: 1 });
419
- const stored = JSON.parse(localStorage.getItem('syntro:editor-panel'));
420
- // Should remain undocked with original dimensions (but undocked since it was docked)
421
- expect(stored.docked).toBeNull();
422
- });
423
- it('resizes northeast corner correctly', () => {
424
- localStorage.setItem('syntro:editor-panel', JSON.stringify({ x: 100, y: 200, width: 500, height: 600, docked: null }));
425
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
426
- const handle = container.querySelector('[data-resize-dir="ne"]');
427
- const panel = container.querySelector('[data-syntro-editor-panel]');
428
- fireEvent.pointerDown(handle, { clientX: 600, clientY: 200, pointerId: 1 });
429
- fireEvent.pointerMove(handle, { clientX: 700, clientY: 100, pointerId: 1 });
430
- // East: width increases by 100
431
- expect(panel.style.width).toBe('600px');
432
- // North: height increases by 100, top decreases by 100
433
- expect(panel.style.height).toBe('700px');
434
- expect(panel.style.top).toBe('100px');
435
- fireEvent.pointerUp(handle, { clientX: 700, clientY: 100, pointerId: 1 });
436
- });
437
- it('resizes southwest corner correctly', () => {
438
- localStorage.setItem('syntro:editor-panel', JSON.stringify({ x: 200, y: 50, width: 500, height: 600, docked: null }));
439
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
440
- const handle = container.querySelector('[data-resize-dir="sw"]');
441
- const panel = container.querySelector('[data-syntro-editor-panel]');
442
- fireEvent.pointerDown(handle, { clientX: 200, clientY: 650, pointerId: 1 });
443
- fireEvent.pointerMove(handle, { clientX: 100, clientY: 750, pointerId: 1 });
444
- // West: width increases by 100, left decreases by 100
445
- expect(panel.style.width).toBe('600px');
446
- expect(panel.style.left).toBe('100px');
447
- // South: height increases by 100
448
- expect(panel.style.height).toBe('700px');
449
- fireEvent.pointerUp(handle, { clientX: 100, clientY: 750, pointerId: 1 });
450
- });
451
- });
452
- describe('viewport clamping', () => {
453
- it('clamps panel position on window resize', () => {
454
- localStorage.setItem('syntro:editor-panel', JSON.stringify({ x: 1200, y: 700, width: 500, height: 600, docked: null }));
455
- render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
456
- // Shrink viewport
457
- Object.defineProperty(window, 'innerWidth', { value: 800, writable: true });
458
- Object.defineProperty(window, 'innerHeight', { value: 600, writable: true });
459
- act(() => {
460
- window.dispatchEvent(new Event('resize'));
461
- });
462
- const stored = JSON.parse(localStorage.getItem('syntro:editor-panel'));
463
- // x should be clamped so FAB stays visible
464
- expect(stored.x).toBeLessThanOrEqual(800 - 56); // vw - FAB_SIZE
465
- });
466
- it('does not clamp docked panels on window resize', () => {
467
- // Docked panels ignore clampToViewport
468
- render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
469
- act(() => {
470
- window.dispatchEvent(new Event('resize'));
471
- });
472
- const stored = JSON.parse(localStorage.getItem('syntro:editor-panel'));
473
- expect(stored.docked).toBe('left');
474
- });
475
- });
476
- it('sets id attribute on panel when panelId is provided', () => {
477
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, panelId: "test-panel", children: _jsx("div", { children: "Content" }) }));
478
- const panel = container.querySelector('#test-panel');
479
- expect(panel).toBeTruthy();
480
- });
481
- it('does not set id attribute on panel when panelId is not provided', () => {
482
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
483
- const panel = container.querySelector('[data-syntro-editor-panel]');
484
- expect(panel.id).toBe('');
485
- });
486
- it('FAB title is "Minimize panel" when open', () => {
487
- const { container } = render(_jsx(EditorPanelShell, { isOpen: true, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
488
- const fab = container.querySelector('[data-syntro-fab]');
489
- expect(fab.title).toBe('Minimize panel');
490
- });
491
- it('FAB title is "Open panel" when closed', () => {
492
- const { container } = render(_jsx(EditorPanelShell, { isOpen: false, onToggle: () => { }, children: _jsx("div", { children: "Content" }) }));
493
- const fab = container.querySelector('[data-syntro-fab]');
494
- expect(fab.title).toBe('Open panel');
495
- });
496
- });
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=EditorSelect.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"EditorSelect.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/EditorSelect.test.tsx"],"names":[],"mappings":""}
@@ -1,22 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { render } from '@testing-library/react';
3
- import { describe, expect, it } from 'vitest';
4
- import { EditorSelect } from '../components/EditorSelect';
5
- describe('EditorSelect', () => {
6
- it('renders label when provided', () => {
7
- const { getByText } = render(_jsx(EditorSelect, { label: "Color", children: _jsx("option", { children: "Red" }) }));
8
- expect(getByText('Color')).toBeTruthy();
9
- });
10
- it('renders a select with children options', () => {
11
- const { container, getByText } = render(_jsxs(EditorSelect, { children: [_jsx("option", { value: "a", children: "Alpha" }), _jsx("option", { value: "b", children: "Beta" })] }));
12
- expect(container.querySelector('select')).toBeTruthy();
13
- expect(getByText('Alpha')).toBeTruthy();
14
- expect(getByText('Beta')).toBeTruthy();
15
- });
16
- it('merges custom className', () => {
17
- const { container } = render(_jsx(EditorSelect, { className: "extra", children: _jsx("option", { children: "X" }) }));
18
- const select = container.querySelector('select');
19
- expect(select.className).toContain('extra');
20
- expect(select.className).toContain('se-w-full');
21
- });
22
- });
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=EditorTextarea.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"EditorTextarea.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/EditorTextarea.test.tsx"],"names":[],"mappings":""}
@@ -1,20 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { render } from '@testing-library/react';
3
- import { describe, expect, it } from 'vitest';
4
- import { EditorTextarea } from '../components/EditorTextarea';
5
- describe('EditorTextarea', () => {
6
- it('renders label when provided', () => {
7
- const { getByText } = render(_jsx(EditorTextarea, { label: "Notes" }));
8
- expect(getByText('Notes')).toBeTruthy();
9
- });
10
- it('renders a textarea element', () => {
11
- const { container } = render(_jsx(EditorTextarea, {}));
12
- expect(container.querySelector('textarea')).toBeTruthy();
13
- });
14
- it('merges custom className', () => {
15
- const { container } = render(_jsx(EditorTextarea, { className: "my-class" }));
16
- const ta = container.querySelector('textarea');
17
- expect(ta.className).toContain('my-class');
18
- expect(ta.className).toContain('se-w-full');
19
- });
20
- });
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=ElementHighlight.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ElementHighlight.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/ElementHighlight.test.tsx"],"names":[],"mappings":""}