@application-kit/ui 0.0.0-stage → 0.0.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/LICENSE +21 -0
- package/README.md +41 -2
- package/dist/_virtual/_plugin-vue_export-helper.js +8 -0
- package/dist/accent-color.d.ts +2 -0
- package/dist/accent-color.js +15 -0
- package/dist/components/avatar/Avatar.js +5 -0
- package/dist/components/avatar/Avatar.vue.d.ts +24 -0
- package/dist/components/avatar/Avatar.vue_vue_type_script_setup_true_lang.js +31 -0
- package/dist/components/button/Button.js +5 -0
- package/dist/components/button/Button.vue.d.ts +130 -0
- package/dist/components/button/Button.vue_vue_type_script_setup_true_lang.js +104 -0
- package/dist/components/button/severity-to-vendor.d.ts +4 -0
- package/dist/components/button/severity-to-vendor.js +11 -0
- package/dist/components/card/Card.js +5 -0
- package/dist/components/card/Card.vue.d.ts +17 -0
- package/dist/components/card/Card.vue_vue_type_script_setup_true_lang.js +34 -0
- package/dist/components/confirm/ConfirmHost.js +5 -0
- package/dist/components/confirm/ConfirmHost.vue.d.ts +3 -0
- package/dist/components/confirm/ConfirmHost.vue_vue_type_script_setup_true_lang.js +13 -0
- package/dist/components/confirm/install-confirmation-service.d.ts +2 -0
- package/dist/components/confirm/install-confirmation-service.js +16 -0
- package/dist/components/date-range-filter/DateRangeFilter.js +7 -0
- package/dist/components/date-range-filter/DateRangeFilter.vue.d.ts +13 -0
- package/dist/components/date-range-filter/DateRangeFilter.vue_vue_type_script_setup_true_lang.js +121 -0
- package/dist/components/dialog/Dialog.js +5 -0
- package/dist/components/dialog/Dialog.vue.d.ts +56 -0
- package/dist/components/dialog/Dialog.vue_vue_type_script_setup_true_lang.js +71 -0
- package/dist/components/drawer/Drawer.js +5 -0
- package/dist/components/drawer/Drawer.vue.d.ts +24 -0
- package/dist/components/drawer/Drawer.vue_vue_type_script_setup_true_lang.js +29 -0
- package/dist/components/error-page/Error.js +7 -0
- package/dist/components/error-page/Error.vue.d.ts +62 -0
- package/dist/components/error-page/Error.vue_vue_type_script_setup_true_lang.js +93 -0
- package/dist/components/error-page/GradientBackground.js +7 -0
- package/dist/components/error-page/GradientBackground.vue.d.ts +17 -0
- package/dist/components/error-page/GradientBackground.vue_vue_type_script_setup_true_lang.js +54 -0
- package/dist/components/form/Checkbox.js +5 -0
- package/dist/components/form/Checkbox.vue.d.ts +16 -0
- package/dist/components/form/Checkbox.vue_vue_type_script_setup_true_lang.js +37 -0
- package/dist/components/form/DateField.js +5 -0
- package/dist/components/form/DateField.vue.d.ts +24 -0
- package/dist/components/form/DateField.vue_vue_type_script_setup_true_lang.js +52 -0
- package/dist/components/form/DateRangeField.js +5 -0
- package/dist/components/form/DateRangeField.vue.d.ts +32 -0
- package/dist/components/form/DateRangeField.vue_vue_type_script_setup_true_lang.js +48 -0
- package/dist/components/form/InputNumber.js +5 -0
- package/dist/components/form/InputNumber.vue.d.ts +17 -0
- package/dist/components/form/InputNumber.vue_vue_type_script_setup_true_lang.js +37 -0
- package/dist/components/form/InputOtp.js +5 -0
- package/dist/components/form/InputOtp.vue.d.ts +20 -0
- package/dist/components/form/InputOtp.vue_vue_type_script_setup_true_lang.js +39 -0
- package/dist/components/form/InputText.js +5 -0
- package/dist/components/form/InputText.vue.d.ts +17 -0
- package/dist/components/form/InputText.vue_vue_type_script_setup_true_lang.js +37 -0
- package/dist/components/form/MultiSelect.js +5 -0
- package/dist/components/form/MultiSelect.vue.d.ts +34 -0
- package/dist/components/form/MultiSelect.vue_vue_type_script_setup_true_lang.js +47 -0
- package/dist/components/form/RadioButton.js +5 -0
- package/dist/components/form/RadioButton.vue.d.ts +27 -0
- package/dist/components/form/RadioButton.vue_vue_type_script_setup_true_lang.js +37 -0
- package/dist/components/form/Select.js +5 -0
- package/dist/components/form/Select.vue.d.ts +41 -0
- package/dist/components/form/Select.vue_vue_type_script_setup_true_lang.js +78 -0
- package/dist/components/form/SelectButton.js +5 -0
- package/dist/components/form/SelectButton.vue.d.ts +27 -0
- package/dist/components/form/SelectButton.vue_vue_type_script_setup_true_lang.js +36 -0
- package/dist/components/form/Textarea.js +5 -0
- package/dist/components/form/Textarea.vue.d.ts +16 -0
- package/dist/components/form/Textarea.vue_vue_type_script_setup_true_lang.js +34 -0
- package/dist/components/form/ToggleSwitch.js +5 -0
- package/dist/components/form/ToggleSwitch.vue.d.ts +14 -0
- package/dist/components/form/ToggleSwitch.vue_vue_type_script_setup_true_lang.js +26 -0
- package/dist/components/form/date-format.d.ts +1 -0
- package/dist/components/form/date-format.js +14 -0
- package/dist/components/form/select-button-option.interface.d.ts +4 -0
- package/dist/components/icon/Icon.js +7 -0
- package/dist/components/icon/Icon.vue.d.ts +23 -0
- package/dist/components/icon/Icon.vue_vue_type_script_setup_true_lang.js +28 -0
- package/dist/components/icon-cell/IconCell.js +7 -0
- package/dist/components/icon-cell/IconCell.vue.d.ts +7 -0
- package/dist/components/icon-cell/IconCell.vue_vue_type_script_setup_true_lang.js +32 -0
- package/dist/components/layouts/EmptyLayout.js +16 -0
- package/dist/components/layouts/EmptyLayout.vue.d.ts +15 -0
- package/dist/components/message/Message.js +5 -0
- package/dist/components/message/Message.vue.d.ts +72 -0
- package/dist/components/message/Message.vue_vue_type_script_setup_true_lang.js +63 -0
- package/dist/components/message/severity-to-vendor.d.ts +4 -0
- package/dist/components/message/severity-to-vendor.js +11 -0
- package/dist/components/overlay-badge/OverlayBadge.js +5 -0
- package/dist/components/overlay-badge/OverlayBadge.vue.d.ts +16 -0
- package/dist/components/overlay-badge/OverlayBadge.vue_vue_type_script_setup_true_lang.js +17 -0
- package/dist/components/skeleton/Skeleton.js +5 -0
- package/dist/components/skeleton/Skeleton.vue.d.ts +7 -0
- package/dist/components/skeleton/Skeleton.vue_vue_type_script_setup_true_lang.js +20 -0
- package/dist/components/table/DataTable.js +7 -0
- package/dist/components/table/DataTable.vue.d.ts +61 -0
- package/dist/components/table/DataTable.vue_vue_type_script_setup_true_lang.js +303 -0
- package/dist/components/table/InfiniteDataTable.js +7 -0
- package/dist/components/table/InfiniteDataTable.vue.d.ts +32 -0
- package/dist/components/table/InfiniteDataTable.vue_vue_type_script_setup_true_lang.js +88 -0
- package/dist/components/table/SelectColumnFilter.js +5 -0
- package/dist/components/table/SelectColumnFilter.vue.d.ts +29 -0
- package/dist/components/table/SelectColumnFilter.vue_vue_type_script_setup_true_lang.js +58 -0
- package/dist/components/table/StaticTable.js +5 -0
- package/dist/components/table/StaticTable.vue.d.ts +39 -0
- package/dist/components/table/StaticTable.vue_vue_type_script_setup_true_lang.js +48 -0
- package/dist/components/table/TextColumn.js +5 -0
- package/dist/components/table/TextColumn.vue.d.ts +13 -0
- package/dist/components/table/TextColumn.vue_vue_type_script_setup_true_lang.js +16 -0
- package/dist/components/table/collect-column-filters.d.ts +4 -0
- package/dist/components/table/collect-column-filters.js +11 -0
- package/dist/components/table/column-filters-interface.d.ts +10 -0
- package/dist/components/table/column-schema-interface.d.ts +20 -0
- package/dist/components/table/get-filters.d.ts +3 -0
- package/dist/components/table/get-filters.js +73 -0
- package/dist/components/table/select-column-filter-option.interface.d.ts +8 -0
- package/dist/components/table/static-table-column.d.ts +1 -0
- package/dist/components/tabs/Tabs.js +5 -0
- package/dist/components/tabs/Tabs.vue.d.ts +35 -0
- package/dist/components/tabs/Tabs.vue_vue_type_script_setup_true_lang.js +54 -0
- package/dist/components/tabs/tab-item.interface.d.ts +7 -0
- package/dist/components/tag/Tag.js +5 -0
- package/dist/components/tag/Tag.vue.d.ts +44 -0
- package/dist/components/tag/Tag.vue_vue_type_script_setup_true_lang.js +47 -0
- package/dist/components/tag/severity-to-vendor.d.ts +4 -0
- package/dist/components/tag/severity-to-vendor.js +11 -0
- package/dist/components/time-lag/TimeLag.js +7 -0
- package/dist/components/time-lag/TimeLag.vue.d.ts +29 -0
- package/dist/components/time-lag/TimeLag.vue_vue_type_script_setup_true_lang.js +38 -0
- package/dist/components/timestamp/Timestamp.js +5 -0
- package/dist/components/timestamp/Timestamp.vue.d.ts +13 -0
- package/dist/components/timestamp/Timestamp.vue_vue_type_script_setup_true_lang.js +21 -0
- package/dist/components/toast/ToastHost.js +6 -0
- package/dist/components/toast/ToastHost.vue.d.ts +3 -0
- package/dist/components/toast/ToastHost.vue_vue_type_script_setup_true_lang.js +13 -0
- package/dist/components/toast/install-toast-service.d.ts +2 -0
- package/dist/components/toast/install-toast-service.js +15 -0
- package/dist/components/toast/severity-to-vendor.d.ts +4 -0
- package/dist/components/toast/severity-to-vendor.js +11 -0
- package/dist/components/tooltip/Tooltip.js +7 -0
- package/dist/components/tooltip/Tooltip.vue.d.ts +51 -0
- package/dist/components/tooltip/Tooltip.vue_vue_type_script_setup_true_lang.js +47 -0
- package/dist/components/tooltip/dismiss-tooltips.d.ts +2 -0
- package/dist/components/tooltip/dismiss-tooltips.js +13 -0
- package/dist/components/tooltip/install-tooltip-directive.d.ts +6 -0
- package/dist/components/tooltip/install-tooltip-directive.js +80 -0
- package/dist/components/tooltip/tooltip-options.interface.d.ts +10 -0
- package/dist/components/truncated-code/TruncatedCode.js +5 -0
- package/dist/components/truncated-code/TruncatedCode.vue.d.ts +9 -0
- package/dist/components/truncated-code/TruncatedCode.vue_vue_type_script_setup_true_lang.js +23 -0
- package/dist/components/ui-icon/UiIcon.js +5 -0
- package/dist/components/ui-icon/UiIcon.vue.d.ts +13 -0
- package/dist/components/ui-icon/UiIcon.vue_vue_type_script_setup_true_lang.js +22 -0
- package/dist/composables/use-app-toast.d.ts +12 -0
- package/dist/composables/use-app-toast.js +50 -0
- package/dist/composables/use-confirm.d.ts +12 -0
- package/dist/composables/use-confirm.js +49 -0
- package/dist/composables/use-copy-to-clipboard.d.ts +2 -0
- package/dist/composables/use-copy-to-clipboard.js +23 -0
- package/dist/icons/ui-icon-registry.d.ts +6 -0
- package/dist/icons/ui-icon-registry.js +4 -0
- package/dist/index.d.ts +66 -0
- package/dist/index.js +56 -0
- package/dist/layout/layout.d.ts +37 -0
- package/dist/layout/layout.js +60 -0
- package/dist/messages/ui-messages.d.ts +23 -0
- package/dist/plugin/ui-injection.d.ts +11 -0
- package/dist/plugin/ui-injection.js +18 -0
- package/dist/plugin/ui-vendor-plugin.d.ts +22 -0
- package/dist/plugin/ui-vendor-plugin.js +57 -0
- package/dist/severity.d.ts +1 -0
- package/dist/store/listing/cursor-listing.d.ts +25 -0
- package/dist/store/listing/cursor-listing.js +97 -0
- package/dist/store/listing/infinite-listing-store.d.ts +21 -0
- package/dist/store/listing/infinite-listing-store.interface.d.ts +13 -0
- package/dist/store/listing/infinite-listing-store.js +68 -0
- package/dist/store/listing/listing-store.d.ts +7 -0
- package/dist/store/listing/listing-store.interface.d.ts +21 -0
- package/dist/store/listing/listing-store.js +114 -0
- package/dist/style.css +158 -0
- package/dist/styles/_tokens.scss +96 -0
- package/dist/styles/_variables.scss +8 -0
- package/dist/testing/browser-api-stubs.d.ts +1 -0
- package/dist/testing/browser-api-stubs.js +38 -0
- package/dist/testing/index.d.ts +5 -0
- package/dist/testing/index.js +6 -0
- package/dist/testing/set-viewport-width.d.ts +1 -0
- package/dist/testing/set-viewport-width.js +18 -0
- package/dist/testing/submit-form.d.ts +1 -0
- package/dist/testing/submit-form.js +25 -0
- package/dist/testing/ui-messages.fixture.d.ts +2 -0
- package/dist/testing/ui-messages.fixture.js +26 -0
- package/dist/testing/vendor-plugins.d.ts +2 -0
- package/dist/testing/vendor-plugins.js +22 -0
- package/dist/utils/datetime.d.ts +10 -0
- package/dist/utils/datetime.js +53 -0
- package/dist/utils/truncate-string.d.ts +2 -0
- package/dist/utils/truncate-string.js +10 -0
- package/package.json +93 -3
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// Мост «вендорские токены → собственные» — единственный в приложении (story 3-7).
|
|
2
|
+
// Вендор объявляет свои CSS-переменные с префиксом `--p-`; фича-код читает только `--ui-*`,
|
|
3
|
+
// объявленные здесь. Смена вендора правит этот файл, а не сотни потребителей.
|
|
4
|
+
// Мост стоит на `:root`, а не в layout-компоненте: страницы логина и ошибки рисуются вне
|
|
5
|
+
// поддерева `.layout`, и мост, объявленный там, до них не доезжает (было ровно так до 3-7).
|
|
6
|
+
// Список — по инвентарю потребителей, а не «все токены вендора»: неиспользуемый токен здесь
|
|
7
|
+
// не объявляется, иначе файл превращается в копию темы вендора со своей судьбой.
|
|
8
|
+
// Полнота держится спекой `tests/tokens.spec.ts`: `--ui-*`, встреченный в `src/` и не
|
|
9
|
+
// объявленный здесь, краснит `yarn test:unit`.
|
|
10
|
+
:root {
|
|
11
|
+
// Поверхности.
|
|
12
|
+
--ui-surface-0: var(--p-surface-0);
|
|
13
|
+
--ui-surface-50: var(--p-surface-50);
|
|
14
|
+
--ui-surface-100: var(--p-surface-100);
|
|
15
|
+
--ui-surface-200: var(--p-surface-200);
|
|
16
|
+
--ui-surface-400: var(--p-surface-400);
|
|
17
|
+
--ui-surface-600: var(--p-surface-600);
|
|
18
|
+
--ui-surface-700: var(--p-surface-700);
|
|
19
|
+
--ui-surface-800: var(--p-surface-800);
|
|
20
|
+
--ui-surface-900: var(--p-surface-900);
|
|
21
|
+
|
|
22
|
+
// Текст и основной акцент.
|
|
23
|
+
--ui-text-color: var(--p-text-color);
|
|
24
|
+
--ui-text-muted-color: var(--p-text-muted-color);
|
|
25
|
+
--ui-primary-color: var(--p-primary-color);
|
|
26
|
+
--ui-primary-contrast-color: var(--p-primary-contrast-color);
|
|
27
|
+
|
|
28
|
+
// Подсветка текста (`<mark>`). Пара «фон — текст» объявляется целиком, а не одним оттенком
|
|
29
|
+
// шкалы: фон подсветки светлый, и без своего цвета текста в тёмной теме подсветка светит
|
|
30
|
+
// белым (до 6-53 он и вовсе стоял числом `#fff8e1`, одним на обе темы).
|
|
31
|
+
--ui-highlight-background: var(--ui-accent-yellow-200);
|
|
32
|
+
--ui-highlight-color: var(--ui-accent-yellow-800);
|
|
33
|
+
|
|
34
|
+
// Контент.
|
|
35
|
+
--ui-content-background: var(--p-content-background);
|
|
36
|
+
--ui-content-border-color: var(--p-content-border-color);
|
|
37
|
+
--ui-content-border-radius: var(--p-content-border-radius);
|
|
38
|
+
|
|
39
|
+
// Поля ввода.
|
|
40
|
+
--ui-form-field-border-color: var(--p-form-field-border-color);
|
|
41
|
+
--ui-form-field-focus-border-color: var(--p-form-field-focus-border-color);
|
|
42
|
+
--ui-form-field-color: var(--p-form-field-color);
|
|
43
|
+
--ui-form-field-icon-color: var(--p-form-field-icon-color);
|
|
44
|
+
--ui-form-field-placeholder-color: var(--p-form-field-placeholder-color);
|
|
45
|
+
|
|
46
|
+
// Навигация и оверлеи.
|
|
47
|
+
--ui-navigation-item-active-background: var(--p-navigation-item-active-background);
|
|
48
|
+
--ui-navigation-item-active-color: var(--p-navigation-item-active-color);
|
|
49
|
+
--ui-navigation-item-color: var(--p-navigation-item-color);
|
|
50
|
+
--ui-navigation-item-focus-background: var(--p-navigation-item-focus-background);
|
|
51
|
+
--ui-navigation-item-icon-color: var(--p-navigation-item-icon-color);
|
|
52
|
+
--ui-overlay-navigation-shadow: var(--p-overlay-navigation-shadow);
|
|
53
|
+
--ui-mask-background: var(--p-mask-background);
|
|
54
|
+
|
|
55
|
+
// Метрики.
|
|
56
|
+
--ui-icon-size: var(--p-icon-size);
|
|
57
|
+
--ui-button-icon-only-width: var(--p-button-icon-only-width);
|
|
58
|
+
--ui-transition-duration: var(--p-transition-duration);
|
|
59
|
+
|
|
60
|
+
// Акценты. Шкала `<оттенок>-<вес>` — публичная поверхность типа `AccentColor`
|
|
61
|
+
// (`@/libs/shared/vue/accent-color`): 200/300/500 читает градиент страницы ошибки,
|
|
62
|
+
// 50/600/700/800 — сцены темы в layout. Новый оттенок заводится парой «значение union +
|
|
63
|
+
// строки здесь», иначе спека токенов краснеет.
|
|
64
|
+
--ui-accent-primary-200: var(--p-primary-200);
|
|
65
|
+
--ui-accent-primary-300: var(--p-primary-300);
|
|
66
|
+
--ui-accent-primary-500: var(--p-primary-500);
|
|
67
|
+
--ui-accent-red-200: var(--p-red-200);
|
|
68
|
+
--ui-accent-red-300: var(--p-red-300);
|
|
69
|
+
--ui-accent-red-500: var(--p-red-500);
|
|
70
|
+
--ui-accent-indigo-200: var(--p-indigo-200);
|
|
71
|
+
--ui-accent-indigo-300: var(--p-indigo-300);
|
|
72
|
+
--ui-accent-indigo-500: var(--p-indigo-500);
|
|
73
|
+
--ui-accent-yellow-200: var(--p-yellow-200);
|
|
74
|
+
--ui-accent-yellow-300: var(--p-yellow-300);
|
|
75
|
+
--ui-accent-yellow-500: var(--p-yellow-500);
|
|
76
|
+
--ui-accent-yellow-50: var(--p-yellow-50);
|
|
77
|
+
--ui-accent-yellow-600: var(--p-yellow-600);
|
|
78
|
+
--ui-accent-yellow-700: var(--p-yellow-700);
|
|
79
|
+
--ui-accent-yellow-800: var(--p-yellow-800);
|
|
80
|
+
--ui-accent-blue-50: var(--p-blue-50);
|
|
81
|
+
--ui-accent-blue-600: var(--p-blue-600);
|
|
82
|
+
--ui-accent-blue-700: var(--p-blue-700);
|
|
83
|
+
--ui-accent-blue-800: var(--p-blue-800);
|
|
84
|
+
--ui-accent-emerald-50: var(--p-emerald-50);
|
|
85
|
+
--ui-accent-emerald-600: var(--p-emerald-600);
|
|
86
|
+
--ui-accent-emerald-700: var(--p-emerald-700);
|
|
87
|
+
--ui-accent-emerald-800: var(--p-emerald-800);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Тёмная тема — класс на `<html>` (`topbar/dark-mode-toggle.ts`), то есть на том же узле, что
|
|
91
|
+
// и `:root` выше. Переобъявляется только то, чей светлый вариант в тёмной теме нечитаем:
|
|
92
|
+
// остальные `--ui-*` смотрят в семантические токены вендора, и их тема вендора меняет сама.
|
|
93
|
+
:root.dark-theme {
|
|
94
|
+
--ui-highlight-background: var(--ui-accent-yellow-800);
|
|
95
|
+
--ui-highlight-color: var(--ui-accent-yellow-200);
|
|
96
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
$scale: 14px;
|
|
2
|
+
|
|
3
|
+
// Единственный источник брейкпойнта мобильной раскладки: медиазапросы берут его отсюда,
|
|
4
|
+
// а TS — производное `MOBILE_MAX_WIDTH_PX` ($breakpoint - 1px, `vue/layout/layout.ts`).
|
|
5
|
+
// Равенство двух сторон держит спека `styles/tests/breakpoint.spec.ts`: она читает эту
|
|
6
|
+
// строку, поэтому разъехаться молча они не могут.
|
|
7
|
+
$breakpoint: 992px;
|
|
8
|
+
$font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const installBrowserApiStubs: () => void;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
//#region src/testing/browser-api-stubs.ts
|
|
2
|
+
/**
|
|
3
|
+
* Stubs for browser APIs that jsdom does not implement but vendor widgets call on mount:
|
|
4
|
+
* `matchMedia` (DatePicker's responsive layout) and `ResizeObserver` (TabList's ink-bar sizing).
|
|
5
|
+
* Without them mounting those wrappers throws before a single assertion runs.
|
|
6
|
+
* Call once in a `beforeAll` hook of a spec that mounts such a wrapper.
|
|
7
|
+
* @example
|
|
8
|
+
* beforeAll(() => {
|
|
9
|
+
* installBrowserApiStubs()
|
|
10
|
+
* })
|
|
11
|
+
*/
|
|
12
|
+
var installBrowserApiStubs = () => {
|
|
13
|
+
if (typeof globalThis.matchMedia !== "function") Object.defineProperty(globalThis, "matchMedia", {
|
|
14
|
+
configurable: true,
|
|
15
|
+
value: (query) => ({
|
|
16
|
+
addEventListener: () => void 0,
|
|
17
|
+
addListener: () => void 0,
|
|
18
|
+
dispatchEvent: () => false,
|
|
19
|
+
matches: false,
|
|
20
|
+
media: query,
|
|
21
|
+
onchange: null,
|
|
22
|
+
removeEventListener: () => void 0,
|
|
23
|
+
removeListener: () => void 0
|
|
24
|
+
}),
|
|
25
|
+
writable: true
|
|
26
|
+
});
|
|
27
|
+
if (typeof ResizeObserver !== "function") Object.defineProperty(globalThis, "ResizeObserver", {
|
|
28
|
+
configurable: true,
|
|
29
|
+
value: class {
|
|
30
|
+
disconnect() {}
|
|
31
|
+
observe() {}
|
|
32
|
+
unobserve() {}
|
|
33
|
+
},
|
|
34
|
+
writable: true
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
//#endregion
|
|
38
|
+
export { installBrowserApiStubs };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { installBrowserApiStubs } from "./browser-api-stubs.js";
|
|
2
|
+
import { setViewportWidth } from "./set-viewport-width.js";
|
|
3
|
+
import { runSubmitPipeline } from "./submit-form.js";
|
|
4
|
+
import { testUiMessages } from "./ui-messages.fixture.js";
|
|
5
|
+
import { installVendorPlugins } from "./vendor-plugins.js";
|
|
6
|
+
export { installBrowserApiStubs, installVendorPlugins, runSubmitPipeline, setViewportWidth, testUiMessages };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const setViewportWidth: (width: number) => void;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
//#region src/testing/set-viewport-width.ts
|
|
2
|
+
/**
|
|
3
|
+
* Resizes the window the way a browser does: the `innerWidth` value AND the `resize` event.
|
|
4
|
+
* The layer's desktop flag (`layout.ts`) is reactive and updates on that event — assigning
|
|
5
|
+
* `innerWidth` alone leaves it frozen, and a spec without the event asserts a stale value.
|
|
6
|
+
* @param width - Ширина окна в пикселях.
|
|
7
|
+
* @example
|
|
8
|
+
* setViewportWidth(320)
|
|
9
|
+
*/
|
|
10
|
+
var setViewportWidth = (width) => {
|
|
11
|
+
Object.defineProperty(globalThis.window, "innerWidth", {
|
|
12
|
+
configurable: true,
|
|
13
|
+
value: width
|
|
14
|
+
});
|
|
15
|
+
globalThis.window.dispatchEvent(new Event("resize"));
|
|
16
|
+
};
|
|
17
|
+
//#endregion
|
|
18
|
+
export { setViewportWidth };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const runSubmitPipeline: (act: () => unknown) => Promise<void>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { flushPromises } from "@vue/test-utils";
|
|
2
|
+
import { vi } from "vitest";
|
|
3
|
+
//#region src/testing/submit-form.ts
|
|
4
|
+
/**
|
|
5
|
+
* Runs a vee-validate submit and waits out its validation pipeline.
|
|
6
|
+
*
|
|
7
|
+
* Пайплайн валидации растягивается на несколько макротасков, и `flushPromises` его не
|
|
8
|
+
* дожидается: спек читал бы список событий раньше, чем форма решила, что отправлять есть что.
|
|
9
|
+
* Фейковые таймеры прогоняют его детерминированно — вместо гонки «сколько тиков подождать».
|
|
10
|
+
*
|
|
11
|
+
* Живёт здесь, а не копией в каждом спеке: форм на `useForm` в проекте больше десятка
|
|
12
|
+
* (`docs/ui-patterns.md`, «Форма с валидацией»), и ожидание у них одно и то же.
|
|
13
|
+
* @param act - Действие, запускающее отправку: submit формы либо клик по кнопке.
|
|
14
|
+
* @example
|
|
15
|
+
* await runSubmitPipeline(() => wrapper.get('form').trigger('submit'))
|
|
16
|
+
*/
|
|
17
|
+
var runSubmitPipeline = async (act) => {
|
|
18
|
+
vi.useFakeTimers();
|
|
19
|
+
await act();
|
|
20
|
+
await vi.runAllTimersAsync();
|
|
21
|
+
vi.useRealTimers();
|
|
22
|
+
await flushPromises();
|
|
23
|
+
};
|
|
24
|
+
//#endregion
|
|
25
|
+
export { runSubmitPipeline };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
//#region src/testing/ui-messages.fixture.ts
|
|
2
|
+
var testUiMessages = {
|
|
3
|
+
dateRangeFilter: {
|
|
4
|
+
clear: "Clear",
|
|
5
|
+
lastMonth: "Month",
|
|
6
|
+
lastSixMonths: "6 months",
|
|
7
|
+
lastWeek: "Week",
|
|
8
|
+
placeholder: "Date range"
|
|
9
|
+
},
|
|
10
|
+
errorPage: {
|
|
11
|
+
copied: "Copied",
|
|
12
|
+
copy: "Copy",
|
|
13
|
+
goToDashboard: "Go to dashboard",
|
|
14
|
+
supportIdTitle: "Support ID"
|
|
15
|
+
},
|
|
16
|
+
table: {
|
|
17
|
+
empty: "Nothing found.",
|
|
18
|
+
error: "Could not load the list.",
|
|
19
|
+
loading: "Loading data. Please wait.",
|
|
20
|
+
loadingMore: "Loading more…",
|
|
21
|
+
searchPlaceholder: "Search",
|
|
22
|
+
selectFilterPlaceholder: "Any"
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
//#endregion
|
|
26
|
+
export { testUiMessages };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { UI_DESCRIBE_REQUEST_ERROR, UI_ICON_CLASS, UI_MESSAGES } from "../plugin/ui-injection.js";
|
|
2
|
+
import { installToastService } from "../components/toast/install-toast-service.js";
|
|
3
|
+
import { testUiMessages } from "./ui-messages.fixture.js";
|
|
4
|
+
import UiVendor from "openvue/config";
|
|
5
|
+
//#region src/testing/vendor-plugins.ts
|
|
6
|
+
/**
|
|
7
|
+
* Installs the vendor plugins and everything the package receives from the app in specs: texts,
|
|
8
|
+
* icon classes and the request-error description. Swapping the vendor does not touch every spec.
|
|
9
|
+
* Works both via `global.plugins` of `\@vue/test-utils` and as a direct call on `createSSRApp`.
|
|
10
|
+
* @param app - Vue.js app created by a spec.
|
|
11
|
+
* @example
|
|
12
|
+
* mount(Checkbox, { global: { plugins: [installVendorPlugins] } })
|
|
13
|
+
*/
|
|
14
|
+
var installVendorPlugins = (app) => {
|
|
15
|
+
app.use(UiVendor);
|
|
16
|
+
app.provide(UI_MESSAGES, testUiMessages);
|
|
17
|
+
app.provide(UI_ICON_CLASS, (name) => `test-icon test-icon--${name}`);
|
|
18
|
+
app.provide(UI_DESCRIBE_REQUEST_ERROR, (_error, fallbackMessage) => fallbackMessage);
|
|
19
|
+
installToastService(app);
|
|
20
|
+
};
|
|
21
|
+
//#endregion
|
|
22
|
+
export { installVendorPlugins };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { DurationUnit } from 'date-fns';
|
|
2
|
+
export declare const formatDistance: (from: Date, to: Date) => string;
|
|
3
|
+
export declare const formatDate: (date: Date, formatString?: string) => string;
|
|
4
|
+
export declare const getDifferenceInHours: (start: Date, end: Date) => number;
|
|
5
|
+
export declare const formatDuration: (start: Date, end: Date, fff?: DurationUnit[]) => string;
|
|
6
|
+
export interface SignificantDurationInterface {
|
|
7
|
+
text: string;
|
|
8
|
+
truncated: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare const formatSignificantDuration: (start: Date, end: Date) => SignificantDurationInterface;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { differenceInHours, format, formatDistanceStrict, formatDuration, intervalToDuration } from "date-fns";
|
|
2
|
+
//#region src/utils/datetime.ts
|
|
3
|
+
var formatDistance = (from, to) => formatDistanceStrict(from, to, { addSuffix: true });
|
|
4
|
+
var formatDate = (date, formatString = "Pp") => format(date, formatString);
|
|
5
|
+
var getDifferenceInHours = (start, end) => differenceInHours(start, end);
|
|
6
|
+
var ALL_DURATION_UNITS = [
|
|
7
|
+
"years",
|
|
8
|
+
"months",
|
|
9
|
+
"days",
|
|
10
|
+
"hours",
|
|
11
|
+
"minutes",
|
|
12
|
+
"seconds"
|
|
13
|
+
];
|
|
14
|
+
var SIGNIFICANT_FORMATS = [
|
|
15
|
+
{
|
|
16
|
+
format: ["years"],
|
|
17
|
+
unit: "years"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
format: ["months"],
|
|
21
|
+
unit: "months"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
format: ["days", "hours"],
|
|
25
|
+
unit: "days"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
format: ["hours"],
|
|
29
|
+
unit: "hours"
|
|
30
|
+
}
|
|
31
|
+
];
|
|
32
|
+
/**
|
|
33
|
+
* Duration, усечённый до значимых единиц: «6 years 8 months 2 days …» → text «6 years»,
|
|
34
|
+
* «2 days 6 hours 44 minutes …» → text «2 days 6 hours»; минуты/секунды — без усечения.
|
|
35
|
+
* @param start - Левая граница (обычно timestamp события во внешнем источнике).
|
|
36
|
+
* @param end - Правая граница (обычно createdAt записи у нас).
|
|
37
|
+
* @returns Text по значимым единицам + флаг truncated (ненулевой хвост отброшен — caller добавляет «more than»).
|
|
38
|
+
* @example
|
|
39
|
+
* formatSignificantDuration(start, end) // { text: '2 days 6 hours', truncated: true }
|
|
40
|
+
*/
|
|
41
|
+
var formatSignificantDuration = (start, end) => {
|
|
42
|
+
const duration = intervalToDuration({
|
|
43
|
+
end,
|
|
44
|
+
start
|
|
45
|
+
});
|
|
46
|
+
const units = SIGNIFICANT_FORMATS.find(({ unit }) => (duration[unit] ?? 0) > 0)?.format ?? ["minutes", "seconds"];
|
|
47
|
+
return {
|
|
48
|
+
text: formatDuration(duration, { format: units }),
|
|
49
|
+
truncated: ALL_DURATION_UNITS.some((unit) => !units.includes(unit) && (duration[unit] ?? 0) > 0)
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
//#endregion
|
|
53
|
+
export { formatDate, formatDistance, formatSignificantDuration, getDifferenceInHours };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
//#region src/utils/truncate-string.ts
|
|
2
|
+
var truncateStringInTheMiddle = (string, length, delimiter = "...") => {
|
|
3
|
+
if (string.length <= length) return string;
|
|
4
|
+
const charsToShow = length - delimiter.length;
|
|
5
|
+
const frontChars = Math.ceil(charsToShow / 2);
|
|
6
|
+
const backChars = Math.floor(charsToShow / 2);
|
|
7
|
+
return string.slice(0, Math.max(0, frontChars)) + delimiter + string.slice(Math.max(0, string.length - backChars));
|
|
8
|
+
};
|
|
9
|
+
//#endregion
|
|
10
|
+
export { truncateStringInTheMiddle };
|
package/package.json
CHANGED
|
@@ -1,6 +1,96 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@application-kit/ui",
|
|
3
|
-
"version": "0.0.0
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "Vue-обёртки над UI-вендором, мост токенов оформления и тестовые помощники без продуктовых словарей",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"design-tokens",
|
|
7
|
+
"ssr",
|
|
8
|
+
"ui-kit",
|
|
9
|
+
"vue"
|
|
10
|
+
],
|
|
11
|
+
"homepage": "https://gitlab.com/application-kit/application-kit/-/tree/main/packages/ui",
|
|
12
|
+
"bugs": "https://gitlab.com/application-kit/application-kit/-/issues",
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "https://gitlab.com/application-kit/application-kit.git",
|
|
16
|
+
"directory": "packages/ui"
|
|
17
|
+
},
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"author": {
|
|
20
|
+
"name": "application-kit"
|
|
21
|
+
},
|
|
22
|
+
"sideEffects": [
|
|
23
|
+
"**/*.css"
|
|
24
|
+
],
|
|
25
|
+
"type": "module",
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"import": {
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"default": "./dist/index.js"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"./package.json": "./package.json",
|
|
34
|
+
"./style.css": "./dist/style.css",
|
|
35
|
+
"./styles/tokens.scss": "./dist/styles/_tokens.scss",
|
|
36
|
+
"./styles/variables.scss": "./dist/styles/_variables.scss",
|
|
37
|
+
"./testing": {
|
|
38
|
+
"import": {
|
|
39
|
+
"types": "./dist/testing/index.d.ts",
|
|
40
|
+
"default": "./dist/testing/index.js"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"main": "./dist/index.js",
|
|
45
|
+
"module": "./dist/index.js",
|
|
46
|
+
"types": "./dist/index.d.ts",
|
|
47
|
+
"files": [
|
|
48
|
+
"dist"
|
|
49
|
+
],
|
|
50
|
+
"scripts": {
|
|
51
|
+
"build": "rm -rf ./dist && vite build && vue-tsc --project tsconfig.build.json && mkdir -p ./dist/styles && cp ./src/styles/_tokens.scss ./src/styles/_variables.scss ./dist/styles/",
|
|
52
|
+
"lint:tsc": "vue-tsc --noEmit --pretty --project .",
|
|
53
|
+
"test:mutation": "stryker run",
|
|
54
|
+
"test:unit": "vitest run"
|
|
55
|
+
},
|
|
56
|
+
"dependencies": {
|
|
57
|
+
"@application-kit/typeorm": "^0.1.0",
|
|
58
|
+
"@openvue/themes": "1.0.0-rc.0",
|
|
59
|
+
"date-fns": "^4.4.0"
|
|
60
|
+
},
|
|
61
|
+
"devDependencies": {
|
|
62
|
+
"@stryker-mutator/core": "^10.0.0",
|
|
63
|
+
"@stryker-mutator/vitest-runner": "^10.0.0",
|
|
64
|
+
"@types/node": "^26.2.0",
|
|
65
|
+
"@vitejs/plugin-vue": "^6.0.8",
|
|
66
|
+
"@vue/test-utils": "^2.4.11",
|
|
67
|
+
"jsdom": "^30.0.1",
|
|
68
|
+
"openvue": "1.0.0-rc.0",
|
|
69
|
+
"pinia": "^4.0.3",
|
|
70
|
+
"sass-embedded": "^1.102.0",
|
|
71
|
+
"typescript": "^6.0.3",
|
|
72
|
+
"vite": "^8.2.1",
|
|
73
|
+
"vitest": "^4.1.11",
|
|
74
|
+
"vue": "^3.5.41",
|
|
75
|
+
"vue-router": "^5.2.0",
|
|
76
|
+
"vue-tsc": "^3.3.11"
|
|
77
|
+
},
|
|
78
|
+
"peerDependencies": {
|
|
79
|
+
"openvue": "1.0.0-rc.0",
|
|
80
|
+
"pinia": "^4.0.0",
|
|
81
|
+
"vitest": "^4.0.0",
|
|
82
|
+
"vue": "^3.5.0",
|
|
83
|
+
"vue-router": "^5.0.0"
|
|
84
|
+
},
|
|
85
|
+
"peerDependenciesMeta": {
|
|
86
|
+
"vitest": {
|
|
87
|
+
"optional": true
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
"engines": {
|
|
91
|
+
"node": ">=24"
|
|
92
|
+
},
|
|
93
|
+
"publishConfig": {
|
|
94
|
+
"access": "public"
|
|
95
|
+
}
|
|
6
96
|
}
|