pith-ui 0.1.1 → 0.1.4
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 +12 -1
- package/API.md +347 -192
- package/README.md +3 -1
- 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 +23 -2
- package/dist/forms/actions.d.ts.map +1 -1
- package/dist/forms/actions.js +53 -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 +435 -369
- 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 +30 -13
- 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 +1 -1
package/dist/foundations.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { controlDisabled,
|
|
1
|
+
import { controlDisabled, Lifetime, setControlPending } from './core.js';
|
|
2
2
|
import { iconElement, setText, uniqueId } from './dom.js';
|
|
3
|
+
import { adoptSelect, refreshSelect } from './select.js';
|
|
4
|
+
import { createOperation } from './operation.js';
|
|
3
5
|
export function adoptAction(node, options = {}) {
|
|
4
6
|
const life = options.onAction ? new Lifetime() : undefined;
|
|
5
|
-
const generation = options.onAction ? new Generation() : undefined;
|
|
6
7
|
let state = { disabled: node.disabled };
|
|
7
8
|
let localPending = false;
|
|
8
9
|
let disposed = false;
|
|
@@ -51,45 +52,20 @@ export function adoptAction(node, options = {}) {
|
|
|
51
52
|
node.prepend(glyph);
|
|
52
53
|
}
|
|
53
54
|
};
|
|
55
|
+
const operation = options.onAction ? createOperation({
|
|
56
|
+
unavailable: () => node.disabled || disposed,
|
|
57
|
+
onPending(value) { localPending = value; update({ ...state, disabled: !!state.disabled, pending: !!state.pending }); },
|
|
58
|
+
onError: options.onError,
|
|
59
|
+
}) : undefined;
|
|
54
60
|
// A delegated product action has no local handler and needs no second listener.
|
|
55
61
|
if (options.onAction)
|
|
56
62
|
life.listen(node, 'click', (() => {
|
|
57
63
|
if (node.disabled || localPending || disposed)
|
|
58
64
|
return;
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
update(state);
|
|
62
|
-
const complete = (result) => {
|
|
63
|
-
if (generation.current(seq) && result && !result.ok)
|
|
64
|
-
options.onError?.(result.error);
|
|
65
|
-
};
|
|
66
|
-
const failed = (reason) => {
|
|
67
|
-
if (generation.current(seq))
|
|
68
|
-
options.onError?.(reason instanceof Error ? reason.message : String(reason));
|
|
69
|
-
};
|
|
70
|
-
const finish = () => {
|
|
71
|
-
if (!generation.current(seq))
|
|
72
|
-
return;
|
|
73
|
-
localPending = false;
|
|
74
|
-
// Include both properties so releasing local pending can enable an action,
|
|
75
|
-
// while a newer external disabled state remains authoritative.
|
|
76
|
-
update({ ...state, disabled: !!state.disabled, pending: !!state.pending });
|
|
77
|
-
};
|
|
78
|
-
try {
|
|
79
|
-
const result = options.onAction();
|
|
80
|
-
if (result && 'then' in result)
|
|
81
|
-
void result.then(complete).catch(failed).finally(finish);
|
|
82
|
-
else {
|
|
83
|
-
complete(result);
|
|
84
|
-
finish();
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
catch (reason) {
|
|
88
|
-
failed(reason);
|
|
89
|
-
finish();
|
|
90
|
-
}
|
|
65
|
+
operation.run(options.onAction, (result) => { if (result && !result.ok)
|
|
66
|
+
options.onError?.(result.error); });
|
|
91
67
|
}));
|
|
92
|
-
return { element: node, update, destroy() { disposed = true;
|
|
68
|
+
return { element: node, update, destroy() { disposed = true; operation?.destroy(); life?.destroy(); } };
|
|
93
69
|
}
|
|
94
70
|
/** Reconcile native options by their stable value without replacing the select.
|
|
95
71
|
* Callers decide the fallback when a preferred value has disappeared.
|
|
@@ -128,6 +104,7 @@ export function reconcileSelectOptions(control, entries, preferred) {
|
|
|
128
104
|
if (control.value !== value || !selected.size)
|
|
129
105
|
control.value = value;
|
|
130
106
|
}
|
|
107
|
+
refreshSelect(control);
|
|
131
108
|
}
|
|
132
109
|
export function adoptNativeControl(control, options = {}) {
|
|
133
110
|
const life = options.onInput || options.onChange ? new Lifetime() : undefined;
|
|
@@ -147,6 +124,7 @@ export function adoptNativeControl(control, options = {}) {
|
|
|
147
124
|
}
|
|
148
125
|
if (options.error)
|
|
149
126
|
options.error.setAttribute('role', 'alert');
|
|
127
|
+
const select = control instanceof HTMLSelectElement ? adoptSelect(control) : undefined;
|
|
150
128
|
const update = (state) => {
|
|
151
129
|
if (disposed)
|
|
152
130
|
return;
|
|
@@ -185,6 +163,7 @@ export function adoptNativeControl(control, options = {}) {
|
|
|
185
163
|
else
|
|
186
164
|
control.removeAttribute('aria-describedby');
|
|
187
165
|
}
|
|
166
|
+
select?.refresh();
|
|
188
167
|
};
|
|
189
168
|
if (options.onInput)
|
|
190
169
|
life.listen(control, 'input', (event => options.onInput(control.value, event)));
|
|
@@ -196,9 +175,14 @@ export function adoptNativeControl(control, options = {}) {
|
|
|
196
175
|
return; if (typeof value === 'boolean' && control instanceof HTMLInputElement)
|
|
197
176
|
control.checked = value;
|
|
198
177
|
else if (typeof value === 'string' && control.value !== value)
|
|
199
|
-
control.value = value; },
|
|
200
|
-
focus() { if (!disposed)
|
|
201
|
-
|
|
178
|
+
control.value = value; select?.refresh(); },
|
|
179
|
+
focus() { if (!disposed) {
|
|
180
|
+
if (select)
|
|
181
|
+
select.focus();
|
|
182
|
+
else
|
|
183
|
+
control.focus();
|
|
184
|
+
} }, destroy() { if (disposed)
|
|
185
|
+
return; disposed = true; life?.destroy(); select?.destroy(); } };
|
|
202
186
|
}
|
|
203
187
|
export function adoptFeedback(node, options) {
|
|
204
188
|
let disposed = false;
|
package/dist/foundations.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"foundations.js","sourceRoot":"","sources":["../src/foundations.ts"],"names":[],"mappings":"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","sourcesContent":["import { controlDisabled, Generation, Lifetime, setControlPending } from './core.js';\nimport type { ActionResult, Density, Intent, UIAction } from './core.js';\nimport { iconElement, setText, uniqueId } from './dom.js';\n\n/** Private controllers shared by factories and the retained product templates.\n * Adoption does not replace nodes, move controls or infer business availability.\n */\nexport interface ActionState {\n label?: string;\n intent?: Intent;\n density?: Density;\n disabled?: boolean;\n pending?: boolean;\n icon?: string;\n title?: string;\n appearance?: 'standard' | 'secondary';\n}\nexport interface ActionController {\n readonly element: HTMLButtonElement;\n update(state: Readonly<ActionState>): void;\n destroy(): void;\n}\nexport function adoptAction(node: HTMLButtonElement, options: {\n caption?: HTMLElement;\n onAction?: UIAction;\n onError?: (message: string) => void;\n} = {}): ActionController {\n const life = options.onAction ? new Lifetime() : undefined;\n const generation = options.onAction ? new Generation() : undefined;\n let state: ActionState = { disabled: node.disabled };\n let localPending = false; let disposed = false;\n let glyph = node.querySelector<SVGSVGElement>(':scope > svg') ?? undefined;\n const caption = options.caption ?? [...node.children].find((child): child is HTMLElement => child instanceof HTMLElement && child.tagName === 'SPAN');\n const iconOnly = !caption && !!glyph && ![...node.childNodes].some(child => child.nodeType === Node.TEXT_NODE && child.textContent?.trim());\n let iconName: string | undefined;\n const update = (next: Readonly<ActionState>): void => {\n if (disposed) return;\n state = { ...state, ...next };\n if (next.label != null) {\n if (caption) setText(caption, next.label);\n else if (iconOnly) node.setAttribute('aria-label', next.label);\n else setText(node, next.label);\n }\n if (next.intent != null) {\n for (const intent of ['neutral', 'primary', 'danger']) node.classList.toggle(`pui-${intent}`, next.intent === intent);\n }\n if (next.density != null) {\n node.classList.toggle('pui-normal', next.density === 'normal');\n node.classList.toggle('pui-compact', next.density === 'compact');\n }\n if (next.appearance != null) node.classList.toggle('pui-secondary-button', next.appearance === 'secondary');\n // Adopted nodes keep their host-owned attributes unless explicitly updated.\n if (next.disabled != null || next.pending != null || localPending) {\n // A retained product action can also be pending in the application's\n // adapter or native-copy controller. Only clear pending that we own.\n if (state.pending != null || options.onAction) setControlPending(node, !!(state.pending || localPending));\n node.disabled = controlDisabled(node, !!(state.disabled || state.pending || localPending));\n node.setAttribute('aria-busy', String(!!(state.pending || localPending || node.dataset.controlPending || node.dataset.copyPending)));\n }\n if (next.title != null) node.title = next.title;\n if (next.icon != null && iconName !== next.icon) {\n glyph?.remove(); iconName = next.icon;\n glyph = next.icon ? iconElement(next.icon) : undefined;\n if (glyph) node.prepend(glyph);\n }\n };\n // A delegated product action has no local handler and needs no second listener.\n if (options.onAction) life!.listen(node, 'click', (() => {\n if (node.disabled || localPending || disposed) return;\n const seq = generation!.next(); localPending = true; update(state);\n const complete = (result: void | ActionResult): void => {\n if (generation!.current(seq) && result && !result.ok) options.onError?.(result.error);\n };\n const failed = (reason: unknown): void => {\n if (generation!.current(seq)) options.onError?.(reason instanceof Error ? reason.message : String(reason));\n };\n const finish = (): void => {\n if (!generation!.current(seq)) return;\n localPending = false;\n // Include both properties so releasing local pending can enable an action,\n // while a newer external disabled state remains authoritative.\n update({ ...state, disabled: !!state.disabled, pending: !!state.pending });\n };\n try {\n const result = options.onAction!();\n if (result && 'then' in result) void result.then(complete).catch(failed).finally(finish);\n else { complete(result); finish(); }\n } catch (reason) { failed(reason); finish(); }\n }) as EventListener);\n return { element: node, update, destroy() { disposed = true; generation?.destroy(); life?.destroy(); } };\n}\n\nexport type NativeControl = HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement;\nexport interface NativeSelectOption { value: string; label: string; disabled?: boolean; }\n/** Reconcile native options by their stable value without replacing the select.\n * Callers decide the fallback when a preferred value has disappeared.\n */\nexport function reconcileSelectOptions(control: HTMLSelectElement, entries: readonly NativeSelectOption[], preferred?: string): void {\n const selected = new Set(preferred == null ? [...control.selectedOptions].map(option => option.value) : [preferred]);\n const existing = new Map<string, HTMLOptionElement[]>();\n for (const option of control.options) { const group = existing.get(option.value) ?? []; group.push(option); existing.set(option.value, group); }\n const keep = new Set<HTMLOptionElement>();\n entries.forEach((entry, index) => {\n const option = existing.get(entry.value)?.shift() ?? document.createElement('option');\n keep.add(option);\n if (option.value !== entry.value) option.value = entry.value;\n if (option.textContent !== entry.label) option.textContent = entry.label;\n if (option.disabled !== !!entry.disabled) option.disabled = !!entry.disabled;\n if (control.options[index] !== option) control.insertBefore(option, control.options[index] ?? null);\n });\n for (const option of [...control.options]) if (!keep.has(option)) option.remove();\n if (control.multiple) {\n for (const option of control.options) if (option.selected !== selected.has(option.value)) option.selected = selected.has(option.value);\n } else {\n const value = preferred ?? [...selected][0] ?? '';\n if (control.value !== value || !selected.size) control.value = value;\n }\n}\nexport interface NativeControlState {\n label?: string;\n description?: string;\n error?: string;\n disabled?: boolean;\n required?: boolean;\n readOnly?: boolean;\n placeholder?: string;\n}\nexport interface NativeControlController {\n readonly element: NativeControl;\n update(state: Readonly<NativeControlState>): void;\n getValue(): string;\n getChecked(): boolean;\n reset(value: string | boolean): void;\n focus(): void;\n destroy(): void;\n}\nexport function adoptNativeControl(control: NativeControl, options: {\n label?: HTMLLabelElement;\n description?: HTMLElement;\n error?: HTMLElement;\n onInput?: (value: string, event: Event) => void;\n onChange?: (value: string, event: Event) => void;\n} = {}): NativeControlController {\n const life = options.onInput || options.onChange ? new Lifetime() : undefined; let disposed = false;\n const originalDescriptions = new Set((control.getAttribute('aria-describedby') ?? '').split(/\\s+/).filter(Boolean));\n const ownedDescriptions = new Set<string>();\n if (options.label) {\n if (!control.id) control.id = uniqueId('pui-input');\n options.label.htmlFor = control.id;\n }\n for (const node of [options.description, options.error]) if (node) {\n if (!node.id) node.id = uniqueId('pui-field-message');\n ownedDescriptions.add(node.id);\n }\n if (options.error) options.error.setAttribute('role', 'alert');\n const update = (state: Readonly<NativeControlState>): void => {\n if (disposed) return;\n if (state.label != null && options.label) setText(options.label, state.label);\n if (state.disabled != null) control.disabled = state.disabled;\n if (state.required != null) control.required = state.required;\n if (state.readOnly != null && !(control instanceof HTMLSelectElement)) control.readOnly = state.readOnly;\n if (state.placeholder != null && !(control instanceof HTMLSelectElement)) control.placeholder = state.placeholder;\n if (state.description != null && options.description) {\n setText(options.description, state.description); options.description.hidden = !state.description;\n }\n if (state.error != null) {\n control.setAttribute('aria-invalid', String(!!state.error));\n if (options.error) { setText(options.error, state.error); options.error.hidden = !state.error; }\n }\n if (options.description || options.error) {\n // Preserve descriptions supplied by the host or another owned component.\n const ids = new Set([...originalDescriptions, ...(control.getAttribute('aria-describedby') ?? '').split(/\\s+/).filter(Boolean)]);\n for (const id of ownedDescriptions) ids.delete(id);\n if (options.description && !options.description.hidden && options.description.textContent) ids.add(options.description.id);\n if (options.error && !options.error.hidden && options.error.textContent) ids.add(options.error.id);\n if (ids.size) control.setAttribute('aria-describedby', [...ids].join(' ')); else control.removeAttribute('aria-describedby');\n }\n };\n if (options.onInput) life!.listen(control, 'input', (event => options.onInput!(control.value, event)) as EventListener);\n if (options.onChange) life!.listen(control, 'change', (event => options.onChange!(control.value, event)) as EventListener);\n return { element: control, update, getValue: () => control.value,\n getChecked: () => control instanceof HTMLInputElement && control.checked,\n reset(value) { if (disposed) return; if (typeof value === 'boolean' && control instanceof HTMLInputElement) control.checked = value; else if (typeof value === 'string' && control.value !== value) control.value = value; },\n focus() { if (!disposed) control.focus(); }, destroy() { disposed = true; life?.destroy(); } };\n}\n\nexport interface FeedbackState { message: string; tone?: 'info' | 'neutral' | 'success' | 'warning' | 'error'; }\nexport interface FeedbackController {\n readonly element: HTMLElement;\n update(state: Readonly<FeedbackState>): void;\n destroy(): void;\n}\nexport function adoptFeedback(node: HTMLElement, options: {\n presentation: 'notice' | 'inline' | 'status';\n autoHide?: boolean;\n}): FeedbackController {\n let disposed = false;\n const update = (state: Readonly<FeedbackState>): void => {\n if (disposed) return;\n const tone = state.tone ?? (options.presentation === 'status' ? 'neutral' : 'info');\n if (options.presentation !== 'inline') {\n const prefix = options.presentation === 'notice' ? 'pui-notice' : 'pui-status';\n node.classList.add(prefix);\n for (const value of ['info', 'neutral', 'success', 'warning', 'error']) node.classList.toggle(`${prefix}-${value}`, tone === value);\n }\n if (options.presentation !== 'status') node.setAttribute('role', tone === 'error' || tone === 'warning' ? 'alert' : 'status');\n if (options.autoHide !== false) node.hidden = !state.message;\n setText(node, state.message);\n };\n return { element: node, update, destroy() { disposed = true; } };\n}\n\nexport interface ActionLayoutState { align?: 'start' | 'end' | 'between'; density?: Density; label?: string; }\nexport function adoptActionLayout(node: HTMLElement, kind: 'actions' | 'toolbar'): {\n readonly element: HTMLElement;\n update(state: Readonly<ActionLayoutState>): void;\n destroy(): void;\n} {\n let disposed = false;\n return { element: node, update(state) {\n if (disposed) return;\n if (state.align != null) node.dataset.align = state.align;\n if (state.density != null) node.classList.toggle('pui-compact', state.density === 'compact');\n if (state.label != null) { node.setAttribute('role', 'group'); node.setAttribute('aria-label', state.label); }\n node.dataset.puiActionLayout = kind;\n }, destroy() { disposed = true; } };\n}\n\n/** Owned controllers for existing product templates; not a renderer or observer.\n * Controllers are lazy. Reconciliation prunes owned handles without rescanning\n * long message histories or allocating a controller for every static button.\n */\nexport function adoptProductParts(owner: HTMLElement): {\n update(): void;\n action(node: HTMLButtonElement): ActionController;\n control(node: NativeControl): NativeControlController;\n feedback(node: HTMLElement): FeedbackController;\n layout(node: HTMLElement, kind: 'actions' | 'toolbar'): ReturnType<typeof adoptActionLayout>;\n destroy(): void;\n} {\n const actions = new Map<HTMLButtonElement, ActionController>();\n const controls = new Map<NativeControl, NativeControlController>();\n const feedbacks = new Map<HTMLElement, FeedbackController>();\n const layouts = new Map<HTMLElement, ReturnType<typeof adoptActionLayout>>();\n let disposed = false;\n const action = (node: HTMLButtonElement): ActionController => {\n let handle = actions.get(node); if (!handle) { handle = adoptAction(node); if (disposed) handle.destroy(); else actions.set(node, handle); } return handle;\n };\n const control = (node: NativeControl): NativeControlController => {\n let handle = controls.get(node); if (!handle) { handle = adoptNativeControl(node); if (disposed) handle.destroy(); else controls.set(node, handle); } return handle;\n };\n const feedback = (node: HTMLElement): FeedbackController => {\n let handle = feedbacks.get(node); if (!handle) { handle = adoptFeedback(node, { presentation: 'inline', autoHide: false }); if (disposed) handle.destroy(); else feedbacks.set(node, handle); } return handle;\n };\n const layout = (node: HTMLElement, kind: 'actions' | 'toolbar'): ReturnType<typeof adoptActionLayout> => {\n let handle = layouts.get(node); if (!handle) { handle = adoptActionLayout(node, kind); if (disposed) handle.destroy(); else layouts.set(node, handle); } return handle;\n };\n const update = (): void => {\n if (disposed) return;\n for (const map of [actions, controls, feedbacks, layouts]) for (const [node, handle] of map) {\n if (!owner.contains(node) && node !== owner) { handle.destroy(); map.delete(node as never); }\n }\n };\n return { update, action, control, feedback, layout, destroy() {\n if (disposed) return; disposed = true;\n for (const map of [actions, controls, feedbacks, layouts]) { for (const handle of map.values()) handle.destroy(); map.clear(); }\n } };\n}\n\n"]}
|
|
1
|
+
{"version":3,"file":"foundations.js","sourceRoot":"","sources":["../src/foundations.ts"],"names":[],"mappings":"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","sourcesContent":["import { controlDisabled, Lifetime, setControlPending } from './core.js';\nimport type { ActionResult, Density, Intent, UIAction } from './core.js';\nimport { iconElement, setText, uniqueId } from './dom.js';\nimport { adoptSelect, refreshSelect } from './select.js';\nimport { createOperation } from './operation.js';\n\n/** Private controllers shared by factories and the retained product templates.\n * Retained nodes keep their identity; single selects get one owned wrapper.\n */\nexport interface ActionState {\n label?: string;\n intent?: Intent;\n density?: Density;\n disabled?: boolean;\n pending?: boolean;\n icon?: string;\n title?: string;\n appearance?: 'standard' | 'secondary';\n}\nexport interface ActionController {\n readonly element: HTMLButtonElement;\n update(state: Readonly<ActionState>): void;\n destroy(): void;\n}\nexport function adoptAction(node: HTMLButtonElement, options: {\n caption?: HTMLElement;\n onAction?: UIAction;\n onError?: (message: string) => void;\n} = {}): ActionController {\n const life = options.onAction ? new Lifetime() : undefined;\n let state: ActionState = { disabled: node.disabled };\n let localPending = false; let disposed = false;\n let glyph = node.querySelector<SVGSVGElement>(':scope > svg') ?? undefined;\n const caption = options.caption ?? [...node.children].find((child): child is HTMLElement => child instanceof HTMLElement && child.tagName === 'SPAN');\n const iconOnly = !caption && !!glyph && ![...node.childNodes].some(child => child.nodeType === Node.TEXT_NODE && child.textContent?.trim());\n let iconName: string | undefined;\n const update = (next: Readonly<ActionState>): void => {\n if (disposed) return;\n state = { ...state, ...next };\n if (next.label != null) {\n if (caption) setText(caption, next.label);\n else if (iconOnly) node.setAttribute('aria-label', next.label);\n else setText(node, next.label);\n }\n if (next.intent != null) {\n for (const intent of ['neutral', 'primary', 'danger']) node.classList.toggle(`pui-${intent}`, next.intent === intent);\n }\n if (next.density != null) {\n node.classList.toggle('pui-normal', next.density === 'normal');\n node.classList.toggle('pui-compact', next.density === 'compact');\n }\n if (next.appearance != null) node.classList.toggle('pui-secondary-button', next.appearance === 'secondary');\n // Adopted nodes keep their host-owned attributes unless explicitly updated.\n if (next.disabled != null || next.pending != null || localPending) {\n // A retained product action can also be pending in the application's\n // adapter or native-copy controller. Only clear pending that we own.\n if (state.pending != null || options.onAction) setControlPending(node, !!(state.pending || localPending));\n node.disabled = controlDisabled(node, !!(state.disabled || state.pending || localPending));\n node.setAttribute('aria-busy', String(!!(state.pending || localPending || node.dataset.controlPending || node.dataset.copyPending)));\n }\n if (next.title != null) node.title = next.title;\n if (next.icon != null && iconName !== next.icon) {\n glyph?.remove(); iconName = next.icon;\n glyph = next.icon ? iconElement(next.icon) : undefined;\n if (glyph) node.prepend(glyph);\n }\n };\n const operation = options.onAction ? createOperation({\n unavailable: () => node.disabled || disposed,\n onPending(value) { localPending = value; update({ ...state, disabled: !!state.disabled, pending: !!state.pending }); },\n onError: options.onError,\n }) : undefined;\n // A delegated product action has no local handler and needs no second listener.\n if (options.onAction) life!.listen(node, 'click', (() => {\n if (node.disabled || localPending || disposed) return;\n operation!.run(options.onAction!, (result: void | ActionResult) => { if (result && !result.ok) options.onError?.(result.error); });\n }) as EventListener);\n return { element: node, update, destroy() { disposed = true; operation?.destroy(); life?.destroy(); } };\n}\n\nexport type NativeControl = HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement;\nexport interface NativeSelectOption { value: string; label: string; disabled?: boolean; }\n/** Reconcile native options by their stable value without replacing the select.\n * Callers decide the fallback when a preferred value has disappeared.\n */\nexport function reconcileSelectOptions(control: HTMLSelectElement, entries: readonly NativeSelectOption[], preferred?: string): void {\n const selected = new Set(preferred == null ? [...control.selectedOptions].map(option => option.value) : [preferred]);\n const existing = new Map<string, HTMLOptionElement[]>();\n for (const option of control.options) { const group = existing.get(option.value) ?? []; group.push(option); existing.set(option.value, group); }\n const keep = new Set<HTMLOptionElement>();\n entries.forEach((entry, index) => {\n const option = existing.get(entry.value)?.shift() ?? document.createElement('option');\n keep.add(option);\n if (option.value !== entry.value) option.value = entry.value;\n if (option.textContent !== entry.label) option.textContent = entry.label;\n if (option.disabled !== !!entry.disabled) option.disabled = !!entry.disabled;\n if (control.options[index] !== option) control.insertBefore(option, control.options[index] ?? null);\n });\n for (const option of [...control.options]) if (!keep.has(option)) option.remove();\n if (control.multiple) {\n for (const option of control.options) if (option.selected !== selected.has(option.value)) option.selected = selected.has(option.value);\n } else {\n const value = preferred ?? [...selected][0] ?? '';\n if (control.value !== value || !selected.size) control.value = value;\n }\n refreshSelect(control);\n}\nexport interface NativeControlState {\n label?: string;\n description?: string;\n error?: string;\n disabled?: boolean;\n required?: boolean;\n readOnly?: boolean;\n placeholder?: string;\n}\nexport interface NativeControlController {\n readonly element: NativeControl;\n update(state: Readonly<NativeControlState>): void;\n getValue(): string;\n getChecked(): boolean;\n reset(value: string | boolean): void;\n focus(): void;\n destroy(): void;\n}\nexport function adoptNativeControl(control: NativeControl, options: {\n label?: HTMLLabelElement;\n description?: HTMLElement;\n error?: HTMLElement;\n onInput?: (value: string, event: Event) => void;\n onChange?: (value: string, event: Event) => void;\n} = {}): NativeControlController {\n const life = options.onInput || options.onChange ? new Lifetime() : undefined; let disposed = false;\n const originalDescriptions = new Set((control.getAttribute('aria-describedby') ?? '').split(/\\s+/).filter(Boolean));\n const ownedDescriptions = new Set<string>();\n if (options.label) {\n if (!control.id) control.id = uniqueId('pui-input');\n options.label.htmlFor = control.id;\n }\n for (const node of [options.description, options.error]) if (node) {\n if (!node.id) node.id = uniqueId('pui-field-message');\n ownedDescriptions.add(node.id);\n }\n if (options.error) options.error.setAttribute('role', 'alert');\n const select = control instanceof HTMLSelectElement ? adoptSelect(control) : undefined;\n const update = (state: Readonly<NativeControlState>): void => {\n if (disposed) return;\n if (state.label != null && options.label) setText(options.label, state.label);\n if (state.disabled != null) control.disabled = state.disabled;\n if (state.required != null) control.required = state.required;\n if (state.readOnly != null && !(control instanceof HTMLSelectElement)) control.readOnly = state.readOnly;\n if (state.placeholder != null && !(control instanceof HTMLSelectElement)) control.placeholder = state.placeholder;\n if (state.description != null && options.description) {\n setText(options.description, state.description); options.description.hidden = !state.description;\n }\n if (state.error != null) {\n control.setAttribute('aria-invalid', String(!!state.error));\n if (options.error) { setText(options.error, state.error); options.error.hidden = !state.error; }\n }\n if (options.description || options.error) {\n // Preserve descriptions supplied by the host or another owned component.\n const ids = new Set([...originalDescriptions, ...(control.getAttribute('aria-describedby') ?? '').split(/\\s+/).filter(Boolean)]);\n for (const id of ownedDescriptions) ids.delete(id);\n if (options.description && !options.description.hidden && options.description.textContent) ids.add(options.description.id);\n if (options.error && !options.error.hidden && options.error.textContent) ids.add(options.error.id);\n if (ids.size) control.setAttribute('aria-describedby', [...ids].join(' ')); else control.removeAttribute('aria-describedby');\n }\n select?.refresh();\n };\n if (options.onInput) life!.listen(control, 'input', (event => options.onInput!(control.value, event)) as EventListener);\n if (options.onChange) life!.listen(control, 'change', (event => options.onChange!(control.value, event)) as EventListener);\n return { element: control, update, getValue: () => control.value,\n getChecked: () => control instanceof HTMLInputElement && control.checked,\n reset(value) { if (disposed) return; if (typeof value === 'boolean' && control instanceof HTMLInputElement) control.checked = value; else if (typeof value === 'string' && control.value !== value) control.value = value; select?.refresh(); },\n focus() { if (!disposed) { if (select) select.focus(); else control.focus(); } }, destroy() { if (disposed) return; disposed = true; life?.destroy(); select?.destroy(); } };\n}\n\nexport interface FeedbackState { message: string; tone?: 'info' | 'neutral' | 'success' | 'warning' | 'error'; }\nexport interface FeedbackController {\n readonly element: HTMLElement;\n update(state: Readonly<FeedbackState>): void;\n destroy(): void;\n}\nexport function adoptFeedback(node: HTMLElement, options: {\n presentation: 'notice' | 'inline' | 'status';\n autoHide?: boolean;\n}): FeedbackController {\n let disposed = false;\n const update = (state: Readonly<FeedbackState>): void => {\n if (disposed) return;\n const tone = state.tone ?? (options.presentation === 'status' ? 'neutral' : 'info');\n if (options.presentation !== 'inline') {\n const prefix = options.presentation === 'notice' ? 'pui-notice' : 'pui-status';\n node.classList.add(prefix);\n for (const value of ['info', 'neutral', 'success', 'warning', 'error']) node.classList.toggle(`${prefix}-${value}`, tone === value);\n }\n if (options.presentation !== 'status') node.setAttribute('role', tone === 'error' || tone === 'warning' ? 'alert' : 'status');\n if (options.autoHide !== false) node.hidden = !state.message;\n setText(node, state.message);\n };\n return { element: node, update, destroy() { disposed = true; } };\n}\n\nexport interface ActionLayoutState { align?: 'start' | 'end' | 'between'; density?: Density; label?: string; }\nexport function adoptActionLayout(node: HTMLElement, kind: 'actions' | 'toolbar'): {\n readonly element: HTMLElement;\n update(state: Readonly<ActionLayoutState>): void;\n destroy(): void;\n} {\n let disposed = false;\n return { element: node, update(state) {\n if (disposed) return;\n if (state.align != null) node.dataset.align = state.align;\n if (state.density != null) node.classList.toggle('pui-compact', state.density === 'compact');\n if (state.label != null) { node.setAttribute('role', 'group'); node.setAttribute('aria-label', state.label); }\n node.dataset.puiActionLayout = kind;\n }, destroy() { disposed = true; } };\n}\n\n/** Owned controllers for existing product templates; not a renderer or observer.\n * Controllers are lazy. Reconciliation prunes owned handles without rescanning\n * long message histories or allocating a controller for every static button.\n */\nexport function adoptProductParts(owner: HTMLElement): {\n update(): void;\n action(node: HTMLButtonElement): ActionController;\n control(node: NativeControl): NativeControlController;\n feedback(node: HTMLElement): FeedbackController;\n layout(node: HTMLElement, kind: 'actions' | 'toolbar'): ReturnType<typeof adoptActionLayout>;\n destroy(): void;\n} {\n const actions = new Map<HTMLButtonElement, ActionController>();\n const controls = new Map<NativeControl, NativeControlController>();\n const feedbacks = new Map<HTMLElement, FeedbackController>();\n const layouts = new Map<HTMLElement, ReturnType<typeof adoptActionLayout>>();\n let disposed = false;\n const action = (node: HTMLButtonElement): ActionController => {\n let handle = actions.get(node); if (!handle) { handle = adoptAction(node); if (disposed) handle.destroy(); else actions.set(node, handle); } return handle;\n };\n const control = (node: NativeControl): NativeControlController => {\n let handle = controls.get(node); if (!handle) { handle = adoptNativeControl(node); if (disposed) handle.destroy(); else controls.set(node, handle); } return handle;\n };\n const feedback = (node: HTMLElement): FeedbackController => {\n let handle = feedbacks.get(node); if (!handle) { handle = adoptFeedback(node, { presentation: 'inline', autoHide: false }); if (disposed) handle.destroy(); else feedbacks.set(node, handle); } return handle;\n };\n const layout = (node: HTMLElement, kind: 'actions' | 'toolbar'): ReturnType<typeof adoptActionLayout> => {\n let handle = layouts.get(node); if (!handle) { handle = adoptActionLayout(node, kind); if (disposed) handle.destroy(); else layouts.set(node, handle); } return handle;\n };\n const update = (): void => {\n if (disposed) return;\n for (const map of [actions, controls, feedbacks, layouts]) for (const [node, handle] of map) {\n if (!owner.contains(node) && node !== owner) { handle.destroy(); map.delete(node as never); }\n }\n };\n return { update, action, control, feedback, layout, destroy() {\n if (disposed) return; disposed = true;\n for (const map of [actions, controls, feedbacks, layouts]) { for (const handle of map.values()) handle.destroy(); map.clear(); }\n } };\n}\n\n"]}
|
|
@@ -15,12 +15,18 @@ export interface ContextMenuState {
|
|
|
15
15
|
label: string;
|
|
16
16
|
items: readonly ContextMenuItem[];
|
|
17
17
|
}
|
|
18
|
+
export interface ContextMenuOpenOptions {
|
|
19
|
+
point?: {
|
|
20
|
+
x: number;
|
|
21
|
+
y: number;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
18
24
|
export declare function createContextMenu(options?: {
|
|
19
25
|
element?: HTMLElement;
|
|
20
26
|
onDismiss?: (restoreFocus: boolean) => void;
|
|
21
27
|
onAction?: (item: ContextMenuItem) => void;
|
|
22
28
|
}): UIBlock<ContextMenuState> & {
|
|
23
|
-
open(trigger: HTMLElement, state: ContextMenuState): void;
|
|
29
|
+
open(trigger: HTMLElement, state: ContextMenuState, options?: ContextMenuOpenOptions): void;
|
|
24
30
|
close(restoreFocus?: boolean): void;
|
|
25
31
|
};
|
|
26
32
|
//# sourceMappingURL=context-menu.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-menu.d.ts","sourceRoot":"","sources":["../../src/navigation/context-menu.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"context-menu.d.ts","sourceRoot":"","sources":["../../src/navigation/context-menu.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAI1C,MAAM,WAAW,eAAe;IAC9B,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACtG,IAAI,CAAC,EAAE;QAAC,cAAc,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAC,CAAC;CACxD;AACD,MAAM,WAAW,gBAAgB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,eAAe,EAAE,CAAA;CAAC;AACpF,MAAM,WAAW,sBAAsB;IAAE,KAAK,CAAC,EAAE;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAC,CAAA;CAAC;AACxE,wBAAgB,iBAAiB,CAAC,OAAO,GAAE;IAAC,OAAO,CAAC,EAAE,WAAW,CAAC;IAAC,SAAS,CAAC,EAAE,CAAC,YAAY,EAAE,OAAO,KAAK,IAAI,CAAC;IAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,IAAI,CAAA;CAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,GAAG;IAAC,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,gBAAgB,EAAE,OAAO,CAAC,EAAE,sBAAsB,GAAG,IAAI,CAAC;IAAC,KAAK,CAAC,YAAY,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;CAAC,CA4ChU"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { installMenuNavigation } from '../surface.js';
|
|
1
|
+
import { installAnchoredSurface, installMenuNavigation } from '../surface.js';
|
|
2
2
|
import { adoptProductParts } from '../foundations.js';
|
|
3
|
+
import { reconcileKeyed } from '../reconcile.js';
|
|
3
4
|
export function createContextMenu(options = {}) {
|
|
4
5
|
const element = options.element || document.createElement('div');
|
|
5
6
|
if (!options.element) {
|
|
@@ -7,74 +8,76 @@ export function createContextMenu(options = {}) {
|
|
|
7
8
|
element.setAttribute('role', 'menu');
|
|
8
9
|
element.hidden = true;
|
|
9
10
|
}
|
|
11
|
+
element.setAttribute('role', 'menu');
|
|
12
|
+
element.tabIndex = -1;
|
|
10
13
|
const abort = new AbortController();
|
|
11
|
-
let
|
|
12
|
-
let
|
|
14
|
+
let destroyed = false, programmaticClose = false;
|
|
15
|
+
let surface;
|
|
13
16
|
const parts = adoptProductParts(element);
|
|
14
17
|
const rows = new Map();
|
|
15
18
|
const actions = new Map();
|
|
16
|
-
const close = (restoreFocus = false) => {
|
|
17
|
-
|
|
19
|
+
const close = (restoreFocus = false) => {
|
|
20
|
+
programmaticClose = true;
|
|
21
|
+
surface?.close(restoreFocus);
|
|
22
|
+
surface?.destroy();
|
|
23
|
+
surface = undefined;
|
|
24
|
+
element.hidden = true;
|
|
25
|
+
programmaticClose = false;
|
|
26
|
+
};
|
|
18
27
|
const dismiss = (restoreFocus) => { close(restoreFocus); options.onDismiss?.(restoreFocus); };
|
|
19
|
-
const navigation = installMenuNavigation(element, { onDismiss: dismiss, isOpen: () =>
|
|
28
|
+
const navigation = installMenuNavigation(element, { onDismiss: dismiss, isOpen: () => surface?.isOpen() ?? false });
|
|
20
29
|
const update = (state) => {
|
|
21
30
|
if (destroyed)
|
|
22
31
|
return;
|
|
23
32
|
element.setAttribute('aria-label', state.label);
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if (item.idle.conversationId)
|
|
51
|
-
button.dataset.idleConversation = item.idle.conversationId;
|
|
52
|
-
if (item.idle.workspaceId)
|
|
53
|
-
button.dataset.idleWorkspace = item.idle.workspaceId;
|
|
54
|
-
}
|
|
55
|
-
actions.set(button, item);
|
|
56
|
-
if (cursor !== button)
|
|
57
|
-
element.insertBefore(button, cursor);
|
|
58
|
-
cursor = button.nextElementSibling;
|
|
59
|
-
}
|
|
60
|
-
for (const [key, button] of rows)
|
|
61
|
-
if (!keep.has(key)) {
|
|
62
|
-
button.remove();
|
|
63
|
-
rows.delete(key);
|
|
64
|
-
actions.delete(button);
|
|
65
|
-
}
|
|
33
|
+
const entries = state.items.map((item, index) => ({ item, key: item.id ?? `${item.action || ''}/${item.sdkAction || ''}/${index}` }));
|
|
34
|
+
reconcileKeyed(element, rows, entries, { key: entry => entry.key, element: button => button,
|
|
35
|
+
create() { const button = document.createElement('button'); button.type = 'button'; button.setAttribute('role', 'menuitem'); return button; },
|
|
36
|
+
update(button, { item }) {
|
|
37
|
+
parts.action(button).update({ label: item.label, disabled: !!item.disabled });
|
|
38
|
+
button.classList.toggle('pui-destructive-menu-item', !!item.danger);
|
|
39
|
+
if (item.action)
|
|
40
|
+
button.dataset.action = item.action;
|
|
41
|
+
else
|
|
42
|
+
delete button.dataset.action;
|
|
43
|
+
if (item.sdkAction)
|
|
44
|
+
button.dataset.sdk = item.sdkAction;
|
|
45
|
+
else
|
|
46
|
+
delete button.dataset.sdk;
|
|
47
|
+
for (const name of ['idleAction', 'idleConversation', 'idleWorkspace'])
|
|
48
|
+
delete button.dataset[name];
|
|
49
|
+
if (item.idle) {
|
|
50
|
+
button.dataset.idleAction = '';
|
|
51
|
+
if (item.idle.conversationId)
|
|
52
|
+
button.dataset.idleConversation = item.idle.conversationId;
|
|
53
|
+
if (item.idle.workspaceId)
|
|
54
|
+
button.dataset.idleWorkspace = item.idle.workspaceId;
|
|
55
|
+
}
|
|
56
|
+
actions.set(button, item);
|
|
57
|
+
}, destroy(button) { actions.delete(button); },
|
|
58
|
+
});
|
|
66
59
|
parts.update();
|
|
67
60
|
};
|
|
68
61
|
if (options.onAction)
|
|
69
|
-
element.addEventListener('click', event => { const button = event.target.closest('button'); const item = button ? actions.get(button) : undefined; if (item && !button.disabled)
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
62
|
+
element.addEventListener('click', event => { const button = event.target.closest('button'); const item = button ? actions.get(button) : undefined; if (item && !button.disabled) {
|
|
63
|
+
event.stopPropagation();
|
|
64
|
+
options.onAction(item);
|
|
65
|
+
} }, { signal: abort.signal });
|
|
66
|
+
return { element, update, close, open(source, state, anchor = {}) {
|
|
67
|
+
if (destroyed)
|
|
68
|
+
return;
|
|
69
|
+
close();
|
|
70
|
+
update(state);
|
|
71
|
+
source.focus({ preventScroll: true });
|
|
72
|
+
surface = installAnchoredSurface({ trigger: source, panel: element, dismissOnMove: true,
|
|
73
|
+
...(anchor.point ? { getAnchor: () => ({ left: anchor.point.x, right: anchor.point.x, top: anchor.point.y, bottom: anchor.point.y, width: 0, height: 0 }) } : {}),
|
|
74
|
+
onToggle(open, restoreFocus) { if (!open && !programmaticClose)
|
|
75
|
+
options.onDismiss?.(!!restoreFocus); }, });
|
|
76
|
+
surface.open();
|
|
77
|
+
navigation.focus();
|
|
78
|
+
if (surface.isOpen() && !element.contains(document.activeElement))
|
|
79
|
+
element.focus({ preventScroll: true });
|
|
80
|
+
}, destroy() { if (destroyed)
|
|
78
81
|
return; destroyed = true; close(); navigation.destroy(); abort.abort(); parts.destroy(); rows.clear(); actions.clear(); if (!options.element)
|
|
79
82
|
element.remove(); } };
|
|
80
83
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-menu.js","sourceRoot":"","sources":["../../src/navigation/context-menu.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"context-menu.js","sourceRoot":"","sources":["../../src/navigation/context-menu.ts"],"names":[],"mappings":"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","sourcesContent":["import type { UIBlock } from '../core.js';\nimport { installAnchoredSurface, installMenuNavigation } from '../surface.js';\nimport { adoptProductParts } from '../foundations.js';\nimport { reconcileKeyed } from '../reconcile.js';\nexport interface ContextMenuItem {\n id?: string; label: string; action?: string; sdkAction?: string; danger?: boolean; disabled?: boolean;\n idle?: {conversationId?: string; workspaceId?: string};\n}\nexport interface ContextMenuState {label: string; items: readonly ContextMenuItem[]}\nexport interface ContextMenuOpenOptions {point?: {x: number; y: number}}\nexport function createContextMenu(options: {element?: HTMLElement; onDismiss?: (restoreFocus: boolean) => void; onAction?: (item: ContextMenuItem) => void} = {}): UIBlock<ContextMenuState> & {open(trigger: HTMLElement, state: ContextMenuState, options?: ContextMenuOpenOptions): void; close(restoreFocus?: boolean): void} {\n const element = options.element || document.createElement('div');\n if (!options.element) {element.className = 'pui-sidebar-conversation-menu pui-context-menu'; element.setAttribute('role', 'menu'); element.hidden = true;}\n element.setAttribute('role', 'menu'); element.tabIndex = -1;\n const abort = new AbortController(); let destroyed = false, programmaticClose = false;\n let surface: ReturnType<typeof installAnchoredSurface> | undefined;\n const parts = adoptProductParts(element);\n const rows = new Map<string, HTMLButtonElement>();\n const actions = new Map<HTMLButtonElement, ContextMenuItem>();\n const close = (restoreFocus = false) => {\n programmaticClose = true;\n surface?.close(restoreFocus); surface?.destroy(); surface = undefined;\n element.hidden = true; programmaticClose = false;\n };\n const dismiss = (restoreFocus: boolean) => {close(restoreFocus); options.onDismiss?.(restoreFocus);};\n const navigation = installMenuNavigation(element, {onDismiss: dismiss, isOpen: () => surface?.isOpen() ?? false});\n const update = (state: Readonly<ContextMenuState>) => {\n if (destroyed) return; element.setAttribute('aria-label', state.label);\n const entries = state.items.map((item, index) => ({item, key: item.id ?? `${item.action || ''}/${item.sdkAction || ''}/${index}`}));\n reconcileKeyed(element, rows, entries, {key: entry => entry.key, element: button => button,\n create() {const button = document.createElement('button'); button.type = 'button'; button.setAttribute('role', 'menuitem'); return button;},\n update(button, {item}) {\n parts.action(button).update({label: item.label, disabled: !!item.disabled});\n button.classList.toggle('pui-destructive-menu-item', !!item.danger);\n if (item.action) button.dataset.action = item.action; else delete button.dataset.action;\n if (item.sdkAction) button.dataset.sdk = item.sdkAction; else delete button.dataset.sdk;\n for (const name of ['idleAction', 'idleConversation', 'idleWorkspace']) delete button.dataset[name];\n if (item.idle) {button.dataset.idleAction = ''; if (item.idle.conversationId) button.dataset.idleConversation = item.idle.conversationId; if (item.idle.workspaceId) button.dataset.idleWorkspace = item.idle.workspaceId;}\n actions.set(button, item);\n }, destroy(button) {actions.delete(button);},\n });\n parts.update();\n };\n if (options.onAction) element.addEventListener('click', event => {const button = (event.target as Element).closest<HTMLButtonElement>('button'); const item = button ? actions.get(button) : undefined; if (item && !button!.disabled) {event.stopPropagation();options.onAction!(item);}}, {signal: abort.signal});\n return {element, update, close, open(source, state, anchor = {}) {\n if (destroyed) return;\n close(); update(state); source.focus({preventScroll: true});\n surface = installAnchoredSurface({trigger: source, panel: element, dismissOnMove: true,\n ...(anchor.point ? {getAnchor: () => ({left: anchor.point!.x, right: anchor.point!.x, top: anchor.point!.y, bottom: anchor.point!.y, width: 0, height: 0})} : {}),\n onToggle(open, restoreFocus) {if (!open && !programmaticClose) options.onDismiss?.(!!restoreFocus);},\n });\n surface.open(); navigation.focus();\n if (surface.isOpen() && !element.contains(document.activeElement)) element.focus({preventScroll: true});\n }, destroy() {if (destroyed) return; destroyed = true; close(); navigation.destroy(); abort.abort(); parts.destroy(); rows.clear(); actions.clear(); if (!options.element) element.remove();}};\n}\n"]}
|
|
@@ -20,11 +20,24 @@ export interface WorkspaceNavigationState {
|
|
|
20
20
|
empty: 'workspaces' | 'search' | null;
|
|
21
21
|
disabled?: boolean;
|
|
22
22
|
}
|
|
23
|
+
export type WorkspaceNavigationAction = {
|
|
24
|
+
action: 'add-workspace';
|
|
25
|
+
trigger: HTMLButtonElement;
|
|
26
|
+
} | {
|
|
27
|
+
action: 'new-conversation' | 'workspace-menu';
|
|
28
|
+
workspaceId: string;
|
|
29
|
+
trigger: HTMLButtonElement;
|
|
30
|
+
} | {
|
|
31
|
+
action: 'conversation-menu';
|
|
32
|
+
conversationId: string;
|
|
33
|
+
trigger: HTMLButtonElement;
|
|
34
|
+
};
|
|
23
35
|
export declare function createWorkspaceNavigation(initial: WorkspaceNavigationState, options?: {
|
|
24
36
|
element?: HTMLElement;
|
|
25
37
|
idPrefix?: string;
|
|
26
38
|
onToggle?: (id: string) => void;
|
|
27
39
|
onSelect?: (id: string) => void;
|
|
40
|
+
onAction?: (action: WorkspaceNavigationAction) => void;
|
|
28
41
|
}): UIBlock<WorkspaceNavigationState>;
|
|
29
42
|
export interface RenameConversationState {
|
|
30
43
|
id: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"navigation.d.ts","sourceRoot":"","sources":["../../src/navigation/navigation.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"navigation.d.ts","sourceRoot":"","sources":["../../src/navigation/navigation.ts"],"names":[],"mappings":"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"}
|