diff --git a/README.md b/README.md
index 04fc902..d3a45ed 100644
--- a/README.md
+++ b/README.md
@@ -6,6 +6,21 @@ React select component library
It's a react component made for Openclassroom hr-net project
+# Summary
+
+- [Getting Started](#getting-started)
+- [Dependencies](#dependencies)
+- [Installing](#installing)
+- [Executing program](#executing-program)
+- [Props](#props)
+- [Data Structure](#data-structure)
+- [Category Object](#category-object)
+- [Item Object](#item-object)
+- [Example usage](#example-usage)
+---
+- [Authors](#authors)
+- [Version History](#version-history)
+
## Getting Started
### Dependencies
@@ -25,10 +40,10 @@ npm install voidsplit-select-component
```
import { SelectMenu } from 'voidsplit_select_component';
-
+
```
* Data Example:
-```
+```javascript
const data = [
{
type: "category",
@@ -36,23 +51,113 @@ const data = [
categoryContent: [
{
type: "item",
+ id: 0,
display: "Item Display Value",
disabled: true
},
{
type: "item",
+ id: 1,
display: "2nd Item Display Value"
}
]
},
{
type: "item",
+ id: 2,
abbreviation: "Item Abreviation",
display: "3rd Item Display Value"
}
]
```
+### Props
+The `SelectMenu` component accepts the following props:
+
+- `innerRef` (function): A reference callback to access the DOM element of the input.
+- `data` (array): An array of objects representing the data to be displayed in the selection menu.
+- `id` (string): A unique identifier for the selection menu component.
+- `label` (string): The label for the selection menu.
+
+## Data Structure
+
+The data structure for the selection menu component should follow a specific format to ensure proper rendering. The data array should consist of objects representing either categories or individual items. Here's how the data should be structured:
+
+Each object in the `data` array represents either a category or an item:
+
+### Category Object
+
+A category object should have the following properties:
+
+- `type` *(string)*: Set to `"category"` to indicate that this object represents a category.
+- `categoryName` *(string)*: The name of the category.
+- `categoryContent` *(array)*: An array containing the items within the category. Each item should be an object with its own properties.
+
+### Item Object
+
+An item object should have the following properties:
+
+- `type` *(string)*: Set to `"item"` to indicate that this object represents an item.
+- `display` *(string)*: The display text for the item.
+- `abbreviation` *(string, optional)*: Abbreviated text for the item (optional).
+- `id` *(number)*: A unique identifier for the item.
+- `disabled` *(boolean, optional)*: Whether the item is disabled (optional).
+
+Here's an example of a properly structured `data` array:
+
+```javascript
+const componentData = [
+ {
+ type: "category",
+ categoryName: "Category 0",
+ categoryContent: [
+ {
+ type: "item",
+ display: "Item Display Value",
+ abbreviation: "Item Abbreviation",
+ id: 0
+ },
+ {
+ type: "item",
+ display: "2nd Item Display Value",
+ id: 1
+ }
+ ]
+ },
+ {
+ type: "item",
+ display: "3rd Item Display Value",
+ abbreviation: "Item Abbreviation",
+ id: 2
+ },
+ // ... more items or categories
+];
+
+```
+
+## Example usage
+
+Here's an example of how to use the component:
+```javascript
+import React, { useRef } from 'react';
+import { SelectMenu } from 'voidsplit_select_component';
+
+const App = () => {
+ const componentRef = useRef(null);
+
+ const componentData = [
+ // ... your data array
+ ];
+
+ return (
+
+
+
+ );
+}
+
+export default App;
+```
## Authors
Contributors names and contact info
@@ -61,6 +166,12 @@ Contributors names and contact info
## Version History
+* 0.3.1
+ * Component Optimisations
+ * Adding jsdoc documentation
+ * Improved readMe documentation
+* 0.3.0
+ * Total component redesign
* 0.2.13
* SEO optimization on npm
* 0.2.12
diff --git a/package-lock.json b/package-lock.json
index 6ceade5..d8fb149 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,15 +1,16 @@
{
"name": "voidsplit_select_component",
- "version": "0.2.6",
+ "version": "0.3.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "voidsplit_select_component",
- "version": "0.2.6",
+ "version": "0.3.0",
"dependencies": {
"@emotion/react": "^11.10.8",
"@emotion/styled": "^11.10.8",
+ "prop-types": "^15.8.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"tailwindcss": "^3.3.2",
@@ -4165,7 +4166,6 @@
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
- "dev": true,
"dependencies": {
"loose-envify": "^1.4.0",
"object-assign": "^4.1.1",
@@ -8368,7 +8368,6 @@
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
- "dev": true,
"requires": {
"loose-envify": "^1.4.0",
"object-assign": "^4.1.1",
diff --git a/package.json b/package.json
index e99942d..8ade111 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,15 @@
{
"name": "voidsplit_select_component",
- "version": "0.2.13",
- "keywords": ["react", "react component", "select", "select menu", "vite", "select component", "openclassroom"],
+ "version": "0.3.0",
+ "keywords": [
+ "react",
+ "react component",
+ "select",
+ "select menu",
+ "vite",
+ "select component",
+ "openclassroom"
+ ],
"type": "module",
"main": "./dist/react-vite-library.umd.cjs",
"module": "./dist/react-vite-library.es.js",
@@ -27,6 +35,7 @@
"dependencies": {
"@emotion/react": "^11.10.8",
"@emotion/styled": "^11.10.8",
+ "prop-types": "^15.8.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"tailwindcss": "^3.3.2",
diff --git a/src/components/SelectMenu/Category.jsx b/src/components/SelectMenu/Category.jsx
new file mode 100644
index 0000000..0d9e8a4
--- /dev/null
+++ b/src/components/SelectMenu/Category.jsx
@@ -0,0 +1,42 @@
+// import PropTypes from 'prop-types';
+/* eslint-disable react/prop-types */
+
+import Item from "./Item";
+
+/**
+ * Represents a category within a selection menu.
+ *
+ * @component
+ * @param {Object} props - The component properties.
+ * @param {string} props.name - The name of the category.
+ * @param {Array} props.list - The list of items within the category.
+ * @param {function} props.itemCallback - The callback function triggered when an item within the category is selected.
+ * @param {number} props.selected - The ID of the currently selected item.
+ * @param {function} props.toggleOpen - Callback to toggle the open state of the menu.
+ * @returns {JSX.Element} A component representing a category in the selection menu.
+ */
+export default function Category({name, list, itemCallback, selected, toggleOpen}) {
+ return (
+
+
{name}
+ {/* Loop through the list to render items within the category */}
+ {list.map((el, index) => {
+ switch(el.type) {
+ case "item":
+ return
+ default:
+ return false
+ }
+ })}
+
+ );
+}
+
+
+// Category.propTypes = {
+// name: PropTypes.string,
+// list: PropTypes.array,
+// itemCallback: PropTypes.func,
+// selected: PropTypes.bool,
+// toggleOpen: PropTypes.func
+// }
\ No newline at end of file
diff --git a/src/components/SelectMenu/Item.jsx b/src/components/SelectMenu/Item.jsx
new file mode 100644
index 0000000..279d500
--- /dev/null
+++ b/src/components/SelectMenu/Item.jsx
@@ -0,0 +1,50 @@
+// import PropTypes from 'prop-types';
+/* eslint-disable react/prop-types */
+
+/**
+ * Represents an item within a selection menu.
+ *
+ * @component
+ * @param {Object} props - The component properties.
+ * @param {function} props.action - The callback function triggered when the item is selected.
+ * @param {string} props.display - The display text for the item.
+ * @param {string} props.abbreviation - The abbreviated text for the item (optional).
+ * @param {number} props.id - The unique identifier for the item.
+ * @param {boolean} props.selected - Indicates whether the item is currently selected.
+ * @param {function} props.toggleOpen - Callback to toggle the open state of the menu.
+ * @returns {JSX.Element} A button representing the selectable item.
+ */
+export default function Item({action, display, abbreviation, id, selected, toggleOpen}) {
+ // Determine the displayed text based on abbreviation or display value
+ let displayed = abbreviation ? abbreviation : display ? display : "error"
+ return (
+
+ );
+}
+
+
+// Item.propTypes = {
+// action: PropTypes.func,
+// display: PropTypes.string,
+// abbreviation: PropTypes.string,
+// id: PropTypes.number,
+// selected: PropTypes.bool,
+// toggleOpen: PropTypes.func
+// }
\ No newline at end of file
diff --git a/src/components/SelectMenu/SelectMenu.jsx b/src/components/SelectMenu/SelectMenu.jsx
index 39a147e..914555e 100644
--- a/src/components/SelectMenu/SelectMenu.jsx
+++ b/src/components/SelectMenu/SelectMenu.jsx
@@ -1,110 +1,93 @@
-/* eslint-disable react/prop-types */
// import PropTypes from 'prop-types';
+/* eslint-disable react/prop-types */
+import Category from './Category';
+import Item from './Item';
-import { useEffect, useState } from "react"
-
-import './selectMenu.css'
+import { useState } from 'react';
+import './styles/selectMenu.css'
-function SelectMenu({data, selectedItem, innerRef, id}) {
- let displayItem;
- selectedItem ? displayItem = data.filter(e => e.name === selectedItem)[0] : displayItem = data[0].type === "category" ? data[0].categoryContent.filter(el => el.disabled !== true)[0] : data[0]
- let displayList = [...data]
+/**
+ * Interactive selection menu component.
+ *
+ * @component
+ * @param {Object} props - The component properties.
+ * @param {function} props.innerRef - Reference to the callback function for accessing the DOM element.
+ * @param {string} props.id - Unique ID for the selection menu element.
+ * @param {Array} props.data - The data to display in the selection menu.
+ * @param {string} props.label - The label for the selection menu.
+ * @returns {JSX.Element} React element representing the selection menu.
+ */
+export function SelectMenu({innerRef, id, data, label}) {
+ // State to manage whether the menu is opened or not
+ const [isOpened, toggleOpen] = useState(false)
- const [selected, changeSelected] = useState(displayItem)
- const [isOpen, toggleOpen] = useState(false)
- const [inputValue, setInputValue] = useState("");
+ // Recursive function to find an item by ID within the data hierarchy
+ function findItemById(list, idToFind) {
+ for (const item of list) {
+ if (item.id === idToFind) {
+ return item;
+ }
+ if (item.type === "category" && item.categoryContent) {
+ const foundItem = findItemById(item.categoryContent, idToFind);
+ if (foundItem) {
+ return foundItem;
+ }
+ }
+ }
+ return null;
+ }
+ // Find the initial selected item using the findItemById function
+ const foundItem = findItemById(data, 0);
- let searchAutorisation = false
+ // State to manage the currently selected item
+ const [selected, ChangeSelected] = useState(foundItem)
- const handleOpenClick = () => {
- toggleOpen(!isOpen)
- }
- const callbackFunction = (props) => {
- changeSelected(props)
- handleOpenClick()
+ // Callback function to handle item selection
+ const handleCallback = (id) => {
+ toggleOpen(false)
+ ChangeSelected(findItemById(data, id))
}
- useEffect(() => {
- setInputValue(selected.abbreviation ? selected.abbreviation : selected.display);
- }, [selected])
-
+
return (
-