@koobiq/components 20.3.1 → 20.4.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/accordion/accordion.scss +4 -1
- package/accordion/index.d.ts +36 -12
- package/alert/index.d.ts +8 -0
- package/breadcrumbs/index.d.ts +2 -0
- package/button-toggle/button-toggle-tokens.scss +14 -0
- package/button-toggle/button-toggle.scss +75 -3
- package/core/index.d.ts +146 -5
- package/core/option/_option-theme.scss +3 -0
- package/core/styles/common/_select.scss +98 -3
- package/core/styles/typography/_typography.scss +8 -0
- package/ellipsis-center/ellipsis-center.scss +31 -0
- package/ellipsis-center/index.d.ts +35 -2
- package/fesm2022/koobiq-components-accordion.mjs +143 -44
- package/fesm2022/koobiq-components-accordion.mjs.map +1 -1
- package/fesm2022/koobiq-components-alert.mjs +17 -1
- package/fesm2022/koobiq-components-alert.mjs.map +1 -1
- package/fesm2022/koobiq-components-autocomplete.mjs +2 -2
- package/fesm2022/koobiq-components-autocomplete.mjs.map +1 -1
- package/fesm2022/koobiq-components-breadcrumbs.mjs +8 -3
- package/fesm2022/koobiq-components-breadcrumbs.mjs.map +1 -1
- package/fesm2022/koobiq-components-button-toggle.mjs +2 -2
- package/fesm2022/koobiq-components-button-toggle.mjs.map +1 -1
- package/fesm2022/koobiq-components-code-block.mjs +10 -5
- package/fesm2022/koobiq-components-code-block.mjs.map +1 -1
- package/fesm2022/koobiq-components-core.mjs +214 -11
- package/fesm2022/koobiq-components-core.mjs.map +1 -1
- package/fesm2022/koobiq-components-dropdown.mjs +2 -2
- package/fesm2022/koobiq-components-dropdown.mjs.map +1 -1
- package/fesm2022/koobiq-components-ellipsis-center.mjs +101 -34
- package/fesm2022/koobiq-components-ellipsis-center.mjs.map +1 -1
- package/fesm2022/koobiq-components-file-upload.mjs +7 -7
- package/fesm2022/koobiq-components-file-upload.mjs.map +1 -1
- package/fesm2022/koobiq-components-filter-bar.mjs +94 -55
- package/fesm2022/koobiq-components-filter-bar.mjs.map +1 -1
- package/fesm2022/koobiq-components-inline-edit.mjs +177 -14
- package/fesm2022/koobiq-components-inline-edit.mjs.map +1 -1
- package/fesm2022/koobiq-components-list.mjs +359 -44
- package/fesm2022/koobiq-components-list.mjs.map +1 -1
- package/fesm2022/koobiq-components-markdown.mjs +6 -2
- package/fesm2022/koobiq-components-markdown.mjs.map +1 -1
- package/fesm2022/koobiq-components-modal.mjs +48 -7
- package/fesm2022/koobiq-components-modal.mjs.map +1 -1
- package/fesm2022/koobiq-components-select.mjs +117 -12
- package/fesm2022/koobiq-components-select.mjs.map +1 -1
- package/fesm2022/koobiq-components-sidebar.mjs +5 -1
- package/fesm2022/koobiq-components-sidebar.mjs.map +1 -1
- package/fesm2022/koobiq-components-sidepanel.mjs +25 -6
- package/fesm2022/koobiq-components-sidepanel.mjs.map +1 -1
- package/fesm2022/koobiq-components-tabs.mjs +460 -197
- package/fesm2022/koobiq-components-tabs.mjs.map +1 -1
- package/fesm2022/koobiq-components-time-range.mjs +388 -74
- package/fesm2022/koobiq-components-time-range.mjs.map +1 -1
- package/fesm2022/koobiq-components-timezone.mjs +4 -4
- package/fesm2022/koobiq-components-timezone.mjs.map +1 -1
- package/fesm2022/koobiq-components-title.mjs +15 -3
- package/fesm2022/koobiq-components-title.mjs.map +1 -1
- package/fesm2022/koobiq-components-tree-select.mjs +2 -2
- package/fesm2022/koobiq-components-tree-select.mjs.map +1 -1
- package/fesm2022/koobiq-components-tree.mjs +14 -4
- package/fesm2022/koobiq-components-tree.mjs.map +1 -1
- package/file-upload/file-upload.scss +0 -18
- package/file-upload/index.d.ts +1 -1
- package/file-upload/multiple-file-upload.component.scss +15 -3
- package/file-upload/single-file-upload.component.scss +10 -2
- package/filter-bar/filter-bar-tokens.scss +2 -1
- package/filter-bar/index.d.ts +41 -4
- package/filter-bar/pipes/base-pipe.scss +24 -6
- package/filter-bar/pipes/pipe-input.scss +3 -1
- package/inline-edit/index.d.ts +87 -8
- package/inline-edit/inline-edit-tokens.scss +1 -0
- package/inline-edit/inline-edit.scss +26 -0
- package/link/_link-theme.scss +50 -15
- package/list/index.d.ts +126 -5
- package/markdown/index.d.ts +2 -0
- package/modal/index.d.ts +16 -7
- package/navbar/_navbar-item_horizontal.scss +5 -0
- package/package.json +3 -3
- package/prebuilt-themes/dark-theme.css +1 -1
- package/prebuilt-themes/light-theme.css +1 -1
- package/prebuilt-themes/theme.css +1 -1
- package/schematics/migrations/alert-signals/index.js +4 -1
- package/schematics/migrations/autocomplete-panel-width-auto/index.js +3 -34
- package/schematics/migrations/empty-state-size-attr/index.js +3 -34
- package/schematics/migrations/filter-bar-signals/index.js +4 -1
- package/schematics/migrations/loader-overlay-size-attr/index.js +3 -34
- package/schematics/migrations/v20-upgrade/index.js +4 -1
- package/schematics/ng-add/index.js +1 -1
- package/schematics/utils/angular-parsing.js +11 -12
- package/schematics/utils/package-config.js +5 -4
- package/schematics/utils/typescript.js +24 -0
- package/select/_select-theme.scss +9 -1
- package/select/index.d.ts +18 -2
- package/select/select.scss +13 -0
- package/sidebar/index.d.ts +1 -0
- package/sidepanel/index.d.ts +9 -0
- package/tabs/_tabs-common.scss +111 -2
- package/tabs/index.d.ts +79 -48
- package/tabs/tab-group.scss +0 -4
- package/tabs/tab-header.scss +0 -2
- package/tabs/tab-nav-bar.scss +3 -11
- package/time-range/index.d.ts +140 -5
- package/time-range/time-range.scss +16 -1
- package/title/index.d.ts +10 -2
- package/tree/index.d.ts +1 -0
|
@@ -17,24 +17,6 @@
|
|
|
17
17
|
align-items: baseline;
|
|
18
18
|
gap: var(--dropzone-gap, var(--kbq-file-upload-size-dropzone-content-gap-horizontal));
|
|
19
19
|
}
|
|
20
|
-
|
|
21
|
-
.kbq-ellipsis-center {
|
|
22
|
-
position: relative;
|
|
23
|
-
display: flex;
|
|
24
|
-
|
|
25
|
-
.kbq-ellipsis-center_data-text-start {
|
|
26
|
-
flex: 0 1 auto;
|
|
27
|
-
overflow: hidden;
|
|
28
|
-
text-overflow: ellipsis;
|
|
29
|
-
white-space: pre;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
.kbq-ellipsis-center_data-text-end {
|
|
33
|
-
flex: 1 0 auto;
|
|
34
|
-
overflow: hidden;
|
|
35
|
-
white-space: pre;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
20
|
}
|
|
39
21
|
|
|
40
22
|
.kbq-file-upload__hint {
|
package/file-upload/index.d.ts
CHANGED
|
@@ -129,7 +129,7 @@ declare class KbqFileList<T> {
|
|
|
129
129
|
addArray(items: T[]): void;
|
|
130
130
|
/** Replaces the current list with the specified items and emits event. */
|
|
131
131
|
replace(items: T[]): void;
|
|
132
|
-
/** Removes
|
|
132
|
+
/** Removes every occurrence of the specified item. Returns the removed items. */
|
|
133
133
|
remove(item: T): T[];
|
|
134
134
|
/** Removes item at specified index. Returns removed items and emits event. */
|
|
135
135
|
removeAt(index: number): T[];
|
|
@@ -225,6 +225,13 @@
|
|
|
225
225
|
align-items: center;
|
|
226
226
|
flex: 1;
|
|
227
227
|
|
|
228
|
+
// The file name is rendered into `white-space: pre` spans by `kbqEllipsisCenter`, and the tail span
|
|
229
|
+
// is `flex-shrink: 0`. Under the default `min-width: auto` that intrinsic width propagates up
|
|
230
|
+
// through every flex item here, so a long name widens the row past the list instead of being
|
|
231
|
+
// truncated — and `kbqEllipsisCenter` measures the overflowed `clientWidth`, so it truncates to a
|
|
232
|
+
// width that is off-screen.
|
|
233
|
+
min-width: 0;
|
|
234
|
+
|
|
228
235
|
.kbq-file-upload__grid-cell {
|
|
229
236
|
padding: 0 var(--kbq-file-upload-size-multiple-big-grid-cell-padding-horizontal);
|
|
230
237
|
}
|
|
@@ -235,9 +242,13 @@
|
|
|
235
242
|
flex-grow: 1;
|
|
236
243
|
gap: var(--kbq-file-upload-size-multiple-big-grid-cell-content-gap-horizontal);
|
|
237
244
|
padding-left: var(--kbq-size-m);
|
|
245
|
+
min-width: 0;
|
|
238
246
|
|
|
239
247
|
.kbq-file-item__text {
|
|
240
|
-
width:
|
|
248
|
+
// Takes whatever is left between the icon and the size column. The `min-width: 0` and
|
|
249
|
+
// `overflow: hidden` that let it shrink below the name's intrinsic width come from
|
|
250
|
+
// `.kbq-ellipsis-center`, which this element also is.
|
|
251
|
+
flex: 1 1 auto;
|
|
241
252
|
}
|
|
242
253
|
}
|
|
243
254
|
|
|
@@ -253,8 +264,9 @@
|
|
|
253
264
|
width: var(--kbq-file-upload-size-multiple-big-grid-cell-file-size-width);
|
|
254
265
|
min-width: var(--kbq-file-upload-size-multiple-big-grid-cell-file-size-width);
|
|
255
266
|
max-width: var(--kbq-file-upload-size-multiple-big-grid-cell-file-size-width);
|
|
256
|
-
|
|
257
|
-
|
|
267
|
+
// The three widths above already pin the column, so growing and shrinking were both inert.
|
|
268
|
+
// Stated outright now that the file-name cell beside it actually shrinks.
|
|
269
|
+
flex: none;
|
|
258
270
|
text-align: left;
|
|
259
271
|
}
|
|
260
272
|
|
|
@@ -113,17 +113,25 @@
|
|
|
113
113
|
|
|
114
114
|
.kbq-file-item {
|
|
115
115
|
width: 100%;
|
|
116
|
+
// The row sits beside the delete button in a flex container, and the wrapper below beside the
|
|
117
|
+
// size column. `min-width: auto` would let the file name's intrinsic width propagate up through
|
|
118
|
+
// both and push the row past the component instead of being shortened — and `kbqEllipsisCenter`
|
|
119
|
+
// measures the overflowed `clientWidth`, so it would shorten to a width that is off-screen.
|
|
120
|
+
min-width: 0;
|
|
116
121
|
|
|
117
122
|
.kbq-file-item__text-wrapper {
|
|
118
123
|
display: flex;
|
|
119
124
|
align-items: center;
|
|
120
125
|
width: 100%;
|
|
126
|
+
min-width: 0;
|
|
121
127
|
|
|
122
128
|
gap: var(--kbq-file-upload-size-single-container-content-gap-horizontal);
|
|
123
129
|
|
|
124
130
|
.kbq-file-item__text {
|
|
125
|
-
width:
|
|
126
|
-
|
|
131
|
+
// Takes whatever is left beside the icon and the size column. The `min-width: 0` and
|
|
132
|
+
// `overflow: hidden` that let it shrink below the name's intrinsic width come from
|
|
133
|
+
// `.kbq-ellipsis-center`, which this element also is.
|
|
134
|
+
flex: 1 1 auto;
|
|
127
135
|
}
|
|
128
136
|
}
|
|
129
137
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
.kbq-filter-bar {
|
|
2
|
-
/* Maximum width of a pipe
|
|
2
|
+
/* Maximum width of a whole pipe, clear and remove buttons included, and of the filters trigger.
|
|
3
|
+
The input pipe keeps its own width. */
|
|
3
4
|
--kbq-filter-bar-pipe-max-width: 320px;
|
|
4
5
|
/* Fixed width of the input pipe's field. Unlike the other pipes it never shrink-wraps its
|
|
5
6
|
content, so this is a width rather than a max-width. */
|
package/filter-bar/index.d.ts
CHANGED
|
@@ -63,6 +63,11 @@ declare abstract class KbqBasePipe<V> implements AfterViewInit {
|
|
|
63
63
|
* `undefined` leaves the list at the select-family default of 256px.
|
|
64
64
|
*/
|
|
65
65
|
protected panelMaxHeight?: KbqPanelMaxHeight;
|
|
66
|
+
/**
|
|
67
|
+
* Whether the dropdown's option names and captions wrap instead of being truncated, forwarded from
|
|
68
|
+
* the pipe template. Only consumed by the select / multi-select pipe components.
|
|
69
|
+
*/
|
|
70
|
+
protected multilineOptions?: boolean;
|
|
66
71
|
/**
|
|
67
72
|
* Whether the current platform is a Mac.
|
|
68
73
|
*
|
|
@@ -125,6 +130,13 @@ declare abstract class KbqBasePipe<V> implements AfterViewInit {
|
|
|
125
130
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<KbqBasePipe<any>, never>;
|
|
126
131
|
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<KbqBasePipe<any>, never, never, {}, {}, never, never, true, never>;
|
|
127
132
|
}
|
|
133
|
+
/**
|
|
134
|
+
* Keeps a pipe part at its natural width while its text is shorter than `maxSymbolsForFitContent`.
|
|
135
|
+
*
|
|
136
|
+
* @deprecated A pipe lays its name and value out as two shrinkable grid tracks, which already keeps a
|
|
137
|
+
* short part intact; on a grid item this `min-width` only pushes the part past its track, where it is
|
|
138
|
+
* clipped without an ellipsis. Will be removed in the next major.
|
|
139
|
+
*/
|
|
128
140
|
declare class KbqPipeMinWidth {
|
|
129
141
|
/** KbqFilterBar instance */
|
|
130
142
|
protected readonly filterBar: KbqFilterBarHost | null;
|
|
@@ -293,7 +305,11 @@ interface KbqFilterBarHost {
|
|
|
293
305
|
readonly internalFilterChanges: BehaviorSubject<KbqFilter | null>;
|
|
294
306
|
/** Internal pipe-template changes. */
|
|
295
307
|
readonly internalTemplatesChanges: BehaviorSubject<KbqPipeTemplate[] | null>;
|
|
296
|
-
/**
|
|
308
|
+
/**
|
|
309
|
+
* Requests that an already-added pipe open its pop-up. A one-shot command handled synchronously by the
|
|
310
|
+
* pipes that exist when it is dispatched, not retained state — clear it back to `null` after `next`. A
|
|
311
|
+
* pipe that has not been rendered yet is opened with `openOnAdd` on the pipe itself, not through this.
|
|
312
|
+
*/
|
|
297
313
|
readonly openPipe: BehaviorSubject<string | number | null>;
|
|
298
314
|
/** Emits when the filter is reset. */
|
|
299
315
|
readonly onResetFilter: BehaviorSubject<boolean>;
|
|
@@ -307,7 +323,11 @@ interface KbqFilterBarHost {
|
|
|
307
323
|
* `useExisting`, so pipes `inject(KBQ_FILTER_BAR_HOST)` instead of depending on the concrete bar.
|
|
308
324
|
*/
|
|
309
325
|
declare const KBQ_FILTER_BAR_HOST: InjectionToken<KbqFilterBarHost>;
|
|
310
|
-
/**
|
|
326
|
+
/**
|
|
327
|
+
* Injection Token for providing pipes in filter-bar. Defaults to {@link defaultFilterBarPipes} so the
|
|
328
|
+
* standalone `KbqFilterBar` works without `KbqFilterBarModule`; override it with
|
|
329
|
+
* {@link kbqFilterBarPipesProvider} or a provider of your own.
|
|
330
|
+
*/
|
|
311
331
|
declare const KBQ_FILTER_BAR_PIPES: InjectionToken<Map<KbqPipeType, Type<KbqBasePipe<unknown>>>>;
|
|
312
332
|
/** Utility provider for `KBQ_FILTER_BAR_PIPES`. */
|
|
313
333
|
declare const kbqFilterBarPipesProvider: () => Provider;
|
|
@@ -337,6 +357,11 @@ interface KbqSelectValue {
|
|
|
337
357
|
value: unknown;
|
|
338
358
|
/** Optional stable identifier used by the select/multi-select pipe comparators. */
|
|
339
359
|
id?: string | number;
|
|
360
|
+
/**
|
|
361
|
+
* Second line under `name` in the dropdown of the `select` / `multiselect` pipes. Ignored where a
|
|
362
|
+
* `valueTemplate` owns the option.
|
|
363
|
+
*/
|
|
364
|
+
caption?: string;
|
|
340
365
|
}
|
|
341
366
|
interface KbqFilter {
|
|
342
367
|
name: string;
|
|
@@ -401,6 +426,12 @@ interface KbqPipeTemplate extends Omit<KbqPipe, 'value'> {
|
|
|
401
426
|
* than scrolled. Ignored by other pipe types.
|
|
402
427
|
*/
|
|
403
428
|
panelMaxHeight?: KbqPanelMaxHeight;
|
|
429
|
+
/**
|
|
430
|
+
* Whether option names and captions in the dropdown wrap instead of being truncated to one line.
|
|
431
|
+
* Applies to the `select` and `multiselect` pipes; ignored by the other pipe types. Unrelated to
|
|
432
|
+
* `KbqSelect.multiline`, which lays the trigger's values out in rows.
|
|
433
|
+
*/
|
|
434
|
+
multilineOptions?: boolean;
|
|
404
435
|
/**
|
|
405
436
|
* Earliest selectable instant for the `date` / `datetime` pipe custom period. Accepts any value the
|
|
406
437
|
* configured `DateAdapter` can deserialize (with the default Luxon adapter: an ISO-8601 string, a
|
|
@@ -814,7 +845,7 @@ declare class KbqFilterBar implements KbqFilterBarHost {
|
|
|
814
845
|
readonly internalFilterChanges: BehaviorSubject<KbqFilter | null>;
|
|
815
846
|
/** internal changes in templates */
|
|
816
847
|
readonly internalTemplatesChanges: BehaviorSubject<KbqPipeTemplate[] | null>;
|
|
817
|
-
/**
|
|
848
|
+
/** Requests that an already-added pipe open its pop-up. See {@link KbqFilterBarHost.openPipe}.
|
|
818
849
|
* @docs-private */
|
|
819
850
|
readonly openPipe: BehaviorSubject<string | number | null>;
|
|
820
851
|
constructor();
|
|
@@ -987,7 +1018,13 @@ declare class KbqPipeState<T> {
|
|
|
987
1018
|
/** KbqFilterBar instance
|
|
988
1019
|
* @docs-private */
|
|
989
1020
|
private readonly filterBar;
|
|
990
|
-
/**
|
|
1021
|
+
/**
|
|
1022
|
+
* Pipe state the styled button belongs to.
|
|
1023
|
+
*
|
|
1024
|
+
* Carries the binding this directive's selector matches. Every binding passes the pipe's own `data`,
|
|
1025
|
+
* which is mutated in place, so this value is a constant for the life of the pipe and the style is
|
|
1026
|
+
* derived from `pipe.isEmpty` instead.
|
|
1027
|
+
*/
|
|
991
1028
|
readonly state: _angular_core.InputSignal<T | null>;
|
|
992
1029
|
constructor();
|
|
993
1030
|
private updateState;
|
|
@@ -5,27 +5,34 @@
|
|
|
5
5
|
display: flex;
|
|
6
6
|
flex-direction: row;
|
|
7
7
|
|
|
8
|
+
// Caps the whole pipe, clear and remove buttons included. The label's grid tracks have no
|
|
9
|
+
// min-content, so the trigger gives way down to its own paddings without `min-width: 0`.
|
|
10
|
+
max-width: var(--kbq-filter-bar-pipe-max-width, 320px);
|
|
8
11
|
max-height: 32px;
|
|
9
12
|
|
|
10
13
|
& .kbq-select .kbq-select__trigger {
|
|
11
14
|
height: unset;
|
|
12
15
|
}
|
|
13
16
|
|
|
14
|
-
|
|
15
|
-
|
|
17
|
+
// The button's default slot is a flex row; a pipe puts its own two independently truncated parts
|
|
18
|
+
// (name + value) in there as two shrinkable grid tracks instead: as flex items they would give up
|
|
19
|
+
// the same percentage, which wipes out a short name long before a long value becomes unreadable.
|
|
20
|
+
// Qualified with `.kbq-button` on purpose: the base rule is `.kbq-button .kbq-button-text`, so a
|
|
21
|
+
// two-class selector would only win on source order, which differs between app bundles.
|
|
22
|
+
.kbq-button .kbq-button-text {
|
|
23
|
+
display: grid;
|
|
24
|
+
grid-auto-flow: column;
|
|
25
|
+
grid-auto-columns: minmax(0, max-content);
|
|
26
|
+
align-items: center;
|
|
16
27
|
}
|
|
17
28
|
|
|
18
29
|
.kbq-pipe__name {
|
|
19
30
|
@include common.kbq-truncate-line();
|
|
20
|
-
|
|
21
|
-
flex: 1 1 auto;
|
|
22
31
|
}
|
|
23
32
|
|
|
24
33
|
.kbq-pipe__value {
|
|
25
34
|
@include common.kbq-truncate-line();
|
|
26
35
|
|
|
27
|
-
flex: 1 1 auto;
|
|
28
|
-
|
|
29
36
|
&:not(.kbq-pipe__value_empty) {
|
|
30
37
|
margin-inline-start: 4px;
|
|
31
38
|
}
|
|
@@ -83,4 +90,15 @@
|
|
|
83
90
|
}
|
|
84
91
|
}
|
|
85
92
|
|
|
93
|
+
// The dropdown is portaled into the overlay, so it is reachable only through the pipe's `panelClass`.
|
|
94
|
+
.kbq-pipe-select__panel_multiline,
|
|
95
|
+
.kbq-pipe-multiselect__panel_multiline {
|
|
96
|
+
// `overflow: hidden` from `kbq-list-text()` stays: it gives the flex item a minimum size of 0, so the
|
|
97
|
+
// text shrinks to the option width instead of stretching the row.
|
|
98
|
+
.kbq-option-text {
|
|
99
|
+
white-space: normal;
|
|
100
|
+
overflow-wrap: break-word;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
86
104
|
@include kbq-filter-bar-pipe-theme();
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
.kbq-pipe.kbq-pipe__input {
|
|
2
2
|
// Fall back like base-pipe.scss does for --kbq-filter-bar-pipe-max-width: the token is declared on
|
|
3
|
-
// .kbq-filter-bar, which a pipe rendered outside a bar never sees.
|
|
3
|
+
// .kbq-filter-bar, which a pipe rendered outside a bar never sees. The width is explicit, so the cap
|
|
4
|
+
// every other pipe takes from that token does not apply here.
|
|
4
5
|
width: var(--kbq-filter-bar-pipe-input-width, 240px);
|
|
6
|
+
max-width: none;
|
|
5
7
|
flex: none;
|
|
6
8
|
|
|
7
9
|
.kbq-form-field {
|
package/inline-edit/index.d.ts
CHANGED
|
@@ -1,14 +1,46 @@
|
|
|
1
|
+
import * as _koobiq_components_core from '@koobiq/components/core';
|
|
2
|
+
import { KbqConnectedOverlayOriginProvider, PopUpPlacements, KbqComponentColors } from '@koobiq/components/core';
|
|
1
3
|
import * as _angular_core from '@angular/core';
|
|
2
|
-
import { ElementRef, TemplateRef } from '@angular/core';
|
|
4
|
+
import { InjectionToken, ElementRef, TemplateRef } from '@angular/core';
|
|
3
5
|
import { ScrollStrategy, CdkConnectedOverlay } from '@angular/cdk/overlay';
|
|
4
|
-
import { KbqConnectedOverlayOriginProvider, PopUpPlacements, KbqComponentColors } from '@koobiq/components/core';
|
|
5
6
|
import { KbqDropdownTrigger } from '@koobiq/components/dropdown';
|
|
6
7
|
import { KbqLabel, KbqFormField } from '@koobiq/components/form-field';
|
|
7
8
|
import { KbqSelect } from '@koobiq/components/select';
|
|
8
9
|
import { KbqTooltipTrigger } from '@koobiq/components/tooltip';
|
|
10
|
+
import { Observable } from 'rxjs';
|
|
9
11
|
import * as i1 from '@angular/cdk/a11y';
|
|
10
12
|
|
|
13
|
+
/** Delay before the save progress state appears, so a fast response causes no flicker. */
|
|
14
|
+
declare const kbqInlineEditSaveProgressDelay = 100;
|
|
15
|
+
/** Minimum time the save progress state stays once it has appeared. */
|
|
16
|
+
declare const kbqInlineEditSaveProgressMinimumDuration = 300;
|
|
11
17
|
type KbqInlineEditMode = 'view' | 'edit';
|
|
18
|
+
/**
|
|
19
|
+
* Saves the edited value, e.g. sends it to a server. Only the first emission counts, and the observable must emit
|
|
20
|
+
* or complete: destroying the row does not cancel it, so one that never settles keeps the row in memory.
|
|
21
|
+
*
|
|
22
|
+
* Called without a receiver, so bind an arrow function rather than a method that relies on `this`.
|
|
23
|
+
*/
|
|
24
|
+
type KbqInlineEditSaveHandler = () => Observable<unknown>;
|
|
25
|
+
/** State of the save request started by `saveHandler`. `progress` is `pending` past the indicator delay. */
|
|
26
|
+
type KbqInlineEditSaveStatus = 'idle' | 'pending' | 'progress' | 'error';
|
|
27
|
+
/** Recovery a failed-save notification can offer: retry, edit again, discard the unsaved value. */
|
|
28
|
+
interface KbqInlineEditSaveRecovery {
|
|
29
|
+
retrySave(): void;
|
|
30
|
+
toggleMode(): void;
|
|
31
|
+
rollback(): void;
|
|
32
|
+
}
|
|
33
|
+
/** Failed save, reported through `saveError` and `KBQ_INLINE_EDIT_SAVE_ERROR_HANDLER`. */
|
|
34
|
+
interface KbqInlineEditSaveErrorContext<E = any> {
|
|
35
|
+
/** Parameterise the interface to type this. */
|
|
36
|
+
readonly error: E;
|
|
37
|
+
/** Inline edit whose save failed. */
|
|
38
|
+
readonly inlineEdit: KbqInlineEditSaveRecovery;
|
|
39
|
+
}
|
|
40
|
+
/** Reaction to a failed save, e.g. opening a toast. */
|
|
41
|
+
type KbqInlineEditSaveErrorHandler = (context: KbqInlineEditSaveErrorContext) => void;
|
|
42
|
+
/** Reports every failed save the same way across the application. Declare it in the root injector. */
|
|
43
|
+
declare const KBQ_INLINE_EDIT_SAVE_ERROR_HANDLER: InjectionToken<KbqInlineEditSaveErrorHandler>;
|
|
12
44
|
/** @docs-private */
|
|
13
45
|
declare class KbqFocusRegionItem {
|
|
14
46
|
readonly tabOut: _angular_core.OutputEmitterRef<KeyboardEvent>;
|
|
@@ -38,7 +70,9 @@ declare class KbqInlineEditMenu {
|
|
|
38
70
|
* This component is projecting edit/view mode templates and adds keyboard/pointer handlers.
|
|
39
71
|
* Edit mode opens in a positioned overlay that matches the view mode width or can be customized.
|
|
40
72
|
*/
|
|
41
|
-
declare class KbqInlineEdit implements KbqConnectedOverlayOriginProvider {
|
|
73
|
+
declare class KbqInlineEdit implements KbqConnectedOverlayOriginProvider, KbqInlineEditSaveRecovery {
|
|
74
|
+
/** Texts of the save status announcements. */
|
|
75
|
+
protected readonly a11yLocaleConfiguration: _angular_core.Signal<_koobiq_components_core.KbqA11yLocaleConfiguration>;
|
|
42
76
|
private readonly overlay;
|
|
43
77
|
private readonly document;
|
|
44
78
|
private readonly window;
|
|
@@ -46,6 +80,7 @@ declare class KbqInlineEdit implements KbqConnectedOverlayOriginProvider {
|
|
|
46
80
|
protected readonly elementRef: ElementRef<HTMLElement>;
|
|
47
81
|
private readonly ngZone;
|
|
48
82
|
private readonly scrollDispatcher;
|
|
83
|
+
private readonly destroyRef;
|
|
49
84
|
/**
|
|
50
85
|
* The validation tooltip is anchored inside the edit-mode overlay — an overlay inside another
|
|
51
86
|
* overlay. Its default `close()` scroll strategy would close it the moment either overlay's
|
|
@@ -83,6 +118,22 @@ declare class KbqInlineEdit implements KbqConnectedOverlayOriginProvider {
|
|
|
83
118
|
readonly getValueHandler: _angular_core.InputSignal<(() => unknown) | undefined>;
|
|
84
119
|
/** Handler function to update the value */
|
|
85
120
|
readonly setValueHandler: _angular_core.InputSignal<((value: any) => void) | undefined>;
|
|
121
|
+
/**
|
|
122
|
+
* Whether the value still equals the one the editor opened with, in which case `saveHandler` is not called.
|
|
123
|
+
* The default suits text and numbers; bind your own for arrays and objects, or `null` to send every time.
|
|
124
|
+
* A failed save is always retried, however the values compare.
|
|
125
|
+
*/
|
|
126
|
+
readonly compareWith: _angular_core.InputSignal<((a: any, b: any) => boolean) | null>;
|
|
127
|
+
/**
|
|
128
|
+
* Saves a valid value in the background: edit mode closes right away and view mode reports how the request
|
|
129
|
+
* went. Without it, a valid value is saved immediately.
|
|
130
|
+
*/
|
|
131
|
+
readonly saveHandler: _angular_core.InputSignal<KbqInlineEditSaveHandler | undefined>;
|
|
132
|
+
/**
|
|
133
|
+
* Reaction to a failed save for this inline edit alone. Defaults to `KBQ_INLINE_EDIT_SAVE_ERROR_HANDLER`;
|
|
134
|
+
* bind `null` to leave it without one.
|
|
135
|
+
*/
|
|
136
|
+
readonly saveErrorHandler: _angular_core.InputSignal<KbqInlineEditSaveErrorHandler | null>;
|
|
86
137
|
/** Customizable function that checks if saving on enter available. */
|
|
87
138
|
readonly canSaveOnEnter: _angular_core.InputSignal<(event: KeyboardEvent) => boolean>;
|
|
88
139
|
/**
|
|
@@ -97,6 +148,8 @@ declare class KbqInlineEdit implements KbqConnectedOverlayOriginProvider {
|
|
|
97
148
|
protected readonly saved: _angular_core.OutputEmitterRef<void>;
|
|
98
149
|
/** Emitted when the inline edit is canceled and changes are discarded. */
|
|
99
150
|
protected readonly canceled: _angular_core.OutputEmitterRef<void>;
|
|
151
|
+
/** Emitted when a `saveHandler` request fails. Silent once the row is destroyed; `saveErrorHandler` is not. */
|
|
152
|
+
protected readonly saveError: _angular_core.OutputEmitterRef<KbqInlineEditSaveErrorContext<any>>;
|
|
100
153
|
/** Emitted when mode switched to edit/view */
|
|
101
154
|
protected readonly modeChange: _angular_core.OutputEmitterRef<KbqInlineEditMode>;
|
|
102
155
|
/** @docs-private */
|
|
@@ -133,6 +186,17 @@ declare class KbqInlineEdit implements KbqConnectedOverlayOriginProvider {
|
|
|
133
186
|
protected readonly scrollStrategy: _angular_core.WritableSignal<ScrollStrategy>;
|
|
134
187
|
/** @docs-private */
|
|
135
188
|
readonly modeAsReadonly: _angular_core.Signal<KbqInlineEditMode>;
|
|
189
|
+
private readonly saveStatusSource;
|
|
190
|
+
/** State of the background save started by `saveHandler`. */
|
|
191
|
+
readonly saveStatus: _angular_core.Signal<KbqInlineEditSaveStatus>;
|
|
192
|
+
/** @docs-private */
|
|
193
|
+
protected readonly isSaving: _angular_core.Signal<boolean>;
|
|
194
|
+
/**
|
|
195
|
+
* Both save states are otherwise conveyed by colour alone. `aria-busy` cannot carry the first one: it is set
|
|
196
|
+
* on the row, which contains this region, and that tells assistive tech to hold the announcement back.
|
|
197
|
+
* @docs-private
|
|
198
|
+
*/
|
|
199
|
+
protected readonly saveStatusMessage: _angular_core.Signal<string>;
|
|
136
200
|
/** @docs-private */
|
|
137
201
|
protected readonly className: _angular_core.Signal<string>;
|
|
138
202
|
/** @docs-private */
|
|
@@ -148,10 +212,15 @@ declare class KbqInlineEdit implements KbqConnectedOverlayOriginProvider {
|
|
|
148
212
|
/** @docs-private */
|
|
149
213
|
protected readonly colors: typeof KbqComponentColors;
|
|
150
214
|
private initialValue;
|
|
215
|
+
/** Value sent by the in-flight `saveHandler` request, which becomes `lastSavedValue` once it succeeds. */
|
|
216
|
+
private submittedValue;
|
|
217
|
+
/** Last value the server accepted — what `rollback()` restores after a failed save. */
|
|
218
|
+
private lastSavedValue;
|
|
219
|
+
private destroyed;
|
|
151
220
|
/** Handle for an in-flight `showValidationTooltip()` scroll/settle request, if any. */
|
|
152
221
|
private validationTooltipScrollHandle;
|
|
153
222
|
constructor();
|
|
154
|
-
/** Manually switch mode */
|
|
223
|
+
/** Manually switch mode. Does nothing while a `saveHandler` request is in flight. */
|
|
155
224
|
toggleMode(): void;
|
|
156
225
|
/**
|
|
157
226
|
* Implements `KbqConnectedOverlayOriginProvider`, letting a nested `KbqFormField`'s control
|
|
@@ -160,14 +229,22 @@ declare class KbqInlineEdit implements KbqConnectedOverlayOriginProvider {
|
|
|
160
229
|
* @docs-private
|
|
161
230
|
*/
|
|
162
231
|
getConnectedOverlayOrigin(): ElementRef | undefined;
|
|
163
|
-
/** Saves the current value
|
|
232
|
+
/** Saves the current value, running the same validation as a normal save. */
|
|
164
233
|
commit(): void;
|
|
234
|
+
/** Repeats the request for a value the server rejected. Does nothing unless the last save failed. */
|
|
235
|
+
retrySave(): void;
|
|
236
|
+
/** Discards the value the server rejected, restoring the last saved one and closing the editor. */
|
|
237
|
+
rollback(): void;
|
|
165
238
|
/** @docs-private */
|
|
166
239
|
protected onClick(event: Event): void;
|
|
167
240
|
/** @docs-private */
|
|
168
241
|
protected onAttach(): void;
|
|
169
242
|
/** @docs-private */
|
|
170
243
|
protected save($event?: Event): void;
|
|
244
|
+
/** Runs `saveHandler` once and maps its lifecycle onto `saveStatus`, holding the progress state steady. */
|
|
245
|
+
private startSave;
|
|
246
|
+
private onSaveSucceeded;
|
|
247
|
+
private onSaveFailed;
|
|
171
248
|
/**
|
|
172
249
|
* Whether `overlayOrigin` is fully within the viewport and every registered `CdkScrollable`
|
|
173
250
|
* ancestor between it and the viewport. Ancestors without the `CdkScrollable` directive aren't
|
|
@@ -207,6 +284,8 @@ declare class KbqInlineEdit implements KbqConnectedOverlayOriginProvider {
|
|
|
207
284
|
*/
|
|
208
285
|
private setOverlayKeydownListener;
|
|
209
286
|
private saveAndFocusNextInlineEdit;
|
|
287
|
+
/** Whether saving would send back the value the editor opened with. */
|
|
288
|
+
private isUnchanged;
|
|
210
289
|
private isInvalid;
|
|
211
290
|
private getValue;
|
|
212
291
|
private setValue;
|
|
@@ -216,7 +295,7 @@ declare class KbqInlineEdit implements KbqConnectedOverlayOriginProvider {
|
|
|
216
295
|
private getInputNativeElement;
|
|
217
296
|
private markAllAsTouched;
|
|
218
297
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<KbqInlineEdit, never>;
|
|
219
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<KbqInlineEdit, "kbq-inline-edit", ["kbqInlineEdit"], { "showActions": { "alias": "showActions"; "required": false; "isSignal": true; }; "showTooltipOnError": { "alias": "showTooltipOnError"; "required": false; "isSignal": true; }; "validationTooltip": { "alias": "validationTooltip"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "editModeWidth": { "alias": "editModeWidth"; "required": false; "isSignal": true; }; "tooltipPlacement": { "alias": "tooltipPlacement"; "required": false; "isSignal": true; }; "overlayPanelClass": { "alias": "overlayPanelClass"; "required": false; "isSignal": true; }; "getValueHandler": { "alias": "getValueHandler"; "required": false; "isSignal": true; }; "setValueHandler": { "alias": "setValueHandler"; "required": false; "isSignal": true; }; "canSaveOnEnter": { "alias": "canSaveOnEnter"; "required": false; "isSignal": true; }; "interactiveSelectors": { "alias": "interactiveSelectors"; "required": false; "isSignal": true; }; }, { "saved": "saved"; "canceled": "canceled"; "modeChange": "modeChange"; }, ["menu", "label", "formFieldRefList", "selectRef"], ["kbq-label", "[kbqInlineEditViewMode]", "[kbqInlineEditMenu]", "[kbqInlineEditEditMode]"], true, [{ directive: typeof i1.CdkMonitorFocus; inputs: {}; outputs: {}; }]>;
|
|
298
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<KbqInlineEdit, "kbq-inline-edit", ["kbqInlineEdit"], { "showActions": { "alias": "showActions"; "required": false; "isSignal": true; }; "showTooltipOnError": { "alias": "showTooltipOnError"; "required": false; "isSignal": true; }; "validationTooltip": { "alias": "validationTooltip"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "editModeWidth": { "alias": "editModeWidth"; "required": false; "isSignal": true; }; "tooltipPlacement": { "alias": "tooltipPlacement"; "required": false; "isSignal": true; }; "overlayPanelClass": { "alias": "overlayPanelClass"; "required": false; "isSignal": true; }; "getValueHandler": { "alias": "getValueHandler"; "required": false; "isSignal": true; }; "setValueHandler": { "alias": "setValueHandler"; "required": false; "isSignal": true; }; "compareWith": { "alias": "compareWith"; "required": false; "isSignal": true; }; "saveHandler": { "alias": "saveHandler"; "required": false; "isSignal": true; }; "saveErrorHandler": { "alias": "saveErrorHandler"; "required": false; "isSignal": true; }; "canSaveOnEnter": { "alias": "canSaveOnEnter"; "required": false; "isSignal": true; }; "interactiveSelectors": { "alias": "interactiveSelectors"; "required": false; "isSignal": true; }; }, { "saved": "saved"; "canceled": "canceled"; "saveError": "saveError"; "modeChange": "modeChange"; }, ["menu", "label", "formFieldRefList", "selectRef"], ["kbq-label", "[kbqInlineEditViewMode]", "[kbqInlineEditMenu]", "[kbqInlineEditEditMode]"], true, [{ directive: typeof i1.CdkMonitorFocus; inputs: {}; outputs: {}; }]>;
|
|
220
299
|
}
|
|
221
300
|
|
|
222
301
|
declare class KbqInlineEditModule {
|
|
@@ -225,5 +304,5 @@ declare class KbqInlineEditModule {
|
|
|
225
304
|
static ɵinj: _angular_core.ɵɵInjectorDeclaration<KbqInlineEditModule>;
|
|
226
305
|
}
|
|
227
306
|
|
|
228
|
-
export { KbqFocusRegionItem, KbqInlineEdit, KbqInlineEditMenu, KbqInlineEditModule, KbqInlineEditPlaceholder };
|
|
229
|
-
export type { KbqInlineEditMode };
|
|
307
|
+
export { KBQ_INLINE_EDIT_SAVE_ERROR_HANDLER, KbqFocusRegionItem, KbqInlineEdit, KbqInlineEditMenu, KbqInlineEditModule, KbqInlineEditPlaceholder, kbqInlineEditSaveProgressDelay, kbqInlineEditSaveProgressMinimumDuration };
|
|
308
|
+
export type { KbqInlineEditMode, KbqInlineEditSaveErrorContext, KbqInlineEditSaveErrorHandler, KbqInlineEditSaveHandler, KbqInlineEditSaveRecovery, KbqInlineEditSaveStatus };
|
|
@@ -5,4 +5,5 @@
|
|
|
5
5
|
--kbq-inline-edit-padding-vertical: calc(var(--kbq-size-xs) - var(--kbq-size-border-width));
|
|
6
6
|
--kbq-inline-edit-panel-shadow: var(--kbq-shadow-popup);
|
|
7
7
|
--kbq-inline-edit-label-color: var(--kbq-foreground-contrast-secondary);
|
|
8
|
+
--kbq-inline-edit-error-background: var(--kbq-background-error-less);
|
|
8
9
|
}
|
|
@@ -81,6 +81,31 @@
|
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
+
/**
|
|
85
|
+
* A save the server rejected keeps the unsaved value marked until the user reacts to the notification, so the
|
|
86
|
+
* state outlives the request itself. Every state `_inline-edit-theme()` paints a background for is repeated here
|
|
87
|
+
* with the error color: each of its selectors is more specific than the plain `.kbq-inline-edit_save-error` rule,
|
|
88
|
+
* so leaving one out would drop the marking in that state.
|
|
89
|
+
*/
|
|
90
|
+
@mixin _inline-edit-save-error-theme {
|
|
91
|
+
&.kbq-inline-edit_view.kbq-inline-edit_save-error {
|
|
92
|
+
--kbq-inline-edit-background: var(--kbq-inline-edit-error-background);
|
|
93
|
+
|
|
94
|
+
&:not(.kbq-inline-edit_disabled) {
|
|
95
|
+
&:hover {
|
|
96
|
+
--kbq-inline-edit-background: var(--kbq-states-background-error-less-hover);
|
|
97
|
+
--kbq-mask-background: var(--kbq-states-background-error-less-hover);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
&:active,
|
|
101
|
+
&:has(.kbq-inline-edit__menu.kbq-active) {
|
|
102
|
+
--kbq-inline-edit-background: var(--kbq-states-background-error-less-active);
|
|
103
|
+
--kbq-mask-background: var(--kbq-states-background-error-less-active);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
84
109
|
@mixin _inline-edit-typography {
|
|
85
110
|
@include tokens.kbq-typography-level-to-styles-css-variables(typography, text-normal);
|
|
86
111
|
}
|
|
@@ -97,6 +122,7 @@
|
|
|
97
122
|
min-height: var(--kbq-inline-edit-height);
|
|
98
123
|
|
|
99
124
|
@include _inline-edit-theme();
|
|
125
|
+
@include _inline-edit-save-error-theme();
|
|
100
126
|
@include _inline-edit-typography();
|
|
101
127
|
|
|
102
128
|
&:not(.kbq-inline-edit_with-label) {
|
package/link/_link-theme.scss
CHANGED
|
@@ -1,7 +1,33 @@
|
|
|
1
|
+
@use 'sass:string';
|
|
2
|
+
|
|
1
3
|
@use '../core/styles/common/tokens' as *;
|
|
2
4
|
|
|
3
5
|
@use './link-tokens';
|
|
4
6
|
|
|
7
|
+
// Unquoted, so that the joiner reaches the CSS as an escape rather than as an invisible character
|
|
8
|
+
$_kbq-link-word-joiner: string.unquote('"\\2060"');
|
|
9
|
+
|
|
10
|
+
// The width of a 16px icon less half a pixel: Chromium lays out a line that ends in negative letter-spacing a
|
|
11
|
+
// fraction wider than the max-content size it reports, so the full width would push the last word to the next
|
|
12
|
+
// line in a shrink-to-fit container.
|
|
13
|
+
$_kbq-link-trailing-icon-reserve: 15.5px;
|
|
14
|
+
|
|
15
|
+
// The gap after the text. Before an icon it is part of the reserve instead of a margin: Firefox does not always
|
|
16
|
+
// keep a margin together with the last word, and the icon could wrap alone again.
|
|
17
|
+
@mixin _kbq-link-text-end-gap($gap) {
|
|
18
|
+
&:not(:last-child) {
|
|
19
|
+
margin-right: $gap;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
&:has(+ .kbq-icon) {
|
|
23
|
+
margin-right: 0;
|
|
24
|
+
|
|
25
|
+
&::after {
|
|
26
|
+
padding-inline-end: calc($gap + $_kbq-link-trailing-icon-reserve);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
5
31
|
@mixin kbq-link-geometry() {
|
|
6
32
|
display: inline;
|
|
7
33
|
|
|
@@ -38,6 +64,21 @@
|
|
|
38
64
|
line-height: 0;
|
|
39
65
|
}
|
|
40
66
|
}
|
|
67
|
+
|
|
68
|
+
// A line may break right before an icon, as before any inline-block, and neither a no-break character
|
|
69
|
+
// nor white-space stops that in every engine. So the text reserves room for the icon after its last
|
|
70
|
+
// word, glued to it by a word joiner kept out of the accessible name, and the icon moves back into that
|
|
71
|
+
// room: the last word and the icon fit on the line together or wrap together.
|
|
72
|
+
.kbq-link__text:has(+ .kbq-icon) {
|
|
73
|
+
&::after {
|
|
74
|
+
content: $_kbq-link-word-joiner;
|
|
75
|
+
content: $_kbq-link-word-joiner / '';
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
+ .kbq-icon {
|
|
79
|
+
margin-inline-start: -$_kbq-link-trailing-icon-reserve;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
41
82
|
}
|
|
42
83
|
|
|
43
84
|
&.kbq-text-with-icon .kbq-link__text {
|
|
@@ -45,9 +86,7 @@
|
|
|
45
86
|
margin-left: var(--kbq-link-size-normal-content-padding);
|
|
46
87
|
}
|
|
47
88
|
|
|
48
|
-
|
|
49
|
-
margin-right: var(--kbq-link-size-normal-content-padding);
|
|
50
|
-
}
|
|
89
|
+
@include _kbq-link-text-end-gap(var(--kbq-link-size-normal-content-padding));
|
|
51
90
|
}
|
|
52
91
|
|
|
53
92
|
&.kbq-link_compact {
|
|
@@ -65,9 +104,7 @@
|
|
|
65
104
|
margin-left: var(--kbq-link-size-compact-content-padding);
|
|
66
105
|
}
|
|
67
106
|
|
|
68
|
-
|
|
69
|
-
margin-right: var(--kbq-link-size-compact-content-padding);
|
|
70
|
-
}
|
|
107
|
+
@include _kbq-link-text-end-gap(var(--kbq-link-size-compact-content-padding));
|
|
71
108
|
}
|
|
72
109
|
}
|
|
73
110
|
}
|
|
@@ -78,20 +115,18 @@
|
|
|
78
115
|
margin-left: var(--kbq-link-size-big-content-padding);
|
|
79
116
|
}
|
|
80
117
|
|
|
81
|
-
|
|
82
|
-
margin-right: var(--kbq-link-size-big-content-padding);
|
|
83
|
-
}
|
|
118
|
+
@include _kbq-link-text-end-gap(var(--kbq-link-size-big-content-padding));
|
|
84
119
|
}
|
|
85
120
|
}
|
|
86
121
|
|
|
87
122
|
&.kbq-text-with-icon.kbq-link_external {
|
|
88
|
-
.kbq-link__text
|
|
89
|
-
|
|
123
|
+
.kbq-link__text {
|
|
124
|
+
@include _kbq-link-text-end-gap(1px);
|
|
90
125
|
}
|
|
91
126
|
|
|
92
127
|
&.kbq-link_compact {
|
|
93
|
-
.kbq-link__text
|
|
94
|
-
|
|
128
|
+
.kbq-link__text {
|
|
129
|
+
@include _kbq-link-text-end-gap(0px);
|
|
95
130
|
}
|
|
96
131
|
|
|
97
132
|
.kbq-icon {
|
|
@@ -100,8 +135,8 @@
|
|
|
100
135
|
}
|
|
101
136
|
|
|
102
137
|
&.kbq-link_big {
|
|
103
|
-
.kbq-link__text
|
|
104
|
-
|
|
138
|
+
.kbq-link__text {
|
|
139
|
+
@include _kbq-link-text-end-gap(2px);
|
|
105
140
|
}
|
|
106
141
|
}
|
|
107
142
|
}
|