@tylertech/forge 3.14.0-dev.5 → 3.14.1

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.
@@ -0,0 +1,331 @@
1
+ /**
2
+ * @license
3
+ * Copyright Tyler Technologies, Inc.
4
+ * License: Apache-2.0
5
+ */
6
+
7
+ import { __decorate } from 'tslib';
8
+ import { CUSTOM_ELEMENT_NAME_PROPERTY, CUSTOM_ELEMENT_DEPENDENCIES_PROPERTY, LiveAnnouncer } from '@tylertech/forge-core';
9
+ import { tylIconEyeOutline, tylIconEyeClosed } from '@tylertech/tyler-icons';
10
+ import { unsafeCSS, html, nothing } from 'lit';
11
+ import { property, query, queryAssignedNodes, state, customElement } from 'lit/decorators.js';
12
+ import { classMap } from 'lit/directives/class-map.js';
13
+ import { createRef, ref } from 'lit/directives/ref.js';
14
+ import { BaseLitElement } from '../core/base/base-lit-element.js';
15
+ import { setDefaultAria } from '../core/utils/a11y-utils.js';
16
+ import { toggleState } from '../core/utils/utils.js';
17
+ import '../icon-button/index.js';
18
+ import '../icon/index.js';
19
+ import '../tooltip/index.js';
20
+ import '../button/index.js';
21
+ import { ButtonComponent } from '../button/button.js';
22
+ import { IconButtonComponent } from '../icon-button/icon-button.js';
23
+ import { TooltipComponent } from '../tooltip/tooltip.js';
24
+ import styles from './secret.scss.js';
25
+ import { IconRegistry } from '../icon/icon-registry.js';
26
+ import { IconComponent } from '../icon/icon.js';
27
+
28
+ var _a, _b;
29
+ const SECRET_TAG_NAME = 'forge-secret';
30
+ /**
31
+ * @tag forge-secret
32
+ *
33
+ * @summary A component that conceals content with a blur or dot mask, revealing it on user interaction.
34
+ *
35
+ * @description
36
+ * The secret component blurs or masks content and provides a connected button to reveal it.
37
+ * Content is revealed on click/keyboard interaction, with optional hover reveal. Multiple instances
38
+ * sharing a name act as a radio group where only one can be revealed at a time.
39
+ *
40
+ * @cssproperty --forge-secret-blur - The radius of the blur effect.
41
+ * @cssproperty --forge-secret-button-background - The background color of the button.
42
+ * @cssproperty --forge-secret-button-color - The text and icon color of the button.
43
+ * @cssproperty --forge-secret-button-shape - The button's border radius.
44
+ * @cssproperty --forge-secret-button-padding - The inline padding around the button or inline and block padding around the text button.
45
+ * @cssproperty --forge-secret-icon-size - The icon's size.
46
+ * @cssproperty --forge-secret-text-button-shape - The text button's border radius.
47
+ * @cssproperty --forge-secret-text-decoration-line - The decoration line applied to open inline content.
48
+ * @cssproperty --forge-secret-text-decoration-style - The style of the text decoration line.
49
+ * @cssproperty --forge-secret-text-decoration-color - The color of the text decoration line.
50
+ * @cssproperty --forge-secret-text-underline-offset - The spacing between the inline content and the text decoration line.
51
+ * @cssproperty --forge-secret-transition-duration - The duration of transitions.
52
+ * @cssproperty --forge-secret-transition-easing - The timing function of transitions.
53
+ *
54
+ * @slot - Default slot for the secret content.
55
+ * @slot close-icon - An icon that is shown when the secret is open, indicating it can be closed.
56
+ * @slot open-icon - An icon that is shown when the secret is closed, indicating it can be opened.
57
+ * @slot label - Text content that appears in the tooltip attached to the button or as the button text when set to block.
58
+ *
59
+ * @state open - Indicates that the content is visible.
60
+ * @state block - Indicates that the secret is displayed as a block element instead of inline.
61
+ *
62
+ * @csspart root - The root container.
63
+ * @csspart content - The content container.
64
+ * @csspart button - The toggle button element.
65
+ * @csspart text-button - The toggle button element when the secret is set to block.
66
+ *
67
+ * @cssclass forge-secret - The secret component container (required).
68
+ * @cssclass forge-secret--blur - Applies a blur effect to conceal content when the button has `aria-expanded="false"`.
69
+ * @cssclass forge-secret--masked - Applies a dot mask to conceal content when the button has `aria-expanded="false"`. Not applicable when the secret is set to block. In that case the blur variant is used instead.
70
+ * @cssclass forge-secret--noise - Applies a noise effect to conceal content when the button has `aria-expanded="false"`.
71
+ * @cssclass forge-secret--block - Displays the secret as a block element.
72
+ * @cssclass forge-secret--show-on-hover - Reveals the secret content when hovering over the component or focusing the button.
73
+ * @cssclass forge-secret__content - The content to be concealed or revealed.
74
+ * @cssclass forge-secret__button - The icon button used to toggle an inline secret.
75
+ * @cssclass forge-secret__text-button - The text button used to toggle a block secret.
76
+ * @cssclass forge-secret__masked - The element replacing concealed content when the masked variant is used. The `data-mask` attribute on this element sets its content.
77
+ *
78
+ * @fires {ToggleEvent} toggle - Dispatched when the secret opens or closes.
79
+ */
80
+ let SecretComponent = class SecretComponent extends BaseLitElement {
81
+ static { _a = CUSTOM_ELEMENT_NAME_PROPERTY, _b = CUSTOM_ELEMENT_DEPENDENCIES_PROPERTY; }
82
+ static {
83
+ IconRegistry.define([tylIconEyeOutline, tylIconEyeClosed]);
84
+ }
85
+ static { this.styles = unsafeCSS(styles); }
86
+ /** @deprecated Used for compatibility with legacy Forge @customElement decorator. */
87
+ static { this[_a] = SECRET_TAG_NAME; }
88
+ /** @deprecated Used for compatibility with legacy Forge @customElement decorator. */
89
+ static { this[_b] = [ButtonComponent, IconButtonComponent, IconComponent, TooltipComponent]; }
90
+ #toggleTextRef;
91
+ #internals;
92
+ constructor() {
93
+ super();
94
+ /**
95
+ * Whether the secret content is visible.
96
+ * @attribute
97
+ * @default false
98
+ */
99
+ this.open = false;
100
+ /**
101
+ * The style applied to hidden content when the secret is set to inline. Possible values are blur, masked, and noise.
102
+ * @attribute
103
+ * @default 'blur'
104
+ */
105
+ this.variant = 'blur';
106
+ /**
107
+ * The mask pattern to use with the masked variant. When empty the slotted text content is used as the mask.
108
+ * @attribute
109
+ * @default ''
110
+ */
111
+ this.mask = '';
112
+ /**
113
+ * The character to replace characters with in the masked variant.
114
+ * @attribute mask-character
115
+ * @default '●'
116
+ */
117
+ this.maskCharacter = '●';
118
+ /**
119
+ * Characters that will not be replaced by the mask character in the masked variant.
120
+ * @attribute unmasked-characters
121
+ * @default ''
122
+ */
123
+ this.unmaskedCharacters = '';
124
+ /**
125
+ * Whether the secret content should be displayed as a block element instead of inline with text.
126
+ * @attribute
127
+ * @default false
128
+ */
129
+ this.block = false;
130
+ /**
131
+ * The position of the button when the secret is set to inline. Possible values are start and end.
132
+ * @attribute button-position
133
+ * @default 'end'
134
+ */
135
+ this.buttonPosition = 'end';
136
+ /**
137
+ * Whether to reveal content on hover/focus in addition to clicks.
138
+ * @attribute show-on-hover
139
+ * @default false
140
+ */
141
+ this.showOnHover = false;
142
+ /**
143
+ * When set, secrets with the same name will close when another secret with that name is opened.
144
+ * @attribute
145
+ * @default ''
146
+ */
147
+ this.name = '';
148
+ this._mask = '';
149
+ this.#toggleTextRef = createRef();
150
+ this.#internals = this.attachInternals();
151
+ }
152
+ firstUpdated() {
153
+ setDefaultAria(this, this.#internals, { role: 'group', ariaLabel: 'secret' });
154
+ }
155
+ willUpdate(changedProperties) {
156
+ if (changedProperties.has('block')) {
157
+ toggleState(this.#internals, 'block', this.block);
158
+ }
159
+ if (changedProperties.has('open')) {
160
+ toggleState(this.#internals, 'open', this.open);
161
+ if (this.open && this.name) {
162
+ this.#hideOtherSecretsInGroup();
163
+ }
164
+ }
165
+ }
166
+ updated(changedProperties) {
167
+ this.#tryUpdateInternalMask(changedProperties);
168
+ if (changedProperties.has('open') && this.open) {
169
+ this.#announceContent();
170
+ }
171
+ }
172
+ render() {
173
+ return html `
174
+ <span
175
+ part="root"
176
+ class=${classMap({ 'forge-secret': true, reverse: this.buttonPosition === 'start', 'show-on-hover': this.showOnHover })}
177
+ @click="${this.#handleClick}">
178
+ <span
179
+ class=${classMap({
180
+ content: true,
181
+ blur: !this.open && (this.variant === 'blur' || (this.block && this.variant === 'masked')),
182
+ masked: !this.open && !this.block && this.variant === 'masked',
183
+ noise: !this.open && this.variant === 'noise'
184
+ })}
185
+ part="content"
186
+ ?inert=${!this.open}
187
+ data-mask=${this._mask || nothing}>
188
+ <slot></slot>
189
+ </span>
190
+ ${this.block ? this.#renderTextButton() : this.#renderIconButton()}
191
+ </span>
192
+ `;
193
+ }
194
+ #renderTextButton() {
195
+ return html `
196
+ <forge-button
197
+ class="text-button"
198
+ exportparts="text-button"
199
+ aria-expanded="${this.open}"
200
+ .ariaControlsElements=${[this]}
201
+ @keydown="${this.#handleKeyDown}">
202
+ ${this.#renderIcon()}
203
+ <slot name="label">${this.open ? 'Hide' : 'Show'}</slot>
204
+ </forge-button>
205
+ `;
206
+ }
207
+ #renderIconButton() {
208
+ const buttonAriaLabelledByElements = [this];
209
+ if (this.#toggleTextRef.value) {
210
+ buttonAriaLabelledByElements.unshift(this.#toggleTextRef.value);
211
+ }
212
+ return html `
213
+ <span hidden ${ref(this.#toggleTextRef)}>Toggle</span>
214
+ <forge-icon-button
215
+ class="button"
216
+ exportparts="button"
217
+ aria-expanded="${this.open}"
218
+ .ariaControlsElements=${[this]}
219
+ .ariaLabelledByElements=${buttonAriaLabelledByElements}
220
+ @keydown="${this.#handleKeyDown}">
221
+ ${this.#renderIcon()}
222
+ </forge-icon-button>
223
+ <forge-tooltip anchor="button" placement="top">
224
+ <slot name="label">${this.open ? 'Hide' : 'Show'}</slot>
225
+ </forge-tooltip>
226
+ `;
227
+ }
228
+ #renderIcon() {
229
+ return html `
230
+ <slot name="${this.open ? 'close-icon' : 'open-icon'}">
231
+ <forge-icon class="icon" .name=${this.open ? 'eye_closed' : 'eye_outline'}></forge-icon>
232
+ </slot>
233
+ `;
234
+ }
235
+ #handleClick(evt) {
236
+ const didClickButton = evt.composedPath().indexOf(this._buttonElement) !== -1;
237
+ if (!didClickButton) {
238
+ // Ignore clicks from the content when visible
239
+ if (this.open) {
240
+ return;
241
+ }
242
+ // Focus the button as if it were clicked instead of the content
243
+ this._buttonElement.focus({ focusVisible: false });
244
+ }
245
+ this.open = !this.open;
246
+ this.#dispatchToggleEvent();
247
+ }
248
+ #handleKeyDown(event) {
249
+ if (event.key === 'Escape' && this.open) {
250
+ event.stopPropagation();
251
+ this.open = false;
252
+ this.#dispatchToggleEvent();
253
+ }
254
+ }
255
+ #hideOtherSecretsInGroup() {
256
+ const root = this.getRootNode();
257
+ const allSecrets = Array.from(root.querySelectorAll('forge-secret'));
258
+ allSecrets
259
+ .filter(secret => secret !== this && secret.name === this.name && secret.open)
260
+ .forEach(secret => {
261
+ secret.open = false;
262
+ secret.#dispatchToggleEvent();
263
+ });
264
+ }
265
+ #dispatchToggleEvent() {
266
+ const event = new ToggleEvent('toggle', { oldState: (!this.open).toString(), bubbles: true, composed: true });
267
+ this.dispatchEvent(event);
268
+ }
269
+ #getTextContent() {
270
+ return Array.from(this._contentNodes)
271
+ .map(node => node.textContent)
272
+ .join(' ')
273
+ .trim();
274
+ }
275
+ #announceContent() {
276
+ LiveAnnouncer.instance.announce(this.#getTextContent(), 'polite');
277
+ }
278
+ #tryUpdateInternalMask(changedProperties) {
279
+ if (this.block || this.variant !== 'masked') {
280
+ return;
281
+ }
282
+ const maskRelatedProperties = ['unmaskedCharacters', 'block', 'mask', 'maskCharacter', 'variant'];
283
+ if (!maskRelatedProperties.some(prop => changedProperties.has(prop))) {
284
+ return;
285
+ }
286
+ const content = this.mask || this.#getTextContent();
287
+ const regex = new RegExp(`[^${this.unmaskedCharacters.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')}]`, 'g');
288
+ this._mask = content.replace(regex, this.maskCharacter);
289
+ }
290
+ };
291
+ __decorate([
292
+ property({ type: Boolean })
293
+ ], SecretComponent.prototype, "open", void 0);
294
+ __decorate([
295
+ property()
296
+ ], SecretComponent.prototype, "variant", void 0);
297
+ __decorate([
298
+ property()
299
+ ], SecretComponent.prototype, "mask", void 0);
300
+ __decorate([
301
+ property({ attribute: 'mask-character' })
302
+ ], SecretComponent.prototype, "maskCharacter", void 0);
303
+ __decorate([
304
+ property({ attribute: 'unmasked-characters' })
305
+ ], SecretComponent.prototype, "unmaskedCharacters", void 0);
306
+ __decorate([
307
+ property({ type: Boolean })
308
+ ], SecretComponent.prototype, "block", void 0);
309
+ __decorate([
310
+ property({ attribute: 'button-position' })
311
+ ], SecretComponent.prototype, "buttonPosition", void 0);
312
+ __decorate([
313
+ property({ type: Boolean, attribute: 'show-on-hover' })
314
+ ], SecretComponent.prototype, "showOnHover", void 0);
315
+ __decorate([
316
+ property({ reflect: true })
317
+ ], SecretComponent.prototype, "name", void 0);
318
+ __decorate([
319
+ query(':is(forge-button, forge-icon-button)')
320
+ ], SecretComponent.prototype, "_buttonElement", void 0);
321
+ __decorate([
322
+ queryAssignedNodes({ flatten: true })
323
+ ], SecretComponent.prototype, "_contentNodes", void 0);
324
+ __decorate([
325
+ state()
326
+ ], SecretComponent.prototype, "_mask", void 0);
327
+ SecretComponent = __decorate([
328
+ customElement(SECRET_TAG_NAME)
329
+ ], SecretComponent);
330
+
331
+ export { SECRET_TAG_NAME, SecretComponent };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @license
3
+ * Copyright Tyler Technologies, Inc.
4
+ * License: Apache-2.0
5
+ */
6
+
7
+ var styles = ":host{display:inline-block;vertical-align:bottom}:host([hidden]){display:none}.forge-secret{--_secret-blur:var(--forge-secret-blur, var(--forge-spacing-xsmall, 8px));--_secret-button-background:var(--forge-secret-button-background, var(--forge-theme-surface-inverse, #333333));--_secret-button-color:var(--forge-secret-button-color, var(--forge-theme-on-surface-inverse, #ffffff));--_secret-button-shape:var(--forge-secret-button-shape, calc(var(--forge-shape-medium, 4px) * var(--forge-shape-factor, 1)));--_secret-button-padding:var(--forge-secret-button-padding, var(--forge-spacing-xsmall, 8px));--_secret-icon-size:var(--forge-secret-icon-size, calc(var(--forge-typography-font-size, 1rem) * 1));--_secret-text-button-shape:var(--forge-secret-text-button-shape, calc(var(--forge-shape-full, 9999px) * var(--forge-shape-factor, 1)));--_secret-text-decoration-line:var(--forge-secret-text-decoration-line, underline);--_secret-text-decoration-style:var(--forge-secret-text-decoration-style, dotted);--_secret-text-decoration-color:var(--forge-secret-text-decoration-color, inherit);--_secret-text-underline-offset:var(--forge-secret-text-underline-offset, var(--forge-spacing-xxxsmall, 2px));--_secret-transition-duration:var(--forge-secret-transition-duration, var(--forge-animation-duration-short4, 200ms));--_secret-transition-easing:var(--forge-secret-transition-easing, var(--forge-animation-easing-standard, cubic-bezier(0.2, 0, 0, 1)))}.forge-secret{display:flex;max-inline-size:fit-content}.reverse{flex-direction:row-reverse}.content{display:inline-block;position:relative;transition:filter var(--_secret-transition-duration) var(--_secret-transition-easing)}.blur{filter:blur(var(--_secret-blur))}.masked::before{content:attr(data-mask)}.masked slot:not([name]){display:none}.noise::before{content:\"\";position:absolute;inset:0;width:100%;height:100%;background-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"600\" height=\"600\"><filter id=\"noise\"><feTurbulence type=\"fractalNoise\" baseFrequency=\"0.85\" numOctaves=\"8\" stitchTiles=\"stitch\" /><feColorMatrix type=\"matrix\" values=\"0.33 0.33 0.33 0 0 0.33 0.33 0.33 0 0 0.33 0.33 0.33 0 0 0 0 0 1 0\" /></filter><rect width=\"100%\" height=\"100%\" filter=\"url(%23noise)\" opacity=\".5\" /></svg>');background-size:600px 600px;background-repeat:repeat;backdrop-filter:blur(24px)}.button{--forge-icon-button-background-color: var(--_secret-button-background);--forge-icon-button-icon-color: var(--_secret-button-color);--forge-icon-button-icon-size: inherit;--forge-icon-button-padding: 0;--forge-icon-button-shape: var(--_secret-button-shape);--forge-icon-button-size: 1lh;--forge-focus-indicator-outward-offset: 2px;block-size:0;padding-inline:var(--_secret-button-padding)}.icon{--forge-icon-font-size: var(--_secret-icon-size)}.text-button{--_button-dense-height:var(--forge-button-dense-height, 24px);--forge-button-background: var(--_secret-button-background);--forge-button-color: var(--_secret-button-color);--forge-button-shape: var(--_secret-text-button-shape);--forge-button-height: var(--_button-dense-height);--forge-focus-indicator-shape: var(--_secret-text-button-shape);padding:var(--_secret-button-padding);position:absolute;place-self:center;inset:0;translate:0;transition-property:inset-block-start,translate;transition-duration:var(--_secret-transition-duration);transition-timing-function:var(--_secret-transition-easing)}.show-on-hover:where(:hover,:has(button:focus-visible)) .content{filter:none}.show-on-hover:where(:hover,:has(button:focus-visible)) .content::before{visibility:hidden}.show-on-hover:where(:hover,:has(button:focus-visible)) .content slot:not([name]){display:initial}.show-on-hover:where(:hover,:has(button:focus-visible)) .masked{display:grid}.show-on-hover:where(:hover,:has(button:focus-visible)) .masked>*,.show-on-hover:where(:hover,:has(button:focus-visible)) .masked::before{grid-row:1;grid-column:1}.show-on-hover:where(:hover,:has(button:focus-visible)) .text-button{inset-block-start:-100%;translate:0 -50%}:host(:state(open)) .text-button{inset-block-start:-100%;translate:0 -50%}:host(:not(:state(open))) .forge-secret{cursor:pointer}:host(:not(:state(block)):state(open)) .content{text-decoration-line:var(--_secret-text-decoration-line);text-decoration-style:var(--_secret-text-decoration-style);text-decoration-color:var(--_secret-text-decoration-color);text-underline-offset:var(--_secret-text-underline-offset)}:host(:state(block)){display:block;vertical-align:initial}:host(:state(block)) .forge-secret{display:block;position:relative}:host(:state(block)) .content{display:block}@media(prefers-reduced-motion: reduce){.forge-secret{--_secret-transition-duration:var(--forge-secret-transition-duration, 0)}}[hidden]{display:none}";
8
+
9
+ export { styles as default };
@@ -4,6 +4,6 @@
4
4
  * License: Apache-2.0
5
5
  */
6
6
 
7
- var styles = ".forge-split-view-panel{display:flex;width:100%;height:100%;overflow:hidden}.forge-split-view-panel__handle{color:var(--forge-theme-text-medium, rgba(0, 0, 0, 0.6));background-color:var(--forge-theme-outline, #e0e0e0);position:relative;display:flex;flex-shrink:0;justify-content:center;align-items:center;outline:none}.forge-split-view-panel__content{flex:1;overflow:hidden}.forge-split-view-panel--closed{display:none}.forge-split-view-panel--disabled #handle{pointer-events:none}.forge-split-view-panel--disabled .forge-split-view-panel__icon{display:none}.forge-split-view-panel[orientation=horizontal]{min-width:var(--forge-split-view-handle-width, 8px);width:calc(var(--forge-split-view-panel-size, unset) + var(--forge-split-view-handle-width, 8px));flex-direction:row}.forge-split-view-panel[orientation=horizontal] .forge-split-view-panel__handle{width:var(--forge-split-view-handle-width, 8px);cursor:var(--forge-split-view-panel-cursor)}.forge-split-view-panel[orientation=horizontal].forge-split-view-panel--closing[resizable=end]{position:absolute;top:0;left:0;animation-name:u0p183v;animation-duration:var(--forge-animation-duration-medium2, 300ms);animation-timing-function:var(--forge-animation-easing-standard, cubic-bezier(0.2, 0, 0, 1))}@keyframes u0p183v{from{transform:none}to{transform:translateX(-100%)}}.forge-split-view-panel[orientation=horizontal].forge-split-view-panel--closing[resizable=start]{position:absolute;top:0;right:0;animation-name:u0p184g;animation-duration:var(--forge-animation-duration-medium2, 300ms);animation-timing-function:var(--forge-animation-easing-standard, cubic-bezier(0.2, 0, 0, 1))}@keyframes u0p184g{from{transform:none}to{transform:translateX(100%)}}.forge-split-view-panel[orientation=horizontal].forge-split-view-panel--opening[resizable=end]{position:absolute;top:0;left:0;animation-name:u0p184m;animation-duration:var(--forge-animation-duration-medium2, 300ms);animation-timing-function:var(--forge-animation-easing-standard, cubic-bezier(0.2, 0, 0, 1))}@keyframes u0p184m{from{transform:none}to{transform:translateX(-100%)}}.forge-split-view-panel[orientation=horizontal].forge-split-view-panel--opening[resizable=end]{animation-direction:reverse}.forge-split-view-panel[orientation=horizontal].forge-split-view-panel--opening[resizable=start]{position:absolute;top:0;right:0;animation-name:u0p1856;animation-duration:var(--forge-animation-duration-medium2, 300ms);animation-timing-function:var(--forge-animation-easing-standard, cubic-bezier(0.2, 0, 0, 1))}@keyframes u0p1856{from{transform:none}to{transform:translateX(100%)}}.forge-split-view-panel[orientation=horizontal].forge-split-view-panel--opening[resizable=start]{animation-direction:reverse}.forge-split-view-panel[orientation=vertical]{min-height:var(--forge-split-view-handle-width, 8px);height:calc(var(--forge-split-view-panel-size, unset) + var(--forge-split-view-handle-width, 8px));flex-direction:column}.forge-split-view-panel[orientation=vertical] .forge-split-view-panel__handle{height:var(--forge-split-view-handle-width, 8px);cursor:var(--forge-split-view-panel-cursor)}.forge-split-view-panel[orientation=vertical].forge-split-view-panel--closing[resizable=end]{position:absolute;top:0;left:0;animation-name:u0p185b;animation-duration:var(--forge-animation-duration-medium2, 300ms);animation-timing-function:var(--forge-animation-easing-standard, cubic-bezier(0.2, 0, 0, 1))}@keyframes u0p185b{from{transform:none}to{transform:translateY(-100%)}}.forge-split-view-panel[orientation=vertical].forge-split-view-panel--closing[resizable=start]{position:absolute;bottom:0;left:0;animation-name:u0p185d;animation-duration:var(--forge-animation-duration-medium2, 300ms);animation-timing-function:var(--forge-animation-easing-standard, cubic-bezier(0.2, 0, 0, 1))}@keyframes u0p185d{from{transform:none}to{transform:translateY(100%)}}.forge-split-view-panel[orientation=vertical].forge-split-view-panel--opening[resizable=end]{position:absolute;top:0;left:0;animation-name:u0p1868;animation-duration:var(--forge-animation-duration-medium2, 300ms);animation-timing-function:var(--forge-animation-easing-standard, cubic-bezier(0.2, 0, 0, 1))}@keyframes u0p1868{from{transform:none}to{transform:translateY(-100%)}}.forge-split-view-panel[orientation=vertical].forge-split-view-panel--opening[resizable=end]{animation-direction:reverse}.forge-split-view-panel[orientation=vertical].forge-split-view-panel--opening[resizable=start]{position:absolute;bottom:0;left:0;animation-name:u0p1877;animation-duration:var(--forge-animation-duration-medium2, 300ms);animation-timing-function:var(--forge-animation-easing-standard, cubic-bezier(0.2, 0, 0, 1))}@keyframes u0p1877{from{transform:none}to{transform:translateY(100%)}}.forge-split-view-panel[orientation=vertical].forge-split-view-panel--opening[resizable=start]{animation-direction:reverse}:host{z-index:var(--forge-split-view-animating-layer) !important;display:block;position:relative;height:100%;width:100%;flex:0}:host([hidden]){display:none}:host(:not([resizable=start],[resizable=end])){flex:1}:host(:not([resizable=start],[resizable=end])) .forge-split-view-panel{width:100%;height:100%;min-width:0;min-height:0}:host(:not([resizable=start],[resizable=end])) .forge-split-view-panel__handle{display:none}forge-focus-indicator{--forge-focus-indicator-active-width: 2px}";
7
+ var styles = ".forge-split-view-panel{display:flex;width:100%;height:100%;overflow:hidden}.forge-split-view-panel__handle{color:var(--forge-theme-text-medium, rgba(0, 0, 0, 0.6));background-color:var(--forge-theme-outline, #e0e0e0);position:relative;display:flex;flex-shrink:0;justify-content:center;align-items:center;outline:none}.forge-split-view-panel__content{flex:1;overflow:hidden}.forge-split-view-panel--closed{display:none}.forge-split-view-panel--disabled #handle{pointer-events:none}.forge-split-view-panel--disabled .forge-split-view-panel__icon{display:none}.forge-split-view-panel[orientation=horizontal]{min-width:var(--forge-split-view-handle-width, 8px);width:calc(var(--forge-split-view-panel-size, unset) + var(--forge-split-view-handle-width, 8px));flex-direction:row}.forge-split-view-panel[orientation=horizontal] .forge-split-view-panel__handle{width:var(--forge-split-view-handle-width, 8px);cursor:var(--forge-split-view-panel-cursor)}.forge-split-view-panel[orientation=horizontal].forge-split-view-panel--closing[resizable=end]{position:absolute;top:0;left:0;animation-name:u38yt61;animation-duration:var(--forge-animation-duration-medium2, 300ms);animation-timing-function:var(--forge-animation-easing-standard, cubic-bezier(0.2, 0, 0, 1))}@keyframes u38yt61{from{transform:none}to{transform:translateX(-100%)}}.forge-split-view-panel[orientation=horizontal].forge-split-view-panel--closing[resizable=start]{position:absolute;top:0;right:0;animation-name:u38yt6x;animation-duration:var(--forge-animation-duration-medium2, 300ms);animation-timing-function:var(--forge-animation-easing-standard, cubic-bezier(0.2, 0, 0, 1))}@keyframes u38yt6x{from{transform:none}to{transform:translateX(100%)}}.forge-split-view-panel[orientation=horizontal].forge-split-view-panel--opening[resizable=end]{position:absolute;top:0;left:0;animation-name:u38yt7f;animation-duration:var(--forge-animation-duration-medium2, 300ms);animation-timing-function:var(--forge-animation-easing-standard, cubic-bezier(0.2, 0, 0, 1))}@keyframes u38yt7f{from{transform:none}to{transform:translateX(-100%)}}.forge-split-view-panel[orientation=horizontal].forge-split-view-panel--opening[resizable=end]{animation-direction:reverse}.forge-split-view-panel[orientation=horizontal].forge-split-view-panel--opening[resizable=start]{position:absolute;top:0;right:0;animation-name:u38yt82;animation-duration:var(--forge-animation-duration-medium2, 300ms);animation-timing-function:var(--forge-animation-easing-standard, cubic-bezier(0.2, 0, 0, 1))}@keyframes u38yt82{from{transform:none}to{transform:translateX(100%)}}.forge-split-view-panel[orientation=horizontal].forge-split-view-panel--opening[resizable=start]{animation-direction:reverse}.forge-split-view-panel[orientation=vertical]{min-height:var(--forge-split-view-handle-width, 8px);height:calc(var(--forge-split-view-panel-size, unset) + var(--forge-split-view-handle-width, 8px));flex-direction:column}.forge-split-view-panel[orientation=vertical] .forge-split-view-panel__handle{height:var(--forge-split-view-handle-width, 8px);cursor:var(--forge-split-view-panel-cursor)}.forge-split-view-panel[orientation=vertical].forge-split-view-panel--closing[resizable=end]{position:absolute;top:0;left:0;animation-name:u38yt83;animation-duration:var(--forge-animation-duration-medium2, 300ms);animation-timing-function:var(--forge-animation-easing-standard, cubic-bezier(0.2, 0, 0, 1))}@keyframes u38yt83{from{transform:none}to{transform:translateY(-100%)}}.forge-split-view-panel[orientation=vertical].forge-split-view-panel--closing[resizable=start]{position:absolute;bottom:0;left:0;animation-name:u38yt92;animation-duration:var(--forge-animation-duration-medium2, 300ms);animation-timing-function:var(--forge-animation-easing-standard, cubic-bezier(0.2, 0, 0, 1))}@keyframes u38yt92{from{transform:none}to{transform:translateY(100%)}}.forge-split-view-panel[orientation=vertical].forge-split-view-panel--opening[resizable=end]{position:absolute;top:0;left:0;animation-name:u38yt9n;animation-duration:var(--forge-animation-duration-medium2, 300ms);animation-timing-function:var(--forge-animation-easing-standard, cubic-bezier(0.2, 0, 0, 1))}@keyframes u38yt9n{from{transform:none}to{transform:translateY(-100%)}}.forge-split-view-panel[orientation=vertical].forge-split-view-panel--opening[resizable=end]{animation-direction:reverse}.forge-split-view-panel[orientation=vertical].forge-split-view-panel--opening[resizable=start]{position:absolute;bottom:0;left:0;animation-name:u38ytae;animation-duration:var(--forge-animation-duration-medium2, 300ms);animation-timing-function:var(--forge-animation-easing-standard, cubic-bezier(0.2, 0, 0, 1))}@keyframes u38ytae{from{transform:none}to{transform:translateY(100%)}}.forge-split-view-panel[orientation=vertical].forge-split-view-panel--opening[resizable=start]{animation-direction:reverse}:host{z-index:var(--forge-split-view-animating-layer) !important;display:block;position:relative;height:100%;width:100%;flex:0}:host([hidden]){display:none}:host(:not([resizable=start],[resizable=end])){flex:1}:host(:not([resizable=start],[resizable=end])) .forge-split-view-panel{width:100%;height:100%;min-width:0;min-height:0}:host(:not([resizable=start],[resizable=end])) .forge-split-view-panel__handle{display:none}forge-focus-indicator{--forge-focus-indicator-active-width: 2px}";
8
8
 
9
9
  export { styles as default };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tylertech/forge",
3
- "version": "3.14.0-dev.5",
3
+ "version": "3.14.1",
4
4
  "description": "Tyler Forge™ Web Components library",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Tyler Technologies, Inc.",
@@ -52,11 +52,11 @@
52
52
  "dependencies": {
53
53
  "@floating-ui/dom": "^1.7.6",
54
54
  "@lit/context": "^1.1.6",
55
- "@tylertech/forge-core": "3.3.0-dev.0",
56
- "@tylertech/tyler-icons": "^2.0.4",
55
+ "@tylertech/tyler-icons": "^2.1.0",
57
56
  "imask": "^7.6.1",
58
57
  "lit": "^3.3.2",
59
- "tslib": "^2.8.1"
58
+ "tslib": "^2.8.1",
59
+ "@tylertech/forge-core": "3.3.0"
60
60
  },
61
- "publishedAt": "2026-03-26T17:42:19.460Z"
61
+ "publishedAt": "2026-04-23T18:05:24.922Z"
62
62
  }
@@ -0,0 +1,27 @@
1
+ @use 'sass:map';
2
+ @use '../../animation';
3
+ @use '../../spacing';
4
+ @use '../../shape';
5
+ @use '../../theme';
6
+ @use '../../typography';
7
+ @use '../../utils';
8
+
9
+ $tokens: (
10
+ blur: utils.module-val(secret, blur, spacing.variable(xsmall)),
11
+ button-background: utils.module-val(secret, button-background, theme.variable(surface-inverse)),
12
+ button-color: utils.module-val(secret, button-color, theme.variable(on-surface-inverse)),
13
+ button-shape: utils.module-val(secret, button-shape, shape.variable(medium)),
14
+ button-padding: utils.module-val(secret, button-padding, spacing.variable(xsmall)),
15
+ icon-size: utils.module-val(secret, icon-size, typography.font-size-relative('1000')),
16
+ text-button-shape: utils.module-val(secret, text-button-shape, shape.variable(full)),
17
+ text-decoration-line: utils.module-val(secret, text-decoration-line, underline),
18
+ text-decoration-style: utils.module-val(secret, text-decoration-style, dotted),
19
+ text-decoration-color: utils.module-val(secret, text-decoration-color, inherit),
20
+ text-underline-offset: utils.module-val(secret, text-underline-offset, spacing.variable(xxxsmall)),
21
+ transition-duration: utils.module-val(secret, transition-duration, animation.variable(duration-short4)),
22
+ transition-easing: utils.module-val(secret, transition-easing, animation.variable(easing-standard))
23
+ ) !default;
24
+
25
+ @function get($key) {
26
+ @return map.get($tokens, $key);
27
+ }
@@ -0,0 +1,170 @@
1
+ @use '../core/styles/typography';
2
+ @use './token-utils' as *;
3
+ @use '../button' as button;
4
+ @use '../focus-indicator' as focus-indicator;
5
+ @use '../icon-button' as icon-button;
6
+ @use '../icon' as icon;
7
+
8
+ @forward './token-utils';
9
+
10
+ @mixin host {
11
+ display: inline-block;
12
+ vertical-align: bottom;
13
+ }
14
+
15
+ @mixin host-block {
16
+ display: block;
17
+ vertical-align: initial;
18
+ }
19
+
20
+ @mixin base {
21
+ display: flex;
22
+ max-inline-size: fit-content;
23
+ }
24
+
25
+ @mixin base-reverse {
26
+ flex-direction: row-reverse;
27
+ }
28
+
29
+ @mixin base-block {
30
+ display: block;
31
+ position: relative;
32
+ }
33
+
34
+ @mixin content {
35
+ display: inline-block;
36
+ position: relative;
37
+ transition: filter #{token(transition-duration)} #{token(transition-easing)};
38
+ }
39
+
40
+ @mixin content-block {
41
+ display: block;
42
+ }
43
+
44
+ @mixin content-inline-open {
45
+ text-decoration-line: #{token(text-decoration-line)};
46
+ text-decoration-style: #{token(text-decoration-style)};
47
+ text-decoration-color: #{token(text-decoration-color)};
48
+ text-underline-offset: #{token(text-underline-offset)};
49
+ }
50
+
51
+ @mixin content-blur {
52
+ filter: blur(#{token(blur)});
53
+ }
54
+
55
+ @mixin content-masked {
56
+ &::before {
57
+ content: attr(data-mask);
58
+ }
59
+
60
+ slot:not([name]) {
61
+ display: none;
62
+ }
63
+ }
64
+
65
+ @mixin content-noise {
66
+ &::before {
67
+ content: '';
68
+ position: absolute;
69
+ inset: 0;
70
+ width: 100%;
71
+ height: 100%;
72
+ background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="600" height="600"><filter id="noise"><feTurbulence type="fractalNoise" baseFrequency="0.85" numOctaves="8" stitchTiles="stitch" /><feColorMatrix type="matrix" values="0.33 0.33 0.33 0 0 0.33 0.33 0.33 0 0 0.33 0.33 0.33 0 0 0 0 0 1 0" /></filter><rect width="100%" height="100%" filter="url(%23noise)" opacity=".5" /></svg>');
73
+ background-size: 600px 600px;
74
+ background-repeat: repeat;
75
+ backdrop-filter: blur(24px);
76
+ }
77
+ }
78
+
79
+ @mixin content-forced-open {
80
+ filter: none;
81
+
82
+ &::before {
83
+ visibility: hidden;
84
+ }
85
+
86
+ slot:not([name]) {
87
+ display: initial;
88
+ }
89
+ }
90
+
91
+ @mixin content-masked-forced-open {
92
+ // Using grid to force the masked and unmasked content into the same space, setting the width of
93
+ // the container to the maximum of the two and preventing layout shift while hovering
94
+ display: grid;
95
+
96
+ & > *,
97
+ &::before {
98
+ grid-row: 1;
99
+ grid-column: 1;
100
+ }
101
+ }
102
+
103
+ @mixin button {
104
+ @include icon-button.provide-theme(
105
+ (
106
+ background-color: #{token(button-background)},
107
+ icon-color: #{token(button-color)},
108
+ icon-size: inherit,
109
+ padding: 0,
110
+ shape: #{token(button-shape)},
111
+ size: 1lh
112
+ )
113
+ );
114
+ @include focus-indicator.provide-theme(
115
+ (
116
+ outward-offset: 2px
117
+ )
118
+ );
119
+
120
+ // Set the block size to 0 to prevent the button from affecting text layout
121
+ block-size: 0;
122
+ padding-inline: #{token(button-padding)};
123
+ }
124
+
125
+ @mixin text-button {
126
+ @include button.tokens(
127
+ $includes: (
128
+ dense-height
129
+ )
130
+ );
131
+ @include button.provide-theme(
132
+ (
133
+ background: #{token(button-background)},
134
+ color: #{token(button-color)},
135
+ shape: #{token(text-button-shape)},
136
+ height: #{button.token(dense-height)}
137
+ )
138
+ );
139
+ @include focus-indicator.provide-theme(
140
+ (
141
+ shape: #{token(text-button-shape)}
142
+ )
143
+ );
144
+
145
+ padding: #{token(button-padding)};
146
+ position: absolute;
147
+ place-self: center;
148
+ inset: 0;
149
+ translate: 0;
150
+ transition-property: inset-block-start, translate;
151
+ transition-duration: #{token(transition-duration)};
152
+ transition-timing-function: #{token(transition-easing)};
153
+ }
154
+
155
+ @mixin text-button-open {
156
+ inset-block-start: -100%;
157
+ translate: 0 -50%;
158
+ }
159
+
160
+ @mixin icon {
161
+ @include icon.provide-theme(
162
+ (
163
+ font-size: #{token(icon-size)}
164
+ )
165
+ );
166
+ }
167
+
168
+ @mixin closed {
169
+ cursor: pointer;
170
+ }
@@ -0,0 +1,25 @@
1
+ @use '../core/styles/tokens/secret/tokens';
2
+ @use '../core/styles/tokens/token-utils';
3
+
4
+ $_module: secret;
5
+ $_tokens: tokens.$tokens;
6
+
7
+ @mixin provide-theme($theme) {
8
+ @include token-utils.provide-theme($_module, $_tokens, $theme);
9
+ }
10
+
11
+ @function token($name, $type: token) {
12
+ @return token-utils.token($_module, $_tokens, $name, $type);
13
+ }
14
+
15
+ @function declare($token) {
16
+ @return token-utils.declare($_module, $token);
17
+ }
18
+
19
+ @mixin override($token, $token-or-value, $type: token) {
20
+ @include token-utils.override($_module, $_tokens, $token, $token-or-value, $type);
21
+ }
22
+
23
+ @mixin tokens($includes: null, $excludes: null) {
24
+ @include token-utils.tokens($_module, $_tokens, $includes, $excludes);
25
+ }