payload-intl 1.2.2 → 1.2.4

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 (171) hide show
  1. package/README.md +21 -18
  2. package/dist/components/MessageFormField.d.ts +15 -0
  3. package/dist/components/MessageFormField.d.ts.map +1 -0
  4. package/dist/components/{MessageController.js → MessageFormField.js} +5 -3
  5. package/dist/components/MessageFormField.js.map +1 -0
  6. package/dist/components/MessagesForm.d.ts +3 -1
  7. package/dist/components/MessagesForm.d.ts.map +1 -1
  8. package/dist/components/MessagesForm.js +25 -36
  9. package/dist/components/MessagesForm.js.map +1 -1
  10. package/dist/components/{MessageFormContext.d.ts → MessagesFormProvider.d.ts} +6 -2
  11. package/dist/components/MessagesFormProvider.d.ts.map +1 -0
  12. package/dist/components/{MessageFormContext.js → MessagesFormProvider.js} +8 -4
  13. package/dist/components/MessagesFormProvider.js.map +1 -0
  14. package/dist/components/MessagesLink.js +5 -2
  15. package/dist/components/MessagesLink.js.map +1 -1
  16. package/dist/components/MessagesView.d.ts +1 -1
  17. package/dist/components/MessagesView.d.ts.map +1 -1
  18. package/dist/components/MessagesView.js +13 -4
  19. package/dist/components/MessagesView.js.map +1 -1
  20. package/dist/components/actions/CopyMessages.d.ts +2 -0
  21. package/dist/components/actions/CopyMessages.d.ts.map +1 -0
  22. package/dist/components/actions/{Move.js → CopyMessages.js} +6 -6
  23. package/dist/components/actions/CopyMessages.js.map +1 -0
  24. package/dist/components/actions/JsonImport.d.ts +4 -1
  25. package/dist/components/actions/JsonImport.d.ts.map +1 -1
  26. package/dist/components/actions/JsonImport.js +7 -25
  27. package/dist/components/actions/JsonImport.js.map +1 -1
  28. package/dist/components/hooks/useHtmlLexicalAdapter.d.ts +12 -0
  29. package/dist/components/hooks/useHtmlLexicalAdapter.d.ts.map +1 -0
  30. package/dist/components/hooks/useHtmlLexicalAdapter.js +63 -0
  31. package/dist/components/hooks/useHtmlLexicalAdapter.js.map +1 -0
  32. package/dist/components/hooks/useMessagesFormSubmit.d.ts +11 -0
  33. package/dist/components/hooks/useMessagesFormSubmit.d.ts.map +1 -0
  34. package/dist/components/hooks/useMessagesFormSubmit.js +44 -0
  35. package/dist/components/hooks/useMessagesFormSubmit.js.map +1 -0
  36. package/dist/components/inputs/FieldWrapper.d.ts +9 -0
  37. package/dist/components/inputs/FieldWrapper.d.ts.map +1 -0
  38. package/dist/components/inputs/FieldWrapper.js +24 -0
  39. package/dist/components/inputs/FieldWrapper.js.map +1 -0
  40. package/dist/components/inputs/{InputWrapper.module.css → FieldWrapper.module.css} +2 -12
  41. package/dist/components/inputs/LexicalInput.d.ts +2 -13
  42. package/dist/components/inputs/LexicalInput.d.ts.map +1 -1
  43. package/dist/components/inputs/LexicalInput.js +4 -63
  44. package/dist/components/inputs/LexicalInput.js.map +1 -1
  45. package/dist/components/inputs/MessageInput.d.ts +6 -3
  46. package/dist/components/inputs/MessageInput.d.ts.map +1 -1
  47. package/dist/components/inputs/MessageInput.js +47 -43
  48. package/dist/components/inputs/MessageInput.js.map +1 -1
  49. package/dist/components/inputs/MessageInput.module.css +23 -4
  50. package/dist/components/inputs/ReferencePopover.d.ts +7 -0
  51. package/dist/components/inputs/ReferencePopover.d.ts.map +1 -0
  52. package/dist/components/inputs/ReferencePopover.js +42 -0
  53. package/dist/components/inputs/ReferencePopover.js.map +1 -0
  54. package/dist/components/inputs/ReferencePopover.module.css +70 -0
  55. package/dist/components/inputs/SingleLinePlugin.d.ts +2 -0
  56. package/dist/components/inputs/SingleLinePlugin.d.ts.map +1 -0
  57. package/dist/components/inputs/SingleLinePlugin.js +24 -0
  58. package/dist/components/inputs/SingleLinePlugin.js.map +1 -0
  59. package/dist/components/inputs/variables/VariableChip.d.ts.map +1 -1
  60. package/dist/components/inputs/variables/VariableChip.js +31 -32
  61. package/dist/components/inputs/variables/VariableChip.js.map +1 -1
  62. package/dist/components/inputs/variables/VariableChip.module.css +3 -3
  63. package/dist/components/inputs/variables/VariableSuggestion.d.ts +4 -0
  64. package/dist/components/inputs/variables/VariableSuggestion.d.ts.map +1 -0
  65. package/dist/components/inputs/variables/VariableSuggestion.js +24 -0
  66. package/dist/components/inputs/variables/VariableSuggestion.js.map +1 -0
  67. package/dist/components/inputs/variables/editors/PluralVariableEditor.d.ts.map +1 -1
  68. package/dist/components/inputs/variables/editors/PluralVariableEditor.js +62 -60
  69. package/dist/components/inputs/variables/editors/PluralVariableEditor.js.map +1 -1
  70. package/dist/components/inputs/variables/editors/PluralVariableEditor.module.css +4 -4
  71. package/dist/components/inputs/variables/editors/TemporalVariableEditor.d.ts +11 -0
  72. package/dist/components/inputs/variables/editors/TemporalVariableEditor.d.ts.map +1 -0
  73. package/dist/components/inputs/variables/editors/{DateVariableEditor.js → TemporalVariableEditor.js} +3 -3
  74. package/dist/components/inputs/variables/editors/TemporalVariableEditor.js.map +1 -0
  75. package/dist/components/inputs/variables/pickers/NumericVariableEditor.d.ts +7 -0
  76. package/dist/components/inputs/variables/pickers/{NumericVariablePicker.d.ts.map → NumericVariableEditor.d.ts.map} +1 -1
  77. package/dist/components/inputs/variables/pickers/{NumericVariablePicker.js → NumericVariableEditor.js} +15 -9
  78. package/dist/components/inputs/variables/pickers/NumericVariableEditor.js.map +1 -0
  79. package/dist/components/inputs/variables/pickers/{NumericVariablePicker.module.css → NumericVariableEditor.module.css} +3 -3
  80. package/dist/components/inputs/variables/pickers/TemporalVariablePicker.d.ts +7 -0
  81. package/dist/components/inputs/variables/pickers/TemporalVariablePicker.d.ts.map +1 -0
  82. package/dist/components/inputs/variables/pickers/TemporalVariablePicker.js +57 -0
  83. package/dist/components/inputs/variables/pickers/TemporalVariablePicker.js.map +1 -0
  84. package/dist/components/inputs/variables/pickers/{TemporalElementEditor.module.css → TemporalVariablePicker.module.css} +3 -3
  85. package/dist/components/layout/GroupStatusDot.d.ts +6 -0
  86. package/dist/components/layout/GroupStatusDot.d.ts.map +1 -0
  87. package/dist/components/layout/GroupStatusDot.js +24 -0
  88. package/dist/components/layout/GroupStatusDot.js.map +1 -0
  89. package/dist/components/layout/MessageField.d.ts +2 -1
  90. package/dist/components/layout/MessageField.d.ts.map +1 -1
  91. package/dist/components/layout/MessageField.js +52 -33
  92. package/dist/components/layout/MessageField.js.map +1 -1
  93. package/dist/components/layout/MessageField.module.css +21 -10
  94. package/dist/components/layout/MessagesTabs.d.ts.map +1 -1
  95. package/dist/components/layout/MessagesTabs.js +3 -5
  96. package/dist/components/layout/MessagesTabs.js.map +1 -1
  97. package/dist/components/layout/MessagesTree.d.ts +1 -1
  98. package/dist/components/layout/MessagesTree.d.ts.map +1 -1
  99. package/dist/components/layout/MessagesTree.js +33 -43
  100. package/dist/components/layout/MessagesTree.js.map +1 -1
  101. package/dist/components/layout/MessagesTree.module.css +10 -5
  102. package/dist/components/layout/StatusDot.d.ts +7 -0
  103. package/dist/components/layout/StatusDot.d.ts.map +1 -0
  104. package/dist/components/layout/StatusDot.js +12 -0
  105. package/dist/components/layout/StatusDot.js.map +1 -0
  106. package/dist/components/layout/StatusDot.module.css +16 -0
  107. package/dist/const.d.ts +2 -2
  108. package/dist/const.js +1 -1
  109. package/dist/entities.d.ts +1 -1
  110. package/dist/entities.js +1 -1
  111. package/dist/index.d.ts +2 -2
  112. package/dist/index.d.ts.map +1 -1
  113. package/dist/index.js.map +1 -1
  114. package/dist/internals/index.d.ts +30 -0
  115. package/dist/internals/index.d.ts.map +1 -0
  116. package/dist/internals/index.js +81 -0
  117. package/dist/internals/index.js.map +1 -0
  118. package/dist/internals/procedure.d.ts.map +1 -0
  119. package/dist/{_common → internals}/procedure.js +1 -0
  120. package/dist/internals/procedure.js.map +1 -0
  121. package/dist/internals/urls.d.ts.map +1 -0
  122. package/dist/internals/urls.js.map +1 -0
  123. package/dist/internals/utils.d.ts +8 -0
  124. package/dist/internals/utils.d.ts.map +1 -0
  125. package/dist/{_common → internals}/utils.js +20 -5
  126. package/dist/internals/utils.js.map +1 -0
  127. package/dist/utils/sanitize.d.ts +7 -6
  128. package/dist/utils/sanitize.d.ts.map +1 -1
  129. package/dist/utils/sanitize.js +11 -8
  130. package/dist/utils/sanitize.js.map +1 -1
  131. package/package.json +4 -3
  132. package/dist/_common/index.d.ts +0 -17
  133. package/dist/_common/index.d.ts.map +0 -1
  134. package/dist/_common/index.js +0 -27
  135. package/dist/_common/index.js.map +0 -1
  136. package/dist/_common/procedure.d.ts.map +0 -1
  137. package/dist/_common/procedure.js.map +0 -1
  138. package/dist/_common/urls.d.ts.map +0 -1
  139. package/dist/_common/urls.js.map +0 -1
  140. package/dist/_common/utils.d.ts +0 -5
  141. package/dist/_common/utils.d.ts.map +0 -1
  142. package/dist/_common/utils.js.map +0 -1
  143. package/dist/components/MessageController.d.ts +0 -13
  144. package/dist/components/MessageController.d.ts.map +0 -1
  145. package/dist/components/MessageController.js.map +0 -1
  146. package/dist/components/MessageFormContext.d.ts.map +0 -1
  147. package/dist/components/MessageFormContext.js.map +0 -1
  148. package/dist/components/actions/Move.d.ts +0 -2
  149. package/dist/components/actions/Move.d.ts.map +0 -1
  150. package/dist/components/actions/Move.js.map +0 -1
  151. package/dist/components/inputs/InputWrapper.d.ts +0 -8
  152. package/dist/components/inputs/InputWrapper.d.ts.map +0 -1
  153. package/dist/components/inputs/InputWrapper.js +0 -34
  154. package/dist/components/inputs/InputWrapper.js.map +0 -1
  155. package/dist/components/inputs/variables/editors/DateVariableEditor.d.ts +0 -10
  156. package/dist/components/inputs/variables/editors/DateVariableEditor.d.ts.map +0 -1
  157. package/dist/components/inputs/variables/editors/DateVariableEditor.js.map +0 -1
  158. package/dist/components/inputs/variables/editors/TimeVariableEditor.d.ts +0 -10
  159. package/dist/components/inputs/variables/editors/TimeVariableEditor.d.ts.map +0 -1
  160. package/dist/components/inputs/variables/editors/TimeVariableEditor.js +0 -15
  161. package/dist/components/inputs/variables/editors/TimeVariableEditor.js.map +0 -1
  162. package/dist/components/inputs/variables/pickers/NumericVariablePicker.d.ts +0 -7
  163. package/dist/components/inputs/variables/pickers/NumericVariablePicker.js.map +0 -1
  164. package/dist/components/inputs/variables/pickers/TemporalElementEditor.d.ts +0 -7
  165. package/dist/components/inputs/variables/pickers/TemporalElementEditor.d.ts.map +0 -1
  166. package/dist/components/inputs/variables/pickers/TemporalElementEditor.js +0 -58
  167. package/dist/components/inputs/variables/pickers/TemporalElementEditor.js.map +0 -1
  168. /package/dist/components/actions/{Move.module.css → CopyMessages.module.css} +0 -0
  169. /package/dist/{_common → internals}/procedure.d.ts +0 -0
  170. /package/dist/{_common → internals}/urls.d.ts +0 -0
  171. /package/dist/{_common → internals}/urls.js +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/components/inputs/variables/editors/PluralVariableEditor.tsx"],"sourcesContent":["import { TYPE } from '@formatjs/icu-messageformat-parser';\nimport { IconX } from '@tabler/icons-react';\nimport { Popover } from 'radix-ui';\nimport { Fragment, useImperativeHandle, useMemo } from 'react';\nimport { Controller, useFieldArray, useForm } from 'react-hook-form';\nimport type { PluralElement } from '@/types';\n\nimport { parseICUMessage, serializeICUMessage } from '@/utils/icu-tranform';\n\nimport styles from './PluralVariableEditor.module.css';\n\nconst NAMED_PLURAL_OPTIONS = ['zero', 'one', 'two', 'few', 'many'] as const;\n\nexport interface PluralVariableEditorProps {\n variableName: string;\n element: PluralElement | undefined;\n ref: React.Ref<{ getValue: () => string }>;\n}\n\n// TODO add support for selectordinal (\"pluralType\": \"ordinal\")\n\nexport function PluralVariableEditor({\n variableName,\n element,\n ref,\n}: PluralVariableEditorProps) {\n const config = useMemo<{\n offset: number;\n options: { name: string; content: string }[];\n other: string;\n }>(() => {\n const { other, ...options } = element?.options ?? {};\n return {\n offset: element?.offset ?? 0,\n options: Object.entries(options).map(([name, option]) => ({\n name,\n content: serializeICUMessage(option.value),\n })),\n other: serializeICUMessage(other ? other.value : []),\n };\n }, [element]);\n\n const { control, register, getValues } = useForm<{\n offset: number;\n options: { name: string; content: string }[];\n other: string;\n customValue?: number;\n }>({\n defaultValues: config,\n });\n\n useImperativeHandle(ref, () => ({\n getValue: () => {\n const values = getValues();\n const updatedElement: PluralElement = {\n type: TYPE.plural,\n value: variableName,\n offset: values.offset,\n pluralType: element?.pluralType ?? 'cardinal',\n options: Object.fromEntries(\n values.options.map(({ name, content }) => [\n name,\n { value: parseICUMessage(content) },\n ]),\n ),\n };\n return serializeICUMessage([updatedElement]);\n },\n }));\n\n const options = useFieldArray({\n control,\n name: 'options',\n });\n\n return (\n <div className={styles.root}>\n <fieldset className={styles.optionsFieldset}>\n <legend>Options</legend>\n {options.fields.map((field, index) => (\n <Fragment key={field.id}>\n <label htmlFor={`options.${index}`}>{field.name}</label>\n {/* // TODO add support for variable mentions */}\n <input\n className={styles.input}\n type=\"text\"\n {...register(`options.${index}.content`, { required: true })}\n />\n <button\n className={styles.removeButton}\n onClick={() => options.remove(index)}\n type=\"button\"\n >\n <IconX size={16} />\n </button>\n </Fragment>\n ))}\n\n <label htmlFor=\"other\">other</label>\n {/* // TODO add support for variable mentions */}\n <input\n className={styles.inputSpan2}\n type=\"text\"\n {...register('other', { required: true })}\n />\n </fieldset>\n <div className={styles.controlsGrid}>\n <label className={styles.offsetLabel}>\n offset\n <input\n className={styles.offsetInput}\n placeholder=\"0\"\n type=\"numeric\"\n {...register('offset')}\n />\n </label>\n <Popover.Root>\n <Popover.Trigger>Add Option</Popover.Trigger>\n <Popover.Portal>\n <Popover.Content className={styles.popoverContent} sideOffset={4}>\n <div className={styles.optionsList}>\n {NAMED_PLURAL_OPTIONS.filter((option) =>\n options.fields.every((field) => field.name !== option),\n ).map((option) => (\n <Popover.Close\n className={styles.optionItem}\n key={option}\n onClick={() => {\n // TODO ensure the fields are always in the same order as staticPluralOptions\n options.append(\n {\n name: option,\n content: '',\n },\n {\n shouldFocus: true,\n },\n );\n }}\n >\n {option}\n </Popover.Close>\n ))}\n </div>\n\n <div className={styles.customInputGroup}>\n <label htmlFor=\"customValue\">custom</label>\n <Controller\n control={control}\n name=\"customValue\"\n render={({ field }) => (\n <input\n className={styles.customInput}\n min={0}\n onChange={({ currentTarget: { value } }) => {\n const number = Number(value);\n if (Number.isNaN(number)) return;\n if (number < 0) return;\n field.onChange(number);\n }}\n onKeyDown={(e) => {\n if (e.key !== 'Enter') return;\n if (field.value === undefined) return;\n const isUnique = !options.fields.some(\n (existingField) =>\n existingField.name === `=${field.value}`,\n );\n if (!isUnique) return; // TODO maybe show error?\n options.append(\n {\n name: `=${field.value}`,\n content: '',\n },\n {\n shouldFocus: true,\n },\n );\n field.onChange(undefined);\n }}\n placeholder=\"=0\"\n type=\"numeric\"\n value={field.value ?? ''}\n />\n )}\n />\n </div>\n </Popover.Content>\n </Popover.Portal>\n </Popover.Root>\n </div>\n </div>\n );\n}\n"],"names":["TYPE","IconX","Popover","Fragment","useImperativeHandle","useMemo","Controller","useFieldArray","useForm","parseICUMessage","serializeICUMessage","styles","NAMED_PLURAL_OPTIONS","PluralVariableEditor","variableName","element","ref","config","other","options","offset","Object","entries","map","name","option","content","value","control","register","getValues","defaultValues","getValue","values","updatedElement","type","plural","pluralType","fromEntries","div","className","root","fieldset","optionsFieldset","legend","fields","field","index","label","htmlFor","input","required","button","removeButton","onClick","remove","size","id","inputSpan2","controlsGrid","offsetLabel","offsetInput","placeholder","Root","Trigger","Portal","Content","popoverContent","sideOffset","optionsList","filter","every","Close","optionItem","append","shouldFocus","customInputGroup","render","customInput","min","onChange","currentTarget","number","Number","isNaN","onKeyDown","e","key","undefined","isUnique","some","existingField"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../src/components/inputs/variables/editors/PluralVariableEditor.tsx"],"sourcesContent":["import { Popover } from '@base-ui/react/popover';\nimport { TYPE } from '@formatjs/icu-messageformat-parser';\nimport { IconX } from '@tabler/icons-react';\nimport { Fragment, useImperativeHandle, useMemo } from 'react';\nimport { Controller, useFieldArray, useForm } from 'react-hook-form';\nimport type { PluralElement } from '@/types';\n\nimport { parseICUMessage, serializeICUMessage } from '@/utils/icu-tranform';\n\nimport styles from './PluralVariableEditor.module.css';\n\nconst NAMED_PLURAL_OPTIONS = ['zero', 'one', 'two', 'few', 'many'] as const;\n\nexport interface PluralVariableEditorProps {\n variableName: string;\n element: PluralElement | undefined;\n ref: React.Ref<{ getValue: () => string }>;\n}\n\n// TODO add support for selectordinal (\"pluralType\": \"ordinal\")\n\nexport function PluralVariableEditor({\n variableName,\n element,\n ref,\n}: PluralVariableEditorProps) {\n const config = useMemo<{\n offset: number;\n options: { name: string; content: string }[];\n other: string;\n }>(() => {\n const { other, ...options } = element?.options ?? {};\n return {\n offset: element?.offset ?? 0,\n options: Object.entries(options).map(([name, option]) => ({\n name,\n content: serializeICUMessage(option.value),\n })),\n other: serializeICUMessage(other ? other.value : []),\n };\n }, [element]);\n\n const { control, register, getValues } = useForm<{\n offset: number;\n options: { name: string; content: string }[];\n other: string;\n customValue?: number;\n }>({\n defaultValues: config,\n });\n\n useImperativeHandle(ref, () => ({\n getValue: () => {\n const values = getValues();\n const updatedElement: PluralElement = {\n type: TYPE.plural,\n value: variableName,\n offset: values.offset,\n pluralType: element?.pluralType ?? 'cardinal',\n options: Object.fromEntries(\n values.options.map(({ name, content }) => [\n name,\n { value: parseICUMessage(content) },\n ]),\n ),\n };\n return serializeICUMessage([updatedElement]);\n },\n }));\n\n const options = useFieldArray({\n control,\n name: 'options',\n });\n\n return (\n <div className={styles.root}>\n <fieldset className={styles.optionsFieldset}>\n <legend>Options</legend>\n {options.fields.map((field, index) => (\n <Fragment key={field.id}>\n <label htmlFor={`options.${index}`}>{field.name}</label>\n {/* // TODO add support for variable mentions */}\n <input\n className={styles.input}\n type=\"text\"\n {...register(`options.${index}.content`, { required: true })}\n />\n <button\n className={styles.removeButton}\n onClick={() => options.remove(index)}\n type=\"button\"\n >\n <IconX size={16} />\n </button>\n </Fragment>\n ))}\n\n <label htmlFor=\"other\">other</label>\n {/* // TODO add support for variable mentions */}\n <input\n className={styles.inputSpan2}\n type=\"text\"\n {...register('other', { required: true })}\n />\n </fieldset>\n <div className={styles.controlsGrid}>\n <label className={styles.offsetLabel}>\n offset\n <input\n className={styles.offsetInput}\n placeholder=\"0\"\n type=\"numeric\"\n {...register('offset')}\n />\n </label>\n <Popover.Root>\n <Popover.Trigger>Add Option</Popover.Trigger>\n <Popover.Portal>\n <Popover.Positioner sideOffset={4}>\n <Popover.Popup className={styles.popoverContent}>\n <div className={styles.optionsList}>\n {NAMED_PLURAL_OPTIONS.filter((option) =>\n options.fields.every((field) => field.name !== option),\n ).map((option) => (\n <Popover.Close\n className={styles.optionItem}\n key={option}\n onClick={() => {\n // TODO ensure the fields are always in the same order as staticPluralOptions\n options.append(\n {\n name: option,\n content: '',\n },\n {\n shouldFocus: true,\n },\n );\n }}\n >\n {option}\n </Popover.Close>\n ))}\n </div>\n\n <div className={styles.customInputGroup}>\n <label htmlFor=\"customValue\">custom</label>\n <Controller\n control={control}\n name=\"customValue\"\n render={({ field }) => (\n <input\n className={styles.customInput}\n min={0}\n onChange={({ currentTarget: { value } }) => {\n const number = Number(value);\n if (Number.isNaN(number)) return;\n if (number < 0) return;\n field.onChange(number);\n }}\n onKeyDown={(e) => {\n if (e.key !== 'Enter') return;\n if (field.value === undefined) return;\n const isUnique = !options.fields.some(\n (existingField) =>\n existingField.name === `=${field.value}`,\n );\n if (!isUnique) return; // TODO maybe show error?\n options.append(\n {\n name: `=${field.value}`,\n content: '',\n },\n {\n shouldFocus: true,\n },\n );\n field.onChange(undefined);\n }}\n placeholder=\"=0\"\n type=\"numeric\"\n value={field.value ?? ''}\n />\n )}\n />\n </div>\n </Popover.Popup>\n </Popover.Positioner>\n </Popover.Portal>\n </Popover.Root>\n </div>\n </div>\n );\n}\n"],"names":["Popover","TYPE","IconX","Fragment","useImperativeHandle","useMemo","Controller","useFieldArray","useForm","parseICUMessage","serializeICUMessage","styles","NAMED_PLURAL_OPTIONS","PluralVariableEditor","variableName","element","ref","config","other","options","offset","Object","entries","map","name","option","content","value","control","register","getValues","defaultValues","getValue","values","updatedElement","type","plural","pluralType","fromEntries","div","className","root","fieldset","optionsFieldset","legend","fields","field","index","label","htmlFor","input","required","button","removeButton","onClick","remove","size","id","inputSpan2","controlsGrid","offsetLabel","offsetInput","placeholder","Root","Trigger","Portal","Positioner","sideOffset","Popup","popoverContent","optionsList","filter","every","Close","optionItem","append","shouldFocus","customInputGroup","render","customInput","min","onChange","currentTarget","number","Number","isNaN","onKeyDown","e","key","undefined","isUnique","some","existingField"],"mappings":"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"}
@@ -68,9 +68,9 @@
68
68
 
69
69
  .popoverContent {
70
70
  z-index: 50;
71
- max-height: var(--radix-dropdown-menu-content-available-height);
71
+ max-height: var(--available-height);
72
72
  min-width: 8rem;
73
- transform-origin: var(--radix-dropdown-menu-content-transform-origin);
73
+ transform-origin: var(--transform-origin);
74
74
  overflow-y: auto;
75
75
  overflow-x: hidden;
76
76
  border-radius: var(--style-radius-m);
@@ -81,11 +81,11 @@
81
81
  0 2px 4px -2px rgb(0 0 0 / 0.1);
82
82
  }
83
83
 
84
- .popoverContent[data-state="open"] {
84
+ .popoverContent[data-open] {
85
85
  animation: popoverIn 150ms ease-out;
86
86
  }
87
87
 
88
- .popoverContent[data-state="closed"] {
88
+ .popoverContent[data-closed] {
89
89
  animation: popoverOut 150ms ease-in;
90
90
  }
91
91
 
@@ -0,0 +1,11 @@
1
+ import type { DateElement, TimeElement } from '../../../../types';
2
+ export interface TemporalVariableEditorProps {
3
+ type: 'date' | 'time';
4
+ name: string;
5
+ element: DateElement | TimeElement | undefined;
6
+ ref: React.Ref<{
7
+ getValue: () => string;
8
+ }>;
9
+ }
10
+ export declare function TemporalVariableEditor({ type, ref, }: TemporalVariableEditorProps): import("react/jsx-runtime").JSX.Element;
11
+ //# sourceMappingURL=TemporalVariableEditor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TemporalVariableEditor.d.ts","sourceRoot":"","sources":["../../../../../src/components/inputs/variables/editors/TemporalVariableEditor.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAExD,MAAM,WAAW,2BAA2B;IAC1C,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,WAAW,GAAG,WAAW,GAAG,SAAS,CAAC;IAC/C,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC;QAAE,QAAQ,EAAE,MAAM,MAAM,CAAA;KAAE,CAAC,CAAC;CAC5C;AAED,wBAAgB,sBAAsB,CAAC,EACrC,IAAI,EACJ,GAAG,GACJ,EAAE,2BAA2B,2CAS7B"}
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useImperativeHandle } from 'react';
3
- export function DateVariableEditor({ ref }) {
3
+ export function TemporalVariableEditor({ type, ref }) {
4
4
  useImperativeHandle(ref, ()=>({
5
5
  getValue: ()=>{
6
6
  // TODO
@@ -8,8 +8,8 @@ export function DateVariableEditor({ ref }) {
8
8
  }
9
9
  }));
10
10
  return /*#__PURE__*/ _jsx(_Fragment, {
11
- children: "DateElementEditor"
11
+ children: type === 'date' ? 'DateElementEditor' : 'TimeElementEditor'
12
12
  });
13
13
  }
14
14
 
15
- //# sourceMappingURL=DateVariableEditor.js.map
15
+ //# sourceMappingURL=TemporalVariableEditor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../src/components/inputs/variables/editors/TemporalVariableEditor.tsx"],"sourcesContent":["import { useImperativeHandle } from 'react';\nimport type { DateElement, TimeElement } from '@/types';\n\nexport interface TemporalVariableEditorProps {\n type: 'date' | 'time';\n name: string;\n element: DateElement | TimeElement | undefined;\n ref: React.Ref<{ getValue: () => string }>;\n}\n\nexport function TemporalVariableEditor({\n type,\n ref,\n}: TemporalVariableEditorProps) {\n useImperativeHandle(ref, () => ({\n getValue: () => {\n // TODO\n return '';\n },\n }));\n\n return <>{type === 'date' ? 'DateElementEditor' : 'TimeElementEditor'}</>;\n}\n"],"names":["useImperativeHandle","TemporalVariableEditor","type","ref","getValue"],"mappings":";AAAA,SAASA,mBAAmB,QAAQ,QAAQ;AAU5C,OAAO,SAASC,uBAAuB,EACrCC,IAAI,EACJC,GAAG,EACyB;IAC5BH,oBAAoBG,KAAK,IAAO,CAAA;YAC9BC,UAAU;gBACR,OAAO;gBACP,OAAO;YACT;QACF,CAAA;IAEA,qBAAO;kBAAGF,SAAS,SAAS,sBAAsB;;AACpD"}
@@ -0,0 +1,7 @@
1
+ import type { NumberElement, PluralElement } from '../../../../types';
2
+ export interface NumericVariableEditorProps {
3
+ element: NumberElement | PluralElement;
4
+ onUpdate: (value: string) => void;
5
+ }
6
+ export declare function NumericVariableEditor({ element, onUpdate, }: NumericVariableEditorProps): import("react/jsx-runtime").JSX.Element;
7
+ //# sourceMappingURL=NumericVariableEditor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"NumericVariablePicker.d.ts","sourceRoot":"","sources":["../../../../../src/components/inputs/variables/pickers/NumericVariablePicker.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAe5D,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,aAAa,GAAG,aAAa,CAAC;IACvC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED,wBAAgB,qBAAqB,CAAC,EACpC,OAAO,EACP,QAAQ,GACT,EAAE,0BAA0B,2CA8C5B"}
1
+ {"version":3,"file":"NumericVariableEditor.d.ts","sourceRoot":"","sources":["../../../../../src/components/inputs/variables/pickers/NumericVariableEditor.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAe5D,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,aAAa,GAAG,aAAa,CAAC;IACvC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED,wBAAgB,qBAAqB,CAAC,EACpC,OAAO,EACP,QAAQ,GACT,EAAE,0BAA0B,2CA6C5B"}
@@ -1,14 +1,15 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { ToggleGroup } from 'radix-ui';
2
+ import { Toggle } from '@base-ui/react/toggle';
3
+ import { ToggleGroup } from '@base-ui/react/toggle-group';
3
4
  import { useEffect, useRef, useState } from 'react';
4
5
  import { isNumberElement, isPluralElement } from '../../../../utils/guards';
5
6
  import { PluralVariableEditor } from '../editors/PluralVariableEditor';
6
- import styles from './NumericVariablePicker.module.css';
7
+ import styles from './NumericVariableEditor.module.css';
7
8
  const NUMERIC_TYPES = [
8
9
  'number',
9
10
  'plural'
10
11
  ];
11
- export function NumericVariablePicker({ element, onUpdate }) {
12
+ export function NumericVariableEditor({ element, onUpdate }) {
12
13
  const [type, setType] = useState(()=>{
13
14
  if (isNumberElement(element)) return 'number';
14
15
  if (isPluralElement(element)) return 'plural';
@@ -24,12 +25,17 @@ export function NumericVariablePicker({ element, onUpdate }) {
24
25
  }, []);
25
26
  return /*#__PURE__*/ _jsxs("div", {
26
27
  children: [
27
- /*#__PURE__*/ _jsx(ToggleGroup.Root, {
28
+ /*#__PURE__*/ _jsx(ToggleGroup, {
28
29
  className: styles.toggleGroup,
29
- onValueChange: (value)=>setType(value),
30
- type: "single",
31
- value: type,
32
- children: NUMERIC_TYPES.map((type)=>/*#__PURE__*/ _jsx(ToggleGroup.Item, {
30
+ onValueChange: (newValue)=>{
31
+ if (newValue.length === 0) return;
32
+ const next = newValue.find((v)=>v !== type);
33
+ if (next) setType(next);
34
+ },
35
+ value: type ? [
36
+ type
37
+ ] : [],
38
+ children: NUMERIC_TYPES.map((type)=>/*#__PURE__*/ _jsx(Toggle, {
33
39
  className: styles.toggleItem,
34
40
  value: type,
35
41
  children: type
@@ -47,4 +53,4 @@ export function NumericVariablePicker({ element, onUpdate }) {
47
53
  });
48
54
  }
49
55
 
50
- //# sourceMappingURL=NumericVariablePicker.js.map
56
+ //# sourceMappingURL=NumericVariableEditor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../src/components/inputs/variables/pickers/NumericVariableEditor.tsx"],"sourcesContent":["import { Toggle } from '@base-ui/react/toggle';\nimport { ToggleGroup } from '@base-ui/react/toggle-group';\nimport { useEffect, useRef, useState } from 'react';\nimport type { NumberElement, PluralElement } from '@/types';\n\nimport { isNumberElement, isPluralElement } from '@/utils/guards';\n\nimport { PluralVariableEditor } from '../editors/PluralVariableEditor';\nimport styles from './NumericVariableEditor.module.css';\n\nconst NUMERIC_TYPES = [\n 'number',\n 'plural',\n // \"selectordinal\"\n] as const;\n\ntype NumericType = (typeof NUMERIC_TYPES)[number];\n\nexport interface NumericVariableEditorProps {\n element: NumberElement | PluralElement;\n onUpdate: (value: string) => void;\n}\n\nexport function NumericVariableEditor({\n element,\n onUpdate,\n}: NumericVariableEditorProps) {\n const [type, setType] = useState<NumericType | undefined>(() => {\n if (isNumberElement(element)) return 'number';\n if (isPluralElement(element)) return 'plural';\n return undefined;\n });\n const getValueRef = useRef<{ getValue: () => string }>(null);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: useEffectEvent\n useEffect(() => {\n return () => {\n if (!getValueRef.current) return;\n onUpdate(getValueRef.current.getValue());\n };\n }, []);\n\n return (\n <div>\n <ToggleGroup\n className={styles.toggleGroup}\n onValueChange={(newValue) => {\n if (newValue.length === 0) return;\n const next = newValue.find((v) => v !== type);\n if (next) setType(next as NumericType);\n }}\n value={type ? [type] : []}\n >\n {NUMERIC_TYPES.map((type) => (\n <Toggle className={styles.toggleItem} key={type} value={type}>\n {type}\n </Toggle>\n ))}\n </ToggleGroup>\n\n <div className={styles.content}>\n {type === 'plural' && (\n <PluralVariableEditor\n element={isPluralElement(element) ? element : undefined}\n ref={getValueRef}\n variableName={element.value}\n />\n )}\n </div>\n </div>\n );\n}\n"],"names":["Toggle","ToggleGroup","useEffect","useRef","useState","isNumberElement","isPluralElement","PluralVariableEditor","styles","NUMERIC_TYPES","NumericVariableEditor","element","onUpdate","type","setType","undefined","getValueRef","current","getValue","div","className","toggleGroup","onValueChange","newValue","length","next","find","v","value","map","toggleItem","content","ref","variableName"],"mappings":";AAAA,SAASA,MAAM,QAAQ,wBAAwB;AAC/C,SAASC,WAAW,QAAQ,8BAA8B;AAC1D,SAASC,SAAS,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,QAAQ;AAGpD,SAASC,eAAe,EAAEC,eAAe,QAAQ,iBAAiB;AAElE,SAASC,oBAAoB,QAAQ,kCAAkC;AACvE,OAAOC,YAAY,qCAAqC;AAExD,MAAMC,gBAAgB;IACpB;IACA;CAED;AASD,OAAO,SAASC,sBAAsB,EACpCC,OAAO,EACPC,QAAQ,EACmB;IAC3B,MAAM,CAACC,MAAMC,QAAQ,GAAGV,SAAkC;QACxD,IAAIC,gBAAgBM,UAAU,OAAO;QACrC,IAAIL,gBAAgBK,UAAU,OAAO;QACrC,OAAOI;IACT;IACA,MAAMC,cAAcb,OAAmC;IAEvD,0EAA0E;IAC1ED,UAAU;QACR,OAAO;YACL,IAAI,CAACc,YAAYC,OAAO,EAAE;YAC1BL,SAASI,YAAYC,OAAO,CAACC,QAAQ;QACvC;IACF,GAAG,EAAE;IAEL,qBACE,MAACC;;0BACC,KAAClB;gBACCmB,WAAWZ,OAAOa,WAAW;gBAC7BC,eAAe,CAACC;oBACd,IAAIA,SAASC,MAAM,KAAK,GAAG;oBAC3B,MAAMC,OAAOF,SAASG,IAAI,CAAC,CAACC,IAAMA,MAAMd;oBACxC,IAAIY,MAAMX,QAAQW;gBACpB;gBACAG,OAAOf,OAAO;oBAACA;iBAAK,GAAG,EAAE;0BAExBJ,cAAcoB,GAAG,CAAC,CAAChB,qBAClB,KAACb;wBAAOoB,WAAWZ,OAAOsB,UAAU;wBAAaF,OAAOf;kCACrDA;uBADwCA;;0BAM/C,KAACM;gBAAIC,WAAWZ,OAAOuB,OAAO;0BAC3BlB,SAAS,0BACR,KAACN;oBACCI,SAASL,gBAAgBK,WAAWA,UAAUI;oBAC9CiB,KAAKhB;oBACLiB,cAActB,QAAQiB,KAAK;;;;;AAMvC"}
@@ -8,16 +8,16 @@
8
8
  border: none;
9
9
  }
10
10
 
11
- .toggleItem[data-state="off"] {
11
+ .toggleItem:not([data-pressed]) {
12
12
  cursor: pointer;
13
13
  opacity: 0.5;
14
14
  }
15
15
 
16
- .toggleItem[data-state="off"]:hover {
16
+ .toggleItem:not([data-pressed]):hover {
17
17
  opacity: 1;
18
18
  }
19
19
 
20
- .toggleItem[data-state="on"] {
20
+ .toggleItem[data-pressed] {
21
21
  background-color: var(--theme-elevation-800);
22
22
  color: var(--theme-elevation-0);
23
23
  }
@@ -0,0 +1,7 @@
1
+ import type { DateElement, TimeElement } from '../../../../types';
2
+ export interface TemporalVariablePickerProps {
3
+ element: DateElement | TimeElement;
4
+ onUpdate: (value: string) => void;
5
+ }
6
+ export declare function TemporalVariablePicker({ element, onUpdate, }: TemporalVariablePickerProps): import("react/jsx-runtime").JSX.Element;
7
+ //# sourceMappingURL=TemporalVariablePicker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TemporalVariablePicker.d.ts","sourceRoot":"","sources":["../../../../../src/components/inputs/variables/pickers/TemporalVariablePicker.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAWxD,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,WAAW,GAAG,WAAW,CAAC;IACnC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED,wBAAgB,sBAAsB,CAAC,EACrC,OAAO,EACP,QAAQ,GACT,EAAE,2BAA2B,2CAsD7B"}
@@ -0,0 +1,57 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Toggle } from '@base-ui/react/toggle';
3
+ import { ToggleGroup } from '@base-ui/react/toggle-group';
4
+ import { useEffect, useRef, useState } from 'react';
5
+ import { isDateElement, isTimeElement } from '../../../../utils/guards';
6
+ import { TemporalVariableEditor } from '../editors/TemporalVariableEditor';
7
+ import styles from './TemporalVariablePicker.module.css';
8
+ const TEMPORAL_TYPES = [
9
+ 'date',
10
+ 'time'
11
+ ];
12
+ export function TemporalVariablePicker({ element, onUpdate }) {
13
+ const [type, setType] = useState(()=>{
14
+ if (isDateElement(element)) return 'date';
15
+ if (isTimeElement(element)) return 'time';
16
+ return undefined;
17
+ });
18
+ const getValueRef = useRef(null);
19
+ // biome-ignore lint/correctness/useExhaustiveDependencies: useEffectEvent
20
+ useEffect(()=>{
21
+ return ()=>{
22
+ if (!getValueRef.current) return;
23
+ onUpdate(getValueRef.current.getValue());
24
+ };
25
+ }, []);
26
+ return /*#__PURE__*/ _jsxs("div", {
27
+ children: [
28
+ /*#__PURE__*/ _jsx(ToggleGroup, {
29
+ className: styles.toggleGroup,
30
+ onValueChange: (newValue)=>{
31
+ if (newValue.length === 0) return;
32
+ const next = newValue.find((v)=>v !== type);
33
+ if (next) setType(next);
34
+ },
35
+ value: type ? [
36
+ type
37
+ ] : [],
38
+ children: TEMPORAL_TYPES.map((type)=>/*#__PURE__*/ _jsx(Toggle, {
39
+ className: styles.toggleItem,
40
+ value: type,
41
+ children: type
42
+ }, type))
43
+ }),
44
+ /*#__PURE__*/ _jsx("div", {
45
+ className: styles.content,
46
+ children: type && /*#__PURE__*/ _jsx(TemporalVariableEditor, {
47
+ element: type === 'date' ? isDateElement(element) ? element : undefined : isTimeElement(element) ? element : undefined,
48
+ name: element.value,
49
+ ref: getValueRef,
50
+ type: type
51
+ })
52
+ })
53
+ ]
54
+ });
55
+ }
56
+
57
+ //# sourceMappingURL=TemporalVariablePicker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../src/components/inputs/variables/pickers/TemporalVariablePicker.tsx"],"sourcesContent":["import { Toggle } from '@base-ui/react/toggle';\nimport { ToggleGroup } from '@base-ui/react/toggle-group';\nimport { useEffect, useRef, useState } from 'react';\nimport type { DateElement, TimeElement } from '@/types';\n\nimport { isDateElement, isTimeElement } from '@/utils/guards';\n\nimport { TemporalVariableEditor } from '../editors/TemporalVariableEditor';\nimport styles from './TemporalVariablePicker.module.css';\n\nconst TEMPORAL_TYPES = ['date', 'time'] as const;\n\ntype TemporalType = (typeof TEMPORAL_TYPES)[number];\n\nexport interface TemporalVariablePickerProps {\n element: DateElement | TimeElement;\n onUpdate: (value: string) => void;\n}\n\nexport function TemporalVariablePicker({\n element,\n onUpdate,\n}: TemporalVariablePickerProps) {\n const [type, setType] = useState<TemporalType | undefined>(() => {\n if (isDateElement(element)) return 'date';\n if (isTimeElement(element)) return 'time';\n return undefined;\n });\n const getValueRef = useRef<{ getValue: () => string }>(null);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: useEffectEvent\n useEffect(() => {\n return () => {\n if (!getValueRef.current) return;\n onUpdate(getValueRef.current.getValue());\n };\n }, []);\n\n return (\n <div>\n <ToggleGroup\n className={styles.toggleGroup}\n onValueChange={(newValue) => {\n if (newValue.length === 0) return;\n const next = newValue.find((v) => v !== type);\n if (next) setType(next as TemporalType);\n }}\n value={type ? [type] : []}\n >\n {TEMPORAL_TYPES.map((type) => (\n <Toggle className={styles.toggleItem} key={type} value={type}>\n {type}\n </Toggle>\n ))}\n </ToggleGroup>\n\n <div className={styles.content}>\n {type && (\n <TemporalVariableEditor\n element={\n type === 'date'\n ? isDateElement(element)\n ? element\n : undefined\n : isTimeElement(element)\n ? element\n : undefined\n }\n name={element.value}\n ref={getValueRef}\n type={type}\n />\n )}\n </div>\n </div>\n );\n}\n"],"names":["Toggle","ToggleGroup","useEffect","useRef","useState","isDateElement","isTimeElement","TemporalVariableEditor","styles","TEMPORAL_TYPES","TemporalVariablePicker","element","onUpdate","type","setType","undefined","getValueRef","current","getValue","div","className","toggleGroup","onValueChange","newValue","length","next","find","v","value","map","toggleItem","content","name","ref"],"mappings":";AAAA,SAASA,MAAM,QAAQ,wBAAwB;AAC/C,SAASC,WAAW,QAAQ,8BAA8B;AAC1D,SAASC,SAAS,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,QAAQ;AAGpD,SAASC,aAAa,EAAEC,aAAa,QAAQ,iBAAiB;AAE9D,SAASC,sBAAsB,QAAQ,oCAAoC;AAC3E,OAAOC,YAAY,sCAAsC;AAEzD,MAAMC,iBAAiB;IAAC;IAAQ;CAAO;AASvC,OAAO,SAASC,uBAAuB,EACrCC,OAAO,EACPC,QAAQ,EACoB;IAC5B,MAAM,CAACC,MAAMC,QAAQ,GAAGV,SAAmC;QACzD,IAAIC,cAAcM,UAAU,OAAO;QACnC,IAAIL,cAAcK,UAAU,OAAO;QACnC,OAAOI;IACT;IACA,MAAMC,cAAcb,OAAmC;IAEvD,0EAA0E;IAC1ED,UAAU;QACR,OAAO;YACL,IAAI,CAACc,YAAYC,OAAO,EAAE;YAC1BL,SAASI,YAAYC,OAAO,CAACC,QAAQ;QACvC;IACF,GAAG,EAAE;IAEL,qBACE,MAACC;;0BACC,KAAClB;gBACCmB,WAAWZ,OAAOa,WAAW;gBAC7BC,eAAe,CAACC;oBACd,IAAIA,SAASC,MAAM,KAAK,GAAG;oBAC3B,MAAMC,OAAOF,SAASG,IAAI,CAAC,CAACC,IAAMA,MAAMd;oBACxC,IAAIY,MAAMX,QAAQW;gBACpB;gBACAG,OAAOf,OAAO;oBAACA;iBAAK,GAAG,EAAE;0BAExBJ,eAAeoB,GAAG,CAAC,CAAChB,qBACnB,KAACb;wBAAOoB,WAAWZ,OAAOsB,UAAU;wBAAaF,OAAOf;kCACrDA;uBADwCA;;0BAM/C,KAACM;gBAAIC,WAAWZ,OAAOuB,OAAO;0BAC3BlB,sBACC,KAACN;oBACCI,SACEE,SAAS,SACLR,cAAcM,WACZA,UACAI,YACFT,cAAcK,WACZA,UACAI;oBAERiB,MAAMrB,QAAQiB,KAAK;oBACnBK,KAAKjB;oBACLH,MAAMA;;;;;AAMlB"}
@@ -8,16 +8,16 @@
8
8
  border: none;
9
9
  }
10
10
 
11
- .toggleItem[data-state="off"] {
11
+ .toggleItem:not([data-pressed]) {
12
12
  cursor: pointer;
13
13
  opacity: 0.5;
14
14
  }
15
15
 
16
- .toggleItem[data-state="off"]:hover {
16
+ .toggleItem:not([data-pressed]):hover {
17
17
  opacity: 1;
18
18
  }
19
19
 
20
- .toggleItem[data-state="on"] {
20
+ .toggleItem[data-pressed] {
21
21
  background-color: var(--theme-elevation-800);
22
22
  color: var(--theme-elevation-0);
23
23
  }
@@ -0,0 +1,6 @@
1
+ interface GroupStatusDotProps {
2
+ path: string;
3
+ }
4
+ export declare function GroupStatusDot({ path }: GroupStatusDotProps): import("react/jsx-runtime").JSX.Element;
5
+ export {};
6
+ //# sourceMappingURL=GroupStatusDot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GroupStatusDot.d.ts","sourceRoot":"","sources":["../../../src/components/layout/GroupStatusDot.tsx"],"names":[],"mappings":"AAaA,UAAU,mBAAmB;IAC3B,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,cAAc,CAAC,EAAE,IAAI,EAAE,EAAE,mBAAmB,2CAK3D"}
@@ -0,0 +1,24 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useWatch } from 'react-hook-form';
3
+ import { useMessagesForm } from '../../components/MessagesFormProvider';
4
+ import { StatusDot } from './StatusDot';
5
+ function isFullyTranslated(values) {
6
+ if (typeof values === 'string') return values.length > 0;
7
+ if (values && typeof values === 'object') {
8
+ return Object.values(values).every(isFullyTranslated);
9
+ }
10
+ return false;
11
+ }
12
+ export function GroupStatusDot({ path }) {
13
+ const { control, activeLocale } = useMessagesForm();
14
+ const value = useWatch({
15
+ control,
16
+ name: `${activeLocale}.${path}`
17
+ });
18
+ const status = isFullyTranslated(value) ? 'translated' : 'missing';
19
+ return /*#__PURE__*/ _jsx(StatusDot, {
20
+ status: status
21
+ });
22
+ }
23
+
24
+ //# sourceMappingURL=GroupStatusDot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/layout/GroupStatusDot.tsx"],"sourcesContent":["import { useWatch } from 'react-hook-form';\nimport { useMessagesForm } from '@/components/MessagesFormProvider';\n\nimport { StatusDot } from './StatusDot';\n\nfunction isFullyTranslated(values: unknown): boolean {\n if (typeof values === 'string') return values.length > 0;\n if (values && typeof values === 'object') {\n return Object.values(values).every(isFullyTranslated);\n }\n return false;\n}\n\ninterface GroupStatusDotProps {\n path: string;\n}\n\nexport function GroupStatusDot({ path }: GroupStatusDotProps) {\n const { control, activeLocale } = useMessagesForm();\n const value = useWatch({ control, name: `${activeLocale}.${path}` as never });\n const status = isFullyTranslated(value) ? 'translated' : 'missing';\n return <StatusDot status={status} />;\n}\n"],"names":["useWatch","useMessagesForm","StatusDot","isFullyTranslated","values","length","Object","every","GroupStatusDot","path","control","activeLocale","value","name","status"],"mappings":";AAAA,SAASA,QAAQ,QAAQ,kBAAkB;AAC3C,SAASC,eAAe,QAAQ,oCAAoC;AAEpE,SAASC,SAAS,QAAQ,cAAc;AAExC,SAASC,kBAAkBC,MAAe;IACxC,IAAI,OAAOA,WAAW,UAAU,OAAOA,OAAOC,MAAM,GAAG;IACvD,IAAID,UAAU,OAAOA,WAAW,UAAU;QACxC,OAAOE,OAAOF,MAAM,CAACA,QAAQG,KAAK,CAACJ;IACrC;IACA,OAAO;AACT;AAMA,OAAO,SAASK,eAAe,EAAEC,IAAI,EAAuB;IAC1D,MAAM,EAAEC,OAAO,EAAEC,YAAY,EAAE,GAAGV;IAClC,MAAMW,QAAQZ,SAAS;QAAEU;QAASG,MAAM,GAAGF,aAAa,CAAC,EAAEF,MAAM;IAAU;IAC3E,MAAMK,SAASX,kBAAkBS,SAAS,eAAe;IACzD,qBAAO,KAACV;QAAUY,QAAQA;;AAC5B"}
@@ -4,7 +4,8 @@ interface MessageFieldProps {
4
4
  messageKey: string;
5
5
  path: string;
6
6
  hidden?: boolean;
7
+ showStatus?: boolean;
7
8
  }
8
- export declare function MessageField({ schema, messageKey, path, hidden, }: MessageFieldProps): React.ReactNode;
9
+ export declare const MessageField: import("react").NamedExoticComponent<MessageFieldProps>;
9
10
  export {};
10
11
  //# sourceMappingURL=MessageField.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"MessageField.d.ts","sourceRoot":"","sources":["../../../src/components/layout/MessageField.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAO7C,UAAU,iBAAiB;IACzB,MAAM,EAAE,aAAa,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAgB,YAAY,CAAC,EAC3B,MAAM,EACN,UAAU,EACV,IAAI,EACJ,MAAM,GACP,EAAE,iBAAiB,GAAG,KAAK,CAAC,SAAS,CA8CrC"}
1
+ {"version":3,"file":"MessageField.d.ts","sourceRoot":"","sources":["../../../src/components/layout/MessageField.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAS7C,UAAU,iBAAiB;IACzB,MAAM,EAAE,aAAa,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,YAAY,yDAwDvB,CAAC"}
@@ -1,21 +1,38 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useMemo } from 'react';
3
- import { useMessagesForm } from '../../components/MessageFormContext';
2
+ import clsx from 'clsx';
3
+ import { get } from 'lodash-es';
4
+ import { memo, useMemo } from 'react';
5
+ import { useFormState, useWatch } from 'react-hook-form';
6
+ import { useMessagesForm } from '../../components/MessagesFormProvider';
7
+ import { toWords } from '../../utils/format';
4
8
  import { parseMessageSchema } from '../../utils/schema';
5
9
  import { createValidator } from '../../utils/validate';
6
- import { MessageController } from '../MessageController';
10
+ import { MessageFormField } from '../MessageFormField';
11
+ import { GroupStatusDot } from './GroupStatusDot';
7
12
  import styles from './MessageField.module.css';
8
- export function MessageField({ schema, messageKey, path, hidden }) {
9
- const { locales } = useMessagesForm();
13
+ export const MessageField = /*#__PURE__*/ memo(function MessageField({ schema, messageKey, path, hidden, showStatus }) {
14
+ const { defaultLocale, activeLocale, control } = useMessagesForm();
10
15
  const config = useMemo(()=>parseMessageSchema(schema), [
11
16
  schema
12
17
  ]);
13
18
  const validator = useMemo(()=>createValidator(config.variables), [
14
19
  config.variables
15
20
  ]);
16
- const [firstLocale, ...otherLocales] = locales;
17
- if (!firstLocale) return null;
18
- return /*#__PURE__*/ _jsxs("div", {
21
+ const multiline = schema.includes('\n');
22
+ const isDefaultLocale = activeLocale === defaultLocale;
23
+ const fieldPath = [
24
+ path,
25
+ messageKey
26
+ ].filter(Boolean).join('.');
27
+ const fullName = `${activeLocale}.${fieldPath}`;
28
+ const defaultValue = useWatch({
29
+ name: `${defaultLocale}.${fieldPath}`
30
+ });
31
+ const { errors } = useFormState({
32
+ control
33
+ });
34
+ const hasError = get(errors, fullName) !== undefined;
35
+ const content = /*#__PURE__*/ _jsxs("div", {
19
36
  style: {
20
37
  display: hidden ? 'none' : undefined
21
38
  },
@@ -23,35 +40,37 @@ export function MessageField({ schema, messageKey, path, hidden }) {
23
40
  config.description && /*#__PURE__*/ _jsx("p", {
24
41
  children: config.description
25
42
  }),
26
- otherLocales.length === 0 ? /*#__PURE__*/ _jsx(MessageController, {
27
- locale: firstLocale,
28
- name: [
29
- firstLocale,
30
- path,
31
- messageKey
32
- ].join('.'),
43
+ /*#__PURE__*/ _jsx(MessageFormField, {
44
+ locale: activeLocale,
45
+ multiline: multiline,
46
+ name: fullName,
47
+ reference: !isDefaultLocale ? defaultValue : undefined,
33
48
  validate: validator,
34
49
  variables: config.variables
35
- }) : /*#__PURE__*/ _jsx("div", {
36
- className: [
37
- styles.localeRow,
38
- styles.localeRowScrollable
39
- ].filter(Boolean).join(' '),
40
- children: locales.map((locale)=>/*#__PURE__*/ _jsx(MessageController, {
41
- className: styles.localeItem,
42
- label: locale.toUpperCase(),
43
- locale: locale,
44
- name: [
45
- locale,
46
- path,
47
- messageKey
48
- ].join('.'),
49
- validate: validator,
50
- variables: config.variables
51
- }, locale))
52
50
  })
53
51
  ]
54
52
  });
55
- }
53
+ if (showStatus !== undefined) {
54
+ return /*#__PURE__*/ _jsxs("div", {
55
+ className: clsx(styles.row, hasError && styles.rowError),
56
+ children: [
57
+ /*#__PURE__*/ _jsxs("span", {
58
+ className: styles.label,
59
+ children: [
60
+ toWords(messageKey),
61
+ showStatus && /*#__PURE__*/ _jsx(GroupStatusDot, {
62
+ path: fieldPath
63
+ })
64
+ ]
65
+ }),
66
+ /*#__PURE__*/ _jsx("div", {
67
+ className: styles.input,
68
+ children: content
69
+ })
70
+ ]
71
+ });
72
+ }
73
+ return content;
74
+ });
56
75
 
57
76
  //# sourceMappingURL=MessageField.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/layout/MessageField.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport { useMessagesForm } from '@/components/MessageFormContext';\nimport type { MessageSchema } from '@/types';\nimport { parseMessageSchema } from '@/utils/schema';\nimport { createValidator } from '@/utils/validate';\n\nimport { MessageController } from '../MessageController';\nimport styles from './MessageField.module.css';\n\ninterface MessageFieldProps {\n schema: MessageSchema;\n messageKey: string;\n path: string;\n hidden?: boolean;\n}\n\nexport function MessageField({\n schema,\n messageKey,\n path,\n hidden,\n}: MessageFieldProps): React.ReactNode {\n const { locales } = useMessagesForm();\n\n const config = useMemo(() => parseMessageSchema(schema), [schema]);\n\n const validator = useMemo(\n () => createValidator(config.variables),\n [config.variables],\n );\n\n const [firstLocale, ...otherLocales] = locales;\n\n if (!firstLocale) return null;\n\n return (\n <div style={{ display: hidden ? 'none' : undefined }}>\n {config.description && <p>{config.description}</p>}\n\n {otherLocales.length === 0 ? (\n <MessageController\n locale={firstLocale}\n name={[firstLocale, path, messageKey].join('.')}\n validate={validator}\n variables={config.variables}\n />\n ) : (\n <div\n className={[styles.localeRow, styles.localeRowScrollable]\n .filter(Boolean)\n .join(' ')}\n >\n {locales.map((locale) => (\n <MessageController\n className={styles.localeItem}\n key={locale}\n label={locale.toUpperCase()}\n locale={locale}\n name={[locale, path, messageKey].join('.')}\n validate={validator}\n variables={config.variables}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n"],"names":["useMemo","useMessagesForm","parseMessageSchema","createValidator","MessageController","styles","MessageField","schema","messageKey","path","hidden","locales","config","validator","variables","firstLocale","otherLocales","div","style","display","undefined","description","p","length","locale","name","join","validate","className","localeRow","localeRowScrollable","filter","Boolean","map","localeItem","label","toUpperCase"],"mappings":";AAAA,SAASA,OAAO,QAAQ,QAAQ;AAChC,SAASC,eAAe,QAAQ,kCAAkC;AAElE,SAASC,kBAAkB,QAAQ,iBAAiB;AACpD,SAASC,eAAe,QAAQ,mBAAmB;AAEnD,SAASC,iBAAiB,QAAQ,uBAAuB;AACzD,OAAOC,YAAY,4BAA4B;AAS/C,OAAO,SAASC,aAAa,EAC3BC,MAAM,EACNC,UAAU,EACVC,IAAI,EACJC,MAAM,EACY;IAClB,MAAM,EAAEC,OAAO,EAAE,GAAGV;IAEpB,MAAMW,SAASZ,QAAQ,IAAME,mBAAmBK,SAAS;QAACA;KAAO;IAEjE,MAAMM,YAAYb,QAChB,IAAMG,gBAAgBS,OAAOE,SAAS,GACtC;QAACF,OAAOE,SAAS;KAAC;IAGpB,MAAM,CAACC,aAAa,GAAGC,aAAa,GAAGL;IAEvC,IAAI,CAACI,aAAa,OAAO;IAEzB,qBACE,MAACE;QAAIC,OAAO;YAAEC,SAAST,SAAS,SAASU;QAAU;;YAChDR,OAAOS,WAAW,kBAAI,KAACC;0BAAGV,OAAOS,WAAW;;YAE5CL,aAAaO,MAAM,KAAK,kBACvB,KAACnB;gBACCoB,QAAQT;gBACRU,MAAM;oBAACV;oBAAaN;oBAAMD;iBAAW,CAACkB,IAAI,CAAC;gBAC3CC,UAAUd;gBACVC,WAAWF,OAAOE,SAAS;+BAG7B,KAACG;gBACCW,WAAW;oBAACvB,OAAOwB,SAAS;oBAAExB,OAAOyB,mBAAmB;iBAAC,CACtDC,MAAM,CAACC,SACPN,IAAI,CAAC;0BAEPf,QAAQsB,GAAG,CAAC,CAACT,uBACZ,KAACpB;wBACCwB,WAAWvB,OAAO6B,UAAU;wBAE5BC,OAAOX,OAAOY,WAAW;wBACzBZ,QAAQA;wBACRC,MAAM;4BAACD;4BAAQf;4BAAMD;yBAAW,CAACkB,IAAI,CAAC;wBACtCC,UAAUd;wBACVC,WAAWF,OAAOE,SAAS;uBALtBU;;;;AAYnB"}
1
+ {"version":3,"sources":["../../../src/components/layout/MessageField.tsx"],"sourcesContent":["import clsx from 'clsx';\nimport { get } from 'lodash-es';\nimport { memo, useMemo } from 'react';\nimport { useFormState, useWatch } from 'react-hook-form';\nimport { useMessagesForm } from '@/components/MessagesFormProvider';\nimport type { MessageSchema } from '@/types';\nimport { toWords } from '@/utils/format';\nimport { parseMessageSchema } from '@/utils/schema';\nimport { createValidator } from '@/utils/validate';\n\nimport { MessageFormField } from '../MessageFormField';\nimport { GroupStatusDot } from './GroupStatusDot';\nimport styles from './MessageField.module.css';\n\ninterface MessageFieldProps {\n schema: MessageSchema;\n messageKey: string;\n path: string;\n hidden?: boolean;\n showStatus?: boolean;\n}\n\nexport const MessageField = memo(function MessageField({\n schema,\n messageKey,\n path,\n hidden,\n showStatus,\n}: MessageFieldProps): React.ReactNode {\n const { defaultLocale, activeLocale, control } = useMessagesForm();\n\n const config = useMemo(() => parseMessageSchema(schema), [schema]);\n\n const validator = useMemo(\n () => createValidator(config.variables),\n [config.variables],\n );\n\n const multiline = schema.includes('\\n');\n const isDefaultLocale = activeLocale === defaultLocale;\n const fieldPath = [path, messageKey].filter(Boolean).join('.');\n const fullName = `${activeLocale}.${fieldPath}`;\n\n const defaultValue = useWatch({ name: `${defaultLocale}.${fieldPath}` }) as\n | string\n | undefined;\n\n const { errors } = useFormState({ control });\n const hasError = get(errors, fullName) !== undefined;\n\n const content = (\n <div style={{ display: hidden ? 'none' : undefined }}>\n {config.description && <p>{config.description}</p>}\n\n <MessageFormField\n locale={activeLocale}\n multiline={multiline}\n name={fullName}\n reference={!isDefaultLocale ? defaultValue : undefined}\n validate={validator}\n variables={config.variables}\n />\n </div>\n );\n\n if (showStatus !== undefined) {\n return (\n <div className={clsx(styles.row, hasError && styles.rowError)}>\n <span className={styles.label}>\n {toWords(messageKey)}\n {showStatus && <GroupStatusDot path={fieldPath} />}\n </span>\n <div className={styles.input}>{content}</div>\n </div>\n );\n }\n\n return content;\n});\n"],"names":["clsx","get","memo","useMemo","useFormState","useWatch","useMessagesForm","toWords","parseMessageSchema","createValidator","MessageFormField","GroupStatusDot","styles","MessageField","schema","messageKey","path","hidden","showStatus","defaultLocale","activeLocale","control","config","validator","variables","multiline","includes","isDefaultLocale","fieldPath","filter","Boolean","join","fullName","defaultValue","name","errors","hasError","undefined","content","div","style","display","description","p","locale","reference","validate","className","row","rowError","span","label","input"],"mappings":";AAAA,OAAOA,UAAU,OAAO;AACxB,SAASC,GAAG,QAAQ,YAAY;AAChC,SAASC,IAAI,EAAEC,OAAO,QAAQ,QAAQ;AACtC,SAASC,YAAY,EAAEC,QAAQ,QAAQ,kBAAkB;AACzD,SAASC,eAAe,QAAQ,oCAAoC;AAEpE,SAASC,OAAO,QAAQ,iBAAiB;AACzC,SAASC,kBAAkB,QAAQ,iBAAiB;AACpD,SAASC,eAAe,QAAQ,mBAAmB;AAEnD,SAASC,gBAAgB,QAAQ,sBAAsB;AACvD,SAASC,cAAc,QAAQ,mBAAmB;AAClD,OAAOC,YAAY,4BAA4B;AAU/C,OAAO,MAAMC,6BAAeX,KAAK,SAASW,aAAa,EACrDC,MAAM,EACNC,UAAU,EACVC,IAAI,EACJC,MAAM,EACNC,UAAU,EACQ;IAClB,MAAM,EAAEC,aAAa,EAAEC,YAAY,EAAEC,OAAO,EAAE,GAAGf;IAEjD,MAAMgB,SAASnB,QAAQ,IAAMK,mBAAmBM,SAAS;QAACA;KAAO;IAEjE,MAAMS,YAAYpB,QAChB,IAAMM,gBAAgBa,OAAOE,SAAS,GACtC;QAACF,OAAOE,SAAS;KAAC;IAGpB,MAAMC,YAAYX,OAAOY,QAAQ,CAAC;IAClC,MAAMC,kBAAkBP,iBAAiBD;IACzC,MAAMS,YAAY;QAACZ;QAAMD;KAAW,CAACc,MAAM,CAACC,SAASC,IAAI,CAAC;IAC1D,MAAMC,WAAW,GAAGZ,aAAa,CAAC,EAAEQ,WAAW;IAE/C,MAAMK,eAAe5B,SAAS;QAAE6B,MAAM,GAAGf,cAAc,CAAC,EAAES,WAAW;IAAC;IAItE,MAAM,EAAEO,MAAM,EAAE,GAAG/B,aAAa;QAAEiB;IAAQ;IAC1C,MAAMe,WAAWnC,IAAIkC,QAAQH,cAAcK;IAE3C,MAAMC,wBACJ,MAACC;QAAIC,OAAO;YAAEC,SAASxB,SAAS,SAASoB;QAAU;;YAChDf,OAAOoB,WAAW,kBAAI,KAACC;0BAAGrB,OAAOoB,WAAW;;0BAE7C,KAAChC;gBACCkC,QAAQxB;gBACRK,WAAWA;gBACXS,MAAMF;gBACNa,WAAW,CAAClB,kBAAkBM,eAAeI;gBAC7CS,UAAUvB;gBACVC,WAAWF,OAAOE,SAAS;;;;IAKjC,IAAIN,eAAemB,WAAW;QAC5B,qBACE,MAACE;YAAIQ,WAAW/C,KAAKY,OAAOoC,GAAG,EAAEZ,YAAYxB,OAAOqC,QAAQ;;8BAC1D,MAACC;oBAAKH,WAAWnC,OAAOuC,KAAK;;wBAC1B5C,QAAQQ;wBACRG,4BAAc,KAACP;4BAAeK,MAAMY;;;;8BAEvC,KAACW;oBAAIQ,WAAWnC,OAAOwC,KAAK;8BAAGd;;;;IAGrC;IAEA,OAAOA;AACT,GAAG"}
@@ -1,19 +1,30 @@
1
- .localeRow {
2
- margin-inline: -0.75rem;
1
+ .row {
3
2
  display: flex;
4
- min-width: 0;
3
+ align-items: flex-start;
5
4
  gap: 1rem;
6
- padding-inline: 0.75rem;
5
+ padding-left: 0.75rem;
6
+ background-color: var(--theme-elevation-50);
7
+ border: 1px solid var(--theme-border-color);
8
+ border-radius: var(--style-radius-m);
7
9
  }
8
10
 
9
- .localeRowScrollable {
10
- overflow-x: auto;
11
+ .rowError {
12
+ border-color: var(--theme-error-400);
11
13
  }
12
14
 
13
- .localeItem {
14
- flex: 1;
15
+ .label {
16
+ display: inline-flex;
17
+ align-items: center;
18
+ flex-shrink: 0;
19
+ min-width: 10ch;
20
+ padding-top: 0.35rem;
21
+ font-size: var(--font-size-large);
22
+ font-weight: 500;
15
23
  }
16
24
 
17
- .hidden {
18
- display: none;
25
+ .input {
26
+ flex: 1;
27
+ min-width: 0;
28
+ margin-block: -1px;
29
+ margin-right: -1px;
19
30
  }
@@ -1 +1 @@
1
- {"version":3,"file":"MessagesTabs.d.ts","sourceRoot":"","sources":["../../../src/components/layout/MessagesTabs.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAI9C,UAAU,iBAAiB;IACzB,MAAM,EAAE,cAAc,CAAC;IACvB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,YAAY,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC;AAGD,wBAAgB,YAAY,CAAC,EAC3B,MAAM,EACN,SAAS,EACT,YAAY,GACb,EAAE,iBAAiB,GAAG,KAAK,CAAC,SAAS,CAoCrC"}
1
+ {"version":3,"file":"MessagesTabs.d.ts","sourceRoot":"","sources":["../../../src/components/layout/MessagesTabs.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAI9C,UAAU,iBAAiB;IACzB,MAAM,EAAE,cAAc,CAAC;IACvB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,YAAY,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC;AAGD,wBAAgB,YAAY,CAAC,EAC3B,MAAM,EACN,SAAS,EACT,YAAY,GACb,EAAE,iBAAiB,GAAG,KAAK,CAAC,SAAS,CA+BrC"}
@@ -1,9 +1,10 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Button } from '@payloadcms/ui';
3
+ import clsx from 'clsx';
3
4
  import { get } from 'lodash-es';
4
5
  import { useCallback } from 'react';
5
6
  import { useFormState } from 'react-hook-form';
6
- import { useMessagesForm } from '../../components/MessageFormContext';
7
+ import { useMessagesForm } from '../../components/MessagesFormProvider';
7
8
  import { toWords } from '../../utils/format';
8
9
  import styles from './MessagesTabs.module.css';
9
10
  // TODO add hash for current tab to url
@@ -26,10 +27,7 @@ export function MessagesTabs({ schema, activeTab, setActiveTab }) {
26
27
  role: "tablist",
27
28
  children: Object.keys(schema).map((key)=>/*#__PURE__*/ _jsx(Button, {
28
29
  buttonStyle: activeTab === key ? 'pill' : 'tab',
29
- className: [
30
- styles.tab,
31
- hasErrors(key) ? activeTab === key ? styles.tabError : styles.tabErrorInactive : undefined
32
- ].filter(Boolean).join(' '),
30
+ className: clsx(styles.tab, hasErrors(key) && activeTab === key && styles.tabError, hasErrors(key) && activeTab !== key && styles.tabErrorInactive),
33
31
  onClick: ()=>setActiveTab(key),
34
32
  size: "large",
35
33
  type: "button",