@agility/plenum-ui 2.3.2 → 2.3.4

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/tailwind.css CHANGED
@@ -2037,10 +2037,18 @@ select {
2037
2037
  width: 100%;
2038
2038
  }
2039
2039
 
2040
+ .min-w-0 {
2041
+ min-width: 0px;
2042
+ }
2043
+
2040
2044
  .min-w-\[320px\] {
2041
2045
  min-width: 320px;
2042
2046
  }
2043
2047
 
2048
+ .flex-1 {
2049
+ flex: 1 1 0%;
2050
+ }
2051
+
2044
2052
  .shrink-0 {
2045
2053
  flex-shrink: 0;
2046
2054
  }
@@ -71735,6 +71743,11 @@ select {
71735
71743
  color: rgb(107 114 128 / var(--tw-text-opacity, 1));
71736
71744
  }
71737
71745
 
71746
+ .text-neutral-700 {
71747
+ --tw-text-opacity: 1;
71748
+ color: rgb(55 65 81 / var(--tw-text-opacity, 1));
71749
+ }
71750
+
71738
71751
  .text-orange-100 {
71739
71752
  --tw-text-opacity: 1;
71740
71753
  color: rgb(255 237 213 / var(--tw-text-opacity, 1));
@@ -73515,6 +73528,11 @@ select {
73515
73528
  color: rgb(131 24 67 / 0.95);
73516
73529
  }
73517
73530
 
73531
+ .text-primary-700 {
73532
+ --tw-text-opacity: 1;
73533
+ color: rgb(109 40 217 / var(--tw-text-opacity, 1));
73534
+ }
73535
+
73518
73536
  .text-purple-100 {
73519
73537
  --tw-text-opacity: 1;
73520
73538
  color: rgb(222 204 246 / var(--tw-text-opacity, 1));
@@ -79020,6 +79038,10 @@ select {
79020
79038
  --anchor-gap: 8px;
79021
79039
  }
79022
79040
 
79041
+ .\!\[max-width\:var\(--dropdown-max-width\)\] {
79042
+ max-width: var(--dropdown-max-width) !important;
79043
+ }
79044
+
79023
79045
  .placeholder\:text-gray-400::-moz-placeholder {
79024
79046
  --tw-text-opacity: 1;
79025
79047
  color: rgb(156 163 175 / var(--tw-text-opacity, 1));
@@ -1,10 +1,10 @@
1
1
  type ParagraphAs = "span" | "p" | "label" | "strong" | "em";
2
2
  type ParagraphSize = "xl" | "lg" | "md" | "sm" | "xs";
3
- export interface ParagraphProps {
3
+ export interface ParagraphProps extends React.HTMLAttributes<HTMLElement> {
4
4
  as?: ParagraphAs;
5
5
  size?: ParagraphSize;
6
6
  children: React.ReactNode;
7
7
  className?: string;
8
8
  }
9
- export default function Paragraph({ as, size, children, className }: ParagraphProps): import("react/jsx-runtime").JSX.Element;
9
+ export default function Paragraph({ as, size, children, className, ...rest }: ParagraphProps): import("react/jsx-runtime").JSX.Element;
10
10
  export {};
@@ -1,9 +1,16 @@
1
1
  import React from "react";
2
+ import { UnifiedIconName } from "@/stories/atoms/icons/DynamicIcon";
2
3
  export interface ISimpleSelectOptions {
3
4
  label: string;
4
5
  value: string;
5
- emoji?: string;
6
+ icon?: UnifiedIconName;
6
7
  description?: string;
8
+ caption?: string;
9
+ }
10
+ interface LabelAction {
11
+ label: string;
12
+ onClick: () => void;
13
+ className?: string;
7
14
  }
8
15
  export interface ISelectProps {
9
16
  /** Label */
@@ -30,6 +37,8 @@ export interface ISelectProps {
30
37
  inputRef?: React.RefObject<HTMLInputElement>;
31
38
  placeholder?: string;
32
39
  dropdownMaxHeight?: number;
40
+ dropdownMaxWidth?: number;
41
+ labelAction?: LabelAction;
33
42
  }
34
43
  declare const Select: React.FC<ISelectProps>;
35
44
  export default Select;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agility/plenum-ui",
3
- "version": "2.3.2",
3
+ "version": "2.3.4",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
@@ -3,7 +3,7 @@ import { default as cn } from "classnames";
3
3
  type ParagraphAs = "span" | "p" | "label" | "strong" | "em";
4
4
  type ParagraphSize = "xl" | "lg" | "md" | "sm" | "xs";
5
5
 
6
- export interface ParagraphProps {
6
+ export interface ParagraphProps extends React.HTMLAttributes<HTMLElement> {
7
7
  as?: ParagraphAs;
8
8
  size?: ParagraphSize;
9
9
  children: React.ReactNode;
@@ -18,8 +18,8 @@ const paragraphStyles: Record<ParagraphSize, string> = {
18
18
  xs: "text-[10px] leading-[12px]"
19
19
  };
20
20
 
21
- export default function Paragraph({ as = "p", size = "md", children, className }: ParagraphProps) {
21
+ export default function Paragraph({ as = "p", size = "md", children, className, ...rest }: ParagraphProps) {
22
22
  const Tag = as;
23
23
 
24
- return <Tag className={cn("gray-900 font-normal", paragraphStyles[size], className)}>{children}</Tag>;
24
+ return <Tag className={cn("gray-900 font-normal", paragraphStyles[size], className)} {...rest}>{children}</Tag>;
25
25
  }
@@ -1,4 +1,5 @@
1
1
  import type { Meta, StoryObj } from "@storybook/react";
2
+ import { action } from "@storybook/addon-actions";
2
3
  import Select from "./Select";
3
4
 
4
5
  const meta: Meta<typeof Select> = {
@@ -61,8 +62,14 @@ export const DefaultSelect: TStory = {
61
62
  id: "select",
62
63
  name: "select",
63
64
  options: [
64
- { label: "Canada", value: "value1", description: "A description for Canada." },
65
- { label: "USA", value: "value2" }
65
+ {
66
+ label: "All",
67
+ value: ""
68
+ },
69
+ {
70
+ label: "Canadian French blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah",
71
+ value: "fr-ca"
72
+ }
66
73
  ],
67
74
  isDisabled: false,
68
75
  isError: false,
@@ -84,6 +91,24 @@ export const ManyOptions: TStory = {
84
91
  }
85
92
  };
86
93
 
94
+ export const WithLabelAction: TStory = {
95
+ args: {
96
+ label: "Batch",
97
+ id: "select-label-action",
98
+ name: "select-label-action",
99
+ isRequired: true,
100
+ options: [
101
+ { label: "Batch 1", value: "batch-1" },
102
+ { label: "Batch 2", value: "batch-2" },
103
+ { label: "Batch 3", value: "batch-3" }
104
+ ],
105
+ labelAction: {
106
+ label: "Add new batch",
107
+ onClick: action("labelAction clicked")
108
+ }
109
+ }
110
+ };
111
+
87
112
  export const DefaultSelectDarkBG: TStory = {
88
113
  args: {
89
114
  label: "Label",
@@ -1,6 +1,6 @@
1
1
  import React, { useEffect, useLayoutEffect, useRef, useState } from "react";
2
2
  import InputLabel from "@/stories/molecules/inputs/InputLabel";
3
- import { DynamicIcon } from "@/stories/atoms/icons/DynamicIcon";
3
+ import { DynamicIcon, UnifiedIconName } from "@/stories/atoms/icons/DynamicIcon";
4
4
  import { useId } from "@/utils/useId";
5
5
  import { default as cn } from "classnames";
6
6
  import {
@@ -11,12 +11,20 @@ import {
11
11
  ComboboxOption
12
12
  } from "@headlessui/react";
13
13
  import { Paragraph } from "@/stories/atoms/Typography/Paragraph";
14
+ import { Label } from "@/stories/atoms/Typography/Label";
14
15
 
15
16
  export interface ISimpleSelectOptions {
16
17
  label: string;
17
18
  value: string;
18
- emoji?: string;
19
+ icon?: UnifiedIconName;
19
20
  description?: string;
21
+ caption?: string;
22
+ }
23
+
24
+ interface LabelAction {
25
+ label: string;
26
+ onClick: () => void;
27
+ className?: string;
20
28
  }
21
29
 
22
30
  export interface ISelectProps {
@@ -44,6 +52,8 @@ export interface ISelectProps {
44
52
  inputRef?: React.RefObject<HTMLInputElement>;
45
53
  placeholder?: string;
46
54
  dropdownMaxHeight?: number;
55
+ dropdownMaxWidth?: number;
56
+ labelAction?: LabelAction;
47
57
  }
48
58
 
49
59
  const Select: React.FC<ISelectProps> = ({
@@ -62,7 +72,9 @@ const Select: React.FC<ISelectProps> = ({
62
72
  message,
63
73
  inputRef,
64
74
  placeholder = "Select",
65
- dropdownMaxHeight = 240
75
+ dropdownMaxHeight = 240,
76
+ dropdownMaxWidth = 240,
77
+ labelAction
66
78
  }) => {
67
79
  const uniqueID = useId();
68
80
  if (!id) id = `select-${uniqueID}`;
@@ -98,7 +110,25 @@ const Select: React.FC<ISelectProps> = ({
98
110
 
99
111
  return (
100
112
  <div className={wrapperStyle}>
101
- {label && <InputLabel id={`${id}-label`} label={label} isRequired={isRequired} />}
113
+ {(label || labelAction) && (
114
+ <div className="flex items-center justify-between">
115
+ {label && (
116
+ <InputLabel
117
+ id={`${id}-label`}
118
+ label={label}
119
+ isRequired={isRequired}
120
+ noMarginBottom={!!labelAction}
121
+ />
122
+ )}
123
+ {labelAction && (
124
+ <button type="button" onClick={labelAction.onClick}>
125
+ <Label size="sm" className={cn("text-primary-700", labelAction.className)}>
126
+ {labelAction.label}
127
+ </Label>
128
+ </button>
129
+ )}
130
+ </div>
131
+ )}
102
132
 
103
133
  <HeadlessCombobox value={selectedOption} onChange={handleChange} disabled={isDisabled} immediate by="value">
104
134
  <div ref={containerRef} className="relative w-full">
@@ -142,13 +172,15 @@ const Select: React.FC<ISelectProps> = ({
142
172
  style={
143
173
  {
144
174
  "--anchor-max-height": `${dropdownMaxHeight}px`,
145
- minWidth: containerWidth
175
+ "--dropdown-max-width": `${dropdownMaxWidth}px`,
176
+ minWidth: Math.max(containerWidth ?? 0, 60)
146
177
  } as React.CSSProperties
147
178
  }
148
179
  className={cn(
149
180
  "z-[9999] overflow-auto rounded bg-white py-1",
150
181
  "text-sm shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none",
151
- "[--anchor-gap:8px]"
182
+ "[--anchor-gap:8px]",
183
+ "![max-width:var(--dropdown-max-width)]"
152
184
  )}
153
185
  >
154
186
  {options.map((option) => (
@@ -163,10 +195,41 @@ const Select: React.FC<ISelectProps> = ({
163
195
  }
164
196
  >
165
197
  {({ selected }) => (
166
- <div className="py-xxsm px-sm flex items-center gap-xsm">
167
- <Paragraph size="md">{option.label}</Paragraph>
168
- {option.description ? (
169
- <Paragraph size="md" className="text-neutral-500">{option.description}</Paragraph>
198
+ <div className="flex justify-between items-center py-xxsm px-sm gap-4">
199
+ <div className="flex flex-col flex-1 min-w-0">
200
+ <div className="flex items-center gap-xsm">
201
+ <Paragraph
202
+ size="md"
203
+ className="text-neutral-700 truncate min-w-0"
204
+ title={option.label}
205
+ onMouseEnter={(e) => {
206
+ const el = e.currentTarget;
207
+ if (el.scrollWidth <= el.clientWidth)
208
+ el.removeAttribute("title");
209
+ }}
210
+ onMouseLeave={(e) => {
211
+ e.currentTarget.setAttribute("title", option.label);
212
+ }}
213
+ >
214
+ {option.label}
215
+ </Paragraph>
216
+ {option.description ? (
217
+ <Paragraph size="md" className="text-neutral-500">
218
+ {option.description}
219
+ </Paragraph>
220
+ ) : null}
221
+ </div>
222
+ {option.caption ? (
223
+ <Paragraph size="sm" className="text-neutral-500">
224
+ {option.caption}
225
+ </Paragraph>
226
+ ) : null}
227
+ </div>
228
+ {option.icon ? (
229
+ <DynamicIcon
230
+ icon={option.icon}
231
+ className="shrink-0 w-5 h-5 text-neutral-500"
232
+ />
170
233
  ) : null}
171
234
  </div>
172
235
  )}