@theseam/ui-common 1.0.2-beta.83 → 1.0.2-beta.85

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,6 +5,7 @@ import * as i1 from '@theseam/ui-common/icon';
5
5
  import { TheSeamIconModule } from '@theseam/ui-common/icon';
6
6
  import { NgTemplateOutlet } from '@angular/common';
7
7
  import { NG_VALUE_ACCESSOR } from '@angular/forms';
8
+ import { ComponentHarness } from '@angular/cdk/testing';
8
9
 
9
10
  function seamFileItemFromFile(file, id) {
10
11
  return {
@@ -529,9 +530,163 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
529
530
  ], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (_hasFile()) {\n <seam-file-tile\n [item]=\"_items()[0]\"\n [variant]=\"_tileVariant()\"\n [showName]=\"showTileName()\"\n [disabled]=\"_effectiveDisabled()\"\n (remove)=\"_onTileRemove($event)\"\n ></seam-file-tile>\n <button\n type=\"button\"\n class=\"seam-file-field__replace\"\n [disabled]=\"_effectiveDisabled()\"\n (click)=\"inputComponentWhenFilled._openPicker()\"\n >\n or <strong>{{ replaceText() }}</strong>\n </button>\n <!-- Hidden mounted input so the replace button has a picker to delegate to. -->\n <seam-file-input\n #inputComponentWhenFilled\n hidden\n [multiple]=\"multiple()\"\n [accept]=\"accept()\"\n [maxSize]=\"maxSize()\"\n [maxFiles]=\"_remainingMaxFiles()\"\n [disabled]=\"_effectiveDisabled()\"\n [hideErrors]=\"true\"\n (filesAdded)=\"_onFilesAdded($event)\"\n (rejected)=\"_onRejected($event)\"\n ></seam-file-input>\n} @else {\n <seam-file-input\n #inputComponent\n [multiple]=\"multiple()\"\n [accept]=\"accept()\"\n [maxSize]=\"maxSize()\"\n [maxFiles]=\"_remainingMaxFiles()\"\n [disabled]=\"_effectiveDisabled()\"\n [hideErrors]=\"hideErrors()\"\n [promptText]=\"promptText()\"\n [promptSuffix]=\"promptSuffix()\"\n (filesAdded)=\"_onFilesAdded($event)\"\n (rejected)=\"_onRejected($event)\"\n ></seam-file-input>\n\n @if (multiple() && _items().length > 0) {\n <div\n class=\"seam-file-field__tiles\"\n [class.seam-file-field__tiles--preview]=\"previewMode()\"\n >\n @for (item of _items(); track item.id ?? item.name) {\n <seam-file-tile\n [item]=\"item\"\n [variant]=\"_tileVariant()\"\n [showName]=\"showTileName()\"\n [disabled]=\"_effectiveDisabled()\"\n (remove)=\"_onTileRemove($event)\"\n ></seam-file-tile>\n }\n </div>\n }\n}\n", styles: [":host{display:block}.seam-file-field__replace{display:block;margin-top:8px;padding:8px 12px;width:100%;background:#f8f9fa;border:1px dashed #ced4da;border-radius:6px;font-size:12px;color:#6c757d;text-align:center;cursor:pointer}.seam-file-field__replace strong{color:#357ebd;font-weight:600}.seam-file-field__replace:disabled{opacity:.6;cursor:not-allowed}.seam-file-field__replace:focus-visible{outline:2px solid #357ebd;outline-offset:2px}seam-file-input[hidden]{display:none}.seam-file-field__tiles{display:flex;flex-direction:column;gap:6px;margin-top:8px}.seam-file-field__tiles--preview{flex-direction:row;flex-wrap:wrap;gap:8px}\n"] }]
530
531
  }], propDecorators: { multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], maxSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSize", required: false }] }], maxFiles: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxFiles", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], previewMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "previewMode", required: false }] }], showTileName: [{ type: i0.Input, args: [{ isSignal: true, alias: "showTileName", required: false }] }], promptText: [{ type: i0.Input, args: [{ isSignal: true, alias: "promptText", required: false }] }], promptSuffix: [{ type: i0.Input, args: [{ isSignal: true, alias: "promptSuffix", required: false }] }], replaceText: [{ type: i0.Input, args: [{ isSignal: true, alias: "replaceText", required: false }] }], hideErrors: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideErrors", required: false }] }], rejected: [{ type: i0.Output, args: ["rejected"] }] } });
531
532
 
533
+ function dataTransferFromFiles(files) {
534
+ const dt = new DataTransfer();
535
+ for (const f of files)
536
+ dt.items.add(f);
537
+ return dt;
538
+ }
539
+
540
+ /**
541
+ * Test harness for an element with `[seamFileDropZone]` attached.
542
+ *
543
+ * Usage:
544
+ * ```ts
545
+ * const harness = await loader.getHarness(TheSeamFileDropZoneHarness)
546
+ * await harness.dropFiles([new File(['x'], 'x.txt')])
547
+ * expect(await harness.isOver()).toBe(false)
548
+ * ```
549
+ */
550
+ class TheSeamFileDropZoneHarness extends ComponentHarness {
551
+ static hostSelector = '[seamFileDropZone]';
552
+ async isOver() {
553
+ const host = await this.host();
554
+ return ((await host.getAttribute('class')) ?? '').includes('seam-file-drop-zone--over');
555
+ }
556
+ async dropFiles(files) {
557
+ const host = await this.host();
558
+ await host.dispatchEvent('drop', {
559
+ dataTransfer: dataTransferFromFiles(files),
560
+ });
561
+ }
562
+ }
563
+
564
+ /**
565
+ * Test harness for `<seam-file-input>`.
566
+ */
567
+ class TheSeamFileInputHarness extends ComponentHarness {
568
+ static hostSelector = 'seam-file-input';
569
+ _zone = this.locatorFor('.seam-file-input__zone');
570
+ _prompt = this.locatorFor('.seam-file-input__prompt');
571
+ _errors = this.locatorForOptional('.seam-file-input__errors');
572
+ _native = this.locatorFor('input[type="file"]');
573
+ /** Trimmed prompt text including the bold portion and suffix. */
574
+ async getPromptText() {
575
+ return (await (await this._prompt()).text()).trim();
576
+ }
577
+ /** Component renders `tabindex=-1` on the zone when disabled. */
578
+ async isDisabled() {
579
+ const zone = await this._zone();
580
+ return (await zone.getAttribute('tabindex')) === '-1';
581
+ }
582
+ /** Trimmed error line text, or null when no errors are visible. */
583
+ async getErrorMessage() {
584
+ const el = await this._errors();
585
+ if (!el)
586
+ return null;
587
+ return (await el.text()).trim();
588
+ }
589
+ /**
590
+ * Simulates drop of files on the zone. The directive performs validation
591
+ * and emits `filesAdded` / `rejected` via the component.
592
+ */
593
+ async dropFiles(files) {
594
+ const zone = await this._zone();
595
+ await zone.dispatchEvent('drop', {
596
+ dataTransfer: dataTransferFromFiles(files),
597
+ });
598
+ }
599
+ }
600
+
601
+ /**
602
+ * Test harness for `<seam-file-tile>`.
603
+ */
604
+ class TheSeamFileTileHarness extends ComponentHarness {
605
+ static hostSelector = 'seam-file-tile';
606
+ _root = this.locatorFor('.seam-file-tile');
607
+ _rowName = this.locatorForOptional('.seam-file-tile__name');
608
+ _previewName = this.locatorForOptional('.seam-file-tile__preview-name');
609
+ _remove = this.locatorForOptional('.seam-file-tile__remove');
610
+ _clickableBody = this.locatorForOptional('.seam-file-tile__clickable-body');
611
+ async getName() {
612
+ const rowName = await this._rowName();
613
+ if (rowName)
614
+ return (await rowName.text()).trim();
615
+ const previewName = await this._previewName();
616
+ if (previewName)
617
+ return (await previewName.text()).trim();
618
+ return '';
619
+ }
620
+ async getVariant() {
621
+ const root = await this._root();
622
+ const cls = (await root.getAttribute('class')) ?? '';
623
+ return cls.includes('seam-file-tile--preview') ? 'preview' : 'row';
624
+ }
625
+ /** True when a consumer has wired `(itemClick)` AND the tile isn't disabled. */
626
+ async isClickable() {
627
+ return (await this._clickableBody()) !== null;
628
+ }
629
+ async click() {
630
+ const clickable = await this._clickableBody();
631
+ if (!clickable) {
632
+ throw new Error('TheSeamFileTileHarness.click: tile is not clickable (no (itemClick) subscriber or disabled)');
633
+ }
634
+ await clickable.click();
635
+ }
636
+ async clickRemove() {
637
+ const btn = await this._remove();
638
+ if (!btn) {
639
+ throw new Error('TheSeamFileTileHarness.clickRemove: remove button is not present (non-removable or disabled)');
640
+ }
641
+ await btn.click();
642
+ }
643
+ }
644
+
645
+ /**
646
+ * Test harness for `<seam-file-field>`. Delegates to tile/input harnesses
647
+ * for their respective pieces.
648
+ */
649
+ class TheSeamFileFieldHarness extends ComponentHarness {
650
+ static hostSelector = 'seam-file-field';
651
+ _replace = this.locatorForOptional('.seam-file-field__replace');
652
+ _allInputs = this.locatorForAll(TheSeamFileInputHarness);
653
+ _tiles = this.locatorForAll(TheSeamFileTileHarness);
654
+ /**
655
+ * Returns the visible embedded file-input harness, or null when the field
656
+ * is in the filled single-mode state (visible input replaced by tile).
657
+ * In filled single-mode the hidden input still exists but is not returned.
658
+ */
659
+ async getInputHarness() {
660
+ const all = await this._allInputs();
661
+ for (const h of all) {
662
+ const host = await h.host();
663
+ if ((await host.getAttribute('hidden')) === null) {
664
+ return h;
665
+ }
666
+ }
667
+ return null;
668
+ }
669
+ async getTiles() {
670
+ return this._tiles();
671
+ }
672
+ async getReplaceButtonText() {
673
+ const btn = await this._replace();
674
+ if (!btn)
675
+ return null;
676
+ return (await btn.text()).trim();
677
+ }
678
+ async clickReplace() {
679
+ const btn = await this._replace();
680
+ if (!btn) {
681
+ throw new Error('TheSeamFileFieldHarness.clickReplace: replace button is not present (field is empty or in multi mode)');
682
+ }
683
+ await btn.click();
684
+ }
685
+ }
686
+
532
687
  /**
533
688
  * Generated bundle index. Do not edit.
534
689
  */
535
690
 
536
- export { TheSeamFileDropZoneDirective, TheSeamFileFieldComponent, TheSeamFileInputComponent, TheSeamFileTileComponent, iconForMime, seamFileItemFromFile, seamFileItemFromUrl, seamFilesFromItems };
691
+ export { TheSeamFileDropZoneDirective, TheSeamFileDropZoneHarness, TheSeamFileFieldComponent, TheSeamFileFieldHarness, TheSeamFileInputComponent, TheSeamFileInputHarness, TheSeamFileTileComponent, TheSeamFileTileHarness, iconForMime, seamFileItemFromFile, seamFileItemFromUrl, seamFilesFromItems };
537
692
  //# sourceMappingURL=theseam-ui-common-file-input.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"theseam-ui-common-file-input.mjs","sources":["../../../projects/ui-common/file-input/file-item.utils.ts","../../../projects/ui-common/file-input/file-input-validation.ts","../../../projects/ui-common/file-input/file-drop-zone.directive.ts","../../../projects/ui-common/file-input/file-input.component.ts","../../../projects/ui-common/file-input/file-input.component.html","../../../projects/ui-common/file-input/file-tile.component.ts","../../../projects/ui-common/file-input/file-tile.component.html","../../../projects/ui-common/file-input/file-field.component.ts","../../../projects/ui-common/file-input/file-field.component.html","../../../projects/ui-common/file-input/theseam-ui-common-file-input.ts"],"sourcesContent":["import {\n faFile,\n faFileExcel,\n faFileImage,\n faFilePdf,\n faFileWord,\n} from '@fortawesome/free-solid-svg-icons'\n\nimport { SeamIcon } from '@theseam/ui-common/icon'\n\nimport { SeamFileItem } from './file-item.models'\n\nexport function seamFileItemFromFile(file: File, id?: string): SeamFileItem {\n return {\n name: file.name,\n size: file.size,\n type: file.type,\n source: { kind: 'file', file },\n id,\n }\n}\n\nexport interface SeamFileItemFromUrlOptions {\n name?: string\n type?: string\n size?: number\n id?: string\n thumbnailUrl?: string\n}\n\nexport function seamFileItemFromUrl(\n url: string,\n opts: SeamFileItemFromUrlOptions = {},\n): SeamFileItem {\n return {\n name: opts.name ?? _basenameFromUrl(url) ?? url,\n size: opts.size,\n type: opts.type,\n source: { kind: 'url', url },\n id: opts.id,\n thumbnailUrl: opts.thumbnailUrl,\n }\n}\n\nfunction _basenameFromUrl(url: string): string | null {\n // Strip query string and fragment before pulling the final path segment.\n const hashIdx = url.indexOf('#')\n const noHash = hashIdx >= 0 ? url.slice(0, hashIdx) : url\n const queryIdx = noHash.indexOf('?')\n const path = queryIdx >= 0 ? noHash.slice(0, queryIdx) : noHash\n\n // Find the last path segment (after the last /)\n const lastSlash = path.lastIndexOf('/')\n if (lastSlash < 0) return null\n\n const basename = path.slice(lastSlash + 1)\n\n // If there's an actual filename after the last slash, decode and return it\n if (basename) {\n try {\n return decodeURIComponent(basename)\n } catch {\n return basename\n }\n }\n\n // No basename (e.g., trailing slash or just protocol/domain), return null\n return null\n}\n\n/**\n * Extracts native `File` objects from items whose source is `file`. Items\n * backed by a URL or a Blob are ignored. Useful for submit-side mapping\n * when the consumer only cares about newly-uploaded blobs.\n */\nexport function seamFilesFromItems(items: SeamFileItem[]): File[] {\n const files: File[] = []\n for (const item of items) {\n if (item.source.kind === 'file') {\n files.push(item.source.file)\n }\n }\n return files\n}\n\nconst WORD_MIMES = new Set<string>([\n 'application/msword',\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n])\n\nconst EXCEL_MIMES = new Set<string>([\n 'application/vnd.ms-excel',\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n 'text/csv',\n])\n\n/**\n * Maps a MIME type to a built-in SeamIcon. Returns a generic file icon for\n * unknown, empty, or missing types. Returns SeamIcon (not IconDefinition) so\n * the icon set can change later without a breaking signature change.\n */\nexport function iconForMime(type: string | undefined): SeamIcon {\n if (!type) return faFile\n if (type === 'application/pdf') return faFilePdf\n if (type.startsWith('image/')) return faFileImage\n if (WORD_MIMES.has(type)) return faFileWord\n if (EXCEL_MIMES.has(type)) return faFileExcel\n return faFile\n}\n","import { SeamFileRejection, SeamFileRejectionReason } from './file-item.models'\n\nexport interface FileValidationOptions {\n accept: string\n maxSize: number | null\n maxFiles: number | null\n}\n\nexport interface FileValidationResult {\n accepted: File[]\n rejected: SeamFileRejection[]\n}\n\n/**\n * Validates a batch of files against accept / maxSize / maxFiles.\n *\n * `accept` is parsed as the standard comma-separated list: `.ext`, `mime/*`,\n * or `mime/subtype`. Matching against `file.type` is case-insensitive; when\n * `file.type` is empty, extension tokens (`.csv`) are tried against the file\n * name. Each rejected file accumulates ALL applicable reasons rather than\n * short-circuiting, so consumers can display comprehensive errors.\n *\n * `maxFiles` caps the total accepted count; files past the cap are rejected\n * with reason `'count'` in arrival order.\n */\nexport function validateFiles(\n files: File[],\n opts: FileValidationOptions,\n): FileValidationResult {\n const acceptTokens = _parseAccept(opts.accept)\n const accepted: File[] = []\n const rejected: SeamFileRejection[] = []\n\n for (const file of files) {\n const reasons: SeamFileRejectionReason[] = []\n\n if (acceptTokens.length > 0 && !_matchesAccept(file, acceptTokens)) {\n reasons.push('type')\n }\n\n if (opts.maxSize !== null && file.size > opts.maxSize) {\n reasons.push('size')\n }\n\n if (reasons.length > 0) {\n rejected.push({ file, reasons })\n continue\n }\n\n if (opts.maxFiles !== null && accepted.length >= opts.maxFiles) {\n rejected.push({ file, reasons: ['count'] })\n continue\n }\n\n accepted.push(file)\n }\n\n return { accepted, rejected }\n}\n\nfunction _parseAccept(accept: string): string[] {\n return accept\n .split(',')\n .map((t) => t.trim().toLowerCase())\n .filter((t) => t.length > 0)\n}\n\nfunction _matchesAccept(file: File, tokens: string[]): boolean {\n const mime = file.type.toLowerCase()\n const name = file.name.toLowerCase()\n\n for (const token of tokens) {\n if (token.startsWith('.')) {\n if (name.endsWith(token)) return true\n continue\n }\n if (!mime) continue\n if (token.endsWith('/*')) {\n const prefix = token.slice(0, -1) // keep the slash\n if (mime.startsWith(prefix)) return true\n continue\n }\n if (token === mime) return true\n }\n return false\n}\n","import {\n booleanAttribute,\n computed,\n Directive,\n input,\n output,\n signal,\n} from '@angular/core'\n\nimport { SeamFileRejection } from './file-item.models'\nimport { validateFiles } from './file-input-validation'\n\n@Directive({\n selector: '[seamFileDropZone]',\n host: {\n '[class.seam-file-drop-zone--over]': '_isOver()',\n '(dragenter)': '_onDragEnter($event)',\n '(dragover)': '_onDragOver($event)',\n '(dragleave)': '_onDragLeave($event)',\n '(drop)': '_onDrop($event)',\n },\n})\nexport class TheSeamFileDropZoneDirective {\n readonly accept = input<string>('')\n readonly maxSize = input<number | null>(null)\n readonly maxFiles = input<number | null>(null)\n readonly disabled = input(false, { transform: booleanAttribute })\n\n readonly seamFileDrop = output<File[]>()\n readonly seamFileDropRejected = output<SeamFileRejection[]>()\n\n /** Counter-based dragenter/leave tracking to avoid child-element flicker. */\n private readonly _dragDepth = signal(0)\n\n protected readonly _isOver = computed(\n () => !this.disabled() && this._dragDepth() > 0,\n )\n\n protected _onDragEnter(event: DragEvent): void {\n if (this.disabled()) return\n event.preventDefault()\n this._dragDepth.update((n) => n + 1)\n }\n\n protected _onDragOver(event: DragEvent): void {\n if (this.disabled()) return\n // preventDefault is required for the drop event to fire.\n event.preventDefault()\n }\n\n protected _onDragLeave(event: DragEvent): void {\n if (this.disabled()) return\n this._dragDepth.update((n) => Math.max(0, n - 1))\n }\n\n protected _onDrop(event: DragEvent): void {\n if (this.disabled()) return\n event.preventDefault()\n this._dragDepth.set(0)\n\n const files = event.dataTransfer ? Array.from(event.dataTransfer.files) : []\n if (files.length === 0) return\n\n const { accepted, rejected } = validateFiles(files, {\n accept: this.accept(),\n maxSize: this.maxSize(),\n maxFiles: this.maxFiles(),\n })\n\n this.seamFileDrop.emit(accepted)\n if (rejected.length > 0) this.seamFileDropRejected.emit(rejected)\n }\n}\n","import {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n ElementRef,\n input,\n output,\n signal,\n viewChild,\n} from '@angular/core'\n\nimport { faUpload } from '@fortawesome/free-solid-svg-icons'\n\nimport { TheSeamIconModule } from '@theseam/ui-common/icon'\n\nimport { TheSeamFileDropZoneDirective } from './file-drop-zone.directive'\nimport { validateFiles } from './file-input-validation'\nimport { SeamFileRejection, SeamFileRejectionReason } from './file-item.models'\n\n@Component({\n selector: 'seam-file-input',\n templateUrl: './file-input.component.html',\n styleUrls: ['./file-input.component.scss'],\n imports: [TheSeamFileDropZoneDirective, TheSeamIconModule],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class TheSeamFileInputComponent {\n readonly multiple = input(false, { transform: booleanAttribute })\n readonly accept = input<string>('')\n readonly maxSize = input<number | null>(null)\n readonly maxFiles = input<number | null>(null)\n readonly disabled = input(false, { transform: booleanAttribute })\n readonly hideErrors = input(false, { transform: booleanAttribute })\n readonly promptText = input<string>('Choose a file')\n readonly promptSuffix = input<string>('or drag it here')\n\n readonly filesAdded = output<File[]>()\n readonly rejected = output<SeamFileRejection[]>()\n\n protected readonly _faUpload = faUpload\n protected readonly _lastRejections = signal<SeamFileRejection[]>([])\n protected readonly _effectiveMaxFiles = computed(() => {\n const explicit = this.maxFiles()\n if (!this.multiple()) {\n return explicit !== null ? Math.min(explicit, 1) : 1\n }\n return explicit\n })\n protected readonly _errorMessage = computed(() =>\n _formatErrors(\n this._lastRejections(),\n this.maxSize(),\n this._effectiveMaxFiles(),\n ),\n )\n\n private readonly _nativeInput =\n viewChild.required<ElementRef<HTMLInputElement>>('native')\n\n _openPicker(): void {\n if (this.disabled()) return\n this._nativeInput().nativeElement.click()\n }\n\n protected _onFilesDropped(files: File[]): void {\n this._lastRejections.set([])\n if (files.length > 0) this.filesAdded.emit(files)\n }\n\n protected _onRejected(rejections: SeamFileRejection[]): void {\n this._lastRejections.set(rejections)\n this.rejected.emit(rejections)\n }\n\n protected _onNativeChange(event: Event): void {\n const nativeInput = event.target as HTMLInputElement\n const files = nativeInput.files ? Array.from(nativeInput.files) : []\n // Clear the value so the same file can be re-selected next time.\n nativeInput.value = ''\n\n if (files.length === 0) return\n\n const { accepted, rejected } = validateFiles(files, {\n accept: this.accept(),\n maxSize: this.maxSize(),\n maxFiles: this._effectiveMaxFiles(),\n })\n\n if (rejected.length > 0) {\n this._lastRejections.set(rejected)\n this.rejected.emit(rejected)\n } else {\n this._lastRejections.set([])\n }\n\n if (accepted.length > 0) this.filesAdded.emit(accepted)\n }\n}\n\nfunction _formatErrors(\n rejections: SeamFileRejection[],\n maxSize: number | null,\n maxFiles: number | null,\n): string | null {\n if (rejections.length === 0) return null\n const firstReason: SeamFileRejectionReason = rejections[0].reasons[0]\n switch (firstReason) {\n case 'type':\n return 'File type not accepted.'\n case 'size': {\n const mb = maxSize !== null ? (maxSize / (1024 * 1024)).toFixed(1) : null\n return mb\n ? `File exceeds the maximum size (${mb} MB).`\n : 'File exceeds the maximum size.'\n }\n case 'count':\n return maxFiles !== null\n ? `Only ${maxFiles} file(s) can be added.`\n : 'Too many files selected.'\n default:\n return 'File could not be accepted.'\n }\n}\n","<div\n class=\"seam-file-input__zone\"\n seamFileDropZone\n [accept]=\"accept()\"\n [maxSize]=\"maxSize()\"\n [maxFiles]=\"_effectiveMaxFiles()\"\n [disabled]=\"disabled()\"\n (seamFileDrop)=\"_onFilesDropped($event)\"\n (seamFileDropRejected)=\"_onRejected($event)\"\n role=\"button\"\n [attr.tabindex]=\"disabled() ? -1 : 0\"\n (click)=\"_openPicker()\"\n (keydown.enter)=\"_openPicker(); $event.preventDefault()\"\n (keydown.space)=\"_openPicker(); $event.preventDefault()\"\n>\n <span class=\"seam-file-input__icon\">\n <seam-icon [icon]=\"_faUpload\"></seam-icon>\n </span>\n <p class=\"seam-file-input__prompt\">\n <strong>{{ promptText() }}</strong> {{ promptSuffix() }}\n </p>\n</div>\n\n<input\n #native\n type=\"file\"\n hidden\n [multiple]=\"multiple()\"\n [attr.accept]=\"accept() || null\"\n (change)=\"_onNativeChange($event)\"\n/>\n\n@if (!hideErrors() && _errorMessage(); as msg) {\n <p class=\"seam-file-input__errors\">{{ msg }}</p>\n}\n","import {\n AfterViewInit,\n booleanAttribute,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n computed,\n effect,\n inject,\n input,\n output,\n signal,\n} from '@angular/core'\n\nimport { faTimes } from '@fortawesome/free-solid-svg-icons'\n\nimport { NgTemplateOutlet } from '@angular/common'\n\nimport { TheSeamIconModule } from '@theseam/ui-common/icon'\n\nimport { iconForMime } from './file-item.utils'\nimport { SeamFileItem, SeamFileTileVariant } from './file-item.models'\n\n@Component({\n selector: 'seam-file-tile',\n templateUrl: './file-tile.component.html',\n styleUrls: ['./file-tile.component.scss'],\n imports: [TheSeamIconModule, NgTemplateOutlet],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class TheSeamFileTileComponent implements AfterViewInit {\n private readonly _cdr = inject(ChangeDetectorRef)\n readonly item = input.required<SeamFileItem>()\n readonly variant = input<SeamFileTileVariant>('row')\n readonly showName = input(true, { transform: booleanAttribute })\n readonly showMeta = input(true, { transform: booleanAttribute })\n readonly removable = input(true, { transform: booleanAttribute })\n readonly disabled = input(false, { transform: booleanAttribute })\n\n readonly remove = output<SeamFileItem>()\n readonly itemClick = output<SeamFileItem>()\n\n protected readonly _faTimes = faTimes\n\n protected readonly _mimeIcon = computed(() => iconForMime(this.item().type))\n protected readonly _metaLine = computed(() => _formatMeta(this.item()))\n protected readonly _showRemoveBtn = computed(\n () => this.removable() && !this.disabled(),\n )\n\n /** True when itemClick is observed AND the tile is not disabled. */\n protected readonly _isInteractive = computed(\n () => this._clickObserved() && !this.disabled(),\n )\n\n /**\n * Thumbnail URL for image items. Tracked across item changes so object\n * URLs are revoked when the item changes or the component is destroyed.\n */\n private _ownedObjectUrl: string | null = null\n private _pendingObjectUrl: string | null = null\n\n protected readonly _thumbUrl = computed(() => {\n const item = this.item()\n\n if (item.thumbnailUrl) return item.thumbnailUrl\n\n const isImage = _isImageMime(item.type)\n\n if (\n (item.source.kind === 'file' || item.source.kind === 'blob') &&\n isImage\n ) {\n const blob =\n item.source.kind === 'file' ? item.source.file : item.source.blob\n const url = URL.createObjectURL(blob)\n this._pendingObjectUrl = url\n return url\n }\n\n if (item.source.kind === 'url' && _looksLikeImage(item)) {\n return item.source.url\n }\n\n return null\n })\n\n /**\n * True once we detect that a consumer has wired (itemClick).\n * Detected in ngAfterViewInit — by that point the parent's template binding\n * has called subscribe() on the OutputEmitterRef, populating its internal\n * `listeners` array (Option A: access via internal field on Angular 20's\n * OutputEmitterRef). If the internal shape is absent, conservatively stays\n * false (opt-out default — no unwanted role=button on inert tiles).\n */\n protected readonly _clickObserved = signal(false)\n\n constructor() {\n // When _thumbUrl changes, revoke the previous owned URL (if any).\n effect(() => {\n // Read the signal so this effect re-runs when the thumbnail changes.\n this._thumbUrl()\n const previous = this._ownedObjectUrl\n this._ownedObjectUrl = this._pendingObjectUrl\n this._pendingObjectUrl = null\n if (previous && previous !== this._ownedObjectUrl) {\n URL.revokeObjectURL(previous)\n }\n })\n // Destroy cleanup: revoke the last owned URL.\n effect((onCleanup) => {\n onCleanup(() => {\n if (this._ownedObjectUrl) {\n URL.revokeObjectURL(this._ownedObjectUrl)\n this._ownedObjectUrl = null\n }\n })\n })\n }\n\n ngAfterViewInit(): void {\n // Detect whether (itemClick) is bound by checking the OutputEmitterRef's\n // internal listeners array. By ngAfterViewInit, the parent's template\n // bindings (including event bindings via subscribe()) have already been\n // applied during the parent's change-detection pass.\n //\n // Option A: access (this.itemClick as any).listeners which is the internal\n // array in Angular 20's OutputEmitterRef (null initially, an array once\n // subscribed). If the internal shape changes, we conservatively keep false.\n const ref = this.itemClick as unknown as { listeners?: unknown[] | null }\n const observed =\n ref.listeners !== undefined ? (ref.listeners?.length ?? 0) > 0 : false\n if (observed) {\n this._clickObserved.set(true)\n this._cdr.markForCheck()\n }\n }\n\n protected _onRemove(event: MouseEvent): void {\n event.stopPropagation()\n this.remove.emit(this.item())\n }\n\n protected _onBodyClick(): void {\n if (!this._clickObserved() || this.disabled()) return\n this.itemClick.emit(this.item())\n }\n\n protected _onBodyKey(event: KeyboardEvent): void {\n if (!this._clickObserved() || this.disabled()) return\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n this.itemClick.emit(this.item())\n }\n }\n}\n\nfunction _formatMeta(item: SeamFileItem): string {\n const parts: string[] = []\n if (item.size !== undefined) parts.push(_formatBytes(item.size))\n if (item.type) parts.push(item.type)\n return parts.join(' · ')\n}\n\nfunction _formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n}\n\nfunction _isImageMime(type: string | undefined): boolean {\n return !!type && type.toLowerCase().startsWith('image/')\n}\n\nconst IMAGE_EXT = /\\.(png|jpe?g|gif|webp|bmp|svg)(\\?|$)/i\n\nfunction _looksLikeImage(item: SeamFileItem): boolean {\n if (_isImageMime(item.type)) return true\n if (item.source.kind === 'url' && IMAGE_EXT.test(item.source.url)) return true\n return false\n}\n","<div\n class=\"seam-file-tile\"\n [class.seam-file-tile--row]=\"variant() === 'row'\"\n [class.seam-file-tile--preview]=\"variant() === 'preview'\"\n [class.seam-file-tile--clickable]=\"_isInteractive()\"\n>\n @if (variant() === 'row') {\n @if (_isInteractive()) {\n <div\n class=\"seam-file-tile__clickable-body\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"_onBodyClick()\"\n (keydown)=\"_onBodyKey($event)\"\n >\n <ng-container *ngTemplateOutlet=\"rowContent\"></ng-container>\n </div>\n } @else {\n <ng-container *ngTemplateOutlet=\"rowContent\"></ng-container>\n }\n\n @if (_showRemoveBtn()) {\n <button\n type=\"button\"\n class=\"seam-file-tile__remove\"\n (click)=\"_onRemove($event)\"\n title=\"Remove file\"\n >\n <seam-icon [icon]=\"_faTimes\"></seam-icon>\n </button>\n }\n } @else {\n @if (_showRemoveBtn()) {\n <button\n type=\"button\"\n class=\"seam-file-tile__remove seam-file-tile__remove--overlay\"\n (click)=\"_onRemove($event)\"\n title=\"Remove file\"\n >\n <seam-icon [icon]=\"_faTimes\"></seam-icon>\n </button>\n }\n @if (_isInteractive()) {\n <div\n class=\"seam-file-tile__clickable-body\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"_onBodyClick()\"\n (keydown)=\"_onBodyKey($event)\"\n >\n <ng-container *ngTemplateOutlet=\"previewContent\"></ng-container>\n </div>\n } @else {\n <ng-container *ngTemplateOutlet=\"previewContent\"></ng-container>\n }\n }\n</div>\n\n<ng-template #rowContent>\n <span\n class=\"seam-file-tile__visual\"\n [class.seam-file-tile__visual--image]=\"!!_thumbUrl()\"\n >\n @if (_thumbUrl(); as url) {\n <img class=\"seam-file-tile__thumb\" [src]=\"url\" [alt]=\"item().name\" />\n } @else {\n <seam-icon [icon]=\"_mimeIcon()\"></seam-icon>\n }\n </span>\n <div class=\"seam-file-tile__body\">\n <div class=\"seam-file-tile__name\" [attr.title]=\"item().name\">\n {{ item().name }}\n </div>\n @if (showMeta() && _metaLine(); as meta) {\n <div class=\"seam-file-tile__meta\">{{ meta }}</div>\n }\n </div>\n</ng-template>\n\n<ng-template #previewContent>\n <span class=\"seam-file-tile__preview-media\">\n @if (_thumbUrl(); as url) {\n <img class=\"seam-file-tile__thumb\" [src]=\"url\" [alt]=\"item().name\" />\n } @else {\n <span class=\"seam-file-tile__visual\">\n <seam-icon [icon]=\"_mimeIcon()\"></seam-icon>\n </span>\n }\n </span>\n @if (showName()) {\n <div class=\"seam-file-tile__preview-name\" [attr.title]=\"item().name\">\n {{ item().name }}\n </div>\n }\n</ng-template>\n","import {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n forwardRef,\n input,\n output,\n signal,\n} from '@angular/core'\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'\n\nimport { TheSeamFileInputComponent } from './file-input.component'\nimport { TheSeamFileTileComponent } from './file-tile.component'\nimport { SeamFileItem, SeamFileRejection } from './file-item.models'\nimport { seamFileItemFromFile } from './file-item.utils'\n\n@Component({\n selector: 'seam-file-field',\n templateUrl: './file-field.component.html',\n styleUrls: ['./file-field.component.scss'],\n imports: [TheSeamFileInputComponent, TheSeamFileTileComponent],\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => TheSeamFileFieldComponent),\n multi: true,\n },\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class TheSeamFileFieldComponent implements ControlValueAccessor {\n readonly multiple = input(false, { transform: booleanAttribute })\n readonly accept = input<string>('')\n readonly maxSize = input<number | null>(null)\n readonly maxFiles = input<number | null>(null)\n readonly disabled = input(false, { transform: booleanAttribute })\n readonly previewMode = input(false, { transform: booleanAttribute })\n readonly showTileName = input(true, { transform: booleanAttribute })\n readonly promptText = input<string>('Choose a file')\n readonly promptSuffix = input<string>('or drag it here')\n readonly replaceText = input<string>('choose a different file')\n readonly hideErrors = input(false, { transform: booleanAttribute })\n\n readonly rejected = output<SeamFileRejection[]>()\n\n protected readonly _items = signal<SeamFileItem[]>([])\n protected readonly _cvaDisabled = signal(false)\n\n protected readonly _effectiveDisabled = computed(\n () => this.disabled() || this._cvaDisabled(),\n )\n\n protected readonly _hasFile = computed(\n () => !this.multiple() && this._items().length > 0,\n )\n\n protected readonly _remainingMaxFiles = computed(() => {\n const max = this.maxFiles()\n if (!this.multiple()) {\n // Single-mode: cap at 1 always. If explicit lower, honor.\n return max !== null ? Math.min(max, 1) : 1\n }\n if (max === null) return null\n return Math.max(0, max - this._items().length)\n })\n\n protected readonly _tileVariant = computed(() =>\n this.previewMode() ? 'preview' : 'row',\n )\n\n private _onChange: (value: SeamFileItem[]) => void = () => undefined\n private _onTouched: () => void = () => undefined\n\n writeValue(value: SeamFileItem[] | null): void {\n this._items.set(value ?? [])\n }\n\n registerOnChange(fn: (value: SeamFileItem[]) => void): void {\n this._onChange = fn\n }\n\n registerOnTouched(fn: () => void): void {\n this._onTouched = fn\n }\n\n setDisabledState(isDisabled: boolean): void {\n this._cvaDisabled.set(isDisabled)\n }\n\n protected _onFilesAdded(files: File[]): void {\n if (files.length === 0) return\n const added = files.map((f) => seamFileItemFromFile(f))\n if (!this.multiple()) {\n this._items.set(added.slice(0, 1))\n } else {\n const remaining = this._remainingMaxFiles()\n const toAdd = remaining !== null ? added.slice(0, remaining) : added\n if (toAdd.length === 0) return\n this._items.update((prev) => [...prev, ...toAdd])\n }\n this._emit()\n }\n\n protected _onRejected(rejections: SeamFileRejection[]): void {\n this.rejected.emit(rejections)\n }\n\n protected _onTileRemove(item: SeamFileItem): void {\n this._items.update((prev) => prev.filter((i) => i !== item))\n this._emit()\n }\n\n private _emit(): void {\n this._onChange(this._items())\n this._onTouched()\n }\n}\n","@if (_hasFile()) {\n <seam-file-tile\n [item]=\"_items()[0]\"\n [variant]=\"_tileVariant()\"\n [showName]=\"showTileName()\"\n [disabled]=\"_effectiveDisabled()\"\n (remove)=\"_onTileRemove($event)\"\n ></seam-file-tile>\n <button\n type=\"button\"\n class=\"seam-file-field__replace\"\n [disabled]=\"_effectiveDisabled()\"\n (click)=\"inputComponentWhenFilled._openPicker()\"\n >\n or <strong>{{ replaceText() }}</strong>\n </button>\n <!-- Hidden mounted input so the replace button has a picker to delegate to. -->\n <seam-file-input\n #inputComponentWhenFilled\n hidden\n [multiple]=\"multiple()\"\n [accept]=\"accept()\"\n [maxSize]=\"maxSize()\"\n [maxFiles]=\"_remainingMaxFiles()\"\n [disabled]=\"_effectiveDisabled()\"\n [hideErrors]=\"true\"\n (filesAdded)=\"_onFilesAdded($event)\"\n (rejected)=\"_onRejected($event)\"\n ></seam-file-input>\n} @else {\n <seam-file-input\n #inputComponent\n [multiple]=\"multiple()\"\n [accept]=\"accept()\"\n [maxSize]=\"maxSize()\"\n [maxFiles]=\"_remainingMaxFiles()\"\n [disabled]=\"_effectiveDisabled()\"\n [hideErrors]=\"hideErrors()\"\n [promptText]=\"promptText()\"\n [promptSuffix]=\"promptSuffix()\"\n (filesAdded)=\"_onFilesAdded($event)\"\n (rejected)=\"_onRejected($event)\"\n ></seam-file-input>\n\n @if (multiple() && _items().length > 0) {\n <div\n class=\"seam-file-field__tiles\"\n [class.seam-file-field__tiles--preview]=\"previewMode()\"\n >\n @for (item of _items(); track item.id ?? item.name) {\n <seam-file-tile\n [item]=\"item\"\n [variant]=\"_tileVariant()\"\n [showName]=\"showTileName()\"\n [disabled]=\"_effectiveDisabled()\"\n (remove)=\"_onTileRemove($event)\"\n ></seam-file-tile>\n }\n </div>\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"theseam-ui-common-file-input.mjs","sources":["../../../projects/ui-common/file-input/file-item.utils.ts","../../../projects/ui-common/file-input/file-input-validation.ts","../../../projects/ui-common/file-input/file-drop-zone.directive.ts","../../../projects/ui-common/file-input/file-input.component.ts","../../../projects/ui-common/file-input/file-input.component.html","../../../projects/ui-common/file-input/file-tile.component.ts","../../../projects/ui-common/file-input/file-tile.component.html","../../../projects/ui-common/file-input/file-field.component.ts","../../../projects/ui-common/file-input/file-field.component.html","../../../projects/ui-common/file-input/testing/_harness-utils.ts","../../../projects/ui-common/file-input/testing/file-drop-zone.harness.ts","../../../projects/ui-common/file-input/testing/file-input.harness.ts","../../../projects/ui-common/file-input/testing/file-tile.harness.ts","../../../projects/ui-common/file-input/testing/file-field.harness.ts","../../../projects/ui-common/file-input/theseam-ui-common-file-input.ts"],"sourcesContent":["import {\n faFile,\n faFileExcel,\n faFileImage,\n faFilePdf,\n faFileWord,\n} from '@fortawesome/free-solid-svg-icons'\n\nimport { SeamIcon } from '@theseam/ui-common/icon'\n\nimport { SeamFileItem } from './file-item.models'\n\nexport function seamFileItemFromFile(file: File, id?: string): SeamFileItem {\n return {\n name: file.name,\n size: file.size,\n type: file.type,\n source: { kind: 'file', file },\n id,\n }\n}\n\nexport interface SeamFileItemFromUrlOptions {\n name?: string\n type?: string\n size?: number\n id?: string\n thumbnailUrl?: string\n}\n\nexport function seamFileItemFromUrl(\n url: string,\n opts: SeamFileItemFromUrlOptions = {},\n): SeamFileItem {\n return {\n name: opts.name ?? _basenameFromUrl(url) ?? url,\n size: opts.size,\n type: opts.type,\n source: { kind: 'url', url },\n id: opts.id,\n thumbnailUrl: opts.thumbnailUrl,\n }\n}\n\nfunction _basenameFromUrl(url: string): string | null {\n // Strip query string and fragment before pulling the final path segment.\n const hashIdx = url.indexOf('#')\n const noHash = hashIdx >= 0 ? url.slice(0, hashIdx) : url\n const queryIdx = noHash.indexOf('?')\n const path = queryIdx >= 0 ? noHash.slice(0, queryIdx) : noHash\n\n // Find the last path segment (after the last /)\n const lastSlash = path.lastIndexOf('/')\n if (lastSlash < 0) return null\n\n const basename = path.slice(lastSlash + 1)\n\n // If there's an actual filename after the last slash, decode and return it\n if (basename) {\n try {\n return decodeURIComponent(basename)\n } catch {\n return basename\n }\n }\n\n // No basename (e.g., trailing slash or just protocol/domain), return null\n return null\n}\n\n/**\n * Extracts native `File` objects from items whose source is `file`. Items\n * backed by a URL or a Blob are ignored. Useful for submit-side mapping\n * when the consumer only cares about newly-uploaded blobs.\n */\nexport function seamFilesFromItems(items: SeamFileItem[]): File[] {\n const files: File[] = []\n for (const item of items) {\n if (item.source.kind === 'file') {\n files.push(item.source.file)\n }\n }\n return files\n}\n\nconst WORD_MIMES = new Set<string>([\n 'application/msword',\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n])\n\nconst EXCEL_MIMES = new Set<string>([\n 'application/vnd.ms-excel',\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n 'text/csv',\n])\n\n/**\n * Maps a MIME type to a built-in SeamIcon. Returns a generic file icon for\n * unknown, empty, or missing types. Returns SeamIcon (not IconDefinition) so\n * the icon set can change later without a breaking signature change.\n */\nexport function iconForMime(type: string | undefined): SeamIcon {\n if (!type) return faFile\n if (type === 'application/pdf') return faFilePdf\n if (type.startsWith('image/')) return faFileImage\n if (WORD_MIMES.has(type)) return faFileWord\n if (EXCEL_MIMES.has(type)) return faFileExcel\n return faFile\n}\n","import { SeamFileRejection, SeamFileRejectionReason } from './file-item.models'\n\nexport interface FileValidationOptions {\n accept: string\n maxSize: number | null\n maxFiles: number | null\n}\n\nexport interface FileValidationResult {\n accepted: File[]\n rejected: SeamFileRejection[]\n}\n\n/**\n * Validates a batch of files against accept / maxSize / maxFiles.\n *\n * `accept` is parsed as the standard comma-separated list: `.ext`, `mime/*`,\n * or `mime/subtype`. Matching against `file.type` is case-insensitive; when\n * `file.type` is empty, extension tokens (`.csv`) are tried against the file\n * name. Each rejected file accumulates ALL applicable reasons rather than\n * short-circuiting, so consumers can display comprehensive errors.\n *\n * `maxFiles` caps the total accepted count; files past the cap are rejected\n * with reason `'count'` in arrival order.\n */\nexport function validateFiles(\n files: File[],\n opts: FileValidationOptions,\n): FileValidationResult {\n const acceptTokens = _parseAccept(opts.accept)\n const accepted: File[] = []\n const rejected: SeamFileRejection[] = []\n\n for (const file of files) {\n const reasons: SeamFileRejectionReason[] = []\n\n if (acceptTokens.length > 0 && !_matchesAccept(file, acceptTokens)) {\n reasons.push('type')\n }\n\n if (opts.maxSize !== null && file.size > opts.maxSize) {\n reasons.push('size')\n }\n\n if (reasons.length > 0) {\n rejected.push({ file, reasons })\n continue\n }\n\n if (opts.maxFiles !== null && accepted.length >= opts.maxFiles) {\n rejected.push({ file, reasons: ['count'] })\n continue\n }\n\n accepted.push(file)\n }\n\n return { accepted, rejected }\n}\n\nfunction _parseAccept(accept: string): string[] {\n return accept\n .split(',')\n .map((t) => t.trim().toLowerCase())\n .filter((t) => t.length > 0)\n}\n\nfunction _matchesAccept(file: File, tokens: string[]): boolean {\n const mime = file.type.toLowerCase()\n const name = file.name.toLowerCase()\n\n for (const token of tokens) {\n if (token.startsWith('.')) {\n if (name.endsWith(token)) return true\n continue\n }\n if (!mime) continue\n if (token.endsWith('/*')) {\n const prefix = token.slice(0, -1) // keep the slash\n if (mime.startsWith(prefix)) return true\n continue\n }\n if (token === mime) return true\n }\n return false\n}\n","import {\n booleanAttribute,\n computed,\n Directive,\n input,\n output,\n signal,\n} from '@angular/core'\n\nimport { SeamFileRejection } from './file-item.models'\nimport { validateFiles } from './file-input-validation'\n\n@Directive({\n selector: '[seamFileDropZone]',\n host: {\n '[class.seam-file-drop-zone--over]': '_isOver()',\n '(dragenter)': '_onDragEnter($event)',\n '(dragover)': '_onDragOver($event)',\n '(dragleave)': '_onDragLeave($event)',\n '(drop)': '_onDrop($event)',\n },\n})\nexport class TheSeamFileDropZoneDirective {\n readonly accept = input<string>('')\n readonly maxSize = input<number | null>(null)\n readonly maxFiles = input<number | null>(null)\n readonly disabled = input(false, { transform: booleanAttribute })\n\n readonly seamFileDrop = output<File[]>()\n readonly seamFileDropRejected = output<SeamFileRejection[]>()\n\n /** Counter-based dragenter/leave tracking to avoid child-element flicker. */\n private readonly _dragDepth = signal(0)\n\n protected readonly _isOver = computed(\n () => !this.disabled() && this._dragDepth() > 0,\n )\n\n protected _onDragEnter(event: DragEvent): void {\n if (this.disabled()) return\n event.preventDefault()\n this._dragDepth.update((n) => n + 1)\n }\n\n protected _onDragOver(event: DragEvent): void {\n if (this.disabled()) return\n // preventDefault is required for the drop event to fire.\n event.preventDefault()\n }\n\n protected _onDragLeave(event: DragEvent): void {\n if (this.disabled()) return\n this._dragDepth.update((n) => Math.max(0, n - 1))\n }\n\n protected _onDrop(event: DragEvent): void {\n if (this.disabled()) return\n event.preventDefault()\n this._dragDepth.set(0)\n\n const files = event.dataTransfer ? Array.from(event.dataTransfer.files) : []\n if (files.length === 0) return\n\n const { accepted, rejected } = validateFiles(files, {\n accept: this.accept(),\n maxSize: this.maxSize(),\n maxFiles: this.maxFiles(),\n })\n\n this.seamFileDrop.emit(accepted)\n if (rejected.length > 0) this.seamFileDropRejected.emit(rejected)\n }\n}\n","import {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n ElementRef,\n input,\n output,\n signal,\n viewChild,\n} from '@angular/core'\n\nimport { faUpload } from '@fortawesome/free-solid-svg-icons'\n\nimport { TheSeamIconModule } from '@theseam/ui-common/icon'\n\nimport { TheSeamFileDropZoneDirective } from './file-drop-zone.directive'\nimport { validateFiles } from './file-input-validation'\nimport { SeamFileRejection, SeamFileRejectionReason } from './file-item.models'\n\n@Component({\n selector: 'seam-file-input',\n templateUrl: './file-input.component.html',\n styleUrls: ['./file-input.component.scss'],\n imports: [TheSeamFileDropZoneDirective, TheSeamIconModule],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class TheSeamFileInputComponent {\n readonly multiple = input(false, { transform: booleanAttribute })\n readonly accept = input<string>('')\n readonly maxSize = input<number | null>(null)\n readonly maxFiles = input<number | null>(null)\n readonly disabled = input(false, { transform: booleanAttribute })\n readonly hideErrors = input(false, { transform: booleanAttribute })\n readonly promptText = input<string>('Choose a file')\n readonly promptSuffix = input<string>('or drag it here')\n\n readonly filesAdded = output<File[]>()\n readonly rejected = output<SeamFileRejection[]>()\n\n protected readonly _faUpload = faUpload\n protected readonly _lastRejections = signal<SeamFileRejection[]>([])\n protected readonly _effectiveMaxFiles = computed(() => {\n const explicit = this.maxFiles()\n if (!this.multiple()) {\n return explicit !== null ? Math.min(explicit, 1) : 1\n }\n return explicit\n })\n protected readonly _errorMessage = computed(() =>\n _formatErrors(\n this._lastRejections(),\n this.maxSize(),\n this._effectiveMaxFiles(),\n ),\n )\n\n private readonly _nativeInput =\n viewChild.required<ElementRef<HTMLInputElement>>('native')\n\n _openPicker(): void {\n if (this.disabled()) return\n this._nativeInput().nativeElement.click()\n }\n\n protected _onFilesDropped(files: File[]): void {\n this._lastRejections.set([])\n if (files.length > 0) this.filesAdded.emit(files)\n }\n\n protected _onRejected(rejections: SeamFileRejection[]): void {\n this._lastRejections.set(rejections)\n this.rejected.emit(rejections)\n }\n\n protected _onNativeChange(event: Event): void {\n const nativeInput = event.target as HTMLInputElement\n const files = nativeInput.files ? Array.from(nativeInput.files) : []\n // Clear the value so the same file can be re-selected next time.\n nativeInput.value = ''\n\n if (files.length === 0) return\n\n const { accepted, rejected } = validateFiles(files, {\n accept: this.accept(),\n maxSize: this.maxSize(),\n maxFiles: this._effectiveMaxFiles(),\n })\n\n if (rejected.length > 0) {\n this._lastRejections.set(rejected)\n this.rejected.emit(rejected)\n } else {\n this._lastRejections.set([])\n }\n\n if (accepted.length > 0) this.filesAdded.emit(accepted)\n }\n}\n\nfunction _formatErrors(\n rejections: SeamFileRejection[],\n maxSize: number | null,\n maxFiles: number | null,\n): string | null {\n if (rejections.length === 0) return null\n const firstReason: SeamFileRejectionReason = rejections[0].reasons[0]\n switch (firstReason) {\n case 'type':\n return 'File type not accepted.'\n case 'size': {\n const mb = maxSize !== null ? (maxSize / (1024 * 1024)).toFixed(1) : null\n return mb\n ? `File exceeds the maximum size (${mb} MB).`\n : 'File exceeds the maximum size.'\n }\n case 'count':\n return maxFiles !== null\n ? `Only ${maxFiles} file(s) can be added.`\n : 'Too many files selected.'\n default:\n return 'File could not be accepted.'\n }\n}\n","<div\n class=\"seam-file-input__zone\"\n seamFileDropZone\n [accept]=\"accept()\"\n [maxSize]=\"maxSize()\"\n [maxFiles]=\"_effectiveMaxFiles()\"\n [disabled]=\"disabled()\"\n (seamFileDrop)=\"_onFilesDropped($event)\"\n (seamFileDropRejected)=\"_onRejected($event)\"\n role=\"button\"\n [attr.tabindex]=\"disabled() ? -1 : 0\"\n (click)=\"_openPicker()\"\n (keydown.enter)=\"_openPicker(); $event.preventDefault()\"\n (keydown.space)=\"_openPicker(); $event.preventDefault()\"\n>\n <span class=\"seam-file-input__icon\">\n <seam-icon [icon]=\"_faUpload\"></seam-icon>\n </span>\n <p class=\"seam-file-input__prompt\">\n <strong>{{ promptText() }}</strong> {{ promptSuffix() }}\n </p>\n</div>\n\n<input\n #native\n type=\"file\"\n hidden\n [multiple]=\"multiple()\"\n [attr.accept]=\"accept() || null\"\n (change)=\"_onNativeChange($event)\"\n/>\n\n@if (!hideErrors() && _errorMessage(); as msg) {\n <p class=\"seam-file-input__errors\">{{ msg }}</p>\n}\n","import {\n AfterViewInit,\n booleanAttribute,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n computed,\n effect,\n inject,\n input,\n output,\n signal,\n} from '@angular/core'\n\nimport { faTimes } from '@fortawesome/free-solid-svg-icons'\n\nimport { NgTemplateOutlet } from '@angular/common'\n\nimport { TheSeamIconModule } from '@theseam/ui-common/icon'\n\nimport { iconForMime } from './file-item.utils'\nimport { SeamFileItem, SeamFileTileVariant } from './file-item.models'\n\n@Component({\n selector: 'seam-file-tile',\n templateUrl: './file-tile.component.html',\n styleUrls: ['./file-tile.component.scss'],\n imports: [TheSeamIconModule, NgTemplateOutlet],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class TheSeamFileTileComponent implements AfterViewInit {\n private readonly _cdr = inject(ChangeDetectorRef)\n readonly item = input.required<SeamFileItem>()\n readonly variant = input<SeamFileTileVariant>('row')\n readonly showName = input(true, { transform: booleanAttribute })\n readonly showMeta = input(true, { transform: booleanAttribute })\n readonly removable = input(true, { transform: booleanAttribute })\n readonly disabled = input(false, { transform: booleanAttribute })\n\n readonly remove = output<SeamFileItem>()\n readonly itemClick = output<SeamFileItem>()\n\n protected readonly _faTimes = faTimes\n\n protected readonly _mimeIcon = computed(() => iconForMime(this.item().type))\n protected readonly _metaLine = computed(() => _formatMeta(this.item()))\n protected readonly _showRemoveBtn = computed(\n () => this.removable() && !this.disabled(),\n )\n\n /** True when itemClick is observed AND the tile is not disabled. */\n protected readonly _isInteractive = computed(\n () => this._clickObserved() && !this.disabled(),\n )\n\n /**\n * Thumbnail URL for image items. Tracked across item changes so object\n * URLs are revoked when the item changes or the component is destroyed.\n */\n private _ownedObjectUrl: string | null = null\n private _pendingObjectUrl: string | null = null\n\n protected readonly _thumbUrl = computed(() => {\n const item = this.item()\n\n if (item.thumbnailUrl) return item.thumbnailUrl\n\n const isImage = _isImageMime(item.type)\n\n if (\n (item.source.kind === 'file' || item.source.kind === 'blob') &&\n isImage\n ) {\n const blob =\n item.source.kind === 'file' ? item.source.file : item.source.blob\n const url = URL.createObjectURL(blob)\n this._pendingObjectUrl = url\n return url\n }\n\n if (item.source.kind === 'url' && _looksLikeImage(item)) {\n return item.source.url\n }\n\n return null\n })\n\n /**\n * True once we detect that a consumer has wired (itemClick).\n * Detected in ngAfterViewInit — by that point the parent's template binding\n * has called subscribe() on the OutputEmitterRef, populating its internal\n * `listeners` array (Option A: access via internal field on Angular 20's\n * OutputEmitterRef). If the internal shape is absent, conservatively stays\n * false (opt-out default — no unwanted role=button on inert tiles).\n */\n protected readonly _clickObserved = signal(false)\n\n constructor() {\n // When _thumbUrl changes, revoke the previous owned URL (if any).\n effect(() => {\n // Read the signal so this effect re-runs when the thumbnail changes.\n this._thumbUrl()\n const previous = this._ownedObjectUrl\n this._ownedObjectUrl = this._pendingObjectUrl\n this._pendingObjectUrl = null\n if (previous && previous !== this._ownedObjectUrl) {\n URL.revokeObjectURL(previous)\n }\n })\n // Destroy cleanup: revoke the last owned URL.\n effect((onCleanup) => {\n onCleanup(() => {\n if (this._ownedObjectUrl) {\n URL.revokeObjectURL(this._ownedObjectUrl)\n this._ownedObjectUrl = null\n }\n })\n })\n }\n\n ngAfterViewInit(): void {\n // Detect whether (itemClick) is bound by checking the OutputEmitterRef's\n // internal listeners array. By ngAfterViewInit, the parent's template\n // bindings (including event bindings via subscribe()) have already been\n // applied during the parent's change-detection pass.\n //\n // Option A: access (this.itemClick as any).listeners which is the internal\n // array in Angular 20's OutputEmitterRef (null initially, an array once\n // subscribed). If the internal shape changes, we conservatively keep false.\n const ref = this.itemClick as unknown as { listeners?: unknown[] | null }\n const observed =\n ref.listeners !== undefined ? (ref.listeners?.length ?? 0) > 0 : false\n if (observed) {\n this._clickObserved.set(true)\n this._cdr.markForCheck()\n }\n }\n\n protected _onRemove(event: MouseEvent): void {\n event.stopPropagation()\n this.remove.emit(this.item())\n }\n\n protected _onBodyClick(): void {\n if (!this._clickObserved() || this.disabled()) return\n this.itemClick.emit(this.item())\n }\n\n protected _onBodyKey(event: KeyboardEvent): void {\n if (!this._clickObserved() || this.disabled()) return\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n this.itemClick.emit(this.item())\n }\n }\n}\n\nfunction _formatMeta(item: SeamFileItem): string {\n const parts: string[] = []\n if (item.size !== undefined) parts.push(_formatBytes(item.size))\n if (item.type) parts.push(item.type)\n return parts.join(' · ')\n}\n\nfunction _formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n}\n\nfunction _isImageMime(type: string | undefined): boolean {\n return !!type && type.toLowerCase().startsWith('image/')\n}\n\nconst IMAGE_EXT = /\\.(png|jpe?g|gif|webp|bmp|svg)(\\?|$)/i\n\nfunction _looksLikeImage(item: SeamFileItem): boolean {\n if (_isImageMime(item.type)) return true\n if (item.source.kind === 'url' && IMAGE_EXT.test(item.source.url)) return true\n return false\n}\n","<div\n class=\"seam-file-tile\"\n [class.seam-file-tile--row]=\"variant() === 'row'\"\n [class.seam-file-tile--preview]=\"variant() === 'preview'\"\n [class.seam-file-tile--clickable]=\"_isInteractive()\"\n>\n @if (variant() === 'row') {\n @if (_isInteractive()) {\n <div\n class=\"seam-file-tile__clickable-body\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"_onBodyClick()\"\n (keydown)=\"_onBodyKey($event)\"\n >\n <ng-container *ngTemplateOutlet=\"rowContent\"></ng-container>\n </div>\n } @else {\n <ng-container *ngTemplateOutlet=\"rowContent\"></ng-container>\n }\n\n @if (_showRemoveBtn()) {\n <button\n type=\"button\"\n class=\"seam-file-tile__remove\"\n (click)=\"_onRemove($event)\"\n title=\"Remove file\"\n >\n <seam-icon [icon]=\"_faTimes\"></seam-icon>\n </button>\n }\n } @else {\n @if (_showRemoveBtn()) {\n <button\n type=\"button\"\n class=\"seam-file-tile__remove seam-file-tile__remove--overlay\"\n (click)=\"_onRemove($event)\"\n title=\"Remove file\"\n >\n <seam-icon [icon]=\"_faTimes\"></seam-icon>\n </button>\n }\n @if (_isInteractive()) {\n <div\n class=\"seam-file-tile__clickable-body\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"_onBodyClick()\"\n (keydown)=\"_onBodyKey($event)\"\n >\n <ng-container *ngTemplateOutlet=\"previewContent\"></ng-container>\n </div>\n } @else {\n <ng-container *ngTemplateOutlet=\"previewContent\"></ng-container>\n }\n }\n</div>\n\n<ng-template #rowContent>\n <span\n class=\"seam-file-tile__visual\"\n [class.seam-file-tile__visual--image]=\"!!_thumbUrl()\"\n >\n @if (_thumbUrl(); as url) {\n <img class=\"seam-file-tile__thumb\" [src]=\"url\" [alt]=\"item().name\" />\n } @else {\n <seam-icon [icon]=\"_mimeIcon()\"></seam-icon>\n }\n </span>\n <div class=\"seam-file-tile__body\">\n <div class=\"seam-file-tile__name\" [attr.title]=\"item().name\">\n {{ item().name }}\n </div>\n @if (showMeta() && _metaLine(); as meta) {\n <div class=\"seam-file-tile__meta\">{{ meta }}</div>\n }\n </div>\n</ng-template>\n\n<ng-template #previewContent>\n <span class=\"seam-file-tile__preview-media\">\n @if (_thumbUrl(); as url) {\n <img class=\"seam-file-tile__thumb\" [src]=\"url\" [alt]=\"item().name\" />\n } @else {\n <span class=\"seam-file-tile__visual\">\n <seam-icon [icon]=\"_mimeIcon()\"></seam-icon>\n </span>\n }\n </span>\n @if (showName()) {\n <div class=\"seam-file-tile__preview-name\" [attr.title]=\"item().name\">\n {{ item().name }}\n </div>\n }\n</ng-template>\n","import {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n forwardRef,\n input,\n output,\n signal,\n} from '@angular/core'\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'\n\nimport { TheSeamFileInputComponent } from './file-input.component'\nimport { TheSeamFileTileComponent } from './file-tile.component'\nimport { SeamFileItem, SeamFileRejection } from './file-item.models'\nimport { seamFileItemFromFile } from './file-item.utils'\n\n@Component({\n selector: 'seam-file-field',\n templateUrl: './file-field.component.html',\n styleUrls: ['./file-field.component.scss'],\n imports: [TheSeamFileInputComponent, TheSeamFileTileComponent],\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => TheSeamFileFieldComponent),\n multi: true,\n },\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class TheSeamFileFieldComponent implements ControlValueAccessor {\n readonly multiple = input(false, { transform: booleanAttribute })\n readonly accept = input<string>('')\n readonly maxSize = input<number | null>(null)\n readonly maxFiles = input<number | null>(null)\n readonly disabled = input(false, { transform: booleanAttribute })\n readonly previewMode = input(false, { transform: booleanAttribute })\n readonly showTileName = input(true, { transform: booleanAttribute })\n readonly promptText = input<string>('Choose a file')\n readonly promptSuffix = input<string>('or drag it here')\n readonly replaceText = input<string>('choose a different file')\n readonly hideErrors = input(false, { transform: booleanAttribute })\n\n readonly rejected = output<SeamFileRejection[]>()\n\n protected readonly _items = signal<SeamFileItem[]>([])\n protected readonly _cvaDisabled = signal(false)\n\n protected readonly _effectiveDisabled = computed(\n () => this.disabled() || this._cvaDisabled(),\n )\n\n protected readonly _hasFile = computed(\n () => !this.multiple() && this._items().length > 0,\n )\n\n protected readonly _remainingMaxFiles = computed(() => {\n const max = this.maxFiles()\n if (!this.multiple()) {\n // Single-mode: cap at 1 always. If explicit lower, honor.\n return max !== null ? Math.min(max, 1) : 1\n }\n if (max === null) return null\n return Math.max(0, max - this._items().length)\n })\n\n protected readonly _tileVariant = computed(() =>\n this.previewMode() ? 'preview' : 'row',\n )\n\n private _onChange: (value: SeamFileItem[]) => void = () => undefined\n private _onTouched: () => void = () => undefined\n\n writeValue(value: SeamFileItem[] | null): void {\n this._items.set(value ?? [])\n }\n\n registerOnChange(fn: (value: SeamFileItem[]) => void): void {\n this._onChange = fn\n }\n\n registerOnTouched(fn: () => void): void {\n this._onTouched = fn\n }\n\n setDisabledState(isDisabled: boolean): void {\n this._cvaDisabled.set(isDisabled)\n }\n\n protected _onFilesAdded(files: File[]): void {\n if (files.length === 0) return\n const added = files.map((f) => seamFileItemFromFile(f))\n if (!this.multiple()) {\n this._items.set(added.slice(0, 1))\n } else {\n const remaining = this._remainingMaxFiles()\n const toAdd = remaining !== null ? added.slice(0, remaining) : added\n if (toAdd.length === 0) return\n this._items.update((prev) => [...prev, ...toAdd])\n }\n this._emit()\n }\n\n protected _onRejected(rejections: SeamFileRejection[]): void {\n this.rejected.emit(rejections)\n }\n\n protected _onTileRemove(item: SeamFileItem): void {\n this._items.update((prev) => prev.filter((i) => i !== item))\n this._emit()\n }\n\n private _emit(): void {\n this._onChange(this._items())\n this._onTouched()\n }\n}\n","@if (_hasFile()) {\n <seam-file-tile\n [item]=\"_items()[0]\"\n [variant]=\"_tileVariant()\"\n [showName]=\"showTileName()\"\n [disabled]=\"_effectiveDisabled()\"\n (remove)=\"_onTileRemove($event)\"\n ></seam-file-tile>\n <button\n type=\"button\"\n class=\"seam-file-field__replace\"\n [disabled]=\"_effectiveDisabled()\"\n (click)=\"inputComponentWhenFilled._openPicker()\"\n >\n or <strong>{{ replaceText() }}</strong>\n </button>\n <!-- Hidden mounted input so the replace button has a picker to delegate to. -->\n <seam-file-input\n #inputComponentWhenFilled\n hidden\n [multiple]=\"multiple()\"\n [accept]=\"accept()\"\n [maxSize]=\"maxSize()\"\n [maxFiles]=\"_remainingMaxFiles()\"\n [disabled]=\"_effectiveDisabled()\"\n [hideErrors]=\"true\"\n (filesAdded)=\"_onFilesAdded($event)\"\n (rejected)=\"_onRejected($event)\"\n ></seam-file-input>\n} @else {\n <seam-file-input\n #inputComponent\n [multiple]=\"multiple()\"\n [accept]=\"accept()\"\n [maxSize]=\"maxSize()\"\n [maxFiles]=\"_remainingMaxFiles()\"\n [disabled]=\"_effectiveDisabled()\"\n [hideErrors]=\"hideErrors()\"\n [promptText]=\"promptText()\"\n [promptSuffix]=\"promptSuffix()\"\n (filesAdded)=\"_onFilesAdded($event)\"\n (rejected)=\"_onRejected($event)\"\n ></seam-file-input>\n\n @if (multiple() && _items().length > 0) {\n <div\n class=\"seam-file-field__tiles\"\n [class.seam-file-field__tiles--preview]=\"previewMode()\"\n >\n @for (item of _items(); track item.id ?? item.name) {\n <seam-file-tile\n [item]=\"item\"\n [variant]=\"_tileVariant()\"\n [showName]=\"showTileName()\"\n [disabled]=\"_effectiveDisabled()\"\n (remove)=\"_onTileRemove($event)\"\n ></seam-file-tile>\n }\n </div>\n }\n}\n","import type { EventData } from '@angular/cdk/testing'\n\nexport function dataTransferFromFiles(files: File[]): EventData {\n const dt = new DataTransfer()\n for (const f of files) dt.items.add(f)\n return dt as unknown as EventData\n}\n","import { ComponentHarness } from '@angular/cdk/testing'\nimport { dataTransferFromFiles } from './_harness-utils'\n\n/**\n * Test harness for an element with `[seamFileDropZone]` attached.\n *\n * Usage:\n * ```ts\n * const harness = await loader.getHarness(TheSeamFileDropZoneHarness)\n * await harness.dropFiles([new File(['x'], 'x.txt')])\n * expect(await harness.isOver()).toBe(false)\n * ```\n */\nexport class TheSeamFileDropZoneHarness extends ComponentHarness {\n static hostSelector = '[seamFileDropZone]'\n\n async isOver(): Promise<boolean> {\n const host = await this.host()\n return ((await host.getAttribute('class')) ?? '').includes(\n 'seam-file-drop-zone--over',\n )\n }\n\n async dropFiles(files: File[]): Promise<void> {\n const host = await this.host()\n await host.dispatchEvent('drop', {\n dataTransfer: dataTransferFromFiles(files),\n })\n }\n}\n","import { ComponentHarness } from '@angular/cdk/testing'\nimport { dataTransferFromFiles } from './_harness-utils'\n\n/**\n * Test harness for `<seam-file-input>`.\n */\nexport class TheSeamFileInputHarness extends ComponentHarness {\n static hostSelector = 'seam-file-input'\n\n private _zone = this.locatorFor('.seam-file-input__zone')\n private _prompt = this.locatorFor('.seam-file-input__prompt')\n private _errors = this.locatorForOptional('.seam-file-input__errors')\n private _native = this.locatorFor('input[type=\"file\"]')\n\n /** Trimmed prompt text including the bold portion and suffix. */\n async getPromptText(): Promise<string> {\n return (await (await this._prompt()).text()).trim()\n }\n\n /** Component renders `tabindex=-1` on the zone when disabled. */\n async isDisabled(): Promise<boolean> {\n const zone = await this._zone()\n return (await zone.getAttribute('tabindex')) === '-1'\n }\n\n /** Trimmed error line text, or null when no errors are visible. */\n async getErrorMessage(): Promise<string | null> {\n const el = await this._errors()\n if (!el) return null\n return (await el.text()).trim()\n }\n\n /**\n * Simulates drop of files on the zone. The directive performs validation\n * and emits `filesAdded` / `rejected` via the component.\n */\n async dropFiles(files: File[]): Promise<void> {\n const zone = await this._zone()\n await zone.dispatchEvent('drop', {\n dataTransfer: dataTransferFromFiles(files),\n })\n }\n}\n","import { ComponentHarness } from '@angular/cdk/testing'\nimport { SeamFileTileVariant } from '../file-item.models'\n\n/**\n * Test harness for `<seam-file-tile>`.\n */\nexport class TheSeamFileTileHarness extends ComponentHarness {\n static hostSelector = 'seam-file-tile'\n\n private _root = this.locatorFor('.seam-file-tile')\n private _rowName = this.locatorForOptional('.seam-file-tile__name')\n private _previewName = this.locatorForOptional(\n '.seam-file-tile__preview-name',\n )\n private _remove = this.locatorForOptional('.seam-file-tile__remove')\n private _clickableBody = this.locatorForOptional(\n '.seam-file-tile__clickable-body',\n )\n\n async getName(): Promise<string> {\n const rowName = await this._rowName()\n if (rowName) return (await rowName.text()).trim()\n const previewName = await this._previewName()\n if (previewName) return (await previewName.text()).trim()\n return ''\n }\n\n async getVariant(): Promise<SeamFileTileVariant> {\n const root = await this._root()\n const cls = (await root.getAttribute('class')) ?? ''\n return cls.includes('seam-file-tile--preview') ? 'preview' : 'row'\n }\n\n /** True when a consumer has wired `(itemClick)` AND the tile isn't disabled. */\n async isClickable(): Promise<boolean> {\n return (await this._clickableBody()) !== null\n }\n\n async click(): Promise<void> {\n const clickable = await this._clickableBody()\n if (!clickable) {\n throw new Error(\n 'TheSeamFileTileHarness.click: tile is not clickable (no (itemClick) subscriber or disabled)',\n )\n }\n await clickable.click()\n }\n\n async clickRemove(): Promise<void> {\n const btn = await this._remove()\n if (!btn) {\n throw new Error(\n 'TheSeamFileTileHarness.clickRemove: remove button is not present (non-removable or disabled)',\n )\n }\n await btn.click()\n }\n}\n","import { ComponentHarness } from '@angular/cdk/testing'\n\nimport { TheSeamFileInputHarness } from './file-input.harness'\nimport { TheSeamFileTileHarness } from './file-tile.harness'\n\n/**\n * Test harness for `<seam-file-field>`. Delegates to tile/input harnesses\n * for their respective pieces.\n */\nexport class TheSeamFileFieldHarness extends ComponentHarness {\n static hostSelector = 'seam-file-field'\n\n private _replace = this.locatorForOptional('.seam-file-field__replace')\n private _allInputs = this.locatorForAll(TheSeamFileInputHarness)\n private _tiles = this.locatorForAll(TheSeamFileTileHarness)\n\n /**\n * Returns the visible embedded file-input harness, or null when the field\n * is in the filled single-mode state (visible input replaced by tile).\n * In filled single-mode the hidden input still exists but is not returned.\n */\n async getInputHarness(): Promise<TheSeamFileInputHarness | null> {\n const all = await this._allInputs()\n for (const h of all) {\n const host = await h.host()\n if ((await host.getAttribute('hidden')) === null) {\n return h\n }\n }\n return null\n }\n\n async getTiles(): Promise<TheSeamFileTileHarness[]> {\n return this._tiles()\n }\n\n async getReplaceButtonText(): Promise<string | null> {\n const btn = await this._replace()\n if (!btn) return null\n return (await btn.text()).trim()\n }\n\n async clickReplace(): Promise<void> {\n const btn = await this._replace()\n if (!btn) {\n throw new Error(\n 'TheSeamFileFieldHarness.clickReplace: replace button is not present (field is empty or in multi mode)',\n )\n }\n await btn.click()\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -10,6 +10,8 @@ import { coerceBooleanProperty } from '@angular/cdk/coercion';
10
10
  import { animation, style, animate, keyframes, trigger, transition, useAnimation } from '@angular/animations';
11
11
  import { faCircle, faUserPlus, faUsers, faUserTimes, faUserEdit, faUserCheck, faTrash, faTimes, faSignature, faShare, faReply, faReceipt, faPrint, faLockOpen, faLock, faInfoCircle, faInbox, faFileUpload, faFileSignature, faFilePrescription, faFileMedicalAlt, faFileMedical, faFileInvoiceDollar, faFileInvoice, faFileImport, faFileExport, faFileDownload, faFileCsv, faFileContract, faExternalLinkSquareAlt, faExclamationTriangle, faExclamationCircle, faExclamation, faEdit, faCog, faCloudUploadAlt, faCheck, faChartBar, faChartArea, faChartLine, faBan } from '@fortawesome/free-solid-svg-icons';
12
12
  import { faFileAlt, faFilePowerpoint, faFileArchive, faFileImage, faFileExcel, faFileWord, faFilePdf, faFile, faUserCircle, faUser, faTrashAlt, faTimesCircle, faStickyNote, faSave, faQuestionCircle, faImages, faImage, faFolderOpen, faFolder, faFileVideo, faFileCode, faFileAudio, faEnvelopeOpen, faEnvelope, faComment, faClock, faCheckCircle, faBookmark, faBell, faAddressCard } from '@fortawesome/free-regular-svg-icons';
13
+ import { ContentContainerComponentHarness, HarnessPredicate } from '@angular/cdk/testing';
14
+ import { hasProperty } from '@theseam/ui-common/utils';
13
15
 
14
16
  //
15
17
  // TODO: Ensure all inputs correctly update the state whenever changed, not just
@@ -674,9 +676,78 @@ function getKnownIcon(iconStr) {
674
676
  return knownIcons[iconStr];
675
677
  }
676
678
 
679
+ function toIconLookup(icon) {
680
+ if (isIconLookup(icon)) {
681
+ return { prefix: icon.prefix, iconName: icon.iconName };
682
+ }
683
+ throw new Error(`Invalid icon type: ${typeof icon}`);
684
+ }
685
+ function isIconLookup(icon) {
686
+ return hasProperty(icon, 'prefix') && hasProperty(icon, 'iconName');
687
+ }
688
+ class TheSeamIconComponentHarness extends ContentContainerComponentHarness {
689
+ /** The selector for the host element of a `TheSeamIconComponent` instance. */
690
+ static hostSelector = 'seam-icon';
691
+ _imgElement = this.locatorForOptional('img');
692
+ _svgElement = this.locatorForOptional('fa-icon svg');
693
+ /**
694
+ * Gets a `HarnessPredicate` that can be used to search for a menu item with specific attributes.
695
+ * @param options Options for filtering which menu item instances are considered a match.
696
+ * @return a `HarnessPredicate` configured with the given options.
697
+ */
698
+ static with(options = {}) {
699
+ return new HarnessPredicate(this, options).addOption('icon', options.icon, async (harness, icon) => {
700
+ const _icon = await harness.getIcon();
701
+ if (_icon === undefined) {
702
+ return false;
703
+ }
704
+ if (typeof _icon === 'string' &&
705
+ (typeof icon === 'string' || icon instanceof RegExp)) {
706
+ return HarnessPredicate.stringMatches(_icon, icon);
707
+ }
708
+ else if (isIconLookup(_icon) && isIconLookup(icon)) {
709
+ return (_icon.prefix === icon.prefix && _icon.iconName === icon.iconName);
710
+ }
711
+ return false;
712
+ });
713
+ }
714
+ /** Whether the menu is disabled. */
715
+ async isDisabled() {
716
+ const disabled = (await this.host())
717
+ .getAttribute('class')
718
+ .then((c) => (c === null ? false : c.indexOf('disabled') !== -1));
719
+ return coerceBooleanProperty(await disabled);
720
+ }
721
+ /** Get icon image. */
722
+ async getIcon() {
723
+ const img = await this._imgElement();
724
+ const svg = await this._svgElement();
725
+ if (img === null && svg === null) {
726
+ return undefined;
727
+ }
728
+ if (img !== null) {
729
+ const src = await img.getAttribute('src');
730
+ return typeof src === 'string' ? src : undefined;
731
+ }
732
+ else if (svg !== null) {
733
+ const prefix = await svg.getAttribute('data-prefix');
734
+ const icon = await svg.getAttribute('data-icon');
735
+ if (prefix === null || icon === null) {
736
+ return undefined;
737
+ }
738
+ return { prefix, iconName: icon };
739
+ }
740
+ }
741
+ /** Get icon type. */
742
+ async getIconType() {
743
+ const iconType = await (await this.host()).getAttribute('icon-type');
744
+ return typeof iconType === 'string' ? iconType : undefined;
745
+ }
746
+ }
747
+
677
748
  /**
678
749
  * Generated bundle index. Do not edit.
679
750
  */
680
751
 
681
- export { DEFAULT_FILE_EXTENSION_ICON, IconBtnComponent, IconComponent, IconNotificationComponent, TheSeamIconModule, fileExtensionIcon, getKnownIcon, pulseAnimation };
752
+ export { DEFAULT_FILE_EXTENSION_ICON, IconBtnComponent, IconComponent, IconNotificationComponent, TheSeamIconComponentHarness, TheSeamIconModule, fileExtensionIcon, getKnownIcon, pulseAnimation, toIconLookup };
682
753
  //# sourceMappingURL=theseam-ui-common-icon.mjs.map