@sdcorejs/angular 21.1.3 → 21.1.5

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.
Files changed (168) hide show
  1. package/README.md +19 -14
  2. package/fesm2022/sdcorejs-angular-components-anchor.mjs +14 -14
  3. package/fesm2022/sdcorejs-angular-components-anchor.mjs.map +1 -1
  4. package/fesm2022/sdcorejs-angular-components-audit-diff.mjs +332 -0
  5. package/fesm2022/sdcorejs-angular-components-audit-diff.mjs.map +1 -0
  6. package/fesm2022/sdcorejs-angular-components-badge.mjs +1 -0
  7. package/fesm2022/sdcorejs-angular-components-badge.mjs.map +1 -1
  8. package/fesm2022/sdcorejs-angular-components-breadcrumb.mjs +121 -0
  9. package/fesm2022/sdcorejs-angular-components-breadcrumb.mjs.map +1 -0
  10. package/fesm2022/sdcorejs-angular-components-data-state.mjs +68 -0
  11. package/fesm2022/sdcorejs-angular-components-data-state.mjs.map +1 -0
  12. package/fesm2022/sdcorejs-angular-components-document-builder.mjs +18 -23
  13. package/fesm2022/sdcorejs-angular-components-document-builder.mjs.map +1 -1
  14. package/fesm2022/sdcorejs-angular-components-editor.mjs +6 -4
  15. package/fesm2022/sdcorejs-angular-components-editor.mjs.map +1 -1
  16. package/fesm2022/sdcorejs-angular-components-form-generic.mjs +495 -838
  17. package/fesm2022/sdcorejs-angular-components-form-generic.mjs.map +1 -1
  18. package/fesm2022/sdcorejs-angular-components-import-excel.mjs +24 -34
  19. package/fesm2022/sdcorejs-angular-components-import-excel.mjs.map +1 -1
  20. package/fesm2022/sdcorejs-angular-components-job-progress.mjs +97 -0
  21. package/fesm2022/sdcorejs-angular-components-job-progress.mjs.map +1 -0
  22. package/fesm2022/sdcorejs-angular-components-mini-editor.mjs +10 -20
  23. package/fesm2022/sdcorejs-angular-components-mini-editor.mjs.map +1 -1
  24. package/fesm2022/sdcorejs-angular-components-modal.mjs +61 -4
  25. package/fesm2022/sdcorejs-angular-components-modal.mjs.map +1 -1
  26. package/fesm2022/sdcorejs-angular-components-preview.mjs +1438 -218
  27. package/fesm2022/sdcorejs-angular-components-preview.mjs.map +1 -1
  28. package/fesm2022/sdcorejs-angular-components-query-bar.mjs +4 -4
  29. package/fesm2022/sdcorejs-angular-components-query-bar.mjs.map +1 -1
  30. package/fesm2022/sdcorejs-angular-components-query-builder.mjs +1 -1
  31. package/fesm2022/sdcorejs-angular-components-query-builder.mjs.map +1 -1
  32. package/fesm2022/sdcorejs-angular-components-side-drawer.mjs +39 -2
  33. package/fesm2022/sdcorejs-angular-components-side-drawer.mjs.map +1 -1
  34. package/fesm2022/sdcorejs-angular-components-tab-router.mjs +16 -22
  35. package/fesm2022/sdcorejs-angular-components-tab-router.mjs.map +1 -1
  36. package/fesm2022/sdcorejs-angular-components-tab.mjs +48 -4
  37. package/fesm2022/sdcorejs-angular-components-tab.mjs.map +1 -1
  38. package/fesm2022/sdcorejs-angular-components-table.mjs +96 -63
  39. package/fesm2022/sdcorejs-angular-components-table.mjs.map +1 -1
  40. package/fesm2022/sdcorejs-angular-components-tree.mjs +186 -17
  41. package/fesm2022/sdcorejs-angular-components-tree.mjs.map +1 -1
  42. package/fesm2022/sdcorejs-angular-components-upload-file.mjs +15 -22
  43. package/fesm2022/sdcorejs-angular-components-upload-file.mjs.map +1 -1
  44. package/fesm2022/sdcorejs-angular-components.mjs +4 -0
  45. package/fesm2022/sdcorejs-angular-components.mjs.map +1 -1
  46. package/fesm2022/sdcorejs-angular-directives.mjs +29 -41
  47. package/fesm2022/sdcorejs-angular-directives.mjs.map +1 -1
  48. package/fesm2022/sdcorejs-angular-forms-autocomplete.mjs +7 -7
  49. package/fesm2022/sdcorejs-angular-forms-autocomplete.mjs.map +1 -1
  50. package/fesm2022/sdcorejs-angular-forms-checkbox.mjs +20 -71
  51. package/fesm2022/sdcorejs-angular-forms-checkbox.mjs.map +1 -1
  52. package/fesm2022/sdcorejs-angular-forms-chip-calendar.mjs +6 -3
  53. package/fesm2022/sdcorejs-angular-forms-chip-calendar.mjs.map +1 -1
  54. package/fesm2022/sdcorejs-angular-forms-chip.mjs +6 -3
  55. package/fesm2022/sdcorejs-angular-forms-chip.mjs.map +1 -1
  56. package/fesm2022/sdcorejs-angular-forms-date-range.mjs +16 -13
  57. package/fesm2022/sdcorejs-angular-forms-date-range.mjs.map +1 -1
  58. package/fesm2022/sdcorejs-angular-forms-date.mjs +42 -65
  59. package/fesm2022/sdcorejs-angular-forms-date.mjs.map +1 -1
  60. package/fesm2022/sdcorejs-angular-forms-datetime.mjs +51 -66
  61. package/fesm2022/sdcorejs-angular-forms-datetime.mjs.map +1 -1
  62. package/fesm2022/sdcorejs-angular-forms-entity-picker.mjs +384 -0
  63. package/fesm2022/sdcorejs-angular-forms-entity-picker.mjs.map +1 -0
  64. package/fesm2022/sdcorejs-angular-forms-input-color.mjs +1 -1
  65. package/fesm2022/sdcorejs-angular-forms-input-color.mjs.map +1 -1
  66. package/fesm2022/sdcorejs-angular-forms-input-number.mjs +7 -5
  67. package/fesm2022/sdcorejs-angular-forms-input-number.mjs.map +1 -1
  68. package/fesm2022/sdcorejs-angular-forms-input.mjs +290 -56
  69. package/fesm2022/sdcorejs-angular-forms-input.mjs.map +1 -1
  70. package/fesm2022/sdcorejs-angular-forms-models.mjs +155 -2
  71. package/fesm2022/sdcorejs-angular-forms-models.mjs.map +1 -1
  72. package/fesm2022/sdcorejs-angular-forms-radio.mjs +44 -66
  73. package/fesm2022/sdcorejs-angular-forms-radio.mjs.map +1 -1
  74. package/fesm2022/sdcorejs-angular-forms-select.mjs +6 -20
  75. package/fesm2022/sdcorejs-angular-forms-select.mjs.map +1 -1
  76. package/fesm2022/sdcorejs-angular-forms-switch.mjs +19 -64
  77. package/fesm2022/sdcorejs-angular-forms-switch.mjs.map +1 -1
  78. package/fesm2022/sdcorejs-angular-forms-textarea.mjs +6 -5
  79. package/fesm2022/sdcorejs-angular-forms-textarea.mjs.map +1 -1
  80. package/fesm2022/sdcorejs-angular-forms-time-range.mjs +277 -0
  81. package/fesm2022/sdcorejs-angular-forms-time-range.mjs.map +1 -0
  82. package/fesm2022/sdcorejs-angular-forms-time.mjs +307 -0
  83. package/fesm2022/sdcorejs-angular-forms-time.mjs.map +1 -0
  84. package/fesm2022/sdcorejs-angular-forms-tree-select.mjs +210 -0
  85. package/fesm2022/sdcorejs-angular-forms-tree-select.mjs.map +1 -0
  86. package/fesm2022/sdcorejs-angular-forms.mjs +73 -4
  87. package/fesm2022/sdcorejs-angular-forms.mjs.map +1 -1
  88. package/fesm2022/sdcorejs-angular-i18n.mjs +375 -10
  89. package/fesm2022/sdcorejs-angular-i18n.mjs.map +1 -1
  90. package/fesm2022/sdcorejs-angular-interceptors.mjs +12 -17
  91. package/fesm2022/sdcorejs-angular-interceptors.mjs.map +1 -1
  92. package/fesm2022/sdcorejs-angular-modules-layout.mjs +994 -168
  93. package/fesm2022/sdcorejs-angular-modules-layout.mjs.map +1 -1
  94. package/fesm2022/sdcorejs-angular-pipes.mjs +5 -7
  95. package/fesm2022/sdcorejs-angular-pipes.mjs.map +1 -1
  96. package/fesm2022/sdcorejs-angular-services-api.mjs +407 -137
  97. package/fesm2022/sdcorejs-angular-services-api.mjs.map +1 -1
  98. package/fesm2022/sdcorejs-angular-services-cache.mjs +515 -105
  99. package/fesm2022/sdcorejs-angular-services-cache.mjs.map +1 -1
  100. package/fesm2022/sdcorejs-angular-services-confirm.mjs +5 -7
  101. package/fesm2022/sdcorejs-angular-services-confirm.mjs.map +1 -1
  102. package/fesm2022/sdcorejs-angular-services-docx.mjs +7 -10
  103. package/fesm2022/sdcorejs-angular-services-docx.mjs.map +1 -1
  104. package/fesm2022/sdcorejs-angular-services-loading.mjs +339 -74
  105. package/fesm2022/sdcorejs-angular-services-loading.mjs.map +1 -1
  106. package/fesm2022/sdcorejs-angular-services-notify.mjs +7 -10
  107. package/fesm2022/sdcorejs-angular-services-notify.mjs.map +1 -1
  108. package/fesm2022/sdcorejs-angular-services-persistence.mjs +899 -0
  109. package/fesm2022/sdcorejs-angular-services-persistence.mjs.map +1 -0
  110. package/fesm2022/sdcorejs-angular-services-storage.mjs +324 -122
  111. package/fesm2022/sdcorejs-angular-services-storage.mjs.map +1 -1
  112. package/fesm2022/sdcorejs-angular-services-task.mjs +389 -0
  113. package/fesm2022/sdcorejs-angular-services-task.mjs.map +1 -0
  114. package/fesm2022/sdcorejs-angular-services-unsaved-changes.mjs +255 -0
  115. package/fesm2022/sdcorejs-angular-services-unsaved-changes.mjs.map +1 -0
  116. package/fesm2022/sdcorejs-angular-services-viewport.mjs +76 -0
  117. package/fesm2022/sdcorejs-angular-services-viewport.mjs.map +1 -0
  118. package/fesm2022/sdcorejs-angular-services.mjs +4 -0
  119. package/fesm2022/sdcorejs-angular-services.mjs.map +1 -1
  120. package/package.json +49 -1
  121. package/types/sdcorejs-angular-components-audit-diff.d.ts +74 -0
  122. package/types/sdcorejs-angular-components-badge.d.ts +1 -1
  123. package/types/sdcorejs-angular-components-breadcrumb.d.ts +53 -0
  124. package/types/sdcorejs-angular-components-data-state.d.ts +44 -0
  125. package/types/sdcorejs-angular-components-document-builder.d.ts +5 -5
  126. package/types/sdcorejs-angular-components-form-generic.d.ts +67 -104
  127. package/types/sdcorejs-angular-components-import-excel.d.ts +4 -14
  128. package/types/sdcorejs-angular-components-job-progress.d.ts +38 -0
  129. package/types/sdcorejs-angular-components-mini-editor.d.ts +9 -9
  130. package/types/sdcorejs-angular-components-modal.d.ts +7 -1
  131. package/types/sdcorejs-angular-components-preview.d.ts +181 -28
  132. package/types/sdcorejs-angular-components-side-drawer.d.ts +7 -1
  133. package/types/sdcorejs-angular-components-tab.d.ts +9 -2
  134. package/types/sdcorejs-angular-components-table.d.ts +8 -7
  135. package/types/sdcorejs-angular-components-tree.d.ts +24 -2
  136. package/types/sdcorejs-angular-components-upload-file.d.ts +5 -4
  137. package/types/sdcorejs-angular-components.d.ts +4 -0
  138. package/types/sdcorejs-angular-directives.d.ts +10 -8
  139. package/types/sdcorejs-angular-forms-autocomplete.d.ts +3 -4
  140. package/types/sdcorejs-angular-forms-checkbox.d.ts +4 -8
  141. package/types/sdcorejs-angular-forms-date-range.d.ts +6 -7
  142. package/types/sdcorejs-angular-forms-date.d.ts +2 -2
  143. package/types/sdcorejs-angular-forms-datetime.d.ts +2 -2
  144. package/types/sdcorejs-angular-forms-entity-picker.d.ts +128 -0
  145. package/types/sdcorejs-angular-forms-input-number.d.ts +1 -1
  146. package/types/sdcorejs-angular-forms-input.d.ts +74 -11
  147. package/types/sdcorejs-angular-forms-models.d.ts +86 -3
  148. package/types/sdcorejs-angular-forms-radio.d.ts +12 -8
  149. package/types/sdcorejs-angular-forms-switch.d.ts +4 -7
  150. package/types/sdcorejs-angular-forms-time-range.d.ts +98 -0
  151. package/types/sdcorejs-angular-forms-time.d.ts +117 -0
  152. package/types/sdcorejs-angular-forms-tree-select.d.ts +76 -0
  153. package/types/sdcorejs-angular-forms.d.ts +15 -5
  154. package/types/sdcorejs-angular-i18n.d.ts +72 -2
  155. package/types/sdcorejs-angular-interceptors.d.ts +5 -6
  156. package/types/sdcorejs-angular-modules-layout.d.ts +354 -17
  157. package/types/sdcorejs-angular-pipes.d.ts +2 -2
  158. package/types/sdcorejs-angular-services-api.d.ts +68 -24
  159. package/types/sdcorejs-angular-services-cache.d.ts +52 -16
  160. package/types/sdcorejs-angular-services-confirm.d.ts +3 -2
  161. package/types/sdcorejs-angular-services-docx.d.ts +2 -3
  162. package/types/sdcorejs-angular-services-loading.d.ts +16 -8
  163. package/types/sdcorejs-angular-services-persistence.d.ts +159 -0
  164. package/types/sdcorejs-angular-services-storage.d.ts +26 -8
  165. package/types/sdcorejs-angular-services-task.d.ts +104 -0
  166. package/types/sdcorejs-angular-services-unsaved-changes.d.ts +83 -0
  167. package/types/sdcorejs-angular-services-viewport.d.ts +42 -0
  168. package/types/sdcorejs-angular-services.d.ts +4 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdcorejs-angular-components-audit-diff.mjs","sources":["../../../projects/sdcorejs-angular/components/audit-diff/src/audit-diff.engine.ts","../../../projects/sdcorejs-angular/components/audit-diff/src/audit-diff.component.ts","../../../projects/sdcorejs-angular/components/audit-diff/src/audit-diff.component.html","../../../projects/sdcorejs-angular/components/audit-diff/sdcorejs-angular-components-audit-diff.ts"],"sourcesContent":["export type SdAuditDiffKind = 'added' | 'removed' | 'changed' | 'unchanged';\nexport type SdAuditDiffSide = 'before' | 'after';\nexport type SdAuditDiffArrayKey = string | ((item: unknown) => unknown);\n\nexport interface SdAuditDiffFormatContext {\n readonly path: string;\n readonly configPath: string;\n readonly side: SdAuditDiffSide;\n readonly kind: SdAuditDiffKind;\n readonly before: unknown;\n readonly after: unknown;\n}\n\nexport interface SdAuditDiffField {\n readonly path: string;\n readonly label?: string;\n readonly order?: number;\n readonly hidden?: boolean;\n readonly redacted?: boolean;\n readonly arrayKey?: SdAuditDiffArrayKey;\n readonly enumMap?: Readonly<Record<string, unknown>>;\n readonly format?: (value: unknown, context: SdAuditDiffFormatContext) => unknown;\n}\n\nexport interface SdAuditDiffOptions {\n readonly fields?: readonly SdAuditDiffField[];\n readonly includeUnchanged?: boolean;\n readonly redactedValue?: unknown;\n readonly rootLabel?: string;\n}\n\nexport interface SdAuditDiffRow {\n readonly id: string;\n readonly path: string;\n readonly configPath: string;\n readonly label: string;\n readonly kind: SdAuditDiffKind;\n readonly before: unknown;\n readonly after: unknown;\n readonly beforePresent: boolean;\n readonly afterPresent: boolean;\n readonly redacted: boolean;\n}\n\ninterface WalkContext {\n readonly options: SdAuditDiffOptions;\n readonly fields: readonly SdAuditDiffField[];\n readonly rows: SdAuditDiffRow[];\n readonly activeBefore: WeakSet<object>;\n readonly activeAfter: WeakSet<object>;\n}\n\ninterface StableArrayItem {\n readonly key: unknown;\n readonly value: unknown;\n}\n\nconst DEFAULT_REDACTED_VALUE = '••••••';\n\nexport function sdBuildAuditDiff(before: unknown, after: unknown, options: SdAuditDiffOptions = {}): SdAuditDiffRow[] {\n const context: WalkContext = {\n options,\n fields: options.fields ?? [],\n rows: [],\n activeBefore: new WeakSet<object>(),\n activeAfter: new WeakSet<object>(),\n };\n walkValue(context, before, after, true, true, '$', '$');\n return context.rows.sort((left, right) => compareRows(left, right, context.fields));\n}\n\nfunction walkValue(\n context: WalkContext,\n before: unknown,\n after: unknown,\n beforePresent: boolean,\n afterPresent: boolean,\n path: string,\n configPath: string\n): void {\n if (isConfigured(context.fields, configPath, 'hidden')) return;\n if (isConfigured(context.fields, configPath, 'redacted')) {\n addAtomicRow(context, before, after, beforePresent, afterPresent, path, configPath, true);\n return;\n }\n\n const field = findExactField(context.fields, configPath);\n if (field?.format || field?.enumMap) {\n addAtomicRow(context, before, after, beforePresent, afterPresent, path, configPath, false);\n return;\n }\n\n const beforeArray = Array.isArray(before);\n const afterArray = Array.isArray(after);\n if (beforeArray || afterArray) {\n if ((!beforePresent && afterArray) || (beforeArray && !afterPresent) || (beforeArray && afterArray)) {\n const arrayKey = field?.arrayKey;\n if (arrayKey && walkStableArray(context, beforeArray ? before : [], afterArray ? after : [], path, configPath, arrayKey)) return;\n }\n addAtomicRow(context, before, after, beforePresent, afterPresent, path, configPath, false);\n return;\n }\n\n const beforeObject = isPlainObject(before);\n const afterObject = isPlainObject(after);\n const canRecurse = (beforeObject && afterObject) || (beforeObject && !afterPresent) || (afterObject && !beforePresent);\n if (canRecurse) {\n if ((beforeObject && context.activeBefore.has(before)) || (afterObject && context.activeAfter.has(after))) return;\n if (beforeObject) context.activeBefore.add(before);\n if (afterObject) context.activeAfter.add(after);\n const beforeRecord = beforeObject ? before : {};\n const afterRecord = afterObject ? after : {};\n const keys = [...new Set([...Object.keys(beforeRecord), ...Object.keys(afterRecord)])].sort(compareText);\n if (keys.length === 0) {\n addAtomicRow(context, before, after, beforePresent, afterPresent, path, configPath, false);\n if (beforeObject) context.activeBefore.delete(before);\n if (afterObject) context.activeAfter.delete(after);\n return;\n }\n for (const key of keys) {\n const childBeforePresent = beforeObject && hasOwn(beforeRecord, key);\n const childAfterPresent = afterObject && hasOwn(afterRecord, key);\n walkValue(\n context,\n childBeforePresent ? beforeRecord[key] : undefined,\n childAfterPresent ? afterRecord[key] : undefined,\n childBeforePresent,\n childAfterPresent,\n path === '$' ? key : `${path}.${key}`,\n configPath === '$' ? key : `${configPath}.${key}`\n );\n }\n if (beforeObject) context.activeBefore.delete(before);\n if (afterObject) context.activeAfter.delete(after);\n return;\n }\n\n addAtomicRow(context, before, after, beforePresent, afterPresent, path, configPath, false);\n}\n\nfunction walkStableArray(\n context: WalkContext,\n before: readonly unknown[],\n after: readonly unknown[],\n path: string,\n configPath: string,\n keySelector: SdAuditDiffArrayKey\n): boolean {\n const beforeItems = indexStableArray(before, keySelector);\n const afterItems = indexStableArray(after, keySelector);\n if (!beforeItems || !afterItems) return false;\n\n const keys = [...new Set([...beforeItems.keys(), ...afterItems.keys()])].sort(compareText);\n const keyName = typeof keySelector === 'string' ? keySelector : 'key';\n for (const key of keys) {\n const beforeItem = beforeItems.get(key);\n const afterItem = afterItems.get(key);\n const itemPath = `${path}[${keyName}=${encodeURIComponent(key)}]`;\n const itemConfigPath = `${configPath}[]`;\n if (!beforeItem || !afterItem) {\n walkValue(context, beforeItem?.value, afterItem?.value, Boolean(beforeItem), Boolean(afterItem), itemPath, itemConfigPath);\n continue;\n }\n walkValue(context, beforeItem.value, afterItem.value, true, true, itemPath, itemConfigPath);\n }\n return true;\n}\n\nfunction indexStableArray(items: readonly unknown[], keySelector: SdAuditDiffArrayKey): Map<string, StableArrayItem> | null {\n const result = new Map<string, StableArrayItem>();\n for (const item of items) {\n let key: unknown;\n try {\n key = typeof keySelector === 'function' ? keySelector(item) : isObject(item) ? item[keySelector] : undefined;\n } catch {\n return null;\n }\n const serialized = serializeStableKey(key);\n if (serialized === null || result.has(serialized)) return null;\n result.set(serialized, { key, value: item });\n }\n return result;\n}\n\nfunction serializeStableKey(key: unknown): string | null {\n if (key === null) return 'null:null';\n switch (typeof key) {\n case 'string':\n case 'number':\n case 'bigint':\n case 'boolean':\n return `${typeof key}:${String(key)}`;\n default:\n return null;\n }\n}\n\nfunction addAtomicRow(\n context: WalkContext,\n before: unknown,\n after: unknown,\n beforePresent: boolean,\n afterPresent: boolean,\n path: string,\n configPath: string,\n redacted: boolean\n): void {\n const kind = classifyChange(before, after, beforePresent, afterPresent);\n if (kind === 'unchanged' && !context.options.includeUnchanged) return;\n\n const field = findExactField(context.fields, configPath);\n const redactedValue = context.options.redactedValue ?? DEFAULT_REDACTED_VALUE;\n const normalizedBefore = redacted\n ? beforePresent\n ? redactedValue\n : undefined\n : normalizeValue(before, beforePresent, 'before', kind, path, configPath, field, after);\n const normalizedAfter = redacted\n ? afterPresent\n ? redactedValue\n : undefined\n : normalizeValue(after, afterPresent, 'after', kind, path, configPath, field, before);\n\n context.rows.push({\n id: path,\n path,\n configPath,\n label: field?.label ?? (path === '$' ? (context.options.rootLabel ?? 'Value') : path),\n kind,\n before: normalizedBefore,\n after: normalizedAfter,\n beforePresent,\n afterPresent,\n redacted,\n });\n}\n\nfunction normalizeValue(\n value: unknown,\n present: boolean,\n side: SdAuditDiffSide,\n kind: SdAuditDiffKind,\n path: string,\n configPath: string,\n field: SdAuditDiffField | undefined,\n otherValue: unknown\n): unknown {\n if (!present) return undefined;\n const mapped = field?.enumMap && hasOwn(field.enumMap, String(value)) ? field.enumMap[String(value)] : value;\n if (!field?.format) return mapped;\n try {\n return field.format(mapped, {\n path,\n configPath,\n side,\n kind,\n before: side === 'before' ? value : otherValue,\n after: side === 'after' ? value : otherValue,\n });\n } catch {\n return mapped;\n }\n}\n\nfunction classifyChange(before: unknown, after: unknown, beforePresent: boolean, afterPresent: boolean): SdAuditDiffKind {\n if (!beforePresent && afterPresent) return 'added';\n if (beforePresent && !afterPresent) return 'removed';\n return deepEqual(before, after) ? 'unchanged' : 'changed';\n}\n\nfunction deepEqual(left: unknown, right: unknown, seen = new WeakMap<object, WeakSet<object>>()): boolean {\n if (Object.is(left, right)) return true;\n if (left instanceof Date && right instanceof Date) return left.getTime() === right.getTime();\n if (!isObject(left) || !isObject(right)) return false;\n let rightSet = seen.get(left);\n if (rightSet?.has(right)) return true;\n if (!rightSet) {\n rightSet = new WeakSet<object>();\n seen.set(left, rightSet);\n }\n rightSet.add(right);\n if (Array.isArray(left) && Array.isArray(right)) {\n if (left.length !== right.length) return false;\n return left.every((value, index) => deepEqual(value, right[index], seen));\n }\n if (!isPlainObject(left) || !isPlainObject(right)) return false;\n const leftKeys = Object.keys(left).sort(compareText);\n const rightKeys = Object.keys(right).sort(compareText);\n if (leftKeys.length !== rightKeys.length || leftKeys.some((key, index) => key !== rightKeys[index])) return false;\n return leftKeys.every(key => deepEqual(left[key], right[key], seen));\n}\n\nfunction compareRows(left: SdAuditDiffRow, right: SdAuditDiffRow, fields: readonly SdAuditDiffField[]): number {\n const leftOrder = explicitOrder(left.configPath, fields);\n const rightOrder = explicitOrder(right.configPath, fields);\n if (leftOrder !== rightOrder) return leftOrder - rightOrder;\n return compareText(left.path, right.path);\n}\n\nfunction explicitOrder(path: string, fields: readonly SdAuditDiffField[]): number {\n const field = fields\n .filter(candidate => Number.isFinite(candidate.order) && isPathOrDescendant(path, candidate.path))\n .sort((left, right) => right.path.length - left.path.length)[0];\n return field?.order ?? Number.POSITIVE_INFINITY;\n}\n\nfunction findExactField(fields: readonly SdAuditDiffField[], path: string): SdAuditDiffField | undefined {\n return fields.find(field => field.path === path);\n}\n\nfunction isConfigured(fields: readonly SdAuditDiffField[], path: string, property: 'hidden' | 'redacted'): boolean {\n return fields.some(field => Boolean(field[property]) && isPathOrDescendant(path, field.path));\n}\n\nfunction isPathOrDescendant(path: string, ancestor: string): boolean {\n return path === ancestor || path.startsWith(`${ancestor}.`) || path.startsWith(`${ancestor}[]`);\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (!isObject(value)) return false;\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n}\n\nfunction hasOwn(object: object, key: PropertyKey): boolean {\n return Object.prototype.hasOwnProperty.call(object, key);\n}\n\nfunction compareText(left: string, right: string): number {\n return left < right ? -1 : left > right ? 1 : 0;\n}\n","import { NgTemplateOutlet } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, Directive, TemplateRef, computed, contentChild, inject, input } from '@angular/core';\nimport { I18nService } from '@sdcorejs/angular/i18n';\nimport { SdAuditDiffOptions, SdAuditDiffRow, SdAuditDiffSide, sdBuildAuditDiff } from './audit-diff.engine';\n\nexport type SdAuditDiffMode = 'table' | 'detail-list';\n\nexport interface SdAuditDiffValueTemplateContext {\n readonly $implicit: unknown;\n readonly row: SdAuditDiffRow;\n readonly side: SdAuditDiffSide;\n}\n\n@Directive({\n selector: 'ng-template[sdAuditDiffValue]',\n standalone: true,\n})\nexport class SdAuditDiffValueTemplateDirective {\n readonly template = inject<TemplateRef<SdAuditDiffValueTemplateContext>>(TemplateRef);\n\n static ngTemplateContextGuard(\n _directive: SdAuditDiffValueTemplateDirective,\n _context: unknown\n ): _context is SdAuditDiffValueTemplateContext {\n return true;\n }\n}\n\n@Component({\n selector: 'sd-audit-diff',\n standalone: true,\n imports: [NgTemplateOutlet],\n templateUrl: './audit-diff.component.html',\n styleUrl: './audit-diff.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class SdAuditDiff {\n readonly before = input<unknown>(undefined);\n readonly after = input<unknown>(undefined);\n readonly options = input<SdAuditDiffOptions>({});\n readonly mode = input<SdAuditDiffMode>('table');\n readonly ariaLabel = input<string | undefined>(undefined);\n\n readonly #i18n = inject(I18nService);\n readonly rows = computed(() => {\n const options = this.options();\n return sdBuildAuditDiff(this.before(), this.after(), {\n ...options,\n rootLabel: options.rootLabel ?? this.text('value.label'),\n });\n });\n protected readonly valueTemplate = contentChild(SdAuditDiffValueTemplateDirective);\n\n protected text(key: string): string {\n return this.#i18n.t(`core.component.audit-diff.${key}`);\n }\n\n protected valueContext(row: SdAuditDiffRow, side: SdAuditDiffSide): SdAuditDiffValueTemplateContext {\n return { $implicit: row[side], row, side };\n }\n\n protected displayValue(row: SdAuditDiffRow, side: SdAuditDiffSide): string {\n const present = side === 'before' ? row.beforePresent : row.afterPresent;\n if (!present) return this.text('value.not-set');\n const value = row[side];\n if (value === undefined) return this.text('value.undefined');\n if (value === null) return this.text('value.null');\n if (value instanceof Date) return value.toISOString();\n if (typeof value === 'boolean') return this.text(`value.${value ? 'true' : 'false'}`);\n if (typeof value === 'string') return value;\n if (typeof value === 'number' || typeof value === 'bigint') return String(value);\n return safeStringify(value);\n }\n}\n\nfunction safeStringify(value: unknown): string {\n const seen = new WeakSet<object>();\n try {\n const result = JSON.stringify(value, (_key, current: unknown) => {\n if (typeof current !== 'object' || current === null) return current;\n if (seen.has(current)) return '[Circular]';\n seen.add(current);\n return current;\n });\n return result ?? String(value);\n } catch {\n return String(value);\n }\n}\n","@let currentRows = rows();\n@let customValue = valueTemplate();\n\n@if (currentRows.length === 0) {\n <p class=\"sd-audit-diff__empty\" data-audit-empty role=\"status\">{{ text('empty') }}</p>\n} @else if (mode() === 'table') {\n <div class=\"sd-audit-diff__table-scroll\">\n <table class=\"sd-audit-diff__table\" [attr.aria-label]=\"ariaLabel() || text('label')\">\n <thead>\n <tr>\n <th scope=\"col\">{{ text('field') }}</th>\n <th scope=\"col\">{{ text('before') }}</th>\n <th scope=\"col\">{{ text('after') }}</th>\n </tr>\n </thead>\n <tbody>\n @for (row of currentRows; track row.id) {\n <tr data-audit-row [attr.data-change-kind]=\"row.kind\">\n <th scope=\"row\">\n <span class=\"sd-audit-diff__field\">{{ row.label }}</span>\n <span class=\"sd-audit-diff__kind\">{{ text('kind.' + row.kind) }}</span>\n </th>\n <td data-audit-before>\n @if (customValue) {\n <ng-container\n [ngTemplateOutlet]=\"customValue.template\"\n [ngTemplateOutletContext]=\"valueContext(row, 'before')\"></ng-container>\n } @else {\n {{ displayValue(row, 'before') }}\n }\n </td>\n <td data-audit-after>\n @if (customValue) {\n <ng-container\n [ngTemplateOutlet]=\"customValue.template\"\n [ngTemplateOutletContext]=\"valueContext(row, 'after')\"></ng-container>\n } @else {\n {{ displayValue(row, 'after') }}\n }\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n} @else {\n <dl class=\"sd-audit-diff__details\" [attr.aria-label]=\"ariaLabel() || text('label')\">\n @for (row of currentRows; track row.id) {\n <div class=\"sd-audit-diff__detail\" data-audit-row [attr.data-change-kind]=\"row.kind\">\n <dt>\n <span class=\"sd-audit-diff__field\">{{ row.label }}</span>\n <span class=\"sd-audit-diff__kind\">{{ text('kind.' + row.kind) }}</span>\n </dt>\n <dd data-audit-before>\n <span class=\"sd-audit-diff__side-label\">{{ text('before') }}</span>\n @if (customValue) {\n <ng-container [ngTemplateOutlet]=\"customValue.template\" [ngTemplateOutletContext]=\"valueContext(row, 'before')\"></ng-container>\n } @else {\n <span>{{ displayValue(row, 'before') }}</span>\n }\n </dd>\n <dd data-audit-after>\n <span class=\"sd-audit-diff__side-label\">{{ text('after') }}</span>\n @if (customValue) {\n <ng-container [ngTemplateOutlet]=\"customValue.template\" [ngTemplateOutletContext]=\"valueContext(row, 'after')\"></ng-container>\n } @else {\n <span>{{ displayValue(row, 'after') }}</span>\n }\n </dd>\n </div>\n }\n </dl>\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -28,6 +28,7 @@ class SdBadge {
28
28
  // ==========================================
29
29
  // 2. OUTPUT
30
30
  // ==========================================
31
+ // why: the template reads EventEmitter.observed to expose pointer styling only when a click listener exists.
31
32
  click = new EventEmitter();
32
33
  onClick = (event) => {
33
34
  event.stopPropagation();
@@ -1 +1 @@
1
- {"version":3,"file":"sdcorejs-angular-components-badge.mjs","sources":["../../../projects/sdcorejs-angular/components/badge/src/badge.component.ts","../../../projects/sdcorejs-angular/components/badge/src/badge.component.html","../../../projects/sdcorejs-angular/components/badge/sdcorejs-angular-components-badge.ts"],"sourcesContent":["import { CommonModule } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, EventEmitter, Output, booleanAttribute, computed, input } from '@angular/core';\nimport { MatTooltipModule } from '@angular/material/tooltip';\nimport { SdIcon, type SdIconSet } from '@sdcorejs/angular/modules/icon';\nimport { Color, Size } from '@sdcorejs/utils/models';\n\n// Export các Type để dùng chung\nexport type SdBadgeType = 'tag' | 'round' | 'icon';\n\n@Component({\n selector: 'sd-badge',\n templateUrl: './badge.component.html',\n styleUrl: './badge.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n standalone: true,\n imports: [CommonModule, SdIcon, MatTooltipModule],\n})\nexport class SdBadge {\n defaultIcon = 'fiber_manual_record';\n\n // ==========================================\n // 1. SIGNAL INPUTS\n // ==========================================\n type = input<SdBadgeType, SdBadgeType | undefined | null>('icon', {\n transform: value => value || 'icon',\n });\n\n color = input<Color, Color | undefined | null>('secondary', {\n transform: value => value || 'secondary',\n });\n\n primary = input(false, { transform: booleanAttribute });\n secondary = input(false, { transform: booleanAttribute });\n success = input(false, { transform: booleanAttribute });\n info = input(false, { transform: booleanAttribute });\n warning = input(false, { transform: booleanAttribute });\n error = input(false, { transform: booleanAttribute });\n\n fontSet = input<SdIconSet | undefined, SdIconSet | undefined | null>(undefined, {\n transform: value => value ?? undefined,\n });\n\n title = input<string | number | undefined | null>();\n description = input<string | undefined | null>();\n tooltip = input<string | undefined | null>();\n icon = input<string | undefined | null>();\n\n size = input<Size, Size | undefined | null>('sm', {\n transform: value => value || 'sm',\n });\n\n // ==========================================\n // 2. OUTPUT\n // ==========================================\n @Output() click = new EventEmitter<Event>();\n\n onClick = (event: Event) => {\n event.stopPropagation();\n this.click.emit(event);\n };\n\n // ==========================================\n // 3. COMPUTED STATE\n // ==========================================\n\n effectiveColor = computed(() => {\n if (this.primary()) return 'primary';\n if (this.secondary()) return 'secondary';\n if (this.success()) return 'success';\n if (this.info()) return 'info';\n if (this.warning()) return 'warning';\n if (this.error()) return 'error';\n return this.color();\n });\n\n baseColorClasses = computed(() => {\n const c = this.effectiveColor();\n return {\n 'c-primary': c === 'primary',\n 'c-secondary': c === 'secondary',\n 'c-info': c === 'info',\n 'c-success': c === 'success',\n 'c-warning': c === 'warning',\n 'c-error': c === 'error',\n };\n });\n\n iconColorClasses = computed(() => {\n const c = this.effectiveColor();\n return {\n 'c-primary': c === 'primary',\n 'c-secondary': c === 'secondary',\n 'c-info': c === 'info',\n 'c-success': c === 'success',\n 'c-warning': c === 'warning',\n 'c-error': c === 'error',\n };\n });\n\n iconSizeAndFontClasses = computed(() => {\n const s = this.size();\n return {\n 'c-sm': s === 'sm',\n 'c-md': s === 'md',\n 'c-lg': s === 'lg',\n };\n });\n\n iconCssSize = computed(() => {\n const s = this.size();\n if (s === 'md') return '18px';\n if (s === 'lg') return '24px';\n return '16px';\n });\n\n // why: keep container size classes separate from icon element size classes.\n containerSizeClasses = computed(() => {\n const s = this.size();\n return {\n 'c-badge--sm': s === 'sm',\n 'c-badge--md': s === 'md',\n 'c-badge--lg': s === 'lg',\n };\n });\n\n // GỘP CLASS CHO BADGE TYPE = 'TAG' (cũng dùng lại cho 'ROUND' khi có icon)\n tagIconCombinedClasses = computed(() => ({\n ...this.iconSizeAndFontClasses(),\n ...this.baseColorClasses(),\n }));\n\n // GỘP CLASS CHO CONTAINER round/tag (color tint + size modifier)\n containerCombinedClasses = computed(() => ({\n ...this.baseColorClasses(),\n ...this.containerSizeClasses(),\n }));\n\n // GỘP CLASS CHO BADGE TYPE = 'ICON'\n iconCombinedClasses = computed(() => ({\n ...this.iconSizeAndFontClasses(),\n ...this.iconColorClasses(),\n }));\n}\n","@let _type = type();\n@let _tooltip = tooltip();\n@let _title = title();\n@let _description = description();\n@let _fontSet = fontSet();\n@let _iconCssSize = iconCssSize();\n@let iconName = icon() || defaultIcon;\n@let isPointer = click.observed;\n\n@if (_type === 'round') {\n <div\n class=\"c-badge\"\n matTooltipPosition=\"above\"\n [matTooltip]=\"_tooltip || ''\"\n matTooltipClass=\"sd-multiline-tooltip\"\n [ngClass]=\"containerCombinedClasses()\"\n [class.c-badge--has-icon]=\"!!icon()\"\n [class.pointer]=\"isPointer\"\n (click)=\"onClick($event)\"\n aria-hidden=\"true\">\n @if (icon()) {\n <sd-icon\n class=\"c-material-icon\"\n [name]=\"iconName\"\n [fontSet]=\"_fontSet\"\n [size]=\"_iconCssSize\"\n [ngClass]=\"tagIconCombinedClasses()\"></sd-icon>\n }\n <span class=\"c-badge-title\">{{ _title }}</span>\n </div>\n} @else if (_type === 'tag') {\n <div\n class=\"c-badge c-badge--tag\"\n matTooltipPosition=\"above\"\n [matTooltip]=\"_tooltip || ''\"\n matTooltipClass=\"sd-multiline-tooltip\"\n [ngClass]=\"containerCombinedClasses()\"\n [class.pointer]=\"isPointer\"\n (click)=\"onClick($event)\"\n aria-hidden=\"true\">\n <div class=\"c-icon d-flex align-items-center\">\n @if (icon()) {\n <sd-icon\n class=\"c-material-icon mr-4\"\n [name]=\"iconName\"\n [fontSet]=\"_fontSet\"\n [size]=\"_iconCssSize\"\n [ngClass]=\"tagIconCombinedClasses()\"></sd-icon>\n }\n <div class=\"d-flex flex-column align-items-start\">\n <span class=\"T14R c-badge-title\">{{ _title }}</span>\n @if (_description) {\n <span class=\"T12R c-badge-description\">{{ _description }}</span>\n }\n </div>\n </div>\n </div>\n} @else {\n <div\n class=\"d-flex\"\n matTooltipPosition=\"above\"\n [matTooltip]=\"_tooltip || ''\"\n matTooltipClass=\"sd-multiline-tooltip\"\n [class.c-badge-icon]=\"_type === 'icon'\"\n [class.pointer]=\"isPointer\"\n (click)=\"onClick($event)\"\n aria-hidden=\"true\">\n <div class=\"c-icon d-flex align-items-center\">\n <sd-icon\n class=\"c-material-icon mr-4\"\n [name]=\"iconName\"\n [fontSet]=\"_fontSet\"\n [size]=\"_iconCssSize\"\n [ngClass]=\"iconCombinedClasses()\"></sd-icon>\n <div class=\"d-flex flex-column\">\n <span class=\"T14R c-badge-title\">{{ _title }}</span>\n @if (_description) {\n <span class=\"T10R c-badge-description\">{{ _description }}</span>\n }\n </div>\n </div>\n </div>\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sdcorejs-angular-components-badge.mjs","sources":["../../../projects/sdcorejs-angular/components/badge/src/badge.component.ts","../../../projects/sdcorejs-angular/components/badge/src/badge.component.html","../../../projects/sdcorejs-angular/components/badge/sdcorejs-angular-components-badge.ts"],"sourcesContent":["import { CommonModule } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, EventEmitter, Output, booleanAttribute, computed, input } from '@angular/core';\nimport { MatTooltipModule } from '@angular/material/tooltip';\nimport { SdIcon, type SdIconSet } from '@sdcorejs/angular/modules/icon';\nimport { Color, Size } from '@sdcorejs/utils/models';\n\n// Export các Type để dùng chung\nexport type SdBadgeType = 'tag' | 'round' | 'icon';\n\n@Component({\n selector: 'sd-badge',\n templateUrl: './badge.component.html',\n styleUrl: './badge.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n standalone: true,\n imports: [CommonModule, SdIcon, MatTooltipModule],\n})\nexport class SdBadge {\n defaultIcon = 'fiber_manual_record';\n\n // ==========================================\n // 1. SIGNAL INPUTS\n // ==========================================\n type = input<SdBadgeType, SdBadgeType | undefined | null>('icon', {\n transform: value => value || 'icon',\n });\n\n color = input<Color, Color | undefined | null>('secondary', {\n transform: value => value || 'secondary',\n });\n\n primary = input(false, { transform: booleanAttribute });\n secondary = input(false, { transform: booleanAttribute });\n success = input(false, { transform: booleanAttribute });\n info = input(false, { transform: booleanAttribute });\n warning = input(false, { transform: booleanAttribute });\n error = input(false, { transform: booleanAttribute });\n\n fontSet = input<SdIconSet | undefined, SdIconSet | undefined | null>(undefined, {\n transform: value => value ?? undefined,\n });\n\n title = input<string | number | undefined | null>();\n description = input<string | undefined | null>();\n tooltip = input<string | undefined | null>();\n icon = input<string | undefined | null>();\n\n size = input<Size, Size | undefined | null>('sm', {\n transform: value => value || 'sm',\n });\n\n // ==========================================\n // 2. OUTPUT\n // ==========================================\n // why: the template reads EventEmitter.observed to expose pointer styling only when a click listener exists.\n @Output() readonly click = new EventEmitter<Event>();\n\n onClick = (event: Event) => {\n event.stopPropagation();\n this.click.emit(event);\n };\n\n // ==========================================\n // 3. COMPUTED STATE\n // ==========================================\n\n effectiveColor = computed(() => {\n if (this.primary()) return 'primary';\n if (this.secondary()) return 'secondary';\n if (this.success()) return 'success';\n if (this.info()) return 'info';\n if (this.warning()) return 'warning';\n if (this.error()) return 'error';\n return this.color();\n });\n\n baseColorClasses = computed(() => {\n const c = this.effectiveColor();\n return {\n 'c-primary': c === 'primary',\n 'c-secondary': c === 'secondary',\n 'c-info': c === 'info',\n 'c-success': c === 'success',\n 'c-warning': c === 'warning',\n 'c-error': c === 'error',\n };\n });\n\n iconColorClasses = computed(() => {\n const c = this.effectiveColor();\n return {\n 'c-primary': c === 'primary',\n 'c-secondary': c === 'secondary',\n 'c-info': c === 'info',\n 'c-success': c === 'success',\n 'c-warning': c === 'warning',\n 'c-error': c === 'error',\n };\n });\n\n iconSizeAndFontClasses = computed(() => {\n const s = this.size();\n return {\n 'c-sm': s === 'sm',\n 'c-md': s === 'md',\n 'c-lg': s === 'lg',\n };\n });\n\n iconCssSize = computed(() => {\n const s = this.size();\n if (s === 'md') return '18px';\n if (s === 'lg') return '24px';\n return '16px';\n });\n\n // why: keep container size classes separate from icon element size classes.\n containerSizeClasses = computed(() => {\n const s = this.size();\n return {\n 'c-badge--sm': s === 'sm',\n 'c-badge--md': s === 'md',\n 'c-badge--lg': s === 'lg',\n };\n });\n\n // GỘP CLASS CHO BADGE TYPE = 'TAG' (cũng dùng lại cho 'ROUND' khi có icon)\n tagIconCombinedClasses = computed(() => ({\n ...this.iconSizeAndFontClasses(),\n ...this.baseColorClasses(),\n }));\n\n // GỘP CLASS CHO CONTAINER round/tag (color tint + size modifier)\n containerCombinedClasses = computed(() => ({\n ...this.baseColorClasses(),\n ...this.containerSizeClasses(),\n }));\n\n // GỘP CLASS CHO BADGE TYPE = 'ICON'\n iconCombinedClasses = computed(() => ({\n ...this.iconSizeAndFontClasses(),\n ...this.iconColorClasses(),\n }));\n}\n","@let _type = type();\n@let _tooltip = tooltip();\n@let _title = title();\n@let _description = description();\n@let _fontSet = fontSet();\n@let _iconCssSize = iconCssSize();\n@let iconName = icon() || defaultIcon;\n@let isPointer = click.observed;\n\n@if (_type === 'round') {\n <div\n class=\"c-badge\"\n matTooltipPosition=\"above\"\n [matTooltip]=\"_tooltip || ''\"\n matTooltipClass=\"sd-multiline-tooltip\"\n [ngClass]=\"containerCombinedClasses()\"\n [class.c-badge--has-icon]=\"!!icon()\"\n [class.pointer]=\"isPointer\"\n (click)=\"onClick($event)\"\n aria-hidden=\"true\">\n @if (icon()) {\n <sd-icon\n class=\"c-material-icon\"\n [name]=\"iconName\"\n [fontSet]=\"_fontSet\"\n [size]=\"_iconCssSize\"\n [ngClass]=\"tagIconCombinedClasses()\"></sd-icon>\n }\n <span class=\"c-badge-title\">{{ _title }}</span>\n </div>\n} @else if (_type === 'tag') {\n <div\n class=\"c-badge c-badge--tag\"\n matTooltipPosition=\"above\"\n [matTooltip]=\"_tooltip || ''\"\n matTooltipClass=\"sd-multiline-tooltip\"\n [ngClass]=\"containerCombinedClasses()\"\n [class.pointer]=\"isPointer\"\n (click)=\"onClick($event)\"\n aria-hidden=\"true\">\n <div class=\"c-icon d-flex align-items-center\">\n @if (icon()) {\n <sd-icon\n class=\"c-material-icon mr-4\"\n [name]=\"iconName\"\n [fontSet]=\"_fontSet\"\n [size]=\"_iconCssSize\"\n [ngClass]=\"tagIconCombinedClasses()\"></sd-icon>\n }\n <div class=\"d-flex flex-column align-items-start\">\n <span class=\"T14R c-badge-title\">{{ _title }}</span>\n @if (_description) {\n <span class=\"T12R c-badge-description\">{{ _description }}</span>\n }\n </div>\n </div>\n </div>\n} @else {\n <div\n class=\"d-flex\"\n matTooltipPosition=\"above\"\n [matTooltip]=\"_tooltip || ''\"\n matTooltipClass=\"sd-multiline-tooltip\"\n [class.c-badge-icon]=\"_type === 'icon'\"\n [class.pointer]=\"isPointer\"\n (click)=\"onClick($event)\"\n aria-hidden=\"true\">\n <div class=\"c-icon d-flex align-items-center\">\n <sd-icon\n class=\"c-material-icon mr-4\"\n [name]=\"iconName\"\n [fontSet]=\"_fontSet\"\n [size]=\"_iconCssSize\"\n [ngClass]=\"iconCombinedClasses()\"></sd-icon>\n <div class=\"d-flex flex-column\">\n <span class=\"T14R c-badge-title\">{{ _title }}</span>\n @if (_description) {\n <span class=\"T10R c-badge-description\">{{ _description }}</span>\n }\n </div>\n </div>\n </div>\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,121 @@
1
+ import { NgTemplateOutlet } from '@angular/common';
2
+ import * as i0 from '@angular/core';
3
+ import { inject, signal, input, output, contentChild, TemplateRef, computed, effect, ChangeDetectionStrategy, Component } from '@angular/core';
4
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
5
+ import { Router, NavigationEnd, PRIMARY_OUTLET } from '@angular/router';
6
+ import { normalizeAsync } from '@sdcorejs/utils/models';
7
+ import { SdIcon } from '@sdcorejs/angular/modules/icon';
8
+ import { filter, combineLatest, defer, map, catchError, of } from 'rxjs';
9
+
10
+ class SdBreadcrumb {
11
+ #router = inject(Router, { optional: true });
12
+ #routeVersion = signal(0, ...(ngDevMode ? [{ debugName: "#routeVersion" }] : /* istanbul ignore next */ []));
13
+ #resolvedItems = signal([], ...(ngDevMode ? [{ debugName: "#resolvedItems" }] : /* istanbul ignore next */ []));
14
+ items = input(undefined, ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
15
+ maxItems = input(5, { ...(ngDevMode ? { debugName: "maxItems" } : /* istanbul ignore next */ {}), transform: normalizeMaxItems });
16
+ ariaLabel = input('Breadcrumb', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
17
+ separator = input('chevron_right', ...(ngDevMode ? [{ debugName: "separator" }] : /* istanbul ignore next */ []));
18
+ sdItemActivate = output();
19
+ itemTemplate = contentChild(TemplateRef, ...(ngDevMode ? [{ debugName: "itemTemplate" }] : /* istanbul ignore next */ []));
20
+ visibleEntries = computed(() => {
21
+ const entries = this.#resolvedItems().map(item => ({ kind: 'item', item }));
22
+ const maxItems = this.maxItems();
23
+ if (entries.length <= maxItems)
24
+ return entries;
25
+ const tailCount = maxItems - 2;
26
+ return [entries[0], { kind: 'ellipsis' }, ...entries.slice(-tailCount)];
27
+ }, ...(ngDevMode ? [{ debugName: "visibleEntries" }] : /* istanbul ignore next */ []));
28
+ constructor() {
29
+ this.#router?.events
30
+ .pipe(filter((event) => event instanceof NavigationEnd), takeUntilDestroyed())
31
+ .subscribe(() => this.#routeVersion.update(version => version + 1));
32
+ effect(onCleanup => {
33
+ const providedItems = this.items();
34
+ if (providedItems == null)
35
+ this.#routeVersion();
36
+ const sourceItems = providedItems ?? this.#createRouteItems();
37
+ if (sourceItems.length === 0) {
38
+ this.#resolvedItems.set([]);
39
+ return;
40
+ }
41
+ const subscription = combineLatest(sourceItems.map(item => defer(() => normalizeAsync(resolveLabelSource(item.label, item.route))).pipe(map(label => ({
42
+ ...item,
43
+ label: String(label ?? '').trim(),
44
+ source: item,
45
+ })), catchError(() => of({ ...item, label: '', source: item }))))).subscribe(items => this.#resolvedItems.set(items.filter(item => item.label)));
46
+ onCleanup(() => subscription.unsubscribe());
47
+ });
48
+ }
49
+ activate(item, event) {
50
+ if (item.disabled) {
51
+ event.preventDefault();
52
+ return;
53
+ }
54
+ this.sdItemActivate.emit(item.source);
55
+ if (!item.url || !this.#router || isModifiedMouseEvent(event))
56
+ return;
57
+ event.preventDefault();
58
+ if (typeof item.url === 'string') {
59
+ void this.#router.navigateByUrl(item.url);
60
+ }
61
+ else {
62
+ void this.#router.navigate(item.url);
63
+ }
64
+ }
65
+ href(item) {
66
+ return typeof item.url === 'string' ? item.url : null;
67
+ }
68
+ templateContext(item) {
69
+ return { $implicit: item, item };
70
+ }
71
+ #createRouteItems() {
72
+ const root = this.#router?.routerState.snapshot.root;
73
+ if (!root)
74
+ return [];
75
+ const items = [];
76
+ const segments = [];
77
+ let route = root;
78
+ while (route) {
79
+ if (route.outlet === PRIMARY_OUTLET) {
80
+ segments.push(...route.url.map(segment => segment.path).filter(Boolean));
81
+ const value = route.data['breadcrumb'];
82
+ if (value !== undefined && value !== null) {
83
+ const config = isRouteConfig(value) ? value : { label: value };
84
+ items.push({
85
+ ...config,
86
+ url: config.url ?? `/${segments.join('/')}`,
87
+ route,
88
+ });
89
+ }
90
+ }
91
+ route = route.children?.find(child => child.outlet === PRIMARY_OUTLET) ?? route.firstChild;
92
+ }
93
+ return items;
94
+ }
95
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SdBreadcrumb, deps: [], target: i0.ɵɵFactoryTarget.Component });
96
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: SdBreadcrumb, isStandalone: true, selector: "sd-breadcrumb", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, maxItems: { classPropertyName: "maxItems", publicName: "maxItems", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, separator: { classPropertyName: "separator", publicName: "separator", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sdItemActivate: "sdItemActivate" }, queries: [{ propertyName: "itemTemplate", first: true, predicate: TemplateRef, descendants: true, isSignal: true }], ngImport: i0, template: "<nav class=\"sd-breadcrumb\" [attr.aria-label]=\"ariaLabel()\">\n <ol class=\"sd-breadcrumb__list\">\n @for (entry of visibleEntries(); track entry.kind === 'item' ? entry.item : $index; let last = $last) {\n <li class=\"sd-breadcrumb__entry\">\n @if (entry.kind === 'ellipsis') {\n <span class=\"sd-breadcrumb__ellipsis\" aria-hidden=\"true\">\u2026</span>\n } @else {\n @let item = entry.item;\n @let template = itemTemplate();\n @if (!last && !item.disabled && href(item) !== null) {\n <a class=\"sd-breadcrumb__item\" [attr.href]=\"href(item)\" (click)=\"activate(item, $event)\">\n @if (template) {\n <ng-container [ngTemplateOutlet]=\"template\" [ngTemplateOutletContext]=\"templateContext(item)\"></ng-container>\n } @else {\n @if (item.icon) {\n <sd-icon class=\"sd-breadcrumb__icon\" aria-hidden=\"true\" [name]=\"item.icon\" [fontSet]=\"item.fontSet\"></sd-icon>\n }\n <span>{{ item.label }}</span>\n }\n </a>\n } @else if (!last && !item.disabled && (item.url || item.clickable)) {\n <button type=\"button\" class=\"sd-breadcrumb__item\" (click)=\"activate(item, $event)\">\n @if (template) {\n <ng-container [ngTemplateOutlet]=\"template\" [ngTemplateOutletContext]=\"templateContext(item)\"></ng-container>\n } @else {\n @if (item.icon) {\n <sd-icon class=\"sd-breadcrumb__icon\" aria-hidden=\"true\" [name]=\"item.icon\" [fontSet]=\"item.fontSet\"></sd-icon>\n }\n <span>{{ item.label }}</span>\n }\n </button>\n } @else {\n <span\n class=\"sd-breadcrumb__item\"\n [class.sd-breadcrumb__item--disabled]=\"item.disabled\"\n [attr.aria-disabled]=\"item.disabled ? 'true' : null\"\n [attr.aria-current]=\"last ? 'page' : null\">\n @if (template) {\n <ng-container [ngTemplateOutlet]=\"template\" [ngTemplateOutletContext]=\"templateContext(item)\"></ng-container>\n } @else {\n @if (item.icon) {\n <sd-icon class=\"sd-breadcrumb__icon\" aria-hidden=\"true\" [name]=\"item.icon\" [fontSet]=\"item.fontSet\"></sd-icon>\n }\n <span>{{ item.label }}</span>\n }\n </span>\n }\n }\n\n @if (!last) {\n <sd-icon class=\"sd-breadcrumb__separator\" aria-hidden=\"true\" [name]=\"separator()\"></sd-icon>\n }\n </li>\n }\n </ol>\n</nav>\n", styles: [":host{display:block;min-width:0}.sd-breadcrumb__list{display:flex;align-items:center;gap:4px;min-width:0;margin:0;padding:0;list-style:none}.sd-breadcrumb__entry{display:inline-flex;align-items:center;min-width:0}.sd-breadcrumb__item{display:inline-flex;align-items:center;gap:4px;min-width:0;max-width:240px;padding:4px;border:0;border-radius:4px;background:transparent;color:var(--sd-text-secondary, #667085);font:inherit;text-decoration:none;cursor:pointer}.sd-breadcrumb__item span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sd-breadcrumb__item:focus-visible{outline:2px solid var(--sd-info, #1677ff);outline-offset:2px}.sd-breadcrumb__item[aria-current=page],.sd-breadcrumb__item--disabled{color:var(--sd-text, #2f3136);cursor:default}.sd-breadcrumb__item--disabled{opacity:.55}.sd-breadcrumb__ellipsis{padding:4px;color:var(--sd-text-secondary, #667085)}.sd-breadcrumb__separator{margin-inline:2px;color:var(--sd-text-disabled, #98a2b3)}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: SdIcon, selector: "sd-icon", inputs: ["name", "fontIcon", "color", "set", "fontSet", "size", "strokeWidth", "absoluteStrokeWidth", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
97
+ }
98
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SdBreadcrumb, decorators: [{
99
+ type: Component,
100
+ args: [{ selector: 'sd-breadcrumb', standalone: true, imports: [NgTemplateOutlet, SdIcon], changeDetection: ChangeDetectionStrategy.OnPush, template: "<nav class=\"sd-breadcrumb\" [attr.aria-label]=\"ariaLabel()\">\n <ol class=\"sd-breadcrumb__list\">\n @for (entry of visibleEntries(); track entry.kind === 'item' ? entry.item : $index; let last = $last) {\n <li class=\"sd-breadcrumb__entry\">\n @if (entry.kind === 'ellipsis') {\n <span class=\"sd-breadcrumb__ellipsis\" aria-hidden=\"true\">\u2026</span>\n } @else {\n @let item = entry.item;\n @let template = itemTemplate();\n @if (!last && !item.disabled && href(item) !== null) {\n <a class=\"sd-breadcrumb__item\" [attr.href]=\"href(item)\" (click)=\"activate(item, $event)\">\n @if (template) {\n <ng-container [ngTemplateOutlet]=\"template\" [ngTemplateOutletContext]=\"templateContext(item)\"></ng-container>\n } @else {\n @if (item.icon) {\n <sd-icon class=\"sd-breadcrumb__icon\" aria-hidden=\"true\" [name]=\"item.icon\" [fontSet]=\"item.fontSet\"></sd-icon>\n }\n <span>{{ item.label }}</span>\n }\n </a>\n } @else if (!last && !item.disabled && (item.url || item.clickable)) {\n <button type=\"button\" class=\"sd-breadcrumb__item\" (click)=\"activate(item, $event)\">\n @if (template) {\n <ng-container [ngTemplateOutlet]=\"template\" [ngTemplateOutletContext]=\"templateContext(item)\"></ng-container>\n } @else {\n @if (item.icon) {\n <sd-icon class=\"sd-breadcrumb__icon\" aria-hidden=\"true\" [name]=\"item.icon\" [fontSet]=\"item.fontSet\"></sd-icon>\n }\n <span>{{ item.label }}</span>\n }\n </button>\n } @else {\n <span\n class=\"sd-breadcrumb__item\"\n [class.sd-breadcrumb__item--disabled]=\"item.disabled\"\n [attr.aria-disabled]=\"item.disabled ? 'true' : null\"\n [attr.aria-current]=\"last ? 'page' : null\">\n @if (template) {\n <ng-container [ngTemplateOutlet]=\"template\" [ngTemplateOutletContext]=\"templateContext(item)\"></ng-container>\n } @else {\n @if (item.icon) {\n <sd-icon class=\"sd-breadcrumb__icon\" aria-hidden=\"true\" [name]=\"item.icon\" [fontSet]=\"item.fontSet\"></sd-icon>\n }\n <span>{{ item.label }}</span>\n }\n </span>\n }\n }\n\n @if (!last) {\n <sd-icon class=\"sd-breadcrumb__separator\" aria-hidden=\"true\" [name]=\"separator()\"></sd-icon>\n }\n </li>\n }\n </ol>\n</nav>\n", styles: [":host{display:block;min-width:0}.sd-breadcrumb__list{display:flex;align-items:center;gap:4px;min-width:0;margin:0;padding:0;list-style:none}.sd-breadcrumb__entry{display:inline-flex;align-items:center;min-width:0}.sd-breadcrumb__item{display:inline-flex;align-items:center;gap:4px;min-width:0;max-width:240px;padding:4px;border:0;border-radius:4px;background:transparent;color:var(--sd-text-secondary, #667085);font:inherit;text-decoration:none;cursor:pointer}.sd-breadcrumb__item span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sd-breadcrumb__item:focus-visible{outline:2px solid var(--sd-info, #1677ff);outline-offset:2px}.sd-breadcrumb__item[aria-current=page],.sd-breadcrumb__item--disabled{color:var(--sd-text, #2f3136);cursor:default}.sd-breadcrumb__item--disabled{opacity:.55}.sd-breadcrumb__ellipsis{padding:4px;color:var(--sd-text-secondary, #667085)}.sd-breadcrumb__separator{margin-inline:2px;color:var(--sd-text-disabled, #98a2b3)}\n"] }]
101
+ }], ctorParameters: () => [], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], maxItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxItems", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], separator: [{ type: i0.Input, args: [{ isSignal: true, alias: "separator", required: false }] }], sdItemActivate: [{ type: i0.Output, args: ["sdItemActivate"] }], itemTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => TemplateRef), { isSignal: true }] }] } });
102
+ function resolveLabelSource(label, route) {
103
+ return typeof label === 'function' ? label(route) : label;
104
+ }
105
+ function isRouteConfig(value) {
106
+ return typeof value === 'object' && value !== null && 'label' in value;
107
+ }
108
+ function normalizeMaxItems(value) {
109
+ const parsed = Number(value);
110
+ return Number.isFinite(parsed) ? Math.max(3, Math.floor(parsed)) : 5;
111
+ }
112
+ function isModifiedMouseEvent(event) {
113
+ return event instanceof MouseEvent && (event.button !== 0 || event.ctrlKey || event.metaKey || event.shiftKey || event.altKey);
114
+ }
115
+
116
+ /**
117
+ * Generated bundle index. Do not edit.
118
+ */
119
+
120
+ export { SdBreadcrumb };
121
+ //# sourceMappingURL=sdcorejs-angular-components-breadcrumb.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdcorejs-angular-components-breadcrumb.mjs","sources":["../../../projects/sdcorejs-angular/components/breadcrumb/src/breadcrumb.component.ts","../../../projects/sdcorejs-angular/components/breadcrumb/src/breadcrumb.component.html","../../../projects/sdcorejs-angular/components/breadcrumb/sdcorejs-angular-components-breadcrumb.ts"],"sourcesContent":["import { NgTemplateOutlet } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n TemplateRef,\n computed,\n contentChild,\n effect,\n inject,\n input,\n output,\n signal,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { ActivatedRouteSnapshot, NavigationEnd, PRIMARY_OUTLET, Router } from '@angular/router';\nimport { MaybeAsync, normalizeAsync } from '@sdcorejs/utils/models';\nimport { SdIcon, SdIconSet } from '@sdcorejs/angular/modules/icon';\nimport { catchError, combineLatest, defer, filter, map, of } from 'rxjs';\n\nexport type SdBreadcrumbLabel =\n | MaybeAsync<string | null | undefined>\n | ((route?: ActivatedRouteSnapshot) => MaybeAsync<string | null | undefined>);\n\nexport interface SdBreadcrumbItem {\n readonly label: SdBreadcrumbLabel;\n readonly url?: string | unknown[];\n readonly icon?: string;\n readonly fontSet?: SdIconSet;\n readonly disabled?: boolean;\n readonly clickable?: boolean;\n}\n\nexport interface SdBreadcrumbRouteConfig extends Omit<SdBreadcrumbItem, 'url'> {\n readonly url?: string | unknown[];\n}\n\nexport interface SdBreadcrumbResolvedItem extends Omit<SdBreadcrumbItem, 'label'> {\n readonly label: string;\n readonly source: SdBreadcrumbItem;\n}\n\nexport interface SdBreadcrumbItemTemplateContext {\n readonly $implicit: SdBreadcrumbResolvedItem;\n readonly item: SdBreadcrumbResolvedItem;\n}\n\ninterface SdBreadcrumbItemEntry {\n readonly kind: 'item';\n readonly item: SdBreadcrumbResolvedItem;\n}\n\ninterface SdBreadcrumbEllipsisEntry {\n readonly kind: 'ellipsis';\n}\n\ntype SdBreadcrumbEntry = SdBreadcrumbItemEntry | SdBreadcrumbEllipsisEntry;\n\ninterface SdBreadcrumbSourceItem extends SdBreadcrumbItem {\n readonly route?: ActivatedRouteSnapshot;\n}\n\n@Component({\n selector: 'sd-breadcrumb',\n standalone: true,\n imports: [NgTemplateOutlet, SdIcon],\n templateUrl: './breadcrumb.component.html',\n styleUrl: './breadcrumb.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class SdBreadcrumb {\n readonly #router = inject(Router, { optional: true });\n readonly #routeVersion = signal(0);\n readonly #resolvedItems = signal<SdBreadcrumbResolvedItem[]>([]);\n\n readonly items = input<readonly SdBreadcrumbItem[] | null | undefined>(undefined);\n readonly maxItems = input(5, { transform: normalizeMaxItems });\n readonly ariaLabel = input('Breadcrumb');\n readonly separator = input('chevron_right');\n readonly sdItemActivate = output<SdBreadcrumbItem>();\n\n protected readonly itemTemplate = contentChild<TemplateRef<SdBreadcrumbItemTemplateContext>>(TemplateRef);\n protected readonly visibleEntries = computed<readonly SdBreadcrumbEntry[]>(() => {\n const entries = this.#resolvedItems().map(item => ({ kind: 'item' as const, item }));\n const maxItems = this.maxItems();\n if (entries.length <= maxItems) return entries;\n\n const tailCount = maxItems - 2;\n return [entries[0]!, { kind: 'ellipsis' as const }, ...entries.slice(-tailCount)];\n });\n\n constructor() {\n this.#router?.events\n .pipe(\n filter((event): event is NavigationEnd => event instanceof NavigationEnd),\n takeUntilDestroyed()\n )\n .subscribe(() => this.#routeVersion.update(version => version + 1));\n\n effect(onCleanup => {\n const providedItems = this.items();\n if (providedItems == null) this.#routeVersion();\n const sourceItems: readonly SdBreadcrumbSourceItem[] = providedItems ?? this.#createRouteItems();\n if (sourceItems.length === 0) {\n this.#resolvedItems.set([]);\n return;\n }\n\n const subscription = combineLatest(\n sourceItems.map(item =>\n defer(() => normalizeAsync(resolveLabelSource(item.label, item.route))).pipe(\n map(label => ({\n ...item,\n label: String(label ?? '').trim(),\n source: item,\n })),\n catchError(() => of({ ...item, label: '', source: item }))\n )\n )\n ).subscribe(items => this.#resolvedItems.set(items.filter(item => item.label)));\n onCleanup(() => subscription.unsubscribe());\n });\n }\n\n protected activate(item: SdBreadcrumbResolvedItem, event: Event): void {\n if (item.disabled) {\n event.preventDefault();\n return;\n }\n this.sdItemActivate.emit(item.source);\n\n if (!item.url || !this.#router || isModifiedMouseEvent(event)) return;\n event.preventDefault();\n if (typeof item.url === 'string') {\n void this.#router.navigateByUrl(item.url);\n } else {\n void this.#router.navigate(item.url);\n }\n }\n\n protected href(item: SdBreadcrumbResolvedItem): string | null {\n return typeof item.url === 'string' ? item.url : null;\n }\n\n protected templateContext(item: SdBreadcrumbResolvedItem): SdBreadcrumbItemTemplateContext {\n return { $implicit: item, item };\n }\n\n #createRouteItems(): SdBreadcrumbSourceItem[] {\n const root = this.#router?.routerState.snapshot.root;\n if (!root) return [];\n\n const items: SdBreadcrumbSourceItem[] = [];\n const segments: string[] = [];\n let route: ActivatedRouteSnapshot | null = root;\n\n while (route) {\n if (route.outlet === PRIMARY_OUTLET) {\n segments.push(...route.url.map(segment => segment.path).filter(Boolean));\n const value = route.data['breadcrumb'] as SdBreadcrumbLabel | SdBreadcrumbRouteConfig | undefined;\n if (value !== undefined && value !== null) {\n const config = isRouteConfig(value) ? value : { label: value };\n items.push({\n ...config,\n url: config.url ?? `/${segments.join('/')}`,\n route,\n });\n }\n }\n route = route.children?.find(child => child.outlet === PRIMARY_OUTLET) ?? route.firstChild;\n }\n\n return items;\n }\n}\n\nfunction resolveLabelSource(label: SdBreadcrumbLabel, route?: ActivatedRouteSnapshot): MaybeAsync<string | null | undefined> {\n return typeof label === 'function' ? label(route) : label;\n}\n\nfunction isRouteConfig(value: SdBreadcrumbLabel | SdBreadcrumbRouteConfig): value is SdBreadcrumbRouteConfig {\n return typeof value === 'object' && value !== null && 'label' in value;\n}\n\nfunction normalizeMaxItems(value: number | string | null | undefined): number {\n const parsed = Number(value);\n return Number.isFinite(parsed) ? Math.max(3, Math.floor(parsed)) : 5;\n}\n\nfunction isModifiedMouseEvent(event: Event): boolean {\n return event instanceof MouseEvent && (event.button !== 0 || event.ctrlKey || event.metaKey || event.shiftKey || event.altKey);\n}\n","<nav class=\"sd-breadcrumb\" [attr.aria-label]=\"ariaLabel()\">\n <ol class=\"sd-breadcrumb__list\">\n @for (entry of visibleEntries(); track entry.kind === 'item' ? entry.item : $index; let last = $last) {\n <li class=\"sd-breadcrumb__entry\">\n @if (entry.kind === 'ellipsis') {\n <span class=\"sd-breadcrumb__ellipsis\" aria-hidden=\"true\">…</span>\n } @else {\n @let item = entry.item;\n @let template = itemTemplate();\n @if (!last && !item.disabled && href(item) !== null) {\n <a class=\"sd-breadcrumb__item\" [attr.href]=\"href(item)\" (click)=\"activate(item, $event)\">\n @if (template) {\n <ng-container [ngTemplateOutlet]=\"template\" [ngTemplateOutletContext]=\"templateContext(item)\"></ng-container>\n } @else {\n @if (item.icon) {\n <sd-icon class=\"sd-breadcrumb__icon\" aria-hidden=\"true\" [name]=\"item.icon\" [fontSet]=\"item.fontSet\"></sd-icon>\n }\n <span>{{ item.label }}</span>\n }\n </a>\n } @else if (!last && !item.disabled && (item.url || item.clickable)) {\n <button type=\"button\" class=\"sd-breadcrumb__item\" (click)=\"activate(item, $event)\">\n @if (template) {\n <ng-container [ngTemplateOutlet]=\"template\" [ngTemplateOutletContext]=\"templateContext(item)\"></ng-container>\n } @else {\n @if (item.icon) {\n <sd-icon class=\"sd-breadcrumb__icon\" aria-hidden=\"true\" [name]=\"item.icon\" [fontSet]=\"item.fontSet\"></sd-icon>\n }\n <span>{{ item.label }}</span>\n }\n </button>\n } @else {\n <span\n class=\"sd-breadcrumb__item\"\n [class.sd-breadcrumb__item--disabled]=\"item.disabled\"\n [attr.aria-disabled]=\"item.disabled ? 'true' : null\"\n [attr.aria-current]=\"last ? 'page' : null\">\n @if (template) {\n <ng-container [ngTemplateOutlet]=\"template\" [ngTemplateOutletContext]=\"templateContext(item)\"></ng-container>\n } @else {\n @if (item.icon) {\n <sd-icon class=\"sd-breadcrumb__icon\" aria-hidden=\"true\" [name]=\"item.icon\" [fontSet]=\"item.fontSet\"></sd-icon>\n }\n <span>{{ item.label }}</span>\n }\n </span>\n }\n }\n\n @if (!last) {\n <sd-icon class=\"sd-breadcrumb__separator\" aria-hidden=\"true\" [name]=\"separator()\"></sd-icon>\n }\n </li>\n }\n </ol>\n</nav>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ import { NgTemplateOutlet } from '@angular/common';
2
+ import * as i0 from '@angular/core';
3
+ import { inject, TemplateRef, Directive, input, booleanAttribute, output, contentChild, computed, ChangeDetectionStrategy, Component } from '@angular/core';
4
+ import { TranslatePipe } from '@sdcorejs/angular/i18n';
5
+ import { SdIcon } from '@sdcorejs/angular/modules/icon';
6
+
7
+ class SdDataStateTemplateDirective {
8
+ template = inject(TemplateRef);
9
+ static ngTemplateContextGuard(_directive, _context) {
10
+ return true;
11
+ }
12
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SdDataStateTemplateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
13
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.17", type: SdDataStateTemplateDirective, isStandalone: true, selector: "ng-template[sdDataStateTemplate]", ngImport: i0 });
14
+ }
15
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SdDataStateTemplateDirective, decorators: [{
16
+ type: Directive,
17
+ args: [{
18
+ selector: 'ng-template[sdDataStateTemplate]',
19
+ standalone: true,
20
+ }]
21
+ }] });
22
+ const DEFAULT_ICON = {
23
+ loading: 'progress_activity',
24
+ empty: 'inbox',
25
+ error: 'error_outline',
26
+ forbidden: 'lock',
27
+ success: null,
28
+ };
29
+ class SdDataState {
30
+ state = input('success', ...(ngDevMode ? [{ debugName: "state" }] : /* istanbul ignore next */ []));
31
+ title = input(...(ngDevMode ? [undefined, { debugName: "title" }] : /* istanbul ignore next */ []));
32
+ message = input(...(ngDevMode ? [undefined, { debugName: "message" }] : /* istanbul ignore next */ []));
33
+ icon = input(...(ngDevMode ? [undefined, { debugName: "icon" }] : /* istanbul ignore next */ []));
34
+ fontSet = input(...(ngDevMode ? [undefined, { debugName: "fontSet" }] : /* istanbul ignore next */ []));
35
+ retryable = input(false, { ...(ngDevMode ? { debugName: "retryable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
36
+ retryLabel = input(...(ngDevMode ? [undefined, { debugName: "retryLabel" }] : /* istanbul ignore next */ []));
37
+ actionLabel = input(...(ngDevMode ? [undefined, { debugName: "actionLabel" }] : /* istanbul ignore next */ []));
38
+ compact = input(false, { ...(ngDevMode ? { debugName: "compact" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
39
+ fullPage = input(false, { ...(ngDevMode ? { debugName: "fullPage" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
40
+ sdRetry = output();
41
+ sdAction = output();
42
+ customTemplate = contentChild(SdDataStateTemplateDirective, ...(ngDevMode ? [{ debugName: "customTemplate" }] : /* istanbul ignore next */ []));
43
+ effectiveIcon = computed(() => this.icon() ?? DEFAULT_ICON[this.state()], ...(ngDevMode ? [{ debugName: "effectiveIcon" }] : /* istanbul ignore next */ []));
44
+ titleKey = computed(() => `core.component.data-state.${this.state()}.title`, ...(ngDevMode ? [{ debugName: "titleKey" }] : /* istanbul ignore next */ []));
45
+ messageKey = computed(() => `core.component.data-state.${this.state()}.message`, ...(ngDevMode ? [{ debugName: "messageKey" }] : /* istanbul ignore next */ []));
46
+ role = computed(() => this.state() === 'error' || this.state() === 'forbidden' ? 'alert' : 'status', ...(ngDevMode ? [{ debugName: "role" }] : /* istanbul ignore next */ []));
47
+ retry = () => this.sdRetry.emit();
48
+ action = () => this.sdAction.emit();
49
+ templateContext = computed(() => ({
50
+ $implicit: this.state(),
51
+ state: this.state(),
52
+ retry: this.retry,
53
+ action: this.action,
54
+ }), ...(ngDevMode ? [{ debugName: "templateContext" }] : /* istanbul ignore next */ []));
55
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SdDataState, deps: [], target: i0.ɵɵFactoryTarget.Component });
56
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: SdDataState, isStandalone: true, selector: "sd-data-state", inputs: { state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, fontSet: { classPropertyName: "fontSet", publicName: "fontSet", isSignal: true, isRequired: false, transformFunction: null }, retryable: { classPropertyName: "retryable", publicName: "retryable", isSignal: true, isRequired: false, transformFunction: null }, retryLabel: { classPropertyName: "retryLabel", publicName: "retryLabel", isSignal: true, isRequired: false, transformFunction: null }, actionLabel: { classPropertyName: "actionLabel", publicName: "actionLabel", isSignal: true, isRequired: false, transformFunction: null }, compact: { classPropertyName: "compact", publicName: "compact", isSignal: true, isRequired: false, transformFunction: null }, fullPage: { classPropertyName: "fullPage", publicName: "fullPage", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sdRetry: "sdRetry", sdAction: "sdAction" }, queries: [{ propertyName: "customTemplate", first: true, predicate: SdDataStateTemplateDirective, descendants: true, isSignal: true }], ngImport: i0, template: "@let currentState = state();\n@let template = customTemplate();\n\n@if (currentState === 'success') {\n @if (template) {\n <ng-container [ngTemplateOutlet]=\"template.template\" [ngTemplateOutletContext]=\"templateContext()\"></ng-container>\n } @else {\n <ng-content></ng-content>\n }\n} @else if (template) {\n <ng-container [ngTemplateOutlet]=\"template.template\" [ngTemplateOutletContext]=\"templateContext()\"></ng-container>\n} @else {\n <section\n class=\"sd-data-state\"\n [class.sd-data-state--compact]=\"compact()\"\n [class.sd-data-state--full-page]=\"fullPage()\"\n [attr.data-state]=\"currentState\"\n [attr.role]=\"role()\"\n [attr.aria-busy]=\"currentState === 'loading' ? 'true' : null\"\n [attr.aria-live]=\"role() === 'alert' ? 'assertive' : 'polite'\">\n @if (effectiveIcon(); as currentIcon) {\n <sd-icon class=\"sd-data-state__icon\" aria-hidden=\"true\" [name]=\"currentIcon\" [fontSet]=\"fontSet()\"></sd-icon>\n }\n\n <div class=\"sd-data-state__title\">{{ title() ?? (titleKey() | translate) }}</div>\n <div class=\"sd-data-state__message\">{{ message() ?? (messageKey() | translate) }}</div>\n\n @if (retryable() || actionLabel()) {\n <div class=\"sd-data-state__actions\">\n @if (retryable()) {\n <button type=\"button\" data-state-retry (click)=\"retry()\">\n {{ retryLabel() || ('core.component.data-state.retry' | translate) }}\n </button>\n }\n @if (actionLabel(); as label) {\n <button type=\"button\" data-state-action (click)=\"action()\">{{ label }}</button>\n }\n </div>\n }\n </section>\n}\n", styles: [":host{display:contents}.sd-data-state{box-sizing:border-box;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;width:100%;min-height:240px;padding:32px;text-align:center;color:var(--sd-text, #2f3136)}.sd-data-state--compact{min-height:120px;padding:16px}.sd-data-state--full-page{min-height:100dvh}.sd-data-state__icon{width:48px;height:48px;color:var(--sd-text-secondary, #667085)}[data-state=loading] .sd-data-state__icon{animation:sd-data-state-spin 1s linear infinite}[data-state=error] .sd-data-state__icon,[data-state=forbidden] .sd-data-state__icon{color:var(--sd-error, #d92d20)}.sd-data-state__title{font-size:18px;font-weight:600;line-height:24px}.sd-data-state__message{max-width:520px;color:var(--sd-text-secondary, #667085);font-size:14px;line-height:20px}.sd-data-state__actions{display:flex;flex-wrap:wrap;justify-content:center;gap:8px;margin-top:8px}.sd-data-state__actions button{min-height:36px;padding:8px 14px;border:1px solid var(--sd-border, #d0d5dd);border-radius:6px;background:#fff;color:var(--sd-text, #2f3136);font:inherit;cursor:pointer}.sd-data-state__actions button:focus-visible{outline:2px solid var(--sd-info, #1677ff);outline-offset:2px}@keyframes sd-data-state-spin{to{transform:rotate(360deg)}}@media(prefers-reduced-motion:reduce){[data-state=loading] .sd-data-state__icon{animation:none}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: SdIcon, selector: "sd-icon", inputs: ["name", "fontIcon", "color", "set", "fontSet", "size", "strokeWidth", "absoluteStrokeWidth", "ariaLabel"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
57
+ }
58
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SdDataState, decorators: [{
59
+ type: Component,
60
+ args: [{ selector: 'sd-data-state', standalone: true, imports: [NgTemplateOutlet, TranslatePipe, SdIcon], changeDetection: ChangeDetectionStrategy.OnPush, template: "@let currentState = state();\n@let template = customTemplate();\n\n@if (currentState === 'success') {\n @if (template) {\n <ng-container [ngTemplateOutlet]=\"template.template\" [ngTemplateOutletContext]=\"templateContext()\"></ng-container>\n } @else {\n <ng-content></ng-content>\n }\n} @else if (template) {\n <ng-container [ngTemplateOutlet]=\"template.template\" [ngTemplateOutletContext]=\"templateContext()\"></ng-container>\n} @else {\n <section\n class=\"sd-data-state\"\n [class.sd-data-state--compact]=\"compact()\"\n [class.sd-data-state--full-page]=\"fullPage()\"\n [attr.data-state]=\"currentState\"\n [attr.role]=\"role()\"\n [attr.aria-busy]=\"currentState === 'loading' ? 'true' : null\"\n [attr.aria-live]=\"role() === 'alert' ? 'assertive' : 'polite'\">\n @if (effectiveIcon(); as currentIcon) {\n <sd-icon class=\"sd-data-state__icon\" aria-hidden=\"true\" [name]=\"currentIcon\" [fontSet]=\"fontSet()\"></sd-icon>\n }\n\n <div class=\"sd-data-state__title\">{{ title() ?? (titleKey() | translate) }}</div>\n <div class=\"sd-data-state__message\">{{ message() ?? (messageKey() | translate) }}</div>\n\n @if (retryable() || actionLabel()) {\n <div class=\"sd-data-state__actions\">\n @if (retryable()) {\n <button type=\"button\" data-state-retry (click)=\"retry()\">\n {{ retryLabel() || ('core.component.data-state.retry' | translate) }}\n </button>\n }\n @if (actionLabel(); as label) {\n <button type=\"button\" data-state-action (click)=\"action()\">{{ label }}</button>\n }\n </div>\n }\n </section>\n}\n", styles: [":host{display:contents}.sd-data-state{box-sizing:border-box;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;width:100%;min-height:240px;padding:32px;text-align:center;color:var(--sd-text, #2f3136)}.sd-data-state--compact{min-height:120px;padding:16px}.sd-data-state--full-page{min-height:100dvh}.sd-data-state__icon{width:48px;height:48px;color:var(--sd-text-secondary, #667085)}[data-state=loading] .sd-data-state__icon{animation:sd-data-state-spin 1s linear infinite}[data-state=error] .sd-data-state__icon,[data-state=forbidden] .sd-data-state__icon{color:var(--sd-error, #d92d20)}.sd-data-state__title{font-size:18px;font-weight:600;line-height:24px}.sd-data-state__message{max-width:520px;color:var(--sd-text-secondary, #667085);font-size:14px;line-height:20px}.sd-data-state__actions{display:flex;flex-wrap:wrap;justify-content:center;gap:8px;margin-top:8px}.sd-data-state__actions button{min-height:36px;padding:8px 14px;border:1px solid var(--sd-border, #d0d5dd);border-radius:6px;background:#fff;color:var(--sd-text, #2f3136);font:inherit;cursor:pointer}.sd-data-state__actions button:focus-visible{outline:2px solid var(--sd-info, #1677ff);outline-offset:2px}@keyframes sd-data-state-spin{to{transform:rotate(360deg)}}@media(prefers-reduced-motion:reduce){[data-state=loading] .sd-data-state__icon{animation:none}}\n"] }]
61
+ }], propDecorators: { state: [{ type: i0.Input, args: [{ isSignal: true, alias: "state", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], fontSet: [{ type: i0.Input, args: [{ isSignal: true, alias: "fontSet", required: false }] }], retryable: [{ type: i0.Input, args: [{ isSignal: true, alias: "retryable", required: false }] }], retryLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "retryLabel", required: false }] }], actionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionLabel", required: false }] }], compact: [{ type: i0.Input, args: [{ isSignal: true, alias: "compact", required: false }] }], fullPage: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullPage", required: false }] }], sdRetry: [{ type: i0.Output, args: ["sdRetry"] }], sdAction: [{ type: i0.Output, args: ["sdAction"] }], customTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdDataStateTemplateDirective), { isSignal: true }] }] } });
62
+
63
+ /**
64
+ * Generated bundle index. Do not edit.
65
+ */
66
+
67
+ export { SdDataState, SdDataStateTemplateDirective };
68
+ //# sourceMappingURL=sdcorejs-angular-components-data-state.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdcorejs-angular-components-data-state.mjs","sources":["../../../projects/sdcorejs-angular/components/data-state/src/data-state.component.ts","../../../projects/sdcorejs-angular/components/data-state/src/data-state.component.html","../../../projects/sdcorejs-angular/components/data-state/sdcorejs-angular-components-data-state.ts"],"sourcesContent":["import { NgTemplateOutlet } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n Directive,\n TemplateRef,\n booleanAttribute,\n computed,\n contentChild,\n inject,\n input,\n output,\n} from '@angular/core';\nimport { TranslatePipe } from '@sdcorejs/angular/i18n';\nimport { SdIcon, SdIconSet } from '@sdcorejs/angular/modules/icon';\n\nexport type SdDataStateKind = 'loading' | 'empty' | 'error' | 'forbidden' | 'success';\n\nexport interface SdDataStateTemplateContext {\n readonly $implicit: SdDataStateKind;\n readonly state: SdDataStateKind;\n readonly retry: () => void;\n readonly action: () => void;\n}\n\n@Directive({\n selector: 'ng-template[sdDataStateTemplate]',\n standalone: true,\n})\nexport class SdDataStateTemplateDirective {\n readonly template = inject<TemplateRef<SdDataStateTemplateContext>>(TemplateRef);\n\n static ngTemplateContextGuard(_directive: SdDataStateTemplateDirective, _context: unknown): _context is SdDataStateTemplateContext {\n return true;\n }\n}\n\nconst DEFAULT_ICON: Readonly<Record<SdDataStateKind, string | null>> = {\n loading: 'progress_activity',\n empty: 'inbox',\n error: 'error_outline',\n forbidden: 'lock',\n success: null,\n};\n\n@Component({\n selector: 'sd-data-state',\n standalone: true,\n imports: [NgTemplateOutlet, TranslatePipe, SdIcon],\n templateUrl: './data-state.component.html',\n styleUrl: './data-state.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class SdDataState {\n readonly state = input<SdDataStateKind>('success');\n readonly title = input<string | null | undefined>();\n readonly message = input<string | null | undefined>();\n readonly icon = input<string | null | undefined>();\n readonly fontSet = input<SdIconSet | undefined>();\n readonly retryable = input(false, { transform: booleanAttribute });\n readonly retryLabel = input<string | null | undefined>();\n readonly actionLabel = input<string | null | undefined>();\n readonly compact = input(false, { transform: booleanAttribute });\n readonly fullPage = input(false, { transform: booleanAttribute });\n readonly sdRetry = output<void>();\n readonly sdAction = output<void>();\n\n protected readonly customTemplate = contentChild(SdDataStateTemplateDirective);\n protected readonly effectiveIcon = computed(() => this.icon() ?? DEFAULT_ICON[this.state()]);\n protected readonly titleKey = computed(() => `core.component.data-state.${this.state()}.title`);\n protected readonly messageKey = computed(() => `core.component.data-state.${this.state()}.message`);\n protected readonly role = computed<'alert' | 'status'>(() =>\n this.state() === 'error' || this.state() === 'forbidden' ? 'alert' : 'status'\n );\n\n protected readonly retry = (): void => this.sdRetry.emit();\n protected readonly action = (): void => this.sdAction.emit();\n protected readonly templateContext = computed<SdDataStateTemplateContext>(() => ({\n $implicit: this.state(),\n state: this.state(),\n retry: this.retry,\n action: this.action,\n }));\n}\n","@let currentState = state();\n@let template = customTemplate();\n\n@if (currentState === 'success') {\n @if (template) {\n <ng-container [ngTemplateOutlet]=\"template.template\" [ngTemplateOutletContext]=\"templateContext()\"></ng-container>\n } @else {\n <ng-content></ng-content>\n }\n} @else if (template) {\n <ng-container [ngTemplateOutlet]=\"template.template\" [ngTemplateOutletContext]=\"templateContext()\"></ng-container>\n} @else {\n <section\n class=\"sd-data-state\"\n [class.sd-data-state--compact]=\"compact()\"\n [class.sd-data-state--full-page]=\"fullPage()\"\n [attr.data-state]=\"currentState\"\n [attr.role]=\"role()\"\n [attr.aria-busy]=\"currentState === 'loading' ? 'true' : null\"\n [attr.aria-live]=\"role() === 'alert' ? 'assertive' : 'polite'\">\n @if (effectiveIcon(); as currentIcon) {\n <sd-icon class=\"sd-data-state__icon\" aria-hidden=\"true\" [name]=\"currentIcon\" [fontSet]=\"fontSet()\"></sd-icon>\n }\n\n <div class=\"sd-data-state__title\">{{ title() ?? (titleKey() | translate) }}</div>\n <div class=\"sd-data-state__message\">{{ message() ?? (messageKey() | translate) }}</div>\n\n @if (retryable() || actionLabel()) {\n <div class=\"sd-data-state__actions\">\n @if (retryable()) {\n <button type=\"button\" data-state-retry (click)=\"retry()\">\n {{ retryLabel() || ('core.component.data-state.retry' | translate) }}\n </button>\n }\n @if (actionLabel(); as label) {\n <button type=\"button\" data-state-action (click)=\"action()\">{{ label }}</button>\n }\n </div>\n }\n </section>\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}