@lax-wp/design-system 0.13.33 → 0.13.34

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 (157) hide show
  1. package/dist/components/button/Button.cjs.js +5 -5
  2. package/dist/components/button/Button.cjs.js.map +1 -1
  3. package/dist/components/button/Button.es.js +18 -18
  4. package/dist/components/button/Button.es.js.map +1 -1
  5. package/dist/components/button/IconButton.cjs.js +1 -1
  6. package/dist/components/button/IconButton.cjs.js.map +1 -1
  7. package/dist/components/button/IconButton.es.js +8 -8
  8. package/dist/components/button/IconButton.es.js.map +1 -1
  9. package/dist/components/buttons/option-button/OptionButton.cjs.js +1 -1
  10. package/dist/components/buttons/option-button/OptionButton.cjs.js.map +1 -1
  11. package/dist/components/buttons/option-button/OptionButton.es.js +1 -1
  12. package/dist/components/buttons/option-button/OptionButton.es.js.map +1 -1
  13. package/dist/components/data-display/comparison/components/Header.cjs.js +1 -1
  14. package/dist/components/data-display/comparison/components/Header.cjs.js.map +1 -1
  15. package/dist/components/data-display/comparison/components/Header.es.js +13 -13
  16. package/dist/components/data-display/comparison/components/Header.es.js.map +1 -1
  17. package/dist/components/data-display/infinite-table/body/cell/DataCell.cjs.js +1 -1
  18. package/dist/components/data-display/infinite-table/body/cell/DataCell.cjs.js.map +1 -1
  19. package/dist/components/data-display/infinite-table/body/cell/DataCell.es.js +1 -1
  20. package/dist/components/data-display/infinite-table/body/cell/DataCell.es.js.map +1 -1
  21. package/dist/components/data-display/infinite-table/body/rows/index.cjs.js +1 -1
  22. package/dist/components/data-display/infinite-table/body/rows/index.cjs.js.map +1 -1
  23. package/dist/components/data-display/infinite-table/body/rows/index.es.js +104 -101
  24. package/dist/components/data-display/infinite-table/body/rows/index.es.js.map +1 -1
  25. package/dist/components/data-display/infinite-table/constants.cjs.js +1 -1
  26. package/dist/components/data-display/infinite-table/constants.cjs.js.map +1 -1
  27. package/dist/components/data-display/infinite-table/constants.d.ts +6 -0
  28. package/dist/components/data-display/infinite-table/constants.es.js +17 -16
  29. package/dist/components/data-display/infinite-table/constants.es.js.map +1 -1
  30. package/dist/components/data-display/infinite-table/index.cjs.js +1 -1
  31. package/dist/components/data-display/infinite-table/index.cjs.js.map +1 -1
  32. package/dist/components/data-display/infinite-table/index.es.js +188 -187
  33. package/dist/components/data-display/infinite-table/index.es.js.map +1 -1
  34. package/dist/components/data-display/infinite-table/useRowHeight.cjs.js +2 -0
  35. package/dist/components/data-display/infinite-table/useRowHeight.cjs.js.map +1 -0
  36. package/dist/components/data-display/infinite-table/useRowHeight.d.ts +15 -0
  37. package/dist/components/data-display/infinite-table/useRowHeight.es.js +24 -0
  38. package/dist/components/data-display/infinite-table/useRowHeight.es.js.map +1 -0
  39. package/dist/components/data-display/tag/Tag.cjs.js +1 -1
  40. package/dist/components/data-display/tag/Tag.cjs.js.map +1 -1
  41. package/dist/components/data-display/tag/Tag.es.js +11 -9
  42. package/dist/components/data-display/tag/Tag.es.js.map +1 -1
  43. package/dist/components/floating-bar/FloatingBar.cjs.js +1 -1
  44. package/dist/components/floating-bar/FloatingBar.cjs.js.map +1 -1
  45. package/dist/components/floating-bar/FloatingBar.es.js +9 -9
  46. package/dist/components/floating-bar/FloatingBar.es.js.map +1 -1
  47. package/dist/components/forms/base-input-field/BaseInputField.cjs.js +2 -2
  48. package/dist/components/forms/base-input-field/BaseInputField.cjs.js.map +1 -1
  49. package/dist/components/forms/base-input-field/BaseInputField.es.js +40 -42
  50. package/dist/components/forms/base-input-field/BaseInputField.es.js.map +1 -1
  51. package/dist/components/forms/creatable-select/CreatableSelect.cjs.js +1 -1
  52. package/dist/components/forms/creatable-select/CreatableSelect.cjs.js.map +1 -1
  53. package/dist/components/forms/creatable-select/CreatableSelect.es.js +14 -15
  54. package/dist/components/forms/creatable-select/CreatableSelect.es.js.map +1 -1
  55. package/dist/components/forms/currency-input/CurrencyInputField.cjs.js +1 -1
  56. package/dist/components/forms/currency-input/CurrencyInputField.cjs.js.map +1 -1
  57. package/dist/components/forms/currency-input/CurrencyInputField.es.js +57 -65
  58. package/dist/components/forms/currency-input/CurrencyInputField.es.js.map +1 -1
  59. package/dist/components/forms/date-time-field/DateTimeField.cjs.js +1 -1
  60. package/dist/components/forms/date-time-field/DateTimeField.cjs.js.map +1 -1
  61. package/dist/components/forms/date-time-field/DateTimeField.es.js +33 -33
  62. package/dist/components/forms/date-time-field/DateTimeField.es.js.map +1 -1
  63. package/dist/components/forms/debounce-input/DebounceInputField.cjs.js +1 -1
  64. package/dist/components/forms/debounce-input/DebounceInputField.cjs.js.map +1 -1
  65. package/dist/components/forms/debounce-input/DebounceInputField.es.js +2 -2
  66. package/dist/components/forms/debounce-input/DebounceInputField.es.js.map +1 -1
  67. package/dist/components/forms/dynamic-data-input/DynamicDataInput.cjs.js +1 -1
  68. package/dist/components/forms/dynamic-data-input/DynamicDataInput.cjs.js.map +1 -1
  69. package/dist/components/forms/dynamic-data-input/DynamicDataInput.es.js +7 -7
  70. package/dist/components/forms/dynamic-data-input/DynamicDataInput.es.js.map +1 -1
  71. package/dist/components/forms/dynamic-data-input/DynamicDataInputField.cjs.js +1 -1
  72. package/dist/components/forms/dynamic-data-input/DynamicDataInputField.cjs.js.map +1 -1
  73. package/dist/components/forms/dynamic-data-input/DynamicDataInputField.es.js +17 -19
  74. package/dist/components/forms/dynamic-data-input/DynamicDataInputField.es.js.map +1 -1
  75. package/dist/components/forms/field-options/Item.cjs.js +1 -1
  76. package/dist/components/forms/field-options/Item.cjs.js.map +1 -1
  77. package/dist/components/forms/field-options/Item.es.js +5 -5
  78. package/dist/components/forms/field-options/Item.es.js.map +1 -1
  79. package/dist/components/forms/formula-input/FormulaInput.cjs.js +1 -1
  80. package/dist/components/forms/formula-input/FormulaInput.cjs.js.map +1 -1
  81. package/dist/components/forms/formula-input/FormulaInput.es.js +10 -10
  82. package/dist/components/forms/formula-input/FormulaInput.es.js.map +1 -1
  83. package/dist/components/forms/icon-picker/IconPicker.cjs.js +1 -1
  84. package/dist/components/forms/icon-picker/IconPicker.cjs.js.map +1 -1
  85. package/dist/components/forms/icon-picker/IconPicker.es.js +42 -57
  86. package/dist/components/forms/icon-picker/IconPicker.es.js.map +1 -1
  87. package/dist/components/forms/input-field/InputField.cjs.js.map +1 -1
  88. package/dist/components/forms/input-field/InputField.es.js.map +1 -1
  89. package/dist/components/forms/master-data-input/MasterDataInputField.cjs.js +1 -1
  90. package/dist/components/forms/master-data-input/MasterDataInputField.cjs.js.map +1 -1
  91. package/dist/components/forms/master-data-input/MasterDataInputField.es.js +54 -60
  92. package/dist/components/forms/master-data-input/MasterDataInputField.es.js.map +1 -1
  93. package/dist/components/forms/md-input/RichMarkdownInput.cjs.js +3 -3
  94. package/dist/components/forms/md-input/RichMarkdownInput.cjs.js.map +1 -1
  95. package/dist/components/forms/md-input/RichMarkdownInput.es.js +63 -63
  96. package/dist/components/forms/md-input/RichMarkdownInput.es.js.map +1 -1
  97. package/dist/components/forms/number-input-field/NumberInputField.cjs.js +1 -1
  98. package/dist/components/forms/number-input-field/NumberInputField.cjs.js.map +1 -1
  99. package/dist/components/forms/number-input-field/NumberInputField.es.js +5 -5
  100. package/dist/components/forms/number-input-field/NumberInputField.es.js.map +1 -1
  101. package/dist/components/forms/percentage-input/PercentageInputField.cjs.js +2 -2
  102. package/dist/components/forms/percentage-input/PercentageInputField.cjs.js.map +1 -1
  103. package/dist/components/forms/percentage-input/PercentageInputField.es.js +20 -20
  104. package/dist/components/forms/percentage-input/PercentageInputField.es.js.map +1 -1
  105. package/dist/components/forms/search-bar/SearchBar.cjs.js +1 -1
  106. package/dist/components/forms/search-bar/SearchBar.cjs.js.map +1 -1
  107. package/dist/components/forms/search-bar/SearchBar.es.js +16 -16
  108. package/dist/components/forms/search-bar/SearchBar.es.js.map +1 -1
  109. package/dist/components/forms/select-field/SelectField.cjs.js +2 -2
  110. package/dist/components/forms/select-field/SelectField.cjs.js.map +1 -1
  111. package/dist/components/forms/select-field/SelectField.d.ts +4 -0
  112. package/dist/components/forms/select-field/SelectField.es.js +202 -203
  113. package/dist/components/forms/select-field/SelectField.es.js.map +1 -1
  114. package/dist/components/forms/text-area-field/TextAreaField.cjs.js +1 -1
  115. package/dist/components/forms/text-area-field/TextAreaField.cjs.js.map +1 -1
  116. package/dist/components/forms/text-area-field/TextAreaField.es.js +14 -14
  117. package/dist/components/forms/text-area-field/TextAreaField.es.js.map +1 -1
  118. package/dist/components/forms/toggle/Toggle.cjs.js +1 -1
  119. package/dist/components/forms/toggle/Toggle.cjs.js.map +1 -1
  120. package/dist/components/forms/toggle/Toggle.es.js +65 -59
  121. package/dist/components/forms/toggle/Toggle.es.js.map +1 -1
  122. package/dist/components/navigation/accordion/Accordion.cjs.js +1 -1
  123. package/dist/components/navigation/accordion/Accordion.cjs.js.map +1 -1
  124. package/dist/components/navigation/accordion/Accordion.es.js +5 -5
  125. package/dist/components/navigation/accordion/Accordion.es.js.map +1 -1
  126. package/dist/components/navigation/stepper/Stepper.cjs.js +1 -1
  127. package/dist/components/navigation/stepper/Stepper.cjs.js.map +1 -1
  128. package/dist/components/navigation/stepper/Stepper.es.js +1 -1
  129. package/dist/components/navigation/stepper/Stepper.es.js.map +1 -1
  130. package/dist/components/navigation/tabs/TabOptions.cjs.js +1 -1
  131. package/dist/components/navigation/tabs/TabOptions.cjs.js.map +1 -1
  132. package/dist/components/navigation/tabs/TabOptions.es.js +15 -15
  133. package/dist/components/navigation/tabs/TabOptions.es.js.map +1 -1
  134. package/dist/components/navigation/tabs/TabSwitch.cjs.js +1 -1
  135. package/dist/components/navigation/tabs/TabSwitch.cjs.js.map +1 -1
  136. package/dist/components/navigation/tabs/TabSwitch.es.js +7 -7
  137. package/dist/components/navigation/tabs/TabSwitch.es.js.map +1 -1
  138. package/dist/components/navigation/tabs/Tabs.cjs.js +1 -1
  139. package/dist/components/navigation/tabs/Tabs.cjs.js.map +1 -1
  140. package/dist/components/navigation/tabs/Tabs.es.js +1 -1
  141. package/dist/components/navigation/tabs/Tabs.es.js.map +1 -1
  142. package/dist/components/tooltip/Tooltip.cjs.js +1 -1
  143. package/dist/components/tooltip/Tooltip.cjs.js.map +1 -1
  144. package/dist/components/tooltip/Tooltip.es.js +19 -19
  145. package/dist/components/tooltip/Tooltip.es.js.map +1 -1
  146. package/dist/components/user-avatar/UserAvatar.cjs.js +1 -1
  147. package/dist/components/user-avatar/UserAvatar.cjs.js.map +1 -1
  148. package/dist/components/user-avatar/UserAvatar.d.ts +1 -1
  149. package/dist/components/user-avatar/UserAvatar.es.js +40 -38
  150. package/dist/components/user-avatar/UserAvatar.es.js.map +1 -1
  151. package/dist/components/user-avatar/constants.cjs.js +1 -1
  152. package/dist/components/user-avatar/constants.cjs.js.map +1 -1
  153. package/dist/components/user-avatar/constants.d.ts +1 -0
  154. package/dist/components/user-avatar/constants.es.js +10 -9
  155. package/dist/components/user-avatar/constants.es.js.map +1 -1
  156. package/dist/design-system.css +1 -1
  157. package/package.json +2 -3
@@ -1 +1 @@
1
- {"version":3,"file":"Item.cjs.js","sources":["../../../../src/components/forms/field-options/Item.tsx"],"sourcesContent":["import cn from 'classnames';\nimport type { FC } from 'react';\nimport { SortableItem, SortableKnob } from 'react-easy-sort';\n\nimport { CloseIcon } from './Icon';\nimport type { TFieldOptionsProps } from './types';\nimport { DragIndicatorIcon } from '../../icon';\n\ntype TProps = Pick<TFieldOptionsProps, 'value' | 'onDeleteItem' | 'userCanManage'> & {\n index: number;\n};\n\nexport const Item: FC<TProps> = (props) => {\n const { value, index, onDeleteItem, userCanManage = false } = props;\n\n return (\n <SortableItem>\n <div\n className={cn(\n 'relative flex items-center px-1.5 py-0.5 text-sm text-primary-600 bg-primary-50 dark:bg-black-700 rounded font-medium text-[14px] font-inter border border-primary-100',\n )}\n >\n {userCanManage && (\n <SortableKnob>\n <button id={`btn-data-display-close-modal`} className='pr-2 cursor-move'>\n <DragIndicatorIcon size={14} className='text-primary-600 dark:text-primary-600' />\n </button>\n </SortableKnob>\n )}\n {value}\n {userCanManage && (\n <span\n className='flex items-center gap-2.5 p-0.5 rounded-xl bg-primary-100 ml-auto cursor-pointer'\n data-dismiss-target='#badge-dismiss-default'\n aria-label='Remove'\n onClick={() => {\n onDeleteItem(index);\n }}\n >\n <CloseIcon size='w-2.5 h-2.5' />\n <span className='sr-only'>{'Remove badge'}</span>\n </span>\n )}\n </div>\n </SortableItem>\n );\n};\n\n\n\n"],"names":["Item","props","value","index","onDeleteItem","userCanManage","SortableItem","jsxs","cn","jsx","SortableKnob","DragIndicatorIcon","CloseIcon"],"mappings":"wQAYaA,EAAoBC,GAAU,CACzC,KAAM,CAAE,MAAAC,EAAA,MAAOC,EAAO,aAAAC,EAAc,cAAAC,EAAgB,IAAUJ,EAE9D,aACGK,EAAAA,aAAA,CACC,SAAAC,EAAAA,KAAC,MAAA,CACC,UAAWC,EACT,wKAAA,EAGA,SAAA,CAAAH,GACAI,EAAAA,IAACC,EAAAA,aAAA,CACC,SAAAD,MAAC,SAAA,CAAO,GAAI,+BAAgC,UAAU,mBACpD,SAAAA,EAAAA,IAACE,EAAAA,mBAAkB,KAAM,GAAI,UAAU,wCAAA,CAAyC,EAClF,EACF,EAEDT,EACAG,GACCE,EAAAA,KAAC,OAAA,CACC,UAAU,mFACV,sBAAoB,yBACpB,aAAW,SACX,QAAS,IAAM,CACbH,EAAaD,CAAK,CACpB,EAEA,SAAA,CAAAM,EAAAA,IAACG,EAAAA,UAAA,CAAU,KAAK,aAAA,CAAc,EAC9BH,EAAAA,IAAC,OAAA,CAAK,UAAU,UAAW,SAAA,cAAA,CAAe,CAAA,CAAA,CAAA,CAC5C,CAAA,CAAA,EAGN,CAEJ"}
1
+ {"version":3,"file":"Item.cjs.js","sources":["../../../../src/components/forms/field-options/Item.tsx"],"sourcesContent":["import cn from 'classnames';\nimport type { FC } from 'react';\nimport { SortableItem, SortableKnob } from 'react-easy-sort';\n\nimport { CloseIcon } from './Icon';\nimport type { TFieldOptionsProps } from './types';\nimport { DragIndicatorIcon } from '../../icon';\n\ntype TProps = Pick<TFieldOptionsProps, 'value' | 'onDeleteItem' | 'userCanManage'> & {\n index: number;\n};\n\nexport const Item: FC<TProps> = (props) => {\n const { value, index, onDeleteItem, userCanManage = false } = props;\n\n return (\n <SortableItem>\n <div\n className={cn(\n 'relative flex items-center px-1.5 py-0.5 text-sm text-primary-600 bg-primary-50 dark:bg-black-700 rounded font-mediumtext-base font-inter border border-primary-100',\n )}\n >\n {userCanManage && (\n <SortableKnob>\n <button id={`btn-data-display-close-modal`} className='pr-2 cursor-move'>\n <DragIndicatorIcon size={14} className='text-primary-600 dark:text-primary-600' />\n </button>\n </SortableKnob>\n )}\n {value}\n {userCanManage && (\n <span\n className='flex items-center gap-2.5 p-0.5 rounded-xl bg-primary-100 ml-auto cursor-pointer'\n data-dismiss-target='#badge-dismiss-default'\n aria-label='Remove'\n onClick={() => {\n onDeleteItem(index);\n }}\n >\n <CloseIcon size='w-2.5 h-2.5' />\n <span className='sr-only'>{'Remove badge'}</span>\n </span>\n )}\n </div>\n </SortableItem>\n );\n};\n\n\n\n"],"names":["Item","props","value","index","onDeleteItem","userCanManage","SortableItem","jsxs","cn","jsx","SortableKnob","DragIndicatorIcon","CloseIcon"],"mappings":"wQAYaA,EAAoBC,GAAU,CACzC,KAAM,CAAE,MAAAC,EAAA,MAAOC,EAAO,aAAAC,EAAc,cAAAC,EAAgB,IAAUJ,EAE9D,aACGK,EAAAA,aAAA,CACC,SAAAC,EAAAA,KAAC,MAAA,CACC,UAAWC,EACT,qKAAA,EAGA,SAAA,CAAAH,GACAI,EAAAA,IAACC,EAAAA,aAAA,CACC,SAAAD,MAAC,SAAA,CAAO,GAAI,+BAAgC,UAAU,mBACpD,SAAAA,EAAAA,IAACE,EAAAA,mBAAkB,KAAM,GAAI,UAAU,wCAAA,CAAyC,EAClF,EACF,EAEDT,EACAG,GACCE,EAAAA,KAAC,OAAA,CACC,UAAU,mFACV,sBAAoB,yBACpB,aAAW,SACX,QAAS,IAAM,CACbH,EAAaD,CAAK,CACpB,EAEA,SAAA,CAAAM,EAAAA,IAACG,EAAAA,UAAA,CAAU,KAAK,aAAA,CAAc,EAC9BH,EAAAA,IAAC,OAAA,CAAK,UAAU,UAAW,SAAA,cAAA,CAAe,CAAA,CAAA,CAAA,CAC5C,CAAA,CAAA,EAGN,CAEJ"}
@@ -1,15 +1,15 @@
1
1
  import { jsx as e, jsxs as a } from "react/jsx-runtime";
2
- import s from "../../../_virtual/index.es.js";
2
+ import m from "../../../_virtual/index.es.js";
3
3
  import { SortableItem as n, SortableKnob as l } from "react-easy-sort";
4
4
  import { CloseIcon as d } from "./Icon.es.js";
5
5
  import { DragIndicatorIcon as c } from "../../icon/icons.generated.es.js";
6
6
  const g = (t) => {
7
- const { value: o, index: i, onDeleteItem: m, userCanManage: r = !1 } = t;
7
+ const { value: o, index: s, onDeleteItem: i, userCanManage: r = !1 } = t;
8
8
  return /* @__PURE__ */ e(n, { children: /* @__PURE__ */ a(
9
9
  "div",
10
10
  {
11
- className: s(
12
- "relative flex items-center px-1.5 py-0.5 text-sm text-primary-600 bg-primary-50 dark:bg-black-700 rounded font-medium text-[14px] font-inter border border-primary-100"
11
+ className: m(
12
+ "relative flex items-center px-1.5 py-0.5 text-sm text-primary-600 bg-primary-50 dark:bg-black-700 rounded font-mediumtext-base font-inter border border-primary-100"
13
13
  ),
14
14
  children: [
15
15
  r && /* @__PURE__ */ e(l, { children: /* @__PURE__ */ e("button", { id: "btn-data-display-close-modal", className: "pr-2 cursor-move", children: /* @__PURE__ */ e(c, { size: 14, className: "text-primary-600 dark:text-primary-600" }) }) }),
@@ -21,7 +21,7 @@ const g = (t) => {
21
21
  "data-dismiss-target": "#badge-dismiss-default",
22
22
  "aria-label": "Remove",
23
23
  onClick: () => {
24
- m(i);
24
+ i(s);
25
25
  },
26
26
  children: [
27
27
  /* @__PURE__ */ e(d, { size: "w-2.5 h-2.5" }),
@@ -1 +1 @@
1
- {"version":3,"file":"Item.es.js","sources":["../../../../src/components/forms/field-options/Item.tsx"],"sourcesContent":["import cn from 'classnames';\nimport type { FC } from 'react';\nimport { SortableItem, SortableKnob } from 'react-easy-sort';\n\nimport { CloseIcon } from './Icon';\nimport type { TFieldOptionsProps } from './types';\nimport { DragIndicatorIcon } from '../../icon';\n\ntype TProps = Pick<TFieldOptionsProps, 'value' | 'onDeleteItem' | 'userCanManage'> & {\n index: number;\n};\n\nexport const Item: FC<TProps> = (props) => {\n const { value, index, onDeleteItem, userCanManage = false } = props;\n\n return (\n <SortableItem>\n <div\n className={cn(\n 'relative flex items-center px-1.5 py-0.5 text-sm text-primary-600 bg-primary-50 dark:bg-black-700 rounded font-medium text-[14px] font-inter border border-primary-100',\n )}\n >\n {userCanManage && (\n <SortableKnob>\n <button id={`btn-data-display-close-modal`} className='pr-2 cursor-move'>\n <DragIndicatorIcon size={14} className='text-primary-600 dark:text-primary-600' />\n </button>\n </SortableKnob>\n )}\n {value}\n {userCanManage && (\n <span\n className='flex items-center gap-2.5 p-0.5 rounded-xl bg-primary-100 ml-auto cursor-pointer'\n data-dismiss-target='#badge-dismiss-default'\n aria-label='Remove'\n onClick={() => {\n onDeleteItem(index);\n }}\n >\n <CloseIcon size='w-2.5 h-2.5' />\n <span className='sr-only'>{'Remove badge'}</span>\n </span>\n )}\n </div>\n </SortableItem>\n );\n};\n\n\n\n"],"names":["Item","props","value","index","onDeleteItem","userCanManage","SortableItem","jsxs","cn","jsx","SortableKnob","DragIndicatorIcon","CloseIcon"],"mappings":";;;;;AAYO,MAAMA,IAAmB,CAACC,MAAU;AACzC,QAAM,EAAE,OAAAC,GAAO,OAAAC,GAAO,cAAAC,GAAc,eAAAC,IAAgB,OAAUJ;AAE9D,2BACGK,GAAA,EACC,UAAA,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAWC;AAAA,QACT;AAAA,MAAA;AAAA,MAGA,UAAA;AAAA,QAAAH,KACA,gBAAAI,EAACC,GAAA,EACC,UAAA,gBAAAD,EAAC,UAAA,EAAO,IAAI,gCAAgC,WAAU,oBACpD,UAAA,gBAAAA,EAACE,KAAkB,MAAM,IAAI,WAAU,yCAAA,CAAyC,GAClF,GACF;AAAA,QAEDT;AAAA,QACAG,KACC,gBAAAE;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,uBAAoB;AAAA,YACpB,cAAW;AAAA,YACX,SAAS,MAAM;AACb,cAAAH,EAAaD,CAAK;AAAA,YACpB;AAAA,YAEA,UAAA;AAAA,cAAA,gBAAAM,EAACG,GAAA,EAAU,MAAK,cAAA,CAAc;AAAA,cAC9B,gBAAAH,EAAC,QAAA,EAAK,WAAU,WAAW,UAAA,eAAA,CAAe;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MAC5C;AAAA,IAAA;AAAA,EAAA,GAGN;AAEJ;"}
1
+ {"version":3,"file":"Item.es.js","sources":["../../../../src/components/forms/field-options/Item.tsx"],"sourcesContent":["import cn from 'classnames';\nimport type { FC } from 'react';\nimport { SortableItem, SortableKnob } from 'react-easy-sort';\n\nimport { CloseIcon } from './Icon';\nimport type { TFieldOptionsProps } from './types';\nimport { DragIndicatorIcon } from '../../icon';\n\ntype TProps = Pick<TFieldOptionsProps, 'value' | 'onDeleteItem' | 'userCanManage'> & {\n index: number;\n};\n\nexport const Item: FC<TProps> = (props) => {\n const { value, index, onDeleteItem, userCanManage = false } = props;\n\n return (\n <SortableItem>\n <div\n className={cn(\n 'relative flex items-center px-1.5 py-0.5 text-sm text-primary-600 bg-primary-50 dark:bg-black-700 rounded font-mediumtext-base font-inter border border-primary-100',\n )}\n >\n {userCanManage && (\n <SortableKnob>\n <button id={`btn-data-display-close-modal`} className='pr-2 cursor-move'>\n <DragIndicatorIcon size={14} className='text-primary-600 dark:text-primary-600' />\n </button>\n </SortableKnob>\n )}\n {value}\n {userCanManage && (\n <span\n className='flex items-center gap-2.5 p-0.5 rounded-xl bg-primary-100 ml-auto cursor-pointer'\n data-dismiss-target='#badge-dismiss-default'\n aria-label='Remove'\n onClick={() => {\n onDeleteItem(index);\n }}\n >\n <CloseIcon size='w-2.5 h-2.5' />\n <span className='sr-only'>{'Remove badge'}</span>\n </span>\n )}\n </div>\n </SortableItem>\n );\n};\n\n\n\n"],"names":["Item","props","value","index","onDeleteItem","userCanManage","SortableItem","jsxs","cn","jsx","SortableKnob","DragIndicatorIcon","CloseIcon"],"mappings":";;;;;AAYO,MAAMA,IAAmB,CAACC,MAAU;AACzC,QAAM,EAAE,OAAAC,GAAO,OAAAC,GAAO,cAAAC,GAAc,eAAAC,IAAgB,OAAUJ;AAE9D,2BACGK,GAAA,EACC,UAAA,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAWC;AAAA,QACT;AAAA,MAAA;AAAA,MAGA,UAAA;AAAA,QAAAH,KACA,gBAAAI,EAACC,GAAA,EACC,UAAA,gBAAAD,EAAC,UAAA,EAAO,IAAI,gCAAgC,WAAU,oBACpD,UAAA,gBAAAA,EAACE,KAAkB,MAAM,IAAI,WAAU,yCAAA,CAAyC,GAClF,GACF;AAAA,QAEDT;AAAA,QACAG,KACC,gBAAAE;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,uBAAoB;AAAA,YACpB,cAAW;AAAA,YACX,SAAS,MAAM;AACb,cAAAH,EAAaD,CAAK;AAAA,YACpB;AAAA,YAEA,UAAA;AAAA,cAAA,gBAAAM,EAACG,GAAA,EAAU,MAAK,cAAA,CAAc;AAAA,cAC9B,gBAAAH,EAAC,QAAA,EAAK,WAAU,WAAW,UAAA,eAAA,CAAe;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MAC5C;AAAA,IAAA;AAAA,EAAA,GAGN;AAEJ;"}
@@ -1,2 +1,2 @@
1
- "use strict";const s=require("react/jsx-runtime"),F=require("../../../_virtual/index.cjs.js"),e=require("react"),ee=require("react-contenteditable"),te=require("react-dom"),z=require("@mui/icons-material"),B=require("../../data-display/typography/Typography.cjs.js"),re=require("../../button/IconButton.cjs.js"),se=require("../../tooltip/Tooltip.cjs.js"),ne=require("../../icons/HelpIcon.cjs.js"),oe=require("../../../hooks/useOutsideClick.cjs.js"),I=require("./utils.cjs.js"),ae=require("../shared/InputLabel.cjs.js"),ce=require("../../../node_modules/@popperjs/core/lib/popper.cjs.js"),le=({value:u="",onChange:b,onFocus:q,onBlur:T,label:v,id:L,required:M,tooltip:D,placeholder:K,disabled:p,errorMessage:y,width:H="100%",suggestions:S=[],showRawValue:U=!1})=>{const c=e.useRef(null),R=e.useRef(null),m=e.useRef(null),j=e.useRef([]),g=e.useRef(null),[a,f]=e.useState(!1),[C,A]=e.useState(""),[d,w]=e.useState(0),[x,$]=e.useState(U),E=e.useRef(a),N=e.useRef([]),V=e.useRef(d),P=e.useRef(u);e.useEffect(()=>{E.current=a},[a]),e.useEffect(()=>{V.current=d},[d]),e.useEffect(()=>{P.current=u},[u]),oe.useOutsideClick({ref:m,handler:()=>{a&&f(!1)}});const h=e.useMemo(()=>{if(!C)return S;const t=C.toLowerCase();return S.filter(r=>r.toLowerCase().includes(t))},[S,C]);e.useEffect(()=>{N.current=h},[h]),e.useEffect(()=>{w(0)},[h]),e.useEffect(()=>{a&&j.current[d]&&j.current[d]?.scrollIntoView({block:"nearest",behavior:"smooth"})},[d,a]),e.useEffect(()=>{if(a&&R.current&&m.current)return g.current=ce.createPopper(R.current,m.current,{placement:"bottom-start",strategy:"fixed",modifiers:[{name:"flip",options:{fallbackPlacements:["top-start","bottom-start"]}},{name:"preventOverflow",options:{boundary:"viewport",padding:8}},{name:"offset",options:{offset:[0,4]}}]}),()=>{g.current&&(g.current.destroy(),g.current=null)}},[a]);const W=e.useCallback(t=>{const r=I.convertFromPills(t.target.value);b(r);const n=I.getTextBeforeCursor(),l=n.lastIndexOf("@");if(l!==-1){const i=n.slice(l+1);i.includes(" ")?f(!1):(A(i),f(!0))}else f(!1)},[b]),G=e.useCallback(()=>{c.current&&(c.current.isFocused=!0),q?.()},[q]),J=e.useCallback(t=>{c.current&&(c.current.isFocused=!1);const r=t.relatedTarget;r&&m.current?.contains(r)||(setTimeout(()=>{f(!1)},200),T?.())},[T]),k=e.useCallback(t=>{if(!c.current)return;const r=P.current,n=r.lastIndexOf("@");if(n!==-1){const i=r.slice(n+1).search(/\s/);let o;i===-1?o=r.length:o=n+1+i;const Y=r.slice(0,n),Z=r.slice(o),_=`${Y}{{${t}}}${Z}`;b(_),f(!1),A(""),setTimeout(()=>{c.current?.focus()},0)}},[b]),O=e.useCallback(t=>{const r=E.current,n=N.current,l=V.current;if(t.key==="Enter"){t.preventDefault(),t.stopPropagation(),r&&n.length>0&&n[l]&&k(n[l]);return}if(r&&n.length>0){const{key:i}=t;if(["ArrowDown","ArrowUp","Escape","Tab"].includes(i))switch(t.preventDefault(),t.stopPropagation(),i){case"ArrowDown":w(o=>o<n.length-1?o+1:o);break;case"ArrowUp":w(o=>o>0?o-1:0);break;case"Escape":f(!1);break;case"Tab":n[l]&&k(n[l]);break}}},[k]),Q=e.useCallback(t=>{t.preventDefault();const r=t.clipboardData.getData("text/plain");document.execCommand("insertText",!1,r)},[]),X=e.useMemo(()=>x?u:I.convertToPills(u),[u,x]);return s.jsxs("div",{className:"w-full",children:[v&&s.jsxs("div",{className:"text-xs font-medium text-gray-600 inline-flex items-center gap-1 font-inter text-left whitespace-nowrap flex-wrap",children:[s.jsx(ae.InputLabel,{label:v||"",required:M||!1}),D&&s.jsx(se,{placement:"top",title:D,children:s.jsx("div",{className:"cursor-pointer",children:s.jsx(ne.HelpIcon,{})})})]}),s.jsxs("div",{className:"relative",ref:R,children:[u?.trim()?null:s.jsx("div",{className:"absolute top-0 left-0 w-full h-full text-gray-400 flex items-center cursor-text px-3 z-50",onClick:()=>c.current?.focus(),children:s.jsx(B.Typography,{size:"extra-small",variant:"medium",children:K})}),s.jsxs("div",{className:"relative",children:[s.jsx(ee,{innerRef:c,className:F("min-h-[42px] rounded-lg p-2.5","text-sm font-inter block font-medium border text-gray-900 dark:text-white whitespace-normal break-words text-left",p?"bg-neutral-100 dark:bg-black-800":"bg-white dark:bg-black-800",!p&&"pr-[60px]",y?"!border-error-500":"border-gray-300 dark:border-black-600 focus:ring-blue-500 focus:border-blue-500","cursor-text"),style:{width:H,wordBreak:"break-word"},html:X,onChange:p?()=>null:W,onFocus:G,onBlur:J,onKeyDownCapture:O,onKeyDown:O,onPaste:Q,disabled:p,id:L}),!p&&s.jsx("div",{className:"absolute right-0 top-0 bottom-0 flex items-center align-middle justify-center p-3 gap-2",children:s.jsx(re,{tooltip:x?"Show Formatted":"Show Raw Value",variant:"ghost",onClick:()=>$(!x),children:x?s.jsx(z.VisibilityOutlined,{sx:{fontSize:18}}):s.jsx(z.VisibilityOffOutlined,{sx:{fontSize:18}})})})]}),a&&h.length>0&&te.createPortal(s.jsx("div",{ref:m,className:"z-[3000] bg-white dark:bg-black-800 border border-gray-300 dark:border-black-600 rounded-lg shadow-lg max-h-60 overflow-y-auto min-w-[200px]",onMouseDown:t=>{t.preventDefault()},children:h.map((t,r)=>s.jsx("div",{ref:n=>j.current[r]=n,className:F("px-3 py-2 cursor-pointer text-sm font-inter",r===d?"bg-primary-100 dark:bg-primary-900 text-primary-700 dark:text-primary-300":"hover:bg-gray-100 dark:hover:bg-black-700 text-gray-900 dark:text-white"),onClick:()=>k(t),onMouseEnter:()=>w(r),children:t},t))}),document.body)]}),y&&s.jsx("div",{className:"pt-1",children:s.jsx(B.Typography,{className:"text-error-500",size:"extra-small",variant:"medium",appearance:"custom",children:y})})]})},ie=e.memo(le);module.exports=ie;
1
+ "use strict";const s=require("react/jsx-runtime"),F=require("../../../_virtual/index.cjs.js"),e=require("react"),ee=require("react-contenteditable"),te=require("react-dom"),z=require("@mui/icons-material"),B=require("../../data-display/typography/Typography.cjs.js"),re=require("../../button/IconButton.cjs.js"),se=require("../../tooltip/Tooltip.cjs.js"),ne=require("../../icons/HelpIcon.cjs.js"),oe=require("../../../hooks/useOutsideClick.cjs.js"),I=require("./utils.cjs.js"),ae=require("../shared/InputLabel.cjs.js"),ce=require("../../../node_modules/@popperjs/core/lib/popper.cjs.js"),le=({value:u="",onChange:b,onFocus:q,onBlur:T,label:v,id:L,required:M,tooltip:D,placeholder:K,disabled:p,errorMessage:y,width:H="100%",suggestions:S=[],showRawValue:U=!1})=>{const c=e.useRef(null),R=e.useRef(null),m=e.useRef(null),j=e.useRef([]),g=e.useRef(null),[a,f]=e.useState(!1),[C,N]=e.useState(""),[d,w]=e.useState(0),[x,$]=e.useState(U),A=e.useRef(a),E=e.useRef([]),V=e.useRef(d),P=e.useRef(u);e.useEffect(()=>{A.current=a},[a]),e.useEffect(()=>{V.current=d},[d]),e.useEffect(()=>{P.current=u},[u]),oe.useOutsideClick({ref:m,handler:()=>{a&&f(!1)}});const h=e.useMemo(()=>{if(!C)return S;const t=C.toLowerCase();return S.filter(r=>r.toLowerCase().includes(t))},[S,C]);e.useEffect(()=>{E.current=h},[h]),e.useEffect(()=>{w(0)},[h]),e.useEffect(()=>{a&&j.current[d]&&j.current[d]?.scrollIntoView({block:"nearest",behavior:"smooth"})},[d,a]),e.useEffect(()=>{if(a&&R.current&&m.current)return g.current=ce.createPopper(R.current,m.current,{placement:"bottom-start",strategy:"fixed",modifiers:[{name:"flip",options:{fallbackPlacements:["top-start","bottom-start"]}},{name:"preventOverflow",options:{boundary:"viewport",padding:8}},{name:"offset",options:{offset:[0,4]}}]}),()=>{g.current&&(g.current.destroy(),g.current=null)}},[a]);const W=e.useCallback(t=>{const r=I.convertFromPills(t.target.value);b(r);const n=I.getTextBeforeCursor(),l=n.lastIndexOf("@");if(l!==-1){const i=n.slice(l+1);i.includes(" ")?f(!1):(N(i),f(!0))}else f(!1)},[b]),G=e.useCallback(()=>{c.current&&(c.current.isFocused=!0),q?.()},[q]),J=e.useCallback(t=>{c.current&&(c.current.isFocused=!1);const r=t.relatedTarget;r&&m.current?.contains(r)||(setTimeout(()=>{f(!1)},200),T?.())},[T]),k=e.useCallback(t=>{if(!c.current)return;const r=P.current,n=r.lastIndexOf("@");if(n!==-1){const i=r.slice(n+1).search(/\s/);let o;i===-1?o=r.length:o=n+1+i;const Y=r.slice(0,n),Z=r.slice(o),_=`${Y}{{${t}}}${Z}`;b(_),f(!1),N(""),setTimeout(()=>{c.current?.focus()},0)}},[b]),O=e.useCallback(t=>{const r=A.current,n=E.current,l=V.current;if(t.key==="Enter"){t.preventDefault(),t.stopPropagation(),r&&n.length>0&&n[l]&&k(n[l]);return}if(r&&n.length>0){const{key:i}=t;if(["ArrowDown","ArrowUp","Escape","Tab"].includes(i))switch(t.preventDefault(),t.stopPropagation(),i){case"ArrowDown":w(o=>o<n.length-1?o+1:o);break;case"ArrowUp":w(o=>o>0?o-1:0);break;case"Escape":f(!1);break;case"Tab":n[l]&&k(n[l]);break}}},[k]),Q=e.useCallback(t=>{t.preventDefault();const r=t.clipboardData.getData("text/plain");document.execCommand("insertText",!1,r)},[]),X=e.useMemo(()=>x?u:I.convertToPills(u),[u,x]);return s.jsxs("div",{className:"w-full",children:[v&&s.jsxs("div",{className:"text-xs font-medium text-gray-600 inline-flex items-center gap-1 font-inter text-left whitespace-nowrap flex-wrap",children:[s.jsx(ae.InputLabel,{label:v||"",required:M||!1}),D&&s.jsx(se,{placement:"top",title:D,children:s.jsx("div",{className:"cursor-pointer",children:s.jsx(ne.HelpIcon,{className:"w-icon-sm h-icon-sm"})})})]}),s.jsxs("div",{className:"relative",ref:R,children:[u?.trim()?null:s.jsx("div",{className:"absolute top-0 left-0 w-full h-full text-gray-400 flex items-center cursor-text px-3 z-50",onClick:()=>c.current?.focus(),children:s.jsx(B.Typography,{size:"extra-small",variant:"medium",children:K})}),s.jsxs("div",{className:"relative",children:[s.jsx(ee,{innerRef:c,className:F("min-h-[42px] rounded-lg p-2.5","text-sm font-inter block font-medium border text-gray-900 dark:text-white whitespace-normal break-words text-left",p?"bg-neutral-100 dark:bg-black-800":"bg-white dark:bg-black-800",!p&&"pr-[60px]",y?"!border-error-500":"border-gray-300 dark:border-black-600 focus:ring-blue-500 focus:border-blue-500","cursor-text"),style:{width:H,wordBreak:"break-word"},html:X,onChange:p?()=>null:W,onFocus:G,onBlur:J,onKeyDownCapture:O,onKeyDown:O,onPaste:Q,disabled:p,id:L}),!p&&s.jsx("div",{className:"absolute right-0 top-0 bottom-0 flex items-center align-middle justify-center p-3 gap-2",children:s.jsx(re,{tooltip:x?"Show Formatted":"Show Raw Value",variant:"ghost",onClick:()=>$(!x),children:x?s.jsx(z.VisibilityOutlined,{sx:{fontSize:18}}):s.jsx(z.VisibilityOffOutlined,{sx:{fontSize:18}})})})]}),a&&h.length>0&&te.createPortal(s.jsx("div",{ref:m,className:"z-[3000] bg-white dark:bg-black-800 border border-gray-300 dark:border-black-600 rounded-lg shadow-lg max-h-60 overflow-y-auto min-w-[200px]",onMouseDown:t=>{t.preventDefault()},children:h.map((t,r)=>s.jsx("div",{ref:n=>j.current[r]=n,className:F("px-3 py-2 cursor-pointer text-sm font-inter",r===d?"bg-primary-100 dark:bg-primary-900 text-primary-700 dark:text-primary-300":"hover:bg-gray-100 dark:hover:bg-black-700 text-gray-900 dark:text-white"),onClick:()=>k(t),onMouseEnter:()=>w(r),children:t},t))}),document.body)]}),y&&s.jsx("div",{className:"pt-1",children:s.jsx(B.Typography,{className:"text-error-500",size:"extra-small",variant:"medium",appearance:"custom",children:y})})]})},ie=e.memo(le);module.exports=ie;
2
2
  //# sourceMappingURL=FormulaInput.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"FormulaInput.cjs.js","sources":["../../../../src/components/forms/formula-input/FormulaInput.tsx"],"sourcesContent":["import { Instance as PopperInstance, createPopper } from '@popperjs/core';\nimport cn from 'classnames';\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport ContentEditable, { ContentEditableEvent } from 'react-contenteditable';\nimport { createPortal } from 'react-dom';\nimport { VisibilityOffOutlined, VisibilityOutlined } from '@mui/icons-material';\n\nimport { Typography } from '../../data-display/typography/Typography';\nimport IconButton from '../../button/IconButton';\nimport Tooltip from '../../tooltip/Tooltip';\nimport { HelpIcon } from '../../icons/HelpIcon';\nimport { useOutsideClick } from '../../../hooks/useOutsideClick';\nimport { convertFromPills, convertToPills, getTextBeforeCursor } from './utils';\nimport { InputLabel } from '../shared/InputLabel';\n\nexport interface FormulaInputProps {\n /** Current value of the input */\n value: string;\n /** Callback when value changes */\n onChange: (value: string) => void;\n /** Callback when input receives focus */\n onFocus?: () => void;\n /** Callback when input loses focus */\n onBlur?: () => void;\n /** Label for the input field */\n label?: string;\n /** Unique identifier for the input */\n id: string;\n /** Whether the field is required */\n required?: boolean;\n /** Tooltip text displayed next to the label */\n tooltip?: string;\n /** Placeholder text */\n placeholder?: string;\n /** Whether the input is disabled */\n disabled?: boolean;\n /** Error message to display */\n errorMessage?: string;\n /** Width of the input */\n width?: string;\n /** List of suggestions for autocomplete */\n suggestions?: string[];\n /** Whether to show the raw value instead of pills */\n showRawValue?: boolean;\n}\n\n/**\n * FormulaInput component for entering formulas with variable suggestions\n * Variables are displayed as pills and can be inserted using @ trigger\n */\nconst FormulaInput: React.FC<FormulaInputProps> = ({\n value = '',\n onChange,\n onFocus,\n onBlur,\n label,\n id,\n required: isRequired,\n tooltip,\n placeholder,\n disabled,\n errorMessage,\n width = '100%',\n suggestions = [],\n showRawValue: showRawValueProp = false,\n}) => {\n const contentRef = useRef<HTMLElement & { isFocused?: boolean }>(null);\n const inputWrapperRef = useRef<HTMLDivElement>(null);\n const suggestionMenuRef = useRef<HTMLDivElement>(null);\n const suggestionRefs = useRef<(HTMLDivElement | null)[]>([]);\n const popperInstanceRef = useRef<PopperInstance | null>(null);\n const [showSuggestions, setShowSuggestions] = useState(false);\n const [searchTerm, setSearchTerm] = useState('');\n const [selectedIndex, setSelectedIndex] = useState(0);\n const [showRawValue, setShowRawValue] = useState(showRawValueProp);\n\n // Use refs to track current state for event handlers\n const showSuggestionsRef = useRef(showSuggestions);\n const filteredSuggestionsRef = useRef<string[]>([]);\n const selectedIndexRef = useRef(selectedIndex);\n const valueRef = useRef(value);\n\n // Keep refs in sync with state\n useEffect(() => {\n showSuggestionsRef.current = showSuggestions;\n }, [showSuggestions]);\n\n useEffect(() => {\n selectedIndexRef.current = selectedIndex;\n }, [selectedIndex]);\n\n useEffect(() => {\n valueRef.current = value;\n }, [value]);\n\n // Close suggestions when clicking outside\n useOutsideClick({\n ref: suggestionMenuRef,\n handler: () => {\n if (showSuggestions) {\n setShowSuggestions(false);\n }\n },\n });\n\n // Filter suggestions based on search term\n const filteredSuggestions = useMemo(() => {\n if (!searchTerm) return suggestions;\n\n const lowerSearchTerm = searchTerm.toLowerCase();\n return suggestions.filter((suggestion) => suggestion.toLowerCase().includes(lowerSearchTerm));\n }, [suggestions, searchTerm]);\n\n // Keep filtered suggestions ref in sync\n useEffect(() => {\n filteredSuggestionsRef.current = filteredSuggestions;\n }, [filteredSuggestions]);\n\n // Reset selected index when filtered suggestions change\n useEffect(() => {\n setSelectedIndex(0);\n }, [filteredSuggestions]);\n\n // Scroll selected suggestion into view\n useEffect(() => {\n if (showSuggestions && suggestionRefs.current[selectedIndex]) {\n suggestionRefs.current[selectedIndex]?.scrollIntoView({\n block: 'nearest',\n behavior: 'smooth',\n });\n }\n }, [selectedIndex, showSuggestions]);\n\n // Setup Popper for dynamic positioning\n useEffect(() => {\n if (showSuggestions && inputWrapperRef.current && suggestionMenuRef.current) {\n // Create popper instance with auto placement\n popperInstanceRef.current = createPopper(inputWrapperRef.current, suggestionMenuRef.current, {\n placement: 'bottom-start',\n strategy: 'fixed',\n modifiers: [\n {\n name: 'flip',\n options: {\n fallbackPlacements: ['top-start', 'bottom-start'],\n },\n },\n {\n name: 'preventOverflow',\n options: {\n boundary: 'viewport',\n padding: 8,\n },\n },\n {\n name: 'offset',\n options: {\n offset: [0, 4],\n },\n },\n ],\n });\n\n return () => {\n if (popperInstanceRef.current) {\n popperInstanceRef.current.destroy();\n popperInstanceRef.current = null;\n }\n };\n }\n }, [showSuggestions]);\n\n const handleChange = useCallback(\n (event: ContentEditableEvent) => {\n const rawValue = convertFromPills(event.target.value);\n onChange(rawValue);\n\n // Check if user typed @ (trigger for suggestions)\n const textBeforeCursor = getTextBeforeCursor();\n const lastAtSymbol = textBeforeCursor.lastIndexOf('@');\n\n if (lastAtSymbol !== -1) {\n // Get text after the @ symbol\n const textAfterAt = textBeforeCursor.slice(lastAtSymbol + 1);\n\n // Check if there's a space after @, which would end the suggestion context\n const hasSpace = textAfterAt.includes(' ');\n\n if (!hasSpace) {\n // We're in suggestion mode - show suggestions filtered by text after @\n setSearchTerm(textAfterAt);\n setShowSuggestions(true);\n } else {\n setShowSuggestions(false);\n }\n } else {\n setShowSuggestions(false);\n }\n },\n [onChange],\n );\n\n const handleFocus = useCallback(() => {\n if (contentRef.current) {\n contentRef.current.isFocused = true;\n }\n onFocus?.();\n }, [onFocus]);\n\n const handleBlur = useCallback(\n (event: React.FocusEvent) => {\n if (contentRef.current) {\n contentRef.current.isFocused = false;\n }\n\n // Check if the blur is due to clicking on a suggestion\n const relatedTarget = event.relatedTarget as HTMLElement;\n if (relatedTarget && suggestionMenuRef.current?.contains(relatedTarget)) {\n // Don't close suggestions if clicking on a suggestion\n return;\n }\n\n // Delay closing suggestions to allow click events to register\n setTimeout(() => {\n setShowSuggestions(false);\n }, 200);\n onBlur?.();\n },\n [onBlur],\n );\n\n const insertSuggestion = useCallback(\n (suggestion: string) => {\n if (!contentRef.current) return;\n\n // IMPORTANT: Use the value prop (not innerText) to preserve existing {{}} syntax\n // innerText only shows display text and loses the {{}} markers from pills\n const currentValue = valueRef.current;\n\n // Find the last occurrence of @ (trigger symbol) in the raw value\n const lastAtSymbol = currentValue.lastIndexOf('@');\n\n if (lastAtSymbol !== -1) {\n // Find where the @ trigger ends (space or end of string)\n const afterAt = currentValue.slice(lastAtSymbol + 1);\n const spaceIndex = afterAt.search(/\\s/);\n\n let endPosition: number;\n if (spaceIndex === -1) {\n // No space found, the incomplete variable goes to the end\n endPosition = currentValue.length;\n } else {\n // Space found, replace up to the space\n endPosition = lastAtSymbol + 1 + spaceIndex;\n }\n\n // Build the new value preserving all existing {{}} syntax\n // Replace @searchTerm with {{suggestion}}\n const beforeAt = currentValue.slice(0, lastAtSymbol);\n const afterCursor = currentValue.slice(endPosition);\n const newValue = `${beforeAt}{{${suggestion}}}${afterCursor}`;\n\n // Update through onChange\n onChange(newValue);\n\n // Close suggestions\n setShowSuggestions(false);\n setSearchTerm('');\n\n // Refocus the input after React updates\n setTimeout(() => {\n contentRef.current?.focus();\n }, 0);\n }\n },\n [onChange],\n );\n\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent) => {\n // Use refs to get the latest state values to avoid stale closures\n const isShowingSuggestions = showSuggestionsRef.current;\n const currentFilteredSuggestions = filteredSuggestionsRef.current;\n const currentSelectedIndex = selectedIndexRef.current;\n\n // Always prevent Enter key to avoid creating new lines/divs\n if (event.key === 'Enter') {\n event.preventDefault();\n event.stopPropagation();\n\n // If suggestions are showing, select the current suggestion\n if (isShowingSuggestions && currentFilteredSuggestions.length > 0 && currentFilteredSuggestions[currentSelectedIndex]) {\n insertSuggestion(currentFilteredSuggestions[currentSelectedIndex]);\n }\n return;\n }\n\n // When suggestions are visible, intercept navigation keys immediately\n if (isShowingSuggestions && currentFilteredSuggestions.length > 0) {\n const { key } = event;\n\n // Prevent default for all navigation keys when suggestions are shown\n if (['ArrowDown', 'ArrowUp', 'Escape', 'Tab'].includes(key)) {\n event.preventDefault();\n event.stopPropagation();\n\n switch (key) {\n case 'ArrowDown':\n setSelectedIndex((prev) => (prev < currentFilteredSuggestions.length - 1 ? prev + 1 : prev));\n break;\n case 'ArrowUp':\n setSelectedIndex((prev) => (prev > 0 ? prev - 1 : 0));\n break;\n case 'Escape':\n setShowSuggestions(false);\n break;\n case 'Tab':\n if (currentFilteredSuggestions[currentSelectedIndex]) {\n insertSuggestion(currentFilteredSuggestions[currentSelectedIndex]);\n }\n break;\n }\n }\n }\n },\n [insertSuggestion],\n );\n\n const handlePaste = useCallback((event: React.ClipboardEvent<HTMLDivElement>) => {\n event.preventDefault();\n const text = event.clipboardData.getData('text/plain');\n document.execCommand('insertText', false, text);\n }, []);\n\n const displayValue = useMemo(() => {\n if (showRawValue) {\n return value;\n }\n return convertToPills(value);\n }, [value, showRawValue]);\n\n return (\n <div className='w-full'>\n {label && (\n <div className='text-xs font-medium text-gray-600 inline-flex items-center gap-1 font-inter text-left whitespace-nowrap flex-wrap'>\n <InputLabel label={label || \"\"} required={isRequired || false} />\n {tooltip && (\n <Tooltip placement='top' title={tooltip}>\n <div className='cursor-pointer'>\n <HelpIcon />\n </div>\n </Tooltip>\n )}\n </div>\n )}\n\n <div className='relative' ref={inputWrapperRef}>\n {!value?.trim() ? (\n <div\n className='absolute top-0 left-0 w-full h-full text-gray-400 flex items-center cursor-text px-3 z-50'\n onClick={() => contentRef.current?.focus()}\n >\n <Typography size='extra-small' variant='medium'>\n {placeholder}\n </Typography>\n </div>\n ) : null}\n\n <div className='relative'>\n <ContentEditable\n innerRef={contentRef}\n className={cn(\n 'min-h-[42px] rounded-lg p-2.5',\n 'text-sm font-inter block font-medium border text-gray-900 dark:text-white whitespace-normal break-words text-left',\n disabled ? 'bg-neutral-100 dark:bg-black-800' : 'bg-white dark:bg-black-800',\n !disabled && 'pr-[60px]',\n errorMessage ? '!border-error-500' : 'border-gray-300 dark:border-black-600 focus:ring-blue-500 focus:border-blue-500',\n 'cursor-text',\n )}\n style={{\n width: width,\n wordBreak: 'break-word',\n }}\n html={displayValue}\n onChange={!disabled ? handleChange : () => null}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onKeyDownCapture={handleKeyDown}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n disabled={disabled}\n id={id}\n />\n\n {!disabled && (\n <div className='absolute right-0 top-0 bottom-0 flex items-center align-middle justify-center p-3 gap-2'>\n <IconButton tooltip={showRawValue ? 'Show Formatted' : 'Show Raw Value'} variant='ghost' onClick={() => setShowRawValue(!showRawValue)}>\n {showRawValue ? <VisibilityOutlined sx={{ fontSize: 18 }} /> : <VisibilityOffOutlined sx={{ fontSize: 18 }} />}\n </IconButton>\n </div>\n )}\n </div>\n\n {showSuggestions &&\n filteredSuggestions.length > 0 &&\n createPortal(\n <div\n ref={suggestionMenuRef}\n className='z-[3000] bg-white dark:bg-black-800 border border-gray-300 dark:border-black-600 rounded-lg shadow-lg max-h-60 overflow-y-auto min-w-[200px]'\n onMouseDown={(e) => {\n // Prevent blur when clicking on suggestions\n e.preventDefault();\n }}\n >\n {filteredSuggestions.map((suggestion, index) => (\n <div\n key={suggestion}\n ref={(el) => (suggestionRefs.current[index] = el)}\n className={cn(\n 'px-3 py-2 cursor-pointer text-sm font-inter',\n index === selectedIndex\n ? 'bg-primary-100 dark:bg-primary-900 text-primary-700 dark:text-primary-300'\n : 'hover:bg-gray-100 dark:hover:bg-black-700 text-gray-900 dark:text-white',\n )}\n onClick={() => insertSuggestion(suggestion)}\n onMouseEnter={() => setSelectedIndex(index)}\n >\n {suggestion}\n </div>\n ))}\n </div>,\n document.body,\n )}\n </div>\n\n {errorMessage && (\n <div className='pt-1'>\n <Typography className='text-error-500' size='extra-small' variant='medium' appearance='custom'>\n {errorMessage}\n </Typography>\n </div>\n )}\n </div>\n );\n};\n\nexport default React.memo(FormulaInput);\n\n\n\n"],"names":["FormulaInput","value","onChange","onFocus","onBlur","label","id","isRequired","tooltip","placeholder","disabled","errorMessage","width","suggestions","showRawValueProp","contentRef","useRef","inputWrapperRef","suggestionMenuRef","suggestionRefs","popperInstanceRef","showSuggestions","setShowSuggestions","useState","searchTerm","setSearchTerm","selectedIndex","setSelectedIndex","showRawValue","setShowRawValue","showSuggestionsRef","filteredSuggestionsRef","selectedIndexRef","valueRef","useEffect","useOutsideClick","filteredSuggestions","useMemo","lowerSearchTerm","suggestion","createPopper","handleChange","useCallback","event","rawValue","convertFromPills","textBeforeCursor","getTextBeforeCursor","lastAtSymbol","textAfterAt","handleFocus","handleBlur","relatedTarget","insertSuggestion","currentValue","spaceIndex","endPosition","beforeAt","afterCursor","newValue","handleKeyDown","isShowingSuggestions","currentFilteredSuggestions","currentSelectedIndex","key","prev","handlePaste","text","displayValue","convertToPills","jsxs","jsx","InputLabel","Tooltip","HelpIcon","Typography","ContentEditable","cn","IconButton","VisibilityOutlined","VisibilityOffOutlined","createPortal","e","index","el","FormulaInput$1","React"],"mappings":"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"}
1
+ {"version":3,"file":"FormulaInput.cjs.js","sources":["../../../../src/components/forms/formula-input/FormulaInput.tsx"],"sourcesContent":["import { Instance as PopperInstance, createPopper } from '@popperjs/core';\nimport cn from 'classnames';\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport ContentEditable, { ContentEditableEvent } from 'react-contenteditable';\nimport { createPortal } from 'react-dom';\nimport { VisibilityOffOutlined, VisibilityOutlined } from '@mui/icons-material';\n\nimport { Typography } from '../../data-display/typography/Typography';\nimport IconButton from '../../button/IconButton';\nimport Tooltip from '../../tooltip/Tooltip';\nimport { HelpIcon } from '../../icons/HelpIcon';\nimport { useOutsideClick } from '../../../hooks/useOutsideClick';\nimport { convertFromPills, convertToPills, getTextBeforeCursor } from './utils';\nimport { InputLabel } from '../shared/InputLabel';\n\nexport interface FormulaInputProps {\n /** Current value of the input */\n value: string;\n /** Callback when value changes */\n onChange: (value: string) => void;\n /** Callback when input receives focus */\n onFocus?: () => void;\n /** Callback when input loses focus */\n onBlur?: () => void;\n /** Label for the input field */\n label?: string;\n /** Unique identifier for the input */\n id: string;\n /** Whether the field is required */\n required?: boolean;\n /** Tooltip text displayed next to the label */\n tooltip?: string;\n /** Placeholder text */\n placeholder?: string;\n /** Whether the input is disabled */\n disabled?: boolean;\n /** Error message to display */\n errorMessage?: string;\n /** Width of the input */\n width?: string;\n /** List of suggestions for autocomplete */\n suggestions?: string[];\n /** Whether to show the raw value instead of pills */\n showRawValue?: boolean;\n}\n\n/**\n * FormulaInput component for entering formulas with variable suggestions\n * Variables are displayed as pills and can be inserted using @ trigger\n */\nconst FormulaInput: React.FC<FormulaInputProps> = ({\n value = '',\n onChange,\n onFocus,\n onBlur,\n label,\n id,\n required: isRequired,\n tooltip,\n placeholder,\n disabled,\n errorMessage,\n width = '100%',\n suggestions = [],\n showRawValue: showRawValueProp = false,\n}) => {\n const contentRef = useRef<HTMLElement & { isFocused?: boolean }>(null);\n const inputWrapperRef = useRef<HTMLDivElement>(null);\n const suggestionMenuRef = useRef<HTMLDivElement>(null);\n const suggestionRefs = useRef<(HTMLDivElement | null)[]>([]);\n const popperInstanceRef = useRef<PopperInstance | null>(null);\n const [showSuggestions, setShowSuggestions] = useState(false);\n const [searchTerm, setSearchTerm] = useState('');\n const [selectedIndex, setSelectedIndex] = useState(0);\n const [showRawValue, setShowRawValue] = useState(showRawValueProp);\n\n // Use refs to track current state for event handlers\n const showSuggestionsRef = useRef(showSuggestions);\n const filteredSuggestionsRef = useRef<string[]>([]);\n const selectedIndexRef = useRef(selectedIndex);\n const valueRef = useRef(value);\n\n // Keep refs in sync with state\n useEffect(() => {\n showSuggestionsRef.current = showSuggestions;\n }, [showSuggestions]);\n\n useEffect(() => {\n selectedIndexRef.current = selectedIndex;\n }, [selectedIndex]);\n\n useEffect(() => {\n valueRef.current = value;\n }, [value]);\n\n // Close suggestions when clicking outside\n useOutsideClick({\n ref: suggestionMenuRef,\n handler: () => {\n if (showSuggestions) {\n setShowSuggestions(false);\n }\n },\n });\n\n // Filter suggestions based on search term\n const filteredSuggestions = useMemo(() => {\n if (!searchTerm) return suggestions;\n\n const lowerSearchTerm = searchTerm.toLowerCase();\n return suggestions.filter((suggestion) => suggestion.toLowerCase().includes(lowerSearchTerm));\n }, [suggestions, searchTerm]);\n\n // Keep filtered suggestions ref in sync\n useEffect(() => {\n filteredSuggestionsRef.current = filteredSuggestions;\n }, [filteredSuggestions]);\n\n // Reset selected index when filtered suggestions change\n useEffect(() => {\n setSelectedIndex(0);\n }, [filteredSuggestions]);\n\n // Scroll selected suggestion into view\n useEffect(() => {\n if (showSuggestions && suggestionRefs.current[selectedIndex]) {\n suggestionRefs.current[selectedIndex]?.scrollIntoView({\n block: 'nearest',\n behavior: 'smooth',\n });\n }\n }, [selectedIndex, showSuggestions]);\n\n // Setup Popper for dynamic positioning\n useEffect(() => {\n if (showSuggestions && inputWrapperRef.current && suggestionMenuRef.current) {\n // Create popper instance with auto placement\n popperInstanceRef.current = createPopper(inputWrapperRef.current, suggestionMenuRef.current, {\n placement: 'bottom-start',\n strategy: 'fixed',\n modifiers: [\n {\n name: 'flip',\n options: {\n fallbackPlacements: ['top-start', 'bottom-start'],\n },\n },\n {\n name: 'preventOverflow',\n options: {\n boundary: 'viewport',\n padding: 8,\n },\n },\n {\n name: 'offset',\n options: {\n offset: [0, 4],\n },\n },\n ],\n });\n\n return () => {\n if (popperInstanceRef.current) {\n popperInstanceRef.current.destroy();\n popperInstanceRef.current = null;\n }\n };\n }\n }, [showSuggestions]);\n\n const handleChange = useCallback(\n (event: ContentEditableEvent) => {\n const rawValue = convertFromPills(event.target.value);\n onChange(rawValue);\n\n // Check if user typed @ (trigger for suggestions)\n const textBeforeCursor = getTextBeforeCursor();\n const lastAtSymbol = textBeforeCursor.lastIndexOf('@');\n\n if (lastAtSymbol !== -1) {\n // Get text after the @ symbol\n const textAfterAt = textBeforeCursor.slice(lastAtSymbol + 1);\n\n // Check if there's a space after @, which would end the suggestion context\n const hasSpace = textAfterAt.includes(' ');\n\n if (!hasSpace) {\n // We're in suggestion mode - show suggestions filtered by text after @\n setSearchTerm(textAfterAt);\n setShowSuggestions(true);\n } else {\n setShowSuggestions(false);\n }\n } else {\n setShowSuggestions(false);\n }\n },\n [onChange],\n );\n\n const handleFocus = useCallback(() => {\n if (contentRef.current) {\n contentRef.current.isFocused = true;\n }\n onFocus?.();\n }, [onFocus]);\n\n const handleBlur = useCallback(\n (event: React.FocusEvent) => {\n if (contentRef.current) {\n contentRef.current.isFocused = false;\n }\n\n // Check if the blur is due to clicking on a suggestion\n const relatedTarget = event.relatedTarget as HTMLElement;\n if (relatedTarget && suggestionMenuRef.current?.contains(relatedTarget)) {\n // Don't close suggestions if clicking on a suggestion\n return;\n }\n\n // Delay closing suggestions to allow click events to register\n setTimeout(() => {\n setShowSuggestions(false);\n }, 200);\n onBlur?.();\n },\n [onBlur],\n );\n\n const insertSuggestion = useCallback(\n (suggestion: string) => {\n if (!contentRef.current) return;\n\n // IMPORTANT: Use the value prop (not innerText) to preserve existing {{}} syntax\n // innerText only shows display text and loses the {{}} markers from pills\n const currentValue = valueRef.current;\n\n // Find the last occurrence of @ (trigger symbol) in the raw value\n const lastAtSymbol = currentValue.lastIndexOf('@');\n\n if (lastAtSymbol !== -1) {\n // Find where the @ trigger ends (space or end of string)\n const afterAt = currentValue.slice(lastAtSymbol + 1);\n const spaceIndex = afterAt.search(/\\s/);\n\n let endPosition: number;\n if (spaceIndex === -1) {\n // No space found, the incomplete variable goes to the end\n endPosition = currentValue.length;\n } else {\n // Space found, replace up to the space\n endPosition = lastAtSymbol + 1 + spaceIndex;\n }\n\n // Build the new value preserving all existing {{}} syntax\n // Replace @searchTerm with {{suggestion}}\n const beforeAt = currentValue.slice(0, lastAtSymbol);\n const afterCursor = currentValue.slice(endPosition);\n const newValue = `${beforeAt}{{${suggestion}}}${afterCursor}`;\n\n // Update through onChange\n onChange(newValue);\n\n // Close suggestions\n setShowSuggestions(false);\n setSearchTerm('');\n\n // Refocus the input after React updates\n setTimeout(() => {\n contentRef.current?.focus();\n }, 0);\n }\n },\n [onChange],\n );\n\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent) => {\n // Use refs to get the latest state values to avoid stale closures\n const isShowingSuggestions = showSuggestionsRef.current;\n const currentFilteredSuggestions = filteredSuggestionsRef.current;\n const currentSelectedIndex = selectedIndexRef.current;\n\n // Always prevent Enter key to avoid creating new lines/divs\n if (event.key === 'Enter') {\n event.preventDefault();\n event.stopPropagation();\n\n // If suggestions are showing, select the current suggestion\n if (isShowingSuggestions && currentFilteredSuggestions.length > 0 && currentFilteredSuggestions[currentSelectedIndex]) {\n insertSuggestion(currentFilteredSuggestions[currentSelectedIndex]);\n }\n return;\n }\n\n // When suggestions are visible, intercept navigation keys immediately\n if (isShowingSuggestions && currentFilteredSuggestions.length > 0) {\n const { key } = event;\n\n // Prevent default for all navigation keys when suggestions are shown\n if (['ArrowDown', 'ArrowUp', 'Escape', 'Tab'].includes(key)) {\n event.preventDefault();\n event.stopPropagation();\n\n switch (key) {\n case 'ArrowDown':\n setSelectedIndex((prev) => (prev < currentFilteredSuggestions.length - 1 ? prev + 1 : prev));\n break;\n case 'ArrowUp':\n setSelectedIndex((prev) => (prev > 0 ? prev - 1 : 0));\n break;\n case 'Escape':\n setShowSuggestions(false);\n break;\n case 'Tab':\n if (currentFilteredSuggestions[currentSelectedIndex]) {\n insertSuggestion(currentFilteredSuggestions[currentSelectedIndex]);\n }\n break;\n }\n }\n }\n },\n [insertSuggestion],\n );\n\n const handlePaste = useCallback((event: React.ClipboardEvent<HTMLDivElement>) => {\n event.preventDefault();\n const text = event.clipboardData.getData('text/plain');\n document.execCommand('insertText', false, text);\n }, []);\n\n const displayValue = useMemo(() => {\n if (showRawValue) {\n return value;\n }\n return convertToPills(value);\n }, [value, showRawValue]);\n\n return (\n <div className='w-full'>\n {label && (\n <div className='text-xs font-medium text-gray-600 inline-flex items-center gap-1 font-inter text-left whitespace-nowrap flex-wrap'>\n <InputLabel label={label || \"\"} required={isRequired || false} />\n {tooltip && (\n <Tooltip placement='top' title={tooltip}>\n <div className='cursor-pointer'>\n <HelpIcon className=\"w-icon-sm h-icon-sm\" />\n </div>\n </Tooltip>\n )}\n </div>\n )}\n\n <div className='relative' ref={inputWrapperRef}>\n {!value?.trim() ? (\n <div\n className='absolute top-0 left-0 w-full h-full text-gray-400 flex items-center cursor-text px-3 z-50'\n onClick={() => contentRef.current?.focus()}\n >\n <Typography size='extra-small' variant='medium'>\n {placeholder}\n </Typography>\n </div>\n ) : null}\n\n <div className='relative'>\n <ContentEditable\n innerRef={contentRef}\n className={cn(\n 'min-h-[42px] rounded-lg p-2.5',\n 'text-sm font-inter block font-medium border text-gray-900 dark:text-white whitespace-normal break-words text-left',\n disabled ? 'bg-neutral-100 dark:bg-black-800' : 'bg-white dark:bg-black-800',\n !disabled && 'pr-[60px]',\n errorMessage ? '!border-error-500' : 'border-gray-300 dark:border-black-600 focus:ring-blue-500 focus:border-blue-500',\n 'cursor-text',\n )}\n style={{\n width: width,\n wordBreak: 'break-word',\n }}\n html={displayValue}\n onChange={!disabled ? handleChange : () => null}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onKeyDownCapture={handleKeyDown}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n disabled={disabled}\n id={id}\n />\n\n {!disabled && (\n <div className='absolute right-0 top-0 bottom-0 flex items-center align-middle justify-center p-3 gap-2'>\n <IconButton tooltip={showRawValue ? 'Show Formatted' : 'Show Raw Value'} variant='ghost' onClick={() => setShowRawValue(!showRawValue)}>\n {showRawValue ? <VisibilityOutlined sx={{ fontSize: 18 }} /> : <VisibilityOffOutlined sx={{ fontSize: 18 }} />}\n </IconButton>\n </div>\n )}\n </div>\n\n {showSuggestions &&\n filteredSuggestions.length > 0 &&\n createPortal(\n <div\n ref={suggestionMenuRef}\n className='z-[3000] bg-white dark:bg-black-800 border border-gray-300 dark:border-black-600 rounded-lg shadow-lg max-h-60 overflow-y-auto min-w-[200px]'\n onMouseDown={(e) => {\n // Prevent blur when clicking on suggestions\n e.preventDefault();\n }}\n >\n {filteredSuggestions.map((suggestion, index) => (\n <div\n key={suggestion}\n ref={(el) => (suggestionRefs.current[index] = el)}\n className={cn(\n 'px-3 py-2 cursor-pointer text-sm font-inter',\n index === selectedIndex\n ? 'bg-primary-100 dark:bg-primary-900 text-primary-700 dark:text-primary-300'\n : 'hover:bg-gray-100 dark:hover:bg-black-700 text-gray-900 dark:text-white',\n )}\n onClick={() => insertSuggestion(suggestion)}\n onMouseEnter={() => setSelectedIndex(index)}\n >\n {suggestion}\n </div>\n ))}\n </div>,\n document.body,\n )}\n </div>\n\n {errorMessage && (\n <div className='pt-1'>\n <Typography className='text-error-500' size='extra-small' variant='medium' appearance='custom'>\n {errorMessage}\n </Typography>\n </div>\n )}\n </div>\n );\n};\n\nexport default React.memo(FormulaInput);\n\n\n\n"],"names":["FormulaInput","value","onChange","onFocus","onBlur","label","id","isRequired","tooltip","placeholder","disabled","errorMessage","width","suggestions","showRawValueProp","contentRef","useRef","inputWrapperRef","suggestionMenuRef","suggestionRefs","popperInstanceRef","showSuggestions","setShowSuggestions","useState","searchTerm","setSearchTerm","selectedIndex","setSelectedIndex","showRawValue","setShowRawValue","showSuggestionsRef","filteredSuggestionsRef","selectedIndexRef","valueRef","useEffect","useOutsideClick","filteredSuggestions","useMemo","lowerSearchTerm","suggestion","createPopper","handleChange","useCallback","event","rawValue","convertFromPills","textBeforeCursor","getTextBeforeCursor","lastAtSymbol","textAfterAt","handleFocus","handleBlur","relatedTarget","insertSuggestion","currentValue","spaceIndex","endPosition","beforeAt","afterCursor","newValue","handleKeyDown","isShowingSuggestions","currentFilteredSuggestions","currentSelectedIndex","key","prev","handlePaste","text","displayValue","convertToPills","jsxs","jsx","InputLabel","Tooltip","HelpIcon","Typography","ContentEditable","cn","IconButton","VisibilityOutlined","VisibilityOffOutlined","createPortal","e","index","el","FormulaInput$1","React"],"mappings":"4kBAkDMA,GAA4C,CAAC,CACjD,MAAAC,EAAQ,GACR,SAAAC,EACA,QAAAC,EACA,OAAAC,EACA,MAAAC,EACA,GAAAC,EACA,SAAUC,EACV,QAAAC,EACA,YAAAC,EACA,SAAAC,EACA,aAAAC,EACA,MAAAC,EAAQ,OACR,YAAAC,EAAc,CAAA,EACd,aAAcC,EAAmB,EACnC,IAAM,CACJ,MAAMC,EAAaC,EAAAA,OAA8C,IAAI,EAC/DC,EAAkBD,EAAAA,OAAuB,IAAI,EAC7CE,EAAoBF,EAAAA,OAAuB,IAAI,EAC/CG,EAAiBH,EAAAA,OAAkC,EAAE,EACrDI,EAAoBJ,EAAAA,OAA8B,IAAI,EACtD,CAACK,EAAiBC,CAAkB,EAAIC,EAAAA,SAAS,EAAK,EACtD,CAACC,EAAYC,CAAa,EAAIF,EAAAA,SAAS,EAAE,EACzC,CAACG,EAAeC,CAAgB,EAAIJ,EAAAA,SAAS,CAAC,EAC9C,CAACK,EAAcC,CAAe,EAAIN,EAAAA,SAAST,CAAgB,EAG3DgB,EAAqBd,EAAAA,OAAOK,CAAe,EAC3CU,EAAyBf,EAAAA,OAAiB,EAAE,EAC5CgB,EAAmBhB,EAAAA,OAAOU,CAAa,EACvCO,EAAWjB,EAAAA,OAAOf,CAAK,EAG7BiC,EAAAA,UAAU,IAAM,CACdJ,EAAmB,QAAUT,CAC/B,EAAG,CAACA,CAAe,CAAC,EAEpBa,EAAAA,UAAU,IAAM,CACdF,EAAiB,QAAUN,CAC7B,EAAG,CAACA,CAAa,CAAC,EAElBQ,EAAAA,UAAU,IAAM,CACdD,EAAS,QAAUhC,CACrB,EAAG,CAACA,CAAK,CAAC,EAGVkC,mBAAgB,CACd,IAAKjB,EACL,QAAS,IAAM,CACTG,GACFC,EAAmB,EAAK,CAE5B,CAAA,CACD,EAGD,MAAMc,EAAsBC,EAAAA,QAAQ,IAAM,CACxC,GAAI,CAACb,EAAY,OAAOX,EAExB,MAAMyB,EAAkBd,EAAW,YAAA,EACnC,OAAOX,EAAY,OAAQ0B,GAAeA,EAAW,YAAA,EAAc,SAASD,CAAe,CAAC,CAC9F,EAAG,CAACzB,EAAaW,CAAU,CAAC,EAG5BU,EAAAA,UAAU,IAAM,CACdH,EAAuB,QAAUK,CACnC,EAAG,CAACA,CAAmB,CAAC,EAGxBF,EAAAA,UAAU,IAAM,CACdP,EAAiB,CAAC,CACpB,EAAG,CAACS,CAAmB,CAAC,EAGxBF,EAAAA,UAAU,IAAM,CACVb,GAAmBF,EAAe,QAAQO,CAAa,GACzDP,EAAe,QAAQO,CAAa,GAAG,eAAe,CACpD,MAAO,UACP,SAAU,QAAA,CACX,CAEL,EAAG,CAACA,EAAeL,CAAe,CAAC,EAGnCa,EAAAA,UAAU,IAAM,CACd,GAAIb,GAAmBJ,EAAgB,SAAWC,EAAkB,QAElE,OAAAE,EAAkB,QAAUoB,GAAAA,aAAavB,EAAgB,QAASC,EAAkB,QAAS,CAC3F,UAAW,eACX,SAAU,QACV,UAAW,CACT,CACE,KAAM,OACN,QAAS,CACP,mBAAoB,CAAC,YAAa,cAAc,CAAA,CAClD,EAEF,CACE,KAAM,kBACN,QAAS,CACP,SAAU,WACV,QAAS,CAAA,CACX,EAEF,CACE,KAAM,SACN,QAAS,CACP,OAAQ,CAAC,EAAG,CAAC,CAAA,CACf,CACF,CACF,CACD,EAEM,IAAM,CACPE,EAAkB,UACpBA,EAAkB,QAAQ,QAAA,EAC1BA,EAAkB,QAAU,KAEhC,CAEJ,EAAG,CAACC,CAAe,CAAC,EAEpB,MAAMoB,EAAeC,EAAAA,YAClBC,GAAgC,CAC/B,MAAMC,EAAWC,EAAAA,iBAAiBF,EAAM,OAAO,KAAK,EACpDzC,EAAS0C,CAAQ,EAGjB,MAAME,EAAmBC,EAAAA,oBAAA,EACnBC,EAAeF,EAAiB,YAAY,GAAG,EAErD,GAAIE,IAAiB,GAAI,CAEvB,MAAMC,EAAcH,EAAiB,MAAME,EAAe,CAAC,EAG1CC,EAAY,SAAS,GAAG,EAOvC3B,EAAmB,EAAK,GAHxBG,EAAcwB,CAAW,EACzB3B,EAAmB,EAAI,EAI3B,MACEA,EAAmB,EAAK,CAE5B,EACA,CAACpB,CAAQ,CAAA,EAGLgD,EAAcR,EAAAA,YAAY,IAAM,CAChC3B,EAAW,UACbA,EAAW,QAAQ,UAAY,IAEjCZ,IAAA,CACF,EAAG,CAACA,CAAO,CAAC,EAENgD,EAAaT,EAAAA,YAChBC,GAA4B,CACvB5B,EAAW,UACbA,EAAW,QAAQ,UAAY,IAIjC,MAAMqC,EAAgBT,EAAM,cACxBS,GAAiBlC,EAAkB,SAAS,SAASkC,CAAa,IAMtE,WAAW,IAAM,CACf9B,EAAmB,EAAK,CAC1B,EAAG,GAAG,EACNlB,IAAA,EACF,EACA,CAACA,CAAM,CAAA,EAGHiD,EAAmBX,EAAAA,YACtBH,GAAuB,CACtB,GAAI,CAACxB,EAAW,QAAS,OAIzB,MAAMuC,EAAerB,EAAS,QAGxBe,EAAeM,EAAa,YAAY,GAAG,EAEjD,GAAIN,IAAiB,GAAI,CAGvB,MAAMO,EADUD,EAAa,MAAMN,EAAe,CAAC,EACxB,OAAO,IAAI,EAEtC,IAAIQ,EACAD,IAAe,GAEjBC,EAAcF,EAAa,OAG3BE,EAAcR,EAAe,EAAIO,EAKnC,MAAME,EAAWH,EAAa,MAAM,EAAGN,CAAY,EAC7CU,EAAcJ,EAAa,MAAME,CAAW,EAC5CG,EAAW,GAAGF,CAAQ,KAAKlB,CAAU,KAAKmB,CAAW,GAG3DxD,EAASyD,CAAQ,EAGjBrC,EAAmB,EAAK,EACxBG,EAAc,EAAE,EAGhB,WAAW,IAAM,CACfV,EAAW,SAAS,MAAA,CACtB,EAAG,CAAC,CACN,CACF,EACA,CAACb,CAAQ,CAAA,EAGL0D,EAAgBlB,EAAAA,YACnBC,GAA+B,CAE9B,MAAMkB,EAAuB/B,EAAmB,QAC1CgC,EAA6B/B,EAAuB,QACpDgC,EAAuB/B,EAAiB,QAG9C,GAAIW,EAAM,MAAQ,QAAS,CACzBA,EAAM,eAAA,EACNA,EAAM,gBAAA,EAGFkB,GAAwBC,EAA2B,OAAS,GAAKA,EAA2BC,CAAoB,GAClHV,EAAiBS,EAA2BC,CAAoB,CAAC,EAEnE,MACF,CAGA,GAAIF,GAAwBC,EAA2B,OAAS,EAAG,CACjE,KAAM,CAAE,IAAAE,GAAQrB,EAGhB,GAAI,CAAC,YAAa,UAAW,SAAU,KAAK,EAAE,SAASqB,CAAG,EAIxD,OAHArB,EAAM,eAAA,EACNA,EAAM,gBAAA,EAEEqB,EAAA,CACN,IAAK,YACHrC,EAAkBsC,GAAUA,EAAOH,EAA2B,OAAS,EAAIG,EAAO,EAAIA,CAAK,EAC3F,MACF,IAAK,UACHtC,EAAkBsC,GAAUA,EAAO,EAAIA,EAAO,EAAI,CAAE,EACpD,MACF,IAAK,SACH3C,EAAmB,EAAK,EACxB,MACF,IAAK,MACCwC,EAA2BC,CAAoB,GACjDV,EAAiBS,EAA2BC,CAAoB,CAAC,EAEnE,KAAA,CAGR,CACF,EACA,CAACV,CAAgB,CAAA,EAGba,EAAcxB,cAAaC,GAAgD,CAC/EA,EAAM,eAAA,EACN,MAAMwB,EAAOxB,EAAM,cAAc,QAAQ,YAAY,EACrD,SAAS,YAAY,aAAc,GAAOwB,CAAI,CAChD,EAAG,CAAA,CAAE,EAECC,EAAe/B,EAAAA,QAAQ,IACvBT,EACK3B,EAEFoE,EAAAA,eAAepE,CAAK,EAC1B,CAACA,EAAO2B,CAAY,CAAC,EAExB,OACE0C,EAAAA,KAAC,MAAA,CAAI,UAAU,SACZ,SAAA,CAAAjE,GACCiE,EAAAA,KAAC,MAAA,CAAI,UAAU,oHACb,SAAA,CAAAC,MAACC,GAAAA,YAAW,MAAOnE,GAAS,GAAI,SAAUE,GAAc,GAAO,EAC9DC,GACC+D,EAAAA,IAACE,GAAA,CAAQ,UAAU,MAAM,MAAOjE,EAC9B,SAAA+D,MAAC,MAAA,CAAI,UAAU,iBACb,SAAAA,MAACG,GAAAA,SAAA,CAAS,UAAU,sBAAsB,EAC5C,CAAA,CACF,CAAA,EAEJ,EAGFJ,EAAAA,KAAC,MAAA,CAAI,UAAU,WAAW,IAAKrD,EAC5B,SAAA,CAAChB,GAAO,OASL,KARFsE,EAAAA,IAAC,MAAA,CACC,UAAU,4FACV,QAAS,IAAMxD,EAAW,SAAS,MAAA,EAEnC,eAAC4D,EAAAA,WAAA,CAAW,KAAK,cAAc,QAAQ,SACpC,SAAAlE,CAAA,CACH,CAAA,CAAA,EAIJ6D,EAAAA,KAAC,MAAA,CAAI,UAAU,WACb,SAAA,CAAAC,EAAAA,IAACK,GAAA,CACC,SAAU7D,EACV,UAAW8D,EACT,gCACA,oHACAnE,EAAW,mCAAqC,6BAChD,CAACA,GAAY,YACbC,EAAe,oBAAsB,kFACrC,aAAA,EAEF,MAAO,CACL,MAAAC,EACA,UAAW,YAAA,EAEb,KAAMwD,EACN,SAAW1D,EAA0B,IAAM,KAArB+B,EACtB,QAASS,EACT,OAAQC,EACR,iBAAkBS,EAClB,UAAWA,EACX,QAASM,EACT,SAAAxD,EACA,GAAAJ,CAAA,CAAA,EAGD,CAACI,GACA6D,EAAAA,IAAC,MAAA,CAAI,UAAU,0FACb,SAAAA,MAACO,GAAA,CAAW,QAASlD,EAAe,iBAAmB,iBAAkB,QAAQ,QAAQ,QAAS,IAAMC,EAAgB,CAACD,CAAY,EAClI,WAAe2C,MAACQ,EAAAA,mBAAA,CAAmB,GAAI,CAAE,SAAU,EAAA,CAAG,CAAG,EAAKR,MAACS,EAAAA,uBAAsB,GAAI,CAAE,SAAU,EAAA,CAAG,CAAG,EAC9G,CAAA,CACF,CAAA,EAEJ,EAEC3D,GACCe,EAAoB,OAAS,GAC7B6C,GAAAA,aACEV,EAAAA,IAAC,MAAA,CACC,IAAKrD,EACL,UAAU,+IACV,YAAcgE,GAAM,CAElBA,EAAE,eAAA,CACJ,EAEC,SAAA9C,EAAoB,IAAI,CAACG,EAAY4C,IACpCZ,EAAAA,IAAC,MAAA,CAEC,IAAMa,GAAQjE,EAAe,QAAQgE,CAAK,EAAIC,EAC9C,UAAWP,EACT,8CACAM,IAAUzD,EACN,4EACA,yEAAA,EAEN,QAAS,IAAM2B,EAAiBd,CAAU,EAC1C,aAAc,IAAMZ,EAAiBwD,CAAK,EAEzC,SAAA5C,CAAA,EAXIA,CAAA,CAaR,CAAA,CAAA,EAEH,SAAS,IAAA,CACX,EACJ,EAEC5B,GACC4D,EAAAA,IAAC,MAAA,CAAI,UAAU,OACb,eAACI,EAAAA,WAAA,CAAW,UAAU,iBAAiB,KAAK,cAAc,QAAQ,SAAS,WAAW,SACnF,WACH,CAAA,CACF,CAAA,EAEJ,CAEJ,EAEAU,GAAeC,EAAM,KAAKtF,EAAY"}
@@ -28,7 +28,7 @@ const be = ({
28
28
  suggestions: T = [],
29
29
  showRawValue: G = !1
30
30
  }) => {
31
- const c = a(null), C = a(null), g = a(null), D = a([]), k = a(null), [s, f] = v(!1), [N, O] = v(""), [m, y] = v(0), [b, J] = v(G), z = a(s), E = a([]), B = a(m), $ = a(u);
31
+ const c = a(null), N = a(null), g = a(null), C = a([]), k = a(null), [s, f] = v(!1), [D, O] = v(""), [m, y] = v(0), [b, J] = v(G), z = a(s), E = a([]), B = a(m), $ = a(u);
32
32
  d(() => {
33
33
  z.current = s;
34
34
  }, [s]), d(() => {
@@ -42,22 +42,22 @@ const be = ({
42
42
  }
43
43
  });
44
44
  const w = L(() => {
45
- if (!N) return T;
46
- const e = N.toLowerCase();
45
+ if (!D) return T;
46
+ const e = D.toLowerCase();
47
47
  return T.filter((t) => t.toLowerCase().includes(e));
48
- }, [T, N]);
48
+ }, [T, D]);
49
49
  d(() => {
50
50
  E.current = w;
51
51
  }, [w]), d(() => {
52
52
  y(0);
53
53
  }, [w]), d(() => {
54
- s && D.current[m] && D.current[m]?.scrollIntoView({
54
+ s && C.current[m] && C.current[m]?.scrollIntoView({
55
55
  block: "nearest",
56
56
  behavior: "smooth"
57
57
  });
58
58
  }, [m, s]), d(() => {
59
- if (s && C.current && g.current)
60
- return k.current = ge(C.current, g.current, {
59
+ if (s && N.current && g.current)
60
+ return k.current = ge(N.current, g.current, {
61
61
  placement: "bottom-start",
62
62
  strategy: "fixed",
63
63
  modifiers: [
@@ -158,9 +158,9 @@ const be = ({
158
158
  return /* @__PURE__ */ R("div", { className: "w-full", children: [
159
159
  P && /* @__PURE__ */ R("div", { className: "text-xs font-medium text-gray-600 inline-flex items-center gap-1 font-inter text-left whitespace-nowrap flex-wrap", children: [
160
160
  /* @__PURE__ */ o(he, { label: P || "", required: U || !1 }),
161
- F && /* @__PURE__ */ o(ie, { placement: "top", title: F, children: /* @__PURE__ */ o("div", { className: "cursor-pointer", children: /* @__PURE__ */ o(ue, {}) }) })
161
+ F && /* @__PURE__ */ o(ie, { placement: "top", title: F, children: /* @__PURE__ */ o("div", { className: "cursor-pointer", children: /* @__PURE__ */ o(ue, { className: "w-icon-sm h-icon-sm" }) }) })
162
162
  ] }),
163
- /* @__PURE__ */ R("div", { className: "relative", ref: C, children: [
163
+ /* @__PURE__ */ R("div", { className: "relative", ref: N, children: [
164
164
  u?.trim() ? null : /* @__PURE__ */ o(
165
165
  "div",
166
166
  {
@@ -211,7 +211,7 @@ const be = ({
211
211
  children: w.map((e, t) => /* @__PURE__ */ o(
212
212
  "div",
213
213
  {
214
- ref: (r) => D.current[t] = r,
214
+ ref: (r) => C.current[t] = r,
215
215
  className: K(
216
216
  "px-3 py-2 cursor-pointer text-sm font-inter",
217
217
  t === m ? "bg-primary-100 dark:bg-primary-900 text-primary-700 dark:text-primary-300" : "hover:bg-gray-100 dark:hover:bg-black-700 text-gray-900 dark:text-white"
@@ -1 +1 @@
1
- {"version":3,"file":"FormulaInput.es.js","sources":["../../../../src/components/forms/formula-input/FormulaInput.tsx"],"sourcesContent":["import { Instance as PopperInstance, createPopper } from '@popperjs/core';\nimport cn from 'classnames';\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport ContentEditable, { ContentEditableEvent } from 'react-contenteditable';\nimport { createPortal } from 'react-dom';\nimport { VisibilityOffOutlined, VisibilityOutlined } from '@mui/icons-material';\n\nimport { Typography } from '../../data-display/typography/Typography';\nimport IconButton from '../../button/IconButton';\nimport Tooltip from '../../tooltip/Tooltip';\nimport { HelpIcon } from '../../icons/HelpIcon';\nimport { useOutsideClick } from '../../../hooks/useOutsideClick';\nimport { convertFromPills, convertToPills, getTextBeforeCursor } from './utils';\nimport { InputLabel } from '../shared/InputLabel';\n\nexport interface FormulaInputProps {\n /** Current value of the input */\n value: string;\n /** Callback when value changes */\n onChange: (value: string) => void;\n /** Callback when input receives focus */\n onFocus?: () => void;\n /** Callback when input loses focus */\n onBlur?: () => void;\n /** Label for the input field */\n label?: string;\n /** Unique identifier for the input */\n id: string;\n /** Whether the field is required */\n required?: boolean;\n /** Tooltip text displayed next to the label */\n tooltip?: string;\n /** Placeholder text */\n placeholder?: string;\n /** Whether the input is disabled */\n disabled?: boolean;\n /** Error message to display */\n errorMessage?: string;\n /** Width of the input */\n width?: string;\n /** List of suggestions for autocomplete */\n suggestions?: string[];\n /** Whether to show the raw value instead of pills */\n showRawValue?: boolean;\n}\n\n/**\n * FormulaInput component for entering formulas with variable suggestions\n * Variables are displayed as pills and can be inserted using @ trigger\n */\nconst FormulaInput: React.FC<FormulaInputProps> = ({\n value = '',\n onChange,\n onFocus,\n onBlur,\n label,\n id,\n required: isRequired,\n tooltip,\n placeholder,\n disabled,\n errorMessage,\n width = '100%',\n suggestions = [],\n showRawValue: showRawValueProp = false,\n}) => {\n const contentRef = useRef<HTMLElement & { isFocused?: boolean }>(null);\n const inputWrapperRef = useRef<HTMLDivElement>(null);\n const suggestionMenuRef = useRef<HTMLDivElement>(null);\n const suggestionRefs = useRef<(HTMLDivElement | null)[]>([]);\n const popperInstanceRef = useRef<PopperInstance | null>(null);\n const [showSuggestions, setShowSuggestions] = useState(false);\n const [searchTerm, setSearchTerm] = useState('');\n const [selectedIndex, setSelectedIndex] = useState(0);\n const [showRawValue, setShowRawValue] = useState(showRawValueProp);\n\n // Use refs to track current state for event handlers\n const showSuggestionsRef = useRef(showSuggestions);\n const filteredSuggestionsRef = useRef<string[]>([]);\n const selectedIndexRef = useRef(selectedIndex);\n const valueRef = useRef(value);\n\n // Keep refs in sync with state\n useEffect(() => {\n showSuggestionsRef.current = showSuggestions;\n }, [showSuggestions]);\n\n useEffect(() => {\n selectedIndexRef.current = selectedIndex;\n }, [selectedIndex]);\n\n useEffect(() => {\n valueRef.current = value;\n }, [value]);\n\n // Close suggestions when clicking outside\n useOutsideClick({\n ref: suggestionMenuRef,\n handler: () => {\n if (showSuggestions) {\n setShowSuggestions(false);\n }\n },\n });\n\n // Filter suggestions based on search term\n const filteredSuggestions = useMemo(() => {\n if (!searchTerm) return suggestions;\n\n const lowerSearchTerm = searchTerm.toLowerCase();\n return suggestions.filter((suggestion) => suggestion.toLowerCase().includes(lowerSearchTerm));\n }, [suggestions, searchTerm]);\n\n // Keep filtered suggestions ref in sync\n useEffect(() => {\n filteredSuggestionsRef.current = filteredSuggestions;\n }, [filteredSuggestions]);\n\n // Reset selected index when filtered suggestions change\n useEffect(() => {\n setSelectedIndex(0);\n }, [filteredSuggestions]);\n\n // Scroll selected suggestion into view\n useEffect(() => {\n if (showSuggestions && suggestionRefs.current[selectedIndex]) {\n suggestionRefs.current[selectedIndex]?.scrollIntoView({\n block: 'nearest',\n behavior: 'smooth',\n });\n }\n }, [selectedIndex, showSuggestions]);\n\n // Setup Popper for dynamic positioning\n useEffect(() => {\n if (showSuggestions && inputWrapperRef.current && suggestionMenuRef.current) {\n // Create popper instance with auto placement\n popperInstanceRef.current = createPopper(inputWrapperRef.current, suggestionMenuRef.current, {\n placement: 'bottom-start',\n strategy: 'fixed',\n modifiers: [\n {\n name: 'flip',\n options: {\n fallbackPlacements: ['top-start', 'bottom-start'],\n },\n },\n {\n name: 'preventOverflow',\n options: {\n boundary: 'viewport',\n padding: 8,\n },\n },\n {\n name: 'offset',\n options: {\n offset: [0, 4],\n },\n },\n ],\n });\n\n return () => {\n if (popperInstanceRef.current) {\n popperInstanceRef.current.destroy();\n popperInstanceRef.current = null;\n }\n };\n }\n }, [showSuggestions]);\n\n const handleChange = useCallback(\n (event: ContentEditableEvent) => {\n const rawValue = convertFromPills(event.target.value);\n onChange(rawValue);\n\n // Check if user typed @ (trigger for suggestions)\n const textBeforeCursor = getTextBeforeCursor();\n const lastAtSymbol = textBeforeCursor.lastIndexOf('@');\n\n if (lastAtSymbol !== -1) {\n // Get text after the @ symbol\n const textAfterAt = textBeforeCursor.slice(lastAtSymbol + 1);\n\n // Check if there's a space after @, which would end the suggestion context\n const hasSpace = textAfterAt.includes(' ');\n\n if (!hasSpace) {\n // We're in suggestion mode - show suggestions filtered by text after @\n setSearchTerm(textAfterAt);\n setShowSuggestions(true);\n } else {\n setShowSuggestions(false);\n }\n } else {\n setShowSuggestions(false);\n }\n },\n [onChange],\n );\n\n const handleFocus = useCallback(() => {\n if (contentRef.current) {\n contentRef.current.isFocused = true;\n }\n onFocus?.();\n }, [onFocus]);\n\n const handleBlur = useCallback(\n (event: React.FocusEvent) => {\n if (contentRef.current) {\n contentRef.current.isFocused = false;\n }\n\n // Check if the blur is due to clicking on a suggestion\n const relatedTarget = event.relatedTarget as HTMLElement;\n if (relatedTarget && suggestionMenuRef.current?.contains(relatedTarget)) {\n // Don't close suggestions if clicking on a suggestion\n return;\n }\n\n // Delay closing suggestions to allow click events to register\n setTimeout(() => {\n setShowSuggestions(false);\n }, 200);\n onBlur?.();\n },\n [onBlur],\n );\n\n const insertSuggestion = useCallback(\n (suggestion: string) => {\n if (!contentRef.current) return;\n\n // IMPORTANT: Use the value prop (not innerText) to preserve existing {{}} syntax\n // innerText only shows display text and loses the {{}} markers from pills\n const currentValue = valueRef.current;\n\n // Find the last occurrence of @ (trigger symbol) in the raw value\n const lastAtSymbol = currentValue.lastIndexOf('@');\n\n if (lastAtSymbol !== -1) {\n // Find where the @ trigger ends (space or end of string)\n const afterAt = currentValue.slice(lastAtSymbol + 1);\n const spaceIndex = afterAt.search(/\\s/);\n\n let endPosition: number;\n if (spaceIndex === -1) {\n // No space found, the incomplete variable goes to the end\n endPosition = currentValue.length;\n } else {\n // Space found, replace up to the space\n endPosition = lastAtSymbol + 1 + spaceIndex;\n }\n\n // Build the new value preserving all existing {{}} syntax\n // Replace @searchTerm with {{suggestion}}\n const beforeAt = currentValue.slice(0, lastAtSymbol);\n const afterCursor = currentValue.slice(endPosition);\n const newValue = `${beforeAt}{{${suggestion}}}${afterCursor}`;\n\n // Update through onChange\n onChange(newValue);\n\n // Close suggestions\n setShowSuggestions(false);\n setSearchTerm('');\n\n // Refocus the input after React updates\n setTimeout(() => {\n contentRef.current?.focus();\n }, 0);\n }\n },\n [onChange],\n );\n\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent) => {\n // Use refs to get the latest state values to avoid stale closures\n const isShowingSuggestions = showSuggestionsRef.current;\n const currentFilteredSuggestions = filteredSuggestionsRef.current;\n const currentSelectedIndex = selectedIndexRef.current;\n\n // Always prevent Enter key to avoid creating new lines/divs\n if (event.key === 'Enter') {\n event.preventDefault();\n event.stopPropagation();\n\n // If suggestions are showing, select the current suggestion\n if (isShowingSuggestions && currentFilteredSuggestions.length > 0 && currentFilteredSuggestions[currentSelectedIndex]) {\n insertSuggestion(currentFilteredSuggestions[currentSelectedIndex]);\n }\n return;\n }\n\n // When suggestions are visible, intercept navigation keys immediately\n if (isShowingSuggestions && currentFilteredSuggestions.length > 0) {\n const { key } = event;\n\n // Prevent default for all navigation keys when suggestions are shown\n if (['ArrowDown', 'ArrowUp', 'Escape', 'Tab'].includes(key)) {\n event.preventDefault();\n event.stopPropagation();\n\n switch (key) {\n case 'ArrowDown':\n setSelectedIndex((prev) => (prev < currentFilteredSuggestions.length - 1 ? prev + 1 : prev));\n break;\n case 'ArrowUp':\n setSelectedIndex((prev) => (prev > 0 ? prev - 1 : 0));\n break;\n case 'Escape':\n setShowSuggestions(false);\n break;\n case 'Tab':\n if (currentFilteredSuggestions[currentSelectedIndex]) {\n insertSuggestion(currentFilteredSuggestions[currentSelectedIndex]);\n }\n break;\n }\n }\n }\n },\n [insertSuggestion],\n );\n\n const handlePaste = useCallback((event: React.ClipboardEvent<HTMLDivElement>) => {\n event.preventDefault();\n const text = event.clipboardData.getData('text/plain');\n document.execCommand('insertText', false, text);\n }, []);\n\n const displayValue = useMemo(() => {\n if (showRawValue) {\n return value;\n }\n return convertToPills(value);\n }, [value, showRawValue]);\n\n return (\n <div className='w-full'>\n {label && (\n <div className='text-xs font-medium text-gray-600 inline-flex items-center gap-1 font-inter text-left whitespace-nowrap flex-wrap'>\n <InputLabel label={label || \"\"} required={isRequired || false} />\n {tooltip && (\n <Tooltip placement='top' title={tooltip}>\n <div className='cursor-pointer'>\n <HelpIcon />\n </div>\n </Tooltip>\n )}\n </div>\n )}\n\n <div className='relative' ref={inputWrapperRef}>\n {!value?.trim() ? (\n <div\n className='absolute top-0 left-0 w-full h-full text-gray-400 flex items-center cursor-text px-3 z-50'\n onClick={() => contentRef.current?.focus()}\n >\n <Typography size='extra-small' variant='medium'>\n {placeholder}\n </Typography>\n </div>\n ) : null}\n\n <div className='relative'>\n <ContentEditable\n innerRef={contentRef}\n className={cn(\n 'min-h-[42px] rounded-lg p-2.5',\n 'text-sm font-inter block font-medium border text-gray-900 dark:text-white whitespace-normal break-words text-left',\n disabled ? 'bg-neutral-100 dark:bg-black-800' : 'bg-white dark:bg-black-800',\n !disabled && 'pr-[60px]',\n errorMessage ? '!border-error-500' : 'border-gray-300 dark:border-black-600 focus:ring-blue-500 focus:border-blue-500',\n 'cursor-text',\n )}\n style={{\n width: width,\n wordBreak: 'break-word',\n }}\n html={displayValue}\n onChange={!disabled ? handleChange : () => null}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onKeyDownCapture={handleKeyDown}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n disabled={disabled}\n id={id}\n />\n\n {!disabled && (\n <div className='absolute right-0 top-0 bottom-0 flex items-center align-middle justify-center p-3 gap-2'>\n <IconButton tooltip={showRawValue ? 'Show Formatted' : 'Show Raw Value'} variant='ghost' onClick={() => setShowRawValue(!showRawValue)}>\n {showRawValue ? <VisibilityOutlined sx={{ fontSize: 18 }} /> : <VisibilityOffOutlined sx={{ fontSize: 18 }} />}\n </IconButton>\n </div>\n )}\n </div>\n\n {showSuggestions &&\n filteredSuggestions.length > 0 &&\n createPortal(\n <div\n ref={suggestionMenuRef}\n className='z-[3000] bg-white dark:bg-black-800 border border-gray-300 dark:border-black-600 rounded-lg shadow-lg max-h-60 overflow-y-auto min-w-[200px]'\n onMouseDown={(e) => {\n // Prevent blur when clicking on suggestions\n e.preventDefault();\n }}\n >\n {filteredSuggestions.map((suggestion, index) => (\n <div\n key={suggestion}\n ref={(el) => (suggestionRefs.current[index] = el)}\n className={cn(\n 'px-3 py-2 cursor-pointer text-sm font-inter',\n index === selectedIndex\n ? 'bg-primary-100 dark:bg-primary-900 text-primary-700 dark:text-primary-300'\n : 'hover:bg-gray-100 dark:hover:bg-black-700 text-gray-900 dark:text-white',\n )}\n onClick={() => insertSuggestion(suggestion)}\n onMouseEnter={() => setSelectedIndex(index)}\n >\n {suggestion}\n </div>\n ))}\n </div>,\n document.body,\n )}\n </div>\n\n {errorMessage && (\n <div className='pt-1'>\n <Typography className='text-error-500' size='extra-small' variant='medium' appearance='custom'>\n {errorMessage}\n </Typography>\n </div>\n )}\n </div>\n );\n};\n\nexport default React.memo(FormulaInput);\n\n\n\n"],"names":["FormulaInput","value","onChange","onFocus","onBlur","label","id","isRequired","tooltip","placeholder","disabled","errorMessage","width","suggestions","showRawValueProp","contentRef","useRef","inputWrapperRef","suggestionMenuRef","suggestionRefs","popperInstanceRef","showSuggestions","setShowSuggestions","useState","searchTerm","setSearchTerm","selectedIndex","setSelectedIndex","showRawValue","setShowRawValue","showSuggestionsRef","filteredSuggestionsRef","selectedIndexRef","valueRef","useEffect","useOutsideClick","filteredSuggestions","useMemo","lowerSearchTerm","suggestion","createPopper","handleChange","useCallback","event","rawValue","convertFromPills","textBeforeCursor","getTextBeforeCursor","lastAtSymbol","textAfterAt","handleFocus","handleBlur","relatedTarget","insertSuggestion","currentValue","spaceIndex","endPosition","beforeAt","afterCursor","newValue","handleKeyDown","isShowingSuggestions","currentFilteredSuggestions","currentSelectedIndex","key","prev","handlePaste","text","displayValue","convertToPills","jsxs","jsx","InputLabel","Tooltip","HelpIcon","Typography","ContentEditable","cn","IconButton","VisibilityOutlined","VisibilityOffOutlined","createPortal","index","el","FormulaInput$1","React"],"mappings":"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"}
1
+ {"version":3,"file":"FormulaInput.es.js","sources":["../../../../src/components/forms/formula-input/FormulaInput.tsx"],"sourcesContent":["import { Instance as PopperInstance, createPopper } from '@popperjs/core';\nimport cn from 'classnames';\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport ContentEditable, { ContentEditableEvent } from 'react-contenteditable';\nimport { createPortal } from 'react-dom';\nimport { VisibilityOffOutlined, VisibilityOutlined } from '@mui/icons-material';\n\nimport { Typography } from '../../data-display/typography/Typography';\nimport IconButton from '../../button/IconButton';\nimport Tooltip from '../../tooltip/Tooltip';\nimport { HelpIcon } from '../../icons/HelpIcon';\nimport { useOutsideClick } from '../../../hooks/useOutsideClick';\nimport { convertFromPills, convertToPills, getTextBeforeCursor } from './utils';\nimport { InputLabel } from '../shared/InputLabel';\n\nexport interface FormulaInputProps {\n /** Current value of the input */\n value: string;\n /** Callback when value changes */\n onChange: (value: string) => void;\n /** Callback when input receives focus */\n onFocus?: () => void;\n /** Callback when input loses focus */\n onBlur?: () => void;\n /** Label for the input field */\n label?: string;\n /** Unique identifier for the input */\n id: string;\n /** Whether the field is required */\n required?: boolean;\n /** Tooltip text displayed next to the label */\n tooltip?: string;\n /** Placeholder text */\n placeholder?: string;\n /** Whether the input is disabled */\n disabled?: boolean;\n /** Error message to display */\n errorMessage?: string;\n /** Width of the input */\n width?: string;\n /** List of suggestions for autocomplete */\n suggestions?: string[];\n /** Whether to show the raw value instead of pills */\n showRawValue?: boolean;\n}\n\n/**\n * FormulaInput component for entering formulas with variable suggestions\n * Variables are displayed as pills and can be inserted using @ trigger\n */\nconst FormulaInput: React.FC<FormulaInputProps> = ({\n value = '',\n onChange,\n onFocus,\n onBlur,\n label,\n id,\n required: isRequired,\n tooltip,\n placeholder,\n disabled,\n errorMessage,\n width = '100%',\n suggestions = [],\n showRawValue: showRawValueProp = false,\n}) => {\n const contentRef = useRef<HTMLElement & { isFocused?: boolean }>(null);\n const inputWrapperRef = useRef<HTMLDivElement>(null);\n const suggestionMenuRef = useRef<HTMLDivElement>(null);\n const suggestionRefs = useRef<(HTMLDivElement | null)[]>([]);\n const popperInstanceRef = useRef<PopperInstance | null>(null);\n const [showSuggestions, setShowSuggestions] = useState(false);\n const [searchTerm, setSearchTerm] = useState('');\n const [selectedIndex, setSelectedIndex] = useState(0);\n const [showRawValue, setShowRawValue] = useState(showRawValueProp);\n\n // Use refs to track current state for event handlers\n const showSuggestionsRef = useRef(showSuggestions);\n const filteredSuggestionsRef = useRef<string[]>([]);\n const selectedIndexRef = useRef(selectedIndex);\n const valueRef = useRef(value);\n\n // Keep refs in sync with state\n useEffect(() => {\n showSuggestionsRef.current = showSuggestions;\n }, [showSuggestions]);\n\n useEffect(() => {\n selectedIndexRef.current = selectedIndex;\n }, [selectedIndex]);\n\n useEffect(() => {\n valueRef.current = value;\n }, [value]);\n\n // Close suggestions when clicking outside\n useOutsideClick({\n ref: suggestionMenuRef,\n handler: () => {\n if (showSuggestions) {\n setShowSuggestions(false);\n }\n },\n });\n\n // Filter suggestions based on search term\n const filteredSuggestions = useMemo(() => {\n if (!searchTerm) return suggestions;\n\n const lowerSearchTerm = searchTerm.toLowerCase();\n return suggestions.filter((suggestion) => suggestion.toLowerCase().includes(lowerSearchTerm));\n }, [suggestions, searchTerm]);\n\n // Keep filtered suggestions ref in sync\n useEffect(() => {\n filteredSuggestionsRef.current = filteredSuggestions;\n }, [filteredSuggestions]);\n\n // Reset selected index when filtered suggestions change\n useEffect(() => {\n setSelectedIndex(0);\n }, [filteredSuggestions]);\n\n // Scroll selected suggestion into view\n useEffect(() => {\n if (showSuggestions && suggestionRefs.current[selectedIndex]) {\n suggestionRefs.current[selectedIndex]?.scrollIntoView({\n block: 'nearest',\n behavior: 'smooth',\n });\n }\n }, [selectedIndex, showSuggestions]);\n\n // Setup Popper for dynamic positioning\n useEffect(() => {\n if (showSuggestions && inputWrapperRef.current && suggestionMenuRef.current) {\n // Create popper instance with auto placement\n popperInstanceRef.current = createPopper(inputWrapperRef.current, suggestionMenuRef.current, {\n placement: 'bottom-start',\n strategy: 'fixed',\n modifiers: [\n {\n name: 'flip',\n options: {\n fallbackPlacements: ['top-start', 'bottom-start'],\n },\n },\n {\n name: 'preventOverflow',\n options: {\n boundary: 'viewport',\n padding: 8,\n },\n },\n {\n name: 'offset',\n options: {\n offset: [0, 4],\n },\n },\n ],\n });\n\n return () => {\n if (popperInstanceRef.current) {\n popperInstanceRef.current.destroy();\n popperInstanceRef.current = null;\n }\n };\n }\n }, [showSuggestions]);\n\n const handleChange = useCallback(\n (event: ContentEditableEvent) => {\n const rawValue = convertFromPills(event.target.value);\n onChange(rawValue);\n\n // Check if user typed @ (trigger for suggestions)\n const textBeforeCursor = getTextBeforeCursor();\n const lastAtSymbol = textBeforeCursor.lastIndexOf('@');\n\n if (lastAtSymbol !== -1) {\n // Get text after the @ symbol\n const textAfterAt = textBeforeCursor.slice(lastAtSymbol + 1);\n\n // Check if there's a space after @, which would end the suggestion context\n const hasSpace = textAfterAt.includes(' ');\n\n if (!hasSpace) {\n // We're in suggestion mode - show suggestions filtered by text after @\n setSearchTerm(textAfterAt);\n setShowSuggestions(true);\n } else {\n setShowSuggestions(false);\n }\n } else {\n setShowSuggestions(false);\n }\n },\n [onChange],\n );\n\n const handleFocus = useCallback(() => {\n if (contentRef.current) {\n contentRef.current.isFocused = true;\n }\n onFocus?.();\n }, [onFocus]);\n\n const handleBlur = useCallback(\n (event: React.FocusEvent) => {\n if (contentRef.current) {\n contentRef.current.isFocused = false;\n }\n\n // Check if the blur is due to clicking on a suggestion\n const relatedTarget = event.relatedTarget as HTMLElement;\n if (relatedTarget && suggestionMenuRef.current?.contains(relatedTarget)) {\n // Don't close suggestions if clicking on a suggestion\n return;\n }\n\n // Delay closing suggestions to allow click events to register\n setTimeout(() => {\n setShowSuggestions(false);\n }, 200);\n onBlur?.();\n },\n [onBlur],\n );\n\n const insertSuggestion = useCallback(\n (suggestion: string) => {\n if (!contentRef.current) return;\n\n // IMPORTANT: Use the value prop (not innerText) to preserve existing {{}} syntax\n // innerText only shows display text and loses the {{}} markers from pills\n const currentValue = valueRef.current;\n\n // Find the last occurrence of @ (trigger symbol) in the raw value\n const lastAtSymbol = currentValue.lastIndexOf('@');\n\n if (lastAtSymbol !== -1) {\n // Find where the @ trigger ends (space or end of string)\n const afterAt = currentValue.slice(lastAtSymbol + 1);\n const spaceIndex = afterAt.search(/\\s/);\n\n let endPosition: number;\n if (spaceIndex === -1) {\n // No space found, the incomplete variable goes to the end\n endPosition = currentValue.length;\n } else {\n // Space found, replace up to the space\n endPosition = lastAtSymbol + 1 + spaceIndex;\n }\n\n // Build the new value preserving all existing {{}} syntax\n // Replace @searchTerm with {{suggestion}}\n const beforeAt = currentValue.slice(0, lastAtSymbol);\n const afterCursor = currentValue.slice(endPosition);\n const newValue = `${beforeAt}{{${suggestion}}}${afterCursor}`;\n\n // Update through onChange\n onChange(newValue);\n\n // Close suggestions\n setShowSuggestions(false);\n setSearchTerm('');\n\n // Refocus the input after React updates\n setTimeout(() => {\n contentRef.current?.focus();\n }, 0);\n }\n },\n [onChange],\n );\n\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent) => {\n // Use refs to get the latest state values to avoid stale closures\n const isShowingSuggestions = showSuggestionsRef.current;\n const currentFilteredSuggestions = filteredSuggestionsRef.current;\n const currentSelectedIndex = selectedIndexRef.current;\n\n // Always prevent Enter key to avoid creating new lines/divs\n if (event.key === 'Enter') {\n event.preventDefault();\n event.stopPropagation();\n\n // If suggestions are showing, select the current suggestion\n if (isShowingSuggestions && currentFilteredSuggestions.length > 0 && currentFilteredSuggestions[currentSelectedIndex]) {\n insertSuggestion(currentFilteredSuggestions[currentSelectedIndex]);\n }\n return;\n }\n\n // When suggestions are visible, intercept navigation keys immediately\n if (isShowingSuggestions && currentFilteredSuggestions.length > 0) {\n const { key } = event;\n\n // Prevent default for all navigation keys when suggestions are shown\n if (['ArrowDown', 'ArrowUp', 'Escape', 'Tab'].includes(key)) {\n event.preventDefault();\n event.stopPropagation();\n\n switch (key) {\n case 'ArrowDown':\n setSelectedIndex((prev) => (prev < currentFilteredSuggestions.length - 1 ? prev + 1 : prev));\n break;\n case 'ArrowUp':\n setSelectedIndex((prev) => (prev > 0 ? prev - 1 : 0));\n break;\n case 'Escape':\n setShowSuggestions(false);\n break;\n case 'Tab':\n if (currentFilteredSuggestions[currentSelectedIndex]) {\n insertSuggestion(currentFilteredSuggestions[currentSelectedIndex]);\n }\n break;\n }\n }\n }\n },\n [insertSuggestion],\n );\n\n const handlePaste = useCallback((event: React.ClipboardEvent<HTMLDivElement>) => {\n event.preventDefault();\n const text = event.clipboardData.getData('text/plain');\n document.execCommand('insertText', false, text);\n }, []);\n\n const displayValue = useMemo(() => {\n if (showRawValue) {\n return value;\n }\n return convertToPills(value);\n }, [value, showRawValue]);\n\n return (\n <div className='w-full'>\n {label && (\n <div className='text-xs font-medium text-gray-600 inline-flex items-center gap-1 font-inter text-left whitespace-nowrap flex-wrap'>\n <InputLabel label={label || \"\"} required={isRequired || false} />\n {tooltip && (\n <Tooltip placement='top' title={tooltip}>\n <div className='cursor-pointer'>\n <HelpIcon className=\"w-icon-sm h-icon-sm\" />\n </div>\n </Tooltip>\n )}\n </div>\n )}\n\n <div className='relative' ref={inputWrapperRef}>\n {!value?.trim() ? (\n <div\n className='absolute top-0 left-0 w-full h-full text-gray-400 flex items-center cursor-text px-3 z-50'\n onClick={() => contentRef.current?.focus()}\n >\n <Typography size='extra-small' variant='medium'>\n {placeholder}\n </Typography>\n </div>\n ) : null}\n\n <div className='relative'>\n <ContentEditable\n innerRef={contentRef}\n className={cn(\n 'min-h-[42px] rounded-lg p-2.5',\n 'text-sm font-inter block font-medium border text-gray-900 dark:text-white whitespace-normal break-words text-left',\n disabled ? 'bg-neutral-100 dark:bg-black-800' : 'bg-white dark:bg-black-800',\n !disabled && 'pr-[60px]',\n errorMessage ? '!border-error-500' : 'border-gray-300 dark:border-black-600 focus:ring-blue-500 focus:border-blue-500',\n 'cursor-text',\n )}\n style={{\n width: width,\n wordBreak: 'break-word',\n }}\n html={displayValue}\n onChange={!disabled ? handleChange : () => null}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onKeyDownCapture={handleKeyDown}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n disabled={disabled}\n id={id}\n />\n\n {!disabled && (\n <div className='absolute right-0 top-0 bottom-0 flex items-center align-middle justify-center p-3 gap-2'>\n <IconButton tooltip={showRawValue ? 'Show Formatted' : 'Show Raw Value'} variant='ghost' onClick={() => setShowRawValue(!showRawValue)}>\n {showRawValue ? <VisibilityOutlined sx={{ fontSize: 18 }} /> : <VisibilityOffOutlined sx={{ fontSize: 18 }} />}\n </IconButton>\n </div>\n )}\n </div>\n\n {showSuggestions &&\n filteredSuggestions.length > 0 &&\n createPortal(\n <div\n ref={suggestionMenuRef}\n className='z-[3000] bg-white dark:bg-black-800 border border-gray-300 dark:border-black-600 rounded-lg shadow-lg max-h-60 overflow-y-auto min-w-[200px]'\n onMouseDown={(e) => {\n // Prevent blur when clicking on suggestions\n e.preventDefault();\n }}\n >\n {filteredSuggestions.map((suggestion, index) => (\n <div\n key={suggestion}\n ref={(el) => (suggestionRefs.current[index] = el)}\n className={cn(\n 'px-3 py-2 cursor-pointer text-sm font-inter',\n index === selectedIndex\n ? 'bg-primary-100 dark:bg-primary-900 text-primary-700 dark:text-primary-300'\n : 'hover:bg-gray-100 dark:hover:bg-black-700 text-gray-900 dark:text-white',\n )}\n onClick={() => insertSuggestion(suggestion)}\n onMouseEnter={() => setSelectedIndex(index)}\n >\n {suggestion}\n </div>\n ))}\n </div>,\n document.body,\n )}\n </div>\n\n {errorMessage && (\n <div className='pt-1'>\n <Typography className='text-error-500' size='extra-small' variant='medium' appearance='custom'>\n {errorMessage}\n </Typography>\n </div>\n )}\n </div>\n );\n};\n\nexport default React.memo(FormulaInput);\n\n\n\n"],"names":["FormulaInput","value","onChange","onFocus","onBlur","label","id","isRequired","tooltip","placeholder","disabled","errorMessage","width","suggestions","showRawValueProp","contentRef","useRef","inputWrapperRef","suggestionMenuRef","suggestionRefs","popperInstanceRef","showSuggestions","setShowSuggestions","useState","searchTerm","setSearchTerm","selectedIndex","setSelectedIndex","showRawValue","setShowRawValue","showSuggestionsRef","filteredSuggestionsRef","selectedIndexRef","valueRef","useEffect","useOutsideClick","filteredSuggestions","useMemo","lowerSearchTerm","suggestion","createPopper","handleChange","useCallback","event","rawValue","convertFromPills","textBeforeCursor","getTextBeforeCursor","lastAtSymbol","textAfterAt","handleFocus","handleBlur","relatedTarget","insertSuggestion","currentValue","spaceIndex","endPosition","beforeAt","afterCursor","newValue","handleKeyDown","isShowingSuggestions","currentFilteredSuggestions","currentSelectedIndex","key","prev","handlePaste","text","displayValue","convertToPills","jsxs","jsx","InputLabel","Tooltip","HelpIcon","Typography","ContentEditable","cn","IconButton","VisibilityOutlined","VisibilityOffOutlined","createPortal","index","el","FormulaInput$1","React"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react/jsx-runtime"),w=require("../../../_virtual/index.cjs.js"),d=require("react"),C=require("react-window"),v=require("@mui/icons-material"),I=require("@mui/material"),y=require("antd"),k=require("../../data-display/typography/Typography.cjs.js"),P=require("../input-field/InputField.cjs.js"),x=require("../../../types/icon-picker.cjs.js"),S=require("../../../utils/countryFlags.cjs.js"),q=require("../shared/InputLabel.cjs.js");function N(e){const n=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const c in e)if(c!=="default"){const a=Object.getOwnPropertyDescriptor(e,c);Object.defineProperty(n,c,a.get?a:{enumerable:!0,get:()=>e[c]})}}return n.default=e,Object.freeze(n)}const h=N(v),R=Object.keys(h).filter(e=>e?.endsWith("Rounded")),O=[...R||[],...(x.COUNTRY_CODES||[]).map(e=>`flag-${e}`)],D=e=>{if(e?.startsWith("flag-")){const n=e?.replace("flag-","");return x.countryNameFromCode(n||"")||n}return e.replaceAll(/([A-Z])/g," $1").trim()},T=({onChange:e,selectedIcon:n,setOpen:c})=>{const[a,f]=d.useState(""),l=(O||[]).filter(r=>{if(r?.startsWith("flag-")){const s=r?.replace("flag-","");return s?.toLowerCase()?.includes(a?.trim()?.toLowerCase()||"")||x.countryNameFromCode(s||"")?.toLowerCase()?.includes(a?.trim()?.toLowerCase()||"")}return r?.trim()?.toLowerCase()?.includes(a?.trim()?.toLowerCase()||"")}),p=(r,s)=>{if(s.stopPropagation(),n===r){e?.(null);return}e?.(r),c?.(!1)};return t.jsxs("div",{className:"flex flex-col gap-3",onKeyDown:r=>{r.key==="Enter"&&(r.preventDefault(),r.stopPropagation())},children:[t.jsx(P.InputField,{id:"input-field-icon-picker",placeholder:"Search icons...",onChange:r=>f(r||""),fieldSuffix:t.jsx(h.Search,{sx:{width:16,height:16,color:"rgb(152 162 179)"}})}),t.jsx(C.FixedSizeGrid,{columnCount:5,rowCount:Math.ceil((l?.length||0)/5),columnWidth:40,rowHeight:40,width:220,height:240,children:({columnIndex:r,rowIndex:s,style:m})=>{const g=s*5+r,i=l?.[g];return i?t.jsx("div",{style:{...m,padding:"4px"},children:t.jsx(y.Tooltip,{title:D(i),placement:"bottom",children:t.jsx(I.IconButton,{type:"button",className:w("flex items-center justify-center !rounded-md hover:bg-neutral-200 dark:hover:bg-black-700",{"!bg-primary-50 dark:!bg-black-800":n===i}),onClick:u=>p(i,u),onKeyDown:u=>{u.key==="Enter"&&(u.preventDefault(),u.stopPropagation())},children:t.jsx(b,{iconName:i,sx:{width:20,height:20},className:"text-neutral-900 dark:text-white"})})})}):null}})]})},b=({iconName:e,sx:n,className:c,isHovering:a})=>{if(e?.startsWith?.("flag-")){const l=e?.replace("flag-","");return S.getFlagComponent?.(l||"",a||!1)||t.jsx("div",{children:"-"})}const f=h?.[e];return f?t.jsx(f,{sx:n,className:c,isHovering:a}):t.jsx("div",{children:"-"})},L=({selectedIcon:e,onChange:n,label:c,required:a=!1,allowClear:f=!0,disabled:l=!1,errorMessage:p,dropdownPosition:r="bottom"})=>{const[s,m]=d.useState(!1),g=d.useRef(!1),i=d.useRef(null),u=d.useRef(!1);d.useEffect(()=>{u.current&&!s&&i.current?.focus(),u.current=s},[s]);const j=o=>{o.stopPropagation(),n?.("")};return t.jsx(y.Popover,{arrow:!1,placement:r,trigger:"click",getPopupContainer:o=>o?.parentElement||document.body,open:s,onOpenChange:o=>{o?(g.current&&m(!0),g.current=!1):m(!1)},content:t.jsx(T,{onChange:n,selectedIcon:e,setOpen:m}),children:t.jsxs("div",{className:"flex flex-col gap-1",children:[c?t.jsx(q.InputLabel,{label:c||"",required:a||!1}):null,t.jsxs("button",{ref:i,type:"button",id:`btn-icon-picker-icon-${e?"selected":"unselected"}`,className:`lax-form-trigger min-w-[83px] py-1.5 px-3 rounded-md border ${l?"cursor-not-allowed opacity-60 bg-neutral-50 dark:bg-black-800":"bg-white dark:bg-black-800"} ${p?"border-red-500":"focus:border-primary-600 dark:focus:border-primary-400"} flex items-center justify-between gap-2`,disabled:l,onClick:o=>{if(l){o.preventDefault(),o.stopPropagation();return}o.detail>0&&(g.current=!0)},onKeyDown:o=>{o.key==="Enter"&&(o.preventDefault(),s||o.currentTarget.closest("form")?.querySelector('button[type="submit"]')?.click())},children:[e?t.jsx(b,{iconName:e,sx:{width:20,height:20},className:"text-neutral-900 dark:text-white"}):t.jsx(k.Typography,{size:"small",variant:"medium",appearance:"subtitle",children:"Select Icon"}),e&&f&&!l?t.jsx(h.CloseRounded,{sx:{width:20,height:20},className:"hover:bg-neutral-100 dark:hover:bg-black-800 rounded-full transition-colors cursor-pointer text-neutral-400 dark:text-neutral-500",onClick:j}):null]}),p&&t.jsx(k.Typography,{size:"extra-small",className:"text-red-500 font-medium",children:p})]})})},F=d.lazy(()=>Promise.resolve({default:e=>t.jsx(d.Suspense,{fallback:t.jsx("div",{className:"min-w-[83px] h-[30px] animate-pulse bg-neutral-100 dark:bg-black-800 rounded-md"}),children:t.jsx(L,{...e})})}));exports.IconPicker=F;exports.IconRenderer=b;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react/jsx-runtime"),w=require("../../../_virtual/index.cjs.js"),d=require("react"),C=require("react-window"),v=require("@mui/icons-material"),I=require("@mui/material"),y=require("antd"),k=require("../../data-display/typography/Typography.cjs.js"),N=require("../input-field/InputField.cjs.js"),x=require("../../../types/icon-picker.cjs.js"),P=require("../../../utils/countryFlags.cjs.js"),S=require("../shared/InputLabel.cjs.js");function q(e){const n=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const a in e)if(a!=="default"){const c=Object.getOwnPropertyDescriptor(e,a);Object.defineProperty(n,a,c.get?c:{enumerable:!0,get:()=>e[a]})}}return n.default=e,Object.freeze(n)}const h=q(v),R=Object.keys(h).filter(e=>e?.endsWith("Rounded")),O=[...R||[],...(x.COUNTRY_CODES||[]).map(e=>`flag-${e}`)],D=e=>{if(e?.startsWith("flag-")){const n=e?.replace("flag-","");return x.countryNameFromCode(n||"")||n}return e.replaceAll(/([A-Z])/g," $1").trim()},T=({onChange:e,selectedIcon:n,setOpen:a})=>{const[c,f]=d.useState(""),l=(O||[]).filter(r=>{if(r?.startsWith("flag-")){const s=r?.replace("flag-","");return s?.toLowerCase()?.includes(c?.trim()?.toLowerCase()||"")||x.countryNameFromCode(s||"")?.toLowerCase()?.includes(c?.trim()?.toLowerCase()||"")}return r?.trim()?.toLowerCase()?.includes(c?.trim()?.toLowerCase()||"")}),p=(r,s)=>{if(s.stopPropagation(),n===r){e?.(null);return}e?.(r),a?.(!1)};return t.jsxs("div",{className:"flex flex-col gap-3",onKeyDown:r=>{r.key==="Enter"&&(r.preventDefault(),r.stopPropagation())},children:[t.jsx(N.InputField,{id:"input-field-icon-picker",placeholder:"Search icons...",onChange:r=>f(r||""),fieldSuffix:t.jsx(h.Search,{className:"!w-4 !h-4 text-neutral-400"})}),t.jsx(C.FixedSizeGrid,{columnCount:5,rowCount:Math.ceil((l?.length||0)/5),columnWidth:40,rowHeight:40,width:220,height:240,children:({columnIndex:r,rowIndex:s,style:m})=>{const g=s*5+r,i=l?.[g];return i?t.jsx("div",{style:m,className:"p-1",children:t.jsx(y.Tooltip,{title:D(i),placement:"bottom",children:t.jsx(I.IconButton,{type:"button",className:w("flex items-center justify-center !rounded-md hover:bg-neutral-200 dark:hover:bg-black-700",{"!bg-primary-50 dark:!bg-black-800":n===i}),onClick:u=>p(i,u),onKeyDown:u=>{u.key==="Enter"&&(u.preventDefault(),u.stopPropagation())},children:t.jsx(b,{iconName:i,className:"!w-5 !h-5 text-neutral-900 dark:text-white"})})})}):null}})]})},b=({iconName:e,sx:n,className:a,isHovering:c})=>{if(e?.startsWith?.("flag-")){const l=e?.replace("flag-","");return P.getFlagComponent?.(l||"",c||!1)||t.jsx("div",{children:"-"})}const f=h?.[e];return f?t.jsx(f,{sx:n,className:a,isHovering:c}):t.jsx("div",{children:"-"})},L=({selectedIcon:e,onChange:n,label:a,required:c=!1,allowClear:f=!0,disabled:l=!1,errorMessage:p,dropdownPosition:r="bottom"})=>{const[s,m]=d.useState(!1),g=d.useRef(!1),i=d.useRef(null),u=d.useRef(!1);d.useEffect(()=>{u.current&&!s&&i.current?.focus(),u.current=s},[s]);const j=o=>{o.stopPropagation(),n?.("")};return t.jsx(y.Popover,{arrow:!1,placement:r,trigger:"click",getPopupContainer:o=>o?.parentElement||document.body,open:s,onOpenChange:o=>{o?(g.current&&m(!0),g.current=!1):m(!1)},content:t.jsx(T,{onChange:n,selectedIcon:e,setOpen:m}),children:t.jsxs("div",{className:"flex flex-col gap-1",children:[a?t.jsx(S.InputLabel,{label:a||"",required:c||!1}):null,t.jsxs("button",{ref:i,type:"button",id:`btn-icon-picker-icon-${e?"selected":"unselected"}`,className:`lax-form-trigger min-w-[83px] py-1.5 px-3 rounded-md border ${l?"cursor-not-allowed opacity-60 bg-neutral-50 dark:bg-black-800":"bg-white dark:bg-black-800"} ${p?"border-red-500":"focus:border-primary-600 dark:focus:border-primary-400"} flex items-center justify-between gap-2`,disabled:l,onClick:o=>{if(l){o.preventDefault(),o.stopPropagation();return}o.detail>0&&(g.current=!0)},onKeyDown:o=>{o.key==="Enter"&&(o.preventDefault(),s||o.currentTarget.closest("form")?.querySelector('button[type="submit"]')?.click())},children:[e?t.jsx(b,{iconName:e,className:"!w-5 !h-5 text-neutral-900 dark:text-white"}):t.jsx(k.Typography,{size:"small",variant:"medium",appearance:"subtitle",children:"Select Icon"}),e&&f&&!l?t.jsx(h.CloseRounded,{className:"!w-5 !h-5 hover:bg-neutral-100 dark:hover:bg-black-800 rounded-full transition-colors cursor-pointer text-neutral-400 dark:text-neutral-500",onClick:j}):null]}),p&&t.jsx(k.Typography,{size:"extra-small",className:"text-red-500 font-medium",children:p})]})})},F=d.lazy(()=>Promise.resolve({default:e=>t.jsx(d.Suspense,{fallback:t.jsx("div",{className:"min-w-20 h-8 animate-pulse bg-neutral-100 dark:bg-black-800 rounded-md"}),children:t.jsx(L,{...e})})}));exports.IconPicker=F;exports.IconRenderer=b;
2
2
  //# sourceMappingURL=IconPicker.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"IconPicker.cjs.js","sources":["../../../../src/components/forms/icon-picker/IconPicker.tsx"],"sourcesContent":["import classNames from 'classnames';\nimport React, { Suspense, useEffect, useRef, useState } from 'react';\nimport { FixedSizeGrid, type GridChildComponentProps } from 'react-window';\nimport * as AllIcons from '@mui/icons-material';\nimport { IconButton, type SvgIconOwnProps } from '@mui/material';\nimport { Popover, Tooltip } from \"antd\";\nimport { Typography } from \"../../data-display/typography/Typography\";\nimport { InputField } from \"../input-field/InputField\";\nimport { COUNTRY_CODES, countryNameFromCode } from \"../../../types/icon-picker\";\nimport { getFlagComponent } from \"../../../utils/countryFlags\";\nimport { InputLabel } from '../shared/InputLabel';\n\nconst roundedIconNames = Object.keys(AllIcons).filter((name) =>\n name?.endsWith(\"Rounded\")\n);\n\n// Merge icon names and country codes for the picker\nconst mergedIconNames = [\n ...(roundedIconNames || []),\n ...(COUNTRY_CODES || []).map((code) => `flag-${code}`),\n];\n\n// Utility function to convert camelCase to human-readable format\nconst formatIconName = (iconName: string): string => {\n // Handle flag icons\n if (iconName?.startsWith(\"flag-\")) {\n const code = iconName?.replace(\"flag-\", \"\");\n return countryNameFromCode(code || \"\") || code;\n }\n\n // Convert camelCase to space-separated words\n // e.g., \"PersonRounded\" -> \"Person Rounded\"\n return iconName.replaceAll(/([A-Z])/g, \" $1\").trim();\n};\n\n/** Ant Design `Popover` placement for the icon panel (bottom edge of the trigger). */\nexport type IconPickerDropdownPosition = 'bottom' | 'bottomLeft' | 'bottomRight';\n\nexport interface IconPickerContentProps {\n selectedIcon: string | null;\n onChange: (iconName: string | null) => void;\n label?: string;\n required?: boolean;\n allowClear?: boolean;\n disabled?: boolean;\n errorMessage?: string;\n /** Popover placement: `bottom` | `bottomLeft` | `bottomRight`. Default: `bottom`. */\n dropdownPosition?: IconPickerDropdownPosition;\n}\n\ninterface IconPickerContentInternalProps {\n onChange: (iconName: string | null) => void;\n selectedIcon: string | null;\n setOpen?: React.Dispatch<React.SetStateAction<boolean>>;\n}\n\nconst IconPickerContent = ({\n onChange,\n selectedIcon,\n setOpen,\n}: IconPickerContentInternalProps) => {\n const [searchTerm, setSearchTerm] = useState<string>(\"\");\n\n // Filter both icons and flags\n const filteredIcons = (mergedIconNames || []).filter((name) => {\n if (name?.startsWith(\"flag-\")) {\n // For flags, allow search by country code or country name\n const code = name?.replace(\"flag-\", \"\");\n return (\n code\n ?.toLowerCase()\n ?.includes(searchTerm?.trim()?.toLowerCase() || \"\") ||\n countryNameFromCode(code || \"\")\n ?.toLowerCase()\n ?.includes(searchTerm?.trim()?.toLowerCase() || \"\")\n );\n }\n return name\n ?.trim()\n ?.toLowerCase()\n ?.includes(searchTerm?.trim()?.toLowerCase() || \"\");\n });\n\n const handleClick = (icon: string, event: React.MouseEvent) => {\n event.stopPropagation();\n if (selectedIcon === icon) {\n onChange?.(null);\n return;\n }\n onChange?.(icon);\n setOpen?.(false);\n };\n\n return (\n <div \n className=\"flex flex-col gap-3\"\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n e.stopPropagation();\n }\n }}\n >\n <InputField\n id={`input-field-icon-picker`}\n placeholder=\"Search icons...\"\n onChange={(value) => setSearchTerm(value || \"\")}\n fieldSuffix={\n <AllIcons.Search\n sx={{\n width: 16,\n height: 16,\n color: \"rgb(152 162 179)\", // neutral-400\n }}\n />\n }\n />\n <FixedSizeGrid\n columnCount={5}\n rowCount={Math.ceil((filteredIcons?.length || 0) / 5)}\n columnWidth={40}\n rowHeight={40}\n width={220}\n height={240}\n >\n {({ columnIndex, rowIndex, style }: GridChildComponentProps) => {\n const itemIndex = rowIndex * 5 + columnIndex;\n const iconName = filteredIcons?.[itemIndex];\n return iconName ? (\n <div style={{ ...style, padding: \"4px\" }}>\n <Tooltip title={formatIconName(iconName)} placement='bottom'>\n <IconButton\n type='button'\n className={classNames(\n \"flex items-center justify-center !rounded-md hover:bg-neutral-200 dark:hover:bg-black-700\",\n {\n \"!bg-primary-50 dark:!bg-black-800\":\n selectedIcon === iconName,\n }\n )}\n onClick={(event) => handleClick(iconName, event)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n e.stopPropagation();\n }\n }}\n >\n <IconRenderer\n iconName={iconName}\n sx={{\n width: 20,\n height: 20,\n }}\n className=\"text-neutral-900 dark:text-white\"\n />\n </IconButton>\n </Tooltip>\n </div>\n ) : null;\n }}\n </FixedSizeGrid>\n </div>\n );\n};\n\ninterface IconRendererProps {\n iconName: string;\n sx?: SvgIconOwnProps['sx'];\n className?: string;\n isHovering?: boolean;\n}\n\nexport const IconRenderer = ({ iconName, sx, className, isHovering }: IconRendererProps) => {\n // Render flag if iconName starts with 'flag-'\n if (iconName?.startsWith?.('flag-')) {\n const code = iconName?.replace('flag-', '');\n return getFlagComponent?.(code || '', isHovering || false) || <div>-</div>;\n }\n const Icon = AllIcons?.[iconName as keyof typeof AllIcons] as React.ComponentType<{\n sx?: SvgIconOwnProps['sx'];\n className?: string;\n isHovering?: boolean;\n }>;\n\n if (!Icon) {\n return <div>-</div>;\n }\n\n return <Icon sx={sx} className={className} isHovering={isHovering} />;\n};\n\nconst IconPickerBase = ({\n selectedIcon,\n onChange,\n label,\n required = false,\n allowClear = true,\n disabled = false,\n errorMessage,\n dropdownPosition = 'bottom',\n}: IconPickerContentProps) => {\n const [open, setOpen] = useState(false);\n const mouseClickRef = useRef(false);\n const buttonRef = useRef<HTMLButtonElement>(null);\n const wasOpenRef = useRef(false);\n\n useEffect(() => {\n if (wasOpenRef.current && !open) {\n buttonRef.current?.focus();\n }\n wasOpenRef.current = open;\n }, [open]);\n const handleClearIcon = (e: React.MouseEvent) => {\n e.stopPropagation();\n onChange?.('');\n };\n\n return (\n <Popover\n arrow={false}\n placement={dropdownPosition}\n trigger='click'\n getPopupContainer={(triggerNode) => triggerNode?.parentElement || document.body}\n open={open}\n onOpenChange={(newOpen) => {\n if (newOpen) {\n if (mouseClickRef.current) {\n setOpen(true);\n }\n mouseClickRef.current = false;\n } else {\n setOpen(false);\n }\n }}\n content={<IconPickerContent onChange={onChange} selectedIcon={selectedIcon} setOpen={setOpen} />}\n >\n <div className='flex flex-col gap-1'>\n {label ? (\n <InputLabel label={label || \"\"} required={required || false} />\n ) : null}\n <button\n ref={buttonRef}\n type='button'\n id={`btn-icon-picker-icon-${selectedIcon ? 'selected' : 'unselected'}`}\n className={`lax-form-trigger min-w-[83px] py-1.5 px-3 rounded-md border ${\n disabled ? 'cursor-not-allowed opacity-60 bg-neutral-50 dark:bg-black-800' : 'bg-white dark:bg-black-800'\n } ${errorMessage ? 'border-red-500' : 'focus:border-primary-600 dark:focus:border-primary-400'} flex items-center justify-between gap-2`}\n disabled={disabled}\n onClick={(e) => {\n if (disabled) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n if (e.detail > 0) {\n mouseClickRef.current = true;\n }\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n if (!open) {\n const form = (e.currentTarget as HTMLElement).closest('form');\n const submitBtn = form?.querySelector('button[type=\"submit\"]') as HTMLButtonElement | null;\n submitBtn?.click();\n }\n }\n }}\n >\n {selectedIcon ? (\n <IconRenderer iconName={selectedIcon} sx={{ width: 20, height: 20 }} className='text-neutral-900 dark:text-white' />\n ) : (\n <Typography\n size='small'\n variant='medium'\n appearance='subtitle'\n >\n Select Icon\n </Typography>\n )}\n {selectedIcon && allowClear && !disabled ? (\n <AllIcons.CloseRounded\n sx={{ width: 20, height: 20 }}\n className='hover:bg-neutral-100 dark:hover:bg-black-800 rounded-full transition-colors cursor-pointer text-neutral-400 dark:text-neutral-500'\n onClick={handleClearIcon}\n />\n ) : (\n null\n )}\n </button>\n {errorMessage && (\n <Typography size='extra-small' className='text-red-500 font-medium'>\n {errorMessage}\n </Typography>\n )}\n </div>\n </Popover>\n );\n};\n\nexport const IconPicker = React.lazy(() =>\n Promise.resolve({\n default: (props: IconPickerContentProps) => (\n <Suspense fallback={<div className='min-w-[83px] h-[30px] animate-pulse bg-neutral-100 dark:bg-black-800 rounded-md' />}>\n <IconPickerBase {...props} />\n </Suspense>\n ),\n }),\n);\n\n"],"names":["roundedIconNames","AllIcons","name","mergedIconNames","COUNTRY_CODES","code","formatIconName","iconName","countryNameFromCode","IconPickerContent","onChange","selectedIcon","setOpen","searchTerm","setSearchTerm","useState","filteredIcons","handleClick","icon","event","jsxs","e","jsx","InputField","value","FixedSizeGrid","columnIndex","rowIndex","style","itemIndex","Tooltip","IconButton","classNames","IconRenderer","sx","className","isHovering","getFlagComponent","Icon","IconPickerBase","label","required","allowClear","disabled","errorMessage","dropdownPosition","open","mouseClickRef","useRef","buttonRef","wasOpenRef","useEffect","handleClearIcon","Popover","triggerNode","newOpen","InputLabel","Typography","IconPicker","React","props","Suspense"],"mappings":"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"}
1
+ {"version":3,"file":"IconPicker.cjs.js","sources":["../../../../src/components/forms/icon-picker/IconPicker.tsx"],"sourcesContent":["import classNames from 'classnames';\nimport React, { Suspense, useEffect, useRef, useState } from 'react';\nimport { FixedSizeGrid, type GridChildComponentProps } from 'react-window';\nimport * as AllIcons from '@mui/icons-material';\nimport { IconButton, type SvgIconOwnProps } from '@mui/material';\nimport { Popover, Tooltip } from \"antd\";\nimport { Typography } from \"../../data-display/typography/Typography\";\nimport { InputField } from \"../input-field/InputField\";\nimport { COUNTRY_CODES, countryNameFromCode } from \"../../../types/icon-picker\";\nimport { getFlagComponent } from \"../../../utils/countryFlags\";\nimport { InputLabel } from '../shared/InputLabel';\n\nconst roundedIconNames = Object.keys(AllIcons).filter((name) =>\n name?.endsWith(\"Rounded\")\n);\n\n// Merge icon names and country codes for the picker\nconst mergedIconNames = [\n ...(roundedIconNames || []),\n ...(COUNTRY_CODES || []).map((code) => `flag-${code}`),\n];\n\n// Utility function to convert camelCase to human-readable format\nconst formatIconName = (iconName: string): string => {\n // Handle flag icons\n if (iconName?.startsWith(\"flag-\")) {\n const code = iconName?.replace(\"flag-\", \"\");\n return countryNameFromCode(code || \"\") || code;\n }\n\n // Convert camelCase to space-separated words\n // e.g., \"PersonRounded\" -> \"Person Rounded\"\n return iconName.replaceAll(/([A-Z])/g, \" $1\").trim();\n};\n\n/** Ant Design `Popover` placement for the icon panel (bottom edge of the trigger). */\nexport type IconPickerDropdownPosition = 'bottom' | 'bottomLeft' | 'bottomRight';\n\nexport interface IconPickerContentProps {\n selectedIcon: string | null;\n onChange: (iconName: string | null) => void;\n label?: string;\n required?: boolean;\n allowClear?: boolean;\n disabled?: boolean;\n errorMessage?: string;\n /** Popover placement: `bottom` | `bottomLeft` | `bottomRight`. Default: `bottom`. */\n dropdownPosition?: IconPickerDropdownPosition;\n}\n\ninterface IconPickerContentInternalProps {\n onChange: (iconName: string | null) => void;\n selectedIcon: string | null;\n setOpen?: React.Dispatch<React.SetStateAction<boolean>>;\n}\n\nconst IconPickerContent = ({\n onChange,\n selectedIcon,\n setOpen,\n}: IconPickerContentInternalProps) => {\n const [searchTerm, setSearchTerm] = useState<string>(\"\");\n\n // Filter both icons and flags\n const filteredIcons = (mergedIconNames || []).filter((name) => {\n if (name?.startsWith(\"flag-\")) {\n // For flags, allow search by country code or country name\n const code = name?.replace(\"flag-\", \"\");\n return (\n code\n ?.toLowerCase()\n ?.includes(searchTerm?.trim()?.toLowerCase() || \"\") ||\n countryNameFromCode(code || \"\")\n ?.toLowerCase()\n ?.includes(searchTerm?.trim()?.toLowerCase() || \"\")\n );\n }\n return name\n ?.trim()\n ?.toLowerCase()\n ?.includes(searchTerm?.trim()?.toLowerCase() || \"\");\n });\n\n const handleClick = (icon: string, event: React.MouseEvent) => {\n event.stopPropagation();\n if (selectedIcon === icon) {\n onChange?.(null);\n return;\n }\n onChange?.(icon);\n setOpen?.(false);\n };\n\n return (\n <div \n className=\"flex flex-col gap-3\"\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n e.stopPropagation();\n }\n }}\n >\n <InputField\n id={`input-field-icon-picker`}\n placeholder=\"Search icons...\"\n onChange={(value) => setSearchTerm(value || \"\")}\n fieldSuffix={\n <AllIcons.Search className=\"!w-4 !h-4 text-neutral-400\" />\n }\n />\n <FixedSizeGrid\n columnCount={5}\n rowCount={Math.ceil((filteredIcons?.length || 0) / 5)}\n columnWidth={40}\n rowHeight={40}\n width={220}\n height={240}\n >\n {({ columnIndex, rowIndex, style }: GridChildComponentProps) => {\n const itemIndex = rowIndex * 5 + columnIndex;\n const iconName = filteredIcons?.[itemIndex];\n return iconName ? (\n <div style={style} className=\"p-1\">\n <Tooltip title={formatIconName(iconName)} placement='bottom'>\n <IconButton\n type='button'\n className={classNames(\n \"flex items-center justify-center !rounded-md hover:bg-neutral-200 dark:hover:bg-black-700\",\n {\n \"!bg-primary-50 dark:!bg-black-800\":\n selectedIcon === iconName,\n }\n )}\n onClick={(event) => handleClick(iconName, event)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n e.stopPropagation();\n }\n }}\n >\n <IconRenderer\n iconName={iconName}\n className=\"!w-5 !h-5 text-neutral-900 dark:text-white\"\n />\n </IconButton>\n </Tooltip>\n </div>\n ) : null;\n }}\n </FixedSizeGrid>\n </div>\n );\n};\n\ninterface IconRendererProps {\n iconName: string;\n sx?: SvgIconOwnProps['sx'];\n className?: string;\n isHovering?: boolean;\n}\n\nexport const IconRenderer = ({ iconName, sx, className, isHovering }: IconRendererProps) => {\n // Render flag if iconName starts with 'flag-'\n if (iconName?.startsWith?.('flag-')) {\n const code = iconName?.replace('flag-', '');\n return getFlagComponent?.(code || '', isHovering || false) || <div>-</div>;\n }\n const Icon = AllIcons?.[iconName as keyof typeof AllIcons] as React.ComponentType<{\n sx?: SvgIconOwnProps['sx'];\n className?: string;\n isHovering?: boolean;\n }>;\n\n if (!Icon) {\n return <div>-</div>;\n }\n\n return <Icon sx={sx} className={className} isHovering={isHovering} />;\n};\n\nconst IconPickerBase = ({\n selectedIcon,\n onChange,\n label,\n required = false,\n allowClear = true,\n disabled = false,\n errorMessage,\n dropdownPosition = 'bottom',\n}: IconPickerContentProps) => {\n const [open, setOpen] = useState(false);\n const mouseClickRef = useRef(false);\n const buttonRef = useRef<HTMLButtonElement>(null);\n const wasOpenRef = useRef(false);\n\n useEffect(() => {\n if (wasOpenRef.current && !open) {\n buttonRef.current?.focus();\n }\n wasOpenRef.current = open;\n }, [open]);\n const handleClearIcon = (e: React.MouseEvent) => {\n e.stopPropagation();\n onChange?.('');\n };\n\n return (\n <Popover\n arrow={false}\n placement={dropdownPosition}\n trigger='click'\n getPopupContainer={(triggerNode) => triggerNode?.parentElement || document.body}\n open={open}\n onOpenChange={(newOpen) => {\n if (newOpen) {\n if (mouseClickRef.current) {\n setOpen(true);\n }\n mouseClickRef.current = false;\n } else {\n setOpen(false);\n }\n }}\n content={<IconPickerContent onChange={onChange} selectedIcon={selectedIcon} setOpen={setOpen} />}\n >\n <div className='flex flex-col gap-1'>\n {label ? (\n <InputLabel label={label || \"\"} required={required || false} />\n ) : null}\n <button\n ref={buttonRef}\n type='button'\n id={`btn-icon-picker-icon-${selectedIcon ? 'selected' : 'unselected'}`}\n className={`lax-form-trigger min-w-[83px] py-1.5 px-3 rounded-md border ${\n disabled ? 'cursor-not-allowed opacity-60 bg-neutral-50 dark:bg-black-800' : 'bg-white dark:bg-black-800'\n } ${errorMessage ? 'border-red-500' : 'focus:border-primary-600 dark:focus:border-primary-400'} flex items-center justify-between gap-2`}\n disabled={disabled}\n onClick={(e) => {\n if (disabled) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n if (e.detail > 0) {\n mouseClickRef.current = true;\n }\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n if (!open) {\n const form = (e.currentTarget as HTMLElement).closest('form');\n const submitBtn = form?.querySelector('button[type=\"submit\"]') as HTMLButtonElement | null;\n submitBtn?.click();\n }\n }\n }}\n >\n {selectedIcon ? (\n <IconRenderer iconName={selectedIcon} className='!w-5 !h-5 text-neutral-900 dark:text-white' />\n ) : (\n <Typography\n size='small'\n variant='medium'\n appearance='subtitle'\n >\n Select Icon\n </Typography>\n )}\n {selectedIcon && allowClear && !disabled ? (\n <AllIcons.CloseRounded\n className='!w-5 !h-5 hover:bg-neutral-100 dark:hover:bg-black-800 rounded-full transition-colors cursor-pointer text-neutral-400 dark:text-neutral-500'\n onClick={handleClearIcon}\n />\n ) : (\n null\n )}\n </button>\n {errorMessage && (\n <Typography size='extra-small' className='text-red-500 font-medium'>\n {errorMessage}\n </Typography>\n )}\n </div>\n </Popover>\n );\n};\n\nexport const IconPicker = React.lazy(() =>\n Promise.resolve({\n default: (props: IconPickerContentProps) => (\n <Suspense fallback={<div className='min-w-20 h-8 animate-pulse bg-neutral-100 dark:bg-black-800 rounded-md' />}>\n <IconPickerBase {...props} />\n </Suspense>\n ),\n }),\n);\n\n"],"names":["roundedIconNames","AllIcons","name","mergedIconNames","COUNTRY_CODES","code","formatIconName","iconName","countryNameFromCode","IconPickerContent","onChange","selectedIcon","setOpen","searchTerm","setSearchTerm","useState","filteredIcons","handleClick","icon","event","jsxs","e","jsx","InputField","value","FixedSizeGrid","columnIndex","rowIndex","style","itemIndex","Tooltip","IconButton","classNames","IconRenderer","sx","className","isHovering","getFlagComponent","Icon","IconPickerBase","label","required","allowClear","disabled","errorMessage","dropdownPosition","open","mouseClickRef","useRef","buttonRef","wasOpenRef","useEffect","handleClearIcon","Popover","triggerNode","newOpen","InputLabel","Typography","IconPicker","React","props","Suspense"],"mappings":"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"}