@sneat/components 0.1.3 → 0.1.4

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 (170) hide show
  1. package/esm2022/index.js +15 -0
  2. package/esm2022/index.js.map +1 -0
  3. package/esm2022/lib/app-version/app-version.component.js +16 -0
  4. package/esm2022/lib/app-version/app-version.component.js.map +1 -0
  5. package/esm2022/lib/app-version/build-info.js +5 -0
  6. package/esm2022/lib/app-version/build-info.js.map +1 -0
  7. package/esm2022/lib/app-version/index.js +3 -0
  8. package/esm2022/lib/app-version/index.js.map +1 -0
  9. package/esm2022/lib/card-list/index.js +2 -0
  10. package/esm2022/lib/card-list/index.js.map +1 -0
  11. package/esm2022/lib/card-list/sneat-card-list.component.js +106 -0
  12. package/esm2022/lib/card-list/sneat-card-list.component.js.map +1 -0
  13. package/esm2022/lib/copyright/copyright.component.js +11 -0
  14. package/esm2022/lib/copyright/copyright.component.js.map +1 -0
  15. package/esm2022/lib/copyright/index.js +2 -0
  16. package/esm2022/lib/copyright/index.js.map +1 -0
  17. package/esm2022/lib/country-input/country-input.component.js +59 -0
  18. package/esm2022/lib/country-input/country-input.component.js.map +1 -0
  19. package/esm2022/lib/country-input/index.js +2 -0
  20. package/esm2022/lib/country-input/index.js.map +1 -0
  21. package/esm2022/lib/country-selector/countries-loader.service.js +91 -0
  22. package/esm2022/lib/country-selector/countries-loader.service.js.map +1 -0
  23. package/esm2022/lib/country-selector/countries.js +22 -0
  24. package/esm2022/lib/country-selector/countries.js.map +1 -0
  25. package/esm2022/lib/country-selector/country-selector.component.js +103 -0
  26. package/esm2022/lib/country-selector/country-selector.component.js.map +1 -0
  27. package/esm2022/lib/country-selector/country-selector.service.js +15 -0
  28. package/esm2022/lib/country-selector/country-selector.service.js.map +1 -0
  29. package/esm2022/lib/country-selector/index.js +5 -0
  30. package/esm2022/lib/country-selector/index.js.map +1 -0
  31. package/esm2022/lib/date-input/date-input.component.js +70 -0
  32. package/esm2022/lib/date-input/date-input.component.js.map +1 -0
  33. package/esm2022/lib/date-input/date-modal.component.js +53 -0
  34. package/esm2022/lib/date-input/date-modal.component.js.map +1 -0
  35. package/esm2022/lib/dialog-header/dialog-header.component.js +23 -0
  36. package/esm2022/lib/dialog-header/dialog-header.component.js.map +1 -0
  37. package/esm2022/lib/dialog-header/index.js +2 -0
  38. package/esm2022/lib/dialog-header/index.js.map +1 -0
  39. package/esm2022/lib/error-card/index.js +2 -0
  40. package/esm2022/lib/error-card/index.js.map +1 -0
  41. package/esm2022/lib/error-card/sneat-error-card.component.js +23 -0
  42. package/esm2022/lib/error-card/sneat-error-card.component.js.map +1 -0
  43. package/esm2022/lib/filter-item/filter-item.component.js +37 -0
  44. package/esm2022/lib/filter-item/filter-item.component.js.map +1 -0
  45. package/esm2022/lib/filter-item/index.js +2 -0
  46. package/esm2022/lib/filter-item/index.js.map +1 -0
  47. package/esm2022/lib/pipes/country-emoji.pipe.js +69 -0
  48. package/esm2022/lib/pipes/country-emoji.pipe.js.map +1 -0
  49. package/esm2022/lib/pipes/decimal64p2.pipe.js +47 -0
  50. package/esm2022/lib/pipes/decimal64p2.pipe.js.map +1 -0
  51. package/esm2022/lib/pipes/gender.pipes.js +69 -0
  52. package/esm2022/lib/pipes/gender.pipes.js.map +1 -0
  53. package/esm2022/lib/pipes/index.js +7 -0
  54. package/esm2022/lib/pipes/index.js.map +1 -0
  55. package/esm2022/lib/pipes/long-month-name.pipe.js +41 -0
  56. package/esm2022/lib/pipes/long-month-name.pipe.js.map +1 -0
  57. package/esm2022/lib/pipes/short-month-name.pipe.js +31 -0
  58. package/esm2022/lib/pipes/short-month-name.pipe.js.map +1 -0
  59. package/esm2022/lib/pipes/team-emoji.pipe.js +31 -0
  60. package/esm2022/lib/pipes/team-emoji.pipe.js.map +1 -0
  61. package/esm2022/lib/save-event.js +2 -0
  62. package/esm2022/lib/save-event.js.map +1 -0
  63. package/esm2022/lib/user-country/user-country.component.js +136 -0
  64. package/esm2022/lib/user-country/user-country.component.js.map +1 -0
  65. package/esm2022/lib/virtual-slider/virtual-slider.js +83 -0
  66. package/esm2022/lib/virtual-slider/virtual-slider.js.map +1 -0
  67. package/esm2022/sneat-components.js +5 -0
  68. package/esm2022/sneat-components.js.map +1 -0
  69. package/lib/app-version/app-version.component.d.ts +9 -0
  70. package/lib/app-version/build-info.d.ts +4 -0
  71. package/lib/card-list/sneat-card-list.component.d.ts +43 -0
  72. package/lib/copyright/copyright.component.d.ts +5 -0
  73. package/lib/country-input/country-input.component.d.ts +16 -0
  74. package/lib/country-selector/countries-loader.service.d.ts +43 -0
  75. package/lib/country-selector/countries.d.ts +25 -0
  76. package/lib/country-selector/country-selector.component.d.ts +31 -0
  77. package/lib/country-selector/country-selector.service.d.ts +8 -0
  78. package/lib/date-input/date-input.component.d.ts +21 -0
  79. package/lib/date-input/date-modal.component.d.ts +13 -0
  80. package/lib/dialog-header/dialog-header.component.d.ts +8 -0
  81. package/lib/error-card/sneat-error-card.component.d.ts +8 -0
  82. package/lib/filter-item/filter-item.component.d.ts +13 -0
  83. package/lib/pipes/country-emoji.pipe.d.ts +29 -0
  84. package/lib/pipes/decimal64p2.pipe.d.ts +12 -0
  85. package/lib/pipes/gender.pipes.d.ts +20 -0
  86. package/lib/pipes/long-month-name.pipe.d.ts +7 -0
  87. package/lib/pipes/short-month-name.pipe.d.ts +8 -0
  88. package/lib/pipes/team-emoji.pipe.d.ts +8 -0
  89. package/lib/save-event.d.ts +5 -0
  90. package/lib/user-country/user-country.component.d.ts +24 -0
  91. package/lib/virtual-slider/virtual-slider.d.ts +13 -0
  92. package/package.json +14 -2
  93. package/sneat-components.d.ts +5 -0
  94. package/eslint.config.js +0 -7
  95. package/ng-package.json +0 -10
  96. package/project.json +0 -38
  97. package/src/assets/data/countries.json +0 -1730
  98. package/src/lib/app-version/app-version.component.html +0 -15
  99. package/src/lib/app-version/app-version.component.spec.ts +0 -25
  100. package/src/lib/app-version/app-version.component.ts +0 -17
  101. package/src/lib/app-version/build-info.ts +0 -8
  102. package/src/lib/card-list/sneat-card-list.component.html +0 -108
  103. package/src/lib/card-list/sneat-card-list.component.spec.ts +0 -131
  104. package/src/lib/card-list/sneat-card-list.component.ts +0 -125
  105. package/src/lib/copyright/copyright.component.html +0 -1
  106. package/src/lib/copyright/copyright.component.spec.ts +0 -24
  107. package/src/lib/copyright/copyright.component.ts +0 -7
  108. package/src/lib/country-input/country-input.component.html +0 -33
  109. package/src/lib/country-input/country-input.component.spec.ts +0 -84
  110. package/src/lib/country-input/country-input.component.ts +0 -76
  111. package/src/lib/country-selector/countries-loader.service.spec.ts +0 -149
  112. package/src/lib/country-selector/countries-loader.service.ts +0 -100
  113. package/src/lib/country-selector/countries.ts +0 -42
  114. package/src/lib/country-selector/country-selector.component.html +0 -24
  115. package/src/lib/country-selector/country-selector.component.spec.ts +0 -5
  116. package/src/lib/country-selector/country-selector.component.ts +0 -125
  117. package/src/lib/country-selector/country-selector.service.spec.ts +0 -23
  118. package/src/lib/country-selector/country-selector.service.ts +0 -11
  119. package/src/lib/date-input/date-input.component.html +0 -39
  120. package/src/lib/date-input/date-input.component.spec.ts +0 -179
  121. package/src/lib/date-input/date-input.component.ts +0 -97
  122. package/src/lib/date-input/date-modal.component.html +0 -23
  123. package/src/lib/date-input/date-modal.component.spec.ts +0 -105
  124. package/src/lib/date-input/date-modal.component.ts +0 -67
  125. package/src/lib/dialog-header/dialog-header.component.html +0 -8
  126. package/src/lib/dialog-header/dialog-header.component.spec.ts +0 -67
  127. package/src/lib/dialog-header/dialog-header.component.ts +0 -26
  128. package/src/lib/dismissable.ts +0 -6
  129. package/src/lib/error-card/sneat-error-card.component.html +0 -20
  130. package/src/lib/error-card/sneat-error-card.component.spec.ts +0 -49
  131. package/src/lib/error-card/sneat-error-card.component.ts +0 -28
  132. package/src/lib/filter-item/filter-item.component.html +0 -19
  133. package/src/lib/filter-item/filter-item.component.spec.ts +0 -83
  134. package/src/lib/filter-item/filter-item.component.ts +0 -47
  135. package/src/lib/pipes/country-emoji.pipe.spec.ts +0 -116
  136. package/src/lib/pipes/country-emoji.pipe.ts +0 -67
  137. package/src/lib/pipes/decimal64p2.pipe.spec.ts +0 -61
  138. package/src/lib/pipes/decimal64p2.pipe.ts +0 -35
  139. package/src/lib/pipes/gender.pipes.spec.ts +0 -84
  140. package/src/lib/pipes/gender.pipes.ts +0 -65
  141. package/src/lib/pipes/long-month-name.pipe.spec.ts +0 -36
  142. package/src/lib/pipes/long-month-name.pipe.ts +0 -35
  143. package/src/lib/pipes/short-month-name.pipe.spec.ts +0 -28
  144. package/src/lib/pipes/short-month-name.pipe.ts +0 -26
  145. package/src/lib/pipes/team-emoji.pipe.spec.ts +0 -27
  146. package/src/lib/pipes/team-emoji.pipe.ts +0 -26
  147. package/src/lib/save-event.ts +0 -5
  148. package/src/lib/test-ide-bug.ts +0 -24
  149. package/src/lib/user-country/user-country.component.html +0 -44
  150. package/src/lib/user-country/user-country.component.spec.ts +0 -136
  151. package/src/lib/user-country/user-country.component.ts +0 -172
  152. package/src/lib/virtual-slider/odd-even-virtual-slider.ts +0 -1
  153. package/src/lib/virtual-slider/virtual-slider.ts +0 -130
  154. package/src/lib/webstorm-type-err-demo.component.ts +0 -35
  155. package/src/test-setup.ts +0 -3
  156. package/tsconfig.json +0 -13
  157. package/tsconfig.lib.json +0 -19
  158. package/tsconfig.lib.prod.json +0 -7
  159. package/tsconfig.spec.json +0 -31
  160. package/vite.config.mts +0 -10
  161. /package/{src/index.ts → index.d.ts} +0 -0
  162. /package/{src/lib/app-version/index.ts → lib/app-version/index.d.ts} +0 -0
  163. /package/{src/lib/card-list/index.ts → lib/card-list/index.d.ts} +0 -0
  164. /package/{src/lib/copyright/index.ts → lib/copyright/index.d.ts} +0 -0
  165. /package/{src/lib/country-input/index.ts → lib/country-input/index.d.ts} +0 -0
  166. /package/{src/lib/country-selector/index.ts → lib/country-selector/index.d.ts} +0 -0
  167. /package/{src/lib/dialog-header/index.ts → lib/dialog-header/index.d.ts} +0 -0
  168. /package/{src/lib/error-card/index.ts → lib/error-card/index.d.ts} +0 -0
  169. /package/{src/lib/filter-item/index.ts → lib/filter-item/index.d.ts} +0 -0
  170. /package/{src/lib/pipes/index.ts → lib/pipes/index.d.ts} +0 -0
@@ -0,0 +1,15 @@
1
+ export * from './lib/app-version';
2
+ export * from './lib/pipes';
3
+ export * from './lib/virtual-slider/virtual-slider';
4
+ export * from './lib/card-list';
5
+ export * from './lib/error-card';
6
+ export * from './lib/country-selector';
7
+ export * from './lib/filter-item';
8
+ export * from './lib/copyright';
9
+ export * from './lib/dialog-header';
10
+ export * from './lib/country-input';
11
+ export * from './lib/save-event';
12
+ export * from './lib/date-input/date-input.component';
13
+ export * from './lib/user-country/user-country.component';
14
+ export * from './lib/card-list/sneat-card-list.component';
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../libs/components/src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAC5B,cAAc,qCAAqC,CAAC;AACpD,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uCAAuC,CAAC;AACtD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,2CAA2C,CAAC","sourcesContent":["export * from './lib/app-version';\nexport * from './lib/pipes';\nexport * from './lib/virtual-slider/virtual-slider';\nexport * from './lib/card-list';\nexport * from './lib/error-card';\nexport * from './lib/country-selector';\nexport * from './lib/filter-item';\nexport * from './lib/copyright';\nexport * from './lib/dialog-header';\nexport * from './lib/country-input';\nexport * from './lib/save-event';\nexport * from './lib/date-input/date-input.component';\nexport * from './lib/user-country/user-country.component';\nexport * from './lib/card-list/sneat-card-list.component';\n"]}
@@ -0,0 +1,16 @@
1
+ import { Component } from '@angular/core';
2
+ import { IonInput, IonItem, IonItemDivider, IonLabel, } from '@ionic/angular/standalone';
3
+ import { buildInfo } from './build-info';
4
+ import * as i0 from "@angular/core";
5
+ export class AppVersionComponent {
6
+ constructor() {
7
+ this.buildInfo = buildInfo;
8
+ }
9
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: AppVersionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
10
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.0", type: AppVersionComponent, isStandalone: true, selector: "sneat-app-version", ngImport: i0, template: "<ion-item-divider color=\"light\">\n <ion-label>App version</ion-label>\n</ion-item-divider>\n<ion-item>\n <ion-input\n label=\"Build:\"\n color=\"medium\"\n readonly=\"true\"\n disabled=\"true\"\n [value]=\"\n buildInfo.gitHash.substring(0, 7) + ' @ ' + buildInfo.buildTimestamp\n \"\n [title]=\"buildInfo.gitHash\"\n />\n</ion-item>\n", dependencies: [{ kind: "component", type: IonItemDivider, selector: "ion-item-divider", inputs: ["color", "mode", "sticky"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonInput, selector: "ion-input", inputs: ["accept", "autocapitalize", "autocomplete", "autocorrect", "autofocus", "clearInput", "clearOnEdit", "color", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "max", "maxlength", "min", "minlength", "mode", "multiple", "name", "pattern", "placeholder", "readonly", "required", "shape", "size", "spellcheck", "step", "type", "value"] }] }); }
11
+ }
12
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: AppVersionComponent, decorators: [{
13
+ type: Component,
14
+ args: [{ selector: 'sneat-app-version', imports: [IonItemDivider, IonLabel, IonItem, IonInput], template: "<ion-item-divider color=\"light\">\n <ion-label>App version</ion-label>\n</ion-item-divider>\n<ion-item>\n <ion-input\n label=\"Build:\"\n color=\"medium\"\n readonly=\"true\"\n disabled=\"true\"\n [value]=\"\n buildInfo.gitHash.substring(0, 7) + ' @ ' + buildInfo.buildTimestamp\n \"\n [title]=\"buildInfo.gitHash\"\n />\n</ion-item>\n" }]
15
+ }] });
16
+ //# sourceMappingURL=app-version.component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-version.component.js","sourceRoot":"","sources":["../../../../../../libs/components/src/lib/app-version/app-version.component.ts","../../../../../../libs/components/src/lib/app-version/app-version.component.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EACL,QAAQ,EACR,OAAO,EACP,cAAc,EACd,QAAQ,GACT,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;;AAOzC,MAAM,OAAO,mBAAmB;IALhC;QAMqB,cAAS,GAAG,SAAS,CAAC;KAC1C;8GAFY,mBAAmB;kGAAnB,mBAAmB,6ECdhC,+WAeA,4CDHY,cAAc,kGAAE,QAAQ,6FAAE,OAAO,0NAAE,QAAQ;;2FAE1C,mBAAmB;kBAL/B,SAAS;+BACE,mBAAmB,WAEpB,CAAC,cAAc,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAC","sourcesContent":["import { Component } from '@angular/core';\nimport {\n IonInput,\n IonItem,\n IonItemDivider,\n IonLabel,\n} from '@ionic/angular/standalone';\nimport { buildInfo } from './build-info';\n\n@Component({\n selector: 'sneat-app-version',\n templateUrl: 'app-version.component.html',\n imports: [IonItemDivider, IonLabel, IonItem, IonInput],\n})\nexport class AppVersionComponent {\n protected readonly buildInfo = buildInfo;\n}\n","<ion-item-divider color=\"light\">\n <ion-label>App version</ion-label>\n</ion-item-divider>\n<ion-item>\n <ion-input\n label=\"Build:\"\n color=\"medium\"\n readonly=\"true\"\n disabled=\"true\"\n [value]=\"\n buildInfo.gitHash.substring(0, 7) + ' @ ' + buildInfo.buildTimestamp\n \"\n [title]=\"buildInfo.gitHash\"\n />\n</ion-item>\n"]}
@@ -0,0 +1,5 @@
1
+ export const buildInfo = {
2
+ gitHash: 'gitHash t0be$et',
3
+ buildTimestamp: 'timestamp t0be$et',
4
+ };
5
+ //# sourceMappingURL=build-info.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-info.js","sourceRoot":"","sources":["../../../../../../libs/components/src/lib/app-version/build-info.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,SAAS,GAIlB;IACF,OAAO,EAAE,iBAAiB;IAC1B,cAAc,EAAE,mBAAmB;CACpC,CAAC","sourcesContent":["export const buildInfo: {\n // TODO: Needs pre-commit hook to check gitHash and buildTimestamp are NOT changed.\n readonly gitHash: string;\n readonly buildTimestamp: string;\n} = {\n gitHash: 'gitHash t0be$et',\n buildTimestamp: 'timestamp t0be$et',\n};\n"]}
@@ -0,0 +1,3 @@
1
+ export * from './app-version.component';
2
+ export * from './build-info';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../libs/components/src/lib/app-version/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,cAAc,CAAC","sourcesContent":["export * from './app-version.component';\nexport * from './build-info';\n"]}
@@ -0,0 +1,2 @@
1
+ export * from './sneat-card-list.component';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../libs/components/src/lib/card-list/index.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAC","sourcesContent":["export * from './sneat-card-list.component';\n"]}
@@ -0,0 +1,106 @@
1
+ import { Component, EventEmitter, Input, Output, ViewChild, inject, } from '@angular/core';
2
+ import { FormsModule } from '@angular/forms';
3
+ import { RouterModule } from '@angular/router';
4
+ import { IonButton, IonButtons, IonCard, IonCardContent, IonIcon, IonInput, IonItem, IonLabel, IonList, IonSegment, IonSegmentButton, IonSkeletonText, } from '@ionic/angular/standalone';
5
+ import { ErrorLogger } from '@sneat/core';
6
+ import * as i0 from "@angular/core";
7
+ import * as i1 from "@angular/router";
8
+ import * as i2 from "@angular/forms";
9
+ export class SneatCardListComponent {
10
+ constructor() {
11
+ this.errorLogger = inject(ErrorLogger);
12
+ this.getRouterLink = () => undefined;
13
+ this.cardTitleClick = new EventEmitter();
14
+ this.itemClick = new EventEmitter();
15
+ this.tabChanged = new EventEmitter();
16
+ this.filter = '';
17
+ this.mode = 'list';
18
+ this.name = '';
19
+ }
20
+ click(event, item) {
21
+ event.preventDefault();
22
+ event.stopPropagation();
23
+ this.itemClick.emit(item);
24
+ }
25
+ showAddForm(event) {
26
+ event.preventDefault();
27
+ event.stopPropagation();
28
+ this.mode = 'add';
29
+ setTimeout(() => {
30
+ // console.log(this.addInput);
31
+ if (this.addInput) {
32
+ this.addInput
33
+ ?.setFocus()
34
+ .catch((err) => this.errorLogger.logError(err, 'Failed to set focus'));
35
+ }
36
+ }, 200);
37
+ }
38
+ tryCreate() {
39
+ this.isAdding = true;
40
+ if (this.create) {
41
+ this.create(this.name.trim()).subscribe({
42
+ next: (item) => {
43
+ this.items?.push(item);
44
+ this.isAdding = false;
45
+ this.mode = 'list';
46
+ this.name = '';
47
+ },
48
+ error: (err) => {
49
+ this.errorLogger.logError(err, 'Failed to create new item');
50
+ this.isAdding = false;
51
+ },
52
+ });
53
+ }
54
+ }
55
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: SneatCardListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
56
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: SneatCardListComponent, isStandalone: true, selector: "sneat-card-list", inputs: { title: "title", isFilterable: "isFilterable", isLoading: "isLoading", items: "items", create: "create", itemIcon: "itemIcon", tab: "tab", tabs: "tabs", noItemsText: "noItemsText", getRouterLink: "getRouterLink" }, outputs: { cardTitleClick: "cardTitleClick", itemClick: "itemClick", tabChanged: "tabChanged" }, viewQueries: [{ propertyName: "addInput", first: true, predicate: IonInput, descendants: true }], ngImport: i0, template: "<ion-card>\n @if (title) {\n <ion-item (click)=\"cardTitleClick.emit()\" tappable>\n @if (itemIcon && !isLoading && !items?.length) {\n <ion-icon [name]=\"itemIcon\" slot=\"start\" />\n }\n <ion-label style=\"font-weight: bold\">{{ title }}</ion-label>\n @if (isFilterable) {\n <ion-input [(ngModel)]=\"filter\" placeholder=\"(type to filter)\" />\n }\n <ion-buttons slot=\"end\">\n @if (filter) {\n <ion-button (click)=\"filter = ''\" title=\"Clear filter\">\n <ion-icon name=\"close-outline\" color=\"medium\" />\n </ion-button>\n }\n @if (mode !== \"add\" && create) {\n <ion-button (click)=\"showAddForm($event)\">\n <ion-icon color=\"primary\" slot=\"start\" name=\"add\" />\n <ion-label color=\"medium\">Add</ion-label>\n </ion-button>\n }\n </ion-buttons>\n </ion-item>\n }\n @if (tabs) {\n <ion-segment [(ngModel)]=\"tab\" (ionChange)=\"tabChanged.emit(tab || '')\">\n @for (tab of tabs; track tab.id) {\n <ion-segment-button [value]=\"tab.id\">\n <ion-label>{{ tab.title }}</ion-label>\n </ion-segment-button>\n }\n </ion-segment>\n <ion-buttons>\n @if (mode !== \"add\" && create) {\n <ion-button (click)=\"showAddForm($event)\">\n <ion-icon color=\"primary\" slot=\"start\" name=\"add\" />\n <ion-label color=\"medium\">Add</ion-label>\n </ion-button>\n }\n </ion-buttons>\n }\n @if (isLoading) {\n <ion-card-content>\n <ion-skeleton-text animated=\"\" style=\"width: 100%\" />\n </ion-card-content>\n } @else {\n <ion-list>\n @for (item of items; track item.id) {\n <ion-item\n tappable\n (click)=\"itemClick && click($event, item)\"\n [routerLink]=\"getRouterLink(item)\"\n >\n @if (itemIcon) {\n <ion-icon [name]=\"itemIcon\" slot=\"start\" />\n }\n <ion-label>{{ item.title || item.id }}</ion-label>\n </ion-item>\n }\n @if (mode === \"add\") {\n <ion-item>\n <ion-icon name=\"earth-outline\" slot=\"start\" color=\"medium\" />\n <ion-input\n [(ngModel)]=\"name\"\n placeholder=\"Name\"\n [disabled]=\"!!isAdding\"\n />\n <ion-buttons slot=\"end\">\n <ion-button\n fill=\"solid\"\n color=\"primary\"\n [disabled]=\"isAdding || !name.trim()\"\n (click)=\"tryCreate()\"\n >\n Create\n </ion-button>\n <ion-button\n (click)=\"mode = 'list'\"\n color=\"medium\"\n title=\"Cancel\"\n [disabled]=\"isAdding\"\n >\n <ion-icon name=\"close-outline\" />\n </ion-button>\n </ion-buttons>\n </ion-item>\n }\n </ion-list>\n @if (!items?.length && mode !== \"add\") {\n <ion-card-content>\n @if (!noItemsText) {\n <p>\n {{ noItemsText }}\n </p>\n } @else {\n <p>\n Not defined for this project yet. Click the\n <span style=\"background-color: whitesmoke; padding: 4px 8px\"\n >+ Add</span\n >\n button above in the header of this card to create a first one.\n </p>\n }\n </ion-card-content>\n }\n }\n</ion-card>\n", dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: IonCard, selector: "ion-card", inputs: ["button", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonInput, selector: "ion-input", inputs: ["accept", "autocapitalize", "autocomplete", "autocorrect", "autofocus", "clearInput", "clearOnEdit", "color", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "max", "maxlength", "min", "minlength", "mode", "multiple", "name", "pattern", "placeholder", "readonly", "required", "shape", "size", "spellcheck", "step", "type", "value"] }, { kind: "component", type: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonSegment, selector: "ion-segment", inputs: ["color", "disabled", "mode", "scrollable", "selectOnFocus", "swipeGesture", "value"] }, { kind: "component", type: IonSegmentButton, selector: "ion-segment-button", inputs: ["contentId", "disabled", "layout", "mode", "type", "value"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: IonCardContent, selector: "ion-card-content", inputs: ["mode"] }, { kind: "component", type: IonSkeletonText, selector: "ion-skeleton-text", inputs: ["animated"] }, { kind: "component", type: IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }] }); }
57
+ }
58
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: SneatCardListComponent, decorators: [{
59
+ type: Component,
60
+ args: [{ selector: 'sneat-card-list', imports: [
61
+ RouterModule,
62
+ IonCard,
63
+ IonItem,
64
+ IonIcon,
65
+ IonLabel,
66
+ IonInput,
67
+ IonButtons,
68
+ IonButton,
69
+ IonSegment,
70
+ IonSegmentButton,
71
+ FormsModule,
72
+ IonCardContent,
73
+ IonSkeletonText,
74
+ IonList,
75
+ ], template: "<ion-card>\n @if (title) {\n <ion-item (click)=\"cardTitleClick.emit()\" tappable>\n @if (itemIcon && !isLoading && !items?.length) {\n <ion-icon [name]=\"itemIcon\" slot=\"start\" />\n }\n <ion-label style=\"font-weight: bold\">{{ title }}</ion-label>\n @if (isFilterable) {\n <ion-input [(ngModel)]=\"filter\" placeholder=\"(type to filter)\" />\n }\n <ion-buttons slot=\"end\">\n @if (filter) {\n <ion-button (click)=\"filter = ''\" title=\"Clear filter\">\n <ion-icon name=\"close-outline\" color=\"medium\" />\n </ion-button>\n }\n @if (mode !== \"add\" && create) {\n <ion-button (click)=\"showAddForm($event)\">\n <ion-icon color=\"primary\" slot=\"start\" name=\"add\" />\n <ion-label color=\"medium\">Add</ion-label>\n </ion-button>\n }\n </ion-buttons>\n </ion-item>\n }\n @if (tabs) {\n <ion-segment [(ngModel)]=\"tab\" (ionChange)=\"tabChanged.emit(tab || '')\">\n @for (tab of tabs; track tab.id) {\n <ion-segment-button [value]=\"tab.id\">\n <ion-label>{{ tab.title }}</ion-label>\n </ion-segment-button>\n }\n </ion-segment>\n <ion-buttons>\n @if (mode !== \"add\" && create) {\n <ion-button (click)=\"showAddForm($event)\">\n <ion-icon color=\"primary\" slot=\"start\" name=\"add\" />\n <ion-label color=\"medium\">Add</ion-label>\n </ion-button>\n }\n </ion-buttons>\n }\n @if (isLoading) {\n <ion-card-content>\n <ion-skeleton-text animated=\"\" style=\"width: 100%\" />\n </ion-card-content>\n } @else {\n <ion-list>\n @for (item of items; track item.id) {\n <ion-item\n tappable\n (click)=\"itemClick && click($event, item)\"\n [routerLink]=\"getRouterLink(item)\"\n >\n @if (itemIcon) {\n <ion-icon [name]=\"itemIcon\" slot=\"start\" />\n }\n <ion-label>{{ item.title || item.id }}</ion-label>\n </ion-item>\n }\n @if (mode === \"add\") {\n <ion-item>\n <ion-icon name=\"earth-outline\" slot=\"start\" color=\"medium\" />\n <ion-input\n [(ngModel)]=\"name\"\n placeholder=\"Name\"\n [disabled]=\"!!isAdding\"\n />\n <ion-buttons slot=\"end\">\n <ion-button\n fill=\"solid\"\n color=\"primary\"\n [disabled]=\"isAdding || !name.trim()\"\n (click)=\"tryCreate()\"\n >\n Create\n </ion-button>\n <ion-button\n (click)=\"mode = 'list'\"\n color=\"medium\"\n title=\"Cancel\"\n [disabled]=\"isAdding\"\n >\n <ion-icon name=\"close-outline\" />\n </ion-button>\n </ion-buttons>\n </ion-item>\n }\n </ion-list>\n @if (!items?.length && mode !== \"add\") {\n <ion-card-content>\n @if (!noItemsText) {\n <p>\n {{ noItemsText }}\n </p>\n } @else {\n <p>\n Not defined for this project yet. Click the\n <span style=\"background-color: whitesmoke; padding: 4px 8px\"\n >+ Add</span\n >\n button above in the header of this card to create a first one.\n </p>\n }\n </ion-card-content>\n }\n }\n</ion-card>\n" }]
76
+ }], propDecorators: { title: [{
77
+ type: Input
78
+ }], isFilterable: [{
79
+ type: Input
80
+ }], isLoading: [{
81
+ type: Input
82
+ }], items: [{
83
+ type: Input
84
+ }], create: [{
85
+ type: Input
86
+ }], itemIcon: [{
87
+ type: Input
88
+ }], tab: [{
89
+ type: Input
90
+ }], tabs: [{
91
+ type: Input
92
+ }], noItemsText: [{
93
+ type: Input
94
+ }], getRouterLink: [{
95
+ type: Input
96
+ }], cardTitleClick: [{
97
+ type: Output
98
+ }], itemClick: [{
99
+ type: Output
100
+ }], tabChanged: [{
101
+ type: Output
102
+ }], addInput: [{
103
+ type: ViewChild,
104
+ args: [IonInput, { static: false }]
105
+ }] } });
106
+ //# sourceMappingURL=sneat-card-list.component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sneat-card-list.component.js","sourceRoot":"","sources":["../../../../../../libs/components/src/lib/card-list/sneat-card-list.component.ts","../../../../../../libs/components/src/lib/card-list/sneat-card-list.component.html"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,YAAY,EACZ,KAAK,EACL,MAAM,EACN,SAAS,EACT,MAAM,GACP,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EACL,SAAS,EACT,UAAU,EACV,OAAO,EACP,cAAc,EACd,OAAO,EACP,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,OAAO,EACP,UAAU,EACV,gBAAgB,EAChB,eAAe,GAChB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAAE,WAAW,EAAgB,MAAM,aAAa,CAAC;;;;AAiCxD,MAAM,OAAO,sBAAsB;IApBnC;QAqBmB,gBAAW,GAAG,MAAM,CAAe,WAAW,CAAC,CAAC;QAWxD,kBAAa,GAA8B,GAAG,EAAE,CACvD,SAA8B,CAAC;QAEd,mBAAc,GAAG,IAAI,YAAY,EAAQ,CAAC;QAC1C,cAAS,GAAG,IAAI,YAAY,EAAW,CAAC;QACxC,eAAU,GAAG,IAAI,YAAY,EAAU,CAAC;QAI3D,WAAM,GAAG,EAAE,CAAC;QAEF,SAAI,GAAmB,MAAM,CAAC;QAC9B,SAAI,GAAG,EAAE,CAAC;KA0CrB;IAvCW,KAAK,CAAC,KAAY,EAAE,IAAa;QACzC,KAAK,CAAC,cAAc,EAAE,CAAC;QACvB,KAAK,CAAC,eAAe,EAAE,CAAC;QACxB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAES,WAAW,CAAC,KAAY;QAChC,KAAK,CAAC,cAAc,EAAE,CAAC;QACvB,KAAK,CAAC,eAAe,EAAE,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC;QAClB,UAAU,CAAC,GAAG,EAAE;YACd,8BAA8B;YAC9B,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAClB,IAAI,CAAC,QAAQ;oBACX,EAAE,QAAQ,EAAE;qBACX,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CACb,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,GAAG,EAAE,qBAAqB,CAAC,CACtD,CAAC;YACN,CAAC;QACH,CAAC,EAAE,GAAG,CAAC,CAAC;IACV,CAAC;IAES,SAAS;QACjB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,SAAS,CAAC;gBACtC,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE;oBACb,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;oBACvB,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;oBACtB,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC;oBACnB,IAAI,CAAC,IAAI,GAAG,EAAE,CAAC;gBACjB,CAAC;gBACD,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE;oBACb,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,GAAG,EAAE,2BAA2B,CAAC,CAAC;oBAC5D,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;gBACxB,CAAC;aACF,CAAC,CAAC;QACL,CAAC;IACH,CAAC;8GAjEU,sBAAsB;kGAAtB,sBAAsB,sbAmBtB,QAAQ,gDC7ErB,27GA4GA,2CDlEI,YAAY,gRACZ,OAAO,yLACP,OAAO,0NACP,OAAO,2JACP,QAAQ,6FACR,QAAQ,8eACR,UAAU,8EACV,SAAS,oPACT,UAAU,uJACV,gBAAgB,oIAChB,WAAW,+VACX,cAAc,+EACd,eAAe,oFACf,OAAO;;2FAGE,sBAAsB;kBApBlC,SAAS;+BACE,iBAAiB,WAElB;wBACP,YAAY;wBACZ,OAAO;wBACP,OAAO;wBACP,OAAO;wBACP,QAAQ;wBACR,QAAQ;wBACR,UAAU;wBACV,SAAS;wBACT,UAAU;wBACV,gBAAgB;wBAChB,WAAW;wBACX,cAAc;wBACd,eAAe;wBACf,OAAO;qBACR;;sBAKA,KAAK;;sBACL,KAAK;;sBACL,KAAK;;sBACL,KAAK;;sBACL,KAAK;;sBACL,KAAK;;sBACL,KAAK;;sBACL,KAAK;;sBACL,KAAK;;sBACL,KAAK;;sBAGL,MAAM;;sBACN,MAAM;;sBACN,MAAM;;sBAEN,SAAS;uBAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE","sourcesContent":["import {\n Component,\n EventEmitter,\n Input,\n Output,\n ViewChild,\n inject,\n} from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { RouterModule } from '@angular/router';\nimport {\n IonButton,\n IonButtons,\n IonCard,\n IonCardContent,\n IonIcon,\n IonInput,\n IonItem,\n IonLabel,\n IonList,\n IonSegment,\n IonSegmentButton,\n IonSkeletonText,\n} from '@ionic/angular/standalone';\nimport { IRecord } from '@sneat/data';\nimport { ErrorLogger, IErrorLogger } from '@sneat/core';\nimport { Observable } from 'rxjs';\n\nexport interface ICardTab {\n id: string;\n title: string;\n}\n\ninterface IOptionallyTitled {\n id?: string;\n title?: string;\n}\n\n@Component({\n selector: 'sneat-card-list',\n templateUrl: './sneat-card-list.component.html',\n imports: [\n RouterModule,\n IonCard,\n IonItem,\n IonIcon,\n IonLabel,\n IonInput,\n IonButtons,\n IonButton,\n IonSegment,\n IonSegmentButton,\n FormsModule,\n IonCardContent,\n IonSkeletonText,\n IonList,\n ],\n})\nexport class SneatCardListComponent {\n private readonly errorLogger = inject<IErrorLogger>(ErrorLogger);\n\n @Input() title?: string;\n @Input() isFilterable?: boolean;\n @Input() isLoading?: boolean;\n @Input() items?: { id?: unknown; title?: string }[];\n @Input() create?: (name: string) => Observable<IRecord<IOptionallyTitled>>;\n @Input() itemIcon?: string;\n @Input() tab?: string;\n @Input() tabs?: ICardTab[];\n @Input() noItemsText?: string;\n @Input() getRouterLink: (item: unknown) => string = () =>\n undefined as unknown as string;\n\n @Output() readonly cardTitleClick = new EventEmitter<void>();\n @Output() readonly itemClick = new EventEmitter<unknown>();\n @Output() readonly tabChanged = new EventEmitter<string>();\n\n @ViewChild(IonInput, { static: false }) addInput?: IonInput;\n\n filter = '';\n\n protected mode: 'list' | 'add' = 'list';\n protected name = '';\n protected isAdding?: boolean;\n\n protected click(event: Event, item: unknown): void {\n event.preventDefault();\n event.stopPropagation();\n this.itemClick.emit(item);\n }\n\n protected showAddForm(event: Event): void {\n event.preventDefault();\n event.stopPropagation();\n this.mode = 'add';\n setTimeout(() => {\n // console.log(this.addInput);\n if (this.addInput) {\n this.addInput\n ?.setFocus()\n .catch((err) =>\n this.errorLogger.logError(err, 'Failed to set focus'),\n );\n }\n }, 200);\n }\n\n protected tryCreate(): void {\n this.isAdding = true;\n if (this.create) {\n this.create(this.name.trim()).subscribe({\n next: (item) => {\n this.items?.push(item);\n this.isAdding = false;\n this.mode = 'list';\n this.name = '';\n },\n error: (err) => {\n this.errorLogger.logError(err, 'Failed to create new item');\n this.isAdding = false;\n },\n });\n }\n }\n}\n","<ion-card>\n @if (title) {\n <ion-item (click)=\"cardTitleClick.emit()\" tappable>\n @if (itemIcon && !isLoading && !items?.length) {\n <ion-icon [name]=\"itemIcon\" slot=\"start\" />\n }\n <ion-label style=\"font-weight: bold\">{{ title }}</ion-label>\n @if (isFilterable) {\n <ion-input [(ngModel)]=\"filter\" placeholder=\"(type to filter)\" />\n }\n <ion-buttons slot=\"end\">\n @if (filter) {\n <ion-button (click)=\"filter = ''\" title=\"Clear filter\">\n <ion-icon name=\"close-outline\" color=\"medium\" />\n </ion-button>\n }\n @if (mode !== \"add\" && create) {\n <ion-button (click)=\"showAddForm($event)\">\n <ion-icon color=\"primary\" slot=\"start\" name=\"add\" />\n <ion-label color=\"medium\">Add</ion-label>\n </ion-button>\n }\n </ion-buttons>\n </ion-item>\n }\n @if (tabs) {\n <ion-segment [(ngModel)]=\"tab\" (ionChange)=\"tabChanged.emit(tab || '')\">\n @for (tab of tabs; track tab.id) {\n <ion-segment-button [value]=\"tab.id\">\n <ion-label>{{ tab.title }}</ion-label>\n </ion-segment-button>\n }\n </ion-segment>\n <ion-buttons>\n @if (mode !== \"add\" && create) {\n <ion-button (click)=\"showAddForm($event)\">\n <ion-icon color=\"primary\" slot=\"start\" name=\"add\" />\n <ion-label color=\"medium\">Add</ion-label>\n </ion-button>\n }\n </ion-buttons>\n }\n @if (isLoading) {\n <ion-card-content>\n <ion-skeleton-text animated=\"\" style=\"width: 100%\" />\n </ion-card-content>\n } @else {\n <ion-list>\n @for (item of items; track item.id) {\n <ion-item\n tappable\n (click)=\"itemClick && click($event, item)\"\n [routerLink]=\"getRouterLink(item)\"\n >\n @if (itemIcon) {\n <ion-icon [name]=\"itemIcon\" slot=\"start\" />\n }\n <ion-label>{{ item.title || item.id }}</ion-label>\n </ion-item>\n }\n @if (mode === \"add\") {\n <ion-item>\n <ion-icon name=\"earth-outline\" slot=\"start\" color=\"medium\" />\n <ion-input\n [(ngModel)]=\"name\"\n placeholder=\"Name\"\n [disabled]=\"!!isAdding\"\n />\n <ion-buttons slot=\"end\">\n <ion-button\n fill=\"solid\"\n color=\"primary\"\n [disabled]=\"isAdding || !name.trim()\"\n (click)=\"tryCreate()\"\n >\n Create\n </ion-button>\n <ion-button\n (click)=\"mode = 'list'\"\n color=\"medium\"\n title=\"Cancel\"\n [disabled]=\"isAdding\"\n >\n <ion-icon name=\"close-outline\" />\n </ion-button>\n </ion-buttons>\n </ion-item>\n }\n </ion-list>\n @if (!items?.length && mode !== \"add\") {\n <ion-card-content>\n @if (!noItemsText) {\n <p>\n {{ noItemsText }}\n </p>\n } @else {\n <p>\n Not defined for this project yet. Click the\n <span style=\"background-color: whitesmoke; padding: 4px 8px\"\n >+ Add</span\n >\n button above in the header of this card to create a first one.\n </p>\n }\n </ion-card-content>\n }\n }\n</ion-card>\n"]}
@@ -0,0 +1,11 @@
1
+ import { Component } from '@angular/core';
2
+ import * as i0 from "@angular/core";
3
+ export class CopyrightComponent {
4
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: CopyrightComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.0", type: CopyrightComponent, isStandalone: true, selector: "sneat-copyright", ngImport: i0, template: "<p>2020 &copy; Sneat.team</p>\n" }); }
6
+ }
7
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: CopyrightComponent, decorators: [{
8
+ type: Component,
9
+ args: [{ selector: 'sneat-copyright', template: "<p>2020 &copy; Sneat.team</p>\n" }]
10
+ }] });
11
+ //# sourceMappingURL=copyright.component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copyright.component.js","sourceRoot":"","sources":["../../../../../../libs/components/src/lib/copyright/copyright.component.ts","../../../../../../libs/components/src/lib/copyright/copyright.component.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;;AAM1C,MAAM,OAAO,kBAAkB;8GAAlB,kBAAkB;kGAAlB,kBAAkB,2ECN/B,iCACA;;2FDKa,kBAAkB;kBAJ9B,SAAS;+BACE,iBAAiB","sourcesContent":["import { Component } from '@angular/core';\n\n@Component({\n selector: 'sneat-copyright',\n templateUrl: './copyright.component.html',\n})\nexport class CopyrightComponent {}\n","<p>2020 &copy; Sneat.team</p>\n"]}
@@ -0,0 +1,2 @@
1
+ export * from './copyright.component';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../libs/components/src/lib/copyright/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC","sourcesContent":["export * from './copyright.component';\n"]}
@@ -0,0 +1,59 @@
1
+ import { Component, EventEmitter, inject, Input, Output, signal, } from '@angular/core';
2
+ import { FormsModule } from '@angular/forms';
3
+ import { IonButton, IonButtons, IonIcon, IonItem, IonSelect, IonSelectOption, } from '@ionic/angular/standalone';
4
+ import { CountriesLoaderService } from '../country-selector';
5
+ import * as i0 from "@angular/core";
6
+ import * as i1 from "@angular/forms";
7
+ export class CountryInputComponent {
8
+ constructor() {
9
+ this.countriesLoader = inject(CountriesLoaderService);
10
+ this.canReset = true;
11
+ this.label = 'Country';
12
+ this.countryID = '';
13
+ this.countryIDChange = new EventEmitter();
14
+ this.countries = signal([], ...(ngDevMode ? [{ debugName: "countries" }] : []));
15
+ }
16
+ ngOnInit() {
17
+ // Load countries data
18
+ this.countriesLoader.getCountries().then((countries) => {
19
+ this.countries.set(countries);
20
+ });
21
+ }
22
+ // constructor(
23
+ // // private readonly countrySelectorService: CountrySelectorService,
24
+ // ) {
25
+ // }
26
+ onCountryChanged() {
27
+ // console.log('CountryInputComponent.onCountryChanged()', this.countryID);
28
+ this.countryIDChange.emit(this.countryID);
29
+ }
30
+ reset(event) {
31
+ event.preventDefault();
32
+ event.stopPropagation();
33
+ this.countryID = '';
34
+ this.countryIDChange.emit('');
35
+ }
36
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: CountryInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
37
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: CountryInputComponent, isStandalone: true, selector: "sneat-country-input", inputs: { canReset: "canReset", label: "label", countryID: "countryID" }, outputs: { countryIDChange: "countryIDChange" }, ngImport: i0, template: "<ion-item class=\"sneat-tiny-end-padding\" lines=\"none\">\n <ion-select\n interface=\"popover\"\n [label]=\"label\"\n [(ngModel)]=\"countryID\"\n (ionChange)=\"onCountryChanged()\"\n >\n <ion-select-option value=\"\">All</ion-select-option>\n @for (c of countries(); track c.id) {\n <ion-select-option [value]=\"c.id\">\n {{ c.title }} {{ c.emoji }}\n </ion-select-option>\n }\n </ion-select>\n @if (countryID && canReset) {\n <ion-buttons slot=\"end\">\n <ion-button color=\"medium\" (click)=\"reset($event)\">\n <ion-icon name=\"close-outline\" />\n </ion-button>\n </ion-buttons>\n }\n <!-- disable for now as select is showing incorrectyl and lookup us not linked-->\n <!--\t<ion-buttons slot=\"end\" class=\"ion-no-margin ion-no-padding\">-->\n <!--\t\t<ion-button *ngIf=\"canReset && countryID\"-->\n <!--\t\t\t\t\t\t\t\tcolor=\"medium\"-->\n <!--\t\t\t\t\t\t\t\t(click)=\"reset($event)\" [disabled]=\"!canReset || !countryID\">-->\n <!--\t\t\t<ion-icon name=\"close-outline\"></ion-icon>-->\n <!--\t\t</ion-button>-->\n <!--\t\t<ion-button (click)=\"openCountrySelector($event)\">-->\n <!--\t\t\t<ion-label>...</ion-label>-->\n <!--\t\t</ion-button>-->\n <!--\t</ion-buttons>-->\n</ion-item>\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonSelect, selector: "ion-select", inputs: ["cancelText", "color", "compareWith", "disabled", "errorText", "expandedIcon", "fill", "helperText", "interface", "interfaceOptions", "justify", "label", "labelPlacement", "mode", "multiple", "name", "okText", "placeholder", "selectedText", "shape", "toggleIcon", "value"] }, { kind: "component", type: IonSelectOption, selector: "ion-select-option", inputs: ["disabled", "value"] }, { kind: "component", type: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }] }); }
38
+ }
39
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: CountryInputComponent, decorators: [{
40
+ type: Component,
41
+ args: [{ selector: 'sneat-country-input', imports: [
42
+ FormsModule,
43
+ IonItem,
44
+ IonSelect,
45
+ IonSelectOption,
46
+ IonButtons,
47
+ IonButton,
48
+ IonIcon,
49
+ ], template: "<ion-item class=\"sneat-tiny-end-padding\" lines=\"none\">\n <ion-select\n interface=\"popover\"\n [label]=\"label\"\n [(ngModel)]=\"countryID\"\n (ionChange)=\"onCountryChanged()\"\n >\n <ion-select-option value=\"\">All</ion-select-option>\n @for (c of countries(); track c.id) {\n <ion-select-option [value]=\"c.id\">\n {{ c.title }} {{ c.emoji }}\n </ion-select-option>\n }\n </ion-select>\n @if (countryID && canReset) {\n <ion-buttons slot=\"end\">\n <ion-button color=\"medium\" (click)=\"reset($event)\">\n <ion-icon name=\"close-outline\" />\n </ion-button>\n </ion-buttons>\n }\n <!-- disable for now as select is showing incorrectyl and lookup us not linked-->\n <!--\t<ion-buttons slot=\"end\" class=\"ion-no-margin ion-no-padding\">-->\n <!--\t\t<ion-button *ngIf=\"canReset && countryID\"-->\n <!--\t\t\t\t\t\t\t\tcolor=\"medium\"-->\n <!--\t\t\t\t\t\t\t\t(click)=\"reset($event)\" [disabled]=\"!canReset || !countryID\">-->\n <!--\t\t\t<ion-icon name=\"close-outline\"></ion-icon>-->\n <!--\t\t</ion-button>-->\n <!--\t\t<ion-button (click)=\"openCountrySelector($event)\">-->\n <!--\t\t\t<ion-label>...</ion-label>-->\n <!--\t\t</ion-button>-->\n <!--\t</ion-buttons>-->\n</ion-item>\n" }]
50
+ }], propDecorators: { canReset: [{
51
+ type: Input
52
+ }], label: [{
53
+ type: Input
54
+ }], countryID: [{
55
+ type: Input
56
+ }], countryIDChange: [{
57
+ type: Output
58
+ }] } });
59
+ //# sourceMappingURL=country-input.component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"country-input.component.js","sourceRoot":"","sources":["../../../../../../libs/components/src/lib/country-input/country-input.component.ts","../../../../../../libs/components/src/lib/country-input/country-input.component.html"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,YAAY,EACZ,MAAM,EACN,KAAK,EAEL,MAAM,EACN,MAAM,GACP,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EACL,SAAS,EACT,UAAU,EACV,OAAO,EACP,OAAO,EACP,SAAS,EACT,eAAe,GAChB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAY,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;;;AAevE,MAAM,OAAO,qBAAqB;IAblC;QAcmB,oBAAe,GAAG,MAAM,CAAC,sBAAsB,CAAC,CAAC;QAEzD,aAAQ,GAAG,IAAI,CAAC;QAChB,UAAK,GAAG,SAAS,CAAC;QAClB,cAAS,GAAG,EAAE,CAAC;QACd,oBAAe,GAAG,IAAI,YAAY,EAAU,CAAC;QAE9C,cAAS,GAAG,MAAM,CAAsB,EAAE,qDAAC,CAAC;KAkCtD;IAhCC,QAAQ;QACN,sBAAsB;QACtB,IAAI,CAAC,eAAe,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE;YACrD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAChC,CAAC,CAAC,CAAC;IACL,CAAC;IAED,eAAe;IACf,uEAAuE;IACvE,MAAM;IACN,IAAI;IAEG,gBAAgB;QACrB,2EAA2E;QAC3E,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,KAAY;QAChB,KAAK,CAAC,cAAc,EAAE,CAAC;QACvB,KAAK,CAAC,eAAe,EAAE,CAAC;QACxB,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;QACpB,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChC,CAAC;8GAhCU,qBAAqB;kGAArB,qBAAqB,0MCjClC,gwCAiCA,2CDTI,WAAW,+VACX,OAAO,0NACP,SAAS,kVACT,eAAe,6FACf,UAAU,8EACV,SAAS,oPACT,OAAO;;2FAGE,qBAAqB;kBAbjC,SAAS;+BACE,qBAAqB,WAEtB;wBACP,WAAW;wBACX,OAAO;wBACP,SAAS;wBACT,eAAe;wBACf,UAAU;wBACV,SAAS;wBACT,OAAO;qBACR;;sBAKA,KAAK;;sBACL,KAAK;;sBACL,KAAK;;sBACL,MAAM","sourcesContent":["import {\n Component,\n EventEmitter,\n inject,\n Input,\n OnInit,\n Output,\n signal,\n} from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport {\n IonButton,\n IonButtons,\n IonIcon,\n IonItem,\n IonSelect,\n IonSelectOption,\n} from '@ionic/angular/standalone';\nimport { ICountry, CountriesLoaderService } from '../country-selector';\n\n@Component({\n selector: 'sneat-country-input',\n templateUrl: './country-input.component.html',\n imports: [\n FormsModule,\n IonItem,\n IonSelect,\n IonSelectOption,\n IonButtons,\n IonButton,\n IonIcon,\n ],\n})\nexport class CountryInputComponent implements OnInit {\n private readonly countriesLoader = inject(CountriesLoaderService);\n\n @Input() canReset = true;\n @Input() label = 'Country';\n @Input() countryID = '';\n @Output() countryIDChange = new EventEmitter<string>();\n\n readonly countries = signal<readonly ICountry[]>([]);\n\n ngOnInit(): void {\n // Load countries data\n this.countriesLoader.getCountries().then((countries) => {\n this.countries.set(countries);\n });\n }\n\n // constructor(\n // \t// private readonly countrySelectorService: CountrySelectorService,\n // ) {\n // }\n\n public onCountryChanged(): void {\n // console.log('CountryInputComponent.onCountryChanged()', this.countryID);\n this.countryIDChange.emit(this.countryID);\n }\n\n reset(event: Event): void {\n event.preventDefault();\n event.stopPropagation();\n this.countryID = '';\n this.countryIDChange.emit('');\n }\n\n // protected openCountrySelector(): void {\n // \t// const options: ISelectorOptions<ICountry> = {\n // \t// \titems: of(countries),\n // \t// };\n // \t// this.countrySelectorService\n // \t// \t.selectSingleInModal(options)\n // \t// \t.then();\n // }\n}\n","<ion-item class=\"sneat-tiny-end-padding\" lines=\"none\">\n <ion-select\n interface=\"popover\"\n [label]=\"label\"\n [(ngModel)]=\"countryID\"\n (ionChange)=\"onCountryChanged()\"\n >\n <ion-select-option value=\"\">All</ion-select-option>\n @for (c of countries(); track c.id) {\n <ion-select-option [value]=\"c.id\">\n {{ c.title }} {{ c.emoji }}\n </ion-select-option>\n }\n </ion-select>\n @if (countryID && canReset) {\n <ion-buttons slot=\"end\">\n <ion-button color=\"medium\" (click)=\"reset($event)\">\n <ion-icon name=\"close-outline\" />\n </ion-button>\n </ion-buttons>\n }\n <!-- disable for now as select is showing incorrectyl and lookup us not linked-->\n <!--\t<ion-buttons slot=\"end\" class=\"ion-no-margin ion-no-padding\">-->\n <!--\t\t<ion-button *ngIf=\"canReset && countryID\"-->\n <!--\t\t\t\t\t\t\t\tcolor=\"medium\"-->\n <!--\t\t\t\t\t\t\t\t(click)=\"reset($event)\" [disabled]=\"!canReset || !countryID\">-->\n <!--\t\t\t<ion-icon name=\"close-outline\"></ion-icon>-->\n <!--\t\t</ion-button>-->\n <!--\t\t<ion-button (click)=\"openCountrySelector($event)\">-->\n <!--\t\t\t<ion-label>...</ion-label>-->\n <!--\t\t</ion-button>-->\n <!--\t</ion-buttons>-->\n</ion-item>\n"]}
@@ -0,0 +1,2 @@
1
+ export * from './country-input.component';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../libs/components/src/lib/country-input/index.ts"],"names":[],"mappings":"AAAA,cAAc,2BAA2B,CAAC","sourcesContent":["export * from './country-input.component';\n"]}
@@ -0,0 +1,91 @@
1
+ import { inject, Injectable } from '@angular/core';
2
+ import { HttpClient } from '@angular/common/http';
3
+ import { firstValueFrom } from 'rxjs';
4
+ import * as i0 from "@angular/core";
5
+ /**
6
+ * Service to lazy load country data.
7
+ * This reduces the initial bundle size by loading country data on-demand.
8
+ */
9
+ export class CountriesLoaderService {
10
+ constructor() {
11
+ this.http = inject(HttpClient);
12
+ }
13
+ /**
14
+ * Loads country data from JSON file.
15
+ * Subsequent calls return the same promise (singleton pattern).
16
+ */
17
+ async loadCountries() {
18
+ if (this.countriesData) {
19
+ return; // Already loaded
20
+ }
21
+ if (!this.loadPromise) {
22
+ this.loadPromise = (async () => {
23
+ try {
24
+ this.countriesData = await firstValueFrom(this.http.get('assets/data/countries.json'));
25
+ }
26
+ catch (error) {
27
+ console.error('Failed to load countries:', error);
28
+ // Set to empty to avoid repeated failures
29
+ this.countriesData = {
30
+ countriesByID: {},
31
+ unknownCountry: {
32
+ id: '--',
33
+ id3: '---',
34
+ title: 'Unknown',
35
+ geoRegions: [],
36
+ emoji: '🏳️',
37
+ },
38
+ };
39
+ }
40
+ })();
41
+ }
42
+ return this.loadPromise;
43
+ }
44
+ /**
45
+ * Gets all countries as an array.
46
+ * Automatically loads country data if not yet loaded.
47
+ */
48
+ async getCountries() {
49
+ await this.loadCountries();
50
+ return Object.values(this.countriesData.countriesByID);
51
+ }
52
+ /**
53
+ * Gets countries by ID lookup.
54
+ * Automatically loads country data if not yet loaded.
55
+ */
56
+ async getCountriesByID() {
57
+ await this.loadCountries();
58
+ return this.countriesData.countriesByID;
59
+ }
60
+ /**
61
+ * Gets a specific country by ID.
62
+ * Automatically loads country data if not yet loaded.
63
+ */
64
+ async getCountryByID(id) {
65
+ await this.loadCountries();
66
+ return this.countriesData.countriesByID[id];
67
+ }
68
+ /**
69
+ * Gets the unknown country constant.
70
+ * Automatically loads country data if not yet loaded.
71
+ */
72
+ async getUnknownCountry() {
73
+ await this.loadCountries();
74
+ return this.countriesData.unknownCountry;
75
+ }
76
+ /**
77
+ * Gets countries filtered by geo region.
78
+ * Automatically loads country data if not yet loaded.
79
+ */
80
+ async getCountriesByRegion(region) {
81
+ const countries = await this.getCountries();
82
+ return countries.filter((c) => c.geoRegions.includes(region));
83
+ }
84
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: CountriesLoaderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
85
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: CountriesLoaderService, providedIn: 'root' }); }
86
+ }
87
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: CountriesLoaderService, decorators: [{
88
+ type: Injectable,
89
+ args: [{ providedIn: 'root' }]
90
+ }] });
91
+ //# sourceMappingURL=countries-loader.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"countries-loader.service.js","sourceRoot":"","sources":["../../../../../../libs/components/src/lib/country-selector/countries-loader.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;;AAQtC;;;GAGG;AAEH,MAAM,OAAO,sBAAsB;IADnC;QAEmB,SAAI,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;KAmF5C;IA/EC;;;OAGG;IACK,KAAK,CAAC,aAAa;QACzB,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,OAAO,CAAC,iBAAiB;QAC3B,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,IAAI,CAAC,WAAW,GAAG,CAAC,KAAK,IAAI,EAAE;gBAC7B,IAAI,CAAC;oBACH,IAAI,CAAC,aAAa,GAAG,MAAM,cAAc,CACvC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAgB,4BAA4B,CAAC,CAC3D,CAAC;gBACJ,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,KAAK,CAAC,CAAC;oBAClD,0CAA0C;oBAC1C,IAAI,CAAC,aAAa,GAAG;wBACnB,aAAa,EAAE,EAAE;wBACjB,cAAc,EAAE;4BACd,EAAE,EAAE,IAAI;4BACR,GAAG,EAAE,KAAK;4BACV,KAAK,EAAE,SAAS;4BAChB,UAAU,EAAE,EAAE;4BACd,KAAK,EAAE,KAAK;yBACb;qBACF,CAAC;gBACJ,CAAC;YACH,CAAC,CAAC,EAAE,CAAC;QACP,CAAC;QAED,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,YAAY;QAChB,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;QAC3B,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,aAAc,CAAC,aAAa,CAAC,CAAC;IAC1D,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,gBAAgB;QACpB,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAC,aAAc,CAAC,aAAa,CAAC;IAC3C,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,cAAc,CAAC,EAAU;QAC7B,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAC,aAAc,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,iBAAiB;QACrB,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAC,aAAc,CAAC,cAAc,CAAC;IAC5C,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,oBAAoB,CAAC,MAAiB;QAC1C,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QAC5C,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IAChE,CAAC;8GAnFU,sBAAsB;kHAAtB,sBAAsB,cADT,MAAM;;2FACnB,sBAAsB;kBADlC,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE","sourcesContent":["import { inject, Injectable } from '@angular/core';\nimport { HttpClient } from '@angular/common/http';\nimport { firstValueFrom } from 'rxjs';\nimport { GeoRegion, ICountry } from './countries';\n\ninterface CountriesData {\n countriesByID: Record<string, ICountry>;\n unknownCountry: ICountry;\n}\n\n/**\n * Service to lazy load country data.\n * This reduces the initial bundle size by loading country data on-demand.\n */\n@Injectable({ providedIn: 'root' })\nexport class CountriesLoaderService {\n private readonly http = inject(HttpClient);\n private countriesData?: CountriesData;\n private loadPromise?: Promise<void>;\n\n /**\n * Loads country data from JSON file.\n * Subsequent calls return the same promise (singleton pattern).\n */\n private async loadCountries(): Promise<void> {\n if (this.countriesData) {\n return; // Already loaded\n }\n\n if (!this.loadPromise) {\n this.loadPromise = (async () => {\n try {\n this.countriesData = await firstValueFrom(\n this.http.get<CountriesData>('assets/data/countries.json'),\n );\n } catch (error) {\n console.error('Failed to load countries:', error);\n // Set to empty to avoid repeated failures\n this.countriesData = {\n countriesByID: {},\n unknownCountry: {\n id: '--',\n id3: '---',\n title: 'Unknown',\n geoRegions: [],\n emoji: '🏳️',\n },\n };\n }\n })();\n }\n\n return this.loadPromise;\n }\n\n /**\n * Gets all countries as an array.\n * Automatically loads country data if not yet loaded.\n */\n async getCountries(): Promise<readonly ICountry[]> {\n await this.loadCountries();\n return Object.values(this.countriesData!.countriesByID);\n }\n\n /**\n * Gets countries by ID lookup.\n * Automatically loads country data if not yet loaded.\n */\n async getCountriesByID(): Promise<Record<string, ICountry>> {\n await this.loadCountries();\n return this.countriesData!.countriesByID;\n }\n\n /**\n * Gets a specific country by ID.\n * Automatically loads country data if not yet loaded.\n */\n async getCountryByID(id: string): Promise<ICountry | undefined> {\n await this.loadCountries();\n return this.countriesData!.countriesByID[id];\n }\n\n /**\n * Gets the unknown country constant.\n * Automatically loads country data if not yet loaded.\n */\n async getUnknownCountry(): Promise<ICountry> {\n await this.loadCountries();\n return this.countriesData!.unknownCountry;\n }\n\n /**\n * Gets countries filtered by geo region.\n * Automatically loads country data if not yet loaded.\n */\n async getCountriesByRegion(region: GeoRegion): Promise<readonly ICountry[]> {\n const countries = await this.getCountries();\n return countries.filter((c) => c.geoRegions.includes(region));\n }\n}\n"]}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @deprecated Use CountriesLoaderService.getCountriesByID() instead.
3
+ * Country data is now lazy-loaded to reduce bundle size.
4
+ */
5
+ export const countriesByID = {};
6
+ /**
7
+ * @deprecated Use CountriesLoaderService.getUnknownCountry() instead.
8
+ * Country data is now lazy-loaded to reduce bundle size.
9
+ */
10
+ export const unknownCountry = {
11
+ id: '--',
12
+ id3: '---',
13
+ title: 'Unknown',
14
+ geoRegions: [],
15
+ emoji: '🏳️',
16
+ };
17
+ /**
18
+ * @deprecated Use CountriesLoaderService.getCountries() instead.
19
+ * Country data is now lazy-loaded to reduce bundle size.
20
+ */
21
+ export const countries = [];
22
+ //# sourceMappingURL=countries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"countries.js","sourceRoot":"","sources":["../../../../../../libs/components/src/lib/country-selector/countries.ts"],"names":[],"mappings":"AAmBA;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAA6B,EAAE,CAAC;AAE1D;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAa;IACtC,EAAE,EAAE,IAAI;IACR,GAAG,EAAE,KAAK;IACV,KAAK,EAAE,SAAS;IAChB,UAAU,EAAE,EAAE;IACd,KAAK,EAAE,KAAK;CACb,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,SAAS,GAAe,EAAE,CAAC","sourcesContent":["export type GeoRegion =\n | 'Europe'\n | 'Asia'\n | 'Americas'\n | 'South America'\n | 'North America'\n | 'Pacific Ocean'\n | 'Africa';\n\nexport interface ICountry {\n id: string;\n id3: string;\n geoRegions: GeoRegion[];\n title: string;\n longTitle?: string;\n shortTitle?: string;\n emoji: string;\n}\n\n/**\n * @deprecated Use CountriesLoaderService.getCountriesByID() instead.\n * Country data is now lazy-loaded to reduce bundle size.\n */\nexport const countriesByID: Record<string, ICountry> = {};\n\n/**\n * @deprecated Use CountriesLoaderService.getUnknownCountry() instead.\n * Country data is now lazy-loaded to reduce bundle size.\n */\nexport const unknownCountry: ICountry = {\n id: '--',\n id3: '---',\n title: 'Unknown',\n geoRegions: [],\n emoji: '🏳️',\n};\n\n/**\n * @deprecated Use CountriesLoaderService.getCountries() instead.\n * Country data is now lazy-loaded to reduce bundle size.\n */\nexport const countries: ICountry[] = [];\n"]}
@@ -0,0 +1,103 @@
1
+ import { Component, computed, EventEmitter, inject, Input, Output, signal, } from '@angular/core';
2
+ import { FormsModule } from '@angular/forms';
3
+ import { IonSegment, IonSegmentButton } from '@ionic/angular/standalone';
4
+ import { SelectFromListComponent } from '@sneat/ui';
5
+ import { CountriesLoaderService } from './countries-loader.service';
6
+ import * as i0 from "@angular/core";
7
+ import * as i1 from "@angular/forms";
8
+ export class CountrySelectorComponent {
9
+ constructor() {
10
+ this.countriesLoader = inject(CountriesLoaderService);
11
+ this.geoRegions = [
12
+ { id: 'Europe' },
13
+ { id: 'Asia' },
14
+ { id: 'Americas' },
15
+ { id: 'Africa' },
16
+ ];
17
+ this.readonly = false;
18
+ this.disabled = false;
19
+ this.label = 'search';
20
+ this.canBeUnknown = false;
21
+ this.countryIDChange = new EventEmitter();
22
+ this.filter = signal('', ...(ngDevMode ? [{ debugName: "filter" }] : []));
23
+ this.geoRegion = signal('All', ...(ngDevMode ? [{ debugName: "geoRegion" }] : []));
24
+ this.allCountries = signal([], ...(ngDevMode ? [{ debugName: "allCountries" }] : []));
25
+ this.unknownCountry = signal(undefined, ...(ngDevMode ? [{ debugName: "unknownCountry" }] : []));
26
+ this.countries = computed(() => {
27
+ const allCountries = this.allCountries();
28
+ if (allCountries.length === 0) {
29
+ return []; // Data not loaded yet
30
+ }
31
+ const filter = this.filter();
32
+ let countriesToShow = filter
33
+ ? allCountries
34
+ : allCountries.filter((c) => this.geoRegion() === 'All' ||
35
+ (this.geoRegion() === 'Americas' &&
36
+ (c.geoRegions.includes('North America') ||
37
+ c.geoRegions.includes('South America'))) ||
38
+ c.geoRegions.includes(this.geoRegion()));
39
+ if (this.canBeUnknown && this.unknownCountry()) {
40
+ countriesToShow = [...countriesToShow, this.unknownCountry()];
41
+ }
42
+ return countriesToShow;
43
+ }, ...(ngDevMode ? [{ debugName: "countries" }] : []));
44
+ this.filterCountryByCode = (item, filter) => {
45
+ const f = filter.trim().toUpperCase();
46
+ const c = item;
47
+ return c.id === f || c.id3.startsWith(f);
48
+ };
49
+ }
50
+ ngOnInit() {
51
+ // Load countries data
52
+ this.countriesLoader.getCountries().then((countries) => {
53
+ this.allCountries.set(countries);
54
+ });
55
+ this.countriesLoader.getUnknownCountry().then((unknown) => {
56
+ this.unknownCountry.set(unknown);
57
+ });
58
+ }
59
+ // protected geoRegion: GeoRegion | 'All' | 'Americas' = 'All';
60
+ onChanged() {
61
+ this.countryIDChange.emit(this.countryID);
62
+ }
63
+ onFilterChanged(filter) {
64
+ this.filter.set(filter);
65
+ }
66
+ ngOnChanges(changes) {
67
+ if (changes['country'] && this.countryID === '--' && !this.canBeUnknown) {
68
+ this.countryID = undefined;
69
+ }
70
+ if (changes['defaultCountryID'] &&
71
+ !this.countryID &&
72
+ this.defaultCountryID &&
73
+ this.defaultCountryID !== '--') {
74
+ this.countryID = this.defaultCountryID;
75
+ this.countryIDChange.emit(this.countryID);
76
+ }
77
+ }
78
+ onRegionChanged(event) {
79
+ this.geoRegion.set(event.detail.value);
80
+ }
81
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: CountrySelectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
82
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: CountrySelectorComponent, isStandalone: true, selector: "sneat-country-selector", inputs: { countryID: "countryID", defaultCountryID: "defaultCountryID", readonly: "readonly", disabled: "disabled", label: "label", canBeUnknown: "canBeUnknown" }, outputs: { countryIDChange: "countryIDChange" }, usesOnChanges: true, ngImport: i0, template: "<sneat-select-from-list\n [value]=\"countryID || ''\"\n [isFilterable]=\"true\"\n [filterLabel]=\"label\"\n [label]=\"label\"\n [items]=\"countries()\"\n [(ngModel)]=\"countryID\"\n (ngModelChange)=\"onChanged()\"\n [isReadonly]=\"readonly\"\n [filterItem]=\"filterCountryByCode\"\n (filterChanged)=\"onFilterChanged($event)\"\n labelPlacement=\"start\"\n>\n @if (!countryID && !filter()) {\n <ion-segment [(ngModel)]=\"geoRegion\" (ionChange)=\"onRegionChanged($event)\">\n <ion-segment-button value=\"All\">All</ion-segment-button>\n @for (region of geoRegions; track region.id) {\n <ion-segment-button [value]=\"region.id\">\n <small>{{ region.id }}</small>\n </ion-segment-button>\n }\n </ion-segment>\n }\n</sneat-select-from-list>\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: SelectFromListComponent, selector: "sneat-select-from-list", inputs: ["value", "filterLabel", "label", "listLabel", "listLabelColor", "isFilterable", "isLoading", "items", "items$", "lastItemLines", "labelPlacement", "justify", "other", "canAdd", "filterItem", "selectMode", "isReadonly", "$isProcessing", "sortBy"], outputs: ["valueChange", "filterChanged"] }, { kind: "component", type: IonSegment, selector: "ion-segment", inputs: ["color", "disabled", "mode", "scrollable", "selectOnFocus", "swipeGesture", "value"] }, { kind: "component", type: IonSegmentButton, selector: "ion-segment-button", inputs: ["contentId", "disabled", "layout", "mode", "type", "value"] }] }); }
83
+ }
84
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: CountrySelectorComponent, decorators: [{
85
+ type: Component,
86
+ args: [{ selector: 'sneat-country-selector', imports: [FormsModule, SelectFromListComponent, IonSegment, IonSegmentButton], template: "<sneat-select-from-list\n [value]=\"countryID || ''\"\n [isFilterable]=\"true\"\n [filterLabel]=\"label\"\n [label]=\"label\"\n [items]=\"countries()\"\n [(ngModel)]=\"countryID\"\n (ngModelChange)=\"onChanged()\"\n [isReadonly]=\"readonly\"\n [filterItem]=\"filterCountryByCode\"\n (filterChanged)=\"onFilterChanged($event)\"\n labelPlacement=\"start\"\n>\n @if (!countryID && !filter()) {\n <ion-segment [(ngModel)]=\"geoRegion\" (ionChange)=\"onRegionChanged($event)\">\n <ion-segment-button value=\"All\">All</ion-segment-button>\n @for (region of geoRegions; track region.id) {\n <ion-segment-button [value]=\"region.id\">\n <small>{{ region.id }}</small>\n </ion-segment-button>\n }\n </ion-segment>\n }\n</sneat-select-from-list>\n" }]
87
+ }], propDecorators: { countryID: [{
88
+ type: Input,
89
+ args: [{ required: true }]
90
+ }], defaultCountryID: [{
91
+ type: Input
92
+ }], readonly: [{
93
+ type: Input
94
+ }], disabled: [{
95
+ type: Input
96
+ }], label: [{
97
+ type: Input
98
+ }], canBeUnknown: [{
99
+ type: Input
100
+ }], countryIDChange: [{
101
+ type: Output
102
+ }] } });
103
+ //# sourceMappingURL=country-selector.component.js.map