ekm-ui 0.4.39 → 0.4.41

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 (37) hide show
  1. package/.turbo/turbo-build.log +72 -67
  2. package/CHANGELOG.md +12 -0
  3. package/dist/accordion.d.ts +9 -8
  4. package/dist/accordion.js +1 -1
  5. package/dist/card-payment-block.js +10 -9
  6. package/dist/{chunk-QJOSZI6O.js → chunk-EY2UUYEC.js} +6 -6
  7. package/dist/{chunk-NQ5VRJLN.js → chunk-FPXEE5TC.js} +2 -2
  8. package/dist/chunk-JFL77JIP.js +14 -0
  9. package/dist/chunk-JFL77JIP.js.map +1 -0
  10. package/dist/chunk-QZFOPL3O.js +12 -0
  11. package/dist/chunk-QZFOPL3O.js.map +1 -0
  12. package/dist/{chunk-U4WMBFRC.js → chunk-R3QJRZTP.js} +2 -2
  13. package/dist/{chunk-U4WMBFRC.js.map → chunk-R3QJRZTP.js.map} +1 -1
  14. package/dist/country-picker/country-modal.js +10 -9
  15. package/dist/date-time-component.d.ts +23 -0
  16. package/dist/date-time-component.js +8 -0
  17. package/dist/date-time-component.js.map +1 -0
  18. package/dist/drag-and-drop.js +10 -9
  19. package/dist/file-picker/file-listing.js +2 -2
  20. package/dist/file-picker/file-picker.js +10 -9
  21. package/dist/index.d.ts +1 -0
  22. package/dist/index.js +10 -9
  23. package/dist/layout/layout.js +10 -9
  24. package/dist/product-picker/product-modal.js +10 -9
  25. package/dist/radio.js +1 -1
  26. package/dist/stacked-list-item.js +10 -9
  27. package/dist/table-result-block.js +10 -9
  28. package/package.json +1 -1
  29. package/src/accordion.tsx +21 -20
  30. package/src/date-time-component.tsx +257 -0
  31. package/src/helpers/datetime.js +90 -0
  32. package/src/index.tsx +2 -1
  33. package/src/radio.tsx +2 -2
  34. package/dist/chunk-YDCYBJPC.js +0 -12
  35. package/dist/chunk-YDCYBJPC.js.map +0 -1
  36. /package/dist/{chunk-QJOSZI6O.js.map → chunk-EY2UUYEC.js.map} +0 -0
  37. /package/dist/{chunk-NQ5VRJLN.js.map → chunk-FPXEE5TC.js.map} +0 -0
@@ -0,0 +1,257 @@
1
+ //@ts-nocheck
2
+ import { useState, useRef, useMemo, useEffect } from 'react'
3
+ import { HiOutlineCalendar } from 'react-icons/hi'
4
+ import { Button } from './button'
5
+ import { useForm, Controller } from 'react-hook-form'
6
+ import debounce from 'lodash/debounce'
7
+ import { variantProps } from 'classname-variants/react'
8
+ import { BiChevronDown } from 'react-icons/bi'
9
+ import PropTypes from 'prop-types'
10
+ import { GetDiscountDateTimeString } from './helpers/datetime'
11
+ import { STANDARD_CONTROL, FAILURE_CONTROL } from './helpers/colour'
12
+
13
+
14
+ const generateTimeOptions = () => {
15
+ const times = [];
16
+ for (let i = 0; i < 24; i++) {
17
+ for (let j = 0; j < 60; j += 15) {
18
+ const hour = (i % 12 || 12).toString().padStart(2, '0'); // Convert 0 to 12 for 12 AM/PM and pad with zero
19
+ const minute = j.toString().padStart(2, '0');
20
+ const period = i < 12 ? 'AM' : 'PM';
21
+ const time = `${hour}:${minute} ${period}`;
22
+ times.push(time);
23
+ }
24
+ }
25
+ return times;
26
+ };
27
+
28
+ export function DateTimeComponent({ id, dateValue, showError=false, callback }) {
29
+ const [showDropdown, setShowDropdown] = useState(false)
30
+ const timeOptions = generateTimeOptions();
31
+
32
+ const handleShowDropdown = () => {
33
+ setShowDropdown(true)
34
+ }
35
+
36
+ const ref = useRef(null)
37
+
38
+ useEffect(() => {
39
+ const handleClickOutside = (e) => {
40
+ if (ref.current && !ref.current.contains(e.target)) {
41
+ setShowDropdown(false)
42
+ }
43
+ }
44
+
45
+ document.addEventListener('click', handleClickOutside, true)
46
+ return () => {
47
+ document.removeEventListener('click', handleClickOutside, true)
48
+ }
49
+ }, [])
50
+
51
+ useEffect(() => {
52
+ if (dateValue && (dateValue instanceof Date)) {
53
+ setValue('date', dateValue.toISOString().split("T")[0])
54
+ const hours = dateValue.getHours()
55
+ const mins = dateValue.getMinutes()
56
+ const newHours = hours === 0 ? 12 : hours > 12 ? hours - 12 : hours
57
+ const suffix = hours < 12 ? 'AM' : 'PM'
58
+ const newTime = `${newHours.toString().padStart(2, '0')}:${mins.toString().padStart(2, '0')} ${suffix}`
59
+ setValue('time', newTime)
60
+ }
61
+ }, [dateValue])
62
+
63
+ const MinDate = useMemo(() => {
64
+ var d = new Date();
65
+ d.setDate(d.getDate() - 1);
66
+ return d;
67
+ }, [new Date().getDay()]);
68
+
69
+ const {
70
+ control,
71
+ reset,
72
+ handleSubmit,
73
+ watch,
74
+ setValue,
75
+ formState: { errors },
76
+ } = useForm({
77
+ defaultValues: {
78
+ date: MinDate.toISOString().split("T")[0],
79
+ time: "12:00 AM"
80
+ },
81
+ });
82
+
83
+ const [err, setErr] = useState(false);
84
+ const [dateErr, setDateErr] = useState(false);
85
+
86
+
87
+
88
+ const debouncedExport = useRef(
89
+ debounce((data) => {
90
+ exportRequest(data);
91
+ }, 500)
92
+ ).current;
93
+
94
+ const handleCancel = (e) => {
95
+ e.preventDefault();
96
+ setShowDropdown(false);
97
+ setDateErr(false);
98
+ };
99
+
100
+ const onSubmit = (data) => {
101
+ debouncedExport(data);
102
+ };
103
+
104
+ function convertToDate(date, time) {
105
+ time = time.trim();
106
+ const timeParts = time.match(/(\d+):(\d+)\s?(AM|PM)/i);
107
+ let hours = parseInt(timeParts[1], 10);
108
+ const minutes = parseInt(timeParts[2], 10);
109
+ const period = timeParts[3].toUpperCase();
110
+ if (period === "PM" && hours !== 12) {
111
+ hours += 12;
112
+ } else if (period === "AM" && hours === 12) {
113
+ hours = 0;
114
+ }
115
+ const [year, month, day] = date.split('-');
116
+ const dateObj = new Date(year, month - 1, day, hours, minutes, 0, 0);
117
+ return dateObj;
118
+ }
119
+
120
+ const exportRequest = (data) => {
121
+ if (data.emptyChk) {
122
+ setErr(true);
123
+ return;
124
+ }
125
+ const newDate = convertToDate(data.date, data.time);
126
+ callback(newDate);
127
+ setShowDropdown(false)
128
+ }
129
+
130
+ const onChanged = () => {
131
+ if (dateErr) setDateErr(false);
132
+ };
133
+
134
+ const renderContent = () => (
135
+ <div>
136
+ <>
137
+ <div className="grid grid-cols-2 pb-4">
138
+ <Controller
139
+ name="date"
140
+ control={control}
141
+ rules={{
142
+ required: "A date is required.",
143
+ validate: {
144
+ whitespace: (v) =>
145
+ (v?.toString().trim() || "").length > 0 ||
146
+ "A date is required.",
147
+ },
148
+ }}
149
+ render={({ field }) => (
150
+ <div className="w-full pr-1">
151
+ <label htmlFor="date">Date</label>
152
+ <input
153
+ type="date"
154
+ id="datePicker"
155
+ value={field.value}
156
+ name="date"
157
+ max={MinDate}
158
+ onChange={(e) => {
159
+ field.onChange(e);
160
+ onChanged();
161
+ }}
162
+ className={`mt-1 block w-full rounded-md border-gray-300 text-xs ${errors.date ? FAILURE_CONTROL : STANDARD_CONTROL}`}
163
+ />
164
+ </div>
165
+ )}
166
+ />
167
+ <Controller
168
+ name="time"
169
+ control={control}
170
+ rules={{
171
+ required: "A time is required.",
172
+ validate: {
173
+ whitespace: (v) =>
174
+ (v?.toString().trim() || "").length > 0 ||
175
+ "A time is required.",
176
+ },
177
+ }}
178
+ render={({ field }) => (
179
+ <div className="w-full pr-1">
180
+ <label htmlFor="time">Time</label>
181
+ <select id="time-select" onChange={(e) => {
182
+ field.onChange(e);
183
+ onChanged();
184
+ }}
185
+ className="mt-1 block w-full rounded-md border-gray-300 text-xs"
186
+ value={field.value}
187
+ >
188
+ {timeOptions.map((time) => (
189
+ <option key={`time-option-${time}`} value={time}>{time}</option>
190
+ ))}
191
+ </select>
192
+ </div>
193
+ )}
194
+ />
195
+ </div>
196
+ </>
197
+ {(errors.date || errors.time || dateErr) &&
198
+ <div className='pb-4 text-sm text-red-600 dark:text-red-500'>
199
+ {errors.date?.message || errors.time?.message || 'A valid date time is required.'}
200
+ </div>
201
+ }
202
+ <div className="flex justify-end gap-4">
203
+ <Button color="gray" size="sm" outline onClick={handleCancel}>
204
+ Cancel
205
+ </Button>
206
+ <Button color="default" size="sm" type="submit">
207
+ Apply
208
+ </Button>
209
+ </div>
210
+ </div>
211
+ );
212
+
213
+ return (
214
+ <div id={`${id}-panel`} className="relative">
215
+ <div className='relative'>
216
+ <input
217
+ id={`${id}-input`}
218
+ placeholder="11-Aug-2024 12:00 AM"
219
+ value={GetDiscountDateTimeString(dateValue, true)}
220
+ className={`block p-2.5 w-full text-sm border rounded-lg cursor-pointer ${showError ?
221
+ 'bg-red-50 border border-red-500 text-red-900 placeholder-red-700 text-sm focus:ring-red-500 dark:bg-gray-700 focus:border-red-500 dark:text-red-500 dark:placeholder-red-500 dark:border-red-500' :
222
+ 'text-gray-900 bg-gray-50 border-gray-300 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500'}`
223
+ }
224
+ onClick={handleShowDropdown}
225
+ readOnly
226
+ />
227
+ <HiOutlineCalendar className='absolute right-2 top-3 cursor-pointer' onClick={handleShowDropdown}/>
228
+ </div>
229
+ <div
230
+ id={`${id}-dropdown`}
231
+ ref={ref}
232
+ className={`z-50 w-full mt-2 absolute ${
233
+ showDropdown ? '' : 'hidden'
234
+ } left-0 bg-white divide-y divide-gray-100 rounded-lg shadow dark:bg-gray-700`}
235
+ >
236
+ <div className="py-2 text-sm text-gray-700 dark:text-gray-200" aria-labelledby="dropdownDefaultButton">
237
+ <form className="space-y-6 p-3" onSubmit={handleSubmit(onSubmit)}>
238
+ {showDropdown && renderContent()}
239
+ </form>
240
+ </div>
241
+ </div>
242
+ </div>
243
+ );
244
+ }
245
+
246
+ DateTimeComponent.propTypes = {
247
+ /** This is the unique Id for the DateTimePicker component */
248
+ id: PropTypes.string.isRequired,
249
+ /** Date object containing date to display in input control. Date should already be converted to local time */
250
+ dateValue: PropTypes.instanceOf(Date).isRequired,
251
+ /** This is an optional boolean option which changes the background colour of the input control to red */
252
+ showError: PropTypes.bool,
253
+ /** Callback function for the DateTimecomponent outputs the chosen date time in form of Date object*/
254
+ callback: PropTypes.func.isRequired,
255
+ };
256
+
257
+ DateTimeComponent.displayName = "DateTimeComponent";
@@ -0,0 +1,90 @@
1
+ // Takes a date time string in UTC time and returns a Date object in local time
2
+ export const ConvertUTCToLocal = (utcTime) => {
3
+ const utcDate = new Date(Date.parse(utcTime))
4
+ return new Date(Date.UTC(utcDate.getFullYear(), utcDate.getMonth(), utcDate.getDate(), utcDate.getHours(), utcDate.getMinutes()))
5
+ }
6
+ // Returns date in format of e.g 30-Jun-2022 10:00 AM
7
+ export const GetDiscountDateTimeString = (utcTime, timeIsLocal = false) => {
8
+ const localDate = timeIsLocal ? new Date(Date.parse(utcTime)) : ConvertUTCToLocal(utcTime)
9
+ const timeString = getTimeString(localDate.getHours(), localDate.getMinutes())
10
+ const dateString = getDateString(localDate.getFullYear(), localDate.getMonth(), localDate.getDate())
11
+ return `${dateString} ${timeString}`
12
+ }
13
+ // Returns date in format of e.g 30-Jun-2022
14
+ export const GetDiscountDateString = (utcTime, timeIsLocal = false) => {
15
+ const localDate = timeIsLocal ? new Date(Date.parse(utcTime)) : ConvertUTCToLocal(utcTime)
16
+ return getDateString(localDate.getFullYear(), localDate.getMonth(), localDate.getDate())
17
+ }
18
+
19
+ export const GetBrowserControlDateTimeString = (utcTime, timeIsLocal = false) => {
20
+ const localDate = timeIsLocal ? new Date(Date.parse(utcTime)) : ConvertUTCToLocal(utcTime)
21
+ return `${getBrowserDateString(localDate.getFullYear(),localDate.getMonth() + 1, localDate.getDate())}T${getBrowserTimeString(localDate.getHours(), localDate.getMinutes())}`
22
+ }
23
+
24
+ export const GetBrowserControTimeString = (utcTime, timeIsLocal = false) => {
25
+ const localDate = timeIsLocal ? new Date(Date.parse(utcTime)) : ConvertUTCToLocal(utcTime)
26
+ return getBrowserTimeString(localDate.getHours(), localDate.getMinutes())
27
+ }
28
+ // Converts the time string, e.g. '06:00', into a full Date object
29
+ export const ConvertBrowserTimeStringToDate = (timeString) => {
30
+ const parts = timeString.split(':')
31
+ if (parts.length === 2) {
32
+ const hours = Number(parts[0])
33
+ const minutes = Number(parts[1])
34
+ if (!isNaN(hours) && !isNaN(minutes)) {
35
+ return new Date().setHours(hours, minutes, 0, 0)
36
+ }
37
+ }
38
+ return new Date().setHours(0,0,0,0)
39
+ }
40
+
41
+ const getBrowserDateString = (year, month, date) => {
42
+ return `${year}-${month.toString().padStart(2, 0)}-${date.toString().padStart(2,0)}`
43
+ }
44
+
45
+ const getBrowserTimeString = (hours, minutes) => {
46
+ return `${hours.toString().padStart(2,0)}:${minutes.toString().padStart(2, 0)}`
47
+ }
48
+
49
+ const getTimeString = (hours, minutes) =>
50
+ {
51
+ const newHours = hours > 12 ? hours - 12 : hours
52
+ const suffix = hours > 11 ? 'PM' : 'AM'
53
+ return `${newHours}:${minutes.toString().padStart(2, '0')} ${suffix} `
54
+ }
55
+
56
+ const getDateString = (year, month, date) =>
57
+ {
58
+ return `${date.toString().padStart(2, '0')}-${shortMonths[month]}-${year}`
59
+ }
60
+
61
+ // left this in for future use
62
+ const months = [
63
+ 'January',
64
+ 'February',
65
+ 'March',
66
+ 'April',
67
+ 'May',
68
+ 'June',
69
+ 'July',
70
+ 'August',
71
+ 'September',
72
+ 'October',
73
+ 'November',
74
+ 'December'
75
+ ]
76
+
77
+ const shortMonths = [
78
+ 'Jan',
79
+ 'Feb',
80
+ 'Mar',
81
+ 'Apr',
82
+ 'May',
83
+ 'Jun',
84
+ 'Jul',
85
+ 'Aug',
86
+ 'Sep',
87
+ 'Oct',
88
+ 'Nov',
89
+ 'Dec'
90
+ ]
package/src/index.tsx CHANGED
@@ -69,7 +69,8 @@ export { NBUI_Card_Form } from "./nbui/nbui-card-form";
69
69
  export { NBUI_Card_Table } from "./nbui/nbui-card-table";
70
70
  export { NBUI_Card_Paragraphs_Large } from "./nbui/nbui-card-paragraphs-lg";
71
71
  export { NBUI_Card_Paragraphs } from "./nbui/nbui-card-paragraphs";
72
- export { NBUI_Footer} from "./nbui/nbui-footer";
72
+ export { NBUI_Footer} from "./nbui/nbui-footer";
73
+ export { DateTimeComponent } from "./date-time-component";
73
74
 
74
75
 
75
76
  import "./styles.css";
package/src/radio.tsx CHANGED
@@ -37,8 +37,8 @@ Radio.propTypes = {
37
37
  disabled: PropTypes.bool,
38
38
  /** function to handle checked value */
39
39
  onChange: PropTypes.func,
40
- /** String for label placed after radio button */
41
- label: PropTypes.string,
40
+ /** label placed after radio button */
41
+ label: PropTypes.node,
42
42
  };
43
43
 
44
44
  Radio.displayName = "Radio";
@@ -1,12 +0,0 @@
1
- import { a } from './chunk-6LHL364H.js';
2
- import { e } from './chunk-Z4LPO673.js';
3
- import { createContext, useRef, useState, useContext, useEffect, Children, cloneElement } from 'react';
4
- import { HiChevronUp, HiChevronDown } from 'react-icons/hi';
5
- import { jsx, jsxs } from 'react/jsx-runtime';
6
-
7
- var r=e(a(),1);var d=createContext({currentlyShowing:null,handleSelection:t=>{},addPanelOrder:t=>{},getPanelList:()=>[]});function s({children:t}){let e=useRef([]),[n,o]=useState(null),i=a=>{o(n===a?null:a);},l=a=>{e.current.push(a);},h=()=>e.current;return jsx(d.Provider,{value:{currentlyShowing:n,handleSelection:i,addPanelOrder:l,getPanelList:h},children:t})}function u({children:t,id:e}){let n=useContext(d);return useEffect(()=>{n.addPanelOrder(e);},[]),jsx("div",{id:`${e}-panel`,"data-accordion":"collapse",children:Children.map(t,o=>cloneElement(o,{id:e}))})}function y({children:t,id:e}){let n=useContext(d),o=()=>{n.handleSelection(e);},i=n.getPanelList(),l=i[i.length-1]===e;return jsx("h2",{id:`${e}-title`,children:jsxs("button",{type:"button",className:`flex w-full items-center justify-between border p-5 text-left font-medium ${l&&n.currentlyShowing!==e?"border-b-1":"border-b-0"} border-gray-200 ${i[0]===e?"rounded-t-xl":l&&n.currentlyShowing!==e?"rounded-b-xl":"rounded-none"} ${n.currentlyShowing===e&&"bg-gray-100"}
8
- text-gray-500 hover:bg-gray-100 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-800 dark:focus:ring-gray-800`,"data-accordion-target":`#${e}-title`,"aria-expanded":"true","aria-controls":`${e}-title`,onClick:o,children:[jsx("span",{children:t}),n.currentlyShowing===`${e}`?jsx(HiChevronUp,{className:"h-6 w-6"}):jsx(HiChevronDown,{className:"h-6 w-6"})]})})}function g({children:t,id:e}){let n=useContext(d),o=n.getPanelList();return jsx("div",{className:e!==n.currentlyShowing?"hidden":"","aria-labelledby":"accordion-collapse-heading-1",children:jsx("div",{className:`border p-5 ${o[o.length-1]===e&&n.currentlyShowing===e?"border-b-1 rounded-b-xl":"border-b-0"} border-gray-200 dark:border-gray-700 dark:bg-gray-900`,children:t})})}s.Panel=u;s.Title=y;s.Content=g;s.propTypes={children:r.default.arrayOf(r.default.element)};u.propTypes={id:r.default.string.isRequired,children:r.default.oneOfType([r.default.shape({type:r.default.oneOf([y])}),r.default.shape({type:r.default.oneOf([g])})]).isRequired};g.propTypes={children:r.default.oneOfType([r.default.elementType])};
9
-
10
- export { d as a, s as b, u as c, y as d, g as e };
11
- //# sourceMappingURL=out.js.map
12
- //# sourceMappingURL=chunk-YDCYBJPC.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/accordion.tsx"],"names":["import_prop_types","useState","createContext","useContext","useEffect","useRef","cloneElement","Children","HiChevronDown","HiChevronUp","jsx","jsxs","AccordionContext","_","Accordion","children","panelListRef","currentlyShowing","setCurrentlyShowing","handleSelection","id","addPanelOrder","getPanelList","AccordionPanel","context","child","AccordionTitle","panelList","isLastPanel","AccordionContent","PropTypes"],"mappings":"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","sourcesContent":["import React, {\n useState,\n createContext,\n useContext,\n useEffect,\n useRef,\n cloneElement,\n Children,\n} from \"react\";\nimport { HiChevronDown, HiChevronUp } from \"react-icons/hi\";\nimport PropTypes from \"prop-types\";\n\ntype AccordionContext = {\n currentlyShowing: string | null;\n handleSelection: (id: string) => void;\n addPanelOrder: (id: string) => void;\n getPanelList: () => string[];\n};\n\nexport const AccordionContext = createContext<AccordionContext>({\n currentlyShowing: null,\n handleSelection: (_: string) => {},\n addPanelOrder: (_: string) => {},\n getPanelList: () => [],\n});\n\ntype AccordionProps = {\n children: React.ReactElement<AccordionPanelProps>[];\n};\n\nexport function Accordion({ children }: AccordionProps) {\n const panelListRef = useRef<string[]>([]);\n const [currentlyShowing, setCurrentlyShowing] = useState<string | null>(null);\n\n const handleSelection = (id: string) => {\n if (currentlyShowing === id) {\n setCurrentlyShowing(null);\n } else {\n setCurrentlyShowing(id);\n }\n };\n\n const addPanelOrder = (id: string) => {\n panelListRef.current.push(id);\n };\n\n const getPanelList = () => {\n return panelListRef.current;\n };\n\n return (\n <AccordionContext.Provider\n value={{ currentlyShowing, handleSelection, addPanelOrder, getPanelList }}\n >\n {children}\n </AccordionContext.Provider>\n );\n}\n\ntype AccordionPanelProps = {\n children: React.DetailedReactHTMLElement<any, HTMLElement>;\n id: string;\n};\n\nexport function AccordionPanel({ children, id }: AccordionPanelProps) {\n const context = useContext(AccordionContext);\n\n useEffect(() => {\n context.addPanelOrder(id);\n }, []);\n\n return (\n <div id={`${id}-panel`} data-accordion=\"collapse\">\n {Children.map(children, (child) => {\n return cloneElement(child, { id: id });\n })}\n </div>\n );\n}\n\ntype AccordionTitleProps = {\n children: React.ReactNode;\n id: string;\n};\n\nexport function AccordionTitle({ children, id }: AccordionTitleProps) {\n const context = useContext(AccordionContext);\n\n const handleSelection = () => {\n context.handleSelection(id);\n };\n\n const panelList = context.getPanelList();\n const isLastPanel = panelList[panelList.length - 1] === id;\n\n return (\n <h2 id={`${id}-title`}>\n <button\n type=\"button\"\n className={`flex w-full items-center justify-between border p-5 text-left font-medium ${\n isLastPanel && context.currentlyShowing !== id\n ? \"border-b-1\"\n : \"border-b-0\"\n } border-gray-200 ${\n panelList[0] === id\n ? \"rounded-t-xl\"\n : isLastPanel && context.currentlyShowing !== id\n ? \"rounded-b-xl\"\n : \"rounded-none\"\n } ${context.currentlyShowing === id && \"bg-gray-100\"}\n text-gray-500 hover:bg-gray-100 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-800 dark:focus:ring-gray-800`}\n data-accordion-target={`#${id}-title`}\n aria-expanded=\"true\"\n aria-controls={`${id}-title`}\n onClick={handleSelection}\n >\n <span>{children}</span>\n {context.currentlyShowing === `${id}` ? (\n <HiChevronUp className=\"h-6 w-6\" />\n ) : (\n <HiChevronDown className=\"h-6 w-6\" />\n )}\n </button>\n </h2>\n );\n}\n\ntype AccordionContentProps = {\n children: React.ReactNode;\n id: string;\n};\n\nexport function AccordionContent({ children, id }: AccordionContentProps) {\n const context = useContext(AccordionContext);\n const panelList = context.getPanelList();\n return (\n <div\n className={id !== context.currentlyShowing ? \"hidden\" : \"\"}\n aria-labelledby=\"accordion-collapse-heading-1\"\n >\n <div\n className={`border p-5 ${\n panelList[panelList.length - 1] === id &&\n context.currentlyShowing === id\n ? \"border-b-1 rounded-b-xl\"\n : \"border-b-0\"\n } border-gray-200 dark:border-gray-700 dark:bg-gray-900`}\n >\n {children}\n </div>\n </div>\n );\n}\n\nAccordion.Panel = AccordionPanel;\nAccordion.Title = AccordionTitle;\nAccordion.Content = AccordionContent;\n\nAccordion.propTypes = {\n /** Components to be rendered as Part of the Compound Component, each panel is a seperate accordion section*/\n children: PropTypes.arrayOf(PropTypes.element),\n};\n\nAccordionPanel.propTypes = {\n /** Unique id for the dropdown */\n id: PropTypes.string.isRequired,\n /** Components to be rendered as Part of the Compound Component*/\n children: PropTypes.oneOfType([\n PropTypes.shape({ type: PropTypes.oneOf([AccordionTitle]) }),\n PropTypes.shape({ type: PropTypes.oneOf([AccordionContent]) }),\n ]).isRequired,\n};\n\nAccordionContent.propTypes = {\n /** Components held within the Content section of the AccordionPanel*/\n children: PropTypes.oneOfType([PropTypes.elementType]),\n};\n"]}