@openproject/primer-view-components 0.80.2 → 0.81.0-rc.0426a0ac2
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/README.md +20 -1
- package/app/assets/javascripts/components/primer/primer.d.ts +1 -0
- package/app/assets/javascripts/lib/primer/forms/character_counter.d.ts +41 -0
- package/app/assets/javascripts/lib/primer/forms/primer_text_area.d.ts +13 -0
- package/app/assets/javascripts/lib/primer/forms/primer_text_field.d.ts +2 -0
- package/app/assets/javascripts/primer_view_components.js +1 -1
- package/app/assets/javascripts/primer_view_components.js.map +1 -1
- package/app/assets/styles/primer_view_components.css +1 -1
- package/app/assets/styles/primer_view_components.css.map +1 -1
- package/app/components/primer/alpha/select_panel_element.js +1 -1
- package/app/components/primer/alpha/tab_nav.css +1 -1
- package/app/components/primer/alpha/tab_nav.css.json +1 -0
- package/app/components/primer/alpha/tool_tip.js +12 -5
- package/app/components/primer/primer.d.ts +1 -0
- package/app/components/primer/primer.js +1 -0
- package/app/lib/primer/forms/character_counter.d.ts +41 -0
- package/app/lib/primer/forms/character_counter.js +114 -0
- package/app/lib/primer/forms/primer_text_area.d.ts +13 -0
- package/app/lib/primer/forms/primer_text_area.js +53 -0
- package/app/lib/primer/forms/primer_text_field.d.ts +2 -0
- package/app/lib/primer/forms/primer_text_field.js +16 -2
- package/package.json +6 -6
- package/static/arguments.json +13 -1
- package/static/form_previews.json +10 -0
- package/static/info_arch.json +106 -15
- package/static/previews.json +93 -14
|
@@ -84,7 +84,7 @@ let SelectPanelElement = class SelectPanelElement extends HTMLElement {
|
|
|
84
84
|
return this.getAttribute('data-select-variant');
|
|
85
85
|
}
|
|
86
86
|
get ariaSelectionType() {
|
|
87
|
-
return
|
|
87
|
+
return 'aria-selected';
|
|
88
88
|
}
|
|
89
89
|
set selectVariant(variant) {
|
|
90
90
|
if (variant) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
.tabnav{border-bottom:var(--borderWidth-thin) solid var(--borderColor-default);margin-bottom:var(--stack-gap-normal);margin-top:0}.tabnav-tabs{display:flex;margin-bottom:calc(var(--borderWidth-thin)*-1);overflow:hidden}.tabnav-tab{background-color:initial;border:var(--borderWidth-thin) solid #0000;border-bottom:0;color:var(--fgColor-muted);display:inline-block;
|
|
1
|
+
.tabnav{border-bottom:var(--borderWidth-thin) solid var(--borderColor-default);margin-bottom:var(--stack-gap-normal);margin-top:0}.tabnav-tabs{display:flex;margin-bottom:calc(var(--borderWidth-thin)*-1);overflow-x:auto;overflow-y:hidden}.tabnav-tab,.tabnav-tabs>li{flex-shrink:0}.tabnav-tab{background-color:initial;border:var(--borderWidth-thin) solid #0000;border-bottom:0;color:var(--fgColor-muted);display:inline-block;font-size:var(--text-body-size-medium);line-height:23px;padding:var(--base-size-8) var(--control-medium-paddingInline-spacious);-webkit-text-decoration:none;text-decoration:none;transition:color .2s cubic-bezier(.3,0,.5,1)}.tabnav-tab.selected,.tabnav-tab[aria-current]:not([aria-current=false]),.tabnav-tab[aria-selected=true]{background-color:var(--bgColor-default);border-color:var(--borderColor-default);border-radius:var(--borderRadius-medium) var(--borderRadius-medium) 0 0;color:var(--fgColor-default)}:is(.tabnav-tab.selected,.tabnav-tab[aria-selected=true],.tabnav-tab[aria-current]:not([aria-current=false])) .octicon{color:inherit}.tabnav-tab:hover{color:var(--fgColor-default);-webkit-text-decoration:none;text-decoration:none;transition-duration:.1s}.tabnav-tab:focus,.tabnav-tab:focus-visible{border-radius:var(--borderRadius-medium) var(--borderRadius-medium) 0 0!important;outline-offset:-6px}.tabnav-tab .octicon,.tabnav-tab:active{color:var(--fgColor-muted)}.tabnav-tab .octicon{margin-right:var(--control-small-gap)}.tabnav-tab .Counter{color:inherit;margin-left:var(--control-small-gap)}.tabnav-extra{color:var(--fgColor-muted);display:inline-block;font-size:var(--text-body-size-small);margin-left:10px;padding-top:10px}.tabnav-extra>.octicon{margin-right:var(--base-size-2)}a.tabnav-extra:hover{color:var(--fgColor-accent);-webkit-text-decoration:none;text-decoration:none}.tabnav-btn{margin-left:var(--controlStack-medium-gap-condensed)}
|
|
@@ -9,7 +9,7 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
|
|
|
9
9
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
10
10
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
11
11
|
};
|
|
12
|
-
var _ToolTipElement_instances, _ToolTipElement_abortController, _ToolTipElement_align, _ToolTipElement_side, _ToolTipElement_allowUpdatePosition, _ToolTipElement_showReason, _ToolTipElement_update, _ToolTipElement_updateControl, _ToolTipElement_updateControlReference, _ToolTipElement_updateDirection, _ToolTipElement_updatePosition;
|
|
12
|
+
var _ToolTipElement_instances, _ToolTipElement_abortController, _ToolTipElement_align, _ToolTipElement_side, _ToolTipElement_allowUpdatePosition, _ToolTipElement_showReason, _ToolTipElement_isControlsPopoverOpen, _ToolTipElement_update, _ToolTipElement_updateControl, _ToolTipElement_updateControlReference, _ToolTipElement_updateDirection, _ToolTipElement_updatePosition;
|
|
13
13
|
import '@oddbird/popover-polyfill';
|
|
14
14
|
import { getAnchoredPosition } from '@primer/behaviors';
|
|
15
15
|
const isPopoverOpen = (() => {
|
|
@@ -78,6 +78,7 @@ class ToolTipElement extends HTMLElement {
|
|
|
78
78
|
_ToolTipElement_side.set(this, 'outside-bottom');
|
|
79
79
|
_ToolTipElement_allowUpdatePosition.set(this, false);
|
|
80
80
|
_ToolTipElement_showReason.set(this, 'mouse');
|
|
81
|
+
_ToolTipElement_isControlsPopoverOpen.set(this, false);
|
|
81
82
|
}
|
|
82
83
|
styles() {
|
|
83
84
|
return `
|
|
@@ -244,18 +245,24 @@ class ToolTipElement extends HTMLElement {
|
|
|
244
245
|
if (!this.control)
|
|
245
246
|
return;
|
|
246
247
|
const showing = isPopoverOpen(this);
|
|
248
|
+
// Track when the control's popover (e.g an ActionMenu) is opened/closed
|
|
249
|
+
if (event.type === 'beforetoggle' && event.currentTarget !== this) {
|
|
250
|
+
__classPrivateFieldSet(this, _ToolTipElement_isControlsPopoverOpen, event.newState === 'open', "f");
|
|
251
|
+
}
|
|
247
252
|
// Ensures that tooltip stays open when hovering between tooltip and element
|
|
248
253
|
// WCAG Success Criterion 1.4.13 Hoverable
|
|
249
|
-
const shouldShow = event.type === 'mouseenter' ||
|
|
254
|
+
const shouldShow = (event.type === 'mouseenter' ||
|
|
250
255
|
// Only show tooltip on focus if running in headless browser (for tests) or if focus ring
|
|
251
256
|
// is visible (i.e. if user is using keyboard navigation)
|
|
252
|
-
(event.type === 'focus' && (navigator.webdriver || this.control.matches(':focus-visible')))
|
|
257
|
+
(event.type === 'focus' && (navigator.webdriver || this.control.matches(':focus-visible')))) &&
|
|
258
|
+
// Don't show tooltip if the control's popover is open (e.g. an ActionMenu)
|
|
259
|
+
!__classPrivateFieldGet(this, _ToolTipElement_isControlsPopoverOpen, "f");
|
|
253
260
|
const isMouseLeaveFromButton = event.type === 'mouseleave' &&
|
|
254
261
|
event.relatedTarget !== this.control &&
|
|
255
262
|
event.relatedTarget !== this;
|
|
256
263
|
const isEscapeKeydown = event.type === 'keydown' && event.key === 'Escape';
|
|
257
264
|
const isMouseDownOnButton = event.type === 'mousedown' && event.currentTarget === this.control;
|
|
258
|
-
const isOpeningOtherPopover = event.type === 'beforetoggle' && event.currentTarget !== this;
|
|
265
|
+
const isOpeningOtherPopover = event.type === 'beforetoggle' && event.currentTarget !== this && event.newState === 'open';
|
|
259
266
|
const shouldHide = isMouseLeaveFromButton || isEscapeKeydown || isMouseDownOnButton || isOpeningOtherPopover;
|
|
260
267
|
if (showing && isEscapeKeydown) {
|
|
261
268
|
/* eslint-disable-next-line no-restricted-syntax */
|
|
@@ -288,7 +295,7 @@ class ToolTipElement extends HTMLElement {
|
|
|
288
295
|
}
|
|
289
296
|
}
|
|
290
297
|
}
|
|
291
|
-
_ToolTipElement_abortController = new WeakMap(), _ToolTipElement_align = new WeakMap(), _ToolTipElement_side = new WeakMap(), _ToolTipElement_allowUpdatePosition = new WeakMap(), _ToolTipElement_showReason = new WeakMap(), _ToolTipElement_instances = new WeakSet(), _ToolTipElement_update = function _ToolTipElement_update(isOpen) {
|
|
298
|
+
_ToolTipElement_abortController = new WeakMap(), _ToolTipElement_align = new WeakMap(), _ToolTipElement_side = new WeakMap(), _ToolTipElement_allowUpdatePosition = new WeakMap(), _ToolTipElement_showReason = new WeakMap(), _ToolTipElement_isControlsPopoverOpen = new WeakMap(), _ToolTipElement_instances = new WeakSet(), _ToolTipElement_update = function _ToolTipElement_update(isOpen) {
|
|
292
299
|
if (isOpen) {
|
|
293
300
|
openTooltips.add(this);
|
|
294
301
|
this.classList.remove(TOOLTIP_SR_ONLY_CLASS);
|
|
@@ -22,6 +22,7 @@ import './beta/relative_time';
|
|
|
22
22
|
import './alpha/tab_container';
|
|
23
23
|
import '../../lib/primer/forms/primer_multi_input';
|
|
24
24
|
import '../../lib/primer/forms/primer_text_field';
|
|
25
|
+
import '../../lib/primer/forms/primer_text_area';
|
|
25
26
|
import '../../lib/primer/forms/toggle_switch_input';
|
|
26
27
|
import './alpha/action_menu/action_menu_element';
|
|
27
28
|
import './alpha/select_panel_element';
|
|
@@ -22,6 +22,7 @@ import './beta/relative_time';
|
|
|
22
22
|
import './alpha/tab_container';
|
|
23
23
|
import '../../lib/primer/forms/primer_multi_input';
|
|
24
24
|
import '../../lib/primer/forms/primer_text_field';
|
|
25
|
+
import '../../lib/primer/forms/primer_text_area';
|
|
25
26
|
import '../../lib/primer/forms/toggle_switch_input';
|
|
26
27
|
import './alpha/action_menu/action_menu_element';
|
|
27
28
|
import './alpha/select_panel_element';
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared character counting functionality for text inputs with character limits.
|
|
3
|
+
* Handles real-time character count updates, validation, and aria-live announcements.
|
|
4
|
+
*/
|
|
5
|
+
export declare class CharacterCounter {
|
|
6
|
+
private inputElement;
|
|
7
|
+
private characterLimitElement;
|
|
8
|
+
private characterLimitSrElement;
|
|
9
|
+
private SCREEN_READER_DELAY;
|
|
10
|
+
private announceTimeout;
|
|
11
|
+
private isInitialLoad;
|
|
12
|
+
constructor(inputElement: HTMLInputElement | HTMLTextAreaElement, characterLimitElement: HTMLElement, characterLimitSrElement: HTMLElement);
|
|
13
|
+
/**
|
|
14
|
+
* Initialize character counting by setting up event listener and initial count
|
|
15
|
+
*/
|
|
16
|
+
initialize(signal?: AbortSignal): void;
|
|
17
|
+
/**
|
|
18
|
+
* Clean up any pending timeouts
|
|
19
|
+
*/
|
|
20
|
+
cleanup(): void;
|
|
21
|
+
/**
|
|
22
|
+
* Pluralizes a word based on the count
|
|
23
|
+
*/
|
|
24
|
+
private pluralize;
|
|
25
|
+
/**
|
|
26
|
+
* Update the character count display and validation state
|
|
27
|
+
*/
|
|
28
|
+
private updateCharacterCount;
|
|
29
|
+
/**
|
|
30
|
+
* Announce character count to screen readers with debouncing
|
|
31
|
+
*/
|
|
32
|
+
private announceToScreenReader;
|
|
33
|
+
/**
|
|
34
|
+
* Set error when character limit is exceeded
|
|
35
|
+
*/
|
|
36
|
+
private setError;
|
|
37
|
+
/**
|
|
38
|
+
* Clear error when back under character limit
|
|
39
|
+
*/
|
|
40
|
+
private clearError;
|
|
41
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared character counting functionality for text inputs with character limits.
|
|
3
|
+
* Handles real-time character count updates, validation, and aria-live announcements.
|
|
4
|
+
*/
|
|
5
|
+
export class CharacterCounter {
|
|
6
|
+
constructor(inputElement, characterLimitElement, characterLimitSrElement) {
|
|
7
|
+
this.inputElement = inputElement;
|
|
8
|
+
this.characterLimitElement = characterLimitElement;
|
|
9
|
+
this.characterLimitSrElement = characterLimitSrElement;
|
|
10
|
+
this.SCREEN_READER_DELAY = 500;
|
|
11
|
+
this.announceTimeout = null;
|
|
12
|
+
this.isInitialLoad = true;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Initialize character counting by setting up event listener and initial count
|
|
16
|
+
*/
|
|
17
|
+
initialize(signal) {
|
|
18
|
+
this.inputElement.addEventListener('keyup', () => this.updateCharacterCount(), signal ? { signal } : undefined); // Keyup used over input for better screen reader support
|
|
19
|
+
this.inputElement.addEventListener('paste', () => setTimeout(() => this.updateCharacterCount(), 50), // Gives the pasted content time to register
|
|
20
|
+
signal ? { signal } : undefined);
|
|
21
|
+
this.updateCharacterCount();
|
|
22
|
+
this.isInitialLoad = false;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Clean up any pending timeouts
|
|
26
|
+
*/
|
|
27
|
+
cleanup() {
|
|
28
|
+
if (this.announceTimeout) {
|
|
29
|
+
clearTimeout(this.announceTimeout);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Pluralizes a word based on the count
|
|
34
|
+
*/
|
|
35
|
+
pluralize(count, string) {
|
|
36
|
+
return count === 1 ? string : `${string}s`;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Update the character count display and validation state
|
|
40
|
+
*/
|
|
41
|
+
updateCharacterCount() {
|
|
42
|
+
if (!this.characterLimitElement)
|
|
43
|
+
return;
|
|
44
|
+
const maxLengthAttr = this.characterLimitElement.getAttribute('data-max-length');
|
|
45
|
+
if (!maxLengthAttr)
|
|
46
|
+
return;
|
|
47
|
+
const maxLength = parseInt(maxLengthAttr, 10);
|
|
48
|
+
const currentLength = this.inputElement.value.length;
|
|
49
|
+
const charactersRemaining = maxLength - currentLength;
|
|
50
|
+
let message = '';
|
|
51
|
+
if (charactersRemaining >= 0) {
|
|
52
|
+
const characterText = this.pluralize(charactersRemaining, 'character');
|
|
53
|
+
message = `${charactersRemaining} ${characterText} remaining`;
|
|
54
|
+
const textSpan = this.characterLimitElement.querySelector('.FormControl-caption-text');
|
|
55
|
+
if (textSpan) {
|
|
56
|
+
textSpan.textContent = message;
|
|
57
|
+
}
|
|
58
|
+
this.clearError();
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
const charactersOver = -charactersRemaining;
|
|
62
|
+
const characterText = this.pluralize(charactersOver, 'character');
|
|
63
|
+
message = `${charactersOver} ${characterText} over`;
|
|
64
|
+
const textSpan = this.characterLimitElement.querySelector('.FormControl-caption-text');
|
|
65
|
+
if (textSpan) {
|
|
66
|
+
textSpan.textContent = message;
|
|
67
|
+
}
|
|
68
|
+
this.setError();
|
|
69
|
+
}
|
|
70
|
+
// We don't want this announced on initial load
|
|
71
|
+
if (!this.isInitialLoad) {
|
|
72
|
+
this.announceToScreenReader(message);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Announce character count to screen readers with debouncing
|
|
77
|
+
*/
|
|
78
|
+
announceToScreenReader(message) {
|
|
79
|
+
if (this.announceTimeout) {
|
|
80
|
+
clearTimeout(this.announceTimeout);
|
|
81
|
+
}
|
|
82
|
+
this.announceTimeout = window.setTimeout(() => {
|
|
83
|
+
if (this.characterLimitSrElement) {
|
|
84
|
+
this.characterLimitSrElement.textContent = message;
|
|
85
|
+
}
|
|
86
|
+
}, this.SCREEN_READER_DELAY);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Set error when character limit is exceeded
|
|
90
|
+
*/
|
|
91
|
+
setError() {
|
|
92
|
+
this.inputElement.setAttribute('invalid', 'true');
|
|
93
|
+
this.inputElement.setAttribute('aria-invalid', 'true');
|
|
94
|
+
this.characterLimitElement.classList.add('fgColor-danger');
|
|
95
|
+
// Show danger icon
|
|
96
|
+
const icon = this.characterLimitElement.querySelector('.FormControl-caption-icon');
|
|
97
|
+
if (icon) {
|
|
98
|
+
icon.removeAttribute('hidden');
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Clear error when back under character limit
|
|
103
|
+
*/
|
|
104
|
+
clearError() {
|
|
105
|
+
this.inputElement.removeAttribute('invalid');
|
|
106
|
+
this.inputElement.removeAttribute('aria-invalid');
|
|
107
|
+
this.characterLimitElement.classList.remove('fgColor-danger');
|
|
108
|
+
// Hide danger icon
|
|
109
|
+
const icon = this.characterLimitElement.querySelector('.FormControl-caption-icon');
|
|
110
|
+
if (icon) {
|
|
111
|
+
icon.setAttribute('hidden', '');
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare class PrimerTextAreaElement extends HTMLElement {
|
|
2
|
+
#private;
|
|
3
|
+
inputElement: HTMLTextAreaElement;
|
|
4
|
+
characterLimitElement: HTMLElement;
|
|
5
|
+
characterLimitSrElement: HTMLElement;
|
|
6
|
+
connectedCallback(): void;
|
|
7
|
+
disconnectedCallback(): void;
|
|
8
|
+
}
|
|
9
|
+
declare global {
|
|
10
|
+
interface Window {
|
|
11
|
+
PrimerTextAreaElement: typeof PrimerTextAreaElement;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
8
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
9
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
10
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
11
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
12
|
+
};
|
|
13
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
14
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
15
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
16
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
17
|
+
};
|
|
18
|
+
var _PrimerTextAreaElement_characterCounter;
|
|
19
|
+
import { controller, target } from '@github/catalyst';
|
|
20
|
+
import { CharacterCounter } from './character_counter';
|
|
21
|
+
let PrimerTextAreaElement = class PrimerTextAreaElement extends HTMLElement {
|
|
22
|
+
constructor() {
|
|
23
|
+
super(...arguments);
|
|
24
|
+
_PrimerTextAreaElement_characterCounter.set(this, null);
|
|
25
|
+
}
|
|
26
|
+
connectedCallback() {
|
|
27
|
+
if (this.characterLimitElement) {
|
|
28
|
+
__classPrivateFieldSet(this, _PrimerTextAreaElement_characterCounter, new CharacterCounter(this.inputElement, this.characterLimitElement, this.characterLimitSrElement), "f");
|
|
29
|
+
__classPrivateFieldGet(this, _PrimerTextAreaElement_characterCounter, "f").initialize();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
disconnectedCallback() {
|
|
33
|
+
__classPrivateFieldGet(this, _PrimerTextAreaElement_characterCounter, "f")?.cleanup();
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
_PrimerTextAreaElement_characterCounter = new WeakMap();
|
|
37
|
+
__decorate([
|
|
38
|
+
target
|
|
39
|
+
], PrimerTextAreaElement.prototype, "inputElement", void 0);
|
|
40
|
+
__decorate([
|
|
41
|
+
target
|
|
42
|
+
], PrimerTextAreaElement.prototype, "characterLimitElement", void 0);
|
|
43
|
+
__decorate([
|
|
44
|
+
target
|
|
45
|
+
], PrimerTextAreaElement.prototype, "characterLimitSrElement", void 0);
|
|
46
|
+
PrimerTextAreaElement = __decorate([
|
|
47
|
+
controller
|
|
48
|
+
], PrimerTextAreaElement);
|
|
49
|
+
export { PrimerTextAreaElement };
|
|
50
|
+
if (!window.customElements.get('primer-text-area')) {
|
|
51
|
+
Object.assign(window, { PrimerTextAreaElement });
|
|
52
|
+
window.customElements.define('primer-text-area', PrimerTextAreaElement);
|
|
53
|
+
}
|
|
@@ -15,6 +15,8 @@ export declare class PrimerTextFieldElement extends HTMLElement {
|
|
|
15
15
|
validationErrorIcon: HTMLElement;
|
|
16
16
|
leadingVisual: HTMLElement;
|
|
17
17
|
leadingSpinner: HTMLElement;
|
|
18
|
+
characterLimitElement: HTMLElement;
|
|
19
|
+
characterLimitSrElement: HTMLElement;
|
|
18
20
|
connectedCallback(): void;
|
|
19
21
|
disconnectedCallback(): void;
|
|
20
22
|
clearContents(): void;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable custom-elements/expose-class-on-global */
|
|
2
1
|
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
2
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
3
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -16,13 +15,15 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
|
|
|
16
15
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
17
16
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
18
17
|
};
|
|
19
|
-
var _PrimerTextFieldElement_abortController;
|
|
18
|
+
var _PrimerTextFieldElement_abortController, _PrimerTextFieldElement_characterCounter;
|
|
20
19
|
import '@github/auto-check-element';
|
|
21
20
|
import { controller, target } from '@github/catalyst';
|
|
21
|
+
import { CharacterCounter } from './character_counter';
|
|
22
22
|
let PrimerTextFieldElement = class PrimerTextFieldElement extends HTMLElement {
|
|
23
23
|
constructor() {
|
|
24
24
|
super(...arguments);
|
|
25
25
|
_PrimerTextFieldElement_abortController.set(this, void 0);
|
|
26
|
+
_PrimerTextFieldElement_characterCounter.set(this, null);
|
|
26
27
|
}
|
|
27
28
|
connectedCallback() {
|
|
28
29
|
__classPrivateFieldGet(this, _PrimerTextFieldElement_abortController, "f")?.abort();
|
|
@@ -40,9 +41,15 @@ let PrimerTextFieldElement = class PrimerTextFieldElement extends HTMLElement {
|
|
|
40
41
|
const errorMessage = await event.detail.response.text();
|
|
41
42
|
this.setError(errorMessage);
|
|
42
43
|
}, { signal });
|
|
44
|
+
// Set up character limit tracking if present
|
|
45
|
+
if (this.characterLimitElement) {
|
|
46
|
+
__classPrivateFieldSet(this, _PrimerTextFieldElement_characterCounter, new CharacterCounter(this.inputElement, this.characterLimitElement, this.characterLimitSrElement), "f");
|
|
47
|
+
__classPrivateFieldGet(this, _PrimerTextFieldElement_characterCounter, "f").initialize(signal);
|
|
48
|
+
}
|
|
43
49
|
}
|
|
44
50
|
disconnectedCallback() {
|
|
45
51
|
__classPrivateFieldGet(this, _PrimerTextFieldElement_abortController, "f")?.abort();
|
|
52
|
+
__classPrivateFieldGet(this, _PrimerTextFieldElement_characterCounter, "f")?.cleanup();
|
|
46
53
|
}
|
|
47
54
|
clearContents() {
|
|
48
55
|
this.inputElement.value = '';
|
|
@@ -92,6 +99,7 @@ let PrimerTextFieldElement = class PrimerTextFieldElement extends HTMLElement {
|
|
|
92
99
|
}
|
|
93
100
|
};
|
|
94
101
|
_PrimerTextFieldElement_abortController = new WeakMap();
|
|
102
|
+
_PrimerTextFieldElement_characterCounter = new WeakMap();
|
|
95
103
|
__decorate([
|
|
96
104
|
target
|
|
97
105
|
], PrimerTextFieldElement.prototype, "inputElement", void 0);
|
|
@@ -113,6 +121,12 @@ __decorate([
|
|
|
113
121
|
__decorate([
|
|
114
122
|
target
|
|
115
123
|
], PrimerTextFieldElement.prototype, "leadingSpinner", void 0);
|
|
124
|
+
__decorate([
|
|
125
|
+
target
|
|
126
|
+
], PrimerTextFieldElement.prototype, "characterLimitElement", void 0);
|
|
127
|
+
__decorate([
|
|
128
|
+
target
|
|
129
|
+
], PrimerTextFieldElement.prototype, "characterLimitSrElement", void 0);
|
|
116
130
|
PrimerTextFieldElement = __decorate([
|
|
117
131
|
controller
|
|
118
132
|
], PrimerTextFieldElement);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openproject/primer-view-components",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.81.0-rc.0426a0ac2",
|
|
4
4
|
"description": "ViewComponents of the Primer Design System for OpenProject",
|
|
5
5
|
"main": "app/assets/javascripts/primer_view_components.js",
|
|
6
6
|
"module": "app/components/primer/primer.js",
|
|
@@ -63,12 +63,12 @@
|
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"@changesets/changelog-github": "^0.5.0",
|
|
65
65
|
"@changesets/cli": "^2.24.1",
|
|
66
|
-
"@github/axe-github": "^0.
|
|
66
|
+
"@github/axe-github": "^0.8.1",
|
|
67
67
|
"@github/browserslist-config": "^1.0.0",
|
|
68
68
|
"@github/markdownlint-github": "^0.8.0",
|
|
69
69
|
"@github/prettier-config": "0.0.6",
|
|
70
|
-
"@playwright/test": "^1.
|
|
71
|
-
"@primer/css": "22.0
|
|
70
|
+
"@playwright/test": "^1.57.0",
|
|
71
|
+
"@primer/css": "22.1.0",
|
|
72
72
|
"@primer/stylelint-config": "^13.1.1",
|
|
73
73
|
"@rollup/plugin-node-resolve": "^16.0.1",
|
|
74
74
|
"@rollup/plugin-typescript": "^8.3.3",
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
"glob": "^11.0.2",
|
|
81
81
|
"markdownlint-cli2": "^0.19.1",
|
|
82
82
|
"mocha": "^11.0.1",
|
|
83
|
-
"playwright": "^1.
|
|
83
|
+
"playwright": "^1.57.0",
|
|
84
84
|
"postcss": "^8.4.16",
|
|
85
85
|
"postcss-cli": "^11.0.0",
|
|
86
86
|
"postcss-import": "^16.0.0",
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
"stylelint-actions-formatters": "^16.3.1",
|
|
93
93
|
"tslib": "^2.4.0",
|
|
94
94
|
"typescript": "^5.2.2",
|
|
95
|
-
"vite": "^
|
|
95
|
+
"vite": "^7.3.0",
|
|
96
96
|
"vite-plugin-ruby": "^5.1.0"
|
|
97
97
|
},
|
|
98
98
|
"prettier": "@github/prettier-config",
|
package/static/arguments.json
CHANGED
|
@@ -2721,7 +2721,7 @@
|
|
|
2721
2721
|
"name": "gap",
|
|
2722
2722
|
"type": "Symbol",
|
|
2723
2723
|
"default": "`GapArg::DEFAULT`",
|
|
2724
|
-
"description": "Specify the gap between children elements in the stack. One of `nil`, `:condensed`, `:normal`, or `:spacious`."
|
|
2724
|
+
"description": "Specify the gap between children elements in the stack. One of `nil`, `:condensed`, `:none`, `:normal`, or `:spacious`."
|
|
2725
2725
|
},
|
|
2726
2726
|
{
|
|
2727
2727
|
"name": "direction",
|
|
@@ -2951,6 +2951,12 @@
|
|
|
2951
2951
|
"default": "N/A",
|
|
2952
2952
|
"description": "When set to `true`, the field will take up all the horizontal space allowed by its container. Defaults to `true`."
|
|
2953
2953
|
},
|
|
2954
|
+
{
|
|
2955
|
+
"name": "character_limit",
|
|
2956
|
+
"type": "Number",
|
|
2957
|
+
"default": "N/A",
|
|
2958
|
+
"description": "Optional character limit for the input. If provided, a character counter will be displayed below the input."
|
|
2959
|
+
},
|
|
2954
2960
|
{
|
|
2955
2961
|
"name": "name",
|
|
2956
2962
|
"type": "String",
|
|
@@ -3087,6 +3093,12 @@
|
|
|
3087
3093
|
"default": "N/A",
|
|
3088
3094
|
"description": "When set to `true`, the field will take up all the horizontal space allowed by its container. Defaults to `true`."
|
|
3089
3095
|
},
|
|
3096
|
+
{
|
|
3097
|
+
"name": "character_limit",
|
|
3098
|
+
"type": "Number",
|
|
3099
|
+
"default": "N/A",
|
|
3100
|
+
"description": "Optional character limit for the input. If provided, a character counter will be displayed below the input."
|
|
3101
|
+
},
|
|
3090
3102
|
{
|
|
3091
3103
|
"name": "name",
|
|
3092
3104
|
"type": "String",
|
|
@@ -117,6 +117,16 @@
|
|
|
117
117
|
"preview_path": "primer/forms/auto_complete_form",
|
|
118
118
|
"name": "auto_complete_form",
|
|
119
119
|
"snapshot": "true"
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"preview_path": "primer/forms/text_area_with_character_limit_form",
|
|
123
|
+
"name": "text_area_with_character_limit_form",
|
|
124
|
+
"snapshot": "true"
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"preview_path": "primer/forms/text_field_with_character_limit_form",
|
|
128
|
+
"name": "text_field_with_character_limit_form",
|
|
129
|
+
"snapshot": "true"
|
|
120
130
|
}
|
|
121
131
|
]
|
|
122
132
|
}
|