@tensor_1/react 2.31.0 → 2.32.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 +350 -0
- package/dist/attachment-labels.d.ts +16 -0
- package/dist/attachment-labels.js +9 -0
- package/dist/calendar-model.d.ts +141 -1
- package/dist/calendar-model.js +200 -11
- package/dist/chart-preset.cjs +127 -7
- package/dist/chart-preset.d.cts +2 -2
- package/dist/chart-preset.d.ts +1 -0
- package/dist/chart-preset.js +6 -1
- package/dist/chart-theme-Cl0IrkKQ.d.cts +112 -0
- package/dist/chart-theme.d.ts +51 -0
- package/dist/chart-theme.js +99 -0
- package/dist/chart.cjs +127 -7
- package/dist/chart.d.cts +2 -2
- package/dist/chart.d.ts +1 -0
- package/dist/chart.js +6 -2
- package/dist/components/Alert.d.ts +17 -1
- package/dist/components/Alert.js +9 -4
- package/dist/components/AlertDismiss.d.ts +14 -0
- package/dist/components/AlertDismiss.js +11 -0
- package/dist/components/Attachment.d.ts +15 -12
- package/dist/components/Attachment.js +17 -17
- package/dist/components/AttachmentParts.d.ts +24 -0
- package/dist/components/AttachmentParts.js +20 -0
- package/dist/components/Chart.d.ts +1 -0
- package/dist/components/Chart.js +6 -1
- package/dist/components/ChartCore.d.ts +6 -1
- package/dist/components/ChartCore.js +23 -5
- package/dist/components/Chip.d.ts +17 -2
- package/dist/components/Chip.js +35 -11
- package/dist/components/ChipRemove.d.ts +17 -0
- package/dist/components/ChipRemove.js +13 -0
- package/dist/components/CollapsibleParts.d.ts +29 -0
- package/dist/components/CollapsibleParts.js +20 -0
- package/dist/components/CollapsibleSection.d.ts +30 -3
- package/dist/components/CollapsibleSection.js +7 -11
- package/dist/components/CollapsibleSectionState.d.ts +1 -1
- package/dist/components/CollapsibleSectionState.js +54 -27
- package/dist/components/DashboardGrid.d.ts +60 -0
- package/dist/components/DashboardGrid.js +40 -0
- package/dist/components/DateRangePicker.d.ts +7 -1
- package/dist/components/DateRangePicker.js +5 -1
- package/dist/components/DescriptionList.d.ts +12 -1
- package/dist/components/DescriptionList.js +5 -5
- package/dist/components/Dialogs.d.ts +24 -3
- package/dist/components/Dialogs.js +74 -16
- package/dist/components/FileUpload.d.ts +10 -2
- package/dist/components/FileUpload.js +10 -4
- package/dist/components/FilterEditor.d.ts +4 -0
- package/dist/components/FilterEditor.js +13 -2
- package/dist/components/Heartbeat.d.ts +31 -0
- package/dist/components/Heartbeat.js +28 -0
- package/dist/components/Menu.d.ts +53 -5
- package/dist/components/Menu.js +104 -4
- package/dist/components/Meter.d.ts +7 -3
- package/dist/components/Meter.js +2 -1
- package/dist/components/Popover.d.ts +21 -2
- package/dist/components/Popover.js +94 -17
- package/dist/components/Prose.d.ts +6 -2
- package/dist/components/Prose.js +1 -1
- package/dist/components/RuleBuilder.d.ts +52 -4
- package/dist/components/RuleBuilder.js +109 -24
- package/dist/components/SchedulingCalendar.d.ts +142 -11
- package/dist/components/SchedulingCalendar.js +234 -57
- package/dist/components/SchedulingTimeline.d.ts +1 -0
- package/dist/components/Segmented.d.ts +17 -3
- package/dist/components/Segmented.js +59 -5
- package/dist/components/Select.d.ts +66 -2
- package/dist/components/Select.js +800 -10
- package/dist/components/Spinner.d.ts +2 -1
- package/dist/components/Spinner.js +1 -1
- package/dist/components/StatusPill.d.ts +8 -2
- package/dist/components/StatusPill.js +2 -2
- package/dist/components/Steps.d.ts +28 -4
- package/dist/components/Steps.js +46 -16
- package/dist/components/TableControls.js +4 -3
- package/dist/components/Tabs.d.ts +7 -2
- package/dist/components/Tabs.js +14 -1
- package/dist/components/TextDiff.d.ts +49 -0
- package/dist/components/TextDiff.js +124 -0
- package/dist/{emoji-image-6mPZ15Zy.d.cts → emoji-image-DjCKpdwE.d.cts} +1 -1
- package/dist/emoji.cjs +169 -27
- package/dist/emoji.d.cts +3 -3
- package/dist/file-model.d.ts +22 -3
- package/dist/file-model.js +6 -4
- package/dist/filter-model.d.ts +26 -2
- package/dist/filter-model.js +13 -1
- package/dist/hooks/useAnchoredPosition.d.ts +24 -1
- package/dist/hooks/useAnchoredPosition.js +58 -8
- package/dist/hooks/useVirtualRows.d.ts +17 -2
- package/dist/hooks/useVirtualRows.js +6 -5
- package/dist/icons/Icon.d.ts +14 -14
- package/dist/index.cjs +4179 -1678
- package/dist/index.d.cts +1706 -660
- package/dist/index.d.ts +16 -9
- package/dist/index.js +53 -4
- package/dist/labels-context.d.ts +28 -0
- package/dist/{overlay-position-Cjv5E7mn.d.cts → overlay-position-2Afke51l.d.cts} +20 -0
- package/dist/overlay-position.d.ts +20 -0
- package/dist/overlay-position.js +17 -2
- package/dist/rich-text.cjs +169 -27
- package/dist/rich-text.d.cts +3 -3
- package/dist/rule-builder-model.d.ts +34 -2
- package/dist/rule-builder-model.js +48 -12
- package/dist/scheduling-calendar-model.d.ts +66 -0
- package/dist/scheduling-calendar-model.js +82 -0
- package/dist/select-model.d.ts +80 -0
- package/dist/select-model.js +109 -0
- package/dist/table-engine.d.ts +7 -0
- package/dist/table-engine.js +2 -1
- package/dist/text-diff-model.d.ts +71 -0
- package/dist/text-diff-model.js +261 -0
- package/package.json +1 -1
- package/dist/ChartCore-DzWe10bN.d.cts +0 -59
package/dist/rich-text.cjs
CHANGED
|
@@ -79,7 +79,7 @@ function fitsOn(side, a, f, vp, offset, padding) {
|
|
|
79
79
|
return spaceOn(side, a, vp, offset) >= need + padding;
|
|
80
80
|
}
|
|
81
81
|
function computePosition(anchor, floating, viewport, options = {}) {
|
|
82
|
-
const { placement = "bottom-start", offset = 6, padding = 8, flip = true, shift = true, stickySide } = options;
|
|
82
|
+
const { placement = "bottom-start", offset = 6, padding = 8, flip = true, shift = true, shiftMainAxis = true, stickySide } = options;
|
|
83
83
|
const { side: preferred, align } = parsePlacement(placement);
|
|
84
84
|
let side = preferred;
|
|
85
85
|
const sticky = stickySide === preferred || stickySide === OPPOSITE[preferred] ? stickySide : void 0;
|
|
@@ -112,12 +112,27 @@ function computePosition(anchor, floating, viewport, options = {}) {
|
|
|
112
112
|
y = align === "start" ? start : align === "end" ? end : center;
|
|
113
113
|
if (shift) y = clamp(y, padding, Math.max(padding, viewport.height - floating.height - padding));
|
|
114
114
|
}
|
|
115
|
+
const mainAxisNatural = horizontal ? y : x;
|
|
116
|
+
const anchorInView = horizontal ? anchor.y + anchor.height > 0 && anchor.y < viewport.height : anchor.x + anchor.width > 0 && anchor.x < viewport.width;
|
|
117
|
+
let mainAxisRange = null;
|
|
118
|
+
if (shiftMainAxis && anchorInView) {
|
|
119
|
+
const extent = horizontal ? viewport.height - floating.height : viewport.width - floating.width;
|
|
120
|
+
mainAxisRange = [padding, Math.max(padding, extent - padding)];
|
|
121
|
+
if (horizontal) y = clamp(y, mainAxisRange[0], mainAxisRange[1]);
|
|
122
|
+
else x = clamp(x, mainAxisRange[0], mainAxisRange[1]);
|
|
123
|
+
}
|
|
115
124
|
return {
|
|
116
125
|
x,
|
|
117
126
|
y,
|
|
118
127
|
placement: align === "center" ? side : `${side}-${align}`,
|
|
119
128
|
side,
|
|
120
|
-
align
|
|
129
|
+
align,
|
|
130
|
+
mainAxisNatural,
|
|
131
|
+
mainAxisRange,
|
|
132
|
+
available: {
|
|
133
|
+
width: Math.max(0, viewport.width - 2 * padding),
|
|
134
|
+
height: Math.max(0, viewport.height - 2 * padding)
|
|
135
|
+
}
|
|
121
136
|
};
|
|
122
137
|
}
|
|
123
138
|
|
|
@@ -780,6 +795,7 @@ function supportsAnchoring() {
|
|
|
780
795
|
}
|
|
781
796
|
return anchoringSupported;
|
|
782
797
|
}
|
|
798
|
+
var ANCHOR_BAND = 64;
|
|
783
799
|
var anchorCount = 0;
|
|
784
800
|
var namesOf = (value) => value.split(",").map((n) => n.trim()).filter((n) => n.startsWith("--"));
|
|
785
801
|
function addAnchorName(el, name) {
|
|
@@ -804,9 +820,12 @@ function translationOf(el) {
|
|
|
804
820
|
}
|
|
805
821
|
var signed = (n) => `${n < 0 ? "-" : "+"} ${Math.round(Math.abs(n) * 100) / 100}px`;
|
|
806
822
|
var prepared = /* @__PURE__ */ new WeakSet();
|
|
807
|
-
function useAnchoredPosition(anchor, floatingRef, { open, placement = "bottom-start", offset = 6, padding = 8 }) {
|
|
808
|
-
const opts = (0, import_react3.useRef)({ placement, offset, padding });
|
|
809
|
-
opts.current = { placement, offset, padding };
|
|
823
|
+
function useAnchoredPosition(anchor, floatingRef, { open, placement = "bottom-start", offset = 6, padding = 8, shiftMainAxis = true, capHeight = false, onAnchorHidden }) {
|
|
824
|
+
const opts = (0, import_react3.useRef)({ placement, offset, padding, shiftMainAxis, capHeight });
|
|
825
|
+
opts.current = { placement, offset, padding, shiftMainAxis, capHeight };
|
|
826
|
+
const onAnchorHiddenRef = (0, import_react3.useRef)(onAnchorHidden);
|
|
827
|
+
onAnchorHiddenRef.current = onAnchorHidden;
|
|
828
|
+
const heightCap = (0, import_react3.useRef)(null);
|
|
810
829
|
const session = (0, import_react3.useRef)(false);
|
|
811
830
|
const side = (0, import_react3.useRef)(null);
|
|
812
831
|
const written = (0, import_react3.useRef)("");
|
|
@@ -830,6 +849,15 @@ function useAnchoredPosition(anchor, floatingRef, { open, placement = "bottom-st
|
|
|
830
849
|
}
|
|
831
850
|
removeAnchorName(current.anchor, current.name);
|
|
832
851
|
}, [floatingRef]);
|
|
852
|
+
const uncap = (0, import_react3.useCallback)(() => {
|
|
853
|
+
const cap = heightCap.current;
|
|
854
|
+
if (!cap) return;
|
|
855
|
+
heightCap.current = null;
|
|
856
|
+
const floating = floatingRef.current;
|
|
857
|
+
if (!floating) return;
|
|
858
|
+
floating.style.maxHeight = cap.inlineMaxHeight;
|
|
859
|
+
if (cap.setOverflow) floating.style.overflowY = cap.inlineOverflowY;
|
|
860
|
+
}, [floatingRef]);
|
|
833
861
|
const reposition = (0, import_react3.useCallback)(() => {
|
|
834
862
|
const anchorEl = resolveAnchor(anchor);
|
|
835
863
|
const floating = floatingRef.current;
|
|
@@ -842,14 +870,36 @@ function useAnchoredPosition(anchor, floatingRef, { open, placement = "bottom-st
|
|
|
842
870
|
prepared.add(floating);
|
|
843
871
|
written.current = "";
|
|
844
872
|
}
|
|
873
|
+
const { placement: p, offset: o, padding: pad, shiftMainAxis: keepInView, capHeight: cap } = opts.current;
|
|
874
|
+
if (cap) {
|
|
875
|
+
if (!heightCap.current) {
|
|
876
|
+
const own = getComputedStyle(floating);
|
|
877
|
+
const setOverflow = !own.overflowY || own.overflowY === "visible";
|
|
878
|
+
heightCap.current = {
|
|
879
|
+
inlineMaxHeight: s.maxHeight,
|
|
880
|
+
inlineOverflowY: s.overflowY,
|
|
881
|
+
ownMaxHeight: own.maxHeight && own.maxHeight !== "none" ? own.maxHeight : "",
|
|
882
|
+
setOverflow,
|
|
883
|
+
written: ""
|
|
884
|
+
};
|
|
885
|
+
if (setOverflow) s.overflowY = "auto";
|
|
886
|
+
}
|
|
887
|
+
const room = `${Math.max(0, window.innerHeight - 2 * pad)}px`;
|
|
888
|
+
const max = heightCap.current.ownMaxHeight ? `min(${room}, ${heightCap.current.ownMaxHeight})` : room;
|
|
889
|
+
if (max !== heightCap.current.written) {
|
|
890
|
+
s.maxHeight = max;
|
|
891
|
+
heightCap.current.written = max;
|
|
892
|
+
}
|
|
893
|
+
} else if (heightCap.current) {
|
|
894
|
+
uncap();
|
|
895
|
+
}
|
|
845
896
|
const a = anchorEl.getBoundingClientRect();
|
|
846
897
|
const size = { width: floating.offsetWidth, height: floating.offsetHeight };
|
|
847
|
-
const { placement: p, offset: o, padding: pad } = opts.current;
|
|
848
898
|
const pos = computePosition(
|
|
849
899
|
{ x: a.x, y: a.y, width: a.width, height: a.height },
|
|
850
900
|
size,
|
|
851
901
|
{ width: window.innerWidth, height: window.innerHeight },
|
|
852
|
-
{ placement: p, offset: o, padding: pad, stickySide: side.current ?? void 0 }
|
|
902
|
+
{ placement: p, offset: o, padding: pad, shiftMainAxis: keepInView, stickySide: side.current ?? void 0 }
|
|
853
903
|
);
|
|
854
904
|
const measured = size.width > 0 || size.height > 0;
|
|
855
905
|
if (measured && session.current) side.current = pos.side;
|
|
@@ -863,7 +913,10 @@ function useAnchoredPosition(anchor, floatingRef, { open, placement = "bottom-st
|
|
|
863
913
|
s.top = top2;
|
|
864
914
|
written.current = key2;
|
|
865
915
|
};
|
|
866
|
-
|
|
916
|
+
const limit = pos.mainAxisRange;
|
|
917
|
+
const nearLimit = limit !== null && (pos.mainAxisNatural < limit[0] + ANCHOR_BAND || pos.mainAxisNatural > limit[1] - ANCHOR_BAND);
|
|
918
|
+
if (anchoringFailed.current || nearLimit || !supportsAnchoring()) {
|
|
919
|
+
if (anchoring.current) release(false);
|
|
867
920
|
writeFixed(pos);
|
|
868
921
|
return;
|
|
869
922
|
}
|
|
@@ -900,7 +953,7 @@ function useAnchoredPosition(anchor, floatingRef, { open, placement = "bottom-st
|
|
|
900
953
|
writeFixed(pos);
|
|
901
954
|
}
|
|
902
955
|
}
|
|
903
|
-
}, [anchor, floatingRef, release]);
|
|
956
|
+
}, [anchor, floatingRef, release, uncap]);
|
|
904
957
|
useIsomorphicLayoutEffect(() => {
|
|
905
958
|
if (!open) return;
|
|
906
959
|
session.current = true;
|
|
@@ -929,8 +982,20 @@ function useAnchoredPosition(anchor, floatingRef, { open, placement = "bottom-st
|
|
|
929
982
|
side.current = null;
|
|
930
983
|
anchoringFailed.current = false;
|
|
931
984
|
release(true);
|
|
985
|
+
uncap();
|
|
932
986
|
};
|
|
933
|
-
}, [open, reposition, anchor, floatingRef, release]);
|
|
987
|
+
}, [open, reposition, anchor, floatingRef, release, uncap]);
|
|
988
|
+
const watchAnchor = open && !!onAnchorHidden;
|
|
989
|
+
(0, import_react3.useEffect)(() => {
|
|
990
|
+
const anchorEl = resolveAnchor(anchor);
|
|
991
|
+
if (!watchAnchor || !anchorEl || typeof IntersectionObserver !== "function") return;
|
|
992
|
+
const observer = new IntersectionObserver((entries) => {
|
|
993
|
+
const latest = entries[entries.length - 1];
|
|
994
|
+
if (latest && !latest.isIntersecting) onAnchorHiddenRef.current?.();
|
|
995
|
+
});
|
|
996
|
+
observer.observe(anchorEl);
|
|
997
|
+
return () => observer.disconnect();
|
|
998
|
+
}, [watchAnchor, anchor]);
|
|
934
999
|
(0, import_react3.useEffect)(() => () => release(false), [release]);
|
|
935
1000
|
return reposition;
|
|
936
1001
|
}
|
|
@@ -952,16 +1017,22 @@ var settle = (el) => {
|
|
|
952
1017
|
el.removeAttribute(PLACING);
|
|
953
1018
|
};
|
|
954
1019
|
function Popover({
|
|
955
|
-
popover
|
|
1020
|
+
popover: popoverProp,
|
|
956
1021
|
anchor,
|
|
957
1022
|
placement = "bottom-start",
|
|
958
1023
|
offset = 6,
|
|
959
1024
|
closeWhenAnchorHidden = false,
|
|
960
1025
|
onAnchorHidden,
|
|
1026
|
+
capHeight = false,
|
|
1027
|
+
openOnHover = false,
|
|
961
1028
|
className,
|
|
962
1029
|
children,
|
|
963
1030
|
...props
|
|
964
1031
|
}) {
|
|
1032
|
+
const hover = !!openOnHover && !!anchor;
|
|
1033
|
+
const popover = popoverProp ?? (hover ? "manual" : "auto");
|
|
1034
|
+
const openDelay = typeof openOnHover === "object" ? openOnHover.openDelay ?? 300 : 300;
|
|
1035
|
+
const closeDelay = typeof openOnHover === "object" ? openOnHover.closeDelay ?? 150 : 150;
|
|
965
1036
|
const ref = (0, import_react4.useRef)(null);
|
|
966
1037
|
const [open, setOpen] = (0, import_react4.useState)(false);
|
|
967
1038
|
const openRef = (0, import_react4.useRef)(false);
|
|
@@ -971,7 +1042,16 @@ function Popover({
|
|
|
971
1042
|
const reposition = useAnchoredPosition(anchor ?? null, ref, {
|
|
972
1043
|
open: open && !!anchor,
|
|
973
1044
|
placement,
|
|
974
|
-
offset
|
|
1045
|
+
offset,
|
|
1046
|
+
capHeight,
|
|
1047
|
+
onAnchorHidden: closeWhenAnchorHidden ? () => {
|
|
1048
|
+
const el = ref.current;
|
|
1049
|
+
if (!el || !isPopoverOpen(el)) return;
|
|
1050
|
+
onAnchorHiddenRef.current?.();
|
|
1051
|
+
const active = el.ownerDocument.activeElement;
|
|
1052
|
+
if (active && el.contains(active)) active.blur();
|
|
1053
|
+
el.hidePopover();
|
|
1054
|
+
} : void 0
|
|
975
1055
|
});
|
|
976
1056
|
(0, import_react4.useEffect)(() => {
|
|
977
1057
|
const el = ref.current;
|
|
@@ -1006,25 +1086,87 @@ function Popover({
|
|
|
1006
1086
|
el.removeAttribute(PLACING);
|
|
1007
1087
|
};
|
|
1008
1088
|
}, [anchor, reposition]);
|
|
1089
|
+
(0, import_react4.useEffect)(() => {
|
|
1090
|
+
const el = ref.current;
|
|
1091
|
+
const anchorEl = resolveAnchor(anchor);
|
|
1092
|
+
if (!hover || !el || !anchorEl) return;
|
|
1093
|
+
let timer;
|
|
1094
|
+
const inside = (node) => !!node && (anchorEl.contains(node) || el.contains(node));
|
|
1095
|
+
const stillWanted = () => {
|
|
1096
|
+
try {
|
|
1097
|
+
return anchorEl.matches(":hover") || el.matches(":hover") || inside(el.ownerDocument.activeElement);
|
|
1098
|
+
} catch {
|
|
1099
|
+
return false;
|
|
1100
|
+
}
|
|
1101
|
+
};
|
|
1102
|
+
const show = (delay) => {
|
|
1103
|
+
window.clearTimeout(timer);
|
|
1104
|
+
timer = window.setTimeout(() => {
|
|
1105
|
+
if (!isPopoverOpen(el)) {
|
|
1106
|
+
try {
|
|
1107
|
+
el.showPopover?.();
|
|
1108
|
+
} catch {
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
}, delay);
|
|
1112
|
+
};
|
|
1113
|
+
const hide = (delay) => {
|
|
1114
|
+
window.clearTimeout(timer);
|
|
1115
|
+
timer = window.setTimeout(() => {
|
|
1116
|
+
if (isPopoverOpen(el) && !stillWanted()) {
|
|
1117
|
+
try {
|
|
1118
|
+
el.hidePopover?.();
|
|
1119
|
+
} catch {
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
}, delay);
|
|
1123
|
+
};
|
|
1124
|
+
const onEnter = (event) => {
|
|
1125
|
+
if (event.pointerType !== "touch") show(openDelay);
|
|
1126
|
+
};
|
|
1127
|
+
const onLeave = (event) => {
|
|
1128
|
+
if (event.pointerType !== "touch") hide(closeDelay);
|
|
1129
|
+
};
|
|
1130
|
+
const onFocusIn = () => show(0);
|
|
1131
|
+
const onFocusOut = (event) => {
|
|
1132
|
+
if (!inside(event.relatedTarget)) hide(closeDelay);
|
|
1133
|
+
};
|
|
1134
|
+
const onKeyDown = (event) => {
|
|
1135
|
+
if (event.key !== "Escape" || !isPopoverOpen(el)) return;
|
|
1136
|
+
window.clearTimeout(timer);
|
|
1137
|
+
const hadFocus = el.contains(el.ownerDocument.activeElement);
|
|
1138
|
+
try {
|
|
1139
|
+
el.hidePopover?.();
|
|
1140
|
+
} catch {
|
|
1141
|
+
}
|
|
1142
|
+
if (hadFocus) {
|
|
1143
|
+
anchorEl.removeEventListener("focusin", onFocusIn);
|
|
1144
|
+
anchorEl.focus();
|
|
1145
|
+
anchorEl.addEventListener("focusin", onFocusIn);
|
|
1146
|
+
}
|
|
1147
|
+
};
|
|
1148
|
+
for (const node of [anchorEl, el]) {
|
|
1149
|
+
node.addEventListener("pointerenter", onEnter);
|
|
1150
|
+
node.addEventListener("pointerleave", onLeave);
|
|
1151
|
+
node.addEventListener("focusout", onFocusOut);
|
|
1152
|
+
node.addEventListener("keydown", onKeyDown);
|
|
1153
|
+
}
|
|
1154
|
+
anchorEl.addEventListener("focusin", onFocusIn);
|
|
1155
|
+
return () => {
|
|
1156
|
+
window.clearTimeout(timer);
|
|
1157
|
+
for (const node of [anchorEl, el]) {
|
|
1158
|
+
node.removeEventListener("pointerenter", onEnter);
|
|
1159
|
+
node.removeEventListener("pointerleave", onLeave);
|
|
1160
|
+
node.removeEventListener("focusout", onFocusOut);
|
|
1161
|
+
node.removeEventListener("keydown", onKeyDown);
|
|
1162
|
+
}
|
|
1163
|
+
anchorEl.removeEventListener("focusin", onFocusIn);
|
|
1164
|
+
};
|
|
1165
|
+
}, [hover, anchor, openDelay, closeDelay]);
|
|
1009
1166
|
useIsomorphicLayoutEffect2(() => {
|
|
1010
1167
|
openRef.current = open;
|
|
1011
1168
|
if (open && ref.current) settle(ref.current);
|
|
1012
1169
|
}, [open]);
|
|
1013
|
-
(0, import_react4.useEffect)(() => {
|
|
1014
|
-
const el = ref.current;
|
|
1015
|
-
const anchorEl = resolveAnchor(anchor);
|
|
1016
|
-
if (!closeWhenAnchorHidden || !open || !el || !anchorEl || typeof IntersectionObserver !== "function") return;
|
|
1017
|
-
const observer = new IntersectionObserver((entries) => {
|
|
1018
|
-
const latest = entries[entries.length - 1];
|
|
1019
|
-
if (!latest || latest.isIntersecting || !isPopoverOpen(el)) return;
|
|
1020
|
-
onAnchorHiddenRef.current?.();
|
|
1021
|
-
const active = el.ownerDocument.activeElement;
|
|
1022
|
-
if (active && el.contains(active)) active.blur();
|
|
1023
|
-
el.hidePopover();
|
|
1024
|
-
});
|
|
1025
|
-
observer.observe(anchorEl);
|
|
1026
|
-
return () => observer.disconnect();
|
|
1027
|
-
}, [closeWhenAnchorHidden, open, anchor]);
|
|
1028
1170
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { ref, className: cx("uix-popover", className), ...popoverAttr, ...props, children });
|
|
1029
1171
|
}
|
|
1030
1172
|
|
package/dist/rich-text.d.cts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
-
import { E as EmojiPickerLabels, a as EmojiLocale } from './emoji-image-
|
|
4
|
-
export { l as emojiImageFileName } from './emoji-image-
|
|
5
|
-
import './overlay-position-
|
|
3
|
+
import { E as EmojiPickerLabels, a as EmojiLocale } from './emoji-image-DjCKpdwE.cjs';
|
|
4
|
+
export { l as emojiImageFileName } from './emoji-image-DjCKpdwE.cjs';
|
|
5
|
+
import './overlay-position-2Afke51l.cjs';
|
|
6
6
|
|
|
7
7
|
type RichTextFeatures = 'full' | 'comment' | 'template';
|
|
8
8
|
type RichTextHeadingLevel = 1 | 2 | 3;
|
|
@@ -20,9 +20,24 @@ interface RuleDefinition {
|
|
|
20
20
|
when: RuleGroup;
|
|
21
21
|
then: RuleAction[];
|
|
22
22
|
}
|
|
23
|
+
/** The built-in checks of `validateRuleDefinition`; each can be reworded or turned off (HAR-1618). */
|
|
24
|
+
type RuleCheck = 'duplicateId' | 'maxDepth' | 'emptyGroup' | 'missingField' | 'missingOperator' | 'noActions' | 'missingActionType';
|
|
23
25
|
interface RuleValidationIssue {
|
|
24
26
|
path: string;
|
|
25
27
|
message: string;
|
|
28
|
+
/** Which built-in check raised it. Absent on issues from the consumer's own `validate`. */
|
|
29
|
+
check?: RuleCheck;
|
|
30
|
+
}
|
|
31
|
+
/** The built-in messages. `{id}` is the duplicated id, `{max}` the depth limit. */
|
|
32
|
+
declare const DEFAULT_RULE_VALIDATION_MESSAGES: Record<RuleCheck, string>;
|
|
33
|
+
interface RuleValidationOptions {
|
|
34
|
+
/** Replace individual messages (a translation). */
|
|
35
|
+
messages?: Partial<Record<RuleCheck, string>>;
|
|
36
|
+
/**
|
|
37
|
+
* `false` turns a check off: `{ emptyGroup: false }` for a rule that may have no condition
|
|
38
|
+
* (a catch-all), `{ noActions: false, missingActionType: false }` for conditions without actions.
|
|
39
|
+
*/
|
|
40
|
+
checks?: Partial<Record<RuleCheck, boolean>>;
|
|
26
41
|
}
|
|
27
42
|
declare function isRuleGroup(node: RuleCondition | RuleGroup): node is RuleGroup;
|
|
28
43
|
declare function ruleDepth(group: RuleGroup): number;
|
|
@@ -31,11 +46,28 @@ declare function mapRuleGroup(group: RuleGroup, id: string, update: (node: RuleC
|
|
|
31
46
|
declare function appendRuleNode(group: RuleGroup, parentId: string, node: RuleCondition | RuleGroup, maxDepth?: number): RuleGroup;
|
|
32
47
|
declare function removeRuleNode(group: RuleGroup, id: string): RuleGroup;
|
|
33
48
|
declare function moveRuleNode(group: RuleGroup, id: string, direction: -1 | 1): RuleGroup;
|
|
34
|
-
|
|
49
|
+
/** Set `combinator` on a group and on every group nested in it. */
|
|
50
|
+
declare function setRuleCombinator(group: RuleGroup, combinator: 'and' | 'or'): RuleGroup;
|
|
51
|
+
declare function validateRuleDefinition(value: RuleDefinition, maxDepth?: number, options?: RuleValidationOptions): RuleValidationIssue[];
|
|
52
|
+
/** The words of the `summarizeRule` sentence. `{conditions}` and `{actions}` are filled in. */
|
|
53
|
+
interface RuleSummaryWords {
|
|
54
|
+
sentence: string;
|
|
55
|
+
/** For a rule with no actions to name (a conditions-only rule). */
|
|
56
|
+
sentenceConditionsOnly: string;
|
|
57
|
+
noConditions: string;
|
|
58
|
+
noActions: string;
|
|
59
|
+
and: string;
|
|
60
|
+
or: string;
|
|
61
|
+
}
|
|
62
|
+
declare const DEFAULT_RULE_SUMMARY_WORDS: RuleSummaryWords;
|
|
35
63
|
declare function summarizeRule(value: RuleDefinition, labels?: {
|
|
36
64
|
fields?: Record<string, string>;
|
|
37
65
|
operators?: Record<string, string>;
|
|
38
66
|
actions?: Record<string, string>;
|
|
67
|
+
/** Translate the sentence itself. Default: English. */
|
|
68
|
+
words?: Partial<RuleSummaryWords>;
|
|
69
|
+
/** Leave the actions out of the sentence. */
|
|
70
|
+
conditionsOnly?: boolean;
|
|
39
71
|
}): string;
|
|
40
72
|
|
|
41
|
-
export { type RuleAction, type RuleCondition, type RuleDefinition, type RuleGroup, type RuleValidationIssue, appendRuleNode, findRuleNodeDepth, isRuleGroup, mapRuleGroup, moveRuleNode, removeRuleNode, ruleDepth, summarizeRule, validateRuleDefinition };
|
|
73
|
+
export { DEFAULT_RULE_SUMMARY_WORDS, DEFAULT_RULE_VALIDATION_MESSAGES, type RuleAction, type RuleCheck, type RuleCondition, type RuleDefinition, type RuleGroup, type RuleSummaryWords, type RuleValidationIssue, type RuleValidationOptions, appendRuleNode, findRuleNodeDepth, isRuleGroup, mapRuleGroup, moveRuleNode, removeRuleNode, ruleDepth, setRuleCombinator, summarizeRule, validateRuleDefinition };
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
const fillLabel = (template, values) => template.replace(/\{(\w+)\}/g, (match, key) => Object.prototype.hasOwnProperty.call(values, key) ? String(values[key]) : match);
|
|
2
|
+
const DEFAULT_RULE_VALIDATION_MESSAGES = {
|
|
3
|
+
duplicateId: "Duplicate id \u201C{id}\u201D.",
|
|
4
|
+
maxDepth: "Nesting exceeds {max} levels.",
|
|
5
|
+
emptyGroup: "Add at least one condition.",
|
|
6
|
+
missingField: "Choose a field.",
|
|
7
|
+
missingOperator: "Choose an operator.",
|
|
8
|
+
noActions: "Add at least one action.",
|
|
9
|
+
missingActionType: "Choose an action."
|
|
10
|
+
};
|
|
1
11
|
function isRuleGroup(node) {
|
|
2
12
|
return "conditions" in node;
|
|
3
13
|
}
|
|
@@ -52,43 +62,68 @@ function moveRuleNode(group, id, direction) {
|
|
|
52
62
|
conditions: group.conditions.map((node) => isRuleGroup(node) ? moveRuleNode(node, id, direction) : node)
|
|
53
63
|
};
|
|
54
64
|
}
|
|
55
|
-
function
|
|
65
|
+
function setRuleCombinator(group, combinator) {
|
|
66
|
+
return {
|
|
67
|
+
...group,
|
|
68
|
+
combinator,
|
|
69
|
+
conditions: group.conditions.map((node) => isRuleGroup(node) ? setRuleCombinator(node, combinator) : node)
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function validateRuleDefinition(value, maxDepth = 3, options = {}) {
|
|
56
73
|
const issues = [];
|
|
74
|
+
const messages = { ...DEFAULT_RULE_VALIDATION_MESSAGES, ...options.messages };
|
|
75
|
+
const report = (check, path, values = {}) => {
|
|
76
|
+
if (options.checks?.[check] === false) return;
|
|
77
|
+
issues.push({ path, message: fillLabel(messages[check], values), check });
|
|
78
|
+
};
|
|
57
79
|
const ids = /* @__PURE__ */ new Set();
|
|
58
80
|
const visit = (group, path, depth) => {
|
|
59
|
-
if (ids.has(group.id))
|
|
81
|
+
if (ids.has(group.id)) report("duplicateId", path, { id: group.id });
|
|
60
82
|
ids.add(group.id);
|
|
61
|
-
if (depth > maxDepth)
|
|
62
|
-
if (group.conditions.length === 0)
|
|
83
|
+
if (depth > maxDepth) report("maxDepth", path, { max: maxDepth });
|
|
84
|
+
if (group.conditions.length === 0) report("emptyGroup", path);
|
|
63
85
|
group.conditions.forEach((node, index) => {
|
|
64
86
|
const nodePath = `${path}.conditions[${index}]`;
|
|
65
|
-
if (ids.has(node.id))
|
|
87
|
+
if (ids.has(node.id)) report("duplicateId", nodePath, { id: node.id });
|
|
66
88
|
if (isRuleGroup(node)) visit(node, nodePath, depth + 1);
|
|
67
89
|
else {
|
|
68
90
|
ids.add(node.id);
|
|
69
|
-
if (!node.field)
|
|
70
|
-
if (!node.operator)
|
|
91
|
+
if (!node.field) report("missingField", nodePath);
|
|
92
|
+
if (!node.operator) report("missingOperator", nodePath);
|
|
71
93
|
}
|
|
72
94
|
});
|
|
73
95
|
};
|
|
74
96
|
visit(value.when, "when", 1);
|
|
75
|
-
if (value.then.length === 0)
|
|
97
|
+
if (value.then.length === 0) report("noActions", "then");
|
|
76
98
|
value.then.forEach((action, index) => {
|
|
77
|
-
if (ids.has(action.id))
|
|
99
|
+
if (ids.has(action.id)) report("duplicateId", `then[${index}]`, { id: action.id });
|
|
78
100
|
ids.add(action.id);
|
|
79
|
-
if (!action.type)
|
|
101
|
+
if (!action.type) report("missingActionType", `then[${index}]`);
|
|
80
102
|
});
|
|
81
103
|
return issues;
|
|
82
104
|
}
|
|
105
|
+
const DEFAULT_RULE_SUMMARY_WORDS = {
|
|
106
|
+
sentence: "When {conditions}, then {actions}.",
|
|
107
|
+
sentenceConditionsOnly: "When {conditions}.",
|
|
108
|
+
noConditions: "no conditions",
|
|
109
|
+
noActions: "no actions",
|
|
110
|
+
and: "AND",
|
|
111
|
+
or: "OR"
|
|
112
|
+
};
|
|
83
113
|
function summarizeRule(value, labels = {}) {
|
|
114
|
+
const words = { ...DEFAULT_RULE_SUMMARY_WORDS, ...labels.words };
|
|
84
115
|
const formatValue = (input) => input === void 0 ? "" : ` ${JSON.stringify(input)}`;
|
|
85
116
|
const formatGroup = (group) => group.conditions.map(
|
|
86
117
|
(node) => isRuleGroup(node) ? `(${formatGroup(node)})` : `${labels.fields?.[node.field] ?? node.field} ${labels.operators?.[node.operator] ?? node.operator}${formatValue(node.value)}`
|
|
87
|
-
).join(` ${group.combinator.
|
|
118
|
+
).join(` ${group.combinator === "or" ? words.or : words.and} `);
|
|
119
|
+
const conditions = formatGroup(value.when) || words.noConditions;
|
|
120
|
+
if (labels.conditionsOnly) return fillLabel(words.sentenceConditionsOnly, { conditions });
|
|
88
121
|
const actions = value.then.map((action) => labels.actions?.[action.type] ?? action.type).join(", ");
|
|
89
|
-
return
|
|
122
|
+
return fillLabel(words.sentence, { conditions, actions: actions || words.noActions });
|
|
90
123
|
}
|
|
91
124
|
export {
|
|
125
|
+
DEFAULT_RULE_SUMMARY_WORDS,
|
|
126
|
+
DEFAULT_RULE_VALIDATION_MESSAGES,
|
|
92
127
|
appendRuleNode,
|
|
93
128
|
findRuleNodeDepth,
|
|
94
129
|
isRuleGroup,
|
|
@@ -96,6 +131,7 @@ export {
|
|
|
96
131
|
moveRuleNode,
|
|
97
132
|
removeRuleNode,
|
|
98
133
|
ruleDepth,
|
|
134
|
+
setRuleCombinator,
|
|
99
135
|
summarizeRule,
|
|
100
136
|
validateRuleDefinition
|
|
101
137
|
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { CalendarWeekday, ZonedDaySpan } from './calendar-model.js';
|
|
2
|
+
|
|
3
|
+
/** Which lane group a span is drawn in: windows sit above multi-day items, and neither takes a chip slot. */
|
|
4
|
+
type MonthSpanGroup = 'window' | 'item';
|
|
5
|
+
interface MonthSpanInput {
|
|
6
|
+
id: string;
|
|
7
|
+
/** Half-open `[start, end)` instants (ISO 8601, epoch ms or Date). */
|
|
8
|
+
start: string | number | Date;
|
|
9
|
+
end: string | number | Date;
|
|
10
|
+
/** Defaults to `'item'`. */
|
|
11
|
+
group?: MonthSpanGroup;
|
|
12
|
+
}
|
|
13
|
+
interface PlacedMonthSpan {
|
|
14
|
+
id: string;
|
|
15
|
+
group: MonthSpanGroup;
|
|
16
|
+
/** 0-based week row of the grid `days` the layout was computed for. */
|
|
17
|
+
weekRow: number;
|
|
18
|
+
/** 0-based lane inside its group. */
|
|
19
|
+
lane: number;
|
|
20
|
+
/** First and last column (0–6, inclusive) the span covers in this row. */
|
|
21
|
+
startCol: number;
|
|
22
|
+
endCol: number;
|
|
23
|
+
/** The span started in an earlier row (or before the grid). */
|
|
24
|
+
continuesBefore: boolean;
|
|
25
|
+
/** The span goes on in a later row (or past the grid). */
|
|
26
|
+
continuesAfter: boolean;
|
|
27
|
+
}
|
|
28
|
+
interface MonthSpanLayout {
|
|
29
|
+
/** One entry per span per week row it got a lane in. Render exactly these; never re-pack. */
|
|
30
|
+
placed: PlacedMonthSpan[];
|
|
31
|
+
/** Per week row, the ids that got no lane, in input order (windows first). An id may name a window and an item. */
|
|
32
|
+
hiddenByRow: Record<number, string[]>;
|
|
33
|
+
/** Per week row with a hidden span, the first day (`YYYY-MM-DD`) a hidden span covers. */
|
|
34
|
+
firstHiddenDayByRow: Record<number, string>;
|
|
35
|
+
}
|
|
36
|
+
interface LayoutMonthSpansOptions {
|
|
37
|
+
/** The display zone that decides which days a span covers. */
|
|
38
|
+
timeZone: string;
|
|
39
|
+
/** When set, `days[0]` must fall on this weekday (a guard against a grid built for another week start). */
|
|
40
|
+
weekStartsOn?: CalendarWeekday;
|
|
41
|
+
/** Lanes per group (default 2). A number applies to both groups. */
|
|
42
|
+
laneCap?: number | Partial<Record<MonthSpanGroup, number>>;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The calendar days an item covers in `timeZone`, end-exclusive (`end` is the first day not
|
|
46
|
+
* covered): a 22:00–00:00 item covers only its start day, a 23:00 → 02:00 item two days. A
|
|
47
|
+
* zero-length item covers the day of its start. Throws a `RangeError` when `end` is before
|
|
48
|
+
* `start`; it never swaps them.
|
|
49
|
+
*/
|
|
50
|
+
declare function itemDaySpan(start: string | number | Date, end: string | number | Date, timeZone: string): ZonedDaySpan;
|
|
51
|
+
/**
|
|
52
|
+
* The date keys a `SchedulingCalendar` grid shows, in order: six week rows for `'month'`
|
|
53
|
+
* (from the week holding the 1st), one for `'week'` (the week holding `anchorDate`). Pass the
|
|
54
|
+
* result to `layoutMonthSpans` so the layout and the rendered grid agree.
|
|
55
|
+
*/
|
|
56
|
+
declare function schedulingGridDays(anchorDate: string, view: 'month' | 'week', weekStartsOn?: CalendarWeekday): string[];
|
|
57
|
+
/**
|
|
58
|
+
* Places multi-day spans as one continuous bar per week row. Spans are taken **in the order
|
|
59
|
+
* given** (the consumer's salience order): in each row and group, the first spans to ask get
|
|
60
|
+
* the lanes, the rest are listed in `hiddenByRow`. Windows and items pack in separate groups,
|
|
61
|
+
* each capped by `laneCap`. Day membership is the end-exclusive zoned span in `timeZone`
|
|
62
|
+
* (never a UTC date). `days` are the grid's date keys, a whole number of weeks.
|
|
63
|
+
*/
|
|
64
|
+
declare function layoutMonthSpans(spans: readonly MonthSpanInput[], days: readonly string[], options: LayoutMonthSpansOptions): MonthSpanLayout;
|
|
65
|
+
|
|
66
|
+
export { type LayoutMonthSpansOptions, type MonthSpanGroup, type MonthSpanInput, type MonthSpanLayout, type PlacedMonthSpan, itemDaySpan, layoutMonthSpans, schedulingGridDays };
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { addCalendarDays, buildMonthGrid, packLanes, startOfMonth, zonedDateKey, zonedDaySpan } from "./calendar-model.js";
|
|
2
|
+
const DEFAULT_LANE_CAP = 2;
|
|
3
|
+
function itemDaySpan(start, end, timeZone) {
|
|
4
|
+
const from = new Date(start);
|
|
5
|
+
const to = new Date(end);
|
|
6
|
+
if (from.getTime() === to.getTime()) {
|
|
7
|
+
const day = zonedDateKey(from, timeZone);
|
|
8
|
+
return { start: day, end: addCalendarDays(day, 1) };
|
|
9
|
+
}
|
|
10
|
+
return zonedDaySpan(from, to, timeZone);
|
|
11
|
+
}
|
|
12
|
+
function schedulingGridDays(anchorDate, view, weekStartsOn = 1) {
|
|
13
|
+
if (view === "month") return buildMonthGrid(startOfMonth(anchorDate), weekStartsOn).map((day) => day.date);
|
|
14
|
+
const weekday = (/* @__PURE__ */ new Date(`${anchorDate}T00:00:00Z`)).getUTCDay();
|
|
15
|
+
const first = addCalendarDays(anchorDate, -((weekday - weekStartsOn + 7) % 7));
|
|
16
|
+
return Array.from({ length: 7 }, (_, index) => addCalendarDays(first, index));
|
|
17
|
+
}
|
|
18
|
+
function layoutMonthSpans(spans, days, options) {
|
|
19
|
+
if (days.length === 0 || days.length % 7 !== 0) throw new RangeError(`layoutMonthSpans: days must be whole weeks, got ${days.length} day(s)`);
|
|
20
|
+
for (let index = 1; index < days.length; index++) {
|
|
21
|
+
if (days[index] !== addCalendarDays(days[index - 1], 1)) throw new RangeError(`layoutMonthSpans: days must be consecutive (${days[index - 1]} \u2192 ${days[index]})`);
|
|
22
|
+
}
|
|
23
|
+
if (options.weekStartsOn !== void 0 && (/* @__PURE__ */ new Date(`${days[0]}T00:00:00Z`)).getUTCDay() !== options.weekStartsOn) {
|
|
24
|
+
throw new RangeError(`layoutMonthSpans: days[0] (${days[0]}) does not fall on weekday ${options.weekStartsOn}`);
|
|
25
|
+
}
|
|
26
|
+
const capFor = (group) => {
|
|
27
|
+
const cap = typeof options.laneCap === "number" ? options.laneCap : options.laneCap?.[group] ?? DEFAULT_LANE_CAP;
|
|
28
|
+
if (!(cap === Infinity || Number.isInteger(cap) && cap >= 0)) throw new RangeError(`layoutMonthSpans: laneCap for ${group} must be a non-negative integer, got ${cap}`);
|
|
29
|
+
return cap;
|
|
30
|
+
};
|
|
31
|
+
const caps = { window: capFor("window"), item: capFor("item") };
|
|
32
|
+
const rows = days.length / 7;
|
|
33
|
+
const gridEnd = addCalendarDays(days[days.length - 1], 1);
|
|
34
|
+
const seen = /* @__PURE__ */ new Set();
|
|
35
|
+
const covered = spans.map((span) => {
|
|
36
|
+
const group = span.group ?? "item";
|
|
37
|
+
if (seen.has(`${group} ${span.id}`)) throw new TypeError(`layoutMonthSpans: duplicate ${group} id ${span.id}`);
|
|
38
|
+
seen.add(`${group} ${span.id}`);
|
|
39
|
+
return { id: span.id, group, days: itemDaySpan(span.start, span.end, options.timeZone) };
|
|
40
|
+
});
|
|
41
|
+
const placed = [];
|
|
42
|
+
const hiddenByRow = {};
|
|
43
|
+
const firstHiddenDayByRow = {};
|
|
44
|
+
for (let row = 0; row < rows; row++) {
|
|
45
|
+
const rowStart = days[row * 7];
|
|
46
|
+
const rowEnd = row + 1 < rows ? days[(row + 1) * 7] : gridEnd;
|
|
47
|
+
for (const group of ["window", "item"]) {
|
|
48
|
+
const inRow = covered.filter((span) => span.group === group && span.days.start < rowEnd && span.days.end > rowStart).map((span) => {
|
|
49
|
+
const from = span.days.start > rowStart ? span.days.start : rowStart;
|
|
50
|
+
const to = span.days.end < rowEnd ? span.days.end : rowEnd;
|
|
51
|
+
const startCol = days.indexOf(from, row * 7) - row * 7;
|
|
52
|
+
const endCol = days.indexOf(addCalendarDays(to, -1), row * 7) - row * 7;
|
|
53
|
+
return { span, from, startCol, endCol };
|
|
54
|
+
});
|
|
55
|
+
const packed = packLanes(inRow.map(({ span, startCol, endCol }) => ({ id: span.id, start: startCol, end: endCol + 1 })), caps[group], { order: "given" });
|
|
56
|
+
for (const { span, from, startCol, endCol } of inRow) {
|
|
57
|
+
const lane = packed.lanes[span.id].lane;
|
|
58
|
+
if (lane === null) {
|
|
59
|
+
(hiddenByRow[row] ?? (hiddenByRow[row] = [])).push(span.id);
|
|
60
|
+
if (firstHiddenDayByRow[row] === void 0 || from < firstHiddenDayByRow[row]) firstHiddenDayByRow[row] = from;
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
placed.push({
|
|
64
|
+
id: span.id,
|
|
65
|
+
group,
|
|
66
|
+
weekRow: row,
|
|
67
|
+
lane,
|
|
68
|
+
startCol,
|
|
69
|
+
endCol,
|
|
70
|
+
continuesBefore: span.days.start < rowStart,
|
|
71
|
+
continuesAfter: span.days.end > rowEnd
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return { placed, hiddenByRow, firstHiddenDayByRow };
|
|
77
|
+
}
|
|
78
|
+
export {
|
|
79
|
+
itemDaySpan,
|
|
80
|
+
layoutMonthSpans,
|
|
81
|
+
schedulingGridDays
|
|
82
|
+
};
|