@akinon/pz-basket-gift-pack 2.0.0-beta.8 → 2.0.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 (4) hide show
  1. package/CHANGELOG.md +124 -15
  2. package/README.md +140 -0
  3. package/package.json +9 -9
  4. package/src/index.tsx +175 -160
package/CHANGELOG.md CHANGED
@@ -1,39 +1,148 @@
1
1
  # @akinon/pz-basket-gift-pack
2
2
 
3
- ## 2.0.0-beta.8
3
+ ## 2.0.0
4
4
 
5
- ## 2.0.0-beta.7
5
+ ## 2.0.0-beta.27
6
6
 
7
- ## 2.0.0-beta.6
7
+ ## 2.0.0-beta.26
8
+
9
+ ## 2.0.0-beta.25
10
+
11
+ ## 2.0.0-beta.24
12
+
13
+ ## 2.0.0-beta.23
14
+
15
+ ## 2.0.0-beta.22
16
+
17
+ ## 2.0.0-beta.21
18
+
19
+ ## 2.0.0-beta.20
20
+
21
+ ## 1.126.0
22
+
23
+ ## 1.125.2
24
+
25
+ ## 1.125.1
26
+
27
+ ## 1.125.0
28
+
29
+ ## 1.124.0
30
+
31
+ ## 1.123.0
32
+
33
+ ## 1.122.0
34
+
35
+ ## 1.121.0
36
+
37
+ ## 1.120.0
38
+
39
+ ## 1.119.0
40
+
41
+ ## 1.118.0
42
+
43
+ ## 1.117.0
44
+
45
+ ## 1.116.0
46
+
47
+ ## 1.115.0
48
+
49
+ ## 1.114.0
50
+
51
+ ## 1.113.0
52
+
53
+ ## 1.112.0
54
+
55
+ ## 1.111.0
56
+
57
+ ## 1.110.0
58
+
59
+ ## 1.109.0
60
+
61
+ ## 1.108.0
62
+
63
+ ## 1.107.0
8
64
 
9
65
  ### Minor Changes
10
66
 
11
- - 8f05f9b: ZERO-3250: Beta branch synchronized with Main branch
67
+ - 72bfcbf2: ZERO-3347: Manage save button disable status
12
68
 
13
- ## 2.0.0-beta.5
69
+ ## 1.106.0
14
70
 
15
- ## 2.0.0-beta.4
71
+ ## 1.105.0
16
72
 
17
- ## 2.0.0-beta.3
73
+ ## 1.104.0
18
74
 
19
- ## 2.0.0-beta.2
75
+ ### Minor Changes
76
+
77
+ - 2ba89b3: ZERO-3361: Refactor basket gift pack component
78
+
79
+ ## 1.103.0
80
+
81
+ ## 1.102.0
82
+
83
+ ## 1.101.0
84
+
85
+ ## 1.100.0
86
+
87
+ ## 1.99.0
88
+
89
+ ### Minor Changes
90
+
91
+ - d58538b: ZERO-3638: Enhance RC pipeline: add fetch, merge, and pre-release setup with conditional commit
92
+
93
+ ## 1.98.0
94
+
95
+ ## 1.97.0
96
+
97
+ ## 1.96.0
98
+
99
+ ## 1.95.0
100
+
101
+ ## 1.94.0
102
+
103
+ ## 1.93.0
104
+
105
+ ## 1.92.0
106
+
107
+ ## 1.91.0
108
+
109
+ ## 1.90.0
110
+
111
+ ## 1.89.0
112
+
113
+ ## 1.88.0
20
114
 
21
115
  ### Minor Changes
22
116
 
23
- - a006015: ZERO-3116: Add not-found page and update default middleware.
24
- - 1eeb3d8: ZERO-3116: Add not found page
117
+ - 3037704: ZERO-3328: Add data-testid attributes for improved testing in BasketItem and BasketGiftPack components
118
+
119
+ ## 1.87.0
25
120
 
26
- ## 2.0.0-beta.1
121
+ ## 1.86.0
122
+
123
+ ## 1.85.0
124
+
125
+ ## 1.84.0
27
126
 
28
127
  ### Minor Changes
29
128
 
30
- - ZERO-3091: Upgrade Next.js to v15 and React to v19
129
+ - 624a4eb: ZERO-3276: Update installation instructions across multiple README files to standardize format and improve clarity
130
+
131
+ ## 1.83.0
132
+
133
+ ## 1.82.0
134
+
135
+ ## 1.81.0
136
+
137
+ ## 1.80.0
138
+
139
+ ## 1.79.0
31
140
 
32
- ## 2.0.0-beta.0
141
+ ## 1.78.0
33
142
 
34
- ### Major Changes
143
+ ## 1.77.0
35
144
 
36
- - be6c09d: ZERO-3114: Create beta version.
145
+ ## 1.76.0
37
146
 
38
147
  ## 1.75.0
39
148
 
package/README.md CHANGED
@@ -19,3 +19,143 @@ npx @akinon/projectzero@latest --plugins
19
19
  | modalClassName | `string` | This prop is used to customize the overall style of the modal. |
20
20
  | modalTitle | `string` | This prop sets the title of the modal. |
21
21
  | modalContentClassName | `string` | This prop is used to customize the style of the modal content. |
22
+ | customUIRender | `React.ReactNode` | Optional function to fully customize the gift pack rendering. Receives hasGiftPack, hasNote, note, textAreaCount, onAddGiftPack, onRemoveGiftPack, onAddNote, onRemoveNote, formContent and translations props. |
23
+ | customGiftNoteFormUIRender | `React.ReactNode` | Optional function to fully customize the form rendering. Receives register, errors, note, textAreaCount, onSubmit, removeNote and handleSubmit props. |
24
+
25
+ ### Customizing Gift Pack
26
+
27
+ ```javascript
28
+ import PluginModule, { Component } from '@akinon/next/components/plugin-module';
29
+
30
+ <PluginModule
31
+ component={Component.BasketGiftPack}
32
+ props={{
33
+ basketItem,
34
+ customUIRender: ({
35
+ hasGiftPack,
36
+ hasNote,
37
+ onAddGiftPack,
38
+ onRemoveGiftPack,
39
+ onAddNote,
40
+ formContent,
41
+ translations
42
+ }) => (
43
+ <>
44
+ <div className="flex gap-4">
45
+ <div className="flex items-center gap-2">
46
+ <Icon
47
+ name="giftbox"
48
+ size={15}
49
+ className={clsx(
50
+ hasGiftPack ? 'text-[#e85150]' : 'text-[#000000]'
51
+ )}
52
+ />
53
+ {hasGiftPack ? (
54
+ <span className="text-[0.75rem]">
55
+ {translations.giftPackAdded}
56
+ </span>
57
+ ) : (
58
+ <Button
59
+ appearance="ghost"
60
+ className="text-[#000000] cursor-pointer underline border-0 px-0 py-0 text-[0.75rem] h-auto hover:bg-transparent hover:text-[#000000]"
61
+ onClick={onAddGiftPack}
62
+ data-testid="add-basket-gift-pack"
63
+ >
64
+ {translations.addGiftPack}
65
+ </Button>
66
+ )}
67
+ </div>
68
+
69
+ {hasGiftPack && (
70
+ <>
71
+ <Button
72
+ appearance="ghost"
73
+ className="text-[#000000] cursor-pointer border-0 px-0 py-0 text-[0.75rem] select-none underline h-auto hover:bg-transparent hover:text-[#000000]"
74
+ onClick={onAddNote}
75
+ data-testid="add-basket-gift-pack-note"
76
+ >
77
+ {hasNote.title}
78
+ </Button>
79
+ <Button
80
+ appearance="ghost"
81
+ className={clsx(
82
+ 'text-[#000000] cursor-pointer border-0 px-0 py-0 text-[0.75rem] underline h-auto hover:bg-transparent hover:text-[#000000]',
83
+ {
84
+ hidden: !hasGiftPack
85
+ }
86
+ )}
87
+ onClick={onRemoveGiftPack}
88
+ data-testid="remove-basket-gift-pack"
89
+ >
90
+ {translations.removeGiftPack}
91
+ </Button>
92
+ </>
93
+ )}
94
+ </div>
95
+
96
+ <div className="w-full">
97
+ {hasNote.state ? <div className="mt-4">{formContent}</div> : null}
98
+ </div>
99
+ </>
100
+ )
101
+ }}
102
+ />;
103
+ ```
104
+
105
+ ### Customizing Gift Note Form
106
+
107
+ ```javascript
108
+ import PluginModule, { Component } from '@akinon/next/components/plugin-module';
109
+
110
+ <PluginModule
111
+ component={Component.BasketGiftPack}
112
+ props={{
113
+ basketItem,
114
+ customGiftNoteFormUIRender: ({
115
+ register,
116
+ errors,
117
+ note,
118
+ textAreaCount,
119
+ onSubmit,
120
+ removeNote,
121
+ handleSubmit
122
+ }) => (
123
+ <div className="bg-gray-100 p-4 rounded-md shadow-lg">
124
+ <h4 className="text-lg font-semibold mb-2">🎁 Add Your Note</h4>
125
+ <form onSubmit={handleSubmit(onSubmit)}>
126
+ <textarea
127
+ className="w-full border border-gray-300 p-2"
128
+ {...register('message')}
129
+ placeholder="Mesajını yaz..."
130
+ rows={5}
131
+ value={note}
132
+ />
133
+ {errors.message && (
134
+ <p className="text-red-500 text-sm">{errors.message.message}</p>
135
+ )}
136
+ <div className="flex justify-between items-center mt-2">
137
+ <span className="text-sm text-gray-500">
138
+ {textAreaCount}/ 160 characters
139
+ </span>
140
+ <div className="flex gap-2">
141
+ <button
142
+ type="button"
143
+ onClick={removeNote}
144
+ className="text-sm underline"
145
+ >
146
+ Delete Note
147
+ </button>
148
+ <button
149
+ type="submit"
150
+ className="bg-black text-white px-3 py-1 text-sm rounded"
151
+ >
152
+ Save
153
+ </button>
154
+ </div>
155
+ </div>
156
+ </form>
157
+ </div>
158
+ )
159
+ }}
160
+ />;
161
+ ```
package/package.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "@akinon/pz-basket-gift-pack",
3
- "version": "2.0.0-beta.8",
3
+ "version": "2.0.0",
4
4
  "license": "MIT",
5
5
  "main": "src/index.tsx",
6
6
  "peerDependencies": {
7
- "react": "^19.0.0",
8
- "react-dom": "^19.0.0"
7
+ "react": "^18.0.0 || ^19.0.0",
8
+ "react-dom": "^18.0.0 || ^19.0.0"
9
9
  },
10
10
  "devDependencies": {
11
- "@types/node": "^22.10.2",
12
- "@types/react": "^19.0.2",
13
- "@types/react-dom": "^19.0.2",
14
- "react": "^19.0.0",
15
- "react-dom": "^19.0.0",
16
- "typescript": "^5.7.2"
11
+ "@types/node": "^18.7.8",
12
+ "@types/react": "^18.0.17",
13
+ "@types/react-dom": "^18.0.6",
14
+ "react": "19.2.5",
15
+ "react-dom": "19.2.5",
16
+ "typescript": "^4.7.4"
17
17
  }
18
18
  }
package/src/index.tsx CHANGED
@@ -4,38 +4,69 @@ import {
4
4
  } from './endpoints';
5
5
  import clsx from 'clsx';
6
6
  import { twMerge } from 'tailwind-merge';
7
- import { useForm, SubmitHandler } from 'react-hook-form';
7
+ import {
8
+ useForm,
9
+ SubmitHandler,
10
+ UseFormRegister,
11
+ FieldErrors,
12
+ UseFormHandleSubmit
13
+ } from 'react-hook-form';
8
14
  import { yupResolver } from '@hookform/resolvers/yup';
9
15
  import * as yup from 'yup';
10
16
  import { useEffect, useState } from 'react';
11
17
  import { Button, Icon, Modal } from '@akinon/next/components';
12
18
  import { BasketItem as BasketItemType } from '@akinon/next/types';
13
19
 
20
+ const defaultTranslations = {
21
+ placeholderInput:
22
+ 'You can leave this area empty. However it will be a gift package without note.',
23
+ warningMessage: 'Ensure this field has no more than 160 characters.',
24
+ addNote: 'Add Note',
25
+ addGiftNote: 'Add Gift Note',
26
+ changeNote: 'Change Note',
27
+ giftPackAdded: 'Gift Pack Added',
28
+ addGiftPack: 'Add Gift Pack',
29
+ removeGiftPack: 'Remove Gift Pack',
30
+ charactersLength: 'characters left',
31
+ removeNote: 'Remove Note',
32
+ save: 'SAVE',
33
+ saving: 'SAVING...',
34
+ close: 'Close'
35
+ };
36
+
14
37
  interface GiftPackForm {
15
38
  message: string;
16
39
  }
17
-
40
+ interface CustomRenderParams {
41
+ hasGiftPack: boolean;
42
+ hasNote: { title: string; state: boolean };
43
+ note: string;
44
+ textAreaCount: number;
45
+ onAddGiftPack: () => void;
46
+ onRemoveGiftPack: () => void;
47
+ onAddNote: () => void;
48
+ onRemoveNote: () => void;
49
+ formContent: React.ReactNode;
50
+ translations: typeof defaultTranslations;
51
+ }
18
52
  interface Props {
19
53
  basketItem: BasketItemType;
20
54
  useModal?: boolean;
21
55
  modalTitle?: string;
22
56
  modalClassName?: string;
23
57
  modalContentClassName?: string;
24
- translations?: {
25
- placeholderInput?: string;
26
- warningMessage?: string;
27
- addNote?: string;
28
- addGiftNote?: string;
29
- changeNote?: string;
30
- giftPackAdded?: string;
31
- addGiftPack?: string;
32
- removeGiftPack?: string;
33
- charactersLength?: string;
34
- removeNote?: string;
35
- save?: string;
36
- close?: string;
37
- };
58
+ translations?: Partial<typeof defaultTranslations>;
38
59
  className?: string;
60
+ customUIRender?: (params: CustomRenderParams) => React.ReactNode;
61
+ customGiftNoteFormUIRender?: (params: {
62
+ register: UseFormRegister<GiftPackForm>;
63
+ errors: FieldErrors<GiftPackForm>;
64
+ note: string;
65
+ textAreaCount: number;
66
+ onSubmit: () => void;
67
+ removeNote: () => void;
68
+ handleSubmit: UseFormHandleSubmit<GiftPackForm>;
69
+ }) => React.ReactNode;
39
70
  }
40
71
 
41
72
  export const BasketGiftPack = ({
@@ -45,30 +76,13 @@ export const BasketGiftPack = ({
45
76
  useModal = false,
46
77
  modalTitle = 'Gift Note',
47
78
  modalClassName,
48
- modalContentClassName
79
+ modalContentClassName,
80
+ customUIRender,
81
+ customGiftNoteFormUIRender
49
82
  }: Props) => {
50
- const defaultTranslations = {
51
- placeholderInput:
52
- 'You can leave this area empty. However it will be a gift package without note.',
53
- warningMessage: 'Ensure this field has no more than 160 characters.',
54
- addNote: 'Add Note',
55
- addGiftNote: 'Add Gift Note',
56
- changeNote: 'Change Note',
57
- giftPackAdded: 'Gift Pack Added',
58
- addGiftPack: 'Add Gift Pack',
59
- removeGiftPack: 'Remove Gift Pack',
60
- charactersLength: 'characters left',
61
- removeNote: 'Remove Note',
62
- save: 'SAVE',
63
- close: 'Close'
64
- };
65
-
66
- const _translations = {
67
- ...defaultTranslations,
68
- ...translations
69
- };
70
-
71
- const [addGiftPackage] = useAddGiftPackageMutation();
83
+ const _translations = { ...defaultTranslations, ...translations };
84
+ const [addGiftPackage, { isLoading: isAddingGiftPackage }] =
85
+ useAddGiftPackageMutation();
72
86
  const [removeGiftPackage] = useRemoveGiftPackageMutation();
73
87
  const [hasGiftPack, setHasGiftPack] = useState(false);
74
88
  const [hasNote, setHasNote] = useState({
@@ -79,10 +93,9 @@ export const BasketGiftPack = ({
79
93
  const [note, setNote] = useState('');
80
94
  const defaultMessage = 'NO-GIFT-NOTE';
81
95
 
82
- const giftPackFormSchema = () =>
83
- yup.object().shape({
84
- message: yup.string().max(160, _translations.warningMessage)
85
- });
96
+ const schema = yup.object().shape({
97
+ message: yup.string().max(160, _translations.warningMessage)
98
+ });
86
99
 
87
100
  const {
88
101
  register,
@@ -90,54 +103,83 @@ export const BasketGiftPack = ({
90
103
  handleSubmit,
91
104
  formState: { errors }
92
105
  } = useForm<GiftPackForm>({
93
- resolver: yupResolver(giftPackFormSchema())
106
+ resolver: yupResolver(schema) as any
94
107
  });
95
108
 
96
109
  const onSubmit: SubmitHandler<GiftPackForm> = async (data) => {
97
- addGiftPackage({ id: basketItem.id, message: data.message })
98
- .unwrap()
99
- .then(() => {
100
- setHasNote((prevstate) => ({ ...prevstate, state: false }));
101
- changeNoteTitle(data.message);
102
- });
110
+ await addGiftPackage({ id: basketItem.id, message: data.message }).unwrap();
111
+ setHasNote({ ...hasNote, state: false });
112
+ changeNoteTitle(data.message);
103
113
  };
104
114
 
105
- const addGiftPack = () => {
106
- addGiftPackage({ id: basketItem.id, message: defaultMessage })
107
- .unwrap()
108
- .then(() => {
109
- setHasGiftPack(true);
110
- setHasNote((prevstate) => ({ ...prevstate, state: false }));
111
- });
115
+ const addGiftPack = async () => {
116
+ await addGiftPackage({
117
+ id: basketItem.id,
118
+ message: defaultMessage
119
+ }).unwrap();
120
+ setHasGiftPack(true);
121
+ setHasNote({ ...hasNote, state: false });
112
122
  };
113
123
 
114
124
  const removeGiftPack = () => {
115
125
  removeGiftPackage({ id: basketItem.id });
116
126
  setHasGiftPack(false);
117
- setHasNote((prevstate) => ({ ...prevstate, state: false }));
127
+ setHasNote({ ...hasNote, state: false });
118
128
  };
119
129
 
120
130
  const removeNote = () => {
121
131
  addGiftPackage({ id: basketItem.id, message: defaultMessage });
122
- setHasNote((prevstate) => ({ ...prevstate, state: false }));
132
+ setHasNote({ ...hasNote, state: false });
123
133
  changeNoteTitle(defaultMessage);
124
134
  };
125
135
 
126
- const changeNoteTitle = (value) => {
127
- if (value !== defaultMessage) {
128
- setHasNote((prevstate) => ({
129
- ...prevstate,
130
- title: _translations.changeNote
131
- }));
132
- } else {
133
- setHasNote((prevstate) => ({
134
- ...prevstate,
135
- title: _translations.addNote
136
- }));
137
- }
136
+ const changeNoteTitle = (value: string) => {
137
+ const title =
138
+ value !== defaultMessage
139
+ ? _translations.changeNote
140
+ : _translations.addNote;
141
+ setHasNote((prev) => ({ ...prev, title }));
138
142
  };
139
143
 
140
- const formContent = (
144
+ useEffect(() => {
145
+ for (const [key, value] of Object.entries(basketItem.attributes)) {
146
+ if (value === '') {
147
+ setHasGiftPack(false);
148
+ setHasNote({ ...hasNote, state: false });
149
+ setNote('');
150
+ setTextAreaCount(0);
151
+ return;
152
+ }
153
+
154
+ if (key) {
155
+ changeNoteTitle(value);
156
+ setNote(value);
157
+ setHasGiftPack(true);
158
+ setTextAreaCount(value === defaultMessage ? 0 : value.length);
159
+ }
160
+ }
161
+ }, [basketItem.attributes]);
162
+
163
+ useEffect(() => {
164
+ const subscription = watch(({ message }) => {
165
+ setNote(message);
166
+ setTextAreaCount(message.length);
167
+ });
168
+
169
+ return () => subscription.unsubscribe();
170
+ }, [watch]);
171
+
172
+ const formContent = customGiftNoteFormUIRender ? (
173
+ customGiftNoteFormUIRender({
174
+ register,
175
+ errors,
176
+ note,
177
+ textAreaCount,
178
+ onSubmit: () => handleSubmit(onSubmit)(),
179
+ removeNote,
180
+ handleSubmit
181
+ })
182
+ ) : (
141
183
  <form onSubmit={handleSubmit(onSubmit)}>
142
184
  {!useModal && (
143
185
  <div className="flex justify-between mb-3">
@@ -149,7 +191,7 @@ export const BasketGiftPack = ({
149
191
  className="text-[#000000] cursor-pointer border-0 px-0 py-0 text-[0.75rem] select-none underline h-auto hover:bg-transparent hover:text-[#000000]"
150
192
  onClick={(e) => {
151
193
  e.preventDefault();
152
- setHasNote((prevstate) => ({ ...prevstate, state: false }));
194
+ setHasNote({ ...hasNote, state: false });
153
195
  }}
154
196
  >
155
197
  {_translations.close}
@@ -157,27 +199,26 @@ export const BasketGiftPack = ({
157
199
  </div>
158
200
  )}
159
201
  <textarea
160
- className="w-full border border-solid border-[#4a4f53] p-4 placeholder:text-[0.75rem] placeholder:text-[#c8c9c8] outline-hidden text-[0.75rem]"
202
+ className="w-full border border-[#4a4f53] p-4 text-[0.75rem] placeholder:text-[#c8c9c8]"
161
203
  rows={7}
162
- name="message"
163
- value={note !== defaultMessage ? note : ' '}
164
204
  placeholder={_translations.placeholderInput}
165
205
  {...register('message')}
206
+ value={note !== defaultMessage ? note : ''}
166
207
  data-testid="basket-gift-pack-note-input"
167
208
  />
168
209
  {errors.message && (
169
- <span className="text-sm text-[#d72a04]">{errors.message.message}</span>
210
+ <span className="text-sm text-[#d72a04]">{String(errors.message.message)}</span>
170
211
  )}
171
- <div className="flex justify-between items-center mt-2">
212
+ <div className="flex justify-between mt-2 items-center">
172
213
  <span
173
214
  className={clsx(
174
- 'text-[0.75rem] ',
215
+ 'text-[0.75rem]',
175
216
  textAreaCount > 160 ? 'text-[#e85150]' : 'text-[#82a27c]'
176
217
  )}
177
218
  >
178
219
  {textAreaCount}/160 {_translations.charactersLength}
179
220
  </span>
180
- <div className="flex items-center gap-3">
221
+ <div className="flex gap-3 items-center">
181
222
  <Button
182
223
  appearance="ghost"
183
224
  className="text-[#000000] cursor-pointer border-0 px-0 py-0 text-[0.75rem] select-none underline h-auto hover:bg-transparent hover:text-[#000000]"
@@ -190,53 +231,23 @@ export const BasketGiftPack = ({
190
231
  type="submit"
191
232
  className="w-28 h-7 font-medium uppercase"
192
233
  data-testid="basket-gift-pack-note-save-button"
234
+ disabled={
235
+ isAddingGiftPackage ||
236
+ textAreaCount === 0 ||
237
+ note.trim() === '' ||
238
+ note === defaultMessage
239
+ }
193
240
  >
194
- {_translations.save}
241
+ {isAddingGiftPackage ? _translations.saving : _translations.save}
195
242
  </Button>
196
243
  </div>
197
244
  </div>
198
245
  </form>
199
246
  );
200
247
 
201
- useEffect(() => {
202
- for (const [key, value] of Object.entries(basketItem.attributes)) {
203
- if (value === '') {
204
- setHasGiftPack(false);
205
- setHasNote((prevstate) => ({ ...prevstate, state: false }));
206
- setNote('');
207
- setTextAreaCount(0);
208
- return;
209
- }
210
-
211
- if (key) {
212
- changeNoteTitle(value);
213
- setNote(value);
214
- setHasGiftPack(true);
215
- setTextAreaCount(value?.length);
216
- }
217
- }
218
- }, [basketItem.attributes]);
219
-
220
- useEffect(() => {
221
- const subscription = watch(({ message }) => {
222
- setNote(message);
223
- setTextAreaCount(message.length);
224
- });
225
-
226
- return () => subscription.unsubscribe();
227
- }, [watch]);
228
-
229
- return (
248
+ const defaultRender = () => (
230
249
  <div
231
- className={twMerge(
232
- clsx(
233
- 'mt-4 sm:mt-0',
234
- {
235
- 'sm:mt-8': hasNote.state
236
- },
237
- className
238
- )
239
- )}
250
+ className={twMerge(clsx('mt-4', { 'md:mt-8': hasNote.state }, className))}
240
251
  >
241
252
  <div className="flex gap-4">
242
253
  <div className="flex items-center gap-2">
@@ -245,7 +256,6 @@ export const BasketGiftPack = ({
245
256
  size={15}
246
257
  className={clsx(hasGiftPack ? 'text-[#e85150]' : 'text-[#000000]')}
247
258
  />
248
-
249
259
  {hasGiftPack ? (
250
260
  <span className="text-[0.75rem]">
251
261
  {_translations.giftPackAdded}
@@ -261,36 +271,34 @@ export const BasketGiftPack = ({
261
271
  </Button>
262
272
  )}
263
273
  </div>
264
- <Button
265
- appearance="ghost"
266
- className={clsx(
267
- 'text-[#000000] underline cursor-pointer border-0 px-0 py-0 text-[0.75rem] h-auto hover:bg-transparent hover:text-[#000000]',
268
- {
269
- hidden: !hasGiftPack
270
- }
271
- )}
272
- onClick={() =>
273
- setHasNote((prevstate) => ({ ...prevstate, state: true }))
274
- }
275
- data-testid="add-basket-gift-pack-note"
276
- >
277
- {hasNote.title}
278
- </Button>
279
274
 
280
- <Button
281
- appearance="ghost"
282
- className={clsx(
283
- 'text-[#000000] cursor-pointer border-0 px-0 py-0 text-[0.75rem] underline h-auto hover:bg-transparent hover:text-[#000000]',
284
- {
285
- hidden: !hasGiftPack
286
- }
287
- )}
288
- onClick={removeGiftPack}
289
- data-testid="remove-basket-gift-pack"
290
- >
291
- {_translations.removeGiftPack}
292
- </Button>
275
+ {hasGiftPack && (
276
+ <>
277
+ <Button
278
+ appearance="ghost"
279
+ className="text-[#000000] cursor-pointer border-0 px-0 py-0 text-[0.75rem] select-none underline h-auto hover:bg-transparent hover:text-[#000000]"
280
+ onClick={() => setHasNote({ ...hasNote, state: true })}
281
+ data-testid="add-basket-gift-pack-note"
282
+ >
283
+ {hasNote.title}
284
+ </Button>
285
+ <Button
286
+ appearance="ghost"
287
+ className={clsx(
288
+ 'text-[#000000] cursor-pointer border-0 px-0 py-0 text-[0.75rem] underline h-auto hover:bg-transparent hover:text-[#000000]',
289
+ {
290
+ hidden: !hasGiftPack
291
+ }
292
+ )}
293
+ onClick={removeGiftPack}
294
+ data-testid="remove-basket-gift-pack"
295
+ >
296
+ {_translations.removeGiftPack}
297
+ </Button>
298
+ </>
299
+ )}
293
300
  </div>
301
+
294
302
  {useModal ? (
295
303
  <Modal
296
304
  portalId="basket-gift-pack-modal"
@@ -300,23 +308,30 @@ export const BasketGiftPack = ({
300
308
  modalClassName
301
309
  )}
302
310
  open={hasNote.state}
303
- setOpen={(state) =>
304
- setHasNote((prevstate) => ({ ...prevstate, state }))
305
- }
311
+ setOpen={(state) => setHasNote((prev) => ({ ...prev, state }))}
306
312
  >
307
313
  <div className={twMerge('px-6 py-4', modalContentClassName)}>
308
314
  {formContent}
309
315
  </div>
310
316
  </Modal>
311
- ) : (
312
- <div
313
- className={clsx('mt-4', {
314
- hidden: !hasNote.state
315
- })}
316
- >
317
- {formContent}
318
- </div>
319
- )}
317
+ ) : hasNote.state ? (
318
+ <div className="mt-4">{formContent}</div>
319
+ ) : null}
320
320
  </div>
321
321
  );
322
+
323
+ return customUIRender
324
+ ? customUIRender({
325
+ hasGiftPack,
326
+ hasNote,
327
+ note,
328
+ textAreaCount,
329
+ onAddGiftPack: addGiftPack,
330
+ onRemoveGiftPack: removeGiftPack,
331
+ onAddNote: () => setHasNote({ ...hasNote, state: true }),
332
+ onRemoveNote: removeNote,
333
+ formContent,
334
+ translations: _translations
335
+ })
336
+ : defaultRender();
322
337
  };