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.
Files changed (140) hide show
  1. package/AI.md +33 -8
  2. package/API.md +424 -268
  3. package/APP-API.md +2019 -0
  4. package/APP.md +137 -0
  5. package/README.md +37 -4
  6. package/dist/app/files.d.ts +68 -0
  7. package/dist/app/files.d.ts.map +1 -0
  8. package/dist/app/files.js +177 -0
  9. package/dist/app/files.js.map +1 -0
  10. package/dist/app/index.d.ts +57 -0
  11. package/dist/app/index.d.ts.map +1 -0
  12. package/dist/app/index.js +300 -0
  13. package/dist/app/index.js.map +1 -0
  14. package/dist/app/internal.d.ts +31 -0
  15. package/dist/app/internal.d.ts.map +1 -0
  16. package/dist/app/internal.js +2 -0
  17. package/dist/app/internal.js.map +1 -0
  18. package/dist/app/resources.d.ts +89 -0
  19. package/dist/app/resources.d.ts.map +1 -0
  20. package/dist/app/resources.js +190 -0
  21. package/dist/app/resources.js.map +1 -0
  22. package/dist/app/session.d.ts +14 -0
  23. package/dist/app/session.d.ts.map +1 -0
  24. package/dist/app/session.js +12 -0
  25. package/dist/app/session.js.map +1 -0
  26. package/dist/app/settings.d.ts +109 -0
  27. package/dist/app/settings.d.ts.map +1 -0
  28. package/dist/app/settings.js +279 -0
  29. package/dist/app/settings.js.map +1 -0
  30. package/dist/app/workspace.d.ts +228 -0
  31. package/dist/app/workspace.d.ts.map +1 -0
  32. package/dist/app/workspace.js +402 -0
  33. package/dist/app/workspace.js.map +1 -0
  34. package/dist/composer.d.ts.map +1 -1
  35. package/dist/composer.js +37 -27
  36. package/dist/composer.js.map +1 -1
  37. package/dist/content/conversation-reader.d.ts.map +1 -1
  38. package/dist/content/conversation-reader.js +8 -1
  39. package/dist/content/conversation-reader.js.map +1 -1
  40. package/dist/content/conversation-view.d.ts.map +1 -1
  41. package/dist/content/conversation-view.js +34 -8
  42. package/dist/content/conversation-view.js.map +1 -1
  43. package/dist/content/image-viewer.d.ts.map +1 -1
  44. package/dist/content/image-viewer.js +11 -3
  45. package/dist/content/image-viewer.js.map +1 -1
  46. package/dist/content/paged-preview.d.ts +1 -1
  47. package/dist/content/paged-preview.d.ts.map +1 -1
  48. package/dist/content/paged-preview.js +4 -2
  49. package/dist/content/paged-preview.js.map +1 -1
  50. package/dist/content/views.d.ts +3 -0
  51. package/dist/content/views.d.ts.map +1 -1
  52. package/dist/content/views.js +110 -41
  53. package/dist/content/views.js.map +1 -1
  54. package/dist/content/welcome.d.ts.map +1 -1
  55. package/dist/content/welcome.js +5 -2
  56. package/dist/content/welcome.js.map +1 -1
  57. package/dist/dom.js +1 -1
  58. package/dist/dom.js.map +1 -1
  59. package/dist/files/panels.d.ts +2 -0
  60. package/dist/files/panels.d.ts.map +1 -1
  61. package/dist/files/panels.js +202 -128
  62. package/dist/files/panels.js.map +1 -1
  63. package/dist/files/systems.d.ts.map +1 -1
  64. package/dist/files/systems.js +37 -64
  65. package/dist/files/systems.js.map +1 -1
  66. package/dist/forms/actions.d.ts +24 -2
  67. package/dist/forms/actions.d.ts.map +1 -1
  68. package/dist/forms/actions.js +54 -25
  69. package/dist/forms/actions.js.map +1 -1
  70. package/dist/forms/custom-connection.d.ts.map +1 -1
  71. package/dist/forms/custom-connection.js +3 -2
  72. package/dist/forms/custom-connection.js.map +1 -1
  73. package/dist/forms/history.d.ts +1 -1
  74. package/dist/forms/history.d.ts.map +1 -1
  75. package/dist/forms/history.js +78 -15
  76. package/dist/forms/history.js.map +1 -1
  77. package/dist/forms/identity.d.ts.map +1 -1
  78. package/dist/forms/identity.js +9 -25
  79. package/dist/forms/identity.js.map +1 -1
  80. package/dist/forms/model-editor.js +3 -3
  81. package/dist/forms/model-editor.js.map +1 -1
  82. package/dist/forms/panels.d.ts +9 -2
  83. package/dist/forms/panels.d.ts.map +1 -1
  84. package/dist/forms/panels.js +79 -88
  85. package/dist/forms/panels.js.map +1 -1
  86. package/dist/forms/provider-login.d.ts.map +1 -1
  87. package/dist/forms/provider-login.js +20 -36
  88. package/dist/forms/provider-login.js.map +1 -1
  89. package/dist/forms/resource-editor.js +5 -4
  90. package/dist/forms/resource-editor.js.map +1 -1
  91. package/dist/foundations.d.ts +1 -1
  92. package/dist/foundations.d.ts.map +1 -1
  93. package/dist/foundations.js +22 -38
  94. package/dist/foundations.js.map +1 -1
  95. package/dist/navigation/context-menu.d.ts +7 -1
  96. package/dist/navigation/context-menu.d.ts.map +1 -1
  97. package/dist/navigation/context-menu.js +60 -57
  98. package/dist/navigation/context-menu.js.map +1 -1
  99. package/dist/navigation/navigation.d.ts +13 -0
  100. package/dist/navigation/navigation.d.ts.map +1 -1
  101. package/dist/navigation/navigation.js +96 -130
  102. package/dist/navigation/navigation.js.map +1 -1
  103. package/dist/operation.d.ts +12 -0
  104. package/dist/operation.d.ts.map +1 -0
  105. package/dist/operation.js +49 -0
  106. package/dist/operation.js.map +1 -0
  107. package/dist/primitives.d.ts +8 -1
  108. package/dist/primitives.d.ts.map +1 -1
  109. package/dist/primitives.js +114 -143
  110. package/dist/primitives.js.map +1 -1
  111. package/dist/reconcile.d.ts +11 -0
  112. package/dist/reconcile.d.ts.map +1 -0
  113. package/dist/reconcile.js +36 -0
  114. package/dist/reconcile.js.map +1 -0
  115. package/dist/select.d.ts +14 -0
  116. package/dist/select.d.ts.map +1 -0
  117. package/dist/select.js +304 -0
  118. package/dist/select.js.map +1 -0
  119. package/dist/styles.css +439 -370
  120. package/dist/surface.d.ts +31 -0
  121. package/dist/surface.d.ts.map +1 -1
  122. package/dist/surface.js +193 -3
  123. package/dist/surface.js.map +1 -1
  124. package/dist/tasks/approval.d.ts.map +1 -1
  125. package/dist/tasks/approval.js +83 -45
  126. package/dist/tasks/approval.js.map +1 -1
  127. package/dist/tasks/permission-element.d.ts +3 -0
  128. package/dist/tasks/permission-element.d.ts.map +1 -0
  129. package/dist/tasks/permission-element.js +10 -0
  130. package/dist/tasks/permission-element.js.map +1 -0
  131. package/dist/tasks/permission.d.ts.map +1 -1
  132. package/dist/tasks/permission.js +37 -18
  133. package/dist/tasks/permission.js.map +1 -1
  134. package/dist/tasks/runtime.d.ts.map +1 -1
  135. package/dist/tasks/runtime.js +32 -15
  136. package/dist/tasks/runtime.js.map +1 -1
  137. package/dist/workspace.d.ts.map +1 -1
  138. package/dist/workspace.js +93 -40
  139. package/dist/workspace.js.map +1 -1
  140. package/package.json +42 -8
@@ -1,8 +1,9 @@
1
- import { controlDisabled, Generation, Lifetime, setControlPending } from './core.js';
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
- const seq = generation.next();
60
- localPending = true;
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; generation?.destroy(); life?.destroy(); } };
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
- control.focus(); }, destroy() { disposed = true; life?.destroy(); } };
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;
@@ -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;AAG1C,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,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,GAAG,IAAI,CAAC;IAAC,KAAK,CAAC,YAAY,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;CAAC,CAkC9R"}
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 trigger = null;
12
- let destroyed = false;
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) => { element.hidden = true; trigger?.setAttribute('aria-expanded', 'false'); if (restoreFocus)
17
- trigger?.focus(); trigger = null; };
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: () => !element.hidden, closeOnOutside: true, contains: target => !!trigger?.contains(target) });
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 keep = new Set();
25
- let cursor = element.firstElementChild;
26
- for (const [index, item] of state.items.entries()) {
27
- const key = item.id ?? `${item.action || ''}/${item.sdkAction || ''}/${index}`;
28
- keep.add(key);
29
- let button = rows.get(key);
30
- if (!button) {
31
- button = document.createElement('button');
32
- button.type = 'button';
33
- button.setAttribute('role', 'menuitem');
34
- rows.set(key, button);
35
- }
36
- parts.action(button).update({ label: item.label, disabled: !!item.disabled });
37
- button.classList.toggle('pui-destructive-menu-item', !!item.danger);
38
- if (item.action)
39
- button.dataset.action = item.action;
40
- else
41
- delete button.dataset.action;
42
- if (item.sdkAction)
43
- button.dataset.sdk = item.sdkAction;
44
- else
45
- delete button.dataset.sdk;
46
- for (const name of ['idleAction', 'idleConversation', 'idleWorkspace'])
47
- delete button.dataset[name];
48
- if (item.idle) {
49
- button.dataset.idleAction = '';
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
- options.onAction(item); }, { signal: abort.signal });
71
- const onScroll = (event) => { if (!element.hidden && event.target instanceof Node && !element.contains(event.target))
72
- dismiss(false); };
73
- document.addEventListener('scroll', onScroll, { capture: true, passive: true, signal: abort.signal });
74
- window.addEventListener('resize', () => { if (!element.hidden)
75
- dismiss(false); }, { signal: abort.signal });
76
- return { element, update, close, open(source, state) { if (destroyed)
77
- return; close(); trigger = source; trigger.setAttribute('aria-expanded', 'true'); update(state); element.hidden = false; const rect = source.getBoundingClientRect(); element.style.left = `${Math.max(8, Math.min(rect.right, window.innerWidth - element.offsetWidth - 8))}px`; element.style.top = `${Math.max(8, Math.min(rect.bottom + 4, window.innerHeight - element.offsetHeight - 8))}px`; navigation.focus(); }, destroy() { if (destroyed)
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;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAMtD,MAAM,UAAU,iBAAiB,CAAC,UAA4H,EAAE;IAC9J,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IACjE,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QAAA,OAAO,CAAC,SAAS,GAAG,gDAAgD,CAAC;QAAC,OAAO,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAAA,CAAC;IAC1J,MAAM,KAAK,GAAG,IAAI,eAAe,EAAE,CAAC;IAAC,IAAI,OAAO,GAAuB,IAAI,CAAC;IAAC,IAAI,SAAS,GAAG,KAAK,CAAC;IACnG,MAAM,KAAK,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,IAAI,GAAG,EAA6B,CAAC;IAClD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAsC,CAAC;IAC9D,MAAM,KAAK,GAAG,CAAC,YAAY,GAAG,KAAK,EAAE,EAAE,GAAE,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,OAAO,EAAE,YAAY,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,YAAY;QAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,CAAA,CAAC,CAAC;IACtK,MAAM,OAAO,GAAG,CAAC,YAAqB,EAAE,EAAE,GAAE,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,YAAY,CAAC,CAAC,CAAA,CAAC,CAAC;IACrG,MAAM,UAAU,GAAG,qBAAqB,CAAC,OAAO,EAAE,EAAC,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAC,CAAC,CAAC;IAC9K,MAAM,MAAM,GAAG,CAAC,KAAiC,EAAE,EAAE;QACnD,IAAI,SAAS;YAAE,OAAO;QAAC,OAAO,CAAC,YAAY,CAAC,YAAY,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QACvE,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAAC,IAAI,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;QACvE,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;YAClD,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC,MAAM,IAAI,EAAE,IAAI,IAAI,CAAC,SAAS,IAAI,EAAE,IAAI,KAAK,EAAE,CAAC;YAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC9F,IAAI,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC3B,IAAI,CAAC,MAAM,EAAE,CAAC;gBAAA,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;gBAAC,MAAM,CAAC,IAAI,GAAG,QAAQ,CAAC;gBAAC,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;gBAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;YAAA,CAAC;YACjJ,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,EAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAC,CAAC,CAAC;YAC5E,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,2BAA2B,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACpE,IAAI,IAAI,CAAC,MAAM;gBAAE,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;;gBAAM,OAAO,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;YACxF,IAAI,IAAI,CAAC,SAAS;gBAAE,MAAM,CAAC,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC;;gBAAM,OAAO,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC;YACxF,KAAK,MAAM,IAAI,IAAI,CAAC,YAAY,EAAE,kBAAkB,EAAE,eAAe,CAAC;gBAAE,OAAO,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACpG,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBAAA,MAAM,CAAC,OAAO,CAAC,UAAU,GAAG,EAAE,CAAC;gBAAC,IAAI,IAAI,CAAC,IAAI,CAAC,cAAc;oBAAE,MAAM,CAAC,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC;gBAAC,IAAI,IAAI,CAAC,IAAI,CAAC,WAAW;oBAAE,MAAM,CAAC,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC;YAAA,CAAC;YAC3N,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAC1B,IAAI,MAAM,KAAK,MAAM;gBAAE,OAAO,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YAAC,MAAM,GAAG,MAAM,CAAC,kBAAkB,CAAC;QAClG,CAAC;QACD,KAAK,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,IAAI;YAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBAAA,MAAM,CAAC,MAAM,EAAE,CAAC;gBAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAAA,CAAC;QAClH,KAAK,CAAC,MAAM,EAAE,CAAC;IACjB,CAAC,CAAC;IACF,IAAI,OAAO,CAAC,QAAQ;QAAE,OAAO,CAAC,gBAAgB,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,GAAE,MAAM,MAAM,GAAI,KAAK,CAAC,MAAkB,CAAC,OAAO,CAAoB,QAAQ,CAAC,CAAC,CAAC,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,MAAO,CAAC,QAAQ;YAAE,OAAO,CAAC,QAAS,CAAC,IAAI,CAAC,CAAC,CAAA,CAAC,EAAE,EAAC,MAAM,EAAE,KAAK,CAAC,MAAM,EAAC,CAAC,CAAC;IAC1R,MAAM,QAAQ,GAAG,CAAC,KAAY,EAAE,EAAE,GAAE,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,YAAY,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC;QAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAA,CAAC,CAAC;IAC7I,QAAQ,CAAC,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,EAAE,EAAC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAC,CAAC,CAAC;IACpG,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAE,IAAI,CAAC,OAAO,CAAC,MAAM;QAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAA,CAAC,EAAE,EAAC,MAAM,EAAE,KAAK,CAAC,MAAM,EAAC,CAAC,CAAC;IACxG,OAAO,EAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,IAAG,IAAI,SAAS;YAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,OAAO,GAAG,MAAM,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,MAAM,IAAI,GAAG,MAAM,CAAC,qBAAqB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,UAAU,GAAG,OAAO,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,MAAM,CAAC,WAAW,GAAG,OAAO,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC,CAAA,CAAC,EAAE,OAAO,KAAI,IAAI,SAAS;YAAE,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO;YAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA,CAAC,EAAC,CAAC;AAC5pB,CAAC","sourcesContent":["import type { UIBlock } from '../core.js';\nimport { installMenuNavigation } from '../surface.js';\nimport { adoptProductParts } from '../foundations.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 function createContextMenu(options: {element?: HTMLElement; onDismiss?: (restoreFocus: boolean) => void; onAction?: (item: ContextMenuItem) => void} = {}): UIBlock<ContextMenuState> & {open(trigger: HTMLElement, state: ContextMenuState): 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 const abort = new AbortController(); let trigger: HTMLElement | null = null; let destroyed = false;\n const parts = adoptProductParts(element);\n const rows = new Map<string, HTMLButtonElement>();\n const actions = new Map<HTMLButtonElement, ContextMenuItem>();\n const close = (restoreFocus = false) => {element.hidden = true; trigger?.setAttribute('aria-expanded', 'false'); if (restoreFocus) trigger?.focus(); trigger = null;};\n const dismiss = (restoreFocus: boolean) => {close(restoreFocus); options.onDismiss?.(restoreFocus);};\n const navigation = installMenuNavigation(element, {onDismiss: dismiss, isOpen: () => !element.hidden, closeOnOutside: true, contains: target => !!trigger?.contains(target)});\n const update = (state: Readonly<ContextMenuState>) => {\n if (destroyed) return; element.setAttribute('aria-label', state.label);\n const keep = new Set<string>(); let cursor = element.firstElementChild;\n for (const [index, item] of state.items.entries()) {\n const key = item.id ?? `${item.action || ''}/${item.sdkAction || ''}/${index}`; keep.add(key);\n let button = rows.get(key);\n if (!button) {button = document.createElement('button'); button.type = 'button'; button.setAttribute('role', 'menuitem'); rows.set(key, button);}\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 if (cursor !== button) element.insertBefore(button, cursor); cursor = button.nextElementSibling;\n }\n for (const [key, button] of rows) if (!keep.has(key)) {button.remove(); rows.delete(key); actions.delete(button);}\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) options.onAction!(item);}, {signal: abort.signal});\n const onScroll = (event: Event) => {if (!element.hidden && event.target instanceof Node && !element.contains(event.target)) dismiss(false);};\n document.addEventListener('scroll', onScroll, {capture: true, passive: true, signal: abort.signal});\n window.addEventListener('resize', () => {if (!element.hidden) dismiss(false);}, {signal: abort.signal});\n return {element, update, close, open(source, state) {if (destroyed) return; close(); trigger = source; trigger.setAttribute('aria-expanded', 'true'); update(state); element.hidden = false; const rect = source.getBoundingClientRect(); element.style.left = `${Math.max(8, Math.min(rect.right, window.innerWidth - element.offsetWidth - 8))}px`; element.style.top = `${Math.max(8, Math.min(rect.bottom + 4, window.innerHeight - element.offsetHeight - 8))}px`; navigation.focus();}, destroy() {if (destroyed) return; destroyed = true; close(); navigation.destroy(); abort.abort(); parts.destroy(); rows.clear(); actions.clear(); if (!options.element) element.remove();}};\n}\n"]}
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,EAAwB,KAAK,YAAY,EAAE,KAAK,OAAO,EAAE,MAAM,YAAY,CAAC;AAInF,MAAM,WAAW,sBAAsB;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,IAAI,GAAG,IAAI,CAAA;CAAC;AAC/H,MAAM,WAAW,mBAAmB;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,SAAS,sBAAsB,EAAE,CAAA;CAAC;AACpL,MAAM,WAAW,wBAAwB;IAAE,MAAM,EAAE,SAAS,mBAAmB,EAAE,CAAC;IAAC,KAAK,EAAE,YAAY,GAAG,QAAQ,GAAG,IAAI,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAC;AAG7I,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,wBAAwB,EAAE,OAAO,GAAE;IAAC,OAAO,CAAC,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;CAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAsD1O;AACD,MAAM,WAAW,uBAAuB;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAC;AACxG,MAAM,WAAW,uBAAuB;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC;AACpE,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC;IAC5B,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,uBAAuB,KAAK,OAAO,CAAC,YAAY,CAAC,GAAG,YAAY,CAAC;IACpF,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AACD,MAAM,WAAW,uBAAwB,SAAQ,OAAO,CAAC,uBAAuB,CAAC;IAC/E,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;IACjC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,IAAI,IAAI,uBAAuB,CAAC;IAChC,KAAK,CAAC,KAAK,EAAE,uBAAuB,GAAG,IAAI,CAAC;IAC5C,IAAI,CAAC,KAAK,CAAC,EAAE,uBAAuB,GAAG,IAAI,CAAC;IAC5C,KAAK,IAAI,IAAI,CAAC;IACd,KAAK,IAAI,IAAI,CAAC;CACf;AACD,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,uBAAuB,EAAE,OAAO,GAAE,yBAA8B,GAAG,uBAAuB,CA8B3I;AACD,MAAM,WAAW,oBAAoB;IAAE,UAAU,EAAE,SAAS;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,EAAE,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAC;AAC3I,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC;IAC5B,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,CAAC,GAAG,YAAY,CAAC;IAClE,MAAM,CAAC,EAAE,MAAM,OAAO,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAC,CAAC,CAAC;IACxD,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AACD,MAAM,WAAW,oBAAqB,SAAQ,OAAO,CAAC,oBAAoB,CAAC;IACzE,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;IACjC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,iBAAiB,CAAC;IACvC,IAAI,IAAI;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC;IACvB,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,IAAI,IAAI,IAAI,CAAC;IACb,KAAK,IAAI,IAAI,CAAC;IACd,KAAK,IAAI,IAAI,CAAC;CACf;AACD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,oBAAoB,EAAE,OAAO,GAAE,sBAA2B,GAAG,oBAAoB,CA2D/H"}
1
+ {"version":3,"file":"navigation.d.ts","sourceRoot":"","sources":["../../src/navigation/navigation.ts"],"names":[],"mappings":"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"}