@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
|
@@ -1,33 +1,33 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<section v-bind="ownedAttrs.bindings()" class="s-catalog-navigator" :aria-label="
|
|
2
|
+
<section v-bind="ownedAttrs.bindings()" class="s-catalog-navigator" :aria-label="resolvedAriaLabel">
|
|
3
3
|
<div class="s-catalog-navigator__toolbar">
|
|
4
4
|
<SInputText
|
|
5
5
|
v-model="query"
|
|
6
6
|
size="sm"
|
|
7
|
-
:placeholder="
|
|
8
|
-
:aria-label="
|
|
7
|
+
:placeholder="resolvedSearchPlaceholder"
|
|
8
|
+
:aria-label="resolvedSearchPlaceholder"
|
|
9
9
|
/>
|
|
10
10
|
<SSelect
|
|
11
11
|
v-model="selectedGroup"
|
|
12
12
|
size="sm"
|
|
13
13
|
:options="groupOptions"
|
|
14
|
-
:label="
|
|
14
|
+
:label="resolvedGroupFilterLabel"
|
|
15
15
|
/>
|
|
16
16
|
<SSelect
|
|
17
17
|
v-model="sortMode"
|
|
18
18
|
size="sm"
|
|
19
19
|
:options="sortOptions"
|
|
20
|
-
label="
|
|
20
|
+
:label="t('navigation.sort')"
|
|
21
21
|
/>
|
|
22
22
|
</div>
|
|
23
23
|
|
|
24
24
|
<div class="s-catalog-navigator__summary" aria-live="polite">
|
|
25
|
-
|
|
25
|
+
{{ t('navigation.found') }} {{ filteredItemCount }} {{ t('navigation.of') }} {{ items.length }}
|
|
26
26
|
</div>
|
|
27
27
|
|
|
28
|
-
<div class="s-catalog-navigator__viewport" role="region" :aria-label="
|
|
28
|
+
<div class="s-catalog-navigator__viewport" role="region" :aria-label="t('navigation.catalogItems', { catalog: resolvedAriaLabel })">
|
|
29
29
|
<div v-if="groupedItems.length === 0" class="s-catalog-navigator__empty">
|
|
30
|
-
{{
|
|
30
|
+
{{ resolvedEmptyText }}
|
|
31
31
|
</div>
|
|
32
32
|
<template v-else>
|
|
33
33
|
<SCatalogNavigatorGroup
|
|
@@ -81,6 +81,7 @@ import SButton from '../controls/SButton.vue';
|
|
|
81
81
|
import SBadge from '../data-display/SBadge.vue';
|
|
82
82
|
import SCatalogNavigatorGroup from './_internal/SCatalogNavigatorGroup.vue';
|
|
83
83
|
import { useOwnedAttrs } from '../../../internal/ownedAttrs';
|
|
84
|
+
import { useUiKitLocale } from '../../../composables/useUiKitLocale';
|
|
84
85
|
|
|
85
86
|
defineOptions({ inheritAttrs: false });
|
|
86
87
|
|
|
@@ -104,11 +105,16 @@ const props = withDefaults(defineProps<{
|
|
|
104
105
|
emptyText?: string;
|
|
105
106
|
}>(), {
|
|
106
107
|
selectedId: null,
|
|
107
|
-
ariaLabel:
|
|
108
|
-
searchPlaceholder:
|
|
109
|
-
groupFilterLabel:
|
|
110
|
-
emptyText:
|
|
108
|
+
ariaLabel: undefined,
|
|
109
|
+
searchPlaceholder: undefined,
|
|
110
|
+
groupFilterLabel: undefined,
|
|
111
|
+
emptyText: undefined,
|
|
111
112
|
});
|
|
113
|
+
const { locale, t } = useUiKitLocale();
|
|
114
|
+
const resolvedAriaLabel = computed(() => props.ariaLabel ?? t('navigation.catalog'));
|
|
115
|
+
const resolvedSearchPlaceholder = computed(() => props.searchPlaceholder ?? t('actions.search'));
|
|
116
|
+
const resolvedGroupFilterLabel = computed(() => props.groupFilterLabel ?? t('navigation.group'));
|
|
117
|
+
const resolvedEmptyText = computed(() => props.emptyText ?? t('navigation.noResults'));
|
|
112
118
|
|
|
113
119
|
const emit = defineEmits<{
|
|
114
120
|
(event: 'select', id: string): void;
|
|
@@ -240,19 +246,19 @@ function groupDisclosureId(groupKey: string): string {
|
|
|
240
246
|
}
|
|
241
247
|
|
|
242
248
|
const groupOptions = computed(() => [
|
|
243
|
-
{ value: ALL_GROUP_FILTER, label: '
|
|
249
|
+
{ value: ALL_GROUP_FILTER, label: t('navigation.allGroups') },
|
|
244
250
|
...[...catalogInventory.value.groups]
|
|
245
|
-
.sort((left, right) => left.label.localeCompare(right.label,
|
|
251
|
+
.sort((left, right) => left.label.localeCompare(right.label, locale.value))
|
|
246
252
|
.map((group) => ({ value: group.filterValue, label: group.label })),
|
|
247
253
|
]);
|
|
248
254
|
|
|
249
|
-
const sortOptions = [
|
|
250
|
-
{ value: 'title-asc', label: '
|
|
251
|
-
{ value: 'title-desc', label: '
|
|
252
|
-
{ value: 'id-asc', label: '
|
|
253
|
-
];
|
|
255
|
+
const sortOptions = computed(() => [
|
|
256
|
+
{ value: 'title-asc', label: t('navigation.sortNameAscending') },
|
|
257
|
+
{ value: 'title-desc', label: t('navigation.sortNameDescending') },
|
|
258
|
+
{ value: 'id-asc', label: t('navigation.sortId') },
|
|
259
|
+
]);
|
|
254
260
|
|
|
255
|
-
const normalizedQuery = computed(() => query.value.trim().toLocaleLowerCase(
|
|
261
|
+
const normalizedQuery = computed(() => query.value.trim().toLocaleLowerCase(locale.value));
|
|
256
262
|
|
|
257
263
|
const selectedGroupKey = computed(() => {
|
|
258
264
|
if (selectedGroup.value === ALL_GROUP_FILTER) return null;
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
class="s-tab-list__tabs"
|
|
36
36
|
:id="tabListId"
|
|
37
37
|
role="tablist"
|
|
38
|
-
:aria-label="
|
|
38
|
+
:aria-label="resolvedAriaLabel"
|
|
39
39
|
aria-orientation="horizontal"
|
|
40
40
|
>
|
|
41
41
|
<slot />
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
ref="controlsRef"
|
|
49
49
|
class="s-tabs-header__controls"
|
|
50
50
|
role="group"
|
|
51
|
-
:aria-label="
|
|
51
|
+
:aria-label="resolvedControlsAriaLabel"
|
|
52
52
|
>
|
|
53
53
|
<slot name="controls" />
|
|
54
54
|
</div>
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
class="s-tab-list__tabs"
|
|
82
82
|
:id="tabListId"
|
|
83
83
|
role="tablist"
|
|
84
|
-
:aria-label="
|
|
84
|
+
:aria-label="resolvedAriaLabel"
|
|
85
85
|
aria-orientation="horizontal"
|
|
86
86
|
>
|
|
87
87
|
<slot />
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
ref="controlsRef"
|
|
93
93
|
class="s-tabs-header__controls"
|
|
94
94
|
role="group"
|
|
95
|
-
:aria-label="
|
|
95
|
+
:aria-label="resolvedControlsAriaLabel"
|
|
96
96
|
>
|
|
97
97
|
<slot name="controls" />
|
|
98
98
|
</div>
|
|
@@ -116,6 +116,7 @@ import {
|
|
|
116
116
|
type STabsContext,
|
|
117
117
|
} from '../_internal/tabsContext'
|
|
118
118
|
import { useOwnedAttrs } from '../../../internal/ownedAttrs'
|
|
119
|
+
import { useUiKitLocale } from '../../../composables/useUiKitLocale'
|
|
119
120
|
import { useInteractiveLeafRegistration } from '../../../internal/passiveContentContract'
|
|
120
121
|
|
|
121
122
|
defineOptions({
|
|
@@ -150,11 +151,14 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
150
151
|
divider: true,
|
|
151
152
|
inset: 'none',
|
|
152
153
|
headerPosition: 'sticky',
|
|
153
|
-
ariaLabel:
|
|
154
|
+
ariaLabel: undefined,
|
|
154
155
|
tabListId: undefined,
|
|
155
156
|
leadingAriaLabel: undefined,
|
|
156
|
-
controlsAriaLabel:
|
|
157
|
+
controlsAriaLabel: undefined,
|
|
157
158
|
})
|
|
159
|
+
const { t } = useUiKitLocale()
|
|
160
|
+
const resolvedAriaLabel = computed(() => props.ariaLabel ?? t('navigation.tabs'))
|
|
161
|
+
const resolvedControlsAriaLabel = computed(() => props.controlsAriaLabel ?? t('navigation.tabActions'))
|
|
158
162
|
|
|
159
163
|
watch(
|
|
160
164
|
() => props.tabListId,
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
<STabList
|
|
22
22
|
v-if="variant !== 'bottom'"
|
|
23
23
|
placement="top"
|
|
24
|
-
:aria-label="
|
|
25
|
-
:controls-aria-label="
|
|
24
|
+
:aria-label="resolvedAriaLabel"
|
|
25
|
+
:controls-aria-label="resolvedControlsAriaLabel"
|
|
26
26
|
:header-position="headerPosition"
|
|
27
27
|
:inset="tabListInset"
|
|
28
28
|
>
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
<STabList
|
|
34
34
|
v-if="variant === 'bottom'"
|
|
35
35
|
placement="bottom"
|
|
36
|
-
:aria-label="
|
|
37
|
-
:controls-aria-label="
|
|
36
|
+
:aria-label="resolvedAriaLabel"
|
|
37
|
+
:controls-aria-label="resolvedControlsAriaLabel"
|
|
38
38
|
>
|
|
39
39
|
<slot name="list" />
|
|
40
40
|
<template v-if="$slots.controls" #controls><slot name="controls" /></template>
|
|
@@ -58,6 +58,7 @@ import {
|
|
|
58
58
|
type VNodeChild,
|
|
59
59
|
} from 'vue'
|
|
60
60
|
import { useOwnedAttrs } from '../../../internal/ownedAttrs'
|
|
61
|
+
import { useUiKitLocale } from '../../../composables/useUiKitLocale'
|
|
61
62
|
import { resolveSemanticToneBinding } from '../../../internal/semanticTone'
|
|
62
63
|
import { lastItem } from '../../../internal/es2020'
|
|
63
64
|
import {
|
|
@@ -153,8 +154,8 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
153
154
|
defaultValue: undefined,
|
|
154
155
|
activationMode: 'automatic',
|
|
155
156
|
tone: 'primary',
|
|
156
|
-
ariaLabel:
|
|
157
|
-
controlsAriaLabel:
|
|
157
|
+
ariaLabel: undefined,
|
|
158
|
+
controlsAriaLabel: undefined,
|
|
158
159
|
headerPosition: 'sticky',
|
|
159
160
|
tabListInset: 'none',
|
|
160
161
|
grow: true,
|
|
@@ -166,6 +167,9 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
166
167
|
surfaceRadius: 'default',
|
|
167
168
|
surface: 'default',
|
|
168
169
|
})
|
|
170
|
+
const { t } = useUiKitLocale()
|
|
171
|
+
const resolvedAriaLabel = computed(() => props.ariaLabel ?? t('navigation.tabs'))
|
|
172
|
+
const resolvedControlsAriaLabel = computed(() => props.controlsAriaLabel ?? t('navigation.tabActions'))
|
|
169
173
|
|
|
170
174
|
const emit = defineEmits<{
|
|
171
175
|
'update:modelValue': [key: string]
|
|
@@ -213,8 +217,8 @@ function assertPropsContract(): void {
|
|
|
213
217
|
if (props.modelValue !== undefined && props.defaultValue !== undefined) {
|
|
214
218
|
throw new Error('STabs: modelValue and defaultValue are mutually exclusive')
|
|
215
219
|
}
|
|
216
|
-
if (!
|
|
217
|
-
if (!
|
|
220
|
+
if (!resolvedAriaLabel.value.trim()) throw new TypeError('STabs: ariaLabel must be non-empty')
|
|
221
|
+
if (!resolvedControlsAriaLabel.value.trim()) throw new TypeError('STabs: controlsAriaLabel must be non-empty')
|
|
218
222
|
if (props.testId !== undefined && !props.testId.trim()) throw new TypeError('STabs: testId must be non-empty')
|
|
219
223
|
}
|
|
220
224
|
|
|
@@ -223,8 +227,8 @@ watch(() => [
|
|
|
223
227
|
props.composition,
|
|
224
228
|
props.modelValue,
|
|
225
229
|
props.defaultValue,
|
|
226
|
-
|
|
227
|
-
|
|
230
|
+
resolvedAriaLabel.value,
|
|
231
|
+
resolvedControlsAriaLabel.value,
|
|
228
232
|
props.testId,
|
|
229
233
|
] as const, assertPropsContract)
|
|
230
234
|
|
|
@@ -538,7 +542,7 @@ defineExpose({
|
|
|
538
542
|
--s-tab-padding-inline: var(--s-tab-base-padding-inline);
|
|
539
543
|
--s-tab-padding-block: 0;
|
|
540
544
|
--s-tab-content-offset-y: 0;
|
|
541
|
-
--s-tab-trigger-min-height: var(--s-
|
|
545
|
+
--s-tab-trigger-min-height: var(--s-tab-row-height);
|
|
542
546
|
--s-tab-indicator-width: 2px;
|
|
543
547
|
--s-tab-radius: 0.375rem 0.375rem 0 0;
|
|
544
548
|
--s-tab-active-translate-y: 1px;
|
|
@@ -63,6 +63,7 @@ export interface Props<T extends PublicSelectionKey = string | number> {
|
|
|
63
63
|
|
|
64
64
|
<script setup lang="ts" generic="T extends SelectionKey = string | number">
|
|
65
65
|
import { computed } from 'vue'
|
|
66
|
+
import { useUiKitLocale } from '../../../composables/useUiKitLocale'
|
|
66
67
|
import { validateBoolean, validateExactString, validateNonEmptyString } from '../../../internal/runtimeContract'
|
|
67
68
|
import { useOwnedAttrs } from '../../../internal/ownedAttrs'
|
|
68
69
|
import SButton from '../controls/SButton.vue'
|
|
@@ -86,8 +87,9 @@ interface WizardStepRecord<TStep extends SelectionKey> {
|
|
|
86
87
|
const props = withDefaults(defineProps<Props<T>>(), {
|
|
87
88
|
columns: 'auto',
|
|
88
89
|
density: 'default',
|
|
89
|
-
ariaLabel:
|
|
90
|
+
ariaLabel: undefined,
|
|
90
91
|
})
|
|
92
|
+
const { t } = useUiKitLocale()
|
|
91
93
|
|
|
92
94
|
const emit = defineEmits<{
|
|
93
95
|
'update:modelValue': [value: T]
|
|
@@ -125,7 +127,7 @@ const validatedDensity = computed(() => validateExactString(
|
|
|
125
127
|
const validatedAriaLabel = computed(() => validateNonEmptyString(
|
|
126
128
|
'SWizardSteps',
|
|
127
129
|
'ariaLabel',
|
|
128
|
-
props.ariaLabel,
|
|
130
|
+
props.ariaLabel ?? t('navigation.wizardSteps'),
|
|
129
131
|
))
|
|
130
132
|
|
|
131
133
|
const stepRecords = computed<readonly WizardStepRecord<T>[]>(() => {
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
resolvePersonaProjectPickerAsyncState,
|
|
26
26
|
} from './_internal/inventory'
|
|
27
27
|
import { useOwnedAttrs } from '../../../internal/ownedAttrs'
|
|
28
|
+
import { useUiKitLocale } from '../../../composables/useUiKitLocale'
|
|
28
29
|
|
|
29
30
|
defineOptions({ inheritAttrs: false })
|
|
30
31
|
|
|
@@ -52,6 +53,7 @@ const emit = defineEmits<{
|
|
|
52
53
|
'activate-connected': [bindingId: string]
|
|
53
54
|
}>()
|
|
54
55
|
const ownedAttrs = useOwnedAttrs({ component: 'SPersonaProjectPicker', owner: 'project-picker modal surface' })
|
|
56
|
+
const { locale, t } = useUiKitLocale()
|
|
55
57
|
|
|
56
58
|
const filter = ref('')
|
|
57
59
|
const selectedProjectId = ref<string | null>(null)
|
|
@@ -122,8 +124,8 @@ const listing = computed(() => {
|
|
|
122
124
|
const pickerAsyncState = computed(() => resolvePersonaProjectPickerAsyncState(
|
|
123
125
|
props.state,
|
|
124
126
|
{
|
|
125
|
-
loadingMessage: '
|
|
126
|
-
emptyMessage: '
|
|
127
|
+
loadingMessage: t('persona.loadingCatalogs'),
|
|
128
|
+
emptyMessage: t('persona.chooseSearchArea'),
|
|
127
129
|
},
|
|
128
130
|
))
|
|
129
131
|
const projectInventory = computed(() => {
|
|
@@ -139,10 +141,10 @@ const selectedProject = computed(() => {
|
|
|
139
141
|
return project?.isSelectable ? project : null
|
|
140
142
|
})
|
|
141
143
|
const visibleDirectories = computed(() => {
|
|
142
|
-
const query = filter.value.trim().toLocaleLowerCase(
|
|
144
|
+
const query = filter.value.trim().toLocaleLowerCase(locale.value)
|
|
143
145
|
if (!query) return listing.value?.directories ?? []
|
|
144
146
|
return (listing.value?.directories ?? []).filter((directory) =>
|
|
145
|
-
`${directory.name} ${directory.displayPath}`.toLocaleLowerCase(
|
|
147
|
+
`${directory.name} ${directory.displayPath}`.toLocaleLowerCase(locale.value).includes(query),
|
|
146
148
|
)
|
|
147
149
|
})
|
|
148
150
|
const breadcrumbs = computed(() => {
|
|
@@ -165,7 +167,9 @@ const breadcrumbs = computed(() => {
|
|
|
165
167
|
}
|
|
166
168
|
return result
|
|
167
169
|
})
|
|
168
|
-
const emptyLabel = computed(() => filter.value.trim()
|
|
170
|
+
const emptyLabel = computed(() => filter.value.trim()
|
|
171
|
+
? t('persona.noMatches')
|
|
172
|
+
: t('persona.noNestedDirectories'))
|
|
169
173
|
|
|
170
174
|
watch(
|
|
171
175
|
() => props.open,
|
|
@@ -205,8 +209,8 @@ function connectedProject(project: PersonaProjectPickerEntry): PersonaProjectPic
|
|
|
205
209
|
function projectActionLabel(project: PersonaProjectPickerEntry): string | undefined {
|
|
206
210
|
if (!project.isSelectable) return undefined
|
|
207
211
|
const connected = connectedProject(project)
|
|
208
|
-
if (connected) return connected.active ? '
|
|
209
|
-
return selectedProject.value?.id === project.id ? '
|
|
212
|
+
if (connected) return connected.active ? t('persona.active') : t('persona.open')
|
|
213
|
+
return selectedProject.value?.id === project.id ? t('persona.selected') : t('persona.select')
|
|
210
214
|
}
|
|
211
215
|
|
|
212
216
|
function projectAction(project: PersonaProjectPickerEntry): void {
|
|
@@ -227,14 +231,14 @@ function confirmSelection(): void {
|
|
|
227
231
|
<SModal
|
|
228
232
|
v-bind="ownedAttrs.bindings()"
|
|
229
233
|
:open="open"
|
|
230
|
-
title="
|
|
234
|
+
:title="t('persona.pickerTitle')"
|
|
231
235
|
size="wide"
|
|
232
236
|
@update:open="emit('update:open', $event)"
|
|
233
237
|
>
|
|
234
238
|
<div class="s-persona-project-picker">
|
|
235
239
|
<div v-if="validatedConnectedProjects.length > 0" class="s-persona-project-picker__connected">
|
|
236
|
-
<SPanel title="
|
|
237
|
-
<SActionList accessible-label="
|
|
240
|
+
<SPanel :title="t('persona.connected')" :icon="FolderTree">
|
|
241
|
+
<SActionList :accessible-label="t('persona.connectedProjects')" max-height="md">
|
|
238
242
|
<SActionListItem
|
|
239
243
|
v-for="project in validatedConnectedProjects"
|
|
240
244
|
:key="project.id"
|
|
@@ -242,9 +246,9 @@ function confirmSelection(): void {
|
|
|
242
246
|
:description="project.path"
|
|
243
247
|
:icon="FolderTree"
|
|
244
248
|
:selected="project.active"
|
|
245
|
-
:status-label="project.active ? '
|
|
249
|
+
:status-label="project.active ? t('persona.active') : undefined"
|
|
246
250
|
status-severity="success"
|
|
247
|
-
:surface="{ mode: 'action', accessibleLabel:
|
|
251
|
+
:surface="{ mode: 'action', accessibleLabel: t('persona.openProject', { title: project.title }) }"
|
|
248
252
|
@activate="emit('activate-connected', project.id)"
|
|
249
253
|
/>
|
|
250
254
|
</SActionList>
|
|
@@ -257,8 +261,8 @@ function confirmSelection(): void {
|
|
|
257
261
|
<SSelect
|
|
258
262
|
:model-value="resolvedSelectedRootId"
|
|
259
263
|
:options="rootOptions"
|
|
260
|
-
placeholder="
|
|
261
|
-
aria-label="
|
|
264
|
+
:placeholder="t('persona.selectArea')"
|
|
265
|
+
:aria-label="t('persona.projectSearchArea')"
|
|
262
266
|
@update:model-value="selectRoot"
|
|
263
267
|
/>
|
|
264
268
|
</div>
|
|
@@ -266,8 +270,8 @@ function confirmSelection(): void {
|
|
|
266
270
|
ref="searchInput"
|
|
267
271
|
v-model="filter"
|
|
268
272
|
size="sm"
|
|
269
|
-
placeholder="
|
|
270
|
-
aria-label="
|
|
273
|
+
:placeholder="t('persona.searchCurrentCatalog')"
|
|
274
|
+
:aria-label="t('persona.catalogSearch')"
|
|
271
275
|
/>
|
|
272
276
|
<SButton
|
|
273
277
|
label=""
|
|
@@ -275,8 +279,8 @@ function confirmSelection(): void {
|
|
|
275
279
|
severity="secondary"
|
|
276
280
|
:leading-icon="RefreshCw"
|
|
277
281
|
icon-only
|
|
278
|
-
title="
|
|
279
|
-
aria-label="
|
|
282
|
+
:title="t('persona.refreshCatalog')"
|
|
283
|
+
:aria-label="t('persona.refreshCatalog')"
|
|
280
284
|
@click="emit('refresh')"
|
|
281
285
|
/>
|
|
282
286
|
</div>
|
|
@@ -284,13 +288,13 @@ function confirmSelection(): void {
|
|
|
284
288
|
<SBreadcrumbs
|
|
285
289
|
v-if="listing"
|
|
286
290
|
:items="breadcrumbs"
|
|
287
|
-
aria-label="
|
|
291
|
+
:aria-label="t('persona.catalogPath')"
|
|
288
292
|
@action="navigateBreadcrumb($event)"
|
|
289
293
|
/>
|
|
290
294
|
|
|
291
295
|
<SAsyncState :state="pickerAsyncState">
|
|
292
296
|
<div v-if="listing" class="s-persona-project-picker__content">
|
|
293
|
-
<SActionList accessible-label="
|
|
297
|
+
<SActionList :accessible-label="t('persona.directoriesAndProjects')" max-height="lg">
|
|
294
298
|
<SActionListItem
|
|
295
299
|
v-if="listing.current.isSelectable"
|
|
296
300
|
:title="listing.current.projectName || listing.current.name"
|
|
@@ -302,7 +306,7 @@ function confirmSelection(): void {
|
|
|
302
306
|
:action-icon="connectedProject(listing.current)?.active ? Check : undefined"
|
|
303
307
|
:action-disabled="connectedProject(listing.current)?.active"
|
|
304
308
|
action-severity="success"
|
|
305
|
-
status-label="
|
|
309
|
+
:status-label="t('persona.personaProject')"
|
|
306
310
|
status-severity="success"
|
|
307
311
|
:surface="{ mode: 'static' }"
|
|
308
312
|
@action="projectAction(listing.current)"
|
|
@@ -319,10 +323,10 @@ function confirmSelection(): void {
|
|
|
319
323
|
:action-icon="connectedProject(directory)?.active || selectedProject?.id === directory.id ? Check : undefined"
|
|
320
324
|
:action-disabled="connectedProject(directory)?.active"
|
|
321
325
|
:action-severity="connectedProject(directory)?.active || selectedProject?.id === directory.id ? 'success' : 'secondary'"
|
|
322
|
-
:status-label="directory.readiness === 'unreadable' ? '
|
|
326
|
+
:status-label="directory.readiness === 'unreadable' ? t('persona.noAccess') : directory.readiness === 'invalid' ? t('persona.projectError') : undefined"
|
|
323
327
|
status-severity="danger"
|
|
324
328
|
:trailing-icon="directory.isSelectable || directory.readiness === 'unreadable' || directory.readiness === 'invalid' ? undefined : ChevronRight"
|
|
325
|
-
:surface="{ mode: 'action', accessibleLabel:
|
|
329
|
+
:surface="{ mode: 'action', accessibleLabel: t('persona.openDirectory', { name: directory.name }) }"
|
|
326
330
|
@activate="emit('navigate', directory.relativePath)"
|
|
327
331
|
@action="projectAction(directory)"
|
|
328
332
|
/>
|
|
@@ -331,7 +335,7 @@ function confirmSelection(): void {
|
|
|
331
335
|
<SEmptyState
|
|
332
336
|
v-if="visibleDirectories.length === 0"
|
|
333
337
|
:title="emptyLabel"
|
|
334
|
-
:description="filter.trim() ? '
|
|
338
|
+
:description="filter.trim() ? t('persona.adjustSearch') : t('persona.chooseAnotherArea')"
|
|
335
339
|
:icon="FolderSearch"
|
|
336
340
|
size="sm"
|
|
337
341
|
/>
|
|
@@ -341,7 +345,7 @@ function confirmSelection(): void {
|
|
|
341
345
|
:loading="state.pagination === 'loading-more'"
|
|
342
346
|
@click="emit('load-more')"
|
|
343
347
|
>
|
|
344
|
-
|
|
348
|
+
{{ t('persona.loadMore') }}
|
|
345
349
|
</SButton>
|
|
346
350
|
</div>
|
|
347
351
|
</SAsyncState>
|
|
@@ -352,8 +356,8 @@ function confirmSelection(): void {
|
|
|
352
356
|
<SBadge v-if="selectedProject" severity="info">{{ selectedProject.displayPath }}</SBadge>
|
|
353
357
|
</template>
|
|
354
358
|
<template #footer-end>
|
|
355
|
-
<SButton severity="secondary" @click="emit('update:open', false)"
|
|
356
|
-
<SButton :disabled="!selectedProject" @click="confirmSelection"
|
|
359
|
+
<SButton severity="secondary" @click="emit('update:open', false)">{{ t('persona.cancel') }}</SButton>
|
|
360
|
+
<SButton :disabled="!selectedProject" @click="confirmSelection">{{ t('persona.connectProject') }}</SButton>
|
|
357
361
|
</template>
|
|
358
362
|
</SModal>
|
|
359
363
|
</template>
|