@antglobal/copilot-cards-web 0.0.20260915071159-dev.1 → 0.0.20260915071159-dev.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -107,7 +107,7 @@ declare function createResponsiveContext(isMobile: boolean, responsive?: Respons
107
107
  */
108
108
 
109
109
  interface RenderCardOptions extends WebActionContextOptions {
110
- /** Disable the whole card using the existing project disabled appearance. Default false. */
110
+ /** Block whole-card interaction and add a configurable overlay without restyling nodes. Default false. */
111
111
  disabled?: boolean;
112
112
  /** Enable mobile component layout explicitly (default false). */
113
113
  isMobile?: boolean;
package/dist/index.js CHANGED
@@ -713,30 +713,9 @@ function buildHeatmapOption(config) {
713
713
  };
714
714
  }
715
715
 
716
- const DISABLED_MARKER = 'data-copilot-card-disabled';
717
- function applyDisabledState(element, disabled) {
718
- if (!disabled)
719
- return;
720
- element.setAttribute('data-disabled', 'true');
721
- element.setAttribute(DISABLED_MARKER, 'true');
722
- // Inline declarations work inside host ShadowRoots too. Use the shorthand
723
- // to mask background images/gradients, matching the historical disabled state.
724
- element.style.background = 'var(--card-disabled-background, #F5F5F5)';
725
- element.style.color = 'var(--card-disabled-foreground, #C0C0C0)';
726
- element.style.pointerEvents = 'none';
727
- element.style.cursor = 'default';
728
- }
729
- function applyDisabledDescendants(element, disabled) {
730
- if (!disabled)
731
- return;
732
- element.querySelectorAll('*').forEach((child) => {
733
- child.setAttribute('data-disabled', 'true');
734
- });
735
- }
736
-
737
716
  const controllers = new WeakMap();
738
717
  const interactionCleanups = new WeakMap();
739
- /** Cancel slot-owned gestures before capturing the disabled presentation. */
718
+ /** Cancel slot-owned gestures before covering the card. */
740
719
  function registerCardDisableCleanup(element, cleanup) {
741
720
  let callbacks = interactionCleanups.get(element);
742
721
  if (!callbacks) {
@@ -762,15 +741,13 @@ const BLOCKED_EVENTS = [
762
741
  'compositionstart', 'compositionupdate', 'compositionend',
763
742
  'choice-request-change', 'choice-navigate',
764
743
  ];
765
- const TOUCH_EVENTS = ['pointerdown', 'pointerup', 'touchstart', 'touchend', 'mousedown', 'mouseup'];
744
+ const TOUCH_EVENTS = ['pointerdown', 'pointerup', 'touchstart', 'touchend', 'mousedown', 'mouseup', 'wheel'];
766
745
  const TAB_TARGETS = [
767
746
  'a[href]', 'area[href]', 'button', 'input', 'select', 'textarea', 'summary',
768
747
  'iframe', 'object', 'embed', 'audio[controls]', 'video[controls]',
769
748
  '[tabindex]', '[contenteditable]:not([contenteditable="false"])',
770
749
  ].join(',');
771
- const VISUAL_ATTRIBUTES = ['data-disabled', 'data-copilot-card-disabled'];
772
- const ownsStyle = (name) => name === 'background' || name.startsWith('background-')
773
- || name === 'color' || name === 'pointer-events' || name === 'cursor';
750
+ const CARD_DISABLED_ATTRIBUTE = 'data-card-disabled';
774
751
  function restoreAttribute(element, name, value) {
775
752
  if (value === null)
776
753
  element.removeAttribute(name);
@@ -784,7 +761,9 @@ function createCardDisabledController(container, initiallyDisabled = false) {
784
761
  let updateDepth = 0;
785
762
  let applyingPresentation = false;
786
763
  let previousAriaDisabled = null;
787
- let snapshots = [];
764
+ let previousDisabledMarker = null;
765
+ let overlay;
766
+ let mountStyles = [];
788
767
  let tabSnapshots = [];
789
768
  let tabObserver;
790
769
  const block = (event) => {
@@ -876,14 +855,39 @@ function createCardDisabledController(container, initiallyDisabled = false) {
876
855
  }
877
856
  function restorePresentation() {
878
857
  restoreTabNavigation();
879
- for (const { element, attributes, styles } of snapshots) {
880
- VISUAL_ATTRIBUTES.forEach((name, index) => restoreAttribute(element, name, attributes[index]));
881
- if (styles) {
882
- Array.from(element.style).filter(ownsStyle).forEach(name => element.style.removeProperty(name));
883
- styles.forEach(([name, value, priority]) => element.style.setProperty(name, value, priority));
884
- }
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);
885
864
  }
886
- snapshots = [];
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);
887
891
  }
888
892
  function applyPresentation() {
889
893
  if (!disabled || disposed || updateDepth > 0 || applyingPresentation)
@@ -891,27 +895,13 @@ function createCardDisabledController(container, initiallyDisabled = false) {
891
895
  applyingPresentation = true;
892
896
  try {
893
897
  // Blur/popup callbacks can synchronously update or toggle the card.
894
- // Always snapshot its current underlying presentation, never our overlay.
898
+ // Reattach only after renderer updates and popup/gesture cleanup finish.
895
899
  restorePresentation();
896
900
  closeTransientUI(container);
897
901
  blurCardInput();
898
902
  if (!disabled || disposed)
899
903
  return;
900
- for (const element of container.querySelectorAll('*')) {
901
- const isRoot = element.parentElement === container;
902
- snapshots.push({
903
- element,
904
- attributes: VISUAL_ATTRIBUTES.map(name => element.getAttribute(name)),
905
- styles: isRoot ? Array.from(element.style).filter(ownsStyle)
906
- .map(name => [name, element.style.getPropertyValue(name), element.style.getPropertyPriority(name)]) : undefined,
907
- });
908
- }
909
- for (const root of Array.from(container.children)) {
910
- if (!(root instanceof HTMLElement))
911
- continue;
912
- applyDisabledState(root, true);
913
- applyDisabledDescendants(root, true);
914
- }
904
+ coverCard();
915
905
  excludeFromTabNavigation(container);
916
906
  }
917
907
  finally {
@@ -946,7 +936,9 @@ function createCardDisabledController(container, initiallyDisabled = false) {
946
936
  epoch += 1;
947
937
  if (disabled) {
948
938
  previousAriaDisabled = container.getAttribute('aria-disabled');
939
+ previousDisabledMarker = container.getAttribute(CARD_DISABLED_ATTRIBUTE);
949
940
  container.setAttribute('aria-disabled', 'true');
941
+ container.setAttribute(CARD_DISABLED_ATTRIBUTE, 'true');
950
942
  listen(true);
951
943
  blurCardInput();
952
944
  applyPresentation();
@@ -954,6 +946,7 @@ function createCardDisabledController(container, initiallyDisabled = false) {
954
946
  else {
955
947
  restorePresentation();
956
948
  restoreAttribute(container, 'aria-disabled', previousAriaDisabled);
949
+ restoreAttribute(container, CARD_DISABLED_ATTRIBUTE, previousDisabledMarker);
957
950
  listen(false);
958
951
  }
959
952
  },
@@ -2912,6 +2905,34 @@ BaseElement.UNITLESS_PROPS = new Set([
2912
2905
  'widows',
2913
2906
  ]);
2914
2907
 
2908
+ /** Marked 18 uses Array.at internally; install it only on runtimes without it. */
2909
+ function ensureArrayAt() {
2910
+ if (typeof Array.prototype.at === 'function')
2911
+ return;
2912
+ // Marked calls this built-in directly; keep the fallback non-enumerable and preserve native implementations.
2913
+ // eslint-disable-next-line no-extend-native
2914
+ Object.defineProperty(Array.prototype, 'at', {
2915
+ configurable: true,
2916
+ writable: true,
2917
+ enumerable: false,
2918
+ // Class methods stay strict in non-module bundles and, like native at, are not constructors.
2919
+ value: class {
2920
+ static at(index) {
2921
+ if (this == null)
2922
+ throw new TypeError('Array.at called on null or undefined');
2923
+ const object = Object(this);
2924
+ const length = Math.min(Math.max(Math.trunc(+object.length) || 0, 0), Number.MAX_SAFE_INTEGER);
2925
+ const relativeIndex = Math.trunc(+index) || 0;
2926
+ const offset = relativeIndex >= 0 ? relativeIndex : length + relativeIndex;
2927
+ return offset < 0 || offset >= length ? undefined : object[offset];
2928
+ }
2929
+ }.at,
2930
+ });
2931
+ const unscopables = Array.prototype[Symbol.unscopables];
2932
+ if (unscopables)
2933
+ unscopables.at = true;
2934
+ }
2935
+
2915
2936
  /**
2916
2937
  * CardText — Custom Element for rendering text content in a card.
2917
2938
  *
@@ -3286,6 +3307,7 @@ class CardText extends BaseElement {
3286
3307
  * Parse markdown to HTML using marked.
3287
3308
  */
3288
3309
  _parseMarkdown(text) {
3310
+ ensureArrayAt();
3289
3311
  const result = marked.parse(text);
3290
3312
  // marked.parse can return string or Promise; we use sync mode
3291
3313
  return typeof result === 'string' ? result : '';
@@ -6529,6 +6551,20 @@ if (typeof customElements !== 'undefined' && !customElements.get(CardLoading.is)
6529
6551
  customElements.define(CardLoading.is, CardLoading);
6530
6552
  }
6531
6553
 
6554
+ /** Replace SDK-owned DOM children on WebViews predating ParentNode.replaceChildren. */
6555
+ function replaceChildren(container, ...children) {
6556
+ if (typeof container.replaceChildren === 'function') {
6557
+ container.replaceChildren(...children);
6558
+ return;
6559
+ }
6560
+ const fragment = container.ownerDocument.createDocumentFragment();
6561
+ for (const child of children)
6562
+ fragment.appendChild(child);
6563
+ while (container.firstChild)
6564
+ container.removeChild(container.firstChild);
6565
+ container.appendChild(fragment);
6566
+ }
6567
+
6532
6568
  const DEFAULT_COLOR = '#1677ff';
6533
6569
  function nonNegative(value) {
6534
6570
  const number = Number(value);
@@ -6709,7 +6745,7 @@ class CardProgress extends BaseElement {
6709
6745
  if (valueText)
6710
6746
  track.setAttribute('aria-valuetext', valueText);
6711
6747
  }
6712
- this.shadowRoot.replaceChildren(styleElement, wrapper);
6748
+ replaceChildren(this.shadowRoot, styleElement, wrapper);
6713
6749
  applyResponsiveStyles(this.shadowRoot, this._responsive);
6714
6750
  }
6715
6751
  buildLegend(segments, position, style, isExpressionResultStyle) {
@@ -9661,6 +9697,27 @@ function createCardNodeAccess(container) {
9661
9697
  };
9662
9698
  }
9663
9699
 
9700
+ const DISABLED_MARKER = 'data-copilot-card-disabled';
9701
+ function applyDisabledState(element, disabled) {
9702
+ if (!disabled)
9703
+ return;
9704
+ element.setAttribute('data-disabled', 'true');
9705
+ element.setAttribute(DISABLED_MARKER, 'true');
9706
+ // Inline declarations work inside host ShadowRoots too. Use the shorthand
9707
+ // to mask background images/gradients, matching the historical disabled state.
9708
+ element.style.background = 'var(--card-disabled-background, #F5F5F5)';
9709
+ element.style.color = 'var(--card-disabled-foreground, #C0C0C0)';
9710
+ element.style.pointerEvents = 'none';
9711
+ element.style.cursor = 'default';
9712
+ }
9713
+ function applyDisabledDescendants(element, disabled) {
9714
+ if (!disabled)
9715
+ return;
9716
+ element.querySelectorAll('*').forEach((child) => {
9717
+ child.setAttribute('data-disabled', 'true');
9718
+ });
9719
+ }
9720
+
9664
9721
  const FORCE_REPLACE = Symbol('bound-force-replace');
9665
9722
  const REPEAT_APPEND = Symbol('bound-repeat-append');
9666
9723
  /**
@@ -10410,7 +10467,7 @@ function renderBoundCard(container, schema, options) {
10410
10467
  for (const suffix of candidate.suffix) {
10411
10468
  disposeBoundSubtreeWithoutThrow(suffix);
10412
10469
  }
10413
- candidate.fragment.replaceChildren();
10470
+ replaceChildren(candidate.fragment);
10414
10471
  candidate.state = 'disposed';
10415
10472
  }
10416
10473
  function prepareRepeatAppendCandidates(preparedRoot, appendPlans, draft) {
@@ -10784,7 +10841,7 @@ function renderBoundCard(container, schema, options) {
10784
10841
  let adoptionThrew = false;
10785
10842
  let adoptionError;
10786
10843
  try {
10787
- container.replaceChildren(element);
10844
+ replaceChildren(container, element);
10788
10845
  }
10789
10846
  catch (error) {
10790
10847
  adoptionThrew = true;
@@ -11303,7 +11360,7 @@ function renderBoundCard(container, schema, options) {
11303
11360
  else {
11304
11361
  disposeChartsIn(container);
11305
11362
  }
11306
- container.replaceChildren();
11363
+ replaceChildren(container);
11307
11364
  const lifecycleNodes = [...activeLifecycleNodes.entries()];
11308
11365
  activeLifecycleNodes.clear();
11309
11366
  lifecycleQueue = lifecycleQueue
@@ -12072,7 +12129,7 @@ function renderStaticCard(container, schema, options) {
12072
12129
  return;
12073
12130
  }
12074
12131
  disposeChartsIn(container);
12075
- container.replaceChildren(initialTree.element);
12132
+ replaceChildren(container, initialTree.element);
12076
12133
  mountedTree = initialTree;
12077
12134
  }
12078
12135
  else {
@@ -12176,7 +12233,7 @@ function renderStaticCard(container, schema, options) {
12176
12233
  else {
12177
12234
  disposeChartsIn(container);
12178
12235
  }
12179
- container.replaceChildren();
12236
+ replaceChildren(container);
12180
12237
  for (const record of lifecycleRecords.values())
12181
12238
  destroyLifecycle(record);
12182
12239
  }
@@ -13278,7 +13335,7 @@ function renderStreamingCard(container, options = {}) {
13278
13335
  const scrollPositions = captureBoundScrollPositions(container);
13279
13336
  const mediaStates = captureBoundMediaStates(container);
13280
13337
  disposeChartsIn(container);
13281
- container.replaceChildren(prepared.dom);
13338
+ replaceChildren(container, prepared.dom);
13282
13339
  replaceProductionIndexes(prepared.indexes);
13283
13340
  currentSchema = schema;
13284
13341
  currentMaterialized = stableMaterialized;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antglobal/copilot-cards-web",
3
- "version": "0.0.20260915071159-dev.1",
3
+ "version": "0.0.20260915071159-dev.9",
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.20260915071159-dev.1",
31
+ "@antglobal/copilot-cards-core": "0.0.20260915071159-dev.9",
32
32
  "echarts": "^5.6.0",
33
33
  "marked": "^18.0.5",
34
34
  "tslib": "^2.8.1",