@ukhomeoffice/formio-gds-template 3.0.0-alpha → 3.0.0-bravo

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 (105) hide show
  1. package/.github/workflows/build-and-test.yml +3 -3
  2. package/README.md +8 -0
  3. package/eslint.config.mjs +6 -5
  4. package/lib/components/datamap/GDSDataMap.d.ts +1 -0
  5. package/lib/components/datamap/GDSDataMap.d.ts.map +1 -0
  6. package/lib/components/datetime/GDSDatetimeComponent.d.ts +14 -1
  7. package/lib/components/datetime/GDSDatetimeComponent.d.ts.map +1 -0
  8. package/lib/components/datetime/GDSDatetimeComponent.js +28 -9
  9. package/lib/components/index.d.ts +3 -0
  10. package/lib/components/index.d.ts.map +1 -0
  11. package/lib/components/index.js +2 -0
  12. package/lib/components/select/GDSSelect.d.ts +143 -0
  13. package/lib/components/select/GDSSelect.d.ts.map +1 -0
  14. package/lib/components/select/GDSSelect.js +340 -0
  15. package/lib/components/selectboxes/GDSCheckBoxes.d.ts +1 -0
  16. package/lib/components/selectboxes/GDSCheckBoxes.d.ts.map +1 -0
  17. package/lib/components/time/GDSTimeComponent.d.ts +1 -0
  18. package/lib/components/time/GDSTimeComponent.d.ts.map +1 -0
  19. package/lib/components/time/GDSTimeComponent.js +5 -5
  20. package/lib/components/util/TimeHelper.d.ts +1 -0
  21. package/lib/components/util/TimeHelper.d.ts.map +1 -0
  22. package/lib/index.d.ts +3 -1
  23. package/lib/index.d.ts.map +1 -0
  24. package/lib/templates/gds/button/index.d.ts +1 -0
  25. package/lib/templates/gds/button/index.d.ts.map +1 -0
  26. package/lib/templates/gds/checkbox/index.d.ts +1 -0
  27. package/lib/templates/gds/checkbox/index.d.ts.map +1 -0
  28. package/lib/templates/gds/columns/index.d.ts +1 -0
  29. package/lib/templates/gds/columns/index.d.ts.map +1 -0
  30. package/lib/templates/gds/component/index.d.ts +1 -0
  31. package/lib/templates/gds/component/index.d.ts.map +1 -0
  32. package/lib/templates/gds/container/index.d.ts +1 -0
  33. package/lib/templates/gds/container/index.d.ts.map +1 -0
  34. package/lib/templates/gds/cssClasses.d.ts +1 -0
  35. package/lib/templates/gds/cssClasses.d.ts.map +1 -0
  36. package/lib/templates/gds/datagrid/form.ejs.js +2 -2
  37. package/lib/templates/gds/datagrid/index.d.ts +1 -0
  38. package/lib/templates/gds/datagrid/index.d.ts.map +1 -0
  39. package/lib/templates/gds/datamap/index.d.ts +1 -0
  40. package/lib/templates/gds/datamap/index.d.ts.map +1 -0
  41. package/lib/templates/gds/datetime/index.d.ts +1 -0
  42. package/lib/templates/gds/datetime/index.d.ts.map +1 -0
  43. package/lib/templates/gds/day/index.d.ts +1 -0
  44. package/lib/templates/gds/day/index.d.ts.map +1 -0
  45. package/lib/templates/gds/editgrid/index.d.ts +1 -0
  46. package/lib/templates/gds/editgrid/index.d.ts.map +1 -0
  47. package/lib/templates/gds/field/index.d.ts +1 -0
  48. package/lib/templates/gds/field/index.d.ts.map +1 -0
  49. package/lib/templates/gds/fieldset/index.d.ts +1 -0
  50. package/lib/templates/gds/fieldset/index.d.ts.map +1 -0
  51. package/lib/templates/gds/file/index.d.ts +1 -0
  52. package/lib/templates/gds/file/index.d.ts.map +1 -0
  53. package/lib/templates/gds/iconClass.d.ts +1 -0
  54. package/lib/templates/gds/iconClass.d.ts.map +1 -0
  55. package/lib/templates/gds/index.d.ts +2 -1
  56. package/lib/templates/gds/index.d.ts.map +1 -0
  57. package/lib/templates/gds/input/index.d.ts +1 -0
  58. package/lib/templates/gds/input/index.d.ts.map +1 -0
  59. package/lib/templates/gds/label/index.d.ts +1 -0
  60. package/lib/templates/gds/label/index.d.ts.map +1 -0
  61. package/lib/templates/gds/message/index.d.ts +1 -0
  62. package/lib/templates/gds/message/index.d.ts.map +1 -0
  63. package/lib/templates/gds/panel/index.d.ts +1 -0
  64. package/lib/templates/gds/panel/index.d.ts.map +1 -0
  65. package/lib/templates/gds/radio/index.d.ts +1 -0
  66. package/lib/templates/gds/radio/index.d.ts.map +1 -0
  67. package/lib/templates/gds/select/index.d.ts +1 -0
  68. package/lib/templates/gds/select/index.d.ts.map +1 -0
  69. package/lib/templates/gds/selectOption/index.d.ts +1 -0
  70. package/lib/templates/gds/selectOption/index.d.ts.map +1 -0
  71. package/lib/templates/gds/selectboxes/index.d.ts +1 -0
  72. package/lib/templates/gds/selectboxes/index.d.ts.map +1 -0
  73. package/lib/templates/gds/survey/index.d.ts +1 -0
  74. package/lib/templates/gds/survey/index.d.ts.map +1 -0
  75. package/lib/templates/gds/tab/index.d.ts +1 -0
  76. package/lib/templates/gds/tab/index.d.ts.map +1 -0
  77. package/lib/templates/gds/table/index.d.ts +1 -0
  78. package/lib/templates/gds/table/index.d.ts.map +1 -0
  79. package/lib/templates/gds/template.css +11 -0
  80. package/lib/templates/gds/template.css.map +1 -1
  81. package/lib/templates/gds/time/index.d.ts +1 -0
  82. package/lib/templates/gds/time/index.d.ts.map +1 -0
  83. package/lib/templates/gds/warning/index.d.ts +1 -0
  84. package/lib/templates/gds/warning/index.d.ts.map +1 -0
  85. package/lib/templates/gds/wizard/index.d.ts +1 -0
  86. package/lib/templates/gds/wizard/index.d.ts.map +1 -0
  87. package/lib/templates/gds/wizardHeader/index.d.ts +1 -0
  88. package/lib/templates/gds/wizardHeader/index.d.ts.map +1 -0
  89. package/lib/templates/gds/wizardNav/index.d.ts +1 -0
  90. package/lib/templates/gds/wizardNav/index.d.ts.map +1 -0
  91. package/lib/templates/index.d.ts +2 -1
  92. package/lib/templates/index.d.ts.map +1 -0
  93. package/lib/types.d.ts +3 -2
  94. package/lib/types.d.ts.map +1 -0
  95. package/package.json +2 -1
  96. package/src/components/datetime/GDSDatetimeComponent.ts +28 -9
  97. package/src/components/index.ts +2 -0
  98. package/src/components/select/GDSSelect.spec.ts +538 -0
  99. package/src/components/select/GDSSelect.ts +418 -0
  100. package/src/components/time/GDSTimeComponent.ts +5 -5
  101. package/src/templates/gds/datagrid/form.ejs +1 -2
  102. package/src/templates/gds/index.ts +1 -1
  103. package/src/templates/gds/template.scss +18 -0
  104. package/src/types.ts +2 -1
  105. package/tsconfig.json +17 -4
@@ -6,10 +6,10 @@ jobs:
6
6
  build_and_test:
7
7
  runs-on: ubuntu-latest
8
8
  steps:
9
- - uses: actions/checkout@v2
10
- - uses: actions/setup-node@v2
9
+ - uses: actions/checkout@v4
10
+ - uses: actions/setup-node@v4
11
11
  with:
12
- node-version: 14
12
+ node-version: 20
13
13
  - name: Install dependencies
14
14
  run: |
15
15
  rm -rf node_modules
package/README.md CHANGED
@@ -16,6 +16,14 @@ NodeJS version 20
16
16
  npm install @ukhomeoffice/formio-gds-template
17
17
  ```
18
18
 
19
+ The compiled `lib/` directory is generated during packaging and is intentionally not committed to the repository. To publish a local build to an application using Yalc, run:
20
+
21
+ ```bash
22
+ npm run yalc:push
23
+ ```
24
+
25
+ This builds the package before pushing it, so the consuming application imports the same compiled files that would be included in an npm package.
26
+
19
27
  ## Usage
20
28
 
21
29
  Using vanilla formio
package/eslint.config.mjs CHANGED
@@ -47,12 +47,13 @@ export default [
47
47
  // tslint max-classes-per-file: false — off (default)
48
48
  'max-classes-per-file': 'off',
49
49
 
50
- // Remaining `any` annotations are intentional — each is accompanied by a comment
51
- // explaining it matches a base-class override signature in @formio/js. Warn rather
52
- // than error so new unintentional `any` is surfaced without breaking CI.
53
- '@typescript-eslint/no-explicit-any': 'warn',
50
+ // Enforce explicit types and disallow untyped variables
51
+ '@typescript-eslint/no-explicit-any': 'error',
54
52
  // Parameters prefixed with _ are intentionally unused (e.g. _flags in override signatures).
55
- '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
53
+ '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
54
+ // Enforce explicit return types on functions and class methods for clear public API contracts
55
+ '@typescript-eslint/explicit-function-return-type': ['error', { allowExpressions: true }],
56
+ '@typescript-eslint/explicit-module-boundary-types': 'error',
56
57
  },
57
58
  },
58
59
  ];
@@ -5,3 +5,4 @@ export default class GDSDataMap extends DataMap {
5
5
  render(): string;
6
6
  }
7
7
  export {};
8
+ //# sourceMappingURL=GDSDataMap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GDSDataMap.d.ts","sourceRoot":"","sources":["../../../src/components/datamap/GDSDataMap.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAG/C,QAAA,MAAM,OAAO,KAAgC,CAAC;AAE9C,MAAM,CAAC,OAAO,OAAO,UAAW,SAAQ,OAAO;IAEnC,SAAS,EAAE,gBAAgB,CAAC;IAE7B,MAAM,IAAI,MAAM;CAiB1B"}
@@ -27,6 +27,18 @@ export default class GDSDatetimeComponent extends Day {
27
27
  };
28
28
  private timeHelper;
29
29
  attach(element: any): Promise<void>;
30
+ /**
31
+ * Override t() to remap translation keys emitted by @formio/core validators that
32
+ * differ from the @formio/js English translation map.
33
+ *
34
+ * @formio/core's date validator emits FieldError('invalidDate', ...) (camelCase).
35
+ * @formio/js translations only define 'invalid_date' (underscore). When t()
36
+ * cannot find 'invalidDate' it returns the raw key as the error message.
37
+ *
38
+ * We map the camelCase core keys to their underscored @formio/js equivalents so
39
+ * the user sees a proper human-readable message.
40
+ */
41
+ t(text: any, ...args: any[]): any;
30
42
  init(): void;
31
43
  setErrorClasses(elements: any, dirty: any, hasError: any): void;
32
44
  removeInputError(elements: any): void;
@@ -34,10 +46,11 @@ export default class GDSDatetimeComponent extends Day {
34
46
  getDate(value: any): string | null;
35
47
  getFieldValue(name: any): string | null;
36
48
  boolValue(value: unknown): boolean;
37
- setValueAt(index: number, value: any): void;
49
+ setValueAt(_index: number, value: any): void;
38
50
  getValueAt(index: number): string | null;
39
51
  normalizeValue(value: any): any;
40
52
  validateRequired(setting: any, value: any): boolean;
41
53
  private processField;
42
54
  }
43
55
  export {};
56
+ //# sourceMappingURL=GDSDatetimeComponent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GDSDatetimeComponent.d.ts","sourceRoot":"","sources":["../../../src/components/datetime/GDSDatetimeComponent.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AAGzD,QAAA,MAAM,GAAG,KAA4B,CAAC;AAEtC,MAAM,CAAC,OAAO,OAAO,oBAAqB,SAAQ,GAAG;IAKzC,SAAS,EAAE,0BAA0B,CAAC;IAItC,IAAI,EAAE;QACV,IAAI,EAAE,gBAAgB,CAAC;QACvB,MAAM,EAAE,gBAAgB,CAAC;QACzB,GAAG,EAAE,gBAAgB,CAAC;QACtB,KAAK,EAAE,gBAAgB,CAAC;QACxB,IAAI,EAAE,gBAAgB,CAAC;QACvB,KAAK,EAAE,gBAAgB,EAAE,CAAC;KAC7B,CAAC;IACM,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,cAAc,EAAE,OAAO,CAAC;IACxB,aAAa,EAAE,MAAM,IAAI,CAAC;IAElC,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,IAAI,YAAY,IAAI,MAAM,CAOzB;IAED,IAAI,UAAU,IAAI,IAAI,CAErB;IAED,IAAI,KAAK,IAAI;QAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAQzH;IAED,OAAO,CAAC,UAAU,CAAgC;IAI3C,MAAM,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IA8C1C;;;;;;;;;;OAUG;IAEI,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,GAAG;IAOjC,IAAI,IAAI,IAAI;IA0BZ,eAAe,CAAC,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,GAAG,IAAI;IAM/D,gBAAgB,CAAC,QAAQ,EAAE,GAAG,GAAG,IAAI;IAIrC,MAAM,IAAI,MAAM;IAgBhB,OAAO,CAAC,KAAK,EAAE,GAAG,GAAG,MAAM,GAAG,IAAI;IAwClC,aAAa,CAAC,IAAI,EAAE,GAAG,GAAG,MAAM,GAAG,IAAI;IA+BvC,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO;IAYlC,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,IAAI;IAyB5C,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAcxC,cAAc,CAAC,KAAK,EAAE,GAAG,GAAG,GAAG;IAM/B,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,GAAG,OAAO;IAyB1D,OAAO,CAAC,YAAY;CAWvB"}
@@ -62,7 +62,7 @@ class GDSDatetimeComponent extends Day {
62
62
  };
63
63
  }
64
64
  // element typed as `any` to match the base Day.attach(element: any) override signature
65
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
65
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
66
66
  attach(element) {
67
67
  this.loadRefs(element, { hour: 'single', minute: 'single' });
68
68
  this.addEventListener(this.refs.hour, 'input', () => {
@@ -100,6 +100,25 @@ class GDSDatetimeComponent extends Day {
100
100
  });
101
101
  return superAttach;
102
102
  }
103
+ /**
104
+ * Override t() to remap translation keys emitted by @formio/core validators that
105
+ * differ from the @formio/js English translation map.
106
+ *
107
+ * @formio/core's date validator emits FieldError('invalidDate', ...) (camelCase).
108
+ * @formio/js translations only define 'invalid_date' (underscore). When t()
109
+ * cannot find 'invalidDate' it returns the raw key as the error message.
110
+ *
111
+ * We map the camelCase core keys to their underscored @formio/js equivalents so
112
+ * the user sees a proper human-readable message.
113
+ */
114
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
115
+ t(text, ...args) {
116
+ var _a;
117
+ const keyMap = {
118
+ invalidDate: 'invalid_date',
119
+ };
120
+ return super.t((_a = keyMap[text]) !== null && _a !== void 0 ? _a : text, ...args);
121
+ }
103
122
  init() {
104
123
  var _a, _b, _c, _d, _e, _f, _g, _h, _j;
105
124
  super.init();
@@ -123,12 +142,12 @@ class GDSDatetimeComponent extends Day {
123
142
  };
124
143
  }
125
144
  // elements typed as `any` to match the base Day.setErrorClasses(elements: any, ...) override signature
126
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
145
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
127
146
  setErrorClasses(elements, dirty, hasError) {
128
147
  super.setErrorClasses([this.refs.hour, this.refs.minute, ...elements], dirty, hasError);
129
148
  }
130
149
  // elements typed as `any` to match the base Component.removeInputError(elements: any) signature
131
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
150
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
132
151
  removeInputError(elements) {
133
152
  super.removeInputError([this.refs.hour, this.refs.minute, ...elements]);
134
153
  }
@@ -146,7 +165,7 @@ class GDSDatetimeComponent extends Day {
146
165
  }));
147
166
  }
148
167
  // value typed as `any` to match the base Day.getDate(value: any): null | string signature
149
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
168
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
150
169
  getDate(value) {
151
170
  const defaults = [];
152
171
  const [DAY, MONTH, YEAR, HOUR, MINUTE] = [0, 1, 2, 3, 4];
@@ -181,7 +200,7 @@ class GDSDatetimeComponent extends Day {
181
200
  return toMoment.format();
182
201
  }
183
202
  // name typed as `any` to match the base Day.getFieldValue(name: any): number signature
184
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
203
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
185
204
  getFieldValue(name) {
186
205
  if (this.dataValue && this.dataValue !== 'Invalid date') {
187
206
  try {
@@ -224,8 +243,8 @@ class GDSDatetimeComponent extends Day {
224
243
  }
225
244
  }
226
245
  // value typed as `any` to match the base Day.setValueAt(index: number, value: any) signature
227
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
228
- setValueAt(index, value) {
246
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
247
+ setValueAt(_index, value) {
229
248
  // temporary solution to avoid input reset on invalid date.
230
249
  if (!value || value === 'Invalid date') {
231
250
  return;
@@ -262,12 +281,12 @@ class GDSDatetimeComponent extends Day {
262
281
  }
263
282
  }
264
283
  // value typed as `any` to match the base Component.normalizeValue(value: any): any signature
265
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
284
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
266
285
  normalizeValue(value) {
267
286
  return value;
268
287
  }
269
288
  // setting/value typed as `any` to match the base Day.validateRequired(setting: any, value: any) signature
270
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
289
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
271
290
  validateRequired(setting, value) {
272
291
  var _a, _b, _c, _d, _e;
273
292
  const { day, month, year, minute, hour } = this.parts;
@@ -1,11 +1,14 @@
1
1
  import datamap from './datamap/GDSDataMap';
2
2
  import datetime from './datetime/GDSDatetimeComponent';
3
+ import select from './select/GDSSelect';
3
4
  import selectboxes from './selectboxes/GDSCheckBoxes';
4
5
  import time from './time/GDSTimeComponent';
5
6
  declare const _default: {
6
7
  datamap: typeof datamap;
7
8
  datetime: typeof datetime;
9
+ select: typeof select;
8
10
  selectboxes: typeof selectboxes;
9
11
  time: typeof time;
10
12
  };
11
13
  export default _default;
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,sBAAsB,CAAC;AAC3C,OAAO,QAAQ,MAAM,iCAAiC,CAAC;AACvD,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,WAAW,MAAM,6BAA6B,CAAC;AACtD,OAAO,IAAI,MAAM,yBAAyB,CAAC;;;;;;;;AAE3C,wBAME"}
@@ -5,11 +5,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const GDSDataMap_1 = __importDefault(require("./datamap/GDSDataMap"));
7
7
  const GDSDatetimeComponent_1 = __importDefault(require("./datetime/GDSDatetimeComponent"));
8
+ const GDSSelect_1 = __importDefault(require("./select/GDSSelect"));
8
9
  const GDSCheckBoxes_1 = __importDefault(require("./selectboxes/GDSCheckBoxes"));
9
10
  const GDSTimeComponent_1 = __importDefault(require("./time/GDSTimeComponent"));
10
11
  exports.default = {
11
12
  datamap: GDSDataMap_1.default,
12
13
  datetime: GDSDatetimeComponent_1.default,
14
+ select: GDSSelect_1.default,
13
15
  selectboxes: GDSCheckBoxes_1.default,
14
16
  time: GDSTimeComponent_1.default,
15
17
  };
@@ -0,0 +1,143 @@
1
+ import { SelectComponent as CoreSelectComponent } from '../../types';
2
+ declare const Select: any;
3
+ interface ChoiceItem {
4
+ label: string;
5
+ active: boolean;
6
+ rank: number;
7
+ id: string | number;
8
+ choiceEl?: HTMLElement;
9
+ [key: string]: unknown;
10
+ }
11
+ interface SearchResult {
12
+ item: ChoiceItem;
13
+ score: number;
14
+ rank: number;
15
+ }
16
+ interface ChoicesInstance {
17
+ _isSearching: boolean;
18
+ _currentValue: string;
19
+ _store: {
20
+ choices: ChoiceItem[];
21
+ dispatch(action: {
22
+ type: string;
23
+ active?: boolean;
24
+ results?: SearchResult[];
25
+ }): void;
26
+ };
27
+ _searchChoices?: (needle: string) => number | null;
28
+ input?: {
29
+ element?: HTMLInputElement;
30
+ };
31
+ }
32
+ /**
33
+ * A formio item from a URL datasource — at minimum it has an id and arbitrary
34
+ * string fields (e.g. name, code). We only constrain what we actually access.
35
+ */
36
+ interface ReferenceItem {
37
+ id?: string | number;
38
+ label?: string;
39
+ [key: string]: unknown;
40
+ }
41
+ /**
42
+ * Shape of the `value` argument passed to itemTemplate / getOptionTemplate.
43
+ * For reference selects (valueProperty = '') this is the full item object;
44
+ * for string selects it is a plain string.
45
+ */
46
+ type SelectValue = ReferenceItem | string | number | null | undefined;
47
+ export default class GDSSelect extends Select {
48
+ component: CoreSelectComponent;
49
+ protected _gdsSearchPatchedChoices?: ChoicesInstance;
50
+ protected _gdsFilterKey?: string;
51
+ constructor(component?: any, options?: any, data?: any);
52
+ init(): any;
53
+ /**
54
+ * Patch the choices.js instance attached to this component so that every
55
+ * search query uses a plain case-insensitive substring filter instead of
56
+ * fuse.js. The patch is applied lazily the first time items are set so
57
+ * that `this.choices` is guaranteed to exist.
58
+ */
59
+ protected _patchChoicesSearch(): void;
60
+ /**
61
+ * True when this select's `filter` is interpolated from other form data
62
+ * (e.g. a port list filtered by the selected country).
63
+ */
64
+ protected get _gdsHasDynamicFilter(): boolean;
65
+ /** The interpolated filter, used to detect when the dependency changed. */
66
+ protected _gdsCurrentFilterKey(): string;
67
+ setItems(items: unknown, fromSearch?: boolean): void;
68
+ attach(element: HTMLElement): Promise<unknown>;
69
+ checkComponentConditions(data: any, flags: any, row: any): boolean;
70
+ updateItems(searchInput: unknown, forceUpdate: boolean): any;
71
+ /**
72
+ * Override getOptionTemplate to escape item data values with `_.escape()`
73
+ * before interpolating them into the template.
74
+ *
75
+ * ## Security model
76
+ *
77
+ * formio 5.x `getOptionTemplate` (ListComponent) passes the assembled template
78
+ * string through `DOMPurify.sanitize()` — which internally calls
79
+ * `DOMParser.parseFromString()`. With thousands of reference-data items this
80
+ * is the dominant performance cost (~300 ms).
81
+ *
82
+ * We replace that post-hoc sanitization with pre-interpolation escaping:
83
+ *
84
+ * 1. Every string value in the item object is passed through `_.escape()`
85
+ * **before** it is substituted into the template. `_.escape` converts
86
+ * `< > & " '` to their HTML-entity equivalents (`&lt;` etc.).
87
+ * 2. The assembled template string — now containing only safe entity-encoded
88
+ * text where user/API data appears — is returned directly without any
89
+ * further DOMPurify call.
90
+ *
91
+ * ### Why this is equivalent security to DOMPurify for text-content templates
92
+ *
93
+ * A template such as `<span>{{ item.name }}</span>` embeds the API value as
94
+ * the *text content* of an element. The only injection vector is:
95
+ *
96
+ * ```
97
+ * item.name = '</span><script>alert(1)</script>'
98
+ * ```
99
+ *
100
+ * After `_.escape()` this becomes:
101
+ *
102
+ * ```
103
+ * &lt;/span&gt;&lt;script&gt;alert(1)&lt;/script&gt;
104
+ * ```
105
+ *
106
+ * The browser renders this as literal text, never as markup or script.
107
+ * DOMPurify would produce the same effective result by stripping the tags.
108
+ *
109
+ * ### Limitation — attribute / URL contexts
110
+ *
111
+ * `_.escape()` is **not** sufficient if the template places a value inside
112
+ * an HTML attribute or a URL (e.g. `<a href="{{ item.url }}">`).
113
+ * HTML-entity encoding does not prevent `javascript:` injection in `href`.
114
+ * If any form schema introduces such a template, this override must be
115
+ * revisited and either DOMPurify reinstated or the attribute value
116
+ * sanitized separately.
117
+ *
118
+ * Current GDS templates are all text-content only (`<span>{{ item.name }}</span>`
119
+ * etc.) so this limitation does not apply today.
120
+ */
121
+ getOptionTemplate(data: ReferenceItem, value: SelectValue, index?: number): string;
122
+ /**
123
+ * Override itemTemplate to skip the redundant outer `sanitize()` call that
124
+ * formio 5.x `ListComponent.itemTemplate` wraps around `getOptionTemplate()`.
125
+ *
126
+ * ## Why the outer sanitize is now safe to skip
127
+ *
128
+ * Our `getOptionTemplate` override (above) pre-escapes all API data values
129
+ * with `_.escape()` before they are interpolated into the template. The
130
+ * assembled string therefore contains no unescaped HTML from variable sources.
131
+ * Running DOMPurify on that string a second time is idempotent — it produces
132
+ * the same output — but costs a full `DOMParser.parseFromString` call per item.
133
+ *
134
+ * This override handles only the common URL-datasource path (object data with
135
+ * a component template). All other branches — primitives, arrays, read-only,
136
+ * selectData, reference fields — fall through to `super.itemTemplate` which
137
+ * retains its full sanitize() call unchanged.
138
+ */
139
+ itemTemplate(data: ReferenceItem | string | number | unknown[], value: SelectValue, index?: number): any;
140
+ choicesOptions(): Record<string, any>;
141
+ }
142
+ export {};
143
+ //# sourceMappingURL=GDSSelect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GDSSelect.d.ts","sourceRoot":"","sources":["../../../src/components/select/GDSSelect.ts"],"names":[],"mappings":"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"}