@activecollab/components 2.0.397 → 2.0.399

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 (61) hide show
  1. package/dist/cjs/presentation/whiteboard/bottomDock.js +194 -0
  2. package/dist/cjs/presentation/whiteboard/bottomDock.js.map +1 -0
  3. package/dist/cjs/presentation/whiteboard/canvasElements.js +877 -0
  4. package/dist/cjs/presentation/whiteboard/canvasElements.js.map +1 -0
  5. package/dist/cjs/presentation/whiteboard/elements.js +816 -0
  6. package/dist/cjs/presentation/whiteboard/elements.js.map +1 -0
  7. package/dist/cjs/presentation/whiteboard/fileElement.js +457 -0
  8. package/dist/cjs/presentation/whiteboard/fileElement.js.map +1 -0
  9. package/dist/cjs/presentation/whiteboard/glyphs.js +67 -0
  10. package/dist/cjs/presentation/whiteboard/glyphs.js.map +1 -0
  11. package/dist/cjs/presentation/whiteboard/inspector.js +884 -0
  12. package/dist/cjs/presentation/whiteboard/inspector.js.map +1 -0
  13. package/dist/cjs/presentation/whiteboard/linkElement.js +357 -0
  14. package/dist/cjs/presentation/whiteboard/linkElement.js.map +1 -0
  15. package/dist/cjs/presentation/whiteboard/outline.js +966 -0
  16. package/dist/cjs/presentation/whiteboard/outline.js.map +1 -0
  17. package/dist/cjs/presentation/whiteboard/peopleMenu.js +516 -0
  18. package/dist/cjs/presentation/whiteboard/peopleMenu.js.map +1 -0
  19. package/dist/cjs/presentation/whiteboard/settingsMenu.js +177 -0
  20. package/dist/cjs/presentation/whiteboard/settingsMenu.js.map +1 -0
  21. package/dist/esm/presentation/whiteboard/bottomDock.d.ts +51 -0
  22. package/dist/esm/presentation/whiteboard/bottomDock.d.ts.map +1 -0
  23. package/dist/esm/presentation/whiteboard/bottomDock.js +162 -0
  24. package/dist/esm/presentation/whiteboard/bottomDock.js.map +1 -0
  25. package/dist/esm/presentation/whiteboard/canvasElements.d.ts +61 -0
  26. package/dist/esm/presentation/whiteboard/canvasElements.d.ts.map +1 -0
  27. package/dist/esm/presentation/whiteboard/canvasElements.js +746 -0
  28. package/dist/esm/presentation/whiteboard/canvasElements.js.map +1 -0
  29. package/dist/esm/presentation/whiteboard/elements.d.ts +180 -0
  30. package/dist/esm/presentation/whiteboard/elements.d.ts.map +1 -0
  31. package/dist/esm/presentation/whiteboard/elements.js +736 -0
  32. package/dist/esm/presentation/whiteboard/elements.js.map +1 -0
  33. package/dist/esm/presentation/whiteboard/fileElement.d.ts +113 -0
  34. package/dist/esm/presentation/whiteboard/fileElement.d.ts.map +1 -0
  35. package/dist/esm/presentation/whiteboard/fileElement.js +430 -0
  36. package/dist/esm/presentation/whiteboard/fileElement.js.map +1 -0
  37. package/dist/esm/presentation/whiteboard/glyphs.d.ts +32 -0
  38. package/dist/esm/presentation/whiteboard/glyphs.d.ts.map +1 -0
  39. package/dist/esm/presentation/whiteboard/glyphs.js +50 -0
  40. package/dist/esm/presentation/whiteboard/glyphs.js.map +1 -0
  41. package/dist/esm/presentation/whiteboard/inspector.d.ts +100 -0
  42. package/dist/esm/presentation/whiteboard/inspector.d.ts.map +1 -0
  43. package/dist/esm/presentation/whiteboard/inspector.js +753 -0
  44. package/dist/esm/presentation/whiteboard/inspector.js.map +1 -0
  45. package/dist/esm/presentation/whiteboard/linkElement.d.ts +97 -0
  46. package/dist/esm/presentation/whiteboard/linkElement.d.ts.map +1 -0
  47. package/dist/esm/presentation/whiteboard/linkElement.js +327 -0
  48. package/dist/esm/presentation/whiteboard/linkElement.js.map +1 -0
  49. package/dist/esm/presentation/whiteboard/outline.d.ts +89 -0
  50. package/dist/esm/presentation/whiteboard/outline.d.ts.map +1 -0
  51. package/dist/esm/presentation/whiteboard/outline.js +870 -0
  52. package/dist/esm/presentation/whiteboard/outline.js.map +1 -0
  53. package/dist/esm/presentation/whiteboard/peopleMenu.d.ts +44 -0
  54. package/dist/esm/presentation/whiteboard/peopleMenu.d.ts.map +1 -0
  55. package/dist/esm/presentation/whiteboard/peopleMenu.js +440 -0
  56. package/dist/esm/presentation/whiteboard/peopleMenu.js.map +1 -0
  57. package/dist/esm/presentation/whiteboard/settingsMenu.d.ts +13 -0
  58. package/dist/esm/presentation/whiteboard/settingsMenu.d.ts.map +1 -0
  59. package/dist/esm/presentation/whiteboard/settingsMenu.js +155 -0
  60. package/dist/esm/presentation/whiteboard/settingsMenu.js.map +1 -0
  61. package/package.json +1 -1
@@ -0,0 +1,966 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.outlineLabel = exports.UNGROUPED = exports.StyledSidebarHeader = exports.StyledPanelChooseSlot = exports.StyledOutlineTypeIcon = exports.StyledOutlineToggle = exports.StyledOutlineSignifiers = exports.StyledOutlineSidebar = exports.StyledOutlineRow = exports.StyledOutlineResizer = exports.StyledOutlineName = exports.StyledOutlineGroupRow = exports.StyledOutlineElementMenu = exports.StyledOutlineCounter = exports.StyledOutlineChildRow = exports.StyledOutlineBody = exports.StyledNewGroupRow = exports.StyledInfoPanel = exports.StyledChooseRow = exports.OutlineMenuSliderStyle = exports.OutlineGroupOptionsMenu = exports.OutlineElementOptionsMenu = exports.OutlineCounter = exports.OUTLINE_WIDTH = exports.OUTLINE_TYPE_LABELS = exports.OUTLINE_TYPE_ICONS = exports.OUTLINE_MIN_WIDTH = exports.OUTLINE_MENU_WIDTH = exports.OUTLINE_MENU_LIST_STYLE = exports.OUTLINE_MAX_WIDTH = exports.OUTLINE_GROUPS = exports.OUTLINE_ELEMENTS = exports.LeftSidebar = exports.LeftMenuContents = exports.InfoPanelContent = exports.INFO_ROWS = exports.ARRANGE_ITEMS = void 0;
7
+ var _react = _interopRequireWildcard(require("react"));
8
+ var _styledComponents = _interopRequireWildcard(require("styled-components"));
9
+ var _elements = require("./elements");
10
+ var _peopleMenu = require("./peopleMenu");
11
+ var _Button = require("../../components/Button");
12
+ var _Chip = require("../../components/Chip");
13
+ var _ChooseV = require("../../components/ChooseV2");
14
+ var _EditableText = require("../../components/EditableText");
15
+ var _IconButton = require("../../components/IconButton");
16
+ var _Icons = require("../../components/Icons");
17
+ var _List = require("../../components/List");
18
+ var _Menu = require("../../components/Menu");
19
+ var _Signifier = require("../../components/Signifier");
20
+ var _Tooltip = require("../../components/Tooltip");
21
+ var _Transitions = require("../../components/Transitions");
22
+ var _Typography = require("../../components/Typography");
23
+ 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); }
24
+ function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
25
+ 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; }
26
+ 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; }
27
+ 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; }
28
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
29
+ 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); }
30
+ function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
31
+ 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."); }
32
+ 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; } }
33
+ 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; }
34
+ 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; } }
35
+ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
36
+ /* ------------------------------------------------------------------ */
37
+ /* Outline sidebar */
38
+ /* ------------------------------------------------------------------ */
39
+
40
+ /* An OUTLINE, not a layers panel. Whiteboard elements are a flat list today
41
+ with no nesting and no names, so the hierarchy here is AUTHORED rather than
42
+ derived from z-order or spatial containment: the user creates groups, names
43
+ things, and drags to order them, and all of that is persisted.
44
+ Deliberately excluded: stacking order. z-order stays on the element context
45
+ menu (send to front / back / forward / backward) and the sidebar never shows
46
+ or edits it — the outline order and the paint order are different questions,
47
+ and conflating them is what makes layers panels confusing on boards that are
48
+ really structured documents.
49
+
50
+ The model this prototype stands in for:
51
+ GroupElement a new element type on the single-table-inheritance
52
+ `whiteboard_elements` table — no migration needed, and it
53
+ inherits ops, realtime, undo/redo and trash for free.
54
+ Element.jsx's render switch already returns null by
55
+ default, so a group draws nothing on the canvas. It must be
56
+ filtered out of the spatial index, marquee select and the
57
+ z-order sort.
58
+ name a real authored field, separate from `content` (the text
59
+ painted on the canvas). Needed because the eventual goal is
60
+ exporting the outline as a document, and `content` is empty
61
+ on every freshly drawn shape and absent on freehand.
62
+ outlinePosition
63
+ integer ordering SCOPED PER CONTAINER — groups ordered
64
+ among themselves, elements ordered within their group.
65
+ Named to avoid colliding with `element.position`, which is
66
+ already the {x, y} canvas coordinate. Reordering follows
67
+ the house TaskReorderer contract: the client sends the full
68
+ ordered id list, the server renumbers 1..N in one
69
+ transaction. Here that is a new `reorder` op on the
70
+ existing ops pipeline, so it inherits undo/redo, the id_map
71
+ reconcile and the realtime merge.
72
+
73
+ ONE level of nesting only. Groups cannot contain groups — an exported
74
+ document does not want arbitrarily deep headings, and multi-level grouping
75
+ is a later, separate model. */
76
+
77
+ /* The local `Glyph` type is for this story's hand-drawn SVGs; the DS icons are
78
+ forwardRef components, so the map needs the wider component type. */
79
+
80
+ var OUTLINE_TYPE_ICONS = exports.OUTLINE_TYPE_ICONS = {
81
+ circle: _Icons.CircleIcon,
82
+ roundedRectangle: _Icons.RoundedRectangleIcon,
83
+ triangle: _Icons.TriangleIcon,
84
+ postit: _Icons.NoteIcon,
85
+ text: _Icons.TextIcon,
86
+ freehand: _Icons.DrawIcon,
87
+ link: _Icons.InsertLinkIcon,
88
+ file: _Icons.AttachmentIcon
89
+ };
90
+
91
+ /* Fallback label when an element has no name. Deliberately reads as a
92
+ PLACEHOLDER (muted + italic) rather than as a name, because an unnamed
93
+ element exports as nothing — the styling is the warning. */
94
+ var OUTLINE_TYPE_LABELS = exports.OUTLINE_TYPE_LABELS = {
95
+ circle: "Circle",
96
+ roundedRectangle: "Rounded Rectangle",
97
+ triangle: "Triangle",
98
+ postit: "Sticky Note",
99
+ text: "Text",
100
+ freehand: "Freehand",
101
+ link: "Link",
102
+ file: "File"
103
+ };
104
+ /* Ids prefixed `shape-` / `sticky` are the elements really on the canvas, so
105
+ selection syncs both ways for them. The rest stand in for the parts of a
106
+ bigger board scrolled out of view — a four-element outline would not show
107
+ whether the grouping reads well. */
108
+ var OUTLINE_GROUPS = exports.OUTLINE_GROUPS = [{
109
+ id: "group-discovery",
110
+ name: "Discovery phase"
111
+ }, {
112
+ id: "group-sketches",
113
+ name: "Solution sketches"
114
+ }, {
115
+ id: "group-questions",
116
+ name: "Open questions"
117
+ }];
118
+ var OUTLINE_ELEMENTS = exports.OUTLINE_ELEMENTS = [{
119
+ id: "sticky",
120
+ name: "Interview five customers",
121
+ type: "postit",
122
+ connections: 2,
123
+ groupId: "group-discovery"
124
+ }, {
125
+ id: "shape-rounded",
126
+ name: "Problem statement",
127
+ type: "roundedRectangle",
128
+ connections: 3,
129
+ groupId: "group-discovery"
130
+ }, {
131
+ id: "outline-freehand",
132
+ name: null,
133
+ type: "freehand",
134
+ groupId: "group-discovery"
135
+ }, {
136
+ id: "shape-circle",
137
+ name: "Success metric",
138
+ type: "circle",
139
+ locked: true,
140
+ connections: 1,
141
+ groupId: "group-discovery"
142
+ }, {
143
+ id: "outline-sketch-link",
144
+ name: "Competitor teardown",
145
+ type: "link",
146
+ groupId: "group-sketches"
147
+ }, {
148
+ id: "outline-sketch-file",
149
+ name: "Wireframes v3.pdf",
150
+ type: "file",
151
+ connections: 1,
152
+ groupId: "group-sketches"
153
+ }, {
154
+ id: "outline-sketch-text",
155
+ name: null,
156
+ type: "text",
157
+ groupId: "group-sketches"
158
+ },
159
+ /* A deliberately long name, so the truncation and the right-edge behaviour of
160
+ the signifiers and the counter are visible in the story. */
161
+ {
162
+ id: "outline-parking",
163
+ name: "Parking lot for everything we could not agree on today",
164
+ type: "postit",
165
+ connections: 4,
166
+ locked: true,
167
+ groupId: null
168
+ }, {
169
+ id: "shape-triangle",
170
+ name: null,
171
+ type: "triangle",
172
+ groupId: null
173
+ }, {
174
+ id: "outline-q3",
175
+ name: "Revisit in Q3",
176
+ type: "text",
177
+ connections: 12,
178
+ groupId: null
179
+ }];
180
+
181
+ /* Min is the point below which a group name plus its counter stops being
182
+ readable; max follows the common side-panel rule of thumb of 3x the min, past
183
+ which the panel competes with the canvas for the screen rather than annotating
184
+ it. The default sits just above the min — panels of this sort open narrow and
185
+ are widened on demand, not the other way round. */
186
+ var OUTLINE_MIN_WIDTH = exports.OUTLINE_MIN_WIDTH = 260;
187
+ var OUTLINE_MAX_WIDTH = exports.OUTLINE_MAX_WIDTH = OUTLINE_MIN_WIDTH * 3;
188
+ var OUTLINE_WIDTH = exports.OUTLINE_WIDTH = 320;
189
+ var UNGROUPED = exports.UNGROUPED = "__ungrouped__";
190
+ var StyledOutlineSidebar = exports.StyledOutlineSidebar = _styledComponents.default.aside.withConfig({
191
+ displayName: "outline__StyledOutlineSidebar",
192
+ componentId: "sc-173k9fg-0"
193
+ })(["flex-shrink:0;position:relative;box-sizing:border-box;display:flex;flex-direction:column;border-right:1px solid var(--selectable);background-color:var(--page-paper-main);font-family:-apple-system,BlinkMacSystemFont,\"Roboto\",\"Helvetica Neue\",Arial,sans-serif;"]);
194
+
195
+ /* Grab strip on the RIGHT edge, because the panel is docked left — dragging it
196
+ right widens. It sits outside the row list and uses mouse events rather than
197
+ HTML5 drag, so it can never be mistaken for a row reorder. 3px wide with a
198
+ larger invisible hit area is the usual compromise: easy to grab. The border
199
+ line itself stays the selectable grey until hover paints the active token
200
+ over it. */
201
+ var StyledOutlineResizer = exports.StyledOutlineResizer = _styledComponents.default.div.withConfig({
202
+ displayName: "outline__StyledOutlineResizer",
203
+ componentId: "sc-173k9fg-1"
204
+ })(["position:absolute;top:0;bottom:0;right:-4px;width:8px;cursor:col-resize;z-index:2;&::after{content:\"\";position:absolute;top:0;bottom:0;left:50%;margin-left:-0.5px;width:1px;background-color:var(--selectable-active);opacity:0;transition:opacity 150ms ease;}&:hover::after,&.resizing::after{opacity:1;}"]);
205
+ var StyledOutlineBody = exports.StyledOutlineBody = _styledComponents.default.div.withConfig({
206
+ displayName: "outline__StyledOutlineBody",
207
+ componentId: "sc-173k9fg-2"
208
+ })(["flex:1;overflow-y:auto;padding:6px 0 24px;"]);
209
+
210
+ /* Rows are bordered, not carded — the outline is a dense list and rounded
211
+ tiles at this density read as clutter. */
212
+ /* Row geometry is My Work's, not something invented for this sidebar: the app's
213
+ `ListItem` is `tw-w-full tw-flex tw-items-center tw-h-10` — a fixed 40px row —
214
+ with `border-bottom: 1px solid var(--color-theme-300)` from `.list-item-wrapper`
215
+ and `background-color: var(--color-theme-200)` on `.task-list-item:hover`.
216
+ Reusing those exact values is what makes the outline read as an ActiveCollab
217
+ list rather than as a bespoke panel. */
218
+ var StyledOutlineRow = exports.StyledOutlineRow = _styledComponents.default.div.withConfig({
219
+ displayName: "outline__StyledOutlineRow",
220
+ componentId: "sc-173k9fg-3"
221
+ })(["display:flex;align-items:center;height:40px;box-sizing:border-box;padding-right:8px;cursor:pointer;position:relative;border-bottom:1px solid var(--color-theme-300);&:hover{background-color:var(--color-theme-200);}&.selected{background-color:var(--color-theme-200);box-shadow:inset 2px 0 0 0 ", ";}&.drop-before::after,&.drop-after::after{content:\"\";position:absolute;left:0;right:0;height:2px;background-color:", ";z-index:1;}&.drop-before::after{top:-1px;}&.drop-after::after{bottom:-1px;}&.drop-into{background-color:var(--color-theme-200);box-shadow:inset 0 0 0 1px ", ";}&.dragging{opacity:0.4;}.outline-trailing{flex-shrink:0;display:flex;align-items:center;}.outline-options{margin-left:auto;flex-shrink:0;display:flex;align-items:center;padding-left:4px;}.outline-hover{opacity:0;transition:opacity 200ms ease;}&:hover .outline-hover,.outline-hover.open,.outline-hover:focus-within{opacity:1;}"], _elements.SELECTION_BLUE, _elements.SELECTION_BLUE, _elements.SELECTION_BLUE);
222
+
223
+ /* 8px so the 24px toggle sits in the same left rail as the app's ExpandToggle,
224
+ scaled down from My Work's 24px page margin for a 300px panel. */
225
+ var StyledOutlineGroupRow = exports.StyledOutlineGroupRow = (0, _styledComponents.default)(StyledOutlineRow).withConfig({
226
+ displayName: "outline__StyledOutlineGroupRow",
227
+ componentId: "sc-173k9fg-4"
228
+ })(["padding-left:8px;"]);
229
+
230
+ /* 32px = where the group's 24px toggle ends. The child's type icon starts
231
+ exactly there, putting the child NAME one 16px step right of the group name —
232
+ enough to read as nested without a staircase, which is all one level of
233
+ nesting ever needs. */
234
+ var StyledOutlineChildRow = exports.StyledOutlineChildRow = (0, _styledComponents.default)(StyledOutlineRow).withConfig({
235
+ displayName: "outline__StyledOutlineChildRow",
236
+ componentId: "sc-173k9fg-5"
237
+ })(["padding-left:32px;"]);
238
+
239
+ /* Matches the app's ExpandToggle exactly: CollapseExpandSingleIcon at its
240
+ intrinsic 24px, rotate(0) expanded and rotate(180deg) collapsed, over
241
+ `transition-transform` 200ms. */
242
+ var StyledOutlineToggle = exports.StyledOutlineToggle = _styledComponents.default.button.withConfig({
243
+ displayName: "outline__StyledOutlineToggle",
244
+ componentId: "sc-173k9fg-6"
245
+ })(["border:0;padding:0;margin:0 8px 0 0;background:none;cursor:pointer;display:flex;align-items:center;flex-shrink:0;transition:transform 200ms ease;&.collapsed{transform:rotate(180deg);}"]);
246
+
247
+ /* Same treatment as the count badges on the System Settings pages — a Chip on
248
+ var(--color-theme-300) with var(--color-theme-900) text — at the 18px small
249
+ size, which sits inside a 40px row without crowding it. Wrapped so the 8px
250
+ left margin is one decision rather than repeated at each call site: it is what
251
+ keeps the chip a fixed distance from the name whether the name is an
252
+ EditableText (whose input carries its own 4px padding) or plain Typography. */
253
+ var StyledOutlineCounter = exports.StyledOutlineCounter = _styledComponents.default.span.withConfig({
254
+ displayName: "outline__StyledOutlineCounter",
255
+ componentId: "sc-173k9fg-7"
256
+ })(["display:flex;align-items:center;flex-shrink:0;margin-left:8px;"]);
257
+ var OutlineCounter = exports.OutlineCounter = function OutlineCounter(_ref) {
258
+ var count = _ref.count;
259
+ return /*#__PURE__*/_react.default.createElement(StyledOutlineCounter, {
260
+ className: "outline-trailing"
261
+ }, /*#__PURE__*/_react.default.createElement(_Chip.Chip, {
262
+ label: String(count),
263
+ backgroundColor: "var(--color-theme-300)",
264
+ color: "var(--color-theme-900)",
265
+ size: "small"
266
+ }));
267
+ };
268
+
269
+ /* The 2px separator dot is a house convention rather than part of the DS
270
+ Signifier: `_components.task-signifiers.less` puts it on `.c-signifier:before`
271
+ at 2px square, `var(--color-theme-600)`, `margin: 0 6px`, with no
272
+ `:not(:first-child)` guard — so the first signifier gets a leading dot too,
273
+ which is exactly what separates it from the name. */
274
+ var StyledOutlineSignifiers = exports.StyledOutlineSignifiers = _styledComponents.default.span.withConfig({
275
+ displayName: "outline__StyledOutlineSignifiers",
276
+ componentId: "sc-173k9fg-8"
277
+ })(["display:inline-flex;align-items:center;flex-shrink:0;.c-signifier::before{content:\"\";flex-shrink:0;width:2px;height:2px;margin:0 6px;border-radius:100%;background-color:var(--color-theme-600);}"]);
278
+
279
+ /* The DS EditableText is an always-live input styled as text — it reveals its
280
+ border on hover and focus rather than swapping into an edit mode. That makes
281
+ it a click-to-edit target, which competes with the row's own click. Element
282
+ rows therefore keep it `disabled` until the row is SELECTED: the first click
283
+ selects, and only then does the name accept a caret. Group rows have no
284
+ selected state, so their name is always live (matching the task-list header
285
+ in ListView) and the toggle, count and row padding carry the collapse. */
286
+ /* 24px reserved so the icon column is stable whether or not a type icon is a
287
+ perfect 16px square, and so it lines up with the group toggle above it. */
288
+ var StyledOutlineTypeIcon = exports.StyledOutlineTypeIcon = _styledComponents.default.span.withConfig({
289
+ displayName: "outline__StyledOutlineTypeIcon",
290
+ componentId: "sc-173k9fg-9"
291
+ })(["display:flex;align-items:center;justify-content:flex-start;width:24px;flex-shrink:0;"]);
292
+ var StyledOutlineName = exports.StyledOutlineName = _styledComponents.default.div.withConfig({
293
+ displayName: "outline__StyledOutlineName",
294
+ componentId: "sc-173k9fg-10"
295
+ })(["display:flex;align-items:center;flex:0 1 auto;min-width:0;> div{max-width:100%;}> .typography{display:block;padding-left:4px;padding-right:4px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}&.unnamed .presentation,&.unnamed input{font-style:italic;color:var(--color-theme-500);}"]);
296
+ var outlineLabel = exports.outlineLabel = function outlineLabel(element) {
297
+ var _element$name;
298
+ return (_element$name = element.name) !== null && _element$name !== void 0 ? _element$name : OUTLINE_TYPE_LABELS[element.type];
299
+ };
300
+
301
+ /* Both menus follow the shared TaskListOptionsMenu shape: Menu in normal mode
302
+ (260px bubble), an IconButton + TreeDots trigger whose `.open` class keeps it
303
+ visible while the menu is up, and a flat List of leading-icon ListItems
304
+ grouped by ListSeparator. Every row is an icon plus a caption — no submenu
305
+ rows and no icon-only action strip, so there is exactly one way to read the
306
+ menu.
307
+
308
+ Note where STACKING lives: bring to front / send to back are here, not in the
309
+ outline. The outline orders the document; the menu orders the pixels. Keeping
310
+ them apart is the whole reason the sidebar can be an outline rather than a
311
+ layers panel. */
312
+ var OUTLINE_MENU_LIST_STYLE = exports.OUTLINE_MENU_LIST_STYLE = {
313
+ padding: "8px 0"
314
+ };
315
+ var OUTLINE_MENU_WIDTH = exports.OUTLINE_MENU_WIDTH = 264;
316
+
317
+ /* Same drill-in mechanics as the board Settings menu: the paper clips the two
318
+ sliding panels and gives them a positioning context. */
319
+ var OutlineMenuSliderStyle = exports.OutlineMenuSliderStyle = (0, _styledComponents.createGlobalStyle)([".c-simple-menu__paper.outline-element-menu{overflow:hidden;position:relative;}"]);
320
+ var StyledOutlineElementMenu = exports.StyledOutlineElementMenu = _styledComponents.default.div.withConfig({
321
+ displayName: "outline__StyledOutlineElementMenu",
322
+ componentId: "sc-173k9fg-11"
323
+ })([".drill-item{justify-content:space-between;}.drill-item .opt-left{display:flex;align-items:center;min-width:0;}.drill-item .opt-left > svg:first-child{margin-right:8px;}.drill-item .drill-caret{flex-shrink:0;fill:var(--color-theme-600);}"]);
324
+ var ARRANGE_ITEMS = exports.ARRANGE_ITEMS = [{
325
+ label: "Bring to Front",
326
+ Icon: _Icons.LayerFrontIcon
327
+ }, {
328
+ label: "Send Forward",
329
+ Icon: _Icons.LayerForwardIcon
330
+ }, {
331
+ label: "Send Backward",
332
+ Icon: _Icons.LayerBackwardIcon
333
+ }, {
334
+ label: "Send to Back",
335
+ Icon: _Icons.LayerBackIcon
336
+ }];
337
+ var OutlineElementOptionsMenu = exports.OutlineElementOptionsMenu = function OutlineElementOptionsMenu(_ref2) {
338
+ var locked = _ref2.locked,
339
+ onToggleLock = _ref2.onToggleLock;
340
+ var _useState = (0, _react.useState)(false),
341
+ _useState2 = _slicedToArray(_useState, 2),
342
+ open = _useState2[0],
343
+ setOpen = _useState2[1];
344
+ var _useState3 = (0, _react.useState)("index"),
345
+ _useState4 = _slicedToArray(_useState3, 2),
346
+ view = _useState4[0],
347
+ setView = _useState4[1];
348
+ var _useState5 = (0, _react.useState)(true),
349
+ _useState6 = _slicedToArray(_useState5, 2),
350
+ isLeft = _useState6[0],
351
+ setIsLeft = _useState6[1];
352
+ var _useState7 = (0, _react.useState)(0),
353
+ _useState8 = _slicedToArray(_useState7, 2),
354
+ height = _useState8[0],
355
+ setHeight = _useState8[1];
356
+ var measure = (0, _react.useCallback)(function (node) {
357
+ if (node) {
358
+ setHeight(node.offsetHeight);
359
+ }
360
+ }, []);
361
+ var goToArrange = function goToArrange() {
362
+ setView("arrange");
363
+ setIsLeft(true);
364
+ };
365
+ var backToIndex = function backToIndex() {
366
+ setView("index");
367
+ setIsLeft(false);
368
+ };
369
+ var handleClose = function handleClose() {
370
+ setOpen(false);
371
+ setView("index");
372
+ setIsLeft(true);
373
+ };
374
+ var indexView = /*#__PURE__*/_react.default.createElement(StyledOutlineElementMenu, null, /*#__PURE__*/_react.default.createElement(_List.List, {
375
+ style: OUTLINE_MENU_LIST_STYLE,
376
+ tabIndex: -1
377
+ }, /*#__PURE__*/_react.default.createElement(_List.ListItem, null, /*#__PURE__*/_react.default.createElement(_Icons.EditIcon, null), "Rename"), /*#__PURE__*/_react.default.createElement(_List.ListItem, null, /*#__PURE__*/_react.default.createElement(_Icons.DuplicateIcon, null), "Duplicate"), /*#__PURE__*/_react.default.createElement(_List.ListSeparator, null), /*#__PURE__*/_react.default.createElement(_List.ListItem, null, /*#__PURE__*/_react.default.createElement(_Icons.FolderMoveIcon, null), "Move to Group"), /*#__PURE__*/_react.default.createElement(_List.ListItem, {
378
+ className: "drill-item",
379
+ onClick: goToArrange
380
+ }, /*#__PURE__*/_react.default.createElement("span", {
381
+ className: "opt-left"
382
+ }, /*#__PURE__*/_react.default.createElement(_Icons.LayersIcon, null), "Arrange"), /*#__PURE__*/_react.default.createElement(_Icons.CaretRightIcon, {
383
+ className: "drill-caret",
384
+ width: 16,
385
+ height: 16
386
+ })), /*#__PURE__*/_react.default.createElement(_List.ListSeparator, null), /*#__PURE__*/_react.default.createElement(_List.ListItem, {
387
+ onClick: function onClick() {
388
+ onToggleLock();
389
+ handleClose();
390
+ }
391
+ }, /*#__PURE__*/_react.default.createElement(_Icons.LockIcon, null), locked ? "Unlock" : "Lock"), /*#__PURE__*/_react.default.createElement(_List.ListSeparator, null), /*#__PURE__*/_react.default.createElement(_List.ListItem, null, /*#__PURE__*/_react.default.createElement(_Icons.TrashIcon, null), "Move to Trash")));
392
+ var arrangeView = /*#__PURE__*/_react.default.createElement(StyledOutlineElementMenu, null, /*#__PURE__*/_react.default.createElement(_Menu.MenuHeader, {
393
+ title: "Arrange",
394
+ leftElement: /*#__PURE__*/_react.default.createElement(_IconButton.IconButton, {
395
+ type: "button",
396
+ variant: "text gray",
397
+ size: "small",
398
+ onClick: backToIndex,
399
+ "aria-label": "Back"
400
+ }, /*#__PURE__*/_react.default.createElement(_Icons.ArrowLeftIcon, null))
401
+ }), /*#__PURE__*/_react.default.createElement(_List.List, {
402
+ style: OUTLINE_MENU_LIST_STYLE,
403
+ tabIndex: -1
404
+ }, ARRANGE_ITEMS.map(function (_ref3) {
405
+ var label = _ref3.label,
406
+ Icon = _ref3.Icon;
407
+ return /*#__PURE__*/_react.default.createElement(_List.ListItem, {
408
+ key: label,
409
+ onClick: backToIndex
410
+ }, /*#__PURE__*/_react.default.createElement(Icon, null), label);
411
+ })));
412
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(OutlineMenuSliderStyle, null), /*#__PURE__*/_react.default.createElement(_Menu.Menu, {
413
+ open: open,
414
+ onOpen: function onOpen() {
415
+ return setOpen(true);
416
+ },
417
+ onClose: handleClose,
418
+ position: "bottom-end",
419
+ menuClassName: "outline-element-menu",
420
+ target: /*#__PURE__*/_react.default.createElement(_IconButton.IconButton, {
421
+ type: "button",
422
+ variant: "text gray",
423
+ className: open ? "open" : undefined,
424
+ active: open
425
+ }, /*#__PURE__*/_react.default.createElement(_Icons.TreeDotsIcon, null))
426
+ }, /*#__PURE__*/_react.default.createElement(_Transitions.ResizeTransition, {
427
+ in: true,
428
+ style: {
429
+ height,
430
+ width: OUTLINE_MENU_WIDTH
431
+ }
432
+ }, /*#__PURE__*/_react.default.createElement("div", {
433
+ style: {
434
+ position: "relative",
435
+ overflow: "hidden"
436
+ }
437
+ }, /*#__PURE__*/_react.default.createElement(_Transitions.SlideLeftRightTransition, {
438
+ in: view === "index",
439
+ direction: isLeft ? "left" : "right"
440
+ }, /*#__PURE__*/_react.default.createElement("div", {
441
+ ref: measure,
442
+ style: {
443
+ width: OUTLINE_MENU_WIDTH
444
+ }
445
+ }, indexView)), /*#__PURE__*/_react.default.createElement(_Transitions.SlideLeftRightTransition, {
446
+ in: view === "arrange",
447
+ direction: isLeft ? "left" : "right"
448
+ }, /*#__PURE__*/_react.default.createElement("div", {
449
+ ref: measure,
450
+ style: {
451
+ width: OUTLINE_MENU_WIDTH
452
+ }
453
+ }, arrangeView))))));
454
+ };
455
+ var OutlineGroupOptionsMenu = exports.OutlineGroupOptionsMenu = function OutlineGroupOptionsMenu() {
456
+ var _useState9 = (0, _react.useState)(false),
457
+ _useState0 = _slicedToArray(_useState9, 2),
458
+ open = _useState0[0],
459
+ setOpen = _useState0[1];
460
+ return /*#__PURE__*/_react.default.createElement(_Menu.Menu, {
461
+ open: open,
462
+ onOpen: function onOpen() {
463
+ return setOpen(true);
464
+ },
465
+ onClose: function onClose() {
466
+ return setOpen(false);
467
+ },
468
+ position: "bottom-end",
469
+ target: /*#__PURE__*/_react.default.createElement(_IconButton.IconButton, {
470
+ type: "button",
471
+ variant: "text gray",
472
+ className: open ? "open" : undefined,
473
+ active: open
474
+ }, /*#__PURE__*/_react.default.createElement(_Icons.TreeDotsIcon, null))
475
+ }, /*#__PURE__*/_react.default.createElement(_List.List, {
476
+ style: OUTLINE_MENU_LIST_STYLE,
477
+ tabIndex: -1
478
+ }, /*#__PURE__*/_react.default.createElement(_List.ListItem, null, /*#__PURE__*/_react.default.createElement(_Icons.EditIcon, null), "Rename"), /*#__PURE__*/_react.default.createElement(_List.ListItem, null, /*#__PURE__*/_react.default.createElement(_Icons.DuplicateIcon, null), "Duplicate"), /*#__PURE__*/_react.default.createElement(_List.ListSeparator, null), /*#__PURE__*/_react.default.createElement(_List.ListItem, null, /*#__PURE__*/_react.default.createElement(_Icons.FolderMoveIcon, null), "Ungroup"), /*#__PURE__*/_react.default.createElement(_List.ListSeparator, null), /*#__PURE__*/_react.default.createElement(_List.ListItem, null, /*#__PURE__*/_react.default.createElement(_Icons.TrashIcon, null), "Move to Trash")));
479
+ };
480
+ var INFO_ROWS = exports.INFO_ROWS = [["Owner", "Ilija Studen"], ["Created", "Jul 30, 2026"], ["Members", "12"], ["Elements", "48"], ["Last edited", "2 hours ago"]];
481
+
482
+ /* The upper-left menu — exit fullscreen, board name, the Show / Hide Sidebar
483
+ toggle and the people menu. It renders in one of two places: floating over the
484
+ board while the sidebar is closed, and inside the sidebar's header once it
485
+ opens, so the controls follow the panel rather than being shoved aside by it. */
486
+ var LeftMenuContents = exports.LeftMenuContents = function LeftMenuContents(_ref4) {
487
+ var sidebarOpen = _ref4.sidebarOpen,
488
+ onToggleSidebar = _ref4.onToggleSidebar,
489
+ boardName = _ref4.boardName,
490
+ onRenameBoard = _ref4.onRenameBoard;
491
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_Tooltip.Tooltip, {
492
+ title: "Back to Whiteboards"
493
+ }, /*#__PURE__*/_react.default.createElement(_IconButton.IconButton, {
494
+ variant: "text gray"
495
+ }, /*#__PURE__*/_react.default.createElement(_Icons.ArrowLeftIcon, null))), /*#__PURE__*/_react.default.createElement("span", {
496
+ className: "wb-title"
497
+ }, /*#__PURE__*/_react.default.createElement(_EditableText.EditableText, {
498
+ value: boardName,
499
+ variant: "Title 2",
500
+ weight: "bold",
501
+ onSave: function onSave(event) {
502
+ return onRenameBoard(event.target.value);
503
+ },
504
+ inputProps: {
505
+ maxLength: 150
506
+ }
507
+ })), /*#__PURE__*/_react.default.createElement(_Tooltip.Tooltip, {
508
+ title: sidebarOpen ? "Hide Sidebar" : "Show Sidebar"
509
+ }, /*#__PURE__*/_react.default.createElement(_IconButton.IconButton, {
510
+ variant: "text gray",
511
+ onClick: onToggleSidebar
512
+ }, /*#__PURE__*/_react.default.createElement(_Icons.SidebarLeftIcon, null))), /*#__PURE__*/_react.default.createElement(_peopleMenu.WhiteboardPeopleMenu, null));
513
+ };
514
+
515
+ /* When the sidebar is open the left menu becomes its header: same controls, but
516
+ laid out as a flat 60px bar with the board name flexing to fill the middle. */
517
+ var StyledSidebarHeader = exports.StyledSidebarHeader = _styledComponents.default.div.withConfig({
518
+ displayName: "outline__StyledSidebarHeader",
519
+ componentId: "sc-173k9fg-12"
520
+ })(["display:flex;align-items:center;gap:2px;height:60px;padding:0 12px;box-sizing:border-box;flex-shrink:0;.wb-title{flex:1;min-width:0;margin:0 4px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}"]);
521
+
522
+ /* Centered segmented switch between the dock's two panels; the active one is
523
+ highlighted. This row replaces the old per-panel header. */
524
+ var StyledChooseRow = exports.StyledChooseRow = _styledComponents.default.div.withConfig({
525
+ displayName: "outline__StyledChooseRow",
526
+ componentId: "sc-173k9fg-13"
527
+ })(["display:flex;justify-content:center;padding:12px 16px;flex-shrink:0;"]);
528
+
529
+ /* The app renders the switch through ChooseV2 in a fixed 224px slot with the
530
+ button group centered inside it (the group alone is narrower than the slot,
531
+ and ChooseV2's own flex container leaves it at the left edge). */
532
+ var StyledPanelChooseSlot = exports.StyledPanelChooseSlot = _styledComponents.default.div.withConfig({
533
+ displayName: "outline__StyledPanelChooseSlot",
534
+ componentId: "sc-173k9fg-14"
535
+ })(["width:224px;.c-btn-group{margin:0 auto;}"]);
536
+ var StyledInfoPanel = exports.StyledInfoPanel = _styledComponents.default.div.withConfig({
537
+ displayName: "outline__StyledInfoPanel",
538
+ componentId: "sc-173k9fg-15"
539
+ })(["flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:16px;.info-meta{display:flex;flex-direction:column;gap:10px;}.info-row{display:flex;align-items:baseline;justify-content:space-between;gap:12px;}"]);
540
+
541
+ /* Mock only — the Info panel's content is a placeholder while the two-panel dock
542
+ is explored; the fields here are not the point. */
543
+ var InfoPanelContent = exports.InfoPanelContent = function InfoPanelContent(_ref5) {
544
+ var boardName = _ref5.boardName;
545
+ return /*#__PURE__*/_react.default.createElement(StyledInfoPanel, null, /*#__PURE__*/_react.default.createElement(_Typography.Header3, {
546
+ color: "primary"
547
+ }, boardName), /*#__PURE__*/_react.default.createElement("div", {
548
+ className: "info-meta"
549
+ }, INFO_ROWS.map(function (_ref6) {
550
+ var _ref7 = _slicedToArray(_ref6, 2),
551
+ label = _ref7[0],
552
+ value = _ref7[1];
553
+ return /*#__PURE__*/_react.default.createElement("div", {
554
+ className: "info-row",
555
+ key: label
556
+ }, /*#__PURE__*/_react.default.createElement(_Typography.Caption1, {
557
+ color: "secondary"
558
+ }, label), /*#__PURE__*/_react.default.createElement(_Typography.Body2, {
559
+ weight: "medium"
560
+ }, value));
561
+ })));
562
+ };
563
+
564
+ /* Centered text button below the group list — same text-gray treatment as the
565
+ old header icon (no outline, gray fill on hover), now with a label since it is
566
+ no longer squeezed into a header. */
567
+ var StyledNewGroupRow = exports.StyledNewGroupRow = _styledComponents.default.div.withConfig({
568
+ displayName: "outline__StyledNewGroupRow",
569
+ componentId: "sc-173k9fg-16"
570
+ })(["display:flex;justify-content:center;padding:12px 0 4px;svg{width:16px;height:16px;margin-right:6px;}"]);
571
+ var LeftSidebar = exports.LeftSidebar = function LeftSidebar(_ref8) {
572
+ var selectedId = _ref8.selectedId,
573
+ onSelect = _ref8.onSelect,
574
+ activePanel = _ref8.activePanel,
575
+ onPanelChange = _ref8.onPanelChange,
576
+ sidebarOpen = _ref8.sidebarOpen,
577
+ onToggleSidebar = _ref8.onToggleSidebar,
578
+ boardName = _ref8.boardName,
579
+ onRenameBoard = _ref8.onRenameBoard;
580
+ var _useState1 = (0, _react.useState)(OUTLINE_WIDTH),
581
+ _useState10 = _slicedToArray(_useState1, 2),
582
+ width = _useState10[0],
583
+ setWidth = _useState10[1];
584
+ var _useState11 = (0, _react.useState)(false),
585
+ _useState12 = _slicedToArray(_useState11, 2),
586
+ resizing = _useState12[0],
587
+ setResizing = _useState12[1];
588
+ var _useState13 = (0, _react.useState)(OUTLINE_GROUPS),
589
+ _useState14 = _slicedToArray(_useState13, 2),
590
+ groups = _useState14[0],
591
+ setGroups = _useState14[1];
592
+ var _useState15 = (0, _react.useState)(OUTLINE_ELEMENTS),
593
+ _useState16 = _slicedToArray(_useState15, 2),
594
+ elements = _useState16[0],
595
+ setElements = _useState16[1];
596
+ var _useState17 = (0, _react.useState)(["group-sketches"]),
597
+ _useState18 = _slicedToArray(_useState17, 2),
598
+ collapsed = _useState18[0],
599
+ setCollapsed = _useState18[1];
600
+ var _useState19 = (0, _react.useState)(null),
601
+ _useState20 = _slicedToArray(_useState19, 2),
602
+ dragId = _useState20[0],
603
+ setDragId = _useState20[1];
604
+ var _useState21 = (0, _react.useState)(null),
605
+ _useState22 = _slicedToArray(_useState21, 2),
606
+ dropSpot = _useState22[0],
607
+ setDropSpot = _useState22[1];
608
+ var isGroup = (0, _react.useCallback)(function (id) {
609
+ return groups.some(function (group) {
610
+ return group.id === id;
611
+ });
612
+ }, [groups]);
613
+ var membersOf = (0, _react.useCallback)(function (groupId) {
614
+ return elements.filter(function (element) {
615
+ return element.groupId === groupId;
616
+ });
617
+ }, [elements]);
618
+ var toggleCollapsed = (0, _react.useCallback)(function (id) {
619
+ setCollapsed(function (current) {
620
+ return current.includes(id) ? current.filter(function (entry) {
621
+ return entry !== id;
622
+ }) : [...current, id];
623
+ });
624
+ }, []);
625
+ var renameGroup = (0, _react.useCallback)(function (id, name) {
626
+ setGroups(function (current) {
627
+ return current.map(function (group) {
628
+ return group.id === id ? _objectSpread(_objectSpread({}, group), {}, {
629
+ name
630
+ }) : group;
631
+ });
632
+ });
633
+ }, []);
634
+ var renameElement = (0, _react.useCallback)(function (id, name) {
635
+ setElements(function (current) {
636
+ return current.map(function (element) {
637
+ return element.id === id ? _objectSpread(_objectSpread({}, element), {}, {
638
+ name
639
+ }) : element;
640
+ });
641
+ });
642
+ }, []);
643
+ var toggleLock = (0, _react.useCallback)(function (id) {
644
+ setElements(function (current) {
645
+ return current.map(function (element) {
646
+ return element.id === id ? _objectSpread(_objectSpread({}, element), {}, {
647
+ locked: !element.locked
648
+ }) : element;
649
+ });
650
+ });
651
+ }, []);
652
+
653
+ /* The gesture is tracked from its ORIGIN (pointer x + width at mousedown)
654
+ rather than from the pointer's absolute position, so the panel edge stays
655
+ locked to the cursor even once the width clamps at a bound — otherwise the
656
+ pointer drifts away from the edge and the panel jumps when it comes back.
657
+ Listeners go on window so the drag survives the pointer leaving the strip,
658
+ and body user-select is suspended so dragging does not select the rows. */
659
+ var startResize = (0, _react.useCallback)(function (event) {
660
+ var _event$currentTarget$, _event$currentTarget$2;
661
+ event.preventDefault();
662
+ var startX = event.clientX;
663
+ var startWidth = (_event$currentTarget$ = (_event$currentTarget$2 = event.currentTarget.parentElement) === null || _event$currentTarget$2 === void 0 ? void 0 : _event$currentTarget$2.offsetWidth) !== null && _event$currentTarget$ !== void 0 ? _event$currentTarget$ : 0;
664
+ var previousUserSelect = document.body.style.userSelect;
665
+ setResizing(true);
666
+ document.body.style.userSelect = "none";
667
+ document.body.style.cursor = "col-resize";
668
+ var handleMove = function handleMove(moveEvent) {
669
+ var next = startWidth + (moveEvent.clientX - startX);
670
+ setWidth(Math.min(OUTLINE_MAX_WIDTH, Math.max(OUTLINE_MIN_WIDTH, next)));
671
+ };
672
+ var _handleUp = function handleUp() {
673
+ setResizing(false);
674
+ document.body.style.userSelect = previousUserSelect;
675
+ document.body.style.cursor = "";
676
+ window.removeEventListener("mousemove", handleMove);
677
+ window.removeEventListener("mouseup", _handleUp);
678
+ };
679
+ window.addEventListener("mousemove", handleMove);
680
+ window.addEventListener("mouseup", _handleUp);
681
+ }, []);
682
+ var addGroup = (0, _react.useCallback)(function () {
683
+ setGroups(function (current) {
684
+ return [...current, {
685
+ id: "group-".concat(Date.now()),
686
+ name: "New group"
687
+ }];
688
+ });
689
+ }, []);
690
+
691
+ /* Reorder mirrors the server contract: splice the moved entry into its new
692
+ slot, then treat the resulting array order AS the 1..N renumbering the
693
+ server would write back. Groups reorder among groups; an element moves
694
+ within or between containers, and its groupId follows the drop target —
695
+ which is the whole of "one level of nesting" as an invariant, since a
696
+ group is never a valid child. */
697
+ var handleDrop = (0, _react.useCallback)(function () {
698
+ var draggedId = dragId;
699
+ var spot = dropSpot;
700
+ setDragId(null);
701
+ setDropSpot(null);
702
+ if (!draggedId || !spot || draggedId === spot.id) {
703
+ return;
704
+ }
705
+ if (isGroup(draggedId)) {
706
+ /* a group can only land among groups, never inside one */
707
+ if (spot.kind === "into" || !isGroup(spot.id)) {
708
+ return;
709
+ }
710
+ setGroups(function (current) {
711
+ var from = current.findIndex(function (group) {
712
+ return group.id === draggedId;
713
+ });
714
+ var next = [...current];
715
+ var _next$splice = next.splice(from, 1),
716
+ _next$splice2 = _slicedToArray(_next$splice, 1),
717
+ moved = _next$splice2[0];
718
+ var to = next.findIndex(function (group) {
719
+ return group.id === spot.id;
720
+ });
721
+ next.splice(spot.kind === "before" ? to : to + 1, 0, moved);
722
+ return next;
723
+ });
724
+ return;
725
+ }
726
+ setElements(function (current) {
727
+ var from = current.findIndex(function (element) {
728
+ return element.id === draggedId;
729
+ });
730
+ var next = [...current];
731
+ var _next$splice3 = next.splice(from, 1),
732
+ _next$splice4 = _slicedToArray(_next$splice3, 1),
733
+ moved = _next$splice4[0];
734
+ if (spot.kind === "into") {
735
+ var groupId = spot.id === UNGROUPED ? null : spot.id;
736
+ var last = next.reduce(function (acc, element, index) {
737
+ return element.groupId === groupId ? index : acc;
738
+ }, -1);
739
+ next.splice(last + 1, 0, _objectSpread(_objectSpread({}, moved), {}, {
740
+ groupId
741
+ }));
742
+ return next;
743
+ }
744
+ var target = next.find(function (element) {
745
+ return element.id === spot.id;
746
+ });
747
+ if (!target) {
748
+ return current;
749
+ }
750
+ var to = next.findIndex(function (element) {
751
+ return element.id === spot.id;
752
+ });
753
+ next.splice(spot.kind === "before" ? to : to + 1, 0, _objectSpread(_objectSpread({}, moved), {}, {
754
+ groupId: target.groupId
755
+ }));
756
+ return next;
757
+ });
758
+ }, [dragId, dropSpot, isGroup]);
759
+ var rowDragProps = (0, _react.useCallback)(function (id) {
760
+ return {
761
+ draggable: true,
762
+ onDragStart: function onDragStart(event) {
763
+ /* A live EditableText input sits inside the row, and dragging a text
764
+ selection inside it must not turn into a row reorder. */
765
+ if (event.target.closest("input")) {
766
+ event.preventDefault();
767
+ return;
768
+ }
769
+ event.stopPropagation();
770
+ setDragId(id);
771
+ },
772
+ onDragEnd: function onDragEnd() {
773
+ setDragId(null);
774
+ setDropSpot(null);
775
+ },
776
+ onDragOver: function onDragOver(event) {
777
+ if (!dragId || dragId === id) {
778
+ return;
779
+ }
780
+ event.preventDefault();
781
+ event.stopPropagation();
782
+ var box = event.currentTarget.getBoundingClientRect();
783
+ var isTopHalf = event.clientY - box.top < box.height / 2;
784
+
785
+ /* an element dragged onto a GROUP header joins that group; the
786
+ insertion halves are reserved for reordering groups themselves */
787
+ if (isGroup(id) && !isGroup(dragId)) {
788
+ setDropSpot({
789
+ kind: "into",
790
+ id
791
+ });
792
+ return;
793
+ }
794
+ setDropSpot({
795
+ kind: isTopHalf ? "before" : "after",
796
+ id
797
+ });
798
+ },
799
+ onDrop: function onDrop(event) {
800
+ event.preventDefault();
801
+ event.stopPropagation();
802
+ handleDrop();
803
+ }
804
+ };
805
+ }, [dragId, handleDrop, isGroup]);
806
+ var dropClass = (0, _react.useCallback)(function (id) {
807
+ if (dragId === id) {
808
+ return "dragging";
809
+ }
810
+ if (!dropSpot || dropSpot.id !== id) {
811
+ return "";
812
+ }
813
+ return "drop-".concat(dropSpot.kind);
814
+ }, [dragId, dropSpot]);
815
+ var renderElementRow = function renderElementRow(element) {
816
+ var TypeIcon = OUTLINE_TYPE_ICONS[element.type];
817
+ var selected = element.id === selectedId;
818
+ return /*#__PURE__*/_react.default.createElement(StyledOutlineChildRow, _extends({
819
+ key: element.id,
820
+ className: "".concat(selected ? "selected" : "", " ").concat(dropClass(element.id)),
821
+ onClick: function onClick() {
822
+ return onSelect(element.id);
823
+ }
824
+ }, rowDragProps(element.id)), /*#__PURE__*/_react.default.createElement(StyledOutlineTypeIcon, null, /*#__PURE__*/_react.default.createElement(TypeIcon, {
825
+ width: 16,
826
+ height: 16,
827
+ fill: element.name ? "var(--color-theme-700)" : "var(--color-theme-500)"
828
+ })), /*#__PURE__*/_react.default.createElement(StyledOutlineName, {
829
+ className: element.name ? "" : "unnamed"
830
+ }, /*#__PURE__*/_react.default.createElement(_EditableText.EditableText, {
831
+ value: outlineLabel(element),
832
+ variant: "Body 2",
833
+ weight: "medium",
834
+ disabled: !selected,
835
+ onSave: function onSave(event) {
836
+ return renameElement(element.id, event.target.value);
837
+ },
838
+ inputProps: {
839
+ maxLength: 150
840
+ }
841
+ })), element.locked || element.connections ? /*#__PURE__*/_react.default.createElement(StyledOutlineSignifiers, {
842
+ className: "outline-trailing"
843
+ }, element.connections ? /*#__PURE__*/_react.default.createElement(_Signifier.Signifier, {
844
+ type: _Icons.DependencySmallIcon,
845
+ value: element.connections,
846
+ tooltipText: "".concat(element.connections, " ").concat(element.connections === 1 ? "connection" : "connections")
847
+ }) : null, element.locked ? /*#__PURE__*/_react.default.createElement(_Signifier.Signifier, {
848
+ type: _Icons.LockSmallIcon,
849
+ tooltipText: "Locked"
850
+ }) : null) : null, /*#__PURE__*/_react.default.createElement("span", {
851
+ className: "outline-options outline-hover"
852
+ }, /*#__PURE__*/_react.default.createElement(OutlineElementOptionsMenu, {
853
+ locked: Boolean(element.locked),
854
+ onToggleLock: function onToggleLock() {
855
+ return toggleLock(element.id);
856
+ }
857
+ })));
858
+ };
859
+ return /*#__PURE__*/_react.default.createElement(StyledOutlineSidebar, {
860
+ style: {
861
+ width
862
+ }
863
+ }, /*#__PURE__*/_react.default.createElement(StyledOutlineResizer, {
864
+ className: resizing ? "resizing" : "",
865
+ onMouseDown: startResize,
866
+ role: "separator",
867
+ "aria-orientation": "vertical",
868
+ "aria-label": "Resize outline"
869
+ }), /*#__PURE__*/_react.default.createElement(StyledSidebarHeader, null, /*#__PURE__*/_react.default.createElement(LeftMenuContents, {
870
+ sidebarOpen: sidebarOpen,
871
+ onToggleSidebar: onToggleSidebar,
872
+ boardName: boardName,
873
+ onRenameBoard: onRenameBoard
874
+ })), /*#__PURE__*/_react.default.createElement(StyledChooseRow, null, /*#__PURE__*/_react.default.createElement(StyledPanelChooseSlot, null, /*#__PURE__*/_react.default.createElement(_ChooseV.ChooseV2, {
875
+ required: true,
876
+ options: [{
877
+ id: "info",
878
+ name: "Info"
879
+ }, {
880
+ id: "outline",
881
+ name: "Outline"
882
+ }],
883
+ selected: [activePanel],
884
+ onChange: function onChange(selected) {
885
+ return onPanelChange(selected[0]);
886
+ }
887
+ }))), activePanel === "info" ? /*#__PURE__*/_react.default.createElement(InfoPanelContent, {
888
+ boardName: boardName
889
+ }) : null, activePanel === "outline" ? /*#__PURE__*/_react.default.createElement(StyledOutlineBody, null, /*#__PURE__*/_react.default.createElement(StyledOutlineGroupRow, {
890
+ className: (dropSpot === null || dropSpot === void 0 ? void 0 : dropSpot.kind) === "into" && dropSpot.id === UNGROUPED ? "drop-into" : "",
891
+ onClick: function onClick() {
892
+ return toggleCollapsed(UNGROUPED);
893
+ },
894
+ onDragOver: function onDragOver(event) {
895
+ if (!dragId || isGroup(dragId)) {
896
+ return;
897
+ }
898
+ event.preventDefault();
899
+ setDropSpot({
900
+ kind: "into",
901
+ id: UNGROUPED
902
+ });
903
+ },
904
+ onDrop: function onDrop(event) {
905
+ event.preventDefault();
906
+ handleDrop();
907
+ }
908
+ }, /*#__PURE__*/_react.default.createElement(StyledOutlineToggle, {
909
+ type: "button",
910
+ className: collapsed.includes(UNGROUPED) ? "collapsed" : "",
911
+ "aria-label": "Toggle ungrouped",
912
+ onClick: function onClick(event) {
913
+ event.stopPropagation();
914
+ toggleCollapsed(UNGROUPED);
915
+ }
916
+ }, /*#__PURE__*/_react.default.createElement(_Icons.CollapseExpandSingleIcon, {
917
+ fill: "var(--color-theme-700)"
918
+ })), /*#__PURE__*/_react.default.createElement(StyledOutlineName, null, /*#__PURE__*/_react.default.createElement(_Typography.Header3, {
919
+ color: "primary"
920
+ }, "Ungrouped")), /*#__PURE__*/_react.default.createElement(OutlineCounter, {
921
+ count: membersOf(null).length
922
+ })), collapsed.includes(UNGROUPED) ? null : membersOf(null).map(renderElementRow), groups.map(function (group) {
923
+ var members = membersOf(group.id);
924
+ var isOpen = !collapsed.includes(group.id);
925
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, {
926
+ key: group.id
927
+ }, /*#__PURE__*/_react.default.createElement(StyledOutlineGroupRow, _extends({
928
+ className: dropClass(group.id),
929
+ onClick: function onClick() {
930
+ return toggleCollapsed(group.id);
931
+ }
932
+ }, rowDragProps(group.id)), /*#__PURE__*/_react.default.createElement(StyledOutlineToggle, {
933
+ type: "button",
934
+ className: isOpen ? "" : "collapsed",
935
+ "aria-label": isOpen ? "Collapse group" : "Expand group",
936
+ onClick: function onClick(event) {
937
+ event.stopPropagation();
938
+ toggleCollapsed(group.id);
939
+ }
940
+ }, /*#__PURE__*/_react.default.createElement(_Icons.CollapseExpandSingleIcon, {
941
+ fill: "var(--color-theme-700)"
942
+ })), /*#__PURE__*/_react.default.createElement(StyledOutlineName, {
943
+ onClick: function onClick(event) {
944
+ return event.stopPropagation();
945
+ }
946
+ }, /*#__PURE__*/_react.default.createElement(_EditableText.EditableText, {
947
+ value: group.name,
948
+ variant: "Header 3",
949
+ weight: "bold",
950
+ onSave: function onSave(event) {
951
+ return renameGroup(group.id, event.target.value);
952
+ },
953
+ inputProps: {
954
+ maxLength: 150
955
+ }
956
+ })), /*#__PURE__*/_react.default.createElement(OutlineCounter, {
957
+ count: members.length
958
+ }), /*#__PURE__*/_react.default.createElement("span", {
959
+ className: "outline-options outline-hover"
960
+ }, /*#__PURE__*/_react.default.createElement(OutlineGroupOptionsMenu, null))), isOpen ? members.map(renderElementRow) : null);
961
+ }), /*#__PURE__*/_react.default.createElement(StyledNewGroupRow, null, /*#__PURE__*/_react.default.createElement(_Button.Button, {
962
+ variant: "text gray",
963
+ onClick: addGroup
964
+ }, /*#__PURE__*/_react.default.createElement(_Icons.FolderPlusIcon, null), "New Group"))) : null);
965
+ };
966
+ //# sourceMappingURL=outline.js.map