@xosue-utils/inputs 0.1.5 → 0.1.8

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.
package/lib/index.d.ts CHANGED
@@ -42,6 +42,7 @@ export { OtpEntryComponent } from './otp-entry/otp-entry.component';
42
42
  export { RichTextEntryComponent } from './rich-text-entry/rich-text-entry.component';
43
43
  export { SignatureEntryComponent } from './signature-entry/signature-entry.component';
44
44
  export { MediaEntryComponent } from './media-entry/media-entry.component';
45
+ export { ListReorder, type ListReorderOptions, type ListReorderEndEvent, } from './list-reorder/list-reorder';
45
46
  export { INPUT_MODAL_SERVICE_COMPONENTS, OnlySelectModalServiceComponent, MultiselectComboboxModalServiceComponent, SearchEntryModalServiceComponent, PhoneEntryModalServiceComponent, DatePickerModalServiceComponent, TimePickerModalServiceComponent, DatetimePickerModalServiceComponent, MonthPickerModalServiceComponent, ColorPickerModalServiceComponent, } from './input-modal-service-components';
46
47
  export { InputModalServicesComponent } from './input-modal-services.component';
47
48
  import { TextEntryComponent } from './text-entry/text-entry.component';
@@ -84,4 +85,4 @@ import { MediaEntryComponent } from './media-entry/media-entry.component';
84
85
  * imports: [...ALL_INPUT_COMPONENTS]
85
86
  * })
86
87
  */
87
- export declare const ALL_INPUT_COMPONENTS: (typeof MediaEntryComponent | typeof SignatureEntryComponent | typeof RichTextEntryComponent | typeof OtpEntryComponent | typeof ColorPickerComponent | typeof PhoneEntryComponent | typeof SwitchEntryComponent | typeof OnlychoiceEntryComponent | typeof MultichoiceEntryComponent | typeof BooleanEntryComponent | typeof MultiselectComboboxComponent | typeof OnlySelectComponent | typeof DatetimePickerComponent | typeof MonthPickerComponent | typeof TimePickerComponent | typeof DatePickerComponent | typeof RatingEntryComponent | typeof SliderEntryComponent | typeof RangeEntryComponent | typeof PriceEntryComponent | typeof CounterEntryComponent | typeof DecimalEntryComponent | typeof IntegerEntryComponent | typeof TagsEntryComponent | typeof SearchEntryComponent | typeof PasswordEntryComponent | typeof UrlEntryComponent | typeof EmailEntryComponent | typeof TextAreaEntryComponent | typeof TextEntryComponent)[];
88
+ export declare const ALL_INPUT_COMPONENTS: (typeof TextEntryComponent | typeof TextAreaEntryComponent | typeof EmailEntryComponent | typeof UrlEntryComponent | typeof PasswordEntryComponent | typeof SearchEntryComponent | typeof TagsEntryComponent | typeof IntegerEntryComponent | typeof DecimalEntryComponent | typeof CounterEntryComponent | typeof PriceEntryComponent | typeof RangeEntryComponent | typeof SliderEntryComponent | typeof RatingEntryComponent | typeof DatePickerComponent | typeof TimePickerComponent | typeof MonthPickerComponent | typeof DatetimePickerComponent | typeof OnlySelectComponent | typeof MultiselectComboboxComponent | typeof BooleanEntryComponent | typeof MultichoiceEntryComponent | typeof OnlychoiceEntryComponent | typeof SwitchEntryComponent | typeof PhoneEntryComponent | typeof ColorPickerComponent | typeof OtpEntryComponent | typeof RichTextEntryComponent | typeof SignatureEntryComponent | typeof MediaEntryComponent)[];
@@ -0,0 +1,86 @@
1
+ import { NgZone } from '@angular/core';
2
+ export interface ListReorderEndEvent {
3
+ oldIndex: number;
4
+ newIndex: number;
5
+ }
6
+ export interface ListReorderOptions {
7
+ /** Items relative to the container. Default: `:scope > *`. */
8
+ itemSelector?: string;
9
+ /** Pointer-down on a matching target does not start a reorder. */
10
+ filter?: string;
11
+ /** Class applied to the item being dragged (placeholder in the list). */
12
+ ghostClass?: string;
13
+ /** FLIP / settle animation in ms. `0` disables. */
14
+ animation?: number;
15
+ disabled?: boolean;
16
+ onEnd?: (event: ListReorderEndEvent) => void;
17
+ /** Keep pointer handling off Angular CD so *ngFor does not reset DOM mid-drag. */
18
+ ngZone?: NgZone;
19
+ }
20
+ /**
21
+ * Pointer-based list/grid reorder. No external libraries.
22
+ * Lifts a floating clone, keeps a dimmed slot, and FLIP-animates siblings.
23
+ */
24
+ export declare class ListReorder {
25
+ private readonly container;
26
+ static attach(container: HTMLElement, options?: ListReorderOptions): ListReorder;
27
+ private readonly itemSelector;
28
+ private readonly itemMatch;
29
+ private readonly filter;
30
+ private readonly ghostClass;
31
+ private readonly animationMs;
32
+ private disabled;
33
+ private readonly onEnd?;
34
+ private readonly ngZone?;
35
+ private pointerId;
36
+ private dragEl;
37
+ private ghostEl;
38
+ private startX;
39
+ private startY;
40
+ private grabOffsetX;
41
+ private grabOffsetY;
42
+ private dragging;
43
+ private settling;
44
+ private oldIndex;
45
+ private lastClientX;
46
+ private lastClientY;
47
+ private scrollFrame;
48
+ private ghostFrame;
49
+ private destroyed;
50
+ private settleGuard;
51
+ private readonly flipGen;
52
+ private readonly onPointerDown;
53
+ private readonly onPointerMove;
54
+ private readonly onPointerUp;
55
+ private readonly suppressClick;
56
+ private constructor();
57
+ isActive(): boolean;
58
+ setDisabled(disabled: boolean): void;
59
+ destroy(): void;
60
+ private listen;
61
+ private emitEnd;
62
+ private findItem;
63
+ private items;
64
+ private handlePointerDown;
65
+ private handlePointerMove;
66
+ private handlePointerUp;
67
+ private beginDrag;
68
+ private spawnGhost;
69
+ private scheduleGhostMove;
70
+ private positionGhost;
71
+ private placeDraggedItem;
72
+ /**
73
+ * Stable insert index: how many siblings have their center before the pointer.
74
+ * Ignores the placeholder, so a swap cannot immediately reverse.
75
+ */
76
+ private indexFromPointer;
77
+ private isHorizontalPair;
78
+ private endReference;
79
+ private animateSiblings;
80
+ private ensureAutoScrollLoop;
81
+ private autoScroll;
82
+ private closestScrollable;
83
+ private finishDrag;
84
+ private cancelDrag;
85
+ private teardownPointer;
86
+ }
@@ -7,8 +7,8 @@ import * as i0 from "@angular/core";
7
7
  * <lucide-icon name="heart" filled></lucide-icon> // relleno + trazo
8
8
  *
9
9
  * SASS — variables CSS (heredan del padre):
10
- * --lucide-stroke: var(--primary)
11
- * --lucide-fill: var(--accent)
10
+ * --lucide-stroke: var(--color-brand)
11
+ * --lucide-fill: var(--color-accent)
12
12
  * --lucide-stroke-width: 2
13
13
  */
14
14
  export declare class LucideIconComponent {
@@ -1,9 +1,10 @@
1
- import { ElementRef, AfterViewInit } from '@angular/core';
1
+ import { ElementRef, AfterViewInit, AfterViewChecked, OnDestroy } from '@angular/core';
2
2
  import { ControlValueAccessor } from '@angular/forms';
3
3
  import * as i0 from "@angular/core";
4
4
  interface FileInfo {
5
5
  name: string;
6
- size: number;
6
+ /** Bytes. `null` = aún no medido / desconocido. */
7
+ size: number | null;
7
8
  progress: number;
8
9
  status: 'loading' | 'success' | 'error';
9
10
  type?: string;
@@ -17,10 +18,11 @@ interface FileInfo {
17
18
  uploadedBytes?: number;
18
19
  }
19
20
  type MediaMode = 'file' | 'image' | 'card';
20
- export declare class MediaEntryComponent implements ControlValueAccessor, AfterViewInit {
21
+ export declare class MediaEntryComponent implements ControlValueAccessor, AfterViewInit, AfterViewChecked, OnDestroy {
21
22
  private cdr;
22
23
  private elementRef;
23
24
  private sanitizer;
25
+ private zone;
24
26
  private readonly inputsConfig;
25
27
  private mediaPreview;
26
28
  /** Visor de previsualización global (consumido desde la plantilla vía `openGeneralMediaPreview`). */
@@ -42,6 +44,8 @@ export declare class MediaEntryComponent implements ControlValueAccessor, AfterV
42
44
  /** Tamaño de cada chunk en MB. Por defecto 1.5 MB para no superar upload_max_filesize=2M en muchos servidores. */
43
45
  chunkSizeMB: number;
44
46
  sortable: boolean;
47
+ /** Tamaños conocidos por URL o nombre de archivo (bytes). Se usa si el HEAD no aplica. */
48
+ set fileSizes(value: Record<string, number> | null);
45
49
  primaryTag: boolean;
46
50
  previewEndpoint?: string;
47
51
  /** Ancho máximo en px para imágenes (opcional). Si no se envía, se conserva el tamaño original. */
@@ -51,9 +55,10 @@ export declare class MediaEntryComponent implements ControlValueAccessor, AfterV
51
55
  get hostDisabledClass(): boolean;
52
56
  set disabled(value: boolean);
53
57
  uploadFormRef?: ElementRef<HTMLFormElement>;
54
- sortableContainer?: ElementRef;
55
- private sortableInstance?;
56
- private sortableInitialized;
58
+ sortableContainer?: ElementRef<HTMLElement>;
59
+ private listReorder?;
60
+ private listReorderHost?;
61
+ private knownSizes;
57
62
  pending: FileInfo[];
58
63
  uploaded: FileInfo[];
59
64
  failed: FileInfo[];
@@ -74,11 +79,17 @@ export declare class MediaEntryComponent implements ControlValueAccessor, AfterV
74
79
  get maxSizeText(): string;
75
80
  ngAfterViewInit(): void;
76
81
  ngAfterViewChecked(): void;
82
+ trackUploaded(_index: number, item: FileInfo): string;
83
+ ngOnDestroy(): void;
84
+ private teardownListReorder;
77
85
  private onChange;
78
86
  private onTouched;
79
87
  writeValue(value: string[] | string | null): void;
88
+ private applyKnownSizes;
89
+ private knownFileSize;
80
90
  /**
81
- * Obtiene el tamaño del archivo con HEAD. En modo imagen con hash usa CDN (Cloudflare).
91
+ * Obtiene el tamaño del archivo (HEAD, Range o blob/data).
92
+ * En modo imagen con hash usa CDN (Cloudflare).
82
93
  */
83
94
  private fetchFileSize;
84
95
  /**
@@ -129,15 +140,15 @@ export declare class MediaEntryComponent implements ControlValueAccessor, AfterV
129
140
  */
130
141
  openGeneralMediaPreview(fileInfo: FileInfo): Promise<void>;
131
142
  /**
132
- * Determina si el archivo se puede previsualizar en el navegador
133
- * El backend maneja todo, así que solo verificamos si tenemos tipo o nombre
143
+ * Imagen, video, audio, PDF y texto plano: el navegador los muestra.
144
+ * Office, zips y similares no: ahí va descarga.
134
145
  */
146
+ canPreviewInBrowser(fileInfo: Pick<FileInfo, 'type' | 'name'>): boolean;
135
147
  canPreview(fileType?: string | null, fileName?: string | null): boolean;
148
+ downloadUploaded(fileInfo: FileInfo): Promise<void>;
149
+ private resolvePlayableUrl;
136
150
  private viewerModeFor;
137
- /**
138
- * Determina si el archivo debe mostrarse en iframe (PDFs y documentos)
139
- * El backend sirve estos archivos directamente, así que usamos iframe para PDFs y documentos Office
140
- */
151
+ /** Solo tipos que el navegador pinta nativo (PDF y texto). Office no. */
141
152
  shouldUseIframe(fileType?: string | null, fileName?: string | null): boolean;
142
153
  private moveToUploaded;
143
154
  private moveToFailed;
@@ -156,8 +167,9 @@ export declare class MediaEntryComponent implements ControlValueAccessor, AfterV
156
167
  statusTimeout?: any;
157
168
  showStatusMessage(msg: string, durationMs?: number): void;
158
169
  private reorderUploadedFromDOM;
170
+ getFileIconName(type: string | undefined): string;
159
171
  getFileIcon(type: string | undefined): string;
160
172
  static ɵfac: i0.ɵɵFactoryDeclaration<MediaEntryComponent, never>;
161
- static ɵcmp: i0.ɵɵComponentDeclaration<MediaEntryComponent, "media-entry", never, { "label": { "alias": "label"; "required": false; }; "opcional": { "alias": "opcional"; "required": false; }; "description": { "alias": "description"; "required": false; }; "placeholder": { "alias": "placeholder"; "required": false; }; "mode": { "alias": "mode"; "required": false; }; "display": { "alias": "display"; "required": false; }; "multiple": { "alias": "multiple"; "required": false; }; "maxItems": { "alias": "maxItems"; "required": false; }; "maxSize": { "alias": "maxSize"; "required": false; }; "types": { "alias": "types"; "required": false; }; "extensions": { "alias": "extensions"; "required": false; }; "endpointUpload": { "alias": "endpointUpload"; "required": false; }; "chunkSizeMB": { "alias": "chunkSizeMB"; "required": false; }; "sortable": { "alias": "sortable"; "required": false; }; "primaryTag": { "alias": "primaryTag"; "required": false; }; "previewEndpoint": { "alias": "previewEndpoint"; "required": false; }; "imageMaxWidth": { "alias": "imageMaxWidth"; "required": false; }; "imageMaxHeight": { "alias": "imageMaxHeight"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; }, {}, never, never, true, never>;
173
+ static ɵcmp: i0.ɵɵComponentDeclaration<MediaEntryComponent, "media-entry", never, { "label": { "alias": "label"; "required": false; }; "opcional": { "alias": "opcional"; "required": false; }; "description": { "alias": "description"; "required": false; }; "placeholder": { "alias": "placeholder"; "required": false; }; "mode": { "alias": "mode"; "required": false; }; "display": { "alias": "display"; "required": false; }; "multiple": { "alias": "multiple"; "required": false; }; "maxItems": { "alias": "maxItems"; "required": false; }; "maxSize": { "alias": "maxSize"; "required": false; }; "types": { "alias": "types"; "required": false; }; "extensions": { "alias": "extensions"; "required": false; }; "endpointUpload": { "alias": "endpointUpload"; "required": false; }; "chunkSizeMB": { "alias": "chunkSizeMB"; "required": false; }; "sortable": { "alias": "sortable"; "required": false; }; "fileSizes": { "alias": "fileSizes"; "required": false; }; "primaryTag": { "alias": "primaryTag"; "required": false; }; "previewEndpoint": { "alias": "previewEndpoint"; "required": false; }; "imageMaxWidth": { "alias": "imageMaxWidth"; "required": false; }; "imageMaxHeight": { "alias": "imageMaxHeight"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; }, {}, never, never, true, never>;
162
174
  }
163
175
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xosue-utils/inputs",
3
- "version": "0.1.5",
3
+ "version": "0.1.8",
4
4
  "description": "Angular standalone form inputs (text, select, date, media, rich-text, ...) shared across apps.",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,
@@ -32,8 +32,7 @@
32
32
  "@lucide/angular": ">=0.500.0 <2.0.0",
33
33
  "lexical": ">=0.42.0 <1.0.0",
34
34
  "luxon": "^3.0.0",
35
- "rxjs": ">=7.8.0 <8.0.0",
36
- "sortablejs": "^1.15.0"
35
+ "rxjs": ">=7.8.0 <8.0.0"
37
36
  },
38
37
  "dependencies": {
39
38
  "tslib": "^2.6.0"
@@ -71,9 +70,6 @@
71
70
  },
72
71
  "luxon": {
73
72
  "optional": true
74
- },
75
- "sortablejs": {
76
- "optional": true
77
73
  }
78
74
  },
79
75
  "module": "fesm2022/xosue-utils-inputs.mjs",
@@ -6,6 +6,7 @@ export declare class ContextMenuServiceComponent implements OnInit, OnDestroy {
6
6
  private platformId;
7
7
  private static readonly VIEWPORT_EDGE_INSET;
8
8
  private static readonly ANCHOR_OFFSET;
9
+ private static readonly COMPACT_MAX_WIDTH;
9
10
  private readonly cdr;
10
11
  panelRef?: ElementRef<HTMLElement>;
11
12
  active: ContextMenuRequest | null;
@@ -14,6 +15,7 @@ export declare class ContextMenuServiceComponent implements OnInit, OnDestroy {
14
15
  y: number;
15
16
  };
16
17
  panelVisible: boolean;
18
+ compact: boolean;
17
19
  private anchor;
18
20
  /** Timestamp hasta el cual ignoramos cierres (evita que el gesto de apertura cierre el menú). */
19
21
  private ignoreOutsideUntil;
@@ -29,8 +31,11 @@ export declare class ContextMenuServiceComponent implements OnInit, OnDestroy {
29
31
  onEscape(event: KeyboardEvent): void;
30
32
  selectOption(option: ContextMenuOption): void;
31
33
  private handleOutsideEvent;
34
+ onBackdropClick(event: Event): void;
35
+ private swallowFollowingClick;
32
36
  private dismissCurrent;
33
37
  private clearMenu;
38
+ private isCompactViewport;
34
39
  private applyClampedPosition;
35
40
  static ɵfac: i0.ɵɵFactoryDeclaration<ContextMenuServiceComponent, never>;
36
41
  static ɵcmp: i0.ɵɵComponentDeclaration<ContextMenuServiceComponent, "context-menu-service", never, {}, {}, never, never, true, never>;
@@ -1,7 +1,7 @@
1
1
  import { PipeTransform } from '@angular/core';
2
2
  import * as i0 from "@angular/core";
3
3
  export declare class FileSizePipe implements PipeTransform {
4
- transform(bytes: number | null | undefined, decimals?: number): string;
4
+ transform(bytes: number | string | null | undefined, decimals?: number): string;
5
5
  static ɵfac: i0.ɵɵFactoryDeclaration<FileSizePipe, never>;
6
6
  static ɵpipe: i0.ɵɵPipeDeclaration<FileSizePipe, "fileSize", true>;
7
7
  }
Binary file