@brickclay-org/ui 0.0.65 → 0.0.67
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.
- package/fesm2022/brickclay-org-ui.mjs +323 -31
- package/fesm2022/brickclay-org-ui.mjs.map +1 -1
- package/index.d.ts +73 -9
- package/package.json +1 -1
- package/src/assets/icons/bin-gray.svg +7 -0
- package/src/assets/icons/check-green.svg +4 -0
- package/src/lib/column-select/components/column-select/column-select.css +3 -0
- package/src/lib/file-card/file-card.css +107 -0
- package/src/lib/file-picker/file-picker.css +106 -0
- package/src/styles.css +2 -0
|
@@ -6742,65 +6742,113 @@ class BkColumnSelect {
|
|
|
6742
6742
|
columnFilterService;
|
|
6743
6743
|
searchable = false;
|
|
6744
6744
|
cacheKey;
|
|
6745
|
-
columns;
|
|
6745
|
+
columns = [];
|
|
6746
6746
|
isOpened = false;
|
|
6747
|
-
formBoxRef;
|
|
6748
|
-
change = new EventEmitter();
|
|
6749
6747
|
isOpenedChange = new EventEmitter();
|
|
6748
|
+
formBoxRef;
|
|
6749
|
+
/** Value bound via ngModel – only updated when user ticks/unticks a checkbox, never on search. */
|
|
6750
6750
|
columnsFilterList = [];
|
|
6751
6751
|
search = '';
|
|
6752
|
+
onChangeCallback = () => { };
|
|
6753
|
+
onTouchedCallback = () => { };
|
|
6752
6754
|
constructor(columnFilterService) {
|
|
6753
6755
|
this.columnFilterService = columnFilterService;
|
|
6754
6756
|
}
|
|
6755
|
-
|
|
6756
|
-
|
|
6757
|
+
writeValue(value) {
|
|
6758
|
+
const isEmpty = !value || !Array.isArray(value) || value.length === 0;
|
|
6759
|
+
if (isEmpty && this.shouldLoadFromService()) {
|
|
6760
|
+
this.loadColumnsFilterListFromService();
|
|
6761
|
+
}
|
|
6762
|
+
else {
|
|
6763
|
+
this.columnsFilterList = Array.isArray(value) ? value : [];
|
|
6764
|
+
}
|
|
6757
6765
|
}
|
|
6758
6766
|
ngOnChanges(changes) {
|
|
6759
|
-
|
|
6760
|
-
|
|
6767
|
+
const columnsChanged = changes['columns'] && !changes['columns'].firstChange;
|
|
6768
|
+
const cacheKeyChanged = changes['cacheKey'] && !changes['cacheKey'].firstChange;
|
|
6769
|
+
if ((columnsChanged || cacheKeyChanged) && this.columnsFilterList.length === 0 && this.shouldLoadFromService()) {
|
|
6770
|
+
this.loadColumnsFilterListFromService();
|
|
6761
6771
|
}
|
|
6762
6772
|
}
|
|
6763
|
-
|
|
6773
|
+
shouldLoadFromService() {
|
|
6774
|
+
return !!this.cacheKey && !!this.columns?.length;
|
|
6775
|
+
}
|
|
6776
|
+
loadColumnsFilterListFromService() {
|
|
6764
6777
|
this.columnsFilterList = this.columnFilterService.getColumnsFilterList(this.cacheKey, this.columns);
|
|
6765
|
-
this.
|
|
6778
|
+
this.onChangeCallback(this.columnsFilterList);
|
|
6779
|
+
}
|
|
6780
|
+
registerOnChange(fn) {
|
|
6781
|
+
this.onChangeCallback = fn;
|
|
6782
|
+
}
|
|
6783
|
+
registerOnTouched(fn) {
|
|
6784
|
+
this.onTouchedCallback = fn;
|
|
6785
|
+
}
|
|
6786
|
+
setDisabledState(isDisabled) {
|
|
6787
|
+
// Optional: disable button/dropdown when control is disabled
|
|
6766
6788
|
}
|
|
6767
6789
|
filterButtonClicked(event) {
|
|
6768
6790
|
event.stopPropagation();
|
|
6769
|
-
|
|
6791
|
+
const willOpen = !this.isOpened;
|
|
6792
|
+
if (!willOpen) {
|
|
6793
|
+
this.clearSearch();
|
|
6794
|
+
this.onTouchedCallback();
|
|
6795
|
+
}
|
|
6796
|
+
this.isOpenedChange.emit(willOpen);
|
|
6770
6797
|
}
|
|
6771
|
-
|
|
6798
|
+
/** Called only on checkbox tick/untick – not on search. Emits via CVA so ngModel updates. */
|
|
6799
|
+
onChangeColumnFilter() {
|
|
6772
6800
|
this.columnFilterService.updateColumnFilterList(this.cacheKey, this.columnsFilterList);
|
|
6773
|
-
this.
|
|
6801
|
+
this.onChangeCallback(this.columnsFilterList);
|
|
6802
|
+
this.onTouchedCallback();
|
|
6803
|
+
}
|
|
6804
|
+
clearSearch() {
|
|
6805
|
+
this.search = '';
|
|
6806
|
+
}
|
|
6807
|
+
closeDropdown() {
|
|
6808
|
+
this.clearSearch();
|
|
6809
|
+
this.onTouchedCallback();
|
|
6810
|
+
this.isOpened = false;
|
|
6811
|
+
this.isOpenedChange.emit(this.isOpened);
|
|
6774
6812
|
}
|
|
6775
6813
|
onClick(event) {
|
|
6776
|
-
|
|
6777
|
-
|
|
6778
|
-
|
|
6779
|
-
|
|
6814
|
+
if (!this.isOpened) {
|
|
6815
|
+
return;
|
|
6816
|
+
}
|
|
6817
|
+
const formBox = this.formBoxRef?.nativeElement;
|
|
6818
|
+
if (formBox && formBox.contains(event.target)) {
|
|
6819
|
+
return;
|
|
6780
6820
|
}
|
|
6781
|
-
// Check if the click target is .ng-value-icon
|
|
6782
6821
|
if (event.target instanceof HTMLElement &&
|
|
6783
6822
|
event.target.classList.contains('ng-value-icon')) {
|
|
6784
|
-
// Do nothing if click is on .ng-value-icon
|
|
6785
6823
|
return;
|
|
6786
6824
|
}
|
|
6787
|
-
|
|
6788
|
-
|
|
6789
|
-
|
|
6790
|
-
// Close the popup if the click is not on the button
|
|
6791
|
-
this.isOpened = false;
|
|
6792
|
-
this.isOpenedChange.emit(this.isOpened);
|
|
6825
|
+
if (event.target instanceof HTMLElement &&
|
|
6826
|
+
event.target.closest('.btn-light-primary-custom')) {
|
|
6827
|
+
return;
|
|
6793
6828
|
}
|
|
6829
|
+
this.closeDropdown();
|
|
6794
6830
|
}
|
|
6795
6831
|
get list() {
|
|
6796
6832
|
return this.columnsFilterList.filter((x) => x.columnName.toLowerCase().includes(this.search.toLowerCase()));
|
|
6797
6833
|
}
|
|
6798
6834
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: BkColumnSelect, deps: [{ token: BkColumnFilterService }], target: i0.ɵɵFactoryTarget.Component });
|
|
6799
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: BkColumnSelect, isStandalone: true, selector: "bk-column-select", inputs: { searchable: "searchable", cacheKey: "cacheKey", columns: "columns", isOpened: "isOpened" }, outputs: {
|
|
6835
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: BkColumnSelect, isStandalone: true, selector: "bk-column-select", inputs: { searchable: "searchable", cacheKey: "cacheKey", columns: "columns", isOpened: "isOpened" }, outputs: { isOpenedChange: "isOpenedChange" }, host: { listeners: { "document:click": "onClick($event)" } }, providers: [
|
|
6836
|
+
{
|
|
6837
|
+
provide: NG_VALUE_ACCESSOR,
|
|
6838
|
+
useExisting: forwardRef(() => BkColumnSelect),
|
|
6839
|
+
multi: true,
|
|
6840
|
+
},
|
|
6841
|
+
], viewQueries: [{ propertyName: "formBoxRef", first: true, predicate: ["formBox"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"relative\">\r\n\r\n <bk-button [size]=\"'xsm'\" [variant]=\"'secondary'\" [leftIcon]=\"'../../../../assets/icons/columns-black.svg'\"\r\n (click)=\"filterButtonClicked($event)\" [label]=\"'Columns'\" [buttonClass]=\"'!text-black'\"></bk-button>\r\n\r\n <!-- Dropdown Box -->\r\n @if(isOpened){\r\n\r\n <div #formBox\r\n class=\"absolute right-0 mt-2 w-[178px] bg-white border border-[#EFEFF1] rounded-xl shadow-xl p-3 pe-1 z-[9999]\">\r\n @if(searchable){\r\n <bk-input [id]=\"'search-input-1'\" [name]=\"'search-input-1'\"\r\n [iconSrc]=\"'../../../../assets/icons/search-input.svg'\" type=\"text\" [(ngModel)]=\"search\"\r\n placeholder=\"Search\"></bk-input>\r\n }\r\n <div class=\"flex flex-col gap-0.5 max-h-[360px] overflow-y-auto\">\r\n @for (column of list; track column.columnName; let i = $index) {\r\n <div class=\"flex items-center gap-2 px-3 py-2\">\r\n <bk-checkbox id=\"columnsFilterList-{{column.columnName}}\" checkboxClass=\"sm\" [(ngModel)]=\"column.selected\"\r\n (change)=\"onChangeColumnFilter()\">\r\n\r\n </bk-checkbox>\r\n\r\n\r\n\r\n <label class=\"text-xs cursor-pointer text-[#141414] select-none truncate font-medium\"\r\n for=\"columnsFilterList-{{column.columnName}}\">\r\n {{column.columnName}}\r\n </label>\r\n </div>\r\n }\r\n @if(!list.length){\r\n <p class=\"column-select-option-empty\">No items found</p>\r\n }\r\n </div>\r\n </div>\r\n }\r\n</div>\r\n\r\n\r\n", styles: [".column-select-option-empty{@apply px-3 py-2 text-gray-400 cursor-default text-sm;}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: BkButton, selector: "bk-button", inputs: ["variant", "size", "label", "leftIcon", "rightIcon", "iconAlt", "type", "loading", "disabled", "buttonClass", "textClass", "spinnerClass"], outputs: ["clicked"] }, { kind: "component", type: BkCheckbox, selector: "bk-checkbox", inputs: ["checkboxClass", "label", "labelClass", "disabled"], outputs: ["change"] }, { kind: "component", type: BkInput, selector: "bk-input", inputs: ["id", "name", "mask", "autoComplete", "label", "placeholder", "hint", "required", "type", "value", "hasError", "showErrorIcon", "errorMessage", "disabled", "tabIndex", "readOnly", "autoCapitalize", "inputMode", "iconSrc", "iconAlt", "showIcon", "phone", "countryCode", "countryOptions", "iconOrientation", "password", "showPassword", "pattern", "max", "min", "step", "maxlength", "minlength"], outputs: ["input", "change", "focus", "blur", "clicked"] }] });
|
|
6800
6842
|
}
|
|
6801
6843
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: BkColumnSelect, decorators: [{
|
|
6802
6844
|
type: Component,
|
|
6803
|
-
args: [{ selector: 'bk-column-select', imports: [FormsModule, BkButton, BkCheckbox, BkInput], standalone: true,
|
|
6845
|
+
args: [{ selector: 'bk-column-select', imports: [FormsModule, BkButton, BkCheckbox, BkInput], standalone: true, providers: [
|
|
6846
|
+
{
|
|
6847
|
+
provide: NG_VALUE_ACCESSOR,
|
|
6848
|
+
useExisting: forwardRef(() => BkColumnSelect),
|
|
6849
|
+
multi: true,
|
|
6850
|
+
},
|
|
6851
|
+
], template: "<div class=\"relative\">\r\n\r\n <bk-button [size]=\"'xsm'\" [variant]=\"'secondary'\" [leftIcon]=\"'../../../../assets/icons/columns-black.svg'\"\r\n (click)=\"filterButtonClicked($event)\" [label]=\"'Columns'\" [buttonClass]=\"'!text-black'\"></bk-button>\r\n\r\n <!-- Dropdown Box -->\r\n @if(isOpened){\r\n\r\n <div #formBox\r\n class=\"absolute right-0 mt-2 w-[178px] bg-white border border-[#EFEFF1] rounded-xl shadow-xl p-3 pe-1 z-[9999]\">\r\n @if(searchable){\r\n <bk-input [id]=\"'search-input-1'\" [name]=\"'search-input-1'\"\r\n [iconSrc]=\"'../../../../assets/icons/search-input.svg'\" type=\"text\" [(ngModel)]=\"search\"\r\n placeholder=\"Search\"></bk-input>\r\n }\r\n <div class=\"flex flex-col gap-0.5 max-h-[360px] overflow-y-auto\">\r\n @for (column of list; track column.columnName; let i = $index) {\r\n <div class=\"flex items-center gap-2 px-3 py-2\">\r\n <bk-checkbox id=\"columnsFilterList-{{column.columnName}}\" checkboxClass=\"sm\" [(ngModel)]=\"column.selected\"\r\n (change)=\"onChangeColumnFilter()\">\r\n\r\n </bk-checkbox>\r\n\r\n\r\n\r\n <label class=\"text-xs cursor-pointer text-[#141414] select-none truncate font-medium\"\r\n for=\"columnsFilterList-{{column.columnName}}\">\r\n {{column.columnName}}\r\n </label>\r\n </div>\r\n }\r\n @if(!list.length){\r\n <p class=\"column-select-option-empty\">No items found</p>\r\n }\r\n </div>\r\n </div>\r\n }\r\n</div>\r\n\r\n\r\n", styles: [".column-select-option-empty{@apply px-3 py-2 text-gray-400 cursor-default text-sm;}\n"] }]
|
|
6804
6852
|
}], ctorParameters: () => [{ type: BkColumnFilterService }], propDecorators: { searchable: [{
|
|
6805
6853
|
type: Input
|
|
6806
6854
|
}], cacheKey: [{
|
|
@@ -6809,18 +6857,262 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
6809
6857
|
type: Input
|
|
6810
6858
|
}], isOpened: [{
|
|
6811
6859
|
type: Input
|
|
6860
|
+
}], isOpenedChange: [{
|
|
6861
|
+
type: Output
|
|
6812
6862
|
}], formBoxRef: [{
|
|
6813
6863
|
type: ViewChild,
|
|
6814
6864
|
args: ['formBox']
|
|
6815
|
-
}], change: [{
|
|
6816
|
-
type: Output
|
|
6817
|
-
}], isOpenedChange: [{
|
|
6818
|
-
type: Output
|
|
6819
6865
|
}], onClick: [{
|
|
6820
6866
|
type: HostListener,
|
|
6821
6867
|
args: ['document:click', ['$event']]
|
|
6822
6868
|
}] } });
|
|
6823
6869
|
|
|
6870
|
+
class BkFilePicker {
|
|
6871
|
+
id = '';
|
|
6872
|
+
name = '';
|
|
6873
|
+
accept = '';
|
|
6874
|
+
multi = false;
|
|
6875
|
+
// @Input() maxFileSizeKB: number | null = null;
|
|
6876
|
+
disable = false;
|
|
6877
|
+
errorMessage = '';
|
|
6878
|
+
hasError = false;
|
|
6879
|
+
draggable = true;
|
|
6880
|
+
set required(val) {
|
|
6881
|
+
this._required = val;
|
|
6882
|
+
this._onValidatorChange?.();
|
|
6883
|
+
}
|
|
6884
|
+
get required() {
|
|
6885
|
+
return this._required;
|
|
6886
|
+
}
|
|
6887
|
+
_required = false;
|
|
6888
|
+
change = new EventEmitter();
|
|
6889
|
+
error = new EventEmitter();
|
|
6890
|
+
cancel = new EventEmitter();
|
|
6891
|
+
fileInputRef;
|
|
6892
|
+
_value = null;
|
|
6893
|
+
_onValidatorChange;
|
|
6894
|
+
onChange = () => { };
|
|
6895
|
+
onTouched = () => { };
|
|
6896
|
+
writeValue(value) {
|
|
6897
|
+
this._value = value;
|
|
6898
|
+
if (!value && this.fileInputRef?.nativeElement) {
|
|
6899
|
+
this.fileInputRef.nativeElement.value = '';
|
|
6900
|
+
}
|
|
6901
|
+
}
|
|
6902
|
+
registerOnChange(fn) {
|
|
6903
|
+
this.onChange = fn;
|
|
6904
|
+
}
|
|
6905
|
+
registerOnTouched(fn) {
|
|
6906
|
+
this.onTouched = fn;
|
|
6907
|
+
}
|
|
6908
|
+
setDisabledState(isDisabled) {
|
|
6909
|
+
this.disable = isDisabled;
|
|
6910
|
+
}
|
|
6911
|
+
validate(control) {
|
|
6912
|
+
if (this.required && !this._value) {
|
|
6913
|
+
return { required: true };
|
|
6914
|
+
}
|
|
6915
|
+
return null;
|
|
6916
|
+
}
|
|
6917
|
+
registerOnValidatorChange(fn) {
|
|
6918
|
+
this._onValidatorChange = fn;
|
|
6919
|
+
}
|
|
6920
|
+
get pickerState() {
|
|
6921
|
+
if (this.disable)
|
|
6922
|
+
return 'disabled';
|
|
6923
|
+
return 'default';
|
|
6924
|
+
}
|
|
6925
|
+
onContainerClick() {
|
|
6926
|
+
if (this.disable)
|
|
6927
|
+
return;
|
|
6928
|
+
this.onTouched(); // ⭐ Touch on interaction start
|
|
6929
|
+
this.fileInputRef?.nativeElement?.click();
|
|
6930
|
+
}
|
|
6931
|
+
onFileChange(event) {
|
|
6932
|
+
// 1. Stop the native HTML change event from bubbling up to the <bk-file-picker> tag
|
|
6933
|
+
event.stopPropagation();
|
|
6934
|
+
const input = event.target;
|
|
6935
|
+
const files = input.files;
|
|
6936
|
+
// 2. Case: User clicked 'Cancel' or no files selected
|
|
6937
|
+
// We update the form state (ngModel) but DO NOT emit the @Output() change
|
|
6938
|
+
if (!files?.length) {
|
|
6939
|
+
this._value = null;
|
|
6940
|
+
this.onChange(null);
|
|
6941
|
+
this.onTouched();
|
|
6942
|
+
return; // Exit without emitting change
|
|
6943
|
+
}
|
|
6944
|
+
const fileList = Array.from(files);
|
|
6945
|
+
// // 3. Case: File exceeds size limit
|
|
6946
|
+
// if (this.maxFileSizeKB != null) {
|
|
6947
|
+
// const maxBytes = this.maxFileSizeKB * 1024;
|
|
6948
|
+
// const oversized = fileList.filter((f) => f.size > maxBytes);
|
|
6949
|
+
// if (oversized.length > 0) {
|
|
6950
|
+
// this.error.emit(`File size exceeds ${this.maxFileSizeKB} KB limit.`);
|
|
6951
|
+
// // Reset internal state and form control
|
|
6952
|
+
// this._value = null;
|
|
6953
|
+
// this.onChange(null);
|
|
6954
|
+
// this.onTouched();
|
|
6955
|
+
// // Reset the physical input so the same file can be picked again later
|
|
6956
|
+
// input.value = '';
|
|
6957
|
+
// return; // Exit without emitting change
|
|
6958
|
+
// }
|
|
6959
|
+
// }
|
|
6960
|
+
// 4. Case: Valid selection
|
|
6961
|
+
const value = this.multi ? fileList : (fileList[0] ?? null);
|
|
6962
|
+
this._value = value;
|
|
6963
|
+
this.onChange(value); // Updates ngModel
|
|
6964
|
+
this.onTouched();
|
|
6965
|
+
// Only emit the custom @Output() now
|
|
6966
|
+
this.change.emit(event);
|
|
6967
|
+
}
|
|
6968
|
+
onCancel() {
|
|
6969
|
+
// Check if there is currently no file selected
|
|
6970
|
+
if (!this._value) {
|
|
6971
|
+
// Reset internal state and notify Angular Forms that the value is null
|
|
6972
|
+
this._value = null;
|
|
6973
|
+
this.onChange(null);
|
|
6974
|
+
// Mark the control as touched to trigger 'required' error visibility
|
|
6975
|
+
this.onTouched();
|
|
6976
|
+
// Force Angular to re-run the 'validate()' function immediately
|
|
6977
|
+
this._onValidatorChange?.();
|
|
6978
|
+
// Clear the native file input value to ensure the browser reset is in sync
|
|
6979
|
+
if (this.fileInputRef?.nativeElement) {
|
|
6980
|
+
this.fileInputRef.nativeElement.value = '';
|
|
6981
|
+
}
|
|
6982
|
+
// Clear any previous error messages (e.g., size limit errors)
|
|
6983
|
+
this.cancel.emit();
|
|
6984
|
+
}
|
|
6985
|
+
}
|
|
6986
|
+
onDragOver(event) {
|
|
6987
|
+
if (this.disable)
|
|
6988
|
+
return;
|
|
6989
|
+
event.preventDefault();
|
|
6990
|
+
event.stopPropagation();
|
|
6991
|
+
}
|
|
6992
|
+
onDrop(event) {
|
|
6993
|
+
if (this.disable)
|
|
6994
|
+
return;
|
|
6995
|
+
event.preventDefault();
|
|
6996
|
+
event.stopPropagation();
|
|
6997
|
+
const input = this.fileInputRef?.nativeElement;
|
|
6998
|
+
if (!input)
|
|
6999
|
+
return;
|
|
7000
|
+
const items = event.dataTransfer?.items;
|
|
7001
|
+
if (!items?.length)
|
|
7002
|
+
return;
|
|
7003
|
+
const files = [];
|
|
7004
|
+
for (let i = 0; i < items.length; i++) {
|
|
7005
|
+
const file = items[i].getAsFile();
|
|
7006
|
+
if (file)
|
|
7007
|
+
files.push(file);
|
|
7008
|
+
}
|
|
7009
|
+
if (files.length === 0)
|
|
7010
|
+
return;
|
|
7011
|
+
const dt = new DataTransfer();
|
|
7012
|
+
(this.multi ? files : [files[0]]).forEach((f) => dt.items.add(f));
|
|
7013
|
+
input.files = dt.files;
|
|
7014
|
+
input.dispatchEvent(new Event('change', { bubbles: true }));
|
|
7015
|
+
}
|
|
7016
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: BkFilePicker, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
7017
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: BkFilePicker, isStandalone: true, selector: "bk-file-picker", inputs: { id: "id", name: "name", accept: "accept", multi: "multi", disable: "disable", errorMessage: "errorMessage", hasError: "hasError", draggable: "draggable", required: "required" }, outputs: { change: "change", error: "error", cancel: "cancel" }, providers: [
|
|
7018
|
+
{
|
|
7019
|
+
provide: NG_VALUE_ACCESSOR,
|
|
7020
|
+
useExisting: forwardRef(() => BkFilePicker),
|
|
7021
|
+
multi: true,
|
|
7022
|
+
},
|
|
7023
|
+
{
|
|
7024
|
+
provide: NG_VALIDATORS,
|
|
7025
|
+
useExisting: forwardRef(() => BkFilePicker),
|
|
7026
|
+
multi: true,
|
|
7027
|
+
},
|
|
7028
|
+
], viewQueries: [{ propertyName: "fileInputRef", first: true, predicate: ["fileInput"], descendants: true }], ngImport: i0, template: "<div class=\"file-picker-wrapper\">\n <input\n #fileInput\n type=\"file\"\n [id]=\"id\"\n [name]=\"name\"\n [accept]=\"accept\"\n [multiple]=\"multi\"\n [disabled]=\"disable\"\n [required]=\"required\"\n class=\"file-picker__input\"\n (cancel)=\"onCancel()\"\n (change)=\"onFileChange($event)\"\n />\n\n <div\n class=\"file-picker\"\n [ngClass]=\"{\n 'file-picker--default': pickerState === 'default',\n 'file-picker--active': pickerState === 'active',\n 'file-picker--disabled': pickerState === 'disabled',\n 'file-picker-has-error': hasError\n }\"\n (click)=\"onContainerClick()\"\n (dragover)=\"onDragOver($event)\"\n (drop)=\"onDrop($event)\"\n role=\"button\"\n [attr.aria-disabled]=\"disable\"\n tabindex=\"0\"\n>\n <svg\n width=\"48\"\n height=\"48\"\n viewBox=\"0 0 48 48\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"file-picker__icon\">\n <rect\n x=\"3.57007\"\n y=\"3.56995\"\n width=\"40\"\n height=\"40\"\n rx=\"20\"\n [attr.fill]=\"pickerState === 'active' ? '#C7E2FF' : pickerState === 'disabled' ? '#F4F4F6' : '#F4F4F6'\"/>\n <rect\n x=\"3.57007\"\n y=\"3.56995\"\n width=\"40\"\n height=\"40\"\n rx=\"20\"\n [attr.stroke]=\"pickerState === 'active' ? '#E5F3FF' : pickerState === 'disabled' ? '#F9FAFA' : '#F9FAFA'\"\n stroke-width=\"7.14\"/>\n <g clip-path=\"url(#clip0_1_149094)\">\n <path\n d=\"M23.5702 20.2366V23.5699M23.5702 26.9032H23.5785M31.9035 23.5699C31.9035 28.1723 28.1725 31.9032 23.5702 31.9032C18.9678 31.9032 15.2368 28.1723 15.2368 23.5699C15.2368 18.9675 18.9678 15.2366 23.5702 15.2366C28.1725 15.2366 31.9035 18.9675 31.9035 23.5699Z\"\n [attr.stroke]=\"pickerState === 'active' ? '#1434CB' : pickerState === 'disabled' ? '#868997' : '#868997'\"\n stroke-width=\"1.66667\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"/>\n </g>\n <defs>\n <clipPath id=\"clip0_1_149094\">\n <rect width=\"20\" height=\"20\" fill=\"white\" transform=\"translate(13.5701 13.5699)\"/>\n </clipPath>\n </defs>\n </svg>\n <p\n class=\"file-picker__text-primary\"\n [ngClass]=\"{\n 'file-picker__text-primary--default': pickerState === 'default',\n 'file-picker__text-primary--active': pickerState === 'active',\n 'file-picker__text-primary--disabled': pickerState === 'disabled'\n }\">\n <span\n [ngClass]=\"{\n 'file-picker__text-primary-bold--default': pickerState === 'default',\n 'file-picker__text-primary-bold--active': pickerState === 'active',\n 'file-picker__text-primary-bold--disabled': pickerState === 'disabled'\n }\">Click to upload</span> or drag and drop\n </p>\n <p\n class=\"file-picker__text-secondary\"\n [ngClass]=\"{\n 'file-picker__text-secondary--default': pickerState === 'default',\n 'file-picker__text-secondary--active': pickerState === 'active',\n 'file-picker__text-secondary--disabled': pickerState === 'disabled'\n }\">SVG, PNG, JPG or GIF (max. 800x400px)</p>\n </div>\n\n @if (hasError) {\n @if (errorMessage) {\n <p class=\"file-picker-error\">{{ errorMessage }}</p>\n }\n }\n</div>\n", styles: [".file-picker-wrapper{@apply relative w-full;}.file-picker__input{@apply absolute opacity-0 w-0 h-0 overflow-hidden pointer-events-none;}.file-picker{@apply py-4 px-6 inline-flex flex-col justify-center items-center rounded-lg cursor-pointer transition-all duration-200 w-full relative;}.file-picker-has-error{@apply border-[#d11e14];}.file-picker-error{@apply text-xs text-[#E7000B] font-normal;}.file-picker--default{@apply border border-[#E5F3FF] bg-white;}.file-picker--active{@apply border border-[#E5F3FF] bg-[#F4FAFF];}.file-picker--disabled{@apply border border-[#D6D7DC] bg-[#F4F4F6] opacity-60 cursor-not-allowed;}.file-picker__icon{@apply mb-3;}.file-picker__text-primary{@apply font-normal text-sm tracking-normal mb-1;}.file-picker__text-primary--default,.file-picker__text-primary--active{@apply text-[#1B223A];}.file-picker__text-primary--disabled{@apply text-[#A1A3AE];}.file-picker__text-primary-bold--default,.file-picker__text-primary-bold--active{@apply font-medium text-[#102BA5];}.file-picker__text-primary-bold--disabled{@apply font-medium text-[#A1A3AE];}.file-picker__text-secondary{@apply font-normal text-xs leading-[18px];}.file-picker__text-secondary--default,.file-picker__text-secondary--active{@apply text-[#6B7080];}.file-picker__text-secondary--disabled{@apply text-[#A1A3AE];}.file-picker__file-item{@apply p-4 border border-[#EFEFF1] rounded-lg bg-white flex items-start justify-between mb-1;}.file-picker__file-content{@apply flex gap-4;}.file-picker__file-info-title{@apply font-medium text-sm text-[#1B223A];}.file-picker__file-info-size{@apply text-[#1B223A] font-normal text-sm;}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
|
|
7029
|
+
}
|
|
7030
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: BkFilePicker, decorators: [{
|
|
7031
|
+
type: Component,
|
|
7032
|
+
args: [{ selector: 'bk-file-picker', imports: [CommonModule], standalone: true, providers: [
|
|
7033
|
+
{
|
|
7034
|
+
provide: NG_VALUE_ACCESSOR,
|
|
7035
|
+
useExisting: forwardRef(() => BkFilePicker),
|
|
7036
|
+
multi: true,
|
|
7037
|
+
},
|
|
7038
|
+
{
|
|
7039
|
+
provide: NG_VALIDATORS,
|
|
7040
|
+
useExisting: forwardRef(() => BkFilePicker),
|
|
7041
|
+
multi: true,
|
|
7042
|
+
},
|
|
7043
|
+
], template: "<div class=\"file-picker-wrapper\">\n <input\n #fileInput\n type=\"file\"\n [id]=\"id\"\n [name]=\"name\"\n [accept]=\"accept\"\n [multiple]=\"multi\"\n [disabled]=\"disable\"\n [required]=\"required\"\n class=\"file-picker__input\"\n (cancel)=\"onCancel()\"\n (change)=\"onFileChange($event)\"\n />\n\n <div\n class=\"file-picker\"\n [ngClass]=\"{\n 'file-picker--default': pickerState === 'default',\n 'file-picker--active': pickerState === 'active',\n 'file-picker--disabled': pickerState === 'disabled',\n 'file-picker-has-error': hasError\n }\"\n (click)=\"onContainerClick()\"\n (dragover)=\"onDragOver($event)\"\n (drop)=\"onDrop($event)\"\n role=\"button\"\n [attr.aria-disabled]=\"disable\"\n tabindex=\"0\"\n>\n <svg\n width=\"48\"\n height=\"48\"\n viewBox=\"0 0 48 48\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"file-picker__icon\">\n <rect\n x=\"3.57007\"\n y=\"3.56995\"\n width=\"40\"\n height=\"40\"\n rx=\"20\"\n [attr.fill]=\"pickerState === 'active' ? '#C7E2FF' : pickerState === 'disabled' ? '#F4F4F6' : '#F4F4F6'\"/>\n <rect\n x=\"3.57007\"\n y=\"3.56995\"\n width=\"40\"\n height=\"40\"\n rx=\"20\"\n [attr.stroke]=\"pickerState === 'active' ? '#E5F3FF' : pickerState === 'disabled' ? '#F9FAFA' : '#F9FAFA'\"\n stroke-width=\"7.14\"/>\n <g clip-path=\"url(#clip0_1_149094)\">\n <path\n d=\"M23.5702 20.2366V23.5699M23.5702 26.9032H23.5785M31.9035 23.5699C31.9035 28.1723 28.1725 31.9032 23.5702 31.9032C18.9678 31.9032 15.2368 28.1723 15.2368 23.5699C15.2368 18.9675 18.9678 15.2366 23.5702 15.2366C28.1725 15.2366 31.9035 18.9675 31.9035 23.5699Z\"\n [attr.stroke]=\"pickerState === 'active' ? '#1434CB' : pickerState === 'disabled' ? '#868997' : '#868997'\"\n stroke-width=\"1.66667\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"/>\n </g>\n <defs>\n <clipPath id=\"clip0_1_149094\">\n <rect width=\"20\" height=\"20\" fill=\"white\" transform=\"translate(13.5701 13.5699)\"/>\n </clipPath>\n </defs>\n </svg>\n <p\n class=\"file-picker__text-primary\"\n [ngClass]=\"{\n 'file-picker__text-primary--default': pickerState === 'default',\n 'file-picker__text-primary--active': pickerState === 'active',\n 'file-picker__text-primary--disabled': pickerState === 'disabled'\n }\">\n <span\n [ngClass]=\"{\n 'file-picker__text-primary-bold--default': pickerState === 'default',\n 'file-picker__text-primary-bold--active': pickerState === 'active',\n 'file-picker__text-primary-bold--disabled': pickerState === 'disabled'\n }\">Click to upload</span> or drag and drop\n </p>\n <p\n class=\"file-picker__text-secondary\"\n [ngClass]=\"{\n 'file-picker__text-secondary--default': pickerState === 'default',\n 'file-picker__text-secondary--active': pickerState === 'active',\n 'file-picker__text-secondary--disabled': pickerState === 'disabled'\n }\">SVG, PNG, JPG or GIF (max. 800x400px)</p>\n </div>\n\n @if (hasError) {\n @if (errorMessage) {\n <p class=\"file-picker-error\">{{ errorMessage }}</p>\n }\n }\n</div>\n", styles: [".file-picker-wrapper{@apply relative w-full;}.file-picker__input{@apply absolute opacity-0 w-0 h-0 overflow-hidden pointer-events-none;}.file-picker{@apply py-4 px-6 inline-flex flex-col justify-center items-center rounded-lg cursor-pointer transition-all duration-200 w-full relative;}.file-picker-has-error{@apply border-[#d11e14];}.file-picker-error{@apply text-xs text-[#E7000B] font-normal;}.file-picker--default{@apply border border-[#E5F3FF] bg-white;}.file-picker--active{@apply border border-[#E5F3FF] bg-[#F4FAFF];}.file-picker--disabled{@apply border border-[#D6D7DC] bg-[#F4F4F6] opacity-60 cursor-not-allowed;}.file-picker__icon{@apply mb-3;}.file-picker__text-primary{@apply font-normal text-sm tracking-normal mb-1;}.file-picker__text-primary--default,.file-picker__text-primary--active{@apply text-[#1B223A];}.file-picker__text-primary--disabled{@apply text-[#A1A3AE];}.file-picker__text-primary-bold--default,.file-picker__text-primary-bold--active{@apply font-medium text-[#102BA5];}.file-picker__text-primary-bold--disabled{@apply font-medium text-[#A1A3AE];}.file-picker__text-secondary{@apply font-normal text-xs leading-[18px];}.file-picker__text-secondary--default,.file-picker__text-secondary--active{@apply text-[#6B7080];}.file-picker__text-secondary--disabled{@apply text-[#A1A3AE];}.file-picker__file-item{@apply p-4 border border-[#EFEFF1] rounded-lg bg-white flex items-start justify-between mb-1;}.file-picker__file-content{@apply flex gap-4;}.file-picker__file-info-title{@apply font-medium text-sm text-[#1B223A];}.file-picker__file-info-size{@apply text-[#1B223A] font-normal text-sm;}\n"] }]
|
|
7044
|
+
}], propDecorators: { id: [{
|
|
7045
|
+
type: Input
|
|
7046
|
+
}], name: [{
|
|
7047
|
+
type: Input
|
|
7048
|
+
}], accept: [{
|
|
7049
|
+
type: Input
|
|
7050
|
+
}], multi: [{
|
|
7051
|
+
type: Input
|
|
7052
|
+
}], disable: [{
|
|
7053
|
+
type: Input
|
|
7054
|
+
}], errorMessage: [{
|
|
7055
|
+
type: Input
|
|
7056
|
+
}], hasError: [{
|
|
7057
|
+
type: Input
|
|
7058
|
+
}], draggable: [{
|
|
7059
|
+
type: Input
|
|
7060
|
+
}], required: [{
|
|
7061
|
+
type: Input
|
|
7062
|
+
}], change: [{
|
|
7063
|
+
type: Output
|
|
7064
|
+
}], error: [{
|
|
7065
|
+
type: Output
|
|
7066
|
+
}], cancel: [{
|
|
7067
|
+
type: Output
|
|
7068
|
+
}], fileInputRef: [{
|
|
7069
|
+
type: ViewChild,
|
|
7070
|
+
args: ['fileInput']
|
|
7071
|
+
}] } });
|
|
7072
|
+
|
|
7073
|
+
class BkFileCard {
|
|
7074
|
+
id = '';
|
|
7075
|
+
state = 'uploading';
|
|
7076
|
+
fileName = 'Tech design requirements.pdf';
|
|
7077
|
+
fileSize = '200 KB';
|
|
7078
|
+
progress = 65; // Progress percentage (0-100)
|
|
7079
|
+
errorMessage = 'Upload failed, please try again';
|
|
7080
|
+
remove = new EventEmitter();
|
|
7081
|
+
/**
|
|
7082
|
+
*
|
|
7083
|
+
*/
|
|
7084
|
+
constructor() {
|
|
7085
|
+
}
|
|
7086
|
+
ngOnInit() {
|
|
7087
|
+
if (!this.id) {
|
|
7088
|
+
this.id = crypto.randomUUID();
|
|
7089
|
+
}
|
|
7090
|
+
}
|
|
7091
|
+
onRemove() {
|
|
7092
|
+
this.remove.emit(this.id);
|
|
7093
|
+
}
|
|
7094
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: BkFileCard, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
7095
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: BkFileCard, isStandalone: true, selector: "bk-file-card", inputs: { id: "id", state: "state", fileName: "fileName", fileSize: "fileSize", progress: "progress", errorMessage: "errorMessage" }, outputs: { remove: "remove" }, ngImport: i0, template: "\r\n <div\r\n class=\"file-uploader\"\r\n [ngClass]=\"{\r\n 'file-uploader--uploading': state === 'uploading',\r\n 'file-uploader--uploaded': state === 'uploaded',\r\n 'file-uploader--failed': state === 'failed'\r\n }\">\r\n <!-- Icon Section -->\r\n <div class=\"file-uploader__icon-container\">\r\n <svg\r\n width=\"48\"\r\n height=\"48\"\r\n viewBox=\"0 0 48 48\"\r\n fill=\"none\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n class=\"file-uploader__icon\">\r\n <rect\r\n x=\"3.57007\"\r\n y=\"3.56995\"\r\n width=\"40\"\r\n height=\"40\"\r\n rx=\"20\"\r\n [attr.fill]=\"state === 'uploading' ? '#C7E2FF' : state === 'uploaded' ? '#C7E2FF' : '#FECACA'\"/>\r\n <rect\r\n x=\"3.57007\"\r\n y=\"3.56995\"\r\n width=\"40\"\r\n height=\"40\"\r\n rx=\"20\"\r\n [attr.stroke]=\"state === 'uploading' ? '#E5F3FF' : state === 'uploaded' ? '#E5F3FF' : '#FEE2E2'\"\r\n stroke-width=\"7.14\"/>\r\n <g clip-path=\"url(#clip0_1_149094)\">\r\n <path\r\n d=\"M23.5702 20.2366V23.5699M23.5702 26.9032H23.5785M31.9035 23.5699C31.9035 28.1723 28.1725 31.9032 23.5702 31.9032C18.9678 31.9032 15.2368 28.1723 15.2368 23.5699C15.2368 18.9675 18.9678 15.2366 23.5702 15.2366C28.1725 15.2366 31.9035 18.9675 31.9035 23.5699Z\"\r\n [attr.stroke]=\"state === 'uploading' ? '#1434CB' : state === 'uploaded' ? '#1434CB' : '#EF4444'\"\r\n stroke-width=\"1.66667\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"/>\r\n </g>\r\n <defs>\r\n <clipPath id=\"clip0_1_149094\">\r\n <rect width=\"20\" height=\"20\" fill=\"white\" transform=\"translate(13.5701 13.5699)\"/>\r\n </clipPath>\r\n </defs>\r\n </svg>\r\n </div>\r\n\r\n <!-- Content Section -->\r\n <div class=\"file-uploader__content\">\r\n <!-- Row 1: File Info + Delete -->\r\n <div class=\"file-uploader__row-1\">\r\n <div class=\"file-uploader__file-info\">\r\n <!-- Uploading State -->\r\n\r\n @if (state === 'uploading' || state === 'uploaded') {\r\n <ng-container>\r\n <span class=\"file-uploader__file-name\">{{ fileName }}</span>\r\n <span class=\"file-uploader__file-size\">{{ fileSize }}</span>\r\n </ng-container>\r\n }\r\n\r\n @if(state === 'failed'){\r\n <!-- Failed State -->\r\n <ng-container>\r\n <p class=\"file-uploader__error-message\">{{ errorMessage }}</p>\r\n <span class=\"file-uploader__file-name file-uploader__file-name--failed\">{{ fileName }}</span>\r\n <p class=\"file-uploader__error-message\">Try again</p>\r\n </ng-container>\r\n }\r\n </div>\r\n ../../../../assets/images/icons/global/bin-gray.svg\r\n <img\r\n src=\"../../assets/icons/bin-gray.svg\"\r\n alt=\"Delete\"\r\n bkTooltip=\"Delete\"\r\n bkTooltipPosition=\"left\"\r\n class=\"file-uploader__delete-icon\"\r\n (click)=\"onRemove()\"\r\n >\r\n </div>\r\n\r\n <!-- Row 2: Progress Bar + Percentage -->\r\n <div class=\"file-uploader__row-2\">\r\n @if (state === 'uploading') {\r\n <!-- Uploading State -->\r\n <ng-container>\r\n <div class=\"file-uploader__progress-bar\">\r\n <div\r\n class=\"file-uploader__progress-fill\"\r\n [style.width.%]=\"progress\"></div>\r\n </div>\r\n <span class=\"file-uploader__progress-text\">{{ progress }}%</span>\r\n </ng-container>\r\n }\r\n @if(state === 'uploaded'){\r\n <!-- Uploaded State -->\r\n <ng-container>\r\n <div class=\"file-uploader__progress-bar\">\r\n <div class=\"file-uploader__progress-fill file-uploader__progress-fill--complete\"></div>\r\n </div>\r\n <img src=\"../../assets/icons/check-green.svg\" alt=\"\" class=\"file-uploader__checkmark\">\r\n </ng-container>\r\n }\r\n\r\n </div>\r\n </div>\r\n </div>\r\n\r\n\r\n", styles: [".file-uploader{@apply p-4 flex gap-4 border rounded-lg border-transparent bg-[white];}.file-uploader--uploading{@apply border-[#EFEFF1];}.file-uploader--uploaded{@apply border-[#1434CB];}.file-uploader--failed{@apply border-[#FDA4A8] bg-[#FFF1F1];}.file-uploader__icon-container,.file-uploader__icon{@apply flex-shrink-0;}.file-uploader__content{@apply flex flex-col flex-1 gap-0;}.file-uploader__row-1{@apply flex items-start justify-between;}.file-uploader__file-info{@apply flex flex-col;}.file-uploader__file-name{@apply font-medium text-sm text-[#1B223A];}.file-uploader__file-name--failed{@apply text-[#B41E32] font-normal mb-1;}.file-uploader__file-size{@apply text-[#1B223A] font-normal text-sm;}.file-uploader__row-2{@apply flex justify-between items-center gap-3 mt-1;}.file-uploader--failed .file-uploader__row-2{@apply mt-0;}.file-uploader__progress-bar{@apply flex-1 h-2 bg-[#EFEFF1] rounded-full overflow-hidden;}.file-uploader__progress-fill{@apply h-full bg-[#1336EF] transition-all duration-300 rounded-full;}.file-uploader__progress-fill--complete{@apply bg-[#22973F];}.file-uploader__progress-text{@apply text-sm text-[#6B7080] font-medium;}.file-uploader__checkmark{@apply flex-shrink-0 size-[14px];}.file-uploader__error-message{@apply text-[#B41E32] font-medium text-sm;}.file-uploader__delete-icon{@apply flex-shrink-0 cursor-pointer size-5;}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: BKTooltipDirective, selector: "[bkTooltip]", inputs: ["bkTooltip", "bkTooltipPosition"] }] });
|
|
7096
|
+
}
|
|
7097
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: BkFileCard, decorators: [{
|
|
7098
|
+
type: Component,
|
|
7099
|
+
args: [{ imports: [CommonModule, BKTooltipDirective], selector: 'bk-file-card', standalone: true, template: "\r\n <div\r\n class=\"file-uploader\"\r\n [ngClass]=\"{\r\n 'file-uploader--uploading': state === 'uploading',\r\n 'file-uploader--uploaded': state === 'uploaded',\r\n 'file-uploader--failed': state === 'failed'\r\n }\">\r\n <!-- Icon Section -->\r\n <div class=\"file-uploader__icon-container\">\r\n <svg\r\n width=\"48\"\r\n height=\"48\"\r\n viewBox=\"0 0 48 48\"\r\n fill=\"none\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n class=\"file-uploader__icon\">\r\n <rect\r\n x=\"3.57007\"\r\n y=\"3.56995\"\r\n width=\"40\"\r\n height=\"40\"\r\n rx=\"20\"\r\n [attr.fill]=\"state === 'uploading' ? '#C7E2FF' : state === 'uploaded' ? '#C7E2FF' : '#FECACA'\"/>\r\n <rect\r\n x=\"3.57007\"\r\n y=\"3.56995\"\r\n width=\"40\"\r\n height=\"40\"\r\n rx=\"20\"\r\n [attr.stroke]=\"state === 'uploading' ? '#E5F3FF' : state === 'uploaded' ? '#E5F3FF' : '#FEE2E2'\"\r\n stroke-width=\"7.14\"/>\r\n <g clip-path=\"url(#clip0_1_149094)\">\r\n <path\r\n d=\"M23.5702 20.2366V23.5699M23.5702 26.9032H23.5785M31.9035 23.5699C31.9035 28.1723 28.1725 31.9032 23.5702 31.9032C18.9678 31.9032 15.2368 28.1723 15.2368 23.5699C15.2368 18.9675 18.9678 15.2366 23.5702 15.2366C28.1725 15.2366 31.9035 18.9675 31.9035 23.5699Z\"\r\n [attr.stroke]=\"state === 'uploading' ? '#1434CB' : state === 'uploaded' ? '#1434CB' : '#EF4444'\"\r\n stroke-width=\"1.66667\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"/>\r\n </g>\r\n <defs>\r\n <clipPath id=\"clip0_1_149094\">\r\n <rect width=\"20\" height=\"20\" fill=\"white\" transform=\"translate(13.5701 13.5699)\"/>\r\n </clipPath>\r\n </defs>\r\n </svg>\r\n </div>\r\n\r\n <!-- Content Section -->\r\n <div class=\"file-uploader__content\">\r\n <!-- Row 1: File Info + Delete -->\r\n <div class=\"file-uploader__row-1\">\r\n <div class=\"file-uploader__file-info\">\r\n <!-- Uploading State -->\r\n\r\n @if (state === 'uploading' || state === 'uploaded') {\r\n <ng-container>\r\n <span class=\"file-uploader__file-name\">{{ fileName }}</span>\r\n <span class=\"file-uploader__file-size\">{{ fileSize }}</span>\r\n </ng-container>\r\n }\r\n\r\n @if(state === 'failed'){\r\n <!-- Failed State -->\r\n <ng-container>\r\n <p class=\"file-uploader__error-message\">{{ errorMessage }}</p>\r\n <span class=\"file-uploader__file-name file-uploader__file-name--failed\">{{ fileName }}</span>\r\n <p class=\"file-uploader__error-message\">Try again</p>\r\n </ng-container>\r\n }\r\n </div>\r\n ../../../../assets/images/icons/global/bin-gray.svg\r\n <img\r\n src=\"../../assets/icons/bin-gray.svg\"\r\n alt=\"Delete\"\r\n bkTooltip=\"Delete\"\r\n bkTooltipPosition=\"left\"\r\n class=\"file-uploader__delete-icon\"\r\n (click)=\"onRemove()\"\r\n >\r\n </div>\r\n\r\n <!-- Row 2: Progress Bar + Percentage -->\r\n <div class=\"file-uploader__row-2\">\r\n @if (state === 'uploading') {\r\n <!-- Uploading State -->\r\n <ng-container>\r\n <div class=\"file-uploader__progress-bar\">\r\n <div\r\n class=\"file-uploader__progress-fill\"\r\n [style.width.%]=\"progress\"></div>\r\n </div>\r\n <span class=\"file-uploader__progress-text\">{{ progress }}%</span>\r\n </ng-container>\r\n }\r\n @if(state === 'uploaded'){\r\n <!-- Uploaded State -->\r\n <ng-container>\r\n <div class=\"file-uploader__progress-bar\">\r\n <div class=\"file-uploader__progress-fill file-uploader__progress-fill--complete\"></div>\r\n </div>\r\n <img src=\"../../assets/icons/check-green.svg\" alt=\"\" class=\"file-uploader__checkmark\">\r\n </ng-container>\r\n }\r\n\r\n </div>\r\n </div>\r\n </div>\r\n\r\n\r\n", styles: [".file-uploader{@apply p-4 flex gap-4 border rounded-lg border-transparent bg-[white];}.file-uploader--uploading{@apply border-[#EFEFF1];}.file-uploader--uploaded{@apply border-[#1434CB];}.file-uploader--failed{@apply border-[#FDA4A8] bg-[#FFF1F1];}.file-uploader__icon-container,.file-uploader__icon{@apply flex-shrink-0;}.file-uploader__content{@apply flex flex-col flex-1 gap-0;}.file-uploader__row-1{@apply flex items-start justify-between;}.file-uploader__file-info{@apply flex flex-col;}.file-uploader__file-name{@apply font-medium text-sm text-[#1B223A];}.file-uploader__file-name--failed{@apply text-[#B41E32] font-normal mb-1;}.file-uploader__file-size{@apply text-[#1B223A] font-normal text-sm;}.file-uploader__row-2{@apply flex justify-between items-center gap-3 mt-1;}.file-uploader--failed .file-uploader__row-2{@apply mt-0;}.file-uploader__progress-bar{@apply flex-1 h-2 bg-[#EFEFF1] rounded-full overflow-hidden;}.file-uploader__progress-fill{@apply h-full bg-[#1336EF] transition-all duration-300 rounded-full;}.file-uploader__progress-fill--complete{@apply bg-[#22973F];}.file-uploader__progress-text{@apply text-sm text-[#6B7080] font-medium;}.file-uploader__checkmark{@apply flex-shrink-0 size-[14px];}.file-uploader__error-message{@apply text-[#B41E32] font-medium text-sm;}.file-uploader__delete-icon{@apply flex-shrink-0 cursor-pointer size-5;}\n"] }]
|
|
7100
|
+
}], ctorParameters: () => [], propDecorators: { id: [{
|
|
7101
|
+
type: Input
|
|
7102
|
+
}], state: [{
|
|
7103
|
+
type: Input
|
|
7104
|
+
}], fileName: [{
|
|
7105
|
+
type: Input
|
|
7106
|
+
}], fileSize: [{
|
|
7107
|
+
type: Input
|
|
7108
|
+
}], progress: [{
|
|
7109
|
+
type: Input
|
|
7110
|
+
}], errorMessage: [{
|
|
7111
|
+
type: Input
|
|
7112
|
+
}], remove: [{
|
|
7113
|
+
type: Output
|
|
7114
|
+
}] } });
|
|
7115
|
+
|
|
6824
7116
|
/*
|
|
6825
7117
|
* Public API Surface of brickclay-lib
|
|
6826
7118
|
*/
|
|
@@ -6830,5 +7122,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
6830
7122
|
* Generated bundle index. Do not edit.
|
|
6831
7123
|
*/
|
|
6832
7124
|
|
|
6833
|
-
export { BKTooltipDirective, BK_DEFAULT_DIALOG_CONFIG, BK_DIALOG_DATA, BK_DIALOG_GLOBAL_CONFIG, BkAvatar, BkAvatarUploader, BkBadge, BkButton, BkButtonGroup, BkCheckbox, BkColumnFilterService, BkColumnSelect, BkCustomCalendar, BkDialogActions, BkDialogClose, BkDialogContent, BkDialogModule, BkDialogRef, BkDialogService, BkDialogTitle, BkGrid, BkHierarchicalSelect, BkIconButton, BkInput, BkInputChips, BkPill, BkRadioButton, BkScheduledDatePicker, BkSelect, BkSpinner, BkTabs, BkTextarea, BkTimePicker, BkToastr, BkToastrService, BkToggle, BkValidator, BrickclayIcons, BrickclayLib, CalendarManagerService, CalendarModule, CalendarSelection, ColumnFilterOption, getDialogBackdropAnimation, getDialogPanelAnimation };
|
|
7125
|
+
export { BKTooltipDirective, BK_DEFAULT_DIALOG_CONFIG, BK_DIALOG_DATA, BK_DIALOG_GLOBAL_CONFIG, BkAvatar, BkAvatarUploader, BkBadge, BkButton, BkButtonGroup, BkCheckbox, BkColumnFilterService, BkColumnSelect, BkCustomCalendar, BkDialogActions, BkDialogClose, BkDialogContent, BkDialogModule, BkDialogRef, BkDialogService, BkDialogTitle, BkFileCard, BkFilePicker, BkGrid, BkHierarchicalSelect, BkIconButton, BkInput, BkInputChips, BkPill, BkRadioButton, BkScheduledDatePicker, BkSelect, BkSpinner, BkTabs, BkTextarea, BkTimePicker, BkToastr, BkToastrService, BkToggle, BkValidator, BrickclayIcons, BrickclayLib, CalendarManagerService, CalendarModule, CalendarSelection, ColumnFilterOption, getDialogBackdropAnimation, getDialogPanelAnimation };
|
|
6834
7126
|
//# sourceMappingURL=brickclay-org-ui.mjs.map
|