@govbr-ds/webcomponents 2.0.0-next.61 → 2.0.0-next.62

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 (38) hide show
  1. package/dist/cjs/br-modal.cjs.entry.js +119 -15
  2. package/dist/cjs/br-modal.entry.cjs.js.map +1 -1
  3. package/dist/cjs/br-scrim.cjs.entry.js +132 -38
  4. package/dist/cjs/br-scrim.entry.cjs.js.map +1 -1
  5. package/dist/cjs/loader.cjs.js +1 -1
  6. package/dist/cjs/webcomponents.cjs.js +1 -1
  7. package/dist/collection/components/modal/modal.js +152 -37
  8. package/dist/collection/components/modal/modal.js.map +1 -1
  9. package/dist/collection/components/scrim/scrim.js +132 -38
  10. package/dist/collection/components/scrim/scrim.js.map +1 -1
  11. package/dist/collection/pages/components/modal/index.js +1 -53
  12. package/dist/components/br-modal.js +123 -26
  13. package/dist/components/br-modal.js.map +1 -1
  14. package/dist/components/br-scrim.js +125 -44
  15. package/dist/components/br-scrim.js.map +1 -1
  16. package/dist/esm/br-modal.entry.js +119 -15
  17. package/dist/esm/br-modal.entry.js.map +1 -1
  18. package/dist/esm/br-scrim.entry.js +132 -38
  19. package/dist/esm/br-scrim.entry.js.map +1 -1
  20. package/dist/esm/loader.js +1 -1
  21. package/dist/esm/webcomponents.js +1 -1
  22. package/dist/hydrate/index.js +252 -55
  23. package/dist/hydrate/index.mjs +252 -55
  24. package/dist/types/components/modal/modal.d.ts +46 -4
  25. package/dist/types/components/scrim/scrim.d.ts +39 -1
  26. package/dist/types/components.d.ts +11 -11
  27. package/dist/webcomponents/br-modal.entry.esm.js.map +1 -1
  28. package/dist/webcomponents/br-scrim.entry.esm.js.map +1 -1
  29. package/dist/webcomponents/{p-e7b38c63.entry.js → p-216dc111.entry.js} +126 -45
  30. package/dist/webcomponents/p-216dc111.entry.js.map +1 -0
  31. package/dist/webcomponents/{p-28dba962.entry.js → p-463b06a4.entry.js} +129 -33
  32. package/dist/webcomponents/p-463b06a4.entry.js.map +1 -0
  33. package/dist/webcomponents/webcomponents.esm.js +1 -1
  34. package/package.json +1 -1
  35. package/dist/custom-elements.json +0 -18276
  36. package/dist/webcomponents/p-28dba962.entry.js.map +0 -1
  37. package/dist/webcomponents/p-e7b38c63.entry.js.map +0 -1
  38. package/dist/webcomponents.html-custom-data.json +0 -1214
@@ -37012,7 +37012,9 @@ const modalCss = "*,*::before,*::after{-webkit-box-sizing:border-box;box-sizing:
37012
37012
  class Modal {
37013
37013
  constructor(hostRef) {
37014
37014
  registerInstance(this, hostRef);
37015
+ this.brModalOpen = createEvent(this, "brModalOpen", 7);
37015
37016
  this.brModalClose = createEvent(this, "brModalClose", 7);
37017
+ this.brModalBeforeClose = createEvent(this, "brModalBeforeClose", 7);
37016
37018
  if (hostRef.$hostElement$["s-ei"]) {
37017
37019
  this.elementInternals = hostRef.$hostElement$["s-ei"];
37018
37020
  }
@@ -37027,32 +37029,132 @@ class Modal {
37027
37029
  this.customId = Helpers.generateUniqueId('modal');
37028
37030
  /** Controla a visibilidade do modal. */
37029
37031
  this.show = false;
37030
- /** Se `true`, o modal se fechará automaticamente ao clicar no botão de fechar ou pressionar a tecla 'Escape'. */
37032
+ /**
37033
+ * Define o comportamento de fechamento do modal.
37034
+ *
37035
+ * - `true`: O modal fecha automaticamente ao clicar no botão fechar.
37036
+ * - `false`: O modal emite `brModalBeforeClose` mas não fecha, permitindo a implementação de lógica customizada (validação, confirmação, etc.) antes do fechamento. O desenvolvedor deve
37037
+ * controlar manualmente o fechamento.
37038
+ */
37031
37039
  this.autoClose = false;
37032
37040
  /**
37033
37041
  * Define o tamanho (largura) do modal.
37034
37042
  */
37035
37043
  this.size = 'medium';
37036
- /** Se `true`, exibe um fundo escurecido (scrim) atrás do modal. */
37037
- this.scrim = false;
37038
37044
  /** Se `true`, habilita a rolagem interna do conteúdo do modal. */
37039
37045
  this.scrollable = false;
37040
37046
  /**
37041
37047
  * Define o alinhamento do conteúdo do rodapé (slot="footer").
37042
37048
  */
37043
37049
  this.alignFooter = 'center';
37050
+ this.isOpeningParentScrim = false;
37051
+ /**
37052
+ * Handler para evento brScrimOpen do parent scrim
37053
+ * Quando scrim abre programaticamente, a modal deve abrir também
37054
+ */
37055
+ this.handleParentScrimOpen = () => {
37056
+ const parentScrim = this.el.closest('br-scrim');
37057
+ if (parentScrim === null)
37058
+ return;
37059
+ if (!this.show) {
37060
+ this.show = true;
37061
+ }
37062
+ };
37063
+ /**
37064
+ * Handler para evento brScrimClose do parent scrim
37065
+ * Se autoClose=true, fecha a modal junto com o scrim
37066
+ * Se autoClose=false, não faz nada (modal permanece aberta)
37067
+ */
37068
+ this.handleParentScrimClose = () => {
37069
+ const parentScrim = this.el.closest('br-scrim');
37070
+ if (parentScrim === null)
37071
+ return;
37072
+ if (this.autoClose && this.show) {
37073
+ this.show = false;
37074
+ }
37075
+ };
37044
37076
  this.handleClose = () => {
37045
- this.brModalClose.emit();
37077
+ this.brModalBeforeClose.emit();
37046
37078
  if (this.autoClose) {
37047
37079
  this.show = false;
37048
- // Se o modal está dentro de um br-scrim, fecha o scrim também
37049
- const parentScrim = this.el.closest('br-scrim');
37050
- if (parentScrim) {
37051
- parentScrim.close();
37052
- }
37053
37080
  }
37054
37081
  };
37055
37082
  }
37083
+ handleShowChange(newValue, oldValue) {
37084
+ if (newValue) {
37085
+ this.brModalOpen.emit();
37086
+ this.openParentScrim();
37087
+ }
37088
+ else if (oldValue === true) {
37089
+ this.brModalClose.emit();
37090
+ this.closeParentScrim();
37091
+ }
37092
+ }
37093
+ closeParentScrim() {
37094
+ const parentScrim = this.el.closest('br-scrim');
37095
+ if (parentScrim && typeof parentScrim.close === 'function') {
37096
+ parentScrim.close();
37097
+ }
37098
+ }
37099
+ componentWillLoad() {
37100
+ if (!this.show) {
37101
+ const parentScrim = this.el.closest('br-scrim');
37102
+ if (parentScrim !== null && parentScrim.isOpen) {
37103
+ this.show = true;
37104
+ }
37105
+ }
37106
+ }
37107
+ componentDidLoad() {
37108
+ this.listenToParentScrimEvents();
37109
+ if (this.show) {
37110
+ this.openParentScrim();
37111
+ }
37112
+ }
37113
+ disconnectedCallback() {
37114
+ this.isOpeningParentScrim = false;
37115
+ this.removeParentScrimEventListeners();
37116
+ }
37117
+ /**
37118
+ * Adiciona listeners para eventos do parent scrim
37119
+ */
37120
+ listenToParentScrimEvents() {
37121
+ const parentScrim = this.el.closest('br-scrim');
37122
+ if (parentScrim !== null) {
37123
+ parentScrim.addEventListener('brScrimOpen', this.handleParentScrimOpen);
37124
+ parentScrim.addEventListener('brScrimClose', this.handleParentScrimClose);
37125
+ }
37126
+ }
37127
+ /**
37128
+ * Remove listeners de eventos do parent scrim
37129
+ */
37130
+ removeParentScrimEventListeners() {
37131
+ const parentScrim = this.el.closest('br-scrim');
37132
+ if (parentScrim !== null) {
37133
+ parentScrim.removeEventListener('brScrimOpen', this.handleParentScrimOpen);
37134
+ parentScrim.removeEventListener('brScrimClose', this.handleParentScrimClose);
37135
+ }
37136
+ }
37137
+ openParentScrim() {
37138
+ if (this.isOpeningParentScrim)
37139
+ return;
37140
+ const parentScrim = this.el.closest('br-scrim');
37141
+ if (parentScrim && !parentScrim.isOpen) {
37142
+ this.isOpeningParentScrim = true;
37143
+ Promise.resolve()
37144
+ .then(() => {
37145
+ try {
37146
+ return parentScrim.open();
37147
+ }
37148
+ catch (error) {
37149
+ console.warn('br-modal: Erro ao abrir scrim pai:', error);
37150
+ throw error;
37151
+ }
37152
+ })
37153
+ .finally(() => {
37154
+ this.isOpeningParentScrim = false;
37155
+ });
37156
+ }
37157
+ }
37056
37158
  get titleId() {
37057
37159
  return `${this.customId}-title`;
37058
37160
  }
@@ -37072,6 +37174,7 @@ class Modal {
37072
37174
  open() {
37073
37175
  return __awaiter(this, void 0, void 0, function* () {
37074
37176
  this.show = true;
37177
+ this.openParentScrim();
37075
37178
  });
37076
37179
  }
37077
37180
  /**
@@ -37079,22 +37182,23 @@ class Modal {
37079
37182
  */
37080
37183
  close() {
37081
37184
  return __awaiter(this, void 0, void 0, function* () {
37082
- this.show = false;
37083
- // Se o modal está dentro de um br-scrim, fecha o scrim também
37084
- const parentScrim = this.el.closest('br-scrim');
37085
- if (parentScrim) {
37086
- parentScrim.close();
37185
+ if (!this.autoClose) {
37186
+ return;
37087
37187
  }
37188
+ this.show = false;
37088
37189
  });
37089
37190
  }
37090
37191
  render() {
37091
37192
  if (!this.show) {
37092
37193
  return null;
37093
37194
  }
37094
- return (hAsync(Host, null, hAsync("div", { class: this.getCssClassMap(), role: "dialog", "aria-modal": "true", "aria-labelledby": this.titleId, "aria-describedby": this.contentId }, hAsync("div", { class: "br-modal-header" }, hAsync("div", { class: "modal-title", id: this.titleId }, hAsync("slot", { name: "header" }, this.titleText)), hAsync("slot", { name: "close-button" }, hAsync("br-button", { class: "close", shape: "circle", density: "small", "aria-label": "Fechar", onClick: this.handleClose }, hAsync("br-icon", { "icon-name": "fa-solid:times" })))), hAsync("div", { id: this.contentId, class: "br-modal-body" }, hAsync("slot", null)), hAsync("div", { class: `br-modal-footer ${this.alignFooter ? `justify-content-${this.alignFooter}` : ''}` }, hAsync("slot", { name: "footer" })))));
37195
+ return (hAsync(Host, null, hAsync("div", { class: this.getCssClassMap(), role: "dialog", "aria-modal": "true", "aria-labelledby": this.titleId, "aria-describedby": this.contentId }, hAsync("div", { class: "br-modal-header" }, hAsync("div", { class: "modal-title", id: this.titleId }, hAsync("slot", { name: "header" }, this.titleText)), hAsync("slot", { name: "close-button" }, hAsync("br-button", { class: "close", shape: "circle", density: "small", "aria-label": "Fechar", onClick: this.handleClose }, hAsync("br-icon", { "icon-name": "fa-solid:times" })))), hAsync("div", { id: this.contentId, class: "br-modal-body" }, hAsync("slot", null)), hAsync("div", { class: `br-modal-footer ${this.alignFooter !== undefined ? `justify-content-${this.alignFooter}` : ''}` }, hAsync("slot", { name: "footer" })))));
37095
37196
  }
37096
37197
  static get formAssociated() { return true; }
37097
37198
  get el() { return getElement(this); }
37199
+ static get watchers() { return {
37200
+ "show": ["handleShowChange"]
37201
+ }; }
37098
37202
  static get style() { return modalCss; }
37099
37203
  static get cmpMeta() { return {
37100
37204
  "$flags$": 329,
@@ -37106,7 +37210,6 @@ class Modal {
37106
37210
  "autoClose": [516, "auto-close"],
37107
37211
  "initialFocusSelector": [1, "initial-focus-selector"],
37108
37212
  "size": [513],
37109
- "scrim": [516],
37110
37213
  "scrollable": [516],
37111
37214
  "alignFooter": [513, "align-footer"],
37112
37215
  "open": [64],
@@ -37114,7 +37217,7 @@ class Modal {
37114
37217
  },
37115
37218
  "$listeners$": undefined,
37116
37219
  "$lazyBundleId$": "-",
37117
- "$attrsToReflect$": [["customId", "custom-id"], ["show", "show"], ["autoClose", "auto-close"], ["size", "size"], ["scrim", "scrim"], ["scrollable", "scrollable"], ["alignFooter", "align-footer"]]
37220
+ "$attrsToReflect$": [["customId", "custom-id"], ["show", "show"], ["autoClose", "auto-close"], ["size", "size"], ["scrollable", "scrollable"], ["alignFooter", "align-footer"]]
37118
37221
  }; }
37119
37222
  }
37120
37223
 
@@ -37844,6 +37947,29 @@ class Scrim {
37844
37947
  this.previouslyFocusedElement = null;
37845
37948
  this.focusTimeoutId = null;
37846
37949
  this.restoreFocusTimeoutId = null;
37950
+ // ======================================================================
37951
+ // GERENCIAMENTO DE COMPONENTES FILHOS
37952
+ // ======================================================================
37953
+ /**
37954
+ * Handler para evento brModalOpen emitido por modal filha
37955
+ */
37956
+ this.handleModalOpen = (event) => {
37957
+ const modalElement = event.target;
37958
+ if (!this.isDirectChild(modalElement))
37959
+ return;
37960
+ if (!this.isOpen) {
37961
+ this.open();
37962
+ }
37963
+ };
37964
+ /**
37965
+ * Handler para evento brModalClose emitido por modal filha
37966
+ */
37967
+ this.handleModalClose = (event) => {
37968
+ const modalElement = event.target;
37969
+ if (!this.isDirectChild(modalElement))
37970
+ return;
37971
+ this.close();
37972
+ };
37847
37973
  this.handleActivatorClick = () => {
37848
37974
  this.toggle();
37849
37975
  };
@@ -37861,6 +37987,10 @@ class Scrim {
37861
37987
  const reference = (_a = this.scrollOrigin) !== null && _a !== void 0 ? _a : this.lastScrollTop;
37862
37988
  if (Math.abs(currentScroll - reference) > this.scrollThreshold) {
37863
37989
  this.scrollOrigin = null;
37990
+ // Não fecha se tiver modal filha com autoClose=false ou não definido
37991
+ if (this.hasModalWithAutoClose()) {
37992
+ return;
37993
+ }
37864
37994
  this.isOpen = false;
37865
37995
  this.handleOpenChange(false);
37866
37996
  return;
@@ -37896,7 +38026,9 @@ class Scrim {
37896
38026
  }
37897
38027
  if (event.key === 'Escape' && !this.disableCloseOnClick) {
37898
38028
  event.preventDefault();
37899
- this.isOpen = false;
38029
+ if (!this.hasModalWithAutoClose()) {
38030
+ this.isOpen = false;
38031
+ }
37900
38032
  }
37901
38033
  };
37902
38034
  // Intercepta TODOS os eventos de clique globalmente quando scrim está ativo
@@ -37930,11 +38062,15 @@ class Scrim {
37930
38062
  }, 0);
37931
38063
  }
37932
38064
  };
37933
- // ======================================================================
37934
- // MANIPULAÇÃO DE EVENTOS E UTILITÁRIOS
37935
- // ======================================================================
38065
+ /**
38066
+ * Handler para clique na máscara do scrim
38067
+ * Fecha o scrim se disableCloseOnClick for false e não houver modal filha com autoClose=false
38068
+ */
37936
38069
  this.handleMaskClick = (_event) => {
37937
38070
  if (!this.disableCloseOnClick) {
38071
+ if (this.hasModalWithAutoClose()) {
38072
+ return;
38073
+ }
37938
38074
  this.close();
37939
38075
  }
37940
38076
  };
@@ -37943,37 +38079,39 @@ class Scrim {
37943
38079
  // LIFECYCLE HOOKS E WATCHERS
37944
38080
  // ======================================================================
37945
38081
  handleOpenChange(newValue) {
37946
- // Cancelar qualquer timeout anterior
37947
- if (this.focusTimeoutId !== null) {
37948
- clearTimeout(this.focusTimeoutId);
37949
- this.focusTimeoutId = null;
37950
- }
37951
- if (this.restoreFocusTimeoutId !== null) {
37952
- clearTimeout(this.restoreFocusTimeoutId);
37953
- this.restoreFocusTimeoutId = null;
37954
- }
37955
- this.isActive = newValue;
37956
- if (newValue && this.scrollStrategy === 'close') {
37957
- const currentScroll = window.scrollY;
37958
- this.lastScrollTop = currentScroll;
37959
- this.scrollOrigin = currentScroll;
37960
- }
37961
- this.updateStyles();
37962
- if (this.isActive) {
37963
- this.previouslyFocusedElement = document.activeElement;
37964
- this.applyScrollStrategy();
37965
- this.addGlobalEventInterception();
37966
- this.focusTimeoutId = setTimeout(() => {
37967
- this.focusFirstElement();
37968
- }, 100);
37969
- this.brScrimOpen.emit();
37970
- }
37971
- else {
37972
- this.resetScrolling();
37973
- this.removeGlobalEventInterception();
37974
- this.restoreFocus();
37975
- this.brScrimClose.emit();
37976
- }
38082
+ return __awaiter(this, void 0, void 0, function* () {
38083
+ // Cancelar qualquer timeout anterior
38084
+ if (this.focusTimeoutId !== null) {
38085
+ clearTimeout(this.focusTimeoutId);
38086
+ this.focusTimeoutId = null;
38087
+ }
38088
+ if (this.restoreFocusTimeoutId !== null) {
38089
+ clearTimeout(this.restoreFocusTimeoutId);
38090
+ this.restoreFocusTimeoutId = null;
38091
+ }
38092
+ this.isActive = newValue;
38093
+ if (newValue && this.scrollStrategy === 'close') {
38094
+ const currentScroll = window.scrollY;
38095
+ this.lastScrollTop = currentScroll;
38096
+ this.scrollOrigin = currentScroll;
38097
+ }
38098
+ this.updateStyles();
38099
+ if (this.isActive) {
38100
+ this.previouslyFocusedElement = document.activeElement;
38101
+ this.applyScrollStrategy();
38102
+ this.addGlobalEventInterception();
38103
+ this.focusTimeoutId = setTimeout(() => {
38104
+ this.focusFirstElement();
38105
+ }, 100);
38106
+ this.brScrimOpen.emit();
38107
+ }
38108
+ else {
38109
+ this.resetScrolling();
38110
+ this.removeGlobalEventInterception();
38111
+ this.restoreFocus();
38112
+ this.brScrimClose.emit();
38113
+ }
38114
+ });
37977
38115
  }
37978
38116
  updateStyles() {
37979
38117
  if (this.zIndex !== null && this.zIndex !== undefined) {
@@ -38000,6 +38138,7 @@ class Scrim {
38000
38138
  this.setupActivator();
38001
38139
  this.setupActivatorSlotClick();
38002
38140
  this.addContentEventListener();
38141
+ this.listenToModalEvents();
38003
38142
  if (this.isActive) {
38004
38143
  this.applyScrollStrategy();
38005
38144
  this.addGlobalEventInterception();
@@ -38033,7 +38172,6 @@ class Scrim {
38033
38172
  clearTimeout(this.restoreFocusTimeoutId);
38034
38173
  this.restoreFocusTimeoutId = null;
38035
38174
  }
38036
- // Remover event listeners
38037
38175
  window.removeEventListener('scroll', this.handleScrollClose);
38038
38176
  window.removeEventListener('scroll', this.handleBlockScroll);
38039
38177
  if (this.contentRef !== null) {
@@ -38042,6 +38180,58 @@ class Scrim {
38042
38180
  this.removeActivatorClickListener();
38043
38181
  this.cleanupActivatorSlotClick();
38044
38182
  this.removeGlobalEventInterception();
38183
+ this.removeModalEventListener();
38184
+ }
38185
+ /**
38186
+ * Verifica se um elemento é filho direto deste scrim (não nested)
38187
+ */
38188
+ isDirectChild(element) {
38189
+ const children = this.getDirectChildren();
38190
+ return children.some((child) => child === element || child.contains(element));
38191
+ }
38192
+ /**
38193
+ * Adiciona listeners para eventos brModalOpen e brModalClose das modais filhas
38194
+ */
38195
+ listenToModalEvents() {
38196
+ this.el.addEventListener('brModalOpen', this.handleModalOpen);
38197
+ this.el.addEventListener('brModalClose', this.handleModalClose);
38198
+ }
38199
+ /**
38200
+ * Remove listeners dos eventos da modal
38201
+ */
38202
+ removeModalEventListener() {
38203
+ this.el.removeEventListener('brModalOpen', this.handleModalOpen);
38204
+ this.el.removeEventListener('brModalClose', this.handleModalClose);
38205
+ }
38206
+ /**
38207
+ * Retorna os elementos filhos diretos do scrim via slot padrão
38208
+ */
38209
+ getDirectChildren() {
38210
+ const shadowRoot = this.el.shadowRoot;
38211
+ if (shadowRoot === null)
38212
+ return [];
38213
+ const slot = shadowRoot.querySelector('slot:not([name])');
38214
+ if (slot === null)
38215
+ return [];
38216
+ return slot.assignedElements();
38217
+ }
38218
+ /**
38219
+ * Busca uma modal filha direta do scrim
38220
+ */
38221
+ findModalChild() {
38222
+ var _a;
38223
+ const children = this.getDirectChildren();
38224
+ const modalElement = children.find((child) => child.tagName === 'BR-MODAL');
38225
+ return (_a = modalElement) !== null && _a !== void 0 ? _a : null;
38226
+ }
38227
+ /**
38228
+ * Verifica se há uma modal filha com autoClose=false (padrão ou explícito)
38229
+ * Retorna true se:
38230
+ * - Existe modal filha E autoClose não é explicitamente true
38231
+ */
38232
+ hasModalWithAutoClose() {
38233
+ const modal = this.findModalChild();
38234
+ return modal !== null && modal.autoClose !== true;
38045
38235
  }
38046
38236
  // ======================================================================
38047
38237
  // GERENCIAMENTO DO ACTIVATOR (ELEMENTO ACIONADOR)
@@ -38230,7 +38420,11 @@ class Scrim {
38230
38420
  return elements.filter((el) => el.offsetWidth > 0 && el.offsetHeight > 0 && getComputedStyle(el).visibility !== 'hidden');
38231
38421
  }
38232
38422
  shouldHandleEscape(event) {
38233
- return (event.key === 'Escape' || event.key === 'Esc') && this.isActive && !this.disableCloseOnClick;
38423
+ if ((event.key === 'Escape' || event.key === 'Esc') && this.isActive && !this.disableCloseOnClick) {
38424
+ // Não fecha se tiver modal filha com autoClose=false ou não definido
38425
+ return !this.hasModalWithAutoClose();
38426
+ }
38427
+ return false;
38234
38428
  }
38235
38429
  handleTabNavigation(event) {
38236
38430
  const focusableElements = this.getFocusableElements();
@@ -38291,6 +38485,9 @@ class Scrim {
38291
38485
  document.removeEventListener('focus', this.handleGlobalFocus, true);
38292
38486
  document.removeEventListener('focusin', this.handleGlobalFocus, true);
38293
38487
  }
38488
+ // ======================================================================
38489
+ // UTILITÁRIOS
38490
+ // ======================================================================
38294
38491
  getCssClassMap() {
38295
38492
  return {
38296
38493
  'br-scrim': true,
@@ -38341,7 +38538,7 @@ class Scrim {
38341
38538
  });
38342
38539
  }
38343
38540
  render() {
38344
- return (hAsync(Host, { key: '1aea7418642867cfb24c099729f34412f9aec7bf' }, hAsync("slot", { key: '4468892291450f13cded3627ee91f31716108443', name: "activator" }), hAsync("div", { key: '6019de52484c176a5f5d706ca1dc759039dae940', class: this.getCssClassMap(), id: this.customId, role: "dialog", "aria-modal": "true", "aria-label": this.ariaLabel || 'Conteúdo do diálogo', "data-visible": this.isActive ? 'true' : 'false' }, hAsync("div", { key: '6c6df83177f1a14097ec5c08e409caaca3953d3b', class: "mask", onClick: this.handleMaskClick }), hAsync("div", { key: '1af0ecd53a0aaf630069139a7e6935533a563e10', ref: (el) => (this.contentRef = el), id: `${this.customId}-content`, class: "content", tabIndex: -1, onKeyDown: this.handleKeyDown }, hAsync("slot", { key: '2cb75f5b254ed22bbe821998700d9c1f4152dd5b' })))));
38541
+ return (hAsync(Host, { key: '249de7af4056263464615cbe086b419f74b8981b' }, hAsync("slot", { key: '1698faa6b492e1ec594eba8425f20582a2af0e4a', name: "activator" }), hAsync("div", { key: 'adedf3eb84f3d8f79ac9bb19209022301453c019', class: this.getCssClassMap(), id: this.customId, role: "dialog", "aria-modal": "true", "aria-label": this.ariaLabel || 'Conteúdo do diálogo', "data-visible": this.isActive ? 'true' : 'false' }, hAsync("div", { key: 'ef7408a6672fabf4d2f79bc7922f301fd102652e', class: "mask", onClick: this.handleMaskClick }), hAsync("div", { key: '91ffb1a84478f09fc90cefbb97180c5db13dba5c', ref: (el) => (this.contentRef = el), id: `${this.customId}-content`, class: "content", tabIndex: -1, onKeyDown: this.handleKeyDown }, hAsync("slot", { key: '0600ac804980446103154cebf83389ac92e44d9d' })))));
38345
38542
  }
38346
38543
  static get formAssociated() { return true; }
38347
38544
  get el() { return getElement(this); }
@@ -23,7 +23,13 @@ export declare class Modal {
23
23
  readonly titleText: string;
24
24
  /** Controla a visibilidade do modal. */
25
25
  show: boolean;
26
- /** Se `true`, o modal se fechará automaticamente ao clicar no botão de fechar ou pressionar a tecla 'Escape'. */
26
+ /**
27
+ * Define o comportamento de fechamento do modal.
28
+ *
29
+ * - `true`: O modal fecha automaticamente ao clicar no botão fechar.
30
+ * - `false`: O modal emite `brModalBeforeClose` mas não fecha, permitindo a implementação de lógica customizada (validação, confirmação, etc.) antes do fechamento. O desenvolvedor deve
31
+ * controlar manualmente o fechamento.
32
+ */
27
33
  autoClose: boolean;
28
34
  /** Seletor CSS para o elemento que deve receber foco quando o modal é aberto. */
29
35
  readonly initialFocusSelector: string;
@@ -31,16 +37,52 @@ export declare class Modal {
31
37
  * Define o tamanho (largura) do modal.
32
38
  */
33
39
  readonly size: 'xsmall' | 'small' | 'medium' | 'large' | 'auto';
34
- /** Se `true`, exibe um fundo escurecido (scrim) atrás do modal. */
35
- readonly scrim = false;
36
40
  /** Se `true`, habilita a rolagem interna do conteúdo do modal. */
37
41
  readonly scrollable = false;
38
42
  /**
39
43
  * Define o alinhamento do conteúdo do rodapé (slot="footer").
40
44
  */
41
45
  readonly alignFooter: 'start' | 'end' | 'center';
42
- /** Evento emitido quando o modal solicita ser fechado (pelo botão 'x', tecla 'Escape' ou clique no scrim). */
46
+ private isOpeningParentScrim;
47
+ /**
48
+ * Evento emitido quando o modal é aberto (quando `show` muda de `false` para `true`).
49
+ */
50
+ brModalOpen: EventEmitter<void>;
51
+ /**
52
+ * Evento emitido após o modal ser fechado (quando `show` muda de `true` para `false`).
53
+ */
43
54
  brModalClose: EventEmitter<void>;
55
+ /**
56
+ * Evento emitido antes do fechamento do modal (quando o botão X é clicado).
57
+ * Se autoClose está desativado, o desenvolvedor deve fechar manualmente o modal após este evento.
58
+ * Se autoClose está ativado, o modal fecha automaticamente após este evento.
59
+ */
60
+ brModalBeforeClose: EventEmitter<void>;
61
+ handleShowChange(newValue: boolean, oldValue: boolean): void;
62
+ private closeParentScrim;
63
+ componentWillLoad(): void;
64
+ componentDidLoad(): void;
65
+ disconnectedCallback(): void;
66
+ /**
67
+ * Adiciona listeners para eventos do parent scrim
68
+ */
69
+ private listenToParentScrimEvents;
70
+ /**
71
+ * Remove listeners de eventos do parent scrim
72
+ */
73
+ private removeParentScrimEventListeners;
74
+ /**
75
+ * Handler para evento brScrimOpen do parent scrim
76
+ * Quando scrim abre programaticamente, a modal deve abrir também
77
+ */
78
+ private handleParentScrimOpen;
79
+ /**
80
+ * Handler para evento brScrimClose do parent scrim
81
+ * Se autoClose=true, fecha a modal junto com o scrim
82
+ * Se autoClose=false, não faz nada (modal permanece aberta)
83
+ */
84
+ private handleParentScrimClose;
85
+ private openParentScrim;
44
86
  private get titleId();
45
87
  private get contentId();
46
88
  private getCssClassMap;
@@ -92,7 +92,7 @@ export declare class Scrim {
92
92
  private focusTimeoutId;
93
93
  private restoreFocusTimeoutId;
94
94
  private static readonly FOCUSABLE_SELECTORS;
95
- handleOpenChange(newValue: boolean): void;
95
+ handleOpenChange(newValue: boolean): Promise<void>;
96
96
  updateStyles(): void;
97
97
  handleActivatorChange(): void;
98
98
  componentWillLoad(): void;
@@ -104,6 +104,40 @@ export declare class Scrim {
104
104
  private addContentEventListener;
105
105
  connectedCallback(): void;
106
106
  disconnectedCallback(): void;
107
+ /**
108
+ * Handler para evento brModalOpen emitido por modal filha
109
+ */
110
+ private handleModalOpen;
111
+ /**
112
+ * Handler para evento brModalClose emitido por modal filha
113
+ */
114
+ private handleModalClose;
115
+ /**
116
+ * Verifica se um elemento é filho direto deste scrim (não nested)
117
+ */
118
+ private isDirectChild;
119
+ /**
120
+ * Adiciona listeners para eventos brModalOpen e brModalClose das modais filhas
121
+ */
122
+ private listenToModalEvents;
123
+ /**
124
+ * Remove listeners dos eventos da modal
125
+ */
126
+ private removeModalEventListener;
127
+ /**
128
+ * Retorna os elementos filhos diretos do scrim via slot padrão
129
+ */
130
+ private getDirectChildren;
131
+ /**
132
+ * Busca uma modal filha direta do scrim
133
+ */
134
+ private findModalChild;
135
+ /**
136
+ * Verifica se há uma modal filha com autoClose=false (padrão ou explícito)
137
+ * Retorna true se:
138
+ * - Existe modal filha E autoClose não é explicitamente true
139
+ */
140
+ private hasModalWithAutoClose;
107
141
  private checkActivatorSlot;
108
142
  private setupActivatorSlotClick;
109
143
  private setupActivator;
@@ -145,6 +179,10 @@ export declare class Scrim {
145
179
  * Remove interceptação global de eventos
146
180
  */
147
181
  private removeGlobalEventInterception;
182
+ /**
183
+ * Handler para clique na máscara do scrim
184
+ * Fecha o scrim se disableCloseOnClick for false e não houver modal filha com autoClose=false
185
+ */
148
186
  private handleMaskClick;
149
187
  private getCssClassMap;
150
188
  /**
@@ -1418,7 +1418,7 @@ export namespace Components {
1418
1418
  */
1419
1419
  "alignFooter": 'start' | 'end' | 'center';
1420
1420
  /**
1421
- * Se `true`, o modal se fechará automaticamente ao clicar no botão de fechar ou pressionar a tecla 'Escape'.
1421
+ * Define o comportamento de fechamento do modal. - `true`: O modal fecha automaticamente ao clicar no botão fechar. - `false`: O modal emite `brModalBeforeClose` mas não fecha, permitindo a implementação de lógica customizada (validação, confirmação, etc.) antes do fechamento. O desenvolvedor deve controlar manualmente o fechamento.
1422
1422
  * @default false
1423
1423
  */
1424
1424
  "autoClose": boolean;
@@ -1439,11 +1439,6 @@ export namespace Components {
1439
1439
  * Método público para abrir o modal
1440
1440
  */
1441
1441
  "open": () => Promise<void>;
1442
- /**
1443
- * Se `true`, exibe um fundo escurecido (scrim) atrás do modal.
1444
- * @default false
1445
- */
1446
- "scrim": false;
1447
1442
  /**
1448
1443
  * Se `true`, habilita a rolagem interna do conteúdo do modal.
1449
1444
  * @default false
@@ -3165,7 +3160,9 @@ declare global {
3165
3160
  new (): HTMLBrMessageElement;
3166
3161
  };
3167
3162
  interface HTMLBrModalElementEventMap {
3163
+ "brModalOpen": void;
3168
3164
  "brModalClose": void;
3165
+ "brModalBeforeClose": void;
3169
3166
  }
3170
3167
  /**
3171
3168
  * ## Design System
@@ -5094,7 +5091,7 @@ declare namespace LocalJSX {
5094
5091
  */
5095
5092
  "alignFooter"?: 'start' | 'end' | 'center';
5096
5093
  /**
5097
- * Se `true`, o modal se fechará automaticamente ao clicar no botão de fechar ou pressionar a tecla 'Escape'.
5094
+ * Define o comportamento de fechamento do modal. - `true`: O modal fecha automaticamente ao clicar no botão fechar. - `false`: O modal emite `brModalBeforeClose` mas não fecha, permitindo a implementação de lógica customizada (validação, confirmação, etc.) antes do fechamento. O desenvolvedor deve controlar manualmente o fechamento.
5098
5095
  * @default false
5099
5096
  */
5100
5097
  "autoClose"?: boolean;
@@ -5108,14 +5105,17 @@ declare namespace LocalJSX {
5108
5105
  */
5109
5106
  "initialFocusSelector"?: string;
5110
5107
  /**
5111
- * Evento emitido quando o modal solicita ser fechado (pelo botão 'x', tecla 'Escape' ou clique no scrim).
5108
+ * Evento emitido antes do fechamento do modal (quando o botão X é clicado). Se autoClose está desativado, o desenvolvedor deve fechar manualmente o modal após este evento. Se autoClose está ativado, o modal fecha automaticamente após este evento.
5109
+ */
5110
+ "onBrModalBeforeClose"?: (event: BrModalCustomEvent<void>) => void;
5111
+ /**
5112
+ * Evento emitido após o modal ser fechado (quando `show` muda de `true` para `false`).
5112
5113
  */
5113
5114
  "onBrModalClose"?: (event: BrModalCustomEvent<void>) => void;
5114
5115
  /**
5115
- * Se `true`, exibe um fundo escurecido (scrim) atrás do modal.
5116
- * @default false
5116
+ * Evento emitido quando o modal é aberto (quando `show` muda de `false` para `true`).
5117
5117
  */
5118
- "scrim"?: false;
5118
+ "onBrModalOpen"?: (event: BrModalCustomEvent<void>) => void;
5119
5119
  /**
5120
5120
  * Se `true`, habilita a rolagem interna do conteúdo do modal.
5121
5121
  * @default false