@activecollab/components 2.0.440 → 2.0.442
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/cjs/components/Dialog/Dialog.js +8 -1
- package/dist/cjs/components/Dialog/Dialog.js.map +1 -1
- package/dist/cjs/components/Modal/Modal.js +16 -4
- package/dist/cjs/components/Modal/Modal.js.map +1 -1
- package/dist/cjs/components/Transitions/Fade/Fade.js +3 -2
- package/dist/cjs/components/Transitions/Fade/Fade.js.map +1 -1
- package/dist/cjs/components/Transitions/SlideFromTop/SlideFromTop.js +7 -5
- package/dist/cjs/components/Transitions/SlideFromTop/SlideFromTop.js.map +1 -1
- package/dist/cjs/presentation/shared/UserDetailsDialog.js +125 -0
- package/dist/cjs/presentation/shared/UserDetailsDialog.js.map +1 -0
- package/dist/cjs/presentation/shared/index.js +15 -0
- package/dist/cjs/presentation/shared/index.js.map +1 -1
- package/dist/cjs/presentation/whiteboard/bottomDock.js +10 -3
- package/dist/cjs/presentation/whiteboard/bottomDock.js.map +1 -1
- package/dist/cjs/presentation/whiteboard/canvasElements.js +114 -25
- package/dist/cjs/presentation/whiteboard/canvasElements.js.map +1 -1
- package/dist/cjs/presentation/whiteboard/entityCardActions.js +79 -0
- package/dist/cjs/presentation/whiteboard/entityCardActions.js.map +1 -0
- package/dist/cjs/presentation/whiteboard/inspector.js +20 -5
- package/dist/cjs/presentation/whiteboard/inspector.js.map +1 -1
- package/dist/cjs/presentation/whiteboard/outline.js +4 -2
- package/dist/cjs/presentation/whiteboard/outline.js.map +1 -1
- package/dist/cjs/presentation/whiteboard/projectElements.js +188 -53
- package/dist/cjs/presentation/whiteboard/projectElements.js.map +1 -1
- package/dist/esm/components/Dialog/Dialog.d.ts.map +1 -1
- package/dist/esm/components/Dialog/Dialog.js +10 -3
- package/dist/esm/components/Dialog/Dialog.js.map +1 -1
- package/dist/esm/components/Modal/Modal.d.ts +5 -0
- package/dist/esm/components/Modal/Modal.d.ts.map +1 -1
- package/dist/esm/components/Modal/Modal.js +16 -4
- package/dist/esm/components/Modal/Modal.js.map +1 -1
- package/dist/esm/components/Transitions/Fade/Fade.d.ts +1 -0
- package/dist/esm/components/Transitions/Fade/Fade.d.ts.map +1 -1
- package/dist/esm/components/Transitions/Fade/Fade.js +2 -1
- package/dist/esm/components/Transitions/Fade/Fade.js.map +1 -1
- package/dist/esm/components/Transitions/SlideFromTop/SlideFromTop.d.ts +2 -0
- package/dist/esm/components/Transitions/SlideFromTop/SlideFromTop.d.ts.map +1 -1
- package/dist/esm/components/Transitions/SlideFromTop/SlideFromTop.js +6 -4
- package/dist/esm/components/Transitions/SlideFromTop/SlideFromTop.js.map +1 -1
- package/dist/esm/presentation/shared/UserDetailsDialog.d.ts +45 -0
- package/dist/esm/presentation/shared/UserDetailsDialog.d.ts.map +1 -0
- package/dist/esm/presentation/shared/UserDetailsDialog.js +115 -0
- package/dist/esm/presentation/shared/UserDetailsDialog.js.map +1 -0
- package/dist/esm/presentation/shared/index.d.ts +2 -0
- package/dist/esm/presentation/shared/index.d.ts.map +1 -1
- package/dist/esm/presentation/shared/index.js +1 -0
- package/dist/esm/presentation/shared/index.js.map +1 -1
- package/dist/esm/presentation/whiteboard/bottomDock.d.ts +3 -2
- package/dist/esm/presentation/whiteboard/bottomDock.d.ts.map +1 -1
- package/dist/esm/presentation/whiteboard/bottomDock.js +9 -4
- package/dist/esm/presentation/whiteboard/bottomDock.js.map +1 -1
- package/dist/esm/presentation/whiteboard/canvasElements.d.ts.map +1 -1
- package/dist/esm/presentation/whiteboard/canvasElements.js +94 -25
- package/dist/esm/presentation/whiteboard/canvasElements.js.map +1 -1
- package/dist/esm/presentation/whiteboard/entityCardActions.d.ts +37 -0
- package/dist/esm/presentation/whiteboard/entityCardActions.d.ts.map +1 -0
- package/dist/esm/presentation/whiteboard/entityCardActions.js +69 -0
- package/dist/esm/presentation/whiteboard/entityCardActions.js.map +1 -0
- package/dist/esm/presentation/whiteboard/inspector.d.ts.map +1 -1
- package/dist/esm/presentation/whiteboard/inspector.js +29 -7
- package/dist/esm/presentation/whiteboard/inspector.js.map +1 -1
- package/dist/esm/presentation/whiteboard/outline.d.ts +1 -1
- package/dist/esm/presentation/whiteboard/outline.d.ts.map +1 -1
- package/dist/esm/presentation/whiteboard/outline.js +5 -3
- package/dist/esm/presentation/whiteboard/outline.js.map +1 -1
- package/dist/esm/presentation/whiteboard/projectElements.d.ts +40 -8
- package/dist/esm/presentation/whiteboard/projectElements.d.ts.map +1 -1
- package/dist/esm/presentation/whiteboard/projectElements.js +181 -55
- package/dist/esm/presentation/whiteboard/projectElements.js.map +1 -1
- package/dist/index.js +34 -10
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/package.json +1 -1
|
@@ -3,7 +3,7 @@ import React, { useMemo, useRef, useState } from "react";
|
|
|
3
3
|
import styled from "styled-components";
|
|
4
4
|
import { SELECTION_BLUE, StyledCanvasElement } from "./elements";
|
|
5
5
|
import { IconButton } from "../../components/IconButton";
|
|
6
|
-
import { ArrowLeftIcon, SortGeneralIcon } from "../../components/Icons";
|
|
6
|
+
import { ArrowLeftIcon, PersonIcon, SortGeneralIcon } from "../../components/Icons";
|
|
7
7
|
import { Input } from "../../components/Input";
|
|
8
8
|
import { SkeletonLoader } from "../../components/Loaders";
|
|
9
9
|
import { Modal } from "../../components/Modal";
|
|
@@ -12,7 +12,7 @@ import { RadioButton } from "../../components/RadioButton";
|
|
|
12
12
|
import { StackedCard } from "../../components/StackedCard";
|
|
13
13
|
import { Tooltip } from "../../components/Tooltip";
|
|
14
14
|
import { Body2, Caption1 } from "../../components/Typography";
|
|
15
|
-
import { AVATAR_COLORS } from "../shared";
|
|
15
|
+
import { AVATAR_COLORS, RoundAvatar } from "../shared";
|
|
16
16
|
import { INTERNAL_CLIENT_LABEL as CONTENT_INTERNAL_CLIENT_LABEL, ProjectCard, TaskCard } from "../stackedCard/content";
|
|
17
17
|
|
|
18
18
|
/* ------------------------------------------------------------------ */
|
|
@@ -54,8 +54,16 @@ export const TASK_CARD_WIDTH = 260;
|
|
|
54
54
|
|
|
55
55
|
/* How long the "details are being resolved from the backend" flash lasts. */
|
|
56
56
|
export const RESOLVE_MS = 480;
|
|
57
|
-
/** True for the
|
|
58
|
-
export const isProjectTool = tool => tool === "project" || tool === "task";
|
|
57
|
+
/** True for the three board tools this module owns. */
|
|
58
|
+
export const isProjectTool = tool => tool === "project" || tool === "task" || tool === "person";
|
|
59
|
+
|
|
60
|
+
/* A person is not a card: a square whose width IS its height, so the avatar
|
|
61
|
+
circle stays a circle. The drawn width is its side, clamped to these bounds —
|
|
62
|
+
the same 1:1 lock the app enforces on the canvas grip and in the Inspector. */
|
|
63
|
+
export const PERSON_DEFAULT_SIZE = 96;
|
|
64
|
+
export const PERSON_MIN_SIZE = 48;
|
|
65
|
+
export const PERSON_MAX_SIZE = 240;
|
|
66
|
+
export const clampPersonSize = size => Math.min(PERSON_MAX_SIZE, Math.max(PERSON_MIN_SIZE, Math.round(size)));
|
|
59
67
|
|
|
60
68
|
/* ------------------------------------------------------------------ */
|
|
61
69
|
/* Mock data */
|
|
@@ -119,6 +127,18 @@ export const PICKER_PEOPLE = {
|
|
|
119
127
|
}
|
|
120
128
|
};
|
|
121
129
|
|
|
130
|
+
/* The People picker's one flat list: everyone the board knows, by name, with
|
|
131
|
+
no company or project layer — a person chip points at a user, not at a
|
|
132
|
+
membership. The record key doubles as the row id. */
|
|
133
|
+
export const PICKER_PEOPLE_LIST = Object.entries(PICKER_PEOPLE).map(_ref => {
|
|
134
|
+
let id = _ref[0],
|
|
135
|
+
person = _ref[1];
|
|
136
|
+
return {
|
|
137
|
+
id,
|
|
138
|
+
person
|
|
139
|
+
};
|
|
140
|
+
}).sort((a, b) => a.person.name.localeCompare(b.person.name));
|
|
141
|
+
|
|
122
142
|
/* Label colours are data too: they are the label's own colour in the app. */
|
|
123
143
|
export const PICKER_LABELS = {
|
|
124
144
|
assigned: {
|
|
@@ -419,6 +439,10 @@ export const projectElementTitle = element => {
|
|
|
419
439
|
if (element.limited) {
|
|
420
440
|
return LIMITED_ACCESS_LABEL;
|
|
421
441
|
}
|
|
442
|
+
if (element.kind === "person") {
|
|
443
|
+
var _element$person$name, _element$person;
|
|
444
|
+
return (_element$person$name = (_element$person = element.person) == null ? void 0 : _element$person.name) != null ? _element$person$name : "Person";
|
|
445
|
+
}
|
|
422
446
|
if (element.kind === "project") {
|
|
423
447
|
var _element$project$name, _element$project;
|
|
424
448
|
return (_element$project$name = (_element$project = element.project) == null ? void 0 : _element$project.name) != null ? _element$project$name : "Project";
|
|
@@ -452,7 +476,8 @@ const SEEDED = [{
|
|
|
452
476
|
status: "resolved",
|
|
453
477
|
limited: true,
|
|
454
478
|
project: null,
|
|
455
|
-
task: null
|
|
479
|
+
task: null,
|
|
480
|
+
person: null
|
|
456
481
|
},
|
|
457
482
|
x: 120,
|
|
458
483
|
y: 200
|
|
@@ -465,7 +490,8 @@ const SEEDED = [{
|
|
|
465
490
|
status: "resolved",
|
|
466
491
|
limited: true,
|
|
467
492
|
project: null,
|
|
468
|
-
task: null
|
|
493
|
+
task: null,
|
|
494
|
+
person: null
|
|
469
495
|
},
|
|
470
496
|
x: 120,
|
|
471
497
|
y: 380
|
|
@@ -489,7 +515,7 @@ export const SEEDED_PROJECT_ELEMENT_POSITIONS = SEEDED.reduce((acc, seed) => {
|
|
|
489
515
|
export const StyledProjectElementBox = styled(StyledCanvasElement).withConfig({
|
|
490
516
|
displayName: "projectElements__StyledProjectElementBox",
|
|
491
517
|
componentId: "sc-1cayxi5-0"
|
|
492
|
-
})(["border-radius:8px;transition:width 160ms ease;&.limited{cursor:not-allowed;}"]);
|
|
518
|
+
})(["border-radius:8px;transition:width 160ms ease;&.limited{cursor:not-allowed;}&.person{border-radius:50%;}"]);
|
|
493
519
|
|
|
494
520
|
/* The rubber band and the armed tool's hover preview — the same blue dashed
|
|
495
521
|
box the link tool draws, so the gesture reads as one board convention. */
|
|
@@ -498,18 +524,44 @@ export const StyledProjectDraft = styled.div.withConfig({
|
|
|
498
524
|
componentId: "sc-1cayxi5-1"
|
|
499
525
|
})(["position:absolute;box-sizing:border-box;border:1.5px dashed ", ";border-radius:8px;background-color:rgba(59,130,246,0.08);pointer-events:none;"], SELECTION_BLUE);
|
|
500
526
|
|
|
527
|
+
/* The person rubber band and hover preview: the same dashed blue, round. */
|
|
528
|
+
export const StyledPersonDraft = styled(StyledProjectDraft).withConfig({
|
|
529
|
+
displayName: "projectElements__StyledPersonDraft",
|
|
530
|
+
componentId: "sc-1cayxi5-2"
|
|
531
|
+
})(["border-radius:50%;"]);
|
|
532
|
+
|
|
501
533
|
/* The placeholder that waits for the picker's answer. Card-like on purpose:
|
|
502
534
|
rounded, dashed, tinted — a card-shaped hole, not a selection marquee. */
|
|
503
535
|
export const StyledPlaceholder = styled.div.withConfig({
|
|
504
536
|
displayName: "projectElements__StyledPlaceholder",
|
|
505
|
-
componentId: "sc-1cayxi5-
|
|
537
|
+
componentId: "sc-1cayxi5-3"
|
|
506
538
|
})(["box-sizing:border-box;width:100%;height:100%;display:flex;align-items:center;justify-content:center;padding:12px;border:1.5px dashed var(--border-primary);border-radius:8px;background-color:var(--color-theme-200);user-select:none;"]);
|
|
507
539
|
|
|
540
|
+
/* A person's placeholder is the circle its avatar will fill — dashed and
|
|
541
|
+
tinted like the card placeholder, with the person glyph where the face will
|
|
542
|
+
be, so the pick swaps one circle for another without a change of shape. */
|
|
543
|
+
export const StyledPersonPlaceholder = styled(StyledPlaceholder).withConfig({
|
|
544
|
+
displayName: "projectElements__StyledPersonPlaceholder",
|
|
545
|
+
componentId: "sc-1cayxi5-4"
|
|
546
|
+
})(["border-radius:50%;padding:0;color:var(--color-theme-600);svg{width:40%;height:40%;fill:currentColor;}"]);
|
|
547
|
+
export const StyledPersonResolving = styled.div.withConfig({
|
|
548
|
+
displayName: "projectElements__StyledPersonResolving",
|
|
549
|
+
componentId: "sc-1cayxi5-5"
|
|
550
|
+
})(["width:100%;height:100%;border-radius:50%;overflow:hidden;.c-loader{width:100%;height:100%;border-radius:50%;}"]);
|
|
551
|
+
|
|
552
|
+
/* The resolved chip. The avatar fills the element's square and the name hangs
|
|
553
|
+
below it, outside the box: the circle is the whole footprint the board
|
|
554
|
+
measures, so the caption never changes the element's size. */
|
|
555
|
+
export const StyledPersonFace = styled.div.withConfig({
|
|
556
|
+
displayName: "projectElements__StyledPersonFace",
|
|
557
|
+
componentId: "sc-1cayxi5-6"
|
|
558
|
+
})(["position:relative;width:100%;height:100%;border-radius:50%;user-select:none;.person-avatar{width:100%;height:100%;}.person-name{position:absolute;top:100%;left:50%;transform:translateX(-50%);margin-top:6px;white-space:nowrap;}"]);
|
|
559
|
+
|
|
508
560
|
/* The resolving flash: the placeholder's box, with the card's rows sketched in
|
|
509
561
|
so the swap to the real card does not read as a different element. */
|
|
510
562
|
export const StyledResolving = styled(StyledPlaceholder).withConfig({
|
|
511
563
|
displayName: "projectElements__StyledResolving",
|
|
512
|
-
componentId: "sc-1cayxi5-
|
|
564
|
+
componentId: "sc-1cayxi5-7"
|
|
513
565
|
})(["flex-direction:column;align-items:stretch;justify-content:center;gap:10px;.c-loader{height:12px;}"]);
|
|
514
566
|
|
|
515
567
|
/**
|
|
@@ -531,8 +583,8 @@ export const StyledResolving = styled(StyledPlaceholder).withConfig({
|
|
|
531
583
|
*/
|
|
532
584
|
export const StyledLimitedCard = styled.div.withConfig({
|
|
533
585
|
displayName: "projectElements__StyledLimitedCard",
|
|
534
|
-
componentId: "sc-1cayxi5-
|
|
535
|
-
})(["box-sizing:border-box;width:100%;height:100%;min-height:96px;display:flex;align-items:center;justify-content:center;padding:12px;border:1px solid var(--border-primary);border-radius:8px;background-color:var(--muted-surface);background-image:repeating-linear-gradient( -45deg,transparent,transparent 5px,var(--stripe-pattern) 5px,var(--stripe-pattern) 5.7px );color:var(--muted-surface-text);cursor:not-allowed;user-select:none;.limited-label{color:var(--muted-surface-text);}"]);
|
|
586
|
+
componentId: "sc-1cayxi5-8"
|
|
587
|
+
})(["box-sizing:border-box;width:100%;height:100%;min-height:96px;display:flex;align-items:center;justify-content:center;padding:12px;border:1px solid var(--border-primary);border-radius:8px;background-color:var(--muted-surface);background-image:repeating-linear-gradient( -45deg,transparent,transparent 5px,var(--stripe-pattern) 5px,var(--stripe-pattern) 5.7px );color:var(--muted-surface-text);cursor:not-allowed;user-select:none;.limited-label{color:var(--muted-surface-text);}&.round{border-radius:50%;min-height:0;}"]);
|
|
536
588
|
|
|
537
589
|
/**
|
|
538
590
|
* Both resolved faces are the design system's `StackedCard` — the same shell the
|
|
@@ -545,7 +597,7 @@ export const StyledLimitedCard = styled.div.withConfig({
|
|
|
545
597
|
*/
|
|
546
598
|
const StyledEntityCard = styled(StackedCard).withConfig({
|
|
547
599
|
displayName: "projectElements__StyledEntityCard",
|
|
548
|
-
componentId: "sc-1cayxi5-
|
|
600
|
+
componentId: "sc-1cayxi5-9"
|
|
549
601
|
})(["&&{width:100%;}user-select:none;"]);
|
|
550
602
|
/**
|
|
551
603
|
* The task face — the shared `TaskCard`, with the project line switched on.
|
|
@@ -560,11 +612,11 @@ const StyledEntityCard = styled(StackedCard).withConfig({
|
|
|
560
612
|
* The title is the app's own display name (`#123: Name`, `taskDisplayName`), so
|
|
561
613
|
* the card's separate task-number prefix stays off.
|
|
562
614
|
*/
|
|
563
|
-
export const TaskElementCard =
|
|
615
|
+
export const TaskElementCard = _ref2 => {
|
|
564
616
|
var _task$subtasks, _task$comments, _task$date;
|
|
565
|
-
let project =
|
|
566
|
-
task =
|
|
567
|
-
selected =
|
|
617
|
+
let project = _ref2.project,
|
|
618
|
+
task = _ref2.task,
|
|
619
|
+
selected = _ref2.selected;
|
|
568
620
|
return /*#__PURE__*/React.createElement(StyledEntityCard, {
|
|
569
621
|
selected: selected
|
|
570
622
|
}, /*#__PURE__*/React.createElement(TaskCard, {
|
|
@@ -589,9 +641,9 @@ export const TaskElementCard = _ref => {
|
|
|
589
641
|
* right. No progress indicator, and no row at all when the project has neither a
|
|
590
642
|
* leader nor a label.
|
|
591
643
|
*/
|
|
592
|
-
export const ProjectElementCard =
|
|
593
|
-
let project =
|
|
594
|
-
selected =
|
|
644
|
+
export const ProjectElementCard = _ref3 => {
|
|
645
|
+
let project = _ref3.project,
|
|
646
|
+
selected = _ref3.selected;
|
|
595
647
|
return /*#__PURE__*/React.createElement(StyledEntityCard, {
|
|
596
648
|
selected: selected
|
|
597
649
|
}, /*#__PURE__*/React.createElement(ProjectCard, {
|
|
@@ -617,23 +669,74 @@ export const ProjectElementCard = _ref2 => {
|
|
|
617
669
|
* not the entity's identity — the opposite of the tooltip Workload disables on
|
|
618
670
|
* a limited event, which would have leaked the name.
|
|
619
671
|
*/
|
|
620
|
-
export const LimitedElementCard =
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
672
|
+
export const LimitedElementCard = _ref4 => {
|
|
673
|
+
let _ref4$round = _ref4.round,
|
|
674
|
+
round = _ref4$round === void 0 ? false : _ref4$round;
|
|
675
|
+
return /*#__PURE__*/React.createElement(Tooltip, {
|
|
676
|
+
title: LIMITED_ACCESS_MESSAGE
|
|
677
|
+
}, /*#__PURE__*/React.createElement(StyledLimitedCard, {
|
|
678
|
+
"data-testid": "wb-limited-card",
|
|
679
|
+
className: round ? "round" : undefined
|
|
680
|
+
}, /*#__PURE__*/React.createElement(Caption1, {
|
|
681
|
+
weight: "bold",
|
|
682
|
+
className: "limited-label"
|
|
683
|
+
}, LIMITED_ACCESS_LABEL)));
|
|
684
|
+
};
|
|
685
|
+
/**
|
|
686
|
+
* The person face — an avatar circle with a name caption. Always a chip: never
|
|
687
|
+
* a StackedCard, it never expands, no hover card, no online-status dot. The
|
|
688
|
+
* initials avatar stands in for the server-rendered avatar, as it does on the
|
|
689
|
+
* cards.
|
|
690
|
+
*/
|
|
691
|
+
export const PersonElementFace = _ref5 => {
|
|
692
|
+
let person = _ref5.person,
|
|
693
|
+
size = _ref5.size;
|
|
694
|
+
return /*#__PURE__*/React.createElement(StyledPersonFace, {
|
|
695
|
+
"data-testid": "wb-person-face"
|
|
696
|
+
}, /*#__PURE__*/React.createElement(RoundAvatar, {
|
|
697
|
+
className: "person-avatar",
|
|
698
|
+
$bg: person.color,
|
|
699
|
+
$size: size,
|
|
700
|
+
$bordered: false,
|
|
701
|
+
style: {
|
|
702
|
+
fontSize: Math.round(size * 0.28)
|
|
703
|
+
},
|
|
704
|
+
"aria-label": person.name
|
|
705
|
+
}, person.initials), /*#__PURE__*/React.createElement(Caption1, {
|
|
706
|
+
weight: "bold",
|
|
707
|
+
className: "person-name"
|
|
708
|
+
}, person.name));
|
|
709
|
+
};
|
|
628
710
|
|
|
629
711
|
/** One board element, in whichever of its three states it currently is. */
|
|
630
|
-
export const ProjectElementNode =
|
|
631
|
-
let element =
|
|
632
|
-
selected =
|
|
712
|
+
export const ProjectElementNode = _ref6 => {
|
|
713
|
+
let element = _ref6.element,
|
|
714
|
+
selected = _ref6.selected;
|
|
633
715
|
/* Checked before anything else: a limited element must never be able to fall
|
|
634
716
|
through to a branch that renders entity data. */
|
|
635
717
|
if (element.limited) {
|
|
636
|
-
return /*#__PURE__*/React.createElement(LimitedElementCard,
|
|
718
|
+
return /*#__PURE__*/React.createElement(LimitedElementCard, {
|
|
719
|
+
round: element.kind === "person"
|
|
720
|
+
});
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
/* A person is the board's second non-card render: every state is a circle. */
|
|
724
|
+
if (element.kind === "person") {
|
|
725
|
+
if (element.status === "placeholder") {
|
|
726
|
+
return /*#__PURE__*/React.createElement(StyledPersonPlaceholder, {
|
|
727
|
+
"aria-label": "Pick a person"
|
|
728
|
+
}, /*#__PURE__*/React.createElement(PersonIcon, null));
|
|
729
|
+
}
|
|
730
|
+
if (element.status === "resolving") {
|
|
731
|
+
return /*#__PURE__*/React.createElement(StyledPersonResolving, null, /*#__PURE__*/React.createElement(SkeletonLoader, null));
|
|
732
|
+
}
|
|
733
|
+
if (element.person) {
|
|
734
|
+
return /*#__PURE__*/React.createElement(PersonElementFace, {
|
|
735
|
+
person: element.person,
|
|
736
|
+
size: element.width
|
|
737
|
+
});
|
|
738
|
+
}
|
|
739
|
+
return /*#__PURE__*/React.createElement(StyledPersonPlaceholder, null);
|
|
637
740
|
}
|
|
638
741
|
if (element.status === "placeholder") {
|
|
639
742
|
return /*#__PURE__*/React.createElement(StyledPlaceholder, null, /*#__PURE__*/React.createElement(Caption1, {
|
|
@@ -681,30 +784,31 @@ export const ProjectElementNode = _ref3 => {
|
|
|
681
784
|
share: the portal, the overlay, the focus lock and the Esc handler. */
|
|
682
785
|
const StyledPickerPanel = styled(Paper).withConfig({
|
|
683
786
|
displayName: "projectElements__StyledPickerPanel",
|
|
684
|
-
componentId: "sc-1cayxi5-
|
|
787
|
+
componentId: "sc-1cayxi5-10"
|
|
685
788
|
})(["position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);display:flex;flex-direction:column;width:470px;max-width:calc(100vw - 32px);max-height:70vh;overflow:hidden;&&{border-radius:12px;border:1px solid var(--border-primary);box-shadow:0 18px 48px rgba(0,0,0,0.24);}"]);
|
|
686
789
|
|
|
687
790
|
/* Search + adornments, mirroring `Select`'s own form row: the back arrow is a
|
|
688
791
|
start adornment (TaskList), the group-by sort a end adornment (ProjectList). */
|
|
689
792
|
const StyledPickerHeader = styled.div.withConfig({
|
|
690
793
|
displayName: "projectElements__StyledPickerHeader",
|
|
691
|
-
componentId: "sc-1cayxi5-
|
|
794
|
+
componentId: "sc-1cayxi5-11"
|
|
692
795
|
})(["display:flex;align-items:center;gap:8px;flex-shrink:0;padding:12px 12px 8px;.picker-search{width:100%;border-radius:8px;}.picker-search:focus-within{border-color:var(--color-primary);outline:1px solid var(--color-primary);}"]);
|
|
693
796
|
const StyledPickerList = styled.div.withConfig({
|
|
694
797
|
displayName: "projectElements__StyledPickerList",
|
|
695
|
-
componentId: "sc-1cayxi5-
|
|
798
|
+
componentId: "sc-1cayxi5-12"
|
|
696
799
|
})(["flex:1 1 auto;min-height:0;overflow-y:auto;padding:4px 0 12px;.picker-group-header{box-sizing:border-box;height:36px;display:flex;align-items:center;padding:0 20px;margin-top:4px;}.picker-empty{padding:24px 20px;text-align:center;}"]);
|
|
697
800
|
|
|
698
801
|
/* A generously spaced row: the name on the left, an empty radio on the right —
|
|
699
802
|
the shape `Select` gives a single-choice option, at picker scale. */
|
|
700
803
|
const StyledPickerRow = styled.div.withConfig({
|
|
701
804
|
displayName: "projectElements__StyledPickerRow",
|
|
702
|
-
componentId: "sc-1cayxi5-
|
|
703
|
-
})(["box-sizing:border-box;height:56px;display:flex;align-items:center;justify-content:space-between;gap:12px;padding:0 20px;cursor:pointer;outline:none;&:hover,&:focus-visible{background-color:var(--color-theme-200);}.row-name{min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}.c-radio-btn{flex-shrink:0;}"]);
|
|
704
|
-
const PickerRow =
|
|
705
|
-
let id =
|
|
706
|
-
name =
|
|
707
|
-
|
|
805
|
+
componentId: "sc-1cayxi5-13"
|
|
806
|
+
})(["box-sizing:border-box;height:56px;display:flex;align-items:center;justify-content:space-between;gap:12px;padding:0 20px;cursor:pointer;outline:none;&:hover,&:focus-visible{background-color:var(--color-theme-200);}.row-lead{display:flex;align-items:center;gap:12px;min-width:0;}.row-name{min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}.c-radio-btn{flex-shrink:0;}"]);
|
|
807
|
+
const PickerRow = _ref7 => {
|
|
808
|
+
let id = _ref7.id,
|
|
809
|
+
name = _ref7.name,
|
|
810
|
+
avatar = _ref7.avatar,
|
|
811
|
+
onSelect = _ref7.onSelect;
|
|
708
812
|
return /*#__PURE__*/React.createElement(StyledPickerRow, {
|
|
709
813
|
role: "button",
|
|
710
814
|
tabIndex: 0,
|
|
@@ -716,23 +820,31 @@ const PickerRow = _ref4 => {
|
|
|
716
820
|
}
|
|
717
821
|
}
|
|
718
822
|
}, /*#__PURE__*/React.createElement("span", {
|
|
823
|
+
className: "row-lead"
|
|
824
|
+
}, avatar ? /*#__PURE__*/React.createElement(RoundAvatar, {
|
|
825
|
+
$bg: avatar.color,
|
|
826
|
+
$size: 24,
|
|
827
|
+
$bordered: false
|
|
828
|
+
}, avatar.initials) : null, /*#__PURE__*/React.createElement("span", {
|
|
719
829
|
className: "row-name"
|
|
720
|
-
}, /*#__PURE__*/React.createElement(Body2, null, name)), /*#__PURE__*/React.createElement(RadioButton, {
|
|
830
|
+
}, /*#__PURE__*/React.createElement(Body2, null, name))), /*#__PURE__*/React.createElement(RadioButton, {
|
|
721
831
|
id: "wb-picker-" + id,
|
|
722
832
|
tabIndex: -1
|
|
723
833
|
}));
|
|
724
834
|
};
|
|
725
835
|
/**
|
|
726
|
-
* One picker,
|
|
727
|
-
* `MenuSelector/ProjectList` (one step)
|
|
728
|
-
* then task)
|
|
729
|
-
*
|
|
836
|
+
* One picker, three flows — the same split the app makes between
|
|
837
|
+
* `MenuSelector/ProjectList` (one step), `ProjectTaskMenuSelector` (project,
|
|
838
|
+
* then task) and the flat People list (one step, no grouping). The task flow
|
|
839
|
+
* deliberately drops the app's "Directly on project" default option: a task
|
|
840
|
+
* card has to be a task.
|
|
730
841
|
*/
|
|
731
|
-
export const ProjectElementPicker =
|
|
732
|
-
let kind =
|
|
733
|
-
onSelectProject =
|
|
734
|
-
onSelectTask =
|
|
735
|
-
|
|
842
|
+
export const ProjectElementPicker = _ref8 => {
|
|
843
|
+
let kind = _ref8.kind,
|
|
844
|
+
onSelectProject = _ref8.onSelectProject,
|
|
845
|
+
onSelectTask = _ref8.onSelectTask,
|
|
846
|
+
onSelectPerson = _ref8.onSelectPerson,
|
|
847
|
+
onCancel = _ref8.onCancel;
|
|
736
848
|
const _useState = useState(null),
|
|
737
849
|
project = _useState[0],
|
|
738
850
|
setProject = _useState[1];
|
|
@@ -746,6 +858,7 @@ export const ProjectElementPicker = _ref5 => {
|
|
|
746
858
|
gesture that created it. */
|
|
747
859
|
const pressedInsideRef = useRef(false);
|
|
748
860
|
const onTaskStep = kind === "task" && project !== null;
|
|
861
|
+
const onPeopleStep = kind === "person";
|
|
749
862
|
const projectGroups = useMemo(() => groupProjects(PICKER_PROJECTS.filter(entry => matchesQuery(entry.name, query))), [query]);
|
|
750
863
|
const taskGroups = useMemo(() => project ? groupTasks(project.tasks.filter(task => matchesQuery(taskDisplayName(task), query))) : [], [project, query]);
|
|
751
864
|
const handleProject = picked => {
|
|
@@ -760,7 +873,10 @@ export const ProjectElementPicker = _ref5 => {
|
|
|
760
873
|
setProject(null);
|
|
761
874
|
setQuery("");
|
|
762
875
|
};
|
|
763
|
-
const
|
|
876
|
+
const people = useMemo(() => PICKER_PEOPLE_LIST.filter(entry => matchesQuery(entry.person.name, query)), [query]);
|
|
877
|
+
const isEmpty = onPeopleStep ? people.length === 0 : onTaskStep ? taskGroups.length === 0 : projectGroups.length === 0;
|
|
878
|
+
const searchPlaceholder = onPeopleStep ? "Search a person" : onTaskStep ? "Search a task" : "Search a project";
|
|
879
|
+
const emptyLabel = onPeopleStep ? "No people" : onTaskStep ? "No Result" : "No Projects";
|
|
764
880
|
return /*#__PURE__*/React.createElement(Modal, {
|
|
765
881
|
open: true,
|
|
766
882
|
onClose: onCancel,
|
|
@@ -786,9 +902,9 @@ export const ProjectElementPicker = _ref5 => {
|
|
|
786
902
|
className: "picker-search",
|
|
787
903
|
autoFocus: true,
|
|
788
904
|
value: query,
|
|
789
|
-
placeholder:
|
|
905
|
+
placeholder: searchPlaceholder,
|
|
790
906
|
onChange: event => setQuery(event.target.value)
|
|
791
|
-
}), onTaskStep ? null : /*#__PURE__*/React.createElement(Tooltip, {
|
|
907
|
+
}), onTaskStep || onPeopleStep ? null : /*#__PURE__*/React.createElement(Tooltip, {
|
|
792
908
|
title: "Group by"
|
|
793
909
|
}, /*#__PURE__*/React.createElement(IconButton, {
|
|
794
910
|
type: "button",
|
|
@@ -797,7 +913,17 @@ export const ProjectElementPicker = _ref5 => {
|
|
|
797
913
|
className: "picker-empty"
|
|
798
914
|
}, /*#__PURE__*/React.createElement(Body2, {
|
|
799
915
|
color: "tertiary"
|
|
800
|
-
},
|
|
916
|
+
}, emptyLabel)) : null, onPeopleStep ? people.map(_ref9 => {
|
|
917
|
+
let id = _ref9.id,
|
|
918
|
+
person = _ref9.person;
|
|
919
|
+
return /*#__PURE__*/React.createElement(PickerRow, {
|
|
920
|
+
key: id,
|
|
921
|
+
id: id,
|
|
922
|
+
name: person.name,
|
|
923
|
+
avatar: person,
|
|
924
|
+
onSelect: () => onSelectPerson(person)
|
|
925
|
+
});
|
|
926
|
+
}) : null, onTaskStep && project ? taskGroups.map(group => /*#__PURE__*/React.createElement("div", {
|
|
801
927
|
key: group.taskList
|
|
802
928
|
}, /*#__PURE__*/React.createElement("div", {
|
|
803
929
|
className: "picker-group-header"
|
|
@@ -808,7 +934,7 @@ export const ProjectElementPicker = _ref5 => {
|
|
|
808
934
|
id: task.id,
|
|
809
935
|
name: taskDisplayName(task),
|
|
810
936
|
onSelect: () => onSelectTask(project, task)
|
|
811
|
-
})))) : null, onTaskStep ? null : projectGroups.map(group => /*#__PURE__*/React.createElement("div", {
|
|
937
|
+
})))) : null, onTaskStep || onPeopleStep ? null : projectGroups.map(group => /*#__PURE__*/React.createElement("div", {
|
|
812
938
|
key: group.client
|
|
813
939
|
}, /*#__PURE__*/React.createElement("div", {
|
|
814
940
|
className: "picker-group-header"
|