@honuware/ui 0.1.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
+ {"version":3,"file":"honuware-ui-foundation.mjs","sources":["../../../projects/honuware-ui/foundation/src/toast/toast.service.ts","../../../projects/honuware-ui/foundation/src/confirm-dialog/confirm-dialog.component.ts","../../../projects/honuware-ui/foundation/src/confirm-dialog/confirm-dialog.component.html","../../../projects/honuware-ui/foundation/src/animations/defaults.ts","../../../projects/honuware-ui/foundation/src/animations/expand-collapse.ts","../../../projects/honuware-ui/foundation/src/animations/fade.ts","../../../projects/honuware-ui/foundation/src/animations/shake.ts","../../../projects/honuware-ui/foundation/src/animations/slide.ts","../../../projects/honuware-ui/foundation/src/animations/zoom.ts","../../../projects/honuware-ui/foundation/src/animations/public-api.ts","../../../projects/honuware-ui/foundation/src/sanitize-return-url.ts","../../../projects/honuware-ui/foundation/src/date-formatting.ts","../../../projects/honuware-ui/foundation/src/public-api.ts","../../../projects/honuware-ui/foundation/src/honuware-ui-foundation.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\nimport { MatSnackBar, MatSnackBarConfig } from '@angular/material/snack-bar';\n\nexport type ToastType = 'success' | 'error' | 'warning' | 'info';\n\n@Injectable({\n providedIn: 'root',\n})\nexport class ToastService {\n private readonly defaultDuration = 5000;\n\n constructor(private snackBar: MatSnackBar) {}\n\n /**\n * Show a success toast notification\n */\n success(message: string, duration?: number): void {\n this.show(message, 'success', duration);\n }\n\n /**\n * Show an error toast notification\n */\n error(message: string, duration?: number): void {\n this.show(message, 'error', duration);\n }\n\n /**\n * Show a warning toast notification\n */\n warning(message: string, duration?: number): void {\n this.show(message, 'warning', duration);\n }\n\n /**\n * Show an info toast notification\n */\n info(message: string, duration?: number): void {\n this.show(message, 'info', duration);\n }\n\n /**\n * Show a toast notification with the specified type\n */\n show(message: string, type: ToastType = 'info', duration?: number): void {\n const config: MatSnackBarConfig = {\n duration: duration ?? this.defaultDuration,\n horizontalPosition: 'center',\n verticalPosition: 'bottom',\n panelClass: [`toast-${type}`],\n };\n\n this.snackBar.open(message, 'Dismiss', config);\n }\n\n /**\n * Dismiss any currently visible toast\n */\n dismiss(): void {\n this.snackBar.dismiss();\n }\n}\n","import { Component, inject } from '@angular/core';\nimport { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';\nimport { MatButtonModule } from '@angular/material/button';\n\nexport interface ConfirmDialogData {\n title: string;\n description?: string;\n buttonText?: string;\n}\n\n@Component({\n selector: 'hw-confirm-dialog',\n imports: [MatDialogModule, MatButtonModule],\n templateUrl: './confirm-dialog.component.html',\n})\nexport class ConfirmDialogComponent {\n readonly dialogRef: MatDialogRef<ConfirmDialogComponent, boolean> = inject(\n MatDialogRef<ConfirmDialogComponent, boolean>\n );\n readonly data = inject<ConfirmDialogData>(MAT_DIALOG_DATA);\n\n public clickConfirm() {\n this.dialogRef.close(true);\n }\n}\n","<h2 mat-dialog-title>{{data.title}}</h2>\n<mat-dialog-content>\n {{data.description}}\n</mat-dialog-content>\n<mat-dialog-actions>\n <button type=\"button\" mat-raised-button color=\"primary\" (click)=\"clickConfirm()\">\n {{data.buttonText ?? 'Confirm'}}\n </button>\n <button type=\"button\" mat-button mat-dialog-close>Cancel</button>\n</mat-dialog-actions>","export class FuseAnimationCurves\n{\n static standard = 'cubic-bezier(0.4, 0.0, 0.2, 1)';\n static deceleration = 'cubic-bezier(0.0, 0.0, 0.2, 1)';\n static acceleration = 'cubic-bezier(0.4, 0.0, 1, 1)';\n static sharp = 'cubic-bezier(0.4, 0.0, 0.6, 1)';\n}\n\nexport class FuseAnimationDurations\n{\n static complex = '375ms';\n static entering = '225ms';\n static exiting = '195ms';\n}\n","import { animate, state, style, transition, trigger } from '@angular/animations';\nimport { FuseAnimationCurves, FuseAnimationDurations } from './defaults';\n\n// -----------------------------------------------------------------------------------------------------\n// @ Expand / collapse\n// -----------------------------------------------------------------------------------------------------\nconst expandCollapse = trigger('expandCollapse',\n [\n state('void, collapsed',\n style({\n height: '0',\n opacity: '0',\n }),\n ),\n\n state('*, expanded',\n style('*'),\n ),\n\n // Prevent the transition if the state is false\n transition('void <=> false, collapsed <=> false, expanded <=> false', []),\n\n // Transition\n transition('void <=> *, collapsed <=> expanded',\n animate('{{timings}}'),\n {\n params: {\n timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`,\n },\n },\n ),\n ],\n);\n\nexport { expandCollapse };\n","import { animate, state, style, transition, trigger } from '@angular/animations';\nimport { FuseAnimationCurves, FuseAnimationDurations } from './defaults';\n\n// -----------------------------------------------------------------------------------------------------\n// @ Fade in\n// -----------------------------------------------------------------------------------------------------\nconst fadeIn = trigger('fadeIn',\n [\n state('void',\n style({\n opacity: 0,\n }),\n ),\n\n state('*',\n style({\n opacity: 1,\n }),\n ),\n\n // Prevent the transition if the state is false\n transition('void => false', []),\n\n // Transition\n transition('void => *', animate('{{timings}}'),\n {\n params: {\n timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`,\n },\n },\n ),\n ],\n);\n\n// -----------------------------------------------------------------------------------------------------\n// @ Fade in top\n// -----------------------------------------------------------------------------------------------------\nconst fadeInTop = trigger('fadeInTop',\n [\n state('void',\n style({\n opacity : 0,\n transform: 'translate3d(0, -100%, 0)',\n }),\n ),\n\n state('*',\n style({\n opacity : 1,\n transform: 'translate3d(0, 0, 0)',\n }),\n ),\n\n // Prevent the transition if the state is false\n transition('void => false', []),\n\n // Transition\n transition('void => *', animate('{{timings}}'),\n {\n params: {\n timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`,\n },\n },\n ),\n ],\n);\n\n// -----------------------------------------------------------------------------------------------------\n// @ Fade in bottom\n// -----------------------------------------------------------------------------------------------------\nconst fadeInBottom = trigger('fadeInBottom',\n [\n state('void',\n style({\n opacity : 0,\n transform: 'translate3d(0, 100%, 0)',\n }),\n ),\n\n state('*',\n style({\n opacity : 1,\n transform: 'translate3d(0, 0, 0)',\n }),\n ),\n\n // Prevent the transition if the state is false\n transition('void => false', []),\n\n // Transition\n transition('void => *', animate('{{timings}}'),\n {\n params: {\n timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`,\n },\n },\n ),\n ],\n);\n\n// -----------------------------------------------------------------------------------------------------\n// @ Fade in left\n// -----------------------------------------------------------------------------------------------------\nconst fadeInLeft = trigger('fadeInLeft',\n [\n state('void',\n style({\n opacity : 0,\n transform: 'translate3d(-100%, 0, 0)',\n }),\n ),\n\n state('*',\n style({\n opacity : 1,\n transform: 'translate3d(0, 0, 0)',\n }),\n ),\n\n // Prevent the transition if the state is false\n transition('void => false', []),\n\n // Transition\n transition('void => *', animate('{{timings}}'),\n {\n params: {\n timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`,\n },\n },\n ),\n ],\n);\n\n// -----------------------------------------------------------------------------------------------------\n// @ Fade in right\n// -----------------------------------------------------------------------------------------------------\nconst fadeInRight = trigger('fadeInRight',\n [\n state('void',\n style({\n opacity : 0,\n transform: 'translate3d(100%, 0, 0)',\n }),\n ),\n\n state('*',\n style({\n opacity : 1,\n transform: 'translate3d(0, 0, 0)',\n }),\n ),\n\n // Prevent the transition if the state is false\n transition('void => false', []),\n\n // Transition\n transition('void => *', animate('{{timings}}'),\n {\n params: {\n timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`,\n },\n },\n ),\n ],\n);\n\n// -----------------------------------------------------------------------------------------------------\n// @ Fade out\n// -----------------------------------------------------------------------------------------------------\nconst fadeOut = trigger('fadeOut',\n [\n state('*',\n style({\n opacity: 1,\n }),\n ),\n\n state('void',\n style({\n opacity: 0,\n }),\n ),\n\n // Prevent the transition if the state is false\n transition('false => void', []),\n\n // Transition\n transition('* => void', animate('{{timings}}'),\n {\n params: {\n timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`,\n },\n },\n ),\n ],\n);\n\n// -----------------------------------------------------------------------------------------------------\n// @ Fade out top\n// -----------------------------------------------------------------------------------------------------\nconst fadeOutTop = trigger('fadeOutTop',\n [\n state('*',\n style({\n opacity : 1,\n transform: 'translate3d(0, 0, 0)',\n }),\n ),\n\n state('void',\n style({\n opacity : 0,\n transform: 'translate3d(0, -100%, 0)',\n }),\n ),\n\n // Prevent the transition if the state is false\n transition('false => void', []),\n\n // Transition\n transition('* => void', animate('{{timings}}'),\n {\n params: {\n timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`,\n },\n },\n ),\n ],\n);\n\n// -----------------------------------------------------------------------------------------------------\n// @ Fade out bottom\n// -----------------------------------------------------------------------------------------------------\nconst fadeOutBottom = trigger('fadeOutBottom',\n [\n state('*',\n style({\n opacity : 1,\n transform: 'translate3d(0, 0, 0)',\n }),\n ),\n\n state('void',\n style({\n opacity : 0,\n transform: 'translate3d(0, 100%, 0)',\n }),\n ),\n\n // Prevent the transition if the state is false\n transition('false => void', []),\n\n // Transition\n transition('* => void', animate('{{timings}}'),\n {\n params: {\n timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`,\n },\n },\n ),\n ],\n);\n\n// -----------------------------------------------------------------------------------------------------\n// @ Fade out left\n// -----------------------------------------------------------------------------------------------------\nconst fadeOutLeft = trigger('fadeOutLeft',\n [\n state('*',\n style({\n opacity : 1,\n transform: 'translate3d(0, 0, 0)',\n }),\n ),\n\n state('void',\n style({\n opacity : 0,\n transform: 'translate3d(-100%, 0, 0)',\n }),\n ),\n\n // Prevent the transition if the state is false\n transition('false => void', []),\n\n // Transition\n transition('* => void', animate('{{timings}}'),\n {\n params: {\n timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`,\n },\n },\n ),\n ],\n);\n\n// -----------------------------------------------------------------------------------------------------\n// @ Fade out right\n// -----------------------------------------------------------------------------------------------------\nconst fadeOutRight = trigger('fadeOutRight',\n [\n state('*',\n style({\n opacity : 1,\n transform: 'translate3d(0, 0, 0)',\n }),\n ),\n\n state('void',\n style({\n opacity : 0,\n transform: 'translate3d(100%, 0, 0)',\n }),\n ),\n\n // Prevent the transition if the state is false\n transition('false => void', []),\n\n // Transition\n transition('* => void', animate('{{timings}}'),\n {\n params: {\n timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`,\n },\n },\n ),\n ],\n);\n\nexport { fadeIn, fadeInTop, fadeInBottom, fadeInLeft, fadeInRight, fadeOut, fadeOutTop, fadeOutBottom, fadeOutLeft, fadeOutRight };\n","import { animate, keyframes, style, transition, trigger } from '@angular/animations';\n\n// -----------------------------------------------------------------------------------------------------\n// @ Shake\n// -----------------------------------------------------------------------------------------------------\nconst shake = trigger('shake',\n [\n\n // Prevent the transition if the state is false\n transition('void => false', []),\n\n // Transition\n transition('void => *, * => true',\n [\n animate('{{timings}}',\n keyframes([\n style({\n transform: 'translate3d(0, 0, 0)',\n offset : 0,\n }),\n style({\n transform: 'translate3d(-10px, 0, 0)',\n offset : 0.1,\n }),\n style({\n transform: 'translate3d(10px, 0, 0)',\n offset : 0.2,\n }),\n style({\n transform: 'translate3d(-10px, 0, 0)',\n offset : 0.3,\n }),\n style({\n transform: 'translate3d(10px, 0, 0)',\n offset : 0.4,\n }),\n style({\n transform: 'translate3d(-10px, 0, 0)',\n offset : 0.5,\n }),\n style({\n transform: 'translate3d(10px, 0, 0)',\n offset : 0.6,\n }),\n style({\n transform: 'translate3d(-10px, 0, 0)',\n offset : 0.7,\n }),\n style({\n transform: 'translate3d(10px, 0, 0)',\n offset : 0.8,\n }),\n style({\n transform: 'translate3d(-10px, 0, 0)',\n offset : 0.9,\n }),\n style({\n transform: 'translate3d(0, 0, 0)',\n offset : 1,\n }),\n ]),\n ),\n ],\n {\n params: {\n timings: '0.8s cubic-bezier(0.455, 0.03, 0.515, 0.955)',\n },\n },\n ),\n ],\n);\n\nexport { shake };\n","import { animate, state, style, transition, trigger } from '@angular/animations';\nimport { FuseAnimationCurves, FuseAnimationDurations } from './defaults';\n\n// -----------------------------------------------------------------------------------------------------\n// @ Slide in top\n// -----------------------------------------------------------------------------------------------------\nconst slideInTop = trigger('slideInTop',\n [\n state('void',\n style({\n transform: 'translate3d(0, -100%, 0)',\n }),\n ),\n\n state('*',\n style({\n transform: 'translate3d(0, 0, 0)',\n }),\n ),\n\n // Prevent the transition if the state is false\n transition('void => false', []),\n\n // Transition\n transition('void => *', animate('{{timings}}'),\n {\n params: {\n timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`,\n },\n },\n ),\n ],\n);\n\n// -----------------------------------------------------------------------------------------------------\n// @ Slide in bottom\n// -----------------------------------------------------------------------------------------------------\nconst slideInBottom = trigger('slideInBottom',\n [\n state('void',\n style({\n transform: 'translate3d(0, 100%, 0)',\n }),\n ),\n\n state('*',\n style({\n transform: 'translate3d(0, 0, 0)',\n }),\n ),\n\n // Prevent the transition if the state is false\n transition('void => false', []),\n\n // Transition\n transition('void => *', animate('{{timings}}'),\n {\n params: {\n timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`,\n },\n },\n ),\n ],\n);\n\n// -----------------------------------------------------------------------------------------------------\n// @ Slide in left\n// -----------------------------------------------------------------------------------------------------\nconst slideInLeft = trigger('slideInLeft',\n [\n state('void',\n style({\n transform: 'translate3d(-100%, 0, 0)',\n }),\n ),\n\n state('*',\n style({\n transform: 'translate3d(0, 0, 0)',\n }),\n ),\n\n // Prevent the transition if the state is false\n transition('void => false', []),\n\n // Transition\n transition('void => *', animate('{{timings}}'),\n {\n params: {\n timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`,\n },\n },\n ),\n ],\n);\n\n// -----------------------------------------------------------------------------------------------------\n// @ Slide in right\n// -----------------------------------------------------------------------------------------------------\nconst slideInRight = trigger('slideInRight',\n [\n state('void',\n style({\n transform: 'translate3d(100%, 0, 0)',\n }),\n ),\n\n state('*',\n style({\n transform: 'translate3d(0, 0, 0)',\n }),\n ),\n\n // Prevent the transition if the state is false\n transition('void => false', []),\n\n // Transition\n transition('void => *', animate('{{timings}}'),\n {\n params: {\n timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`,\n },\n },\n ),\n ],\n);\n\n// -----------------------------------------------------------------------------------------------------\n// @ Slide out top\n// -----------------------------------------------------------------------------------------------------\nconst slideOutTop = trigger('slideOutTop',\n [\n state('*',\n style({\n transform: 'translate3d(0, 0, 0)',\n }),\n ),\n\n state('void',\n style({\n transform: 'translate3d(0, -100%, 0)',\n }),\n ),\n\n // Prevent the transition if the state is false\n transition('false => void', []),\n\n // Transition\n transition('* => void', animate('{{timings}}'),\n {\n params: {\n timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`,\n },\n },\n ),\n ],\n);\n\n// -----------------------------------------------------------------------------------------------------\n// @ Slide out bottom\n// -----------------------------------------------------------------------------------------------------\nconst slideOutBottom = trigger('slideOutBottom',\n [\n state('*',\n style({\n transform: 'translate3d(0, 0, 0)',\n }),\n ),\n\n state('void',\n style({\n transform: 'translate3d(0, 100%, 0)',\n }),\n ),\n\n // Prevent the transition if the state is false\n transition('false => void', []),\n\n // Transition\n transition('* => void', animate('{{timings}}'),\n {\n params: {\n timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`,\n },\n },\n ),\n ],\n);\n\n// -----------------------------------------------------------------------------------------------------\n// @ Slide out left\n// -----------------------------------------------------------------------------------------------------\nconst slideOutLeft = trigger('slideOutLeft',\n [\n state('*',\n style({\n transform: 'translate3d(0, 0, 0)',\n }),\n ),\n\n state('void',\n style({\n transform: 'translate3d(-100%, 0, 0)',\n }),\n ),\n\n // Prevent the transition if the state is false\n transition('false => void', []),\n\n // Transition\n transition('* => void', animate('{{timings}}'),\n {\n params: {\n timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`,\n },\n },\n ),\n ],\n);\n\n// -----------------------------------------------------------------------------------------------------\n// @ Slide out right\n// -----------------------------------------------------------------------------------------------------\nconst slideOutRight = trigger('slideOutRight',\n [\n state('*',\n style({\n transform: 'translate3d(0, 0, 0)',\n }),\n ),\n\n state('void',\n style({\n transform: 'translate3d(100%, 0, 0)',\n }),\n ),\n\n // Prevent the transition if the state is false\n transition('false => void', []),\n\n // Transition\n transition('* => void', animate('{{timings}}'),\n {\n params: {\n timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`,\n },\n },\n ),\n ],\n);\n\nexport { slideInTop, slideInBottom, slideInLeft, slideInRight, slideOutTop, slideOutBottom, slideOutLeft, slideOutRight };\n","import { animate, state, style, transition, trigger } from '@angular/animations';\nimport { FuseAnimationCurves, FuseAnimationDurations } from './defaults';\n\n// -----------------------------------------------------------------------------------------------------\n// @ Zoom in\n// -----------------------------------------------------------------------------------------------------\nconst zoomIn = trigger('zoomIn',\n [\n\n state('void',\n style({\n opacity : 0,\n transform: 'scale(0.5)',\n }),\n ),\n\n state('*',\n style({\n opacity : 1,\n transform: 'scale(1)',\n }),\n ),\n\n // Prevent the transition if the state is false\n transition('void => false', []),\n\n // Transition\n transition('void => *', animate('{{timings}}'),\n {\n params: {\n timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`,\n },\n },\n ),\n ],\n);\n\n// -----------------------------------------------------------------------------------------------------\n// @ Zoom out\n// -----------------------------------------------------------------------------------------------------\nconst zoomOut = trigger('zoomOut',\n [\n\n state('*',\n style({\n opacity : 1,\n transform: 'scale(1)',\n }),\n ),\n\n state('void',\n style({\n opacity : 0,\n transform: 'scale(0.5)',\n }),\n ),\n\n // Prevent the transition if the state is false\n transition('false => void', []),\n\n // Transition\n transition('* => void', animate('{{timings}}'),\n {\n params: {\n timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`,\n },\n },\n ),\n ],\n);\n\nexport { zoomIn, zoomOut };\n\n","import { expandCollapse } from './expand-collapse';\nimport { fadeIn, fadeInBottom, fadeInLeft, fadeInRight, fadeInTop, fadeOut, fadeOutBottom, fadeOutLeft, fadeOutRight, fadeOutTop } from './fade';\nimport { shake } from './shake';\nimport { slideInBottom, slideInLeft, slideInRight, slideInTop, slideOutBottom, slideOutLeft, slideOutRight, slideOutTop } from './slide';\nimport { zoomIn, zoomOut } from './zoom';\n\nexport const fuseAnimations = [\n expandCollapse,\n fadeIn, fadeInTop, fadeInBottom, fadeInLeft, fadeInRight,\n fadeOut, fadeOutTop, fadeOutBottom, fadeOutLeft, fadeOutRight,\n shake,\n slideInTop, slideInBottom, slideInLeft, slideInRight,\n slideOutTop, slideOutBottom, slideOutLeft, slideOutRight,\n zoomIn, zoomOut,\n];\n","// Open-redirect defense for a post-login `returnUrl` query parameter. An\n// unvalidated returnUrl lets an attacker craft a phishing flow like\n// `/login?returnUrl=https://evil.example/` — the user logs in legitimately and\n// then gets bounced to an attacker-controlled origin.\n//\n// Restricts returnUrl to same-origin paths under a known feature area. The\n// allow-list is a REQUIRED parameter (foundation sits below auth, so it can't\n// default to the auth-routes allow-list) — callers pass their own set of\n// permitted path prefixes. Returns `/` for any input that's missing,\n// non-string, or fails the same-origin + allow-list checks; the default-deny\n// stance degrades safely to a home-page redirect.\nexport function sanitizeReturnUrl(\n raw: string | null | undefined,\n allowlist: ReadonlyArray<string>,\n): string {\n if (typeof raw !== 'string' || raw.length === 0) return '/';\n // Reject anything that escapes same-origin:\n // - Protocol-relative URLs (`//evil.com/...`)\n // - Backslash-prefixed variants (`/\\evil.com` — some browsers\n // normalize backslashes to forward slashes during navigation)\n // - Anything that doesn't start with a single `/`\n if (!raw.startsWith('/')) return '/';\n if (raw.startsWith('//')) return '/';\n if (raw.startsWith('/\\\\')) return '/';\n // Allow the exact root path.\n if (raw === '/') return '/';\n // Otherwise require a known prefix followed by either end-of-string\n // or another `/` (so `/admin` matches `/admin` and `/admin/users`,\n // but NOT a hypothetical `/administer-evil` route).\n for (const prefix of allowlist) {\n if (raw === prefix || raw.startsWith(prefix + '/')) {\n return raw;\n }\n }\n return '/';\n}\n","export function isMicrosecondTimestamp(value: string): boolean {\n return /^\\d{11,}$/.test(value);\n}\n\nexport function microsToDate(value: string): Date {\n return new Date(Number(value) / 1000);\n}\n\nexport function dateToMicros(date: Date): string {\n return String(date.getTime() * 1000);\n}\n\nconst ONE_DAY_US = 86400000000;\n\n/**\n * Format a microsecond timestamp as a UTC calendar date.\n * Use for dates that represent calendar days stored as UTC midnight\n * (e.g., period_start_us, valid_from_us, next_billing_us).\n */\nexport function formatCalendarDate(value: string | number, long = false): string {\n const us = typeof value === 'string' ? Number(value) : value;\n if (!us || isNaN(us)) return '';\n return new Intl.DateTimeFormat('en-US', {\n month: long ? 'long' : 'short', day: 'numeric', year: 'numeric', timeZone: 'UTC',\n }).format(new Date(us / 1000));\n}\n\n/**\n * Format an exclusive-end microsecond timestamp as an inclusive UTC date.\n * Subtracts 1 day to convert from \"first moment of next period\" to \"last day of period\".\n * Use for period_end_us, valid_to_us where the stored value is the start of the next period.\n */\nexport function formatPeriodEndDate(value: string | number, long = false): string {\n const us = typeof value === 'string' ? Number(value) : value;\n if (!us || isNaN(us)) return '';\n return formatCalendarDate(us - ONE_DAY_US, long);\n}\n\n/** Get the UTC year from a microsecond timestamp string. */\nexport function getUtcYear(value: string): number {\n return new Date(Number(value) / 1000).getUTCFullYear();\n}\n\n/** Get the UTC month (0-indexed) from a microsecond timestamp string. */\nexport function getUtcMonth(value: string): number {\n return new Date(Number(value) / 1000).getUTCMonth();\n}\n\n// ---------------------------------------------------------------------------\n// Local calendar-date arithmetic (used by the calendar views). These operate\n// on local-time Date objects and never mutate their inputs.\n// ---------------------------------------------------------------------------\n\nexport function areSameDates(date1: Date, date2: Date): boolean {\n return (\n date1.getFullYear() === date2.getFullYear() &&\n date1.getMonth() === date2.getMonth() &&\n date1.getDate() === date2.getDate()\n );\n}\n\n/** The Sunday starting the week containing `date` (local time). */\nexport function firstDayOfWeek(date: Date): Date {\n return new Date(\n date.getFullYear(),\n date.getMonth(),\n date.getDate() - date.getDay()\n );\n}\n\n/** The Saturday ending the week containing `date` (local time). */\nexport function lastDayOfWeek(date: Date): Date {\n return new Date(\n date.getFullYear(),\n date.getMonth(),\n date.getDate() - date.getDay() + 6\n );\n}\n\nexport function firstDayOfMonth(date: Date): Date {\n return new Date(date.getFullYear(), date.getMonth(), 1);\n}\n\n/** Expects the first day of a month; returns that month's last day. */\nexport function lastDayOfMonth(date: Date): Date {\n return addDaysToDate(addMonthsToDate(date, 1), -1);\n}\n\nexport function addDaysToDate(date: Date, days: number): Date {\n const dateValue = new Date(date.valueOf());\n return new Date(dateValue.setDate(dateValue.getDate() + days));\n}\n\nexport function addWeeksToDate(date: Date, weeks: number): Date {\n return addDaysToDate(date, weeks * 7);\n}\n\nexport function addMonthsToDate(date: Date, months: number): Date {\n const dateValue = new Date(date.valueOf());\n return new Date(dateValue.setMonth(dateValue.getMonth() + months));\n}\n\nexport function formatMicroseconds(value: string): string {\n if (!value || !isMicrosecondTimestamp(value)) {\n return value;\n }\n\n const date = microsToDate(value);\n if (isNaN(date.getTime())) {\n return value;\n }\n\n const now = Date.now();\n const diffMs = now - date.getTime();\n\n if (diffMs < 60 * 1000) {\n return 'just now';\n }\n\n if (diffMs < 60 * 60 * 1000) {\n const minutes = Math.floor(diffMs / (60 * 1000));\n return minutes === 1 ? '1 minute ago' : `${minutes} minutes ago`;\n }\n\n if (diffMs < 24 * 60 * 60 * 1000) {\n const hours = Math.floor(diffMs / (60 * 60 * 1000));\n return hours === 1 ? '1 hour ago' : `${hours} hours ago`;\n }\n\n return new Intl.DateTimeFormat('en-US', {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n hour: 'numeric',\n minute: '2-digit',\n hour12: true\n }).format(date);\n}\n","/*\n * @honuware/ui/foundation — the bottom layer (no internal dependencies).\n * Toast, ConfirmDialog, fuse animations, microsecond date utilities, and the\n * open-redirect returnUrl sanitizer.\n */\nexport { ToastService } from './toast/toast.service';\nexport type { ToastType } from './toast/toast.service';\nexport { ConfirmDialogComponent } from './confirm-dialog/confirm-dialog.component';\nexport type { ConfirmDialogData } from './confirm-dialog/confirm-dialog.component';\nexport { fuseAnimations } from './animations/public-api';\nexport { sanitizeReturnUrl } from './sanitize-return-url';\nexport * from './date-formatting';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,238 @@
1
+ import * as i0 from '@angular/core';
2
+ import { Input, Inject, Component } from '@angular/core';
3
+ import { of, from } from 'rxjs';
4
+ import { switchMap, tap, map } from 'rxjs/operators';
5
+ import * as i2 from '@angular/material/button';
6
+ import { MatButtonModule } from '@angular/material/button';
7
+ import * as i3 from '@angular/material/icon';
8
+ import { MatIconModule } from '@angular/material/icon';
9
+ import * as i4 from '@angular/material/progress-spinner';
10
+ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
11
+ import * as i1 from '@honuware/ui/access';
12
+ import { HONUWARE_PHOTO_ACCESS } from '@honuware/ui/access';
13
+
14
+ class PhotoUploadComponent {
15
+ photoAccess;
16
+ photoUrlBuilder;
17
+ tableName;
18
+ tableItemId;
19
+ userMode = false;
20
+ deferUpload = false;
21
+ // Must match the server's image_max_source_width / image_max_source_height
22
+ // defaults. Images larger than this are resized on the client before upload
23
+ // so they stay under the server's image_max_upload_bytes limit.
24
+ static MAX_IMAGE_DIMENSION = 4096;
25
+ photoUrl = '';
26
+ hasPhoto = false;
27
+ loading = true;
28
+ uploading = false;
29
+ error;
30
+ pendingFile = null;
31
+ pendingPreviewUrl = '';
32
+ constructor(photoAccess, photoUrlBuilder) {
33
+ this.photoAccess = photoAccess;
34
+ this.photoUrlBuilder = photoUrlBuilder;
35
+ }
36
+ ngOnInit() {
37
+ if (this.deferUpload) {
38
+ this.loading = false;
39
+ }
40
+ else {
41
+ this.checkPhoto();
42
+ }
43
+ }
44
+ ngOnChanges(changes) {
45
+ if (this.deferUpload)
46
+ return;
47
+ if ((changes['tableName'] || changes['tableItemId']) && !changes['tableName']?.firstChange) {
48
+ this.checkPhoto();
49
+ }
50
+ }
51
+ ngOnDestroy() {
52
+ this.clearPendingFile();
53
+ }
54
+ checkPhoto() {
55
+ this.loading = true;
56
+ this.error = undefined;
57
+ this.photoAccess.hasPhoto(this.tableName, this.tableItemId).subscribe({
58
+ next: (result) => {
59
+ this.hasPhoto = result.has_photo;
60
+ if (this.hasPhoto) {
61
+ this.photoUrl = this.buildPhotoUrl();
62
+ }
63
+ this.loading = false;
64
+ },
65
+ error: () => {
66
+ this.hasPhoto = false;
67
+ this.loading = false;
68
+ }
69
+ });
70
+ }
71
+ buildPhotoUrl() {
72
+ return this.photoUrlBuilder.scaledPhotoUrl(this.tableName, this.tableItemId, 300, 300);
73
+ }
74
+ onFileSelected(event) {
75
+ const input = event.target;
76
+ if (!input.files || input.files.length === 0)
77
+ return;
78
+ const file = input.files[0];
79
+ this.uploadFile(file);
80
+ }
81
+ onDragOver(event) {
82
+ event.preventDefault();
83
+ event.stopPropagation();
84
+ }
85
+ onDrop(event) {
86
+ event.preventDefault();
87
+ event.stopPropagation();
88
+ if (!event.dataTransfer?.files || event.dataTransfer.files.length === 0)
89
+ return;
90
+ const file = event.dataTransfer.files[0];
91
+ this.uploadFile(file);
92
+ }
93
+ uploadFile(file) {
94
+ if (this.deferUpload) {
95
+ this.clearPendingFile();
96
+ this.pendingFile = file;
97
+ const reader = new FileReader();
98
+ reader.onload = () => {
99
+ this.pendingPreviewUrl = reader.result;
100
+ };
101
+ reader.readAsDataURL(file);
102
+ return;
103
+ }
104
+ this.uploading = true;
105
+ this.error = undefined;
106
+ this.prepareImageForUpload(file).then(({ buffer, imageType }) => {
107
+ const upload$ = this.userMode
108
+ ? this.photoAccess.uploadUserPhoto(buffer, imageType)
109
+ : this.photoAccess.uploadPhoto(this.tableName, this.tableItemId, buffer, imageType);
110
+ upload$.subscribe({
111
+ next: () => {
112
+ this.hasPhoto = true;
113
+ this.uploading = false;
114
+ // Bust cache by adding timestamp
115
+ this.photoUrl = this.buildPhotoUrl() + '?t=' + Date.now();
116
+ },
117
+ error: (err) => {
118
+ this.error = 'Failed to upload photo';
119
+ this.uploading = false;
120
+ console.error('Error uploading photo:', err);
121
+ }
122
+ });
123
+ }).catch((err) => {
124
+ // Without this catch, a decode/encode failure (e.g. an unsupported
125
+ // format such as HEIC, which browsers can't render) would leave the
126
+ // control stuck on "Processing…" with no error and no request.
127
+ this.error = 'Could not read this image. Try a JPEG or PNG '
128
+ + '(formats like HEIC are not supported).';
129
+ this.uploading = false;
130
+ console.error('Error preparing image for upload:', err);
131
+ });
132
+ }
133
+ get hasPendingFile() {
134
+ return this.pendingFile !== null;
135
+ }
136
+ clearPendingFile() {
137
+ this.pendingFile = null;
138
+ this.pendingPreviewUrl = '';
139
+ }
140
+ uploadPendingPhoto(tableName, tableItemId) {
141
+ if (!this.pendingFile) {
142
+ return of(void 0);
143
+ }
144
+ const file = this.pendingFile;
145
+ return from(this.prepareImageForUpload(file)).pipe(switchMap(({ buffer, imageType }) => this.photoAccess.uploadPhoto(tableName, tableItemId, buffer, imageType)), tap(() => this.clearPendingFile()), map(() => void 0));
146
+ }
147
+ /**
148
+ * Re-encode the image as JPEG and resize if it exceeds the max dimensions.
149
+ * Converting to JPEG dramatically reduces file size for photographic content
150
+ * (a 25 MB PNG becomes ~1-2 MB JPEG) and keeps uploads under the server's
151
+ * image_max_upload_bytes limit.
152
+ */
153
+ prepareImageForUpload(file) {
154
+ const maxDim = PhotoUploadComponent.MAX_IMAGE_DIMENSION;
155
+ return new Promise((resolve, reject) => {
156
+ const img = new Image();
157
+ const objectUrl = URL.createObjectURL(file);
158
+ img.onload = () => {
159
+ URL.revokeObjectURL(objectUrl);
160
+ // Clamp dimensions to max while preserving aspect ratio
161
+ let width = img.naturalWidth;
162
+ let height = img.naturalHeight;
163
+ if (width > maxDim || height > maxDim) {
164
+ const ratio = Math.min(maxDim / width, maxDim / height);
165
+ width = Math.round(width * ratio);
166
+ height = Math.round(height * ratio);
167
+ }
168
+ const canvas = document.createElement('canvas');
169
+ canvas.width = width;
170
+ canvas.height = height;
171
+ const ctx = canvas.getContext('2d');
172
+ if (!ctx) {
173
+ reject(new Error('Could not create canvas context'));
174
+ return;
175
+ }
176
+ ctx.drawImage(img, 0, 0, width, height);
177
+ canvas.toBlob(blob => {
178
+ if (!blob) {
179
+ reject(new Error('Canvas toBlob returned null'));
180
+ return;
181
+ }
182
+ blob.arrayBuffer().then(buffer => resolve({ buffer, imageType: 'jpeg' }), err => reject(err));
183
+ }, 'image/jpeg', 0.92);
184
+ };
185
+ img.onerror = () => {
186
+ URL.revokeObjectURL(objectUrl);
187
+ reject(new Error('Failed to load image'));
188
+ };
189
+ img.src = objectUrl;
190
+ });
191
+ }
192
+ onDeletePhoto() {
193
+ this.uploading = true;
194
+ this.error = undefined;
195
+ this.photoAccess.deletePhoto(this.tableName, this.tableItemId).subscribe({
196
+ next: () => {
197
+ this.hasPhoto = false;
198
+ this.uploading = false;
199
+ },
200
+ error: (err) => {
201
+ this.error = 'Failed to delete photo';
202
+ this.uploading = false;
203
+ console.error('Error deleting photo:', err);
204
+ }
205
+ });
206
+ }
207
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: PhotoUploadComponent, deps: [{ token: HONUWARE_PHOTO_ACCESS }, { token: i1.PhotoUrlBuilder }], target: i0.ɵɵFactoryTarget.Component });
208
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.18", type: PhotoUploadComponent, isStandalone: true, selector: "hw-photo-upload", inputs: { tableName: "tableName", tableItemId: "tableItemId", userMode: "userMode", deferUpload: "deferUpload" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"photo-upload-container\">\n @if (loading) {\n <div class=\"loading-container\">\n <mat-spinner diameter=\"30\"></mat-spinner>\n </div>\n } @else {\n <!-- Current photo display -->\n @if (hasPhoto) {\n <div class=\"photo-display\">\n <img [src]=\"photoUrl\" class=\"current-photo\" alt=\"Current photo\">\n </div>\n } @else if (hasPendingFile) {\n <div class=\"photo-display\">\n <img [src]=\"pendingPreviewUrl\" class=\"current-photo\" alt=\"Selected photo\">\n </div>\n } @else {\n <div class=\"photo-placeholder\">\n <mat-icon>image</mat-icon>\n <span>No photo</span>\n </div>\n }\n\n <!-- Upload area -->\n @if (!uploading) {\n <div class=\"upload-area\"\n (dragover)=\"onDragOver($event)\"\n (drop)=\"onDrop($event)\">\n <mat-icon>cloud_upload</mat-icon>\n <span>Drag & drop or</span>\n <label class=\"file-input-label\">\n <span>choose file</span>\n <input type=\"file\" accept=\"image/*\" (change)=\"onFileSelected($event)\" hidden>\n </label>\n </div>\n\n @if (hasPhoto) {\n <button mat-stroked-button color=\"warn\" class=\"delete-button\" (click)=\"onDeletePhoto()\">\n <mat-icon>delete</mat-icon>\n Delete Photo\n </button>\n }\n @if (hasPendingFile) {\n <button mat-stroked-button color=\"warn\" class=\"delete-button\" (click)=\"clearPendingFile()\">\n <mat-icon>close</mat-icon>\n Remove\n </button>\n }\n } @else {\n <div class=\"uploading-container\">\n <mat-spinner diameter=\"24\"></mat-spinner>\n <span>Processing...</span>\n </div>\n }\n\n @if (error) {\n <div class=\"error-message\">{{ error }}</div>\n }\n }\n</div>\n", styles: [".photo-upload-container{display:flex;flex-direction:column;align-items:center;gap:12px;padding:16px;border:1px solid #d1d5db;border-radius:8px;max-width:350px}.loading-container{display:flex;justify-content:center;padding:24px}.photo-display .current-photo{max-width:300px;max-height:300px;border-radius:4px;object-fit:contain}.photo-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;width:200px;height:150px;background-color:#f5f5f5;border-radius:4px;color:#9e9e9e}.photo-placeholder mat-icon{font-size:48px;width:48px;height:48px}.photo-placeholder span{margin-top:8px;font-size:14px}.upload-area{display:flex;align-items:center;gap:8px;padding:12px 16px;border:2px dashed #d1d5db;border-radius:8px;color:#666;font-size:14px;cursor:default}.upload-area:hover{border-color:#3f51b5}.upload-area mat-icon{color:#3f51b5}.file-input-label span{color:#3f51b5;cursor:pointer;text-decoration:underline}.file-input-label span:hover{color:#303f9f}.delete-button{font-size:13px}.uploading-container{display:flex;align-items:center;gap:8px;padding:12px;color:#666;font-size:14px}.error-message{color:#f44336;font-size:13px}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i4.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }] });
209
+ }
210
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: PhotoUploadComponent, decorators: [{
211
+ type: Component,
212
+ args: [{ selector: 'hw-photo-upload', standalone: true, imports: [MatButtonModule, MatIconModule, MatProgressSpinnerModule], template: "<div class=\"photo-upload-container\">\n @if (loading) {\n <div class=\"loading-container\">\n <mat-spinner diameter=\"30\"></mat-spinner>\n </div>\n } @else {\n <!-- Current photo display -->\n @if (hasPhoto) {\n <div class=\"photo-display\">\n <img [src]=\"photoUrl\" class=\"current-photo\" alt=\"Current photo\">\n </div>\n } @else if (hasPendingFile) {\n <div class=\"photo-display\">\n <img [src]=\"pendingPreviewUrl\" class=\"current-photo\" alt=\"Selected photo\">\n </div>\n } @else {\n <div class=\"photo-placeholder\">\n <mat-icon>image</mat-icon>\n <span>No photo</span>\n </div>\n }\n\n <!-- Upload area -->\n @if (!uploading) {\n <div class=\"upload-area\"\n (dragover)=\"onDragOver($event)\"\n (drop)=\"onDrop($event)\">\n <mat-icon>cloud_upload</mat-icon>\n <span>Drag & drop or</span>\n <label class=\"file-input-label\">\n <span>choose file</span>\n <input type=\"file\" accept=\"image/*\" (change)=\"onFileSelected($event)\" hidden>\n </label>\n </div>\n\n @if (hasPhoto) {\n <button mat-stroked-button color=\"warn\" class=\"delete-button\" (click)=\"onDeletePhoto()\">\n <mat-icon>delete</mat-icon>\n Delete Photo\n </button>\n }\n @if (hasPendingFile) {\n <button mat-stroked-button color=\"warn\" class=\"delete-button\" (click)=\"clearPendingFile()\">\n <mat-icon>close</mat-icon>\n Remove\n </button>\n }\n } @else {\n <div class=\"uploading-container\">\n <mat-spinner diameter=\"24\"></mat-spinner>\n <span>Processing...</span>\n </div>\n }\n\n @if (error) {\n <div class=\"error-message\">{{ error }}</div>\n }\n }\n</div>\n", styles: [".photo-upload-container{display:flex;flex-direction:column;align-items:center;gap:12px;padding:16px;border:1px solid #d1d5db;border-radius:8px;max-width:350px}.loading-container{display:flex;justify-content:center;padding:24px}.photo-display .current-photo{max-width:300px;max-height:300px;border-radius:4px;object-fit:contain}.photo-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;width:200px;height:150px;background-color:#f5f5f5;border-radius:4px;color:#9e9e9e}.photo-placeholder mat-icon{font-size:48px;width:48px;height:48px}.photo-placeholder span{margin-top:8px;font-size:14px}.upload-area{display:flex;align-items:center;gap:8px;padding:12px 16px;border:2px dashed #d1d5db;border-radius:8px;color:#666;font-size:14px;cursor:default}.upload-area:hover{border-color:#3f51b5}.upload-area mat-icon{color:#3f51b5}.file-input-label span{color:#3f51b5;cursor:pointer;text-decoration:underline}.file-input-label span:hover{color:#303f9f}.delete-button{font-size:13px}.uploading-container{display:flex;align-items:center;gap:8px;padding:12px;color:#666;font-size:14px}.error-message{color:#f44336;font-size:13px}\n"] }]
213
+ }], ctorParameters: () => [{ type: undefined, decorators: [{
214
+ type: Inject,
215
+ args: [HONUWARE_PHOTO_ACCESS]
216
+ }] }, { type: i1.PhotoUrlBuilder }], propDecorators: { tableName: [{
217
+ type: Input
218
+ }], tableItemId: [{
219
+ type: Input
220
+ }], userMode: [{
221
+ type: Input
222
+ }], deferUpload: [{
223
+ type: Input
224
+ }] } });
225
+
226
+ /*
227
+ * @honuware/ui/photos — the photo-upload control (drag-drop, client-side
228
+ * resize/re-encode to JPEG, deferred-upload mode for create flows, userMode
229
+ * avatar path). Depends on access (PhotoAccess seam + PhotoUrlBuilder).
230
+ * Selector uses the `hw-` prefix.
231
+ */
232
+
233
+ /**
234
+ * Generated bundle index. Do not edit.
235
+ */
236
+
237
+ export { PhotoUploadComponent };
238
+ //# sourceMappingURL=honuware-ui-photos.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"honuware-ui-photos.mjs","sources":["../../../projects/honuware-ui/photos/src/photo-upload/photo-upload.component.ts","../../../projects/honuware-ui/photos/src/photo-upload/photo-upload.component.html","../../../projects/honuware-ui/photos/src/public-api.ts","../../../projects/honuware-ui/photos/src/honuware-ui-photos.ts"],"sourcesContent":["import { Component, Input, OnInit, OnChanges, OnDestroy, SimpleChanges, Inject } from '@angular/core';\n\nimport { Observable, of, from } from 'rxjs';\nimport { switchMap, tap, map } from 'rxjs/operators';\nimport { MatButtonModule } from '@angular/material/button';\nimport { MatIconModule } from '@angular/material/icon';\nimport { MatProgressSpinnerModule } from '@angular/material/progress-spinner';\nimport { PhotoAccess, HONUWARE_PHOTO_ACCESS, PhotoUrlBuilder } from '@honuware/ui/access';\n\n@Component({\n selector: 'hw-photo-upload',\n standalone: true,\n imports: [MatButtonModule, MatIconModule, MatProgressSpinnerModule],\n templateUrl: './photo-upload.component.html',\n styleUrls: ['./photo-upload.component.scss']\n})\nexport class PhotoUploadComponent implements OnInit, OnChanges, OnDestroy {\n @Input() tableName!: string;\n @Input() tableItemId!: number;\n @Input() userMode: boolean = false;\n @Input() deferUpload: boolean = false;\n\n // Must match the server's image_max_source_width / image_max_source_height\n // defaults. Images larger than this are resized on the client before upload\n // so they stay under the server's image_max_upload_bytes limit.\n private static readonly MAX_IMAGE_DIMENSION = 4096;\n\n photoUrl: string = '';\n hasPhoto: boolean = false;\n loading: boolean = true;\n uploading: boolean = false;\n error?: string;\n\n pendingFile: File | null = null;\n pendingPreviewUrl: string = '';\n\n constructor(\n @Inject(HONUWARE_PHOTO_ACCESS) private photoAccess: PhotoAccess,\n private photoUrlBuilder: PhotoUrlBuilder\n ) {}\n\n ngOnInit(): void {\n if (this.deferUpload) {\n this.loading = false;\n } else {\n this.checkPhoto();\n }\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (this.deferUpload) return;\n if ((changes['tableName'] || changes['tableItemId']) && !changes['tableName']?.firstChange) {\n this.checkPhoto();\n }\n }\n\n ngOnDestroy(): void {\n this.clearPendingFile();\n }\n\n private checkPhoto(): void {\n this.loading = true;\n this.error = undefined;\n\n this.photoAccess.hasPhoto(this.tableName, this.tableItemId).subscribe({\n next: (result) => {\n this.hasPhoto = result.has_photo;\n if (this.hasPhoto) {\n this.photoUrl = this.buildPhotoUrl();\n }\n this.loading = false;\n },\n error: () => {\n this.hasPhoto = false;\n this.loading = false;\n }\n });\n }\n\n private buildPhotoUrl(): string {\n return this.photoUrlBuilder.scaledPhotoUrl(this.tableName, this.tableItemId, 300, 300);\n }\n\n onFileSelected(event: Event): void {\n const input = event.target as HTMLInputElement;\n if (!input.files || input.files.length === 0) return;\n\n const file = input.files[0];\n this.uploadFile(file);\n }\n\n onDragOver(event: DragEvent): void {\n event.preventDefault();\n event.stopPropagation();\n }\n\n onDrop(event: DragEvent): void {\n event.preventDefault();\n event.stopPropagation();\n if (!event.dataTransfer?.files || event.dataTransfer.files.length === 0) return;\n\n const file = event.dataTransfer.files[0];\n this.uploadFile(file);\n }\n\n private uploadFile(file: File): void {\n if (this.deferUpload) {\n this.clearPendingFile();\n this.pendingFile = file;\n const reader = new FileReader();\n reader.onload = () => {\n this.pendingPreviewUrl = reader.result as string;\n };\n reader.readAsDataURL(file);\n return;\n }\n\n this.uploading = true;\n this.error = undefined;\n\n this.prepareImageForUpload(file).then(({ buffer, imageType }) => {\n const upload$ = this.userMode\n ? this.photoAccess.uploadUserPhoto(buffer, imageType)\n : this.photoAccess.uploadPhoto(this.tableName, this.tableItemId, buffer, imageType);\n upload$.subscribe({\n next: () => {\n this.hasPhoto = true;\n this.uploading = false;\n // Bust cache by adding timestamp\n this.photoUrl = this.buildPhotoUrl() + '?t=' + Date.now();\n },\n error: (err) => {\n this.error = 'Failed to upload photo';\n this.uploading = false;\n console.error('Error uploading photo:', err);\n }\n });\n }).catch((err) => {\n // Without this catch, a decode/encode failure (e.g. an unsupported\n // format such as HEIC, which browsers can't render) would leave the\n // control stuck on \"Processing…\" with no error and no request.\n this.error = 'Could not read this image. Try a JPEG or PNG '\n + '(formats like HEIC are not supported).';\n this.uploading = false;\n console.error('Error preparing image for upload:', err);\n });\n }\n\n get hasPendingFile(): boolean {\n return this.pendingFile !== null;\n }\n\n clearPendingFile(): void {\n this.pendingFile = null;\n this.pendingPreviewUrl = '';\n }\n\n uploadPendingPhoto(tableName: string, tableItemId: number): Observable<void> {\n if (!this.pendingFile) {\n return of(void 0);\n }\n const file = this.pendingFile;\n\n return from(this.prepareImageForUpload(file)).pipe(\n switchMap(({ buffer, imageType }) =>\n this.photoAccess.uploadPhoto(tableName, tableItemId, buffer, imageType)),\n tap(() => this.clearPendingFile()),\n map(() => void 0)\n );\n }\n\n /**\n * Re-encode the image as JPEG and resize if it exceeds the max dimensions.\n * Converting to JPEG dramatically reduces file size for photographic content\n * (a 25 MB PNG becomes ~1-2 MB JPEG) and keeps uploads under the server's\n * image_max_upload_bytes limit.\n */\n private prepareImageForUpload(file: File): Promise<{ buffer: ArrayBuffer; imageType: string }> {\n const maxDim = PhotoUploadComponent.MAX_IMAGE_DIMENSION;\n\n return new Promise((resolve, reject) => {\n const img = new Image();\n const objectUrl = URL.createObjectURL(file);\n\n img.onload = () => {\n URL.revokeObjectURL(objectUrl);\n\n // Clamp dimensions to max while preserving aspect ratio\n let width = img.naturalWidth;\n let height = img.naturalHeight;\n if (width > maxDim || height > maxDim) {\n const ratio = Math.min(maxDim / width, maxDim / height);\n width = Math.round(width * ratio);\n height = Math.round(height * ratio);\n }\n\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n const ctx = canvas.getContext('2d');\n if (!ctx) {\n reject(new Error('Could not create canvas context'));\n return;\n }\n ctx.drawImage(img, 0, 0, width, height);\n\n canvas.toBlob(\n blob => {\n if (!blob) {\n reject(new Error('Canvas toBlob returned null'));\n return;\n }\n blob.arrayBuffer().then(\n buffer => resolve({ buffer, imageType: 'jpeg' }),\n err => reject(err)\n );\n },\n 'image/jpeg',\n 0.92\n );\n };\n\n img.onerror = () => {\n URL.revokeObjectURL(objectUrl);\n reject(new Error('Failed to load image'));\n };\n\n img.src = objectUrl;\n });\n }\n\n onDeletePhoto(): void {\n this.uploading = true;\n this.error = undefined;\n\n this.photoAccess.deletePhoto(this.tableName, this.tableItemId).subscribe({\n next: () => {\n this.hasPhoto = false;\n this.uploading = false;\n },\n error: (err) => {\n this.error = 'Failed to delete photo';\n this.uploading = false;\n console.error('Error deleting photo:', err);\n }\n });\n }\n}\n","<div class=\"photo-upload-container\">\n @if (loading) {\n <div class=\"loading-container\">\n <mat-spinner diameter=\"30\"></mat-spinner>\n </div>\n } @else {\n <!-- Current photo display -->\n @if (hasPhoto) {\n <div class=\"photo-display\">\n <img [src]=\"photoUrl\" class=\"current-photo\" alt=\"Current photo\">\n </div>\n } @else if (hasPendingFile) {\n <div class=\"photo-display\">\n <img [src]=\"pendingPreviewUrl\" class=\"current-photo\" alt=\"Selected photo\">\n </div>\n } @else {\n <div class=\"photo-placeholder\">\n <mat-icon>image</mat-icon>\n <span>No photo</span>\n </div>\n }\n\n <!-- Upload area -->\n @if (!uploading) {\n <div class=\"upload-area\"\n (dragover)=\"onDragOver($event)\"\n (drop)=\"onDrop($event)\">\n <mat-icon>cloud_upload</mat-icon>\n <span>Drag & drop or</span>\n <label class=\"file-input-label\">\n <span>choose file</span>\n <input type=\"file\" accept=\"image/*\" (change)=\"onFileSelected($event)\" hidden>\n </label>\n </div>\n\n @if (hasPhoto) {\n <button mat-stroked-button color=\"warn\" class=\"delete-button\" (click)=\"onDeletePhoto()\">\n <mat-icon>delete</mat-icon>\n Delete Photo\n </button>\n }\n @if (hasPendingFile) {\n <button mat-stroked-button color=\"warn\" class=\"delete-button\" (click)=\"clearPendingFile()\">\n <mat-icon>close</mat-icon>\n Remove\n </button>\n }\n } @else {\n <div class=\"uploading-container\">\n <mat-spinner diameter=\"24\"></mat-spinner>\n <span>Processing...</span>\n </div>\n }\n\n @if (error) {\n <div class=\"error-message\">{{ error }}</div>\n }\n }\n</div>\n","/*\n * @honuware/ui/photos — the photo-upload control (drag-drop, client-side\n * resize/re-encode to JPEG, deferred-upload mode for create flows, userMode\n * avatar path). Depends on access (PhotoAccess seam + PhotoUrlBuilder).\n * Selector uses the `hw-` prefix.\n */\nexport { PhotoUploadComponent } from './photo-upload/photo-upload.component';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,128 @@
1
+ import * as i0 from '@angular/core';
2
+ import { InjectionToken, Inject, Injectable } from '@angular/core';
3
+
4
+ const SQUARE_CONFIG = new InjectionToken('SQUARE_CONFIG', {
5
+ providedIn: 'root',
6
+ factory: () => ({
7
+ applicationId: 'sandbox-sq0idp-placeholder',
8
+ locationId: 'placeholder',
9
+ scriptUrl: 'https://sandbox.web.squarecdn.com/v1/square.js',
10
+ }),
11
+ });
12
+
13
+ /**
14
+ * Service for handling Square Web Payments SDK integration.
15
+ * Dynamically loads the Square SDK script based on the injected SQUARE_CONFIG.
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * // In a component
20
+ * async ngAfterViewInit() {
21
+ * await this.squarePayment.attachCard('#card-container');
22
+ * }
23
+ *
24
+ * async onSubmit() {
25
+ * const token = await this.squarePayment.tokenizeCard();
26
+ * // Send token to server
27
+ * }
28
+ * ```
29
+ */
30
+ class SquarePaymentService {
31
+ squareConfig;
32
+ payments = null;
33
+ card = null;
34
+ scriptLoaded = false;
35
+ constructor(squareConfig) {
36
+ this.squareConfig = squareConfig;
37
+ }
38
+ /**
39
+ * Dynamically loads the Square SDK script based on the injected config.
40
+ * Only loads once; subsequent calls return immediately.
41
+ */
42
+ loadScript() {
43
+ return new Promise((resolve, reject) => {
44
+ if (this.scriptLoaded || window.Square) {
45
+ this.scriptLoaded = true;
46
+ resolve();
47
+ return;
48
+ }
49
+ const script = document.createElement('script');
50
+ script.src = this.squareConfig.scriptUrl;
51
+ script.onload = () => {
52
+ this.scriptLoaded = true;
53
+ resolve();
54
+ };
55
+ script.onerror = () => reject(new Error('Failed to load Square SDK'));
56
+ document.head.appendChild(script);
57
+ });
58
+ }
59
+ /**
60
+ * Initializes the Square Payments SDK.
61
+ * Automatically loads the script if not already loaded.
62
+ */
63
+ async initialize() {
64
+ await this.loadScript();
65
+ if (!window.Square) {
66
+ throw new Error('Square SDK not available after loading');
67
+ }
68
+ this.payments = await window.Square.payments(this.squareConfig.applicationId, this.squareConfig.locationId);
69
+ }
70
+ /**
71
+ * Attaches the Square card input form to a DOM element.
72
+ * @param containerId CSS selector for the container element (e.g., '#card-container')
73
+ */
74
+ async attachCard(containerId) {
75
+ if (!this.payments) {
76
+ await this.initialize();
77
+ }
78
+ this.card = await this.payments.card();
79
+ await this.card.attach(containerId);
80
+ }
81
+ /**
82
+ * Tokenizes the card data entered by the user.
83
+ * @returns The payment token to send to the server
84
+ * @throws Error if tokenization fails
85
+ */
86
+ async tokenizeCard() {
87
+ if (!this.card) {
88
+ throw new Error('Card not attached. Call attachCard() first.');
89
+ }
90
+ const result = await this.card.tokenize();
91
+ if (result.status !== 'OK' || !result.token) {
92
+ const errorMessage = result.errors?.[0]?.message || 'Card tokenization failed';
93
+ throw new Error(errorMessage);
94
+ }
95
+ return result.token;
96
+ }
97
+ /**
98
+ * Destroys the card form and resets state.
99
+ * Call this when navigating away from the payment page.
100
+ */
101
+ destroy() {
102
+ this.card = null;
103
+ this.payments = null;
104
+ // Note: We don't unload the script as it may be needed again
105
+ }
106
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: SquarePaymentService, deps: [{ token: SQUARE_CONFIG }], target: i0.ɵɵFactoryTarget.Injectable });
107
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: SquarePaymentService, providedIn: 'root' });
108
+ }
109
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: SquarePaymentService, decorators: [{
110
+ type: Injectable,
111
+ args: [{ providedIn: 'root' }]
112
+ }], ctorParameters: () => [{ type: undefined, decorators: [{
113
+ type: Inject,
114
+ args: [SQUARE_CONFIG]
115
+ }] }] });
116
+
117
+ /*
118
+ * @honuware/ui/square — SquarePaymentService behind the SQUARE_CONFIG token
119
+ * (Web Payments SDK loader + card tokenizer). A standalone side entry that
120
+ * depends on nothing internal. The Square SDK ambient types ship in square.d.ts.
121
+ */
122
+
123
+ /**
124
+ * Generated bundle index. Do not edit.
125
+ */
126
+
127
+ export { SQUARE_CONFIG, SquarePaymentService };
128
+ //# sourceMappingURL=honuware-ui-square.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"honuware-ui-square.mjs","sources":["../../../projects/honuware-ui/square/src/square-config.ts","../../../projects/honuware-ui/square/src/square-payment.service.ts","../../../projects/honuware-ui/square/src/public-api.ts","../../../projects/honuware-ui/square/src/honuware-ui-square.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\n\n// Client-side Square Web Payments SDK configuration. These are public\n// identifiers (safe to expose in the bundle). Injected so the payment service\n// no longer imports a consumer's `environment` file — the app wires the real\n// values in `app.config.ts` from `environment.square`, and a honuware consumer\n// (or a test) provides its own. The default below is a benign sandbox\n// placeholder that will not tokenize a real card.\nexport interface SquareConfig {\n applicationId: string;\n locationId: string;\n scriptUrl: string;\n}\n\nexport const SQUARE_CONFIG = new InjectionToken<SquareConfig>('SQUARE_CONFIG', {\n providedIn: 'root',\n factory: () => ({\n applicationId: 'sandbox-sq0idp-placeholder',\n locationId: 'placeholder',\n scriptUrl: 'https://sandbox.web.squarecdn.com/v1/square.js',\n }),\n});\n","import { Inject, Injectable } from '@angular/core';\nimport { Payments, Card } from './square-sdk';\nimport { SQUARE_CONFIG, SquareConfig } from './square-config';\n\n/**\n * Service for handling Square Web Payments SDK integration.\n * Dynamically loads the Square SDK script based on the injected SQUARE_CONFIG.\n *\n * @example\n * ```typescript\n * // In a component\n * async ngAfterViewInit() {\n * await this.squarePayment.attachCard('#card-container');\n * }\n *\n * async onSubmit() {\n * const token = await this.squarePayment.tokenizeCard();\n * // Send token to server\n * }\n * ```\n */\n@Injectable({ providedIn: 'root' })\nexport class SquarePaymentService {\n private payments: Payments | null = null;\n private card: Card | null = null;\n private scriptLoaded = false;\n\n constructor(@Inject(SQUARE_CONFIG) private squareConfig: SquareConfig) {}\n\n /**\n * Dynamically loads the Square SDK script based on the injected config.\n * Only loads once; subsequent calls return immediately.\n */\n private loadScript(): Promise<void> {\n return new Promise((resolve, reject) => {\n if (this.scriptLoaded || window.Square) {\n this.scriptLoaded = true;\n resolve();\n return;\n }\n\n const script = document.createElement('script');\n script.src = this.squareConfig.scriptUrl;\n script.onload = () => {\n this.scriptLoaded = true;\n resolve();\n };\n script.onerror = () => reject(new Error('Failed to load Square SDK'));\n document.head.appendChild(script);\n });\n }\n\n /**\n * Initializes the Square Payments SDK.\n * Automatically loads the script if not already loaded.\n */\n async initialize(): Promise<void> {\n await this.loadScript();\n\n if (!window.Square) {\n throw new Error('Square SDK not available after loading');\n }\n\n this.payments = await window.Square.payments(\n this.squareConfig.applicationId,\n this.squareConfig.locationId\n );\n }\n\n /**\n * Attaches the Square card input form to a DOM element.\n * @param containerId CSS selector for the container element (e.g., '#card-container')\n */\n async attachCard(containerId: string): Promise<void> {\n if (!this.payments) {\n await this.initialize();\n }\n this.card = await this.payments!.card();\n await this.card.attach(containerId);\n }\n\n /**\n * Tokenizes the card data entered by the user.\n * @returns The payment token to send to the server\n * @throws Error if tokenization fails\n */\n async tokenizeCard(): Promise<string> {\n if (!this.card) {\n throw new Error('Card not attached. Call attachCard() first.');\n }\n\n const result = await this.card.tokenize();\n\n if (result.status !== 'OK' || !result.token) {\n const errorMessage = result.errors?.[0]?.message || 'Card tokenization failed';\n throw new Error(errorMessage);\n }\n\n return result.token;\n }\n\n /**\n * Destroys the card form and resets state.\n * Call this when navigating away from the payment page.\n */\n destroy(): void {\n this.card = null;\n this.payments = null;\n // Note: We don't unload the script as it may be needed again\n }\n}\n","/*\n * @honuware/ui/square — SquarePaymentService behind the SQUARE_CONFIG token\n * (Web Payments SDK loader + card tokenizer). A standalone side entry that\n * depends on nothing internal. The Square SDK ambient types ship in square.d.ts.\n */\nexport { SquarePaymentService } from './square-payment.service';\nexport { SQUARE_CONFIG } from './square-config';\nexport type { SquareConfig } from './square-config';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}