no-frills-ui 0.0.14-alpha.0 → 0.0.14-alpha.1

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.
@@ -1,5 +1,7 @@
1
1
  interface ChipProps {
2
+ /** Label for the chip */
2
3
  label: string;
4
+ /** Callback when the close button is clicked */
3
5
  onCloseClick?: () => void;
4
6
  }
5
7
  export default function Chip(props: ChipProps): import("@emotion/react/jsx-runtime").JSX.Element;
@@ -15,6 +15,7 @@ import constants from '../../shared/constants';
15
15
  import { Close } from '../../icons';
16
16
  const Container = styled.div `
17
17
  padding: 5px;
18
+ padding-left: 15px;
18
19
  border-radius: 16px;
19
20
  background-color: var(--border-light-color, ${constants.BORDER_LIGHT_COLOR});
20
21
  display: inline-flex;
@@ -23,7 +24,7 @@ const Container = styled.div `
23
24
  align-items: center;
24
25
 
25
26
  &:focus-within {
26
- background-color: var(--light-grey, ${constants.LIGHT_GREY});
27
+ outline: 2px solid var(--primary-light, ${constants.PRIMARY_LIGHT});
27
28
  }
28
29
  `;
29
30
  const Button = styled.button `
@@ -42,6 +43,6 @@ export default function Chip(props) {
42
43
  onCloseClick === null || onCloseClick === void 0 ? void 0 : onCloseClick();
43
44
  }
44
45
  };
45
- return (_jsxs(Container, Object.assign({}, rest, { onKeyUp: keyUpHandler, children: [label, _jsx(Button, { onClick: onCloseClick, children: _jsx(Close, { height: 20, width: 20 }) })] })));
46
+ return (_jsxs(Container, Object.assign({}, rest, { onKeyUp: keyUpHandler, children: [label, _jsx(Button, { onClick: onCloseClick, "aria-label": `Remove ${label}`, children: _jsx(Close, { height: 20, width: 20 }) })] })));
46
47
  }
47
48
  //# sourceMappingURL=Chip.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Chip.js","sourceRoot":"","sources":["../../../src/components/Chip/Chip.tsx"],"names":[],"mappings":";;;;;;;;;;;;AACA,OAAO,MAAM,MAAM,iBAAiB,CAAC;AACrC,OAAO,SAAS,MAAM,wBAAwB,CAAC;AAC/C,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAOpC,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAA;;;kDAGsB,SAAS,CAAC,kBAAkB;;;;;;;8CAOhC,SAAS,CAAC,UAAU;;CAEjE,CAAC;AAEF,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAA;;+CAEmB,SAAS,CAAC,eAAe;;;;;;CAMvE,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,IAAI,CAAC,KAAgB;IACzC,MAAM,EAAE,KAAK,EAAE,YAAY,KAAc,KAAK,EAAd,IAAI,UAAK,KAAK,EAAxC,yBAAgC,CAAQ,CAAC;IAE/C,MAAM,YAAY,GAA8C,CAAC,CAAC,EAAE,EAAE;QAClE,IAAI,CAAC,CAAC,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,KAAK,EAAE,EAAE,CAAC;YACtC,YAAY,aAAZ,YAAY,uBAAZ,YAAY,EAAI,CAAC;QACrB,CAAC;IACL,CAAC,CAAA;IAED,OAAO,CACH,MAAC,SAAS,oBAAK,IAAI,IAAE,OAAO,EAAE,YAAY,aACrC,KAAK,EACN,KAAC,MAAM,IAAC,OAAO,EAAE,YAAY,YAAE,KAAC,KAAK,IAAC,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,GAAI,GAAS,KAChE,CACf,CAAC;AACN,CAAC"}
1
+ {"version":3,"file":"Chip.js","sourceRoot":"","sources":["../../../src/components/Chip/Chip.tsx"],"names":[],"mappings":";;;;;;;;;;;;AACA,OAAO,MAAM,MAAM,iBAAiB,CAAC;AACrC,OAAO,SAAS,MAAM,wBAAwB,CAAC;AAC/C,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AASpC,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAA;;;;kDAIsB,SAAS,CAAC,kBAAkB;;;;;;;kDAO5B,SAAS,CAAC,aAAa;;CAExE,CAAC;AAEF,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAA;;+CAEmB,SAAS,CAAC,eAAe;;;;;;CAMvE,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,IAAI,CAAC,KAAgB;IACzC,MAAM,EAAE,KAAK,EAAE,YAAY,KAAc,KAAK,EAAd,IAAI,UAAK,KAAK,EAAxC,yBAAgC,CAAQ,CAAC;IAE/C,MAAM,YAAY,GAA8C,CAAC,CAAC,EAAE,EAAE;QAClE,IAAI,CAAC,CAAC,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,KAAK,EAAE,EAAE,CAAC;YACtC,YAAY,aAAZ,YAAY,uBAAZ,YAAY,EAAI,CAAC;QACrB,CAAC;IACL,CAAC,CAAA;IAED,OAAO,CACH,MAAC,SAAS,oBAAK,IAAI,IAAE,OAAO,EAAE,YAAY,aACrC,KAAK,EACN,KAAC,MAAM,IAAC,OAAO,EAAE,YAAY,gBAAc,UAAU,KAAK,EAAE,YACxD,KAAC,KAAK,IAAC,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,GAAI,GAC3B,KACD,CACf,CAAC;AACN,CAAC"}
@@ -0,0 +1,33 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ type ChipInputProps = PropTypes.InferProps<typeof ChipInput.propTypes>;
4
+ /**
5
+ * A chip input component that allows users to add and remove chips (tags) by typing and pressing Enter.
6
+ * @component
7
+ * @example
8
+ * ```tsx
9
+ * <ChipInput
10
+ * value={['tag1', 'tag2']}
11
+ * onChange={(newTags) => console.log(newTags)}
12
+ * label="Add tags"
13
+ * errorText="At least one tag is required"
14
+ * />
15
+ * ```
16
+ */
17
+ declare function ChipInput(props: ChipInputProps & React.AllHTMLAttributes<HTMLInputElement>): import("@emotion/react/jsx-runtime").JSX.Element;
18
+ declare namespace ChipInput {
19
+ var propTypes: {
20
+ /** Label for the field */
21
+ label: PropTypes.Validator<string>;
22
+ /** Error message for the field */
23
+ errorText: PropTypes.Requireable<string>;
24
+ /** Values to display as chips */
25
+ value: PropTypes.Requireable<string[]>;
26
+ /** Callback when chips change */
27
+ onChange: PropTypes.Requireable<(...args: any[]) => any>;
28
+ };
29
+ var defaultProps: {
30
+ value: any[];
31
+ };
32
+ }
33
+ export default ChipInput;
@@ -0,0 +1,216 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
2
+ import React, { useEffect, useState } from 'react';
3
+ import PropTypes from 'prop-types';
4
+ import styled from '@emotion/styled';
5
+ import constants from '../../shared/constants';
6
+ import Chip from '../Chip/Chip';
7
+ import { DragAndDrop, ORIENTATION } from '../DragAndDrop';
8
+ // Label component for the ChipInput
9
+ const Label = styled.label `
10
+ display: inline-flex;
11
+ flex-direction: column;
12
+ flex: 1;
13
+ position: relative;
14
+ margin: 10px 5px;
15
+ color: inherit;
16
+ padding: 0 8px;
17
+ width: 250px;
18
+ border-radius: 3px;
19
+ border: 1px solid var(--border-color, ${constants.BORDER_COLOR});
20
+ background-color: var(--background, ${constants.BACKGROUND});
21
+
22
+ /** Focused */
23
+ &:has(:focus), &:has(:active) {
24
+ border-color: var(--primary, ${constants.PRIMARY});
25
+ box-shadow: 0 0 0 4px var(--primary-light, ${constants.PRIMARY_LIGHT});
26
+ }
27
+
28
+ &:has(:focus) > span, &:has(:active) > span {
29
+ color: var(--primary, ${constants.PRIMARY});
30
+ }
31
+
32
+ /** Disabled */
33
+ &:has(:disabled) {
34
+ border-color: var(--disabled-border, ${constants.DISABLED_BORDER});
35
+ background-color: var(--disabled-background, ${constants.DISABLED_BACKGROUND});
36
+ }
37
+
38
+ &:has(:disabled) > span {
39
+ color: #777;
40
+ }
41
+
42
+ /** Invalid */
43
+ &:has(:focus:invalid) {
44
+ border-color: var(--error, ${constants.ERROR});
45
+ box-shadow: 0 0 0 4px var(--error-light, ${constants.ERROR_LIGHT});
46
+ }
47
+
48
+ ${props => props.touched ? `
49
+ &:has(:invalid) {
50
+ border-color: var(--error, ${constants.ERROR});
51
+ }
52
+
53
+ &:has(:invalid) > span {
54
+ color: var(--error, ${constants.ERROR});
55
+ }
56
+ ` : ''}
57
+
58
+ /** Error */
59
+ ${props => props.errorText ? `
60
+ border-color: var(--error, ${constants.ERROR});
61
+
62
+ & > span {
63
+ color: var(--error, ${constants.ERROR});
64
+ }
65
+ ` : ''}
66
+
67
+ /** Required */
68
+ &:has(:required) > span:after {
69
+ content: '*';
70
+ margin-left: 2px;
71
+ color: var(--error, ${constants.ERROR});
72
+ }
73
+
74
+ & > input {
75
+ border: none;
76
+ outline: none;
77
+ width: 100%;
78
+ line-height: 30px;
79
+ min-height: 30px;
80
+ }
81
+
82
+ /** Label Animation */
83
+ & > span {
84
+ position: absolute;
85
+ padding: 0 5px;
86
+ top: 0px;
87
+ left: 4px;
88
+ font-size: 14px;
89
+ line-height: 32px;
90
+ transition: all 300ms ease;
91
+ }
92
+
93
+ &:has(:focus) > span, &:has(:placeholder-shown) > span {
94
+ top: -8px;
95
+ background: var(--background, ${constants.BACKGROUND});
96
+ font-size: 12px;
97
+ line-height: 14px;
98
+ }
99
+
100
+ ${props => props.text !== '' ? `
101
+ & > span {
102
+ top: -8px;
103
+ background: var(--background, ${constants.BACKGROUND});
104
+ font-size: 12px;
105
+ line-height: 14px;
106
+ }
107
+ ` : ''}
108
+ `;
109
+ // Error message container
110
+ const ErrorContainer = styled.div `
111
+ color: var(--error, ${constants.ERROR});
112
+ padding-top: 3px;
113
+ font-size: 12px;
114
+ line-height: 14px;
115
+ margin-left: 3px;
116
+ `;
117
+ /**
118
+ * A chip input component that allows users to add and remove chips (tags) by typing and pressing Enter.
119
+ * @component
120
+ * @example
121
+ * ```tsx
122
+ * <ChipInput
123
+ * value={['tag1', 'tag2']}
124
+ * onChange={(newTags) => console.log(newTags)}
125
+ * label="Add tags"
126
+ * errorText="At least one tag is required"
127
+ * />
128
+ * ```
129
+ */
130
+ export default function ChipInput(props) {
131
+ const [text, setText] = useState('');
132
+ const [touched, setTouched] = useState(false);
133
+ const [value, setValue] = useState(props.value);
134
+ const InputRef = React.useRef(null);
135
+ // Sync internal value with props.value
136
+ useEffect(() => {
137
+ setValue(props.value);
138
+ }, [props.value]);
139
+ /**
140
+ * Update the chip values and notify changes.
141
+ * @param newValue The new array of chip values
142
+ */
143
+ const updateValue = (newValue) => {
144
+ var _a;
145
+ const deduped = Array.from(new Set(newValue));
146
+ setValue(deduped);
147
+ (_a = props.onChange) === null || _a === void 0 ? void 0 : _a.call(props, deduped);
148
+ };
149
+ /**
150
+ * Marks the input as touched on focus.
151
+ * @param e React focus event
152
+ */
153
+ const handleFocus = (e) => {
154
+ setTouched(true);
155
+ if (props.onFocus) {
156
+ props.onFocus(e);
157
+ }
158
+ };
159
+ /**
160
+ * Change handler for the input field.
161
+ * @param e React change event
162
+ */
163
+ const handleChange = (e) => {
164
+ setText(e.target.value);
165
+ };
166
+ /**
167
+ * Adds a new chip on Enter key press.
168
+ * @param e React keyboard event
169
+ */
170
+ const handleKeyUp = (e) => {
171
+ if (e.key === 'Enter' && text.trim() !== '') {
172
+ const newValue = [...value, text.trim()];
173
+ updateValue(newValue);
174
+ setText('');
175
+ }
176
+ };
177
+ /**
178
+ * Removes a chip from the list.
179
+ * @param chipToRemove The chip value to remove
180
+ */
181
+ const removeChip = (chipToRemove) => {
182
+ const newValue = value.filter(chip => chip !== chipToRemove);
183
+ updateValue(newValue);
184
+ };
185
+ /**
186
+ * Moves a chip from one position to another.
187
+ * @param start The starting index of the item to move
188
+ * @param end The ending index where the item should be placed
189
+ */
190
+ const onDrop = (start, end) => {
191
+ // Clone existing elements
192
+ const newItems = [...value];
193
+ // Remove the element to be moved
194
+ const item = newItems.splice(start, 1);
195
+ // Add it back at the required position
196
+ newItems.splice(end, 0, item[0]);
197
+ // Update
198
+ updateValue(newItems);
199
+ };
200
+ // Render the component
201
+ return (_jsxs(Label, { text: text, touched: touched, errorText: props.errorText, children: [_jsx("input", Object.assign({}, props, { ref: InputRef, type: "text", value: text, onChange: handleChange, onFocus: handleFocus, onKeyUp: handleKeyUp, required: props.required && value.length === 0 })), _jsx("div", { children: (value === null || value === void 0 ? void 0 : value.length) > 0 && (_jsx(DragAndDrop, { orientation: ORIENTATION.HORIZONTAL, onDrop: onDrop, children: value.map((chip) => (_jsx(Chip, { label: chip, onCloseClick: () => removeChip(chip) }, chip))) })) }), _jsx("span", { children: props.label }), props.errorText && _jsx(ErrorContainer, { children: props.errorText })] }));
202
+ }
203
+ ChipInput.propTypes = {
204
+ /** Label for the field */
205
+ label: PropTypes.string.isRequired,
206
+ /** Error message for the field */
207
+ errorText: PropTypes.string,
208
+ /** Values to display as chips */
209
+ value: PropTypes.arrayOf(PropTypes.string),
210
+ /** Callback when chips change */
211
+ onChange: PropTypes.func,
212
+ };
213
+ ChipInput.defaultProps = {
214
+ value: [],
215
+ };
216
+ //# sourceMappingURL=ChipInput.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChipInput.js","sourceRoot":"","sources":["../../../src/components/ChipInput/ChipInput.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export { default as ChipInput } from './ChipInput';
@@ -0,0 +1,2 @@
1
+ export { default as ChipInput } from './ChipInput';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/ChipInput/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,aAAa,CAAC"}
@@ -8,10 +8,37 @@ type DragAndDropProps = {
8
8
  /** Shows drag indicator against each list item */
9
9
  showIndicator: boolean;
10
10
  } & PropsWithChildren<{}>;
11
+ /**
12
+ * A drag and drop container component that enables reordering of child elements.
13
+ *
14
+ * @component
15
+ * @example
16
+ * ```tsx
17
+ * <DragAndDrop
18
+ * orientation={ORIENTATION.VERTICAL}
19
+ * onDrop={(start, end) => handleReorder(start, end)}
20
+ * showIndicator={true}
21
+ * >
22
+ * <div>Item 1</div>
23
+ * <div>Item 2</div>
24
+ * <div>Item 3</div>
25
+ * </DragAndDrop>
26
+ * ```
27
+ *
28
+ * @param {DragAndDropProps} props - The component props
29
+ * @param {ORIENTATION} props.orientation - Determines the layout direction (horizontal or vertical). Defaults to VERTICAL.
30
+ * @param {(start: number, end: number) => void} props.onDrop - Callback fired when an item is dropped, receives the start and end indices
31
+ * @param {boolean} props.showIndicator - Whether to display drag indicators for each list item. Defaults to false.
32
+ * @param {React.ReactNode} props.children - Child elements to be rendered as draggable items
33
+ *
34
+ * @returns {JSX.Element} A draggable container with reorderable items
35
+ */
11
36
  declare function DragAndDrop(props: DragAndDropProps): import("@emotion/react/jsx-runtime").JSX.Element;
12
37
  declare namespace DragAndDrop {
13
38
  var defaultProps: {
39
+ /** Orientation of the list layout */
14
40
  orientation: ORIENTATION;
41
+ /** Whether to display drag indicators for each list item */
15
42
  showIndicator: boolean;
16
43
  };
17
44
  }
@@ -3,23 +3,59 @@ import React, { useState } from 'react';
3
3
  import styled from '@emotion/styled';
4
4
  import DragItem from './DragItem';
5
5
  import { ORIENTATION, DragContext } from './types';
6
+ /** Container Component */
6
7
  const Container = styled.div `
7
8
  flex: 1;
8
9
  display: flex;
9
10
  position: relative;
11
+ flex-wrap: wrap;
10
12
  flex-direction: ${props => props.orientation === ORIENTATION.HORIZONTAL ? 'row' : 'column'};
11
13
  `;
14
+ /**
15
+ * A drag and drop container component that enables reordering of child elements.
16
+ *
17
+ * @component
18
+ * @example
19
+ * ```tsx
20
+ * <DragAndDrop
21
+ * orientation={ORIENTATION.VERTICAL}
22
+ * onDrop={(start, end) => handleReorder(start, end)}
23
+ * showIndicator={true}
24
+ * >
25
+ * <div>Item 1</div>
26
+ * <div>Item 2</div>
27
+ * <div>Item 3</div>
28
+ * </DragAndDrop>
29
+ * ```
30
+ *
31
+ * @param {DragAndDropProps} props - The component props
32
+ * @param {ORIENTATION} props.orientation - Determines the layout direction (horizontal or vertical). Defaults to VERTICAL.
33
+ * @param {(start: number, end: number) => void} props.onDrop - Callback fired when an item is dropped, receives the start and end indices
34
+ * @param {boolean} props.showIndicator - Whether to display drag indicators for each list item. Defaults to false.
35
+ * @param {React.ReactNode} props.children - Child elements to be rendered as draggable items
36
+ *
37
+ * @returns {JSX.Element} A draggable container with reorderable items
38
+ */
12
39
  export default function DragAndDrop(props) {
13
40
  const { orientation, children, onDrop, showIndicator } = props;
14
41
  const [startIndex, setStartIndex] = useState(null);
42
+ const [isDragging, setIsDragging] = useState(false);
43
+ const [dragOver, setDragOver] = useState(null);
44
+ /**
45
+ * Drop handler invoked when a draggable item is released.
46
+ * @param index
47
+ */
15
48
  const drop = (index) => {
16
49
  startIndex !== null && (onDrop === null || onDrop === void 0 ? void 0 : onDrop(startIndex, index));
17
50
  setStartIndex(null);
51
+ setIsDragging(false);
18
52
  };
19
- return (_jsx(DragContext.Provider, { value: { startIndex, setStartIndex, drop }, children: _jsx(Container, { orientation: orientation, children: React.Children.map(children, (child, index) => (_jsx(DragItem, { index: index, orientation: orientation, showIndicator: showIndicator, children: child }))) }) }));
53
+ return (_jsx(DragContext.Provider, { value: { startIndex, setStartIndex, drop, isDragging, setIsDragging, setDragOver }, children: _jsx(Container, { orientation: orientation, children: React.Children.map(children, (child, index) => (_jsx(DragItem, { index: index, orientation: orientation, showIndicator: showIndicator, dragOver: dragOver, children: child }))) }) }));
20
54
  }
21
55
  DragAndDrop.defaultProps = {
56
+ /** Orientation of the list layout */
22
57
  orientation: ORIENTATION.VERTICAL,
58
+ /** Whether to display drag indicators for each list item */
23
59
  showIndicator: false,
24
60
  };
25
61
  //# sourceMappingURL=DragAndDrop.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DragAndDrop.js","sourceRoot":"","sources":["../../../src/components/DragAndDrop/DragAndDrop.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,EAAqB,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC3D,OAAO,MAAM,MAAM,iBAAiB,CAAC;AACrC,OAAO,QAAQ,MAAM,YAAY,CAAC;AAClC,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAWnD,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAA4B;;;;sBAIlC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,KAAK,WAAW,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ;CAC7F,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,KAAuB;IACvD,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,GAAG,KAAK,CAAC;IAC/D,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAS,IAAI,CAAC,CAAC;IAE3D,MAAM,IAAI,GAAG,CAAC,KAAa,EAAE,EAAE;QAC3B,UAAU,KAAK,IAAI,KAAI,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAG,UAAU,EAAE,KAAK,CAAC,CAAA,CAAC;QACnD,aAAa,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC,CAAA;IAED,OAAO,CAAC,KAAC,WAAW,CAAC,QAAQ,IAAC,KAAK,EAAE,EAAE,UAAU,EAAE,aAAa,EAAE,IAAI,EAAE,YACpE,KAAC,SAAS,IAAC,WAAW,EAAE,WAAW,YAC9B,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CAC5C,KAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,aAAa,EAAE,aAAa,YACzE,KAAK,GACC,CACd,CAAC,GACM,GACO,CAAC,CAAC;AAC7B,CAAC;AAED,WAAW,CAAC,YAAY,GAAG;IACvB,WAAW,EAAE,WAAW,CAAC,QAAQ;IACjC,aAAa,EAAE,KAAK;CACvB,CAAA"}
1
+ {"version":3,"file":"DragAndDrop.js","sourceRoot":"","sources":["../../../src/components/DragAndDrop/DragAndDrop.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,EAAqB,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC3D,OAAO,MAAM,MAAM,iBAAiB,CAAC;AACrC,OAAO,QAAQ,MAAM,YAAY,CAAC;AAClC,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAWnD,0BAA0B;AAC1B,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAA4B;;;;;sBAKlC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,KAAK,WAAW,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ;CAC7F,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,KAAuB;IACvD,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,GAAG,KAAK,CAAC;IAC/D,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAS,IAAI,CAAC,CAAC;IAC3D,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAU,KAAK,CAAC,CAAC;IAC7D,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAS,IAAI,CAAC,CAAC;IAEvD;;;OAGG;IACH,MAAM,IAAI,GAAG,CAAC,KAAa,EAAE,EAAE;QAC3B,UAAU,KAAK,IAAI,KAAI,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAG,UAAU,EAAE,KAAK,CAAC,CAAA,CAAC;QACnD,aAAa,CAAC,IAAI,CAAC,CAAC;QACpB,aAAa,CAAC,KAAK,CAAC,CAAC;IACzB,CAAC,CAAA;IAED,OAAO,CAAC,KAAC,WAAW,CAAC,QAAQ,IAAC,KAAK,EAAE,EAAE,UAAU,EAAE,aAAa,EAAE,IAAI,EAAE,UAAU,EAAE,aAAa,EAAE,WAAW,EAAE,YAC5G,KAAC,SAAS,IAAC,WAAW,EAAE,WAAW,YAC9B,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CAC5C,KAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,aAAa,EAAE,aAAa,EAAE,QAAQ,EAAE,QAAQ,YAC7F,KAAK,GACC,CACd,CAAC,GACM,GACO,CAAC,CAAC;AAC7B,CAAC;AAED,WAAW,CAAC,YAAY,GAAG;IACvB,qCAAqC;IACrC,WAAW,EAAE,WAAW,CAAC,QAAQ;IACjC,4DAA4D;IAC5D,aAAa,EAAE,KAAK;CACvB,CAAA"}
@@ -1,9 +1,46 @@
1
1
  import { PropsWithChildren } from 'react';
2
2
  import { ORIENTATION } from './types';
3
3
  interface DragItemProps {
4
+ /** Position index of the draggable item */
4
5
  index: number;
6
+ /** Orientation of the drag operation (VERTICAL or HORIZONTAL) */
5
7
  orientation: ORIENTATION;
8
+ /** Whether to show a drag handle indicator instead of making the entire item draggable */
6
9
  showIndicator: boolean;
10
+ /** The index of the item currently being dragged over */
11
+ dragOver: number;
7
12
  }
13
+ /**
14
+ * A draggable item component that supports both mouse and touch interactions for drag-and-drop functionality.
15
+ *
16
+ * @component
17
+ * @example
18
+ * ```tsx
19
+ * <DragItem
20
+ * index={0}
21
+ * orientation={ORIENTATION.VERTICAL}
22
+ * showIndicator={true}
23
+ * dragOver={-1}
24
+ * >
25
+ * <div>Draggable content</div>
26
+ * </DragItem>
27
+ * ```
28
+ *
29
+ * @param props - The component props
30
+ * @param props.index - The position index of this item in the draggable list
31
+ * @param props.orientation - The orientation of the drag operation (VERTICAL or HORIZONTAL)
32
+ * @param props.showIndicator - Whether to show a drag handle indicator instead of making the entire item draggable
33
+ * @param props.dragOver - The index of the item currently being dragged over
34
+ * @param props.children - The content to be rendered inside the draggable item
35
+ *
36
+ * @remarks
37
+ * - Uses the DragContext to manage drag state across items
38
+ * - Provides visual feedback with borders during drag operations
39
+ * - Supports haptic feedback (vibration) on touch devices
40
+ * - For touch devices, requires a 200ms hold before drag starts
41
+ * - When showIndicator is true, only the drag handle can initiate drag operations
42
+ *
43
+ * @returns A draggable item with optional drag indicator and visual feedback
44
+ */
8
45
  export default function DragItem(props: PropsWithChildren<DragItemProps>): import("@emotion/react/jsx-runtime").JSX.Element;
9
46
  export {};
@@ -1,12 +1,14 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
2
- import { useContext, useState } from 'react';
2
+ import { useContext, useState, useEffect } from 'react';
3
3
  import styled from '@emotion/styled';
4
4
  import constants from '../../shared/constants';
5
5
  import { ORIENTATION, DragContext } from './types';
6
6
  import { DragIndicator } from '../../icons';
7
+ /** Styled component for the draggable item container */
7
8
  const Item = styled.div `
8
9
  cursor: ${props => props.showIndicator ? 'default' : 'move'};
9
10
  display: flex;
11
+ user-select: ${props => props.showIndicator ? 'auto' : 'none'};
10
12
  border-top: 2px solid ${props => props.orientation === ORIENTATION.VERTICAL && props.active > 0
11
13
  ? constants.PRIMARY : 'transparent'};
12
14
  border-bottom: 2px solid ${props => props.orientation === ORIENTATION.VERTICAL && props.active < 0
@@ -15,35 +17,171 @@ const Item = styled.div `
15
17
  ? constants.PRIMARY : 'transparent'};
16
18
  border-right: 2px solid ${props => props.orientation === ORIENTATION.HORIZONTAL && props.active < 0
17
19
  ? constants.PRIMARY : 'transparent'};
20
+ opacity: ${props => props.dragging ? 0.5 : 1};
18
21
  `;
22
+ /** Styled component for the drag handle indicator */
19
23
  const DragKnob = styled.div `
20
24
  padding-top: 8px;
21
25
  cursor: move;
26
+ touch-action: none;
22
27
  color: var(--disabled, ${constants.DISABLED});
23
28
  `;
29
+ /** Container for the children */
24
30
  const Container = styled.div `
25
31
  flex: 1;
26
32
  `;
33
+ /**
34
+ * A draggable item component that supports both mouse and touch interactions for drag-and-drop functionality.
35
+ *
36
+ * @component
37
+ * @example
38
+ * ```tsx
39
+ * <DragItem
40
+ * index={0}
41
+ * orientation={ORIENTATION.VERTICAL}
42
+ * showIndicator={true}
43
+ * dragOver={-1}
44
+ * >
45
+ * <div>Draggable content</div>
46
+ * </DragItem>
47
+ * ```
48
+ *
49
+ * @param props - The component props
50
+ * @param props.index - The position index of this item in the draggable list
51
+ * @param props.orientation - The orientation of the drag operation (VERTICAL or HORIZONTAL)
52
+ * @param props.showIndicator - Whether to show a drag handle indicator instead of making the entire item draggable
53
+ * @param props.dragOver - The index of the item currently being dragged over
54
+ * @param props.children - The content to be rendered inside the draggable item
55
+ *
56
+ * @remarks
57
+ * - Uses the DragContext to manage drag state across items
58
+ * - Provides visual feedback with borders during drag operations
59
+ * - Supports haptic feedback (vibration) on touch devices
60
+ * - For touch devices, requires a 200ms hold before drag starts
61
+ * - When showIndicator is true, only the drag handle can initiate drag operations
62
+ *
63
+ * @returns A draggable item with optional drag indicator and visual feedback
64
+ */
27
65
  export default function DragItem(props) {
28
- const { index, orientation, children, showIndicator } = props;
66
+ const { index, orientation, children, showIndicator, dragOver } = props;
29
67
  const [active, setActive] = useState(0);
68
+ const [touchTimer, setTouchTimer] = useState(null);
30
69
  const context = useContext(DragContext);
70
+ /**
71
+ * Vibrate the device for haptic feedback
72
+ * @param duration Duration of the vibration in milliseconds
73
+ */
74
+ const vibrate = (duration) => {
75
+ if (navigator.vibrate) {
76
+ navigator.vibrate(duration);
77
+ }
78
+ };
79
+ /**
80
+ * Drag start event handler
81
+ * @param e Event
82
+ */
31
83
  const dragStartHandler = (e) => {
32
84
  context.setStartIndex(index);
85
+ context.setIsDragging(true);
33
86
  };
87
+ /**
88
+ * Drag over event handler
89
+ * @param e Event
90
+ */
34
91
  const dragOverHandler = (e) => {
35
92
  e.preventDefault();
36
93
  e.stopPropagation();
37
94
  setActive(context.startIndex - index);
38
95
  };
96
+ /**
97
+ * Drag leave event handler
98
+ */
39
99
  const dragExitHandler = () => {
40
100
  setActive(0);
41
101
  };
102
+ /**
103
+ * Drop event handler
104
+ * @param e Event
105
+ */
42
106
  const dropHandler = (e) => {
43
107
  e.preventDefault();
44
108
  setActive(0);
45
109
  context.drop(index);
110
+ context.setIsDragging(false);
111
+ };
112
+ /**
113
+ * Touch start event handler
114
+ * @param e Event
115
+ */
116
+ const touchStartHandler = (e) => {
117
+ const timer = setTimeout(() => {
118
+ context.setStartIndex(index);
119
+ context.setIsDragging(true);
120
+ context.setDragOver(index);
121
+ document.body.style.overflow = 'hidden';
122
+ vibrate(50);
123
+ }, 200);
124
+ setTouchTimer(timer);
125
+ };
126
+ /**
127
+ * Touch move event handler
128
+ * @param e Event
129
+ * @returns void
130
+ */
131
+ const touchMoveHandler = (e) => {
132
+ var _a;
133
+ const touch = e.touches[0];
134
+ if (!touch)
135
+ return;
136
+ if (context.isDragging) {
137
+ e.preventDefault();
138
+ // get the element under the touch point
139
+ const el = document.elementFromPoint(touch.clientX, touch.clientY);
140
+ const overAttr = (_a = el === null || el === void 0 ? void 0 : el.closest('[data-drag-index]')) === null || _a === void 0 ? void 0 : _a.getAttribute('data-drag-index');
141
+ const overIndex = overAttr != null ? parseInt(overAttr, 10) : null;
142
+ // if we know which index we're over, update visual state
143
+ if (overIndex !== null) {
144
+ context.setDragOver(overIndex);
145
+ }
146
+ }
147
+ else if (touchTimer) {
148
+ clearTimeout(touchTimer);
149
+ setTouchTimer(null);
150
+ }
151
+ };
152
+ /**
153
+ * Touch end event handler
154
+ * @param e Event
155
+ */
156
+ const touchEndHandler = (e) => {
157
+ if (touchTimer) {
158
+ clearTimeout(touchTimer);
159
+ setTouchTimer(null);
160
+ }
161
+ if (context.isDragging) {
162
+ context.drop(dragOver);
163
+ vibrate(50);
164
+ context.setIsDragging(false);
165
+ document.body.style.overflow = 'auto';
166
+ }
46
167
  };
47
- return _jsxs(Item, { draggable: !showIndicator, showIndicator: showIndicator, active: active, orientation: orientation, onDragStart: !showIndicator && dragStartHandler, onDragOver: dragOverHandler, onDragLeave: dragExitHandler, onDrop: dropHandler, children: [showIndicator && _jsx(DragKnob, { draggable: true, onDragStart: dragStartHandler, children: _jsx(DragIndicator, {}) }), _jsx(Container, { children: children })] });
168
+ /** Cleanup touch timer on unmount */
169
+ useEffect(() => {
170
+ return () => {
171
+ if (touchTimer)
172
+ clearTimeout(touchTimer);
173
+ document.body.style.overflow = 'auto';
174
+ };
175
+ }, [touchTimer]);
176
+ /** Update active state based on dragOver changes */
177
+ useEffect(() => {
178
+ if (context.isDragging && dragOver === index) {
179
+ setActive(context.startIndex - index);
180
+ }
181
+ else {
182
+ setActive(0);
183
+ }
184
+ }, [dragOver, context.startIndex, index, context.isDragging]);
185
+ return _jsxs(Item, { draggable: !showIndicator, showIndicator: showIndicator, active: active, dragging: context.isDragging && context.startIndex === index, orientation: orientation, "data-drag-index": index, onDragStart: !showIndicator ? dragStartHandler : undefined, onDragOver: dragOverHandler, onDragLeave: dragExitHandler, onDrop: dropHandler, onTouchStart: !showIndicator ? touchStartHandler : undefined, onTouchMove: touchMoveHandler, onTouchEnd: touchEndHandler, onTouchCancel: touchEndHandler, children: [showIndicator && _jsx(DragKnob, { draggable: true, onDragStart: dragStartHandler, onTouchStart: touchStartHandler, children: _jsx(DragIndicator, {}) }), _jsx(Container, { children: children })] });
48
186
  }
49
187
  //# sourceMappingURL=DragItem.js.map