@de-kit/st-ui 0.1.10 → 0.1.13

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 CHANGED
@@ -27,7 +27,7 @@ import { IconClose, LogoVisa } from '@de-kit/st-ui/icons';
27
27
  <IconClose width={16} height={16} aria-label="Закрыть" />
28
28
  ```
29
29
 
30
- `icon_*` и `control_*` — 20×20 и `currentColor` (галерея 20×40). Размер меняется пропом `width`/`height` или CSS, он перекрывает дефолт. `icon_label-*` сохраняют заливку. `logo_*` и `illustration_*` — размер из SVG, у иллюстраций чёрный stroke заменён на `currentColor`. Новый svg кладётся в `src/icons/svg`, дальше `pnpm build:icons` (его же зовут `dev` и `build`).
30
+ `icon_*` и `control_*` — 20×20 и `currentColor`. У стрелок галереи `viewBox` 20×40, рисуются тоже 20×20. Размер меняется пропом `width`/`height` или CSS, он перекрывает дефолт. `icon_label-*` сохраняют заливку. `logo_*` и `illustration_*` — размер из SVG, у иллюстраций чёрный stroke заменён на `currentColor`. Новый svg кладётся в `src/icons/svg`, дальше `pnpm build:icons` (его же зовут `dev` и `build`).
31
31
 
32
32
  `global.scss` — база приложения (body, заголовки, таблицы, `.wrapper`). В чужой странице его не подключать. Шрифт Inter библиотека не везёт, его по-прежнему грузит фронтенд.
33
33
 
@@ -117,7 +117,7 @@ import { IconClose, LogoVisa } from '@de-kit/st-ui/icons';
117
117
 
118
118
  ## Поле
119
119
 
120
- `Field` оборачивает один контрол: ставит лейбл, подсказку и ошибку и связывает их через `aria-describedby`, `aria-errormessage` и `role="alert"`.
120
+ `Field` оборачивает один контрол: ставит подсказку и ошибку и связывает их через `aria-describedby`, `aria-errormessage` и `role="alert"`. `label` необязателен: без него `<label>` не рисуется, а текст `required` — «Обязательное поле».
121
121
 
122
122
  ```tsx
123
123
  <Field label="Имя" hint="Нельзя изменить после проверки">
@@ -5,7 +5,7 @@
5
5
  width: fit-content;
6
6
  display: flex;
7
7
  align-items: center;
8
- padding: 8px 18px;
8
+ padding: 8px 16px;
9
9
  border-radius: 30px;
10
10
  font-size: var(--text-sm);
11
11
  line-height: var(--text-sm--line-height);
@@ -18,28 +18,33 @@
18
18
  flex-shrink: 0;
19
19
  cursor: pointer;
20
20
  transition: none;
21
- gap: 8px;
21
+ gap: 5px;
22
22
  text-decoration: none;
23
23
 
24
- &:hover:not(:active, :disabled, [aria-disabled='true']) {
24
+ &:hover:not(:active, [data-active], :disabled, [aria-disabled='true']) {
25
25
  background-color: var(--color-primary-hover);
26
26
  border-color: var(--color-primary-hover);
27
27
  }
28
28
 
29
- &:focus:not(:focus-visible) {
29
+ // data-* повторяют псевдоклассы: в Storybook :active и :focus-visible
30
+ // на нескольких кнопках сразу не удержать.
31
+ &:focus:not(:focus-visible),
32
+ &[data-focus]:not([data-focus-visible]) {
30
33
  outline: none;
31
34
  }
32
35
 
33
- &:focus-visible {
36
+ &:focus-visible,
37
+ &[data-focus-visible] {
34
38
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
35
39
  outline-offset: var(--focus-ring-offset);
36
40
  }
37
41
 
38
- &:active:not(:disabled, [aria-disabled='true']) {
39
- background-color: var(--color-muted);
40
- color: var(--color-muted-foreground);
42
+ &:active:not(:disabled, [aria-disabled='true']),
43
+ &[data-active]:not(:disabled, [aria-disabled='true']) {
44
+ background-color: var(--color-primary);
45
+ color: var(--color-primary-foreground);
41
46
  fill: currentColor;
42
- border-color: var(--color-muted);
47
+ border-color: var(--color-primary);
43
48
  }
44
49
 
45
50
  // pointer-events не гасим: нативный disabled и так не пускает клик, а так
@@ -62,7 +67,7 @@
62
67
  fill: currentColor;
63
68
  border: 2px solid var(--color-foreground);
64
69
 
65
- &:hover:not(:active, :disabled, [aria-disabled='true']) {
70
+ &:hover:not(:active, [data-active], :disabled, [aria-disabled='true']) {
66
71
  background-color: transparent;
67
72
  border-color: var(--color-foreground);
68
73
  color: var(--color-foreground);
@@ -80,14 +85,15 @@
80
85
  background-color: transparent;
81
86
  color: var(--color-foreground);
82
87
  fill: currentColor;
83
- border-radius: 0;
88
+ border-radius: var(--radius-sm);
84
89
  padding: 0;
85
90
 
86
- &:hover:not(:active, :disabled, [aria-disabled='true']) {
91
+ &:hover:not(:active, [data-active], :disabled, [aria-disabled='true']) {
87
92
  background-color: transparent;
88
93
  }
89
94
 
90
95
  &:active:not([aria-disabled='true']),
96
+ &[data-active]:not([aria-disabled='true']),
91
97
  &:disabled,
92
98
  &[aria-disabled='true']:not([aria-busy='true']) {
93
99
  background-color: transparent;
@@ -103,12 +109,18 @@
103
109
  width: var(--size);
104
110
  height: var(--size);
105
111
  position: relative;
112
+ justify-content: center;
106
113
 
107
114
  @include mixins.min-width(md) {
108
115
  --size: 100px;
109
116
  }
110
117
 
111
- &:hover:not(:active, :disabled, [aria-disabled='true']) {
118
+ &:hover:not(:active, [data-active], :disabled, [aria-disabled='true']) {
119
+ background-color: var(--color-secondary);
120
+ }
121
+
122
+ &:active:not(:disabled, [aria-disabled='true']),
123
+ &[data-active]:not(:disabled, [aria-disabled='true']) {
112
124
  background-color: var(--color-secondary);
113
125
  }
114
126
 
@@ -12,7 +12,8 @@ const requiredText = (label, message) => {
12
12
  };
13
13
  const Field = ({ label, hint, hintPlacement = "bottom", error, required = false, requiredMessage, className, children }) => {
14
14
  const inputId = (0, react.useId)();
15
- const labelId = `${inputId}-label`;
15
+ const hasLabel = Boolean(label);
16
+ const labelId = hasLabel ? `${inputId}-label` : void 0;
16
17
  const rootRef = (0, react.useRef)(null);
17
18
  const hadValueRef = (0, react.useRef)(false);
18
19
  const [showRequired, setShowRequired] = (0, react.useState)(false);
@@ -79,12 +80,12 @@ const Field = ({ label, hint, hintPlacement = "bottom", error, required = false,
79
80
  ref: rootRef,
80
81
  className: require_cn.cn("field", className, require_cn.when(Boolean(hint) && hintPlacement === "label", "field--hint-label")),
81
82
  children: [
82
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
83
+ hasLabel ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
83
84
  id: labelId,
84
85
  className: "field__label",
85
86
  htmlFor: inputId,
86
87
  children: label
87
- }),
88
+ }) : null,
88
89
  hintByPlacement.label,
89
90
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_field_context.FieldControlProvider, {
90
91
  value: contextValue,
@@ -1 +1 @@
1
- {"version":3,"file":"field.cjs","names":["useId","useRef","useState","useCallback","useMemo","cn","when","FieldControlProvider"],"sources":["../../../src/components/field/field.tsx"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from 'react';\n\nimport { cn, when } from '@/lib/cn';\nimport {\n FieldControlProvider,\n type FieldControlContext,\n} from './field-context';\nimport './field.scss';\n\nexport type FieldHintPlacement = 'bottom' | 'label';\n\nexport interface FieldProps {\n label: ReactNode;\n hint?: ReactNode;\n /** `bottom` — под полем, `label` — сразу под лейблом. */\n hintPlacement?: FieldHintPlacement;\n error?: ReactNode;\n /** Пустое значение после того, как в поле уже что-то было. */\n required?: boolean;\n /**\n * По умолчанию «Поле «{label}» обязательно», если лейбл — строка.\n * Слово «поле» среднего рода, поэтому формулировка не зависит от рода лейбла.\n */\n requiredMessage?: ReactNode;\n className?: string;\n /**\n * Один контрол: id он берёт у поля, поэтому свой `id` на ребёнке\n * перебивается, а два контрола внутри получат одинаковый.\n */\n children: ReactNode;\n}\n\nconst isFilled = (value: string) => value.trim() !== '';\n\nconst requiredText = (label: ReactNode, message: ReactNode | undefined) => {\n if (message) return message;\n if (typeof label === 'string') return `Поле «${label}» обязательно`;\n return 'Обязательное поле';\n};\n\nexport const Field = ({\n label,\n hint,\n hintPlacement = 'bottom',\n error,\n required = false,\n requiredMessage,\n className,\n children,\n}: FieldProps) => {\n const inputId = useId();\n const labelId = `${inputId}-label`;\n const rootRef = useRef<HTMLDivElement>(null);\n // ponytail: value/defaultValue больше не читаем с ребёнка. Контрол зовёт\n // reportValue из эффекта — до первого эффекта hadValue ещё false.\n const hadValueRef = useRef(false);\n const [showRequired, setShowRequired] = useState(false);\n const requiredError =\n required && showRequired ? requiredText(label, requiredMessage) : null;\n const visibleError = error ?? requiredError;\n const invalid = Boolean(visibleError);\n const hintId = hint ? `${inputId}-hint` : undefined;\n const errorId = invalid ? `${inputId}-error` : undefined;\n const describedBy = [errorId, hintId].filter(Boolean).join(' ');\n\n const reportValue = useCallback(\n (value: string) => {\n if (!required) return;\n\n if (isFilled(value)) {\n hadValueRef.current = true;\n setShowRequired(false);\n return;\n }\n\n if (hadValueRef.current) setShowRequired(true);\n },\n [required],\n );\n\n /**\n * Второй повод пожаловаться — неудачная проверка формы. Нужен для контролов,\n * которые нельзя опустошить: радиогруппу обратно не снимут, и до отправки\n * момента для ошибки нет. `invalid` не всплывает, но проходит фазу захвата,\n * поэтому одного слушателя на корне поля хватает на любой контрол внутри.\n * Реагируем только на пустое значение: формат, длина и прочие нарушения\n * обязательности не касаются, и чужую ошибку выдавать за неё нельзя.\n */\n useEffect(() => {\n const node = rootRef.current;\n if (!node || !required) return;\n\n const handleInvalid = (event: Event) => {\n const target = event.target;\n const missing =\n (target instanceof HTMLInputElement ||\n target instanceof HTMLTextAreaElement ||\n target instanceof HTMLSelectElement) &&\n target.validity.valueMissing;\n\n if (missing) setShowRequired(true);\n };\n\n node.addEventListener('invalid', handleInvalid, true);\n return () => node.removeEventListener('invalid', handleInvalid, true);\n }, [required]);\n\n const contextValue = useMemo<FieldControlContext>(\n () => ({\n id: inputId,\n labelId,\n invalid,\n required,\n describedBy: describedBy || undefined,\n errorId,\n reportValue,\n }),\n [describedBy, errorId, inputId, invalid, labelId, reportValue, required],\n );\n\n const hintByPlacement: Record<FieldHintPlacement, ReactNode> = {\n label: null,\n bottom: null,\n };\n\n if (hint) {\n hintByPlacement[hintPlacement] = (\n <p\n id={hintId}\n className={cn(\n 'field__hint',\n when(hintPlacement === 'label', 'field__hint--label'),\n )}\n >\n {hint}\n </p>\n );\n }\n\n return (\n <div\n ref={rootRef}\n className={cn(\n 'field',\n className,\n when(Boolean(hint) && hintPlacement === 'label', 'field--hint-label'),\n )}\n >\n <label id={labelId} className=\"field__label\" htmlFor={inputId}>\n {label}\n </label>\n {hintByPlacement.label}\n <FieldControlProvider value={contextValue}>\n {children}\n </FieldControlProvider>\n {visibleError ? (\n <p id={errorId} className=\"field__error\" role=\"alert\">\n {visibleError}\n </p>\n ) : null}\n {hintByPlacement.bottom}\n </div>\n );\n};\n"],"mappings":";;;;;;AAwCA,MAAM,YAAY,UAAkB,MAAM,KAAK,MAAM;AAErD,MAAM,gBAAgB,OAAkB,YAAmC;CACzE,IAAI,SAAS,OAAO;CACpB,IAAI,OAAO,UAAU,UAAU,OAAO,SAAS,MAAM;CACrD,OAAO;AACT;AAEA,MAAa,SAAS,EACpB,OACA,MACA,gBAAgB,UAChB,OACA,WAAW,OACX,iBACA,WACA,eACgB;CAChB,MAAM,WAAA,GAAUA,MAAAA,MAAAA,CAAM;CACtB,MAAM,UAAU,GAAG,QAAQ;CAC3B,MAAM,WAAA,GAAUC,MAAAA,OAAAA,CAAuB,IAAI;CAG3C,MAAM,eAAA,GAAcA,MAAAA,OAAAA,CAAO,KAAK;CAChC,MAAM,CAAC,cAAc,oBAAA,GAAmBC,MAAAA,SAAAA,CAAS,KAAK;CACtD,MAAM,gBACJ,YAAY,eAAe,aAAa,OAAO,eAAe,IAAI;CACpE,MAAM,eAAe,SAAS;CAC9B,MAAM,UAAU,QAAQ,YAAY;CACpC,MAAM,SAAS,OAAO,GAAG,QAAQ,SAAS,KAAA;CAC1C,MAAM,UAAU,UAAU,GAAG,QAAQ,UAAU,KAAA;CAC/C,MAAM,cAAc,CAAC,SAAS,MAAM,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;CAE9D,MAAM,eAAA,GAAcC,MAAAA,YAAAA,EACjB,UAAkB;EACjB,IAAI,CAAC,UAAU;EAEf,IAAI,SAAS,KAAK,GAAG;GACnB,YAAY,UAAU;GACtB,gBAAgB,KAAK;GACrB;EACF;EAEA,IAAI,YAAY,SAAS,gBAAgB,IAAI;CAC/C,GACA,CAAC,QAAQ,CACX;;;;;;;;;CAUA,CAAA,GAAA,MAAA,UAAA,OAAgB;EACd,MAAM,OAAO,QAAQ;EACrB,IAAI,CAAC,QAAQ,CAAC,UAAU;EAExB,MAAM,iBAAiB,UAAiB;GACtC,MAAM,SAAS,MAAM;GAOrB,KALG,kBAAkB,oBACjB,kBAAkB,uBAClB,kBAAkB,sBACpB,OAAO,SAAS,cAEL,gBAAgB,IAAI;EACnC;EAEA,KAAK,iBAAiB,WAAW,eAAe,IAAI;EACpD,aAAa,KAAK,oBAAoB,WAAW,eAAe,IAAI;CACtE,GAAG,CAAC,QAAQ,CAAC;CAEb,MAAM,gBAAA,GAAeC,MAAAA,QAAAA,QACZ;EACL,IAAI;EACJ;EACA;EACA;EACA,aAAa,eAAe,KAAA;EAC5B;EACA;CACF,IACA;EAAC;EAAa;EAAS;EAAS;EAAS;EAAS;EAAa;CAAQ,CACzE;CAEA,MAAM,kBAAyD;EAC7D,OAAO;EACP,QAAQ;CACV;CAEA,IAAI,MACF,gBAAgB,iBACd,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;EACE,IAAI;EACJ,WAAWC,WAAAA,GACT,eACAC,WAAAA,KAAK,kBAAkB,SAAS,oBAAoB,CACtD;EAEC,UAAA;CACA,CAAA;CAIP,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;EACE,KAAK;EACL,WAAWD,WAAAA,GACT,SACA,WACAC,WAAAA,KAAK,QAAQ,IAAI,KAAK,kBAAkB,SAAS,mBAAmB,CACtE;EANF,UAAA;GAQE,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD;IAAO,IAAI;IAAS,WAAU;IAAe,SAAS;IACnD,UAAA;GACI,CAAA;GACN,gBAAgB;GACjB,iBAAA,GAAA,kBAAA,IAAA,CAACC,sBAAAA,sBAAD;IAAsB,OAAO;IAC1B;GACmB,CAAA;GACrB,eACC,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;IAAG,IAAI;IAAS,WAAU;IAAe,MAAK;IAC3C,UAAA;GACA,CAAA,IACD;GACH,gBAAgB;EACd;;AAET"}
1
+ {"version":3,"file":"field.cjs","names":["useId","useRef","useState","useCallback","useMemo","cn","when","FieldControlProvider"],"sources":["../../../src/components/field/field.tsx"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from 'react';\n\nimport { cn, when } from '@/lib/cn';\nimport {\n FieldControlProvider,\n type FieldControlContext,\n} from './field-context';\nimport './field.scss';\n\nexport type FieldHintPlacement = 'bottom' | 'label';\n\nexport interface FieldProps {\n label?: ReactNode;\n hint?: ReactNode;\n /** `bottom` — под полем, `label` — сразу под лейблом. */\n hintPlacement?: FieldHintPlacement;\n error?: ReactNode;\n /** Пустое значение после того, как в поле уже что-то было. */\n required?: boolean;\n /**\n * По умолчанию «Поле «{label}» обязательно», если лейбл — строка.\n * Слово «поле» среднего рода, поэтому формулировка не зависит от рода лейбла.\n */\n requiredMessage?: ReactNode;\n className?: string;\n /**\n * Один контрол: id он берёт у поля, поэтому свой `id` на ребёнке\n * перебивается, а два контрола внутри получат одинаковый.\n */\n children: ReactNode;\n}\n\nconst isFilled = (value: string) => value.trim() !== '';\n\nconst requiredText = (label: ReactNode, message: ReactNode | undefined) => {\n if (message) return message;\n if (typeof label === 'string') return `Поле «${label}» обязательно`;\n return 'Обязательное поле';\n};\n\nexport const Field = ({\n label,\n hint,\n hintPlacement = 'bottom',\n error,\n required = false,\n requiredMessage,\n className,\n children,\n}: FieldProps) => {\n const inputId = useId();\n const hasLabel = Boolean(label);\n const labelId = hasLabel ? `${inputId}-label` : undefined;\n const rootRef = useRef<HTMLDivElement>(null);\n // ponytail: value/defaultValue больше не читаем с ребёнка. Контрол зовёт\n // reportValue из эффекта — до первого эффекта hadValue ещё false.\n const hadValueRef = useRef(false);\n const [showRequired, setShowRequired] = useState(false);\n const requiredError =\n required && showRequired ? requiredText(label, requiredMessage) : null;\n const visibleError = error ?? requiredError;\n const invalid = Boolean(visibleError);\n const hintId = hint ? `${inputId}-hint` : undefined;\n const errorId = invalid ? `${inputId}-error` : undefined;\n const describedBy = [errorId, hintId].filter(Boolean).join(' ');\n\n const reportValue = useCallback(\n (value: string) => {\n if (!required) return;\n\n if (isFilled(value)) {\n hadValueRef.current = true;\n setShowRequired(false);\n return;\n }\n\n if (hadValueRef.current) setShowRequired(true);\n },\n [required],\n );\n\n /**\n * Второй повод пожаловаться — неудачная проверка формы. Нужен для контролов,\n * которые нельзя опустошить: радиогруппу обратно не снимут, и до отправки\n * момента для ошибки нет. `invalid` не всплывает, но проходит фазу захвата,\n * поэтому одного слушателя на корне поля хватает на любой контрол внутри.\n * Реагируем только на пустое значение: формат, длина и прочие нарушения\n * обязательности не касаются, и чужую ошибку выдавать за неё нельзя.\n */\n useEffect(() => {\n const node = rootRef.current;\n if (!node || !required) return;\n\n const handleInvalid = (event: Event) => {\n const target = event.target;\n const missing =\n (target instanceof HTMLInputElement ||\n target instanceof HTMLTextAreaElement ||\n target instanceof HTMLSelectElement) &&\n target.validity.valueMissing;\n\n if (missing) setShowRequired(true);\n };\n\n node.addEventListener('invalid', handleInvalid, true);\n return () => node.removeEventListener('invalid', handleInvalid, true);\n }, [required]);\n\n const contextValue = useMemo<FieldControlContext>(\n () => ({\n id: inputId,\n labelId,\n invalid,\n required,\n describedBy: describedBy || undefined,\n errorId,\n reportValue,\n }),\n [describedBy, errorId, inputId, invalid, labelId, reportValue, required],\n );\n\n const hintByPlacement: Record<FieldHintPlacement, ReactNode> = {\n label: null,\n bottom: null,\n };\n\n if (hint) {\n hintByPlacement[hintPlacement] = (\n <p\n id={hintId}\n className={cn(\n 'field__hint',\n when(hintPlacement === 'label', 'field__hint--label'),\n )}\n >\n {hint}\n </p>\n );\n }\n\n return (\n <div\n ref={rootRef}\n className={cn(\n 'field',\n className,\n when(Boolean(hint) && hintPlacement === 'label', 'field--hint-label'),\n )}\n >\n {hasLabel ? (\n <label id={labelId} className=\"field__label\" htmlFor={inputId}>\n {label}\n </label>\n ) : null}\n {hintByPlacement.label}\n <FieldControlProvider value={contextValue}>\n {children}\n </FieldControlProvider>\n {visibleError ? (\n <p id={errorId} className=\"field__error\" role=\"alert\">\n {visibleError}\n </p>\n ) : null}\n {hintByPlacement.bottom}\n </div>\n );\n};\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { ReactNode } from "react";
2
2
  export type FieldHintPlacement = 'bottom' | 'label';
3
3
  export interface FieldProps {
4
- label: ReactNode;
4
+ label?: ReactNode;
5
5
  hint?: ReactNode;
6
6
  /** `bottom` — под полем, `label` — сразу под лейблом. */
7
7
  hintPlacement?: FieldHintPlacement;
@@ -1,7 +1,7 @@
1
1
  import { ReactNode } from "react";
2
2
  export type FieldHintPlacement = 'bottom' | 'label';
3
3
  export interface FieldProps {
4
- label: ReactNode;
4
+ label?: ReactNode;
5
5
  hint?: ReactNode;
6
6
  /** `bottom` — под полем, `label` — сразу под лейблом. */
7
7
  hintPlacement?: FieldHintPlacement;
@@ -12,7 +12,8 @@ const requiredText = (label, message) => {
12
12
  };
13
13
  const Field = ({ label, hint, hintPlacement = "bottom", error, required = false, requiredMessage, className, children }) => {
14
14
  const inputId = useId();
15
- const labelId = `${inputId}-label`;
15
+ const hasLabel = Boolean(label);
16
+ const labelId = hasLabel ? `${inputId}-label` : void 0;
16
17
  const rootRef = useRef(null);
17
18
  const hadValueRef = useRef(false);
18
19
  const [showRequired, setShowRequired] = useState(false);
@@ -79,12 +80,12 @@ const Field = ({ label, hint, hintPlacement = "bottom", error, required = false,
79
80
  ref: rootRef,
80
81
  className: cn("field", className, when(Boolean(hint) && hintPlacement === "label", "field--hint-label")),
81
82
  children: [
82
- /* @__PURE__ */ jsx("label", {
83
+ hasLabel ? /* @__PURE__ */ jsx("label", {
83
84
  id: labelId,
84
85
  className: "field__label",
85
86
  htmlFor: inputId,
86
87
  children: label
87
- }),
88
+ }) : null,
88
89
  hintByPlacement.label,
89
90
  /* @__PURE__ */ jsx(FieldControlProvider, {
90
91
  value: contextValue,
@@ -1 +1 @@
1
- {"version":3,"file":"field.js","names":[],"sources":["../../../src/components/field/field.tsx"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from 'react';\n\nimport { cn, when } from '@/lib/cn';\nimport {\n FieldControlProvider,\n type FieldControlContext,\n} from './field-context';\nimport './field.scss';\n\nexport type FieldHintPlacement = 'bottom' | 'label';\n\nexport interface FieldProps {\n label: ReactNode;\n hint?: ReactNode;\n /** `bottom` — под полем, `label` — сразу под лейблом. */\n hintPlacement?: FieldHintPlacement;\n error?: ReactNode;\n /** Пустое значение после того, как в поле уже что-то было. */\n required?: boolean;\n /**\n * По умолчанию «Поле «{label}» обязательно», если лейбл — строка.\n * Слово «поле» среднего рода, поэтому формулировка не зависит от рода лейбла.\n */\n requiredMessage?: ReactNode;\n className?: string;\n /**\n * Один контрол: id он берёт у поля, поэтому свой `id` на ребёнке\n * перебивается, а два контрола внутри получат одинаковый.\n */\n children: ReactNode;\n}\n\nconst isFilled = (value: string) => value.trim() !== '';\n\nconst requiredText = (label: ReactNode, message: ReactNode | undefined) => {\n if (message) return message;\n if (typeof label === 'string') return `Поле «${label}» обязательно`;\n return 'Обязательное поле';\n};\n\nexport const Field = ({\n label,\n hint,\n hintPlacement = 'bottom',\n error,\n required = false,\n requiredMessage,\n className,\n children,\n}: FieldProps) => {\n const inputId = useId();\n const labelId = `${inputId}-label`;\n const rootRef = useRef<HTMLDivElement>(null);\n // ponytail: value/defaultValue больше не читаем с ребёнка. Контрол зовёт\n // reportValue из эффекта — до первого эффекта hadValue ещё false.\n const hadValueRef = useRef(false);\n const [showRequired, setShowRequired] = useState(false);\n const requiredError =\n required && showRequired ? requiredText(label, requiredMessage) : null;\n const visibleError = error ?? requiredError;\n const invalid = Boolean(visibleError);\n const hintId = hint ? `${inputId}-hint` : undefined;\n const errorId = invalid ? `${inputId}-error` : undefined;\n const describedBy = [errorId, hintId].filter(Boolean).join(' ');\n\n const reportValue = useCallback(\n (value: string) => {\n if (!required) return;\n\n if (isFilled(value)) {\n hadValueRef.current = true;\n setShowRequired(false);\n return;\n }\n\n if (hadValueRef.current) setShowRequired(true);\n },\n [required],\n );\n\n /**\n * Второй повод пожаловаться — неудачная проверка формы. Нужен для контролов,\n * которые нельзя опустошить: радиогруппу обратно не снимут, и до отправки\n * момента для ошибки нет. `invalid` не всплывает, но проходит фазу захвата,\n * поэтому одного слушателя на корне поля хватает на любой контрол внутри.\n * Реагируем только на пустое значение: формат, длина и прочие нарушения\n * обязательности не касаются, и чужую ошибку выдавать за неё нельзя.\n */\n useEffect(() => {\n const node = rootRef.current;\n if (!node || !required) return;\n\n const handleInvalid = (event: Event) => {\n const target = event.target;\n const missing =\n (target instanceof HTMLInputElement ||\n target instanceof HTMLTextAreaElement ||\n target instanceof HTMLSelectElement) &&\n target.validity.valueMissing;\n\n if (missing) setShowRequired(true);\n };\n\n node.addEventListener('invalid', handleInvalid, true);\n return () => node.removeEventListener('invalid', handleInvalid, true);\n }, [required]);\n\n const contextValue = useMemo<FieldControlContext>(\n () => ({\n id: inputId,\n labelId,\n invalid,\n required,\n describedBy: describedBy || undefined,\n errorId,\n reportValue,\n }),\n [describedBy, errorId, inputId, invalid, labelId, reportValue, required],\n );\n\n const hintByPlacement: Record<FieldHintPlacement, ReactNode> = {\n label: null,\n bottom: null,\n };\n\n if (hint) {\n hintByPlacement[hintPlacement] = (\n <p\n id={hintId}\n className={cn(\n 'field__hint',\n when(hintPlacement === 'label', 'field__hint--label'),\n )}\n >\n {hint}\n </p>\n );\n }\n\n return (\n <div\n ref={rootRef}\n className={cn(\n 'field',\n className,\n when(Boolean(hint) && hintPlacement === 'label', 'field--hint-label'),\n )}\n >\n <label id={labelId} className=\"field__label\" htmlFor={inputId}>\n {label}\n </label>\n {hintByPlacement.label}\n <FieldControlProvider value={contextValue}>\n {children}\n </FieldControlProvider>\n {visibleError ? (\n <p id={errorId} className=\"field__error\" role=\"alert\">\n {visibleError}\n </p>\n ) : null}\n {hintByPlacement.bottom}\n </div>\n );\n};\n"],"mappings":";;;;;;AAwCA,MAAM,YAAY,UAAkB,MAAM,KAAK,MAAM;AAErD,MAAM,gBAAgB,OAAkB,YAAmC;CACzE,IAAI,SAAS,OAAO;CACpB,IAAI,OAAO,UAAU,UAAU,OAAO,SAAS,MAAM;CACrD,OAAO;AACT;AAEA,MAAa,SAAS,EACpB,OACA,MACA,gBAAgB,UAChB,OACA,WAAW,OACX,iBACA,WACA,eACgB;CAChB,MAAM,UAAU,MAAM;CACtB,MAAM,UAAU,GAAG,QAAQ;CAC3B,MAAM,UAAU,OAAuB,IAAI;CAG3C,MAAM,cAAc,OAAO,KAAK;CAChC,MAAM,CAAC,cAAc,mBAAmB,SAAS,KAAK;CACtD,MAAM,gBACJ,YAAY,eAAe,aAAa,OAAO,eAAe,IAAI;CACpE,MAAM,eAAe,SAAS;CAC9B,MAAM,UAAU,QAAQ,YAAY;CACpC,MAAM,SAAS,OAAO,GAAG,QAAQ,SAAS,KAAA;CAC1C,MAAM,UAAU,UAAU,GAAG,QAAQ,UAAU,KAAA;CAC/C,MAAM,cAAc,CAAC,SAAS,MAAM,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;CAE9D,MAAM,cAAc,aACjB,UAAkB;EACjB,IAAI,CAAC,UAAU;EAEf,IAAI,SAAS,KAAK,GAAG;GACnB,YAAY,UAAU;GACtB,gBAAgB,KAAK;GACrB;EACF;EAEA,IAAI,YAAY,SAAS,gBAAgB,IAAI;CAC/C,GACA,CAAC,QAAQ,CACX;;;;;;;;;CAUA,gBAAgB;EACd,MAAM,OAAO,QAAQ;EACrB,IAAI,CAAC,QAAQ,CAAC,UAAU;EAExB,MAAM,iBAAiB,UAAiB;GACtC,MAAM,SAAS,MAAM;GAOrB,KALG,kBAAkB,oBACjB,kBAAkB,uBAClB,kBAAkB,sBACpB,OAAO,SAAS,cAEL,gBAAgB,IAAI;EACnC;EAEA,KAAK,iBAAiB,WAAW,eAAe,IAAI;EACpD,aAAa,KAAK,oBAAoB,WAAW,eAAe,IAAI;CACtE,GAAG,CAAC,QAAQ,CAAC;CAEb,MAAM,eAAe,eACZ;EACL,IAAI;EACJ;EACA;EACA;EACA,aAAa,eAAe,KAAA;EAC5B;EACA;CACF,IACA;EAAC;EAAa;EAAS;EAAS;EAAS;EAAS;EAAa;CAAQ,CACzE;CAEA,MAAM,kBAAyD;EAC7D,OAAO;EACP,QAAQ;CACV;CAEA,IAAI,MACF,gBAAgB,iBACd,oBAAC,KAAD;EACE,IAAI;EACJ,WAAW,GACT,eACA,KAAK,kBAAkB,SAAS,oBAAoB,CACtD;EAEC,UAAA;CACA,CAAA;CAIP,OACE,qBAAC,OAAD;EACE,KAAK;EACL,WAAW,GACT,SACA,WACA,KAAK,QAAQ,IAAI,KAAK,kBAAkB,SAAS,mBAAmB,CACtE;EANF,UAAA;GAQE,oBAAC,SAAD;IAAO,IAAI;IAAS,WAAU;IAAe,SAAS;IACnD,UAAA;GACI,CAAA;GACN,gBAAgB;GACjB,oBAAC,sBAAD;IAAsB,OAAO;IAC1B;GACmB,CAAA;GACrB,eACC,oBAAC,KAAD;IAAG,IAAI;IAAS,WAAU;IAAe,MAAK;IAC3C,UAAA;GACA,CAAA,IACD;GACH,gBAAgB;EACd;;AAET"}
1
+ {"version":3,"file":"field.js","names":[],"sources":["../../../src/components/field/field.tsx"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from 'react';\n\nimport { cn, when } from '@/lib/cn';\nimport {\n FieldControlProvider,\n type FieldControlContext,\n} from './field-context';\nimport './field.scss';\n\nexport type FieldHintPlacement = 'bottom' | 'label';\n\nexport interface FieldProps {\n label?: ReactNode;\n hint?: ReactNode;\n /** `bottom` — под полем, `label` — сразу под лейблом. */\n hintPlacement?: FieldHintPlacement;\n error?: ReactNode;\n /** Пустое значение после того, как в поле уже что-то было. */\n required?: boolean;\n /**\n * По умолчанию «Поле «{label}» обязательно», если лейбл — строка.\n * Слово «поле» среднего рода, поэтому формулировка не зависит от рода лейбла.\n */\n requiredMessage?: ReactNode;\n className?: string;\n /**\n * Один контрол: id он берёт у поля, поэтому свой `id` на ребёнке\n * перебивается, а два контрола внутри получат одинаковый.\n */\n children: ReactNode;\n}\n\nconst isFilled = (value: string) => value.trim() !== '';\n\nconst requiredText = (label: ReactNode, message: ReactNode | undefined) => {\n if (message) return message;\n if (typeof label === 'string') return `Поле «${label}» обязательно`;\n return 'Обязательное поле';\n};\n\nexport const Field = ({\n label,\n hint,\n hintPlacement = 'bottom',\n error,\n required = false,\n requiredMessage,\n className,\n children,\n}: FieldProps) => {\n const inputId = useId();\n const hasLabel = Boolean(label);\n const labelId = hasLabel ? `${inputId}-label` : undefined;\n const rootRef = useRef<HTMLDivElement>(null);\n // ponytail: value/defaultValue больше не читаем с ребёнка. Контрол зовёт\n // reportValue из эффекта — до первого эффекта hadValue ещё false.\n const hadValueRef = useRef(false);\n const [showRequired, setShowRequired] = useState(false);\n const requiredError =\n required && showRequired ? requiredText(label, requiredMessage) : null;\n const visibleError = error ?? requiredError;\n const invalid = Boolean(visibleError);\n const hintId = hint ? `${inputId}-hint` : undefined;\n const errorId = invalid ? `${inputId}-error` : undefined;\n const describedBy = [errorId, hintId].filter(Boolean).join(' ');\n\n const reportValue = useCallback(\n (value: string) => {\n if (!required) return;\n\n if (isFilled(value)) {\n hadValueRef.current = true;\n setShowRequired(false);\n return;\n }\n\n if (hadValueRef.current) setShowRequired(true);\n },\n [required],\n );\n\n /**\n * Второй повод пожаловаться — неудачная проверка формы. Нужен для контролов,\n * которые нельзя опустошить: радиогруппу обратно не снимут, и до отправки\n * момента для ошибки нет. `invalid` не всплывает, но проходит фазу захвата,\n * поэтому одного слушателя на корне поля хватает на любой контрол внутри.\n * Реагируем только на пустое значение: формат, длина и прочие нарушения\n * обязательности не касаются, и чужую ошибку выдавать за неё нельзя.\n */\n useEffect(() => {\n const node = rootRef.current;\n if (!node || !required) return;\n\n const handleInvalid = (event: Event) => {\n const target = event.target;\n const missing =\n (target instanceof HTMLInputElement ||\n target instanceof HTMLTextAreaElement ||\n target instanceof HTMLSelectElement) &&\n target.validity.valueMissing;\n\n if (missing) setShowRequired(true);\n };\n\n node.addEventListener('invalid', handleInvalid, true);\n return () => node.removeEventListener('invalid', handleInvalid, true);\n }, [required]);\n\n const contextValue = useMemo<FieldControlContext>(\n () => ({\n id: inputId,\n labelId,\n invalid,\n required,\n describedBy: describedBy || undefined,\n errorId,\n reportValue,\n }),\n [describedBy, errorId, inputId, invalid, labelId, reportValue, required],\n );\n\n const hintByPlacement: Record<FieldHintPlacement, ReactNode> = {\n label: null,\n bottom: null,\n };\n\n if (hint) {\n hintByPlacement[hintPlacement] = (\n <p\n id={hintId}\n className={cn(\n 'field__hint',\n when(hintPlacement === 'label', 'field__hint--label'),\n )}\n >\n {hint}\n </p>\n );\n }\n\n return (\n <div\n ref={rootRef}\n className={cn(\n 'field',\n className,\n when(Boolean(hint) && hintPlacement === 'label', 'field--hint-label'),\n )}\n >\n {hasLabel ? (\n <label id={labelId} className=\"field__label\" htmlFor={inputId}>\n {label}\n </label>\n ) : null}\n {hintByPlacement.label}\n <FieldControlProvider value={contextValue}>\n {children}\n </FieldControlProvider>\n {visibleError ? (\n <p id={errorId} className=\"field__error\" role=\"alert\">\n {visibleError}\n </p>\n ) : null}\n {hintByPlacement.bottom}\n </div>\n );\n};\n"],"mappings":";;;;;;AAwCA,MAAM,YAAY,UAAkB,MAAM,KAAK,MAAM;AAErD,MAAM,gBAAgB,OAAkB,YAAmC;CACzE,IAAI,SAAS,OAAO;CACpB,IAAI,OAAO,UAAU,UAAU,OAAO,SAAS,MAAM;CACrD,OAAO;AACT;AAEA,MAAa,SAAS,EACpB,OACA,MACA,gBAAgB,UAChB,OACA,WAAW,OACX,iBACA,WACA,eACgB;CAChB,MAAM,UAAU,MAAM;CACtB,MAAM,WAAW,QAAQ,KAAK;CAC9B,MAAM,UAAU,WAAW,GAAG,QAAQ,UAAU,KAAA;CAChD,MAAM,UAAU,OAAuB,IAAI;CAG3C,MAAM,cAAc,OAAO,KAAK;CAChC,MAAM,CAAC,cAAc,mBAAmB,SAAS,KAAK;CACtD,MAAM,gBACJ,YAAY,eAAe,aAAa,OAAO,eAAe,IAAI;CACpE,MAAM,eAAe,SAAS;CAC9B,MAAM,UAAU,QAAQ,YAAY;CACpC,MAAM,SAAS,OAAO,GAAG,QAAQ,SAAS,KAAA;CAC1C,MAAM,UAAU,UAAU,GAAG,QAAQ,UAAU,KAAA;CAC/C,MAAM,cAAc,CAAC,SAAS,MAAM,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;CAE9D,MAAM,cAAc,aACjB,UAAkB;EACjB,IAAI,CAAC,UAAU;EAEf,IAAI,SAAS,KAAK,GAAG;GACnB,YAAY,UAAU;GACtB,gBAAgB,KAAK;GACrB;EACF;EAEA,IAAI,YAAY,SAAS,gBAAgB,IAAI;CAC/C,GACA,CAAC,QAAQ,CACX;;;;;;;;;CAUA,gBAAgB;EACd,MAAM,OAAO,QAAQ;EACrB,IAAI,CAAC,QAAQ,CAAC,UAAU;EAExB,MAAM,iBAAiB,UAAiB;GACtC,MAAM,SAAS,MAAM;GAOrB,KALG,kBAAkB,oBACjB,kBAAkB,uBAClB,kBAAkB,sBACpB,OAAO,SAAS,cAEL,gBAAgB,IAAI;EACnC;EAEA,KAAK,iBAAiB,WAAW,eAAe,IAAI;EACpD,aAAa,KAAK,oBAAoB,WAAW,eAAe,IAAI;CACtE,GAAG,CAAC,QAAQ,CAAC;CAEb,MAAM,eAAe,eACZ;EACL,IAAI;EACJ;EACA;EACA;EACA,aAAa,eAAe,KAAA;EAC5B;EACA;CACF,IACA;EAAC;EAAa;EAAS;EAAS;EAAS;EAAS;EAAa;CAAQ,CACzE;CAEA,MAAM,kBAAyD;EAC7D,OAAO;EACP,QAAQ;CACV;CAEA,IAAI,MACF,gBAAgB,iBACd,oBAAC,KAAD;EACE,IAAI;EACJ,WAAW,GACT,eACA,KAAK,kBAAkB,SAAS,oBAAoB,CACtD;EAEC,UAAA;CACA,CAAA;CAIP,OACE,qBAAC,OAAD;EACE,KAAK;EACL,WAAW,GACT,SACA,WACA,KAAK,QAAQ,IAAI,KAAK,kBAAkB,SAAS,mBAAmB,CACtE;EANF,UAAA;GAQG,WACC,oBAAC,SAAD;IAAO,IAAI;IAAS,WAAU;IAAe,SAAS;IACnD,UAAA;GACI,CAAA,IACL;GACH,gBAAgB;GACjB,oBAAC,sBAAD;IAAsB,OAAO;IAC1B;GACmB,CAAA;GACrB,eACC,oBAAC,KAAD;IAAG,IAAI;IAAS,WAAU;IAAe,MAAK;IAC3C,UAAA;GACA,CAAA,IACD;GACH,gBAAgB;EACd;;AAET"}
@@ -4,7 +4,7 @@ let react_jsx_runtime = require("react/jsx-runtime");
4
4
  const IconGalleryNext = (props) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_svg.Svg, {
5
5
  viewBox: "0 0 20 40",
6
6
  width: 20,
7
- height: 40,
7
+ height: 20,
8
8
  fill: "currentColor",
9
9
  ...props,
10
10
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
@@ -1 +1 @@
1
- {"version":3,"file":"icon-gallery-next.cjs","names":["Svg"],"sources":["../../src/icons/icon-gallery-next.tsx"],"sourcesContent":["// Generated by scripts/build-icons.mjs. Do not edit.\nimport { Svg, type IconProps } from './svg';\n\nexport const IconGalleryNext = (props: IconProps) => (\n <Svg\n viewBox=\"0 0 20 40\"\n width={20}\n height={40}\n fill=\"currentColor\"\n {...props}\n >\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M17.707,19.293l-14-14c-0.391-0.391-1.023-0.391-1.414,0s-0.391,1.023,0,1.414L15.586,20L2.293,33.293c-0.391,0.391-0.391,1.023,0,1.414s1.023,0.391,1.414,0s14-14,14-14C18.098,20.316,18.098,19.684,17.707,19.293z\"\n />\n </Svg>\n);\n"],"mappings":";;;AAGA,MAAa,mBAAmB,UAC9B,iBAAA,GAAA,kBAAA,IAAA,CAACA,YAAAA,KAAD;CACE,SAAQ;CACR,OAAO;CACP,QAAQ;CACR,MAAK;CACL,GAAI;CAEJ,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;EACE,UAAS;EACT,UAAS;EACT,GAAE;CACH,CAAA;AACE,CAAA"}
1
+ {"version":3,"file":"icon-gallery-next.cjs","names":["Svg"],"sources":["../../src/icons/icon-gallery-next.tsx"],"sourcesContent":["// Generated by scripts/build-icons.mjs. Do not edit.\nimport { Svg, type IconProps } from './svg';\n\nexport const IconGalleryNext = (props: IconProps) => (\n <Svg\n viewBox=\"0 0 20 40\"\n width={20}\n height={20}\n fill=\"currentColor\"\n {...props}\n >\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M17.707,19.293l-14-14c-0.391-0.391-1.023-0.391-1.414,0s-0.391,1.023,0,1.414L15.586,20L2.293,33.293c-0.391,0.391-0.391,1.023,0,1.414s1.023,0.391,1.414,0s14-14,14-14C18.098,20.316,18.098,19.684,17.707,19.293z\"\n />\n </Svg>\n);\n"],"mappings":";;;AAGA,MAAa,mBAAmB,UAC9B,iBAAA,GAAA,kBAAA,IAAA,CAACA,YAAAA,KAAD;CACE,SAAQ;CACR,OAAO;CACP,QAAQ;CACR,MAAK;CACL,GAAI;CAEJ,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;EACE,UAAS;EACT,UAAS;EACT,GAAE;CACH,CAAA;AACE,CAAA"}
@@ -4,7 +4,7 @@ import { jsx } from "react/jsx-runtime";
4
4
  const IconGalleryNext = (props) => /* @__PURE__ */ jsx(Svg, {
5
5
  viewBox: "0 0 20 40",
6
6
  width: 20,
7
- height: 40,
7
+ height: 20,
8
8
  fill: "currentColor",
9
9
  ...props,
10
10
  children: /* @__PURE__ */ jsx("path", {
@@ -1 +1 @@
1
- {"version":3,"file":"icon-gallery-next.js","names":[],"sources":["../../src/icons/icon-gallery-next.tsx"],"sourcesContent":["// Generated by scripts/build-icons.mjs. Do not edit.\nimport { Svg, type IconProps } from './svg';\n\nexport const IconGalleryNext = (props: IconProps) => (\n <Svg\n viewBox=\"0 0 20 40\"\n width={20}\n height={40}\n fill=\"currentColor\"\n {...props}\n >\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M17.707,19.293l-14-14c-0.391-0.391-1.023-0.391-1.414,0s-0.391,1.023,0,1.414L15.586,20L2.293,33.293c-0.391,0.391-0.391,1.023,0,1.414s1.023,0.391,1.414,0s14-14,14-14C18.098,20.316,18.098,19.684,17.707,19.293z\"\n />\n </Svg>\n);\n"],"mappings":";;;AAGA,MAAa,mBAAmB,UAC9B,oBAAC,KAAD;CACE,SAAQ;CACR,OAAO;CACP,QAAQ;CACR,MAAK;CACL,GAAI;CAEJ,UAAA,oBAAC,QAAD;EACE,UAAS;EACT,UAAS;EACT,GAAE;CACH,CAAA;AACE,CAAA"}
1
+ {"version":3,"file":"icon-gallery-next.js","names":[],"sources":["../../src/icons/icon-gallery-next.tsx"],"sourcesContent":["// Generated by scripts/build-icons.mjs. Do not edit.\nimport { Svg, type IconProps } from './svg';\n\nexport const IconGalleryNext = (props: IconProps) => (\n <Svg\n viewBox=\"0 0 20 40\"\n width={20}\n height={20}\n fill=\"currentColor\"\n {...props}\n >\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M17.707,19.293l-14-14c-0.391-0.391-1.023-0.391-1.414,0s-0.391,1.023,0,1.414L15.586,20L2.293,33.293c-0.391,0.391-0.391,1.023,0,1.414s1.023,0.391,1.414,0s14-14,14-14C18.098,20.316,18.098,19.684,17.707,19.293z\"\n />\n </Svg>\n);\n"],"mappings":";;;AAGA,MAAa,mBAAmB,UAC9B,oBAAC,KAAD;CACE,SAAQ;CACR,OAAO;CACP,QAAQ;CACR,MAAK;CACL,GAAI;CAEJ,UAAA,oBAAC,QAAD;EACE,UAAS;EACT,UAAS;EACT,GAAE;CACH,CAAA;AACE,CAAA"}
@@ -4,7 +4,7 @@ let react_jsx_runtime = require("react/jsx-runtime");
4
4
  const IconGalleryPrev = (props) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_svg.Svg, {
5
5
  viewBox: "0 0 20 40",
6
6
  width: 20,
7
- height: 40,
7
+ height: 20,
8
8
  fill: "currentColor",
9
9
  ...props,
10
10
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M4.414,20L17.707,6.707c0.391-0.391,0.391-1.023,0-1.414s-1.023-0.391-1.414,0s-14,14-14,14c-0.391,0.391-0.391,1.023,0,1.414l14,14c0.391,0.391,1.023,0.391,1.414,0s0.391-1.023,0-1.414L4.414,20z" })
@@ -1 +1 @@
1
- {"version":3,"file":"icon-gallery-prev.cjs","names":["Svg"],"sources":["../../src/icons/icon-gallery-prev.tsx"],"sourcesContent":["// Generated by scripts/build-icons.mjs. Do not edit.\nimport { Svg, type IconProps } from './svg';\n\nexport const IconGalleryPrev = (props: IconProps) => (\n <Svg\n viewBox=\"0 0 20 40\"\n width={20}\n height={40}\n fill=\"currentColor\"\n {...props}\n >\n <path d=\"M4.414,20L17.707,6.707c0.391-0.391,0.391-1.023,0-1.414s-1.023-0.391-1.414,0s-14,14-14,14c-0.391,0.391-0.391,1.023,0,1.414l14,14c0.391,0.391,1.023,0.391,1.414,0s0.391-1.023,0-1.414L4.414,20z\" />\n </Svg>\n);\n"],"mappings":";;;AAGA,MAAa,mBAAmB,UAC9B,iBAAA,GAAA,kBAAA,IAAA,CAACA,YAAAA,KAAD;CACE,SAAQ;CACR,OAAO;CACP,QAAQ;CACR,MAAK;CACL,GAAI;CAEJ,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,GAAE,gMAAiM,CAAA;AACtM,CAAA"}
1
+ {"version":3,"file":"icon-gallery-prev.cjs","names":["Svg"],"sources":["../../src/icons/icon-gallery-prev.tsx"],"sourcesContent":["// Generated by scripts/build-icons.mjs. Do not edit.\nimport { Svg, type IconProps } from './svg';\n\nexport const IconGalleryPrev = (props: IconProps) => (\n <Svg\n viewBox=\"0 0 20 40\"\n width={20}\n height={20}\n fill=\"currentColor\"\n {...props}\n >\n <path d=\"M4.414,20L17.707,6.707c0.391-0.391,0.391-1.023,0-1.414s-1.023-0.391-1.414,0s-14,14-14,14c-0.391,0.391-0.391,1.023,0,1.414l14,14c0.391,0.391,1.023,0.391,1.414,0s0.391-1.023,0-1.414L4.414,20z\" />\n </Svg>\n);\n"],"mappings":";;;AAGA,MAAa,mBAAmB,UAC9B,iBAAA,GAAA,kBAAA,IAAA,CAACA,YAAAA,KAAD;CACE,SAAQ;CACR,OAAO;CACP,QAAQ;CACR,MAAK;CACL,GAAI;CAEJ,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,GAAE,gMAAiM,CAAA;AACtM,CAAA"}
@@ -4,7 +4,7 @@ import { jsx } from "react/jsx-runtime";
4
4
  const IconGalleryPrev = (props) => /* @__PURE__ */ jsx(Svg, {
5
5
  viewBox: "0 0 20 40",
6
6
  width: 20,
7
- height: 40,
7
+ height: 20,
8
8
  fill: "currentColor",
9
9
  ...props,
10
10
  children: /* @__PURE__ */ jsx("path", { d: "M4.414,20L17.707,6.707c0.391-0.391,0.391-1.023,0-1.414s-1.023-0.391-1.414,0s-14,14-14,14c-0.391,0.391-0.391,1.023,0,1.414l14,14c0.391,0.391,1.023,0.391,1.414,0s0.391-1.023,0-1.414L4.414,20z" })
@@ -1 +1 @@
1
- {"version":3,"file":"icon-gallery-prev.js","names":[],"sources":["../../src/icons/icon-gallery-prev.tsx"],"sourcesContent":["// Generated by scripts/build-icons.mjs. Do not edit.\nimport { Svg, type IconProps } from './svg';\n\nexport const IconGalleryPrev = (props: IconProps) => (\n <Svg\n viewBox=\"0 0 20 40\"\n width={20}\n height={40}\n fill=\"currentColor\"\n {...props}\n >\n <path d=\"M4.414,20L17.707,6.707c0.391-0.391,0.391-1.023,0-1.414s-1.023-0.391-1.414,0s-14,14-14,14c-0.391,0.391-0.391,1.023,0,1.414l14,14c0.391,0.391,1.023,0.391,1.414,0s0.391-1.023,0-1.414L4.414,20z\" />\n </Svg>\n);\n"],"mappings":";;;AAGA,MAAa,mBAAmB,UAC9B,oBAAC,KAAD;CACE,SAAQ;CACR,OAAO;CACP,QAAQ;CACR,MAAK;CACL,GAAI;CAEJ,UAAA,oBAAC,QAAD,EAAM,GAAE,gMAAiM,CAAA;AACtM,CAAA"}
1
+ {"version":3,"file":"icon-gallery-prev.js","names":[],"sources":["../../src/icons/icon-gallery-prev.tsx"],"sourcesContent":["// Generated by scripts/build-icons.mjs. Do not edit.\nimport { Svg, type IconProps } from './svg';\n\nexport const IconGalleryPrev = (props: IconProps) => (\n <Svg\n viewBox=\"0 0 20 40\"\n width={20}\n height={20}\n fill=\"currentColor\"\n {...props}\n >\n <path d=\"M4.414,20L17.707,6.707c0.391-0.391,0.391-1.023,0-1.414s-1.023-0.391-1.414,0s-14,14-14,14c-0.391,0.391-0.391,1.023,0,1.414l14,14c0.391,0.391,1.023,0.391,1.414,0s0.391-1.023,0-1.414L4.414,20z\" />\n </Svg>\n);\n"],"mappings":";;;AAGA,MAAa,mBAAmB,UAC9B,oBAAC,KAAD;CACE,SAAQ;CACR,OAAO;CACP,QAAQ;CACR,MAAK;CACL,GAAI;CAEJ,UAAA,oBAAC,QAAD,EAAM,GAAE,gMAAiM,CAAA;AACtM,CAAA"}
@@ -18,7 +18,7 @@
18
18
  // Ховер outline. Выключенный контрол и вторичный текст/иконка.
19
19
  --color-secondary: #f7f7f7;
20
20
  --color-muted: #e5e5e5;
21
- --color-muted-foreground: #727272;
21
+ --color-muted-foreground: #808080; // 727272
22
22
 
23
23
  --color-border: color-mix(in srgb, var(--color-foreground) 10%, transparent);
24
24
  --color-input: #d9d9d9;
@@ -30,7 +30,7 @@
30
30
  --color-sidebar: color-mix(in srgb, var(--color-foreground) 3%, transparent);
31
31
 
32
32
  // Акцент, ошибка, успех. Текст на акценте отдельный: в тёмной теме primary-foreground инвертируется, этот нет.
33
- --color-accent: #002bff;
33
+ --color-accent: #0000ff;
34
34
  --color-accent-foreground: #fff;
35
35
  --color-destructive: #ff0000;
36
36
  --color-success: #00a66f;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@de-kit/st-ui",
3
- "version": "0.1.10",
3
+ "version": "0.1.13",
4
4
  "description": "React-компоненты splittest: глобальный SCSS и токены из основного фронтенда",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {