@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
@@ -11,7 +11,9 @@ const modalCss = "*,*::before,*::after{-webkit-box-sizing:border-box;box-sizing:
11
11
  const Modal = class {
12
12
  constructor(hostRef) {
13
13
  registerInstance(this, hostRef);
14
+ this.brModalOpen = createEvent(this, "brModalOpen", 7);
14
15
  this.brModalClose = createEvent(this, "brModalClose", 7);
16
+ this.brModalBeforeClose = createEvent(this, "brModalBeforeClose", 7);
15
17
  if (hostRef.$hostElement$["s-ei"]) {
16
18
  this.elementInternals = hostRef.$hostElement$["s-ei"];
17
19
  }
@@ -26,32 +28,132 @@ const Modal = class {
26
28
  this.customId = Helpers.generateUniqueId('modal');
27
29
  /** Controla a visibilidade do modal. */
28
30
  this.show = false;
29
- /** Se `true`, o modal se fechará automaticamente ao clicar no botão de fechar ou pressionar a tecla 'Escape'. */
31
+ /**
32
+ * Define o comportamento de fechamento do modal.
33
+ *
34
+ * - `true`: O modal fecha automaticamente ao clicar no botão fechar.
35
+ * - `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
36
+ * controlar manualmente o fechamento.
37
+ */
30
38
  this.autoClose = false;
31
39
  /**
32
40
  * Define o tamanho (largura) do modal.
33
41
  */
34
42
  this.size = 'medium';
35
- /** Se `true`, exibe um fundo escurecido (scrim) atrás do modal. */
36
- this.scrim = false;
37
43
  /** Se `true`, habilita a rolagem interna do conteúdo do modal. */
38
44
  this.scrollable = false;
39
45
  /**
40
46
  * Define o alinhamento do conteúdo do rodapé (slot="footer").
41
47
  */
42
48
  this.alignFooter = 'center';
49
+ this.isOpeningParentScrim = false;
50
+ /**
51
+ * Handler para evento brScrimOpen do parent scrim
52
+ * Quando scrim abre programaticamente, a modal deve abrir também
53
+ */
54
+ this.handleParentScrimOpen = () => {
55
+ const parentScrim = this.el.closest('br-scrim');
56
+ if (parentScrim === null)
57
+ return;
58
+ if (!this.show) {
59
+ this.show = true;
60
+ }
61
+ };
62
+ /**
63
+ * Handler para evento brScrimClose do parent scrim
64
+ * Se autoClose=true, fecha a modal junto com o scrim
65
+ * Se autoClose=false, não faz nada (modal permanece aberta)
66
+ */
67
+ this.handleParentScrimClose = () => {
68
+ const parentScrim = this.el.closest('br-scrim');
69
+ if (parentScrim === null)
70
+ return;
71
+ if (this.autoClose && this.show) {
72
+ this.show = false;
73
+ }
74
+ };
43
75
  this.handleClose = () => {
44
- this.brModalClose.emit();
76
+ this.brModalBeforeClose.emit();
45
77
  if (this.autoClose) {
46
78
  this.show = false;
47
- // Se o modal está dentro de um br-scrim, fecha o scrim também
48
- const parentScrim = this.el.closest('br-scrim');
49
- if (parentScrim) {
50
- parentScrim.close();
51
- }
52
79
  }
53
80
  };
54
81
  }
82
+ handleShowChange(newValue, oldValue) {
83
+ if (newValue) {
84
+ this.brModalOpen.emit();
85
+ this.openParentScrim();
86
+ }
87
+ else if (oldValue === true) {
88
+ this.brModalClose.emit();
89
+ this.closeParentScrim();
90
+ }
91
+ }
92
+ closeParentScrim() {
93
+ const parentScrim = this.el.closest('br-scrim');
94
+ if (parentScrim && typeof parentScrim.close === 'function') {
95
+ parentScrim.close();
96
+ }
97
+ }
98
+ componentWillLoad() {
99
+ if (!this.show) {
100
+ const parentScrim = this.el.closest('br-scrim');
101
+ if (parentScrim !== null && parentScrim.isOpen) {
102
+ this.show = true;
103
+ }
104
+ }
105
+ }
106
+ componentDidLoad() {
107
+ this.listenToParentScrimEvents();
108
+ if (this.show) {
109
+ this.openParentScrim();
110
+ }
111
+ }
112
+ disconnectedCallback() {
113
+ this.isOpeningParentScrim = false;
114
+ this.removeParentScrimEventListeners();
115
+ }
116
+ /**
117
+ * Adiciona listeners para eventos do parent scrim
118
+ */
119
+ listenToParentScrimEvents() {
120
+ const parentScrim = this.el.closest('br-scrim');
121
+ if (parentScrim !== null) {
122
+ parentScrim.addEventListener('brScrimOpen', this.handleParentScrimOpen);
123
+ parentScrim.addEventListener('brScrimClose', this.handleParentScrimClose);
124
+ }
125
+ }
126
+ /**
127
+ * Remove listeners de eventos do parent scrim
128
+ */
129
+ removeParentScrimEventListeners() {
130
+ const parentScrim = this.el.closest('br-scrim');
131
+ if (parentScrim !== null) {
132
+ parentScrim.removeEventListener('brScrimOpen', this.handleParentScrimOpen);
133
+ parentScrim.removeEventListener('brScrimClose', this.handleParentScrimClose);
134
+ }
135
+ }
136
+ openParentScrim() {
137
+ if (this.isOpeningParentScrim)
138
+ return;
139
+ const parentScrim = this.el.closest('br-scrim');
140
+ if (parentScrim && !parentScrim.isOpen) {
141
+ this.isOpeningParentScrim = true;
142
+ Promise.resolve()
143
+ .then(() => {
144
+ try {
145
+ return parentScrim.open();
146
+ }
147
+ catch (error) {
148
+ console.warn('br-modal: Erro ao abrir scrim pai:', error);
149
+ throw error;
150
+ }
151
+ })
152
+ .finally(() => {
153
+ this.isOpeningParentScrim = false;
154
+ });
155
+ }
156
+ }
55
157
  get titleId() {
56
158
  return `${this.customId}-title`;
57
159
  }
@@ -71,6 +173,7 @@ const Modal = class {
71
173
  open() {
72
174
  return __awaiter(this, void 0, void 0, function* () {
73
175
  this.show = true;
176
+ this.openParentScrim();
74
177
  });
75
178
  }
76
179
  /**
@@ -78,22 +181,23 @@ const Modal = class {
78
181
  */
79
182
  close() {
80
183
  return __awaiter(this, void 0, void 0, function* () {
81
- this.show = false;
82
- // Se o modal está dentro de um br-scrim, fecha o scrim também
83
- const parentScrim = this.el.closest('br-scrim');
84
- if (parentScrim) {
85
- parentScrim.close();
184
+ if (!this.autoClose) {
185
+ return;
86
186
  }
187
+ this.show = false;
87
188
  });
88
189
  }
89
190
  render() {
90
191
  if (!this.show) {
91
192
  return null;
92
193
  }
93
- return (h(Host, null, h("div", { class: this.getCssClassMap(), role: "dialog", "aria-modal": "true", "aria-labelledby": this.titleId, "aria-describedby": this.contentId }, h("div", { class: "br-modal-header" }, h("div", { class: "modal-title", id: this.titleId }, h("slot", { name: "header" }, this.titleText)), h("slot", { name: "close-button" }, h("br-button", { class: "close", shape: "circle", density: "small", "aria-label": "Fechar", onClick: this.handleClose }, h("br-icon", { "icon-name": "fa-solid:times" })))), h("div", { id: this.contentId, class: "br-modal-body" }, h("slot", null)), h("div", { class: `br-modal-footer ${this.alignFooter ? `justify-content-${this.alignFooter}` : ''}` }, h("slot", { name: "footer" })))));
194
+ return (h(Host, null, h("div", { class: this.getCssClassMap(), role: "dialog", "aria-modal": "true", "aria-labelledby": this.titleId, "aria-describedby": this.contentId }, h("div", { class: "br-modal-header" }, h("div", { class: "modal-title", id: this.titleId }, h("slot", { name: "header" }, this.titleText)), h("slot", { name: "close-button" }, h("br-button", { class: "close", shape: "circle", density: "small", "aria-label": "Fechar", onClick: this.handleClose }, h("br-icon", { "icon-name": "fa-solid:times" })))), h("div", { id: this.contentId, class: "br-modal-body" }, h("slot", null)), h("div", { class: `br-modal-footer ${this.alignFooter !== undefined ? `justify-content-${this.alignFooter}` : ''}` }, h("slot", { name: "footer" })))));
94
195
  }
95
196
  static get formAssociated() { return true; }
96
197
  get el() { return getElement(this); }
198
+ static get watchers() { return {
199
+ "show": ["handleShowChange"]
200
+ }; }
97
201
  };
98
202
  Modal.style = modalCss;
99
203
 
@@ -1 +1 @@
1
- {"version":3,"file":"br-modal.entry.js","sources":["../../packages/webcomponents/src/components/modal/modal.scss?tag=br-modal&encapsulation=shadow","../../packages/webcomponents/src/components/modal/modal.tsx"],"sourcesContent":["@import \"~@govbr-ds/core/src/components/modal/modal\";\n\n.br-modal.scrollable {\n max-height: 400px;\n}\n\n.br-modal-footer.justify-content-end {\n justify-content: flex-end;\n}\n","import { AttachInternals, Component, Element, Event, EventEmitter, h, Host, Method, Prop } from '@stencil/core'\n\nimport Helpers from '../../utils/helpers'\nimport { CssClassMap } from '../../utils/interfaces'\n\n/**\n * ## Design System\n *\n * Para a documentação completa de design, incluindo diretrizes de uso, acessibilidade e exemplos visuais, consulte o [Design System do GovBR](https://www.gov.br/ds/components/modal?tab=designer).\n *\n * @slot header - Cabeçalho do modal. Se não for usado, o `title-text` será exibido.\n * @slot default - Corpo do modal.\n * @slot footer - Rodapé do modal.\n * @slot close-button - Botão de fechar customizado. Se não for usado, o botão padrão será exibido.\n *\n */\n@Component({\n tag: 'br-modal',\n styleUrl: 'modal.scss',\n shadow: true,\n formAssociated: true,\n})\nexport class Modal {\n /** Referência ao elemento host do componente. */\n @Element() el: HTMLBrModalElement\n\n @AttachInternals() elementInternals: ElementInternals\n\n /**\n * Identificador único.\n * Caso não seja fornecido, um ID gerado automaticamente será usado.\n */\n @Prop({ reflect: true }) readonly customId: string = Helpers.generateUniqueId('modal')\n\n /** O texto do título a ser exibido no cabeçalho do modal. Usado quando o slot `header` não é fornecido. */\n @Prop() readonly titleText: string\n\n /** Controla a visibilidade do modal. */\n @Prop({ reflect: true, mutable: true }) show = false\n\n /** Se `true`, o modal se fechará automaticamente ao clicar no botão de fechar ou pressionar a tecla 'Escape'. */\n @Prop({ reflect: true }) autoClose = false\n\n /** Seletor CSS para o elemento que deve receber foco quando o modal é aberto. */\n @Prop() readonly initialFocusSelector: string\n\n /**\n * Define o tamanho (largura) do modal.\n */\n @Prop({ reflect: true }) readonly size: 'xsmall' | 'small' | 'medium' | 'large' | 'auto' = 'medium'\n\n /** Se `true`, exibe um fundo escurecido (scrim) atrás do modal. */\n @Prop({ reflect: true }) readonly scrim = false\n\n /** Se `true`, habilita a rolagem interna do conteúdo do modal. */\n @Prop({ reflect: true }) readonly scrollable = false\n\n /**\n * Define o alinhamento do conteúdo do rodapé (slot=\"footer\").\n */\n @Prop({ reflect: true }) readonly alignFooter: 'start' | 'end' | 'center' = 'center'\n\n /** Evento emitido quando o modal solicita ser fechado (pelo botão 'x', tecla 'Escape' ou clique no scrim). */\n @Event() brModalClose: EventEmitter<void>\n\n private get titleId() {\n return `${this.customId}-title`\n }\n\n private get contentId() {\n return `${this.customId}-content`\n }\n\n private getCssClassMap(): CssClassMap {\n return {\n 'br-modal': true,\n [this.size]: true,\n scrollable: this.scrollable,\n }\n }\n\n private handleClose = () => {\n this.brModalClose.emit()\n if (this.autoClose) {\n this.show = false\n\n // Se o modal está dentro de um br-scrim, fecha o scrim também\n const parentScrim = this.el.closest('br-scrim')\n if (parentScrim) {\n parentScrim.close()\n }\n }\n }\n\n /**\n * Método público para abrir o modal\n */\n @Method()\n async open() {\n this.show = true\n }\n\n /**\n * Método público para fechar o modal\n */\n @Method()\n async close() {\n this.show = false\n\n // Se o modal está dentro de um br-scrim, fecha o scrim também\n const parentScrim = this.el.closest('br-scrim')\n if (parentScrim) {\n parentScrim.close()\n }\n }\n\n render() {\n if (!this.show) {\n return null\n }\n\n return (\n <Host>\n <div\n class={this.getCssClassMap()}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={this.titleId}\n aria-describedby={this.contentId}\n >\n <div class=\"br-modal-header\">\n <div class=\"modal-title\" id={this.titleId}>\n <slot name=\"header\">{this.titleText}</slot>\n </div>\n <slot name=\"close-button\">\n <br-button class=\"close\" shape=\"circle\" density=\"small\" aria-label=\"Fechar\" onClick={this.handleClose}>\n <br-icon icon-name=\"fa-solid:times\"></br-icon>\n </br-button>\n </slot>\n </div>\n <div id={this.contentId} class=\"br-modal-body\">\n <slot></slot>\n </div>\n <div class={`br-modal-footer ${this.alignFooter ? `justify-content-${this.alignFooter}` : ''}`}>\n <slot name=\"footer\"></slot>\n </div>\n </div>\n </Host>\n )\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"br-modal.entry.js","sources":["../../packages/webcomponents/src/components/modal/modal.scss?tag=br-modal&encapsulation=shadow","../../packages/webcomponents/src/components/modal/modal.tsx"],"sourcesContent":["@import \"~@govbr-ds/core/src/components/modal/modal\";\n\n.br-modal.scrollable {\n max-height: 400px;\n}\n\n.br-modal-footer.justify-content-end {\n justify-content: flex-end;\n}\n","import { AttachInternals, Component, Element, Event, EventEmitter, h, Host, Method, Prop, Watch } from '@stencil/core'\n\nimport Helpers from '../../utils/helpers'\nimport { CssClassMap } from '../../utils/interfaces'\n\n/**\n * ## Design System\n *\n * Para a documentação completa de design, incluindo diretrizes de uso, acessibilidade e exemplos visuais, consulte o [Design System do GovBR](https://www.gov.br/ds/components/modal?tab=designer).\n *\n * @slot header - Cabeçalho do modal. Se não for usado, o `title-text` será exibido.\n * @slot default - Corpo do modal.\n * @slot footer - Rodapé do modal.\n * @slot close-button - Botão de fechar customizado. Se não for usado, o botão padrão será exibido.\n *\n */\n@Component({\n tag: 'br-modal',\n styleUrl: 'modal.scss',\n shadow: true,\n formAssociated: true,\n})\nexport class Modal {\n /** Referência ao elemento host do componente. */\n @Element() el: HTMLBrModalElement\n\n @AttachInternals() elementInternals: ElementInternals\n\n /**\n * Identificador único.\n * Caso não seja fornecido, um ID gerado automaticamente será usado.\n */\n @Prop({ reflect: true }) readonly customId: string = Helpers.generateUniqueId('modal')\n\n /** O texto do título a ser exibido no cabeçalho do modal. Usado quando o slot `header` não é fornecido. */\n @Prop() readonly titleText: string\n\n /** Controla a visibilidade do modal. */\n @Prop({ reflect: true, mutable: true }) show = false\n\n /**\n * Define o comportamento de fechamento do modal.\n *\n * - `true`: O modal fecha automaticamente ao clicar no botão fechar.\n * - `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\n * controlar manualmente o fechamento.\n */\n @Prop({ reflect: true }) autoClose = false\n\n /** Seletor CSS para o elemento que deve receber foco quando o modal é aberto. */\n @Prop() readonly initialFocusSelector: string\n\n /**\n * Define o tamanho (largura) do modal.\n */\n @Prop({ reflect: true }) readonly size: 'xsmall' | 'small' | 'medium' | 'large' | 'auto' = 'medium'\n\n /** Se `true`, habilita a rolagem interna do conteúdo do modal. */\n @Prop({ reflect: true }) readonly scrollable = false\n\n /**\n * Define o alinhamento do conteúdo do rodapé (slot=\"footer\").\n */\n @Prop({ reflect: true }) readonly alignFooter: 'start' | 'end' | 'center' = 'center'\n\n private isOpeningParentScrim = false\n\n /**\n * Evento emitido quando o modal é aberto (quando `show` muda de `false` para `true`).\n */\n @Event() brModalOpen: EventEmitter<void>\n\n /**\n * Evento emitido após o modal ser fechado (quando `show` muda de `true` para `false`).\n */\n @Event() brModalClose: EventEmitter<void>\n\n /**\n * Evento emitido antes do fechamento do modal (quando o botão X é clicado).\n * Se autoClose está desativado, o desenvolvedor deve fechar manualmente o modal após este evento.\n * Se autoClose está ativado, o modal fecha automaticamente após este evento.\n */\n @Event() brModalBeforeClose: EventEmitter<void>\n\n @Watch('show')\n handleShowChange(newValue: boolean, oldValue: boolean) {\n if (newValue) {\n this.brModalOpen.emit()\n this.openParentScrim()\n } else if (oldValue === true) {\n this.brModalClose.emit()\n this.closeParentScrim()\n }\n }\n\n private closeParentScrim() {\n const parentScrim = this.el.closest('br-scrim')\n if (parentScrim && typeof parentScrim.close === 'function') {\n parentScrim.close()\n }\n }\n\n componentWillLoad() {\n if (!this.show) {\n const parentScrim = this.el.closest('br-scrim')\n if (parentScrim !== null && parentScrim.isOpen) {\n this.show = true\n }\n }\n }\n\n componentDidLoad() {\n this.listenToParentScrimEvents()\n\n if (this.show) {\n this.openParentScrim()\n }\n }\n\n disconnectedCallback() {\n this.isOpeningParentScrim = false\n this.removeParentScrimEventListeners()\n }\n\n /**\n * Adiciona listeners para eventos do parent scrim\n */\n private listenToParentScrimEvents() {\n const parentScrim = this.el.closest('br-scrim')\n if (parentScrim !== null) {\n parentScrim.addEventListener('brScrimOpen', this.handleParentScrimOpen)\n parentScrim.addEventListener('brScrimClose', this.handleParentScrimClose)\n }\n }\n\n /**\n * Remove listeners de eventos do parent scrim\n */\n private removeParentScrimEventListeners() {\n const parentScrim = this.el.closest('br-scrim')\n if (parentScrim !== null) {\n parentScrim.removeEventListener('brScrimOpen', this.handleParentScrimOpen)\n parentScrim.removeEventListener('brScrimClose', this.handleParentScrimClose)\n }\n }\n\n /**\n * Handler para evento brScrimOpen do parent scrim\n * Quando scrim abre programaticamente, a modal deve abrir também\n */\n private handleParentScrimOpen = () => {\n const parentScrim = this.el.closest('br-scrim')\n if (parentScrim === null) return\n\n if (!this.show) {\n this.show = true\n }\n }\n\n /**\n * Handler para evento brScrimClose do parent scrim\n * Se autoClose=true, fecha a modal junto com o scrim\n * Se autoClose=false, não faz nada (modal permanece aberta)\n */\n private handleParentScrimClose = () => {\n const parentScrim = this.el.closest('br-scrim')\n if (parentScrim === null) return\n\n if (this.autoClose && this.show) {\n this.show = false\n }\n }\n\n private openParentScrim() {\n if (this.isOpeningParentScrim) return\n\n const parentScrim = this.el.closest('br-scrim')\n if (parentScrim && !parentScrim.isOpen) {\n this.isOpeningParentScrim = true\n\n Promise.resolve()\n .then(() => {\n try {\n return parentScrim.open()\n } catch (error) {\n console.warn('br-modal: Erro ao abrir scrim pai:', error)\n throw error\n }\n })\n .finally(() => {\n this.isOpeningParentScrim = false\n })\n }\n }\n\n private get titleId() {\n return `${this.customId}-title`\n }\n\n private get contentId() {\n return `${this.customId}-content`\n }\n\n private getCssClassMap(): CssClassMap {\n return {\n 'br-modal': true,\n [this.size]: true,\n scrollable: this.scrollable,\n }\n }\n\n private handleClose = () => {\n this.brModalBeforeClose.emit()\n\n if (this.autoClose) {\n this.show = false\n }\n }\n\n /**\n * Método público para abrir o modal\n */\n @Method()\n async open() {\n this.show = true\n\n this.openParentScrim()\n }\n\n /**\n * Método público para fechar o modal\n */\n @Method()\n async close() {\n if (!this.autoClose) {\n return\n }\n\n this.show = false\n }\n\n render() {\n if (!this.show) {\n return null\n }\n\n return (\n <Host>\n <div\n class={this.getCssClassMap()}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={this.titleId}\n aria-describedby={this.contentId}\n >\n <div class=\"br-modal-header\">\n <div class=\"modal-title\" id={this.titleId}>\n <slot name=\"header\">{this.titleText}</slot>\n </div>\n <slot name=\"close-button\">\n <br-button class=\"close\" shape=\"circle\" density=\"small\" aria-label=\"Fechar\" onClick={this.handleClose}>\n <br-icon icon-name=\"fa-solid:times\"></br-icon>\n </br-button>\n </slot>\n </div>\n <div id={this.contentId} class=\"br-modal-body\">\n <slot></slot>\n </div>\n <div class={`br-modal-footer ${this.alignFooter !== undefined ? `justify-content-${this.alignFooter}` : ''}`}>\n <slot name=\"footer\"></slot>\n </div>\n </div>\n </Host>\n )\n }\n}\n"],"names":[],"mappings":"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"}
@@ -87,6 +87,29 @@ const Scrim = class {
87
87
  this.previouslyFocusedElement = null;
88
88
  this.focusTimeoutId = null;
89
89
  this.restoreFocusTimeoutId = null;
90
+ // ======================================================================
91
+ // GERENCIAMENTO DE COMPONENTES FILHOS
92
+ // ======================================================================
93
+ /**
94
+ * Handler para evento brModalOpen emitido por modal filha
95
+ */
96
+ this.handleModalOpen = (event) => {
97
+ const modalElement = event.target;
98
+ if (!this.isDirectChild(modalElement))
99
+ return;
100
+ if (!this.isOpen) {
101
+ this.open();
102
+ }
103
+ };
104
+ /**
105
+ * Handler para evento brModalClose emitido por modal filha
106
+ */
107
+ this.handleModalClose = (event) => {
108
+ const modalElement = event.target;
109
+ if (!this.isDirectChild(modalElement))
110
+ return;
111
+ this.close();
112
+ };
90
113
  this.handleActivatorClick = () => {
91
114
  this.toggle();
92
115
  };
@@ -104,6 +127,10 @@ const Scrim = class {
104
127
  const reference = (_a = this.scrollOrigin) !== null && _a !== void 0 ? _a : this.lastScrollTop;
105
128
  if (Math.abs(currentScroll - reference) > this.scrollThreshold) {
106
129
  this.scrollOrigin = null;
130
+ // Não fecha se tiver modal filha com autoClose=false ou não definido
131
+ if (this.hasModalWithAutoClose()) {
132
+ return;
133
+ }
107
134
  this.isOpen = false;
108
135
  this.handleOpenChange(false);
109
136
  return;
@@ -139,7 +166,9 @@ const Scrim = class {
139
166
  }
140
167
  if (event.key === 'Escape' && !this.disableCloseOnClick) {
141
168
  event.preventDefault();
142
- this.isOpen = false;
169
+ if (!this.hasModalWithAutoClose()) {
170
+ this.isOpen = false;
171
+ }
143
172
  }
144
173
  };
145
174
  // Intercepta TODOS os eventos de clique globalmente quando scrim está ativo
@@ -173,11 +202,15 @@ const Scrim = class {
173
202
  }, 0);
174
203
  }
175
204
  };
176
- // ======================================================================
177
- // MANIPULAÇÃO DE EVENTOS E UTILITÁRIOS
178
- // ======================================================================
205
+ /**
206
+ * Handler para clique na máscara do scrim
207
+ * Fecha o scrim se disableCloseOnClick for false e não houver modal filha com autoClose=false
208
+ */
179
209
  this.handleMaskClick = (_event) => {
180
210
  if (!this.disableCloseOnClick) {
211
+ if (this.hasModalWithAutoClose()) {
212
+ return;
213
+ }
181
214
  this.close();
182
215
  }
183
216
  };
@@ -186,37 +219,39 @@ const Scrim = class {
186
219
  // LIFECYCLE HOOKS E WATCHERS
187
220
  // ======================================================================
188
221
  handleOpenChange(newValue) {
189
- // Cancelar qualquer timeout anterior
190
- if (this.focusTimeoutId !== null) {
191
- clearTimeout(this.focusTimeoutId);
192
- this.focusTimeoutId = null;
193
- }
194
- if (this.restoreFocusTimeoutId !== null) {
195
- clearTimeout(this.restoreFocusTimeoutId);
196
- this.restoreFocusTimeoutId = null;
197
- }
198
- this.isActive = newValue;
199
- if (newValue && this.scrollStrategy === 'close') {
200
- const currentScroll = window.scrollY;
201
- this.lastScrollTop = currentScroll;
202
- this.scrollOrigin = currentScroll;
203
- }
204
- this.updateStyles();
205
- if (this.isActive) {
206
- this.previouslyFocusedElement = document.activeElement;
207
- this.applyScrollStrategy();
208
- this.addGlobalEventInterception();
209
- this.focusTimeoutId = setTimeout(() => {
210
- this.focusFirstElement();
211
- }, 100);
212
- this.brScrimOpen.emit();
213
- }
214
- else {
215
- this.resetScrolling();
216
- this.removeGlobalEventInterception();
217
- this.restoreFocus();
218
- this.brScrimClose.emit();
219
- }
222
+ return __awaiter(this, void 0, void 0, function* () {
223
+ // Cancelar qualquer timeout anterior
224
+ if (this.focusTimeoutId !== null) {
225
+ clearTimeout(this.focusTimeoutId);
226
+ this.focusTimeoutId = null;
227
+ }
228
+ if (this.restoreFocusTimeoutId !== null) {
229
+ clearTimeout(this.restoreFocusTimeoutId);
230
+ this.restoreFocusTimeoutId = null;
231
+ }
232
+ this.isActive = newValue;
233
+ if (newValue && this.scrollStrategy === 'close') {
234
+ const currentScroll = window.scrollY;
235
+ this.lastScrollTop = currentScroll;
236
+ this.scrollOrigin = currentScroll;
237
+ }
238
+ this.updateStyles();
239
+ if (this.isActive) {
240
+ this.previouslyFocusedElement = document.activeElement;
241
+ this.applyScrollStrategy();
242
+ this.addGlobalEventInterception();
243
+ this.focusTimeoutId = setTimeout(() => {
244
+ this.focusFirstElement();
245
+ }, 100);
246
+ this.brScrimOpen.emit();
247
+ }
248
+ else {
249
+ this.resetScrolling();
250
+ this.removeGlobalEventInterception();
251
+ this.restoreFocus();
252
+ this.brScrimClose.emit();
253
+ }
254
+ });
220
255
  }
221
256
  updateStyles() {
222
257
  if (this.zIndex !== null && this.zIndex !== undefined) {
@@ -243,6 +278,7 @@ const Scrim = class {
243
278
  this.setupActivator();
244
279
  this.setupActivatorSlotClick();
245
280
  this.addContentEventListener();
281
+ this.listenToModalEvents();
246
282
  if (this.isActive) {
247
283
  this.applyScrollStrategy();
248
284
  this.addGlobalEventInterception();
@@ -276,7 +312,6 @@ const Scrim = class {
276
312
  clearTimeout(this.restoreFocusTimeoutId);
277
313
  this.restoreFocusTimeoutId = null;
278
314
  }
279
- // Remover event listeners
280
315
  window.removeEventListener('scroll', this.handleScrollClose);
281
316
  window.removeEventListener('scroll', this.handleBlockScroll);
282
317
  if (this.contentRef !== null) {
@@ -285,6 +320,58 @@ const Scrim = class {
285
320
  this.removeActivatorClickListener();
286
321
  this.cleanupActivatorSlotClick();
287
322
  this.removeGlobalEventInterception();
323
+ this.removeModalEventListener();
324
+ }
325
+ /**
326
+ * Verifica se um elemento é filho direto deste scrim (não nested)
327
+ */
328
+ isDirectChild(element) {
329
+ const children = this.getDirectChildren();
330
+ return children.some((child) => child === element || child.contains(element));
331
+ }
332
+ /**
333
+ * Adiciona listeners para eventos brModalOpen e brModalClose das modais filhas
334
+ */
335
+ listenToModalEvents() {
336
+ this.el.addEventListener('brModalOpen', this.handleModalOpen);
337
+ this.el.addEventListener('brModalClose', this.handleModalClose);
338
+ }
339
+ /**
340
+ * Remove listeners dos eventos da modal
341
+ */
342
+ removeModalEventListener() {
343
+ this.el.removeEventListener('brModalOpen', this.handleModalOpen);
344
+ this.el.removeEventListener('brModalClose', this.handleModalClose);
345
+ }
346
+ /**
347
+ * Retorna os elementos filhos diretos do scrim via slot padrão
348
+ */
349
+ getDirectChildren() {
350
+ const shadowRoot = this.el.shadowRoot;
351
+ if (shadowRoot === null)
352
+ return [];
353
+ const slot = shadowRoot.querySelector('slot:not([name])');
354
+ if (slot === null)
355
+ return [];
356
+ return slot.assignedElements();
357
+ }
358
+ /**
359
+ * Busca uma modal filha direta do scrim
360
+ */
361
+ findModalChild() {
362
+ var _a;
363
+ const children = this.getDirectChildren();
364
+ const modalElement = children.find((child) => child.tagName === 'BR-MODAL');
365
+ return (_a = modalElement) !== null && _a !== void 0 ? _a : null;
366
+ }
367
+ /**
368
+ * Verifica se há uma modal filha com autoClose=false (padrão ou explícito)
369
+ * Retorna true se:
370
+ * - Existe modal filha E autoClose não é explicitamente true
371
+ */
372
+ hasModalWithAutoClose() {
373
+ const modal = this.findModalChild();
374
+ return modal !== null && modal.autoClose !== true;
288
375
  }
289
376
  // ======================================================================
290
377
  // GERENCIAMENTO DO ACTIVATOR (ELEMENTO ACIONADOR)
@@ -473,7 +560,11 @@ const Scrim = class {
473
560
  return elements.filter((el) => el.offsetWidth > 0 && el.offsetHeight > 0 && getComputedStyle(el).visibility !== 'hidden');
474
561
  }
475
562
  shouldHandleEscape(event) {
476
- return (event.key === 'Escape' || event.key === 'Esc') && this.isActive && !this.disableCloseOnClick;
563
+ if ((event.key === 'Escape' || event.key === 'Esc') && this.isActive && !this.disableCloseOnClick) {
564
+ // Não fecha se tiver modal filha com autoClose=false ou não definido
565
+ return !this.hasModalWithAutoClose();
566
+ }
567
+ return false;
477
568
  }
478
569
  handleTabNavigation(event) {
479
570
  const focusableElements = this.getFocusableElements();
@@ -534,6 +625,9 @@ const Scrim = class {
534
625
  document.removeEventListener('focus', this.handleGlobalFocus, true);
535
626
  document.removeEventListener('focusin', this.handleGlobalFocus, true);
536
627
  }
628
+ // ======================================================================
629
+ // UTILITÁRIOS
630
+ // ======================================================================
537
631
  getCssClassMap() {
538
632
  return {
539
633
  'br-scrim': true,
@@ -584,7 +678,7 @@ const Scrim = class {
584
678
  });
585
679
  }
586
680
  render() {
587
- return (h(Host, { key: '1aea7418642867cfb24c099729f34412f9aec7bf' }, h("slot", { key: '4468892291450f13cded3627ee91f31716108443', name: "activator" }), h("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' }, h("div", { key: '6c6df83177f1a14097ec5c08e409caaca3953d3b', class: "mask", onClick: this.handleMaskClick }), h("div", { key: '1af0ecd53a0aaf630069139a7e6935533a563e10', ref: (el) => (this.contentRef = el), id: `${this.customId}-content`, class: "content", tabIndex: -1, onKeyDown: this.handleKeyDown }, h("slot", { key: '2cb75f5b254ed22bbe821998700d9c1f4152dd5b' })))));
681
+ return (h(Host, { key: '249de7af4056263464615cbe086b419f74b8981b' }, h("slot", { key: '1698faa6b492e1ec594eba8425f20582a2af0e4a', name: "activator" }), h("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' }, h("div", { key: 'ef7408a6672fabf4d2f79bc7922f301fd102652e', class: "mask", onClick: this.handleMaskClick }), h("div", { key: '91ffb1a84478f09fc90cefbb97180c5db13dba5c', ref: (el) => (this.contentRef = el), id: `${this.customId}-content`, class: "content", tabIndex: -1, onKeyDown: this.handleKeyDown }, h("slot", { key: '0600ac804980446103154cebf83389ac92e44d9d' })))));
588
682
  }
589
683
  static get formAssociated() { return true; }
590
684
  get el() { return getElement(this); }