@genesislcap/foundation-ui 14.411.0 → 14.412.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.
@@ -8,6 +8,27 @@ export declare class TextField extends FASTTextField {
8
8
  autocapitalize: string;
9
9
  private autocapitalizeChanged;
10
10
  step: number;
11
+ /**
12
+ * Optional non-editable label shown on the left inside the field, before the input.
13
+ */
14
+ prefix: string;
15
+ /**
16
+ * Optional non-editable suffix (e.g. unit label) shown on the right inside the field.
17
+ */
18
+ suffix: string;
19
+ /**
20
+ * When true, prefix/suffix are not exposed to assistive technology (`aria-hidden` on affixes, and their ids are omitted from the control’s `aria-describedby`).
21
+ * Use only when the unit or symbol is redundant with the visible label or other text.
22
+ * @remarks
23
+ * By default, affix text is **included** for screen readers: stable ids are assigned to the affix nodes and referenced from the input’s `aria-describedby` (merged with any author `aria-describedby`), which announces them as supplementary description after the field name from the label.
24
+ * For cases where the affix should be part of the accessible **name** instead (e.g. currency code read as part of the label), set `hide-affix-from-screen-reader` and wire `aria-labelledby` on the host to reference the label slot and your own elements, or provide a single `aria-label` that includes the full name.
25
+ */
26
+ hideAffixFromScreenReader: boolean;
27
+ /**
28
+ * Merges the host `aria-describedby` with ids of the prefix/suffix nodes when those affixes are exposed to SRs.
29
+ * @internal
30
+ */
31
+ get controlAriaDescribedby(): string | undefined;
11
32
  }
12
33
  export declare const foundationTextFieldShadowOptions: ShadowRootInit;
13
34
  export declare const defaultTextFieldConfig: {};
@@ -1 +1 @@
1
- {"version":3,"file":"text-field.d.ts","sourceRoot":"","sources":["../../../src/text-field/text-field.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAOxE;;GAEG;AACH,qBAAa,SAAU,SAAQ,aAAa;IACpC,YAAY,EAAE,MAAM,CAAS;IACnC,OAAO,CAAC,mBAAmB;IAKrB,cAAc,EAAE,MAAM,CAAS;IACrC,OAAO,CAAC,qBAAqB;IAKvB,IAAI,EAAE,MAAM,CAAC;CACpB;AAGD,eAAO,MAAM,gCAAgC,EAAE,cAG9C,CAAC;AAEF,eAAO,MAAM,sBAAsB,IAAK,CAAC;AAEzC;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,yTAM9B,CAAC"}
1
+ {"version":3,"file":"text-field.d.ts","sourceRoot":"","sources":["../../../src/text-field/text-field.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAOxE;;GAEG;AACH,qBAAa,SAAU,SAAQ,aAAa;IACpC,YAAY,EAAE,MAAM,CAAS;IACnC,OAAO,CAAC,mBAAmB;IAKrB,cAAc,EAAE,MAAM,CAAS;IACrC,OAAO,CAAC,qBAAqB;IAKvB,IAAI,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACG,MAAM,EAAE,MAAM,CAAC;IAErB;;OAEG;IACG,MAAM,EAAE,MAAM,CAAC;IAErB;;;;;;OAMG;IAEH,yBAAyB,EAAE,OAAO,CAAS;IAE3C;;;OAGG;IACH,IAAI,sBAAsB,IAAI,MAAM,GAAG,SAAS,CAyB/C;CACF;AAGD,eAAO,MAAM,gCAAgC,EAAE,cAG9C,CAAC;AAEF,eAAO,MAAM,sBAAsB,IAAK,CAAC;AAEzC;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,yTAM9B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"text-field.styles.d.ts","sourceRoot":"","sources":["../../../src/text-field/text-field.styles.ts"],"names":[],"mappings":"AAEA,OAAO,EAAO,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,KAAK,EACV,wBAAwB,EACxB,2BAA2B,EAC5B,MAAM,4BAA4B,CAAC;AAEpC,eAAO,MAAM,yBAAyB,GACpC,SAAS,wBAAwB,EACjC,YAAY,2BAA2B,KACtC,aAUF,CAAC"}
1
+ {"version":3,"file":"text-field.styles.d.ts","sourceRoot":"","sources":["../../../src/text-field/text-field.styles.ts"],"names":[],"mappings":"AAEA,OAAO,EAAO,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,KAAK,EACV,wBAAwB,EACxB,2BAA2B,EAC5B,MAAM,4BAA4B,CAAC;AAEpC,eAAO,MAAM,yBAAyB,GACpC,SAAS,wBAAwB,EACjC,YAAY,2BAA2B,KACtC,aAmEF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"text-field.template.d.ts","sourceRoot":"","sources":["../../../src/text-field/text-field.template.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAEL,yBAAyB,EAEzB,gBAAgB,EAEjB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,EAAE,yBAAyB,CACjE,YAAY,CAAC,SAAS,CAAC,EACvB,gBAAgB,CAgEjB,CAAC"}
1
+ {"version":3,"file":"text-field.template.d.ts","sourceRoot":"","sources":["../../../src/text-field/text-field.template.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAEL,yBAAyB,EAEzB,gBAAgB,EAEjB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,EAAE,yBAAyB,CACjE,YAAY,CAAC,SAAS,CAAC,EACvB,gBAAgB,CA2FjB,CAAC"}
@@ -12,6 +12,14 @@ export class TextField extends FASTTextField {
12
12
  super(...arguments);
13
13
  this.autocomplete = 'off';
14
14
  this.autocapitalize = 'off';
15
+ /**
16
+ * When true, prefix/suffix are not exposed to assistive technology (`aria-hidden` on affixes, and their ids are omitted from the control’s `aria-describedby`).
17
+ * Use only when the unit or symbol is redundant with the visible label or other text.
18
+ * @remarks
19
+ * By default, affix text is **included** for screen readers: stable ids are assigned to the affix nodes and referenced from the input’s `aria-describedby` (merged with any author `aria-describedby`), which announces them as supplementary description after the field name from the label.
20
+ * For cases where the affix should be part of the accessible **name** instead (e.g. currency code read as part of the label), set `hide-affix-from-screen-reader` and wire `aria-labelledby` on the host to reference the label slot and your own elements, or provide a single `aria-label` that includes the full name.
21
+ */
22
+ this.hideAffixFromScreenReader = false;
15
23
  }
16
24
  autocompleteChanged() {
17
25
  if (this.proxy instanceof HTMLInputElement) {
@@ -23,6 +31,37 @@ export class TextField extends FASTTextField {
23
31
  this.proxy.autocapitalize = this.autocapitalize;
24
32
  }
25
33
  }
34
+ /**
35
+ * Merges the host `aria-describedby` with ids of the prefix/suffix nodes when those affixes are exposed to SRs.
36
+ * @internal
37
+ */
38
+ get controlAriaDescribedby() {
39
+ var _a;
40
+ const hostIds = (_a = this.ariaDescribedby) === null || _a === void 0 ? void 0 : _a.trim();
41
+ const parts = [];
42
+ if (hostIds) {
43
+ parts.push(...hostIds.split(/\s+/).filter(Boolean));
44
+ }
45
+ if (!this.hideAffixFromScreenReader) {
46
+ const base = this.id || 'control';
47
+ if (this.prefix) {
48
+ parts.push(`${base}-prefix`);
49
+ }
50
+ if (this.suffix) {
51
+ parts.push(`${base}-suffix`);
52
+ }
53
+ }
54
+ const seen = new Set();
55
+ const deduped = [];
56
+ for (const id of parts) {
57
+ if (!seen.has(id)) {
58
+ seen.add(id);
59
+ deduped.push(id);
60
+ }
61
+ }
62
+ const merged = deduped.join(' ');
63
+ return merged || undefined;
64
+ }
26
65
  }
27
66
  __decorate([
28
67
  attr
@@ -33,6 +72,15 @@ __decorate([
33
72
  __decorate([
34
73
  attr
35
74
  ], TextField.prototype, "step", void 0);
75
+ __decorate([
76
+ attr
77
+ ], TextField.prototype, "prefix", void 0);
78
+ __decorate([
79
+ attr
80
+ ], TextField.prototype, "suffix", void 0);
81
+ __decorate([
82
+ attr({ attribute: 'hide-affix-from-screen-reader', mode: 'boolean' })
83
+ ], TextField.prototype, "hideAffixFromScreenReader", void 0);
36
84
  // explicitly declaring for extensibility
37
85
  export const foundationTextFieldShadowOptions = {
38
86
  mode: 'open',
@@ -4,6 +4,63 @@ import { css } from '@microsoft/fast-element';
4
4
  export const foundationTextFieldStyles = (context, definition) => css `
5
5
  ${fastTextFieldStyles(context, definition)}
6
6
 
7
+ /* Override FAST .root align-items: baseline for this flex child so it still fills the row. */
8
+ .control-field {
9
+ display: flex;
10
+ flex: 1 1 0%;
11
+ min-width: 0;
12
+ align-self: stretch;
13
+ align-items: stretch;
14
+ }
15
+
16
+ .control-field .control {
17
+ flex: 1 1 auto;
18
+ min-width: 0;
19
+ width: auto;
20
+ }
21
+
22
+ .prefix,
23
+ .suffix {
24
+ display: flex;
25
+ align-items: center;
26
+ flex-shrink: 0;
27
+ box-sizing: border-box;
28
+ padding: 0 calc(var(--design-unit) * 2px);
29
+ user-select: none;
30
+ white-space: nowrap;
31
+ background-color: var(--neutral-fill-rest);
32
+ color: var(--neutral-foreground-hint);
33
+ font-size: var(--type-ramp-base-font-size);
34
+ font-family: inherit;
35
+ line-height: 1;
36
+ }
37
+
38
+ .prefix {
39
+ border-right: 1px solid var(--neutral-stroke-divider-rest);
40
+ border-radius: calc(var(--control-corner-radius) * 1px) 0 0
41
+ calc(var(--control-corner-radius) * 1px);
42
+ }
43
+
44
+ .suffix {
45
+ border-left: 1px solid var(--neutral-stroke-divider-rest);
46
+ border-radius: 0 calc(var(--control-corner-radius) * 1px)
47
+ calc(var(--control-corner-radius) * 1px) 0;
48
+ }
49
+
50
+ :host(.has-prefix:not(.has-suffix)) .control-field .control {
51
+ border-radius: 0 calc(var(--control-corner-radius) * 1px)
52
+ calc(var(--control-corner-radius) * 1px) 0;
53
+ }
54
+
55
+ :host(.has-suffix:not(.has-prefix)) .control-field .control {
56
+ border-radius: calc(var(--control-corner-radius) * 1px) 0 0
57
+ calc(var(--control-corner-radius) * 1px);
58
+ }
59
+
60
+ :host(.has-prefix.has-suffix) .control-field .control {
61
+ border-radius: 0;
62
+ }
63
+
7
64
  input {
8
65
  color-scheme: ${activeColorScheme};
9
66
  }
@@ -1,5 +1,6 @@
1
- import { html, ref, slotted } from '@microsoft/fast-element';
1
+ import { html, ref, slotted, when } from '@microsoft/fast-element';
2
2
  import { endSlotTemplate, startSlotTemplate, whitespaceFilter, } from '@microsoft/fast-foundation';
3
+ import { classNames } from '@microsoft/fast-web-utilities';
3
4
  /**
4
5
  * @privateRemarks TODO: Raise PR against FAST
5
6
  * Unfortunately this template is almost a complete duplicate of the original fast version, just with additional
@@ -8,9 +9,7 @@ import { endSlotTemplate, startSlotTemplate, whitespaceFilter, } from '@microsof
8
9
  */
9
10
  export const foundationTextFieldTemplate = (context, definition) => html `
10
11
  <template
11
- class="
12
- ${(x) => (x.readOnly ? 'readonly' : '')}
13
- "
12
+ class="${(x) => classNames(['readonly', x.readOnly], ['has-prefix', !!x.prefix], ['has-suffix', !!x.suffix])}"
14
13
  >
15
14
  <label
16
15
  part="label"
@@ -21,50 +20,72 @@ export const foundationTextFieldTemplate = (context, definition) => html `
21
20
  </label>
22
21
  <div class="root" part="root">
23
22
  ${startSlotTemplate(context, definition)}
24
- <input
25
- name="${(x) => x.name}"
26
- autocomplete="${(x) => x.autocomplete}"
27
- autocapitalize="${(x) => x.autocapitalize}"
28
- id="${(x) => (x.id ? x.id : 'control')}"
29
- class="control"
30
- part="control"
31
- @input="${(x) => x.handleTextInput()}"
32
- @change="${(x) => x.handleChange()}"
33
- step="${(x) => x.step}"
34
- ?autofocus="${(x) => x.autofocus}"
35
- ?disabled="${(x) => x.disabled}"
36
- list="${(x) => x.list}"
37
- maxlength="${(x) => x.maxlength}"
38
- minlength="${(x) => x.minlength}"
39
- pattern="${(x) => x.pattern}"
40
- placeholder="${(x) => x.placeholder}"
41
- ?readonly="${(x) => x.readOnly}"
42
- ?required="${(x) => x.required}"
43
- size="${(x) => x.size}"
44
- ?spellcheck="${(x) => x.spellcheck}"
45
- :value="${(x) => x.value}"
46
- type="${(x) => x.type}"
47
- aria-atomic="${(x) => x.ariaAtomic}"
48
- aria-busy="${(x) => x.ariaBusy}"
49
- aria-controls="${(x) => x.ariaControls}"
50
- aria-current="${(x) => x.ariaCurrent}"
51
- aria-describedby="${(x) => x.ariaDescribedby}"
52
- aria-details="${(x) => x.ariaDetails}"
53
- aria-disabled="${(x) => x.ariaDisabled}"
54
- aria-errormessage="${(x) => x.ariaErrormessage}"
55
- aria-flowto="${(x) => x.ariaFlowto}"
56
- aria-haspopup="${(x) => x.ariaHaspopup}"
57
- aria-hidden="${(x) => x.ariaHidden}"
58
- aria-invalid="${(x) => x.ariaInvalid}"
59
- aria-keyshortcuts="${(x) => x.ariaKeyshortcuts}"
60
- aria-label="${(x) => x.ariaLabel}"
61
- aria-labelledby="${(x) => x.ariaLabelledby}"
62
- aria-live="${(x) => x.ariaLive}"
63
- aria-owns="${(x) => x.ariaOwns}"
64
- aria-relevant="${(x) => x.ariaRelevant}"
65
- aria-roledescription="${(x) => x.ariaRoledescription}"
66
- ${ref('control')}
67
- />
23
+ <div class="control-field">
24
+ ${when((x) => x.prefix, html `
25
+ <span
26
+ class="prefix"
27
+ part="prefix"
28
+ id="${(x) => `${x.id || 'control'}-prefix`}"
29
+ ?aria-hidden="${(x) => x.hideAffixFromScreenReader}"
30
+ >
31
+ ${(x) => x.prefix}
32
+ </span>
33
+ `)}
34
+ <input
35
+ name="${(x) => x.name}"
36
+ autocomplete="${(x) => x.autocomplete}"
37
+ autocapitalize="${(x) => x.autocapitalize}"
38
+ id="${(x) => (x.id ? x.id : 'control')}"
39
+ class="control"
40
+ part="control"
41
+ @input="${(x) => x.handleTextInput()}"
42
+ @change="${(x) => x.handleChange()}"
43
+ step="${(x) => x.step}"
44
+ ?autofocus="${(x) => x.autofocus}"
45
+ ?disabled="${(x) => x.disabled}"
46
+ list="${(x) => x.list}"
47
+ maxlength="${(x) => x.maxlength}"
48
+ minlength="${(x) => x.minlength}"
49
+ pattern="${(x) => x.pattern}"
50
+ placeholder="${(x) => x.placeholder}"
51
+ ?readonly="${(x) => x.readOnly}"
52
+ ?required="${(x) => x.required}"
53
+ size="${(x) => x.size}"
54
+ ?spellcheck="${(x) => x.spellcheck}"
55
+ :value="${(x) => x.value}"
56
+ type="${(x) => x.type}"
57
+ aria-atomic="${(x) => x.ariaAtomic}"
58
+ aria-busy="${(x) => x.ariaBusy}"
59
+ aria-controls="${(x) => x.ariaControls}"
60
+ aria-current="${(x) => x.ariaCurrent}"
61
+ aria-describedby="${(x) => x.controlAriaDescribedby}"
62
+ aria-details="${(x) => x.ariaDetails}"
63
+ aria-disabled="${(x) => x.ariaDisabled}"
64
+ aria-errormessage="${(x) => x.ariaErrormessage}"
65
+ aria-flowto="${(x) => x.ariaFlowto}"
66
+ aria-haspopup="${(x) => x.ariaHaspopup}"
67
+ aria-hidden="${(x) => x.ariaHidden}"
68
+ aria-invalid="${(x) => x.ariaInvalid}"
69
+ aria-keyshortcuts="${(x) => x.ariaKeyshortcuts}"
70
+ aria-label="${(x) => x.ariaLabel}"
71
+ aria-labelledby="${(x) => x.ariaLabelledby}"
72
+ aria-live="${(x) => x.ariaLive}"
73
+ aria-owns="${(x) => x.ariaOwns}"
74
+ aria-relevant="${(x) => x.ariaRelevant}"
75
+ aria-roledescription="${(x) => x.ariaRoledescription}"
76
+ ${ref('control')}
77
+ />
78
+ ${when((x) => x.suffix, html `
79
+ <span
80
+ class="suffix"
81
+ part="suffix"
82
+ id="${(x) => `${x.id || 'control'}-suffix`}"
83
+ ?aria-hidden="${(x) => x.hideAffixFromScreenReader}"
84
+ >
85
+ ${(x) => x.suffix}
86
+ </span>
87
+ `)}
88
+ </div>
68
89
  ${endSlotTemplate(context, definition)}
69
90
  </div>
70
91
  </template>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@genesislcap/foundation-ui",
3
3
  "description": "Genesis Foundation UI",
4
- "version": "14.411.0",
4
+ "version": "14.412.0",
5
5
  "sideEffects": false,
6
6
  "license": "SEE LICENSE IN license.txt",
7
7
  "main": "dist/esm/index.js",
@@ -85,13 +85,13 @@
85
85
  }
86
86
  },
87
87
  "devDependencies": {
88
- "@genesislcap/foundation-testing": "14.411.0",
89
- "@genesislcap/genx": "14.411.0",
90
- "@genesislcap/rollup-builder": "14.411.0",
91
- "@genesislcap/ts-builder": "14.411.0",
92
- "@genesislcap/uvu-playwright-builder": "14.411.0",
93
- "@genesislcap/vite-builder": "14.411.0",
94
- "@genesislcap/webpack-builder": "14.411.0",
88
+ "@genesislcap/foundation-testing": "14.412.0",
89
+ "@genesislcap/genx": "14.412.0",
90
+ "@genesislcap/rollup-builder": "14.412.0",
91
+ "@genesislcap/ts-builder": "14.412.0",
92
+ "@genesislcap/uvu-playwright-builder": "14.412.0",
93
+ "@genesislcap/vite-builder": "14.412.0",
94
+ "@genesislcap/webpack-builder": "14.412.0",
95
95
  "copyfiles": "^2.4.1"
96
96
  },
97
97
  "dependencies": {
@@ -100,16 +100,16 @@
100
100
  "@fortawesome/free-regular-svg-icons": "^6.2.1",
101
101
  "@fortawesome/free-solid-svg-icons": "^6.2.1",
102
102
  "@genesiscommunitysuccess/analyzer-import-alias-plugin": "^5.0.3",
103
- "@genesislcap/expression-builder": "14.411.0",
104
- "@genesislcap/foundation-ai": "14.411.0",
105
- "@genesislcap/foundation-comms": "14.411.0",
106
- "@genesislcap/foundation-criteria": "14.411.0",
107
- "@genesislcap/foundation-errors": "14.411.0",
108
- "@genesislcap/foundation-events": "14.411.0",
109
- "@genesislcap/foundation-logger": "14.411.0",
110
- "@genesislcap/foundation-notifications": "14.411.0",
111
- "@genesislcap/foundation-user": "14.411.0",
112
- "@genesislcap/foundation-utils": "14.411.0",
103
+ "@genesislcap/expression-builder": "14.412.0",
104
+ "@genesislcap/foundation-ai": "14.412.0",
105
+ "@genesislcap/foundation-comms": "14.412.0",
106
+ "@genesislcap/foundation-criteria": "14.412.0",
107
+ "@genesislcap/foundation-errors": "14.412.0",
108
+ "@genesislcap/foundation-events": "14.412.0",
109
+ "@genesislcap/foundation-logger": "14.412.0",
110
+ "@genesislcap/foundation-notifications": "14.412.0",
111
+ "@genesislcap/foundation-user": "14.412.0",
112
+ "@genesislcap/foundation-utils": "14.412.0",
113
113
  "@microsoft/fast-colors": "5.3.1",
114
114
  "@microsoft/fast-components": "2.30.6",
115
115
  "@microsoft/fast-element": "1.14.0",
@@ -131,5 +131,5 @@
131
131
  "access": "public"
132
132
  },
133
133
  "customElements": "dist/custom-elements.json",
134
- "gitHead": "f0f06261f9263da766433fa02f4c011c3391e3c4"
134
+ "gitHead": "b759370097c295bea2a87d6f3a132ec6dba807ca"
135
135
  }