@cloud-ru/ds-fields 2.2.7-preview-a2208aeb.0 → 2.2.7-preview-c228f409.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 +0 -1
- package/dist/cjs/components/FieldColor/FieldColor.js +1 -1
- package/dist/cjs/components/FieldColor/styles.module.css +9 -9
- package/dist/cjs/components/FieldCombo/FieldCombo.js +1 -1
- package/dist/cjs/components/FieldDate/styles.module.css +3 -3
- package/dist/cjs/components/FieldSecure/FieldSecure.js +1 -1
- package/dist/cjs/components/FieldSelect/FieldSelect.js +2 -2
- package/dist/cjs/components/FieldSelect/styles.module.css +18 -15
- package/dist/cjs/components/FieldSelect/types.d.ts +1 -1
- package/dist/cjs/components/FieldSlider/FieldSlider.js +1 -1
- package/dist/cjs/components/FieldSlider/styles.module.css +7 -0
- package/dist/cjs/components/FieldStepper/FieldStepper.js +2 -2
- package/dist/cjs/components/FieldStepper/styles.module.css +52 -6
- package/dist/cjs/components/FieldTextArea/FieldTextArea.js +1 -1
- package/dist/cjs/components/FieldTextArea/styles.module.css +36 -39
- package/dist/cjs/components/FieldTime/FieldTime.js +1 -1
- package/dist/cjs/components/shared/helperComponents/FieldElementButton/styles.module.css +22 -22
- package/dist/cjs/components/shared/helperComponents/FieldShell/FieldShell.d.ts +1 -3
- package/dist/cjs/components/shared/helperComponents/FieldShell/FieldShell.js +2 -2
- package/dist/cjs/components/shared/styles.module.css +124 -151
- package/dist/cjs/style.css +271 -245
- package/dist/esm/components/FieldColor/FieldColor.js +1 -1
- package/dist/esm/components/FieldColor/styles.module.css +9 -9
- package/dist/esm/components/FieldCombo/FieldCombo.js +1 -1
- package/dist/esm/components/FieldDate/styles.module.css +3 -3
- package/dist/esm/components/FieldSecure/FieldSecure.js +1 -1
- package/dist/esm/components/FieldSelect/FieldSelect.js +2 -2
- package/dist/esm/components/FieldSelect/styles.module.css +18 -15
- package/dist/esm/components/FieldSelect/types.d.ts +1 -1
- package/dist/esm/components/FieldSlider/FieldSlider.js +2 -2
- package/dist/esm/components/FieldSlider/styles.module.css +7 -0
- package/dist/esm/components/FieldStepper/FieldStepper.js +2 -2
- package/dist/esm/components/FieldStepper/styles.module.css +52 -6
- package/dist/esm/components/FieldTextArea/FieldTextArea.js +1 -1
- package/dist/esm/components/FieldTextArea/styles.module.css +36 -39
- package/dist/esm/components/FieldTime/FieldTime.js +1 -1
- package/dist/esm/components/shared/helperComponents/FieldElementButton/styles.module.css +22 -22
- package/dist/esm/components/shared/helperComponents/FieldShell/FieldShell.d.ts +1 -3
- package/dist/esm/components/shared/helperComponents/FieldShell/FieldShell.js +2 -2
- package/dist/esm/components/shared/styles.module.css +124 -151
- package/dist/esm/style.css +271 -245
- package/dist/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/tsconfig.esm.tsbuildinfo +1 -1
- package/package.json +17 -17
- package/src/components/FieldColor/FieldColor.tsx +1 -1
- package/src/components/FieldColor/styles.module.scss +7 -5
- package/src/components/FieldCombo/FieldCombo.tsx +1 -1
- package/src/components/FieldDate/styles.module.scss +1 -1
- package/src/components/FieldSecure/FieldSecure.tsx +1 -2
- package/src/components/FieldSelect/FieldSelect.tsx +0 -2
- package/src/components/FieldSelect/styles.module.scss +5 -7
- package/src/components/FieldSelect/types.ts +0 -1
- package/src/components/FieldSlider/FieldSlider.tsx +3 -3
- package/src/components/FieldSlider/styles.module.scss +8 -0
- package/src/components/FieldStepper/FieldStepper.tsx +41 -46
- package/src/components/FieldStepper/styles.module.scss +60 -10
- package/src/components/FieldTextArea/FieldTextArea.tsx +1 -2
- package/src/components/FieldTextArea/styles.module.scss +22 -33
- package/src/components/FieldTime/FieldTime.tsx +1 -1
- package/src/components/shared/helperComponents/FieldElementButton/styles.module.scss +2 -2
- package/src/components/shared/helperComponents/FieldShell/FieldShell.tsx +0 -4
- package/src/components/shared/styles.module.scss +17 -58
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloud-ru/ds-fields",
|
|
3
|
-
"version": "2.2.7-preview-
|
|
3
|
+
"version": "2.2.7-preview-c228f409.0",
|
|
4
4
|
"description": "Поля ввода с единой обёрткой label/caption/hint/error и общими осями size/validationState — текст, пароль, число, ползунок, дата, время, выбор, цвет.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -39,24 +39,24 @@
|
|
|
39
39
|
"classnames": "^2.5.1",
|
|
40
40
|
"merge-refs": "^2.0.0",
|
|
41
41
|
"react-textarea-autosize": "^8.5.9",
|
|
42
|
-
"@cloud-ru/ds-bottom-sheet": "1.1.3-preview-a2208aeb.0",
|
|
43
42
|
"@cloud-ru/ds-adaptive": "1.0.1",
|
|
44
|
-
"@cloud-ru/ds-
|
|
45
|
-
"@cloud-ru/ds-
|
|
46
|
-
"@cloud-ru/ds-field-decorator": "1.0.7-preview-a2208aeb.0",
|
|
43
|
+
"@cloud-ru/ds-calendar": "1.0.19-preview-c228f409.0",
|
|
44
|
+
"@cloud-ru/ds-button": "1.0.2",
|
|
47
45
|
"@cloud-ru/ds-divider": "1.0.1",
|
|
48
|
-
"@cloud-ru/ds-
|
|
49
|
-
"@cloud-ru/ds-
|
|
50
|
-
"@cloud-ru/ds-
|
|
51
|
-
"@cloud-ru/ds-
|
|
52
|
-
"@cloud-ru/ds-
|
|
53
|
-
"@cloud-ru/ds-
|
|
54
|
-
"@cloud-ru/ds-
|
|
46
|
+
"@cloud-ru/ds-dropdown": "1.0.10-preview-c228f409.0",
|
|
47
|
+
"@cloud-ru/ds-field-decorator": "1.0.7-preview-c228f409.0",
|
|
48
|
+
"@cloud-ru/ds-bottom-sheet": "1.1.3-preview-c228f409.0",
|
|
49
|
+
"@cloud-ru/ds-color-picker": "1.0.8-preview-c228f409.0",
|
|
50
|
+
"@cloud-ru/ds-icons": "1.2.0",
|
|
51
|
+
"@cloud-ru/ds-input-private": "1.0.5",
|
|
52
|
+
"@cloud-ru/ds-list": "2.2.1-preview-c228f409.0",
|
|
53
|
+
"@cloud-ru/ds-loader": "1.0.1",
|
|
54
|
+
"@cloud-ru/ds-materials": "1.0.1",
|
|
55
|
+
"@cloud-ru/ds-scroll": "1.0.3-preview-c228f409.0",
|
|
55
56
|
"@cloud-ru/ds-skeleton": "1.0.1",
|
|
56
|
-
"@cloud-ru/ds-
|
|
57
|
-
"@cloud-ru/ds-
|
|
58
|
-
"@cloud-ru/ds-
|
|
59
|
-
"@cloud-ru/ds-utils": "1.1.0"
|
|
60
|
-
"@cloud-ru/ds-tooltip": "1.0.6-preview-a2208aeb.0"
|
|
57
|
+
"@cloud-ru/ds-slider": "1.0.5",
|
|
58
|
+
"@cloud-ru/ds-tag": "1.1.3-preview-c228f409.0",
|
|
59
|
+
"@cloud-ru/ds-tooltip": "1.0.5",
|
|
60
|
+
"@cloud-ru/ds-utils": "1.1.0"
|
|
61
61
|
}
|
|
62
62
|
}
|
|
@@ -329,8 +329,8 @@ export const FieldColor = forwardRef<HTMLInputElement, FieldColorProps>(function
|
|
|
329
329
|
{...restInputProps}
|
|
330
330
|
data-test-id={TEST_IDS.fieldColorInput}
|
|
331
331
|
/>
|
|
332
|
+
{postfixButtons && <span className={fieldStyles.postfixButtonsSlot}>{postfixButtons}</span>}
|
|
332
333
|
</div>
|
|
333
|
-
{postfixButtons && <span className={fieldStyles.postfixButtonsSlot}>{postfixButtons}</span>}
|
|
334
334
|
</div>
|
|
335
335
|
{/* Chevron присутствует во всех состояниях, включая readonly — паритет с Figma
|
|
336
336
|
readonly-варианты тоже показывают chevron-down рядом с copy). */}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
@use '@cloud-ru/ds-figma-variables/build/scss/styles/styles.module' as base;
|
|
2
2
|
@use '@cloud-ru/ds-figma-variables/build/scss/components/colorPicker.module' as colorPicker;
|
|
3
3
|
|
|
4
|
-
// FieldColor size →
|
|
5
|
-
// s →
|
|
4
|
+
// FieldColor size → colorPicker previewColor size (Figma fieldSelectColor):
|
|
5
|
+
// s → colorPicker s (16px / radius 4), m → colorPicker m (24px / radius 8),
|
|
6
|
+
// l → colorPicker m (24px / radius 8) — в макете L-поле референсит m-токен previewColor,
|
|
7
|
+
// swatch не увеличивается до 32.
|
|
6
8
|
$swatch-sizes: (
|
|
7
|
-
's': '
|
|
8
|
-
'm': '
|
|
9
|
-
'l': '
|
|
9
|
+
's': 's',
|
|
10
|
+
'm': 'm',
|
|
11
|
+
'l': 'm',
|
|
10
12
|
);
|
|
11
13
|
|
|
12
14
|
.trigger {
|
|
@@ -453,8 +453,8 @@ export const FieldCombo = forwardRef<HTMLInputElement, FieldComboProps>(function
|
|
|
453
453
|
autoFocus={resolvedAutoFocus}
|
|
454
454
|
data-test-id={innerTestIds?.input ?? TEST_IDS.fieldComboInput}
|
|
455
455
|
/>
|
|
456
|
+
{postfixButtons && <span className={fieldStyles.postfixButtonsSlot}>{postfixButtons}</span>}
|
|
456
457
|
</div>
|
|
457
|
-
{postfixButtons && <span className={fieldStyles.postfixButtonsSlot}>{postfixButtons}</span>}
|
|
458
458
|
{postfix && <span className={fieldStyles.postfix}>{postfix}</span>}
|
|
459
459
|
</div>
|
|
460
460
|
{iconAfter && <div className={fieldStyles.iconSlot}>{iconAfter}</div>}
|
|
@@ -27,7 +27,7 @@ $sizes: 's', 'm', 'l';
|
|
|
27
27
|
|
|
28
28
|
@each $size in $sizes {
|
|
29
29
|
[data-size='#{$size}'] & {
|
|
30
|
-
gap: base.simple-var(field.$field, 'anatomy', 'size', $size, 'fieldContainer', 'contentWrapper', '
|
|
30
|
+
gap: base.simple-var(field.$field, 'anatomy', 'size', $size, 'fieldContainer', 'contentWrapper', 'inputLine', 'gap');
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
}
|
|
@@ -346,8 +346,8 @@ export const FieldSecure = forwardRef<HTMLInputElement, FieldSecureProps>(functi
|
|
|
346
346
|
data-test-id={TEST_IDS.fieldSecureInput}
|
|
347
347
|
/>
|
|
348
348
|
</WithSkeleton>
|
|
349
|
+
{postfixButtons && <span className={fieldStyles.postfixButtonsSlot}>{postfixButtons}</span>}
|
|
349
350
|
</div>
|
|
350
|
-
{postfixButtons && <span className={fieldStyles.postfixButtonsSlot}>{postfixButtons}</span>}
|
|
351
351
|
</div>
|
|
352
352
|
</div>
|
|
353
353
|
</div>
|
|
@@ -358,7 +358,6 @@ export const FieldSecure = forwardRef<HTMLInputElement, FieldSecureProps>(functi
|
|
|
358
358
|
</div>
|
|
359
359
|
<FieldElementButton
|
|
360
360
|
ref={hideButtonRef}
|
|
361
|
-
className={fieldStyles.elementButtonInheritDisabled}
|
|
362
361
|
variant='after'
|
|
363
362
|
size={size}
|
|
364
363
|
action={hidden ? <EyeSVG /> : <EyeClosedSVG />}
|
|
@@ -92,7 +92,6 @@ export const FieldSelect = forwardRef<HTMLInputElement, FieldSelectProps>(functi
|
|
|
92
92
|
enableFuzzySearch = true,
|
|
93
93
|
selectedOptionFormatter,
|
|
94
94
|
footer,
|
|
95
|
-
footerDivider,
|
|
96
95
|
footerActiveElementsRefs,
|
|
97
96
|
loading,
|
|
98
97
|
noDataState,
|
|
@@ -705,7 +704,6 @@ export const FieldSelect = forwardRef<HTMLInputElement, FieldSelectProps>(functi
|
|
|
705
704
|
selection={droplistSelection}
|
|
706
705
|
closeDroplistOnItemClick={closeDroplistOnItemClick}
|
|
707
706
|
footer={footer}
|
|
708
|
-
footerDivider={footerDivider}
|
|
709
707
|
footerActiveElementsRefs={footerActiveElementsRefs}
|
|
710
708
|
loading={loading}
|
|
711
709
|
noDataState={noDataState}
|
|
@@ -54,16 +54,14 @@ $chip-sizes: (
|
|
|
54
54
|
|
|
55
55
|
@each $size, $tagSize in $chip-sizes {
|
|
56
56
|
[data-size='#{$size}'] & {
|
|
57
|
-
$contentPaddingTop: base.simple-var(field.$field, 'anatomy', 'size', $size, 'fieldContainer', 'contentWrapper', 'padding-top');
|
|
58
|
-
$contentPaddingBottom: base.simple-var(field.$field, 'anatomy', 'size', $size, 'fieldContainer', 'contentWrapper', 'padding-bottom');
|
|
59
|
-
$inputWrapper: base.simple-var(field.$field, 'anatomy', 'size', $size, 'fieldContainer', 'contentWrapper', 'inputWrapper');
|
|
60
57
|
// gap = tag.tagRow.gap по mapped tag size (Figma fieldSelectMultiple chips: 2 для xs/s) —
|
|
61
58
|
// одновременно column- и row-gap при flex-wrap (отступ между чипами и между рядами).
|
|
62
59
|
gap: base.simple-var(tag.$tag, 'anatomy', 'size', $tagSize, 'tagRow', 'gap');
|
|
63
|
-
|
|
64
|
-
//
|
|
65
|
-
|
|
66
|
-
|
|
60
|
+
// Вертикальные отступы строк чипов (Figma fieldContainer.contentWrapper.verticalPadding) —
|
|
61
|
+
// shared-поле их не применяет (single-line центрируется), а мультиселекту они нужны, чтобы
|
|
62
|
+
// ряды чипов не липли к краям контейнера (пропавшие отступы по макету).
|
|
63
|
+
padding-top: base.simple-var(field.$field, 'anatomy', 'size', $size, 'fieldContainer', 'contentWrapper', 'padding-top');
|
|
64
|
+
padding-bottom: base.simple-var(field.$field, 'anatomy', 'size', $size, 'fieldContainer', 'contentWrapper', 'padding-bottom');
|
|
67
65
|
}
|
|
68
66
|
}
|
|
69
67
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Button } from '@cloud-ru/ds-button';
|
|
2
2
|
import { FieldDecorator, FieldDecoratorProps, SIZE, VALIDATION_STATE } from '@cloud-ru/ds-field-decorator';
|
|
3
3
|
import { CheckSVG, CopySVG } from '@cloud-ru/ds-icons/interface/system';
|
|
4
|
-
import {
|
|
4
|
+
import { INPUT_MODE, InputPrivate, TYPE } from '@cloud-ru/ds-input-private';
|
|
5
5
|
import { Slider, SliderProps } from '@cloud-ru/ds-slider';
|
|
6
6
|
import { extractSupportProps, useValueControl } from '@cloud-ru/ds-utils';
|
|
7
7
|
import cn from 'classnames';
|
|
@@ -438,13 +438,13 @@ export const FieldSlider = forwardRef<HTMLInputElement, FieldSliderProps>(functi
|
|
|
438
438
|
/>
|
|
439
439
|
</div>
|
|
440
440
|
{showCopyUi && (
|
|
441
|
-
<span className={
|
|
441
|
+
<span className={styles.copyButton}>
|
|
442
442
|
<Button
|
|
443
443
|
innerRef={copyButtonRef}
|
|
444
444
|
type='button'
|
|
445
445
|
view='function'
|
|
446
446
|
appearance='neutral'
|
|
447
|
-
size={
|
|
447
|
+
size={size}
|
|
448
448
|
icon={copied ? <CheckSVG /> : <CopySVG />}
|
|
449
449
|
onClick={handleCopy}
|
|
450
450
|
onKeyDown={handleCopyButtonKeyDown}
|
|
@@ -37,3 +37,11 @@ $sizes: 's', 'm', 'l';
|
|
|
37
37
|
|
|
38
38
|
color: base.$sn-theme-color-available-version-textTertiary;
|
|
39
39
|
}
|
|
40
|
+
|
|
41
|
+
// Copy-кнопка (readonly) центрируется в строке значения.
|
|
42
|
+
.copyButton {
|
|
43
|
+
display: flex;
|
|
44
|
+
flex-shrink: 0;
|
|
45
|
+
align-items: center;
|
|
46
|
+
justify-content: center;
|
|
47
|
+
}
|
|
@@ -260,7 +260,7 @@ export const FieldStepper = forwardRef<HTMLInputElement, FieldStepperProps>(func
|
|
|
260
260
|
|
|
261
261
|
// Ширина инпута по числу символов значения (минимум 2ch), задаётся через `ch`-юниты в CSS-переменной —
|
|
262
262
|
// без px-хардкода и подгонки под ширину глифа.
|
|
263
|
-
const inputWidthCh = Math.max(
|
|
263
|
+
const inputWidthCh = Math.max(2, String(value).length);
|
|
264
264
|
|
|
265
265
|
const handleMouseEnter = useCallback(() => {
|
|
266
266
|
if (!readOnly) {
|
|
@@ -374,56 +374,51 @@ export const FieldStepper = forwardRef<HTMLInputElement, FieldStepperProps>(func
|
|
|
374
374
|
</div>
|
|
375
375
|
<div className={fieldStyles.fieldContainer}>
|
|
376
376
|
<div className={fieldStyles.contentWrapper}>
|
|
377
|
-
<div className={
|
|
378
|
-
{prefix && <span className={
|
|
379
|
-
<div className={
|
|
380
|
-
<
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
autoFocus={resolvedAutoFocus}
|
|
401
|
-
data-test-id={TEST_IDS.fieldStepperInput}
|
|
402
|
-
{...extractSupportProps(rest)}
|
|
403
|
-
/>
|
|
404
|
-
</div>
|
|
377
|
+
<div className={styles.valueArea}>
|
|
378
|
+
{prefix && <span className={styles.affix}>{prefix}</span>}
|
|
379
|
+
<div className={styles.inputWrapper} style={{ '--field-stepper-input-ch': inputWidthCh } as CSSProperties}>
|
|
380
|
+
<InputPrivate
|
|
381
|
+
ref={mergeRefs(ref, localRef)}
|
|
382
|
+
className={cn(fieldStyles.fieldInput, styles.input)}
|
|
383
|
+
value={String(value)}
|
|
384
|
+
type={TYPE.Number}
|
|
385
|
+
disabled={disabled}
|
|
386
|
+
readonly={readOnly}
|
|
387
|
+
onChange={handleInputChange}
|
|
388
|
+
onFocus={handleFocus}
|
|
389
|
+
onBlur={handleBlur}
|
|
390
|
+
onKeyDown={handleInputKeyDown}
|
|
391
|
+
id={id}
|
|
392
|
+
name={name}
|
|
393
|
+
min={min}
|
|
394
|
+
max={max}
|
|
395
|
+
step={step}
|
|
396
|
+
autoFocus={resolvedAutoFocus}
|
|
397
|
+
data-test-id={TEST_IDS.fieldStepperInput}
|
|
398
|
+
{...extractSupportProps(rest)}
|
|
399
|
+
/>
|
|
405
400
|
</div>
|
|
406
|
-
{postfix && <span className={
|
|
407
|
-
{showCopyUi && (
|
|
408
|
-
<span className={fieldStyles.postfixButtonsSlot}>
|
|
409
|
-
<Button
|
|
410
|
-
innerRef={copyButtonRef}
|
|
411
|
-
type='button'
|
|
412
|
-
view='function'
|
|
413
|
-
appearance='neutral'
|
|
414
|
-
size={BUTTON_SIZE_MAP[size]}
|
|
415
|
-
icon={copied ? <CheckSVG /> : <CopySVG />}
|
|
416
|
-
onClick={handleCopy}
|
|
417
|
-
onKeyDown={handleCopyButtonKeyDown}
|
|
418
|
-
tabIndex={-1}
|
|
419
|
-
data-test-id={TEST_IDS.fieldStepperCopyButton}
|
|
420
|
-
/>
|
|
421
|
-
</span>
|
|
422
|
-
)}
|
|
401
|
+
{postfix && <span className={styles.affix}>{postfix}</span>}
|
|
423
402
|
</div>
|
|
424
403
|
</div>
|
|
425
404
|
</div>
|
|
426
405
|
<div className={fieldStyles.elementWrapperAfter}>
|
|
406
|
+
{showCopyUi && (
|
|
407
|
+
<span className={styles.copyButton}>
|
|
408
|
+
<Button
|
|
409
|
+
innerRef={copyButtonRef}
|
|
410
|
+
type='button'
|
|
411
|
+
view='function'
|
|
412
|
+
appearance='neutral'
|
|
413
|
+
size={BUTTON_SIZE_MAP[size]}
|
|
414
|
+
icon={copied ? <CheckSVG /> : <CopySVG />}
|
|
415
|
+
onClick={handleCopy}
|
|
416
|
+
onKeyDown={handleCopyButtonKeyDown}
|
|
417
|
+
tabIndex={-1}
|
|
418
|
+
data-test-id={TEST_IDS.fieldStepperCopyButton}
|
|
419
|
+
/>
|
|
420
|
+
</span>
|
|
421
|
+
)}
|
|
427
422
|
<div className={fieldStyles.lineWrapper} data-outline={background || undefined}>
|
|
428
423
|
<Divider orientation='vertical' variant='regular' />
|
|
429
424
|
</div>
|
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
@use '@cloud-ru/ds-figma-variables/build/scss/styles/styles.module' as base;
|
|
2
|
+
@use '@cloud-ru/ds-figma-variables/build/scss/components/field.module' as field;
|
|
3
|
+
|
|
4
|
+
$sizes: 's', 'm', 'l';
|
|
5
|
+
|
|
6
|
+
// Figma-typo-мост: stepper inputLine.gap для size=m ссылается на токен size=s (=2px),
|
|
7
|
+
// а не на size=m (=4px). s→s(2), m→s(2), l→l(6).
|
|
8
|
+
$inputLineGapSizes: (
|
|
9
|
+
's': 's',
|
|
10
|
+
'm': 's',
|
|
11
|
+
'l': 'l',
|
|
12
|
+
);
|
|
2
13
|
|
|
3
14
|
// Tooltip оборачивает −/+ в block-триггер: растягиваем его на всю высоту слота,
|
|
4
15
|
// чтобы buttonField-кнопка внутри занимала полную высоту поля (как в FieldText).
|
|
@@ -8,30 +19,56 @@
|
|
|
8
19
|
height: 100%;
|
|
9
20
|
}
|
|
10
21
|
|
|
11
|
-
//
|
|
12
|
-
.
|
|
13
|
-
|
|
22
|
+
// Copy-кнопка (readonly) центрируется во всю высоту слота, как и step-триггеры.
|
|
23
|
+
.copyButton {
|
|
24
|
+
display: flex;
|
|
25
|
+
align-items: center;
|
|
26
|
+
height: 100%;
|
|
14
27
|
}
|
|
15
28
|
|
|
16
|
-
.
|
|
17
|
-
|
|
29
|
+
.valueArea {
|
|
30
|
+
display: flex;
|
|
31
|
+
flex: 1 1 auto;
|
|
32
|
+
align-items: baseline;
|
|
33
|
+
justify-content: center;
|
|
34
|
+
|
|
35
|
+
min-width: 0;
|
|
36
|
+
|
|
37
|
+
color: base.$sn-theme-color-available-version-textMain;
|
|
38
|
+
text-align: center;
|
|
39
|
+
|
|
40
|
+
@each $size, $tokenSize in $inputLineGapSizes {
|
|
41
|
+
[data-size='#{$size}'] & {
|
|
42
|
+
gap: base.simple-var(
|
|
43
|
+
field.$field,
|
|
44
|
+
'anatomy',
|
|
45
|
+
'size',
|
|
46
|
+
$tokenSize,
|
|
47
|
+
'fieldContainer',
|
|
48
|
+
'contentWrapper',
|
|
49
|
+
'inputLine',
|
|
50
|
+
'gap'
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
18
54
|
}
|
|
19
55
|
|
|
20
56
|
.inputWrapper {
|
|
21
57
|
display: flex;
|
|
22
58
|
flex: 0 0 auto;
|
|
59
|
+
|
|
60
|
+
// ширина по числу символов значения (var выставляется компонентом), минимум 2ch.
|
|
61
|
+
// +1ch — запас под каретку и субпиксельное округление: без него значение шириной ровно
|
|
62
|
+
// N символов (напр. «100» = 3ch) обрезается ellipsis'ом инпута до «1…».
|
|
63
|
+
width: calc((var(--field-stepper-input-ch, 2) + 1) * 1ch);
|
|
23
64
|
max-width: 100%;
|
|
24
65
|
}
|
|
25
66
|
|
|
26
67
|
.input {
|
|
27
68
|
flex: 0 0 auto;
|
|
28
69
|
|
|
29
|
-
|
|
30
|
-
// самого input (типографика по размеру поля); цифры SB Sans моноширинные — 1 символ = 1ch.
|
|
31
|
-
// Запас dimension-2 — под каретку и округление, иначе «100» обрезается до «1…».
|
|
32
|
-
width: calc(var(--field-stepper-input-ch, 1) * 1ch + #{base.$sn-primitive-dimension-2});
|
|
70
|
+
width: 100%;
|
|
33
71
|
min-width: 1ch;
|
|
34
|
-
max-width: 100%;
|
|
35
72
|
|
|
36
73
|
text-align: center;
|
|
37
74
|
|
|
@@ -46,3 +83,16 @@
|
|
|
46
83
|
-webkit-appearance: none;
|
|
47
84
|
}
|
|
48
85
|
}
|
|
86
|
+
|
|
87
|
+
.affix {
|
|
88
|
+
flex-shrink: 0;
|
|
89
|
+
color: base.$sn-theme-color-available-version-textTertiary;
|
|
90
|
+
|
|
91
|
+
// DS-типографика по size из корневого fieldWrapper. Без этого фолбэк на Nunito Sans 16/24
|
|
92
|
+
// визуально не сходится с инпутом.
|
|
93
|
+
@each $size in $sizes {
|
|
94
|
+
[data-size='#{$size}'] & {
|
|
95
|
+
@include base.composite-var(base.$sn-regular, 'body', $size);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -314,7 +314,6 @@ export const FieldTextArea = forwardRef<HTMLTextAreaElement, FieldTextAreaProps>
|
|
|
314
314
|
hover={hover}
|
|
315
315
|
header={header}
|
|
316
316
|
footer={footer}
|
|
317
|
-
resizable={isResizable}
|
|
318
317
|
style={{ '--field-textarea-min-rows': minRows, '--field-textarea-max-rows': maxRows } as CSSProperties}
|
|
319
318
|
onMouseEnter={handleMouseEnter}
|
|
320
319
|
onMouseLeave={handleMouseLeave}
|
|
@@ -336,7 +335,7 @@ export const FieldTextArea = forwardRef<HTMLTextAreaElement, FieldTextAreaProps>
|
|
|
336
335
|
overflow={{ x: 'hidden' }}
|
|
337
336
|
data-test-id={TEST_IDS.fieldTextAreaScrollArea}
|
|
338
337
|
>
|
|
339
|
-
<div className={fieldStyles.
|
|
338
|
+
<div className={fieldStyles.inputLine}>
|
|
340
339
|
<TextareaAutosize
|
|
341
340
|
ref={mergeRefs(ref, localRef)}
|
|
342
341
|
className={styles.textarea}
|
|
@@ -20,13 +20,6 @@ $scrollbar-width: base.simple-var(scroll.$scroll, 'anatomy', 'container', 'size'
|
|
|
20
20
|
@each $size in $sizes {
|
|
21
21
|
[data-size='#{$size}'] & {
|
|
22
22
|
--field-textarea-row-height: #{base.simple-var(base.$sn-regular, 'body', $size, 'line-height')};
|
|
23
|
-
|
|
24
|
-
// Полоса скролла в мастере прижата к правому краю поля и накрывает его боковой паддинг
|
|
25
|
-
// (`resizeWrapper` — absolute, anchor right). Скролл рисуется по краю контейнера-хоста,
|
|
26
|
-
// поэтому хост выводим за паддинг отрицательным отступом.
|
|
27
|
-
margin-right: calc(
|
|
28
|
-
-1 * #{base.simple-var(field.$field, 'anatomy', 'size', $size, 'fieldContainer', 'padding-right')}
|
|
29
|
-
);
|
|
30
23
|
}
|
|
31
24
|
}
|
|
32
25
|
}
|
|
@@ -71,12 +64,13 @@ $scrollbar-width: base.simple-var(scroll.$scroll, 'anatomy', 'container', 'size'
|
|
|
71
64
|
color: base.$sn-theme-color-available-version-textTertiary;
|
|
72
65
|
}
|
|
73
66
|
|
|
74
|
-
// DS-типографика
|
|
75
|
-
//
|
|
67
|
+
// DS-типографика + min-height multiLine из field-токенов per-size.
|
|
68
|
+
// Без этого textarea наследует Nunito Sans 16/24 от Storybook root и не имеет минимальной высоты.
|
|
76
69
|
@each $size in $sizes {
|
|
77
70
|
[data-size='#{$size}'] & {
|
|
78
|
-
// Резерв справа под колонку clear/copy
|
|
79
|
-
//
|
|
71
|
+
// Резерв справа под колонку clear/copy-кнопок (квадрат centeredWrapper) + скроллбар
|
|
72
|
+
// + горизонтальный паддинг inputLine (отступ слота кнопок от скроллбара по Figma):
|
|
73
|
+
// кнопки позиционируются абсолютно поверх скролл-области (см. .postfixColumn).
|
|
80
74
|
$button-slot: base.simple-var(
|
|
81
75
|
field.$field,
|
|
82
76
|
'anatomy',
|
|
@@ -84,13 +78,21 @@ $scrollbar-width: base.simple-var(scroll.$scroll, 'anatomy', 'container', 'size'
|
|
|
84
78
|
$size,
|
|
85
79
|
'fieldContainer',
|
|
86
80
|
'centeredWrapper',
|
|
87
|
-
'
|
|
81
|
+
'max-height'
|
|
82
|
+
);
|
|
83
|
+
$input-line-padding: base.simple-var(
|
|
84
|
+
field.$field,
|
|
85
|
+
'anatomy',
|
|
86
|
+
'size',
|
|
87
|
+
$size,
|
|
88
|
+
'fieldContainer',
|
|
89
|
+
'contentWrapper',
|
|
90
|
+
'inputLine',
|
|
91
|
+
'padding-right'
|
|
88
92
|
);
|
|
89
|
-
// Хост скролла вынесен за правый паддинг поля (см. `.scrollContainer`), поэтому резерв
|
|
90
|
-
// текста добирает его обратно. Паддинг строки уже даёт `.inputArea`, второй раз не считаем.
|
|
91
|
-
$container-padding: base.simple-var(field.$field, 'anatomy', 'size', $size, 'fieldContainer', 'padding-right');
|
|
92
93
|
|
|
93
|
-
|
|
94
|
+
min-height: base.simple-var(field.$field, 'anatomy', 'size', $size, 'fieldContainer', 'multiLine', 'min-height');
|
|
95
|
+
padding-right: calc(#{$button-slot} + #{$scrollbar-width} + #{$input-line-padding});
|
|
94
96
|
|
|
95
97
|
@include base.composite-var(base.$sn-regular, 'body', $size);
|
|
96
98
|
}
|
|
@@ -130,7 +132,7 @@ $scrollbar-width: base.simple-var(scroll.$scroll, 'anatomy', 'container', 'size'
|
|
|
130
132
|
}
|
|
131
133
|
|
|
132
134
|
// Кнопки clear/copy — поверх скролл-области, левее скроллбара (паритет с Figma и легаси:
|
|
133
|
-
// порядок справа налево — край поля, скроллбар,
|
|
135
|
+
// порядок справа налево — край поля, скроллбар, inputLine-паддинг, кнопки). Место под них
|
|
134
136
|
// резервирует padding-right textarea выше. Grid-ячейки клампят слот каждой кнопки до
|
|
135
137
|
// centeredWrapper-квадрата: сама кнопка крупнее слота и симметрично выступает за него
|
|
136
138
|
// (тот же приём, что .postfixButtonsSlot в shared/styles для FieldText), первый слот
|
|
@@ -155,7 +157,7 @@ $scrollbar-width: base.simple-var(scroll.$scroll, 'anatomy', 'container', 'size'
|
|
|
155
157
|
$size,
|
|
156
158
|
'fieldContainer',
|
|
157
159
|
'centeredWrapper',
|
|
158
|
-
'height'
|
|
160
|
+
'max-height'
|
|
159
161
|
);
|
|
160
162
|
$input-line-padding: base.simple-var(
|
|
161
163
|
field.$field,
|
|
@@ -164,7 +166,7 @@ $scrollbar-width: base.simple-var(scroll.$scroll, 'anatomy', 'container', 'size'
|
|
|
164
166
|
$size,
|
|
165
167
|
'fieldContainer',
|
|
166
168
|
'contentWrapper',
|
|
167
|
-
'
|
|
169
|
+
'inputLine',
|
|
168
170
|
'padding-right'
|
|
169
171
|
);
|
|
170
172
|
$line-height: base.simple-var(base.$sn-regular, 'body', $size, 'line-height');
|
|
@@ -181,21 +183,8 @@ $scrollbar-width: base.simple-var(scroll.$scroll, 'anatomy', 'container', 'size'
|
|
|
181
183
|
// Кнопка центрируется по первой строке текста: verticalPadding (отступ контента сверху)
|
|
182
184
|
// + центровка слота в line-height. Так 32px-кнопка верхним краем садится ровно на
|
|
183
185
|
// внутреннюю границу поля (Figma), а не выступает над ней.
|
|
184
|
-
$slot-width: base.simple-var(field.$field, 'anatomy', 'size', $size, 'fieldContainer', 'centeredWrapper', 'width');
|
|
185
|
-
$button-size: 'm';
|
|
186
|
-
|
|
187
|
-
@if $size == 's' {
|
|
188
|
-
$button-size: 's';
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
// Ширина кнопки — слот centeredWrapper из макета (16/24/24), высота остаётся высотой кнопки.
|
|
192
|
-
--sn-button-anatomy-size-#{$button-size}-container-iconOnly-minWidth: #{$slot-width};
|
|
193
|
-
|
|
194
186
|
top: calc(#{$vertical-padding} + (#{$line-height} - #{$square}) / 2);
|
|
195
|
-
|
|
196
|
-
// Правый край кнопки совпадает с внутренней границей поля (Figma): колонку уже кнопки
|
|
197
|
-
// на половину её выступа, поэтому компенсируем его.
|
|
198
|
-
right: calc((#{$slot-width} - #{$square}) / 2);
|
|
187
|
+
right: calc(#{$scrollbar-width} + #{$input-line-padding});
|
|
199
188
|
grid-auto-rows: $square;
|
|
200
189
|
width: $square;
|
|
201
190
|
}
|
|
@@ -345,8 +345,8 @@ export const FieldTime = forwardRef<HTMLInputElement, FieldTimeProps>(function F
|
|
|
345
345
|
{...extractSupportProps(rest)}
|
|
346
346
|
data-test-id={TEST_IDS.fieldTimeInput}
|
|
347
347
|
/>
|
|
348
|
+
{postfixButtons && <span className={fieldStyles.postfixButtonsSlot}>{postfixButtons}</span>}
|
|
348
349
|
</div>
|
|
349
|
-
{postfixButtons && <span className={fieldStyles.postfixButtonsSlot}>{postfixButtons}</span>}
|
|
350
350
|
</div>
|
|
351
351
|
{/* Иконка часов — декоративная; дроплист открывается кликом по полю. */}
|
|
352
352
|
<div className={fieldStyles.iconSlot} data-test-id={TEST_IDS.fieldTimeIcon} aria-hidden>
|
|
@@ -92,10 +92,10 @@ $sizes: 's', 'm', 'l';
|
|
|
92
92
|
// s → icon-xs (16), m/l → icon-s (24). max-* (как в @cloud-ru/ds-button): @cloud-ru/ds-icons задают инлайн
|
|
93
93
|
// `style="width:24"`, который перебивает width, но не max-width — поэтому клампится без JS-пропа.
|
|
94
94
|
.elementWrapper svg {
|
|
95
|
-
$iconSize: base.$sn-density-icon-s;
|
|
95
|
+
$iconSize: base.$sn-density-size-icon-s;
|
|
96
96
|
|
|
97
97
|
@if $size == 's' {
|
|
98
|
-
$iconSize: base.$sn-density-icon-xs;
|
|
98
|
+
$iconSize: base.$sn-density-size-icon-xs;
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
max-width: $iconSize;
|
|
@@ -31,8 +31,6 @@ export type FieldShellProps = WithSupportProps<{
|
|
|
31
31
|
header?: ReactNode;
|
|
32
32
|
/** Ряд элементов под контентом (действия, счётчик) */
|
|
33
33
|
footer?: ReactNode;
|
|
34
|
-
/** Многострочное поле с ручным изменением высоты — поднимает минимальную высоту контейнера */
|
|
35
|
-
resizable?: boolean;
|
|
36
34
|
/** CSS-класс оболочки (fieldWrapper) */
|
|
37
35
|
className?: string;
|
|
38
36
|
/** Inline-стиль оболочки (например, CSS-переменные высоты) */
|
|
@@ -60,7 +58,6 @@ export function FieldShell({
|
|
|
60
58
|
hover,
|
|
61
59
|
header,
|
|
62
60
|
footer,
|
|
63
|
-
resizable,
|
|
64
61
|
className,
|
|
65
62
|
style,
|
|
66
63
|
onMouseEnter,
|
|
@@ -78,7 +75,6 @@ export function FieldShell({
|
|
|
78
75
|
data-withbackground={background || undefined}
|
|
79
76
|
data-focusvisible={focusVisible || undefined}
|
|
80
77
|
data-hover={!readOnly && hover ? true : undefined}
|
|
81
|
-
data-resizable={resizable || undefined}
|
|
82
78
|
style={style}
|
|
83
79
|
onMouseEnter={onMouseEnter}
|
|
84
80
|
onMouseLeave={onMouseLeave}
|