@wavelengthusaf/web-components 1.3.0 → 1.4.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.
@@ -4066,9 +4066,273 @@ if (!customElements.get("wavelength-date-picker")) {
4066
4066
  customElements.define("wavelength-date-picker", WavelengthDatePicker);
4067
4067
  }
4068
4068
 
4069
- // src/web-components/wavelength-multi-select-autocomplete.ts
4069
+ // src/web-components/wavelength-notification-panel.ts
4070
4070
  var template4 = document.createElement("template");
4071
4071
  template4.innerHTML = `
4072
+ <style>
4073
+ :host {
4074
+ display: flex;
4075
+ flex-direction: column;
4076
+ align-items: stretch;
4077
+ height: 100%;
4078
+ }
4079
+ :host([open]) .dropdown-panel {
4080
+ display: flex;
4081
+ }
4082
+
4083
+ .pill {
4084
+ display: inline-flex;
4085
+ position: relative;
4086
+ overflow: hidden;
4087
+ border: 1px solid #d3d3d3;
4088
+ border-radius: 0.25rem;
4089
+ background-color: #ffffff;
4090
+ color: black;
4091
+ cursor: pointer;
4092
+ font-family: "Roboto", "Helvetica", "Arial", sans-serif;
4093
+ font-weight: 500;
4094
+ font-size: 0.875rem;
4095
+ letter-spacing: 0.02857rem;
4096
+ white-space: normal;
4097
+ word-break: break-word;
4098
+ text-align: left;
4099
+ height: auto;
4100
+ width: 125px;
4101
+ line-height: 0.5;
4102
+ height: 80%;
4103
+ border-radius: 6px;
4104
+ }
4105
+
4106
+ .main {
4107
+ display: flex;
4108
+ flex-direction: column;
4109
+ align-items: flex-end;
4110
+ }
4111
+
4112
+ .dot {
4113
+ position: absolute;
4114
+ top: 8px;
4115
+ right: 8px;
4116
+ height: 5px;
4117
+ width: 5px;
4118
+ background-color: #8f0000;
4119
+ border-radius: 50%;
4120
+ z-index: 2;
4121
+ }
4122
+
4123
+ p.notification {
4124
+ color: #d3d3d3;
4125
+ }
4126
+
4127
+ .dropdown-panel {
4128
+ box-sizing: border-box;
4129
+ flex-direction: column;
4130
+ align-items: center;
4131
+ overflow: hidden;
4132
+ border: 1px solid #d3d3d3;
4133
+ border-radius: 0.5rem;
4134
+ background-color: #ffffff;
4135
+ color: black;
4136
+ font-family: "Roboto", "Helvetica", "Arial", sans-serif;
4137
+ font-weight: 500;
4138
+ font-size: 0.875rem;
4139
+ letter-spacing: 0.02857rem;
4140
+ word-break: break-word;
4141
+ text-align: left;
4142
+ height: 220px;
4143
+ width: 325px;
4144
+ line-height: 0.5;
4145
+ margin-top: 8px;
4146
+ display: none;
4147
+ position: absolute;
4148
+ top: 100%; /* opens BELOW navbar */
4149
+ right: 0;
4150
+ z-index: 2000;
4151
+ }
4152
+
4153
+ .dropdown-panel.invisible {
4154
+ display: none;
4155
+ }
4156
+
4157
+ .dropdown-content {
4158
+ display: flex;
4159
+ flex-direction: column;
4160
+ position: relative;
4161
+ overflow: hidden;
4162
+ border: 1px solid #d3d3d3;
4163
+ border-radius: 0.25rem;
4164
+ background-color: #ffffff;
4165
+ color: black;
4166
+ white-space: normal;
4167
+ word-break: break-word;
4168
+ text-align: center;
4169
+ height: 85px;
4170
+ width: 300px;
4171
+ line-height: 0.5;
4172
+ margin-top: 3px;
4173
+ }
4174
+
4175
+ .dropdown-header {
4176
+ padding: 8px;
4177
+ width: 100%;
4178
+ box-sizing: border-box;
4179
+ flex-shrink: 0;
4180
+ font-size: 15px;
4181
+ flew-wrap: nowrap;
4182
+ border: 1px solid pink;
4183
+ }
4184
+
4185
+ .mark-as-read {
4186
+ box-sizing: border-box;
4187
+ flex-shrink: 0;
4188
+ font-size: 10px;
4189
+ background-color: #ffffff;
4190
+ border: none;
4191
+ height: 10px;
4192
+ float: right;
4193
+ text-decoration: underline;
4194
+ cursor: pointer;
4195
+ }
4196
+
4197
+ .dropdown-footer {
4198
+ display: flex;
4199
+ flex-direction: column;
4200
+ flex-shrink: 0;
4201
+ width: 100%;
4202
+ padding: 8px;
4203
+ box-sizing: border-box;
4204
+ }
4205
+
4206
+ .footer-button-settings {
4207
+ margin-top: 8px;
4208
+ border: 1px;
4209
+ width: 100%;
4210
+ height 85px;
4211
+ background-color: #ffffff;
4212
+ display: flex;
4213
+ cursor: pointer;
4214
+ color: #7d7c7cff;
4215
+ font-size: 13px;
4216
+ }
4217
+
4218
+ .footer-button-sign-out {
4219
+ margin-top: 8px;
4220
+ border: 1px;
4221
+ width: 100%;
4222
+ height 85px;
4223
+ background-color: #ffffff;
4224
+ display: flex;
4225
+ cursor: pointer;
4226
+ color: #7d7c7cff;
4227
+ font-size: 13px;
4228
+ }
4229
+
4230
+ .footer-button-settings:hover {
4231
+ background-color: #e0e0e0; /* Light gray on hover */
4232
+ }
4233
+
4234
+ .footer-button-sign-out:hover {
4235
+ background-color: #e0e0e0; /* Light gray on hover */
4236
+ }
4237
+
4238
+ </style>
4239
+ <div class="main">
4240
+ <button class="pill">
4241
+ <div>
4242
+ <p>Your Name</p>
4243
+ <p class="notification">No Notifications</p>
4244
+ </div>
4245
+ </button>
4246
+ <span class="dot"></span>
4247
+ <div class=dropdown-panel>
4248
+ <div class="dropdown-header">
4249
+ <p>Notifications</p>
4250
+ <button class=mark-as-read> Mark As Read </button>
4251
+ </div>
4252
+ <div class="dropdown-content">
4253
+ <p>no notifications</p>
4254
+ </div>
4255
+ <div class=dropdown-footer>
4256
+ <button class=footer-button-settings>Account Settings</button>
4257
+ <button class=footer-button-sign-out>Sign Out</button>
4258
+ </div>
4259
+ </div>
4260
+ </div>
4261
+ `;
4262
+ var WavelengthNotificationPanel = class extends HTMLElement {
4263
+ // List of attributes to observe for changes
4264
+ static get observedAttributes() {
4265
+ return ["notification", "darkMode"];
4266
+ }
4267
+ constructor() {
4268
+ super();
4269
+ const shadow = this.attachShadow({ mode: "open" });
4270
+ shadow.appendChild(template4.content.cloneNode(true));
4271
+ this.panelButton = shadow.querySelector(".pill");
4272
+ this.panel = shadow.querySelector(".dropdown-panel");
4273
+ this.signOutButton = shadow.querySelector(".footer-button-sign-out");
4274
+ this.accountButton = shadow.querySelector(".footer-button-settings");
4275
+ this.markAsRead = shadow.querySelector(".mark-as-read");
4276
+ this.panelButton.addEventListener("click", (event) => {
4277
+ if (this.panelButton.disabled || this.hasAttribute("disabled")) {
4278
+ event.preventDefault();
4279
+ event.stopImmediatePropagation();
4280
+ return;
4281
+ }
4282
+ if (this.hasAttribute("open")) {
4283
+ this.removeAttribute("open");
4284
+ } else {
4285
+ this.setAttribute("open", "");
4286
+ }
4287
+ this.updatePanelVisibility();
4288
+ });
4289
+ this.signOutButton.addEventListener("click", () => {
4290
+ if (typeof this.onSignOut === "function") {
4291
+ this.onSignOut();
4292
+ } else {
4293
+ alert("Insert function to Complete sign out functionality");
4294
+ }
4295
+ });
4296
+ this.accountButton.addEventListener("click", () => {
4297
+ if (typeof this.accountLink === "string") {
4298
+ window.location.href = this.accountLink;
4299
+ } else {
4300
+ alert("Missing the link for an account");
4301
+ }
4302
+ });
4303
+ this.markAsRead.addEventListener("click", () => {
4304
+ if (typeof this.onMarkAsRead === "function") {
4305
+ this.onMarkAsRead();
4306
+ } else {
4307
+ alert("Insert function to clear notifications");
4308
+ }
4309
+ });
4310
+ }
4311
+ // Called when component is inserted into the DOM
4312
+ connectedCallback() {
4313
+ this.updatePanelVisibility();
4314
+ }
4315
+ // Called when observed attributes change
4316
+ attributeChangedCallback() {
4317
+ this.updateComponent();
4318
+ }
4319
+ // Main update logic; Your component's functionality will go here and/or in other methods that you have below
4320
+ updateComponent() {
4321
+ const prop = this.getAttribute("test-prop") || "";
4322
+ }
4323
+ updatePanelVisibility() {
4324
+ if (!this.panel) return;
4325
+ const isOpen = this.hasAttribute("open");
4326
+ this.panel.style.display = isOpen ? "inline-flex" : "none";
4327
+ }
4328
+ };
4329
+ if (!customElements.get("wavelength-notification-panel")) {
4330
+ customElements.define("wavelength-notification-panel", WavelengthNotificationPanel);
4331
+ }
4332
+
4333
+ // src/web-components/wavelength-multi-select-autocomplete.ts
4334
+ var template5 = document.createElement("template");
4335
+ template5.innerHTML = `
4072
4336
  <style>
4073
4337
  .multi-select-container {
4074
4338
  background-color: white;
@@ -4310,7 +4574,7 @@ var BaseWavelengthMultiSelectAutocomplete = class extends HTMLElement {
4310
4574
  this._internals = this.attachInternals();
4311
4575
  this._internals.role = "combobox";
4312
4576
  const shadow = this.attachShadow({ mode: "open" });
4313
- shadow.appendChild(template4.content.cloneNode(true));
4577
+ shadow.appendChild(template5.content.cloneNode(true));
4314
4578
  this._container = this.shadowRoot.querySelector(".multi-select-container");
4315
4579
  this._inputWrapper = this.shadowRoot.querySelector(".multi-select-input-wrapper");
4316
4580
  this._input = this.shadowRoot.querySelector(".multi-select-input");
@@ -4527,18 +4791,19 @@ if (!customElements.get("wavelength-multi-select-autocomplete")) {
4527
4791
  }
4528
4792
 
4529
4793
  // src/web-components/wavelength-nav-bar.ts
4530
- var template5 = document.createElement("template");
4531
- template5.innerHTML = `
4794
+ var template6 = document.createElement("template");
4795
+ template6.innerHTML = `
4532
4796
  <style>
4533
4797
  :host {
4534
4798
  display: block;
4535
4799
  font-family: sans-serif;
4800
+ height: 100%;
4536
4801
  }
4537
4802
 
4538
4803
 
4539
4804
  nav {
4540
4805
  display: flex;
4541
- width: 100%;
4806
+ width: 95%;
4542
4807
  height: var(--height, 25px);
4543
4808
  padding: var(--padding, 1rem);
4544
4809
  border-bottom: var(--border, 1px solid #ddd);
@@ -4553,9 +4818,10 @@ template5.innerHTML = `
4553
4818
  justify-content: space-between;
4554
4819
  }
4555
4820
 
4556
- .flex-spacer {
4557
- flex: 8;
4558
- }
4821
+ .nav-center {
4822
+ display: flex;
4823
+ justify-content: center;
4824
+ }
4559
4825
 
4560
4826
  .home {
4561
4827
  flex: 1;
@@ -4588,22 +4854,25 @@ template5.innerHTML = `
4588
4854
 
4589
4855
 
4590
4856
  .settings {
4591
- flex: 1;
4592
- justify-content: flex-end;
4593
- cursor: pointer;
4594
- display: flex;
4595
- align-items: center;
4596
- gap: 0.5rem;
4597
- }
4857
+ flex: 1;
4858
+ justify-content: flex-end;
4859
+ cursor: pointer;
4860
+ display: flex;
4861
+ align-items: center;
4862
+ gap: 0.5rem;
4863
+ }
4598
4864
 
4599
4865
  .profile {
4600
- padding: 0.5rem 0.75rem;
4866
+ padding: var(--padding, 1rem);
4601
4867
  border: 2px solid #ccc;
4602
4868
  border-radius: 6px;
4603
4869
  cursor: pointer;
4604
4870
  display: flex;
4605
4871
  flex-direction: column;
4606
4872
  text-align: center;
4873
+ width: 100%;
4874
+ height: var(--height, 25px);
4875
+ position: fixed;
4607
4876
  }
4608
4877
 
4609
4878
  .profile-name {
@@ -4621,6 +4890,14 @@ template5.innerHTML = `
4621
4890
  gap: 0.5rem;
4622
4891
  flex: 3;
4623
4892
  }
4893
+ .notification-wrapper {
4894
+ position: relative;
4895
+ height: 100%;
4896
+ display: flex;
4897
+
4898
+ }
4899
+
4900
+
4624
4901
  </style>
4625
4902
  <nav>
4626
4903
  <div class="section home" id="logo">
@@ -4644,18 +4921,14 @@ template5.innerHTML = `
4644
4921
  </svg>
4645
4922
  <slot name="home"></slot>
4646
4923
  </div>
4647
- <div class="flex-spacer"></div>
4924
+ <div class="nav-center"></div>
4648
4925
  <div class = "middle-tab-group">
4649
4926
  <div class="tab"><a href="/applications"><slot name="tab">Applications</slot></a></div>
4650
4927
  <div class="tab"><a href="/users"><slot name="tab">Users</slot></a></div>
4651
4928
  <div class="tab"><a href="/apikeys"><slot name="tab">API Keys</slot></a></div>
4652
4929
  </div>
4653
- <div class="flex-spacer"></div>
4654
- <div class="section settings">
4655
- <div class="profile">
4656
- <span class="profile-name">User</span>
4657
- <span class="profile-note">Notifications</span>
4658
- </div>
4930
+ <div class="notification-wrapper">
4931
+ <wavelength-notification-panel ></wavelength-notification-panel>
4659
4932
  </div>
4660
4933
  </nav>
4661
4934
  `;
@@ -4666,7 +4939,7 @@ var WavelengthNavBar = class extends HTMLElement {
4666
4939
  constructor() {
4667
4940
  super();
4668
4941
  const shadow = this.attachShadow({ mode: "open" });
4669
- shadow.appendChild(template5.content.cloneNode(true));
4942
+ shadow.appendChild(template6.content.cloneNode(true));
4670
4943
  _optionalChain([shadow, 'access', _61 => _61.querySelector, 'call', _62 => _62("#logo"), 'optionalAccess', _63 => _63.addEventListener, 'call', _64 => _64("click", () => {
4671
4944
  this.dispatchEvent(new CustomEvent("home-click"));
4672
4945
  })]);
@@ -4680,7 +4953,7 @@ var WavelengthNavBar = class extends HTMLElement {
4680
4953
  this.renderTabs();
4681
4954
  }
4682
4955
  applyStyles() {
4683
- this.style.setProperty("--bg", this.getAttribute("bg-color") || "#fff");
4956
+ this.style.setProperty("--bg", this.getAttribute("bg-color") || "#ffffffff");
4684
4957
  this.style.setProperty("--txt", this.getAttribute("txt-color") || "#000");
4685
4958
  this.style.setProperty("--height", this.getAttribute("height") || "60px");
4686
4959
  this.style.setProperty("--padding", this.getAttribute("padding") || "0 1rem");
@@ -4711,8 +4984,8 @@ if (!customElements.get("wavelength-nav-bar")) {
4711
4984
 
4712
4985
  // src/web-components/wavelength-child-data-table.ts
4713
4986
  var import_react = __toESM(require_react(), 1);
4714
- var template6 = document.createElement("template");
4715
- template6.innerHTML = `
4987
+ var template7 = document.createElement("template");
4988
+ template7.innerHTML = `
4716
4989
 
4717
4990
  <style>
4718
4991
 
@@ -4863,7 +5136,7 @@ var ChildDataTable = class extends HTMLElement {
4863
5136
  <path d="M13.2375 0L7.5 5.725L1.7625 0L0 1.7625L7.5 9.2625L15 1.7625L13.2375 0Z" fill="currentColor"/>
4864
5137
  </svg>`;
4865
5138
  this.shadow = this.attachShadow({ mode: "open" });
4866
- this.shadow.append(template6.content.cloneNode(true));
5139
+ this.shadow.append(template7.content.cloneNode(true));
4867
5140
  }
4868
5141
  static get observedAttributes() {
4869
5142
  return ["table-columns", "table-data", "dropdown-arrow-location", "sort-icon", "dropdown-button-icon"];
@@ -5163,6 +5436,212 @@ if (!customElements.get("wavelength-child-data-table")) {
5163
5436
  customElements.define("wavelength-child-data-table", ChildDataTable);
5164
5437
  }
5165
5438
 
5439
+ // src/web-components/wavelength-file-drop-zone.ts
5440
+ var fileDropZoneTemplate = document.createElement("template");
5441
+ fileDropZoneTemplate.innerHTML = `
5442
+ <style>
5443
+ :host {
5444
+ display: var(--hostDisplay, block);
5445
+ width: var(--hostWidth, 100%);
5446
+ }
5447
+
5448
+ .file-input {
5449
+ display: var(--inputDisplay, none);
5450
+ }
5451
+
5452
+ .file-drop-zone {
5453
+ border: var(--borderWidth, 1px) var(--borderStyle, dashed) var(--borderColor, #596381);
5454
+ border-radius: var(--borderRadius, 8px);
5455
+ padding: var(--padding, 20px);
5456
+ text-align: var(--textAlign, center);
5457
+ background-color: var(--backgroundColor, #242834);
5458
+ cursor: var(--cursor, pointer);
5459
+ transition: var(--transition, border-color 0.3s, background-color 0.3s);
5460
+ display: var(--display, flex);
5461
+ flex-direction: var(--flexDirection, column);
5462
+ align-items: var(--alignItems, center);
5463
+ gap: var(--gap, 10px);
5464
+ }
5465
+
5466
+ .file-drop-zone:hover {
5467
+ border-color: var(--borderHoverColor, #26BABE);
5468
+ background-color: var(--backgroundHoverColor, #242834);
5469
+ }
5470
+
5471
+ .file-drop-zone.dragover {
5472
+ border-color: var(--borderActiveColor, #26BABE);
5473
+ background-color: var(--backgroundActiveColor, #3E455A);
5474
+ }
5475
+
5476
+ .drop-zone-content {
5477
+ display: var(--contentDisplay, flex);
5478
+ flex-direction: var(--contentFlexDirection, column);
5479
+ align-items: var(--contentAlignItems, center);
5480
+ gap: var(--contentGap, 10px);
5481
+ color: var(--textColor, #FFFFFFCC);
5482
+ }
5483
+
5484
+ .drop-zone-content span {
5485
+ font-family: var(--fontFamily, Montserrat);
5486
+ font-style: var(--fontStyle, normal);
5487
+ font-size: var(--fontSize, 12px);
5488
+ line-height: var(--lineHeight, 100%);
5489
+ letter-spacing: var(--letterSpacing, 0%);
5490
+ }
5491
+
5492
+ .drop-zone-icon {
5493
+ width: var(--iconSize, 24px);
5494
+ height: var(--iconSize, 24px);
5495
+ }
5496
+
5497
+ .error-message {
5498
+ color: var(--errorColor, #ff4444);
5499
+ font-family: var(--errorFontFamily, Montserrat);
5500
+ font-size: var(--errorFontSize, 12px);
5501
+ margin-top: var(--errorMarginTop, 10px);
5502
+ }
5503
+ </style>
5504
+ <div class="file-drop-zone">
5505
+ <input type="file" class="file-input">
5506
+ <div class="drop-zone-content">
5507
+ <img class="drop-zone-icon" alt="Drag icon">
5508
+ <span class="drag-text"></span>
5509
+ </div>
5510
+ <div class="error-message"></div>
5511
+ </div>
5512
+ `;
5513
+ var WavelengthFileDropZone = class extends HTMLElement {
5514
+ constructor() {
5515
+ super();
5516
+ this.dropZone = null;
5517
+ this.fileInput = null;
5518
+ this.dragText = null;
5519
+ this.icon = null;
5520
+ this.errorMessage = null;
5521
+ this.attachShadow({ mode: "open" });
5522
+ this.shadowRoot.appendChild(fileDropZoneTemplate.content.cloneNode(true));
5523
+ this.initializeElements();
5524
+ this.setupEventListeners();
5525
+ }
5526
+ static get observedAttributes() {
5527
+ return ["accepted-types", "max-size", "multiple", "drag-text", "icon-src"];
5528
+ }
5529
+ attributeChangedCallback(name, oldValue, newValue) {
5530
+ if (oldValue === newValue) return;
5531
+ switch (name) {
5532
+ case "drag-text":
5533
+ if (this.dragText) this.dragText.textContent = newValue;
5534
+ break;
5535
+ case "icon-src":
5536
+ if (this.icon) this.icon.src = newValue || "";
5537
+ break;
5538
+ case "accepted-types":
5539
+ if (this.fileInput) this.fileInput.accept = newValue || "";
5540
+ break;
5541
+ case "multiple":
5542
+ if (this.fileInput) this.fileInput.multiple = newValue !== null;
5543
+ break;
5544
+ }
5545
+ }
5546
+ initializeElements() {
5547
+ if (!this.shadowRoot) return;
5548
+ this.dropZone = this.shadowRoot.querySelector(".file-drop-zone");
5549
+ this.fileInput = this.shadowRoot.querySelector(".file-input");
5550
+ this.dragText = this.shadowRoot.querySelector(".drag-text");
5551
+ this.icon = this.shadowRoot.querySelector(".drop-zone-icon");
5552
+ this.errorMessage = this.shadowRoot.querySelector(".error-message");
5553
+ }
5554
+ connectedCallback() {
5555
+ this.updateFromAttributes();
5556
+ }
5557
+ updateFromAttributes() {
5558
+ if (this.dragText) {
5559
+ this.dragText.textContent = this.getAttribute("drag-text") || "Drag & drop or click to choose files";
5560
+ }
5561
+ if (this.icon) {
5562
+ this.icon.src = this.getAttribute("icon-src") || "";
5563
+ }
5564
+ if (this.fileInput) {
5565
+ this.fileInput.accept = this.getAttribute("accepted-types") || "";
5566
+ this.fileInput.multiple = this.hasAttribute("multiple");
5567
+ }
5568
+ }
5569
+ setupEventListeners() {
5570
+ if (!this.dropZone || !this.fileInput) return;
5571
+ this.dropZone.addEventListener("dragover", (e) => {
5572
+ e.preventDefault();
5573
+ _optionalChain([this, 'access', _68 => _68.dropZone, 'optionalAccess', _69 => _69.classList, 'access', _70 => _70.add, 'call', _71 => _71("dragover")]);
5574
+ });
5575
+ this.dropZone.addEventListener("dragleave", (e) => {
5576
+ e.preventDefault();
5577
+ _optionalChain([this, 'access', _72 => _72.dropZone, 'optionalAccess', _73 => _73.classList, 'access', _74 => _74.remove, 'call', _75 => _75("dragover")]);
5578
+ });
5579
+ this.dropZone.addEventListener("drop", (e) => {
5580
+ e.preventDefault();
5581
+ _optionalChain([this, 'access', _76 => _76.dropZone, 'optionalAccess', _77 => _77.classList, 'access', _78 => _78.remove, 'call', _79 => _79("dragover")]);
5582
+ const files = _optionalChain([e, 'access', _80 => _80.dataTransfer, 'optionalAccess', _81 => _81.files]);
5583
+ if (_optionalChain([files, 'optionalAccess', _82 => _82.length])) {
5584
+ this.validateAndProcessFiles(files);
5585
+ }
5586
+ });
5587
+ this.dropZone.addEventListener("click", () => {
5588
+ _optionalChain([this, 'access', _83 => _83.fileInput, 'optionalAccess', _84 => _84.click, 'call', _85 => _85()]);
5589
+ });
5590
+ this.fileInput.addEventListener("change", (event) => {
5591
+ const input = event.target;
5592
+ if (_optionalChain([input, 'access', _86 => _86.files, 'optionalAccess', _87 => _87.length])) {
5593
+ this.validateAndProcessFiles(input.files);
5594
+ }
5595
+ });
5596
+ }
5597
+ validateAndProcessFiles(files) {
5598
+ const fileList = Array.from(files);
5599
+ let errorMessage = "";
5600
+ const acceptedTypes = _optionalChain([this, 'access', _88 => _88.getAttribute, 'call', _89 => _89("accepted-types"), 'optionalAccess', _90 => _90.split, 'call', _91 => _91(",")]) || [];
5601
+ if (acceptedTypes.length) {
5602
+ const invalidFiles = fileList.filter((file) => !acceptedTypes.some((type) => file.name.toLowerCase().endsWith(type.toLowerCase().replace("*", ""))));
5603
+ if (invalidFiles.length) {
5604
+ errorMessage = `Invalid file type. Accepted types: ${acceptedTypes.join(", ")}`;
5605
+ }
5606
+ }
5607
+ const maxSize = Number(this.getAttribute("max-size"));
5608
+ if (maxSize && fileList.some((file) => file.size > maxSize)) {
5609
+ errorMessage = `File size exceeds the maximum limit of ${this.formatFileSize(maxSize)}`;
5610
+ }
5611
+ if (errorMessage) {
5612
+ if (this.errorMessage) {
5613
+ this.errorMessage.textContent = errorMessage;
5614
+ }
5615
+ return;
5616
+ }
5617
+ if (this.errorMessage) {
5618
+ this.errorMessage.textContent = "";
5619
+ }
5620
+ this.dispatchEvent(
5621
+ new CustomEvent("files-selected", {
5622
+ detail: {
5623
+ files: this.hasAttribute("multiple") ? fileList : fileList[0]
5624
+ },
5625
+ bubbles: true,
5626
+ composed: true
5627
+ })
5628
+ );
5629
+ }
5630
+ formatFileSize(bytes) {
5631
+ const units = ["B", "KB", "MB", "GB"];
5632
+ let size = bytes;
5633
+ let unitIndex = 0;
5634
+ while (size >= 1024 && unitIndex < units.length - 1) {
5635
+ size /= 1024;
5636
+ unitIndex++;
5637
+ }
5638
+ return `${size.toFixed(2)} ${units[unitIndex]}`;
5639
+ }
5640
+ };
5641
+ customElements.define("wavelength-file-drop-zone", WavelengthFileDropZone);
5642
+
5643
+
5644
+
5166
5645
 
5167
5646
 
5168
5647
 
@@ -5176,7 +5655,7 @@ if (!customElements.get("wavelength-child-data-table")) {
5176
5655
 
5177
5656
 
5178
5657
 
5179
- exports.BaseWavelengthInput = BaseWavelengthInput; exports.BaseWavelengthMultiSelectAutocomplete = BaseWavelengthMultiSelectAutocomplete; exports.ChildDataTable = ChildDataTable; exports.SampleComponent = SampleComponent; exports.WavelengthBanner = WavelengthBanner; exports.WavelengthButton = WavelengthButton; exports.WavelengthDatePicker = WavelengthDatePicker; exports.WavelengthForm = WavelengthForm; exports.WavelengthInput = WavelengthInput; exports.WavelengthMultiSelectAutocomplete = WavelengthMultiSelectAutocomplete; exports.WavelengthNavBar = WavelengthNavBar; exports.WavelengthProgressBar = WavelengthProgressBar; exports.WavelengthTitleBar = WavelengthTitleBar;
5658
+ exports.BaseWavelengthInput = BaseWavelengthInput; exports.BaseWavelengthMultiSelectAutocomplete = BaseWavelengthMultiSelectAutocomplete; exports.ChildDataTable = ChildDataTable; exports.SampleComponent = SampleComponent; exports.WavelengthBanner = WavelengthBanner; exports.WavelengthButton = WavelengthButton; exports.WavelengthDatePicker = WavelengthDatePicker; exports.WavelengthFileDropZone = WavelengthFileDropZone; exports.WavelengthForm = WavelengthForm; exports.WavelengthInput = WavelengthInput; exports.WavelengthMultiSelectAutocomplete = WavelengthMultiSelectAutocomplete; exports.WavelengthNavBar = WavelengthNavBar; exports.WavelengthNotificationPanel = WavelengthNotificationPanel; exports.WavelengthProgressBar = WavelengthProgressBar; exports.WavelengthTitleBar = WavelengthTitleBar;
5180
5659
  /*! Bundled license information:
5181
5660
 
5182
5661
  react/cjs/react.production.min.js:
@@ -941,6 +941,23 @@ declare class WavelengthDatePicker extends HTMLElement {
941
941
  updateInput(): void;
942
942
  }
943
943
 
944
+ declare class WavelengthNotificationPanel extends HTMLElement {
945
+ static get observedAttributes(): string[];
946
+ private panelButton;
947
+ private panel;
948
+ private signOutButton;
949
+ private accountButton;
950
+ private markAsRead;
951
+ onMarkAsRead?: () => void;
952
+ onSignOut?: () => void;
953
+ accountLink?: string;
954
+ constructor();
955
+ connectedCallback(): void;
956
+ attributeChangedCallback(): void;
957
+ updateComponent(): void;
958
+ updatePanelVisibility(): void;
959
+ }
960
+
944
961
  interface Option {
945
962
  label: string;
946
963
  value: string;
@@ -1408,4 +1425,21 @@ declare class ChildDataTable extends HTMLElement {
1408
1425
  set setDropdownButtonIcon(icon: typeof this._sortIcon);
1409
1426
  }
1410
1427
 
1411
- export { BaseWavelengthInput, BaseWavelengthMultiSelectAutocomplete, ChildDataTable, SampleComponent, WavelengthBanner, WavelengthButton, WavelengthDatePicker, WavelengthForm, WavelengthInput, WavelengthMultiSelectAutocomplete, WavelengthNavBar, WavelengthProgressBar, WavelengthTitleBar };
1428
+ declare class WavelengthFileDropZone extends HTMLElement {
1429
+ private dropZone;
1430
+ private fileInput;
1431
+ private dragText;
1432
+ private icon;
1433
+ private errorMessage;
1434
+ static get observedAttributes(): string[];
1435
+ attributeChangedCallback(name: string, oldValue: string, newValue: string): void;
1436
+ constructor();
1437
+ private initializeElements;
1438
+ connectedCallback(): void;
1439
+ private updateFromAttributes;
1440
+ private setupEventListeners;
1441
+ private validateAndProcessFiles;
1442
+ private formatFileSize;
1443
+ }
1444
+
1445
+ export { BaseWavelengthInput, BaseWavelengthMultiSelectAutocomplete, ChildDataTable, SampleComponent, WavelengthBanner, WavelengthButton, WavelengthDatePicker, WavelengthFileDropZone, WavelengthForm, WavelengthInput, WavelengthMultiSelectAutocomplete, WavelengthNavBar, WavelengthNotificationPanel, WavelengthProgressBar, WavelengthTitleBar };
@@ -941,6 +941,23 @@ declare class WavelengthDatePicker extends HTMLElement {
941
941
  updateInput(): void;
942
942
  }
943
943
 
944
+ declare class WavelengthNotificationPanel extends HTMLElement {
945
+ static get observedAttributes(): string[];
946
+ private panelButton;
947
+ private panel;
948
+ private signOutButton;
949
+ private accountButton;
950
+ private markAsRead;
951
+ onMarkAsRead?: () => void;
952
+ onSignOut?: () => void;
953
+ accountLink?: string;
954
+ constructor();
955
+ connectedCallback(): void;
956
+ attributeChangedCallback(): void;
957
+ updateComponent(): void;
958
+ updatePanelVisibility(): void;
959
+ }
960
+
944
961
  interface Option {
945
962
  label: string;
946
963
  value: string;
@@ -1408,4 +1425,21 @@ declare class ChildDataTable extends HTMLElement {
1408
1425
  set setDropdownButtonIcon(icon: typeof this._sortIcon);
1409
1426
  }
1410
1427
 
1411
- export { BaseWavelengthInput, BaseWavelengthMultiSelectAutocomplete, ChildDataTable, SampleComponent, WavelengthBanner, WavelengthButton, WavelengthDatePicker, WavelengthForm, WavelengthInput, WavelengthMultiSelectAutocomplete, WavelengthNavBar, WavelengthProgressBar, WavelengthTitleBar };
1428
+ declare class WavelengthFileDropZone extends HTMLElement {
1429
+ private dropZone;
1430
+ private fileInput;
1431
+ private dragText;
1432
+ private icon;
1433
+ private errorMessage;
1434
+ static get observedAttributes(): string[];
1435
+ attributeChangedCallback(name: string, oldValue: string, newValue: string): void;
1436
+ constructor();
1437
+ private initializeElements;
1438
+ connectedCallback(): void;
1439
+ private updateFromAttributes;
1440
+ private setupEventListeners;
1441
+ private validateAndProcessFiles;
1442
+ private formatFileSize;
1443
+ }
1444
+
1445
+ export { BaseWavelengthInput, BaseWavelengthMultiSelectAutocomplete, ChildDataTable, SampleComponent, WavelengthBanner, WavelengthButton, WavelengthDatePicker, WavelengthFileDropZone, WavelengthForm, WavelengthInput, WavelengthMultiSelectAutocomplete, WavelengthNavBar, WavelengthNotificationPanel, WavelengthProgressBar, WavelengthTitleBar };
package/dist/esm/index.js CHANGED
@@ -4066,9 +4066,273 @@ if (!customElements.get("wavelength-date-picker")) {
4066
4066
  customElements.define("wavelength-date-picker", WavelengthDatePicker);
4067
4067
  }
4068
4068
 
4069
- // src/web-components/wavelength-multi-select-autocomplete.ts
4069
+ // src/web-components/wavelength-notification-panel.ts
4070
4070
  var template4 = document.createElement("template");
4071
4071
  template4.innerHTML = `
4072
+ <style>
4073
+ :host {
4074
+ display: flex;
4075
+ flex-direction: column;
4076
+ align-items: stretch;
4077
+ height: 100%;
4078
+ }
4079
+ :host([open]) .dropdown-panel {
4080
+ display: flex;
4081
+ }
4082
+
4083
+ .pill {
4084
+ display: inline-flex;
4085
+ position: relative;
4086
+ overflow: hidden;
4087
+ border: 1px solid #d3d3d3;
4088
+ border-radius: 0.25rem;
4089
+ background-color: #ffffff;
4090
+ color: black;
4091
+ cursor: pointer;
4092
+ font-family: "Roboto", "Helvetica", "Arial", sans-serif;
4093
+ font-weight: 500;
4094
+ font-size: 0.875rem;
4095
+ letter-spacing: 0.02857rem;
4096
+ white-space: normal;
4097
+ word-break: break-word;
4098
+ text-align: left;
4099
+ height: auto;
4100
+ width: 125px;
4101
+ line-height: 0.5;
4102
+ height: 80%;
4103
+ border-radius: 6px;
4104
+ }
4105
+
4106
+ .main {
4107
+ display: flex;
4108
+ flex-direction: column;
4109
+ align-items: flex-end;
4110
+ }
4111
+
4112
+ .dot {
4113
+ position: absolute;
4114
+ top: 8px;
4115
+ right: 8px;
4116
+ height: 5px;
4117
+ width: 5px;
4118
+ background-color: #8f0000;
4119
+ border-radius: 50%;
4120
+ z-index: 2;
4121
+ }
4122
+
4123
+ p.notification {
4124
+ color: #d3d3d3;
4125
+ }
4126
+
4127
+ .dropdown-panel {
4128
+ box-sizing: border-box;
4129
+ flex-direction: column;
4130
+ align-items: center;
4131
+ overflow: hidden;
4132
+ border: 1px solid #d3d3d3;
4133
+ border-radius: 0.5rem;
4134
+ background-color: #ffffff;
4135
+ color: black;
4136
+ font-family: "Roboto", "Helvetica", "Arial", sans-serif;
4137
+ font-weight: 500;
4138
+ font-size: 0.875rem;
4139
+ letter-spacing: 0.02857rem;
4140
+ word-break: break-word;
4141
+ text-align: left;
4142
+ height: 220px;
4143
+ width: 325px;
4144
+ line-height: 0.5;
4145
+ margin-top: 8px;
4146
+ display: none;
4147
+ position: absolute;
4148
+ top: 100%; /* opens BELOW navbar */
4149
+ right: 0;
4150
+ z-index: 2000;
4151
+ }
4152
+
4153
+ .dropdown-panel.invisible {
4154
+ display: none;
4155
+ }
4156
+
4157
+ .dropdown-content {
4158
+ display: flex;
4159
+ flex-direction: column;
4160
+ position: relative;
4161
+ overflow: hidden;
4162
+ border: 1px solid #d3d3d3;
4163
+ border-radius: 0.25rem;
4164
+ background-color: #ffffff;
4165
+ color: black;
4166
+ white-space: normal;
4167
+ word-break: break-word;
4168
+ text-align: center;
4169
+ height: 85px;
4170
+ width: 300px;
4171
+ line-height: 0.5;
4172
+ margin-top: 3px;
4173
+ }
4174
+
4175
+ .dropdown-header {
4176
+ padding: 8px;
4177
+ width: 100%;
4178
+ box-sizing: border-box;
4179
+ flex-shrink: 0;
4180
+ font-size: 15px;
4181
+ flew-wrap: nowrap;
4182
+ border: 1px solid pink;
4183
+ }
4184
+
4185
+ .mark-as-read {
4186
+ box-sizing: border-box;
4187
+ flex-shrink: 0;
4188
+ font-size: 10px;
4189
+ background-color: #ffffff;
4190
+ border: none;
4191
+ height: 10px;
4192
+ float: right;
4193
+ text-decoration: underline;
4194
+ cursor: pointer;
4195
+ }
4196
+
4197
+ .dropdown-footer {
4198
+ display: flex;
4199
+ flex-direction: column;
4200
+ flex-shrink: 0;
4201
+ width: 100%;
4202
+ padding: 8px;
4203
+ box-sizing: border-box;
4204
+ }
4205
+
4206
+ .footer-button-settings {
4207
+ margin-top: 8px;
4208
+ border: 1px;
4209
+ width: 100%;
4210
+ height 85px;
4211
+ background-color: #ffffff;
4212
+ display: flex;
4213
+ cursor: pointer;
4214
+ color: #7d7c7cff;
4215
+ font-size: 13px;
4216
+ }
4217
+
4218
+ .footer-button-sign-out {
4219
+ margin-top: 8px;
4220
+ border: 1px;
4221
+ width: 100%;
4222
+ height 85px;
4223
+ background-color: #ffffff;
4224
+ display: flex;
4225
+ cursor: pointer;
4226
+ color: #7d7c7cff;
4227
+ font-size: 13px;
4228
+ }
4229
+
4230
+ .footer-button-settings:hover {
4231
+ background-color: #e0e0e0; /* Light gray on hover */
4232
+ }
4233
+
4234
+ .footer-button-sign-out:hover {
4235
+ background-color: #e0e0e0; /* Light gray on hover */
4236
+ }
4237
+
4238
+ </style>
4239
+ <div class="main">
4240
+ <button class="pill">
4241
+ <div>
4242
+ <p>Your Name</p>
4243
+ <p class="notification">No Notifications</p>
4244
+ </div>
4245
+ </button>
4246
+ <span class="dot"></span>
4247
+ <div class=dropdown-panel>
4248
+ <div class="dropdown-header">
4249
+ <p>Notifications</p>
4250
+ <button class=mark-as-read> Mark As Read </button>
4251
+ </div>
4252
+ <div class="dropdown-content">
4253
+ <p>no notifications</p>
4254
+ </div>
4255
+ <div class=dropdown-footer>
4256
+ <button class=footer-button-settings>Account Settings</button>
4257
+ <button class=footer-button-sign-out>Sign Out</button>
4258
+ </div>
4259
+ </div>
4260
+ </div>
4261
+ `;
4262
+ var WavelengthNotificationPanel = class extends HTMLElement {
4263
+ // List of attributes to observe for changes
4264
+ static get observedAttributes() {
4265
+ return ["notification", "darkMode"];
4266
+ }
4267
+ constructor() {
4268
+ super();
4269
+ const shadow = this.attachShadow({ mode: "open" });
4270
+ shadow.appendChild(template4.content.cloneNode(true));
4271
+ this.panelButton = shadow.querySelector(".pill");
4272
+ this.panel = shadow.querySelector(".dropdown-panel");
4273
+ this.signOutButton = shadow.querySelector(".footer-button-sign-out");
4274
+ this.accountButton = shadow.querySelector(".footer-button-settings");
4275
+ this.markAsRead = shadow.querySelector(".mark-as-read");
4276
+ this.panelButton.addEventListener("click", (event) => {
4277
+ if (this.panelButton.disabled || this.hasAttribute("disabled")) {
4278
+ event.preventDefault();
4279
+ event.stopImmediatePropagation();
4280
+ return;
4281
+ }
4282
+ if (this.hasAttribute("open")) {
4283
+ this.removeAttribute("open");
4284
+ } else {
4285
+ this.setAttribute("open", "");
4286
+ }
4287
+ this.updatePanelVisibility();
4288
+ });
4289
+ this.signOutButton.addEventListener("click", () => {
4290
+ if (typeof this.onSignOut === "function") {
4291
+ this.onSignOut();
4292
+ } else {
4293
+ alert("Insert function to Complete sign out functionality");
4294
+ }
4295
+ });
4296
+ this.accountButton.addEventListener("click", () => {
4297
+ if (typeof this.accountLink === "string") {
4298
+ window.location.href = this.accountLink;
4299
+ } else {
4300
+ alert("Missing the link for an account");
4301
+ }
4302
+ });
4303
+ this.markAsRead.addEventListener("click", () => {
4304
+ if (typeof this.onMarkAsRead === "function") {
4305
+ this.onMarkAsRead();
4306
+ } else {
4307
+ alert("Insert function to clear notifications");
4308
+ }
4309
+ });
4310
+ }
4311
+ // Called when component is inserted into the DOM
4312
+ connectedCallback() {
4313
+ this.updatePanelVisibility();
4314
+ }
4315
+ // Called when observed attributes change
4316
+ attributeChangedCallback() {
4317
+ this.updateComponent();
4318
+ }
4319
+ // Main update logic; Your component's functionality will go here and/or in other methods that you have below
4320
+ updateComponent() {
4321
+ const prop = this.getAttribute("test-prop") || "";
4322
+ }
4323
+ updatePanelVisibility() {
4324
+ if (!this.panel) return;
4325
+ const isOpen = this.hasAttribute("open");
4326
+ this.panel.style.display = isOpen ? "inline-flex" : "none";
4327
+ }
4328
+ };
4329
+ if (!customElements.get("wavelength-notification-panel")) {
4330
+ customElements.define("wavelength-notification-panel", WavelengthNotificationPanel);
4331
+ }
4332
+
4333
+ // src/web-components/wavelength-multi-select-autocomplete.ts
4334
+ var template5 = document.createElement("template");
4335
+ template5.innerHTML = `
4072
4336
  <style>
4073
4337
  .multi-select-container {
4074
4338
  background-color: white;
@@ -4310,7 +4574,7 @@ var BaseWavelengthMultiSelectAutocomplete = class extends HTMLElement {
4310
4574
  this._internals = this.attachInternals();
4311
4575
  this._internals.role = "combobox";
4312
4576
  const shadow = this.attachShadow({ mode: "open" });
4313
- shadow.appendChild(template4.content.cloneNode(true));
4577
+ shadow.appendChild(template5.content.cloneNode(true));
4314
4578
  this._container = this.shadowRoot.querySelector(".multi-select-container");
4315
4579
  this._inputWrapper = this.shadowRoot.querySelector(".multi-select-input-wrapper");
4316
4580
  this._input = this.shadowRoot.querySelector(".multi-select-input");
@@ -4527,18 +4791,19 @@ if (!customElements.get("wavelength-multi-select-autocomplete")) {
4527
4791
  }
4528
4792
 
4529
4793
  // src/web-components/wavelength-nav-bar.ts
4530
- var template5 = document.createElement("template");
4531
- template5.innerHTML = `
4794
+ var template6 = document.createElement("template");
4795
+ template6.innerHTML = `
4532
4796
  <style>
4533
4797
  :host {
4534
4798
  display: block;
4535
4799
  font-family: sans-serif;
4800
+ height: 100%;
4536
4801
  }
4537
4802
 
4538
4803
 
4539
4804
  nav {
4540
4805
  display: flex;
4541
- width: 100%;
4806
+ width: 95%;
4542
4807
  height: var(--height, 25px);
4543
4808
  padding: var(--padding, 1rem);
4544
4809
  border-bottom: var(--border, 1px solid #ddd);
@@ -4553,9 +4818,10 @@ template5.innerHTML = `
4553
4818
  justify-content: space-between;
4554
4819
  }
4555
4820
 
4556
- .flex-spacer {
4557
- flex: 8;
4558
- }
4821
+ .nav-center {
4822
+ display: flex;
4823
+ justify-content: center;
4824
+ }
4559
4825
 
4560
4826
  .home {
4561
4827
  flex: 1;
@@ -4588,22 +4854,25 @@ template5.innerHTML = `
4588
4854
 
4589
4855
 
4590
4856
  .settings {
4591
- flex: 1;
4592
- justify-content: flex-end;
4593
- cursor: pointer;
4594
- display: flex;
4595
- align-items: center;
4596
- gap: 0.5rem;
4597
- }
4857
+ flex: 1;
4858
+ justify-content: flex-end;
4859
+ cursor: pointer;
4860
+ display: flex;
4861
+ align-items: center;
4862
+ gap: 0.5rem;
4863
+ }
4598
4864
 
4599
4865
  .profile {
4600
- padding: 0.5rem 0.75rem;
4866
+ padding: var(--padding, 1rem);
4601
4867
  border: 2px solid #ccc;
4602
4868
  border-radius: 6px;
4603
4869
  cursor: pointer;
4604
4870
  display: flex;
4605
4871
  flex-direction: column;
4606
4872
  text-align: center;
4873
+ width: 100%;
4874
+ height: var(--height, 25px);
4875
+ position: fixed;
4607
4876
  }
4608
4877
 
4609
4878
  .profile-name {
@@ -4621,6 +4890,14 @@ template5.innerHTML = `
4621
4890
  gap: 0.5rem;
4622
4891
  flex: 3;
4623
4892
  }
4893
+ .notification-wrapper {
4894
+ position: relative;
4895
+ height: 100%;
4896
+ display: flex;
4897
+
4898
+ }
4899
+
4900
+
4624
4901
  </style>
4625
4902
  <nav>
4626
4903
  <div class="section home" id="logo">
@@ -4644,18 +4921,14 @@ template5.innerHTML = `
4644
4921
  </svg>
4645
4922
  <slot name="home"></slot>
4646
4923
  </div>
4647
- <div class="flex-spacer"></div>
4924
+ <div class="nav-center"></div>
4648
4925
  <div class = "middle-tab-group">
4649
4926
  <div class="tab"><a href="/applications"><slot name="tab">Applications</slot></a></div>
4650
4927
  <div class="tab"><a href="/users"><slot name="tab">Users</slot></a></div>
4651
4928
  <div class="tab"><a href="/apikeys"><slot name="tab">API Keys</slot></a></div>
4652
4929
  </div>
4653
- <div class="flex-spacer"></div>
4654
- <div class="section settings">
4655
- <div class="profile">
4656
- <span class="profile-name">User</span>
4657
- <span class="profile-note">Notifications</span>
4658
- </div>
4930
+ <div class="notification-wrapper">
4931
+ <wavelength-notification-panel ></wavelength-notification-panel>
4659
4932
  </div>
4660
4933
  </nav>
4661
4934
  `;
@@ -4666,7 +4939,7 @@ var WavelengthNavBar = class extends HTMLElement {
4666
4939
  constructor() {
4667
4940
  super();
4668
4941
  const shadow = this.attachShadow({ mode: "open" });
4669
- shadow.appendChild(template5.content.cloneNode(true));
4942
+ shadow.appendChild(template6.content.cloneNode(true));
4670
4943
  shadow.querySelector("#logo")?.addEventListener("click", () => {
4671
4944
  this.dispatchEvent(new CustomEvent("home-click"));
4672
4945
  });
@@ -4680,7 +4953,7 @@ var WavelengthNavBar = class extends HTMLElement {
4680
4953
  this.renderTabs();
4681
4954
  }
4682
4955
  applyStyles() {
4683
- this.style.setProperty("--bg", this.getAttribute("bg-color") || "#fff");
4956
+ this.style.setProperty("--bg", this.getAttribute("bg-color") || "#ffffffff");
4684
4957
  this.style.setProperty("--txt", this.getAttribute("txt-color") || "#000");
4685
4958
  this.style.setProperty("--height", this.getAttribute("height") || "60px");
4686
4959
  this.style.setProperty("--padding", this.getAttribute("padding") || "0 1rem");
@@ -4711,8 +4984,8 @@ if (!customElements.get("wavelength-nav-bar")) {
4711
4984
 
4712
4985
  // src/web-components/wavelength-child-data-table.ts
4713
4986
  var import_react = __toESM(require_react(), 1);
4714
- var template6 = document.createElement("template");
4715
- template6.innerHTML = `
4987
+ var template7 = document.createElement("template");
4988
+ template7.innerHTML = `
4716
4989
 
4717
4990
  <style>
4718
4991
 
@@ -4863,7 +5136,7 @@ var ChildDataTable = class extends HTMLElement {
4863
5136
  <path d="M13.2375 0L7.5 5.725L1.7625 0L0 1.7625L7.5 9.2625L15 1.7625L13.2375 0Z" fill="currentColor"/>
4864
5137
  </svg>`;
4865
5138
  this.shadow = this.attachShadow({ mode: "open" });
4866
- this.shadow.append(template6.content.cloneNode(true));
5139
+ this.shadow.append(template7.content.cloneNode(true));
4867
5140
  }
4868
5141
  static get observedAttributes() {
4869
5142
  return ["table-columns", "table-data", "dropdown-arrow-location", "sort-icon", "dropdown-button-icon"];
@@ -5162,6 +5435,210 @@ var ChildDataTable = class extends HTMLElement {
5162
5435
  if (!customElements.get("wavelength-child-data-table")) {
5163
5436
  customElements.define("wavelength-child-data-table", ChildDataTable);
5164
5437
  }
5438
+
5439
+ // src/web-components/wavelength-file-drop-zone.ts
5440
+ var fileDropZoneTemplate = document.createElement("template");
5441
+ fileDropZoneTemplate.innerHTML = `
5442
+ <style>
5443
+ :host {
5444
+ display: var(--hostDisplay, block);
5445
+ width: var(--hostWidth, 100%);
5446
+ }
5447
+
5448
+ .file-input {
5449
+ display: var(--inputDisplay, none);
5450
+ }
5451
+
5452
+ .file-drop-zone {
5453
+ border: var(--borderWidth, 1px) var(--borderStyle, dashed) var(--borderColor, #596381);
5454
+ border-radius: var(--borderRadius, 8px);
5455
+ padding: var(--padding, 20px);
5456
+ text-align: var(--textAlign, center);
5457
+ background-color: var(--backgroundColor, #242834);
5458
+ cursor: var(--cursor, pointer);
5459
+ transition: var(--transition, border-color 0.3s, background-color 0.3s);
5460
+ display: var(--display, flex);
5461
+ flex-direction: var(--flexDirection, column);
5462
+ align-items: var(--alignItems, center);
5463
+ gap: var(--gap, 10px);
5464
+ }
5465
+
5466
+ .file-drop-zone:hover {
5467
+ border-color: var(--borderHoverColor, #26BABE);
5468
+ background-color: var(--backgroundHoverColor, #242834);
5469
+ }
5470
+
5471
+ .file-drop-zone.dragover {
5472
+ border-color: var(--borderActiveColor, #26BABE);
5473
+ background-color: var(--backgroundActiveColor, #3E455A);
5474
+ }
5475
+
5476
+ .drop-zone-content {
5477
+ display: var(--contentDisplay, flex);
5478
+ flex-direction: var(--contentFlexDirection, column);
5479
+ align-items: var(--contentAlignItems, center);
5480
+ gap: var(--contentGap, 10px);
5481
+ color: var(--textColor, #FFFFFFCC);
5482
+ }
5483
+
5484
+ .drop-zone-content span {
5485
+ font-family: var(--fontFamily, Montserrat);
5486
+ font-style: var(--fontStyle, normal);
5487
+ font-size: var(--fontSize, 12px);
5488
+ line-height: var(--lineHeight, 100%);
5489
+ letter-spacing: var(--letterSpacing, 0%);
5490
+ }
5491
+
5492
+ .drop-zone-icon {
5493
+ width: var(--iconSize, 24px);
5494
+ height: var(--iconSize, 24px);
5495
+ }
5496
+
5497
+ .error-message {
5498
+ color: var(--errorColor, #ff4444);
5499
+ font-family: var(--errorFontFamily, Montserrat);
5500
+ font-size: var(--errorFontSize, 12px);
5501
+ margin-top: var(--errorMarginTop, 10px);
5502
+ }
5503
+ </style>
5504
+ <div class="file-drop-zone">
5505
+ <input type="file" class="file-input">
5506
+ <div class="drop-zone-content">
5507
+ <img class="drop-zone-icon" alt="Drag icon">
5508
+ <span class="drag-text"></span>
5509
+ </div>
5510
+ <div class="error-message"></div>
5511
+ </div>
5512
+ `;
5513
+ var WavelengthFileDropZone = class extends HTMLElement {
5514
+ constructor() {
5515
+ super();
5516
+ this.dropZone = null;
5517
+ this.fileInput = null;
5518
+ this.dragText = null;
5519
+ this.icon = null;
5520
+ this.errorMessage = null;
5521
+ this.attachShadow({ mode: "open" });
5522
+ this.shadowRoot.appendChild(fileDropZoneTemplate.content.cloneNode(true));
5523
+ this.initializeElements();
5524
+ this.setupEventListeners();
5525
+ }
5526
+ static get observedAttributes() {
5527
+ return ["accepted-types", "max-size", "multiple", "drag-text", "icon-src"];
5528
+ }
5529
+ attributeChangedCallback(name, oldValue, newValue) {
5530
+ if (oldValue === newValue) return;
5531
+ switch (name) {
5532
+ case "drag-text":
5533
+ if (this.dragText) this.dragText.textContent = newValue;
5534
+ break;
5535
+ case "icon-src":
5536
+ if (this.icon) this.icon.src = newValue || "";
5537
+ break;
5538
+ case "accepted-types":
5539
+ if (this.fileInput) this.fileInput.accept = newValue || "";
5540
+ break;
5541
+ case "multiple":
5542
+ if (this.fileInput) this.fileInput.multiple = newValue !== null;
5543
+ break;
5544
+ }
5545
+ }
5546
+ initializeElements() {
5547
+ if (!this.shadowRoot) return;
5548
+ this.dropZone = this.shadowRoot.querySelector(".file-drop-zone");
5549
+ this.fileInput = this.shadowRoot.querySelector(".file-input");
5550
+ this.dragText = this.shadowRoot.querySelector(".drag-text");
5551
+ this.icon = this.shadowRoot.querySelector(".drop-zone-icon");
5552
+ this.errorMessage = this.shadowRoot.querySelector(".error-message");
5553
+ }
5554
+ connectedCallback() {
5555
+ this.updateFromAttributes();
5556
+ }
5557
+ updateFromAttributes() {
5558
+ if (this.dragText) {
5559
+ this.dragText.textContent = this.getAttribute("drag-text") || "Drag & drop or click to choose files";
5560
+ }
5561
+ if (this.icon) {
5562
+ this.icon.src = this.getAttribute("icon-src") || "";
5563
+ }
5564
+ if (this.fileInput) {
5565
+ this.fileInput.accept = this.getAttribute("accepted-types") || "";
5566
+ this.fileInput.multiple = this.hasAttribute("multiple");
5567
+ }
5568
+ }
5569
+ setupEventListeners() {
5570
+ if (!this.dropZone || !this.fileInput) return;
5571
+ this.dropZone.addEventListener("dragover", (e) => {
5572
+ e.preventDefault();
5573
+ this.dropZone?.classList.add("dragover");
5574
+ });
5575
+ this.dropZone.addEventListener("dragleave", (e) => {
5576
+ e.preventDefault();
5577
+ this.dropZone?.classList.remove("dragover");
5578
+ });
5579
+ this.dropZone.addEventListener("drop", (e) => {
5580
+ e.preventDefault();
5581
+ this.dropZone?.classList.remove("dragover");
5582
+ const files = e.dataTransfer?.files;
5583
+ if (files?.length) {
5584
+ this.validateAndProcessFiles(files);
5585
+ }
5586
+ });
5587
+ this.dropZone.addEventListener("click", () => {
5588
+ this.fileInput?.click();
5589
+ });
5590
+ this.fileInput.addEventListener("change", (event) => {
5591
+ const input = event.target;
5592
+ if (input.files?.length) {
5593
+ this.validateAndProcessFiles(input.files);
5594
+ }
5595
+ });
5596
+ }
5597
+ validateAndProcessFiles(files) {
5598
+ const fileList = Array.from(files);
5599
+ let errorMessage = "";
5600
+ const acceptedTypes = this.getAttribute("accepted-types")?.split(",") || [];
5601
+ if (acceptedTypes.length) {
5602
+ const invalidFiles = fileList.filter((file) => !acceptedTypes.some((type) => file.name.toLowerCase().endsWith(type.toLowerCase().replace("*", ""))));
5603
+ if (invalidFiles.length) {
5604
+ errorMessage = `Invalid file type. Accepted types: ${acceptedTypes.join(", ")}`;
5605
+ }
5606
+ }
5607
+ const maxSize = Number(this.getAttribute("max-size"));
5608
+ if (maxSize && fileList.some((file) => file.size > maxSize)) {
5609
+ errorMessage = `File size exceeds the maximum limit of ${this.formatFileSize(maxSize)}`;
5610
+ }
5611
+ if (errorMessage) {
5612
+ if (this.errorMessage) {
5613
+ this.errorMessage.textContent = errorMessage;
5614
+ }
5615
+ return;
5616
+ }
5617
+ if (this.errorMessage) {
5618
+ this.errorMessage.textContent = "";
5619
+ }
5620
+ this.dispatchEvent(
5621
+ new CustomEvent("files-selected", {
5622
+ detail: {
5623
+ files: this.hasAttribute("multiple") ? fileList : fileList[0]
5624
+ },
5625
+ bubbles: true,
5626
+ composed: true
5627
+ })
5628
+ );
5629
+ }
5630
+ formatFileSize(bytes) {
5631
+ const units = ["B", "KB", "MB", "GB"];
5632
+ let size = bytes;
5633
+ let unitIndex = 0;
5634
+ while (size >= 1024 && unitIndex < units.length - 1) {
5635
+ size /= 1024;
5636
+ unitIndex++;
5637
+ }
5638
+ return `${size.toFixed(2)} ${units[unitIndex]}`;
5639
+ }
5640
+ };
5641
+ customElements.define("wavelength-file-drop-zone", WavelengthFileDropZone);
5165
5642
  export {
5166
5643
  BaseWavelengthInput,
5167
5644
  BaseWavelengthMultiSelectAutocomplete,
@@ -5170,10 +5647,12 @@ export {
5170
5647
  WavelengthBanner,
5171
5648
  WavelengthButton,
5172
5649
  WavelengthDatePicker,
5650
+ WavelengthFileDropZone,
5173
5651
  WavelengthForm,
5174
5652
  WavelengthInput,
5175
5653
  WavelengthMultiSelectAutocomplete,
5176
5654
  WavelengthNavBar,
5655
+ WavelengthNotificationPanel,
5177
5656
  WavelengthProgressBar,
5178
5657
  WavelengthTitleBar
5179
5658
  };
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@wavelengthusaf/web-components",
3
3
  "author": "563 EWS - Wavelength",
4
4
  "license": "MIT",
5
- "version": "1.3.0",
5
+ "version": "1.4.0",
6
6
  "description": "Common component library used by Wavelength developers (NATIVE WEB COMPONENTS)",
7
7
  "main": "/dist/cjs/index.cjs",
8
8
  "module": "/dist/esm/index.js",