@africanies/angular-web-sdk 0.1.10 → 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 (98) hide show
  1. package/.nx/cache/{14995846848874973576 → 14892813664845064572}/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs +1634 -1016
  2. package/.nx/cache/14892813664845064572/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs.map +1 -0
  3. package/.nx/cache/{14995846848874973576 → 14892813664845064572}/dist/libs/africanies-ui/types/africanies-africanies-ui.d.ts +261 -137
  4. package/.nx/cache/{14876618240301288353 → 7821397806208783174}/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs +2641 -1011
  5. package/.nx/cache/7821397806208783174/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs.map +1 -0
  6. package/.nx/cache/{14876618240301288353 → 7821397806208783174}/dist/libs/africanies-ui/types/africanies-africanies-ui.d.ts +460 -147
  7. package/.nx/cache/run.json +16 -16
  8. package/.nx/cache/terminalOutputs/{14876618240301288353 → 14892813664845064572} +2 -2
  9. package/.nx/cache/terminalOutputs/16208231681037145050 +85 -0
  10. package/.nx/cache/terminalOutputs/{1446890025183346611 → 17909810599991457481} +15 -7
  11. package/.nx/cache/terminalOutputs/{7978448102466861029 → 2927637324428060203} +41 -31
  12. package/.nx/cache/terminalOutputs/{17394769338046050914 → 4787481949164239892} +2 -2
  13. package/.nx/cache/terminalOutputs/{14995846848874973576 → 7821397806208783174} +2 -2
  14. package/.nx/workspace-data/0091ABA9-5C90-580D-953C-8C94E763ADB5-v3.db +0 -0
  15. package/.nx/workspace-data/0091ABA9-5C90-580D-953C-8C94E763ADB5-v3.db-shm +0 -0
  16. package/.nx/workspace-data/0091ABA9-5C90-580D-953C-8C94E763ADB5-v3.db-wal +0 -0
  17. package/.nx/workspace-data/d/daemon.log +3694 -0
  18. package/.nx/workspace-data/d/server-process.json +2 -2
  19. package/.nx/workspace-data/file-map.json +1508 -1478
  20. package/.nx/workspace-data/nx_files.nxt +0 -0
  21. package/.nx/workspace-data/project-graph.json +2 -2
  22. package/README.md +0 -17
  23. package/apps/playground/src/app/pages/forms-page.ts +70 -14
  24. package/apps/playground/src/app/snippets/forms.snippets.ts +41 -6
  25. package/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs +1149 -142
  26. package/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs.map +1 -1
  27. package/dist/libs/africanies-ui/types/africanies-africanies-ui.d.ts +205 -18
  28. package/libs/africanies-ui/src/index.ts +18 -0
  29. package/libs/africanies-ui/src/lib/forms/index.ts +20 -0
  30. package/libs/africanies-ui/src/lib/forms/phone-input/index.ts +21 -0
  31. package/libs/africanies-ui/src/lib/forms/phone-input/phone-codes.ts +264 -0
  32. package/libs/africanies-ui/src/lib/forms/phone-input/phone-input.component.ts +477 -0
  33. package/libs/africanies-ui/src/lib/forms/phone-input/phone-input.types.ts +35 -0
  34. package/libs/africanies-ui/src/lib/forms/phone-input/phone-input.utils.spec.ts +81 -0
  35. package/libs/africanies-ui/src/lib/forms/phone-input/phone-input.utils.ts +275 -0
  36. package/libs/africanies-ui/src/lib/modules/africanies-forms.module.ts +2 -0
  37. package/libs/africanies-ui/src/lib/navigation/segment/segment.component.ts +2 -1
  38. package/libs/africanies-ui/src/lib/navigation/shipping-mode-switch/shipping-mode-switch.component.spec.ts +15 -0
  39. package/libs/africanies-ui/src/lib/navigation/shipping-mode-switch/shipping-mode-switch.component.ts +6 -3
  40. package/libs/africanies-ui/src/lib/table/table.component.ts +70 -65
  41. package/package.json +1 -1
  42. package/.nx/cache/13466509747676776487/dist/libs/africanies-core/README.md +0 -85
  43. package/.nx/cache/13466509747676776487/dist/libs/africanies-core/fesm2022/africanies-africanies-core.mjs +0 -4634
  44. package/.nx/cache/13466509747676776487/dist/libs/africanies-core/fesm2022/africanies-africanies-core.mjs.map +0 -1
  45. package/.nx/cache/13466509747676776487/dist/libs/africanies-core/package.json +0 -31
  46. package/.nx/cache/13466509747676776487/dist/libs/africanies-core/types/africanies-africanies-core.d.ts +0 -2743
  47. package/.nx/cache/14416694322692463866/dist/libs/africanies-models/README.md +0 -60
  48. package/.nx/cache/14416694322692463866/dist/libs/africanies-models/fesm2022/africanies-africanies-models.mjs +0 -599
  49. package/.nx/cache/14416694322692463866/dist/libs/africanies-models/fesm2022/africanies-africanies-models.mjs.map +0 -1
  50. package/.nx/cache/14416694322692463866/dist/libs/africanies-models/package.json +0 -23
  51. package/.nx/cache/14416694322692463866/dist/libs/africanies-models/types/africanies-africanies-models.d.ts +0 -1452
  52. package/.nx/cache/14876618240301288353/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs.map +0 -1
  53. package/.nx/cache/14995846848874973576/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs.map +0 -1
  54. package/.nx/cache/17626862048742598274/dist/libs/africanies-theme/README.md +0 -46
  55. package/.nx/cache/17626862048742598274/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs +0 -221
  56. package/.nx/cache/17626862048742598274/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs.map +0 -1
  57. package/.nx/cache/17626862048742598274/dist/libs/africanies-theme/package.json +0 -35
  58. package/.nx/cache/17626862048742598274/dist/libs/africanies-theme/tailwind-preset.cjs +0 -253
  59. package/.nx/cache/17626862048742598274/dist/libs/africanies-theme/types/africanies-africanies-theme.d.ts +0 -166
  60. package/.nx/cache/6664915487114632770/dist/libs/africanies-icons/README.md +0 -69
  61. package/.nx/cache/6664915487114632770/dist/libs/africanies-icons/assets/icons.sprite.svg +0 -1844
  62. package/.nx/cache/6664915487114632770/dist/libs/africanies-icons/fesm2022/africanies-africanies-icons.mjs +0 -832
  63. package/.nx/cache/6664915487114632770/dist/libs/africanies-icons/fesm2022/africanies-africanies-icons.mjs.map +0 -1
  64. package/.nx/cache/6664915487114632770/dist/libs/africanies-icons/package.json +0 -30
  65. package/.nx/cache/6664915487114632770/dist/libs/africanies-icons/types/africanies-africanies-icons.d.ts +0 -108
  66. package/.nx/cache/6673686859704879504/dist/libs/africanies-theme/README.md +0 -46
  67. package/.nx/cache/6673686859704879504/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs +0 -231
  68. package/.nx/cache/6673686859704879504/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs.map +0 -1
  69. package/.nx/cache/6673686859704879504/dist/libs/africanies-theme/package.json +0 -35
  70. package/.nx/cache/6673686859704879504/dist/libs/africanies-theme/tailwind-preset.cjs +0 -262
  71. package/.nx/cache/6673686859704879504/dist/libs/africanies-theme/types/africanies-africanies-theme.d.ts +0 -174
  72. package/.nx/cache/9040451482998546630/dist/libs/africanies-core/README.md +0 -85
  73. package/.nx/cache/9040451482998546630/dist/libs/africanies-core/fesm2022/africanies-africanies-core.mjs +0 -4511
  74. package/.nx/cache/9040451482998546630/dist/libs/africanies-core/fesm2022/africanies-africanies-core.mjs.map +0 -1
  75. package/.nx/cache/9040451482998546630/dist/libs/africanies-core/package.json +0 -31
  76. package/.nx/cache/9040451482998546630/dist/libs/africanies-core/types/africanies-africanies-core.d.ts +0 -2741
  77. package/.nx/cache/terminalOutputs/13466509747676776487 +0 -21
  78. package/.nx/cache/terminalOutputs/13555699813138069787 +0 -6
  79. package/.nx/cache/terminalOutputs/14061940909886036014 +0 -173
  80. package/.nx/cache/terminalOutputs/14416694322692463866 +0 -108
  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/9040451482998546630 +0 -21
  87. /package/.nx/cache/{14876618240301288353 → 14892813664845064572}/dist/libs/africanies-ui/README.md +0 -0
  88. /package/.nx/cache/{14876618240301288353 → 14892813664845064572}/dist/libs/africanies-ui/assets/brand/africanies-logo-mini.png +0 -0
  89. /package/.nx/cache/{14876618240301288353 → 14892813664845064572}/dist/libs/africanies-ui/assets/brand/africanies-logo.png +0 -0
  90. /package/.nx/cache/{14876618240301288353 → 14892813664845064572}/dist/libs/africanies-ui/assets/brand/africanies-logo.svg +0 -0
  91. /package/.nx/cache/{14876618240301288353 → 14892813664845064572}/dist/libs/africanies-ui/assets/carriers/dhl.svg +0 -0
  92. /package/.nx/cache/{14876618240301288353 → 14892813664845064572}/dist/libs/africanies-ui/package.json +0 -0
  93. /package/.nx/cache/{14995846848874973576 → 7821397806208783174}/dist/libs/africanies-ui/README.md +0 -0
  94. /package/.nx/cache/{14995846848874973576 → 7821397806208783174}/dist/libs/africanies-ui/assets/brand/africanies-logo-mini.png +0 -0
  95. /package/.nx/cache/{14995846848874973576 → 7821397806208783174}/dist/libs/africanies-ui/assets/brand/africanies-logo.png +0 -0
  96. /package/.nx/cache/{14995846848874973576 → 7821397806208783174}/dist/libs/africanies-ui/assets/brand/africanies-logo.svg +0 -0
  97. /package/.nx/cache/{14995846848874973576 → 7821397806208783174}/dist/libs/africanies-ui/assets/carriers/dhl.svg +0 -0
  98. /package/.nx/cache/{14995846848874973576 → 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';
@@ -13773,9 +14761,12 @@ class ShippingModeSwitchComponent {
13773
14761
  >
13774
14762
  Shipping mode
13775
14763
  </p>
13776
- <africanies-chip [variant]="modeChipVariant()" size="sm">
13777
- {{ modeChipLabel() }}
13778
- </africanies-chip>
14764
+ <!-- STN / SFN chip only when the tiles are collapsed — open panel already shows both modes. -->
14765
+ @if (!panelOpen()) {
14766
+ <africanies-chip [variant]="modeChipVariant()" size="sm">
14767
+ {{ modeChipLabel() }}
14768
+ </africanies-chip>
14769
+ }
13779
14770
  <span class="min-w-0 flex-1" aria-hidden="true"></span>
13780
14771
  <button
13781
14772
  type="button"
@@ -13915,9 +14906,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
13915
14906
  >
13916
14907
  Shipping mode
13917
14908
  </p>
13918
- <africanies-chip [variant]="modeChipVariant()" size="sm">
13919
- {{ modeChipLabel() }}
13920
- </africanies-chip>
14909
+ <!-- STN / SFN chip only when the tiles are collapsed — open panel already shows both modes. -->
14910
+ @if (!panelOpen()) {
14911
+ <africanies-chip [variant]="modeChipVariant()" size="sm">
14912
+ {{ modeChipLabel() }}
14913
+ </africanies-chip>
14914
+ }
13921
14915
  <span class="min-w-0 flex-1" aria-hidden="true"></span>
13922
14916
  <button
13923
14917
  type="button"
@@ -18014,8 +19008,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
18014
19008
  * `<ng-template africaniesCellDef="key">` templates. Columns without a matching
18015
19009
  * template fall back to rendering `row[key]` as plain text.
18016
19010
  *
18017
- * Optional toolbar: top-left **shipping mode** segment (on by default;
18018
- * `[showShippingMode]="false"` to hide) and **Refresh** (`showRefresh` →
19011
+ * Optional toolbar: top-left **shipping mode** segment on its own row above
19012
+ * Refresh / Filter / Export (on by default; `[showShippingMode]="false"` to
19013
+ * hide) and **Refresh** (`showRefresh` →
18019
19014
  * {@link refreshClick}). Refresh is hidden while
18020
19015
  * the body shows empty or error — those states expose Retry instead.
18021
19016
  * While {@link refreshing} is true the rows stay on screen — the refresh icon
@@ -18635,71 +19630,75 @@ class TableComponent {
18635
19630
  showFilter() ||
18636
19631
  showExport()
18637
19632
  ) {
18638
- <div class="flex flex-wrap items-center justify-between gap-2">
18639
- <div class="flex min-w-0 flex-wrap items-center gap-2">
18640
- @if (showShippingMode()) {
18641
- <africanies-segment
18642
- class="min-w-0"
18643
- [items]="shippingModeItems"
18644
- [activeId]="shippingModeActiveId()"
18645
- ariaLabel="Shipping mode"
18646
- (activeIdChange)="onShippingModeChange($event)"
18647
- />
18648
- }
18649
- @if (showToolbarRefresh()) {
18650
- <button
18651
- africanies-button
18652
- type="button"
18653
- variant="flat"
18654
- size="sm"
18655
- [disabled]="loading() || refreshing()"
18656
- [attr.aria-label]="refreshLabel()"
18657
- (click)="refreshClick.emit()"
18658
- >
18659
- <africanies-icon
18660
- name="refresh"
18661
- [size]="16"
18662
- [class]="refreshing() ? 'animate-spin' : ''"
18663
- />
18664
- {{ refreshLabel() }}
18665
- </button>
18666
- }
18667
- </div>
18668
- <div class="flex items-center gap-2">
18669
- @if (showFilter()) {
18670
- <button
18671
- africanies-button
18672
- type="button"
18673
- variant="flat"
18674
- size="sm"
18675
- [attr.aria-label]="filterLabel()"
18676
- (click)="filterClick.emit()"
18677
- >
18678
- <africanies-icon name="filter" [size]="16" />
18679
- {{ filterLabel() }}
18680
- @if (filterCount() > 0) {
18681
- <span
18682
- class="inline-flex min-w-5 items-center justify-center rounded-full bg-ink px-1.5 py-0.5 text-caption font-semibold tabular-nums text-white dark:bg-white dark:text-ink"
19633
+ <div class="flex w-full min-w-0 flex-col gap-3">
19634
+ @if (showShippingMode()) {
19635
+ <africanies-segment
19636
+ class="min-w-0 self-start"
19637
+ [items]="shippingModeItems"
19638
+ [activeId]="shippingModeActiveId()"
19639
+ ariaLabel="Shipping mode"
19640
+ (activeIdChange)="onShippingModeChange($event)"
19641
+ />
19642
+ }
19643
+ @if (showToolbarRefresh() || showFilter() || showExport()) {
19644
+ <div class="flex flex-wrap items-center justify-between gap-2">
19645
+ <div class="flex min-w-0 flex-wrap items-center gap-2">
19646
+ @if (showToolbarRefresh()) {
19647
+ <button
19648
+ africanies-button
19649
+ type="button"
19650
+ variant="flat"
19651
+ size="sm"
19652
+ [disabled]="loading() || refreshing()"
19653
+ [attr.aria-label]="refreshLabel()"
19654
+ (click)="refreshClick.emit()"
18683
19655
  >
18684
- {{ filterCount() }}
18685
- </span>
19656
+ <africanies-icon
19657
+ name="refresh"
19658
+ [size]="16"
19659
+ [class]="refreshing() ? 'animate-spin' : ''"
19660
+ />
19661
+ {{ refreshLabel() }}
19662
+ </button>
18686
19663
  }
18687
- </button>
18688
- }
18689
- @if (showExport()) {
18690
- <button
18691
- africanies-button
18692
- type="button"
18693
- variant="flat"
18694
- size="sm"
18695
- [attr.aria-label]="exportLabel()"
18696
- (click)="exportClick.emit()"
18697
- >
18698
- <africanies-icon name="download" [size]="16" />
18699
- {{ exportLabel() }}
18700
- </button>
18701
- }
18702
- </div>
19664
+ </div>
19665
+ <div class="flex items-center gap-2">
19666
+ @if (showFilter()) {
19667
+ <button
19668
+ africanies-button
19669
+ type="button"
19670
+ variant="flat"
19671
+ size="sm"
19672
+ [attr.aria-label]="filterLabel()"
19673
+ (click)="filterClick.emit()"
19674
+ >
19675
+ <africanies-icon name="filter" [size]="16" />
19676
+ {{ filterLabel() }}
19677
+ @if (filterCount() > 0) {
19678
+ <span
19679
+ class="inline-flex min-w-5 items-center justify-center rounded-full bg-ink px-1.5 py-0.5 text-caption font-semibold tabular-nums text-white dark:bg-white dark:text-ink"
19680
+ >
19681
+ {{ filterCount() }}
19682
+ </span>
19683
+ }
19684
+ </button>
19685
+ }
19686
+ @if (showExport()) {
19687
+ <button
19688
+ africanies-button
19689
+ type="button"
19690
+ variant="flat"
19691
+ size="sm"
19692
+ [attr.aria-label]="exportLabel()"
19693
+ (click)="exportClick.emit()"
19694
+ >
19695
+ <africanies-icon name="download" [size]="16" />
19696
+ {{ exportLabel() }}
19697
+ </button>
19698
+ }
19699
+ </div>
19700
+ </div>
19701
+ }
18703
19702
  </div>
18704
19703
  }
18705
19704
 
@@ -18977,71 +19976,75 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
18977
19976
  showFilter() ||
18978
19977
  showExport()
18979
19978
  ) {
18980
- <div class="flex flex-wrap items-center justify-between gap-2">
18981
- <div class="flex min-w-0 flex-wrap items-center gap-2">
18982
- @if (showShippingMode()) {
18983
- <africanies-segment
18984
- class="min-w-0"
18985
- [items]="shippingModeItems"
18986
- [activeId]="shippingModeActiveId()"
18987
- ariaLabel="Shipping mode"
18988
- (activeIdChange)="onShippingModeChange($event)"
18989
- />
18990
- }
18991
- @if (showToolbarRefresh()) {
18992
- <button
18993
- africanies-button
18994
- type="button"
18995
- variant="flat"
18996
- size="sm"
18997
- [disabled]="loading() || refreshing()"
18998
- [attr.aria-label]="refreshLabel()"
18999
- (click)="refreshClick.emit()"
19000
- >
19001
- <africanies-icon
19002
- name="refresh"
19003
- [size]="16"
19004
- [class]="refreshing() ? 'animate-spin' : ''"
19005
- />
19006
- {{ refreshLabel() }}
19007
- </button>
19008
- }
19009
- </div>
19010
- <div class="flex items-center gap-2">
19011
- @if (showFilter()) {
19012
- <button
19013
- africanies-button
19014
- type="button"
19015
- variant="flat"
19016
- size="sm"
19017
- [attr.aria-label]="filterLabel()"
19018
- (click)="filterClick.emit()"
19019
- >
19020
- <africanies-icon name="filter" [size]="16" />
19021
- {{ filterLabel() }}
19022
- @if (filterCount() > 0) {
19023
- <span
19024
- class="inline-flex min-w-5 items-center justify-center rounded-full bg-ink px-1.5 py-0.5 text-caption font-semibold tabular-nums text-white dark:bg-white dark:text-ink"
19979
+ <div class="flex w-full min-w-0 flex-col gap-3">
19980
+ @if (showShippingMode()) {
19981
+ <africanies-segment
19982
+ class="min-w-0 self-start"
19983
+ [items]="shippingModeItems"
19984
+ [activeId]="shippingModeActiveId()"
19985
+ ariaLabel="Shipping mode"
19986
+ (activeIdChange)="onShippingModeChange($event)"
19987
+ />
19988
+ }
19989
+ @if (showToolbarRefresh() || showFilter() || showExport()) {
19990
+ <div class="flex flex-wrap items-center justify-between gap-2">
19991
+ <div class="flex min-w-0 flex-wrap items-center gap-2">
19992
+ @if (showToolbarRefresh()) {
19993
+ <button
19994
+ africanies-button
19995
+ type="button"
19996
+ variant="flat"
19997
+ size="sm"
19998
+ [disabled]="loading() || refreshing()"
19999
+ [attr.aria-label]="refreshLabel()"
20000
+ (click)="refreshClick.emit()"
19025
20001
  >
19026
- {{ filterCount() }}
19027
- </span>
20002
+ <africanies-icon
20003
+ name="refresh"
20004
+ [size]="16"
20005
+ [class]="refreshing() ? 'animate-spin' : ''"
20006
+ />
20007
+ {{ refreshLabel() }}
20008
+ </button>
19028
20009
  }
19029
- </button>
19030
- }
19031
- @if (showExport()) {
19032
- <button
19033
- africanies-button
19034
- type="button"
19035
- variant="flat"
19036
- size="sm"
19037
- [attr.aria-label]="exportLabel()"
19038
- (click)="exportClick.emit()"
19039
- >
19040
- <africanies-icon name="download" [size]="16" />
19041
- {{ exportLabel() }}
19042
- </button>
19043
- }
19044
- </div>
20010
+ </div>
20011
+ <div class="flex items-center gap-2">
20012
+ @if (showFilter()) {
20013
+ <button
20014
+ africanies-button
20015
+ type="button"
20016
+ variant="flat"
20017
+ size="sm"
20018
+ [attr.aria-label]="filterLabel()"
20019
+ (click)="filterClick.emit()"
20020
+ >
20021
+ <africanies-icon name="filter" [size]="16" />
20022
+ {{ filterLabel() }}
20023
+ @if (filterCount() > 0) {
20024
+ <span
20025
+ class="inline-flex min-w-5 items-center justify-center rounded-full bg-ink px-1.5 py-0.5 text-caption font-semibold tabular-nums text-white dark:bg-white dark:text-ink"
20026
+ >
20027
+ {{ filterCount() }}
20028
+ </span>
20029
+ }
20030
+ </button>
20031
+ }
20032
+ @if (showExport()) {
20033
+ <button
20034
+ africanies-button
20035
+ type="button"
20036
+ variant="flat"
20037
+ size="sm"
20038
+ [attr.aria-label]="exportLabel()"
20039
+ (click)="exportClick.emit()"
20040
+ >
20041
+ <africanies-icon name="download" [size]="16" />
20042
+ {{ exportLabel() }}
20043
+ </button>
20044
+ }
20045
+ </div>
20046
+ </div>
20047
+ }
19045
20048
  </div>
19046
20049
  }
19047
20050
 
@@ -19730,6 +20733,7 @@ const FORM_CONTROLS = [
19730
20733
  DatePickerComponent,
19731
20734
  FileUploadComponent,
19732
20735
  OtpInputComponent,
20736
+ PhoneInputComponent,
19733
20737
  ];
19734
20738
  /**
19735
20739
  * All form controls in one import for apps that prefer NgModules.
@@ -19756,7 +20760,8 @@ class AfricaniesFormsModule {
19756
20760
  ToggleComponent,
19757
20761
  DatePickerComponent,
19758
20762
  FileUploadComponent,
19759
- OtpInputComponent], exports: [TextInputComponent,
20763
+ OtpInputComponent,
20764
+ PhoneInputComponent], exports: [TextInputComponent,
19760
20765
  TextareaComponent,
19761
20766
  NumberInputComponent,
19762
20767
  SelectComponent,
@@ -19766,12 +20771,14 @@ class AfricaniesFormsModule {
19766
20771
  ToggleComponent,
19767
20772
  DatePickerComponent,
19768
20773
  FileUploadComponent,
19769
- OtpInputComponent] });
20774
+ OtpInputComponent,
20775
+ PhoneInputComponent] });
19770
20776
  static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AfricaniesFormsModule, imports: [SelectComponent,
19771
20777
  CheckboxComponent,
19772
20778
  ToggleComponent,
19773
20779
  FileUploadComponent,
19774
- OtpInputComponent] });
20780
+ OtpInputComponent,
20781
+ PhoneInputComponent] });
19775
20782
  }
19776
20783
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AfricaniesFormsModule, decorators: [{
19777
20784
  type: NgModule,
@@ -19994,5 +21001,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
19994
21001
  * Generated bundle index. Do not edit.
19995
21002
  */
19996
21003
 
19997
- 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 };
19998
21005
  //# sourceMappingURL=africanies-africanies-ui.mjs.map