@adobe/spectrum-wc-core 2.0.0-beta.3 → 2.0.0-beta.4

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.
Files changed (39) hide show
  1. package/README.md +1 -1
  2. package/dist/components/action-group/ActionGroup.base.js +1 -1
  3. package/dist/components/action-group/ActionGroup.base.js.map +1 -1
  4. package/dist/components/asset/Asset.base.d.ts +89 -10
  5. package/dist/components/asset/Asset.base.js +117 -18
  6. package/dist/components/asset/Asset.base.js.map +1 -1
  7. package/dist/components/asset/Asset.types.d.ts +20 -2
  8. package/dist/components/asset/Asset.types.js +10 -2
  9. package/dist/components/asset/Asset.types.js.map +1 -1
  10. package/dist/components/asset/index.js +3 -3
  11. package/dist/components/dropzone/Dropzone.base.d.ts +1 -1
  12. package/dist/components/dropzone/Dropzone.base.js.map +1 -1
  13. package/dist/components/popover/Popover.base.d.ts +1 -21
  14. package/dist/components/popover/Popover.base.js +35 -59
  15. package/dist/components/popover/Popover.base.js.map +1 -1
  16. package/dist/components/tabs/TabPanel.base.d.ts +1 -1
  17. package/dist/components/tabs/TabPanel.base.js.map +1 -1
  18. package/dist/controllers/focusgroup-navigation-controller/src/focusgroup-navigation-controller.d.ts +1 -1
  19. package/dist/controllers/focusgroup-navigation-controller/src/focusgroup-navigation-controller.js.map +1 -1
  20. package/dist/controllers/index.d.ts +2 -1
  21. package/dist/controllers/index.js +2 -1
  22. package/dist/controllers/language-resolution.d.ts +1 -1
  23. package/dist/controllers/language-resolution.js.map +1 -1
  24. package/dist/controllers/trigger-press-controller/index.d.ts +12 -0
  25. package/dist/controllers/trigger-press-controller/index.js +2 -0
  26. package/dist/controllers/trigger-press-controller/src/trigger-press-controller.d.ts +149 -0
  27. package/dist/controllers/trigger-press-controller/src/trigger-press-controller.js +43 -0
  28. package/dist/controllers/trigger-press-controller/src/trigger-press-controller.js.map +1 -0
  29. package/dist/directives/index.d.ts +1 -1
  30. package/dist/element/define-element.js +1 -1
  31. package/dist/element/define-element.js.map +1 -1
  32. package/dist/element/spectrum-element.js +1 -1
  33. package/dist/element/spectrum-element.js.map +1 -1
  34. package/dist/element/version.d.ts +3 -3
  35. package/dist/element/version.js +1 -1
  36. package/dist/element/version.js.map +1 -1
  37. package/dist/utils/resolve-trigger.js.map +1 -1
  38. package/package.json +151 -9
  39. package/CHANGELOG.md +0 -191
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Abstract base classes for Spectrum Web Components.
4
4
 
5
- This package provides the behavior layer for 2nd-gen Spectrum Web Components and is **not intended for direct external use**. It is independent from 1st-gen — there is no runtime dependency between them.
5
+ This package provides the behavior layer for gen2 Spectrum Web Components and is **not intended for direct external use**. It is independent from 1st-gen — there is no runtime dependency between them.
6
6
 
7
7
  For more information, visit the [Spectrum Web Components repository](https://github.com/adobe/spectrum-web-components).
8
8
 
@@ -26,7 +26,7 @@ var c, l = class extends s(o, {
26
26
  var t;
27
27
  if (super.updated(e), e.has("accessibleLabel") && (this.accessibleLabel ? this.setAttribute("aria-label", this.accessibleLabel) : this.removeAttribute("aria-label")), e.has("disabled") && (this.disabled ? this.setAttribute("aria-disabled", "true") : this.removeAttribute("aria-disabled"), this.propagateDisabledToChildren()), (t = window.__swc) != null && t.DEBUG) {
28
28
  let e = this.constructor;
29
- e.ORIENTATIONS.includes(this.orientation) || window.__swc.warn(this, `<${this.localName}> element expects the "orientation" attribute to be one of the following: ${e.ORIENTATIONS.join(", ")}.`, "https://opensource.adobe.com/spectrum-web-components/components/action-group/", { issues: [...e.ORIENTATIONS] });
29
+ e.ORIENTATIONS.includes(this.orientation) || window.__swc.warn(this, `<${this.localName}> element expects the "orientation" attribute to be one of the following: ${e.ORIENTATIONS.join(", ")}.`, "https://spectrum-web-components.adobe.com/components/action-group/", { issues: [...e.ORIENTATIONS] });
30
30
  }
31
31
  }
32
32
  propagateDisabledToChildren() {
@@ -1 +1 @@
1
- {"version":3,"file":"ActionGroup.base.js","names":[],"sources":["../../../components/action-group/ActionGroup.base.ts"],"sourcesContent":["/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { PropertyValues } from 'lit';\nimport { property, queryAssignedElements } from 'lit/decorators.js';\n\nimport { SpectrumElement } from '@adobe/spectrum-wc-core/element/index.js';\nimport { SizedMixin } from '@adobe/spectrum-wc-core/mixins/index.js';\n\nimport {\n ACTION_GROUP_ORIENTATIONS,\n ACTION_GROUP_STATIC_COLORS,\n ACTION_GROUP_VALID_SIZES,\n type ActionGroupOrientation,\n type ActionGroupSize,\n} from './ActionGroup.types.js';\n\n/**\n * An action group clusters related actions together with consistent\n * spacing, sizing, and orientation. It treats the whole strip as a single\n * stop in the keyboard sequence, with arrow keys moving between children.\n *\n * This base class owns the accessibility semantics, `accessible-label` →\n * `aria-label` management, `disabled` state contract, and child collection logic.\n * Rendering and styling live in the concrete SWC subclass.\n *\n * @slot - One or more `swc-action-button` or `swc-action-menu` elements.\n *\n * @attribute {ActionGroupSize} size - The size of the group and its children.\n */\nexport abstract class ActionGroupBase extends SizedMixin(SpectrumElement, {\n validSizes: ACTION_GROUP_VALID_SIZES,\n noDefaultSize: true,\n}) {\n static override shadowRootOptions = {\n ...SpectrumElement.shadowRootOptions,\n delegatesFocus: true,\n };\n\n /**\n * The size of the action group. Propagated to all slotted children.\n */\n declare public size: ActionGroupSize;\n\n // ──────────────────\n // SHARED API\n // ──────────────────\n\n /**\n * @internal\n *\n * Valid orientation values for validation.\n */\n static readonly ORIENTATIONS: readonly string[] = ACTION_GROUP_ORIENTATIONS;\n\n /**\n * @internal\n *\n * Valid static-color values for validation.\n */\n static readonly STATIC_COLORS: readonly string[] = ACTION_GROUP_STATIC_COLORS;\n\n /**\n * The layout direction of the action group.\n *\n * When set to `\"vertical\"`, the group stacks children vertically and\n * `FocusgroupNavigationController` moves focus with the Up/Down arrow\n * keys instead of Left/Right.\n *\n * Note: this property does NOT set `aria-orientation` on the host. The\n * host's role is fixed to `role=\"group\"`, and `aria-orientation` is only\n * a supported ARIA attribute on roles that expose it (`toolbar`,\n * `listbox`, `menu`, etc.), not `group`, regardless of this component's\n * roving-tabindex keyboard model. Setting it anyway fails axe's\n * `aria-allowed-attr` rule.\n *\n * @default horizontal\n */\n @property({ type: String, reflect: true })\n public orientation: ActionGroupOrientation = 'horizontal';\n\n /**\n * Accessible label for the group. Reflected to `aria-label` on the host.\n *\n * Providing a label is recommended whenever the strip has a distinct\n * purpose (e.g., \"Image adjustments\" or \"Edit\"). An empty value removes\n * the `aria-label` attribute.\n */\n @property({ type: String, attribute: 'accessible-label' })\n public accessibleLabel = '';\n\n /**\n * Whether the group and all of its children are disabled.\n *\n * Sets `aria-disabled=\"true\"` on the host and propagates `aria-disabled`\n * to each managed child. Children remain keyboard-reachable so that screen\n * reader users can still discover the group. Native `disabled` is not\n * applied to children.\n */\n @property({ type: Boolean, reflect: true })\n public disabled = false;\n\n // ──────────────────────\n // IMPLEMENTATION\n // ──────────────────────\n\n /**\n * @internal\n *\n * The managed children: all `swc-action-button` and `swc-action-menu`\n * elements assigned to the default slot. Populated by the concrete\n * subclass via `@queryAssignedElements`.\n */\n @queryAssignedElements({ flatten: true })\n protected managedChildren!: HTMLElement[];\n\n /**\n * Focuses the first enabled child in the group.\n *\n * The SWC concrete class overrides this with `FocusgroupNavigationController`,\n * restoring focus to the last active item when memory is enabled. This\n * implementation serves as a fallback for non-SWC subclasses.\n */\n public override focus(options?: FocusOptions): void {\n const firstEnabled = this.managedChildren?.find(\n (el) =>\n !el.hasAttribute('disabled') &&\n el.getAttribute('aria-disabled') !== 'true'\n );\n firstEnabled?.focus(options);\n }\n\n /**\n * @internal\n *\n * Handles slot-change events. Propagates `aria-disabled` to newly slotted\n * children when the group is disabled. Concrete subclasses call\n * `super.handleSlotchange()` and then propagate visual attributes.\n */\n protected handleSlotchange(): void {\n if (this.disabled) {\n this.propagateDisabledToChildren();\n }\n }\n\n protected override firstUpdated(changed: PropertyValues<this>): void {\n super.firstUpdated(changed);\n this.setAttribute('role', 'group');\n }\n\n protected override updated(changed: PropertyValues<this>): void {\n super.updated(changed);\n\n if (changed.has('accessibleLabel')) {\n if (this.accessibleLabel) {\n this.setAttribute('aria-label', this.accessibleLabel);\n } else {\n this.removeAttribute('aria-label');\n }\n }\n\n if (changed.has('disabled')) {\n if (this.disabled) {\n this.setAttribute('aria-disabled', 'true');\n } else {\n this.removeAttribute('aria-disabled');\n }\n this.propagateDisabledToChildren();\n }\n\n if (window.__swc?.DEBUG) {\n const constructor = this.constructor as typeof ActionGroupBase;\n if (!constructor.ORIENTATIONS.includes(this.orientation)) {\n window.__swc.warn(\n this,\n `<${this.localName}> element expects the \"orientation\" attribute to be one of the following: ${constructor.ORIENTATIONS.join(', ')}.`,\n 'https://opensource.adobe.com/spectrum-web-components/components/action-group/',\n { issues: [...constructor.ORIENTATIONS] }\n );\n }\n }\n }\n\n private propagateDisabledToChildren(): void {\n // `aria-disabled` is set on the child host element. For AT to announce the\n // child as disabled, each child component must forward the host attribute to\n // its inner interactive element. `swc-action-button` already does this\n // (observes `aria-disabled` and forwards to its inner <button>).\n // `swc-action-menu` will need the same treatment when it is built — it must\n // forward `aria-disabled` from its host to its inner trigger element and\n // apply disabled appearance via :host([aria-disabled=\"true\"]) CSS.\n for (const child of this.managedChildren ?? []) {\n if (this.disabled) {\n child.setAttribute('aria-disabled', 'true');\n } else {\n child.removeAttribute('aria-disabled');\n }\n }\n }\n}\n"],"mappings":";;;;;;OAuCsB,IAAtB,cAA8C,EAAW,GAAiB;CACxE,YAAY;CACZ,eAAe;CAChB,CAAC,CAAC;;kCA8C4C,qCAUpB,oBAWP;;CAuBlB,MAAsB,GAA8B;;EAClD,IAAM,KAAA,IAAe,KAAK,oBAAA,OAAA,KAAA,IAAA,EAAiB,MACxC,MACC,CAAC,EAAG,aAAa,WAAW,IAC5B,EAAG,aAAa,gBAAgB,KAAK,OACxC;AACD,OAAA,QAAA,EAAc,MAAM,EAAQ;;CAU9B,mBAAmC;AACjC,EAAI,KAAK,YACP,KAAK,6BAA6B;;CAItC,aAAgC,GAAqC;AAEnE,EADA,MAAM,aAAa,EAAQ,EAC3B,KAAK,aAAa,QAAQ,QAAQ;;CAGpC,QAA2B,GAAqC;;AAoB9D,MAnBA,MAAM,QAAQ,EAAQ,EAElB,EAAQ,IAAI,kBAAkB,KAC5B,KAAK,kBACP,KAAK,aAAa,cAAc,KAAK,gBAAgB,GAErD,KAAK,gBAAgB,aAAa,GAIlC,EAAQ,IAAI,WAAW,KACrB,KAAK,WACP,KAAK,aAAa,iBAAiB,OAAO,GAE1C,KAAK,gBAAgB,gBAAgB,EAEvC,KAAK,6BAA6B,IAGpC,IAAI,OAAO,UAAA,QAAA,EAAO,OAAO;GACvB,IAAM,IAAc,KAAK;AACzB,GAAK,EAAY,aAAa,SAAS,KAAK,YAAY,IACtD,OAAO,MAAM,KACX,MACA,IAAI,KAAK,UAAU,4EAA4E,EAAY,aAAa,KAAK,KAAK,CAAC,IACnI,iFACA,EAAE,QAAQ,CAAC,GAAG,EAAY,aAAa,EAAE,CAC1C;;;CAKP,8BAA4C;;AAQ1C,OAAK,IAAM,MAAA,IAAS,KAAK,oBAAA,OAAmB,EAAE,GAArB,EACvB,CAAI,KAAK,WACP,EAAM,aAAa,iBAAiB,OAAO,GAE3C,EAAM,gBAAgB,gBAAgB;;;6BAjKR;CAClC,GAAG,EAAgB;CACnB,gBAAgB;CACjB,mBAgBiD,qBAOC,MAkBlD,EAAS;CAAE,MAAM;CAAQ,SAAS;CAAM,CAAC,CAAA,EAAA,EAAA,WAAA,eAAA,KAAA,EAAA,KAUzC,EAAS;CAAE,MAAM;CAAQ,WAAW;CAAoB,CAAC,CAAA,EAAA,EAAA,WAAA,mBAAA,KAAA,EAAA,KAWzD,EAAS;CAAE,MAAM;CAAS,SAAS;CAAM,CAAC,CAAA,EAAA,EAAA,WAAA,YAAA,KAAA,EAAA,KAc1C,EAAsB,EAAE,SAAS,IAAM,CAAC,CAAA,EAAA,EAAA,WAAA,mBAAA,KAAA,EAAA"}
1
+ {"version":3,"file":"ActionGroup.base.js","names":[],"sources":["../../../components/action-group/ActionGroup.base.ts"],"sourcesContent":["/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { PropertyValues } from 'lit';\nimport { property, queryAssignedElements } from 'lit/decorators.js';\n\nimport { SpectrumElement } from '@adobe/spectrum-wc-core/element/index.js';\nimport { SizedMixin } from '@adobe/spectrum-wc-core/mixins/index.js';\n\nimport {\n ACTION_GROUP_ORIENTATIONS,\n ACTION_GROUP_STATIC_COLORS,\n ACTION_GROUP_VALID_SIZES,\n type ActionGroupOrientation,\n type ActionGroupSize,\n} from './ActionGroup.types.js';\n\n/**\n * An action group clusters related actions together with consistent\n * spacing, sizing, and orientation. It treats the whole strip as a single\n * stop in the keyboard sequence, with arrow keys moving between children.\n *\n * This base class owns the accessibility semantics, `accessible-label` →\n * `aria-label` management, `disabled` state contract, and child collection logic.\n * Rendering and styling live in the concrete SWC subclass.\n *\n * @slot - One or more `swc-action-button` or `swc-action-menu` elements.\n *\n * @attribute {ActionGroupSize} size - The size of the group and its children.\n */\nexport abstract class ActionGroupBase extends SizedMixin(SpectrumElement, {\n validSizes: ACTION_GROUP_VALID_SIZES,\n noDefaultSize: true,\n}) {\n static override shadowRootOptions = {\n ...SpectrumElement.shadowRootOptions,\n delegatesFocus: true,\n };\n\n /**\n * The size of the action group. Propagated to all slotted children.\n */\n declare public size: ActionGroupSize;\n\n // ──────────────────\n // SHARED API\n // ──────────────────\n\n /**\n * @internal\n *\n * Valid orientation values for validation.\n */\n static readonly ORIENTATIONS: readonly string[] = ACTION_GROUP_ORIENTATIONS;\n\n /**\n * @internal\n *\n * Valid static-color values for validation.\n */\n static readonly STATIC_COLORS: readonly string[] = ACTION_GROUP_STATIC_COLORS;\n\n /**\n * The layout direction of the action group.\n *\n * When set to `\"vertical\"`, the group stacks children vertically and\n * `FocusgroupNavigationController` moves focus with the Up/Down arrow\n * keys instead of Left/Right.\n *\n * Note: this property does NOT set `aria-orientation` on the host. The\n * host's role is fixed to `role=\"group\"`, and `aria-orientation` is only\n * a supported ARIA attribute on roles that expose it (`toolbar`,\n * `listbox`, `menu`, etc.), not `group`, regardless of this component's\n * roving-tabindex keyboard model. Setting it anyway fails axe's\n * `aria-allowed-attr` rule.\n *\n * @default horizontal\n */\n @property({ type: String, reflect: true })\n public orientation: ActionGroupOrientation = 'horizontal';\n\n /**\n * Accessible label for the group. Reflected to `aria-label` on the host.\n *\n * Providing a label is recommended whenever the strip has a distinct\n * purpose (e.g., \"Image adjustments\" or \"Edit\"). An empty value removes\n * the `aria-label` attribute.\n */\n @property({ type: String, attribute: 'accessible-label' })\n public accessibleLabel = '';\n\n /**\n * Whether the group and all of its children are disabled.\n *\n * Sets `aria-disabled=\"true\"` on the host and propagates `aria-disabled`\n * to each managed child. Children remain keyboard-reachable so that screen\n * reader users can still discover the group. Native `disabled` is not\n * applied to children.\n */\n @property({ type: Boolean, reflect: true })\n public disabled = false;\n\n // ──────────────────────\n // IMPLEMENTATION\n // ──────────────────────\n\n /**\n * @internal\n *\n * The managed children: all `swc-action-button` and `swc-action-menu`\n * elements assigned to the default slot. Populated by the concrete\n * subclass via `@queryAssignedElements`.\n */\n @queryAssignedElements({ flatten: true })\n protected managedChildren!: HTMLElement[];\n\n /**\n * Focuses the first enabled child in the group.\n *\n * The SWC concrete class overrides this with `FocusgroupNavigationController`,\n * restoring focus to the last active item when memory is enabled. This\n * implementation serves as a fallback for non-SWC subclasses.\n */\n public override focus(options?: FocusOptions): void {\n const firstEnabled = this.managedChildren?.find(\n (el) =>\n !el.hasAttribute('disabled') &&\n el.getAttribute('aria-disabled') !== 'true'\n );\n firstEnabled?.focus(options);\n }\n\n /**\n * @internal\n *\n * Handles slot-change events. Propagates `aria-disabled` to newly slotted\n * children when the group is disabled. Concrete subclasses call\n * `super.handleSlotchange()` and then propagate visual attributes.\n */\n protected handleSlotchange(): void {\n if (this.disabled) {\n this.propagateDisabledToChildren();\n }\n }\n\n protected override firstUpdated(changed: PropertyValues<this>): void {\n super.firstUpdated(changed);\n this.setAttribute('role', 'group');\n }\n\n protected override updated(changed: PropertyValues<this>): void {\n super.updated(changed);\n\n if (changed.has('accessibleLabel')) {\n if (this.accessibleLabel) {\n this.setAttribute('aria-label', this.accessibleLabel);\n } else {\n this.removeAttribute('aria-label');\n }\n }\n\n if (changed.has('disabled')) {\n if (this.disabled) {\n this.setAttribute('aria-disabled', 'true');\n } else {\n this.removeAttribute('aria-disabled');\n }\n this.propagateDisabledToChildren();\n }\n\n if (window.__swc?.DEBUG) {\n const constructor = this.constructor as typeof ActionGroupBase;\n if (!constructor.ORIENTATIONS.includes(this.orientation)) {\n window.__swc.warn(\n this,\n `<${this.localName}> element expects the \"orientation\" attribute to be one of the following: ${constructor.ORIENTATIONS.join(', ')}.`,\n 'https://spectrum-web-components.adobe.com/components/action-group/',\n { issues: [...constructor.ORIENTATIONS] }\n );\n }\n }\n }\n\n private propagateDisabledToChildren(): void {\n // `aria-disabled` is set on the child host element. For AT to announce the\n // child as disabled, each child component must forward the host attribute to\n // its inner interactive element. `swc-action-button` already does this\n // (observes `aria-disabled` and forwards to its inner <button>).\n // `swc-action-menu` will need the same treatment when it is built — it must\n // forward `aria-disabled` from its host to its inner trigger element and\n // apply disabled appearance via :host([aria-disabled=\"true\"]) CSS.\n for (const child of this.managedChildren ?? []) {\n if (this.disabled) {\n child.setAttribute('aria-disabled', 'true');\n } else {\n child.removeAttribute('aria-disabled');\n }\n }\n }\n}\n"],"mappings":";;;;;;OAuCsB,IAAtB,cAA8C,EAAW,GAAiB;CACxE,YAAY;CACZ,eAAe;CAChB,CAAC,CAAC;;kCA8C4C,qCAUpB,oBAWP;;CAuBlB,MAAsB,GAA8B;;EAClD,IAAM,KAAA,IAAe,KAAK,oBAAA,OAAA,KAAA,IAAA,EAAiB,MACxC,MACC,CAAC,EAAG,aAAa,WAAW,IAC5B,EAAG,aAAa,gBAAgB,KAAK,OACxC;AACD,OAAA,QAAA,EAAc,MAAM,EAAQ;;CAU9B,mBAAmC;AACjC,EAAI,KAAK,YACP,KAAK,6BAA6B;;CAItC,aAAgC,GAAqC;AAEnE,EADA,MAAM,aAAa,EAAQ,EAC3B,KAAK,aAAa,QAAQ,QAAQ;;CAGpC,QAA2B,GAAqC;;AAoB9D,MAnBA,MAAM,QAAQ,EAAQ,EAElB,EAAQ,IAAI,kBAAkB,KAC5B,KAAK,kBACP,KAAK,aAAa,cAAc,KAAK,gBAAgB,GAErD,KAAK,gBAAgB,aAAa,GAIlC,EAAQ,IAAI,WAAW,KACrB,KAAK,WACP,KAAK,aAAa,iBAAiB,OAAO,GAE1C,KAAK,gBAAgB,gBAAgB,EAEvC,KAAK,6BAA6B,IAGpC,IAAI,OAAO,UAAA,QAAA,EAAO,OAAO;GACvB,IAAM,IAAc,KAAK;AACzB,GAAK,EAAY,aAAa,SAAS,KAAK,YAAY,IACtD,OAAO,MAAM,KACX,MACA,IAAI,KAAK,UAAU,4EAA4E,EAAY,aAAa,KAAK,KAAK,CAAC,IACnI,sEACA,EAAE,QAAQ,CAAC,GAAG,EAAY,aAAa,EAAE,CAC1C;;;CAKP,8BAA4C;;AAQ1C,OAAK,IAAM,MAAA,IAAS,KAAK,oBAAA,OAAmB,EAAE,GAArB,EACvB,CAAI,KAAK,WACP,EAAM,aAAa,iBAAiB,OAAO,GAE3C,EAAM,gBAAgB,gBAAgB;;;6BAjKR;CAClC,GAAG,EAAgB;CACnB,gBAAgB;CACjB,mBAgBiD,qBAOC,MAkBlD,EAAS;CAAE,MAAM;CAAQ,SAAS;CAAM,CAAC,CAAA,EAAA,EAAA,WAAA,eAAA,KAAA,EAAA,KAUzC,EAAS;CAAE,MAAM;CAAQ,WAAW;CAAoB,CAAC,CAAA,EAAA,EAAA,WAAA,mBAAA,KAAA,EAAA,KAWzD,EAAS;CAAE,MAAM;CAAS,SAAS;CAAM,CAAC,CAAA,EAAA,EAAA,WAAA,YAAA,KAAA,EAAA,KAc1C,EAAsB,EAAE,SAAS,IAAM,CAAC,CAAA,EAAA,EAAA,WAAA,mBAAA,KAAA,EAAA"}
@@ -1,22 +1,101 @@
1
1
  import { PropertyValues } from 'lit';
2
2
  import { SpectrumElement } from '../../element/index.js';
3
- import { AssetVariant } from './Asset.types.js';
3
+ import { AssetBackground, AssetFit, AssetLoadState } from './Asset.types.js';
4
+ /**
5
+ * Base class for the `<swc-asset>` general image/media primitive.
6
+ *
7
+ * @slot - a single `<img>` or `<svg>` element to display
8
+ */
4
9
  export declare abstract class AssetBase extends SpectrumElement {
10
+ private _aspectRatio;
11
+ private _rawAspectRatio;
5
12
  /**
6
- * @internal
7
- *
8
- * A readonly array of all valid variants for the asset.
13
+ * The aspect ratio to apply to the asset, in CSS `<ratio>` syntax (e.g.
14
+ * `"16/9"`), plus the `square` keyword. `:`-separated ratios (e.g.
15
+ * `"16:9"`) are normalized to `/`. Falls through to an ancestor-supplied
16
+ * default, else `auto`, when unset. Has no effect when both `width` and
17
+ * `height` are also set.
18
+ */
19
+ get aspectRatio(): string | undefined;
20
+ set aspectRatio(value: string | undefined);
21
+ /**
22
+ * An explicit width, as a CSS `<length-percentage>` (e.g. `"100px"`,
23
+ * `"90%"`). An alternative to `aspectRatio` for sizing the asset.
24
+ */
25
+ width: string | undefined;
26
+ /**
27
+ * An explicit height, as a CSS `<length-percentage>` (e.g. `"100px"`,
28
+ * `"90%"`). An alternative to `aspectRatio` for sizing the asset.
29
+ */
30
+ height: string | undefined;
31
+ /**
32
+ * How slotted image/SVG content fits within the asset's box.
9
33
  *
10
- * This is an actual internal property, intended not for customer use
34
+ * @default cover
35
+ */
36
+ fit: AssetFit;
37
+ /**
38
+ * Marks the asset as decorative, removing it from the accessibility tree
39
+ * (`aria-hidden="true"` on the host) regardless of slotted content or
40
+ * `accessibleLabel`.
41
+ */
42
+ decorative: boolean;
43
+ /**
44
+ * A fallback accessible name, applied to the slotted `<img>` or `<svg>`
45
+ * only when it doesn't already carry its own accessible name.
11
46
  */
12
- static readonly VARIANTS: readonly AssetVariant[];
47
+ accessibleLabel: string | undefined;
13
48
  /**
14
- * The variant of the asset. When not provided, slot content is rendered (e.g., an image).
49
+ * The background shown behind slotted content: `transparent` (no
50
+ * background), a `solid` color, or an opacity `checkerboard`.
51
+ *
52
+ * @default transparent
15
53
  */
16
- variant: AssetVariant | undefined;
54
+ background: AssetBackground;
17
55
  /**
18
- * Accessible label for the asset’s file or folder variant.
56
+ * The load status of the slotted `<img>`: `'loading'` while its request is
57
+ * in flight, `'loaded'` on success, `'error'` on failure. Immediately
58
+ * `'loaded'` for a slotted `<svg>` or no slotted content, since there's
59
+ * nothing asynchronous to wait for. Set internally by Asset; a consumer
60
+ * influences it only by changing what's slotted, not by setting it
61
+ * directly.
19
62
  */
20
- label: string;
63
+ loadState: AssetLoadState;
64
+ private _appliedAriaHidden;
65
+ private _trackedImg;
66
+ private _preserveAspectRatioAppliedTo;
67
+ private _appliedAccessibleLabelTo;
21
68
  protected update(changes: PropertyValues): void;
69
+ /**
70
+ * Warns when the default slot receives more than one child, or a child
71
+ * that isn't an `<img>` or `<svg>`. There is exactly one (default) slot,
72
+ * so its assigned elements are the host's own light DOM children.
73
+ */
74
+ private validateSlottedContent;
75
+ /**
76
+ * Implements `decorative` and the `accessibleLabel` fallback, in priority
77
+ * order: `decorative` > the child's own name (self-healing a missing
78
+ * `role="img"` on a named `<svg>`) > `accessibleLabel` > warn.
79
+ */
80
+ private resolveAccessibleName;
81
+ /**
82
+ * Whether `child` already has its own accessible name. The `<svg>` branch
83
+ * doesn't require `role="img"` — `resolveAccessibleName` self-heals a
84
+ * missing role separately.
85
+ */
86
+ private hasOwnAccessibleName;
87
+ /**
88
+ * Applies `fit` to a slotted `<svg>` via `preserveAspectRatio`, without
89
+ * overwriting a consumer-set value or writing on every update.
90
+ */
91
+ private applyFitToSvg;
92
+ /**
93
+ * Tracks `loadState` against the slotted `<img>`, re-wiring listeners only
94
+ * when the tracked element actually changes (a no-op on every other
95
+ * property update, since re-running this for the same `<img>` would
96
+ * incorrectly reset an already-resolved `loadState` back to `'loading'`).
97
+ */
98
+ private updateLoadState;
99
+ private readonly handleImgLoad;
100
+ private readonly handleImgError;
22
101
  }
@@ -1,31 +1,130 @@
1
1
  import { __decorate as e } from "../../_virtual/_@oxc-project_runtime@0.124.0/helpers/decorate.js";
2
- import { ASSET_VARIANTS as t } from "./Asset.types.js";
3
- import { property as n } from "lit/decorators.js";
4
- import { SpectrumElement as r } from "@adobe/spectrum-wc-core/element/index.js";
5
- import { validateEnum as i } from "@adobe/spectrum-wc-core/utils/index.js";
2
+ import { ASSET_BACKGROUND_VALUES as t, ASSET_FIT_VALUES as n, ASSET_LOAD_STATE_VALUES as r, SWC_ASSET_ERROR_EVENT as i, SWC_ASSET_LOAD_EVENT as a } from "./Asset.types.js";
3
+ import { property as o } from "lit/decorators.js";
4
+ import { SpectrumElement as s } from "@adobe/spectrum-wc-core/element/index.js";
5
+ import { isDebug as c, validateEnum as l, warnIf as u } from "@adobe/spectrum-wc-core/utils/index.js";
6
6
  //#region components/asset/Asset.base.ts
7
- var a, o = class extends r {
7
+ var d = "https://spectrum-web-components.adobe.com/?path=/docs/components-asset--docs", f = String.raw`(?:\d+\.?\d*|\.\d+)`, p = String.raw`${f}(?:\s*\/\s*${f})?`, m = RegExp(`^(?:auto|${p}|auto\\s+${p}|${p}\\s+auto)$`), h = {
8
+ cover: "xMidYMid slice",
9
+ contain: "xMidYMid meet"
10
+ };
11
+ function g(e) {
12
+ return e && (e === "square" ? "1/1" : e.replace(":", "/"));
13
+ }
14
+ var _ = class extends s {
8
15
  constructor(...e) {
9
- super(...e), this.label = "";
16
+ super(...e), this.fit = "cover", this.decorative = !1, this.background = "transparent", this.loadState = "loading", this._appliedAriaHidden = !1, this._trackedImg = void 0, this._preserveAspectRatioAppliedTo = null, this._appliedAccessibleLabelTo = null, this.handleImgLoad = () => {
17
+ this.loadState = "loaded", this.dispatchEvent(new CustomEvent(a, {
18
+ bubbles: !0,
19
+ composed: !0
20
+ }));
21
+ }, this.handleImgError = () => {
22
+ var e, t;
23
+ this.loadState = "error", this.dispatchEvent(new CustomEvent(i, {
24
+ bubbles: !0,
25
+ composed: !0,
26
+ detail: { src: (e = (t = this._trackedImg) == null ? void 0 : t.currentSrc) == null ? "" : e }
27
+ }));
28
+ };
29
+ }
30
+ get aspectRatio() {
31
+ return this._aspectRatio;
32
+ }
33
+ set aspectRatio(e) {
34
+ let t = this._aspectRatio;
35
+ this._rawAspectRatio = e, this._aspectRatio = g(e), this.requestUpdate("aspectRatio", t);
10
36
  }
11
37
  update(e) {
12
- if (this.variant !== void 0) {
13
- let e = this.constructor;
14
- i(this, {
15
- prop: "variant",
16
- value: this.variant,
17
- valid: e.VARIANTS,
18
- url: "https://spectrum-web-components.adobe.com/?path=/docs/components-asset--docs"
19
- });
38
+ e.has("fit") && l(this, {
39
+ prop: "fit",
40
+ value: this.fit,
41
+ valid: n,
42
+ url: d
43
+ }), e.has("background") && l(this, {
44
+ prop: "background",
45
+ value: this.background,
46
+ valid: t,
47
+ url: d
48
+ }), e.has("loadState") && l(this, {
49
+ prop: "load-state",
50
+ value: this.loadState,
51
+ valid: r,
52
+ url: d
53
+ }), (e.has("aspectRatio") || e.has("width") || e.has("height")) && (u(this, this.aspectRatio !== void 0 && !m.test(this.aspectRatio), `<${this.localName}> expects "aspect-ratio" to be a CSS <ratio> (e.g. "16/9"), the "square" keyword, or a ":"-separated ratio (e.g. "16:9"). Received "${this._rawAspectRatio}".`, d), u(this, this.aspectRatio !== void 0 && this.width !== void 0 && this.height !== void 0, `<${this.localName}> "aspect-ratio" has no effect when both "width" and "height" are set.`, d));
54
+ let i = Array.from(this.children);
55
+ c() && this.validateSlottedContent(i), this.resolveAccessibleName(i), this.applyFitToSvg(i), this.updateLoadState(i), super.update(e);
56
+ }
57
+ validateSlottedContent(e) {
58
+ u(this, e.length > 1, `<${this.localName}> only supports a single slotted <img> or <svg> element. Received ${e.length} children.`, d);
59
+ let [t] = e;
60
+ if (t) {
61
+ let e = t.tagName.toLowerCase();
62
+ u(this, e !== "img" && e !== "svg", `<${this.localName}> expects its slotted content to be an <img> or <svg> element. Received <${e}>.`, d);
63
+ }
64
+ }
65
+ resolveAccessibleName(e) {
66
+ if (this.decorative) {
67
+ this.hasAttribute("aria-hidden") || (this._appliedAriaHidden = !0, this.setAttribute("aria-hidden", "true"));
68
+ return;
69
+ }
70
+ this._appliedAriaHidden && (this.removeAttribute("aria-hidden"), this._appliedAriaHidden = !1);
71
+ let [t] = e, n = t == null ? void 0 : t.tagName.toLowerCase();
72
+ if (t && n !== "img" && n !== "svg") return;
73
+ let r = !!t && this._appliedAccessibleLabelTo === t, i = !!t && !r && this.hasOwnAccessibleName(t, n);
74
+ t && (i ? n === "svg" && !t.hasAttribute("role") && t.setAttribute("role", "img") : this.accessibleLabel ? (n === "img" ? t.alt = this.accessibleLabel : (t.setAttribute("role", "img"), t.setAttribute("aria-label", this.accessibleLabel)), this._appliedAccessibleLabelTo = t) : r && (n === "img" ? t.removeAttribute("alt") : (t.removeAttribute("role"), t.removeAttribute("aria-label")), this._appliedAccessibleLabelTo = null)), u(this, !i && !this.accessibleLabel, `<${this.localName}> requires an accessible name: set "alt" on the slotted <img> (or "aria-label"/"aria-labelledby"/a child <title> on the slotted <svg>), set "accessible-label" on <${this.localName}>, or set "decorative".`, d);
75
+ }
76
+ hasOwnAccessibleName(e, t) {
77
+ let n = e.hasAttribute("aria-label") || e.hasAttribute("aria-labelledby");
78
+ if (t === "img") return n || e.hasAttribute("alt");
79
+ let r = !!e.querySelector(":scope > title");
80
+ return n || r;
81
+ }
82
+ applyFitToSvg(e) {
83
+ var t;
84
+ let [n] = e;
85
+ if ((n == null ? void 0 : n.tagName.toLowerCase()) !== "svg") {
86
+ this._preserveAspectRatioAppliedTo = null;
87
+ return;
88
+ }
89
+ let r = this._preserveAspectRatioAppliedTo === n;
90
+ if (n.hasAttribute("preserveAspectRatio") && !r) return;
91
+ let i = (t = h[this.fit]) == null ? h.cover : t;
92
+ n.getAttribute("preserveAspectRatio") !== i && n.setAttribute("preserveAspectRatio", i), this._preserveAspectRatioAppliedTo = n;
93
+ }
94
+ updateLoadState(e) {
95
+ let [t] = e, n = (t == null ? void 0 : t.tagName.toLowerCase()) === "img" ? t : null;
96
+ if (n !== this._trackedImg) {
97
+ if (this._trackedImg && (this._trackedImg.removeEventListener("load", this.handleImgLoad), this._trackedImg.removeEventListener("error", this.handleImgError)), this._trackedImg = n, !n) {
98
+ this.loadState = "loaded";
99
+ return;
100
+ }
101
+ if (this.loadState = "loading", n.addEventListener("load", this.handleImgLoad), n.addEventListener("error", this.handleImgError), n.complete && n.currentSrc) {
102
+ let e = n.naturalWidth > 0;
103
+ queueMicrotask(() => {
104
+ this._trackedImg === n && (e ? this.handleImgLoad() : this.handleImgError());
105
+ });
106
+ }
20
107
  }
21
- super.update(e);
22
108
  }
23
109
  };
24
- a = o, a.VARIANTS = t, e([n({
110
+ e([o({ attribute: "aspect-ratio" })], _.prototype, "aspectRatio", null), e([o({ type: String })], _.prototype, "width", void 0), e([o({ type: String })], _.prototype, "height", void 0), e([o({
111
+ type: String,
112
+ reflect: !0
113
+ })], _.prototype, "fit", void 0), e([o({
114
+ type: Boolean,
115
+ reflect: !0
116
+ })], _.prototype, "decorative", void 0), e([o({
117
+ type: String,
118
+ attribute: "accessible-label"
119
+ })], _.prototype, "accessibleLabel", void 0), e([o({
25
120
  type: String,
26
121
  reflect: !0
27
- })], o.prototype, "variant", void 0), e([n({ type: String })], o.prototype, "label", void 0);
122
+ })], _.prototype, "background", void 0), e([o({
123
+ type: String,
124
+ reflect: !0,
125
+ attribute: "load-state"
126
+ })], _.prototype, "loadState", void 0);
28
127
  //#endregion
29
- export { o as AssetBase };
128
+ export { _ as AssetBase };
30
129
 
31
130
  //# sourceMappingURL=Asset.base.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Asset.base.js","names":[],"sources":["../../../components/asset/Asset.base.ts"],"sourcesContent":["/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { PropertyValues } from 'lit';\nimport { property } from 'lit/decorators.js';\n\nimport { SpectrumElement } from '@adobe/spectrum-wc-core/element/index.js';\nimport { validateEnum } from '@adobe/spectrum-wc-core/utils/index.js';\n\nimport { ASSET_VARIANTS, type AssetVariant } from './Asset.types.js';\n\nexport abstract class AssetBase extends SpectrumElement {\n // ─────────────────────────\n // API TO OVERRIDE\n // ─────────────────────────\n\n /**\n * @internal\n *\n * A readonly array of all valid variants for the asset.\n *\n * This is an actual internal property, intended not for customer use\n */\n static readonly VARIANTS: readonly AssetVariant[] = ASSET_VARIANTS;\n\n // ─────────────────\n // SHARED API\n // ─────────────────\n\n /**\n * The variant of the asset. When not provided, slot content is rendered (e.g., an image).\n */\n @property({ type: String, reflect: true })\n public variant: AssetVariant | undefined;\n\n /**\n * Accessible label for the asset’s file or folder variant.\n */\n @property({ type: String })\n public label = '';\n\n // ──────────────────────\n // IMPLEMENTATION\n // ──────────────────────\n\n protected override update(changes: PropertyValues): void {\n if (typeof this.variant !== 'undefined') {\n const constructor = this.constructor as typeof AssetBase;\n validateEnum(this, {\n prop: 'variant',\n value: this.variant,\n valid: constructor.VARIANTS,\n url: 'https://spectrum-web-components.adobe.com/?path=/docs/components-asset--docs',\n });\n }\n super.update(changes);\n }\n}\n"],"mappings":";;;;;;OAoBsB,IAAtB,cAAwC,EAAgB;;4BA4BvC;;CAMf,OAA0B,GAA+B;AACvD,MAAW,KAAK,YAAY,QAAa;GACvC,IAAM,IAAc,KAAK;AACzB,KAAa,MAAM;IACjB,MAAM;IACN,OAAO,KAAK;IACZ,OAAO,EAAY;IACnB,KAAK;IACN,CAAC;;AAEJ,QAAM,OAAO,EAAQ;;;oBAhC6B,MASnD,EAAS;CAAE,MAAM;CAAQ,SAAS;CAAM,CAAC,CAAA,EAAA,EAAA,WAAA,WAAA,KAAA,EAAA,KAMzC,EAAS,EAAE,MAAM,QAAQ,CAAC,CAAA,EAAA,EAAA,WAAA,SAAA,KAAA,EAAA"}
1
+ {"version":3,"file":"Asset.base.js","names":[],"sources":["../../../components/asset/Asset.base.ts"],"sourcesContent":["/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { PropertyValues } from 'lit';\nimport { property } from 'lit/decorators.js';\n\nimport { SpectrumElement } from '@adobe/spectrum-wc-core/element/index.js';\nimport {\n isDebug,\n validateEnum,\n warnIf,\n} from '@adobe/spectrum-wc-core/utils/index.js';\n\nimport {\n ASSET_BACKGROUND_VALUES,\n ASSET_FIT_VALUES,\n ASSET_LOAD_STATE_VALUES,\n type AssetBackground,\n type AssetErrorEventDetail,\n type AssetFit,\n type AssetLoadState,\n SWC_ASSET_ERROR_EVENT,\n SWC_ASSET_LOAD_EVENT,\n} from './Asset.types.js';\n\nconst DOCS_URL =\n 'https://spectrum-web-components.adobe.com/?path=/docs/components-asset--docs';\n\n// A plain CSS <number>: \"16\", \"1.5\", or \".5\".\nconst NUMBER = String.raw`(?:\\d+\\.?\\d*|\\.\\d+)`;\n// A CSS <ratio>, optionally paired with `auto` on either side (both orders\n// are valid, e.g. \"auto 16/9\" or \"16/9 auto\").\nconst RATIO = String.raw`${NUMBER}(?:\\s*\\/\\s*${NUMBER})?`;\nconst ASPECT_RATIO_PATTERN = new RegExp(\n `^(?:auto|${RATIO}|auto\\\\s+${RATIO}|${RATIO}\\\\s+auto)$`\n);\n\n// object-fit doesn't apply to inline <svg>, so `fit` drives\n// `preserveAspectRatio` instead.\nconst SVG_PRESERVE_ASPECT_RATIO: Record<AssetFit, string> = {\n cover: 'xMidYMid slice',\n contain: 'xMidYMid meet',\n};\n\n/**\n * Normalizes an `aspectRatio` value: maps the `square` keyword to `1/1`, and\n * `:`-separated ratios (e.g. `16:9`) to the CSS `<ratio>` separator (`16/9`).\n */\nfunction normalizeAspectRatio(value: string | undefined): string | undefined {\n if (!value) {\n return value;\n }\n if (value === 'square') {\n return '1/1';\n }\n return value.replace(':', '/');\n}\n\n/**\n * Base class for the `<swc-asset>` general image/media primitive.\n *\n * @slot - a single `<img>` or `<svg>` element to display\n */\nexport abstract class AssetBase extends SpectrumElement {\n // ──────────────────\n // SHARED API\n // ──────────────────\n\n private _aspectRatio: string | undefined;\n\n // The pre-normalization value, kept for the malformed-ratio warning\n private _rawAspectRatio: string | undefined;\n\n /**\n * The aspect ratio to apply to the asset, in CSS `<ratio>` syntax (e.g.\n * `\"16/9\"`), plus the `square` keyword. `:`-separated ratios (e.g.\n * `\"16:9\"`) are normalized to `/`. Falls through to an ancestor-supplied\n * default, else `auto`, when unset. Has no effect when both `width` and\n * `height` are also set.\n */\n @property({ attribute: 'aspect-ratio' })\n public get aspectRatio(): string | undefined {\n return this._aspectRatio;\n }\n\n public set aspectRatio(value: string | undefined) {\n const oldValue = this._aspectRatio;\n this._rawAspectRatio = value;\n this._aspectRatio = normalizeAspectRatio(value);\n this.requestUpdate('aspectRatio', oldValue);\n }\n\n /**\n * An explicit width, as a CSS `<length-percentage>` (e.g. `\"100px\"`,\n * `\"90%\"`). An alternative to `aspectRatio` for sizing the asset.\n */\n @property({ type: String })\n public width: string | undefined;\n\n /**\n * An explicit height, as a CSS `<length-percentage>` (e.g. `\"100px\"`,\n * `\"90%\"`). An alternative to `aspectRatio` for sizing the asset.\n */\n @property({ type: String })\n public height: string | undefined;\n\n /**\n * How slotted image/SVG content fits within the asset's box.\n *\n * @default cover\n */\n @property({ type: String, reflect: true })\n public fit: AssetFit = 'cover';\n\n /**\n * Marks the asset as decorative, removing it from the accessibility tree\n * (`aria-hidden=\"true\"` on the host) regardless of slotted content or\n * `accessibleLabel`.\n */\n @property({ type: Boolean, reflect: true })\n public decorative = false;\n\n /**\n * A fallback accessible name, applied to the slotted `<img>` or `<svg>`\n * only when it doesn't already carry its own accessible name.\n */\n @property({ type: String, attribute: 'accessible-label' })\n public accessibleLabel: string | undefined;\n\n /**\n * The background shown behind slotted content: `transparent` (no\n * background), a `solid` color, or an opacity `checkerboard`.\n *\n * @default transparent\n */\n @property({ type: String, reflect: true })\n public background: AssetBackground = 'transparent';\n\n /**\n * The load status of the slotted `<img>`: `'loading'` while its request is\n * in flight, `'loaded'` on success, `'error'` on failure. Immediately\n * `'loaded'` for a slotted `<svg>` or no slotted content, since there's\n * nothing asynchronous to wait for. Set internally by Asset; a consumer\n * influences it only by changing what's slotted, not by setting it\n * directly.\n */\n @property({ type: String, reflect: true, attribute: 'load-state' })\n public loadState: AssetLoadState = 'loading';\n\n // ──────────────────────\n // IMPLEMENTATION\n // ──────────────────────\n\n // Only clear `aria-hidden` if this instance set it, so a consumer's own\n // attribute survives.\n private _appliedAriaHidden = false;\n\n // `undefined` means \"not yet determined\" (distinct from `null`, \"confirmed\n // no `<img>` child\"), so the first resolution to \"no `<img>`\" isn't\n // mistaken for an already-processed steady state. See `updateLoadState`.\n private _trackedImg: HTMLImageElement | null | undefined = undefined;\n\n // The <svg> this instance owns `preserveAspectRatio` on, so a\n // consumer-set value is left alone until this instance takes over.\n private _preserveAspectRatioAppliedTo: Element | null = null;\n\n // The child this instance applied `accessibleLabel` to, so a later\n // change or clearing it updates/removes our own value instead of being\n // mistaken for the child's own name.\n private _appliedAccessibleLabelTo: Element | null = null;\n\n protected override update(changes: PropertyValues): void {\n if (changes.has('fit')) {\n validateEnum(this, {\n prop: 'fit',\n value: this.fit,\n valid: ASSET_FIT_VALUES,\n url: DOCS_URL,\n });\n }\n if (changes.has('background')) {\n validateEnum(this, {\n prop: 'background',\n value: this.background,\n valid: ASSET_BACKGROUND_VALUES,\n url: DOCS_URL,\n });\n }\n if (changes.has('loadState')) {\n validateEnum(this, {\n prop: 'load-state',\n value: this.loadState,\n valid: ASSET_LOAD_STATE_VALUES,\n url: DOCS_URL,\n });\n }\n if (\n changes.has('aspectRatio') ||\n changes.has('width') ||\n changes.has('height')\n ) {\n warnIf(\n this,\n typeof this.aspectRatio !== 'undefined' &&\n !ASPECT_RATIO_PATTERN.test(this.aspectRatio),\n `<${this.localName}> expects \"aspect-ratio\" to be a CSS <ratio> (e.g. \"16/9\"), the \"square\" keyword, or a \":\"-separated ratio (e.g. \"16:9\"). Received \"${this._rawAspectRatio}\".`,\n DOCS_URL\n );\n warnIf(\n this,\n typeof this.aspectRatio !== 'undefined' &&\n typeof this.width !== 'undefined' &&\n typeof this.height !== 'undefined',\n `<${this.localName}> \"aspect-ratio\" has no effect when both \"width\" and \"height\" are set.`,\n DOCS_URL\n );\n }\n\n const children = Array.from(this.children);\n if (isDebug()) {\n this.validateSlottedContent(children);\n }\n this.resolveAccessibleName(children);\n this.applyFitToSvg(children);\n this.updateLoadState(children);\n super.update(changes);\n }\n\n /**\n * Warns when the default slot receives more than one child, or a child\n * that isn't an `<img>` or `<svg>`. There is exactly one (default) slot,\n * so its assigned elements are the host's own light DOM children.\n */\n private validateSlottedContent(children: Element[]): void {\n warnIf(\n this,\n children.length > 1,\n `<${this.localName}> only supports a single slotted <img> or <svg> element. Received ${children.length} children.`,\n DOCS_URL\n );\n const [child] = children;\n if (child) {\n const tagName = child.tagName.toLowerCase();\n warnIf(\n this,\n tagName !== 'img' && tagName !== 'svg',\n `<${this.localName}> expects its slotted content to be an <img> or <svg> element. Received <${tagName}>.`,\n DOCS_URL\n );\n }\n }\n\n /**\n * Implements `decorative` and the `accessibleLabel` fallback, in priority\n * order: `decorative` > the child's own name (self-healing a missing\n * `role=\"img\"` on a named `<svg>`) > `accessibleLabel` > warn.\n */\n private resolveAccessibleName(children: Element[]): void {\n if (this.decorative) {\n // Only claim ownership (and write the attribute) when it isn't\n // already present, to avoid redundant attribute writes.\n if (!this.hasAttribute('aria-hidden')) {\n this._appliedAriaHidden = true;\n this.setAttribute('aria-hidden', 'true');\n }\n return;\n }\n if (this._appliedAriaHidden) {\n this.removeAttribute('aria-hidden');\n this._appliedAriaHidden = false;\n }\n\n const [child] = children;\n const tagName = child?.tagName.toLowerCase();\n if (child && tagName !== 'img' && tagName !== 'svg') {\n // Already warned about by validateSlottedContent.\n return;\n }\n\n // Excludes a name this instance applied itself from counting as the\n // child's own.\n const ownsAppliedName = !!child && this._appliedAccessibleLabelTo === child;\n const hasOwnName =\n !!child &&\n !ownsAppliedName &&\n this.hasOwnAccessibleName(child, tagName as 'img' | 'svg');\n\n if (child) {\n if (hasOwnName) {\n if (tagName === 'svg' && !child.hasAttribute('role')) {\n child.setAttribute('role', 'img');\n }\n } else if (this.accessibleLabel) {\n if (tagName === 'img') {\n (child as HTMLImageElement).alt = this.accessibleLabel;\n } else {\n child.setAttribute('role', 'img');\n child.setAttribute('aria-label', this.accessibleLabel);\n }\n this._appliedAccessibleLabelTo = child;\n } else if (ownsAppliedName) {\n // accessibleLabel cleared; remove the name we applied instead of\n // leaving it stale.\n if (tagName === 'img') {\n (child as HTMLImageElement).removeAttribute('alt');\n } else {\n child.removeAttribute('role');\n child.removeAttribute('aria-label');\n }\n this._appliedAccessibleLabelTo = null;\n }\n }\n\n warnIf(\n this,\n !hasOwnName && !this.accessibleLabel,\n `<${this.localName}> requires an accessible name: set \"alt\" on the slotted <img> (or \"aria-label\"/\"aria-labelledby\"/a child <title> on the slotted <svg>), set \"accessible-label\" on <${this.localName}>, or set \"decorative\".`,\n DOCS_URL\n );\n }\n\n /**\n * Whether `child` already has its own accessible name. The `<svg>` branch\n * doesn't require `role=\"img\"` — `resolveAccessibleName` self-heals a\n * missing role separately.\n */\n private hasOwnAccessibleName(\n child: Element,\n tagName: 'img' | 'svg'\n ): boolean {\n const hasAriaName =\n child.hasAttribute('aria-label') || child.hasAttribute('aria-labelledby');\n if (tagName === 'img') {\n return hasAriaName || child.hasAttribute('alt');\n }\n const hasTitleChild = !!child.querySelector(':scope > title');\n return hasAriaName || hasTitleChild;\n }\n\n /**\n * Applies `fit` to a slotted `<svg>` via `preserveAspectRatio`, without\n * overwriting a consumer-set value or writing on every update.\n */\n private applyFitToSvg(children: Element[]): void {\n const [child] = children;\n if (child?.tagName.toLowerCase() !== 'svg') {\n this._preserveAspectRatioAppliedTo = null;\n return;\n }\n const alreadyOwned = this._preserveAspectRatioAppliedTo === child;\n if (child.hasAttribute('preserveAspectRatio') && !alreadyOwned) {\n return;\n }\n const value =\n SVG_PRESERVE_ASPECT_RATIO[this.fit] ?? SVG_PRESERVE_ASPECT_RATIO.cover;\n if (child.getAttribute('preserveAspectRatio') !== value) {\n child.setAttribute('preserveAspectRatio', value);\n }\n this._preserveAspectRatioAppliedTo = child;\n }\n\n /**\n * Tracks `loadState` against the slotted `<img>`, re-wiring listeners only\n * when the tracked element actually changes (a no-op on every other\n * property update, since re-running this for the same `<img>` would\n * incorrectly reset an already-resolved `loadState` back to `'loading'`).\n */\n private updateLoadState(children: Element[]): void {\n const [child] = children;\n const img =\n child?.tagName.toLowerCase() === 'img'\n ? (child as HTMLImageElement)\n : null;\n\n if (img === this._trackedImg) {\n return;\n }\n\n if (this._trackedImg) {\n this._trackedImg.removeEventListener('load', this.handleImgLoad);\n this._trackedImg.removeEventListener('error', this.handleImgError);\n }\n this._trackedImg = img;\n\n if (!img) {\n // No <img> to wait for: a slotted <svg>, an unsupported child, or\n // nothing slotted at all.\n this.loadState = 'loaded';\n return;\n }\n\n this.loadState = 'loading';\n img.addEventListener('load', this.handleImgLoad);\n img.addEventListener('error', this.handleImgError);\n\n // An already-complete `<img>` (e.g. cached) already fired its native\n // `load`/`error` before these listeners attached, so schedule the\n // equivalent transition instead of skipping it - a consumer can always\n // just listen for the events without special-casing the cache case.\n // An `<img>` with no `src` yet is also `complete` but has nothing to\n // report, hence the `currentSrc` check.\n if (img.complete && img.currentSrc) {\n const succeeded = img.naturalWidth > 0;\n queueMicrotask(() => {\n if (this._trackedImg !== img) {\n return;\n }\n if (succeeded) {\n this.handleImgLoad();\n } else {\n this.handleImgError();\n }\n });\n }\n }\n\n private readonly handleImgLoad = (): void => {\n this.loadState = 'loaded';\n this.dispatchEvent(\n new CustomEvent(SWC_ASSET_LOAD_EVENT, {\n bubbles: true,\n composed: true,\n })\n );\n };\n\n private readonly handleImgError = (): void => {\n this.loadState = 'error';\n this.dispatchEvent(\n new CustomEvent<AssetErrorEventDetail>(SWC_ASSET_ERROR_EVENT, {\n bubbles: true,\n composed: true,\n detail: { src: this._trackedImg?.currentSrc ?? '' },\n })\n );\n };\n}\n"],"mappings":"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"}
@@ -9,5 +9,23 @@
9
9
  * OF ANY KIND, either express or implied. See the License for the specific language
10
10
  * governing permissions and limitations under the License.
11
11
  */
12
- export declare const ASSET_VARIANTS: readonly ["file", "folder"];
13
- export type AssetVariant = (typeof ASSET_VARIANTS)[number];
12
+ export declare const ASSET_FIT_VALUES: readonly ["cover", "contain"];
13
+ export type AssetFit = (typeof ASSET_FIT_VALUES)[number];
14
+ export declare const ASSET_BACKGROUND_VALUES: readonly ["transparent", "solid", "checkerboard"];
15
+ export type AssetBackground = (typeof ASSET_BACKGROUND_VALUES)[number];
16
+ export declare const ASSET_LOAD_STATE_VALUES: readonly ["loading", "loaded", "error"];
17
+ export type AssetLoadState = (typeof ASSET_LOAD_STATE_VALUES)[number];
18
+ /** Fired when the slotted `<img>` finishes loading successfully. */
19
+ export declare const SWC_ASSET_LOAD_EVENT = "swc-asset-load";
20
+ /** Fired when the slotted `<img>` fails to load. */
21
+ export declare const SWC_ASSET_ERROR_EVENT = "swc-asset-error";
22
+ /** Detail emitted with `swc-asset-error`. */
23
+ export interface AssetErrorEventDetail {
24
+ src: string;
25
+ }
26
+ declare global {
27
+ interface GlobalEventHandlersEventMap {
28
+ [SWC_ASSET_LOAD_EVENT]: CustomEvent<undefined>;
29
+ [SWC_ASSET_ERROR_EVENT]: CustomEvent<AssetErrorEventDetail>;
30
+ }
31
+ }
@@ -1,6 +1,14 @@
1
1
  //#region components/asset/Asset.types.ts
2
- var e = ["file", "folder"];
2
+ var e = ["cover", "contain"], t = [
3
+ "transparent",
4
+ "solid",
5
+ "checkerboard"
6
+ ], n = [
7
+ "loading",
8
+ "loaded",
9
+ "error"
10
+ ], r = "swc-asset-load", i = "swc-asset-error";
3
11
  //#endregion
4
- export { e as ASSET_VARIANTS };
12
+ export { t as ASSET_BACKGROUND_VALUES, e as ASSET_FIT_VALUES, n as ASSET_LOAD_STATE_VALUES, i as SWC_ASSET_ERROR_EVENT, r as SWC_ASSET_LOAD_EVENT };
5
13
 
6
14
  //# sourceMappingURL=Asset.types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Asset.types.js","names":[],"sources":["../../../components/asset/Asset.types.ts"],"sourcesContent":["/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nexport const ASSET_VARIANTS = [\n 'file',\n 'folder',\n] as const satisfies readonly string[];\n\nexport type AssetVariant = (typeof ASSET_VARIANTS)[number];\n"],"mappings":";AAYA,IAAa,IAAiB,CAC5B,QACA,SACD"}
1
+ {"version":3,"file":"Asset.types.js","names":[],"sources":["../../../components/asset/Asset.types.ts"],"sourcesContent":["/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nexport const ASSET_FIT_VALUES = [\n 'cover',\n 'contain',\n] as const satisfies readonly string[];\n\nexport type AssetFit = (typeof ASSET_FIT_VALUES)[number];\n\nexport const ASSET_BACKGROUND_VALUES = [\n 'transparent',\n 'solid',\n 'checkerboard',\n] as const satisfies readonly string[];\n\nexport type AssetBackground = (typeof ASSET_BACKGROUND_VALUES)[number];\n\nexport const ASSET_LOAD_STATE_VALUES = [\n 'loading',\n 'loaded',\n 'error',\n] as const satisfies readonly string[];\n\nexport type AssetLoadState = (typeof ASSET_LOAD_STATE_VALUES)[number];\n\n// ──────────────────\n// EVENTS\n// ──────────────────\n\n/** Fired when the slotted `<img>` finishes loading successfully. */\nexport const SWC_ASSET_LOAD_EVENT = 'swc-asset-load';\n\n/** Fired when the slotted `<img>` fails to load. */\nexport const SWC_ASSET_ERROR_EVENT = 'swc-asset-error';\n\n/** Detail emitted with `swc-asset-error`. */\nexport interface AssetErrorEventDetail {\n src: string;\n}\n\ndeclare global {\n interface GlobalEventHandlersEventMap {\n [SWC_ASSET_LOAD_EVENT]: CustomEvent<undefined>;\n [SWC_ASSET_ERROR_EVENT]: CustomEvent<AssetErrorEventDetail>;\n }\n}\n"],"mappings":";AAYA,IAAa,IAAmB,CAC9B,SACA,UACD,EAIY,IAA0B;CACrC;CACA;CACA;CACD,EAIY,IAA0B;CACrC;CACA;CACA;CACD,EASY,IAAuB,kBAGvB,IAAwB"}
@@ -1,3 +1,3 @@
1
- import { ASSET_VARIANTS as e } from "./Asset.types.js";
2
- import { AssetBase as t } from "./Asset.base.js";
3
- export { e as ASSET_VARIANTS, t as AssetBase };
1
+ import { ASSET_BACKGROUND_VALUES as e, ASSET_FIT_VALUES as t, ASSET_LOAD_STATE_VALUES as n, SWC_ASSET_ERROR_EVENT as r, SWC_ASSET_LOAD_EVENT as i } from "./Asset.types.js";
2
+ import { AssetBase as a } from "./Asset.base.js";
3
+ export { e as ASSET_BACKGROUND_VALUES, t as ASSET_FIT_VALUES, n as ASSET_LOAD_STATE_VALUES, a as AssetBase, r as SWC_ASSET_ERROR_EVENT, i as SWC_ASSET_LOAD_EVENT };
@@ -65,7 +65,7 @@ export declare abstract class DropzoneBase extends DropzoneBase_base {
65
65
  set dropEffect(value: DropEffect | null);
66
66
  /** @internal */
67
67
  private _dropEffect;
68
- protected constructor();
68
+ constructor();
69
69
  /** @internal */
70
70
  private readonly _sizePropagation;
71
71
  /** @internal */
@@ -1 +1 @@
1
- {"version":3,"file":"Dropzone.base.js","names":[],"sources":["../../../components/dropzone/Dropzone.base.ts"],"sourcesContent":["/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { property } from 'lit/decorators.js';\n\nimport { SpectrumElement } from '@adobe/spectrum-wc-core/element/index.js';\nimport { SizedMixin } from '@adobe/spectrum-wc-core/mixins/index.js';\nimport { validateEnum } from '@adobe/spectrum-wc-core/utils/index.js';\n\nimport { DragAndDropController } from '../../controllers/drag-and-drop-controller/index.js';\nimport { SlotAttributePropagationController } from '../../controllers/slot-attribute-propagation-controller/index.js';\nimport {\n DROP_EFFECTS,\n type DropEffect,\n DROPZONE_DEFAULT_DROP_EFFECT,\n DROPZONE_VALID_SIZES,\n type DropzoneDragLeaveDetail,\n type DropzoneSize,\n SWC_DROPZONE_DRAGLEAVE_EVENT,\n SWC_DROPZONE_DRAGOVER_EVENT,\n SWC_DROPZONE_DROP_EVENT,\n SWC_DROPZONE_SHOULD_ACCEPT_EVENT,\n} from './Dropzone.types.js';\n\n/**\n * Base class for the `<swc-dropzone>` drop zone component.\n *\n * Encapsulates all drag-and-drop event handling, state management, and\n * validation logic. Rendering, ARIA, and CSS are provided by the concrete\n * SWC subclass.\n *\n * @attribute {DropzoneSize} size - Controls the illustrated icon scale and container dimensions.\n *\n * @slot - Slot for the illustrated message and browse control. Hidden automatically when `filled` is true.\n * @slot filled-content - Slot for the uploaded-state content (e.g. an image preview). Shown automatically when `filled` is true; hidden otherwise.\n *\n * @fires swc-dropzone-should-accept - Cancelable event fired on every native `dragover`\n * tick while a drag is over the zone, not just on entry. Cancel to reject the dragged\n * payload and set the cursor to `none`.\n * @fires swc-dropzone-dragover - Fired once when dragged files enter the zone and are\n * accepted; does not repeat on subsequent `dragover` ticks while still hovering.\n * @fires swc-dropzone-dragleave - Fired when an accepted drag leaves the zone after a\n * 100 ms debounce, or immediately when it becomes rejected. Detail is a plain snapshot\n * `{ clientX, clientY, relatedTarget }` captured synchronously from the native event.\n * @fires swc-dropzone-drop - Fired when files are dropped on the zone. `element.dragged`\n * is still `true` when this event fires; it transitions to `false` after dispatch.\n */\nexport abstract class DropzoneBase extends SizedMixin(SpectrumElement, {\n validSizes: DROPZONE_VALID_SIZES,\n}) {\n /**\n * The size of the drop zone.\n *\n * @default m\n */\n declare public size: DropzoneSize;\n\n // ──────────────────────────\n // SHARED API\n // ──────────────────────────\n\n /**\n * Whether files are currently being dragged over the drop zone.\n * Set automatically by the component; also settable to reflect programmatic state.\n *\n * @attr dragged\n * @default false\n */\n @property({ type: Boolean, reflect: true })\n public dragged = false;\n\n /**\n * Whether the drop zone has received a file and is in the filled state.\n * Set by consuming code after a successful drop or browse-file selection to\n * switch the zone to its filled visual.\n *\n * @attr filled\n * @default false\n */\n @property({ type: Boolean, reflect: true })\n public filled = false;\n\n /**\n * The OS drag-cursor feedback shown while a file is held over the zone.\n * Maps directly to `DataTransfer.dropEffect`. Settable via the `drop-effect`\n * attribute, but property changes do not reflect back to the attribute\n * because it controls browser chrome, not component state.\n *\n * @attr drop-effect\n * @type {'copy' | 'move' | 'link' | 'none'}\n * @default 'copy'\n */\n @property({ type: String, attribute: 'drop-effect' })\n public get dropEffect(): DropEffect {\n return this._dropEffect;\n }\n\n public set dropEffect(value: DropEffect | null) {\n // Lit passes `null` here when the `drop-effect` attribute is removed;\n // treat that as \"reset to the default\" rather than an invalid value.\n if (value === null) {\n const oldValue = this._dropEffect;\n this._dropEffect = DROPZONE_DEFAULT_DROP_EFFECT;\n this.requestUpdate('dropEffect', oldValue);\n } else if ((DROP_EFFECTS as readonly string[]).includes(value)) {\n const oldValue = this._dropEffect;\n this._dropEffect = value;\n this.requestUpdate('dropEffect', oldValue);\n } else {\n validateEnum(this, {\n prop: 'drop-effect',\n value,\n valid: DROP_EFFECTS,\n url: 'https://spectrum-web-components.adobe.com/?path=/docs/components-dropzone--docs',\n });\n }\n }\n\n /** @internal */\n private _dropEffect: DropEffect = DROPZONE_DEFAULT_DROP_EFFECT;\n\n // ──────────────────────────\n // IMPLEMENTATION\n // ──────────────────────────\n\n protected constructor() {\n super();\n new DragAndDropController(this, {\n isDragged: () => this.dragged,\n shouldAccept: (event) =>\n this.dispatchEvent(\n new CustomEvent<DragEvent>(SWC_DROPZONE_SHOULD_ACCEPT_EVENT, {\n bubbles: true,\n cancelable: true,\n composed: true,\n detail: event,\n })\n ),\n dropEffect: () => this._dropEffect,\n onDragEnter: (event) => {\n this.dragged = true;\n this.dispatchEvent(\n new CustomEvent<DragEvent>(SWC_DROPZONE_DRAGOVER_EVENT, {\n bubbles: true,\n composed: true,\n detail: event,\n })\n );\n },\n onDragLeave: (snapshot) => {\n this.dragged = false;\n this.dispatchEvent(\n new CustomEvent<DropzoneDragLeaveDetail>(\n SWC_DROPZONE_DRAGLEAVE_EVENT,\n {\n bubbles: true,\n composed: true,\n detail: snapshot,\n }\n )\n );\n },\n onDrop: (event) => {\n // Dispatch before clearing `dragged`; `updated()` handles the status region after `filled` settles.\n this.dispatchEvent(\n new CustomEvent<DragEvent>(SWC_DROPZONE_DROP_EVENT, {\n bubbles: true,\n composed: true,\n detail: event,\n })\n );\n this.dragged = false;\n },\n });\n }\n\n /** @internal */\n private readonly _sizePropagation = new SlotAttributePropagationController(\n this,\n {\n attribute: 'size',\n getValue: () => this.size,\n selector: 'swc-illustrated-message',\n }\n );\n\n /** @internal */\n protected handleDefaultSlotChange(): void {\n this._sizePropagation.propagate();\n }\n}\n"],"mappings":";;;;;;;;;AAwDA,IAAsB,IAAtB,cAA2C,EAAW,GAAiB,EACrE,YAAY,GACb,CAAC,CAAC;CA2CD,IACW,aAAyB;AAClC,SAAO,KAAK;;CAGd,IAAW,WAAW,GAA0B;AAG9C,MAAI,MAAU,MAAM;GAClB,IAAM,IAAW,KAAK;AAEtB,GADA,KAAK,cAAc,GACnB,KAAK,cAAc,cAAc,EAAS;aAChC,EAAmC,SAAS,EAAM,EAAE;GAC9D,IAAM,IAAW,KAAK;AAEtB,GADA,KAAK,cAAc,GACnB,KAAK,cAAc,cAAc,EAAS;QAE1C,GAAa,MAAM;GACjB,MAAM;GACN;GACA,OAAO;GACP,KAAK;GACN,CAAC;;CAWN,cAAwB;AAEtB,EADA,OAAO,iBAzDQ,kBAWD,uBAuCkB,2BA0DE,IAAI,EACtC,MACA;GACE,WAAW;GACX,gBAAgB,KAAK;GACrB,UAAU;GACX,CACF,EAzDC,IAAI,EAAsB,MAAM;GAC9B,iBAAiB,KAAK;GACtB,eAAe,MACb,KAAK,cACH,IAAI,YAAuB,GAAkC;IAC3D,SAAS;IACT,YAAY;IACZ,UAAU;IACV,QAAQ;IACT,CAAC,CACH;GACH,kBAAkB,KAAK;GACvB,cAAc,MAAU;AAEtB,IADA,KAAK,UAAU,IACf,KAAK,cACH,IAAI,YAAuB,GAA6B;KACtD,SAAS;KACT,UAAU;KACV,QAAQ;KACT,CAAC,CACH;;GAEH,cAAc,MAAa;AAEzB,IADA,KAAK,UAAU,IACf,KAAK,cACH,IAAI,YACF,GACA;KACE,SAAS;KACT,UAAU;KACV,QAAQ;KACT,CACF,CACF;;GAEH,SAAS,MAAU;AASjB,IAPA,KAAK,cACH,IAAI,YAAuB,GAAyB;KAClD,SAAS;KACT,UAAU;KACV,QAAQ;KACT,CAAC,CACH,EACD,KAAK,UAAU;;GAElB,CAAC;;CAcJ,0BAA0C;AACxC,OAAK,iBAAiB,WAAW;;;GAxHlC,EAAS;CAAE,MAAM;CAAS,SAAS;CAAM,CAAC,CAAA,EAAA,EAAA,WAAA,WAAA,KAAA,EAAA,KAW1C,EAAS;CAAE,MAAM;CAAS,SAAS;CAAM,CAAC,CAAA,EAAA,EAAA,WAAA,UAAA,KAAA,EAAA,KAa1C,EAAS;CAAE,MAAM;CAAQ,WAAW;CAAe,CAAC,CAAA,EAAA,EAAA,WAAA,cAAA,KAAA"}
1
+ {"version":3,"file":"Dropzone.base.js","names":[],"sources":["../../../components/dropzone/Dropzone.base.ts"],"sourcesContent":["/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { property } from 'lit/decorators.js';\n\nimport { SpectrumElement } from '@adobe/spectrum-wc-core/element/index.js';\nimport { SizedMixin } from '@adobe/spectrum-wc-core/mixins/index.js';\nimport { validateEnum } from '@adobe/spectrum-wc-core/utils/index.js';\n\nimport { DragAndDropController } from '../../controllers/drag-and-drop-controller/index.js';\nimport { SlotAttributePropagationController } from '../../controllers/slot-attribute-propagation-controller/index.js';\nimport {\n DROP_EFFECTS,\n type DropEffect,\n DROPZONE_DEFAULT_DROP_EFFECT,\n DROPZONE_VALID_SIZES,\n type DropzoneDragLeaveDetail,\n type DropzoneSize,\n SWC_DROPZONE_DRAGLEAVE_EVENT,\n SWC_DROPZONE_DRAGOVER_EVENT,\n SWC_DROPZONE_DROP_EVENT,\n SWC_DROPZONE_SHOULD_ACCEPT_EVENT,\n} from './Dropzone.types.js';\n\n/**\n * Base class for the `<swc-dropzone>` drop zone component.\n *\n * Encapsulates all drag-and-drop event handling, state management, and\n * validation logic. Rendering, ARIA, and CSS are provided by the concrete\n * SWC subclass.\n *\n * @attribute {DropzoneSize} size - Controls the illustrated icon scale and container dimensions.\n *\n * @slot - Slot for the illustrated message and browse control. Hidden automatically when `filled` is true.\n * @slot filled-content - Slot for the uploaded-state content (e.g. an image preview). Shown automatically when `filled` is true; hidden otherwise.\n *\n * @fires swc-dropzone-should-accept - Cancelable event fired on every native `dragover`\n * tick while a drag is over the zone, not just on entry. Cancel to reject the dragged\n * payload and set the cursor to `none`.\n * @fires swc-dropzone-dragover - Fired once when dragged files enter the zone and are\n * accepted; does not repeat on subsequent `dragover` ticks while still hovering.\n * @fires swc-dropzone-dragleave - Fired when an accepted drag leaves the zone after a\n * 100 ms debounce, or immediately when it becomes rejected. Detail is a plain snapshot\n * `{ clientX, clientY, relatedTarget }` captured synchronously from the native event.\n * @fires swc-dropzone-drop - Fired when files are dropped on the zone. `element.dragged`\n * is still `true` when this event fires; it transitions to `false` after dispatch.\n */\nexport abstract class DropzoneBase extends SizedMixin(SpectrumElement, {\n validSizes: DROPZONE_VALID_SIZES,\n}) {\n /**\n * The size of the drop zone.\n *\n * @default m\n */\n declare public size: DropzoneSize;\n\n // ──────────────────────────\n // SHARED API\n // ──────────────────────────\n\n /**\n * Whether files are currently being dragged over the drop zone.\n * Set automatically by the component; also settable to reflect programmatic state.\n *\n * @attr dragged\n * @default false\n */\n @property({ type: Boolean, reflect: true })\n public dragged = false;\n\n /**\n * Whether the drop zone has received a file and is in the filled state.\n * Set by consuming code after a successful drop or browse-file selection to\n * switch the zone to its filled visual.\n *\n * @attr filled\n * @default false\n */\n @property({ type: Boolean, reflect: true })\n public filled = false;\n\n /**\n * The OS drag-cursor feedback shown while a file is held over the zone.\n * Maps directly to `DataTransfer.dropEffect`. Settable via the `drop-effect`\n * attribute, but property changes do not reflect back to the attribute\n * because it controls browser chrome, not component state.\n *\n * @attr drop-effect\n * @type {'copy' | 'move' | 'link' | 'none'}\n * @default 'copy'\n */\n @property({ type: String, attribute: 'drop-effect' })\n public get dropEffect(): DropEffect {\n return this._dropEffect;\n }\n\n public set dropEffect(value: DropEffect | null) {\n // Lit passes `null` here when the `drop-effect` attribute is removed;\n // treat that as \"reset to the default\" rather than an invalid value.\n if (value === null) {\n const oldValue = this._dropEffect;\n this._dropEffect = DROPZONE_DEFAULT_DROP_EFFECT;\n this.requestUpdate('dropEffect', oldValue);\n } else if ((DROP_EFFECTS as readonly string[]).includes(value)) {\n const oldValue = this._dropEffect;\n this._dropEffect = value;\n this.requestUpdate('dropEffect', oldValue);\n } else {\n validateEnum(this, {\n prop: 'drop-effect',\n value,\n valid: DROP_EFFECTS,\n url: 'https://spectrum-web-components.adobe.com/?path=/docs/components-dropzone--docs',\n });\n }\n }\n\n /** @internal */\n private _dropEffect: DropEffect = DROPZONE_DEFAULT_DROP_EFFECT;\n\n // ──────────────────────────\n // IMPLEMENTATION\n // ──────────────────────────\n\n constructor() {\n super();\n new DragAndDropController(this, {\n isDragged: () => this.dragged,\n shouldAccept: (event) =>\n this.dispatchEvent(\n new CustomEvent<DragEvent>(SWC_DROPZONE_SHOULD_ACCEPT_EVENT, {\n bubbles: true,\n cancelable: true,\n composed: true,\n detail: event,\n })\n ),\n dropEffect: () => this._dropEffect,\n onDragEnter: (event) => {\n this.dragged = true;\n this.dispatchEvent(\n new CustomEvent<DragEvent>(SWC_DROPZONE_DRAGOVER_EVENT, {\n bubbles: true,\n composed: true,\n detail: event,\n })\n );\n },\n onDragLeave: (snapshot) => {\n this.dragged = false;\n this.dispatchEvent(\n new CustomEvent<DropzoneDragLeaveDetail>(\n SWC_DROPZONE_DRAGLEAVE_EVENT,\n {\n bubbles: true,\n composed: true,\n detail: snapshot,\n }\n )\n );\n },\n onDrop: (event) => {\n // Dispatch before clearing `dragged`; `updated()` handles the status region after `filled` settles.\n this.dispatchEvent(\n new CustomEvent<DragEvent>(SWC_DROPZONE_DROP_EVENT, {\n bubbles: true,\n composed: true,\n detail: event,\n })\n );\n this.dragged = false;\n },\n });\n }\n\n /** @internal */\n private readonly _sizePropagation = new SlotAttributePropagationController(\n this,\n {\n attribute: 'size',\n getValue: () => this.size,\n selector: 'swc-illustrated-message',\n }\n );\n\n /** @internal */\n protected handleDefaultSlotChange(): void {\n this._sizePropagation.propagate();\n }\n}\n"],"mappings":";;;;;;;;;AAwDA,IAAsB,IAAtB,cAA2C,EAAW,GAAiB,EACrE,YAAY,GACb,CAAC,CAAC;CA2CD,IACW,aAAyB;AAClC,SAAO,KAAK;;CAGd,IAAW,WAAW,GAA0B;AAG9C,MAAI,MAAU,MAAM;GAClB,IAAM,IAAW,KAAK;AAEtB,GADA,KAAK,cAAc,GACnB,KAAK,cAAc,cAAc,EAAS;aAChC,EAAmC,SAAS,EAAM,EAAE;GAC9D,IAAM,IAAW,KAAK;AAEtB,GADA,KAAK,cAAc,GACnB,KAAK,cAAc,cAAc,EAAS;QAE1C,GAAa,MAAM;GACjB,MAAM;GACN;GACA,OAAO;GACP,KAAK;GACN,CAAC;;CAWN,cAAc;AAEZ,EADA,OAAO,iBAzDQ,kBAWD,uBAuCkB,2BA0DE,IAAI,EACtC,MACA;GACE,WAAW;GACX,gBAAgB,KAAK;GACrB,UAAU;GACX,CACF,EAzDC,IAAI,EAAsB,MAAM;GAC9B,iBAAiB,KAAK;GACtB,eAAe,MACb,KAAK,cACH,IAAI,YAAuB,GAAkC;IAC3D,SAAS;IACT,YAAY;IACZ,UAAU;IACV,QAAQ;IACT,CAAC,CACH;GACH,kBAAkB,KAAK;GACvB,cAAc,MAAU;AAEtB,IADA,KAAK,UAAU,IACf,KAAK,cACH,IAAI,YAAuB,GAA6B;KACtD,SAAS;KACT,UAAU;KACV,QAAQ;KACT,CAAC,CACH;;GAEH,cAAc,MAAa;AAEzB,IADA,KAAK,UAAU,IACf,KAAK,cACH,IAAI,YACF,GACA;KACE,SAAS;KACT,UAAU;KACV,QAAQ;KACT,CACF,CACF;;GAEH,SAAS,MAAU;AASjB,IAPA,KAAK,cACH,IAAI,YAAuB,GAAyB;KAClD,SAAS;KACT,UAAU;KACV,QAAQ;KACT,CAAC,CACH,EACD,KAAK,UAAU;;GAElB,CAAC;;CAcJ,0BAA0C;AACxC,OAAK,iBAAiB,WAAW;;;GAxHlC,EAAS;CAAE,MAAM;CAAS,SAAS;CAAM,CAAC,CAAA,EAAA,EAAA,WAAA,WAAA,KAAA,EAAA,KAW1C,EAAS;CAAE,MAAM;CAAS,SAAS;CAAM,CAAC,CAAA,EAAA,EAAA,WAAA,UAAA,KAAA,EAAA,KAa1C,EAAS;CAAE,MAAM;CAAQ,WAAW;CAAe,CAAC,CAAA,EAAA,EAAA,WAAA,cAAA,KAAA"}
@@ -151,23 +151,7 @@ export declare abstract class PopoverBase extends SpectrumElement {
151
151
  private _interactiveElement;
152
152
  /** The positioning anchor (an element or a `VirtualTrigger`). */
153
153
  private _anchor;
154
- /** The element the click-to-toggle listeners are currently attached to. */
155
- private _clickTrigger;
156
- /**
157
- * True between a trigger press start (`pointerdown`/`touchstart`) and its
158
- * `click`, so a light-dismiss inside that window is attributed to the press.
159
- * Both events open it, covering touch (where the dismiss can fire off
160
- * `touchstart` before `pointerdown`).
161
- */
162
- private _triggerPointerActive;
163
- /** Cancels the pending press-end listeners armed in `_onTriggerPressStart`. */
164
- private _pressEndAbort;
165
- /**
166
- * Set when the trigger press light-dismissed an open popover (an `'outside'`
167
- * close observed while `_triggerPointerActive`), so the trailing `click` of
168
- * that same gesture is read as the close rather than a reopen.
169
- */
170
- private _dismissedByTriggerPress;
154
+ private readonly _pressGuard;
171
155
  /** Cause of the in-progress close, read when dispatching `swc-close`. */
172
156
  private _closeSource;
173
157
  /** Suppresses the open/close effect when `open` is synced from a native event. */
@@ -200,10 +184,6 @@ export declare abstract class PopoverBase extends SpectrumElement {
200
184
  protected updated(changedProperties: PropertyValues): void;
201
185
  private _positioningChanged;
202
186
  private _wireTrigger;
203
- private _removeTriggerListeners;
204
- private _onTriggerPressStart;
205
- private _onTriggerPressEnd;
206
- private _onTriggerClick;
207
187
  private _clearTriggerAria;
208
188
  private _isFocusWithin;
209
189
  private _startPositioning;