@pgcorp/ui-kit 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +188 -9
- package/docs/getting-started.md +135 -0
- package/docs/public-api.md +53 -4
- package/docs/rich-document.md +216 -0
- package/docs/scroll-viewport.md +167 -0
- package/package.json +103 -50
- package/src/components/layout/SAppShell.vue +3 -1
- package/src/components/layout/SDockRegion.vue +5 -3
- package/src/components/layout/SWorkbenchPanelShell.vue +4 -2
- package/src/components/shared/_internal/SDialogSurface.css +5 -0
- package/src/components/shared/_internal/SDialogSurface.vue +3 -1
- package/src/components/shared/_internal/SToastItem.css +4 -0
- package/src/components/shared/_internal/SToastItem.vue +44 -8
- package/src/components/shared/_internal/STreeNode.vue +24 -11
- package/src/components/shared/complex/SKanbanLane.vue +4 -2
- package/src/components/shared/containers/SCloudChromeRow.vue +3 -2
- package/src/components/shared/containers/SDrawer.vue +5 -2
- package/src/components/shared/containers/SModal.vue +5 -2
- package/src/components/shared/containers/SPanel.vue +4 -2
- package/src/components/shared/containers/SPopover.vue +7 -3
- package/src/components/shared/containers/SUiKitLocaleProvider.vue +57 -0
- package/src/components/shared/controls/SButton.css +14 -10
- package/src/components/shared/controls/SCombobox.vue +8 -6
- package/src/components/shared/controls/SComboboxTrigger.css +7 -4
- package/src/components/shared/controls/SComboboxTrigger.vue +5 -2
- package/src/components/shared/controls/SContextToggleButton.vue +6 -4
- package/src/components/shared/controls/SDragHandle.vue +8 -4
- package/src/components/shared/controls/SDropdownMenu.vue +7 -4
- package/src/components/shared/controls/SInputText.css +5 -4
- package/src/components/shared/controls/SListbox.vue +4 -2
- package/src/components/shared/controls/SSelect.vue +4 -2
- package/src/components/shared/controls/_internal/SInlineTokenSurface.vue +4 -2
- package/src/components/shared/data-display/SChart.vue +7 -5
- package/src/components/shared/data-display/SChip.vue +3 -1
- package/src/components/shared/data-display/SCodeBlock.css +4 -0
- package/src/components/shared/data-display/SCodeBlock.vue +42 -20
- package/src/components/shared/data-display/SCodeEditor.css +17 -0
- package/src/components/shared/data-display/SCodeEditor.vue +173 -8
- package/src/components/shared/data-display/SCodeSearchPanel.vue +48 -33
- package/src/components/shared/data-display/SCodeWorkspaceEditor.css +13 -0
- package/src/components/shared/data-display/SCodeWorkspaceEditor.vue +355 -0
- package/src/components/shared/data-display/SControlledToastViewport.css +89 -0
- package/src/components/shared/data-display/SControlledToastViewport.vue +205 -0
- package/src/components/shared/data-display/SCopyField.vue +12 -10
- package/src/components/shared/data-display/SDiffViewer.css +122 -0
- package/src/components/shared/data-display/SDiffViewer.vue +499 -0
- package/src/components/shared/data-display/SDocBlock.vue +99 -71
- package/src/components/shared/data-display/SExpandableText.vue +10 -8
- package/src/components/shared/data-display/SJsonTree.vue +4 -2
- package/src/components/shared/data-display/SLinkedSystemsList.vue +4 -2
- package/src/components/shared/data-display/SMessage.vue +6 -6
- package/src/components/shared/data-display/SRichDocument.css +8 -0
- package/src/components/shared/data-display/SRichDocument.vue +65 -0
- package/src/components/shared/data-display/SScrollViewport.css +53 -0
- package/src/components/shared/data-display/SScrollViewport.vue +470 -0
- package/src/components/shared/data-display/STable.vue +38 -19
- package/src/components/shared/data-display/SToastContainer.vue +22 -17
- package/src/components/shared/data-display/_internal/SCodeTokenLine.css +72 -0
- package/src/components/shared/data-display/_internal/SCodeTokenLine.vue +79 -0
- package/src/components/shared/data-display/_internal/SRichBlockNode.css +85 -0
- package/src/components/shared/data-display/_internal/SRichBlockNode.vue +282 -0
- package/src/components/shared/data-display/_internal/SRichInlineNode.css +6 -0
- package/src/components/shared/data-display/_internal/SRichInlineNode.vue +76 -0
- package/src/components/shared/data-display/_internal/SRichMath.css +42 -0
- package/src/components/shared/data-display/_internal/SRichMath.vue +102 -0
- package/src/components/shared/data-display/codeEditor.ts +200 -0
- package/src/components/shared/data-display/codeWorkspace.ts +233 -0
- package/src/components/shared/data-display/diff.ts +541 -0
- package/src/components/shared/data-display/richDocument.ts +876 -0
- package/src/components/shared/data-display/scrollViewport.ts +47 -0
- package/src/components/shared/data-display/toast.ts +194 -0
- package/src/components/shared/database/SDataGrid.vue +7 -4
- package/src/components/shared/database/SSqlEditor.vue +39 -39
- package/src/components/shared/feedback/SAsyncState.vue +3 -1
- package/src/components/shared/graph/SGraphViewport.vue +11 -9
- package/src/components/shared/navigation/SBreadcrumbs.vue +8 -5
- package/src/components/shared/navigation/SCatalogNavigator.vue +26 -20
- package/src/components/shared/navigation/STabList.vue +10 -6
- package/src/components/shared/navigation/STabs.vue +15 -11
- package/src/components/shared/navigation/SWizardSteps.vue +4 -2
- package/src/components/shared/persona/SPersonaProjectPicker.vue +31 -27
- package/src/components/shared/persona/SPersonaRunWorkbench.vue +39 -33
- package/src/components/shared/persona/_internal/SPersonaRunConsole.vue +8 -6
- package/src/components/shared/persona/_internal/labels.ts +66 -57
- package/src/components/shared/persona/presentation.ts +140 -110
- package/src/composables/useFloatingPosition.ts +39 -2
- package/src/composables/useUiKitLocale.ts +17 -0
- package/src/internal/codeHighlight.ts +110 -0
- package/src/internal/diffEngine.ts +464 -0
- package/src/internal/diffRuntime.ts +189 -0
- package/src/internal/feedbackPresentation.ts +33 -14
- package/src/internal/localeContext.ts +22 -0
- package/src/internal/ownedAttrs.ts +8 -0
- package/src/internal/runtimeContract.ts +11 -9
- package/src/internal/semanticSizing.ts +13 -0
- package/src/locales/catalog.ts +634 -0
- package/src/locales/locale.ts +472 -0
- package/src/locales/messages.generated.ts +1826 -0
- package/src/locales/messages.ts +150 -0
- package/src/stores/useNotifierStore.ts +61 -44
- package/src/styles/tokens.css +20 -2
- package/src/theme.ts +59 -32
- package/src/workers/diff.worker.ts +73 -0
- package/src/workers/diffProtocol.ts +155 -0
- package/src/components/shared/data-display/SToastContainer.css +0 -53
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
**A typed PGCorp design system for Vue 3, spanning foundational controls and
|
|
7
7
|
complete workbench interfaces.**
|
|
8
8
|
|
|
9
|
-
`Vue 3` · `TypeScript` · `
|
|
9
|
+
`Vue 3` · `TypeScript` · `exact public exports` · `6 themes` · `MIT`
|
|
10
10
|
|
|
11
11
|
## Что входит / What is included
|
|
12
12
|
|
|
@@ -26,22 +26,23 @@ complete workbench interfaces.**
|
|
|
26
26
|
## Установка / Installation
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
|
-
npm install @pgcorp/ui-kit vue pinia vue-router
|
|
29
|
+
npm install @pgcorp/ui-kit @vue/devtools-api vue pinia vue-router
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
| Требование / Requirement | Версия / Version |
|
|
33
33
|
| --- | --- |
|
|
34
|
-
| Node.js |
|
|
34
|
+
| Node.js | `^22.22.2 \|\| ^24.15.0 \|\| ^26.0.0` |
|
|
35
35
|
| npm | `>=10.9.2 <12` |
|
|
36
|
-
| Vue | `^3.5.
|
|
37
|
-
| Pinia | `^
|
|
38
|
-
| Vue
|
|
36
|
+
| Vue | `^3.5.43` |
|
|
37
|
+
| Pinia | `^4.0.3` |
|
|
38
|
+
| Vue Devtools API | `^8.2.1` |
|
|
39
|
+
| Vue Router | `^5.3.1` |
|
|
39
40
|
| Build tool | Vite with Vue SFC support |
|
|
40
41
|
|
|
41
|
-
`vue`, `pinia` и `vue-router` являются peer dependencies. Consumer-приложение
|
|
42
|
+
`vue`, `pinia`, `@vue/devtools-api` и `vue-router` являются peer dependencies. Consumer-приложение
|
|
42
43
|
владеет их единственными runtime-экземплярами.
|
|
43
44
|
|
|
44
|
-
`vue`, `pinia`, and `vue-router` are peer dependencies. The consumer application
|
|
45
|
+
`vue`, `pinia`, `@vue/devtools-api`, and `vue-router` are peer dependencies. The consumer application
|
|
45
46
|
owns their single runtime instances.
|
|
46
47
|
|
|
47
48
|
## Быстрый старт / Quick start
|
|
@@ -113,6 +114,120 @@ Production build должен разрешать package exports напряму
|
|
|
113
114
|
The production build must resolve package exports directly, without a source
|
|
114
115
|
monorepo alias or copied UI-kit files.
|
|
115
116
|
|
|
117
|
+
### Локализация / Localization
|
|
118
|
+
|
|
119
|
+
UI-kit поддерживает `en`, `ru`, `zh-CN` и `zh-TW`. Без provider используется
|
|
120
|
+
`ru`; `SUiKitLocaleProvider` задаёт локаль для одного Vue subtree и не создаёт
|
|
121
|
+
дополнительный DOM-элемент. / The UI kit supports `en`, `ru`, `zh-CN`, and
|
|
122
|
+
`zh-TW`. Without a provider it uses `ru`; `SUiKitLocaleProvider` selects a
|
|
123
|
+
locale for one Vue subtree without adding a DOM element.
|
|
124
|
+
|
|
125
|
+
```vue
|
|
126
|
+
<script setup lang="ts">
|
|
127
|
+
import SUiKitLocaleProvider from '@pgcorp/ui-kit/shared/containers/SUiKitLocaleProvider.vue'
|
|
128
|
+
import type { UiKitLocale } from '@pgcorp/ui-kit/composables/useUiKitLocale'
|
|
129
|
+
|
|
130
|
+
const locale: UiKitLocale = 'en'
|
|
131
|
+
</script>
|
|
132
|
+
|
|
133
|
+
<template>
|
|
134
|
+
<SUiKitLocaleProvider :locale="locale">
|
|
135
|
+
<AppWorkspace />
|
|
136
|
+
</SUiKitLocaleProvider>
|
|
137
|
+
</template>
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Provider переводит только kit-owned visible/assistive copy. Доменные данные и
|
|
141
|
+
пользовательский контент остаются ответственностью consumer. Вложенные provider
|
|
142
|
+
наследуют ближайший context и принимают типизированный `messages` override. /
|
|
143
|
+
The provider translates kit-owned visible and assistive copy only. Domain data
|
|
144
|
+
and user content remain consumer-owned. Nested providers inherit the nearest
|
|
145
|
+
context and accept a typed `messages` override.
|
|
146
|
+
|
|
147
|
+
### Уведомления / Notifications
|
|
148
|
+
|
|
149
|
+
`SControlledToastViewport` отображает readonly application records и возвращает
|
|
150
|
+
serializable `dismiss`, `action` и `lifetime-expired` intents. Consumer остаётся
|
|
151
|
+
владельцем массива, порядка, ID и durable history. Режим `consumer` не создаёт
|
|
152
|
+
таймеры; режим `viewport` управляет только presentation lifetime и ставит его на
|
|
153
|
+
паузу при hover/focus. / `SControlledToastViewport` renders readonly application
|
|
154
|
+
records and emits serializable `dismiss`, `action`, and `lifetime-expired`
|
|
155
|
+
intents. The consumer owns the array, ordering, IDs, and durable history. The
|
|
156
|
+
`consumer` mode creates no timers; the `viewport` mode owns presentation
|
|
157
|
+
lifetime only and pauses it on hover/focus.
|
|
158
|
+
|
|
159
|
+
```ts
|
|
160
|
+
import type { SToastPresentation } from '@pgcorp/ui-kit/shared/data-display/toast'
|
|
161
|
+
import SControlledToastViewport from '@pgcorp/ui-kit/shared/data-display/SControlledToastViewport.vue'
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
`SToastContainer` и `useNotifier` образуют автономный convenience-контракт для
|
|
165
|
+
одного Pinia root. Store хранит не более 100 history records и освобождает свои
|
|
166
|
+
таймеры через `$dispose()`/`$reset()`. / `SToastContainer` and `useNotifier`
|
|
167
|
+
provide the autonomous convenience contract for one Pinia root. The store keeps
|
|
168
|
+
at most 100 history records and releases its timers through `$dispose()`/`$reset()`.
|
|
169
|
+
|
|
170
|
+
### Безопасные rich documents / Safe rich documents
|
|
171
|
+
|
|
172
|
+
`SRichDocument` отображает закрытую versioned `SRichDocumentV1` AST без raw
|
|
173
|
+
HTML, VNodes, callbacks и trust flags. Внешний JSON проверяется через
|
|
174
|
+
`validateRichDocument` и `validateRichDocumentResources`; ошибки содержат
|
|
175
|
+
stable code и точный node path. Consumer-owned resources связываются по ID, а
|
|
176
|
+
link/resource/action effects возвращаются как typed intents. Link-node с
|
|
177
|
+
`current: true` выражает текущее назначение через `aria-current="page"`.
|
|
178
|
+
|
|
179
|
+
`SRichDocument` renders the closed, versioned `SRichDocumentV1` AST without raw
|
|
180
|
+
HTML, VNodes, callbacks, or trust flags. External JSON is checked with
|
|
181
|
+
`validateRichDocument` and `validateRichDocumentResources`; failures include a
|
|
182
|
+
stable code and exact node path. Consumer-owned resources are joined by ID, and
|
|
183
|
+
link/resource/action effects are emitted as typed intents. A link node with
|
|
184
|
+
`current: true` exposes the current destination through `aria-current="page"`.
|
|
185
|
+
|
|
186
|
+
```ts
|
|
187
|
+
import SRichDocument from '@pgcorp/ui-kit/shared/data-display/SRichDocument.vue'
|
|
188
|
+
import {
|
|
189
|
+
validateRichDocument,
|
|
190
|
+
validateRichDocumentResources,
|
|
191
|
+
type SRichDocumentV1,
|
|
192
|
+
} from '@pgcorp/ui-kit/shared/data-display/richDocument'
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Code highlighting and KaTeX load through local lazy chunks; SSR uses safe text
|
|
196
|
+
fallbacks. Полный security, resource, event и versioning contract описан в
|
|
197
|
+
[`docs/rich-document.md`](https://github.com/pglyanenko/sputnig/blob/master/packages/ui-kit/docs/rich-document.md). / The complete security,
|
|
198
|
+
resource, event, and versioning contract is documented in
|
|
199
|
+
[`docs/rich-document.md`](https://github.com/pglyanenko/sputnig/blob/master/packages/ui-kit/docs/rich-document.md).
|
|
200
|
+
|
|
201
|
+
### Области прокрутки / Scroll viewports
|
|
202
|
+
|
|
203
|
+
`SScrollViewport` владеет именованной scroll region, осями `x`/`y`/`both`,
|
|
204
|
+
semantic block size, overscroll policy и root-only keyboard navigation.
|
|
205
|
+
Событие `scroll-state` возвращает normalized physical и writing-mode-aware
|
|
206
|
+
semantic offsets. Exposed API предоставляет `focus`, `scrollToBoundary` и
|
|
207
|
+
`reveal`, но не открывает DOM owner.
|
|
208
|
+
|
|
209
|
+
`SScrollViewport` owns a named scroll region, `x`/`y`/`both` axes, semantic
|
|
210
|
+
block size, overscroll policy, and root-only keyboard navigation. The
|
|
211
|
+
`scroll-state` event provides normalized physical and writing-mode-aware
|
|
212
|
+
semantic offsets. Its exposed API provides `focus`, `scrollToBoundary`, and
|
|
213
|
+
`reveal` without exposing the DOM owner.
|
|
214
|
+
|
|
215
|
+
```ts
|
|
216
|
+
import SScrollViewport from '@pgcorp/ui-kit/shared/data-display/SScrollViewport.vue'
|
|
217
|
+
import type {
|
|
218
|
+
SScrollViewportApi,
|
|
219
|
+
SScrollViewportState,
|
|
220
|
+
} from '@pgcorp/ui-kit/shared/data-display/scrollViewport'
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Вложенные inputs, editors и terminals сохраняют собственную клавиатуру,
|
|
224
|
+
selection и native copy. Полный axes, state, API и lifecycle contract описан в
|
|
225
|
+
[`docs/scroll-viewport.md`](https://github.com/pglyanenko/sputnig/blob/master/packages/ui-kit/docs/scroll-viewport.md). /
|
|
226
|
+
Nested inputs, editors, and terminals retain their keyboard behavior,
|
|
227
|
+
selection, and native copy. The complete axes, state, API, and lifecycle
|
|
228
|
+
contract is documented in
|
|
229
|
+
[`docs/scroll-viewport.md`](https://github.com/pglyanenko/sputnig/blob/master/packages/ui-kit/docs/scroll-viewport.md).
|
|
230
|
+
|
|
116
231
|
## Карта компонентов / Component map
|
|
117
232
|
|
|
118
233
|
| Группа / Group | Назначение / Purpose | Примеры exports / Example exports |
|
|
@@ -120,7 +235,7 @@ monorepo alias or copied UI-kit files.
|
|
|
120
235
|
| Layout | App shell, dock regions, stacks, workbench layout | `layout/SAppShell.vue`, `layout/SStack.vue`, `layout/SWorkbenchLayout.vue` |
|
|
121
236
|
| Controls | Buttons, fields, inputs, switches, selects, comboboxes, menus | `shared/controls/SButton.vue`, `shared/controls/SSwitch.vue`, `shared/controls/SCombobox.vue` |
|
|
122
237
|
| Containers | Panels, modal, drawer, popover, sidebars | `shared/containers/SPanel.vue`, `shared/containers/SModal.vue`, `shared/containers/SPopover.vue` |
|
|
123
|
-
| Data display | Tables, charts, metric cards, chips, status, progress, code, JSON, tooltips | `shared/data-display/STable.vue`, `shared/data-display/SChart.vue`, `shared/data-display/
|
|
238
|
+
| Data display | Tables, charts, metric cards, scroll regions, chips, status, progress, code, JSON, tooltips | `shared/data-display/STable.vue`, `shared/data-display/SChart.vue`, `shared/data-display/SScrollViewport.vue` |
|
|
124
239
|
| Navigation | Tabs, breadcrumbs, catalog navigation, wizard | `shared/navigation/STabs.vue`, `shared/navigation/SBreadcrumbs.vue`, `shared/navigation/SWizardSteps.vue` |
|
|
125
240
|
| Complex surfaces | Tree, Kanban, data grid, SQL editor, graph | `shared/complex/STree.vue`, `shared/database/SDataGrid.vue`, `shared/graph/SGraphViewport.vue` |
|
|
126
241
|
| Runtime | Themes, variants, icons, composables, stores | `theme`, `variants`, `icons`, `composables/useNotifier`, `stores/useNotifierStore` |
|
|
@@ -264,6 +379,70 @@ already labelled card uses `accessibility.mode="decorative"` with
|
|
|
264
379
|
`data-table-presentation="none"`; a meaningful standalone chart keeps the
|
|
265
380
|
default assistive data table.
|
|
266
381
|
|
|
382
|
+
### Сравнение исходников / Source diff
|
|
383
|
+
|
|
384
|
+
`SDiffViewer` является semantic owner для exact-text diff. `before.text` и
|
|
385
|
+
`after.text` сравниваются без нормализации переводов строк или содержимого;
|
|
386
|
+
`label`, `revision` и `language` являются metadata. `layout="unified"` сохраняет
|
|
387
|
+
единый горизонтальный scroll для длинных строк, `layout="split"` показывает
|
|
388
|
+
равные колонки с переносом кода. `viewport` использует те же semantic размеры,
|
|
389
|
+
что и code surfaces.
|
|
390
|
+
|
|
391
|
+
`SDiffViewer` is the semantic owner for exact-text diff. `before.text` and
|
|
392
|
+
`after.text` are compared without newline or payload normalization; `label`,
|
|
393
|
+
`revision`, and `language` are metadata. `layout="unified"` preserves one
|
|
394
|
+
horizontal scroll surface for long lines, while `layout="split"` renders equal
|
|
395
|
+
columns with wrapped code. `viewport` uses the same semantic sizes as the code
|
|
396
|
+
surfaces.
|
|
397
|
+
|
|
398
|
+
```ts
|
|
399
|
+
import type {
|
|
400
|
+
SDiffResult,
|
|
401
|
+
SDiffSource,
|
|
402
|
+
} from '@pgcorp/ui-kit/shared/data-display/diff'
|
|
403
|
+
import SDiffViewer from '@pgcorp/ui-kit/shared/data-display/SDiffViewer.vue'
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
```vue
|
|
407
|
+
<SDiffViewer
|
|
408
|
+
v-model:expanded-gap-ids="expandedGapIds"
|
|
409
|
+
:before="baseSource"
|
|
410
|
+
:after="currentSource"
|
|
411
|
+
:context-lines="3"
|
|
412
|
+
layout="split"
|
|
413
|
+
viewport="expanded"
|
|
414
|
+
aria-label="Изменения конфигурации"
|
|
415
|
+
@computed="handleComputed"
|
|
416
|
+
@retry="handleRetry"
|
|
417
|
+
/>
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
`contextLines` задаёт число видимых неизменённых строк вокруг каждого hunk.
|
|
421
|
+
Без `expandedGapIds` компонент владеет раскрытием gap; с
|
|
422
|
+
`v-model:expanded-gap-ids` consumer применяет intent как controlled state.
|
|
423
|
+
`computed` передаёт валидированный `SDiffResult`, `retry` сообщает о повторном
|
|
424
|
+
запуске после ошибки. Для синхронного вычисления вне интерактивной поверхности
|
|
425
|
+
экспортируется `computeDiff(before, after, options)`.
|
|
426
|
+
|
|
427
|
+
`contextLines` selects the unchanged lines around each hunk. Without
|
|
428
|
+
`expandedGapIds`, the component owns gap expansion; with
|
|
429
|
+
`v-model:expanded-gap-ids`, the consumer applies expansion intents as controlled
|
|
430
|
+
state. `computed` provides a validated `SDiffResult`, and `retry` reports a
|
|
431
|
+
retry after an error. `computeDiff(before, after, options)` is exported for
|
|
432
|
+
synchronous computation outside an interactive surface.
|
|
433
|
+
|
|
434
|
+
Строки виртуализируются независимо от размера source. Дорогие интерактивные
|
|
435
|
+
вычисления выполняются через управляемый worker: смена source отменяет и
|
|
436
|
+
освобождает прежнюю работу, unmount освобождает активный worker, а результат
|
|
437
|
+
неактуального поколения не попадает в UI. Consumer не создаёт worker и не
|
|
438
|
+
управляет его жизненным циклом.
|
|
439
|
+
|
|
440
|
+
Lines are virtualized independently of source size. Expensive interactive
|
|
441
|
+
computations use a managed worker: source replacement cancels and releases the
|
|
442
|
+
previous job, unmount releases the active worker, and stale-generation results
|
|
443
|
+
never reach the UI. Consumers neither create the worker nor manage its
|
|
444
|
+
lifecycle.
|
|
445
|
+
|
|
267
446
|
### Действия chip и адаптивный header панели / Chip actions and responsive panel header
|
|
268
447
|
|
|
269
448
|
`SChip` принимает typed `surface` contract для статичного, action и link
|
package/docs/getting-started.md
CHANGED
|
@@ -39,6 +39,94 @@ import App from './App.vue'
|
|
|
39
39
|
createApp(App).use(createPinia()).use(router).mount('#app')
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
+
### Локаль UI-kit
|
|
43
|
+
|
|
44
|
+
Без provider UI-kit использует `ru`. Для локали конкретного Vue subtree
|
|
45
|
+
оберните его в DOM-less `SUiKitLocaleProvider`. Поддерживаются `en`, `ru`,
|
|
46
|
+
`zh-CN` и `zh-TW`:
|
|
47
|
+
|
|
48
|
+
```vue
|
|
49
|
+
<script setup lang="ts">
|
|
50
|
+
import SUiKitLocaleProvider from '@pgcorp/ui-kit/shared/containers/SUiKitLocaleProvider.vue'
|
|
51
|
+
import type { UiKitLocale } from '@pgcorp/ui-kit/composables/useUiKitLocale'
|
|
52
|
+
|
|
53
|
+
const locale: UiKitLocale = 'en'
|
|
54
|
+
</script>
|
|
55
|
+
|
|
56
|
+
<template>
|
|
57
|
+
<SUiKitLocaleProvider :locale="locale">
|
|
58
|
+
<AppWorkspace />
|
|
59
|
+
</SUiKitLocaleProvider>
|
|
60
|
+
</template>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Provider локализует только текст, принадлежащий UI-kit: labels controls,
|
|
64
|
+
assistive names, loading/empty copy и системные UI-сообщения. Доменные данные,
|
|
65
|
+
заголовки экранов и пользовательский контент передаются consumer-ом уже на
|
|
66
|
+
нужном языке. Вложенный provider наследует locale и messages ближайшего
|
|
67
|
+
родителя; prop `messages` принимает типизированный deep-partial override для
|
|
68
|
+
своего subtree. Неизвестная locale, неизвестный ключ override или неверные
|
|
69
|
+
параметры интерполяции завершаются явной диагностикой.
|
|
70
|
+
|
|
71
|
+
### Controlled-уведомления
|
|
72
|
+
|
|
73
|
+
`SControlledToastViewport` принимает readonly-массив сериализуемых records.
|
|
74
|
+
Consumer владеет ID, порядком, application state и durable history; viewport не
|
|
75
|
+
изменяет входной массив. Действия records содержат только ID, label и appearance,
|
|
76
|
+
без callback-полей.
|
|
77
|
+
|
|
78
|
+
```vue
|
|
79
|
+
<script setup lang="ts">
|
|
80
|
+
import { ref } from 'vue'
|
|
81
|
+
import SControlledToastViewport from '@pgcorp/ui-kit/shared/data-display/SControlledToastViewport.vue'
|
|
82
|
+
import type {
|
|
83
|
+
SToastActionIntent,
|
|
84
|
+
SToastDismissIntent,
|
|
85
|
+
SToastPresentation,
|
|
86
|
+
} from '@pgcorp/ui-kit/shared/data-display/toast'
|
|
87
|
+
|
|
88
|
+
const notifications = ref<readonly SToastPresentation[]>([
|
|
89
|
+
{
|
|
90
|
+
id: 'sync-ready',
|
|
91
|
+
severity: 'success',
|
|
92
|
+
title: 'Синхронизация завершена',
|
|
93
|
+
message: 'Данные рабочего пространства обновлены.',
|
|
94
|
+
actions: [{ id: 'open', label: 'Открыть', appearance: 'outline' }],
|
|
95
|
+
},
|
|
96
|
+
])
|
|
97
|
+
const selectedAction = ref<SToastActionIntent | null>(null)
|
|
98
|
+
|
|
99
|
+
function dismiss(intent: SToastDismissIntent): void {
|
|
100
|
+
notifications.value = notifications.value.filter(({ id }) => id !== intent.id)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function act(intent: SToastActionIntent): void {
|
|
104
|
+
selectedAction.value = intent
|
|
105
|
+
}
|
|
106
|
+
</script>
|
|
107
|
+
|
|
108
|
+
<template>
|
|
109
|
+
<SControlledToastViewport
|
|
110
|
+
:notifications="notifications"
|
|
111
|
+
accessible-label="Системные уведомления"
|
|
112
|
+
lifetime-owner="consumer"
|
|
113
|
+
position="top-end"
|
|
114
|
+
@dismiss="dismiss"
|
|
115
|
+
@action="act"
|
|
116
|
+
/>
|
|
117
|
+
</template>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
`lifetime-owner="consumer"` не создаёт auto-dismiss timers. В режиме
|
|
121
|
+
`viewport` record задаёт `durationMs`; истечение эмитит `lifetime-expired`, а
|
|
122
|
+
consumer удаляет record. Hover и focus приостанавливают оставшееся время.
|
|
123
|
+
Удаление record и unmount очищают связанные timers.
|
|
124
|
+
|
|
125
|
+
Для автономного сценария разместите `SToastContainer` один раз в app root и
|
|
126
|
+
вызывайте `useNotifier`. Его store принадлежит конкретному Pinia root, хранит
|
|
127
|
+
100 последних history records и очищает timers при `$dispose()` или `$reset()`.
|
|
128
|
+
Не создавайте локальную копию notifier store с тем же Pinia ID.
|
|
129
|
+
|
|
42
130
|
Каждый компонент импортируется через точный публичный subpath:
|
|
43
131
|
|
|
44
132
|
```ts
|
|
@@ -94,6 +182,53 @@ import App from './App.vue'
|
|
|
94
182
|
createApp(App).use(createPinia()).use(router).mount('#app')
|
|
95
183
|
```
|
|
96
184
|
|
|
185
|
+
### UI-kit locale
|
|
186
|
+
|
|
187
|
+
Without a provider, the UI kit uses `ru`. Wrap a Vue subtree in the DOM-less
|
|
188
|
+
`SUiKitLocaleProvider` to select its locale. Supported locales are `en`, `ru`,
|
|
189
|
+
`zh-CN`, and `zh-TW`:
|
|
190
|
+
|
|
191
|
+
```vue
|
|
192
|
+
<script setup lang="ts">
|
|
193
|
+
import SUiKitLocaleProvider from '@pgcorp/ui-kit/shared/containers/SUiKitLocaleProvider.vue'
|
|
194
|
+
import type { UiKitLocale } from '@pgcorp/ui-kit/composables/useUiKitLocale'
|
|
195
|
+
|
|
196
|
+
const locale: UiKitLocale = 'en'
|
|
197
|
+
</script>
|
|
198
|
+
|
|
199
|
+
<template>
|
|
200
|
+
<SUiKitLocaleProvider :locale="locale">
|
|
201
|
+
<AppWorkspace />
|
|
202
|
+
</SUiKitLocaleProvider>
|
|
203
|
+
</template>
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
The provider localizes UI-kit-owned copy only: control labels, assistive names,
|
|
207
|
+
loading and empty copy, and system UI messages. Domain data, screen titles, and
|
|
208
|
+
user content are supplied by the consumer in the required language. A nested
|
|
209
|
+
provider inherits the nearest parent's locale and messages; the `messages` prop
|
|
210
|
+
accepts a typed deep-partial override for that subtree. An unknown locale,
|
|
211
|
+
unknown override key, or invalid interpolation parameters fail with an explicit
|
|
212
|
+
diagnostic.
|
|
213
|
+
|
|
214
|
+
### Controlled notifications
|
|
215
|
+
|
|
216
|
+
`SControlledToastViewport` accepts a readonly array of serializable records.
|
|
217
|
+
The consumer owns IDs, ordering, application state, and durable history; the
|
|
218
|
+
viewport never mutates the input array. Record actions contain IDs, labels, and
|
|
219
|
+
an optional appearance without callback fields.
|
|
220
|
+
|
|
221
|
+
Use `lifetime-owner="consumer"` when the application owns expiry; this mode
|
|
222
|
+
creates no auto-dismiss timers. In `viewport` mode, a record supplies
|
|
223
|
+
`durationMs`, expiry emits `lifetime-expired`, and the consumer removes the
|
|
224
|
+
record. Hover and focus pause the remaining duration. Record removal and
|
|
225
|
+
component unmount release associated timers.
|
|
226
|
+
|
|
227
|
+
For the autonomous path, mount `SToastContainer` once at the application root
|
|
228
|
+
and call `useNotifier`. Its store belongs to one Pinia root, retains 100 history
|
|
229
|
+
records, and clears timers on `$dispose()` or `$reset()`. Do not create a local
|
|
230
|
+
notifier store with the same Pinia ID.
|
|
231
|
+
|
|
97
232
|
Import every component through an exact public subpath:
|
|
98
233
|
|
|
99
234
|
```ts
|
package/docs/public-api.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
- `shared/data-display/*` — badges, tables, code, JSON, progress, status и tooltips;
|
|
14
14
|
- `shared/navigation/*` — tabs, breadcrumbs, catalog navigation и wizard steps;
|
|
15
15
|
- `shared/database/*`, `shared/graph/*`, `shared/persona/*` — доменные сложные поверхности;
|
|
16
|
-
- `composables/*`, `stores/*`, `theme`, `variants`, `icons` — typed runtime modules;
|
|
16
|
+
- `composables/*`, `stores/*`, `theme`, `variants`, `icons` — typed runtime modules, включая locale context;
|
|
17
17
|
- `tailwind.css` — полный Tailwind 4 integration entrypoint;
|
|
18
18
|
- `style.css`, `tokens.css`, `reference.css` — global styles, token-only и compile-time reference entrypoints.
|
|
19
19
|
|
|
@@ -27,7 +27,12 @@ compiler регистрирует их без межфайлового filesyste
|
|
|
27
27
|
Публикуемый production-source компилируется с `target/lib: ES2020`, совпадающим
|
|
28
28
|
с baseline `@vue/tsconfig/tsconfig.dom.json`, и не требует скрытых полифиллов.
|
|
29
29
|
Типы таблицы импортируются из `shared/data-display/table`, типы графиков — из
|
|
30
|
-
`shared/data-display/chart
|
|
30
|
+
`shared/data-display/chart`, типы и чистая функция diff — из
|
|
31
|
+
`shared/data-display/diff`. `SDiffViewer` принимает exact-text snapshots,
|
|
32
|
+
показывает unified/split представление, виртуализирует строки и управляет
|
|
33
|
+
вычислением в worker для больших входов. Смена source и unmount отменяют
|
|
34
|
+
неактуальную работу; завершившийся устаревший результат не публикуется.
|
|
35
|
+
`SChart` объединяет line/area/bar/pie/donut,
|
|
31
36
|
responsive geometry, semantic palette и доступную таблицу данных. `SMetricCard`
|
|
32
37
|
принимает компактный график через `#chart`. `SCodeBlock` сохраняет CodeMirror за
|
|
33
38
|
async boundary; `presentation="plain"` является lightweight read-only контрактом
|
|
@@ -37,6 +42,25 @@ async boundary; `presentation="plain"` является lightweight read-only к
|
|
|
37
42
|
`SActionListItem` держат primary activation и дополнительные controls
|
|
38
43
|
sibling-элементами внутри одного chrome; `actionsLayout`/`trailingLayout`
|
|
39
44
|
управляют inline, stacked и container-responsive раскладкой.
|
|
45
|
+
`SUiKitLocaleProvider` задаёт `en | ru | zh-CN | zh-TW` для одного Vue subtree,
|
|
46
|
+
а `composables/useUiKitLocale` экспортирует readonly context, полный список
|
|
47
|
+
локалей и типы messages/overrides/ключей. Provider не создаёт DOM owner и
|
|
48
|
+
поддерживает независимые локали в соседних app roots.
|
|
49
|
+
`shared/data-display/SControlledToastViewport.vue` является controlled owner
|
|
50
|
+
стека уведомлений; `shared/data-display/toast` экспортирует presentation records,
|
|
51
|
+
action/dismiss/lifetime intents, position и lifetime types. `SToastContainer`
|
|
52
|
+
является adapter над `stores/useNotifierStore`, а не вторым layout owner.
|
|
53
|
+
`shared/data-display/SRichDocument.vue` отображает только валидированную
|
|
54
|
+
`SRichDocumentV1` AST. `shared/data-display/richDocument` экспортирует закрытую
|
|
55
|
+
модель, consumer-owned resource records, typed intents и validators со stable
|
|
56
|
+
error code/path. Link-node поддерживает `current: true` для
|
|
57
|
+
`aria-current="page"`. Raw HTML, VNodes, callbacks и trust flags не входят в
|
|
58
|
+
API.
|
|
59
|
+
`shared/data-display/SScrollViewport.vue` владеет accessible scroll region,
|
|
60
|
+
разрешёнными осями, semantic block size, root-only keyboard navigation и
|
|
61
|
+
ResizeObserver lifecycle. `shared/data-display/scrollViewport` экспортирует
|
|
62
|
+
сериализуемое physical/semantic state и exposed API `focus`,
|
|
63
|
+
`scrollToBoundary`, `reveal` без доступа к внутреннему DOM.
|
|
40
64
|
|
|
41
65
|
## English
|
|
42
66
|
|
|
@@ -51,7 +75,7 @@ Primary groups:
|
|
|
51
75
|
- `shared/data-display/*` — badges, tables, code, JSON, progress, status, and tooltips;
|
|
52
76
|
- `shared/navigation/*` — tabs, breadcrumbs, catalog navigation, and wizard steps;
|
|
53
77
|
- `shared/database/*`, `shared/graph/*`, `shared/persona/*` — complex domain surfaces;
|
|
54
|
-
- `composables/*`, `stores/*`, `theme`, `variants`, `icons` — typed runtime modules;
|
|
78
|
+
- `composables/*`, `stores/*`, `theme`, `variants`, `icons` — typed runtime modules, including locale context;
|
|
55
79
|
- `tailwind.css` — the complete Tailwind 4 integration entrypoint;
|
|
56
80
|
- `style.css`, `tokens.css`, `reference.css` — global styles, token-only, and compile-time reference entrypoints.
|
|
57
81
|
|
|
@@ -65,7 +89,12 @@ compiler registers them without a cross-file filesystem type resolver.
|
|
|
65
89
|
Published production source compiles with the `target/lib: ES2020` baseline from
|
|
66
90
|
`@vue/tsconfig/tsconfig.dom.json` and does not require implicit polyfills.
|
|
67
91
|
Table types are imported from `shared/data-display/table`; chart types are
|
|
68
|
-
imported from `shared/data-display/chart
|
|
92
|
+
imported from `shared/data-display/chart`; diff types and its pure computation
|
|
93
|
+
function are imported from `shared/data-display/diff`. `SDiffViewer` accepts
|
|
94
|
+
exact-text snapshots, renders unified or split presentation, virtualizes lines,
|
|
95
|
+
and manages worker computation for large inputs. Source replacement and unmount
|
|
96
|
+
cancel obsolete work, and a completed stale result is never published.
|
|
97
|
+
`SChart` unifies
|
|
69
98
|
line/area/bar/pie/donut charts, responsive geometry, the semantic palette, and
|
|
70
99
|
an accessible data table. `SMetricCard` accepts a compact chart through
|
|
71
100
|
`#chart`. `SCodeBlock` keeps CodeMirror behind an async boundary;
|
|
@@ -76,3 +105,23 @@ the editor runtime. `SChip.surface` owns action/link semantics, while
|
|
|
76
105
|
compositions keep primary activation and additional controls as siblings inside
|
|
77
106
|
one chrome; `actionsLayout`/`trailingLayout` control inline, stacked, and
|
|
78
107
|
container-responsive layout.
|
|
108
|
+
`SUiKitLocaleProvider` selects `en | ru | zh-CN | zh-TW` for one Vue subtree,
|
|
109
|
+
while `composables/useUiKitLocale` exports the readonly context, the complete
|
|
110
|
+
locale list, and message/override/key types. The provider renders no DOM owner
|
|
111
|
+
and supports independent locales in adjacent application roots.
|
|
112
|
+
`shared/data-display/SControlledToastViewport.vue` is the controlled owner of
|
|
113
|
+
the notification stack; `shared/data-display/toast` exports presentation
|
|
114
|
+
records, action/dismiss/lifetime intents, positions, and lifetime types.
|
|
115
|
+
`SToastContainer` is an adapter over `stores/useNotifierStore`, not a second
|
|
116
|
+
layout owner.
|
|
117
|
+
`shared/data-display/SRichDocument.vue` renders validated `SRichDocumentV1` AST
|
|
118
|
+
only. `shared/data-display/richDocument` exports the closed model,
|
|
119
|
+
consumer-owned resource records, typed intents, and validators with stable
|
|
120
|
+
error code/path diagnostics. Link nodes support `current: true` for
|
|
121
|
+
`aria-current="page"`. Raw HTML, VNodes, callbacks, and trust flags are not part
|
|
122
|
+
of the API.
|
|
123
|
+
`shared/data-display/SScrollViewport.vue` owns the accessible scroll region,
|
|
124
|
+
enabled axes, semantic block size, root-only keyboard navigation, and
|
|
125
|
+
ResizeObserver lifecycle. `shared/data-display/scrollViewport` exports
|
|
126
|
+
serializable physical and semantic state plus the `focus`, `scrollToBoundary`,
|
|
127
|
+
and `reveal` exposed API without access to internal DOM.
|