@muibook/components 14.0.1 → 15.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,9 +5,15 @@ import "../mui-stack/hstack/index.js";
5
5
  import "../mui-button/index.js";
6
6
  import "../mui-icons/warning/index.js";
7
7
  import "../mui-dialog/index.js";
8
- class x extends HTMLElement {
8
+ import "../mui-select/index.js";
9
+ class R extends HTMLElement {
9
10
  constructor() {
10
- super(), this.defaultSlot = null, this.headerSlot = null, this.headerAfterSlot = null, this.headerDescriptionSlot = null, this.footerSlot = null, this.footerAfterSlot = null, this.footerDescriptionSlot = null, this.notesSlot = null, this.imageSlot = null, this.surfaceEl = null, this.pointerStartX = null, this.pointerStartY = null, this.onSlotChange = () => this.syncSections(), this.onChromeSlotChange = () => this.syncChromeState(), this.onSurfaceClick = (e) => this.handleSurfaceClick(e), this.onPointerDown = (e) => this.handlePointerDown(e), this.onPointerUp = (e) => this.handlePointerUp(e), this.onKeyDown = (e) => this.handleArrowNavigation(e), this.onDocumentKeyDown = (e) => {
11
+ super(), this.defaultSlot = null, this.headerSlot = null, this.headerAfterSlot = null, this.headerDescriptionSlot = null, this.footerSlot = null, this.footerAfterSlot = null, this.footerDescriptionSlot = null, this.notesSlot = null, this.imageSlot = null, this.stageEl = null, this.surfaceEl = null, this.nativeFullscreenActive = !1, this.pointerStartX = null, this.pointerStartY = null, this.onSlotChange = () => this.syncSections(), this.onChromeSlotChange = () => this.syncChromeState(), this.onSurfaceClick = (e) => this.handleSurfaceClick(e), this.onPointerDown = (e) => this.handlePointerDown(e), this.onPointerUp = (e) => this.handlePointerUp(e), this.onKeyDown = (e) => this.handleArrowNavigation(e), this.onFullscreenChange = () => this.handleFullscreenChange(), this.onFullscreenError = () => this.handleFullscreenError(), this.onWindowResize = () => this.updateFullscreenSurfaceFit(), this.onDocumentKeyDown = (e) => {
12
+ const t = document.fullscreenElement === this;
13
+ if (e.key === "Escape" && this.hasAttribute("present") && !t) {
14
+ e.preventDefault(), this.resetPresentationState();
15
+ return;
16
+ }
11
17
  this.shouldHandleGlobalKeys(e) && (this.isEditableTarget(e.target) || this.handleArrowNavigation(e));
12
18
  }, this.attachShadow({ mode: "open" });
13
19
  }
@@ -24,22 +30,50 @@ class x extends HTMLElement {
24
30
  "radius",
25
31
  "title",
26
32
  "footer-text",
33
+ "hide-header",
34
+ "hide-footer",
27
35
  "hide-counter",
28
36
  "preview",
29
37
  "lightbox",
30
- "scroll"
38
+ "scroll",
39
+ "fullscreen"
31
40
  ];
32
41
  }
33
42
  connectedCallback() {
34
- this.hasAttribute("ratio") || this.setAttribute("ratio", "16:9"), this.hasAttribute("padding") || this.setAttribute("padding", "medium"), this.hasAttribute("active-section") || this.setAttribute("active-section", "0"), this.hasAttribute("variant") || this.setAttribute("variant", "default"), this.hasAttribute("radius") || this.setAttribute("radius", "default"), this.render(), this.syncSections(), this.syncChromeState(), this.addEventListener("keydown", this.onKeyDown), document.addEventListener("keydown", this.onDocumentKeyDown);
43
+ this.hasAttribute("ratio") || this.setAttribute("ratio", "16:9"), this.hasAttribute("padding") || this.setAttribute("padding", "medium"), this.hasAttribute("active-section") || this.setAttribute("active-section", "0"), this.hasAttribute("variant") || this.setAttribute("variant", "default"), this.hasAttribute("radius") || this.setAttribute("radius", "default"), this.render(), this.syncSections(), this.syncChromeState(), this.addEventListener("keydown", this.onKeyDown), document.addEventListener("keydown", this.onDocumentKeyDown), document.addEventListener("fullscreenchange", this.onFullscreenChange), document.addEventListener("fullscreenerror", this.onFullscreenError), window.addEventListener("resize", this.onWindowResize);
35
44
  }
36
45
  disconnectedCallback() {
37
- var e, t, i, o, s, r, a, l, h, d, n, c;
38
- (e = this.defaultSlot) == null || e.removeEventListener("slotchange", this.onSlotChange), (t = this.headerSlot) == null || t.removeEventListener("slotchange", this.onChromeSlotChange), (i = this.headerAfterSlot) == null || i.removeEventListener("slotchange", this.onChromeSlotChange), (o = this.headerDescriptionSlot) == null || o.removeEventListener("slotchange", this.onChromeSlotChange), (s = this.footerSlot) == null || s.removeEventListener("slotchange", this.onChromeSlotChange), (r = this.footerAfterSlot) == null || r.removeEventListener("slotchange", this.onChromeSlotChange), (a = this.footerDescriptionSlot) == null || a.removeEventListener("slotchange", this.onChromeSlotChange), (l = this.notesSlot) == null || l.removeEventListener("slotchange", this.onChromeSlotChange), (h = this.imageSlot) == null || h.removeEventListener("slotchange", this.onChromeSlotChange), (d = this.surfaceEl) == null || d.removeEventListener("click", this.onSurfaceClick), (n = this.surfaceEl) == null || n.removeEventListener("pointerdown", this.onPointerDown), (c = this.surfaceEl) == null || c.removeEventListener("pointerup", this.onPointerUp), this.removeEventListener("keydown", this.onKeyDown), document.removeEventListener("keydown", this.onDocumentKeyDown);
46
+ var e, t, i, s, r, o, n, h, b, m, f, d;
47
+ (e = this.defaultSlot) == null || e.removeEventListener("slotchange", this.onSlotChange), (t = this.headerSlot) == null || t.removeEventListener("slotchange", this.onChromeSlotChange), (i = this.headerAfterSlot) == null || i.removeEventListener("slotchange", this.onChromeSlotChange), (s = this.headerDescriptionSlot) == null || s.removeEventListener("slotchange", this.onChromeSlotChange), (r = this.footerSlot) == null || r.removeEventListener("slotchange", this.onChromeSlotChange), (o = this.footerAfterSlot) == null || o.removeEventListener("slotchange", this.onChromeSlotChange), (n = this.footerDescriptionSlot) == null || n.removeEventListener("slotchange", this.onChromeSlotChange), (h = this.notesSlot) == null || h.removeEventListener("slotchange", this.onChromeSlotChange), (b = this.imageSlot) == null || b.removeEventListener("slotchange", this.onChromeSlotChange), (m = this.surfaceEl) == null || m.removeEventListener("click", this.onSurfaceClick), (f = this.surfaceEl) == null || f.removeEventListener("pointerdown", this.onPointerDown), (d = this.surfaceEl) == null || d.removeEventListener("pointerup", this.onPointerUp), this.removeEventListener("keydown", this.onKeyDown), document.removeEventListener("keydown", this.onDocumentKeyDown), document.removeEventListener("fullscreenchange", this.onFullscreenChange), document.removeEventListener("fullscreenerror", this.onFullscreenError), window.removeEventListener("resize", this.onWindowResize);
39
48
  }
40
49
  attributeChangedCallback(e, t, i) {
41
50
  t !== i && (this.render(), this.syncSections(), this.syncChromeState());
42
51
  }
52
+ async enterFullscreen() {
53
+ if (document.fullscreenElement === this) return !0;
54
+ const e = this;
55
+ if (typeof e.requestFullscreen != "function") return !0;
56
+ try {
57
+ return await e.requestFullscreen(), !0;
58
+ } catch {
59
+ return this.dispatchEvent(new CustomEvent("fullscreen-error", { bubbles: !0, composed: !0 })), !0;
60
+ }
61
+ }
62
+ async exitFullscreen() {
63
+ if (document.fullscreenElement === this && typeof document.exitFullscreen == "function")
64
+ try {
65
+ await document.exitFullscreen();
66
+ } catch {
67
+ this.dispatchEvent(new CustomEvent("fullscreen-error", { bubbles: !0, composed: !0 }));
68
+ }
69
+ return !0;
70
+ }
71
+ async toggleFullscreen(e) {
72
+ return (typeof e == "boolean" ? e : !this.hasAttribute("fullscreen")) ? this.enterFullscreen() : this.exitFullscreen();
73
+ }
74
+ resetPresentationState() {
75
+ this.nativeFullscreenActive = !1, this.removeAttribute("present"), this.removeAttribute("fullscreen"), this.syncChromeState();
76
+ }
43
77
  getSections() {
44
78
  var t;
45
79
  return (((t = this.defaultSlot) == null ? void 0 : t.assignedElements({ flatten: !0 })) || []).filter((i) => !["header", "footer"].includes(i.getAttribute("slot") || ""));
@@ -78,10 +112,10 @@ class x extends HTMLElement {
78
112
  addSection(e) {
79
113
  const t = document.createElement("div");
80
114
  t.setAttribute("data-slide-section", ""), typeof e == "string" ? t.textContent = e : e instanceof HTMLElement && t.appendChild(e), this.appendChild(t);
81
- const i = this.getSections(), o = Math.max(0, i.length - 1);
82
- this.setActiveSectionIndex(o), this.syncSections(), this.dispatchEvent(
115
+ const i = this.getSections(), s = Math.max(0, i.length - 1);
116
+ this.setActiveSectionIndex(s), this.syncSections(), this.dispatchEvent(
83
117
  new CustomEvent("section-add", {
84
- detail: { index: o, total: i.length },
118
+ detail: { index: s, total: i.length },
85
119
  bubbles: !0,
86
120
  composed: !0
87
121
  })
@@ -100,24 +134,42 @@ class x extends HTMLElement {
100
134
  resolveRatio() {
101
135
  const e = (this.getAttribute("ratio") || "16:9").trim();
102
136
  if (e === "custom") {
103
- const i = parseFloat(this.getAttribute("ratio-width") || "16"), o = parseFloat(this.getAttribute("ratio-height") || "9");
104
- return i > 0 && o > 0 ? `${i} / ${o}` : "16 / 9";
137
+ const i = parseFloat(this.getAttribute("ratio-width") || "16"), s = parseFloat(this.getAttribute("ratio-height") || "9");
138
+ return i > 0 && s > 0 ? `${i} / ${s}` : "16 / 9";
105
139
  }
106
140
  const t = e.split(":");
107
141
  if (t.length === 2) {
108
- const i = parseFloat(t[0]), o = parseFloat(t[1]);
109
- if (i > 0 && o > 0) return `${i} / ${o}`;
142
+ const i = parseFloat(t[0]), s = parseFloat(t[1]);
143
+ if (i > 0 && s > 0) return `${i} / ${s}`;
110
144
  }
111
145
  return "16 / 9";
112
146
  }
147
+ resolveRatioParts() {
148
+ const e = (this.getAttribute("ratio") || "16:9").trim();
149
+ if (e === "custom") {
150
+ const i = parseFloat(this.getAttribute("ratio-width") || "16"), s = parseFloat(this.getAttribute("ratio-height") || "9");
151
+ return i > 0 && s > 0 ? { width: i, height: s } : { width: 16, height: 9 };
152
+ }
153
+ const t = e.split(":");
154
+ if (t.length === 2) {
155
+ const i = parseFloat(t[0]), s = parseFloat(t[1]);
156
+ if (i > 0 && s > 0) return { width: i, height: s };
157
+ }
158
+ return { width: 16, height: 9 };
159
+ }
113
160
  syncSections() {
114
161
  if (!this.shadowRoot) return;
115
162
  const e = this.getSections(), t = this.getActiveSectionIndex(), i = this.hasAttribute("present") || e.length > 1;
116
- e.forEach((o, s) => {
117
- o.setAttribute("data-slide-section", ""), s === t ? (o.removeAttribute("slide-hidden"), o.setAttribute("slide-active", "")) : (o.removeAttribute("slide-active"), i ? o.setAttribute("slide-hidden", "") : o.removeAttribute("slide-hidden"));
118
- }), this.style.setProperty("--slide-frame-ratio", this.resolveRatio());
163
+ e.forEach((s, r) => {
164
+ s.setAttribute("data-slide-section", ""), r === t ? (s.removeAttribute("slide-hidden"), s.setAttribute("slide-active", "")) : (s.removeAttribute("slide-active"), i ? s.setAttribute("slide-hidden", "") : s.removeAttribute("slide-hidden"));
165
+ }), this.style.setProperty("--slide-frame-ratio", this.resolveRatio()), this.updateFullscreenSurfaceFit();
119
166
  }
120
167
  handleArrowNavigation(e) {
168
+ const t = document.fullscreenElement === this;
169
+ if (e.key === "Escape" && this.hasAttribute("present") && !t) {
170
+ e.preventDefault(), this.resetPresentationState();
171
+ return;
172
+ }
121
173
  if (!(this.getSections().length < 2) && !e.defaultPrevented) {
122
174
  if (e.key === "ArrowRight" || e.key === "ArrowDown") {
123
175
  e.preventDefault(), this.nextSection();
@@ -136,9 +188,9 @@ class x extends HTMLElement {
136
188
  return !!(i && this.contains(i));
137
189
  }
138
190
  render() {
139
- var s, r, a, l, h, d, n, c, g, u, m, f, v, p, b, S, w, y;
191
+ var r, o, n, h, b, m, f, d, c, S, w, y, u, g, a, l, p, x, E, A;
140
192
  if (!this.shadowRoot) return;
141
- const e = (this.getAttribute("title") || "").trim(), t = (this.getAttribute("footer-text") || "").trim(), i = this.escapeHtml(e), o = this.escapeHtml(t);
193
+ const e = (this.getAttribute("title") || "").trim(), t = (this.getAttribute("footer-text") || "").trim(), i = this.escapeHtml(e), s = this.escapeHtml(t);
142
194
  this.shadowRoot.innerHTML = /*html*/
143
195
  `
144
196
  <style>
@@ -146,70 +198,149 @@ class x extends HTMLElement {
146
198
  display: block;
147
199
  width: 100%;
148
200
  --slide-frame-ratio: 16 / 9;
149
- --slide-frame-padding-active: var(--slide-frame-padding-medium);
150
201
  --slide-frame-leading-offset: var(--space-025);
151
- --slide-frame-border-active: var(--border-thin);
152
- --slide-frame-border-color-active: var(--slide-frame-border-color);
153
- --slide-frame-background-active: var(--slide-frame-background);
154
- --slide-frame-shadow-active: var(--slide-frame-shadow);
155
- --slide-frame-radius-active: var(--slide-frame-radius);
156
- }
157
- :host([variant="plain"]) {
158
- --slide-frame-border-active: none;
159
- --slide-frame-border-color-active: transparent;
160
- --slide-frame-background-active: transparent;
161
- --slide-frame-shadow-active: none;
162
- }
163
- :host([variant="ghost"]) {
164
- --slide-frame-border-active: none;
165
- --slide-frame-border-color-active: transparent;
166
- --slide-frame-background-active: var(--slide-frame-background-ghost);
167
- --slide-frame-shadow-active: none;
168
- }
169
- :host([radius="none"]) { --slide-frame-radius-active: 0; }
170
- :host([radius="small"]) { --slide-frame-radius-active: var(--slide-frame-radius-small); }
171
- :host([radius="medium"]) { --slide-frame-radius-active: var(--slide-frame-radius-medium); }
172
- :host([radius="large"]) { --slide-frame-radius-active: var(--slide-frame-radius-large); }
202
+ --slide-frame-surface-padding-active: var(--slide-frame-padding-medium);
203
+ --slide-frame-header-padding-inline: var(--slide-frame-surface-padding-active);
204
+ --slide-frame-header-padding-block: var(--slide-frame-surface-padding-active);
205
+ --slide-frame-header-padding-top: var(--slide-frame-header-padding-block);
206
+ --slide-frame-header-padding-bottom: 0;
207
+ --slide-frame-footer-padding-inline: var(--slide-frame-surface-padding-active);
208
+ --slide-frame-footer-padding-block: var(--slide-frame-surface-padding-active);
209
+ --slide-frame-footer-padding-top: 0;
210
+ --slide-frame-footer-padding-bottom: var(--space-200);
211
+ }
212
+ :host([padding="none"]) { --slide-frame-surface-padding-active: 0; }
213
+ :host([padding="small"]) { --slide-frame-surface-padding-active: var(--slide-frame-padding-small); }
214
+ :host([padding="medium"]),
215
+ :host(:not([padding])) { --slide-frame-surface-padding-active: var(--slide-frame-padding-medium); }
216
+ :host([padding="large"]) { --slide-frame-surface-padding-active: var(--slide-frame-padding-large); }
217
+ :host([fullscreen]) {
218
+ position: fixed;
219
+ inset: 0;
220
+ width: 100vw;
221
+ height: 100dvh;
222
+ z-index: var(--slide-frame-fullscreen-z-index, 1000);
223
+ }
224
+ :host([padding="none"]) .surface { padding: 0; }
225
+ :host([padding="small"]) .surface { padding: var(--slide-frame-padding-small); }
226
+ :host([padding="large"]) .surface { padding: var(--slide-frame-padding-large); }
227
+ :host([padding="medium"]) .surface,
228
+ :host(:not([padding])) .surface { padding: var(--slide-frame-padding-medium); }
229
+
230
+ :host([variant="plain"]) .stage {
231
+ border: none;
232
+ border-color: transparent;
233
+ background: transparent;
234
+ box-shadow: none;
235
+ }
236
+ :host([variant="ghost"]) .stage {
237
+ border: none;
238
+ border-color: transparent;
239
+ background: var(--slide-frame-background-ghost);
240
+ box-shadow: none;
241
+ }
242
+ :host([radius="none"]) .stage { border-radius: 0; }
243
+ :host([radius="small"]) .stage { border-radius: var(--slide-frame-radius-small); }
244
+ :host([radius="medium"]) .stage { border-radius: var(--slide-frame-radius-medium); }
245
+ :host([radius="large"]) .stage { border-radius: var(--slide-frame-radius-large); }
173
246
 
174
247
  .frame {
175
248
  display: grid;
176
249
  width: 100%;
250
+ height: 100%;
177
251
  gap: 0;
178
252
  padding: var(--space-400);
179
- background: var(--surface-recessed-200);
253
+ background: var(--surface-recessed-100);
180
254
  box-sizing: border-box;
181
255
  }
256
+ :host([fullscreen]) .frame {
257
+ width: 100%;
258
+ min-height: 100%;
259
+ grid-template-rows: auto minmax(0, 1fr) auto;
260
+ overflow-y: auto;
261
+ overflow-x: hidden;
262
+ padding: 0;
263
+ }
264
+ :host(:fullscreen) .frame {
265
+ padding: 0;
266
+ }
182
267
  :host([has-chrome]) .frame {
183
268
  gap: var(--slide-frame-gap, var(--space-300));
184
269
  }
185
270
 
186
- .surface {
271
+ .stage {
187
272
  position: relative;
188
273
  width: 100%;
274
+ height: 100%;
189
275
  aspect-ratio: var(--slide-frame-ratio);
190
- border: var(--slide-frame-border-active);
191
- border-color: var(--slide-frame-border-color-active);
192
- border-radius: var(--slide-frame-radius-active);
193
- background: var(--slide-frame-background-active);
194
- box-shadow: var(--slide-frame-shadow-active);
276
+ border: var(--border-thin);
277
+ border-color: var(--slide-frame-border-color);
278
+ border-radius: var(--slide-frame-radius);
279
+ background: var(--slide-frame-background);
280
+ box-shadow: var(--slide-frame-shadow);
281
+ box-sizing: border-box;
282
+ overflow: hidden;
283
+ display: grid;
284
+ grid-template-rows: auto minmax(0, 1fr) auto;
285
+ }
286
+ :host([fullscreen]) .stage,
287
+ :host([present]) .stage {
288
+ justify-self: center;
289
+ align-self: center;
290
+ height: 100%;
291
+ max-height: 100%;
292
+ width: auto;
293
+ max-width: 100%;
294
+ }
295
+ :host([fullscreen]) .stage,
296
+ :host(:fullscreen) .stage {
297
+ border: none;
298
+ border-radius: 0;
299
+ }
300
+ .surface {
301
+ position: relative;
302
+ width: 100%;
303
+ min-width: 0;
304
+ min-height: 0;
195
305
  box-sizing: border-box;
196
- padding: var(--slide-frame-padding-active);
197
306
  overflow: hidden;
198
307
  display: block;
199
308
  }
200
309
  :host([scroll]) .surface {
201
310
  overflow: auto;
202
311
  }
203
- :host([preview]) .surface {
312
+ :host([fullscreen]) .surface,
313
+ :host([present]) .surface {
314
+ overflow: auto !important;
315
+ }
316
+ :host([preview]) .stage {
204
317
  border-color: var(--slide-frame-preview-border-color, var(--text-color-warning));
318
+ }
319
+ :host([preview]:not([variant="plain"]):not([variant="ghost"])) .stage {
205
320
  box-shadow:
206
- var(--slide-frame-shadow-active),
321
+ var(--slide-frame-shadow),
207
322
  0 0 0 var(--stroke-size-100) color-mix(in srgb, var(--slide-frame-preview-border-color, var(--text-color-warning)) 45%, transparent);
208
323
  }
324
+ :host([preview][variant="plain"]) .stage,
325
+ :host([preview][variant="ghost"]) .stage {
326
+ box-shadow: 0 0 0 var(--stroke-size-100) color-mix(in srgb, var(--slide-frame-preview-border-color, var(--text-color-warning)) 45%, transparent);
327
+ }
209
328
  .header,
210
329
  .footer {
211
330
  display: block;
212
331
  }
332
+ .header {
333
+ padding:
334
+ var(--slide-frame-header-padding-top)
335
+ var(--slide-frame-header-padding-inline)
336
+ var(--slide-frame-header-padding-bottom);
337
+ }
338
+ .footer {
339
+ padding:
340
+ var(--slide-frame-footer-padding-top)
341
+ var(--slide-frame-footer-padding-inline)
342
+ var(--slide-frame-footer-padding-bottom);
343
+ }
213
344
  .leading {
214
345
  margin-inline: var(--slide-frame-leading-offset);
215
346
  }
@@ -249,6 +380,15 @@ class x extends HTMLElement {
249
380
  .footer-counter {
250
381
  white-space: nowrap;
251
382
  }
383
+ .footer-counter .counter-value {
384
+ display: inline-block;
385
+ min-width: calc(var(--slide-frame-counter-digits, 1) * 1ch);
386
+ text-align: right;
387
+ }
388
+ .footer-counter::part(text) {
389
+ font-variant-numeric: tabular-nums;
390
+ font-feature-settings: "tnum" 1;
391
+ }
252
392
  .notes {
253
393
  display: none;
254
394
  }
@@ -259,8 +399,8 @@ class x extends HTMLElement {
259
399
  border-radius: var(--radius-200);
260
400
 
261
401
  }
262
- :host([present]) .surface {
263
- background: var(--slide-frame-background-present, var(--slide-frame-background-active));
402
+ :host([present]) .stage {
403
+ background: var(--slide-frame-background-present, var(--slide-frame-background));
264
404
  }
265
405
  .lightbox-image {
266
406
  display: block;
@@ -272,14 +412,13 @@ class x extends HTMLElement {
272
412
 
273
413
  .present-controls {
274
414
  display: grid;
275
- padding-bottom: var(--space-100);
276
- border-bottom: var(--border-thin);
277
415
  }
278
- :host([present]) .present-controls {
279
- display: none;
416
+ :host([fullscreen]) .present-controls,
417
+ :host(:fullscreen) .present-controls {
418
+ display: none !important;
280
419
  }
281
- :host(:not([present])) #slideFrameTogglePresentBtn {
282
- /* optional: style to indicate inactive state */
420
+ :host(:not([fullscreen])) #slideFrameExitPresentBtn {
421
+ display: none !important;
283
422
  }
284
423
 
285
424
  ::slotted([data-slide-section][slide-hidden]) {
@@ -291,9 +430,10 @@ class x extends HTMLElement {
291
430
  <mui-h-stack space="var(--space-050)" aligny="center">
292
431
  <mui-button id="slideFrameAddSectionBtn" variant="tertiary" size="x-small">Add Section</mui-button>
293
432
  <mui-rule direction="vertical" length="var(--space-300)"></mui-rule>
294
- <mui-button id="slideFrameTogglePresentBtn" variant="tertiary" size="x-small">Present Mode</mui-button>
433
+ <mui-button id="slideFrameToggleFullscreenBtn" variant="tertiary" size="x-small">Full Screen</mui-button>
295
434
  <mui-rule direction="vertical" length="var(--space-300)"></mui-rule>
296
435
  <mui-button id="slideFrameToggleNotesBtn" variant="tertiary" size="x-small">Notes</mui-button>
436
+ <mui-rule direction="vertical" length="var(--space-300)"></mui-rule>
297
437
  </mui-h-stack>
298
438
  <mui-h-stack space="var(--space-050)" aligny="center">
299
439
  <mui-button id="slideFramePrevSectionBtn" variant="tertiary" size="x-small"><mui-icon-left-chevron slot="before"></mui-icon-left-chevron>Previous</mui-button>
@@ -301,77 +441,109 @@ class x extends HTMLElement {
301
441
  <mui-button id="slideFrameNextSectionBtn" variant="tertiary" size="x-small">Next<mui-icon-right-chevron slot="after"></mui-icon-right-chevron></mui-button>
302
442
  </mui-h-stack>
303
443
  </mui-grid>
304
- <div class="header" id="headerRegion">
305
- <mui-v-stack class="leading leading_top" space="var(--space-100)" alignx="stretch" aligny="center">
306
- <mui-h-stack class="header-main" alignx="space-between" aligny="center" space="var(--space-300)">
307
- <div class="header-leading">
308
- <mui-heading class="header-title" size="4" level="4" id="headerTitle"${i ? "" : " hidden"}>${i}</mui-heading>
309
- <slot name="header"></slot>
310
- </div>
311
- <mui-h-stack class="header-after" alignx="end" aligny="center" space="var(--space-200)">
312
- <slot name="header-after"></slot>
444
+ <div class="stage">
445
+ <div class="header" id="headerRegion">
446
+ <mui-v-stack class="leading leading_top" space="var(--space-100)" alignx="stretch" aligny="center">
447
+ <mui-h-stack class="header-main" alignx="space-between" aligny="center" space="var(--space-300)">
448
+ <div class="header-leading">
449
+ <mui-heading class="header-title" size="4" level="4" id="headerTitle"${i ? "" : " hidden"}>${i}</mui-heading>
450
+ <slot name="header"></slot>
451
+ </div>
452
+ <mui-h-stack class="header-after" alignx="end" aligny="center" space="var(--space-200)">
453
+ <slot name="header-after"></slot>
454
+ </mui-h-stack>
313
455
  </mui-h-stack>
314
- </mui-h-stack>
315
- <mui-h-stack class="header-description" alignx="start" aligny="start" space="var(--space-200)">
316
- <slot name="header-description"></slot>
317
- </mui-h-stack>
318
- </mui-v-stack>
319
- </div>
320
- <div class="surface" tabindex="0" role="region" aria-label="Slide frame">
321
- <slot name="image"></slot>
322
- <slot></slot>
323
- </div>
324
- <div class="notes"><mui-body variant="optional" size="x-small">Notes...</mui-body><slot name="notes"></slot></div>
325
- <div class="footer" id="footerRegion">
326
- <mui-v-stack class="leading leading_bottom" space="var(--space-400)">
327
- <mui-h-stack class="footer-main" alignx="space-between" aligny="center" space="var(--space-300)">
328
- <div class="footer-leading">
329
- <mui-body class="footer-copy" size="small" id="footerText"${o ? "" : " hidden"}>${o}</mui-body>
330
- <slot name="footer"></slot>
331
- </div>
332
- <mui-h-stack class="footer-after" alignx="end" aligny="center" space="var(--space-200)">
333
- <mui-body class="footer-counter" id="footerCounter" size="x-small" variant="optional" hidden>Section 1/1</mui-body>
334
- <slot name="footer-after"></slot>
456
+ <mui-h-stack class="header-description" alignx="start" aligny="start" space="var(--space-200)">
457
+ <slot name="header-description"></slot>
458
+ </mui-h-stack>
459
+ </mui-v-stack>
460
+ </div>
461
+ <div class="surface" tabindex="0" role="region" aria-label="Slide frame">
462
+ <slot name="image"></slot>
463
+ <slot></slot>
464
+ </div>
465
+ <div class="footer" id="footerRegion">
466
+ <mui-v-stack class="leading leading_bottom" space="var(--space-400)">
467
+ <mui-h-stack class="footer-main" alignx="space-between" aligny="center" space="var(--space-300)">
468
+ <div class="footer-leading">
469
+ <mui-body class="footer-copy" size="small" id="footerText"${s ? "" : " hidden"}>${s}</mui-body>
470
+ <slot name="footer"></slot>
471
+ </div>
472
+ <mui-h-stack class="footer-after" alignx="end" aligny="center" space="var(--space-200)">
473
+ <mui-select
474
+ id="slideFrameRatioSelect"
475
+ size="x-small"
476
+ style="width: 7rem; margin-right: var(--space-025)"
477
+ options='[{"label":"16:9","value":"16:9"},{"label":"4:3","value":"4:3"},{"label":"1:1","value":"1:1"}]'
478
+ value="${this.getAttribute("ratio") || "16:9"}"
479
+ aria-label="Slide ratio">
480
+ </mui-select>
481
+ <mui-button id="slideFrameExitPresentBtn" size="x-small" variant="tertiary" hidden style="margin-right: var(--space-025)">Exit Fullscreen</mui-button>
482
+ <mui-body class="footer-counter" id="footerCounter" size="x-small" variant="optional" hidden>Section 1/1</mui-body>
483
+ <slot name="footer-after"></slot>
484
+ </mui-h-stack>
335
485
  </mui-h-stack>
336
- </mui-h-stack>
337
- </mui-v-stack>
486
+ </mui-v-stack>
487
+ </div>
338
488
  </div>
489
+ <div class="notes"><mui-body variant="optional" size="x-small">Notes...</mui-body><slot name="notes"></slot></div>
339
490
  </div>
340
491
  <mui-dialog id="lightboxDialog" width="min(94vw, 1200px)" content-padding="none">
341
492
  <mui-heading slot="title" size="5" level="3">Image Preview</mui-heading>
342
493
  <img id="lightboxImage" class="lightbox-image" alt="Slide image preview" />
343
494
  </mui-dialog>
344
- `, this.defaultSlot = this.shadowRoot.querySelector("slot:not([name])"), (s = this.defaultSlot) == null || s.addEventListener("slotchange", this.onSlotChange), this.headerSlot = this.shadowRoot.querySelector('slot[name="header"]'), this.headerAfterSlot = this.shadowRoot.querySelector('slot[name="header-after"]'), this.headerDescriptionSlot = this.shadowRoot.querySelector('slot[name="header-description"]'), this.footerSlot = this.shadowRoot.querySelector('slot[name="footer"]'), this.footerAfterSlot = this.shadowRoot.querySelector('slot[name="footer-after"]'), this.notesSlot = this.shadowRoot.querySelector('slot[name="notes"]'), this.imageSlot = this.shadowRoot.querySelector('slot[name="image"]'), this.surfaceEl = this.shadowRoot.querySelector(".surface"), (r = this.headerSlot) == null || r.addEventListener("slotchange", this.onChromeSlotChange), (a = this.headerAfterSlot) == null || a.addEventListener("slotchange", this.onChromeSlotChange), (l = this.headerDescriptionSlot) == null || l.addEventListener("slotchange", this.onChromeSlotChange), (h = this.footerSlot) == null || h.addEventListener("slotchange", this.onChromeSlotChange), (d = this.footerAfterSlot) == null || d.addEventListener("slotchange", this.onChromeSlotChange), (n = this.footerDescriptionSlot) == null || n.addEventListener("slotchange", this.onChromeSlotChange), (c = this.notesSlot) == null || c.addEventListener("slotchange", this.onChromeSlotChange), (g = this.surfaceEl) == null || g.addEventListener("click", this.onSurfaceClick), (u = this.surfaceEl) == null || u.addEventListener("pointerdown", this.onPointerDown), (m = this.surfaceEl) == null || m.addEventListener("pointerup", this.onPointerUp), this.style.setProperty("--slide-frame-ratio", this.resolveRatio()), (f = this.shadowRoot.querySelector("#lightboxDialog")) == null || f.addEventListener("mui-dialog-close", () => {
495
+ `, this.defaultSlot = this.shadowRoot.querySelector("slot:not([name])"), (r = this.defaultSlot) == null || r.addEventListener("slotchange", this.onSlotChange), this.headerSlot = this.shadowRoot.querySelector('slot[name="header"]'), this.headerAfterSlot = this.shadowRoot.querySelector('slot[name="header-after"]'), this.headerDescriptionSlot = this.shadowRoot.querySelector('slot[name="header-description"]'), this.footerSlot = this.shadowRoot.querySelector('slot[name="footer"]'), this.footerAfterSlot = this.shadowRoot.querySelector('slot[name="footer-after"]'), this.notesSlot = this.shadowRoot.querySelector('slot[name="notes"]'), this.imageSlot = this.shadowRoot.querySelector('slot[name="image"]'), this.stageEl = this.shadowRoot.querySelector(".stage"), this.surfaceEl = this.shadowRoot.querySelector(".surface"), (o = this.headerSlot) == null || o.addEventListener("slotchange", this.onChromeSlotChange), (n = this.headerAfterSlot) == null || n.addEventListener("slotchange", this.onChromeSlotChange), (h = this.headerDescriptionSlot) == null || h.addEventListener("slotchange", this.onChromeSlotChange), (b = this.footerSlot) == null || b.addEventListener("slotchange", this.onChromeSlotChange), (m = this.footerAfterSlot) == null || m.addEventListener("slotchange", this.onChromeSlotChange), (f = this.footerDescriptionSlot) == null || f.addEventListener("slotchange", this.onChromeSlotChange), (d = this.notesSlot) == null || d.addEventListener("slotchange", this.onChromeSlotChange), (c = this.surfaceEl) == null || c.addEventListener("click", this.onSurfaceClick), (S = this.surfaceEl) == null || S.addEventListener("pointerdown", this.onPointerDown), (w = this.surfaceEl) == null || w.addEventListener("pointerup", this.onPointerUp), this.style.setProperty("--slide-frame-ratio", this.resolveRatio()), (y = this.shadowRoot.querySelector("#lightboxDialog")) == null || y.addEventListener("mui-dialog-close", () => {
345
496
  this.dispatchEvent(new CustomEvent("lightbox-close", { bubbles: !0, composed: !0 }));
346
- }), (v = this.shadowRoot.querySelector("#notesActionBtn")) == null || v.addEventListener("click", () => {
497
+ }), (u = this.shadowRoot.querySelector("#notesActionBtn")) == null || u.addEventListener("click", () => {
347
498
  this.toggleNotes();
348
- }), (p = this.shadowRoot.querySelector("#slideFrameAddSectionBtn")) == null || p.addEventListener("click", () => {
499
+ }), (g = this.shadowRoot.querySelector("#slideFrameAddSectionBtn")) == null || g.addEventListener("click", () => {
349
500
  this.addSection(`Section ${(this.getSections().length + 1).toString()}: New`);
350
- }), (b = this.shadowRoot.querySelector("#slideFramePrevSectionBtn")) == null || b.addEventListener("click", () => {
501
+ }), (a = this.shadowRoot.querySelector("#slideFramePrevSectionBtn")) == null || a.addEventListener("click", () => {
351
502
  this.prevSection();
352
- }), (S = this.shadowRoot.querySelector("#slideFrameNextSectionBtn")) == null || S.addEventListener("click", () => {
503
+ }), (l = this.shadowRoot.querySelector("#slideFrameNextSectionBtn")) == null || l.addEventListener("click", () => {
353
504
  this.nextSection();
354
- }), (w = this.shadowRoot.querySelector("#slideFrameTogglePresentBtn")) == null || w.addEventListener("click", () => {
355
- this.toggleAttribute("present"), this.syncChromeState();
356
- }), (y = this.shadowRoot.querySelector("#slideFrameToggleNotesBtn")) == null || y.addEventListener("click", () => {
505
+ }), (p = this.shadowRoot.querySelector("#slideFrameToggleFullscreenBtn")) == null || p.addEventListener("click", () => {
506
+ if (this.hasAttribute("fullscreen") || document.fullscreenElement === this) {
507
+ this.resetPresentationState(), this.exitFullscreen();
508
+ return;
509
+ }
510
+ this.setAttribute("present", ""), this.setAttribute("fullscreen", ""), this.syncChromeState(), this.enterFullscreen().then((v) => {
511
+ v && this.syncChromeState();
512
+ });
513
+ }), (x = this.shadowRoot.querySelector("#slideFrameExitPresentBtn")) == null || x.addEventListener("click", () => {
514
+ this.resetPresentationState(), this.exitFullscreen();
515
+ }), (E = this.shadowRoot.querySelector("#slideFrameToggleNotesBtn")) == null || E.addEventListener("click", () => {
357
516
  this.toggleNotes();
358
- });
517
+ }), (A = this.shadowRoot.querySelector("#slideFrameRatioSelect")) == null || A.addEventListener("change", (F) => {
518
+ var C;
519
+ const v = F.currentTarget, k = (v == null ? void 0 : v.value) || ((C = v == null ? void 0 : v.getAttribute) == null ? void 0 : C.call(v, "value")) || "16:9";
520
+ this.setAttribute("ratio", k);
521
+ }), requestAnimationFrame(() => this.updateFullscreenSurfaceFit());
359
522
  }
360
523
  syncChromeState() {
361
524
  if (!this.shadowRoot) return;
362
- const e = (u) => ((u == null ? void 0 : u.assignedNodes({ flatten: !0 })) || []).some(
363
- (m) => m.nodeType === Node.ELEMENT_NODE || (m.textContent || "").trim().length > 0
364
- ), t = !!(this.getAttribute("title") || "").trim(), i = !!(this.getAttribute("footer-text") || "").trim(), o = !this.hasAttribute("hide-counter") && this.getSections().length > 0, s = t || e(this.headerSlot) || e(this.headerAfterSlot) || e(this.headerDescriptionSlot), r = i || e(this.footerSlot) || e(this.footerAfterSlot) || e(this.footerDescriptionSlot) || o, a = e(this.notesSlot), l = this.hasAttribute("notes-open"), h = this.shadowRoot.querySelector("#headerRegion"), d = this.shadowRoot.querySelector("#footerRegion"), n = this.shadowRoot.querySelector("#footerCounter"), c = Math.max(this.getSections().length, 1), g = this.getActiveSectionIndex() + 1;
365
- n && (n.hidden = !o, n.textContent = `Section ${Math.min(g, c)}/${c}`), h && (h.hidden = !s), d && (d.hidden = !r), this.toggleAttribute("has-header", s), this.toggleAttribute("has-footer", r), this.toggleAttribute("has-notes", a), this.toggleAttribute("notes-visible", l), this.toggleAttribute("has-chrome", s || r || l);
525
+ const e = (a) => ((a == null ? void 0 : a.assignedNodes({ flatten: !0 })) || []).some(
526
+ (l) => l.nodeType === Node.ELEMENT_NODE || (l.textContent || "").trim().length > 0
527
+ ), t = !!(this.getAttribute("title") || "").trim(), i = !!(this.getAttribute("footer-text") || "").trim(), s = this.hasAttribute("hide-header"), r = this.hasAttribute("hide-footer"), o = !this.hasAttribute("hide-counter") && this.getSections().length > 0, n = !s && (t || e(this.headerSlot) || e(this.headerAfterSlot) || e(this.headerDescriptionSlot)), h = !r && (i || e(this.footerSlot) || e(this.footerAfterSlot) || e(this.footerDescriptionSlot) || o || this.hasAttribute("present") || this.hasAttribute("fullscreen")), b = e(this.notesSlot), m = this.hasAttribute("notes-open"), f = this.shadowRoot.querySelector("#headerRegion"), d = this.shadowRoot.querySelector("#footerRegion"), c = this.shadowRoot.querySelector("#footerCounter"), S = this.shadowRoot.querySelector("#slideFrameExitPresentBtn"), w = this.shadowRoot.querySelector("#slideFrameToggleFullscreenBtn"), y = this.shadowRoot.querySelector(".present-controls"), u = Math.max(this.getSections().length, 1), g = this.getActiveSectionIndex() + 1;
528
+ if (y) {
529
+ const a = this.hasAttribute("fullscreen") || document.fullscreenElement === this;
530
+ y.hidden = a;
531
+ }
532
+ if (c) {
533
+ c.hidden = !o;
534
+ const a = Math.min(g, u), l = String(u).length;
535
+ c.style.setProperty("--slide-frame-counter-digits", String(l)), c.setAttribute("aria-label", `Section ${a} of ${u}`), c.innerHTML = `Section <span class="counter-value">${a}</span>/<span class="counter-value">${u}</span>`;
536
+ }
537
+ S && (S.hidden = !this.hasAttribute("fullscreen")), w && (w.textContent = this.hasAttribute("fullscreen") ? "Exit Fullscreen" : "Full Screen"), f && (f.hidden = !n), d && (d.hidden = !h), this.toggleAttribute("has-header", n), this.toggleAttribute("has-footer", h), this.toggleAttribute("has-notes", b), this.toggleAttribute("notes-visible", m), this.toggleAttribute("has-chrome", n || h || m), this.updateFullscreenSurfaceFit();
366
538
  }
367
539
  handleSurfaceClick(e) {
368
540
  if (!this.hasAttribute("lightbox") || !this.imageSlot) return;
369
541
  const t = this.imageSlot.assignedElements({ flatten: !0 });
370
542
  if (t.length === 0) return;
371
543
  const i = e.composedPath();
372
- if (!t.some((r) => i.includes(r))) return;
373
- const s = this.resolveLightboxImage(i, t);
374
- !s || !s.src || this.openLightbox(s.src, s.alt || "Slide image preview");
544
+ if (!t.some((o) => i.includes(o))) return;
545
+ const r = this.resolveLightboxImage(i, t);
546
+ !r || !r.src || this.openLightbox(r.src, r.alt || "Slide image preview");
375
547
  }
376
548
  handlePointerDown(e) {
377
549
  this.pointerStartX = e.clientX, this.pointerStartY = e.clientY;
@@ -381,21 +553,56 @@ class x extends HTMLElement {
381
553
  const t = e.clientX - this.pointerStartX, i = e.clientY - this.pointerStartY;
382
554
  this.pointerStartX = null, this.pointerStartY = null, !(Math.abs(t) < 40 || Math.abs(t) <= Math.abs(i)) && (t < 0 ? this.nextSection() : this.prevSection());
383
555
  }
556
+ handleFullscreenChange() {
557
+ const e = document.fullscreenElement === this, t = this.hasAttribute("fullscreen");
558
+ if (e)
559
+ this.nativeFullscreenActive = !0, this.toggleAttribute("fullscreen", !0), this.toggleAttribute("present", !0);
560
+ else if (this.nativeFullscreenActive || t)
561
+ this.resetPresentationState();
562
+ else
563
+ return;
564
+ this.syncChromeState(), this.updateFullscreenSurfaceFit(), this.dispatchEvent(
565
+ new CustomEvent("fullscreen-change", {
566
+ detail: { active: e },
567
+ bubbles: !0,
568
+ composed: !0
569
+ })
570
+ );
571
+ }
572
+ handleFullscreenError() {
573
+ if (this.nativeFullscreenActive = !1, this.hasAttribute("fullscreen")) {
574
+ this.resetPresentationState(), this.dispatchEvent(new CustomEvent("fullscreen-error", { bubbles: !0, composed: !0 }));
575
+ return;
576
+ }
577
+ this.syncChromeState(), this.dispatchEvent(new CustomEvent("fullscreen-error", { bubbles: !0, composed: !0 }));
578
+ }
579
+ updateFullscreenSurfaceFit() {
580
+ if (!this.shadowRoot || !this.stageEl) return;
581
+ if (!(this.hasAttribute("fullscreen") || this.hasAttribute("present"))) {
582
+ this.stageEl.style.width = "", this.stageEl.style.height = "";
583
+ return;
584
+ }
585
+ const t = this.shadowRoot.querySelector(".frame"), i = this.shadowRoot.querySelector(".present-controls"), s = this.shadowRoot.querySelector(".notes");
586
+ if (!t) return;
587
+ const r = t.getBoundingClientRect(), o = getComputedStyle(t), n = parseFloat(o.paddingTop || "0") || 0, h = parseFloat(o.paddingBottom || "0") || 0, b = parseFloat(o.paddingLeft || "0") || 0, m = parseFloat(o.paddingRight || "0") || 0, f = parseFloat(o.rowGap || o.gap || "0") || 0, d = i && getComputedStyle(i).display !== "none" ? i.getBoundingClientRect().height : 0, c = s && getComputedStyle(s).display !== "none" ? s.getBoundingClientRect().height : 0, S = [d > 0, !0, c > 0].filter(Boolean).length, w = Math.max(0, S - 1), y = Math.max(0, r.width - b - m), u = Math.max(0, r.height - n - h - d - c - f * w), g = this.resolveRatioParts(), a = this.hasAttribute("fullscreen") || document.fullscreenElement === this;
588
+ let l, p;
589
+ a ? (p = u, l = p * (g.width / g.height)) : (l = y, p = l * (g.height / g.width), p > u && (p = u, l = p * (g.width / g.height))), this.stageEl.style.width = `${Math.max(0, Math.floor(l))}px`, this.stageEl.style.height = `${Math.max(0, Math.floor(p))}px`;
590
+ }
384
591
  resolveLightboxImage(e, t) {
385
- var o;
386
- const i = e.find((s) => s instanceof HTMLImageElement);
592
+ var s;
593
+ const i = e.find((r) => r instanceof HTMLImageElement);
387
594
  if (i instanceof HTMLImageElement) return i;
388
- for (const s of t) {
389
- if (s instanceof HTMLImageElement) return s;
390
- const r = (o = s.querySelector) == null ? void 0 : o.call(s, "img");
595
+ for (const r of t) {
391
596
  if (r instanceof HTMLImageElement) return r;
597
+ const o = (s = r.querySelector) == null ? void 0 : s.call(r, "img");
598
+ if (o instanceof HTMLImageElement) return o;
392
599
  }
393
600
  return null;
394
601
  }
395
602
  openLightbox(e, t) {
396
- var s, r, a;
397
- const i = (s = this.shadowRoot) == null ? void 0 : s.querySelector("#lightboxDialog"), o = (r = this.shadowRoot) == null ? void 0 : r.querySelector("#lightboxImage");
398
- !i || !o || (o.src = e, o.alt = t, (a = i.open) == null || a.call(i), this.dispatchEvent(
603
+ var r, o, n;
604
+ const i = (r = this.shadowRoot) == null ? void 0 : r.querySelector("#lightboxDialog"), s = (o = this.shadowRoot) == null ? void 0 : o.querySelector("#lightboxImage");
605
+ !i || !s || (s.src = e, s.alt = t, (n = i.open) == null || n.call(i), this.dispatchEvent(
399
606
  new CustomEvent("lightbox-open", {
400
607
  detail: { src: e, alt: t },
401
608
  bubbles: !0,
@@ -407,4 +614,4 @@ class x extends HTMLElement {
407
614
  return e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
408
615
  }
409
616
  }
410
- customElements.get("mui-slide-frame") || customElements.define("mui-slide-frame", x);
617
+ customElements.get("mui-slide-frame") || customElements.define("mui-slide-frame", R);