ekm-ui 0.0.29 → 0.2.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 (58) hide show
  1. package/.turbo/turbo-build.log +110 -80
  2. package/CHANGELOG.md +6 -1
  3. package/dist/accordion.d.ts +51 -0
  4. package/dist/accordion.mjs +5 -0
  5. package/dist/accordion.mjs.map +1 -0
  6. package/dist/breadcrumb.d.ts +33 -0
  7. package/dist/breadcrumb.mjs +5 -0
  8. package/dist/breadcrumb.mjs.map +1 -0
  9. package/dist/button.d.ts +3 -3
  10. package/dist/card-payment-block.css +1 -1
  11. package/dist/card-payment-block.css.map +1 -1
  12. package/dist/card-payment-block.mjs +20 -14
  13. package/dist/checkbox.d.ts +5 -0
  14. package/dist/checkbox.mjs +5 -0
  15. package/dist/checkbox.mjs.map +1 -0
  16. package/dist/chunk-EQANFKDN.mjs +10 -0
  17. package/dist/chunk-EQANFKDN.mjs.map +1 -0
  18. package/dist/chunk-ER4YVWM3.mjs +12 -0
  19. package/dist/chunk-ER4YVWM3.mjs.map +1 -0
  20. package/dist/{chunk-MG4OUK2N.mjs → chunk-IUZHBHDJ.mjs} +4 -4
  21. package/dist/chunk-NI4IFVX3.mjs +11 -0
  22. package/dist/chunk-NI4IFVX3.mjs.map +1 -0
  23. package/dist/chunk-NS6AVKX7.mjs +12 -0
  24. package/dist/chunk-NS6AVKX7.mjs.map +1 -0
  25. package/dist/chunk-S7V4MUJ2.mjs +10 -0
  26. package/dist/chunk-S7V4MUJ2.mjs.map +1 -0
  27. package/dist/chunk-VASBTVLS.mjs +10 -0
  28. package/dist/chunk-VASBTVLS.mjs.map +1 -0
  29. package/dist/dropdown.d.ts +49 -0
  30. package/dist/dropdown.mjs +5 -0
  31. package/dist/dropdown.mjs.map +1 -0
  32. package/dist/index.css +1 -1
  33. package/dist/index.css.map +1 -1
  34. package/dist/index.d.ts +6 -0
  35. package/dist/index.mjs +20 -14
  36. package/dist/layout/layout.css +1 -1
  37. package/dist/layout/layout.css.map +1 -1
  38. package/dist/layout/layout.mjs +20 -14
  39. package/dist/rich-text-editor/index.d.ts +2 -2
  40. package/dist/select.d.ts +5 -0
  41. package/dist/select.mjs +5 -0
  42. package/dist/select.mjs.map +1 -0
  43. package/dist/stacked-list-item.css +1 -1
  44. package/dist/stacked-list-item.css.map +1 -1
  45. package/dist/stacked-list-item.mjs +20 -14
  46. package/dist/textarea.d.ts +5 -0
  47. package/dist/textarea.mjs +5 -0
  48. package/dist/textarea.mjs.map +1 -0
  49. package/dist/toast/index.d.ts +2 -2
  50. package/package.json +2 -1
  51. package/src/accordion.tsx +115 -0
  52. package/src/breadcrumb.tsx +43 -0
  53. package/src/checkbox.tsx +30 -0
  54. package/src/dropdown.tsx +140 -0
  55. package/src/index.tsx +6 -0
  56. package/src/select.tsx +44 -0
  57. package/src/textarea.tsx +51 -0
  58. /package/dist/{chunk-MG4OUK2N.mjs.map → chunk-IUZHBHDJ.mjs.map} +0 -0
@@ -1,36 +1,42 @@
1
- export { a as StackedListItem } from './chunk-MG4OUK2N.mjs';
2
- import './chunk-HAQTLD4G.mjs';
3
- import './chunk-X6GXSTW7.mjs';
1
+ export { a as StackedListItem } from './chunk-IUZHBHDJ.mjs';
4
2
  import './chunk-ZHHTK7UM.mjs';
5
3
  import './chunk-QWPN2UNV.mjs';
6
- import './chunk-RMX72FR3.mjs';
7
- import './chunk-25FJ277C.mjs';
8
4
  import './chunk-FAFXVD4P.mjs';
9
5
  import './chunk-256SAVHD.mjs';
10
6
  import './chunk-VPLCWU7T.mjs';
11
7
  import './chunk-3ZCDEN7B.mjs';
12
8
  import './chunk-HDNA6QBW.mjs';
9
+ import './chunk-HAQTLD4G.mjs';
10
+ import './chunk-X6GXSTW7.mjs';
11
+ import './chunk-FJQEJBBY.mjs';
12
+ import './chunk-EWNPNF2B.mjs';
13
+ import './chunk-YQAMEBON.mjs';
14
+ import './chunk-EQANFKDN.mjs';
15
+ import './chunk-RMX72FR3.mjs';
16
+ import './chunk-NI4IFVX3.mjs';
17
+ import './chunk-25FJ277C.mjs';
18
+ import './chunk-LWDFKEBO.mjs';
19
+ import './chunk-PJMH47GY.mjs';
13
20
  import './chunk-KAQJAKQH.mjs';
14
21
  import './chunk-BIU2AAPZ.mjs';
15
22
  import './chunk-B2KVPYRJ.mjs';
16
23
  import './chunk-OT256LE6.mjs';
17
- import './chunk-FJQEJBBY.mjs';
18
- import './chunk-EWNPNF2B.mjs';
19
- import './chunk-YQAMEBON.mjs';
24
+ import './chunk-FRIXS4BL.mjs';
25
+ import './chunk-YTTLKTRL.mjs';
26
+ import './chunk-T2OVPC6F.mjs';
27
+ import './chunk-3CISFAGD.mjs';
20
28
  import './chunk-ZPLTGYYM.mjs';
21
29
  import './chunk-QRNTMHBL.mjs';
30
+ import './chunk-ER4YVWM3.mjs';
22
31
  import './chunk-ZT7KDTGF.mjs';
23
32
  import './chunk-WU66HPYP.mjs';
24
- import './chunk-FRIXS4BL.mjs';
25
- import './chunk-LWDFKEBO.mjs';
26
- import './chunk-PJMH47GY.mjs';
33
+ import './chunk-NS6AVKX7.mjs';
27
34
  import './chunk-O3QYDTAF.mjs';
28
35
  import './chunk-664HOPW7.mjs';
36
+ import './chunk-S7V4MUJ2.mjs';
29
37
  import './chunk-SAXGEQRG.mjs';
30
38
  import './chunk-LN7UO7PK.mjs';
31
- import './chunk-YTTLKTRL.mjs';
32
- import './chunk-T2OVPC6F.mjs';
33
- import './chunk-3CISFAGD.mjs';
39
+ import './chunk-VASBTVLS.mjs';
34
40
  import './chunk-QTAUYFKM.mjs';
35
41
  import './chunk-RUPJ2ZHA.mjs';
36
42
  //# sourceMappingURL=out.js.map
@@ -0,0 +1,5 @@
1
+ import * as react from 'react';
2
+
3
+ declare const TextArea: react.ForwardRefExoticComponent<react.RefAttributes<unknown>>;
4
+
5
+ export { TextArea };
@@ -0,0 +1,5 @@
1
+ export { a as TextArea } from './chunk-NI4IFVX3.mjs';
2
+ import './chunk-QTAUYFKM.mjs';
3
+ import './chunk-RUPJ2ZHA.mjs';
4
+ //# sourceMappingURL=out.js.map
5
+ //# sourceMappingURL=textarea.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":""}
@@ -1,6 +1,6 @@
1
- import * as React$1 from 'react';
1
+ import * as react from 'react';
2
2
 
3
- declare const ToastContext: React$1.Context<((toast: ToastEvent) => void) | undefined>;
3
+ declare const ToastContext: react.Context<((toast: ToastEvent) => void) | undefined>;
4
4
  declare function ToastProvider({ children }: {
5
5
  children: React.ReactNode;
6
6
  }): JSX.Element;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ekm-ui",
3
- "version": "0.0.29",
3
+ "version": "0.2.0",
4
4
  "sideEffects": [
5
5
  "**/*.css"
6
6
  ],
@@ -62,6 +62,7 @@
62
62
  "@dnd-kit/utilities": "^3.2.1",
63
63
  "@headlessui/react": "^1.7.14",
64
64
  "@heroicons/react": "^2.0.18",
65
+ "classname-variants": "^1.3.2",
65
66
  "clsx": "^1.2.1",
66
67
  "flowbite": "^1.8.1",
67
68
  "flowbite-react": "^0.6.4",
@@ -0,0 +1,115 @@
1
+ //@ts-nocheck
2
+ import { useState, createContext, useContext, useEffect, useRef, cloneElement, Children } from 'react'
3
+ import { HiChevronDown, HiChevronUp } from 'react-icons/hi'
4
+ import PropTypes from 'prop-types'
5
+ export const AccordionContext = createContext()
6
+
7
+ export function Accordion({ children, ...props }) {
8
+ const panelListRef = useRef([])
9
+ const [currentlyShowing, setCurrentlyShowing] = useState(null)
10
+
11
+ const handleSelection = (id) => {
12
+ if (currentlyShowing === id) {
13
+ setCurrentlyShowing(null)
14
+ } else {
15
+ setCurrentlyShowing(id)
16
+ }
17
+ }
18
+
19
+ const addPanelOrder = (id) => {
20
+ panelListRef.current.push(id)
21
+ }
22
+
23
+ const getPanelList = () => {
24
+ return panelListRef.current
25
+ }
26
+
27
+ return <AccordionContext.Provider value={{ currentlyShowing, handleSelection, addPanelOrder, getPanelList }}>{children}</AccordionContext.Provider>
28
+ }
29
+
30
+ export function AccordionPanel({ children, ...props }) {
31
+ const context = useContext(AccordionContext)
32
+ useEffect(() => {
33
+ context.addPanelOrder(props.id)
34
+ }, [])
35
+
36
+ return (
37
+ <div id={`${props.id}-panel`} data-accordion="collapse">
38
+ {Children.map(children, (child) => {
39
+ return cloneElement(child, { id: props.id })
40
+ })}
41
+ </div>
42
+ )
43
+ }
44
+
45
+ export function AccordionTitle({ children, ...props }) {
46
+ const context = useContext(AccordionContext)
47
+
48
+ const handleSelection = (e) => {
49
+ context.handleSelection(props.id)
50
+ }
51
+
52
+ const panelList = context.getPanelList()
53
+ const isLastPanel = panelList[panelList.length - 1] === props.id
54
+
55
+ return (
56
+ <h2 id={`${props.id}-title`}>
57
+ <button
58
+ type="button"
59
+ className={`flex items-center justify-between w-full p-5 font-medium text-left border ${
60
+ isLastPanel && context.currentlyShowing !== props.id ? 'border-b-1' : 'border-b-0'
61
+ } border-gray-200 ${
62
+ panelList[0] === props.id ? 'rounded-t-xl' : isLastPanel && context.currentlyShowing !== props.id ? 'rounded-b-xl' : 'rounded-none'
63
+ } ${context.currentlyShowing === props.id && 'bg-gray-100'}
64
+ dark:focus:ring-gray-800 dark:border-gray-700 hover:bg-gray-100 dark:hover:bg-gray-800 text-gray-500 dark:text-gray-400`}
65
+ data-accordion-target={`#${props.id}-title`}
66
+ aria-expanded="true"
67
+ aria-controls={`${props.id}-title`}
68
+ onClick={handleSelection}
69
+ >
70
+ <span>{children}</span>
71
+ {context.currentlyShowing === `${props.id}` ? <HiChevronUp className="w-6 h-6" /> : <HiChevronDown className="w-6 h-6" />}
72
+ </button>
73
+ </h2>
74
+ )
75
+ }
76
+
77
+ export function AccordionContent({ children, ...props }) {
78
+ const context = useContext(AccordionContext)
79
+ const panelList = context.getPanelList()
80
+ return (
81
+ <div className={props.id !== context.currentlyShowing ? 'hidden' : ''} aria-labelledby="accordion-collapse-heading-1">
82
+ <div
83
+ className={`p-5 border ${
84
+ panelList[panelList.length - 1] === props.id && context.currentlyShowing === props.id ? 'rounded-b-xl border-b-1' : 'border-b-0'
85
+ } border-gray-200 dark:border-gray-700 dark:bg-gray-900`}
86
+ >
87
+ {children}
88
+ </div>
89
+ </div>
90
+ )
91
+ }
92
+
93
+ Accordion.Panel = AccordionPanel
94
+ Accordion.Title = AccordionTitle
95
+ Accordion.Content = AccordionContent
96
+
97
+ Accordion.propTypes = {
98
+ /** Components to be rendered as Part of the Compound Component, each panel is a seperate accordion section*/
99
+ children: PropTypes.shape({ type: PropTypes.arrayOf([AccordionPanel]) }).isRequired,
100
+ }
101
+
102
+ AccordionPanel.propTypes = {
103
+ /** Unique id for the dropdown */
104
+ id: PropTypes.string.isRequired,
105
+ /** Components to be rendered as Part of the Compound Component*/
106
+ children: PropTypes.oneOfType([
107
+ PropTypes.shape({ type: PropTypes.oneOf([AccordionTitle]) }),
108
+ PropTypes.shape({ type: PropTypes.oneOf([AccordionContent]) }),
109
+ ]).isRequired,
110
+ }
111
+
112
+ AccordionContent.propTypes = {
113
+ /** Components held within the Content section of the AccordionPanel*/
114
+ children: PropTypes.oneOfType([PropTypes.elementType]),
115
+ }
@@ -0,0 +1,43 @@
1
+ //@ts-nocheck
2
+ import { HiOutlineChevronRight } from 'react-icons/hi'
3
+ import PropTypes from 'prop-types'
4
+
5
+ export function Breadcrumb({ children }) {
6
+ return (
7
+ <nav className="flex" aria-label="Breadcrumb">
8
+ <ol className="inline-flex items-center space-x-1 md:space-x-3">{children}</ol>
9
+ </nav>
10
+ )
11
+ }
12
+ export function BreadcrumbHome({ children }) {
13
+ return <li className="inline-flex items-center">{children}</li>
14
+ }
15
+ export function BreadcrumbItem({ children }) {
16
+ return (
17
+ <li className="inline-flex items-center">
18
+ <HiOutlineChevronRight class="w-3 h-3 mr-2.5" />
19
+ {children}
20
+ </li>
21
+ )
22
+ }
23
+
24
+ Breadcrumb.Home = BreadcrumbHome
25
+ Breadcrumb.Item = BreadcrumbItem
26
+
27
+ Breadcrumb.propTypes = {
28
+ /** Beadcrumb compunds elements that make up the breadcrumb*/
29
+ children: PropTypes.arrayOf([PropTypes.oneOfType([PropTypes.shape({ type: PropTypes.oneOf([BreadcrumbHome]) }),
30
+ PropTypes.arrayOf(PropTypes.shape({ type: BreadcrumbItem }))])]).isRequired
31
+ }
32
+
33
+ BreadcrumbHome.propTypes = {
34
+ /** Elements to show in the breadcrumb usually this will be an icon with just a string or element like a span */
35
+ children : PropTypes.arrayOf([PropTypes.node]).isRequired
36
+ }
37
+
38
+ BreadcrumbItem.propTypes = {
39
+ /** Elements to show in the breadcrumb usually this will be just a string or element like a span */
40
+ children : PropTypes.oneOfType([
41
+ PropTypes.string,
42
+ PropTypes.node]).isRequired
43
+ }
@@ -0,0 +1,30 @@
1
+ //@ts-nocheck
2
+ import { forwardRef } from 'react'
3
+ import PropTypes from 'prop-types'
4
+
5
+ export const Checkbox = forwardRef(function Checkbox(props, ref) {
6
+ return (
7
+ <div className="flex items-center">
8
+ <input
9
+ id={props.id}
10
+ ref={ref}
11
+ type="checkbox"
12
+ className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
13
+ {...props}
14
+ />
15
+ {props.label && (
16
+ <label id={`${props.id}-lbl`} htmlFor={props.id} className="ms-2 text-sm font-medium text-gray-900 dark:text-gray-300">
17
+ {props.label}
18
+ </label>
19
+ )}
20
+ </div>
21
+ )
22
+ })
23
+
24
+ Checkbox.propTypes = {
25
+ id: PropTypes.string.isRequired,
26
+ label: PropTypes.string,
27
+ checked: PropTypes.bool,
28
+ disabled: PropTypes.bool,
29
+ onChange: PropTypes.func,
30
+ }
@@ -0,0 +1,140 @@
1
+ //@ts-nocheck
2
+ import { variantProps } from 'classname-variants/react'
3
+ import { useState, createContext, useContext, useEffect, useRef } from 'react'
4
+ import { BiChevronDown } from 'react-icons/bi'
5
+ import PropTypes from 'prop-types'
6
+ const DropdownContext = createContext()
7
+
8
+ // BUTTON CLASSES
9
+ const buttonProps = variantProps({
10
+ base: 'text-white focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium text-sm py-2.5 text-center inline-flex items-center',
11
+ variants: {
12
+ color: {
13
+ blue: 'bg-blue-700 hover:bg-blue-800 dark:bg-blue-600 dark:hover:bg-blue-700 focus:ring-blue-300',
14
+ gray: 'bg-gray-700 hover:bg-gray-800 dark:bg-gray-600 dark:hover:bg-gray-700 focus:ring-gray-300',
15
+ green: 'bg-green-700 hover:bg-green-800 dark:bg-green-600 dark:hover:bg-green-700 focus:ring-green-300',
16
+ red: 'bg-red-700 hover:bg-red-800 dark:bg-red-600 dark:hover:bg-red-700 focus:ring-red-300',
17
+ yellow: 'bg-yellow-700 hover:bg-yellow-800 dark:bg-yellow-600 dark:hover:bg-yellow-700 focus:ring-yellow-300',
18
+ },
19
+ size: {
20
+ sm: 'px-5 py-1.5',
21
+ md: 'px-5 py-2.5',
22
+ lg: 'px-5 py-3.5',
23
+ // WORKAROUND: Compound variants don't work with classname-variants/react (revisit later)
24
+ rsm: 'px-2.5 py-2.5',
25
+ rmd: 'px-3.5 py-3.5',
26
+ rlg: 'px-4.5 py-4.5',
27
+ },
28
+ type: {
29
+ rect: 'rounded-lg',
30
+ round: 'rounded-full',
31
+ },
32
+ defaultVariants: {
33
+ color: 'blue',
34
+ size: 'md',
35
+ type: 'rect',
36
+ },
37
+ },
38
+ })
39
+
40
+ const DropdownState = Object.freeze({
41
+ OPEN: 'open',
42
+ CLOSED: 'closed',
43
+ })
44
+
45
+ export function Dropdown({ children, ...props }) {
46
+ const [showDropdown, setShowDropdown] = useState(DropdownState.CLOSED)
47
+ const handleShowDropdown = () => {
48
+ const currState = showDropdown
49
+ setShowDropdown(currState === DropdownState.CLOSED ? DropdownState.OPEN : DropdownState.CLOSED)
50
+ }
51
+
52
+ useEffect(() => {
53
+ const handleClickOutside = (e) => {
54
+ if (e.target.id === props.id) return
55
+ setShowDropdown(DropdownState.CLOSED)
56
+ }
57
+
58
+ document.addEventListener('click', handleClickOutside)
59
+
60
+ return () => {
61
+ document.removeEventListener('click', handleClickOutside)
62
+ }
63
+ }, [])
64
+
65
+ return (
66
+ <DropdownContext.Provider value={{ showDropdown, setShowDropdown }}>
67
+ <button id={props.id} {...buttonProps(props)} data-dropdown-toggle={`${props.id}-dropdown`} type="button" onClick={handleShowDropdown}>
68
+ {props.label}
69
+ {props.type === 'rect' && <BiChevronDown />}
70
+ </button>
71
+ <div
72
+ id={`${props.id}-dropdown`}
73
+ className={`z-10 mt-2 absolute ${
74
+ showDropdown === DropdownState.OPEN ? '' : 'hidden'
75
+ } bg-white divide-y divide-gray-100 rounded-lg shadow w-44 dark:bg-gray-700`}
76
+ >
77
+ <ul className="py-2 text-sm text-gray-700 dark:text-gray-200" aria-labelledby="dropdownDefaultButton">
78
+ {children}
79
+ </ul>
80
+ </div>
81
+ </DropdownContext.Provider>
82
+ )
83
+ }
84
+
85
+ export function DropdownDivider() {
86
+ return (
87
+ <li>
88
+ <hr className="h-px my-2 bg-gray-200 border-0 dark:bg-gray-700" />
89
+ </li>
90
+ )
91
+ }
92
+
93
+ export function DropdownItem({ callback, children }) {
94
+ const context = useContext(DropdownContext)
95
+
96
+ const handleSelection = () => {
97
+ context.setShowDropdown(false)
98
+ callback()
99
+ }
100
+ return (
101
+ <li>
102
+ <div className="block px-4 py-2 cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white" onClick={handleSelection}>
103
+ {children}
104
+ </div>
105
+ </li>
106
+ )
107
+ }
108
+
109
+ Dropdown.Divider = DropdownDivider
110
+ Dropdown.Item = DropdownItem
111
+
112
+ Dropdown.propTypes = {
113
+ /** Unique id for the dropdown */
114
+ id: PropTypes.string.isRequired,
115
+ /** Components to be rendered as Part of the Compound Component*/
116
+ children: PropTypes.oneOfType([
117
+ PropTypes.shape({ type: PropTypes.oneOf([DropdownItem]), }),
118
+ PropTypes.arrayOf(PropTypes.shape({ type: PropTypes.oneOf([DropdownDivider]) }))
119
+ ]).isRequired,
120
+ /** Shape of the button rectangle or round */
121
+ type: PropTypes.oneOf(['rect', 'round']),
122
+ /** Size of the button sm,md,lg used for rectangle and rsm, rmd, rlg used for a round button */
123
+ size: PropTypes.oneOf(['sm', 'md', 'lg', 'rsm', 'rmd', 'rlg']),
124
+ /** Colour of the button based upon predefined values */
125
+ color: PropTypes.oneOf(['blue', 'gray', 'green', 'red', 'yellow']),
126
+ /** Rectangle should have a text label eg:'Dropdown' and a round type should take an icon element eg:'...' */
127
+ label: PropTypes.oneOfType([PropTypes.string, PropTypes.node]).isRequired,
128
+ /** Returns value of the selected item */
129
+ callback: PropTypes.func.isRequired,
130
+ }
131
+ Dropdown.defaultProps = {
132
+ type: 'rect',
133
+ size: 'md',
134
+ color: 'blue',
135
+ label: 'Dropdown',
136
+ }
137
+ DropdownItem.propTypes = {
138
+ /** Returns value of the dropdown item selected*/
139
+ callback: PropTypes.func.isRequired,
140
+ }
package/src/index.tsx CHANGED
@@ -31,5 +31,11 @@ export { TableHeader } from "./table-header/table-header";
31
31
  export { Search } from "./search/search";
32
32
  export { LoadingButton } from "./loading-button";
33
33
  export { DragAndDrop } from "./drag-and-drop";
34
+ export { Dropdown } from "./dropdown";
35
+ export { Select } from "./select";
36
+ export { Checkbox } from "./checkbox";
37
+ export { Accordion } from "./accordion";
38
+ export { Breadcrumb } from "./breadcrumb";
39
+ export {TextArea} from "./textarea";
34
40
 
35
41
  import "./styles.css";
package/src/select.tsx ADDED
@@ -0,0 +1,44 @@
1
+ //@ts-nocheck
2
+ import { forwardRef } from 'react'
3
+ import PropTypes from 'prop-types'
4
+ export const Select = forwardRef(function Select(props, ref) {
5
+ return (
6
+ <>
7
+ {props.label && (
8
+ <label htmlFor={`${props.id}-select`} className="block mb-2 text-sm font-medium text-gray-900 dark:text-white">
9
+ {props.label}
10
+ </label>
11
+ )}
12
+ <select
13
+ id={`${props.id}-select`}
14
+ ref={ref}
15
+ className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 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"
16
+ {...props}
17
+ >
18
+ {(props.options || []).map((o) => {
19
+ return (
20
+ <option key={`${props.id}-${o.value}`} value={o.value} disabled={o.disabled}>
21
+ {o.display}
22
+ </option>
23
+ )
24
+ })}
25
+ </select>
26
+ </>
27
+ )
28
+ })
29
+
30
+ Select.propTypes = {
31
+ /** Unique id for the dropdown */
32
+ id: PropTypes.string.isRequired,
33
+ /** Optional label for the dropdown */
34
+ label: PropTypes.string,
35
+ /** Optional inital selected value must match the value of an element of an object in the options array. (defaults to first value in the list)*/
36
+ defaultValue: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
37
+ /** Array of objects with value and display properties */
38
+ options: PropTypes.arrayOf(PropTypes.shape({
39
+ value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
40
+ display: PropTypes.string.isRequired
41
+ })).isRequired,
42
+ /** Callback function when the dropdown value changes */
43
+ onChange: PropTypes.func.isRequired
44
+ }
@@ -0,0 +1,51 @@
1
+ //@ts-nocheck
2
+ import { forwardRef } from 'react'
3
+ import { variantProps } from 'classname-variants/react'
4
+ import PropTypes from 'prop-types'
5
+
6
+ const fieldProps = variantProps({
7
+ base: 'block p-2.5 w-full text-sm rounded-lg border ',
8
+ variants: {
9
+ color: {
10
+ failure:
11
+ 'text-red-700 bg-red-50 border-red-500 focus:ring-red-500 focus:border-red-500 dark:bg-red-700 dark:border-red-600 dark:placeholder-red-700 dark:text-red-900 dark:focus:ring-red-500 dark:focus:border-red-500',
12
+ gray: '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',
13
+ },
14
+ },
15
+ defaultVariants: {
16
+ color: 'gray',
17
+ },
18
+ })
19
+
20
+ export const TextArea = forwardRef(function TextArea(props, ref) {
21
+ return (
22
+ <>
23
+ {props.label && (
24
+ <label htmlFor={props.id} className="block mb-2 text-sm font-medium text-gray-900 dark:text-white">
25
+ {props.label}
26
+ </label>
27
+ )}
28
+ <textarea
29
+ ref={ref}
30
+ id={props.id}
31
+ rows={props.rows || 3}
32
+ {...fieldProps(props)}
33
+ placeholder={props.placeholder || 'Enter your text here...'}
34
+ {...props}
35
+ ></textarea>
36
+ </>
37
+ )
38
+ })
39
+
40
+ TextArea.propTypes = {
41
+ /** Unique id for the TextArea Component */
42
+ id: PropTypes.string.isRequired,
43
+ /** Optional Label to acompany TextArea Component */
44
+ label: PropTypes.string,
45
+ /** Optional placeholder text for TextArea Component */
46
+ placeholder: PropTypes.string,
47
+ /** Optional number of rows for the TextArea, this defaults to 3 rows if none provided */
48
+ rows: PropTypes.number,
49
+ /** Optional color defaults to gray and shpuld be set to failure if it fails validation*/
50
+ color: PropTypes.oneOf(['gray', 'failure']),
51
+ }