@agility/plenum-ui 2.0.0-rc36 → 2.0.0-rc37
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.
- package/dist/index.js +1 -1
- package/dist/index.js.map +3 -3
- package/dist/tailwind.css +1 -0
- package/package.json +1 -1
- package/stories/atoms/buttons/Button/Button.tsx +2 -2
- package/stories/organisms/DropdownComponent/DropdownComponent.tsx +182 -169
- package/stories/organisms/DropdownComponent/dropdownItems.ts +3 -6
package/dist/tailwind.css
CHANGED
|
@@ -480,6 +480,7 @@ input::placeholder,textarea::placeholder {
|
|
|
480
480
|
|
|
481
481
|
::-webkit-date-and-time-value {
|
|
482
482
|
min-height: 1.5em;
|
|
483
|
+
text-align: inherit;
|
|
483
484
|
}
|
|
484
485
|
|
|
485
486
|
::-webkit-datetime-edit,::-webkit-datetime-edit-year-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-meridiem-field {
|
package/package.json
CHANGED
|
@@ -74,7 +74,7 @@ const _Button = (
|
|
|
74
74
|
target: asLink.target,
|
|
75
75
|
title: asLink.title,
|
|
76
76
|
className: cn(
|
|
77
|
-
"inline-flex items-center justify-center gap-x-2 font-medium rounded-[3px] !ring-offset-white outline-none focus-visible:ring-2 focus-visible:ring-purple-600 focus-visible:ring-offset-2 focus-within:ring-2 focus-within:ring-purple-600 focus-within:ring-offset-2 focus:ring-2 focus:ring-purple-600 focus:ring-offset-2 active:ring-2 active:ring-purple-600 active:ring-offset-2 transition-all",
|
|
77
|
+
"inline-flex items-center justify-center gap-x-2 font-medium p-2 rounded-[3px] !ring-offset-white outline-none focus-visible:ring-2 focus-visible:ring-purple-600 focus-visible:ring-offset-2 focus-within:ring-2 focus-within:ring-purple-600 focus-within:ring-offset-2 focus:ring-2 focus:ring-purple-600 focus:ring-offset-2 active:ring-2 active:ring-purple-600 active:ring-offset-2 transition-all",
|
|
78
78
|
{ "w-full": fullWidth },
|
|
79
79
|
{ "px-[11px] py-[7px] text-xs": size === "xs" },
|
|
80
80
|
{ "px-[13px] py-[9px] text-sm": size === "sm" },
|
|
@@ -149,7 +149,7 @@ const _Button = (
|
|
|
149
149
|
<button
|
|
150
150
|
type="button"
|
|
151
151
|
className={cn(
|
|
152
|
-
"inline-flex items-center justify-center gap-x-2 font-medium rounded-[3px] !ring-offset-white outline-none focus-visible:ring-2 focus-visible:ring-purple-600 focus-visible:ring-offset-2 focus-within:ring-2 focus-within:ring-purple-600 focus-within:ring-offset-2 focus:ring-2 focus:ring-purple-600 focus:ring-offset-2 active:ring-2 active:ring-purple-600 active:ring-offset-2 transition-all",
|
|
152
|
+
"inline-flex items-center justify-center gap-x-2 font-medium p-2 rounded-[3px] !ring-offset-white outline-none focus-visible:ring-2 focus-visible:ring-purple-600 focus-visible:ring-offset-2 focus-within:ring-2 focus-within:ring-purple-600 focus-within:ring-offset-2 focus:ring-2 focus:ring-purple-600 focus:ring-offset-2 active:ring-2 active:ring-purple-600 active:ring-offset-2 transition-all",
|
|
153
153
|
{ "w-full": fullWidth },
|
|
154
154
|
{ "px-[11px] py-[7px] text-xs": size === "xs" },
|
|
155
155
|
{ "px-[13px] py-[9px] text-sm": size === "sm" },
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { HTMLAttributes, useState } from "react"
|
|
1
|
+
import React, { HTMLAttributes, useEffect, useMemo, useRef, useState } from "react"
|
|
2
2
|
import { default as cn } from "classnames"
|
|
3
3
|
import {
|
|
4
4
|
useFloating,
|
|
@@ -12,12 +12,15 @@ import {
|
|
|
12
12
|
autoPlacement,
|
|
13
13
|
shift,
|
|
14
14
|
FloatingPortal,
|
|
15
|
+
FloatingList,
|
|
15
16
|
useTransitionStyles,
|
|
16
|
-
Placement
|
|
17
|
+
Placement,
|
|
18
|
+
useListNavigation
|
|
17
19
|
} from "@floating-ui/react"
|
|
18
20
|
|
|
19
21
|
import { ClassNameWithAutocomplete } from "utils/types"
|
|
20
22
|
import { DynamicIcon, IDynamicIconProps, UnifiedIconName } from "@/stories/atoms/icons"
|
|
23
|
+
import { list } from "postcss"
|
|
21
24
|
|
|
22
25
|
export interface IItemProp {
|
|
23
26
|
//Don't think this needs to extend HtmlButton... extends HTMLAttributes<HTMLButtonElement> {
|
|
@@ -83,11 +86,19 @@ const Dropdown: React.FC<IDropdownProps> = ({
|
|
|
83
86
|
}: IDropdownProps): JSX.Element | null => {
|
|
84
87
|
const [isOpen, setIsOpen] = useState(false)
|
|
85
88
|
const [activeItem, setActiveItem] = useState<React.Key | null>(null)
|
|
89
|
+
const [activeIndex, setActiveIndex] = useState<number | null>(null)
|
|
90
|
+
|
|
91
|
+
const listRef = useRef<(HTMLButtonElement | null)[]>([])
|
|
86
92
|
|
|
87
93
|
// Floating UI logic
|
|
88
94
|
const { refs, floatingStyles, context } = useFloating({
|
|
89
95
|
open: isOpen,
|
|
90
|
-
onOpenChange:
|
|
96
|
+
onOpenChange: (bool) => {
|
|
97
|
+
console.log("onOpenChange", bool)
|
|
98
|
+
listRef.current = []
|
|
99
|
+
setActiveIndex(null)
|
|
100
|
+
setIsOpen(bool)
|
|
101
|
+
},
|
|
91
102
|
placement,
|
|
92
103
|
middleware: [
|
|
93
104
|
offset(offsetOptions ?? 10),
|
|
@@ -101,20 +112,157 @@ const Dropdown: React.FC<IDropdownProps> = ({
|
|
|
101
112
|
const click = useClick(context)
|
|
102
113
|
const dismiss = useDismiss(context)
|
|
103
114
|
const role = useRole(context)
|
|
104
|
-
const
|
|
115
|
+
const listNavigation = useListNavigation(context, {
|
|
116
|
+
listRef,
|
|
117
|
+
activeIndex,
|
|
118
|
+
onNavigate: (index) => {
|
|
119
|
+
if (index !== null && listRef.current[index]) {
|
|
120
|
+
setActiveIndex(index)
|
|
121
|
+
listRef.current[index]?.focus()
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
const { getReferenceProps, getFloatingProps, getItemProps } = useInteractions([
|
|
127
|
+
click,
|
|
128
|
+
dismiss,
|
|
129
|
+
role,
|
|
130
|
+
listNavigation
|
|
131
|
+
])
|
|
132
|
+
|
|
133
|
+
const ItemComponents = useMemo(
|
|
134
|
+
() =>
|
|
135
|
+
items.map((itemStack, stackIndex) => {
|
|
136
|
+
return itemStack.map((item, itemIndex) => {
|
|
137
|
+
const { key, label, icon, iconObj, iconPosition, isEmphasized, onClick, ...rest } = item
|
|
138
|
+
const active = activeItem && activeItem === key
|
|
139
|
+
const itemClass = cn(
|
|
140
|
+
defaultClassNames.itemClassname,
|
|
141
|
+
itemClassname,
|
|
142
|
+
"group flex cursor-pointer items-center px-4 py-2 text-sm transition-all",
|
|
143
|
+
{
|
|
144
|
+
"text-red-500": isEmphasized
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
"text-gray-900": !isEmphasized
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
"bg-gray-100 text-gray-900": active
|
|
151
|
+
},
|
|
152
|
+
active ? cn(defaultClassNames.activeItemClassname, activeItemClassname) : "",
|
|
153
|
+
{
|
|
154
|
+
"bg-gray-100 text-red-500 hover:text-red-500": active && isEmphasized
|
|
155
|
+
}
|
|
156
|
+
)
|
|
157
|
+
return (
|
|
158
|
+
<button
|
|
159
|
+
{...{
|
|
160
|
+
onClick: () => {
|
|
161
|
+
onClick && onClick()
|
|
162
|
+
setTimeout(() => {
|
|
163
|
+
//hide the dropdown after click
|
|
164
|
+
setIsOpen(false)
|
|
165
|
+
}, 150)
|
|
166
|
+
},
|
|
167
|
+
key: key,
|
|
168
|
+
id: key.toString(),
|
|
169
|
+
className: cn(itemClass, "w-full"),
|
|
170
|
+
...rest,
|
|
171
|
+
...getItemProps()
|
|
172
|
+
}}
|
|
173
|
+
ref={(node) => {
|
|
174
|
+
//If the list ref already contains a node with the same id do nothing, otherwise add it
|
|
175
|
+
if (listRef.current.some((item) => item?.id === key)) {
|
|
176
|
+
return
|
|
177
|
+
}
|
|
178
|
+
listRef.current.push(node)
|
|
179
|
+
}}
|
|
180
|
+
key={key}
|
|
181
|
+
>
|
|
182
|
+
<div className={cn(defaultClassNames.iconSpacingClassname, iconSpacingClassname)}>
|
|
183
|
+
{iconObj && (iconPosition === "leading" || iconPosition === undefined) && (
|
|
184
|
+
<>{iconObj}</>
|
|
185
|
+
)}
|
|
186
|
+
{icon &&
|
|
187
|
+
(iconPosition === "leading" || iconPosition === undefined) &&
|
|
188
|
+
(typeof icon === "string" ? (
|
|
189
|
+
<DynamicIcon
|
|
190
|
+
{...{
|
|
191
|
+
icon: icon,
|
|
192
|
+
className: cn(
|
|
193
|
+
{
|
|
194
|
+
"text-red-500": isEmphasized
|
|
195
|
+
},
|
|
196
|
+
"opacity-60 group"
|
|
197
|
+
)
|
|
198
|
+
}}
|
|
199
|
+
/>
|
|
200
|
+
) : (
|
|
201
|
+
<DynamicIcon
|
|
202
|
+
{...{
|
|
203
|
+
...icon,
|
|
204
|
+
className: cn(
|
|
205
|
+
icon.className,
|
|
206
|
+
{
|
|
207
|
+
"text-red-500": isEmphasized
|
|
208
|
+
},
|
|
209
|
+
"opacity-60 group"
|
|
210
|
+
)
|
|
211
|
+
}}
|
|
212
|
+
/>
|
|
213
|
+
))}
|
|
214
|
+
<div className="whitespace-nowrap">{label}</div>
|
|
215
|
+
{iconObj && iconPosition === "trailing" && <>{iconObj}</>}
|
|
216
|
+
{icon &&
|
|
217
|
+
iconPosition === "trailing" &&
|
|
218
|
+
(typeof icon === "string" ? (
|
|
219
|
+
<DynamicIcon
|
|
220
|
+
{...{
|
|
221
|
+
icon: icon,
|
|
222
|
+
className: cn(
|
|
223
|
+
{
|
|
224
|
+
"text-red-500": isEmphasized
|
|
225
|
+
},
|
|
226
|
+
"opacity-60 group"
|
|
227
|
+
)
|
|
228
|
+
}}
|
|
229
|
+
/>
|
|
230
|
+
) : (
|
|
231
|
+
<DynamicIcon
|
|
232
|
+
{...{
|
|
233
|
+
...icon,
|
|
234
|
+
className: cn(
|
|
235
|
+
icon.className,
|
|
236
|
+
{
|
|
237
|
+
"text-red-500": isEmphasized
|
|
238
|
+
},
|
|
239
|
+
"opacity-60 group"
|
|
240
|
+
)
|
|
241
|
+
}}
|
|
242
|
+
/>
|
|
243
|
+
))}
|
|
244
|
+
</div>
|
|
245
|
+
</button>
|
|
246
|
+
)
|
|
247
|
+
})
|
|
248
|
+
}),
|
|
249
|
+
[activeItem, activeItemClassname, getItemProps, iconSpacingClassname, itemClassname, items]
|
|
250
|
+
)
|
|
251
|
+
|
|
105
252
|
const { isMounted, styles: transitionStyles } = useTransitionStyles(context, {
|
|
106
253
|
duration: {
|
|
107
254
|
open: 200,
|
|
108
255
|
close: 200
|
|
109
256
|
},
|
|
110
257
|
initial: {
|
|
111
|
-
opacity: 0
|
|
258
|
+
opacity: 0,
|
|
259
|
+
scale: 95
|
|
112
260
|
},
|
|
113
261
|
open: {
|
|
114
|
-
opacity: 1
|
|
262
|
+
opacity: 1,
|
|
263
|
+
scale: 100
|
|
115
264
|
}
|
|
116
265
|
})
|
|
117
|
-
|
|
118
266
|
return (
|
|
119
267
|
<div
|
|
120
268
|
{...{
|
|
@@ -152,168 +300,33 @@ const Dropdown: React.FC<IDropdownProps> = ({
|
|
|
152
300
|
</button>
|
|
153
301
|
|
|
154
302
|
{isMounted && items.length > 0 && isOpen && (
|
|
155
|
-
<
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
icon,
|
|
183
|
-
iconPosition,
|
|
184
|
-
iconObj,
|
|
185
|
-
...rest
|
|
186
|
-
},
|
|
187
|
-
idx
|
|
188
|
-
) => {
|
|
189
|
-
const active = activeItem && activeItem === key
|
|
190
|
-
const itemClass = cn(
|
|
191
|
-
defaultClassNames.itemClassname,
|
|
192
|
-
itemClassname,
|
|
193
|
-
"group flex cursor-pointer items-center px-4 py-2 text-sm transition-all",
|
|
194
|
-
{
|
|
195
|
-
"text-red-500": isEmphasized
|
|
196
|
-
},
|
|
197
|
-
{
|
|
198
|
-
"text-gray-900": !isEmphasized
|
|
199
|
-
},
|
|
200
|
-
{
|
|
201
|
-
"bg-gray-100 text-gray-900": active
|
|
202
|
-
},
|
|
203
|
-
active
|
|
204
|
-
? cn(
|
|
205
|
-
defaultClassNames.activeItemClassname,
|
|
206
|
-
activeItemClassname
|
|
207
|
-
)
|
|
208
|
-
: "",
|
|
209
|
-
{
|
|
210
|
-
"bg-gray-100 text-red-500 hover:text-red-500":
|
|
211
|
-
active && isEmphasized
|
|
212
|
-
}
|
|
213
|
-
)
|
|
214
|
-
return (
|
|
215
|
-
<li key={`${key}-${idx}`}>
|
|
216
|
-
<button
|
|
217
|
-
{...{
|
|
218
|
-
onClick: () => {
|
|
219
|
-
onClick && onClick()
|
|
220
|
-
setTimeout(() => {
|
|
221
|
-
//hide the dropdown after click
|
|
222
|
-
setIsOpen(false)
|
|
223
|
-
}, 150)
|
|
224
|
-
},
|
|
225
|
-
key: key,
|
|
226
|
-
className: cn(itemClass, "w-full"),
|
|
227
|
-
...rest
|
|
228
|
-
}}
|
|
229
|
-
>
|
|
230
|
-
<div
|
|
231
|
-
className={cn(
|
|
232
|
-
defaultClassNames.iconSpacingClassname,
|
|
233
|
-
iconSpacingClassname
|
|
234
|
-
)}
|
|
235
|
-
>
|
|
236
|
-
{iconObj &&
|
|
237
|
-
(iconPosition === "leading" ||
|
|
238
|
-
iconPosition === undefined) && (
|
|
239
|
-
<>{iconObj}</>
|
|
240
|
-
)}
|
|
241
|
-
|
|
242
|
-
{icon &&
|
|
243
|
-
(iconPosition === "leading" ||
|
|
244
|
-
iconPosition === undefined) &&
|
|
245
|
-
(typeof icon === "string" ? (
|
|
246
|
-
<DynamicIcon
|
|
247
|
-
{...{
|
|
248
|
-
icon: icon,
|
|
249
|
-
className: cn(
|
|
250
|
-
{
|
|
251
|
-
"text-red-500": isEmphasized
|
|
252
|
-
},
|
|
253
|
-
"opacity-60 group"
|
|
254
|
-
)
|
|
255
|
-
}}
|
|
256
|
-
/>
|
|
257
|
-
) : (
|
|
258
|
-
<DynamicIcon
|
|
259
|
-
{...{
|
|
260
|
-
...icon,
|
|
261
|
-
className: cn(
|
|
262
|
-
icon.className,
|
|
263
|
-
{
|
|
264
|
-
"text-red-500": isEmphasized
|
|
265
|
-
},
|
|
266
|
-
"opacity-60 group"
|
|
267
|
-
)
|
|
268
|
-
}}
|
|
269
|
-
/>
|
|
270
|
-
))}
|
|
271
|
-
<div className="whitespace-nowrap">{label}</div>
|
|
272
|
-
{iconObj && iconPosition === "trailing" && (
|
|
273
|
-
<>{iconObj}</>
|
|
274
|
-
)}
|
|
275
|
-
|
|
276
|
-
{icon &&
|
|
277
|
-
iconPosition === "trailing" &&
|
|
278
|
-
(typeof icon === "string" ? (
|
|
279
|
-
<DynamicIcon
|
|
280
|
-
{...{
|
|
281
|
-
icon: icon,
|
|
282
|
-
className: cn(
|
|
283
|
-
{
|
|
284
|
-
"text-red-500": isEmphasized
|
|
285
|
-
},
|
|
286
|
-
"opacity-60 group"
|
|
287
|
-
)
|
|
288
|
-
}}
|
|
289
|
-
/>
|
|
290
|
-
) : (
|
|
291
|
-
<DynamicIcon
|
|
292
|
-
{...{
|
|
293
|
-
...icon,
|
|
294
|
-
className: cn(
|
|
295
|
-
icon.className,
|
|
296
|
-
{
|
|
297
|
-
"text-red-500": isEmphasized
|
|
298
|
-
},
|
|
299
|
-
"opacity-60 group"
|
|
300
|
-
)
|
|
301
|
-
}}
|
|
302
|
-
/>
|
|
303
|
-
))}
|
|
304
|
-
</div>
|
|
305
|
-
</button>
|
|
306
|
-
</li>
|
|
307
|
-
)
|
|
308
|
-
}
|
|
309
|
-
)}
|
|
310
|
-
</React.Fragment>
|
|
311
|
-
)
|
|
312
|
-
})}
|
|
313
|
-
</ul>
|
|
314
|
-
</div>
|
|
315
|
-
</FloatingFocusManager>
|
|
316
|
-
</FloatingPortal>
|
|
303
|
+
<FloatingList
|
|
304
|
+
{...{
|
|
305
|
+
elementsRef: listRef
|
|
306
|
+
}}
|
|
307
|
+
>
|
|
308
|
+
<FloatingPortal>
|
|
309
|
+
<FloatingFocusManager context={context} modal={true}>
|
|
310
|
+
<div
|
|
311
|
+
{...getFloatingProps()}
|
|
312
|
+
className={cn(defaultClassNames.itemsClassname, itemsClassname)}
|
|
313
|
+
ref={refs.setFloating}
|
|
314
|
+
aria-labelledby={label}
|
|
315
|
+
style={{
|
|
316
|
+
position: context.strategy,
|
|
317
|
+
top: Math.round(context.y ?? 0),
|
|
318
|
+
left: Math.round(context.x ?? 0),
|
|
319
|
+
width: "max-content",
|
|
320
|
+
maxWidth: "min(calc(100vw - 10px), 25rem)",
|
|
321
|
+
...floatingStyles,
|
|
322
|
+
...transitionStyles
|
|
323
|
+
}}
|
|
324
|
+
>
|
|
325
|
+
{ItemComponents}
|
|
326
|
+
</div>
|
|
327
|
+
</FloatingFocusManager>
|
|
328
|
+
</FloatingPortal>
|
|
329
|
+
</FloatingList>
|
|
317
330
|
)}
|
|
318
331
|
</div>
|
|
319
332
|
)
|
|
@@ -14,9 +14,8 @@ export const dropdownDataBase: IItemProp[][] = [
|
|
|
14
14
|
onClick: () => {
|
|
15
15
|
console.log("Copy action")
|
|
16
16
|
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
[
|
|
17
|
+
},
|
|
18
|
+
|
|
20
19
|
{
|
|
21
20
|
icon: {
|
|
22
21
|
icon: "IconPlus"
|
|
@@ -42,9 +41,7 @@ export const dropdownDataBase: IItemProp[][] = [
|
|
|
42
41
|
onClick: () => {
|
|
43
42
|
console.log("View Batch action")
|
|
44
43
|
}
|
|
45
|
-
}
|
|
46
|
-
],
|
|
47
|
-
[
|
|
44
|
+
},
|
|
48
45
|
{
|
|
49
46
|
icon: {
|
|
50
47
|
icon: "IconTrash"
|