@nysds/nys-fileinput 1.13.1 → 1.15.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.
@@ -0,0 +1 @@
1
+ export * from "./nys-fileinput";
@@ -0,0 +1,118 @@
1
+ import { LitElement } from "lit";
2
+ import "./nys-fileitem";
3
+ /**
4
+ * A file input for uploading files with support for multiple files, drag-and-drop, and progress tracking.
5
+ * Validates file types via magic bytes (not just extension). Form-associated via ElementInternals.
6
+ *
7
+ * Use for document uploads, image uploads, or any file submission. Enable `dropzone` for drag-and-drop UI.
8
+ *
9
+ * @summary File input with drag-and-drop, validation, and progress tracking.
10
+ * @element nys-fileinput
11
+ *
12
+ * @slot description - Custom HTML description content.
13
+ *
14
+ * @fires nys-change - Fired when files are added or removed. Detail: `{id, files}`.
15
+ *
16
+ * @example Single file upload
17
+ * ```html
18
+ * <nys-fileinput label="Upload document" accept=".pdf,.doc" required></nys-fileinput>
19
+ * ```
20
+ *
21
+ * @example Multiple files with dropzone
22
+ * ```html
23
+ * <nys-fileinput label="Upload images" accept="image/*" multiple dropzone></nys-fileinput>
24
+ * ```
25
+ */
26
+ export declare class NysFileinput extends LitElement {
27
+ static styles: import("lit").CSSResult;
28
+ static shadowRootOptions: {
29
+ delegatesFocus: boolean;
30
+ clonable?: boolean;
31
+ customElementRegistry?: CustomElementRegistry;
32
+ mode: ShadowRootMode;
33
+ serializable?: boolean;
34
+ slotAssignment?: SlotAssignmentMode;
35
+ };
36
+ /** Unique identifier. Auto-generated if not provided. */
37
+ id: string;
38
+ /** Name for form submission. */
39
+ name: string;
40
+ /** Visible label text. */
41
+ label: string;
42
+ /** Helper text below label. Use slot for custom HTML. */
43
+ description: string;
44
+ /** Allows selecting multiple files. */
45
+ multiple: boolean;
46
+ /** Form `id` to associate with. */
47
+ form: string | null;
48
+ /** Tooltip text shown on hover/focus of info icon. */
49
+ tooltip: string;
50
+ /** Accepted file types. Use MIME types (`image/*`) or extensions (`.pdf`). Validated via magic bytes. */
51
+ accept: string;
52
+ /** Prevents interaction. */
53
+ disabled: boolean;
54
+ /** Requires at least one file to be uploaded. */
55
+ required: boolean;
56
+ /** Shows "Optional" flag. */
57
+ optional: boolean;
58
+ /** Shows error message when true. */
59
+ showError: boolean;
60
+ /** Error message text. Shown only when `showError` is true. */
61
+ errorMessage: string;
62
+ /** Enables drag-and-drop zone UI. */
63
+ dropzone: boolean;
64
+ /**
65
+ * Component width: `lg` (384px) or `full` (100%, default).
66
+ * @default "full"
67
+ */
68
+ width: "lg" | "full";
69
+ /** Adjusts colors for dark backgrounds. */
70
+ inverted: boolean;
71
+ private _selectedFiles;
72
+ private _dragActive;
73
+ private get _isDropDisabled();
74
+ private get _buttonAriaLabel();
75
+ private get _buttonAriaDescription();
76
+ private get _innerNysButton();
77
+ private _internals;
78
+ /**
79
+ * Lifecycle methods
80
+ * --------------------------------------------------------------------------
81
+ */
82
+ static formAssociated: boolean;
83
+ constructor();
84
+ connectedCallback(): void;
85
+ disconnectedCallback(): void;
86
+ firstUpdated(): void;
87
+ /**
88
+ * Form Integration
89
+ * --------------------------------------------------------------------------
90
+ */
91
+ private _setValue;
92
+ private _manageRequire;
93
+ private _setValidityMessage;
94
+ private _validate;
95
+ checkValidity(): boolean;
96
+ formResetCallback(): void;
97
+ private _handleInvalid;
98
+ /**
99
+ * Functions
100
+ * --------------------------------------------------------------------------
101
+ */
102
+ private _saveSelectedFiles;
103
+ private _processFile;
104
+ private _dispatchChangeEvent;
105
+ private _openFileDialog;
106
+ private _handlePostFileSelectionFocus;
107
+ private _focusFirstFileItemIfSingleMode;
108
+ /**
109
+ * Event Handlers
110
+ * --------------------------------------------------------------------------
111
+ */
112
+ private _handleFileChange;
113
+ private _handleFileRemove;
114
+ private _onDragOver;
115
+ private _onDragLeave;
116
+ private _onDrop;
117
+ render(): import("lit-html").TemplateResult<1>;
118
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -1,6 +1,16 @@
1
- import { LitElement as y, unsafeCSS as g, html as a } from "lit";
2
- import { property as n } from "lit/decorators.js";
1
+ import { LitElement as h, unsafeCSS as g, html as a } from "lit";
2
+ import { property as o } from "lit/decorators.js";
3
3
  import { ifDefined as m } from "lit/directives/if-defined.js";
4
+ /*!
5
+ * █▄ █ █ █ █▀▀▀█ █▀▀▄ █▀▀▀█
6
+ * █ █ █ █▄▄▄█ ▀▀▀▄▄ █ █ ▀▀▀▄▄
7
+ * █ ▀█ █ █▄▄▄█ █▄▄▀ █▄▄▄█
8
+ *
9
+ * Fileinput Component
10
+ * Part of the New York State Design System
11
+ * Repository: https://github.com/its-hcd/nysds
12
+ * License: MIT
13
+ */
4
14
  async function _(p, e) {
5
15
  if (!e || e.trim() === "") return !0;
6
16
  const t = e.toLowerCase().split(",").map((r) => r.trim()), i = p.name.toLowerCase(), s = i.includes(".") ? i.split(".").pop() : "";
@@ -9,13 +19,13 @@ async function _(p, e) {
9
19
  return !0;
10
20
  return !1;
11
21
  }
12
- const v = ':host{--_nys-fileitem-border-radius: var(--nys-radius-md, 4px);--_nys-fileitem-padding: var(--nys-space-100, 8px) var(--nys-space-200, 16px);--_nys-fileitem-background-color: var(--nys-color-ink-reverse, #fff);--_nys-fileitem-border-color: var(--nys-color-neutral-100, #d0d0ce);--_nys-fileitem-font-family: var( --nys-font-family-ui, var( --nys-font-family-sans, "Proxima Nova", "Helvetica Neue", "Helvetica", "Arial", sans-serif ) );--_nys-fileitem-font-size: var(--nys-font-size-ui-md, 16px);--_nys-fileitem-font-weight: var(--nys-font-weight-regular, 400);--_nys-fileitem-line-height: var(--nys-font-lineheight-ui-md, 24px);--_nys-fileitem-letter-spacing: var( --nys-font-letterspacing-ui-md, .044px );--_nys-fileitem-background-color--progress: var( --nys-color-neutral-50, #ededed );--_nys-fileitem-background-color--progress--fill: var( --nys-color-info, #004dd1 )}.file-item{position:relative;border-radius:var(--_nys-fileitem-border-radius);border-width:var(--nys-border-width-sm, 1px);border-style:solid;border-color:var(--_nys-fileitem-border-color);background-color:var(--_nys-fileitem-background-color)}.file-item.error{--_nys-fileitem-border-color: var(--nys-color-danger, #b52c2c)}.file-item__main{display:flex;justify-items:center;align-items:center;gap:var(--_nys-fileinput-gap);padding:var(--_nys-fileitem-padding);height:56px;box-sizing:border-box}.file-item__info{display:flex;flex-direction:column;flex:1;min-width:0;font-family:var(--_nys-fileitem-font-family);font-size:var(--_nys-fileitem-font-size);font-style:normal;font-weight:var(--_nys-fileitem-font-weight);line-height:var(--_nys-fileitem-line-height);letter-spacing:var(--_nys-fileitem-letter-spacing)}.file-item__info-name{display:flex;max-width:100%;overflow:hidden;white-space:nowrap;align-items:center}.file-item__info-name-start{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex-shrink:1;min-width:0}.file-item p{margin:0}.file-item__error{color:var(--nys-color-danger, #b52c2c);text-overflow:ellipsis;font-weight:700}progress{position:absolute;bottom:0;display:flex;width:100%;height:6px;border-radius:var(--nys-radius-round, 1776px);background:var(--_nys-fileitem-background-color--progress--fill);overflow:hidden;appearance:none}progress::-moz-progress-bar{background-color:var(--_nys-fileitem-background-color--progress)}progress::-webkit-progress-value{background-color:var(--_nys-fileitem-background-color--progress--fill)}progress::-webkit-progress-bar{background-color:var(--_nys-fileitem-background-color--progress)}.file-icon[name=progress_activity]{animation:spin 1s linear infinite}.file-icon[name=error]{color:var(--nys-color-danger, #b52c2c)}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}';
13
- var b = Object.defineProperty, h = (p, e, t, i) => {
22
+ const v = ':host{--_nys-fileitem-border-radius: var(--nys-radius-md, 4px);--_nys-fileitem-padding: var(--nys-space-100, 8px) var(--nys-space-200, 16px);--_nys-fileitem-background-color: var(--nys-color-ink-reverse, #ffffff);--_nys-fileitem-border-color: var(--nys-color-neutral-100, #d0d0ce);--_nys-fileitem-font-family: var( --nys-font-family-ui, var( --nys-font-family-sans, "Proxima Nova", "Helvetica Neue", "Helvetica", "Arial", sans-serif ) );--_nys-fileitem-font-size: var(--nys-font-size-ui-md, 16px);--_nys-fileitem-font-weight: var(--nys-font-weight-regular, 400);--_nys-fileitem-line-height: var(--nys-font-lineheight-ui-md, 24px);--_nys-fileitem-letter-spacing: var( --nys-font-letterspacing-ui-md, .044px );--_nys-fileitem-background-color--progress: var( --nys-color-neutral-50, #ededed );--_nys-fileitem-background-color--progress--fill: var( --nys-color-info, #004dd1 )}.file-item{position:relative;border-radius:var(--_nys-fileitem-border-radius);border-width:var(--nys-border-width-sm, 1px);border-style:solid;border-color:var(--_nys-fileitem-border-color);background-color:var(--_nys-fileitem-background-color)}.file-item.error{--_nys-fileitem-border-color: var(--nys-color-danger, #b52c2c)}.file-item__main{display:flex;place-items:center center;gap:var(--_nys-fileinput-gap);padding:var(--_nys-fileitem-padding);height:56px;box-sizing:border-box}.file-item__info{display:flex;flex-direction:column;flex:1;min-width:0;font-family:var(--_nys-fileitem-font-family);font-size:var(--_nys-fileitem-font-size);font-style:normal;font-weight:var(--_nys-fileitem-font-weight);line-height:var(--_nys-fileitem-line-height);letter-spacing:var(--_nys-fileitem-letter-spacing)}.file-item__info-name{display:flex;max-width:100%;overflow:hidden;white-space:nowrap;align-items:center}.file-item__info-name-start{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex-shrink:1;min-width:0}.file-item p{margin:0}.file-item__error{color:var(--nys-color-danger, #b52c2c);text-overflow:ellipsis;font-weight:700}progress{position:absolute;bottom:0;display:flex;width:100%;height:6px;border-radius:var(--nys-radius-round, 1776px);background:var(--_nys-fileitem-background-color--progress--fill);overflow:hidden;appearance:none}progress::-moz-progress-bar{background-color:var(--_nys-fileitem-background-color--progress)}progress::-webkit-progress-value{background-color:var(--_nys-fileitem-background-color--progress--fill)}progress::-webkit-progress-bar{background-color:var(--_nys-fileitem-background-color--progress)}.file-icon[name=progress_activity]{animation:spin 1s linear infinite}.file-icon[name=error]{color:var(--nys-color-danger, #b52c2c)}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}';
23
+ var b = Object.defineProperty, y = (p, e, t, i) => {
14
24
  for (var s = void 0, r = p.length - 1, d; r >= 0; r--)
15
25
  (d = p[r]) && (s = d(e, t, s) || s);
16
26
  return s && b(e, t, s), s;
17
27
  };
18
- const u = class u extends y {
28
+ const u = class u extends h {
19
29
  constructor() {
20
30
  super(...arguments), this.filename = "", this.status = "pending", this.progress = 0, this.errorMessage = "";
21
31
  }
@@ -88,29 +98,32 @@ const u = class u extends y {
88
98
  `;
89
99
  }
90
100
  };
91
- u.styles = g(v);
101
+ u.styles = g(v), u.shadowRootOptions = {
102
+ ...h.shadowRootOptions,
103
+ delegatesFocus: !0
104
+ };
92
105
  let c = u;
93
- h([
94
- n({ type: String })
106
+ y([
107
+ o({ type: String })
95
108
  ], c.prototype, "filename");
96
- h([
97
- n({ type: String })
109
+ y([
110
+ o({ type: String })
98
111
  ], c.prototype, "status");
99
- h([
100
- n({ type: Number })
112
+ y([
113
+ o({ type: Number })
101
114
  ], c.prototype, "progress");
102
- h([
103
- n({ type: String })
115
+ y([
116
+ o({ type: String })
104
117
  ], c.prototype, "errorMessage");
105
118
  customElements.define("nys-fileitem", c);
106
- const w = ':host{--_nys-fileinput-gap: var(--nys-space-100, 8px);--_nys-fileinput-font-size: var(--nys-font-size-ui-md, 16px);--_nys-fileinput-font-weight: var(--nys-font-weight-semibold, 600);--_nys-fileinput-line-height: var(--nys-font-lineheight-ui-md, 24px);--_nys-fileinput-font-family: var( --nys-font-family-ui, var( --nys-font-family-sans, "Proxima Nova", "Helvetica Neue", "Helvetica", "Arial", sans-serif ) );--_nys-fileinput-background-color--dropzone: var( --nys-color-ink-reverse, #fff );--_nys-fileinput-background-color--dropzone--disabled: var( --nys-color-neutral-10, #f6f6f6 );--_nys-fileinput-background-color--dropzone--active: var( --nys-color-theme-faint, #f7fafd );--_nys-fileinput-border-radius--dropzone: var( --nys-radius-lg, var(--nys-space-100, 8px) );--_nys-fileinput-border-style: dashed;--_nys-fileinput-border-color: var(--nys-color-neutral-200, #bec0c1);--_nys-fileinput-border-width: var(--nys-border-width-sm, 1px)}.nys-fileinput{display:flex;flex-direction:column;align-items:flex-start;justify-content:center;gap:var(--_nys-fileinput-gap);font-family:var(--_nys-fileinput-font-family);font-size:var(--_nys-fileinput-font-size);font-weight:var(--_nys-fileinput-font-weight);line-height:var(--_nys-fileinput-line-height)}:host([width=lg]) .nys-fileinput{max-width:var(--nys-form-width-lg, 384px)}ul{list-style-type:none;padding:0;margin:0;width:100%;display:flex;flex-direction:column;gap:var(--_nys-fileinput-gap)}.nys-fileinput__dropzone{display:flex;padding:var(--nys-space-400, 32px) var(--nys-space-200, 16px);justify-content:center;align-items:center;gap:12px;align-self:stretch;border-radius:var(--_nys-fileinput-border-radius--dropzone);outline:var(--_nys-fileinput-border-width) var(--_nys-fileinput-border-style) var(--_nys-fileinput-border-color);background-color:var(--_nys-fileinput-background-color--dropzone);transition:all 60ms ease-in-out}.nys-fileinput__dropzone:hover{cursor:pointer;--_nys-fileinput-border-width: var(--nys-border-width-md, 2px);--_nys-fileinput-border-color: var(--nys-color-neutral-700, #4a4d4f)}.nys-fileinput__dropzone.drag-active{--_nys-fileinput-border-width: var(--nys-border-width-md, 2px);--_nys-fileinput-border-color: var(--nys-color-theme, #154973);--_nys-fileinput-border-style: solid}.nys-fileinput__dropzone.error{--_nys-fileinput-border-color: var(--nys-color-danger, #b52c2c)}.nys-fileinput__dropzone.error:hover{--_nys-fileinput-border-width: var(--nys-border-width-md, 2px);--_nys-fileinput-border-color: var(--nys-color-emergency, #721c1c)}.nys-fileinput__dropzone.disabled{cursor:not-allowed;--_nys-fileinput-border-color: var(--nys-color-neutral-300, #a7a9ab);--_nys-fileinput-border-width: var(--nys-border-width-sm, 1px);background-color:var(--_nys-fileinput-background-color--dropzone--disabled);color:var(--_nys-fileinput-color--dropzone--disabled)}progress{display:flex;width:100%;height:6px;border-radius:var(--nys-radius-round, 1776px);background-color:var(--_nys-fileinput-progress-background);overflow:hidden;appearance:none;border:none}progress::-moz-progress-bar{background-color:var(--_nys-fileinput-progress-background)}progress::-webkit-progress-value{background-color:var(--_nys-fileinput-progress-background)}progress::-webkit-progress-bar{background-color:var(--_nys-fileinput-progress-background)}';
119
+ const w = ':host{--_nys-fileinput-gap: var(--nys-space-100, 8px);--_nys-fileinput-font-size: var(--nys-font-size-ui-md, 16px);--_nys-fileinput-font-weight: var(--nys-font-weight-semibold, 600);--_nys-fileinput-line-height: var(--nys-font-lineheight-ui-md, 24px);--_nys-fileinput-font-family: var( --nys-font-family-ui, var( --nys-font-family-sans, "Proxima Nova", "Helvetica Neue", "Helvetica", "Arial", sans-serif ) );--_nys-fileinput-background-color--dropzone: var( --nys-color-ink-reverse, #ffffff );--_nys-fileinput-background-color--dropzone--disabled: var( --nys-color-neutral-10, #f6f6f6 );--_nys-fileinput-background-color--dropzone--active: var( --nys-color-theme-faint, #f7fafd );--_nys-fileinput-border-radius--dropzone: var( --nys-radius-lg, var(--nys-space-100, 8px) );--_nys-fileinput-border-style: dashed;--_nys-fileinput-border-color: var(--nys-color-neutral-200, #bec0c1);--_nys-fileinput-border-width: var(--nys-border-width-sm, 1px)}.nys-fileinput{display:flex;flex-direction:column;align-items:flex-start;justify-content:center;gap:var(--_nys-fileinput-gap);font-family:var(--_nys-fileinput-font-family);font-size:var(--_nys-fileinput-font-size);font-weight:var(--_nys-fileinput-font-weight);line-height:var(--_nys-fileinput-line-height)}:host([width=lg]) .nys-fileinput{max-width:var(--nys-form-width-lg, 384px)}ul{list-style-type:none;padding:0;margin:0;width:100%;display:flex;flex-direction:column;gap:var(--_nys-fileinput-gap)}.nys-fileinput__dropzone{display:flex;padding:var(--nys-space-400, 32px) var(--nys-space-200, 16px);justify-content:center;align-items:center;gap:12px;align-self:stretch;border-radius:var(--_nys-fileinput-border-radius--dropzone);outline:var(--_nys-fileinput-border-width) var(--_nys-fileinput-border-style) var(--_nys-fileinput-border-color);background-color:var(--_nys-fileinput-background-color--dropzone);transition:all 60ms ease-in-out}.nys-fileinput__dropzone:hover{cursor:pointer;--_nys-fileinput-border-width: var(--nys-border-width-md, 2px);--_nys-fileinput-border-color: var(--nys-color-neutral-700, #4a4d4f)}.nys-fileinput__dropzone.drag-active{--_nys-fileinput-border-width: var(--nys-border-width-md, 2px);--_nys-fileinput-border-color: var(--nys-color-theme, #154973);--_nys-fileinput-border-style: solid}.nys-fileinput__dropzone.error{--_nys-fileinput-border-color: var(--nys-color-danger, #b52c2c)}.nys-fileinput__dropzone.error:hover{--_nys-fileinput-border-width: var(--nys-border-width-md, 2px);--_nys-fileinput-border-color: var(--nys-color-emergency, #721c1c)}.nys-fileinput__dropzone.disabled{cursor:not-allowed;--_nys-fileinput-border-color: var(--nys-color-neutral-300, #a7a9ab);--_nys-fileinput-border-width: var(--nys-border-width-sm, 1px);background-color:var(--_nys-fileinput-background-color--dropzone--disabled);color:var(--_nys-fileinput-color--dropzone--disabled)}progress{display:flex;width:100%;height:6px;border-radius:var(--nys-radius-round, 1776px);background-color:var(--_nys-fileinput-progress-background);overflow:hidden;appearance:none;border:none}progress::-moz-progress-bar{background-color:var(--_nys-fileinput-progress-background)}progress::-webkit-progress-value{background-color:var(--_nys-fileinput-progress-background)}progress::-webkit-progress-bar{background-color:var(--_nys-fileinput-progress-background)}';
107
120
  var $ = Object.defineProperty, l = (p, e, t, i) => {
108
121
  for (var s = void 0, r = p.length - 1, d; r >= 0; r--)
109
122
  (d = p[r]) && (s = d(e, t, s) || s);
110
123
  return s && $(e, t, s), s;
111
124
  };
112
125
  let F = 0;
113
- const f = class f extends y {
126
+ const f = class f extends h {
114
127
  // allows use of elementInternals' API
115
128
  constructor() {
116
129
  super(), this.id = "", this.name = "", this.label = "", this.description = "", this.multiple = !1, this.form = null, this.tooltip = "", this.accept = "", this.disabled = !1, this.required = !1, this.optional = !1, this.showError = !1, this.errorMessage = "", this.dropzone = !1, this.width = "full", this.inverted = !1, this._selectedFiles = [], this._dragActive = !1, this._internals = this.attachInternals();
@@ -335,6 +348,7 @@ const f = class f extends y {
335
348
  @nys-fileRemove=${this._handleFileRemove}
336
349
  >
337
350
  <nys-label
351
+ for=${this.id}
338
352
  label=${this.label}
339
353
  description=${this.description}
340
354
  flag=${this.required ? "required" : this.optional ? "optional" : ""}
@@ -345,6 +359,7 @@ const f = class f extends y {
345
359
  </nys-label>
346
360
 
347
361
  <input
362
+ id=${this.id}
348
363
  class="hidden-file-input"
349
364
  tabindex="-1"
350
365
  type="file"
@@ -419,58 +434,61 @@ const f = class f extends y {
419
434
  </div>`;
420
435
  }
421
436
  };
422
- f.styles = g(w), f.formAssociated = !0;
423
- let o = f;
437
+ f.styles = g(w), f.shadowRootOptions = {
438
+ ...h.shadowRootOptions,
439
+ delegatesFocus: !0
440
+ }, f.formAssociated = !0;
441
+ let n = f;
424
442
  l([
425
- n({ type: String, reflect: !0 })
426
- ], o.prototype, "id");
443
+ o({ type: String, reflect: !0 })
444
+ ], n.prototype, "id");
427
445
  l([
428
- n({ type: String, reflect: !0 })
429
- ], o.prototype, "name");
446
+ o({ type: String, reflect: !0 })
447
+ ], n.prototype, "name");
430
448
  l([
431
- n({ type: String })
432
- ], o.prototype, "label");
449
+ o({ type: String })
450
+ ], n.prototype, "label");
433
451
  l([
434
- n({ type: String })
435
- ], o.prototype, "description");
452
+ o({ type: String })
453
+ ], n.prototype, "description");
436
454
  l([
437
- n({ type: Boolean })
438
- ], o.prototype, "multiple");
455
+ o({ type: Boolean })
456
+ ], n.prototype, "multiple");
439
457
  l([
440
- n({ type: String, reflect: !0 })
441
- ], o.prototype, "form");
458
+ o({ type: String, reflect: !0 })
459
+ ], n.prototype, "form");
442
460
  l([
443
- n({ type: String })
444
- ], o.prototype, "tooltip");
461
+ o({ type: String })
462
+ ], n.prototype, "tooltip");
445
463
  l([
446
- n({ type: String })
447
- ], o.prototype, "accept");
464
+ o({ type: String })
465
+ ], n.prototype, "accept");
448
466
  l([
449
- n({ type: Boolean, reflect: !0 })
450
- ], o.prototype, "disabled");
467
+ o({ type: Boolean, reflect: !0 })
468
+ ], n.prototype, "disabled");
451
469
  l([
452
- n({ type: Boolean, reflect: !0 })
453
- ], o.prototype, "required");
470
+ o({ type: Boolean, reflect: !0 })
471
+ ], n.prototype, "required");
454
472
  l([
455
- n({ type: Boolean, reflect: !0 })
456
- ], o.prototype, "optional");
473
+ o({ type: Boolean, reflect: !0 })
474
+ ], n.prototype, "optional");
457
475
  l([
458
- n({ type: Boolean, reflect: !0 })
459
- ], o.prototype, "showError");
476
+ o({ type: Boolean, reflect: !0 })
477
+ ], n.prototype, "showError");
460
478
  l([
461
- n({ type: String })
462
- ], o.prototype, "errorMessage");
479
+ o({ type: String })
480
+ ], n.prototype, "errorMessage");
463
481
  l([
464
- n({ type: Boolean })
465
- ], o.prototype, "dropzone");
482
+ o({ type: Boolean })
483
+ ], n.prototype, "dropzone");
466
484
  l([
467
- n({ type: String, reflect: !0 })
468
- ], o.prototype, "width");
485
+ o({ type: String, reflect: !0 })
486
+ ], n.prototype, "width");
469
487
  l([
470
- n({ type: Boolean, reflect: !0 })
471
- ], o.prototype, "inverted");
472
- customElements.get("nys-fileinput") || customElements.define("nys-fileinput", o);
488
+ o({ type: Boolean, reflect: !0 })
489
+ ], n.prototype, "inverted");
490
+ customElements.get("nys-fileinput") || customElements.define("nys-fileinput", n);
473
491
  export {
474
- o as NysFileinput
492
+ n as NysFileinput
475
493
  };
476
494
  //# sourceMappingURL=nys-fileinput.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"nys-fileinput.js","sources":["../src/validateFileHeader.ts","../src/nys-fileitem.ts","../src/nys-fileinput.ts"],"sourcesContent":["// The main function for file validation based only on extension and `accept` attribute.\nexport async function validateFileHeader(\n file: File,\n accept: string,\n): Promise<boolean> {\n // 1) If no accept attribute is defined, assume anything is allowed\n if (!accept || accept.trim() === \"\") return true;\n\n // 2) Normalize and parse the accept attribute\n const acceptItems = accept\n .toLowerCase()\n .split(\",\")\n .map((a) => a.trim());\n\n // 3) Get the file extension\n const filename = file.name.toLowerCase();\n const fileExt = filename.includes(\".\") ? filename.split(\".\").pop()! : \"\";\n\n // 4) Check if extension matches any of the accept items\n for (const acceptItem of acceptItems) {\n // Direct extension match (e.g. \".pdf\")\n if (acceptItem.startsWith(\".\") && acceptItem.slice(1) === fileExt) {\n return true;\n }\n\n // Wildcard /* (e.g. \"image/*\") -> match common prefixes\n if (\n acceptItem.endsWith(\"/*\") &&\n file.type.startsWith(acceptItem.slice(0, -1))\n ) {\n return true;\n }\n\n // Exact MIME match\n if (file.type === acceptItem) {\n return true;\n }\n }\n\n // 5) Not matched\n return false;\n}\n","import { LitElement, html, unsafeCSS } from \"lit\";\nimport { property } from \"lit/decorators.js\";\n// @ts-ignore: SCSS module imported via bundler as inline\nimport styles from \"./nys-fileitem.scss?inline\";\n\n/**\n * **Internal component.** Displays an individual file within `nys-fileinput` with status and progress.\n *\n * Rendered automatically by `nys-fileinput` for each selected file. Shows filename, upload status\n * (pending/processing/done/error), progress bar during upload, and error messages. Remove button emits event.\n *\n * @summary Internal file item display with status, progress bar, and remove action.\n * @element nys-fileitem\n *\n * @fires nys-fileRemove - Fired when remove button is clicked. Detail: `{filename}`.\n */\nexport class NysFileItem extends LitElement {\n static styles = unsafeCSS(styles);\n\n /** Name of the file being displayed. */\n @property({ type: String }) filename = \"\";\n\n /**\n * Upload status: `pending` (queued), `processing` (uploading), `done` (complete), `error` (failed).\n * @default \"pending\"\n */\n @property({ type: String }) status:\n | \"pending\"\n | \"processing\"\n | \"done\"\n | \"error\" = \"pending\";\n\n /** Upload progress percentage (0-100). Only shown when status is `processing`. */\n @property({ type: Number }) progress = 0;\n\n /** Error message displayed when status is `error`. */\n @property({ type: String }) errorMessage = \"\";\n\n private _handleRemove() {\n this.dispatchEvent(\n new CustomEvent(\"nys-fileRemove\", {\n detail: { filename: this.filename },\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n private splitFilename(filename: string) {\n const lastDotIndex = filename.lastIndexOf(\".\");\n const extension = lastDotIndex !== -1 ? filename.slice(lastDotIndex) : \"\"; // e.g. \".pdf\"\n const name =\n lastDotIndex !== -1 ? filename.slice(0, lastDotIndex) : filename;\n\n const startPart = name.slice(0, name.length - 3);\n const endPart = name.slice(-3);\n\n return { startPart, endPart, extension };\n }\n\n render() {\n const { startPart, endPart, extension } = this.splitFilename(this.filename);\n\n return html`\n <div\n class=\"file-item ${this.status}\"\n aria-busy=${this.status === \"processing\" ? \"true\" : \"false\"}\n aria-label=\"You have selected ${this.filename}\"\n >\n <div class=\"file-item__main\" role=\"group\">\n <nys-icon\n class=\"file-icon\"\n name=${this.status === \"processing\"\n ? \"progress_activity\"\n : this.status === \"error\"\n ? \"error\"\n : \"attach_file\"}\n size=\"2xl\"\n ></nys-icon>\n <div class=\"file-item__info\">\n <div class=\"file-item__info-name\">\n <span class=\"file-item__info-name-start\">${startPart}</span>\n <span class=\"file-item__info-name-end\"\n >${endPart}${extension}</span\n >\n </div>\n ${this.errorMessage\n ? html`<p\n class=\"file-item__error\"\n role=\"alert\"\n aria-live=\"assertive\"\n aria-invalid=\"true\"\n aria-errormessage=${this.errorMessage}\n id=\"${this.filename}-error\"\n >\n ${this.errorMessage}\n </p>`\n : null}\n </div>\n <nys-button\n circle\n icon=\"close\"\n ariaLabel=\"close button\"\n size=\"sm\"\n variant=\"ghost\"\n @nys-click=${this._handleRemove}\n ariaLabel=\"Remove file: ${this.filename}\"\n ></nys-button>\n </div>\n ${this.status === \"processing\"\n ? html`<div\n class=\"file-item__progress-container\"\n role=\"progressbar\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n aria-valuenow=\"${this.progress}\"\n aria-label=\"Upload progress for ${this.filename}\"\n >\n <progress value=${this.progress} max=\"100\"></progress>\n </div>`\n : null}\n </div>\n `;\n }\n}\n\ncustomElements.define(\"nys-fileitem\", NysFileItem);\n","import { LitElement, html, unsafeCSS } from \"lit\";\nimport { property } from \"lit/decorators.js\";\nimport { ifDefined } from \"lit/directives/if-defined.js\";\nimport { validateFileHeader } from \"./validateFileHeader\";\nimport \"./nys-fileitem\";\n// @ts-ignore: SCSS module imported via bundler as inline\nimport styles from \"./nys-fileinput.scss?inline\";\n\nlet fileinputIdCounter = 0;\n\ninterface FileWithProgress {\n file: File;\n progress: number;\n status: \"pending\" | \"processing\" | \"done\" | \"error\";\n errorMsg?: string;\n}\n\n/**\n * A file input for uploading files with support for multiple files, drag-and-drop, and progress tracking.\n * Validates file types via magic bytes (not just extension). Form-associated via ElementInternals.\n *\n * Use for document uploads, image uploads, or any file submission. Enable `dropzone` for drag-and-drop UI.\n *\n * @summary File input with drag-and-drop, validation, and progress tracking.\n * @element nys-fileinput\n *\n * @slot description - Custom HTML description content.\n *\n * @fires nys-change - Fired when files are added or removed. Detail: `{id, files}`.\n *\n * @example Single file upload\n * ```html\n * <nys-fileinput label=\"Upload document\" accept=\".pdf,.doc\" required></nys-fileinput>\n * ```\n *\n * @example Multiple files with dropzone\n * ```html\n * <nys-fileinput label=\"Upload images\" accept=\"image/*\" multiple dropzone></nys-fileinput>\n * ```\n */\n\nexport class NysFileinput extends LitElement {\n static styles = unsafeCSS(styles);\n\n /** Unique identifier. Auto-generated if not provided. */\n @property({ type: String, reflect: true }) id = \"\";\n\n /** Name for form submission. */\n @property({ type: String, reflect: true }) name = \"\";\n\n /** Visible label text. */\n @property({ type: String }) label = \"\";\n\n /** Helper text below label. Use slot for custom HTML. */\n @property({ type: String }) description = \"\";\n\n /** Allows selecting multiple files. */\n @property({ type: Boolean }) multiple = false;\n\n /** Form `id` to associate with. */\n @property({ type: String, reflect: true }) form: string | null = null;\n\n /** Tooltip text shown on hover/focus of info icon. */\n @property({ type: String }) tooltip = \"\";\n\n /** Accepted file types. Use MIME types (`image/*`) or extensions (`.pdf`). Validated via magic bytes. */\n @property({ type: String }) accept = \"\";\n\n /** Prevents interaction. */\n @property({ type: Boolean, reflect: true }) disabled = false;\n\n /** Requires at least one file to be uploaded. */\n @property({ type: Boolean, reflect: true }) required = false;\n\n /** Shows \"Optional\" flag. */\n @property({ type: Boolean, reflect: true }) optional = false;\n\n /** Shows error message when true. */\n @property({ type: Boolean, reflect: true }) showError = false;\n\n /** Error message text. Shown only when `showError` is true. */\n @property({ type: String }) errorMessage = \"\";\n\n /** Enables drag-and-drop zone UI. */\n @property({ type: Boolean }) dropzone = false;\n\n /**\n * Component width: `lg` (384px) or `full` (100%, default).\n * @default \"full\"\n */\n @property({ type: String, reflect: true }) width: \"lg\" | \"full\" = \"full\";\n\n /** Adjusts colors for dark backgrounds. */\n @property({ type: Boolean, reflect: true }) inverted = false;\n\n private _selectedFiles: FileWithProgress[] = [];\n private _dragActive = false;\n private get _isDropDisabled(): boolean {\n return this.disabled || (!this.multiple && this._selectedFiles.length > 0);\n }\n\n private get _buttonAriaLabel(): string {\n if (this._selectedFiles.length === 0) {\n return this.multiple ? \"Choose files: \" : \"Choose file: \";\n }\n\n return this.multiple ? \"Change files: \" : \"Change file: \";\n }\n\n private get _buttonAriaDescription(): string {\n if (this._selectedFiles.length === 0)\n return `${this.label + \" \" + this.description}`;\n\n const hasInvalidFiles = this._selectedFiles.some(\n (file) => file.status === \"error\",\n );\n\n let base = \"\";\n\n if (this._selectedFiles.length === 1) {\n base = `You have selected ${this._selectedFiles[0].file.name}.`;\n } else {\n const fileNames = this._selectedFiles.map((f) => f.file.name).join(\", \");\n base = `You have selected ${this._selectedFiles.length} files: ${fileNames}`;\n }\n\n const error = hasInvalidFiles\n ? \" Error: One or more files are not valid file types.\"\n : \"\";\n\n return `${base}${error}`;\n }\n\n private get _innerNysButton(): HTMLElement | null {\n const nysButton = this.renderRoot.querySelector(\n '[name=\"file-btn\"]',\n ) as HTMLButtonElement | null;\n const innerButton = nysButton?.shadowRoot?.querySelector(\n \"button\",\n ) as HTMLElement | null;\n return innerButton;\n }\n\n private _internals: ElementInternals;\n\n /**\n * Lifecycle methods\n * --------------------------------------------------------------------------\n */\n\n static formAssociated = true; // allows use of elementInternals' API\n\n constructor() {\n super();\n this._internals = this.attachInternals();\n }\n\n // Generate a unique ID if one is not provided\n connectedCallback() {\n super.connectedCallback();\n if (!this.id) {\n this.id = `nys-fileinput-${Date.now()}-${fileinputIdCounter++}`;\n }\n\n this.addEventListener(\"invalid\", this._handleInvalid);\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this.removeEventListener(\"invalid\", this._handleInvalid);\n }\n\n firstUpdated() {\n // This ensures our element always participates in the form\n this._setValue();\n }\n\n /**\n * Form Integration\n * --------------------------------------------------------------------------\n */\n private _setValue() {\n // for multiple file uploads, we upload File object as an array\n if (this.multiple) {\n const files = this._selectedFiles.map((entry) => entry.file);\n\n if (files.length > 0) {\n const formData = new FormData();\n files.forEach((file) => {\n formData.append(this.name, file);\n });\n this._internals.setFormValue(formData);\n } else {\n this._internals.setFormValue(null);\n }\n } else {\n const singleFile = this._selectedFiles[0]?.file || null;\n this._internals.setFormValue(singleFile);\n }\n\n this._manageRequire(); // Check validation when value is set\n }\n\n // Called to internally set the initial internalElement required flag.\n private _manageRequire() {\n const input = this.shadowRoot?.querySelector(\"input\");\n if (!input) return;\n\n const message = this.errorMessage || \"Please upload a file.\";\n const isInvalid = this.required && this._selectedFiles.length == 0;\n\n if (isInvalid) {\n this._internals.ariaRequired = \"true\"; // Screen readers should announce error\n this._internals.setValidity({ valueMissing: true }, message, input);\n } else {\n this._internals.ariaRequired = \"false\"; // Reset when valid\n this._internals.setValidity({}, \"\", input);\n }\n }\n\n private _setValidityMessage(message: string = \"\") {\n const input = this.shadowRoot?.querySelector(\"input\");\n if (!input) return;\n\n // Toggle the HTML <div> tag error message\n this.showError = message === (this.errorMessage || \"Please upload a file.\");\n\n // If user sets errorMessage, this will always override the native validation message\n if (this.errorMessage?.trim() && message !== \"\") {\n message = this.errorMessage;\n }\n\n this._internals.setValidity(\n message ? { customError: true } : {},\n message,\n input,\n );\n }\n\n private _validate() {\n const hasErrorFiles = this._selectedFiles.some(\n (entry) => entry.status === \"error\",\n );\n const isEmpty = this.required && this._selectedFiles.length === 0;\n\n let message = \"\";\n if (isEmpty) {\n message = this.errorMessage || \"Please upload a file.\";\n } else if (hasErrorFiles) {\n message = \"One or more files are invalid.\";\n }\n\n this._setValidityMessage(message);\n }\n\n // This helper function is called to perform the element's native validation.\n checkValidity(): boolean {\n const input = this.shadowRoot?.querySelector(\"input\");\n return input ? input.checkValidity() : true;\n }\n\n // Called automatically when the parent form is reset\n public formResetCallback() {\n this._selectedFiles = [];\n const input = this.shadowRoot?.querySelector(\n \".hidden-file-input\",\n ) as HTMLInputElement | null;\n\n if (input) {\n input.value = \"\";\n }\n\n this._internals.setFormValue(null);\n\n // Reset validation UI\n this.showError = false;\n this.errorMessage = \"\";\n this._internals.setValidity({});\n\n // Re-render UI\n this.requestUpdate();\n }\n\n private _handleInvalid(event: Event) {\n event.preventDefault();\n this._validate();\n\n const innerButton = this._innerNysButton;\n if (innerButton) {\n // Focus only if this is the first invalid element (top-down approach)\n const form = this._internals.form;\n if (form) {\n const elements = Array.from(form.elements) as Array<\n HTMLElement & { checkValidity?: () => boolean }\n >;\n // Find the first element in the form that is invalid\n const firstInvalidElement = elements.find(\n (element) =>\n typeof element.checkValidity === \"function\" &&\n !element.checkValidity(),\n );\n if (firstInvalidElement === this) {\n innerButton.focus();\n innerButton.classList.add(\"active-focus\"); // This class styling is found within <nys-button>\n }\n } else {\n // If not part of a form, simply focus.\n innerButton.focus();\n innerButton.classList.add(\"active-focus\"); // This class styling is found within <nys-button>\n }\n }\n }\n\n /**\n * Functions\n * --------------------------------------------------------------------------\n */\n\n // Store the files to be displayed\n private async _saveSelectedFiles(file: File) {\n const isDuplicate = this._selectedFiles.some(\n (existingFile) => existingFile.file.name == file.name,\n );\n if (isDuplicate) return;\n\n if (!this.multiple && this._selectedFiles.length >= 1) return;\n\n const entry: FileWithProgress = {\n file,\n progress: 0,\n status: \"pending\",\n };\n\n this._selectedFiles.push(entry);\n await this._processFile(entry);\n\n // Now that the file is added, update form value and validation\n this._setValue();\n this._validate();\n }\n\n // Read the contents of stored files, this will indicate loading progress of the uploaded files\n private async _processFile(entry: FileWithProgress) {\n entry.status = \"processing\";\n\n try {\n const isValid = await validateFileHeader(entry.file, this.accept);\n if (!isValid) {\n entry.status = \"error\";\n entry.errorMsg = \"File type is invalid.\";\n this.requestUpdate();\n return;\n }\n\n const reader = new FileReader();\n\n reader.onprogress = (e) => {\n if (e.lengthComputable) {\n const percentage = Math.round((e.loaded * 100) / e.total);\n entry.progress = percentage;\n this.requestUpdate();\n }\n };\n\n reader.onload = () => {\n entry.progress = 100;\n entry.status = \"done\";\n this.requestUpdate();\n };\n\n reader.onerror = () => {\n entry.status = \"error\";\n entry.errorMsg = \"Failed to load file.\";\n this.requestUpdate();\n };\n\n reader.readAsArrayBuffer(entry.file);\n } catch {\n entry.status = \"error\";\n entry.errorMsg = \"Error validating file.\";\n this.requestUpdate();\n }\n }\n\n private _dispatchChangeEvent() {\n this.dispatchEvent(\n new CustomEvent(\"nys-change\", {\n detail: { id: this.id, files: this._selectedFiles },\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n private _openFileDialog() {\n const input = this.renderRoot.querySelector(\n \".hidden-file-input\",\n ) as HTMLInputElement;\n\n input?.click();\n }\n\n private _handlePostFileSelectionFocus() {\n if (this.multiple) {\n const innerButton = this._innerNysButton;\n\n if (innerButton) {\n innerButton.focus();\n }\n } else {\n this._focusFirstFileItemIfSingleMode();\n }\n }\n\n private async _focusFirstFileItemIfSingleMode() {\n if (!this.multiple) {\n await this.updateComplete;\n const fileItem = this.renderRoot.querySelector(\n \"nys-fileitem\",\n ) as HTMLElement;\n\n const innerFileItemMainContainer = fileItem?.shadowRoot?.querySelector(\n \".file-item\",\n ) as HTMLElement | null;\n\n if (innerFileItemMainContainer) {\n innerFileItemMainContainer.setAttribute(\"tabindex\", \"-1\");\n innerFileItemMainContainer.focus();\n }\n }\n }\n\n /**\n * Event Handlers\n * --------------------------------------------------------------------------\n */\n\n // Access the selected files & add new files to the internal list via the hidden <input type=\"file\">\n private _handleFileChange(e: Event) {\n const input = e.target as HTMLInputElement;\n const files = input.files;\n const newFiles = files ? Array.from(files) : []; // changes FileList to array\n\n // Store the uploaded files\n newFiles.map((file) => {\n this._saveSelectedFiles(file);\n });\n\n this.requestUpdate();\n this._dispatchChangeEvent();\n this._handlePostFileSelectionFocus();\n }\n\n private _handleFileRemove(e: CustomEvent) {\n const filenameToRemove = e.detail.filename;\n\n // Remove selected files\n this._selectedFiles = this._selectedFiles.filter(\n (existingFile) => existingFile.file.name !== filenameToRemove,\n );\n\n if (this._selectedFiles.length === 0) {\n const input = this.shadowRoot?.querySelector(\n \"input\",\n ) as HTMLInputElement | null;\n if (input) input.value = \"\";\n }\n\n this._setValue();\n this._validate();\n\n this.requestUpdate();\n this._dispatchChangeEvent();\n }\n\n private _onDragOver(e: DragEvent) {\n if (this.disabled) return;\n\n e.stopPropagation();\n e.preventDefault();\n if (!this._dragActive) {\n this._dragActive = true; // For styling purpose\n this.requestUpdate();\n }\n }\n\n // Mostly used for styling purpose\n private _onDragLeave(e: DragEvent) {\n if (this.disabled) return;\n\n e.stopPropagation();\n e.preventDefault();\n // Only reset if leaving the dropzone itself (not children)\n if (e.currentTarget === e.target) {\n this._dragActive = false; // For styling purpose\n this.requestUpdate();\n }\n }\n\n private _onDrop(e: DragEvent) {\n if (this.disabled) return;\n\n e.preventDefault();\n this._dragActive = false; // For styling purpose\n this.requestUpdate();\n\n const files = e.dataTransfer?.files;\n if (!files) return;\n\n const newFiles = Array.from(files);\n\n if (this.multiple) {\n newFiles.forEach((file) => {\n this._saveSelectedFiles(file);\n });\n } else {\n this._saveSelectedFiles(newFiles[0]);\n }\n\n this.requestUpdate();\n this._dispatchChangeEvent();\n }\n\n render() {\n return html`<div\n class=\"nys-fileinput\"\n @nys-fileRemove=${this._handleFileRemove}\n >\n <nys-label\n label=${this.label}\n description=${this.description}\n flag=${this.required ? \"required\" : this.optional ? \"optional\" : \"\"}\n tooltip=${this.tooltip}\n ?inverted=${this.inverted}\n >\n <slot name=\"description\" slot=\"description\">${this.description}</slot>\n </nys-label>\n\n <input\n class=\"hidden-file-input\"\n tabindex=\"-1\"\n type=\"file\"\n name=${this.name}\n accept=${this.accept}\n form=${ifDefined(this.form || undefined)}\n ?multiple=${this.multiple}\n ?required=${this.required}\n ?disabled=${this.disabled ||\n (!this.multiple && this._selectedFiles.length > 0)}\n aria-disabled=\"${this.disabled}\"\n aria-hidden=\"true\"\n @change=${this._handleFileChange}\n hidden\n />\n\n ${!this.dropzone\n ? html`<nys-button\n id=\"choose-files-btn\"\n name=\"file-btn\"\n label=${this.multiple ? \"Choose files\" : \"Choose file\"}\n variant=\"outline\"\n ariaLabel=${this._buttonAriaLabel}\n ariaDescription=${this._buttonAriaDescription}\n ?disabled=${this.disabled ||\n (!this.multiple && this._selectedFiles.length > 0)}\n @nys-click=${this._openFileDialog}\n ></nys-button>`\n : html`<div\n class=\"nys-fileinput__dropzone\n ${this._dragActive ? \"drag-active\" : \"\"}\n ${this._isDropDisabled ? \"disabled\" : \"\"}\n ${this.showError && !this._isDropDisabled ? \"error\" : \"\"}\"\n @click=${this._isDropDisabled\n ? null\n : (e: MouseEvent) => {\n const target = e.target as HTMLElement;\n\n // Ignore clicks that originated within a nys-button\n if (target.closest(\"nys-button\")) return;\n\n // Only handle direct wrapper clicks (outside of buttons)\n this._openFileDialog();\n }}\n @dragover=${this._isDropDisabled ? null : this._onDragOver}\n @dragleave=${this._isDropDisabled ? null : this._onDragLeave}\n @drop=${this._isDropDisabled ? null : this._onDrop}\n aria-label=\"Drag files here or choose from folder\"\n >\n ${this._dragActive\n ? html`<p>Drop file to upload</p>`\n : html` <nys-button\n id=\"choose-files-btn-drag\"\n name=\"file-btn\"\n label=${this.multiple ? \"Choose files\" : \"Choose file\"}\n variant=\"outline\"\n ariaLabel=${this._buttonAriaLabel}\n ariaDescription=${this._buttonAriaDescription}\n ?disabled=${this._isDropDisabled}\n @nys-click=\"${(e: CustomEvent) => {\n e.preventDefault();\n e.stopPropagation();\n this._openFileDialog();\n }}\"\n ></nys-button>\n <p>or drag here</p>`}\n </div>`}\n ${this.showError\n ? html`\n <nys-errormessage\n ?showError=${this.showError}\n errorMessage=${this._internals.validationMessage ||\n this.errorMessage}\n ></nys-errormessage>\n `\n : null}\n ${this._selectedFiles.length > 0\n ? html`\n <ul>\n ${this._selectedFiles.map(\n (entry) =>\n html`<li>\n <nys-fileitem\n filename=${entry.file.name}\n status=${entry.status}\n progress=${entry.progress}\n errorMessage=${entry.errorMsg || \"\"}\n ></nys-fileitem>\n </li>`,\n )}\n </ul>\n `\n : null}\n </div>`;\n }\n}\n\nif (!customElements.get(\"nys-fileinput\")) {\n customElements.define(\"nys-fileinput\", NysFileinput);\n}\n"],"names":["validateFileHeader","file","accept","acceptItems","a","filename","fileExt","acceptItem","_NysFileItem","LitElement","lastDotIndex","extension","name","startPart","endPart","html","unsafeCSS","styles","NysFileItem","__decorateClass","property","fileinputIdCounter","_NysFileinput","hasInvalidFiles","base","fileNames","f","files","entry","formData","singleFile","input","message","hasErrorFiles","isEmpty","event","innerButton","form","element","existingFile","reader","e","percentage","innerFileItemMainContainer","filenameToRemove","newFiles","ifDefined","NysFileinput"],"mappings":";;;AACA,eAAsBA,EACpBC,GACAC,GACkB;AAElB,MAAI,CAACA,KAAUA,EAAO,KAAA,MAAW,GAAI,QAAO;AAG5C,QAAMC,IAAcD,EACjB,YAAA,EACA,MAAM,GAAG,EACT,IAAI,CAACE,MAAMA,EAAE,KAAA,CAAM,GAGhBC,IAAWJ,EAAK,KAAK,YAAA,GACrBK,IAAUD,EAAS,SAAS,GAAG,IAAIA,EAAS,MAAM,GAAG,EAAE,IAAA,IAAS;AAGtE,aAAWE,KAAcJ;AAevB,QAbII,EAAW,WAAW,GAAG,KAAKA,EAAW,MAAM,CAAC,MAAMD,KAMxDC,EAAW,SAAS,IAAI,KACxBN,EAAK,KAAK,WAAWM,EAAW,MAAM,GAAG,EAAE,CAAC,KAM1CN,EAAK,SAASM;AAChB,aAAO;AAKX,SAAO;AACT;;;;;;;ACzBO,MAAMC,IAAN,MAAMA,UAAoBC,EAAW;AAAA,EAArC,cAAA;AAAA,UAAA,GAAA,SAAA,GAIuB,KAAA,WAAW,IAMX,KAAA,SAId,WAGc,KAAA,WAAW,GAGX,KAAA,eAAe;AAAA,EAAA;AAAA,EAEnC,gBAAgB;AACtB,SAAK;AAAA,MACH,IAAI,YAAY,kBAAkB;AAAA,QAChC,QAAQ,EAAE,UAAU,KAAK,SAAA;AAAA,QACzB,SAAS;AAAA,QACT,UAAU;AAAA,MAAA,CACX;AAAA,IAAA;AAAA,EAEL;AAAA,EAEQ,cAAcJ,GAAkB;AACtC,UAAMK,IAAeL,EAAS,YAAY,GAAG,GACvCM,IAAYD,MAAiB,KAAKL,EAAS,MAAMK,CAAY,IAAI,IACjEE,IACJF,MAAiB,KAAKL,EAAS,MAAM,GAAGK,CAAY,IAAIL,GAEpDQ,IAAYD,EAAK,MAAM,GAAGA,EAAK,SAAS,CAAC,GACzCE,IAAUF,EAAK,MAAM,EAAE;AAE7B,WAAO,EAAE,WAAAC,GAAW,SAAAC,GAAS,WAAAH,EAAA;AAAA,EAC/B;AAAA,EAEA,SAAS;AACP,UAAM,EAAE,WAAAE,GAAW,SAAAC,GAAS,WAAAH,EAAA,IAAc,KAAK,cAAc,KAAK,QAAQ;AAE1E,WAAOI;AAAA;AAAA,2BAEgB,KAAK,MAAM;AAAA,oBAClB,KAAK,WAAW,eAAe,SAAS,OAAO;AAAA,wCAC3B,KAAK,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA,mBAKlC,KAAK,WAAW,eACnB,sBACA,KAAK,WAAW,UACd,UACA,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA,yDAK0BF,CAAS;AAAA;AAAA,mBAE/CC,CAAO,GAAGH,CAAS;AAAA;AAAA;AAAA,cAGxB,KAAK,eACHI;AAAA;AAAA;AAAA;AAAA;AAAA,sCAKsB,KAAK,YAAY;AAAA,wBAC/B,KAAK,QAAQ;AAAA;AAAA,oBAEjB,KAAK,YAAY;AAAA,wBAErB,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAQK,KAAK,aAAa;AAAA,sCACL,KAAK,QAAQ;AAAA;AAAA;AAAA,UAGzC,KAAK,WAAW,eACdA;AAAA;AAAA;AAAA;AAAA;AAAA,+BAKmB,KAAK,QAAQ;AAAA,gDACI,KAAK,QAAQ;AAAA;AAAA,gCAE7B,KAAK,QAAQ;AAAA,sBAEjC,IAAI;AAAA;AAAA;AAAA,EAGd;AACF;AA3GEP,EAAO,SAASQ,EAAUC,CAAM;AAD3B,IAAMC,IAANV;AAIuBW,EAAA;AAAA,EAA3BC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAJfF,EAIiB,WAAA,UAAA;AAMAC,EAAA;AAAA,EAA3BC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAVfF,EAUiB,WAAA,QAAA;AAOAC,EAAA;AAAA,EAA3BC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAjBfF,EAiBiB,WAAA,UAAA;AAGAC,EAAA;AAAA,EAA3BC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GApBfF,EAoBiB,WAAA,cAAA;AA0F9B,eAAe,OAAO,gBAAgBA,CAAW;;;;;;;ACtHjD,IAAIG,IAAqB;AAiClB,MAAMC,IAAN,MAAMA,UAAqBb,EAAW;AAAA;AAAA,EA+G3C,cAAc;AACZ,UAAA,GA5GyC,KAAA,KAAK,IAGL,KAAA,OAAO,IAGtB,KAAA,QAAQ,IAGR,KAAA,cAAc,IAGb,KAAA,WAAW,IAGG,KAAA,OAAsB,MAGrC,KAAA,UAAU,IAGV,KAAA,SAAS,IAGO,KAAA,WAAW,IAGX,KAAA,WAAW,IAGX,KAAA,WAAW,IAGX,KAAA,YAAY,IAG5B,KAAA,eAAe,IAGd,KAAA,WAAW,IAMG,KAAA,QAAuB,QAGtB,KAAA,WAAW,IAEvD,KAAQ,iBAAqC,CAAA,GAC7C,KAAQ,cAAc,IA0DpB,KAAK,aAAa,KAAK,gBAAA;AAAA,EACzB;AAAA,EA1DA,IAAY,kBAA2B;AACrC,WAAO,KAAK,YAAa,CAAC,KAAK,YAAY,KAAK,eAAe,SAAS;AAAA,EAC1E;AAAA,EAEA,IAAY,mBAA2B;AACrC,WAAI,KAAK,eAAe,WAAW,IAC1B,KAAK,WAAW,mBAAmB,kBAGrC,KAAK,WAAW,mBAAmB;AAAA,EAC5C;AAAA,EAEA,IAAY,yBAAiC;AAC3C,QAAI,KAAK,eAAe,WAAW;AACjC,aAAO,GAAG,KAAK,QAAQ,MAAM,KAAK,WAAW;AAE/C,UAAMc,IAAkB,KAAK,eAAe;AAAA,MAC1C,CAACtB,MAASA,EAAK,WAAW;AAAA,IAAA;AAG5B,QAAIuB,IAAO;AAEX,QAAI,KAAK,eAAe,WAAW;AACjC,MAAAA,IAAO,qBAAqB,KAAK,eAAe,CAAC,EAAE,KAAK,IAAI;AAAA,SACvD;AACL,YAAMC,IAAY,KAAK,eAAe,IAAI,CAACC,MAAMA,EAAE,KAAK,IAAI,EAAE,KAAK,IAAI;AACvE,MAAAF,IAAO,qBAAqB,KAAK,eAAe,MAAM,WAAWC,CAAS;AAAA,IAC5E;AAMA,WAAO,GAAGD,CAAI,GAJAD,IACV,wDACA,EAEkB;AAAA,EACxB;AAAA,EAEA,IAAY,kBAAsC;AAOhD,WANkB,KAAK,WAAW;AAAA,MAChC;AAAA,IAAA,GAE6B,YAAY;AAAA,MACzC;AAAA,IAAA;AAAA,EAGJ;AAAA;AAAA,EAiBA,oBAAoB;AAClB,UAAM,kBAAA,GACD,KAAK,OACR,KAAK,KAAK,iBAAiB,KAAK,KAAK,IAAIF,GAAoB,KAG/D,KAAK,iBAAiB,WAAW,KAAK,cAAc;AAAA,EACtD;AAAA,EAEA,uBAAuB;AACrB,UAAM,qBAAA,GACN,KAAK,oBAAoB,WAAW,KAAK,cAAc;AAAA,EACzD;AAAA,EAEA,eAAe;AAEb,SAAK,UAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,YAAY;AAElB,QAAI,KAAK,UAAU;AACjB,YAAMM,IAAQ,KAAK,eAAe,IAAI,CAACC,MAAUA,EAAM,IAAI;AAE3D,UAAID,EAAM,SAAS,GAAG;AACpB,cAAME,IAAW,IAAI,SAAA;AACrB,QAAAF,EAAM,QAAQ,CAAC1B,MAAS;AACtB,UAAA4B,EAAS,OAAO,KAAK,MAAM5B,CAAI;AAAA,QACjC,CAAC,GACD,KAAK,WAAW,aAAa4B,CAAQ;AAAA,MACvC;AACE,aAAK,WAAW,aAAa,IAAI;AAAA,IAErC,OAAO;AACL,YAAMC,IAAa,KAAK,eAAe,CAAC,GAAG,QAAQ;AACnD,WAAK,WAAW,aAAaA,CAAU;AAAA,IACzC;AAEA,SAAK,eAAA;AAAA,EACP;AAAA;AAAA,EAGQ,iBAAiB;AACvB,UAAMC,IAAQ,KAAK,YAAY,cAAc,OAAO;AACpD,QAAI,CAACA,EAAO;AAEZ,UAAMC,IAAU,KAAK,gBAAgB;AAGrC,IAFkB,KAAK,YAAY,KAAK,eAAe,UAAU,KAG/D,KAAK,WAAW,eAAe,QAC/B,KAAK,WAAW,YAAY,EAAE,cAAc,GAAA,GAAQA,GAASD,CAAK,MAElE,KAAK,WAAW,eAAe,SAC/B,KAAK,WAAW,YAAY,CAAA,GAAI,IAAIA,CAAK;AAAA,EAE7C;AAAA,EAEQ,oBAAoBC,IAAkB,IAAI;AAChD,UAAMD,IAAQ,KAAK,YAAY,cAAc,OAAO;AACpD,IAAKA,MAGL,KAAK,YAAYC,OAAa,KAAK,gBAAgB,0BAG/C,KAAK,cAAc,KAAA,KAAUA,MAAY,OAC3CA,IAAU,KAAK,eAGjB,KAAK,WAAW;AAAA,MACdA,IAAU,EAAE,aAAa,GAAA,IAAS,CAAA;AAAA,MAClCA;AAAA,MACAD;AAAA,IAAA;AAAA,EAEJ;AAAA,EAEQ,YAAY;AAClB,UAAME,IAAgB,KAAK,eAAe;AAAA,MACxC,CAACL,MAAUA,EAAM,WAAW;AAAA,IAAA,GAExBM,IAAU,KAAK,YAAY,KAAK,eAAe,WAAW;AAEhE,QAAIF,IAAU;AACd,IAAIE,IACFF,IAAU,KAAK,gBAAgB,0BACtBC,MACTD,IAAU,mCAGZ,KAAK,oBAAoBA,CAAO;AAAA,EAClC;AAAA;AAAA,EAGA,gBAAyB;AACvB,UAAMD,IAAQ,KAAK,YAAY,cAAc,OAAO;AACpD,WAAOA,IAAQA,EAAM,cAAA,IAAkB;AAAA,EACzC;AAAA;AAAA,EAGO,oBAAoB;AACzB,SAAK,iBAAiB,CAAA;AACtB,UAAMA,IAAQ,KAAK,YAAY;AAAA,MAC7B;AAAA,IAAA;AAGF,IAAIA,MACFA,EAAM,QAAQ,KAGhB,KAAK,WAAW,aAAa,IAAI,GAGjC,KAAK,YAAY,IACjB,KAAK,eAAe,IACpB,KAAK,WAAW,YAAY,EAAE,GAG9B,KAAK,cAAA;AAAA,EACP;AAAA,EAEQ,eAAeI,GAAc;AACnC,IAAAA,EAAM,eAAA,GACN,KAAK,UAAA;AAEL,UAAMC,IAAc,KAAK;AACzB,QAAIA,GAAa;AAEf,YAAMC,IAAO,KAAK,WAAW;AAC7B,MAAIA,IACe,MAAM,KAAKA,EAAK,QAAQ,EAIJ;AAAA,QACnC,CAACC,MACC,OAAOA,EAAQ,iBAAkB,cACjC,CAACA,EAAQ,cAAA;AAAA,MAAc,MAEC,SAC1BF,EAAY,MAAA,GACZA,EAAY,UAAU,IAAI,cAAc,MAI1CA,EAAY,MAAA,GACZA,EAAY,UAAU,IAAI,cAAc;AAAA,IAE5C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,mBAAmBnC,GAAY;AAM3C,QALoB,KAAK,eAAe;AAAA,MACtC,CAACsC,MAAiBA,EAAa,KAAK,QAAQtC,EAAK;AAAA,IAAA,KAI/C,CAAC,KAAK,YAAY,KAAK,eAAe,UAAU,EAAG;AAEvD,UAAM2B,IAA0B;AAAA,MAC9B,MAAA3B;AAAA,MACA,UAAU;AAAA,MACV,QAAQ;AAAA,IAAA;AAGV,SAAK,eAAe,KAAK2B,CAAK,GAC9B,MAAM,KAAK,aAAaA,CAAK,GAG7B,KAAK,UAAA,GACL,KAAK,UAAA;AAAA,EACP;AAAA;AAAA,EAGA,MAAc,aAAaA,GAAyB;AAClD,IAAAA,EAAM,SAAS;AAEf,QAAI;AAEF,UAAI,CADY,MAAM5B,EAAmB4B,EAAM,MAAM,KAAK,MAAM,GAClD;AACZ,QAAAA,EAAM,SAAS,SACfA,EAAM,WAAW,yBACjB,KAAK,cAAA;AACL;AAAA,MACF;AAEA,YAAMY,IAAS,IAAI,WAAA;AAEnB,MAAAA,EAAO,aAAa,CAACC,MAAM;AACzB,YAAIA,EAAE,kBAAkB;AACtB,gBAAMC,IAAa,KAAK,MAAOD,EAAE,SAAS,MAAOA,EAAE,KAAK;AACxD,UAAAb,EAAM,WAAWc,GACjB,KAAK,cAAA;AAAA,QACP;AAAA,MACF,GAEAF,EAAO,SAAS,MAAM;AACpB,QAAAZ,EAAM,WAAW,KACjBA,EAAM,SAAS,QACf,KAAK,cAAA;AAAA,MACP,GAEAY,EAAO,UAAU,MAAM;AACrB,QAAAZ,EAAM,SAAS,SACfA,EAAM,WAAW,wBACjB,KAAK,cAAA;AAAA,MACP,GAEAY,EAAO,kBAAkBZ,EAAM,IAAI;AAAA,IACrC,QAAQ;AACN,MAAAA,EAAM,SAAS,SACfA,EAAM,WAAW,0BACjB,KAAK,cAAA;AAAA,IACP;AAAA,EACF;AAAA,EAEQ,uBAAuB;AAC7B,SAAK;AAAA,MACH,IAAI,YAAY,cAAc;AAAA,QAC5B,QAAQ,EAAE,IAAI,KAAK,IAAI,OAAO,KAAK,eAAA;AAAA,QACnC,SAAS;AAAA,QACT,UAAU;AAAA,MAAA,CACX;AAAA,IAAA;AAAA,EAEL;AAAA,EAEQ,kBAAkB;AAKxB,IAJc,KAAK,WAAW;AAAA,MAC5B;AAAA,IAAA,GAGK,MAAA;AAAA,EACT;AAAA,EAEQ,gCAAgC;AACtC,QAAI,KAAK,UAAU;AACjB,YAAMQ,IAAc,KAAK;AAEzB,MAAIA,KACFA,EAAY,MAAA;AAAA,IAEhB;AACE,WAAK,gCAAA;AAAA,EAET;AAAA,EAEA,MAAc,kCAAkC;AAC9C,QAAI,CAAC,KAAK,UAAU;AAClB,YAAM,KAAK;AAKX,YAAMO,IAJW,KAAK,WAAW;AAAA,QAC/B;AAAA,MAAA,GAG2C,YAAY;AAAA,QACvD;AAAA,MAAA;AAGF,MAAIA,MACFA,EAA2B,aAAa,YAAY,IAAI,GACxDA,EAA2B,MAAA;AAAA,IAE/B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,kBAAkB,GAAU;AAElC,UAAMhB,IADQ,EAAE,OACI;AAIpB,KAHiBA,IAAQ,MAAM,KAAKA,CAAK,IAAI,CAAA,GAGpC,IAAI,CAAC1B,MAAS;AACrB,WAAK,mBAAmBA,CAAI;AAAA,IAC9B,CAAC,GAED,KAAK,cAAA,GACL,KAAK,qBAAA,GACL,KAAK,8BAAA;AAAA,EACP;AAAA,EAEQ,kBAAkB,GAAgB;AACxC,UAAM2C,IAAmB,EAAE,OAAO;AAOlC,QAJA,KAAK,iBAAiB,KAAK,eAAe;AAAA,MACxC,CAACL,MAAiBA,EAAa,KAAK,SAASK;AAAA,IAAA,GAG3C,KAAK,eAAe,WAAW,GAAG;AACpC,YAAMb,IAAQ,KAAK,YAAY;AAAA,QAC7B;AAAA,MAAA;AAEF,MAAIA,QAAa,QAAQ;AAAA,IAC3B;AAEA,SAAK,UAAA,GACL,KAAK,UAAA,GAEL,KAAK,cAAA,GACL,KAAK,qBAAA;AAAA,EACP;AAAA,EAEQ,YAAY,GAAc;AAChC,IAAI,KAAK,aAET,EAAE,gBAAA,GACF,EAAE,eAAA,GACG,KAAK,gBACR,KAAK,cAAc,IACnB,KAAK,cAAA;AAAA,EAET;AAAA;AAAA,EAGQ,aAAa,GAAc;AACjC,IAAI,KAAK,aAET,EAAE,gBAAA,GACF,EAAE,eAAA,GAEE,EAAE,kBAAkB,EAAE,WACxB,KAAK,cAAc,IACnB,KAAK,cAAA;AAAA,EAET;AAAA,EAEQ,QAAQ,GAAc;AAC5B,QAAI,KAAK,SAAU;AAEnB,MAAE,eAAA,GACF,KAAK,cAAc,IACnB,KAAK,cAAA;AAEL,UAAMJ,IAAQ,EAAE,cAAc;AAC9B,QAAI,CAACA,EAAO;AAEZ,UAAMkB,IAAW,MAAM,KAAKlB,CAAK;AAEjC,IAAI,KAAK,WACPkB,EAAS,QAAQ,CAAC5C,MAAS;AACzB,WAAK,mBAAmBA,CAAI;AAAA,IAC9B,CAAC,IAED,KAAK,mBAAmB4C,EAAS,CAAC,CAAC,GAGrC,KAAK,cAAA,GACL,KAAK,qBAAA;AAAA,EACP;AAAA,EAEA,SAAS;AACP,WAAO9B;AAAA;AAAA,wBAEa,KAAK,iBAAiB;AAAA;AAAA;AAAA,gBAG9B,KAAK,KAAK;AAAA,sBACJ,KAAK,WAAW;AAAA,eACvB,KAAK,WAAW,aAAa,KAAK,WAAW,aAAa,EAAE;AAAA,kBACzD,KAAK,OAAO;AAAA,oBACV,KAAK,QAAQ;AAAA;AAAA,sDAEqB,KAAK,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,eAOvD,KAAK,IAAI;AAAA,iBACP,KAAK,MAAM;AAAA,eACb+B,EAAU,KAAK,QAAQ,MAAS,CAAC;AAAA,oBAC5B,KAAK,QAAQ;AAAA,oBACb,KAAK,QAAQ;AAAA,oBACb,KAAK,YAChB,CAAC,KAAK,YAAY,KAAK,eAAe,SAAS,CAAE;AAAA,yBACjC,KAAK,QAAQ;AAAA;AAAA,kBAEpB,KAAK,iBAAiB;AAAA;AAAA;AAAA;AAAA,QAI/B,KAAK,WAYJ/B;AAAA;AAAA,cAEI,KAAK,cAAc,gBAAgB,EAAE;AAAA,cACrC,KAAK,kBAAkB,aAAa,EAAE;AAAA,cACtC,KAAK,aAAa,CAAC,KAAK,kBAAkB,UAAU,EAAE;AAAA,qBAC/C,KAAK,kBACV,OACA,CAAC,MAAkB;AAIjB,MAHe,EAAE,OAGN,QAAQ,YAAY,KAG/B,KAAK,gBAAA;AAAA,IACP,CAAC;AAAA,wBACO,KAAK,kBAAkB,OAAO,KAAK,WAAW;AAAA,yBAC7C,KAAK,kBAAkB,OAAO,KAAK,YAAY;AAAA,oBACpD,KAAK,kBAAkB,OAAO,KAAK,OAAO;AAAA;AAAA;AAAA,cAGhD,KAAK,cACHA,gCACAA;AAAA;AAAA;AAAA,4BAGY,KAAK,WAAW,iBAAiB,aAAa;AAAA;AAAA,gCAE1C,KAAK,gBAAgB;AAAA,sCACf,KAAK,sBAAsB;AAAA,gCACjC,KAAK,eAAe;AAAA,kCAClB,CAAC,MAAmB;AAChC,QAAE,eAAA,GACF,EAAE,gBAAA,GACF,KAAK,gBAAA;AAAA,IACP,CAAC;AAAA;AAAA,sCAEiB;AAAA,oBAhD5BA;AAAA;AAAA;AAAA,oBAGU,KAAK,WAAW,iBAAiB,aAAa;AAAA;AAAA,wBAE1C,KAAK,gBAAgB;AAAA,8BACf,KAAK,sBAAsB;AAAA,wBACjC,KAAK,YAChB,CAAC,KAAK,YAAY,KAAK,eAAe,SAAS,CAAE;AAAA,yBACrC,KAAK,eAAe;AAAA,yBAwC5B;AAAA,QACT,KAAK,YACHA;AAAA;AAAA,2BAEiB,KAAK,SAAS;AAAA,6BACZ,KAAK,WAAW,qBAC/B,KAAK,YAAY;AAAA;AAAA,cAGrB,IAAI;AAAA,QACN,KAAK,eAAe,SAAS,IAC3BA;AAAA;AAAA,gBAEM,KAAK,eAAe;AAAA,MACpB,CAACa,MACCb;AAAA;AAAA,iCAEea,EAAM,KAAK,IAAI;AAAA,+BACjBA,EAAM,MAAM;AAAA,iCACVA,EAAM,QAAQ;AAAA,qCACVA,EAAM,YAAY,EAAE;AAAA;AAAA;AAAA,IAAA,CAG1C;AAAA;AAAA,cAGL,IAAI;AAAA;AAAA,EAEZ;AACF;AAhlBEN,EAAO,SAASN,EAAUC,CAAM,GA4GhCK,EAAO,iBAAiB;AA7GnB,IAAMyB,IAANzB;AAIsCH,EAAA;AAAA,EAA1CC,EAAS,EAAE,MAAM,QAAQ,SAAS,IAAM;AAAA,GAJ9B2B,EAIgC,WAAA,IAAA;AAGA5B,EAAA;AAAA,EAA1CC,EAAS,EAAE,MAAM,QAAQ,SAAS,IAAM;AAAA,GAP9B2B,EAOgC,WAAA,MAAA;AAGf5B,EAAA;AAAA,EAA3BC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAVf2B,EAUiB,WAAA,OAAA;AAGA5B,EAAA;AAAA,EAA3BC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAbf2B,EAaiB,WAAA,aAAA;AAGC5B,EAAA;AAAA,EAA5BC,EAAS,EAAE,MAAM,QAAA,CAAS;AAAA,GAhBhB2B,EAgBkB,WAAA,UAAA;AAGc5B,EAAA;AAAA,EAA1CC,EAAS,EAAE,MAAM,QAAQ,SAAS,IAAM;AAAA,GAnB9B2B,EAmBgC,WAAA,MAAA;AAGf5B,EAAA;AAAA,EAA3BC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAtBf2B,EAsBiB,WAAA,SAAA;AAGA5B,EAAA;AAAA,EAA3BC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAzBf2B,EAyBiB,WAAA,QAAA;AAGgB5B,EAAA;AAAA,EAA3CC,EAAS,EAAE,MAAM,SAAS,SAAS,IAAM;AAAA,GA5B/B2B,EA4BiC,WAAA,UAAA;AAGA5B,EAAA;AAAA,EAA3CC,EAAS,EAAE,MAAM,SAAS,SAAS,IAAM;AAAA,GA/B/B2B,EA+BiC,WAAA,UAAA;AAGA5B,EAAA;AAAA,EAA3CC,EAAS,EAAE,MAAM,SAAS,SAAS,IAAM;AAAA,GAlC/B2B,EAkCiC,WAAA,UAAA;AAGA5B,EAAA;AAAA,EAA3CC,EAAS,EAAE,MAAM,SAAS,SAAS,IAAM;AAAA,GArC/B2B,EAqCiC,WAAA,WAAA;AAGhB5B,EAAA;AAAA,EAA3BC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAxCf2B,EAwCiB,WAAA,cAAA;AAGC5B,EAAA;AAAA,EAA5BC,EAAS,EAAE,MAAM,QAAA,CAAS;AAAA,GA3ChB2B,EA2CkB,WAAA,UAAA;AAMc5B,EAAA;AAAA,EAA1CC,EAAS,EAAE,MAAM,QAAQ,SAAS,IAAM;AAAA,GAjD9B2B,EAiDgC,WAAA,OAAA;AAGC5B,EAAA;AAAA,EAA3CC,EAAS,EAAE,MAAM,SAAS,SAAS,IAAM;AAAA,GApD/B2B,EAoDiC,WAAA,UAAA;AA+hBzC,eAAe,IAAI,eAAe,KACrC,eAAe,OAAO,iBAAiBA,CAAY;"}
1
+ {"version":3,"file":"nys-fileinput.js","sources":["../src/validateFileHeader.ts","../src/nys-fileitem.ts","../src/nys-fileinput.ts"],"sourcesContent":["// The main function for file validation based only on extension and `accept` attribute.\nexport async function validateFileHeader(\n file: File,\n accept: string,\n): Promise<boolean> {\n // 1) If no accept attribute is defined, assume anything is allowed\n if (!accept || accept.trim() === \"\") return true;\n\n // 2) Normalize and parse the accept attribute\n const acceptItems = accept\n .toLowerCase()\n .split(\",\")\n .map((a) => a.trim());\n\n // 3) Get the file extension\n const filename = file.name.toLowerCase();\n const fileExt = filename.includes(\".\") ? filename.split(\".\").pop()! : \"\";\n\n // 4) Check if extension matches any of the accept items\n for (const acceptItem of acceptItems) {\n // Direct extension match (e.g. \".pdf\")\n if (acceptItem.startsWith(\".\") && acceptItem.slice(1) === fileExt) {\n return true;\n }\n\n // Wildcard /* (e.g. \"image/*\") -> match common prefixes\n if (\n acceptItem.endsWith(\"/*\") &&\n file.type.startsWith(acceptItem.slice(0, -1))\n ) {\n return true;\n }\n\n // Exact MIME match\n if (file.type === acceptItem) {\n return true;\n }\n }\n\n // 5) Not matched\n return false;\n}\n","import { LitElement, html, unsafeCSS } from \"lit\";\nimport { property } from \"lit/decorators.js\";\n// @ts-ignore: SCSS module imported via bundler as inline\nimport styles from \"./nys-fileitem.scss?inline\";\n\n/**\n * **Internal component.** Displays an individual file within `nys-fileinput` with status and progress.\n *\n * Rendered automatically by `nys-fileinput` for each selected file. Shows filename, upload status\n * (pending/processing/done/error), progress bar during upload, and error messages. Remove button emits event.\n *\n * @summary Internal file item display with status, progress bar, and remove action.\n * @element nys-fileitem\n *\n * @fires nys-fileRemove - Fired when remove button is clicked. Detail: `{filename}`.\n */\nexport class NysFileItem extends LitElement {\n static styles = unsafeCSS(styles);\n static shadowRootOptions = {\n ...LitElement.shadowRootOptions,\n delegatesFocus: true,\n };\n\n /** Name of the file being displayed. */\n @property({ type: String }) filename = \"\";\n\n /**\n * Upload status: `pending` (queued), `processing` (uploading), `done` (complete), `error` (failed).\n * @default \"pending\"\n */\n @property({ type: String }) status:\n | \"pending\"\n | \"processing\"\n | \"done\"\n | \"error\" = \"pending\";\n\n /** Upload progress percentage (0-100). Only shown when status is `processing`. */\n @property({ type: Number }) progress = 0;\n\n /** Error message displayed when status is `error`. */\n @property({ type: String }) errorMessage = \"\";\n\n private _handleRemove() {\n this.dispatchEvent(\n new CustomEvent(\"nys-fileRemove\", {\n detail: { filename: this.filename },\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n private splitFilename(filename: string) {\n const lastDotIndex = filename.lastIndexOf(\".\");\n const extension = lastDotIndex !== -1 ? filename.slice(lastDotIndex) : \"\"; // e.g. \".pdf\"\n const name =\n lastDotIndex !== -1 ? filename.slice(0, lastDotIndex) : filename;\n\n const startPart = name.slice(0, name.length - 3);\n const endPart = name.slice(-3);\n\n return { startPart, endPart, extension };\n }\n\n render() {\n const { startPart, endPart, extension } = this.splitFilename(this.filename);\n\n return html`\n <div\n class=\"file-item ${this.status}\"\n aria-busy=${this.status === \"processing\" ? \"true\" : \"false\"}\n aria-label=\"You have selected ${this.filename}\"\n >\n <div class=\"file-item__main\" role=\"group\">\n <nys-icon\n class=\"file-icon\"\n name=${this.status === \"processing\"\n ? \"progress_activity\"\n : this.status === \"error\"\n ? \"error\"\n : \"attach_file\"}\n size=\"2xl\"\n ></nys-icon>\n <div class=\"file-item__info\">\n <div class=\"file-item__info-name\">\n <span class=\"file-item__info-name-start\">${startPart}</span>\n <span class=\"file-item__info-name-end\"\n >${endPart}${extension}</span\n >\n </div>\n ${this.errorMessage\n ? html`<p\n class=\"file-item__error\"\n role=\"alert\"\n aria-live=\"assertive\"\n aria-invalid=\"true\"\n aria-errormessage=${this.errorMessage}\n id=\"${this.filename}-error\"\n >\n ${this.errorMessage}\n </p>`\n : null}\n </div>\n <nys-button\n circle\n icon=\"close\"\n ariaLabel=\"close button\"\n size=\"sm\"\n variant=\"ghost\"\n @nys-click=${this._handleRemove}\n ariaLabel=\"Remove file: ${this.filename}\"\n ></nys-button>\n </div>\n ${this.status === \"processing\"\n ? html`<div\n class=\"file-item__progress-container\"\n role=\"progressbar\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n aria-valuenow=\"${this.progress}\"\n aria-label=\"Upload progress for ${this.filename}\"\n >\n <progress value=${this.progress} max=\"100\"></progress>\n </div>`\n : null}\n </div>\n `;\n }\n}\n\ncustomElements.define(\"nys-fileitem\", NysFileItem);\n","import { LitElement, html, unsafeCSS } from \"lit\";\nimport { property } from \"lit/decorators.js\";\nimport { ifDefined } from \"lit/directives/if-defined.js\";\nimport { validateFileHeader } from \"./validateFileHeader\";\nimport \"./nys-fileitem\";\n// @ts-ignore: SCSS module imported via bundler as inline\nimport styles from \"./nys-fileinput.scss?inline\";\n\nlet fileinputIdCounter = 0;\n\ninterface FileWithProgress {\n file: File;\n progress: number;\n status: \"pending\" | \"processing\" | \"done\" | \"error\";\n errorMsg?: string;\n}\n\n/**\n * A file input for uploading files with support for multiple files, drag-and-drop, and progress tracking.\n * Validates file types via magic bytes (not just extension). Form-associated via ElementInternals.\n *\n * Use for document uploads, image uploads, or any file submission. Enable `dropzone` for drag-and-drop UI.\n *\n * @summary File input with drag-and-drop, validation, and progress tracking.\n * @element nys-fileinput\n *\n * @slot description - Custom HTML description content.\n *\n * @fires nys-change - Fired when files are added or removed. Detail: `{id, files}`.\n *\n * @example Single file upload\n * ```html\n * <nys-fileinput label=\"Upload document\" accept=\".pdf,.doc\" required></nys-fileinput>\n * ```\n *\n * @example Multiple files with dropzone\n * ```html\n * <nys-fileinput label=\"Upload images\" accept=\"image/*\" multiple dropzone></nys-fileinput>\n * ```\n */\n\nexport class NysFileinput extends LitElement {\n static styles = unsafeCSS(styles);\n static shadowRootOptions = {\n ...LitElement.shadowRootOptions,\n delegatesFocus: true,\n };\n\n /** Unique identifier. Auto-generated if not provided. */\n @property({ type: String, reflect: true }) id = \"\";\n\n /** Name for form submission. */\n @property({ type: String, reflect: true }) name = \"\";\n\n /** Visible label text. */\n @property({ type: String }) label = \"\";\n\n /** Helper text below label. Use slot for custom HTML. */\n @property({ type: String }) description = \"\";\n\n /** Allows selecting multiple files. */\n @property({ type: Boolean }) multiple = false;\n\n /** Form `id` to associate with. */\n @property({ type: String, reflect: true }) form: string | null = null;\n\n /** Tooltip text shown on hover/focus of info icon. */\n @property({ type: String }) tooltip = \"\";\n\n /** Accepted file types. Use MIME types (`image/*`) or extensions (`.pdf`). Validated via magic bytes. */\n @property({ type: String }) accept = \"\";\n\n /** Prevents interaction. */\n @property({ type: Boolean, reflect: true }) disabled = false;\n\n /** Requires at least one file to be uploaded. */\n @property({ type: Boolean, reflect: true }) required = false;\n\n /** Shows \"Optional\" flag. */\n @property({ type: Boolean, reflect: true }) optional = false;\n\n /** Shows error message when true. */\n @property({ type: Boolean, reflect: true }) showError = false;\n\n /** Error message text. Shown only when `showError` is true. */\n @property({ type: String }) errorMessage = \"\";\n\n /** Enables drag-and-drop zone UI. */\n @property({ type: Boolean }) dropzone = false;\n\n /**\n * Component width: `lg` (384px) or `full` (100%, default).\n * @default \"full\"\n */\n @property({ type: String, reflect: true }) width: \"lg\" | \"full\" = \"full\";\n\n /** Adjusts colors for dark backgrounds. */\n @property({ type: Boolean, reflect: true }) inverted = false;\n\n private _selectedFiles: FileWithProgress[] = [];\n private _dragActive = false;\n private get _isDropDisabled(): boolean {\n return this.disabled || (!this.multiple && this._selectedFiles.length > 0);\n }\n\n private get _buttonAriaLabel(): string {\n if (this._selectedFiles.length === 0) {\n return this.multiple ? \"Choose files: \" : \"Choose file: \";\n }\n\n return this.multiple ? \"Change files: \" : \"Change file: \";\n }\n\n private get _buttonAriaDescription(): string {\n if (this._selectedFiles.length === 0)\n return `${this.label + \" \" + this.description}`;\n\n const hasInvalidFiles = this._selectedFiles.some(\n (file) => file.status === \"error\",\n );\n\n let base = \"\";\n\n if (this._selectedFiles.length === 1) {\n base = `You have selected ${this._selectedFiles[0].file.name}.`;\n } else {\n const fileNames = this._selectedFiles.map((f) => f.file.name).join(\", \");\n base = `You have selected ${this._selectedFiles.length} files: ${fileNames}`;\n }\n\n const error = hasInvalidFiles\n ? \" Error: One or more files are not valid file types.\"\n : \"\";\n\n return `${base}${error}`;\n }\n\n private get _innerNysButton(): HTMLElement | null {\n const nysButton = this.renderRoot.querySelector(\n '[name=\"file-btn\"]',\n ) as HTMLButtonElement | null;\n const innerButton = nysButton?.shadowRoot?.querySelector(\n \"button\",\n ) as HTMLElement | null;\n return innerButton;\n }\n\n private _internals: ElementInternals;\n\n /**\n * Lifecycle methods\n * --------------------------------------------------------------------------\n */\n\n static formAssociated = true; // allows use of elementInternals' API\n\n constructor() {\n super();\n this._internals = this.attachInternals();\n }\n\n // Generate a unique ID if one is not provided\n connectedCallback() {\n super.connectedCallback();\n if (!this.id) {\n this.id = `nys-fileinput-${Date.now()}-${fileinputIdCounter++}`;\n }\n\n this.addEventListener(\"invalid\", this._handleInvalid);\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this.removeEventListener(\"invalid\", this._handleInvalid);\n }\n\n firstUpdated() {\n // This ensures our element always participates in the form\n this._setValue();\n }\n\n /**\n * Form Integration\n * --------------------------------------------------------------------------\n */\n private _setValue() {\n // for multiple file uploads, we upload File object as an array\n if (this.multiple) {\n const files = this._selectedFiles.map((entry) => entry.file);\n\n if (files.length > 0) {\n const formData = new FormData();\n files.forEach((file) => {\n formData.append(this.name, file);\n });\n this._internals.setFormValue(formData);\n } else {\n this._internals.setFormValue(null);\n }\n } else {\n const singleFile = this._selectedFiles[0]?.file || null;\n this._internals.setFormValue(singleFile);\n }\n\n this._manageRequire(); // Check validation when value is set\n }\n\n // Called to internally set the initial internalElement required flag.\n private _manageRequire() {\n const input = this.shadowRoot?.querySelector(\"input\");\n if (!input) return;\n\n const message = this.errorMessage || \"Please upload a file.\";\n const isInvalid = this.required && this._selectedFiles.length == 0;\n\n if (isInvalid) {\n this._internals.ariaRequired = \"true\"; // Screen readers should announce error\n this._internals.setValidity({ valueMissing: true }, message, input);\n } else {\n this._internals.ariaRequired = \"false\"; // Reset when valid\n this._internals.setValidity({}, \"\", input);\n }\n }\n\n private _setValidityMessage(message: string = \"\") {\n const input = this.shadowRoot?.querySelector(\"input\");\n if (!input) return;\n\n // Toggle the HTML <div> tag error message\n this.showError = message === (this.errorMessage || \"Please upload a file.\");\n\n // If user sets errorMessage, this will always override the native validation message\n if (this.errorMessage?.trim() && message !== \"\") {\n message = this.errorMessage;\n }\n\n this._internals.setValidity(\n message ? { customError: true } : {},\n message,\n input,\n );\n }\n\n private _validate() {\n const hasErrorFiles = this._selectedFiles.some(\n (entry) => entry.status === \"error\",\n );\n const isEmpty = this.required && this._selectedFiles.length === 0;\n\n let message = \"\";\n if (isEmpty) {\n message = this.errorMessage || \"Please upload a file.\";\n } else if (hasErrorFiles) {\n message = \"One or more files are invalid.\";\n }\n\n this._setValidityMessage(message);\n }\n\n // This helper function is called to perform the element's native validation.\n checkValidity(): boolean {\n const input = this.shadowRoot?.querySelector(\"input\");\n return input ? input.checkValidity() : true;\n }\n\n // Called automatically when the parent form is reset\n public formResetCallback() {\n this._selectedFiles = [];\n const input = this.shadowRoot?.querySelector(\n \".hidden-file-input\",\n ) as HTMLInputElement | null;\n\n if (input) {\n input.value = \"\";\n }\n\n this._internals.setFormValue(null);\n\n // Reset validation UI\n this.showError = false;\n this.errorMessage = \"\";\n this._internals.setValidity({});\n\n // Re-render UI\n this.requestUpdate();\n }\n\n private _handleInvalid(event: Event) {\n event.preventDefault();\n this._validate();\n\n const innerButton = this._innerNysButton;\n if (innerButton) {\n // Focus only if this is the first invalid element (top-down approach)\n const form = this._internals.form;\n if (form) {\n const elements = Array.from(form.elements) as Array<\n HTMLElement & { checkValidity?: () => boolean }\n >;\n // Find the first element in the form that is invalid\n const firstInvalidElement = elements.find(\n (element) =>\n typeof element.checkValidity === \"function\" &&\n !element.checkValidity(),\n );\n if (firstInvalidElement === this) {\n innerButton.focus();\n innerButton.classList.add(\"active-focus\"); // This class styling is found within <nys-button>\n }\n } else {\n // If not part of a form, simply focus.\n innerButton.focus();\n innerButton.classList.add(\"active-focus\"); // This class styling is found within <nys-button>\n }\n }\n }\n\n /**\n * Functions\n * --------------------------------------------------------------------------\n */\n\n // Store the files to be displayed\n private async _saveSelectedFiles(file: File) {\n const isDuplicate = this._selectedFiles.some(\n (existingFile) => existingFile.file.name == file.name,\n );\n if (isDuplicate) return;\n\n if (!this.multiple && this._selectedFiles.length >= 1) return;\n\n const entry: FileWithProgress = {\n file,\n progress: 0,\n status: \"pending\",\n };\n\n this._selectedFiles.push(entry);\n await this._processFile(entry);\n\n // Now that the file is added, update form value and validation\n this._setValue();\n this._validate();\n }\n\n // Read the contents of stored files, this will indicate loading progress of the uploaded files\n private async _processFile(entry: FileWithProgress) {\n entry.status = \"processing\";\n\n try {\n const isValid = await validateFileHeader(entry.file, this.accept);\n if (!isValid) {\n entry.status = \"error\";\n entry.errorMsg = \"File type is invalid.\";\n this.requestUpdate();\n return;\n }\n\n const reader = new FileReader();\n\n reader.onprogress = (e) => {\n if (e.lengthComputable) {\n const percentage = Math.round((e.loaded * 100) / e.total);\n entry.progress = percentage;\n this.requestUpdate();\n }\n };\n\n reader.onload = () => {\n entry.progress = 100;\n entry.status = \"done\";\n this.requestUpdate();\n };\n\n reader.onerror = () => {\n entry.status = \"error\";\n entry.errorMsg = \"Failed to load file.\";\n this.requestUpdate();\n };\n\n reader.readAsArrayBuffer(entry.file);\n } catch {\n entry.status = \"error\";\n entry.errorMsg = \"Error validating file.\";\n this.requestUpdate();\n }\n }\n\n private _dispatchChangeEvent() {\n this.dispatchEvent(\n new CustomEvent(\"nys-change\", {\n detail: { id: this.id, files: this._selectedFiles },\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n private _openFileDialog() {\n const input = this.renderRoot.querySelector(\n \".hidden-file-input\",\n ) as HTMLInputElement;\n\n input?.click();\n }\n\n private _handlePostFileSelectionFocus() {\n if (this.multiple) {\n const innerButton = this._innerNysButton;\n\n if (innerButton) {\n innerButton.focus();\n }\n } else {\n this._focusFirstFileItemIfSingleMode();\n }\n }\n\n private async _focusFirstFileItemIfSingleMode() {\n if (!this.multiple) {\n await this.updateComplete;\n const fileItem = this.renderRoot.querySelector(\n \"nys-fileitem\",\n ) as HTMLElement;\n\n const innerFileItemMainContainer = fileItem?.shadowRoot?.querySelector(\n \".file-item\",\n ) as HTMLElement | null;\n\n if (innerFileItemMainContainer) {\n innerFileItemMainContainer.setAttribute(\"tabindex\", \"-1\");\n innerFileItemMainContainer.focus();\n }\n }\n }\n\n /**\n * Event Handlers\n * --------------------------------------------------------------------------\n */\n\n // Access the selected files & add new files to the internal list via the hidden <input type=\"file\">\n private _handleFileChange(e: Event) {\n const input = e.target as HTMLInputElement;\n const files = input.files;\n const newFiles = files ? Array.from(files) : []; // changes FileList to array\n\n // Store the uploaded files\n newFiles.map((file) => {\n this._saveSelectedFiles(file);\n });\n\n this.requestUpdate();\n this._dispatchChangeEvent();\n this._handlePostFileSelectionFocus();\n }\n\n private _handleFileRemove(e: CustomEvent) {\n const filenameToRemove = e.detail.filename;\n\n // Remove selected files\n this._selectedFiles = this._selectedFiles.filter(\n (existingFile) => existingFile.file.name !== filenameToRemove,\n );\n\n if (this._selectedFiles.length === 0) {\n const input = this.shadowRoot?.querySelector(\n \"input\",\n ) as HTMLInputElement | null;\n if (input) input.value = \"\";\n }\n\n this._setValue();\n this._validate();\n\n this.requestUpdate();\n this._dispatchChangeEvent();\n }\n\n private _onDragOver(e: DragEvent) {\n if (this.disabled) return;\n\n e.stopPropagation();\n e.preventDefault();\n if (!this._dragActive) {\n this._dragActive = true; // For styling purpose\n this.requestUpdate();\n }\n }\n\n // Mostly used for styling purpose\n private _onDragLeave(e: DragEvent) {\n if (this.disabled) return;\n\n e.stopPropagation();\n e.preventDefault();\n // Only reset if leaving the dropzone itself (not children)\n if (e.currentTarget === e.target) {\n this._dragActive = false; // For styling purpose\n this.requestUpdate();\n }\n }\n\n private _onDrop(e: DragEvent) {\n if (this.disabled) return;\n\n e.preventDefault();\n this._dragActive = false; // For styling purpose\n this.requestUpdate();\n\n const files = e.dataTransfer?.files;\n if (!files) return;\n\n const newFiles = Array.from(files);\n\n if (this.multiple) {\n newFiles.forEach((file) => {\n this._saveSelectedFiles(file);\n });\n } else {\n this._saveSelectedFiles(newFiles[0]);\n }\n\n this.requestUpdate();\n this._dispatchChangeEvent();\n }\n\n render() {\n return html`<div\n class=\"nys-fileinput\"\n @nys-fileRemove=${this._handleFileRemove}\n >\n <nys-label\n for=${this.id}\n label=${this.label}\n description=${this.description}\n flag=${this.required ? \"required\" : this.optional ? \"optional\" : \"\"}\n tooltip=${this.tooltip}\n ?inverted=${this.inverted}\n >\n <slot name=\"description\" slot=\"description\">${this.description}</slot>\n </nys-label>\n\n <input\n id=${this.id}\n class=\"hidden-file-input\"\n tabindex=\"-1\"\n type=\"file\"\n name=${this.name}\n accept=${this.accept}\n form=${ifDefined(this.form || undefined)}\n ?multiple=${this.multiple}\n ?required=${this.required}\n ?disabled=${this.disabled ||\n (!this.multiple && this._selectedFiles.length > 0)}\n aria-disabled=\"${this.disabled}\"\n aria-hidden=\"true\"\n @change=${this._handleFileChange}\n hidden\n />\n\n ${!this.dropzone\n ? html`<nys-button\n id=\"choose-files-btn\"\n name=\"file-btn\"\n label=${this.multiple ? \"Choose files\" : \"Choose file\"}\n variant=\"outline\"\n ariaLabel=${this._buttonAriaLabel}\n ariaDescription=${this._buttonAriaDescription}\n ?disabled=${this.disabled ||\n (!this.multiple && this._selectedFiles.length > 0)}\n @nys-click=${this._openFileDialog}\n ></nys-button>`\n : html`<div\n class=\"nys-fileinput__dropzone\n ${this._dragActive ? \"drag-active\" : \"\"}\n ${this._isDropDisabled ? \"disabled\" : \"\"}\n ${this.showError && !this._isDropDisabled ? \"error\" : \"\"}\"\n @click=${this._isDropDisabled\n ? null\n : (e: MouseEvent) => {\n const target = e.target as HTMLElement;\n\n // Ignore clicks that originated within a nys-button\n if (target.closest(\"nys-button\")) return;\n\n // Only handle direct wrapper clicks (outside of buttons)\n this._openFileDialog();\n }}\n @dragover=${this._isDropDisabled ? null : this._onDragOver}\n @dragleave=${this._isDropDisabled ? null : this._onDragLeave}\n @drop=${this._isDropDisabled ? null : this._onDrop}\n aria-label=\"Drag files here or choose from folder\"\n >\n ${this._dragActive\n ? html`<p>Drop file to upload</p>`\n : html` <nys-button\n id=\"choose-files-btn-drag\"\n name=\"file-btn\"\n label=${this.multiple ? \"Choose files\" : \"Choose file\"}\n variant=\"outline\"\n ariaLabel=${this._buttonAriaLabel}\n ariaDescription=${this._buttonAriaDescription}\n ?disabled=${this._isDropDisabled}\n @nys-click=\"${(e: CustomEvent) => {\n e.preventDefault();\n e.stopPropagation();\n this._openFileDialog();\n }}\"\n ></nys-button>\n <p>or drag here</p>`}\n </div>`}\n ${this.showError\n ? html`\n <nys-errormessage\n ?showError=${this.showError}\n errorMessage=${this._internals.validationMessage ||\n this.errorMessage}\n ></nys-errormessage>\n `\n : null}\n ${this._selectedFiles.length > 0\n ? html`\n <ul>\n ${this._selectedFiles.map(\n (entry) =>\n html`<li>\n <nys-fileitem\n filename=${entry.file.name}\n status=${entry.status}\n progress=${entry.progress}\n errorMessage=${entry.errorMsg || \"\"}\n ></nys-fileitem>\n </li>`,\n )}\n </ul>\n `\n : null}\n </div>`;\n }\n}\n\nif (!customElements.get(\"nys-fileinput\")) {\n customElements.define(\"nys-fileinput\", NysFileinput);\n}\n"],"names":["LitElement","unsafeCSS","html","property","ifDefined","validateFileHeader","file","accept","acceptItems","a","filename","fileExt","acceptItem","_NysFileItem","lastDotIndex","extension","name","startPart","endPart","styles","NysFileItem","__decorateClass","fileinputIdCounter","_NysFileinput","hasInvalidFiles","base","fileNames","f","files","entry","formData","singleFile","input","message","hasErrorFiles","isEmpty","event","innerButton","form","element","existingFile","reader","e","percentage","innerFileItemMainContainer","filenameToRemove","newFiles","NysFileinput"],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import { LitElement } from "lit";
2
+ /**
3
+ * **Internal component.** Displays an individual file within `nys-fileinput` with status and progress.
4
+ *
5
+ * Rendered automatically by `nys-fileinput` for each selected file. Shows filename, upload status
6
+ * (pending/processing/done/error), progress bar during upload, and error messages. Remove button emits event.
7
+ *
8
+ * @summary Internal file item display with status, progress bar, and remove action.
9
+ * @element nys-fileitem
10
+ *
11
+ * @fires nys-fileRemove - Fired when remove button is clicked. Detail: `{filename}`.
12
+ */
13
+ export declare class NysFileItem extends LitElement {
14
+ static styles: import("lit").CSSResult;
15
+ static shadowRootOptions: {
16
+ delegatesFocus: boolean;
17
+ clonable?: boolean;
18
+ customElementRegistry?: CustomElementRegistry;
19
+ mode: ShadowRootMode;
20
+ serializable?: boolean;
21
+ slotAssignment?: SlotAssignmentMode;
22
+ };
23
+ /** Name of the file being displayed. */
24
+ filename: string;
25
+ /**
26
+ * Upload status: `pending` (queued), `processing` (uploading), `done` (complete), `error` (failed).
27
+ * @default "pending"
28
+ */
29
+ status: "pending" | "processing" | "done" | "error";
30
+ /** Upload progress percentage (0-100). Only shown when status is `processing`. */
31
+ progress: number;
32
+ /** Error message displayed when status is `error`. */
33
+ errorMessage: string;
34
+ private _handleRemove;
35
+ private splitFilename;
36
+ render(): import("lit-html").TemplateResult<1>;
37
+ }
@@ -0,0 +1 @@
1
+ export declare function validateFileHeader(file: File, accept: string): Promise<boolean>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nysds/nys-fileinput",
3
- "version": "1.13.1",
3
+ "version": "1.15.0",
4
4
  "description": "The Fileinput component from the NYS Design System.",
5
5
  "module": "dist/nys-fileinput.js",
6
6
  "types": "dist/index.d.ts",
@@ -23,15 +23,15 @@
23
23
  "lit-analyze": "lit-analyzer '**/*.ts'"
24
24
  },
25
25
  "dependencies": {
26
- "@nysds/nys-icon": "^1.13.1",
27
- "@nysds/nys-button": "^1.13.1",
28
- "@nysds/nys-label": "^1.13.1",
29
- "@nysds/nys-errormessage": "^1.13.1"
26
+ "@nysds/nys-icon": "^1.15.0",
27
+ "@nysds/nys-button": "^1.15.0",
28
+ "@nysds/nys-label": "^1.15.0",
29
+ "@nysds/nys-errormessage": "^1.15.0"
30
30
  },
31
31
  "devDependencies": {
32
32
  "lit": "^3.3.1",
33
33
  "typescript": "^5.9.3",
34
- "vite": "^7.1.12"
34
+ "vite": "^7.3.1"
35
35
  },
36
36
  "keywords": [
37
37
  "new-york-state",