@activecollab/components 2.0.341 → 2.0.343

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.
@@ -0,0 +1,690 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.LinkBranchOrPullRequestDialog = void 0;
7
+ var _react = _interopRequireWildcard(require("react"));
8
+ var _styledComponents = _interopRequireWildcard(require("styled-components"));
9
+ var _ConnectRepositoryDialog = require("./ConnectRepositoryDialog");
10
+ var _Button = require("../../components/Button");
11
+ var _ChooseV = require("../../components/ChooseV2");
12
+ var _Dialog = require("../../components/Dialog");
13
+ var _Input = require("../../components/Input");
14
+ var _Label = require("../../components/Label");
15
+ var _Loaders = require("../../components/Loaders");
16
+ var _Select = require("../../components/Select");
17
+ var _SelectTrigger = require("../../components/SelectTrigger");
18
+ var _Typography = require("../../components/Typography");
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 _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
21
+ 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."); }
22
+ 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; } }
23
+ 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; }
24
+ 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; } }
25
+ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
26
+ /**
27
+ * "Link Branch or Pull Request" dialog — shared by every `Presentation/Task
28
+ * Source` story (the empty state and the populated Source Code section) so the
29
+ * flow lives in one place.
30
+ *
31
+ * Three modes (ChooseV2): **Link Existing** (default), **New Branch**, **New
32
+ * Pull Request**. The primary button is always enabled; validation runs on
33
+ * click and outlines the offending field. Esc does not close the dialog (it
34
+ * would lose entered data) — this is an action dialog.
35
+ *
36
+ * On open the body shows a ~1s skeleton, standing in for the future API loads
37
+ * that will drive the repository / branch / PR pickers.
38
+ *
39
+ * The **Link Existing** picker is a grouped, multi-level select: options are
40
+ * grouped by repository (with the connection name in parentheses), each option
41
+ * carries a branch or pull-request icon, everything is sorted by name and
42
+ * filterable via the search box at the top. The menu is sized to match the
43
+ * trigger width.
44
+ */
45
+
46
+ var SANS = '-apple-system, BlinkMacSystemFont, "Roboto", "Helvetica Neue", Arial, sans-serif';
47
+
48
+ /* ---- Mock data ------------------------------------------------------- */
49
+
50
+ var LINKABLES = [{
51
+ id: "pr-500",
52
+ kind: "pr",
53
+ // Deliberately long, to show the name truncating with an ellipsis while the
54
+ // right-aligned detail and radio stay visible.
55
+ name: "#500 Refactor rank recalculation to support multi-region contract archival and backfill",
56
+ repoId: "backend",
57
+ updatedMinutesAgo: 8,
58
+ author: "Nikola M."
59
+ }, {
60
+ id: "branch-cache",
61
+ kind: "branch",
62
+ name: "spike/rank-cache",
63
+ repoId: "backend",
64
+ updatedMinutesAgo: 30
65
+ }, {
66
+ id: "branch-export",
67
+ kind: "branch",
68
+ name: "feature/retainer-export-34",
69
+ repoId: "backend",
70
+ updatedMinutesAgo: 5 * 60
71
+ }, {
72
+ id: "pr-119900",
73
+ kind: "pr",
74
+ name: "#119900 Rank API endpoints",
75
+ repoId: "backend",
76
+ updatedMinutesAgo: 2 * 24 * 60,
77
+ author: "Ilija S."
78
+ }, {
79
+ id: "branch-fe-retainers",
80
+ kind: "branch",
81
+ name: "feature/retainers-ui-34",
82
+ repoId: "frontend",
83
+ updatedMinutesAgo: 2 * 60
84
+ }, {
85
+ id: "pr-412",
86
+ kind: "pr",
87
+ name: "#412 Contract list filters",
88
+ repoId: "frontend",
89
+ updatedMinutesAgo: 24 * 60,
90
+ author: "Marko K."
91
+ }, {
92
+ id: "mr-88",
93
+ kind: "pr",
94
+ name: "!88 Bump worker memory",
95
+ repoId: "infra",
96
+ updatedMinutesAgo: 3 * 24 * 60,
97
+ author: "Ana P."
98
+ }, {
99
+ id: "branch-deploy",
100
+ kind: "branch",
101
+ name: "chore/deploy-rank-cache",
102
+ repoId: "infra",
103
+ updatedMinutesAgo: 24 * 60
104
+ }];
105
+ var MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
106
+ var pad = function pad(n) {
107
+ return String(n).padStart(2, "0");
108
+ };
109
+
110
+ /**
111
+ * Reproduces the format of ActiveCollab's standard `Ago` component
112
+ * (`Angie.functions.ago()`) for the mock: "Just now", "N minutes ago",
113
+ * "Today HH:mm", "Yesterday HH:mm", "MMM D. HH:mm", else "MMM D. YYYY HH:mm".
114
+ * Production must use the real component.
115
+ */
116
+ var formatAgo = function formatAgo(minutesAgo) {
117
+ var now = new Date();
118
+ var then = new Date(now.getTime() - minutesAgo * 60000);
119
+ if (minutesAgo < 2) {
120
+ return "Just now";
121
+ }
122
+ if (minutesAgo < 60) {
123
+ return "".concat(Math.floor(minutesAgo), " minutes ago");
124
+ }
125
+ var time = "".concat(pad(then.getHours()), ":").concat(pad(then.getMinutes()));
126
+ if (then.toDateString() === now.toDateString()) {
127
+ return "Today ".concat(time);
128
+ }
129
+ var yesterday = new Date(now.getTime() - 24 * 60 * 60000);
130
+ if (then.toDateString() === yesterday.toDateString()) {
131
+ return "Yesterday ".concat(time);
132
+ }
133
+ var monthDay = "".concat(MONTHS[then.getMonth()], " ").concat(then.getDate(), ".");
134
+ if (then.getFullYear() === now.getFullYear()) {
135
+ return "".concat(monthDay, " ").concat(time);
136
+ }
137
+ return "".concat(monthDay, " ").concat(then.getFullYear(), " ").concat(time);
138
+ };
139
+
140
+ /**
141
+ * The detail shown on the right of an option: a branch keeps just the time of
142
+ * its last activity; a pull request appends the author ("… by Name").
143
+ */
144
+ var linkableDetail = function linkableDetail(item) {
145
+ return item.kind === "pr" && item.author ? "".concat(formatAgo(item.updatedMinutesAgo), " by ").concat(item.author) : formatAgo(item.updatedMinutesAgo);
146
+ };
147
+
148
+ /**
149
+ * Grouped options for the Select. One group per repository, labelled
150
+ * "repo (Org, Type)" and sorted by name; inside a group, branches and PRs are
151
+ * ordered by latest activity (freshest first). Standard option rendering shows
152
+ * the name (truncated) with the detail right-aligned and a radio.
153
+ */
154
+ var GROUPED_OPTIONS = _ConnectRepositoryDialog.PROJECT_REPOSITORIES.map(function (repo) {
155
+ var connection = _ConnectRepositoryDialog.CONNECTIONS.find(function (c) {
156
+ return c.id === repo.connectionId;
157
+ });
158
+ var items = LINKABLES.filter(function (l) {
159
+ return l.repoId === repo.id;
160
+ }).sort(function (a, b) {
161
+ return a.updatedMinutesAgo - b.updatedMinutesAgo;
162
+ }).map(function (l) {
163
+ return {
164
+ id: l.id,
165
+ name: l.name,
166
+ additionalInfo: linkableDetail(l)
167
+ };
168
+ });
169
+ return {
170
+ id: repo.id,
171
+ name: connection ? "".concat(repo.name, " (").concat(connection.name, ", ").concat((0, _ConnectRepositoryDialog.serviceLabel)(connection.service), ")") : repo.name,
172
+ options: items
173
+ };
174
+ }).filter(function (group) {
175
+ return group.options.length > 0;
176
+ }).sort(function (a, b) {
177
+ return a.name.localeCompare(b.name);
178
+ });
179
+ var ALL_ITEMS = LINKABLES;
180
+
181
+ /* ---- Branch mock data (for the New Branch / New Pull Request bases) --- */
182
+
183
+ var BRANCHES = [
184
+ // activecollab/backend
185
+ {
186
+ id: "backend-main",
187
+ name: "main",
188
+ repoId: "backend",
189
+ isDefault: true,
190
+ updatedMinutesAgo: 60
191
+ }, {
192
+ id: "backend-cache",
193
+ name: "spike/rank-cache",
194
+ repoId: "backend",
195
+ updatedMinutesAgo: 30
196
+ }, {
197
+ id: "backend-export",
198
+ name: "feature/retainer-export-34",
199
+ repoId: "backend",
200
+ updatedMinutesAgo: 5 * 60
201
+ }, {
202
+ id: "backend-hotfix",
203
+ name: "hotfix/rank-typo",
204
+ repoId: "backend",
205
+ updatedMinutesAgo: 3 * 24 * 60
206
+ },
207
+ // activecollab/frontend
208
+ {
209
+ id: "frontend-main",
210
+ name: "main",
211
+ repoId: "frontend",
212
+ isDefault: true,
213
+ updatedMinutesAgo: 90
214
+ }, {
215
+ id: "frontend-retainers",
216
+ name: "feature/retainers-ui-34",
217
+ repoId: "frontend",
218
+ updatedMinutesAgo: 2 * 60
219
+ }, {
220
+ id: "frontend-filters",
221
+ name: "feature/contract-filters",
222
+ repoId: "frontend",
223
+ updatedMinutesAgo: 24 * 60
224
+ },
225
+ // activecollab/infrastructure
226
+ {
227
+ id: "infra-master",
228
+ name: "master",
229
+ repoId: "infra",
230
+ isDefault: true,
231
+ updatedMinutesAgo: 6 * 60
232
+ }, {
233
+ id: "infra-deploy",
234
+ name: "chore/deploy-rank-cache",
235
+ repoId: "infra",
236
+ updatedMinutesAgo: 24 * 60
237
+ }];
238
+ var repoBranches = function repoBranches(repoId) {
239
+ return BRANCHES.filter(function (b) {
240
+ return b.repoId === repoId;
241
+ });
242
+ };
243
+ var repoDefaultBranchId = function repoDefaultBranchId(repoId) {
244
+ var _repoBranches$find$id, _repoBranches$find;
245
+ return (_repoBranches$find$id = (_repoBranches$find = repoBranches(repoId).find(function (b) {
246
+ return b.isDefault;
247
+ })) === null || _repoBranches$find === void 0 ? void 0 : _repoBranches$find.id) !== null && _repoBranches$find$id !== void 0 ? _repoBranches$find$id : null;
248
+ };
249
+ /**
250
+ * Base-branch options (Create From / Merge Into): the default branch first with
251
+ * no timestamp, then the rest sorted by latest activity (freshest first), each
252
+ * with a muted "last activity" time.
253
+ */
254
+ var baseBranchOptions = function baseBranchOptions(repoId) {
255
+ var branches = repoBranches(repoId);
256
+ var defaults = branches.filter(function (b) {
257
+ return b.isDefault;
258
+ }).map(function (b) {
259
+ return {
260
+ id: b.id,
261
+ name: b.name
262
+ };
263
+ });
264
+ var rest = branches.filter(function (b) {
265
+ return !b.isDefault;
266
+ }).sort(function (a, b) {
267
+ return a.updatedMinutesAgo - b.updatedMinutesAgo;
268
+ }).map(function (b) {
269
+ return {
270
+ id: b.id,
271
+ name: b.name,
272
+ additionalInfo: formatAgo(b.updatedMinutesAgo)
273
+ };
274
+ });
275
+ return [...defaults, ...rest];
276
+ };
277
+
278
+ /**
279
+ * Source-branch options (New Pull Request): the default branch is excluded — you
280
+ * don't open a PR to merge the trunk into a feature branch — and the rest are
281
+ * sorted by latest activity, each with a muted "last activity" time.
282
+ */
283
+ var sourceBranchOptions = function sourceBranchOptions(repoId) {
284
+ return repoBranches(repoId).filter(function (b) {
285
+ return !b.isDefault;
286
+ }).sort(function (a, b) {
287
+ return a.updatedMinutesAgo - b.updatedMinutesAgo;
288
+ }).map(function (b) {
289
+ return {
290
+ id: b.id,
291
+ name: b.name,
292
+ additionalInfo: formatAgo(b.updatedMinutesAgo)
293
+ };
294
+ });
295
+ };
296
+
297
+ /* ---- Styles ---------------------------------------------------------- */
298
+
299
+ var StyledLinkBody = _styledComponents.default.div.withConfig({
300
+ displayName: "LinkBranchOrPullRequestDialog__StyledLinkBody",
301
+ componentId: "sc-2wiwoe-0"
302
+ })(["font-family:", ";.lk-tabbody{margin-top:18px;}.lk-field{margin-bottom:16px;}.lk-field:last-child{margin-bottom:0;}.lk-label{display:block;margin-bottom:6px;}.lk-control,.lk-control.c-input-wrapper{width:100%;max-width:none;}.lk-repo-hint{display:block;margin-top:8px;}.lk-repo-link{background:none;border:none;padding:0;font:inherit;color:var(--color-primary);cursor:pointer;}.lk-repo-link:hover{text-decoration:underline;}.lk-skeleton .sk-row{margin-bottom:18px;}.lk-skeleton .sk-choose{width:100%;height:36px;border-radius:6px;}.lk-skeleton .sk-label{width:160px;height:12px;margin-bottom:8px;}.lk-skeleton .sk-control{width:100%;height:40px;border-radius:6px;}"], SANS);
303
+
304
+ /**
305
+ * The grouped select menu renders through a portal, so the "match the trigger
306
+ * width" override has to be global, scoped to the menu's class. `$menuWidth` is
307
+ * measured from the trigger and injected here.
308
+ */
309
+ var MenuGlobalStyle = (0, _styledComponents.createGlobalStyle)([".c-select.lk-existing-select-menu{", "}.c-select.lk-existing-select-menu .c-option--text + span{color:var(--color-theme-600);font-size:12px;}"], function (_ref) {
310
+ var $menuWidth = _ref.$menuWidth;
311
+ return $menuWidth ? "width: ".concat($menuWidth, "px !important; max-width: none !important;") : "";
312
+ });
313
+
314
+ /**
315
+ * Per-instance global style for a branch select menu: matches the trigger width
316
+ * and applies the standard muted styling to the right-aligned "last activity".
317
+ */
318
+ var BranchMenuGlobalStyle = (0, _styledComponents.createGlobalStyle)([".c-select.", "{", "}.c-select.", " .c-option--text + span{color:var(--color-theme-600);font-size:12px;}"], function (p) {
319
+ return p.$cls;
320
+ }, function (p) {
321
+ return p.$w ? "width: ".concat(p.$w, "px !important; max-width: none !important;") : "";
322
+ }, function (p) {
323
+ return p.$cls;
324
+ });
325
+ var BranchSelectWrap = _styledComponents.default.div.withConfig({
326
+ displayName: "LinkBranchOrPullRequestDialog__BranchSelectWrap",
327
+ componentId: "sc-2wiwoe-1"
328
+ })(["font-family:", ";.branch-trigger{width:100%;max-width:none;}"], SANS);
329
+ /**
330
+ * Flat branch picker (Create From / Source Branch / Merge Into). The caller
331
+ * supplies the option order (default-first or activity-sorted); the DS internal
332
+ * alphabetical sort is disabled so that order is preserved.
333
+ */
334
+ var BranchSelect = function BranchSelect(_ref2) {
335
+ var _options$find$name, _options$find;
336
+ var options = _ref2.options,
337
+ selected = _ref2.selected,
338
+ _onChange = _ref2.onChange,
339
+ _ref2$placeholder = _ref2.placeholder,
340
+ placeholder = _ref2$placeholder === void 0 ? "Select branch" : _ref2$placeholder;
341
+ var wrapRef = (0, _react.useRef)(null);
342
+ var _useState = (0, _react.useState)(),
343
+ _useState2 = _slicedToArray(_useState, 2),
344
+ menuWidth = _useState2[0],
345
+ setMenuWidth = _useState2[1];
346
+ var _useState3 = (0, _react.useState)(function () {
347
+ return "branch-select-menu-".concat(Math.random().toString(36).slice(2));
348
+ }),
349
+ _useState4 = _slicedToArray(_useState3, 1),
350
+ menuCls = _useState4[0];
351
+ var measure = (0, _react.useCallback)(function () {
352
+ if (wrapRef.current) {
353
+ setMenuWidth(wrapRef.current.offsetWidth);
354
+ }
355
+ }, []);
356
+ (0, _react.useEffect)(function () {
357
+ measure();
358
+ }, [measure]);
359
+ var selectedName = (_options$find$name = (_options$find = options.find(function (o) {
360
+ return o.id === selected;
361
+ })) === null || _options$find === void 0 ? void 0 : _options$find.name) !== null && _options$find$name !== void 0 ? _options$find$name : placeholder;
362
+ return /*#__PURE__*/_react.default.createElement(BranchSelectWrap, {
363
+ ref: wrapRef
364
+ }, /*#__PURE__*/_react.default.createElement(BranchMenuGlobalStyle, {
365
+ $cls: menuCls,
366
+ $w: menuWidth
367
+ }), /*#__PURE__*/_react.default.createElement(_Select.Select, {
368
+ options: options,
369
+ selected: selected === null ? undefined : selected,
370
+ onChange: function onChange(v) {
371
+ return _onChange(String(v));
372
+ },
373
+ placeholder: "Search branches",
374
+ selectClassName: menuCls,
375
+ onSelectOpen: measure,
376
+ disabledInternalSort: true,
377
+ forceCloseMenu: true,
378
+ target: /*#__PURE__*/_react.default.createElement(_SelectTrigger.SelectTrigger, {
379
+ className: "branch-trigger",
380
+ typographyProps: selected === null ? {
381
+ color: "tertiary"
382
+ } : undefined
383
+ }, selectedName)
384
+ }));
385
+ };
386
+ var MODE_OPTIONS = [{
387
+ id: "existing",
388
+ name: "Link Existing"
389
+ }, {
390
+ id: "branch",
391
+ name: "New Branch"
392
+ }, {
393
+ id: "pr",
394
+ name: "New Pull Request"
395
+ }];
396
+ var LinkBranchOrPullRequestDialog = exports.LinkBranchOrPullRequestDialog = function LinkBranchOrPullRequestDialog(_ref3) {
397
+ var _ALL_ITEMS$find$name, _ALL_ITEMS$find;
398
+ var open = _ref3.open,
399
+ onClose = _ref3.onClose;
400
+ var _useState5 = (0, _react.useState)("existing"),
401
+ _useState6 = _slicedToArray(_useState5, 2),
402
+ mode = _useState6[0],
403
+ setMode = _useState6[1];
404
+ var _useState7 = (0, _react.useState)(null),
405
+ _useState8 = _slicedToArray(_useState7, 2),
406
+ selected = _useState8[0],
407
+ setSelected = _useState8[1];
408
+ var _useState9 = (0, _react.useState)("feature/retainers-34"),
409
+ _useState0 = _slicedToArray(_useState9, 2),
410
+ branchName = _useState0[0],
411
+ setBranchName = _useState0[1];
412
+ var _useState1 = (0, _react.useState)("#34 Retainers & Contracts functionality"),
413
+ _useState10 = _slicedToArray(_useState1, 2),
414
+ prTitle = _useState10[0],
415
+ setPrTitle = _useState10[1];
416
+ var _useState11 = (0, _react.useState)(false),
417
+ _useState12 = _slicedToArray(_useState11, 2),
418
+ attempted = _useState12[0],
419
+ setAttempted = _useState12[1];
420
+ var _useState13 = (0, _react.useState)(true),
421
+ _useState14 = _slicedToArray(_useState13, 2),
422
+ loading = _useState14[0],
423
+ setLoading = _useState14[1];
424
+ var _useState15 = (0, _react.useState)(),
425
+ _useState16 = _slicedToArray(_useState15, 2),
426
+ menuWidth = _useState16[0],
427
+ setMenuWidth = _useState16[1];
428
+
429
+ // Repository picker (New Branch / New Pull Request) + connect-repository flow.
430
+ var _useState17 = (0, _react.useState)("backend"),
431
+ _useState18 = _slicedToArray(_useState17, 2),
432
+ repo = _useState18[0],
433
+ setRepo = _useState18[1];
434
+ var _useState19 = (0, _react.useState)(false),
435
+ _useState20 = _slicedToArray(_useState19, 2),
436
+ connectOpen = _useState20[0],
437
+ setConnectOpen = _useState20[1];
438
+ var _useState21 = (0, _react.useState)([]),
439
+ _useState22 = _slicedToArray(_useState21, 2),
440
+ extraRepos = _useState22[0],
441
+ setExtraRepos = _useState22[1];
442
+
443
+ // Branch bases. Create From / Merge Into default to the repo's default branch;
444
+ // Source Branch starts unselected.
445
+ var _useState23 = (0, _react.useState)(function () {
446
+ return repoDefaultBranchId("backend");
447
+ }),
448
+ _useState24 = _slicedToArray(_useState23, 2),
449
+ createFrom = _useState24[0],
450
+ setCreateFrom = _useState24[1];
451
+ var _useState25 = (0, _react.useState)(null),
452
+ _useState26 = _slicedToArray(_useState25, 2),
453
+ sourceBranch = _useState26[0],
454
+ setSourceBranch = _useState26[1];
455
+ var _useState27 = (0, _react.useState)(function () {
456
+ return repoDefaultBranchId("backend");
457
+ }),
458
+ _useState28 = _slicedToArray(_useState27, 2),
459
+ mergeInto = _useState28[0],
460
+ setMergeInto = _useState28[1];
461
+
462
+ // When the repository changes, reset the bases: default branch for
463
+ // Create From / Merge Into, nothing for Source Branch.
464
+ (0, _react.useEffect)(function () {
465
+ var defaultId = repoDefaultBranchId(repo);
466
+ setCreateFrom(defaultId);
467
+ setMergeInto(defaultId);
468
+ setSourceBranch(null);
469
+ }, [repo]);
470
+ var fieldRef = (0, _react.useRef)(null);
471
+
472
+ // Simulate the API loads that will drive the pickers: a ~1s skeleton on open.
473
+ (0, _react.useEffect)(function () {
474
+ if (!open) {
475
+ return undefined;
476
+ }
477
+ setLoading(true);
478
+ var timer = window.setTimeout(function () {
479
+ return setLoading(false);
480
+ }, 1000);
481
+ return function () {
482
+ return window.clearTimeout(timer);
483
+ };
484
+ }, [open]);
485
+ var measureMenu = (0, _react.useCallback)(function () {
486
+ if (fieldRef.current) {
487
+ setMenuWidth(fieldRef.current.offsetWidth);
488
+ }
489
+ }, []);
490
+
491
+ // Keep the menu width in sync with the trigger once the form is visible.
492
+ (0, _react.useEffect)(function () {
493
+ if (open && !loading && mode === "existing") {
494
+ measureMenu();
495
+ }
496
+ }, [open, loading, mode, measureMenu]);
497
+
498
+ // Submit is always enabled; validation runs on click and outlines fields.
499
+ var existingInvalid = attempted && mode === "existing" && selected === null;
500
+ var branchInvalid = attempted && mode === "branch" && branchName.trim() === "";
501
+ var titleInvalid = attempted && mode === "pr" && prTitle.trim() === "";
502
+ var primaryLabel = mode === "existing" ? "Link" : mode === "branch" ? "Create Branch" : "Create Pull Request";
503
+ var close = function close() {
504
+ setAttempted(false);
505
+ onClose();
506
+ };
507
+ var handleSubmit = function handleSubmit() {
508
+ var valid = mode === "existing" ? selected !== null : mode === "branch" ? branchName.trim() !== "" : prTitle.trim() !== "";
509
+ if (!valid) {
510
+ setAttempted(true);
511
+ return;
512
+ }
513
+ close();
514
+ };
515
+ var changeMode = function changeMode(next) {
516
+ setMode(next);
517
+ setAttempted(false);
518
+ };
519
+ var selectedLabel = (_ALL_ITEMS$find$name = (_ALL_ITEMS$find = ALL_ITEMS.find(function (o) {
520
+ return o.id === selected;
521
+ })) === null || _ALL_ITEMS$find === void 0 ? void 0 : _ALL_ITEMS$find.name) !== null && _ALL_ITEMS$find$name !== void 0 ? _ALL_ITEMS$find$name : "Select branch or pull request";
522
+
523
+ // Repositories already on the project (plus any just connected), and the
524
+ // remaining ones that can still be connected from here.
525
+ var projectRepos = [..._ConnectRepositoryDialog.PROJECT_REPOSITORIES, ...extraRepos];
526
+ var connectableRepos = _ConnectRepositoryDialog.CONNECTABLE_REPOSITORIES.filter(function (r) {
527
+ return !projectRepos.some(function (p) {
528
+ return p.id === r.id;
529
+ });
530
+ });
531
+ var handleConnected = function handleConnected(connected) {
532
+ setExtraRepos(function (prev) {
533
+ return prev.some(function (r) {
534
+ return r.id === connected.id;
535
+ }) ? prev : [...prev, connected];
536
+ });
537
+ // The repository just connected becomes the selection in the picker.
538
+ setRepo(connected.id);
539
+ };
540
+ var renderRepositoryField = function renderRepositoryField() {
541
+ return /*#__PURE__*/_react.default.createElement("div", {
542
+ className: "lk-field"
543
+ }, /*#__PURE__*/_react.default.createElement(_Label.Label, {
544
+ size: "small",
545
+ className: "lk-label"
546
+ }, "Repository"), /*#__PURE__*/_react.default.createElement(_ConnectRepositoryDialog.RepositorySelect, {
547
+ repositories: projectRepos,
548
+ connections: _ConnectRepositoryDialog.CONNECTIONS,
549
+ selected: repo,
550
+ onChange: setRepo
551
+ }), /*#__PURE__*/_react.default.createElement(_Typography.Caption1, {
552
+ color: "tertiary",
553
+ className: "lk-repo-hint"
554
+ }, "Only repositories connected to this project are listed.", " ", /*#__PURE__*/_react.default.createElement("button", {
555
+ type: "button",
556
+ className: "lk-repo-link",
557
+ onClick: function onClick() {
558
+ return setConnectOpen(true);
559
+ }
560
+ }, "Connect a repository"), " ", "if the one you need is missing."));
561
+ };
562
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_Dialog.Dialog, {
563
+ open: open,
564
+ onClose: close,
565
+ disableCloseOnEsc: true
566
+ }, /*#__PURE__*/_react.default.createElement(MenuGlobalStyle, {
567
+ $menuWidth: menuWidth
568
+ }), /*#__PURE__*/_react.default.createElement(_Dialog.Dialog.Title, null, "Link Branch or Pull Request"), /*#__PURE__*/_react.default.createElement(_Dialog.Dialog.ContentDivider, null), /*#__PURE__*/_react.default.createElement(_Dialog.Dialog.Content, null, /*#__PURE__*/_react.default.createElement(StyledLinkBody, null, loading ? /*#__PURE__*/_react.default.createElement("div", {
569
+ className: "lk-skeleton"
570
+ }, /*#__PURE__*/_react.default.createElement("div", {
571
+ className: "sk-row"
572
+ }, /*#__PURE__*/_react.default.createElement(_Loaders.SkeletonLoader, {
573
+ className: "sk-choose"
574
+ })), /*#__PURE__*/_react.default.createElement("div", {
575
+ className: "sk-row"
576
+ }, /*#__PURE__*/_react.default.createElement(_Loaders.SkeletonLoader, {
577
+ className: "sk-label"
578
+ }), /*#__PURE__*/_react.default.createElement(_Loaders.SkeletonLoader, {
579
+ className: "sk-control"
580
+ }))) : /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_ChooseV.ChooseV2, {
581
+ required: true,
582
+ options: MODE_OPTIONS,
583
+ selected: [mode],
584
+ onChange: function onChange(ids) {
585
+ return changeMode(ids[0]);
586
+ }
587
+ }), /*#__PURE__*/_react.default.createElement("div", {
588
+ className: "lk-tabbody"
589
+ }, mode === "existing" ? /*#__PURE__*/_react.default.createElement("div", {
590
+ className: "lk-field",
591
+ ref: fieldRef
592
+ }, /*#__PURE__*/_react.default.createElement(_Label.Label, {
593
+ size: "small",
594
+ className: "lk-label",
595
+ invalid: existingInvalid
596
+ }, "Branch or Pull Request"), /*#__PURE__*/_react.default.createElement(_Select.Select, {
597
+ options: GROUPED_OPTIONS,
598
+ selected: selected === null ? undefined : selected,
599
+ onChange: function onChange(v) {
600
+ return setSelected(v);
601
+ },
602
+ placeholder: "Search branches and pull requests",
603
+ selectClassName: "lk-existing-select-menu",
604
+ onSelectOpen: measureMenu,
605
+ disabledInternalSort: true,
606
+ forceCloseMenu: true,
607
+ target: /*#__PURE__*/_react.default.createElement(_SelectTrigger.SelectTrigger, {
608
+ className: "lk-control",
609
+ invalid: existingInvalid,
610
+ typographyProps: selected === null ? {
611
+ color: "tertiary"
612
+ } : undefined
613
+ }, selectedLabel)
614
+ })) : mode === "branch" ? /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, renderRepositoryField(), /*#__PURE__*/_react.default.createElement("div", {
615
+ className: "lk-field"
616
+ }, /*#__PURE__*/_react.default.createElement(_Label.Label, {
617
+ size: "small",
618
+ className: "lk-label",
619
+ invalid: branchInvalid
620
+ }, "Branch Name"), /*#__PURE__*/_react.default.createElement(_Input.Input, {
621
+ className: "lk-control",
622
+ value: branchName,
623
+ invalid: branchInvalid,
624
+ onChange: function onChange(e) {
625
+ return setBranchName(e.target.value);
626
+ }
627
+ })), /*#__PURE__*/_react.default.createElement("div", {
628
+ className: "lk-field"
629
+ }, /*#__PURE__*/_react.default.createElement(_Label.Label, {
630
+ size: "small",
631
+ className: "lk-label"
632
+ }, "Create From"), /*#__PURE__*/_react.default.createElement(BranchSelect, {
633
+ options: baseBranchOptions(repo),
634
+ selected: createFrom,
635
+ onChange: setCreateFrom,
636
+ placeholder: "Select base branch"
637
+ }))) : /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, renderRepositoryField(), /*#__PURE__*/_react.default.createElement("div", {
638
+ className: "lk-field"
639
+ }, /*#__PURE__*/_react.default.createElement(_Label.Label, {
640
+ size: "small",
641
+ className: "lk-label"
642
+ }, "Source Branch"), /*#__PURE__*/_react.default.createElement(BranchSelect, {
643
+ options: sourceBranchOptions(repo),
644
+ selected: sourceBranch,
645
+ onChange: setSourceBranch,
646
+ placeholder: "Select source branch"
647
+ })), /*#__PURE__*/_react.default.createElement("div", {
648
+ className: "lk-field"
649
+ }, /*#__PURE__*/_react.default.createElement(_Label.Label, {
650
+ size: "small",
651
+ className: "lk-label"
652
+ }, "Merge Into"), /*#__PURE__*/_react.default.createElement(BranchSelect, {
653
+ options: baseBranchOptions(repo),
654
+ selected: mergeInto,
655
+ onChange: setMergeInto,
656
+ placeholder: "Select base branch"
657
+ })), /*#__PURE__*/_react.default.createElement("div", {
658
+ className: "lk-field"
659
+ }, /*#__PURE__*/_react.default.createElement(_Label.Label, {
660
+ size: "small",
661
+ className: "lk-label",
662
+ invalid: titleInvalid
663
+ }, "Title"), /*#__PURE__*/_react.default.createElement(_Input.Input, {
664
+ className: "lk-control",
665
+ value: prTitle,
666
+ invalid: titleInvalid,
667
+ onChange: function onChange(e) {
668
+ return setPrTitle(e.target.value);
669
+ }
670
+ }))))))), /*#__PURE__*/_react.default.createElement(_Dialog.Dialog.ContentDivider, null), /*#__PURE__*/_react.default.createElement(_Dialog.Dialog.Actions, null, /*#__PURE__*/_react.default.createElement(_Button.Button, {
671
+ variant: "primary",
672
+ style: {
673
+ marginRight: 12
674
+ },
675
+ disabled: loading,
676
+ onClick: handleSubmit
677
+ }, primaryLabel), /*#__PURE__*/_react.default.createElement(_Button.Button, {
678
+ variant: "secondary",
679
+ onClick: close
680
+ }, "Cancel"))), /*#__PURE__*/_react.default.createElement(_ConnectRepositoryDialog.ConnectRepositoryDialog, {
681
+ open: connectOpen,
682
+ onClose: function onClose() {
683
+ return setConnectOpen(false);
684
+ },
685
+ onConnect: handleConnected,
686
+ repositories: connectableRepos,
687
+ connections: _ConnectRepositoryDialog.CONNECTIONS
688
+ }));
689
+ };
690
+ //# sourceMappingURL=LinkBranchOrPullRequestDialog.js.map