UNPKG

@rero/ng-core

Version:

RERO angular core library.

1,174 lines (1,162 loc) 635 kB
import * as i0 from '@angular/core'; import { inject, Pipe, input, linkedSignal, computed, ChangeDetectionStrategy, Component, output, viewChild, effect, HostListener, Injectable, LOCALE_ID, model, Injector, runInInjectionContext, signal, DestroyRef, makeEnvironmentProviders, ElementRef, booleanAttribute, afterNextRender, Directive, ViewContainerRef, inputBinding, untracked, ChangeDetectorRef } from '@angular/core'; import { DomSanitizer, Title } from '@angular/platform-browser'; import { marked } from 'marked'; import { DateTime, Settings } from 'luxon'; import { definePreset } from '@primeuix/themes'; import Aura from '@primeuix/themes/aura'; import { _, TranslatePipe, TranslateService, TranslateDirective } from '@ngx-translate/core'; import { Button, ButtonDirective } from 'primeng/button'; import { DynamicDialogConfig, DynamicDialogRef, DialogService } from 'primeng/dynamicdialog'; import { InputGroup } from 'primeng/inputgroup'; import { InputText } from 'primeng/inputtext'; import { AutoFocus } from 'primeng/autofocus'; import { InputGroupAddon } from 'primeng/inputgroupaddon'; import { ActivatedRoute, TitleStrategy, RouterLink, Router } from '@angular/router'; import * as i1 from '@ngx-formly/core'; import { FieldType, FormlyModule, FieldWrapper, FieldArrayType, FORMLY_CONFIG, provideFormlyCore } from '@ngx-formly/core'; import { ConfirmationService, MessageService } from 'primeng/api'; import { throwError, of, isObservable, Subscription, startWith, combineLatest, map as map$5, Subject, switchMap, shareReplay, tap, merge, forkJoin, pipe, EMPTY, catchError as catchError$1, filter, finalize as finalize$1 } from 'rxjs'; import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http'; import { catchError, map as map$4, debounceTime, finalize, first, switchMap as switchMap$1, distinctUntilChanged, tap as tap$1 } from 'rxjs/operators'; import { withFormlyPrimeNG } from '@ngx-formly/primeng'; import * as i1$2 from '@angular/common'; import { NgClass, NgTemplateOutlet, registerLocaleData, DatePipe, JsonPipe, SlicePipe, AsyncPipe, CommonModule, Location } from '@angular/common'; import * as i1$1 from '@angular/forms'; import { FormsModule, ReactiveFormsModule, FormControl, UntypedFormGroup } from '@angular/forms'; import { DatePicker } from 'primeng/datepicker'; import EasyMDE from 'easymde'; import { Textarea } from 'primeng/textarea'; import { toSignal, takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop'; import { Checkbox } from 'primeng/checkbox'; import { MultiSelect } from 'primeng/multiselect'; import { Tooltip } from 'primeng/tooltip'; import { Clipboard } from '@angular/cdk/clipboard'; import { GeneratePassword } from 'generate-password-lite'; import { RadioButton } from 'primeng/radiobutton'; import { AutoComplete } from 'primeng/autocomplete'; import { Select } from 'primeng/select'; import { ToggleSwitch } from 'primeng/toggleswitch'; import { TreeSelect } from 'primeng/treeselect'; import { Fieldset } from 'primeng/fieldset'; import { TieredMenu } from 'primeng/tieredmenu'; import localeDe from '@angular/common/locales/de'; import localeEn from '@angular/common/locales/en-GB'; import localeFr from '@angular/common/locales/fr'; import localeIt from '@angular/common/locales/it'; import { de as de$6 } from 'primelocale/js/de.js'; import { en as en$6 } from 'primelocale/js/en.js'; import { fr as fr$6 } from 'primelocale/js/fr.js'; import { it as it$6 } from 'primelocale/js/it.js'; import { PrimeNG } from 'primeng/config'; import renderMathInElement from 'katex/contrib/auto-render'; import * as CryptoJS from 'crypto-js'; import { Listbox } from 'primeng/listbox'; import { signalStoreFeature, type, withState, withComputed, withMethods, patchState, withHooks, withProps, signalStore } from '@ngrx/signals'; import { rxMethod } from '@ngrx/signals/rxjs-interop'; import { NgxSpinnerService } from 'ngx-spinner'; import { DataView } from 'primeng/dataview'; import { Message } from 'primeng/message'; import { InputNumber } from 'primeng/inputnumber'; import { Divider } from 'primeng/divider'; import { Menu } from 'primeng/menu'; import { Paginator } from 'primeng/paginator'; import { Ripple } from 'primeng/ripple'; import { Tabs, TabList, Tab } from 'primeng/tabs'; import { FormlyJsonschema } from '@ngx-formly/core/json-schema'; import { cloneDeep } from 'lodash-es'; import { SplitButton } from 'primeng/splitbutton'; import { DomHandler } from 'primeng/dom'; // SPDX-FileCopyrightText: Fondation RERO+ // SPDX-License-Identifier: AGPL-3.0-or-later /** * Pipe for converting carriage returns to <br> html entities. */ class Nl2brPipe { sanitizer = inject(DomSanitizer); /** * Returns transformed value containing <br> entities. * * @param value Value to transform. * @return Transformed value. */ transform(value) { if (!value) { return this.sanitizer.bypassSecurityTrustHtml(''); } return this.sanitizer.bypassSecurityTrustHtml(value.replace(/\r\n?|\n/g, '<br>\n')); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: Nl2brPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.17", ngImport: i0, type: Nl2brPipe, isStandalone: true, name: "nl2br" }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: Nl2brPipe, decorators: [{ type: Pipe, args: [{ name: 'nl2br' }] }] }); // SPDX-FileCopyrightText: Fondation RERO+ // SPDX-License-Identifier: AGPL-3.0-or-later /** * Get human readable file size. */ class FilesizePipe { /** * Transform size to a human readable size. * * @param size Size of file. * @param precision Number of decimals. * @return Human readable file size. */ transform(size, precision = 2) { let i = -1; const byteUnits = ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; do { size /= 1024; i++; } while (size > 1024); return [Math.max(size, 0.1).toFixed(precision), byteUnits[i]].join(' '); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: FilesizePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.17", ngImport: i0, type: FilesizePipe, isStandalone: true, name: "filesize" }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: FilesizePipe, decorators: [{ type: Pipe, args: [{ name: 'filesize' }] }] }); // SPDX-FileCopyrightText: Fondation RERO+ // SPDX-License-Identifier: AGPL-3.0-or-later /** * Pipe for truncating text. */ class TruncateTextPipe { /** * Truncate text. * * @param value Text to truncate. * @param limit Limit after which the text is truncated. * @param trail Trailing chars * @param type Word or Char type * @return Truncated string */ transform(value, limit = 40, trail = '…', type = 'word') { let result = value || ''; if (type === 'char' && value) { if (value.length < limit) { return value; } else { return value.substring(0, limit) + trail; } } if (type === 'word' && value) { const words = value.split(/\s+/); if (words.length > Math.abs(limit)) { if (limit < 0) { limit *= -1; result = trail + words.slice(words.length - limit).join(' '); } else { result = words.slice(0, limit).join(' ') + trail; } } } return result; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: TruncateTextPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.17", ngImport: i0, type: TruncateTextPipe, isStandalone: true, name: "truncateText" }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: TruncateTextPipe, decorators: [{ type: Pipe, args: [{ name: 'truncateText' }] }] }); // SPDX-FileCopyrightText: Fondation RERO+ // SPDX-License-Identifier: AGPL-3.0-or-later function extractIdOnRef(ref) { if (!ref) { throw new Error('extractIdOnRef: ref is null or empty'); } const match = /.*\/([^/]+)$/.exec(ref); if (!match) { throw new Error(`extractIdOnRef: unable to extract id from ref "${ref}"`); } return match[1]; } function cleanDictKeys(data) { return Object.fromEntries(Object.entries(data).filter(([, value]) => { if (value == null) { return false; } if (typeof value === 'string' || Array.isArray(value)) { return value.length > 0; } return true; })); } function capitalize(value) { return value.charAt(0).toUpperCase() + value.slice(1); } function removeChars(value, chars = ['"']) { const re = new RegExp('[' + chars.join('') + ']', 'gi'); return value.replace(re, ''); } // SPDX-FileCopyrightText: Fondation RERO+ // SPDX-License-Identifier: AGPL-3.0-or-later /** * Uppercase the first letter of the string. */ class UpperCaseFirstPipe { /** * Uppercase the first letter of the given value. * * @param value Value to transform. * @return Transformed value. */ transform(value) { if (!value) { return value; } return capitalize(value); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: UpperCaseFirstPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.17", ngImport: i0, type: UpperCaseFirstPipe, isStandalone: true, name: "ucfirst" }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: UpperCaseFirstPipe, decorators: [{ type: Pipe, args: [{ name: 'ucfirst' }] }] }); // SPDX-FileCopyrightText: Fondation RERO+ // SPDX-License-Identifier: AGPL-3.0-or-later /** * Pipe to transform markdown to html. */ class MarkdownPipe { sanitizer = inject(DomSanitizer); /** * Transform markdown to HTML. * * @param value Markdown initial value. * @returns HTML corresponding to markdown. */ transform(value) { const markValue = marked.parse(value, { gfm: true, breaks: false, async: false }); return this.sanitizer.bypassSecurityTrustHtml(markValue); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: MarkdownPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.17", ngImport: i0, type: MarkdownPipe, isStandalone: true, name: "markdown" }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: MarkdownPipe, decorators: [{ type: Pipe, args: [{ name: 'markdown' }] }] }); // SPDX-FileCopyrightText: Fondation RERO+ // SPDX-License-Identifier: AGPL-3.0-or-later /** * Pipe for applying a callback function to filter array items. */ class CallbackArrayFilterPipe { /** * Filter array items with the given callback function. * * @param items List of items. * @param callback Callback function to apply. * @return List of filtered values. */ transform(items, callback) { if (items?.length) { if (!callback) { return items; } else { return items.filter((item) => callback(item)); } } return []; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: CallbackArrayFilterPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.17", ngImport: i0, type: CallbackArrayFilterPipe, isStandalone: true, name: "callbackArrayFilter" }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: CallbackArrayFilterPipe, decorators: [{ type: Pipe, args: [{ name: 'callbackArrayFilter' }] }] }); // @dynamic class TimeValidator { static FORMAT = 'hh:mm'; /** * Allow to control if time interval limits are well formed : the end limit should be 'older' the start limit * @param start: the field name where to find the start limit value * @param end: the field name where to find the end limit value */ static greaterThanValidator(start, end) { return (control) => { const startTime = control.get(start); const endTime = control.get(end); if (control && startTime && endTime) { let isLessThan = false; const startDate = DateTime.fromFormat(startTime.value, TimeValidator.FORMAT); const endDate = DateTime.fromFormat(endTime.value, TimeValidator.FORMAT); if (startDate.toFormat(TimeValidator.FORMAT) !== '00:00' || endDate.toFormat(TimeValidator.FORMAT) !== '00:00') { isLessThan = startDate >= endDate; } return isLessThan ? { lessThan: { value: isLessThan } } : null; } return null; }; } static RangePeriodValidator() { return (control) => { if (control.value) { let isRangeLessThan = false; const times = control.get('times'); if (control.get('is_open')?.value && times && times.value.length > 1) { const firstStartDate = DateTime.fromFormat(times.at(0).get('start_time')?.value, TimeValidator.FORMAT); const firstEndDate = DateTime.fromFormat(times.at(0).get('end_time')?.value, TimeValidator.FORMAT); const lastStartDate = DateTime.fromFormat(times.at(1).get('start_time')?.value, TimeValidator.FORMAT); const lastEndDate = DateTime.fromFormat(times.at(1).get('end_time')?.value, TimeValidator.FORMAT); if (firstStartDate > lastStartDate) { isRangeLessThan = firstStartDate <= lastStartDate || firstStartDate <= lastEndDate; } else { isRangeLessThan = lastStartDate <= firstEndDate || lastStartDate <= firstEndDate; } } return isRangeLessThan ? { rangeLessThan: { value: isRangeLessThan } } : null; } return null; }; } } // @dynamic class UniqueValidator { static createValidator(recordService, recordType, fieldName, excludePid) { return (control) => { return recordService.valueAlreadyExists(recordType, fieldName, control.value, excludePid); }; } } // SPDX-FileCopyrightText: Fondation RERO+ // SPDX-License-Identifier: AGPL-3.0-or-later const primeNGConfig = { theme: { options: { // Layer order (lowest → highest priority). PrimeNG injects this @layer // declaration before styles.css, so "primeng" is established below // "utilities" — allowing Tailwind utility classes (ui:, core:) to // override PrimeNG component styles. Do not move "utilities" before // "primeng" or Tailwind overrides will stop working. cssLayer: { name: 'primeng', order: 'theme, base, primeng, utilities' }, darkModeSelector: false, }, preset: definePreset(Aura, { primitive: { borderRadius: { none: '0', xs: '2px', sm: '4px', md: '6px', lg: '8px', xl: '12px', }, emerald: { 50: '#ecfdf5', 100: '#d1fae5', 200: '#a7f3d0', 300: '#6ee7b7', 400: '#34d399', 500: '#10b981', 600: '#059669', 700: '#047857', 800: '#065f46', 900: '#064e3b', 950: '#022c22', }, green: { 50: '#f0fdf4', 100: '#dcfce7', 200: '#bbf7d0', 300: '#86efac', 400: '#4ade80', 500: '#22c55e', 600: '#16a34a', 700: '#15803d', 800: '#166534', 900: '#14532d', 950: '#052e16', }, lime: { 50: '#f7fee7', 100: '#ecfccb', 200: '#d9f99d', 300: '#bef264', 400: '#a3e635', 500: '#84cc16', 600: '#65a30d', 700: '#4d7c0f', 800: '#3f6212', 900: '#365314', 950: '#1a2e05', }, red: { 50: '#fef2f2', 100: '#fee2e2', 200: '#fecaca', 300: '#fca5a5', 400: '#f87171', 500: '#ef4444', 600: '#dc2626', 700: '#b91c1c', 800: '#991b1b', 900: '#7f1d1d', 950: '#450a0a', }, orange: { 50: '#fff7ed', 100: '#ffedd5', 200: '#fed7aa', 300: '#fdba74', 400: '#fb923c', 500: '#f97316', 600: '#ea580c', 700: '#c2410c', 800: '#9a3412', 900: '#7c2d12', 950: '#431407', }, amber: { 50: '#fffbeb', 100: '#fef3c7', 200: '#fde68a', 300: '#fcd34d', 400: '#fbbf24', 500: '#f59e0b', 600: '#d97706', 700: '#b45309', 800: '#92400e', 900: '#78350f', 950: '#451a03', }, yellow: { 50: '#fefce8', 100: '#fef9c3', 200: '#fef08a', 300: '#fde047', 400: '#facc15', 500: '#eab308', 600: '#ca8a04', 700: '#a16207', 800: '#854d0e', 900: '#713f12', 950: '#422006', }, teal: { 50: '#f0fdfa', 100: '#ccfbf1', 200: '#99f6e4', 300: '#5eead4', 400: '#2dd4bf', 500: '#14b8a6', 600: '#0d9488', 700: '#0f766e', 800: '#115e59', 900: '#134e4a', 950: '#042f2e', }, cyan: { 50: '#ecfeff', 100: '#cffafe', 200: '#a5f3fc', 300: '#67e8f9', 400: '#22d3ee', 500: '#06b6d4', 600: '#0891b2', 700: '#0e7490', 800: '#155e75', 900: '#164e63', 950: '#083344', }, sky: { 50: '#f0f9ff', 100: '#e0f2fe', 200: '#bae6fd', 300: '#7dd3fc', 400: '#38bdf8', 500: '#0ea5e9', 600: '#0284c7', 700: '#0369a1', 800: '#075985', 900: '#0c4a6e', 950: '#082f49', }, blue: { 50: '#eff6ff', 100: '#dbeafe', 200: '#bfdbfe', 300: '#93c5fd', 400: '#60a5fa', 500: '#3b82f6', 600: '#2563eb', 700: '#1d4ed8', 800: '#1e40af', 900: '#1e3a8a', 950: '#172554', }, indigo: { 50: '#eef2ff', 100: '#e0e7ff', 200: '#c7d2fe', 300: '#a5b4fc', 400: '#818cf8', 500: '#6366f1', 600: '#4f46e5', 700: '#4338ca', 800: '#3730a3', 900: '#312e81', 950: '#1e1b4b', }, violet: { 50: '#f5f3ff', 100: '#ede9fe', 200: '#ddd6fe', 300: '#c4b5fd', 400: '#a78bfa', 500: '#8b5cf6', 600: '#7c3aed', 700: '#6d28d9', 800: '#5b21b6', 900: '#4c1d95', 950: '#2e1065', }, purple: { 50: '#faf5ff', 100: '#f3e8ff', 200: '#e9d5ff', 300: '#d8b4fe', 400: '#c084fc', 500: '#a855f7', 600: '#9333ea', 700: '#7e22ce', 800: '#6b21a8', 900: '#581c87', 950: '#3b0764', }, fuchsia: { 50: '#fdf4ff', 100: '#fae8ff', 200: '#f5d0fe', 300: '#f0abfc', 400: '#e879f9', 500: '#d946ef', 600: '#c026d3', 700: '#a21caf', 800: '#86198f', 900: '#701a75', 950: '#4a044e', }, pink: { 50: '#fdf2f8', 100: '#fce7f3', 200: '#fbcfe8', 300: '#f9a8d4', 400: '#f472b6', 500: '#ec4899', 600: '#db2777', 700: '#be185d', 800: '#9d174d', 900: '#831843', 950: '#500724', }, rose: { 50: '#fff1f2', 100: '#ffe4e6', 200: '#fecdd3', 300: '#fda4af', 400: '#fb7185', 500: '#f43f5e', 600: '#e11d48', 700: '#be123c', 800: '#9f1239', 900: '#881337', 950: '#4c0519', }, slate: { 50: '#f8fafc', 100: '#f1f5f9', 200: '#e2e8f0', 300: '#cbd5e1', 400: '#94a3b8', 500: '#64748b', 600: '#475569', 700: '#334155', 800: '#1e293b', 900: '#0f172a', 950: '#020617', }, gray: { 50: '#f9fafb', 100: '#f3f4f6', 200: '#e5e7eb', 300: '#d1d5db', 400: '#9ca3af', 500: '#6b7280', 600: '#4b5563', 700: '#374151', 800: '#1f2937', 900: '#111827', 950: '#030712', }, zinc: { 50: '#fafafa', 100: '#f4f4f5', 200: '#e4e4e7', 300: '#d4d4d8', 400: '#a1a1aa', 500: '#71717a', 600: '#52525b', 700: '#3f3f46', 800: '#27272a', 900: '#18181b', 950: '#09090b', }, neutral: { 50: '#fafafa', 100: '#f5f5f5', 200: '#e5e5e5', 300: '#d4d4d4', 400: '#a3a3a3', 500: '#737373', 600: '#525252', 700: '#404040', 800: '#262626', 900: '#171717', 950: '#0a0a0a', }, stone: { 50: '#fafaf9', 100: '#f5f5f4', 200: '#e7e5e4', 300: '#d6d3d1', 400: '#a8a29e', 500: '#78716c', 600: '#57534e', 700: '#44403c', 800: '#292524', 900: '#1c1917', 950: '#0c0a09', }, }, semantic: { transitionDuration: '0.2s', focusRing: { width: '1px', style: 'solid', color: '{primary.color}', offset: '2px', shadow: 'none', }, disabledOpacity: '0.6', iconSize: '1rem', anchorGutter: '2px', primary: { 50: '#eff6ff', 100: '#dbeafe', 200: '#bfdbfe', 300: '#93c5fd', 400: '#60a5fa', 500: '#3b82f6', 600: '#2563eb', 700: '#1d4ed8', 800: '#1e40af', 900: '#1e3a8a', 950: '#172554', }, formField: { paddingX: '0.75rem', paddingY: '0.5rem', sm: { fontSize: '0.875rem', paddingX: '0.625rem', paddingY: '0.375rem', }, lg: { fontSize: '1.125rem', paddingX: '0.875rem', paddingY: '0.625rem', }, borderRadius: '{border.radius.md}', focusRing: { width: '0', style: 'none', color: 'transparent', offset: '0', shadow: 'none', }, transitionDuration: '{transition.duration}', }, list: { padding: '0.25rem 0.25rem', gap: '2px', header: { padding: '0.5rem 1rem 0.25rem 1rem', }, option: { padding: '0.5rem 0.75rem', borderRadius: '{border.radius.sm}', }, optionGroup: { padding: '0.5rem 0.75rem', fontWeight: '600', }, }, content: { borderRadius: '{border.radius.md}', }, mask: { transitionDuration: '0.15s', }, navigation: { list: { padding: '0.25rem 0.25rem', gap: '2px', }, item: { padding: '0.5rem 0.75rem', borderRadius: '{border.radius.sm}', gap: '0.5rem', }, submenuLabel: { padding: '0.5rem 0.75rem', fontWeight: '600', }, submenuIcon: { size: '0.875rem', }, }, overlay: { select: { borderRadius: '{border.radius.md}', shadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1)', }, popover: { borderRadius: '{border.radius.md}', padding: '0.75rem', shadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1)', }, modal: { borderRadius: '{border.radius.xl}', padding: '1.25rem', shadow: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1)', }, navigation: { shadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1)', }, }, colorScheme: { light: { surface: { 0: '#ffffff', 50: '#f8fafc', 100: '#f1f5f9', 200: '#e2e8f0', 300: '#cbd5e1', 400: '#94a3b8', 500: '#64748b', 600: '#475569', 700: '#334155', 800: '#1e293b', 900: '#0f172a', 950: '#020617', }, primary: { color: '{primary.500}', contrastColor: '#ffffff', hoverColor: '{primary.600}', activeColor: '{primary.700}', }, highlight: { background: '{primary.50}', focusBackground: '{primary.100}', color: '{primary.700}', focusColor: '{primary.800}', }, mask: { background: 'rgba(0,0,0,0.4)', color: '{surface.200}', }, formField: { background: '{surface.0}', disabledBackground: '{surface.200}', filledBackground: '{surface.50}', filledHoverBackground: '{surface.50}', filledFocusBackground: '{surface.50}', borderColor: '{surface.300}', hoverBorderColor: '{surface.400}', focusBorderColor: '{primary.color}', invalidBorderColor: '{red.400}', color: '{surface.700}', disabledColor: '{surface.500}', placeholderColor: '{surface.500}', invalidPlaceholderColor: '{red.600}', floatLabelColor: '{surface.500}', floatLabelFocusColor: '{primary.600}', floatLabelActiveColor: '{surface.500}', floatLabelInvalidColor: '{form.field.invalid.placeholder.color}', iconColor: '{surface.400}', shadow: '0 0 #0000, 0 0 #0000, 0 1px 2px 0 rgba(18, 18, 23, 0.05)', }, text: { color: '{surface.800}', hoverColor: '{surface.900}', mutedColor: '{surface.500}', hoverMutedColor: '{surface.600}', }, content: { background: '{surface.0}', hoverBackground: '{surface.100}', borderColor: '{surface.200}', color: '{text.color}', hoverColor: '{text.hover.color}', }, overlay: { select: { background: '{surface.0}', borderColor: '{surface.200}', color: '{text.color}', }, popover: { background: '{surface.0}', borderColor: '{surface.200}', color: '{text.color}', }, modal: { background: '{surface.0}', borderColor: '{surface.200}', color: '{text.color}', }, }, list: { option: { focusBackground: '{surface.100}', selectedBackground: '{highlight.background}', selectedFocusBackground: '{highlight.focus.background}', color: '{text.color}', focusColor: '{text.hover.color}', selectedColor: '{highlight.color}', selectedFocusColor: '{highlight.focus.color}', icon: { color: '{surface.400}', focusColor: '{surface.500}', }, }, optionGroup: { background: 'transparent', color: '{text.muted.color}', }, }, navigation: { item: { focusBackground: '{surface.100}', activeBackground: '{surface.100}', color: '{text.color}', focusColor: '{text.hover.color}', activeColor: '{text.hover.color}', icon: { color: '{surface.400}', focusColor: '{surface.500}', activeColor: '{surface.500}', }, }, submenuLabel: { background: 'transparent', color: '{text.muted.color}', }, submenuIcon: { color: '{surface.400}', focusColor: '{surface.500}', activeColor: '{surface.500}', }, }, }, dark: { surface: { 0: '#ffffff', 50: '#fafafa', 100: '#f4f4f5', 200: '#e4e4e7', 300: '#d4d4d8', 400: '#a1a1aa', 500: '#71717a', 600: '#52525b', 700: '#3f3f46', 800: '#27272a', 900: '#18181b', 950: '#09090b', }, primary: { color: '{primary.400}', contrastColor: '{surface.900}', hoverColor: '{primary.300}', activeColor: '{primary.200}', }, highlight: { background: 'color-mix(in srgb, {primary.400}, transparent 84%)', focusBackground: 'color-mix(in srgb, {primary.400}, transparent 76%)', color: 'rgba(255,255,255,.87)', focusColor: 'rgba(255,255,255,.87)', }, mask: { background: 'rgba(0,0,0,0.6)', color: '{surface.200}', }, formField: { background: '{surface.950}', disabledBackground: '{surface.700}', filledBackground: '{surface.800}', filledHoverBackground: '{surface.800}', filledFocusBackground: '{surface.800}', borderColor: '{surface.600}', hoverBorderColor: '{surface.500}', focusBorderColor: '{primary.color}', invalidBorderColor: '{red.300}', color: '{surface.0}', disabledColor: '{surface.400}', placeholderColor: '{surface.400}', invalidPlaceholderColor: '{red.400}', floatLabelColor: '{surface.400}', floatLabelFocusColor: '{primary.color}', floatLabelActiveColor: '{surface.400}', floatLabelInvalidColor: '{form.field.invalid.placeholder.color}', iconColor: '{surface.400}', shadow: '0 0 #0000, 0 0 #0000, 0 1px 2px 0 rgba(18, 18, 23, 0.05)', }, text: { color: '{surface.0}', hoverColor: '{surface.0}', mutedColor: '{surface.400}', hoverMutedColor: '{surface.300}', }, content: { background: '{surface.900}', hoverBackground: '{surface.800}', borderColor: '{surface.700}', color: '{text.color}', hoverColor: '{text.hover.color}', }, overlay: { select: { background: '{surface.900}', borderColor: '{surface.700}', color: '{text.color}', }, popover: { background: '{surface.900}', borderColor: '{surface.700}', color: '{text.color}', }, modal: { background: '{surface.900}', borderColor: '{surface.700}', color: '{text.color}', }, }, list: { option: { focusBackground: '{surface.800}', selectedBackground: '{highlight.background}', selectedFocusBackground: '{highlight.focus.background}', color: '{text.color}', focusColor: '{text.hover.color}', selectedColor: '{highlight.color}', selectedFocusColor: '{highlight.focus.color}', icon: { color: '{surface.500}', focusColor: '{surface.400}', }, }, optionGroup: { background: 'transparent', color: '{text.muted.color}', }, }, navigation: { item: { focusBackground: '{surface.800}', activeBackground: '{surface.800}', color: '{text.color}', focusColor: '{text.hover.color}', activeColor: '{text.hover.color}', icon: { color: '{surface.500}', focusColor: '{surface.400}', activeColor: '{surface.400}', }, }, submenuLabel: { background: 'transparent', color: '{text.muted.color}', }, submenuIcon: { color: '{surface.500}', focusColor: '{surface.400}', activeColor: '{surface.400}', }, }, }, }, }, components: { accordion: { header: { borderRadius: '{content.border.radius}', borderColor: '{content.border.color}', background: '{surface.100}', hoverBackground: '{surface.200}', activeBackground: '{surface.200}', activeHoverBackground: '{surface.200}', }, content: { padding: '0.5rem 0.25rem', }, }, autocomplete: { option: { padding: '0.2rem 0.5rem', }, }, card: { root: { background: '{surface.100}', }, body: { padding: '0', }, }, fieldset: { legend: { padding: '0 0.25rem 0.25rem 0.25rem', }, }, listbox: { option: { padding: '0.2rem 0.5rem', }, }, menubar: { root: { borderColor: 'transparent', }, }, panel: { root: { background: '{surface.100}', }, content: { padding: '0', }, }, tag: { root: { fontSize: '0.8rem', fontWeight: '600', padding: '0.15rem 0.5rem', gap: '0.25rem', borderRadius: '{content.border.radius}', roundedBorderRadius: '{border.radius.xl}', }, icon: { size: '0.5rem', }, colorScheme: { light: { primary: { background: '{primary.100}', color: '{primary.700}', }, secondary: { background: '{surface.500}', color: '{surface.0}', }, success: { background: '{green.100}', color: '{green.700}', }, info: { background: '{sky.100}', color: '{sky.700}', }, warn: { background: '{orange.100}', color: '{orange.700}', }, danger: { background: '{red.100}', color: '{red.700}', }, contrast: { background: '{surface.950}', color: '{surface.0}', }, }, dark: { primary: { background: 'color-mix(in srgb, {primary.500}, transparent 84%)', color: '{primary.300}', }, secondary: { background: '{surface.800}', color: '{surface.300}', }, success: { background: 'color-mix(in srgb, {green.500}, transparent 84%)', color: '{green.300}', }, info: { background: 'color-mix(in srgb, {sky.500}, transparent 84%)', color: '{sky.300}', }, warn: { background: 'color-mix(in srgb, {orange.500}, transparent 84%)', color: '{orange.300}', }, danger: { background: 'color-mix(in srgb, {red.500}, transparent 84%)', color: '{red.300}', }, contrast: { background: '{surface.0}', color: '{surface.950}', }, }, }, }, timeline: { event: { minHeight: '2.5rem', }, }, }, }), }, }; // SPDX-FileCopyrightText: Fondation RERO+ // SPDX-License-Identifier: AGPL-3.0-or-later const CONFIG = { MESSAGE_LIFE: 5000, // Message lifetime in ms DEFAULT_SELECT_SCROLL_HEIGHT: '50vh', }; // SPDX-FileCopyrightText: Fondation RERO+ // SPDX-License-Identifier: AGPL-3.0-or-later class ReadMoreComponent { text = input.required(...(ngDevMode ? [{ debugName: "text" }] : /* istanbul ignore next */ [])); limit = input(50, ...(ngDevMode ? [{ debugName: "limit" }] : /* istanbul ignore next */ [])); unit = input('word', ...(ngDevMode ? [{ debugName: "unit" }] : /* istanbul ignore next */ [])); trailing = input('…', ...(ngDevMode ? [{ debugName: "trailing" }] : /* istanbul ignore next */ [])); showMoreLabel = input(_('show more'), ...(ngDevMode ? [{ debugName: "showMoreLabel" }] : /* istanbul ignore next */ [])); showLessLabel = input(_('show less'), ...(ngDevMode ? [{ debugName: "showLessLabel" }] : /* istanbul ignore next */ [])); showMore = linkedSignal(() => this.showMoreActivated(), ...(ngDevMode ? [{ debugName: "showMore" }] : /* istanbul ignore next */ [])); textDisplay = computed(() => this.processText(this.originalText(), this.showMore()), ...(ngDevMode ? [{ debugName: "textDisplay" }] : /* istanbul ignore next */ [])); showMoreLinkLabel = computed(() => (this.showMore() ? this.showMoreLabel() : this.showLessLabel()), ...(ngDevMode ? [{ debugName: "showMoreLinkLabel" }] : /* istanbul ignore next */ [])); showMoreActivated = computed(() => this.countElement() > this.limit(), ...(ngDevMode ? [{ debugName: "showMoreActivated" }] : /* istanbul ignore next */ [])); originalText = computed(() => this.text().replace(/<.*?>/g, ''), ...(ngDevMode ? [{ debugName: "originalText" }] : /* istanbul ignore next