@antglobal/copilot-cards-web 0.0.20260828032020-dev.9 → 0.0.20260915071159-dev.5
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 +1 -1
- package/dist/index.d.ts +8 -0
- package/dist/index.js +606 -81
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ The package includes the core schema and action APIs, responsive rendering, Shad
|
|
|
7
7
|
## Installation
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
npm install @antglobal/copilot-cards-web@1.0.
|
|
10
|
+
npm install @antglobal/copilot-cards-web@1.0.9
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
`@antglobal/copilot-cards-core` is installed automatically.
|
package/dist/index.d.ts
CHANGED
|
@@ -107,6 +107,8 @@ declare function createResponsiveContext(isMobile: boolean, responsive?: Respons
|
|
|
107
107
|
*/
|
|
108
108
|
|
|
109
109
|
interface RenderCardOptions extends WebActionContextOptions {
|
|
110
|
+
/** Block whole-card interaction and add a configurable overlay without restyling nodes. Default false. */
|
|
111
|
+
disabled?: boolean;
|
|
110
112
|
/** Enable mobile component layout explicitly (default false). */
|
|
111
113
|
isMobile?: boolean;
|
|
112
114
|
/** Optional mobile sizing conversion; omitted values preserve px output. */
|
|
@@ -117,6 +119,8 @@ interface RenderCardOptions extends WebActionContextOptions {
|
|
|
117
119
|
botId?: string;
|
|
118
120
|
}
|
|
119
121
|
interface CardInstance {
|
|
122
|
+
/** Toggle whole-card interaction without changing schema or component business rules. */
|
|
123
|
+
setDisabled: (disabled: boolean) => void;
|
|
120
124
|
/** Dispose the card: unmount all lifecycles, remove DOM, detach listeners. */
|
|
121
125
|
dispose: () => void;
|
|
122
126
|
/** Update variables and re-render. */
|
|
@@ -509,6 +513,8 @@ declare abstract class BaseElement extends HTMLElement {
|
|
|
509
513
|
* Subclasses must implement this to render their UI into `this.shadowRoot`.
|
|
510
514
|
*/
|
|
511
515
|
protected abstract render(): void;
|
|
516
|
+
/** @internal Close temporary interaction UI without clearing component values. */
|
|
517
|
+
closeTransientUI(): void;
|
|
512
518
|
/** Convert any content value to a safe display string. */
|
|
513
519
|
protected resolveContent(content: any): string;
|
|
514
520
|
/**
|
|
@@ -736,6 +742,7 @@ declare class CardImage extends BaseElement {
|
|
|
736
742
|
private bindEvents;
|
|
737
743
|
private openLightbox;
|
|
738
744
|
private closeLightbox;
|
|
745
|
+
closeTransientUI(): void;
|
|
739
746
|
disconnectedCallback(): void;
|
|
740
747
|
}
|
|
741
748
|
|
|
@@ -899,6 +906,7 @@ declare class CardSelect extends BaseElement {
|
|
|
899
906
|
private _onDocClick;
|
|
900
907
|
static readonly is = "ai-card-select";
|
|
901
908
|
protected render(): void;
|
|
909
|
+
closeTransientUI(): void;
|
|
902
910
|
disconnectedCallback(): void;
|
|
903
911
|
updateProps(props: Record<string, any>, isMobile?: boolean, responsive?: ResponsiveOptions): void;
|
|
904
912
|
private _setOpen;
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getBuiltinIcon, cloneJsonData, createLifecycleManager, materializeCard, findAffectedRepeatOwners, createA2UIParameterResolver, createExpressionContext, replaceRootContents, getByJsonPointer, resolveA2UIDeep, resolveDeep, resolveExpressionValue,
|
|
1
|
+
import { getBuiltinIcon, cloneJsonData, createLifecycleManager, materializeCard, findAffectedRepeatOwners, createA2UIParameterResolver, createExpressionContext, replaceRootContents, getByJsonPointer, resolveA2UIDeep, resolveDeep, resolveExpressionValue, isBoundRenderTreeNode, resolveActionRef, hasExpression, resolveExpression, runActionSteps, normalizeSchema, validateSchema, requiresBindingMaterialization, parseSchema, StreamingParser, StreamingEngine, bindingTopologyFingerprint, findTemplateRepeatOwners, extractPartialSchema, runActionStep, registry } from '@antglobal/copilot-cards-core';
|
|
2
2
|
export { ActionRegistry, a2uiComponentToElement, a2uiToCommand, convertLegacySchema, createLifecycleManager, hasExpression, isA2UIEnvelope, isLegacySchema, normalizeSchema, parseSchema, registerActionHandler, registry, resolveActionRef, resolveDeep, resolveExpression, resolveExpressionValue, runActionStep, runActionSteps, validateSchema } from '@antglobal/copilot-cards-core';
|
|
3
3
|
import * as echarts from 'echarts/core';
|
|
4
4
|
import { LineChart, BarChart, PieChart, ScatterChart, FunnelChart, HeatmapChart } from 'echarts/charts';
|
|
@@ -713,6 +713,269 @@ function buildHeatmapOption(config) {
|
|
|
713
713
|
};
|
|
714
714
|
}
|
|
715
715
|
|
|
716
|
+
const controllers = new WeakMap();
|
|
717
|
+
const interactionCleanups = new WeakMap();
|
|
718
|
+
/** Cancel slot-owned gestures before covering the card. */
|
|
719
|
+
function registerCardDisableCleanup(element, cleanup) {
|
|
720
|
+
let callbacks = interactionCleanups.get(element);
|
|
721
|
+
if (!callbacks) {
|
|
722
|
+
callbacks = new Set();
|
|
723
|
+
interactionCleanups.set(element, callbacks);
|
|
724
|
+
}
|
|
725
|
+
callbacks.add(cleanup);
|
|
726
|
+
return () => { callbacks.delete(cleanup); };
|
|
727
|
+
}
|
|
728
|
+
function composedParent(node) {
|
|
729
|
+
return node.parentNode ?? (node instanceof ShadowRoot ? node.host : null);
|
|
730
|
+
}
|
|
731
|
+
function isCardDisabled(node) {
|
|
732
|
+
for (let current = node; current; current = composedParent(current)) {
|
|
733
|
+
if (current instanceof HTMLElement && controllers.get(current)?.isDisabled)
|
|
734
|
+
return true;
|
|
735
|
+
}
|
|
736
|
+
return false;
|
|
737
|
+
}
|
|
738
|
+
const BLOCKED_EVENTS = [
|
|
739
|
+
'click', 'dblclick', 'auxclick', 'contextmenu',
|
|
740
|
+
'beforeinput', 'input', 'change', 'submit', 'keydown', 'keyup',
|
|
741
|
+
'compositionstart', 'compositionupdate', 'compositionend',
|
|
742
|
+
'choice-request-change', 'choice-navigate',
|
|
743
|
+
];
|
|
744
|
+
const TOUCH_EVENTS = ['pointerdown', 'pointerup', 'touchstart', 'touchend', 'mousedown', 'mouseup', 'wheel'];
|
|
745
|
+
const TAB_TARGETS = [
|
|
746
|
+
'a[href]', 'area[href]', 'button', 'input', 'select', 'textarea', 'summary',
|
|
747
|
+
'iframe', 'object', 'embed', 'audio[controls]', 'video[controls]',
|
|
748
|
+
'[tabindex]', '[contenteditable]:not([contenteditable="false"])',
|
|
749
|
+
].join(',');
|
|
750
|
+
const CARD_DISABLED_ATTRIBUTE = 'data-card-disabled';
|
|
751
|
+
function restoreAttribute(element, name, value) {
|
|
752
|
+
if (value === null)
|
|
753
|
+
element.removeAttribute(name);
|
|
754
|
+
else
|
|
755
|
+
element.setAttribute(name, value);
|
|
756
|
+
}
|
|
757
|
+
function createCardDisabledController(container, initiallyDisabled = false) {
|
|
758
|
+
let disabled = false;
|
|
759
|
+
let disposed = false;
|
|
760
|
+
let epoch = 0;
|
|
761
|
+
let updateDepth = 0;
|
|
762
|
+
let applyingPresentation = false;
|
|
763
|
+
let previousAriaDisabled = null;
|
|
764
|
+
let previousDisabledMarker = null;
|
|
765
|
+
let overlay;
|
|
766
|
+
let mountStyles = [];
|
|
767
|
+
let tabSnapshots = [];
|
|
768
|
+
let tabObserver;
|
|
769
|
+
const block = (event) => {
|
|
770
|
+
if (!disabled || disposed)
|
|
771
|
+
return;
|
|
772
|
+
event.preventDefault();
|
|
773
|
+
event.stopImmediatePropagation();
|
|
774
|
+
};
|
|
775
|
+
// Prevent component gesture handlers without cancelling the browser's scroll.
|
|
776
|
+
const stopGesture = (event) => {
|
|
777
|
+
if (disabled && !disposed)
|
|
778
|
+
event.stopImmediatePropagation();
|
|
779
|
+
};
|
|
780
|
+
const blockFocus = (event) => {
|
|
781
|
+
if (!disabled || disposed)
|
|
782
|
+
return;
|
|
783
|
+
const target = event.composedPath()[0] ?? event.target;
|
|
784
|
+
if (target instanceof HTMLElement)
|
|
785
|
+
target.blur();
|
|
786
|
+
event.stopImmediatePropagation();
|
|
787
|
+
};
|
|
788
|
+
function closeTransientUI(root) {
|
|
789
|
+
for (const element of root.querySelectorAll('*')) {
|
|
790
|
+
interactionCleanups.get(element)?.forEach(cleanup => cleanup());
|
|
791
|
+
const component = element;
|
|
792
|
+
component.closeTransientUI?.();
|
|
793
|
+
if (element.shadowRoot)
|
|
794
|
+
closeTransientUI(element.shadowRoot);
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
function blurCardInput() {
|
|
798
|
+
let active = container.ownerDocument.activeElement;
|
|
799
|
+
while (active?.shadowRoot?.activeElement)
|
|
800
|
+
active = active.shadowRoot.activeElement;
|
|
801
|
+
if (!(active instanceof HTMLElement))
|
|
802
|
+
return;
|
|
803
|
+
for (let node = active; node; node = composedParent(node)) {
|
|
804
|
+
if (node === container) {
|
|
805
|
+
active.blur();
|
|
806
|
+
return;
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
function excludeFromTabNavigation(root) {
|
|
811
|
+
const observer = tabObserver ?? (tabObserver = new MutationObserver(() => {
|
|
812
|
+
if (!disabled || disposed || updateDepth > 0)
|
|
813
|
+
return;
|
|
814
|
+
// Components such as streaming Markdown also update their own Shadow DOM.
|
|
815
|
+
restoreTabNavigation();
|
|
816
|
+
excludeFromTabNavigation(container);
|
|
817
|
+
}));
|
|
818
|
+
const targets = [];
|
|
819
|
+
const collect = (element) => {
|
|
820
|
+
if (element.matches(TAB_TARGETS)) {
|
|
821
|
+
targets.push(element);
|
|
822
|
+
return;
|
|
823
|
+
}
|
|
824
|
+
// Browsers can put scroll containers in the Tab order without tabindex.
|
|
825
|
+
const style = element.ownerDocument.defaultView?.getComputedStyle(element);
|
|
826
|
+
if (style && [style.overflowX, style.overflowY].some(value => value === 'auto' || value === 'scroll')) {
|
|
827
|
+
targets.push(element);
|
|
828
|
+
}
|
|
829
|
+
};
|
|
830
|
+
const walk = (parent) => {
|
|
831
|
+
observer.observe(parent, { childList: true, subtree: true });
|
|
832
|
+
if (parent instanceof HTMLElement)
|
|
833
|
+
collect(parent);
|
|
834
|
+
for (const element of parent.querySelectorAll('*')) {
|
|
835
|
+
collect(element);
|
|
836
|
+
if (element.shadowRoot)
|
|
837
|
+
walk(element.shadowRoot);
|
|
838
|
+
}
|
|
839
|
+
};
|
|
840
|
+
// Collect before writing attributes so style reads stay in one batch.
|
|
841
|
+
walk(root);
|
|
842
|
+
for (const element of targets) {
|
|
843
|
+
tabSnapshots.push({ element, tabindex: element.getAttribute('tabindex') });
|
|
844
|
+
element.setAttribute('tabindex', '-1');
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
function restoreTabNavigation() {
|
|
848
|
+
tabObserver?.disconnect();
|
|
849
|
+
if (!disabled)
|
|
850
|
+
tabObserver = undefined;
|
|
851
|
+
for (const { element, tabindex } of tabSnapshots) {
|
|
852
|
+
restoreAttribute(element, 'tabindex', tabindex);
|
|
853
|
+
}
|
|
854
|
+
tabSnapshots = [];
|
|
855
|
+
}
|
|
856
|
+
function restorePresentation() {
|
|
857
|
+
restoreTabNavigation();
|
|
858
|
+
overlay?.remove();
|
|
859
|
+
for (const [name, value, priority] of mountStyles) {
|
|
860
|
+
if (value)
|
|
861
|
+
container.style.setProperty(name, value, priority);
|
|
862
|
+
else
|
|
863
|
+
container.style.removeProperty(name);
|
|
864
|
+
}
|
|
865
|
+
mountStyles = [];
|
|
866
|
+
}
|
|
867
|
+
function coverCard() {
|
|
868
|
+
const root = container.firstElementChild;
|
|
869
|
+
if (!root)
|
|
870
|
+
return;
|
|
871
|
+
const style = container.ownerDocument.defaultView?.getComputedStyle(container);
|
|
872
|
+
const ownStyle = (name, value) => {
|
|
873
|
+
mountStyles.push([name, container.style.getPropertyValue(name), container.style.getPropertyPriority(name)]);
|
|
874
|
+
container.style.setProperty(name, value, 'important');
|
|
875
|
+
};
|
|
876
|
+
if (!style?.position || style.position === 'static')
|
|
877
|
+
ownStyle('position', 'relative');
|
|
878
|
+
// Keep the mask above card content without covering neighboring messages.
|
|
879
|
+
ownStyle('isolation', 'isolate');
|
|
880
|
+
overlay ?? (overlay = container.ownerDocument.createElement('div'));
|
|
881
|
+
overlay.setAttribute('data-card-disabled-overlay', '');
|
|
882
|
+
overlay.setAttribute('aria-hidden', 'true');
|
|
883
|
+
overlay.style.cssText = 'position:absolute;inset:0;z-index:2147483647;pointer-events:auto;cursor:default;'
|
|
884
|
+
+ 'background:var(--card-disabled-overlay-background, rgba(255, 255, 255, 0.6));';
|
|
885
|
+
// A dedicated mount normally shares the root card's bounds. Respect a mount
|
|
886
|
+
// radius when provided, otherwise match the rendered card's rounded corners.
|
|
887
|
+
const rootStyle = container.ownerDocument.defaultView?.getComputedStyle(root);
|
|
888
|
+
overlay.style.borderRadius = style?.borderRadius && style.borderRadius !== '0px'
|
|
889
|
+
? style.borderRadius : rootStyle?.borderRadius ?? '';
|
|
890
|
+
container.appendChild(overlay);
|
|
891
|
+
}
|
|
892
|
+
function applyPresentation() {
|
|
893
|
+
if (!disabled || disposed || updateDepth > 0 || applyingPresentation)
|
|
894
|
+
return;
|
|
895
|
+
applyingPresentation = true;
|
|
896
|
+
try {
|
|
897
|
+
// Blur/popup callbacks can synchronously update or toggle the card.
|
|
898
|
+
// Reattach only after renderer updates and popup/gesture cleanup finish.
|
|
899
|
+
restorePresentation();
|
|
900
|
+
closeTransientUI(container);
|
|
901
|
+
blurCardInput();
|
|
902
|
+
if (!disabled || disposed)
|
|
903
|
+
return;
|
|
904
|
+
coverCard();
|
|
905
|
+
excludeFromTabNavigation(container);
|
|
906
|
+
}
|
|
907
|
+
finally {
|
|
908
|
+
applyingPresentation = false;
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
function listen(enabled) {
|
|
912
|
+
for (const name of BLOCKED_EVENTS) {
|
|
913
|
+
if (enabled)
|
|
914
|
+
container.addEventListener(name, block, true);
|
|
915
|
+
else
|
|
916
|
+
container.removeEventListener(name, block, true);
|
|
917
|
+
}
|
|
918
|
+
for (const name of TOUCH_EVENTS) {
|
|
919
|
+
if (enabled)
|
|
920
|
+
container.addEventListener(name, stopGesture, { capture: true, passive: true });
|
|
921
|
+
else
|
|
922
|
+
container.removeEventListener(name, stopGesture, true);
|
|
923
|
+
}
|
|
924
|
+
if (enabled)
|
|
925
|
+
container.addEventListener('focus', blockFocus, true);
|
|
926
|
+
else
|
|
927
|
+
container.removeEventListener('focus', blockFocus, true);
|
|
928
|
+
}
|
|
929
|
+
const controller = {
|
|
930
|
+
get isDisabled() { return disabled && !disposed; },
|
|
931
|
+
get epoch() { return epoch; },
|
|
932
|
+
setDisabled(value) {
|
|
933
|
+
if (disposed || disabled === value)
|
|
934
|
+
return;
|
|
935
|
+
disabled = value;
|
|
936
|
+
epoch += 1;
|
|
937
|
+
if (disabled) {
|
|
938
|
+
previousAriaDisabled = container.getAttribute('aria-disabled');
|
|
939
|
+
previousDisabledMarker = container.getAttribute(CARD_DISABLED_ATTRIBUTE);
|
|
940
|
+
container.setAttribute('aria-disabled', 'true');
|
|
941
|
+
container.setAttribute(CARD_DISABLED_ATTRIBUTE, 'true');
|
|
942
|
+
listen(true);
|
|
943
|
+
blurCardInput();
|
|
944
|
+
applyPresentation();
|
|
945
|
+
}
|
|
946
|
+
else {
|
|
947
|
+
restorePresentation();
|
|
948
|
+
restoreAttribute(container, 'aria-disabled', previousAriaDisabled);
|
|
949
|
+
restoreAttribute(container, CARD_DISABLED_ATTRIBUTE, previousDisabledMarker);
|
|
950
|
+
listen(false);
|
|
951
|
+
}
|
|
952
|
+
},
|
|
953
|
+
update(render) {
|
|
954
|
+
if (updateDepth === 0)
|
|
955
|
+
restorePresentation();
|
|
956
|
+
updateDepth += 1;
|
|
957
|
+
try {
|
|
958
|
+
return render();
|
|
959
|
+
}
|
|
960
|
+
finally {
|
|
961
|
+
updateDepth -= 1;
|
|
962
|
+
if (updateDepth === 0)
|
|
963
|
+
applyPresentation();
|
|
964
|
+
}
|
|
965
|
+
},
|
|
966
|
+
dispose() {
|
|
967
|
+
if (disposed)
|
|
968
|
+
return;
|
|
969
|
+
controller.setDisabled(false);
|
|
970
|
+
disposed = true;
|
|
971
|
+
controllers.delete(container);
|
|
972
|
+
},
|
|
973
|
+
};
|
|
974
|
+
controllers.set(container, controller);
|
|
975
|
+
controller.setDisabled(initiallyDisabled);
|
|
976
|
+
return controller;
|
|
977
|
+
}
|
|
978
|
+
|
|
716
979
|
/**
|
|
717
980
|
* Slot Layout Renderers — each slot key maps to a specific layout strategy.
|
|
718
981
|
*
|
|
@@ -1033,6 +1296,15 @@ function mergePresentationOwnership(...ownership) {
|
|
|
1033
1296
|
styleProperties: Array.from(new Set(ownership.flatMap(value => value.styleProperties))),
|
|
1034
1297
|
};
|
|
1035
1298
|
}
|
|
1299
|
+
const datePickerRowPaddingPatches = new WeakMap();
|
|
1300
|
+
/** Suspend an open date picker's row padding around renderer-owned style updates. */
|
|
1301
|
+
function registerDatePickerRowPaddingPatch(row, suspend) {
|
|
1302
|
+
datePickerRowPaddingPatches.set(row, suspend);
|
|
1303
|
+
return () => {
|
|
1304
|
+
if (datePickerRowPaddingPatches.get(row) === suspend)
|
|
1305
|
+
datePickerRowPaddingPatches.delete(row);
|
|
1306
|
+
};
|
|
1307
|
+
}
|
|
1036
1308
|
/** Patch renderer-owned shell presentation without overwriting layout state. */
|
|
1037
1309
|
function patchElementShellPresentation(current, previous, desired, ...preservedOwnership) {
|
|
1038
1310
|
const ownership = mergePresentationOwnership(...preservedOwnership);
|
|
@@ -1068,43 +1340,49 @@ function patchElementShellPresentation(current, previous, desired, ...preservedO
|
|
|
1068
1340
|
else
|
|
1069
1341
|
current.removeAttribute(name);
|
|
1070
1342
|
}
|
|
1071
|
-
const
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
if (previousHas) {
|
|
1093
|
-
if (!currentPropertyNames.has(name)
|
|
1094
|
-
|| current.style.getPropertyValue(name) !== previousValue
|
|
1095
|
-
|| current.style.getPropertyPriority(name) !== previousPriority) {
|
|
1343
|
+
const resumeDatePickerPadding = datePickerRowPaddingPatches.get(current)?.();
|
|
1344
|
+
try {
|
|
1345
|
+
const previousPropertyNames = stylePropertyNames(previous.style);
|
|
1346
|
+
const desiredPropertyNames = stylePropertyNames(desired.style);
|
|
1347
|
+
const propertyNames = new Set([
|
|
1348
|
+
...previousPropertyNames,
|
|
1349
|
+
...desiredPropertyNames,
|
|
1350
|
+
]);
|
|
1351
|
+
const currentPropertyNames = stylePropertyNames(current.style);
|
|
1352
|
+
for (const name of propertyNames) {
|
|
1353
|
+
if (layoutStyleProperties.has(name))
|
|
1354
|
+
continue;
|
|
1355
|
+
const previousHas = previousPropertyNames.has(name);
|
|
1356
|
+
const desiredHas = desiredPropertyNames.has(name);
|
|
1357
|
+
const previousValue = previous.style.getPropertyValue(name);
|
|
1358
|
+
const desiredValue = desired.style.getPropertyValue(name);
|
|
1359
|
+
const previousPriority = previous.style.getPropertyPriority(name);
|
|
1360
|
+
const desiredPriority = desired.style.getPropertyPriority(name);
|
|
1361
|
+
if (previousHas === desiredHas
|
|
1362
|
+
&& previousValue === desiredValue
|
|
1363
|
+
&& previousPriority === desiredPriority) {
|
|
1096
1364
|
continue;
|
|
1097
1365
|
}
|
|
1366
|
+
if (previousHas) {
|
|
1367
|
+
if (!currentPropertyNames.has(name)
|
|
1368
|
+
|| current.style.getPropertyValue(name) !== previousValue
|
|
1369
|
+
|| current.style.getPropertyPriority(name) !== previousPriority) {
|
|
1370
|
+
continue;
|
|
1371
|
+
}
|
|
1372
|
+
}
|
|
1373
|
+
else if (currentPropertyNames.has(name)) {
|
|
1374
|
+
continue;
|
|
1375
|
+
}
|
|
1376
|
+
if (desiredHas) {
|
|
1377
|
+
current.style.setProperty(name, desiredValue, desiredPriority);
|
|
1378
|
+
}
|
|
1379
|
+
else {
|
|
1380
|
+
current.style.removeProperty(name);
|
|
1381
|
+
}
|
|
1098
1382
|
}
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
if (desiredHas) {
|
|
1103
|
-
current.style.setProperty(name, desiredValue, desiredPriority);
|
|
1104
|
-
}
|
|
1105
|
-
else {
|
|
1106
|
-
current.style.removeProperty(name);
|
|
1107
|
-
}
|
|
1383
|
+
}
|
|
1384
|
+
finally {
|
|
1385
|
+
resumeDatePickerPadding?.();
|
|
1108
1386
|
}
|
|
1109
1387
|
}
|
|
1110
1388
|
/** Release slot-owned item listeners within a disposed subtree. */
|
|
@@ -1391,15 +1669,29 @@ function renderHorizontalScrollSlot(container, children, slotContent, renderChil
|
|
|
1391
1669
|
e.preventDefault();
|
|
1392
1670
|
track.scrollLeft = scrollLeft - (e.pageX - startX);
|
|
1393
1671
|
};
|
|
1394
|
-
const
|
|
1672
|
+
const cancelDrag = () => {
|
|
1395
1673
|
if (!isDragging)
|
|
1396
1674
|
return;
|
|
1397
1675
|
isDragging = false;
|
|
1398
1676
|
track.style.cursor = 'grab';
|
|
1399
1677
|
track.style.removeProperty('user-select');
|
|
1678
|
+
};
|
|
1679
|
+
const stopDrag = () => {
|
|
1680
|
+
if (!isDragging)
|
|
1681
|
+
return;
|
|
1682
|
+
cancelDrag();
|
|
1400
1683
|
if (snap)
|
|
1401
1684
|
track.style.scrollSnapType = 'x mandatory';
|
|
1402
1685
|
};
|
|
1686
|
+
// Leave snap suspended on disable so the viewport does not jump. The next
|
|
1687
|
+
// normal drag/wheel completion restores it.
|
|
1688
|
+
ownerCleanup.add(registerCardDisableCleanup(track, () => {
|
|
1689
|
+
cancelDrag();
|
|
1690
|
+
if (wheelTimer) {
|
|
1691
|
+
window.clearTimeout(wheelTimer);
|
|
1692
|
+
wheelTimer = 0;
|
|
1693
|
+
}
|
|
1694
|
+
}));
|
|
1403
1695
|
addSlotOwnerListener(ownerCleanup, track, 'mousedown', handleMouseDown);
|
|
1404
1696
|
addSlotOwnerListener(ownerCleanup, track, 'mousemove', handleMouseMove);
|
|
1405
1697
|
addSlotOwnerListener(ownerCleanup, track, 'mouseup', stopDrag);
|
|
@@ -1963,6 +2255,7 @@ function renderCarouselSlot(container, children, _slotContent, props, renderChil
|
|
|
1963
2255
|
let isDragging = false;
|
|
1964
2256
|
let startX = 0;
|
|
1965
2257
|
let scrollStart = 0;
|
|
2258
|
+
let wheelTimer = 0;
|
|
1966
2259
|
const handleMouseDown = (event) => {
|
|
1967
2260
|
if (ownerDisposed)
|
|
1968
2261
|
return;
|
|
@@ -1993,12 +2286,46 @@ function renderCarouselSlot(container, children, _slotContent, props, renderChil
|
|
|
1993
2286
|
if (!ownerDisposed)
|
|
1994
2287
|
snapToNearest();
|
|
1995
2288
|
};
|
|
2289
|
+
ownerCleanup.add(registerCardDisableCleanup(container, () => {
|
|
2290
|
+
if (isDragging) {
|
|
2291
|
+
isDragging = false;
|
|
2292
|
+
container.style.cursor = 'grab';
|
|
2293
|
+
}
|
|
2294
|
+
if (wheelTimer) {
|
|
2295
|
+
window.clearTimeout(wheelTimer);
|
|
2296
|
+
wheelTimer = 0;
|
|
2297
|
+
}
|
|
2298
|
+
const wasSnapping = pendingSnapScrollEnd !== null || pendingSnapTimer !== 0;
|
|
2299
|
+
clearPendingSnap();
|
|
2300
|
+
// Cancel the browser's in-flight animation as well as its completion callbacks.
|
|
2301
|
+
// The next normal interaction restores snap through snapToNearest.
|
|
2302
|
+
if (wasSnapping) {
|
|
2303
|
+
const left = container.scrollLeft;
|
|
2304
|
+
const overflowX = container.style.getPropertyValue('overflow-x');
|
|
2305
|
+
const priority = container.style.getPropertyPriority('overflow-x');
|
|
2306
|
+
// Safari can deliver a stale compositor frame after scrollTo('instant').
|
|
2307
|
+
// Flush the scroll-container change synchronously so no delayed correction
|
|
2308
|
+
// can overwrite a fresh gesture or API navigation after re-enabling.
|
|
2309
|
+
container.style.setProperty('overflow-x', 'hidden', 'important');
|
|
2310
|
+
try {
|
|
2311
|
+
void container.offsetWidth;
|
|
2312
|
+
container.scrollTo({ left, behavior: 'instant' });
|
|
2313
|
+
}
|
|
2314
|
+
finally {
|
|
2315
|
+
if (overflowX)
|
|
2316
|
+
container.style.setProperty('overflow-x', overflowX, priority);
|
|
2317
|
+
else
|
|
2318
|
+
container.style.removeProperty('overflow-x');
|
|
2319
|
+
}
|
|
2320
|
+
void container.offsetWidth;
|
|
2321
|
+
container.scrollTo({ left, behavior: 'instant' });
|
|
2322
|
+
}
|
|
2323
|
+
}));
|
|
1996
2324
|
addSlotOwnerListener(ownerCleanup, container, 'mousedown', handleMouseDown);
|
|
1997
2325
|
addSlotOwnerListener(ownerCleanup, document, 'mousemove', handleMouseMove);
|
|
1998
2326
|
addSlotOwnerListener(ownerCleanup, document, 'mouseup', handleMouseUp);
|
|
1999
2327
|
addSlotOwnerListener(ownerCleanup, container, 'touchend', handleTouchEnd, { passive: true });
|
|
2000
2328
|
// Wheel support
|
|
2001
|
-
let wheelTimer = 0;
|
|
2002
2329
|
const handleWheel = (event) => {
|
|
2003
2330
|
if (ownerDisposed)
|
|
2004
2331
|
return;
|
|
@@ -2396,6 +2723,8 @@ class BaseElement extends HTMLElement {
|
|
|
2396
2723
|
this._responsive = createResponsiveContext(this._isMobile, this._responsiveOptions);
|
|
2397
2724
|
this.render();
|
|
2398
2725
|
}
|
|
2726
|
+
/** @internal Close temporary interaction UI without clearing component values. */
|
|
2727
|
+
closeTransientUI() { }
|
|
2399
2728
|
// ─── Helpers ────────────────────────────────────────────────
|
|
2400
2729
|
/** Convert any content value to a safe display string. */
|
|
2401
2730
|
resolveContent(content) {
|
|
@@ -3856,7 +4185,8 @@ class CardInput extends BaseElement {
|
|
|
3856
4185
|
requestAutoFocus() {
|
|
3857
4186
|
if (!this.isConnected
|
|
3858
4187
|
|| !this._props.autoFocus
|
|
3859
|
-
|| this.hasAttribute('data-disabled')
|
|
4188
|
+
|| this.hasAttribute('data-disabled')
|
|
4189
|
+
|| isCardDisabled(this)) {
|
|
3860
4190
|
return false;
|
|
3861
4191
|
}
|
|
3862
4192
|
const control = this.shadowRoot?.querySelector('.card-input');
|
|
@@ -4182,6 +4512,10 @@ class CardImage extends BaseElement {
|
|
|
4182
4512
|
document.body.style.overflow = '';
|
|
4183
4513
|
document.removeEventListener('keydown', this._handleEscape);
|
|
4184
4514
|
}
|
|
4515
|
+
closeTransientUI() {
|
|
4516
|
+
if (this._lightbox?.classList.contains('open'))
|
|
4517
|
+
this.closeLightbox(this._lightbox);
|
|
4518
|
+
}
|
|
4185
4519
|
disconnectedCallback() {
|
|
4186
4520
|
// Ensure body overflow is restored when element is removed
|
|
4187
4521
|
document.body.style.overflow = '';
|
|
@@ -5118,6 +5452,9 @@ class CardSelect extends BaseElement {
|
|
|
5118
5452
|
});
|
|
5119
5453
|
});
|
|
5120
5454
|
}
|
|
5455
|
+
closeTransientUI() {
|
|
5456
|
+
this._setOpen(false);
|
|
5457
|
+
}
|
|
5121
5458
|
disconnectedCallback() {
|
|
5122
5459
|
document.removeEventListener('click', this._onDocClick);
|
|
5123
5460
|
}
|
|
@@ -7222,17 +7559,85 @@ const CHEVRON_ICON = `
|
|
|
7222
7559
|
<svg viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
|
7223
7560
|
<path d="M2.5 4.5L6 8l3.5-3.5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/>
|
|
7224
7561
|
</svg>`;
|
|
7562
|
+
// Opening another picker starts before the document click closes the first one.
|
|
7563
|
+
// Share the row reservation so that this overlap cannot accumulate padding.
|
|
7564
|
+
const mobilePanelRows = new WeakMap();
|
|
7565
|
+
function updateRowSpace(row, space) {
|
|
7566
|
+
// Preserve host style changes made while the calendar owns extra padding.
|
|
7567
|
+
const padding = row.style.getPropertyValue('padding-bottom');
|
|
7568
|
+
const priority = row.style.getPropertyPriority('padding-bottom');
|
|
7569
|
+
if (padding !== space.appliedPaddingBottom || priority !== space.priority) {
|
|
7570
|
+
space.paddingBottom = padding;
|
|
7571
|
+
space.priority = priority;
|
|
7572
|
+
space.basePaddingBottom = padding || getComputedStyle(row).paddingBottom;
|
|
7573
|
+
}
|
|
7574
|
+
if (space.panels.size) {
|
|
7575
|
+
const height = Math.max(...space.panels.values());
|
|
7576
|
+
row.style.setProperty('padding-bottom', `calc(${space.basePaddingBottom} + ${height}px)`, space.priority);
|
|
7577
|
+
}
|
|
7578
|
+
else {
|
|
7579
|
+
if (space.paddingBottom)
|
|
7580
|
+
row.style.setProperty('padding-bottom', space.paddingBottom, space.priority);
|
|
7581
|
+
else
|
|
7582
|
+
row.style.removeProperty('padding-bottom');
|
|
7583
|
+
mobilePanelRows.delete(row);
|
|
7584
|
+
space.releasePatch();
|
|
7585
|
+
}
|
|
7586
|
+
// CSSOM can simplify calc(); compare its serialized value on the next write.
|
|
7587
|
+
space.appliedPaddingBottom = row.style.getPropertyValue('padding-bottom');
|
|
7588
|
+
}
|
|
7225
7589
|
class CardDatePicker extends BaseElement {
|
|
7226
7590
|
constructor() {
|
|
7227
7591
|
super(...arguments);
|
|
7228
7592
|
this._open = false;
|
|
7229
7593
|
this._calendar = null;
|
|
7594
|
+
this._panelResizeObserver = null;
|
|
7595
|
+
this._mobilePanelRow = null;
|
|
7230
7596
|
/** Dates picked in the panel; shown until props.value changes externally. */
|
|
7231
7597
|
this._localValue = null;
|
|
7232
7598
|
this._onDocClick = (e) => {
|
|
7233
|
-
if (!
|
|
7599
|
+
if (!e.composedPath().includes(this))
|
|
7234
7600
|
this._setOpen(false);
|
|
7235
7601
|
};
|
|
7602
|
+
this._positionMobilePanel = () => {
|
|
7603
|
+
if (!this._isMobile || !this._open)
|
|
7604
|
+
return;
|
|
7605
|
+
const panel = this.shadowRoot?.querySelector('.panel');
|
|
7606
|
+
const calendar = panel?.querySelector('[data-vc="calendar"]');
|
|
7607
|
+
if (!panel || !calendar)
|
|
7608
|
+
return;
|
|
7609
|
+
this._panelResizeObserver?.observe(calendar);
|
|
7610
|
+
const row = this._mobilePanelRow;
|
|
7611
|
+
if (row) {
|
|
7612
|
+
const style = getComputedStyle(row);
|
|
7613
|
+
const contentBottom = row.getBoundingClientRect().bottom
|
|
7614
|
+
- parseFloat(style.paddingBottom) - parseFloat(style.borderBottomWidth);
|
|
7615
|
+
panel.style.top = `${contentBottom - this.getBoundingClientRect().top}px`;
|
|
7616
|
+
const space = mobilePanelRows.get(row);
|
|
7617
|
+
space.panels.set(this, calendar.getBoundingClientRect().bottom - contentBottom);
|
|
7618
|
+
updateRowSpace(row, space);
|
|
7619
|
+
}
|
|
7620
|
+
panel.style.left = '0px';
|
|
7621
|
+
const bounds = calendar.getBoundingClientRect();
|
|
7622
|
+
let left = 0;
|
|
7623
|
+
let right = document.documentElement.clientWidth;
|
|
7624
|
+
// Intersect clipping ancestors, crossing shadow roots when cards are embedded.
|
|
7625
|
+
let ancestor = this.shadowRoot.host;
|
|
7626
|
+
while (ancestor) {
|
|
7627
|
+
this._panelResizeObserver?.observe(ancestor);
|
|
7628
|
+
if (/^(auto|scroll|hidden|clip)$/.test(getComputedStyle(ancestor).overflowX)) {
|
|
7629
|
+
const rect = ancestor.getBoundingClientRect();
|
|
7630
|
+
const innerLeft = rect.left + ancestor.clientLeft;
|
|
7631
|
+
left = Math.max(left, innerLeft);
|
|
7632
|
+
right = Math.min(right, innerLeft + ancestor.clientWidth);
|
|
7633
|
+
}
|
|
7634
|
+
const root = ancestor.getRootNode();
|
|
7635
|
+
ancestor = ancestor.assignedSlot ?? ancestor.parentElement
|
|
7636
|
+
?? (root instanceof ShadowRoot ? root.host : null);
|
|
7637
|
+
}
|
|
7638
|
+
// Shift the panel without changing the trigger's intrinsic width.
|
|
7639
|
+
panel.style.left = `${Math.max(left, Math.min(bounds.left, right - bounds.width)) - bounds.left}px`;
|
|
7640
|
+
};
|
|
7236
7641
|
}
|
|
7237
7642
|
render() {
|
|
7238
7643
|
if (!this.shadowRoot || !this._node)
|
|
@@ -7333,8 +7738,11 @@ class CardDatePicker extends BaseElement {
|
|
|
7333
7738
|
.trigger-arrow.open { transform: rotate(180deg); }
|
|
7334
7739
|
.panel {
|
|
7335
7740
|
display: none;
|
|
7336
|
-
|
|
7337
|
-
|
|
7741
|
+
/* Column layouts include the calendar in flow. Horizontal flex rows
|
|
7742
|
+
reserve space below the whole row when the panel is mounted. */
|
|
7743
|
+
position: ${this._isMobile ? 'relative' : 'absolute'};
|
|
7744
|
+
${this._isMobile ? 'margin-top: 4px; contain: inline-size;' : ''}
|
|
7745
|
+
top: ${this._isMobile ? '0' : 'calc(100% + 4px)'};
|
|
7338
7746
|
left: 0;
|
|
7339
7747
|
z-index: 1000;
|
|
7340
7748
|
}
|
|
@@ -7386,6 +7794,9 @@ class CardDatePicker extends BaseElement {
|
|
|
7386
7794
|
this._destroyCalendar();
|
|
7387
7795
|
}
|
|
7388
7796
|
// ─── Private ────────────────────────────────────────────────
|
|
7797
|
+
closeTransientUI() {
|
|
7798
|
+
this._setOpen(false);
|
|
7799
|
+
}
|
|
7389
7800
|
_setOpen(open) {
|
|
7390
7801
|
if (this._open === open)
|
|
7391
7802
|
return;
|
|
@@ -7467,8 +7878,59 @@ class CardDatePicker extends BaseElement {
|
|
|
7467
7878
|
},
|
|
7468
7879
|
});
|
|
7469
7880
|
this._calendar.init();
|
|
7881
|
+
if (this._isMobile) {
|
|
7882
|
+
const row = this.parentElement;
|
|
7883
|
+
if (row && /^(inline-)?flex$/.test(getComputedStyle(row).display)
|
|
7884
|
+
&& /^row/.test(getComputedStyle(row).flexDirection)) {
|
|
7885
|
+
const panel = container.parentElement;
|
|
7886
|
+
panel.style.position = 'absolute';
|
|
7887
|
+
this._mobilePanelRow = row;
|
|
7888
|
+
if (!mobilePanelRows.has(row)) {
|
|
7889
|
+
const space = {
|
|
7890
|
+
paddingBottom: row.style.getPropertyValue('padding-bottom'),
|
|
7891
|
+
priority: row.style.getPropertyPriority('padding-bottom'),
|
|
7892
|
+
basePaddingBottom: row.style.paddingBottom || getComputedStyle(row).paddingBottom,
|
|
7893
|
+
appliedPaddingBottom: row.style.getPropertyValue('padding-bottom'),
|
|
7894
|
+
panels: new Map(),
|
|
7895
|
+
releasePatch: () => { },
|
|
7896
|
+
};
|
|
7897
|
+
mobilePanelRows.set(row, space);
|
|
7898
|
+
space.releasePatch = registerDatePickerRowPaddingPatch(row, () => {
|
|
7899
|
+
// Make the schema's baseline visible to the incremental style diff.
|
|
7900
|
+
// If a host already replaced our value, leave that external style.
|
|
7901
|
+
if (row.style.getPropertyValue('padding-bottom') === space.appliedPaddingBottom
|
|
7902
|
+
&& row.style.getPropertyPriority('padding-bottom') === space.priority) {
|
|
7903
|
+
if (space.paddingBottom)
|
|
7904
|
+
row.style.setProperty('padding-bottom', space.paddingBottom, space.priority);
|
|
7905
|
+
else
|
|
7906
|
+
row.style.removeProperty('padding-bottom');
|
|
7907
|
+
space.appliedPaddingBottom = row.style.getPropertyValue('padding-bottom');
|
|
7908
|
+
}
|
|
7909
|
+
return () => updateRowSpace(row, space);
|
|
7910
|
+
});
|
|
7911
|
+
}
|
|
7912
|
+
}
|
|
7913
|
+
if (typeof ResizeObserver !== 'undefined') {
|
|
7914
|
+
this._panelResizeObserver = new ResizeObserver(this._positionMobilePanel);
|
|
7915
|
+
}
|
|
7916
|
+
// Calendar navigation changes height synchronously, including browsers
|
|
7917
|
+
// without ResizeObserver. Run after the calendar's own click handler.
|
|
7918
|
+
container.parentElement.addEventListener('click', this._positionMobilePanel);
|
|
7919
|
+
window.addEventListener('resize', this._positionMobilePanel);
|
|
7920
|
+
this._positionMobilePanel();
|
|
7921
|
+
}
|
|
7470
7922
|
}
|
|
7471
7923
|
_destroyCalendar() {
|
|
7924
|
+
window.removeEventListener('resize', this._positionMobilePanel);
|
|
7925
|
+
this.shadowRoot?.querySelector('.panel')?.removeEventListener('click', this._positionMobilePanel);
|
|
7926
|
+
this._panelResizeObserver?.disconnect();
|
|
7927
|
+
this._panelResizeObserver = null;
|
|
7928
|
+
if (this._mobilePanelRow) {
|
|
7929
|
+
const space = mobilePanelRows.get(this._mobilePanelRow);
|
|
7930
|
+
space.panels.delete(this);
|
|
7931
|
+
updateRowSpace(this._mobilePanelRow, space);
|
|
7932
|
+
this._mobilePanelRow = null;
|
|
7933
|
+
}
|
|
7472
7934
|
if (this._calendar) {
|
|
7473
7935
|
this._calendar.destroy();
|
|
7474
7936
|
this._calendar = null;
|
|
@@ -8972,7 +9434,7 @@ function createCardNodeAccess(container) {
|
|
|
8972
9434
|
},
|
|
8973
9435
|
focus(options) {
|
|
8974
9436
|
const element = resolveElement(id);
|
|
8975
|
-
if (!element || element.hasAttribute('data-disabled'))
|
|
9437
|
+
if (!element || element.hasAttribute('data-disabled') || isCardDisabled(element))
|
|
8976
9438
|
return false;
|
|
8977
9439
|
const target = element.shadowRoot
|
|
8978
9440
|
?.querySelector(FOCUS_TARGET_SELECTOR) ?? element;
|
|
@@ -9193,28 +9655,15 @@ function createCardNodeAccess(container) {
|
|
|
9193
9655
|
}
|
|
9194
9656
|
|
|
9195
9657
|
const DISABLED_MARKER = 'data-copilot-card-disabled';
|
|
9196
|
-
const DISABLED_STYLES_MARKER = 'data-copilot-card-disabled-styles';
|
|
9197
|
-
const DISABLED_PRESENTATION_CSS = `
|
|
9198
|
-
[${DISABLED_MARKER}="true"] {
|
|
9199
|
-
background-color: var(--card-disabled-background, #F5F5F5) !important;
|
|
9200
|
-
color: var(--card-disabled-foreground, #C0C0C0) !important;
|
|
9201
|
-
}
|
|
9202
|
-
`;
|
|
9203
|
-
function ensureDisabledPresentationStyles(ownerDocument) {
|
|
9204
|
-
if (ownerDocument.head.querySelector(`style[${DISABLED_STYLES_MARKER}]`)) {
|
|
9205
|
-
return;
|
|
9206
|
-
}
|
|
9207
|
-
const style = ownerDocument.createElement('style');
|
|
9208
|
-
style.setAttribute(DISABLED_STYLES_MARKER, '');
|
|
9209
|
-
style.textContent = DISABLED_PRESENTATION_CSS;
|
|
9210
|
-
ownerDocument.head.appendChild(style);
|
|
9211
|
-
}
|
|
9212
9658
|
function applyDisabledState(element, disabled) {
|
|
9213
9659
|
if (!disabled)
|
|
9214
9660
|
return;
|
|
9215
|
-
ensureDisabledPresentationStyles(element.ownerDocument);
|
|
9216
9661
|
element.setAttribute('data-disabled', 'true');
|
|
9217
9662
|
element.setAttribute(DISABLED_MARKER, 'true');
|
|
9663
|
+
// Inline declarations work inside host ShadowRoots too. Use the shorthand
|
|
9664
|
+
// to mask background images/gradients, matching the historical disabled state.
|
|
9665
|
+
element.style.background = 'var(--card-disabled-background, #F5F5F5)';
|
|
9666
|
+
element.style.color = 'var(--card-disabled-foreground, #C0C0C0)';
|
|
9218
9667
|
element.style.pointerEvents = 'none';
|
|
9219
9668
|
element.style.cursor = 'default';
|
|
9220
9669
|
}
|
|
@@ -9479,6 +9928,7 @@ function renderBoundCard(container, schema, options) {
|
|
|
9479
9928
|
},
|
|
9480
9929
|
events,
|
|
9481
9930
|
isActive: () => (!disposed
|
|
9931
|
+
&& !cardDisabled.isDisabled
|
|
9482
9932
|
&& !publishing
|
|
9483
9933
|
&& container.contains(element)),
|
|
9484
9934
|
});
|
|
@@ -9982,7 +10432,12 @@ function renderBoundCard(container, schema, options) {
|
|
|
9982
10432
|
try {
|
|
9983
10433
|
for (const [occurrenceKey, plan] of appendPlans) {
|
|
9984
10434
|
const prepared = findPreparedByOccurrenceKey(preparedRoot, occurrenceKey);
|
|
9985
|
-
|
|
10435
|
+
// Hidden or force-replaced ancestors prune their descendants from the
|
|
10436
|
+
// prepared tree. Their normal replacement commits the new variables;
|
|
10437
|
+
// there is no live descendant append to prepare in this transaction.
|
|
10438
|
+
if (!prepared)
|
|
10439
|
+
continue;
|
|
10440
|
+
if (!prepared[REPEAT_APPEND]) {
|
|
9986
10441
|
throw new Error(`[renderCard] Missing prepared repeat append owner "${occurrenceKey}"`);
|
|
9987
10442
|
}
|
|
9988
10443
|
const nextOccurrenceKeys = occurrenceKeysForChildren(plan.current.occurrenceKey, plan.nextNode.children);
|
|
@@ -10463,7 +10918,7 @@ function renderBoundCard(container, schema, options) {
|
|
|
10463
10918
|
error.failures = failures;
|
|
10464
10919
|
return error;
|
|
10465
10920
|
}
|
|
10466
|
-
function
|
|
10921
|
+
function commitIncrementalCandidateContent(candidate, renderVariables) {
|
|
10467
10922
|
const replacements = candidate.replacementRoots;
|
|
10468
10923
|
try {
|
|
10469
10924
|
if (!currentMountedTree) {
|
|
@@ -10655,6 +11110,9 @@ function renderBoundCard(container, schema, options) {
|
|
|
10655
11110
|
disposeCandidate(candidate);
|
|
10656
11111
|
}
|
|
10657
11112
|
}
|
|
11113
|
+
function commitIncrementalCandidate(candidate, renderVariables) {
|
|
11114
|
+
return cardDisabled.update(() => commitIncrementalCandidateContent(candidate, renderVariables));
|
|
11115
|
+
}
|
|
10658
11116
|
function assertCurrentRevision(baseRevision) {
|
|
10659
11117
|
if (disposed || publishing || revision !== baseRevision) {
|
|
10660
11118
|
const error = new Error('[renderCard] BOUND_TRANSACTION_CONFLICT');
|
|
@@ -10662,7 +11120,7 @@ function renderBoundCard(container, schema, options) {
|
|
|
10662
11120
|
throw error;
|
|
10663
11121
|
}
|
|
10664
11122
|
}
|
|
10665
|
-
function
|
|
11123
|
+
function commitDraftContent(before, draft, baseRevision) {
|
|
10666
11124
|
assertCurrentRevision(baseRevision);
|
|
10667
11125
|
const validationRoot = cloneJsonData(variables);
|
|
10668
11126
|
replaceRootContents(validationRoot, draft);
|
|
@@ -10716,6 +11174,9 @@ function renderBoundCard(container, schema, options) {
|
|
|
10716
11174
|
reconcileLifecycles(selectLifecycleNodes(currentMaterialized, collectMountedLifecycleIds(currentMountedTree)));
|
|
10717
11175
|
applyAutoFocus(candidate);
|
|
10718
11176
|
}
|
|
11177
|
+
function commitDraft(before, draft, baseRevision) {
|
|
11178
|
+
return cardDisabled.update(() => commitDraftContent(before, draft, baseRevision));
|
|
11179
|
+
}
|
|
10719
11180
|
function writeDraftVariable(draft, key, value) {
|
|
10720
11181
|
Object.defineProperty(draft, String(key), {
|
|
10721
11182
|
value,
|
|
@@ -10772,7 +11233,7 @@ function renderBoundCard(container, schema, options) {
|
|
|
10772
11233
|
};
|
|
10773
11234
|
}
|
|
10774
11235
|
async function runBoundEvent(runtimeId, eventName, eventDetail, baseRevision, repeatTargetFingerprint) {
|
|
10775
|
-
if (disposed)
|
|
11236
|
+
if (disposed || cardDisabled.isDisabled)
|
|
10776
11237
|
return;
|
|
10777
11238
|
assertCurrentRevision(baseRevision);
|
|
10778
11239
|
const transactionBefore = cloneJsonData(variables);
|
|
@@ -10808,13 +11269,14 @@ function renderBoundCard(container, schema, options) {
|
|
|
10808
11269
|
commitDraft(cloneJsonData(lastPublishedVariables), draft, baseRevision);
|
|
10809
11270
|
}
|
|
10810
11271
|
function enqueueBoundEvent(runtimeId, eventName, eventDetail, repeatTargetFingerprint) {
|
|
10811
|
-
if (disposed)
|
|
11272
|
+
if (disposed || cardDisabled.isDisabled)
|
|
10812
11273
|
return;
|
|
11274
|
+
const interactionEpoch = cardDisabled.epoch;
|
|
10813
11275
|
const enqueueRevision = revision;
|
|
10814
11276
|
const queuedBehindAnotherAction = queuedActionCount > 0;
|
|
10815
11277
|
queuedActionCount += 1;
|
|
10816
11278
|
actionQueue = actionQueue
|
|
10817
|
-
.then(() => runBoundEvent(runtimeId, eventName, eventDetail, queuedBehindAnotherAction ? revision : enqueueRevision, repeatTargetFingerprint))
|
|
11279
|
+
.then(() => interactionEpoch === cardDisabled.epoch ? runBoundEvent(runtimeId, eventName, eventDetail, queuedBehindAnotherAction ? revision : enqueueRevision, repeatTargetFingerprint) : undefined)
|
|
10818
11280
|
.catch((error) => {
|
|
10819
11281
|
if (error
|
|
10820
11282
|
&& typeof error === 'object'
|
|
@@ -10846,6 +11308,7 @@ function renderBoundCard(container, schema, options) {
|
|
|
10846
11308
|
disposed = true;
|
|
10847
11309
|
disposeRequested = false;
|
|
10848
11310
|
nodeAccess.dispose();
|
|
11311
|
+
cardDisabled.dispose();
|
|
10849
11312
|
abortController.abort();
|
|
10850
11313
|
if (currentMountedTree) {
|
|
10851
11314
|
disposeBoundSubtree(currentMountedTree);
|
|
@@ -10883,17 +11346,26 @@ function renderBoundCard(container, schema, options) {
|
|
|
10883
11346
|
console.error('[renderCard] Bound lifecycle dispose failed', error);
|
|
10884
11347
|
});
|
|
10885
11348
|
}
|
|
10886
|
-
const
|
|
10887
|
-
publishing = true;
|
|
11349
|
+
const cardDisabled = createCardDisabledController(container, options.disabled);
|
|
10888
11350
|
try {
|
|
10889
|
-
|
|
10890
|
-
|
|
11351
|
+
const initialCandidate = prepareIncrementalCandidate(variables, variables);
|
|
11352
|
+
publishing = true;
|
|
11353
|
+
try {
|
|
11354
|
+
currentMountedTree = commitIncrementalCandidate(initialCandidate, variables);
|
|
11355
|
+
currentMaterialized = materializeCard(schema, variables);
|
|
11356
|
+
}
|
|
11357
|
+
finally {
|
|
11358
|
+
publishing = false;
|
|
11359
|
+
}
|
|
11360
|
+
reconcileLifecycles(selectLifecycleNodes(currentMaterialized, collectMountedLifecycleIds(currentMountedTree)));
|
|
10891
11361
|
}
|
|
10892
|
-
|
|
10893
|
-
|
|
11362
|
+
catch (error) {
|
|
11363
|
+
nodeAccess.dispose();
|
|
11364
|
+
cardDisabled.dispose();
|
|
11365
|
+
throw error;
|
|
10894
11366
|
}
|
|
10895
|
-
reconcileLifecycles(selectLifecycleNodes(currentMaterialized, collectMountedLifecycleIds(currentMountedTree)));
|
|
10896
11367
|
return {
|
|
11368
|
+
setDisabled: cardDisabled.setDisabled,
|
|
10897
11369
|
getNode: nodeAccess.getNode,
|
|
10898
11370
|
onFocusChange: nodeAccess.onFocusChange,
|
|
10899
11371
|
onScroll: nodeAccess.onScroll,
|
|
@@ -11261,7 +11733,7 @@ function renderStaticCard(container, schema, options) {
|
|
|
11261
11733
|
};
|
|
11262
11734
|
}
|
|
11263
11735
|
function runStaticEventActions(steps, detail) {
|
|
11264
|
-
if (disposed)
|
|
11736
|
+
if (disposed || cardDisabled.isDisabled)
|
|
11265
11737
|
return;
|
|
11266
11738
|
if (detail != null)
|
|
11267
11739
|
variables._event = detail;
|
|
@@ -11400,6 +11872,7 @@ function renderStaticCard(container, schema, options) {
|
|
|
11400
11872
|
},
|
|
11401
11873
|
events: resolvedEventBindings,
|
|
11402
11874
|
isActive: () => (!disposed
|
|
11875
|
+
&& !cardDisabled.isDisabled
|
|
11403
11876
|
&& !publishing
|
|
11404
11877
|
&& container.contains(element)),
|
|
11405
11878
|
});
|
|
@@ -11598,7 +12071,7 @@ function renderStaticCard(container, schema, options) {
|
|
|
11598
12071
|
}
|
|
11599
12072
|
}
|
|
11600
12073
|
}
|
|
11601
|
-
function
|
|
12074
|
+
function renderContent() {
|
|
11602
12075
|
if (disposed)
|
|
11603
12076
|
return;
|
|
11604
12077
|
const generation = ++renderGeneration;
|
|
@@ -11692,6 +12165,9 @@ function renderStaticCard(container, schema, options) {
|
|
|
11692
12165
|
startLifecycleMount(id, lifecycle);
|
|
11693
12166
|
}
|
|
11694
12167
|
}
|
|
12168
|
+
function render() {
|
|
12169
|
+
return cardDisabled.update(() => renderContent());
|
|
12170
|
+
}
|
|
11695
12171
|
function rerender() {
|
|
11696
12172
|
if (disposed)
|
|
11697
12173
|
return;
|
|
@@ -11705,6 +12181,7 @@ function renderStaticCard(container, schema, options) {
|
|
|
11705
12181
|
disposeRequested = false;
|
|
11706
12182
|
hostAuthorityEpoch += 1;
|
|
11707
12183
|
nodeAccess.dispose();
|
|
12184
|
+
cardDisabled.dispose();
|
|
11708
12185
|
abortController.abort();
|
|
11709
12186
|
if (mountedTree) {
|
|
11710
12187
|
disposeStaticSubtree(mountedTree);
|
|
@@ -11718,9 +12195,18 @@ function renderStaticCard(container, schema, options) {
|
|
|
11718
12195
|
destroyLifecycle(record);
|
|
11719
12196
|
}
|
|
11720
12197
|
// 7. Initial render
|
|
11721
|
-
|
|
12198
|
+
const cardDisabled = createCardDisabledController(container, options.disabled);
|
|
12199
|
+
try {
|
|
12200
|
+
render();
|
|
12201
|
+
}
|
|
12202
|
+
catch (error) {
|
|
12203
|
+
nodeAccess.dispose();
|
|
12204
|
+
cardDisabled.dispose();
|
|
12205
|
+
throw error;
|
|
12206
|
+
}
|
|
11722
12207
|
// 8. Return instance handle
|
|
11723
12208
|
return {
|
|
12209
|
+
setDisabled: cardDisabled.setDisabled,
|
|
11724
12210
|
getNode: nodeAccess.getNode,
|
|
11725
12211
|
onFocusChange: nodeAccess.onFocusChange,
|
|
11726
12212
|
onScroll: nodeAccess.onScroll,
|
|
@@ -12101,6 +12587,8 @@ function renderStreamingCard(container, options = {}) {
|
|
|
12101
12587
|
const variableKey = resolvedProps.variableKey;
|
|
12102
12588
|
if (variableKey) {
|
|
12103
12589
|
element.addEventListener('input', ((event) => {
|
|
12590
|
+
if (disposed || cardDisabled.isDisabled || !container.contains(element))
|
|
12591
|
+
return;
|
|
12104
12592
|
if (event.target !== element || !currentMaterialized)
|
|
12105
12593
|
return;
|
|
12106
12594
|
const value = event.detail?.value
|
|
@@ -12116,6 +12604,8 @@ function renderStreamingCard(container, options = {}) {
|
|
|
12116
12604
|
}
|
|
12117
12605
|
const domEvent = eventMap[eventName] ?? eventName;
|
|
12118
12606
|
element.addEventListener(domEvent, ((event) => {
|
|
12607
|
+
if (disposed || cardDisabled.isDisabled || !container.contains(element))
|
|
12608
|
+
return;
|
|
12119
12609
|
const ownsValueEvent = ((domEvent === 'input' || domEvent === 'change')
|
|
12120
12610
|
&& valueControlTypes.has(node.type));
|
|
12121
12611
|
if (ownsValueEvent && event.target !== element)
|
|
@@ -12184,6 +12674,8 @@ function renderStreamingCard(container, options = {}) {
|
|
|
12184
12674
|
const variableKey = resolvedProps.variableKey;
|
|
12185
12675
|
if (variableKey) {
|
|
12186
12676
|
el.addEventListener('input', ((e) => {
|
|
12677
|
+
if (disposed || cardDisabled.isDisabled || !container.contains(el))
|
|
12678
|
+
return;
|
|
12187
12679
|
const value = e.detail?.value
|
|
12188
12680
|
?? e.target?.value;
|
|
12189
12681
|
if (value !== undefined) {
|
|
@@ -12202,6 +12694,8 @@ function renderStreamingCard(container, options = {}) {
|
|
|
12202
12694
|
continue;
|
|
12203
12695
|
const domEvent = eventMap[event] ?? event;
|
|
12204
12696
|
el.addEventListener(domEvent, ((e) => {
|
|
12697
|
+
if (disposed || cardDisabled.isDisabled || !container.contains(el))
|
|
12698
|
+
return;
|
|
12205
12699
|
if (e instanceof CustomEvent && e.detail != null) {
|
|
12206
12700
|
variables._event = e.detail;
|
|
12207
12701
|
}
|
|
@@ -12385,7 +12879,7 @@ function renderStreamingCard(container, options = {}) {
|
|
|
12385
12879
|
* (visibility flips / container shape changes) re-render only their subtree.
|
|
12386
12880
|
* Falls back to a full render solely when a subtree can't be rebuilt.
|
|
12387
12881
|
*/
|
|
12388
|
-
function
|
|
12882
|
+
function diffAllElementsContent(previousVariables) {
|
|
12389
12883
|
actionContext = buildActionContext();
|
|
12390
12884
|
const schema = (currentSurfaceId ? engine.getSchema(currentSurfaceId) : undefined) ?? currentSchema;
|
|
12391
12885
|
if (!schema)
|
|
@@ -12425,6 +12919,8 @@ function renderStreamingCard(container, options = {}) {
|
|
|
12425
12919
|
continue;
|
|
12426
12920
|
if ('updateProps' in el) {
|
|
12427
12921
|
el.updateProps(resolved, isMobile, options.responsive);
|
|
12922
|
+
// Some components replace host cssText while updating their props.
|
|
12923
|
+
applyDisabledState(el, wasDisabled);
|
|
12428
12924
|
propsCache.set(id, key);
|
|
12429
12925
|
}
|
|
12430
12926
|
else if (!replaceSubtree(schema, id, el)) {
|
|
@@ -12435,6 +12931,9 @@ function renderStreamingCard(container, options = {}) {
|
|
|
12435
12931
|
}
|
|
12436
12932
|
applyAutoFocusIds(autoFocusIds);
|
|
12437
12933
|
}
|
|
12934
|
+
function diffAllElements(previousVariables) {
|
|
12935
|
+
return cardDisabled.update(() => diffAllElementsContent(previousVariables));
|
|
12936
|
+
}
|
|
12438
12937
|
function captureBoundScrollPositions(root) {
|
|
12439
12938
|
const positions = new Map();
|
|
12440
12939
|
root.querySelectorAll('[data-scroll-id]').forEach((element) => {
|
|
@@ -12785,7 +13284,7 @@ function renderStreamingCard(container, options = {}) {
|
|
|
12785
13284
|
throw error;
|
|
12786
13285
|
}
|
|
12787
13286
|
}
|
|
12788
|
-
function
|
|
13287
|
+
function commitBoundFullContent(prepared, schema, draft, baseRevision, commitAuthoritativeVariables) {
|
|
12789
13288
|
assertBoundRevision(baseRevision);
|
|
12790
13289
|
commitAuthoritativeVariables?.();
|
|
12791
13290
|
replaceRootContents(variables, draft);
|
|
@@ -12807,6 +13306,9 @@ function renderStreamingCard(container, options = {}) {
|
|
|
12807
13306
|
restoreBoundScrollPositions(container, scrollPositions);
|
|
12808
13307
|
restoreBoundMediaStates(container, mediaStates);
|
|
12809
13308
|
}
|
|
13309
|
+
function commitBoundFull(prepared, schema, draft, baseRevision, commitAuthoritativeVariables) {
|
|
13310
|
+
return cardDisabled.update(() => commitBoundFullContent(prepared, schema, draft, baseRevision, commitAuthoritativeVariables));
|
|
13311
|
+
}
|
|
12810
13312
|
function ownerKeysWithoutNestedDuplicates(materialized, owners) {
|
|
12811
13313
|
const selected = new Set(owners.map(owner => owner.key));
|
|
12812
13314
|
return owners.filter((owner) => {
|
|
@@ -12926,7 +13428,7 @@ function renderStreamingCard(container, options = {}) {
|
|
|
12926
13428
|
replacedLifecycleIds,
|
|
12927
13429
|
};
|
|
12928
13430
|
}
|
|
12929
|
-
function
|
|
13431
|
+
function commitBoundIncrementalContent(prepared, schema, draft, baseRevision, commitAuthoritativeVariables) {
|
|
12930
13432
|
assertBoundRevision(baseRevision);
|
|
12931
13433
|
commitAuthoritativeVariables?.();
|
|
12932
13434
|
replaceRootContents(variables, draft);
|
|
@@ -12957,6 +13459,9 @@ function renderStreamingCard(container, options = {}) {
|
|
|
12957
13459
|
restoreBoundScrollPositions(container, scrollPositions);
|
|
12958
13460
|
restoreBoundMediaStates(container, mediaStates);
|
|
12959
13461
|
}
|
|
13462
|
+
function commitBoundIncremental(prepared, schema, draft, baseRevision, commitAuthoritativeVariables) {
|
|
13463
|
+
return cardDisabled.update(() => commitBoundIncrementalContent(prepared, schema, draft, baseRevision, commitAuthoritativeVariables));
|
|
13464
|
+
}
|
|
12960
13465
|
function prepareAndCommitBoundUpdate(schema, draft, owners, baseRevision, commitAuthoritativeVariables, changedSourceIds = new Set()) {
|
|
12961
13466
|
try {
|
|
12962
13467
|
const prepared = prepareBoundIncremental(schema, draft, owners, changedSourceIds);
|
|
@@ -13136,6 +13641,8 @@ function renderStreamingCard(container, options = {}) {
|
|
|
13136
13641
|
prepareAndCommitBoundUpdate(schema, draft, owners, baseRevision, commitAuthoritative);
|
|
13137
13642
|
}
|
|
13138
13643
|
async function runBoundEvent(runtimeId, eventName, eventDetail) {
|
|
13644
|
+
if (disposed || cardDisabled.isDisabled)
|
|
13645
|
+
return;
|
|
13139
13646
|
if (!currentMaterialized || !currentSchema || !currentSurfaceId)
|
|
13140
13647
|
return;
|
|
13141
13648
|
const baseRevision = boundRevision;
|
|
@@ -13162,8 +13669,12 @@ function renderStreamingCard(container, options = {}) {
|
|
|
13162
13669
|
applyAutoFocusIds(autoFocusIds);
|
|
13163
13670
|
}
|
|
13164
13671
|
function enqueueBoundEvent(runtimeId, eventName, eventDetail) {
|
|
13672
|
+
if (disposed || cardDisabled.isDisabled)
|
|
13673
|
+
return;
|
|
13674
|
+
const interactionEpoch = cardDisabled.epoch;
|
|
13165
13675
|
boundActionQueue = boundActionQueue
|
|
13166
|
-
.then(() =>
|
|
13676
|
+
.then(() => interactionEpoch === cardDisabled.epoch
|
|
13677
|
+
? runBoundEvent(runtimeId, eventName, eventDetail) : undefined)
|
|
13167
13678
|
.catch((error) => {
|
|
13168
13679
|
if (error
|
|
13169
13680
|
&& typeof error === 'object'
|
|
@@ -13338,7 +13849,7 @@ function renderStreamingCard(container, options = {}) {
|
|
|
13338
13849
|
* assigned on createSurface — so newly added components would not render and text
|
|
13339
13850
|
* appended via appendContent would be wiped on the next full re-render.
|
|
13340
13851
|
*/
|
|
13341
|
-
function
|
|
13852
|
+
function renderFullContent() {
|
|
13342
13853
|
const engineSchema = currentSurfaceId ? engine.getSchema(currentSurfaceId) : undefined;
|
|
13343
13854
|
const schema = engineSchema ?? currentSchema;
|
|
13344
13855
|
if (!schema)
|
|
@@ -13365,6 +13876,9 @@ function renderStreamingCard(container, options = {}) {
|
|
|
13365
13876
|
const dom = renderNode(tree);
|
|
13366
13877
|
container.appendChild(dom);
|
|
13367
13878
|
}
|
|
13879
|
+
function renderFull() {
|
|
13880
|
+
return cardDisabled.update(() => renderFullContent());
|
|
13881
|
+
}
|
|
13368
13882
|
/**
|
|
13369
13883
|
* Full render that tolerates mid-stream schemas (e.g. children referencing
|
|
13370
13884
|
* elements that have not arrived yet): keeps the previous DOM on failure so
|
|
@@ -13381,7 +13895,7 @@ function renderStreamingCard(container, options = {}) {
|
|
|
13381
13895
|
}
|
|
13382
13896
|
}
|
|
13383
13897
|
// ─── Engine Event Handlers ──────────────────────────────────────
|
|
13384
|
-
const
|
|
13898
|
+
const engineEvents = {
|
|
13385
13899
|
onSurfaceCreated(surfaceId, schemaInput) {
|
|
13386
13900
|
if (schemaInput) {
|
|
13387
13901
|
const nextSchema = engine.getSchema(surfaceId)
|
|
@@ -13596,6 +14110,7 @@ function renderStreamingCard(container, options = {}) {
|
|
|
13596
14110
|
const typeChanged = el.getAttribute('data-card-type') !== element.type;
|
|
13597
14111
|
if (!typeChanged && 'updateProps' in el) {
|
|
13598
14112
|
el.updateProps(resolved, isMobile, options.responsive);
|
|
14113
|
+
applyDisabledState(el, wasDisabled);
|
|
13599
14114
|
propsCache.set(id, key);
|
|
13600
14115
|
}
|
|
13601
14116
|
else if (!typeChanged && isChildrenOnlyChange(propsCache.get(id), key, element)) {
|
|
@@ -13746,9 +14261,18 @@ function renderStreamingCard(container, options = {}) {
|
|
|
13746
14261
|
boundRevision += 1;
|
|
13747
14262
|
lifecycleManager.dispose(actionContext);
|
|
13748
14263
|
},
|
|
14264
|
+
};
|
|
14265
|
+
const engine = new StreamingEngine({
|
|
14266
|
+
onSurfaceCreated: (...args) => cardDisabled.update(() => engineEvents.onSurfaceCreated?.(...args)),
|
|
14267
|
+
onComponentsUpdated: (...args) => cardDisabled.update(() => engineEvents.onComponentsUpdated?.(...args)),
|
|
14268
|
+
onDataModelUpdated: (...args) => cardDisabled.update(() => engineEvents.onDataModelUpdated?.(...args)),
|
|
14269
|
+
onContentAppended: (...args) => cardDisabled.update(() => engineEvents.onContentAppended?.(...args)),
|
|
14270
|
+
onSurfaceDeleted: (...args) => cardDisabled.update(() => engineEvents.onSurfaceDeleted?.(...args)),
|
|
13749
14271
|
});
|
|
13750
14272
|
// ─── Public API ─────────────────────────────────────────────────
|
|
14273
|
+
const cardDisabled = createCardDisabledController(container, options.disabled);
|
|
13751
14274
|
return {
|
|
14275
|
+
setDisabled: cardDisabled.setDisabled,
|
|
13752
14276
|
getNode: nodeAccess.getNode,
|
|
13753
14277
|
onFocusChange: nodeAccess.onFocusChange,
|
|
13754
14278
|
onScroll: nodeAccess.onScroll,
|
|
@@ -13829,6 +14353,7 @@ function renderStreamingCard(container, options = {}) {
|
|
|
13829
14353
|
return;
|
|
13830
14354
|
disposed = true;
|
|
13831
14355
|
nodeAccess.dispose();
|
|
14356
|
+
cardDisabled.dispose();
|
|
13832
14357
|
boundRevision += 1;
|
|
13833
14358
|
abortController.abort();
|
|
13834
14359
|
teardownBoundLifecycles();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@antglobal/copilot-cards-web",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.20260915071159-dev.5",
|
|
4
4
|
"description": "Web Component renderer for copilot bot card SDK — PC + Mobile + WebView unified rendering via Custom Elements",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
],
|
|
29
29
|
"license": "MIT",
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@antglobal/copilot-cards-core": "0.0.
|
|
31
|
+
"@antglobal/copilot-cards-core": "0.0.20260915071159-dev.5",
|
|
32
32
|
"echarts": "^5.6.0",
|
|
33
33
|
"marked": "^18.0.5",
|
|
34
34
|
"tslib": "^2.8.1",
|