@pareto-engineering/design-system 4.2.0 → 4.2.1-alpha.0

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 (48) hide show
  1. package/dist/cjs/f/fields/EditorInput/EditorInput.js +4 -6
  2. package/dist/cjs/g/FormBuilder/FormBuilder.js +38 -5
  3. package/dist/cjs/g/FormBuilder/common/Builder/Builder.js +62 -25
  4. package/dist/cjs/g/FormBuilder/common/Builder/common/ActionsContainer/ActionsContainer.js +80 -0
  5. package/dist/cjs/g/FormBuilder/common/Builder/common/ActionsContainer/index.js +13 -0
  6. package/dist/cjs/g/FormBuilder/common/Builder/common/ActionsContainer/styles.scss +59 -0
  7. package/dist/cjs/g/FormBuilder/common/Builder/common/InputBuilder/InputBuilder.js +19 -45
  8. package/dist/cjs/g/FormBuilder/common/Builder/common/InputBuilder/styles.scss +0 -49
  9. package/dist/cjs/g/FormBuilder/common/Builder/common/Section/Section.js +14 -3
  10. package/dist/cjs/g/FormBuilder/common/Builder/common/Section/styles.scss +61 -0
  11. package/dist/cjs/g/FormBuilder/common/Builder/common/index.js +8 -1
  12. package/dist/cjs/g/FormBuilder/common/Builder/styles.scss +5 -48
  13. package/dist/cjs/g/FormBuilder/common/Renderer/Renderer.js +76 -33
  14. package/dist/cjs/g/FormBuilder/common/Renderer/common/Section/Section.js +8 -3
  15. package/dist/cjs/g/FormBuilder/common/Renderer/styles.scss +12 -1
  16. package/dist/es/f/fields/EditorInput/EditorInput.js +5 -7
  17. package/dist/es/g/FormBuilder/FormBuilder.js +38 -5
  18. package/dist/es/g/FormBuilder/common/Builder/Builder.js +56 -20
  19. package/dist/es/g/FormBuilder/common/Builder/common/ActionsContainer/ActionsContainer.js +70 -0
  20. package/dist/es/g/FormBuilder/common/Builder/common/ActionsContainer/index.js +2 -0
  21. package/dist/es/g/FormBuilder/common/Builder/common/ActionsContainer/styles.scss +59 -0
  22. package/dist/es/g/FormBuilder/common/Builder/common/InputBuilder/InputBuilder.js +21 -47
  23. package/dist/es/g/FormBuilder/common/Builder/common/InputBuilder/styles.scss +0 -49
  24. package/dist/es/g/FormBuilder/common/Builder/common/Section/Section.js +14 -3
  25. package/dist/es/g/FormBuilder/common/Builder/common/Section/styles.scss +61 -0
  26. package/dist/es/g/FormBuilder/common/Builder/common/index.js +2 -1
  27. package/dist/es/g/FormBuilder/common/Builder/styles.scss +5 -48
  28. package/dist/es/g/FormBuilder/common/Renderer/Renderer.js +76 -34
  29. package/dist/es/g/FormBuilder/common/Renderer/common/Section/Section.js +8 -3
  30. package/dist/es/g/FormBuilder/common/Renderer/styles.scss +12 -1
  31. package/package.json +3 -3
  32. package/src/stories/g/FormBuilder.stories.jsx +116 -21
  33. package/src/ui/f/fields/EditorInput/EditorInput.jsx +6 -8
  34. package/src/ui/g/FormBuilder/FormBuilder.jsx +50 -3
  35. package/src/ui/g/FormBuilder/common/Builder/Builder.jsx +56 -18
  36. package/src/ui/g/FormBuilder/common/Builder/common/ActionsContainer/ActionsContainer.jsx +97 -0
  37. package/src/ui/g/FormBuilder/common/Builder/common/ActionsContainer/index.js +2 -0
  38. package/src/ui/g/FormBuilder/common/Builder/common/ActionsContainer/styles.scss +59 -0
  39. package/src/ui/g/FormBuilder/common/Builder/common/InputBuilder/InputBuilder.jsx +40 -60
  40. package/src/ui/g/FormBuilder/common/Builder/common/InputBuilder/styles.scss +0 -49
  41. package/src/ui/g/FormBuilder/common/Builder/common/Section/Section.jsx +26 -4
  42. package/src/ui/g/FormBuilder/common/Builder/common/Section/styles.scss +61 -0
  43. package/src/ui/g/FormBuilder/common/Builder/common/index.js +1 -0
  44. package/src/ui/g/FormBuilder/common/Builder/styles.scss +5 -48
  45. package/src/ui/g/FormBuilder/common/Renderer/Renderer.jsx +84 -33
  46. package/src/ui/g/FormBuilder/common/Renderer/common/Section/Section.jsx +3 -2
  47. package/src/ui/g/FormBuilder/common/Renderer/styles.scss +12 -1
  48. package/tests/__snapshots__/Storyshots.test.js.snap +395 -133
@@ -44,38 +44,82 @@ export const Builder = {
44
44
  const sampleFormData = {
45
45
  sections:[
46
46
  {
47
- title :'titlel',
48
- description:'{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"background-color: #a37575;","text":"asdvczvcsdvjksadvkl sdvasdvn mdvaskldvnsdavkjc,mndsvb asdvsdvsadv","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}',
49
- key :'section-title',
47
+ title :'This is a survey of some of the best LLM models out there',
48
+ description:'{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Best LLM models for software developers","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"heading","version":1,"tag":"h3"},{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Chat GPT","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"listitem","version":1,"value":1},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Perplexity","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"listitem","version":1,"value":2},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Gemini","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"listitem","version":1,"value":3},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Claude","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"listitem","version":1,"value":4}],"direction":"ltr","format":"","indent":0,"type":"list","version":1,"listType":"bullet","start":1,"tag":"ul"},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Please add more exciting models that we might missed","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"quote","version":1},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"You can make them ","type":"text","version":1},{"detail":0,"format":1,"mode":"normal","style":"","text":"bold","type":"text","version":1},{"detail":0,"format":0,"mode":"normal","style":"","text":" or ","type":"text","version":1},{"detail":0,"format":2,"mode":"normal","style":"","text":"Italic or ","type":"text","version":1},{"detail":0,"format":10,"mode":"normal","style":"","text":"underlined","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1},{"children":[{"detail":0,"format":4,"mode":"normal","style":"color: #110b53;","text":"You can also color them and strike through them!","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}',
49
+ key :'section-0',
50
50
  inputs :[
51
51
  {
52
- name :'section_0_input_0',
53
- label :'Names',
54
- type :'multiple',
55
- required:false,
56
- options :[
52
+ name :'section_0_input_0',
53
+ label :'Name the Model',
54
+ type :'text',
55
+ required :true,
56
+ options :[],
57
+ conditionalLogic:null,
58
+ description :'',
59
+ },
60
+ {
61
+ name :'section_0_input_1',
62
+ label :'Describe the Model in detail',
63
+ type :'textarea',
64
+ required :false,
65
+ options :[],
66
+ conditionalLogic:null,
67
+ description :'brief model description',
68
+ },
69
+ ],
70
+ orderedInputDragIds:[],
71
+ navigation :{
72
+ nextSection:'next',
73
+ },
74
+ },
75
+ {
76
+ title :'Rate the Models',
77
+ description:'{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Best LLM models for software developers","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1},{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Chat GPT","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"listitem","version":1,"value":1},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Perplexity","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"listitem","version":1,"value":2},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Gemini","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"listitem","version":1,"value":3},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Claude","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"listitem","version":1,"value":4}],"direction":"ltr","format":"","indent":0,"type":"list","version":1,"listType":"bullet","start":1,"tag":"ul"},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Please add more exciting models that we might missed","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"quote","version":1},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"You can make them ","type":"text","version":1},{"detail":0,"format":1,"mode":"normal","style":"","text":"bold","type":"text","version":1},{"detail":0,"format":0,"mode":"normal","style":"","text":" or ","type":"text","version":1},{"detail":0,"format":2,"mode":"normal","style":"","text":"Italic or ","type":"text","version":1},{"detail":0,"format":10,"mode":"normal","style":"","text":"underlined","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1},{"children":[{"detail":0,"format":4,"mode":"normal","style":"","text":"You can also color them and strike through them!","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}',
78
+ key :'section-1',
79
+ inputs :[
80
+ {
81
+ type :'choices',
82
+ options:[
57
83
  {
58
- key :'sections-0-inputs-0-options--1',
59
- value :'James',
60
- label :'James',
84
+ key :'sections-1-inputs-0-options--1',
85
+ value :'Chat GPT',
86
+ label :'Chat GPT',
61
87
  nextSection:'',
62
88
  },
63
89
  {
64
- key :'sections-0-inputs-0-options-0',
65
- value :'Coigo',
66
- label :'Coigo',
90
+ key :'sections-1-inputs-0-options-0',
91
+ value :'Gemini',
92
+ label :'Gemini',
93
+ nextSection:'',
94
+ },
95
+ ],
96
+ required :true,
97
+ description:'',
98
+ name :'section_1_input_0',
99
+ label :'Which is better between the 2?',
100
+ },
101
+ {
102
+ name :'section_1_input_1',
103
+ label :'Choose the worst of them ',
104
+ type :'multiple',
105
+ required:false,
106
+ options :[
107
+ {
108
+ key :'sections-1-inputs-1-options--1',
109
+ value :'Chat GPT',
110
+ label :'Chat GPT',
67
111
  nextSection:'',
68
112
  },
69
113
  {
70
- key :'sections-0-inputs-0-options-1',
71
- value :'Nyanjui',
72
- label :'Nyanjui',
114
+ key :'sections-1-inputs-1-options-0',
115
+ value :'Gemini',
116
+ label :'Gemini',
73
117
  nextSection:'',
74
118
  },
75
119
  {
76
- key :'sections-0-inputs-0-options-2',
77
- value :'Masalia',
78
- label :'Masalia',
120
+ key :'sections-1-inputs-1-options-1',
121
+ value :'Claude',
122
+ label :'Claude',
79
123
  nextSection:'',
80
124
  },
81
125
  ],
@@ -83,15 +127,66 @@ const sampleFormData = {
83
127
  description :'',
84
128
  },
85
129
  ],
86
- navigation:{
130
+ orderedInputDragIds:[],
131
+ navigation :{
132
+ nextSection:'next',
133
+ },
134
+ },
135
+ {
136
+ title :'General sentiments',
137
+ description:'{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Best LLM models for software developers","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"heading","version":1,"tag":"h3"},{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Chat GPT","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"listitem","version":1,"value":1},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Perplexity","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"listitem","version":1,"value":2},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Gemini","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"listitem","version":1,"value":3},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Claude","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"listitem","version":1,"value":4}],"direction":"ltr","format":"","indent":0,"type":"list","version":1,"listType":"bullet","start":1,"tag":"ul"},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Please add more exciting models that we might missed","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"quote","version":1},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"You can make them ","type":"text","version":1},{"detail":0,"format":1,"mode":"normal","style":"","text":"bold","type":"text","version":1},{"detail":0,"format":0,"mode":"normal","style":"","text":" or ","type":"text","version":1},{"detail":0,"format":2,"mode":"normal","style":"","text":"Italic or ","type":"text","version":1},{"detail":0,"format":10,"mode":"normal","style":"","text":"underlined","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1},{"children":[{"detail":0,"format":4,"mode":"normal","style":"","text":"You can also color them and strike through them!","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}',
138
+ key :'section-2',
139
+ inputs :[
140
+ {
141
+ type :'textarea',
142
+ options :[],
143
+ required :true,
144
+ description:'',
145
+ name :'section_2_input_0',
146
+ label :'Give a final brief description of your findings',
147
+ },
148
+ ],
149
+ orderedInputDragIds:[],
150
+ navigation :{
87
151
  nextSection:'next',
88
152
  },
89
153
  },
90
154
  ],
91
155
  }
156
+
92
157
  export const Renderer = {
93
158
  args:{
94
159
  mode :'render',
95
160
  formData:sampleFormData,
96
161
  },
162
+ render:(args) => {
163
+ const [values, setValues] = useState({})
164
+
165
+ const handleFormDataUpdateWithValues = (argsValues) => {
166
+ setValues(argsValues)
167
+ }
168
+
169
+ return (
170
+ <>
171
+ <FormBuilder {...args} onRendererFormSave={handleFormDataUpdateWithValues} />
172
+ <pre>{JSON.stringify(values, null, 2)}</pre>
173
+ </>
174
+ )
175
+ },
176
+ }
177
+
178
+ export const RendererWithSubmit = {
179
+ ...Renderer,
180
+ args:{
181
+ ...Renderer.args,
182
+ shouldSubmit:true,
183
+ },
184
+ }
185
+
186
+ export const RendererWithDisabled = {
187
+ ...Renderer,
188
+ args:{
189
+ ...Renderer.args,
190
+ readOnly:true,
191
+ },
97
192
  }
@@ -2,7 +2,7 @@
2
2
  /* eslint-disable import/no-extraneous-dependencies -- required here */
3
3
  import * as React from 'react'
4
4
  import { memo, useEffect } from 'react'
5
- import { useFormikContext } from 'formik'
5
+ import { useField, useFormikContext } from 'formik'
6
6
  import { LexicalComposer } from '@lexical/react/LexicalComposer'
7
7
  import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin'
8
8
  import { ContentEditable } from '@lexical/react/LexicalContentEditable'
@@ -62,17 +62,15 @@ const EditorInput = ({
62
62
  showDebugger,
63
63
  stopPropagationKeys,
64
64
  setEditorState,
65
- // handleOnChange,
66
65
  // ...otherProps
67
66
  }) => {
68
- const { values, setFieldValue } = useFormikContext()
67
+ const [field, ,] = useField(name)
68
+ const { setFieldValue } = useFormikContext()
69
69
 
70
70
  const setInitialValue = () => {
71
- const value = values[name]
72
-
73
71
  try {
74
- JSON.parse(value)
75
- return value
72
+ JSON.parse(field.value)
73
+ return field.value
76
74
  } catch {
77
75
  const defaultValue = {
78
76
  root:{
@@ -103,7 +101,7 @@ const EditorInput = ({
103
101
  version :1,
104
102
  },
105
103
  }
106
- defaultValue.root.children[0].children[0].text = value
104
+ defaultValue.root.children[0].children[0].text = field.value
107
105
  return JSON.stringify(defaultValue)
108
106
  }
109
107
  }
@@ -24,9 +24,15 @@ const FormBuilder = ({
24
24
  style,
25
25
  mode,
26
26
  formData,
27
+ readOnly,
28
+ shouldSubmit,
27
29
  formBuilderId,
28
30
  onBuilderFormSave,
31
+ onBuilderError,
32
+ onRendererError,
29
33
  onRendererFormSave,
34
+ onBuilderValidate,
35
+ initialBuilderValues,
30
36
  // ...otherProps
31
37
  }) => (
32
38
  <div
@@ -43,8 +49,24 @@ const FormBuilder = ({
43
49
  style={style}
44
50
  // {...otherProps}
45
51
  >
46
- {mode === 'build' && <Builder formBuilderId={formBuilderId} onSave={onBuilderFormSave} />}
47
- {mode === 'render' && <Renderer formData={formData} onSave={onRendererFormSave} />}
52
+ {mode === 'build' && (
53
+ <Builder
54
+ initialValues={initialBuilderValues}
55
+ formBuilderId={formBuilderId}
56
+ onSave={onBuilderFormSave}
57
+ onError={onBuilderError}
58
+ validate={onBuilderValidate}
59
+ />
60
+ )}
61
+ {mode === 'render' && (
62
+ <Renderer
63
+ formData={formData}
64
+ onSave={onRendererFormSave}
65
+ readOnly={readOnly}
66
+ shouldSubmit={shouldSubmit}
67
+ onError={onRendererError}
68
+ />
69
+ )}
48
70
  </div>
49
71
  )
50
72
 
@@ -73,10 +95,35 @@ FormBuilder.propTypes = {
73
95
  * This is the ID of the form element in the <Builder /> component
74
96
  */
75
97
  formBuilderId:PropTypes.string.isRequired,
98
+
99
+ /**
100
+ * The form data to be used to construct the form builder in renderer mode
101
+ */
102
+ formData:PropTypes.shape({
103
+ sections:PropTypes.arrayOf(PropTypes.objectOf(PropTypes.any)),
104
+ }),
105
+
106
+ /**
107
+ * The initial values to instatiate form builder in builder mode
108
+ */
109
+ initialBuilderValues:PropTypes.shape({
110
+ sections:PropTypes.arrayOf(PropTypes.objectOf(PropTypes.any)),
111
+ }),
112
+
113
+ /**
114
+ * Whether the whole Form in renderer mode should be readOnly
115
+ */
116
+ readOnly:PropTypes.bool,
117
+
118
+ /**
119
+ * Whether the form builder in renderer mode should submit the form values itself
120
+ */
121
+ shouldSubmit:PropTypes.bool,
76
122
  }
77
123
 
78
124
  FormBuilder.defaultProps = {
79
- mode:'build',
125
+ mode :'build',
126
+ readOnly:false,
80
127
  }
81
128
 
82
129
  FormBuilder.Builder = Builder
@@ -1,6 +1,8 @@
1
1
  /* @pareto-engineering/generator-front 1.1.1-alpha.2 */
2
2
  import * as React from 'react'
3
3
 
4
+ import { useEffect } from 'react'
5
+
4
6
  import { Formik, Form, FieldArray } from 'formik'
5
7
 
6
8
  import PropTypes from 'prop-types'
@@ -38,12 +40,43 @@ const Builder = ({
38
40
  className:userClassName,
39
41
  style,
40
42
  onSave,
43
+ onError,
44
+ validate,
41
45
  formBuilderId,
46
+ initialValues = {},
42
47
  // ...otherProps
43
48
  }) => {
44
49
  const handleSubmit = (values) => {
45
50
  const reOrderedValues = reorderInputs(values)
46
- onSave(reOrderedValues)
51
+ onSave?.(reOrderedValues)
52
+ }
53
+
54
+ const initialFormState = initialValues?.sections
55
+ ? initialValues
56
+ : {
57
+ sections:[
58
+ {
59
+ title :'',
60
+ description :'',
61
+ key :'section-0',
62
+ inputs :[],
63
+ orderedInputDragIds:[],
64
+ navigation :{ nextSection: 'next' },
65
+ },
66
+ ],
67
+ }
68
+
69
+ const handleDeleteSection = ({ index, remove, values }) => {
70
+ remove(index)
71
+
72
+ values.sections.splice(index, 1)
73
+
74
+ values.sections.forEach((section, sectionIndex) => {
75
+ section.inputs.forEach((input, inputIndex) => {
76
+ // eslint-disable-next-line no-param-reassign
77
+ input.name = `section_${sectionIndex}_input_${inputIndex}`
78
+ })
79
+ })
47
80
  }
48
81
 
49
82
  return (
@@ -61,22 +94,21 @@ const Builder = ({
61
94
 
62
95
  <p className="h3">Form Builder</p>
63
96
  <Formik
64
- initialValues={{
65
- sections:[
66
- {
67
- title :'',
68
- description :'',
69
- key :'section-0',
70
- inputs :[],
71
- orderedInputDragIds:[],
72
- navigation :{ nextSection: 'next' },
73
- },
74
- ],
75
- }}
97
+ initialValues={initialFormState}
76
98
  onSubmit={handleSubmit}
99
+ validate={validate}
77
100
  >
78
- {({ values }) => {
79
- const availableSections = values.sections.map((section, idx) => ({
101
+ {({ values, errors, setFieldValue }) => {
102
+ useEffect(() => {
103
+ const reOrderedValues = reorderInputs(values)
104
+ onSave?.(reOrderedValues)
105
+ }, [values])
106
+
107
+ useEffect(() => {
108
+ onError?.(errors)
109
+ }, [errors, values])
110
+
111
+ const availableSections = values?.sections?.map((section, idx) => ({
80
112
  value:idx,
81
113
  label:`Go to ${section.title || `Untitled Section ${idx + 1}`}`,
82
114
  }))
@@ -84,10 +116,16 @@ const Builder = ({
84
116
  return (
85
117
  <Form id={formBuilderId}>
86
118
  <FieldArray name="sections">
87
- {({ push }) => (
119
+ {({ push, remove }) => (
88
120
  <>
89
- {values.sections.map((section, index) => (
90
- <Section key={section.key} index={index} />
121
+ {values?.sections?.map((section, index) => (
122
+ <Section
123
+ key={section.key}
124
+ index={index}
125
+ handleDeleteSection={() => handleDeleteSection({
126
+ index, remove, values, setFieldValue,
127
+ })}
128
+ />
91
129
  ))}
92
130
  <div className="section-footer">
93
131
  <button
@@ -0,0 +1,97 @@
1
+ /* @pareto-engineering/generator-front 1.1.1-alpha.2 */
2
+ import * as React from 'react'
3
+
4
+ import { useState, useRef } from 'react'
5
+
6
+ import PropTypes from 'prop-types'
7
+
8
+ import styleNames from '@pareto-engineering/bem/exports'
9
+
10
+ import './styles.scss'
11
+
12
+ // Local Definitions
13
+
14
+ import { useOutsideClick } from 'ui/utils'
15
+
16
+ import { Popover } from 'ui/a'
17
+
18
+ const baseClassName = styleNames.base
19
+
20
+ const componentClassName = 'actions-container'
21
+
22
+ /**
23
+ * This is the component description.
24
+ */
25
+ const ActionsContainer = ({
26
+ id,
27
+ className:userClassName,
28
+ style,
29
+ preferredPopoverOrder,
30
+ children,
31
+ // ...otherProps
32
+ }) => {
33
+ const parentRef = useRef(null)
34
+ const [isOpen, setIsOpen] = useState(false)
35
+ useOutsideClick(parentRef, () => setIsOpen(false))
36
+
37
+ return (
38
+ <div
39
+ id={id}
40
+ className={[
41
+
42
+ baseClassName,
43
+
44
+ componentClassName,
45
+ userClassName,
46
+ ]
47
+ .filter((e) => e)
48
+ .join(' ')}
49
+ style={style}
50
+ ref={parentRef}
51
+ >
52
+ <button type="button" onClick={() => setIsOpen(!isOpen)}>
53
+ <span className="icon x-ui-icons c-x">!</span>
54
+ </button>
55
+ <Popover
56
+ isOpen={isOpen}
57
+ parentRef={parentRef}
58
+ preferredPrimaryOrder={preferredPopoverOrder}
59
+ >
60
+ {children}
61
+ </Popover>
62
+ </div>
63
+ )
64
+ }
65
+
66
+ ActionsContainer.propTypes = {
67
+ /**
68
+ * The HTML id for this element
69
+ */
70
+ id:PropTypes.string,
71
+
72
+ /**
73
+ * The HTML class names for this element
74
+ */
75
+ className:PropTypes.string,
76
+
77
+ /**
78
+ * The React-written, css properties for this element.
79
+ */
80
+ style:PropTypes.objectOf(PropTypes.string),
81
+
82
+ /**
83
+ * The preferred order for the popover
84
+ */
85
+ preferredPopoverOrder:PropTypes.arrayOf(PropTypes.string),
86
+
87
+ /**
88
+ * The children of the actions container
89
+ */
90
+ children:PropTypes.node,
91
+ }
92
+
93
+ ActionsContainer.defaultProps = {
94
+ preferredPopoverOrder:['right', 'bottom', 'left', 'top'],
95
+ }
96
+
97
+ export default ActionsContainer
@@ -0,0 +1,2 @@
1
+ /* @pareto-engineering/generator-front 1.1.1-alpha.2 */
2
+ export { default as ActionsContainer } from './ActionsContainer'
@@ -0,0 +1,59 @@
1
+ /* @pareto-engineering/generator-front 1.1.1-alpha.2 */
2
+
3
+ @use "@pareto-engineering/bem";
4
+
5
+ $default-padding: 1rem;
6
+ $default-margin: 1rem;
7
+ $default-list-width: var(--action-button-width, 18rem);
8
+
9
+ .#{bem.$base}.actions-container {
10
+ position: relative;
11
+
12
+ > button {
13
+ background-color: transparent;
14
+ border: 0;
15
+ cursor: pointer;
16
+ }
17
+
18
+ > .#{bem.$base}.popover {
19
+ background-color: var(--background-cards);
20
+ border: var(--theme-default-border-style) var(--main2);
21
+ border-radius: calc(var(--theme-default-border-radius) / 2);
22
+ cursor: default;
23
+ padding: $default-padding;
24
+ width: $default-list-width;
25
+
26
+ > p {
27
+ margin: 0;
28
+ }
29
+
30
+ > ul {
31
+ list-style: none;
32
+ margin: 0;
33
+ padding: 0;
34
+ white-space: nowrap;
35
+
36
+ > .option {
37
+ cursor: pointer;
38
+ padding-block: calc($default-padding / 4);
39
+
40
+ &:not(.with-check-mark) {
41
+ padding-inline: $default-padding;
42
+ }
43
+
44
+ /* stylelint-disable-next-line selector-max-compound-selectors -- required */
45
+ > button {
46
+ background: transparent;
47
+ border: 0;
48
+ color: var(--paragraph);
49
+ cursor: pointer;
50
+ font-size: calc(var(--s0) * .875rem);
51
+ text-align: left;
52
+ width: 100%;
53
+ }
54
+ }
55
+ }
56
+ }
57
+ }
58
+
59
+