@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
@@ -13,7 +13,9 @@ const modalCss = "*,*::before,*::after{-webkit-box-sizing:border-box;box-sizing:
13
13
  const Modal = class {
14
14
  constructor(hostRef) {
15
15
  index.registerInstance(this, hostRef);
16
+ this.brModalOpen = index.createEvent(this, "brModalOpen", 7);
16
17
  this.brModalClose = index.createEvent(this, "brModalClose", 7);
18
+ this.brModalBeforeClose = index.createEvent(this, "brModalBeforeClose", 7);
17
19
  if (hostRef.$hostElement$["s-ei"]) {
18
20
  this.elementInternals = hostRef.$hostElement$["s-ei"];
19
21
  }
@@ -28,32 +30,132 @@ const Modal = class {
28
30
  this.customId = helpers.Helpers.generateUniqueId('modal');
29
31
  /** Controla a visibilidade do modal. */
30
32
  this.show = false;
31
- /** Se `true`, o modal se fechará automaticamente ao clicar no botão de fechar ou pressionar a tecla 'Escape'. */
33
+ /**
34
+ * Define o comportamento de fechamento do modal.
35
+ *
36
+ * - `true`: O modal fecha automaticamente ao clicar no botão fechar.
37
+ * - `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
38
+ * controlar manualmente o fechamento.
39
+ */
32
40
  this.autoClose = false;
33
41
  /**
34
42
  * Define o tamanho (largura) do modal.
35
43
  */
36
44
  this.size = 'medium';
37
- /** Se `true`, exibe um fundo escurecido (scrim) atrás do modal. */
38
- this.scrim = false;
39
45
  /** Se `true`, habilita a rolagem interna do conteúdo do modal. */
40
46
  this.scrollable = false;
41
47
  /**
42
48
  * Define o alinhamento do conteúdo do rodapé (slot="footer").
43
49
  */
44
50
  this.alignFooter = 'center';
51
+ this.isOpeningParentScrim = false;
52
+ /**
53
+ * Handler para evento brScrimOpen do parent scrim
54
+ * Quando scrim abre programaticamente, a modal deve abrir também
55
+ */
56
+ this.handleParentScrimOpen = () => {
57
+ const parentScrim = this.el.closest('br-scrim');
58
+ if (parentScrim === null)
59
+ return;
60
+ if (!this.show) {
61
+ this.show = true;
62
+ }
63
+ };
64
+ /**
65
+ * Handler para evento brScrimClose do parent scrim
66
+ * Se autoClose=true, fecha a modal junto com o scrim
67
+ * Se autoClose=false, não faz nada (modal permanece aberta)
68
+ */
69
+ this.handleParentScrimClose = () => {
70
+ const parentScrim = this.el.closest('br-scrim');
71
+ if (parentScrim === null)
72
+ return;
73
+ if (this.autoClose && this.show) {
74
+ this.show = false;
75
+ }
76
+ };
45
77
  this.handleClose = () => {
46
- this.brModalClose.emit();
78
+ this.brModalBeforeClose.emit();
47
79
  if (this.autoClose) {
48
80
  this.show = false;
49
- // Se o modal está dentro de um br-scrim, fecha o scrim também
50
- const parentScrim = this.el.closest('br-scrim');
51
- if (parentScrim) {
52
- parentScrim.close();
53
- }
54
81
  }
55
82
  };
56
83
  }
84
+ handleShowChange(newValue, oldValue) {
85
+ if (newValue) {
86
+ this.brModalOpen.emit();
87
+ this.openParentScrim();
88
+ }
89
+ else if (oldValue === true) {
90
+ this.brModalClose.emit();
91
+ this.closeParentScrim();
92
+ }
93
+ }
94
+ closeParentScrim() {
95
+ const parentScrim = this.el.closest('br-scrim');
96
+ if (parentScrim && typeof parentScrim.close === 'function') {
97
+ parentScrim.close();
98
+ }
99
+ }
100
+ componentWillLoad() {
101
+ if (!this.show) {
102
+ const parentScrim = this.el.closest('br-scrim');
103
+ if (parentScrim !== null && parentScrim.isOpen) {
104
+ this.show = true;
105
+ }
106
+ }
107
+ }
108
+ componentDidLoad() {
109
+ this.listenToParentScrimEvents();
110
+ if (this.show) {
111
+ this.openParentScrim();
112
+ }
113
+ }
114
+ disconnectedCallback() {
115
+ this.isOpeningParentScrim = false;
116
+ this.removeParentScrimEventListeners();
117
+ }
118
+ /**
119
+ * Adiciona listeners para eventos do parent scrim
120
+ */
121
+ listenToParentScrimEvents() {
122
+ const parentScrim = this.el.closest('br-scrim');
123
+ if (parentScrim !== null) {
124
+ parentScrim.addEventListener('brScrimOpen', this.handleParentScrimOpen);
125
+ parentScrim.addEventListener('brScrimClose', this.handleParentScrimClose);
126
+ }
127
+ }
128
+ /**
129
+ * Remove listeners de eventos do parent scrim
130
+ */
131
+ removeParentScrimEventListeners() {
132
+ const parentScrim = this.el.closest('br-scrim');
133
+ if (parentScrim !== null) {
134
+ parentScrim.removeEventListener('brScrimOpen', this.handleParentScrimOpen);
135
+ parentScrim.removeEventListener('brScrimClose', this.handleParentScrimClose);
136
+ }
137
+ }
138
+ openParentScrim() {
139
+ if (this.isOpeningParentScrim)
140
+ return;
141
+ const parentScrim = this.el.closest('br-scrim');
142
+ if (parentScrim && !parentScrim.isOpen) {
143
+ this.isOpeningParentScrim = true;
144
+ Promise.resolve()
145
+ .then(() => {
146
+ try {
147
+ return parentScrim.open();
148
+ }
149
+ catch (error) {
150
+ console.warn('br-modal: Erro ao abrir scrim pai:', error);
151
+ throw error;
152
+ }
153
+ })
154
+ .finally(() => {
155
+ this.isOpeningParentScrim = false;
156
+ });
157
+ }
158
+ }
57
159
  get titleId() {
58
160
  return `${this.customId}-title`;
59
161
  }
@@ -73,6 +175,7 @@ const Modal = class {
73
175
  open() {
74
176
  return tslib_es6.__awaiter(this, void 0, void 0, function* () {
75
177
  this.show = true;
178
+ this.openParentScrim();
76
179
  });
77
180
  }
78
181
  /**
@@ -80,22 +183,23 @@ const Modal = class {
80
183
  */
81
184
  close() {
82
185
  return tslib_es6.__awaiter(this, void 0, void 0, function* () {
83
- this.show = false;
84
- // Se o modal está dentro de um br-scrim, fecha o scrim também
85
- const parentScrim = this.el.closest('br-scrim');
86
- if (parentScrim) {
87
- parentScrim.close();
186
+ if (!this.autoClose) {
187
+ return;
88
188
  }
189
+ this.show = false;
89
190
  });
90
191
  }
91
192
  render() {
92
193
  if (!this.show) {
93
194
  return null;
94
195
  }
95
- return (index.h(index.Host, null, index.h("div", { class: this.getCssClassMap(), role: "dialog", "aria-modal": "true", "aria-labelledby": this.titleId, "aria-describedby": this.contentId }, index.h("div", { class: "br-modal-header" }, index.h("div", { class: "modal-title", id: this.titleId }, index.h("slot", { name: "header" }, this.titleText)), index.h("slot", { name: "close-button" }, index.h("br-button", { class: "close", shape: "circle", density: "small", "aria-label": "Fechar", onClick: this.handleClose }, index.h("br-icon", { "icon-name": "fa-solid:times" })))), index.h("div", { id: this.contentId, class: "br-modal-body" }, index.h("slot", null)), index.h("div", { class: `br-modal-footer ${this.alignFooter ? `justify-content-${this.alignFooter}` : ''}` }, index.h("slot", { name: "footer" })))));
196
+ return (index.h(index.Host, null, index.h("div", { class: this.getCssClassMap(), role: "dialog", "aria-modal": "true", "aria-labelledby": this.titleId, "aria-describedby": this.contentId }, index.h("div", { class: "br-modal-header" }, index.h("div", { class: "modal-title", id: this.titleId }, index.h("slot", { name: "header" }, this.titleText)), index.h("slot", { name: "close-button" }, index.h("br-button", { class: "close", shape: "circle", density: "small", "aria-label": "Fechar", onClick: this.handleClose }, index.h("br-icon", { "icon-name": "fa-solid:times" })))), index.h("div", { id: this.contentId, class: "br-modal-body" }, index.h("slot", null)), index.h("div", { class: `br-modal-footer ${this.alignFooter !== undefined ? `justify-content-${this.alignFooter}` : ''}` }, index.h("slot", { name: "footer" })))));
96
197
  }
97
198
  static get formAssociated() { return true; }
98
199
  get el() { return index.getElement(this); }
200
+ static get watchers() { return {
201
+ "show": ["handleShowChange"]
202
+ }; }
99
203
  };
100
204
  Modal.style = modalCss;
101
205
 
@@ -1 +1 @@
1
- {"version":3,"file":"br-modal.entry.cjs.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":["Helpers","h","Host"],"mappings":"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"}
1
+ {"version":3,"file":"br-modal.entry.cjs.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":["Helpers","h","Host"],"mappings":";;;;;;;;;;AAAA,MAAM,QAAQ,GAAG,+8cAA+8c;;MCsBn9c,KAAK,GAAA,MAAA;AANlB,IAAA,WAAA,CAAA,OAAA,EAAA;;;;;;;;;;;;AAYE;;;AAGG;QAC+B,IAAA,CAAA,QAAQ,GAAWA,eAAO,CAAC,gBAAgB,CAAC,OAAO,CAAC;;AAM9C,QAAA,IAAI,CAAA,IAAA,GAAG,KAAK;AAEpD;;;;;;AAMG;AACsB,QAAA,IAAS,CAAA,SAAA,GAAG,KAAK;AAK1C;;AAEG;AAC+B,QAAA,IAAI,CAAA,IAAA,GAAqD,QAAQ;;AAGjE,QAAA,IAAU,CAAA,UAAA,GAAG,KAAK;AAEpD;;AAEG;AAC+B,QAAA,IAAW,CAAA,WAAA,GAA+B,QAAQ;AAE5E,QAAA,IAAoB,CAAA,oBAAA,GAAG,KAAK;AAiFpC;;;AAGG;AACK,QAAA,IAAqB,CAAA,qBAAA,GAAG,MAAK;YACnC,MAAM,WAAW,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC;YAC/C,IAAI,WAAW,KAAK,IAAI;gBAAE;AAE1B,YAAA,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;AACd,gBAAA,IAAI,CAAC,IAAI,GAAG,IAAI;;AAEpB,SAAC;AAED;;;;AAIG;AACK,QAAA,IAAsB,CAAA,sBAAA,GAAG,MAAK;YACpC,MAAM,WAAW,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC;YAC/C,IAAI,WAAW,KAAK,IAAI;gBAAE;YAE1B,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,IAAI,EAAE;AAC/B,gBAAA,IAAI,CAAC,IAAI,GAAG,KAAK;;AAErB,SAAC;AAwCO,QAAA,IAAW,CAAA,WAAA,GAAG,MAAK;AACzB,YAAA,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE;AAE9B,YAAA,IAAI,IAAI,CAAC,SAAS,EAAE;AAClB,gBAAA,IAAI,CAAC,IAAI,GAAG,KAAK;;AAErB,SAAC;AA0DF;IA9LC,gBAAgB,CAAC,QAAiB,EAAE,QAAiB,EAAA;QACnD,IAAI,QAAQ,EAAE;AACZ,YAAA,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE;YACvB,IAAI,CAAC,eAAe,EAAE;;AACjB,aAAA,IAAI,QAAQ,KAAK,IAAI,EAAE;AAC5B,YAAA,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE;YACxB,IAAI,CAAC,gBAAgB,EAAE;;;IAInB,gBAAgB,GAAA;QACtB,MAAM,WAAW,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC;QAC/C,IAAI,WAAW,IAAI,OAAO,WAAW,CAAC,KAAK,KAAK,UAAU,EAAE;YAC1D,WAAW,CAAC,KAAK,EAAE;;;IAIvB,iBAAiB,GAAA;AACf,QAAA,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;YACd,MAAM,WAAW,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC;YAC/C,IAAI,WAAW,KAAK,IAAI,IAAI,WAAW,CAAC,MAAM,EAAE;AAC9C,gBAAA,IAAI,CAAC,IAAI,GAAG,IAAI;;;;IAKtB,gBAAgB,GAAA;QACd,IAAI,CAAC,yBAAyB,EAAE;AAEhC,QAAA,IAAI,IAAI,CAAC,IAAI,EAAE;YACb,IAAI,CAAC,eAAe,EAAE;;;IAI1B,oBAAoB,GAAA;AAClB,QAAA,IAAI,CAAC,oBAAoB,GAAG,KAAK;QACjC,IAAI,CAAC,+BAA+B,EAAE;;AAGxC;;AAEG;IACK,yBAAyB,GAAA;QAC/B,MAAM,WAAW,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC;AAC/C,QAAA,IAAI,WAAW,KAAK,IAAI,EAAE;YACxB,WAAW,CAAC,gBAAgB,CAAC,aAAa,EAAE,IAAI,CAAC,qBAAqB,CAAC;YACvE,WAAW,CAAC,gBAAgB,CAAC,cAAc,EAAE,IAAI,CAAC,sBAAsB,CAAC;;;AAI7E;;AAEG;IACK,+BAA+B,GAAA;QACrC,MAAM,WAAW,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC;AAC/C,QAAA,IAAI,WAAW,KAAK,IAAI,EAAE;YACxB,WAAW,CAAC,mBAAmB,CAAC,aAAa,EAAE,IAAI,CAAC,qBAAqB,CAAC;YAC1E,WAAW,CAAC,mBAAmB,CAAC,cAAc,EAAE,IAAI,CAAC,sBAAsB,CAAC;;;IA+BxE,eAAe,GAAA;QACrB,IAAI,IAAI,CAAC,oBAAoB;YAAE;QAE/B,MAAM,WAAW,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC;AAC/C,QAAA,IAAI,WAAW,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE;AACtC,YAAA,IAAI,CAAC,oBAAoB,GAAG,IAAI;YAEhC,OAAO,CAAC,OAAO;iBACZ,IAAI,CAAC,MAAK;AACT,gBAAA,IAAI;AACF,oBAAA,OAAO,WAAW,CAAC,IAAI,EAAE;;gBACzB,OAAO,KAAK,EAAE;AACd,oBAAA,OAAO,CAAC,IAAI,CAAC,oCAAoC,EAAE,KAAK,CAAC;AACzD,oBAAA,MAAM,KAAK;;AAEf,aAAC;iBACA,OAAO,CAAC,MAAK;AACZ,gBAAA,IAAI,CAAC,oBAAoB,GAAG,KAAK;AACnC,aAAC,CAAC;;;AAIR,IAAA,IAAY,OAAO,GAAA;AACjB,QAAA,OAAO,CAAG,EAAA,IAAI,CAAC,QAAQ,QAAQ;;AAGjC,IAAA,IAAY,SAAS,GAAA;AACnB,QAAA,OAAO,CAAG,EAAA,IAAI,CAAC,QAAQ,UAAU;;IAG3B,cAAc,GAAA;QACpB,OAAO;AACL,YAAA,UAAU,EAAE,IAAI;AAChB,YAAA,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI;YACjB,UAAU,EAAE,IAAI,CAAC,UAAU;SAC5B;;AAWH;;AAEG;IAEG,IAAI,GAAA;;AACR,YAAA,IAAI,CAAC,IAAI,GAAG,IAAI;YAEhB,IAAI,CAAC,eAAe,EAAE;AACxB,SAAC,CAAA;;AAED;;AAEG;IAEG,KAAK,GAAA;;AACT,YAAA,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;gBACnB;;AAGF,YAAA,IAAI,CAAC,IAAI,GAAG,KAAK;AACnB,SAAC,CAAA;;IAED,MAAM,GAAA;AACJ,QAAA,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;AACd,YAAA,OAAO,IAAI;;QAGb,QACEC,QAACC,UAAI,EAAA,IAAA,EACHD,OAAA,CAAA,KAAA,EAAA,EACE,KAAK,EAAE,IAAI,CAAC,cAAc,EAAE,EAC5B,IAAI,EAAC,QAAQ,EACF,YAAA,EAAA,MAAM,qBACA,IAAI,CAAC,OAAO,EACX,kBAAA,EAAA,IAAI,CAAC,SAAS,EAAA,EAEhCA,OAAK,CAAA,KAAA,EAAA,EAAA,KAAK,EAAC,iBAAiB,EAAA,EAC1BA,OAAK,CAAA,KAAA,EAAA,EAAA,KAAK,EAAC,aAAa,EAAC,EAAE,EAAE,IAAI,CAAC,OAAO,EAAA,EACvCA,OAAM,CAAA,MAAA,EAAA,EAAA,IAAI,EAAC,QAAQ,EAAA,EAAE,IAAI,CAAC,SAAS,CAAQ,CACvC,EACNA,OAAM,CAAA,MAAA,EAAA,EAAA,IAAI,EAAC,cAAc,EAAA,EACvBA,OAAA,CAAA,WAAA,EAAA,EAAW,KAAK,EAAC,OAAO,EAAC,KAAK,EAAC,QAAQ,EAAC,OAAO,EAAC,OAAO,gBAAY,QAAQ,EAAC,OAAO,EAAE,IAAI,CAAC,WAAW,EAAA,EACnGA,OAAA,CAAA,SAAA,EAAA,EAAA,WAAA,EAAmB,gBAAgB,EAAA,CAAW,CACpC,CACP,CACH,EACNA,OAAK,CAAA,KAAA,EAAA,EAAA,EAAE,EAAE,IAAI,CAAC,SAAS,EAAE,KAAK,EAAC,eAAe,EAAA,EAC5CA,OAAA,CAAA,MAAA,EAAA,IAAA,CAAa,CACT,EACNA,OAAK,CAAA,KAAA,EAAA,EAAA,KAAK,EAAE,CAAA,gBAAA,EAAmB,IAAI,CAAC,WAAW,KAAK,SAAS,GAAG,CAAmB,gBAAA,EAAA,IAAI,CAAC,WAAW,CAAA,CAAE,GAAG,EAAE,CAAE,CAAA,EAAA,EAC1GA,OAAM,CAAA,MAAA,EAAA,EAAA,IAAI,EAAC,QAAQ,EAAA,CAAQ,CACvB,CACF,CACD;;;;;;;;;;;;"}
@@ -89,6 +89,29 @@ const Scrim = class {
89
89
  this.previouslyFocusedElement = null;
90
90
  this.focusTimeoutId = null;
91
91
  this.restoreFocusTimeoutId = null;
92
+ // ======================================================================
93
+ // GERENCIAMENTO DE COMPONENTES FILHOS
94
+ // ======================================================================
95
+ /**
96
+ * Handler para evento brModalOpen emitido por modal filha
97
+ */
98
+ this.handleModalOpen = (event) => {
99
+ const modalElement = event.target;
100
+ if (!this.isDirectChild(modalElement))
101
+ return;
102
+ if (!this.isOpen) {
103
+ this.open();
104
+ }
105
+ };
106
+ /**
107
+ * Handler para evento brModalClose emitido por modal filha
108
+ */
109
+ this.handleModalClose = (event) => {
110
+ const modalElement = event.target;
111
+ if (!this.isDirectChild(modalElement))
112
+ return;
113
+ this.close();
114
+ };
92
115
  this.handleActivatorClick = () => {
93
116
  this.toggle();
94
117
  };
@@ -106,6 +129,10 @@ const Scrim = class {
106
129
  const reference = (_a = this.scrollOrigin) !== null && _a !== void 0 ? _a : this.lastScrollTop;
107
130
  if (Math.abs(currentScroll - reference) > this.scrollThreshold) {
108
131
  this.scrollOrigin = null;
132
+ // Não fecha se tiver modal filha com autoClose=false ou não definido
133
+ if (this.hasModalWithAutoClose()) {
134
+ return;
135
+ }
109
136
  this.isOpen = false;
110
137
  this.handleOpenChange(false);
111
138
  return;
@@ -141,7 +168,9 @@ const Scrim = class {
141
168
  }
142
169
  if (event.key === 'Escape' && !this.disableCloseOnClick) {
143
170
  event.preventDefault();
144
- this.isOpen = false;
171
+ if (!this.hasModalWithAutoClose()) {
172
+ this.isOpen = false;
173
+ }
145
174
  }
146
175
  };
147
176
  // Intercepta TODOS os eventos de clique globalmente quando scrim está ativo
@@ -175,11 +204,15 @@ const Scrim = class {
175
204
  }, 0);
176
205
  }
177
206
  };
178
- // ======================================================================
179
- // MANIPULAÇÃO DE EVENTOS E UTILITÁRIOS
180
- // ======================================================================
207
+ /**
208
+ * Handler para clique na máscara do scrim
209
+ * Fecha o scrim se disableCloseOnClick for false e não houver modal filha com autoClose=false
210
+ */
181
211
  this.handleMaskClick = (_event) => {
182
212
  if (!this.disableCloseOnClick) {
213
+ if (this.hasModalWithAutoClose()) {
214
+ return;
215
+ }
183
216
  this.close();
184
217
  }
185
218
  };
@@ -188,37 +221,39 @@ const Scrim = class {
188
221
  // LIFECYCLE HOOKS E WATCHERS
189
222
  // ======================================================================
190
223
  handleOpenChange(newValue) {
191
- // Cancelar qualquer timeout anterior
192
- if (this.focusTimeoutId !== null) {
193
- clearTimeout(this.focusTimeoutId);
194
- this.focusTimeoutId = null;
195
- }
196
- if (this.restoreFocusTimeoutId !== null) {
197
- clearTimeout(this.restoreFocusTimeoutId);
198
- this.restoreFocusTimeoutId = null;
199
- }
200
- this.isActive = newValue;
201
- if (newValue && this.scrollStrategy === 'close') {
202
- const currentScroll = window.scrollY;
203
- this.lastScrollTop = currentScroll;
204
- this.scrollOrigin = currentScroll;
205
- }
206
- this.updateStyles();
207
- if (this.isActive) {
208
- this.previouslyFocusedElement = document.activeElement;
209
- this.applyScrollStrategy();
210
- this.addGlobalEventInterception();
211
- this.focusTimeoutId = setTimeout(() => {
212
- this.focusFirstElement();
213
- }, 100);
214
- this.brScrimOpen.emit();
215
- }
216
- else {
217
- this.resetScrolling();
218
- this.removeGlobalEventInterception();
219
- this.restoreFocus();
220
- this.brScrimClose.emit();
221
- }
224
+ return tslib_es6.__awaiter(this, void 0, void 0, function* () {
225
+ // Cancelar qualquer timeout anterior
226
+ if (this.focusTimeoutId !== null) {
227
+ clearTimeout(this.focusTimeoutId);
228
+ this.focusTimeoutId = null;
229
+ }
230
+ if (this.restoreFocusTimeoutId !== null) {
231
+ clearTimeout(this.restoreFocusTimeoutId);
232
+ this.restoreFocusTimeoutId = null;
233
+ }
234
+ this.isActive = newValue;
235
+ if (newValue && this.scrollStrategy === 'close') {
236
+ const currentScroll = window.scrollY;
237
+ this.lastScrollTop = currentScroll;
238
+ this.scrollOrigin = currentScroll;
239
+ }
240
+ this.updateStyles();
241
+ if (this.isActive) {
242
+ this.previouslyFocusedElement = document.activeElement;
243
+ this.applyScrollStrategy();
244
+ this.addGlobalEventInterception();
245
+ this.focusTimeoutId = setTimeout(() => {
246
+ this.focusFirstElement();
247
+ }, 100);
248
+ this.brScrimOpen.emit();
249
+ }
250
+ else {
251
+ this.resetScrolling();
252
+ this.removeGlobalEventInterception();
253
+ this.restoreFocus();
254
+ this.brScrimClose.emit();
255
+ }
256
+ });
222
257
  }
223
258
  updateStyles() {
224
259
  if (this.zIndex !== null && this.zIndex !== undefined) {
@@ -245,6 +280,7 @@ const Scrim = class {
245
280
  this.setupActivator();
246
281
  this.setupActivatorSlotClick();
247
282
  this.addContentEventListener();
283
+ this.listenToModalEvents();
248
284
  if (this.isActive) {
249
285
  this.applyScrollStrategy();
250
286
  this.addGlobalEventInterception();
@@ -278,7 +314,6 @@ const Scrim = class {
278
314
  clearTimeout(this.restoreFocusTimeoutId);
279
315
  this.restoreFocusTimeoutId = null;
280
316
  }
281
- // Remover event listeners
282
317
  window.removeEventListener('scroll', this.handleScrollClose);
283
318
  window.removeEventListener('scroll', this.handleBlockScroll);
284
319
  if (this.contentRef !== null) {
@@ -287,6 +322,58 @@ const Scrim = class {
287
322
  this.removeActivatorClickListener();
288
323
  this.cleanupActivatorSlotClick();
289
324
  this.removeGlobalEventInterception();
325
+ this.removeModalEventListener();
326
+ }
327
+ /**
328
+ * Verifica se um elemento é filho direto deste scrim (não nested)
329
+ */
330
+ isDirectChild(element) {
331
+ const children = this.getDirectChildren();
332
+ return children.some((child) => child === element || child.contains(element));
333
+ }
334
+ /**
335
+ * Adiciona listeners para eventos brModalOpen e brModalClose das modais filhas
336
+ */
337
+ listenToModalEvents() {
338
+ this.el.addEventListener('brModalOpen', this.handleModalOpen);
339
+ this.el.addEventListener('brModalClose', this.handleModalClose);
340
+ }
341
+ /**
342
+ * Remove listeners dos eventos da modal
343
+ */
344
+ removeModalEventListener() {
345
+ this.el.removeEventListener('brModalOpen', this.handleModalOpen);
346
+ this.el.removeEventListener('brModalClose', this.handleModalClose);
347
+ }
348
+ /**
349
+ * Retorna os elementos filhos diretos do scrim via slot padrão
350
+ */
351
+ getDirectChildren() {
352
+ const shadowRoot = this.el.shadowRoot;
353
+ if (shadowRoot === null)
354
+ return [];
355
+ const slot = shadowRoot.querySelector('slot:not([name])');
356
+ if (slot === null)
357
+ return [];
358
+ return slot.assignedElements();
359
+ }
360
+ /**
361
+ * Busca uma modal filha direta do scrim
362
+ */
363
+ findModalChild() {
364
+ var _a;
365
+ const children = this.getDirectChildren();
366
+ const modalElement = children.find((child) => child.tagName === 'BR-MODAL');
367
+ return (_a = modalElement) !== null && _a !== void 0 ? _a : null;
368
+ }
369
+ /**
370
+ * Verifica se há uma modal filha com autoClose=false (padrão ou explícito)
371
+ * Retorna true se:
372
+ * - Existe modal filha E autoClose não é explicitamente true
373
+ */
374
+ hasModalWithAutoClose() {
375
+ const modal = this.findModalChild();
376
+ return modal !== null && modal.autoClose !== true;
290
377
  }
291
378
  // ======================================================================
292
379
  // GERENCIAMENTO DO ACTIVATOR (ELEMENTO ACIONADOR)
@@ -475,7 +562,11 @@ const Scrim = class {
475
562
  return elements.filter((el) => el.offsetWidth > 0 && el.offsetHeight > 0 && getComputedStyle(el).visibility !== 'hidden');
476
563
  }
477
564
  shouldHandleEscape(event) {
478
- return (event.key === 'Escape' || event.key === 'Esc') && this.isActive && !this.disableCloseOnClick;
565
+ if ((event.key === 'Escape' || event.key === 'Esc') && this.isActive && !this.disableCloseOnClick) {
566
+ // Não fecha se tiver modal filha com autoClose=false ou não definido
567
+ return !this.hasModalWithAutoClose();
568
+ }
569
+ return false;
479
570
  }
480
571
  handleTabNavigation(event) {
481
572
  const focusableElements = this.getFocusableElements();
@@ -536,6 +627,9 @@ const Scrim = class {
536
627
  document.removeEventListener('focus', this.handleGlobalFocus, true);
537
628
  document.removeEventListener('focusin', this.handleGlobalFocus, true);
538
629
  }
630
+ // ======================================================================
631
+ // UTILITÁRIOS
632
+ // ======================================================================
539
633
  getCssClassMap() {
540
634
  return {
541
635
  'br-scrim': true,
@@ -586,7 +680,7 @@ const Scrim = class {
586
680
  });
587
681
  }
588
682
  render() {
589
- return (index.h(index.Host, { key: '1aea7418642867cfb24c099729f34412f9aec7bf' }, index.h("slot", { key: '4468892291450f13cded3627ee91f31716108443', name: "activator" }), index.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' }, index.h("div", { key: '6c6df83177f1a14097ec5c08e409caaca3953d3b', class: "mask", onClick: this.handleMaskClick }), index.h("div", { key: '1af0ecd53a0aaf630069139a7e6935533a563e10', ref: (el) => (this.contentRef = el), id: `${this.customId}-content`, class: "content", tabIndex: -1, onKeyDown: this.handleKeyDown }, index.h("slot", { key: '2cb75f5b254ed22bbe821998700d9c1f4152dd5b' })))));
683
+ return (index.h(index.Host, { key: '249de7af4056263464615cbe086b419f74b8981b' }, index.h("slot", { key: '1698faa6b492e1ec594eba8425f20582a2af0e4a', name: "activator" }), index.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' }, index.h("div", { key: 'ef7408a6672fabf4d2f79bc7922f301fd102652e', class: "mask", onClick: this.handleMaskClick }), index.h("div", { key: '91ffb1a84478f09fc90cefbb97180c5db13dba5c', ref: (el) => (this.contentRef = el), id: `${this.customId}-content`, class: "content", tabIndex: -1, onKeyDown: this.handleKeyDown }, index.h("slot", { key: '0600ac804980446103154cebf83389ac92e44d9d' })))));
590
684
  }
591
685
  static get formAssociated() { return true; }
592
686
  get el() { return index.getElement(this); }