@plusscommunities/pluss-feature-builder-web-a 1.0.7 → 1.0.9-beta.3

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 (119) hide show
  1. package/dist/{index.cjs.js → index.js} +3803 -3504
  2. package/dist/index.js.map +1 -0
  3. package/package.json +20 -27
  4. package/.babelrc +0 -4
  5. package/rollup.config.js +0 -69
  6. package/src/actions/featureBuilderStringsActions.js +0 -88
  7. package/src/actions/featureDefinitionsIndex.js +0 -258
  8. package/src/actions/formActions.js +0 -301
  9. package/src/actions/index.js +0 -12
  10. package/src/actions/listingActions.js +0 -352
  11. package/src/actions/wizardActions.js +0 -228
  12. package/src/components/ActivityCardExample.jsx +0 -86
  13. package/src/components/ActivityCardExample.module.css +0 -130
  14. package/src/components/BackgroundLoader.jsx +0 -33
  15. package/src/components/BackgroundLoader.module.css +0 -46
  16. package/src/components/BaseFieldConfig.jsx +0 -305
  17. package/src/components/BaseFieldConfig.module.css +0 -42
  18. package/src/components/CenteredContainer.jsx +0 -29
  19. package/src/components/CenteredContainer.module.css +0 -171
  20. package/src/components/DeleteConfirmationPopup.jsx +0 -95
  21. package/src/components/DeleteConfirmationPopup.module.css +0 -12
  22. package/src/components/ErrorBoundary.jsx +0 -134
  23. package/src/components/ErrorBoundary.module.css +0 -77
  24. package/src/components/ErrorMessage.jsx +0 -85
  25. package/src/components/ErrorMessage.module.css +0 -116
  26. package/src/components/ExampleDisplay.jsx +0 -26
  27. package/src/components/ExampleDisplay.module.css +0 -3
  28. package/src/components/FeatureBuilderSidebar.jsx +0 -84
  29. package/src/components/FeatureBuilderSuccessPopup.jsx +0 -49
  30. package/src/components/FeatureBuilderSuccessPopup.module.css +0 -41
  31. package/src/components/FeatureBuilderWelcomePopup.jsx +0 -51
  32. package/src/components/FeatureBuilderWelcomePopup.module.css +0 -21
  33. package/src/components/FeatureListingCard.jsx +0 -104
  34. package/src/components/FeatureListingCard.module.css +0 -62
  35. package/src/components/Fields.jsx +0 -423
  36. package/src/components/Fields.module.css +0 -159
  37. package/src/components/IconLoader.jsx +0 -153
  38. package/src/components/IconLoader.module.css +0 -92
  39. package/src/components/IconSelector.jsx +0 -111
  40. package/src/components/IconSelector.module.css +0 -197
  41. package/src/components/ListingEditor.jsx +0 -405
  42. package/src/components/ListingEditor.module.css +0 -14
  43. package/src/components/ListingSuccessPopup.jsx +0 -52
  44. package/src/components/LoadingScreen.jsx +0 -54
  45. package/src/components/LoadingScreen.module.css +0 -103
  46. package/src/components/LoadingState.jsx +0 -40
  47. package/src/components/LoadingState.module.css +0 -18
  48. package/src/components/PreviewFull.js +0 -24
  49. package/src/components/PreviewFull.module.css +0 -11
  50. package/src/components/PreviewGrid.js +0 -14
  51. package/src/components/PreviewWidget.js +0 -27
  52. package/src/components/PreviewWidget.module.css +0 -15
  53. package/src/components/SidebarLayout.jsx +0 -252
  54. package/src/components/SidebarLayout.module.css +0 -71
  55. package/src/components/SkeletonLoader.jsx +0 -128
  56. package/src/components/SkeletonLoader.module.css +0 -295
  57. package/src/components/SortButtonGroup.jsx +0 -34
  58. package/src/components/SortButtonGroup.module.css +0 -51
  59. package/src/components/ToastContainer.jsx +0 -98
  60. package/src/components/ToastContainer.module.css +0 -156
  61. package/src/components/ToggleSwitch.js +0 -40
  62. package/src/components/ToggleSwitch.module.css +0 -48
  63. package/src/components/TwoColumnInput.jsx +0 -29
  64. package/src/components/TwoColumnInput.module.css +0 -32
  65. package/src/components/ViewFull.js +0 -139
  66. package/src/components/ViewFull.module.css +0 -71
  67. package/src/components/ViewWidget.js +0 -62
  68. package/src/components/ViewWidget.module.css +0 -28
  69. package/src/components/iconCategories.js +0 -135
  70. package/src/components/iconImports.js +0 -409
  71. package/src/components/index.js +0 -59
  72. package/src/components/listing/FileListItem.jsx +0 -86
  73. package/src/components/listing/GalleryDisplay.jsx +0 -330
  74. package/src/components/listing/GalleryDisplay.module.css +0 -309
  75. package/src/components/listing/ListingCTAInput.jsx +0 -82
  76. package/src/components/listing/ListingDescriptionInput.jsx +0 -73
  77. package/src/components/listing/ListingField.jsx +0 -101
  78. package/src/components/listing/ListingField.module.css +0 -106
  79. package/src/components/listing/ListingFileInput.jsx +0 -273
  80. package/src/components/listing/ListingFileInput.module.css +0 -189
  81. package/src/components/listing/ListingForm.jsx +0 -90
  82. package/src/components/listing/ListingForm.module.css +0 -38
  83. package/src/components/listing/ListingGalleryInput.jsx +0 -239
  84. package/src/components/listing/ListingGalleryInput.module.css +0 -132
  85. package/src/components/listing/ListingImageInput.jsx +0 -153
  86. package/src/components/listing/ListingTextInput.jsx +0 -72
  87. package/src/feature.config.js +0 -130
  88. package/src/helper/index.js +0 -135
  89. package/src/hooks/useFeatureDefinitionLoader.js +0 -66
  90. package/src/images/full.png +0 -0
  91. package/src/images/fullNoTitle.png +0 -0
  92. package/src/images/previewWidget.png +0 -0
  93. package/src/images/widget.png +0 -0
  94. package/src/index.js +0 -38
  95. package/src/pages/CreateListingPage.jsx +0 -49
  96. package/src/pages/EditListingPage.jsx +0 -58
  97. package/src/reducers/featureBuilderReducer.js +0 -739
  98. package/src/screens/CreateListing.module.css +0 -45
  99. package/src/screens/Form.module.css +0 -744
  100. package/src/screens/FormFieldsStep.jsx +0 -626
  101. package/src/screens/FormLayoutStep.jsx +0 -405
  102. package/src/screens/FormOverviewStep.jsx +0 -389
  103. package/src/screens/ListingScreen.jsx +0 -477
  104. package/src/screens/ListingScreen.module.css +0 -333
  105. package/src/selectors/featureBuilderSelectors.js +0 -533
  106. package/src/types/index.js +0 -91
  107. package/src/utils/textUtils.js +0 -89
  108. package/src/validators/galleryValidators.js +0 -345
  109. package/src/values.config.a.js +0 -49
  110. package/src/values.config.b.js +0 -49
  111. package/src/values.config.c.js +0 -49
  112. package/src/values.config.d.js +0 -49
  113. package/src/values.config.default.js +0 -49
  114. package/src/values.config.js +0 -49
  115. package/src/webapi/featureDefinitionActions.js +0 -0
  116. package/src/webapi/featuresActions.js +0 -90
  117. package/src/webapi/helper.js +0 -4
  118. package/src/webapi/index.js +0 -12
  119. package/src/webapi/listingActions.js +0 -176
@@ -1,228 +0,0 @@
1
- import {
2
- selectFormTitle,
3
- selectFormIcon,
4
- selectFormDisplayName,
5
- selectFormLayout,
6
- selectFormFields,
7
- } from "../selectors/featureBuilderSelectors";
8
-
9
- import { clearFormSubmissionState } from "./formActions";
10
-
11
- import { values } from "../values.config";
12
-
13
- // Wizard action types
14
- const REDUCER_PREFIX = values.reducerKey.toUpperCase();
15
- export const SET_WIZARD_MODE = `${REDUCER_PREFIX}_SET_WIZARD_MODE`;
16
- export const SET_NAVIGATION_STATE = `${REDUCER_PREFIX}_SET_NAVIGATION_STATE`;
17
- export const UPDATE_STEP_VALIDATION = `${REDUCER_PREFIX}_UPDATE_STEP_VALIDATION`;
18
- export const MARK_STEP_COMPLETE = `${REDUCER_PREFIX}_MARK_STEP_COMPLETE`;
19
- export const RESET_WIZARD_STATE = `${REDUCER_PREFIX}_RESET_WIZARD_STATE`;
20
- export const VALIDATE_AND_UPDATE_STEP = `${REDUCER_PREFIX}_VALIDATE_AND_UPDATE_STEP`;
21
-
22
- // Mode setters
23
- export const setWizardMode = (mode) => ({
24
- type: SET_WIZARD_MODE,
25
- payload: mode,
26
- });
27
-
28
- // Navigation actions
29
- export const setNavigationState = (navigationState) => ({
30
- type: SET_NAVIGATION_STATE,
31
- payload: navigationState,
32
- });
33
-
34
- export const setCurrentStep = (step, previousStep = null) => ({
35
- type: SET_NAVIGATION_STATE,
36
- payload: {
37
- currentStep: step,
38
- previousStep,
39
- canGoBack: step !== "welcome",
40
- canGoForward: true,
41
- },
42
- });
43
-
44
- export const goToStep = (step) => (dispatch, getState) => {
45
- const state = getState()[values.reducerKey];
46
- const currentStep = state?.wizard?.navigation?.currentStep;
47
-
48
- // Clear form submission state when changing steps
49
- dispatch(clearFormSubmissionState());
50
-
51
- dispatch(setCurrentStep(step, currentStep));
52
- };
53
-
54
- export const updateStepValidation = (step, isValid, errors = {}) => ({
55
- type: UPDATE_STEP_VALIDATION,
56
- payload: {
57
- step,
58
- isValid,
59
- errors,
60
- },
61
- });
62
-
63
- export const validateAndUpdateStep = (step) => (dispatch, getState) => {
64
- // Use existing selectors to get form data
65
- const state = getState();
66
- const title = selectFormTitle(state);
67
- const icon = selectFormIcon(state);
68
- const displayName = selectFormDisplayName(state);
69
- const layout = selectFormLayout(state);
70
- const fields = selectFormFields(state);
71
-
72
- const form = { title, icon, displayName, layout, fields };
73
-
74
- const { isValid, errors } = getFormValidation(form, step);
75
-
76
- dispatch(updateStepValidation(step, isValid, errors));
77
-
78
- // If valid, mark as complete
79
- if (isValid) {
80
- dispatch({
81
- type: MARK_STEP_COMPLETE,
82
- payload: step,
83
- });
84
- }
85
-
86
- return { isValid, errors };
87
- };
88
-
89
- // Step completion
90
- export const markStepComplete = (step) => ({
91
- type: MARK_STEP_COMPLETE,
92
- payload: step,
93
- });
94
-
95
- // Reset wizard state
96
- export const resetWizardState = () => ({
97
- type: RESET_WIZARD_STATE,
98
- });
99
-
100
- const getFormValidation = (form, step) => {
101
- // Return validation results for undefined form (prevent crashes)
102
- if (!form) {
103
- switch (step) {
104
- case "overview":
105
- return {
106
- isValid: false,
107
- errors: {
108
- title: "Title is required",
109
- displayName: "Display name is required",
110
- icon: "Icon is required",
111
- },
112
- };
113
- case "fields":
114
- return {
115
- isValid: false,
116
- errors: {
117
- missingTitle: "Title field is required",
118
- missingImage: "Feature image field is required",
119
- fieldLabels: "Some fields are missing labels",
120
- },
121
- };
122
- case "layout":
123
- return {
124
- isValid: false,
125
- errors: {
126
- layoutType: "Layout type is required",
127
- },
128
- };
129
- default:
130
- return { isValid: false, errors: {} };
131
- }
132
- }
133
-
134
- switch (step) {
135
- case "overview": {
136
- const hasTitle = form.title?.trim().length > 0;
137
- const hasDisplayName = form.displayName?.trim().length > 0;
138
- const hasIcon = form.icon?.length > 0;
139
-
140
- return {
141
- isValid: hasTitle && hasDisplayName && hasIcon,
142
- errors: {
143
- title: !hasTitle ? "Title is required" : null,
144
- displayName: !hasDisplayName ? "Display name is required" : null,
145
- icon: !hasIcon ? "Icon is required" : null,
146
- },
147
- };
148
- }
149
- case "fields": {
150
- const hasTitleField = form.fields?.some(
151
- (field) => field.id === "mandatory-title",
152
- );
153
- const hasImageField = form.fields?.some(
154
- (field) => field.id === "mandatory-feature-image",
155
- );
156
-
157
- // Check each field for missing labels and create field-specific errors
158
- const fieldErrors = {};
159
- let allFieldsHaveLabels = true;
160
-
161
- if (form.fields) {
162
- form.fields.forEach((field) => {
163
- if (
164
- (field.type === "text" ||
165
- field.type === "description" ||
166
- field.type === "title" ||
167
- field.type === "image" ||
168
- field.type === "gallery" ||
169
- field.type === "feature-image" ||
170
- field.type === "file" ||
171
- field.type === "cta") &&
172
- field.values
173
- ) {
174
- if (!field.values.label || field.values.label.trim().length === 0) {
175
- fieldErrors[field.id] = "Field label is required";
176
- allFieldsHaveLabels = false;
177
- }
178
- }
179
- });
180
- }
181
-
182
- return {
183
- isValid: hasTitleField && hasImageField && allFieldsHaveLabels,
184
- errors: {
185
- missingTitle: !hasTitleField ? "Title field is required" : null,
186
- missingImage: !hasImageField
187
- ? "Feature image field is required"
188
- : null,
189
- ...fieldErrors,
190
- },
191
- };
192
- }
193
- case "layout": {
194
- const hasLayoutType = form.layout?.type?.length > 0;
195
- return {
196
- isValid: hasLayoutType,
197
- errors: {
198
- layoutType: !hasLayoutType ? "Layout type is required" : null,
199
- },
200
- };
201
- }
202
- default:
203
- return { isValid: true, errors: {} };
204
- }
205
- };
206
-
207
- export const setWizardModeAndSave = (mode) => (dispatch) => {
208
- dispatch(setWizardMode(mode));
209
- };
210
-
211
- export const setCurrentStepAndSave =
212
- (step, previousStep = null) =>
213
- (dispatch) => {
214
- dispatch(setCurrentStep(step, previousStep));
215
- };
216
-
217
- export const updateStepValidationAndSave =
218
- (step, isValid, errors = {}) =>
219
- (dispatch) => {
220
- dispatch(updateStepValidation(step, isValid, errors));
221
- if (isValid) {
222
- dispatch(markStepComplete(step));
223
- }
224
- };
225
-
226
- export const markStepCompleteAndSave = (step) => (dispatch) => {
227
- dispatch(markStepComplete(step));
228
- };
@@ -1,86 +0,0 @@
1
- import React from "react";
2
- import { Button } from "../components";
3
- import { PlussCore } from "../feature.config";
4
- const { Text } = PlussCore.Components;
5
- import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
6
- import { faUserCircle, faClock } from "@fortawesome/free-solid-svg-icons";
7
- import { capitalizeTextWithFallback } from "../utils/textUtils";
8
- import styles from "./ActivityCardExample.module.css";
9
-
10
- const ActivityCardExample = ({ displayName }) => {
11
- // Handle "a/an" grammar correctly
12
- const getArticle = (name) => {
13
- if (!name) return "a";
14
- const firstChar = name.toLowerCase().charAt(0);
15
- // Handle vowel sounds and special cases
16
- return ["a", "e", "i", "o", "u"].includes(firstChar) ? "an" : "a";
17
- };
18
-
19
- // Handle button click - show that it's a display-only button
20
- const handleButtonClick = () => {
21
- alert(
22
- "This is just a preview of how your button will look. In the actual application, this button would create a new " +
23
- (displayName || "item") +
24
- ".",
25
- );
26
- };
27
-
28
- const exampleTitle = displayName
29
- ? `${capitalizeTextWithFallback(displayName, "")} Example`
30
- : "Example Item";
31
-
32
- return (
33
- <div className={styles.activityCardExample}>
34
- <Text type="formLabel" className={styles.title}>
35
- Activity Feed Example
36
- </Text>
37
-
38
- {/* Additional info */}
39
- <div className={styles.additionalInfo}>
40
- <Text type="help" className={styles.infoText}>
41
- This shows how your single page name will appear in real activity
42
- feeds and on buttons throughout the application.
43
- </Text>
44
- </div>
45
-
46
- <div className={styles.activityCard}>
47
- {/* User Avatar */}
48
- <div className={styles.profilePic}>
49
- <FontAwesomeIcon icon={faUserCircle} className={styles.avatarIcon} />
50
- </div>
51
-
52
- {/* Activity Content */}
53
- <div className={styles.activityContent}>
54
- <div className={styles.activityText}>
55
- <span className={styles.highlightedUser}>John Smith</span>
56
- &nbsp;commented on {getArticle(displayName)}&nbsp;
57
- <span className={styles.highlightedFeature}>
58
- {capitalizeTextWithFallback(displayName, "item")}
59
- </span>
60
- :&nbsp;
61
- <span className={styles.exampleTitle}>{exampleTitle}</span>
62
- </div>
63
-
64
- <div className={styles.activityTime}>
65
- <FontAwesomeIcon icon={faClock} className={styles.timeIcon} /> 2
66
- minutes ago
67
- </div>
68
- </div>
69
- </div>
70
-
71
- {/* Primary Add Button */}
72
- <div className={styles.buttonContainer}>
73
- <Button
74
- buttonType="primary"
75
- leftIcon="plus"
76
- isActive
77
- onClick={handleButtonClick}
78
- >
79
- New {capitalizeTextWithFallback(displayName, "Item")}
80
- </Button>
81
- </div>
82
- </div>
83
- );
84
- };
85
-
86
- export default ActivityCardExample;
@@ -1,130 +0,0 @@
1
- /* Activity Card Example Component Styles */
2
- .activityCardExample {
3
- margin-top: 16px;
4
- margin-bottom: 24px;
5
- }
6
-
7
- .title {
8
- margin-bottom: 8px;
9
- font-weight: 600;
10
- color: var(--active-text);
11
- }
12
-
13
- .activityCard {
14
- display: flex;
15
- align-items: flex-start;
16
- gap: 12px;
17
- padding: 16px;
18
- background: var(--bg-white);
19
- border: 1px solid var(--linegrey);
20
- border-radius: 8px;
21
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
22
- transition: box-shadow 0.2s ease;
23
- margin-top: 12px;
24
- }
25
-
26
- .activityCard:hover {
27
- box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
28
- }
29
-
30
- /* Profile Picture */
31
- .profilePic {
32
- width: 34px;
33
- height: 34px;
34
- display: flex;
35
- align-items: center;
36
- justify-content: center;
37
- background: var(--bg-bluegrey);
38
- border-radius: 50%;
39
- flex-shrink: 0;
40
- }
41
-
42
- .avatarIcon {
43
- font-size: 20px;
44
- color: var(--text-light);
45
- }
46
-
47
- /* Activity Content */
48
- .activityContent {
49
- flex: 1;
50
- min-width: 0;
51
- }
52
-
53
- .activityText {
54
- font-size: 14px;
55
- line-height: 1.4;
56
- color: var(--active-text);
57
- margin-bottom: 4px;
58
- word-wrap: break-word;
59
- }
60
-
61
- .highlightedUser {
62
- font-weight: 600;
63
- color: var(--colour-blue);
64
- }
65
-
66
- .highlightedFeature {
67
- font-weight: 600;
68
- color: var(--colour-blue);
69
- }
70
-
71
- .exampleTitle {
72
- color: var(--text-mid);
73
- font-style: italic;
74
- }
75
-
76
- /* Activity Time */
77
- .activityTime {
78
- display: flex;
79
- align-items: center;
80
- gap: 4px;
81
- font-size: 12px;
82
- color: var(--text-light);
83
- }
84
-
85
- .timeIcon {
86
- font-size: 10px;
87
- color: var(--text-light);
88
- }
89
-
90
- /* Additional Info */
91
- .additionalInfo {
92
- margin-bottom: 8px;
93
- }
94
-
95
- .infoText {
96
- font-size: 11px;
97
- color: var(--text-light);
98
- line-height: 1.3;
99
- }
100
-
101
- /* Primary Add Button */
102
- .buttonContainer {
103
- margin-top: 20px;
104
- display: flex;
105
- justify-content: flex-start;
106
- }
107
-
108
- /* Responsive design */
109
- @media (max-width: 768px) {
110
- .activityCard {
111
- padding: 12px;
112
- }
113
-
114
- .profilePic {
115
- width: 30px;
116
- height: 30px;
117
- }
118
-
119
- .avatarIcon {
120
- font-size: 18px;
121
- }
122
-
123
- .activityText {
124
- font-size: 13px;
125
- }
126
-
127
- .activityTime {
128
- font-size: 11px;
129
- }
130
- }
@@ -1,33 +0,0 @@
1
- import React from "react";
2
- import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
3
- import { faSync } from "@fortawesome/free-solid-svg-icons";
4
- import styles from "./BackgroundLoader.module.css";
5
-
6
- /**
7
- * Background Loader component for overlay loading states
8
- * Displays a spinning icon with text overlay for async operations
9
- * Conditionally renders based on show prop
10
- *
11
- * @param {Object} props - Component props
12
- * @param {string} [props.text="Updating..."] - Text to display alongside spinner
13
- * @param {boolean} [props.show=true] - Whether the loader should be visible
14
- * @returns {React.ReactElement|null} Background loader overlay or null if hidden
15
- *
16
- * @example
17
- * <BackgroundLoader text="Saving data..." show={isLoading} />
18
- *
19
- * @example
20
- * <BackgroundLoader />
21
- */
22
- const BackgroundLoader = ({ text = "Updating...", show = true }) => {
23
- if (!show) return null;
24
-
25
- return (
26
- <div className={styles.backgroundLoader}>
27
- <FontAwesomeIcon icon={faSync} spin className={styles.icon} />
28
- <span className={styles.text}>{text}</span>
29
- </div>
30
- );
31
- };
32
-
33
- export default BackgroundLoader;
@@ -1,46 +0,0 @@
1
- .backgroundLoader {
2
- display: flex;
3
- align-items: center;
4
- gap: 0.5rem;
5
- padding: 0.5rem 1rem;
6
- background: rgba(255, 255, 255, 0.95);
7
- border: 1px solid #e9ecef;
8
- border-radius: 20px;
9
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
10
- font-size: 0.875rem;
11
- color: var(--text-bluegrey, #6c7a90);
12
- position: fixed;
13
- top: 1rem;
14
- right: 1rem;
15
- z-index: 1000;
16
- animation: slideIn 0.3s ease-out;
17
- }
18
-
19
- .icon {
20
- color: var(--colour-branding-main, #4a57b7);
21
- font-size: 0.875rem;
22
- }
23
-
24
- .text {
25
- font-weight: 500;
26
- }
27
-
28
- @keyframes slideIn {
29
- from {
30
- opacity: 0;
31
- transform: translateX(20px);
32
- }
33
- to {
34
- opacity: 1;
35
- transform: translateX(0);
36
- }
37
- }
38
-
39
- @media (max-width: 768px) {
40
- .backgroundLoader {
41
- top: auto;
42
- bottom: 1rem;
43
- right: 1rem;
44
- font-size: 0.75rem;
45
- }
46
- }