@dryui/feedback 0.0.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 (79) hide show
  1. package/dist/components/annotation-marker.svelte +163 -0
  2. package/dist/components/annotation-marker.svelte.d.ts +11 -0
  3. package/dist/components/annotation-popup.svelte +669 -0
  4. package/dist/components/annotation-popup.svelte.d.ts +42 -0
  5. package/dist/components/highlight-overlay.svelte +48 -0
  6. package/dist/components/highlight-overlay.svelte.d.ts +8 -0
  7. package/dist/components/settings-panel.svelte +446 -0
  8. package/dist/components/settings-panel.svelte.d.ts +24 -0
  9. package/dist/components/toolbar.svelte +1111 -0
  10. package/dist/components/toolbar.svelte.d.ts +46 -0
  11. package/dist/constants.d.ts +9 -0
  12. package/dist/constants.js +37 -0
  13. package/dist/feedback.svelte +2879 -0
  14. package/dist/feedback.svelte.d.ts +4 -0
  15. package/dist/index.d.ts +10 -0
  16. package/dist/index.js +7 -0
  17. package/dist/layout-mode/catalog.d.ts +16 -0
  18. package/dist/layout-mode/catalog.js +81 -0
  19. package/dist/layout-mode/component-actions.svelte +84 -0
  20. package/dist/layout-mode/component-actions.svelte.d.ts +18 -0
  21. package/dist/layout-mode/component-picker.svelte +73 -0
  22. package/dist/layout-mode/component-picker.svelte.d.ts +10 -0
  23. package/dist/layout-mode/design-mode.svelte +1115 -0
  24. package/dist/layout-mode/design-mode.svelte.d.ts +24 -0
  25. package/dist/layout-mode/design-palette.svelte +396 -0
  26. package/dist/layout-mode/design-palette.svelte.d.ts +20 -0
  27. package/dist/layout-mode/element-heuristics.d.ts +5 -0
  28. package/dist/layout-mode/element-heuristics.js +51 -0
  29. package/dist/layout-mode/freeze.d.ts +6 -0
  30. package/dist/layout-mode/freeze.js +163 -0
  31. package/dist/layout-mode/generated-library.d.ts +940 -0
  32. package/dist/layout-mode/generated-library.js +1445 -0
  33. package/dist/layout-mode/geometry.d.ts +38 -0
  34. package/dist/layout-mode/geometry.js +133 -0
  35. package/dist/layout-mode/history.d.ts +10 -0
  36. package/dist/layout-mode/history.js +45 -0
  37. package/dist/layout-mode/index.d.ts +23 -0
  38. package/dist/layout-mode/index.js +18 -0
  39. package/dist/layout-mode/live-mount.d.ts +20 -0
  40. package/dist/layout-mode/live-mount.js +70 -0
  41. package/dist/layout-mode/output.d.ts +26 -0
  42. package/dist/layout-mode/output.js +550 -0
  43. package/dist/layout-mode/placement-skeleton.d.ts +9 -0
  44. package/dist/layout-mode/placement-skeleton.js +535 -0
  45. package/dist/layout-mode/rearrange-overlay.svelte +1293 -0
  46. package/dist/layout-mode/rearrange-overlay.svelte.d.ts +18 -0
  47. package/dist/layout-mode/responsive-bar.svelte +39 -0
  48. package/dist/layout-mode/responsive-bar.svelte.d.ts +8 -0
  49. package/dist/layout-mode/route-creator.svelte +70 -0
  50. package/dist/layout-mode/route-creator.svelte.d.ts +8 -0
  51. package/dist/layout-mode/section-detection.d.ts +6 -0
  52. package/dist/layout-mode/section-detection.js +214 -0
  53. package/dist/layout-mode/spatial.d.ts +42 -0
  54. package/dist/layout-mode/spatial.js +156 -0
  55. package/dist/layout-mode/types.d.ts +144 -0
  56. package/dist/layout-mode/types.js +84 -0
  57. package/dist/types.d.ts +157 -0
  58. package/dist/types.js +1 -0
  59. package/dist/utils/dryui-detection.d.ts +1 -0
  60. package/dist/utils/dryui-detection.js +219 -0
  61. package/dist/utils/element-id.d.ts +12 -0
  62. package/dist/utils/element-id.js +333 -0
  63. package/dist/utils/freeze.d.ts +7 -0
  64. package/dist/utils/freeze.js +168 -0
  65. package/dist/utils/output.d.ts +15 -0
  66. package/dist/utils/output.js +245 -0
  67. package/dist/utils/selection.d.ts +22 -0
  68. package/dist/utils/selection.js +58 -0
  69. package/dist/utils/shadow-dom.d.ts +4 -0
  70. package/dist/utils/shadow-dom.js +39 -0
  71. package/dist/utils/storage.d.ts +30 -0
  72. package/dist/utils/storage.js +206 -0
  73. package/dist/utils/svelte-detection.d.ts +8 -0
  74. package/dist/utils/svelte-detection.js +86 -0
  75. package/dist/utils/svelte-meta.d.ts +6 -0
  76. package/dist/utils/svelte-meta.js +69 -0
  77. package/dist/utils/sync.d.ts +18 -0
  78. package/dist/utils/sync.js +62 -0
  79. package/package.json +65 -0
@@ -0,0 +1,333 @@
1
+ const MAX_TEXT_LENGTH = 40;
2
+ const MAX_PATH_DEPTH = 4;
3
+ const MAX_NEARBY_ELEMENTS = 4;
4
+ const SKIP_TAGS = new Set(['html', 'body', '#document']);
5
+ const DEFAULT_STYLE_VALUES = new Set([
6
+ '',
7
+ 'none',
8
+ 'normal',
9
+ 'auto',
10
+ '0px',
11
+ 'rgba(0, 0, 0, 0)',
12
+ 'transparent',
13
+ 'static',
14
+ 'visible',
15
+ ]);
16
+ const TEXT_ELEMENTS = new Set([
17
+ 'a',
18
+ 'b',
19
+ 'blockquote',
20
+ 'caption',
21
+ 'cite',
22
+ 'code',
23
+ 'dd',
24
+ 'dt',
25
+ 'em',
26
+ 'figcaption',
27
+ 'h1',
28
+ 'h2',
29
+ 'h3',
30
+ 'h4',
31
+ 'h5',
32
+ 'h6',
33
+ 'i',
34
+ 'label',
35
+ 'li',
36
+ 'p',
37
+ 'pre',
38
+ 'q',
39
+ 'span',
40
+ 'strong',
41
+ 'td',
42
+ 'th',
43
+ 'time',
44
+ ]);
45
+ const FORM_INPUT_ELEMENTS = new Set(['input', 'select', 'textarea']);
46
+ const MEDIA_ELEMENTS = new Set(['canvas', 'img', 'svg', 'video']);
47
+ const CONTAINER_ELEMENTS = new Set([
48
+ 'article',
49
+ 'aside',
50
+ 'div',
51
+ 'fieldset',
52
+ 'footer',
53
+ 'form',
54
+ 'header',
55
+ 'main',
56
+ 'nav',
57
+ 'ol',
58
+ 'section',
59
+ 'ul',
60
+ ]);
61
+ const FORENSIC_PROPERTIES = [
62
+ 'color',
63
+ 'backgroundColor',
64
+ 'borderColor',
65
+ 'fontSize',
66
+ 'fontWeight',
67
+ 'fontFamily',
68
+ 'lineHeight',
69
+ 'letterSpacing',
70
+ 'textAlign',
71
+ 'width',
72
+ 'height',
73
+ 'padding',
74
+ 'margin',
75
+ 'border',
76
+ 'borderRadius',
77
+ 'display',
78
+ 'position',
79
+ 'top',
80
+ 'right',
81
+ 'bottom',
82
+ 'left',
83
+ 'zIndex',
84
+ 'flexDirection',
85
+ 'justifyContent',
86
+ 'alignItems',
87
+ 'gap',
88
+ 'opacity',
89
+ 'visibility',
90
+ 'overflow',
91
+ 'boxShadow',
92
+ 'transform',
93
+ ];
94
+ function truncate(text, max) {
95
+ const trimmed = text.trim().replace(/\s+/g, ' ');
96
+ if (trimmed.length <= max)
97
+ return trimmed;
98
+ return trimmed.slice(0, max - 3) + '...';
99
+ }
100
+ function getParentElement(el) {
101
+ if (el.parentElement)
102
+ return el.parentElement;
103
+ const root = el.getRootNode();
104
+ if (root instanceof ShadowRoot) {
105
+ return root.host;
106
+ }
107
+ return null;
108
+ }
109
+ function getTagLabel(el) {
110
+ const tag = el.tagName.toLowerCase();
111
+ if (tag === 'img')
112
+ return 'image';
113
+ if (el instanceof SVGElement || tag === 'svg')
114
+ return 'icon';
115
+ return tag;
116
+ }
117
+ function getTextIdentifier(el) {
118
+ const ariaLabel = el.getAttribute('aria-label');
119
+ if (ariaLabel)
120
+ return truncate(ariaLabel, MAX_TEXT_LENGTH);
121
+ if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) {
122
+ if (el.placeholder)
123
+ return truncate(el.placeholder, MAX_TEXT_LENGTH);
124
+ }
125
+ if (el instanceof HTMLImageElement && el.alt) {
126
+ return truncate(el.alt, MAX_TEXT_LENGTH);
127
+ }
128
+ const text = el.textContent?.trim();
129
+ if (text && text.length > 0 && text.length < 200) {
130
+ return truncate(text, MAX_TEXT_LENGTH);
131
+ }
132
+ return undefined;
133
+ }
134
+ function cleanClassName(value) {
135
+ return value.replace(/[_][a-zA-Z0-9]{5,}.*$/, '');
136
+ }
137
+ function getMeaningfulClass(el) {
138
+ return Array.from(el.classList)
139
+ .map((className) => cleanClassName(className))
140
+ .find((className) => className.length > 2 && !/^[a-z]{1,2}$/.test(className));
141
+ }
142
+ function getComputedStyleValue(el, cssPropertyName) {
143
+ if (typeof window === 'undefined' || !(el instanceof HTMLElement))
144
+ return '';
145
+ return window.getComputedStyle(el).getPropertyValue(cssPropertyName).trim();
146
+ }
147
+ function getDetailedStyleProperties(tag, el) {
148
+ if (TEXT_ELEMENTS.has(tag)) {
149
+ return ['color', 'fontSize', 'fontWeight', 'fontFamily', 'lineHeight'];
150
+ }
151
+ if (tag === 'button' || (tag === 'a' && el.getAttribute('role') === 'button')) {
152
+ return ['backgroundColor', 'color', 'padding', 'borderRadius', 'fontSize'];
153
+ }
154
+ if (FORM_INPUT_ELEMENTS.has(tag)) {
155
+ return ['backgroundColor', 'color', 'padding', 'borderRadius', 'fontSize'];
156
+ }
157
+ if (MEDIA_ELEMENTS.has(tag)) {
158
+ return ['width', 'height', 'objectFit', 'borderRadius'];
159
+ }
160
+ if (CONTAINER_ELEMENTS.has(tag)) {
161
+ return ['display', 'padding', 'margin', 'gap', 'backgroundColor'];
162
+ }
163
+ return ['color', 'fontSize', 'margin', 'padding', 'backgroundColor'];
164
+ }
165
+ function toCssPropertyName(property) {
166
+ return property.replace(/([A-Z])/g, '-$1').toLowerCase();
167
+ }
168
+ function getNodeIndex(el) {
169
+ const parent = getParentElement(el);
170
+ if (!parent)
171
+ return 1;
172
+ const siblings = Array.from(parent.children).filter((child) => child.tagName === el.tagName);
173
+ const index = siblings.indexOf(el);
174
+ return index >= 0 ? index + 1 : 1;
175
+ }
176
+ export function identifyElement(el) {
177
+ const tag = getTagLabel(el);
178
+ const path = getElementPath(el);
179
+ const textId = getTextIdentifier(el);
180
+ if (textId) {
181
+ return { name: `${tag} "${textId}"`, path };
182
+ }
183
+ if (el.id) {
184
+ return { name: `${tag} #${el.id}`, path };
185
+ }
186
+ const firstClass = el.classList[0];
187
+ if (firstClass) {
188
+ return { name: `${tag} [${cleanClassName(firstClass)}]`, path };
189
+ }
190
+ return { name: tag, path };
191
+ }
192
+ export function getElementPath(el, maxDepth = MAX_PATH_DEPTH) {
193
+ const parts = [];
194
+ let current = el;
195
+ while (current && parts.length < maxDepth) {
196
+ const tag = current.tagName.toLowerCase();
197
+ if (SKIP_TAGS.has(tag))
198
+ break;
199
+ parts.unshift(tag);
200
+ current = getParentElement(current);
201
+ }
202
+ return parts.join(' > ');
203
+ }
204
+ export function getFullElementPath(el) {
205
+ const parts = [];
206
+ let current = el;
207
+ while (current) {
208
+ const tag = current.tagName.toLowerCase();
209
+ if (tag === 'html') {
210
+ parts.unshift(tag);
211
+ break;
212
+ }
213
+ let identifier = tag;
214
+ if (current.id) {
215
+ identifier = `${tag}#${current.id}`;
216
+ }
217
+ else {
218
+ const className = getMeaningfulClass(current);
219
+ if (className) {
220
+ identifier = `${tag}.${className}`;
221
+ }
222
+ else {
223
+ identifier = `${tag}:nth-of-type(${getNodeIndex(current)})`;
224
+ }
225
+ }
226
+ if (!current.parentElement && current.getRootNode() instanceof ShadowRoot) {
227
+ identifier = `shadow(${identifier})`;
228
+ }
229
+ parts.unshift(identifier);
230
+ current = getParentElement(current);
231
+ }
232
+ return parts.join(' > ');
233
+ }
234
+ export function getNearbyText(el) {
235
+ const texts = [];
236
+ const parent = getParentElement(el);
237
+ if (!parent)
238
+ return '';
239
+ for (const sibling of parent.children) {
240
+ if (sibling === el)
241
+ continue;
242
+ const text = sibling.textContent?.trim();
243
+ if (text && text.length > 0 && text.length < 100) {
244
+ texts.push(truncate(text, 50));
245
+ }
246
+ }
247
+ return texts.join(', ');
248
+ }
249
+ export function getNearbyElements(el) {
250
+ const parent = getParentElement(el);
251
+ if (!parent)
252
+ return '';
253
+ const siblings = Array.from(parent.children).filter((child) => child !== el);
254
+ if (siblings.length === 0)
255
+ return '';
256
+ const labels = siblings.slice(0, MAX_NEARBY_ELEMENTS).map((sibling) => {
257
+ const tag = sibling.tagName.toLowerCase();
258
+ const className = getMeaningfulClass(sibling);
259
+ const text = tag === 'button' || tag === 'a' ? sibling.textContent?.trim().slice(0, 15) : '';
260
+ if (text) {
261
+ return `${tag}${className ? `.${className}` : ''} "${text}"`;
262
+ }
263
+ return `${tag}${className ? `.${className}` : ''}`;
264
+ });
265
+ const parentTag = parent.tagName.toLowerCase();
266
+ const parentClass = getMeaningfulClass(parent);
267
+ const total = parent.children.length;
268
+ const suffix = ` (${total} total in ${parentClass ? `.${parentClass}` : parentTag})`;
269
+ return labels.join(', ') + suffix;
270
+ }
271
+ export function getElementClasses(el) {
272
+ return Array.from(el.classList)
273
+ .map((className) => cleanClassName(className))
274
+ .filter((className, index, array) => className.length > 0 && array.indexOf(className) === index)
275
+ .join(' ');
276
+ }
277
+ export function getDetailedComputedStyles(el) {
278
+ if (typeof window === 'undefined' || !(el instanceof HTMLElement))
279
+ return {};
280
+ const tag = el.tagName.toLowerCase();
281
+ const result = {};
282
+ for (const property of getDetailedStyleProperties(tag, el)) {
283
+ const value = getComputedStyleValue(el, toCssPropertyName(property));
284
+ if (value && !DEFAULT_STYLE_VALUES.has(value)) {
285
+ result[property] = value;
286
+ }
287
+ }
288
+ return result;
289
+ }
290
+ export function getForensicComputedStyles(el) {
291
+ if (typeof window === 'undefined' || !(el instanceof HTMLElement))
292
+ return '';
293
+ const parts = [];
294
+ for (const property of FORENSIC_PROPERTIES) {
295
+ const cssPropertyName = toCssPropertyName(property);
296
+ const value = getComputedStyleValue(el, cssPropertyName);
297
+ if (value && !DEFAULT_STYLE_VALUES.has(value)) {
298
+ parts.push(`${cssPropertyName}: ${value}`);
299
+ }
300
+ }
301
+ return parts.join('; ');
302
+ }
303
+ export function getAccessibilityInfo(el) {
304
+ const parts = [];
305
+ const role = el.getAttribute('role');
306
+ const ariaLabel = el.getAttribute('aria-label');
307
+ const ariaDescription = el.getAttribute('aria-describedby');
308
+ const ariaExpanded = el.getAttribute('aria-expanded');
309
+ const ariaPressed = el.getAttribute('aria-pressed');
310
+ const ariaChecked = el.getAttribute('aria-checked');
311
+ const tabIndex = el.getAttribute('tabindex');
312
+ if (role)
313
+ parts.push(`role="${role}"`);
314
+ if (ariaLabel)
315
+ parts.push(`aria-label="${ariaLabel}"`);
316
+ if (ariaDescription)
317
+ parts.push(`aria-describedby="${ariaDescription}"`);
318
+ if (ariaExpanded)
319
+ parts.push(`aria-expanded=${ariaExpanded}`);
320
+ if (ariaPressed)
321
+ parts.push(`aria-pressed=${ariaPressed}`);
322
+ if (ariaChecked)
323
+ parts.push(`aria-checked=${ariaChecked}`);
324
+ if (tabIndex)
325
+ parts.push(`tabindex=${tabIndex}`);
326
+ if (el instanceof HTMLImageElement && el.alt) {
327
+ parts.push(`alt="${truncate(el.alt, MAX_TEXT_LENGTH)}"`);
328
+ }
329
+ if (el.matches('a, button, input, select, summary, textarea, [role="button"], [role="link"], [tabindex]')) {
330
+ parts.push('focusable');
331
+ }
332
+ return parts.join(', ');
333
+ }
@@ -0,0 +1,7 @@
1
+ export declare const originalSetTimeout: typeof setTimeout;
2
+ export declare const originalSetInterval: typeof setInterval;
3
+ export declare const originalRequestAnimationFrame: typeof requestAnimationFrame;
4
+ export declare function freezeAnimations(): void;
5
+ export declare function unfreezeAnimations(): void;
6
+ export declare function toggleAnimationsFrozen(): boolean;
7
+ export declare function animationsAreFrozen(): boolean;
@@ -0,0 +1,168 @@
1
+ const EXCLUDE_SELECTOR = '[data-dryui-feedback]';
2
+ const STATE_KEY = '__dryui_feedback_freeze__';
3
+ const STYLE_ID = 'dryui-feedback-freeze-styles';
4
+ function getServerState() {
5
+ return {
6
+ frozen: false,
7
+ installed: true,
8
+ origSetTimeout: setTimeout,
9
+ origSetInterval: setInterval,
10
+ origRAF: (callback) => {
11
+ callback(0);
12
+ return 0;
13
+ },
14
+ pausedAnimations: [],
15
+ queuedTimeouts: [],
16
+ queuedRAFs: [],
17
+ };
18
+ }
19
+ function getState() {
20
+ if (typeof window === 'undefined')
21
+ return getServerState();
22
+ const record = window;
23
+ if (!record[STATE_KEY]) {
24
+ record[STATE_KEY] = {
25
+ frozen: false,
26
+ installed: false,
27
+ origSetTimeout: window.setTimeout.bind(window),
28
+ origSetInterval: window.setInterval.bind(window),
29
+ origRAF: window.requestAnimationFrame.bind(window),
30
+ pausedAnimations: [],
31
+ queuedTimeouts: [],
32
+ queuedRAFs: [],
33
+ };
34
+ }
35
+ return record[STATE_KEY];
36
+ }
37
+ const state = getState();
38
+ if (typeof window !== 'undefined' && !state.installed) {
39
+ window.setTimeout = ((handler, timeout, ...args) => state.origSetTimeout((...callbackArgs) => {
40
+ if (typeof handler === 'string')
41
+ return;
42
+ if (state.frozen) {
43
+ state.queuedTimeouts.push(() => handler(...callbackArgs));
44
+ return;
45
+ }
46
+ handler(...callbackArgs);
47
+ }, timeout, ...args));
48
+ window.setInterval = ((handler, timeout, ...args) => state.origSetInterval((...callbackArgs) => {
49
+ if (typeof handler === 'string')
50
+ return;
51
+ if (!state.frozen) {
52
+ handler(...callbackArgs);
53
+ }
54
+ }, timeout, ...args));
55
+ window.requestAnimationFrame = ((callback) => state.origRAF((timestamp) => {
56
+ if (state.frozen) {
57
+ state.queuedRAFs.push(callback);
58
+ return;
59
+ }
60
+ callback(timestamp);
61
+ }));
62
+ state.installed = true;
63
+ }
64
+ function excludedAnimationTarget(target) {
65
+ return Boolean(target?.closest(EXCLUDE_SELECTOR));
66
+ }
67
+ export const originalSetTimeout = state.origSetTimeout;
68
+ export const originalSetInterval = state.origSetInterval;
69
+ export const originalRequestAnimationFrame = state.origRAF;
70
+ export function freezeAnimations() {
71
+ if (typeof document === 'undefined' || state.frozen)
72
+ return;
73
+ state.frozen = true;
74
+ state.queuedTimeouts = [];
75
+ state.queuedRAFs = [];
76
+ let style = document.getElementById(STYLE_ID);
77
+ if (!style) {
78
+ style = document.createElement('style');
79
+ style.id = STYLE_ID;
80
+ document.head.appendChild(style);
81
+ }
82
+ style.textContent = `
83
+ html[data-dryui-feedback-frozen='true'] body *:not(${EXCLUDE_SELECTOR}):not(${EXCLUDE_SELECTOR} *)::before,
84
+ html[data-dryui-feedback-frozen='true'] body *:not(${EXCLUDE_SELECTOR}):not(${EXCLUDE_SELECTOR} *)::after,
85
+ html[data-dryui-feedback-frozen='true'] body *:not(${EXCLUDE_SELECTOR}):not(${EXCLUDE_SELECTOR} *) {
86
+ animation-play-state: paused;
87
+ transition-duration: 0s;
88
+ transition-delay: 0s;
89
+ }
90
+ `;
91
+ document.documentElement.dataset.dryuiFeedbackFrozen = 'true';
92
+ try {
93
+ state.pausedAnimations = [];
94
+ document.getAnimations().forEach((animation) => {
95
+ if (animation.playState !== 'running')
96
+ return;
97
+ const target = animation.effect?.target;
98
+ if (excludedAnimationTarget(target))
99
+ return;
100
+ animation.pause();
101
+ state.pausedAnimations.push(animation);
102
+ });
103
+ }
104
+ catch {
105
+ // getAnimations is not universally available
106
+ }
107
+ document.querySelectorAll('video').forEach((video) => {
108
+ if (!video.paused) {
109
+ video.dataset.dryuiFeedbackWasPaused = 'false';
110
+ video.pause();
111
+ }
112
+ });
113
+ }
114
+ export function unfreezeAnimations() {
115
+ if (typeof document === 'undefined' || !state.frozen)
116
+ return;
117
+ state.frozen = false;
118
+ delete document.documentElement.dataset.dryuiFeedbackFrozen;
119
+ document.getElementById(STYLE_ID)?.remove();
120
+ const queuedTimeouts = state.queuedTimeouts;
121
+ state.queuedTimeouts = [];
122
+ for (const callback of queuedTimeouts) {
123
+ state.origSetTimeout(() => {
124
+ if (state.frozen) {
125
+ state.queuedTimeouts.push(callback);
126
+ return;
127
+ }
128
+ callback();
129
+ }, 0);
130
+ }
131
+ const queuedRAFs = state.queuedRAFs;
132
+ state.queuedRAFs = [];
133
+ for (const callback of queuedRAFs) {
134
+ state.origRAF((timestamp) => {
135
+ if (state.frozen) {
136
+ state.queuedRAFs.push(callback);
137
+ return;
138
+ }
139
+ callback(timestamp);
140
+ });
141
+ }
142
+ for (const animation of state.pausedAnimations) {
143
+ try {
144
+ animation.play();
145
+ }
146
+ catch {
147
+ // animation may have been discarded by the browser
148
+ }
149
+ }
150
+ state.pausedAnimations = [];
151
+ document.querySelectorAll('video').forEach((video) => {
152
+ if (video.dataset.dryuiFeedbackWasPaused === 'false') {
153
+ video.play().catch(() => { });
154
+ delete video.dataset.dryuiFeedbackWasPaused;
155
+ }
156
+ });
157
+ }
158
+ export function toggleAnimationsFrozen() {
159
+ if (state.frozen) {
160
+ unfreezeAnimations();
161
+ return false;
162
+ }
163
+ freezeAnimations();
164
+ return true;
165
+ }
166
+ export function animationsAreFrozen() {
167
+ return state.frozen;
168
+ }
@@ -0,0 +1,15 @@
1
+ import type { Annotation, DesignPlacement, OutputDetail, RearrangeState } from '../types.js';
2
+ export declare const OUTPUT_DETAIL_OPTIONS: Array<{
3
+ value: OutputDetail;
4
+ label: string;
5
+ }>;
6
+ export interface GenerateOutputOptions {
7
+ designPlacements?: DesignPlacement[];
8
+ rearrangeState?: RearrangeState | null;
9
+ blankCanvas?: boolean;
10
+ wireframePurpose?: string;
11
+ }
12
+ export declare function generateFeedbackOutput(annotations: Annotation[], pathname: string, detail: OutputDetail): string;
13
+ export declare function generateDesignOutput(placements: DesignPlacement[], detail: OutputDetail, options?: Pick<GenerateOutputOptions, 'blankCanvas' | 'wireframePurpose'>): string;
14
+ export declare function generateRearrangeOutput(state: RearrangeState, detail: OutputDetail): string;
15
+ export declare function generateOutput(annotations: Annotation[], pathname: string, detail: OutputDetail, options?: GenerateOutputOptions): string;