@carbon/ibm-products-web-components 0.36.0 → 0.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/custom-elements.json +227 -26
  2. package/es/components/action-set/action-set.d.ts +109 -0
  3. package/es/components/action-set/action-set.d.ts.map +1 -0
  4. package/es/components/action-set/action-set.js +275 -0
  5. package/es/components/action-set/action-set.js.map +1 -0
  6. package/es/components/action-set/action-set.scss.js +15 -0
  7. package/es/components/action-set/action-set.scss.js.map +1 -0
  8. package/es/components/action-set/index.d.ts +11 -0
  9. package/es/components/action-set/index.d.ts.map +1 -0
  10. package/es/components/action-set/index.js +8 -0
  11. package/es/components/big-number/big-number-skeleton.js +1 -1
  12. package/es/components/big-number/big-number.js +1 -1
  13. package/es/components/checklist/checklist-icon.js +1 -1
  14. package/es/components/checklist/checklist-item.js +1 -1
  15. package/es/components/checklist/checklist.js +1 -1
  16. package/es/components/coachmark/coachmark-tagline/coachmark-tagline.d.ts +1 -0
  17. package/es/components/coachmark/coachmark-tagline/coachmark-tagline.d.ts.map +1 -1
  18. package/es/components/coachmark/coachmark-tagline/coachmark-tagline.js +4 -1
  19. package/es/components/coachmark/coachmark-tagline/coachmark-tagline.js.map +1 -1
  20. package/es/components/coachmark/coachmark-tagline/coachmark-tagline.scss.js +1 -1
  21. package/es/components/coachmark/coachmark-tagline/coachmark-tagline.scss.js.map +1 -1
  22. package/es/components/coachmark/coachmark.d.ts +5 -1
  23. package/es/components/coachmark/coachmark.d.ts.map +1 -1
  24. package/es/components/coachmark/coachmark.js +10 -5
  25. package/es/components/coachmark/coachmark.js.map +1 -1
  26. package/es/components/guide-banner/guide-banner.js +2 -2
  27. package/es/components/interstitial-screen/interstitial-screen-body.js +1 -1
  28. package/es/components/interstitial-screen/interstitial-screen-body.scss.js +1 -1
  29. package/es/components/interstitial-screen/interstitial-screen-body.scss.js.map +1 -1
  30. package/es/components/interstitial-screen/interstitial-screen-footer.d.ts +1 -0
  31. package/es/components/interstitial-screen/interstitial-screen-footer.d.ts.map +1 -1
  32. package/es/components/interstitial-screen/interstitial-screen-footer.js +20 -19
  33. package/es/components/interstitial-screen/interstitial-screen-footer.js.map +1 -1
  34. package/es/components/interstitial-screen/interstitial-screen-footer.scss.js +1 -1
  35. package/es/components/interstitial-screen/interstitial-screen-footer.scss.js.map +1 -1
  36. package/es/components/interstitial-screen/interstitial-screen-header.scss.js +1 -1
  37. package/es/components/interstitial-screen/interstitial-screen.scss.js +1 -1
  38. package/es/components/notification-panel/notification-panel.js +2 -2
  39. package/es/components/notification-panel/notification.js +1 -1
  40. package/es/components/options-tile/options-tile.js +2 -2
  41. package/es/components/page-header/page-header-breadcrumb.js +1 -1
  42. package/es/components/page-header/page-header-content.js +1 -1
  43. package/es/components/page-header/page-header-scroller.js +2 -2
  44. package/es/components/side-panel/side-panel.js +2 -2
  45. package/es/components/tearsheet/tearsheet.js +2 -2
  46. package/es/components/tearsheet-preview/tearsheet-scroller.js +2 -2
  47. package/es/components/truncated-text/truncated-text.js +1 -1
  48. package/es/components/user-avatar/user-avatar.js +1 -1
  49. package/es/index.d.ts +1 -0
  50. package/es/index.d.ts.map +1 -1
  51. package/es/index.js +2 -1
  52. package/es/package.js +1 -1
  53. package/es-custom/components/action-set/action-set.js +275 -0
  54. package/es-custom/components/action-set/action-set.js.map +1 -0
  55. package/es-custom/components/action-set/action-set.scss.js +15 -0
  56. package/es-custom/components/action-set/action-set.scss.js.map +1 -0
  57. package/es-custom/components/action-set/index.js +8 -0
  58. package/es-custom/components/big-number/big-number-skeleton.js +1 -1
  59. package/es-custom/components/big-number/big-number.js +1 -1
  60. package/es-custom/components/checklist/checklist-icon.js +1 -1
  61. package/es-custom/components/checklist/checklist-item.js +1 -1
  62. package/es-custom/components/checklist/checklist.js +1 -1
  63. package/es-custom/components/coachmark/coachmark-tagline/coachmark-tagline.js +4 -1
  64. package/es-custom/components/coachmark/coachmark-tagline/coachmark-tagline.js.map +1 -1
  65. package/es-custom/components/coachmark/coachmark-tagline/coachmark-tagline.scss.js +1 -1
  66. package/es-custom/components/coachmark/coachmark-tagline/coachmark-tagline.scss.js.map +1 -1
  67. package/es-custom/components/coachmark/coachmark.js +10 -5
  68. package/es-custom/components/coachmark/coachmark.js.map +1 -1
  69. package/es-custom/components/guide-banner/guide-banner.js +2 -2
  70. package/es-custom/components/interstitial-screen/interstitial-screen-body.js +1 -1
  71. package/es-custom/components/interstitial-screen/interstitial-screen-body.scss.js +1 -1
  72. package/es-custom/components/interstitial-screen/interstitial-screen-body.scss.js.map +1 -1
  73. package/es-custom/components/interstitial-screen/interstitial-screen-footer.js +20 -19
  74. package/es-custom/components/interstitial-screen/interstitial-screen-footer.js.map +1 -1
  75. package/es-custom/components/interstitial-screen/interstitial-screen-footer.scss.js +1 -1
  76. package/es-custom/components/interstitial-screen/interstitial-screen-footer.scss.js.map +1 -1
  77. package/es-custom/components/interstitial-screen/interstitial-screen-header.scss.js +1 -1
  78. package/es-custom/components/interstitial-screen/interstitial-screen.scss.js +1 -1
  79. package/es-custom/components/notification-panel/notification-panel.js +2 -2
  80. package/es-custom/components/notification-panel/notification.js +1 -1
  81. package/es-custom/components/options-tile/options-tile.js +2 -2
  82. package/es-custom/components/page-header/page-header-breadcrumb.js +1 -1
  83. package/es-custom/components/page-header/page-header-content.js +1 -1
  84. package/es-custom/components/page-header/page-header-scroller.js +2 -2
  85. package/es-custom/components/side-panel/side-panel.js +2 -2
  86. package/es-custom/components/tearsheet/tearsheet.js +2 -2
  87. package/es-custom/components/tearsheet-preview/tearsheet-scroller.js +2 -2
  88. package/es-custom/components/truncated-text/truncated-text.js +1 -1
  89. package/es-custom/components/user-avatar/user-avatar.js +1 -1
  90. package/es-custom/index.js +2 -1
  91. package/es-custom/package.js +1 -1
  92. package/lib/components/action-set/action-set.d.ts +109 -0
  93. package/lib/components/action-set/action-set.d.ts.map +1 -0
  94. package/lib/components/action-set/index.d.ts +11 -0
  95. package/lib/components/action-set/index.d.ts.map +1 -0
  96. package/lib/components/coachmark/coachmark-tagline/coachmark-tagline.d.ts +1 -0
  97. package/lib/components/coachmark/coachmark-tagline/coachmark-tagline.d.ts.map +1 -1
  98. package/lib/components/coachmark/coachmark.d.ts +5 -1
  99. package/lib/components/coachmark/coachmark.d.ts.map +1 -1
  100. package/lib/components/interstitial-screen/interstitial-screen-footer.d.ts +1 -0
  101. package/lib/components/interstitial-screen/interstitial-screen-footer.d.ts.map +1 -1
  102. package/lib/index.d.ts +1 -0
  103. package/lib/index.d.ts.map +1 -1
  104. package/package.json +4 -4
  105. package/scss/components/action-set/action-set.scss +71 -0
  106. package/scss/components/coachmark/coachmark-tagline/coachmark-tagline.scss +18 -0
  107. package/scss/components/interstitial-screen/interstitial-screen-body.scss +6 -0
  108. package/scss/components/interstitial-screen/interstitial-screen-footer.scss +34 -6
  109. package/telemetry.yml +11 -0
@@ -0,0 +1,109 @@
1
+ /**
2
+ * @license
3
+ *
4
+ * Copyright IBM Corp. 2026
5
+ *
6
+ * This source code is licensed under the Apache-2.0 license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+ import { LitElement } from 'lit';
10
+ import CDSButton from '@carbon/web-components/es/components/button/button.js';
11
+ import '@carbon/web-components/es/components/button/index.js';
12
+ export declare const ButtonSizes: readonly ["sm", "md", "lg", "xl", "2xl"];
13
+ export type ButtonSize = (typeof ButtonSizes)[number];
14
+ export type ButtonKind = 'primary' | 'secondary' | 'tertiary' | 'danger' | 'ghost' | 'danger--ghost';
15
+ /**
16
+ * Action button configuration that extends CDSButton properties.
17
+ * Includes all standard button attributes plus custom action-specific properties.
18
+ */
19
+ export interface ActionButton extends Partial<Omit<CDSButton, 'kind'>> {
20
+ kind?: ButtonKind;
21
+ label?: string;
22
+ loading?: boolean;
23
+ onClick?: (event: Event) => void;
24
+ [key: string]: any;
25
+ }
26
+ /**
27
+ * Action Set component - A specialized button set with validation and ordering logic.
28
+ * Extends Carbon's button-set with additional features for action buttons.
29
+ *
30
+ * @element c4p-action-set
31
+ * @slot - Slot for cds-button elements (used when actions prop is not provided)
32
+ */
33
+ export declare class CDSActionSet extends LitElement {
34
+ /**
35
+ * Number of slotted buttons (computed internally).
36
+ */
37
+ private _slottedButtonCount;
38
+ /**
39
+ * Computed property: `true` if the buttons are currently stacked.
40
+ * This is derived from size, disableStacking, and button count.
41
+ */
42
+ get stacked(): boolean;
43
+ /**
44
+ * The size of buttons to use for the actions.
45
+ */
46
+ buttonSize?: ButtonSize;
47
+ /**
48
+ * The size of the action set. Different button arrangements are used at
49
+ * different sizes, to make best use of the available space.
50
+ */
51
+ size: ButtonSize;
52
+ /**
53
+ * When true, prevents automatic stacking of buttons even when size would
54
+ * normally trigger stacking (e.g., 'sm' size or 'md' with 3+ actions).
55
+ * Buttons will remain in a horizontal layout.
56
+ */
57
+ disableStacking: boolean;
58
+ /**
59
+ * Array of action button configurations. When provided, buttons will be
60
+ * rendered internally instead of using slotted content.
61
+ */
62
+ actions: ActionButton[];
63
+ static styles: any;
64
+ /**
65
+ * Applies common button styling (size, classes, expressive attribute)
66
+ * @private
67
+ */
68
+ private _applyButtonStyles;
69
+ /**
70
+ * Processes actions: validates, determines stacking, and sorts
71
+ * @private
72
+ */
73
+ private _processActions;
74
+ /**
75
+ * Handler for @slotchange, processes and orders buttons based on ActionSet logic
76
+ *
77
+ * @private
78
+ */
79
+ protected _handleSlotChange(event: Event): void;
80
+ /**
81
+ * Reorders the button elements in the DOM based on the sorted actions
82
+ * and applies appropriate styling
83
+ *
84
+ * @private
85
+ */
86
+ private _reorderButtons;
87
+ /**
88
+ * When a button within the action-set is focused, hide the margin on both sides
89
+ * of the focused button, by applying the appropriate styles to its sibling
90
+ *
91
+ * @private
92
+ */
93
+ private _hideSiblingMargin;
94
+ connectedCallback(): void;
95
+ disconnectedCallback(): void;
96
+ /**
97
+ * Renders buttons from the actions prop
98
+ * @private
99
+ */
100
+ private _renderActionsFromProp;
101
+ render(): import("lit-html").TemplateResult<1>;
102
+ }
103
+ declare global {
104
+ interface HTMLElementTagNameMap {
105
+ 'c4p-action-set': CDSActionSet;
106
+ }
107
+ }
108
+ export default CDSActionSet;
109
+ //# sourceMappingURL=action-set.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-set.d.ts","sourceRoot":"","sources":["../../../src/components/action-set/action-set.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAQ,UAAU,EAAE,MAAM,KAAK,CAAC;AAOvC,OAAO,SAAS,MAAM,uDAAuD,CAAC;AAC9E,OAAO,sDAAsD,CAAC;AAK9D,eAAO,MAAM,WAAW,0CAA2C,CAAC;AACpE,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtD,MAAM,MAAM,UAAU,GAClB,SAAS,GACT,WAAW,GACX,UAAU,GACV,QAAQ,GACR,OAAO,GACP,eAAe,CAAC;AAEpB;;;GAGG;AACH,MAAM,WAAW,YAAa,SAAQ,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAEpE,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAGjC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AA6GD;;;;;;GAMG;AACH,qBACa,YAAa,SAAQ,UAAU;IAC1C;;OAEG;IAEH,OAAO,CAAC,mBAAmB,CAAK;IAEhC;;;OAGG;IACH,IAAI,OAAO,IAAI,OAAO,CAGrB;IAED;;OAEG;IAEH,UAAU,CAAC,EAAE,UAAU,CAAC;IAExB;;;OAGG;IAEH,IAAI,EAAE,UAAU,CAAQ;IAExB;;;;OAIG;IAEH,eAAe,EAAE,OAAO,CAAS;IAEjC;;;OAGG;IAEH,OAAO,EAAE,YAAY,EAAE,CAAM;IAE7B,MAAM,CAAC,MAAM,MAAU;IAEvB;;;OAGG;IACH,OAAO,CAAC,kBAAkB;IAc1B;;;OAGG;IACH,OAAO,CAAC,eAAe;IAoBvB;;;;OAIG;IACH,SAAS,CAAC,iBAAiB,CAAC,KAAK,EAAE,KAAK;IA6CxC;;;;;OAKG;IACH,OAAO,CAAC,eAAe;IAmBvB;;;;;OAKG;IACH,OAAO,CAAC,kBAAkB,CA+BxB;IAEF,iBAAiB;IAMjB,oBAAoB;IAMpB;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IA8D9B,MAAM;CAyCP;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,gBAAgB,EAAE,YAAY,CAAC;KAChC;CACF;AAED,eAAe,YAAY,CAAC"}
@@ -0,0 +1,275 @@
1
+ /**
2
+ * Copyright IBM Corp. 2020, 2026
3
+ *
4
+ * This source code is licensed under the Apache-2.0 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ import { carbonPrefix, prefix } from "../../globals/settings.js";
9
+ import action_set_default$1 from "./action-set.scss.js";
10
+ import pconsole_default from "../../globals/internal/pconsole.js";
11
+ import { __decorate } from "../../_virtual/_@oxc-project_runtime@0.112.0/helpers/decorate.js";
12
+ import { classMap } from "lit/directives/class-map.js";
13
+ import { LitElement, html } from "lit";
14
+ import { property, state } from "lit/decorators.js";
15
+ import { ref } from "lit/directives/ref.js";
16
+ import { carbonElement } from "@carbon/web-components/es/globals/decorators/carbon-element";
17
+ import "@carbon/web-components/es/components/button/index.js";
18
+
19
+ //#region src/components/action-set/action-set.ts
20
+ /**
21
+ * @license
22
+ *
23
+ * Copyright IBM Corp. 2026
24
+ *
25
+ * This source code is licensed under the Apache-2.0 license found in the
26
+ * LICENSE file in the root directory of this source tree.
27
+ */
28
+ const blockClass = `${prefix}--action-set`;
29
+ const ButtonSizes = [
30
+ "sm",
31
+ "md",
32
+ "lg",
33
+ "xl",
34
+ "2xl"
35
+ ];
36
+ const defaultKind = "primary";
37
+ /**
38
+ * Determines if buttons should be stacked based on size and number of actions
39
+ */
40
+ const willStack = (size, numberOfActions) => size === "sm" || size === "md" && numberOfActions > 2;
41
+ /**
42
+ * Returns the order priority for a button kind
43
+ * Lower numbers appear first (or last when stacking)
44
+ */
45
+ const buttonOrder = (kind) => ({
46
+ ghost: 1,
47
+ "danger--ghost": 2,
48
+ tertiary: 3,
49
+ danger: 5,
50
+ primary: 6
51
+ })[kind] ?? 4;
52
+ /**
53
+ * Sorts actions based on button kind and stacking mode
54
+ * When not stacking: ghost first, primary last
55
+ * When stacking: primary first, ghost last
56
+ */
57
+ const sortActions = (actions, stacking) => {
58
+ const sortedActions = [...actions];
59
+ sortedActions.sort((action1, action2) => (buttonOrder(action1.kind || defaultKind) - buttonOrder(action2.kind || defaultKind)) * (stacking ? -1 : 1));
60
+ return sortedActions;
61
+ };
62
+ /**
63
+ * Validates action set configuration and returns problems
64
+ */
65
+ const validateActionSet = (actions, size) => {
66
+ if (!actions || actions.length === 0) return [];
67
+ const problems = [];
68
+ const stacking = willStack(size, actions.length);
69
+ const countActions = (kind) => actions.filter((action) => (action.kind || defaultKind) === kind).length;
70
+ const primaryActions = countActions("primary");
71
+ const secondaryActions = countActions("secondary");
72
+ const tertiaryActions = countActions("tertiary");
73
+ const dangerActions = countActions("danger");
74
+ const ghostActions = countActions("ghost") + countActions("danger--ghost");
75
+ if (stacking && actions.length > 3) problems.push("you cannot have more than three actions in this size of ActionSet");
76
+ if (actions.length > 4) problems.push("you cannot have more than four actions in an ActionSet");
77
+ if (primaryActions > 1) problems.push("you cannot have more than one 'primary' action in an ActionSet");
78
+ if (ghostActions > 1) problems.push("you cannot have more than one 'ghost' action in an ActionSet");
79
+ if (stacking && actions.length > 1 && ghostActions > 0) problems.push("you cannot have a 'ghost' button in conjunction with other action types in this size of ActionSet");
80
+ if (actions.length > primaryActions + secondaryActions + tertiaryActions + dangerActions + ghostActions) problems.push("you can only have 'primary', 'danger', 'secondary', 'tertiary', 'ghost' and 'danger--ghost' buttons in an ActionSet");
81
+ return problems;
82
+ };
83
+ let CDSActionSet = class CDSActionSet extends LitElement {
84
+ constructor(..._args) {
85
+ super(..._args);
86
+ this._slottedButtonCount = 0;
87
+ this.size = "md";
88
+ this.disableStacking = false;
89
+ this.actions = [];
90
+ this._hideSiblingMargin = () => {
91
+ let items = [];
92
+ const slot = this.shadowRoot?.querySelector("slot");
93
+ if (slot) items = slot.assignedElements().filter((el) => el.tagName.toLowerCase() === `${carbonPrefix}-button`);
94
+ if (items.length === 0 && this.shadowRoot) items = Array.from(this.shadowRoot.querySelectorAll(`${carbonPrefix}-button`));
95
+ if (items.length === 0) return;
96
+ const focusedIndex = items.findIndex((el) => el.matches(":focus-within"));
97
+ items.forEach((el, idx) => {
98
+ const shouldHide = focusedIndex >= 0 && (idx === focusedIndex || idx === focusedIndex + 1);
99
+ el.toggleAttribute("hide-margin", shouldHide);
100
+ });
101
+ };
102
+ }
103
+ /**
104
+ * Computed property: `true` if the buttons are currently stacked.
105
+ * This is derived from size, disableStacking, and button count.
106
+ */
107
+ get stacked() {
108
+ const buttonCount = this.actions?.length || this._slottedButtonCount;
109
+ return this.disableStacking ? false : willStack(this.size, buttonCount);
110
+ }
111
+ static {
112
+ this.styles = action_set_default$1;
113
+ }
114
+ /**
115
+ * Applies common button styling (size, classes, expressive attribute)
116
+ * @private
117
+ */
118
+ _applyButtonStyles(button, kind) {
119
+ if (this.buttonSize) button.setAttribute("size", this.buttonSize);
120
+ button.classList.add(`${blockClass}__action-button`);
121
+ if (kind === "ghost" || kind === "danger--ghost") button.classList.add(`${blockClass}__action-button--ghost`);
122
+ button.setAttribute("is-expressive", "true");
123
+ }
124
+ /**
125
+ * Processes actions: validates, determines stacking, and sorts
126
+ * @private
127
+ */
128
+ _processActions(actions) {
129
+ const problems = validateActionSet(actions, this.size);
130
+ const stacking = this.disableStacking ? false : willStack(this.size, actions.length);
131
+ const sortedActions = sortActions(actions, stacking);
132
+ if (problems.length > 0) pconsole_default.warn(`Invalid actions in ActionSet: ${problems.join(", and ")}.`);
133
+ return {
134
+ sortedActions,
135
+ stacking,
136
+ problems
137
+ };
138
+ }
139
+ /**
140
+ * Handler for @slotchange, processes and orders buttons based on ActionSet logic
141
+ *
142
+ * @private
143
+ */
144
+ _handleSlotChange(event) {
145
+ const childItems = event.target.assignedNodes().filter((elem) => elem.matches !== void 0 ? elem.matches(`${carbonPrefix}-button`) : false);
146
+ if (childItems.length === 0) return;
147
+ const actions = childItems.map((button) => {
148
+ const kind = button.getAttribute("kind");
149
+ const disabled = button.hasAttribute("disabled");
150
+ const label = button.textContent?.trim() || "";
151
+ return {
152
+ kind: kind || "primary",
153
+ disabled,
154
+ label
155
+ };
156
+ });
157
+ const { sortedActions } = this._processActions(actions);
158
+ this._slottedButtonCount = childItems.length;
159
+ this._reorderButtons(childItems, sortedActions);
160
+ const update = new CustomEvent(`${prefix}-action-set-update`, {
161
+ bubbles: true,
162
+ cancelable: true,
163
+ composed: true
164
+ });
165
+ this.dispatchEvent(update);
166
+ }
167
+ /**
168
+ * Reorders the button elements in the DOM based on the sorted actions
169
+ * and applies appropriate styling
170
+ *
171
+ * @private
172
+ */
173
+ _reorderButtons(buttons, sortedActions) {
174
+ const buttonMap = /* @__PURE__ */ new Map();
175
+ buttons.forEach((button) => {
176
+ const label = button.textContent?.trim() || "";
177
+ buttonMap.set(label, button);
178
+ });
179
+ sortedActions.forEach((action) => {
180
+ const button = buttonMap.get(action.label || "");
181
+ if (button) this._applyButtonStyles(button, action.kind);
182
+ });
183
+ }
184
+ connectedCallback() {
185
+ super.connectedCallback();
186
+ this.addEventListener("focusin", this._hideSiblingMargin);
187
+ this.addEventListener("focusout", this._hideSiblingMargin);
188
+ }
189
+ disconnectedCallback() {
190
+ super.disconnectedCallback();
191
+ this.removeEventListener("focusin", this._hideSiblingMargin);
192
+ this.removeEventListener("focusout", this._hideSiblingMargin);
193
+ }
194
+ /**
195
+ * Renders buttons from the actions prop
196
+ * @private
197
+ */
198
+ _renderActionsFromProp() {
199
+ if (!this.actions || this.actions.length === 0) return null;
200
+ const { sortedActions } = this._processActions(this.actions);
201
+ return sortedActions.map((action) => {
202
+ const { kind = "primary", label = "", disabled = false, loading = false, onClick, class: customClass, ...rest } = action;
203
+ const buttonClasses = classMap({
204
+ [`${blockClass}__action-button`]: true,
205
+ [`${blockClass}__action-button--ghost`]: kind === "ghost" || kind === "danger--ghost",
206
+ ...customClass ? { [customClass]: true } : {}
207
+ });
208
+ const buttonRef = (el) => {
209
+ if (el && rest) Object.entries(rest).forEach(([key, value]) => {
210
+ if (value !== void 0 && value !== null) if (typeof value === "boolean") if (value) el.setAttribute(key, "");
211
+ else el.removeAttribute(key);
212
+ else el.setAttribute(key, String(value));
213
+ });
214
+ };
215
+ return html`
216
+ <cds-button
217
+ ${ref(buttonRef)}
218
+ class="${buttonClasses}"
219
+ kind="${kind}"
220
+ size="${this.buttonSize}"
221
+ ?disabled="${disabled || loading}"
222
+ is-expressive="true"
223
+ @click="${typeof onClick === "function" ? onClick : () => {}}"
224
+ >
225
+ ${label}
226
+ </cds-button>
227
+ `;
228
+ });
229
+ }
230
+ render() {
231
+ const { actions, _slottedButtonCount, stacked } = this;
232
+ const buttonCount = actions?.length || _slottedButtonCount;
233
+ const defaultClasses = {
234
+ [blockClass]: true,
235
+ [`${blockClass}--row-single`]: !stacked && buttonCount === 1,
236
+ [`${blockClass}--row-double`]: !stacked && buttonCount === 2,
237
+ [`${blockClass}--row-triple`]: !stacked && buttonCount === 3,
238
+ [`${blockClass}--row-quadruple`]: !stacked && buttonCount >= 4,
239
+ [`${blockClass}--stacking`]: stacked,
240
+ [`${blockClass}--${this.size}`]: true
241
+ };
242
+ if (actions && actions.length > 0) return html`<div
243
+ class="${classMap({
244
+ ...defaultClasses,
245
+ [`${carbonPrefix}--btn-set--stacked`]: stacked,
246
+ [`${carbonPrefix}--btn-set`]: true
247
+ })}"
248
+ part="action-set"
249
+ role="list"
250
+ >
251
+ ${this._renderActionsFromProp()}
252
+ </div>`;
253
+ return html`<div class="${classMap({
254
+ ...defaultClasses,
255
+ [`${carbonPrefix}--btn-set--stacked`]: stacked,
256
+ [`${carbonPrefix}--btn-set`]: true
257
+ })}" part="action-set" role="list">
258
+ <slot @slotchange="${this._handleSlotChange}"></slot>
259
+ </div>`;
260
+ }
261
+ };
262
+ __decorate([state()], CDSActionSet.prototype, "_slottedButtonCount", void 0);
263
+ __decorate([property({ attribute: "button-size" })], CDSActionSet.prototype, "buttonSize", void 0);
264
+ __decorate([property()], CDSActionSet.prototype, "size", void 0);
265
+ __decorate([property({
266
+ type: Boolean,
267
+ attribute: "disable-stacking"
268
+ })], CDSActionSet.prototype, "disableStacking", void 0);
269
+ __decorate([property({ type: Array })], CDSActionSet.prototype, "actions", void 0);
270
+ CDSActionSet = __decorate([carbonElement(`${prefix}-action-set`)], CDSActionSet);
271
+ var action_set_default = CDSActionSet;
272
+
273
+ //#endregion
274
+ export { ButtonSizes, CDSActionSet, action_set_default as default };
275
+ //# sourceMappingURL=action-set.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-set.js","names":["styles","customElement"],"sources":["../../../src/components/action-set/action-set.ts"],"sourcesContent":["/**\n * @license\n *\n * Copyright IBM Corp. 2026\n *\n * This source code is licensed under the Apache-2.0 license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport { classMap } from 'lit/directives/class-map.js';\nimport { html, LitElement } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { ref } from 'lit/directives/ref.js';\nimport { prefix, carbonPrefix } from '../../globals/settings';\nimport { carbonElement as customElement } from '@carbon/web-components/es/globals/decorators/carbon-element';\nimport styles from './action-set.scss?lit';\nimport pconsole from '../../globals/internal/pconsole';\nimport CDSButton from '@carbon/web-components/es/components/button/button.js';\nimport '@carbon/web-components/es/components/button/index.js';\n\nconst blockClass = `${prefix}--action-set`;\n\n// Type definitions\nexport const ButtonSizes = ['sm', 'md', 'lg', 'xl', '2xl'] as const;\nexport type ButtonSize = (typeof ButtonSizes)[number];\n\nexport type ButtonKind =\n | 'primary'\n | 'secondary'\n | 'tertiary'\n | 'danger'\n | 'ghost'\n | 'danger--ghost';\n\n/**\n * Action button configuration that extends CDSButton properties.\n * Includes all standard button attributes plus custom action-specific properties.\n */\nexport interface ActionButton extends Partial<Omit<CDSButton, 'kind'>> {\n // Action-specific properties (override CDSButton types where needed)\n kind?: ButtonKind;\n label?: string;\n loading?: boolean;\n onClick?: (event: Event) => void;\n\n // Allow any other HTML attributes or custom properties\n [key: string]: any;\n}\n\nconst defaultKind: ButtonKind = 'primary';\n\n/**\n * Determines if buttons should be stacked based on size and number of actions\n */\nconst willStack = (size: ButtonSize, numberOfActions: number): boolean =>\n size === 'sm' || (size === 'md' && numberOfActions > 2);\n\n/**\n * Returns the order priority for a button kind\n * Lower numbers appear first (or last when stacking)\n */\nconst buttonOrder = (kind: ButtonKind): number =>\n ({\n ghost: 1,\n 'danger--ghost': 2,\n tertiary: 3,\n danger: 5,\n primary: 6,\n })[kind] ?? 4;\n\n/**\n * Sorts actions based on button kind and stacking mode\n * When not stacking: ghost first, primary last\n * When stacking: primary first, ghost last\n */\nconst sortActions = (\n actions: ActionButton[],\n stacking: boolean\n): ActionButton[] => {\n const sortedActions = [...actions];\n sortedActions.sort(\n (action1, action2) =>\n (buttonOrder(action1.kind || defaultKind) -\n buttonOrder(action2.kind || defaultKind)) *\n (stacking ? -1 : 1)\n );\n return sortedActions;\n};\n\n/**\n * Validates action set configuration and returns problems\n */\nconst validateActionSet = (\n actions: ActionButton[],\n size: ButtonSize\n): string[] => {\n if (!actions || actions.length === 0) {\n return [];\n }\n\n const problems: string[] = [];\n const stacking = willStack(size, actions.length);\n\n const countActions = (kind: ButtonKind): number =>\n actions.filter((action) => (action.kind || defaultKind) === kind).length;\n\n const primaryActions = countActions('primary');\n const secondaryActions = countActions('secondary');\n const tertiaryActions = countActions('tertiary');\n const dangerActions = countActions('danger');\n const ghostActions = countActions('ghost') + countActions('danger--ghost');\n\n if (stacking && actions.length > 3) {\n problems.push(\n 'you cannot have more than three actions in this size of ActionSet'\n );\n }\n\n if (actions.length > 4) {\n problems.push('you cannot have more than four actions in an ActionSet');\n }\n\n if (primaryActions > 1) {\n problems.push(\n \"you cannot have more than one 'primary' action in an ActionSet\"\n );\n }\n\n if (ghostActions > 1) {\n problems.push(\n \"you cannot have more than one 'ghost' action in an ActionSet\"\n );\n }\n\n if (stacking && actions.length > 1 && ghostActions > 0) {\n problems.push(\n \"you cannot have a 'ghost' button in conjunction with other action types in this size of ActionSet\"\n );\n }\n\n if (\n actions.length >\n primaryActions +\n secondaryActions +\n tertiaryActions +\n dangerActions +\n ghostActions\n ) {\n problems.push(\n \"you can only have 'primary', 'danger', 'secondary', 'tertiary', 'ghost' and 'danger--ghost' buttons in an ActionSet\"\n );\n }\n\n return problems;\n};\n\n/**\n * Action Set component - A specialized button set with validation and ordering logic.\n * Extends Carbon's button-set with additional features for action buttons.\n *\n * @element c4p-action-set\n * @slot - Slot for cds-button elements (used when actions prop is not provided)\n */\n@customElement(`${prefix}-action-set`)\nexport class CDSActionSet extends LitElement {\n /**\n * Number of slotted buttons (computed internally).\n */\n @state()\n private _slottedButtonCount = 0;\n\n /**\n * Computed property: `true` if the buttons are currently stacked.\n * This is derived from size, disableStacking, and button count.\n */\n get stacked(): boolean {\n const buttonCount = this.actions?.length || this._slottedButtonCount;\n return this.disableStacking ? false : willStack(this.size, buttonCount);\n }\n\n /**\n * The size of buttons to use for the actions.\n */\n @property({ attribute: 'button-size' })\n buttonSize?: ButtonSize;\n\n /**\n * The size of the action set. Different button arrangements are used at\n * different sizes, to make best use of the available space.\n */\n @property()\n size: ButtonSize = 'md';\n\n /**\n * When true, prevents automatic stacking of buttons even when size would\n * normally trigger stacking (e.g., 'sm' size or 'md' with 3+ actions).\n * Buttons will remain in a horizontal layout.\n */\n @property({ type: Boolean, attribute: 'disable-stacking' })\n disableStacking: boolean = false;\n\n /**\n * Array of action button configurations. When provided, buttons will be\n * rendered internally instead of using slotted content.\n */\n @property({ type: Array })\n actions: ActionButton[] = [];\n\n static styles = styles;\n\n /**\n * Applies common button styling (size, classes, expressive attribute)\n * @private\n */\n private _applyButtonStyles(button: HTMLElement, kind?: ButtonKind) {\n if (this.buttonSize) {\n button.setAttribute('size', this.buttonSize);\n }\n\n button.classList.add(`${blockClass}__action-button`);\n\n if (kind === 'ghost' || kind === 'danger--ghost') {\n button.classList.add(`${blockClass}__action-button--ghost`);\n }\n\n button.setAttribute('is-expressive', 'true');\n }\n\n /**\n * Processes actions: validates, determines stacking, and sorts\n * @private\n */\n private _processActions(actions: ActionButton[]): {\n sortedActions: ActionButton[];\n stacking: boolean;\n problems: string[];\n } {\n const problems = validateActionSet(actions, this.size);\n const stacking = this.disableStacking\n ? false\n : willStack(this.size, actions.length);\n const sortedActions = sortActions(actions, stacking);\n\n if (problems.length > 0) {\n pconsole.warn(\n `Invalid actions in ActionSet: ${problems.join(', and ')}.`\n );\n }\n\n return { sortedActions, stacking, problems };\n }\n\n /**\n * Handler for @slotchange, processes and orders buttons based on ActionSet logic\n *\n * @private\n */\n protected _handleSlotChange(event: Event) {\n const childItems = (event.target as HTMLSlotElement)\n .assignedNodes()\n .filter((elem) =>\n (elem as HTMLElement).matches !== undefined\n ? (elem as HTMLElement).matches(`${carbonPrefix}-button`)\n : false\n ) as HTMLElement[];\n\n if (childItems.length === 0) {\n return;\n }\n\n // Extract button properties to create ActionButton objects\n const actions: ActionButton[] = childItems.map((button) => {\n const kind = button.getAttribute('kind') as ButtonKind;\n const disabled = button.hasAttribute('disabled');\n const label = button.textContent?.trim() || '';\n\n return {\n kind: kind || 'primary',\n disabled,\n label,\n };\n });\n\n // Process actions (validate, sort, determine stacking)\n const { sortedActions } = this._processActions(actions);\n\n // Update state\n this._slottedButtonCount = childItems.length;\n\n // Reorder and style the buttons\n this._reorderButtons(childItems, sortedActions);\n\n // Dispatch update event\n const update = new CustomEvent(`${prefix}-action-set-update`, {\n bubbles: true,\n cancelable: true,\n composed: true,\n });\n\n this.dispatchEvent(update);\n }\n\n /**\n * Reorders the button elements in the DOM based on the sorted actions\n * and applies appropriate styling\n *\n * @private\n */\n private _reorderButtons(\n buttons: HTMLElement[],\n sortedActions: ActionButton[]\n ) {\n // Create a map of button labels to elements for quick lookup\n const buttonMap = new Map<string, HTMLElement>();\n buttons.forEach((button) => {\n const label = button.textContent?.trim() || '';\n buttonMap.set(label, button);\n });\n // Apply styling to buttons based on sorted order\n sortedActions.forEach((action) => {\n const button = buttonMap.get(action.label || '');\n if (button) {\n this._applyButtonStyles(button, action.kind);\n }\n });\n }\n\n /**\n * When a button within the action-set is focused, hide the margin on both sides\n * of the focused button, by applying the appropriate styles to its sibling\n *\n * @private\n */\n private _hideSiblingMargin = () => {\n let items: HTMLElement[] = [];\n\n // Check if we have slotted content\n const slot = this.shadowRoot?.querySelector('slot');\n if (slot) {\n items = slot\n .assignedElements()\n .filter(\n (el) => el.tagName.toLowerCase() === `${carbonPrefix}-button`\n ) as HTMLElement[];\n }\n\n // If no slotted content, check for directly rendered buttons in shadow DOM\n if (items.length === 0 && this.shadowRoot) {\n items = Array.from(\n this.shadowRoot.querySelectorAll(`${carbonPrefix}-button`)\n ) as HTMLElement[];\n }\n\n if (items.length === 0) {\n return;\n }\n\n const focusedIndex = items.findIndex((el) => el.matches(':focus-within'));\n\n items.forEach((el, idx) => {\n const shouldHide =\n focusedIndex >= 0 && (idx === focusedIndex || idx === focusedIndex + 1);\n el.toggleAttribute('hide-margin', shouldHide);\n });\n };\n\n connectedCallback() {\n super.connectedCallback();\n this.addEventListener('focusin', this._hideSiblingMargin);\n this.addEventListener('focusout', this._hideSiblingMargin);\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this.removeEventListener('focusin', this._hideSiblingMargin);\n this.removeEventListener('focusout', this._hideSiblingMargin);\n }\n\n /**\n * Renders buttons from the actions prop\n * @private\n */\n private _renderActionsFromProp() {\n if (!this.actions || this.actions.length === 0) {\n return null;\n }\n\n // Process actions (validate, sort)\n const { sortedActions } = this._processActions(this.actions);\n\n return sortedActions.map((action) => {\n const {\n kind = 'primary',\n label = '',\n disabled = false,\n loading = false,\n onClick,\n class: customClass,\n ...rest\n } = action;\n\n // Merge custom class with action-set classes\n const buttonClasses = classMap({\n [`${blockClass}__action-button`]: true,\n [`${blockClass}__action-button--ghost`]:\n kind === 'ghost' || kind === 'danger--ghost',\n ...(customClass ? { [customClass]: true } : {}),\n });\n\n // Create a ref callback to apply rest properties (excluding class which is handled above)\n const buttonRef = (el: Element | undefined) => {\n if (el && rest) {\n Object.entries(rest).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n if (typeof value === 'boolean') {\n if (value) {\n el.setAttribute(key, '');\n } else {\n el.removeAttribute(key);\n }\n } else {\n el.setAttribute(key, String(value));\n }\n }\n });\n }\n };\n\n return html`\n <cds-button\n ${ref(buttonRef)}\n class=\"${buttonClasses}\"\n kind=\"${kind}\"\n size=\"${this.buttonSize}\"\n ?disabled=\"${disabled || loading}\"\n is-expressive=\"true\"\n @click=\"${typeof onClick === 'function' ? onClick : () => {}}\"\n >\n ${label}\n </cds-button>\n `;\n });\n }\n\n render() {\n const { actions, _slottedButtonCount, stacked } = this;\n const buttonCount = actions?.length || _slottedButtonCount;\n\n const defaultClasses = {\n [blockClass]: true,\n [`${blockClass}--row-single`]: !stacked && buttonCount === 1,\n [`${blockClass}--row-double`]: !stacked && buttonCount === 2,\n [`${blockClass}--row-triple`]: !stacked && buttonCount === 3,\n [`${blockClass}--row-quadruple`]: !stacked && buttonCount >= 4,\n [`${blockClass}--stacking`]: stacked,\n [`${blockClass}--${this.size}`]: true,\n };\n\n // If actions prop is provided, render buttons directly without cds-button-set\n // to avoid button-set's automatic kind assignment\n if (actions && actions.length > 0) {\n const buttonSetClasses = classMap({\n ...defaultClasses,\n [`${carbonPrefix}--btn-set--stacked`]: stacked,\n [`${carbonPrefix}--btn-set`]: true,\n });\n\n return html`<div\n class=\"${buttonSetClasses}\"\n part=\"action-set\"\n role=\"list\"\n >\n ${this._renderActionsFromProp()}\n </div>`;\n }\n\n const classes = classMap({\n ...defaultClasses,\n [`${carbonPrefix}--btn-set--stacked`]: stacked,\n [`${carbonPrefix}--btn-set`]: true,\n });\n return html`<div class=\"${classes}\" part=\"action-set\" role=\"list\">\n <slot @slotchange=\"${this._handleSlotChange}\"></slot>\n </div>`;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'c4p-action-set': CDSActionSet;\n }\n}\n\nexport default CDSActionSet;\n"],"mappings":"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"}