@aceshooting/lyra-ui 24.0.0 → 24.1.0
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/CHANGELOG.md +11 -0
- package/custom-elements.json +1 -1
- package/dist/components/conversation/agent-workspace/agent-workspace.class.d.ts +11 -1
- package/dist/components/conversation/agent-workspace/agent-workspace.class.js +1 -1
- package/dist/components/forms/swatch-picker/swatch-picker.class.d.ts +3 -1
- package/dist/components/forms/swatch-picker/swatch-picker.class.js +1 -1
- package/dist/internal/package-metadata.d.ts +1 -1
- package/dist/internal/package-metadata.js +1 -1
- package/llms/components/lr-agent-workspace.md +23 -1
- package/llms/components/lr-swatch-picker.md +3 -2
- package/llms/shared/events-and-types.md +8 -8
- package/llms/shared.md +8 -8
- package/package.json +1 -1
- package/web-types.json +1 -1
|
@@ -15,6 +15,10 @@ import type{MarkdownStreamingRender}from'../markdown/markdown-shared.js';import
|
|
|
15
15
|
* Composer value, follow state, and retrieval selection are request-only:
|
|
16
16
|
* child events are forwarded, but the workspace never writes those public
|
|
17
17
|
* properties. The host applies accepted state back to the component.
|
|
18
|
+
* A vetoed tool approval in the built-in timeline stays pending until the host calls
|
|
19
|
+
* `finalizePendingApproval()` after persistence or `revertPendingApproval()` after failure.
|
|
20
|
+
* Async hosts must ignore stale completions after replacing the run or tools because these
|
|
21
|
+
* methods act on the currently pending approval.
|
|
18
22
|
*
|
|
19
23
|
* Public collection properties take bounded, clone-owned readonly snapshots. Create a new
|
|
20
24
|
* collection and reassign it after changes; mutating the assigned array does not update the view.
|
|
@@ -117,7 +121,13 @@ private composerStatusValue;get composerStatus():ChatComposerStatus;set composer
|
|
|
117
121
|
/** Placeholder for the built-in composer. */
|
|
118
122
|
composerPlaceholder?:string;
|
|
119
123
|
/** Minimum and maximum rows for the built-in composer. */
|
|
120
|
-
composerMinRows:number;composerMaxRows:number;private hasSlotted;private
|
|
124
|
+
composerMinRows:number;composerMaxRows:number;private hasSlotted;private builtInToolTimeline;
|
|
125
|
+
/** Closes a vetoed approval in the built-in tool timeline after the host persists its decision.
|
|
126
|
+
* No-op when that timeline or a pending approval is absent, including with a custom details slot. */
|
|
127
|
+
finalizePendingApproval():void;
|
|
128
|
+
/** Releases a vetoed approval in the built-in tool timeline after persistence fails, preserving
|
|
129
|
+
* the open dialog and its edited arguments for retry. No-op without the built-in timeline. */
|
|
130
|
+
revertPendingApproval():void;private get safeContextTotal();private get effectiveTools();private get effectiveRetrievalChunks();private get effectiveCitations();private get effectiveContextSegments();private get effectiveMessages();private get safeUnreadStartIndex();private get safeComposerMinRows();private get safeComposerMaxRows();private onRetrievalSelect;private onMessageRetry;private stopOwnedEvent;private renderMessage;private renderMessages;private messageWindowOffsetFor;
|
|
121
131
|
/** Bound to every named slot whose assignment `render()` reads back through `hasSlotted()` --
|
|
122
132
|
* `messages` (which decides how `safeUnreadStartIndex` is projected), `details`, `composer`, and
|
|
123
133
|
* `header-actions` (whose empty wrapper is hidden).
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{__decorate}from"tslib";import{collectionSupport}from"../../../internal/collection-snapshot.js";import{html,nothing}from"lit";import{property}from"lit/decorators.js";import{repeat}from"lit/directives/repeat.js";import{LyraElement}from"../../../internal/lyra-element.js";import{finiteCount}from"../../../internal/numbers.js";import{normalizeChatComposerStatus}from"../chat-composer/chat-composer.class.js";import{styles}from"./agent-workspace.styles.js";import{trueDefaultBooleanConverter}from"../../../internal/converters.js";import{LYRA_DEFAULT_agentWorkspaceContext,LYRA_DEFAULT_agentWorkspaceConversation,LYRA_DEFAULT_agentWorkspaceDetails,LYRA_DEFAULT_agentWorkspaceEmpty,LYRA_DEFAULT_agentWorkspaceGrounding,LYRA_DEFAULT_agentWorkspaceLabel,LYRA_DEFAULT_agentWorkspaceRetrieval,LYRA_DEFAULT_agentWorkspaceRun,LYRA_DEFAULT_agentWorkspaceTools,LYRA_DEFAULT_composerPlaceholder,LYRA_DEFAULT_fieldRequired}from"../../../internal/default-strings.generated.js";const MAX_RENDERED_MESSAGES=500;function firstByWorkspaceIdentity(items,identity){const result=[],seen=new Set;for(const item of items){let id;try{id=identity(item)}catch{continue}typeof id!="string"||id.trim()===""||seen.has(id)||(seen.add(id),result.push(item))}return result}class LyraAgentWorkspace extends LyraElement{constructor(){super(...arguments),this.streamingRender="plain",this.accessibleLabel=null,this.messages=[],this.run=null,this.metrics=[],this.tools=[],this.retrievalChunks=[],this.selectedRetrievalChunkIds=[],this.retrievalLoading=!1,this.retrievalHasMore=!1,this.retrievalErrorText="",this.groundingAssessment=null,this.citations=[],this.contextSegments=[],this.contextTotal=0,this.follow=!0,this.unreadStartIndex=null,this.withoutDetails=!1,this.withoutComposer=!1,this.composerValue="",this.composerStatusValue="idle",this.composerMinRows=1,this.composerMaxRows=8,this.onRetrievalSelect=event=>{event.stopPropagation(),this.emit("lr-retrieval-select",event.detail)},this.onMessageRetry=event=>{event.stopPropagation(),event.detail.messageId&&this.emit("lr-message-retry",{messageId:event.detail.messageId})},this.onNamedSlotChange=()=>{this.requestUpdate()}}static{this.defaultStrings={...super.defaultStrings,agentWorkspaceContext:LYRA_DEFAULT_agentWorkspaceContext,agentWorkspaceConversation:LYRA_DEFAULT_agentWorkspaceConversation,agentWorkspaceDetails:LYRA_DEFAULT_agentWorkspaceDetails,agentWorkspaceEmpty:LYRA_DEFAULT_agentWorkspaceEmpty,agentWorkspaceGrounding:LYRA_DEFAULT_agentWorkspaceGrounding,agentWorkspaceLabel:LYRA_DEFAULT_agentWorkspaceLabel,agentWorkspaceRetrieval:LYRA_DEFAULT_agentWorkspaceRetrieval,agentWorkspaceRun:LYRA_DEFAULT_agentWorkspaceRun,agentWorkspaceTools:LYRA_DEFAULT_agentWorkspaceTools,composerPlaceholder:LYRA_DEFAULT_composerPlaceholder,fieldRequired:LYRA_DEFAULT_fieldRequired}}static{this.collectionSupport=collectionSupport}static{this.immutableEventDetails=Object.freeze(["lr-retrieval-select"])}static{this.ownedCollectionProperties=Object.freeze(["messages","run","metrics","tools","retrievalChunks","selectedRetrievalChunkIds","groundingAssessment","citations","contextSegments"])}static{this.styles=[LyraElement.styles,styles]}get composerStatus(){return this.composerStatusValue}set composerStatus(value){const previous=this.composerStatusValue;this.composerStatusValue=normalizeChatComposerStatus(value),this.requestUpdate("composerStatus",previous)}hasSlotted(name){return Array.from(this.children).some(element=>element.getAttribute("slot")===name)}get safeContextTotal(){return finiteCount(this.contextTotal)}get effectiveTools(){return firstByWorkspaceIdentity(this.tools,entry=>{const id=entry.id;if(typeof id!="string"||id.trim()==="")return;const sourceKey=entry.sourceKey;return`${typeof sourceKey=="string"?sourceKey:""}\0${id}`})}get effectiveRetrievalChunks(){return firstByWorkspaceIdentity(this.retrievalChunks,chunk=>chunk.id)}get effectiveCitations(){return firstByWorkspaceIdentity(this.citations,citation=>citation.id)}get effectiveContextSegments(){return firstByWorkspaceIdentity(this.contextSegments,segment=>segment.id)}get effectiveMessages(){const source=this.messages,seen=new Set,messages=[];for(let sourceIndex=0;sourceIndex<source.length;sourceIndex++){const message=source[sourceIndex];if(!message)continue;const id=message?.id;typeof id!="string"||id.trim()===""||seen.has(id)||(seen.add(id),messages.push({message,sourceIndex}))}return messages}get safeUnreadStartIndex(){if(this.unreadStartIndex==null)return null;const normalized=finiteCount(this.unreadStartIndex);if(this.hasSlotted("messages"))return normalized;const messages=this.effectiveMessages,effectiveIndex=messages.filter(({sourceIndex})=>sourceIndex<normalized).length;return Math.max(0,effectiveIndex-this.messageWindowOffsetFor(messages))}get safeComposerMinRows(){return Math.max(1,finiteCount(this.composerMinRows,1))}get safeComposerMaxRows(){return Math.max(this.safeComposerMinRows,finiteCount(this.composerMaxRows,8))}stopOwnedEvent(event){event.stopPropagation()}renderMessage(message){return html`
|
|
1
|
+
import{__decorate}from"tslib";import{collectionSupport}from"../../../internal/collection-snapshot.js";import{html,nothing}from"lit";import{property}from"lit/decorators.js";import{repeat}from"lit/directives/repeat.js";import{LyraElement}from"../../../internal/lyra-element.js";import{finiteCount}from"../../../internal/numbers.js";import{tag}from"../../../internal/prefix.js";import{normalizeChatComposerStatus}from"../chat-composer/chat-composer.class.js";import{styles}from"./agent-workspace.styles.js";import{trueDefaultBooleanConverter}from"../../../internal/converters.js";import{LYRA_DEFAULT_agentWorkspaceContext,LYRA_DEFAULT_agentWorkspaceConversation,LYRA_DEFAULT_agentWorkspaceDetails,LYRA_DEFAULT_agentWorkspaceEmpty,LYRA_DEFAULT_agentWorkspaceGrounding,LYRA_DEFAULT_agentWorkspaceLabel,LYRA_DEFAULT_agentWorkspaceRetrieval,LYRA_DEFAULT_agentWorkspaceRun,LYRA_DEFAULT_agentWorkspaceTools,LYRA_DEFAULT_composerPlaceholder,LYRA_DEFAULT_fieldRequired}from"../../../internal/default-strings.generated.js";const MAX_RENDERED_MESSAGES=500;function firstByWorkspaceIdentity(items,identity){const result=[],seen=new Set;for(const item of items){let id;try{id=identity(item)}catch{continue}typeof id!="string"||id.trim()===""||seen.has(id)||(seen.add(id),result.push(item))}return result}class LyraAgentWorkspace extends LyraElement{constructor(){super(...arguments),this.streamingRender="plain",this.accessibleLabel=null,this.messages=[],this.run=null,this.metrics=[],this.tools=[],this.retrievalChunks=[],this.selectedRetrievalChunkIds=[],this.retrievalLoading=!1,this.retrievalHasMore=!1,this.retrievalErrorText="",this.groundingAssessment=null,this.citations=[],this.contextSegments=[],this.contextTotal=0,this.follow=!0,this.unreadStartIndex=null,this.withoutDetails=!1,this.withoutComposer=!1,this.composerValue="",this.composerStatusValue="idle",this.composerMinRows=1,this.composerMaxRows=8,this.onRetrievalSelect=event=>{event.stopPropagation(),this.emit("lr-retrieval-select",event.detail)},this.onMessageRetry=event=>{event.stopPropagation(),event.detail.messageId&&this.emit("lr-message-retry",{messageId:event.detail.messageId})},this.onNamedSlotChange=()=>{this.requestUpdate()}}static{this.defaultStrings={...super.defaultStrings,agentWorkspaceContext:LYRA_DEFAULT_agentWorkspaceContext,agentWorkspaceConversation:LYRA_DEFAULT_agentWorkspaceConversation,agentWorkspaceDetails:LYRA_DEFAULT_agentWorkspaceDetails,agentWorkspaceEmpty:LYRA_DEFAULT_agentWorkspaceEmpty,agentWorkspaceGrounding:LYRA_DEFAULT_agentWorkspaceGrounding,agentWorkspaceLabel:LYRA_DEFAULT_agentWorkspaceLabel,agentWorkspaceRetrieval:LYRA_DEFAULT_agentWorkspaceRetrieval,agentWorkspaceRun:LYRA_DEFAULT_agentWorkspaceRun,agentWorkspaceTools:LYRA_DEFAULT_agentWorkspaceTools,composerPlaceholder:LYRA_DEFAULT_composerPlaceholder,fieldRequired:LYRA_DEFAULT_fieldRequired}}static{this.collectionSupport=collectionSupport}static{this.immutableEventDetails=Object.freeze(["lr-retrieval-select"])}static{this.ownedCollectionProperties=Object.freeze(["messages","run","metrics","tools","retrievalChunks","selectedRetrievalChunkIds","groundingAssessment","citations","contextSegments"])}static{this.styles=[LyraElement.styles,styles]}get composerStatus(){return this.composerStatusValue}set composerStatus(value){const previous=this.composerStatusValue;this.composerStatusValue=normalizeChatComposerStatus(value),this.requestUpdate("composerStatus",previous)}hasSlotted(name){return Array.from(this.children).some(element=>element.getAttribute("slot")===name)}builtInToolTimeline(){return this.withoutDetails||this.hasSlotted("details")?null:this.renderRoot?.querySelector(tag("tool-timeline"))??null}finalizePendingApproval(){this.builtInToolTimeline()?.finalizePendingApproval()}revertPendingApproval(){this.builtInToolTimeline()?.revertPendingApproval()}get safeContextTotal(){return finiteCount(this.contextTotal)}get effectiveTools(){return firstByWorkspaceIdentity(this.tools,entry=>{const id=entry.id;if(typeof id!="string"||id.trim()==="")return;const sourceKey=entry.sourceKey;return`${typeof sourceKey=="string"?sourceKey:""}\0${id}`})}get effectiveRetrievalChunks(){return firstByWorkspaceIdentity(this.retrievalChunks,chunk=>chunk.id)}get effectiveCitations(){return firstByWorkspaceIdentity(this.citations,citation=>citation.id)}get effectiveContextSegments(){return firstByWorkspaceIdentity(this.contextSegments,segment=>segment.id)}get effectiveMessages(){const source=this.messages,seen=new Set,messages=[];for(let sourceIndex=0;sourceIndex<source.length;sourceIndex++){const message=source[sourceIndex];if(!message)continue;const id=message?.id;typeof id!="string"||id.trim()===""||seen.has(id)||(seen.add(id),messages.push({message,sourceIndex}))}return messages}get safeUnreadStartIndex(){if(this.unreadStartIndex==null)return null;const normalized=finiteCount(this.unreadStartIndex);if(this.hasSlotted("messages"))return normalized;const messages=this.effectiveMessages,effectiveIndex=messages.filter(({sourceIndex})=>sourceIndex<normalized).length;return Math.max(0,effectiveIndex-this.messageWindowOffsetFor(messages))}get safeComposerMinRows(){return Math.max(1,finiteCount(this.composerMinRows,1))}get safeComposerMaxRows(){return Math.max(this.safeComposerMinRows,finiteCount(this.composerMaxRows,8))}stopOwnedEvent(event){event.stopPropagation()}renderMessage(message){return html`
|
|
2
2
|
<lr-chat-message
|
|
3
3
|
part="messages message"
|
|
4
4
|
.messageRole=${message.role}
|
|
@@ -35,6 +35,8 @@ readonly gemstone?:GemstoneKey;}export type LyraSwatchPickerMode='swatch'|'gemst
|
|
|
35
35
|
* display order and `value` still controls the initial selection. Live option reorders preserve
|
|
36
36
|
* focus by option identity; removing the focused option moves focus to the nearest surviving
|
|
37
37
|
* swatch without changing the controlled `value` or emitting `lr-change`.
|
|
38
|
+
* Equivalent fresh items retain their immutable snapshots and radio nodes without blurring
|
|
39
|
+
* keyboard focus. Duplicate values remain distinct occurrences; custom icons match by identity.
|
|
38
40
|
*
|
|
39
41
|
* `disabled` locks the whole picker: every swatch renders as a real `disabled` `<button>` (out of
|
|
40
42
|
* the tab sequence, inert to activation), keyboard navigation and `click()` become no-ops, and the
|
|
@@ -128,7 +130,7 @@ accessibleLabel:string;
|
|
|
128
130
|
* nothing and has no name, validity or reset semantics — so, exactly like a native `<div>`,
|
|
129
131
|
* it takes no disablement from an ancestor `<fieldset disabled>`. Disable the picker itself
|
|
130
132
|
* alongside the fieldset when a form needs both. */
|
|
131
|
-
disabled:boolean;private selectedOption?;private
|
|
133
|
+
disabled:boolean;private selectedOption?;private fallbackTabbableIndex;private pendingFocusIndex?;private resolveSelectedIndex;private select;private focusSwatch;protected willUpdate(changed:PropertyValues<this>):void;protected updated(changed:PropertyValues<this>):void;
|
|
132
134
|
/** The single `role="radio"` swatch that is currently in the roving tab sequence -- the
|
|
133
135
|
* selected one, the nearest survivor of a live palette mutation, or the first swatch when
|
|
134
136
|
* nothing has been selected yet. Mirrors the identical `tabbableIndex` fallback in `render()`. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{__decorate}from"tslib";import{html,nothing}from"lit";import{property}from"lit/decorators.js";import{repeat}from"lit/directives/repeat.js";import{styleMap}from"lit/directives/style-map.js";import{LyraElement}from"../../../internal/lyra-element.js";import{renderInertPresentation}from"../../../internal/inert-presentation.js";import{isRtl}from"../../../internal/rtl.js";import{gemstoneGlyph,gemstoneSelectedGlyphStyles}from"../../../theme/gemstones.js";import{styles}from"./swatch-picker.styles.js";import{sanitizeCssColor}from"../../../internal/safe-css.js";import{literalSetConverter}from"../../../internal/converters.js";import{activeElementIn}from"../../../internal/active-element.js";const SWATCH_PICKER_MODE=literalSetConverter(["swatch","gemstone"],"swatch");class LyraSwatchPicker extends LyraElement{constructor(){super(...arguments),this._items=Object.freeze([]),this.itemSnapshots=new WeakMap,this.value=null,this.size="m",this._mode="swatch",this.accessibleLabel="",this.disabled=!1,this.
|
|
1
|
+
import{__decorate}from"tslib";import{html,nothing}from"lit";import{property}from"lit/decorators.js";import{repeat}from"lit/directives/repeat.js";import{styleMap}from"lit/directives/style-map.js";import{LyraElement}from"../../../internal/lyra-element.js";import{renderInertPresentation}from"../../../internal/inert-presentation.js";import{isRtl}from"../../../internal/rtl.js";import{gemstoneGlyph,gemstoneSelectedGlyphStyles}from"../../../theme/gemstones.js";import{styles}from"./swatch-picker.styles.js";import{sanitizeCssColor}from"../../../internal/safe-css.js";import{literalSetConverter}from"../../../internal/converters.js";import{activeElementIn}from"../../../internal/active-element.js";const SWATCH_PICKER_MODE=literalSetConverter(["swatch","gemstone"],"swatch");class LyraSwatchPicker extends LyraElement{constructor(){super(...arguments),this._items=Object.freeze([]),this.itemSnapshots=new WeakMap,this.value=null,this.size="m",this._mode="swatch",this.accessibleLabel="",this.disabled=!1,this.fallbackTabbableIndex=0,this.onKeyDown=e=>{if(this.disabled)return;const navigable=this.items;if(navigable.length===0)return;const currentIndex=this.keyboardOriginIndex(e),rtl=isRtl(this),forwardKey=rtl?"ArrowLeft":"ArrowRight",backwardKey=rtl?"ArrowRight":"ArrowLeft";let targetIndex;switch(e.key){case forwardKey:targetIndex=currentIndex<0?0:(currentIndex+1)%navigable.length;break;case backwardKey:targetIndex=currentIndex<0?navigable.length-1:(currentIndex-1+navigable.length)%navigable.length;break;case"Home":targetIndex=0;break;case"End":targetIndex=navigable.length-1;break;default:return}e.preventDefault();const target=navigable[targetIndex];this.select(target,targetIndex),this.focusSwatch(targetIndex)}}static{this.styles=[LyraElement.styles,styles,gemstoneSelectedGlyphStyles]}static{this.properties={items:{attribute:!1,noAccessor:!0}}}get items(){return this._items}set items(next){const old=this._items,snapshots=[],rows=[],reserved=new Set;if(Array.isArray(next))for(let index=0;index<Math.min(next.length,512);index++)try{const raw=next[index];if(raw===null||typeof raw!="object")continue;rows.push(raw),reserved.add(this.itemSnapshots.get(raw))}catch{}const identities=new Map,identity=value=>(identities.has(value)||identities.set(value,identities.size),identities.get(value)),snapshotKey=item=>JSON.stringify([item.value,item.color,item.label,identity(item.gemstone),identity(item.icon)]),buckets=new Map;for(const item of[...old].reverse()){if(reserved.has(item))continue;const key=snapshotKey(item);let queue=buckets.get(key);queue||buckets.set(key,queue=[]),queue.push(item)}for(const raw of rows)try{let item=this.itemSnapshots.get(raw);if(item&&reserved.delete(item)){snapshots.push(item);continue}if(!item){const{value,color,label}=raw;if(typeof value!="string"||typeof color!="string"||typeof label!="string"||label.trim()==="")continue;const{icon,gemstone}=raw;item={value,color,label,...icon===void 0?{}:{icon},...gemstone===void 0?{}:{gemstone}}}const snapshot=buckets.get(snapshotKey(item))?.pop()??Object.freeze({...item});this.itemSnapshots.has(raw)||this.itemSnapshots.set(raw,snapshot),snapshots.push(snapshot)}catch{}this._items=Object.freeze(snapshots),this.requestUpdate("items",old)}get mode(){return this._mode}set mode(next){const normalized=SWATCH_PICKER_MODE.normalizeReflected(this,"mode",next),old=this._mode;old!==normalized&&(this._mode=normalized,this.requestUpdate("mode",old))}resolveSelectedIndex(){if(this.value===null)return this.selectedOption=void 0,-1;const identityIndex=this.selectedOption?.value===this.value?this.items.indexOf(this.selectedOption):-1,selectedIndex=identityIndex>=0?identityIndex:this.items.findIndex(option=>option.value===this.value);return this.selectedOption=this.items[selectedIndex],selectedIndex}select(option,index){if(this.disabled)return;const previousIndex=this.resolveSelectedIndex();if(index!==previousIndex||option.value!==this.value){const previousValue=this.value;this.selectedOption=option,this.value=option.value,previousValue===option.value&&this.requestUpdate(),this.emit("lr-change",{value:option.value})}this.emit("lr-activate",{value:option.value})}focusSwatch(index){if(this.disabled)return;this.renderRoot.querySelector(`[part="swatch"][data-index="${index}"]`)?.focus()}willUpdate(changed){if(super.willUpdate(changed),!changed.has("items"))return;const active=activeElementIn(this.shadowRoot);if(typeof active?.getAttribute!="function"||active.getAttribute("part")!=="swatch")return;const previousOptions=changed.get("items"),previousIndex=Number(active.dataset.index);if(!Number.isInteger(previousIndex)||previousIndex<0)return;const focusedOption=previousOptions?.[previousIndex],identityIndex=focusedOption===void 0?-1:this.items.indexOf(focusedOption),nextIndex=identityIndex>=0?identityIndex:Math.min(previousIndex,this.items.length-1);if(nextIndex<0){this.pendingFocusIndex=void 0,this.fallbackTabbableIndex=0;return}this.pendingFocusIndex=nextIndex,this.fallbackTabbableIndex=nextIndex}updated(changed){super.updated(changed),!(!changed.has("items")||this.pendingFocusIndex===void 0)&&this.scheduleAfterUpdate(()=>{const pendingIndex=this.pendingFocusIndex;this.pendingFocusIndex=void 0,!(pendingIndex===void 0||this.items.length===0)&&this.focusSwatch(Math.min(pendingIndex,this.items.length-1))},"restore-swatch-picker-focus")}tabbableSwatch(){const selectedIndex=this.resolveSelectedIndex(),tabbableIndex=selectedIndex!==-1?selectedIndex:Math.min(this.fallbackTabbableIndex,Math.max(0,this.items.length-1));return this.renderRoot?.querySelector(`[part="swatch"][data-index="${tabbableIndex}"]`)??null}click(){this.disabled||this.tabbableSwatch()?.click()}focus(options){this.disabled||this.tabbableSwatch()?.focus(options)}blur(){this.tabbableSwatch()?.blur()}keyboardOriginIndex(event){const fromEvent=event.composedPath().find(candidate2=>candidate2.nodeType===1&&candidate2.getAttribute?.("part")==="swatch"&&candidate2.getRootNode()===this.renderRoot),focused=activeElementIn(this.shadowRoot),candidate=fromEvent??(typeof focused?.getAttribute=="function"&&focused.getAttribute("part")==="swatch"?focused:void 0),index=Number(candidate?.dataset.index);return Number.isInteger(index)&&index>=0&&index<this.items.length?index:this.resolveSelectedIndex()}render(){const hostLabel=this.getAttribute("aria-label"),ariaLabel=hostLabel!==null?hostLabel:this.accessibleLabel||nothing,selectedIndex=this.resolveSelectedIndex(),tabbableIndex=selectedIndex!==-1?selectedIndex:Math.min(this.fallbackTabbableIndex,Math.max(0,this.items.length-1));return html`
|
|
2
2
|
<div
|
|
3
3
|
part="base"
|
|
4
4
|
role="radiogroup"
|
|
@@ -2,4 +2,4 @@
|
|
|
2
2
|
* Generated from package.json by scripts/generate-package-metadata.mjs.
|
|
3
3
|
* Run `pnpm package-metadata` after changing package identity or version.
|
|
4
4
|
*/
|
|
5
|
-
export declare const LYRA_PACKAGE_NAME:'@aceshooting/lyra-ui';export declare const LYRA_PACKAGE_VERSION:'24.
|
|
5
|
+
export declare const LYRA_PACKAGE_NAME:'@aceshooting/lyra-ui';export declare const LYRA_PACKAGE_VERSION:'24.1.0';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const LYRA_PACKAGE_NAME="@aceshooting/lyra-ui",LYRA_PACKAGE_VERSION="24.
|
|
1
|
+
const LYRA_PACKAGE_NAME="@aceshooting/lyra-ui",LYRA_PACKAGE_VERSION="24.1.0";export{LYRA_PACKAGE_NAME,LYRA_PACKAGE_VERSION};
|
|
@@ -103,12 +103,34 @@ RetrievalChunk[] }`) — forwarded from the built-in retrieval results.
|
|
|
103
103
|
- `lr-tool-approval-decide-request` (`detail: ToolTimelineApprovalDetail` = `ToolApprovalEventDetail &
|
|
104
104
|
{ args?: unknown }` = `{ invocationId: string; approved: boolean; args?: unknown }`) — forwarded
|
|
105
105
|
from the built-in tool timeline; `args` is present only on approval and may differ from what the
|
|
106
|
-
entry originally proposed (the dialog's inline edit step).
|
|
106
|
+
entry originally proposed (the dialog's inline edit step). Call `preventDefault()` synchronously
|
|
107
|
+
to hold the built-in dialog while persisting the decision.
|
|
107
108
|
- `lr-cancel` (`detail: CancelEventDetail = { reason?: string }`) / `lr-run-retry` (`detail: RetryEventDetail` =
|
|
108
109
|
`{ attempt: number; messageId?: string }`, from `@aceshooting/lyra-ui/ai`) — forwarded from the
|
|
109
110
|
built-in agent run. The distinct retry name prevents a rendered message or attachment retry from
|
|
110
111
|
being mistaken for a whole-run retry.
|
|
111
112
|
|
|
113
|
+
**Methods:** `finalizePendingApproval(): void` closes a vetoed approval in the built-in tool timeline
|
|
114
|
+
after persistence succeeds; `revertPendingApproval(): void` releases its pending state after a failed
|
|
115
|
+
save while retaining the open dialog and edited arguments for retry. Both forward to the built-in
|
|
116
|
+
timeline only and are no-ops when no timeline or pending decision exists, including when `details`
|
|
117
|
+
is replaced by a custom slot or `withoutDetails` is set. The host still owns `tools` updates.
|
|
118
|
+
These methods settle whichever approval is currently pending; an async host must discard stale
|
|
119
|
+
completions when it replaces the run or tools before persistence returns.
|
|
120
|
+
|
|
121
|
+
```ts
|
|
122
|
+
workspace.addEventListener('lr-tool-approval-decide-request', async (event) => {
|
|
123
|
+
event.preventDefault();
|
|
124
|
+
try {
|
|
125
|
+
await persistDecision(event.detail);
|
|
126
|
+
workspace.tools = applyDecision(workspace.tools, event.detail);
|
|
127
|
+
workspace.finalizePendingApproval();
|
|
128
|
+
} catch {
|
|
129
|
+
workspace.revertPendingApproval();
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
```
|
|
133
|
+
|
|
112
134
|
**Slots:** `messages` (replaces the data-driven transcript message list; assign ordinary messages
|
|
113
135
|
directly, or exactly one `lr-virtual-list` when the slot itself owns virtualization), `details` (replaces the
|
|
114
136
|
built-in run/tool/retrieval/grounding/context details pane while keeping the responsive shell),
|
|
@@ -43,6 +43,9 @@ gemstone?: GemstoneKey }`; a valid CSS `color` is used as the
|
|
|
43
43
|
remains the sole action. `gemstone` selects the canonical faceted glyph when
|
|
44
44
|
`mode="gemstone"`. An explicit `icon` wins over `gemstone`. Assignments are bounded and copied
|
|
45
45
|
into a frozen owned snapshot; mutate a new array/item and reassign it to update the palette.
|
|
46
|
+
Fresh items with unchanged fields retain their radio nodes and keyboard focus without a blur.
|
|
47
|
+
Custom icons match by identity. Duplicate values remain distinct occurrences; surviving original
|
|
48
|
+
item identities take precedence when a palette mixes original and equivalent fresh items.
|
|
46
49
|
- `value: string | null = null` — the currently selected option's `value` (controlled); `null`
|
|
47
50
|
leaves nothing selected while keeping the first swatch tabbable.
|
|
48
51
|
- `size: '2xs' | 'xs' | 's' | 'm' | 'l' | 'xl' = 'm'` (reflected — scales the swatch hit-area and
|
|
@@ -305,8 +308,6 @@ locale's own separator), and `translateGemstone()` come from the application's c
|
|
|
305
308
|
`onAccentChange()` validates the string and updates application state:
|
|
306
309
|
|
|
307
310
|
```ts
|
|
308
|
-
// Build once per locale. A new array on every render re-creates every swatch and briefly blurs
|
|
309
|
-
// the focused one.
|
|
310
311
|
const items = GEMSTONE_KEYS.map((key) => ({
|
|
311
312
|
value: key,
|
|
312
313
|
color: GEMSTONES[key].fill,
|
|
@@ -24,7 +24,7 @@ Every one of those names is also typed — per component through its own event m
|
|
|
24
24
|
through `@aceshooting/lyra-ui/events` for listeners on an ancestor, `document` or `window`. See
|
|
25
25
|
"TypeScript" below.
|
|
26
26
|
|
|
27
|
-
For
|
|
27
|
+
For event-detail compatibility fields removed in the v23-to-v24 upgrade,
|
|
28
28
|
use step 7 of the [migration checklist](v23-to-v24-migration.md#migrate-a-project-in-reviewable-steps).
|
|
29
29
|
Those nested detail fields are separate from deprecated event names and are not automatic renames.
|
|
30
30
|
|
|
@@ -36,7 +36,7 @@ Those nested detail fields are separate from deprecated event names and are not
|
|
|
36
36
|
```ts
|
|
37
37
|
import { LyraTable } from "@aceshooting/lyra-ui/components/data/table/table.class.js";
|
|
38
38
|
const table = document.querySelector("lr-table") as LyraTable;
|
|
39
|
-
table.addEventListener("lr-sort", (event) => event.detail.
|
|
39
|
+
table.addEventListener("lr-sort", (event) => event.detail.sortKey); // typed
|
|
40
40
|
```
|
|
41
41
|
- **`HTMLElementTagNameMap`** is augmented in the `.class.d.ts` files. `document.querySelector('lr-table')`
|
|
42
42
|
is only typed as `LyraTable` when that class module is in the type graph — importing just the
|
|
@@ -75,13 +75,13 @@ Those nested detail fields are separate from deprecated event names and are not
|
|
|
75
75
|
`LyraGlobalEventMap` is exported as well, for writing your own typed helper over it.
|
|
76
76
|
|
|
77
77
|
- **The surface is per-event type aliases, not runtime event classes.** `LyraSortEvent` and its
|
|
78
|
-
generated siblings are `type` aliases over
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
listener would cost every consumer runtime bytes for
|
|
82
|
-
costs zero.
|
|
78
|
+
generated siblings are `type` aliases over component event-map entries. `LyraSortEvent` unions
|
|
79
|
+
the `lr-sort` entries for document-library, eval-dataset and table. These aliases have no runtime
|
|
80
|
+
constructor and cannot be used with `new` or `instanceof`. The module compiles to `export {};`:
|
|
81
|
+
shipping runtime event subclasses to type a listener would cost every consumer runtime bytes for
|
|
82
|
+
a compile-time concern, so it deliberately costs zero.
|
|
83
83
|
- **A shared event name narrows to the union of its dispatchers.** One name can come from several
|
|
84
|
-
components with different details
|
|
84
|
+
components with different details, such as `lr-select` and `lr-selection-change`, so
|
|
85
85
|
its global entry is the _union_ of their entries, and `event.detail` there exposes only what all
|
|
86
86
|
of them share. Index the owning component's own map when you need one component's exact detail:
|
|
87
87
|
|
package/llms/shared.md
CHANGED
|
@@ -394,7 +394,7 @@ Every one of those names is also typed — per component through its own event m
|
|
|
394
394
|
through `@aceshooting/lyra-ui/events` for listeners on an ancestor, `document` or `window`. See
|
|
395
395
|
"TypeScript" below.
|
|
396
396
|
|
|
397
|
-
For
|
|
397
|
+
For event-detail compatibility fields removed in the v23-to-v24 upgrade,
|
|
398
398
|
use step 7 of the [migration checklist](v23-to-v24-migration.md#migrate-a-project-in-reviewable-steps).
|
|
399
399
|
Those nested detail fields are separate from deprecated event names and are not automatic renames.
|
|
400
400
|
|
|
@@ -406,7 +406,7 @@ Those nested detail fields are separate from deprecated event names and are not
|
|
|
406
406
|
```ts
|
|
407
407
|
import { LyraTable } from "@aceshooting/lyra-ui/components/data/table/table.class.js";
|
|
408
408
|
const table = document.querySelector("lr-table") as LyraTable;
|
|
409
|
-
table.addEventListener("lr-sort", (event) => event.detail.
|
|
409
|
+
table.addEventListener("lr-sort", (event) => event.detail.sortKey); // typed
|
|
410
410
|
```
|
|
411
411
|
- **`HTMLElementTagNameMap`** is augmented in the `.class.d.ts` files. `document.querySelector('lr-table')`
|
|
412
412
|
is only typed as `LyraTable` when that class module is in the type graph — importing just the
|
|
@@ -445,13 +445,13 @@ Those nested detail fields are separate from deprecated event names and are not
|
|
|
445
445
|
`LyraGlobalEventMap` is exported as well, for writing your own typed helper over it.
|
|
446
446
|
|
|
447
447
|
- **The surface is per-event type aliases, not runtime event classes.** `LyraSortEvent` and its
|
|
448
|
-
generated siblings are `type` aliases over
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
listener would cost every consumer runtime bytes for
|
|
452
|
-
costs zero.
|
|
448
|
+
generated siblings are `type` aliases over component event-map entries. `LyraSortEvent` unions
|
|
449
|
+
the `lr-sort` entries for document-library, eval-dataset and table. These aliases have no runtime
|
|
450
|
+
constructor and cannot be used with `new` or `instanceof`. The module compiles to `export {};`:
|
|
451
|
+
shipping runtime event subclasses to type a listener would cost every consumer runtime bytes for
|
|
452
|
+
a compile-time concern, so it deliberately costs zero.
|
|
453
453
|
- **A shared event name narrows to the union of its dispatchers.** One name can come from several
|
|
454
|
-
components with different details
|
|
454
|
+
components with different details, such as `lr-select` and `lr-selection-change`, so
|
|
455
455
|
its global entry is the _union_ of their entries, and `event.detail` there exposes only what all
|
|
456
456
|
of them share. Index the owning component's own map when you need one component's exact detail:
|
|
457
457
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aceshooting/lyra-ui",
|
|
3
|
-
"version": "24.
|
|
3
|
+
"version": "24.1.0",
|
|
4
4
|
"description": "Free, independent Lit web components: an open-source alternative to Shoelace and Web Awesome with accessible forms, dashboards, charts, and agent UI.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"web-components",
|