@activecollab/components 2.0.421 → 2.0.422

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 (71) hide show
  1. package/dist/cjs/components/RadioCard/RadioCard.js +81 -0
  2. package/dist/cjs/components/RadioCard/RadioCard.js.map +1 -0
  3. package/dist/cjs/components/RadioCard/Styles.js +39 -0
  4. package/dist/cjs/components/RadioCard/Styles.js.map +1 -0
  5. package/dist/cjs/components/RadioCard/index.js +17 -0
  6. package/dist/cjs/components/RadioCard/index.js.map +1 -0
  7. package/dist/cjs/components/RadioGroup/RadioGroup.js +102 -0
  8. package/dist/cjs/components/RadioGroup/RadioGroup.js.map +1 -0
  9. package/dist/cjs/components/RadioGroup/Styles.js +38 -0
  10. package/dist/cjs/components/RadioGroup/Styles.js.map +1 -0
  11. package/dist/cjs/components/RadioGroup/index.js +17 -0
  12. package/dist/cjs/components/RadioGroup/index.js.map +1 -0
  13. package/dist/cjs/components/index.js +22 -0
  14. package/dist/cjs/components/index.js.map +1 -1
  15. package/dist/cjs/presentation/shared/PortfolioOptionsMenu.js +74 -15
  16. package/dist/cjs/presentation/shared/PortfolioOptionsMenu.js.map +1 -1
  17. package/dist/cjs/presentation/shared/index.js +93 -1
  18. package/dist/cjs/presentation/shared/index.js.map +1 -1
  19. package/dist/cjs/presentation/shared/portfolioDetails.js +566 -0
  20. package/dist/cjs/presentation/shared/portfolioDetails.js.map +1 -0
  21. package/dist/cjs/utils/useStableId.js +33 -0
  22. package/dist/cjs/utils/useStableId.js.map +1 -0
  23. package/dist/esm/components/RadioCard/RadioCard.d.ts +27 -0
  24. package/dist/esm/components/RadioCard/RadioCard.d.ts.map +1 -0
  25. package/dist/esm/components/RadioCard/RadioCard.js +72 -0
  26. package/dist/esm/components/RadioCard/RadioCard.js.map +1 -0
  27. package/dist/esm/components/RadioCard/Styles.d.ts +16 -0
  28. package/dist/esm/components/RadioCard/Styles.d.ts.map +1 -0
  29. package/dist/esm/components/RadioCard/Styles.js +26 -0
  30. package/dist/esm/components/RadioCard/Styles.js.map +1 -0
  31. package/dist/esm/components/RadioCard/index.d.ts +2 -0
  32. package/dist/esm/components/RadioCard/index.d.ts.map +1 -0
  33. package/dist/esm/components/RadioCard/index.js +2 -0
  34. package/dist/esm/components/RadioCard/index.js.map +1 -0
  35. package/dist/esm/components/RadioGroup/RadioGroup.d.ts +48 -0
  36. package/dist/esm/components/RadioGroup/RadioGroup.d.ts.map +1 -0
  37. package/dist/esm/components/RadioGroup/RadioGroup.js +89 -0
  38. package/dist/esm/components/RadioGroup/RadioGroup.js.map +1 -0
  39. package/dist/esm/components/RadioGroup/Styles.d.ts +22 -0
  40. package/dist/esm/components/RadioGroup/Styles.d.ts.map +1 -0
  41. package/dist/esm/components/RadioGroup/Styles.js +23 -0
  42. package/dist/esm/components/RadioGroup/Styles.js.map +1 -0
  43. package/dist/esm/components/RadioGroup/index.d.ts +2 -0
  44. package/dist/esm/components/RadioGroup/index.d.ts.map +1 -0
  45. package/dist/esm/components/RadioGroup/index.js +2 -0
  46. package/dist/esm/components/RadioGroup/index.js.map +1 -0
  47. package/dist/esm/components/index.d.ts +2 -0
  48. package/dist/esm/components/index.d.ts.map +1 -1
  49. package/dist/esm/components/index.js +2 -0
  50. package/dist/esm/components/index.js.map +1 -1
  51. package/dist/esm/presentation/shared/PortfolioOptionsMenu.d.ts +5 -1
  52. package/dist/esm/presentation/shared/PortfolioOptionsMenu.d.ts.map +1 -1
  53. package/dist/esm/presentation/shared/PortfolioOptionsMenu.js +61 -14
  54. package/dist/esm/presentation/shared/PortfolioOptionsMenu.js.map +1 -1
  55. package/dist/esm/presentation/shared/index.d.ts +2 -0
  56. package/dist/esm/presentation/shared/index.d.ts.map +1 -1
  57. package/dist/esm/presentation/shared/index.js +1 -0
  58. package/dist/esm/presentation/shared/index.js.map +1 -1
  59. package/dist/esm/presentation/shared/portfolioDetails.d.ts +74 -0
  60. package/dist/esm/presentation/shared/portfolioDetails.d.ts.map +1 -0
  61. package/dist/esm/presentation/shared/portfolioDetails.js +490 -0
  62. package/dist/esm/presentation/shared/portfolioDetails.js.map +1 -0
  63. package/dist/esm/utils/useStableId.d.ts +2 -0
  64. package/dist/esm/utils/useStableId.d.ts.map +1 -0
  65. package/dist/esm/utils/useStableId.js +25 -0
  66. package/dist/esm/utils/useStableId.js.map +1 -0
  67. package/dist/index.js +1068 -815
  68. package/dist/index.js.map +1 -1
  69. package/dist/index.min.js +1 -1
  70. package/dist/index.min.js.map +1 -1
  71. package/package.json +1 -1
@@ -0,0 +1,566 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.sampleProjectOptionIds = exports.leaderShortName = exports.isPortfolioDetailsValid = exports.defaultPortfolioName = exports.contextFieldLabel = exports.VISIBILITY_OPTIONS = exports.PortfolioDetailsFields = exports.PORTFOLIO_TYPES = exports.LEADERS_LIST = exports.EditPortfolioDialog = exports.DEFAULT_PORTFOLIO_FORM_VALUES = exports.CLIENTS = exports.CATEGORIES = void 0;
7
+ var _react = _interopRequireWildcard(require("react"));
8
+ var _styledComponents = _interopRequireDefault(require("styled-components"));
9
+ var _Button = require("../../components/Button");
10
+ var _Dialog = require("../../components/Dialog");
11
+ var _IconButton = require("../../components/IconButton");
12
+ var _Icons = require("../../components/Icons");
13
+ var _Input = require("../../components/Input");
14
+ var _Label = require("../../components/Label");
15
+ var _RadioGroup = require("../../components/RadioGroup");
16
+ var _Select = require("../../components/Select");
17
+ var _SelectTrigger = require("../../components/SelectTrigger");
18
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
19
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
20
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
21
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
22
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
23
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
24
+ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
25
+ function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
26
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
27
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
28
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
29
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
30
+ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
31
+ /*
32
+ Portfolio details form — the shared "step 2" of the Create Portfolio wizard,
33
+ reused verbatim as the Edit Portfolio dialog.
34
+
35
+ This mirrors a pattern used across the app: the fields that make up the final
36
+ step of a creation wizard are the same fields shown, later, when the object is
37
+ edited. So the form body (name, the type's picker, visibility) and its
38
+ validation live here once, and two consumers render it:
39
+
40
+ - The Create Portfolio wizard (PortfoliosList.stories.tsx) renders
41
+ <PortfolioDetailsFields> inside its step-2 <Dialog.Content>, with a
42
+ "Create Portfolio" action.
43
+ - <EditPortfolioDialog> (opened from PortfolioOptionsMenu's Edit item)
44
+ renders the SAME <PortfolioDetailsFields> inside a standalone <Dialog>,
45
+ with a "Save Changes" action.
46
+
47
+ Both use isPortfolioDetailsValid() and the same always-enabled-submit,
48
+ outline-on-submit validation rule.
49
+ */
50
+
51
+ /* ------------------------------------------------------------------ */
52
+ /* Domain types */
53
+ /* ------------------------------------------------------------------ */
54
+
55
+ /** How a portfolio decides its members (two kinds, three context types). */
56
+
57
+ /** Grouping of the projects multi-select — matches Invite-to-Projects. */
58
+
59
+ /** The editable shape shared by create step 2 and the edit dialog. */
60
+
61
+ /** A blank custom portfolio — the fallback seed for the edit dialog. */
62
+ var DEFAULT_PORTFOLIO_FORM_VALUES = exports.DEFAULT_PORTFOLIO_FORM_VALUES = {
63
+ type: "custom",
64
+ name: "",
65
+ context: undefined,
66
+ projectIds: [],
67
+ groupBy: "favorites",
68
+ visibility: "everyone"
69
+ };
70
+
71
+ /* ------------------------------------------------------------------ */
72
+ /* Pickers' mock data */
73
+ /* ------------------------------------------------------------------ */
74
+
75
+ var LEADERS_LIST = exports.LEADERS_LIST = [{
76
+ name: "Theo Brandt",
77
+ short: "Theo B."
78
+ }, {
79
+ name: "Isabel Cortez",
80
+ short: "Isabel C."
81
+ }, {
82
+ name: "Grace Bauer",
83
+ short: "Grace B."
84
+ }, {
85
+ name: "Noah Mercer",
86
+ short: "Noah M."
87
+ }];
88
+ var CATEGORIES = exports.CATEGORIES = ["Brand & Identity", "Web & Product", "Marketing", "Internal Ops"];
89
+ var CLIENTS = exports.CLIENTS = ["Aperture Studio", "Orbit Telecom", "Northwind Traders", "Meridian Health"];
90
+ var PICKER_PROJECTS = [{
91
+ id: 1,
92
+ name: "Website Redesign",
93
+ client: "Aperture Studio",
94
+ category: "Web & Product",
95
+ label: "Design",
96
+ leader: "Theo Brandt",
97
+ favorite: true
98
+ }, {
99
+ id: 2,
100
+ name: "Brand Refresh",
101
+ client: "Aperture Studio",
102
+ category: "Brand & Identity",
103
+ label: "Design",
104
+ leader: "Isabel Cortez",
105
+ favorite: true
106
+ }, {
107
+ id: 3,
108
+ name: "Mobile App",
109
+ client: "Orbit Telecom",
110
+ category: "Web & Product",
111
+ label: "Build",
112
+ leader: "Grace Bauer",
113
+ favorite: false
114
+ }, {
115
+ id: 4,
116
+ name: "Q3 Campaign",
117
+ client: "Orbit Telecom",
118
+ category: "Marketing",
119
+ label: "Campaign",
120
+ leader: "Noah Mercer",
121
+ favorite: true
122
+ }, {
123
+ id: 5,
124
+ name: "Internal Wiki",
125
+ client: "",
126
+ category: "Internal Ops",
127
+ label: "",
128
+ leader: "Theo Brandt",
129
+ favorite: false
130
+ }, {
131
+ id: 6,
132
+ name: "Packaging System",
133
+ client: "Northwind Traders",
134
+ category: "Brand & Identity",
135
+ label: "Design",
136
+ leader: "Isabel Cortez",
137
+ favorite: false
138
+ }, {
139
+ id: 7,
140
+ name: "Support Portal",
141
+ client: "Meridian Health",
142
+ category: "Web & Product",
143
+ label: "Build",
144
+ leader: "Grace Bauer",
145
+ favorite: false
146
+ }, {
147
+ id: 8,
148
+ name: "Annual Report",
149
+ client: "Northwind Traders",
150
+ category: "Marketing",
151
+ label: "Campaign",
152
+ leader: "Noah Mercer",
153
+ favorite: true
154
+ }];
155
+
156
+ /* Group-by options and default match the Invite-to-Projects picker exactly. */
157
+ var GROUP_BY_OPTIONS = [{
158
+ id: "favorites",
159
+ name: "Favorites"
160
+ }, {
161
+ id: "labels",
162
+ name: "Label"
163
+ }, {
164
+ id: "companies",
165
+ name: "Client"
166
+ }, {
167
+ id: "categories",
168
+ name: "Category"
169
+ }, {
170
+ id: "leaders",
171
+ name: "Project Leader"
172
+ }];
173
+ var projectOptionId = function projectOptionId(project) {
174
+ return "p".concat(project.id);
175
+ };
176
+
177
+ /** A small deterministic set of project option ids — seeds a custom
178
+ portfolio's edit dialog so the picker reads as an existing selection. */
179
+ var sampleProjectOptionIds = exports.sampleProjectOptionIds = function sampleProjectOptionIds(count) {
180
+ return PICKER_PROJECTS.slice(0, Math.max(0, count)).map(projectOptionId);
181
+ };
182
+ var toProjectOptions = function toProjectOptions(projects) {
183
+ return projects.map(function (project) {
184
+ return {
185
+ id: projectOptionId(project),
186
+ name: project.name
187
+ };
188
+ }).sort(function (a, b) {
189
+ return a.name.localeCompare(b.name);
190
+ });
191
+ };
192
+
193
+ /* Build the grouped option tree the Select expects. Alphabetical rows and
194
+ groups; the "Without ..." / "Other" bucket sits last; the Favorites grouping
195
+ collapses to a flat list when it is the only group (as the app's does). */
196
+ var groupPickerProjects = function groupPickerProjects(groupBy) {
197
+ if (groupBy === "favorites") {
198
+ var favorite = PICKER_PROJECTS.filter(function (project) {
199
+ return project.favorite;
200
+ });
201
+ var other = PICKER_PROJECTS.filter(function (project) {
202
+ return !project.favorite;
203
+ });
204
+ var groups = [];
205
+ if (favorite.length) {
206
+ groups.push({
207
+ id: "g-fav",
208
+ name: "Favorite",
209
+ options: toProjectOptions(favorite)
210
+ });
211
+ }
212
+ if (other.length) {
213
+ groups.push({
214
+ id: "g-other",
215
+ name: "Other",
216
+ options: toProjectOptions(other)
217
+ });
218
+ }
219
+ return groups.length === 1 ? groups[0].options : groups;
220
+ }
221
+ var field = groupBy === "labels" ? "label" : groupBy === "companies" ? "client" : groupBy === "categories" ? "category" : "leader";
222
+ var without = groupBy === "labels" ? "Without Label" : groupBy === "companies" ? "Without Client" : groupBy === "categories" ? "Without Category" : "Without Leader";
223
+ var buckets = new Map();
224
+ PICKER_PROJECTS.forEach(function (project) {
225
+ var _buckets$get;
226
+ var key = project[field] || without;
227
+ if (!buckets.has(key)) {
228
+ buckets.set(key, []);
229
+ }
230
+ (_buckets$get = buckets.get(key)) === null || _buckets$get === void 0 || _buckets$get.push(project);
231
+ });
232
+ return Array.from(buckets.entries()).map(function (_ref) {
233
+ var _ref2 = _slicedToArray(_ref, 2),
234
+ name = _ref2[0],
235
+ projects = _ref2[1];
236
+ return {
237
+ id: "g-".concat(name),
238
+ name,
239
+ options: toProjectOptions(projects)
240
+ };
241
+ }).sort(function (a, b) {
242
+ return a.name === without ? 1 : b.name === without ? -1 : a.name.localeCompare(b.name);
243
+ });
244
+ };
245
+
246
+ /* ------------------------------------------------------------------ */
247
+ /* Type + visibility option copy */
248
+ /* ------------------------------------------------------------------ */
249
+
250
+ var PORTFOLIO_TYPES = exports.PORTFOLIO_TYPES = [{
251
+ id: "custom",
252
+ title: "Custom Portfolio",
253
+ description: "The projects you pick by hand. Nothing joins automatically."
254
+ }, {
255
+ id: "client",
256
+ title: "Client Portfolio",
257
+ description: "All projects for a client company. New ones join automatically."
258
+ }, {
259
+ id: "leader",
260
+ title: "Project Leader Portfolio",
261
+ description: "All projects led by a person. New ones join automatically."
262
+ }, {
263
+ id: "category",
264
+ title: "Category Portfolio",
265
+ description: "All projects in a project category. New ones join automatically."
266
+ }];
267
+ var VISIBILITY_OPTIONS = exports.VISIBILITY_OPTIONS = [{
268
+ id: "everyone",
269
+ title: "Visible to Everyone",
270
+ description: "Anyone who can use portfolios sees this one. They still only see the projects they already have access to."
271
+ }, {
272
+ id: "me",
273
+ title: "Visible Only to Me",
274
+ description: "Nobody else sees this portfolio."
275
+ }];
276
+ var contextFieldLabel = exports.contextFieldLabel = function contextFieldLabel(type) {
277
+ return type === "custom" ? "Projects" : type === "category" ? "Category" : type === "client" ? "Client" : "Project leader";
278
+ };
279
+ var leaderShortName = exports.leaderShortName = function leaderShortName(name) {
280
+ var _LEADERS_LIST$find$sh, _LEADERS_LIST$find;
281
+ return (_LEADERS_LIST$find$sh = (_LEADERS_LIST$find = LEADERS_LIST.find(function (leader) {
282
+ return leader.name === name;
283
+ })) === null || _LEADERS_LIST$find === void 0 ? void 0 : _LEADERS_LIST$find.short) !== null && _LEADERS_LIST$find$sh !== void 0 ? _LEADERS_LIST$find$sh : name;
284
+ };
285
+
286
+ /* Default names: "{Category} Projects", "{Client} Projects", "Lead by {N.}". */
287
+ var defaultPortfolioName = exports.defaultPortfolioName = function defaultPortfolioName(type, context) {
288
+ if (!context) return "";
289
+ if (type === "category" || type === "client") return "".concat(context, " Projects");
290
+ if (type === "leader") return "Lead by ".concat(leaderShortName(context));
291
+ return "";
292
+ };
293
+
294
+ /* ------------------------------------------------------------------ */
295
+ /* Validation (shared by create step 2 and the edit dialog) */
296
+ /* ------------------------------------------------------------------ */
297
+
298
+ /** Name is required; a custom portfolio needs at least one project, a context
299
+ portfolio needs its context chosen. Same rule for create and edit. */
300
+ var isPortfolioDetailsValid = exports.isPortfolioDetailsValid = function isPortfolioDetailsValid(values) {
301
+ return values.name.trim().length > 0 && (values.type === "custom" ? values.projectIds.length > 0 : Boolean(values.context));
302
+ };
303
+
304
+ /* ------------------------------------------------------------------ */
305
+ /* Pickers */
306
+ /* ------------------------------------------------------------------ */
307
+
308
+ /* Group-by control: the SortGeneralIcon button the Invite-to-Projects picker
309
+ shows as the search bar's right-side adornment. Controls grouping, not sort. */
310
+ var ProjectsGroupBy = function ProjectsGroupBy(_ref3) {
311
+ var selected = _ref3.selected,
312
+ _onChange = _ref3.onChange;
313
+ return /*#__PURE__*/_react.default.createElement(_Select.Select, {
314
+ keepSameOptionsOrder: true,
315
+ disableSearch: true,
316
+ disabledInternalSort: true,
317
+ forceCloseMenu: true,
318
+ position: "bottom-end",
319
+ selected: selected,
320
+ onChange: function onChange(value) {
321
+ return _onChange(value);
322
+ },
323
+ options: GROUP_BY_OPTIONS,
324
+ target: /*#__PURE__*/_react.default.createElement(_IconButton.IconButton, {
325
+ type: "button",
326
+ variant: "text gray"
327
+ }, /*#__PURE__*/_react.default.createElement(_Icons.SortGeneralIcon, null))
328
+ });
329
+ };
330
+ var ProjectsPicker = function ProjectsPicker(_ref4) {
331
+ var selected = _ref4.selected,
332
+ _onChange2 = _ref4.onChange,
333
+ groupBy = _ref4.groupBy,
334
+ onGroupBy = _ref4.onGroupBy,
335
+ invalid = _ref4.invalid;
336
+ var options = (0, _react.useMemo)(function () {
337
+ return groupPickerProjects(groupBy);
338
+ }, [groupBy]);
339
+ var count = selected.length;
340
+ var triggerText = count === 0 ? "Choose projects" : count === 1 ? "1 project selected" : "".concat(count, " projects selected");
341
+ return /*#__PURE__*/_react.default.createElement(_Select.Select, {
342
+ type: "multiple",
343
+ options: options,
344
+ selected: selected,
345
+ onChange: function onChange(value) {
346
+ return _onChange2(value);
347
+ },
348
+ noResultText: "No results",
349
+ endAdornment: /*#__PURE__*/_react.default.createElement(ProjectsGroupBy, {
350
+ selected: groupBy,
351
+ onChange: onGroupBy
352
+ }),
353
+ target: /*#__PURE__*/_react.default.createElement(_SelectTrigger.SelectTrigger, {
354
+ id: "pf-projects",
355
+ className: "pf-trigger",
356
+ invalid: invalid,
357
+ typographyProps: {
358
+ color: count > 0 ? "primary" : "quaternary"
359
+ }
360
+ }, triggerText)
361
+ });
362
+ };
363
+ var ContextPicker = function ContextPicker(_ref5) {
364
+ var type = _ref5.type,
365
+ value = _ref5.value,
366
+ _onChange3 = _ref5.onChange,
367
+ invalid = _ref5.invalid;
368
+ var options = type === "category" ? CATEGORIES.map(function (name) {
369
+ return {
370
+ id: name,
371
+ name
372
+ };
373
+ }) : type === "client" ? CLIENTS.map(function (name) {
374
+ return {
375
+ id: name,
376
+ name
377
+ };
378
+ }) : LEADERS_LIST.map(function (leader) {
379
+ return {
380
+ id: leader.name,
381
+ name: leader.name
382
+ };
383
+ });
384
+ var placeholder = type === "category" ? "Choose a category" : type === "client" ? "Choose a client" : "Choose a project leader";
385
+ return /*#__PURE__*/_react.default.createElement(_Select.Select, {
386
+ forceCloseMenu: true,
387
+ options: options,
388
+ selected: value !== null && value !== void 0 ? value : "",
389
+ onChange: function onChange(next) {
390
+ return _onChange3(String(next));
391
+ },
392
+ target: /*#__PURE__*/_react.default.createElement(_SelectTrigger.SelectTrigger, {
393
+ id: "pf-context",
394
+ className: "pf-trigger",
395
+ invalid: invalid,
396
+ typographyProps: {
397
+ color: value ? "primary" : "quaternary"
398
+ }
399
+ }, value !== null && value !== void 0 ? value : placeholder)
400
+ });
401
+ };
402
+
403
+ /* ------------------------------------------------------------------ */
404
+ /* The reusable form body */
405
+ /* ------------------------------------------------------------------ */
406
+
407
+ var StyledDetailsForm = _styledComponents.default.div.withConfig({
408
+ displayName: "portfolioDetails__StyledDetailsForm",
409
+ componentId: "sc-yxi1uj-0"
410
+ })(["display:flex;flex-direction:column;gap:24px;.field{display:flex;flex-direction:column;gap:8px;}.field .c-input-wrapper{width:100%;}.field .pf-trigger{width:100%;}"]);
411
+ /** Name + the type's picker + visibility. No Dialog wrappers and no action
412
+ button — the consumer (create step or edit dialog) supplies those. */
413
+ var PortfolioDetailsFields = exports.PortfolioDetailsFields = function PortfolioDetailsFields(_ref6) {
414
+ var values = _ref6.values,
415
+ onName = _ref6.onName,
416
+ onContext = _ref6.onContext,
417
+ onProjects = _ref6.onProjects,
418
+ onGroupBy = _ref6.onGroupBy,
419
+ onVisibility = _ref6.onVisibility,
420
+ showErrors = _ref6.showErrors;
421
+ var type = values.type,
422
+ name = values.name,
423
+ context = values.context,
424
+ projectIds = values.projectIds,
425
+ groupBy = values.groupBy,
426
+ visibility = values.visibility;
427
+ var nameInvalid = showErrors && name.trim().length === 0;
428
+ var pickerInvalid = showErrors && (type === "custom" ? projectIds.length === 0 : !context);
429
+ return /*#__PURE__*/_react.default.createElement(StyledDetailsForm, null, /*#__PURE__*/_react.default.createElement("div", {
430
+ className: "field"
431
+ }, /*#__PURE__*/_react.default.createElement(_Label.Label, {
432
+ htmlFor: "pf-name"
433
+ }, "Name"), /*#__PURE__*/_react.default.createElement(_Input.Input, {
434
+ id: "pf-name",
435
+ value: name,
436
+ placeholder: "Portfolio name",
437
+ invalid: nameInvalid,
438
+ onChange: function onChange(event) {
439
+ return onName(event.target.value);
440
+ }
441
+ })), /*#__PURE__*/_react.default.createElement("div", {
442
+ className: "field"
443
+ }, /*#__PURE__*/_react.default.createElement(_Label.Label, {
444
+ htmlFor: type === "custom" ? "pf-projects" : "pf-context"
445
+ }, contextFieldLabel(type)), type === "custom" ? /*#__PURE__*/_react.default.createElement(ProjectsPicker, {
446
+ selected: projectIds,
447
+ onChange: onProjects,
448
+ groupBy: groupBy,
449
+ onGroupBy: onGroupBy,
450
+ invalid: pickerInvalid
451
+ }) : /*#__PURE__*/_react.default.createElement(ContextPicker, {
452
+ type: type,
453
+ value: context,
454
+ onChange: onContext,
455
+ invalid: pickerInvalid
456
+ })), /*#__PURE__*/_react.default.createElement("div", {
457
+ className: "field"
458
+ }, /*#__PURE__*/_react.default.createElement(_RadioGroup.RadioGroup, {
459
+ label: "Visibility",
460
+ variant: "plain",
461
+ value: visibility,
462
+ onChange: function onChange(value) {
463
+ return onVisibility(value);
464
+ },
465
+ options: VISIBILITY_OPTIONS.map(function (option) {
466
+ return {
467
+ id: option.id,
468
+ name: option.title,
469
+ description: option.description
470
+ };
471
+ })
472
+ })));
473
+ };
474
+ PortfolioDetailsFields.displayName = "PortfolioDetailsFields";
475
+
476
+ /* ------------------------------------------------------------------ */
477
+ /* Edit Portfolio dialog — the create wizard's step 2, on its own */
478
+ /* ------------------------------------------------------------------ */
479
+
480
+ /*
481
+ Same fields, same validation as create step 2. The type is fixed to the
482
+ portfolio's kind (edit changes the details, not the kind), so there is no
483
+ type radio here — only the name, the type's picker, and visibility.
484
+ */
485
+ var EditPortfolioDialog = exports.EditPortfolioDialog = function EditPortfolioDialog(_ref7) {
486
+ var open = _ref7.open,
487
+ initialValues = _ref7.initialValues,
488
+ onClose = _ref7.onClose,
489
+ onSave = _ref7.onSave;
490
+ var _useState = (0, _react.useState)(initialValues),
491
+ _useState2 = _slicedToArray(_useState, 2),
492
+ values = _useState2[0],
493
+ setValues = _useState2[1];
494
+ var _useState3 = (0, _react.useState)(false),
495
+ _useState4 = _slicedToArray(_useState3, 2),
496
+ showErrors = _useState4[0],
497
+ setShowErrors = _useState4[1];
498
+
499
+ /* Re-seed from the portfolio each time the dialog opens. */
500
+ (0, _react.useEffect)(function () {
501
+ if (open) {
502
+ setValues(initialValues);
503
+ setShowErrors(false);
504
+ }
505
+ // Seed on open only — initialValues is read at that moment by design.
506
+ // eslint-disable-next-line react-hooks/exhaustive-deps
507
+ }, [open]);
508
+ var patch = function patch(next) {
509
+ return setValues(function (current) {
510
+ return _objectSpread(_objectSpread({}, current), next);
511
+ });
512
+ };
513
+ var handleSave = function handleSave() {
514
+ if (!isPortfolioDetailsValid(values)) {
515
+ setShowErrors(true);
516
+ return;
517
+ }
518
+ onSave === null || onSave === void 0 || onSave(values);
519
+ onClose();
520
+ };
521
+ return /*#__PURE__*/_react.default.createElement(_Dialog.Dialog, {
522
+ open: open,
523
+ onClose: onClose,
524
+ disableCloseOnEsc: true
525
+ }, /*#__PURE__*/_react.default.createElement(_Dialog.Dialog.Title, null, "Edit Portfolio"), /*#__PURE__*/_react.default.createElement(_Dialog.Dialog.ContentDivider, null), /*#__PURE__*/_react.default.createElement(_Dialog.Dialog.Content, null, /*#__PURE__*/_react.default.createElement(PortfolioDetailsFields, {
526
+ values: values,
527
+ onName: function onName(name) {
528
+ return patch({
529
+ name
530
+ });
531
+ },
532
+ onContext: function onContext(context) {
533
+ return patch({
534
+ context
535
+ });
536
+ },
537
+ onProjects: function onProjects(projectIds) {
538
+ return patch({
539
+ projectIds
540
+ });
541
+ },
542
+ onGroupBy: function onGroupBy(groupBy) {
543
+ return patch({
544
+ groupBy
545
+ });
546
+ },
547
+ onVisibility: function onVisibility(visibility) {
548
+ return patch({
549
+ visibility
550
+ });
551
+ },
552
+ showErrors: showErrors
553
+ })), /*#__PURE__*/_react.default.createElement(_Dialog.Dialog.ContentDivider, null), /*#__PURE__*/_react.default.createElement(_Dialog.Dialog.Actions, null, /*#__PURE__*/_react.default.createElement(_Button.Button, {
554
+ variant: "primary",
555
+ style: {
556
+ marginRight: "12px"
557
+ },
558
+ onClick: handleSave
559
+ }, "Save Changes"), /*#__PURE__*/_react.default.createElement(_Button.Button, {
560
+ variant: "secondary",
561
+ "data-action": "cancel",
562
+ onClick: onClose
563
+ }, "Cancel")));
564
+ };
565
+ EditPortfolioDialog.displayName = "EditPortfolioDialog";
566
+ //# sourceMappingURL=portfolioDetails.js.map