@arkyn/components 3.0.8 → 3.0.9

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 (86) hide show
  1. package/dist/components/calendar/calendarTableTd/index.d.ts.map +1 -1
  2. package/dist/components/currencyInput/index.d.ts +1 -1
  3. package/dist/components/datePicker/datePickerCalendarContainer/index.d.ts +1 -0
  4. package/dist/components/datePicker/datePickerCalendarContainer/index.d.ts.map +1 -1
  5. package/dist/components/datePicker/datePickerContainer/index.d.ts +5 -1
  6. package/dist/components/datePicker/datePickerContainer/index.d.ts.map +1 -1
  7. package/dist/components/datePicker/index.d.ts.map +1 -1
  8. package/dist/components/drawer/drawerContainer/index.d.ts.map +1 -1
  9. package/dist/components/imageUpload/index.d.ts +1 -1
  10. package/dist/components/input/index.d.ts +1 -1
  11. package/dist/components/modal/modalContainer/index.d.ts.map +1 -1
  12. package/dist/components/multiSelect/index.d.ts +1 -1
  13. package/dist/components/multiSelect/index.d.ts.map +1 -1
  14. package/dist/components/multiSelect/multiSelectContainer/index.d.ts +6 -1
  15. package/dist/components/multiSelect/multiSelectContainer/index.d.ts.map +1 -1
  16. package/dist/components/multiSelect/multiSelectOption/index.d.ts +2 -0
  17. package/dist/components/multiSelect/multiSelectOption/index.d.ts.map +1 -1
  18. package/dist/components/multiSelect/multiSelectOptionsContainer/index.d.ts +1 -0
  19. package/dist/components/multiSelect/multiSelectOptionsContainer/index.d.ts.map +1 -1
  20. package/dist/components/popover/index.d.ts.map +1 -1
  21. package/dist/components/richText/index.d.ts +1 -1
  22. package/dist/components/select/index.d.ts +1 -1
  23. package/dist/components/select/index.d.ts.map +1 -1
  24. package/dist/components/select/selectContainer/index.d.ts +6 -1
  25. package/dist/components/select/selectContainer/index.d.ts.map +1 -1
  26. package/dist/components/select/selectOption/index.d.ts +2 -0
  27. package/dist/components/select/selectOption/index.d.ts.map +1 -1
  28. package/dist/components/select/selectOptionsContainer/index.d.ts +1 -0
  29. package/dist/components/select/selectOptionsContainer/index.d.ts.map +1 -1
  30. package/dist/hooks/useEscapeKey.d.ts +24 -0
  31. package/dist/hooks/useEscapeKey.d.ts.map +1 -0
  32. package/dist/hooks/useFocusTrap.d.ts +28 -0
  33. package/dist/hooks/useFocusTrap.d.ts.map +1 -0
  34. package/dist/index.js +948 -736
  35. package/dist/index.js.map +1 -1
  36. package/dist/modules/components/calendar/calendarTableTd/index.js +7 -2
  37. package/dist/modules/components/calendar/calendarTableTd/index.js.map +1 -1
  38. package/dist/modules/components/calendar/calendarTableTd/styles.css +1 -1
  39. package/dist/modules/components/calendar/styles.css +2 -2
  40. package/dist/modules/components/currencyInput/index.js.map +1 -1
  41. package/dist/modules/components/datePicker/datePickerCalendarContainer/index.js +12 -9
  42. package/dist/modules/components/datePicker/datePickerCalendarContainer/index.js.map +1 -1
  43. package/dist/modules/components/datePicker/datePickerContainer/index.js +9 -2
  44. package/dist/modules/components/datePicker/datePickerContainer/index.js.map +1 -1
  45. package/dist/modules/components/datePicker/index.js +63 -44
  46. package/dist/modules/components/datePicker/index.js.map +1 -1
  47. package/dist/modules/components/datePicker/styles.css +4 -4
  48. package/dist/modules/components/drawer/drawerContainer/index.js +31 -23
  49. package/dist/modules/components/drawer/drawerContainer/index.js.map +1 -1
  50. package/dist/modules/components/facebookPixel/pixel.js +1 -1
  51. package/dist/modules/components/facebookPixel/pixel.js.map +1 -1
  52. package/dist/modules/components/imageUpload/index.js.map +1 -1
  53. package/dist/modules/components/input/index.js.map +1 -1
  54. package/dist/modules/components/modal/modalContainer/index.js +30 -22
  55. package/dist/modules/components/modal/modalContainer/index.js.map +1 -1
  56. package/dist/modules/components/multiSelect/index.js +119 -79
  57. package/dist/modules/components/multiSelect/index.js.map +1 -1
  58. package/dist/modules/components/multiSelect/multiSelectContainer/index.js +10 -2
  59. package/dist/modules/components/multiSelect/multiSelectContainer/index.js.map +1 -1
  60. package/dist/modules/components/multiSelect/multiSelectOption/index.js +7 -3
  61. package/dist/modules/components/multiSelect/multiSelectOption/index.js.map +1 -1
  62. package/dist/modules/components/multiSelect/multiSelectOption/styles.css +1 -1
  63. package/dist/modules/components/multiSelect/multiSelectOptionsContainer/index.js +18 -15
  64. package/dist/modules/components/multiSelect/multiSelectOptionsContainer/index.js.map +1 -1
  65. package/dist/modules/components/multiSelect/styles.css +1 -1
  66. package/dist/modules/components/popover/index.js +23 -17
  67. package/dist/modules/components/popover/index.js.map +1 -1
  68. package/dist/modules/components/richText/index.js.map +1 -1
  69. package/dist/modules/components/searchPlaces.js +1 -1
  70. package/dist/modules/components/searchPlaces.js.map +1 -1
  71. package/dist/modules/components/select/index.js +120 -80
  72. package/dist/modules/components/select/index.js.map +1 -1
  73. package/dist/modules/components/select/selectContainer/index.js +10 -2
  74. package/dist/modules/components/select/selectContainer/index.js.map +1 -1
  75. package/dist/modules/components/select/selectOption/index.js +5 -2
  76. package/dist/modules/components/select/selectOption/index.js.map +1 -1
  77. package/dist/modules/components/select/selectOption/styles.css +1 -1
  78. package/dist/modules/components/select/selectOptionsContainer/index.js +17 -15
  79. package/dist/modules/components/select/selectOptionsContainer/index.js.map +1 -1
  80. package/dist/modules/components/select/styles.css +1 -1
  81. package/dist/modules/hooks/useEscapeKey.js +18 -0
  82. package/dist/modules/hooks/useEscapeKey.js.map +1 -0
  83. package/dist/modules/hooks/useFocusTrap.js +44 -0
  84. package/dist/modules/hooks/useFocusTrap.js.map +1 -0
  85. package/dist/style.css +1 -1
  86. package/package.json +8 -8
@@ -2,114 +2,154 @@ import { useForm as e } from "../../hooks/useForm.js";
2
2
  import { IconRenderer as t } from "../../services/iconRenderer.js";
3
3
  import { FieldTemplate as n } from "../../services/fieldTemplate.js";
4
4
  import { SelectChevron as r } from "./selectChevron/index.js";
5
- import { SelectContainer as i } from "./selectContainer/index.js";
6
- import { SelectContent as a } from "./selectContent/index.js";
7
- import { SelectOption as o } from "./selectOption/index.js";
8
- import { SelectOptionsContainer as s } from "./selectOptionsContainer/index.js";
9
- import { SelectOverlay as ee } from "./selectOverlay/index.js";
10
- import { SelectSpinner as te } from "./selectSpinner/index.js";
11
- import { useId as c, useRef as l, useState as u } from "react";
12
- import { jsx as d, jsxs as f } from "react/jsx-runtime";
5
+ import { SelectContainer as ee } from "./selectContainer/index.js";
6
+ import { SelectContent as te } from "./selectContent/index.js";
7
+ import { SelectOption as ne } from "./selectOption/index.js";
8
+ import { SelectOptionsContainer as re } from "./selectOptionsContainer/index.js";
9
+ import { SelectOverlay as ie } from "./selectOverlay/index.js";
10
+ import { SelectSpinner as ae } from "./selectSpinner/index.js";
11
+ import { useId as i, useRef as a, useState as o } from "react";
12
+ import { jsx as s, jsxs as c } from "react/jsx-runtime";
13
13
  //#region src/components/select/index.tsx
14
- function p(p) {
15
- let { name: m, options: h, className: g = "", placeholder: _ = "Selecione...", closeOnSelect: v = !0, defaultValue: y = "", errorMessage: b, isLoading: x = !1, readOnly: S = !1, isSearchable: ne = !1, id: re, label: ie, showAsterisk: C, leftIcon: w, onSearch: T, onChange: E, onBlur: D, notFoundText: O = "Sem opções disponíveis", onFocus: k, disabled: A = !1, prefix: j, size: M = "md", value: N, variant: P = "solid", orientation: F = "vertical", unShowFieldTemplate: I = !1 } = p, { fieldErrors: L } = e(), R = l(null), ae = c(), z = re || ae, B = b || L?.[m], V = !!B, H = A || x || S, U = {
14
+ function l(l) {
15
+ let { name: u, options: d, className: f = "", placeholder: p = "Selecione...", closeOnSelect: m = !0, defaultValue: h = "", errorMessage: g, isLoading: _ = !1, readOnly: v = !1, isSearchable: y = !1, id: b, label: oe, showAsterisk: se, leftIcon: x, onSearch: S, onChange: C, onBlur: ce, notFoundText: le = "Sem opções disponíveis", onFocus: ue, disabled: de = !1, prefix: w, size: T = "md", value: E, variant: D = "solid", orientation: O = "vertical", unShowFieldTemplate: k = !1 } = l, { fieldErrors: A } = e(), j = a(null), M = a(null), N = i(), P = b || N, F = `${P}-listbox`, I = g || A?.[u], L = !!I, R = de || _ || v, z = {
16
16
  md: 20,
17
17
  lg: 20
18
- }[M], [W, G] = u(""), [K, q] = u(!1), [J, Y] = u(y), X = N || J;
19
- function Z(e) {
20
- return X === e;
18
+ }[T], [B, V] = o(""), [H, U] = o(!1), [fe, W] = o(h), [G, K] = o(-1), q = E === void 0 ? fe : E;
19
+ function J(e) {
20
+ return q === e;
21
21
  }
22
- function oe(e) {
23
- return h.find((t) => t.value === e)?.label || "";
22
+ function pe(e) {
23
+ return d.find((t) => t.value === e)?.label || "";
24
24
  }
25
- function se() {
26
- H || !R?.current || K || (q(!0), R.current.focus(), k?.());
25
+ function Y(e) {
26
+ return `${F}-option-${e.replace(/[^a-zA-Z0-9_-]/g, "-")}`;
27
27
  }
28
- function Q() {
29
- q(!1), D && R.current && R.current.blur();
28
+ function X() {
29
+ R || !j?.current || H || (U(!0), K(-1), j.current.focus(), ue?.());
30
30
  }
31
- function ce(e) {
32
- G(e), T && T(e);
31
+ function Z() {
32
+ U(!1), K(-1), ce && j.current && j.current.blur();
33
33
  }
34
- function le(e) {
35
- Z(e) ? (Y(""), E && E("")) : (Y(e), E && E(e)), v && Q();
34
+ function me(e) {
35
+ V(e), K(-1), S && S(e);
36
36
  }
37
- let $ = h.filter((e) => !!(p.onSearch || !p.isSearchable || e.label.toLowerCase().includes(W.toLowerCase())));
38
- return /* @__PURE__ */ d(n, {
39
- name: m,
40
- label: ie,
41
- showAsterisk: C,
42
- className: g,
43
- errorMessage: B,
44
- unShowFieldTemplate: I,
45
- orientation: F,
46
- children: /* @__PURE__ */ f(i, {
47
- handleContainerFocus: se,
48
- disabled: H,
49
- isError: V,
50
- isFocused: K,
51
- isLoading: x,
52
- readOnly: S,
53
- size: M,
54
- variant: P,
55
- prefixExists: !!j,
56
- id: z,
37
+ function Q(e) {
38
+ J(e) ? (W(""), C && C("")) : (W(e), C && C(e)), m && Z();
39
+ }
40
+ let $ = d.filter((e) => !!(l.onSearch || !l.isSearchable || e.label.toLowerCase().includes(B.toLowerCase())));
41
+ function he(e) {
42
+ if (R) return;
43
+ if (!H) {
44
+ (e.key === "Enter" || e.key === " " || e.key === "ArrowDown") && (e.preventDefault(), X(), e.key === "ArrowDown" && K(0));
45
+ return;
46
+ }
47
+ let t = e.target?.tagName === "INPUT", n = e.target?.tagName === "BUTTON";
48
+ switch (e.key) {
49
+ case "Escape":
50
+ e.preventDefault(), Z(), M.current?.focus();
51
+ break;
52
+ case "ArrowDown":
53
+ e.preventDefault(), K((e) => $.length === 0 ? -1 : e < 0 || e + 1 >= $.length ? 0 : e + 1);
54
+ break;
55
+ case "ArrowUp":
56
+ e.preventDefault(), K((e) => $.length === 0 ? -1 : e < 0 || e - 1 < 0 ? $.length - 1 : e - 1);
57
+ break;
58
+ case " ":
59
+ if (t || n) return;
60
+ e.preventDefault(), G >= 0 && G < $.length && Q($[G].value);
61
+ break;
62
+ case "Enter":
63
+ if (n) return;
64
+ e.preventDefault(), G >= 0 && G < $.length && Q($[G].value);
65
+ break;
66
+ default: break;
67
+ }
68
+ }
69
+ let ge = G >= 0 && G < $.length ? Y($[G].value) : void 0;
70
+ return /* @__PURE__ */ s(n, {
71
+ name: u,
72
+ label: oe,
73
+ showAsterisk: se,
74
+ className: f,
75
+ errorMessage: I,
76
+ unShowFieldTemplate: k,
77
+ orientation: O,
78
+ children: /* @__PURE__ */ c(ee, {
79
+ handleContainerFocus: X,
80
+ disabled: R,
81
+ isError: L,
82
+ isFocused: H,
83
+ isLoading: _,
84
+ readOnly: v,
85
+ size: T,
86
+ variant: D,
87
+ prefixExists: !!w,
88
+ id: P,
89
+ containerRef: M,
90
+ onContainerKeyDown: he,
91
+ tabIndex: R ? -1 : 0,
92
+ ariaControls: F,
93
+ ariaActiveDescendant: ge,
57
94
  children: [
58
- /* @__PURE__ */ d("input", {
59
- ref: R,
60
- name: m,
61
- value: X,
95
+ /* @__PURE__ */ s("input", {
96
+ ref: j,
97
+ name: u,
98
+ value: q,
62
99
  type: "hidden"
63
100
  }),
64
- /* @__PURE__ */ d(t, {
65
- iconSize: U,
66
- icon: j,
101
+ /* @__PURE__ */ s(t, {
102
+ iconSize: z,
103
+ icon: w,
67
104
  className: "prefix"
68
105
  }),
69
- w && /* @__PURE__ */ d(w, {
70
- size: U,
106
+ x && /* @__PURE__ */ s(x, {
107
+ size: z,
71
108
  strokeWidth: 2.5
72
109
  }),
73
- /* @__PURE__ */ f(a, {
74
- size: M,
75
- children: [X !== "" && /* @__PURE__ */ d("p", {
110
+ /* @__PURE__ */ c(te, {
111
+ size: T,
112
+ children: [q !== "" && /* @__PURE__ */ s("p", {
76
113
  className: "hasValue",
77
- children: oe(X)
78
- }), X === "" && /* @__PURE__ */ d("p", { children: _ })]
114
+ children: pe(q)
115
+ }), q === "" && /* @__PURE__ */ s("p", { children: p })]
79
116
  }),
80
- /* @__PURE__ */ f(s, {
81
- isFocused: K,
82
- isSearchable: ne,
83
- search: W,
84
- onSearch: ce,
85
- children: [$.map(({ label: e, value: t }) => /* @__PURE__ */ d(o, {
117
+ /* @__PURE__ */ c(re, {
118
+ id: F,
119
+ isFocused: H,
120
+ isSearchable: y,
121
+ search: B,
122
+ onSearch: me,
123
+ children: [$.map(({ label: e, value: t }, n) => /* @__PURE__ */ s(ne, {
124
+ id: Y(t),
86
125
  label: e,
87
126
  value: t,
88
- size: M,
89
- handleChangeValue: le,
90
- optionHasSelected: Z
91
- }, t)), $.length <= 0 && /* @__PURE__ */ d("p", { children: O })]
127
+ size: T,
128
+ isHighlighted: n === G,
129
+ handleChangeValue: Q,
130
+ optionHasSelected: J
131
+ }, t)), $.length <= 0 && /* @__PURE__ */ s("p", { children: le })]
92
132
  }),
93
- /* @__PURE__ */ d(r, {
94
- disabled: H,
95
- isFocused: K,
96
- readOnly: S,
97
- iconSize: U,
98
- isLoading: x
133
+ /* @__PURE__ */ s(r, {
134
+ disabled: R,
135
+ isFocused: H,
136
+ readOnly: v,
137
+ iconSize: z,
138
+ isLoading: _
99
139
  }),
100
- /* @__PURE__ */ d(te, {
101
- iconSize: U,
102
- isLoading: x
140
+ /* @__PURE__ */ s(ae, {
141
+ iconSize: z,
142
+ isLoading: _
103
143
  }),
104
- /* @__PURE__ */ d(ee, {
105
- handleBlur: Q,
106
- isFocused: K
144
+ /* @__PURE__ */ s(ie, {
145
+ handleBlur: Z,
146
+ isFocused: H
107
147
  })
108
148
  ]
109
149
  })
110
150
  });
111
151
  }
112
152
  //#endregion
113
- export { p as Select };
153
+ export { l as Select };
114
154
 
115
155
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../src/components/select/index.tsx"],"sourcesContent":["import type { LucideIcon } from \"lucide-react\";\nimport { type FocusEvent, useId, useRef, useState } from \"react\";\n\nimport { useForm } from \"../../hooks/useForm\";\nimport { FieldTemplate } from \"../../services/fieldTemplate\";\nimport { IconRenderer } from \"../../services/iconRenderer\";\n\nimport { SelectChevron } from \"./selectChevron\";\nimport { SelectContainer } from \"./selectContainer\";\nimport { SelectContent } from \"./selectContent\";\nimport { SelectOption } from \"./selectOption\";\nimport { SelectOptionsContainer } from \"./selectOptionsContainer\";\nimport { SelectOverlay } from \"./selectOverlay\";\nimport { SelectSpinner } from \"./selectSpinner\";\n\ntype SelectProps = {\n\t/** Field name for form submission. Required. */\n\tname: string;\n\t/** Array of selectable options. Required. */\n\toptions: { label: string; value: string }[];\n\t/** Optional HTML id for the underlying hidden input. */\n\tid?: string;\n\t/** Controlled selected value. */\n\tvalue?: string;\n\t/** Uncontrolled default selected value. @default \"\" */\n\tdefaultValue?: string;\n\t/** Displays an asterisk on the label to signal a required field. */\n\tshowAsterisk?: boolean;\n\t/** Optional label text displayed above the select. */\n\tlabel?: string;\n\t/** Validation error message displayed below the select. */\n\terrorMessage?: string;\n\t/** Placeholder text shown when no option is selected. @default \"Selecione...\" */\n\tplaceholder?: string;\n\t/** Text shown when no options match the search query. @default \"Sem opções disponíveis\" */\n\tnotFoundText?: string;\n\t/** Additional CSS class applied to the wrapper element. */\n\tclassName?: string;\n\t/** Disables all interactions. @default false */\n\tdisabled?: boolean;\n\t/** Prevents value changes while keeping the current value visible. @default false */\n\treadOnly?: boolean;\n\t/** Shows a loading spinner and disables interactions. @default false */\n\tisLoading?: boolean;\n\t/** Enables search/filter within the dropdown. @default false */\n\tisSearchable?: boolean;\n\t/** Closes the dropdown after an option is selected. @default true */\n\tcloseOnSelect?: boolean;\n\t/** Callback fired when the search query changes. Use for async option loading. */\n\tonSearch?: (value: string) => void;\n\t/** Callback fired when the selected value changes. */\n\tonChange?: (value: string) => void;\n\t/** Callback fired when the select gains focus. */\n\tonFocus?: () => void;\n\t/** Callback fired when the select loses focus. */\n\tonBlur?: (e: FocusEvent<HTMLDivElement>) => void;\n\t/**\n\t * Select size.\n\t * @default \"md\"\n\t */\n\tsize?: \"md\" | \"lg\";\n\t/**\n\t * Visual style variant.\n\t * - `solid`: filled background.\n\t * - `outline`: bordered, transparent background.\n\t * - `underline`: bottom border only.\n\t * @default \"solid\"\n\t */\n\tvariant?: \"solid\" | \"outline\" | \"underline\";\n\t/** Text or icon rendered at the far left, outside the select area. */\n\tprefix?: string | LucideIcon;\n\t/** Lucide icon rendered inside the select on the left. */\n\tleftIcon?: LucideIcon;\n\t/** Maximum height (in px) of the options dropdown. */\n\toptionMaxHeight?: number;\n\t/** When true, skips `FieldTemplate` wrapper (label and error text). @default false */\n\tunShowFieldTemplate?: boolean;\n\t/**\n\t * Layout direction forwarded to `FieldTemplate`.\n\t * @default \"horizontal\"\n\t */\n\torientation?: \"horizontal\" | \"vertical\" | \"horizontalReverse\";\n};\n\n/**\n * Select, single-option dropdown with optional search, label, validation, and form integration.\n *\n * Integrates with `useForm` to display validation errors by field name.\n *\n * @param props.name - Field name for form submission. Required.\n * @param props.options - Array of selectable options (`{ label, value }`). Required.\n * @param props.value - Controlled selected value.\n * @param props.defaultValue - Uncontrolled default value. Default: \"\"\n * @param props.label - Label text displayed above the select.\n * @param props.placeholder - Placeholder shown when nothing is selected. Default: \"Selecione...\"\n * @param props.errorMessage - Validation error message.\n * @param props.isSearchable - Enables search/filter within the dropdown. Default: false\n * @param props.isLoading - Shows a loading spinner and disables interactions. Default: false\n * @param props.closeOnSelect - Closes the dropdown after selecting. Default: true\n * @param props.onChange - Callback fired when the selected value changes.\n * @param props.onSearch - Callback fired when the search query changes.\n * @param props.size - Select size (`md` | `lg`). Default: \"md\"\n * @param props.variant - Visual style variant. Default: \"solid\"\n * @param props.orientation - Layout direction. Default: \"horizontal\"\n * @param props.unShowFieldTemplate - Skips wrapper, label, and error rendering. Default: false\n *\n * @returns Select JSX element wrapped in `FieldTemplate`.\n *\n * @example\n * ```tsx\n * // Basic\n * <Select\n * name=\"category\"\n * options={[\n * { label: \"Technology\", value: \"tech\" },\n * { label: \"Design\", value: \"design\" },\n * ]}\n * />\n *\n * // With label, validation, and searchable\n * <Select\n * name=\"country\"\n * label=\"Country\"\n * showAsterisk\n * isSearchable\n * options={countryOptions}\n * errorMessage={errors.country}\n * notFoundText=\"No countries found\"\n * />\n *\n * // Controlled with async search\n * <Select\n * name=\"tag\"\n * label=\"Tag\"\n * value={selectedTag}\n * onChange={setSelectedTag}\n * onSearch={fetchTagOptions}\n * isLoading={isLoadingTags}\n * options={tagOptions}\n * />\n * ```\n */\n\nfunction Select(props: SelectProps) {\n\tconst {\n\t\tname,\n\t\toptions,\n\t\tclassName: wrapperClassName = \"\",\n\t\tplaceholder = \"Selecione...\",\n\t\tcloseOnSelect = true,\n\t\tdefaultValue = \"\",\n\t\terrorMessage: baseErrorMessage,\n\t\tisLoading = false,\n\t\treadOnly = false,\n\t\tisSearchable = false,\n\t\tid,\n\t\tlabel,\n\t\tshowAsterisk,\n\t\tleftIcon: LeftIcon,\n\t\tonSearch,\n\t\tonChange,\n\t\tonBlur,\n\t\tnotFoundText = \"Sem opções disponíveis\",\n\t\tonFocus,\n\t\tdisabled: baseDisabled = false,\n\t\tprefix,\n\t\tsize = \"md\",\n\t\tvalue,\n\t\tvariant = \"solid\",\n\t\torientation = \"vertical\",\n\t\tunShowFieldTemplate = false,\n\t} = props;\n\n\tconst { fieldErrors } = useForm();\n\n\tconst selectRef = useRef<HTMLInputElement>(null);\n\tconst generatedId = useId();\n\tconst selectId = id || generatedId;\n\n\tconst errorMessage = baseErrorMessage || fieldErrors?.[name];\n\tconst isError = !!errorMessage;\n\tconst disabled = baseDisabled || isLoading || readOnly;\n\n\tconst iconSizes = { md: 20, lg: 20 };\n\tconst iconSize = iconSizes[size];\n\n\tconst [search, setSearch] = useState(\"\");\n\tconst [isFocused, setIsFocused] = useState(false);\n\tconst [selectedOption, setSelectedOption] = useState(defaultValue);\n\n\tconst forceSelectedOptions = value || selectedOption;\n\n\tfunction optionHasSelected(value: string) {\n\t\treturn forceSelectedOptions === value;\n\t}\n\n\tfunction getOptionLabel(value: string) {\n\t\tconst option = options.find((option) => option.value === value);\n\t\treturn option?.label || \"\";\n\t}\n\n\tfunction handleContainerFocus() {\n\t\tif (disabled || !selectRef?.current || isFocused) return;\n\t\tsetIsFocused(true);\n\t\tselectRef.current.focus();\n\t\tonFocus?.();\n\t}\n\n\tfunction handleBlur() {\n\t\tsetIsFocused(false);\n\t\tif (onBlur && selectRef.current) selectRef.current.blur();\n\t}\n\n\tfunction handleSearch(value: string) {\n\t\tsetSearch(value);\n\t\tif (onSearch) onSearch(value);\n\t}\n\n\tfunction handleChangeValue(value: string) {\n\t\tif (optionHasSelected(value)) {\n\t\t\tsetSelectedOption(\"\");\n\t\t\tif (onChange) onChange(\"\");\n\t\t} else {\n\t\t\tsetSelectedOption(value);\n\t\t\tif (onChange) onChange(value);\n\t\t}\n\n\t\tif (closeOnSelect) handleBlur();\n\t}\n\n\tconst mappedOptions = options.filter((option) => {\n\t\tif (props.onSearch) return true;\n\t\tif (!props.isSearchable) return true;\n\t\tif (option.label.toLowerCase().includes(search.toLowerCase())) return true;\n\t\treturn false;\n\t});\n\n\treturn (\n\t\t<FieldTemplate\n\t\t\tname={name}\n\t\t\tlabel={label}\n\t\t\tshowAsterisk={showAsterisk}\n\t\t\tclassName={wrapperClassName}\n\t\t\terrorMessage={errorMessage}\n\t\t\tunShowFieldTemplate={unShowFieldTemplate}\n\t\t\torientation={orientation}\n\t\t>\n\t\t\t<SelectContainer\n\t\t\t\thandleContainerFocus={handleContainerFocus}\n\t\t\t\tdisabled={disabled}\n\t\t\t\tisError={isError}\n\t\t\t\tisFocused={isFocused}\n\t\t\t\tisLoading={isLoading}\n\t\t\t\treadOnly={readOnly}\n\t\t\t\tsize={size}\n\t\t\t\tvariant={variant}\n\t\t\t\tprefixExists={!!prefix}\n\t\t\t\tid={selectId}\n\t\t\t>\n\t\t\t\t<input\n\t\t\t\t\tref={selectRef}\n\t\t\t\t\tname={name}\n\t\t\t\t\tvalue={forceSelectedOptions}\n\t\t\t\t\ttype=\"hidden\"\n\t\t\t\t/>\n\n\t\t\t\t<IconRenderer iconSize={iconSize} icon={prefix} className=\"prefix\" />\n\n\t\t\t\t{LeftIcon && <LeftIcon size={iconSize} strokeWidth={2.5} />}\n\n\t\t\t\t<SelectContent size={size}>\n\t\t\t\t\t{forceSelectedOptions !== \"\" && (\n\t\t\t\t\t\t<p className=\"hasValue\">{getOptionLabel(forceSelectedOptions)}</p>\n\t\t\t\t\t)}\n\t\t\t\t\t{forceSelectedOptions === \"\" && <p>{placeholder}</p>}\n\t\t\t\t</SelectContent>\n\n\t\t\t\t<SelectOptionsContainer\n\t\t\t\t\tisFocused={isFocused}\n\t\t\t\t\tisSearchable={isSearchable}\n\t\t\t\t\tsearch={search}\n\t\t\t\t\tonSearch={handleSearch}\n\t\t\t\t>\n\t\t\t\t\t{mappedOptions.map(({ label, value }) => (\n\t\t\t\t\t\t<SelectOption\n\t\t\t\t\t\t\tkey={value}\n\t\t\t\t\t\t\tlabel={label}\n\t\t\t\t\t\t\tvalue={value}\n\t\t\t\t\t\t\tsize={size}\n\t\t\t\t\t\t\thandleChangeValue={handleChangeValue}\n\t\t\t\t\t\t\toptionHasSelected={optionHasSelected}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\n\t\t\t\t\t{mappedOptions.length <= 0 && <p>{notFoundText}</p>}\n\t\t\t\t</SelectOptionsContainer>\n\n\t\t\t\t<SelectChevron\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tisFocused={isFocused}\n\t\t\t\t\treadOnly={readOnly}\n\t\t\t\t\ticonSize={iconSize}\n\t\t\t\t\tisLoading={isLoading}\n\t\t\t\t/>\n\n\t\t\t\t<SelectSpinner iconSize={iconSize} isLoading={isLoading} />\n\t\t\t\t<SelectOverlay handleBlur={handleBlur} isFocused={isFocused} />\n\t\t\t</SelectContainer>\n\t\t</FieldTemplate>\n\t);\n}\n\nexport { Select };\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../src/components/select/index.tsx"],"sourcesContent":["import type { LucideIcon } from \"lucide-react\";\nimport {\n\ttype FocusEvent,\n\ttype KeyboardEvent,\n\tuseId,\n\tuseRef,\n\tuseState,\n} from \"react\";\n\nimport { useForm } from \"../../hooks/useForm\";\nimport { FieldTemplate } from \"../../services/fieldTemplate\";\nimport { IconRenderer } from \"../../services/iconRenderer\";\n\nimport { SelectChevron } from \"./selectChevron\";\nimport { SelectContainer } from \"./selectContainer\";\nimport { SelectContent } from \"./selectContent\";\nimport { SelectOption } from \"./selectOption\";\nimport { SelectOptionsContainer } from \"./selectOptionsContainer\";\nimport { SelectOverlay } from \"./selectOverlay\";\nimport { SelectSpinner } from \"./selectSpinner\";\n\ntype SelectProps = {\n\t/** Field name for form submission. Required. */\n\tname: string;\n\t/** Array of selectable options. Required. */\n\toptions: { label: string; value: string }[];\n\t/** Optional HTML id for the underlying hidden input. */\n\tid?: string;\n\t/** Controlled selected value. */\n\tvalue?: string;\n\t/** Uncontrolled default selected value. @default \"\" */\n\tdefaultValue?: string;\n\t/** Displays an asterisk on the label to signal a required field. */\n\tshowAsterisk?: boolean;\n\t/** Optional label text displayed above the select. */\n\tlabel?: string;\n\t/** Validation error message displayed below the select. */\n\terrorMessage?: string;\n\t/** Placeholder text shown when no option is selected. @default \"Selecione...\" */\n\tplaceholder?: string;\n\t/** Text shown when no options match the search query. @default \"Sem opções disponíveis\" */\n\tnotFoundText?: string;\n\t/** Additional CSS class applied to the wrapper element. */\n\tclassName?: string;\n\t/** Disables all interactions. @default false */\n\tdisabled?: boolean;\n\t/** Prevents value changes while keeping the current value visible. @default false */\n\treadOnly?: boolean;\n\t/** Shows a loading spinner and disables interactions. @default false */\n\tisLoading?: boolean;\n\t/** Enables search/filter within the dropdown. @default false */\n\tisSearchable?: boolean;\n\t/** Closes the dropdown after an option is selected. @default true */\n\tcloseOnSelect?: boolean;\n\t/** Callback fired when the search query changes. Use for async option loading. */\n\tonSearch?: (value: string) => void;\n\t/** Callback fired when the selected value changes. */\n\tonChange?: (value: string) => void;\n\t/** Callback fired when the select gains focus. */\n\tonFocus?: () => void;\n\t/** Callback fired when the select loses focus. */\n\tonBlur?: (e: FocusEvent<HTMLDivElement>) => void;\n\t/**\n\t * Select size.\n\t * @default \"md\"\n\t */\n\tsize?: \"md\" | \"lg\";\n\t/**\n\t * Visual style variant.\n\t * - `solid`: filled background.\n\t * - `outline`: bordered, transparent background.\n\t * - `underline`: bottom border only.\n\t * @default \"solid\"\n\t */\n\tvariant?: \"solid\" | \"outline\" | \"underline\";\n\t/** Text or icon rendered at the far left, outside the select area. */\n\tprefix?: string | LucideIcon;\n\t/** Lucide icon rendered inside the select on the left. */\n\tleftIcon?: LucideIcon;\n\t/** Maximum height (in px) of the options dropdown. */\n\toptionMaxHeight?: number;\n\t/** When true, skips `FieldTemplate` wrapper (label and error text). @default false */\n\tunShowFieldTemplate?: boolean;\n\t/**\n\t * Layout direction forwarded to `FieldTemplate`.\n\t * @default \"horizontal\"\n\t */\n\torientation?: \"horizontal\" | \"vertical\" | \"horizontalReverse\";\n};\n\n/**\n * Select, single-option dropdown with optional search, label, validation, and form integration.\n *\n * Integrates with `useForm` to display validation errors by field name.\n *\n * @param props.name - Field name for form submission. Required.\n * @param props.options - Array of selectable options (`{ label, value }`). Required.\n * @param props.value - Controlled selected value.\n * @param props.defaultValue - Uncontrolled default value. Default: \"\"\n * @param props.label - Label text displayed above the select.\n * @param props.placeholder - Placeholder shown when nothing is selected. Default: \"Selecione...\"\n * @param props.errorMessage - Validation error message.\n * @param props.isSearchable - Enables search/filter within the dropdown. Default: false\n * @param props.isLoading - Shows a loading spinner and disables interactions. Default: false\n * @param props.closeOnSelect - Closes the dropdown after selecting. Default: true\n * @param props.onChange - Callback fired when the selected value changes.\n * @param props.onSearch - Callback fired when the search query changes.\n * @param props.size - Select size (`md` | `lg`). Default: \"md\"\n * @param props.variant - Visual style variant. Default: \"solid\"\n * @param props.orientation - Layout direction. Default: \"vertical\"\n * @param props.unShowFieldTemplate - Skips wrapper, label, and error rendering. Default: false\n *\n * @returns Select JSX element wrapped in `FieldTemplate`.\n *\n * @example\n * ```tsx\n * // Basic\n * <Select\n * name=\"category\"\n * options={[\n * { label: \"Technology\", value: \"tech\" },\n * { label: \"Design\", value: \"design\" },\n * ]}\n * />\n *\n * // With label, validation, and searchable\n * <Select\n * name=\"country\"\n * label=\"Country\"\n * showAsterisk\n * isSearchable\n * options={countryOptions}\n * errorMessage={errors.country}\n * notFoundText=\"No countries found\"\n * />\n *\n * // Controlled with async search\n * <Select\n * name=\"tag\"\n * label=\"Tag\"\n * value={selectedTag}\n * onChange={setSelectedTag}\n * onSearch={fetchTagOptions}\n * isLoading={isLoadingTags}\n * options={tagOptions}\n * />\n * ```\n */\n\nfunction Select(props: SelectProps) {\n\tconst {\n\t\tname,\n\t\toptions,\n\t\tclassName: wrapperClassName = \"\",\n\t\tplaceholder = \"Selecione...\",\n\t\tcloseOnSelect = true,\n\t\tdefaultValue = \"\",\n\t\terrorMessage: baseErrorMessage,\n\t\tisLoading = false,\n\t\treadOnly = false,\n\t\tisSearchable = false,\n\t\tid,\n\t\tlabel,\n\t\tshowAsterisk,\n\t\tleftIcon: LeftIcon,\n\t\tonSearch,\n\t\tonChange,\n\t\tonBlur,\n\t\tnotFoundText = \"Sem opções disponíveis\",\n\t\tonFocus,\n\t\tdisabled: baseDisabled = false,\n\t\tprefix,\n\t\tsize = \"md\",\n\t\tvalue,\n\t\tvariant = \"solid\",\n\t\torientation = \"vertical\",\n\t\tunShowFieldTemplate = false,\n\t} = props;\n\n\tconst { fieldErrors } = useForm();\n\n\tconst selectRef = useRef<HTMLInputElement>(null);\n\tconst containerRef = useRef<HTMLDivElement>(null);\n\tconst generatedId = useId();\n\tconst selectId = id || generatedId;\n\tconst listboxId = `${selectId}-listbox`;\n\n\tconst errorMessage = baseErrorMessage || fieldErrors?.[name];\n\tconst isError = !!errorMessage;\n\tconst disabled = baseDisabled || isLoading || readOnly;\n\n\tconst iconSizes = { md: 20, lg: 20 };\n\tconst iconSize = iconSizes[size];\n\n\tconst [search, setSearch] = useState(\"\");\n\tconst [isFocused, setIsFocused] = useState(false);\n\tconst [selectedOption, setSelectedOption] = useState(defaultValue);\n\tconst [highlightedIndex, setHighlightedIndex] = useState(-1);\n\n\tconst forceSelectedOptions = value !== undefined ? value : selectedOption;\n\n\tfunction optionHasSelected(value: string) {\n\t\treturn forceSelectedOptions === value;\n\t}\n\n\tfunction getOptionLabel(value: string) {\n\t\tconst option = options.find((option) => option.value === value);\n\t\treturn option?.label || \"\";\n\t}\n\n\tfunction getOptionId(value: string) {\n\t\treturn `${listboxId}-option-${value.replace(/[^a-zA-Z0-9_-]/g, \"-\")}`;\n\t}\n\n\tfunction handleContainerFocus() {\n\t\tif (disabled || !selectRef?.current || isFocused) return;\n\t\tsetIsFocused(true);\n\t\tsetHighlightedIndex(-1);\n\t\tselectRef.current.focus();\n\t\tonFocus?.();\n\t}\n\n\tfunction handleBlur() {\n\t\tsetIsFocused(false);\n\t\tsetHighlightedIndex(-1);\n\t\tif (onBlur && selectRef.current) selectRef.current.blur();\n\t}\n\n\tfunction handleSearch(value: string) {\n\t\tsetSearch(value);\n\t\t// The visible option list is about to change, so drop the current\n\t\t// highlight instead of letting it point at a filtered-out option.\n\t\tsetHighlightedIndex(-1);\n\t\tif (onSearch) onSearch(value);\n\t}\n\n\tfunction handleChangeValue(value: string) {\n\t\tif (optionHasSelected(value)) {\n\t\t\tsetSelectedOption(\"\");\n\t\t\tif (onChange) onChange(\"\");\n\t\t} else {\n\t\t\tsetSelectedOption(value);\n\t\t\tif (onChange) onChange(value);\n\t\t}\n\n\t\tif (closeOnSelect) handleBlur();\n\t}\n\n\tconst mappedOptions = options.filter((option) => {\n\t\tif (props.onSearch) return true;\n\t\tif (!props.isSearchable) return true;\n\t\tif (option.label.toLowerCase().includes(search.toLowerCase())) return true;\n\t\treturn false;\n\t});\n\n\tfunction handleContainerKeyDown(e: KeyboardEvent<HTMLDivElement>) {\n\t\tif (disabled) return;\n\n\t\tif (!isFocused) {\n\t\t\tif (e.key === \"Enter\" || e.key === \" \" || e.key === \"ArrowDown\") {\n\t\t\t\te.preventDefault();\n\t\t\t\thandleContainerFocus();\n\t\t\t\tif (e.key === \"ArrowDown\") setHighlightedIndex(0);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tconst isTypingTarget = (e.target as HTMLElement)?.tagName === \"INPUT\";\n\t\t// When focus has moved onto an option/button directly (e.g. via Tab),\n\t\t// let that element handle its own native Enter/Space activation instead\n\t\t// of double-handling it here through the highlighted-index shortcut.\n\t\tconst isButtonTarget = (e.target as HTMLElement)?.tagName === \"BUTTON\";\n\n\t\tswitch (e.key) {\n\t\t\tcase \"Escape\":\n\t\t\t\te.preventDefault();\n\t\t\t\thandleBlur();\n\t\t\t\tcontainerRef.current?.focus();\n\t\t\t\tbreak;\n\t\t\tcase \"ArrowDown\":\n\t\t\t\te.preventDefault();\n\t\t\t\tsetHighlightedIndex((prev) => {\n\t\t\t\t\tif (mappedOptions.length === 0) return -1;\n\t\t\t\t\tif (prev < 0) return 0;\n\t\t\t\t\treturn prev + 1 >= mappedOptions.length ? 0 : prev + 1;\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase \"ArrowUp\":\n\t\t\t\te.preventDefault();\n\t\t\t\tsetHighlightedIndex((prev) => {\n\t\t\t\t\tif (mappedOptions.length === 0) return -1;\n\t\t\t\t\tif (prev < 0) return mappedOptions.length - 1;\n\t\t\t\t\treturn prev - 1 < 0 ? mappedOptions.length - 1 : prev - 1;\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase \" \":\n\t\t\t\tif (isTypingTarget || isButtonTarget) return;\n\t\t\t\te.preventDefault();\n\t\t\t\tif (highlightedIndex >= 0 && highlightedIndex < mappedOptions.length) {\n\t\t\t\t\thandleChangeValue(mappedOptions[highlightedIndex].value);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"Enter\":\n\t\t\t\tif (isButtonTarget) return;\n\t\t\t\te.preventDefault();\n\t\t\t\tif (highlightedIndex >= 0 && highlightedIndex < mappedOptions.length) {\n\t\t\t\t\thandleChangeValue(mappedOptions[highlightedIndex].value);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tconst activeDescendantId =\n\t\thighlightedIndex >= 0 && highlightedIndex < mappedOptions.length\n\t\t\t? getOptionId(mappedOptions[highlightedIndex].value)\n\t\t\t: undefined;\n\n\treturn (\n\t\t<FieldTemplate\n\t\t\tname={name}\n\t\t\tlabel={label}\n\t\t\tshowAsterisk={showAsterisk}\n\t\t\tclassName={wrapperClassName}\n\t\t\terrorMessage={errorMessage}\n\t\t\tunShowFieldTemplate={unShowFieldTemplate}\n\t\t\torientation={orientation}\n\t\t>\n\t\t\t<SelectContainer\n\t\t\t\thandleContainerFocus={handleContainerFocus}\n\t\t\t\tdisabled={disabled}\n\t\t\t\tisError={isError}\n\t\t\t\tisFocused={isFocused}\n\t\t\t\tisLoading={isLoading}\n\t\t\t\treadOnly={readOnly}\n\t\t\t\tsize={size}\n\t\t\t\tvariant={variant}\n\t\t\t\tprefixExists={!!prefix}\n\t\t\t\tid={selectId}\n\t\t\t\tcontainerRef={containerRef}\n\t\t\t\tonContainerKeyDown={handleContainerKeyDown}\n\t\t\t\ttabIndex={disabled ? -1 : 0}\n\t\t\t\tariaControls={listboxId}\n\t\t\t\tariaActiveDescendant={activeDescendantId}\n\t\t\t>\n\t\t\t\t<input\n\t\t\t\t\tref={selectRef}\n\t\t\t\t\tname={name}\n\t\t\t\t\tvalue={forceSelectedOptions}\n\t\t\t\t\ttype=\"hidden\"\n\t\t\t\t/>\n\n\t\t\t\t<IconRenderer iconSize={iconSize} icon={prefix} className=\"prefix\" />\n\n\t\t\t\t{LeftIcon && <LeftIcon size={iconSize} strokeWidth={2.5} />}\n\n\t\t\t\t<SelectContent size={size}>\n\t\t\t\t\t{forceSelectedOptions !== \"\" && (\n\t\t\t\t\t\t<p className=\"hasValue\">{getOptionLabel(forceSelectedOptions)}</p>\n\t\t\t\t\t)}\n\t\t\t\t\t{forceSelectedOptions === \"\" && <p>{placeholder}</p>}\n\t\t\t\t</SelectContent>\n\n\t\t\t\t<SelectOptionsContainer\n\t\t\t\t\tid={listboxId}\n\t\t\t\t\tisFocused={isFocused}\n\t\t\t\t\tisSearchable={isSearchable}\n\t\t\t\t\tsearch={search}\n\t\t\t\t\tonSearch={handleSearch}\n\t\t\t\t>\n\t\t\t\t\t{mappedOptions.map(({ label, value }, index) => (\n\t\t\t\t\t\t<SelectOption\n\t\t\t\t\t\t\tkey={value}\n\t\t\t\t\t\t\tid={getOptionId(value)}\n\t\t\t\t\t\t\tlabel={label}\n\t\t\t\t\t\t\tvalue={value}\n\t\t\t\t\t\t\tsize={size}\n\t\t\t\t\t\t\tisHighlighted={index === highlightedIndex}\n\t\t\t\t\t\t\thandleChangeValue={handleChangeValue}\n\t\t\t\t\t\t\toptionHasSelected={optionHasSelected}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\n\t\t\t\t\t{mappedOptions.length <= 0 && <p>{notFoundText}</p>}\n\t\t\t\t</SelectOptionsContainer>\n\n\t\t\t\t<SelectChevron\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tisFocused={isFocused}\n\t\t\t\t\treadOnly={readOnly}\n\t\t\t\t\ticonSize={iconSize}\n\t\t\t\t\tisLoading={isLoading}\n\t\t\t\t/>\n\n\t\t\t\t<SelectSpinner iconSize={iconSize} isLoading={isLoading} />\n\t\t\t\t<SelectOverlay handleBlur={handleBlur} isFocused={isFocused} />\n\t\t\t</SelectContainer>\n\t\t</FieldTemplate>\n\t);\n}\n\nexport { Select };\n"],"mappings":"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"}
@@ -2,11 +2,19 @@
2
2
  import { jsx as e } from "react/jsx-runtime";
3
3
  //#region src/components/select/selectContainer/index.tsx
4
4
  function t(t) {
5
- let { children: n, handleContainerFocus: r, disabled: i, isError: a, isLoading: o, isFocused: s, className: c, readOnly: l, variant: u, size: d, id: f, prefixExists: p } = t;
6
- return /* @__PURE__ */ e("section", {
5
+ let { children: n, handleContainerFocus: r, disabled: i, isError: a, isLoading: o, isFocused: s, className: c, readOnly: l, variant: u, size: d, id: f, prefixExists: p, containerRef: m, onContainerKeyDown: h, tabIndex: g, ariaControls: _, ariaActiveDescendant: v } = t;
6
+ return /* @__PURE__ */ e("div", {
7
+ ref: m,
7
8
  id: f,
9
+ tabIndex: g,
10
+ role: "combobox",
11
+ "aria-haspopup": "listbox",
12
+ "aria-expanded": s,
13
+ "aria-controls": _,
14
+ "aria-activedescendant": v,
8
15
  className: `arkynSelectContainer ${p ? "hasPrefix" : ""} ${u} ${d} ${i || l || o ? "opacity" : ""} ${a ? "errored" : ""} ${s ? "focused" : ""} ${c}`,
9
16
  onClick: r,
17
+ onKeyDown: h,
10
18
  children: n
11
19
  });
12
20
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../../src/components/select/selectContainer/index.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport \"./styles.css\";\n\ntype SelectContainerProps = {\n\tchildren: ReactNode;\n\thandleContainerFocus: () => void;\n\tprefixExists: boolean;\n\tisError: boolean;\n\tdisabled: boolean;\n\treadOnly: boolean;\n\tisLoading: boolean;\n\tisFocused: boolean;\n\tclassName?: string;\n\tid: string;\n\tvariant: \"solid\" | \"outline\" | \"underline\";\n\tsize: \"md\" | \"lg\";\n};\n\nfunction SelectContainer(props: SelectContainerProps) {\n\tconst {\n\t\tchildren,\n\t\thandleContainerFocus,\n\t\tdisabled,\n\t\tisError,\n\t\tisLoading,\n\t\tisFocused,\n\t\tclassName,\n\t\treadOnly,\n\t\tvariant,\n\t\tsize,\n\t\tid,\n\t\tprefixExists,\n\t} = props;\n\n\tconst hasPrefix = prefixExists ? \"hasPrefix\" : \"\";\n\tconst errored = isError ? \"errored\" : \"\";\n\tconst opacity = disabled || readOnly || isLoading ? \"opacity\" : \"\";\n\tconst focused = isFocused ? \"focused\" : \"\";\n\n\treturn (\n\t\t<section\n\t\t\tid={id}\n\t\t\tclassName={`arkynSelectContainer ${hasPrefix} ${variant} ${size} ${opacity} ${errored} ${focused} ${className}`}\n\t\t\tonClick={handleContainerFocus}\n\t\t>\n\t\t\t{children}\n\t\t</section>\n\t);\n}\n\nexport { SelectContainer };\n"],"mappings":";;;AAkBA,SAAS,EAAgB,GAA6B;CACrD,IAAM,EACL,aACA,yBACA,aACA,YACA,cACA,cACA,cACA,aACA,YACA,SACA,OACA,oBACG;CAOJ,OACC,kBAAC,WAAD;EACK;EACJ,WAAW,wBARK,IAAe,cAAc,GAQA,GAAG,EAAQ,GAAG,EAAK,GANlD,KAAY,KAAY,IAAY,YAAY,GAMa,GAP7D,IAAU,YAAY,GAOkD,GALxE,IAAY,YAAY,GAK2D,GAAG;EACpG,SAAS;EAER;CACO,CAAA;AAEX"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../../src/components/select/selectContainer/index.tsx"],"sourcesContent":["import type { KeyboardEvent, ReactNode, RefObject } from \"react\";\nimport \"./styles.css\";\n\ntype SelectContainerProps = {\n\tchildren: ReactNode;\n\thandleContainerFocus: () => void;\n\tprefixExists: boolean;\n\tisError: boolean;\n\tdisabled: boolean;\n\treadOnly: boolean;\n\tisLoading: boolean;\n\tisFocused: boolean;\n\tclassName?: string;\n\tid: string;\n\tvariant: \"solid\" | \"outline\" | \"underline\";\n\tsize: \"md\" | \"lg\";\n\tcontainerRef?: RefObject<HTMLDivElement | null>;\n\tonContainerKeyDown?: (e: KeyboardEvent<HTMLDivElement>) => void;\n\ttabIndex?: number;\n\tariaControls?: string;\n\tariaActiveDescendant?: string;\n};\n\nfunction SelectContainer(props: SelectContainerProps) {\n\tconst {\n\t\tchildren,\n\t\thandleContainerFocus,\n\t\tdisabled,\n\t\tisError,\n\t\tisLoading,\n\t\tisFocused,\n\t\tclassName,\n\t\treadOnly,\n\t\tvariant,\n\t\tsize,\n\t\tid,\n\t\tprefixExists,\n\t\tcontainerRef,\n\t\tonContainerKeyDown,\n\t\ttabIndex,\n\t\tariaControls,\n\t\tariaActiveDescendant,\n\t} = props;\n\n\tconst hasPrefix = prefixExists ? \"hasPrefix\" : \"\";\n\tconst errored = isError ? \"errored\" : \"\";\n\tconst opacity = disabled || readOnly || isLoading ? \"opacity\" : \"\";\n\tconst focused = isFocused ? \"focused\" : \"\";\n\n\treturn (\n\t\t<div\n\t\t\tref={containerRef}\n\t\t\tid={id}\n\t\t\ttabIndex={tabIndex}\n\t\t\trole=\"combobox\"\n\t\t\taria-haspopup=\"listbox\"\n\t\t\taria-expanded={isFocused}\n\t\t\taria-controls={ariaControls}\n\t\t\taria-activedescendant={ariaActiveDescendant}\n\t\t\tclassName={`arkynSelectContainer ${hasPrefix} ${variant} ${size} ${opacity} ${errored} ${focused} ${className}`}\n\t\t\tonClick={handleContainerFocus}\n\t\t\tonKeyDown={onContainerKeyDown}\n\t\t>\n\t\t\t{children}\n\t\t</div>\n\t);\n}\n\nexport { SelectContainer };\n"],"mappings":";;;AAuBA,SAAS,EAAgB,GAA6B;CACrD,IAAM,EACL,aACA,yBACA,aACA,YACA,cACA,cACA,cACA,aACA,YACA,SACA,OACA,iBACA,iBACA,uBACA,aACA,iBACA,4BACG;CAOJ,OACC,kBAAC,OAAD;EACC,KAAK;EACD;EACM;EACV,MAAK;EACL,iBAAc;EACd,iBAAe;EACf,iBAAe;EACf,yBAAuB;EACvB,WAAW,wBAfK,IAAe,cAAc,GAeA,GAAG,EAAQ,GAAG,EAAK,GAblD,KAAY,KAAY,IAAY,YAAY,GAaa,GAd7D,IAAU,YAAY,GAckD,GAZxE,IAAY,YAAY,GAY2D,GAAG;EACpG,SAAS;EACT,WAAW;EAEV;CACG,CAAA;AAEP"}
@@ -3,11 +3,14 @@ import { jsx as e, jsxs as t } from "react/jsx-runtime";
3
3
  import { Check as n } from "lucide-react";
4
4
  //#region src/components/select/selectOption/index.tsx
5
5
  function r(r) {
6
- let { label: i, optionHasSelected: a, handleChangeValue: o, value: s, size: c } = r;
6
+ let { label: i, optionHasSelected: a, handleChangeValue: o, value: s, size: c, id: l, isHighlighted: u = !1 } = r, d = a(s);
7
7
  return /* @__PURE__ */ t("button", {
8
8
  type: "button",
9
+ id: l,
10
+ role: "option",
11
+ "aria-selected": d,
9
12
  onClick: () => o(s),
10
- className: `arkynSelectOption ${c} ${a(s) ? "active" : ""}`,
13
+ className: `arkynSelectOption ${c} ${d ? "active" : ""} ${u ? "highlighted" : ""}`,
11
14
  children: [
12
15
  i,
13
16
  " ",
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../../src/components/select/selectOption/index.tsx"],"sourcesContent":["import { Check } from \"lucide-react\";\nimport \"./styles.css\";\n\ntype SelectOptionProps = {\n\tvalue: string;\n\tlabel: string;\n\tsize: \"md\" | \"lg\";\n\toptionHasSelected: (value: string) => boolean;\n\thandleChangeValue: (value: string) => void;\n};\n\nfunction SelectOption(props: SelectOptionProps) {\n\tconst { label, optionHasSelected, handleChangeValue, value, size } = props;\n\n\tconst hasActive = optionHasSelected(value) ? \"active\" : \"\";\n\tconst className = `arkynSelectOption ${size} ${hasActive}`;\n\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tonClick={() => handleChangeValue(value)}\n\t\t\tclassName={className}\n\t\t>\n\t\t\t{label} <Check />\n\t\t</button>\n\t);\n}\n\nexport { SelectOption };\n"],"mappings":";;;;AAWA,SAAS,EAAa,GAA0B;CAC/C,IAAM,EAAE,UAAO,sBAAmB,sBAAmB,UAAO,YAAS;CAKrE,OACC,kBAAC,UAAD;EACC,MAAK;EACL,eAAe,EAAkB,CAAK;EAC3B,WAAA,qBAN0B,EAAK,GAD1B,EAAkB,CAAK,IAAI,WAAW;YAIvD;GAKE;GAAM;GAAC,kBAAC,GAAD,CAAQ,CAAA;EACT;;AAEV"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../../src/components/select/selectOption/index.tsx"],"sourcesContent":["import { Check } from \"lucide-react\";\nimport \"./styles.css\";\n\ntype SelectOptionProps = {\n\tvalue: string;\n\tlabel: string;\n\tsize: \"md\" | \"lg\";\n\tid?: string;\n\tisHighlighted?: boolean;\n\toptionHasSelected: (value: string) => boolean;\n\thandleChangeValue: (value: string) => void;\n};\n\nfunction SelectOption(props: SelectOptionProps) {\n\tconst {\n\t\tlabel,\n\t\toptionHasSelected,\n\t\thandleChangeValue,\n\t\tvalue,\n\t\tsize,\n\t\tid,\n\t\tisHighlighted = false,\n\t} = props;\n\n\tconst isSelected = optionHasSelected(value);\n\tconst hasActive = isSelected ? \"active\" : \"\";\n\tconst highlighted = isHighlighted ? \"highlighted\" : \"\";\n\tconst className = `arkynSelectOption ${size} ${hasActive} ${highlighted}`;\n\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tid={id}\n\t\t\trole=\"option\"\n\t\t\taria-selected={isSelected}\n\t\t\tonClick={() => handleChangeValue(value)}\n\t\t\tclassName={className}\n\t\t>\n\t\t\t{label} <Check />\n\t\t</button>\n\t);\n}\n\nexport { SelectOption };\n"],"mappings":";;;;AAaA,SAAS,EAAa,GAA0B;CAC/C,IAAM,EACL,UACA,sBACA,sBACA,UACA,SACA,OACA,mBAAgB,OACb,GAEE,IAAa,EAAkB,CAAK;CAK1C,OACC,kBAAC,UAAD;EACC,MAAK;EACD;EACJ,MAAK;EACL,iBAAe;EACf,eAAe,EAAkB,CAAK;EAC3B,WAAA,qBAT0B,EAAK,GAF1B,IAAa,WAAW,GAEe,GADrC,IAAgB,gBAAgB;YAInD;GAQE;GAAM;GAAC,kBAAC,GAAD,CAAQ,CAAA;EACT;;AAEV"}
@@ -1 +1 @@
1
- @layer arkyn{.arkynSelectOption{color:var(--text-body,#52525b);background-color:inherit;-webkit-user-select:none;user-select:none;border:none;justify-content:space-between;align-items:center;font-weight:400;line-height:21.79px;display:flex}.arkynSelectOption.md{padding:8px 16px;font-size:14px}.arkynSelectOption.lg{padding:8px 16px;font-size:16px}.arkynSelectOption svg{width:20px;height:20px;color:rgb(var(--spotlight-primary,17, 109, 220));display:none}.arkynSelectOption:hover{cursor:pointer;filter:brightness(.98)}.arkynSelectOption.active{color:var(--text-heading,#09090b);filter:brightness(.95);font-weight:600}.arkynSelectOption.active svg{display:unset}html.dark .arkynSelectOption:hover,html.dark .arkynSelectOption.active{filter:brightness(1.2)}}
1
+ @layer arkyn{.arkynSelectOption{color:var(--text-body,#52525b);background-color:inherit;-webkit-user-select:none;user-select:none;border:none;justify-content:space-between;align-items:center;font-weight:400;line-height:21.79px;display:flex}.arkynSelectOption.md{padding:8px 16px;font-size:14px}.arkynSelectOption.lg{padding:8px 16px;font-size:16px}.arkynSelectOption svg{width:20px;height:20px;color:rgb(var(--spotlight-primary,17, 109, 220));display:none}.arkynSelectOption:hover{cursor:pointer;filter:brightness(.98)}.arkynSelectOption.active{color:var(--text-heading,#09090b);filter:brightness(.95);font-weight:600}.arkynSelectOption.active svg{display:unset}.arkynSelectOption.highlighted{filter:brightness(.98)}html.dark .arkynSelectOption:hover,html.dark .arkynSelectOption.active,html.dark .arkynSelectOption.highlighted{filter:brightness(1.2)}}
@@ -6,29 +6,31 @@ import { jsx as a, jsxs as o } from "react/jsx-runtime";
6
6
  import { Search as s } from "lucide-react";
7
7
  //#region src/components/select/selectOptionsContainer/index.tsx
8
8
  function c(c) {
9
- let { children: l, isFocused: u, isSearchable: d, search: f, onSearch: p } = c, m = r(null), [h, g] = i("bottom");
10
- e(u), n(() => {
11
- u && (() => {
12
- if (!m.current) return;
13
- let e = m.current.parentElement;
9
+ let { children: l, id: u, isFocused: d, isSearchable: f, search: p, onSearch: m } = c, h = r(null), [g, _] = i("bottom");
10
+ e(d), n(() => {
11
+ d && (() => {
12
+ if (!h.current) return;
13
+ let e = h.current.parentElement;
14
14
  if (!e) return;
15
15
  let t = e.getBoundingClientRect();
16
- window.innerHeight - t.bottom < 300 && t.top > 300 ? g("top") : g("bottom");
16
+ window.innerHeight - t.bottom < 300 && t.top > 300 ? _("top") : _("bottom");
17
17
  })();
18
- }, [u]);
19
- function _(e) {
20
- d && p(e.target.value);
18
+ }, [d]);
19
+ function v(e) {
20
+ f && m(e.target.value);
21
21
  }
22
- return u ? /* @__PURE__ */ o("div", {
23
- ref: m,
24
- className: `arkynSelectOptionsContainer ${h}`,
25
- children: [d && /* @__PURE__ */ a(t, {
22
+ return d ? /* @__PURE__ */ o("div", {
23
+ ref: h,
24
+ id: u,
25
+ role: "listbox",
26
+ className: `arkynSelectOptionsContainer ${g}`,
27
+ children: [f && /* @__PURE__ */ a(t, {
26
28
  type: "search",
27
29
  name: "search-select",
28
30
  variant: "underline",
29
31
  leftIcon: s,
30
- value: f,
31
- onChange: _
32
+ value: p,
33
+ onChange: v
32
34
  }), l]
33
35
  }) : null;
34
36
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../../src/components/select/selectOptionsContainer/index.tsx"],"sourcesContent":["import { Search } from \"lucide-react\";\nimport {\n\ttype ChangeEvent,\n\ttype ReactNode,\n\tuseEffect,\n\tuseRef,\n\tuseState,\n} from \"react\";\n\nimport { useScrollLock } from \"../../../hooks/useScrollLock\";\nimport { Input } from \"../../input\";\n\nimport \"./styles.css\";\n\ntype SelectOptionsContainerProps = {\n\tisFocused: boolean;\n\tisSearchable: boolean;\n\tchildren: ReactNode;\n\tsearch: string;\n\tonSearch: (value: string) => void;\n};\n\nfunction SelectOptionsContainer(props: SelectOptionsContainerProps) {\n\tconst { children, isFocused, isSearchable, search, onSearch } = props;\n\n\tconst containerRef = useRef<HTMLDivElement>(null);\n\tconst [position, setPosition] = useState<\"bottom\" | \"top\">(\"bottom\");\n\n\tuseScrollLock(isFocused);\n\n\tuseEffect(() => {\n\t\tif (!isFocused) return;\n\n\t\tconst checkContainerPosition = () => {\n\t\t\tif (!containerRef.current) return;\n\n\t\t\tconst parentElement = containerRef.current.parentElement;\n\t\t\tif (!parentElement) return;\n\n\t\t\tconst parentRect = parentElement.getBoundingClientRect();\n\t\t\tconst viewportHeight = window.innerHeight;\n\n\t\t\tconst estimatedContainerHeight = 300;\n\t\t\tconst spaceBelow = viewportHeight - parentRect.bottom;\n\n\t\t\tif (\n\t\t\t\tspaceBelow < estimatedContainerHeight &&\n\t\t\t\tparentRect.top > estimatedContainerHeight\n\t\t\t) {\n\t\t\t\tsetPosition(\"top\");\n\t\t\t} else {\n\t\t\t\tsetPosition(\"bottom\");\n\t\t\t}\n\t\t};\n\n\t\tcheckContainerPosition();\n\t}, [isFocused]);\n\n\tfunction handleSearch(e: ChangeEvent<HTMLInputElement>) {\n\t\tif (!isSearchable) return;\n\t\tonSearch(e.target.value);\n\t}\n\n\tif (!isFocused) return null;\n\n\treturn (\n\t\t<div\n\t\t\tref={containerRef}\n\t\t\tclassName={`arkynSelectOptionsContainer ${position}`}\n\t\t>\n\t\t\t{isSearchable && (\n\t\t\t\t<Input\n\t\t\t\t\ttype=\"search\"\n\t\t\t\t\tname=\"search-select\"\n\t\t\t\t\tvariant=\"underline\"\n\t\t\t\t\tleftIcon={Search}\n\t\t\t\t\tvalue={search}\n\t\t\t\t\tonChange={handleSearch}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t{children}\n\t\t</div>\n\t);\n}\n\nexport { SelectOptionsContainer };\n"],"mappings":";;;;;;;AAsBA,SAAS,EAAuB,GAAoC;CACnE,IAAM,EAAE,aAAU,cAAW,iBAAc,WAAQ,gBAAa,GAE1D,IAAe,EAAuB,IAAI,GAC1C,CAAC,GAAU,KAAe,EAA2B,QAAQ;CAInE,AAFA,EAAc,CAAS,GAEvB,QAAgB;EACV,YAEgC;GACpC,IAAI,CAAC,EAAa,SAAS;GAE3B,IAAM,IAAgB,EAAa,QAAQ;GAC3C,IAAI,CAAC,GAAe;GAEpB,IAAM,IAAa,EAAc,sBAAsB;GAMvD,AALuB,OAAO,cAGM,EAAW,SAGjC,OACb,EAAW,MAAM,MAEjB,EAAY,KAAK,IAEjB,EAAY,QAAQ;EAEtB,EAEA,CAAuB;CACxB,GAAG,CAAC,CAAS,CAAC;CAEd,SAAS,EAAa,GAAkC;EAClD,KACL,EAAS,EAAE,OAAO,KAAK;CACxB;CAIA,OAFK,IAGJ,kBAAC,OAAD;EACC,KAAK;EACL,WAAW,+BAA+B;YAF3C,CAIE,KACA,kBAAC,GAAD;GACC,MAAK;GACL,MAAK;GACL,SAAQ;GACR,UAAU;GACV,OAAO;GACP,UAAU;EACV,CAAA,GAGD,CACG;MAnBiB;AAqBxB"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../../src/components/select/selectOptionsContainer/index.tsx"],"sourcesContent":["import { Search } from \"lucide-react\";\nimport {\n\ttype ChangeEvent,\n\ttype ReactNode,\n\tuseEffect,\n\tuseRef,\n\tuseState,\n} from \"react\";\n\nimport { useScrollLock } from \"../../../hooks/useScrollLock\";\nimport { Input } from \"../../input\";\n\nimport \"./styles.css\";\n\ntype SelectOptionsContainerProps = {\n\tid?: string;\n\tisFocused: boolean;\n\tisSearchable: boolean;\n\tchildren: ReactNode;\n\tsearch: string;\n\tonSearch: (value: string) => void;\n};\n\nfunction SelectOptionsContainer(props: SelectOptionsContainerProps) {\n\tconst { children, id, isFocused, isSearchable, search, onSearch } = props;\n\n\tconst containerRef = useRef<HTMLDivElement>(null);\n\tconst [position, setPosition] = useState<\"bottom\" | \"top\">(\"bottom\");\n\n\tuseScrollLock(isFocused);\n\n\tuseEffect(() => {\n\t\tif (!isFocused) return;\n\n\t\tconst checkContainerPosition = () => {\n\t\t\tif (!containerRef.current) return;\n\n\t\t\tconst parentElement = containerRef.current.parentElement;\n\t\t\tif (!parentElement) return;\n\n\t\t\tconst parentRect = parentElement.getBoundingClientRect();\n\t\t\tconst viewportHeight = window.innerHeight;\n\n\t\t\tconst estimatedContainerHeight = 300;\n\t\t\tconst spaceBelow = viewportHeight - parentRect.bottom;\n\n\t\t\tif (\n\t\t\t\tspaceBelow < estimatedContainerHeight &&\n\t\t\t\tparentRect.top > estimatedContainerHeight\n\t\t\t) {\n\t\t\t\tsetPosition(\"top\");\n\t\t\t} else {\n\t\t\t\tsetPosition(\"bottom\");\n\t\t\t}\n\t\t};\n\n\t\tcheckContainerPosition();\n\t}, [isFocused]);\n\n\tfunction handleSearch(e: ChangeEvent<HTMLInputElement>) {\n\t\tif (!isSearchable) return;\n\t\tonSearch(e.target.value);\n\t}\n\n\tif (!isFocused) return null;\n\n\treturn (\n\t\t<div\n\t\t\tref={containerRef}\n\t\t\tid={id}\n\t\t\trole=\"listbox\"\n\t\t\tclassName={`arkynSelectOptionsContainer ${position}`}\n\t\t>\n\t\t\t{isSearchable && (\n\t\t\t\t<Input\n\t\t\t\t\ttype=\"search\"\n\t\t\t\t\tname=\"search-select\"\n\t\t\t\t\tvariant=\"underline\"\n\t\t\t\t\tleftIcon={Search}\n\t\t\t\t\tvalue={search}\n\t\t\t\t\tonChange={handleSearch}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t{children}\n\t\t</div>\n\t);\n}\n\nexport { SelectOptionsContainer };\n"],"mappings":";;;;;;;AAuBA,SAAS,EAAuB,GAAoC;CACnE,IAAM,EAAE,aAAU,OAAI,cAAW,iBAAc,WAAQ,gBAAa,GAE9D,IAAe,EAAuB,IAAI,GAC1C,CAAC,GAAU,KAAe,EAA2B,QAAQ;CAInE,AAFA,EAAc,CAAS,GAEvB,QAAgB;EACV,YAEgC;GACpC,IAAI,CAAC,EAAa,SAAS;GAE3B,IAAM,IAAgB,EAAa,QAAQ;GAC3C,IAAI,CAAC,GAAe;GAEpB,IAAM,IAAa,EAAc,sBAAsB;GAMvD,AALuB,OAAO,cAGM,EAAW,SAGjC,OACb,EAAW,MAAM,MAEjB,EAAY,KAAK,IAEjB,EAAY,QAAQ;EAEtB,EAEA,CAAuB;CACxB,GAAG,CAAC,CAAS,CAAC;CAEd,SAAS,EAAa,GAAkC;EAClD,KACL,EAAS,EAAE,OAAO,KAAK;CACxB;CAIA,OAFK,IAGJ,kBAAC,OAAD;EACC,KAAK;EACD;EACJ,MAAK;EACL,WAAW,+BAA+B;YAJ3C,CAME,KACA,kBAAC,GAAD;GACC,MAAK;GACL,MAAK;GACL,SAAQ;GACR,UAAU;GACV,OAAO;GACP,UAAU;EACV,CAAA,GAGD,CACG;MArBiB;AAuBxB"}
@@ -10,7 +10,7 @@
10
10
 
11
11
  @layer arkyn{.arkynSelectContent{flex-wrap:wrap;flex:1;align-items:start;gap:4px;display:flex}.arkynSelectContent>p{color:var(--text-muted,#a1a1aa);-webkit-user-select:none;user-select:none;font-weight:400}.arkynSelectContent>p.hasValue{color:var(--text-body,#52525b)}.arkynSelectContent.md>p{font-size:14px;line-height:14px}.arkynSelectContent.lg>p{font-size:16px;line-height:16px}}
12
12
 
13
- @layer arkyn{.arkynSelectOption{color:var(--text-body,#52525b);background-color:inherit;-webkit-user-select:none;user-select:none;border:none;justify-content:space-between;align-items:center;font-weight:400;line-height:21.79px;display:flex}.arkynSelectOption.md{padding:8px 16px;font-size:14px}.arkynSelectOption.lg{padding:8px 16px;font-size:16px}.arkynSelectOption svg{width:20px;height:20px;color:rgb(var(--spotlight-primary,17, 109, 220));display:none}.arkynSelectOption:hover{cursor:pointer;filter:brightness(.98)}.arkynSelectOption.active{color:var(--text-heading,#09090b);filter:brightness(.95);font-weight:600}.arkynSelectOption.active svg{display:unset}html.dark .arkynSelectOption:hover,html.dark .arkynSelectOption.active{filter:brightness(1.2)}}
13
+ @layer arkyn{.arkynSelectOption{color:var(--text-body,#52525b);background-color:inherit;-webkit-user-select:none;user-select:none;border:none;justify-content:space-between;align-items:center;font-weight:400;line-height:21.79px;display:flex}.arkynSelectOption.md{padding:8px 16px;font-size:14px}.arkynSelectOption.lg{padding:8px 16px;font-size:16px}.arkynSelectOption svg{width:20px;height:20px;color:rgb(var(--spotlight-primary,17, 109, 220));display:none}.arkynSelectOption:hover{cursor:pointer;filter:brightness(.98)}.arkynSelectOption.active{color:var(--text-heading,#09090b);filter:brightness(.95);font-weight:600}.arkynSelectOption.active svg{display:unset}.arkynSelectOption.highlighted{filter:brightness(.98)}html.dark .arkynSelectOption:hover,html.dark .arkynSelectOption.active,html.dark .arkynSelectOption.highlighted{filter:brightness(1.2)}}
14
14
 
15
15
  @layer arkyn{.arkynSelectOptionsContainer{z-index:7;border:1px solid var(--border,#e2e8f0);background-color:var(--background-foreground,#fff);border-radius:6px;flex-direction:column;flex:1;height:max-content;max-height:300px;list-style:none;display:flex;position:absolute;left:-2px;right:-2px;overflow:auto;box-shadow:0 4px 8px #0000001a}.arkynSelectOptionsContainer.bottom{top:calc(100% + 5px)}.arkynSelectOptionsContainer.top{bottom:calc(100% + 5px)}.arkynSelectOptionsContainer>p{text-align:center;color:var(--text-body,#52525b);padding:16px;font-size:14px;font-weight:400;line-height:21.79px}}
16
16
 
@@ -0,0 +1,18 @@
1
+ import { useEffect as e, useRef as t } from "react";
2
+ //#region src/hooks/useEscapeKey.ts
3
+ function n(n, r) {
4
+ let i = t(r);
5
+ i.current = r, e(() => {
6
+ if (!n) return;
7
+ function e(e) {
8
+ e.key === "Escape" && i.current();
9
+ }
10
+ return document.addEventListener("keydown", e), () => {
11
+ document.removeEventListener("keydown", e);
12
+ };
13
+ }, [n]);
14
+ }
15
+ //#endregion
16
+ export { n as useEscapeKey };
17
+
18
+ //# sourceMappingURL=useEscapeKey.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useEscapeKey.js","names":[],"sources":["../../../src/hooks/useEscapeKey.ts"],"sourcesContent":["import { useEffect, useRef } from \"react\";\n\n/**\n * useEscapeKey, invokes a callback when the `Escape` key is pressed while active.\n *\n * Listens on `document`, so it fires regardless of which descendant currently\n * has focus. The callback is always the latest one passed in, without\n * re-attaching the listener on every render.\n *\n * Used internally by `ModalContainer`, `DrawerContainer`, and `Popover` to\n * close the overlay on Escape.\n *\n * @param isActive - When `true`, the Escape key listener is attached.\n * @param onEscape - Called when Escape is pressed while `isActive` is `true`.\n *\n * @example\n * ```tsx\n * function CustomOverlay({ isOpen, onClose }) {\n * useEscapeKey(isOpen, onClose);\n * return isOpen ? <div role=\"dialog\">...</div> : null;\n * }\n * ```\n */\n\nfunction useEscapeKey(isActive: boolean, onEscape: () => void): void {\n\tconst onEscapeRef = useRef(onEscape);\n\tonEscapeRef.current = onEscape;\n\n\tuseEffect(() => {\n\t\tif (!isActive) return;\n\n\t\tfunction handleKeyDown(event: KeyboardEvent) {\n\t\t\tif (event.key === \"Escape\") onEscapeRef.current();\n\t\t}\n\n\t\tdocument.addEventListener(\"keydown\", handleKeyDown);\n\n\t\treturn () => {\n\t\t\tdocument.removeEventListener(\"keydown\", handleKeyDown);\n\t\t};\n\t}, [isActive]);\n}\n\nexport { useEscapeKey };\n"],"mappings":";;AAwBA,SAAS,EAAa,GAAmB,GAA4B;CACpE,IAAM,IAAc,EAAO,CAAQ;CAGnC,AAFA,EAAY,UAAU,GAEtB,QAAgB;EACf,IAAI,CAAC,GAAU;EAEf,SAAS,EAAc,GAAsB;GAC5C,AAAI,EAAM,QAAQ,YAAU,EAAY,QAAQ;EACjD;EAIA,OAFA,SAAS,iBAAiB,WAAW,CAAa,SAErC;GACZ,SAAS,oBAAoB,WAAW,CAAa;EACtD;CACD,GAAG,CAAC,CAAQ,CAAC;AACd"}
@@ -0,0 +1,44 @@
1
+ import { useEffect as e, useRef as t } from "react";
2
+ //#region src/hooks/useFocusTrap.ts
3
+ var n = [
4
+ "a[href]",
5
+ "area[href]",
6
+ "button:not([disabled])",
7
+ "input:not([disabled])",
8
+ "select:not([disabled])",
9
+ "textarea:not([disabled])",
10
+ "iframe",
11
+ "[tabindex]:not([tabindex='-1'])"
12
+ ].join(", ");
13
+ function r(e) {
14
+ return Array.from(e.querySelectorAll(n));
15
+ }
16
+ function i(n, i) {
17
+ let a = t(null);
18
+ e(() => {
19
+ if (!n) return;
20
+ let e = i.current;
21
+ if (!e) return;
22
+ let t = e;
23
+ a.current = document.activeElement;
24
+ let [o] = r(t);
25
+ (o ?? t).focus();
26
+ function s(e) {
27
+ if (e.key !== "Tab") return;
28
+ let n = r(t);
29
+ if (n.length === 0) {
30
+ e.preventDefault(), t.focus();
31
+ return;
32
+ }
33
+ let i = n[0], a = n[n.length - 1], o = document.activeElement;
34
+ e.shiftKey && o === i ? (e.preventDefault(), a.focus()) : !e.shiftKey && o === a && (e.preventDefault(), i.focus());
35
+ }
36
+ return document.addEventListener("keydown", s), () => {
37
+ document.removeEventListener("keydown", s), a.current?.focus(), a.current = null;
38
+ };
39
+ }, [n, i]);
40
+ }
41
+ //#endregion
42
+ export { i as useFocusTrap };
43
+
44
+ //# sourceMappingURL=useFocusTrap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useFocusTrap.js","names":[],"sources":["../../../src/hooks/useFocusTrap.ts"],"sourcesContent":["import { type RefObject, useEffect, useRef } from \"react\";\n\nconst FOCUSABLE_SELECTOR = [\n\t\"a[href]\",\n\t\"area[href]\",\n\t\"button:not([disabled])\",\n\t\"input:not([disabled])\",\n\t\"select:not([disabled])\",\n\t\"textarea:not([disabled])\",\n\t\"iframe\",\n\t\"[tabindex]:not([tabindex='-1'])\",\n].join(\", \");\n\nfunction getFocusableElements(container: HTMLElement): HTMLElement[] {\n\treturn Array.from(\n\t\tcontainer.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR),\n\t);\n}\n\n/**\n * useFocusTrap, keeps keyboard focus inside a container while `isActive`.\n *\n * On activation, saves the currently focused element and moves focus to the\n * first focusable descendant of `containerRef.current` (or to the container\n * itself when it has none). While active, `Tab`/`Shift+Tab` cycle focus\n * between the first and last focusable descendants instead of leaving the\n * container. On deactivation (or unmount), focus is restored to the element\n * that was focused right before activation.\n *\n * Used internally by `ModalContainer`, `DrawerContainer`, and `Popover`.\n *\n * @param isActive - When `true`, focus is moved into and trapped inside the container.\n * @param containerRef - Ref to the container that should trap focus. Give the element `tabIndex={-1}` so it can still receive focus when it has no focusable children.\n *\n * @example\n * ```tsx\n * function CustomOverlay({ isOpen }) {\n * const containerRef = useRef<HTMLDivElement>(null);\n * useFocusTrap(isOpen, containerRef);\n * return isOpen ? <div ref={containerRef} tabIndex={-1}>...</div> : null;\n * }\n * ```\n */\n\nfunction useFocusTrap(\n\tisActive: boolean,\n\tcontainerRef: RefObject<HTMLElement | null>,\n): void {\n\tconst previouslyFocused = useRef<HTMLElement | null>(null);\n\n\tuseEffect(() => {\n\t\tif (!isActive) return;\n\n\t\tconst container: HTMLElement | null = containerRef.current;\n\t\tif (!container) return;\n\t\tconst dialogNode: HTMLElement = container;\n\n\t\tpreviouslyFocused.current = document.activeElement as HTMLElement | null;\n\n\t\tconst [firstFocusable] = getFocusableElements(dialogNode);\n\t\t(firstFocusable ?? dialogNode).focus();\n\n\t\tfunction handleKeyDown(event: KeyboardEvent) {\n\t\t\tif (event.key !== \"Tab\") return;\n\n\t\t\tconst focusable = getFocusableElements(dialogNode);\n\n\t\t\tif (focusable.length === 0) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tdialogNode.focus();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst first = focusable[0];\n\t\t\tconst last = focusable[focusable.length - 1];\n\t\t\tconst active = document.activeElement;\n\n\t\t\tif (event.shiftKey && active === first) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tlast.focus();\n\t\t\t} else if (!event.shiftKey && active === last) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tfirst.focus();\n\t\t\t}\n\t\t}\n\n\t\tdocument.addEventListener(\"keydown\", handleKeyDown);\n\n\t\treturn () => {\n\t\t\tdocument.removeEventListener(\"keydown\", handleKeyDown);\n\t\t\tpreviouslyFocused.current?.focus();\n\t\t\tpreviouslyFocused.current = null;\n\t\t};\n\t}, [isActive, containerRef]);\n}\n\nexport { useFocusTrap };\n"],"mappings":";;AAEA,IAAM,IAAqB;CAC1B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACD,CAAC,CAAC,KAAK,IAAI;AAEX,SAAS,EAAqB,GAAuC;CACpE,OAAO,MAAM,KACZ,EAAU,iBAA8B,CAAkB,CAC3D;AACD;AA2BA,SAAS,EACR,GACA,GACO;CACP,IAAM,IAAoB,EAA2B,IAAI;CAEzD,QAAgB;EACf,IAAI,CAAC,GAAU;EAEf,IAAM,IAAgC,EAAa;EACnD,IAAI,CAAC,GAAW;EAChB,IAAM,IAA0B;EAEhC,EAAkB,UAAU,SAAS;EAErC,IAAM,CAAC,KAAkB,EAAqB,CAAU;EACxD,CAAC,KAAkB,EAAA,CAAY,MAAM;EAErC,SAAS,EAAc,GAAsB;GAC5C,IAAI,EAAM,QAAQ,OAAO;GAEzB,IAAM,IAAY,EAAqB,CAAU;GAEjD,IAAI,EAAU,WAAW,GAAG;IAE3B,AADA,EAAM,eAAe,GACrB,EAAW,MAAM;IACjB;GACD;GAEA,IAAM,IAAQ,EAAU,IAClB,IAAO,EAAU,EAAU,SAAS,IACpC,IAAS,SAAS;GAExB,AAAI,EAAM,YAAY,MAAW,KAChC,EAAM,eAAe,GACrB,EAAK,MAAM,KACD,CAAC,EAAM,YAAY,MAAW,MACxC,EAAM,eAAe,GACrB,EAAM,MAAM;EAEd;EAIA,OAFA,SAAS,iBAAiB,WAAW,CAAa,SAErC;GAGZ,AAFA,SAAS,oBAAoB,WAAW,CAAa,GACrD,EAAkB,SAAS,MAAM,GACjC,EAAkB,UAAU;EAC7B;CACD,GAAG,CAAC,GAAU,CAAY,CAAC;AAC5B"}