@africanies/angular-web-sdk 0.1.11 → 0.1.12

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 (93) hide show
  1. package/.nx/cache/{14995846848874973576 → 7821397806208783174}/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs +2572 -962
  2. package/.nx/cache/7821397806208783174/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs.map +1 -0
  3. package/.nx/cache/{14995846848874973576 → 7821397806208783174}/dist/libs/africanies-ui/types/africanies-africanies-ui.d.ts +450 -140
  4. package/.nx/cache/run.json +15 -15
  5. package/.nx/cache/terminalOutputs/16208231681037145050 +85 -0
  6. package/.nx/cache/terminalOutputs/{14995846848874973576 → 7821397806208783174} +2 -2
  7. package/.nx/workspace-data/0091ABA9-5C90-580D-953C-8C94E763ADB5-v3.db +0 -0
  8. package/.nx/workspace-data/0091ABA9-5C90-580D-953C-8C94E763ADB5-v3.db-shm +0 -0
  9. package/.nx/workspace-data/0091ABA9-5C90-580D-953C-8C94E763ADB5-v3.db-wal +0 -0
  10. package/.nx/workspace-data/d/daemon.log +1317 -0
  11. package/.nx/workspace-data/d/server-process.json +2 -2
  12. package/.nx/workspace-data/file-map.json +3458 -3424
  13. package/.nx/workspace-data/nx_files.nxt +0 -0
  14. package/.nx/workspace-data/project-graph.json +2 -2
  15. package/apps/playground/src/app/pages/forms-page.ts +70 -14
  16. package/apps/playground/src/app/snippets/forms.snippets.ts +41 -6
  17. package/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs +1000 -8
  18. package/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs.map +1 -1
  19. package/dist/libs/africanies-ui/types/africanies-africanies-ui.d.ts +201 -15
  20. package/libs/africanies-ui/src/index.ts +18 -0
  21. package/libs/africanies-ui/src/lib/forms/index.ts +20 -0
  22. package/libs/africanies-ui/src/lib/forms/phone-input/index.ts +21 -0
  23. package/libs/africanies-ui/src/lib/forms/phone-input/phone-codes.ts +264 -0
  24. package/libs/africanies-ui/src/lib/forms/phone-input/phone-input.component.ts +477 -0
  25. package/libs/africanies-ui/src/lib/forms/phone-input/phone-input.types.ts +35 -0
  26. package/libs/africanies-ui/src/lib/forms/phone-input/phone-input.utils.spec.ts +81 -0
  27. package/libs/africanies-ui/src/lib/forms/phone-input/phone-input.utils.ts +275 -0
  28. package/libs/africanies-ui/src/lib/modules/africanies-forms.module.ts +2 -0
  29. package/libs/africanies-ui/src/lib/navigation/segment/segment.component.ts +2 -1
  30. package/package.json +1 -1
  31. package/.nx/cache/13466509747676776487/dist/libs/africanies-core/README.md +0 -85
  32. package/.nx/cache/13466509747676776487/dist/libs/africanies-core/fesm2022/africanies-africanies-core.mjs +0 -4634
  33. package/.nx/cache/13466509747676776487/dist/libs/africanies-core/fesm2022/africanies-africanies-core.mjs.map +0 -1
  34. package/.nx/cache/13466509747676776487/dist/libs/africanies-core/package.json +0 -31
  35. package/.nx/cache/13466509747676776487/dist/libs/africanies-core/types/africanies-africanies-core.d.ts +0 -2743
  36. package/.nx/cache/14416694322692463866/dist/libs/africanies-models/README.md +0 -60
  37. package/.nx/cache/14416694322692463866/dist/libs/africanies-models/fesm2022/africanies-africanies-models.mjs +0 -599
  38. package/.nx/cache/14416694322692463866/dist/libs/africanies-models/fesm2022/africanies-africanies-models.mjs.map +0 -1
  39. package/.nx/cache/14416694322692463866/dist/libs/africanies-models/package.json +0 -23
  40. package/.nx/cache/14416694322692463866/dist/libs/africanies-models/types/africanies-africanies-models.d.ts +0 -1452
  41. package/.nx/cache/14876618240301288353/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs +0 -19375
  42. package/.nx/cache/14876618240301288353/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs.map +0 -1
  43. package/.nx/cache/14876618240301288353/dist/libs/africanies-ui/types/africanies-africanies-ui.d.ts +0 -5490
  44. package/.nx/cache/14995846848874973576/dist/libs/africanies-ui/README.md +0 -68
  45. package/.nx/cache/14995846848874973576/dist/libs/africanies-ui/assets/brand/africanies-logo-mini.png +0 -0
  46. package/.nx/cache/14995846848874973576/dist/libs/africanies-ui/assets/brand/africanies-logo.png +0 -0
  47. package/.nx/cache/14995846848874973576/dist/libs/africanies-ui/assets/brand/africanies-logo.svg +0 -5
  48. package/.nx/cache/14995846848874973576/dist/libs/africanies-ui/assets/carriers/dhl.svg +0 -7
  49. package/.nx/cache/14995846848874973576/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs.map +0 -1
  50. package/.nx/cache/14995846848874973576/dist/libs/africanies-ui/package.json +0 -35
  51. package/.nx/cache/17626862048742598274/dist/libs/africanies-theme/README.md +0 -46
  52. package/.nx/cache/17626862048742598274/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs +0 -221
  53. package/.nx/cache/17626862048742598274/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs.map +0 -1
  54. package/.nx/cache/17626862048742598274/dist/libs/africanies-theme/package.json +0 -35
  55. package/.nx/cache/17626862048742598274/dist/libs/africanies-theme/tailwind-preset.cjs +0 -253
  56. package/.nx/cache/17626862048742598274/dist/libs/africanies-theme/types/africanies-africanies-theme.d.ts +0 -166
  57. package/.nx/cache/6664915487114632770/dist/libs/africanies-icons/README.md +0 -69
  58. package/.nx/cache/6664915487114632770/dist/libs/africanies-icons/assets/icons.sprite.svg +0 -1844
  59. package/.nx/cache/6664915487114632770/dist/libs/africanies-icons/fesm2022/africanies-africanies-icons.mjs +0 -832
  60. package/.nx/cache/6664915487114632770/dist/libs/africanies-icons/fesm2022/africanies-africanies-icons.mjs.map +0 -1
  61. package/.nx/cache/6664915487114632770/dist/libs/africanies-icons/package.json +0 -30
  62. package/.nx/cache/6664915487114632770/dist/libs/africanies-icons/types/africanies-africanies-icons.d.ts +0 -108
  63. package/.nx/cache/6673686859704879504/dist/libs/africanies-theme/README.md +0 -46
  64. package/.nx/cache/6673686859704879504/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs +0 -231
  65. package/.nx/cache/6673686859704879504/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs.map +0 -1
  66. package/.nx/cache/6673686859704879504/dist/libs/africanies-theme/package.json +0 -35
  67. package/.nx/cache/6673686859704879504/dist/libs/africanies-theme/tailwind-preset.cjs +0 -262
  68. package/.nx/cache/6673686859704879504/dist/libs/africanies-theme/types/africanies-africanies-theme.d.ts +0 -174
  69. package/.nx/cache/9040451482998546630/dist/libs/africanies-core/README.md +0 -85
  70. package/.nx/cache/9040451482998546630/dist/libs/africanies-core/fesm2022/africanies-africanies-core.mjs +0 -4511
  71. package/.nx/cache/9040451482998546630/dist/libs/africanies-core/fesm2022/africanies-africanies-core.mjs.map +0 -1
  72. package/.nx/cache/9040451482998546630/dist/libs/africanies-core/package.json +0 -31
  73. package/.nx/cache/9040451482998546630/dist/libs/africanies-core/types/africanies-africanies-core.d.ts +0 -2741
  74. package/.nx/cache/terminalOutputs/13466509747676776487 +0 -21
  75. package/.nx/cache/terminalOutputs/13555699813138069787 +0 -6
  76. package/.nx/cache/terminalOutputs/14061940909886036014 +0 -173
  77. package/.nx/cache/terminalOutputs/14416694322692463866 +0 -108
  78. package/.nx/cache/terminalOutputs/1446890025183346611 +0 -32
  79. package/.nx/cache/terminalOutputs/14876618240301288353 +0 -21
  80. package/.nx/cache/terminalOutputs/17394769338046050914 +0 -8
  81. package/.nx/cache/terminalOutputs/17626862048742598274 +0 -21
  82. package/.nx/cache/terminalOutputs/6337357866566791975 +0 -6
  83. package/.nx/cache/terminalOutputs/6664915487114632770 +0 -44
  84. package/.nx/cache/terminalOutputs/6673686859704879504 +0 -21
  85. package/.nx/cache/terminalOutputs/783228502946611950 +0 -19
  86. package/.nx/cache/terminalOutputs/7978448102466861029 +0 -32
  87. package/.nx/cache/terminalOutputs/9040451482998546630 +0 -21
  88. /package/.nx/cache/{14876618240301288353 → 7821397806208783174}/dist/libs/africanies-ui/README.md +0 -0
  89. /package/.nx/cache/{14876618240301288353 → 7821397806208783174}/dist/libs/africanies-ui/assets/brand/africanies-logo-mini.png +0 -0
  90. /package/.nx/cache/{14876618240301288353 → 7821397806208783174}/dist/libs/africanies-ui/assets/brand/africanies-logo.png +0 -0
  91. /package/.nx/cache/{14876618240301288353 → 7821397806208783174}/dist/libs/africanies-ui/assets/brand/africanies-logo.svg +0 -0
  92. /package/.nx/cache/{14876618240301288353 → 7821397806208783174}/dist/libs/africanies-ui/assets/carriers/dhl.svg +0 -0
  93. /package/.nx/cache/{14876618240301288353 → 7821397806208783174}/dist/libs/africanies-ui/package.json +0 -0
@@ -1,8 +1,8 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, input, booleanAttribute, computed, ChangeDetectionStrategy, Component, output, signal, Injector, DestroyRef, Injectable, numberAttribute, Directive, viewChild, contentChild, model, makeEnvironmentProviders, provideAppInitializer, forwardRef, InjectionToken, effect, afterNextRender, viewChildren, TemplateRef, contentChildren, untracked, runInInjectionContext, afterRenderEffect, NgModule } from '@angular/core';
2
+ import { inject, input, booleanAttribute, computed, ChangeDetectionStrategy, Component, output, signal, Injector, DestroyRef, Injectable, numberAttribute, Directive, viewChild, contentChild, model, makeEnvironmentProviders, provideAppInitializer, forwardRef, InjectionToken, effect, afterNextRender, viewChildren, untracked, TemplateRef, contentChildren, runInInjectionContext, afterRenderEffect, NgModule } from '@angular/core';
3
3
  import { AfricaniesIconComponent } from '@africanies/africanies-icons';
4
4
  import { ModeColorService, ThemeService } from '@africanies/africanies-theme';
5
- import { copyToClipboard, AFRICANIES_HTTP_TOAST, FilterOptionsResolver, MODAL_SERVICE, DRAWER_SERVICE, ShippingModeService, resolveNotificationLinkForMode } from '@africanies/africanies-core';
5
+ import { copyToClipboard, AFRICANIES_HTTP_TOAST, FilterOptionsResolver, MODAL_SERVICE, DRAWER_SERVICE, countryFlagUrl, ShippingModeService, resolveNotificationLinkForMode } from '@africanies/africanies-core';
6
6
  import { Overlay, CdkOverlayOrigin, CdkConnectedOverlay } from '@angular/cdk/overlay';
7
7
  import { ComponentPortal } from '@angular/cdk/portal';
8
8
  import { Router, ActivatedRoute, RouterLink, NavigationEnd } from '@angular/router';
@@ -11487,6 +11487,994 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
11487
11487
  `, styles: [".africanies-otp-cell-masked{-webkit-text-security:disc;text-security:disc}\n"] }]
11488
11488
  }], ctorParameters: () => [], propDecorators: { cellInputs: [{ type: i0.ViewChildren, args: ['cellInput', { isSignal: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], length: [{ type: i0.Input, args: [{ isSignal: true, alias: "length", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabledInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], showResend: [{ type: i0.Input, args: [{ isSignal: true, alias: "showResend", required: false }] }], resendPrompt: [{ type: i0.Input, args: [{ isSignal: true, alias: "resendPrompt", required: false }] }], resendLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "resendLabel", required: false }] }], resendCooldown: [{ type: i0.Input, args: [{ isSignal: true, alias: "resendCooldown", required: false }] }], completed: [{ type: i0.Output, args: ["completed"] }], resend: [{ type: i0.Output, args: ["resend"] }] } });
11489
11489
 
11490
+ /**
11491
+ * ISO 3166-1 alpha-2 → dial code (with `+`).
11492
+ *
11493
+ * Shared with classic import-export phone fields; used when
11494
+ * `libphonenumber-js` is not bundled as a peer.
11495
+ */
11496
+ const PHONE_DIAL_CODES = {
11497
+ AF: '+93',
11498
+ AX: '+358',
11499
+ AL: '+355',
11500
+ DZ: '+213',
11501
+ AS: '+1',
11502
+ AD: '+376',
11503
+ AO: '+244',
11504
+ AI: '+1',
11505
+ AQ: '+672',
11506
+ AG: '+1',
11507
+ AR: '+54',
11508
+ AM: '+374',
11509
+ AW: '+297',
11510
+ AU: '+61',
11511
+ AT: '+43',
11512
+ AZ: '+994',
11513
+ BS: '+1',
11514
+ BH: '+973',
11515
+ BD: '+880',
11516
+ BB: '+1',
11517
+ BY: '+375',
11518
+ BE: '+32',
11519
+ BZ: '+501',
11520
+ BJ: '+229',
11521
+ BM: '+1',
11522
+ BT: '+975',
11523
+ BO: '+591',
11524
+ BQ: '+599',
11525
+ BA: '+387',
11526
+ BW: '+267',
11527
+ BV: '+55',
11528
+ BR: '+55',
11529
+ IO: '+246',
11530
+ BN: '+673',
11531
+ BG: '+359',
11532
+ BF: '+226',
11533
+ BI: '+257',
11534
+ KH: '+855',
11535
+ CM: '+237',
11536
+ CA: '+1',
11537
+ CV: '+238',
11538
+ KY: '+1',
11539
+ CF: '+236',
11540
+ TD: '+235',
11541
+ CL: '+56',
11542
+ CN: '+86',
11543
+ CX: '+61',
11544
+ CC: '+61',
11545
+ CO: '+57',
11546
+ KM: '+269',
11547
+ CG: '+242',
11548
+ CK: '+682',
11549
+ CR: '+506',
11550
+ HR: '+385',
11551
+ CU: '+53',
11552
+ CW: '+599',
11553
+ CY: '+357',
11554
+ CZ: '+420',
11555
+ DK: '+45',
11556
+ DJ: '+253',
11557
+ DM: '+1',
11558
+ DO: '+1',
11559
+ CD: '+243',
11560
+ EC: '+593',
11561
+ EG: '+20',
11562
+ SV: '+503',
11563
+ GQ: '+240',
11564
+ ER: '+291',
11565
+ EE: '+370',
11566
+ ET: '+251',
11567
+ FK: '+500',
11568
+ FO: '+298',
11569
+ FJ: '+679',
11570
+ FI: '+358',
11571
+ FR: '+33',
11572
+ GF: '+594',
11573
+ PF: '+689',
11574
+ TF: '+262',
11575
+ GA: '+241',
11576
+ GM: '+220',
11577
+ GE: '+995',
11578
+ DE: '+49',
11579
+ GH: '+233',
11580
+ GI: '+350',
11581
+ GR: '+30',
11582
+ GL: '+299',
11583
+ GD: '+1',
11584
+ GP: '+590',
11585
+ GU: '+1',
11586
+ GT: '+502',
11587
+ GG: '+44',
11588
+ GN: '+224',
11589
+ GW: '+245',
11590
+ GY: '+592',
11591
+ HT: '+509',
11592
+ HM: '+672',
11593
+ HN: '+504',
11594
+ HK: '+852',
11595
+ HU: '+36',
11596
+ IS: '+354',
11597
+ IN: '+91',
11598
+ ID: '+62',
11599
+ IR: '+98',
11600
+ IQ: '+964',
11601
+ IE: '+353',
11602
+ IM: '+44',
11603
+ IL: '+972',
11604
+ IT: '+39',
11605
+ CI: '+225',
11606
+ JM: '+1',
11607
+ JP: '+81',
11608
+ JE: '+44',
11609
+ JO: '+962',
11610
+ KZ: '+7',
11611
+ KE: '+254',
11612
+ KI: '+686',
11613
+ XK: '+383',
11614
+ KW: '+965',
11615
+ KG: '+996',
11616
+ LA: '+856',
11617
+ LV: '+371',
11618
+ LB: '+961',
11619
+ LS: '+266',
11620
+ LR: '+231',
11621
+ LY: '+218',
11622
+ LI: '+423',
11623
+ LT: '+370',
11624
+ LU: '+352',
11625
+ MO: '+853',
11626
+ MK: '+389',
11627
+ MG: '+261',
11628
+ MW: '+265',
11629
+ MY: '+60',
11630
+ MV: '+960',
11631
+ ML: '+223',
11632
+ MT: '+356',
11633
+ MH: '+692',
11634
+ MQ: '+596',
11635
+ MR: '+222',
11636
+ MU: '+230',
11637
+ YT: '+262',
11638
+ MX: '+52',
11639
+ FM: '+691',
11640
+ MD: '+373',
11641
+ MC: '+377',
11642
+ MN: '+976',
11643
+ ME: '+382',
11644
+ MS: '+1',
11645
+ MA: '+212',
11646
+ MZ: '+258',
11647
+ MM: '+95',
11648
+ NA: '+264',
11649
+ NR: '+674',
11650
+ NP: '+977',
11651
+ NL: '+31',
11652
+ AN: '+599',
11653
+ NC: '+687',
11654
+ NZ: '+64',
11655
+ NI: '+505',
11656
+ NE: '+227',
11657
+ NG: '+234',
11658
+ NU: '+683',
11659
+ NF: '+672',
11660
+ MP: '+1',
11661
+ KP: '+850',
11662
+ NO: '+47',
11663
+ OM: '+968',
11664
+ PK: '+92',
11665
+ PW: '+680',
11666
+ PS: '+970',
11667
+ PA: '+507',
11668
+ PG: '+675',
11669
+ PY: '+595',
11670
+ PE: '+51',
11671
+ PH: '+63',
11672
+ PN: '+64',
11673
+ PL: '+48',
11674
+ PT: '+351',
11675
+ PR: '+1',
11676
+ QA: '+974',
11677
+ RO: '+40',
11678
+ RU: '+7',
11679
+ RW: '+250',
11680
+ RE: '+262',
11681
+ BL: '+590',
11682
+ MF: '+590',
11683
+ SH: '+290',
11684
+ KN: '+1',
11685
+ LC: '+1',
11686
+ PM: '+508',
11687
+ VC: '+1',
11688
+ WS: '+685',
11689
+ SM: '+378',
11690
+ ST: '+239',
11691
+ SA: '+966',
11692
+ SN: '+221',
11693
+ RS: '+381',
11694
+ SC: '+248',
11695
+ SL: '+232',
11696
+ SG: '+65',
11697
+ SX: '+1',
11698
+ SK: '+421',
11699
+ SI: '+386',
11700
+ SB: '+677',
11701
+ SO: '+252',
11702
+ ZA: '+27',
11703
+ GS: '+500',
11704
+ KR: '+82',
11705
+ SS: '+211',
11706
+ ES: '+34',
11707
+ LK: '+94',
11708
+ SD: '+249',
11709
+ SR: '+597',
11710
+ SJ: '+47',
11711
+ SZ: '+268',
11712
+ SE: '+46',
11713
+ CH: '+41',
11714
+ SY: '+963',
11715
+ TW: '+886',
11716
+ TJ: '+992',
11717
+ TZ: '+255',
11718
+ TH: '+66',
11719
+ TL: '+670',
11720
+ TG: '+228',
11721
+ TK: '+690',
11722
+ TO: '+676',
11723
+ TT: '+1',
11724
+ TN: '+216',
11725
+ TR: '+90',
11726
+ TM: '+993',
11727
+ TC: '+1',
11728
+ TV: '+688',
11729
+ UG: '+256',
11730
+ UA: '+380',
11731
+ AE: '+971',
11732
+ GB: '+44',
11733
+ US: '+1',
11734
+ UY: '+598',
11735
+ UZ: '+998',
11736
+ VU: '+678',
11737
+ VA: '+379',
11738
+ VE: '+58',
11739
+ VN: '+84',
11740
+ VG: '+1',
11741
+ VI: '+1',
11742
+ WF: '+681',
11743
+ EH: '+212',
11744
+ YE: '+967',
11745
+ ZM: '+260',
11746
+ ZW: '+263',
11747
+ };
11748
+ /** Max national digit count (ITU E.164 national significant number). */
11749
+ const PHONE_MAX_NATIONAL_DIGITS = 15;
11750
+ /** Minimum national digits before we treat a draft as a complete number. */
11751
+ const PHONE_MIN_NATIONAL_DIGITS = 4;
11752
+
11753
+ const regionNames = typeof Intl !== 'undefined' && 'DisplayNames' in Intl
11754
+ ? new Intl.DisplayNames(['en'], { type: 'region' })
11755
+ : null;
11756
+ /** Digits only from a phone draft. */
11757
+ function phoneDigitsOnly(value) {
11758
+ return (value ?? '').replace(/\D/g, '');
11759
+ }
11760
+ /** Normalize ISO2 to uppercase two letters, or `''`. */
11761
+ function normalizePhoneIso2(iso2) {
11762
+ const code = (iso2 ?? '').trim().toUpperCase();
11763
+ return /^[A-Z]{2}$/.test(code) ? code : '';
11764
+ }
11765
+ /** Dial code for an ISO2 (with `+`), or `''` when unknown. */
11766
+ function dialCodeForIso2(iso2) {
11767
+ const code = normalizePhoneIso2(iso2);
11768
+ return code ? (PHONE_DIAL_CODES[code] ?? '') : '';
11769
+ }
11770
+ /** English country name from ISO2 (falls back to the code). */
11771
+ function phoneCountryName(iso2) {
11772
+ const code = normalizePhoneIso2(iso2);
11773
+ if (!code) {
11774
+ return '';
11775
+ }
11776
+ try {
11777
+ return regionNames?.of(code) ?? code;
11778
+ }
11779
+ catch {
11780
+ return code;
11781
+ }
11782
+ }
11783
+ /** All dial-code countries for the picker (sorted by name). */
11784
+ function phoneCountryOptions() {
11785
+ return Object.keys(PHONE_DIAL_CODES)
11786
+ .map((iso2) => {
11787
+ const dialCode = PHONE_DIAL_CODES[iso2];
11788
+ return {
11789
+ iso2,
11790
+ dialCode,
11791
+ name: phoneCountryName(iso2),
11792
+ flagUrl: countryFlagUrl(iso2, { width: 40 }),
11793
+ };
11794
+ })
11795
+ .sort((a, b) => a.name.localeCompare(b.name));
11796
+ }
11797
+ /**
11798
+ * Filter dial-code countries by name, ISO2, or dial digits.
11799
+ * Digit matching is skipped when the query has no digits — otherwise
11800
+ * `''.includes('')` would keep every country for letter-only searches.
11801
+ */
11802
+ function filterPhoneCountries(countries, query) {
11803
+ const q = query.trim().toLowerCase();
11804
+ if (!q) {
11805
+ return [...countries];
11806
+ }
11807
+ const qDigits = phoneDigitsOnly(q);
11808
+ return countries.filter((row) => {
11809
+ if (row.name.toLowerCase().includes(q) ||
11810
+ row.iso2.toLowerCase().includes(q) ||
11811
+ row.dialCode.toLowerCase().includes(q)) {
11812
+ return true;
11813
+ }
11814
+ return qDigits.length > 0
11815
+ ? phoneDigitsOnly(row.dialCode).includes(qDigits)
11816
+ : false;
11817
+ });
11818
+ }
11819
+ /**
11820
+ * Match an E.164 / international string to the longest known dial code.
11821
+ * Prefers `hintIso2` when several countries share the same dial code (e.g. `+1`).
11822
+ */
11823
+ function matchDialCode(e164OrInternational, hintIso2) {
11824
+ const digits = phoneDigitsOnly(e164OrInternational);
11825
+ if (!digits) {
11826
+ return null;
11827
+ }
11828
+ const hint = normalizePhoneIso2(hintIso2);
11829
+ if (hint) {
11830
+ const hintDial = PHONE_DIAL_CODES[hint];
11831
+ if (hintDial) {
11832
+ const hintDigits = phoneDigitsOnly(hintDial);
11833
+ if (digits.startsWith(hintDigits)) {
11834
+ return {
11835
+ iso2: hint,
11836
+ dialCode: hintDial,
11837
+ nationalDigits: digits.slice(hintDigits.length),
11838
+ };
11839
+ }
11840
+ }
11841
+ }
11842
+ let best = null;
11843
+ for (const [iso2, dialCode] of Object.entries(PHONE_DIAL_CODES)) {
11844
+ const dialDigits = phoneDigitsOnly(dialCode);
11845
+ if (!digits.startsWith(dialDigits)) {
11846
+ continue;
11847
+ }
11848
+ const nationalDigits = digits.slice(dialDigits.length);
11849
+ if (!best ||
11850
+ dialDigits.length > phoneDigitsOnly(best.dialCode).length) {
11851
+ best = { iso2, dialCode, nationalDigits };
11852
+ }
11853
+ }
11854
+ return best;
11855
+ }
11856
+ /**
11857
+ * Strip a leading dial code from a stored phone (classic `removeDialCode`).
11858
+ * Returns national digits for prefilling the input.
11859
+ */
11860
+ function removeDialCode(phone, hintIso2) {
11861
+ const raw = (phone ?? '').trim();
11862
+ if (!raw) {
11863
+ return '';
11864
+ }
11865
+ const matched = matchDialCode(raw, hintIso2);
11866
+ if (matched) {
11867
+ return matched.nationalDigits;
11868
+ }
11869
+ return phoneDigitsOnly(raw);
11870
+ }
11871
+ /** Group national digits for readable display (… + last 4). */
11872
+ function formatNationalDigits(digits) {
11873
+ const clean = phoneDigitsOnly(digits).slice(0, PHONE_MAX_NATIONAL_DIGITS);
11874
+ if (!clean) {
11875
+ return '';
11876
+ }
11877
+ if (clean.length <= 4) {
11878
+ return clean;
11879
+ }
11880
+ const end = clean.slice(-4);
11881
+ const head = clean.slice(0, -4).replace(/(\d{3})(?=\d)/g, '$1 ').trim();
11882
+ return `${head} ${end}`.trim();
11883
+ }
11884
+ /**
11885
+ * Build the structured value (or `null` when empty).
11886
+ */
11887
+ function buildPhoneNumberValue(iso2, nationalDraft) {
11888
+ const countryCode = normalizePhoneIso2(iso2);
11889
+ const dialCode = dialCodeForIso2(countryCode);
11890
+ if (!countryCode || !dialCode) {
11891
+ return null;
11892
+ }
11893
+ const nationalDigits = phoneDigitsOnly(nationalDraft).slice(0, PHONE_MAX_NATIONAL_DIGITS);
11894
+ if (!nationalDigits) {
11895
+ return null;
11896
+ }
11897
+ const number = formatNationalDigits(nationalDigits);
11898
+ const e164Number = `${dialCode}${nationalDigits}`;
11899
+ const internationalNumber = `${dialCode} ${number}`.trim();
11900
+ // Trunk-prefix `0` for national display when digits omit it (classic ngx shape).
11901
+ const nationalNumber = nationalDigits.startsWith('0')
11902
+ ? number
11903
+ : `0${number}`;
11904
+ return {
11905
+ number,
11906
+ internationalNumber,
11907
+ nationalNumber,
11908
+ e164Number,
11909
+ countryCode,
11910
+ dialCode,
11911
+ };
11912
+ }
11913
+ /**
11914
+ * Canonical outbound phone string — prefer E.164 from a structured value.
11915
+ */
11916
+ function phoneToE164(phone) {
11917
+ if (phone == null) {
11918
+ return '';
11919
+ }
11920
+ if (typeof phone === 'string') {
11921
+ const digits = phoneDigitsOnly(phone);
11922
+ if (!digits) {
11923
+ return '';
11924
+ }
11925
+ return phone.trim().startsWith('+') ? `+${digits}` : phone.trim();
11926
+ }
11927
+ return phone.e164Number?.trim() || '';
11928
+ }
11929
+ /**
11930
+ * Soft validity: has dial code + enough national digits (not full libphonenumber).
11931
+ */
11932
+ function isPhoneNumberComplete(phone) {
11933
+ if (!phone?.e164Number) {
11934
+ return false;
11935
+ }
11936
+ const national = phoneDigitsOnly(phone.number);
11937
+ return (national.length >= PHONE_MIN_NATIONAL_DIGITS &&
11938
+ national.length <= PHONE_MAX_NATIONAL_DIGITS);
11939
+ }
11940
+ /**
11941
+ * Split an incoming control value (E.164 string or structured) into UI state.
11942
+ */
11943
+ function parsePhoneControlValue(value, fallbackIso2) {
11944
+ const fallback = normalizePhoneIso2(fallbackIso2) || 'US';
11945
+ if (value == null || value === '') {
11946
+ return { iso2: fallback, nationalDigits: '' };
11947
+ }
11948
+ if (typeof value === 'object') {
11949
+ const iso2 = normalizePhoneIso2(value.countryCode) || fallback;
11950
+ const national = phoneDigitsOnly(value.number) ||
11951
+ phoneDigitsOnly(value.nationalNumber) ||
11952
+ removeDialCode(value.e164Number, iso2);
11953
+ return { iso2, nationalDigits: national };
11954
+ }
11955
+ const matched = matchDialCode(value, fallback);
11956
+ if (matched) {
11957
+ return {
11958
+ iso2: matched.iso2,
11959
+ nationalDigits: matched.nationalDigits,
11960
+ };
11961
+ }
11962
+ return {
11963
+ iso2: fallback,
11964
+ nationalDigits: phoneDigitsOnly(value),
11965
+ };
11966
+ }
11967
+
11968
+ let nextPhoneInputId = 0;
11969
+ const PANEL_POSITIONS$1 = [
11970
+ {
11971
+ originX: 'start',
11972
+ originY: 'bottom',
11973
+ overlayX: 'start',
11974
+ overlayY: 'top',
11975
+ offsetY: 4,
11976
+ },
11977
+ {
11978
+ originX: 'start',
11979
+ originY: 'top',
11980
+ overlayX: 'start',
11981
+ overlayY: 'bottom',
11982
+ offsetY: -4,
11983
+ },
11984
+ ];
11985
+ /**
11986
+ * International phone field — flag + dial code + national number.
11987
+ *
11988
+ * Visual / behavioral cousin of classic `africanies-phone-field`
11989
+ * (`ngx-intl-tel-input`), rebuilt for Angular 22 + AFRICANIES form chrome
11990
+ * (no ngx peer-dep).
11991
+ *
11992
+ * **Value contract**
11993
+ * - `[(value)]` / CVA → **E.164 string** (e.g. `+2348012345678`) so admin
11994
+ * mappers stay `phone: string`.
11995
+ * - `phoneValue` model mirrors the structured classic object when you need
11996
+ * `countryCode` / `dialCode` in the parent.
11997
+ *
11998
+ * @example
11999
+ * ```html
12000
+ * <africanies-phone-input
12001
+ * label="Phone"
12002
+ * [countryIso2]="countryIso"
12003
+ * [lockCountry]="true"
12004
+ * [error]="phoneError()"
12005
+ * [(value)]="phone"
12006
+ * />
12007
+ * ```
12008
+ */
12009
+ class PhoneInputComponent {
12010
+ controlId = `africanies-phone-input-${++nextPhoneInputId}`;
12011
+ hintId = `${this.controlId}-hint`;
12012
+ errorId = `${this.controlId}-error`;
12013
+ labelClass = FORM_LABEL_CLASS;
12014
+ hintClass = FORM_HINT_CLASS;
12015
+ errorClass = FORM_ERROR_CLASS;
12016
+ panelPositions = PANEL_POSITIONS$1;
12017
+ allCountries = phoneCountryOptions();
12018
+ injector = inject(Injector);
12019
+ countrySearch = viewChild('countrySearch', /* @ts-ignore */
12020
+ ...(ngDevMode ? [{ debugName: "countrySearch" }] : /* istanbul ignore next */ []));
12021
+ /** Visible field label. */
12022
+ label = input('', /* @ts-ignore */
12023
+ ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
12024
+ /** Helper under the field (hidden while {@link error} is set). */
12025
+ hint = input(undefined, /* @ts-ignore */
12026
+ ...(ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []));
12027
+ /** Field-level validation message. */
12028
+ error = input(null, /* @ts-ignore */
12029
+ ...(ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []));
12030
+ /** National-number placeholder. */
12031
+ placeholder = input('Phone number', /* @ts-ignore */
12032
+ ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
12033
+ /**
12034
+ * Selected country ISO2. Parents set this from address/user country.
12035
+ * Two-way so picking a country updates the parent.
12036
+ */
12037
+ countryIso2 = model('US', /* @ts-ignore */
12038
+ ...(ngDevMode ? [{ debugName: "countryIso2" }] : /* istanbul ignore next */ []));
12039
+ /**
12040
+ * When true, the flag/dial segment is not clickable (classic `resetISO`).
12041
+ * Use for locked sender-country phones; set `false` for free country pick.
12042
+ */
12043
+ lockCountry = input(false, { ...(ngDevMode ? { debugName: "lockCountry" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
12044
+ /**
12045
+ * E.164 string for `[(value)]` / reactive forms.
12046
+ * Empty string when cleared.
12047
+ */
12048
+ value = model('', /* @ts-ignore */
12049
+ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
12050
+ /**
12051
+ * Structured phone object (classic `PhoneNumberFormat` shape).
12052
+ * `null` when the national field is empty.
12053
+ */
12054
+ phoneValue = model(null, /* @ts-ignore */
12055
+ ...(ngDevMode ? [{ debugName: "phoneValue" }] : /* istanbul ignore next */ []));
12056
+ disabledInput = input(false, { ...(ngDevMode ? { debugName: "disabledInput" } : /* istanbul ignore next */ {}), alias: 'disabled',
12057
+ transform: booleanAttribute });
12058
+ cvaDisabled = signal(false, /* @ts-ignore */
12059
+ ...(ngDevMode ? [{ debugName: "cvaDisabled" }] : /* istanbul ignore next */ []));
12060
+ disabled = computed(() => this.disabledInput() || this.cvaDisabled(), /* @ts-ignore */
12061
+ ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
12062
+ countryOpen = signal(false, /* @ts-ignore */
12063
+ ...(ngDevMode ? [{ debugName: "countryOpen" }] : /* istanbul ignore next */ []));
12064
+ countryQuery = signal('', /* @ts-ignore */
12065
+ ...(ngDevMode ? [{ debugName: "countryQuery" }] : /* istanbul ignore next */ []));
12066
+ /** Digits currently typed in the national field. */
12067
+ nationalDigits = signal('', /* @ts-ignore */
12068
+ ...(ngDevMode ? [{ debugName: "nationalDigits" }] : /* istanbul ignore next */ []));
12069
+ dialCode = computed(() => dialCodeForIso2(this.countryIso2()) || '+1', /* @ts-ignore */
12070
+ ...(ngDevMode ? [{ debugName: "dialCode" }] : /* istanbul ignore next */ []));
12071
+ flagUrl = computed(() => {
12072
+ const iso = normalizePhoneIso2(this.countryIso2());
12073
+ return iso ? countryFlagUrl(iso, { width: 40 }) : '';
12074
+ }, /* @ts-ignore */
12075
+ ...(ngDevMode ? [{ debugName: "flagUrl" }] : /* istanbul ignore next */ []));
12076
+ nationalDisplay = computed(() => this.nationalDigits(), /* @ts-ignore */
12077
+ ...(ngDevMode ? [{ debugName: "nationalDisplay" }] : /* istanbul ignore next */ []));
12078
+ filteredCountries = computed(() => filterPhoneCountries(this.allCountries, this.countryQuery()), /* @ts-ignore */
12079
+ ...(ngDevMode ? [{ debugName: "filteredCountries" }] : /* istanbul ignore next */ []));
12080
+ shellClass = computed(() => {
12081
+ let classes = FORM_FIELD_CLASS;
12082
+ if (this.error()) {
12083
+ classes += ` ${FORM_FIELD_ERROR_CLASS}`;
12084
+ }
12085
+ if (this.disabled()) {
12086
+ classes += ` ${FORM_DISABLED_CLASS}`;
12087
+ }
12088
+ return classes;
12089
+ }, /* @ts-ignore */
12090
+ ...(ngDevMode ? [{ debugName: "shellClass" }] : /* istanbul ignore next */ []));
12091
+ describedBy = computed(() => {
12092
+ if (this.error()) {
12093
+ return this.errorId;
12094
+ }
12095
+ if (this.hint()) {
12096
+ return this.hintId;
12097
+ }
12098
+ return null;
12099
+ }, /* @ts-ignore */
12100
+ ...(ngDevMode ? [{ debugName: "describedBy" }] : /* istanbul ignore next */ []));
12101
+ onChange = () => undefined;
12102
+ onTouched = () => undefined;
12103
+ /** True while applying an external `value` so emit does not loop. */
12104
+ syncingFromExternal = false;
12105
+ constructor() {
12106
+ // Template `[(value)]` / `[value]` updates the model but does not call CVA
12107
+ // `writeValue`. Sync national digits whenever the external value or the
12108
+ // parent-bound country changes (edit prepopulate + locked country forms).
12109
+ effect(() => {
12110
+ const external = this.value();
12111
+ const iso = this.countryIso2();
12112
+ const locked = this.lockCountry();
12113
+ untracked(() => this.applyExternalValue(external, iso, locked));
12114
+ });
12115
+ }
12116
+ maxLengthAttr() {
12117
+ return PHONE_MAX_NATIONAL_DIGITS;
12118
+ }
12119
+ writeValue(value) {
12120
+ this.applyExternalValue(value, this.countryIso2(), this.lockCountry());
12121
+ const e164 = this.phoneValue()?.e164Number ??
12122
+ (typeof value === 'string' ? value.trim() : '');
12123
+ this.syncingFromExternal = true;
12124
+ this.value.set(e164);
12125
+ this.syncingFromExternal = false;
12126
+ }
12127
+ registerOnChange(fn) {
12128
+ this.onChange = fn;
12129
+ }
12130
+ registerOnTouched(fn) {
12131
+ this.onTouched = fn;
12132
+ }
12133
+ setDisabledState(isDisabled) {
12134
+ this.cvaDisabled.set(isDisabled);
12135
+ }
12136
+ toggleCountryPicker(event) {
12137
+ event.preventDefault();
12138
+ event.stopPropagation();
12139
+ if (this.disabled() || this.lockCountry()) {
12140
+ return;
12141
+ }
12142
+ this.countryOpen.update((open) => !open);
12143
+ if (this.countryOpen()) {
12144
+ this.countryQuery.set('');
12145
+ // Overlay attaches on the next render; focus search so typing filters.
12146
+ afterNextRender(() => this.countrySearch()?.nativeElement.focus(), { injector: this.injector });
12147
+ }
12148
+ }
12149
+ closeCountryPicker() {
12150
+ this.countryOpen.set(false);
12151
+ }
12152
+ onCountryQuery(event) {
12153
+ this.countryQuery.set(event.target.value);
12154
+ }
12155
+ selectCountry(row) {
12156
+ this.countryIso2.set(row.iso2);
12157
+ this.closeCountryPicker();
12158
+ this.emitFromState();
12159
+ }
12160
+ onNationalInput(event) {
12161
+ const raw = event.target.value;
12162
+ const digits = phoneDigitsOnly(raw).slice(0, PHONE_MAX_NATIONAL_DIGITS);
12163
+ this.nationalDigits.set(digits);
12164
+ this.emitFromState();
12165
+ }
12166
+ onBlur() {
12167
+ this.onTouched();
12168
+ }
12169
+ applyExternalValue(value, preferredIso2, lockCountry) {
12170
+ const preferred = normalizePhoneIso2(preferredIso2) || 'US';
12171
+ const parsed = parsePhoneControlValue(value, preferred);
12172
+ // Locked forms keep the parent country; still strip that dial code from
12173
+ // stored E.164 / international strings so the national field prefills.
12174
+ const iso2 = lockCountry ? preferred : parsed.iso2;
12175
+ const nationalDigits = lockCountry
12176
+ ? nationalDigitsForLockedCountry(value, preferred)
12177
+ : parsed.nationalDigits;
12178
+ if (iso2 === normalizePhoneIso2(this.countryIso2()) &&
12179
+ nationalDigits === this.nationalDigits()) {
12180
+ return;
12181
+ }
12182
+ this.syncingFromExternal = true;
12183
+ if (!lockCountry) {
12184
+ this.countryIso2.set(iso2);
12185
+ }
12186
+ this.nationalDigits.set(nationalDigits);
12187
+ this.phoneValue.set(buildPhoneNumberValue(iso2, nationalDigits));
12188
+ this.syncingFromExternal = false;
12189
+ }
12190
+ emitFromState() {
12191
+ if (this.syncingFromExternal) {
12192
+ return;
12193
+ }
12194
+ const structured = buildPhoneNumberValue(this.countryIso2(), this.nationalDigits());
12195
+ const e164 = structured ? phoneToE164(structured) : '';
12196
+ this.phoneValue.set(structured);
12197
+ this.value.set(e164);
12198
+ this.onChange(e164);
12199
+ }
12200
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: PhoneInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
12201
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: PhoneInputComponent, isStandalone: true, selector: "africanies-phone-input", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, countryIso2: { classPropertyName: "countryIso2", publicName: "countryIso2", isSignal: true, isRequired: false, transformFunction: null }, lockCountry: { classPropertyName: "lockCountry", publicName: "lockCountry", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, phoneValue: { classPropertyName: "phoneValue", publicName: "phoneValue", isSignal: true, isRequired: false, transformFunction: null }, disabledInput: { classPropertyName: "disabledInput", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { countryIso2: "countryIso2Change", value: "valueChange", phoneValue: "phoneValueChange" }, host: { classAttribute: "relative block" }, providers: [
12202
+ {
12203
+ provide: NG_VALUE_ACCESSOR,
12204
+ useExisting: forwardRef(() => PhoneInputComponent),
12205
+ multi: true,
12206
+ },
12207
+ ], viewQueries: [{ propertyName: "countrySearch", first: true, predicate: ["countrySearch"], descendants: true, isSignal: true }], ngImport: i0, template: `
12208
+ <label [attr.for]="controlId" [class]="labelClass">{{ label() }}</label>
12209
+
12210
+ <div [class]="shellClass()">
12211
+ <button
12212
+ cdkOverlayOrigin
12213
+ #dialOrigin="cdkOverlayOrigin"
12214
+ type="button"
12215
+ class="inline-flex h-full shrink-0 items-center gap-1.5 border-0 border-r border-control bg-transparent px-2.5 text-body-sm text-ink dark:border-white/25 dark:text-white disabled:cursor-not-allowed"
12216
+ [class.pointer-events-none]="lockCountry()"
12217
+ [attr.aria-expanded]="countryOpen()"
12218
+ [attr.aria-haspopup]="'listbox'"
12219
+ [attr.aria-label]="'Country dial code'"
12220
+ [disabled]="disabled() || lockCountry()"
12221
+ (click)="toggleCountryPicker($event)"
12222
+ >
12223
+ @if (flagUrl(); as src) {
12224
+ <img
12225
+ [src]="src"
12226
+ alt=""
12227
+ class="h-4 w-5 rounded-sm object-cover"
12228
+ loading="lazy"
12229
+ aria-hidden="true"
12230
+ />
12231
+ }
12232
+ <span class="tabular-nums">{{ dialCode() }}</span>
12233
+ @if (!lockCountry()) {
12234
+ <africanies-icon name="chevron-down" [size]="14" class="shrink-0 opacity-70" />
12235
+ }
12236
+ </button>
12237
+
12238
+ <input
12239
+ [id]="controlId"
12240
+ type="tel"
12241
+ inputmode="tel"
12242
+ autocomplete="tel-national"
12243
+ class="min-h-0 h-full min-w-0 flex-1 border-0 bg-transparent px-3 py-0 text-body text-ink outline-none placeholder:text-neutral-500 disabled:cursor-not-allowed dark:text-white"
12244
+ [value]="nationalDisplay()"
12245
+ [disabled]="disabled()"
12246
+ [attr.placeholder]="placeholder() || null"
12247
+ [attr.maxlength]="maxLengthAttr()"
12248
+ [attr.aria-invalid]="error() ? true : null"
12249
+ [attr.aria-describedby]="describedBy()"
12250
+ (input)="onNationalInput($event)"
12251
+ (blur)="onBlur()"
12252
+ />
12253
+ </div>
12254
+
12255
+ @if (error(); as err) {
12256
+ <p [id]="errorId" [class]="errorClass" role="alert">{{ err }}</p>
12257
+ } @else if (hint(); as h) {
12258
+ <p [id]="hintId" [class]="hintClass">{{ h }}</p>
12259
+ }
12260
+
12261
+ <ng-template
12262
+ cdkConnectedOverlay
12263
+ [cdkConnectedOverlayOrigin]="dialOrigin"
12264
+ [cdkConnectedOverlayOpen]="countryOpen()"
12265
+ [cdkConnectedOverlayPositions]="panelPositions"
12266
+ [cdkConnectedOverlayWidth]="320"
12267
+ [cdkConnectedOverlayPush]="true"
12268
+ [cdkConnectedOverlayHasBackdrop]="true"
12269
+ cdkConnectedOverlayBackdropClass="cdk-overlay-transparent-backdrop"
12270
+ (backdropClick)="closeCountryPicker()"
12271
+ (overlayOutsideClick)="closeCountryPicker()"
12272
+ >
12273
+ <div
12274
+ class="flex w-full flex-col overflow-hidden rounded-md border border-border bg-white shadow-lg dark:border-white/15 dark:bg-ink-950"
12275
+ role="listbox"
12276
+ [attr.aria-label]="'Select country'"
12277
+ >
12278
+ <div class="border-b border-border p-2 dark:border-white/15">
12279
+ <input
12280
+ #countrySearch
12281
+ type="search"
12282
+ class="h-9 w-full rounded-control border border-control bg-transparent px-3 text-body-sm text-ink outline-none placeholder:text-neutral-500 focus:ring-2 focus:ring-inset focus:ring-focus dark:border-white/25 dark:text-white"
12283
+ placeholder="Search country or code"
12284
+ [value]="countryQuery()"
12285
+ (input)="onCountryQuery($event)"
12286
+ (keydown)="$event.stopPropagation()"
12287
+ />
12288
+ </div>
12289
+ <ul class="africanies-overlay-scroll m-0 max-h-56 list-none overflow-auto p-1">
12290
+ @for (row of filteredCountries(); track row.iso2) {
12291
+ <li>
12292
+ <button
12293
+ type="button"
12294
+ class="flex w-full cursor-pointer items-center gap-2 rounded-md px-2 py-2 text-left text-body-sm text-ink hover:bg-neutral-100 dark:text-white dark:hover:bg-white/10"
12295
+ [class.bg-neutral-100]="row.iso2 === countryIso2()"
12296
+ [class.dark:bg-white/10]="row.iso2 === countryIso2()"
12297
+ role="option"
12298
+ [attr.aria-selected]="row.iso2 === countryIso2()"
12299
+ (click)="selectCountry(row)"
12300
+ >
12301
+ <img
12302
+ [src]="row.flagUrl"
12303
+ alt=""
12304
+ class="h-4 w-5 shrink-0 rounded-sm object-cover"
12305
+ loading="lazy"
12306
+ aria-hidden="true"
12307
+ />
12308
+ <span class="min-w-0 flex-1 truncate">{{ row.name }}</span>
12309
+ <span class="shrink-0 tabular-nums text-neutral-600 dark:text-neutral-400">
12310
+ {{ row.dialCode }}
12311
+ </span>
12312
+ </button>
12313
+ </li>
12314
+ } @empty {
12315
+ <li class="px-3 py-4 text-center text-caption text-neutral-600 dark:text-neutral-400">
12316
+ No countries match.
12317
+ </li>
12318
+ }
12319
+ </ul>
12320
+ </div>
12321
+ </ng-template>
12322
+ `, isInline: true, dependencies: [{ kind: "component", type: AfricaniesIconComponent, selector: "africanies-icon", inputs: ["name", "size"] }, { kind: "directive", type: CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "directive", type: CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation", "cdkConnectedOverlayUsePopover", "cdkConnectedOverlayMatchWidth", "cdkConnectedOverlay"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
12323
+ }
12324
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: PhoneInputComponent, decorators: [{
12325
+ type: Component,
12326
+ args: [{
12327
+ selector: 'africanies-phone-input',
12328
+ standalone: true,
12329
+ changeDetection: ChangeDetectionStrategy.OnPush,
12330
+ imports: [AfricaniesIconComponent, CdkOverlayOrigin, CdkConnectedOverlay],
12331
+ providers: [
12332
+ {
12333
+ provide: NG_VALUE_ACCESSOR,
12334
+ useExisting: forwardRef(() => PhoneInputComponent),
12335
+ multi: true,
12336
+ },
12337
+ ],
12338
+ host: {
12339
+ class: 'relative block',
12340
+ },
12341
+ template: `
12342
+ <label [attr.for]="controlId" [class]="labelClass">{{ label() }}</label>
12343
+
12344
+ <div [class]="shellClass()">
12345
+ <button
12346
+ cdkOverlayOrigin
12347
+ #dialOrigin="cdkOverlayOrigin"
12348
+ type="button"
12349
+ class="inline-flex h-full shrink-0 items-center gap-1.5 border-0 border-r border-control bg-transparent px-2.5 text-body-sm text-ink dark:border-white/25 dark:text-white disabled:cursor-not-allowed"
12350
+ [class.pointer-events-none]="lockCountry()"
12351
+ [attr.aria-expanded]="countryOpen()"
12352
+ [attr.aria-haspopup]="'listbox'"
12353
+ [attr.aria-label]="'Country dial code'"
12354
+ [disabled]="disabled() || lockCountry()"
12355
+ (click)="toggleCountryPicker($event)"
12356
+ >
12357
+ @if (flagUrl(); as src) {
12358
+ <img
12359
+ [src]="src"
12360
+ alt=""
12361
+ class="h-4 w-5 rounded-sm object-cover"
12362
+ loading="lazy"
12363
+ aria-hidden="true"
12364
+ />
12365
+ }
12366
+ <span class="tabular-nums">{{ dialCode() }}</span>
12367
+ @if (!lockCountry()) {
12368
+ <africanies-icon name="chevron-down" [size]="14" class="shrink-0 opacity-70" />
12369
+ }
12370
+ </button>
12371
+
12372
+ <input
12373
+ [id]="controlId"
12374
+ type="tel"
12375
+ inputmode="tel"
12376
+ autocomplete="tel-national"
12377
+ class="min-h-0 h-full min-w-0 flex-1 border-0 bg-transparent px-3 py-0 text-body text-ink outline-none placeholder:text-neutral-500 disabled:cursor-not-allowed dark:text-white"
12378
+ [value]="nationalDisplay()"
12379
+ [disabled]="disabled()"
12380
+ [attr.placeholder]="placeholder() || null"
12381
+ [attr.maxlength]="maxLengthAttr()"
12382
+ [attr.aria-invalid]="error() ? true : null"
12383
+ [attr.aria-describedby]="describedBy()"
12384
+ (input)="onNationalInput($event)"
12385
+ (blur)="onBlur()"
12386
+ />
12387
+ </div>
12388
+
12389
+ @if (error(); as err) {
12390
+ <p [id]="errorId" [class]="errorClass" role="alert">{{ err }}</p>
12391
+ } @else if (hint(); as h) {
12392
+ <p [id]="hintId" [class]="hintClass">{{ h }}</p>
12393
+ }
12394
+
12395
+ <ng-template
12396
+ cdkConnectedOverlay
12397
+ [cdkConnectedOverlayOrigin]="dialOrigin"
12398
+ [cdkConnectedOverlayOpen]="countryOpen()"
12399
+ [cdkConnectedOverlayPositions]="panelPositions"
12400
+ [cdkConnectedOverlayWidth]="320"
12401
+ [cdkConnectedOverlayPush]="true"
12402
+ [cdkConnectedOverlayHasBackdrop]="true"
12403
+ cdkConnectedOverlayBackdropClass="cdk-overlay-transparent-backdrop"
12404
+ (backdropClick)="closeCountryPicker()"
12405
+ (overlayOutsideClick)="closeCountryPicker()"
12406
+ >
12407
+ <div
12408
+ class="flex w-full flex-col overflow-hidden rounded-md border border-border bg-white shadow-lg dark:border-white/15 dark:bg-ink-950"
12409
+ role="listbox"
12410
+ [attr.aria-label]="'Select country'"
12411
+ >
12412
+ <div class="border-b border-border p-2 dark:border-white/15">
12413
+ <input
12414
+ #countrySearch
12415
+ type="search"
12416
+ class="h-9 w-full rounded-control border border-control bg-transparent px-3 text-body-sm text-ink outline-none placeholder:text-neutral-500 focus:ring-2 focus:ring-inset focus:ring-focus dark:border-white/25 dark:text-white"
12417
+ placeholder="Search country or code"
12418
+ [value]="countryQuery()"
12419
+ (input)="onCountryQuery($event)"
12420
+ (keydown)="$event.stopPropagation()"
12421
+ />
12422
+ </div>
12423
+ <ul class="africanies-overlay-scroll m-0 max-h-56 list-none overflow-auto p-1">
12424
+ @for (row of filteredCountries(); track row.iso2) {
12425
+ <li>
12426
+ <button
12427
+ type="button"
12428
+ class="flex w-full cursor-pointer items-center gap-2 rounded-md px-2 py-2 text-left text-body-sm text-ink hover:bg-neutral-100 dark:text-white dark:hover:bg-white/10"
12429
+ [class.bg-neutral-100]="row.iso2 === countryIso2()"
12430
+ [class.dark:bg-white/10]="row.iso2 === countryIso2()"
12431
+ role="option"
12432
+ [attr.aria-selected]="row.iso2 === countryIso2()"
12433
+ (click)="selectCountry(row)"
12434
+ >
12435
+ <img
12436
+ [src]="row.flagUrl"
12437
+ alt=""
12438
+ class="h-4 w-5 shrink-0 rounded-sm object-cover"
12439
+ loading="lazy"
12440
+ aria-hidden="true"
12441
+ />
12442
+ <span class="min-w-0 flex-1 truncate">{{ row.name }}</span>
12443
+ <span class="shrink-0 tabular-nums text-neutral-600 dark:text-neutral-400">
12444
+ {{ row.dialCode }}
12445
+ </span>
12446
+ </button>
12447
+ </li>
12448
+ } @empty {
12449
+ <li class="px-3 py-4 text-center text-caption text-neutral-600 dark:text-neutral-400">
12450
+ No countries match.
12451
+ </li>
12452
+ }
12453
+ </ul>
12454
+ </div>
12455
+ </ng-template>
12456
+ `,
12457
+ }]
12458
+ }], ctorParameters: () => [], propDecorators: { countrySearch: [{ type: i0.ViewChild, args: ['countrySearch', { isSignal: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], countryIso2: [{ type: i0.Input, args: [{ isSignal: true, alias: "countryIso2", required: false }] }, { type: i0.Output, args: ["countryIso2Change"] }], lockCountry: [{ type: i0.Input, args: [{ isSignal: true, alias: "lockCountry", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], phoneValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "phoneValue", required: false }] }, { type: i0.Output, args: ["phoneValueChange"] }], disabledInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
12459
+ /** National digits when the dial-code country is fixed by the parent. */
12460
+ function nationalDigitsForLockedCountry(value, iso2) {
12461
+ if (value == null || value === '') {
12462
+ return '';
12463
+ }
12464
+ if (typeof value === 'object') {
12465
+ return (phoneDigitsOnly(value.number) ||
12466
+ phoneDigitsOnly(value.nationalNumber) ||
12467
+ removeDialCode(value.e164Number, iso2));
12468
+ }
12469
+ const stripped = removeDialCode(value, iso2);
12470
+ // removeDialCode returns full digits when no dial matched — still fine as national.
12471
+ return stripped;
12472
+ }
12473
+
12474
+ /**
12475
+ * Phone input form control exports.
12476
+ */
12477
+
11490
12478
  let nextRadioId = 0;
11491
12479
  /**
11492
12480
  * Radio group following the shared AFRICANIES form field pattern.
@@ -13527,7 +14515,7 @@ class SegmentComponent {
13527
14515
  }
13528
14516
  }
13529
14517
  </div>
13530
- `, isInline: true, styles: [":host .africanies-segment-thumb{width:calc((100% - .5rem)/2)}\n"], dependencies: [{ kind: "component", type: AfricaniesIconComponent, selector: "africanies-icon", inputs: ["name", "size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
14518
+ `, isInline: true, styles: [":host .africanies-segment-thumb{width:calc((100% - .75rem)/2)}\n"], dependencies: [{ kind: "component", type: AfricaniesIconComponent, selector: "africanies-icon", inputs: ["name", "size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
13531
14519
  }
13532
14520
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SegmentComponent, decorators: [{
13533
14521
  type: Component,
@@ -13589,7 +14577,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
13589
14577
  }
13590
14578
  }
13591
14579
  </div>
13592
- `, styles: [":host .africanies-segment-thumb{width:calc((100% - .5rem)/2)}\n"] }]
14580
+ `, styles: [":host .africanies-segment-thumb{width:calc((100% - .75rem)/2)}\n"] }]
13593
14581
  }], ctorParameters: () => [], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], activeId: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeId", required: false }] }, { type: i0.Output, args: ["activeIdChange"] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], linkActiveOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "linkActiveOptions", required: false }] }], keepScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "keepScroll", required: false }] }] } });
13594
14582
 
13595
14583
  const PANEL_OPEN_STORAGE_KEY = 'africanies-shipping-mode-panel-open';
@@ -19745,6 +20733,7 @@ const FORM_CONTROLS = [
19745
20733
  DatePickerComponent,
19746
20734
  FileUploadComponent,
19747
20735
  OtpInputComponent,
20736
+ PhoneInputComponent,
19748
20737
  ];
19749
20738
  /**
19750
20739
  * All form controls in one import for apps that prefer NgModules.
@@ -19771,7 +20760,8 @@ class AfricaniesFormsModule {
19771
20760
  ToggleComponent,
19772
20761
  DatePickerComponent,
19773
20762
  FileUploadComponent,
19774
- OtpInputComponent], exports: [TextInputComponent,
20763
+ OtpInputComponent,
20764
+ PhoneInputComponent], exports: [TextInputComponent,
19775
20765
  TextareaComponent,
19776
20766
  NumberInputComponent,
19777
20767
  SelectComponent,
@@ -19781,12 +20771,14 @@ class AfricaniesFormsModule {
19781
20771
  ToggleComponent,
19782
20772
  DatePickerComponent,
19783
20773
  FileUploadComponent,
19784
- OtpInputComponent] });
20774
+ OtpInputComponent,
20775
+ PhoneInputComponent] });
19785
20776
  static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AfricaniesFormsModule, imports: [SelectComponent,
19786
20777
  CheckboxComponent,
19787
20778
  ToggleComponent,
19788
20779
  FileUploadComponent,
19789
- OtpInputComponent] });
20780
+ OtpInputComponent,
20781
+ PhoneInputComponent] });
19790
20782
  }
19791
20783
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AfricaniesFormsModule, decorators: [{
19792
20784
  type: NgModule,
@@ -20009,5 +21001,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
20009
21001
  * Generated bundle index. Do not edit.
20010
21002
  */
20011
21003
 
20012
- export { AFRICANIES_BRAND_LOGO_MINI_URL, AFRICANIES_BRAND_LOGO_URL, AccordionComponent, ActionMenuComponent, ActionMenuTriggerDirective, AddressInputComponent, AfricaniesActionsModule, AfricaniesFeedbackModule, AfricaniesFormsModule, AfricaniesInfoPopoverModule, AfricaniesNavigationModule, AfricaniesOverlayRef, AfricaniesStepperModule, AfricaniesTableModule, AfricaniesTooltipModule, AlertComponent, AppShellComponent, AppShellContentHeaderComponent, AppShellHeaderComponent, AppShellHeaderEndDirective, AppShellHeaderSlotDirective, AppShellHeaderStartDirective, AsyncStateComponent, AvatarComponent, AvatarMenuComponent, BrandLogoComponent, BreadcrumbComponent, ButtonComponent, CarrierLogoComponent, CellDefDirective, CheckboxComponent, ChipComponent, ConfirmDialogComponent, ConfirmService, ContentStackComponent, CopyButtonComponent, DatePickerComponent, DrawerService, EmptyStateComponent, ErrorIndicatorComponent, ErrorStateComponent, FileUploadComponent, FilterDrawerPanel, FilterDrawerService, FilterQueryService, GOOGLE_PLACES_CONFIG, GooglePlacesService, HeaderCellDefDirective, ImageComponent, InfoPopoverComponent, InfoPopoverContentDirective, InfoPopoverTriggerDirective, LoadingStateComponent, MODAL_SIZE_PANEL_CLASS, ModalService, NotificationDrawerPanel, NotificationDrawerService, NumberInputComponent, OVERLAY_DATA, OtpInputComponent, OverlayFooterDirective, OverlayFrameComponent, OverlayHeaderDirective, PageHeaderComponent, PaginationComponent, RadioComponent, RowDetailDefDirective, SearchComboboxComponent, SegmentComponent, SelectComponent, ShippingModeSwitchComponent, SideNavComponent, StepDefDirective, StepperComponent, TOAST_DURATION_MS, TOAST_ICONS, TabDefDirective, TableComponent, TabsComponent, TextInputComponent, TextareaComponent, ToastService, ToggleComponent, TooltipComponent, TooltipTriggerDirective, acceptLabels, buildBreadcrumbsFromSideNav, deliveryVendorOptionsForStoredValue, deliveryVendorSelectOptions, deliveryVendorSelected, fileExtensionLabel, fileMatchesAccept, headerGreetingFirstName, headerGreetingPeriod, isCatalogRootRoute, isNavItemActive, isNestedChildRoute, navItemUrlTree, normalizeCarrierLogoSlug, normalizeNavPath, pickHeaderGreeting, provideAfricaniesToasts, provideAfricaniesUiOverlays, provideGooglePlaces, resolveCatalogRootLink, resolveContentBackTarget, resolveHeaderBackTarget, resolveParentPathFromRootSnapshot, toastFingerprint };
21004
+ export { AFRICANIES_BRAND_LOGO_MINI_URL, AFRICANIES_BRAND_LOGO_URL, AccordionComponent, ActionMenuComponent, ActionMenuTriggerDirective, AddressInputComponent, AfricaniesActionsModule, AfricaniesFeedbackModule, AfricaniesFormsModule, AfricaniesInfoPopoverModule, AfricaniesNavigationModule, AfricaniesOverlayRef, AfricaniesStepperModule, AfricaniesTableModule, AfricaniesTooltipModule, AlertComponent, AppShellComponent, AppShellContentHeaderComponent, AppShellHeaderComponent, AppShellHeaderEndDirective, AppShellHeaderSlotDirective, AppShellHeaderStartDirective, AsyncStateComponent, AvatarComponent, AvatarMenuComponent, BrandLogoComponent, BreadcrumbComponent, ButtonComponent, CarrierLogoComponent, CellDefDirective, CheckboxComponent, ChipComponent, ConfirmDialogComponent, ConfirmService, ContentStackComponent, CopyButtonComponent, DatePickerComponent, DrawerService, EmptyStateComponent, ErrorIndicatorComponent, ErrorStateComponent, FileUploadComponent, FilterDrawerPanel, FilterDrawerService, FilterQueryService, GOOGLE_PLACES_CONFIG, GooglePlacesService, HeaderCellDefDirective, ImageComponent, InfoPopoverComponent, InfoPopoverContentDirective, InfoPopoverTriggerDirective, LoadingStateComponent, MODAL_SIZE_PANEL_CLASS, ModalService, NotificationDrawerPanel, NotificationDrawerService, NumberInputComponent, OVERLAY_DATA, OtpInputComponent, OverlayFooterDirective, OverlayFrameComponent, OverlayHeaderDirective, PHONE_DIAL_CODES, PHONE_MAX_NATIONAL_DIGITS, PHONE_MIN_NATIONAL_DIGITS, PageHeaderComponent, PaginationComponent, PhoneInputComponent, RadioComponent, RowDetailDefDirective, SearchComboboxComponent, SegmentComponent, SelectComponent, ShippingModeSwitchComponent, SideNavComponent, StepDefDirective, StepperComponent, TOAST_DURATION_MS, TOAST_ICONS, TabDefDirective, TableComponent, TabsComponent, TextInputComponent, TextareaComponent, ToastService, ToggleComponent, TooltipComponent, TooltipTriggerDirective, acceptLabels, buildBreadcrumbsFromSideNav, buildPhoneNumberValue, deliveryVendorOptionsForStoredValue, deliveryVendorSelectOptions, deliveryVendorSelected, dialCodeForIso2, fileExtensionLabel, fileMatchesAccept, formatNationalDigits, headerGreetingFirstName, headerGreetingPeriod, isCatalogRootRoute, isNavItemActive, isNestedChildRoute, isPhoneNumberComplete, matchDialCode, navItemUrlTree, normalizeCarrierLogoSlug, normalizeNavPath, normalizePhoneIso2, parsePhoneControlValue, phoneCountryName, phoneCountryOptions, phoneDigitsOnly, phoneToE164, pickHeaderGreeting, provideAfricaniesToasts, provideAfricaniesUiOverlays, provideGooglePlaces, removeDialCode, resolveCatalogRootLink, resolveContentBackTarget, resolveHeaderBackTarget, resolveParentPathFromRootSnapshot, toastFingerprint };
20013
21005
  //# sourceMappingURL=africanies-africanies-ui.mjs.map