@nysds/nys-globalfooter 1.19.1 → 1.19.3

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.
@@ -0,0 +1,88 @@
1
+ import { LitElement } from "lit";
2
+ /**
3
+ * Agency-branded footer with agency name and slotted content sections. Auto-layouts based on content structure.
4
+ *
5
+ * Place above `nys-unavfooter`. Slot contact info, links, or other content. Use `<h4>` elements
6
+ * to create multi-column layouts; without `<h4>`, renders as compact single section.
7
+ *
8
+ * @summary Agency footer with auto-layout for contact info and link sections.
9
+ * @element nys-globalfooter
10
+ *
11
+ * @slot - Footer content (links, contact info). Use `<h4>` for column headings.
12
+ *
13
+ * @example Basic
14
+ * ```html
15
+ * <nys-globalfooter agencyName="Office of Information Technology Services"></nys-globalfooter>
16
+ * ```
17
+ *
18
+ * @example Homepage Link
19
+ * ```html
20
+ * <nys-globalfooter
21
+ * agencyName="Office of Information Technology Services"
22
+ * homepageLink="https://its.ny.gov"
23
+ * ></nys-globalfooter>
24
+ * ```
25
+ *
26
+ * @example Menu Links
27
+ * ```html
28
+ * <nys-globalfooter agencyName="Office of Information Technology Services">
29
+ * <ul>
30
+ * <li><a href="https://its.ny.gov">ITS Home</a></li>
31
+ * <li><a href="https://its.ny.gov/about-us">About ITS</a></li>
32
+ * </ul>
33
+ * </nys-globalfooter>
34
+ * ```
35
+ *
36
+ * @example Column Links
37
+ * ```html
38
+ * <nys-globalfooter agencyName="Office of Information Technology Services">
39
+ * <ul>
40
+ * <li>
41
+ * <span>About</span>
42
+ * <ul>
43
+ * <li><a href="https://its.ny.gov/about-us">About ITS</a></li>
44
+ * <li><a href="https://its.ny.gov/contact-us">Contact</a></li>
45
+ * <li><a href="https://its.ny.gov/policies">Policies</a></li>
46
+ * </ul>
47
+ * </li>
48
+ * <li>
49
+ * <span>Resources</span>
50
+ * <ul>
51
+ * <li><a href="https://its.ny.gov/resources">Developer Tools</a></li>
52
+ * <li><a href="https://its.ny.gov/accessibility">Accessibility</a></li>
53
+ * <li><a href="https://its.ny.gov/privacy">Privacy</a></li>
54
+ * </ul>
55
+ * </li>
56
+ * </ul>
57
+ * </nys-globalfooter>
58
+ * ```
59
+ *
60
+ * @example Subheading
61
+ * ```html
62
+ * <nys-globalfooter
63
+ * agencyName="Office of Information Technology Services"
64
+ * agencySubheading="Innovating Technology for a Better New York"
65
+ * ></nys-globalfooter>
66
+ * ```
67
+ */
68
+ export declare class NysGlobalFooter extends LitElement {
69
+ static styles: import("lit").CSSResult;
70
+ /** Agency name displayed as the footer heading. */
71
+ agencyName: string;
72
+ /** Optional subheading displayed below the agency name. */
73
+ agencySubheading: string;
74
+ /** URL for the agency name link. If empty, name is not clickable. */
75
+ homepageLink: string;
76
+ private slotHasContent;
77
+ /**
78
+ * Lifecycle Methods
79
+ * --------------------------------------------------------------------------
80
+ */
81
+ firstUpdated(): void;
82
+ /**
83
+ * Functions
84
+ * --------------------------------------------------------------------------
85
+ */
86
+ private _handleSlotChange;
87
+ render(): import("lit-html").TemplateResult<1>;
88
+ }
@@ -1,24 +1,24 @@
1
- import { LitElement as h, unsafeCSS as m, html as i } from "lit";
2
- import { property as c, state as b } from "lit/decorators.js";
1
+ import { LitElement as h, unsafeCSS as b, nothing as _, html as i } from "lit";
2
+ import { property as f, state as m } from "lit/decorators.js";
3
3
  /*!
4
4
  * █▄ █ █ █ █▀▀▀█ █▀▀▄ █▀▀▀█
5
5
  * █ █ █ █▄▄▄█ ▀▀▀▄▄ █ █ ▀▀▀▄▄
6
6
  * █ ▀█ █ █▄▄▄█ █▄▄▀ █▄▄▄█
7
7
  *
8
- * Global Footer Component v1.19.1
8
+ * Global Footer Component v1.19.3
9
9
  * Part of the New York State Design System
10
10
  * Repository: https://github.com/its-hcd/nysds
11
11
  * License: MIT
12
12
  */
13
- const _ = ':host{--_nys-globalfooter-color: var( --nys-color-text, var(--nys-color-neutral-900, #1b1b1b) );--_nys-globalfooter-background-color: var( --nys-color-theme-weaker, var(--nys-color-state-blue-50, #eff6fb) );--_nys-globalfooter-gap: var(--nys-space-300, 24px);--_nys-globalfooter-padding--y: var(--nys-space-400, 32px);--_nys-globalfooter-padding--gutter: var(--nys-gutter-sm, 20px);--_nys-globalfooter-font-size--agency: var( --nys-font-size-agency-xl, var(--nys-font-size-2xl, 22px) );--_nys-globalfooter-font-size--link: var( --nys-font-size-body-md, var(--nys-font-size-md, 16px) );--_nys-globalfooter-line-height--agency: normal;--_nys-globalfooter-font-weight--regular: var(--nys-font-weight-regular, 400);--_nys-globalfooter-font-weight--semibold: var( --nys-font-weight-semibold, 600 );--_nys-globalfooter-max-width: var(--nys-max-content-width, 1280px);--_nys-globalfooter-font-family--agency: var( --nys-font-family-agency, "D Sari", Arial, sans-serif );--_nys-globalfooter-column-gap: var(--nys-space-400, 32px);--_nys-globalfooter-row-gap: var(--nys-space-400, 32px);--_nys-globalfooter-line-height--link: var(--nys-font-lineheight-ui-md, 24px);--_nys-globalfooter-letter-spacing: var( --nys-font-letterspacing-ui-md, var(--nys-font-letterspacing-400, .044px) );--_nys-globalfooter-font-family--link: var( --nys-font-family-ui, var( --nys-font-family-sans, "Proxima Nova", "Helvetica Neue", "Helvetica", "Arial", sans-serif ) );--_nys-globalfooter-text-decoration-thickness: var(--nys-size-2px, 2px);--_nys-globalfooter-background--divider: var(--nys-color-theme, #154973);--_nys-globalfooter-margin--divider: var(--nys-space-50, 4px)}.nys-globalfooter{display:flex;padding:var(--_nys-globalfooter-padding--y) var(--_nys-globalfooter-padding--gutter);justify-content:center;background-color:var(--_nys-globalfooter-background-color);color:var(--_nys-globalfooter-color);width:100%;box-sizing:border-box}.nys-globalfooter__main-container{display:flex;flex-direction:column;gap:var(--_nys-globalfooter-gap);width:100%;max-width:var(--_nys-globalfooter-max-width)}.nys-globalfooter__name{text-align:left;margin:0;color:var(--_nys-globalfooter-color);font-family:var(--_nys-globalfooter-font-family--agency);font-size:var(--_nys-globalfooter-font-size--agency);font-style:normal;font-weight:var(--_nys-globalfooter-font-weight--semibold);line-height:var(--_nys-globalfooter-line-height--agency);letter-spacing:normal}ul{list-style-type:none;padding:0;margin:0}li{margin:0;padding:0}a,span{color:var(--_nys-globalfooter-color);text-decoration:none;font-family:var(--_nys-globalfooter-font-family--link);font-size:var(--_nys-globalfooter-font-size--link);font-style:normal;font-weight:var(--_nys-globalfooter-font-weight--semibold);line-height:var(--_nys-globalfooter-line-height--link);letter-spacing:var(--_nys-globalfooter-letter-spacing)}ul li>span+ul li a{font-weight:var(--_nys-globalfooter-font-weight--regular)}a:hover{text-decoration:underline}a:active{text-decoration-thickness:var(--_nys-globalfooter-text-decoration-thickness)}.nys-globalfooter__content{width:100%}.nys-globalfooter__content ul{display:flex;flex-flow:column wrap;gap:var(--_nys-globalfooter-row-gap) var(--_nys-globalfooter-column-gap)}.nys-globalfooter__content ul li:has(span~ul){flex:1;display:flex;flex-direction:column}.nys-globalfooter__content ul:has(li>span~ul){--_nys-globalfooter-column-gap: var(--nys-space-500, 40px)}.nys-globalfooter__content ul li>span~ul{display:flex;flex-direction:column;gap:var(--nys-space-200, 16px)}.divider{margin-top:var(--_nys-globalfooter-margin--divider);margin-bottom:var(--nys-space-300, 24px)}@media(min-width:768px){.nys-globalfooter__content ul{flex-direction:row}.nys-globalfooter__content ul li:has(span~ul){flex:1 0 205px}:host{--_nys-globalfooter-padding--gutter: var(--nys-gutter-lg, 32px);--_nys-globalfooter-row-gap: var(--nys-space-600, 48px)}}@media(min-width:1280px){:host{--_nys-globalfooter-padding--gutter: var(--nys-gutter-xl, 64px)}}';
14
- var v = Object.defineProperty, g = (y, a, l, n) => {
15
- for (var o = void 0, e = y.length - 1, t; e >= 0; e--)
16
- (t = y[e]) && (o = t(a, l, o) || o);
17
- return o && v(a, l, o), o;
13
+ const v = ':host{--_nys-globalfooter-color: var( --nys-color-text, var(--nys-color-neutral-900, #1b1b1b) );--_nys-globalfooter-background-color: var( --nys-color-theme-weaker, var(--nys-color-state-blue-50, #eff6fb) );--_nys-globalfooter-gap: var(--nys-space-300, 24px);--_nys-globalfooter-gap--heading-container: var(--nys-space-150, 12px);--_nys-globalfooter-padding--y: var(--nys-space-400, 32px);--_nys-globalfooter-padding--gutter: var(--nys-gutter-sm, 20px);--_nys-globalfooter-font-size--agency: var( --nys-font-size-agency-xl, var(--nys-font-size-2xl, 22px) );--_nys-globalfooter-font-size--link: var( --nys-font-size-body-md, var(--nys-font-size-md, 16px) );--_nys-globalfooter-line-height--agency: normal;--_nys-globalfooter-font-weight--regular: var(--nys-font-weight-regular, 400);--_nys-globalfooter-font-weight--semibold: var( --nys-font-weight-semibold, 600 );--_nys-globalfooter-max-width: var(--nys-max-content-width, 1280px);--_nys-globalfooter-font-family--agency: var( --nys-font-family-agency, "D Sari", Arial, sans-serif );--_nys-globalfooter-column-gap: var(--nys-space-400, 32px);--_nys-globalfooter-row-gap: var(--nys-space-400, 32px);--_nys-globalfooter-line-height--link: var(--nys-font-lineheight-ui-md, 24px);--_nys-globalfooter-letter-spacing: var( --nys-font-letterspacing-ui-md, var(--nys-font-letterspacing-400, .044px) );--_nys-globalfooter-font-family--link: var( --nys-font-family-ui, var( --nys-font-family-sans, "Proxima Nova", "Helvetica Neue", "Helvetica", "Arial", sans-serif ) );--_nys-globalfooter-text-decoration-thickness: var(--nys-size-2px, 2px);--_nys-globalfooter-background--divider: var(--nys-color-theme, #154973);--_nys-globalfooter-margin--divider: var(--nys-space-50, 4px)}.nys-globalfooter{display:flex;padding:var(--_nys-globalfooter-padding--y) var(--_nys-globalfooter-padding--gutter);justify-content:center;background-color:var(--_nys-globalfooter-background-color);color:var(--_nys-globalfooter-color);width:100%;box-sizing:border-box}.nys-globalfooter .nys-globalfooter__main-container{display:flex;flex-direction:column;gap:var(--_nys-globalfooter-gap);width:100%;max-width:var(--_nys-globalfooter-max-width)}.nys-globalfooter .nys-globalfooter__main-container .nys-globalfooter__heading-container{display:flex;flex-direction:column;gap:var(--_nys-globalfooter-gap--heading-container)}.nys-globalfooter .nys-globalfooter__main-container .nys-globalfooter__heading-container .nys-globalfooter__name{text-align:left;margin:0;color:var(--_nys-globalfooter-color);font-family:var(--_nys-globalfooter-font-family--agency);font-size:var(--_nys-globalfooter-font-size--agency);font-style:normal;font-weight:var(--_nys-globalfooter-font-weight--semibold);line-height:var(--_nys-globalfooter-line-height--agency);letter-spacing:normal}.nys-globalfooter .nys-globalfooter__main-container .nys-globalfooter__heading-container .nys-globalfooter__subheading{margin:0}ul{list-style-type:none;padding:0;margin:0}li{margin:0;padding:0}a,span{color:var(--_nys-globalfooter-color);text-decoration:none;font-family:var(--_nys-globalfooter-font-family--link);font-size:var(--_nys-globalfooter-font-size--link);font-style:normal;font-weight:var(--_nys-globalfooter-font-weight--semibold);line-height:var(--_nys-globalfooter-line-height--link);letter-spacing:var(--_nys-globalfooter-letter-spacing)}ul li>span+ul li a{font-weight:var(--_nys-globalfooter-font-weight--regular)}a:hover{text-decoration:underline}a:active{text-decoration-thickness:var(--_nys-globalfooter-text-decoration-thickness)}.nys-globalfooter__content{width:100%}.nys-globalfooter__content ul{display:flex;flex-flow:column wrap;gap:var(--_nys-globalfooter-row-gap) var(--_nys-globalfooter-column-gap)}.nys-globalfooter__content ul li:has(span~ul){flex:1;display:flex;flex-direction:column}.nys-globalfooter__content ul:has(li>span~ul){--_nys-globalfooter-column-gap: var(--nys-space-500, 40px)}.nys-globalfooter__content ul li>span~ul{display:flex;flex-direction:column;gap:var(--nys-space-200, 16px)}.divider{margin-top:var(--_nys-globalfooter-margin--divider);margin-bottom:var(--nys-space-300, 24px)}@media(min-width:768px){.nys-globalfooter__content ul{flex-direction:row}.nys-globalfooter__content ul li:has(span~ul){flex:1 0 205px}:host{--_nys-globalfooter-padding--gutter: var(--nys-gutter-lg, 32px);--_nys-globalfooter-row-gap: var(--nys-space-600, 48px)}}@media(min-width:1280px){:host{--_nys-globalfooter-padding--gutter: var(--nys-gutter-xl, 64px)}}';
14
+ var u = Object.defineProperty, g = (c, l, s, t) => {
15
+ for (var o = void 0, e = c.length - 1, n; e >= 0; e--)
16
+ (n = c[e]) && (o = n(l, s, o) || o);
17
+ return o && u(l, s, o), o;
18
18
  };
19
- const f = class f extends h {
19
+ const y = class y extends h {
20
20
  constructor() {
21
- super(...arguments), this.agencyName = "", this.homepageLink = "", this.slotHasContent = !0;
21
+ super(...arguments), this.agencyName = "", this.agencySubheading = "", this.homepageLink = "", this.slotHasContent = !0;
22
22
  }
23
23
  /**
24
24
  * Lifecycle Methods
@@ -33,34 +33,39 @@ const f = class f extends h {
33
33
  */
34
34
  // Gets called when the slot content changes and directly appends the slotted elements into the shadow DOM
35
35
  async _handleSlotChange() {
36
- const a = this.shadowRoot?.querySelector("slot");
37
- if (!a) return;
38
- const l = a?.assignedNodes({ flatten: !0 }).filter((e) => e.nodeType === Node.ELEMENT_NODE);
39
- await Promise.resolve(), this.slotHasContent = l.length > 0;
40
- const n = this.shadowRoot?.querySelector(
36
+ const l = this.shadowRoot?.querySelector("slot");
37
+ if (!l) return;
38
+ const s = l?.assignedNodes({ flatten: !0 }).filter((e) => e.nodeType === Node.ELEMENT_NODE);
39
+ await Promise.resolve(), this.slotHasContent = s.length > 0;
40
+ const t = this.shadowRoot?.querySelector(
41
41
  ".nys-globalfooter__content"
42
- ), o = l?.some(
42
+ ), o = s?.some(
43
43
  (e) => e.tagName === "H4"
44
44
  );
45
- n && (n.classList.toggle("columns", o), n.classList.toggle("small", !o), n.innerHTML = "", l.forEach((t) => {
46
- if (t.nodeType === Node.ELEMENT_NODE) {
47
- const r = t.cloneNode(!0);
45
+ t && (t.classList.toggle("columns", o), t.classList.toggle("small", !o), t.innerHTML = "", s.forEach((n) => {
46
+ if (n.nodeType === Node.ELEMENT_NODE) {
47
+ const r = n.cloneNode(!0);
48
48
  ["script", "iframe", "object", "embed", "img"].forEach((d) => {
49
49
  r.querySelectorAll(d).forEach((p) => p.remove());
50
- }), n.appendChild(r), t.remove();
50
+ }), t.appendChild(r), n.remove();
51
51
  }
52
- }), n.querySelectorAll("span").forEach((t) => {
52
+ }), t.querySelectorAll("span").forEach((n) => {
53
53
  const r = document.createElement("nys-divider");
54
- r.classList.add("divider"), t.insertAdjacentElement("afterend", r);
54
+ r.classList.add("divider"), n.insertAdjacentElement("afterend", r);
55
55
  }));
56
56
  }
57
57
  render() {
58
58
  return i`
59
59
  <footer class="nys-globalfooter">
60
60
  <div class="nys-globalfooter__main-container">
61
- ${this.homepageLink?.trim() ? i`<a href=${this.homepageLink?.trim()}>
62
- <h2 class="nys-globalfooter__name">${this.agencyName}</h2>
63
- </a>` : i`<h2 class="nys-globalfooter__name">${this.agencyName}</h2>`}
61
+ <div class="nys-globalfooter__heading-container">
62
+ ${this.homepageLink?.trim() ? i`<a href=${this.homepageLink?.trim()}>
63
+ <h2 class="nys-globalfooter__name">${this.agencyName}</h2>
64
+ </a>` : i`<h2 class="nys-globalfooter__name">${this.agencyName}</h2>`}
65
+ ${this.agencySubheading ? i`<p class="nys-globalfooter__subheading">
66
+ ${this.agencySubheading}
67
+ </p>` : _}
68
+ </div>
64
69
  ${this.slotHasContent ? i`<div class="nys-globalfooter__content">
65
70
  <slot
66
71
  style="display: hidden"
@@ -72,19 +77,22 @@ const f = class f extends h {
72
77
  `;
73
78
  }
74
79
  };
75
- f.styles = m(_);
76
- let s = f;
80
+ y.styles = b(v);
81
+ let a = y;
77
82
  g([
78
- c({ type: String })
79
- ], s.prototype, "agencyName");
83
+ f({ type: String })
84
+ ], a.prototype, "agencyName");
80
85
  g([
81
- c({ type: String })
82
- ], s.prototype, "homepageLink");
86
+ f({ type: String })
87
+ ], a.prototype, "agencySubheading");
83
88
  g([
84
- b()
85
- ], s.prototype, "slotHasContent");
86
- customElements.get("nys-globalfooter") || customElements.define("nys-globalfooter", s);
89
+ f({ type: String })
90
+ ], a.prototype, "homepageLink");
91
+ g([
92
+ m()
93
+ ], a.prototype, "slotHasContent");
94
+ customElements.get("nys-globalfooter") || customElements.define("nys-globalfooter", a);
87
95
  export {
88
- s as NysGlobalFooter
96
+ a as NysGlobalFooter
89
97
  };
90
98
  //# sourceMappingURL=nys-globalfooter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"nys-globalfooter.js","sources":["../src/nys-globalfooter.ts"],"sourcesContent":["import { LitElement, html, unsafeCSS } from \"lit\";\nimport { property, state } from \"lit/decorators.js\";\n// @ts-ignore: SCSS module imported via bundler as inline\nimport styles from \"./nys-globalfooter.scss?inline\";\n\n/**\n * Agency-branded footer with agency name and slotted content sections. Auto-layouts based on content structure.\n *\n * Place above `nys-unavfooter`. Slot contact info, links, or other content. Use `<h4>` elements\n * to create multi-column layouts; without `<h4>`, renders as compact single section.\n *\n * @summary Agency footer with auto-layout for contact info and link sections.\n * @element nys-globalfooter\n *\n * @slot - Footer content (links, contact info). Use `<h4>` for column headings.\n *\n * @example Simple footer\n * ```html\n * <nys-globalfooter agencyName=\"Department of Health\" homepageLink=\"/\">\n * <span>123 Main St, Albany NY</span>\n * <span>info@health.ny.gov</span>\n * </nys-globalfooter>\n * ```\n */\n\nexport class NysGlobalFooter extends LitElement {\n static styles = unsafeCSS(styles);\n\n /** Agency name displayed as the footer heading. */\n @property({ type: String }) agencyName = \"\";\n\n /** URL for the agency name link. If empty, name is not clickable. */\n @property({ type: String }) homepageLink = \"\";\n @state() private slotHasContent = true;\n\n /**\n * Lifecycle Methods\n * --------------------------------------------------------------------------\n */\n\n firstUpdated() {\n // Check for slot content after rendering\n const slot = this.shadowRoot?.querySelector<HTMLSlotElement>(\"slot\");\n slot?.addEventListener(\"slotchange\", () => this._handleSlotChange());\n this._handleSlotChange(); // Initial check\n }\n\n /**\n * Functions\n * --------------------------------------------------------------------------\n */\n\n // Gets called when the slot content changes and directly appends the slotted elements into the shadow DOM\n private async _handleSlotChange() {\n const slot = this.shadowRoot?.querySelector<HTMLSlotElement>(\"slot\");\n if (!slot) return;\n\n const assignedNodes = slot\n ?.assignedNodes({ flatten: true })\n .filter((node) => node.nodeType === Node.ELEMENT_NODE) as Element[]; // Filter to elements only\n\n await Promise.resolve(); // Wait for current update cycle to complete before modifying reactive state (solves the lit issue \"scheduled an update\")\n\n this.slotHasContent = assignedNodes.length > 0;\n\n // Determine layout based on content structure\n const container = this.shadowRoot?.querySelector(\n \".nys-globalfooter__content\",\n );\n const hasMultipleGroups = assignedNodes?.some(\n (node) => node.tagName === \"H4\",\n );\n\n // Toggle layout classes\n if (container) {\n container.classList.toggle(\"columns\", hasMultipleGroups);\n container.classList.toggle(\"small\", !hasMultipleGroups);\n\n container.innerHTML = \"\";\n\n // Clone and append slotted elements into the shadow DOM container\n assignedNodes.forEach((node) => {\n if (node.nodeType === Node.ELEMENT_NODE) {\n const cleanNode = node.cloneNode(true);\n\n // Remove <script>, <iframe>, <object>, and any potentially dangerous elements XSS\n const dangerousTags = [\"script\", \"iframe\", \"object\", \"embed\", \"img\"];\n dangerousTags.forEach((tag) => {\n (cleanNode as Element)\n .querySelectorAll(tag)\n .forEach((element) => element.remove());\n });\n container.appendChild(cleanNode);\n node.remove(); // Remove from light DOM to avoid duplication\n }\n });\n\n const spans = container.querySelectorAll(\"span\");\n spans.forEach((span) => {\n const divider = document.createElement(\"nys-divider\");\n divider.classList.add(\"divider\");\n span.insertAdjacentElement(\"afterend\", divider);\n });\n }\n }\n\n render() {\n return html`\n <footer class=\"nys-globalfooter\">\n <div class=\"nys-globalfooter__main-container\">\n ${!this.homepageLink?.trim()\n ? html`<h2 class=\"nys-globalfooter__name\">${this.agencyName}</h2>`\n : html`<a href=${this.homepageLink?.trim()}>\n <h2 class=\"nys-globalfooter__name\">${this.agencyName}</h2>\n </a>`}\n ${this.slotHasContent\n ? html`<div class=\"nys-globalfooter__content\">\n <slot\n style=\"display: hidden\"\n @slotchange=\"${this._handleSlotChange}\"\n ></slot>\n </div>`\n : \"\"}\n </div>\n </footer>\n `;\n }\n}\n\nif (!customElements.get(\"nys-globalfooter\")) {\n customElements.define(\"nys-globalfooter\", NysGlobalFooter);\n}\n"],"names":["_NysGlobalFooter","LitElement","slot","assignedNodes","node","container","hasMultipleGroups","cleanNode","tag","element","span","divider","html","unsafeCSS","styles","NysGlobalFooter","__decorateClass","property","state"],"mappings":";;;;;;;;;;;;;;;;;;AAyBO,MAAMA,IAAN,MAAMA,UAAwBC,EAAW;AAAA,EAAzC,cAAA;AAAA,UAAA,GAAA,SAAA,GAIuB,KAAA,aAAa,IAGb,KAAA,eAAe,IAClC,KAAQ,iBAAiB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOlC,eAAe;AAGb,IADa,KAAK,YAAY,cAA+B,MAAM,GAC7D,iBAAiB,cAAc,MAAM,KAAK,mBAAmB,GACnE,KAAK,kBAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,oBAAoB;AAChC,UAAMC,IAAO,KAAK,YAAY,cAA+B,MAAM;AACnE,QAAI,CAACA,EAAM;AAEX,UAAMC,IAAgBD,GAClB,cAAc,EAAE,SAAS,GAAA,CAAM,EAChC,OAAO,CAACE,MAASA,EAAK,aAAa,KAAK,YAAY;AAEvD,UAAM,QAAQ,QAAA,GAEd,KAAK,iBAAiBD,EAAc,SAAS;AAG7C,UAAME,IAAY,KAAK,YAAY;AAAA,MACjC;AAAA,IAAA,GAEIC,IAAoBH,GAAe;AAAA,MACvC,CAACC,MAASA,EAAK,YAAY;AAAA,IAAA;AAI7B,IAAIC,MACFA,EAAU,UAAU,OAAO,WAAWC,CAAiB,GACvDD,EAAU,UAAU,OAAO,SAAS,CAACC,CAAiB,GAEtDD,EAAU,YAAY,IAGtBF,EAAc,QAAQ,CAACC,MAAS;AAC9B,UAAIA,EAAK,aAAa,KAAK,cAAc;AACvC,cAAMG,IAAYH,EAAK,UAAU,EAAI;AAIrC,QADsB,CAAC,UAAU,UAAU,UAAU,SAAS,KAAK,EACrD,QAAQ,CAACI,MAAQ;AAC5B,UAAAD,EACE,iBAAiBC,CAAG,EACpB,QAAQ,CAACC,MAAYA,EAAQ,QAAQ;AAAA,QAC1C,CAAC,GACDJ,EAAU,YAAYE,CAAS,GAC/BH,EAAK,OAAA;AAAA,MACP;AAAA,IACF,CAAC,GAEaC,EAAU,iBAAiB,MAAM,EACzC,QAAQ,CAACK,MAAS;AACtB,YAAMC,IAAU,SAAS,cAAc,aAAa;AACpD,MAAAA,EAAQ,UAAU,IAAI,SAAS,GAC/BD,EAAK,sBAAsB,YAAYC,CAAO;AAAA,IAChD,CAAC;AAAA,EAEL;AAAA,EAEA,SAAS;AACP,WAAOC;AAAA;AAAA;AAAA,YAGE,KAAK,cAAc,KAAA,IAElBA,YAAe,KAAK,cAAc,MAAM;AAAA,qDACD,KAAK,UAAU;AAAA,sBAFtDA,uCAA0C,KAAK,UAAU,OAGpD;AAAA,YACP,KAAK,iBACHA;AAAA;AAAA;AAAA,iCAGmB,KAAK,iBAAiB;AAAA;AAAA,wBAGzC,EAAE;AAAA;AAAA;AAAA;AAAA,EAId;AACF;AArGEZ,EAAO,SAASa,EAAUC,CAAM;AAD3B,IAAMC,IAANf;AAIuBgB,EAAA;AAAA,EAA3BC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAJfF,EAIiB,WAAA,YAAA;AAGAC,EAAA;AAAA,EAA3BC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAPfF,EAOiB,WAAA,cAAA;AACXC,EAAA;AAAA,EAAhBE,EAAA;AAAM,GARIH,EAQM,WAAA,gBAAA;AAgGd,eAAe,IAAI,kBAAkB,KACxC,eAAe,OAAO,oBAAoBA,CAAe;"}
1
+ {"version":3,"file":"nys-globalfooter.js","sources":["../src/nys-globalfooter.ts"],"sourcesContent":["import { LitElement, html, unsafeCSS, nothing } from \"lit\";\nimport { property, state } from \"lit/decorators.js\";\n// @ts-ignore: SCSS module imported via bundler as inline\nimport styles from \"./nys-globalfooter.scss?inline\";\n\n/**\n * Agency-branded footer with agency name and slotted content sections. Auto-layouts based on content structure.\n *\n * Place above `nys-unavfooter`. Slot contact info, links, or other content. Use `<h4>` elements\n * to create multi-column layouts; without `<h4>`, renders as compact single section.\n *\n * @summary Agency footer with auto-layout for contact info and link sections.\n * @element nys-globalfooter\n *\n * @slot - Footer content (links, contact info). Use `<h4>` for column headings.\n *\n * @example Basic\n * ```html\n * <nys-globalfooter agencyName=\"Office of Information Technology Services\"></nys-globalfooter>\n * ```\n *\n * @example Homepage Link\n * ```html\n * <nys-globalfooter\n * agencyName=\"Office of Information Technology Services\"\n * homepageLink=\"https://its.ny.gov\"\n * ></nys-globalfooter>\n * ```\n *\n * @example Menu Links\n * ```html\n * <nys-globalfooter agencyName=\"Office of Information Technology Services\">\n * <ul>\n * <li><a href=\"https://its.ny.gov\">ITS Home</a></li>\n * <li><a href=\"https://its.ny.gov/about-us\">About ITS</a></li>\n * </ul>\n * </nys-globalfooter>\n * ```\n *\n * @example Column Links\n * ```html\n * <nys-globalfooter agencyName=\"Office of Information Technology Services\">\n * <ul>\n * <li>\n * <span>About</span>\n * <ul>\n * <li><a href=\"https://its.ny.gov/about-us\">About ITS</a></li>\n * <li><a href=\"https://its.ny.gov/contact-us\">Contact</a></li>\n * <li><a href=\"https://its.ny.gov/policies\">Policies</a></li>\n * </ul>\n * </li>\n * <li>\n * <span>Resources</span>\n * <ul>\n * <li><a href=\"https://its.ny.gov/resources\">Developer Tools</a></li>\n * <li><a href=\"https://its.ny.gov/accessibility\">Accessibility</a></li>\n * <li><a href=\"https://its.ny.gov/privacy\">Privacy</a></li>\n * </ul>\n * </li>\n * </ul>\n * </nys-globalfooter>\n * ```\n *\n * @example Subheading\n * ```html\n * <nys-globalfooter\n * agencyName=\"Office of Information Technology Services\"\n * agencySubheading=\"Innovating Technology for a Better New York\"\n * ></nys-globalfooter>\n * ```\n */\n\nexport class NysGlobalFooter extends LitElement {\n static styles = unsafeCSS(styles);\n\n /** Agency name displayed as the footer heading. */\n @property({ type: String }) agencyName = \"\";\n\n /** Optional subheading displayed below the agency name. */\n @property({ type: String }) agencySubheading = \"\";\n\n /** URL for the agency name link. If empty, name is not clickable. */\n @property({ type: String }) homepageLink = \"\";\n @state() private slotHasContent = true;\n\n /**\n * Lifecycle Methods\n * --------------------------------------------------------------------------\n */\n\n firstUpdated() {\n // Check for slot content after rendering\n const slot = this.shadowRoot?.querySelector<HTMLSlotElement>(\"slot\");\n slot?.addEventListener(\"slotchange\", () => this._handleSlotChange());\n this._handleSlotChange(); // Initial check\n }\n\n /**\n * Functions\n * --------------------------------------------------------------------------\n */\n\n // Gets called when the slot content changes and directly appends the slotted elements into the shadow DOM\n private async _handleSlotChange() {\n const slot = this.shadowRoot?.querySelector<HTMLSlotElement>(\"slot\");\n if (!slot) return;\n\n const assignedNodes = slot\n ?.assignedNodes({ flatten: true })\n .filter((node) => node.nodeType === Node.ELEMENT_NODE) as Element[]; // Filter to elements only\n\n await Promise.resolve(); // Wait for current update cycle to complete before modifying reactive state (solves the lit issue \"scheduled an update\")\n\n this.slotHasContent = assignedNodes.length > 0;\n\n // Determine layout based on content structure\n const container = this.shadowRoot?.querySelector(\n \".nys-globalfooter__content\",\n );\n const hasMultipleGroups = assignedNodes?.some(\n (node) => node.tagName === \"H4\",\n );\n\n // Toggle layout classes\n if (container) {\n container.classList.toggle(\"columns\", hasMultipleGroups);\n container.classList.toggle(\"small\", !hasMultipleGroups);\n\n container.innerHTML = \"\";\n\n // Clone and append slotted elements into the shadow DOM container\n assignedNodes.forEach((node) => {\n if (node.nodeType === Node.ELEMENT_NODE) {\n const cleanNode = node.cloneNode(true);\n\n // Remove <script>, <iframe>, <object>, and any potentially dangerous elements XSS\n const dangerousTags = [\"script\", \"iframe\", \"object\", \"embed\", \"img\"];\n dangerousTags.forEach((tag) => {\n (cleanNode as Element)\n .querySelectorAll(tag)\n .forEach((element) => element.remove());\n });\n container.appendChild(cleanNode);\n node.remove(); // Remove from light DOM to avoid duplication\n }\n });\n\n const spans = container.querySelectorAll(\"span\");\n spans.forEach((span) => {\n const divider = document.createElement(\"nys-divider\");\n divider.classList.add(\"divider\");\n span.insertAdjacentElement(\"afterend\", divider);\n });\n }\n }\n\n render() {\n return html`\n <footer class=\"nys-globalfooter\">\n <div class=\"nys-globalfooter__main-container\">\n <div class=\"nys-globalfooter__heading-container\">\n ${!this.homepageLink?.trim()\n ? html`<h2 class=\"nys-globalfooter__name\">${this.agencyName}</h2>`\n : html`<a href=${this.homepageLink?.trim()}>\n <h2 class=\"nys-globalfooter__name\">${this.agencyName}</h2>\n </a>`}\n ${this.agencySubheading\n ? html`<p class=\"nys-globalfooter__subheading\">\n ${this.agencySubheading}\n </p>`\n : nothing}\n </div>\n ${this.slotHasContent\n ? html`<div class=\"nys-globalfooter__content\">\n <slot\n style=\"display: hidden\"\n @slotchange=\"${this._handleSlotChange}\"\n ></slot>\n </div>`\n : \"\"}\n </div>\n </footer>\n `;\n }\n}\n\nif (!customElements.get(\"nys-globalfooter\")) {\n customElements.define(\"nys-globalfooter\", NysGlobalFooter);\n}\n"],"names":["_NysGlobalFooter","LitElement","slot","assignedNodes","node","container","hasMultipleGroups","cleanNode","tag","element","span","divider","html","nothing","unsafeCSS","styles","NysGlobalFooter","__decorateClass","property","state"],"mappings":";;;;;;;;;;;;;;;;;;AAwEO,MAAMA,IAAN,MAAMA,UAAwBC,EAAW;AAAA,EAAzC,cAAA;AAAA,UAAA,GAAA,SAAA,GAIuB,KAAA,aAAa,IAGb,KAAA,mBAAmB,IAGnB,KAAA,eAAe,IAClC,KAAQ,iBAAiB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOlC,eAAe;AAGb,IADa,KAAK,YAAY,cAA+B,MAAM,GAC7D,iBAAiB,cAAc,MAAM,KAAK,mBAAmB,GACnE,KAAK,kBAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,oBAAoB;AAChC,UAAMC,IAAO,KAAK,YAAY,cAA+B,MAAM;AACnE,QAAI,CAACA,EAAM;AAEX,UAAMC,IAAgBD,GAClB,cAAc,EAAE,SAAS,GAAA,CAAM,EAChC,OAAO,CAACE,MAASA,EAAK,aAAa,KAAK,YAAY;AAEvD,UAAM,QAAQ,QAAA,GAEd,KAAK,iBAAiBD,EAAc,SAAS;AAG7C,UAAME,IAAY,KAAK,YAAY;AAAA,MACjC;AAAA,IAAA,GAEIC,IAAoBH,GAAe;AAAA,MACvC,CAACC,MAASA,EAAK,YAAY;AAAA,IAAA;AAI7B,IAAIC,MACFA,EAAU,UAAU,OAAO,WAAWC,CAAiB,GACvDD,EAAU,UAAU,OAAO,SAAS,CAACC,CAAiB,GAEtDD,EAAU,YAAY,IAGtBF,EAAc,QAAQ,CAACC,MAAS;AAC9B,UAAIA,EAAK,aAAa,KAAK,cAAc;AACvC,cAAMG,IAAYH,EAAK,UAAU,EAAI;AAIrC,QADsB,CAAC,UAAU,UAAU,UAAU,SAAS,KAAK,EACrD,QAAQ,CAACI,MAAQ;AAC5B,UAAAD,EACE,iBAAiBC,CAAG,EACpB,QAAQ,CAACC,MAAYA,EAAQ,QAAQ;AAAA,QAC1C,CAAC,GACDJ,EAAU,YAAYE,CAAS,GAC/BH,EAAK,OAAA;AAAA,MACP;AAAA,IACF,CAAC,GAEaC,EAAU,iBAAiB,MAAM,EACzC,QAAQ,CAACK,MAAS;AACtB,YAAMC,IAAU,SAAS,cAAc,aAAa;AACpD,MAAAA,EAAQ,UAAU,IAAI,SAAS,GAC/BD,EAAK,sBAAsB,YAAYC,CAAO;AAAA,IAChD,CAAC;AAAA,EAEL;AAAA,EAEA,SAAS;AACP,WAAOC;AAAA;AAAA;AAAA;AAAA,cAII,KAAK,cAAc,KAAA,IAElBA,YAAe,KAAK,cAAc,MAAM;AAAA,uDACD,KAAK,UAAU;AAAA,wBAFtDA,uCAA0C,KAAK,UAAU,OAGpD;AAAA,cACP,KAAK,mBACHA;AAAA,oBACI,KAAK,gBAAgB;AAAA,wBAEzBC,CAAO;AAAA;AAAA,YAEX,KAAK,iBACHD;AAAA;AAAA;AAAA,iCAGmB,KAAK,iBAAiB;AAAA;AAAA,wBAGzC,EAAE;AAAA;AAAA;AAAA;AAAA,EAId;AACF;AA/GEZ,EAAO,SAASc,EAAUC,CAAM;AAD3B,IAAMC,IAANhB;AAIuBiB,EAAA;AAAA,EAA3BC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAJfF,EAIiB,WAAA,YAAA;AAGAC,EAAA;AAAA,EAA3BC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAPfF,EAOiB,WAAA,kBAAA;AAGAC,EAAA;AAAA,EAA3BC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAVfF,EAUiB,WAAA,cAAA;AACXC,EAAA;AAAA,EAAhBE,EAAA;AAAM,GAXIH,EAWM,WAAA,gBAAA;AAuGd,eAAe,IAAI,kBAAkB,KACxC,eAAe,OAAO,oBAAoBA,CAAe;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nysds/nys-globalfooter",
3
- "version": "1.19.1",
3
+ "version": "1.19.3",
4
4
  "description": "The Globalfooter component from the NYS Design System.",
5
5
  "module": "dist/nys-globalfooter.js",
6
6
  "types": "dist/index.d.ts",
@@ -23,7 +23,7 @@
23
23
  "lit-analyze": "lit-analyzer '**/*.ts'"
24
24
  },
25
25
  "dependencies": {
26
- "@nysds/nys-divider": "^1.19.1"
26
+ "@nysds/nys-divider": "^1.19.3"
27
27
  },
28
28
  "devDependencies": {
29
29
  "lit": "^3.3.1",
@@ -39,5 +39,9 @@
39
39
  "globalfooter"
40
40
  ],
41
41
  "author": "New York State Design System Team",
42
- "license": "MIT"
42
+ "license": "MIT",
43
+ "sideEffects": true,
44
+ "peerDependencies": {
45
+ "lit": "^3.3.1"
46
+ }
43
47
  }