@pgcorp/ui-kit 0.13.0 → 0.15.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.
Files changed (354) hide show
  1. package/README.md +1055 -31
  2. package/dist/assets/src/components/layout/SDockRegion.vue_vue_type_style_index_0_scoped_a1f403e2_lang.css +1 -0
  3. package/dist/assets/src/components/layout/{SResizeHandle.vue_vue_type_style_index_0_scoped_90cc655e_lang.css → SResizeHandle.vue_vue_type_style_index_0_scoped_dc65aba1_lang.css} +1 -1
  4. package/dist/assets/src/components/layout/{SWorkbenchPanelShell.css_vue_type_style_index_0_src_1030a231_scoped_1030a231_lang.css → SWorkbenchPanelShell.css_vue_type_style_index_0_src_f9faa52a_scoped_f9faa52a_lang.css} +1 -1
  5. package/dist/assets/src/components/shared/_internal/SDialogSurface.css_vue_type_style_index_0_src_a108e8f1_scoped_a108e8f1_lang.css +2 -0
  6. package/dist/assets/src/components/shared/_internal/{SListboxGroup.css_vue_type_style_index_0_src_518787d3_scoped_518787d3_lang.css → SListboxGroup.css_vue_type_style_index_0_src_00060944_scoped_00060944_lang.css} +1 -1
  7. package/dist/assets/src/components/shared/_internal/SMenuLayer.css_vue_type_style_index_0_src_e478164c_scoped_e478164c_lang.css +1 -0
  8. package/dist/assets/src/components/shared/containers/{SCollapsiblePanel.css_vue_type_style_index_0_src_71824088_scoped_71824088_lang.css → SCollapsiblePanel.css_vue_type_style_index_0_src_db85261d_scoped_db85261d_lang.css} +1 -1
  9. package/dist/assets/src/components/shared/containers/SOverlayHost.css_vue_type_style_index_0_src_09215628_scoped_09215628_lang.css +2 -0
  10. package/dist/assets/src/components/shared/containers/SPopover.css_vue_type_style_index_0_src_a4f1f64a_scoped_a4f1f64a_lang.css +2 -0
  11. package/dist/assets/src/components/shared/containers/{SSidebarGroup.css_vue_type_style_index_0_src_3e8bc2d7_scoped_3e8bc2d7_lang.css → SSidebarGroup.css_vue_type_style_index_0_src_5b1eeb6c_scoped_5b1eeb6c_lang.css} +1 -1
  12. package/dist/assets/src/components/shared/containers/SSidebarSection.css_vue_type_style_index_0_src_52396e42_scoped_52396e42_lang.css +2 -0
  13. package/dist/assets/src/components/shared/controls/SButton.css_vue_type_style_index_0_src_7a5acda9_scoped_7a5acda9_lang.css +2 -0
  14. package/dist/assets/src/components/shared/controls/SCheckbox.css_vue_type_style_index_0_src_2562f916_scoped_2562f916_lang.css +2 -0
  15. package/dist/assets/src/components/shared/controls/SCombobox.css_vue_type_style_index_0_src_d630c922_scoped_d630c922_lang.css +2 -0
  16. package/dist/assets/src/components/shared/controls/SContextMenu.css_vue_type_style_index_0_src_43b6e378_scoped_43b6e378_lang.css +1 -0
  17. package/dist/assets/src/components/shared/controls/{SDropdownMenu.css_vue_type_style_index_0_src_1ccb9efc_scoped_1ccb9efc_lang.css → SDropdownMenu.css_vue_type_style_index_0_src_40040ae5_scoped_40040ae5_lang.css} +1 -1
  18. package/dist/assets/src/components/shared/controls/SField.css_vue_type_style_index_0_src_2d353c26_scoped_2d353c26_lang.css +2 -0
  19. package/dist/assets/src/components/shared/controls/{SInteractiveSurface.css_vue_type_style_index_0_src_998940dd_scoped_998940dd_lang.css → SInteractiveSurface.css_vue_type_style_index_0_src_5e422fac_scoped_5e422fac_lang.css} +1 -1
  20. package/dist/assets/src/components/shared/controls/{SLink.css_vue_type_style_index_0_src_c7ae14e1_scoped_c7ae14e1_lang.css → SLink.css_vue_type_style_index_0_src_ac46e5a4_scoped_ac46e5a4_lang.css} +1 -1
  21. package/dist/assets/src/components/shared/controls/SListbox.css_vue_type_style_index_0_src_50063f9f_scoped_50063f9f_lang.css +2 -0
  22. package/dist/assets/src/components/shared/controls/{SListboxOption.css_vue_type_style_index_0_src_77c399b4_scoped_77c399b4_lang.css → SListboxOption.css_vue_type_style_index_0_src_59c9c538_scoped_59c9c538_lang.css} +1 -1
  23. package/dist/assets/src/components/shared/controls/SMenuSurface.css_vue_type_style_index_0_src_d2b7d71b_scoped_d2b7d71b_lang.css +2 -0
  24. package/dist/assets/src/components/shared/controls/SSelect.css_vue_type_style_index_0_src_d1ead6c0_scoped_d1ead6c0_lang.css +2 -0
  25. package/dist/assets/src/components/shared/controls/STextarea.css_vue_type_style_index_0_src_true_lang.css +1 -1
  26. package/dist/assets/src/components/shared/data-display/SControlledToastViewport.css_vue_type_style_index_0_src_a69aa84b_scoped_a69aa84b_lang.css +2 -0
  27. package/dist/assets/src/components/shared/data-display/SProgressBar.css_vue_type_style_index_0_src_cad721dd_scoped_cad721dd_lang.css +2 -0
  28. package/dist/assets/src/components/shared/data-display/SRichDocument.css_vue_type_style_index_0_src_8db085d5_scoped_8db085d5_lang.css +2 -0
  29. package/dist/assets/src/components/shared/data-display/SScrollViewport.css_vue_type_style_index_0_src_d94fcf8c_scoped_d94fcf8c_lang.css +2 -0
  30. package/dist/assets/src/components/shared/data-display/SStatus.css_vue_type_style_index_0_src_3ce41a12_scoped_3ce41a12_lang.css +1 -1
  31. package/dist/assets/src/components/shared/data-display/STable.css_vue_type_style_index_0_src_b23b3d71_scoped_b23b3d71_lang.css +2 -0
  32. package/dist/assets/src/components/shared/data-display/STooltip.css_vue_type_style_index_0_src_true_lang.css +1 -1
  33. package/dist/assets/src/components/shared/data-display/SVirtualList.css_vue_type_style_index_0_src_9fe3ade0_scoped_9fe3ade0_lang.css +2 -0
  34. package/dist/assets/src/components/shared/data-display/_internal/SRichBlockNode.css_vue_type_style_index_0_src_eaae882d_scoped_eaae882d_lang.css +2 -0
  35. package/dist/assets/src/components/shared/data-display/_internal/SRichDisclosure.css_vue_type_style_index_0_src_1f0ffc97_scoped_1f0ffc97_lang.css +2 -0
  36. package/dist/assets/src/components/shared/data-display/_internal/SRichImage.css_vue_type_style_index_0_src_2f1c39a9_scoped_2f1c39a9_lang.css +2 -0
  37. package/dist/assets/src/components/shared/data-display/_internal/{SRichInlineNode.css_vue_type_style_index_0_src_20c8cc87_scoped_20c8cc87_lang.css → SRichInlineNode.css_vue_type_style_index_0_src_3ca8df12_scoped_3ca8df12_lang.css} +1 -1
  38. package/dist/assets/src/components/shared/data-display/_internal/STableCell.css_vue_type_style_index_0_src_b829cbc6_scoped_b829cbc6_lang.css +2 -0
  39. package/dist/assets/src/components/shared/data-display/_internal/STableFrame.css_vue_type_style_index_0_src_914bad28_scoped_914bad28_lang.css +2 -0
  40. package/dist/assets/src/components/shared/data-display/_internal/STableRow.css_vue_type_style_index_0_src_1661f8b8_scoped_1661f8b8_lang.css +2 -0
  41. package/dist/assets/src/components/shared/feedback/SAsyncState.css_vue_type_style_index_0_src_8a291af7_scoped_8a291af7_lang.css +2 -0
  42. package/dist/assets/src/components/shared/navigation/{SBottomNav.vue_vue_type_style_index_0_scoped_b3963080_lang.css → SBottomNav.vue_vue_type_style_index_0_scoped_68cf84b3_lang.css} +1 -1
  43. package/dist/index.d.ts +1 -0
  44. package/dist/index.js +3 -3
  45. package/dist/reference.css +4 -0
  46. package/dist/src/components/icons/_internal/generatedSputnigUiIconComponents.d.ts +15 -0
  47. package/dist/src/components/icons/_internal/generatedSputnigUiIconComponents.js +4 -4
  48. package/dist/src/components/icons/_internal/generatedSputnigUiIconMarkup.d.ts +46 -1
  49. package/dist/src/components/icons/_internal/generatedSputnigUiIconMarkup.js +260 -230
  50. package/dist/src/components/icons/sputnigUiIcons.d.ts +1 -1
  51. package/dist/src/components/icons/sputnigUiIcons.js +233 -218
  52. package/dist/src/components/layout/SAppShell.vue_vue_type_script_setup_true_lang.js +8 -8
  53. package/dist/src/components/layout/SDockRegion.vue.d.ts +18 -5
  54. package/dist/src/components/layout/SDockRegion.vue.js +2 -2
  55. package/dist/src/components/layout/SDockRegion.vue_vue_type_script_setup_true_lang.js +112 -64
  56. package/dist/src/components/layout/SResizeHandle.vue.d.ts +6 -3
  57. package/dist/src/components/layout/SResizeHandle.vue.js +2 -2
  58. package/dist/src/components/layout/SResizeHandle.vue_vue_type_script_setup_true_lang.js +127 -87
  59. package/dist/src/components/layout/SStack.vue.d.ts +1 -1
  60. package/dist/src/components/layout/SWorkbenchPanelShell.vue.d.ts +4 -4
  61. package/dist/src/components/layout/SWorkbenchPanelShell.vue.js +2 -2
  62. package/dist/src/components/layout/SWorkbenchPanelShell.vue_vue_type_script_setup_true_lang.js +62 -58
  63. package/dist/src/components/layout/types.d.ts +20 -0
  64. package/dist/src/components/shared/_internal/SDialogSurface.vue.d.ts +9 -1
  65. package/dist/src/components/shared/_internal/SDialogSurface.vue.js +2 -2
  66. package/dist/src/components/shared/_internal/SDialogSurface.vue_vue_type_script_setup_true_lang.js +183 -68
  67. package/dist/src/components/shared/_internal/SHeaderSurface.vue.d.ts +1 -1
  68. package/dist/src/components/shared/_internal/SListboxGroup.vue.d.ts +5 -0
  69. package/dist/src/components/shared/_internal/SListboxGroup.vue.js +2 -2
  70. package/dist/src/components/shared/_internal/SListboxGroup.vue_vue_type_script_setup_true_lang.js +33 -15
  71. package/dist/src/components/shared/_internal/SMenuLayer.vue.d.ts +5 -1
  72. package/dist/src/components/shared/_internal/SMenuLayer.vue.js +2 -2
  73. package/dist/src/components/shared/_internal/SMenuLayer.vue_vue_type_script_setup_true_lang.js +64 -20
  74. package/dist/src/components/shared/_internal/dialogSurface.d.ts +17 -2
  75. package/dist/src/components/shared/_internal/dialogSurface.js +42 -23
  76. package/dist/src/components/shared/_internal/dialogSurfaceMotion.d.ts +14 -0
  77. package/dist/src/components/shared/_internal/dialogSurfaceMotion.js +84 -0
  78. package/dist/src/components/shared/_internal/focusTrap.js +15 -13
  79. package/dist/src/components/shared/_internal/listboxContext.d.ts +1 -0
  80. package/dist/src/components/shared/_internal/listboxInventory.d.ts +51 -0
  81. package/dist/src/components/shared/_internal/listboxInventory.js +85 -0
  82. package/dist/src/components/shared/_internal/menuContext.d.ts +8 -0
  83. package/dist/src/components/shared/_internal/menuContext.js +2 -2
  84. package/dist/src/components/shared/_internal/sidebarGroupContext.d.ts +1 -0
  85. package/dist/src/components/shared/_internal/useVirtualCollection.d.ts +45 -0
  86. package/dist/src/components/shared/_internal/useVirtualCollection.js +123 -0
  87. package/dist/src/components/shared/complex/SKanbanLane.vue_vue_type_script_setup_true_lang.js +5 -5
  88. package/dist/src/components/shared/containers/SCloudChrome.vue.d.ts +1 -1
  89. package/dist/src/components/shared/containers/SCloudChromeRow.vue.d.ts +1 -1
  90. package/dist/src/components/shared/containers/SCollapsiblePanel.vue.d.ts +5 -0
  91. package/dist/src/components/shared/containers/SCollapsiblePanel.vue.js +2 -2
  92. package/dist/src/components/shared/containers/SCollapsiblePanel.vue_vue_type_script_setup_true_lang.js +123 -121
  93. package/dist/src/components/shared/containers/SDrawer.vue.d.ts +16 -5
  94. package/dist/src/components/shared/containers/SDrawer.vue.js +3 -6
  95. package/dist/src/components/shared/containers/SDrawer.vue_vue_type_script_setup_true_lang.js +149 -75
  96. package/dist/src/components/shared/containers/SModal.vue.d.ts +8 -8
  97. package/dist/src/components/shared/containers/SModal.vue.js +3 -6
  98. package/dist/src/components/shared/containers/SModal.vue_vue_type_script_setup_true_lang.js +93 -85
  99. package/dist/src/components/shared/containers/SOverlayHost.vue.d.ts +16 -0
  100. package/dist/src/components/shared/containers/SOverlayHost.vue.js +8 -0
  101. package/dist/src/components/shared/containers/SOverlayHost.vue_vue_type_script_setup_true_lang.js +66 -0
  102. package/dist/src/components/shared/containers/SPageHeader.vue.d.ts +1 -1
  103. package/dist/src/components/shared/containers/SPanel.vue.d.ts +2 -2
  104. package/dist/src/components/shared/containers/SPanel.vue_vue_type_script_setup_true_lang.js +7 -7
  105. package/dist/src/components/shared/containers/SPopover.vue.js +2 -2
  106. package/dist/src/components/shared/containers/SPopover.vue_vue_type_script_setup_true_lang.js +250 -156
  107. package/dist/src/components/shared/containers/SSidebarGroup.vue.js +2 -2
  108. package/dist/src/components/shared/containers/SSidebarGroup.vue_vue_type_script_setup_true_lang.js +30 -8
  109. package/dist/src/components/shared/containers/SSidebarSection.vue.js +2 -2
  110. package/dist/src/components/shared/containers/SSidebarSection.vue_vue_type_script_setup_true_lang.js +59 -45
  111. package/dist/src/components/shared/controls/SButton.vue.d.ts +7 -0
  112. package/dist/src/components/shared/controls/SButton.vue.js +2 -2
  113. package/dist/src/components/shared/controls/SButton.vue_vue_type_script_setup_true_lang.js +11 -5
  114. package/dist/src/components/shared/controls/SCheckbox.vue.d.ts +3 -0
  115. package/dist/src/components/shared/controls/SCheckbox.vue.js +2 -2
  116. package/dist/src/components/shared/controls/SCheckbox.vue_vue_type_script_setup_true_lang.js +53 -43
  117. package/dist/src/components/shared/controls/SCheckboxGroup.vue_vue_type_script_setup_true_lang.js +7 -7
  118. package/dist/src/components/shared/controls/SChoiceCards.vue_vue_type_script_setup_true_lang.js +4 -4
  119. package/dist/src/components/shared/controls/SColorSelect.vue_vue_type_script_setup_true_lang.js +6 -6
  120. package/dist/src/components/shared/controls/SCombobox.vue.js +2 -2
  121. package/dist/src/components/shared/controls/SCombobox.vue_vue_type_script_setup_true_lang.js +157 -132
  122. package/dist/src/components/shared/controls/SComboboxTrigger.vue.d.ts +2 -2
  123. package/dist/src/components/shared/controls/SContextMenu.vue.d.ts +11 -0
  124. package/dist/src/components/shared/controls/SContextMenu.vue.js +2 -2
  125. package/dist/src/components/shared/controls/SContextMenu.vue_vue_type_script_setup_true_lang.js +163 -73
  126. package/dist/src/components/shared/controls/SContextToggleButton.vue_vue_type_script_setup_true_lang.js +6 -6
  127. package/dist/src/components/shared/controls/SDragHandle.vue_vue_type_script_setup_true_lang.js +5 -5
  128. package/dist/src/components/shared/controls/SDropdownMenu.vue.js +2 -2
  129. package/dist/src/components/shared/controls/SDropdownMenu.vue_vue_type_script_setup_true_lang.js +77 -65
  130. package/dist/src/components/shared/controls/SField.vue.d.ts +9 -6
  131. package/dist/src/components/shared/controls/SField.vue.js +2 -2
  132. package/dist/src/components/shared/controls/SField.vue_vue_type_script_setup_true_lang.js +69 -52
  133. package/dist/src/components/shared/controls/SFieldGroup.vue_vue_type_script_setup_true_lang.js +13 -13
  134. package/dist/src/components/shared/controls/SInlineTokenEditor.vue_vue_type_script_setup_true_lang.js +26 -26
  135. package/dist/src/components/shared/controls/SInputText.vue_vue_type_script_setup_true_lang.js +21 -21
  136. package/dist/src/components/shared/controls/SInteractiveSurface.vue.js +2 -2
  137. package/dist/src/components/shared/controls/SInteractiveSurface.vue_vue_type_script_setup_true_lang.js +99 -74
  138. package/dist/src/components/shared/controls/SLink.d.ts +11 -1
  139. package/dist/src/components/shared/controls/SLink.vue.d.ts +17 -1
  140. package/dist/src/components/shared/controls/SLink.vue.js +2 -2
  141. package/dist/src/components/shared/controls/SLink.vue_vue_type_script_setup_true_lang.js +157 -62
  142. package/dist/src/components/shared/controls/SListbox.vue.d.ts +10 -1
  143. package/dist/src/components/shared/controls/SListbox.vue.js +2 -2
  144. package/dist/src/components/shared/controls/SListbox.vue_vue_type_script_setup_true_lang.js +371 -189
  145. package/dist/src/components/shared/controls/SListboxOption.vue.d.ts +6 -0
  146. package/dist/src/components/shared/controls/SListboxOption.vue.js +2 -2
  147. package/dist/src/components/shared/controls/SListboxOption.vue_vue_type_script_setup_true_lang.js +47 -34
  148. package/dist/src/components/shared/controls/SMenuSurface.vue.d.ts +2 -2
  149. package/dist/src/components/shared/controls/SMenuSurface.vue.js +2 -2
  150. package/dist/src/components/shared/controls/SMenuSurface.vue_vue_type_script_setup_true_lang.js +145 -115
  151. package/dist/src/components/shared/controls/SRange.vue_vue_type_script_setup_true_lang.js +12 -12
  152. package/dist/src/components/shared/controls/SSelect.vue.js +2 -2
  153. package/dist/src/components/shared/controls/SSelect.vue_vue_type_script_setup_true_lang.js +130 -112
  154. package/dist/src/components/shared/controls/STextarea.d.ts +1 -1
  155. package/dist/src/components/shared/controls/STextarea.vue.d.ts +28 -2
  156. package/dist/src/components/shared/controls/STextarea.vue_vue_type_script_setup_true_lang.js +348 -209
  157. package/dist/src/components/shared/controls/_internal/SInlineTokenSurface.vue_vue_type_script_lang.js +36 -36
  158. package/dist/src/components/shared/data-display/SActionList.vue.d.ts +1 -1
  159. package/dist/src/components/shared/data-display/SActionListItem.vue.d.ts +4 -4
  160. package/dist/src/components/shared/data-display/SActionListItem.vue_vue_type_script_setup_true_lang.js +6 -6
  161. package/dist/src/components/shared/data-display/SBadge.vue.d.ts +1 -1
  162. package/dist/src/components/shared/data-display/SChart.vue_vue_type_script_setup_true_lang.js +89 -89
  163. package/dist/src/components/shared/data-display/SChip.vue.d.ts +1 -1
  164. package/dist/src/components/shared/data-display/SChip.vue_vue_type_script_setup_true_lang.js +7 -7
  165. package/dist/src/components/shared/data-display/SCodeBlock.vue_vue_type_script_setup_true_lang.js +19 -19
  166. package/dist/src/components/shared/data-display/SCodeEditor.vue_vue_type_script_setup_true_lang.js +37 -37
  167. package/dist/src/components/shared/data-display/SCodeSearchPanel.vue_vue_type_script_setup_true_lang.js +17 -17
  168. package/dist/src/components/shared/data-display/SCodeWorkspaceEditor.vue_vue_type_script_setup_true_lang.js +12 -12
  169. package/dist/src/components/shared/data-display/SControlledToastViewport.vue.js +2 -2
  170. package/dist/src/components/shared/data-display/SControlledToastViewport.vue_vue_type_script_setup_true_lang.js +57 -48
  171. package/dist/src/components/shared/data-display/SDiffViewer.vue_vue_type_script_setup_true_lang.js +13 -13
  172. package/dist/src/components/shared/data-display/SDocBlock.vue_vue_type_script_setup_true_lang.js +12 -12
  173. package/dist/src/components/shared/data-display/SEmptyState.vue.d.ts +1 -1
  174. package/dist/src/components/shared/data-display/SEmptyState.vue_vue_type_script_setup_true_lang.js +4 -4
  175. package/dist/src/components/shared/data-display/SExpandableText.vue_vue_type_script_setup_true_lang.js +7 -7
  176. package/dist/src/components/shared/data-display/SKeyValueGrid.vue_vue_type_script_setup_true_lang.js +15 -15
  177. package/dist/src/components/shared/data-display/SLinkedSystemsList.vue_vue_type_script_setup_true_lang.js +17 -17
  178. package/dist/src/components/shared/data-display/SMessage.vue.d.ts +1 -1
  179. package/dist/src/components/shared/data-display/SMessage.vue_vue_type_script_setup_true_lang.js +9 -9
  180. package/dist/src/components/shared/data-display/SMetricCard.vue.d.ts +1 -1
  181. package/dist/src/components/shared/data-display/SProgressBar.vue.d.ts +22 -3
  182. package/dist/src/components/shared/data-display/SProgressBar.vue.js +2 -2
  183. package/dist/src/components/shared/data-display/SProgressBar.vue_vue_type_script_setup_true_lang.js +133 -47
  184. package/dist/src/components/shared/data-display/SProgressIndicator.vue_vue_type_script_setup_true_lang.js +4 -4
  185. package/dist/src/components/shared/data-display/SRichDocument.vue.js +2 -2
  186. package/dist/src/components/shared/data-display/SRichDocument.vue_vue_type_script_setup_true_lang.js +46 -23
  187. package/dist/src/components/shared/data-display/SScrollViewport.vue.d.ts +10 -5
  188. package/dist/src/components/shared/data-display/SScrollViewport.vue.js +2 -2
  189. package/dist/src/components/shared/data-display/SScrollViewport.vue_vue_type_script_setup_true_lang.js +162 -111
  190. package/dist/src/components/shared/data-display/SSectionHeader.vue.d.ts +1 -1
  191. package/dist/src/components/shared/data-display/SStatus.vue_vue_type_script_setup_true_lang.js +4 -4
  192. package/dist/src/components/shared/data-display/STable.vue.js +2 -2
  193. package/dist/src/components/shared/data-display/STable.vue_vue_type_script_setup_true_lang.js +343 -322
  194. package/dist/src/components/shared/data-display/STooltip.vue.d.ts +2 -2
  195. package/dist/src/components/shared/data-display/STooltip.vue_vue_type_script_setup_true_lang.js +284 -205
  196. package/dist/src/components/shared/data-display/STooltipAnchor.vue_vue_type_script_setup_true_lang.js +5 -5
  197. package/dist/src/components/shared/data-display/STooltipTarget.vue_vue_type_script_setup_true_lang.js +4 -4
  198. package/dist/src/components/shared/data-display/SVirtualList.vue.js +2 -2
  199. package/dist/src/components/shared/data-display/SVirtualList.vue_vue_type_script_setup_true_lang.js +196 -246
  200. package/dist/src/components/shared/data-display/_internal/SRichBlockNode.vue.js +2 -2
  201. package/dist/src/components/shared/data-display/_internal/SRichBlockNode.vue_vue_type_script_setup_true_lang.js +242 -220
  202. package/dist/src/components/shared/data-display/_internal/SRichDisclosure.vue.d.ts +13 -2
  203. package/dist/src/components/shared/data-display/_internal/SRichDisclosure.vue.js +2 -2
  204. package/dist/src/components/shared/data-display/_internal/SRichDisclosure.vue_vue_type_script_setup_true_lang.js +67 -11
  205. package/dist/src/components/shared/data-display/_internal/SRichImage.vue.d.ts +11 -0
  206. package/dist/src/components/shared/data-display/_internal/SRichImage.vue.js +8 -0
  207. package/dist/src/components/shared/data-display/_internal/SRichImage.vue_vue_type_script_setup_true_lang.js +89 -0
  208. package/dist/src/components/shared/data-display/_internal/SRichInlineNode.vue.d.ts +3 -2
  209. package/dist/src/components/shared/data-display/_internal/SRichInlineNode.vue.js +2 -2
  210. package/dist/src/components/shared/data-display/_internal/SRichInlineNode.vue_vue_type_script_setup_true_lang.js +179 -125
  211. package/dist/src/components/shared/data-display/_internal/SRichMath.vue_vue_type_script_setup_true_lang.js +4 -4
  212. package/dist/src/components/shared/data-display/_internal/SRichTableNode.vue.d.ts +21 -0
  213. package/dist/src/components/shared/data-display/_internal/SRichTableNode.vue.js +5 -0
  214. package/dist/src/components/shared/data-display/_internal/SRichTableNode.vue_vue_type_script_setup_true_lang.js +150 -0
  215. package/dist/src/components/shared/data-display/_internal/STableCell.vue.d.ts +52 -0
  216. package/dist/src/components/shared/data-display/_internal/STableCell.vue.js +8 -0
  217. package/dist/src/components/shared/data-display/_internal/STableCell.vue_vue_type_script_setup_true_lang.js +148 -0
  218. package/dist/src/components/shared/data-display/_internal/STableFrame.vue.d.ts +42 -0
  219. package/dist/src/components/shared/data-display/_internal/STableFrame.vue.js +8 -0
  220. package/dist/src/components/shared/data-display/_internal/STableFrame.vue_vue_type_script_setup_true_lang.js +114 -0
  221. package/dist/src/components/shared/data-display/_internal/STableRow.vue.d.ts +43 -0
  222. package/dist/src/components/shared/data-display/_internal/STableRow.vue.js +8 -0
  223. package/dist/src/components/shared/data-display/_internal/STableRow.vue_vue_type_script_setup_true_lang.js +115 -0
  224. package/dist/src/components/shared/data-display/_internal/STableSection.vue.d.ts +28 -0
  225. package/dist/src/components/shared/data-display/_internal/STableSection.vue.js +5 -0
  226. package/dist/src/components/shared/data-display/_internal/STableSection.vue_vue_type_script_setup_true_lang.js +77 -0
  227. package/dist/src/components/shared/data-display/_internal/richDocumentMedia.d.ts +6 -0
  228. package/dist/src/components/shared/data-display/_internal/richDocumentMedia.js +136 -0
  229. package/dist/src/components/shared/data-display/_internal/richDocumentMetadata.d.ts +21 -0
  230. package/dist/src/components/shared/data-display/_internal/richDocumentMetadata.js +39 -0
  231. package/dist/src/components/shared/data-display/_internal/richDocumentNavigation.d.ts +30 -0
  232. package/dist/src/components/shared/data-display/_internal/richDocumentNavigation.js +88 -0
  233. package/dist/src/components/shared/data-display/_internal/richDocumentTableValidation.d.ts +9 -0
  234. package/dist/src/components/shared/data-display/_internal/richDocumentTableValidation.js +240 -0
  235. package/dist/src/components/shared/data-display/_internal/richDocumentTraversal.d.ts +15 -0
  236. package/dist/src/components/shared/data-display/_internal/richDocumentTraversal.js +61 -0
  237. package/dist/src/components/shared/data-display/_internal/richDocumentTypes.d.ts +466 -0
  238. package/dist/src/components/shared/data-display/_internal/richDocumentValidation.d.ts +65 -0
  239. package/dist/src/components/shared/data-display/_internal/richDocumentValidation.js +192 -0
  240. package/dist/src/components/shared/data-display/_internal/tableFoundation.d.ts +27 -0
  241. package/dist/src/components/shared/data-display/_internal/tableFoundation.js +16 -0
  242. package/dist/src/components/shared/data-display/richDocument.d.ts +3 -220
  243. package/dist/src/components/shared/data-display/richDocument.js +607 -399
  244. package/dist/src/components/shared/data-display/scrollViewport.d.ts +2 -0
  245. package/dist/src/components/shared/database/SDataGrid.vue_vue_type_script_setup_true_lang.js +36 -36
  246. package/dist/src/components/shared/database/SSqlEditor.vue.d.ts +2 -2
  247. package/dist/src/components/shared/database/SSqlEditor.vue_vue_type_script_setup_true_lang.js +36 -36
  248. package/dist/src/components/shared/feedback/SAsyncState.vue.js +2 -2
  249. package/dist/src/components/shared/feedback/SAsyncState.vue_vue_type_script_setup_true_lang.js +70 -63
  250. package/dist/src/components/shared/navigation/SBottomNav.vue.d.ts +2 -2
  251. package/dist/src/components/shared/navigation/SBottomNav.vue.js +2 -2
  252. package/dist/src/components/shared/navigation/SBottomNav.vue_vue_type_script_setup_true_lang.js +140 -129
  253. package/dist/src/components/shared/navigation/SBreadcrumbs.vue.d.ts +2 -2
  254. package/dist/src/components/shared/navigation/STabList.vue.d.ts +1 -1
  255. package/dist/src/components/shared/navigation/STabPanel.vue.d.ts +2 -2
  256. package/dist/src/components/shared/navigation/SWizardSteps.vue_vue_type_script_setup_true_lang.js +16 -16
  257. package/dist/src/components/shared/persona/SPersonaProjectPicker.vue.d.ts +2 -2
  258. package/dist/src/composables/useDialogOverlay.d.ts +21 -2
  259. package/dist/src/composables/useDialogOverlay.js +275 -44
  260. package/dist/src/composables/useFloatingPosition.d.ts +20 -0
  261. package/dist/src/composables/useFloatingPosition.js +129 -52
  262. package/dist/src/internal/fieldSurface.d.ts +3 -0
  263. package/dist/src/internal/fieldSurface.js +3 -2
  264. package/dist/src/internal/flatTree.d.ts +8 -0
  265. package/dist/src/internal/flatTree.js +23 -0
  266. package/dist/src/internal/focusNavigation.d.ts +5 -0
  267. package/dist/src/internal/focusNavigation.js +29 -16
  268. package/dist/src/internal/inertLease.d.ts +8 -0
  269. package/dist/src/internal/inertLease.js +33 -0
  270. package/dist/src/internal/layerStack.d.ts +52 -0
  271. package/dist/src/internal/layerStack.js +343 -60
  272. package/dist/src/internal/linkTarget.d.ts +7 -1
  273. package/dist/src/internal/linkTarget.js +11 -7
  274. package/dist/src/internal/nativeFocus.d.ts +4 -0
  275. package/dist/src/internal/nativeFocus.js +12 -0
  276. package/dist/src/internal/overlayHost.d.ts +18 -0
  277. package/dist/src/internal/overlayHost.js +18 -0
  278. package/dist/src/internal/overlayPortal.d.ts +17 -0
  279. package/dist/src/internal/overlayPortal.js +23 -0
  280. package/dist/src/internal/ownedAttrs.d.ts +13 -3
  281. package/dist/src/internal/ownedAttrs.js +8 -1
  282. package/dist/src/internal/runtimeContract.d.ts +2 -0
  283. package/dist/src/internal/runtimeContract.js +10 -5
  284. package/dist/src/internal/semanticSizing.d.ts +2 -2
  285. package/dist/src/internal/semanticSizing.js +2 -1
  286. package/dist/src/internal/useMenuLayer.d.ts +8 -4
  287. package/dist/src/internal/useMenuLayer.js +78 -49
  288. package/dist/src/internal/viewportModality.d.ts +27 -0
  289. package/dist/src/internal/viewportModality.js +132 -0
  290. package/dist/tailwind.css +3 -0
  291. package/dist/typography.LICENSE.txt +94 -0
  292. package/dist/typography.js +5105 -0
  293. package/docs/getting-started.md +39 -0
  294. package/docs/link-download.md +114 -0
  295. package/docs/listbox.md +129 -0
  296. package/docs/overlay-lifecycle.md +195 -0
  297. package/docs/public-api.md +335 -6
  298. package/docs/resize.md +158 -0
  299. package/docs/rich-document.md +442 -25
  300. package/docs/scroll-viewport.md +30 -10
  301. package/docs/theming.md +42 -8
  302. package/package.json +12 -4
  303. package/src/components/shared/_internal/SDialogSurface.css +213 -36
  304. package/src/components/shared/_internal/SMenuLayer.css +4 -0
  305. package/src/components/shared/containers/SOverlayHost.css +14 -0
  306. package/src/components/shared/containers/SPopover.css +8 -2
  307. package/src/components/shared/controls/SButton.css +4 -3
  308. package/src/components/shared/controls/SCheckbox.css +19 -7
  309. package/src/components/shared/controls/SField.css +6 -0
  310. package/src/components/shared/controls/SListbox.css +17 -0
  311. package/src/components/shared/controls/SMenuSurface.css +18 -4
  312. package/src/components/shared/controls/STextarea.css +42 -3
  313. package/src/components/shared/data-display/SControlledToastViewport.css +2 -10
  314. package/src/components/shared/data-display/SProgressBar.css +79 -0
  315. package/src/components/shared/data-display/SRichDocument.css +1 -0
  316. package/src/components/shared/data-display/SScrollViewport.css +17 -1
  317. package/src/components/shared/data-display/SStatus.css +8 -25
  318. package/src/components/shared/data-display/STable.css +0 -113
  319. package/src/components/shared/data-display/STooltip.css +3 -0
  320. package/src/components/shared/data-display/_internal/SRichBlockNode.css +11 -7
  321. package/src/components/shared/data-display/_internal/SRichDisclosure.css +16 -0
  322. package/src/components/shared/data-display/_internal/SRichImage.css +37 -0
  323. package/src/components/shared/data-display/_internal/STableCell.css +55 -0
  324. package/src/components/shared/data-display/_internal/STableFrame.css +37 -0
  325. package/src/components/shared/data-display/_internal/STableRow.css +12 -0
  326. package/src/components/shared/feedback/SAsyncState.css +0 -4
  327. package/src/styles/style.css +9 -5
  328. package/src/styles/tokens.css +30 -0
  329. package/dist/assets/src/components/layout/SDockRegion.vue_vue_type_style_index_0_scoped_2932631d_lang.css +0 -1
  330. package/dist/assets/src/components/shared/_internal/SDialogSurface.css_vue_type_style_index_0_src_d1b65adf_scoped_d1b65adf_lang.css +0 -2
  331. package/dist/assets/src/components/shared/_internal/SMenuLayer.css_vue_type_style_index_0_src_4913bbe1_scoped_4913bbe1_lang.css +0 -1
  332. package/dist/assets/src/components/shared/containers/SDrawer.css_vue_type_style_index_0_src_091d7325_scoped_091d7325_lang.css +0 -2
  333. package/dist/assets/src/components/shared/containers/SModal.css_vue_type_style_index_0_src_0dc51b74_scoped_0dc51b74_lang.css +0 -2
  334. package/dist/assets/src/components/shared/containers/SPopover.css_vue_type_style_index_0_src_deded766_scoped_deded766_lang.css +0 -2
  335. package/dist/assets/src/components/shared/containers/SSidebarSection.css_vue_type_style_index_0_src_96f51ac6_scoped_96f51ac6_lang.css +0 -2
  336. package/dist/assets/src/components/shared/controls/SButton.css_vue_type_style_index_0_src_a5d8f7e0_scoped_a5d8f7e0_lang.css +0 -2
  337. package/dist/assets/src/components/shared/controls/SCheckbox.css_vue_type_style_index_0_src_b20b27dd_scoped_b20b27dd_lang.css +0 -2
  338. package/dist/assets/src/components/shared/controls/SCombobox.css_vue_type_style_index_0_src_e3b4f580_scoped_e3b4f580_lang.css +0 -2
  339. package/dist/assets/src/components/shared/controls/SContextMenu.css_vue_type_style_index_0_src_00c91d39_scoped_00c91d39_lang.css +0 -1
  340. package/dist/assets/src/components/shared/controls/SField.css_vue_type_style_index_0_src_60628f96_scoped_60628f96_lang.css +0 -2
  341. package/dist/assets/src/components/shared/controls/SListbox.css_vue_type_style_index_0_src_24db4abb_scoped_24db4abb_lang.css +0 -2
  342. package/dist/assets/src/components/shared/controls/SMenuSurface.css_vue_type_style_index_0_src_ddcc5fbb_scoped_ddcc5fbb_lang.css +0 -2
  343. package/dist/assets/src/components/shared/controls/SSelect.css_vue_type_style_index_0_src_441648c9_scoped_441648c9_lang.css +0 -2
  344. package/dist/assets/src/components/shared/data-display/SControlledToastViewport.css_vue_type_style_index_0_src_5864b6c6_scoped_5864b6c6_lang.css +0 -2
  345. package/dist/assets/src/components/shared/data-display/SProgressBar.css_vue_type_style_index_0_src_9308293a_scoped_9308293a_lang.css +0 -2
  346. package/dist/assets/src/components/shared/data-display/SRichDocument.css_vue_type_style_index_0_src_d1afafc5_scoped_d1afafc5_lang.css +0 -2
  347. package/dist/assets/src/components/shared/data-display/SScrollViewport.css_vue_type_style_index_0_src_e5d11342_scoped_e5d11342_lang.css +0 -2
  348. package/dist/assets/src/components/shared/data-display/STable.css_vue_type_style_index_0_src_9955d482_scoped_9955d482_lang.css +0 -2
  349. package/dist/assets/src/components/shared/data-display/SVirtualList.css_vue_type_style_index_0_src_cee8c247_scoped_cee8c247_lang.css +0 -2
  350. package/dist/assets/src/components/shared/data-display/_internal/SRichBlockNode.css_vue_type_style_index_0_src_195d5c06_scoped_195d5c06_lang.css +0 -2
  351. package/dist/assets/src/components/shared/data-display/_internal/SRichDisclosure.css_vue_type_style_index_0_src_fa94e2ff_scoped_fa94e2ff_lang.css +0 -2
  352. package/dist/assets/src/components/shared/feedback/SAsyncState.css_vue_type_style_index_0_src_bfc28903_scoped_bfc28903_lang.css +0 -2
  353. package/src/components/shared/containers/SDrawer.css +0 -69
  354. package/src/components/shared/containers/SModal.css +0 -27
package/README.md CHANGED
@@ -23,6 +23,80 @@ complete workbench interfaces.**
23
23
  - Только явные package exports: wildcard и private source imports отсутствуют.
24
24
  Explicit package exports only, with no wildcards or private source imports.
25
25
 
26
+ ### Полные option-каталоги / Complete option catalogs
27
+
28
+ `SListbox.virtualization` задаёт measured viewport над полным набором `options`:
29
+ `{ viewportHeight, estimatedItemHeight, overscan? }`. Keyboard navigation, groups,
30
+ clear, disabled и multiple selection работают по всему каталогу. Для external
31
+ focus owner событие `active-descendant-change` передаёт ID смонтированной option
32
+ в `STextarea.suggestions`. Полный контракт и примеры включены в пакет: `docs/listbox.md`.
33
+
34
+ `SListbox.virtualization` provides a measured viewport over the complete option
35
+ catalog. Keyboard navigation and selection use the full inventory; the
36
+ `active-descendant-change` event supplies a mounted option ID to an external
37
+ focus owner. The package includes the complete contract and examples in `docs/listbox.md`.
38
+
39
+ ### Измеряемый прогресс / Measured progress
40
+
41
+ `SProgressBar` использует один numerical/accessibility owner для `shape="linear"`
42
+ и `shape="circular"`. Линейная форма является default. Круговая форма имеет
43
+ размеры `xs/sm/md = 24/28/32 px` и требует явный `value` от 0 до 100 в
44
+ `mode="determinate"`. `showValue` выводит округлённое число в центре;
45
+ `aria-valuenow` сохраняет точное значение, включая дробную часть.
46
+ `valueText` передаёт доступное предметное описание, например tokens/limit.
47
+ Существующий scoped default slot форматирует только linear label и получает
48
+ точный `value`; circular label принадлежит владельцу и отклоняет default slot.
49
+
50
+ `accuracy="estimated"` требует `valueText` и показывает приблизительность.
51
+ `mode="unknown"` требует `valueText`, не принимает `value` и не сообщает
52
+ `aria-valuenow`. Эти состояния статичны. `mode="indeterminate"` обозначает
53
+ выполняющуюся операцию, не принимает `showValue` и учитывает reduced motion.
54
+ `severity` управляет semantic palette, а не выводится из процента автоматически.
55
+
56
+ ```vue
57
+ <SProgressBar
58
+ :accessibility="{ mode: 'label', label: 'Заполнение контекста' }"
59
+ shape="circular"
60
+ size="md"
61
+ :value="37.5"
62
+ value-text="37 500 из 100 000 токенов"
63
+ show-value
64
+ severity="info"
65
+ />
66
+ <SProgressBar
67
+ :accessibility="{ mode: 'label', label: 'Заполнение контекста' }"
68
+ shape="circular"
69
+ mode="unknown"
70
+ value-text="Размер контекста недоступен"
71
+ show-value
72
+ />
73
+ ```
74
+
75
+ Для действия показатель помещается в default slot `SButton` с
76
+ `iconOnly`, `shape="circle"`, `size="lg"`, `density="default"` и
77
+ `appearance="ghost"`: штатная
78
+ контрольная область равна **48×48 px**, то есть не меньше 44 px. Внутренний
79
+ показатель использует `accessibility.mode="decorative"`; действие, доступное
80
+ имя с точным значением и tooltip bindings принадлежат внешней кнопке.
81
+ Показатель не создаёт вложенный control или дополнительную остановку Tab.
82
+
83
+ `SProgressBar` shares numerical and accessibility ownership across linear and
84
+ circular shapes. Circular `xs/sm/md` sizes are 24/28/32 px. Determinate circular
85
+ progress requires an explicit value in 0–100; central display rounds the
86
+ percentage while `aria-valuenow` retains its exact precision. `valueText`
87
+ supplies a domain description such as tokens/limit. Estimated progress requires
88
+ `valueText` and a visible approximation marker. Explicit unknown progress
89
+ requires `valueText`, rejects `value`, omits `aria-valuenow`, and remains static.
90
+ Severity is consumer-selected rather than inferred from a percentage. The
91
+ existing scoped default slot formats linear labels and receives the exact
92
+ value. Circular labels are owner-controlled and reject a supplied default slot.
93
+
94
+ For an actionable indicator, place decorative progress in the default slot of
95
+ a circular `SButton` with `iconOnly`, `size="lg"`, default density, and
96
+ `appearance="ghost"`: its target is
97
+ 48×48 px, not exactly 44 px. The inner progress is decorative; the button owns
98
+ focus, the action, the accessible name, and tooltip bindings.
99
+
26
100
  ## Установка / Installation
27
101
 
28
102
  ```bash
@@ -45,6 +119,23 @@ npm install @pgcorp/ui-kit @vue/devtools-api vue pinia vue-router
45
119
  `vue`, `pinia`, `@vue/devtools-api`, and `vue-router` are peer dependencies. The consumer application
46
120
  owns their single runtime instances.
47
121
 
122
+ Tailwind/PostCSS принадлежат build-контуру приложения и объявляются его прямыми
123
+ dev dependencies. / Tailwind/PostCSS belong to the application's build pipeline
124
+ and must be declared as its direct dev dependencies.
125
+
126
+ ```bash
127
+ npm install -D tailwindcss@^4.3.3 @tailwindcss/postcss@^4.3.3 postcss@^8.5.28
128
+ ```
129
+
130
+ `postcss.config.mjs`:
131
+
132
+ ```js
133
+ export default { plugins: { '@tailwindcss/postcss': {} } }
134
+ ```
135
+
136
+ Контракт установки: [Tailwind CSS с PostCSS](https://tailwindcss.com/docs/installation/using-postcss).
137
+ / Setup contract: [Tailwind CSS with PostCSS](https://tailwindcss.com/docs/installation/using-postcss).
138
+
48
139
  ## Быстрый старт / Quick start
49
140
 
50
141
  Создайте корневой CSS entrypoint приложения. Интеграционный stylesheet подключает
@@ -177,6 +268,16 @@ link/resource/action effects возвращаются как typed intents. Link
177
268
  `current: true` выражает текущее назначение через `aria-current="page"`.
178
269
  Task lists, deletion, `keyboard`, sup/sub, disclosure и scoped footnotes имеют
179
270
  собственные serializable nodes; raw markup для этих семантик не требуется.
271
+ Типизированный semantic profile включает hard breaks, inline/picture media,
272
+ rich summary/header content, definitions, ruby и структурные таблицы с
273
+ header associations, spans и footer. `STable`, `SDataGrid` и rich tables
274
+ используют общих native table owners. Якоря и повторные сноски имеют локальный
275
+ scope, раскрывают целевую секцию и переводят фокус без изменения истории.
276
+ `heading.presentation: 'assistive'` сохраняет нативный уровень, содержимое,
277
+ scoped anchors и IDREFs, визуально скрывая сам heading вне normal flow.
278
+ Значение по умолчанию — `visible`; интерактивные потомки в assistive heading
279
+ отклоняются с точным node path. GFM producer сохраняет скрытый heading сносок
280
+ и его `describedBy` references, не передавая raw `class`.
180
281
 
181
282
  `SRichDocument` renders the closed, versioned `SRichDocumentV1` AST without raw
182
283
  HTML, VNodes, callbacks, or trust flags. External JSON is checked with
@@ -186,6 +287,26 @@ link/resource/action effects are emitted as typed intents. A link node with
186
287
  `current: true` exposes the current destination through `aria-current="page"`.
187
288
  Task lists, deletion, `keyboard`, sup/sub, disclosure, and scoped footnotes use
188
289
  dedicated serializable nodes; these semantics never require raw markup.
290
+ The typed semantic profile includes hard breaks, inline/picture media, rich
291
+ summary/header content, definitions, ruby, and structural tables with header
292
+ associations, spans, and a footer. `STable`, `SDataGrid`, and rich tables share
293
+ native table owners. Anchors and repeated footnotes are scoped locally, reveal
294
+ their target disclosure, and move focus without changing browser history.
295
+ `heading.presentation: 'assistive'` retains the native level, content, scoped
296
+ anchors, and IDREFs while placing the heading outside normal flow. The default
297
+ is `visible`; interactive descendants fail at their exact node path. A GFM
298
+ producer preserves its hidden footnote heading and description references
299
+ without passing raw classes.
300
+
301
+ `SCheckbox presentation="inline"` и `SField contentFlow="phrasing"` сохраняют
302
+ phrasing content model внутри текста. `SLink` предоставляет actual native
303
+ `getElement()`/`focus()` и semantic props `domId`, `language`, `direction`,
304
+ `ariaLabel`, `ariaLabelledby`, `ariaDescribedby`; IDREFs задаются непустыми DOM
305
+ идентификаторами через один ASCII-пробел без автоматического исправления ввода.
306
+ / `SCheckbox presentation="inline"` and `SField contentFlow="phrasing"` preserve
307
+ the phrasing content model inside text. `SLink` exposes the actual native
308
+ `getElement()`/`focus()` and the semantic props listed above; IDREFs are explicit
309
+ non-empty DOM identities separated by one ASCII space, without input repair.
189
310
 
190
311
  ```ts
191
312
  import SRichDocument from '@pgcorp/ui-kit/shared/data-display/SRichDocument.vue'
@@ -210,12 +331,32 @@ semantic block size, overscroll policy и root-only keyboard navigation.
210
331
  semantic offsets. Exposed API предоставляет `focus`, `scrollToBoundary` и
211
332
  `reveal`, но не открывает DOM owner.
212
333
 
334
+ `focusPolicy="always"` сохраняет именованную region; `focusPolicy="overflow"`
335
+ добавляет region и Tab stop только при переполнении разрешённой оси. Имя задаётся
336
+ ровно одним из `accessibleLabel` и `accessibleLabelledby`. `blockSize="content"`
337
+ сохраняет естественную высоту, `maxBlockSize="none|sm|md|lg"` ограничивает её
338
+ общей шкалой viewport. Таблицы `STable`, `SDataGrid` и rich-document используют
339
+ этот общий scroll owner: пустые и пассивные таблицы доступны клавиатуре при
340
+ переполнении, вложенные controls сохраняют собственную клавиатуру.
341
+ При исчезновении переполнения focused root сохраняет `tabindex="-1"` до blur;
342
+ он не добавляет остановку Tab и не переносит фокус.
343
+
213
344
  `SScrollViewport` owns a named scroll region, `x`/`y`/`both` axes, semantic
214
345
  block size, overscroll policy, and root-only keyboard navigation. The
215
346
  `scroll-state` event provides normalized physical and writing-mode-aware
216
347
  semantic offsets. Its exposed API provides `focus`, `scrollToBoundary`, and
217
348
  `reveal` without exposing the DOM owner.
218
349
 
350
+ `focusPolicy="always"` retains the named region; `focusPolicy="overflow"`
351
+ adds a region and Tab stop only when an enabled axis overflows. Exactly one
352
+ of `accessibleLabel` and `accessibleLabelledby` supplies its name.
353
+ `blockSize="content"` retains intrinsic height; `maxBlockSize="none|sm|md|lg"`
354
+ uses the shared viewport limit scale. `STable`, `SDataGrid`, and rich-document
355
+ tables compose this scroll owner: overflowing empty and passive tables are
356
+ keyboard reachable, while nested controls retain their own keyboard behavior.
357
+ When overflow disappears, a focused root retains `tabindex="-1"` until blur;
358
+ it adds no Tab stop and does not move focus.
359
+
219
360
  ```ts
220
361
  import SScrollViewport from '@pgcorp/ui-kit/shared/data-display/SScrollViewport.vue'
221
362
  import type {
@@ -521,7 +662,179 @@ reserved for runtime catalog values and intentionally includes the complete
521
662
  registry.
522
663
 
523
664
  ```ts
524
- import { Bell, Cable, GitCompare, PanelLeftOpen } from '@pgcorp/ui-kit/icons'
665
+ import {
666
+ ArrowUpRight, Bell, Cable, CalendarDays, Disc, GitCompare, GitFork,
667
+ ChevronLeft, HardDrive, PanelLeftOpen, Paperclip, Pause, Radio, RotateCw, Usb, Volume2, Zap, ZoomIn, ZoomOut,
668
+ } from '@pgcorp/ui-kit/icons'
669
+ ```
670
+
671
+ `HardDrive`, `Usb` и `Disc` обозначают локальный накопитель, USB-подключение
672
+ и оптический диск; `CalendarDays` — дату, `ArrowUpRight` — переход или открытие.
673
+ `Paperclip` обозначает прикрепление файла, `GitFork` — разветвление разговора;
674
+ `ZoomIn`/`ZoomOut` — изменение масштаба изображения, `RotateCw` — поворот по
675
+ часовой стрелке, `Volume2` — аудио. Поворот против часовой стрелки представлен
676
+ отдельным `RotateCcw`, а не alias для `RotateCw`.
677
+ `Radio` обозначает сетевое вещание или фоновое уведомление, не radio input.
678
+ `Pause` обозначает состояние паузы задачи; `ChevronLeft` — переход влево.
679
+ `Zap` обозначает молнию и подходит для роли быстрой модели. Это primary-only
680
+ силуэт: duotone сохраняет одну цветовую роль, без дополнительного accent.
681
+ Все используют общий icon contract: `iconSetMode` (`classic`, `sputnig`),
682
+ `colorMode` (`auto`, `duotone`, `monochrome`), тему и tree-shakeable ESM exports.
683
+ Внутри control иконка передаётся через его icon slot; размер и состояние
684
+ задаёт control owner.
685
+
686
+ `HardDrive`, `Usb`, and `Disc` represent a local drive, a USB connection, and
687
+ an optical disc; `CalendarDays` represents a date, and `ArrowUpRight` represents
688
+ navigation or opening. All share the icon contract: `iconSetMode` (`classic`, `sputnig`),
689
+ `colorMode` (`auto`, `duotone`, `monochrome`), theme support, and tree-shakeable ESM
690
+ exports. Pass an icon through a control's icon slot; the control owner defines
691
+ its size and state.
692
+
693
+ `Paperclip` represents file attachment and `GitFork` conversation branching.
694
+ `ZoomIn`/`ZoomOut` represent image zoom, `RotateCw` clockwise rotation, and
695
+ `Volume2` audio. Counterclockwise rotation has a distinct `RotateCcw` export;
696
+ the two rotation actions are not aliases.
697
+ `Radio` represents network broadcast or a background notification, not a radio input.
698
+ `Pause` represents a paused task; `ChevronLeft` represents leftward navigation.
699
+ `Zap` represents a lightning bolt and can identify the fast-model role. Its
700
+ primary-only silhouette retains one color role in duotone, without an accent shape.
701
+
702
+ ```vue
703
+ <SButton label="Выбрать локальный накопитель">
704
+ <template #leading-icon><HardDrive /></template>
705
+ </SButton>
706
+ ```
707
+
708
+ ### Скачивание через ссылку / Native link downloads
709
+
710
+ `SButton` и `SLink` поддерживают typed `download?: string | boolean` только в
711
+ `href`-режиме. Filename передаётся native anchor буквально; `true`/`""` оставляют
712
+ выбор имени браузеру, `false` не создаёт download attribute. Router `to` и action
713
+ button не принимают этот prop. Consumer владеет полным Blob и object URL;
714
+ ограниченный preview не становится источником скачивания. `SLink.disabled` и
715
+ `SButton.disabled/loading` блокируют activation и удаляют `href`/`download`.
716
+
717
+ `SButton` and `SLink` support typed `download?: string | boolean` in `href` mode
718
+ only. The filename is passed verbatim to the native anchor; `true`/`""` let the
719
+ browser choose it, and `false` omits the attribute. Router `to` and action buttons
720
+ reject this prop. The consumer owns the complete Blob and its object URL; a
721
+ limited preview is not the download source. `SLink.disabled` and
722
+ `SButton.disabled/loading` block activation and remove `href`/`download`.
723
+
724
+ Контракт, Blob lifecycle и ограничения браузера включены в пакет: `docs/link-download.md`.
725
+ The package includes the contract, Blob lifecycle, and browser limitations in `docs/link-download.md`.
726
+
727
+ ### Идентичность динамических вкладок / Dynamic tab identity
728
+
729
+ В managed-композиции `STabs` значение `modelValue`, `STab.name` и
730
+ `STabPanel.name` используют один стабильный ID сущности. Vue `key` также
731
+ основан на этом ID. Добавление элемента и выбор его ID допускаются в одной
732
+ reactive update, включая вставку в начало массива. Порядковый номер и подпись
733
+ вкладки являются отображением, а не идентичностью.
734
+
735
+ Для E2E consumer задаёт собственные `data-*` маркеры по ID и проверяет роль
736
+ `tab`, `aria-selected`, связь `aria-controls` с ID панели и обратную
737
+ `aria-labelledby`. Внутренний формат DOM ID, `nth()` и индекс в подписи не
738
+ являются selector-контрактом. Сохранённые панели сохраняют свой input при
739
+ переключении; ручная DOM-активация и remount для выбора не требуются.
740
+
741
+ In managed `STabs`, `modelValue`, `STab.name`, `STabPanel.name`, and Vue `key`
742
+ use the same stable entity ID. Adding a keyed item and selecting its ID can
743
+ occur in one reactive update, including insertion at the beginning. An ordinal
744
+ or label is presentation, not identity. E2E tests use consumer-owned `data-*`
745
+ IDs, the `tab` role, `aria-selected`, and the matching `aria-controls` /
746
+ `aria-labelledby` relationship. Internal DOM ID formats, `nth()`, and label
747
+ indices are not selector contracts. Retained panels preserve their input;
748
+ selection does not require manual DOM activation or remounting.
749
+
750
+ ### Подсказка на интерактивной поверхности / Tooltip on an interactive surface
751
+
752
+ `SInteractiveSurface` принимает полный combined `trigger` от `STooltip` через
753
+ prop `tooltipTrigger`. Binding относится к primary activation owner: кнопке
754
+ для `surface.mode="action"` или ссылке для `surface.mode="link"`.
755
+ Link surface принимает ровно один target: `href` либо Vue Router `to`.
756
+ Для `to` приложение подключает Vue Router. `accessibleLabel` обязателен
757
+ в обоих интерактивных режимах; static surface не принимает tooltip binding.
758
+ Подсказка открывается по pointer/focus и закрывается через Escape.
759
+ Дополнительные controls передаются в `#actions` и сохраняют собственные
760
+ focus и activation независимо от primary owner.
761
+
762
+ `showDelay` задаёт задержку открытия (120 мс), `hideDelay` — закрытия после
763
+ выхода указателя и фокуса (80 мс). Указатель может переходить с target на
764
+ пассивную панель подсказки: она остаётся видимой, не получает focus и не
765
+ добавляет Tab stop. Escape закрывает открытую панель и отменяет pending
766
+ открытие; pending-подсказка не забирает событие у меню или диалога.
767
+ Blur окна, скрытие документа, disabled и освобождение target отменяют
768
+ таймеры и слушатели. Новый вход указателя или получение фокуса открывает
769
+ подсказку по действующему `showDelay`.
770
+ Canonical focus owner допускает binding внутри сохранённой скрытой секции.
771
+ Скрытый или недоступный owner не активирует подсказку. Скрытие ancestor
772
+ отменяет pending-таймеры, сразу исключает открытую панель из взаимодействия
773
+ и снимает description. Reveal сохраняет owner; новый pointer/focus вход
774
+ открывает подсказку без дополнительного Tab stop.
775
+
776
+ Пассивная tooltip-поверхность передаёт полный `text`/`title`/`description`,
777
+ `details` и `sections` как доступное описание focus owner через
778
+ `aria-describedby`; внешние `triggerDescribedBy` сохраняются. Визуальный
779
+ portal имеет `aria-hidden="true"`, исключая повторное самостоятельное чтение
780
+ того же текста вне landmark. Пассивная поверхность прозрачна для указателя:
781
+ нажатие достигает расположенного под ней действия, а наведение на видимый
782
+ контент сохраняет текущую подсказку. Имя и роль owner не изменяются. Подсказка не
783
+ содержит интерактивных действий; для popup с controls используется другой
784
+ overlay-компонент. Описание связывается при показе панели, включая открытие
785
+ по возвращённому фокусу после закрытия dialog.
786
+
787
+ The passive tooltip surface exposes all text, title, description, details,
788
+ and sections as the focus owner's accessible description through
789
+ `aria-describedby`, preserving external `triggerDescribedBy` references.
790
+ The visual portal has `aria-hidden="true"` to avoid duplicating that description
791
+ as independent content outside a landmark. The passive surface is pointer-transparent:
792
+ native activation reaches the underlying action while hovering the displayed content
793
+ keeps its current tooltip lease open. The owner's name and role remain
794
+ unchanged. A tooltip contains no interactive actions; use another overlay
795
+ component for a popup with controls. The description is associated when the
796
+ surface is shown, including focus restored after a dialog closes.
797
+
798
+ `SInteractiveSurface` accepts the complete combined `STooltip` trigger through
799
+ the `tooltipTrigger` prop. The binding belongs to the primary activation owner:
800
+ a button for `surface.mode="action"` or a link for `surface.mode="link"`.
801
+ A link surface accepts exactly one target: `href` or Vue Router `to`.
802
+ The application installs Vue Router when using `to`. `accessibleLabel` is
803
+ required in both interactive modes; a static surface rejects a tooltip binding.
804
+ The tooltip opens on pointer/focus and closes with Escape. Additional controls
805
+ use `#actions` and retain independent focus and activation.
806
+
807
+ `showDelay` controls the opening delay (120ms); `hideDelay` controls closing
808
+ after pointer hover and focus leave (80ms). The pointer can move from the
809
+ target onto the passive tooltip panel: it remains visible, receives no focus,
810
+ and adds no Tab stop. Escape closes the visible panel or cancels a pending
811
+ opening; a pending tooltip does not consume the event from a menu or dialog.
812
+ Window blur, a hidden document, disabled state, and released target identity
813
+ cancel timers and listeners. Fresh pointer entry or acquired focus opens the
814
+ tooltip according to its current `showDelay`.
815
+ A canonical focus owner can bind inside a retained hidden section. A hidden
816
+ or unavailable owner cannot activate the tooltip. Hiding its ancestor
817
+ cancels pending timers, immediately retires the open panel from interaction,
818
+ and removes its description. Revealing the section retains the owner;
819
+ fresh pointer/focus entry opens the tooltip without another Tab stop.
820
+
821
+ ```vue
822
+ <STooltip text="/workspace/repository" v-slot="{ trigger }">
823
+ <SInteractiveSurface
824
+ :surface="{
825
+ mode: 'link',
826
+ to: '/projects/repository',
827
+ accessibleLabel: 'Открыть проект',
828
+ }"
829
+ :tooltip-trigger="trigger"
830
+ actions-layout="responsive"
831
+ >
832
+ Проект Repository
833
+ <template #actions>
834
+ <SButton label="Параметры проекта" size="sm" />
835
+ </template>
836
+ </SInteractiveSurface>
837
+ </STooltip>
525
838
  ```
526
839
 
527
840
  ### Подсказка на части действия / Tooltip for part of an action
@@ -567,6 +880,69 @@ the multiline textbox with a consumer-owned popup without private attributes.
567
880
  The textarea keeps its native role; `role="combobox"` is not assigned to this
568
881
  HTML element. Pixel bounds belong to the auto-resize contract.
569
882
 
883
+ Слоты `empty-content` и `helper-content` располагаются обычным потоком внутри
884
+ единой field surface. `empty-content` доступен при пустом тексте вне IME
885
+ composition; native input скрывает его до подтверждения `v-model` родителем.
886
+ `helper-content` не зависит от значения. Оба слота получают
887
+ `STextareaContentContext`: `empty`, `disabled`, `readonly`, `invalid`, `composing`,
888
+ `hasMultipleVisualLines` и `focus()`. Действия в слотах создаются через UI-kit controls; их доступность
889
+ задаётся через `disabled`/`readonly` контекста. `focus()` возвращает фокус
890
+ native textarea без изменения selection. `helpText` и `errorMessage` сохраняют
891
+ свой supporting-text contract снаружи surface.
892
+
893
+ При наличии content slots `minHeight`/`maxHeight` ограничивают всю surface:
894
+ textarea, supporting regions, интервалы и внутренние поля. Редактор сохраняет
895
+ место минимум для одной строки; длинный helper прокручивается в своей in-flow
896
+ области, а его keyboard actions доступны Tab. Конфигурация, в которой
897
+ `maxHeight` не вмещает editable line и обязательный surface chrome, отклоняется
898
+ с `RangeError`. `rows` задаёт исходную высоту редактора, `maxRows` ограничивает
899
+ редактируемые строки с учётом присутствующего supporting content. Content slots
900
+ не требуют абсолютного позиционирования, consumer padding или дополнительного
901
+ resize handler. Изменение естественной высоты slot-контента автоматически
902
+ увеличивает или уменьшает surface в заданных пределах; самостоятельно
903
+ обновляемые дочерние компоненты наблюдаются тем же resize owner.
904
+
905
+ The `empty-content` and `helper-content` slots participate in normal flow inside
906
+ the shared field surface. Empty content is visible only for an empty editor
907
+ outside IME composition; native input hides it before a delayed parent model
908
+ acknowledgement. Helper content is independent of the value. Both slots receive
909
+ `STextareaContentContext` with editing-state flags and the native `focus()`
910
+ method. Pixel bounds include the whole surface and preserve at least one
911
+ editable line; oversized supporting content has its own bounded scroll region.
912
+ Intrinsic slot-content changes automatically grow or shrink the surface within
913
+ its bounds, including independently updated child components. Use UI-kit
914
+ controls for slot actions, without consumer overlays, padding or resize calls.
915
+
916
+ `hasMultipleVisualLines` описывает native текст с учётом переносов по текущей
917
+ ширине: `false` — одна визуальная строка, `true` — несколько. `null` означает
918
+ недоступную геометрию: SSR, скрытый editor или нулевую ширину. Пустое значение
919
+ при доступной геометрии занимает одну строку; placeholder не определяет это
920
+ состояние. Измерение обновляется для fixed и auto-resize полей, native ввода до
921
+ подтверждения controlled модели, изменений ширины и типографики. Consumer
922
+ задаёт политику показа helper через slot context, без доступа к private DOM:
923
+
924
+ `hasMultipleVisualLines` describes native text wrapping at the current editor
925
+ width: `false` is one visual line, `true` is multiple lines, and `null` denotes
926
+ unavailable layout during SSR, hidden rendering or zero width. An empty value
927
+ has one editable line once layout is available; placeholder text does not
928
+ determine this state. Fixed and auto-resizing editors update the state for
929
+ native input, delayed model acknowledgement, width and typography changes.
930
+ Helper visibility is an explicit consumer policy expressed through slot state:
931
+
932
+ ```vue
933
+ <STextarea v-model="message" label="Сообщение" :rows="1" auto-resize :min-height="64" :max-height="240">
934
+ <template #helper-content="{ hasMultipleVisualLines, composing, disabled, focus }">
935
+ <SButton
936
+ v-if="hasMultipleVisualLines === false && !composing && !disabled"
937
+ label="Справка по вводу"
938
+ size="sm"
939
+ appearance="text"
940
+ @click="focus()"
941
+ />
942
+ </template>
943
+ </STextarea>
944
+ ```
945
+
570
946
  `minLength` и `maxLength` используют тот же строгий native contract, что и
571
947
  `SInputText`: принимают неотрицательные safe integers и требуют
572
948
  `minLength <= maxLength`. Ограничение применяется к пользовательскому вводу;
@@ -597,7 +973,128 @@ correction.
597
973
  @focus="handleFocus"
598
974
  @blur="handleBlur"
599
975
  @paste="handlePaste"
600
- />
976
+ >
977
+ <template #empty-content="{ disabled, readonly, focus }">
978
+ <SButton
979
+ label="Прикрепить файл"
980
+ size="sm"
981
+ appearance="text"
982
+ :disabled="disabled || readonly"
983
+ @click="selectAttachment(); focus()"
984
+ />
985
+ </template>
986
+ <template #helper-content="{ focus }">
987
+ <SButton label="Справка по вводу" size="sm" appearance="text" @click="openInputHelp(); focus()" />
988
+ </template>
989
+ </STextarea>
990
+ ```
991
+
992
+ Контекстное меню native textarea подключается через
993
+ `SContextMenu` slot `textInputTriggerProps`. Он содержит `aria-haspopup="menu"`,
994
+ `aria-controls` смонтированного открытого меню и `onKeydown` для ContextMenu/Shift+F10. Фокус, ввод и
995
+ selection принадлежат `STextarea`; меню владеет pointer/keyboard activation,
996
+ позиционированием, Escape и возвратом фокуса. ArrowUp/Down сохраняют native
997
+ редактирование. IME composition и отменённое keydown не открывают меню.
998
+ Для действий-кнопок используется отдельный `triggerProps` с
999
+ `aria-expanded`: [WAI-ARIA textbox](https://www.w3.org/TR/wai-aria-1.2/#textbox)
1000
+ этого состояния не поддерживает. Raw button-oriented `triggerProps` не
1001
+ передаётся в textarea, её HTML-роль не заменяется.
1002
+
1003
+ `triggerProps` открывает контекстное меню через ContextMenu и Shift+F10;
1004
+ при `trigger="click"` или `"both"` также доступны ArrowDown/ArrowUp.
1005
+ Событие компонента `before-open` синхронно передаёт исходный
1006
+ `SContextMenuBeforeOpenEvent = MouseEvent | KeyboardEvent` до перехвата native
1007
+ действия, монтажа меню и перемещения фокуса. Обработчик сохраняет точный текст
1008
+ выделения и обновляет реактивный `items`. `event.preventDefault()` отменяет
1009
+ открытие. Меню применяет текущий список после Vue commit; consumer не вызывает
1010
+ `nextTick`, таймер или повторное событие. Отменённое событие, `enabled=false`
1011
+ и IME composition не запускают подготовку и не открывают меню. Неактивная
1012
+ граница сохраняет native propagation.
1013
+
1014
+ Подготовленный запрос принадлежит конкретной boundary и вызывающему элементу.
1015
+ Повторная активация заменяет его; отключение, удаление вызывающего элемента
1016
+ или boundary, unmount и Escape во время подготовки отменяют его без позднего
1017
+ открытия и захвата фокуса. Вложенные активные boundaries обрабатывают событие
1018
+ только в ближайшем владельце. Позиционирование, выбор действия, Escape и
1019
+ возврат фокуса принадлежат общему menu owner.
1020
+
1021
+ Полный `triggerProps` предназначен для кнопки-триггера. Пассивная область
1022
+ `role="group"` получает только поддерживаемую её семантикой `aria-controls`.
1023
+ Этот атрибут присутствует только при открытом смонтированном меню;
1024
+ `aria-expanded` и `aria-haspopup` кнопки группе не передаются. Boundary кита
1025
+ делегирует ContextMenu/Shift+F10 от реально сфокусированного потомка, сохраняя
1026
+ его владельцем фокуса. Обычные клавиши редактирования не перехватываются.
1027
+ Consumer не добавляет группе native contextmenu/keydown handlers и не меняет
1028
+ роль ради открытия меню.
1029
+
1030
+ ```vue
1031
+ <SContextMenu
1032
+ :items="selectionActions"
1033
+ boundary-layout="contents"
1034
+ v-slot="{ triggerProps }"
1035
+ @before-open="captureSelection"
1036
+ >
1037
+ <div
1038
+ role="group"
1039
+ aria-label="Действия с выделенным текстом"
1040
+ tabindex="0"
1041
+ :aria-controls="triggerProps['aria-controls']"
1042
+ >
1043
+ <slot />
1044
+ </div>
1045
+ </SContextMenu>
1046
+ ```
1047
+
1048
+ ```ts
1049
+ import type { SContextMenuBeforeOpenEvent } from '@pgcorp/ui-kit/shared/controls/SContextMenu.vue'
1050
+
1051
+ function captureSelection(event: SContextMenuBeforeOpenEvent): void {
1052
+ const selection = window.getSelection()
1053
+ if (!selection) throw new Error('Native selection is unavailable')
1054
+ selectedText.value = selection.toString()
1055
+ if (!selectedText.value) event.preventDefault()
1056
+ }
1057
+ ```
1058
+
1059
+ The synchronous `before-open` component event receives the original admitted
1060
+ `MouseEvent | KeyboardEvent` before interception, mounting or menu focus.
1061
+ Update reactive items in that handler; `preventDefault()` cancels opening.
1062
+ The kit commits current items and owns initial focus, dismissal and request
1063
+ cleanup. Disabled, already-cancelled and composing events do not prepare a menu.
1064
+ Passive groups bind only the optional mounted-menu `aria-controls` relationship;
1065
+ the kit boundary delegates ContextMenu/Shift+F10 from the actual focused
1066
+ descendant. No native consumer listeners, fabricated button role or timer are
1067
+ required. Full `triggerProps` belongs to a button; `textInputTriggerProps`
1068
+ preserves native textbox editing and selection semantics.
1069
+
1070
+ При сочетании menu и suggestions `suggestions.active` явно выбирает участие
1071
+ suggestion popup; default — `true`. Активные suggestions задают
1072
+ `aria-haspopup`, `aria-autocomplete` и `aria-activedescendant`. При
1073
+ `active=false` `activeDescendant` запрещён, `aria-haspopup` принадлежит
1074
+ внешнему context-menu owner. `aria-controls` объединяет проверенные canonical
1075
+ ID обоих owners без потери связи. Native `aria-controls` принимает один DOM ID
1076
+ внешнего popup; `suggestions.controls` — один DOM ID suggestion popup.
1077
+ Кит не определяет активность по DOM, не меняет ID и не создаёт focusable wrapper.
1078
+
1079
+ The `textInputTriggerProps` slot binds a context menu to the native textarea
1080
+ without button-only `aria-expanded` or arrow-key menu activation. ContextMenu
1081
+ and Shift+F10 use the shared menu owner; Escape restores the editing owner's
1082
+ focus and selection. `suggestions.active` explicitly selects the suggestion
1083
+ popup's ARIA participation, while validated control references are merged.
1084
+
1085
+ ```vue
1086
+ <SContextMenu :items="editingActions" v-slot="{ textInputTriggerProps }">
1087
+ <STextarea
1088
+ v-model="message"
1089
+ v-bind="textInputTriggerProps"
1090
+ label="Сообщение"
1091
+ :suggestions="{
1092
+ controls: 'mention-listbox',
1093
+ active: suggestionsVisible,
1094
+ ...(suggestionsVisible && activeMentionId ? { activeDescendant: activeMentionId } : {}),
1095
+ }"
1096
+ />
1097
+ </SContextMenu>
601
1098
  ```
602
1099
 
603
1100
  ```ts
@@ -614,6 +1111,8 @@ function handleFocus(event: FocusEvent): void {
614
1111
  }
615
1112
 
616
1113
  composer.value?.setSelection({ start, end, direction: 'forward' })
1114
+ composer.value?.selectAll()
1115
+ composer.value?.selectAll(false)
617
1116
  composer.value?.replaceSelection('@file README.md')
618
1117
  ```
619
1118
 
@@ -629,6 +1128,26 @@ IME composition fails with an explicit diagnostic. The `selection-change`,
629
1128
  `compositionstart`, `compositionupdate`, `compositionend`, and `state-change`
630
1129
  events synchronize a popup without reading internal DOM.
631
1130
 
1131
+ `selectAll(focusOwner?: boolean): void` выделяет весь текущий native API value
1132
+ вперёд через общий selection owner. По умолчанию запрашивается focus;
1133
+ `false` сохраняет внешний focus. Readonly-текст доступен для выделения;
1134
+ disabled и detached элементы соблюдают native eligibility фокуса.
1135
+ Метод использует длину текущего `textarea.value`, включая ввод до подтверждения
1136
+ controlled model, и не изменяет исходные CRLF/Unicode bytes, model или input
1137
+ history. HTML API value исключает CR; consumer не переписывает source и не
1138
+ считает native offsets через `source.length`. Unmounted/disposed owner и
1139
+ неboolean focus policy дают явную ошибку.
1140
+
1141
+ `selectAll(focusOwner?: boolean): void` selects the complete current native
1142
+ API value forward through the shared selection owner. It requests focus by
1143
+ default; `false` preserves external focus. Readonly text remains selectable;
1144
+ disabled and detached elements follow native focus eligibility.
1145
+ The method uses the current `textarea.value.length`, including edits awaiting
1146
+ controlled-model acknowledgement, and does not change the source CRLF/Unicode
1147
+ bytes, model, or input history. The HTML API value excludes CR; consumers do not
1148
+ rewrite the source or calculate native offsets from `source.length`.
1149
+ An unmounted/disposed owner or non-boolean focus policy throws an explicit error.
1150
+
632
1151
  ### Карточки и строки выбора / Choice cards and rows
633
1152
 
634
1153
  `SChoiceCards` использует `appearance="cards"` для крупных плиток и
@@ -672,6 +1191,20 @@ focus, and keyboard contracts remain unchanged.
672
1191
  </SButton>
673
1192
  ```
674
1193
 
1194
+ ### Доступность действий / Action availability
1195
+
1196
+ `SButton.disabled` и `loading` исключают native activation и Tab focus;
1197
+ недоступная `href`-кнопка не содержит navigation target. При разрешении
1198
+ действия foreground и background применяются одной контрастной парой без
1199
+ интерполяции цветов. Действие доступно сразу, без ожидания декоративной
1200
+ анимации; transition тени и transform не меняет читаемость подписи.
1201
+
1202
+ `SButton.disabled` and `loading` prevent native activation and Tab focus;
1203
+ an unavailable `href` button has no navigation target. Enabling an action
1204
+ applies its foreground/background contrast pair atomically, without color
1205
+ interpolation. The action is immediately available, independently of
1206
+ decorative shadow or transform transitions.
1207
+
675
1208
  ### Controlled checkbox и switch / Controlled checkbox and switch
676
1209
 
677
1210
  `SCheckbox` и `SSwitch` всегда отражают authoritative `modelValue` в native
@@ -688,6 +1221,22 @@ supports asynchronous persistence or rejection without rekeying, manual DOM
688
1221
  resets, or an optimistic model. The consumer updates `modelValue` normally
689
1222
  after confirmation.
690
1223
 
1224
+ У `SCheckbox` единственный focus owner — native checkbox. Прозрачный input
1225
+ покрывает индикатор и его pointer target; нажатие на индикатор или связанную
1226
+ подпись выполняет одно действие. Обычный field использует semantic hitbox
1227
+ `--s-control-hitbox-2xs`, inline-представление — размер индикатора, согласованный
1228
+ со строкой документа. Tab переводит фокус на input, Space переключает его,
1229
+ focus-visible отображается на индикаторе. `disabled` и `readonly` не эмитят
1230
+ изменение или click; `indeterminate` показывает частичный выбор через минус.
1231
+
1232
+ `SCheckbox` has one focus owner: the native checkbox. Its transparent input
1233
+ covers the indicator and its pointer target; activating the indicator or its
1234
+ associated label performs one action. Field presentation uses the semantic
1235
+ `--s-control-hitbox-2xs` target; inline presentation uses the indicator size
1236
+ aligned with document text. Tab focuses the input, Space toggles it, and the
1237
+ indicator renders focus-visible. `disabled` and `readonly` emit neither change
1238
+ intent nor click; `indeterminate` represents partial selection with a minus.
1239
+
691
1240
  ```vue
692
1241
  <SSwitch
693
1242
  :model-value="autoPublish"
@@ -721,17 +1270,145 @@ contract applies only to textual types: `text`, `search`, `password`, `email`,
721
1270
 
722
1271
  ### Drawer placement
723
1272
 
724
- `SDrawer` использует `placement="right"` по умолчанию. Нижняя панель задаётся
725
- `placement="bottom"`; semantic sizes соответствуют 50, 70 и 90 процентам
726
- dynamic viewport height. Body остаётся единственным scroll owner, а overlay,
727
- focus trap/restore, Escape, backdrop и nested layer stack совпадают с боковой
728
- панелью.
1273
+ `SDrawer.placement` принимает `left | right | bottom`, по умолчанию — `right`.
1274
+ `left` и `right` обозначают физическую сторону независимо от направления текста.
1275
+ Боковые панели используют общую шкалу `sm/md/lg`: максимальная ширина
1276
+ `30/36/44rem`, ограниченная viewport. При `scope="viewport"` нижняя панель
1277
+ `placement="bottom"` занимает `50/70/90` процентов dynamic viewport height.
1278
+ `mobileFullScreen` задаёт полноширинную боковую viewport-панель на узком экране;
1279
+ размещение, header/body/footer и доступность действий сохраняются.
1280
+ При `scrollBehavior="body"` body — единственный scroll owner. Все размещения
1281
+ используют общие viewport overlay, focus trap/restore, Escape, backdrop и nested
1282
+ layer stack.
1283
+
1284
+ Viewport `SModal` и `SDrawer` используют единственный нативный `dialog` в
1285
+ modal top layer. Фон, включая SVG, MathML и shadow-композиции, исключён из
1286
+ pointer/focus interaction и accessibility tree. Дочерние select, меню, popover
1287
+ и tooltip используют принадлежащий этому dialog portal вне transform и
1288
+ scroll clipping. Вложенный viewport dialog изолирует родителя до закрытия.
1289
+ Native blocking освобождается синхронно при retirement; общая focus lease
1290
+ управляет возвратом, независимо от завершения visual leave.
1291
+
1292
+ `SDrawer.placement` accepts `left | right | bottom`, defaulting to `right`.
1293
+ `left` and `right` are physical sides independent of text direction. Side
1294
+ drawers share the `sm/md/lg` scale: viewport-bounded maximum widths of
1295
+ `30/36/44rem`. With `scope="viewport"`, a `placement="bottom"` sheet occupies
1296
+ `50/70/90` percent of the dynamic viewport height. `mobileFullScreen` provides
1297
+ a full-width side viewport drawer on a narrow screen while preserving its
1298
+ placement, header/body/footer and reachable actions. With
1299
+ `scrollBehavior="body"`, the body is the sole scroll owner. All placements
1300
+ share viewport overlay, focus trap/restore, Escape, backdrop and the nested
1301
+ layer stack.
1302
+
1303
+ Viewport `SModal` and `SDrawer` use one native `dialog` in the modal top layer.
1304
+ Background content, including SVG, MathML, and shadow compositions, is excluded
1305
+ from pointer/focus interaction and the accessibility tree. Descendant selects,
1306
+ menus, popovers, and tooltips use that dialog's portal outside transforms and
1307
+ scroll clipping. A nested viewport dialog isolates its parent until closed.
1308
+ Retirement releases native blocking synchronously; the shared focus lease
1309
+ controls restoration independently of visual leave completion.
1310
+
1311
+ Для обновления на `0.15` готовые `SModal`/`SDrawer` сохраняют публичные props,
1312
+ slots и events. Собственный viewport leaf на экспортируемом `useDialogOverlay`
1313
+ требует миграции: `setPanelElement` получает native `HTMLDialogElement`, а
1314
+ `setPortalElement` — его непосредственный дочерний HTMLElement portal.
1315
+ Разметка, стили принадлежащих leaf surfaces и controlled close описаны в
1316
+ [`docs/overlay-lifecycle.md`](https://github.com/pglyanenko/sputnig/blob/master/packages/ui-kit/docs/overlay-lifecycle.md),
1317
+ включая карту binding исполняемой story `SModal.NativeOwnerContract`.
1318
+
1319
+ For an upgrade to `0.15`, the ready-made `SModal`/`SDrawer` preserve their public
1320
+ props, slots, and events. A custom viewport leaf using the exported
1321
+ `useDialogOverlay` requires migration: `setPanelElement` receives a native
1322
+ `HTMLDialogElement`, and `setPortalElement` receives its direct-child HTMLElement
1323
+ portal. The owned markup, styles, and controlled close contract are documented in
1324
+ [`docs/overlay-lifecycle.md`](https://github.com/pglyanenko/sputnig/blob/master/packages/ui-kit/docs/overlay-lifecycle.md),
1325
+ including the binding map of the executable `SModal.NativeOwnerContract` story.
1326
+
1327
+ `scope="contained"` требует ближайший `SOverlayHost`. Его default-слот содержит
1328
+ основную историю, `#overlay` — панель. Размеры `sm/md/lg` означают 50/70/90%
1329
+ доступной области по оси `placement`; `extent` принимает конечный процент больше
1330
+ 0 и не больше 100. Для `left/right` это ширина host, для `bottom` — высота.
1331
+ `extent` применим только к contained-режиму. Размеры host
1332
+ принадлежат композиции страницы; размер и оформление панели принадлежат киту.
1333
+ `mobileFullScreen` не переводит contained-панель за границы host.
1334
+ `scope` меняется только при `open=false`; переход между владельцами не переносит
1335
+ открытый overlay lifetime.
1336
+
1337
+ Contained drawer — немодальный `dialog`: composer и terminal вне host остаются
1338
+ доступны, global body lock и собственный Tab trap отсутствуют. Основное
1339
+ содержимое host имеет `inert` на время открытой панели и сохраняет DOM/прокрутку.
1340
+ Нативный диапазон выделения сохраняет text owner и координаты; видимое выделение
1341
+ следует браузерному `inert`-контракту и доступно после закрытия панели.
1342
+ Escape и нажатие backdrop обрабатываются внутри host; внешний ввод не закрывает
1343
+ панель и не получает отложенный возврат чужого фокуса. Вложенный `SModal`
1344
+ использует общий stack, глобальную модальность и свой focus trap.
1345
+
1346
+ `scrollBehavior="body"` оставляет padded body единственным scroll owner.
1347
+ `scrollBehavior="content"` предоставляет растягиваемый слот без полей и второго
1348
+ скролла для `SVirtualList` или `SScrollViewport block-size="fill"`.
1349
+ Consumer обрабатывает `update:open`, в том числе при retirement host. Удаление,
1350
+ замена или ошибка host завершают его слои и pending focus/`opened`; повторное
1351
+ открытие — явный переход `open=false` → `true`. Новый host с новым drawer и
1352
+ `open=true` является новым запросом, а не продолжением предыдущего lifetime.
1353
+
1354
+ `scope="contained"` requires the nearest `SOverlayHost`. Its default slot owns
1355
+ the main history, and `#overlay` owns the drawer. Sizes `sm/md/lg` mean
1356
+ 50/70/90% of the available host extent along the placement axis; `extent` is a
1357
+ finite percentage greater than 0 and at most 100, valid only for contained
1358
+ drawers. The axis is host width for `left/right` and host height for `bottom`.
1359
+ Page composition owns host dimensions; the kit owns drawer geometry
1360
+ and presentation. `mobileFullScreen` does not move a contained drawer outside
1361
+ its host.
1362
+ `scope` changes only while `open=false`; changing owners does not transfer an
1363
+ open overlay lifetime.
1364
+
1365
+ A contained drawer is a nonmodal dialog: external composer/terminal remain
1366
+ available, without global body locking or its own Tab trap. Host background
1367
+ content is inert while the drawer is open and retains its DOM/scroll position.
1368
+ Native selection ranges retain their text owner and offsets; visible selection
1369
+ follows the browser's inert contract and is available after the drawer closes.
1370
+ Escape and backdrop dismissal are host-scoped; external input neither closes
1371
+ the drawer nor receives a stale focus restoration. A nested `SModal` uses the
1372
+ same layer stack with global modality and its own focus trap.
1373
+
1374
+ `scrollBehavior="body"` provides the padded body scroll owner.
1375
+ `scrollBehavior="content"` provides a stretching slot without padding or a
1376
+ second scroll container for `SVirtualList` or `SScrollViewport block-size="fill"`.
1377
+ The consumer handles `update:open`, including host retirement. Host removal,
1378
+ replacement, or failure retires its layers and pending focus/`opened`; reopen
1379
+ requires an explicit `open=false` → `true` transition. A new host and a new
1380
+ drawer with `open=true` represent a new request, not the previous lifetime.
1381
+
1382
+ ```vue
1383
+ <SDrawer
1384
+ v-model:open="navigationOpen"
1385
+ title="Проекты и чаты"
1386
+ placement="left"
1387
+ size="md"
1388
+ >
1389
+ <ProjectChatNavigation />
1390
+ </SDrawer>
1391
+ ```
729
1392
 
730
- `SDrawer` uses `placement="right"` by default. Set `placement="bottom"` for a
731
- bottom sheet; semantic sizes map to 50, 70, and 90 percent of the dynamic
732
- viewport height. The body remains the sole scroll owner, while overlay,
733
- focus trap/restore, Escape, backdrop, and the nested layer stack are shared
734
- with the side drawer.
1393
+ ```vue
1394
+ <SOverlayHost>
1395
+ <ConversationHistory />
1396
+ <template #overlay>
1397
+ <SDrawer
1398
+ v-model:open="historyOpen"
1399
+ title="История подагента"
1400
+ scope="contained"
1401
+ placement="bottom"
1402
+ size="lg"
1403
+ scroll-behavior="content"
1404
+ >
1405
+ <VirtualSubagentHistory />
1406
+ </SDrawer>
1407
+ </template>
1408
+ </SOverlayHost>
1409
+ <Composer />
1410
+ <Terminal />
1411
+ ```
735
1412
 
736
1413
  ```vue
737
1414
  <SDrawer
@@ -745,19 +1422,47 @@ with the side drawer.
745
1422
  </SDrawer>
746
1423
  ```
747
1424
 
1425
+ ### Передача фокуса из меню / Menu focus handoff
1426
+
1427
+ Открытие `SDrawer` из действия `SDropdownMenu` передаёт initial focus
1428
+ диалогу и сохраняет устойчивый menu trigger для возврата при закрытии.
1429
+ Меню и его trigger могут находиться вне contained host. Удаление временного
1430
+ menuitem в render-cycle не делает его целью возврата и не расширяет
1431
+ Escape boundary за пределы host. Повторные открытия используют отдельный
1432
+ open-cycle. Внешний переход фокуса отменяет незавершённую передачу и stale
1433
+ return; consumer не восстанавливает фокус DOM-вызовом.
1434
+
1435
+ Передача относится к текущему open intent и связанному завершению menu
1436
+ lifetime. Произвольное ожидание сервера перед первым запросом открытия не
1437
+ сохраняет право перехватить последующий внешний фокус.
1438
+
1439
+ Opening `SDrawer` from an `SDropdownMenu` action transfers initial focus
1440
+ to the dialog and retains the stable menu trigger for restoration on close.
1441
+ The menu and its trigger may live outside a contained host. Removing the
1442
+ transient menu item during rendering neither makes it a restoration target
1443
+ nor extends Escape handling beyond the host. Repeated openings have separate
1444
+ open cycles. An external focus change cancels pending handoff and stale
1445
+ restoration; consumers do not restore focus with DOM calls.
1446
+
1447
+ Handoff belongs to the current opening intent and the associated menu
1448
+ retirement. Arbitrary server work before the first opening request does not
1449
+ preserve permission to take subsequent external focus.
1450
+
748
1451
  ### Dialog heading hierarchy
749
1452
 
750
1453
  `SModal` и `SDrawer` используют `heading-level="2"` по умолчанию: самостоятельный
751
1454
  диалог следует за основным `h1` страницы. Для диалога, вложенного в секцию или
752
1455
  другой dialog surface, consumer передаёт фактический уровень document outline
753
- числом от `1` до `6`. Видимый заголовок при любом уровне остаётся accessible name
1456
+ числом от `1` до `6`. Локальная шапка диалога не создаёт page-level `banner`.
1457
+ Видимый заголовок при любом уровне остаётся accessible name
754
1458
  через `aria-labelledby`; заменять его локальным заголовком или DOM-обходом не
755
1459
  нужно.
756
1460
 
757
1461
  `SModal` and `SDrawer` default to `heading-level="2"`, so a standalone dialog
758
1462
  follows the page's primary `h1`. A dialog nested in a section or another dialog
759
1463
  surface receives its actual document-outline level from the consumer as an
760
- integer from `1` through `6`. At every level the visible title remains the
1464
+ integer from `1` through `6`. Local dialog chrome does not create a page-level
1465
+ `banner` landmark. At every level the visible title remains the
761
1466
  accessible name through `aria-labelledby`; no local heading or DOM workaround
762
1467
  is required.
763
1468
 
@@ -783,6 +1488,62 @@ responsive and shrinks to the available viewport. If a child mount fails, the
783
1488
  modal releases its body lock, layer registration, and owned teleport nodes
784
1489
  before the error reaches the host application.
785
1490
 
1491
+ ### Управляемое открытие popover / Controlled popover opening
1492
+
1493
+ `SPopover` поддерживает `v-model:open` и программные `open(triggerId?)`/`close()`.
1494
+ Запрос от trigger сохраняет его native anchor и исходный focus owner до
1495
+ подтверждения `open`, включая отложенное применение prop. Если фокус переведён
1496
+ во внешний редактор, появление панели не перехватывает его. Открытие напрямую
1497
+ через prop использует текущий focus owner. `close()` отменяет ожидающий запрос
1498
+ через `update:open=false`; закрытие восстанавливает фокус только из принадлежащей
1499
+ панели, не из внешнего поля. Каждый новый цикл использует актуального invoker.
1500
+ Удаление или отключение текущего focused action оставляет панель открытой;
1501
+ Принятое закрытие через Escape восстанавливает focus доступному
1502
+ зарегистрированному trigger. Явный blur
1503
+ доступного элемента и переход во внешний focus owner закрывают панель
1504
+ по outside-политике без перехвата внешнего focus.
1505
+
1506
+ `SPopover` supports `v-model:open` and the programmatic `open(triggerId?)`/`close()`
1507
+ API. A trigger request preserves its native anchor and original focus owner
1508
+ through acknowledgement, including delayed prop application. A panel does not
1509
+ take focus from an external editor focused in the meantime. Direct prop-driven
1510
+ opening uses the current focus owner. `close()` cancels a pending request with
1511
+ `update:open=false`; closing restores focus only from the owned panel, not an
1512
+ external field. Each new cycle uses its current invoker.
1513
+ Removing or disabling the currently focused action keeps the panel open;
1514
+ An accepted Escape close restores focus to the available registered trigger.
1515
+ Explicitly blurring an
1516
+ available element or moving to an external focus owner dismisses the panel
1517
+ under its outside policy without taking external focus.
1518
+
1519
+ `width="trigger"` задаёт минимальную ширину anchor; `content` сохраняет
1520
+ intrinsic-ширину содержимого. `sm`, `md`, `lg` задают `20rem`, `28rem`, `36rem`
1521
+ с viewport-ограничением. Фон, тень и focus surface занимают полный dialog;
1522
+ `surface="transparent"` задаёт максимальную ширину всего dialog `90vw`;
1523
+ при `width="trigger"` минимальная ширина anchor имеет приоритет над этим максимумом.
1524
+
1525
+ `width="trigger"` sets the anchor's minimum width; `content` keeps the content's
1526
+ intrinsic width. `sm`, `md`, and `lg` specify `20rem`, `28rem`, and `36rem`,
1527
+ bounded by the viewport. Background, shadow, and focus surface occupy the full
1528
+ dialog; `surface="transparent"` sets the entire dialog's maximum width to `90vw`.
1529
+ With `width="trigger"`, the anchor minimum takes precedence over this maximum.
1530
+
1531
+ ### Читаемость всплывающих поверхностей / Overlay motion readability
1532
+
1533
+ `SDrawer`, `SPopover`, `STooltip`, `SContextMenu` и
1534
+ `SControlledToastViewport` сохраняют `opacity: 1` содержимого
1535
+ при открытии и закрытии. Прозрачность выбранного фона принадлежит surface
1536
+ контракту, а не анимации. Анимация использует перемещение и масштаб;
1537
+ backdrop имеет отдельный opacity transition. Reduced-motion предпочтение,
1538
+ focus ownership и keyboard dismissal принадлежат общим owners кита.
1539
+
1540
+ `SDrawer`, `SPopover`, `STooltip`, `SContextMenu`, and
1541
+ `SControlledToastViewport` keep content at `opacity: 1` during entry and
1542
+ exit. Background translucency belongs to the selected surface contract,
1543
+ not the animation. Motion uses translation and scale; the backdrop has an independent
1544
+ opacity transition. Reduced-motion preference, focus ownership, and keyboard
1545
+ dismissal belong to the kit's shared owners.
1546
+
786
1547
  ### Управляемое dropdown menu / Controlled dropdown menu
787
1548
 
788
1549
  `SDropdownMenu` поддерживает controlled `v-model:open`, начальное
@@ -799,6 +1560,31 @@ for asynchronous operations and repeated selection. `kind="group"` creates a
799
1560
  semantic group with a visible label, while `description` adds an accessible
800
1561
  item hint through `aria-describedby` without another tab stop.
801
1562
 
1563
+ Dropdown, контекстные и вложенные меню автоматически ограничиваются доступной
1564
+ областью viewport. `placement` задаёт предпочтительную сторону; collision
1565
+ handling допускает переход на другую сторону. Полный список пунктов сохраняется,
1566
+ а высокий список прокручивается внутри menu surface с единым chrome и scroll
1567
+ owner. Высота учитывает размеры viewport и содержимого; consumer не задаёт
1568
+ `max-height` и не переоформляет внутренности меню. Arrow/Home/End раскрывают
1569
+ сфокусированный пункт в этом viewport без прокрутки фонового документа.
1570
+ Внутренняя прокрутка сохраняет открытое меню и его родительский layer.
1571
+ Home/End повторно раскрывают текущую строку после ручной прокрутки. Если ни одна
1572
+ inline-сторона не вмещает вложенную menu surface, общий collision owner выбирает
1573
+ доступную верхнюю или нижнюю сторону.
1574
+ Escape закрывает текущий уровень и возвращает фокус его trigger.
1575
+
1576
+ Dropdown, context, and nested menus are automatically bounded by the available
1577
+ viewport. `placement` specifies the preferred side; collision handling can
1578
+ choose the opposite side. The complete item inventory is retained, while a
1579
+ tall list scrolls inside the menu surface with one chrome and scroll owner.
1580
+ Its height follows the viewport and content dimensions; consumers do not set
1581
+ `max-height` or restyle menu internals. Arrow/Home/End reveal the focused item
1582
+ inside this viewport without scrolling the background document. Internal
1583
+ scrolling preserves the open menu and its parent layer. Home/End reveal the
1584
+ current row after manual scrolling. If neither inline side can fit a submenu
1585
+ surface, the shared collision owner selects the available top or bottom side.
1586
+ Escape closes the current level and returns focus to its trigger.
1587
+
802
1588
  ```vue
803
1589
  <SDropdownMenu
804
1590
  v-model:open="workspaceMenuOpen"
@@ -820,6 +1606,63 @@ item hint through `aria-describedby` without another tab stop.
820
1606
  `SButton` disclosure hitbox at `32px`; `comfortable` retains the default
821
1607
  geometry. Consumers do not set height, padding, or internal selectors.
822
1608
 
1609
+ ### Семантика сворачиваемой панели / Collapsible panel semantics
1610
+
1611
+ `SCollapsiblePanel.contentRole` принимает `region | group`; по умолчанию
1612
+ `region`. Самостоятельные, значимые для навигации разделы используют
1613
+ `region`; повторяемые и вложенные сведения — `group`, не создающий
1614
+ landmark. Обе роли сохраняют доступное имя из видимого `summary` через
1615
+ `aria-labelledby` и связь с disclosure trigger через `aria-controls`.
1616
+ Повторяемые группы могут иметь одинаковые пользовательские заголовки.
1617
+ Роль задаётся prop, не raw `role` attr; неизвестное значение вызывает
1618
+ ошибку контракта. `lazy` монтирует slot при первом принятом раскрытии
1619
+ и удерживает содержимое после сворачивания, включая анимированный
1620
+ неуправляемый режим.
1621
+
1622
+ Controlled `open` эмитит `update:open` как намерение до подтверждения prop;
1623
+ uncontrolled режим изменяет собственное состояние без этого события.
1624
+
1625
+ Принятое сворачивание сразу исключает content из клавиатурного обхода и
1626
+ дерева доступности через `inert` и `aria-hidden`; завершающая визуальная
1627
+ анимация сохраняет mounted slot. Фокус внутри закрываемого content
1628
+ возвращается доступному trigger через его публичный focus API. Внешний
1629
+ фокус и неподтверждённое controlled намерение не перехватываются.
1630
+ Motion завершается по фактическому переходу высоты или сразу при его
1631
+ отсутствии; reduced motion, повторное раскрытие и изменение содержимого
1632
+ не требуют ожиданий или DOM-вызовов consumer.
1633
+
1634
+ `SCollapsiblePanel.contentRole` accepts `region | group` and defaults to
1635
+ `region`. Independently significant, navigable sections use `region`;
1636
+ repeated and nested details use the non-landmark `group`. Both roles
1637
+ retain an accessible name from the visible `summary` through
1638
+ `aria-labelledby` and the trigger relationship through `aria-controls`.
1639
+ Repeated groups may share the same user-facing heading. The role is
1640
+ specified by a prop, not a raw `role` attr; an unknown value fails the
1641
+ contract. `lazy` mounts the slot on its first accepted opening and retains
1642
+ the content after collapse, including animated uncontrolled mode.
1643
+
1644
+ Controlled `open` emits an `update:open` intent before prop acknowledgement;
1645
+ uncontrolled mode updates its owned state without that event.
1646
+
1647
+ An accepted collapse immediately excludes content from keyboard navigation
1648
+ and the accessibility tree using `inert` and `aria-hidden`; the closing
1649
+ visual transition retains the mounted slot. Focus inside the collapsing
1650
+ content returns to an available trigger through its public focus API.
1651
+ External focus and unacknowledged controlled intent are not intercepted.
1652
+ Motion settles on the actual height transition or immediately when none
1653
+ exists; reduced motion, reopening, and content changes require no consumer
1654
+ waits or DOM calls.
1655
+
1656
+ ```vue
1657
+ <SCollapsiblePanel summary="Технические сведения" content-role="group" lazy>
1658
+ <SInputText v-model="connectionName" label="Имя подключения" />
1659
+ </SCollapsiblePanel>
1660
+ ```
1661
+
1662
+ [APG Accordion](https://www.w3.org/WAI/ARIA/apg/patterns/accordion/) рассматривает
1663
+ landmark role как необязательный; [ARIA group](https://www.w3.org/TR/wai-aria-1.2/#group)
1664
+ предназначен для локальной группировки без включения в оглавление страницы.
1665
+
823
1666
  ### Dialog open lifecycle
824
1667
 
825
1668
  `SModal` и `SDrawer` эмитят `opened` один раз для каждого подтверждённого цикла
@@ -836,13 +1679,65 @@ focus. The handler can call a nested leaf's public exposed API, such as
836
1679
  cancels the event; Escape, focus trapping, and focus restoration remain owned
837
1680
  by the dialog surface.
838
1681
 
1682
+ Закрытие через `open=false` и удаление открытой feature-формы через `v-if`
1683
+ поддерживают один focus-контракт, включая удаление формы в том же обработчике,
1684
+ который закрывает вложенное или соседнее подтверждение. После удаления
1685
+ владеющего фокусом dialog focus возвращается подключённому, видимому инициатору,
1686
+ допустимому в текущей modal boundary. Consumer не ожидает отдельное событие
1687
+ закрытия и не вызывает DOM `focus()`/`nextTick()` для восстановления. Новый
1688
+ overlay или явное перемещение фокуса отменяют отложенный возврат. Скрытие
1689
+ retained dock и аварийное освобождение overlay не возвращают focus скрытому
1690
+ или inert инициатору.
1691
+
1692
+ Retained dialog сохраняет право возврата после удаления или отключения
1693
+ focused action во время асинхронной операции. Утрата native focus
1694
+ определяется по завершённому DOM-обновлению: focus остаётся на BODY, а
1695
+ наблюдённый descendant удалён или потерял native focus capability.
1696
+ Отдельный blur живого enabled элемента, завершённый до его удаления,
1697
+ отменяет это право. Перемещение фокуса на другой owner отменяет его сразу,
1698
+ включая последующий blur этого owner. Consumer не подавляет blur/removal
1699
+ events и не управляет порядком native focus fixup.
1700
+
1701
+ Closing with `open=false` and removing an open feature form with `v-if` share
1702
+ one focus contract, including removal in the same handler that closes a nested
1703
+ or sibling confirmation. After removing the focus-owning dialog, focus returns
1704
+ to its connected, visible invoker if allowed by the current modal boundary.
1705
+ Consumers need no separate close acknowledgement or DOM `focus()`/`nextTick()`
1706
+ for restoration. A new overlay or explicit focus move cancels pending
1707
+ restoration. Retained dock hiding and error cleanup do not restore focus to a
1708
+ hidden or inert invoker.
1709
+
1710
+ A retained dialog preserves focus return after a focused action is removed
1711
+ or disabled during asynchronous work. Native focus loss is evaluated after
1712
+ the DOM update: focus remains on BODY and the observed descendant is removed
1713
+ or loses its native focus capability. A separate blur of a live enabled
1714
+ element, completed before removal, cancels this ownership. Moving focus to
1715
+ another owner cancels it immediately, including a later blur of that owner.
1716
+ Consumers do not suppress blur/removal events or manage native focus-fixup order.
1717
+
839
1718
  ```vue
840
- <SModal v-model:open="open" title="Исходный текст" @opened="selectAll">
1719
+ <SModal v-model:open="open" title="Исходный текст" @opened="textarea?.selectAll()">
841
1720
  <STextarea ref="textarea" :model-value="source" label="Текст" readonly />
842
1721
  </SModal>
843
1722
  ```
844
1723
 
845
- ### Assistive live status
1724
+ ### Status presentation and assistive announcements
1725
+
1726
+ Видимый `SStatus` использует общую feedback-пару `tone`; `neutral` соответствует
1727
+ нейтральной `secondary`-паре. `appearance="soft"` владеет своим непрозрачным
1728
+ фоном и foreground. Текстовый статус внутри пассивного slot `SButton` использует
1729
+ foreground интерактивного владельца, включая solid, hover, active и focus;
1730
+ `tone`, текст и семантическая иконка сохраняются. `SCollapsiblePanel.summaryStatus`
1731
+ использует этот же контракт в compact/dense заголовке. Локальные color overrides
1732
+ для вложенных статусов не требуются.
1733
+
1734
+ Visible `SStatus` uses the shared feedback `tone` pair; `neutral` maps to the
1735
+ neutral `secondary` pair. `appearance="soft"` owns its opaque background and
1736
+ foreground. A text status in an `SButton` passive slot uses the interactive
1737
+ owner's foreground across solid, hover, active, and focus states; `tone`, its
1738
+ label, and the semantic icon are preserved. `SCollapsiblePanel.summaryStatus`
1739
+ uses the same contract in compact/dense headers. Nested statuses require no
1740
+ local color overrides.
846
1741
 
847
1742
  `SStatus` с `visibility="assistive"` выводит всю status surface из layout,
848
1743
  сохраняя текст сообщения в accessibility tree. `live="polite"` или
@@ -899,7 +1794,7 @@ snapshot can move between instances or be retained while switching chats.
899
1794
  @viewport-change="viewport = $event"
900
1795
  >
901
1796
  <template #header>
902
- <SButton variant="ghost" @click="loadPreviousPage">
1797
+ <SButton appearance="ghost" @click="loadPreviousPage">
903
1798
  Загрузить предыдущие
904
1799
  </SButton>
905
1800
  </template>
@@ -913,10 +1808,13 @@ snapshot can move between instances or be retained while switching chats.
913
1808
  ```
914
1809
 
915
1810
  ```ts
916
- const snapshot = history.value?.captureViewport()
917
- await history.value?.restoreViewport(snapshot)
918
- history.value?.scrollToKey(messageId, 'center')
919
- history.value?.scrollToEnd({ follow: true })
1811
+ const historyOwner = history.value
1812
+ if (historyOwner) {
1813
+ const snapshot = historyOwner.captureViewport()
1814
+ await historyOwner.restoreViewport(snapshot)
1815
+ historyOwner.scrollToKey(messageId, 'center')
1816
+ historyOwner.scrollToEnd({ follow: true })
1817
+ }
920
1818
  ```
921
1819
 
922
1820
  `viewport-change` сообщает keyed anchor, visible range, `nearStart`, `atEnd` и
@@ -928,6 +1826,11 @@ Paging, status и end-marker рендерятся через `header`/`footer`,
928
1826
  синтетические элементы domain-списка. Home, End, Page и Arrow keys владеют
929
1827
  viewport navigation только при focus самого `SVirtualList`; вложенный
930
1828
  editable/control сохраняет свою keyboard-семантику.
1829
+ Строка с фактическим DOM-фокусом сохраняет keyed DOM identity при изменении
1830
+ измерений, viewport и rendered range. Вложенный редактор сохраняет focus и
1831
+ selection без программного перевода фокуса. Lease удерживает только одну
1832
+ дополнительную строку вне виртуального окна и снимается при focusout из строки,
1833
+ удалении её domain key или unmount. `header`/`footer` не входят в keyed lease.
931
1834
 
932
1835
  `viewport-change` reports the keyed anchor, visible range, `nearStart`, `atEnd`,
933
1836
  and `pinnedToEnd`. An upward wheel, keyboard, or scrollbar gesture detaches
@@ -939,6 +1842,12 @@ Paging, status, and end markers belong in `header`/`footer`, not in the keyed
939
1842
  domain items. Home, End, Page, and Arrow keys control the viewport only while
940
1843
  `SVirtualList` itself owns focus; a nested editable/control retains its own
941
1844
  keyboard semantics.
1845
+ The row containing actual DOM focus retains its keyed DOM identity across
1846
+ measurement, viewport, and rendered-range changes. A nested editor preserves
1847
+ focus and selection without programmatic refocusing. This lease retains only
1848
+ one additional row outside the virtual window and ends when focus leaves that
1849
+ row, its domain key is removed, or the list unmounts. `header`/`footer` regions
1850
+ do not own a keyed row lease.
942
1851
 
943
1852
  ## Темы и стили / Themes and styles
944
1853
 
@@ -960,6 +1869,26 @@ application's own `@import "tailwindcss"`:
960
1869
  typography plugin. `reference.css` is a compile-time `@reference` target for
961
1870
  component styles.
962
1871
 
1872
+ Оба CSS entrypoint используют полную сборку upstream typography plugin внутри
1873
+ пакета. Устанавливать `@tailwindcss/typography` или переопределять его transitive
1874
+ зависимости в consumer не требуется. Лицензии включённых модулей находятся в
1875
+ `dist/typography.LICENSE.txt`. / Both CSS entrypoints use the complete upstream
1876
+ typography plugin bundled in the package. Consumers do not need to install
1877
+ `@tailwindcss/typography` or override its transitive dependencies. The included
1878
+ module licenses are provided in `dist/typography.LICENSE.txt`.
1879
+
1880
+ `dist/typography.js` — build-time Node ESM plugin. Он использует native
1881
+ `node:util`, сохраняет upstream options API `className`/`target` для
1882
+ `modern` и `legacy`, полный prose handler и theme. Импорты
1883
+ `tailwind.css`/`reference.css` не требуют browser Web Storage, DOM globals
1884
+ или дополнительных Node flags в consumer build.
1885
+
1886
+ `dist/typography.js` is a build-time Node ESM plugin. It uses native
1887
+ `node:util` and retains the upstream `className`/`target` options for
1888
+ `modern` and `legacy`, the complete prose handler, and theme. Building
1889
+ `tailwind.css`/`reference.css` needs neither browser Web Storage nor
1890
+ DOM globals or additional Node flags.
1891
+
963
1892
  Для token-only интеграции доступен отдельный entrypoint:
964
1893
 
965
1894
  A separate entrypoint is available for token-only integration:
@@ -1000,8 +1929,12 @@ Components consume semantic custom properties. Consumers override documented
1000
1929
  tokens on the root theme container and do not depend on internal CSS classes or
1001
1930
  template structure.
1002
1931
 
1003
- Floating surfaces teleport to `document.body`; toast, drag fallbacks, modal, and
1004
- drawer also use root-level bands. The values `--s-layer-floating`,
1932
+ Unscoped floating surfaces teleport to `document.body`. Floating descendants of
1933
+ a viewport dialog use its untransformed portal. Native modal top-layer order
1934
+ belongs to the browser, not to a larger `z-index`. Global notifications remain
1935
+ background content during viewport modality; a modal-local notification viewport
1936
+ uses its own dialog's portal. Toast and drag root bands do not override native
1937
+ top-layer isolation. The values `--s-layer-floating`,
1005
1938
  `--s-layer-toast`, `--s-layer-drag`, and `--s-layer-overlay-backdrop` are base
1006
1939
  anchors. Registered nested layers advance by `--s-layer-overlay-step`, while a
1007
1940
  modal surface uses `--s-layer-overlay-surface-offset` above its backdrop.
@@ -1017,6 +1950,7 @@ Integrate a host overlay scale through one root offset:
1017
1950
 
1018
1951
  `--host-overlay-surface` belongs to the host application. The offset shifts all
1019
1952
  root UI-kit bands together and leaves local content/navigation anchors intact.
1953
+ It integrates ordinary host stacking contexts, not another native top layer.
1020
1954
  Do not combine it with manual shifts of individual layer tokens. The complete
1021
1955
  owner map, dynamic-stack contract, and verification checklist are published in
1022
1956
  `docs/theming.md` inside the npm package.
@@ -1036,6 +1970,79 @@ separator по умолчанию использует `compact`, overlay handle
1036
1970
  Для 12-пиксельной границы workbench-панели используйте `standard`, не изменяя
1037
1971
  внутренние стили компонента.
1038
1972
 
1973
+ Pointer resize имеет отдельные `resize-end` и `resize-cancel`: завершение
1974
+ принимает конечную координату, отмена возвращает snapshot без сохранения
1975
+ preview. `SDockRegion` передаёт `hitbox` и поддерживает opt-in
1976
+ `collapseThreshold` с отдельным `collapse({ preferredSize })` intent.
1977
+ Клавиатурный Home остаётся установкой минимального размера. Типы, transaction
1978
+ ownership и примеры включены в пакет: `docs/resize.md`.
1979
+
1980
+ ### Сохранение скрытой рабочей панели / Hidden dock content retention
1981
+
1982
+ `SDockRegion.keepMounted` — boolean с default `false`: скрытие освобождает
1983
+ slot owner. При `true` один slot owner сохраняется, включая начальное
1984
+ `visible=false`. Скрытый регион имеет нулевой layout, `hidden`/`inert`,
1985
+ не участвует в Tab, pointer или accessibility tree и не содержит resize handle.
1986
+ Скрытие во время drag отменяет resize через его общий lifecycle без terminal
1987
+ commit. Повторное отображение сохраняет экземпляр и native состояние содержимого,
1988
+ но не забирает focus у внешнего editor. Выключение retention у скрытого региона
1989
+ или unmount освобождает его содержимое.
1990
+
1991
+ Вложенные UI-kit menu, listbox, popover, tooltip и dialog следуют `visible`,
1992
+ включая Teleport-поверхности: скрытие завершает открытые и ожидающие циклы,
1993
+ освобождает overlay leases/body lock и не возвращает focus скрытому trigger.
1994
+ Начальный hidden state запрещает открытие. Controlled `open=true` получает
1995
+ один close intent; для нового открытия требуется запрос `false → true`.
1996
+ Отображение retained content не возобновляет завершённый цикл. Вложенные dock
1997
+ сочетают visibility через логическое AND, независимые sibling overlays не
1998
+ затрагиваются. Произвольные consumer-owned portals остаются ответственностью
1999
+ consumer.
2000
+
2001
+ Содержимое, transport и output buffer принадлежат consumer. Для imperative
2002
+ терминала экземпляр получает output и при скрытом регионе; `Terminal.open()`
2003
+ вызывается только для connected, видимого host с положительными размерами.
2004
+ UI-kit не импортирует xterm и не пересоздаёт PTY. Политика едина для
2005
+ `left | right | bottom` и `fixed | fill-on-narrow`.
2006
+
2007
+ `SDockRegion.keepMounted` is a boolean defaulting to `false`: hiding disposes
2008
+ the slot owner. With `true`, the same owner remains mounted, including initial
2009
+ `visible=false`. The hidden region has zero layout footprint, is `hidden` and
2010
+ `inert`, participates in no Tab/pointer/accessibility navigation, and contains
2011
+ no resize handle. Hiding during a drag cancels the shared resize lifecycle
2012
+ without a terminal commit. Showing retains the instance and its native state
2013
+ without stealing focus from an external editor. Disabling retention while
2014
+ hidden or unmounting disposes the content.
2015
+
2016
+ Nested UI-kit menus, listboxes, popovers, tooltips, and dialogs follow `visible`,
2017
+ including their Teleport surfaces. Hiding retires open and pending cycles,
2018
+ releases overlay leases/body locks, and never restores focus to a hidden trigger.
2019
+ Initially hidden content cannot open an overlay. Controlled `open=true` receives
2020
+ one close intent and requires a fresh `false → true` request. Showing retained
2021
+ content does not resurrect a retired cycle. Nested docks compose visibility with
2022
+ logical AND; independent sibling overlays are unaffected. Arbitrary
2023
+ consumer-owned portals remain the consumer's responsibility.
2024
+
2025
+ Content, transport, and output buffers belong to the consumer. An imperative
2026
+ terminal can receive output while hidden; call `Terminal.open()` only for a
2027
+ connected, visible host with positive dimensions. The UI-kit does not import
2028
+ xterm or restart a PTY. The policy applies to `left | right | bottom` and
2029
+ `fixed | fill-on-narrow`.
2030
+
2031
+ ```vue
2032
+ <SDockRegion
2033
+ placement="bottom"
2034
+ :visible="terminalVisible"
2035
+ keep-mounted
2036
+ :size="terminalHeight"
2037
+ :min-size="160"
2038
+ :max-size="480"
2039
+ resize-label="Высота терминала"
2040
+ @resize="terminalHeight = $event"
2041
+ >
2042
+ <TerminalViewport :visible="terminalVisible" />
2043
+ </SDockRegion>
2044
+ ```
2045
+
1039
2046
  ## Публичный контракт / Public contract
1040
2047
 
1041
2048
  `package.json#exports` — источник истины для импортов. Публичный контракт
@@ -1087,16 +2094,33 @@ local DOM listeners or CSS.
1087
2094
 
1088
2095
  ## Версии / Versioning
1089
2096
 
1090
- Пакет следует Semantic Versioning:
2097
+ Пакет следует [Semantic Versioning](https://semver.org/). В серии `0.x`
2098
+ контракт развивается по явной политике:
2099
+
2100
+ The package follows [Semantic Versioning](https://semver.org/). The `0.x` series
2101
+ uses an explicit development policy:
2102
+
2103
+ - `0.y.patch` сохраняет документированный public API;
2104
+ `0.y.patch` preserves the documented public API;
2105
+ - `0.minor.0` может расширять API или требовать явно описанной миграции.
2106
+ Затронутая поверхность и действия consumer фиксируются в release notes и guide;
2107
+ `0.minor.0` may extend the API or require an explicitly documented migration.
2108
+ Release notes and a guide identify the affected surface and consumer actions.
2109
+
2110
+ Обновление между minor-сериями `0.x` требует чтения migration notes и проверки
2111
+ своей композиции; один только minor номер не обещает отсутствие миграции.
2112
+
2113
+ Upgrading between `0.x` minor series requires reviewing migration notes and
2114
+ verifying the consumer composition; a minor number alone does not guarantee a
2115
+ migration-free upgrade.
1091
2116
 
1092
- The package follows Semantic Versioning:
2117
+ Начиная с `1.0.0` действует стабильный public API: `patch` — совместимое
2118
+ исправление, `minor` — совместимое расширение, `major` — несовместимое изменение
2119
+ exports, props, events, tokens или поведения.
1093
2120
 
1094
- - `patch` — исправление с сохранением документированного контракта;
1095
- a fix that preserves the documented contract;
1096
- - `minor` — обратно совместимое расширение public API;
1097
- a backward-compatible public API extension;
1098
- - `major` — несовместимое изменение exports, props, events, tokens или поведения;
1099
- an incompatible change to exports, props, events, tokens, or behavior.
2121
+ From `1.0.0`, the public API is stable: `patch` is a compatible fix, `minor` is
2122
+ a compatible extension, and `major` is an incompatible change to exports,
2123
+ props, events, tokens, or behavior.
1100
2124
 
1101
2125
  Один и тот же номер версии не публикуется повторно.
1102
2126