@sdcorejs/angular 21.0.9 → 21.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. package/README.md +270 -140
  2. package/assets/scss/core/utilities/_grid.scss +25 -19
  3. package/fesm2022/sdcorejs-angular-components-anchor.mjs +15 -18
  4. package/fesm2022/sdcorejs-angular-components-anchor.mjs.map +1 -1
  5. package/fesm2022/sdcorejs-angular-components-autoid-inspector.mjs.map +1 -1
  6. package/fesm2022/sdcorejs-angular-components-avatar.mjs.map +1 -1
  7. package/fesm2022/sdcorejs-angular-components-badge.mjs +0 -1
  8. package/fesm2022/sdcorejs-angular-components-badge.mjs.map +1 -1
  9. package/fesm2022/sdcorejs-angular-components-button.mjs +6 -7
  10. package/fesm2022/sdcorejs-angular-components-button.mjs.map +1 -1
  11. package/fesm2022/sdcorejs-angular-components-chart.mjs.map +1 -1
  12. package/fesm2022/sdcorejs-angular-components-ckeditor-styles.mjs.map +1 -1
  13. package/fesm2022/sdcorejs-angular-components-code-editor.mjs +1 -1
  14. package/fesm2022/sdcorejs-angular-components-code-editor.mjs.map +1 -1
  15. package/fesm2022/sdcorejs-angular-components-document-builder.mjs +17 -26
  16. package/fesm2022/sdcorejs-angular-components-document-builder.mjs.map +1 -1
  17. package/fesm2022/sdcorejs-angular-components-editor.mjs +7 -2
  18. package/fesm2022/sdcorejs-angular-components-editor.mjs.map +1 -1
  19. package/fesm2022/sdcorejs-angular-components-form-generic.mjs +712 -427
  20. package/fesm2022/sdcorejs-angular-components-form-generic.mjs.map +1 -1
  21. package/fesm2022/sdcorejs-angular-components-import-excel.mjs +35 -18
  22. package/fesm2022/sdcorejs-angular-components-import-excel.mjs.map +1 -1
  23. package/fesm2022/sdcorejs-angular-components-inform.mjs +0 -1
  24. package/fesm2022/sdcorejs-angular-components-inform.mjs.map +1 -1
  25. package/fesm2022/sdcorejs-angular-components-mini-editor.mjs.map +1 -1
  26. package/fesm2022/sdcorejs-angular-components-modal-resizable.mjs.map +1 -1
  27. package/fesm2022/sdcorejs-angular-components-modal.mjs +21 -14
  28. package/fesm2022/sdcorejs-angular-components-modal.mjs.map +1 -1
  29. package/fesm2022/sdcorejs-angular-components-operator.mjs +1 -1
  30. package/fesm2022/sdcorejs-angular-components-operator.mjs.map +1 -1
  31. package/fesm2022/sdcorejs-angular-components-org-chart.mjs.map +1 -1
  32. package/fesm2022/sdcorejs-angular-components-preview.mjs +33 -29
  33. package/fesm2022/sdcorejs-angular-components-preview.mjs.map +1 -1
  34. package/fesm2022/sdcorejs-angular-components-query-bar.mjs +15 -28
  35. package/fesm2022/sdcorejs-angular-components-query-bar.mjs.map +1 -1
  36. package/fesm2022/sdcorejs-angular-components-query-builder.mjs +2 -3
  37. package/fesm2022/sdcorejs-angular-components-query-builder.mjs.map +1 -1
  38. package/fesm2022/sdcorejs-angular-components-quick-action.mjs.map +1 -1
  39. package/fesm2022/sdcorejs-angular-components-section.mjs +0 -1
  40. package/fesm2022/sdcorejs-angular-components-section.mjs.map +1 -1
  41. package/fesm2022/sdcorejs-angular-components-side-drawer.mjs +3 -3
  42. package/fesm2022/sdcorejs-angular-components-side-drawer.mjs.map +1 -1
  43. package/fesm2022/sdcorejs-angular-components-splitter.mjs +4 -4
  44. package/fesm2022/sdcorejs-angular-components-splitter.mjs.map +1 -1
  45. package/fesm2022/sdcorejs-angular-components-stepper.mjs.map +1 -1
  46. package/fesm2022/sdcorejs-angular-components-tab-router.mjs +31 -31
  47. package/fesm2022/sdcorejs-angular-components-tab-router.mjs.map +1 -1
  48. package/fesm2022/sdcorejs-angular-components-tab.mjs.map +1 -1
  49. package/fesm2022/sdcorejs-angular-components-table.mjs +66 -84
  50. package/fesm2022/sdcorejs-angular-components-table.mjs.map +1 -1
  51. package/fesm2022/sdcorejs-angular-components-tree.mjs.map +1 -1
  52. package/fesm2022/sdcorejs-angular-components-upload-file.mjs +6 -6
  53. package/fesm2022/sdcorejs-angular-components-upload-file.mjs.map +1 -1
  54. package/fesm2022/sdcorejs-angular-components-view.mjs +3 -9
  55. package/fesm2022/sdcorejs-angular-components-view.mjs.map +1 -1
  56. package/fesm2022/sdcorejs-angular-configurations.mjs.map +1 -1
  57. package/fesm2022/sdcorejs-angular-directives.mjs +2 -7
  58. package/fesm2022/sdcorejs-angular-directives.mjs.map +1 -1
  59. package/fesm2022/sdcorejs-angular-forms-autocomplete.mjs +0 -3
  60. package/fesm2022/sdcorejs-angular-forms-autocomplete.mjs.map +1 -1
  61. package/fesm2022/sdcorejs-angular-forms-checkbox.mjs.map +1 -1
  62. package/fesm2022/sdcorejs-angular-forms-chip-calendar.mjs +2 -2
  63. package/fesm2022/sdcorejs-angular-forms-chip-calendar.mjs.map +1 -1
  64. package/fesm2022/sdcorejs-angular-forms-chip.mjs +2 -2
  65. package/fesm2022/sdcorejs-angular-forms-chip.mjs.map +1 -1
  66. package/fesm2022/sdcorejs-angular-forms-date-range.mjs +1 -3
  67. package/fesm2022/sdcorejs-angular-forms-date-range.mjs.map +1 -1
  68. package/fesm2022/sdcorejs-angular-forms-date.mjs +2 -4
  69. package/fesm2022/sdcorejs-angular-forms-date.mjs.map +1 -1
  70. package/fesm2022/sdcorejs-angular-forms-datetime.mjs +2 -6
  71. package/fesm2022/sdcorejs-angular-forms-datetime.mjs.map +1 -1
  72. package/fesm2022/sdcorejs-angular-forms-input-color.mjs +4 -4
  73. package/fesm2022/sdcorejs-angular-forms-input-color.mjs.map +1 -1
  74. package/fesm2022/sdcorejs-angular-forms-input-number.mjs +1 -1
  75. package/fesm2022/sdcorejs-angular-forms-input-number.mjs.map +1 -1
  76. package/fesm2022/sdcorejs-angular-forms-input.mjs.map +1 -1
  77. package/fesm2022/sdcorejs-angular-forms-label.mjs +0 -1
  78. package/fesm2022/sdcorejs-angular-forms-label.mjs.map +1 -1
  79. package/fesm2022/sdcorejs-angular-forms-models.mjs.map +1 -1
  80. package/fesm2022/sdcorejs-angular-forms-radio.mjs +12 -2
  81. package/fesm2022/sdcorejs-angular-forms-radio.mjs.map +1 -1
  82. package/fesm2022/sdcorejs-angular-forms-select.mjs +45 -14
  83. package/fesm2022/sdcorejs-angular-forms-select.mjs.map +1 -1
  84. package/fesm2022/sdcorejs-angular-forms-switch.mjs.map +1 -1
  85. package/fesm2022/sdcorejs-angular-forms-textarea.mjs +2 -2
  86. package/fesm2022/sdcorejs-angular-forms-textarea.mjs.map +1 -1
  87. package/fesm2022/sdcorejs-angular-handlers.mjs +3 -6
  88. package/fesm2022/sdcorejs-angular-handlers.mjs.map +1 -1
  89. package/fesm2022/sdcorejs-angular-i18n.mjs +11 -7
  90. package/fesm2022/sdcorejs-angular-i18n.mjs.map +1 -1
  91. package/fesm2022/sdcorejs-angular-interceptors.mjs +0 -2
  92. package/fesm2022/sdcorejs-angular-interceptors.mjs.map +1 -1
  93. package/fesm2022/sdcorejs-angular-modules-auth.mjs +14 -38
  94. package/fesm2022/sdcorejs-angular-modules-auth.mjs.map +1 -1
  95. package/fesm2022/sdcorejs-angular-modules-authom.mjs +14 -14
  96. package/fesm2022/sdcorejs-angular-modules-authom.mjs.map +1 -1
  97. package/fesm2022/sdcorejs-angular-modules-keycloak.mjs +22 -11
  98. package/fesm2022/sdcorejs-angular-modules-keycloak.mjs.map +1 -1
  99. package/fesm2022/sdcorejs-angular-modules-layout.mjs +30 -27
  100. package/fesm2022/sdcorejs-angular-modules-layout.mjs.map +1 -1
  101. package/fesm2022/sdcorejs-angular-modules-permission.mjs +5 -12
  102. package/fesm2022/sdcorejs-angular-modules-permission.mjs.map +1 -1
  103. package/fesm2022/sdcorejs-angular-pipes.mjs +71 -17
  104. package/fesm2022/sdcorejs-angular-pipes.mjs.map +1 -1
  105. package/fesm2022/sdcorejs-angular-services-api.mjs +0 -2
  106. package/fesm2022/sdcorejs-angular-services-api.mjs.map +1 -1
  107. package/fesm2022/sdcorejs-angular-services-cache.mjs +5 -11
  108. package/fesm2022/sdcorejs-angular-services-cache.mjs.map +1 -1
  109. package/fesm2022/sdcorejs-angular-services-confirm.mjs +16 -21
  110. package/fesm2022/sdcorejs-angular-services-confirm.mjs.map +1 -1
  111. package/fesm2022/sdcorejs-angular-services-docx.mjs +2 -8
  112. package/fesm2022/sdcorejs-angular-services-docx.mjs.map +1 -1
  113. package/fesm2022/sdcorejs-angular-services-excel.mjs +2 -2
  114. package/fesm2022/sdcorejs-angular-services-excel.mjs.map +1 -1
  115. package/fesm2022/sdcorejs-angular-services-license.mjs +5 -12
  116. package/fesm2022/sdcorejs-angular-services-license.mjs.map +1 -1
  117. package/fesm2022/sdcorejs-angular-services-notify.mjs +70 -87
  118. package/fesm2022/sdcorejs-angular-services-notify.mjs.map +1 -1
  119. package/fesm2022/sdcorejs-angular-services-storage.mjs +6 -15
  120. package/fesm2022/sdcorejs-angular-services-storage.mjs.map +1 -1
  121. package/fesm2022/sdcorejs-angular-utilities-data-state.mjs.map +1 -1
  122. package/fesm2022/sdcorejs-angular-utilities-extensions.mjs +47 -5
  123. package/fesm2022/sdcorejs-angular-utilities-extensions.mjs.map +1 -1
  124. package/fesm2022/sdcorejs-angular-utilities-models.mjs +18 -3
  125. package/fesm2022/sdcorejs-angular-utilities-models.mjs.map +1 -1
  126. package/fesm2022/sdcorejs-angular.mjs.map +1 -1
  127. package/package.json +2 -2
  128. package/types/sdcorejs-angular-components-document-builder.d.ts +2 -2
  129. package/types/sdcorejs-angular-components-form-generic.d.ts +45 -23
  130. package/types/sdcorejs-angular-components-import-excel.d.ts +2 -2
  131. package/types/sdcorejs-angular-components-mini-editor.d.ts +4 -4
  132. package/types/sdcorejs-angular-components-modal.d.ts +1 -1
  133. package/types/sdcorejs-angular-components-query-builder.d.ts +4 -4
  134. package/types/sdcorejs-angular-components-tab-router.d.ts +3 -3
  135. package/types/sdcorejs-angular-components-table.d.ts +3 -2
  136. package/types/sdcorejs-angular-components-view.d.ts +1 -1
  137. package/types/sdcorejs-angular-forms-chip-calendar.d.ts +2 -2
  138. package/types/sdcorejs-angular-forms-chip.d.ts +2 -2
  139. package/types/sdcorejs-angular-forms-input-color.d.ts +2 -1
  140. package/types/sdcorejs-angular-forms-select.d.ts +10 -2
  141. package/types/sdcorejs-angular-modules-auth.d.ts +7 -9
  142. package/types/sdcorejs-angular-modules-permission.d.ts +5 -6
  143. package/types/sdcorejs-angular-pipes.d.ts +22 -4
  144. package/types/sdcorejs-angular-services-confirm.d.ts +3 -3
  145. package/types/sdcorejs-angular-services-license.d.ts +2 -3
  146. package/types/sdcorejs-angular-services-notify.d.ts +4 -5
  147. package/types/sdcorejs-angular-services-storage.d.ts +2 -3
  148. package/types/sdcorejs-angular-utilities-extensions.d.ts +9 -1
@@ -1,7 +1,6 @@
1
1
  import { ValidationUtilities, StringUtilities as StringUtilities$1, ColorUtilities } from '@sdcorejs/utils/fns';
2
2
  export { ArrayUtilities, BrowserUtilities, ColorUtilities, DateUtilities, NumberUtilities, Utilities, ValidationUtilities } from '@sdcorejs/utils/fns';
3
3
 
4
- /* eslint-disable @typescript-eslint/no-explicit-any */
5
4
  // Deprecated wrappers — moved to ValidationUtilities
6
5
  const isValidEmail = (value) => ValidationUtilities.isEmail(value);
7
6
  const isValidPhone = (value) => ValidationUtilities.isPhone(value);
@@ -55,7 +54,9 @@ const getSdUploadLang = () => {
55
54
  if (stored && stored in SD_UPLOAD_MESSAGES)
56
55
  return stored;
57
56
  }
58
- catch { /* ignore */ }
57
+ catch {
58
+ /* ignore */
59
+ }
59
60
  return 'vi';
60
61
  };
61
62
  const upload = (option) => {
@@ -78,7 +79,6 @@ const upload = (option) => {
78
79
  }
79
80
  element.style.display = 'none';
80
81
  body.appendChild(element);
81
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
82
82
  element.addEventListener('change', (evt) => {
83
83
  try {
84
84
  const target = evt.target;
@@ -375,7 +375,7 @@ const SdUtilities = {
375
375
  parseQueryParams,
376
376
  getClientPublicIp,
377
377
  generateUuid,
378
- getNestedValue
378
+ getNestedValue,
379
379
  };
380
380
 
381
381
  /** @deprecated Use {@link ColorUtilities.hslToHex} from `@sdcorejs/utils/fns` instead */
@@ -383,9 +383,51 @@ const hslToHex = ColorUtilities.hslToHex;
383
383
  /** @deprecated Use {@link ColorUtilities.rgbToHex} from `@sdcorejs/utils/fns` instead */
384
384
  const rgbToHex = ColorUtilities.rgbToHex;
385
385
 
386
+ const isPlainObject = (value) => {
387
+ if (value === null || typeof value !== 'object')
388
+ return false;
389
+ const prototype = Object.getPrototypeOf(value);
390
+ return prototype === Object.prototype || prototype === null;
391
+ };
392
+ const clone = (value) => {
393
+ if (Array.isArray(value)) {
394
+ return value.map(item => clone(item));
395
+ }
396
+ if (isPlainObject(value)) {
397
+ return Object.keys(value).reduce((result, key) => {
398
+ result[key] = clone(value[key]);
399
+ return result;
400
+ }, {});
401
+ }
402
+ return value;
403
+ };
404
+ const merge = (target, source) => {
405
+ const result = clone(target);
406
+ Object.keys(source).forEach(key => {
407
+ const sourceValue = source[key];
408
+ if (sourceValue === undefined)
409
+ return;
410
+ const targetValue = result[key];
411
+ if (isPlainObject(targetValue) && isPlainObject(sourceValue)) {
412
+ result[key] = merge(targetValue, sourceValue);
413
+ }
414
+ else {
415
+ result[key] = clone(sourceValue);
416
+ }
417
+ });
418
+ return result;
419
+ };
420
+ const deepMerge = (...sources) => sources.reduce((result, source) => merge(result, source), {});
421
+ const ObjectUtilities = {
422
+ isPlainObject,
423
+ clone,
424
+ merge,
425
+ deepMerge,
426
+ };
427
+
386
428
  /**
387
429
  * Generated bundle index. Do not edit.
388
430
  */
389
431
 
390
- export { SdUtilities, StringUtilities, hslToHex, rgbToHex };
432
+ export { ObjectUtilities, SdUtilities, StringUtilities, hslToHex, rgbToHex };
391
433
  //# sourceMappingURL=sdcorejs-angular-utilities-extensions.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"sdcorejs-angular-utilities-extensions.mjs","sources":["../../../projects/sdcorejs-angular/utilities/extensions/src/string.extension.ts","../../../projects/sdcorejs-angular/utilities/extensions/src/utility.extension.ts","../../../projects/sdcorejs-angular/utilities/extensions/src/color.extension.ts","../../../projects/sdcorejs-angular/utilities/extensions/sdcorejs-angular-utilities-extensions.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { StringUtilities as _Utils, ValidationUtilities } from '@sdcorejs/utils/fns';\n\nexport { ValidationUtilities };\n\n// Deprecated wrappers — moved to ValidationUtilities\nconst isValidEmail = (value: any) => ValidationUtilities.isEmail(value);\nconst isValidPhone = (value: any) => ValidationUtilities.isPhone(value);\nconst isValidCode = (value: any) => ValidationUtilities.isCode(value);\n\nexport const StringUtilities = {\n ..._Utils,\n // Deprecated aliases for renamed regex constants (renamed in @sdcorejs/utils v1.0.2)\n /** @deprecated Use REGEX_VN_PHONE instead */\n REGEX_PHONE_VN: _Utils.REGEX_VN_PHONE,\n /** @deprecated Use REGEX_VN_ID instead */\n REGEX_IDVN: _Utils.REGEX_VN_ID,\n /** @deprecated Use REGEX_VN_ID_OR_PASSPORT instead */\n REGEX_IDVN_OR_PASSPORT: _Utils.REGEX_VN_ID_OR_PASSPORT,\n // Deprecated validators — moved to ValidationUtilities\n /** @deprecated Use {@link ValidationUtilities.isEmail} instead */\n isValidEmail,\n /** @deprecated Use {@link ValidationUtilities.isPhone} instead */\n isValidPhone,\n /** @deprecated Use {@link ValidationUtilities.isCode} instead */\n isValidCode,\n};\n","export { Utilities, BrowserUtilities } from '@sdcorejs/utils/fns';\n\n// Hardcoded i18n cho upload utility — pure function nên không inject() được I18nService.\n// Đọc lang trực tiếp từ localStorage (cùng key với I18nService: 'sd-core.language').\n// Khi I18nService chuyển sang reload-on-change model, lang ở đây luôn đồng bộ với UI.\nconst SD_UPLOAD_MESSAGES = {\n vi: {\n 'invalid-format': '[{name}] File tải lên không đúng định dạng. Vui lòng chọn lại',\n 'invalid-size': '[{name}] Kích thước file không hợp lệ. Vui lòng chọn một file khác',\n },\n en: {\n 'invalid-format': '[{name}] Invalid file format. Please select again',\n 'invalid-size': '[{name}] Invalid file size. Please choose a different file',\n },\n ja: {\n 'invalid-format': '[{name}] ファイル形式が正しくありません。もう一度選択してください',\n 'invalid-size': '[{name}] ファイルサイズが正しくありません。別のファイルを選択してください',\n },\n ko: {\n 'invalid-format': '[{name}] 파일 형식이 올바르지 않습니다. 다시 선택해 주세요',\n 'invalid-size': '[{name}] 파일 크기가 올바르지 않습니다. 다른 파일을 선택해 주세요',\n },\n zh: {\n 'invalid-format': '[{name}] 文件格式不正确,请重新选择',\n 'invalid-size': '[{name}] 文件大小不符合要求,请选择其他文件',\n },\n} as const;\n\ntype SdUploadMsgKey = keyof typeof SD_UPLOAD_MESSAGES.vi;\ntype SdUploadLang = keyof typeof SD_UPLOAD_MESSAGES;\n\nconst getSdUploadLang = (): SdUploadLang => {\n try {\n const stored = localStorage.getItem('sd-core.language');\n if (stored && stored in SD_UPLOAD_MESSAGES) return stored as SdUploadLang;\n } catch { /* ignore */ }\n return 'vi';\n};\n\nconst upload = (option?: { extensions?: string[]; maxSizeInMb?: number; validator?: (fileName: string) => string; multiple?: boolean }) => {\n const uploadId = 'U1e09c1c0-b647-437e-995e-d7a1a1b60550';\n const promise = new Promise<File | File[] | null>((resolve, reject) => {\n const body = document.getElementsByTagName('body')?.[0];\n if (!body) {\n resolve(null);\n return;\n }\n const existedElement = document.getElementById(uploadId);\n if (existedElement) {\n existedElement.remove();\n }\n const element = document.createElement('input');\n element.setAttribute('id', uploadId);\n element.setAttribute('type', 'file');\n if (option?.multiple) {\n element.setAttribute('multiple', '');\n }\n element.style.display = 'none';\n body.appendChild(element);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n element.addEventListener('change', (evt: any) => {\n try {\n const target = evt.target as DataTransfer;\n\n // Hardcode i18n cho upload utility — pure function nên không inject() được I18nService.\n // Đọc lang trực tiếp từ localStorage (cùng key với I18nService: 'sd-core.language').\n // Throw plain Error(translatedText) để consumer không cần xử lý đặc biệt.\n const throwUploadError = (msgKey: SdUploadMsgKey, name: string): never => {\n const lang = getSdUploadLang();\n const template = SD_UPLOAD_MESSAGES[lang][msgKey] ?? SD_UPLOAD_MESSAGES.vi[msgKey];\n throw new Error(template.replace('{name}', name));\n };\n\n if (option?.multiple) {\n const files: File[] = [];\n for (const file of target.files) {\n if (file) {\n const lastDot = file.name.lastIndexOf('.');\n if (lastDot === -1) {\n throwUploadError('invalid-format', file.name);\n }\n const extension = file.name.substring(lastDot + 1);\n if (option) {\n if (option.extensions?.length && !option.extensions.some(e => e.toLowerCase() === extension.toLowerCase())) {\n throwUploadError('invalid-format', file.name);\n }\n if (option.maxSizeInMb && option.maxSizeInMb > 0 && option.maxSizeInMb * 1024 * 1024 < file.size) {\n throwUploadError('invalid-size', file.name);\n }\n if (option.validator && option.validator(file.name)) {\n // Custom validator returns its own message — pass through as-is (caller defines format).\n const message = option.validator(file.name);\n throw new Error(message);\n }\n }\n files.push(file);\n }\n resolve(files);\n }\n } else {\n const file = target.files.item(0);\n if (file) {\n const lastDot = file.name.lastIndexOf('.');\n if (lastDot === -1) {\n throwUploadError('invalid-format', file.name);\n }\n const extension = file.name.substring(lastDot + 1);\n if (option) {\n if (option.extensions?.length && !option.extensions.some(e => e.toLowerCase() === extension.toLowerCase())) {\n throwUploadError('invalid-format', file.name);\n }\n if (option.maxSizeInMb && option.maxSizeInMb > 0 && option.maxSizeInMb * 1024 * 1024 < file.size) {\n throwUploadError('invalid-size', file.name);\n }\n if (option.validator && option.validator(file.name)) {\n const message = option.validator(file.name);\n throw new Error(message);\n }\n }\n resolve(file);\n }\n }\n } catch (error) {\n reject(error);\n }\n });\n element.click();\n });\n return promise;\n};\n\nconst generateFileName = (fileName?: string | null) => {\n if (!fileName) {\n return `file_${randomId()}`;\n }\n return fileName;\n};\n\nconst download = (fileOrPath: File | string | undefined | null, fileName?: string | null) => {\n if (!fileOrPath) {\n console.warn('No file or path provided for download');\n return;\n }\n fileName = generateFileName(fileName);\n if (fileOrPath instanceof File) {\n // Hoặc sử dụng cách thông thường:\n const url = URL.createObjectURL(fileOrPath);\n const a = document.createElement('a');\n a.href = url;\n a.download = fileOrPath.name || fileName;\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n URL.revokeObjectURL(url); // Giải phóng tài nguyên\n return;\n }\n const a = document.createElement('a');\n a.href = fileOrPath;\n if (fileOrPath.startsWith('http')) {\n a.target = '_blank'; // mở tab mới\n } else {\n a.download = fileName;\n }\n a.style.visibility = 'hidden';\n document.body.appendChild(a);\n a.click();\n a.remove();\n return;\n};\n\nconst downloadBlob = (blob: Blob, fileName?: string) => {\n try {\n const url = window.URL.createObjectURL(blob);\n const link = document.createElement('a');\n if (link.download !== undefined) {\n // feature detection\n link.download = generateFileName(fileName);\n link.href = url;\n link.style.visibility = 'hidden';\n document.body.appendChild(link);\n link.click();\n window.URL.revokeObjectURL(url);\n link.remove();\n }\n } catch (e) {\n console.error('BlobToSaveAs error', e);\n }\n};\n\nconst changeAliasLowerCase = (alias: string) => {\n let str = alias?.toString() ?? '';\n str = str.toString().toLowerCase();\n str = str.replace(/à|á|ạ|ả|ã|â|ầ|ấ|ậ|ẩ|ẫ|ă|ằ|ắ|ặ|ẳ|ẵ/g, 'a');\n str = str.replace(/è|é|ẹ|ẻ|ẽ|ê|ề|ế|ệ|ể|ễ/g, 'e');\n str = str.replace(/ì|í|ị|ỉ|ĩ/g, 'i');\n str = str.replace(/ò|ó|ọ|ỏ|õ|ô|ồ|ố|ộ|ổ|ỗ|ơ|ờ|ớ|ợ|ở|ỡ/g, 'o');\n str = str.replace(/ù|ú|ụ|ủ|ũ|ư|ừ|ứ|ự|ử|ữ/g, 'u');\n str = str.replace(/ỳ|ý|ỵ|ỷ|ỹ/g, 'y');\n str = str.replace(/đ/g, 'd');\n // eslint-disable-next-line no-useless-escape\n str = str.replace(/!|@|%|\\^|\\*|\\(|\\)|\\+|\\=|\\<|\\>|\\?|\\/|,|\\.|\\:|\\;|\\'|\\\"|\\&|\\#|\\[|\\]|~|\\$|_|`|-|{|}|\\||\\\\/g, ' ');\n str = str.replace(/ + /g, ' ');\n str = str.trim();\n return str;\n};\n\nconst copyToClipboard = (text: string) => {\n navigator.clipboard.writeText(text);\n};\n\nconst allWithPaging = async <T = unknown>(\n func: (pageSize: number, pageNumber: number) => Promise<{ items: T[]; total: number }>,\n defaultPageSize?: number\n): Promise<T[]> => {\n const pageSize = defaultPageSize || 1000;\n let pageNumber = 0;\n let count = 0;\n let items: T[] = [];\n while (true) {\n const res = await func(pageSize, pageNumber);\n if (Array(res?.items) && res?.total > 0) {\n items = [...items, ...res.items];\n count += res.items.length;\n pageNumber++;\n if (count >= res.total || !res.items?.length) {\n return items;\n }\n } else {\n return [];\n }\n }\n};\n\nconst isIncognito = async (): Promise<boolean> => {\n // Chrome-based\n if ('storage' in navigator && 'estimate' in navigator.storage) {\n try {\n const { quota } = await navigator.storage.estimate();\n if (quota && quota < 120 * 1024 * 1024) return true;\n } catch (err) {\n console.error(err);\n }\n }\n\n // Safari fallback\n try {\n localStorage.setItem('__incognito_test', '1');\n localStorage.removeItem('__incognito_test');\n return false;\n } catch {\n return true;\n }\n};\n\nconst isMobile = (): boolean => {\n return /Mobi|Android/i.test(navigator.userAgent);\n};\n\nconst randomId = (prefix?: string | null): string => {\n const id = `${new Date().getTime().toString(36)}${Math.random().toString(36).substring(2, 7)}`;\n if (prefix) {\n return `${prefix}_${id}`;\n }\n return id;\n};\n\nconst hash = (obj: any): string => {\n const json = stableStringify(obj);\n let hash = 0;\n\n for (let i = 0; i < json.length; i++) {\n hash = (hash << 5) - hash + json.charCodeAt(i);\n hash |= 0; // Convert to 32bit integer\n }\n\n return `h${Math.abs(hash)}`;\n};\n\n/**\n * Convert object to stable JSON string (keys sorted)\n */\nconst stableStringify = (obj: any): string => {\n if (obj === null || typeof obj !== 'object') {\n return JSON.stringify(obj);\n }\n\n if (obj instanceof File) {\n // Chỉ serialize các thuộc tính quan trọng của File\n return JSON.stringify({\n __type: 'File',\n name: obj.name,\n size: obj.size,\n type: obj.type,\n lastModified: obj.lastModified,\n });\n }\n\n if (Array.isArray(obj)) {\n return `[${obj.map(stableStringify).join(',')}]`;\n }\n\n const keys = Object.keys(obj).sort();\n const keyValuePairs = keys.map(key => `\"${key}\":${stableStringify(obj[key])}`);\n\n return `{${keyValuePairs.join(',')}}`;\n};\n\n// Hàm `parseQueryParams` dùng để phân tích chuỗi query string (phần sau dấu `?` trên URL)\n// và chuyển đổi nó thành một đối tượng JavaScript với các cặp key-value.\nconst parseQueryParams = (queryString?: string): Record<string, string> => {\n const params = new URLSearchParams(queryString || '');\n const result: Record<string, string> = {};\n params.forEach((value, key) => {\n result[key] = value;\n });\n return result;\n};\n\n/**\n * Lấy địa chỉ IP public của client bằng cách gọi API bên thứ ba.\n */\nconst getClientPublicIp = async (): Promise<string | null> => {\n try {\n // Gọi đến API của ipify để lấy IP dưới dạng JSON\n const response = await fetch('https://api.ipify.org?format=json');\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n const data = await response.json();\n // Trả về địa chỉ IP\n return data.ip;\n } catch (error) {\n console.error('Failed to fetch client IP:', error);\n return null; // Trả về null nếu có lỗi\n }\n};\n\n\n// Helper function với fallback\nconst generateUuid = (): string => {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n // Fallback cho browser cũ\n return `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\n};\n\n/**\n * Truy xuất giá trị của object dựa trên đường dẫn nested (VD: 'user.address.city')\n */\nconst getNestedValue = (obj: any, path: string) => {\n if (!obj || !path) return undefined;\n // Tách chuỗi theo dấu chấm và duyệt qua từng cấp của object\n return path.split('.').reduce((acc, part) => acc?.[part], obj);\n};\n\n/**\n * @deprecated Use {@link Utilities} and {@link BrowserUtilities} from `@sdcorejs/utils/fns` instead.\n * - upload/download/clipboard/isMobile → BrowserUtilities\n * - allWithPaging (→ fetchAllByPaging) / randomId / hash / parseQueryParams / generateUuid / getNestedValue → Utilities\n */\nconst SdUtilities = {\n upload,\n download,\n downloadBlob,\n changeAliasLowerCase,\n copyToClipboard,\n allWithPaging,\n isIncognito,\n isMobile,\n randomId,\n hash,\n parseQueryParams,\n getClientPublicIp,\n generateUuid,\n getNestedValue\n};\nexport { SdUtilities };\n\n","export { ColorUtilities } from '@sdcorejs/utils/fns';\n\nimport { ColorUtilities } from '@sdcorejs/utils/fns';\n/** @deprecated Use {@link ColorUtilities.hslToHex} from `@sdcorejs/utils/fns` instead */\nexport const hslToHex = ColorUtilities.hslToHex;\n/** @deprecated Use {@link ColorUtilities.rgbToHex} from `@sdcorejs/utils/fns` instead */\nexport const rgbToHex = ColorUtilities.rgbToHex;\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["_Utils"],"mappings":";;;AAAA;AAKA;AACA,MAAM,YAAY,GAAG,CAAC,KAAU,KAAK,mBAAmB,CAAC,OAAO,CAAC,KAAK,CAAC;AACvE,MAAM,YAAY,GAAG,CAAC,KAAU,KAAK,mBAAmB,CAAC,OAAO,CAAC,KAAK,CAAC;AACvE,MAAM,WAAW,GAAI,CAAC,KAAU,KAAK,mBAAmB,CAAC,MAAM,CAAC,KAAK,CAAC;AAE/D,MAAM,eAAe,GAAG;AAC7B,IAAA,GAAGA,iBAAM;;;IAGT,cAAc,EAAEA,iBAAM,CAAC,cAAc;;IAErC,UAAU,EAAEA,iBAAM,CAAC,WAAW;;IAE9B,sBAAsB,EAAEA,iBAAM,CAAC,uBAAuB;;;IAGtD,YAAY;;IAEZ,YAAY;;IAEZ,WAAW;;;ACvBb;AACA;AACA;AACA,MAAM,kBAAkB,GAAG;AACzB,IAAA,EAAE,EAAE;AACF,QAAA,gBAAgB,EAAE,+DAA+D;AACjF,QAAA,cAAc,EAAE,oEAAoE;AACrF,KAAA;AACD,IAAA,EAAE,EAAE;AACF,QAAA,gBAAgB,EAAE,mDAAmD;AACrE,QAAA,cAAc,EAAE,4DAA4D;AAC7E,KAAA;AACD,IAAA,EAAE,EAAE;AACF,QAAA,gBAAgB,EAAE,uCAAuC;AACzD,QAAA,cAAc,EAAE,2CAA2C;AAC5D,KAAA;AACD,IAAA,EAAE,EAAE;AACF,QAAA,gBAAgB,EAAE,uCAAuC;AACzD,QAAA,cAAc,EAAE,2CAA2C;AAC5D,KAAA;AACD,IAAA,EAAE,EAAE;AACF,QAAA,gBAAgB,EAAE,wBAAwB;AAC1C,QAAA,cAAc,EAAE,4BAA4B;AAC7C,KAAA;CACO;AAKV,MAAM,eAAe,GAAG,MAAmB;AACzC,IAAA,IAAI;QACF,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,kBAAkB,CAAC;AACvD,QAAA,IAAI,MAAM,IAAI,MAAM,IAAI,kBAAkB;AAAE,YAAA,OAAO,MAAsB;IAC3E;AAAE,IAAA,MAAM,eAAe;AACvB,IAAA,OAAO,IAAI;AACb,CAAC;AAED,MAAM,MAAM,GAAG,CAAC,MAAsH,KAAI;IACxI,MAAM,QAAQ,GAAG,uCAAuC;IACxD,MAAM,OAAO,GAAG,IAAI,OAAO,CAAuB,CAAC,OAAO,EAAE,MAAM,KAAI;AACpE,QAAA,MAAM,IAAI,GAAG,QAAQ,CAAC,oBAAoB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACvD,IAAI,CAAC,IAAI,EAAE;YACT,OAAO,CAAC,IAAI,CAAC;YACb;QACF;QACA,MAAM,cAAc,GAAG,QAAQ,CAAC,cAAc,CAAC,QAAQ,CAAC;QACxD,IAAI,cAAc,EAAE;YAClB,cAAc,CAAC,MAAM,EAAE;QACzB;QACA,MAAM,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC;AAC/C,QAAA,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,QAAQ,CAAC;AACpC,QAAA,OAAO,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC;AACpC,QAAA,IAAI,MAAM,EAAE,QAAQ,EAAE;AACpB,YAAA,OAAO,CAAC,YAAY,CAAC,UAAU,EAAE,EAAE,CAAC;QACtC;AACA,QAAA,OAAO,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM;AAC9B,QAAA,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC;;QAEzB,OAAO,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC,GAAQ,KAAI;AAC9C,YAAA,IAAI;AACF,gBAAA,MAAM,MAAM,GAAG,GAAG,CAAC,MAAsB;;;;AAKzC,gBAAA,MAAM,gBAAgB,GAAG,CAAC,MAAsB,EAAE,IAAY,KAAW;AACvE,oBAAA,MAAM,IAAI,GAAG,eAAe,EAAE;AAC9B,oBAAA,MAAM,QAAQ,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,kBAAkB,CAAC,EAAE,CAAC,MAAM,CAAC;AAClF,oBAAA,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;AACnD,gBAAA,CAAC;AAED,gBAAA,IAAI,MAAM,EAAE,QAAQ,EAAE;oBACpB,MAAM,KAAK,GAAW,EAAE;AACxB,oBAAA,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE;wBAC/B,IAAI,IAAI,EAAE;4BACR,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC;AAC1C,4BAAA,IAAI,OAAO,KAAK,CAAC,CAAC,EAAE;AAClB,gCAAA,gBAAgB,CAAC,gBAAgB,EAAE,IAAI,CAAC,IAAI,CAAC;4BAC/C;AACA,4BAAA,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,GAAG,CAAC,CAAC;4BAClD,IAAI,MAAM,EAAE;AACV,gCAAA,IAAI,MAAM,CAAC,UAAU,EAAE,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,KAAK,SAAS,CAAC,WAAW,EAAE,CAAC,EAAE;AAC1G,oCAAA,gBAAgB,CAAC,gBAAgB,EAAE,IAAI,CAAC,IAAI,CAAC;gCAC/C;gCACA,IAAI,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,WAAW,GAAG,CAAC,IAAI,MAAM,CAAC,WAAW,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE;AAChG,oCAAA,gBAAgB,CAAC,cAAc,EAAE,IAAI,CAAC,IAAI,CAAC;gCAC7C;AACA,gCAAA,IAAI,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;;oCAEnD,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;AAC3C,oCAAA,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC;gCAC1B;4BACF;AACA,4BAAA,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;wBAClB;wBACA,OAAO,CAAC,KAAK,CAAC;oBAChB;gBACF;qBAAO;oBACL,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;oBACjC,IAAI,IAAI,EAAE;wBACR,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC;AAC1C,wBAAA,IAAI,OAAO,KAAK,CAAC,CAAC,EAAE;AAClB,4BAAA,gBAAgB,CAAC,gBAAgB,EAAE,IAAI,CAAC,IAAI,CAAC;wBAC/C;AACA,wBAAA,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,GAAG,CAAC,CAAC;wBAClD,IAAI,MAAM,EAAE;AACV,4BAAA,IAAI,MAAM,CAAC,UAAU,EAAE,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,KAAK,SAAS,CAAC,WAAW,EAAE,CAAC,EAAE;AAC1G,gCAAA,gBAAgB,CAAC,gBAAgB,EAAE,IAAI,CAAC,IAAI,CAAC;4BAC/C;4BACA,IAAI,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,WAAW,GAAG,CAAC,IAAI,MAAM,CAAC,WAAW,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE;AAChG,gCAAA,gBAAgB,CAAC,cAAc,EAAE,IAAI,CAAC,IAAI,CAAC;4BAC7C;AACA,4BAAA,IAAI,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;gCACnD,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;AAC3C,gCAAA,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC;4BAC1B;wBACF;wBACA,OAAO,CAAC,IAAI,CAAC;oBACf;gBACF;YACF;YAAE,OAAO,KAAK,EAAE;gBACd,MAAM,CAAC,KAAK,CAAC;YACf;AACF,QAAA,CAAC,CAAC;QACF,OAAO,CAAC,KAAK,EAAE;AACjB,IAAA,CAAC,CAAC;AACF,IAAA,OAAO,OAAO;AAChB,CAAC;AAED,MAAM,gBAAgB,GAAG,CAAC,QAAwB,KAAI;IACpD,IAAI,CAAC,QAAQ,EAAE;AACb,QAAA,OAAO,CAAA,KAAA,EAAQ,QAAQ,EAAE,CAAA,CAAE;IAC7B;AACA,IAAA,OAAO,QAAQ;AACjB,CAAC;AAED,MAAM,QAAQ,GAAG,CAAC,UAA4C,EAAE,QAAwB,KAAI;IAC1F,IAAI,CAAC,UAAU,EAAE;AACf,QAAA,OAAO,CAAC,IAAI,CAAC,uCAAuC,CAAC;QACrD;IACF;AACA,IAAA,QAAQ,GAAG,gBAAgB,CAAC,QAAQ,CAAC;AACrC,IAAA,IAAI,UAAU,YAAY,IAAI,EAAE;;QAE9B,MAAM,GAAG,GAAG,GAAG,CAAC,eAAe,CAAC,UAAU,CAAC;QAC3C,MAAM,CAAC,GAAG,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC;AACrC,QAAA,CAAC,CAAC,IAAI,GAAG,GAAG;QACZ,CAAC,CAAC,QAAQ,GAAG,UAAU,CAAC,IAAI,IAAI,QAAQ;AACxC,QAAA,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;QAC5B,CAAC,CAAC,KAAK,EAAE;AACT,QAAA,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;AAC5B,QAAA,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;QACzB;IACF;IACA,MAAM,CAAC,GAAG,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC;AACrC,IAAA,CAAC,CAAC,IAAI,GAAG,UAAU;AACnB,IAAA,IAAI,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE;AACjC,QAAA,CAAC,CAAC,MAAM,GAAG,QAAQ,CAAC;IACtB;SAAO;AACL,QAAA,CAAC,CAAC,QAAQ,GAAG,QAAQ;IACvB;AACA,IAAA,CAAC,CAAC,KAAK,CAAC,UAAU,GAAG,QAAQ;AAC7B,IAAA,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;IAC5B,CAAC,CAAC,KAAK,EAAE;IACT,CAAC,CAAC,MAAM,EAAE;IACV;AACF,CAAC;AAED,MAAM,YAAY,GAAG,CAAC,IAAU,EAAE,QAAiB,KAAI;AACrD,IAAA,IAAI;QACF,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC;QAC5C,MAAM,IAAI,GAAG,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC;AACxC,QAAA,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,EAAE;;AAE/B,YAAA,IAAI,CAAC,QAAQ,GAAG,gBAAgB,CAAC,QAAQ,CAAC;AAC1C,YAAA,IAAI,CAAC,IAAI,GAAG,GAAG;AACf,YAAA,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,QAAQ;AAChC,YAAA,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;YAC/B,IAAI,CAAC,KAAK,EAAE;AACZ,YAAA,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC;YAC/B,IAAI,CAAC,MAAM,EAAE;QACf;IACF;IAAE,OAAO,CAAC,EAAE;AACV,QAAA,OAAO,CAAC,KAAK,CAAC,oBAAoB,EAAE,CAAC,CAAC;IACxC;AACF,CAAC;AAED,MAAM,oBAAoB,GAAG,CAAC,KAAa,KAAI;IAC7C,IAAI,GAAG,GAAG,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE;IACjC,GAAG,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC,WAAW,EAAE;IAClC,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,oCAAoC,EAAE,GAAG,CAAC;IAC5D,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,wBAAwB,EAAE,GAAG,CAAC;IAChD,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC;IACpC,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,oCAAoC,EAAE,GAAG,CAAC;IAC5D,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,wBAAwB,EAAE,GAAG,CAAC;IAChD,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC;IACpC,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC;;IAE5B,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,wFAAwF,EAAE,GAAG,CAAC;IAChH,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;AAC9B,IAAA,GAAG,GAAG,GAAG,CAAC,IAAI,EAAE;AAChB,IAAA,OAAO,GAAG;AACZ,CAAC;AAED,MAAM,eAAe,GAAG,CAAC,IAAY,KAAI;AACvC,IAAA,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC;AACrC,CAAC;AAED,MAAM,aAAa,GAAG,OACpB,IAAsF,EACtF,eAAwB,KACR;AAChB,IAAA,MAAM,QAAQ,GAAG,eAAe,IAAI,IAAI;IACxC,IAAI,UAAU,GAAG,CAAC;IAClB,IAAI,KAAK,GAAG,CAAC;IACb,IAAI,KAAK,GAAQ,EAAE;IACnB,OAAO,IAAI,EAAE;QACX,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC;AAC5C,QAAA,IAAI,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,GAAG,EAAE,KAAK,GAAG,CAAC,EAAE;YACvC,KAAK,GAAG,CAAC,GAAG,KAAK,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC;AAChC,YAAA,KAAK,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM;AACzB,YAAA,UAAU,EAAE;AACZ,YAAA,IAAI,KAAK,IAAI,GAAG,CAAC,KAAK,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE;AAC5C,gBAAA,OAAO,KAAK;YACd;QACF;aAAO;AACL,YAAA,OAAO,EAAE;QACX;IACF;AACF,CAAC;AAED,MAAM,WAAW,GAAG,YAA6B;;IAE/C,IAAI,SAAS,IAAI,SAAS,IAAI,UAAU,IAAI,SAAS,CAAC,OAAO,EAAE;AAC7D,QAAA,IAAI;YACF,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,QAAQ,EAAE;YACpD,IAAI,KAAK,IAAI,KAAK,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI;AAAE,gBAAA,OAAO,IAAI;QACrD;QAAE,OAAO,GAAG,EAAE;AACZ,YAAA,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC;QACpB;IACF;;AAGA,IAAA,IAAI;AACF,QAAA,YAAY,CAAC,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC;AAC7C,QAAA,YAAY,CAAC,UAAU,CAAC,kBAAkB,CAAC;AAC3C,QAAA,OAAO,KAAK;IACd;AAAE,IAAA,MAAM;AACN,QAAA,OAAO,IAAI;IACb;AACF,CAAC;AAED,MAAM,QAAQ,GAAG,MAAc;IAC7B,OAAO,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;AAClD,CAAC;AAED,MAAM,QAAQ,GAAG,CAAC,MAAsB,KAAY;AAClD,IAAA,MAAM,EAAE,GAAG,CAAA,EAAG,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA,EAAG,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE;IAC9F,IAAI,MAAM,EAAE;AACV,QAAA,OAAO,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,EAAE,EAAE;IAC1B;AACA,IAAA,OAAO,EAAE;AACX,CAAC;AAED,MAAM,IAAI,GAAG,CAAC,GAAQ,KAAY;AAChC,IAAA,MAAM,IAAI,GAAG,eAAe,CAAC,GAAG,CAAC;IACjC,IAAI,IAAI,GAAG,CAAC;AAEZ,IAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AACpC,QAAA,IAAI,GAAG,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;AAC9C,QAAA,IAAI,IAAI,CAAC,CAAC;IACZ;IAEA,OAAO,CAAA,CAAA,EAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;AAC7B,CAAC;AAED;;AAEG;AACH,MAAM,eAAe,GAAG,CAAC,GAAQ,KAAY;IAC3C,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE;AAC3C,QAAA,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC;IAC5B;AAEA,IAAA,IAAI,GAAG,YAAY,IAAI,EAAE;;QAEvB,OAAO,IAAI,CAAC,SAAS,CAAC;AACpB,YAAA,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,YAAY,EAAE,GAAG,CAAC,YAAY;AAC/B,SAAA,CAAC;IACJ;AAEA,IAAA,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;AACtB,QAAA,OAAO,CAAA,CAAA,EAAI,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG;IAClD;IAEA,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE;IACpC,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAA,CAAA,EAAI,GAAG,CAAA,EAAA,EAAK,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAA,CAAE,CAAC;IAE9E,OAAO,CAAA,CAAA,EAAI,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG;AACvC,CAAC;AAED;AACA;AACA,MAAM,gBAAgB,GAAG,CAAC,WAAoB,KAA4B;IACxE,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,WAAW,IAAI,EAAE,CAAC;IACrD,MAAM,MAAM,GAA2B,EAAE;IACzC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,GAAG,KAAI;AAC5B,QAAA,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK;AACrB,IAAA,CAAC,CAAC;AACF,IAAA,OAAO,MAAM;AACf,CAAC;AAED;;AAEG;AACH,MAAM,iBAAiB,GAAG,YAAmC;AAC3D,IAAA,IAAI;;AAEF,QAAA,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,mCAAmC,CAAC;AACjE,QAAA,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE;YAChB,MAAM,IAAI,KAAK,CAAC,CAAA,oBAAA,EAAuB,QAAQ,CAAC,MAAM,CAAA,CAAE,CAAC;QAC3D;AACA,QAAA,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE;;QAElC,OAAO,IAAI,CAAC,EAAE;IAChB;IAAE,OAAO,KAAK,EAAE;AACd,QAAA,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,KAAK,CAAC;QAClD,OAAO,IAAI,CAAC;IACd;AACF,CAAC;AAGD;AACA,MAAM,YAAY,GAAG,MAAa;IAChC,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,MAAM,CAAC,UAAU,EAAE;AACtD,QAAA,OAAO,MAAM,CAAC,UAAU,EAAE;IAC5B;;IAEA,OAAO,CAAA,EAAG,IAAI,CAAC,GAAG,EAAE,CAAA,CAAA,EAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA,CAAE;AACtE,CAAC;AAED;;AAEG;AACH,MAAM,cAAc,GAAG,CAAC,GAAQ,EAAE,IAAY,KAAI;AAChD,IAAA,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI;AAAE,QAAA,OAAO,SAAS;;IAEnC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,KAAK,GAAG,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC;AAChE,CAAC;AAED;;;;AAIG;AACH,MAAM,WAAW,GAAG;IAClB,MAAM;IACN,QAAQ;IACR,YAAY;IACZ,oBAAoB;IACpB,eAAe;IACf,aAAa;IACb,WAAW;IACX,QAAQ;IACR,QAAQ;IACR,IAAI;IACJ,gBAAgB;IAChB,iBAAiB;IACjB,YAAY;IACZ;;;ACpXF;AACO,MAAM,QAAQ,GAAG,cAAc,CAAC;AACvC;AACO,MAAM,QAAQ,GAAG,cAAc,CAAC;;ACNvC;;AAEG;;;;"}
1
+ {"version":3,"file":"sdcorejs-angular-utilities-extensions.mjs","sources":["../../../projects/sdcorejs-angular/utilities/extensions/src/string.extension.ts","../../../projects/sdcorejs-angular/utilities/extensions/src/utility.extension.ts","../../../projects/sdcorejs-angular/utilities/extensions/src/color.extension.ts","../../../projects/sdcorejs-angular/utilities/extensions/src/object.extension.ts","../../../projects/sdcorejs-angular/utilities/extensions/sdcorejs-angular-utilities-extensions.ts"],"sourcesContent":["import { StringUtilities as _Utils, ValidationUtilities } from '@sdcorejs/utils/fns';\n\nexport { ValidationUtilities };\n\n// Deprecated wrappers — moved to ValidationUtilities\nconst isValidEmail = (value: any) => ValidationUtilities.isEmail(value);\nconst isValidPhone = (value: any) => ValidationUtilities.isPhone(value);\nconst isValidCode = (value: any) => ValidationUtilities.isCode(value);\n\nexport const StringUtilities = {\n ..._Utils,\n // Deprecated aliases for renamed regex constants (renamed in @sdcorejs/utils v1.0.2)\n /** @deprecated Use REGEX_VN_PHONE instead */\n REGEX_PHONE_VN: _Utils.REGEX_VN_PHONE,\n /** @deprecated Use REGEX_VN_ID instead */\n REGEX_IDVN: _Utils.REGEX_VN_ID,\n /** @deprecated Use REGEX_VN_ID_OR_PASSPORT instead */\n REGEX_IDVN_OR_PASSPORT: _Utils.REGEX_VN_ID_OR_PASSPORT,\n // Deprecated validators — moved to ValidationUtilities\n /** @deprecated Use {@link ValidationUtilities.isEmail} instead */\n isValidEmail,\n /** @deprecated Use {@link ValidationUtilities.isPhone} instead */\n isValidPhone,\n /** @deprecated Use {@link ValidationUtilities.isCode} instead */\n isValidCode,\n};\n","export { Utilities, BrowserUtilities } from '@sdcorejs/utils/fns';\n\n// Hardcoded i18n cho upload utility — pure function nên không inject() được I18nService.\n// Đọc lang trực tiếp từ localStorage (cùng key với I18nService: 'sd-core.language').\n// Khi I18nService chuyển sang reload-on-change model, lang ở đây luôn đồng bộ với UI.\nconst SD_UPLOAD_MESSAGES = {\n vi: {\n 'invalid-format': '[{name}] File tải lên không đúng định dạng. Vui lòng chọn lại',\n 'invalid-size': '[{name}] Kích thước file không hợp lệ. Vui lòng chọn một file khác',\n },\n en: {\n 'invalid-format': '[{name}] Invalid file format. Please select again',\n 'invalid-size': '[{name}] Invalid file size. Please choose a different file',\n },\n ja: {\n 'invalid-format': '[{name}] ファイル形式が正しくありません。もう一度選択してください',\n 'invalid-size': '[{name}] ファイルサイズが正しくありません。別のファイルを選択してください',\n },\n ko: {\n 'invalid-format': '[{name}] 파일 형식이 올바르지 않습니다. 다시 선택해 주세요',\n 'invalid-size': '[{name}] 파일 크기가 올바르지 않습니다. 다른 파일을 선택해 주세요',\n },\n zh: {\n 'invalid-format': '[{name}] 文件格式不正确,请重新选择',\n 'invalid-size': '[{name}] 文件大小不符合要求,请选择其他文件',\n },\n} as const;\n\ntype SdUploadMsgKey = keyof typeof SD_UPLOAD_MESSAGES.vi;\ntype SdUploadLang = keyof typeof SD_UPLOAD_MESSAGES;\n\nconst getSdUploadLang = (): SdUploadLang => {\n try {\n const stored = localStorage.getItem('sd-core.language');\n if (stored && stored in SD_UPLOAD_MESSAGES) return stored as SdUploadLang;\n } catch {\n /* ignore */\n }\n return 'vi';\n};\n\nconst upload = (option?: { extensions?: string[]; maxSizeInMb?: number; validator?: (fileName: string) => string; multiple?: boolean }) => {\n const uploadId = 'U1e09c1c0-b647-437e-995e-d7a1a1b60550';\n const promise = new Promise<File | File[] | null>((resolve, reject) => {\n const body = document.getElementsByTagName('body')?.[0];\n if (!body) {\n resolve(null);\n return;\n }\n const existedElement = document.getElementById(uploadId);\n if (existedElement) {\n existedElement.remove();\n }\n const element = document.createElement('input');\n element.setAttribute('id', uploadId);\n element.setAttribute('type', 'file');\n if (option?.multiple) {\n element.setAttribute('multiple', '');\n }\n element.style.display = 'none';\n body.appendChild(element);\n\n element.addEventListener('change', (evt: any) => {\n try {\n const target = evt.target as DataTransfer;\n\n // Hardcode i18n cho upload utility — pure function nên không inject() được I18nService.\n // Đọc lang trực tiếp từ localStorage (cùng key với I18nService: 'sd-core.language').\n // Throw plain Error(translatedText) để consumer không cần xử lý đặc biệt.\n const throwUploadError = (msgKey: SdUploadMsgKey, name: string): never => {\n const lang = getSdUploadLang();\n const template = SD_UPLOAD_MESSAGES[lang][msgKey] ?? SD_UPLOAD_MESSAGES.vi[msgKey];\n throw new Error(template.replace('{name}', name));\n };\n\n if (option?.multiple) {\n const files: File[] = [];\n for (const file of target.files) {\n if (file) {\n const lastDot = file.name.lastIndexOf('.');\n if (lastDot === -1) {\n throwUploadError('invalid-format', file.name);\n }\n const extension = file.name.substring(lastDot + 1);\n if (option) {\n if (option.extensions?.length && !option.extensions.some(e => e.toLowerCase() === extension.toLowerCase())) {\n throwUploadError('invalid-format', file.name);\n }\n if (option.maxSizeInMb && option.maxSizeInMb > 0 && option.maxSizeInMb * 1024 * 1024 < file.size) {\n throwUploadError('invalid-size', file.name);\n }\n if (option.validator && option.validator(file.name)) {\n // Custom validator returns its own message — pass through as-is (caller defines format).\n const message = option.validator(file.name);\n throw new Error(message);\n }\n }\n files.push(file);\n }\n resolve(files);\n }\n } else {\n const file = target.files.item(0);\n if (file) {\n const lastDot = file.name.lastIndexOf('.');\n if (lastDot === -1) {\n throwUploadError('invalid-format', file.name);\n }\n const extension = file.name.substring(lastDot + 1);\n if (option) {\n if (option.extensions?.length && !option.extensions.some(e => e.toLowerCase() === extension.toLowerCase())) {\n throwUploadError('invalid-format', file.name);\n }\n if (option.maxSizeInMb && option.maxSizeInMb > 0 && option.maxSizeInMb * 1024 * 1024 < file.size) {\n throwUploadError('invalid-size', file.name);\n }\n if (option.validator && option.validator(file.name)) {\n const message = option.validator(file.name);\n throw new Error(message);\n }\n }\n resolve(file);\n }\n }\n } catch (error) {\n reject(error);\n }\n });\n element.click();\n });\n return promise;\n};\n\nconst generateFileName = (fileName?: string | null) => {\n if (!fileName) {\n return `file_${randomId()}`;\n }\n return fileName;\n};\n\nconst download = (fileOrPath: File | string | undefined | null, fileName?: string | null) => {\n if (!fileOrPath) {\n console.warn('No file or path provided for download');\n return;\n }\n fileName = generateFileName(fileName);\n if (fileOrPath instanceof File) {\n // Hoặc sử dụng cách thông thường:\n const url = URL.createObjectURL(fileOrPath);\n const a = document.createElement('a');\n a.href = url;\n a.download = fileOrPath.name || fileName;\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n URL.revokeObjectURL(url); // Giải phóng tài nguyên\n return;\n }\n const a = document.createElement('a');\n a.href = fileOrPath;\n if (fileOrPath.startsWith('http')) {\n a.target = '_blank'; // mở tab mới\n } else {\n a.download = fileName;\n }\n a.style.visibility = 'hidden';\n document.body.appendChild(a);\n a.click();\n a.remove();\n return;\n};\n\nconst downloadBlob = (blob: Blob, fileName?: string) => {\n try {\n const url = window.URL.createObjectURL(blob);\n const link = document.createElement('a');\n if (link.download !== undefined) {\n // feature detection\n link.download = generateFileName(fileName);\n link.href = url;\n link.style.visibility = 'hidden';\n document.body.appendChild(link);\n link.click();\n window.URL.revokeObjectURL(url);\n link.remove();\n }\n } catch (e) {\n console.error('BlobToSaveAs error', e);\n }\n};\n\nconst changeAliasLowerCase = (alias: string) => {\n let str = alias?.toString() ?? '';\n str = str.toString().toLowerCase();\n str = str.replace(/à|á|ạ|ả|ã|â|ầ|ấ|ậ|ẩ|ẫ|ă|ằ|ắ|ặ|ẳ|ẵ/g, 'a');\n str = str.replace(/è|é|ẹ|ẻ|ẽ|ê|ề|ế|ệ|ể|ễ/g, 'e');\n str = str.replace(/ì|í|ị|ỉ|ĩ/g, 'i');\n str = str.replace(/ò|ó|ọ|ỏ|õ|ô|ồ|ố|ộ|ổ|ỗ|ơ|ờ|ớ|ợ|ở|ỡ/g, 'o');\n str = str.replace(/ù|ú|ụ|ủ|ũ|ư|ừ|ứ|ự|ử|ữ/g, 'u');\n str = str.replace(/ỳ|ý|ỵ|ỷ|ỹ/g, 'y');\n str = str.replace(/đ/g, 'd');\n // eslint-disable-next-line no-useless-escape\n str = str.replace(/!|@|%|\\^|\\*|\\(|\\)|\\+|\\=|\\<|\\>|\\?|\\/|,|\\.|\\:|\\;|\\'|\\\"|\\&|\\#|\\[|\\]|~|\\$|_|`|-|{|}|\\||\\\\/g, ' ');\n str = str.replace(/ + /g, ' ');\n str = str.trim();\n return str;\n};\n\nconst copyToClipboard = (text: string) => {\n navigator.clipboard.writeText(text);\n};\n\nconst allWithPaging = async <T = unknown>(\n func: (pageSize: number, pageNumber: number) => Promise<{ items: T[]; total: number }>,\n defaultPageSize?: number\n): Promise<T[]> => {\n const pageSize = defaultPageSize || 1000;\n let pageNumber = 0;\n let count = 0;\n let items: T[] = [];\n while (true) {\n const res = await func(pageSize, pageNumber);\n if (Array(res?.items) && res?.total > 0) {\n items = [...items, ...res.items];\n count += res.items.length;\n pageNumber++;\n if (count >= res.total || !res.items?.length) {\n return items;\n }\n } else {\n return [];\n }\n }\n};\n\nconst isIncognito = async (): Promise<boolean> => {\n // Chrome-based\n if ('storage' in navigator && 'estimate' in navigator.storage) {\n try {\n const { quota } = await navigator.storage.estimate();\n if (quota && quota < 120 * 1024 * 1024) return true;\n } catch (err) {\n console.error(err);\n }\n }\n\n // Safari fallback\n try {\n localStorage.setItem('__incognito_test', '1');\n localStorage.removeItem('__incognito_test');\n return false;\n } catch {\n return true;\n }\n};\n\nconst isMobile = (): boolean => {\n return /Mobi|Android/i.test(navigator.userAgent);\n};\n\nconst randomId = (prefix?: string | null): string => {\n const id = `${new Date().getTime().toString(36)}${Math.random().toString(36).substring(2, 7)}`;\n if (prefix) {\n return `${prefix}_${id}`;\n }\n return id;\n};\n\nconst hash = (obj: any): string => {\n const json = stableStringify(obj);\n let hash = 0;\n\n for (let i = 0; i < json.length; i++) {\n hash = (hash << 5) - hash + json.charCodeAt(i);\n hash |= 0; // Convert to 32bit integer\n }\n\n return `h${Math.abs(hash)}`;\n};\n\n/**\n * Convert object to stable JSON string (keys sorted)\n */\nconst stableStringify = (obj: any): string => {\n if (obj === null || typeof obj !== 'object') {\n return JSON.stringify(obj);\n }\n\n if (obj instanceof File) {\n // Chỉ serialize các thuộc tính quan trọng của File\n return JSON.stringify({\n __type: 'File',\n name: obj.name,\n size: obj.size,\n type: obj.type,\n lastModified: obj.lastModified,\n });\n }\n\n if (Array.isArray(obj)) {\n return `[${obj.map(stableStringify).join(',')}]`;\n }\n\n const keys = Object.keys(obj).sort();\n const keyValuePairs = keys.map(key => `\"${key}\":${stableStringify(obj[key])}`);\n\n return `{${keyValuePairs.join(',')}}`;\n};\n\n// Hàm `parseQueryParams` dùng để phân tích chuỗi query string (phần sau dấu `?` trên URL)\n// và chuyển đổi nó thành một đối tượng JavaScript với các cặp key-value.\nconst parseQueryParams = (queryString?: string): Record<string, string> => {\n const params = new URLSearchParams(queryString || '');\n const result: Record<string, string> = {};\n params.forEach((value, key) => {\n result[key] = value;\n });\n return result;\n};\n\n/**\n * Lấy địa chỉ IP public của client bằng cách gọi API bên thứ ba.\n */\nconst getClientPublicIp = async (): Promise<string | null> => {\n try {\n // Gọi đến API của ipify để lấy IP dưới dạng JSON\n const response = await fetch('https://api.ipify.org?format=json');\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n const data = await response.json();\n // Trả về địa chỉ IP\n return data.ip;\n } catch (error) {\n console.error('Failed to fetch client IP:', error);\n return null; // Trả về null nếu có lỗi\n }\n};\n\n// Helper function với fallback\nconst generateUuid = (): string => {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n // Fallback cho browser cũ\n return `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\n};\n\n/**\n * Truy xuất giá trị của object dựa trên đường dẫn nested (VD: 'user.address.city')\n */\nconst getNestedValue = (obj: any, path: string) => {\n if (!obj || !path) return undefined;\n // Tách chuỗi theo dấu chấm và duyệt qua từng cấp của object\n return path.split('.').reduce((acc, part) => acc?.[part], obj);\n};\n\n/**\n * @deprecated Use {@link Utilities} and {@link BrowserUtilities} from `@sdcorejs/utils/fns` instead.\n * - upload/download/clipboard/isMobile → BrowserUtilities\n * - allWithPaging (→ fetchAllByPaging) / randomId / hash / parseQueryParams / generateUuid / getNestedValue → Utilities\n */\nconst SdUtilities = {\n upload,\n download,\n downloadBlob,\n changeAliasLowerCase,\n copyToClipboard,\n allWithPaging,\n isIncognito,\n isMobile,\n randomId,\n hash,\n parseQueryParams,\n getClientPublicIp,\n generateUuid,\n getNestedValue,\n};\nexport { SdUtilities };\n","export { ColorUtilities } from '@sdcorejs/utils/fns';\n\nimport { ColorUtilities } from '@sdcorejs/utils/fns';\n/** @deprecated Use {@link ColorUtilities.hslToHex} from `@sdcorejs/utils/fns` instead */\nexport const hslToHex = ColorUtilities.hslToHex;\n/** @deprecated Use {@link ColorUtilities.rgbToHex} from `@sdcorejs/utils/fns` instead */\nexport const rgbToHex = ColorUtilities.rgbToHex;\n","type PlainObject = Record<PropertyKey, unknown>;\n\nconst isPlainObject = (value: unknown): value is PlainObject => {\n if (value === null || typeof value !== 'object') return false;\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n};\n\nconst clone = <T>(value: T): T => {\n if (Array.isArray(value)) {\n return value.map(item => clone(item)) as T;\n }\n if (isPlainObject(value)) {\n return Object.keys(value).reduce((result, key) => {\n result[key] = clone(value[key]);\n return result;\n }, {} as PlainObject) as T;\n }\n return value;\n};\n\nconst merge = <T extends PlainObject, U extends PlainObject>(target: T, source: U): T & U => {\n const result = clone(target) as PlainObject;\n Object.keys(source).forEach(key => {\n const sourceValue = source[key];\n if (sourceValue === undefined) return;\n\n const targetValue = result[key];\n if (isPlainObject(targetValue) && isPlainObject(sourceValue)) {\n result[key] = merge(targetValue, sourceValue);\n } else {\n result[key] = clone(sourceValue);\n }\n });\n return result as T & U;\n};\n\nconst deepMerge = <T extends PlainObject>(...sources: T[]): T =>\n sources.reduce((result, source) => merge(result, source), {} as PlainObject) as T;\n\nexport const ObjectUtilities = {\n isPlainObject,\n clone,\n merge,\n deepMerge,\n};\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["_Utils"],"mappings":"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"}
@@ -11,10 +11,25 @@ const DefaultMaterialIconFontSet = 'material-icons-outlined';
11
11
  const SdPatternCommons = [
12
12
  { type: 'EMAIL', name: 'core.validator.email.name', regex: StringUtilities.REGEX_EMAIL, errorMessage: 'core.validator.email.error' },
13
13
  { type: 'PHONE', name: 'core.validator.phone.name', regex: StringUtilities.REGEX_PHONE, errorMessage: 'core.validator.phone.error' },
14
- { type: 'PHONE_VN', name: 'core.validator.phone-vn.name', regex: StringUtilities.REGEX_VN_PHONE, errorMessage: 'core.validator.phone-vn.error' },
14
+ {
15
+ type: 'PHONE_VN',
16
+ name: 'core.validator.phone-vn.name',
17
+ regex: StringUtilities.REGEX_VN_PHONE,
18
+ errorMessage: 'core.validator.phone-vn.error',
19
+ },
15
20
  { type: 'IDVN', name: 'core.validator.cccd.name', regex: StringUtilities.REGEX_VN_ID, errorMessage: 'core.validator.cccd.error' },
16
- { type: 'PASSPORT', name: 'core.validator.passport.name', regex: StringUtilities.REGEX_PASSPORT, errorMessage: 'core.validator.passport.error' },
17
- { type: 'IDVN_OR_PASSPORT', name: 'core.validator.id-vn.name', regex: StringUtilities.REGEX_VN_ID_OR_PASSPORT, errorMessage: 'core.validator.id-vn.error' },
21
+ {
22
+ type: 'PASSPORT',
23
+ name: 'core.validator.passport.name',
24
+ regex: StringUtilities.REGEX_PASSPORT,
25
+ errorMessage: 'core.validator.passport.error',
26
+ },
27
+ {
28
+ type: 'IDVN_OR_PASSPORT',
29
+ name: 'core.validator.id-vn.name',
30
+ regex: StringUtilities.REGEX_VN_ID_OR_PASSPORT,
31
+ errorMessage: 'core.validator.id-vn.error',
32
+ },
18
33
  { type: 'TIME', name: 'core.validator.time.name', regex: StringUtilities.REGEX_TIME, errorMessage: 'core.validator.time.error' },
19
34
  ];
20
35
 
@@ -1 +1 @@
1
- {"version":3,"file":"sdcorejs-angular-utilities-models.mjs","sources":["../../../projects/sdcorejs-angular/utilities/models/src/icon.model.ts","../../../projects/sdcorejs-angular/utilities/models/src/pattern.model.ts","../../../projects/sdcorejs-angular/utilities/models/src/empty.model.ts","../../../projects/sdcorejs-angular/utilities/models/src/maybe-async.model.ts","../../../projects/sdcorejs-angular/utilities/models/src/operator.model.ts","../../../projects/sdcorejs-angular/utilities/models/sdcorejs-angular-utilities-models.ts"],"sourcesContent":["export type MaterialIconFontSet = 'material-icons' | 'material-icons-outlined' | 'material-icons-round' | 'material-icons-sharp';\nexport const DefaultMaterialIconFontSet: MaterialIconFontSet = 'material-icons-outlined';\n","import type { ValidationPatternType, ValidationPattern } from '@sdcorejs/utils/models';\nimport { VALIDATION_PATTERNS } from '@sdcorejs/utils/constants';\nimport { StringUtilities } from '@sdcorejs/utils/fns';\nexport type { ValidationPatternType, ValidationPattern };\nexport { VALIDATION_PATTERNS };\n\n/**\n * @deprecated Use {@link ValidationPatternType} from `@sdcorejs/utils/models` instead.\n * Note: member names changed — PHONE_VN → VN_PHONE, IDVN → VN_ID, IDVN_OR_PASSPORT → VN_ID_OR_PASSPORT.\n */\nexport type SdPatternType = 'EMAIL' | 'PHONE' | 'PHONE_VN' | 'IDVN' | 'PASSPORT' | 'IDVN_OR_PASSPORT' | 'TIME';\n\n/**\n * @deprecated Use {@link ValidationPattern} from `@sdcorejs/utils/models` instead.\n * Note: `regex` field renamed to `pattern` to align with Angular `Validators.pattern()`.\n */\nexport interface SdPatternCommon {\n type: SdPatternType;\n name: string;\n regex: string;\n errorMessage: string;\n}\n\n// `name` và `errorMessage` chứa i18n KEY (không phải chuỗi đã dịch).\n/** @deprecated Use `VALIDATION_PATTERNS` from `@sdcorejs/utils/constants` instead. */\nexport const SdPatternCommons: SdPatternCommon[] = [\n { type: 'EMAIL', name: 'core.validator.email.name', regex: StringUtilities.REGEX_EMAIL, errorMessage: 'core.validator.email.error' },\n { type: 'PHONE', name: 'core.validator.phone.name', regex: StringUtilities.REGEX_PHONE, errorMessage: 'core.validator.phone.error' },\n { type: 'PHONE_VN', name: 'core.validator.phone-vn.name', regex: StringUtilities.REGEX_VN_PHONE, errorMessage: 'core.validator.phone-vn.error' },\n { type: 'IDVN', name: 'core.validator.cccd.name', regex: StringUtilities.REGEX_VN_ID, errorMessage: 'core.validator.cccd.error' },\n { type: 'PASSPORT', name: 'core.validator.passport.name', regex: StringUtilities.REGEX_PASSPORT, errorMessage: 'core.validator.passport.error' },\n { type: 'IDVN_OR_PASSPORT', name: 'core.validator.id-vn.name', regex: StringUtilities.REGEX_VN_ID_OR_PASSPORT, errorMessage: 'core.validator.id-vn.error' },\n { type: 'TIME', name: 'core.validator.time.name', regex: StringUtilities.REGEX_TIME, errorMessage: 'core.validator.time.error' },\n];\n","import { EMPTY_STR } from '@sdcorejs/utils/constants';\nexport { EMPTY_STR };\n\n/** @deprecated Use {@link EMPTY_STR} from `@sdcorejs/utils/constants` instead */\nexport const SD_EMPTY_STR = EMPTY_STR;\n","import type { MaybeAsync } from '@sdcorejs/utils/models';\nimport { resolveMaybeAsync, normalizeAsync } from '@sdcorejs/utils/models';\nexport type { MaybeAsync };\nexport { resolveMaybeAsync, normalizeAsync };\n\n/** @deprecated Use {@link MaybeAsync} from `@sdcorejs/utils/models` instead */\nexport type SdMaybeAsync<T> = MaybeAsync<T>;\n/** @deprecated Use {@link resolveMaybeAsync} from `@sdcorejs/utils/models` instead */\nexport const SdResolveMaybeAsync = resolveMaybeAsync;\n/** @deprecated Use {@link normalizeAsync} from `@sdcorejs/utils/models` instead */\nexport const SdNormalizeAsync = normalizeAsync;\n","import type { Operator, OperatorHasData, OperatorNoData } from '@sdcorejs/utils/models';\nexport type { Operator, OperatorHasData, OperatorNoData };\n\n/** @deprecated Use {@link Operator} from `@sdcorejs/utils/models` instead */\nexport type SdOperator = Operator;\n/** @deprecated Use {@link OperatorHasData} from `@sdcorejs/utils/models` instead */\nexport type SdOperatorHasData = OperatorHasData;\n/** @deprecated Use {@link OperatorNoData} from `@sdcorejs/utils/models` instead */\nexport type SdOperatorNoData = OperatorNoData;\n\n// `display` chứa i18n KEY (không phải chuỗi đã dịch).\n// Consumer phải gọi i18n.t(display) trước khi render ra UI.\n// @deprecated Use `OPERATORS` from `@sdcorejs/utils/constants` instead.\n// Note: OPERATORS has translated display labels; SdOperators uses i18n keys.\nexport const SdOperators: {\n value: Operator;\n symbol?: string;\n display: string;\n}[] = [\n { value: 'EQUAL', symbol: '=', display: 'core.operator.equal.display' },\n { value: 'NOT_EQUAL', symbol: '≠', display: 'core.operator.not-equal.display' },\n { value: 'GREATER_THAN', symbol: '>', display: 'core.operator.greater-than.display' },\n { value: 'LESS_THAN', symbol: '<', display: 'core.operator.less-than.display' },\n { value: 'GREATER_OR_EQUAL', symbol: '≥', display: 'core.operator.greater-or-equal.display' },\n { value: 'LESS_OR_EQUAL', symbol: '≤', display: 'core.operator.less-or-equal.display' },\n { value: 'CONTAIN', symbol: 'join_inner', display: 'core.operator.contain.display' },\n { value: 'NOT_CONTAIN', symbol: 'join', display: 'core.operator.not-contain.display' },\n { value: 'START_WITH', symbol: 'line_start_circle', display: 'core.operator.start-with.display' },\n { value: 'END_WITH', symbol: 'line_end_circle', display: 'core.operator.end-with.display' },\n { value: 'IN', symbol: 'checklist_rtl', display: 'core.operator.in.display' },\n { value: 'NOT_IN', symbol: 'event_list', display: 'core.operator.not-in.display' },\n { value: 'NULL', symbol: 'motion_photos_off', display: 'core.operator.null.display' },\n { value: 'NOT_NULL', symbol: 'adjust', display: 'core.operator.not-null.display' },\n];\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sdcorejs-angular-utilities-models.mjs","sources":["../../../projects/sdcorejs-angular/utilities/models/src/icon.model.ts","../../../projects/sdcorejs-angular/utilities/models/src/pattern.model.ts","../../../projects/sdcorejs-angular/utilities/models/src/empty.model.ts","../../../projects/sdcorejs-angular/utilities/models/src/maybe-async.model.ts","../../../projects/sdcorejs-angular/utilities/models/src/operator.model.ts","../../../projects/sdcorejs-angular/utilities/models/sdcorejs-angular-utilities-models.ts"],"sourcesContent":["export type MaterialIconFontSet = 'material-icons' | 'material-icons-outlined' | 'material-icons-round' | 'material-icons-sharp';\nexport const DefaultMaterialIconFontSet: MaterialIconFontSet = 'material-icons-outlined';\n","import type { ValidationPatternType, ValidationPattern } from '@sdcorejs/utils/models';\nimport { VALIDATION_PATTERNS } from '@sdcorejs/utils/constants';\nimport { StringUtilities } from '@sdcorejs/utils/fns';\nexport type { ValidationPatternType, ValidationPattern };\nexport { VALIDATION_PATTERNS };\n\n/**\n * @deprecated Use {@link ValidationPatternType} from `@sdcorejs/utils/models` instead.\n * Note: member names changed — PHONE_VN → VN_PHONE, IDVN → VN_ID, IDVN_OR_PASSPORT → VN_ID_OR_PASSPORT.\n */\nexport type SdPatternType = 'EMAIL' | 'PHONE' | 'PHONE_VN' | 'IDVN' | 'PASSPORT' | 'IDVN_OR_PASSPORT' | 'TIME';\n\n/**\n * @deprecated Use {@link ValidationPattern} from `@sdcorejs/utils/models` instead.\n * Note: `regex` field renamed to `pattern` to align with Angular `Validators.pattern()`.\n */\nexport interface SdPatternCommon {\n type: SdPatternType;\n name: string;\n regex: string;\n errorMessage: string;\n}\n\n// `name` và `errorMessage` chứa i18n KEY (không phải chuỗi đã dịch).\n/** @deprecated Use `VALIDATION_PATTERNS` from `@sdcorejs/utils/constants` instead. */\nexport const SdPatternCommons: SdPatternCommon[] = [\n { type: 'EMAIL', name: 'core.validator.email.name', regex: StringUtilities.REGEX_EMAIL, errorMessage: 'core.validator.email.error' },\n { type: 'PHONE', name: 'core.validator.phone.name', regex: StringUtilities.REGEX_PHONE, errorMessage: 'core.validator.phone.error' },\n {\n type: 'PHONE_VN',\n name: 'core.validator.phone-vn.name',\n regex: StringUtilities.REGEX_VN_PHONE,\n errorMessage: 'core.validator.phone-vn.error',\n },\n { type: 'IDVN', name: 'core.validator.cccd.name', regex: StringUtilities.REGEX_VN_ID, errorMessage: 'core.validator.cccd.error' },\n {\n type: 'PASSPORT',\n name: 'core.validator.passport.name',\n regex: StringUtilities.REGEX_PASSPORT,\n errorMessage: 'core.validator.passport.error',\n },\n {\n type: 'IDVN_OR_PASSPORT',\n name: 'core.validator.id-vn.name',\n regex: StringUtilities.REGEX_VN_ID_OR_PASSPORT,\n errorMessage: 'core.validator.id-vn.error',\n },\n { type: 'TIME', name: 'core.validator.time.name', regex: StringUtilities.REGEX_TIME, errorMessage: 'core.validator.time.error' },\n];\n","import { EMPTY_STR } from '@sdcorejs/utils/constants';\nexport { EMPTY_STR };\n\n/** @deprecated Use {@link EMPTY_STR} from `@sdcorejs/utils/constants` instead */\nexport const SD_EMPTY_STR = EMPTY_STR;\n","import type { MaybeAsync } from '@sdcorejs/utils/models';\nimport { resolveMaybeAsync, normalizeAsync } from '@sdcorejs/utils/models';\nexport type { MaybeAsync };\nexport { resolveMaybeAsync, normalizeAsync };\n\n/** @deprecated Use {@link MaybeAsync} from `@sdcorejs/utils/models` instead */\nexport type SdMaybeAsync<T> = MaybeAsync<T>;\n/** @deprecated Use {@link resolveMaybeAsync} from `@sdcorejs/utils/models` instead */\nexport const SdResolveMaybeAsync = resolveMaybeAsync;\n/** @deprecated Use {@link normalizeAsync} from `@sdcorejs/utils/models` instead */\nexport const SdNormalizeAsync = normalizeAsync;\n","import type { Operator, OperatorHasData, OperatorNoData } from '@sdcorejs/utils/models';\nexport type { Operator, OperatorHasData, OperatorNoData };\n\n/** @deprecated Use {@link Operator} from `@sdcorejs/utils/models` instead */\nexport type SdOperator = Operator;\n/** @deprecated Use {@link OperatorHasData} from `@sdcorejs/utils/models` instead */\nexport type SdOperatorHasData = OperatorHasData;\n/** @deprecated Use {@link OperatorNoData} from `@sdcorejs/utils/models` instead */\nexport type SdOperatorNoData = OperatorNoData;\n\n// `display` chứa i18n KEY (không phải chuỗi đã dịch).\n// Consumer phải gọi i18n.t(display) trước khi render ra UI.\n// @deprecated Use `OPERATORS` from `@sdcorejs/utils/constants` instead.\n// Note: OPERATORS has translated display labels; SdOperators uses i18n keys.\nexport const SdOperators: {\n value: Operator;\n symbol?: string;\n display: string;\n}[] = [\n { value: 'EQUAL', symbol: '=', display: 'core.operator.equal.display' },\n { value: 'NOT_EQUAL', symbol: '≠', display: 'core.operator.not-equal.display' },\n { value: 'GREATER_THAN', symbol: '>', display: 'core.operator.greater-than.display' },\n { value: 'LESS_THAN', symbol: '<', display: 'core.operator.less-than.display' },\n { value: 'GREATER_OR_EQUAL', symbol: '≥', display: 'core.operator.greater-or-equal.display' },\n { value: 'LESS_OR_EQUAL', symbol: '≤', display: 'core.operator.less-or-equal.display' },\n { value: 'CONTAIN', symbol: 'join_inner', display: 'core.operator.contain.display' },\n { value: 'NOT_CONTAIN', symbol: 'join', display: 'core.operator.not-contain.display' },\n { value: 'START_WITH', symbol: 'line_start_circle', display: 'core.operator.start-with.display' },\n { value: 'END_WITH', symbol: 'line_end_circle', display: 'core.operator.end-with.display' },\n { value: 'IN', symbol: 'checklist_rtl', display: 'core.operator.in.display' },\n { value: 'NOT_IN', symbol: 'event_list', display: 'core.operator.not-in.display' },\n { value: 'NULL', symbol: 'motion_photos_off', display: 'core.operator.null.display' },\n { value: 'NOT_NULL', symbol: 'adjust', display: 'core.operator.not-null.display' },\n];\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"sdcorejs-angular.mjs","sources":["../../../projects/sdcorejs-angular/src/public-api.ts","../../../projects/sdcorejs-angular/src/sdcorejs-angular.ts"],"sourcesContent":["/*\n * Public API Surface of sd-angular\n */\nimport '@sdcorejs/angular/configurations';\nimport '@sdcorejs/angular/utilities';\nimport '@sdcorejs/angular/pipes';\nimport '@sdcorejs/angular/directives';\nimport '@sdcorejs/angular/services';\nimport '@sdcorejs/angular/interceptors';\nimport '@sdcorejs/angular/handlers';\nimport '@sdcorejs/angular/components';\nimport '@sdcorejs/angular/forms';\nimport '@sdcorejs/angular/modules';","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;;;;;;;;AAAA;;AAEG;;ACFH;;AAEG"}
1
+ {"version":3,"file":"sdcorejs-angular.mjs","sources":["../../../projects/sdcorejs-angular/src/public-api.ts","../../../projects/sdcorejs-angular/src/sdcorejs-angular.ts"],"sourcesContent":["/*\n * Public API Surface of sd-angular\n */\nimport '@sdcorejs/angular/configurations';\nimport '@sdcorejs/angular/utilities';\nimport '@sdcorejs/angular/pipes';\nimport '@sdcorejs/angular/directives';\nimport '@sdcorejs/angular/services';\nimport '@sdcorejs/angular/interceptors';\nimport '@sdcorejs/angular/handlers';\nimport '@sdcorejs/angular/components';\nimport '@sdcorejs/angular/forms';\nimport '@sdcorejs/angular/modules';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;;;;;;;;AAAA;;AAEG;;ACFH;;AAEG"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sdcorejs/angular",
3
- "version": "21.0.9",
3
+ "version": "21.0.10",
4
4
  "license": "MIT",
5
5
  "peerDependencies": {
6
6
  "@angular/common": "^19.0.0 || ^20.0.0 || ^21.0.0",
@@ -9,7 +9,7 @@
9
9
  "@angular/material-date-fns-adapter": "^19.0.0 || ^20.0.0 || ^21.0.0"
10
10
  },
11
11
  "dependencies": {
12
- "@sdcorejs/utils": "^1.1.3",
12
+ "@sdcorejs/utils": "1.1.4",
13
13
  "@ckeditor/ckeditor5-angular": "11.1.2",
14
14
  "@omer-go/docx-parser-converter-ts": "^1.0.0",
15
15
  "@bjorn3/browser_wasi_shim": "^0.4.2",
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { EventEmitter } from '@angular/core';
2
+ import { EventEmitter, OnInit, OnDestroy } from '@angular/core';
3
3
  import { ModelRange, EditorConfig, ModelDocumentSelection, EventInfo, ViewDataTransfer, ClassicEditor, Plugin, Widget, ContextualBalloon } from 'ckeditor5';
4
4
  import { I18nParams } from '@sdcorejs/angular/i18n';
5
5
 
@@ -199,7 +199,7 @@ declare class CkCommentPlugin extends Plugin {
199
199
  clearPendingSelection(): void;
200
200
  }
201
201
 
202
- declare class SdDocumentBuilder {
202
+ declare class SdDocumentBuilder implements OnInit, OnDestroy {
203
203
  #private;
204
204
  option: SdDocumentBuilderOption;
205
205
  disabled: boolean;
@@ -1,11 +1,11 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, PipeTransform, OnDestroy, ChangeDetectorRef, AfterViewInit, QueryList, EventEmitter } from '@angular/core';
2
+ import { InjectionToken, PipeTransform, OnDestroy, OnInit, ChangeDetectorRef, AfterViewInit, QueryList, EventEmitter } from '@angular/core';
3
3
  import { SdSearch, SdCustomValidator } from '@sdcorejs/angular/forms/models';
4
4
  import { SdTableColumn, SdTableOption, SdTable } from '@sdcorejs/angular/components/table';
5
5
  import { SdUploadFile } from '@sdcorejs/angular/components/upload-file';
6
6
  import { Operator as Operator$1, ValidationPatternType, Color } from '@sdcorejs/utils/models';
7
7
  import { SdUnwrapSignal } from '@sdcorejs/angular/utilities/models';
8
- import { CdkDragMove, CdkDragDrop } from '@angular/cdk/drag-drop';
8
+ import { CdkDragMove, CdkDragDrop, CdkDrag, CdkDropList } from '@angular/cdk/drag-drop';
9
9
  import { FormGroup } from '@angular/forms';
10
10
  import { SdModal } from '@sdcorejs/angular/components/modal';
11
11
  import { Subject } from 'rxjs';
@@ -458,14 +458,14 @@ interface SdFormGenericHtml {
458
458
  type FormBuilderComponentGroup = 'basic' | 'choice' | 'advanced' | 'layout';
459
459
  interface FormBuilderComponent {
460
460
  type: string;
461
- /** Material Symbols Rounded icon name. Rendered via <span class="msi">{symbol}</span>. */
461
+ /** Material Icons Outlined icon name. Rendered via the builder icon alias. */
462
462
  symbol: string;
463
463
  /** Category group for the left palette grouping. */
464
464
  group: FormBuilderComponentGroup;
465
465
  name: string;
466
466
  }
467
467
  declare const FormBuilderComponents: FormBuilderComponent[];
468
- /** Lookup: component type → Material Symbol + label, used by attribute panel header. */
468
+ /** Lookup: component type → Material icon + label, used by attribute panel header. */
469
469
  declare const COMPONENT_ICONS: Record<string, {
470
470
  symbol: string;
471
471
  label: string;
@@ -530,7 +530,7 @@ interface IWorkflowConfigurationForm<TSelectionArgs = any> {
530
530
  templates: SdFormGenericTemplate[];
531
531
  selections: SdFormGenericDefinitionSelection<any, TSelectionArgs>[] | (() => SdFormGenericDefinitionSelection<any, TSelectionArgs>[]) | (() => Promise<SdFormGenericDefinitionSelection[]>);
532
532
  getValues?: (key: string, selectionArgs?: TSelectionArgs) => Promise<SdFormGenericSelectionItem[]>;
533
- getLazyValues?: (key: string, selectionArgs?: TSelectionArgs) => ((searchArgs: Parameters<SdSearch>[0], args: SdFormGenericArgs) => Promise<SdFormGenericSelectionItem[]>);
533
+ getLazyValues?: (key: string, selectionArgs?: TSelectionArgs) => (searchArgs: Parameters<SdSearch>[0], args: SdFormGenericArgs) => Promise<SdFormGenericSelectionItem[]>;
534
534
  tables: SdFormGenericDefinitionTable[];
535
535
  htmls: SdFormGenericDefinitionHtml[] | (() => SdFormGenericDefinitionHtml[]) | (() => Promise<SdFormGenericDefinitionHtml[]>);
536
536
  validation?: SdFormGenericValidationConfiguration;
@@ -544,7 +544,6 @@ declare const SD_FORM_GENERIC_CONFIGURATION: InjectionToken<ISdFormGenericConfig
544
544
  declare class FormGenericService {
545
545
  #private;
546
546
  private readonly configuration;
547
- constructor(configuration: ISdFormGenericConfiguration);
548
547
  get selections(): (() => Promise<SdFormGenericDefinitionSelection[]>) | SdFormGenericDefinitionSelection<any, any>[] | (() => SdFormGenericDefinitionSelection<any, any>[]);
549
548
  get tables(): _sdcorejs_angular_components_form_generic.SdFormGenericDefinitionTable<any>[];
550
549
  getSelection: (valuesKey: string | undefined | null) => Promise<SdFormGenericDefinitionSelection | undefined>;
@@ -560,7 +559,7 @@ declare class FormGenericService {
560
559
  definitions: () => Promise<SdFormGenericDefinitionHtml[]>;
561
560
  getContent: (template: string, query?: Record<string, any>) => Promise<string>;
562
561
  };
563
- static ɵfac: i0.ɵɵFactoryDeclaration<FormGenericService, [{ optional: true; }]>;
562
+ static ɵfac: i0.ɵɵFactoryDeclaration<FormGenericService, never>;
564
563
  static ɵprov: i0.ɵɵInjectableDeclaration<FormGenericService>;
565
564
  }
566
565
 
@@ -590,7 +589,7 @@ declare class SdFormRenderService {
590
589
  static ɵprov: i0.ɵɵInjectableDeclaration<SdFormRenderService>;
591
590
  }
592
591
 
593
- declare class UploadComponent implements OnDestroy {
592
+ declare class UploadComponent implements OnDestroy, OnInit {
594
593
  #private;
595
594
  private readonly ref;
596
595
  setVariables: Subject<{
@@ -620,7 +619,7 @@ declare class UploadComponent implements OnDestroy {
620
619
  static ɵcmp: i0.ɵɵComponentDeclaration<UploadComponent, "lib-upload", never, { "setVariables": { "alias": "setVariables"; "required": true; }; "form": { "alias": "form"; "required": false; }; "_entity": { "alias": "entity"; "required": true; }; "_component": { "alias": "component"; "required": true; }; "_disabled": { "alias": "disabled"; "required": false; }; "_required": { "alias": "required"; "required": false; }; "_viewed": { "alias": "viewed"; "required": false; }; "_validator": { "alias": "validator"; "required": false; }; }, {}, never, never, true, never>;
621
620
  }
622
621
 
623
- declare class TableComponent implements AfterViewInit, OnDestroy {
622
+ declare class TableComponent implements AfterViewInit, OnDestroy, OnInit {
624
623
  #private;
625
624
  private ref;
626
625
  private readonly formGenericService;
@@ -691,8 +690,6 @@ declare class LibItemComponent {
691
690
 
692
691
  declare class SdFormRender implements OnDestroy, AfterViewInit {
693
692
  #private;
694
- private ref;
695
- private formGenericConfiguration;
696
693
  formRenderItems: QueryList<LibItemComponent>;
697
694
  form: FormGroup;
698
695
  configuration: SdFormRenderConfiguration;
@@ -711,18 +708,17 @@ declare class SdFormRender implements OnDestroy, AfterViewInit {
711
708
  key: string;
712
709
  value: any;
713
710
  }>;
714
- constructor(ref: ChangeDetectorRef, formGenericConfiguration: ISdFormGenericConfiguration | null);
711
+ private readonly ref;
712
+ private readonly formGenericConfiguration;
715
713
  ngAfterViewInit(): void;
716
714
  ngOnDestroy(): void;
717
715
  upload: () => Promise<void>;
718
716
  getValidationMessages: (alert: SdFormGenericValidation["alert"]) => Promise<string[] | undefined>;
719
- static ɵfac: i0.ɵɵFactoryDeclaration<SdFormRender, [null, { optional: true; }]>;
717
+ static ɵfac: i0.ɵɵFactoryDeclaration<SdFormRender, never>;
720
718
  static ɵcmp: i0.ɵɵComponentDeclaration<SdFormRender, "sd-form-render", never, { "form": { "alias": "form"; "required": false; }; "_configuration": { "alias": "configuration"; "required": true; }; "_default": { "alias": "defaultEntity"; "required": false; }; "_entity": { "alias": "entity"; "required": false; }; "_properties": { "alias": "properties"; "required": false; }; "_viewed": { "alias": "viewed"; "required": false; }; }, {}, never, never, true, never>;
721
719
  }
722
720
 
723
- declare class ConfigureValidationComponent {
724
- private ref;
725
- private formGenericConfiguration;
721
+ declare class ConfigureValidationComponent implements AfterViewInit, OnDestroy {
726
722
  modal?: SdModal;
727
723
  form: FormGroup<{}>;
728
724
  attributes: Attribute[];
@@ -733,22 +729,35 @@ declare class ConfigureValidationComponent {
733
729
  display: string;
734
730
  }[];
735
731
  accept: EventEmitter<SdFormGenericValidation[]>;
736
- constructor(ref: ChangeDetectorRef, formGenericConfiguration: ISdFormGenericConfiguration | null);
732
+ private readonly ref;
733
+ private readonly formGenericConfiguration;
734
+ constructor();
737
735
  ngAfterViewInit(): void;
738
736
  ngOnDestroy(): void;
739
737
  open: (formGeneric: SdFormGeneric) => void;
740
738
  addValidation: (type: SdFormGenericValidation["type"]) => void;
741
739
  removaValidation: (index: number) => void;
742
740
  updateValidations: () => void;
743
- static ɵfac: i0.ɵɵFactoryDeclaration<ConfigureValidationComponent, [null, { optional: true; }]>;
741
+ static ɵfac: i0.ɵɵFactoryDeclaration<ConfigureValidationComponent, never>;
744
742
  static ɵcmp: i0.ɵɵComponentDeclaration<ConfigureValidationComponent, "configure-validation", never, {}, { "accept": "accept"; }, never, never, true, never>;
745
743
  }
746
744
 
747
- interface DragDropRowItem {
748
- items: (SdFormGenericComponent | SdFormGenericGroup)[];
745
+ type FormBuilderLayoutItem = SdFormGenericComponent | SdFormGenericGroup;
746
+ interface FormBuilderLayoutRow {
747
+ id: string;
748
+ items: FormBuilderLayoutItem[];
749
+ columns: number;
750
+ }
751
+
752
+ interface DragDropRowItem extends FormBuilderLayoutRow {
749
753
  rowIndex?: number;
750
754
  }
751
- declare class SdFormBuilder {
755
+ interface ResizeState {
756
+ itemId: string;
757
+ rowId: string;
758
+ columns: string;
759
+ }
760
+ declare class SdFormBuilder implements OnInit, OnDestroy {
752
761
  #private;
753
762
  readonly popupViewJSON: i0.Signal<SdModal | undefined>;
754
763
  readonly popupConfigureVariables: i0.Signal<SdModal | undefined>;
@@ -781,6 +790,9 @@ declare class SdFormBuilder {
781
790
  /** Signal toàn cục: TRUE khi BẤT KỲ cdkDrag nào đang active (palette, canvas, group, resize).
782
791
  * Trigger class `.fb-shell--dragging` để ẩn hover/actions/resize toàn diện, không phụ thuộc :has(). */
783
792
  readonly isAnyDragging: i0.WritableSignal<boolean>;
793
+ readonly dragSource: i0.WritableSignal<"row" | "palette" | "canvas" | "resize" | undefined>;
794
+ readonly resizeState: i0.WritableSignal<ResizeState | undefined>;
795
+ readonly isResizing: i0.Signal<boolean>;
784
796
  expand: boolean;
785
797
  dragDropRows: DragDropRowItem[];
786
798
  isDragging: boolean;
@@ -788,18 +800,25 @@ declare class SdFormBuilder {
788
800
  private lastDragPointer?;
789
801
  /** Handler chung cho mọi cdkDragStarted — set signal global true. */
790
802
  onAnyDragStarted: () => void;
803
+ onPaletteDragStarted: () => void;
804
+ onRowDragStarted: () => void;
791
805
  onAnyDragMoved: (event: CdkDragMove<any>) => void;
792
806
  /** Handler chung cho mọi cdkDragEnded — set signal global false (dùng setTimeout 0
793
807
  * để chờ CDK xử lý xong drop event trước khi UI re-enable). */
794
808
  onAnyDragEnded: () => void;
809
+ startResizeControl: (item: SdFormGenericComponent | SdFormGenericGroup, row: DragDropRowItem) => void;
810
+ endResizeControl: (event: any) => void;
795
811
  constructor();
796
812
  ngOnInit(): void;
797
813
  ngOnDestroy(): void;
798
- addComponent: (item: FormBuilderComponent, index?: number) => void;
814
+ addComponent: (item: FormBuilderComponent, index?: number, layoutColumns?: string) => void;
799
815
  /** Symbol Material để render trên canvas item / attribute header. */
800
816
  symbolFor: (item: SdFormGenericComponent | SdFormGenericGroup) => string;
801
817
  /** Human-readable type label (e.g. "Text field", "Date"). */
802
818
  typeLabelFor: (item: SdFormGenericComponent | SdFormGenericGroup) => string;
819
+ placeholderSymbolFor: (item: FormBuilderComponent | SdFormGenericComponent | SdFormGenericGroup | DragDropRowItem | undefined) => string;
820
+ placeholderTitleFor: (item: FormBuilderComponent | SdFormGenericComponent | SdFormGenericGroup | DragDropRowItem | undefined) => string;
821
+ placeholderMetaFor: (item: FormBuilderComponent | SdFormGenericComponent | SdFormGenericGroup | DragDropRowItem | undefined) => string;
803
822
  /** True nếu component có expression điều kiện — drives the "conditional" status chip. */
804
823
  hasConditional: (item: SdFormGenericComponent | SdFormGenericGroup) => boolean;
805
824
  /** Map SdColor preset → 2 CSS var names cho header-bg và header-fg của group card. */
@@ -828,6 +847,9 @@ declare class SdFormBuilder {
828
847
  dragStartComponentItem: (event: any) => void;
829
848
  dragEndComponentItem: (event: any) => void;
830
849
  onMouseover: (event: MouseEvent, rowItem: DragDropRowItem) => void;
850
+ isRowFull: (row: DragDropRowItem) => boolean;
851
+ isRowInlineDropLocked: (row: DragDropRowItem) => boolean;
852
+ canEnterRowDropList: (drag: CdkDrag<FormBuilderComponent | SdFormGenericComponent | SdFormGenericGroup>, drop: CdkDropList<(SdFormGenericComponent | SdFormGenericGroup)[]>) => boolean;
831
853
  onFocus: (event: FocusEvent) => void;
832
854
  xuLyKeoCheo: (dragItem?: SdFormGenericComponent | SdFormGenericGroup) => void;
833
855
  noReturnPredicate: () => boolean;
@@ -853,7 +875,7 @@ declare class SdFormBuilder {
853
875
  static ɵcmp: i0.ɵɵComponentDeclaration<SdFormBuilder, "sd-form-builder", never, { "formGeneric": { "alias": "formGeneric"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
854
876
  }
855
877
 
856
- declare class SdFeelExpression {
878
+ declare class SdFeelExpression implements OnInit {
857
879
  #private;
858
880
  private ref;
859
881
  private expressionFeelPipe;
@@ -97,7 +97,7 @@ interface SdUploadExcelColumnStringArray<T = any> extends SdUploadExcelBaseColum
97
97
  minlength?: number;
98
98
  maxlength?: number;
99
99
  }
100
- type SdImportExcelItem<T = any> = {
100
+ interface SdImportExcelItem<T = any> {
101
101
  data: T;
102
102
  meta: {
103
103
  excelIndex: number;
@@ -107,7 +107,7 @@ type SdImportExcelItem<T = any> = {
107
107
  warning: Record<string, string>;
108
108
  warningMessages: string[];
109
109
  };
110
- };
110
+ }
111
111
 
112
112
  declare class ColumnHiddenPipe implements PipeTransform {
113
113
  constructor();
@@ -1,7 +1,7 @@
1
1
  import { MentionFeed, MentionFeedObjectItem, EditorConfig, ClassicEditor } from 'ckeditor5';
2
2
  export { MentionFeedObjectItem } from 'ckeditor5';
3
3
  import * as i0 from '@angular/core';
4
- import { EventEmitter } from '@angular/core';
4
+ import { OnDestroy, EventEmitter } from '@angular/core';
5
5
  import { ControlValueAccessor } from '@angular/forms';
6
6
 
7
7
  type SdMiniEditorOutputFormat = 'html' | 'markdown';
@@ -62,7 +62,7 @@ type SdMiniEditorConfig = EditorConfig & {
62
62
  * </sd-mini-editor>
63
63
  * ```
64
64
  */
65
- declare class SdMiniEditor implements ControlValueAccessor {
65
+ declare class SdMiniEditor implements ControlValueAccessor, OnDestroy {
66
66
  #private;
67
67
  /** Cấu hình option cho editor */
68
68
  option: SdMiniEditorOption;
@@ -113,11 +113,11 @@ declare class SdMiniEditor implements ControlValueAccessor {
113
113
  /**
114
114
  * Get danh sách mentions trong nội dung
115
115
  */
116
- getMentions(): Array<{
116
+ getMentions(): {
117
117
  id: string;
118
118
  name: string;
119
119
  marker: string;
120
- }>;
120
+ }[];
121
121
  /**
122
122
  * ControlValueAccessor: Write value
123
123
  */
@@ -16,7 +16,7 @@ declare class SdModal {
16
16
  width: _angular_core.InputSignalWithTransform<string, string | null | undefined>;
17
17
  height: _angular_core.InputSignalWithTransform<string, string | null | undefined>;
18
18
  view: _angular_core.InputSignalWithTransform<"dialog" | "bottom-sheet" | undefined, "dialog" | "bottom-sheet" | null | undefined>;
19
- modalClass: _angular_core.InputSignalWithTransform<string | string[] | Record<string, boolean>, string | string[] | Record<string, boolean> | null | undefined>;
19
+ modalClass: _angular_core.InputSignalWithTransform<string | Record<string, boolean> | string[], string | Record<string, boolean> | string[] | null | undefined>;
20
20
  lazyLoadContent: _angular_core.InputSignalWithTransform<boolean, unknown>;
21
21
  hideClose: _angular_core.InputSignalWithTransform<boolean, boolean | "">;
22
22
  disableBackdropClose: _angular_core.InputSignalWithTransform<boolean, boolean | "">;