UNPKG

@rero/ng-core

Version:

RERO angular core library.

1 lines 731 kB
{"version":3,"file":"rero-ng-core.mjs","sources":["../../../../projects/rero/ng-core/src/lib/core/pipe/nl2br/nl2br.pipe.ts","../../../../projects/rero/ng-core/src/lib/core/pipe/filesize/filesize.pipe.ts","../../../../projects/rero/ng-core/src/lib/core/pipe/truncate-text/truncate-text.pipe.ts","../../../../projects/rero/ng-core/src/lib/core/utils/utils.ts","../../../../projects/rero/ng-core/src/lib/core/pipe/ucfirst/ucfirst.pipe.ts","../../../../projects/rero/ng-core/src/lib/core/pipe/markdown/markdown.pipe.ts","../../../../projects/rero/ng-core/src/lib/core/pipe/callback-array-filter/callback-array-filter.pipe.ts","../../../../projects/rero/ng-core/src/lib/core/validator/time.validator.ts","../../../../projects/rero/ng-core/src/lib/core/validator/unique.validator.ts","../../../../projects/rero/ng-core/src/lib/core/config/primeng-config.ts","../../../../projects/rero/ng-core/src/lib/core/config/config.ts","../../../../projects/rero/ng-core/src/lib/core/component/read-more/read-more.component.ts","../../../../projects/rero/ng-core/src/lib/core/component/dialog/dialog.component.ts","../../../../projects/rero/ng-core/src/lib/core/component/error/error.component.ts","../../../../projects/rero/ng-core/src/lib/core/component/error/error.interface.ts","../../../../projects/rero/ng-core/src/lib/core/component/search-input/search-input.component.ts","../../../../projects/rero/ng-core/src/lib/core/component/search-input/search-input.component.html","../../../../projects/rero/ng-core/src/lib/core/component/abstract-can-deactivate/abstract-can-deactivate.component.ts","../../../../projects/rero/ng-core/src/lib/record/editor/utils/utils.ts","../../../../projects/rero/ng-core/src/lib/record/service/api/api.service.ts","../../../../projects/rero/ng-core/src/lib/record/service/record-handle-error/record-handle-error.service.ts","../../../../projects/rero/ng-core/src/lib/record/service/record/record.service.ts","../../../../projects/rero/ng-core/src/lib/formly/config/extensions.ts","../../../../projects/rero/ng-core/src/lib/formly/types/date-picker/date-picker.component.ts","../../../../projects/rero/ng-core/src/lib/formly/types/input/input.component.ts","../../../../projects/rero/ng-core/src/lib/formly/types/markdown/markdown.component.ts","../../../../projects/rero/ng-core/src/lib/formly/service/translate-label.service.ts","../../../../projects/rero/ng-core/src/lib/formly/types/multi-checkbox/multi-checkbox.component.ts","../../../../projects/rero/ng-core/src/lib/formly/types/multi-select/multi-select.component.ts","../../../../projects/rero/ng-core/src/lib/formly/types/multischema/multischema.component.ts","../../../../projects/rero/ng-core/src/lib/formly/types/object/object.component.ts","../../../../projects/rero/ng-core/src/lib/formly/types/object/object.component.html","../../../../projects/rero/ng-core/src/lib/formly/types/password-generator/password-generator.component.ts","../../../../projects/rero/ng-core/src/lib/formly/types/radio-button/radio-button.component.ts","../../../../projects/rero/ng-core/src/lib/formly/types/remote-autocomplete/remote-autocomplete.service.ts","../../../../projects/rero/ng-core/src/lib/formly/types/remote-autocomplete/remote-autocomplete.component.ts","../../../../projects/rero/ng-core/src/lib/formly/types/select/select.component.ts","../../../../projects/rero/ng-core/src/lib/formly/types/switch/switch.component.ts","../../../../projects/rero/ng-core/src/lib/formly/types/textarea/textarea.component.ts","../../../../projects/rero/ng-core/src/lib/formly/types/tree-select/tree-select.component.ts","../../../../projects/rero/ng-core/src/lib/formly/validator/email.validator.ts","../../../../projects/rero/ng-core/src/lib/formly/component/dropdown-label-editor/dropdown-label-editor.component.ts","../../../../projects/rero/ng-core/src/lib/formly/component/dropdown-label-editor/dropdown-label-editor.component.html","../../../../projects/rero/ng-core/src/lib/formly/component/label/label.component.ts","../../../../projects/rero/ng-core/src/lib/formly/component/label/label.component.html","../../../../projects/rero/ng-core/src/lib/formly/wrappers/card-wrapper/card-wrapper.component.ts","../../../../projects/rero/ng-core/src/lib/formly/wrappers/form-field-wrapper/form-field-wrapper.component.ts","../../../../projects/rero/ng-core/src/lib/formly/wrappers/hide-wrapper/hide-wrapper.component.ts","../../../../projects/rero/ng-core/src/lib/formly/types/array/array.component.ts","../../../../projects/rero/ng-core/src/lib/formly/types/array/array.component.html","../../../../projects/rero/ng-core/src/lib/formly/config/formly-config.ts","../../../../projects/rero/ng-core/src/lib/core/service/core-config/core-config.service.ts","../../../../projects/rero/ng-core/src/lib/translate/service/translate/translate-service.ts","../../../../projects/rero/ng-core/src/lib/core/service/page-title-strategy/page-title-strategy.ts","../../../../projects/rero/ng-core/src/lib/core/core.provider.ts","../../../../projects/rero/ng-core/src/lib/core/directive/katex.directive.ts","../../../../projects/rero/ng-core/src/lib/core/route-data-types.interface.ts","../../../../projects/rero/ng-core/src/lib/core/service/crypto-js/crypto-js.service.ts","../../../../projects/rero/ng-core/src/lib/core/service/local-storage/local-storage.service.ts","../../../../projects/rero/ng-core/src/lib/core/guard/component-can-deactivate.guard.ts","../../../../projects/rero/ng-core/src/lib/core/service/http-pending/http-pending.service.ts","../../../../projects/rero/ng-core/src/lib/core/interceptor/http-pending.interceptor.ts","../../../../projects/rero/ng-core/src/lib/core/index.ts","../../../../projects/rero/ng-core/src/lib/formly/component/add-field-editor/add-field-editor.component.ts","../../../../projects/rero/ng-core/src/lib/formly/component/add-field-editor/add-field-editor.component.html","../../../../projects/rero/ng-core/src/lib/formly/index.ts","../../../../projects/rero/ng-core/src/lib/model/action-status.interface.ts","../../../../projects/rero/ng-core/src/lib/model/index.ts","../../../../projects/rero/ng-core/src/lib/translate/pipe/date-translate/date-translate-pipe.ts","../../../../projects/rero/ng-core/src/lib/translate/service/translate-language/translate-language.service.ts","../../../../projects/rero/ng-core/src/lib/translate/pipe/translate-language/translate-language.pipe.ts","../../../../projects/rero/ng-core/src/lib/translate/loader/translate-loader.ts","../../../../projects/rero/ng-core/src/lib/translate/index.ts","../../../../projects/rero/ng-core/src/lib/record/pipe/get-record.pipe.ts","../../../../projects/rero/ng-core/src/lib/record/record-search-utils.ts","../../../../projects/rero/ng-core/src/lib/record/component/search/store/features/with-aggregations.feature.ts","../../../../projects/rero/ng-core/src/lib/record/component/detail/default-detail/default-detail.component.ts","../../../../projects/rero/ng-core/src/lib/record/component/search/record-search/record-search-result/default-search-result/default-search-result.component.ts","../../../../projects/rero/ng-core/src/lib/record/component/search/store/features/with-config.feature.ts","../../../../projects/rero/ng-core/src/lib/record/component/search/store/features/with-results.feature.ts","../../../../projects/rero/ng-core/src/lib/record/component/search/store/features/with-search-params.feature.ts","../../../../projects/rero/ng-core/src/lib/record/component/search/store/record-search.store.ts","../../../../projects/rero/ng-core/src/lib/record/service/record-ui/record-ui.service.ts","../../../../projects/rero/ng-core/src/lib/record/component/search/record-search/aggregation/buckets/buckets.component.ts","../../../../projects/rero/ng-core/src/lib/record/component/search/record-search/aggregation/buckets/buckets.component.html","../../../../projects/rero/ng-core/src/lib/record/component/search/record-search/aggregation/slider/slider.component.ts","../../../../projects/rero/ng-core/src/lib/record/component/search/record-search/aggregation/slider/slider.component.html","../../../../projects/rero/ng-core/src/lib/record/component/search/record-search/aggregation/date-range/date-range.component.ts","../../../../projects/rero/ng-core/src/lib/record/component/search/record-search/aggregation/date-range/date-range.component.html","../../../../projects/rero/ng-core/src/lib/record/component/search/record-search/aggregation/aggregation.component.ts","../../../../projects/rero/ng-core/src/lib/record/component/search/record-search/aggregation/aggregation.component.html","../../../../projects/rero/ng-core/src/lib/record/component/search/record-search/aggregation/list-filters/list-filters.component.ts","../../../../projects/rero/ng-core/src/lib/record/component/search/record-search/aggregation/list-filters/list-filters.component.html","../../../../projects/rero/ng-core/src/lib/record/component/search/record-search/export-button/export-button.component.ts","../../../../projects/rero/ng-core/src/lib/record/component/search/record-search/export-button/export-button.component.html","../../../../projects/rero/ng-core/src/lib/record/component/search/record-search/menu-sort/menu-sort.component.ts","../../../../projects/rero/ng-core/src/lib/record/component/search/record-search/menu-sort/menu-sort.component.html","../../../../projects/rero/ng-core/src/lib/record/component/search/record-search/paginator/paginator.component.ts","../../../../projects/rero/ng-core/src/lib/record/component/search/record-search/paginator/paginator.component.html","../../../../projects/rero/ng-core/src/lib/record/component/search/record-search/record-search-result/record-search-result.component.ts","../../../../projects/rero/ng-core/src/lib/record/component/search/record-search/record-search-result/record-search-result.component.html","../../../../projects/rero/ng-core/src/lib/record/component/search/record-search/search-filters/search-filters.component.ts","../../../../projects/rero/ng-core/src/lib/record/component/search/record-search/search-filters/search-filters.component.html","../../../../projects/rero/ng-core/src/lib/record/component/search/record-search/search-tabs/search-tabs.component.ts","../../../../projects/rero/ng-core/src/lib/record/component/search/record-search/search-tabs/search-tabs.component.html","../../../../projects/rero/ng-core/src/lib/record/component/search/record-search/record-search.component.ts","../../../../projects/rero/ng-core/src/lib/record/component/search/record-search/record-search.component.html","../../../../projects/rero/ng-core/src/lib/record/component/search/record-search-page.component.ts","../../../../projects/rero/ng-core/src/lib/record/component/search/record-search-page.component.html","../../../../projects/rero/ng-core/src/lib/record/component/detail/detail-button/detail-button.component.ts","../../../../projects/rero/ng-core/src/lib/record/component/detail/detail-button/detail-button.component.html","../../../../projects/rero/ng-core/src/lib/record/component/detail/detail.component.ts","../../../../projects/rero/ng-core/src/lib/record/component/detail/detail.component.html","../../../../projects/rero/ng-core/src/lib/record/editor/services/jsonschema/jsonschema.service.ts","../../../../projects/rero/ng-core/src/lib/record/editor/services/template/templates.service.ts","../../../../projects/rero/ng-core/src/lib/record/editor/component/load-template-form/load-template-form.component.ts","../../../../projects/rero/ng-core/src/lib/record/editor/component/load-template-form/load-template-form.component.html","../../../../projects/rero/ng-core/src/lib/record/editor/component/save-template-form/save-template-form.component.ts","../../../../projects/rero/ng-core/src/lib/record/editor/component/save-template-form/save-template-form.component.html","../../../../projects/rero/ng-core/src/lib/record/editor/component/editor/editor.component.ts","../../../../projects/rero/ng-core/src/lib/record/editor/component/editor/editor.component.html","../../../../projects/rero/ng-core/src/lib/record/record.routes.ts","../../../../projects/rero/ng-core/src/lib/record/component/autocomplete/search-autocomplete.component.ts","../../../../projects/rero/ng-core/src/lib/record/model/result-item.interface.ts","../../../../projects/rero/ng-core/src/lib/record/component/search/model/aggregations-filter.interface.ts","../../../../projects/rero/ng-core/src/lib/record/model/record-search.interface.ts","../../../../projects/rero/ng-core/src/lib/record/index.ts","../../../../projects/rero/ng-core/src/public-api.ts","../../../../projects/rero/ng-core/src/rero-ng-core.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Fondation RERO+\n// SPDX-License-Identifier: AGPL-3.0-or-later\nimport { inject, Pipe, PipeTransform } from '@angular/core';\nimport { DomSanitizer, SafeHtml } from '@angular/platform-browser';\n\n/**\n * Pipe for converting carriage returns to <br> html entities.\n */\n@Pipe({ name: 'nl2br' })\nexport class Nl2brPipe implements PipeTransform {\n protected sanitizer: DomSanitizer = inject(DomSanitizer);\n\n /**\n * Returns transformed value containing <br> entities.\n *\n * @param value Value to transform.\n * @return Transformed value.\n */\n transform(value: string): SafeHtml {\n if (!value) {\n return this.sanitizer.bypassSecurityTrustHtml('');\n }\n return this.sanitizer.bypassSecurityTrustHtml(value.replace(/\\r\\n?|\\n/g, '<br>\\n'));\n }\n}\n","// SPDX-FileCopyrightText: Fondation RERO+\n// SPDX-License-Identifier: AGPL-3.0-or-later\nimport { Pipe, PipeTransform } from '@angular/core';\n\n/**\n * Get human readable file size.\n */\n@Pipe({ name: 'filesize' })\nexport class FilesizePipe implements PipeTransform {\n /**\n * Transform size to a human readable size.\n *\n * @param size Size of file.\n * @param precision Number of decimals.\n * @return Human readable file size.\n */\n transform(size: number, precision = 2): string {\n let i = -1;\n const byteUnits = ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];\n do {\n size /= 1024;\n i++;\n } while (size > 1024);\n\n return [Math.max(size, 0.1).toFixed(precision), byteUnits[i]].join(' ');\n }\n}\n","// SPDX-FileCopyrightText: Fondation RERO+\n// SPDX-License-Identifier: AGPL-3.0-or-later\nimport { Pipe, PipeTransform } from '@angular/core';\n\n/**\n * Pipe for truncating text.\n */\n@Pipe({ name: 'truncateText' })\nexport class TruncateTextPipe implements PipeTransform {\n /**\n * Truncate text.\n *\n * @param value Text to truncate.\n * @param limit Limit after which the text is truncated.\n * @param trail Trailing chars\n * @param type Word or Char type\n * @return Truncated string\n */\n transform(value: string, limit = 40, trail = '…', type: 'word' | 'char' = 'word'): string {\n let result = value || '';\n\n if (type === 'char' && value) {\n if (value.length < limit) {\n return value;\n } else {\n return value.substring(0, limit) + trail;\n }\n }\n\n if (type === 'word' && value) {\n const words = value.split(/\\s+/);\n if (words.length > Math.abs(limit)) {\n if (limit < 0) {\n limit *= -1;\n result = trail + words.slice(words.length - limit).join(' ');\n } else {\n result = words.slice(0, limit).join(' ') + trail;\n }\n }\n }\n\n return result;\n }\n}\n","// SPDX-FileCopyrightText: Fondation RERO+\n// SPDX-License-Identifier: AGPL-3.0-or-later\nexport function extractIdOnRef(ref: string): string {\n if (!ref) {\n throw new Error('extractIdOnRef: ref is null or empty');\n }\n\n const match = /.*\\/([^/]+)$/.exec(ref);\n\n if (!match) {\n throw new Error(`extractIdOnRef: unable to extract id from ref \"${ref}\"`);\n }\n\n return match[1];\n}\n\nexport function cleanDictKeys<T extends Record<string, unknown>>(data: T): Partial<T> {\n return Object.fromEntries(\n Object.entries(data).filter(([, value]) => {\n if (value == null) {\n return false;\n }\n\n if (typeof value === 'string' || Array.isArray(value)) {\n return value.length > 0;\n }\n\n return true;\n }),\n ) as Partial<T>;\n}\n\nexport function capitalize(value: string): string {\n return value.charAt(0).toUpperCase() + value.slice(1);\n}\n\nexport function removeChars(value: string, chars: string[] = ['\"']): string {\n const re = new RegExp('[' + chars.join('') + ']', 'gi');\n return value.replace(re, '');\n}\n","// SPDX-FileCopyrightText: Fondation RERO+\n// SPDX-License-Identifier: AGPL-3.0-or-later\nimport { Pipe, PipeTransform } from '@angular/core';\nimport { capitalize } from '../../utils/utils';\n\n/**\n * Uppercase the first letter of the string.\n */\n@Pipe({ name: 'ucfirst' })\nexport class UpperCaseFirstPipe implements PipeTransform {\n /**\n * Uppercase the first letter of the given value.\n *\n * @param value Value to transform.\n * @return Transformed value.\n */\n transform(value: string): string {\n if (!value) {\n return value;\n }\n\n return capitalize(value);\n }\n}\n","// SPDX-FileCopyrightText: Fondation RERO+\n// SPDX-License-Identifier: AGPL-3.0-or-later\nimport { inject, Pipe, PipeTransform } from '@angular/core';\nimport { DomSanitizer, SafeHtml } from '@angular/platform-browser';\nimport { marked } from 'marked';\n\n/**\n * Pipe to transform markdown to html.\n */\n@Pipe({ name: 'markdown' })\nexport class MarkdownPipe implements PipeTransform {\n protected sanitizer: DomSanitizer = inject(DomSanitizer);\n\n /**\n * Transform markdown to HTML.\n *\n * @param value Markdown initial value.\n * @returns HTML corresponding to markdown.\n */\n transform(value: string): SafeHtml {\n const markValue: string = marked.parse(value, { gfm: true, breaks: false, async: false });\n return this.sanitizer.bypassSecurityTrustHtml(markValue);\n }\n}\n","// SPDX-FileCopyrightText: Fondation RERO+\n// SPDX-License-Identifier: AGPL-3.0-or-later\nimport { Pipe, PipeTransform } from '@angular/core';\n\n/**\n * Pipe for applying a callback function to filter array items.\n */\n@Pipe({ name: 'callbackArrayFilter' })\nexport class CallbackArrayFilterPipe implements PipeTransform {\n /**\n * Filter array items with the given callback function.\n *\n * @param items List of items.\n * @param callback Callback function to apply.\n * @return List of filtered values.\n */\n transform<T>(items: T[], callback?: (item: T) => boolean): T[] {\n if (items?.length) {\n if (!callback) {\n return items;\n } else {\n return items.filter((item) => callback(item));\n }\n }\n return [];\n }\n}\n","// SPDX-FileCopyrightText: Fondation RERO+\n// SPDX-License-Identifier: AGPL-3.0-or-later\nimport { AbstractControl, UntypedFormArray, ValidationErrors, ValidatorFn } from '@angular/forms';\nimport { DateTime } from 'luxon';\n\n// @dynamic\nexport class TimeValidator {\n static readonly FORMAT = 'hh:mm';\n\n /**\n * Allow to control if time interval limits are well formed : the end limit should be 'older' the start limit\n * @param start: the field name where to find the start limit value\n * @param end: the field name where to find the end limit value\n */\n static greaterThanValidator(start: string, end: string): ValidatorFn {\n return (control: AbstractControl): ValidationErrors | null => {\n const startTime = control.get(start);\n const endTime = control.get(end);\n if (control && startTime && endTime) {\n let isLessThan = false;\n const startDate = DateTime.fromFormat(startTime.value, TimeValidator.FORMAT);\n const endDate = DateTime.fromFormat(endTime.value, TimeValidator.FORMAT);\n if (\n startDate.toFormat(TimeValidator.FORMAT) !== '00:00' ||\n endDate.toFormat(TimeValidator.FORMAT) !== '00:00'\n ) {\n isLessThan = startDate >= endDate;\n }\n return isLessThan ? { lessThan: { value: isLessThan } } : null;\n }\n return null;\n };\n }\n\n static RangePeriodValidator(): ValidatorFn {\n return (control: AbstractControl): ValidationErrors | null => {\n if (control.value) {\n let isRangeLessThan = false;\n const times = control.get('times') as UntypedFormArray;\n if (control.get('is_open')?.value && times && times.value.length > 1) {\n const firstStartDate = DateTime.fromFormat(times.at(0).get('start_time')?.value, TimeValidator.FORMAT);\n const firstEndDate = DateTime.fromFormat(times.at(0).get('end_time')?.value, TimeValidator.FORMAT);\n const lastStartDate = DateTime.fromFormat(times.at(1).get('start_time')?.value, TimeValidator.FORMAT);\n const lastEndDate = DateTime.fromFormat(times.at(1).get('end_time')?.value, TimeValidator.FORMAT);\n if (firstStartDate > lastStartDate) {\n isRangeLessThan = firstStartDate <= lastStartDate || firstStartDate <= lastEndDate;\n } else {\n isRangeLessThan = lastStartDate <= firstEndDate || lastStartDate <= firstEndDate;\n }\n }\n return isRangeLessThan ? { rangeLessThan: { value: isRangeLessThan } } : null;\n }\n return null;\n };\n }\n}\n","// SPDX-FileCopyrightText: Fondation RERO+\n// SPDX-License-Identifier: AGPL-3.0-or-later\nimport { AbstractControl } from '@angular/forms';\nimport { RecordService } from '../../record/service/record/record.service';\n\n// @dynamic\nexport class UniqueValidator {\n static createValidator(recordService: RecordService, recordType: string, fieldName: string, excludePid?: string) {\n return (control: AbstractControl) => {\n return recordService.valueAlreadyExists(recordType, fieldName, control.value, excludePid);\n };\n }\n}\n","// SPDX-FileCopyrightText: Fondation RERO+\n// SPDX-License-Identifier: AGPL-3.0-or-later\n\nimport { definePreset } from '@primeuix/themes';\nimport Aura from '@primeuix/themes/aura';\n\nexport const primeNGConfig = {\n theme: {\n options: {\n // Layer order (lowest → highest priority). PrimeNG injects this @layer\n // declaration before styles.css, so \"primeng\" is established below\n // \"utilities\" — allowing Tailwind utility classes (ui:, core:) to\n // override PrimeNG component styles. Do not move \"utilities\" before\n // \"primeng\" or Tailwind overrides will stop working.\n cssLayer: {\n name: 'primeng',\n order: 'theme, base, primeng, utilities'\n },\n darkModeSelector: false,\n },\n preset: definePreset(Aura, {\n primitive: {\n borderRadius: {\n none: '0',\n xs: '2px',\n sm: '4px',\n md: '6px',\n lg: '8px',\n xl: '12px',\n },\n emerald: {\n 50: '#ecfdf5',\n 100: '#d1fae5',\n 200: '#a7f3d0',\n 300: '#6ee7b7',\n 400: '#34d399',\n 500: '#10b981',\n 600: '#059669',\n 700: '#047857',\n 800: '#065f46',\n 900: '#064e3b',\n 950: '#022c22',\n },\n green: {\n 50: '#f0fdf4',\n 100: '#dcfce7',\n 200: '#bbf7d0',\n 300: '#86efac',\n 400: '#4ade80',\n 500: '#22c55e',\n 600: '#16a34a',\n 700: '#15803d',\n 800: '#166534',\n 900: '#14532d',\n 950: '#052e16',\n },\n lime: {\n 50: '#f7fee7',\n 100: '#ecfccb',\n 200: '#d9f99d',\n 300: '#bef264',\n 400: '#a3e635',\n 500: '#84cc16',\n 600: '#65a30d',\n 700: '#4d7c0f',\n 800: '#3f6212',\n 900: '#365314',\n 950: '#1a2e05',\n },\n red: {\n 50: '#fef2f2',\n 100: '#fee2e2',\n 200: '#fecaca',\n 300: '#fca5a5',\n 400: '#f87171',\n 500: '#ef4444',\n 600: '#dc2626',\n 700: '#b91c1c',\n 800: '#991b1b',\n 900: '#7f1d1d',\n 950: '#450a0a',\n },\n orange: {\n 50: '#fff7ed',\n 100: '#ffedd5',\n 200: '#fed7aa',\n 300: '#fdba74',\n 400: '#fb923c',\n 500: '#f97316',\n 600: '#ea580c',\n 700: '#c2410c',\n 800: '#9a3412',\n 900: '#7c2d12',\n 950: '#431407',\n },\n amber: {\n 50: '#fffbeb',\n 100: '#fef3c7',\n 200: '#fde68a',\n 300: '#fcd34d',\n 400: '#fbbf24',\n 500: '#f59e0b',\n 600: '#d97706',\n 700: '#b45309',\n 800: '#92400e',\n 900: '#78350f',\n 950: '#451a03',\n },\n yellow: {\n 50: '#fefce8',\n 100: '#fef9c3',\n 200: '#fef08a',\n 300: '#fde047',\n 400: '#facc15',\n 500: '#eab308',\n 600: '#ca8a04',\n 700: '#a16207',\n 800: '#854d0e',\n 900: '#713f12',\n 950: '#422006',\n },\n teal: {\n 50: '#f0fdfa',\n 100: '#ccfbf1',\n 200: '#99f6e4',\n 300: '#5eead4',\n 400: '#2dd4bf',\n 500: '#14b8a6',\n 600: '#0d9488',\n 700: '#0f766e',\n 800: '#115e59',\n 900: '#134e4a',\n 950: '#042f2e',\n },\n cyan: {\n 50: '#ecfeff',\n 100: '#cffafe',\n 200: '#a5f3fc',\n 300: '#67e8f9',\n 400: '#22d3ee',\n 500: '#06b6d4',\n 600: '#0891b2',\n 700: '#0e7490',\n 800: '#155e75',\n 900: '#164e63',\n 950: '#083344',\n },\n sky: {\n 50: '#f0f9ff',\n 100: '#e0f2fe',\n 200: '#bae6fd',\n 300: '#7dd3fc',\n 400: '#38bdf8',\n 500: '#0ea5e9',\n 600: '#0284c7',\n 700: '#0369a1',\n 800: '#075985',\n 900: '#0c4a6e',\n 950: '#082f49',\n },\n blue: {\n 50: '#eff6ff',\n 100: '#dbeafe',\n 200: '#bfdbfe',\n 300: '#93c5fd',\n 400: '#60a5fa',\n 500: '#3b82f6',\n 600: '#2563eb',\n 700: '#1d4ed8',\n 800: '#1e40af',\n 900: '#1e3a8a',\n 950: '#172554',\n },\n indigo: {\n 50: '#eef2ff',\n 100: '#e0e7ff',\n 200: '#c7d2fe',\n 300: '#a5b4fc',\n 400: '#818cf8',\n 500: '#6366f1',\n 600: '#4f46e5',\n 700: '#4338ca',\n 800: '#3730a3',\n 900: '#312e81',\n 950: '#1e1b4b',\n },\n violet: {\n 50: '#f5f3ff',\n 100: '#ede9fe',\n 200: '#ddd6fe',\n 300: '#c4b5fd',\n 400: '#a78bfa',\n 500: '#8b5cf6',\n 600: '#7c3aed',\n 700: '#6d28d9',\n 800: '#5b21b6',\n 900: '#4c1d95',\n 950: '#2e1065',\n },\n purple: {\n 50: '#faf5ff',\n 100: '#f3e8ff',\n 200: '#e9d5ff',\n 300: '#d8b4fe',\n 400: '#c084fc',\n 500: '#a855f7',\n 600: '#9333ea',\n 700: '#7e22ce',\n 800: '#6b21a8',\n 900: '#581c87',\n 950: '#3b0764',\n },\n fuchsia: {\n 50: '#fdf4ff',\n 100: '#fae8ff',\n 200: '#f5d0fe',\n 300: '#f0abfc',\n 400: '#e879f9',\n 500: '#d946ef',\n 600: '#c026d3',\n 700: '#a21caf',\n 800: '#86198f',\n 900: '#701a75',\n 950: '#4a044e',\n },\n pink: {\n 50: '#fdf2f8',\n 100: '#fce7f3',\n 200: '#fbcfe8',\n 300: '#f9a8d4',\n 400: '#f472b6',\n 500: '#ec4899',\n 600: '#db2777',\n 700: '#be185d',\n 800: '#9d174d',\n 900: '#831843',\n 950: '#500724',\n },\n rose: {\n 50: '#fff1f2',\n 100: '#ffe4e6',\n 200: '#fecdd3',\n 300: '#fda4af',\n 400: '#fb7185',\n 500: '#f43f5e',\n 600: '#e11d48',\n 700: '#be123c',\n 800: '#9f1239',\n 900: '#881337',\n 950: '#4c0519',\n },\n slate: {\n 50: '#f8fafc',\n 100: '#f1f5f9',\n 200: '#e2e8f0',\n 300: '#cbd5e1',\n 400: '#94a3b8',\n 500: '#64748b',\n 600: '#475569',\n 700: '#334155',\n 800: '#1e293b',\n 900: '#0f172a',\n 950: '#020617',\n },\n gray: {\n 50: '#f9fafb',\n 100: '#f3f4f6',\n 200: '#e5e7eb',\n 300: '#d1d5db',\n 400: '#9ca3af',\n 500: '#6b7280',\n 600: '#4b5563',\n 700: '#374151',\n 800: '#1f2937',\n 900: '#111827',\n 950: '#030712',\n },\n zinc: {\n 50: '#fafafa',\n 100: '#f4f4f5',\n 200: '#e4e4e7',\n 300: '#d4d4d8',\n 400: '#a1a1aa',\n 500: '#71717a',\n 600: '#52525b',\n 700: '#3f3f46',\n 800: '#27272a',\n 900: '#18181b',\n 950: '#09090b',\n },\n neutral: {\n 50: '#fafafa',\n 100: '#f5f5f5',\n 200: '#e5e5e5',\n 300: '#d4d4d4',\n 400: '#a3a3a3',\n 500: '#737373',\n 600: '#525252',\n 700: '#404040',\n 800: '#262626',\n 900: '#171717',\n 950: '#0a0a0a',\n },\n stone: {\n 50: '#fafaf9',\n 100: '#f5f5f4',\n 200: '#e7e5e4',\n 300: '#d6d3d1',\n 400: '#a8a29e',\n 500: '#78716c',\n 600: '#57534e',\n 700: '#44403c',\n 800: '#292524',\n 900: '#1c1917',\n 950: '#0c0a09',\n },\n },\n semantic: {\n transitionDuration: '0.2s',\n focusRing: {\n width: '1px',\n style: 'solid',\n color: '{primary.color}',\n offset: '2px',\n shadow: 'none',\n },\n disabledOpacity: '0.6',\n iconSize: '1rem',\n anchorGutter: '2px',\n primary: {\n 50: '#eff6ff',\n 100: '#dbeafe',\n 200: '#bfdbfe',\n 300: '#93c5fd',\n 400: '#60a5fa',\n 500: '#3b82f6',\n 600: '#2563eb',\n 700: '#1d4ed8',\n 800: '#1e40af',\n 900: '#1e3a8a',\n 950: '#172554',\n },\n formField: {\n paddingX: '0.75rem',\n paddingY: '0.5rem',\n sm: {\n fontSize: '0.875rem',\n paddingX: '0.625rem',\n paddingY: '0.375rem',\n },\n lg: {\n fontSize: '1.125rem',\n paddingX: '0.875rem',\n paddingY: '0.625rem',\n },\n borderRadius: '{border.radius.md}',\n focusRing: {\n width: '0',\n style: 'none',\n color: 'transparent',\n offset: '0',\n shadow: 'none',\n },\n transitionDuration: '{transition.duration}',\n },\n list: {\n padding: '0.25rem 0.25rem',\n gap: '2px',\n header: {\n padding: '0.5rem 1rem 0.25rem 1rem',\n },\n option: {\n padding: '0.5rem 0.75rem',\n borderRadius: '{border.radius.sm}',\n },\n optionGroup: {\n padding: '0.5rem 0.75rem',\n fontWeight: '600',\n },\n },\n content: {\n borderRadius: '{border.radius.md}',\n },\n mask: {\n transitionDuration: '0.15s',\n },\n navigation: {\n list: {\n padding: '0.25rem 0.25rem',\n gap: '2px',\n },\n item: {\n padding: '0.5rem 0.75rem',\n borderRadius: '{border.radius.sm}',\n gap: '0.5rem',\n },\n submenuLabel: {\n padding: '0.5rem 0.75rem',\n fontWeight: '600',\n },\n submenuIcon: {\n size: '0.875rem',\n },\n },\n overlay: {\n select: {\n borderRadius: '{border.radius.md}',\n shadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1)',\n },\n popover: {\n borderRadius: '{border.radius.md}',\n padding: '0.75rem',\n shadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1)',\n },\n modal: {\n borderRadius: '{border.radius.xl}',\n padding: '1.25rem',\n shadow: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1)',\n },\n navigation: {\n shadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1)',\n },\n },\n colorScheme: {\n light: {\n surface: {\n 0: '#ffffff',\n 50: '#f8fafc',\n 100: '#f1f5f9',\n 200: '#e2e8f0',\n 300: '#cbd5e1',\n 400: '#94a3b8',\n 500: '#64748b',\n 600: '#475569',\n 700: '#334155',\n 800: '#1e293b',\n 900: '#0f172a',\n 950: '#020617',\n },\n primary: {\n color: '{primary.500}',\n contrastColor: '#ffffff',\n hoverColor: '{primary.600}',\n activeColor: '{primary.700}',\n },\n highlight: {\n background: '{primary.50}',\n focusBackground: '{primary.100}',\n color: '{primary.700}',\n focusColor: '{primary.800}',\n },\n mask: {\n background: 'rgba(0,0,0,0.4)',\n color: '{surface.200}',\n },\n formField: {\n background: '{surface.0}',\n disabledBackground: '{surface.200}',\n filledBackground: '{surface.50}',\n filledHoverBackground: '{surface.50}',\n filledFocusBackground: '{surface.50}',\n borderColor: '{surface.300}',\n hoverBorderColor: '{surface.400}',\n focusBorderColor: '{primary.color}',\n invalidBorderColor: '{red.400}',\n color: '{surface.700}',\n disabledColor: '{surface.500}',\n placeholderColor: '{surface.500}',\n invalidPlaceholderColor: '{red.600}',\n floatLabelColor: '{surface.500}',\n floatLabelFocusColor: '{primary.600}',\n floatLabelActiveColor: '{surface.500}',\n floatLabelInvalidColor: '{form.field.invalid.placeholder.color}',\n iconColor: '{surface.400}',\n shadow: '0 0 #0000, 0 0 #0000, 0 1px 2px 0 rgba(18, 18, 23, 0.05)',\n },\n text: {\n color: '{surface.800}',\n hoverColor: '{surface.900}',\n mutedColor: '{surface.500}',\n hoverMutedColor: '{surface.600}',\n },\n content: {\n background: '{surface.0}',\n hoverBackground: '{surface.100}',\n borderColor: '{surface.200}',\n color: '{text.color}',\n hoverColor: '{text.hover.color}',\n },\n overlay: {\n select: {\n background: '{surface.0}',\n borderColor: '{surface.200}',\n color: '{text.color}',\n },\n popover: {\n background: '{surface.0}',\n borderColor: '{surface.200}',\n color: '{text.color}',\n },\n modal: {\n background: '{surface.0}',\n borderColor: '{surface.200}',\n color: '{text.color}',\n },\n },\n list: {\n option: {\n focusBackground: '{surface.100}',\n selectedBackground: '{highlight.background}',\n selectedFocusBackground: '{highlight.focus.background}',\n color: '{text.color}',\n focusColor: '{text.hover.color}',\n selectedColor: '{highlight.color}',\n selectedFocusColor: '{highlight.focus.color}',\n icon: {\n color: '{surface.400}',\n focusColor: '{surface.500}',\n },\n },\n optionGroup: {\n background: 'transparent',\n color: '{text.muted.color}',\n },\n },\n navigation: {\n item: {\n focusBackground: '{surface.100}',\n activeBackground: '{surface.100}',\n color: '{text.color}',\n focusColor: '{text.hover.color}',\n activeColor: '{text.hover.color}',\n icon: {\n color: '{surface.400}',\n focusColor: '{surface.500}',\n activeColor: '{surface.500}',\n },\n },\n submenuLabel: {\n background: 'transparent',\n color: '{text.muted.color}',\n },\n submenuIcon: {\n color: '{surface.400}',\n focusColor: '{surface.500}',\n activeColor: '{surface.500}',\n },\n },\n },\n dark: {\n surface: {\n 0: '#ffffff',\n 50: '#fafafa',\n 100: '#f4f4f5',\n 200: '#e4e4e7',\n 300: '#d4d4d8',\n 400: '#a1a1aa',\n 500: '#71717a',\n 600: '#52525b',\n 700: '#3f3f46',\n 800: '#27272a',\n 900: '#18181b',\n 950: '#09090b',\n },\n primary: {\n color: '{primary.400}',\n contrastColor: '{surface.900}',\n hoverColor: '{primary.300}',\n activeColor: '{primary.200}',\n },\n highlight: {\n background: 'color-mix(in srgb, {primary.400}, transparent 84%)',\n focusBackground: 'color-mix(in srgb, {primary.400}, transparent 76%)',\n color: 'rgba(255,255,255,.87)',\n focusColor: 'rgba(255,255,255,.87)',\n },\n mask: {\n background: 'rgba(0,0,0,0.6)',\n color: '{surface.200}',\n },\n formField: {\n background: '{surface.950}',\n disabledBackground: '{surface.700}',\n filledBackground: '{surface.800}',\n filledHoverBackground: '{surface.800}',\n filledFocusBackground: '{surface.800}',\n borderColor: '{surface.600}',\n hoverBorderColor: '{surface.500}',\n focusBorderColor: '{primary.color}',\n invalidBorderColor: '{red.300}',\n color: '{surface.0}',\n disabledColor: '{surface.400}',\n placeholderColor: '{surface.400}',\n invalidPlaceholderColor: '{red.400}',\n floatLabelColor: '{surface.400}',\n floatLabelFocusColor: '{primary.color}',\n floatLabelActiveColor: '{surface.400}',\n floatLabelInvalidColor: '{form.field.invalid.placeholder.color}',\n iconColor: '{surface.400}',\n shadow: '0 0 #0000, 0 0 #0000, 0 1px 2px 0 rgba(18, 18, 23, 0.05)',\n },\n text: {\n color: '{surface.0}',\n hoverColor: '{surface.0}',\n mutedColor: '{surface.400}',\n hoverMutedColor: '{surface.300}',\n },\n content: {\n background: '{surface.900}',\n hoverBackground: '{surface.800}',\n borderColor: '{surface.700}',\n color: '{text.color}',\n hoverColor: '{text.hover.color}',\n },\n overlay: {\n select: {\n background: '{surface.900}',\n borderColor: '{surface.700}',\n color: '{text.color}',\n },\n popover: {\n background: '{surface.900}',\n borderColor: '{surface.700}',\n color: '{text.color}',\n },\n modal: {\n background: '{surface.900}',\n borderColor: '{surface.700}',\n color: '{text.color}',\n },\n },\n list: {\n option: {\n focusBackground: '{surface.800}',\n selectedBackground: '{highlight.background}',\n selectedFocusBackground: '{highlight.focus.background}',\n color: '{text.color}',\n focusColor: '{text.hover.color}',\n selectedColor: '{highlight.color}',\n selectedFocusColor: '{highlight.focus.color}',\n icon: {\n color: '{surface.500}',\n focusColor: '{surface.400}',\n },\n },\n optionGroup: {\n background: 'transparent',\n color: '{text.muted.color}',\n },\n },\n navigation: {\n item: {\n focusBackground: '{surface.800}',\n activeBackground: '{surface.800}',\n color: '{text.color}',\n focusColor: '{text.hover.color}',\n activeColor: '{text.hover.color}',\n icon: {\n color: '{surface.500}',\n focusColor: '{surface.400}',\n activeColor: '{surface.400}',\n },\n },\n submenuLabel: {\n background: 'transparent',\n color: '{text.muted.color}',\n },\n submenuIcon: {\n color: '{surface.500}',\n focusColor: '{surface.400}',\n activeColor: '{surface.400}',\n },\n },\n },\n },\n },\n components: {\n accordion: {\n header: {\n borderRadius: '{content.border.radius}',\n borderColor: '{content.border.color}',\n background: '{surface.100}',\n hoverBackground: '{surface.200}',\n activeBackground: '{surface.200}',\n activeHoverBackground: '{surface.200}',\n },\n content: {\n padding: '0.5rem 0.25rem',\n },\n },\n autocomplete: {\n option: {\n padding: '0.2rem 0.5rem',\n },\n },\n card: {\n root: {\n background: '{surface.100}',\n },\n body: {\n padding: '0',\n },\n },\n fieldset: {\n legend: {\n padding: '0 0.25rem 0.25rem 0.25rem',\n },\n },\n listbox: {\n option: {\n padding: '0.2rem 0.5rem',\n },\n },\n menubar: {\n root: {\n borderColor: 'transparent',\n },\n },\n panel: {\n root: {\n background: '{surface.100}',\n },\n content: {\n padding: '0',\n },\n },\n tag: {\n root: {\n fontSize: '0.8rem',\n fontWeight: '600',\n padding: '0.15rem 0.5rem',\n gap: '0.25rem',\n borderRadius: '{content.border.radius}',\n roundedBorderRadius: '{border.radius.xl}',\n },\n icon: {\n size: '0.5rem',\n },\n colorScheme: {\n light: {\n primary: {\n background: '{primary.100}',\n color: '{primary.700}',\n },\n secondary: {\n background: '{surface.500}',\n color: '{surface.0}',\n },\n success: {\n background: '{green.100}',\n color: '{green.700}',\n },\n info: {\n background: '{sky.100}',\n color: '{sky.700}',\n },\n warn: {\n background: '{orange.100}',\n color: '{orange.700}',\n },\n danger: {\n background: '{red.100}',\n color: '{red.700}',\n },\n contrast: {\n background: '{surface.950}',\n color: '{surface.0}',\n },\n },\n dark: {\n primary: {\n background: 'color-mix(in srgb, {primary.500}, transparent 84%)',\n color: '{primary.300}',\n },\n secondary: {\n background: '{surface.800}',\n color: '{surface.300}',\n },\n success: {\n background: 'color-mix(in srgb, {green.500}, transparent 84%)',\n color: '{green.300}',\n },\n info: {\n background: 'color-mix(in srgb, {sky.500}, transparent 84%)',\n color: '{sky.300}',\n },\n warn: {\n background: 'color-mix(in srgb, {orange.500}, transparent 84%)',\n color: '{orange.300}',\n },\n danger: {\n background: 'color-mix(in srgb, {red.500}, transparent 84%)',\n color: '{red.300}',\n },\n contrast: {\n background: '{surface.0}',\n color: '{surface.950}',\n },\n },\n },\n },\n timeline: {\n event: {\n minHeight: '2.5rem',\n },\n },\n },\n }),\n },\n};\n","// SPDX-FileCopyrightText: Fondation RERO+\n// SPDX-License-Identifier: AGPL-3.0-or-later\nexport const CONFIG = {\n MESSAGE_LIFE: 5000, // Message lifetime in ms\n DEFAULT_SELECT_SCROLL_HEIGHT: '50vh',\n};\n","// SPDX-FileCopyrightText: Fondation RERO+\n// SPDX-License-Identifier: AGPL-3.0-or-later\nimport { ChangeDetectionStrategy, Component, computed, input, linkedSignal } from '@angular/core';\nimport { _, TranslatePipe } from '@ngx-translate/core';\nimport { Nl2brPipe } from '../../pipe/nl2br/nl2br.pipe';\nimport { Button } from 'primeng/button';\n\n@Component({\n selector: 'ng-core-read-more',\n template: `\n <span [innerHTML]=\"textDisplay() | nl2br\"></span>\n\n @if (showMoreActivated()) {\n <p-button link size=\"small\" (click)=\"toggleText($event)\">{{ showMoreLinkLabel() | translate }}</p-button>\n }\n `,\n imports: [TranslatePipe, Nl2brPipe, Button],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ReadMoreComponent {\n text = input.required<string>();\n limit = input<number>(50);\n unit = input<'char' | 'word'>('word');\n trailing = input<string>('…');\n showMoreLabel = input<string>(_('show more'));\n showLessLabel = input<string>(_('show less'));\n\n showMore = linkedSignal(() => this.showMoreActivated());\n\n textDisplay = computed(() => this.processText(this.originalText(), this.showMore()));\n showMoreLinkLabel = computed(() => (this.showMore() ? this.showMoreLabel() : this.showLessLabel()));\n showMoreActivated = computed(() => this.countElement() > this.limit());\n\n private originalText = computed(() => this.text().replace(/<.*?>/g, ''));\n\n toggleText(event: Event): void {\n event.preventDefault();\n this.showMore.set(!this.showMore());\n }\n\n private countElement(): number {\n return this.unit() === 'word' ? this.splitWord().length : this.originalText().length;\n }\n\n private processText(data: string, more: boolean): string {\n if (more) {\n let result = [];\n if (this.unit() === 'word') {\n result = this.splitWord().slice(0, this.limit());\n } else {\n result.push(data.slice(0, this.limit()));\n }\n result.push(this.trailing());\n return result.join(' ');\n } else {\n return data;\n }\n }\n\n private splitWord(): string[] {\n return this.originalText().split(/\\s+/);\n }\n}\n","// SPDX-FileCopyrightText: Fondation RERO+\n// SPDX-License-Identifier: AGPL-3.0-or-later\nimport { ChangeDetectionStrategy, Component, inject } from '@angular/core';\nimport { DynamicDialogConfig, DynamicDialogRef } from 'primeng/dynamicdialog';\nimport { Button } from 'primeng/button';\nimport { TranslatePipe } from '@ngx-translate/core';\nimport { Nl2brPipe } from '../../pipe/nl2br/nl2br.pipe';\n\n@Component({\n selector: 'ng-core-dialog',\n template: `\n <div class=\"core:flex core:flex-col core:gap-2\">\n <div class=\"core:flex\" [innerHtml]=\"config.data.body | nl2br\"></div>\n <div class=\"core:flex core:justify-end core:gap-1\">\n <p-button\n [label]=\"config.data.cancelTitleButton || 'Cancel' | translate\"\n severity=\"danger\"\n [outlined]=\"true\"\n (onClick)=\"cancel()\"\n />\n @if (config.data.confirmButton) {\n <p-button [label]=\"config.data.confirmTitleButton || 'OK' | translate\" (onClick)=\"confirm()\" />\n }\n </div>\n </div>\n `,\n imports: [Button, TranslatePipe, Nl2brPipe],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class DialogComponent {\n config: DynamicDialogConfig = inject