@shmidko61/lc-ui-kit 0.0.1

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 (128) hide show
  1. package/README.md +38 -0
  2. package/dist/accordion/accordion-context.d.ts +3 -0
  3. package/dist/accordion/accordion-item.d.ts +48 -0
  4. package/dist/accordion/accordion-root.d.ts +5 -0
  5. package/dist/accordion/accordion.d.ts +8 -0
  6. package/dist/accordion.cjs +1 -0
  7. package/dist/accordion.js +206 -0
  8. package/dist/arrow-CS6d64Y4.cjs +1 -0
  9. package/dist/arrow-DBc2opRL.js +5 -0
  10. package/dist/box/box.d.ts +7 -0
  11. package/dist/box/box.helpers.d.ts +11 -0
  12. package/dist/box/box.types.d.ts +62 -0
  13. package/dist/box.cjs +1 -0
  14. package/dist/box.js +342 -0
  15. package/dist/button/button.d.ts +22 -0
  16. package/dist/button/button.helpers.d.ts +119 -0
  17. package/dist/button.cjs +1 -0
  18. package/dist/button.js +438 -0
  19. package/dist/design-tokens/color.tokens.d.ts +6 -0
  20. package/dist/design-tokens/typography.tokens.d.ts +9 -0
  21. package/dist/drop-down-CdIuWbLC.cjs +1 -0
  22. package/dist/drop-down-DH2_3qXq.js +5 -0
  23. package/dist/eye-open-5zYaeyLp.cjs +1 -0
  24. package/dist/eye-open-CoTSj5cT.js +5 -0
  25. package/dist/flex/flex.d.ts +5 -0
  26. package/dist/flex/flex.helpers.d.ts +9 -0
  27. package/dist/flex/flex.types.d.ts +12 -0
  28. package/dist/flex.cjs +1 -0
  29. package/dist/flex.js +128 -0
  30. package/dist/grid/grid.d.ts +25 -0
  31. package/dist/grid/grid.helpers.d.ts +13 -0
  32. package/dist/grid/grid.types.d.ts +49 -0
  33. package/dist/grid.cjs +1 -0
  34. package/dist/grid.js +103 -0
  35. package/dist/icons/icons.d.ts +30 -0
  36. package/dist/icons.cjs +1 -0
  37. package/dist/icons.js +38 -0
  38. package/dist/index.cjs +1 -0
  39. package/dist/index.d.ts +22 -0
  40. package/dist/index.js +97 -0
  41. package/dist/input/input.d.ts +49 -0
  42. package/dist/input/input.helpers.d.ts +9 -0
  43. package/dist/input.cjs +1 -0
  44. package/dist/input.js +85 -0
  45. package/dist/media-card/components/media-card-pick-indicator.d.ts +6 -0
  46. package/dist/media-card/components/media-card-preview.d.ts +7 -0
  47. package/dist/media-card/components/media-card-upload-footer.d.ts +7 -0
  48. package/dist/media-card/components/media-card-upload.d.ts +5 -0
  49. package/dist/media-card/media-card-pick.d.ts +5 -0
  50. package/dist/media-card/media-card.d.ts +4 -0
  51. package/dist/media-card/media-card.types.d.ts +10 -0
  52. package/dist/media-card.cjs +1 -0
  53. package/dist/media-card.js +104 -0
  54. package/dist/media-gallery/media-gallery.d.ts +12 -0
  55. package/dist/media-gallery/media-gallery.helpers.d.ts +27 -0
  56. package/dist/media-gallery/media-gallery.types.d.ts +59 -0
  57. package/dist/media-gallery.cjs +1 -0
  58. package/dist/media-gallery.js +100 -0
  59. package/dist/media-picture-BN4saEVT.js +6 -0
  60. package/dist/media-picture-BmERSmsd.cjs +1 -0
  61. package/dist/modal/modal.d.ts +50 -0
  62. package/dist/modal.cjs +1 -0
  63. package/dist/modal.js +143 -0
  64. package/dist/pagination/pagination.d.ts +22 -0
  65. package/dist/pagination.cjs +1 -0
  66. package/dist/pagination.js +155 -0
  67. package/dist/picture/picture.d.ts +12 -0
  68. package/dist/picture/picture.helpers.d.ts +9 -0
  69. package/dist/picture/picture.types.d.ts +56 -0
  70. package/dist/picture.cjs +1 -0
  71. package/dist/picture.js +55 -0
  72. package/dist/responsive-style.config-B2m9jVlX.cjs +1 -0
  73. package/dist/responsive-style.config-DFuATrIM.js +19 -0
  74. package/dist/responsive-style.utils-BdyoDkKg.cjs +1 -0
  75. package/dist/responsive-style.utils-D10sC561.js +25 -0
  76. package/dist/select/select.d.ts +55 -0
  77. package/dist/select/select.helpers.d.ts +14 -0
  78. package/dist/select/select.types.d.ts +12 -0
  79. package/dist/select.cjs +1 -0
  80. package/dist/select.js +179 -0
  81. package/dist/shared/lib/cn.d.ts +2 -0
  82. package/dist/shared/responsive-style/responsive-style.config.d.ts +20 -0
  83. package/dist/shared/responsive-style/responsive-style.types.d.ts +52 -0
  84. package/dist/shared/responsive-style/responsive-style.utils.d.ts +17 -0
  85. package/dist/status-badge/status-badge.d.ts +11 -0
  86. package/dist/status-badge.cjs +1 -0
  87. package/dist/status-badge.js +39 -0
  88. package/dist/styles.css +1 -0
  89. package/dist/switch/switch.d.ts +34 -0
  90. package/dist/switch.cjs +1 -0
  91. package/dist/switch.js +127 -0
  92. package/dist/table/data-table.d.ts +3 -0
  93. package/dist/table/table-container.d.ts +8 -0
  94. package/dist/table/table-primitives.d.ts +40 -0
  95. package/dist/table/table-status.d.ts +12 -0
  96. package/dist/table/table.d.ts +8 -0
  97. package/dist/table/table.types.d.ts +48 -0
  98. package/dist/table-container-BsE-uIE1.js +242 -0
  99. package/dist/table-container-DqqqkChm.cjs +1 -0
  100. package/dist/table.cjs +1 -0
  101. package/dist/table.js +16 -0
  102. package/dist/telephone-DVftjRG9.cjs +1 -0
  103. package/dist/telephone-DvXakgBQ.js +26 -0
  104. package/dist/time-clock-DOwPzcx7.cjs +1 -0
  105. package/dist/time-clock-DjqcZ8tI.js +5 -0
  106. package/dist/types/flex.types.d.ts +25 -0
  107. package/dist/types/index.d.ts +7 -0
  108. package/dist/types/interaction.types.d.ts +8 -0
  109. package/dist/types/layout.types.d.ts +52 -0
  110. package/dist/types/shared.types.d.ts +8 -0
  111. package/dist/types/spacing.types.d.ts +123 -0
  112. package/dist/types/typography.types.d.ts +75 -0
  113. package/dist/types/visual.types.d.ts +82 -0
  114. package/dist/types.cjs +1 -0
  115. package/dist/types.js +1 -0
  116. package/dist/typography/typography.d.ts +39 -0
  117. package/dist/typography/typography.helpers.d.ts +237 -0
  118. package/dist/typography.cjs +1 -0
  119. package/dist/typography.js +469 -0
  120. package/dist/ui-kit-provider/ui-kit-provider.d.ts +53 -0
  121. package/dist/ui-kit-provider-C6Mk5g_7.js +167 -0
  122. package/dist/ui-kit-provider-raEFsUm0.cjs +1 -0
  123. package/dist/ui-kit-provider.cjs +1 -0
  124. package/dist/ui-kit-provider.js +8 -0
  125. package/dist/vite.config.d.ts +2 -0
  126. package/dist/x-mark-DId-ylR6.cjs +1 -0
  127. package/dist/x-mark-WU1eT82T.js +5 -0
  128. package/package.json +219 -0
@@ -0,0 +1,155 @@
1
+ import { jsxs as g, jsx as c } from "react/jsx-runtime";
2
+ import { S as d } from "./arrow-DBc2opRL.js";
3
+ import { c as b } from "./responsive-style.config-DFuATrIM.js";
4
+ import { Typography as $ } from "./typography.js";
5
+ function P({
6
+ boundaryCount: e = 1,
7
+ className: n,
8
+ currentPage: r,
9
+ disabled: i = !1,
10
+ onPageChange: s,
11
+ pageSize: o,
12
+ showRangeLabel: h = !0,
13
+ siblingCount: m = 1,
14
+ totalItems: p,
15
+ totalPages: a,
16
+ ...u
17
+ }) {
18
+ const f = Math.max(1, a), t = A(r, 1, f), M = j({
19
+ boundaryCount: e,
20
+ currentPage: t,
21
+ siblingCount: m,
22
+ totalPages: f
23
+ }), N = t > 1 && !i, k = t < f && !i, w = G({
24
+ currentPage: t,
25
+ pageSize: o,
26
+ totalItems: p,
27
+ totalPages: f
28
+ });
29
+ return /* @__PURE__ */ g(
30
+ "nav",
31
+ {
32
+ "aria-label": "Pagination",
33
+ className: b("inline-flex items-center gap-6", n),
34
+ ...u,
35
+ children: [
36
+ h ? /* @__PURE__ */ c(
37
+ $,
38
+ {
39
+ as: "span",
40
+ className: "whitespace-nowrap text-[var(--color-text-secondary)]",
41
+ variant: "b3",
42
+ children: w
43
+ }
44
+ ) : null,
45
+ /* @__PURE__ */ g("div", { className: "inline-flex items-center gap-[6px]", children: [
46
+ /* @__PURE__ */ c(
47
+ v,
48
+ {
49
+ "aria-label": "Предыдущая страница",
50
+ disabled: !N,
51
+ onClick: () => s?.(t - 1),
52
+ children: /* @__PURE__ */ c(d, { className: "h-[9px] w-3" })
53
+ }
54
+ ),
55
+ M.map(
56
+ (l, _) => l === "ellipsis" ? /* @__PURE__ */ c(
57
+ "span",
58
+ {
59
+ "aria-hidden": "true",
60
+ className: "inline-flex min-h-6 min-w-6 items-center justify-center text-[13px] leading-[18px] text-[var(--color-text-secondary)]",
61
+ children: "..."
62
+ },
63
+ `ellipsis-${_}`
64
+ ) : /* @__PURE__ */ c(
65
+ v,
66
+ {
67
+ "aria-current": l === t ? "page" : void 0,
68
+ "aria-label": `Страница ${l}`,
69
+ isActive: l === t,
70
+ disabled: i,
71
+ onClick: () => s?.(l),
72
+ children: l
73
+ },
74
+ l
75
+ )
76
+ ),
77
+ /* @__PURE__ */ c(
78
+ v,
79
+ {
80
+ "aria-label": "Следующая страница",
81
+ disabled: !k,
82
+ onClick: () => s?.(t + 1),
83
+ children: /* @__PURE__ */ c(d, { className: "h-[9px] w-3 rotate-180" })
84
+ }
85
+ )
86
+ ] })
87
+ ]
88
+ }
89
+ );
90
+ }
91
+ function v({
92
+ children: e,
93
+ className: n,
94
+ disabled: r,
95
+ isActive: i = !1,
96
+ ...s
97
+ }) {
98
+ return /* @__PURE__ */ c(
99
+ "button",
100
+ {
101
+ className: b(
102
+ "inline-flex min-h-6 min-w-6 items-center justify-center rounded-[6px] bg-[var(--color-background-subtle)] px-1 text-[13px] font-normal leading-[18px] text-[var(--color-text-primary)] transition-colors [font-family:var(--font-family)] hover:bg-[color-mix(in_srgb,var(--color-background-subtle)_90%,#000)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[color-mix(in_srgb,var(--color-primary-accent)_35%,transparent)] disabled:pointer-events-none disabled:opacity-50 [&_svg]:shrink-0",
103
+ i && "bg-[var(--color-primary-accent)] text-[var(--color-background-default)] hover:bg-[color-mix(in_srgb,var(--color-primary-accent)_80%,#fff)]",
104
+ n
105
+ ),
106
+ disabled: r,
107
+ type: "button",
108
+ ...s,
109
+ children: e
110
+ }
111
+ );
112
+ }
113
+ function j({
114
+ boundaryCount: e,
115
+ currentPage: n,
116
+ siblingCount: r,
117
+ totalPages: i
118
+ }) {
119
+ const s = e * 2 + r * 2 + 3;
120
+ if (i <= s)
121
+ return x(1, i);
122
+ const o = x(1, e), h = x(i - e + 1, i), m = Math.max(
123
+ Math.min(n - r, i - e - r * 2 - 1),
124
+ e + 2
125
+ ), p = Math.min(
126
+ Math.max(n + r, e + r * 2 + 2),
127
+ i - e - 1
128
+ ), a = [...o];
129
+ return m > e + 2 ? a.push("ellipsis") : e + 1 < i - e && a.push(e + 1), a.push(...x(m, p)), p < i - e - 1 ? a.push("ellipsis") : i - e > e && a.push(i - e), a.push(...h), a;
130
+ }
131
+ function x(e, n) {
132
+ if (n < e)
133
+ return [];
134
+ const r = [];
135
+ for (let i = e; i <= n; i += 1)
136
+ r.push(i);
137
+ return r;
138
+ }
139
+ function A(e, n, r) {
140
+ return Math.min(Math.max(e, n), r);
141
+ }
142
+ function G({
143
+ currentPage: e,
144
+ pageSize: n,
145
+ totalItems: r,
146
+ totalPages: i
147
+ }) {
148
+ if (!n || !r)
149
+ return `${e} из ${i}`;
150
+ const s = (e - 1) * n + 1, o = Math.min(e * n, r);
151
+ return `${s}-${o} из ${r}`;
152
+ }
153
+ export {
154
+ P as Pagination
155
+ };
@@ -0,0 +1,12 @@
1
+ import { ReactNode } from 'react';
2
+ import { PictureProps } from './picture.types';
3
+ /**
4
+ * Адаптивная обертка над HTML-элементом `picture`.
5
+ *
6
+ * Компонент принимает изображения через проектные брейкпоинты `sm`, `md`,
7
+ * `lg` и `xl`. Значение `sm` используется как обязательный fallback для
8
+ * внутреннего `img`, а остальные значения преобразуются в `source` с
9
+ * min-width из общего responsive-конфига ui-kit.
10
+ */
11
+ export declare function Picture({ display, image, sources, ...props }: PictureProps): ReactNode;
12
+ export type { PictureBreakpoint, PictureBreakpointSource, PictureBreakpointSources, PictureProps, } from './picture.types';
@@ -0,0 +1,9 @@
1
+ import { SourceHTMLAttributes } from 'react';
2
+ import { PictureBreakpoint, PictureBreakpointSource, PictureBreakpointSources } from './picture.types';
3
+ export type PictureResolvedBreakpointSource = {
4
+ breakpoint: Exclude<PictureBreakpoint, 'sm'>;
5
+ source: PictureBreakpointSource;
6
+ };
7
+ export declare function buildBreakpointSources(sources: PictureBreakpointSources): PictureResolvedBreakpointSource[];
8
+ export declare function getSourceSrcSet(source: PictureBreakpointSource): string;
9
+ export declare function getSourceProps(source: PictureBreakpointSource): SourceHTMLAttributes<HTMLSourceElement>;
@@ -0,0 +1,56 @@
1
+ import { ImgHTMLAttributes, SourceHTMLAttributes } from 'react';
2
+ import { BoxProps } from '../box/box.types';
3
+ /**
4
+ * Поддерживаемые проектные брейкпоинты для компонента `Picture`.
5
+ *
6
+ * `sm` не превращается в отдельный `source`: это базовая картинка для
7
+ * внутреннего `img`. Остальные брейкпоинты получают media-query из общего
8
+ * responsive-конфига ui-kit.
9
+ */
10
+ export type PictureBreakpoint = 'sm' | 'md' | 'lg' | 'xl';
11
+ /**
12
+ * Описание картинки для одного брейкпоинта.
13
+ *
14
+ * Можно передать строку, если достаточно указать только `srcSet`. В этом
15
+ * случае компонент добавит `type="image/webp"` по умолчанию.
16
+ *
17
+ * Можно передать объект, если нужно управлять дополнительными атрибутами
18
+ * `source`, например `type`, `sizes`, `width` или `height`.
19
+ */
20
+ export type PictureBreakpointSource = string | (Omit<SourceHTMLAttributes<HTMLSourceElement>, 'media' | 'srcSet'> & {
21
+ srcSet: string;
22
+ });
23
+ /**
24
+ * Набор изображений для проектных брейкпоинтов.
25
+ *
26
+ * `sm` обязателен: он используется как fallback `src` для внутреннего `img`.
27
+ * `md`, `lg` и `xl` опциональны и рендерятся как `source` в порядке от
28
+ * большего брейкпоинта к меньшему, чтобы браузер выбрал наиболее подходящий
29
+ * ресурс.
30
+ */
31
+ export type PictureBreakpointSources = {
32
+ sm: PictureBreakpointSource;
33
+ } & Partial<Record<Exclude<PictureBreakpoint, 'sm'>, PictureBreakpointSource>>;
34
+ /**
35
+ * Свойства компонента `Picture`.
36
+ *
37
+ * Компонент наследует свойства `Box`, кроме `as` и `children`: тег всегда
38
+ * фиксирован как `picture`, а содержимое формируется из `sources` и `image`.
39
+ */
40
+ export type PictureProps = Omit<BoxProps<'picture'>, 'as' | 'children'> & {
41
+ /**
42
+ * Атрибуты для внутреннего элемента `img`.
43
+ *
44
+ * `src` задается автоматически из `sources.sm`, поэтому его нельзя передать
45
+ * через этот объект. `alt` лучше указывать явно; если он не передан,
46
+ * компонент использует пустую строку для декоративного изображения.
47
+ */
48
+ image?: Omit<ImgHTMLAttributes<HTMLImageElement>, 'src'>;
49
+ /**
50
+ * Изображения для проектных брейкпоинтов.
51
+ *
52
+ * `sm` является обязательным fallback, `md`, `lg` и `xl` подключаются через
53
+ * media-query, значения которых берутся из общего responsive-конфига ui-kit.
54
+ */
55
+ sources: PictureBreakpointSources;
56
+ };
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("react/jsx-runtime"),f=require("./box.cjs"),p=require("./responsive-style.config-B2m9jVlX.cjs");function S(e){return[...p.responsiveBreakpoints].reverse().flatMap(t=>{const i=e[t];return i?[{breakpoint:t,source:i}]:[]})}function o(e){return typeof e=="string"?e:e.srcSet}function y(e){if(typeof e!="string")return e;const t=e.split("?")[0].split("#")[0].split(".").pop()?.toLowerCase(),i={avif:"image/avif",jpeg:"image/jpeg",jpg:"image/jpeg",png:"image/png",webp:"image/webp"};return t&&i[t]?{type:i[t]}:{}}function d({display:e="block",image:t,sources:i,...c}){const{alt:a="",style:g,...u}=t??{},l=o(i.sm),m=S(i);return n.jsxs(f.Box,{...c,as:"picture",display:e,children:[m.map(({breakpoint:r,source:s})=>n.jsx("source",{...y(s),media:`(min-width: ${p.responsiveBreakpointMinWidth[r]})`,srcSet:o(s)},r)),n.jsx("img",{alt:a,src:l,style:{display:"block",height:"auto",width:"100%",...g},...u})]})}exports.Picture=d;
@@ -0,0 +1,55 @@
1
+ import { jsxs as f, jsx as o } from "react/jsx-runtime";
2
+ import { Box as u } from "./box.js";
3
+ import { a as S, r as y } from "./responsive-style.config-DFuATrIM.js";
4
+ function d(e) {
5
+ return [...S].reverse().flatMap((t) => {
6
+ const i = e[t];
7
+ return i ? [{ breakpoint: t, source: i }] : [];
8
+ });
9
+ }
10
+ function s(e) {
11
+ return typeof e == "string" ? e : e.srcSet;
12
+ }
13
+ function h(e) {
14
+ if (typeof e != "string")
15
+ return e;
16
+ const t = e.split("?")[0].split("#")[0].split(".").pop()?.toLowerCase(), i = {
17
+ avif: "image/avif",
18
+ jpeg: "image/jpeg",
19
+ jpg: "image/jpeg",
20
+ png: "image/png",
21
+ webp: "image/webp"
22
+ };
23
+ return t && i[t] ? { type: i[t] } : {};
24
+ }
25
+ function k({ display: e = "block", image: t, sources: i, ...p }) {
26
+ const { alt: a = "", style: c, ...m } = t ?? {}, g = s(i.sm), l = d(i);
27
+ return /* @__PURE__ */ f(u, { ...p, as: "picture", display: e, children: [
28
+ l.map(({ breakpoint: r, source: n }) => /* @__PURE__ */ o(
29
+ "source",
30
+ {
31
+ ...h(n),
32
+ media: `(min-width: ${y[r]})`,
33
+ srcSet: s(n)
34
+ },
35
+ r
36
+ )),
37
+ /* @__PURE__ */ o(
38
+ "img",
39
+ {
40
+ alt: a,
41
+ src: g,
42
+ style: {
43
+ display: "block",
44
+ height: "auto",
45
+ width: "100%",
46
+ ...c
47
+ },
48
+ ...m
49
+ }
50
+ )
51
+ ] });
52
+ }
53
+ export {
54
+ k as Picture
55
+ };
@@ -0,0 +1 @@
1
+ "use strict";const n=require("clsx"),i=require("tailwind-merge");function s(...e){return i.twMerge(n.clsx(e))}const r=["md","lg","xl"],t={md:"768px",lg:"1024px",xl:"1440px"};exports.cn=s;exports.responsiveBreakpointMinWidth=t;exports.responsiveBreakpoints=r;
@@ -0,0 +1,19 @@
1
+ import { clsx as o } from "clsx";
2
+ import { twMerge as n } from "tailwind-merge";
3
+ function e(...r) {
4
+ return n(o(r));
5
+ }
6
+ const p = [
7
+ "md",
8
+ "lg",
9
+ "xl"
10
+ ], i = {
11
+ md: "768px",
12
+ lg: "1024px",
13
+ xl: "1440px"
14
+ };
15
+ export {
16
+ p as a,
17
+ e as c,
18
+ i as r
19
+ };
@@ -0,0 +1 @@
1
+ "use strict";function a(...r){return r.reduce((o,s)=>s?{colors:{...o.colors,...s.colors},typography:{...o.typography,...s.typography},vars:{...o.vars,...s.vars},md:y(o.md,s.md),lg:y(o.lg,s.lg),xl:y(o.xl,s.xl)}:o,{})}function i(r){return typeof r=="string"&&r.startsWith("--")?`var(${r})`:r}function y(r,o){if(!(!r&&!o))return{colors:{...r?.colors,...o?.colors},typography:{...r?.typography,...o?.typography},vars:{...r?.vars,...o?.vars}}}exports.mergeResponsiveStyleProps=a;exports.normalizeCssTokenValue=i;
@@ -0,0 +1,25 @@
1
+ function g(...r) {
2
+ return r.reduce((o, a) => a ? {
3
+ colors: { ...o.colors, ...a.colors },
4
+ typography: { ...o.typography, ...a.typography },
5
+ vars: { ...o.vars, ...a.vars },
6
+ md: y(o.md, a.md),
7
+ lg: y(o.lg, a.lg),
8
+ xl: y(o.xl, a.xl)
9
+ } : o, {});
10
+ }
11
+ function i(r) {
12
+ return typeof r == "string" && r.startsWith("--") ? `var(${r})` : r;
13
+ }
14
+ function y(r, o) {
15
+ if (!(!r && !o))
16
+ return {
17
+ colors: { ...r?.colors, ...o?.colors },
18
+ typography: { ...r?.typography, ...o?.typography },
19
+ vars: { ...r?.vars, ...o?.vars }
20
+ };
21
+ }
22
+ export {
23
+ g as m,
24
+ i as n
25
+ };
@@ -0,0 +1,55 @@
1
+ import { ButtonHTMLAttributes, JSX, ReactNode, SelectHTMLAttributes } from 'react';
2
+ import { SelectDropdownBoxProps, SelectOption, SelectTriggerBoxProps } from './select.types';
3
+ export type { SelectOption } from './select.types';
4
+ export interface SelectTriggerRenderProps {
5
+ displayValue: ReactNode;
6
+ isOpen: boolean;
7
+ isPlaceholder: boolean;
8
+ selectedOption: SelectOption | undefined;
9
+ selectedValue: string;
10
+ }
11
+ export interface SelectTriggerSlotProps extends SelectTriggerRenderProps {
12
+ defaultTrigger: ReactNode;
13
+ triggerProps: ButtonHTMLAttributes<HTMLButtonElement> & {
14
+ className: string;
15
+ fullWidth: true;
16
+ type: 'button';
17
+ variant: 'secondary';
18
+ };
19
+ }
20
+ export interface SelectOptionRenderProps {
21
+ defaultOption: ReactNode;
22
+ isDisabled: boolean;
23
+ isSelected: boolean;
24
+ option: SelectOption;
25
+ optionProps: ButtonHTMLAttributes<HTMLButtonElement>;
26
+ }
27
+ export interface SelectProps extends Omit<SelectHTMLAttributes<HTMLSelectElement>, 'children' | 'size'> {
28
+ /** Альтернативный способ передать пункты через native `<option>`. */
29
+ children?: ReactNode;
30
+ /** Размеры и фон dropdown-панели через Box responsive props. */
31
+ dropdownBoxProps?: SelectDropdownBoxProps;
32
+ /** Переводит select в состояние ошибки. */
33
+ error?: boolean;
34
+ /** Текст ошибки. Показывается под select и окрашивается в danger-токен. */
35
+ errorMessage?: ReactNode;
36
+ /** Подсказка под select, показывается когда нет `errorMessage`. */
37
+ helperText?: ReactNode;
38
+ /** Label над select. */
39
+ label?: ReactNode;
40
+ /** Callback с новым значением без synthetic event. */
41
+ onValueChange?: (value: string) => void;
42
+ /** Список пунктов select. */
43
+ options?: SelectOption[];
44
+ /** Текст, который показывается когда значение не выбрано. */
45
+ placeholder?: string;
46
+ /** Полная замена option-рендера. Получает готовые optionProps и defaultOption. */
47
+ renderOption?: (props: SelectOptionRenderProps) => ReactNode;
48
+ /** Полная замена trigger-рендера. Получает готовые triggerProps и defaultTrigger. */
49
+ renderTrigger?: (props: SelectTriggerSlotProps) => ReactNode;
50
+ /** Кастомное содержимое trigger-кнопки или render-функция для полного контроля над ним. */
51
+ trigger?: ReactNode | ((props: SelectTriggerRenderProps) => ReactNode);
52
+ /** Размеры trigger-кнопки через Box responsive props. */
53
+ triggerBoxProps?: SelectTriggerBoxProps;
54
+ }
55
+ export declare function Select({ className, defaultValue, disabled, dropdownBoxProps, error, errorMessage, helperText, id, label, name, onChange, onValueChange, options, placeholder, renderOption, renderTrigger, required, trigger, triggerBoxProps, value, children, ...props }: SelectProps): JSX.Element;
@@ -0,0 +1,14 @@
1
+ import { ReactNode } from 'react';
2
+ import { SelectOption } from './select.types';
3
+ /**
4
+ * Приводит варианты select к единому внутреннему формату.
5
+ *
6
+ * Компонент поддерживает два способа задания пунктов:
7
+ * - через prop `options`;
8
+ * - через native `<option>` в `children`.
9
+ *
10
+ * Если `options` передан явно, он считается главным источником данных. Если
11
+ * нет, helper читает React children, оставляет только валидные элементы с
12
+ * `value` и собирает из них `SelectOption`.
13
+ */
14
+ export declare function normalizeOptions(options: SelectOption[] | undefined, children: ReactNode): SelectOption[];
@@ -0,0 +1,12 @@
1
+ import { ReactNode } from 'react';
2
+ import { BoxProps } from '../box/box.types';
3
+ export type SelectTriggerBoxProps = Pick<BoxProps, 'width' | 'maxWidth' | 'minWidth' | 'height' | 'maxHeight' | 'minHeight' | 'md' | 'lg' | 'xl'>;
4
+ export type SelectDropdownBoxProps = Pick<BoxProps, 'width' | 'maxWidth' | 'minWidth' | 'height' | 'maxHeight' | 'minHeight' | 'background' | 'backgroundColor' | 'md' | 'lg' | 'xl'>;
5
+ export interface SelectOption {
6
+ /** Отключает конкретный пункт списка. */
7
+ disabled?: boolean;
8
+ /** Видимый текст или React-содержимое пункта. */
9
+ label: ReactNode;
10
+ /** Значение, которое попадет в форму и callback при выборе пункта. */
11
+ value: string;
12
+ }
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react/jsx-runtime"),n=require("react"),L=require("./box.cjs"),X=require("./button.cjs"),u=require("./responsive-style.config-B2m9jVlX.cjs"),p=require("./typography.cjs");function Y(l,x){return l||n.Children.toArray(x).flatMap(r=>{if(!n.isValidElement(r))return[];const s=r.props.value;return s===void 0?[]:[{disabled:r.props.disabled,label:r.props.children??s,value:s}]})}function Z({className:l,defaultValue:x,disabled:r=!1,dropdownBoxProps:s,error:j=!1,errorMessage:w,helperText:M,id:V,label:N,name:f,onChange:S,onValueChange:W,options:O,placeholder:b,renderOption:k,renderTrigger:q,required:A,trigger:v,triggerBoxProps:D,value:o,children:C,..._}){const G=n.useId(),h=V??G,P=n.useRef(null),[i,m]=n.useState(!1),[J,K]=n.useState(()=>String(x??o??"")),T=w??M,c=n.useMemo(()=>Y(O,C),[O,C]),d=o!==void 0?String(o):J,y=c.find(e=>e.value===d),I=y?.label??b,R=!y,B={displayValue:I,isOpen:i,isPlaceholder:R,selectedOption:y,selectedValue:d},Q=typeof v=="function"?v(B):v;n.useEffect(()=>{function e(a){P.current?.contains(a.target)||m(!1)}return document.addEventListener("mousedown",e),()=>document.removeEventListener("mousedown",e)},[]);function U(e){const a=c.find(g=>g.value===e);!a||a.disabled||r||(o===void 0&&K(e),W?.(e),S?.({currentTarget:{name:f,value:e},target:{name:f,value:e}}),m(!1))}const E={"aria-expanded":i,"aria-haspopup":"listbox","aria-invalid":j||_["aria-invalid"],className:u.cn("h-full min-h-0 min-w-0 justify-between border border-transparent px-[16px] py-[12px] text-left",j&&"border-[var(--color-secondary-accent-2)] focus-visible:ring-[var(--color-secondary-accent-2)]",l),disabled:r,fullWidth:!0,id:h,type:"button",variant:"secondary",onClick:()=>m(e=>!e)},z=t.jsx(X.Button,{...E,children:Q??t.jsxs(t.Fragment,{children:[t.jsx(p.Typography,{as:"span",className:u.cn("min-w-[0px] truncate",R&&"text-[var(--color-text-secondary)]"),variant:"b3",children:I}),t.jsx("span",{className:"relative size-[16px] shrink-0 text-[var(--color-text-primary)]",children:t.jsx("span",{className:u.cn("absolute left-1/2 top-1/2 h-[8px] w-[8px] -translate-x-1/2 -translate-y-[65%] rotate-45 border-b border-r border-current transition-transform",i&&"translate-y-[-35%] rotate-[225deg]")})})]})});return t.jsxs("div",{className:"grid w-full gap-[8px]",ref:P,children:[N?t.jsx(p.Typography,{as:"label",color:"--color-text-secondary",htmlFor:h,variant:"b2",children:N}):null,t.jsxs("div",{className:"relative w-full",children:[t.jsx(L.Box,{minHeight:42,width:"100%",...D,children:q?q({...B,defaultTrigger:z,triggerProps:E}):z}),i&&!r?t.jsx(L.Box,{backgroundColor:"--color-background-default",className:"absolute left-0 top-full z-50 mt-[8px] flex overflow-hidden rounded-[8px] p-[8px] shadow-md",maxHeight:220,minWidth:214,width:"100%",...s,children:t.jsx("div",{className:"grid max-h-[204px] flex-1 gap-[0px] overflow-y-auto pr-[4px]",role:"listbox","aria-labelledby":h,children:c.map(e=>{const a=e.value===d,g=!!e.disabled,F={"aria-selected":a,className:u.cn("flex min-h-[45px] w-full items-center rounded-[8px] px-[16px] py-[12px] text-left transition-colors hover:bg-[var(--color-background-subtle)] disabled:pointer-events-none disabled:opacity-50",a&&"bg-[var(--color-background-subtle)]"),disabled:e.disabled,role:"option",type:"button",onClick:()=>U(e.value)},H=t.jsx("button",{...F,children:t.jsx(p.Typography,{as:"span",className:"min-w-[0px] truncate",variant:"b2",children:e.label})});return t.jsx(n.Fragment,{children:k?k({defaultOption:H,isDisabled:g,isSelected:a,option:e,optionProps:F}):H},e.value)})})}):null,t.jsxs("select",{"aria-hidden":"true",className:"sr-only",disabled:r,name:f,required:A,tabIndex:-1,value:d,onChange:S??(()=>{}),children:[b?t.jsx("option",{value:"",children:b}):null,c.map(e=>t.jsx("option",{disabled:e.disabled,value:e.value,children:e.label},e.value))]})]}),T?t.jsx(p.Typography,{color:w?"--color-secondary-accent-2":"--color-text-secondary",variant:"b3",children:T}):null]})}exports.Select=Z;
package/dist/select.js ADDED
@@ -0,0 +1,179 @@
1
+ import { jsx as t, jsxs as d, Fragment as Y } from "react/jsx-runtime";
2
+ import { Children as Z, isValidElement as _, useId as ee, useRef as te, useState as V, useMemo as re, useEffect as ae, Fragment as ne } from "react";
3
+ import { Box as W } from "./box.js";
4
+ import { Button as le } from "./button.js";
5
+ import { c as u } from "./responsive-style.config-DFuATrIM.js";
6
+ import { Typography as p } from "./typography.js";
7
+ function oe(l, f) {
8
+ return l || Z.toArray(f).flatMap((r) => {
9
+ if (!_(r))
10
+ return [];
11
+ const n = r.props.value;
12
+ return n === void 0 ? [] : [
13
+ {
14
+ disabled: r.props.disabled,
15
+ label: r.props.children ?? n,
16
+ value: n
17
+ }
18
+ ];
19
+ });
20
+ }
21
+ function fe({
22
+ className: l,
23
+ defaultValue: f,
24
+ disabled: r = !1,
25
+ dropdownBoxProps: n,
26
+ error: w = !1,
27
+ errorMessage: N,
28
+ helperText: A,
29
+ id: D,
30
+ label: k,
31
+ name: m,
32
+ onChange: O,
33
+ onValueChange: M,
34
+ options: C,
35
+ placeholder: b,
36
+ renderOption: S,
37
+ renderTrigger: I,
38
+ required: $,
39
+ trigger: v,
40
+ triggerBoxProps: q,
41
+ value: o,
42
+ children: P,
43
+ ...G
44
+ }) {
45
+ const J = ee(), x = D ?? J, E = te(null), [s, h] = V(!1), [K, Q] = V(
46
+ () => String(f ?? o ?? "")
47
+ ), F = N ?? A, i = re(() => oe(C, P), [C, P]), c = o !== void 0 ? String(o) : K, g = i.find((e) => e.value === c), j = g?.label ?? b, z = !g, B = {
48
+ displayValue: j,
49
+ isOpen: s,
50
+ isPlaceholder: z,
51
+ selectedOption: g,
52
+ selectedValue: c
53
+ }, U = typeof v == "function" ? v(B) : v;
54
+ ae(() => {
55
+ function e(a) {
56
+ E.current?.contains(a.target) || h(!1);
57
+ }
58
+ return document.addEventListener("mousedown", e), () => document.removeEventListener("mousedown", e);
59
+ }, []);
60
+ function X(e) {
61
+ const a = i.find((y) => y.value === e);
62
+ !a || a.disabled || r || (o === void 0 && Q(e), M?.(e), O?.({
63
+ currentTarget: { name: m, value: e },
64
+ target: { name: m, value: e }
65
+ }), h(!1));
66
+ }
67
+ const R = {
68
+ "aria-expanded": s,
69
+ "aria-haspopup": "listbox",
70
+ "aria-invalid": w || G["aria-invalid"],
71
+ className: u(
72
+ "h-full min-h-0 min-w-0 justify-between border border-transparent px-[16px] py-[12px] text-left",
73
+ w && "border-[var(--color-secondary-accent-2)] focus-visible:ring-[var(--color-secondary-accent-2)]",
74
+ l
75
+ ),
76
+ disabled: r,
77
+ fullWidth: !0,
78
+ id: x,
79
+ type: "button",
80
+ variant: "secondary",
81
+ onClick: () => h((e) => !e)
82
+ }, H = /* @__PURE__ */ t(le, { ...R, children: U ?? /* @__PURE__ */ d(Y, { children: [
83
+ /* @__PURE__ */ t(
84
+ p,
85
+ {
86
+ as: "span",
87
+ className: u(
88
+ "min-w-[0px] truncate",
89
+ z && "text-[var(--color-text-secondary)]"
90
+ ),
91
+ variant: "b3",
92
+ children: j
93
+ }
94
+ ),
95
+ /* @__PURE__ */ t("span", { className: "relative size-[16px] shrink-0 text-[var(--color-text-primary)]", children: /* @__PURE__ */ t(
96
+ "span",
97
+ {
98
+ className: u(
99
+ "absolute left-1/2 top-1/2 h-[8px] w-[8px] -translate-x-1/2 -translate-y-[65%] rotate-45 border-b border-r border-current transition-transform",
100
+ s && "translate-y-[-35%] rotate-[225deg]"
101
+ )
102
+ }
103
+ ) })
104
+ ] }) });
105
+ return /* @__PURE__ */ d("div", { className: "grid w-full gap-[8px]", ref: E, children: [
106
+ k ? /* @__PURE__ */ t(p, { as: "label", color: "--color-text-secondary", htmlFor: x, variant: "b2", children: k }) : null,
107
+ /* @__PURE__ */ d("div", { className: "relative w-full", children: [
108
+ /* @__PURE__ */ t(W, { minHeight: 42, width: "100%", ...q, children: I ? I({ ...B, defaultTrigger: H, triggerProps: R }) : H }),
109
+ s && !r ? /* @__PURE__ */ t(
110
+ W,
111
+ {
112
+ backgroundColor: "--color-background-default",
113
+ className: "absolute left-0 top-full z-50 mt-[8px] flex overflow-hidden rounded-[8px] p-[8px] shadow-md",
114
+ maxHeight: 220,
115
+ minWidth: 214,
116
+ width: "100%",
117
+ ...n,
118
+ children: /* @__PURE__ */ t(
119
+ "div",
120
+ {
121
+ className: "grid max-h-[204px] flex-1 gap-[0px] overflow-y-auto pr-[4px]",
122
+ role: "listbox",
123
+ "aria-labelledby": x,
124
+ children: i.map((e) => {
125
+ const a = e.value === c, y = !!e.disabled, L = {
126
+ "aria-selected": a,
127
+ className: u(
128
+ "flex min-h-[45px] w-full items-center rounded-[8px] px-[16px] py-[12px] text-left transition-colors hover:bg-[var(--color-background-subtle)] disabled:pointer-events-none disabled:opacity-50",
129
+ a && "bg-[var(--color-background-subtle)]"
130
+ ),
131
+ disabled: e.disabled,
132
+ role: "option",
133
+ type: "button",
134
+ onClick: () => X(e.value)
135
+ }, T = /* @__PURE__ */ t("button", { ...L, children: /* @__PURE__ */ t(p, { as: "span", className: "min-w-[0px] truncate", variant: "b2", children: e.label }) });
136
+ return /* @__PURE__ */ t(ne, { children: S ? S({
137
+ defaultOption: T,
138
+ isDisabled: y,
139
+ isSelected: a,
140
+ option: e,
141
+ optionProps: L
142
+ }) : T }, e.value);
143
+ })
144
+ }
145
+ )
146
+ }
147
+ ) : null,
148
+ /* @__PURE__ */ d(
149
+ "select",
150
+ {
151
+ "aria-hidden": "true",
152
+ className: "sr-only",
153
+ disabled: r,
154
+ name: m,
155
+ required: $,
156
+ tabIndex: -1,
157
+ value: c,
158
+ onChange: O ?? (() => {
159
+ }),
160
+ children: [
161
+ b ? /* @__PURE__ */ t("option", { value: "", children: b }) : null,
162
+ i.map((e) => /* @__PURE__ */ t("option", { disabled: e.disabled, value: e.value, children: e.label }, e.value))
163
+ ]
164
+ }
165
+ )
166
+ ] }),
167
+ F ? /* @__PURE__ */ t(
168
+ p,
169
+ {
170
+ color: N ? "--color-secondary-accent-2" : "--color-text-secondary",
171
+ variant: "b3",
172
+ children: F
173
+ }
174
+ ) : null
175
+ ] });
176
+ }
177
+ export {
178
+ fe as Select
179
+ };
@@ -0,0 +1,2 @@
1
+ import { ClassValue } from 'clsx';
2
+ export declare function cn(...inputs: ClassValue[]): string;
@@ -0,0 +1,20 @@
1
+ import { ResponsiveStyleBreakpoint } from './responsive-style.types';
2
+ export type ResponsiveBreakpointMinWidth = Record<ResponsiveStyleBreakpoint, string>;
3
+ /**
4
+ * Единый порядок responsive breakpoints для всего ui-kit.
5
+ *
6
+ * Важно для разработчика и ИИ: не заводить локальные массивы breakpoint-ов
7
+ * внутри компонентов. Все компоненты, которые генерируют responsive CSS, должны
8
+ * использовать этот список, чтобы cascade и порядок media queries были одинаковыми.
9
+ */
10
+ export declare const responsiveBreakpoints: readonly ["md", "lg", "xl"];
11
+ /**
12
+ * Единые min-width значения breakpoint-ов для всего ui-kit.
13
+ *
14
+ * Если дизайн-система меняет пороги адаптива, править нужно только этот объект.
15
+ */
16
+ export declare const responsiveBreakpointMinWidth: {
17
+ readonly md: "768px";
18
+ readonly lg: "1024px";
19
+ readonly xl: "1440px";
20
+ };