@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
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../src/components/multiSelect/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 { MultiSelectChevron } from \"./multiSelectChevron\";\nimport { MultiSelectContainer } from \"./multiSelectContainer\";\nimport { MultiSelectContent } from \"./multiSelectContent\";\nimport { MultiSelectMark } from \"./multiSelectMark\";\nimport { MultiSelectOption } from \"./multiSelectOption\";\nimport { MultiSelectOptionsContainer } from \"./multiSelectOptionsContainer\";\nimport { MultiSelectOverlay } from \"./multiSelectOverlay\";\nimport { MultiSelectSpinner } from \"./multiSelectSpinner\";\n\ntype MultiSelectProps = {\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 array of selected values. */\n\tvalue?: string[];\n\t/** Uncontrolled default array of selected values. @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 multiselect. */\n\tlabel?: string;\n\t/** Validation error message displayed below the multiselect. */\n\terrorMessage?: string;\n\t/** Placeholder text shown when no options are 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 selection 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 or deselected. @default false */\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 values array changes. */\n\tonChange?: (value: string[]) => void;\n\t/** Callback fired when the multiselect gains focus. */\n\tonFocus?: () => void;\n\t/** Callback fired when the multiselect loses focus. */\n\tonBlur?: (e: FocusEvent<HTMLDivElement>) => void;\n\t/**\n\t * MultiSelect 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 * MultiSelect, multi-option dropdown with optional search, label, validation, and form integration.\n *\n * Selected values are stored as a JSON array in a hidden `<input>` for form submission.\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 array of selected values.\n * @param props.defaultValue - Uncontrolled default selection. Default: []\n * @param props.label - Label text displayed above the multiselect.\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 toggling an option. Default: false\n * @param props.onChange - Callback fired when the selection changes.\n * @param props.onSearch - Callback fired when the search query changes.\n * @param props.size - MultiSelect 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 MultiSelect JSX element wrapped in `FieldTemplate`.\n *\n * @example\n * ```tsx\n * // Basic\n * <MultiSelect\n * name=\"categories\"\n * options={[\n * { label: \"Technology\", value: \"tech\" },\n * { label: \"Design\", value: \"design\" },\n * ]}\n * />\n *\n * // With label, validation, and searchable\n * <MultiSelect\n * name=\"skills\"\n * label=\"Skills\"\n * showAsterisk\n * isSearchable\n * options={skillOptions}\n * errorMessage={errors.skills}\n * />\n *\n * // Controlled with async search\n * <MultiSelect\n * name=\"tags\"\n * label=\"Tags\"\n * value={selectedTags}\n * onChange={setSelectedTags}\n * onSearch={fetchTagOptions}\n * isLoading={isLoadingTags}\n * options={tagOptions}\n * />\n * ```\n */\n\nfunction MultiSelect(props: MultiSelectProps) {\n\tconst {\n\t\tname,\n\t\toptions,\n\t\tclassName: wrapperClassName = \"\",\n\t\tplaceholder = \"Selecione...\",\n\t\tcloseOnSelect = false,\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\tunShowFieldTemplate = false,\n\t\torientation = \"vertical\",\n\t} = props;\n\n\tconst { fieldErrors } = useForm();\n\n\tconst multiSelectRef = useRef<HTMLInputElement>(null);\n\tconst generatedId = useId();\n\tconst multiSelectId = 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 [selectedOptions, setSelectedOptions] = useState(defaultValue);\n\n\tconst forceSelectedOptions = value || selectedOptions;\n\n\tfunction optionHasSelected(value: string) {\n\t\treturn forceSelectedOptions.includes(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 || !multiSelectRef?.current || isFocused) return;\n\t\tsetIsFocused(true);\n\t\tmultiSelectRef.current.focus();\n\t\tonFocus?.();\n\t}\n\n\tfunction handleBlur() {\n\t\tsetIsFocused(false);\n\t\tif (onBlur && multiSelectRef.current) multiSelectRef.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\tsetSelectedOptions(selectedOptions.filter((v) => v !== value));\n\t\t\tif (onChange) onChange(selectedOptions.filter((v) => v !== value));\n\t\t} else {\n\t\t\tsetSelectedOptions([...selectedOptions, value]);\n\t\t\tif (onChange) onChange([...selectedOptions, 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<MultiSelectContainer\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={multiSelectId}\n\t\t\t>\n\t\t\t\t<input\n\t\t\t\t\tref={multiSelectRef}\n\t\t\t\t\tname={name}\n\t\t\t\t\tvalue={JSON.stringify(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<MultiSelectContent size={size}>\n\t\t\t\t\t{forceSelectedOptions.map((value) => (\n\t\t\t\t\t\t<MultiSelectMark\n\t\t\t\t\t\t\tkey={value}\n\t\t\t\t\t\t\tlabel={getOptionLabel(value)}\n\t\t\t\t\t\t\tvalue={value}\n\t\t\t\t\t\t\thandleChangeValue={handleChangeValue}\n\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\n\t\t\t\t\t{forceSelectedOptions.length <= 0 && <p>{placeholder}</p>}\n\t\t\t\t</MultiSelectContent>\n\n\t\t\t\t<MultiSelectOptionsContainer\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<MultiSelectOption\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</MultiSelectOptionsContainer>\n\n\t\t\t\t<MultiSelectChevron\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<MultiSelectSpinner iconSize={iconSize} isLoading={isLoading} />\n\t\t\t\t<MultiSelectOverlay handleBlur={handleBlur} isFocused={isFocused} />\n\t\t\t</MultiSelectContainer>\n\t\t</FieldTemplate>\n\t);\n}\n\nexport { MultiSelect };\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../src/components/multiSelect/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 { MultiSelectChevron } from \"./multiSelectChevron\";\nimport { MultiSelectContainer } from \"./multiSelectContainer\";\nimport { MultiSelectContent } from \"./multiSelectContent\";\nimport { MultiSelectMark } from \"./multiSelectMark\";\nimport { MultiSelectOption } from \"./multiSelectOption\";\nimport { MultiSelectOptionsContainer } from \"./multiSelectOptionsContainer\";\nimport { MultiSelectOverlay } from \"./multiSelectOverlay\";\nimport { MultiSelectSpinner } from \"./multiSelectSpinner\";\n\ntype MultiSelectProps = {\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 array of selected values. */\n\tvalue?: string[];\n\t/** Uncontrolled default array of selected values. @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 multiselect. */\n\tlabel?: string;\n\t/** Validation error message displayed below the multiselect. */\n\terrorMessage?: string;\n\t/** Placeholder text shown when no options are 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 selection 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 or deselected. @default false */\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 values array changes. */\n\tonChange?: (value: string[]) => void;\n\t/** Callback fired when the multiselect gains focus. */\n\tonFocus?: () => void;\n\t/** Callback fired when the multiselect loses focus. */\n\tonBlur?: (e: FocusEvent<HTMLDivElement>) => void;\n\t/**\n\t * MultiSelect 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 * MultiSelect, multi-option dropdown with optional search, label, validation, and form integration.\n *\n * Selected values are stored as a JSON array in a hidden `<input>` for form submission.\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 array of selected values.\n * @param props.defaultValue - Uncontrolled default selection. Default: []\n * @param props.label - Label text displayed above the multiselect.\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 toggling an option. Default: false\n * @param props.onChange - Callback fired when the selection changes.\n * @param props.onSearch - Callback fired when the search query changes.\n * @param props.size - MultiSelect 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 MultiSelect JSX element wrapped in `FieldTemplate`.\n *\n * @example\n * ```tsx\n * // Basic\n * <MultiSelect\n * name=\"categories\"\n * options={[\n * { label: \"Technology\", value: \"tech\" },\n * { label: \"Design\", value: \"design\" },\n * ]}\n * />\n *\n * // With label, validation, and searchable\n * <MultiSelect\n * name=\"skills\"\n * label=\"Skills\"\n * showAsterisk\n * isSearchable\n * options={skillOptions}\n * errorMessage={errors.skills}\n * />\n *\n * // Controlled with async search\n * <MultiSelect\n * name=\"tags\"\n * label=\"Tags\"\n * value={selectedTags}\n * onChange={setSelectedTags}\n * onSearch={fetchTagOptions}\n * isLoading={isLoadingTags}\n * options={tagOptions}\n * />\n * ```\n */\n\nfunction MultiSelect(props: MultiSelectProps) {\n\tconst {\n\t\tname,\n\t\toptions,\n\t\tclassName: wrapperClassName = \"\",\n\t\tplaceholder = \"Selecione...\",\n\t\tcloseOnSelect = false,\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\tunShowFieldTemplate = false,\n\t\torientation = \"vertical\",\n\t} = props;\n\n\tconst { fieldErrors } = useForm();\n\n\tconst multiSelectRef = useRef<HTMLInputElement>(null);\n\tconst containerRef = useRef<HTMLDivElement>(null);\n\tconst generatedId = useId();\n\tconst multiSelectId = id || generatedId;\n\tconst listboxId = `${multiSelectId}-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 [selectedOptions, setSelectedOptions] = useState(defaultValue);\n\tconst [highlightedIndex, setHighlightedIndex] = useState(-1);\n\n\tconst forceSelectedOptions = value || selectedOptions;\n\n\tfunction optionHasSelected(value: string) {\n\t\treturn forceSelectedOptions.includes(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 || !multiSelectRef?.current || isFocused) return;\n\t\tsetIsFocused(true);\n\t\tsetHighlightedIndex(-1);\n\t\tmultiSelectRef.current.focus();\n\t\tonFocus?.();\n\t}\n\n\tfunction handleBlur() {\n\t\tsetIsFocused(false);\n\t\tsetHighlightedIndex(-1);\n\t\tif (onBlur && multiSelectRef.current) multiSelectRef.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\tsetSelectedOptions(selectedOptions.filter((v) => v !== value));\n\t\t\tif (onChange) onChange(selectedOptions.filter((v) => v !== value));\n\t\t} else {\n\t\t\tsetSelectedOptions([...selectedOptions, value]);\n\t\t\tif (onChange) onChange([...selectedOptions, 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<MultiSelectContainer\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={multiSelectId}\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={multiSelectRef}\n\t\t\t\t\tname={name}\n\t\t\t\t\tvalue={JSON.stringify(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<MultiSelectContent size={size}>\n\t\t\t\t\t{forceSelectedOptions.map((value) => (\n\t\t\t\t\t\t<MultiSelectMark\n\t\t\t\t\t\t\tkey={value}\n\t\t\t\t\t\t\tlabel={getOptionLabel(value)}\n\t\t\t\t\t\t\tvalue={value}\n\t\t\t\t\t\t\thandleChangeValue={handleChangeValue}\n\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\n\t\t\t\t\t{forceSelectedOptions.length <= 0 && <p>{placeholder}</p>}\n\t\t\t\t</MultiSelectContent>\n\n\t\t\t\t<MultiSelectOptionsContainer\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<MultiSelectOption\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</MultiSelectOptionsContainer>\n\n\t\t\t\t<MultiSelectChevron\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<MultiSelectSpinner iconSize={iconSize} isLoading={isLoading} />\n\t\t\t\t<MultiSelectOverlay handleBlur={handleBlur} isFocused={isFocused} />\n\t\t\t</MultiSelectContainer>\n\t\t</FieldTemplate>\n\t);\n}\n\nexport { MultiSelect };\n"],"mappings":";;;;;;;;;;;;;;AAsJA,SAAS,EAAY,GAAyB;CAC7C,IAAM,EACL,SACA,YACA,WAAW,IAAmB,IAC9B,iBAAc,gBACd,mBAAgB,IAChB,kBAAe,CAAC,GAChB,cAAc,GACd,eAAY,IACZ,cAAW,IACX,mBAAe,IACf,QACA,WACA,kBACA,UAAU,GACV,aACA,aACA,YACA,mBAAe,0BACf,aACA,UAAU,KAAe,IACzB,WACA,UAAO,MACP,WACA,aAAU,SACV,yBAAsB,IACtB,iBAAc,eACX,GAEE,EAAE,mBAAgB,EAAQ,GAE1B,IAAiB,EAAyB,IAAI,GAC9C,IAAe,EAAuB,IAAI,GAC1C,IAAc,EAAM,GACpB,IAAgB,MAAM,GACtB,IAAY,GAAG,EAAc,WAE7B,IAAe,KAAoB,IAAc,IACjD,IAAU,CAAC,CAAC,GACZ,IAAW,MAAgB,KAAa,GAGxC,IAAW;EADG,IAAI;EAAI,IAAI;CACf,EAAU,IAErB,CAAC,GAAQ,KAAa,EAAS,EAAE,GACjC,CAAC,GAAW,KAAgB,EAAS,EAAK,GAC1C,CAAC,GAAiB,KAAsB,EAAS,CAAY,GAC7D,CAAC,GAAkB,KAAuB,EAAS,EAAE,GAErD,IAAuB,MAAS;CAEtC,SAAS,EAAkB,GAAe;EACzC,OAAO,EAAqB,SAAS,CAAK;CAC3C;CAEA,SAAS,GAAe,GAAe;EAEtC,OADe,EAAQ,MAAM,MAAW,EAAO,UAAU,CAClD,CAAA,EAAQ,SAAS;CACzB;CAEA,SAAS,EAAY,GAAe;EACnC,OAAO,GAAG,EAAU,UAAU,EAAM,QAAQ,mBAAmB,GAAG;CACnE;CAEA,SAAS,IAAuB;EAC3B,KAAY,CAAC,GAAgB,WAAW,MAC5C,EAAa,EAAI,GACjB,EAAoB,EAAE,GACtB,EAAe,QAAQ,MAAM,GAC7B,KAAU;CACX;CAEA,SAAS,IAAa;EAGrB,AAFA,EAAa,EAAK,GAClB,EAAoB,EAAE,GAClB,MAAU,EAAe,WAAS,EAAe,QAAQ,KAAK;CACnE;CAEA,SAAS,GAAa,GAAe;EAKpC,AAJA,EAAU,CAAK,GAGf,EAAoB,EAAE,GAClB,KAAU,EAAS,CAAK;CAC7B;CAEA,SAAS,EAAkB,GAAe;EASzC,AARI,EAAkB,CAAK,KAC1B,EAAmB,EAAgB,QAAQ,MAAM,MAAM,CAAK,CAAC,GACzD,KAAU,EAAS,EAAgB,QAAQ,MAAM,MAAM,CAAK,CAAC,MAEjE,EAAmB,CAAC,GAAG,GAAiB,CAAK,CAAC,GAC1C,KAAU,EAAS,CAAC,GAAG,GAAiB,CAAK,CAAC,IAG/C,KAAe,EAAW;CAC/B;CAEA,IAAM,IAAgB,EAAQ,QAAQ,MAGrC,GAFI,EAAM,YACN,CAAC,EAAM,gBACP,EAAO,MAAM,YAAY,CAAC,CAAC,SAAS,EAAO,YAAY,CAAC,EAE5D;CAED,SAAS,GAAuB,GAAkC;EACjE,IAAI,GAAU;EAEd,IAAI,CAAC,GAAW;GACf,CAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,OAAO,EAAE,QAAQ,iBACnD,EAAE,eAAe,GACjB,EAAqB,GACjB,EAAE,QAAQ,eAAa,EAAoB,CAAC;GAEjD;EACD;EAEA,IAAM,IAAkB,EAAE,QAAwB,YAAY,SAIxD,IAAkB,EAAE,QAAwB,YAAY;EAE9D,QAAQ,EAAE,KAAV;GACC,KAAK;IAGJ,AAFA,EAAE,eAAe,GACjB,EAAW,GACX,EAAa,SAAS,MAAM;IAC5B;GACD,KAAK;IAEJ,AADA,EAAE,eAAe,GACjB,GAAqB,MAChB,EAAc,WAAW,IAAU,KACnC,IAAO,KACJ,IAAO,KAAK,EAAc,SADZ,IACyB,IAAO,CACrD;IACD;GACD,KAAK;IAEJ,AADA,EAAE,eAAe,GACjB,GAAqB,MAChB,EAAc,WAAW,IAAU,KACnC,IAAO,KACJ,IAAO,IAAI,IADG,EAAc,SAAS,IACK,IAAO,CACxD;IACD;GACD,KAAK;IACJ,IAAI,KAAkB,GAAgB;IAEtC,AADA,EAAE,eAAe,GACb,KAAoB,KAAK,IAAmB,EAAc,UAC7D,EAAkB,EAAc,EAAiB,CAAC,KAAK;IAExD;GACD,KAAK;IACJ,IAAI,GAAgB;IAEpB,AADA,EAAE,eAAe,GACb,KAAoB,KAAK,IAAmB,EAAc,UAC7D,EAAkB,EAAc,EAAiB,CAAC,KAAK;IAExD;GACD,SACC;EACF;CACD;CAEA,IAAM,KACL,KAAoB,KAAK,IAAmB,EAAc,SACvD,EAAY,EAAc,EAAiB,CAAC,KAAK,IACjD,KAAA;CAEJ,OACC,kBAAC,GAAD;EACO;EACC;EACO;EACd,WAAW;EACG;EACO;EACR;YAEb,kBAAC,IAAD;GACuB;GACZ;GACD;GACE;GACA;GACD;GACJ;GACG;GACT,cAAc,CAAC,CAAC;GAChB,IAAI;GACU;GACd,oBAAoB;GACpB,UAAU,IAAW,KAAK;GAC1B,cAAc;GACd,sBAAsB;aAfvB;IAiBC,kBAAC,SAAD;KACC,KAAK;KACC;KACN,OAAO,KAAK,UAAU,CAAoB;KAC1C,MAAK;IACL,CAAA;IAED,kBAAC,GAAD;KAAwB;KAAU,MAAM;KAAQ,WAAU;IAAU,CAAA;IAEnE,KAAY,kBAAC,GAAD;KAAU,MAAM;KAAU,aAAa;IAAM,CAAA;IAE1D,kBAAC,IAAD;KAA0B;eAA1B,CACE,EAAqB,KAAK,MAC1B,kBAAC,IAAD;MAEC,OAAO,GAAe,CAAK;MACpB;MACY;MACT;KACV,GALK,CAKL,CACD,GAEA,EAAqB,UAAU,KAAK,kBAAC,KAAD,EAAA,UAAI,EAAe,CAAA,CACrC;;IAEpB,kBAAC,GAAD;KACC,IAAI;KACO;KACG;KACN;KACR,UAAU;eALX,CAOE,EAAc,KAAK,EAAE,UAAO,YAAS,MACrC,kBAAC,IAAD;MAEC,IAAI,EAAY,CAAK;MACd;MACA;MACD;MACN,eAAe,MAAU;MACN;MACA;KACnB,GARK,CAQL,CACD,GAEA,EAAc,UAAU,KAAK,kBAAC,KAAD,EAAA,UAAI,GAAgB,CAAA,CACtB;;IAE7B,kBAAC,IAAD;KACW;KACC;KACD;KACA;KACC;IACX,CAAA;IAED,kBAAC,GAAD;KAA8B;KAAqB;IAAY,CAAA;IAC/D,kBAAC,GAAD;KAAgC;KAAuB;IAAY,CAAA;GAC9C;;CACR,CAAA;AAEjB"}
@@ -2,11 +2,19 @@
2
2
  import { jsx as e } from "react/jsx-runtime";
3
3
  //#region src/components/multiSelect/multiSelectContainer/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: `arkynMultiSelectContainer ${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/multiSelect/multiSelectContainer/index.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport \"./styles.css\";\n\ntype MultiSelectContainerProps = {\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 MultiSelectContainer(props: MultiSelectContainerProps) {\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={`arkynMultiSelectContainer ${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 { MultiSelectContainer };\n"],"mappings":";;;AAkBA,SAAS,EAAqB,GAAkC;CAC/D,IAAM,EACL,aACA,yBACA,aACA,YACA,cACA,cACA,cACA,aACA,YACA,SACA,OACA,oBACG;CAOJ,OACC,kBAAC,WAAD;EACK;EACJ,WAAW,6BARK,IAAe,cAAc,GAQK,GAAG,EAAQ,GAAG,EAAK,GANvD,KAAY,KAAY,IAAY,YAAY,GAMkB,GAPlE,IAAU,YAAY,GAOuD,GAL7E,IAAY,YAAY,GAKgE,GAAG;EACzG,SAAS;EAER;CACO,CAAA;AAEX"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../../src/components/multiSelect/multiSelectContainer/index.tsx"],"sourcesContent":["import type { KeyboardEvent, ReactNode, RefObject } from \"react\";\nimport \"./styles.css\";\n\ntype MultiSelectContainerProps = {\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 MultiSelectContainer(props: MultiSelectContainerProps) {\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={`arkynMultiSelectContainer ${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 { MultiSelectContainer };\n"],"mappings":";;;AAuBA,SAAS,EAAqB,GAAkC;CAC/D,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,6BAfK,IAAe,cAAc,GAeK,GAAG,EAAQ,GAAG,EAAK,GAbvD,KAAY,KAAY,IAAY,YAAY,GAakB,GAdlE,IAAU,YAAY,GAcuD,GAZ7E,IAAY,YAAY,GAYgE,GAAG;EACzG,SAAS;EACT,WAAW;EAEV;CACG,CAAA;AAEP"}
@@ -3,10 +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/multiSelect/multiSelectOption/index.tsx
5
5
  function r(r) {
6
- let { label: i, optionHasSelected: a, handleChangeValue: o, value: s, size: c } = r;
7
- return /* @__PURE__ */ t("div", {
6
+ let { label: i, optionHasSelected: a, handleChangeValue: o, value: s, size: c, id: l, isHighlighted: u = !1 } = r, d = a(s);
7
+ return /* @__PURE__ */ t("button", {
8
+ type: "button",
9
+ id: l,
10
+ role: "option",
11
+ "aria-selected": d,
8
12
  onClick: () => o(s),
9
- className: `arkynMultiSelectOption ${c} ${a(s) ? "active" : ""}`,
13
+ className: `arkynMultiSelectOption ${c} ${d ? "active" : ""} ${u ? "highlighted" : ""}`,
10
14
  children: [
11
15
  i,
12
16
  " ",
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../../src/components/multiSelect/multiSelectOption/index.tsx"],"sourcesContent":["import { Check } from \"lucide-react\";\nimport \"./styles.css\";\n\ntype MultiSelectOptionProps = {\n\tvalue: string;\n\tlabel: string;\n\tsize: \"md\" | \"lg\";\n\toptionHasSelected: (value: string) => boolean;\n\thandleChangeValue: (value: string) => void;\n};\n\nfunction MultiSelectOption(props: MultiSelectOptionProps) {\n\tconst { label, optionHasSelected, handleChangeValue, value, size } = props;\n\n\tconst hasActive = optionHasSelected(value) ? \"active\" : \"\";\n\tconst className = `arkynMultiSelectOption ${size} ${hasActive}`;\n\n\treturn (\n\t\t<div onClick={() => handleChangeValue(value)} className={className}>\n\t\t\t{label} <Check />\n\t\t</div>\n\t);\n}\n\nexport { MultiSelectOption };\n"],"mappings":";;;;AAWA,SAAS,EAAkB,GAA+B;CACzD,IAAM,EAAE,UAAO,sBAAmB,sBAAmB,UAAO,YAAS;CAKrE,OACC,kBAAC,OAAD;EAAK,eAAe,EAAkB,CAAK;EAAc,WAAA,0BAHd,EAAK,GAD/B,EAAkB,CAAK,IAAI,WAAW;YAIvD;GACE;GAAM;GAAC,kBAAC,GAAD,CAAQ,CAAA;EACZ;;AAEP"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../../src/components/multiSelect/multiSelectOption/index.tsx"],"sourcesContent":["import { Check } from \"lucide-react\";\nimport \"./styles.css\";\n\ntype MultiSelectOptionProps = {\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 MultiSelectOption(props: MultiSelectOptionProps) {\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 = `arkynMultiSelectOption ${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 { MultiSelectOption };\n"],"mappings":";;;;AAaA,SAAS,EAAkB,GAA+B;CACzD,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,0BAT+B,EAAK,GAF/B,IAAa,WAAW,GAEoB,GAD1C,IAAgB,gBAAgB;YAInD;GAQE;GAAM;GAAC,kBAAC,GAAD,CAAQ,CAAA;EACT;;AAEV"}
@@ -1 +1 @@
1
- @layer arkyn{.arkynMultiSelectOption{color:var(--text-body,#52525b);-webkit-user-select:none;user-select:none;background-color:var(--background-foreground,#fff);justify-content:space-between;align-items:center;font-weight:400;line-height:21.79px;display:flex}.arkynMultiSelectOption.md{padding:8px 16px;font-size:14px}.arkynMultiSelectOption.lg{padding:8px 16px;font-size:16px}.arkynMultiSelectOption svg{width:20px;height:20px;color:rgb(var(--spotlight-primary,17, 109, 220));display:none}.arkynMultiSelectOption:hover{cursor:pointer;filter:brightness(.95)}.arkynMultiSelectOption.active{color:var(--text-heading,#09090b);filter:brightness(.95);font-weight:600}.arkynMultiSelectOption.active svg{display:unset}}
1
+ @layer arkyn{.arkynMultiSelectOption{text-align:left;width:100%;color:var(--text-body,#52525b);-webkit-user-select:none;user-select:none;background-color:var(--background-foreground,#fff);border:none;justify-content:space-between;align-items:center;margin:0;font-family:inherit;font-weight:400;line-height:21.79px;display:flex}.arkynMultiSelectOption.md{padding:8px 16px;font-size:14px}.arkynMultiSelectOption.lg{padding:8px 16px;font-size:16px}.arkynMultiSelectOption svg{width:20px;height:20px;color:rgb(var(--spotlight-primary,17, 109, 220));display:none}.arkynMultiSelectOption:hover{cursor:pointer;filter:brightness(.95)}.arkynMultiSelectOption.active{color:var(--text-heading,#09090b);filter:brightness(.95);font-weight:600}.arkynMultiSelectOption.active svg{display:unset}.arkynMultiSelectOption.highlighted{filter:brightness(.95)}}
@@ -6,29 +6,32 @@ 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/multiSelect/multiSelectOptionsContainer/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: `arkynMultiSelectOptionsContainer ${h}`,
25
- children: [d && /* @__PURE__ */ a(t, {
22
+ return d ? /* @__PURE__ */ o("div", {
23
+ ref: h,
24
+ id: u,
25
+ role: "listbox",
26
+ "aria-multiselectable": "true",
27
+ className: `arkynMultiSelectOptionsContainer ${g}`,
28
+ children: [f && /* @__PURE__ */ a(t, {
26
29
  type: "search",
27
30
  name: "search-select",
28
31
  variant: "underline",
29
32
  leftIcon: s,
30
- value: f,
31
- onChange: _
33
+ value: p,
34
+ onChange: v
32
35
  }), l]
33
36
  }) : null;
34
37
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../../src/components/multiSelect/multiSelectOptionsContainer/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 MultiSelectOptionsContainerProps = {\n\tisFocused: boolean;\n\tisSearchable: boolean;\n\tchildren: ReactNode;\n\tsearch: string;\n\tonSearch: (value: string) => void;\n};\n\nfunction MultiSelectOptionsContainer(props: MultiSelectOptionsContainerProps) {\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={`arkynMultiSelectOptionsContainer ${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 { MultiSelectOptionsContainer };\n"],"mappings":";;;;;;;AAsBA,SAAS,EAA4B,GAAyC;CAC7E,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,oCAAoC;YAFhD,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/multiSelect/multiSelectOptionsContainer/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 MultiSelectOptionsContainerProps = {\n\tid?: string;\n\tisFocused: boolean;\n\tisSearchable: boolean;\n\tchildren: ReactNode;\n\tsearch: string;\n\tonSearch: (value: string) => void;\n};\n\nfunction MultiSelectOptionsContainer(props: MultiSelectOptionsContainerProps) {\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\taria-multiselectable=\"true\"\n\t\t\tclassName={`arkynMultiSelectOptionsContainer ${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 { MultiSelectOptionsContainer };\n"],"mappings":";;;;;;;AAuBA,SAAS,EAA4B,GAAyC;CAC7E,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,wBAAqB;EACrB,WAAW,oCAAoC;YALhD,CAOE,KACA,kBAAC,GAAD;GACC,MAAK;GACL,MAAK;GACL,SAAQ;GACR,UAAU;GACV,OAAO;GACP,UAAU;EACV,CAAA,GAGD,CACG;MAtBiB;AAwBxB"}
@@ -12,7 +12,7 @@
12
12
 
13
13
  @layer arkyn{.arkynMultiSelectMark{background:var(--background,#f4f4f5);color:var(--text-body,#52525b);text-align:left;z-index:6;-webkit-user-select:none;user-select:none;border-radius:4px;align-items:center;gap:4px;padding:2px 6px;font-size:14px;font-weight:400;line-height:19.07px;display:flex}.arkynMultiSelectMark button{background:inherit;border:none;justify-content:center;align-items:center;width:15px;height:15px;display:flex}.arkynMultiSelectMark button:disabled{cursor:not-allowed}.arkynMultiSelectMark button:hover:not(:disabled){cursor:pointer;filter:brightness(.9)}.arkynMultiSelectMark button svg{min-width:10px;min-height:10px;color:var(--text-muted,#a1a1aa)}}
14
14
 
15
- @layer arkyn{.arkynMultiSelectOption{color:var(--text-body,#52525b);-webkit-user-select:none;user-select:none;background-color:var(--background-foreground,#fff);justify-content:space-between;align-items:center;font-weight:400;line-height:21.79px;display:flex}.arkynMultiSelectOption.md{padding:8px 16px;font-size:14px}.arkynMultiSelectOption.lg{padding:8px 16px;font-size:16px}.arkynMultiSelectOption svg{width:20px;height:20px;color:rgb(var(--spotlight-primary,17, 109, 220));display:none}.arkynMultiSelectOption:hover{cursor:pointer;filter:brightness(.95)}.arkynMultiSelectOption.active{color:var(--text-heading,#09090b);filter:brightness(.95);font-weight:600}.arkynMultiSelectOption.active svg{display:unset}}
15
+ @layer arkyn{.arkynMultiSelectOption{text-align:left;width:100%;color:var(--text-body,#52525b);-webkit-user-select:none;user-select:none;background-color:var(--background-foreground,#fff);border:none;justify-content:space-between;align-items:center;margin:0;font-family:inherit;font-weight:400;line-height:21.79px;display:flex}.arkynMultiSelectOption.md{padding:8px 16px;font-size:14px}.arkynMultiSelectOption.lg{padding:8px 16px;font-size:16px}.arkynMultiSelectOption svg{width:20px;height:20px;color:rgb(var(--spotlight-primary,17, 109, 220));display:none}.arkynMultiSelectOption:hover{cursor:pointer;filter:brightness(.95)}.arkynMultiSelectOption.active{color:var(--text-heading,#09090b);filter:brightness(.95);font-weight:600}.arkynMultiSelectOption.active svg{display:unset}.arkynMultiSelectOption.highlighted{filter:brightness(.95)}}
16
16
 
17
17
  @layer arkyn{.arkynMultiSelectOptionsContainer{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}.arkynMultiSelectOptionsContainer.bottom{top:calc(100% + 5px)}.arkynMultiSelectOptionsContainer.top{bottom:calc(100% + 5px)}.arkynMultiSelectOptionsContainer>p{text-align:center;color:var(--text-body,#52525b);padding:16px;font-size:14px;font-weight:400;line-height:21.79px}}
18
18
 
@@ -1,32 +1,38 @@
1
1
  import { useScrollLock as e } from "../../hooks/useScrollLock.js";
2
+ import { useEscapeKey as t } from "../../hooks/useEscapeKey.js";
3
+ import { useFocusTrap as n } from "../../hooks/useFocusTrap.js";
2
4
  /* empty css */
3
- import { useState as t } from "react";
4
- import { jsx as n, jsxs as r } from "react/jsx-runtime";
5
+ import { useRef as r, useState as i } from "react";
6
+ import { jsx as a, jsxs as o } from "react/jsx-runtime";
5
7
  //#region src/components/popover/index.tsx
6
- function i(i) {
7
- let { children: a, button: o, closeOnClick: s, className: c = "", orientation: l = "bottomLeft" } = i, [u, d] = t(!1), f = `arkynPopover ${l} ${u ? "visibleTrue" : "visibleFalse"} ${c}`;
8
- function p() {
9
- u || d(!0);
8
+ function s(s) {
9
+ let { children: c, button: l, closeOnClick: u, className: d = "", orientation: f = "bottomLeft" } = s, [p, m] = i(!1), h = r(null), g = `arkynPopover ${f} ${p ? "visibleTrue" : "visibleFalse"} ${d}`;
10
+ function _() {
11
+ p || m(!0);
10
12
  }
11
- return e(u), /* @__PURE__ */ r("div", {
12
- className: f,
13
- onClick: p,
13
+ return e(p), t(p, () => m(!1)), n(p, h), /* @__PURE__ */ o("div", {
14
+ className: g,
15
+ onClick: _,
14
16
  children: [
15
- o,
16
- /* @__PURE__ */ n("div", {
17
- style: { visibility: u ? "visible" : "hidden" },
18
- onClick: () => s && d(!1),
17
+ l,
18
+ /* @__PURE__ */ a("div", {
19
+ ref: h,
20
+ role: "dialog",
21
+ "aria-modal": "true",
22
+ tabIndex: -1,
23
+ style: { visibility: p ? "visible" : "hidden" },
24
+ onClick: () => u && m(!1),
19
25
  className: "arkynPopoverContent",
20
- children: a
26
+ children: c
21
27
  }),
22
- u && /* @__PURE__ */ n("div", {
23
- onClick: () => d(!1),
28
+ p && /* @__PURE__ */ a("div", {
29
+ onClick: () => m(!1),
24
30
  className: "arkynPopoverOverlay"
25
31
  })
26
32
  ]
27
33
  });
28
34
  }
29
35
  //#endregion
30
- export { i as Popover };
36
+ export { s as Popover };
31
37
 
32
38
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../src/components/popover/index.tsx"],"sourcesContent":["import { type ReactNode, useState } from \"react\";\n\nimport { useScrollLock } from \"../../hooks/useScrollLock\";\nimport \"./styles.css\";\n\ntype OrientationProps =\n\t| \"bottomLeft\"\n\t| \"bottomRight\"\n\t| \"topLeft\"\n\t| \"topRight\"\n\t| \"top\"\n\t| \"left\"\n\t| \"bottom\"\n\t| \"right\";\n\ntype PopoverProps = {\n\t/** Content rendered inside the floating panel. Required. */\n\tchildren: ReactNode;\n\t/** Trigger element, clicking it opens the popover. Required. */\n\tbutton: ReactNode;\n\t/** When true, clicking the popover content also closes it. @default false */\n\tcloseOnClick?: boolean;\n\t/**\n\t * Position of the floating panel relative to the trigger.\n\t * Options: `\"bottomLeft\"` | `\"bottomRight\"` | `\"topLeft\"` | `\"topRight\"` | `\"top\"` | `\"bottom\"` | `\"left\"` | `\"right\"`.\n\t * @default \"bottomLeft\"\n\t */\n\torientation?: OrientationProps;\n\t/** Additional CSS class applied to the popover root element. */\n\tclassName?: string;\n};\n\n/**\n * Popover, floating panel that appears relative to a trigger element.\n *\n * Clicking outside the popover (or clicking the content when `closeOnClick` is set)\n * dismisses it. Locks body scroll while open.\n *\n * @param props.children - Content to display inside the panel. Required.\n * @param props.button - Trigger element that opens the popover. Required.\n * @param props.closeOnClick - Clicking the content also closes the popover. Default: false\n * @param props.orientation - Panel position relative to the trigger. Default: \"bottomLeft\"\n * @param props.className - Additional CSS class for the root element.\n *\n * @returns Popover JSX element with trigger, animated panel, and outside-click overlay.\n *\n * @example\n * ```tsx\n * // Basic dropdown menu\n * <Popover button={<Button>Options</Button>} closeOnClick>\n * <ul>\n * <li onClick={handleEdit}>Edit</li>\n * <li onClick={handleDelete}>Delete</li>\n * </ul>\n * </Popover>\n *\n * // User profile menu (bottom-right)\n * <Popover\n * button={<IconButton icon={User} aria-label=\"Account\" />}\n * orientation=\"bottomRight\"\n * closeOnClick\n * >\n * <nav>\n * <a href=\"/profile\">Profile</a>\n * <a href=\"/settings\">Settings</a>\n * <a href=\"/logout\">Sign out</a>\n * </nav>\n * </Popover>\n *\n * // Filter panel (top-left)\n * <Popover button={<Badge>Filters</Badge>} orientation=\"topLeft\">\n * <Input name=\"search\" placeholder=\"Search...\" />\n * <Select name=\"status\" options={statusOptions} />\n * </Popover>\n * ```\n */\n\nfunction Popover(props: PopoverProps) {\n\tconst {\n\t\tchildren,\n\t\tbutton,\n\t\tcloseOnClick,\n\t\tclassName: baseClassName = \"\",\n\t\torientation = \"bottomLeft\",\n\t} = props;\n\tconst [isOpen, setIsOpen] = useState(false);\n\n\tconst visible = isOpen ? \"visibleTrue\" : \"visibleFalse\";\n\tconst className = `arkynPopover ${orientation} ${visible} ${baseClassName}`;\n\n\tfunction handleOpenPopover() {\n\t\tif (!isOpen) setIsOpen(true);\n\t}\n\n\tuseScrollLock(isOpen);\n\n\treturn (\n\t\t<div className={className} onClick={handleOpenPopover}>\n\t\t\t{button}\n\n\t\t\t<div\n\t\t\t\tstyle={{ visibility: isOpen ? \"visible\" : \"hidden\" }}\n\t\t\t\tonClick={() => closeOnClick && setIsOpen(false)}\n\t\t\t\tclassName=\"arkynPopoverContent\"\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</div>\n\n\t\t\t{isOpen && (\n\t\t\t\t<div onClick={() => setIsOpen(false)} className=\"arkynPopoverOverlay\" />\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\nexport { Popover };\n"],"mappings":";;;;;AA6EA,SAAS,EAAQ,GAAqB;CACrC,IAAM,EACL,aACA,WACA,iBACA,WAAW,IAAgB,IAC3B,iBAAc,iBACX,GACE,CAAC,GAAQ,KAAa,EAAS,EAAK,GAGpC,IAAY,gBAAgB,EAAY,GAD9B,IAAS,gBAAgB,eACgB,GAAG;CAE5D,SAAS,IAAoB;EAC5B,AAAK,KAAQ,EAAU,EAAI;CAC5B;CAIA,OAFA,EAAc,CAAM,GAGnB,kBAAC,OAAD;EAAgB;EAAW,SAAS;YAApC;GACE;GAED,kBAAC,OAAD;IACC,OAAO,EAAE,YAAY,IAAS,YAAY,SAAS;IACnD,eAAe,KAAgB,EAAU,EAAK;IAC9C,WAAU;IAET;GACG,CAAA;GAEJ,KACA,kBAAC,OAAD;IAAK,eAAe,EAAU,EAAK;IAAG,WAAU;GAAuB,CAAA;EAEpE;;AAEP"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../src/components/popover/index.tsx"],"sourcesContent":["import { type ReactNode, useRef, useState } from \"react\";\n\nimport { useEscapeKey } from \"../../hooks/useEscapeKey\";\nimport { useFocusTrap } from \"../../hooks/useFocusTrap\";\nimport { useScrollLock } from \"../../hooks/useScrollLock\";\nimport \"./styles.css\";\n\ntype OrientationProps =\n\t| \"bottomLeft\"\n\t| \"bottomRight\"\n\t| \"topLeft\"\n\t| \"topRight\"\n\t| \"top\"\n\t| \"left\"\n\t| \"bottom\"\n\t| \"right\";\n\ntype PopoverProps = {\n\t/** Content rendered inside the floating panel. Required. */\n\tchildren: ReactNode;\n\t/** Trigger element, clicking it opens the popover. Required. */\n\tbutton: ReactNode;\n\t/** When true, clicking the popover content also closes it. @default false */\n\tcloseOnClick?: boolean;\n\t/**\n\t * Position of the floating panel relative to the trigger.\n\t * Options: `\"bottomLeft\"` | `\"bottomRight\"` | `\"topLeft\"` | `\"topRight\"` | `\"top\"` | `\"bottom\"` | `\"left\"` | `\"right\"`.\n\t * @default \"bottomLeft\"\n\t */\n\torientation?: OrientationProps;\n\t/** Additional CSS class applied to the popover root element. */\n\tclassName?: string;\n};\n\n/**\n * Popover, floating panel that appears relative to a trigger element.\n *\n * Clicking outside the popover (or clicking the content when `closeOnClick` is set)\n * dismisses it. Locks body scroll while open.\n *\n * @param props.children - Content to display inside the panel. Required.\n * @param props.button - Trigger element that opens the popover. Required.\n * @param props.closeOnClick - Clicking the content also closes the popover. Default: false\n * @param props.orientation - Panel position relative to the trigger. Default: \"bottomLeft\"\n * @param props.className - Additional CSS class for the root element.\n *\n * @returns Popover JSX element with trigger, animated panel, and outside-click overlay.\n *\n * @example\n * ```tsx\n * // Basic dropdown menu\n * <Popover button={<Button>Options</Button>} closeOnClick>\n * <ul>\n * <li onClick={handleEdit}>Edit</li>\n * <li onClick={handleDelete}>Delete</li>\n * </ul>\n * </Popover>\n *\n * // User profile menu (bottom-right)\n * <Popover\n * button={<IconButton icon={User} aria-label=\"Account\" />}\n * orientation=\"bottomRight\"\n * closeOnClick\n * >\n * <nav>\n * <a href=\"/profile\">Profile</a>\n * <a href=\"/settings\">Settings</a>\n * <a href=\"/logout\">Sign out</a>\n * </nav>\n * </Popover>\n *\n * // Filter panel (top-left)\n * <Popover button={<Badge>Filters</Badge>} orientation=\"topLeft\">\n * <Input name=\"search\" placeholder=\"Search...\" />\n * <Select name=\"status\" options={statusOptions} />\n * </Popover>\n * ```\n */\n\nfunction Popover(props: PopoverProps) {\n\tconst {\n\t\tchildren,\n\t\tbutton,\n\t\tcloseOnClick,\n\t\tclassName: baseClassName = \"\",\n\t\torientation = \"bottomLeft\",\n\t} = props;\n\tconst [isOpen, setIsOpen] = useState(false);\n\tconst contentRef = useRef<HTMLDivElement>(null);\n\n\tconst visible = isOpen ? \"visibleTrue\" : \"visibleFalse\";\n\tconst className = `arkynPopover ${orientation} ${visible} ${baseClassName}`;\n\n\tfunction handleOpenPopover() {\n\t\tif (!isOpen) setIsOpen(true);\n\t}\n\n\tuseScrollLock(isOpen);\n\tuseEscapeKey(isOpen, () => setIsOpen(false));\n\tuseFocusTrap(isOpen, contentRef);\n\n\treturn (\n\t\t<div className={className} onClick={handleOpenPopover}>\n\t\t\t{button}\n\n\t\t\t<div\n\t\t\t\tref={contentRef}\n\t\t\t\trole=\"dialog\"\n\t\t\t\taria-modal=\"true\"\n\t\t\t\ttabIndex={-1}\n\t\t\t\tstyle={{ visibility: isOpen ? \"visible\" : \"hidden\" }}\n\t\t\t\tonClick={() => closeOnClick && setIsOpen(false)}\n\t\t\t\tclassName=\"arkynPopoverContent\"\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</div>\n\n\t\t\t{isOpen && (\n\t\t\t\t<div onClick={() => setIsOpen(false)} className=\"arkynPopoverOverlay\" />\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\nexport { Popover };\n"],"mappings":";;;;;;;AA+EA,SAAS,EAAQ,GAAqB;CACrC,IAAM,EACL,aACA,WACA,iBACA,WAAW,IAAgB,IAC3B,iBAAc,iBACX,GACE,CAAC,GAAQ,KAAa,EAAS,EAAK,GACpC,IAAa,EAAuB,IAAI,GAGxC,IAAY,gBAAgB,EAAY,GAD9B,IAAS,gBAAgB,eACgB,GAAG;CAE5D,SAAS,IAAoB;EAC5B,AAAK,KAAQ,EAAU,EAAI;CAC5B;CAMA,OAJA,EAAc,CAAM,GACpB,EAAa,SAAc,EAAU,EAAK,CAAC,GAC3C,EAAa,GAAQ,CAAU,GAG9B,kBAAC,OAAD;EAAgB;EAAW,SAAS;YAApC;GACE;GAED,kBAAC,OAAD;IACC,KAAK;IACL,MAAK;IACL,cAAW;IACX,UAAU;IACV,OAAO,EAAE,YAAY,IAAS,YAAY,SAAS;IACnD,eAAe,KAAgB,EAAU,EAAK;IAC9C,WAAU;IAET;GACG,CAAA;GAEJ,KACA,kBAAC,OAAD;IAAK,eAAe,EAAU,EAAK;IAAG,WAAU;GAAuB,CAAA;EAEpE;;AAEP"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../src/components/richText/index.tsx"],"sourcesContent":["import { isHotkey } from \"is-hotkey\";\nimport {\n\tAlignCenter,\n\tAlignJustify,\n\tAlignLeft,\n\tAlignRight,\n\tBold,\n\tCode,\n\tHeading1,\n\tHeading2,\n\tItalic,\n\tQuote,\n\tUnderline,\n} from \"lucide-react\";\nimport { useCallback, useId, useMemo, useRef, useState } from \"react\";\nimport { createEditor, type Descendant } from \"slate\";\nimport { withHistory } from \"slate-history\";\nimport { Editable, Slate, withReact } from \"slate-react\";\nimport { useForm } from \"../../hooks/useForm\";\nimport { clearLinkMarkAtBoundary } from \"../../services/clearLinkMarkAtBoundary\";\nimport { extractTextFromNode } from \"../../services/extractTextFromNode\";\nimport { FieldTemplate } from \"../../services/fieldTemplate\";\nimport { toggleMark } from \"../../services/toggleMark\";\nimport { hotKeys, initialValue } from \"../../templates/richTextTemplates\";\nimport type {\n\tRichTextHiddenButtonKey,\n\tRichTextProps,\n} from \"../../types/richTextTypes\";\nimport { BlockButton } from \"./blockButton\";\nimport { Element } from \"./element\";\nimport { InsertImage } from \"./insertImage\";\nimport { InsertLink } from \"./insertLink\";\nimport { InsertVideo } from \"./insertVideo\";\nimport { Leaf } from \"./leaf\";\nimport { MarkButton } from \"./markButton\";\nimport { Toolbar } from \"./toolbar\";\nimport \"./styles.css\";\n\n/**\n * RichText, WYSIWYG rich-text editor built on Slate.js with a configurable toolbar.\n *\n * **Toolbar features:** bold, italic, underline, code, H1/H2, block quote, alignment (left/center/right/justify), image, video, and link insertion.\n * Pressing Space or Enter right after a link automatically stops new text from continuing to be part of that link.\n *\n * Editor content is stored as a Slate JSON string in a hidden `<input>` for form submission.\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.label - Label text displayed above the editor.\n * @param props.hiddenButtons - Toolbar button keys to hide (e.g. `[\"image\", \"code\"]`).\n * @param props.imageConfig - Enables image insertion; contains the upload endpoint and modal labels.\n * @param props.videoConfig - Customizes the video insertion modal labels.\n * @param props.linkConfig - Customizes the link insertion modal labels.\n * @param props.defaultValue - Initial editor content as a Slate JSON string. Default: \"[]\"\n * @param props.maxLimit - Maximum character count. Default: 10000\n * @param props.enforceCharacterLimit - Prevents typing past `maxLimit`. Default: false\n * @param props.onChangeCharactersCount - Callback fired on every keystroke, receives the current character count.\n * @param props.onChange - Callback fired when editor content changes, receives the Slate `Descendant[]`.\n * @param props.baseErrorMessage - Custom error message (overrides `useForm` context error).\n * @param props.isError - Forces the error visual state.\n * @param props.id - Custom id for the editable area element.\n * @param props.showAsterisk - Appends `*` to the label.\n * @param props.orientation - Layout direction. Default: \"horizontal\"\n * @param props.unShowFieldTemplate - Skips wrapper, label, and error rendering. Default: false\n *\n * @returns RichText JSX element wrapped in `FieldTemplate`.\n *\n * @example\n * ```tsx\n * // Basic\n * <RichText name=\"content\" />\n *\n * // With character limit and hidden toolbar buttons\n * <RichText\n * name=\"description\"\n * label=\"Description\"\n * maxLimit={500}\n * enforceCharacterLimit\n * hiddenButtons={[\"image\", \"video\", \"code\"]}\n * onChangeCharactersCount={(n) => setCharCount(n)}\n * />\n *\n * // With image upload support\n * <RichText\n * name=\"article\"\n * label=\"Article Body\"\n * imageConfig={{ action: \"/api/upload\" }}\n * />\n *\n * // With custom link insertion modal labels\n * <RichText\n * name=\"article\"\n * label=\"Article Body\"\n * linkConfig={{ modalTitle: \"Add a link\" }}\n * />\n * ```\n */\n\nfunction RichText(props: RichTextProps) {\n\tconst {\n\t\tname,\n\t\thiddenButtons,\n\t\timageConfig,\n\t\tvideoConfig,\n\t\tlinkConfig,\n\t\tclassName: wrapperClassName = \"\",\n\t\tdefaultValue = \"[]\",\n\t\tenforceCharacterLimit = false,\n\t\tonChangeCharactersCount,\n\t\tbaseErrorMessage,\n\t\tmaxLimit = 10000,\n\t\tonChange,\n\t\tisError: baseIsError,\n\t\tlabel,\n\t\tshowAsterisk,\n\t\tid,\n\t\torientation = \"vertical\",\n\t\tunShowFieldTemplate = false,\n\t} = props;\n\n\tconst editor = useMemo(() => withHistory(withReact(createEditor())), []);\n\n\tconst { fieldErrors } = useForm();\n\n\tconst defaultNodes = useMemo((): Descendant[] => {\n\t\ttry {\n\t\t\tconst parsedNodes = JSON.parse(defaultValue);\n\t\t\tif (!Array.isArray(parsedNodes) || parsedNodes.length === 0) {\n\t\t\t\treturn structuredClone(initialValue);\n\t\t\t}\n\n\t\t\tconst isValidNodes = parsedNodes.every(\n\t\t\t\t(node) =>\n\t\t\t\t\ttypeof node === \"object\" &&\n\t\t\t\t\tnode !== null &&\n\t\t\t\t\t\"type\" in node &&\n\t\t\t\t\t\"children\" in node,\n\t\t\t);\n\n\t\t\treturn isValidNodes ? parsedNodes : structuredClone(initialValue);\n\t\t} catch (_error) {\n\t\t\treturn structuredClone(initialValue);\n\t\t}\n\t}, [defaultValue]);\n\n\tconst textFromNodes = extractTextFromNode(defaultNodes);\n\n\tconst [charactersCount, setCharactersCount] = useState(textFromNodes.length);\n\tconst [inputValue, setInputValue] = useState(\n\t\tJSON.stringify(defaultNodes) || \"[]\",\n\t);\n\n\tconst [onFocus, setOnFocus] = useState(false);\n\n\tconst ref = useRef<HTMLInputElement>(null);\n\tconst generatedId = useId();\n\tconst inputId = id || generatedId;\n\n\tconst errorMessage = baseErrorMessage || fieldErrors?.[name];\n\tconst isError = baseIsError || !!errorMessage;\n\n\tconst renderLeaf = useCallback(Leaf, []);\n\tconst renderElement = useCallback(Element, []);\n\n\tfunction handleChange(value: Descendant[]) {\n\t\tconst text = extractTextFromNode(value);\n\n\t\tsetCharactersCount(text.length);\n\t\tonChangeCharactersCount?.(text.length);\n\n\t\tif (enforceCharacterLimit && text.length >= maxLimit) {\n\t\t\treturn;\n\t\t}\n\n\t\tsetInputValue(JSON.stringify(value));\n\t\tonChange?.(value);\n\t}\n\n\tconst focusClass = onFocus ? \"focusTrue\" : \"focusFalse\";\n\tconst errorClass = isError\n\t\t? \"errorTrue\"\n\t\t: maxLimit < charactersCount\n\t\t\t? \"errorTrue\"\n\t\t\t: \"errorFalse\";\n\n\tconst className = `arkynRichText ${errorClass} ${focusClass}`;\n\n\tconst restatesCharacters = maxLimit - charactersCount;\n\n\tfunction buttonIsNotHidden(format: RichTextHiddenButtonKey) {\n\t\treturn !hiddenButtons?.includes(format);\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<Slate\n\t\t\t\teditor={editor}\n\t\t\t\tinitialValue={defaultNodes}\n\t\t\t\tonChange={handleChange}\n\t\t\t\tonValueChange={handleChange}\n\t\t\t>\n\t\t\t\t<div className={className}>\n\t\t\t\t\t<Toolbar>\n\t\t\t\t\t\t{buttonIsNotHidden(\"headingOne\") && (\n\t\t\t\t\t\t\t<BlockButton format=\"headingOne\" icon={Heading1} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"headingTwo\") && (\n\t\t\t\t\t\t\t<BlockButton format=\"headingTwo\" icon={Heading2} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"blockQuote\") && (\n\t\t\t\t\t\t\t<BlockButton format=\"blockQuote\" icon={Quote} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"bold\") && (\n\t\t\t\t\t\t\t<MarkButton format=\"bold\" icon={Bold} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"italic\") && (\n\t\t\t\t\t\t\t<MarkButton format=\"italic\" icon={Italic} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"underline\") && (\n\t\t\t\t\t\t\t<MarkButton format=\"underline\" icon={Underline} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"code\") && (\n\t\t\t\t\t\t\t<MarkButton format=\"code\" icon={Code} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"left\") && (\n\t\t\t\t\t\t\t<BlockButton format=\"left\" icon={AlignLeft} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"right\") && (\n\t\t\t\t\t\t\t<BlockButton format=\"right\" icon={AlignRight} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"center\") && (\n\t\t\t\t\t\t\t<BlockButton format=\"center\" icon={AlignCenter} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"justify\") && (\n\t\t\t\t\t\t\t<BlockButton format=\"justify\" icon={AlignJustify} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{imageConfig && buttonIsNotHidden(\"image\") && (\n\t\t\t\t\t\t\t<InsertImage {...imageConfig} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"video\") && <InsertVideo {...videoConfig} />}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"link\") && <InsertLink {...linkConfig} />}\n\t\t\t\t\t</Toolbar>\n\n\t\t\t\t\t<Editable\n\t\t\t\t\t\tclassName=\"editorContainer\"\n\t\t\t\t\t\trenderElement={renderElement}\n\t\t\t\t\t\trenderLeaf={renderLeaf}\n\t\t\t\t\t\tspellCheck\n\t\t\t\t\t\tref={ref}\n\t\t\t\t\t\tid={inputId}\n\t\t\t\t\t\tonFocus={() => setOnFocus(true)}\n\t\t\t\t\t\tonBlur={() => setOnFocus(false)}\n\t\t\t\t\t\tonKeyDown={(event) => {\n\t\t\t\t\t\t\tif (event.key === \" \" || event.key === \"Enter\") {\n\t\t\t\t\t\t\t\tclearLinkMarkAtBoundary(editor);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tfor (const hotkey in hotKeys) {\n\t\t\t\t\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: intentional\n\t\t\t\t\t\t\t\tif (isHotkey(hotkey, event as any)) {\n\t\t\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\t\t\tconst mark = hotKeys[hotkey as keyof typeof hotKeys];\n\t\t\t\t\t\t\t\t\ttoggleMark(editor, mark);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\n\t\t\t\t\t{restatesCharacters < 0 && (\n\t\t\t\t\t\t<div className=\"restatesCharacters\">{restatesCharacters}</div>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\n\t\t\t\t<input\n\t\t\t\t\ttype=\"hidden\"\n\t\t\t\t\tname={name}\n\t\t\t\t\tvalue={inputValue.slice(0, maxLimit)}\n\t\t\t\t/>\n\n\t\t\t\t<input type=\"hidden\" name={`${name}Count`} value={charactersCount} />\n\t\t\t</Slate>\n\t\t</FieldTemplate>\n\t);\n}\n\nexport { RichText };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAkGA,SAAS,EAAS,GAAsB;CACvC,IAAM,EACL,SACA,kBACA,gBACA,gBACA,eACA,WAAW,IAAmB,IAC9B,kBAAe,MACf,2BAAwB,IACxB,4BACA,qBACA,cAAW,KACX,cACA,SAAS,GACT,UACA,iBACA,QACA,kBAAc,YACd,0BAAsB,OACnB,GAEE,IAAS,QAAc,EAAY,EAAU,EAAa,CAAC,CAAC,GAAG,CAAC,CAAC,GAEjE,EAAE,oBAAgB,EAAQ,GAE1B,IAAe,QAA4B;EAChD,IAAI;GACH,IAAM,IAAc,KAAK,MAAM,CAAY;GAa3C,OAZI,CAAC,MAAM,QAAQ,CAAW,KAAK,EAAY,WAAW,IAClD,gBAAgB,CAAY,IAGf,EAAY,OAC/B,MACA,OAAO,KAAS,cAChB,KACA,UAAU,KACV,cAAc,CAGT,IAAe,IAAc,gBAAgB,CAAY;EACjE,QAAiB;GAChB,OAAO,gBAAgB,CAAY;EACpC;CACD,GAAG,CAAC,CAAY,CAAC,GAIX,CAAC,GAAiB,MAAsB,EAFxB,EAAoB,CAEa,CAAA,CAAc,MAAM,GACrE,CAAC,IAAY,MAAiB,EACnC,KAAK,UAAU,CAAY,KAAK,IACjC,GAEM,CAAC,IAAS,KAAc,EAAS,EAAK,GAEtC,IAAM,GAAyB,IAAI,GACnC,KAAc,EAAM,GACpB,KAAU,MAAM,IAEhB,IAAe,KAAoB,KAAc,IACjD,KAAU,KAAe,CAAC,CAAC,GAE3B,KAAa,EAAY,IAAM,CAAC,CAAC,GACjC,KAAgB,EAAY,GAAS,CAAC,CAAC;CAE7C,SAAS,EAAa,GAAqB;EAC1C,IAAM,IAAO,EAAoB,CAAK;EAEtC,GAAmB,EAAK,MAAM,GAC9B,IAA0B,EAAK,MAAM,GAEjC,OAAyB,EAAK,UAAU,OAI5C,GAAc,KAAK,UAAU,CAAK,CAAC,GACnC,KAAW,CAAK;CACjB;CASA,IAAM,KAAY,iBANC,MAEhB,IAAW,IADX,cAGC,aAE0C,GAP3B,KAAU,cAAc,gBASrC,IAAqB,IAAW;CAEtC,SAAS,EAAkB,GAAiC;EAC3D,OAAO,CAAC,GAAe,SAAS,CAAM;CACvC;CAEA,OACC,kBAAC,GAAD;EACO;EACC;EACO;EACd,WAAW;EACG;EACO;EACR;YAEb,kBAAC,GAAD;GACS;GACR,cAAc;GACd,UAAU;GACV,eAAe;aAJhB;IAMC,kBAAC,OAAD;KAAgB;eAAhB;MACC,kBAAC,GAAD,EAAA,UAAA;OACE,EAAkB,YAAY,KAC9B,kBAAC,GAAD;QAAa,QAAO;QAAa,MAAM;OAAW,CAAA;OAGlD,EAAkB,YAAY,KAC9B,kBAAC,GAAD;QAAa,QAAO;QAAa,MAAM;OAAW,CAAA;OAGlD,EAAkB,YAAY,KAC9B,kBAAC,GAAD;QAAa,QAAO;QAAa,MAAM;OAAQ,CAAA;OAG/C,EAAkB,MAAM,KACxB,kBAAC,GAAD;QAAY,QAAO;QAAO,MAAM;OAAO,CAAA;OAGvC,EAAkB,QAAQ,KAC1B,kBAAC,GAAD;QAAY,QAAO;QAAS,MAAM;OAAS,CAAA;OAG3C,EAAkB,WAAW,KAC7B,kBAAC,GAAD;QAAY,QAAO;QAAY,MAAM;OAAY,CAAA;OAGjD,EAAkB,MAAM,KACxB,kBAAC,GAAD;QAAY,QAAO;QAAO,MAAM;OAAO,CAAA;OAGvC,EAAkB,MAAM,KACxB,kBAAC,GAAD;QAAa,QAAO;QAAO,MAAM;OAAY,CAAA;OAG7C,EAAkB,OAAO,KACzB,kBAAC,GAAD;QAAa,QAAO;QAAQ,MAAM;OAAa,CAAA;OAG/C,EAAkB,QAAQ,KAC1B,kBAAC,GAAD;QAAa,QAAO;QAAS,MAAM;OAAc,CAAA;OAGjD,EAAkB,SAAS,KAC3B,kBAAC,GAAD;QAAa,QAAO;QAAU,MAAM;OAAe,CAAA;OAGnD,KAAe,EAAkB,OAAO,KACxC,kBAAC,GAAD,EAAa,GAAI,EAAc,CAAA;OAG/B,EAAkB,OAAO,KAAK,kBAAC,IAAD,EAAa,GAAI,EAAc,CAAA;OAE7D,EAAkB,MAAM,KAAK,kBAAC,IAAD,EAAY,GAAI,EAAa,CAAA;MACnD,EAAA,CAAA;MAET,kBAAC,GAAD;OACC,WAAU;OACK;OACH;OACZ,YAAA;OACK;OACL,IAAI;OACJ,eAAe,EAAW,EAAI;OAC9B,cAAc,EAAW,EAAK;OAC9B,YAAY,MAAU;QACrB,CAAI,EAAM,QAAQ,OAAO,EAAM,QAAQ,YACtC,EAAwB,CAAM;QAG/B,KAAK,IAAM,KAAU,GAEpB,IAAI,EAAS,GAAQ,CAAY,GAAG;SACnC,EAAM,eAAe;SACrB,IAAM,IAAO,EAAQ;SACrB,EAAW,GAAQ,CAAI;QACxB;OAEF;MACA,CAAA;MAEA,IAAqB,KACrB,kBAAC,OAAD;OAAK,WAAU;iBAAsB;MAAwB,CAAA;KAE1D;;IAEL,kBAAC,SAAD;KACC,MAAK;KACC;KACN,OAAO,GAAW,MAAM,GAAG,CAAQ;IACnC,CAAA;IAED,kBAAC,SAAD;KAAO,MAAK;KAAS,MAAM,GAAG,EAAK;KAAQ,OAAO;IAAkB,CAAA;GAC9D;;CACO,CAAA;AAEjB"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../src/components/richText/index.tsx"],"sourcesContent":["import { isHotkey } from \"is-hotkey\";\nimport {\n\tAlignCenter,\n\tAlignJustify,\n\tAlignLeft,\n\tAlignRight,\n\tBold,\n\tCode,\n\tHeading1,\n\tHeading2,\n\tItalic,\n\tQuote,\n\tUnderline,\n} from \"lucide-react\";\nimport { useCallback, useId, useMemo, useRef, useState } from \"react\";\nimport { createEditor, type Descendant } from \"slate\";\nimport { withHistory } from \"slate-history\";\nimport { Editable, Slate, withReact } from \"slate-react\";\nimport { useForm } from \"../../hooks/useForm\";\nimport { clearLinkMarkAtBoundary } from \"../../services/clearLinkMarkAtBoundary\";\nimport { extractTextFromNode } from \"../../services/extractTextFromNode\";\nimport { FieldTemplate } from \"../../services/fieldTemplate\";\nimport { toggleMark } from \"../../services/toggleMark\";\nimport { hotKeys, initialValue } from \"../../templates/richTextTemplates\";\nimport type {\n\tRichTextHiddenButtonKey,\n\tRichTextProps,\n} from \"../../types/richTextTypes\";\nimport { BlockButton } from \"./blockButton\";\nimport { Element } from \"./element\";\nimport { InsertImage } from \"./insertImage\";\nimport { InsertLink } from \"./insertLink\";\nimport { InsertVideo } from \"./insertVideo\";\nimport { Leaf } from \"./leaf\";\nimport { MarkButton } from \"./markButton\";\nimport { Toolbar } from \"./toolbar\";\nimport \"./styles.css\";\n\n/**\n * RichText, WYSIWYG rich-text editor built on Slate.js with a configurable toolbar.\n *\n * **Toolbar features:** bold, italic, underline, code, H1/H2, block quote, alignment (left/center/right/justify), image, video, and link insertion.\n * Pressing Space or Enter right after a link automatically stops new text from continuing to be part of that link.\n *\n * Editor content is stored as a Slate JSON string in a hidden `<input>` for form submission.\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.label - Label text displayed above the editor.\n * @param props.hiddenButtons - Toolbar button keys to hide (e.g. `[\"image\", \"code\"]`).\n * @param props.imageConfig - Enables image insertion; contains the upload endpoint and modal labels.\n * @param props.videoConfig - Customizes the video insertion modal labels.\n * @param props.linkConfig - Customizes the link insertion modal labels.\n * @param props.defaultValue - Initial editor content as a Slate JSON string. Default: \"[]\"\n * @param props.maxLimit - Maximum character count. Default: 10000\n * @param props.enforceCharacterLimit - Prevents typing past `maxLimit`. Default: false\n * @param props.onChangeCharactersCount - Callback fired on every keystroke, receives the current character count.\n * @param props.onChange - Callback fired when editor content changes, receives the Slate `Descendant[]`.\n * @param props.baseErrorMessage - Custom error message (overrides `useForm` context error).\n * @param props.isError - Forces the error visual state.\n * @param props.id - Custom id for the editable area element.\n * @param props.showAsterisk - Appends `*` to the label.\n * @param props.orientation - Layout direction. Default: \"vertical\"\n * @param props.unShowFieldTemplate - Skips wrapper, label, and error rendering. Default: false\n *\n * @returns RichText JSX element wrapped in `FieldTemplate`.\n *\n * @example\n * ```tsx\n * // Basic\n * <RichText name=\"content\" />\n *\n * // With character limit and hidden toolbar buttons\n * <RichText\n * name=\"description\"\n * label=\"Description\"\n * maxLimit={500}\n * enforceCharacterLimit\n * hiddenButtons={[\"image\", \"video\", \"code\"]}\n * onChangeCharactersCount={(n) => setCharCount(n)}\n * />\n *\n * // With image upload support\n * <RichText\n * name=\"article\"\n * label=\"Article Body\"\n * imageConfig={{ action: \"/api/upload\" }}\n * />\n *\n * // With custom link insertion modal labels\n * <RichText\n * name=\"article\"\n * label=\"Article Body\"\n * linkConfig={{ modalTitle: \"Add a link\" }}\n * />\n * ```\n */\n\nfunction RichText(props: RichTextProps) {\n\tconst {\n\t\tname,\n\t\thiddenButtons,\n\t\timageConfig,\n\t\tvideoConfig,\n\t\tlinkConfig,\n\t\tclassName: wrapperClassName = \"\",\n\t\tdefaultValue = \"[]\",\n\t\tenforceCharacterLimit = false,\n\t\tonChangeCharactersCount,\n\t\tbaseErrorMessage,\n\t\tmaxLimit = 10000,\n\t\tonChange,\n\t\tisError: baseIsError,\n\t\tlabel,\n\t\tshowAsterisk,\n\t\tid,\n\t\torientation = \"vertical\",\n\t\tunShowFieldTemplate = false,\n\t} = props;\n\n\tconst editor = useMemo(() => withHistory(withReact(createEditor())), []);\n\n\tconst { fieldErrors } = useForm();\n\n\tconst defaultNodes = useMemo((): Descendant[] => {\n\t\ttry {\n\t\t\tconst parsedNodes = JSON.parse(defaultValue);\n\t\t\tif (!Array.isArray(parsedNodes) || parsedNodes.length === 0) {\n\t\t\t\treturn structuredClone(initialValue);\n\t\t\t}\n\n\t\t\tconst isValidNodes = parsedNodes.every(\n\t\t\t\t(node) =>\n\t\t\t\t\ttypeof node === \"object\" &&\n\t\t\t\t\tnode !== null &&\n\t\t\t\t\t\"type\" in node &&\n\t\t\t\t\t\"children\" in node,\n\t\t\t);\n\n\t\t\treturn isValidNodes ? parsedNodes : structuredClone(initialValue);\n\t\t} catch (_error) {\n\t\t\treturn structuredClone(initialValue);\n\t\t}\n\t}, [defaultValue]);\n\n\tconst textFromNodes = extractTextFromNode(defaultNodes);\n\n\tconst [charactersCount, setCharactersCount] = useState(textFromNodes.length);\n\tconst [inputValue, setInputValue] = useState(\n\t\tJSON.stringify(defaultNodes) || \"[]\",\n\t);\n\n\tconst [onFocus, setOnFocus] = useState(false);\n\n\tconst ref = useRef<HTMLInputElement>(null);\n\tconst generatedId = useId();\n\tconst inputId = id || generatedId;\n\n\tconst errorMessage = baseErrorMessage || fieldErrors?.[name];\n\tconst isError = baseIsError || !!errorMessage;\n\n\tconst renderLeaf = useCallback(Leaf, []);\n\tconst renderElement = useCallback(Element, []);\n\n\tfunction handleChange(value: Descendant[]) {\n\t\tconst text = extractTextFromNode(value);\n\n\t\tsetCharactersCount(text.length);\n\t\tonChangeCharactersCount?.(text.length);\n\n\t\tif (enforceCharacterLimit && text.length >= maxLimit) {\n\t\t\treturn;\n\t\t}\n\n\t\tsetInputValue(JSON.stringify(value));\n\t\tonChange?.(value);\n\t}\n\n\tconst focusClass = onFocus ? \"focusTrue\" : \"focusFalse\";\n\tconst errorClass = isError\n\t\t? \"errorTrue\"\n\t\t: maxLimit < charactersCount\n\t\t\t? \"errorTrue\"\n\t\t\t: \"errorFalse\";\n\n\tconst className = `arkynRichText ${errorClass} ${focusClass}`;\n\n\tconst restatesCharacters = maxLimit - charactersCount;\n\n\tfunction buttonIsNotHidden(format: RichTextHiddenButtonKey) {\n\t\treturn !hiddenButtons?.includes(format);\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<Slate\n\t\t\t\teditor={editor}\n\t\t\t\tinitialValue={defaultNodes}\n\t\t\t\tonChange={handleChange}\n\t\t\t\tonValueChange={handleChange}\n\t\t\t>\n\t\t\t\t<div className={className}>\n\t\t\t\t\t<Toolbar>\n\t\t\t\t\t\t{buttonIsNotHidden(\"headingOne\") && (\n\t\t\t\t\t\t\t<BlockButton format=\"headingOne\" icon={Heading1} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"headingTwo\") && (\n\t\t\t\t\t\t\t<BlockButton format=\"headingTwo\" icon={Heading2} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"blockQuote\") && (\n\t\t\t\t\t\t\t<BlockButton format=\"blockQuote\" icon={Quote} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"bold\") && (\n\t\t\t\t\t\t\t<MarkButton format=\"bold\" icon={Bold} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"italic\") && (\n\t\t\t\t\t\t\t<MarkButton format=\"italic\" icon={Italic} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"underline\") && (\n\t\t\t\t\t\t\t<MarkButton format=\"underline\" icon={Underline} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"code\") && (\n\t\t\t\t\t\t\t<MarkButton format=\"code\" icon={Code} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"left\") && (\n\t\t\t\t\t\t\t<BlockButton format=\"left\" icon={AlignLeft} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"right\") && (\n\t\t\t\t\t\t\t<BlockButton format=\"right\" icon={AlignRight} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"center\") && (\n\t\t\t\t\t\t\t<BlockButton format=\"center\" icon={AlignCenter} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"justify\") && (\n\t\t\t\t\t\t\t<BlockButton format=\"justify\" icon={AlignJustify} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{imageConfig && buttonIsNotHidden(\"image\") && (\n\t\t\t\t\t\t\t<InsertImage {...imageConfig} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"video\") && <InsertVideo {...videoConfig} />}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"link\") && <InsertLink {...linkConfig} />}\n\t\t\t\t\t</Toolbar>\n\n\t\t\t\t\t<Editable\n\t\t\t\t\t\tclassName=\"editorContainer\"\n\t\t\t\t\t\trenderElement={renderElement}\n\t\t\t\t\t\trenderLeaf={renderLeaf}\n\t\t\t\t\t\tspellCheck\n\t\t\t\t\t\tref={ref}\n\t\t\t\t\t\tid={inputId}\n\t\t\t\t\t\tonFocus={() => setOnFocus(true)}\n\t\t\t\t\t\tonBlur={() => setOnFocus(false)}\n\t\t\t\t\t\tonKeyDown={(event) => {\n\t\t\t\t\t\t\tif (event.key === \" \" || event.key === \"Enter\") {\n\t\t\t\t\t\t\t\tclearLinkMarkAtBoundary(editor);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tfor (const hotkey in hotKeys) {\n\t\t\t\t\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: intentional\n\t\t\t\t\t\t\t\tif (isHotkey(hotkey, event as any)) {\n\t\t\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\t\t\tconst mark = hotKeys[hotkey as keyof typeof hotKeys];\n\t\t\t\t\t\t\t\t\ttoggleMark(editor, mark);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\n\t\t\t\t\t{restatesCharacters < 0 && (\n\t\t\t\t\t\t<div className=\"restatesCharacters\">{restatesCharacters}</div>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\n\t\t\t\t<input\n\t\t\t\t\ttype=\"hidden\"\n\t\t\t\t\tname={name}\n\t\t\t\t\tvalue={inputValue.slice(0, maxLimit)}\n\t\t\t\t/>\n\n\t\t\t\t<input type=\"hidden\" name={`${name}Count`} value={charactersCount} />\n\t\t\t</Slate>\n\t\t</FieldTemplate>\n\t);\n}\n\nexport { RichText };\n"],"mappings":"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"}
@@ -8,7 +8,7 @@ function i(i) {
8
8
  return /* @__PURE__ */ n(r, {
9
9
  onLoad: (e) => u(e),
10
10
  onPlacesChanged: () => {
11
- let e = l?.getPlaces(), t = e ? e[0] : null, n = t?.address_components;
11
+ let e = l?.getPlaces(), t = e ? e[0] : null, n = t?.address_components ?? [];
12
12
  function r(e) {
13
13
  let t = n.find((t) => t.types[0] === e);
14
14
  return t ? t.long_name : "";
@@ -1 +1 @@
1
- {"version":3,"file":"searchPlaces.js","names":[],"sources":["../../../src/components/searchPlaces.tsx"],"sourcesContent":["import type { StandaloneSearchBoxProps } from \"@react-google-maps/api\";\nimport { StandaloneSearchBox } from \"@react-google-maps/api\";\nimport { type JSX, useState } from \"react\";\nimport { Input, type InputProps } from \"./input\";\n\ntype AddressComponentsType = {\n\tlong_name: string;\n\tshort_name: string;\n\ttypes: string[];\n}[];\n\n/** Structured address data extracted from a Google Places result. */\ntype PlaceData = {\n\t/** Street name (e.g. `\"Rua Exemplo\"`). */\n\tstreet: string;\n\t/** City name (e.g. `\"São Paulo\"`). */\n\tcity: string;\n\t/** Full state name (e.g. `\"São Paulo\"`). */\n\tstate: string;\n\t/** Neighborhood / district name. */\n\tneighborhood: string;\n\t/** Postal / ZIP code. */\n\tpostalCode: string;\n\t/** State abbreviation (e.g. `\"SP\"`). */\n\tstateShortName: string;\n\t/** Street number (e.g. `\"123\"`). */\n\tstreetNumber: string;\n\t/** Geographic coordinates of the place. */\n\tcoordinates: { lat: number; lng: number };\n};\n\ntype SearchPlacesProps = {\n\t/** Google Maps `StandaloneSearchBox` options (e.g. `componentRestrictions`, `bounds`). */\n\toptions?: StandaloneSearchBoxProps[\"options\"];\n\t/** Callback fired every time the input text changes. Receives the current string value. */\n\tonChange?: (e: string) => void;\n\t/**\n\t * Callback fired when the user selects a place from the autocomplete suggestions.\n\t * Receives a structured {@link PlaceData} object.\n\t */\n\tonPlaceChanged?: (e: PlaceData) => void;\n} & Omit<InputProps, \"onLoad\" | \"onChange\" | \"type\">;\n\n/**\n * SearchPlaces, text input with Google Places autocomplete that returns structured address data.\n *\n * Requires the Google Maps JavaScript API with the Places library to be loaded.\n * Built on `@react-google-maps/api`'s `StandaloneSearchBox`.\n *\n * @param props.options - Google Maps search box options (e.g. restrict by country).\n * @param props.onChange - Fires on every keystroke, receives the current text value.\n * @param props.onPlaceChanged - Fires when the user selects a suggestion, receives structured address data.\n *\n * **...Other valid `Input` properties (except `onLoad`, `onChange`, `type`)**\n *\n * @returns SearchPlaces JSX element (an `Input` wrapped in `StandaloneSearchBox`).\n *\n * @example\n * ```tsx\n * <SearchPlaces\n * name=\"address\"\n * label=\"Address\"\n * placeholder=\"Start typing an address…\"\n * options={{ componentRestrictions: { country: \"br\" } }}\n * onChange={(v) => setRawAddress(v)}\n * onPlaceChanged={(place) => {\n * setAddress({\n * street: place.street,\n * city: place.city,\n * state: place.state,\n * postalCode: place.postalCode,\n * coordinates: place.coordinates,\n * });\n * }}\n * />\n * ```\n */\n\nfunction SearchPlaces(props: SearchPlacesProps): JSX.Element {\n\tconst { onChange, onPlaceChanged, options, ...rest } = props;\n\n\t// biome-ignore lint/suspicious/noExplicitAny: intentional\n\tconst [searchBox, setSearchBox] = useState<any>(null);\n\t// biome-ignore lint/suspicious/noExplicitAny: intentional\n\tconst handleLoad = (ref: any) => setSearchBox(ref);\n\n\tconst handlePlacesChanged = () => {\n\t\tconst places = searchBox?.getPlaces();\n\t\tconst place = places ? places[0] : null;\n\n\t\tconst address_components =\n\t\t\tplace?.address_components as AddressComponentsType;\n\n\t\tfunction findData(key: string) {\n\t\t\tconst data = address_components.find((item) => item.types[0] === key);\n\t\t\tif (data) return data.long_name;\n\t\t\treturn \"\";\n\t\t}\n\n\t\tfunction findDataShort(key: string) {\n\t\t\tconst data = address_components.find((item) => item.types[0] === key);\n\t\t\tif (data) return data.short_name;\n\t\t\treturn \"\";\n\t\t}\n\n\t\tfunction findDataByMultipleTypes(keys: string[]) {\n\t\t\tfor (const key of keys) {\n\t\t\t\tconst data = address_components.find((item) =>\n\t\t\t\t\titem.types.includes(key),\n\t\t\t\t);\n\t\t\t\tif (data) return data.long_name;\n\t\t\t}\n\t\t\treturn \"\";\n\t\t}\n\n\t\tif (place) {\n\t\t\tconst street = findData(\"route\");\n\t\t\tconst streetNumber = findData(\"street_number\");\n\t\t\tconst neighborhood = findDataByMultipleTypes([\n\t\t\t\t\"sublocality_level_1\",\n\t\t\t\t\"sublocality\",\n\t\t\t\t\"neighborhood\",\n\t\t\t]);\n\t\t\tconst city = findData(\"administrative_area_level_2\");\n\t\t\tconst state = findData(\"administrative_area_level_1\");\n\t\t\tconst stateShortName = findDataShort(\"administrative_area_level_1\");\n\t\t\tconst postalCode = findDataByMultipleTypes([\n\t\t\t\t\"postal_code\",\n\t\t\t\t\"postal_code_prefix\",\n\t\t\t]);\n\n\t\t\tconst lat = place.geometry?.location?.lat();\n\t\t\tconst lng = place.geometry?.location?.lng();\n\n\t\t\tconst sendPlace = {\n\t\t\t\tstreet,\n\t\t\t\tcity,\n\t\t\t\tstate,\n\t\t\t\tneighborhood,\n\t\t\t\tpostalCode,\n\t\t\t\tstreetNumber,\n\t\t\t\tstateShortName,\n\t\t\t\tcoordinates: { lat, lng },\n\t\t\t};\n\n\t\t\tonPlaceChanged?.(sendPlace);\n\t\t}\n\t};\n\n\treturn (\n\t\t<StandaloneSearchBox\n\t\t\tonLoad={handleLoad}\n\t\t\tonPlacesChanged={handlePlacesChanged}\n\t\t\toptions={options}\n\t\t>\n\t\t\t<Input\n\t\t\t\ttype=\"text\"\n\t\t\t\tautoComplete=\"off\"\n\t\t\t\tonChange={(e) => onChange?.(e.target.value)}\n\t\t\t\t{...rest}\n\t\t\t/>\n\t\t</StandaloneSearchBox>\n\t);\n}\n\nexport { SearchPlaces };\n"],"mappings":";;;;;AA8EA,SAAS,EAAa,GAAuC;CAC5D,IAAM,EAAE,aAAU,mBAAgB,YAAS,GAAG,MAAS,GAGjD,CAAC,GAAW,KAAgB,EAAc,IAAI;CAmEpD,OACC,kBAAC,GAAD;EACC,SAnEkB,MAAa,EAAa,CAAG;EAoE/C,uBAlEgC;GACjC,IAAM,IAAS,GAAW,UAAU,GAC9B,IAAQ,IAAS,EAAO,KAAK,MAE7B,IACL,GAAO;GAER,SAAS,EAAS,GAAa;IAC9B,IAAM,IAAO,EAAmB,MAAM,MAAS,EAAK,MAAM,OAAO,CAAG;IAEpE,OADI,IAAa,EAAK,YACf;GACR;GAEA,SAAS,EAAc,GAAa;IACnC,IAAM,IAAO,EAAmB,MAAM,MAAS,EAAK,MAAM,OAAO,CAAG;IAEpE,OADI,IAAa,EAAK,aACf;GACR;GAEA,SAAS,EAAwB,GAAgB;IAChD,KAAK,IAAM,KAAO,GAAM;KACvB,IAAM,IAAO,EAAmB,MAAM,MACrC,EAAK,MAAM,SAAS,CAAG,CACxB;KACA,IAAI,GAAM,OAAO,EAAK;IACvB;IACA,OAAO;GACR;GAEA,IAAI,GAAO;IACV,IAAM,IAAS,EAAS,OAAO,GACzB,IAAe,EAAS,eAAe,GACvC,IAAe,EAAwB;KAC5C;KACA;KACA;IACD,CAAC,GACK,IAAO,EAAS,6BAA6B,GAC7C,IAAQ,EAAS,6BAA6B,GAC9C,IAAiB,EAAc,6BAA6B,GAS5D,IAAY;KACjB;KACA;KACA;KACA;KACA,YAbkB,EAAwB,CAC1C,eACA,oBACD,CAUC;KACA;KACA;KACA,aAAa;MAAE,KAXJ,EAAM,UAAU,UAAU,IAAI;MAWrB,KAVT,EAAM,UAAU,UAAU,IAAI;KAUjB;IACzB;IAEA,IAAiB,CAAS;GAC3B;EACD;EAMW;YAET,kBAAC,GAAD;GACC,MAAK;GACL,cAAa;GACb,WAAW,MAAM,IAAW,EAAE,OAAO,KAAK;GAC1C,GAAI;EACJ,CAAA;CACmB,CAAA;AAEvB"}
1
+ {"version":3,"file":"searchPlaces.js","names":[],"sources":["../../../src/components/searchPlaces.tsx"],"sourcesContent":["import type { StandaloneSearchBoxProps } from \"@react-google-maps/api\";\nimport { StandaloneSearchBox } from \"@react-google-maps/api\";\nimport { type JSX, useState } from \"react\";\nimport { Input, type InputProps } from \"./input\";\n\ntype AddressComponentsType = {\n\tlong_name: string;\n\tshort_name: string;\n\ttypes: string[];\n}[];\n\n/** Structured address data extracted from a Google Places result. */\ntype PlaceData = {\n\t/** Street name (e.g. `\"Rua Exemplo\"`). */\n\tstreet: string;\n\t/** City name (e.g. `\"São Paulo\"`). */\n\tcity: string;\n\t/** Full state name (e.g. `\"São Paulo\"`). */\n\tstate: string;\n\t/** Neighborhood / district name. */\n\tneighborhood: string;\n\t/** Postal / ZIP code. */\n\tpostalCode: string;\n\t/** State abbreviation (e.g. `\"SP\"`). */\n\tstateShortName: string;\n\t/** Street number (e.g. `\"123\"`). */\n\tstreetNumber: string;\n\t/** Geographic coordinates of the place. */\n\tcoordinates: { lat: number; lng: number };\n};\n\ntype SearchPlacesProps = {\n\t/** Google Maps `StandaloneSearchBox` options (e.g. `componentRestrictions`, `bounds`). */\n\toptions?: StandaloneSearchBoxProps[\"options\"];\n\t/** Callback fired every time the input text changes. Receives the current string value. */\n\tonChange?: (e: string) => void;\n\t/**\n\t * Callback fired when the user selects a place from the autocomplete suggestions.\n\t * Receives a structured {@link PlaceData} object.\n\t */\n\tonPlaceChanged?: (e: PlaceData) => void;\n} & Omit<InputProps, \"onLoad\" | \"onChange\" | \"type\">;\n\n/**\n * SearchPlaces, text input with Google Places autocomplete that returns structured address data.\n *\n * Requires the Google Maps JavaScript API with the Places library to be loaded.\n * Built on `@react-google-maps/api`'s `StandaloneSearchBox`.\n *\n * @param props.options - Google Maps search box options (e.g. restrict by country).\n * @param props.onChange - Fires on every keystroke, receives the current text value.\n * @param props.onPlaceChanged - Fires when the user selects a suggestion, receives structured address data.\n *\n * **...Other valid `Input` properties (except `onLoad`, `onChange`, `type`)**\n *\n * @returns SearchPlaces JSX element (an `Input` wrapped in `StandaloneSearchBox`).\n *\n * @example\n * ```tsx\n * <SearchPlaces\n * name=\"address\"\n * label=\"Address\"\n * placeholder=\"Start typing an address…\"\n * options={{ componentRestrictions: { country: \"br\" } }}\n * onChange={(v) => setRawAddress(v)}\n * onPlaceChanged={(place) => {\n * setAddress({\n * street: place.street,\n * city: place.city,\n * state: place.state,\n * postalCode: place.postalCode,\n * coordinates: place.coordinates,\n * });\n * }}\n * />\n * ```\n */\n\nfunction SearchPlaces(props: SearchPlacesProps): JSX.Element {\n\tconst { onChange, onPlaceChanged, options, ...rest } = props;\n\n\t// biome-ignore lint/suspicious/noExplicitAny: intentional\n\tconst [searchBox, setSearchBox] = useState<any>(null);\n\t// biome-ignore lint/suspicious/noExplicitAny: intentional\n\tconst handleLoad = (ref: any) => setSearchBox(ref);\n\n\tconst handlePlacesChanged = () => {\n\t\tconst places = searchBox?.getPlaces();\n\t\tconst place = places ? places[0] : null;\n\n\t\tconst address_components = (place?.address_components ??\n\t\t\t[]) as AddressComponentsType;\n\n\t\tfunction findData(key: string) {\n\t\t\tconst data = address_components.find((item) => item.types[0] === key);\n\t\t\tif (data) return data.long_name;\n\t\t\treturn \"\";\n\t\t}\n\n\t\tfunction findDataShort(key: string) {\n\t\t\tconst data = address_components.find((item) => item.types[0] === key);\n\t\t\tif (data) return data.short_name;\n\t\t\treturn \"\";\n\t\t}\n\n\t\tfunction findDataByMultipleTypes(keys: string[]) {\n\t\t\tfor (const key of keys) {\n\t\t\t\tconst data = address_components.find((item) =>\n\t\t\t\t\titem.types.includes(key),\n\t\t\t\t);\n\t\t\t\tif (data) return data.long_name;\n\t\t\t}\n\t\t\treturn \"\";\n\t\t}\n\n\t\tif (place) {\n\t\t\tconst street = findData(\"route\");\n\t\t\tconst streetNumber = findData(\"street_number\");\n\t\t\tconst neighborhood = findDataByMultipleTypes([\n\t\t\t\t\"sublocality_level_1\",\n\t\t\t\t\"sublocality\",\n\t\t\t\t\"neighborhood\",\n\t\t\t]);\n\t\t\tconst city = findData(\"administrative_area_level_2\");\n\t\t\tconst state = findData(\"administrative_area_level_1\");\n\t\t\tconst stateShortName = findDataShort(\"administrative_area_level_1\");\n\t\t\tconst postalCode = findDataByMultipleTypes([\n\t\t\t\t\"postal_code\",\n\t\t\t\t\"postal_code_prefix\",\n\t\t\t]);\n\n\t\t\tconst lat = place.geometry?.location?.lat();\n\t\t\tconst lng = place.geometry?.location?.lng();\n\n\t\t\tconst sendPlace = {\n\t\t\t\tstreet,\n\t\t\t\tcity,\n\t\t\t\tstate,\n\t\t\t\tneighborhood,\n\t\t\t\tpostalCode,\n\t\t\t\tstreetNumber,\n\t\t\t\tstateShortName,\n\t\t\t\tcoordinates: { lat, lng },\n\t\t\t};\n\n\t\t\tonPlaceChanged?.(sendPlace);\n\t\t}\n\t};\n\n\treturn (\n\t\t<StandaloneSearchBox\n\t\t\tonLoad={handleLoad}\n\t\t\tonPlacesChanged={handlePlacesChanged}\n\t\t\toptions={options}\n\t\t>\n\t\t\t<Input\n\t\t\t\ttype=\"text\"\n\t\t\t\tautoComplete=\"off\"\n\t\t\t\tonChange={(e) => onChange?.(e.target.value)}\n\t\t\t\t{...rest}\n\t\t\t/>\n\t\t</StandaloneSearchBox>\n\t);\n}\n\nexport { SearchPlaces };\n"],"mappings":";;;;;AA8EA,SAAS,EAAa,GAAuC;CAC5D,IAAM,EAAE,aAAU,mBAAgB,YAAS,GAAG,MAAS,GAGjD,CAAC,GAAW,KAAgB,EAAc,IAAI;CAmEpD,OACC,kBAAC,GAAD;EACC,SAnEkB,MAAa,EAAa,CAAG;EAoE/C,uBAlEgC;GACjC,IAAM,IAAS,GAAW,UAAU,GAC9B,IAAQ,IAAS,EAAO,KAAK,MAE7B,IAAsB,GAAO,sBAClC,CAAC;GAEF,SAAS,EAAS,GAAa;IAC9B,IAAM,IAAO,EAAmB,MAAM,MAAS,EAAK,MAAM,OAAO,CAAG;IAEpE,OADI,IAAa,EAAK,YACf;GACR;GAEA,SAAS,EAAc,GAAa;IACnC,IAAM,IAAO,EAAmB,MAAM,MAAS,EAAK,MAAM,OAAO,CAAG;IAEpE,OADI,IAAa,EAAK,aACf;GACR;GAEA,SAAS,EAAwB,GAAgB;IAChD,KAAK,IAAM,KAAO,GAAM;KACvB,IAAM,IAAO,EAAmB,MAAM,MACrC,EAAK,MAAM,SAAS,CAAG,CACxB;KACA,IAAI,GAAM,OAAO,EAAK;IACvB;IACA,OAAO;GACR;GAEA,IAAI,GAAO;IACV,IAAM,IAAS,EAAS,OAAO,GACzB,IAAe,EAAS,eAAe,GACvC,IAAe,EAAwB;KAC5C;KACA;KACA;IACD,CAAC,GACK,IAAO,EAAS,6BAA6B,GAC7C,IAAQ,EAAS,6BAA6B,GAC9C,IAAiB,EAAc,6BAA6B,GAS5D,IAAY;KACjB;KACA;KACA;KACA;KACA,YAbkB,EAAwB,CAC1C,eACA,oBACD,CAUC;KACA;KACA;KACA,aAAa;MAAE,KAXJ,EAAM,UAAU,UAAU,IAAI;MAWrB,KAVT,EAAM,UAAU,UAAU,IAAI;KAUjB;IACzB;IAEA,IAAiB,CAAS;GAC3B;EACD;EAMW;YAET,kBAAC,GAAD;GACC,MAAK;GACL,cAAa;GACb,WAAW,MAAM,IAAW,EAAE,OAAO,KAAK;GAC1C,GAAI;EACJ,CAAA;CACmB,CAAA;AAEvB"}