vira 31.29.0 → 31.31.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.
@@ -35,4 +35,4 @@ export declare const ViraMenuItem: import("element-vir").DeclarativeElementDefin
35
35
  * gated by `keepOpenAfterInteraction`.
36
36
  */
37
37
  activate: import("element-vir").DefineEvent<undefined>;
38
- }, "vira-menu-item-selected" | "vira-menu-item-disabled" | "vira-menu-item-enabled" | "vira-menu-item-default-icon" | "vira-menu-item-default-styles", "vira-menu-item-icon-gap", readonly [], readonly []>;
38
+ }, "vira-menu-item-selected" | "vira-menu-item-disabled" | "vira-menu-item-enabled" | "vira-menu-item-default-icon" | "vira-menu-item-default-styles", "vira-menu-item-icon-gap" | "vira-menu-item-padding" | "vira-menu-item-border-radius", readonly [], readonly []>;
@@ -37,7 +37,9 @@ export const ViraMenuItem = defineViraElement()({
37
37
  },
38
38
  cssVars: {
39
39
  /** Horizontal gap between a menu item's icon and its label. */
40
- 'vira-menu-item-icon-gap': '3px',
40
+ 'vira-menu-item-icon-gap': '8px',
41
+ 'vira-menu-item-padding': '6px 8px',
42
+ 'vira-menu-item-border-radius': '4px',
41
43
  },
42
44
  styles: ({ hostClasses, cssVars }) => css `
43
45
  :host {
@@ -48,8 +50,8 @@ export const ViraMenuItem = defineViraElement()({
48
50
  max-width: 100%;
49
51
  gap: ${cssVars['vira-menu-item-icon-gap'].value};
50
52
  overflow: hidden;
51
- padding: 8px 3px;
52
- padding-right: 16px;
53
+ padding: ${cssVars['vira-menu-item-padding'].value};
54
+ border-radius: ${cssVars['vira-menu-item-border-radius'].value};
53
55
  align-items: center;
54
56
  text-align: left;
55
57
  }
@@ -33,4 +33,4 @@ export declare const ViraMenu: import("element-vir").DeclarativeElementDefinitio
33
33
  direction: ViraMenuPopUpDirection;
34
34
  /** @default PopUpMenuCornerStyle.Directional */
35
35
  cornerStyle: ViraMenuCornerStyle;
36
- }>, {}, {}, "vira-menu-open-upwards" | "vira-menu-rounded" | "vira-menu-square", "vira-menu-", readonly [], readonly []>;
36
+ }>, {}, {}, "vira-menu-open-upwards" | "vira-menu-rounded" | "vira-menu-square", "vira-menu-padding", readonly [], readonly []>;
@@ -40,10 +40,14 @@ export const ViraMenu = defineViraElement()({
40
40
  'vira-menu-rounded': ({ inputs }) => inputs.cornerStyle === ViraMenuCornerStyle.AllRounded,
41
41
  'vira-menu-square': ({ inputs }) => inputs.cornerStyle === ViraMenuCornerStyle.AllSquare,
42
42
  },
43
- styles: ({ hostClasses }) => css `
43
+ cssVars: {
44
+ 'vira-menu-padding': '4px',
45
+ },
46
+ styles: ({ hostClasses, cssVars }) => css `
44
47
  :host {
45
48
  display: flex;
46
49
  flex-direction: column;
50
+ padding: ${cssVars['vira-menu-padding'].value};
47
51
  max-width: 100%;
48
52
  max-height: 100%;
49
53
  overflow-y: auto;
@@ -36,9 +36,16 @@ export declare const ViraButton: import("element-vir").DeclarativeElementDefinit
36
36
  */
37
37
  color: ViraColorVariant | ViraThemeColorName;
38
38
  /**
39
- * Set to `true`
39
+ * Set to `true` to render `icon` after `text` instead of before it.
40
40
  *
41
41
  * @default false
42
42
  */
43
+ showIconOnRight: boolean;
44
+ /**
45
+ * Set to `true` to append a downwards chevron after the button's text.
46
+ *
47
+ * @deprecated Set `icon` to `ChevronDown16Icon` and `showIconOnRight` to `true` instead.
48
+ * @default false
49
+ */
43
50
  showMenuCaret: boolean;
44
51
  }>, {}, {}, "vira-button-with-menu-caret" | "vira-button-size-large" | "vira-button-size-medium" | "vira-button-size-small" | "vira-button-emphasis-standard" | "vira-button-emphasis-subtle" | "vira-button-color-red" | "vira-button-color-yellow" | "vira-button-color-green" | "vira-button-color-blue" | "vira-button-color-brand" | "vira-button-color-purple" | "vira-button-color-plain" | "vira-button-color-neutral" | "vira-button-color-teal" | "vira-button-color-pink" | "vira-button-color-grey" | "vira-button-disabled" | "vira-button-icon-only", "vira-button-text-color" | "vira-button-background-color" | "vira-button-border-color" | "vira-button-hover-text-color" | "vira-button-hover-background-color" | "vira-button-hover-border-color" | "vira-button-active-text-color" | "vira-button-active-background-color" | "vira-button-active-border-color" | "vira-button-disabled-text-color" | "vira-button-disabled-background-color" | "vira-button-disabled-border-color" | "vira-button-border-width" | "vira-button-border-radius", readonly [], readonly []>;
@@ -121,6 +121,7 @@ const neutralButtonColors = {
121
121
  export const ViraButton = defineViraElement()({
122
122
  tagName: 'vira-button',
123
123
  hostClasses: {
124
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
124
125
  'vira-button-with-menu-caret': ({ inputs }) => !!inputs.showMenuCaret,
125
126
  'vira-button-size-large': ({ inputs }) => inputs.buttonSize === ViraSize.Large,
126
127
  'vira-button-size-medium': ({ inputs }) => !inputs.buttonSize || inputs.buttonSize === ViraSize.Medium,
@@ -316,7 +317,8 @@ export const ViraButton = defineViraElement()({
316
317
  width: 0;
317
318
  }
318
319
 
319
- button ${ViraIcon} + .text-template {
320
+ button ${ViraIcon} + .text-template,
321
+ button .text-template + ${ViraIcon} {
320
322
  margin-left: 8px;
321
323
  }
322
324
 
@@ -375,6 +377,7 @@ export const ViraButton = defineViraElement()({
375
377
  : html `
376
378
  <span class="empty-text">&nbsp;</span>
377
379
  `;
380
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
378
381
  const caretIconTemplate = inputs.showMenuCaret
379
382
  ? html `
380
383
  <${ViraIcon.assign({
@@ -384,10 +387,18 @@ export const ViraButton = defineViraElement()({
384
387
  ></${ViraIcon}>
385
388
  `
386
389
  : nothing;
390
+ /* Both templates are interpolated with no whitespace between them so `+` selectors match. */
391
+ const templates = inputs.showIconOnRight
392
+ ? [
393
+ textTemplate,
394
+ iconTemplate,
395
+ ]
396
+ : [
397
+ iconTemplate,
398
+ textTemplate,
399
+ ];
387
400
  return html `
388
- <button ?disabled=${inputs.isDisabled}>
389
- ${iconTemplate}${textTemplate}${caretIconTemplate}
390
- </button>
401
+ <button ?disabled=${inputs.isDisabled}>${templates}${caretIconTemplate}</button>
391
402
  `;
392
403
  },
393
404
  });
@@ -25,7 +25,7 @@ export const ViraCard = defineViraElement()({
25
25
  },
26
26
  cssVars: {
27
27
  'vira-card-border': css `1px solid ${viraFormCssVars['vira-form-border-color'].value}`,
28
- 'vira-card-padding': viraFormCssVars['vira-form-wrapper-radius'].value,
28
+ 'vira-card-padding': '24px',
29
29
  },
30
30
  styles: ({ hostClasses, cssVars }) => css `
31
31
  :host {
@@ -11,6 +11,20 @@ export declare const ViraCollapsibleWrapper: import("element-vir").DeclarativeEl
11
11
  expandOnPrint?: boolean;
12
12
  }, {
13
13
  contentHeight: number;
14
+ contentWidth: number;
15
+ /**
16
+ * Collapsed content that is merely `height: 0` is still rendered, so the browser emits
17
+ * a line break for it when serializing a selection to plain text. Copying a region that
18
+ * spans collapsed wrappers then pastes with runs of blank lines. Taking the content out
19
+ * of layout entirely is what drops those breaks; `visibility: hidden` and `user-select:
20
+ * none` both leave them behind.
21
+ *
22
+ * This starts `false` even when collapsed because the wrapper takes both its width and
23
+ * its animation target height from the content, so the content has to be laid out once
24
+ * before it can be hidden.
25
+ */
26
+ isContentHidden: boolean;
27
+ collapsingElement: HTMLDivElement | undefined;
14
28
  }, {
15
29
  expandChange: import("element-vir").DefineEvent<boolean>;
16
30
  }, "vira-collapsible-wrapper-expand-on-print", `vira-${string}-`, readonly ["vira-collapsible-wrapper-header"], readonly []>;
@@ -1,4 +1,5 @@
1
- import { classMap, css, defineElementEvent, html, listen, onResize } from 'element-vir';
1
+ import { assertWrap } from '@augment-vir/assert';
2
+ import { classMap, css, defineElementEvent, html, listen, onDomCreated, onResize } from 'element-vir';
2
3
  import { noNativeFormStyles, noUserSelect, viraAnimationDurations } from '../styles/index.js';
3
4
  import { defineViraElement } from '../util/define-vira-element.js';
4
5
  /**
@@ -13,6 +14,20 @@ export const ViraCollapsibleWrapper = defineViraElement()({
13
14
  state() {
14
15
  return {
15
16
  contentHeight: 0,
17
+ contentWidth: 0,
18
+ /**
19
+ * Collapsed content that is merely `height: 0` is still rendered, so the browser emits
20
+ * a line break for it when serializing a selection to plain text. Copying a region that
21
+ * spans collapsed wrappers then pastes with runs of blank lines. Taking the content out
22
+ * of layout entirely is what drops those breaks; `visibility: hidden` and `user-select:
23
+ * none` both leave them behind.
24
+ *
25
+ * This starts `false` even when collapsed because the wrapper takes both its width and
26
+ * its animation target height from the content, so the content has to be laid out once
27
+ * before it can be hidden.
28
+ */
29
+ isContentHidden: false,
30
+ collapsingElement: undefined,
16
31
  };
17
32
  },
18
33
  hostClasses: {
@@ -48,12 +63,20 @@ export const ViraCollapsibleWrapper = defineViraElement()({
48
63
  }
49
64
  }
50
65
 
66
+ .content-wrapper.hidden-content {
67
+ display: none;
68
+ }
69
+
51
70
  @media print {
52
71
  :host(.${hostClasses['vira-collapsible-wrapper-expand-on-print'].name})
53
72
  .collapsing-element {
54
73
  height: auto !important;
55
74
  overflow: visible !important;
56
75
  transition: none !important;
76
+
77
+ & .content-wrapper.hidden-content {
78
+ display: flex !important;
79
+ }
57
80
  }
58
81
  }
59
82
  `,
@@ -61,12 +84,71 @@ export const ViraCollapsibleWrapper = defineViraElement()({
61
84
  expandChange: defineElementEvent(),
62
85
  },
63
86
  render({ state, slotNames, updateState, dispatch, events, inputs }) {
87
+ if (inputs.expanded && state.isContentHidden) {
88
+ updateState({
89
+ isContentHidden: false,
90
+ });
91
+ }
92
+ else if (!inputs.expanded &&
93
+ !state.isContentHidden &&
94
+ state.contentHeight &&
95
+ !state.collapsingElement?.clientHeight) {
96
+ /**
97
+ * Already at zero height, so no collapse animation will run and `transitionend` will
98
+ * never fire. Covers a wrapper that mounts collapsed and one that gets collapsed before
99
+ * its expanded height has been painted.
100
+ *
101
+ * Hiding here rather than straight from the resize callback: changing the size of the
102
+ * observed element from inside its own callback trips the browser's resize observer
103
+ * loop detection.
104
+ */
105
+ updateState({
106
+ isContentHidden: true,
107
+ });
108
+ }
109
+ /**
110
+ * Hidden content contributes no width, so the wrapper would shrink to its header without
111
+ * the width measured while the content was last laid out. `max-width` keeps that from
112
+ * blocking a later shrink to a narrower container.
113
+ */
114
+ const hiddenContentStyles = state.isContentHidden
115
+ ? css `
116
+ width: ${state.contentWidth}px;
117
+ max-width: 100%;
118
+ `
119
+ : css ``;
120
+ /**
121
+ * Hidden content is rendered without the resize observer rather than with a callback that
122
+ * ignores it. An attached observer still fires when the content is hidden, and the browser
123
+ * reports that as a resize observer loop.
124
+ */
125
+ const contentWrapperTemplate = state.isContentHidden
126
+ ? html `
127
+ <div class="content-wrapper hidden-content">
128
+ <slot></slot>
129
+ </div>
130
+ `
131
+ : html `
132
+ <div
133
+ ${onResize(({ contentRect }) => {
134
+ updateState({
135
+ contentHeight: contentRect.height,
136
+ contentWidth: contentRect.width,
137
+ });
138
+ })}
139
+ class="content-wrapper"
140
+ >
141
+ <slot></slot>
142
+ </div>
143
+ `;
64
144
  const collapsingStyles = inputs.expanded
65
145
  ? css `
66
146
  height: ${state.contentHeight}px;
147
+ ${hiddenContentStyles}
67
148
  `
68
149
  : css `
69
150
  height: 0;
151
+ ${hiddenContentStyles}
70
152
  `;
71
153
  return html `
72
154
  <button
@@ -84,17 +166,22 @@ export const ViraCollapsibleWrapper = defineViraElement()({
84
166
  })}"
85
167
  style=${collapsingStyles}
86
168
  disabled="disabled"
87
- >
88
- <div
89
- ${onResize(({ contentRect }) => {
169
+ ${onDomCreated((element) => {
90
170
  updateState({
91
- contentHeight: contentRect.height,
171
+ collapsingElement: assertWrap.instanceOf(element, HTMLDivElement),
92
172
  });
93
173
  })}
94
- class="content-wrapper"
95
- >
96
- <slot></slot>
97
- </div>
174
+ ${listen('transitionend', (event) => {
175
+ if (event.propertyName === 'height' &&
176
+ event.target === event.currentTarget &&
177
+ !inputs.expanded) {
178
+ updateState({
179
+ isContentHidden: true,
180
+ });
181
+ }
182
+ })}
183
+ >
184
+ ${contentWrapperTemplate}
98
185
  </div>
99
186
  `;
100
187
  },
@@ -37,8 +37,8 @@ export var ViraInputType;
37
37
  export const ViraInput = defineViraElement()({
38
38
  tagName: 'vira-input',
39
39
  cssVars: {
40
- 'vira-input-padding-horizontal': '10px',
41
- 'vira-input-padding-vertical': '5px',
40
+ 'vira-input-padding-horizontal': '12px',
41
+ 'vira-input-padding-vertical': '4px',
42
42
  },
43
43
  styles: ({ hostClasses, cssVars }) => {
44
44
  return css `
@@ -37,4 +37,4 @@ export declare const ViraModal: import("element-vir").DeclarativeElementDefiniti
37
37
  cleanupListeners: undefined | (() => void);
38
38
  }, {
39
39
  modalClose: import("element-vir").DefineEvent<void>;
40
- }, "vira-modal-phone-size" | "vira-modal-no-content-padding", "vira-modal-backdrop-filter", readonly ["vira-modal-modal-title"], readonly []>;
40
+ }, "vira-modal-phone-size" | "vira-modal-no-content-padding", "vira-modal-backdrop-filter" | "vira-modal-border-radius", readonly ["vira-modal-modal-title"], readonly []>;
@@ -45,12 +45,13 @@ export const ViraModal = defineViraElement()({
45
45
  slotNames: ['vira-modal-modal-title'],
46
46
  cssVars: {
47
47
  'vira-modal-backdrop-filter': 'blur(3px)',
48
+ 'vira-modal-border-radius': '8px',
48
49
  },
49
50
  styles: ({ hostClasses, cssVars }) => css `
50
51
  :host {
51
52
  display: contents;
52
53
  min-width: 280px;
53
- border-radius: 16px;
54
+ border-radius: ${cssVars['vira-modal-border-radius'].value};
54
55
  }
55
56
 
56
57
  h1 {
@@ -15,4 +15,4 @@ export declare const ViraProgress: import("element-vir").DeclarativeElementDefin
15
15
  min: number;
16
16
  /** @default 100 */
17
17
  max: number;
18
- }>, {}, {}, "vira-progress-", "vira-progress-border-radius", readonly [], readonly []>;
18
+ }>, {}, {}, "vira-progress-", "vira-progress-border-radius" | "vira-progress-height", readonly [], readonly []>;
@@ -20,13 +20,13 @@ export const ViraProgress = defineViraElement()({
20
20
  * dimension which creates a perfect pill border radius.
21
21
  */
22
22
  'vira-progress-border-radius': '99999999px',
23
+ 'vira-progress-height': '8px',
23
24
  },
24
25
  styles: ({ cssVars }) => css `
25
26
  :host {
26
27
  /* Default width that can easily be overridden because it's applied on the host. */
27
28
  width: 100px;
28
- /* Default height that can easily be overridden because it's applied on the host. */
29
- height: 10px;
29
+ height: ${cssVars['vira-progress-height'].value};
30
30
  display: inline-flex;
31
31
  align-items: center;
32
32
  border-radius: ${cssVars['vira-progress-border-radius'].value};
@@ -48,8 +48,8 @@ export const ViraSelect = defineViraElement()({
48
48
  valueChange: defineElementEvent(),
49
49
  },
50
50
  cssVars: {
51
- 'vira-select-padding-horizontal': '10px',
52
- 'vira-select-padding-vertical': '6px',
51
+ 'vira-select-padding-horizontal': '12px',
52
+ 'vira-select-padding-vertical': '8px',
53
53
  'vira-select-icon-padding': '44px',
54
54
  },
55
55
  hostClasses: {
@@ -17,8 +17,8 @@ import { filterTextInputValue, textInputListener, } from '../util/shared-text-in
17
17
  export const ViraTextArea = defineViraElement()({
18
18
  tagName: 'vira-text-area',
19
19
  cssVars: {
20
- 'vira-text-area-padding-horizontal': '10px',
21
- 'vira-text-area-padding-vertical': '6px',
20
+ 'vira-text-area-padding-horizontal': '12px',
21
+ 'vira-text-area-padding-vertical': '8px',
22
22
  },
23
23
  styles: ({ hostClasses, cssVars }) => css `
24
24
  :host {
@@ -8,5 +8,5 @@ export declare const viraFontCssVars: import("lit-css-vars").CssVarDefinitions<{
8
8
  readonly 'vira-monospace': "monospace";
9
9
  readonly 'vira-font-weight-normal': "normal";
10
10
  readonly 'vira-font-weight-medium': "500";
11
- readonly 'vira-font-weight-bold': "bold";
11
+ readonly 'vira-font-weight-bold': "600";
12
12
  }>;
@@ -9,5 +9,5 @@ export const viraFontCssVars = defineCssVars({
9
9
  'vira-monospace': 'monospace',
10
10
  'vira-font-weight-normal': 'normal',
11
11
  'vira-font-weight-medium': '500',
12
- 'vira-font-weight-bold': 'bold',
12
+ 'vira-font-weight-bold': '600',
13
13
  });
@@ -26,10 +26,10 @@ export declare const viraFormCssVars: import("lit-css-vars").CssVarDefinitions<{
26
26
  readonly 'vira-form-success-color': import("element-vir").CSSResult;
27
27
  readonly 'vira-form-label-font-weight': import("element-vir").CSSResult;
28
28
  readonly 'vira-form-small-text-size': "14px";
29
- readonly 'vira-form-medium-text-size': "16px";
29
+ readonly 'vira-form-medium-text-size': "14px";
30
30
  readonly 'vira-form-large-text-size': "22px";
31
- readonly 'vira-form-radius': "8px";
32
- readonly 'vira-form-wrapper-radius': "16px";
31
+ readonly 'vira-form-radius': "6px";
32
+ readonly 'vira-form-wrapper-radius': "12px";
33
33
  readonly 'vira-form-focus-outline-color': import("element-vir").CSSResult;
34
34
  readonly 'vira-form-focus-outline-border-radius': import("element-vir").CSSResult;
35
35
  readonly 'vira-form-plain-color': import("element-vir").CSSResult;
@@ -4,7 +4,7 @@ import { themeDefaultKey } from 'theme-vir/dist/color-theme/color-theme.js';
4
4
  import { viraFontCssVars } from './font.js';
5
5
  import { viraColorPalette } from './vira-color-palette.js';
6
6
  import { viraTheme } from './vira-color-theme.js';
7
- const defaultViraFormRadius = '8px';
7
+ const defaultViraFormRadius = '6px';
8
8
  /**
9
9
  * CSS vars for vira form elements.
10
10
  *
@@ -33,10 +33,10 @@ export const viraFormCssVars = defineCssVars({
33
33
  'vira-form-success-color': viraTheme.colors['vira-green-behind-bg-non-body'].background.value,
34
34
  'vira-form-label-font-weight': viraFontCssVars['vira-font-weight-bold'].value,
35
35
  'vira-form-small-text-size': '14px',
36
- 'vira-form-medium-text-size': '16px',
36
+ 'vira-form-medium-text-size': '14px',
37
37
  'vira-form-large-text-size': '22px',
38
38
  'vira-form-radius': defaultViraFormRadius,
39
- 'vira-form-wrapper-radius': '16px',
39
+ 'vira-form-wrapper-radius': '12px',
40
40
  'vira-form-focus-outline-color': viraTheme.colors['vira-brand-foreground-header'].foreground.value,
41
41
  'vira-form-focus-outline-border-radius': css `calc(var(--vira-form-radius, ${unsafeCSS(defaultViraFormRadius)}) + 2px)`,
42
42
  'vira-form-plain-color': viraColorPalette['vira-grey-100'].value,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vira",
3
- "version": "31.29.0",
3
+ "version": "31.31.0",
4
4
  "description": "A simple and highly versatile design system using element-vir.",
5
5
  "keywords": [
6
6
  "design",