@activecollab/components
Version:
ActiveCollab Components
136 lines (130 loc) • 6.82 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.projectClientLine = exports.ProjectCard = exports.INTERNAL_CLIENT_LABEL = void 0;
var _react = _interopRequireDefault(require("react"));
var _styledComponents = _interopRequireDefault(require("styled-components"));
var _shared = require("./shared");
var _Chip = require("../../../components/Chip");
var _StackedCard = require("../../../components/StackedCard");
var _Typography = require("../../../components/Typography");
var _shared2 = require("../../shared");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* ProjectCard — a project as a stacked card.
*
* The sixth content type, and the second one that mirrors a project-management
* record rather than something authored on the surface (TaskCard is the first).
* It composes the same shell and the same rows; nothing in `components/StackedCard`
* knows it exists.
*
* The face is the app's Projects page, read off `ProjectListGroup.jsx`:
* - the NAME is the card's title (`Header3`, as in the grid card);
* - the CLIENT sits under it — `Entity.Property "entity-property-client"`, the
* company the project is for;
* - the DESCRIPTION is the project's `body`, the grid card's `Body2` tertiary
* excerpt, clamped because the whole text lives on the project and this is a
* reference to it, not a copy;
* - the LEADER and the LABEL share one row. The label is a FILLED pill whose
* background is the label's own colour and whose text is a darker shade of
* it (`ProjectLabel.jsx`: `EntityLabel` with `backgroundColor: label.color`,
* `color: label.darker_text_color`) — the design system's `Chip`, not the
* colour-text `Tag` the column cards use for task labels.
*
* There is deliberately NO progress indicator. A single percentage is the one
* number on a project that cannot be read without knowing how it was computed,
* and a card is a place people put a project to talk ABOUT it — the number
* invites a conversation about the number instead.
*/
/** A project label carries both of the colours the app stores for it. */
/**
* What an internal project's client line says.
*
* A project with no client belongs to the account's own company, and printing
* that company's name back at someone who works there says nothing. So the line
* states the fact instead.
*/
var INTERNAL_CLIENT_LABEL = exports.INTERNAL_CLIENT_LABEL = "Internal";
/** One rule for the client line, so no surface can label the same project twice. */
var projectClientLine = exports.projectClientLine = function projectClientLine(client) {
return client !== null && client !== void 0 ? client : INTERNAL_CLIENT_LABEL;
};
/* The description excerpt. Three lines is the most a card can carry before it
stops being a card, so it clamps. */
var StyledExcerpt = (0, _styledComponents.default)(_Typography.Body2).withConfig({
displayName: "ProjectCard__StyledExcerpt",
componentId: "sc-1afak94-0"
})(["display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;"]);
var StyledName = (0, _styledComponents.default)(_Typography.Header3).withConfig({
displayName: "ProjectCard__StyledName",
componentId: "sc-1afak94-1"
})(["overflow:hidden;white-space:nowrap;text-overflow:ellipsis;"]);
var StyledClient = (0, _styledComponents.default)(_Typography.Caption2).withConfig({
displayName: "ProjectCard__StyledClient",
componentId: "sc-1afak94-2"
})(["display:block;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;"]);
/**
* One row for the two facts that are each optional: the leader on the LEFT, the
* label on the RIGHT. `space-between` is what keeps the label right when there is
* no leader beside it, and the row is not rendered at all when the project has
* neither — a bare project produces a small card, not a card with empty
* furniture in it.
*
* No rule above it: the card carries no internal separators. The row's own role
* padding is what sets it apart from the excerpt, the same way every other row in
* every other content type is set apart — a hairline here would be the only line
* inside any card in the set.
*/
var StyledMetaRow = (0, _styledComponents.default)(_StackedCard.StackedCardRow).withConfig({
displayName: "ProjectCard__StyledMetaRow",
componentId: "sc-1afak94-3"
})(["justify-content:space-between;.sc-leader{display:flex;align-items:center;gap:8px;min-width:0;}.sc-leader > .typography{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}.sc-label{flex-shrink:0;display:flex;}"]);
var ProjectCard = exports.ProjectCard = function ProjectCard(_ref) {
var _ref$name = _ref.name,
name = _ref$name === void 0 ? "Marketing Site" : _ref$name,
_ref$client = _ref.client,
client = _ref$client === void 0 ? "ActiveCollab Inc." : _ref$client,
description = _ref.description,
leader = _ref.leader,
label = _ref.label;
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_StackedCard.StackedCardRow, {
role: "title"
}, /*#__PURE__*/_react.default.createElement(_shared.StyledTitleBlock, null, /*#__PURE__*/_react.default.createElement(StyledName, null, name), /*#__PURE__*/_react.default.createElement(StyledClient, {
color: "tertiary"
}, projectClientLine(client))), /*#__PURE__*/_react.default.createElement(_shared.EntityDots, {
"aria-label": "Project options"
})), description ? /*#__PURE__*/_react.default.createElement(_StackedCard.StackedCardRow, {
role: "custom"
}, /*#__PURE__*/_react.default.createElement(StyledExcerpt, {
color: "secondary"
}, description)) : null, leader || label ? /*#__PURE__*/_react.default.createElement(StyledMetaRow, {
role: "footer"
}, leader ? /*#__PURE__*/_react.default.createElement("span", {
className: "sc-leader"
}, /*#__PURE__*/_react.default.createElement(_shared2.RoundAvatar, {
$bg: leader.color,
$size: 24,
$bordered: false,
"data-fixed": true
}, leader.initials), /*#__PURE__*/_react.default.createElement(_Typography.Caption1, {
color: "secondary"
}, leader.name)) :
/*#__PURE__*/
/* Keeps the label on the right when there is no leader to push it
there — an empty flex item is cheaper than a second layout. */
_react.default.createElement("span", null), label ? /*#__PURE__*/_react.default.createElement("span", {
className: "sc-label",
"data-fixed": true
}, /*#__PURE__*/_react.default.createElement(_Chip.Chip, {
size: "small",
label: label.text,
backgroundColor: label.color,
color: label.textColor,
typographyProps: {
variant: "Caption 2",
weight: "bold"
}
})) : null) : null);
};
//# sourceMappingURL=ProjectCard.js.map