@elaraai/e3-ui-components 1.0.31 → 1.0.32
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/decision/grouping.d.ts +23 -0
- package/dist/decision/grouping.d.ts.map +1 -0
- package/dist/decision/queue.d.ts.map +1 -1
- package/dist/index.cjs +162 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +163 -31
- package/dist/index.js.map +1 -1
- package/package.json +13 -13
package/dist/index.js
CHANGED
|
@@ -28,7 +28,7 @@ import { jsx as jsx$1, Fragment, jsxs } from "react/jsx-runtime";
|
|
|
28
28
|
import * as React from "react";
|
|
29
29
|
import React__default, { useId, useMemo, useContext, createContext, useRef, useEffect, useState, useCallback, useSyncExternalStore, memo, forwardRef, useLayoutEffect, Fragment as Fragment$1, Component } from "react";
|
|
30
30
|
import { Box, Flex, Text, HStack, Input, useSlotRecipe, useRecipe, VStack, useToken, Drawer, Portal, Field, NativeSelect, Textarea, chakra, Tooltip, SegmentGroup, Menu, HoverCard, useChakraContext, Spinner, Code, Clipboard, IconButton, Badge, Button, Tabs, useTabs } from "@chakra-ui/react";
|
|
31
|
-
import { implementUIComponent, getSomeorUndefined, formatPredicate, SliceEditPopover, SlicePredicateBuilder, EastChakraSelect, EastChakraStringInput, EastChakraDateTimeInput, EastChakraFloatInput, EastChakraIntegerInput, formatTick, useSliceReactivity, SliceRailCluster, EastChakraComponent, ClauseChip, StateImpl, NavImpl, SliceImpl, SliceApplyImpl, OverlayImpl, ClipboardImpl, DownloadImpl, ShareImpl, createUIStore, UIStoreProvider } from "@elaraai/east-ui-components";
|
|
31
|
+
import { implementUIComponent, getSomeorUndefined, formatPredicate, SliceEditPopover, SlicePredicateBuilder, EastChakraSelect, EastChakraStringInput, EastChakraDateTimeInput, EastChakraFloatInput, EastChakraIntegerInput, formatTick, useSliceReactivity, usePersistedState, SliceRailCluster, EastChakraComponent, ClauseChip, StateImpl, NavImpl, SliceImpl, SliceApplyImpl, OverlayImpl, ClipboardImpl, DownloadImpl, ShareImpl, createUIStore, UIStoreProvider } from "@elaraai/east-ui-components";
|
|
32
32
|
import { createPortal } from "react-dom";
|
|
33
33
|
import { sliceMatches } from "@elaraai/east-ui/internal";
|
|
34
34
|
import { QueryClient as QueryClient$1, QueryClientProvider, useMutation, useQuery } from "@tanstack/react-query";
|
|
@@ -62910,6 +62910,39 @@ const URGENCY_RANK = {
|
|
|
62910
62910
|
due: 1,
|
|
62911
62911
|
routine: 2
|
|
62912
62912
|
};
|
|
62913
|
+
const URGENCY_GROUP_LABEL = {
|
|
62914
|
+
overdue: "Overdue",
|
|
62915
|
+
due: "Due today",
|
|
62916
|
+
routine: "Routine"
|
|
62917
|
+
};
|
|
62918
|
+
function buildGroups(rows, option) {
|
|
62919
|
+
if (option.key === "none") {
|
|
62920
|
+
return [{ label: "", decisions: rows, pastSla: 0, total: 0, bulk: false }];
|
|
62921
|
+
}
|
|
62922
|
+
const labelFor = (d2) => {
|
|
62923
|
+
var _a2;
|
|
62924
|
+
return option.key === "urgency" ? URGENCY_GROUP_LABEL[d2.urgency.type] : option.key === "kind" ? d2.kind : ((_a2 = option.accessor) == null ? void 0 : _a2.call(option, d2)) ?? "";
|
|
62925
|
+
};
|
|
62926
|
+
const out = /* @__PURE__ */ new Map();
|
|
62927
|
+
for (const d2 of rows) {
|
|
62928
|
+
const label = labelFor(d2);
|
|
62929
|
+
let group2 = out.get(label);
|
|
62930
|
+
if (group2 === void 0) {
|
|
62931
|
+
group2 = {
|
|
62932
|
+
label,
|
|
62933
|
+
decisions: [],
|
|
62934
|
+
pastSla: 0,
|
|
62935
|
+
total: 0,
|
|
62936
|
+
bulk: option.key === "urgency" && d2.urgency.type === "routine"
|
|
62937
|
+
};
|
|
62938
|
+
out.set(label, group2);
|
|
62939
|
+
}
|
|
62940
|
+
group2.decisions.push(d2);
|
|
62941
|
+
group2.total += d2.value;
|
|
62942
|
+
if (d2.urgency.type === "overdue") group2.pastSla += 1;
|
|
62943
|
+
}
|
|
62944
|
+
return [...out.values()];
|
|
62945
|
+
}
|
|
62913
62946
|
const FACETS = [
|
|
62914
62947
|
{ key: "evidence", label: "Evidence" },
|
|
62915
62948
|
{ key: "options", label: "Options" },
|
|
@@ -63026,7 +63059,8 @@ const Row = memo(function Row2({ decision, handle, selected: selected2, narrow,
|
|
|
63026
63059
|
),
|
|
63027
63060
|
/* @__PURE__ */ jsx$1(Box, { as: "button", css: button({ variant: "ghost", size: "xs" }), onClick: handleReject, children: "Reject" })
|
|
63028
63061
|
] });
|
|
63029
|
-
const
|
|
63062
|
+
const fullTitle = `${decision.kind} · ${decision.title}${summary !== void 0 ? ` · ${summary}` : ""}`;
|
|
63063
|
+
const title = /* @__PURE__ */ jsxs(Box, { css: rs.titleText, title: fullTitle, cursor: selected2 ? void 0 : "pointer", onClick: handleSelect, children: [
|
|
63030
63064
|
/* @__PURE__ */ jsx$1(Text, { as: "span", fontWeight: "semibold", children: decision.kind }),
|
|
63031
63065
|
/* @__PURE__ */ jsx$1(Text, { as: "span", color: "fg.subtle", children: " · " }),
|
|
63032
63066
|
/* @__PURE__ */ jsx$1(Text, { as: "span", children: decision.title }),
|
|
@@ -63111,10 +63145,39 @@ const RoutineGroup = memo(function RoutineGroup2({ routine, acceptAll, leaving,
|
|
|
63111
63145
|
] })
|
|
63112
63146
|
] });
|
|
63113
63147
|
});
|
|
63148
|
+
const GroupHead = memo(function GroupHead2({ group: group2, collapsible, collapsed, onToggle, acceptAll }) {
|
|
63149
|
+
const dq = useSlotRecipe({ key: "decisionQueue" });
|
|
63150
|
+
const button = useRecipe({ key: "button" });
|
|
63151
|
+
const rs = dq({});
|
|
63152
|
+
const format2 = group2.decisions[0] ? getSomeorUndefined(group2.decisions[0].format) : void 0;
|
|
63153
|
+
const handleToggle = useCallback(() => {
|
|
63154
|
+
if (collapsible) onToggle(group2.label);
|
|
63155
|
+
}, [collapsible, onToggle, group2.label]);
|
|
63156
|
+
const handleAcceptAll = useCallback((e3) => {
|
|
63157
|
+
e3.stopPropagation();
|
|
63158
|
+
if (acceptAll) acceptAll(group2.decisions);
|
|
63159
|
+
}, [acceptAll, group2.decisions]);
|
|
63160
|
+
return /* @__PURE__ */ jsxs(Box, { css: rs.groupHead, ...collapsible ? { "data-collapsible": "" } : {}, onClick: handleToggle, children: [
|
|
63161
|
+
collapsible && /* @__PURE__ */ jsx$1(Box, { as: "span", css: rs.groupCaret, children: collapsed ? "▸" : "▾" }),
|
|
63162
|
+
/* @__PURE__ */ jsxs(Box, { as: "span", css: rs.groupLabel, children: [
|
|
63163
|
+
group2.label,
|
|
63164
|
+
" · ",
|
|
63165
|
+
group2.decisions.length
|
|
63166
|
+
] }),
|
|
63167
|
+
/* @__PURE__ */ jsxs(Box, { as: "span", css: rs.groupSummary, children: [
|
|
63168
|
+
formatTick(group2.total, format2),
|
|
63169
|
+
group2.pastSla > 0 ? ` · ${group2.pastSla} past SLA` : ""
|
|
63170
|
+
] }),
|
|
63171
|
+
acceptAll && /* @__PURE__ */ jsx$1(Box, { as: "button", css: button({ variant: "solid", size: "xs" }), onClick: handleAcceptAll, children: "Accept all" })
|
|
63172
|
+
] });
|
|
63173
|
+
});
|
|
63114
63174
|
const EastChakraDecisionQueue = memo(function EastChakraDecisionQueue2({ value, storageKey }) {
|
|
63115
63175
|
var _a2;
|
|
63116
63176
|
const eyebrow = useSlotRecipe({ key: "eyebrowRow" });
|
|
63117
63177
|
const es = eyebrow({});
|
|
63178
|
+
const dq = useSlotRecipe({ key: "decisionQueue" });
|
|
63179
|
+
const qs = dq({});
|
|
63180
|
+
const chip = useRecipe({ key: "chip" });
|
|
63118
63181
|
const handleRef = value.handle;
|
|
63119
63182
|
const handle = useDecisionHandle(handleRef);
|
|
63120
63183
|
const decisions = handle.decisions;
|
|
@@ -63183,6 +63246,25 @@ const EastChakraDecisionQueue = memo(function EastChakraDecisionQueue2({ value,
|
|
|
63183
63246
|
return facets === void 0 ? null : new Set(facets.map((f2) => f2.type));
|
|
63184
63247
|
}, [value.facets]);
|
|
63185
63248
|
const defaultExpanded = getSomeorUndefined(value.defaultExpanded);
|
|
63249
|
+
const groupDefs = useMemo(
|
|
63250
|
+
() => getSomeorUndefined(value.groups) ?? [],
|
|
63251
|
+
[value.groups]
|
|
63252
|
+
);
|
|
63253
|
+
const defaultGroupKey = getSomeorUndefined(value.groupBy);
|
|
63254
|
+
const grouped = defaultGroupKey !== void 0;
|
|
63255
|
+
const collapsible = grouped && (getSomeorUndefined(value.collapsible) ?? true);
|
|
63256
|
+
const groupOptions = useMemo(() => [
|
|
63257
|
+
{ key: "urgency", label: "Urgency" },
|
|
63258
|
+
{ key: "kind", label: "Kind" },
|
|
63259
|
+
...groupDefs.map((g2) => ({ key: g2.label, label: g2.label, accessor: g2.value })),
|
|
63260
|
+
{ key: "none", label: "None" }
|
|
63261
|
+
], [groupDefs]);
|
|
63262
|
+
const { state: toolbar, setState: setToolbar } = usePersistedState(`${storageKey}.toolbar`, {
|
|
63263
|
+
groupKey: defaultGroupKey ?? "urgency",
|
|
63264
|
+
// The urgency grouping's routine tail ships collapsed.
|
|
63265
|
+
collapsed: [URGENCY_GROUP_LABEL.routine]
|
|
63266
|
+
});
|
|
63267
|
+
const activeOption = groupOptions.find((o2) => o2.key === toolbar.groupKey) ?? groupOptions[0];
|
|
63186
63268
|
const selectedId = handle.selected ?? (defaultExpanded == null ? void 0 : defaultExpanded.id) ?? null;
|
|
63187
63269
|
const resolve2 = useCallback((ds, hook2, reason) => {
|
|
63188
63270
|
if (hook2) for (const d2 of ds) {
|
|
@@ -63197,15 +63279,15 @@ const EastChakraDecisionQueue = memo(function EastChakraDecisionQueue2({ value,
|
|
|
63197
63279
|
const apply2 = useCallback((d2) => resolve2([d2], onApply, "apply"), [resolve2, onApply]);
|
|
63198
63280
|
const reject2 = useCallback((d2) => resolve2([d2], onReject, "reject"), [resolve2, onReject]);
|
|
63199
63281
|
const acceptAll = useCallback((ds) => resolve2(ds, onApply, "apply"), [resolve2, onApply]);
|
|
63200
|
-
const { active, routine, pastSla, visible } = useMemo(() => {
|
|
63282
|
+
const { merged, active, routine, pastSla, visible } = useMemo(() => {
|
|
63201
63283
|
const scoped = decisions ?? [];
|
|
63202
63284
|
const now2 = /* @__PURE__ */ new Date();
|
|
63203
63285
|
const live = sliceState !== null ? scoped.filter((d2) => sliceMatches(sliceState, DECISION_SLICE_CONFIG, d2, now2)) : scoped;
|
|
63204
|
-
const
|
|
63286
|
+
const merged2 = [...live];
|
|
63205
63287
|
for (const { decision } of exiting.values()) {
|
|
63206
|
-
if (!
|
|
63288
|
+
if (!merged2.some((d2) => d2.id === decision.id)) merged2.push(decision);
|
|
63207
63289
|
}
|
|
63208
|
-
|
|
63290
|
+
merged2.sort((a2, b2) => {
|
|
63209
63291
|
var _a3, _b2;
|
|
63210
63292
|
const r2 = URGENCY_RANK[a2.urgency.type] - URGENCY_RANK[b2.urgency.type];
|
|
63211
63293
|
if (r2 !== 0) return r2;
|
|
@@ -63215,17 +63297,55 @@ const EastChakraDecisionQueue = memo(function EastChakraDecisionQueue2({ value,
|
|
|
63215
63297
|
return b2.value - a2.value;
|
|
63216
63298
|
});
|
|
63217
63299
|
return {
|
|
63218
|
-
|
|
63219
|
-
|
|
63220
|
-
|
|
63300
|
+
merged: merged2,
|
|
63301
|
+
active: merged2.filter((d2) => d2.urgency.type !== "routine"),
|
|
63302
|
+
routine: merged2.filter((d2) => d2.urgency.type === "routine"),
|
|
63303
|
+
pastSla: merged2.filter((d2) => d2.urgency.type === "overdue").length,
|
|
63221
63304
|
visible: live.length
|
|
63222
63305
|
};
|
|
63223
63306
|
}, [decisions, exiting, sliceState]);
|
|
63307
|
+
const groups = useMemo(
|
|
63308
|
+
() => grouped ? buildGroups(merged, activeOption) : [],
|
|
63309
|
+
[grouped, merged, activeOption]
|
|
63310
|
+
);
|
|
63311
|
+
const allCollapsed = groups.length > 0 && groups.every((g2) => g2.label === "" || toolbar.collapsed.includes(g2.label));
|
|
63312
|
+
const toggleGroup = useCallback((label) => {
|
|
63313
|
+
setToolbar((prev2) => ({
|
|
63314
|
+
...prev2,
|
|
63315
|
+
collapsed: prev2.collapsed.includes(label) ? prev2.collapsed.filter((l2) => l2 !== label) : [...prev2.collapsed, label]
|
|
63316
|
+
}));
|
|
63317
|
+
}, [setToolbar]);
|
|
63318
|
+
const toggleAll = useCallback(() => {
|
|
63319
|
+
const next2 = allCollapsed ? [] : groups.map((g2) => g2.label).filter((l2) => l2 !== "");
|
|
63320
|
+
setToolbar((prev2) => ({ ...prev2, collapsed: next2 }));
|
|
63321
|
+
}, [setToolbar, allCollapsed, groups]);
|
|
63322
|
+
const setGroupKey = useCallback((key) => {
|
|
63323
|
+
setToolbar((prev2) => prev2.groupKey === key ? prev2 : { ...prev2, groupKey: key });
|
|
63324
|
+
}, [setToolbar]);
|
|
63224
63325
|
const exitingReasons = useMemo(() => {
|
|
63225
63326
|
const m2 = /* @__PURE__ */ new Map();
|
|
63226
63327
|
for (const [id3, e3] of exiting) m2.set(id3, e3.reason);
|
|
63227
63328
|
return m2;
|
|
63228
63329
|
}, [exiting]);
|
|
63330
|
+
const renderRow = (d2) => /* @__PURE__ */ jsx$1(
|
|
63331
|
+
Row,
|
|
63332
|
+
{
|
|
63333
|
+
decision: d2,
|
|
63334
|
+
handle,
|
|
63335
|
+
selected: selectedId === d2.id,
|
|
63336
|
+
narrow,
|
|
63337
|
+
leverPayloads,
|
|
63338
|
+
modify,
|
|
63339
|
+
evidence,
|
|
63340
|
+
defaultFacet,
|
|
63341
|
+
facetInclude,
|
|
63342
|
+
apply: apply2,
|
|
63343
|
+
reject: reject2,
|
|
63344
|
+
leaving: exitingReasons.get(d2.id),
|
|
63345
|
+
storageKey
|
|
63346
|
+
},
|
|
63347
|
+
d2.id
|
|
63348
|
+
);
|
|
63229
63349
|
if (decisions === null) {
|
|
63230
63350
|
return /* @__PURE__ */ jsx$1(Box, { layerStyle: "surface.frameless", p: "16px", children: /* @__PURE__ */ jsx$1(Text, { color: "fg.muted", fontSize: "13px", children: "Loading decisions…" }) });
|
|
63231
63351
|
}
|
|
@@ -63253,33 +63373,45 @@ const EastChakraDecisionQueue = memo(function EastChakraDecisionQueue2({ value,
|
|
|
63253
63373
|
] })
|
|
63254
63374
|
] })
|
|
63255
63375
|
] }),
|
|
63256
|
-
/* @__PURE__ */ jsxs(
|
|
63376
|
+
grouped && /* @__PURE__ */ jsxs(Box, { css: qs.toolbar, children: [
|
|
63377
|
+
/* @__PURE__ */ jsx$1(Box, { as: "span", css: qs.segLabel, children: "Group by" }),
|
|
63378
|
+
groupOptions.map((o2) => /* @__PURE__ */ jsx$1(
|
|
63379
|
+
Box,
|
|
63380
|
+
{
|
|
63381
|
+
as: "button",
|
|
63382
|
+
css: { ...chip({ tone: toolbar.groupKey === o2.key ? "brand" : "neutral", size: "sm" }), cursor: "pointer" },
|
|
63383
|
+
"aria-pressed": toolbar.groupKey === o2.key,
|
|
63384
|
+
onClick: () => setGroupKey(o2.key),
|
|
63385
|
+
children: o2.label
|
|
63386
|
+
},
|
|
63387
|
+
o2.key
|
|
63388
|
+
)),
|
|
63389
|
+
collapsible && /* @__PURE__ */ jsx$1(Box, { as: "button", css: qs.collapseAll, onClick: toggleAll, children: allCollapsed ? "Expand all" : "Collapse all" })
|
|
63390
|
+
] }),
|
|
63391
|
+
/* @__PURE__ */ jsx$1(
|
|
63257
63392
|
Box,
|
|
63258
63393
|
{
|
|
63259
63394
|
maxHeight: getSomeorUndefined(value.maxHeight),
|
|
63260
63395
|
overflowY: value.maxHeight.type === "some" ? "auto" : void 0,
|
|
63261
|
-
children:
|
|
63262
|
-
|
|
63263
|
-
|
|
63264
|
-
|
|
63265
|
-
|
|
63266
|
-
|
|
63267
|
-
|
|
63268
|
-
|
|
63269
|
-
|
|
63270
|
-
|
|
63271
|
-
|
|
63272
|
-
|
|
63273
|
-
|
|
63274
|
-
|
|
63275
|
-
|
|
63276
|
-
|
|
63277
|
-
|
|
63278
|
-
},
|
|
63279
|
-
d2.id
|
|
63280
|
-
)),
|
|
63396
|
+
children: grouped ? groups.map((g2) => {
|
|
63397
|
+
const isCollapsed = collapsible && g2.label !== "" && toolbar.collapsed.includes(g2.label);
|
|
63398
|
+
return /* @__PURE__ */ jsxs(Box, { children: [
|
|
63399
|
+
g2.label !== "" && /* @__PURE__ */ jsx$1(
|
|
63400
|
+
GroupHead,
|
|
63401
|
+
{
|
|
63402
|
+
group: g2,
|
|
63403
|
+
collapsible,
|
|
63404
|
+
collapsed: isCollapsed,
|
|
63405
|
+
onToggle: toggleGroup,
|
|
63406
|
+
acceptAll: g2.bulk ? acceptAll : void 0
|
|
63407
|
+
}
|
|
63408
|
+
),
|
|
63409
|
+
!isCollapsed && g2.decisions.map(renderRow)
|
|
63410
|
+
] }, g2.label || "_flat");
|
|
63411
|
+
}) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
63412
|
+
active.map(renderRow),
|
|
63281
63413
|
/* @__PURE__ */ jsx$1(RoutineGroup, { routine, acceptAll, leaving: exitingReasons, narrow })
|
|
63282
|
-
]
|
|
63414
|
+
] })
|
|
63283
63415
|
}
|
|
63284
63416
|
)
|
|
63285
63417
|
] });
|