@aceshooting/lyra-ui 28.0.0 → 28.1.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 (85) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/dist/components/agent-tools/commit-card/commit-card.class.d.ts +2 -2
  3. package/dist/components/agent-tools/commit-card/commit-card.class.js +7 -8
  4. package/dist/components/agent-tools/eval-dataset/eval-dataset.class.js +1 -1
  5. package/dist/components/agent-tools/schema-viewer/schema-viewer.class.js +1 -1
  6. package/dist/components/agent-tools/tool-param-form/tool-param-form.class.js +4 -4
  7. package/dist/components/charts/chart/box-plot.class.d.ts +5 -3
  8. package/dist/components/charts/chart/box-plot.class.js +18 -17
  9. package/dist/components/charts/chart/chart.class.d.ts +6 -4
  10. package/dist/components/charts/chart/chart.class.js +19 -18
  11. package/dist/components/charts/chart/lite-chart.class.d.ts +1 -1
  12. package/dist/components/charts/chart/lite-chart.class.js +8 -8
  13. package/dist/components/conversation/message-feedback/message-feedback.class.js +2 -2
  14. package/dist/components/conversation/selection-toolbar/selection-toolbar.class.js +1 -1
  15. package/dist/components/data/data-grid/data-grid-processing.js +1 -1
  16. package/dist/components/data/gauge/gauge.class.js +1 -1
  17. package/dist/components/data/graph-query-builder/graph-query-builder.class.d.ts +1 -1
  18. package/dist/components/data/graph-query-builder/graph-query-builder.class.js +2 -2
  19. package/dist/components/data/heatmap/heatmap-label-cache.js +1 -0
  20. package/dist/components/data/heatmap/heatmap.class.d.ts +3 -2
  21. package/dist/components/data/heatmap/heatmap.class.js +2 -2
  22. package/dist/components/data/heatmap/heatmap.styles.js +1 -1
  23. package/dist/components/data/stat/stat.class.d.ts +11 -9
  24. package/dist/components/data/stat/stat.class.js +4 -2
  25. package/dist/components/data/tree/tree.class.js +1 -1
  26. package/dist/components/forms/checkbox-group/checkbox-group.class.js +1 -1
  27. package/dist/components/forms/color-picker/color-picker.class.js +3 -3
  28. package/dist/components/forms/combobox/combobox.class.d.ts +2 -4
  29. package/dist/components/forms/combobox/combobox.class.js +1 -1
  30. package/dist/components/forms/emoji-picker/emoji-picker.class.js +5 -5
  31. package/dist/components/forms/locale-picker/locale-picker.class.js +1 -1
  32. package/dist/components/forms/select/select.class.js +4 -3
  33. package/dist/components/forms/toggle-group/toggle-group.class.js +1 -1
  34. package/dist/components/layout/command-palette/command-palette.styles.js +1 -1
  35. package/dist/components/layout/filter-bar/filter-bar.class.js +3 -3
  36. package/dist/components/layout/menu/menu.class.js +1 -1
  37. package/dist/components/layout/menubar/menubar.class.js +1 -1
  38. package/dist/components/layout/navigation-menu-item/navigation-menu-item.class.d.ts +1 -1
  39. package/dist/components/layout/navigation-menu-item/navigation-menu-item.class.js +1 -1
  40. package/dist/components/layout/page/page.class.js +1 -1
  41. package/dist/components/layout/tab-group/tab-group.class.js +1 -1
  42. package/dist/components/media/attachment-trigger/attachment-trigger.class.js +1 -1
  43. package/dist/components/media/file-input/file-input.class.js +1 -1
  44. package/dist/components/media/video-playlist/video-playlist.class.js +1 -1
  45. package/dist/components/retrieval/chunk-inspector/chunk-inspector.class.d.ts +1 -1
  46. package/dist/components/retrieval/chunk-inspector/chunk-inspector.class.js +2 -2
  47. package/dist/components/retrieval/citation-badge/citation-badge.class.js +1 -1
  48. package/dist/components/retrieval/entity-chip/entity-chip.class.js +1 -1
  49. package/dist/components/retrieval/graph/graph-canvas.js +1 -1
  50. package/dist/components/retrieval/graph-legend/graph-legend.class.js +2 -2
  51. package/dist/components/retrieval/knowledge-graph-explorer/knowledge-graph-explorer.class.js +1 -1
  52. package/dist/components/retrieval/neighbor-list/neighbor-list.class.js +1 -1
  53. package/dist/components/retrieval/retrieval-results/retrieval-results.class.d.ts +1 -1
  54. package/dist/components/retrieval/retrieval-results/retrieval-results.class.js +4 -4
  55. package/dist/components/retrieval/source-picker/source-picker.class.d.ts +1 -1
  56. package/dist/components/retrieval/source-picker/source-picker.class.js +1 -1
  57. package/dist/components/viewers/email-viewer/email-viewer.class.js +1 -1
  58. package/dist/components/viewers/pdf-viewer/pdf-viewer.class.js +1 -1
  59. package/dist/framework-types.d.ts +1 -1
  60. package/dist/internal/default-strings/charts.generated.js +1 -1
  61. package/dist/internal/localization-types.d.ts +1 -1
  62. package/dist/internal/localization.js +1 -1
  63. package/dist/internal/native-modal-carrier.js +2 -2
  64. package/dist/internal/nonmodal-overlay-manager.js +1 -1
  65. package/dist/internal/open-overlay-ancestors.js +1 -0
  66. package/dist/internal/open-overlay-raise.styles.js +1 -1
  67. package/dist/internal/overlay-manager.d.ts +2 -0
  68. package/dist/internal/overlay-manager.js +1 -1
  69. package/dist/internal/package-metadata.js +1 -1
  70. package/dist/testing/happy-dom-shims.d.ts +3 -1
  71. package/dist/testing/happy-dom-shims.js +1 -1
  72. package/llms/components/lr-box-plot.md +5 -0
  73. package/llms/components/lr-chart.md +6 -0
  74. package/llms/components/lr-color-picker.md +2 -0
  75. package/llms/components/lr-commit-card.md +3 -2
  76. package/llms/components/lr-heatmap.md +10 -2
  77. package/llms/components/lr-select.md +2 -0
  78. package/llms/components/lr-stat.md +4 -0
  79. package/llms/peers.md +1 -1
  80. package/llms/shared/ai-and-peers.md +44 -0
  81. package/llms/shared/testing-and-utilities.md +14 -1
  82. package/llms/shared.md +58 -1
  83. package/locales.json +138 -138
  84. package/package.json +7 -6
  85. package/registrations.json +1 -1
@@ -1 +1 @@
1
- import{getActiveNativeModal,isPageHelperRegion}from"./native-modal-context.js";import{activateNonmodalOverlay}from"./nonmodal-overlay-manager.js";import{RenderedStateController}from"./rendered-state.js";import{lockScroll}from"./scroll-lock.js";import{acquireOverlayRoutingSuspension,activateOverlayStack,observeOverlayStack}from"./overlay-stack.js";const EMPTY_STACK={entries:[]},modalStates=new WeakMap;function modalStateFor(doc){const existing=modalStates.get(doc);if(existing)return existing;const state={document:doc,snapshot:EMPTY_STACK,registrations:0,externalModalSuspensions:new Set,inerted:new Map,pendingInertWrites:new Map,observedRoots:new Set,allowedParents:new Set,inertUpdateQueued:!1,started:!1};return modalStates.set(doc,state),state}function scheduleInertUpdate(state){state.inertUpdateQueued||(state.inertUpdateQueued=!0,queueMicrotask(()=>{state.inertUpdateQueued=!1,applyTopmostInert(state)}))}function pruneExternalModalSuspensions(state){let changed=!1;for(const entry of state.externalModalSuspensions)entry.root.isConnected&&entry.root.ownerDocument===state.document||(entry.active=!1,state.externalModalSuspensions.delete(entry),entry.releaseRouting(),changed=!0);return changed}function movesStackHost(state,record){for(const entry of state.snapshot.entries)for(const list of[record.addedNodes,record.removedNodes])for(const node of list)if(node.contains(entry.host))return!0;return!1}function handleMutations(state,records){const prunedExternalModal=pruneExternalModalSuspensions(state);let needsInertUpdate=prunedExternalModal;for(let index=0;index<records.length;index++){const record=records[index];if(!record)continue;if(record.type==="childList"){(state.allowedParents.has(record.target)||movesStackHost(state,record))&&(needsInertUpdate=!0);continue}if(record.attributeName==="open"){needsInertUpdate=!0;continue}const element=record.target;let nextRecord;for(let nextIndex=index+1;nextIndex<records.length;nextIndex++){const candidate=records[nextIndex];if(candidate?.type==="attributes"&&candidate.attributeName==="inert"&&candidate.target===element){nextRecord=candidate;break}}const newValue=nextRecord?nextRecord.oldValue!==null:element.hasAttribute("inert"),pending=state.pendingInertWrites.get(element);if(pending?.[0]===newValue){pending.shift(),pending.length===0&&state.pendingInertWrites.delete(element);continue}state.inerted.has(element)&&(state.inerted.set(element,newValue),needsInertUpdate=!0)}needsInertUpdate&&(prunedExternalModal?applyTopmostInert(state):scheduleInertUpdate(state)),stopModalStateIfIdle(state)}const mutationObserverOptions={attributeFilter:["inert","open"],attributeOldValue:!0,attributes:!0,childList:!0,subtree:!0};function observeMutationRoot(state,root){!state.observer||state.observedRoots.has(root)||(state.observer.observe(root===state.document?state.document.documentElement:root,mutationObserverOptions),state.observedRoots.add(root))}function startModalState(state){if(state.started)return;state.started=!0;const Observer=state.document.defaultView?.MutationObserver??MutationObserver;state.observer=new Observer(records=>handleMutations(state,records)),observeMutationRoot(state,state.document),state.unsubscribeStack=observeOverlayStack(state.document,snapshot=>{state.snapshot=snapshot,applyTopmostInert(state)})}function stopModalState(state){if(state.started){state.started=!1,state.unsubscribeStack?.(),state.unsubscribeStack=void 0;for(const[element,intended]of state.inerted)element.inert=intended;state.inerted.clear(),state.observer?.disconnect(),state.observer=void 0,state.observedRoots.clear(),state.pendingInertWrites.clear(),state.snapshot=EMPTY_STACK}}function stopModalStateIfIdle(state){state.registrations===0&&state.externalModalSuspensions.size===0&&stopModalState(state)}function retainModalState(doc){const state=modalStateFor(doc);state.registrations++,startModalState(state);let active=!0;return()=>{active&&(active=!1,state.registrations--,stopModalStateIfIdle(state))}}function setInertByManager(state,element,value){if(element.inert!==value){if(state.observer&&state.observedRoots.has(element.getRootNode())){let pending=state.pendingInertWrites.get(element);pending||(pending=[],state.pendingInertWrites.set(element,pending)),pending.push(value)}else state.pendingInertWrites.delete(element);element.inert=value}}function inertElement(state,element,desired){if(!("inert"in element)||element.localName==="dialog"&&element.matches(":modal")||isPageHelperRegion(element))return;const htmlElement=element;desired.add(htmlElement),state.inerted.has(htmlElement)||state.inerted.set(htmlElement,htmlElement.inert),setInertByManager(state,htmlElement,!0)}function pathParent(element){return element.assignedSlot??element.parentNode}function parentPathElement(parent){return parent.nodeType===Node.ELEMENT_NODE?parent:parent.host??null}function composedChildren(parent){return parent.localName==="slot"?parent.assignedElements({flatten:!0}):"children"in parent?Array.from(parent.children):[]}function isShadowRoot(node){return node.nodeType===11&&"host"in node}function addAllowedPath(allowed,host,doc){let current=host;for(;current&&current!==doc.body&&current!==doc.documentElement;){const parent=pathParent(current);if(!parent)break;let children=allowed.get(parent);children||(children=new Set,allowed.set(parent,children)),children.add(current),current=parentPathElement(parent)}}function modalAllowedRoot(entry,doc){const explicit=entry.modalRoot?.()??null;return explicit?.isConnected&&explicit.ownerDocument===doc?explicit:entry.host}function applyTopmostInert(state){let modalIndex=-1;for(let index=state.snapshot.entries.length-1;index>=0;index--)if(state.snapshot.entries[index]?.modal){modalIndex=index;break}const desired=new Set;if(state.allowedParents=new Set,state.externalModalSuspensions.size>0){const allowed=new Map;for(const suspension of state.externalModalSuspensions)addAllowedPath(allowed,suspension.root,state.document);inertOutsideAllowedPaths(state,allowed,desired)}else if(modalIndex!==-1){const allowed=new Map;for(const entry of state.snapshot.entries.slice(modalIndex))if(entry.host.isConnected){addAllowedPath(allowed,modalAllowedRoot(entry,state.document),state.document);for(const root of entry.auxiliaryRoots?.()??[])root.isConnected&&root.ownerDocument===state.document&&addAllowedPath(allowed,root,state.document)}const nativeModal=getActiveNativeModal(state.document);nativeModal&&addAllowedPath(allowed,nativeModal,state.document),inertOutsideAllowedPaths(state,allowed,desired)}for(const[element,intended]of state.inerted)desired.has(element)||(setInertByManager(state,element,intended),state.inerted.delete(element))}function inertOutsideAllowedPaths(state,allowed,desired){for(const[parent,children]of allowed){state.allowedParents.add(parent),isShadowRoot(parent)&&observeMutationRoot(state,parent);for(const child of composedChildren(parent))children.has(child)||inertElement(state,child,desired)}}function activateOverlay(options){if(options.modal===!1&&options.trapFocus===!1&&!options.suspendWhenUnrendered&&!options.lockScroll)return activateNonmodalOverlay(options);const modal=options.modal!==!1;let releaseModalState,releaseScrollLock,renderedState;const coreHandle=activateOverlayStack({...options,initiallySuspended:options.suspendWhenUnrendered===!0,modal,trapFocus:options.trapFocus!==!1,onRegistered:doc=>{modal&&(releaseModalState=retainModalState(doc)),options.lockScroll&&(releaseScrollLock=lockScroll(doc))},onUnregistered:(_doc,deferResourceRelease)=>{const releaseModal=releaseModalState;releaseModalState=void 0;const release=releaseScrollLock;releaseScrollLock=void 0;const deferredRelease=release&&deferResourceRelease?release:void 0;return release&&!deferResourceRelease&&release(),releaseModal?.(),deferredRelease},onDeactivate:()=>renderedState?.stop()});return coreHandle.isActive()?(options.suspendWhenUnrendered&&(renderedState=new RenderedStateController(options.host,options.panel,rendered=>{if(!coreHandle.isActive())return;if(!rendered){coreHandle.suspend();return}const wasTopmost=coreHandle.isTopmost();coreHandle.resume(),!wasTopmost&&coreHandle.isTopmost()&&queueMicrotask(()=>coreHandle.focusInitial())}),renderedState.start()),{focusInitial:()=>{renderedState?.check(),coreHandle.focusInitial()},focusAutofocus:()=>(renderedState?.check(),coreHandle.focusAutofocus()),updateRestoreFocusTo:target=>coreHandle.updateRestoreFocusTo(target),deactivate:deactivateOptions=>coreHandle.deactivate(deactivateOptions),suspend:()=>coreHandle.suspend(),resume:()=>{renderedState&&!renderedState.check()||coreHandle.resume()},isTopmost:()=>(renderedState?.check(),coreHandle.isTopmost()),isActive:()=>coreHandle.isActive(),dismissBackdrop:()=>(renderedState?.check(),coreHandle.dismissBackdrop())}):coreHandle}function suspendLyraModalsFor(externalModal){if(!externalModal.isConnected)return()=>{};const state=modalStateFor(externalModal.ownerDocument);startModalState(state);const entry={root:externalModal,active:!0,releaseRouting:()=>{},state};return state.externalModalSuspensions.add(entry),entry.releaseRouting=acquireOverlayRoutingSuspension(state.document),applyTopmostInert(state),()=>{entry.active&&(entry.active=!1,entry.state.externalModalSuspensions.delete(entry),entry.releaseRouting(),applyTopmostInert(entry.state),stopModalStateIfIdle(entry.state))}}import{collectAutofocusElements,collectFocusableElements,composedContains,deepActiveElement}from"./overlay-stack.js";export{activateOverlay,collectAutofocusElements,collectFocusableElements,composedContains,deepActiveElement,suspendLyraModalsFor};
1
+ import{getActiveNativeModal,isPageHelperRegion}from"./native-modal-context.js";import{activateNonmodalOverlay}from"./nonmodal-overlay-manager.js";import{RenderedStateController}from"./rendered-state.js";import{lockScroll}from"./scroll-lock.js";import{acquireOverlayRoutingSuspension,activateOverlayStack,observeOverlayStack}from"./overlay-stack.js";const EMPTY_STACK={entries:[]},modalStates=new WeakMap;function authoredOverlayInert(host){const state=modalStates.get(host.ownerDocument);if(!state)return host.inert;const records=state.observer?.takeRecords();return records?.length&&handleMutations(state,records),state.inerted.get(host)??host.inert}function modalStateFor(doc){const existing=modalStates.get(doc);if(existing)return existing;const state={document:doc,snapshot:EMPTY_STACK,registrations:0,externalModalSuspensions:new Set,inerted:new Map,pendingInertWrites:new Map,observedRoots:new Set,allowedParents:new Set,inertUpdateQueued:!1,started:!1};return modalStates.set(doc,state),state}function scheduleInertUpdate(state){state.inertUpdateQueued||(state.inertUpdateQueued=!0,queueMicrotask(()=>{state.inertUpdateQueued=!1,applyTopmostInert(state)}))}function pruneExternalModalSuspensions(state){let changed=!1;for(const entry of state.externalModalSuspensions)entry.root.isConnected&&entry.root.ownerDocument===state.document||(entry.active=!1,state.externalModalSuspensions.delete(entry),entry.releaseRouting(),changed=!0);return changed}function movesStackHost(state,record){for(const entry of state.snapshot.entries)for(const list of[record.addedNodes,record.removedNodes])for(const node of list)if(node.contains(entry.host))return!0;return!1}function handleMutations(state,records){const prunedExternalModal=pruneExternalModalSuspensions(state);let needsInertUpdate=prunedExternalModal;for(let index=0;index<records.length;index++){const record=records[index];if(!record)continue;if(record.type==="childList"){(state.allowedParents.has(record.target)||movesStackHost(state,record))&&(needsInertUpdate=!0);continue}if(record.attributeName==="open"){needsInertUpdate=!0;continue}const element=record.target;let nextRecord;for(let nextIndex=index+1;nextIndex<records.length;nextIndex++){const candidate=records[nextIndex];if(candidate?.type==="attributes"&&candidate.attributeName==="inert"&&candidate.target===element){nextRecord=candidate;break}}const newValue=nextRecord?nextRecord.oldValue!==null:element.hasAttribute("inert"),pending=state.pendingInertWrites.get(element);if(pending?.[0]===newValue){pending.shift(),pending.length===0&&state.pendingInertWrites.delete(element);continue}state.inerted.has(element)&&(state.inerted.set(element,newValue),needsInertUpdate=!0)}needsInertUpdate&&(prunedExternalModal?applyTopmostInert(state):scheduleInertUpdate(state)),stopModalStateIfIdle(state)}const mutationObserverOptions={attributeFilter:["inert","open"],attributeOldValue:!0,attributes:!0,childList:!0,subtree:!0};function observeMutationRoot(state,root){!state.observer||state.observedRoots.has(root)||(state.observer.observe(root===state.document?state.document.documentElement:root,mutationObserverOptions),state.observedRoots.add(root))}function startModalState(state){if(state.started)return;state.started=!0;const Observer=state.document.defaultView?.MutationObserver??MutationObserver;state.observer=new Observer(records=>handleMutations(state,records)),observeMutationRoot(state,state.document),state.unsubscribeStack=observeOverlayStack(state.document,snapshot=>{state.snapshot=snapshot,applyTopmostInert(state)})}function stopModalState(state){if(state.started){state.started=!1,state.unsubscribeStack?.(),state.unsubscribeStack=void 0;for(const[element,intended]of state.inerted)element.inert=intended;state.inerted.clear(),state.observer?.disconnect(),state.observer=void 0,state.observedRoots.clear(),state.pendingInertWrites.clear(),state.snapshot=EMPTY_STACK}}function stopModalStateIfIdle(state){state.registrations===0&&state.externalModalSuspensions.size===0&&stopModalState(state)}function retainModalState(doc){const state=modalStateFor(doc);state.registrations++,startModalState(state);let active=!0;return()=>{active&&(active=!1,state.registrations--,stopModalStateIfIdle(state))}}function setInertByManager(state,element,value){if(element.inert!==value){if(state.observer&&state.observedRoots.has(element.getRootNode())){let pending=state.pendingInertWrites.get(element);pending||(pending=[],state.pendingInertWrites.set(element,pending)),pending.push(value)}else state.pendingInertWrites.delete(element);element.inert=value}}function inertElement(state,element,desired){if(!("inert"in element)||element.localName==="dialog"&&element.matches(":modal")||isPageHelperRegion(element))return;const htmlElement=element;desired.add(htmlElement),state.inerted.has(htmlElement)||state.inerted.set(htmlElement,htmlElement.inert),setInertByManager(state,htmlElement,!0)}function pathParent(element){return element.assignedSlot??element.parentNode}function parentPathElement(parent){return parent.nodeType===Node.ELEMENT_NODE?parent:parent.host??null}function composedChildren(parent){return parent.localName==="slot"?parent.assignedElements({flatten:!0}):"children"in parent?Array.from(parent.children):[]}function isShadowRoot(node){return node.nodeType===11&&"host"in node}function addAllowedPath(allowed,host,doc){let current=host;for(;current&&current!==doc.body&&current!==doc.documentElement;){const parent=pathParent(current);if(!parent)break;let children=allowed.get(parent);children||(children=new Set,allowed.set(parent,children)),children.add(current),current=parentPathElement(parent)}}function modalAllowedRoot(entry,doc){const explicit=entry.modalRoot?.()??null;return explicit?.isConnected&&explicit.ownerDocument===doc?explicit:entry.host}function applyTopmostInert(state){let modalIndex=-1;for(let index=state.snapshot.entries.length-1;index>=0;index--)if(state.snapshot.entries[index]?.modal){modalIndex=index;break}const desired=new Set;if(state.allowedParents=new Set,state.externalModalSuspensions.size>0){const allowed=new Map;for(const suspension of state.externalModalSuspensions)addAllowedPath(allowed,suspension.root,state.document);inertOutsideAllowedPaths(state,allowed,desired)}else if(modalIndex!==-1){const allowed=new Map;for(const entry of state.snapshot.entries.slice(modalIndex))if(entry.host.isConnected){addAllowedPath(allowed,modalAllowedRoot(entry,state.document),state.document);for(const root of entry.auxiliaryRoots?.()??[])root.isConnected&&root.ownerDocument===state.document&&addAllowedPath(allowed,root,state.document)}const nativeModal=getActiveNativeModal(state.document);nativeModal&&addAllowedPath(allowed,nativeModal,state.document),inertOutsideAllowedPaths(state,allowed,desired)}for(const[element,intended]of state.inerted)desired.has(element)||(setInertByManager(state,element,intended),state.inerted.delete(element))}function inertOutsideAllowedPaths(state,allowed,desired){for(const[parent,children]of allowed){state.allowedParents.add(parent),isShadowRoot(parent)&&observeMutationRoot(state,parent);for(const child of composedChildren(parent))children.has(child)||inertElement(state,child,desired)}}function activateOverlay(options){if(options.modal===!1&&options.trapFocus===!1&&!options.suspendWhenUnrendered&&!options.lockScroll)return activateNonmodalOverlay(options);const modal=options.modal!==!1;let releaseModalState,releaseScrollLock,renderedState;const coreHandle=activateOverlayStack({...options,initiallySuspended:options.suspendWhenUnrendered===!0,modal,trapFocus:options.trapFocus!==!1,onRegistered:doc=>{modal&&(releaseModalState=retainModalState(doc)),options.lockScroll&&(releaseScrollLock=lockScroll(doc))},onUnregistered:(_doc,deferResourceRelease)=>{const releaseModal=releaseModalState;releaseModalState=void 0;const release=releaseScrollLock;releaseScrollLock=void 0;const deferredRelease=release&&deferResourceRelease?release:void 0;return release&&!deferResourceRelease&&release(),releaseModal?.(),deferredRelease},onDeactivate:()=>renderedState?.stop()});return coreHandle.isActive()?(options.suspendWhenUnrendered&&(renderedState=new RenderedStateController(options.host,options.panel,rendered=>{if(!coreHandle.isActive())return;if(!rendered){coreHandle.suspend();return}const wasTopmost=coreHandle.isTopmost();coreHandle.resume(),!wasTopmost&&coreHandle.isTopmost()&&queueMicrotask(()=>coreHandle.focusInitial())}),renderedState.start()),{focusInitial:()=>{renderedState?.check(),coreHandle.focusInitial()},focusAutofocus:()=>(renderedState?.check(),coreHandle.focusAutofocus()),updateRestoreFocusTo:target=>coreHandle.updateRestoreFocusTo(target),deactivate:deactivateOptions=>coreHandle.deactivate(deactivateOptions),suspend:()=>coreHandle.suspend(),resume:()=>{renderedState&&!renderedState.check()||coreHandle.resume()},isTopmost:()=>(renderedState?.check(),coreHandle.isTopmost()),isActive:()=>coreHandle.isActive(),dismissBackdrop:()=>(renderedState?.check(),coreHandle.dismissBackdrop())}):coreHandle}function suspendLyraModalsFor(externalModal){if(!externalModal.isConnected)return()=>{};const state=modalStateFor(externalModal.ownerDocument);startModalState(state);const entry={root:externalModal,active:!0,releaseRouting:()=>{},state};return state.externalModalSuspensions.add(entry),entry.releaseRouting=acquireOverlayRoutingSuspension(state.document),applyTopmostInert(state),()=>{entry.active&&(entry.active=!1,entry.state.externalModalSuspensions.delete(entry),entry.releaseRouting(),applyTopmostInert(entry.state),stopModalStateIfIdle(entry.state))}}import{collectAutofocusElements,collectFocusableElements,composedContains,deepActiveElement}from"./overlay-stack.js";export{activateOverlay,authoredOverlayInert,collectAutofocusElements,collectFocusableElements,composedContains,deepActiveElement,suspendLyraModalsFor};
@@ -1 +1 @@
1
- const LYRA_PACKAGE_NAME="@aceshooting/lyra-ui",LYRA_PACKAGE_VERSION="28.0.0";export{LYRA_PACKAGE_NAME,LYRA_PACKAGE_VERSION};
1
+ const LYRA_PACKAGE_NAME="@aceshooting/lyra-ui",LYRA_PACKAGE_VERSION="28.1.1";export{LYRA_PACKAGE_NAME,LYRA_PACKAGE_VERSION};
@@ -63,7 +63,9 @@ export declare function flattenCascadeLayers(css:string):string;interface SheetT
63
63
  * `CSSStyleSheet`; installs once and returns a function that restores the original methods.
64
64
  * `proto` and `misbehaves` default to the global `CSSStyleSheet.prototype` and the engine probe.
65
65
  */
66
- export declare function installHappyDomCascadeLayerShim(proto?:SheetTextMethods|undefined,misbehaves?:()=>boolean):()=>void;export declare function installHappyDomShims():void;
66
+ export declare function installHappyDomCascadeLayerShim(proto?:SheetTextMethods|undefined,misbehaves?:()=>boolean):()=>void;
67
+ /** Installs the feature-detected Happy DOM form, focus, ARIA, CSS layer, stylesheet and direction fixes. */
68
+ export declare function installHappyDomShims():void;
67
69
  /** Test-only: returns a fresh stub `ElementInternals`-shaped object, independent of whether
68
70
  * `attachInternals` already exists natively -- exists purely so this module's own test can
69
71
  * verify the stub's call-shape coverage without needing to run under happy-dom itself. */
@@ -1 +1 @@
1
- function createStubInternals(host){return{get form(){return host.closest("form")},labels:document.createDocumentFragment().querySelectorAll("label"),states:new Set,validity:{valid:!0},validationMessage:"",willValidate:!0,setFormValue(){},checkValidity(){return!0},reportValidity(){return!0},setValidity(){}}}function installHappyDomFormAssociatedShims(){typeof HTMLElement>"u"||typeof HTMLElement.prototype.attachInternals!="function"&&(HTMLElement.prototype.attachInternals=function(){return createStubInternals(this)})}function siblingActiveElementThrows(){const body=document.body;if(!body)return!1;const previous=document.activeElement,hosts=[document.createElement("div"),document.createElement("div")],roots=hosts.map(host=>host.attachShadow({mode:"open"})),button=document.createElement("button");roots[0]?.appendChild(button),hosts.forEach(host=>body.appendChild(host));try{return button.focus(),roots[1].activeElement,!1}catch{return!0}finally{button.blur(),hosts.forEach(host=>host.remove()),previous instanceof HTMLElement&&previous.focus()}}function detachedActiveElementThrows(){const root=document.createElement("div").attachShadow({mode:"open"});try{return root.activeElement,!1}catch{return!0}}function guardShadowActiveElement(proto,misbehaves){const descriptor=Object.getOwnPropertyDescriptor(proto,"activeElement"),native=descriptor?.get;if(!(!descriptor||!native||!misbehaves()))return Object.defineProperty(proto,"activeElement",{...descriptor,get(){try{return native.call(this)}catch(error){if(error instanceof TypeError)return null;throw error}}}),()=>Object.defineProperty(proto,"activeElement",descriptor)}function installHappyDomShadowFocusShim(){return typeof ShadowRoot>"u"||typeof document>"u"?()=>{}:guardShadowActiveElement(ShadowRoot.prototype,()=>siblingActiveElementThrows()||detachedActiveElementThrows())??(()=>{})}function isInScope(source,target){const targetRoot=target.getRootNode();let root=source.getRootNode();for(;root;){if(root===targetRoot)return!0;root="host"in root?root.host.getRootNode():null}return!1}function createAriaControlsElementsDescriptor(){const explicit=new WeakMap;return{configurable:!0,enumerable:!0,get(){const attr=this.getAttribute("aria-controls");if(attr===null)return null;const stored=explicit.get(this);if(stored&&stored.attr===attr)return stored.elements.filter(element=>isInScope(this,element));const root=this.getRootNode();return attr.split(/\s+/).filter(Boolean).map(id=>root.getElementById?.(id)??null).filter(element=>element!==null)},set(value){if(value==null){explicit.delete(this),this.removeAttribute("aria-controls");return}this.setAttribute("aria-controls",""),explicit.set(this,{elements:Array.from(value),attr:""})}}}function installHappyDomAriaControlsShim(proto=globalThis.Element?.prototype){!proto||"ariaControlsElements"in proto||Object.defineProperty(proto,"ariaControlsElements",createAriaControlsElementsDescriptor())}function skipOpaqueToken(css,index){const char=css[index];if(char==="/"&&css[index+1]==="*"){const end=css.indexOf("*/",index+2);return end===-1?css.length:end+2}if(char==='"'||char==="'"){let cursor=index+1;for(;cursor<css.length&&css[cursor]!==char;)cursor+=css[cursor]==="\\"?2:1;return Math.min(cursor+1,css.length)}if((char==="u"||char==="U")&&/^url\(/i.test(css.slice(index,index+4))&&!/[\w-]/.test(css[index-1]??"")){let cursor=index+4;for(;cursor<css.length&&/\s/.test(css[cursor]);)cursor++;if(css[cursor]==='"'||css[cursor]==="'")return index;const end=css.indexOf(")",cursor);return end===-1?css.length:end+1}return index}function matchingBrace(css,open){let depth=0;for(let index=open;index<css.length;index++){const skipped=skipOpaqueToken(css,index);if(skipped!==index){index=skipped-1;continue}if(css[index]==="{")depth++;else if(css[index]==="}"&&--depth===0)return index}return css.length}function flattenCascadeLayers(css){let output="",index=0;for(;index<css.length;){const skipped=skipOpaqueToken(css,index);if(skipped!==index){output+=css.slice(index,skipped),index=skipped;continue}if(css.startsWith("@layer",index)&&!/[\w-]/.test(css[index+6]??"")){let cursor=index+6;for(;cursor<css.length&&css[cursor]!==";"&&css[cursor]!=="{";)cursor++;if(css[cursor]==="{"){const close=matchingBrace(css,cursor);output+=flattenCascadeLayers(css.slice(cursor+1,close)),index=close+1}else index=cursor+1;continue}output+=css[index],index++}return output}function cascadeLayerRulesDropped(){try{const sheet=new CSSStyleSheet;return sheet.replaceSync("@layer lr-probe{:root{--lr-probe:1}}"),sheet.cssRules.length===0}catch{return!1}}const FLATTENING=Symbol.for("lyra-ui.testing.cascade-layer-shim");function installHappyDomCascadeLayerShim(proto=globalThis.CSSStyleSheet?.prototype,misbehaves=cascadeLayerRulesDropped){if(!proto||typeof proto.replaceSync!="function")return()=>{};const installed=proto;if(installed[FLATTENING]||!misbehaves())return()=>{};const{replaceSync,replace}=proto;return installed.replaceSync=function(text){replaceSync.call(this,typeof text=="string"?flattenCascadeLayers(text):text)},typeof replace=="function"&&(installed.replace=function(text){return replace.call(this,typeof text=="string"?flattenCascadeLayers(text):text)}),installed[FLATTENING]=!0,()=>{installed.replaceSync=replaceSync,typeof replace=="function"&&(installed.replace=replace),delete installed[FLATTENING]}}function installHappyDomShims(){installHappyDomFormAssociatedShims(),installHappyDomShadowFocusShim(),installHappyDomAriaControlsShim(),installHappyDomCascadeLayerShim()}function installStubInternalsForTest(host){return createStubInternals(host)}export{createAriaControlsElementsDescriptor,flattenCascadeLayers,guardShadowActiveElement,installHappyDomAriaControlsShim,installHappyDomCascadeLayerShim,installHappyDomFormAssociatedShims,installHappyDomShadowFocusShim,installHappyDomShims,installStubInternalsForTest};
1
+ function createStubInternals(host){return{get form(){return host.closest("form")},labels:document.createDocumentFragment().querySelectorAll("label"),states:new Set,validity:{valid:!0},validationMessage:"",willValidate:!0,setFormValue(){},checkValidity(){return!0},reportValidity(){return!0},setValidity(){}}}function installHappyDomFormAssociatedShims(){typeof HTMLElement>"u"||typeof HTMLElement.prototype.attachInternals!="function"&&(HTMLElement.prototype.attachInternals=function(){return createStubInternals(this)})}function siblingActiveElementThrows(){const body=document.body;if(!body)return!1;const previous=document.activeElement,hosts=[document.createElement("div"),document.createElement("div")],roots=hosts.map(host=>host.attachShadow({mode:"open"})),button=document.createElement("button");roots[0]?.appendChild(button),hosts.forEach(host=>body.appendChild(host));try{return button.focus(),roots[1].activeElement,!1}catch{return!0}finally{button.blur(),hosts.forEach(host=>host.remove()),previous instanceof HTMLElement&&previous.focus()}}function detachedActiveElementThrows(){const root=document.createElement("div").attachShadow({mode:"open"});try{return root.activeElement,!1}catch{return!0}}function guardShadowActiveElement(proto,misbehaves){const descriptor=Object.getOwnPropertyDescriptor(proto,"activeElement"),native=descriptor?.get;if(!(!descriptor||!native||!misbehaves()))return Object.defineProperty(proto,"activeElement",{...descriptor,get(){try{return native.call(this)}catch(error){if(error instanceof TypeError)return null;throw error}}}),()=>Object.defineProperty(proto,"activeElement",descriptor)}function installHappyDomShadowFocusShim(){return typeof ShadowRoot>"u"||typeof document>"u"?()=>{}:guardShadowActiveElement(ShadowRoot.prototype,()=>siblingActiveElementThrows()||detachedActiveElementThrows())??(()=>{})}function isInScope(source,target){const targetRoot=target.getRootNode();let root=source.getRootNode();for(;root;){if(root===targetRoot)return!0;root="host"in root?root.host.getRootNode():null}return!1}function createAriaControlsElementsDescriptor(){const explicit=new WeakMap;return{configurable:!0,enumerable:!0,get(){const attr=this.getAttribute("aria-controls");if(attr===null)return null;const stored=explicit.get(this);if(stored&&stored.attr===attr)return stored.elements.filter(element=>isInScope(this,element));const root=this.getRootNode();return attr.split(/\s+/).filter(Boolean).map(id=>root.getElementById?.(id)??null).filter(element=>element!==null)},set(value){if(value==null){explicit.delete(this),this.removeAttribute("aria-controls");return}this.setAttribute("aria-controls",""),explicit.set(this,{elements:Array.from(value),attr:""})}}}function installHappyDomAriaControlsShim(proto=globalThis.Element?.prototype){!proto||"ariaControlsElements"in proto||Object.defineProperty(proto,"ariaControlsElements",createAriaControlsElementsDescriptor())}function skipOpaqueToken(css,index){const char=css[index];if(char==="/"&&css[index+1]==="*"){const end=css.indexOf("*/",index+2);return end===-1?css.length:end+2}if(char==='"'||char==="'"){let cursor=index+1;for(;cursor<css.length&&css[cursor]!==char;)cursor+=css[cursor]==="\\"?2:1;return Math.min(cursor+1,css.length)}if((char==="u"||char==="U")&&/^url\(/i.test(css.slice(index,index+4))&&!/[\w-]/.test(css[index-1]??"")){let cursor=index+4;for(;cursor<css.length&&/\s/.test(css[cursor]);)cursor++;if(css[cursor]==='"'||css[cursor]==="'")return index;const end=css.indexOf(")",cursor);return end===-1?css.length:end+1}return index}function matchingBrace(css,open){let depth=0;for(let index=open;index<css.length;index++){const skipped=skipOpaqueToken(css,index);if(skipped!==index){index=skipped-1;continue}if(css[index]==="{")depth++;else if(css[index]==="}"&&--depth===0)return index}return css.length}function flattenCascadeLayers(css){let output="",index=0;for(;index<css.length;){const skipped=skipOpaqueToken(css,index);if(skipped!==index){output+=css.slice(index,skipped),index=skipped;continue}if(css.startsWith("@layer",index)&&!/[\w-]/.test(css[index+6]??"")){let cursor=index+6;for(;cursor<css.length&&css[cursor]!==";"&&css[cursor]!=="{";)cursor++;if(css[cursor]==="{"){const close=matchingBrace(css,cursor);output+=flattenCascadeLayers(css.slice(cursor+1,close)),index=close+1}else index=cursor+1;continue}output+=css[index],index++}return output}function cascadeLayerRulesDropped(){try{const sheet=new CSSStyleSheet;return sheet.replaceSync("@layer lr-probe{:root{--lr-probe:1}}"),sheet.cssRules.length===0}catch{return!1}}const FLATTENING=Symbol.for("lyra-ui.testing.cascade-layer-shim");function installHappyDomCascadeLayerShim(proto=globalThis.CSSStyleSheet?.prototype,misbehaves=cascadeLayerRulesDropped){if(!proto||typeof proto.replaceSync!="function")return()=>{};const installed=proto;if(installed[FLATTENING]||!misbehaves())return()=>{};const{replaceSync,replace}=proto;return installed.replaceSync=function(text){replaceSync.call(this,typeof text=="string"?flattenCascadeLayers(text):text)},typeof replace=="function"&&(installed.replace=function(text){return replace.call(this,typeof text=="string"?flattenCascadeLayers(text):text)}),installed[FLATTENING]=!0,()=>{installed.replaceSync=replaceSync,typeof replace=="function"&&(installed.replace=replace),delete installed[FLATTENING]}}function installHappyDomShadowStyleSheetsShim(){if(typeof ShadowRoot>"u"||"styleSheets"in ShadowRoot.prototype)return;const lists=new WeakMap;Object.defineProperty(ShadowRoot.prototype,"styleSheets",{configurable:!0,enumerable:!0,get(){let list=lists.get(this);if(list)return list;const root=this,read=()=>Array.from(root.querySelectorAll('style, link[rel~="stylesheet" i]'),element=>element.sheet).filter(sheet=>sheet!==null),collection={get length(){return read().length},item(index){return read()[index>>>0]??null},*[Symbol.iterator](){for(let index=0;index<this.length;index++)yield this.item(index)}};return list=new Proxy(collection,{get(target,key,receiver){return typeof key=="string"&&/^(0|[1-9]\d*)$/.test(key)?read()[Number(key)]:Reflect.get(target,key,receiver)}}),lists.set(root,list),list}})}const happyDomDirectionStyles=new WeakMap;function installHappyDomDirectionShim(){if(typeof document>"u"||typeof navigator>"u"||!/happy.?dom/i.test(navigator.userAgent)||!document.head||!document.body||happyDomDirectionStyles.get(document)?.isConnected)return;const probe=document.createElement("div");probe.dir="rtl",document.body.append(probe);let supported;try{supported=document.defaultView?.getComputedStyle(probe).direction==="rtl"}finally{probe.remove()}if(supported)return;const style=document.createElement("style"),selector=value=>{let cases=[""];for(const character of value)cases=cases.flatMap(prefix=>[prefix+character,prefix+character.toUpperCase()]);return`:where(${cases.map(variant=>`[dir="${variant}"]`).join(",")})`};style.textContent=`${selector("ltr")}{direction:ltr}${selector("rtl")}{direction:rtl}`,document.head.append(style),happyDomDirectionStyles.set(document,style)}function installHappyDomShims(){installHappyDomFormAssociatedShims(),installHappyDomShadowFocusShim(),installHappyDomAriaControlsShim(),installHappyDomCascadeLayerShim(),installHappyDomShadowStyleSheetsShim(),installHappyDomDirectionShim()}function installStubInternalsForTest(host){return createStubInternals(host)}export{createAriaControlsElementsDescriptor,flattenCascadeLayers,guardShadowActiveElement,installHappyDomAriaControlsShim,installHappyDomCascadeLayerShim,installHappyDomFormAssociatedShims,installHappyDomShadowFocusShim,installHappyDomShims,installStubInternalsForTest};
@@ -19,6 +19,11 @@
19
19
  Box-and-whisker chart from a precomputed five-number summary (no raw sample data sent to the
20
20
  browser). Does **not** extend `LyraChart` — a deliberately bespoke API.
21
21
 
22
+ If the browser cannot acquire a 2D canvas context, a localized visible message replaces the plot
23
+ and the generated or slotted data table becomes visible. No failed Chart.js instance is retained.
24
+ Changing the data or calling `refreshTheme()` retries rendering, so the plot recovers when the
25
+ canvas capability becomes available.
26
+
22
27
  With `IntersectionObserver` available, canvas construction waits for its first delivered visibility
23
28
  decision. An off-screen box plot stays unconstructed until visible. Without the observer, drawing
24
29
  starts when the peers and canvas are ready; an empty delivered callback retains the visible
@@ -25,6 +25,12 @@ For horizontal scalar bars, tooltip values come from parsed x rather than the ca
25
25
  an effective raw `config.options.indexAxis` override. Both formatter APIs follow this rule;
26
26
  structured points retain their y-value formatting.
27
27
 
28
+
29
+ If the browser cannot acquire a 2D canvas context, a localized visible message replaces the plot
30
+ and the generated or slotted data table becomes visible. No failed Chart.js instance is retained.
31
+ Changing the data or calling `refreshTheme()` retries rendering, so the plot recovers when the
32
+ canvas capability becomes available.
33
+
28
34
  **Properties:**
29
35
  - `axes: LyraChartAxes = 'both'` — `'x' | 'y' | 'both' | 'none'`, controlling complete cartesian
30
36
  axes: labels, ticks, borders and grid lines. The `y` setting includes `y2`; invalid values use
@@ -57,6 +57,8 @@ visually-hidden span spelling the current value out in text, the panel shows it
57
57
  field, and the selected palette swatch is marked with `aria-checked` plus a check mark rather than
58
58
  a tint alone. The palette is one roving `radiogroup` with a single tab stop: the arrow keys (Left/Right
59
59
  swap under RTL), Home and End move to and select the next enabled swatch, like `lr-swatch-picker`.
60
+ When required, the trigger also includes the localized `fieldRequired` description; the editable
61
+ value field exposes `aria-required`.
60
62
 
61
63
  Validation is projected onto both editing owners with an explicit stateful `aria-invalid`. A
62
64
  required empty picker starts pristine, so the popup trigger and panel value input both expose
@@ -60,8 +60,9 @@ resolves successfully). A failed or unavailable write emits the compatibility `l
60
60
 
61
61
  `file-status` is the one-letter git-status badge (`A`/`M`/`D`/`R`/`U`/`C`/`!`) rendered inside
62
62
  `[part="file-path"]`, present only for a file that has a `status`. The letter alone is meaningless to
63
- a screen reader, so the element carries the localized expansion as its `aria-label` — "Modified",
64
- "Added", … — reusing `<lr-file-tree>`'s shared `gitStatusAdded`/`gitStatusModified`/
63
+ a screen reader, so visually hidden text supplies the localized expansion — "Modified", "Added",
64
+ … — in the file button's name, while the visual letter is hidden from assistive technology.
65
+ It reuses `<lr-file-tree>`'s shared `gitStatusAdded`/`gitStatusModified`/
65
66
  `gitStatusDeleted`/`gitStatusRenamed`/`gitStatusUntracked`/`gitStatusConflicted`/`gitStatusIgnored`
66
67
  message keys, so one `registerLyraLocale()` registration (or one `.strings` override) translates the
67
68
  badge in both components at once.
@@ -9,7 +9,7 @@
9
9
  - **Release history** [CHANGELOG.md](../../CHANGELOG.md)
10
10
  - **Deprecations** none
11
11
  - **Optional peers** none
12
- - **Themeable via** 18 parts, 12 custom properties — see this component's own `@csspart`/`@cssprop` list below
12
+ - **Themeable via** 18 parts, 13 custom properties — see this component's own `@csspart`/`@cssprop` list below
13
13
  - **Library-wide behavior** (events, form association, `locale`/`strings`, tokens, TS types): `llms/shared.md`
14
14
 
15
15
  ---
@@ -30,7 +30,10 @@ movements remain separate announcements, and `[part="live-region"]` is only an `
30
30
  Both modes deliberately retain physical LTR grid geometry under `dir="rtl"`: matrix column 0 and
31
31
  calendar week 0 remain at the physical left, so ArrowLeft and ArrowRight retain their physical
32
32
  previous/next movement instead of swapping for RTL.
33
- Full canvas redraws pause while the host is outside the viewport. Data, locale, theme, resize, and
33
+ Full canvas redraws pause while the host is outside the viewport. A deferred `fitToWidth` frame
34
+ stays within a smaller allocation when the current grid fits it; explicit cell floors, accessible
35
+ hit targets and custom column extents still retain intentional overflow. The next visible draw
36
+ restores the bitmap and cell geometry together. Data, locale, theme, resize, and
34
37
  DPR invalidations remain pending and coalesce into one redraw when the heatmap intersects again;
35
38
  environments without `IntersectionObserver` retain eager drawing. A theme signal (any ancestor
36
39
  `style`/`class` write) repaints only when a theme token the canvas reads changed, or while `cellColor`
@@ -464,6 +467,11 @@ resolve-via-`getComputedStyle` pattern), `--lr-heatmap-label-font` (default
464
467
  `--lr-heatmap-focus-ring-color` (default
465
468
  `var(--lr-focus-ring-color)` — the canvas-drawn ring stroked around the keyboard-focused cell;
466
469
  also reused by `[part="canvas"]`'s own `:focus-visible` outline so the two stay visually in sync),
470
+ `--lr-heatmap-hover-ring-color` (defaults to the effective `--lr-heatmap-focus-ring-color`) —
471
+ the pointer-hover outline on the canvas and accessible cells. Set it to `transparent` to omit
472
+ that outline while retaining keyboard-focus and pressed feedback. Leaving it unset preserves
473
+ existing hover styling; native forced-color adjustment remains enabled.
474
+
467
475
  `--lr-heatmap-color-steps-gradient` (default
468
476
  `linear-gradient(to right, var(--lr-heatmap-scale-lo), var(--lr-heatmap-scale-hi))` — the gradient
469
477
  painted on the continuous legend bar; the component writes it onto the host itself while
@@ -109,6 +109,8 @@ combobox with a permanently inert popup state — opening a one-row list to pick
109
109
  choice is pure friction with no real decision behind it. It never changes `value`/validity defaults
110
110
  on its own: an unselected single-option select stays unselected (and a `required` one stays invalid)
111
111
  exactly like the multi-option case, until the trigger is actually activated.
112
+ In this button mode, a required field is described with the localized `fieldRequired` message;
113
+ the normal combobox trigger continues to expose `aria-required`.
112
114
 
113
115
  **Properties:**
114
116
 
@@ -114,6 +114,10 @@ it with `[part="label"]`'s generated id whenever `label` is non-empty (so tabbin
114
114
  `exactValue`-focusable value still announces e.g. "Revenue $1.2K USD", including the visible unit,
115
115
  not just the bare value); each
116
116
  `[part="row-value"]` is paired the same way with its own row's `[part="row-label"]`.
117
+ Present metric and row labels expose the `term` role; their named values expose `definition`,
118
+ which supports these accessible names. A unit-only headline value also exposes `definition`
119
+ and includes the unit in its name. Values without a label or unit remain plain text; setting
120
+ `exactValue` still adds the existing focus stop and exact-value tooltip in an unlinked stat.
117
121
 
118
122
  **Themeable custom properties:** `--lr-stat-bg` (default `var(--lr-color-surface)`) is
119
123
  `[part="base"]`'s RESTING background — the tier a dashboard sits at all day, and the companion to
package/llms/peers.md CHANGED
@@ -38,7 +38,7 @@ for the page.
38
38
  | Peer | Range | Needed by |
39
39
  |---|---|---|
40
40
  | `@aceshooting/lyra-flags` | `^2.3.0` | _(loaded by a shared internal module)_ |
41
- | `@aceshooting/lyra-translations` | `^28.0.0` | _(not referenced by any component)_ |
41
+ | `@aceshooting/lyra-translations` | `^28.1.1` | _(not referenced by any component)_ |
42
42
  | `@aiden0z/pptx-renderer` | `^1.3.0` | `lr-pptx-viewer` |
43
43
  | `@sgratzl/chartjs-chart-boxplot` | `^4.0.0` | `lr-box-plot` |
44
44
  | `chart.js` | `^4.0.1` | `lr-bar-chart`, `lr-box-plot`, `lr-bubble-chart`, `lr-chart`, `lr-doughnut-chart`, `lr-histogram`, `lr-line-chart`, `lr-pie-chart`, `lr-polar-area-chart`, `lr-radar-chart`, `lr-scatter-chart` |
@@ -130,3 +130,47 @@ sanitizer is unavailable. Some components additionally issue a deduped warning.
130
130
  component section instead of assuming every peer user renders an `<lr-skeleton>` or the same
131
131
  degraded state. `lr-phone-input` is the exception to dynamic peer import: it takes a consumer-built
132
132
  adapter (`loadLibphonenumberAdapter()`) rather than importing `libphonenumber-js` itself.
133
+
134
+ ### Experimental DOCX editing companion
135
+
136
+ Use `@aceshooting/lyra-docs` for editing; `lr-docx-viewer` remains a viewer in Lyra UI.
137
+ The companion uses optional `@docx-editor.dev/core@2.27.0`. Its installed README owns
138
+ installation, admission limits, lifecycle, exact supported structures and save receipts.
139
+
140
+ ```ts
141
+ import '@aceshooting/lyra-ui/theme.css';
142
+ import '@aceshooting/lyra-docs/docx/editor';
143
+ import '@aceshooting/lyra-docs/docx/editor.css';
144
+ import { createDocxSession } from '@aceshooting/lyra-docs/docx';
145
+ ```
146
+
147
+ `lr-docx-editor` provides command search (Ctrl/Command+K), bounded find excerpts and
148
+ replace-and-advance, Outline, Checks and Review panels, table formatting and local raster
149
+ image tools. `createDocxSession({ mount })` supports a host-owned toolbar; it requires a
150
+ connected empty light-DOM mount. Both routes expose `can()`/`execute()`, `find()`/
151
+ `selectMatch()`/`replaceMatch()`, `outline()`/`selectOutlineItem()`, `inspectDocument()`/
152
+ `selectDiagnostic()`, and `review()`/`selectReviewItem()`. Query rows are copied, bounded
153
+ and revision-scoped; refresh after edits and pass the returned `expectedRevision` when
154
+ navigating. Queries do not save or fetch. Inspection covers body metadata only; capability
155
+ fields `preserved`, `renderable` and `editable` remain `unverified`, and the report is not
156
+ an accessibility certification.
157
+
158
+ `insertImage(source, options)` copies local raster bytes and requires explicit dimensions;
159
+ its narrow package profile includes visible styles and plain table cells at existing
160
+ paragraph/run boundaries. `replaceImage(bytes, options)` preserves selected image size,
161
+ title and description. Both use `DocxInsertImageOptions` for retained selection, revision
162
+ and cancellation. `canInsertImage()` and `canReplaceImage()` are advisory; unsupported
163
+ content refuses unchanged after canonical qualification.
164
+
165
+ Table actions cover simple topology, explicit first-row headers, current-cell vertical
166
+ alignment/shading/borders, and equal-column table width. Adding or replying to comments
167
+ and changing tracking mode require an explicit author; supported comments can be replied
168
+ to, resolved/reopened and deleted.
169
+ Only bounded simple body text insertion/deletion revisions support accept/reject;
170
+ unsupported revisions remain `readOnly`. These contracts do not qualify every native
171
+ engine gesture or promise arbitrary DOCX fidelity.
172
+
173
+ The host persists bytes explicitly: `save()` returns a receipt; call
174
+ `acknowledgeSaved(receipt)` only after durable persistence. Disconnect destroys the
175
+ session and undo history. See the [companion README](https://github.com/aceshooting/lyra-ui/blob/main/packages/lyra-docs/README.md)
176
+ for complete public types, bounds and guarded examples.
@@ -10,7 +10,7 @@ that need form-value or validity behavior: it supplies
10
10
  `form`/`labels`/`validity`/`validationMessage`/`willValidate`. The shim is a no-op where the
11
11
  platform already provides internals, so it is safe in a shared setup file.
12
12
 
13
- `installHappyDomShims()` installs that shim plus two more Happy DOM gap fixes, each a no-op where
13
+ `installHappyDomShims()` installs that shim plus Happy DOM gap fixes, each a no-op where
14
14
  the engine already behaves (feature-detected, so safe in a shared setup file and never part of a
15
15
  production bundle): `installHappyDomShadowFocusShim()` makes `ShadowRoot.activeElement` return
16
16
  `null` for a sibling or detached shadow root instead of throwing a `TypeError` (own-root and
@@ -36,6 +36,19 @@ a no-op in every browser and without a `CSSStyleSheet` global; it installs once
36
36
  function that restores the original methods. Install it before any stylesheet is parsed (in the
37
37
  same `setupFiles` entry): a sheet parsed earlier keeps the rules it dropped.
38
38
 
39
+ `installHappyDomShims()` also supplies `ShadowRoot.styleSheets` when the environment lacks it.
40
+ The live collection lists non-null `<style>` and stylesheet-link sheets in that shadow tree,
41
+ in tree order, with indexed access, `length`, `item()` and iteration. Retained collections reflect
42
+ insertions and removals; nested shadow trees and constructed `adoptedStyleSheets` remain separate.
43
+ This lets marked application scopes discover and adopt their token provider under Happy DOM.
44
+ An existing platform collection is never replaced, and plain Node remains unchanged.
45
+
46
+ When Happy DOM lacks the HTML `dir="ltr"`/`dir="rtl"` presentational hints,
47
+ `installHappyDomShims()` adds zero-specificity direction rules to the document head. This restores
48
+ computed direction and inherited component direction while preserving explicit author CSS.
49
+ The shim probes support before installing, is idempotent, and never runs in a native browser.
50
+ It does not emulate `dir="auto"` text analysis or the `:dir()` pseudo-class.
51
+
39
52
  ### jsdom: `installJsdomShims()`
40
53
 
41
54
  jsdom implements no `adoptedStyleSheets`, so Lit renders one `<style>` element per component
package/llms/shared.md CHANGED
@@ -2719,6 +2719,50 @@ component section instead of assuming every peer user renders an `<lr-skeleton>`
2719
2719
  degraded state. `lr-phone-input` is the exception to dynamic peer import: it takes a consumer-built
2720
2720
  adapter (`loadLibphonenumberAdapter()`) rather than importing `libphonenumber-js` itself.
2721
2721
 
2722
+ ### Experimental DOCX editing companion
2723
+
2724
+ Use `@aceshooting/lyra-docs` for editing; `lr-docx-viewer` remains a viewer in Lyra UI.
2725
+ The companion uses optional `@docx-editor.dev/core@2.27.0`. Its installed README owns
2726
+ installation, admission limits, lifecycle, exact supported structures and save receipts.
2727
+
2728
+ ```ts
2729
+ import '@aceshooting/lyra-ui/theme.css';
2730
+ import '@aceshooting/lyra-docs/docx/editor';
2731
+ import '@aceshooting/lyra-docs/docx/editor.css';
2732
+ import { createDocxSession } from '@aceshooting/lyra-docs/docx';
2733
+ ```
2734
+
2735
+ `lr-docx-editor` provides command search (Ctrl/Command+K), bounded find excerpts and
2736
+ replace-and-advance, Outline, Checks and Review panels, table formatting and local raster
2737
+ image tools. `createDocxSession({ mount })` supports a host-owned toolbar; it requires a
2738
+ connected empty light-DOM mount. Both routes expose `can()`/`execute()`, `find()`/
2739
+ `selectMatch()`/`replaceMatch()`, `outline()`/`selectOutlineItem()`, `inspectDocument()`/
2740
+ `selectDiagnostic()`, and `review()`/`selectReviewItem()`. Query rows are copied, bounded
2741
+ and revision-scoped; refresh after edits and pass the returned `expectedRevision` when
2742
+ navigating. Queries do not save or fetch. Inspection covers body metadata only; capability
2743
+ fields `preserved`, `renderable` and `editable` remain `unverified`, and the report is not
2744
+ an accessibility certification.
2745
+
2746
+ `insertImage(source, options)` copies local raster bytes and requires explicit dimensions;
2747
+ its narrow package profile includes visible styles and plain table cells at existing
2748
+ paragraph/run boundaries. `replaceImage(bytes, options)` preserves selected image size,
2749
+ title and description. Both use `DocxInsertImageOptions` for retained selection, revision
2750
+ and cancellation. `canInsertImage()` and `canReplaceImage()` are advisory; unsupported
2751
+ content refuses unchanged after canonical qualification.
2752
+
2753
+ Table actions cover simple topology, explicit first-row headers, current-cell vertical
2754
+ alignment/shading/borders, and equal-column table width. Adding or replying to comments
2755
+ and changing tracking mode require an explicit author; supported comments can be replied
2756
+ to, resolved/reopened and deleted.
2757
+ Only bounded simple body text insertion/deletion revisions support accept/reject;
2758
+ unsupported revisions remain `readOnly`. These contracts do not qualify every native
2759
+ engine gesture or promise arbitrary DOCX fidelity.
2760
+
2761
+ The host persists bytes explicitly: `save()` returns a receipt; call
2762
+ `acknowledgeSaved(receipt)` only after durable persistence. Disconnect destroys the
2763
+ session and undo history. See the [companion README](https://github.com/aceshooting/lyra-ui/blob/main/packages/lyra-docs/README.md)
2764
+ for complete public types, bounds and guarded examples.
2765
+
2722
2766
  ## Framework integration
2723
2767
 
2724
2768
  Plain custom elements, so they work anywhere — with the usual two caveats. React 19/JSX, Vue 3,
@@ -2852,7 +2896,7 @@ that need form-value or validity behavior: it supplies
2852
2896
  `form`/`labels`/`validity`/`validationMessage`/`willValidate`. The shim is a no-op where the
2853
2897
  platform already provides internals, so it is safe in a shared setup file.
2854
2898
 
2855
- `installHappyDomShims()` installs that shim plus two more Happy DOM gap fixes, each a no-op where
2899
+ `installHappyDomShims()` installs that shim plus Happy DOM gap fixes, each a no-op where
2856
2900
  the engine already behaves (feature-detected, so safe in a shared setup file and never part of a
2857
2901
  production bundle): `installHappyDomShadowFocusShim()` makes `ShadowRoot.activeElement` return
2858
2902
  `null` for a sibling or detached shadow root instead of throwing a `TypeError` (own-root and
@@ -2878,6 +2922,19 @@ a no-op in every browser and without a `CSSStyleSheet` global; it installs once
2878
2922
  function that restores the original methods. Install it before any stylesheet is parsed (in the
2879
2923
  same `setupFiles` entry): a sheet parsed earlier keeps the rules it dropped.
2880
2924
 
2925
+ `installHappyDomShims()` also supplies `ShadowRoot.styleSheets` when the environment lacks it.
2926
+ The live collection lists non-null `<style>` and stylesheet-link sheets in that shadow tree,
2927
+ in tree order, with indexed access, `length`, `item()` and iteration. Retained collections reflect
2928
+ insertions and removals; nested shadow trees and constructed `adoptedStyleSheets` remain separate.
2929
+ This lets marked application scopes discover and adopt their token provider under Happy DOM.
2930
+ An existing platform collection is never replaced, and plain Node remains unchanged.
2931
+
2932
+ When Happy DOM lacks the HTML `dir="ltr"`/`dir="rtl"` presentational hints,
2933
+ `installHappyDomShims()` adds zero-specificity direction rules to the document head. This restores
2934
+ computed direction and inherited component direction while preserving explicit author CSS.
2935
+ The shim probes support before installing, is idempotent, and never runs in a native browser.
2936
+ It does not emulate `dir="auto"` text analysis or the `:dir()` pseudo-class.
2937
+
2881
2938
  ### jsdom: `installJsdomShims()`
2882
2939
 
2883
2940
  jsdom implements no `adoptedStyleSheets`, so Lit renders one `<style>` element per component