@tensor_1/react 2.47.0 → 2.48.0
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/README.md +470 -1
- package/dist/{SchedulingCalendar-B6TakO2h.d.ts → SchedulingCalendar-WWyFL3Eo.d.ts} +51 -2
- package/dist/announce.d.ts +10 -0
- package/dist/announce.js +30 -0
- package/dist/chart-analytic.cjs +33 -25
- package/dist/chart-preset.cjs +23 -15
- package/dist/chart.cjs +23 -15
- package/dist/combobox-model.d.ts +10 -1
- package/dist/combobox-model.js +15 -0
- package/dist/command-palette-model.d.ts +44 -0
- package/dist/command-palette-model.js +36 -0
- package/dist/components/AccountMenu.d.ts +44 -0
- package/dist/components/AccountMenu.js +43 -0
- package/dist/components/AppShell.d.ts +45 -2
- package/dist/components/AppShell.js +116 -5
- package/dist/components/AuditLog.d.ts +128 -0
- package/dist/components/AuditLog.js +196 -0
- package/dist/components/BrandProfiles.js +4 -3
- package/dist/components/Breadcrumbs.d.ts +9 -2
- package/dist/components/Breadcrumbs.js +3 -2
- package/dist/components/Button.d.ts +12 -5
- package/dist/components/Button.js +7 -3
- package/dist/components/Card.d.ts +18 -1
- package/dist/components/Card.js +5 -1
- package/dist/components/ChangeHighlight.d.ts +30 -0
- package/dist/components/ChangeHighlight.js +21 -0
- package/dist/components/ChartCore.js +2 -1
- package/dist/components/Checkbox.d.ts +27 -1
- package/dist/components/Checkbox.js +31 -2
- package/dist/components/CodeDisplay.d.ts +65 -0
- package/dist/components/CodeDisplay.js +124 -0
- package/dist/components/Combobox.d.ts +27 -6
- package/dist/components/Combobox.js +195 -58
- package/dist/components/CommandPalette.d.ts +36 -1
- package/dist/components/CommandPalette.js +254 -2
- package/dist/components/ContactCard.d.ts +66 -0
- package/dist/components/ContactCard.js +74 -0
- package/dist/components/Count.d.ts +24 -0
- package/dist/components/Count.js +32 -0
- package/dist/components/DataWorkspace.d.ts +167 -0
- package/dist/components/DataWorkspace.js +383 -0
- package/dist/components/DateFieldParts.d.ts +2 -1
- package/dist/components/DateFieldParts.js +7 -0
- package/dist/components/DatePicker.d.ts +9 -2
- package/dist/components/DatePicker.js +67 -28
- package/dist/components/DateRangePicker.d.ts +12 -2
- package/dist/components/DateRangePicker.js +13 -12
- package/dist/components/DetailPage.d.ts +7 -1
- package/dist/components/DetailPage.js +2 -1
- package/dist/components/Dialogs.d.ts +71 -10
- package/dist/components/Dialogs.js +130 -30
- package/dist/components/DiffViewer.d.ts +23 -3
- package/dist/components/DiffViewer.js +26 -12
- package/dist/components/DiscardPrompt.js +16 -0
- package/dist/components/DisplayPreferences.d.ts +83 -0
- package/dist/components/DisplayPreferences.js +185 -0
- package/dist/components/EditorialHome.d.ts +23 -3
- package/dist/components/EditorialHome.js +16 -11
- package/dist/components/EntityPicker.d.ts +20 -3
- package/dist/components/EntityPicker.js +32 -13
- package/dist/components/FilterEditor.d.ts +18 -4
- package/dist/components/FilterEditor.js +141 -19
- package/dist/components/InfoTip.js +11 -12
- package/dist/components/InlineEdit.d.ts +87 -20
- package/dist/components/InlineEdit.js +197 -54
- package/dist/components/Input.d.ts +12 -2
- package/dist/components/Input.js +5 -3
- package/dist/components/Kbd.d.ts +6 -1
- package/dist/components/Kbd.js +6 -6
- package/dist/components/Lightbox.d.ts +41 -5
- package/dist/components/Lightbox.js +95 -9
- package/dist/components/MatchReview.d.ts +40 -1
- package/dist/components/MatchReview.js +130 -4
- package/dist/components/MetricInput.js +3 -2
- package/dist/components/Modal.d.ts +2 -1
- package/dist/components/Modal.js +13 -4
- package/dist/components/NavFavourites.d.ts +5 -0
- package/dist/components/NavFavourites.js +7 -7
- package/dist/components/OtpInput.d.ts +33 -0
- package/dist/components/OtpInput.js +123 -0
- package/dist/components/PageHeader.d.ts +7 -1
- package/dist/components/PageHeader.js +2 -2
- package/dist/components/Pagination.js +6 -5
- package/dist/components/PasswordInput.d.ts +34 -0
- package/dist/components/PasswordInput.js +101 -0
- package/dist/components/Peek.js +3 -3
- package/dist/components/Popover.js +2 -0
- package/dist/components/PrintLayout.d.ts +63 -0
- package/dist/components/PrintLayout.js +114 -0
- package/dist/components/QrCode.d.ts +47 -0
- package/dist/components/QrCode.js +55 -0
- package/dist/components/QrScanner.d.ts +95 -0
- package/dist/components/QrScanner.js +266 -0
- package/dist/components/RelationshipGraph.d.ts +32 -1
- package/dist/components/RelationshipGraph.js +18 -5
- package/dist/components/RelationshipGraphLayered.d.ts +1 -1
- package/dist/components/RelationshipGraphLayered.js +190 -115
- package/dist/components/RelationshipGraphList.js +33 -6
- package/dist/components/RuleBuilder.js +39 -7
- package/dist/components/SchedulingAgenda.d.ts +3 -1
- package/dist/components/SchedulingCalendar.d.ts +3 -1
- package/dist/components/SchedulingCalendar.js +43 -4
- package/dist/components/SchedulingResourceDay.d.ts +57 -0
- package/dist/components/SchedulingResourceDay.js +287 -0
- package/dist/components/SchedulingTimeGrid.d.ts +3 -1
- package/dist/components/SchedulingTimeline.d.ts +3 -1
- package/dist/components/SearchSuggest.d.ts +23 -3
- package/dist/components/SearchSuggest.js +48 -17
- package/dist/components/Segmented.d.ts +39 -4
- package/dist/components/Segmented.js +31 -3
- package/dist/components/Select.d.ts +3 -2
- package/dist/components/Select.js +1 -1
- package/dist/components/ShortcutHint.d.ts +11 -10
- package/dist/components/ShortcutHint.js +44 -38
- package/dist/components/Sidebar.d.ts +36 -4
- package/dist/components/Sidebar.js +37 -12
- package/dist/components/SortableList.d.ts +45 -0
- package/dist/components/SortableList.js +134 -0
- package/dist/components/Stat.d.ts +28 -3
- package/dist/components/Stat.js +13 -3
- package/dist/components/StatusPill.d.ts +14 -3
- package/dist/components/StatusPill.js +11 -3
- package/dist/components/Steps.js +2 -1
- package/dist/components/Table.d.ts +9 -2
- package/dist/components/Table.js +4 -2
- package/dist/components/TableControls.js +18 -58
- package/dist/components/TableOverflowProbe.d.ts +12 -0
- package/dist/components/TableOverflowProbe.js +27 -0
- package/dist/components/Tabs.d.ts +2 -1
- package/dist/components/Tabs.js +1 -0
- package/dist/components/TagInput.d.ts +67 -0
- package/dist/components/TagInput.js +342 -0
- package/dist/components/Textarea.d.ts +5 -0
- package/dist/components/Textarea.js +2 -2
- package/dist/components/TimePicker.d.ts +80 -0
- package/dist/components/TimePicker.js +347 -0
- package/dist/components/Toast.js +3 -2
- package/dist/components/Tooltip.d.ts +8 -4
- package/dist/components/Tooltip.js +24 -21
- package/dist/components/Tree.d.ts +8 -0
- package/dist/components/Tree.js +11 -5
- package/dist/display-preferences-model.d.ts +53 -0
- package/dist/display-preferences-model.js +64 -0
- package/dist/emoji.cjs +28 -35
- package/dist/filter-model.d.ts +59 -3
- package/dist/filter-model.js +67 -2
- package/dist/hooks/useChangeHighlight.d.ts +33 -0
- package/dist/hooks/useChangeHighlight.js +44 -0
- package/dist/hooks/useDialog.d.ts +5 -0
- package/dist/hooks/useDialog.js +3 -2
- package/dist/hooks/useOptimisticValue.d.ts +51 -0
- package/dist/hooks/useOptimisticValue.js +61 -0
- package/dist/hooks/useReducedMotion.d.ts +4 -1
- package/dist/hooks/useReducedMotion.js +7 -1
- package/dist/hooks/useResolvedFilterLabels.d.ts +15 -0
- package/dist/hooks/useResolvedFilterLabels.js +34 -0
- package/dist/hooks/useVirtualRows.d.ts +21 -2
- package/dist/hooks/useVirtualRows.js +30 -3
- package/dist/icons/Icon.d.ts +1 -1
- package/dist/index.cjs +18644 -13210
- package/dist/index.d.cts +3003 -699
- package/dist/index.d.ts +42 -16
- package/dist/index.js +139 -7
- package/dist/labels-context.d.ts +90 -3
- package/dist/overlay-stack.d.ts +6 -0
- package/dist/overlay-stack.js +13 -0
- package/dist/qr-model.d.ts +65 -0
- package/dist/qr-model.js +323 -0
- package/dist/relationship-graph-model.d.ts +78 -3
- package/dist/relationship-graph-model.js +112 -5
- package/dist/reorder.d.ts +30 -0
- package/dist/reorder.js +74 -0
- package/dist/rich-text.cjs +4 -2
- package/dist/scheduling-resource-model.d.ts +76 -0
- package/dist/scheduling-resource-model.js +74 -0
- package/dist/search-suggest-model.js +3 -1
- package/dist/shell-context.d.ts +11 -0
- package/dist/shell-context.js +7 -0
- package/dist/time-field-model.d.ts +46 -0
- package/dist/time-field-model.js +152 -0
- package/dist/toast-store.d.ts +17 -1
- package/dist/toast-store.js +23 -7
- package/package.json +2 -1
|
@@ -1,8 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A colour that a node or an edge shares with a legend item (HAR-1639). Colour is never the only
|
|
3
|
+
* signal: say the same thing in the node's text, the edge's `description` or its `variant`.
|
|
4
|
+
*/
|
|
5
|
+
type RelationshipGraphTone = 'neutral' | 'info' | 'success' | 'warning' | 'danger' | 'accent';
|
|
1
6
|
interface RelationshipGraphNode {
|
|
2
7
|
id: string;
|
|
3
8
|
label: string;
|
|
4
9
|
type?: string;
|
|
5
10
|
description?: string;
|
|
11
|
+
/** Layered layout: the node's border and edge mark take this tone (HAR-1639). */
|
|
12
|
+
tone?: RelationshipGraphTone;
|
|
6
13
|
x?: number;
|
|
7
14
|
y?: number;
|
|
8
15
|
/** Layered layout: the node's column. Omitted → BFS distance from the root along source→target. */
|
|
@@ -20,6 +27,18 @@ interface RelationshipGraphEdge {
|
|
|
20
27
|
arrow?: RelationshipGraphArrow;
|
|
21
28
|
/** Layered layout: always draw this edge's label, whatever the label policy. */
|
|
22
29
|
emphasis?: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* `dashed` draws the line dashed, e.g. an expected relation that is missing (HAR-1639). Default
|
|
32
|
+
* `solid`; a lateral or cycle edge is dashed either way.
|
|
33
|
+
*/
|
|
34
|
+
variant?: 'solid' | 'dashed';
|
|
35
|
+
/** The line and arrowhead take this tone (HAR-1639). */
|
|
36
|
+
tone?: RelationshipGraphTone;
|
|
37
|
+
/**
|
|
38
|
+
* Said to assistive technology with the relationship, on both nodes it joins, e.g. "expected,
|
|
39
|
+
* missing" (HAR-1639). The drawn line itself is decoration; the nodes carry the relationship.
|
|
40
|
+
*/
|
|
41
|
+
description?: string;
|
|
23
42
|
}
|
|
24
43
|
interface PositionedRelationshipNode extends RelationshipGraphNode {
|
|
25
44
|
x: number;
|
|
@@ -35,7 +54,12 @@ declare function boundRelationshipGraph(nodes: RelationshipGraphNode[], edges: R
|
|
|
35
54
|
declare function relationshipNeighbors(nodeId: string, edges: RelationshipGraphEdge[]): string[];
|
|
36
55
|
declare function layoutRelationshipGraph(nodes: RelationshipGraphNode[], edges: RelationshipGraphEdge[], rootId?: string): PositionedRelationshipNode[];
|
|
37
56
|
declare function traverseRelationshipNode(nodes: RelationshipGraphNode[], currentId: string | undefined, direction: -1 | 1): string | undefined;
|
|
38
|
-
|
|
57
|
+
/**
|
|
58
|
+
* `forward` steps one column right; `skip` goes right across more than one column; `lateral`
|
|
59
|
+
* stays in its column; `back` goes left without closing a loop; `cycle` goes left and closes one
|
|
60
|
+
* (HAR-1639: only a cycle is flagged as one, and only lateral and cycle edges are dashed).
|
|
61
|
+
*/
|
|
62
|
+
type LayeredEdgeKind = 'forward' | 'skip' | 'lateral' | 'back' | 'cycle';
|
|
39
63
|
interface LayeredLayoutOptions {
|
|
40
64
|
rootId?: string;
|
|
41
65
|
/** Minimum sibling group size that collapses into a cluster. Default 6; 0 disables. */
|
|
@@ -70,7 +94,7 @@ interface LayeredItem {
|
|
|
70
94
|
children: string[];
|
|
71
95
|
/** Set on the first member of an expanded cluster: the group its collapse control belongs to. */
|
|
72
96
|
expandedGroup?: RelationshipGraphCluster;
|
|
73
|
-
/** True when a
|
|
97
|
+
/** True when a cycle edge touches this node (HAR-1639: no longer set by skip, lateral or back edges). */
|
|
74
98
|
inCycle: boolean;
|
|
75
99
|
/** Edges (any kind) touching this item. */
|
|
76
100
|
degree: number;
|
|
@@ -87,6 +111,10 @@ interface RoutedEdge {
|
|
|
87
111
|
label?: string;
|
|
88
112
|
arrow: RelationshipGraphArrow;
|
|
89
113
|
emphasis: boolean;
|
|
114
|
+
/** The first underlying edge's `variant`, `tone` and `description`. */
|
|
115
|
+
variant: 'solid' | 'dashed';
|
|
116
|
+
tone?: RelationshipGraphTone;
|
|
117
|
+
description?: string;
|
|
90
118
|
path: string;
|
|
91
119
|
labelX: number;
|
|
92
120
|
labelY: number;
|
|
@@ -96,6 +124,17 @@ interface RoutedEdge {
|
|
|
96
124
|
arrowAngle: number;
|
|
97
125
|
/** Label policy `auto` shows this label without interaction. */
|
|
98
126
|
autoLabel: boolean;
|
|
127
|
+
/**
|
|
128
|
+
* The label is said once by the target column's header (`LayeredColumn.edgeLabel`), so the
|
|
129
|
+
* edge itself never draws it under `edgeLabels="auto"` (HAR-1387: 197 of 200 labels on a
|
|
130
|
+
* 300-node map read "depends on").
|
|
131
|
+
*/
|
|
132
|
+
columnLabel: boolean;
|
|
133
|
+
/**
|
|
134
|
+
* One of a busy node's forward edges, drawn as a bus: along a shared trunk in the column gap
|
|
135
|
+
* and a short stub into the target, so a fan-out reads as one line, not a black fan (HAR-1387).
|
|
136
|
+
*/
|
|
137
|
+
bus: boolean;
|
|
99
138
|
/** The label wrapped to fit the column gap (at most two lines). */
|
|
100
139
|
labelLines: string[];
|
|
101
140
|
}
|
|
@@ -104,6 +143,11 @@ interface LayeredColumn {
|
|
|
104
143
|
x: number;
|
|
105
144
|
/** Underlying nodes in the column, cluster members included. */
|
|
106
145
|
count: number;
|
|
146
|
+
/**
|
|
147
|
+
* The relation most forward edges into this column share, when the column takes more than a
|
|
148
|
+
* few of them: the header says it once and those edges draw no label (HAR-1387).
|
|
149
|
+
*/
|
|
150
|
+
edgeLabel?: string;
|
|
107
151
|
}
|
|
108
152
|
interface LayeredLayout {
|
|
109
153
|
rootId: string | undefined;
|
|
@@ -135,8 +179,39 @@ declare function classifyLayeredEdges(nodes: RelationshipGraphNode[], edges: Rel
|
|
|
135
179
|
declare function clusterIdFor(parentId: string, type: string | undefined, edgeType: string | undefined): string;
|
|
136
180
|
/** Layered, clustered, crossing-reduced layout for `RelationshipGraph layout="layered"`. */
|
|
137
181
|
declare function layoutLayeredGraph(nodes: RelationshipGraphNode[], edges: RelationshipGraphEdge[], options?: LayeredLayoutOptions): LayeredLayout;
|
|
182
|
+
/** An edge label's box on the stage, for `separateEdgeLabels`. */
|
|
183
|
+
interface EdgeLabelBox {
|
|
184
|
+
id: string;
|
|
185
|
+
/** Centre of the label. */
|
|
186
|
+
x: number;
|
|
187
|
+
y: number;
|
|
188
|
+
width: number;
|
|
189
|
+
height: number;
|
|
190
|
+
}
|
|
191
|
+
/** Where a label is drawn after `separateEdgeLabels`, or that it is left out. */
|
|
192
|
+
interface PlacedEdgeLabel {
|
|
193
|
+
x: number;
|
|
194
|
+
y: number;
|
|
195
|
+
hidden: boolean;
|
|
196
|
+
}
|
|
197
|
+
/** The box a wrapped edge label takes, from its lines (the meta type size, as `wrapEdgeLabel` assumes). */
|
|
198
|
+
declare function edgeLabelSize(lines: readonly string[]): {
|
|
199
|
+
width: number;
|
|
200
|
+
height: number;
|
|
201
|
+
};
|
|
202
|
+
/**
|
|
203
|
+
* Moves edge labels apart where they would be drawn over each other (HAR-1639: two labels on top
|
|
204
|
+
* of each other in a dense layered column). Labels are taken top to bottom; one that overlaps a
|
|
205
|
+
* label already placed moves down just below it. A label that would have to move further than
|
|
206
|
+
* `maxShift` from its edge is left out instead (the relationship is still in the nodes'
|
|
207
|
+
* descriptions and in the list). Deterministic: the same boxes give the same placement.
|
|
208
|
+
*/
|
|
209
|
+
declare function separateEdgeLabels(boxes: readonly EdgeLabelBox[], options?: {
|
|
210
|
+
gap?: number;
|
|
211
|
+
maxShift?: number;
|
|
212
|
+
}): Map<string, PlacedEdgeLabel>;
|
|
138
213
|
type LayeredNavigationKey = 'ArrowUp' | 'ArrowDown' | 'ArrowLeft' | 'ArrowRight' | 'Home' | 'End';
|
|
139
214
|
/** Keyboard traversal over a layered layout: ←/→ along forward edges, ↑/↓ within a column. */
|
|
140
215
|
declare function layeredNeighbor(layout: LayeredLayout, currentId: string | undefined, key: LayeredNavigationKey): string | undefined;
|
|
141
216
|
|
|
142
|
-
export { type BoundedRelationshipGraph, type LayeredColumn, type LayeredEdgeClassification, type LayeredEdgeKind, type LayeredItem, type LayeredLayout, type LayeredLayoutOptions, type LayeredNavigationKey, type PositionedRelationshipNode, type RelationshipGraphArrow, type RelationshipGraphCluster, type RelationshipGraphEdge, type RelationshipGraphNode, type RoutedEdge, boundRelationshipGraph, classifyLayeredEdges, clusterIdFor, layeredNeighbor, layoutLayeredGraph, layoutRelationshipGraph, relationshipNeighbors, traverseRelationshipNode, wrapEdgeLabel };
|
|
217
|
+
export { type BoundedRelationshipGraph, type EdgeLabelBox, type LayeredColumn, type LayeredEdgeClassification, type LayeredEdgeKind, type LayeredItem, type LayeredLayout, type LayeredLayoutOptions, type LayeredNavigationKey, type PlacedEdgeLabel, type PositionedRelationshipNode, type RelationshipGraphArrow, type RelationshipGraphCluster, type RelationshipGraphEdge, type RelationshipGraphNode, type RelationshipGraphTone, type RoutedEdge, boundRelationshipGraph, classifyLayeredEdges, clusterIdFor, edgeLabelSize, layeredNeighbor, layoutLayeredGraph, layoutRelationshipGraph, relationshipNeighbors, separateEdgeLabels, traverseRelationshipNode, wrapEdgeLabel };
|
|
@@ -142,6 +142,8 @@ function classifyLayeredEdges(nodes, edges, rootId = nodes[0]?.id) {
|
|
|
142
142
|
const list = forwardOut.get(edge.source);
|
|
143
143
|
if (list) list.push(edge.target);
|
|
144
144
|
else forwardOut.set(edge.source, [edge.target]);
|
|
145
|
+
} else if (to > from + 1) {
|
|
146
|
+
kindById.set(edge.id, "skip");
|
|
145
147
|
} else if (to < from) {
|
|
146
148
|
backEdges.push(edge);
|
|
147
149
|
} else {
|
|
@@ -166,13 +168,20 @@ function classifyLayeredEdges(nodes, edges, rootId = nodes[0]?.id) {
|
|
|
166
168
|
}
|
|
167
169
|
}
|
|
168
170
|
}
|
|
169
|
-
kindById.set(edge.id, closes ? "cycle" : "
|
|
171
|
+
kindById.set(edge.id, closes ? "cycle" : "back");
|
|
170
172
|
}
|
|
171
173
|
return { depthById, kindById };
|
|
172
174
|
}
|
|
173
175
|
function clusterIdFor(parentId, type, edgeType) {
|
|
174
176
|
return `cluster:${parentId}:${type ?? ""}:${edgeType ?? ""}`;
|
|
175
177
|
}
|
|
178
|
+
function busPath(startX, startY, trunk, endX, endY) {
|
|
179
|
+
const dy = endY - startY;
|
|
180
|
+
if (Math.abs(dy) < 1) return `M${round1(startX)} ${round1(startY)} H${round1(endX)}`;
|
|
181
|
+
const r = Math.min(8, Math.abs(dy) / 2, trunk - startX, endX - trunk);
|
|
182
|
+
const dir = Math.sign(dy);
|
|
183
|
+
return `M${round1(startX)} ${round1(startY)} H${round1(trunk - r)} Q${round1(trunk)} ${round1(startY)} ${round1(trunk)} ${round1(startY + dir * r)} V${round1(endY - dir * r)} Q${round1(trunk)} ${round1(endY)} ${round1(trunk + r)} ${round1(endY)} H${round1(endX)}`;
|
|
184
|
+
}
|
|
176
185
|
const mean = (values) => values.reduce((sum, value) => sum + value, 0) / values.length;
|
|
177
186
|
const round1 = (value) => Math.round(value * 10) / 10;
|
|
178
187
|
function layoutLayeredGraph(nodes, edges, options = {}) {
|
|
@@ -200,6 +209,7 @@ function layoutLayeredGraph(nodes, edges, options = {}) {
|
|
|
200
209
|
const forwardParents = /* @__PURE__ */ new Map();
|
|
201
210
|
const forwardChildCount = /* @__PURE__ */ new Map();
|
|
202
211
|
const inCycle = /* @__PURE__ */ new Set();
|
|
212
|
+
const crossLinked = /* @__PURE__ */ new Set();
|
|
203
213
|
const nodeDegree = /* @__PURE__ */ new Map();
|
|
204
214
|
for (const edge of drawable) {
|
|
205
215
|
nodeDegree.set(edge.source, (nodeDegree.get(edge.source) ?? 0) + 1);
|
|
@@ -210,14 +220,18 @@ function layoutLayeredGraph(nodes, edges, options = {}) {
|
|
|
210
220
|
else forwardParents.set(edge.target, [edge]);
|
|
211
221
|
forwardChildCount.set(edge.source, (forwardChildCount.get(edge.source) ?? 0) + 1);
|
|
212
222
|
} else {
|
|
213
|
-
|
|
214
|
-
|
|
223
|
+
crossLinked.add(edge.source);
|
|
224
|
+
crossLinked.add(edge.target);
|
|
225
|
+
if (kindById.get(edge.id) === "cycle") {
|
|
226
|
+
inCycle.add(edge.source);
|
|
227
|
+
inCycle.add(edge.target);
|
|
228
|
+
}
|
|
215
229
|
}
|
|
216
230
|
}
|
|
217
231
|
const groups = /* @__PURE__ */ new Map();
|
|
218
232
|
if (threshold > 0) {
|
|
219
233
|
for (const node of nodes) {
|
|
220
|
-
if (node.id === rootId ||
|
|
234
|
+
if (node.id === rootId || crossLinked.has(node.id) || (forwardChildCount.get(node.id) ?? 0) > 0) continue;
|
|
221
235
|
const parents = forwardParents.get(node.id) ?? [];
|
|
222
236
|
if (parents.length !== 1) continue;
|
|
223
237
|
const via = parents[0];
|
|
@@ -369,7 +383,33 @@ function layoutLayeredGraph(nodes, edges, options = {}) {
|
|
|
369
383
|
let labelY;
|
|
370
384
|
let startAngle;
|
|
371
385
|
let endAngle;
|
|
372
|
-
if (kind === "
|
|
386
|
+
if (kind === "skip") {
|
|
387
|
+
startX = from.x + from.width;
|
|
388
|
+
startY = from.y + from.height / 2;
|
|
389
|
+
endX = to.x;
|
|
390
|
+
endY = to.y + to.height / 2;
|
|
391
|
+
let floor = Math.max(startY, endY);
|
|
392
|
+
for (const item of itemById.values()) if (item.depth > from.depth && item.depth < to.depth) floor = Math.max(floor, item.y + item.height);
|
|
393
|
+
const channel = floor + 18;
|
|
394
|
+
const half = columnGap / 2;
|
|
395
|
+
path = `M${round1(startX)} ${round1(startY)} C${round1(startX + half)} ${round1(startY)} ${round1(startX + half)} ${round1(channel)} ${round1(startX + half)} ${round1(channel)} L${round1(endX - half)} ${round1(channel)} C${round1(endX - half)} ${round1(channel)} ${round1(endX - half)} ${round1(endY)} ${round1(endX)} ${round1(endY)}`;
|
|
396
|
+
labelX = (startX + endX) / 2;
|
|
397
|
+
labelY = channel;
|
|
398
|
+
startAngle = Math.PI;
|
|
399
|
+
endAngle = 0;
|
|
400
|
+
height = Math.max(height, channel + 8);
|
|
401
|
+
} else if (kind === "forward" && from.children.length > AUTO_LABEL_MAX_FANOUT) {
|
|
402
|
+
startX = from.x + from.width;
|
|
403
|
+
startY = from.y + from.height / 2;
|
|
404
|
+
endX = to.x;
|
|
405
|
+
endY = to.y + to.height / 2;
|
|
406
|
+
const trunk = startX + columnGap / 2;
|
|
407
|
+
path = busPath(startX, startY, trunk, endX, endY);
|
|
408
|
+
labelX = (trunk + endX) / 2;
|
|
409
|
+
labelY = endY;
|
|
410
|
+
startAngle = Math.PI;
|
|
411
|
+
endAngle = 0;
|
|
412
|
+
} else if (kind === "forward") {
|
|
373
413
|
startX = from.x + from.width;
|
|
374
414
|
startY = from.y + from.height / 2;
|
|
375
415
|
endX = to.x;
|
|
@@ -415,6 +455,7 @@ function layoutLayeredGraph(nodes, edges, options = {}) {
|
|
|
415
455
|
edgeIds: [edge.id],
|
|
416
456
|
arrow,
|
|
417
457
|
emphasis: edge.emphasis === true,
|
|
458
|
+
variant: edge.variant === "dashed" ? "dashed" : "solid",
|
|
418
459
|
path,
|
|
419
460
|
labelX: round1(labelX),
|
|
420
461
|
labelY: round1(labelY),
|
|
@@ -422,13 +463,48 @@ function layoutLayeredGraph(nodes, edges, options = {}) {
|
|
|
422
463
|
arrowY: round1(atStart ? startY : endY),
|
|
423
464
|
arrowAngle: atStart ? startAngle : endAngle,
|
|
424
465
|
labelLines: [],
|
|
466
|
+
columnLabel: false,
|
|
467
|
+
bus: kind === "forward" && from.children.length > AUTO_LABEL_MAX_FANOUT,
|
|
425
468
|
autoLabel: to.kind !== "cluster" && (edge.emphasis === true || kind === "forward" && from.children.length <= AUTO_LABEL_MAX_FANOUT)
|
|
426
469
|
};
|
|
427
470
|
if (edge.type !== void 0) entry.type = edge.type;
|
|
471
|
+
if (edge.tone !== void 0) entry.tone = edge.tone;
|
|
472
|
+
if (edge.description !== void 0) entry.description = edge.description;
|
|
428
473
|
const label = edge.label ?? edge.type;
|
|
429
474
|
if (label !== void 0) entry.label = label;
|
|
430
475
|
routed.set(key, entry);
|
|
431
476
|
}
|
|
477
|
+
const intoColumn = /* @__PURE__ */ new Map();
|
|
478
|
+
for (const entry of routed.values()) {
|
|
479
|
+
if (entry.kind !== "forward" || entry.label === void 0) continue;
|
|
480
|
+
const depth = itemById.get(entry.target).depth;
|
|
481
|
+
const list = intoColumn.get(depth);
|
|
482
|
+
if (list) list.push(entry);
|
|
483
|
+
else intoColumn.set(depth, [entry]);
|
|
484
|
+
}
|
|
485
|
+
for (const [depth, entries] of intoColumn) {
|
|
486
|
+
if (entries.length <= AUTO_LABEL_MAX_FANOUT) continue;
|
|
487
|
+
const counts = /* @__PURE__ */ new Map();
|
|
488
|
+
for (const entry of entries) counts.set(entry.label, (counts.get(entry.label) ?? 0) + 1);
|
|
489
|
+
let dominant;
|
|
490
|
+
let most = 1;
|
|
491
|
+
for (const [label, count] of counts) if (count > most) {
|
|
492
|
+
dominant = label;
|
|
493
|
+
most = count;
|
|
494
|
+
}
|
|
495
|
+
if (dominant === void 0) continue;
|
|
496
|
+
const column = columns.find((candidate) => candidate.depth === depth);
|
|
497
|
+
if (column) column.edgeLabel = dominant;
|
|
498
|
+
for (const entry of entries) {
|
|
499
|
+
if (entry.emphasis) continue;
|
|
500
|
+
if (entry.label === dominant) {
|
|
501
|
+
entry.columnLabel = true;
|
|
502
|
+
entry.autoLabel = false;
|
|
503
|
+
} else if (itemById.get(entry.target).kind !== "cluster") {
|
|
504
|
+
entry.autoLabel = true;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
}
|
|
432
508
|
const seenLabels = /* @__PURE__ */ new Set();
|
|
433
509
|
for (const entry of routed.values()) {
|
|
434
510
|
if (entry.label === void 0) continue;
|
|
@@ -452,6 +528,35 @@ function layoutLayeredGraph(nodes, edges, options = {}) {
|
|
|
452
528
|
headerHeight: LAYERED_HEADER
|
|
453
529
|
};
|
|
454
530
|
}
|
|
531
|
+
function edgeLabelSize(lines) {
|
|
532
|
+
const longest = lines.reduce((max, line) => Math.max(max, line.length), 0);
|
|
533
|
+
return { width: longest * LABEL_CHAR_WIDTH + 8, height: Math.max(1, lines.length) * 13 + 2 };
|
|
534
|
+
}
|
|
535
|
+
function separateEdgeLabels(boxes, options = {}) {
|
|
536
|
+
const gap = options.gap ?? 2;
|
|
537
|
+
const maxShift = options.maxShift ?? 40;
|
|
538
|
+
const placed = [];
|
|
539
|
+
const result = /* @__PURE__ */ new Map();
|
|
540
|
+
const ordered = [...boxes].sort((a, b) => a.y - b.y || a.x - b.x || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
|
|
541
|
+
for (const box of ordered) {
|
|
542
|
+
const left = box.x - box.width / 2;
|
|
543
|
+
const right = box.x + box.width / 2;
|
|
544
|
+
let top = box.y - box.height / 2;
|
|
545
|
+
for (let guard = 0; guard <= placed.length; guard += 1) {
|
|
546
|
+
const hit = placed.find((other) => left < other.right && other.left < right && top < other.bottom + gap && other.top - gap < top + box.height);
|
|
547
|
+
if (!hit) break;
|
|
548
|
+
top = hit.bottom + gap;
|
|
549
|
+
}
|
|
550
|
+
const shift = top - (box.y - box.height / 2);
|
|
551
|
+
if (shift > maxShift) {
|
|
552
|
+
result.set(box.id, { x: box.x, y: box.y, hidden: true });
|
|
553
|
+
continue;
|
|
554
|
+
}
|
|
555
|
+
placed.push({ left, right, top, bottom: top + box.height });
|
|
556
|
+
result.set(box.id, { x: box.x, y: round1(top + box.height / 2), hidden: false });
|
|
557
|
+
}
|
|
558
|
+
return result;
|
|
559
|
+
}
|
|
455
560
|
function layeredNeighbor(layout, currentId, key) {
|
|
456
561
|
const root = layout.rootId !== void 0 ? layout.itemOf[layout.rootId] : layout.items[0]?.id;
|
|
457
562
|
const current = layout.items.find((item) => item.id === currentId);
|
|
@@ -478,10 +583,12 @@ export {
|
|
|
478
583
|
boundRelationshipGraph,
|
|
479
584
|
classifyLayeredEdges,
|
|
480
585
|
clusterIdFor,
|
|
586
|
+
edgeLabelSize,
|
|
481
587
|
layeredNeighbor,
|
|
482
588
|
layoutLayeredGraph,
|
|
483
589
|
layoutRelationshipGraph,
|
|
484
590
|
relationshipNeighbors,
|
|
591
|
+
separateEdgeLabels,
|
|
485
592
|
traverseRelationshipNode,
|
|
486
593
|
wrapEdgeLabel
|
|
487
594
|
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { PointerEvent } from 'react';
|
|
2
|
+
|
|
3
|
+
/** Move `id` to `index` within `ids`. Returns `ids` itself when nothing moves. */
|
|
4
|
+
declare function placeId(ids: readonly string[], id: string, index: number): readonly string[];
|
|
5
|
+
/** True when two orders hold the same ids in the same order. */
|
|
6
|
+
declare const sameOrder: (a: readonly string[], b: readonly string[]) => boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Where a dragged row lands: how many of the OTHER rows have their middle above the pointer.
|
|
9
|
+
* The rows reorder live while dragging, so counting the dragged row itself would push it one
|
|
10
|
+
* slot past the pointer every time it moves down.
|
|
11
|
+
*/
|
|
12
|
+
declare function dropIndex(rows: readonly Element[], dragged: Element | null, clientY: number): number;
|
|
13
|
+
interface RowDragHandlers {
|
|
14
|
+
over: (id: string, index: number) => void;
|
|
15
|
+
drop: (id: string) => void;
|
|
16
|
+
/** The drag was cancelled (Escape, or the browser took the pointer): put the starting order back. */
|
|
17
|
+
cancel?: (id: string) => void;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Pointer drag for a list whose rows reorder live. It listens on the window for the whole drag:
|
|
21
|
+
* React moves the dragged row's DOM node when the order changes, which releases pointer capture on
|
|
22
|
+
* its grip, so after the first move down the grip itself stops receiving move and up events.
|
|
23
|
+
* Nothing animates: the row is placed where the pointer is, frame by frame.
|
|
24
|
+
*/
|
|
25
|
+
declare function useRowDrag(rowSelector: string, handlers: RowDragHandlers): {
|
|
26
|
+
dragging: string | null;
|
|
27
|
+
start: (event: PointerEvent<HTMLElement>, id: string) => void;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export { type RowDragHandlers, dropIndex, placeId, sameOrder, useRowDrag };
|
package/dist/reorder.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useEffect, useRef, useState } from "react";
|
|
3
|
+
function placeId(ids, id, index) {
|
|
4
|
+
const from = ids.indexOf(id);
|
|
5
|
+
const to = Math.max(0, Math.min(index, ids.length - 1));
|
|
6
|
+
if (from < 0 || from === to) return ids;
|
|
7
|
+
const next = ids.filter((other) => other !== id);
|
|
8
|
+
next.splice(to, 0, id);
|
|
9
|
+
return next;
|
|
10
|
+
}
|
|
11
|
+
const sameOrder = (a, b) => a.length === b.length && a.every((id, i) => id === b[i]);
|
|
12
|
+
function dropIndex(rows, dragged, clientY) {
|
|
13
|
+
let index = 0;
|
|
14
|
+
for (const row of rows) {
|
|
15
|
+
if (row === dragged) continue;
|
|
16
|
+
const box = row.getBoundingClientRect();
|
|
17
|
+
if (clientY > box.top + box.height / 2) index++;
|
|
18
|
+
}
|
|
19
|
+
return index;
|
|
20
|
+
}
|
|
21
|
+
function useRowDrag(rowSelector, handlers) {
|
|
22
|
+
const [dragging, setDragging] = useState(null);
|
|
23
|
+
const drag = useRef(null);
|
|
24
|
+
const latest = useRef(handlers);
|
|
25
|
+
latest.current = handlers;
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
if (!dragging) return;
|
|
28
|
+
const move = (event) => {
|
|
29
|
+
const current = drag.current;
|
|
30
|
+
if (!current) return;
|
|
31
|
+
latest.current.over(current.id, dropIndex(Array.from(current.list.querySelectorAll(`:scope > ${rowSelector}`)), current.row, event.clientY));
|
|
32
|
+
};
|
|
33
|
+
const finish = (kind) => {
|
|
34
|
+
const current = drag.current;
|
|
35
|
+
drag.current = null;
|
|
36
|
+
setDragging(null);
|
|
37
|
+
if (!current) return;
|
|
38
|
+
if (kind === "drop") latest.current.drop(current.id);
|
|
39
|
+
else latest.current.cancel?.(current.id);
|
|
40
|
+
};
|
|
41
|
+
const end = () => finish("drop");
|
|
42
|
+
const cancel = () => finish("cancel");
|
|
43
|
+
const escape = (event) => {
|
|
44
|
+
if (event.key !== "Escape") return;
|
|
45
|
+
event.preventDefault();
|
|
46
|
+
event.stopPropagation();
|
|
47
|
+
finish("cancel");
|
|
48
|
+
};
|
|
49
|
+
window.addEventListener("pointermove", move);
|
|
50
|
+
window.addEventListener("pointerup", end);
|
|
51
|
+
window.addEventListener("pointercancel", cancel);
|
|
52
|
+
window.addEventListener("keydown", escape, true);
|
|
53
|
+
return () => {
|
|
54
|
+
window.removeEventListener("pointermove", move);
|
|
55
|
+
window.removeEventListener("pointerup", end);
|
|
56
|
+
window.removeEventListener("pointercancel", cancel);
|
|
57
|
+
window.removeEventListener("keydown", escape, true);
|
|
58
|
+
};
|
|
59
|
+
}, [dragging, rowSelector]);
|
|
60
|
+
const start = (event, id) => {
|
|
61
|
+
const row = event.currentTarget.closest("li");
|
|
62
|
+
if (!row?.parentElement) return;
|
|
63
|
+
event.currentTarget.setPointerCapture?.(event.pointerId);
|
|
64
|
+
drag.current = { id, list: row.parentElement, row };
|
|
65
|
+
setDragging(id);
|
|
66
|
+
};
|
|
67
|
+
return { dragging, start };
|
|
68
|
+
}
|
|
69
|
+
export {
|
|
70
|
+
dropIndex,
|
|
71
|
+
placeId,
|
|
72
|
+
sameOrder,
|
|
73
|
+
useRowDrag
|
|
74
|
+
};
|
package/dist/rich-text.cjs
CHANGED
|
@@ -1700,6 +1700,8 @@ function Popover({
|
|
|
1700
1700
|
};
|
|
1701
1701
|
const onKeyDown = (event) => {
|
|
1702
1702
|
if (event.key !== "Escape" || !isPopoverOpen(el)) return;
|
|
1703
|
+
event.preventDefault();
|
|
1704
|
+
event.stopPropagation();
|
|
1703
1705
|
window.clearTimeout(timer);
|
|
1704
1706
|
const hadFocus = el.contains(el.ownerDocument.activeElement);
|
|
1705
1707
|
try {
|
|
@@ -2170,11 +2172,11 @@ function Markdown({
|
|
|
2170
2172
|
var import_react6 = require("react");
|
|
2171
2173
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
2172
2174
|
var Textarea = (0, import_react6.forwardRef)(
|
|
2173
|
-
({ invalid, className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2175
|
+
({ invalid, size = "md", className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2174
2176
|
"textarea",
|
|
2175
2177
|
{
|
|
2176
2178
|
ref,
|
|
2177
|
-
className: cx("uix-textarea", className),
|
|
2179
|
+
className: cx("uix-textarea", size === "lg" && "uix-textarea--lg", className),
|
|
2178
2180
|
"aria-invalid": invalid || void 0,
|
|
2179
2181
|
...props
|
|
2180
2182
|
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/** What a span of a resource's day is: open to book, booked, or not working. */
|
|
2
|
+
type SchedulingAvailabilityKind = 'free' | 'booked' | 'off';
|
|
3
|
+
/** One column of the resource day, e.g. a practitioner. */
|
|
4
|
+
interface SchedulingResource {
|
|
5
|
+
id: string;
|
|
6
|
+
/** The column heading and the start of every slot's accessible name. */
|
|
7
|
+
label: string;
|
|
8
|
+
/** A second line under the heading, e.g. the speciality or the room. */
|
|
9
|
+
description?: string;
|
|
10
|
+
}
|
|
11
|
+
/** A stretch of one resource's day, as the server composed it. */
|
|
12
|
+
interface SchedulingResourceSpan {
|
|
13
|
+
id: string;
|
|
14
|
+
resourceId: string;
|
|
15
|
+
/** ISO 8601 instants, half-open `[start, end)`. */
|
|
16
|
+
start: string;
|
|
17
|
+
end: string;
|
|
18
|
+
kind: SchedulingAvailabilityKind;
|
|
19
|
+
/** Shown on the span, e.g. the patient's name on a booking or "Lunch" on time off. */
|
|
20
|
+
label?: string;
|
|
21
|
+
/** The complete accessible name, in the consumer's words. Replaces the built one. */
|
|
22
|
+
accessibleName?: string;
|
|
23
|
+
}
|
|
24
|
+
/** One row of the slot axis. */
|
|
25
|
+
interface ResourceDaySlot {
|
|
26
|
+
/** Epoch milliseconds of the slot's start and end. */
|
|
27
|
+
start: number;
|
|
28
|
+
end: number;
|
|
29
|
+
/** The local time it starts, `HH:MM`, in the display zone. */
|
|
30
|
+
label: string;
|
|
31
|
+
}
|
|
32
|
+
interface ResourceDaySlotOptions {
|
|
33
|
+
/** The first local time shown, `HH:MM`. Default `'07:00'`. */
|
|
34
|
+
dayStart?: string;
|
|
35
|
+
/** The local time the axis ends, `HH:MM` (exclusive). Default `'19:00'`. */
|
|
36
|
+
dayEnd?: string;
|
|
37
|
+
/** Minutes per slot. Default 15. */
|
|
38
|
+
slotMinutes?: number;
|
|
39
|
+
}
|
|
40
|
+
/** One drawn piece of a column: a bookable slot of a free span, a booking, or time off. */
|
|
41
|
+
interface ResourceDayItem {
|
|
42
|
+
key: string;
|
|
43
|
+
span: SchedulingResourceSpan;
|
|
44
|
+
kind: SchedulingAvailabilityKind;
|
|
45
|
+
/** Epoch milliseconds of what this piece covers (a free span is cut at slot edges). */
|
|
46
|
+
start: number;
|
|
47
|
+
end: number;
|
|
48
|
+
/** Slots from the top of the axis to the piece's start (fractional). */
|
|
49
|
+
offset: number;
|
|
50
|
+
/** Slots the piece is long (fractional). */
|
|
51
|
+
length: number;
|
|
52
|
+
lane: number;
|
|
53
|
+
lanes: number;
|
|
54
|
+
/** The span starts before or ends after the axis. */
|
|
55
|
+
continuesBefore: boolean;
|
|
56
|
+
continuesAfter: boolean;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The slot axis of `date` in `timeZone`: one slot per `slotMinutes` of real time from the first
|
|
60
|
+
* local time at or after `dayStart` to the last before `dayEnd`. On a clock-change day the axis
|
|
61
|
+
* is as long as the day really is (a skipped hour has no slots; a repeated hour has two sets).
|
|
62
|
+
*/
|
|
63
|
+
declare function resourceDaySlots(date: string, timeZone: string, options?: ResourceDaySlotOptions): ResourceDaySlot[];
|
|
64
|
+
/**
|
|
65
|
+
* Where the spans of one resource go on the slot axis. Free spans are cut at slot edges, so each
|
|
66
|
+
* bookable slot is its own piece; bookings and time off stay whole. Pieces outside the axis are
|
|
67
|
+
* dropped, pieces across its edges are clipped. Overlapping pieces (a double booking) get lanes.
|
|
68
|
+
*/
|
|
69
|
+
declare function layoutResourceColumn(spans: readonly SchedulingResourceSpan[], slots: readonly ResourceDaySlot[]): ResourceDayItem[];
|
|
70
|
+
/** The stretches of the axis no span covers: shown as "no schedule", never as free. */
|
|
71
|
+
declare function resourceDayGaps(items: readonly ResourceDayItem[], slots: readonly ResourceDaySlot[]): Array<{
|
|
72
|
+
start: number;
|
|
73
|
+
end: number;
|
|
74
|
+
}>;
|
|
75
|
+
|
|
76
|
+
export { type ResourceDayItem, type ResourceDaySlot, type ResourceDaySlotOptions, type SchedulingAvailabilityKind, type SchedulingResource, type SchedulingResourceSpan, layoutResourceColumn, resourceDayGaps, resourceDaySlots };
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { packLanes, zonedDayBounds, zonedTimeOfDay } from "./calendar-model.js";
|
|
2
|
+
const MINUTE = 6e4;
|
|
3
|
+
const TIME = /^([01]\d|2[0-3]):[0-5]\d$/;
|
|
4
|
+
function resourceDaySlots(date, timeZone, options = {}) {
|
|
5
|
+
const dayStart = options.dayStart && TIME.test(options.dayStart) ? options.dayStart : "07:00";
|
|
6
|
+
const dayEnd = options.dayEnd && TIME.test(options.dayEnd) ? options.dayEnd : "19:00";
|
|
7
|
+
const minutes = Number.isFinite(options.slotMinutes) && options.slotMinutes >= 5 ? Math.floor(options.slotMinutes) : 15;
|
|
8
|
+
const step = minutes * MINUTE;
|
|
9
|
+
const bounds = zonedDayBounds(date, timeZone);
|
|
10
|
+
const all = [];
|
|
11
|
+
for (let at = bounds.start.getTime(); at < bounds.end.getTime(); at += step) {
|
|
12
|
+
all.push({ start: at, end: Math.min(at + step, bounds.end.getTime()), label: zonedTimeOfDay(at, timeZone) });
|
|
13
|
+
}
|
|
14
|
+
const first = all.findIndex((slot) => slot.label >= dayStart);
|
|
15
|
+
let last = -1;
|
|
16
|
+
all.forEach((slot, index) => {
|
|
17
|
+
if (slot.label < dayEnd) last = index;
|
|
18
|
+
});
|
|
19
|
+
if (first === -1 || last < first) return [];
|
|
20
|
+
return all.slice(first, last + 1);
|
|
21
|
+
}
|
|
22
|
+
function layoutResourceColumn(spans, slots) {
|
|
23
|
+
if (slots.length === 0) return [];
|
|
24
|
+
const axisStart = slots[0].start;
|
|
25
|
+
const axisEnd = slots[slots.length - 1].end;
|
|
26
|
+
const slotMs = slots[0].end - slots[0].start;
|
|
27
|
+
const pieces = [];
|
|
28
|
+
const seen = /* @__PURE__ */ new Set();
|
|
29
|
+
for (const span of spans) {
|
|
30
|
+
if (seen.has(span.id)) continue;
|
|
31
|
+
seen.add(span.id);
|
|
32
|
+
const start = new Date(span.start).getTime();
|
|
33
|
+
const end = new Date(span.end).getTime();
|
|
34
|
+
if (!(end > start) || end <= axisStart || start >= axisEnd) continue;
|
|
35
|
+
const from = Math.max(start, axisStart);
|
|
36
|
+
const to = Math.min(end, axisEnd);
|
|
37
|
+
const edges = { continuesBefore: start < axisStart, continuesAfter: end > axisEnd };
|
|
38
|
+
if (span.kind === "free") {
|
|
39
|
+
for (const slot of slots) {
|
|
40
|
+
const a = Math.max(from, slot.start);
|
|
41
|
+
const b = Math.min(to, slot.end);
|
|
42
|
+
if (b > a) pieces.push({ key: `${span.id}@${a}`, span, kind: "free", start: a, end: b, ...edges });
|
|
43
|
+
}
|
|
44
|
+
} else pieces.push({ key: span.id, span, kind: span.kind, start: from, end: to, ...edges });
|
|
45
|
+
}
|
|
46
|
+
const packed = packLanes(pieces.map((piece) => ({ id: piece.key, start: piece.start, end: piece.end })), Infinity);
|
|
47
|
+
return pieces.map((piece) => {
|
|
48
|
+
const placement = packed.lanes[piece.key];
|
|
49
|
+
return {
|
|
50
|
+
...piece,
|
|
51
|
+
offset: (piece.start - axisStart) / slotMs,
|
|
52
|
+
length: (piece.end - piece.start) / slotMs,
|
|
53
|
+
lane: placement.lane ?? 0,
|
|
54
|
+
lanes: packed.clusters[placement.cluster].laneCount || 1
|
|
55
|
+
};
|
|
56
|
+
}).sort((a, b) => a.start - b.start || a.lane - b.lane);
|
|
57
|
+
}
|
|
58
|
+
function resourceDayGaps(items, slots) {
|
|
59
|
+
if (slots.length === 0) return [];
|
|
60
|
+
const gaps = [];
|
|
61
|
+
let at = slots[0].start;
|
|
62
|
+
for (const item of [...items].sort((a, b) => a.start - b.start)) {
|
|
63
|
+
if (item.start > at) gaps.push({ start: at, end: item.start });
|
|
64
|
+
at = Math.max(at, item.end);
|
|
65
|
+
}
|
|
66
|
+
const axisEnd = slots[slots.length - 1].end;
|
|
67
|
+
if (at < axisEnd) gaps.push({ start: at, end: axisEnd });
|
|
68
|
+
return gaps;
|
|
69
|
+
}
|
|
70
|
+
export {
|
|
71
|
+
layoutResourceColumn,
|
|
72
|
+
resourceDayGaps,
|
|
73
|
+
resourceDaySlots
|
|
74
|
+
};
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
const COMBINING_MARK = /\p{M}/u;
|
|
2
|
+
const STROKED = { "\u0111": "d", "\xF8": "o", "\u0142": "l", "\u0131": "i", "\u0127": "h", "\u0167": "t" };
|
|
2
3
|
function foldForSearch(text) {
|
|
3
4
|
let folded = "";
|
|
4
5
|
const source = [];
|
|
5
6
|
const sourceEnd = [];
|
|
6
7
|
let index = 0;
|
|
7
8
|
for (const char of text) {
|
|
8
|
-
const
|
|
9
|
+
const lower = char.toLowerCase();
|
|
10
|
+
const base = char === "\xDF" || char === "\u1E9E" ? "ss" : STROKED[lower] ?? lower.normalize("NFD");
|
|
9
11
|
for (const part of base) {
|
|
10
12
|
if (COMBINING_MARK.test(part)) continue;
|
|
11
13
|
folded += part;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* True inside AppShell's phone navigation drawer (HAR-1371). The sidebar there is shown full,
|
|
5
|
+
* whatever tier a person chose on a wide screen: a Sidebar and an AccountMenu read this and drop
|
|
6
|
+
* their rail form. Internal: not exported from the package.
|
|
7
|
+
*/
|
|
8
|
+
declare const ShellDrawerContext: react.Context<boolean>;
|
|
9
|
+
declare const useInShellDrawer: () => boolean;
|
|
10
|
+
|
|
11
|
+
export { ShellDrawerContext, useInShellDrawer };
|