@masterteam/components 0.0.171 → 0.0.172

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.
@@ -212,6 +212,19 @@ class Tree {
212
212
  };
213
213
  updateNodeCheckedState(this.treeValue());
214
214
  }
215
+ /**
216
+ * Clears the tree's search/filter input and resets the filtered nodes.
217
+ */
218
+ resetFilter() {
219
+ const tree = this.primeTree();
220
+ if (!tree)
221
+ return;
222
+ tree.resetFilter();
223
+ // PrimeNG's resetFilter() does not re-serialize the nodes, so the
224
+ // (virtual-scrolled) list keeps showing the previously filtered set.
225
+ // Refresh the serialized value so the full tree is rendered again.
226
+ tree.updateSerializedValue();
227
+ }
215
228
  resolveActionLoading(action, node) {
216
229
  if (typeof action.loading === 'function') {
217
230
  return action.loading(node);
@@ -1 +1 @@
1
- {"version":3,"file":"masterteam-components-tree.mjs","sources":["../../../../packages/masterteam/components/tree/tree.ts","../../../../packages/masterteam/components/tree/tree.html","../../../../packages/masterteam/components/tree/masterteam-components-tree.ts"],"sourcesContent":["import { ToggleField } from '@masterteam/components/toggle-field';\r\nimport { Avatar } from '@masterteam/components/avatar';\r\nimport { Button } from '@masterteam/components/button';\r\nimport {\r\n Component,\r\n input,\r\n output,\r\n viewChild,\r\n effect,\r\n inject,\r\n computed,\r\n model,\r\n Signal,\r\n signal,\r\n} from '@angular/core';\r\nimport { Tree as PrimeTree, TreeModule } from 'primeng/tree';\r\nimport { MenuItem, TreeNode } from 'primeng/api';\r\nimport { Icon } from '@masterteam/icons';\r\nimport { MTIcon } from '@masterteam/icons';\r\nimport { CommonModule } from '@angular/common';\r\nimport { Directionality } from '@angular/cdk/bidi';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { ContextMenuModule } from 'primeng/contextmenu';\r\nimport { TranslocoModule } from '@jsverse/transloco';\r\nimport {\r\n TreeAction,\r\n TreeContextMenuAction,\r\n TreeActionEvent,\r\n} from './tree-types';\r\nimport { TranslocoService } from '@jsverse/transloco';\r\n\r\n@Component({\r\n selector: 'mt-tree',\r\n standalone: true,\r\n imports: [\r\n TreeModule,\r\n Icon,\r\n CommonModule,\r\n Avatar,\r\n Button,\r\n FormsModule,\r\n ToggleField,\r\n ContextMenuModule,\r\n TranslocoModule,\r\n ],\r\n templateUrl: './tree.html',\r\n styleUrls: ['./tree.scss'],\r\n})\r\nexport class Tree {\r\n transloco = inject(TranslocoService);\r\n\r\n dir = inject(Directionality, { optional: true });\r\n\r\n readonly primeTree = viewChild<PrimeTree>('primeTree');\r\n\r\n readonly value = input.required<TreeNode[]>();\r\n readonly selection = model<TreeNode | TreeNode[] | null>();\r\n readonly selectionMode = input<'single' | 'multiple' | 'checkbox'>();\r\n readonly nodeIcon = input<MTIcon | undefined>();\r\n readonly propagateSelectionUp = input<boolean>(false);\r\n readonly propagateSelectionDown = input<boolean>(false);\r\n readonly checkAllChildren = input<boolean>(false);\r\n readonly loading = input<boolean>(false);\r\n readonly emptyMessage = input<string>(\r\n this.transloco.translate('components.tree.no-data-found'),\r\n );\r\n readonly checkAllLabel = input<string>(\r\n this.transloco.translate('components.tree.check-all'),\r\n );\r\n readonly filterPlaceholder = input<string>(\r\n this.transloco.translate('components.tree.search'),\r\n );\r\n readonly dataKey = input<'key'>('key');\r\n readonly filter = input<boolean>(false);\r\n readonly filterMode = input<'lenient' | 'strict'>('lenient');\r\n readonly virtualScroll = input<boolean>(false);\r\n readonly virtualScrollItemSize = input<number>(46);\r\n readonly scrollHeight = input<string | undefined>();\r\n\r\n readonly styleClass = input<string>('');\r\n readonly style = input<Record<string, string>>();\r\n readonly pInputs = input<Partial<PrimeTree>>();\r\n readonly nodeActions = input<TreeAction[]>([]);\r\n readonly nodeContextmenuActions = input<TreeContextMenuAction[]>([]);\r\n\r\n // Context menu state\r\n readonly contextMenuSelection = model<TreeNode | null>(null);\r\n readonly contextMenuItems = computed<MenuItem[]>(() => {\r\n const actions = this.nodeContextmenuActions();\r\n return actions.map((action) => ({\r\n label: action.label,\r\n icon: action.icon,\r\n command: () => {\r\n const node = this.contextMenuSelection();\r\n if (node) {\r\n action.action(node);\r\n }\r\n },\r\n }));\r\n });\r\n\r\n readonly action = output<TreeActionEvent>();\r\n CheckAllValue = signal<boolean>(false);\r\n // Computed tree value with \"Check All\" nodes added recursively to all parents\r\n readonly treeValue: Signal<TreeNode[]> = computed(() => {\r\n const nodes = this.value();\r\n const shouldAddCheckAll =\r\n this.checkAllChildren() && this.selectionMode() === 'checkbox';\r\n\r\n if (!shouldAddCheckAll) {\r\n return nodes;\r\n }\r\n\r\n // Recursively add \"Check All\" child to any parent node\r\n const addCheckAllRecursive = (node: TreeNode): TreeNode => {\r\n if (node.children && node.children.length > 0) {\r\n const checkAllNode: TreeNode = {\r\n key: `${node.key}-check-all`,\r\n label: this.checkAllLabel(),\r\n icon: 'general.check-square-broken',\r\n data: node,\r\n };\r\n\r\n return {\r\n ...node,\r\n children: [checkAllNode, ...node.children.map(addCheckAllRecursive)],\r\n };\r\n }\r\n return node;\r\n };\r\n\r\n // Transform all nodes\r\n const transformedNodes = nodes.map(addCheckAllRecursive);\r\n\r\n // Add \"Check All\" for entire tree at the beginning\r\n const treeCheckAllNode: TreeNode = {\r\n key: 'tree-check-all',\r\n label: this.checkAllLabel(),\r\n icon: 'general.check-square-broken',\r\n data: { isTreeRoot: true, children: transformedNodes },\r\n };\r\n\r\n return [treeCheckAllNode, ...transformedNodes];\r\n });\r\n\r\n constructor() {\r\n // Apply pInputs to the PrimeNG tree instance\r\n effect(() => {\r\n const tree = this.primeTree();\r\n const inputs = this.pInputs();\r\n if (tree && inputs) {\r\n Object.assign(tree, inputs);\r\n }\r\n });\r\n\r\n // Sync checked state when selection changes (including initial value)\r\n effect(() => {\r\n const value = this.treeValue();\r\n // Only run if we have nodes and selection\r\n if (value.length > 0 && this.selectionMode() === 'checkbox') {\r\n this.handleCheckedNodes();\r\n }\r\n });\r\n }\r\n private isProcessingBatchSelection = signal<boolean>(false);\r\n\r\n onSelectionChange(event: TreeNode | TreeNode[] | null) {\r\n // Skip emitting if we're in the middle of batch processing\r\n if (this.isProcessingBatchSelection()) {\r\n return;\r\n }\r\n this.handleCheckedNodes();\r\n this.action.emit({ action: 'selectionChange', data: event });\r\n }\r\n\r\n onNodeSelect(event: { node: TreeNode }) {\r\n this.action.emit({ action: 'nodeSelect', data: event });\r\n }\r\n\r\n onNodeUnselect(event: { node: TreeNode }) {\r\n this.action.emit({ action: 'nodeUnselect', data: event });\r\n }\r\n\r\n onNodeExpand(event: { node: TreeNode }) {\r\n this.action.emit({ action: 'nodeExpand', data: event });\r\n }\r\n\r\n onNodeCollapse(event: { node: TreeNode }) {\r\n this.action.emit({ action: 'nodeCollapse', data: event });\r\n }\r\n\r\n onContextMenuSelect(event: TreeNode) {\r\n this.contextMenuSelection.set(event);\r\n }\r\n getCheckAllValue(event: any) {\r\n this.CheckAllValue.set(event);\r\n }\r\n toggleNodeExpanded(node: TreeNode, event: MouseEvent): void {\r\n event.stopPropagation();\r\n node.expanded = !node.expanded;\r\n const tree = this.primeTree();\r\n if (tree && this.virtualScroll()) {\r\n tree.updateSerializedValue();\r\n }\r\n this.action.emit({\r\n action: node.expanded ? 'nodeExpand' : 'nodeCollapse',\r\n data: { node },\r\n });\r\n }\r\n\r\n toggleNodeSelection(node: TreeNode, event: MouseEvent): void {\r\n event.stopPropagation();\r\n if (node.selectable === false) {\r\n return;\r\n }\r\n\r\n const tree = this.primeTree();\r\n if (this.selectionMode() === 'checkbox' && tree) {\r\n if (node.key?.includes('check-all') && node.data) {\r\n const checkValue = this.CheckAllValue() ?? true;\r\n // Handle parent-level \"Check All\" - only check immediate children\r\n const parentNode = node.data;\r\n\r\n // Start batch processing to prevent multiple selection change events\r\n this.isProcessingBatchSelection.set(true);\r\n\r\n parentNode?.children?.forEach((child: TreeNode) => {\r\n if (!child.key?.includes('check-all')) {\r\n const isSelected = tree.isSelected(child);\r\n // Only toggle if the current state doesn't match desired state\r\n if ((checkValue && !isSelected) || (!checkValue && isSelected)) {\r\n tree.onNodeClick(event, child);\r\n }\r\n }\r\n });\r\n\r\n // End batch processing and emit single selection change event\r\n this.isProcessingBatchSelection.set(false);\r\n this.handleCheckedNodes();\r\n this.action.emit({\r\n action: 'selectionChange',\r\n data: this.selection(),\r\n });\r\n } else {\r\n tree.onNodeClick(event, node);\r\n }\r\n }\r\n }\r\n\r\n handleCheckedNodes() {\r\n const tree = this.primeTree();\r\n if (!tree) return;\r\n\r\n // Build a Set of selected keys for O(1) lookup instead of repeated isSelected() calls\r\n const selection = this.selection();\r\n const selectedKeys = new Set<string>();\r\n if (Array.isArray(selection)) {\r\n for (const node of selection) {\r\n if (node.key) selectedKeys.add(node.key);\r\n }\r\n }\r\n\r\n const updateNodeCheckedState = (nodes: TreeNode[]) => {\r\n for (const node of nodes) {\r\n if ((node as any).key?.includes('check-all')) {\r\n (node as any).checked = nodes.every(\r\n (n: any) => n.key?.includes('check-all') || selectedKeys.has(n.key),\r\n );\r\n } else {\r\n (node as any).checked = selectedKeys.has((node as any).key);\r\n }\r\n if (node.children) {\r\n updateNodeCheckedState(node.children);\r\n }\r\n }\r\n };\r\n updateNodeCheckedState(this.treeValue());\r\n }\r\n\r\n resolveActionLoading(action: TreeAction, node: any): boolean | undefined {\r\n if (typeof action.loading === 'function') {\r\n return action.loading(node);\r\n }\r\n return action.loading;\r\n }\r\n\r\n nodeAction(action: TreeAction, node: any): void {\r\n action.action(node);\r\n }\r\n}\r\n","<p-tree\r\n #primeTree\r\n [value]=\"treeValue()\"\r\n [(selection)]=\"selection\"\r\n [selectionMode]=\"selectionMode()\"\r\n [propagateSelectionUp]=\"propagateSelectionUp()\"\r\n [propagateSelectionDown]=\"propagateSelectionDown()\"\r\n [loading]=\"loading()\"\r\n [emptyMessage]=\"emptyMessage()\"\r\n [filter]=\"filter()\"\r\n [virtualScroll]=\"virtualScroll()\"\r\n [virtualScrollItemSize]=\"virtualScrollItemSize()\"\r\n [scrollHeight]=\"scrollHeight()\"\r\n [filterMode]=\"filterMode()\"\r\n [filterPlaceholder]=\"filterPlaceholder()\"\r\n [styleClass]=\"'mt-tree ' + styleClass()\"\r\n [style]=\"style()\"\r\n [contextMenu]=\"contextMenuItems().length ? cm : null\"\r\n [(contextMenuSelection)]=\"contextMenuSelection\"\r\n contextMenuSelectionMode=\"separate\"\r\n (selectionChange)=\"onSelectionChange($event)\"\r\n (onNodeSelect)=\"onNodeSelect($event)\"\r\n (onNodeUnselect)=\"onNodeUnselect($event)\"\r\n (onNodeExpand)=\"onNodeExpand($event)\"\r\n (onNodeCollapse)=\"onNodeCollapse($event)\"\r\n (onNodeContextMenuSelect)=\"onContextMenuSelect($event.node)\"\r\n>\r\n <ng-template let-node pTemplate=\"default\">\r\n <div\r\n (click)=\"selectionMode() === 'checkbox' ? $event.stopPropagation() : null\"\r\n class=\"mt-tree-node border-1 border-gray-300 cursor-default rounded-lg flex items-center hover:bg-surface-100 justify-between\"\r\n [class]=\"node?.key.includes('check-all') ? 'bg-surface-100 ' : ''\"\r\n >\r\n <div\r\n class=\"px-3 flex items-center justify-between flex-1\"\r\n [class.cursor-pointer]=\"\r\n selectionMode() === 'single' || selectionMode() === 'multiple'\r\n \"\r\n >\r\n <div class=\"flex items-center\">\r\n @if (node.children && node.children.length > 0) {\r\n <div class=\"py-3\" (click)=\"toggleNodeExpanded(node, $event)\">\r\n <mt-icon\r\n class=\"text-2xl cursor-pointer\"\r\n [icon]=\"\r\n node.expanded\r\n ? 'arrow.chevron-down'\r\n : dir?.value === 'rtl'\r\n ? 'arrow.chevron-left'\r\n : 'arrow.chevron-right'\r\n \"\r\n />\r\n </div>\r\n }\r\n @if (node.icon || nodeIcon()) {\r\n <mt-avatar\r\n class=\"ms-2\"\r\n [icon]=\"node.icon || nodeIcon()\"\r\n shape=\"square\"\r\n size=\"small\"\r\n style=\"\r\n --p-avatar-background: var(--p-primary-50);\r\n --p-avatar-color: var(--p-primary-color);\r\n \"\r\n [style]=\"\r\n node?.key.includes('check-all')\r\n ? ' --p-avatar-background: var(--p-primary-color); --p-avatar-color: white'\r\n : ''\r\n \"\r\n >\r\n </mt-avatar>\r\n }\r\n <div class=\"text-md mx-3 py-4\">{{ node.label }}</div>\r\n </div>\r\n <div class=\"flex items-center gap-2\">\r\n @if (nodeActions().length > 0) {\r\n <div class=\"flex items-center\">\r\n @for (action of nodeActions(); track action.icon) {\r\n @let hidden = action.hidden?.(node);\r\n @if (!hidden) {\r\n <mt-button\r\n [variant]=\"action.variant\"\r\n [icon]=\"action.icon\"\r\n [severity]=\"action.severity\"\r\n [size]=\"action.size\"\r\n [label]=\"action.label\"\r\n [tooltip]=\"action.tooltip\"\r\n [loading]=\"resolveActionLoading(action, node)\"\r\n (click)=\"nodeAction(action, node)\"\r\n >\r\n </mt-button>\r\n }\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n @if (selectionMode() === \"checkbox\") {\r\n <div\r\n class=\"me-3\"\r\n [class.cursor-pointer]=\"node.selectable !== false\"\r\n (click)=\"toggleNodeSelection(node, $event)\"\r\n >\r\n <mt-toggle-field\r\n (ngModelChange)=\"getCheckAllValue($event)\"\r\n [ngModel]=\"node.checked\"\r\n [disabled]=\"node.selectable === false\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n </ng-template>\r\n</p-tree>\r\n\r\n<p-contextMenu #cm [model]=\"contextMenuItems()\" appendTo=\"body\">\r\n <ng-template pTemplate=\"item\" let-item>\r\n <div class=\"p-menu-item-content\" (click)=\"item.command()\">\r\n <a class=\"p-menu-item-link flex items-center gap-2\">\r\n @if (item.icon) {\r\n <mt-icon [icon]=\"item.icon\" class=\"text-lg\" />\r\n }\r\n <span class=\"p-menu-item-label\">{{ item.label }}</span>\r\n </a>\r\n </div>\r\n </ng-template>\r\n</p-contextMenu>\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"masterteam-components-tree.mjs","sources":["../../../../packages/masterteam/components/tree/tree.ts","../../../../packages/masterteam/components/tree/tree.html","../../../../packages/masterteam/components/tree/masterteam-components-tree.ts"],"sourcesContent":["import { ToggleField } from '@masterteam/components/toggle-field';\r\nimport { Avatar } from '@masterteam/components/avatar';\r\nimport { Button } from '@masterteam/components/button';\r\nimport {\r\n Component,\r\n input,\r\n output,\r\n viewChild,\r\n effect,\r\n inject,\r\n computed,\r\n model,\r\n Signal,\r\n signal,\r\n} from '@angular/core';\r\nimport { Tree as PrimeTree, TreeModule } from 'primeng/tree';\r\nimport { MenuItem, TreeNode } from 'primeng/api';\r\nimport { Icon } from '@masterteam/icons';\r\nimport { MTIcon } from '@masterteam/icons';\r\nimport { CommonModule } from '@angular/common';\r\nimport { Directionality } from '@angular/cdk/bidi';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { ContextMenuModule } from 'primeng/contextmenu';\r\nimport { TranslocoModule } from '@jsverse/transloco';\r\nimport {\r\n TreeAction,\r\n TreeContextMenuAction,\r\n TreeActionEvent,\r\n} from './tree-types';\r\nimport { TranslocoService } from '@jsverse/transloco';\r\n\r\n@Component({\r\n selector: 'mt-tree',\r\n standalone: true,\r\n imports: [\r\n TreeModule,\r\n Icon,\r\n CommonModule,\r\n Avatar,\r\n Button,\r\n FormsModule,\r\n ToggleField,\r\n ContextMenuModule,\r\n TranslocoModule,\r\n ],\r\n templateUrl: './tree.html',\r\n styleUrls: ['./tree.scss'],\r\n})\r\nexport class Tree {\r\n transloco = inject(TranslocoService);\r\n\r\n dir = inject(Directionality, { optional: true });\r\n\r\n readonly primeTree = viewChild<PrimeTree>('primeTree');\r\n\r\n readonly value = input.required<TreeNode[]>();\r\n readonly selection = model<TreeNode | TreeNode[] | null>();\r\n readonly selectionMode = input<'single' | 'multiple' | 'checkbox'>();\r\n readonly nodeIcon = input<MTIcon | undefined>();\r\n readonly propagateSelectionUp = input<boolean>(false);\r\n readonly propagateSelectionDown = input<boolean>(false);\r\n readonly checkAllChildren = input<boolean>(false);\r\n readonly loading = input<boolean>(false);\r\n readonly emptyMessage = input<string>(\r\n this.transloco.translate('components.tree.no-data-found'),\r\n );\r\n readonly checkAllLabel = input<string>(\r\n this.transloco.translate('components.tree.check-all'),\r\n );\r\n readonly filterPlaceholder = input<string>(\r\n this.transloco.translate('components.tree.search'),\r\n );\r\n readonly dataKey = input<'key'>('key');\r\n readonly filter = input<boolean>(false);\r\n readonly filterMode = input<'lenient' | 'strict'>('lenient');\r\n readonly virtualScroll = input<boolean>(false);\r\n readonly virtualScrollItemSize = input<number>(46);\r\n readonly scrollHeight = input<string | undefined>();\r\n\r\n readonly styleClass = input<string>('');\r\n readonly style = input<Record<string, string>>();\r\n readonly pInputs = input<Partial<PrimeTree>>();\r\n readonly nodeActions = input<TreeAction[]>([]);\r\n readonly nodeContextmenuActions = input<TreeContextMenuAction[]>([]);\r\n\r\n // Context menu state\r\n readonly contextMenuSelection = model<TreeNode | null>(null);\r\n readonly contextMenuItems = computed<MenuItem[]>(() => {\r\n const actions = this.nodeContextmenuActions();\r\n return actions.map((action) => ({\r\n label: action.label,\r\n icon: action.icon,\r\n command: () => {\r\n const node = this.contextMenuSelection();\r\n if (node) {\r\n action.action(node);\r\n }\r\n },\r\n }));\r\n });\r\n\r\n readonly action = output<TreeActionEvent>();\r\n CheckAllValue = signal<boolean>(false);\r\n // Computed tree value with \"Check All\" nodes added recursively to all parents\r\n readonly treeValue: Signal<TreeNode[]> = computed(() => {\r\n const nodes = this.value();\r\n const shouldAddCheckAll =\r\n this.checkAllChildren() && this.selectionMode() === 'checkbox';\r\n\r\n if (!shouldAddCheckAll) {\r\n return nodes;\r\n }\r\n\r\n // Recursively add \"Check All\" child to any parent node\r\n const addCheckAllRecursive = (node: TreeNode): TreeNode => {\r\n if (node.children && node.children.length > 0) {\r\n const checkAllNode: TreeNode = {\r\n key: `${node.key}-check-all`,\r\n label: this.checkAllLabel(),\r\n icon: 'general.check-square-broken',\r\n data: node,\r\n };\r\n\r\n return {\r\n ...node,\r\n children: [checkAllNode, ...node.children.map(addCheckAllRecursive)],\r\n };\r\n }\r\n return node;\r\n };\r\n\r\n // Transform all nodes\r\n const transformedNodes = nodes.map(addCheckAllRecursive);\r\n\r\n // Add \"Check All\" for entire tree at the beginning\r\n const treeCheckAllNode: TreeNode = {\r\n key: 'tree-check-all',\r\n label: this.checkAllLabel(),\r\n icon: 'general.check-square-broken',\r\n data: { isTreeRoot: true, children: transformedNodes },\r\n };\r\n\r\n return [treeCheckAllNode, ...transformedNodes];\r\n });\r\n\r\n constructor() {\r\n // Apply pInputs to the PrimeNG tree instance\r\n effect(() => {\r\n const tree = this.primeTree();\r\n const inputs = this.pInputs();\r\n if (tree && inputs) {\r\n Object.assign(tree, inputs);\r\n }\r\n });\r\n\r\n // Sync checked state when selection changes (including initial value)\r\n effect(() => {\r\n const value = this.treeValue();\r\n // Only run if we have nodes and selection\r\n if (value.length > 0 && this.selectionMode() === 'checkbox') {\r\n this.handleCheckedNodes();\r\n }\r\n });\r\n }\r\n private isProcessingBatchSelection = signal<boolean>(false);\r\n\r\n onSelectionChange(event: TreeNode | TreeNode[] | null) {\r\n // Skip emitting if we're in the middle of batch processing\r\n if (this.isProcessingBatchSelection()) {\r\n return;\r\n }\r\n this.handleCheckedNodes();\r\n this.action.emit({ action: 'selectionChange', data: event });\r\n }\r\n\r\n onNodeSelect(event: { node: TreeNode }) {\r\n this.action.emit({ action: 'nodeSelect', data: event });\r\n }\r\n\r\n onNodeUnselect(event: { node: TreeNode }) {\r\n this.action.emit({ action: 'nodeUnselect', data: event });\r\n }\r\n\r\n onNodeExpand(event: { node: TreeNode }) {\r\n this.action.emit({ action: 'nodeExpand', data: event });\r\n }\r\n\r\n onNodeCollapse(event: { node: TreeNode }) {\r\n this.action.emit({ action: 'nodeCollapse', data: event });\r\n }\r\n\r\n onContextMenuSelect(event: TreeNode) {\r\n this.contextMenuSelection.set(event);\r\n }\r\n getCheckAllValue(event: any) {\r\n this.CheckAllValue.set(event);\r\n }\r\n toggleNodeExpanded(node: TreeNode, event: MouseEvent): void {\r\n event.stopPropagation();\r\n node.expanded = !node.expanded;\r\n const tree = this.primeTree();\r\n if (tree && this.virtualScroll()) {\r\n tree.updateSerializedValue();\r\n }\r\n this.action.emit({\r\n action: node.expanded ? 'nodeExpand' : 'nodeCollapse',\r\n data: { node },\r\n });\r\n }\r\n\r\n toggleNodeSelection(node: TreeNode, event: MouseEvent): void {\r\n event.stopPropagation();\r\n if (node.selectable === false) {\r\n return;\r\n }\r\n\r\n const tree = this.primeTree();\r\n if (this.selectionMode() === 'checkbox' && tree) {\r\n if (node.key?.includes('check-all') && node.data) {\r\n const checkValue = this.CheckAllValue() ?? true;\r\n // Handle parent-level \"Check All\" - only check immediate children\r\n const parentNode = node.data;\r\n\r\n // Start batch processing to prevent multiple selection change events\r\n this.isProcessingBatchSelection.set(true);\r\n\r\n parentNode?.children?.forEach((child: TreeNode) => {\r\n if (!child.key?.includes('check-all')) {\r\n const isSelected = tree.isSelected(child);\r\n // Only toggle if the current state doesn't match desired state\r\n if ((checkValue && !isSelected) || (!checkValue && isSelected)) {\r\n tree.onNodeClick(event, child);\r\n }\r\n }\r\n });\r\n\r\n // End batch processing and emit single selection change event\r\n this.isProcessingBatchSelection.set(false);\r\n this.handleCheckedNodes();\r\n this.action.emit({\r\n action: 'selectionChange',\r\n data: this.selection(),\r\n });\r\n } else {\r\n tree.onNodeClick(event, node);\r\n }\r\n }\r\n }\r\n\r\n handleCheckedNodes() {\r\n const tree = this.primeTree();\r\n if (!tree) return;\r\n\r\n // Build a Set of selected keys for O(1) lookup instead of repeated isSelected() calls\r\n const selection = this.selection();\r\n const selectedKeys = new Set<string>();\r\n if (Array.isArray(selection)) {\r\n for (const node of selection) {\r\n if (node.key) selectedKeys.add(node.key);\r\n }\r\n }\r\n\r\n const updateNodeCheckedState = (nodes: TreeNode[]) => {\r\n for (const node of nodes) {\r\n if ((node as any).key?.includes('check-all')) {\r\n (node as any).checked = nodes.every(\r\n (n: any) => n.key?.includes('check-all') || selectedKeys.has(n.key),\r\n );\r\n } else {\r\n (node as any).checked = selectedKeys.has((node as any).key);\r\n }\r\n if (node.children) {\r\n updateNodeCheckedState(node.children);\r\n }\r\n }\r\n };\r\n updateNodeCheckedState(this.treeValue());\r\n }\r\n\r\n /**\r\n * Clears the tree's search/filter input and resets the filtered nodes.\r\n */\r\n resetFilter(): void {\r\n const tree = this.primeTree();\r\n if (!tree) return;\r\n tree.resetFilter();\r\n // PrimeNG's resetFilter() does not re-serialize the nodes, so the\r\n // (virtual-scrolled) list keeps showing the previously filtered set.\r\n // Refresh the serialized value so the full tree is rendered again.\r\n tree.updateSerializedValue();\r\n }\r\n\r\n resolveActionLoading(action: TreeAction, node: any): boolean | undefined {\r\n if (typeof action.loading === 'function') {\r\n return action.loading(node);\r\n }\r\n return action.loading;\r\n }\r\n\r\n nodeAction(action: TreeAction, node: any): void {\r\n action.action(node);\r\n }\r\n}\r\n","<p-tree\r\n #primeTree\r\n [value]=\"treeValue()\"\r\n [(selection)]=\"selection\"\r\n [selectionMode]=\"selectionMode()\"\r\n [propagateSelectionUp]=\"propagateSelectionUp()\"\r\n [propagateSelectionDown]=\"propagateSelectionDown()\"\r\n [loading]=\"loading()\"\r\n [emptyMessage]=\"emptyMessage()\"\r\n [filter]=\"filter()\"\r\n [virtualScroll]=\"virtualScroll()\"\r\n [virtualScrollItemSize]=\"virtualScrollItemSize()\"\r\n [scrollHeight]=\"scrollHeight()\"\r\n [filterMode]=\"filterMode()\"\r\n [filterPlaceholder]=\"filterPlaceholder()\"\r\n [styleClass]=\"'mt-tree ' + styleClass()\"\r\n [style]=\"style()\"\r\n [contextMenu]=\"contextMenuItems().length ? cm : null\"\r\n [(contextMenuSelection)]=\"contextMenuSelection\"\r\n contextMenuSelectionMode=\"separate\"\r\n (selectionChange)=\"onSelectionChange($event)\"\r\n (onNodeSelect)=\"onNodeSelect($event)\"\r\n (onNodeUnselect)=\"onNodeUnselect($event)\"\r\n (onNodeExpand)=\"onNodeExpand($event)\"\r\n (onNodeCollapse)=\"onNodeCollapse($event)\"\r\n (onNodeContextMenuSelect)=\"onContextMenuSelect($event.node)\"\r\n>\r\n <ng-template let-node pTemplate=\"default\">\r\n <div\r\n (click)=\"selectionMode() === 'checkbox' ? $event.stopPropagation() : null\"\r\n class=\"mt-tree-node border-1 border-gray-300 cursor-default rounded-lg flex items-center hover:bg-surface-100 justify-between\"\r\n [class]=\"node?.key.includes('check-all') ? 'bg-surface-100 ' : ''\"\r\n >\r\n <div\r\n class=\"px-3 flex items-center justify-between flex-1\"\r\n [class.cursor-pointer]=\"\r\n selectionMode() === 'single' || selectionMode() === 'multiple'\r\n \"\r\n >\r\n <div class=\"flex items-center\">\r\n @if (node.children && node.children.length > 0) {\r\n <div class=\"py-3\" (click)=\"toggleNodeExpanded(node, $event)\">\r\n <mt-icon\r\n class=\"text-2xl cursor-pointer\"\r\n [icon]=\"\r\n node.expanded\r\n ? 'arrow.chevron-down'\r\n : dir?.value === 'rtl'\r\n ? 'arrow.chevron-left'\r\n : 'arrow.chevron-right'\r\n \"\r\n />\r\n </div>\r\n }\r\n @if (node.icon || nodeIcon()) {\r\n <mt-avatar\r\n class=\"ms-2\"\r\n [icon]=\"node.icon || nodeIcon()\"\r\n shape=\"square\"\r\n size=\"small\"\r\n style=\"\r\n --p-avatar-background: var(--p-primary-50);\r\n --p-avatar-color: var(--p-primary-color);\r\n \"\r\n [style]=\"\r\n node?.key.includes('check-all')\r\n ? ' --p-avatar-background: var(--p-primary-color); --p-avatar-color: white'\r\n : ''\r\n \"\r\n >\r\n </mt-avatar>\r\n }\r\n <div class=\"text-md mx-3 py-4\">{{ node.label }}</div>\r\n </div>\r\n <div class=\"flex items-center gap-2\">\r\n @if (nodeActions().length > 0) {\r\n <div class=\"flex items-center\">\r\n @for (action of nodeActions(); track action.icon) {\r\n @let hidden = action.hidden?.(node);\r\n @if (!hidden) {\r\n <mt-button\r\n [variant]=\"action.variant\"\r\n [icon]=\"action.icon\"\r\n [severity]=\"action.severity\"\r\n [size]=\"action.size\"\r\n [label]=\"action.label\"\r\n [tooltip]=\"action.tooltip\"\r\n [loading]=\"resolveActionLoading(action, node)\"\r\n (click)=\"nodeAction(action, node)\"\r\n >\r\n </mt-button>\r\n }\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n @if (selectionMode() === \"checkbox\") {\r\n <div\r\n class=\"me-3\"\r\n [class.cursor-pointer]=\"node.selectable !== false\"\r\n (click)=\"toggleNodeSelection(node, $event)\"\r\n >\r\n <mt-toggle-field\r\n (ngModelChange)=\"getCheckAllValue($event)\"\r\n [ngModel]=\"node.checked\"\r\n [disabled]=\"node.selectable === false\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n </ng-template>\r\n</p-tree>\r\n\r\n<p-contextMenu #cm [model]=\"contextMenuItems()\" appendTo=\"body\">\r\n <ng-template pTemplate=\"item\" let-item>\r\n <div class=\"p-menu-item-content\" (click)=\"item.command()\">\r\n <a class=\"p-menu-item-link flex items-center gap-2\">\r\n @if (item.icon) {\r\n <mt-icon [icon]=\"item.icon\" class=\"text-lg\" />\r\n }\r\n <span class=\"p-menu-item-label\">{{ item.label }}</span>\r\n </a>\r\n </div>\r\n </ng-template>\r\n</p-contextMenu>\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -287,6 +287,45 @@ class UploadField {
287
287
  readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
288
288
  context = input(undefined, ...(ngDevMode ? [{ debugName: "context" }] : /* istanbul ignore next */ []));
289
289
  isMultipleEnabled = computed(() => this.shape() !== 'circle' && this.multiple(), ...(ngDevMode ? [{ debugName: "isMultipleEnabled" }] : /* istanbul ignore next */ []));
290
+ /**
291
+ * The native `accept` attribute is only a UI hint — users can switch the OS
292
+ * file dialog to "All files" and pick anything. This is the spec we re-check
293
+ * every selected/dropped file against before uploading to the backend.
294
+ */
295
+ effectiveAccept = computed(() => this.shape() === 'circle' ? 'image/*' : (this.accept() ?? ''), ...(ngDevMode ? [{ debugName: "effectiveAccept" }] : /* istanbul ignore next */ []));
296
+ /**
297
+ * Human-friendly, de-duplicated list of accepted types shown next to the
298
+ * upload prompt so the user knows what to pick before opening the dialog
299
+ * (e.g. ".pdf,.doc,image/*" -> "PDF, DOC, Images"). Empty when everything
300
+ * is allowed, so the hint can be hidden entirely.
301
+ */
302
+ acceptedTypesLabel = computed(() => {
303
+ const spec = this.effectiveAccept().trim();
304
+ if (!spec || spec === '*' || spec === '*/*') {
305
+ return '';
306
+ }
307
+ const labels = spec
308
+ .split(',')
309
+ .map((token) => token.trim().toLowerCase())
310
+ .filter((token) => token.length > 0 && token !== '*' && token !== '*/*')
311
+ .map((token) => {
312
+ if (token.startsWith('.')) {
313
+ return token.slice(1).toUpperCase();
314
+ }
315
+ const [group, subtype] = token.split('/');
316
+ if (subtype === '*') {
317
+ const key = `components.upload.fileGroups.${group}`;
318
+ const translated = this.transloco.translate(key);
319
+ // Transloco echoes the key back when it has no entry for it.
320
+ return translated === key
321
+ ? group.charAt(0).toUpperCase() + group.slice(1)
322
+ : translated;
323
+ }
324
+ return (subtype ?? group).toUpperCase();
325
+ })
326
+ .filter((label) => !!label);
327
+ return Array.from(new Set(labels)).join(', ');
328
+ }, ...(ngDevMode ? [{ debugName: "acceptedTypesLabel" }] : /* istanbul ignore next */ []));
290
329
  onChange = output();
291
330
  requiredValidator = Validators.required;
292
331
  value = signal(null, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
@@ -380,9 +419,14 @@ class UploadField {
380
419
  }
381
420
  prepareFiles(files) {
382
421
  this.ngControl.control?.setErrors({ uploading: true });
383
- if (this.shape() === 'circle' &&
384
- files.some((file) => !file?.type.startsWith('image/'))) {
385
- this.ngControl.control?.setErrors({ invalidFileType: true });
422
+ const accept = this.effectiveAccept();
423
+ const rejected = files.filter((file) => !isFileAccepted(file, accept));
424
+ if (rejected.length) {
425
+ this.ngControl.control?.setErrors({
426
+ invalidFileType: {
427
+ message: this.transloco.translate('components.validation.invalidFileType', { types: accept }),
428
+ },
429
+ });
386
430
  return;
387
431
  }
388
432
  const filesToUpload = this.isMultipleEnabled() ? files : [files[0]];
@@ -525,7 +569,7 @@ class UploadField {
525
569
  });
526
570
  }
527
571
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: UploadField, deps: [], target: i0.ɵɵFactoryTarget.Component });
528
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: UploadField, isStandalone: true, selector: "mt-upload-field", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, endPoint: { classPropertyName: "endPoint", publicName: "endPoint", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, userImgClass: { classPropertyName: "userImgClass", publicName: "userImgClass", isSignal: true, isRequired: false, transformFunction: null }, shape: { classPropertyName: "shape", publicName: "shape", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, accept: { classPropertyName: "accept", publicName: "accept", isSignal: true, isRequired: false, transformFunction: null }, isDragging: { classPropertyName: "isDragging", publicName: "isDragging", isSignal: true, isRequired: false, transformFunction: null }, fileSizeLimit: { classPropertyName: "fileSizeLimit", publicName: "fileSizeLimit", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { isDragging: "isDraggingChange", onChange: "onChange" }, ngImport: i0, template: "<input\r\n #uploadInput\r\n type=\"file\"\r\n name=\"file[]\"\r\n (change)=\"onFileSelect($event)\"\r\n style=\"display: none\"\r\n [multiple]=\"isMultipleEnabled()\"\r\n [accept]=\"shape() === 'circle' ? 'image/*' : accept()\"\r\n/>\r\n\r\n@if (shape() === \"circle\") {\r\n <div class=\"flex flex-col items-center gap-2 w-full\">\r\n <div class=\"flex\">\r\n <div class=\"flex flex-col items-center\">\r\n <mt-upload-user-preview\r\n [value]=\"primaryFile()\"\r\n [imgPath]=\"imgPath()\"\r\n [disabled]=\"disabled()\"\r\n [readonly]=\"readonly()\"\r\n [loading]=\"loading()\"\r\n [size]=\"size()\"\r\n [context]=\"context()\"\r\n [userImgClass]=\"userImgClass()\"\r\n [isDragging]=\"isDragging()\"\r\n [uploadProgress]=\"uploadProgress()\"\r\n (onUploadInputClicked)=\"uploadInput.click()\"\r\n (ondDownloadFile)=\"downloadFile($event)\"\r\n (onDeleteFile)=\"onDelete(primaryFile())\"\r\n (onDragOver)=\"onDragOver($event)\"\r\n (onDragLeave)=\"onDragLeave($event)\"\r\n (onDrop)=\"onDrop($event)\"\r\n ></mt-upload-user-preview>\r\n @if (label()) {\r\n <label\r\n [class.required]=\"\r\n ngControl?.control?.hasValidator(requiredValidator)\r\n \"\r\n [for]=\"ngControl?.name || label()\"\r\n >{{ label() }}</label\r\n >\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n} @else if (shape() === \"card\") {\r\n <mt-card\r\n headless\r\n class=\"border-2 border-dashed border-gray-300 rounded-lg cursor-pointer hover:bg-gray-50\"\r\n >\r\n <div class=\"content flex flex-col gap-5 items-center text-center\">\r\n @if (!files().length && !loading()) {\r\n <div class=\"flex flex-col gap-1\">\r\n @if (title()) {\r\n <div class=\"title text-lg font-semibold\">\r\n {{ title() }}\r\n </div>\r\n }\r\n @if (description()) {\r\n <div\r\n class=\"description text-sm text-muted-foreground secondary text-surface-500\"\r\n >\r\n {{ description() }}\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n @if (files().length) {\r\n <div class=\"flex w-full flex-col gap-2\">\r\n @for (file of files(); track $index) {\r\n <mt-upload-file-preview\r\n style=\"width: 100%\"\r\n [value]=\"file\"\r\n [imgPath]=\"resolveImgPath(file)\"\r\n [disabled]=\"disabled()\"\r\n [readonly]=\"readonly()\"\r\n [loading]=\"loading()\"\r\n [context]=\"context()\"\r\n [uploadProgress]=\"uploadProgress()\"\r\n (onUploadInputClicked)=\"uploadInput.click()\"\r\n (ondDownloadFile)=\"downloadFile(file)\"\r\n (onDeleteFile)=\"onDelete(file)\"\r\n />\r\n }\r\n @if (\r\n isMultipleEnabled() && !disabled() && !readonly() && !loading()\r\n ) {\r\n <mt-button\r\n [size]=\"'small'\"\r\n [label]=\"'components.upload.addMore' | transloco\"\r\n [icon]=\"'general.upload-01'\"\r\n (onClick)=\"uploadInput.click()\"\r\n />\r\n }\r\n </div>\r\n } @else if (loading()) {\r\n <div class=\"w-full flex gap-3 items-center justify-center p-3\">\r\n <p class=\"text-lg text-gray-500\">\r\n {{\r\n (\"components.upload.uploading\" | transloco) +\r\n uploadProgress() +\r\n \"%\"\r\n }}\r\n </p>\r\n </div>\r\n } @else {\r\n <mt-button\r\n [size]=\"'small'\"\r\n [label]=\"'components.upload.upload' | transloco\"\r\n [icon]=\"'general.upload-01'\"\r\n (onClick)=\"\r\n !loading() && !disabled() && !readonly() ? uploadInput.click() : ''\r\n \"\r\n [disabled]=\"disabled() || loading() || readonly()\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n} @else {\r\n <div class=\"flex flex-col items-start gap-2 w-full\">\r\n @if (label()) {\r\n <label\r\n [class.required]=\"ngControl?.control?.hasValidator(requiredValidator)\"\r\n [for]=\"ngControl?.name || label()\"\r\n >{{ label() }}</label\r\n >\r\n }\r\n\r\n <div\r\n class=\"w-full flex gap-3 items-center justify-center border-2 border-dashed border-gray-300 rounded-lg cursor-pointer hover:bg-gray-50\"\r\n [class]=\"disabled() ? 'bg-gray-50' : ''\"\r\n (click)=\"\r\n !loading() && !disabled() && !readonly() ? uploadInput.click() : ''\r\n \"\r\n [class.border-blue-500]=\"isDragging()\"\r\n [class.bg-blue-50]=\"isDragging()\"\r\n (dragover)=\"onDragOver($event)\"\r\n (dragleave)=\"onDragLeave($event)\"\r\n (drop)=\"onDrop($event)\"\r\n >\r\n @if (files().length) {\r\n <div\r\n class=\"flex w-full flex-col gap-2 p-2\"\r\n (click)=\"$event.stopPropagation()\"\r\n >\r\n @for (file of files(); track $index) {\r\n <mt-upload-file-preview\r\n style=\"width: 100%\"\r\n [value]=\"file\"\r\n [imgPath]=\"resolveImgPath(file)\"\r\n [disabled]=\"disabled()\"\r\n [readonly]=\"readonly()\"\r\n [loading]=\"loading()\"\r\n [context]=\"context()\"\r\n [uploadProgress]=\"uploadProgress()\"\r\n (onUploadInputClicked)=\"uploadInput.click()\"\r\n (ondDownloadFile)=\"downloadFile(file)\"\r\n (onDeleteFile)=\"onDelete(file)\"\r\n />\r\n }\r\n @if (\r\n isMultipleEnabled() && !disabled() && !readonly() && !loading()\r\n ) {\r\n <div\r\n class=\"w-full flex gap-2 items-center justify-center p-2 border-t border-dashed border-gray-300 cursor-pointer hover:bg-gray-100 rounded-b-lg transition-colors\"\r\n (click)=\"uploadInput.click()\"\r\n >\r\n <mt-icon icon=\"general.upload-01\" />\r\n <span class=\"text-sm text-gray-500\">\r\n {{ \"components.upload.addMore\" | transloco }}\r\n </span>\r\n </div>\r\n }\r\n </div>\r\n } @else if (loading()) {\r\n <div class=\"w-full flex gap-3 items-center justify-center p-3\">\r\n <p class=\"text-lg text-gray-500\">\r\n {{\r\n (\"components.upload.uploading\" | transloco) +\r\n uploadProgress() +\r\n \"%\"\r\n }}\r\n </p>\r\n </div>\r\n } @else {\r\n <div class=\"w-full flex gap-3 items-center justify-center p-3\">\r\n <mt-icon icon=\"general.upload-01\" />\r\n <p class=\"text-lg text-gray-500\">\r\n {{ \"components.upload.clickOrDrop\" | transloco }}\r\n </p>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n}\r\n<mt-field-validation [control]=\"ngControl?.control\"></mt-field-validation>\r\n", dependencies: [{ kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }, { kind: "component", type: UploadUserPreview, selector: "mt-upload-user-preview", inputs: ["value", "imgPath", "context", "loading", "uploadProgress", "isDragging", "disabled", "readonly", "size", "userImgClass"], outputs: ["onUploadInputClicked", "ondDownloadFile", "onDeleteFile", "onDragOver", "onDragLeave", "onDrop", "disabledChange"] }, { kind: "component", type: UploadFilePreview, selector: "mt-upload-file-preview", inputs: ["value", "imgPath", "context", "loading", "uploadProgress", "disabled", "readonly", "size"], outputs: ["onUploadInputClicked", "ondDownloadFile", "onDeleteFile", "disabledChange"] }, { kind: "component", type: FieldValidation, selector: "mt-field-validation", inputs: ["control", "touched"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "pipe", type: i1.TranslocoPipe, name: "transloco" }] });
572
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: UploadField, isStandalone: true, selector: "mt-upload-field", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, endPoint: { classPropertyName: "endPoint", publicName: "endPoint", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, userImgClass: { classPropertyName: "userImgClass", publicName: "userImgClass", isSignal: true, isRequired: false, transformFunction: null }, shape: { classPropertyName: "shape", publicName: "shape", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, accept: { classPropertyName: "accept", publicName: "accept", isSignal: true, isRequired: false, transformFunction: null }, isDragging: { classPropertyName: "isDragging", publicName: "isDragging", isSignal: true, isRequired: false, transformFunction: null }, fileSizeLimit: { classPropertyName: "fileSizeLimit", publicName: "fileSizeLimit", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { isDragging: "isDraggingChange", onChange: "onChange" }, ngImport: i0, template: "<input\n #uploadInput\n type=\"file\"\n name=\"file[]\"\n (change)=\"onFileSelect($event)\"\n style=\"display: none\"\n [multiple]=\"isMultipleEnabled()\"\n [accept]=\"shape() === 'circle' ? 'image/*' : accept()\"\n/>\n\n@if (shape() === \"circle\") {\n <div class=\"flex flex-col items-center gap-2 w-full\">\n <div class=\"flex\">\n <div class=\"flex flex-col items-center\">\n <mt-upload-user-preview\n [value]=\"primaryFile()\"\n [imgPath]=\"imgPath()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [loading]=\"loading()\"\n [size]=\"size()\"\n [context]=\"context()\"\n [userImgClass]=\"userImgClass()\"\n [isDragging]=\"isDragging()\"\n [uploadProgress]=\"uploadProgress()\"\n (onUploadInputClicked)=\"uploadInput.click()\"\n (ondDownloadFile)=\"downloadFile($event)\"\n (onDeleteFile)=\"onDelete(primaryFile())\"\n (onDragOver)=\"onDragOver($event)\"\n (onDragLeave)=\"onDragLeave($event)\"\n (onDrop)=\"onDrop($event)\"\n ></mt-upload-user-preview>\n @if (label()) {\n <label\n [class.required]=\"\n ngControl?.control?.hasValidator(requiredValidator)\n \"\n [for]=\"ngControl?.name || label()\"\n >{{ label() }}</label\n >\n }\n @if (acceptedTypesLabel()) {\n <span class=\"mt-1 text-xs text-surface-400\">\n {{\n \"components.upload.allowedTypes\"\n | transloco: { types: acceptedTypesLabel() }\n }}\n </span>\n }\n </div>\n </div>\n </div>\n} @else if (shape() === \"card\") {\n <mt-card\n headless\n class=\"border-2 border-dashed border-gray-300 rounded-lg cursor-pointer hover:bg-gray-50\"\n >\n <div class=\"content flex flex-col gap-5 items-center text-center\">\n @if (!files().length && !loading()) {\n <div class=\"flex flex-col gap-1\">\n @if (title()) {\n <div class=\"title text-lg font-semibold\">\n {{ title() }}\n </div>\n }\n @if (description()) {\n <div\n class=\"description text-sm text-muted-foreground secondary text-surface-500\"\n >\n {{ description() }}\n </div>\n }\n @if (acceptedTypesLabel()) {\n <div class=\"mt-1 flex items-center justify-center gap-1.5\">\n <mt-icon\n icon=\"general.info-circle\"\n class=\"text-xs text-surface-400\"\n />\n <span class=\"text-xs text-surface-400\">\n {{\n \"components.upload.allowedTypes\"\n | transloco: { types: acceptedTypesLabel() }\n }}\n </span>\n </div>\n }\n </div>\n }\n\n @if (files().length) {\n <div class=\"flex w-full flex-col gap-2\">\n @for (file of files(); track $index) {\n <mt-upload-file-preview\n style=\"width: 100%\"\n [value]=\"file\"\n [imgPath]=\"resolveImgPath(file)\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [loading]=\"loading()\"\n [context]=\"context()\"\n [uploadProgress]=\"uploadProgress()\"\n (onUploadInputClicked)=\"uploadInput.click()\"\n (ondDownloadFile)=\"downloadFile(file)\"\n (onDeleteFile)=\"onDelete(file)\"\n />\n }\n @if (\n isMultipleEnabled() && !disabled() && !readonly() && !loading()\n ) {\n <mt-button\n [size]=\"'small'\"\n [label]=\"'components.upload.addMore' | transloco\"\n [icon]=\"'general.upload-01'\"\n (onClick)=\"uploadInput.click()\"\n />\n }\n </div>\n } @else if (loading()) {\n <div class=\"w-full flex gap-3 items-center justify-center p-3\">\n <p class=\"text-lg text-gray-500\">\n {{\n (\"components.upload.uploading\" | transloco) +\n uploadProgress() +\n \"%\"\n }}\n </p>\n </div>\n } @else {\n <mt-button\n [size]=\"'small'\"\n [label]=\"'components.upload.upload' | transloco\"\n [icon]=\"'general.upload-01'\"\n (onClick)=\"\n !loading() && !disabled() && !readonly() ? uploadInput.click() : ''\n \"\n [disabled]=\"disabled() || loading() || readonly()\"\n />\n }\n </div>\n </mt-card>\n} @else {\n <div class=\"flex flex-col items-start gap-2 w-full\">\n @if (label()) {\n <label\n [class.required]=\"ngControl?.control?.hasValidator(requiredValidator)\"\n [for]=\"ngControl?.name || label()\"\n >{{ label() }}</label\n >\n }\n\n <div\n class=\"w-full flex gap-3 items-center justify-center border-2 border-dashed border-gray-300 rounded-lg cursor-pointer hover:bg-gray-50\"\n [class]=\"disabled() ? 'bg-gray-50' : ''\"\n (click)=\"\n !loading() && !disabled() && !readonly() ? uploadInput.click() : ''\n \"\n [class.border-blue-500]=\"isDragging()\"\n [class.bg-blue-50]=\"isDragging()\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\"\n >\n @if (files().length) {\n <div\n class=\"flex w-full flex-col gap-2 p-2\"\n (click)=\"$event.stopPropagation()\"\n >\n @for (file of files(); track $index) {\n <mt-upload-file-preview\n style=\"width: 100%\"\n [value]=\"file\"\n [imgPath]=\"resolveImgPath(file)\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [loading]=\"loading()\"\n [context]=\"context()\"\n [uploadProgress]=\"uploadProgress()\"\n (onUploadInputClicked)=\"uploadInput.click()\"\n (ondDownloadFile)=\"downloadFile(file)\"\n (onDeleteFile)=\"onDelete(file)\"\n />\n }\n @if (\n isMultipleEnabled() && !disabled() && !readonly() && !loading()\n ) {\n <div\n class=\"w-full flex gap-2 items-center justify-center p-2 border-t border-dashed border-gray-300 cursor-pointer hover:bg-gray-100 rounded-b-lg transition-colors\"\n (click)=\"uploadInput.click()\"\n >\n <mt-icon icon=\"general.upload-01\" />\n <span class=\"text-sm text-gray-500\">\n {{ \"components.upload.addMore\" | transloco }}\n </span>\n </div>\n }\n </div>\n } @else if (loading()) {\n <div class=\"w-full flex gap-3 items-center justify-center p-3\">\n <p class=\"text-lg text-gray-500\">\n {{\n (\"components.upload.uploading\" | transloco) +\n uploadProgress() +\n \"%\"\n }}\n </p>\n </div>\n } @else {\n <div class=\"w-full flex flex-col gap-1 items-center justify-center p-3\">\n <div class=\"flex gap-3 items-center\">\n <mt-icon icon=\"general.upload-01\" />\n <p class=\"text-lg text-gray-500\">\n {{ \"components.upload.clickOrDrop\" | transloco }}\n </p>\n </div>\n @if (acceptedTypesLabel()) {\n <span class=\"text-xs text-surface-400\">\n {{\n \"components.upload.allowedTypes\"\n | transloco: { types: acceptedTypesLabel() }\n }}\n </span>\n }\n </div>\n }\n </div>\n </div>\n}\n<mt-field-validation [control]=\"ngControl?.control\"></mt-field-validation>\n", dependencies: [{ kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }, { kind: "component", type: UploadUserPreview, selector: "mt-upload-user-preview", inputs: ["value", "imgPath", "context", "loading", "uploadProgress", "isDragging", "disabled", "readonly", "size", "userImgClass"], outputs: ["onUploadInputClicked", "ondDownloadFile", "onDeleteFile", "onDragOver", "onDragLeave", "onDrop", "disabledChange"] }, { kind: "component", type: UploadFilePreview, selector: "mt-upload-file-preview", inputs: ["value", "imgPath", "context", "loading", "uploadProgress", "disabled", "readonly", "size"], outputs: ["onUploadInputClicked", "ondDownloadFile", "onDeleteFile", "disabledChange"] }, { kind: "component", type: FieldValidation, selector: "mt-field-validation", inputs: ["control", "touched"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "pipe", type: i1.TranslocoPipe, name: "transloco" }] });
529
573
  }
530
574
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: UploadField, decorators: [{
531
575
  type: Component,
@@ -537,8 +581,45 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
537
581
  Card,
538
582
  Button,
539
583
  TranslocoModule,
540
- ], template: "<input\r\n #uploadInput\r\n type=\"file\"\r\n name=\"file[]\"\r\n (change)=\"onFileSelect($event)\"\r\n style=\"display: none\"\r\n [multiple]=\"isMultipleEnabled()\"\r\n [accept]=\"shape() === 'circle' ? 'image/*' : accept()\"\r\n/>\r\n\r\n@if (shape() === \"circle\") {\r\n <div class=\"flex flex-col items-center gap-2 w-full\">\r\n <div class=\"flex\">\r\n <div class=\"flex flex-col items-center\">\r\n <mt-upload-user-preview\r\n [value]=\"primaryFile()\"\r\n [imgPath]=\"imgPath()\"\r\n [disabled]=\"disabled()\"\r\n [readonly]=\"readonly()\"\r\n [loading]=\"loading()\"\r\n [size]=\"size()\"\r\n [context]=\"context()\"\r\n [userImgClass]=\"userImgClass()\"\r\n [isDragging]=\"isDragging()\"\r\n [uploadProgress]=\"uploadProgress()\"\r\n (onUploadInputClicked)=\"uploadInput.click()\"\r\n (ondDownloadFile)=\"downloadFile($event)\"\r\n (onDeleteFile)=\"onDelete(primaryFile())\"\r\n (onDragOver)=\"onDragOver($event)\"\r\n (onDragLeave)=\"onDragLeave($event)\"\r\n (onDrop)=\"onDrop($event)\"\r\n ></mt-upload-user-preview>\r\n @if (label()) {\r\n <label\r\n [class.required]=\"\r\n ngControl?.control?.hasValidator(requiredValidator)\r\n \"\r\n [for]=\"ngControl?.name || label()\"\r\n >{{ label() }}</label\r\n >\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n} @else if (shape() === \"card\") {\r\n <mt-card\r\n headless\r\n class=\"border-2 border-dashed border-gray-300 rounded-lg cursor-pointer hover:bg-gray-50\"\r\n >\r\n <div class=\"content flex flex-col gap-5 items-center text-center\">\r\n @if (!files().length && !loading()) {\r\n <div class=\"flex flex-col gap-1\">\r\n @if (title()) {\r\n <div class=\"title text-lg font-semibold\">\r\n {{ title() }}\r\n </div>\r\n }\r\n @if (description()) {\r\n <div\r\n class=\"description text-sm text-muted-foreground secondary text-surface-500\"\r\n >\r\n {{ description() }}\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n @if (files().length) {\r\n <div class=\"flex w-full flex-col gap-2\">\r\n @for (file of files(); track $index) {\r\n <mt-upload-file-preview\r\n style=\"width: 100%\"\r\n [value]=\"file\"\r\n [imgPath]=\"resolveImgPath(file)\"\r\n [disabled]=\"disabled()\"\r\n [readonly]=\"readonly()\"\r\n [loading]=\"loading()\"\r\n [context]=\"context()\"\r\n [uploadProgress]=\"uploadProgress()\"\r\n (onUploadInputClicked)=\"uploadInput.click()\"\r\n (ondDownloadFile)=\"downloadFile(file)\"\r\n (onDeleteFile)=\"onDelete(file)\"\r\n />\r\n }\r\n @if (\r\n isMultipleEnabled() && !disabled() && !readonly() && !loading()\r\n ) {\r\n <mt-button\r\n [size]=\"'small'\"\r\n [label]=\"'components.upload.addMore' | transloco\"\r\n [icon]=\"'general.upload-01'\"\r\n (onClick)=\"uploadInput.click()\"\r\n />\r\n }\r\n </div>\r\n } @else if (loading()) {\r\n <div class=\"w-full flex gap-3 items-center justify-center p-3\">\r\n <p class=\"text-lg text-gray-500\">\r\n {{\r\n (\"components.upload.uploading\" | transloco) +\r\n uploadProgress() +\r\n \"%\"\r\n }}\r\n </p>\r\n </div>\r\n } @else {\r\n <mt-button\r\n [size]=\"'small'\"\r\n [label]=\"'components.upload.upload' | transloco\"\r\n [icon]=\"'general.upload-01'\"\r\n (onClick)=\"\r\n !loading() && !disabled() && !readonly() ? uploadInput.click() : ''\r\n \"\r\n [disabled]=\"disabled() || loading() || readonly()\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n} @else {\r\n <div class=\"flex flex-col items-start gap-2 w-full\">\r\n @if (label()) {\r\n <label\r\n [class.required]=\"ngControl?.control?.hasValidator(requiredValidator)\"\r\n [for]=\"ngControl?.name || label()\"\r\n >{{ label() }}</label\r\n >\r\n }\r\n\r\n <div\r\n class=\"w-full flex gap-3 items-center justify-center border-2 border-dashed border-gray-300 rounded-lg cursor-pointer hover:bg-gray-50\"\r\n [class]=\"disabled() ? 'bg-gray-50' : ''\"\r\n (click)=\"\r\n !loading() && !disabled() && !readonly() ? uploadInput.click() : ''\r\n \"\r\n [class.border-blue-500]=\"isDragging()\"\r\n [class.bg-blue-50]=\"isDragging()\"\r\n (dragover)=\"onDragOver($event)\"\r\n (dragleave)=\"onDragLeave($event)\"\r\n (drop)=\"onDrop($event)\"\r\n >\r\n @if (files().length) {\r\n <div\r\n class=\"flex w-full flex-col gap-2 p-2\"\r\n (click)=\"$event.stopPropagation()\"\r\n >\r\n @for (file of files(); track $index) {\r\n <mt-upload-file-preview\r\n style=\"width: 100%\"\r\n [value]=\"file\"\r\n [imgPath]=\"resolveImgPath(file)\"\r\n [disabled]=\"disabled()\"\r\n [readonly]=\"readonly()\"\r\n [loading]=\"loading()\"\r\n [context]=\"context()\"\r\n [uploadProgress]=\"uploadProgress()\"\r\n (onUploadInputClicked)=\"uploadInput.click()\"\r\n (ondDownloadFile)=\"downloadFile(file)\"\r\n (onDeleteFile)=\"onDelete(file)\"\r\n />\r\n }\r\n @if (\r\n isMultipleEnabled() && !disabled() && !readonly() && !loading()\r\n ) {\r\n <div\r\n class=\"w-full flex gap-2 items-center justify-center p-2 border-t border-dashed border-gray-300 cursor-pointer hover:bg-gray-100 rounded-b-lg transition-colors\"\r\n (click)=\"uploadInput.click()\"\r\n >\r\n <mt-icon icon=\"general.upload-01\" />\r\n <span class=\"text-sm text-gray-500\">\r\n {{ \"components.upload.addMore\" | transloco }}\r\n </span>\r\n </div>\r\n }\r\n </div>\r\n } @else if (loading()) {\r\n <div class=\"w-full flex gap-3 items-center justify-center p-3\">\r\n <p class=\"text-lg text-gray-500\">\r\n {{\r\n (\"components.upload.uploading\" | transloco) +\r\n uploadProgress() +\r\n \"%\"\r\n }}\r\n </p>\r\n </div>\r\n } @else {\r\n <div class=\"w-full flex gap-3 items-center justify-center p-3\">\r\n <mt-icon icon=\"general.upload-01\" />\r\n <p class=\"text-lg text-gray-500\">\r\n {{ \"components.upload.clickOrDrop\" | transloco }}\r\n </p>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n}\r\n<mt-field-validation [control]=\"ngControl?.control\"></mt-field-validation>\r\n" }]
584
+ ], template: "<input\n #uploadInput\n type=\"file\"\n name=\"file[]\"\n (change)=\"onFileSelect($event)\"\n style=\"display: none\"\n [multiple]=\"isMultipleEnabled()\"\n [accept]=\"shape() === 'circle' ? 'image/*' : accept()\"\n/>\n\n@if (shape() === \"circle\") {\n <div class=\"flex flex-col items-center gap-2 w-full\">\n <div class=\"flex\">\n <div class=\"flex flex-col items-center\">\n <mt-upload-user-preview\n [value]=\"primaryFile()\"\n [imgPath]=\"imgPath()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [loading]=\"loading()\"\n [size]=\"size()\"\n [context]=\"context()\"\n [userImgClass]=\"userImgClass()\"\n [isDragging]=\"isDragging()\"\n [uploadProgress]=\"uploadProgress()\"\n (onUploadInputClicked)=\"uploadInput.click()\"\n (ondDownloadFile)=\"downloadFile($event)\"\n (onDeleteFile)=\"onDelete(primaryFile())\"\n (onDragOver)=\"onDragOver($event)\"\n (onDragLeave)=\"onDragLeave($event)\"\n (onDrop)=\"onDrop($event)\"\n ></mt-upload-user-preview>\n @if (label()) {\n <label\n [class.required]=\"\n ngControl?.control?.hasValidator(requiredValidator)\n \"\n [for]=\"ngControl?.name || label()\"\n >{{ label() }}</label\n >\n }\n @if (acceptedTypesLabel()) {\n <span class=\"mt-1 text-xs text-surface-400\">\n {{\n \"components.upload.allowedTypes\"\n | transloco: { types: acceptedTypesLabel() }\n }}\n </span>\n }\n </div>\n </div>\n </div>\n} @else if (shape() === \"card\") {\n <mt-card\n headless\n class=\"border-2 border-dashed border-gray-300 rounded-lg cursor-pointer hover:bg-gray-50\"\n >\n <div class=\"content flex flex-col gap-5 items-center text-center\">\n @if (!files().length && !loading()) {\n <div class=\"flex flex-col gap-1\">\n @if (title()) {\n <div class=\"title text-lg font-semibold\">\n {{ title() }}\n </div>\n }\n @if (description()) {\n <div\n class=\"description text-sm text-muted-foreground secondary text-surface-500\"\n >\n {{ description() }}\n </div>\n }\n @if (acceptedTypesLabel()) {\n <div class=\"mt-1 flex items-center justify-center gap-1.5\">\n <mt-icon\n icon=\"general.info-circle\"\n class=\"text-xs text-surface-400\"\n />\n <span class=\"text-xs text-surface-400\">\n {{\n \"components.upload.allowedTypes\"\n | transloco: { types: acceptedTypesLabel() }\n }}\n </span>\n </div>\n }\n </div>\n }\n\n @if (files().length) {\n <div class=\"flex w-full flex-col gap-2\">\n @for (file of files(); track $index) {\n <mt-upload-file-preview\n style=\"width: 100%\"\n [value]=\"file\"\n [imgPath]=\"resolveImgPath(file)\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [loading]=\"loading()\"\n [context]=\"context()\"\n [uploadProgress]=\"uploadProgress()\"\n (onUploadInputClicked)=\"uploadInput.click()\"\n (ondDownloadFile)=\"downloadFile(file)\"\n (onDeleteFile)=\"onDelete(file)\"\n />\n }\n @if (\n isMultipleEnabled() && !disabled() && !readonly() && !loading()\n ) {\n <mt-button\n [size]=\"'small'\"\n [label]=\"'components.upload.addMore' | transloco\"\n [icon]=\"'general.upload-01'\"\n (onClick)=\"uploadInput.click()\"\n />\n }\n </div>\n } @else if (loading()) {\n <div class=\"w-full flex gap-3 items-center justify-center p-3\">\n <p class=\"text-lg text-gray-500\">\n {{\n (\"components.upload.uploading\" | transloco) +\n uploadProgress() +\n \"%\"\n }}\n </p>\n </div>\n } @else {\n <mt-button\n [size]=\"'small'\"\n [label]=\"'components.upload.upload' | transloco\"\n [icon]=\"'general.upload-01'\"\n (onClick)=\"\n !loading() && !disabled() && !readonly() ? uploadInput.click() : ''\n \"\n [disabled]=\"disabled() || loading() || readonly()\"\n />\n }\n </div>\n </mt-card>\n} @else {\n <div class=\"flex flex-col items-start gap-2 w-full\">\n @if (label()) {\n <label\n [class.required]=\"ngControl?.control?.hasValidator(requiredValidator)\"\n [for]=\"ngControl?.name || label()\"\n >{{ label() }}</label\n >\n }\n\n <div\n class=\"w-full flex gap-3 items-center justify-center border-2 border-dashed border-gray-300 rounded-lg cursor-pointer hover:bg-gray-50\"\n [class]=\"disabled() ? 'bg-gray-50' : ''\"\n (click)=\"\n !loading() && !disabled() && !readonly() ? uploadInput.click() : ''\n \"\n [class.border-blue-500]=\"isDragging()\"\n [class.bg-blue-50]=\"isDragging()\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\"\n >\n @if (files().length) {\n <div\n class=\"flex w-full flex-col gap-2 p-2\"\n (click)=\"$event.stopPropagation()\"\n >\n @for (file of files(); track $index) {\n <mt-upload-file-preview\n style=\"width: 100%\"\n [value]=\"file\"\n [imgPath]=\"resolveImgPath(file)\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [loading]=\"loading()\"\n [context]=\"context()\"\n [uploadProgress]=\"uploadProgress()\"\n (onUploadInputClicked)=\"uploadInput.click()\"\n (ondDownloadFile)=\"downloadFile(file)\"\n (onDeleteFile)=\"onDelete(file)\"\n />\n }\n @if (\n isMultipleEnabled() && !disabled() && !readonly() && !loading()\n ) {\n <div\n class=\"w-full flex gap-2 items-center justify-center p-2 border-t border-dashed border-gray-300 cursor-pointer hover:bg-gray-100 rounded-b-lg transition-colors\"\n (click)=\"uploadInput.click()\"\n >\n <mt-icon icon=\"general.upload-01\" />\n <span class=\"text-sm text-gray-500\">\n {{ \"components.upload.addMore\" | transloco }}\n </span>\n </div>\n }\n </div>\n } @else if (loading()) {\n <div class=\"w-full flex gap-3 items-center justify-center p-3\">\n <p class=\"text-lg text-gray-500\">\n {{\n (\"components.upload.uploading\" | transloco) +\n uploadProgress() +\n \"%\"\n }}\n </p>\n </div>\n } @else {\n <div class=\"w-full flex flex-col gap-1 items-center justify-center p-3\">\n <div class=\"flex gap-3 items-center\">\n <mt-icon icon=\"general.upload-01\" />\n <p class=\"text-lg text-gray-500\">\n {{ \"components.upload.clickOrDrop\" | transloco }}\n </p>\n </div>\n @if (acceptedTypesLabel()) {\n <span class=\"text-xs text-surface-400\">\n {{\n \"components.upload.allowedTypes\"\n | transloco: { types: acceptedTypesLabel() }\n }}\n </span>\n }\n </div>\n }\n </div>\n </div>\n}\n<mt-field-validation [control]=\"ngControl?.control\"></mt-field-validation>\n" }]
541
585
  }], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], endPoint: [{ type: i0.Input, args: [{ isSignal: true, alias: "endPoint", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], userImgClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "userImgClass", required: false }] }], shape: [{ type: i0.Input, args: [{ isSignal: true, alias: "shape", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], isDragging: [{ type: i0.Input, args: [{ isSignal: true, alias: "isDragging", required: false }] }, { type: i0.Output, args: ["isDraggingChange"] }], fileSizeLimit: [{ type: i0.Input, args: [{ isSignal: true, alias: "fileSizeLimit", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], context: [{ type: i0.Input, args: [{ isSignal: true, alias: "context", required: false }] }], onChange: [{ type: i0.Output, args: ["onChange"] }] } });
586
+ /**
587
+ * Re-validates a picked/dropped file against the `accept` spec on the client,
588
+ * since the native picker's accept filter can be bypassed by the user.
589
+ * Supports the full HTML accept syntax: extensions (`.pdf`), exact MIME
590
+ * (`application/pdf`), wildcard MIME (`image/*`), and catch-all (`*` / `*\/*`).
591
+ */
592
+ function isFileAccepted(file, accept) {
593
+ const spec = (accept ?? '').trim();
594
+ // No restriction configured, or explicitly allowing every file.
595
+ if (!spec || spec === '*' || spec === '*/*') {
596
+ return true;
597
+ }
598
+ const fileName = (file?.name ?? '').toLowerCase();
599
+ const fileType = (file?.type ?? '').toLowerCase();
600
+ return spec
601
+ .split(',')
602
+ .map((token) => token.trim().toLowerCase())
603
+ .filter((token) => token.length > 0)
604
+ .some((token) => {
605
+ // Catch-all token.
606
+ if (token === '*' || token === '*/*') {
607
+ return true;
608
+ }
609
+ // Extension token, e.g. ".pdf" — the only reliable check when the
610
+ // browser cannot resolve a MIME type (common for .docx/.xlsx).
611
+ if (token.startsWith('.')) {
612
+ return fileName.endsWith(token);
613
+ }
614
+ // Wildcard MIME token, e.g. "image/*".
615
+ if (token.endsWith('/*')) {
616
+ const group = token.slice(0, token.indexOf('/') + 1);
617
+ return !!fileType && fileType.startsWith(group);
618
+ }
619
+ // Exact MIME token, e.g. "application/pdf".
620
+ return !!fileType && fileType === token;
621
+ });
622
+ }
542
623
  function isSameFile(source, target) {
543
624
  if (!source || !target) {
544
625
  return source === target;