pith-ui 0.1.1 → 0.2.0-app.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AI.md +33 -8
- package/API.md +424 -268
- package/APP-API.md +2019 -0
- package/APP.md +137 -0
- package/README.md +37 -4
- package/dist/app/files.d.ts +68 -0
- package/dist/app/files.d.ts.map +1 -0
- package/dist/app/files.js +177 -0
- package/dist/app/files.js.map +1 -0
- package/dist/app/index.d.ts +57 -0
- package/dist/app/index.d.ts.map +1 -0
- package/dist/app/index.js +300 -0
- package/dist/app/index.js.map +1 -0
- package/dist/app/internal.d.ts +31 -0
- package/dist/app/internal.d.ts.map +1 -0
- package/dist/app/internal.js +2 -0
- package/dist/app/internal.js.map +1 -0
- package/dist/app/resources.d.ts +89 -0
- package/dist/app/resources.d.ts.map +1 -0
- package/dist/app/resources.js +190 -0
- package/dist/app/resources.js.map +1 -0
- package/dist/app/session.d.ts +14 -0
- package/dist/app/session.d.ts.map +1 -0
- package/dist/app/session.js +12 -0
- package/dist/app/session.js.map +1 -0
- package/dist/app/settings.d.ts +109 -0
- package/dist/app/settings.d.ts.map +1 -0
- package/dist/app/settings.js +279 -0
- package/dist/app/settings.js.map +1 -0
- package/dist/app/workspace.d.ts +228 -0
- package/dist/app/workspace.d.ts.map +1 -0
- package/dist/app/workspace.js +402 -0
- package/dist/app/workspace.js.map +1 -0
- package/dist/composer.d.ts.map +1 -1
- package/dist/composer.js +37 -27
- package/dist/composer.js.map +1 -1
- package/dist/content/conversation-reader.d.ts.map +1 -1
- package/dist/content/conversation-reader.js +8 -1
- package/dist/content/conversation-reader.js.map +1 -1
- package/dist/content/conversation-view.d.ts.map +1 -1
- package/dist/content/conversation-view.js +34 -8
- package/dist/content/conversation-view.js.map +1 -1
- package/dist/content/image-viewer.d.ts.map +1 -1
- package/dist/content/image-viewer.js +11 -3
- package/dist/content/image-viewer.js.map +1 -1
- package/dist/content/paged-preview.d.ts +1 -1
- package/dist/content/paged-preview.d.ts.map +1 -1
- package/dist/content/paged-preview.js +4 -2
- package/dist/content/paged-preview.js.map +1 -1
- package/dist/content/views.d.ts +3 -0
- package/dist/content/views.d.ts.map +1 -1
- package/dist/content/views.js +110 -41
- package/dist/content/views.js.map +1 -1
- package/dist/content/welcome.d.ts.map +1 -1
- package/dist/content/welcome.js +5 -2
- package/dist/content/welcome.js.map +1 -1
- package/dist/dom.js +1 -1
- package/dist/dom.js.map +1 -1
- package/dist/files/panels.d.ts +2 -0
- package/dist/files/panels.d.ts.map +1 -1
- package/dist/files/panels.js +202 -128
- package/dist/files/panels.js.map +1 -1
- package/dist/files/systems.d.ts.map +1 -1
- package/dist/files/systems.js +37 -64
- package/dist/files/systems.js.map +1 -1
- package/dist/forms/actions.d.ts +24 -2
- package/dist/forms/actions.d.ts.map +1 -1
- package/dist/forms/actions.js +54 -25
- package/dist/forms/actions.js.map +1 -1
- package/dist/forms/custom-connection.d.ts.map +1 -1
- package/dist/forms/custom-connection.js +3 -2
- package/dist/forms/custom-connection.js.map +1 -1
- package/dist/forms/history.d.ts +1 -1
- package/dist/forms/history.d.ts.map +1 -1
- package/dist/forms/history.js +78 -15
- package/dist/forms/history.js.map +1 -1
- package/dist/forms/identity.d.ts.map +1 -1
- package/dist/forms/identity.js +9 -25
- package/dist/forms/identity.js.map +1 -1
- package/dist/forms/model-editor.js +3 -3
- package/dist/forms/model-editor.js.map +1 -1
- package/dist/forms/panels.d.ts +9 -2
- package/dist/forms/panels.d.ts.map +1 -1
- package/dist/forms/panels.js +79 -88
- package/dist/forms/panels.js.map +1 -1
- package/dist/forms/provider-login.d.ts.map +1 -1
- package/dist/forms/provider-login.js +20 -36
- package/dist/forms/provider-login.js.map +1 -1
- package/dist/forms/resource-editor.js +5 -4
- package/dist/forms/resource-editor.js.map +1 -1
- package/dist/foundations.d.ts +1 -1
- package/dist/foundations.d.ts.map +1 -1
- package/dist/foundations.js +22 -38
- package/dist/foundations.js.map +1 -1
- package/dist/navigation/context-menu.d.ts +7 -1
- package/dist/navigation/context-menu.d.ts.map +1 -1
- package/dist/navigation/context-menu.js +60 -57
- package/dist/navigation/context-menu.js.map +1 -1
- package/dist/navigation/navigation.d.ts +13 -0
- package/dist/navigation/navigation.d.ts.map +1 -1
- package/dist/navigation/navigation.js +96 -130
- package/dist/navigation/navigation.js.map +1 -1
- package/dist/operation.d.ts +12 -0
- package/dist/operation.d.ts.map +1 -0
- package/dist/operation.js +49 -0
- package/dist/operation.js.map +1 -0
- package/dist/primitives.d.ts +8 -1
- package/dist/primitives.d.ts.map +1 -1
- package/dist/primitives.js +114 -143
- package/dist/primitives.js.map +1 -1
- package/dist/reconcile.d.ts +11 -0
- package/dist/reconcile.d.ts.map +1 -0
- package/dist/reconcile.js +36 -0
- package/dist/reconcile.js.map +1 -0
- package/dist/select.d.ts +14 -0
- package/dist/select.d.ts.map +1 -0
- package/dist/select.js +304 -0
- package/dist/select.js.map +1 -0
- package/dist/styles.css +439 -370
- package/dist/surface.d.ts +31 -0
- package/dist/surface.d.ts.map +1 -1
- package/dist/surface.js +193 -3
- package/dist/surface.js.map +1 -1
- package/dist/tasks/approval.d.ts.map +1 -1
- package/dist/tasks/approval.js +83 -45
- package/dist/tasks/approval.js.map +1 -1
- package/dist/tasks/permission-element.d.ts +3 -0
- package/dist/tasks/permission-element.d.ts.map +1 -0
- package/dist/tasks/permission-element.js +10 -0
- package/dist/tasks/permission-element.js.map +1 -0
- package/dist/tasks/permission.d.ts.map +1 -1
- package/dist/tasks/permission.js +37 -18
- package/dist/tasks/permission.js.map +1 -1
- package/dist/tasks/runtime.d.ts.map +1 -1
- package/dist/tasks/runtime.js +32 -15
- package/dist/tasks/runtime.js.map +1 -1
- package/dist/workspace.d.ts.map +1 -1
- package/dist/workspace.js +93 -40
- package/dist/workspace.js.map +1 -1
- package/package.json +42 -8
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { escape, icon } from '../dom.js';
|
|
2
2
|
import { installDialogLifecycle } from '../surface.js';
|
|
3
|
+
import { adoptFeedback } from '../foundations.js';
|
|
3
4
|
let sequence = 0;
|
|
4
5
|
/** A modal above either a generated-file preview or a conversation attachment. */
|
|
5
6
|
export function createImageViewer(options = {}) {
|
|
@@ -14,6 +15,7 @@ export function createImageViewer(options = {}) {
|
|
|
14
15
|
const viewport = dialog.querySelector('.pui-image-viewer-viewport');
|
|
15
16
|
const title = dialog.querySelector('h2');
|
|
16
17
|
const status = dialog.querySelector('[data-image-scale]');
|
|
18
|
+
const feedback = adoptFeedback(status, { presentation: 'inline', autoHide: false });
|
|
17
19
|
const listeners = new AbortController();
|
|
18
20
|
const signal = listeners.signal;
|
|
19
21
|
let destroyed = false;
|
|
@@ -25,7 +27,7 @@ export function createImageViewer(options = {}) {
|
|
|
25
27
|
scale = Math.min(1, viewport.clientWidth / image.naturalWidth, viewport.clientHeight / image.naturalHeight);
|
|
26
28
|
image.style.width = `${image.naturalWidth * scale}px`;
|
|
27
29
|
image.style.height = `${image.naturalHeight * scale}px`;
|
|
28
|
-
|
|
30
|
+
feedback.update({ message: `${Math.round(scale * 100)}% · ${image.naturalWidth} × ${image.naturalHeight}`, tone: 'info' });
|
|
29
31
|
}
|
|
30
32
|
function resize(factor) { fitted = false; const next = scale * factor; if (Number.isFinite(next) && next > 0)
|
|
31
33
|
scale = next; update(); }
|
|
@@ -43,9 +45,12 @@ export function createImageViewer(options = {}) {
|
|
|
43
45
|
image.removeAttribute('style');
|
|
44
46
|
source = null;
|
|
45
47
|
} });
|
|
46
|
-
|
|
48
|
+
dialog.addEventListener('keydown', (event) => {
|
|
47
49
|
if (!dialog.open || event.isComposing || event.metaKey || event.ctrlKey || event.altKey)
|
|
48
50
|
return;
|
|
51
|
+
const target = event.target instanceof Element ? event.target : null;
|
|
52
|
+
if (target?.closest('dialog') !== dialog || target.closest('input, textarea, [contenteditable]:not([contenteditable="false"])'))
|
|
53
|
+
return;
|
|
49
54
|
if (event.key === '+' || event.key === '=') {
|
|
50
55
|
event.preventDefault();
|
|
51
56
|
resize(1.25);
|
|
@@ -71,7 +76,7 @@ export function createImageViewer(options = {}) {
|
|
|
71
76
|
image.alt = input.alt || '';
|
|
72
77
|
scale = 1;
|
|
73
78
|
fitted = true;
|
|
74
|
-
|
|
79
|
+
feedback.update({ message: 'Loading…', tone: 'info' });
|
|
75
80
|
image.src = input.src;
|
|
76
81
|
lifecycle.open();
|
|
77
82
|
viewport.scrollTop = viewport.scrollLeft = 0;
|
|
@@ -88,9 +93,12 @@ export function createImageViewer(options = {}) {
|
|
|
88
93
|
source = null;
|
|
89
94
|
destroyed = true;
|
|
90
95
|
observer.disconnect();
|
|
96
|
+
feedback.destroy();
|
|
91
97
|
lifecycle.destroy();
|
|
92
98
|
listeners.abort();
|
|
93
99
|
dialog.replaceChildren();
|
|
100
|
+
if (!options.dialog)
|
|
101
|
+
dialog.remove();
|
|
94
102
|
},
|
|
95
103
|
};
|
|
96
104
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image-viewer.js","sourceRoot":"","sources":["../../src/content/image-viewer.ts"],"names":[],"mappings":"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","sourcesContent":["import { escape, icon } from '../dom.js';\nimport { installDialogLifecycle } from '../surface.js';\n\nexport interface ImageViewerOptions { dialog?: HTMLDialogElement; headingId?: string }\nexport interface ImageViewerInput { src: string; alt?: string; returnFocus?: HTMLElement }\nlet sequence = 0;\n\n/** A modal above either a generated-file preview or a conversation attachment. */\nexport function createImageViewer(options: ImageViewerOptions = {}) {\n const dialog = options.dialog || document.createElement('dialog');\n const headingId = options.headingId || `pui-image-title-${++sequence}`;\n dialog.classList.add('pui-modal', 'pui-image-viewer');\n dialog.setAttribute('aria-labelledby', headingId);\n dialog.innerHTML = `<div class=\"pui-modal-heading\"><h2 id=\"${escape(headingId)}\">Image</h2><button type=\"button\" class=\"pui-quiet-icon\" data-image-close aria-label=\"Close image\">${icon('close')}</button></div>\n <div class=\"pui-image-viewer-viewport\"><img alt=\"\" /></div>\n <div class=\"pui-image-viewer-toolbar\"><span data-image-scale role=\"status\"></span><div><button type=\"button\" class=\"pui-secondary-button\" data-image-out aria-label=\"Zoom out\">−</button><button type=\"button\" class=\"pui-secondary-button\" data-image-in aria-label=\"Zoom in\">+</button><button type=\"button\" class=\"pui-secondary-button\" data-image-fit>Fit</button><button type=\"button\" class=\"pui-secondary-button\" data-image-original>Original size</button></div></div>`;\n const image = dialog.querySelector<HTMLImageElement>('img')!;\n const viewport = dialog.querySelector<HTMLElement>('.pui-image-viewer-viewport')!;\n const title = dialog.querySelector<HTMLElement>('h2')!;\n const status = dialog.querySelector<HTMLElement>('[data-image-scale]')!;\n const listeners = new AbortController();\n const signal = listeners.signal;\n let destroyed = false;\n let scale = 1, fitted = true, source: HTMLElement | null = null;\n function update(): void {\n if (destroyed || !image.naturalWidth) return;\n if (fitted) scale = Math.min(1, viewport.clientWidth / image.naturalWidth, viewport.clientHeight / image.naturalHeight);\n image.style.width = `${image.naturalWidth * scale}px`;\n image.style.height = `${image.naturalHeight * scale}px`;\n status.textContent = `${Math.round(scale * 100)}% · ${image.naturalWidth} × ${image.naturalHeight}`;\n }\n function resize(factor: number): void { fitted = false; const next = scale * factor; if (Number.isFinite(next) && next > 0) scale = next; update(); }\n dialog.querySelector('[data-image-fit]')!.addEventListener('click', () => { fitted = true; update(); }, { signal });\n dialog.querySelector('[data-image-original]')!.addEventListener('click', () => { fitted = false; scale = 1; update(); }, { signal });\n dialog.querySelector('[data-image-in]')!.addEventListener('click', () => resize(1.25), { signal });\n dialog.querySelector('[data-image-out]')!.addEventListener('click', () => resize(1 / 1.25), { signal });\n dialog.querySelector('[data-image-close]')!.addEventListener('click', () => dialog.close(), { signal });\n image.addEventListener('load', update, { signal });\n const observer = new ResizeObserver(() => { if (dialog.open && fitted) update(); });\n observer.observe(viewport);\n const lifecycle = installDialogLifecycle(dialog, { returnFocus: () => source, onClose: () => {\n image.removeAttribute('src');\n image.removeAttribute('style');\n source = null;\n } });\n document.addEventListener('keydown', (event) => {\n if (!dialog.open || event.isComposing || event.metaKey || event.ctrlKey || event.altKey) return;\n if (event.key === '+' || event.key === '=') { event.preventDefault(); resize(1.25); }\n if (event.key === '-') { event.preventDefault(); resize(1 / 1.25); }\n }, { signal });\n function close(): void { lifecycle.close(); }\n return {\n element: dialog,\n open(target: HTMLImageElement | ImageViewerInput): void {\n if (destroyed) return;\n const input = target instanceof HTMLImageElement\n ? target.getAttribute('src') && !target.classList.contains('pui-image-unavailable') ? { src: target.src, alt: target.alt, returnFocus: target } : null\n : target;\n if (!input?.src) return;\n source = input.returnFocus || null;\n title.textContent = input.alt || 'Image';\n image.alt = input.alt || '';\n scale = 1;\n fitted = true;\n status.textContent = 'Loading…';\n image.src = input.src;\n lifecycle.open();\n viewport.scrollTop = viewport.scrollLeft = 0;\n update();\n },\n close,\n destroy(): void {\n if (destroyed) return;\n close();\n image.removeAttribute('src');\n image.removeAttribute('style');\n source?.focus({ preventScroll: true });\n source = null;\n destroyed = true;\n observer.disconnect();\n lifecycle.destroy();\n listeners.abort();\n dialog.replaceChildren();\n },\n };\n}\n\nexport function installImageViewer(dialog: HTMLDialogElement, options: { triggerRoot?: HTMLElement } = {}) {\n const viewer = createImageViewer({ dialog, headingId: dialog.getAttribute('aria-labelledby') || undefined });\n const abort = new AbortController();\n const trigger = (event: Event) => {\n const image = event.target;\n if (!(image instanceof HTMLImageElement) || !image.matches('.pui-history-image, .pui-draft-image img, .pui-file-preview-image')) return;\n if (event instanceof KeyboardEvent && (event.isComposing || !['Enter', ' '].includes(event.key))) return;\n if (event instanceof KeyboardEvent) event.preventDefault();\n viewer.open(image);\n };\n options.triggerRoot?.addEventListener('click', trigger, { signal: abort.signal });\n options.triggerRoot?.addEventListener('keydown', trigger, { signal: abort.signal });\n return { ...viewer, destroy() { abort.abort(); viewer.destroy(); } };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"image-viewer.js","sourceRoot":"","sources":["../../src/content/image-viewer.ts"],"names":[],"mappings":"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","sourcesContent":["import { escape, icon } from '../dom.js';\nimport { installDialogLifecycle } from '../surface.js';\nimport {adoptFeedback} from '../foundations.js';\n\nexport interface ImageViewerOptions { dialog?: HTMLDialogElement; headingId?: string }\nexport interface ImageViewerInput { src: string; alt?: string; returnFocus?: HTMLElement }\nlet sequence = 0;\n\n/** A modal above either a generated-file preview or a conversation attachment. */\nexport function createImageViewer(options: ImageViewerOptions = {}) {\n const dialog = options.dialog || document.createElement('dialog');\n const headingId = options.headingId || `pui-image-title-${++sequence}`;\n dialog.classList.add('pui-modal', 'pui-image-viewer');\n dialog.setAttribute('aria-labelledby', headingId);\n dialog.innerHTML = `<div class=\"pui-modal-heading\"><h2 id=\"${escape(headingId)}\">Image</h2><button type=\"button\" class=\"pui-quiet-icon\" data-image-close aria-label=\"Close image\">${icon('close')}</button></div>\n <div class=\"pui-image-viewer-viewport\"><img alt=\"\" /></div>\n <div class=\"pui-image-viewer-toolbar\"><span data-image-scale role=\"status\"></span><div><button type=\"button\" class=\"pui-secondary-button\" data-image-out aria-label=\"Zoom out\">−</button><button type=\"button\" class=\"pui-secondary-button\" data-image-in aria-label=\"Zoom in\">+</button><button type=\"button\" class=\"pui-secondary-button\" data-image-fit>Fit</button><button type=\"button\" class=\"pui-secondary-button\" data-image-original>Original size</button></div></div>`;\n const image = dialog.querySelector<HTMLImageElement>('img')!;\n const viewport = dialog.querySelector<HTMLElement>('.pui-image-viewer-viewport')!;\n const title = dialog.querySelector<HTMLElement>('h2')!;\n const status = dialog.querySelector<HTMLElement>('[data-image-scale]')!;\n const feedback = adoptFeedback(status, {presentation:'inline', autoHide:false});\n const listeners = new AbortController();\n const signal = listeners.signal;\n let destroyed = false;\n let scale = 1, fitted = true, source: HTMLElement | null = null;\n function update(): void {\n if (destroyed || !image.naturalWidth) return;\n if (fitted) scale = Math.min(1, viewport.clientWidth / image.naturalWidth, viewport.clientHeight / image.naturalHeight);\n image.style.width = `${image.naturalWidth * scale}px`;\n image.style.height = `${image.naturalHeight * scale}px`;\n feedback.update({message:`${Math.round(scale * 100)}% · ${image.naturalWidth} × ${image.naturalHeight}`, tone:'info'});\n }\n function resize(factor: number): void { fitted = false; const next = scale * factor; if (Number.isFinite(next) && next > 0) scale = next; update(); }\n dialog.querySelector('[data-image-fit]')!.addEventListener('click', () => { fitted = true; update(); }, { signal });\n dialog.querySelector('[data-image-original]')!.addEventListener('click', () => { fitted = false; scale = 1; update(); }, { signal });\n dialog.querySelector('[data-image-in]')!.addEventListener('click', () => resize(1.25), { signal });\n dialog.querySelector('[data-image-out]')!.addEventListener('click', () => resize(1 / 1.25), { signal });\n dialog.querySelector('[data-image-close]')!.addEventListener('click', () => dialog.close(), { signal });\n image.addEventListener('load', update, { signal });\n const observer = new ResizeObserver(() => { if (dialog.open && fitted) update(); });\n observer.observe(viewport);\n const lifecycle = installDialogLifecycle(dialog, { returnFocus: () => source, onClose: () => {\n image.removeAttribute('src');\n image.removeAttribute('style');\n source = null;\n } });\n dialog.addEventListener('keydown', (event) => {\n if (!dialog.open || event.isComposing || event.metaKey || event.ctrlKey || event.altKey) return;\n const target = event.target instanceof Element ? event.target : null;\n if (target?.closest('dialog') !== dialog || target.closest('input, textarea, [contenteditable]:not([contenteditable=\"false\"])')) return;\n if (event.key === '+' || event.key === '=') { event.preventDefault(); resize(1.25); }\n if (event.key === '-') { event.preventDefault(); resize(1 / 1.25); }\n }, { signal });\n function close(): void { lifecycle.close(); }\n return {\n element: dialog,\n open(target: HTMLImageElement | ImageViewerInput): void {\n if (destroyed) return;\n const input = target instanceof HTMLImageElement\n ? target.getAttribute('src') && !target.classList.contains('pui-image-unavailable') ? { src: target.src, alt: target.alt, returnFocus: target } : null\n : target;\n if (!input?.src) return;\n source = input.returnFocus || null;\n title.textContent = input.alt || 'Image';\n image.alt = input.alt || '';\n scale = 1;\n fitted = true;\n feedback.update({message:'Loading…', tone:'info'});\n image.src = input.src;\n lifecycle.open();\n viewport.scrollTop = viewport.scrollLeft = 0;\n update();\n },\n close,\n destroy(): void {\n if (destroyed) return;\n close();\n image.removeAttribute('src');\n image.removeAttribute('style');\n source?.focus({ preventScroll: true });\n source = null;\n destroyed = true;\n observer.disconnect();\n feedback.destroy();\n lifecycle.destroy();\n listeners.abort();\n dialog.replaceChildren();\n if (!options.dialog) dialog.remove();\n },\n };\n}\n\nexport function installImageViewer(dialog: HTMLDialogElement, options: { triggerRoot?: HTMLElement } = {}) {\n const viewer = createImageViewer({ dialog, headingId: dialog.getAttribute('aria-labelledby') || undefined });\n const abort = new AbortController();\n const trigger = (event: Event) => {\n const image = event.target;\n if (!(image instanceof HTMLImageElement) || !image.matches('.pui-history-image, .pui-draft-image img, .pui-file-preview-image')) return;\n if (event instanceof KeyboardEvent && (event.isComposing || !['Enter', ' '].includes(event.key))) return;\n if (event instanceof KeyboardEvent) event.preventDefault();\n viewer.open(image);\n };\n options.triggerRoot?.addEventListener('click', trigger, { signal: abort.signal });\n options.triggerRoot?.addEventListener('keydown', trigger, { signal: abort.signal });\n return { ...viewer, destroy() { abort.abort(); viewer.destroy(); } };\n}\n"]}
|
|
@@ -8,7 +8,7 @@ export interface PagedPreviewState {
|
|
|
8
8
|
}
|
|
9
9
|
export interface PagedPreviewOptions extends PagedPreviewState {
|
|
10
10
|
container?: HTMLElement;
|
|
11
|
-
onCopyCode?: (text: string) => void;
|
|
11
|
+
onCopyCode?: (text: string, button: HTMLButtonElement) => void;
|
|
12
12
|
}
|
|
13
13
|
export declare function createPagedPreview(options: PagedPreviewOptions): UIBlock<PagedPreviewState>;
|
|
14
14
|
export declare function mountPagedPreview(container: HTMLElement, text: string, kind: PreviewKind): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paged-preview.d.ts","sourceRoot":"","sources":["../../src/content/paged-preview.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAK1C,eAAO,MAAM,gBAAgB,QAAa,CAAC;AAE3C,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,SAAmB,GAAG,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAgBvG;AAED,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC;AACvD,MAAM,WAAW,iBAAiB;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,WAAW,CAAA;CAAE;AACtE,MAAM,WAAW,mBAAoB,SAAQ,iBAAiB;IAAG,SAAS,CAAC,EAAE,WAAW,CAAC;IAAC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE;
|
|
1
|
+
{"version":3,"file":"paged-preview.d.ts","sourceRoot":"","sources":["../../src/content/paged-preview.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAK1C,eAAO,MAAM,gBAAgB,QAAa,CAAC;AAE3C,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,SAAmB,GAAG,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAgBvG;AAED,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC;AACvD,MAAM,WAAW,iBAAiB;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,WAAW,CAAA;CAAE;AACtE,MAAM,WAAW,mBAAoB,SAAQ,iBAAiB;IAAG,SAAS,CAAC,EAAE,WAAW,CAAC;IAAC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,KAAK,IAAI,CAAA;CAAE;AAE1J,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA0B3F;AAGD,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,IAAI,CAG/F"}
|
|
@@ -32,8 +32,10 @@ export function createPagedPreview(options) {
|
|
|
32
32
|
let dispose = renderPreview(element, current.text, current.kind);
|
|
33
33
|
const click = (event) => {
|
|
34
34
|
const button = event.target.closest('[data-copy-code]');
|
|
35
|
-
if (button && !button.disabled && element.contains(button))
|
|
36
|
-
|
|
35
|
+
if (button && !button.disabled && element.contains(button) && options.onCopyCode) {
|
|
36
|
+
event.stopPropagation();
|
|
37
|
+
void options.onCopyCode(button.closest('.pui-code-block')?.querySelector('code')?.textContent || '', button);
|
|
38
|
+
}
|
|
37
39
|
};
|
|
38
40
|
if (options.onCopyCode)
|
|
39
41
|
element.addEventListener('click', click);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paged-preview.js","sourceRoot":"","sources":["../../src/content/paged-preview.ts"],"names":[],"mappings":"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","sourcesContent":["import { renderDiff, renderMarkdown } from './markdown.js';\nimport type { UIBlock } from '../core.js';\nimport { adoptProductParts } from '../foundations.js';\n\n// A rendering window, not a file acceptance cap. Large Markdown is shown as\n// original text so page boundaries cannot change the meaning of fenced code.\nexport const previewPageBytes = 256 * 1024;\n\nexport function previewPageRanges(bytes: Uint8Array, window = previewPageBytes): Array<[number, number]> {\n if (window < 4) throw new RangeError('A preview window must fit a UTF-8 character');\n const ranges: Array<[number, number]> = [];\n for (let start = 0; start < bytes.length;) {\n let end = Math.min(start + window, bytes.length);\n while (end < bytes.length && (bytes[end] & 0xc0) === 0x80) end--;\n if (end < bytes.length) {\n // Prefer complete lines without turning a long line into tiny pages.\n for (let i = end - 1; i >= start + window / 2 - 1; i--) {\n if (bytes[i] === 10) { end = i + 1; break; }\n }\n }\n ranges.push([start, end]);\n start = end;\n }\n return ranges.length ? ranges : [[0, 0]];\n}\n\nexport type PreviewKind = 'text' | 'markdown' | 'diff';\nexport interface PagedPreviewState { text: string; kind: PreviewKind }\nexport interface PagedPreviewOptions extends PagedPreviewState { container?: HTMLElement; onCopyCode?: (text: string) => void }\n\nexport function createPagedPreview(options: PagedPreviewOptions): UIBlock<PagedPreviewState> {\n const element = options.container || document.createElement('div');\n let current = { text: options.text, kind: options.kind };\n let disposed = false;\n let dispose = renderPreview(element, current.text, current.kind);\n const click = (event: Event) => {\n const button = (event.target as Element).closest<HTMLButtonElement>('[data-copy-code]');\n if (button && !button.disabled && element.contains(button)) options.onCopyCode?.(button.closest('.pui-code-block')?.querySelector('code')?.textContent || '');\n };\n if (options.onCopyCode) element.addEventListener('click', click);\n return {\n element,\n update(state): void {\n if (disposed || (state.text === current.text && state.kind === current.kind)) return;\n dispose();\n current = { ...state };\n dispose = renderPreview(element, state.text, state.kind);\n },\n destroy(): void {\n if (disposed) return;\n disposed = true;\n dispose();\n element.removeEventListener('click', click);\n element.replaceChildren();\n },\n };\n}\n\nconst mounted = new WeakMap<HTMLElement, UIBlock<PagedPreviewState>>();\nexport function mountPagedPreview(container: HTMLElement, text: string, kind: PreviewKind): void {\n mounted.get(container)?.destroy();\n mounted.set(container, createPagedPreview({ container, text, kind }));\n}\n\nfunction renderPreview(container: HTMLElement, text: string, kind: PreviewKind): () => void {\n const bytes = new TextEncoder().encode(text);\n const ranges = previewPageRanges(bytes);\n const content = document.createElement(kind === 'markdown' && ranges.length === 1 ? 'div' : 'pre');\n content.className = kind === 'diff' ? 'pui-approval-diff' : content.tagName === 'DIV' ? 'pui-markdown' : 'pui-file-preview-text';\n if (kind === 'diff') content.setAttribute('aria-label', 'Proposed file changes');\n const toolbar = document.createElement('div');\n toolbar.className = 'pui-feature-toolbar pui-preview-pagination';\n const previous = document.createElement('button');\n const next = document.createElement('button');\n const status = document.createElement('span');\n status.setAttribute('aria-live', 'polite');\n for (const button of [previous, next]) { button.type = 'button'; button.className = 'pui-secondary-button'; }\n previous.textContent = 'Previous'; next.textContent = 'Next';\n toolbar.append(previous, status, next);\n const parts = adoptProductParts(container);\n let page = 0;\n const decoder = new TextDecoder('utf-8', { fatal: true });\n const render = () => {\n const [start, end] = ranges[page];\n const value = decoder.decode(bytes.subarray(start, end));\n if (kind === 'markdown' && ranges.length === 1) content.innerHTML = renderMarkdown(value);\n else if (kind === 'diff') content.innerHTML = renderDiff(value);\n else content.textContent = value;\n parts.action(previous).update({ disabled: page === 0 }); parts.action(next).update({ disabled: page === ranges.length - 1 });\n status.textContent = `${page + 1} / ${ranges.length}${kind === 'markdown' && ranges.length > 1 ? ' · Plain text preview' : ''}`;\n content.scrollTop = 0;\n parts.update();\n };\n previous.onclick = () => { page--; render(); };\n next.onclick = () => { page++; render(); };\n container.replaceChildren(...(ranges.length > 1 ? [toolbar, content] : [content]));\n render();\n return () => { parts.destroy(); previous.onclick = null; next.onclick = null; };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"paged-preview.js","sourceRoot":"","sources":["../../src/content/paged-preview.ts"],"names":[],"mappings":"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","sourcesContent":["import { renderDiff, renderMarkdown } from './markdown.js';\nimport type { UIBlock } from '../core.js';\nimport { adoptProductParts } from '../foundations.js';\n\n// A rendering window, not a file acceptance cap. Large Markdown is shown as\n// original text so page boundaries cannot change the meaning of fenced code.\nexport const previewPageBytes = 256 * 1024;\n\nexport function previewPageRanges(bytes: Uint8Array, window = previewPageBytes): Array<[number, number]> {\n if (window < 4) throw new RangeError('A preview window must fit a UTF-8 character');\n const ranges: Array<[number, number]> = [];\n for (let start = 0; start < bytes.length;) {\n let end = Math.min(start + window, bytes.length);\n while (end < bytes.length && (bytes[end] & 0xc0) === 0x80) end--;\n if (end < bytes.length) {\n // Prefer complete lines without turning a long line into tiny pages.\n for (let i = end - 1; i >= start + window / 2 - 1; i--) {\n if (bytes[i] === 10) { end = i + 1; break; }\n }\n }\n ranges.push([start, end]);\n start = end;\n }\n return ranges.length ? ranges : [[0, 0]];\n}\n\nexport type PreviewKind = 'text' | 'markdown' | 'diff';\nexport interface PagedPreviewState { text: string; kind: PreviewKind }\nexport interface PagedPreviewOptions extends PagedPreviewState { container?: HTMLElement; onCopyCode?: (text: string, button: HTMLButtonElement) => void }\n\nexport function createPagedPreview(options: PagedPreviewOptions): UIBlock<PagedPreviewState> {\n const element = options.container || document.createElement('div');\n let current = { text: options.text, kind: options.kind };\n let disposed = false;\n let dispose = renderPreview(element, current.text, current.kind);\n const click = (event: Event) => {\n const button = (event.target as Element).closest<HTMLButtonElement>('[data-copy-code]');\n if (button && !button.disabled && element.contains(button) && options.onCopyCode) {event.stopPropagation(); void options.onCopyCode(button.closest('.pui-code-block')?.querySelector('code')?.textContent || '', button);}\n };\n if (options.onCopyCode) element.addEventListener('click', click);\n return {\n element,\n update(state): void {\n if (disposed || (state.text === current.text && state.kind === current.kind)) return;\n dispose();\n current = { ...state };\n dispose = renderPreview(element, state.text, state.kind);\n },\n destroy(): void {\n if (disposed) return;\n disposed = true;\n dispose();\n element.removeEventListener('click', click);\n element.replaceChildren();\n },\n };\n}\n\nconst mounted = new WeakMap<HTMLElement, UIBlock<PagedPreviewState>>();\nexport function mountPagedPreview(container: HTMLElement, text: string, kind: PreviewKind): void {\n mounted.get(container)?.destroy();\n mounted.set(container, createPagedPreview({ container, text, kind }));\n}\n\nfunction renderPreview(container: HTMLElement, text: string, kind: PreviewKind): () => void {\n const bytes = new TextEncoder().encode(text);\n const ranges = previewPageRanges(bytes);\n const content = document.createElement(kind === 'markdown' && ranges.length === 1 ? 'div' : 'pre');\n content.className = kind === 'diff' ? 'pui-approval-diff' : content.tagName === 'DIV' ? 'pui-markdown' : 'pui-file-preview-text';\n if (kind === 'diff') content.setAttribute('aria-label', 'Proposed file changes');\n const toolbar = document.createElement('div');\n toolbar.className = 'pui-feature-toolbar pui-preview-pagination';\n const previous = document.createElement('button');\n const next = document.createElement('button');\n const status = document.createElement('span');\n status.setAttribute('aria-live', 'polite');\n for (const button of [previous, next]) { button.type = 'button'; button.className = 'pui-secondary-button'; }\n previous.textContent = 'Previous'; next.textContent = 'Next';\n toolbar.append(previous, status, next);\n const parts = adoptProductParts(container);\n let page = 0;\n const decoder = new TextDecoder('utf-8', { fatal: true });\n const render = () => {\n const [start, end] = ranges[page];\n const value = decoder.decode(bytes.subarray(start, end));\n if (kind === 'markdown' && ranges.length === 1) content.innerHTML = renderMarkdown(value);\n else if (kind === 'diff') content.innerHTML = renderDiff(value);\n else content.textContent = value;\n parts.action(previous).update({ disabled: page === 0 }); parts.action(next).update({ disabled: page === ranges.length - 1 });\n status.textContent = `${page + 1} / ${ranges.length}${kind === 'markdown' && ranges.length > 1 ? ' · Plain text preview' : ''}`;\n content.scrollTop = 0;\n parts.update();\n };\n previous.onclick = () => { page--; render(); };\n next.onclick = () => { page++; render(); };\n container.replaceChildren(...(ranges.length > 1 ? [toolbar, content] : [content]));\n render();\n return () => { parts.destroy(); previous.onclick = null; next.onclick = null; };\n}\n"]}
|
package/dist/content/views.d.ts
CHANGED
|
@@ -6,4 +6,7 @@ export type View = {
|
|
|
6
6
|
};
|
|
7
7
|
export declare function reconcileViews(parent: HTMLElement, views: View[]): void;
|
|
8
8
|
export declare function clearViews(parent: HTMLElement): void;
|
|
9
|
+
/** Private patching of library-produced, sanitized markup. This is not a public
|
|
10
|
+
* HTML renderer: product factories retain their own templates and state. */
|
|
11
|
+
export declare function patchChildren(parent: HTMLElement, source: ParentNode): void;
|
|
9
12
|
//# sourceMappingURL=views.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"views.d.ts","sourceRoot":"","sources":["../../src/content/views.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"views.d.ts","sourceRoot":"","sources":["../../src/content/views.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,IAAI,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,CAAA;CAAE,CAAC;AAO7F,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI,CAwBvE;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAAsD;AAE3G;4EAC4E;AAC5E,wBAAgB,aAAa,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAI3E"}
|
package/dist/content/views.js
CHANGED
|
@@ -1,53 +1,122 @@
|
|
|
1
|
+
import { reconcileKeyed } from '../reconcile.js';
|
|
1
2
|
let version = 0;
|
|
2
3
|
const entries = new WeakMap();
|
|
3
4
|
// Reuse unchanged nodes: selection, focus, decoded images, feedback and code
|
|
4
5
|
// scrolling belong to the reader, and must survive another message's updates.
|
|
5
6
|
export function reconcileViews(parent, views) {
|
|
6
7
|
const previous = entries.get(parent) || new Map();
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
entry.
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
for (const image of element.querySelectorAll('[data-image-key]')) {
|
|
26
|
-
const saved = images.get(image.dataset.imageKey);
|
|
27
|
-
if (saved)
|
|
28
|
-
image.replaceWith(saved);
|
|
29
|
-
}
|
|
30
|
-
scroll = Array.from(entry.element.querySelectorAll('pre'), (pre) => pre.scrollLeft);
|
|
31
|
-
entry.element.replaceWith(element);
|
|
32
|
-
if (cursor === entry.element)
|
|
33
|
-
cursor = element;
|
|
8
|
+
const render = (view) => {
|
|
9
|
+
const template = document.createElement('template');
|
|
10
|
+
template.innerHTML = view.html();
|
|
11
|
+
const element = template.content.firstElementChild;
|
|
12
|
+
element.dataset.renderVersion = String(++version);
|
|
13
|
+
return element;
|
|
14
|
+
};
|
|
15
|
+
reconcileKeyed(parent, previous, views, {
|
|
16
|
+
key: view => view.key, element: entry => entry.element,
|
|
17
|
+
create: view => ({ element: render(view), signature: view.signature }),
|
|
18
|
+
update(entry, view) {
|
|
19
|
+
if (entry.signature !== view.signature) {
|
|
20
|
+
const next = render(view);
|
|
21
|
+
if (entry.element.tagName === next.tagName)
|
|
22
|
+
patchElement(entry.element, next);
|
|
23
|
+
else {
|
|
24
|
+
entry.element.replaceWith(next);
|
|
25
|
+
entry.element = next;
|
|
34
26
|
}
|
|
35
|
-
entry =
|
|
27
|
+
entry.signature = view.signature;
|
|
36
28
|
}
|
|
29
|
+
if (view.children)
|
|
30
|
+
reconcileViews(entry.element.querySelector('[data-view-children]'), view.children);
|
|
31
|
+
},
|
|
32
|
+
destroy() { },
|
|
33
|
+
});
|
|
34
|
+
entries.set(parent, previous);
|
|
35
|
+
}
|
|
36
|
+
export function clearViews(parent) { parent.replaceChildren(); entries.delete(parent); }
|
|
37
|
+
/** Private patching of library-produced, sanitized markup. This is not a public
|
|
38
|
+
* HTML renderer: product factories retain their own templates and state. */
|
|
39
|
+
export function patchChildren(parent, source) {
|
|
40
|
+
const focused = parent.ownerDocument.activeElement;
|
|
41
|
+
patchNodes(parent, source);
|
|
42
|
+
if (focused instanceof HTMLElement && focused.isConnected && parent.contains(focused) && parent.ownerDocument.activeElement !== focused)
|
|
43
|
+
focused.focus({ preventScroll: true });
|
|
44
|
+
}
|
|
45
|
+
function key(node) {
|
|
46
|
+
if (!(node instanceof Element))
|
|
47
|
+
return;
|
|
48
|
+
for (const attribute of ['data-image-key', 'data-message-action', 'data-welcome-action', 'data-prompt', 'data-view-children', 'data-copy-code', 'id']) {
|
|
49
|
+
if (node.hasAttribute(attribute))
|
|
50
|
+
return `${node.tagName}:${attribute}:${node.getAttribute(attribute)}`;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function matches(current, next) {
|
|
54
|
+
if (current.nodeType !== next.nodeType)
|
|
55
|
+
return false;
|
|
56
|
+
if (current instanceof Element && next instanceof Element)
|
|
57
|
+
return current.tagName === next.tagName && key(current) === key(next);
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
function patchNodes(parent, source) {
|
|
61
|
+
let cursor = parent.firstChild;
|
|
62
|
+
for (const next of [...source.childNodes]) {
|
|
63
|
+
let current = cursor;
|
|
64
|
+
if (!current || !matches(current, next))
|
|
65
|
+
current = key(next) ? [...parent.childNodes].find(node => matches(node, next)) ?? null : null;
|
|
66
|
+
if (!current) {
|
|
67
|
+
parent.insertBefore(next, cursor);
|
|
68
|
+
continue;
|
|
37
69
|
}
|
|
38
|
-
if (
|
|
39
|
-
parent.insertBefore(
|
|
40
|
-
if (
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
70
|
+
if (current !== cursor)
|
|
71
|
+
parent.insertBefore(current, cursor);
|
|
72
|
+
if (current instanceof HTMLElement && next instanceof HTMLElement)
|
|
73
|
+
patchElement(current, next);
|
|
74
|
+
else if (current instanceof SVGElement && next instanceof SVGElement) {
|
|
75
|
+
patchAttributes(current, next);
|
|
76
|
+
patchNodes(current, next);
|
|
77
|
+
}
|
|
78
|
+
else if (current instanceof Text && next instanceof Text && current.data !== next.data) {
|
|
79
|
+
// Replacing only the changed span retains Range offsets in an unchanged
|
|
80
|
+
// streamed prefix, unlike assigning textContent or replacing the Text.
|
|
81
|
+
let prefix = 0, suffix = 0;
|
|
82
|
+
while (prefix < current.length && prefix < next.length && current.data[prefix] === next.data[prefix])
|
|
83
|
+
prefix++;
|
|
84
|
+
while (suffix < current.length - prefix && suffix < next.length - prefix && current.data[current.length - suffix - 1] === next.data[next.length - suffix - 1])
|
|
85
|
+
suffix++;
|
|
86
|
+
current.replaceData(prefix, current.length - prefix - suffix, next.data.slice(prefix, next.length - suffix));
|
|
87
|
+
}
|
|
88
|
+
cursor = current.nextSibling;
|
|
89
|
+
}
|
|
90
|
+
while (cursor) {
|
|
91
|
+
const next = cursor.nextSibling;
|
|
92
|
+
cursor.remove();
|
|
93
|
+
cursor = next;
|
|
46
94
|
}
|
|
47
|
-
for (const [key, entry] of previous)
|
|
48
|
-
if (!current.has(key))
|
|
49
|
-
entry.element.remove();
|
|
50
|
-
entries.set(parent, current);
|
|
51
95
|
}
|
|
52
|
-
|
|
96
|
+
function patchAttributes(current, next) {
|
|
97
|
+
for (const attribute of [...current.attributes]) {
|
|
98
|
+
if (current instanceof HTMLDetailsElement && attribute.name === 'open')
|
|
99
|
+
continue;
|
|
100
|
+
if (!next.hasAttribute(attribute.name))
|
|
101
|
+
current.removeAttribute(attribute.name);
|
|
102
|
+
}
|
|
103
|
+
for (const attribute of [...next.attributes]) {
|
|
104
|
+
if (current instanceof HTMLDetailsElement && attribute.name === 'open')
|
|
105
|
+
continue;
|
|
106
|
+
if (current.getAttribute(attribute.name) !== attribute.value)
|
|
107
|
+
current.setAttribute(attribute.name, attribute.value);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
function patchElement(current, next) {
|
|
111
|
+
if ((current instanceof HTMLImageElement && current.dataset.imageKey && current.dataset.imageKey === next.dataset.imageKey) || (current instanceof HTMLButtonElement && current.dataset.copyPending === 'true'))
|
|
112
|
+
return;
|
|
113
|
+
const scrollTop = current.scrollTop, scrollLeft = current.scrollLeft;
|
|
114
|
+
patchAttributes(current, next);
|
|
115
|
+
if (!current.hasAttribute('data-view-children'))
|
|
116
|
+
patchChildren(current, next);
|
|
117
|
+
if (current.scrollTop !== scrollTop)
|
|
118
|
+
current.scrollTop = scrollTop;
|
|
119
|
+
if (current.scrollLeft !== scrollLeft)
|
|
120
|
+
current.scrollLeft = scrollLeft;
|
|
121
|
+
}
|
|
53
122
|
//# sourceMappingURL=views.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"views.js","sourceRoot":"","sources":["../../src/content/views.ts"],"names":[],"mappings":"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","sourcesContent":["export type View = { key: string; signature: string; html: () => string; children?: View[] };\ntype Entry = { element: HTMLElement; signature: string };\nlet version = 0;\nconst entries = new WeakMap<HTMLElement, Map<string, Entry>>();\n\n// Reuse unchanged nodes: selection, focus, decoded images, feedback and code\n// scrolling belong to the reader, and must survive another message's updates.\nexport function reconcileViews(parent: HTMLElement, views: View[]): void {\n const previous = entries.get(parent) || new Map<string, Entry>();\n const current = new Map<string, Entry>();\n let cursor = parent.firstElementChild;\n for (const view of views) {\n let entry = previous.get(view.key);\n let scroll: number[] | undefined;\n if (!entry || entry.signature !== view.signature) {\n const template = document.createElement('template');\n template.innerHTML = view.html();\n const element = template.content.firstElementChild as HTMLElement;\n element.dataset.renderVersion = String(++version);\n if (entry && view.children) {\n // Group summaries may change while completed tool results stay intact.\n entry.element.querySelector('summary')!.replaceWith(element.querySelector('summary')!);\n entry.signature = view.signature;\n } else {\n if (entry) {\n const images = new Map(Array.from(entry.element.querySelectorAll<HTMLImageElement>('[data-image-key]'), (image) => [image.dataset.imageKey, image]));\n for (const image of element.querySelectorAll<HTMLImageElement>('[data-image-key]')) {\n const saved = images.get(image.dataset.imageKey);\n if (saved) image.replaceWith(saved);\n }\n scroll = Array.from(entry.element.querySelectorAll('pre'), (pre) => pre.scrollLeft);\n entry.element.replaceWith(element);\n if (cursor === entry.element) cursor = element;\n }\n entry = { element, signature: view.signature };\n }\n }\n if (entry.element !== cursor) parent.insertBefore(entry.element, cursor);\n if (scroll) entry.element.querySelectorAll('pre').forEach((pre, index) => { pre.scrollLeft = scroll![index] || 0; });\n cursor = entry.element.nextElementSibling;\n if (view.children) reconcileViews(entry.element.querySelector<HTMLElement>('[data-view-children]')!, view.children);\n current.set(view.key, entry);\n }\n for (const [key, entry] of previous) if (!current.has(key)) entry.element.remove();\n entries.set(parent, current);\n}\n\nexport function clearViews(parent: HTMLElement): void { parent.replaceChildren(); entries.delete(parent); }\n"]}
|
|
1
|
+
{"version":3,"file":"views.js","sourceRoot":"","sources":["../../src/content/views.ts"],"names":[],"mappings":"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","sourcesContent":["import {reconcileKeyed} from '../reconcile.js';\n\nexport type View = { key: string; signature: string; html: () => string; children?: View[] };\ntype Entry = { element: HTMLElement; signature: string };\nlet version = 0;\nconst entries = new WeakMap<HTMLElement, Map<string, Entry>>();\n\n// Reuse unchanged nodes: selection, focus, decoded images, feedback and code\n// scrolling belong to the reader, and must survive another message's updates.\nexport function reconcileViews(parent: HTMLElement, views: View[]): void {\n const previous = entries.get(parent) || new Map<string, Entry>();\n const render = (view: View): HTMLElement => {\n const template = document.createElement('template');\n template.innerHTML = view.html();\n const element = template.content.firstElementChild as HTMLElement;\n element.dataset.renderVersion = String(++version);\n return element;\n };\n reconcileKeyed(parent, previous, views, {\n key: view => view.key, element: entry => entry.element,\n create: view => ({element:render(view), signature:view.signature}),\n update(entry, view) {\n if (entry.signature !== view.signature) {\n const next = render(view);\n if (entry.element.tagName === next.tagName) patchElement(entry.element, next);\n else {entry.element.replaceWith(next); entry.element = next;}\n entry.signature = view.signature;\n }\n if (view.children) reconcileViews(entry.element.querySelector<HTMLElement>('[data-view-children]')!, view.children);\n },\n destroy() {},\n });\n entries.set(parent, previous);\n}\n\nexport function clearViews(parent: HTMLElement): void { parent.replaceChildren(); entries.delete(parent); }\n\n/** Private patching of library-produced, sanitized markup. This is not a public\n * HTML renderer: product factories retain their own templates and state. */\nexport function patchChildren(parent: HTMLElement, source: ParentNode): void {\n const focused = parent.ownerDocument.activeElement;\n patchNodes(parent, source);\n if (focused instanceof HTMLElement && focused.isConnected && parent.contains(focused) && parent.ownerDocument.activeElement !== focused) focused.focus({preventScroll:true});\n}\n\nfunction key(node: Node): string | undefined {\n if (!(node instanceof Element)) return;\n for (const attribute of ['data-image-key', 'data-message-action', 'data-welcome-action', 'data-prompt', 'data-view-children', 'data-copy-code', 'id']) {\n if (node.hasAttribute(attribute)) return `${node.tagName}:${attribute}:${node.getAttribute(attribute)}`;\n }\n}\nfunction matches(current: Node, next: Node): boolean {\n if (current.nodeType !== next.nodeType) return false;\n if (current instanceof Element && next instanceof Element) return current.tagName === next.tagName && key(current) === key(next);\n return true;\n}\nfunction patchNodes(parent: Element, source: ParentNode): void {\n let cursor: ChildNode | null = parent.firstChild;\n for (const next of [...source.childNodes]) {\n let current = cursor;\n if (!current || !matches(current, next)) current = key(next) ? [...parent.childNodes].find(node => matches(node, next)) ?? null : null;\n if (!current) {parent.insertBefore(next, cursor); continue;}\n if (current !== cursor) parent.insertBefore(current, cursor);\n if (current instanceof HTMLElement && next instanceof HTMLElement) patchElement(current, next);\n else if (current instanceof SVGElement && next instanceof SVGElement) {patchAttributes(current, next); patchNodes(current, next);}\n else if (current instanceof Text && next instanceof Text && current.data !== next.data) {\n // Replacing only the changed span retains Range offsets in an unchanged\n // streamed prefix, unlike assigning textContent or replacing the Text.\n let prefix = 0, suffix = 0;\n while (prefix < current.length && prefix < next.length && current.data[prefix] === next.data[prefix]) prefix++;\n while (suffix < current.length - prefix && suffix < next.length - prefix && current.data[current.length - suffix - 1] === next.data[next.length - suffix - 1]) suffix++;\n current.replaceData(prefix, current.length - prefix - suffix, next.data.slice(prefix, next.length - suffix));\n }\n cursor = current.nextSibling;\n }\n while (cursor) {const next = cursor.nextSibling; cursor.remove(); cursor = next;}\n}\nfunction patchAttributes(current: Element, next: Element): void {\n for (const attribute of [...current.attributes]) {\n if (current instanceof HTMLDetailsElement && attribute.name === 'open') continue;\n if (!next.hasAttribute(attribute.name)) current.removeAttribute(attribute.name);\n }\n for (const attribute of [...next.attributes]) {\n if (current instanceof HTMLDetailsElement && attribute.name === 'open') continue;\n if (current.getAttribute(attribute.name) !== attribute.value) current.setAttribute(attribute.name, attribute.value);\n }\n}\nfunction patchElement(current: HTMLElement, next: HTMLElement): void {\n if ((current instanceof HTMLImageElement && current.dataset.imageKey && current.dataset.imageKey === next.dataset.imageKey) || (current instanceof HTMLButtonElement && current.dataset.copyPending === 'true')) return;\n const scrollTop = current.scrollTop, scrollLeft = current.scrollLeft;\n patchAttributes(current, next);\n if (!current.hasAttribute('data-view-children')) patchChildren(current, next);\n if (current.scrollTop !== scrollTop) current.scrollTop = scrollTop;\n if (current.scrollLeft !== scrollLeft) current.scrollLeft = scrollLeft;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"welcome.d.ts","sourceRoot":"","sources":["../../src/content/welcome.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"welcome.d.ts","sourceRoot":"","sources":["../../src/content/welcome.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAG1C,MAAM,WAAW,YAAY;IAC3B,SAAS,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,OAAO,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;CACnB;AACD,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,GAAG,UAAU,GAAG,WAAW,KAAK,IAAI,CAAC;IAChE,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,YAAY,CAAC,CAuCrF"}
|
package/dist/content/welcome.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { escape, icon } from '../dom.js';
|
|
2
|
+
import { patchChildren } from './views.js';
|
|
2
3
|
export function createWelcomeView(options = {}) {
|
|
3
4
|
const element = options.container || document.createElement('div');
|
|
4
5
|
let destroyed = false;
|
|
@@ -28,7 +29,8 @@ export function createWelcomeView(options = {}) {
|
|
|
28
29
|
signature = next;
|
|
29
30
|
const workspace = state.workspace;
|
|
30
31
|
const ready = !!workspace && state.hasApiKey;
|
|
31
|
-
|
|
32
|
+
const template = document.createElement('template');
|
|
33
|
+
template.innerHTML = `<div class="pui-welcome-mark"></div>
|
|
32
34
|
<p class="pui-eyebrow">YOUR LOCAL WORK COMPANION</p>
|
|
33
35
|
<h1>${ready ? 'What are we working on?' : 'Your work. A little more possible.'}</h1>
|
|
34
36
|
<p class="pui-welcome-description">An agent that works alongside you, with your files<br class="pui-desktop-break"> and the tools you choose.</p>
|
|
@@ -40,7 +42,8 @@ export function createWelcomeView(options = {}) {
|
|
|
40
42
|
<div class="pui-suggestions"><button type="button" data-prompt="Explore this workspace and give me a concise overview of its files.">${icon('file')}Explore my workspace</button><button type="button" data-prompt="Help me plan a task. Start by asking what I want to accomplish.">${icon('chat')}Think through a task</button><button type="button" data-prompt="I'd like help creating a document in this workspace. Ask me what it should cover.">${icon('plus')}Create something</button></div>`}
|
|
41
43
|
<div class="pui-welcome-footnote">${icon('shield')}Local workspace. Your choice of model.</div>`;
|
|
42
44
|
if (options.logo)
|
|
43
|
-
|
|
45
|
+
template.content.querySelector('.pui-welcome-mark').append(options.logo.cloneNode(true));
|
|
46
|
+
patchChildren(element, template.content);
|
|
44
47
|
},
|
|
45
48
|
destroy() {
|
|
46
49
|
if (destroyed)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"welcome.js","sourceRoot":"","sources":["../../src/content/welcome.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"welcome.js","sourceRoot":"","sources":["../../src/content/welcome.ts"],"names":[],"mappings":"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","sourcesContent":["import { escape, icon } from '../dom.js';\nimport type { UIBlock } from '../core.js';\nimport {patchChildren} from './views.js';\n\nexport interface WelcomeState {\n workspace?: { name: string; path: string };\n hasApiKey: boolean;\n hasConnections: boolean;\n modelName: string;\n}\nexport interface WelcomeOptions {\n container?: HTMLElement;\n logo?: Node;\n onAction?: (action: 'model' | 'settings' | 'workspace') => void;\n onPrompt?: (text: string) => void;\n}\n\nexport function createWelcomeView(options: WelcomeOptions = {}): UIBlock<WelcomeState> {\n const element = options.container || document.createElement('div');\n let destroyed = false; let signature = '';\n const click = (event: Event) => {\n const action = (event.target as Element).closest<HTMLElement>('[data-welcome-action], [data-prompt]');\n if (!action || !element.contains(action) || (action instanceof HTMLButtonElement && action.disabled)) return;\n if (action.dataset.prompt && options.onPrompt) {event.stopPropagation(); options.onPrompt(action.dataset.prompt);}\n else if (action.dataset.welcomeAction && options.onAction) {event.stopPropagation(); options.onAction(action.dataset.welcomeAction as 'model' | 'settings' | 'workspace');}\n };\n element.addEventListener('click', click);\n return {\n element,\n update(state): void {\n if (destroyed) return;\n const next = JSON.stringify(state); if (next === signature) return; signature = next;\n const workspace = state.workspace;\n const ready = !!workspace && state.hasApiKey;\n const template = document.createElement('template');\n template.innerHTML = `<div class=\"pui-welcome-mark\"></div>\n <p class=\"pui-eyebrow\">YOUR LOCAL WORK COMPANION</p>\n <h1>${ready ? 'What are we working on?' : 'Your work. A little more possible.'}</h1>\n <p class=\"pui-welcome-description\">An agent that works alongside you, with your files<br class=\"pui-desktop-break\"> and the tools you choose.</p>\n ${!ready ? `<div class=\"pui-setup-card\">\n <div class=\"pui-setup-card-heading\">Make yourself at home <span>Two quick steps</span></div>\n <button type=\"button\" class=\"pui-setup-step\" data-welcome-action=\"${state.hasConnections ? 'model' : 'settings'}\"><span class=\"pui-step-number ${state.hasApiKey ? 'pui-complete' : ''}\">${state.hasApiKey ? icon('check') : '1'}</span><span><strong>${state.hasApiKey ? 'Model selected' : state.hasConnections ? 'Choose a model' : 'Connect a provider'}</strong><small>${state.hasApiKey ? escape(state.modelName) : state.hasConnections ? 'Your provider connection is ready' : 'Bring your provider API key'}</small></span>${icon('chevron')}</button>\n <button type=\"button\" class=\"pui-setup-step\" data-welcome-action=\"workspace\"><span class=\"pui-step-number ${workspace ? 'pui-complete' : ''}\">${workspace ? icon('check') : '2'}</span><span><strong>${workspace ? escape(workspace.name) : 'Choose a workspace'}</strong><small>${workspace ? escape(workspace.path) : 'A folder Pith can help you work in'}</small></span>${icon('chevron')}</button>\n </div>` : `<div class=\"pui-welcome-workspace\">${icon('folder')}<span>Working in <strong>${escape(workspace.name)}</strong></span><button class=\"pui-secondary-button\" type=\"button\" data-welcome-action=\"workspace\">Change</button></div>\n <div class=\"pui-suggestions\"><button type=\"button\" data-prompt=\"Explore this workspace and give me a concise overview of its files.\">${icon('file')}Explore my workspace</button><button type=\"button\" data-prompt=\"Help me plan a task. Start by asking what I want to accomplish.\">${icon('chat')}Think through a task</button><button type=\"button\" data-prompt=\"I'd like help creating a document in this workspace. Ask me what it should cover.\">${icon('plus')}Create something</button></div>`}\n <div class=\"pui-welcome-footnote\">${icon('shield')}Local workspace. Your choice of model.</div>`;\n if (options.logo) template.content.querySelector('.pui-welcome-mark')!.append(options.logo.cloneNode(true));\n patchChildren(element, template.content);\n },\n destroy(): void {\n if (destroyed) return;\n destroyed = true;\n element.removeEventListener('click', click);\n element.replaceChildren();\n },\n };\n}\n"]}
|
package/dist/dom.js
CHANGED
|
@@ -55,7 +55,7 @@ export function setText(node, value) {
|
|
|
55
55
|
}
|
|
56
56
|
export function focusableElements(owner) {
|
|
57
57
|
return [...owner.querySelectorAll('button:not([disabled]), input:not([disabled]), textarea:not([disabled]), select:not([disabled]), a[href], [tabindex="0"]')]
|
|
58
|
-
.filter(node => !node.
|
|
58
|
+
.filter(node => node.tabIndex >= 0 && !node.matches(':disabled') && !node.closest('[hidden], [inert], [aria-hidden="true"]') && !!node.getClientRects().length && getComputedStyle(node).visibility !== 'hidden');
|
|
59
59
|
}
|
|
60
60
|
let nextId = 0;
|
|
61
61
|
export function uniqueId(prefix = 'pui') { return `${prefix}-${++nextId}`; }
|
package/dist/dom.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dom.js","sourceRoot":"","sources":["../src/dom.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"dom.js","sourceRoot":"","sources":["../src/dom.ts"],"names":[],"mappings":"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","sourcesContent":["const paths: Record<string, string> = {\n steer: '<path d=\"M4 5v7a3 3 0 0 0 3 3h13m-5-5 5 5-5 5\"/>',\n edit: '<path d=\"m16 3 5 5-12 12-6 1 1-6Z M14 5l5 5\"/>',\n trash: '<path d=\"M3 6h18M9 6V3h6v3M5 6l1 15h12l1-15M10 10v7M14 10v7\"/>',\n branch: '<path d=\"M4 12h7M11 12l9-9M14 3h6v6M11 12l9 9M14 21h6v-6\"/>',\n compress: '<path d=\"M7 3h10M12 3v6m-3-3 3 3 3-3M5 12h14M12 21v-6m-3 3 3-3 3 3M7 21h10\"/>',\n image: '<rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"3\"/><circle cx=\"8\" cy=\"8\" r=\"1.5\"/><path d=\"m3 17 6-6 4 4 3-3 5 5\"/>',\n plus: '<path d=\"M12 5v14M5 12h14\"/>',\n chat: '<path d=\"M21 11.5a8.4 8.4 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.4 8.4 0 0 1-3.8-.9L3 21l1.9-5.7A8.4 8.4 0 0 1 4 11.5a8.5 8.5 0 0 1 4.7-7.6 8.4 8.4 0 0 1 3.8-.9h.5a8.5 8.5 0 0 1 8 8v.5Z\"/>',\n folder: '<path d=\"M3 7a2 2 0 0 1 2-2h5l2 2h7a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2Z\"/>',\n settings: '<path d=\"m9.5 3-.7 2.2-2.1 1.2-2.3-.5-2.5 4.2 1.6 1.7v2.4l-1.6 1.7 2.5 4.2 2.3-.5 2.1 1.2.7 2.2h5l.7-2.2 2.1-1.2 2.3.5 2.5-4.2-1.6-1.7v-2.4l1.6-1.7-2.5-4.2-2.3.5-2.1-1.2-.7-2.2Z\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/>',\n arrow: '<path d=\"M12 19V5m-6 6 6-6 6 6\"/>',\n stop: '<rect x=\"6\" y=\"6\" width=\"12\" height=\"12\" rx=\"2\"/>',\n chevron: '<path d=\"m9 5 7 7-7 7\"/>',\n down: '<path d=\"m6 9 6 6 6-6\"/>',\n close: '<path d=\"m6 6 12 12M18 6 6 18\"/>',\n check: '<path d=\"m5 12 4 4L19 6\"/>',\n shield: '<path d=\"m12 3 8 4v5c0 5-8 9-8 9s-8-4-8-9V7Z\"/><path d=\"m8 12 3 3 5-6\"/>',\n file: '<path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z\"/><path d=\"M14 2v6h6M8 13h8M8 17h5\"/>',\n terminal: '<path d=\"m4 7 5 5-5 5M12 17h8\"/>',\n copy: '<rect x=\"8\" y=\"8\" width=\"12\" height=\"12\" rx=\"2\"/><path d=\"M16 8V4a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h4\"/>',\n menu: '<path d=\"M4 6h16M4 12h16M4 18h16\"/>',\n globe: '<circle cx=\"12\" cy=\"12\" r=\"9\"/><path d=\"M3 12h18M12 3a17 17 0 0 1 0 18 17 17 0 0 1 0-18Z\"/>',\n search: '<circle cx=\"10.5\" cy=\"10.5\" r=\"6.5\"/><path d=\"m16 16 5 5\"/>',\n more: '<circle cx=\"5\" cy=\"12\" r=\"1\"/><circle cx=\"12\" cy=\"12\" r=\"1\"/><circle cx=\"19\" cy=\"12\" r=\"1\"/>',\n compose: '<path d=\"M12 4H5a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2h13a2 2 0 0 0 2-2v-7\"/><path d=\"m16 3 5 5-10 10-5 1 1-5Z\"/>',\n plug: '<path d=\"M8 3v5M16 3v5M6 8h12v3a6 6 0 0 1-6 6v4M8 8V5M16 8V5\"/>',\n};\nexport const escape = (value: unknown): string => String(value ?? '').replace(/[&<>\"']/g, (char) => ({ '&': '&', '<': '<', '>': '>', '\"': '"', \"'\": ''' }[char]!));\nexport const escapeHTML = escape;\n/** Compatibility markup from a closed, trusted icon registry. */\nexport const icon = (name: string, className = '') => `<svg class=\"pui-icon ${escape(className)}\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">${paths[name] ?? paths.chat}</svg>`;\n\nexport function dialogHeading(title: string, id: string, dialogId: string, eyebrow = ''): string {\n return `<div class=\"pui-dialog-heading pui-modal-heading\"><div>${eyebrow ? `<span class=\"pui-eyebrow\">${escape(eyebrow)}</span>` : ''}<h2 id=\"${escape(id)}\">${escape(title)}</h2></div><button type=\"button\" class=\"pui-icon-button pui-quiet-icon\" data-close=\"${escape(dialogId)}\" aria-label=\"Close ${escape(title.toLowerCase())}\">${icon('close')}</button></div>`;\n}\n\nexport type DOMChild = Node | string | null | undefined;\n/** Safe DOM construction; strings are always text nodes. */\nexport function element<K extends keyof HTMLElementTagNameMap>(tag: K, className = '', ...children: DOMChild[]): HTMLElementTagNameMap[K] {\n const node = document.createElement(tag);\n if (className) node.className = className;\n for (const child of children) if (child != null) node.append(typeof child === 'string' ? document.createTextNode(child) : child);\n return node;\n}\n\nexport function iconElement(name: string): SVGSVGElement {\n const holder = document.createElement('span');\n holder.innerHTML = icon(name);\n return holder.firstElementChild as SVGSVGElement;\n}\n\nexport function setText(node: HTMLElement, value: unknown): void {\n const text = String(value ?? '');\n if (node.textContent !== text) node.textContent = text;\n}\n\nexport function focusableElements(owner: HTMLElement): HTMLElement[] {\n return [...owner.querySelectorAll<HTMLElement>('button:not([disabled]), input:not([disabled]), textarea:not([disabled]), select:not([disabled]), a[href], [tabindex=\"0\"]')]\n .filter(node => node.tabIndex >= 0 && !node.matches(':disabled') && !node.closest('[hidden], [inert], [aria-hidden=\"true\"]') && !!node.getClientRects().length && getComputedStyle(node).visibility !== 'hidden');\n}\n\nlet nextId = 0;\nexport function uniqueId(prefix = 'pui'): string { return `${prefix}-${++nextId}`; }\n\nexport function showDialogError(owner: HTMLElement, message: string): void {\n const error = owner.querySelector<HTMLElement>('[data-dialog-error]') || owner.querySelector<HTMLElement>('.pui-form-error[role=\"alert\"]');\n if (error) { error.textContent = message; error.scrollIntoView({ block: 'nearest' }); }\n}\n"]}
|
package/dist/files/panels.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export interface FileActionOptions {
|
|
|
10
10
|
export declare function fileActionsMarkup(options: FileActionOptions): string;
|
|
11
11
|
export declare function createFileActions(options: FileActionOptions): {
|
|
12
12
|
element: HTMLElement;
|
|
13
|
+
setDisabled(disabled: boolean): void;
|
|
13
14
|
destroy(): void;
|
|
14
15
|
};
|
|
15
16
|
export interface ArtifactPanelState {
|
|
@@ -85,6 +86,7 @@ export interface FilePreviewOptions {
|
|
|
85
86
|
dialogId?: string;
|
|
86
87
|
bodyId?: string;
|
|
87
88
|
onClose?: () => void;
|
|
89
|
+
onCopyCode?: (text: string, button: HTMLButtonElement) => void;
|
|
88
90
|
}
|
|
89
91
|
export declare function createFilePreview(options?: FilePreviewOptions): {
|
|
90
92
|
element: HTMLElement;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"panels.d.ts","sourceRoot":"","sources":["../../src/files/panels.ts"],"names":[],"mappings":"AAEA,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"panels.d.ts","sourceRoot":"","sources":["../../src/files/panels.ts"],"names":[],"mappings":"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"}
|