@tylertech/forge 3.1.3 → 3.3.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.
Files changed (68) hide show
  1. package/custom-elements.json +239 -60
  2. package/dist/chips/forge-chips.css +1 -0
  3. package/dist/field/forge-field.css +2 -0
  4. package/dist/inline-message/forge-inline-message.css +2 -0
  5. package/dist/lib.js +1 -1
  6. package/dist/lib.js.map +4 -4
  7. package/dist/vscode.css-custom-data.json +5 -0
  8. package/dist/vscode.html-custom-data.json +22 -2
  9. package/esm/app-bar/app-bar/app-bar.d.ts +2 -0
  10. package/esm/app-bar/app-bar/app-bar.js +2 -0
  11. package/esm/autocomplete/autocomplete-adapter.js +1 -7
  12. package/esm/button/base/base-button-adapter.js +1 -1
  13. package/esm/calendar/calendar-adapter.d.ts +6 -6
  14. package/esm/calendar/calendar-adapter.js +45 -11
  15. package/esm/calendar/calendar-constants.d.ts +20 -0
  16. package/esm/calendar/calendar-constants.js +22 -0
  17. package/esm/calendar/calendar-core.d.ts +3 -3
  18. package/esm/calendar/calendar-core.js +5 -17
  19. package/esm/calendar/calendar-dom-utils.js +10 -4
  20. package/esm/calendar/calendar-dropdown/calendar-dropdown-constants.d.ts +2 -0
  21. package/esm/calendar/calendar.d.ts +9 -0
  22. package/esm/calendar/calendar.js +9 -0
  23. package/esm/chip-field/chip-field.js +1 -1
  24. package/esm/chips/chip/chip-core.js +0 -1
  25. package/esm/chips/chip/chip.d.ts +1 -0
  26. package/esm/chips/chip/chip.js +2 -1
  27. package/esm/circular-progress/circular-progress.js +1 -1
  28. package/esm/date-picker/base/base-date-picker-adapter.d.ts +3 -0
  29. package/esm/date-picker/base/base-date-picker-adapter.js +56 -0
  30. package/esm/date-picker/base/base-date-picker-constants.d.ts +11 -0
  31. package/esm/date-picker/base/base-date-picker-constants.js +2 -1
  32. package/esm/date-picker/base/base-date-picker-core.d.ts +4 -1
  33. package/esm/date-picker/base/base-date-picker-core.js +12 -1
  34. package/esm/date-picker/base/base-date-picker.d.ts +5 -1
  35. package/esm/date-picker/base/base-date-picker.js +8 -0
  36. package/esm/field/field-adapter.d.ts +2 -0
  37. package/esm/field/field-adapter.js +4 -0
  38. package/esm/field/field-core.js +1 -0
  39. package/esm/field/field.js +1 -1
  40. package/esm/inline-message/inline-message.js +1 -1
  41. package/esm/paginator/paginator.js +1 -1
  42. package/esm/select/select/select.js +1 -1
  43. package/esm/skip-link/skip-link-constants.d.ts +2 -0
  44. package/esm/skip-link/skip-link-constants.js +2 -1
  45. package/esm/skip-link/skip-link.d.ts +36 -12
  46. package/esm/skip-link/skip-link.js +55 -12
  47. package/esm/tabs/tab/tab-constants.d.ts +1 -3
  48. package/esm/tabs/tab/tab-constants.js +1 -3
  49. package/esm/tabs/tab/tab.d.ts +1 -1
  50. package/esm/tabs/tab/tab.js +1 -1
  51. package/esm/tabs/tab-bar/tab-bar-core.js +2 -1
  52. package/esm/tabs/tab-bar/tab-bar.d.ts +1 -1
  53. package/esm/tabs/tab-bar/tab-bar.js +1 -1
  54. package/esm/text-field/text-field-adapter.d.ts +8 -4
  55. package/esm/text-field/text-field-adapter.js +9 -4
  56. package/esm/text-field/text-field-constants.d.ts +2 -0
  57. package/esm/text-field/text-field-constants.js +2 -0
  58. package/esm/text-field/text-field-core.d.ts +2 -0
  59. package/esm/text-field/text-field-core.js +10 -3
  60. package/package.json +1 -1
  61. package/sass/chip-field/chip-field.scss +2 -1
  62. package/sass/chips/chip/chip.scss +1 -1
  63. package/sass/circular-progress/_core.scss +2 -2
  64. package/sass/core/styles/tokens/chips/chip/_tokens.scss +1 -0
  65. package/sass/field/_core.scss +1 -0
  66. package/sass/field/field.scss +1 -1
  67. package/sass/field/forge-field.scss +3 -1
  68. package/sass/inline-message/_core.scss +2 -0
@@ -29,7 +29,7 @@ const styles = ':host{position:relative;display:block}:host([hidden]){display:no
29
29
  * @dependency forge-icon-button
30
30
  * @dependency forge-icon
31
31
  *
32
- * @property {boolean} [disabled=false] - The disabled state of the tab bar.
32
+ * @property {boolean} [disabled=false] - Sets the disabled state of all child tabs. If true, any new tabs added to the DOM will be disabled by default. This can be used instead of setting individual tab disabled properties, mixing the two methods of disabling is not supported.
33
33
  * @property {number} [activeTab=null] - The index of the active tab.
34
34
  * @property {boolean} [vertical=false] - Controls whether the tab bar is vertical or horizontal.
35
35
  * @property {boolean} [clustered=false] - Controls whether the tabs stretch the full width of their container or cluster together at their minimum width.
@@ -12,19 +12,22 @@ export interface ITextFieldAdapter extends IBaseFieldAdapter {
12
12
  addRootListener(name: keyof HTMLElementEventMap, listener: EventListener): void;
13
13
  removeRootListener(name: keyof HTMLElementEventMap, listener: EventListener): void;
14
14
  disableInput(disabled: boolean): void;
15
- handleDefaultSlotChange(slot: HTMLSlotElement, listener: TextFieldInputAttributeObserver): void;
15
+ handleDefaultSlotChange(listener: TextFieldInputAttributeObserver): void;
16
16
  tryAddValueChangeListener(context: unknown, listener: TextFieldValueChangeListener): void;
17
17
  removeValueChangeListener(): void;
18
18
  tryFloatLabel(force?: boolean): void;
19
- tryConnectSlottedLabel(slot: HTMLSlotElement): void;
19
+ tryConnectSlottedLabel(): void;
20
20
  connectClearButton(listener: EventListener): void;
21
21
  disconnectClearButton(listener: EventListener): void;
22
22
  toggleClearButtonVisibility(visible: boolean): void;
23
23
  clearInput(): void;
24
+ getAllSlotElements(): HTMLSlotElement[];
24
25
  }
25
26
  export declare class TextFieldAdapter extends BaseFieldAdapter implements ITextFieldAdapter {
26
27
  protected readonly _fieldElement: IFieldComponent;
27
28
  private readonly _clearButtonSlotElement;
29
+ private readonly _defaultSlotElement;
30
+ private readonly _labelSlotElement;
28
31
  private _popoverTargetElement;
29
32
  private _inputElements;
30
33
  private _inputMutationObserver?;
@@ -39,13 +42,14 @@ export declare class TextFieldAdapter extends BaseFieldAdapter implements ITextF
39
42
  inputIsDisabled(): boolean;
40
43
  click(): void;
41
44
  applyLabel(value: string | null): void;
42
- handleDefaultSlotChange(slot: HTMLSlotElement, listener: TextFieldInputAttributeObserver): void;
45
+ handleDefaultSlotChange(listener: TextFieldInputAttributeObserver): void;
43
46
  tryAddValueChangeListener(context: unknown, listener: TextFieldValueChangeListener): void;
44
47
  removeValueChangeListener(): void;
45
48
  tryFloatLabel(force?: boolean): void;
46
- tryConnectSlottedLabel(slot: HTMLSlotElement): void;
49
+ tryConnectSlottedLabel(): void;
47
50
  connectClearButton(listener: EventListener): void;
48
51
  disconnectClearButton(listener: EventListener): void;
49
52
  toggleClearButtonVisibility(visible: boolean): void;
50
53
  clearInput(): void;
54
+ getAllSlotElements(): HTMLSlotElement[];
51
55
  }
@@ -26,6 +26,8 @@ export class TextFieldAdapter extends BaseFieldAdapter {
26
26
  this._destroyValueChangerListeners = [];
27
27
  this._fieldElement = getShadowElement(component, TEXT_FIELD_CONSTANTS.selectors.FIELD);
28
28
  this._clearButtonSlotElement = getShadowElement(component, TEXT_FIELD_CONSTANTS.selectors.CLEAR_BUTTON_SLOT);
29
+ this._defaultSlotElement = getShadowElement(component, TEXT_FIELD_CONSTANTS.selectors.DEFAULT_SLOT);
30
+ this._labelSlotElement = getShadowElement(component, TEXT_FIELD_CONSTANTS.selectors.LABEL_SLOT);
29
31
  this._fieldElement.setAttribute('exportparts', Object.values(FIELD_CONSTANTS.parts).join(', '));
30
32
  this._clearButtonSlotElement.remove();
31
33
  }
@@ -49,11 +51,11 @@ export class TextFieldAdapter extends BaseFieldAdapter {
49
51
  toggleAttribute(inputElement, !!value, 'aria-label', value ?? '');
50
52
  });
51
53
  }
52
- handleDefaultSlotChange(slot, listener) {
54
+ handleDefaultSlotChange(listener) {
53
55
  // Destroy the mutation observer if it exists
54
56
  this._inputMutationObserver?.disconnect();
55
57
  // If there are no assigned elements, return
56
- const assignedElements = slot.assignedElements();
58
+ const assignedElements = this._defaultSlotElement.assignedElements();
57
59
  if (!assignedElements.length) {
58
60
  return;
59
61
  }
@@ -106,14 +108,14 @@ export class TextFieldAdapter extends BaseFieldAdapter {
106
108
  // Float the label if no input has a value or a placeholder
107
109
  this._fieldElement.floatLabel = this.hasValue || this.hasPlaceholder;
108
110
  }
109
- tryConnectSlottedLabel(slot) {
111
+ tryConnectSlottedLabel() {
110
112
  // Only one input can be automatically connected to a label, return if there are no or more
111
113
  // than one inputs or if the input is already labelled
112
114
  if (this._inputElements.length !== 1 || this._inputElements[0].labels?.length) {
113
115
  return;
114
116
  }
115
117
  const inputElement = this._inputElements[0];
116
- const elements = slot.assignedElements({ flatten: true });
118
+ const elements = this._labelSlotElement.assignedElements({ flatten: true });
117
119
  // Attempt to find and connect a `<forge-label>` element
118
120
  const forgeLabel = elements.find(el => el.matches(TEXT_FIELD_CONSTANTS.selectors.FORGE_LABEL));
119
121
  if (forgeLabel) {
@@ -151,4 +153,7 @@ export class TextFieldAdapter extends BaseFieldAdapter {
151
153
  this._inputElements.forEach(el => (el.value = ''));
152
154
  this._inputElements[0].focus();
153
155
  }
156
+ getAllSlotElements() {
157
+ return Array.from(this._component.shadowRoot?.querySelectorAll('slot') ?? []);
158
+ }
154
159
  }
@@ -14,6 +14,8 @@ export declare const TEXT_FIELD_CONSTANTS: {
14
14
  };
15
15
  selectors: {
16
16
  FIELD: string;
17
+ DEFAULT_SLOT: string;
18
+ LABEL_SLOT: string;
17
19
  CLEAR_BUTTON_SLOT: string;
18
20
  FORGE_LABEL: "forge-label";
19
21
  INPUT: string;
@@ -14,6 +14,8 @@ const attributes = {
14
14
  };
15
15
  const selectors = {
16
16
  FIELD: '#field',
17
+ DEFAULT_SLOT: 'slot:not([name])',
18
+ LABEL_SLOT: 'slot[name=label]',
17
19
  CLEAR_BUTTON_SLOT: 'slot[name=clear-button]',
18
20
  FORGE_LABEL: LABEL_CONSTANTS.elementName,
19
21
  INPUT: ':where(input:not([type=button], [type=checkbox], [type=color], [type=hidden], [type=image], [type=radio], [type=range], [type=reset], [type=submit]), textarea)'
@@ -22,7 +22,9 @@ export declare class TextFieldCore extends BaseFieldCore<ITextFieldAdapter> impl
22
22
  initialize(): void;
23
23
  destroy(): void;
24
24
  get popoverTargetElement(): HTMLElement;
25
+ private _initializeSlots;
25
26
  private _onSlotChange;
27
+ private _handleSlotChange;
26
28
  private _onInputAttributeChange;
27
29
  private _onClearButtonClick;
28
30
  private _onValueChange;
@@ -21,6 +21,7 @@ export class TextFieldCore extends BaseFieldCore {
21
21
  this._adapter.tryApplyGlobalConfiguration(['labelPosition', 'variant']);
22
22
  this._adapter.addRootListener('slotchange', this._slotChangeListener);
23
23
  this._adapter.addRootListener('input', this._inputListener);
24
+ this._initializeSlots();
24
25
  }
25
26
  destroy() {
26
27
  this._adapter.removeRootListener('slotchange', this._slotChangeListener);
@@ -30,14 +31,20 @@ export class TextFieldCore extends BaseFieldCore {
30
31
  get popoverTargetElement() {
31
32
  return this._adapter.popoverTargetElement;
32
33
  }
34
+ _initializeSlots() {
35
+ this._adapter.getAllSlotElements().forEach(slot => this._handleSlotChange(slot.name));
36
+ }
33
37
  _onSlotChange(evt) {
34
38
  const target = evt.target;
35
- switch (target.name) {
39
+ this._handleSlotChange(target.name);
40
+ }
41
+ _handleSlotChange(name) {
42
+ switch (name) {
36
43
  case 'label':
37
- this._adapter.tryConnectSlottedLabel(target);
44
+ this._adapter.tryConnectSlottedLabel();
38
45
  break;
39
46
  case '':
40
- this._adapter.handleDefaultSlotChange(target, this._inputAttributeListener);
47
+ this._adapter.handleDefaultSlotChange(this._inputAttributeListener);
41
48
  this._adapter.tryAddValueChangeListener(this, this._valueChangeListener);
42
49
  this._tryFloatLabel();
43
50
  break;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tylertech/forge",
3
3
  "description": "Tyler Forge™ Web Components library",
4
- "version": "3.1.3",
4
+ "version": "3.3.0",
5
5
  "author": "Tyler Technologies, Inc.",
6
6
  "license": "Apache-2.0",
7
7
  "repository": {
@@ -77,7 +77,8 @@ $themes: (primary, secondary, tertiary, success, warning, error, info);
77
77
  @include chip.provide-theme(
78
78
  (
79
79
  field-background: theme.variable($theme),
80
- field-color: theme.variable(on-#{$theme})
80
+ field-color: theme.variable(on-#{$theme}),
81
+ focus-indicator-color: theme.variable($theme)
81
82
  )
82
83
  );
83
84
  }
@@ -64,7 +64,7 @@
64
64
  forge-focus-indicator {
65
65
  @include focus-indicator.provide-theme(
66
66
  (
67
- color: #{token(color)},
67
+ color: #{token(focus-indicator-color)},
68
68
  shape: #{token(shape)}
69
69
  )
70
70
  );
@@ -14,8 +14,8 @@ $_cycle-duration: calc(4 * #{token(arc-duration)});
14
14
  @mixin container {
15
15
  display: inline-flex;
16
16
  vertical-align: middle;
17
- min-block-size: #{token(size)};
18
- min-inline-size: #{token(size)};
17
+ block-size: #{token(size)};
18
+ inline-size: #{token(size)};
19
19
  position: relative;
20
20
  align-items: center;
21
21
  justify-content: center;
@@ -22,6 +22,7 @@ $tokens: (
22
22
  padding-block: utils.module-val(chip, padding-block, 0),
23
23
  cursor: utils.module-val(chip, cursor, pointer),
24
24
  icon-font-size: utils.module-val(chip, icon-font-size, 1.5rem),
25
+ focus-indicator-color: utils.module-ref(chip, focus-indicator-color, color),
25
26
  // Disabled
26
27
  disabled-opacity: utils.module-val(chip, disabled-opacity, theme.emphasis(medium-low)),
27
28
  disabled-cursor: utils.module-val(chip, disabled-cursor, not-allowed),
@@ -83,6 +83,7 @@
83
83
  outline-style: #{token(outline-style)};
84
84
  outline-width: #{token(outline-width)};
85
85
  outline-color: #{token(outline-color, custom)};
86
+ outline-offset: calc(#{token(outline-width)} * -1);
86
87
  pointer-events: none;
87
88
  }
88
89
 
@@ -676,7 +676,7 @@ forge-focus-indicator {
676
676
  @include focus-indicator.provide-theme(
677
677
  (
678
678
  color: #{token(focus-indicator-color, custom)},
679
- outward-offset: 0px,
679
+ outward-offset: calc(#{token(outline-width)} * -1),
680
680
  shape: #{token(shape)},
681
681
  width: #{token(focus-indicator-width)}
682
682
  )
@@ -46,6 +46,7 @@ $_input-selector: ':where(input, textarea, select, .forge-field__input)';
46
46
  outline-style: #{token(outline-style)};
47
47
  outline-width: #{token(outline-width)};
48
48
  outline-color: #{theme.variable(outline-low)};
49
+ outline-offset: calc(#{token(outline-width)} * -1);
49
50
 
50
51
  background: #{token(background)};
51
52
 
@@ -329,7 +330,8 @@ $_input-selector: ':where(input, textarea, select, .forge-field__input)';
329
330
  &.forge-field:has(#{$_input-selector}:focus) {
330
331
  @include focus-indicator.provide-theme(
331
332
  (
332
- color: #{theme.variable(error)}
333
+ color: #{theme.variable(error)},
334
+ outward-offset: calc(#{token(outline-width)} * -1)
333
335
  )
334
336
  );
335
337
  }
@@ -24,6 +24,7 @@
24
24
  border-color: #{token(border-color)};
25
25
 
26
26
  display: flex;
27
+ align-items: center;
27
28
  gap: #{token(icon-gap)};
28
29
  box-sizing: border-box;
29
30
  padding-inline: #{token(padding-inline)};
@@ -42,4 +43,5 @@
42
43
 
43
44
  @mixin icon {
44
45
  color: #{token(icon-color)};
46
+ align-self: start;
45
47
  }