@pgcorp/ui-kit 0.8.1 → 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.
Files changed (113) hide show
  1. package/README.md +332 -9
  2. package/docs/getting-started.md +135 -0
  3. package/docs/public-api.md +53 -4
  4. package/docs/rich-document.md +216 -0
  5. package/docs/scroll-viewport.md +167 -0
  6. package/docs/theming.md +17 -0
  7. package/package.json +108 -50
  8. package/src/components/layout/SAppShell.vue +3 -1
  9. package/src/components/layout/SDockRegion.vue +5 -3
  10. package/src/components/layout/SResizeHandle.vue +45 -5
  11. package/src/components/layout/SWorkbenchPanelShell.vue +4 -2
  12. package/src/components/shared/_internal/SDialogSurface.css +23 -0
  13. package/src/components/shared/_internal/SDialogSurface.vue +9 -2
  14. package/src/components/shared/_internal/SToastItem.css +4 -0
  15. package/src/components/shared/_internal/SToastItem.vue +44 -8
  16. package/src/components/shared/_internal/STreeNode.vue +24 -11
  17. package/src/components/shared/_internal/dialogSurface.ts +7 -1
  18. package/src/components/shared/complex/SKanbanLane.vue +4 -2
  19. package/src/components/shared/containers/SCloudChromeRow.vue +3 -2
  20. package/src/components/shared/containers/SDrawer.css +11 -2
  21. package/src/components/shared/containers/SDrawer.vue +48 -9
  22. package/src/components/shared/containers/SModal.vue +5 -2
  23. package/src/components/shared/containers/SPanel.vue +4 -2
  24. package/src/components/shared/containers/SPopover.vue +7 -3
  25. package/src/components/shared/containers/SUiKitLocaleProvider.vue +57 -0
  26. package/src/components/shared/controls/SButton.css +14 -10
  27. package/src/components/shared/controls/SCombobox.vue +8 -6
  28. package/src/components/shared/controls/SComboboxTrigger.css +7 -4
  29. package/src/components/shared/controls/SComboboxTrigger.vue +5 -2
  30. package/src/components/shared/controls/SContextToggleButton.vue +6 -4
  31. package/src/components/shared/controls/SDragHandle.vue +8 -4
  32. package/src/components/shared/controls/SDropdownMenu.vue +7 -4
  33. package/src/components/shared/controls/SInputText.css +5 -4
  34. package/src/components/shared/controls/SListbox.vue +4 -2
  35. package/src/components/shared/controls/SSelect.vue +4 -2
  36. package/src/components/shared/controls/STextarea.ts +13 -0
  37. package/src/components/shared/controls/STextarea.vue +391 -37
  38. package/src/components/shared/controls/_internal/SInlineTokenSurface.vue +4 -2
  39. package/src/components/shared/data-display/SChart.vue +7 -5
  40. package/src/components/shared/data-display/SChip.vue +3 -1
  41. package/src/components/shared/data-display/SCodeBlock.css +4 -0
  42. package/src/components/shared/data-display/SCodeBlock.vue +46 -22
  43. package/src/components/shared/data-display/SCodeEditor.css +17 -0
  44. package/src/components/shared/data-display/SCodeEditor.vue +173 -8
  45. package/src/components/shared/data-display/SCodeSearchPanel.vue +48 -33
  46. package/src/components/shared/data-display/SCodeWorkspaceEditor.css +13 -0
  47. package/src/components/shared/data-display/SCodeWorkspaceEditor.vue +355 -0
  48. package/src/components/shared/data-display/SControlledToastViewport.css +89 -0
  49. package/src/components/shared/data-display/SControlledToastViewport.vue +205 -0
  50. package/src/components/shared/data-display/SCopyField.vue +12 -10
  51. package/src/components/shared/data-display/SDiffViewer.css +122 -0
  52. package/src/components/shared/data-display/SDiffViewer.vue +499 -0
  53. package/src/components/shared/data-display/SDocBlock.vue +99 -71
  54. package/src/components/shared/data-display/SExpandableText.vue +10 -8
  55. package/src/components/shared/data-display/SJsonTree.vue +4 -2
  56. package/src/components/shared/data-display/SLinkedSystemsList.vue +4 -2
  57. package/src/components/shared/data-display/SMessage.vue +6 -6
  58. package/src/components/shared/data-display/SRichDocument.css +8 -0
  59. package/src/components/shared/data-display/SRichDocument.vue +65 -0
  60. package/src/components/shared/data-display/SScrollViewport.css +53 -0
  61. package/src/components/shared/data-display/SScrollViewport.vue +470 -0
  62. package/src/components/shared/data-display/STable.vue +38 -19
  63. package/src/components/shared/data-display/SToastContainer.vue +22 -17
  64. package/src/components/shared/data-display/SVirtualList.ts +33 -0
  65. package/src/components/shared/data-display/SVirtualList.vue +321 -36
  66. package/src/components/shared/data-display/_internal/SCodeTokenLine.css +72 -0
  67. package/src/components/shared/data-display/_internal/SCodeTokenLine.vue +79 -0
  68. package/src/components/shared/data-display/_internal/SRichBlockNode.css +85 -0
  69. package/src/components/shared/data-display/_internal/SRichBlockNode.vue +282 -0
  70. package/src/components/shared/data-display/_internal/SRichInlineNode.css +6 -0
  71. package/src/components/shared/data-display/_internal/SRichInlineNode.vue +76 -0
  72. package/src/components/shared/data-display/_internal/SRichMath.css +42 -0
  73. package/src/components/shared/data-display/_internal/SRichMath.vue +102 -0
  74. package/src/components/shared/data-display/codeEditor.ts +200 -0
  75. package/src/components/shared/data-display/codeWorkspace.ts +233 -0
  76. package/src/components/shared/data-display/diff.ts +541 -0
  77. package/src/components/shared/data-display/richDocument.ts +876 -0
  78. package/src/components/shared/data-display/scrollViewport.ts +47 -0
  79. package/src/components/shared/data-display/toast.ts +194 -0
  80. package/src/components/shared/database/SDataGrid.vue +7 -4
  81. package/src/components/shared/database/SSqlEditor.vue +39 -39
  82. package/src/components/shared/feedback/SAsyncState.vue +3 -1
  83. package/src/components/shared/graph/SGraphViewport.vue +11 -9
  84. package/src/components/shared/navigation/SBreadcrumbs.vue +8 -5
  85. package/src/components/shared/navigation/SCatalogNavigator.vue +26 -20
  86. package/src/components/shared/navigation/STabList.vue +10 -6
  87. package/src/components/shared/navigation/STabs.vue +15 -11
  88. package/src/components/shared/navigation/SWizardSteps.vue +4 -2
  89. package/src/components/shared/persona/SPersonaProjectPicker.vue +31 -27
  90. package/src/components/shared/persona/SPersonaRunWorkbench.vue +39 -33
  91. package/src/components/shared/persona/_internal/SPersonaRunConsole.vue +8 -6
  92. package/src/components/shared/persona/_internal/labels.ts +66 -57
  93. package/src/components/shared/persona/presentation.ts +140 -110
  94. package/src/composables/useFloatingPosition.ts +39 -2
  95. package/src/composables/useUiKitLocale.ts +17 -0
  96. package/src/internal/codeHighlight.ts +110 -0
  97. package/src/internal/diffEngine.ts +464 -0
  98. package/src/internal/diffRuntime.ts +189 -0
  99. package/src/internal/feedbackPresentation.ts +33 -14
  100. package/src/internal/localeContext.ts +22 -0
  101. package/src/internal/ownedAttrs.ts +8 -0
  102. package/src/internal/runtimeContract.ts +11 -9
  103. package/src/internal/semanticSizing.ts +13 -0
  104. package/src/locales/catalog.ts +634 -0
  105. package/src/locales/locale.ts +472 -0
  106. package/src/locales/messages.generated.ts +1826 -0
  107. package/src/locales/messages.ts +150 -0
  108. package/src/stores/useNotifierStore.ts +61 -44
  109. package/src/styles/tokens.css +23 -2
  110. package/src/theme.ts +59 -32
  111. package/src/workers/diff.worker.ts +73 -0
  112. package/src/workers/diffProtocol.ts +155 -0
  113. package/src/components/shared/data-display/SToastContainer.css +0 -53
@@ -1,6 +1,8 @@
1
1
  import type { Component } from 'vue'
2
2
 
3
3
  import { AlertTriangle, CheckCircle2, Info, LoaderCircle, XCircle } from '../components/icons/sputnigUiIcons'
4
+ import { createUiKitTranslate, UI_KIT_MESSAGES } from '../locales/messages'
5
+ import type { UiKitStaticMessageKey, UiKitTranslate } from '../locales/locale'
4
6
 
5
7
  export type FeedbackTone = 'neutral' | 'info' | 'success' | 'warn' | 'danger'
6
8
  export type FeedbackSeverity = Exclude<FeedbackTone, 'neutral'>
@@ -37,20 +39,35 @@ export interface FeedbackIndicatorPresentation {
37
39
  readonly motion: 'static' | 'spin'
38
40
  }
39
41
 
40
- const presentations: Readonly<Record<FeedbackTone, Readonly<FeedbackPresentation>>> = {
41
- neutral: { icon: Info, iconName: 'info', fallbackTitle: 'Статус' },
42
- info: { icon: Info, iconName: 'info', fallbackTitle: 'Информация' },
43
- success: { icon: CheckCircle2, iconName: 'check-circle', fallbackTitle: 'Успех' },
44
- warn: { icon: AlertTriangle, iconName: 'alert-triangle', fallbackTitle: 'Предупреждение' },
45
- danger: { icon: XCircle, iconName: 'x-circle', fallbackTitle: 'Ошибка' },
42
+ interface FeedbackPresentationSeed {
43
+ readonly icon: Component
44
+ readonly iconName: FeedbackPresentation['iconName']
45
+ readonly fallbackTitleKey: UiKitStaticMessageKey
46
+ }
47
+
48
+ const presentations: Readonly<Record<FeedbackTone, FeedbackPresentationSeed>> = {
49
+ neutral: { icon: Info, iconName: 'info', fallbackTitleKey: 'feedback.titleStatus' },
50
+ info: { icon: Info, iconName: 'info', fallbackTitleKey: 'feedback.titleInformation' },
51
+ success: { icon: CheckCircle2, iconName: 'check-circle', fallbackTitleKey: 'feedback.titleSuccess' },
52
+ warn: { icon: AlertTriangle, iconName: 'alert-triangle', fallbackTitleKey: 'feedback.titleWarning' },
53
+ danger: { icon: XCircle, iconName: 'x-circle', fallbackTitleKey: 'feedback.titleError' },
46
54
  }
55
+ const defaultTranslate = createUiKitTranslate(() => UI_KIT_MESSAGES.ru)
47
56
 
48
57
  /**
49
58
  * Возвращает единую icon/title-презентацию для feedback tone.
50
59
  * Returns the canonical icon/title presentation for a feedback tone.
51
60
  */
52
- export function resolveFeedbackPresentation(tone: FeedbackTone): Readonly<FeedbackPresentation> {
53
- return presentations[tone]
61
+ export function resolveFeedbackPresentation(
62
+ tone: FeedbackTone,
63
+ t: UiKitTranslate = defaultTranslate,
64
+ ): Readonly<FeedbackPresentation> {
65
+ const presentation = presentations[tone]
66
+ return {
67
+ icon: presentation.icon,
68
+ iconName: presentation.iconName,
69
+ fallbackTitle: t(presentation.fallbackTitleKey),
70
+ }
54
71
  }
55
72
 
56
73
  /**
@@ -59,17 +76,18 @@ export function resolveFeedbackPresentation(tone: FeedbackTone): Readonly<Feedba
59
76
  */
60
77
  export function resolveFeedbackIndicator(
61
78
  state: FeedbackIndicatorState,
79
+ t: UiKitTranslate = defaultTranslate,
62
80
  ): Readonly<FeedbackIndicatorPresentation> {
63
81
  if (state === 'progress') {
64
82
  return {
65
83
  tone: 'info',
66
84
  icon: LoaderCircle,
67
85
  iconName: 'loader-circle',
68
- fallbackTitle: 'Выполняется',
86
+ fallbackTitle: t('feedback.titleRunning'),
69
87
  motion: 'spin',
70
88
  }
71
89
  }
72
- const presentation = resolveFeedbackPresentation(state)
90
+ const presentation = resolveFeedbackPresentation(state, t)
73
91
  return {
74
92
  tone: state,
75
93
  icon: presentation.icon,
@@ -102,14 +120,15 @@ export function resolveFeedbackLive(
102
120
  */
103
121
  export function resolveAsyncFeedbackPresentation(
104
122
  status: AsyncFeedbackStatus,
123
+ t: UiKitTranslate = defaultTranslate,
105
124
  ): Readonly<AsyncFeedbackPresentation> {
106
125
  if (status === 'loading') {
107
- const progress = resolveFeedbackIndicator('progress')
126
+ const progress = resolveFeedbackIndicator('progress', t)
108
127
  return {
109
128
  tone: progress.tone,
110
129
  icon: progress.icon,
111
130
  iconName: progress.iconName,
112
- fallbackMessage: 'Загрузка…',
131
+ fallbackMessage: t('feedback.loading'),
113
132
  busy: true,
114
133
  live: resolveFeedbackLive(progress.tone, 'auto'),
115
134
  }
@@ -119,12 +138,12 @@ export function resolveAsyncFeedbackPresentation(
119
138
  tone: 'neutral',
120
139
  icon: null,
121
140
  iconName: null,
122
- fallbackMessage: 'Нет данных для отображения.',
141
+ fallbackMessage: t('feedback.empty'),
123
142
  busy: false,
124
143
  live: resolveFeedbackLive('neutral', 'auto'),
125
144
  }
126
145
  }
127
- const error = resolveFeedbackIndicator('danger')
146
+ const error = resolveFeedbackIndicator('danger', t)
128
147
  return {
129
148
  tone: 'danger',
130
149
  icon: error.icon,
@@ -0,0 +1,22 @@
1
+ import { computed, inject, type ComputedRef, type InjectionKey } from 'vue'
2
+
3
+ import { createUiKitTranslate, UI_KIT_MESSAGES } from '../locales/messages'
4
+ import type { UiKitLocale, UiKitMessages, UiKitTranslate } from '../locales/locale'
5
+
6
+ export interface UiKitLocaleContext {
7
+ readonly locale: ComputedRef<UiKitLocale>
8
+ readonly messages: ComputedRef<Readonly<UiKitMessages>>
9
+ readonly t: UiKitTranslate
10
+ }
11
+
12
+ export const UI_KIT_LOCALE_CONTEXT: InjectionKey<UiKitLocaleContext> = Symbol('SUiKitLocaleProvider')
13
+
14
+ export function createDefaultUiKitLocaleContext(): UiKitLocaleContext {
15
+ const locale = computed<UiKitLocale>(() => 'ru')
16
+ const messages = computed<Readonly<UiKitMessages>>(() => UI_KIT_MESSAGES.ru)
17
+ return Object.freeze({ locale, messages, t: createUiKitTranslate(() => messages.value) })
18
+ }
19
+
20
+ export function resolveUiKitLocaleContext(): UiKitLocaleContext {
21
+ return inject(UI_KIT_LOCALE_CONTEXT, null) ?? createDefaultUiKitLocaleContext()
22
+ }
@@ -73,6 +73,7 @@ export const ownedAttributeSchemas = Object.freeze({
73
73
  'data-testid': 'data',
74
74
  }),
75
75
  SPageHeader: defineOwnedAttributeSchema({}),
76
+ SUiKitLocaleProvider: defineOwnedAttributeSchema({}),
76
77
  SPanel: defineOwnedAttributeSchema({
77
78
  'data-testid': 'data',
78
79
  }),
@@ -268,6 +269,12 @@ export const ownedAttributeSchemas = Object.freeze({
268
269
  'aria-labelledby': 'string',
269
270
  autofocus: 'boolean-attribute',
270
271
  }),
272
+ SCodeWorkspaceEditor: defineOwnedAttributeSchema({}),
273
+ SDiffViewer: defineOwnedAttributeSchema({}),
274
+ SRichDocument: defineOwnedAttributeSchema({}),
275
+ SScrollViewport: defineOwnedAttributeSchema({
276
+ 'data-testid': 'data',
277
+ }),
271
278
  SCodeSearchPanel: defineOwnedAttributeSchema({}),
272
279
  SCopyField: defineOwnedAttributeSchema({}),
273
280
  SDocBlock: defineOwnedAttributeSchema({}),
@@ -288,6 +295,7 @@ export const ownedAttributeSchemas = Object.freeze({
288
295
  SSectionHeader: defineOwnedAttributeSchema({}),
289
296
  SStatus: defineOwnedAttributeSchema({}),
290
297
  STable: defineOwnedAttributeSchema({}),
298
+ SControlledToastViewport: defineOwnedAttributeSchema({}),
291
299
  SToastContainer: defineOwnedAttributeSchema({}),
292
300
  STooltip: defineOwnedAttributeSchema({}),
293
301
  STooltipAnchor: defineOwnedAttributeSchema({
@@ -28,15 +28,17 @@ function assertBoundedDomain(
28
28
  || (Number.isInteger(domain.minimum) && Number.isInteger(domain.maximum))
29
29
  if (validNumbers && validIntegerBounds && domain.minimum <= domain.maximum) return
30
30
 
31
- const russianKind = integer ? 'целыми числами' : 'конечными числами'
32
- const englishKind = integer ? 'integers' : 'finite numbers'
33
- throw new TypeError(
34
- `runtimeContract: границы domain для ${owner}.${coordinate} должны быть ${russianKind}, `
35
- + `где minimum <= maximum; получено minimum=${describeRuntimeValue(domain.minimum)}, `
36
- + `maximum=${describeRuntimeValue(domain.maximum)}. / runtimeContract: domain bounds for `
37
- + `${owner}.${coordinate} must be ${englishKind} with minimum <= maximum; received `
38
- + `minimum=${describeRuntimeValue(domain.minimum)}, maximum=${describeRuntimeValue(domain.maximum)}.`,
39
- )
31
+ throw new TypeError(integer
32
+ ? `runtimeContract: границы domain для ${owner}.${coordinate} должны быть целыми числами, `
33
+ + `где minimum <= maximum; получено minimum=${describeRuntimeValue(domain.minimum)}, `
34
+ + `maximum=${describeRuntimeValue(domain.maximum)}. / runtimeContract: domain bounds for `
35
+ + `${owner}.${coordinate} must be integers with minimum <= maximum; received `
36
+ + `minimum=${describeRuntimeValue(domain.minimum)}, maximum=${describeRuntimeValue(domain.maximum)}.`
37
+ : `runtimeContract: границы domain для ${owner}.${coordinate} должны быть конечными числами, `
38
+ + `где minimum <= maximum; получено minimum=${describeRuntimeValue(domain.minimum)}, `
39
+ + `maximum=${describeRuntimeValue(domain.maximum)}. / runtimeContract: domain bounds for `
40
+ + `${owner}.${coordinate} must be finite numbers with minimum <= maximum; received `
41
+ + `minimum=${describeRuntimeValue(domain.minimum)}, maximum=${describeRuntimeValue(domain.maximum)}.`)
40
42
  }
41
43
 
42
44
  function assertExactStringDomain(
@@ -1,6 +1,7 @@
1
1
  import { validateExactString } from './runtimeContract'
2
2
 
3
3
  const SCROLLABLE_VIEWPORT_MAX_BLOCK_SIZES = ['none', 'sm', 'md', 'lg'] as const
4
+ const SCROLL_VIEWPORT_BLOCK_SIZES = ['sm', 'md', 'lg', 'fill'] as const
4
5
  const EXPANDED_CONTENT_MAX_BLOCK_SIZES = ['sm', 'md', 'lg'] as const
5
6
  const TABLE_COLUMN_INLINE_SIZES = ['auto', 'content', '2xs', 'xs', 'sm', 'md', 'lg', 'xl', 'fill'] as const
6
7
  const TABLE_COLUMN_MIN_INLINE_SIZES = ['2xs', 'xs', 'sm', 'md', 'lg', 'xl'] as const
@@ -11,6 +12,9 @@ const TABLE_COLUMN_MIN_INLINE_SIZES = ['2xs', 'xs', 'sm', 'md', 'lg', 'xl'] as c
11
12
  */
12
13
  export type ScrollableViewportMaxBlockSize = typeof SCROLLABLE_VIEWPORT_MAX_BLOCK_SIZES[number]
13
14
 
15
+ /** Фиксированная semantic block-size рабочей scroll-области. / Fixed semantic block size of a scroll workspace. */
16
+ export type ScrollViewportBlockSize = typeof SCROLL_VIEWPORT_BLOCK_SIZES[number]
17
+
14
18
  /**
15
19
  * Максимальный block-size раскрытого текстового content region.
16
20
  * Maximum block size for an expanded textual content region.
@@ -32,6 +36,15 @@ export function validateScrollableViewportMaxBlockSize(
32
36
  return validateExactString(owner, coordinate, value, SCROLLABLE_VIEWPORT_MAX_BLOCK_SIZES)
33
37
  }
34
38
 
39
+ /** Проверяет semantic scroll-workspace size без raw CSS-length. / Validates a semantic scroll-workspace size without a raw CSS length. */
40
+ export function validateScrollViewportBlockSize(
41
+ owner: string,
42
+ coordinate: string,
43
+ value: unknown,
44
+ ): ScrollViewportBlockSize {
45
+ return validateExactString(owner, coordinate, value, SCROLL_VIEWPORT_BLOCK_SIZES)
46
+ }
47
+
35
48
  /** Проверяет semantic expanded-content size без CSS-length escape. / Validates a semantic expanded-content size without a CSS-length escape. */
36
49
  export function validateExpandedContentMaxBlockSize(
37
50
  owner: string,