@abgov/jsonforms-components 2.75.2 → 2.76.0

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.
package/index.esm.js CHANGED
@@ -13890,10 +13890,17 @@ const FullNameDobReviewControl = props => {
13890
13890
  const GoAInputBaseFullNameDobControlReview = withJsonFormsAllOfProps(FullNameDobReviewControl);
13891
13891
 
13892
13892
  // Encapsulates masked-input state for a GoA input: display value, mount reflection, and change/keypress handling.
13893
+ const resetMaskedValue = (detail, nextValue) => {
13894
+ const target = getMaskInputTarget(detail);
13895
+ if (target) {
13896
+ target.value = nextValue;
13897
+ }
13898
+ };
13893
13899
  const useMaskedInput = ({
13894
13900
  mask,
13895
13901
  inPlace,
13896
13902
  data,
13903
+ allowedKeys,
13897
13904
  onCommit
13898
13905
  }) => {
13899
13906
  const format = value => inPlace ? toMaskTemplate(value, mask) : formatWithPattern(value, mask);
@@ -13909,20 +13916,24 @@ const useMaskedInput = ({
13909
13916
  const handleChange = detail => {
13910
13917
  var _target$selectionStar;
13911
13918
  const rawValue = detail.value;
13919
+ const cleaned = allowedKeys ? filterAllowedKeys(rawValue, allowedKeys) : rawValue;
13912
13920
  if (!inPlace) {
13913
- const stored = formatWithPattern(rawValue, mask);
13921
+ const stored = cleaned === '' ? '' : formatWithPattern(cleaned, mask);
13922
+ if (allowedKeys && cleaned !== rawValue) {
13923
+ resetMaskedValue(detail, stored);
13924
+ }
13914
13925
  setValue(stored);
13915
13926
  onCommit(stored);
13916
13927
  return;
13917
13928
  }
13918
13929
  const target = getMaskInputTarget(detail);
13919
- const caretIndex = (_target$selectionStar = target == null ? void 0 : target.selectionStart) != null ? _target$selectionStar : rawValue.length;
13920
- const overflow = overflowMaskEdit(value, rawValue, caretIndex, mask);
13930
+ const caretIndex = (_target$selectionStar = target == null ? void 0 : target.selectionStart) != null ? _target$selectionStar : cleaned.length;
13931
+ const overflow = overflowMaskEdit(value, cleaned, caretIndex, mask);
13921
13932
  if (overflow) {
13922
13933
  applyInPlaceEdit(target, overflow);
13923
13934
  return;
13924
13935
  }
13925
- const edit = computeMaskEdit(rawValue, caretIndex, mask);
13936
+ const edit = computeMaskEdit(cleaned, caretIndex, mask);
13926
13937
  applyInPlaceEdit(target, edit);
13927
13938
  setValue(edit.display);
13928
13939
  onCommit(edit.stored);
@@ -13930,10 +13941,15 @@ const useMaskedInput = ({
13930
13941
  // In-place has no maxLength (the template is already full length) and GoA keyPress is keyup, so restore on overflow.
13931
13942
  const handleKeyPress = detail => {
13932
13943
  var _detail$event, _target$value, _target$selectionStar2;
13933
- if (!inPlace || !/^[A-Za-z0-9]$/.test(detail.key) || !isMaskFilled(value, mask)) {
13944
+ const blockDisallowed = shouldBlockKey(detail.key, allowedKeys);
13945
+ const blockOverflow = inPlace && /^[A-Za-z0-9]$/.test(detail.key) && isMaskFilled(value, mask);
13946
+ if (!blockDisallowed && !blockOverflow) {
13934
13947
  return;
13935
13948
  }
13936
13949
  (_detail$event = detail.event) == null || _detail$event.preventDefault();
13950
+ if (!blockOverflow) {
13951
+ return;
13952
+ }
13937
13953
  const target = getMaskInputTarget(detail);
13938
13954
  const rawValue = (_target$value = target == null ? void 0 : target.value) != null ? _target$value : value;
13939
13955
  const overflow = overflowMaskEdit(value, rawValue, (_target$selectionStar2 = target == null ? void 0 : target.selectionStart) != null ? _target$selectionStar2 : value.length, mask);
@@ -13973,6 +13989,7 @@ const PhoneNumberControl = props => {
13973
13989
  mask: phoneMask,
13974
13990
  inPlace,
13975
13991
  data,
13992
+ allowedKeys: DEFAULT_PATTERNS.phone.allowedKeys,
13976
13993
  onCommit: stored => {
13977
13994
  setError(stored && !DEFAULT_PATTERNS.phone.pattern.test(stored) ? DEFAULT_PATTERNS.phone.error : '');
13978
13995
  handleChange(path, stored);
@@ -13995,7 +14012,7 @@ const PhoneNumberControl = props => {
13995
14012
  maxLength: inPlace ? undefined : phoneMask.length,
13996
14013
  placeholder: inPlace ? undefined : maskPlaceholder(phoneMask),
13997
14014
  onChange: detail => handleMaskChange(detail),
13998
- onKeyPress: inPlace ? detail => handleKeyPress(detail) : undefined,
14015
+ onKeyPress: detail => handleKeyPress(detail),
13999
14016
  width: "100%"
14000
14017
  })
14001
14018
  })
@@ -20623,6 +20640,24 @@ var GoAErrorControl = withJsonFormsControlProps(ErrorControl);
20623
20640
 
20624
20641
  // Allow empty values so incomplete fields are not treated as format errors.
20625
20642
  const optionalFormat = pattern => input => !input || pattern.test(input);
20643
+ const optionalSinFormat = input => {
20644
+ if (!input) {
20645
+ return true;
20646
+ }
20647
+ if (!DEFAULT_PATTERNS.sin.pattern.test(input)) {
20648
+ return false;
20649
+ }
20650
+ return validateSinWithLuhn(input);
20651
+ };
20652
+ const isValidSinWhenComplete = data => {
20653
+ if (typeof data !== 'string' || data.length === 0) {
20654
+ return true;
20655
+ }
20656
+ if (!DEFAULT_PATTERNS.sin.pattern.test(data)) {
20657
+ return true;
20658
+ }
20659
+ return validateSinWithLuhn(data);
20660
+ };
20626
20661
  const createDefaultAjv = (...schemas) => {
20627
20662
  const ajv = new Ajv({
20628
20663
  allErrors: true,
@@ -20637,7 +20672,7 @@ const createDefaultAjv = (...schemas) => {
20637
20672
  addFormats(ajv);
20638
20673
  ajv.addFormat('time', /^([01]\d|2[0-3]):[0-5]\d(:[0-5]\d)?$/);
20639
20674
  Object.entries(DEFAULT_PATTERNS).forEach(([format, config]) => {
20640
- ajv.addFormat(format, optionalFormat(config.pattern));
20675
+ ajv.addFormat(format, format === 'sin' ? optionalSinFormat : optionalFormat(config.pattern));
20641
20676
  });
20642
20677
  ajv.addFormat('phone', PHONE_REGEX);
20643
20678
  ajv.addFormat('computed', /^[a-zA-Z0-9._-]+$/);
@@ -20659,14 +20694,10 @@ const createDefaultAjv = (...schemas) => {
20659
20694
  type: 'string',
20660
20695
  schemaType: 'boolean',
20661
20696
  validate: (shouldValidate, data) => {
20662
- if (!shouldValidate) return true;
20663
- if (typeof data !== 'string' || data.length === 0) {
20664
- return true;
20665
- }
20666
- if (!/^\d{3} \d{3} \d{3}$/.test(data)) {
20697
+ if (shouldValidate === false) {
20667
20698
  return true;
20668
20699
  }
20669
- return validateSinWithLuhn(data);
20700
+ return isValidSinWhenComplete(data);
20670
20701
  },
20671
20702
  error: {
20672
20703
  message: invalidSin
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abgov/jsonforms-components",
3
- "version": "2.75.2",
3
+ "version": "2.76.0",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Government of Alberta - React renderers for JSON Forms based on the design system.",
6
6
  "repository": "https://github.com/GovAlta/adsp-monorepo",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": "1.0.0",
3
- "generatedAt": "2026-09-09T19:26:19.202Z",
4
- "sourceCommit": "7fb9064678498d4c0d4a0cc3926968d141a9f242",
3
+ "generatedAt": "2026-09-11T14:27:30.190Z",
4
+ "sourceCommit": "485a48a50395d09849d740a77ea76cbe502ba424",
5
5
  "sourcePath": "libs/jsonforms-components/src/index.ts",
6
6
  "rendererCount": 33,
7
7
  "renderers": [
@@ -10,6 +10,7 @@ interface UseMaskedInputOptions {
10
10
  mask: string;
11
11
  inPlace: boolean;
12
12
  data: unknown;
13
+ allowedKeys?: RegExp;
13
14
  onCommit: (stored: string) => void;
14
15
  }
15
16
  interface UseMaskedInputResult {
@@ -17,5 +18,5 @@ interface UseMaskedInputResult {
17
18
  handleChange: (detail: MaskChangeDetail) => void;
18
19
  handleKeyPress: (detail: MaskKeyPressDetail) => void;
19
20
  }
20
- export declare const useMaskedInput: ({ mask, inPlace, data, onCommit }: UseMaskedInputOptions) => UseMaskedInputResult;
21
+ export declare const useMaskedInput: ({ mask, inPlace, data, allowedKeys, onCommit, }: UseMaskedInputOptions) => UseMaskedInputResult;
21
22
  export {};