@de-kit/st-ui 0.1.7 → 0.1.8

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.
Files changed (44) hide show
  1. package/README.md +143 -143
  2. package/dist/components/button/button.cjs +4 -3
  3. package/dist/components/button/button.cjs.map +1 -1
  4. package/dist/components/button/button.d.cts +5 -3
  5. package/dist/components/button/button.d.ts +5 -3
  6. package/dist/components/button/button.js +4 -3
  7. package/dist/components/button/button.js.map +1 -1
  8. package/dist/components/button/button.scss +147 -148
  9. package/dist/components/checkbox/checkbox.cjs.map +1 -1
  10. package/dist/components/checkbox/checkbox.js.map +1 -1
  11. package/dist/components/checkbox/checkbox.scss +137 -137
  12. package/dist/components/field/field-context.cjs.map +1 -1
  13. package/dist/components/field/field-context.js.map +1 -1
  14. package/dist/components/field/field.cjs.map +1 -1
  15. package/dist/components/field/field.js.map +1 -1
  16. package/dist/components/field/field.scss +43 -43
  17. package/dist/components/input/input.cjs.map +1 -1
  18. package/dist/components/input/input.js.map +1 -1
  19. package/dist/components/input/input.scss +127 -127
  20. package/dist/components/radio/radio.cjs.map +1 -1
  21. package/dist/components/radio/radio.js.map +1 -1
  22. package/dist/components/radio/radio.scss +144 -144
  23. package/dist/components/spinner/spinner.cjs.map +1 -1
  24. package/dist/components/spinner/spinner.js.map +1 -1
  25. package/dist/components/spinner/spinner.scss +29 -29
  26. package/dist/components/textarea/textarea.cjs.map +1 -1
  27. package/dist/components/textarea/textarea.js.map +1 -1
  28. package/dist/components/textarea/textarea.scss +85 -85
  29. package/dist/icons/icon-label-ozon.cjs +4 -4
  30. package/dist/icons/icon-label-ozon.cjs.map +1 -1
  31. package/dist/icons/icon-label-ozon.js +4 -4
  32. package/dist/icons/icon-label-ozon.js.map +1 -1
  33. package/dist/icons/icon-label-yandex.cjs +1 -1
  34. package/dist/icons/icon-label-yandex.cjs.map +1 -1
  35. package/dist/icons/icon-label-yandex.js +1 -1
  36. package/dist/icons/icon-label-yandex.js.map +1 -1
  37. package/dist/icons/svg.cjs.map +1 -1
  38. package/dist/icons/svg.js.map +1 -1
  39. package/dist/lib/cn.cjs.map +1 -1
  40. package/dist/lib/cn.js.map +1 -1
  41. package/dist/styles/global.scss +201 -201
  42. package/dist/styles/mixins.scss +51 -51
  43. package/dist/styles/vars.scss +87 -87
  44. package/package.json +1 -1
@@ -1,148 +1,147 @@
1
- .button {
2
- box-sizing: border-box;
3
- width: fit-content;
4
- display: flex;
5
- align-items: center;
6
- padding: 8px 18px;
7
- border-radius: 30px;
8
- font-size: var(--text-sm);
9
- line-height: var(--text-sm--line-height);
10
- background-color: var(--color-primary);
11
- color: var(--color-primary-foreground);
12
- fill: var(--color-primary-foreground);
13
- font-weight: bold;
14
- font-family: var(--font-sans);
15
- border: 2px solid var(--color-primary);
16
- flex-shrink: 0;
17
- cursor: pointer;
18
- transition: none;
19
- gap: 8px;
20
- text-decoration: none;
21
-
22
- &:hover:not(:active):not(:disabled) {
23
- background-color: var(--color-primary-hover);
24
- border-color: var(--color-primary-hover);
25
- }
26
-
27
- &:focus:not(:focus-visible) {
28
- outline: none;
29
- }
30
-
31
- &:focus-visible {
32
- outline: var(--focus-ring-width) solid var(--focus-ring-color);
33
- outline-offset: var(--focus-ring-offset);
34
- }
35
-
36
- &:active {
37
- background-color: var(--color-muted);
38
- color: var(--color-muted-foreground);
39
- fill: currentColor;
40
- border-color: var(--color-muted);
41
- }
42
-
43
- // pointer-events не гасим: нативный disabled и так не пускает клик, а так
44
- // на кнопку можно навести тултип «почему недоступна».
45
- &:disabled {
46
- background-color: var(--color-muted);
47
- color: var(--color-muted-foreground);
48
- fill: currentColor;
49
- border-color: var(--color-muted);
50
- cursor: default;
51
- user-select: none;
52
- }
53
-
54
- &--outline {
55
- background-color: transparent;
56
- color: var(--color-foreground);
57
- fill: currentColor;
58
- border: 2px solid var(--color-foreground);
59
-
60
- &:hover:not(:active):not(:disabled) {
61
- background-color: var(--color-secondary);
62
- border-color: var(--color-foreground);
63
- color: var(--color-foreground);
64
- fill: currentColor;
65
- }
66
-
67
- &:disabled {
68
- background-color: transparent;
69
- }
70
- }
71
-
72
- &--link {
73
- border: none;
74
- background-color: transparent;
75
- color: var(--color-foreground);
76
- fill: currentColor;
77
- border-radius: 0;
78
- padding: 0;
79
-
80
- &:hover:not(:active):not(:disabled) {
81
- background-color: transparent;
82
- text-decoration: underline;
83
- }
84
-
85
- &:active,
86
- &:disabled {
87
- background-color: transparent;
88
- }
89
- }
90
-
91
- &--loading {
92
- position: relative;
93
- }
94
-
95
- &__label {
96
- display: flex;
97
- align-items: center;
98
- gap: inherit;
99
- opacity: 0;
100
- }
101
-
102
- &__spinner {
103
- position: absolute;
104
- inset: 0;
105
- display: flex;
106
- align-items: center;
107
- justify-content: center;
108
- pointer-events: none;
109
- }
110
-
111
- // 12/16 и 16/24 у sm и lg сняты со старого макета и в шкалу --text-* не попадают.
112
- &--sm {
113
- padding: 5px 12px;
114
- font-size: 12px;
115
- line-height: 16px;
116
- }
117
-
118
- &--lg {
119
- padding: 12px 24px;
120
- font-size: 16px;
121
- line-height: 24px;
122
- }
123
-
124
- &--full-width {
125
- width: 100%;
126
- justify-content: center;
127
- }
128
-
129
- svg {
130
- flex-shrink: 0;
131
- }
132
- }
133
-
134
- .button__icon--spin {
135
- animation: button-spin 0.8s linear infinite;
136
- }
137
-
138
- @keyframes button-spin {
139
- to {
140
- transform: rotate(360deg);
141
- }
142
- }
143
-
144
- @media (prefers-reduced-motion: reduce) {
145
- .button__icon--spin {
146
- animation: none;
147
- }
148
- }
1
+ .button {
2
+ box-sizing: border-box;
3
+ width: fit-content;
4
+ display: flex;
5
+ align-items: center;
6
+ padding: 8px 18px;
7
+ border-radius: 30px;
8
+ font-size: var(--text-sm);
9
+ line-height: var(--text-sm--line-height);
10
+ background-color: var(--color-primary);
11
+ color: var(--color-primary-foreground);
12
+ fill: var(--color-primary-foreground);
13
+ font-weight: bold;
14
+ font-family: var(--font-sans);
15
+ border: 2px solid var(--color-primary);
16
+ flex-shrink: 0;
17
+ cursor: pointer;
18
+ transition: none;
19
+ gap: 8px;
20
+ text-decoration: none;
21
+
22
+ &:hover:not(:active):not(:disabled) {
23
+ background-color: var(--color-primary-hover);
24
+ border-color: var(--color-primary-hover);
25
+ }
26
+
27
+ &:focus:not(:focus-visible) {
28
+ outline: none;
29
+ }
30
+
31
+ &:focus-visible {
32
+ outline: var(--focus-ring-width) solid var(--focus-ring-color);
33
+ outline-offset: var(--focus-ring-offset);
34
+ }
35
+
36
+ &:active {
37
+ background-color: var(--color-muted);
38
+ color: var(--color-muted-foreground);
39
+ fill: currentColor;
40
+ border-color: var(--color-muted);
41
+ }
42
+
43
+ // pointer-events не гасим: нативный disabled и так не пускает клик, а так
44
+ // на кнопку можно навести тултип «почему недоступна».
45
+ &:disabled {
46
+ background-color: var(--color-muted);
47
+ color: var(--color-muted-foreground);
48
+ fill: currentColor;
49
+ border-color: var(--color-muted);
50
+ cursor: default;
51
+ user-select: none;
52
+ }
53
+
54
+ &--outline {
55
+ background-color: transparent;
56
+ color: var(--color-foreground);
57
+ fill: currentColor;
58
+ border: 2px solid var(--color-foreground);
59
+
60
+ &:hover:not(:active):not(:disabled) {
61
+ background-color: transparent;
62
+ border-color: var(--color-foreground);
63
+ color: var(--color-foreground);
64
+ fill: currentColor;
65
+ }
66
+
67
+ &:disabled {
68
+ background-color: transparent;
69
+ }
70
+ }
71
+
72
+ &--link {
73
+ border: none;
74
+ background-color: transparent;
75
+ color: var(--color-foreground);
76
+ fill: currentColor;
77
+ border-radius: 0;
78
+ padding: 0;
79
+
80
+ &:hover:not(:active):not(:disabled) {
81
+ background-color: transparent;
82
+ }
83
+
84
+ &:active,
85
+ &:disabled {
86
+ background-color: transparent;
87
+ }
88
+ }
89
+
90
+ &--loading {
91
+ position: relative;
92
+ }
93
+
94
+ &__label {
95
+ display: flex;
96
+ align-items: center;
97
+ gap: inherit;
98
+ opacity: 0;
99
+ }
100
+
101
+ &__spinner {
102
+ position: absolute;
103
+ inset: 0;
104
+ display: flex;
105
+ align-items: center;
106
+ justify-content: center;
107
+ pointer-events: none;
108
+ }
109
+
110
+ // 12/16 и 16/24 у sm и lg сняты со старого макета и в шкалу --text-* не попадают.
111
+ &--sm {
112
+ padding: 5px 12px;
113
+ font-size: 12px;
114
+ line-height: 16px;
115
+ }
116
+
117
+ &--lg {
118
+ padding: 12px 24px;
119
+ font-size: 16px;
120
+ line-height: 24px;
121
+ }
122
+
123
+ &--full-width {
124
+ width: 100%;
125
+ justify-content: center;
126
+ }
127
+
128
+ svg {
129
+ flex-shrink: 0;
130
+ }
131
+ }
132
+
133
+ .button__icon--spin {
134
+ animation: button-spin 0.8s linear infinite;
135
+ }
136
+
137
+ @keyframes button-spin {
138
+ to {
139
+ transform: rotate(360deg);
140
+ }
141
+ }
142
+
143
+ @media (prefers-reduced-motion: reduce) {
144
+ .button__icon--spin {
145
+ animation: none;
146
+ }
147
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"checkbox.cjs","names":["forwardRef","useFieldControl","useId","useRef","useCallback","cn","when"],"sources":["../../../src/components/checkbox/checkbox.tsx"],"sourcesContent":["import {\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useRef,\n type ChangeEvent,\n type InputHTMLAttributes,\n type ReactNode,\n type Ref,\n} from 'react';\n\nimport { useFieldControl } from '@/components/field/field-context';\nimport { cn, when } from '@/lib/cn';\nimport './checkbox.scss';\n\nexport interface CheckboxInputProps extends InputHTMLAttributes<HTMLInputElement> {\n label?: ReactNode;\n /** Красная рамка. Внутри `Field` состоянием ошибки распоряжается он. */\n error?: boolean;\n /** «Выбрать все»: IDL `indeterminate`, React его атрибутом не прокидывает. */\n indeterminate?: boolean;\n /**\n * false — `pointer-events: none` на input (`checkbox__input--no-events`).\n * Клик по лейблу по-прежнему переключает.\n */\n clickable?: boolean;\n}\n\nconst assignRef = (\n ref: Ref<HTMLInputElement> | null,\n node: HTMLInputElement | null,\n) => {\n if (typeof ref === 'function') {\n ref(node);\n return;\n }\n\n if (ref) ref.current = node;\n};\n\nconst mergeDescribedBy = (\n fromField: string | undefined,\n fromProps: string | undefined,\n) => {\n const value = [fromField, fromProps].filter(part => Boolean(part)).join(' ');\n return value || undefined;\n};\n\nexport const CheckboxInput = forwardRef<HTMLInputElement, CheckboxInputProps>(\n function CheckboxInput(\n {\n className,\n id,\n label,\n error,\n disabled,\n clickable = true,\n indeterminate = false,\n checked,\n onChange,\n ...props\n },\n ref,\n ) {\n const field = useFieldControl();\n const reportValue = field?.reportValue;\n const autoId = useId();\n const inputId = field?.id ?? id ?? autoId;\n const inputRef = useRef<HTMLInputElement>(null);\n const isInvalid = Boolean(error) || Boolean(field?.invalid);\n\n const setRef = useCallback(\n (node: HTMLInputElement | null) => {\n inputRef.current = node;\n assignRef(ref, node);\n },\n [ref],\n );\n\n useEffect(() => {\n if (inputRef.current) inputRef.current.indeterminate = indeterminate;\n }, [indeterminate]);\n\n // Field ждёт строку: отдаём то же, что ушло бы в FormData — 'on' или пусто.\n useEffect(() => {\n const node = inputRef.current;\n if (node) reportValue?.(node.checked ? 'on' : '');\n }, [checked, reportValue]);\n\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\n if (checked === undefined) {\n reportValue?.(event.target.checked ? 'on' : '');\n }\n onChange?.(event);\n };\n\n const describedBy = field\n ? mergeDescribedBy(field.describedBy, props['aria-describedby'])\n : undefined;\n\n const fieldAttrs: InputHTMLAttributes<HTMLInputElement> = {};\n\n if (field?.required) {\n fieldAttrs.required = true;\n fieldAttrs['aria-required'] = true;\n }\n\n if (isInvalid) fieldAttrs['aria-invalid'] = true;\n if (describedBy) fieldAttrs['aria-describedby'] = describedBy;\n if (field?.errorId) fieldAttrs['aria-errormessage'] = field.errorId;\n\n return (\n <div className={cn('checkbox', className)}>\n <input\n {...props}\n ref={setRef}\n type=\"checkbox\"\n id={inputId}\n disabled={disabled}\n {...(checked !== undefined ? { checked } : {})}\n onChange={handleChange}\n className={cn(\n 'checkbox__input',\n when(!clickable, 'checkbox__input--no-events'),\n )}\n {...fieldAttrs}\n />\n {label ? (\n <label className=\"checkbox__label\" htmlFor={inputId}>\n {label}\n </label>\n ) : null}\n </div>\n );\n },\n);\n"],"mappings":";;;;;;AA6BA,MAAM,aACJ,KACA,SACG;CACH,IAAI,OAAO,QAAQ,YAAY;EAC7B,IAAI,IAAI;EACR;CACF;CAEA,IAAI,KAAK,IAAI,UAAU;AACzB;AAEA,MAAM,oBACJ,WACA,cACG;CAEH,OADc,CAAC,WAAW,SAAS,CAAC,CAAC,QAAO,SAAQ,QAAQ,IAAI,CAAC,CAAC,CAAC,KAAK,GAC7D,KAAK,KAAA;AAClB;AAEA,MAAa,iBAAA,GAAgBA,MAAAA,WAAAA,CAC3B,SAAS,cACP,EACE,WACA,IACA,OACA,OACA,UACA,YAAY,MACZ,gBAAgB,OAChB,SACA,UACA,GAAG,SAEL,KACA;CACA,MAAM,QAAQC,sBAAAA,gBAAgB;CAC9B,MAAM,cAAc,OAAO;CAC3B,MAAM,UAAA,GAASC,MAAAA,MAAAA,CAAM;CACrB,MAAM,UAAU,OAAO,MAAM,MAAM;CACnC,MAAM,YAAA,GAAWC,MAAAA,OAAAA,CAAyB,IAAI;CAC9C,MAAM,YAAY,QAAQ,KAAK,KAAK,QAAQ,OAAO,OAAO;CAE1D,MAAM,UAAA,GAASC,MAAAA,YAAAA,EACZ,SAAkC;EACjC,SAAS,UAAU;EACnB,UAAU,KAAK,IAAI;CACrB,GACA,CAAC,GAAG,CACN;CAEA,CAAA,GAAA,MAAA,UAAA,OAAgB;EACd,IAAI,SAAS,SAAS,SAAS,QAAQ,gBAAgB;CACzD,GAAG,CAAC,aAAa,CAAC;CAGlB,CAAA,GAAA,MAAA,UAAA,OAAgB;EACd,MAAM,OAAO,SAAS;EACtB,IAAI,MAAM,cAAc,KAAK,UAAU,OAAO,EAAE;CAClD,GAAG,CAAC,SAAS,WAAW,CAAC;CAEzB,MAAM,gBAAgB,UAAyC;EAC7D,IAAI,YAAY,KAAA,GACd,cAAc,MAAM,OAAO,UAAU,OAAO,EAAE;EAEhD,WAAW,KAAK;CAClB;CAEA,MAAM,cAAc,QAChB,iBAAiB,MAAM,aAAa,MAAM,mBAAmB,IAC7D,KAAA;CAEJ,MAAM,aAAoD,CAAC;CAE3D,IAAI,OAAO,UAAU;EACnB,WAAW,WAAW;EACtB,WAAW,mBAAmB;CAChC;CAEA,IAAI,WAAW,WAAW,kBAAkB;CAC5C,IAAI,aAAa,WAAW,sBAAsB;CAClD,IAAI,OAAO,SAAS,WAAW,uBAAuB,MAAM;CAE5D,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;EAAK,WAAWC,WAAAA,GAAG,YAAY,SAAS;EAAxC,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD;GACE,GAAI;GACJ,KAAK;GACL,MAAK;GACL,IAAI;GACM;GACV,GAAK,YAAY,KAAA,IAAY,EAAE,QAAQ,IAAI,CAAC;GAC5C,UAAU;GACV,WAAWA,WAAAA,GACT,mBACAC,WAAAA,KAAK,CAAC,WAAW,4BAA4B,CAC/C;GACA,GAAI;EACL,CAAA,GACA,QACC,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD;GAAO,WAAU;GAAkB,SAAS;GACzC,UAAA;EACI,CAAA,IACL,IACD;;AAET,CACF"}
1
+ {"version":3,"file":"checkbox.cjs","names":["forwardRef","useFieldControl","useId","useRef","useCallback","cn","when"],"sources":["../../../src/components/checkbox/checkbox.tsx"],"sourcesContent":["import {\r\n forwardRef,\r\n useCallback,\r\n useEffect,\r\n useId,\r\n useRef,\r\n type ChangeEvent,\r\n type InputHTMLAttributes,\r\n type ReactNode,\r\n type Ref,\r\n} from 'react';\r\n\r\nimport { useFieldControl } from '@/components/field/field-context';\r\nimport { cn, when } from '@/lib/cn';\r\nimport './checkbox.scss';\r\n\r\nexport interface CheckboxInputProps extends InputHTMLAttributes<HTMLInputElement> {\r\n label?: ReactNode;\r\n /** Красная рамка. Внутри `Field` состоянием ошибки распоряжается он. */\r\n error?: boolean;\r\n /** «Выбрать все»: IDL `indeterminate`, React его атрибутом не прокидывает. */\r\n indeterminate?: boolean;\r\n /**\r\n * false — `pointer-events: none` на input (`checkbox__input--no-events`).\r\n * Клик по лейблу по-прежнему переключает.\r\n */\r\n clickable?: boolean;\r\n}\r\n\r\nconst assignRef = (\r\n ref: Ref<HTMLInputElement> | null,\r\n node: HTMLInputElement | null,\r\n) => {\r\n if (typeof ref === 'function') {\r\n ref(node);\r\n return;\r\n }\r\n\r\n if (ref) ref.current = node;\r\n};\r\n\r\nconst mergeDescribedBy = (\r\n fromField: string | undefined,\r\n fromProps: string | undefined,\r\n) => {\r\n const value = [fromField, fromProps].filter(part => Boolean(part)).join(' ');\r\n return value || undefined;\r\n};\r\n\r\nexport const CheckboxInput = forwardRef<HTMLInputElement, CheckboxInputProps>(\r\n function CheckboxInput(\r\n {\r\n className,\r\n id,\r\n label,\r\n error,\r\n disabled,\r\n clickable = true,\r\n indeterminate = false,\r\n checked,\r\n onChange,\r\n ...props\r\n },\r\n ref,\r\n ) {\r\n const field = useFieldControl();\r\n const reportValue = field?.reportValue;\r\n const autoId = useId();\r\n const inputId = field?.id ?? id ?? autoId;\r\n const inputRef = useRef<HTMLInputElement>(null);\r\n const isInvalid = Boolean(error) || Boolean(field?.invalid);\r\n\r\n const setRef = useCallback(\r\n (node: HTMLInputElement | null) => {\r\n inputRef.current = node;\r\n assignRef(ref, node);\r\n },\r\n [ref],\r\n );\r\n\r\n useEffect(() => {\r\n if (inputRef.current) inputRef.current.indeterminate = indeterminate;\r\n }, [indeterminate]);\r\n\r\n // Field ждёт строку: отдаём то же, что ушло бы в FormData — 'on' или пусто.\r\n useEffect(() => {\r\n const node = inputRef.current;\r\n if (node) reportValue?.(node.checked ? 'on' : '');\r\n }, [checked, reportValue]);\r\n\r\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\r\n if (checked === undefined) {\r\n reportValue?.(event.target.checked ? 'on' : '');\r\n }\r\n onChange?.(event);\r\n };\r\n\r\n const describedBy = field\r\n ? mergeDescribedBy(field.describedBy, props['aria-describedby'])\r\n : undefined;\r\n\r\n const fieldAttrs: InputHTMLAttributes<HTMLInputElement> = {};\r\n\r\n if (field?.required) {\r\n fieldAttrs.required = true;\r\n fieldAttrs['aria-required'] = true;\r\n }\r\n\r\n if (isInvalid) fieldAttrs['aria-invalid'] = true;\r\n if (describedBy) fieldAttrs['aria-describedby'] = describedBy;\r\n if (field?.errorId) fieldAttrs['aria-errormessage'] = field.errorId;\r\n\r\n return (\r\n <div className={cn('checkbox', className)}>\r\n <input\r\n {...props}\r\n ref={setRef}\r\n type=\"checkbox\"\r\n id={inputId}\r\n disabled={disabled}\r\n {...(checked !== undefined ? { checked } : {})}\r\n onChange={handleChange}\r\n className={cn(\r\n 'checkbox__input',\r\n when(!clickable, 'checkbox__input--no-events'),\r\n )}\r\n {...fieldAttrs}\r\n />\r\n {label ? (\r\n <label className=\"checkbox__label\" htmlFor={inputId}>\r\n {label}\r\n </label>\r\n ) : null}\r\n </div>\r\n );\r\n },\r\n);\r\n"],"mappings":";;;;;;AA6BA,MAAM,aACJ,KACA,SACG;CACH,IAAI,OAAO,QAAQ,YAAY;EAC7B,IAAI,IAAI;EACR;CACF;CAEA,IAAI,KAAK,IAAI,UAAU;AACzB;AAEA,MAAM,oBACJ,WACA,cACG;CAEH,OADc,CAAC,WAAW,SAAS,CAAC,CAAC,QAAO,SAAQ,QAAQ,IAAI,CAAC,CAAC,CAAC,KAAK,GAC7D,KAAK,KAAA;AAClB;AAEA,MAAa,iBAAA,GAAgBA,MAAAA,WAAAA,CAC3B,SAAS,cACP,EACE,WACA,IACA,OACA,OACA,UACA,YAAY,MACZ,gBAAgB,OAChB,SACA,UACA,GAAG,SAEL,KACA;CACA,MAAM,QAAQC,sBAAAA,gBAAgB;CAC9B,MAAM,cAAc,OAAO;CAC3B,MAAM,UAAA,GAASC,MAAAA,MAAAA,CAAM;CACrB,MAAM,UAAU,OAAO,MAAM,MAAM;CACnC,MAAM,YAAA,GAAWC,MAAAA,OAAAA,CAAyB,IAAI;CAC9C,MAAM,YAAY,QAAQ,KAAK,KAAK,QAAQ,OAAO,OAAO;CAE1D,MAAM,UAAA,GAASC,MAAAA,YAAAA,EACZ,SAAkC;EACjC,SAAS,UAAU;EACnB,UAAU,KAAK,IAAI;CACrB,GACA,CAAC,GAAG,CACN;CAEA,CAAA,GAAA,MAAA,UAAA,OAAgB;EACd,IAAI,SAAS,SAAS,SAAS,QAAQ,gBAAgB;CACzD,GAAG,CAAC,aAAa,CAAC;CAGlB,CAAA,GAAA,MAAA,UAAA,OAAgB;EACd,MAAM,OAAO,SAAS;EACtB,IAAI,MAAM,cAAc,KAAK,UAAU,OAAO,EAAE;CAClD,GAAG,CAAC,SAAS,WAAW,CAAC;CAEzB,MAAM,gBAAgB,UAAyC;EAC7D,IAAI,YAAY,KAAA,GACd,cAAc,MAAM,OAAO,UAAU,OAAO,EAAE;EAEhD,WAAW,KAAK;CAClB;CAEA,MAAM,cAAc,QAChB,iBAAiB,MAAM,aAAa,MAAM,mBAAmB,IAC7D,KAAA;CAEJ,MAAM,aAAoD,CAAC;CAE3D,IAAI,OAAO,UAAU;EACnB,WAAW,WAAW;EACtB,WAAW,mBAAmB;CAChC;CAEA,IAAI,WAAW,WAAW,kBAAkB;CAC5C,IAAI,aAAa,WAAW,sBAAsB;CAClD,IAAI,OAAO,SAAS,WAAW,uBAAuB,MAAM;CAE5D,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;EAAK,WAAWC,WAAAA,GAAG,YAAY,SAAS;EAAxC,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD;GACE,GAAI;GACJ,KAAK;GACL,MAAK;GACL,IAAI;GACM;GACV,GAAK,YAAY,KAAA,IAAY,EAAE,QAAQ,IAAI,CAAC;GAC5C,UAAU;GACV,WAAWA,WAAAA,GACT,mBACAC,WAAAA,KAAK,CAAC,WAAW,4BAA4B,CAC/C;GACA,GAAI;EACL,CAAA,GACA,QACC,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD;GAAO,WAAU;GAAkB,SAAS;GACzC,UAAA;EACI,CAAA,IACL,IACD;;AAET,CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"checkbox.js","names":[],"sources":["../../../src/components/checkbox/checkbox.tsx"],"sourcesContent":["import {\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useRef,\n type ChangeEvent,\n type InputHTMLAttributes,\n type ReactNode,\n type Ref,\n} from 'react';\n\nimport { useFieldControl } from '@/components/field/field-context';\nimport { cn, when } from '@/lib/cn';\nimport './checkbox.scss';\n\nexport interface CheckboxInputProps extends InputHTMLAttributes<HTMLInputElement> {\n label?: ReactNode;\n /** Красная рамка. Внутри `Field` состоянием ошибки распоряжается он. */\n error?: boolean;\n /** «Выбрать все»: IDL `indeterminate`, React его атрибутом не прокидывает. */\n indeterminate?: boolean;\n /**\n * false — `pointer-events: none` на input (`checkbox__input--no-events`).\n * Клик по лейблу по-прежнему переключает.\n */\n clickable?: boolean;\n}\n\nconst assignRef = (\n ref: Ref<HTMLInputElement> | null,\n node: HTMLInputElement | null,\n) => {\n if (typeof ref === 'function') {\n ref(node);\n return;\n }\n\n if (ref) ref.current = node;\n};\n\nconst mergeDescribedBy = (\n fromField: string | undefined,\n fromProps: string | undefined,\n) => {\n const value = [fromField, fromProps].filter(part => Boolean(part)).join(' ');\n return value || undefined;\n};\n\nexport const CheckboxInput = forwardRef<HTMLInputElement, CheckboxInputProps>(\n function CheckboxInput(\n {\n className,\n id,\n label,\n error,\n disabled,\n clickable = true,\n indeterminate = false,\n checked,\n onChange,\n ...props\n },\n ref,\n ) {\n const field = useFieldControl();\n const reportValue = field?.reportValue;\n const autoId = useId();\n const inputId = field?.id ?? id ?? autoId;\n const inputRef = useRef<HTMLInputElement>(null);\n const isInvalid = Boolean(error) || Boolean(field?.invalid);\n\n const setRef = useCallback(\n (node: HTMLInputElement | null) => {\n inputRef.current = node;\n assignRef(ref, node);\n },\n [ref],\n );\n\n useEffect(() => {\n if (inputRef.current) inputRef.current.indeterminate = indeterminate;\n }, [indeterminate]);\n\n // Field ждёт строку: отдаём то же, что ушло бы в FormData — 'on' или пусто.\n useEffect(() => {\n const node = inputRef.current;\n if (node) reportValue?.(node.checked ? 'on' : '');\n }, [checked, reportValue]);\n\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\n if (checked === undefined) {\n reportValue?.(event.target.checked ? 'on' : '');\n }\n onChange?.(event);\n };\n\n const describedBy = field\n ? mergeDescribedBy(field.describedBy, props['aria-describedby'])\n : undefined;\n\n const fieldAttrs: InputHTMLAttributes<HTMLInputElement> = {};\n\n if (field?.required) {\n fieldAttrs.required = true;\n fieldAttrs['aria-required'] = true;\n }\n\n if (isInvalid) fieldAttrs['aria-invalid'] = true;\n if (describedBy) fieldAttrs['aria-describedby'] = describedBy;\n if (field?.errorId) fieldAttrs['aria-errormessage'] = field.errorId;\n\n return (\n <div className={cn('checkbox', className)}>\n <input\n {...props}\n ref={setRef}\n type=\"checkbox\"\n id={inputId}\n disabled={disabled}\n {...(checked !== undefined ? { checked } : {})}\n onChange={handleChange}\n className={cn(\n 'checkbox__input',\n when(!clickable, 'checkbox__input--no-events'),\n )}\n {...fieldAttrs}\n />\n {label ? (\n <label className=\"checkbox__label\" htmlFor={inputId}>\n {label}\n </label>\n ) : null}\n </div>\n );\n },\n);\n"],"mappings":";;;;;;AA6BA,MAAM,aACJ,KACA,SACG;CACH,IAAI,OAAO,QAAQ,YAAY;EAC7B,IAAI,IAAI;EACR;CACF;CAEA,IAAI,KAAK,IAAI,UAAU;AACzB;AAEA,MAAM,oBACJ,WACA,cACG;CAEH,OADc,CAAC,WAAW,SAAS,CAAC,CAAC,QAAO,SAAQ,QAAQ,IAAI,CAAC,CAAC,CAAC,KAAK,GAC7D,KAAK,KAAA;AAClB;AAEA,MAAa,gBAAgB,WAC3B,SAAS,cACP,EACE,WACA,IACA,OACA,OACA,UACA,YAAY,MACZ,gBAAgB,OAChB,SACA,UACA,GAAG,SAEL,KACA;CACA,MAAM,QAAQ,gBAAgB;CAC9B,MAAM,cAAc,OAAO;CAC3B,MAAM,SAAS,MAAM;CACrB,MAAM,UAAU,OAAO,MAAM,MAAM;CACnC,MAAM,WAAW,OAAyB,IAAI;CAC9C,MAAM,YAAY,QAAQ,KAAK,KAAK,QAAQ,OAAO,OAAO;CAE1D,MAAM,SAAS,aACZ,SAAkC;EACjC,SAAS,UAAU;EACnB,UAAU,KAAK,IAAI;CACrB,GACA,CAAC,GAAG,CACN;CAEA,gBAAgB;EACd,IAAI,SAAS,SAAS,SAAS,QAAQ,gBAAgB;CACzD,GAAG,CAAC,aAAa,CAAC;CAGlB,gBAAgB;EACd,MAAM,OAAO,SAAS;EACtB,IAAI,MAAM,cAAc,KAAK,UAAU,OAAO,EAAE;CAClD,GAAG,CAAC,SAAS,WAAW,CAAC;CAEzB,MAAM,gBAAgB,UAAyC;EAC7D,IAAI,YAAY,KAAA,GACd,cAAc,MAAM,OAAO,UAAU,OAAO,EAAE;EAEhD,WAAW,KAAK;CAClB;CAEA,MAAM,cAAc,QAChB,iBAAiB,MAAM,aAAa,MAAM,mBAAmB,IAC7D,KAAA;CAEJ,MAAM,aAAoD,CAAC;CAE3D,IAAI,OAAO,UAAU;EACnB,WAAW,WAAW;EACtB,WAAW,mBAAmB;CAChC;CAEA,IAAI,WAAW,WAAW,kBAAkB;CAC5C,IAAI,aAAa,WAAW,sBAAsB;CAClD,IAAI,OAAO,SAAS,WAAW,uBAAuB,MAAM;CAE5D,OACE,qBAAC,OAAD;EAAK,WAAW,GAAG,YAAY,SAAS;EAAxC,UAAA,CACE,oBAAC,SAAD;GACE,GAAI;GACJ,KAAK;GACL,MAAK;GACL,IAAI;GACM;GACV,GAAK,YAAY,KAAA,IAAY,EAAE,QAAQ,IAAI,CAAC;GAC5C,UAAU;GACV,WAAW,GACT,mBACA,KAAK,CAAC,WAAW,4BAA4B,CAC/C;GACA,GAAI;EACL,CAAA,GACA,QACC,oBAAC,SAAD;GAAO,WAAU;GAAkB,SAAS;GACzC,UAAA;EACI,CAAA,IACL,IACD;;AAET,CACF"}
1
+ {"version":3,"file":"checkbox.js","names":[],"sources":["../../../src/components/checkbox/checkbox.tsx"],"sourcesContent":["import {\r\n forwardRef,\r\n useCallback,\r\n useEffect,\r\n useId,\r\n useRef,\r\n type ChangeEvent,\r\n type InputHTMLAttributes,\r\n type ReactNode,\r\n type Ref,\r\n} from 'react';\r\n\r\nimport { useFieldControl } from '@/components/field/field-context';\r\nimport { cn, when } from '@/lib/cn';\r\nimport './checkbox.scss';\r\n\r\nexport interface CheckboxInputProps extends InputHTMLAttributes<HTMLInputElement> {\r\n label?: ReactNode;\r\n /** Красная рамка. Внутри `Field` состоянием ошибки распоряжается он. */\r\n error?: boolean;\r\n /** «Выбрать все»: IDL `indeterminate`, React его атрибутом не прокидывает. */\r\n indeterminate?: boolean;\r\n /**\r\n * false — `pointer-events: none` на input (`checkbox__input--no-events`).\r\n * Клик по лейблу по-прежнему переключает.\r\n */\r\n clickable?: boolean;\r\n}\r\n\r\nconst assignRef = (\r\n ref: Ref<HTMLInputElement> | null,\r\n node: HTMLInputElement | null,\r\n) => {\r\n if (typeof ref === 'function') {\r\n ref(node);\r\n return;\r\n }\r\n\r\n if (ref) ref.current = node;\r\n};\r\n\r\nconst mergeDescribedBy = (\r\n fromField: string | undefined,\r\n fromProps: string | undefined,\r\n) => {\r\n const value = [fromField, fromProps].filter(part => Boolean(part)).join(' ');\r\n return value || undefined;\r\n};\r\n\r\nexport const CheckboxInput = forwardRef<HTMLInputElement, CheckboxInputProps>(\r\n function CheckboxInput(\r\n {\r\n className,\r\n id,\r\n label,\r\n error,\r\n disabled,\r\n clickable = true,\r\n indeterminate = false,\r\n checked,\r\n onChange,\r\n ...props\r\n },\r\n ref,\r\n ) {\r\n const field = useFieldControl();\r\n const reportValue = field?.reportValue;\r\n const autoId = useId();\r\n const inputId = field?.id ?? id ?? autoId;\r\n const inputRef = useRef<HTMLInputElement>(null);\r\n const isInvalid = Boolean(error) || Boolean(field?.invalid);\r\n\r\n const setRef = useCallback(\r\n (node: HTMLInputElement | null) => {\r\n inputRef.current = node;\r\n assignRef(ref, node);\r\n },\r\n [ref],\r\n );\r\n\r\n useEffect(() => {\r\n if (inputRef.current) inputRef.current.indeterminate = indeterminate;\r\n }, [indeterminate]);\r\n\r\n // Field ждёт строку: отдаём то же, что ушло бы в FormData — 'on' или пусто.\r\n useEffect(() => {\r\n const node = inputRef.current;\r\n if (node) reportValue?.(node.checked ? 'on' : '');\r\n }, [checked, reportValue]);\r\n\r\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\r\n if (checked === undefined) {\r\n reportValue?.(event.target.checked ? 'on' : '');\r\n }\r\n onChange?.(event);\r\n };\r\n\r\n const describedBy = field\r\n ? mergeDescribedBy(field.describedBy, props['aria-describedby'])\r\n : undefined;\r\n\r\n const fieldAttrs: InputHTMLAttributes<HTMLInputElement> = {};\r\n\r\n if (field?.required) {\r\n fieldAttrs.required = true;\r\n fieldAttrs['aria-required'] = true;\r\n }\r\n\r\n if (isInvalid) fieldAttrs['aria-invalid'] = true;\r\n if (describedBy) fieldAttrs['aria-describedby'] = describedBy;\r\n if (field?.errorId) fieldAttrs['aria-errormessage'] = field.errorId;\r\n\r\n return (\r\n <div className={cn('checkbox', className)}>\r\n <input\r\n {...props}\r\n ref={setRef}\r\n type=\"checkbox\"\r\n id={inputId}\r\n disabled={disabled}\r\n {...(checked !== undefined ? { checked } : {})}\r\n onChange={handleChange}\r\n className={cn(\r\n 'checkbox__input',\r\n when(!clickable, 'checkbox__input--no-events'),\r\n )}\r\n {...fieldAttrs}\r\n />\r\n {label ? (\r\n <label className=\"checkbox__label\" htmlFor={inputId}>\r\n {label}\r\n </label>\r\n ) : null}\r\n </div>\r\n );\r\n },\r\n);\r\n"],"mappings":";;;;;;AA6BA,MAAM,aACJ,KACA,SACG;CACH,IAAI,OAAO,QAAQ,YAAY;EAC7B,IAAI,IAAI;EACR;CACF;CAEA,IAAI,KAAK,IAAI,UAAU;AACzB;AAEA,MAAM,oBACJ,WACA,cACG;CAEH,OADc,CAAC,WAAW,SAAS,CAAC,CAAC,QAAO,SAAQ,QAAQ,IAAI,CAAC,CAAC,CAAC,KAAK,GAC7D,KAAK,KAAA;AAClB;AAEA,MAAa,gBAAgB,WAC3B,SAAS,cACP,EACE,WACA,IACA,OACA,OACA,UACA,YAAY,MACZ,gBAAgB,OAChB,SACA,UACA,GAAG,SAEL,KACA;CACA,MAAM,QAAQ,gBAAgB;CAC9B,MAAM,cAAc,OAAO;CAC3B,MAAM,SAAS,MAAM;CACrB,MAAM,UAAU,OAAO,MAAM,MAAM;CACnC,MAAM,WAAW,OAAyB,IAAI;CAC9C,MAAM,YAAY,QAAQ,KAAK,KAAK,QAAQ,OAAO,OAAO;CAE1D,MAAM,SAAS,aACZ,SAAkC;EACjC,SAAS,UAAU;EACnB,UAAU,KAAK,IAAI;CACrB,GACA,CAAC,GAAG,CACN;CAEA,gBAAgB;EACd,IAAI,SAAS,SAAS,SAAS,QAAQ,gBAAgB;CACzD,GAAG,CAAC,aAAa,CAAC;CAGlB,gBAAgB;EACd,MAAM,OAAO,SAAS;EACtB,IAAI,MAAM,cAAc,KAAK,UAAU,OAAO,EAAE;CAClD,GAAG,CAAC,SAAS,WAAW,CAAC;CAEzB,MAAM,gBAAgB,UAAyC;EAC7D,IAAI,YAAY,KAAA,GACd,cAAc,MAAM,OAAO,UAAU,OAAO,EAAE;EAEhD,WAAW,KAAK;CAClB;CAEA,MAAM,cAAc,QAChB,iBAAiB,MAAM,aAAa,MAAM,mBAAmB,IAC7D,KAAA;CAEJ,MAAM,aAAoD,CAAC;CAE3D,IAAI,OAAO,UAAU;EACnB,WAAW,WAAW;EACtB,WAAW,mBAAmB;CAChC;CAEA,IAAI,WAAW,WAAW,kBAAkB;CAC5C,IAAI,aAAa,WAAW,sBAAsB;CAClD,IAAI,OAAO,SAAS,WAAW,uBAAuB,MAAM;CAE5D,OACE,qBAAC,OAAD;EAAK,WAAW,GAAG,YAAY,SAAS;EAAxC,UAAA,CACE,oBAAC,SAAD;GACE,GAAI;GACJ,KAAK;GACL,MAAK;GACL,IAAI;GACM;GACV,GAAK,YAAY,KAAA,IAAY,EAAE,QAAQ,IAAI,CAAC;GAC5C,UAAU;GACV,WAAW,GACT,mBACA,KAAK,CAAC,WAAW,4BAA4B,CAC/C;GACA,GAAI;EACL,CAAA,GACA,QACC,oBAAC,SAAD;GAAO,WAAU;GAAkB,SAAS;GACzC,UAAA;EACI,CAAA,IACL,IACD;;AAET,CACF"}
@@ -1,137 +1,137 @@
1
- // data-uri не читает custom properties, поэтому галочка — маска: цвет берёт background-color.
2
- @function get-check-icon() {
3
- @return url("data:image/svg+xml,%3Csvg fill='%23fff' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' width='20px' height='20px'%3E%3Cpath d='M15.71,6.29c-0.39-0.39-1.02-0.39-1.41,0c-0.31,0.31-3.76,3.76-5.29,5.29c-0.81-0.81-2.01-2.01-2.29-2.29c-0.39-0.39-1.02-0.39-1.41,0c-0.39,0.39-0.39,1.02,0,1.41c0.39,0.39,2.61,2.61,3,3c0.39,0.39,1.02,0.39,1.41,0c0.39-0.39,5.61-5.61,6-6C16.1,7.32,16.1,6.68,15.71,6.29z'/%3E%3C/svg%3E");
4
- }
5
-
6
- .checkbox {
7
- display: flex;
8
- align-items: flex-start;
9
- }
10
-
11
- .checkbox__label {
12
- font-size: var(--text-sm);
13
- line-height: var(--text-sm--line-height);
14
- display: inline-block;
15
- vertical-align: top;
16
- padding-left: var(--space-1);
17
- user-select: none;
18
- cursor: pointer;
19
- }
20
-
21
- .checkbox__input {
22
- --active: var(--color-primary);
23
- --active-inner: var(--color-primary-foreground);
24
- --border: var(--color-muted);
25
- --border-hover: var(--color-foreground);
26
- --background: var(--color-background);
27
- --disabled: var(--color-muted);
28
- --disabled-inner: var(--color-muted);
29
- box-sizing: border-box;
30
- appearance: none;
31
- width: 20px;
32
- height: 20px;
33
- outline: none;
34
- display: inline-block;
35
- vertical-align: top;
36
- position: relative;
37
- margin: 0;
38
- flex-shrink: 0;
39
- border: 1px solid var(--bc, var(--border));
40
- background: var(--b, var(--background));
41
- border-radius: var(--radius-sm);
42
- transition:
43
- background 0.3s,
44
- border-color 0.3s,
45
- box-shadow 0.2s;
46
- cursor: pointer;
47
-
48
- &::after {
49
- content: '';
50
- display: block;
51
- left: 0;
52
- top: 0;
53
- right: 0;
54
- bottom: 0;
55
- position: absolute;
56
- transition: opacity var(--d-o, 0.2s);
57
- opacity: var(--o, 0);
58
- background-color: var(--active-inner);
59
- -webkit-mask: get-check-icon() center / 20px 20px no-repeat;
60
- mask: get-check-icon() center / 20px 20px no-repeat;
61
- }
62
-
63
- // Красным красит состояние ошибки, а не сам по себе required: моментом ошибки
64
- // внутри Field распоряжается он. Рамка держится и под курсором — ховер только
65
- // добавляет к ней толщину.
66
- &[aria-invalid='true']:not(:disabled) {
67
- border-color: var(--color-destructive);
68
- }
69
-
70
- &:checked {
71
- --b: var(--active);
72
- --bc: var(--active);
73
- --o: 1;
74
- }
75
-
76
- &:indeterminate {
77
- --b: var(--active);
78
- --bc: var(--active);
79
- --o: 1;
80
-
81
- &::after {
82
- -webkit-mask: none;
83
- mask: none;
84
- top: 9px;
85
- right: 4px;
86
- bottom: 9px;
87
- left: 4px;
88
- }
89
- }
90
-
91
- &:hover:not(:checked):not(:disabled) {
92
- border-width: 2px;
93
- --bc: var(--active);
94
- }
95
-
96
- &:focus {
97
- border-color: var(--border-hover);
98
- border-width: 2px;
99
- }
100
-
101
- &:focus:not(:focus-visible) {
102
- outline: none;
103
- }
104
-
105
- &:focus-visible {
106
- outline: var(--focus-ring-width) solid var(--focus-ring-color);
107
- outline-offset: var(--focus-ring-offset);
108
- }
109
-
110
- &:disabled {
111
- --b: var(--disabled);
112
- border: 1px solid var(--disabled);
113
- cursor: not-allowed;
114
- opacity: 1;
115
-
116
- &:checked {
117
- --b: var(--disabled-inner);
118
- --active-inner: var(--color-muted-foreground);
119
- }
120
-
121
- & + .checkbox__label {
122
- color: var(--color-muted-foreground);
123
- cursor: not-allowed;
124
- }
125
- }
126
-
127
- &--no-events {
128
- pointer-events: none;
129
- }
130
- }
131
-
132
- @media (prefers-reduced-motion: reduce) {
133
- .checkbox__input,
134
- .checkbox__input::after {
135
- transition: none;
136
- }
137
- }
1
+ // data-uri не читает custom properties, поэтому галочка — маска: цвет берёт background-color.
2
+ @function get-check-icon() {
3
+ @return url("data:image/svg+xml,%3Csvg fill='%23fff' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' width='20px' height='20px'%3E%3Cpath d='M15.71,6.29c-0.39-0.39-1.02-0.39-1.41,0c-0.31,0.31-3.76,3.76-5.29,5.29c-0.81-0.81-2.01-2.01-2.29-2.29c-0.39-0.39-1.02-0.39-1.41,0c-0.39,0.39-0.39,1.02,0,1.41c0.39,0.39,2.61,2.61,3,3c0.39,0.39,1.02,0.39,1.41,0c0.39-0.39,5.61-5.61,6-6C16.1,7.32,16.1,6.68,15.71,6.29z'/%3E%3C/svg%3E");
4
+ }
5
+
6
+ .checkbox {
7
+ display: flex;
8
+ align-items: flex-start;
9
+ }
10
+
11
+ .checkbox__label {
12
+ font-size: var(--text-sm);
13
+ line-height: var(--text-sm--line-height);
14
+ display: inline-block;
15
+ vertical-align: top;
16
+ padding-left: var(--space-1);
17
+ user-select: none;
18
+ cursor: pointer;
19
+ }
20
+
21
+ .checkbox__input {
22
+ --active: var(--color-primary);
23
+ --active-inner: var(--color-primary-foreground);
24
+ --border: var(--color-muted);
25
+ --border-hover: var(--color-foreground);
26
+ --background: var(--color-background);
27
+ --disabled: var(--color-muted);
28
+ --disabled-inner: var(--color-muted);
29
+ box-sizing: border-box;
30
+ appearance: none;
31
+ width: 20px;
32
+ height: 20px;
33
+ outline: none;
34
+ display: inline-block;
35
+ vertical-align: top;
36
+ position: relative;
37
+ margin: 0;
38
+ flex-shrink: 0;
39
+ border: 1px solid var(--bc, var(--border));
40
+ background: var(--b, var(--background));
41
+ border-radius: var(--radius-sm);
42
+ transition:
43
+ background 0.3s,
44
+ border-color 0.3s,
45
+ box-shadow 0.2s;
46
+ cursor: pointer;
47
+
48
+ &::after {
49
+ content: '';
50
+ display: block;
51
+ left: 0;
52
+ top: 0;
53
+ right: 0;
54
+ bottom: 0;
55
+ position: absolute;
56
+ transition: opacity var(--d-o, 0.2s);
57
+ opacity: var(--o, 0);
58
+ background-color: var(--active-inner);
59
+ -webkit-mask: get-check-icon() center / 20px 20px no-repeat;
60
+ mask: get-check-icon() center / 20px 20px no-repeat;
61
+ }
62
+
63
+ // Красным красит состояние ошибки, а не сам по себе required: моментом ошибки
64
+ // внутри Field распоряжается он. Рамка держится и под курсором — ховер только
65
+ // добавляет к ней толщину.
66
+ &[aria-invalid='true']:not(:disabled) {
67
+ border-color: var(--color-destructive);
68
+ }
69
+
70
+ &:checked {
71
+ --b: var(--active);
72
+ --bc: var(--active);
73
+ --o: 1;
74
+ }
75
+
76
+ &:indeterminate {
77
+ --b: var(--active);
78
+ --bc: var(--active);
79
+ --o: 1;
80
+
81
+ &::after {
82
+ -webkit-mask: none;
83
+ mask: none;
84
+ top: 9px;
85
+ right: 4px;
86
+ bottom: 9px;
87
+ left: 4px;
88
+ }
89
+ }
90
+
91
+ &:hover:not(:checked):not(:disabled) {
92
+ border-width: 2px;
93
+ --bc: var(--active);
94
+ }
95
+
96
+ &:focus {
97
+ border-color: var(--border-hover);
98
+ border-width: 2px;
99
+ }
100
+
101
+ &:focus:not(:focus-visible) {
102
+ outline: none;
103
+ }
104
+
105
+ &:focus-visible {
106
+ outline: var(--focus-ring-width) solid var(--focus-ring-color);
107
+ outline-offset: var(--focus-ring-offset);
108
+ }
109
+
110
+ &:disabled {
111
+ --b: var(--disabled);
112
+ border: 1px solid var(--disabled);
113
+ cursor: not-allowed;
114
+ opacity: 1;
115
+
116
+ &:checked {
117
+ --b: var(--disabled-inner);
118
+ --active-inner: var(--color-muted-foreground);
119
+ }
120
+
121
+ & + .checkbox__label {
122
+ color: var(--color-muted-foreground);
123
+ cursor: not-allowed;
124
+ }
125
+ }
126
+
127
+ &--no-events {
128
+ pointer-events: none;
129
+ }
130
+ }
131
+
132
+ @media (prefers-reduced-motion: reduce) {
133
+ .checkbox__input,
134
+ .checkbox__input::after {
135
+ transition: none;
136
+ }
137
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"field-context.cjs","names":["createContext","useContext"],"sources":["../../../src/components/field/field-context.ts"],"sourcesContent":["import { createContext, useContext } from 'react';\n\nexport interface FieldControlContext {\n id: string;\n /** Для контролов без собственного лейбла: группа ссылается на него aria-labelledby. */\n labelId?: string;\n invalid: boolean;\n required: boolean;\n describedBy?: string;\n errorId?: string;\n /** Контрол сообщает показанное значение: текст поля или 'on' у отмеченного чекбокса. */\n reportValue?: (value: string) => void;\n}\n\nconst FieldControlReactContext = createContext<FieldControlContext | null>(\n null,\n);\n\nexport const FieldControlProvider = FieldControlReactContext.Provider;\n\nexport const useFieldControl = (): FieldControlContext | null =>\n useContext(FieldControlReactContext);\n"],"mappings":";;AAcA,MAAM,4BAAA,GAA2BA,MAAAA,cAAAA,CAC/B,IACF;AAEA,MAAa,uBAAuB,yBAAyB;AAE7D,MAAa,yBAAA,GACXC,MAAAA,WAAAA,CAAW,wBAAwB"}
1
+ {"version":3,"file":"field-context.cjs","names":["createContext","useContext"],"sources":["../../../src/components/field/field-context.ts"],"sourcesContent":["import { createContext, useContext } from 'react';\r\n\r\nexport interface FieldControlContext {\r\n id: string;\r\n /** Для контролов без собственного лейбла: группа ссылается на него aria-labelledby. */\r\n labelId?: string;\r\n invalid: boolean;\r\n required: boolean;\r\n describedBy?: string;\r\n errorId?: string;\r\n /** Контрол сообщает показанное значение: текст поля или 'on' у отмеченного чекбокса. */\r\n reportValue?: (value: string) => void;\r\n}\r\n\r\nconst FieldControlReactContext = createContext<FieldControlContext | null>(\r\n null,\r\n);\r\n\r\nexport const FieldControlProvider = FieldControlReactContext.Provider;\r\n\r\nexport const useFieldControl = (): FieldControlContext | null =>\r\n useContext(FieldControlReactContext);\r\n"],"mappings":";;AAcA,MAAM,4BAAA,GAA2BA,MAAAA,cAAAA,CAC/B,IACF;AAEA,MAAa,uBAAuB,yBAAyB;AAE7D,MAAa,yBAAA,GACXC,MAAAA,WAAAA,CAAW,wBAAwB"}
@@ -1 +1 @@
1
- {"version":3,"file":"field-context.js","names":[],"sources":["../../../src/components/field/field-context.ts"],"sourcesContent":["import { createContext, useContext } from 'react';\n\nexport interface FieldControlContext {\n id: string;\n /** Для контролов без собственного лейбла: группа ссылается на него aria-labelledby. */\n labelId?: string;\n invalid: boolean;\n required: boolean;\n describedBy?: string;\n errorId?: string;\n /** Контрол сообщает показанное значение: текст поля или 'on' у отмеченного чекбокса. */\n reportValue?: (value: string) => void;\n}\n\nconst FieldControlReactContext = createContext<FieldControlContext | null>(\n null,\n);\n\nexport const FieldControlProvider = FieldControlReactContext.Provider;\n\nexport const useFieldControl = (): FieldControlContext | null =>\n useContext(FieldControlReactContext);\n"],"mappings":";;AAcA,MAAM,2BAA2B,cAC/B,IACF;AAEA,MAAa,uBAAuB,yBAAyB;AAE7D,MAAa,wBACX,WAAW,wBAAwB"}
1
+ {"version":3,"file":"field-context.js","names":[],"sources":["../../../src/components/field/field-context.ts"],"sourcesContent":["import { createContext, useContext } from 'react';\r\n\r\nexport interface FieldControlContext {\r\n id: string;\r\n /** Для контролов без собственного лейбла: группа ссылается на него aria-labelledby. */\r\n labelId?: string;\r\n invalid: boolean;\r\n required: boolean;\r\n describedBy?: string;\r\n errorId?: string;\r\n /** Контрол сообщает показанное значение: текст поля или 'on' у отмеченного чекбокса. */\r\n reportValue?: (value: string) => void;\r\n}\r\n\r\nconst FieldControlReactContext = createContext<FieldControlContext | null>(\r\n null,\r\n);\r\n\r\nexport const FieldControlProvider = FieldControlReactContext.Provider;\r\n\r\nexport const useFieldControl = (): FieldControlContext | null =>\r\n useContext(FieldControlReactContext);\r\n"],"mappings":";;AAcA,MAAM,2BAA2B,cAC/B,IACF;AAEA,MAAa,uBAAuB,yBAAyB;AAE7D,MAAa,wBACX,WAAW,wBAAwB"}