@ulu/frontend 0.2.1 → 0.3.1

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 (41) hide show
  1. package/README.dev.md +16 -0
  2. package/dist/es/index.js +18 -16
  3. package/dist/es/ui/dialog.d.ts +3 -1
  4. package/dist/es/ui/dialog.d.ts.map +1 -1
  5. package/dist/es/ui/dialog.js +57 -51
  6. package/dist/es/ui/modal-builder.d.ts +6 -0
  7. package/dist/es/ui/modal-builder.d.ts.map +1 -1
  8. package/dist/es/ui/modal-builder.js +53 -45
  9. package/dist/es/utils/dialog.d.ts +14 -0
  10. package/dist/es/utils/dialog.d.ts.map +1 -0
  11. package/dist/es/utils/dialog.js +16 -0
  12. package/dist/es/utils/iframe.d.ts +15 -0
  13. package/dist/es/utils/iframe.d.ts.map +1 -0
  14. package/dist/es/utils/iframe.js +33 -0
  15. package/dist/es/utils/index.d.ts +1 -0
  16. package/dist/umd/frontend.css +1 -1
  17. package/dist/umd/ulu-frontend.umd.js +12 -12
  18. package/lib/js/exports.md +1 -0
  19. package/lib/js/ui/dialog.js +23 -3
  20. package/lib/js/ui/modal-builder.js +21 -0
  21. package/lib/js/utils/dialog.js +29 -0
  22. package/lib/js/utils/iframe.js +59 -0
  23. package/lib/js/utils/index.js +4 -1
  24. package/lib/scss/_color.scss +1 -1
  25. package/lib/scss/_element.scss +15 -0
  26. package/lib/scss/_utils.scss +22 -0
  27. package/lib/scss/base/_elements.scss +3 -0
  28. package/lib/scss/components/_accordion.scss +7 -2
  29. package/lib/scss/components/_badge.scss +1 -1
  30. package/lib/scss/components/_button-group.scss +8 -3
  31. package/lib/scss/components/_card-grid.scss +8 -14
  32. package/lib/scss/components/_card.scss +15 -13
  33. package/lib/scss/components/_data-list.scss +270 -0
  34. package/lib/scss/components/_data-table.scss +3 -1
  35. package/lib/scss/components/_index.scss +12 -0
  36. package/lib/scss/components/_menu-stack.scss +1 -1
  37. package/lib/scss/components/_modal.scss +97 -19
  38. package/lib/scss/components/_ratio-box.scss +11 -10
  39. package/lib/scss/components/_table-scroller.scss +63 -0
  40. package/lib/scss/helpers/_utilities.scss +23 -1
  41. package/package.json +4 -1
package/README.dev.md CHANGED
@@ -22,6 +22,22 @@ The library is designed with a clear separation between styles (SCSS) and behavi
22
22
 
23
23
  In short, the SCSS defines what components and their different states *look like*, while the JavaScript is responsible for activating components and changing their states based on user interaction. This creates a flexible and efficient system.
24
24
 
25
+ ## SCSS Development Conventions
26
+
27
+ When developing new SCSS components or maintaining existing ones, adhere to the following architectural patterns:
28
+
29
+ 1. **Configuration Property Naming:**
30
+ * Modifier-specific properties must begin with the modifier name.
31
+ * *Correct:* `clickable-background-color-hover`
32
+ * *Incorrect:* `background-color-clickable-hover`
33
+ * Responsive state variables should describe the *behavior*, not a hardcoded viewport/breakpoint name if possible. Example a component that stacks when on smaller screens might refer to that breakpoint as `stacked-breakpoint`
34
+
35
+ TODO: This section should be added to... (sassdoc type naming, etc). Formatting...
36
+
37
+ ## Documentation
38
+
39
+ - `site/`: Contains the source code for the documentation website (Eleventy). **Edit files here.**
40
+ - `docs/`: The build output for GitHub Pages. **Do not edit files here directly.**
25
41
 
26
42
  ## Benchmark Notes
27
43
 
package/dist/es/index.js CHANGED
@@ -2,9 +2,9 @@ import { createUluEvent as i, dispatchCoreEvent as r, getCoreEventName as a, get
2
2
  import { getDefaultSettings as l, getSetting as n, getSettings as p, updateSetting as g, updateSettings as u, wrapSettingString as f } from "./core/settings.js";
3
3
  import { ComponentInitializer as m } from "./core/component.js";
4
4
  import { BreakpointManager as I } from "./ui/breakpoints.js";
5
- import { Collapsible as z } from "./ui/collapsible.js";
5
+ import { Collapsible as S } from "./ui/collapsible.js";
6
6
  import { init as D, initializer as C, setupGroup as v } from "./ui/details-group.js";
7
- import { baseAttribute as T, closeAttribute as y, defaults as B, getDialogOptions as P, init as h, initializer as A, setDefaults as k, setupDialog as G, setupTrigger as L } from "./ui/dialog.js";
7
+ import { baseAttribute as y, closeAttribute as T, defaults as B, getDialogOptions as P, init as h, initializer as A, setDefaults as L, setupDialog as k, setupTrigger as G } from "./ui/dialog.js";
8
8
  import { Flipcard as M, init as w, initializer as U } from "./ui/flipcard.js";
9
9
  import { init as F, initializer as O } from "./ui/grid.js";
10
10
  import { buildModal as N, defaults as R, init as W, initializer as K, setDefaults as j } from "./ui/modal-builder.js";
@@ -15,11 +15,11 @@ import { init as $ } from "./ui/page.js";
15
15
  import { Popover as te, getContentByTrigger as ie, init as re, initializer as ae, instances as oe, resolve as se } from "./ui/popover.js";
16
16
  import { attrs as ne, init as pe } from "./ui/print-details.js";
17
17
  import { init as ue } from "./ui/print.js";
18
- import { attachHandlers as de, defaults as me, init as xe, initializer as Ie, setDefaults as ce, setupProxy as ze } from "./ui/proxy-click.js";
18
+ import { attachHandlers as de, defaults as me, init as xe, initializer as Ie, setDefaults as ce, setupProxy as Se } from "./ui/proxy-click.js";
19
19
  import { Resizer as De } from "./ui/resizer.js";
20
20
  import { init as ve, initializer as be } from "./ui/scroll-slider.js";
21
- import { Scrollpoint as ye, init as Be, initializer as Pe } from "./ui/scrollpoint.js";
22
- import { Slider as Ae, init as ke, initializer as Ge, setupSlider as Le } from "./ui/slider.js";
21
+ import { Scrollpoint as Te, init as Be, initializer as Pe } from "./ui/scrollpoint.js";
22
+ import { Slider as Ae, init as Le, initializer as ke, setupSlider as Ge } from "./ui/slider.js";
23
23
  import { TabManager as Me } from "./ui/tab-manager.js";
24
24
  import { init as Ue, initializer as Ve, instances as Fe, setup as Oe } from "./ui/tabs.js";
25
25
  import { defaults as Ne, init as Re, initializer as We, setDefaults as Ke, setupToggle as je } from "./ui/theme-toggle.js";
@@ -31,9 +31,10 @@ import { createFloatingUi as nt, defaults as pt } from "./utils/floating-ui.js";
31
31
  import { configureIcons as ut } from "./utils/font-awesome.js";
32
32
  import { ensureId as dt, newId as mt } from "./utils/id.js";
33
33
  import { pauseVideos as It, prepVideos as ct } from "./utils/pause-youtube-video.js";
34
+ import { getSoleIframeLayout as zt } from "./utils/iframe.js";
34
35
  export {
35
36
  I as BreakpointManager,
36
- z as Collapsible,
37
+ S as Collapsible,
37
38
  m as ComponentInitializer,
38
39
  st as FileSave,
39
40
  M as Flipcard,
@@ -41,7 +42,7 @@ export {
41
42
  te as Popover,
42
43
  J as ProgrammaticModalManager,
43
44
  De as Resizer,
44
- ye as Scrollpoint,
45
+ Te as Scrollpoint,
45
46
  Ae as Slider,
46
47
  Me as TabManager,
47
48
  Je as Tooltip,
@@ -55,15 +56,15 @@ export {
55
56
  D as detailsGroupInit,
56
57
  C as detailsGroupInitializer,
57
58
  v as detailsGroupSetupGroup,
58
- T as dialogBaseAttribute,
59
- y as dialogCloseAttribute,
59
+ y as dialogBaseAttribute,
60
+ T as dialogCloseAttribute,
60
61
  B as dialogDefaults,
61
62
  P as dialogGetDialogOptions,
62
63
  h as dialogInit,
63
64
  A as dialogInitializer,
64
- k as dialogSetDefaults,
65
- G as dialogSetupDialog,
66
- L as dialogSetupTrigger,
65
+ L as dialogSetDefaults,
66
+ k as dialogSetupDialog,
67
+ G as dialogSetupTrigger,
67
68
  r as dispatchCoreEvent,
68
69
  dt as ensureId,
69
70
  w as flipcardInit,
@@ -74,6 +75,7 @@ export {
74
75
  l as getDefaultSettings,
75
76
  n as getSetting,
76
77
  p as getSettings,
78
+ zt as getSoleIframeLayout,
77
79
  o as getUluEventName,
78
80
  F as gridInit,
79
81
  O as gridInitializer,
@@ -98,16 +100,16 @@ export {
98
100
  xe as proxyClickInit,
99
101
  Ie as proxyClickInitializer,
100
102
  ce as proxyClickSetDefaults,
101
- ze as proxyClickSetupProxy,
103
+ Se as proxyClickSetupProxy,
102
104
  rt as resolveClasses,
103
105
  ve as scrollSliderInit,
104
106
  be as scrollSliderInitializer,
105
107
  Be as scrollpointInit,
106
108
  Pe as scrollpointInitializer,
107
109
  at as setPositionClasses,
108
- ke as sliderInit,
109
- Ge as sliderInitializer,
110
- Le as sliderSetupSlider,
110
+ Le as sliderInit,
111
+ ke as sliderInitializer,
112
+ Ge as sliderSetupSlider,
111
113
  Ue as tabsInit,
112
114
  Ve as tabsInitializer,
113
115
  Fe as tabsInstances,
@@ -18,7 +18,9 @@ export function setupTrigger(trigger: Node, dialogId: string): void;
18
18
  * Setup click handlers for a dialog
19
19
  * @param {Node} dialog
20
20
  */
21
- export function setupDialog(dialog: Node, userOptions: any): void;
21
+ export function setupDialog(dialog: Node, userOptions: any): {
22
+ destroy: () => void;
23
+ };
22
24
  /**
23
25
  * For a given dialog, get it's options (from data attribute)
24
26
  * @param {Node} dialog
@@ -1 +1 @@
1
- {"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../../../lib/js/ui/dialog.js"],"names":[],"mappings":"AA6DA;;GAEG;AACH,qCAFW,MAAM,QAIhB;AAED;;;GAGG;AACH,6BAqBC;AAED;;;;GAIG;AACH,sCAHW,IAAI,0BA2Bd;AAED;;;GAGG;AACH,oCAFW,IAAI,0BA6Dd;AAED;;;;GAIG;AACH,yCAHW,IAAI,GACF,MAAM,CAIlB;AA7LD;;GAEG;AACH,4BAA6B,iBAAiB,CAAC;AAE/C;;GAEG;AACH,+CAAuF;AAEvF;;GAEG;AACH,oCAAgE;;;;;;;;;qCAjB3B,sBAAsB"}
1
+ {"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../../../lib/js/ui/dialog.js"],"names":[],"mappings":"AA8DA;;GAEG;AACH,qCAFW,MAAM,QAIhB;AAED;;;GAGG;AACH,6BAqBC;AAED;;;;GAIG;AACH,sCAHW,IAAI,0BA2Bd;AAED;;;GAGG;AACH,oCAFW,IAAI;;EAgFd;AAED;;;;GAIG;AACH,yCAHW,IAAI,GACF,MAAM,CAIlB;AAhND;;GAEG;AACH,4BAA6B,iBAAiB,CAAC;AAE/C;;GAEG;AACH,+CAAuF;AAEvF;;GAEG;AACH,oCAAgE;;;;;;;;;qCAlB3B,sBAAsB"}
@@ -1,19 +1,20 @@
1
- var O = Object.defineProperty;
2
- var f = Object.getOwnPropertySymbols;
3
- var S = Object.prototype.hasOwnProperty, b = Object.prototype.propertyIsEnumerable;
4
- var m = (e, o, t) => o in e ? O(e, o, { enumerable: !0, configurable: !0, writable: !0, value: t }) : e[o] = t, g = (e, o) => {
1
+ var S = Object.defineProperty;
2
+ var p = Object.getOwnPropertySymbols;
3
+ var D = Object.prototype.hasOwnProperty, O = Object.prototype.propertyIsEnumerable;
4
+ var f = (e, o, t) => o in e ? S(e, o, { enumerable: !0, configurable: !0, writable: !0, value: t }) : e[o] = t, m = (e, o) => {
5
5
  for (var t in o || (o = {}))
6
- S.call(o, t) && m(e, t, o[t]);
7
- if (f)
8
- for (var t of f(o))
9
- b.call(o, t) && m(e, t, o[t]);
6
+ D.call(o, t) && f(e, t, o[t]);
7
+ if (p)
8
+ for (var t of p(o))
9
+ O.call(o, t) && f(e, t, o[t]);
10
10
  return e;
11
11
  };
12
- import { getUluEventName as v } from "../core/events.js";
12
+ import { getUluEventName as g } from "../core/events.js";
13
13
  import { ComponentInitializer as V } from "../core/component.js";
14
- import { preventScroll as w, wasClickOutside as C } from "@ulu/utils/browser/dom.js";
15
- import { prepVideos as D, pauseVideos as k } from "../utils/pause-youtube-video.js";
16
- const L = "data-ulu-dialog", i = new V({ type: "dialog", baseAttribute: L }), x = i.getAttribute("close"), y = {
14
+ import { wasClickOutside as C, preventScroll as k } from "@ulu/utils/browser/dom.js";
15
+ import { prepVideos as w, pauseVideos as y } from "../utils/pause-youtube-video.js";
16
+ import { observeDialogToggle as z } from "../utils/dialog.js";
17
+ const L = "data-ulu-dialog", r = new V({ type: "dialog", baseAttribute: L }), G = r.getAttribute("close"), M = {
17
18
  /**
18
19
  * Use non-modal interface for dialog
19
20
  */
@@ -41,31 +42,31 @@ const L = "data-ulu-dialog", i = new V({ type: "dialog", baseAttribute: L }), x
41
42
  */
42
43
  preventScrollShift: !0
43
44
  };
44
- let a = g({}, y);
45
- function P(e) {
45
+ let a = m({}, M);
46
+ function H(e) {
46
47
  a = Object.assign({}, a, e);
47
48
  }
48
- function U() {
49
- i.init({
49
+ function J() {
50
+ r.init({
50
51
  coreEvents: ["pageModified"],
51
52
  withData: !0,
52
53
  setup({ element: e, initialize: o, data: t }) {
53
- M(e, t), o();
54
+ I(e, t), o();
54
55
  }
55
- }), i.init({
56
+ }), r.init({
56
57
  key: "trigger",
57
58
  coreEvents: ["pageModified"],
58
59
  withData: !0,
59
60
  setup({ element: e, initialize: o, data: t }) {
60
- z(e, t), o();
61
+ A(e, t), o();
61
62
  }
62
63
  });
63
64
  }
64
- function z(e, o) {
65
+ function A(e, o) {
65
66
  e.addEventListener("click", t);
66
- function t(r) {
67
+ function t(l) {
67
68
  var c;
68
- r.target.closest("a") && r.preventDefault();
69
+ l.target.closest("a") && l.preventDefault();
69
70
  const n = document.getElementById(o);
70
71
  if (!n) {
71
72
  console.error("Could not locate dialog (id)", o);
@@ -75,49 +76,54 @@ function z(e, o) {
75
76
  console.error("Attempted to trigger non <dialog> element. Did you mean to use modal builder?");
76
77
  return;
77
78
  }
78
- const u = A(n);
79
- n[u.nonModal ? "show" : "showModal"]();
79
+ const i = R(n);
80
+ n[i.nonModal ? "show" : "showModal"]();
80
81
  }
81
82
  }
82
- function M(e, o) {
83
- const t = Object.assign({}, a, o), r = document.body, { preventScrollShift: d } = t;
84
- let n;
85
- if (e.addEventListener(v("resizer:start"), c), e.addEventListener(v("resizer:end"), h), e.addEventListener("click", u), t.documentEnd && r.appendChild(e), t.pauseVideos && I(e), !t.nonModal && t.preventScroll) {
83
+ function I(e, o) {
84
+ const t = Object.assign({}, a, o), l = document.body, { preventScrollShift: d } = t;
85
+ let n = null, i;
86
+ if (e.addEventListener(g("resizer:start"), v), e.addEventListener(g("resizer:end"), b), e.addEventListener("click", c), t.documentEnd && l.appendChild(e), t.pauseVideos && T(e), !t.nonModal && t.preventScroll) {
86
87
  let s;
87
- e.addEventListener("toggle", (l) => {
88
- l.newState === "open" ? s = w({ preventShift: d }) : s && s();
88
+ n = z(e, (u) => {
89
+ u ? s = k({ preventShift: d }) : s && (s(), s = null);
89
90
  });
90
91
  }
91
- function u(s) {
92
- const { target: l } = s, p = l === e, E = l.closest(i.attributeSelector("close"));
93
- (!n && t.clickOutsideCloses && p && C(e, s) || E) && (t.pauseVideos && j(e), e.close());
94
- }
95
92
  function c(s) {
96
- n = s.pointerId;
93
+ const { target: u } = s, h = u === e, E = u.closest(r.attributeSelector("close"));
94
+ (!i && t.clickOutsideCloses && h && C(e, s) || E) && (t.pauseVideos && j(e), e.close());
95
+ }
96
+ function v(s) {
97
+ i = s.pointerId;
97
98
  }
98
- function h(s) {
99
- n === s.pointerId && setTimeout(() => {
100
- n = null;
99
+ function b(s) {
100
+ i === s.pointerId && setTimeout(() => {
101
+ i = null;
101
102
  }, 0);
102
103
  }
104
+ return {
105
+ destroy: () => {
106
+ n && n.destroy();
107
+ }
108
+ };
103
109
  }
104
- function A(e) {
105
- return Object.assign({}, a, i.getData(e));
110
+ function R(e) {
111
+ return Object.assign({}, a, r.getData(e));
106
112
  }
107
- function I(e) {
108
- D(e);
113
+ function T(e) {
114
+ w(e);
109
115
  }
110
116
  function j(e) {
111
- k(e), e.querySelectorAll("video").forEach((t) => t.pause());
117
+ y(e), e.querySelectorAll("video").forEach((t) => t.pause());
112
118
  }
113
119
  export {
114
120
  L as baseAttribute,
115
- x as closeAttribute,
116
- y as defaults,
117
- A as getDialogOptions,
118
- U as init,
119
- i as initializer,
120
- P as setDefaults,
121
- M as setupDialog,
122
- z as setupTrigger
121
+ G as closeAttribute,
122
+ M as defaults,
123
+ R as getDialogOptions,
124
+ J as init,
125
+ r as initializer,
126
+ H as setDefaults,
127
+ I as setupDialog,
128
+ A as setupTrigger
123
129
  };
@@ -37,6 +37,7 @@ export namespace defaults {
37
37
  export let size: string;
38
38
  export let print: boolean;
39
39
  export let noMinHeight: boolean;
40
+ export let fullscreenMobile: boolean;
40
41
  let _class: string;
41
42
  export { _class as class };
42
43
  export let baseClass: string;
@@ -47,6 +48,7 @@ export namespace defaults {
47
48
  export let classResizerIcon: Object;
48
49
  export let classResizerIconBoth: Object;
49
50
  export let debug: boolean;
51
+ export let autoIframe: boolean;
50
52
  export function templateCloseIcon(config: any): string;
51
53
  export function templateResizerIcon(config: any): string;
52
54
  /**
@@ -152,6 +154,10 @@ export type DefaultModalOptions = {
152
154
  * - Enables debug logging. Defaults to `false`.
153
155
  */
154
156
  debug: boolean;
157
+ /**
158
+ * - Opt-in convenience behavior. If the modal body's sole content is an iframe, it automatically applies layout fixes. If the iframe has static width/height attributes (like YouTube), it retains that aspect ratio responsively. Otherwise, it forces the iframe to fill the modal. Defaults to `false`.
159
+ */
160
+ autoIframe: boolean;
155
161
  /**
156
162
  * - A function that returns the HTML for the close icon.
157
163
  */
@@ -1 +1 @@
1
- {"version":3,"file":"modal-builder.d.ts","sourceRoot":"","sources":["../../../lib/js/ui/modal-builder.js"],"names":[],"mappings":"AAoJA;;GAEG;AACH,qCAFW,MAAM,QAIhB;AAED;;;GAGG;AACH,6BAQC;AAED;;;;GAIG;AACH,oCAHW,IAAI,WACJ,MAAM;;;EAqEhB;AApOD;;GAEG;AACH,+CAGG;;;;;;;;;;;;;;;;;;;;;;;;;;IAiED,uDAGC;IACD,yDAIC;IACD;;;;;OAKG;IACH,6CAHW,MAAM,UA8ChB;;;;;;;;;;;;WAnHW,MAAM,GAAC,IAAI;;;;eACX,MAAM,GAAC,IAAI;;;;gBACX,MAAM;;;;gBACN,MAAM;;;;iBACN,MAAM;;;;cACN,OAAO;;;;iBACP,OAAO;;;;iBACP,OAAO;;;;cACP,QAAQ,GAAC,UAAU,GAAC,YAAY,GAAC,WAAW,GAAC,aAAa,GAAC,eAAe,GAAC,cAAc;;;;eACzF,OAAO;;;;gBACP,OAAO;;;;UACP,SAAS,GAAC,OAAO,GAAC,OAAO,GAAC,YAAY;;;;WACtC,OAAO;;;;iBACP,OAAO;;;;WACP,MAAM;;;;eACN,MAAM;;;;gBACN,MAAM;;;;oBACN,MAAM;;;;sBACN,MAAM;;;;mBACN,MAAM,GAAC,IAAI;;;;gBACX,MAAM,GAAC,IAAI;;;;WACX,OAAO;;;;uBACP,CAAS,IAAM,EAAN,MAAM,KAAG,MAAM;;;;YACxB,CAAS,IAAM,EAAN,MAAM,KAAG,MAAM;;wBA1Cd,cAAc;qCAHD,sBAAsB"}
1
+ {"version":3,"file":"modal-builder.d.ts","sourceRoot":"","sources":["../../../lib/js/ui/modal-builder.js"],"names":[],"mappings":"AAyJA;;GAEG;AACH,qCAFW,MAAM,QAIhB;AAED;;;GAGG;AACH,6BAQC;AAED;;;;GAIG;AACH,oCAHW,IAAI,WACJ,MAAM;;;EAqFhB;AAxPD;;GAEG;AACH,+CAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAoED,uDAGC;IACD,yDAIC;IACD;;;;;OAKG;IACH,6CAHW,MAAM,UA+ChB;;;;;;;;;;;;WAvHW,MAAM,GAAC,IAAI;;;;eACX,MAAM,GAAC,IAAI;;;;gBACX,MAAM;;;;gBACN,MAAM;;;;iBACN,MAAM;;;;cACN,OAAO;;;;iBACP,OAAO;;;;iBACP,OAAO;;;;cACP,QAAQ,GAAC,UAAU,GAAC,YAAY,GAAC,WAAW,GAAC,aAAa,GAAC,eAAe,GAAC,cAAc;;;;eACzF,OAAO;;;;gBACP,OAAO;;;;UACP,SAAS,GAAC,OAAO,GAAC,OAAO,GAAC,YAAY;;;;WACtC,OAAO;;;;iBACP,OAAO;;;;WACP,MAAM;;;;eACN,MAAM;;;;gBACN,MAAM;;;;oBACN,MAAM;;;;sBACN,MAAM;;;;mBACN,MAAM,GAAC,IAAI;;;;gBACX,MAAM,GAAC,IAAI;;;;WACX,OAAO;;;;gBACP,OAAO;;;;uBACP,CAAS,IAAM,EAAN,MAAM,KAAG,MAAM;;;;YACxB,CAAS,IAAM,EAAN,MAAM,KAAG,MAAM;;wBA5Cd,cAAc;qCAHD,sBAAsB"}
@@ -1,24 +1,25 @@
1
1
  var I = Object.defineProperty;
2
2
  var m = Object.getOwnPropertySymbols;
3
- var E = Object.prototype.hasOwnProperty, v = Object.prototype.propertyIsEnumerable;
3
+ var R = Object.prototype.hasOwnProperty, E = Object.prototype.propertyIsEnumerable;
4
4
  var p = (s, t, e) => t in s ? I(s, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : s[t] = e, $ = (s, t) => {
5
5
  for (var e in t || (t = {}))
6
- E.call(t, e) && p(s, e, t[e]);
6
+ R.call(t, e) && p(s, e, t[e]);
7
7
  if (m)
8
8
  for (var e of m(t))
9
- v.call(t, e) && p(s, e, t[e]);
9
+ E.call(t, e) && p(s, e, t[e]);
10
10
  return s;
11
11
  };
12
- import { ComponentInitializer as R } from "../core/component.js";
13
- import { wrapSettingString as d } from "../core/settings.js";
12
+ import { ComponentInitializer as v } from "../core/component.js";
13
+ import { wrapSettingString as c } from "../core/settings.js";
14
14
  import { getCoreEventName as f } from "../core/events.js";
15
15
  import { Resizer as w } from "./resizer.js";
16
- import { baseAttribute as A, closeAttribute as g, defaults as D } from "./dialog.js";
17
- import { createElementFromHtml as O, getElement as M } from "@ulu/utils/browser/dom.js";
18
- const n = new R({
16
+ import { baseAttribute as g, closeAttribute as A, defaults as H } from "./dialog.js";
17
+ import { createElementFromHtml as M, getElement as S } from "@ulu/utils/browser/dom.js";
18
+ import { getSoleIframeLayout as D } from "../utils/iframe.js";
19
+ const n = new v({
19
20
  type: "modal-builder",
20
21
  baseAttribute: "data-ulu-modal-builder"
21
- }), B = {
22
+ }), L = {
22
23
  title: null,
23
24
  titleIcon: null,
24
25
  titleClass: "",
@@ -33,22 +34,24 @@ const n = new R({
33
34
  size: "default",
34
35
  print: !1,
35
36
  noMinHeight: !1,
37
+ fullscreenMobile: !1,
36
38
  class: "",
37
39
  baseClass: "modal",
38
40
  footerElement: null,
39
41
  footerHtml: null,
40
42
  classClose: "button button--icon",
41
- classCloseIcon: d("iconClassClose", (s) => `${s} button__icon`),
42
- classResizerIcon: d("iconClassDragX"),
43
- classResizerIconBoth: d("iconClassDragBoth"),
43
+ classCloseIcon: c("iconClassClose", (s) => `${s} button__icon`),
44
+ classResizerIcon: c("iconClassDragX"),
45
+ classResizerIconBoth: c("iconClassDragBoth"),
44
46
  debug: !1,
47
+ autoIframe: !1,
45
48
  templateCloseIcon(s) {
46
49
  const { baseClass: t, classCloseIcon: e } = s;
47
50
  return `<span class="${t}__close-icon ${e}" aria-hidden="true"></span>`;
48
51
  },
49
52
  templateResizerIcon(s) {
50
- const { baseClass: t, classResizerIcon: e, classResizerIconBoth: i } = s, r = s.position === "center" ? i : e;
51
- return `<span class="${t}__resizer-icon ${r}" aria-hidden="true"></span>`;
53
+ const { baseClass: t, classResizerIcon: e, classResizerIconBoth: a } = s, o = s.position === "center" ? a : e;
54
+ return `<span class="${t}__resizer-icon ${o}" aria-hidden="true"></span>`;
52
55
  },
53
56
  /**
54
57
  * Default modal template
@@ -57,7 +60,7 @@ const n = new R({
57
60
  * @returns {String} Markup for modal
58
61
  */
59
62
  template(s, t) {
60
- const { baseClass: e, describedby: i, footerHtml: r } = t, o = [
63
+ const { baseClass: e, describedby: a, footerHtml: o } = t, i = [
61
64
  e,
62
65
  `${e}--${t.position}`,
63
66
  `${e}--${t.size}`,
@@ -66,28 +69,29 @@ const n = new R({
66
69
  ...t.bodyFills ? [`${e}--body-fills`] : [],
67
70
  ...t.noBackdrop ? [`${e}--no-backdrop`] : [],
68
71
  ...t.noMinHeight ? [`${e}--no-min-height`] : [],
72
+ ...t.fullscreenMobile ? [`${e}--fullscreen-mobile`] : [],
69
73
  ...t.class ? [t.class] : []
70
- ], a = t.title ? `${s}--title` : t.labelledby;
74
+ ], r = t.title ? `${s}--title` : t.labelledby;
71
75
  return `
72
76
  <dialog
73
77
  id="${s}"
74
- class="${o.join(" ")}"
75
- ${a ? `aria-labelledby="${a}"` : ""}
76
- ${i ? `aria-describedby="${i}"` : ""}
78
+ class="${i.join(" ")}"
79
+ ${r ? `aria-labelledby="${r}"` : ""}
80
+ ${a ? `aria-describedby="${a}"` : ""}
77
81
  >
78
82
  ${t.title ? `
79
83
  <header class="${e}__header">
80
- <h2 id="${a}" class="${e}__title ${t.titleClass}">
84
+ <h2 id="${r}" class="${e}__title ${t.titleClass}">
81
85
  ${t.titleIcon ? `<span class="${e}__title-icon ${t.titleIcon}" aria-hidden="true"></span>` : ""}
82
86
  <span class="${e}__title-text">${t.title}</span>
83
87
  </h2>
84
- <button class="${e}__close ${t.classClose}" aria-label="Close modal" ${g} autofocus>
88
+ <button class="${e}__close ${t.classClose}" aria-label="Close modal" ${A} autofocus>
85
89
  ${t.templateCloseIcon(t)}
86
90
  </button>
87
91
  </header>
88
92
  ` : ""}
89
93
  <div class="${e}__body" ${n.getAttribute("body")}></div>
90
- ${r ? `<div class="${e}__footer">${r}</div>` : ""}
94
+ ${o ? `<div class="${e}__footer">${o}</div>` : ""}
91
95
  ${t.allowResize ? `<button class="${e}__resizer" type="button" ${n.getAttribute("resizer")}>
92
96
  ${t.templateResizerIcon(t)}
93
97
  </button>` : ""}
@@ -95,53 +99,57 @@ const n = new R({
95
99
  `;
96
100
  }
97
101
  };
98
- let c = $({}, B);
99
- function x(s) {
100
- c = Object.assign({}, c, s);
102
+ let u = $({}, L);
103
+ function J(s) {
104
+ u = Object.assign({}, u, s);
101
105
  }
102
- function q() {
106
+ function Y() {
103
107
  n.init({
104
108
  withData: !0,
105
109
  coreEvents: ["pageModified"],
106
110
  setup({ element: s, data: t }) {
107
- H(s, t);
111
+ O(s, t);
108
112
  }
109
113
  });
110
114
  }
111
- function H(s, t) {
112
- const e = Object.assign({}, c, t), { position: i } = e;
115
+ function O(s, t) {
116
+ const e = Object.assign({}, u, t), { position: a } = e;
113
117
  if (e.debug && n.log(e, s), !s.id)
114
118
  throw new Error("Missing ID on modal");
115
- const r = e.template(s.id, e), o = O(r.trim()), a = (l) => o.querySelector(n.attributeSelector(l)), u = a("body"), h = a("resizer"), z = S(e);
116
- if (s.removeAttribute("id"), s.removeAttribute("hidden"), s.removeAttribute(n.getAttribute()), s.parentNode.replaceChild(o, s), u.appendChild(s), o.setAttribute(A, JSON.stringify(z)), e.footerElement) {
117
- const l = M(e.footerElement);
118
- l && (l.classList.add(`${e.baseClass}__footer`), u.after(l));
119
+ const o = e.template(s.id, e), i = M(o.trim()), r = (l) => i.querySelector(n.attributeSelector(l)), d = r("body"), h = r("resizer"), C = B(e);
120
+ if (s.removeAttribute("id"), s.removeAttribute("hidden"), s.removeAttribute(n.getAttribute()), s.parentNode.replaceChild(i, s), d.appendChild(s), i.setAttribute(g, JSON.stringify(C)), e.footerElement) {
121
+ const l = S(e.footerElement);
122
+ l && (l.classList.add(`${e.baseClass}__footer`), d.after(l));
123
+ }
124
+ if (e.autoIframe) {
125
+ const l = D(s);
126
+ l && (l.iframe.classList.add(`${e.baseClass}__frame-content`), l.isStaticSize ? (i.classList.add(`${e.baseClass}--frame-ratio`), d.style.aspectRatio = l.aspectRatio) : (i.classList.add(`${e.baseClass}--frame-fill`), l.fillHeight && (d.style.minHeight = l.fillHeight)));
119
127
  }
120
128
  let b;
121
- const C = ["left", "right", "center"], _ = i === "center", y = i === "right";
129
+ const z = ["left", "right", "center"], _ = a === "center", y = a === "right";
122
130
  if (e.allowResize)
123
- if (C.includes(i)) {
131
+ if (z.includes(a)) {
124
132
  const l = _ ? { fromX: "right", fromY: "bottom", multiplier: 2 } : { fromX: y ? "left" : "right" };
125
- b = new w(o, h, l);
133
+ b = new w(i, h, l);
126
134
  } else
127
- console.warn(`${i} is not supported for resizing`);
135
+ console.warn(`${a} is not supported for resizing`);
128
136
  if (e.print) {
129
137
  let l;
130
138
  document.addEventListener(f("beforePrint"), () => {
131
- l = s.cloneNode(!0), o.after(l);
139
+ l = s.cloneNode(!0), i.after(l);
132
140
  }), document.addEventListener(f("afterPrint"), () => {
133
141
  l.remove();
134
142
  });
135
143
  }
136
- return { modal: o, resizer: b };
144
+ return { modal: i, resizer: b };
137
145
  }
138
- function S(s) {
139
- return Object.keys(D).reduce((t, e) => (e in s && (t[e] = s[e]), t), {});
146
+ function B(s) {
147
+ return Object.keys(H).reduce((t, e) => (e in s && (t[e] = s[e]), t), {});
140
148
  }
141
149
  export {
142
- H as buildModal,
143
- B as defaults,
144
- q as init,
150
+ O as buildModal,
151
+ L as defaults,
152
+ Y as init,
145
153
  n as initializer,
146
- x as setDefaults
154
+ J as setDefaults
147
155
  };
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Utility functions for dialogs
3
+ * @module utils/dialog
4
+ */
5
+ /**
6
+ * Workaround for poor Safari support of the dialog 'toggle' event.
7
+ * Watches for changes to the 'open' attribute and fires a callback.
8
+ *
9
+ * @param {HTMLDialogElement} dialog The dialog element to observe
10
+ * @param {Function} callback Function to call when the open state changes. Receives boolean indicating open state.
11
+ * @returns {Object} Object with a destroy method to disconnect the observer
12
+ */
13
+ export function observeDialogToggle(dialog: HTMLDialogElement, callback: Function): Object;
14
+ //# sourceMappingURL=dialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../../../lib/js/utils/dialog.js"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;GAOG;AACH,4CAJW,iBAAiB,uBAEf,MAAM,CAiBlB"}
@@ -0,0 +1,16 @@
1
+ function i(e, r) {
2
+ const t = new MutationObserver((o) => {
3
+ o.forEach((n) => {
4
+ if (n.attributeName === "open") {
5
+ const s = e.hasAttribute("open");
6
+ r(s);
7
+ }
8
+ });
9
+ });
10
+ return t.observe(e, { attributes: !0, attributeFilter: ["open"] }), {
11
+ destroy: () => t.disconnect()
12
+ };
13
+ }
14
+ export {
15
+ i as observeDialogToggle
16
+ };
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Checks if an element's sole content is an iframe, and determines its layout type.
3
+ * Useful for determining if layout fixes should be applied to containers.
4
+ * @param {HTMLElement} container The container to check
5
+ * @returns {{iframe: HTMLIFrameElement, isStaticSize: boolean, width: string|null, height: string|null, aspectRatio: string|null, fillHeight: string|null}|null} Returns an object with iframe details, or null if not a sole iframe
6
+ */
7
+ export function getSoleIframeLayout(container: HTMLElement): {
8
+ iframe: HTMLIFrameElement;
9
+ isStaticSize: boolean;
10
+ width: string | null;
11
+ height: string | null;
12
+ aspectRatio: string | null;
13
+ fillHeight: string | null;
14
+ } | null;
15
+ //# sourceMappingURL=iframe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"iframe.d.ts","sourceRoot":"","sources":["../../../lib/js/utils/iframe.js"],"names":[],"mappings":"AAQA;;;;;GAKG;AACH,+CAHW,WAAW,GACT;IAAC,MAAM,EAAE,iBAAiB,CAAC;IAAC,YAAY,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,GAAC,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,GAAC,IAAI,CAAC;IAAC,WAAW,EAAE,MAAM,GAAC,IAAI,CAAC;IAAC,UAAU,EAAE,MAAM,GAAC,IAAI,CAAA;CAAC,GAAC,IAAI,CA8C/J"}
@@ -0,0 +1,33 @@
1
+ import { separateCssUnit as u } from "@ulu/utils/string.js";
2
+ const o = /^\d+$/;
3
+ function h(a) {
4
+ const c = a.querySelectorAll("iframe");
5
+ if (c.length === 1 && a.textContent.trim() === "") {
6
+ const n = c[0], l = n.getAttribute("width"), t = n.getAttribute("height"), e = !!(l && t && o.test(l) && o.test(t));
7
+ let s = null;
8
+ if (!e) {
9
+ const i = n.style.height || t;
10
+ if (i)
11
+ if (o.test(i))
12
+ s = `${i}px`;
13
+ else
14
+ try {
15
+ const r = u(i);
16
+ r && r.unit && r.unit !== "%" && (s = i);
17
+ } catch (r) {
18
+ }
19
+ }
20
+ return {
21
+ iframe: n,
22
+ isStaticSize: e,
23
+ width: e ? l : null,
24
+ height: e ? t : null,
25
+ aspectRatio: e ? `${l} / ${t}` : null,
26
+ fillHeight: s
27
+ };
28
+ }
29
+ return null;
30
+ }
31
+ export {
32
+ h as getSoleIframeLayout
33
+ };
@@ -1,5 +1,6 @@
1
1
  export { FileSave } from './file-save.js';
2
2
  export { configureIcons as fontAwesomeConfigureIcons } from './font-awesome.js';
3
+ export { getSoleIframeLayout } from './iframe.js';
3
4
  export { set as classLoggerSet, log as classLoggerLog, logWarning as classLoggerLogWarning, logError as classLoggerLogError } from './class-logger.js';
4
5
  export { dataAttributeToDatasetKey, setPositionClasses, resolveClasses } from './dom.js';
5
6
  export { defaults as floatingUiDefaults, createFloatingUi } from './floating-ui.js';